diff --git a/bootable/bootloader/lk/platform/msm_shared/qpic_nand.c b/bootable/bootloader/lk/platform/msm_shared/qpic_nand.c index b7241a11b..96a9dd891 100755 --- a/bootable/bootloader/lk/platform/msm_shared/qpic_nand.c +++ b/bootable/bootloader/lk/platform/msm_shared/qpic_nand.c @@ -71,15 +71,17 @@ static struct flash_id supported_flash[] = { /* Flash ID Flash ID2 ID Mask ID Mask2 Density(MB) Wid Pgsz Blksz oobsz 8-bit ECCf */ {0x1590AC2C, 0x56, 0xFFFFFFFF, 0xFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 0}, {0x1590AC2C, 0x57, 0xFFFFFFFF, 0xFF, 0x20000000, 0, 2048, 0x00020000, 0x40, 1}, - {0x1590AA2C, 0x06, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0xE0, 0}, + {0x1590AA2C, 0x06, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x80, 1}, // wuchao modify, 20.12.29, for ESMT FM6BD2G1GXA(2A) {0x2690AC2C, 0x54, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1}, {0x1590ACAD, 0, 0xFFFFFFFF, 0x0, 0x20000000, 0, 2048, 0x00020000, 0x80, 0}, {0x9590DC2C, 0x56, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x40, 0}, - {0x1590aa98, 0x76, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x80, 1}, + {0x1590aa98, 0x76, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x80, 1}, /* NM1281KSLAXAJ-3B */ {0x2690A32C, 0x64, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1}, {0x2690AC98, 0x81676, 0xFFFFFFFF, 0x0, 0x20000000, 0, 4096, 0x00040000, 0xE0, 1}, - {0x1590AAEF, 0, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x40, 0}, /* Add by yangjihong for W20GF3FW*/ - {0x1590AAC8, 0, 0xFFFFFFFF, 0X0, 0x10000000, 0, 2048, 0x00020000, 0x40, 0}, /* Add by wuchao, 16.08.30, for ESMT(FM6BD2G1GA) */ + {0x1590AAEF, 0, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x40, 0}, /* Add by yangjihong for W71NW20GF3FW*/ + {0x1590AAC8, 0, 0xFFFFFFFF, 0x0, 0x10000000, 0, 2048, 0x00020000, 0x40, 0}, /* Add by wuchao, 16.08.30, for ESMT(FM6BD2G1GA) */ + {0x1590AAAD, 0x46, 0xFFFFFFFF, 0X0, 0x10000000, 0, 2048, 0x00020000, 0x80, 0}, /* Add by wuchao, 17.12.29, for JSFBAB3YHABBG-425 */ + {0x1590AA01, 0x46, 0xFFFFFFFF, 0X0, 0x10000000, 0, 2048, 0x00020000, 0x80, 0}, /* JSFBAB3YHABBG-425 */ /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash */ }; diff --git a/bootable/recovery/install.c b/bootable/recovery/install.c old mode 100644 new mode 100755 index f80ea7633..e8f5e0784 --- a/bootable/recovery/install.c +++ b/bootable/recovery/install.c @@ -38,7 +38,7 @@ // Flash dsp*.mbn files included in the zip /* [yangjihong] Update dsp image */ -#define MAX_DSP_MBN_IMAGES 4 +#define MAX_DSP_MBN_IMAGES 5 #define WLAN_MODEM_ZIP_PATH "firmware" #define WLAN_MODEM_DEST_PATH "/firmware" #define WLAN_MODEM_INFO_FILE "firmware/image/update_info" @@ -140,10 +140,11 @@ static bool install_mbns(const ZipArchive *zip) "sbl1.mbn", "appsboot.mbn", "NON-HLOS.ubi", - "boot.img" + "boot.img", + "rpm.mbn" }; const char *mbn_partitions[MAX_DSP_MBN_IMAGES] = - {"sbl", "aboot", "modem", "boot"}; + {"sbl", "aboot", "modem", "boot", "rpm"}; const ZipEntry *mbn_entry; const MtdPartition *part; diff --git a/bootable/recovery/recovery_color_img_data.h b/bootable/recovery/recovery_color_img_data.h index 7b80c78ed..b7063647c 100755 --- a/bootable/recovery/recovery_color_img_data.h +++ b/bootable/recovery/recovery_color_img_data.h @@ -16,7 +16,7 @@ #define _RECOVERY_COLOR_IMG_DATA_H_ //image: updating -const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0X01,0X1B,*/ +const unsigned char gImage_updating[32768] = { /* 0X10,0X10,0X00,0X80,0X00,0X80,0X01,0X1B, */ 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -504,8 +504,40 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X08,0X41,0X22,0X09,0X43,0XD0,0X5C,0XF5,0X6E,0X3A,0X76,0XBD,0X7F,0X3E, -0X87,0X3F,0X7E,0XBD,0X6E,0X3A,0X5D,0X36,0X43,0XD0,0X22,0X09,0X00,0X41,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X08,0X41,0X22,0X09,0X43,0X90,0X5C,0XF5,0X6D,0XFA,0X76,0X7C,0X7E,0XFE, +0X7E,0XFE,0X76,0X7C,0X6D,0XFA,0X5C,0XF5,0X43,0X90,0X22,0X09,0X08,0X41,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -520,8 +552,713 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X22,0X09, -0X54,0XF5,0X7E,0XFE,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X7E,0XFE,0X54,0XF5, +0X54,0XB4,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XBD,0X54,0XB4, +0X22,0X09,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X6D,0XB9,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X6D,0XB9,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X04,0X5D,0X36,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X6D,0XF9,0X4B,0XD1,0X2A,0X4A,0X19,0X46,0X08,0X82,0X00,0X41, +0X00,0X41,0X08,0X82,0X19,0X46,0X2A,0X4A,0X4B,0XD1,0X6D,0XF9,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X5D,0X36,0X11,0X04,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X2A,0X4A,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XBD, +0X4B,0XD1,0X19,0X45,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X19,0X45,0X4B,0XD1, +0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XBD,0X2A,0X4A,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X43,0X90,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XFE,0X4C,0X31,0X08,0X82, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X08,0X82,0X4C,0X31,0X7E,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X43,0X90,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X4C,0X32,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X6D,0XFA,0X19,0X46,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X41,0X32,0XCC, +0X32,0XCC,0X08,0X41,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X19,0X86,0X6D,0XFA,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X4C,0X32, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X43,0X90, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X5C,0XF6,0X08,0X42,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X10,0XC3,0X6D,0XB8,0X86,0XFE, +0X86,0XFE,0X6D,0XB8,0X10,0XC3,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X42,0X5C,0XF6,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X43,0X90,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X54,0XB4,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X19,0X46,0X76,0X3B,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X76,0X3B,0X19,0X46,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XB4,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X04,0X7E,0XBD,0X86,0XFE, +0X86,0XFE,0X5C,0XF6,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X09,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XBD,0X2A,0X09,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X5C,0XF6,0X86,0XFE, +0X86,0XFE,0X7E,0XBD,0X11,0X04,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X5D,0X36,0X86,0XFE,0X86,0XFE, +0X6D,0XFA,0X08,0X42,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X3B,0X0D,0X7E,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X4B,0XD1, +0X4B,0XD1,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XFE,0X3B,0X0D,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X82,0X6D,0XFA, +0X86,0XFE,0X86,0XFE,0X5D,0X36,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X86,0XFE,0X86,0XFE,0X7E,0XFE, +0X19,0X46,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X4C,0X32,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XFE,0X32,0XCC,0X00,0X00, +0X00,0X00,0X32,0XCC,0X7E,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X4C,0X32,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X19,0X86, +0X7E,0XFE,0X86,0XFE,0X86,0XFE,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X6D,0XB9,0X86,0XFE,0X86,0XFE,0X4C,0X31, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X82, +0X5D,0X36,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XBC,0X21,0XC8,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X21,0XC8,0X7E,0XBC,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X5C,0XF6, +0X08,0X42,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X4C,0X31,0X86,0XFE,0X86,0XFE,0X6D,0XB9,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X22,0X09,0X86,0XFE,0X86,0XFE,0X7E,0XBD,0X08,0X82, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X10,0XC4,0X6D,0XF9, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X76,0X3A,0X19,0X05,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X19,0X05,0X76,0X3A,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X6D,0XB9,0X10,0XC4,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X08,0X82,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X22,0X09,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XB4,0X86,0XFE,0X86,0XFE,0X4B,0XD1,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X19,0X86,0X76,0X7B,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X65,0X77,0X08,0X83,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X83,0X65,0X78,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X76,0X7B,0X19,0X86,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X4B,0XD1,0X86,0XFE,0X86,0XFE,0X54,0XB4,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X08,0X41,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X19,0X45,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X7E,0XBD,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X54,0XB4,0X08,0X41,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X41,0X54,0XB4,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X7E,0XBD,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X19,0X45,0X86,0XFE,0X86,0XFE,0X7E,0XBD,0X08,0X41,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X22,0X09,0X86,0XFE,0X86,0XFE,0X6D,0XF9,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X3B,0X4E,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X76,0X7B,0X43,0X8F,0X43,0X8F,0X43,0X8F,0X43,0X8F,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X43,0X8F,0X43,0X8F,0X43,0X8F,0X43,0X8F,0X76,0X7B, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X3B,0X4E,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X6D,0XF9,0X86,0XFE,0X86,0XFE,0X22,0X09,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X43,0X90,0X86,0XFE,0X86,0XFE,0X4B,0XD1,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X2A,0X4A,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X2A,0X4A,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X4B,0XD1,0X86,0XFE,0X86,0XFE,0X43,0X90,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5C,0XF5,0X86,0XFE,0X86,0XFE,0X2A,0X4A,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X2A,0X8B,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X2A,0X4A,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X2A,0X4A,0X86,0XFE,0X86,0XFE,0X5C,0XF5,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X6D,0XFA,0X86,0XFE,0X86,0XFE,0X19,0X45,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X49,0X43,0X4F,0X43,0X8F,0X43,0X8F,0X43,0X8F, +0X43,0X8F,0X43,0X8F,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X43,0X8F,0X43,0X8F, +0X43,0X8F,0X43,0X8F,0X43,0X8F,0X43,0X4F,0X2A,0X49,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X19,0X46,0X86,0XFE,0X86,0XFE,0X6D,0XFA,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X76,0X7C,0X86,0XFE,0X86,0XFE,0X08,0X82,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X7E,0XFE,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X08,0X83,0X86,0XFE,0X86,0XFE,0X76,0X7C,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7E,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X41,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X65,0XB8,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X65,0XB8,0X86,0XFE,0X7E,0XFE,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7E,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X41,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X7E,0XBD,0X3A,0XCD,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X32,0X8B,0X7E,0XBC,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X76,0X7C,0X86,0XFE,0X86,0XFE,0X08,0X82,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X76,0X3B,0X19,0X45,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X21,0XC8,0X4C,0X32,0X6D,0XB9,0X7E,0XBD,0X7E,0XFE,0X7E,0XBD,0X6D,0XB9,0X4C,0X32, +0X21,0XC8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X10,0XC4,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X6D,0XFA,0X86,0XFE,0X86,0XFE,0X19,0X46,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X76,0X3B,0X10,0XC4,0X00,0X00,0X00,0X00,0X00,0X00,0X21,0XC8,0X6D,0XB8, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X6D,0XB8,0X21,0XC8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5C,0XF5,0X86,0XFE,0X86,0XFE,0X2A,0X4A,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X65,0X77,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X7E,0XBD,0X19,0X45,0X00,0X00,0X00,0X00,0X00,0X00,0X4B,0XD1,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X4B,0XD1,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X43,0X90,0X86,0XFE,0X86,0XFE,0X4B,0XD1,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X5C,0XF5,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X7E,0XBD,0X4C,0X31,0X21,0XC8,0X10,0XC3,0X00,0X41,0X10,0XC3,0X21,0XC8,0X4C,0X31, +0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X5C,0XF5,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X22,0X09,0X86,0XFE,0X86,0XFE,0X6D,0XF9,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X4B,0XD1,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X6E,0X3A, +0X08,0XC3,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X08,0XC3,0X54,0XB4,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X4B,0XD1,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X08,0X41,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X19,0X45,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X65,0X77,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X2A,0X09, +0X00,0X00,0X00,0X00,0X21,0XC8,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X54,0X73,0X86,0XFE,0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE, +0X00,0X00,0X00,0X00,0X43,0X90,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X21,0XC8,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XB4,0X86,0XFE,0X86,0XFE,0X4B,0XD1,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X76,0X3B,0X00,0X00, +0X00,0X00,0X00,0X00,0X6D,0XB8,0X86,0XFE,0X86,0XFE,0X6E,0X3A,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE, +0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XB4,0X86,0XFE,0X86,0XFE,0X6D,0XB8,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X22,0X09,0X86,0XFE,0X86,0XFE,0X7E,0XBD,0X08,0X82, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X65,0X77,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X4C,0X31,0X00,0X00, +0X00,0X00,0X21,0XC8,0X86,0XFE,0X86,0XFE,0X7E,0XBD,0X08,0XC3,0X54,0X73,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE, +0X00,0X00,0X00,0X00,0X00,0X00,0X08,0XC3,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X21,0XC8, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X6D,0XB9,0X86,0XFE,0X86,0XFE,0X4C,0X31, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X4C,0X32,0X86,0XFE,0X86,0XFE,0X4C,0X31,0X00,0X00,0X00,0X00,0X54,0X73, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X54,0X73,0X00,0X00,0X00,0X00,0X86,0XFE,0X86,0XFE, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X4C,0X31,0X86,0XFE,0X86,0XFE,0X4C,0X32, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X86,0XFE,0X86,0XFE,0X7E,0XFE, +0X19,0X86,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X76,0X7C,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X11,0X04,0X00,0X00, +0X00,0X00,0X6D,0XB9,0X86,0XFE,0X86,0XFE,0X21,0XC8,0X00,0X00,0X00,0X00,0X65,0X77, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X65,0X77,0X00,0X00,0X00,0X00,0X21,0XC8,0X86,0XFE,0X86,0XFE,0X6D,0XB9, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X5D,0X36,0X86,0XFE,0X86,0XFE, +0X6D,0XFA,0X08,0X42,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X3B,0X0D,0X43,0X8F,0X43,0X8F,0X43,0X8F,0X00,0X41,0X00,0X00, +0X00,0X00,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X10,0XC3,0X00,0X00,0X00,0X00,0X65,0X77, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X65,0X77,0X00,0X00,0X00,0X00,0X10,0XC3,0X86,0XFE,0X86,0XFE,0X7E,0XBD, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X04,0X7E,0XBD,0X86,0XFE, +0X86,0XFE,0X5C,0XF6,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X7E,0XFE,0X86,0XFE,0X86,0XFE,0X00,0X41,0X00,0X00,0X00,0X00,0X00,0X00, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X41,0X86,0XFE,0X86,0XFE,0X7E,0XFE, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X54,0XB4,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X10,0XC3,0X00,0X00,0X00,0X00,0X00,0X00, +0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X7E,0XBD,0X00,0X00,0X00,0X00,0X00,0X00,0X10,0XC3,0X86,0XFE,0X86,0XFE,0X7E,0XBD, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X43,0X90, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X5C,0XF6,0X08,0X82,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X6D,0XB9,0X86,0XFE,0X86,0XFE,0X21,0XC8,0X00,0X00,0X00,0X00,0X00,0X00, +0X5C,0XF5,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X76,0X3B,0X00,0X00,0X00,0X00,0X00,0X00,0X21,0XC8,0X86,0XFE,0X86,0XFE,0X6D,0XB9, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X4C,0X32,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X6D,0XFA,0X19,0X86,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X4C,0X32,0X86,0XFE,0X86,0XFE,0X4C,0X31,0X00,0X00,0X00,0X00,0X00,0X00, +0X11,0X04,0X7E,0XBC,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X54,0X73,0X00,0X00,0X00,0X00,0X4C,0X31,0X86,0XFE,0X86,0XFE,0X4C,0X32, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X43,0X90,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XFE,0X4C,0X31,0X08,0X82, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X21,0XC8,0X86,0XFE,0X86,0XFE,0X7E,0XBD,0X08,0XC3,0X00,0X00,0X00,0X00, +0X00,0X00,0X11,0X04,0X5C,0XF5,0X7E,0XFE,0X86,0XFE,0X7E,0XFE,0X76,0X3B,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X54,0X73,0X08,0XC3,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X21,0XC8, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X2A,0X4A,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X7E,0XBD, +0X4B,0XD1,0X19,0X45,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X6D,0XB8,0X86,0XFE,0X86,0XFE,0X54,0XB4,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X4B,0XD0,0X86,0XFE,0X4C,0X32,0X00,0X00,0X54,0X73, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X6E,0X3A,0X86,0XFE,0X86,0XFE,0X6D,0XB8,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X04,0X5D,0X36,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X6D,0XF9,0X4B,0XD1,0X2A,0X4A,0X19,0X46,0X08,0X83,0X00,0X00, +0X00,0X00,0X00,0X00,0X21,0XC8,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X43,0X90,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X4B,0XD0,0X86,0XFE,0X4C,0X32,0X00,0X00,0X00,0X00, +0X54,0X73,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X21,0XC8,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X6D,0XB9,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X65,0XB8, +0X00,0X00,0X00,0X00,0X00,0X00,0X4B,0XD1,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X54,0XB4, +0X08,0XC3,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X08,0XC3,0X6E,0X3A,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X4B,0XD1,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X22,0X09, +0X54,0XB4,0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X32,0X8B,0X00,0X00,0X00,0X00,0X00,0X00,0X5C,0XF5,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X7E,0XBD,0X4C,0X31,0X21,0XC8,0X10,0XC3,0X00,0X41,0X10,0XC3,0X21,0XC8,0X4C,0X31, +0X7E,0XBD,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X5C,0XF5,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X08,0X41,0X22,0X09,0X43,0X90,0X5C,0XF5,0X6D,0XFA,0X76,0X7C,0X7E,0XFE, +0X7E,0XBC,0X10,0XC4,0X00,0X00,0X00,0X00,0X00,0X00,0X4B,0XD1,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X4B,0XD1,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X21,0XC8,0X6D,0XB8, +0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE,0X86,0XFE, +0X86,0XFE,0X6D,0XB8,0X21,0XC8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X21,0XC8,0X4C,0X32,0X6D,0XB9,0X7E,0XBD,0X7E,0XFE,0X7E,0XBD,0X6D,0XB9,0X4C,0X32, 0X21,0XC8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -535,10 +1272,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X6D,0XF9,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X6D,0XFA,0X2A,0X09,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -551,10 +1284,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X04,0X5D,0X77,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X76,0X7C,0X32,0X8B,0X08,0X82, -0X08,0X82,0X32,0X8B,0X76,0X7C,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X65,0X77,0X10,0XC4,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -567,10 +1296,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X2A,0X8B,0X7E,0XFD,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X7E,0XFE, -0X4C,0X72,0X65,0XB8,0X87,0X3F,0X87,0X3F,0X6D,0XFA,0X08,0XC3,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X08,0XC3,0X6D,0XFA,0X87,0X3F,0X87,0X3F,0X65,0XB8,0X4C,0X72, -0X7E,0XFE,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X7E,0XFD,0X2A,0X8B,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -583,10 +1308,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X43,0XD0,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X7F,0X3F,0X4C,0X72,0X10,0XC3, -0X21,0XC8,0X7F,0X3F,0X87,0X3F,0X7E,0XBD,0X11,0X04,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X04,0X7E,0XBD,0X87,0X3F,0X7F,0X3F,0X21,0XC8, -0X10,0XC3,0X4C,0X72,0X7F,0X3F,0X87,0X3F,0X87,0X3F,0X7F,0X3F,0X43,0X90,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -599,10 +1320,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X4C,0X32,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X6E,0X3B,0X21,0X87,0X00,0X00,0X00,0X00, -0X65,0XB8,0X87,0X3F,0X87,0X3F,0X32,0XCC,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X32,0XCD,0X87,0X3F,0X87,0X3F,0X65,0XB8, -0X00,0X00,0X00,0X00,0X21,0X87,0X6E,0X3B,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X4C,0X32, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -614,12 +1331,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X43,0XD0, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X5D,0X77,0X08,0X82,0X00,0X00,0X00,0X00,0X21,0XC8, -0X87,0X3F,0X87,0X3F,0X6E,0X3A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X6E,0X3A,0X87,0X3F,0X87,0X3F, -0X21,0XC8,0X00,0X00,0X00,0X00,0X08,0X82,0X5D,0X36,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X43,0X90,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -630,12 +1341,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X8B,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X2A,0X8B,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -646,12 +1351,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X04,0X7E,0XFD,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X7E,0XFE,0X11,0X04,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -662,12 +1361,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X5D,0X77,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X5D,0X77,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -678,12 +1371,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X87,0X3F,0X87,0X3F,0X7F,0X3F, -0X19,0X87,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XB4,0X87,0X3F, -0X87,0X3F,0X2A,0X8B,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X8B,0X87,0X3F, -0X87,0X3F,0X54,0XB4,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X19,0X87, -0X7F,0X3F,0X87,0X3F,0X87,0X3F,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -694,12 +1381,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X6D,0XF9,0X87,0X3F,0X87,0X3F,0X4C,0X32, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X76,0XBC,0X87,0X3F, -0X7F,0X3F,0X08,0X83,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X83,0X7F,0X3F, -0X87,0X3F,0X76,0XBC,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X4C,0X32,0X87,0X3F,0X87,0X3F,0X6D,0XFA,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -710,12 +1391,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X22,0X09,0X87,0X3F,0X87,0X3F,0X7E,0XFE,0X08,0X82, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X04,0X87,0X3F,0X87,0X3F, -0X6E,0X3B,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X6E,0X3B, -0X87,0X3F,0X87,0X3F,0X11,0X04,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X08,0X82,0X7E,0XFE,0X87,0X3F,0X87,0X3F,0X22,0X09,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -726,12 +1401,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XF4,0X87,0X3F,0X87,0X3F,0X4C,0X72,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X87,0X3F,0X87,0X3F, -0X54,0XF5,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XF5, -0X87,0X3F,0X87,0X3F,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X4C,0X31,0X87,0X3F,0X87,0X3F,0X54,0XF5,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -742,12 +1411,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X08,0X41,0X7E,0XFE,0X87,0X3F,0X87,0X3F,0X19,0X05,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X43,0X8F,0X87,0X3F,0X87,0X3F, -0X43,0X8F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X43,0X8F, -0X87,0X3F,0X87,0X3F,0X43,0X8F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X19,0X45,0X87,0X3F,0X87,0X3F,0X7E,0XFE,0X08,0X41,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -758,12 +1421,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X22,0X09,0X87,0X3F,0X87,0X3F,0X6D,0XFA,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XB4,0X87,0X3F,0X87,0X3F, -0X32,0X8B,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X32,0X8B, -0X87,0X3F,0X87,0X3F,0X54,0XB4,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X6E,0X3B,0X87,0X3F,0X87,0X3F,0X22,0X09,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -774,12 +1431,6 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X43,0XD0,0X87,0X3F,0X87,0X3F,0X4C,0X31,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X65,0X77,0X87,0X3F,0X87,0X3F, -0X21,0XC7,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X21,0XC7, -0X87,0X3F,0X87,0X3F,0X65,0X77,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X4C,0X31,0X87,0X3F,0X87,0X3F,0X43,0X90,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -790,28 +1441,20 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X5D,0X36,0X87,0X3F,0X87,0X3F,0X2A,0X4A,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X6E,0X3A,0X87,0X3F,0X87,0X3F, -0X11,0X05,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X05, -0X87,0X3F,0X87,0X3F,0X6E,0X3A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X32,0X8B,0X87,0X3F,0X87,0X3F,0X5D,0X36,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0XDE,0XFB,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XFF,0XFF,0X29,0X45, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75, +0X00,0X00,0X29,0X45,0XFF,0XFF,0XAD,0X75,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X6E,0X3A,0X87,0X3F,0X87,0X3F,0X19,0X45,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X76,0XBC,0X87,0X3F,0X87,0X3F, -0X08,0X83,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X83, -0X87,0X3F,0X87,0X3F,0X76,0XBC,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X19,0X46,0X87,0X3F,0X87,0X3F,0X6D,0XFA,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -819,15 +1462,12 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0XDE,0XFB,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XFF,0XFF,0X29,0X45, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X76,0XBD,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -838,12 +1478,13 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X7F,0X3E,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00, +0XDE,0XFB,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XFF,0XFF,0X29,0X45, +0XAD,0X75,0XF7,0XBE,0XB5,0XB6,0XFF,0XFF,0XFF,0XFF,0X8C,0X71,0X00,0X00,0X00,0X00, +0X7B,0XCF,0XF7,0XBE,0XFF,0XFF,0XCE,0X79,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X7B,0XCF, +0XF7,0XBE,0XFF,0XFF,0XF7,0XBE,0X8C,0X71,0X00,0X00,0XF7,0XBE,0XFF,0XFF,0XFF,0XFF, +0XFF,0XFF,0X5A,0XCB,0XFF,0XFF,0X9C,0XF3,0X29,0X45,0XFF,0XFF,0XB5,0XB6,0XDE,0XFB, +0XFF,0XFF,0XCE,0X79,0X29,0X45,0X00,0X00,0X42,0X08,0XDE,0XFB,0XFF,0XFF,0XDE,0XFB, +0XC6,0X38,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -853,789 +1494,13 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X7F,0X3E,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X76,0XBD,0X87,0X3F,0X87,0X3F,0X10,0XC3,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7E,0XFD,0X87,0X3F,0X87,0X3F, -0X08,0X42,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X42, -0X87,0X3F,0X87,0X3F,0X7E,0XFD,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X10,0XC3,0X87,0X3F,0X87,0X3F,0X76,0XBC,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X6E,0X3A,0X87,0X3F,0X87,0X3F,0X21,0X87,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X76,0X7C,0X87,0X3F,0X87,0X3F, -0X10,0XC3,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X10,0XC4, -0X87,0X3F,0X87,0X3F,0X76,0X7C,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X21,0X87,0X87,0X3F,0X87,0X3F,0X6D,0XF9,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X5D,0X36,0X87,0X3F,0X87,0X3F,0X32,0X8B,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X6E,0X3A,0X87,0X3F,0X87,0X3F, -0X19,0X45,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X19,0X45, -0X87,0X3F,0X87,0X3F,0X6E,0X3A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X32,0X8B,0X87,0X3F,0X87,0X3F,0X5C,0XF5,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X43,0XD0,0X87,0X3F,0X87,0X3F,0X4C,0X32,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X5D,0X77,0X87,0X3F,0X87,0X3F, -0X21,0XC8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X41, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X21,0XC8, -0X87,0X3F,0X87,0X3F,0X5D,0X77,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X4C,0X72,0X87,0X3F,0X87,0X3F,0X43,0X8F,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X22,0X09,0X87,0X3F,0X87,0X3F,0X6E,0X3A,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XB3,0X87,0X3F,0X87,0X3F, -0X32,0XCC,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X22,0X08,0X76,0XBD, -0X22,0X09,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X32,0XCC, -0X87,0X3F,0X87,0X3F,0X54,0XB4,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X6E,0X3A,0X87,0X3F,0X87,0X3F,0X21,0XC8,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X08,0X41,0X7E,0XFE,0X87,0X3F,0X87,0X3F,0X19,0X46,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3B,0X4F,0X87,0X3F,0X87,0X3F, -0X32,0XCC,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X22,0X09,0X7E,0XFE,0X87,0X3F, -0X7E,0XFE,0X2A,0X09,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X43,0XD0, -0X87,0X3F,0X87,0X3F,0X3B,0X4F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X19,0X46,0X87,0X3F,0X87,0X3F,0X7E,0XFE,0X00,0X41,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X54,0XF4,0X87,0X3F,0X87,0X3F,0X4C,0X72,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X87,0X3F,0X43,0X90, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X7F,0X3E,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X7F,0X3E,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3B,0X0D, -0X87,0X3F,0X87,0X3F,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X4C,0X72,0X87,0X3F,0X87,0X3F,0X54,0XB4,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X22,0X08,0X87,0X3F,0X87,0X3F,0X7E,0XFE,0X08,0X83, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X10,0XC3,0X3B,0X0E,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X7F,0X3E,0X87,0X3F,0X87,0X3F,0X6E,0X3B, -0X87,0X3F,0X87,0X3F,0X7F,0X3F,0X2A,0X8B,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X3B,0X4E,0X7F,0X3F,0X10,0XC3,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X10,0XC3,0X7E,0XFE,0X87,0X3F,0X87,0X3F,0X21,0XC8,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X6D,0XF9,0X87,0X3F,0X87,0X3F,0X4C,0X32, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X32,0X8B,0X7F,0X3F,0X87,0X3F,0X87,0X3F,0X54,0XF5,0X00,0X41, -0X54,0XF4,0X87,0X3F,0X87,0X3F,0X7F,0X3F,0X32,0X8B,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X2A,0X8B,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X4C,0X72,0X87,0X3F,0X87,0X3F,0X65,0XB8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X09,0X87,0X3F,0X87,0X3F,0X7F,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X7F,0X3E,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X32,0XCC,0X7F,0X3F,0X87,0X3F,0X87,0X3F,0X5D,0X36,0X00,0X41,0X00,0X00, -0X00,0X41,0X5D,0X36,0X87,0X3F,0X87,0X3F,0X7F,0X3F,0X32,0XCC,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X2A,0X8B,0X7F,0X3E,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X22,0X09,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X5D,0X36,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X7E,0XFE,0X22,0X09,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X33,0X0D,0X7F,0X3F,0X87,0X3F,0X87,0X3F,0X65,0X77,0X08,0X41,0X00,0X00,0X00,0X00, -0X00,0X00,0X08,0X41,0X65,0X77,0X87,0X3F,0X87,0X3F,0X7F,0X3F,0X3B,0X0D,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X09,0X7E,0XFE,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X5D,0X36,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X10,0XC4,0X7E,0XBD,0X87,0X3F, -0X87,0X3F,0X7E,0XFD,0X21,0XC7,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3B,0X0E, -0X7F,0X3F,0X87,0X3F,0X87,0X3F,0X65,0XB8,0X08,0X42,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X08,0X41,0X65,0XB8,0X87,0X3F,0X87,0X3F,0X7F,0X3F,0X3B,0X4E, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X21,0XC8,0X7E,0XFD,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X76,0XBD,0X10,0XC4,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X2A,0X4A,0X7F,0X3F, -0X76,0XBC,0X19,0X46,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3B,0X4E,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X6D,0XFA,0X08,0X82,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X82,0X6D,0XF9,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X43,0X8F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X05,0X76,0XBD,0X87,0X3F, -0X7F,0X3F,0X2A,0X4A,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3B,0X0D, -0X11,0X05,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X43,0X8F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X6E,0X3A,0X08,0X83,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X83,0X6E,0X3A,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X43,0XD0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X19,0X45,0X76,0X7C, -0X3B,0X4F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X43,0XD0,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X76,0X7B,0X10,0XC3,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X10,0XC3,0X6E,0X7B,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X43,0XD1,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X08,0X82, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X4C,0X31,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X76,0X7C, -0X11,0X04,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X11,0X04,0X76,0X7C, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X4C,0X32,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X4C,0X72,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X6E,0X3A, -0X5D,0X77,0X5D,0X77,0X5D,0X77,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X5D,0X77,0X5D,0X77,0X5D,0X77,0X6E,0X3A, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X4C,0X72,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X11,0X04, -0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X11,0X04,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X76,0X7C,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X76,0XBC,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X22,0X09,0X76,0XBC,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F, -0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X87,0X3F,0X76,0X7C,0X22,0X09,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0XFF,0XFF,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0XFF,0XFF, -0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF, -0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF, -0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF, -0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF, -0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF, -0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00, -0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF, -0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF, -0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF, -0XFF,0XFF,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF, -0X00,0X00,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF, -0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0XFF,0XFF,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, -0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0XDE,0XFB,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XFF,0XFF,0X29,0X45, +0XAD,0X75,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X5A,0XCB,0X29,0X45, +0XF7,0XBE,0XB5,0XB6,0X00,0X00,0X8C,0X71,0XFF,0XFF,0XAD,0X75,0X00,0X00,0XF7,0XBE, +0X9C,0XF3,0X00,0X00,0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75, +0X00,0X00,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X29,0X45,0XFF,0XFF,0XE7,0X3C,0X29,0X45, +0X5A,0XCB,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0XDE,0XFB,0XDE,0XFB,0X00,0X00,0X42,0X08, +0XF7,0XBE,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1645,6 +1510,13 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0XDE,0XFB,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XFF,0XFF,0X29,0X45, +0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X8C,0X71, +0XFF,0XFF,0X42,0X08,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X5A,0XCB,0X00,0X00,0XF7,0XBE,0XAD,0X75, +0X00,0X00,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X00,0X00, +0X00,0X00,0XF7,0XBE,0XAD,0X75,0X42,0X08,0XFF,0XFF,0X8C,0X71,0X00,0X00,0X00,0X00, +0XCE,0X79,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1654,6 +1526,13 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0XDE,0XFB,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XFF,0XFF,0X29,0X45, +0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X9C,0XF3, +0XFF,0XFF,0X29,0X45,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X9C,0XF3, +0XE7,0X3C,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X5A,0XCB,0X00,0X00,0XF7,0XBE,0XAD,0X75, +0X00,0X00,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X00,0X00, +0X00,0X00,0XF7,0XBE,0XAD,0X75,0X5A,0XCB,0XFF,0XFF,0X7B,0XCF,0X00,0X00,0X00,0X00, +0XC6,0X38,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1663,6 +1542,13 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0XB5,0XB6,0XE7,0X3C,0X00,0X00,0X00,0X00,0X00,0X00,0XB5,0XB6,0XE7,0X3C,0X00,0X00, +0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X42,0X08,0XFF,0XFF,0X9C,0XF3,0X9C,0XF3, +0XFF,0XFF,0X42,0X08,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X7B,0XCF,0XFF,0XFF, +0X9C,0XF3,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X5A,0XCB,0X00,0X00,0XF7,0XBE,0XAD,0X75, +0X00,0X00,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X00,0X00, +0X00,0X00,0XF7,0XBE,0XAD,0X75,0X5A,0XCB,0XFF,0XFF,0X8C,0X71,0X00,0X00,0X00,0X00, +0XCE,0X79,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1672,6 +1558,13 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X7B,0XCF,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X42,0X08,0XF7,0XBE,0XAD,0X75,0X00,0X00, +0XAD,0X75,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0XAD,0X75,0XFF,0XFF,0X5A,0XCB,0X42,0X08, +0XFF,0XFF,0XB5,0XB6,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0XAD,0X75,0X8C,0X71,0XFF,0XFF, +0X5A,0XCB,0X00,0X00,0XC6,0X38,0XFF,0XFF,0X5A,0XCB,0X00,0X00,0XDE,0XFB,0XC6,0X38, +0X00,0X00,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X00,0X00, +0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0XE7,0X3C,0XDE,0XFB,0X00,0X00,0X5A,0XCB, +0XF7,0XBE,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1681,6 +1574,13 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X9C,0XF3,0XF7,0XBE,0XFF,0XFF,0XFF,0XFF,0XB5,0XB6,0X00,0X00,0X00,0X00, +0XAD,0X75,0XF7,0XBE,0XCE,0X79,0XFF,0XFF,0XF7,0XBE,0X8C,0X71,0X00,0X00,0X00,0X00, +0X8C,0X71,0XFF,0XFF,0XFF,0XFF,0XC6,0X38,0XDE,0XFB,0XAD,0X75,0X00,0X00,0XCE,0X79, +0XFF,0XFF,0XF7,0XBE,0XB5,0XB6,0XFF,0XFF,0X5A,0XCB,0X00,0X00,0X8C,0X71,0XFF,0XFF, +0XFF,0XFF,0X7B,0XCF,0XFF,0XFF,0X9C,0XF3,0X29,0X45,0XFF,0XFF,0X9C,0XF3,0X00,0X00, +0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X5A,0XCB,0XE7,0X3C,0XFF,0XFF,0XDE,0XFB, +0XDE,0XFB,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1691,9 +1591,12 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X29,0X45, +0XE7,0X3C,0XAD,0X75,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1704,9 +1607,12 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF, +0XC6,0X38,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1793,54 +1699,146 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5A,0XCB,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XDE,0XFB, +0X8C,0X71,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X29,0X45,0XCE,0X79,0XFF,0XFF,0XE7,0X3C,0X29,0X45,0XCE,0X79,0XFF,0XFF,0XE7,0X3C, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5A,0XCB,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0X9C,0XF3, +0XFF,0XFF,0X8C,0X71,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X8C,0X71,0XFF,0XFF,0X5A,0XCB,0X00,0X00,0X8C,0X71,0XFF,0XFF,0X5A,0XCB,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5A,0XCB,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0X00,0X00, +0XDE,0XFB,0XE7,0X3C,0X00,0X00,0X00,0X00,0X8C,0X71,0XF7,0XBE,0XFF,0XFF,0XE7,0X3C, +0X7B,0XCF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XF7,0XBE,0XAD,0X75, +0XFF,0XFF,0XFF,0XFF,0X8C,0X71,0X00,0X00,0X00,0X00,0X8C,0X71,0XF7,0XBE,0XFF,0XFF, +0XE7,0X3C,0X7B,0XCF,0X00,0X00,0XF7,0XBE,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X5A,0XCB, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0XAD,0X75,0XFF,0XFF,0XFF,0XFF,0XB5,0XB6, +0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XFF,0XFF,0XFF,0XFF,0XCE,0X79,0X42,0X08, +0X42,0X08,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X42,0X08,0X00,0X00, +0XE7,0X3C,0XB5,0XB6,0X00,0X00,0X8C,0X71,0XF7,0XBE,0XFF,0XFF,0XDE,0XFB,0X5A,0XCB, +0X00,0X00,0XAD,0X75,0XF7,0XBE,0XCE,0X79,0XFF,0XFF,0X6B,0X4D,0X00,0X00,0X00,0X00, +0X00,0X00,0X5A,0XCB,0XDE,0XFB,0XFF,0XFF,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X9C,0XF3, +0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF7,0XBE,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XAD,0X75, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5A,0XCB,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0X00,0X00, +0X9C,0XF3,0XFF,0XFF,0X42,0X08,0X7B,0XCF,0XFF,0XFF,0X8C,0X71,0X00,0X00,0XAD,0X75, +0XF7,0XBE,0X29,0X45,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XFF,0XFF,0X9C,0XF3, +0X00,0X00,0XC6,0X38,0XF7,0XBE,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X8C,0X71,0X00,0X00, +0XAD,0X75,0XF7,0XBE,0X29,0X45,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0XCE,0X79,0X00,0X00,0X6B,0X4D,0XFF,0XFF, +0X9C,0XF3,0X00,0X00,0XAD,0X75,0XF7,0XBE,0X42,0X08,0X00,0X00,0XCE,0X79,0XDE,0XFB, +0X00,0X00,0XE7,0X3C,0XCE,0X79,0X00,0X00,0XCE,0X79,0XFF,0XFF,0X8C,0X71,0X42,0X08, +0XFF,0XFF,0X8C,0X71,0X7B,0XCF,0XFF,0XFF,0X7B,0XCF,0X00,0X00,0XB5,0XB6,0XE7,0X3C, +0X00,0X00,0XAD,0X75,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X29,0X45,0XF7,0XBE,0XB5,0XB6,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X7B,0XCF,0X00,0X00, +0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5A,0XCB,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0X00,0X00, +0X9C,0XF3,0XFF,0XFF,0X5A,0XCB,0XB5,0XB6,0XE7,0X3C,0X00,0X00,0X00,0X00,0X42,0X08, +0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XF7,0XBE,0X00,0X00, +0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0XB5,0XB6,0XE7,0X3C,0X00,0X00,0X00,0X00, +0X42,0X08,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X6B,0X4D,0X00,0X00,0X00,0X00,0XDE,0XFB, +0XCE,0X79,0X00,0X00,0XE7,0X3C,0XB5,0XB6,0X00,0X00,0X00,0X00,0X8C,0X71,0XFF,0XFF, +0X5A,0XCB,0XB5,0XB6,0XE7,0X3C,0X00,0X00,0XF7,0XBE,0XCE,0X79,0XB5,0XB6,0X7B,0XCF, +0XFF,0XFF,0X42,0X08,0XB5,0XB6,0XE7,0X3C,0X00,0X00,0X00,0X00,0X6B,0X4D,0XFF,0XFF, +0X42,0X08,0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X8C,0X71,0XFF,0XFF,0X42,0X08,0X00,0X00,0X00,0X00,0XE7,0X3C,0XC6,0X38,0X00,0X00, +0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5A,0XCB,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0X00,0X00, +0XAD,0X75,0XFF,0XFF,0X29,0X45,0XC6,0X38,0XDE,0XFB,0X00,0X00,0X00,0X00,0X29,0X45, +0XFF,0XFF,0XAD,0X75,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XF7,0XBE,0X00,0X00, +0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0XC6,0X38,0XDE,0XFB,0X00,0X00,0X00,0X00, +0X29,0X45,0XFF,0XFF,0XAD,0X75,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X5A,0XCB,0X00,0X00,0X00,0X00,0XC6,0X38, +0XDE,0XFB,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF, +0X7B,0XCF,0X8C,0X71,0XFF,0XFF,0X8C,0X71,0XE7,0X3C,0X8C,0X71,0XE7,0X3C,0X9C,0XF3, +0XE7,0X3C,0X00,0X00,0XC6,0X38,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF, +0X5A,0XCB,0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00,0X00,0X00,0XDE,0XFB,0XDE,0XFB,0X00,0X00, +0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5A,0XCB,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0X00,0X00, +0XDE,0XFB,0XDE,0XFB,0X00,0X00,0XB5,0XB6,0XE7,0X3C,0X00,0X00,0X00,0X00,0X42,0X08, +0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XF7,0XBE,0X00,0X00, +0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0XB5,0XB6,0XE7,0X3C,0X00,0X00,0X00,0X00, +0X42,0X08,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0XF7,0XBE,0XAD,0X75,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X6B,0X4D,0X00,0X00,0X00,0X00,0XE7,0X3C, +0XCE,0X79,0X00,0X00,0XE7,0X3C,0XB5,0XB6,0X00,0X00,0X00,0X00,0X8C,0X71,0XFF,0XFF, +0X5A,0XCB,0X42,0X08,0XFF,0XFF,0XDE,0XFB,0XB5,0XB6,0X42,0X08,0XFF,0XFF,0XDE,0XFB, +0XB5,0XB6,0X00,0X00,0XB5,0XB6,0XDE,0XFB,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X8C,0X71,0XFF,0XFF,0X42,0X08,0X00,0X00,0X00,0X00,0XE7,0X3C,0XC6,0X38,0X00,0X00, +0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5A,0XCB,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00,0XC6,0X38, +0XFF,0XFF,0X6B,0X4D,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X8C,0X71,0X00,0X00,0XAD,0X75, +0XF7,0XBE,0X29,0X45,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XF7,0XBE,0X00,0X00, +0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X7B,0XCF,0XFF,0XFF,0X8C,0X71,0X00,0X00, +0XAD,0X75,0XF7,0XBE,0X29,0X45,0X00,0X00,0XDE,0XFB,0XC6,0X38,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0XCE,0X79,0X00,0X00,0X7B,0XCF,0XFF,0XFF, +0X9C,0XF3,0X00,0X00,0XAD,0X75,0XF7,0XBE,0X42,0X08,0X00,0X00,0XCE,0X79,0XDE,0XFB, +0X00,0X00,0X00,0X00,0XDE,0XFB,0XFF,0XFF,0X8C,0X71,0X00,0X00,0XE7,0X3C,0XFF,0XFF, +0X8C,0X71,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X6B,0X4D,0X00,0X00,0XB5,0XB6,0XF7,0XBE, +0X00,0X00,0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X29,0X45,0XF7,0XBE,0XB5,0XB6,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X7B,0XCF,0X00,0X00, +0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X5A,0XCB,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XCE,0X79, +0X7B,0XCF,0X00,0X00,0X00,0X00,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0XFF,0XFF,0XE7,0X3C, +0X7B,0XCF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XAD,0X75,0XF7,0XBE,0X00,0X00, +0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0XFF,0XFF, +0XE7,0X3C,0X7B,0XCF,0X00,0X00,0X00,0X00,0X8C,0X71,0XFF,0XFF,0XFF,0XFF,0X6B,0X4D, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0XC6,0X38,0XFF,0XFF,0XFF,0XFF,0XAD,0X75, +0X00,0X00,0X00,0X00,0X00,0X00,0XC6,0X38,0XFF,0XFF,0XFF,0XFF,0XCE,0X79,0X42,0X08, +0X00,0X00,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X42,0X08,0X00,0X00,0XB5,0XB6,0XFF,0XFF, +0X42,0X08,0X00,0X00,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0XFF,0XFF,0XE7,0X3C,0X7B,0XCF, +0X00,0X00,0XAD,0X75,0XF7,0XBE,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X7B,0XCF,0XE7,0X3C,0XFF,0XFF,0XFF,0XFF,0X9C,0XF3,0X00,0X00,0X00,0X00, +0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00,0X9C,0XF3,0XFF,0XFF,0X29,0X45,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1850,6 +1848,7 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X5A,0XCB,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, @@ -1865,6 +1864,7 @@ const unsigned char gImage_updating[32768] = { /*0X10,0X10,0X00,0X80,0X00,0X80,0 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, +0X00,0X00,0X00,0X00,0X7B,0XCF,0XFF,0XFF,0X5A,0XCB,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00, diff --git a/bootable/scripts/tools/releasetools/make_ota_test_zip.sh b/bootable/scripts/tools/releasetools/make_ota_test_zip.sh index a0ce17cb8..df8077bca 100755 --- a/bootable/scripts/tools/releasetools/make_ota_test_zip.sh +++ b/bootable/scripts/tools/releasetools/make_ota_test_zip.sh @@ -5,7 +5,9 @@ ORIGIN_UPDATE_ZIP=../../../../oe-core/build/tmp-glibc/deploy/images/mdm9607/mdm9 OTA_TEST_ZIP=mdm9607-ota-target-image-ubi.zip OUTPUT_ZIP=ota_test_tmp.zip -MODIFY_PRODUCT_FILE=SYSTEM/etc/default_config/product +#MODIFY_PRODUCT_FILE=SYSTEM/etc/default_config/product +CURRENT_PATH=`pwd` +MODIFY_PRODUCT_FILE=${CURRENT_PATH}/../../../../tp-product/product RM_DATA_BIN=SYSTEM/usr/bin/smbd # copy mdm9607-ota-target-image-ubi.zip @@ -21,6 +23,7 @@ pushd ${OTA_TEST_TMP_DIR} FIRMWARE_VER=`cat ${MODIFY_PRODUCT_FILE} | grep -oP '(?<=option firmware_ver ")[\d\.]+'` TEST_FIRMWARE_VER=`echo ${FIRMWARE_VER} | awk -F"." '{print $1 "." $2 "." expr $3 + 1}'` PRODUCT_ID=`cat ${MODIFY_PRODUCT_FILE} | grep -oP '(?<=option product_id ")[\d\.]+'` +UPDATE_VER=`cat ${MODIFY_PRODUCT_FILE} | grep -oP '(?<=option update_ver ")[\d\.]+'` # modify product (firmware_ver + 1) sed -i "s/option firmware_ver \"${FIRMWARE_VER}\"/option firmware_ver \"${TEST_FIRMWARE_VER}\"/g" ${MODIFY_PRODUCT_FILE} @@ -35,7 +38,7 @@ zip ${OTA_TEST_ZIP} ${RM_DATA_BIN} -d # produce compatibility.txt COMPA_TXT=compatibility.txt -echo ${PRODUCT_ID}:${FIRMWARE_VER} > ${COMPA_TXT} +echo ${PRODUCT_ID}:${FIRMWARE_VER}:${UPDATE_VER} > ${COMPA_TXT} ./make_ota_package.sh ${OTA_TEST_ZIP} ${OUTPUT_ZIP} n n OTE_TEST_ZIP=${FIRMWARE_VER}_${TEST_FIRMWARE_VER}.zip @@ -43,7 +46,7 @@ mv update.zip ${OTE_TEST_ZIP} # produce compatibility.txt COMPA_TXT=compatibility.txt -echo ${PRODUCT_ID}:0 > ${COMPA_TXT} +echo ${PRODUCT_ID}:0:${UPDATE_VER} > ${COMPA_TXT} cp -f ${ORIGIN_UPDATE_ZIP} ./${OTA_TEST_ZIP} ./make_ota_package.sh origin_update.zip ${OTA_TEST_ZIP} n n diff --git a/kernel/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi b/kernel/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi index 571a184f5..d1496481f 100644 --- a/kernel/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi +++ b/kernel/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi @@ -328,8 +328,8 @@ regulator-min-microvolt = <1>; regulator-max-microvolt = <7>; - qcom,cpr-voltage-ceiling = <1350000 1350000 1350000>; - qcom,cpr-voltage-floor = <1350000 1350000 1350000>; + qcom,cpr-voltage-ceiling = <1050000 1225000 1350000>; + qcom,cpr-voltage-floor = <1050000 1050000 1350000>; vdd-apc-supply = <&mdm9607_s1>; vdd-mx-supply = <&mdm9607_l12_level_ao>; diff --git a/kernel/drivers/i2c/busses/i2c-msm-v2.c b/kernel/drivers/i2c/busses/i2c-msm-v2.c old mode 100644 new mode 100755 index f7586ecb0..f4273d1cf --- a/kernel/drivers/i2c/busses/i2c-msm-v2.c +++ b/kernel/drivers/i2c/busses/i2c-msm-v2.c @@ -2965,7 +2965,7 @@ static int i2c_msm_init(void) { return platform_driver_register(&i2c_msm_driver); } -arch_initcall(i2c_msm_init); +subsys_initcall(i2c_msm_init); static void i2c_msm_exit(void) { diff --git a/kernel/drivers/mtd/nand/nand_ids.c b/kernel/drivers/mtd/nand/nand_ids.c index 654066093..3fff83d81 100755 --- a/kernel/drivers/mtd/nand/nand_ids.c +++ b/kernel/drivers/mtd/nand/nand_ids.c @@ -69,14 +69,20 @@ struct nand_flash_dev nand_flash_ids[] = { { .id = {0x98, 0xac, 0x90, 0x26, 0x76, 0x00, 0x00, 0x00} }, SZ_4K, SZ_512, SZ_256K, 0, 5, 128, NAND_ECC_INFO(8, SZ_512) }, - {"MT29RZ2B1DZZHGSP 2G 1.8V 4-bit", - { .id = {0x2c, 0xaa, 0x90, 0x15, 0x00, 0x00, 0x00, 0x00} }, - SZ_2K, SZ_256, SZ_128K, 0, 4, 64, NAND_ECC_INFO(4, SZ_512) }, + // Add by wuchao, 20.12.29, for ESMT FM6BD2G1GXA, this flash support ONFI, info here will not be used + {"FM6BD2G1GXA 2G 1.8V 8-bit", + { .id = {0x2c, 0xaa, 0x90, 0x15, 0x06, 0x00, 0x00, 0x00} }, + SZ_2K, SZ_256, SZ_128K, 0, 5, 128, NAND_ECC_INFO(8, SZ_512) }, {"KSLCMAL2TA0M2A 2G 1.8V 8-bit", { .id = {0x98, 0xaa, 0x90, 0x15, 0x00, 0x00, 0x00, 0x00} }, SZ_2K, SZ_256, SZ_128K, 0, 4, 128, NAND_ECC_INFO(8, SZ_512)}, + // Add by wuchao, 20.12.29, for ESMT FM6BD2G1GA, this flash does not support ONFI + {"FM6BD2G1GA 2G 1.8V 8-bit", + { .id = {0xc8, 0xaa, 0x90, 0x15, 0x00, 0x00, 0x00, 0x00} }, + SZ_2K, SZ_256, SZ_128K, 0, 4, 64, NAND_ECC_INFO(4, SZ_512)}, + LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE5, 4, SZ_8K, SP_OPTIONS), @@ -206,6 +212,7 @@ struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_INTEL, "Intel"}, {NAND_MFR_WINBOND, "Winbond"}, {NAND_MFR_ESMT, "ESMT"}, + {NAND_MFR_ESMT2, "ESMT"}, {0x0, "Unknown"} }; diff --git a/kernel/drivers/oled/s90319fb.c b/kernel/drivers/oled/s90319fb.c index 52e542f82..c7e2a508a 100644 --- a/kernel/drivers/oled/s90319fb.c +++ b/kernel/drivers/oled/s90319fb.c @@ -52,12 +52,16 @@ typedef unsigned int boolean; #define FALSE 0 #endif +#define ID_GC9106 0x9106 +#define ID_GC9104 0x9104 + // reset static int lcd_s90319_rsx; - static int lcd_s90319_cs; static int lcd_s90319_boost_en; +static unsigned int lcd_id = 0; + enum GPIO_LCD_S90319 { GPIO_LCD_CS = 0, GPIO_LCD_RESET, @@ -65,6 +69,8 @@ enum GPIO_LCD_S90319 { GPIO_LCD_RSX, GPIO_LCD_VDD0, GPIO_LCD_VDD1, + GPIO_LCD_MOSI, + GPIO_LCD_CLK, GPIO_LCD_END, }; @@ -76,7 +82,8 @@ static const char *dts_gpio_name[] = { [GPIO_LCD_RSX] = "qcom,oled-rsx-gpio", [GPIO_LCD_VDD0] = "qcom,oled-vdd0-gpio", [GPIO_LCD_VDD1] = "qcom,oled-vdd1-gpio", - + [GPIO_LCD_MOSI] = "qcom,oled-mosi-gpio", + [GPIO_LCD_CLK] = "qcom,oled-clk-gpio", [GPIO_LCD_END] = "", }; @@ -98,8 +105,6 @@ static struct spi_device *s90319_spi; static uint8_t frame_data[COLUMN_NUM * ROW_NUM * 2] ={0}; static uint8_t frame_data_buf[COLUMN_NUM * ROW_NUM * 2] ={0}; -static int lcd_s90319_rsx; - static struct mutex flush_mutex; static struct mutex oled_panel_mutex; @@ -304,7 +309,6 @@ static int s90319_spi_txdata(uint8_t *txdata, const uint16_t length) return spi_sync(s90319_spi, &spi_msg); } - /************************************************************ Function : s90319_spi_write_cmd Description: transfer cmd by spi @@ -393,7 +397,6 @@ void wr_dat(uint8_t data) s90319_spi_write_data(&data, 1); } - /************************************************************ Function : oled_s90319_fill_with_pic Description: write pic data on location assign @@ -415,8 +418,17 @@ static int oled_s90319_fill_with_pic(const uint8_t *pic, const uint8_t x, oled_s90319_set_col_addr[1] = x + X_OFFSET; oled_s90319_set_col_addr[3] = x + width - 1 + X_OFFSET; - oled_s90319_set_row_addr[1] = y + Y_OFFSET; - oled_s90319_set_row_addr[3] = y + height - 1 + Y_OFFSET; + + if (lcd_id == ID_GC9106 || lcd_id == ID_GC9104) + { + oled_s90319_set_row_addr[1] = y + Y_OFFSET_GC9106; + oled_s90319_set_row_addr[3] = y + height - 1 + Y_OFFSET_GC9106; + } + else + { + oled_s90319_set_row_addr[1] = y + Y_OFFSET; + oled_s90319_set_row_addr[3] = y + height - 1 + Y_OFFSET; + } for (i = 0; i < height; i++){ for (j = 0; j < width * 2; j++) @@ -468,89 +480,485 @@ static void s90319fb_fillrect(struct fb_info *info, const struct fb_fillrect *re oled_s90319_fill_with_pic(info->screen_base, x, y, width, height); } -static void lcd_s90319_panel_init(void) +/******************************************************************************* + Function : spi_start + Description : Start or restart spi communication + Input : None + Output : None + Return : None + Others : None +*******************************************************************************/ +void spi_start(void) { - /* End Reset Sequence */ - wr_comm(0x11); //Sleep out - mdelay (120); //Delay 120ms - /* Frame Rate */ - wr_comm(0xB1); + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_CS], 0); + //oled_udelay(SPI_SPEED_DURATION); + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_CS], 0);/* start condition */ + //oled_udelay(SPI_SPEED_DURATION); +} + +/******************************************************************************* + Function : spi_stop + Description : stop spi communication + Input : None + Output : None + Return : None + Others : None +*******************************************************************************/ +void spi_stop(void) +{ + //gpio_set_value(lcd_s90319_gpio[GPIO_LCD_CS], 1); /* stop condition */ + //oled_udelay(SPI_SPEED_DURATION); +} + +/******************************************************************************* + Function : s90319_spi_txdata_byte + Description : Transfer data, from baseband chip to spi device. + Input : data: Data to transfer + Output : None + Return : None + Others : None +*******************************************************************************/ +void s90319_spi_txdata_byte(uint8_t data) +{ + int i = 0; + + for(i = 7; (i >= 0)&&(i <= 7); i--) { + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_CLK], 0); + //oled_udelay(SPI_SPEED_DURATION); + if(i == 7) { + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_MOSI], 0); + } + + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_MOSI], (data >> i) & 0x01); + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_CLK], 1); + } + + return; +} + +int spi_txdata_by_gpio(uint8_t *txdata, const uint16_t length, int compress) +{ + uint8_t j; + signed char m; + uint8_t data; + uint8_t data_first; + uint8_t data_second; + + spi_start(); + if (compress){ + for(j = 0; j < length; j++, txdata++) { + data = *txdata; + for(m = 7; (m >= 0)&&(m <= 7); m--) + { + if((data >> m) & 0x01) + { + data_first = 0x00; + data_second = 0x00; + } + else + { + data_first = 0xFF; + data_second = 0xFF; + } + s90319_spi_txdata_byte(data_first); + s90319_spi_txdata_byte(data_second); + } + } + } + else + { + for(j = 0; j < length; j++, txdata++) { + s90319_spi_txdata_byte(*txdata); + } + } + + spi_stop(); + + return 0; +} + +/******************************************************************************* + Function : spi_write_cmd_by_gpio + Description : Transfer cmd. + Input : data: cmd to transfer + len: length of cmd + Output : None + Return : None + Others : None +*******************************************************************************/ +int spi_write_cmd_by_gpio(const uint8_t *data, const uint16_t len) +{ + int rc = 0; + + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_RSX], 0); + mdelay(1); + + memcpy(frame_data, data, len); + + rc = spi_txdata_by_gpio(frame_data, len, FALSE); + + return rc; +} + +/******************************************************************************* + Function : wr_comm + Description : write init cmd. + Input : + Output : None + Return : None + Others : None +*******************************************************************************/ +void wr_comm_by_gpio(uint8_t cmd) +{ + spi_write_cmd_by_gpio(&cmd, 1); +} + +void oled_gpio_spi_config(void) +{ + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_MOSI], 0); + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_CS], 0); + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_BOOST_EN], 0); + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_RESET], 0); + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_CLK], 0); + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_VDD0], 0); + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_VDD1], 0); + gpio_direction_output(lcd_s90319_gpio[GPIO_LCD_RSX], 0); + + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_VDD0], 1); + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_VDD1], 1); + + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_CS], 0); + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_RSX], 0); + + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_RESET], 1); + mdelay(120); + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_RESET], 0); + mdelay(100); + gpio_set_value(lcd_s90319_gpio[GPIO_LCD_RESET], 1); + mdelay(120); +} + +unsigned int oled_read_data(int num) +{ + unsigned int i=0, dat=0; + + for(i=0;i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef BQ25601_DEBUG + +#undef dev_dbg +#ifdef BQ25601_DEBUG +#define dev_dbg(dev, format, arg...) dev_printk(KERN_INFO, dev, format, ##arg) +#else +#define dev_dbg(dev, format, arg...) +#endif + +//define addrflag +int addrflag = 1; +int part_id; + +// current is defined as a macro in current.h + +/* Correspondence table of voltage and temperature */ +static const int adc_map_temp[][2] = +{ + {1800, -100}, + {1712, -40}, + {1654, -30}, + {1570, -20}, + {1517, -15}, + {1457, -10}, + {1390, -5}, + {1316, 0}, + {1238, 5}, + {1155, 10}, + {1070, 15}, + {985, 20}, + {900, 25}, + {817, 30}, + {738, 35}, + {663, 40}, + {593, 45}, + {529, 50}, + {470, 55}, + {417, 60}, + {370, 65}, + {291, 75}, + {160, 100}, + {91, 125}, + {0, 1000}, +}; + +struct bq25601_charger { + struct i2c_client *client; + struct device *dev; + + struct power_supply *usb_psy; + struct power_supply batt_psy; + + struct qpnp_vadc_chip *vadc_dev; + + struct work_struct usb_detect_work; + + struct mutex lock; + struct mutex irq_lock; + struct mutex read_write_lock; + + u32 irq_gpio; + u32 charge_gpio; + + int usb_status; + int vbat_div; +}; + +static enum power_supply_property bq25601_power_properties[] = { + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_VOLTAGE_MAX, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_MANUFACTURER, +}; + +/* i2c read & write */ + +static int __bq25601_read_reg(struct bq25601_charger *chip, u8 reg, u8 *val) +{ + s32 ret; + + ret = i2c_smbus_read_byte_data(chip->client, reg); + if (ret < 0) + { + dev_err(chip->dev, "i2c read fail: can't read from %02x: %d\n", reg, ret); + return ret; + } + else + { + *val = ret; + } + + dev_dbg(chip->dev, "%s: get reg(0x%02x) value 0x%02x\n", __func__, reg, *val); + return 0; +} + +static int __bq25601_write_reg(struct bq25601_charger *chip, int reg, u8 val) +{ + s32 ret; + + ret = i2c_smbus_write_byte_data(chip->client, reg, val); + if (ret < 0) + { + dev_err(chip->dev, "i2c write fail: can't write %02x to %02x: %d\n", val, reg, ret); + return ret; + } + + dev_dbg(chip->dev, "%s: set reg(0x%02x) value 0x%02x\n", __func__, reg, val); + return 0; +} + +static int bq25601_read_reg(struct bq25601_charger *chip, int reg, u8 *val) +{ + int rc; + + mutex_lock(&chip->read_write_lock); + rc = __bq25601_read_reg(chip, reg, val); + mutex_unlock(&chip->read_write_lock); + + return rc; +} + +static int bq25601_masked_write(struct bq25601_charger *chip, int reg, u8 mask, u8 val, u8 shift) +{ + s32 rc; + u8 temp; + + mutex_lock(&chip->read_write_lock); + rc = __bq25601_read_reg(chip, reg, &temp); + if (rc) + { + goto out; + } + + mask <<= shift; + val <<= shift; + + temp &= ~mask; + temp |= val & mask; + rc = __bq25601_write_reg(chip, reg, temp); + +out: + mutex_unlock(&chip->read_write_lock); + return rc; +} + +/* set usb charging current */ + +#define USB_CHARGE_CURRENT_CTRL_REG 0x0 +#define USB_CHARGE_CURRENT_MASK 0x1F +#define USB_CHARGE_CURRENT_SHIFT 0 + +// to do... we can use a better way +#define USB_CHARGE_CURRENT_VAL1000 0x9 + +static int bq25601_set_usb_charge_current(struct bq25601_charger *chip, unsigned int charge_current) +{ + u8 val = USB_CHARGE_CURRENT_VAL1000; + + dev_dbg(chip->dev, "%s: set usb charge current %dmA\n", __func__, charge_current); + + switch (charge_current) + { + case 1000: + val = USB_CHARGE_CURRENT_VAL1000; + break; + default: + val = USB_CHARGE_CURRENT_VAL1000; + break; + } + + return bq25601_masked_write(chip, USB_CHARGE_CURRENT_CTRL_REG, + USB_CHARGE_CURRENT_MASK, val, USB_CHARGE_CURRENT_SHIFT); +} + +/* set & get battery charging current */ + +#define BATT_CHARGE_CURRENT_CTRL_REG 0x2 +#define BATT_CHARGE_CURRENT_MASK 0x3F +#define BATT_CHARGE_CURRENT_SHIFT 0 + +// to do... we can use a better way +#define BATT_CHARGE_CURRENT_VAL0 0x0 +#define BATT_CHARGE_CURRENT_VAL420 0x7 +#define BATT_CHARGE_CURRENT_VAL960 0x10 +#define BATT_CHARGE_CURRENT_VAL420_NEW 0x1C +#define BATT_CHARGE_CURRENT_VAL960_NEW 0x27 + +static int bq25601_set_batt_charge_current(struct bq25601_charger *chip, unsigned int charge_current, int addrflag) +{ + u8 val = BATT_CHARGE_CURRENT_VAL0; + + dev_dbg(chip->dev, "%s: set battery charge current %dmA\n", __func__, charge_current); + + if ((addrflag == 2) && (part_id >= 0)) + { + switch (charge_current) + { + case 0: + val = BATT_CHARGE_CURRENT_VAL0; + break; + case 400: + val = BATT_CHARGE_CURRENT_VAL420_NEW; + break; + case 1000: + val = BATT_CHARGE_CURRENT_VAL960_NEW; + break; + default: + val = BATT_CHARGE_CURRENT_VAL420_NEW; + break; + } + } + else + { + switch (charge_current) + { + case 0: + val = BATT_CHARGE_CURRENT_VAL0; + break; + case 400: + val = BATT_CHARGE_CURRENT_VAL420; + break; + case 1000: + val = BATT_CHARGE_CURRENT_VAL960; + break; + default: + val = BATT_CHARGE_CURRENT_VAL420; + break; + } + } + return bq25601_masked_write(chip, BATT_CHARGE_CURRENT_CTRL_REG, + BATT_CHARGE_CURRENT_MASK, val, BATT_CHARGE_CURRENT_SHIFT); +} + +static int bq25601_get_batt_charge_current(struct bq25601_charger *chip, unsigned int *charge_current, int addrflag) +{ + int rc; + u8 val; + + rc = bq25601_read_reg(chip, BATT_CHARGE_CURRENT_CTRL_REG, &val); + if (rc < 0) + return -EAGAIN; + + if ((addrflag == 2) && (part_id >= 0)) + { + switch ((val >> BATT_CHARGE_CURRENT_SHIFT) & BATT_CHARGE_CURRENT_MASK) + { + case BATT_CHARGE_CURRENT_VAL0: + *charge_current = 0; + break; + case BATT_CHARGE_CURRENT_VAL420_NEW: + *charge_current = 400; + break; + case BATT_CHARGE_CURRENT_VAL960_NEW: + *charge_current = 1000; + break; + default: + *charge_current = 400; + break; + } + } + else + { + switch ((val >> BATT_CHARGE_CURRENT_SHIFT) & BATT_CHARGE_CURRENT_MASK) + { + case BATT_CHARGE_CURRENT_VAL0: + *charge_current = 0; + break; + case BATT_CHARGE_CURRENT_VAL420: + *charge_current = 400; + break; + case BATT_CHARGE_CURRENT_VAL960: + *charge_current = 1000; + break; + default: + *charge_current = 400; + break; + } + } + + dev_dbg(chip->dev, "%s: get battery charge current(0x%02x) %dmA\n", __func__, val, *charge_current); + return 0; +} + +/*set & get pre charge current */ +#define BATT_CHARGE_PRE_CURRENT_REG 0x3 +#define BATT_CHARGE_PRE_CURRENT_VAL180 0xDD +#define BATT_CHARGE_PRE_CURRENT_VAL40 0xD5 + +static int bq25601_set_batt_pre_charge_current(struct bq25601_charger *chip, unsigned int pre_current) +{ + u8 val = BATT_CHARGE_PRE_CURRENT_VAL180; + + dev_dbg(chip->dev, "%s: set batt pre charge current %dmA\n", __func__, val); + + s32 ret; + + switch (pre_current) + { + case 180: + val = BATT_CHARGE_PRE_CURRENT_VAL180; + break; + case 40: + val = BATT_CHARGE_PRE_CURRENT_VAL40; + break; + default: + val = BATT_CHARGE_PRE_CURRENT_VAL180; + break; + } + + ret = i2c_smbus_write_byte_data(chip->client, BATT_CHARGE_PRE_CURRENT_REG, val); + if (ret < 0) + { + dev_err(chip->dev, "i2c write fail: can't write %02x to %02x: %d\n", val, BATT_CHARGE_PRE_CURRENT_REG, ret); + return ret; + } + return 0; +} + +static int bq25601_get_batt_pre_charge_current(struct bq25601_charger *chip, unsigned int *pre_current) +{ + int rc; + u8 val; + + rc = bq25601_read_reg(chip, BATT_CHARGE_PRE_CURRENT_REG, &val); + if (rc < 0) + return -EAGAIN; + + switch (val) + { + case BATT_CHARGE_PRE_CURRENT_VAL180: + *pre_current = 180; + break; + case BATT_CHARGE_PRE_CURRENT_VAL40: + *pre_current = 40; + break; + default: + *pre_current = 180; + break; + } + return 0; +} + +/* set & get battery charging voltage */ + +#define BATT_CHARGE_VOLTAGE_CTRL_REG 0x4 +#define BATT_CHARGE_VOLTAGE_MASK 0x1F +#define BATT_CHARGE_VOLTAGE_SHIFT 3 + +// to do... we can use a better way +#define BATT_CHARGE_VOLTAGE_VAL4080 0x7 +#define BATT_CHARGE_VOLTAGE_VAL4208 0xB + +static int bq25601_set_batt_charge_voltage(struct bq25601_charger *chip, unsigned int voltage) +{ + u8 val = BATT_CHARGE_VOLTAGE_VAL4208; + + dev_dbg(chip->dev, "%s: set battery charge voltage %dmV\n", __func__, voltage); + + switch (voltage) + { + case 4100: + val = BATT_CHARGE_VOLTAGE_VAL4080; + break; + case 4200: + val = BATT_CHARGE_VOLTAGE_VAL4208; + break; + default: + val = BATT_CHARGE_VOLTAGE_VAL4080; + break; + } + + return bq25601_masked_write(chip, BATT_CHARGE_VOLTAGE_CTRL_REG, + BATT_CHARGE_VOLTAGE_MASK, val, BATT_CHARGE_VOLTAGE_SHIFT); +} + +static int bq25601_get_batt_charge_voltage(struct bq25601_charger *chip, unsigned int *voltage) +{ + int rc; + u8 val; + + rc = bq25601_read_reg(chip, BATT_CHARGE_VOLTAGE_CTRL_REG, &val); + if (rc < 0) + return -EAGAIN; + + switch ((val >> BATT_CHARGE_VOLTAGE_SHIFT) & BATT_CHARGE_VOLTAGE_MASK) + { + case BATT_CHARGE_VOLTAGE_VAL4080: + *voltage = 4100; + break; + case BATT_CHARGE_VOLTAGE_VAL4208: + *voltage = 4200; + break; + default: + *voltage = 4100; + break; + } + + dev_dbg(chip->dev, "%s: get battery charge voltage(0x%02x) %dmV\n", __func__, val, *voltage); + return 0; +} + +/* disable watchdog */ + +#define WATCHDOG_CTRL_REG 0x5 +#define WATCHDOG_MASK 0x3 +#define WATCHDOG_SHIFT 4 + +// to do... we can use a better way +#define WATCHDOG_DISABLED 0x0 + +static int bq25601_disable_watchdog(struct bq25601_charger *chip) +{ + u8 val = WATCHDOG_DISABLED; + + dev_dbg(chip->dev, "%s: disable watchdog\n", __func__); + + return bq25601_masked_write(chip, WATCHDOG_CTRL_REG, WATCHDOG_MASK, val, WATCHDOG_SHIFT); +} + +/* set usb charging min voltage */ + +#define USB_CHARGE_VOLTAGE_CTRL_REG 0x6 +#define USB_CHARGE_VOLTAGE_MASK 0xF +#define USB_CHARGE_VOLTAGE_SHIFT 0 + +// to do... we can use a better way +#define USB_CHARGE_VOLTAGE_VAL4600 0x7 + +static int bq25601_set_usb_charge_voltage(struct bq25601_charger *chip, unsigned int voltage) +{ + u8 val = USB_CHARGE_VOLTAGE_VAL4600; + + dev_dbg(chip->dev, "%s: set usb charge voltage %dmV\n", __func__, voltage); + + switch (voltage) + { + case 4600: + val = USB_CHARGE_VOLTAGE_VAL4600; + break; + default: + val = USB_CHARGE_VOLTAGE_VAL4600; + break; + } + + return bq25601_masked_write(chip, USB_CHARGE_VOLTAGE_CTRL_REG, + USB_CHARGE_VOLTAGE_MASK, val, USB_CHARGE_VOLTAGE_SHIFT); +} + +/* get usb status */ + +#define USB_STATUS_CTRL_REG 0x8 +#define USB_POWER_STATUS_MASK 0x1 +#define USB_POWER_STATUS_SHIFT 2 + +static int bq25601_get_usb_status(struct bq25601_charger *chip, unsigned int *status) +{ + int rc; + u8 val; + + rc = bq25601_read_reg(chip, USB_STATUS_CTRL_REG, &val); + if (rc < 0) + return -EAGAIN; + + // we can just use PG_STST + if ((val >> USB_POWER_STATUS_SHIFT) & USB_POWER_STATUS_MASK) + { + *status = 1; + } + else + { + *status = 0; + } + + dev_dbg(chip->dev, "%s: get usb status(0x%02x) %d\n", __func__, val, *status); + return 0; +} + +/* get battery voltage */ + +static int bq25601_get_property_battery_voltage(struct bq25601_charger *chip) +{ + int rc = 0; + struct qpnp_vadc_result results; + int voltage = 0; + + if (IS_ERR_OR_NULL(chip->vadc_dev)) + { + chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg"); + if (IS_ERR(chip->vadc_dev)) + { + pr_err("%s, Failed to get vadc\n", __func__); + return PTR_ERR(chip->vadc_dev); + } + } + + rc = qpnp_vadc_read(chip->vadc_dev, P_MUX2_1_1, &results); + if (rc) + { + pr_err("Unable to read battery voltage, rc = %d\n", rc); + return rc; + } + + voltage = (int)(results.physical * chip->vbat_div) / 1000; + dev_dbg(chip->dev, "%s: get battery voltage %d\n", __func__, voltage); + return voltage; +} + +/* get part id */ +#define BATT_PART_ID_REG 0xB +static int bq25601_get_batt_part_id(struct bq25601_charger *chip) +{ + int rc; + u8 val; + + rc = bq25601_read_reg(chip, BATT_PART_ID_REG, &val); + dev_dbg("get reg(0x%02x) value 0x%02x\n", BATT_PART_ID_REG, val); + if (rc < 0) + return -1; + return val; +} + +/* get battery temperature */ + +static int em_batt_map_linear(const int (*table)[2], const u32 table_size, int in_num, int *out_num) +{ + u32 i = 0; + + if ((NULL == table) || (NULL == out_num)) + { + pr_err("Invalid parameter\n"); + return -EINVAL; + } + + while (i < table_size) + { + if (table[i][0] < in_num) + { + break; + } + i++; + } + + if (i == 0) + { + *out_num = table[0][1]; + } + else if (i == table_size) + { + *out_num = table[table_size-1][1]; + } + else + { + /* result is between search_index and search_index-1, interpolate linearly */ + *out_num = (((table[i][1] - table[i-1][1]) * (in_num - table[i-1][0])) + / (table[i][0] - table[i-1][0])) + table[i-1][1]; + } + + return 0; +} + +static int bq25601_get_property_battery_id_therm(struct bq25601_charger *chip) +{ + int rc = 0; + int temp_value = 0; + struct qpnp_vadc_result results; + + if (IS_ERR_OR_NULL(chip->vadc_dev)) + { + chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg"); + if (IS_ERR(chip->vadc_dev)) + { + pr_err("%s, Failed to get vadc\n", __func__); + return PTR_ERR(chip->vadc_dev); + } + } + + rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX2_BAT_ID, &results); + if (rc) + { + pr_err("Unable to read battery temperature, rc = %d\n", rc); + return rc; + } + + temp_value = ((int)results.physical) / 1000; /* convert to mV */ + + rc = em_batt_map_linear(adc_map_temp, sizeof(adc_map_temp) / sizeof(adc_map_temp[0]), + temp_value, &temp_value); + if (rc) + { + pr_err("Unable to calculate battery temperature, rc = %d\n", rc); + return rc; + } + + return temp_value; +} + +/* sysfs, write & read */ + +static int bq25601_property_is_writeable(struct power_supply *psy, enum power_supply_property psp) +{ + switch (psp) + { + case POWER_SUPPLY_PROP_CURRENT_MAX: + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + case POWER_SUPPLY_PROP_CURRENT_NOW: + return 1; + default: + return 0; + } +} + +static int bq25601_power_set_property(struct power_supply *psy, enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct bq25601_charger *chip = container_of(psy, struct bq25601_charger, batt_psy); + + mutex_lock(&chip->lock); + + switch (psp) + { + case POWER_SUPPLY_PROP_CURRENT_MAX: + bq25601_set_batt_charge_current(chip, val->intval, addrflag); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + bq25601_set_batt_charge_voltage(chip, val->intval); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + bq25601_set_batt_pre_charge_current(chip, val->intval); + break; + default: + mutex_unlock(&chip->lock); + return -EINVAL; + } + + mutex_unlock(&chip->lock); + power_supply_changed(&chip->batt_psy); + return 0; +} + +static int bq25601_power_get_property(struct power_supply *psy, enum power_supply_property psp, + union power_supply_propval *val) +{ + struct bq25601_charger *chip = container_of(psy, struct bq25601_charger, batt_psy); + + mutex_lock(&chip->lock); + + switch (psp) + { + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = bq25601_get_property_battery_voltage(chip); + break; + case POWER_SUPPLY_PROP_TEMP: + val->intval = bq25601_get_property_battery_id_therm(chip); + break; + case POWER_SUPPLY_PROP_CURRENT_MAX: + bq25601_get_batt_charge_current(chip, &(val->intval), addrflag); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MAX: + bq25601_get_batt_charge_voltage(chip, &(val->intval)); + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + bq25601_get_batt_pre_charge_current(chip, &(val->intval)); + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = POWER_SUPPLY_TECHNOLOGY_LION; + break; + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = "BQ25601"; + break; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = "TI"; + break; + default: + mutex_unlock(&chip->lock); + return -EINVAL; + } + + mutex_unlock(&chip->lock); + return 0; +} + +/* irq handler & usb detect */ + +static int bq25601_set_usb_default_status(struct bq25601_charger *chip) +{ + int rc = 0; + + // set usb charge limit voltage 4.6V + rc = bq25601_set_usb_charge_voltage(chip, 4600); + if (rc) + { + dev_err(chip->dev, "set usb charge voltage failed\n"); + return rc; + } + + // set usb charge current 1A + rc = bq25601_set_usb_charge_current(chip, 1000); + if (rc) + { + dev_err(chip->dev, "set usb charge current failed\n"); + return rc; + } + + // enable usb charging + rc = gpio_direction_output(chip->charge_gpio, 0); + if (rc) + { + dev_err(chip->dev, "set direction for charge gpio(%d) failed\n", chip->charge_gpio); + return rc; + } + + // disable watchdog + rc = bq25601_disable_watchdog(chip); + if (rc) + { + dev_err(chip->dev, "disable watchdog failed\n"); + return rc; + } + + //set batt pre charge + if ((addrflag == 2) && (part_id >= 0)) + { + rc = bq25601_set_batt_pre_charge_current(chip, 180); + } + if (rc) + { + dev_err(chip->dev, "set batt pre charge failed\n"); + return rc; + } + + return rc; +} + +static void bq25601_usb_detect_work_func(struct work_struct *work) +{ + struct bq25601_charger *chip = container_of(work, struct bq25601_charger, usb_detect_work); + int status = 0; + + bq25601_get_usb_status(chip, &status); + if ((chip->usb_status != status) && (chip->usb_psy)) + { + if (status) + { + dev_info(chip->dev, "usb insert, reset usb charge status\n"); + bq25601_set_usb_default_status(chip); + } + power_supply_set_present(chip->usb_psy, status); + chip->usb_status = status; + } + else + { + dev_dbg(chip->dev, "usb status not changed\n"); + } +} + +static irqreturn_t bq25601_irq_handler(int irq, void *dev_id) +{ + struct bq25601_charger *chip = dev_id; + + mutex_lock(&chip->irq_lock); + dev_dbg(chip->dev, "IRQ triggered\n"); + schedule_work(&chip->usb_detect_work); + mutex_unlock(&chip->irq_lock); + + return IRQ_HANDLED; +} + +/* module init & probe & remove */ + +static int bq25601_charger_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int rc, irq, value; + struct bq25601_charger *chip; + struct power_supply *usb_psy; + + dev_info(&client->dev, "BQ25601 charger probe start...\n"); + + usb_psy = power_supply_get_by_name("usb"); + if (!usb_psy) + { + dev_dbg(&client->dev, "USB psy not found, deferring probe\n"); + return -EPROBE_DEFER; + } + // same init value as chip->usb_status + power_supply_set_present(usb_psy, 0); + + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + { + dev_err(&client->dev, "Cannot allocate memory\n"); + return -ENOMEM; + } + + chip->client = client; + if (client->addr == 0x6b) + { + addrflag = 1; + } + else + { + addrflag = 2; + } + chip->dev = &client->dev; + chip->usb_psy = usb_psy; + chip->usb_status = 0; + + mutex_init(&chip->lock); + mutex_init(&chip->irq_lock); + mutex_init(&chip->read_write_lock); + part_id = bq25601_get_batt_part_id(chip); + if (part_id < 0) + { + return -1; + } + if (of_find_property(chip->dev->of_node, "qcom,chg-vadc", NULL)) + { + /* early for VADC get, defer probe if needed */ + chip->vadc_dev = qpnp_get_vadc(chip->dev, "chg"); + if (IS_ERR(chip->vadc_dev)) + { + rc = PTR_ERR(chip->vadc_dev); + if (rc != -EPROBE_DEFER) + pr_err("vadc property configured incorrectly\n"); + return rc; + } + } + + chip->batt_psy.name = "battery"; + chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY; + chip->batt_psy.get_property = bq25601_power_get_property; + chip->batt_psy.set_property = bq25601_power_set_property; + chip->batt_psy.property_is_writeable = bq25601_property_is_writeable; + chip->batt_psy.properties = bq25601_power_properties; + chip->batt_psy.num_properties = ARRAY_SIZE(bq25601_power_properties); + + rc = power_supply_register(chip->dev, &chip->batt_psy); + if (rc < 0) + { + dev_err(&client->dev, "Cannot register batt_psy, rc = %d\n", rc); + return rc; + } + + INIT_WORK(&chip->usb_detect_work, bq25601_usb_detect_work_func); + + rc = of_property_read_u32(chip->dev->of_node, "ti,chg-vbat-div", &value); + if (rc == 0) + { + chip->vbat_div = value; + } + else + { + chip->vbat_div = 1; + dev_err(&client->dev, "Failed to get battery voltage division, rc = %d\n", rc); + } + + chip->charge_gpio = of_get_named_gpio(chip->dev->of_node, "ti,chg-en-gpio", 0); + dev_info(&client->dev, "charge gpio: %d\n", chip->charge_gpio); + if (gpio_is_valid(chip->charge_gpio)) + { + rc = gpio_request(chip->charge_gpio, "ti,chg-en-gpio"); + if (rc) + { + pr_err("charge enable gpio request failed, rc = %d\n", rc); + goto fail_charge_gpio_init; + } + } + else + { + goto fail_charge_gpio_init; + } + + chip->irq_gpio = of_get_named_gpio_flags(chip->dev->of_node, "ti,irq-gpio", 0, NULL); + dev_info(&client->dev, "irq gpio: %d\n", chip->irq_gpio); + if (gpio_is_valid(chip->irq_gpio)) + { + rc = gpio_request(chip->irq_gpio, "bq25601_irq"); + if (rc) + { + dev_err(&client->dev, "irq gpio request failed, rc = %d", rc); + goto fail_irq_gpio_init; + } + rc = gpio_direction_input(chip->irq_gpio); + if (rc) + { + dev_err(&client->dev, "set direction for irq gpio(%d) failed\n", chip->irq_gpio); + goto fail_irq_gpio_init; + } + irq = gpio_to_irq(chip->irq_gpio); + if (irq < 0) + { + dev_err(&client->dev, "Invalid irq_gpio irq = %d\n", irq); + goto fail_irq_gpio_init; + } + rc = devm_request_threaded_irq(&client->dev, irq, NULL, bq25601_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "bq25601_irq", chip); + if (rc) + { + dev_err(&client->dev, "Failed allocate irq = %d request, rc = %d\n", irq, rc); + goto fail_irq_gpio_init; + } + enable_irq_wake(irq); + dev_info(&client->dev, "set irq success\n"); + } + else + { + goto fail_irq_gpio_init; + } + + rc = bq25601_set_usb_default_status(chip); + if (rc) + { + goto fail_enable_charge; + } + + // init usb status + schedule_work(&chip->usb_detect_work); + + dev_info(&client->dev, "BQ25601 charger successfully probed\n"); + return 0; + +fail_enable_charge: +fail_irq_gpio_init: + if (gpio_is_valid(chip->irq_gpio)) + gpio_free(chip->irq_gpio); +fail_charge_gpio_init: + if (gpio_is_valid(chip->charge_gpio)) + gpio_free(chip->charge_gpio); + power_supply_unregister(&chip->batt_psy); + return rc; +} + +static int bq25601_charger_remove(struct i2c_client *client) +{ + struct bq25601_charger *chip = i2c_get_clientdata(client); + + power_supply_unregister(&chip->batt_psy); + if (gpio_is_valid(chip->charge_gpio)) + gpio_free(chip->charge_gpio); + if (gpio_is_valid(chip->irq_gpio)) + gpio_free(chip->irq_gpio); + mutex_destroy(&chip->irq_lock); + + return 0; +} + +static int bq25601_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + dev_info(&client->dev, "BQ25601 charger suspend\n"); + return 0; +} + +static int bq25601_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + dev_info(&client->dev, "BQ25601 charger resume\n"); + return 0; +} + +static const struct dev_pm_ops bq25601_pm_ops = { + .suspend = bq25601_suspend, + .resume = bq25601_resume, +}; + +static struct of_device_id bq25601_match_table[] = { + { .compatible = "ti,sgm41513-charger",}, + { .compatible = "ti,bq25601-charger",}, +}; + +static const struct i2c_device_id bq25601_charger_id[] = { + {"sgm41513-charger", 0}, + {"bq25601-charger", 1}, +}; +MODULE_DEVICE_TABLE(i2c, bq25601_charger_id); + +static struct i2c_driver bq25601_charger_driver = { + .driver = { + .name = "bq25601-charger", + .owner = THIS_MODULE, + .of_match_table = bq25601_match_table, + .pm = &bq25601_pm_ops, + }, + .probe = bq25601_charger_probe, + .remove = bq25601_charger_remove, + .id_table = bq25601_charger_id, +}; + +module_i2c_driver(bq25601_charger_driver); + +MODULE_DESCRIPTION("BQ25601 Charger"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("i2c:bq25601-charger"); diff --git a/kernel/include/linux/mtd/nand.h b/kernel/include/linux/mtd/nand.h index 119d3cc37..fefa0e4c2 100755 --- a/kernel/include/linux/mtd/nand.h +++ b/kernel/include/linux/mtd/nand.h @@ -725,6 +725,7 @@ struct nand_chip { #define NAND_MFR_INTEL 0x89 #define NAND_MFR_WINBOND 0xef #define NAND_MFR_ESMT 0xc8 +#define NAND_MFR_ESMT2 0x2c /* The maximum expected count of bytes in the NAND ID sequence */ #define NAND_MAX_ID_LEN 8 diff --git a/kernel/include/linux/netdevice.h b/kernel/include/linux/netdevice.h old mode 100644 new mode 100755 index 8f32a5301..dd9a2f96e --- a/kernel/include/linux/netdevice.h +++ b/kernel/include/linux/netdevice.h @@ -1220,6 +1220,7 @@ enum netdev_priv_flags { IFF_LIVE_ADDR_CHANGE = 1<<20, IFF_MACVLAN = 1<<21, IFF_XMIT_DST_RELEASE_PERM = 1<<22, + IFF_WAN_DEV = 1<<23, }; #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN @@ -1245,6 +1246,7 @@ enum netdev_priv_flags { #define IFF_LIVE_ADDR_CHANGE IFF_LIVE_ADDR_CHANGE #define IFF_MACVLAN IFF_MACVLAN #define IFF_XMIT_DST_RELEASE_PERM IFF_XMIT_DST_RELEASE_PERM +#define IFF_WAN_DEV IFF_WAN_DEV /** * struct net_device - The DEVICE structure. diff --git a/kernel/net/core/dev.c b/kernel/net/core/dev.c old mode 100644 new mode 100755 index a63ce1729..ac30a3323 --- a/kernel/net/core/dev.c +++ b/kernel/net/core/dev.c @@ -175,6 +175,13 @@ static int call_netdevice_notifiers_info(unsigned long val, DEFINE_RWLOCK(dev_base_lock); EXPORT_SYMBOL(dev_base_lock); +//[zhangguosong start] 2018-05-07 +/* +*brief 对所有æ¥è‡ªWANçš„æµé‡å‡è®¾ç½®æ•°æ®åŒ…çš„mark字段 +*/ +#define MASK_FOR_WAN2LAN (0x00008000) +//[zhangguosong end] + /* protects napi_hash addition/deletion and napi_gen_id */ static DEFINE_SPINLOCK(napi_hash_lock); @@ -3412,6 +3419,14 @@ static int netif_rx_internal(struct sk_buff *skb) net_timestamp_check(netdev_tstamp_prequeue, skb); trace_netif_rx(skb); + + //[zhangguosong start] 2018-05-07 for mark downstream (traffic from wan interface) + if (skb->dev && (skb->dev->priv_flags & IFF_WAN_DEV)) + { + skb->mark |= MASK_FOR_WAN2LAN; + } + //[zhangguosong end] + #ifdef CONFIG_RPS WARN_ONCE(skb_cloned(skb), "Cloned packet from dev %s\n", skb->dev->name); @@ -5621,6 +5636,7 @@ void dev_set_rx_mode(struct net_device *dev) netif_addr_unlock_bh(dev); } + /** * dev_get_flags - get flags reported to userspace * @dev: device diff --git a/kernel/net/core/dev_ioctl.c b/kernel/net/core/dev_ioctl.c old mode 100644 new mode 100755 index 72e899a3e..16058f613 --- a/kernel/net/core/dev_ioctl.c +++ b/kernel/net/core/dev_ioctl.c @@ -17,6 +17,35 @@ * match. --pb */ +#define SIOCSIFPRIVFLAGS 0x89ba //set device priv_flags +#define SIOCGIFPRIVFLAGS 0x89bb //get device priv_flags + +//[zhangguosong start] 2018-06-20 +static unsigned int dev_get_privflags(const struct net_device *dev) +{ + return dev->priv_flags; +} + +static unsigned int dev_change_privflags(struct net_device *dev, unsigned int flags) +{ + int old_flags = dev->priv_flags; + + if ((old_flags ^ flags) & IFF_WAN_DEV) + { + if (old_flags & IFF_WAN_DEV) + { + dev->priv_flags &= ~IFF_WAN_DEV; + } + else + { + dev->priv_flags |= IFF_WAN_DEV; + } + } + + return 0; +} +//[zhangguosong end] + static int dev_ifname(struct net *net, struct ifreq __user *arg) { struct ifreq ifr; @@ -115,6 +144,7 @@ static int dev_ifconf(struct net *net, char __user *arg) return copy_to_user(arg, &ifc, sizeof(struct ifconf)) ? -EFAULT : 0; } +#define ifr_iflags ifr_ifru.ifru_ivalue /* add by zhangguosong, for traffic control module */ /* * Perform the SIOCxIFxxx calls, inside rcu_read_lock() */ @@ -127,6 +157,10 @@ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cm return -ENODEV; switch (cmd) { + //[zhangguosong start] + case SIOCGIFPRIVFLAGS: /* Get interface priv_flags */ + ifr->ifr_iflags = dev_get_privflags(dev); + //[zhangguosng end] case SIOCGIFFLAGS: /* Get interface flags */ ifr->ifr_flags = (short) dev_get_flags(dev); return 0; @@ -248,6 +282,10 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) ops = dev->netdev_ops; switch (cmd) { + //[zhangguosong start] 2018-06-20 + case SIOCSIFPRIVFLAGS: + return dev_change_privflags(dev, ifr->ifr_iflags); + //[zhangguosong end] case SIOCSIFFLAGS: /* Set interface flags */ return dev_change_flags(dev, ifr->ifr_flags); @@ -427,6 +465,9 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) * - atomic and do not require locking. * - return a value */ + //[zhangguosong start] + case SIOCGIFPRIVFLAGS: + //[zhangguosong end] case SIOCGIFFLAGS: case SIOCGIFMETRIC: case SIOCGIFMTU: @@ -503,6 +544,9 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) * - require strict serialization. * - do not return a value */ + //[zhangguosong start] 2018-06-20 + case SIOCSIFPRIVFLAGS: + //[zhangguosong end] case SIOCSIFFLAGS: case SIOCSIFMETRIC: case SIOCSIFMTU: diff --git a/oe-core/build/conf/bblayers.conf b/oe-core/build/conf/bblayers.conf old mode 100644 new mode 100755 index 746912f8b..b55549e88 --- a/oe-core/build/conf/bblayers.conf +++ b/oe-core/build/conf/bblayers.conf @@ -7,4 +7,4 @@ export WORKSPACE := "${@os.path.abspath(os.path.join(os.path.dirname(bb.data.get BBPATH = "${TOPDIR}" BBFILES ?= "" -BBLAYERS = "/home/mobile/Work/mifi/M7350v5_en_gpl/M7350v5_en_gpl/oe-core/meta-tp /home/mobile/Work/mifi/M7350v5_en_gpl/M7350v5_en_gpl/oe-core/meta-msm /home/mobile/Work/mifi/M7350v5_en_gpl/M7350v5_en_gpl/oe-core/meta" +BBLAYERS = "/home/bba/projects/dev/M7350v7/M7350v7_en_gpl/oe-core/meta-tp /home/bba/projects/dev/M7350v7/M7350v7_en_gpl/oe-core/meta-msm /home/bba/projects/dev/M7350v7/M7350v7_en_gpl/oe-core/meta" diff --git a/oe-core/build/conf/sanity_info b/oe-core/build/conf/sanity_info new file mode 100755 index 000000000..74e525de0 --- /dev/null +++ b/oe-core/build/conf/sanity_info @@ -0,0 +1,3 @@ +SANITY_VERSION 1 +TMPDIR /home/bba/projects/dev/M7350v7/M7350v7_en_gpl/oe-core/build/tmp-glibc +SSTATE_DIR /home/bba/projects/dev/M7350v7/M7350v7_en_gpl/oe-core/build/sstate-cache diff --git a/oe-core/build/conf/templateconf.cfg b/oe-core/build/conf/templateconf.cfg old mode 100644 new mode 100755 diff --git a/oe-core/build/conf/tp_set_bb_env.sh b/oe-core/build/conf/tp_set_bb_env.sh old mode 100644 new mode 100755 index 028f60600..0b473f6d5 --- a/oe-core/build/conf/tp_set_bb_env.sh +++ b/oe-core/build/conf/tp_set_bb_env.sh @@ -1,4 +1,4 @@ -PRODUCT_CHOICES=(m7350v5) +PRODUCT_CHOICES=(m7350v6) BUILD_TYPE_CHOICES=(release debug) export TARGET_BOARD=mdm9607 @@ -200,6 +200,8 @@ function copy_kernel_dts_and_defconfig() local PRODUCT_KERNEL_DEFCONFIG_FILE=tp-product/${TARGET_PRODUCT}/kernel/mdm9607_defconfig local PRODUCT_KERNEL_PATCH_FILE=tp-product/${TARGET_PRODUCT}/kernel/kernel_diff.patch local DEBUG_DEFCONFIG_FILE=${WS}/kernel/arch/arm/configs/mdm9607_debug_defconfig + local PRODUCT_QCN_FILE=${WS}/tp-proprietary/qcn/factory.xqcn + local PRODUCT_QCN_DIR=${WS}/tp-proprietary/qcn/${TARGET_PRODUCT} :<> ${WS}/kernel/arch/arm/configs/mdm9607_defconfig fi + + cp ${PRODUCT_QCN_DIR}/*.xqcn ${PRODUCT_QCN_FILE} + cp ${WS}/tp-product/${TARGET_PRODUCT}/config/product ${WS}/tp-product/product +} + +function create_firmware_id() +{ + local PRODUCT_FILE=${WS}/tp-product/${TARGET_PRODUCT}/config/product + local PRODUCT_FILE_TMP=${WS}/tp-product/product_tmp + + echo "---------------------------------------------------------" + echo " generate firmware_id" + echo "---------------------------------------------------------" + + ${WS}/oe-core/build/conf/gen_firmware_id.sh ${PRODUCT_FILE} ${PRODUCT_FILE_TMP} + cat ${PRODUCT_FILE} } function choosecombo() @@ -270,6 +288,8 @@ function rpp () { function build() { + create_firmware_id + if check_config then echo "Your environment is set, please check if it is right." diff --git a/oe-core/build/downloads/curl-7.30.0.tar.bz2 b/oe-core/build/downloads/curl-7.30.0.tar.bz2 new file mode 100644 index 000000000..bb0be75cf Binary files /dev/null and b/oe-core/build/downloads/curl-7.30.0.tar.bz2 differ diff --git a/oe-core/build/downloads/curl-7.30.0.tar.bz2.done b/oe-core/build/downloads/curl-7.30.0.tar.bz2.done new file mode 100644 index 000000000..e69de29bb diff --git a/oe-core/build/downloads/dnsmasq-2.73.tar.gz b/oe-core/build/downloads/dnsmasq-2.73.tar.gz new file mode 100644 index 000000000..f0fcba243 Binary files /dev/null and b/oe-core/build/downloads/dnsmasq-2.73.tar.gz differ diff --git a/oe-core/build/downloads/dnsmasq-2.73.tar.gz.done b/oe-core/build/downloads/dnsmasq-2.73.tar.gz.done new file mode 100644 index 000000000..e69de29bb diff --git a/oe-core/build/downloads/dnsmasq-2.78.tar.gz b/oe-core/build/downloads/dnsmasq-2.78.tar.gz new file mode 100644 index 000000000..96dc0dd60 Binary files /dev/null and b/oe-core/build/downloads/dnsmasq-2.78.tar.gz differ diff --git a/oe-core/build/downloads/dnsmasq-2.78.tar.gz.done b/oe-core/build/downloads/dnsmasq-2.78.tar.gz.done new file mode 100644 index 000000000..e69de29bb diff --git a/oe-core/build/downloads/libghttp_1.0.9-17.patch.done b/oe-core/build/downloads/libghttp_1.0.9-17.patch.done new file mode 100644 index 000000000..e69de29bb diff --git a/oe-core/build/downloads/libghttp_1.0.9-18.patch.done b/oe-core/build/downloads/libghttp_1.0.9-18.patch.done new file mode 100644 index 000000000..e69de29bb diff --git a/oe-core/build/downloads/libghttp_1.0.9.orig.tar.gz b/oe-core/build/downloads/libghttp_1.0.9.orig.tar.gz new file mode 100755 index 000000000..8c45bc33b Binary files /dev/null and b/oe-core/build/downloads/libghttp_1.0.9.orig.tar.gz differ diff --git a/oe-core/build/downloads/libghttp_1.0.9.orig.tar.gz.done b/oe-core/build/downloads/libghttp_1.0.9.orig.tar.gz.done new file mode 100644 index 000000000..e69de29bb diff --git a/oe-core/build/downloads/libupnp.tar.bz2 b/oe-core/build/downloads/libupnp.tar.bz2 new file mode 100644 index 000000000..73c5fe9a6 Binary files /dev/null and b/oe-core/build/downloads/libupnp.tar.bz2 differ diff --git a/oe-core/build/downloads/libupnp.tar.bz2.done b/oe-core/build/downloads/libupnp.tar.bz2.done new file mode 100644 index 000000000..e69de29bb diff --git a/oe-core/build/downloads/upnpd.tar.bz2 b/oe-core/build/downloads/upnpd.tar.bz2 new file mode 100644 index 000000000..0292b8289 Binary files /dev/null and b/oe-core/build/downloads/upnpd.tar.bz2 differ diff --git a/oe-core/build/downloads/upnpd.tar.bz2.done b/oe-core/build/downloads/upnpd.tar.bz2.done new file mode 100644 index 000000000..e69de29bb diff --git a/oe-core/meta-msm/recipes/lighttpd/files/lighttpd.conf b/oe-core/meta-msm/recipes/lighttpd/files/lighttpd.conf index 0f68991ed..8cce27d70 100755 --- a/oe-core/meta-msm/recipes/lighttpd/files/lighttpd.conf +++ b/oe-core/meta-msm/recipes/lighttpd/files/lighttpd.conf @@ -12,6 +12,7 @@ # - saves some time # - saves memory server.modules = ( + "mod_expire", # "mod_rewrite", "mod_redirect", # "mod_alias", @@ -20,7 +21,7 @@ server.modules = ( # "mod_trigger_b4_dl", # "mod_auth", # "mod_status", -# "mod_setenv", + "mod_setenv", # "mod_fastcgi", # "mod_proxy", # "mod_simple_vhost", @@ -30,7 +31,6 @@ server.modules = ( # "mod_compress", # "mod_ssi", # "mod_usertrack", -# "mod_expire", # "mod_secdownload", # "mod_rrdtool", # "mod_webdav", @@ -119,6 +119,9 @@ mimetype.assign = ( #accesslog.filename = "/www/access.log" #debug.log-request-handling = "enable" +###[pudongfang] add ipv6 support +$SERVER["socket"] == "[::]:80" {} + $HTTP["url"] =~ "/" { server.document-root = "/WEBSERVER/www/" #server.errorlog = "/www/lighttpd.error.log" @@ -154,6 +157,16 @@ $HTTP["url"] == "/" { } } } +$HTTP["url"] =~ "/*.html" { + setenv.add-response-header = ( "Cache-Control" => "no-cache" ) +} +$HTTP["url"] =~ "/*.css" { + expire.url = ( "" => "access 1 hours") +} +$HTTP["url"] =~ "/*.js" { + setenv.add-response-header = ( "Cache-Control" => "no-cache" ) +} +expire.url = ( "/images/" => "access 1 hours") ## # which extensions should not be handle via static-file transfer diff --git a/oe-core/meta-msm/recipes/lighttpd/lighttpd_1.4.35.bbappend b/oe-core/meta-msm/recipes/lighttpd/lighttpd_1.4.35.bbappend index 15cb70f9c..11c5aa034 100755 --- a/oe-core/meta-msm/recipes/lighttpd/lighttpd_1.4.35.bbappend +++ b/oe-core/meta-msm/recipes/lighttpd/lighttpd_1.4.35.bbappend @@ -15,6 +15,8 @@ RDEPENDS_${PN} += " \ lighttpd-module-auth \ lighttpd-module-redirect \ lighttpd-module-evasive \ + lighttpd-module-expire \ + lighttpd-module-setenv \ " EXTRA_OECONF += " \ --with-openssl \ diff --git a/oe-core/meta-msm/recipes/linux-quic/linux-quic_git.bb b/oe-core/meta-msm/recipes/linux-quic/linux-quic_git.bb old mode 100644 new mode 100755 diff --git a/oe-core/meta-msm/recipes/sfe/sfe_git.bb b/oe-core/meta-msm/recipes/sfe/sfe_git.bb index ab9215f49..f6d97db89 100644 --- a/oe-core/meta-msm/recipes/sfe/sfe_git.bb +++ b/oe-core/meta-msm/recipes/sfe/sfe_git.bb @@ -11,6 +11,8 @@ S = "${WORKDIR}/shortcut-fe/shortcut-fe" FILES_${PN}="/etc/init.d/start_shortcut_fe_le" +EXTRA_OEMAKE += "${@base_conditional('TP_FEATURE_CLOUD', 'y', 'EXTRA_CFLAGS+=-DTP_FEATURE_CLOUD', '', d)}" + do_install() { module_do_install install -d ${D}${sysconfdir}/init.d diff --git a/oe-core/meta-msm/recipes/sigma-dut/sigma-dut_git.bb b/oe-core/meta-msm/recipes/sigma-dut/sigma-dut_git.bb deleted file mode 100644 index 5cd3a10b2..000000000 --- a/oe-core/meta-msm/recipes/sigma-dut/sigma-dut_git.bb +++ /dev/null @@ -1,16 +0,0 @@ -inherit autotools qcommon - -DESCRIPTION = "WFA certification testing tool for QCA devices" -HOMEPAGE = "https://github.com/qca/sigma-dut" -LICENSE = "BSD-3-Clause" -LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/${LICENSE};md5=550794465ba0ec5312d6919e203a55f9" - -PR = "r0" - -SRC_DIR = "${WORKSPACE}/wlan/utils/sigma-dut/" - -S = "${WORKDIR}/wlan/utils/sigma-dut" - -do_install() { - make install DESTDIR=${D} BINDIR=${sbindir}/ -} diff --git a/oe-core/meta-tp/classes/tp-link-common.bbclass b/oe-core/meta-tp/classes/tp-link-common.bbclass index 664af337e..27c0fab82 100755 --- a/oe-core/meta-tp/classes/tp-link-common.bbclass +++ b/oe-core/meta-tp/classes/tp-link-common.bbclass @@ -10,8 +10,8 @@ FILESPATH =+ "${WORKSPACE}:" SRC_URI = "file://${@d.getVar('SRC_DIR', True).replace('${WORKSPACE}/', '')}" PV = "git-${GITSHA}" -LICENSE = "TPLink-Technologies-Inc.-Proprietary" -LIC_FILES_CHKSUM = "file://${COREBASE}/meta-tp/files/tp-licenses/${LICENSE};md5=abd123e5a2e897447f2c177f6053913c" +LICENSE = "TPLink-Corporation-Limited.-Proprietary" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta-tp/files/tp-licenses/${LICENSE};md5=414f2f16c6966d51db8a805b26f9a907" TP-PROPRIETARY = "${WORKSPACE}/tp-proprietary" TP-OPENSOURCE = "${WORKSPACE}/tp-opensource" diff --git a/oe-core/meta-tp/conf/layer.conf b/oe-core/meta-tp/conf/layer.conf index 2f411f5b5..0cd324dd0 100755 --- a/oe-core/meta-tp/conf/layer.conf +++ b/oe-core/meta-tp/conf/layer.conf @@ -5,4 +5,4 @@ BBFILE_PRIORITY_tp = "20" BBFILE_PATTERN_tp := "^${LAYERDIR}/" #LICENSE_PATH += "${LAYERDIR}/files/tp-licenses" LICENSE_DIR .= "${LAYERDIR}/files/tp-licenses" -SPDXLICENSEMAP[TPLink-Technologies-Inc.-Proprietary] = "TPLink-Technologies-Inc.-Proprietary" +SPDXLICENSEMAP[TPLink-Corporation-Limited.-Proprietary] = "TPLink-Corporation-Limited.-Proprietary" diff --git a/oe-core/meta-tp/files/tp-licenses/TPLink-Corporation-Limited.-Proprietary b/oe-core/meta-tp/files/tp-licenses/TPLink-Corporation-Limited.-Proprietary new file mode 100755 index 000000000..84656a27b --- /dev/null +++ b/oe-core/meta-tp/files/tp-licenses/TPLink-Corporation-Limited.-Proprietary @@ -0,0 +1,2 @@ +Copyright (c) 2020 TPLINK CORPORATION LIMITED. All Rights Reserved. +TP-Link Corporation Limited Proprietary and Confidential. diff --git a/oe-core/meta-tp/files/tp-licenses/TPLink-Technologies-Inc.-Proprietary b/oe-core/meta-tp/files/tp-licenses/TPLink-Technologies-Inc.-Proprietary deleted file mode 100755 index 35b7ce313..000000000 --- a/oe-core/meta-tp/files/tp-licenses/TPLink-Technologies-Inc.-Proprietary +++ /dev/null @@ -1,2 +0,0 @@ -Copyright (c) 2015 TPLINK TECHNOLOGIES CO., LTD. All Rights Reserved. -TP-Link Technologies Proprietary and Confidential. diff --git a/oe-core/meta-tp/recipes/uci/files/gdpr.patch b/oe-core/meta-tp/recipes/uci/files/gdpr.patch new file mode 100644 index 000000000..d50ee6018 --- /dev/null +++ b/oe-core/meta-tp/recipes/uci/files/gdpr.patch @@ -0,0 +1,1577 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index f9decc6..fe3e0c4 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -8,15 +8,31 @@ ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -g3 -I. -DUCI_PREFIX="${CMAKE_INST + OPTION(UCI_DEBUG "debugging support" OFF) + OPTION(UCI_DEBUG_TYPECAST "typecast debugging support" OFF) + OPTION(BUILD_LUA "build Lua binding" ON) ++#OPTION(TP_FEATURE_GDPR "GDPR support" ON) ++OPTION(DEBUG "debug support" OFF) + + CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/uci_config.h.in ${CMAKE_SOURCE_DIR}/uci_config.h ) + + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +-SET(LIB_SOURCES libuci.c file.c util.c delta.c parse.c blob.c) ++#IF(TP_FEATURE_GDPR) ++# message("add TP_FEATURE_GDPR") ++# add_definitions("-DTP_FEATURE_GDPR") ++#ELSE() ++# message("GDPR not support") ++#ENDIF(TP_FEATURE_GDPR) ++ ++IF(DEBUG) ++ message("add DEBUG") ++ add_definitions("-DDEBUG") ++ELSE() ++ message(" DEBUG not support") ++ENDIF(DEBUG) ++ ++SET(LIB_SOURCES libuci.c file.c util.c delta.c parse.c blob.c gdpr_aes_interface.c base64.c) + + ADD_LIBRARY(uci SHARED ${LIB_SOURCES}) +-TARGET_LINK_LIBRARIES(uci ubox) ++TARGET_LINK_LIBRARIES(uci ubox crypto) + SET_TARGET_PROPERTIES(uci PROPERTIES OUTPUT_NAME uci) + + ADD_EXECUTABLE(cli cli.c) +diff --git a/base64.c b/base64.c +new file mode 100644 +index 0000000..16cda8e +--- /dev/null ++++ b/base64.c +@@ -0,0 +1,168 @@ ++/* ++ * This file is part of libESMTP, a library for submission of RFC 2822 ++ * formatted electronic mail messages using the SMTP protocol described ++ * in RFC 2821. ++ * ++ * Copyright (C) 2001,2002 Brian Stafford ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/*#ifdef HAVE_CONFIG_H ++#include ++#endif*/ ++ ++#include ++ ++/* Routines to encode and decode base64 text. ++ */ ++#include ++#include ++#include "base64.h" ++ ++/* RFC 2045 section 6.8 */ ++ ++static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ "abcdefghijklmnopqrstuvwxyz" ++ "0123456789" ++ "+/"; ++ ++static const char index_64[128] = ++ { ++ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ++ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ++ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, ++ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, ++ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ++ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, ++ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, ++ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, ++ }; ++ ++/* Decode srclen bytes of base64 data contained in src and put the result ++ in dst. Since the destination buffer may contain arbitrary binary ++ data and it is not necessarily a string, there is no \0 byte at the ++ end of the decoded data. */ ++int ++b64_decode (void *dst, int dstlen, const char *src, int srclen) ++{ ++ const unsigned char *p, *q; ++ unsigned char *t; ++ int c1, c2; ++ ++ assert (dst != NULL && dstlen > 0); ++ ++ if (src == NULL) ++ return 0; ++ ++ if (srclen < 0) ++ srclen = strlen (src); ++ ++ /* Remove leading and trailing white space */ ++ for (p = (const unsigned char *) src; ++ srclen > 0 && isspace (*p); ++ p++, srclen--) ++ ; ++ for (q = p + srclen - 1; q >= p && isspace (*q); q--, srclen--) ++ ; ++ ++ /* Length MUST be a multiple of 4 */ ++ if (srclen % 4 != 0) ++ return -1; ++ ++ /* Destination buffer length must be sufficient */ ++ if (srclen / 4 * 3 + 1 > dstlen) ++ return -1; ++ ++ t = dst; ++ while (srclen > 0) ++ { ++ srclen -= 4; ++ if (*p >= 128 || (c1 = index_64[*p++]) == -1) ++ return -1; ++ if (*p >= 128 || (c2 = index_64[*p++]) == -1) ++ return -1; ++ *t++ = (c1 << 2) | ((c2 & 0x30) >> 4); ++ ++ if (p[0] == '=' && p[1] == '=') ++ break; ++ if (*p >= 128 || (c1 = index_64[*p++]) == -1) ++ return -1; ++ *t++ = ((c2 & 0x0f) << 4) | ((c1 & 0x3c) >> 2); ++ ++ if (p[0] == '=') ++ break; ++ if (*p >= 128 || (c2 = index_64[*p++]) == -1) ++ return -1; ++ *t++ = ((c1 & 0x03) << 6) | c2; ++ } ++ ++ return t - (unsigned char *) dst; ++} ++ ++/* Return a pointer to a base 64 encoded string. The input data is ++ arbitrary binary data, the output is a \0 terminated string. ++ src and dst may not share the same buffer. */ ++int ++b64_encode (unsigned char *dst, int dstlen, const void *src, int srclen) ++{ ++ char *to = (char *)dst; ++ const unsigned char *from; ++ unsigned char c1, c2; ++ int dst_needed; ++ ++ assert (dst != NULL && dstlen > 0 && srclen >= 0); ++ ++ if (src == NULL) ++ return 0; ++ ++ dst_needed = (srclen + 2) / 3; ++ dst_needed *= 4; ++ if (dstlen < dst_needed + 1) ++ return -1; ++ ++ from = src; ++ while (srclen > 0) ++ { ++ c1 = *from++; srclen--; ++ *to++ = base64[c1 >> 2]; ++ c1 = (c1 & 0x03) << 4; ++ if (srclen <= 0) ++ { ++ *to++ = base64[c1]; ++ *to++ = '='; ++ *to++ = '='; ++ break; ++ } ++ c2 = *from++; srclen--; ++ c1 |= (c2 >> 4) & 0x0f; ++ *to++ = base64[c1]; ++ c1 = (c2 & 0x0f) << 2; ++ if (srclen <= 0) ++ { ++ *to++ = base64[c1]; ++ *to++ = '='; ++ break; ++ } ++ c2 = *from++; srclen--; ++ c1 |= (c2 >> 6) & 0x03; ++ *to++ = base64[c1]; ++ *to++ = base64[c2 & 0x3f]; ++ } ++ *to = '\0'; ++ return to - (char *)dst; ++} ++ ++ +diff --git a/base64.h b/base64.h +new file mode 100644 +index 0000000..f9223bb +--- /dev/null ++++ b/base64.h +@@ -0,0 +1,29 @@ ++#ifndef _base64_h ++#define _base64_h ++/* ++ * This file is part of libESMTP, a library for submission of RFC 2822 ++ * formatted electronic mail messages using the SMTP protocol described ++ * in RFC 2821. ++ * ++ * Copyright (C) 2001,2002 Brian Stafford ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++int b64_decode (void *dst, int dstlen, const char *src, int srclen); ++int b64_encode (unsigned char *dst, int dstlen, const void *src, int srclen); ++ ++#endif ++ +diff --git a/file.c b/file.c +index 36bfdda..c623d8d 100644 +--- a/file.c ++++ b/file.c +@@ -31,6 +31,7 @@ + + #include "uci.h" + #include "uci_internal.h" ++#include "gdpr_aes_interface.h" + + #define LINEBUF 32 + #define LINEBUF_MAX 4096 +@@ -445,7 +446,21 @@ static void uci_parse_option(struct uci_context *ctx, char **str, bool list) + if (e) + ptr.o = uci_to_option(e); + ptr.option = name; +- ptr.value = value; ++ ++#ifdef TP_FEATURE_GDPR ++ char decrypt_data_buf[LINEBUF_MAX]; ++ int decrypt_data_buf_len = LINEBUF_MAX; ++ int ret = 0; ++ ret = uci_decrypt(decrypt_data_buf, decrypt_data_buf_len,value, strlen(value)); ++ if( ret != 0) ++ { ++ UCI_THROW(ctx, UCI_ERR_DECRYPT); ++ } ++ ptr.value = decrypt_data_buf; ++#else ++ ptr.value = value; ++#endif ++ + + ctx->internal = !pctx->merge; + if (list) +@@ -577,7 +592,20 @@ static void uci_export_package(struct uci_package *p, FILE *stream, bool header) + switch(opt->type) { + case UCI_TYPE_STRING: + fprintf(stream, "\toption %s", uci_escape(ctx, opt->e.name)); ++ ++#ifdef TP_FEATURE_GDPR ++ char encry_data_buf[LINEBUF_MAX]; ++ int ret = 0; ++ ret = uci_encrypt( opt->v.string, strlen( opt->v.string), encry_data_buf, LINEBUF_MAX); ++ if( ret != 0 ) ++ { ++ UCI_THROW(ctx, UCI_ERR_DECRYPT); ++ } ++ fprintf(stream, " '%s'\n", uci_escape(ctx, encry_data_buf)); ++#else + fprintf(stream, " '%s'\n", uci_escape(ctx, opt->v.string)); ++#endif ++ + break; + case UCI_TYPE_LIST: + uci_foreach_element(&opt->v.list, i) { +diff --git a/gdpr_aes_interface.c b/gdpr_aes_interface.c +new file mode 100755 +index 0000000..a470c38 +--- /dev/null ++++ b/gdpr_aes_interface.c +@@ -0,0 +1,972 @@ ++/* Copyright(c) 2009-2018 Shenzhen TP-LINK Technologies Co.Ltd. ++ * ++ * file gdpr_aes_interface.c ++ * brief AES handle ++ * details lcrypto ++ * ++ * author Li Qiang ++ * version 1.0.0 ++ * date 26Apr18 ++ * ++ * warning ++ * ++ * history \arg 1.0.0, 25May18, Li Qiang, Create the file. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "gdpr_aes_interface.h" ++#include "base64.h" ++#include "gdpr_log.h" ++ ++/**************************************************************************************************/ ++/* DEFINES */ ++/**************************************************************************************************/ ++#define HTTP_ERROR -1 ++#define HTTP_OK 0 ++ ++#define MAX_BUF_SIZE 600 ++#define MARK_LEN 1 ++ ++/**************************************************************************************************/ ++/* TYPES */ ++/**************************************************************************************************/ ++ ++/**************************************************************************************************/ ++/* VARIABLES */ ++/**************************************************************************************************/ ++static unsigned char *l_pKey = NULL; ++static unsigned char *l_pV = NULL; ++ ++unsigned char *l_key = (unsigned char *)"1527156067762978"; ++unsigned char *l_v = (unsigned char *)"1527156067762421"; ++ ++unsigned char gmark[MARK_LEN+1] = {0x03,0x0}; ++ ++/**************************************************************************************************/ ++/* FUNCTIONS */ ++/**************************************************************************************************/ ++/* ++**Function: unsigned char *real_padding_buf(unsigned char *buf,int size, int *final_size) ++**Des: padding buf ++**param[in] buf - enough buffer padding the buffer ++**param[in] size ++**param[in] final_size ++** ++**ret the after buff padding ++*/ ++void real_padding_buf(unsigned char *buf, int size, int *final_size) ++{ ++ //unsigned char * ret = NULL; ++ int pidding_size = AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE); ++ int i; ++ ++ if(buf == NULL || final_size == NULL) ++ { ++ GDPR_DEBUG("buf or final_size NULL !!!\n"); ++ return ; ++ } ++ *final_size = size + pidding_size; ++ ++ if (pidding_size!=0) { ++ for (i =size;i < (size+pidding_size); i++ ) { ++ buf[i] = pidding_size; ++ } ++ } ++} ++ ++unsigned char *padding_buf(unsigned char *buf,int size, int *final_size) ++{ ++ unsigned char *ret = NULL; ++ int pidding_size = AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE); ++ int i; ++ ++ *final_size = size + pidding_size; ++ ret = (unsigned char *)malloc(size+pidding_size); ++ memcpy( ret, buf, size); ++ ++ if (pidding_size!=0) { ++ for (i =size;i < (size+pidding_size); i++ ) { ++ ret[i] = pidding_size; ++ } ++ } ++ ++ return ret; ++} ++ ++int remove_padding(unsigned char *buff, int dataLen, int blockSize) ++{ ++ int paddingLen = 0; ++ ++ if (NULL == buff || 0 == dataLen || 0 == blockSize) ++ { ++ GDPR_DEBUG("remove padding fail: input params\n"); ++ return -1; ++ } ++ ++ paddingLen = buff[dataLen - 1]; ++ ++ if (paddingLen > blockSize || paddingLen > dataLen) ++ { ++ GDPR_DEBUG("remove padding fail. paddingLen: %d, dataLen: %d, blockSize: %d\n", ++ paddingLen, dataLen, blockSize); ++ return -1; ++ } ++ ++ return paddingLen; ++} ++ ++void printf_buff(unsigned char *buff,int size) ++{ ++ int i = 0; ++ ++ for (i=0;i ITEM_LEN) ++ { ++ ++ lenpart = ITEM_LEN; ++ ret = aes_cbc_encrypt_intface(pIndex, pOut, &lenpart, ptmpKey , tmpIv, 1); ++ if(ret != HTTP_OK) ++ { ++ GDPR_DEBUG("aes_cbc_encrypt_intface_bypart aes_cbc_encrypt_intface Error "); ++ return HTTP_ERROR; ++ } ++ ++ memcpy(pIndex, pOut, lenpart); ++ pIndex += ITEM_LEN; ++ memset(encrypt_buf, 0, ITEM_LEN + AES_BLOCK_SIZE + 1); ++ enlen -= ITEM_LEN; ++ } ++ ++ memset(encrypt_buf, 0, ITEM_LEN + AES_BLOCK_SIZE + 1); ++ if(enlen) ++ { ++ padding_size -= enlen; ++ ++ //aes_cbc_encrypt_16NL_intface(pIndex, pOut, enlen, ptmpKey, tmpIv, 1); ++ ret = aes_tmp_encrypt_buf_nopadding_new(pIndex, pOut, &enlen, ptmpKey, tmpIv); ++ if(ret != HTTP_OK) ++ { ++ GDPR_DEBUG("aes_cbc_encrypt_intface_bypart aes_tmp_encrypt_buf_nopadding_new Error \n"); ++ return HTTP_ERROR; ++ } ++ ++ memcpy(pIndex, pOut, enlen); ++ ++ padding_size += enlen; ++ ++ } ++ ++ *len = padding_size; ++ ++ return HTTP_OK; ++} ++ ++ ++int aes_cbc_decrypt_intface_bypart(unsigned char *raw_buf, int* len, unsigned char *ptmpKey, unsigned char * ptmpIv) ++{ ++ unsigned char tmpIv[AES_KEY_LEN+1] = {0}; ++ unsigned char encrypt_buf[ITEM_LEN + AES_BLOCK_SIZE + 1] = {0}; ++ unsigned int padding_size = * len; ++ int enlen = 0; ++ unsigned char * pOut = NULL; ++ unsigned char * pIndex = NULL; ++ int lenpart = 0; ++ //unsigned char * ptmp=NULL; ++ int ret = HTTP_OK; ++ ++ memcpy(tmpIv, ptmpIv, AES_KEY_LEN); ++ enlen = padding_size; ++ pIndex = raw_buf; ++ ++ memset(encrypt_buf, 0, ITEM_LEN + AES_BLOCK_SIZE + 1); ++ ++ pOut = encrypt_buf; ++ ++ while( enlen > ITEM_LEN) ++ { ++ ++ lenpart = ITEM_LEN; ++ ret = aes_cbc_encrypt_intface(pIndex, pOut, &lenpart, ptmpKey , tmpIv, 0); ++ if(ret != HTTP_OK) ++ { ++ GDPR_DEBUG("aes_cbc_decrypt_intface_bypart aes_cbc_encrypt_intface Error \n"); ++ return HTTP_ERROR; ++ } ++ memcpy(pIndex, pOut, lenpart); ++ pIndex += ITEM_LEN; ++ memset(encrypt_buf, 0, ITEM_LEN + AES_BLOCK_SIZE + 1); ++ enlen -= ITEM_LEN; ++ } ++ memset(encrypt_buf, 0, ITEM_LEN + AES_BLOCK_SIZE + 1); ++ // no padding ++ if(enlen) ++ { ++ padding_size -= enlen; ++ ++ //aes_cbc_encrypt_16NL_intface(pIndex, pOut, enlen, ptmpKey, tmpIv, 0); ++ ret = aes_tmp_decrypt_buf_nopadding_new(pIndex, pOut, &enlen, ptmpKey, tmpIv); ++ if(ret != HTTP_OK) ++ { ++ GDPR_DEBUG("aes_cbc_decrypt_intface_bypart aes_tmp_decrypt_buf_nopadding_new Error \n"); ++ return HTTP_ERROR; ++ } ++ ++ memcpy(pIndex, pOut, enlen); ++ padding_size += enlen; ++ } ++ ++ *len = padding_size; ++ GDPR_DEBUG("aes_cbc_decrypt_intface_bypart Success !!! \n"); ++ ++ ++ return HTTP_OK; ++} ++ ++/*************************************************************************************/ ++int aes_genKey() ++{ ++ ++ l_pKey = (unsigned char *)malloc(AES_KEY_LEN); ++ l_pV = (unsigned char *)malloc(AES_KEY_LEN); ++ ++ if(l_pKey == NULL || l_pV == NULL) ++ { ++ GDPR_DEBUG("l_pKey or l_pV is NULL \n"); ++ return HTTP_ERROR; ++ } ++ ++ memset(l_pKey, 0, AES_KEY_LEN); ++ memset(l_pV, 0, AES_KEY_LEN); ++ ++ AES_STRNCPY(l_pKey, l_key, AES_KEY_LEN); ++ AES_STRNCPY(l_pV, l_v, AES_KEY_LEN); ++ ++ return HTTP_OK; ++} ++ ++ ++int aes_getKey(unsigned char *key, unsigned char *iv) ++{ ++ ++ if(l_pKey != NULL && l_pV != NULL ) ++ { ++ AES_STRNCPY(key, l_pKey, AES_KEY_LEN); ++ AES_STRNCPY(iv, l_pV, AES_KEY_LEN); ++ } ++ else ++ { ++ GDPR_DEBUG("aes_getKey failed "); ++ return HTTP_ERROR; ++ } ++ ++ return HTTP_OK; ++} ++ ++int aes_set_KeyandIv(unsigned char * Keystr, unsigned char *Ivstr) ++{ ++ if( Keystr == NULL || Ivstr == NULL) ++ { ++ GDPR_DEBUG("Error aes_set_KeyandIv !!!\n"); ++ return HTTP_ERROR; ++ } ++ ++ if(aes_free_KeyandIv() != HTTP_OK) ++ { ++ GDPR_DEBUG("Error aes_set_KeyandIv !!!\n"); ++ return HTTP_ERROR; ++ } ++ ++ l_pKey = (unsigned char *)malloc(AES_KEY_LEN); ++ l_pV = (unsigned char *)malloc(AES_KEY_LEN); ++ ++ if(l_pKey == NULL || l_pV == NULL ) ++ { ++ GDPR_DEBUG("Error aes_set_KeyandIv !!!\n"); ++ return HTTP_ERROR; ++ } ++ memset( l_pKey, 0, AES_KEY_LEN); ++ memset( l_pV, 0, AES_KEY_LEN); ++ ++ AES_STRNCPY(l_pKey, Keystr, AES_KEY_LEN); ++ AES_STRNCPY(l_pV, Ivstr, AES_KEY_LEN); ++ ++ return HTTP_OK; ++} ++ ++ ++int aes_free_KeyandIv() ++{ ++ ++ if(l_pKey!= NULL) ++ { ++ memset(l_pKey, 0, AES_KEY_LEN); ++ free(l_pKey); ++ l_pKey = NULL; ++ } ++ ++ if(l_pV != NULL ) ++ { ++ memset(l_pV, 0, AES_KEY_LEN); ++ free(l_pV); ++ l_pV = NULL; ++ } ++ ++ return HTTP_OK; ++} ++ ++/* ++**Function: int aes_enBufToFile(char * pfile, char *pIn, unsigned int inLen, unsigned char *Key, unsigned char *Iv,unsigned char*pExtend, unsigned int exLen) ++**Des: Encrypt the Buff to File ++**param[in] pfile ++**param[in] pIn ++**param[in] Key ++**param[in] Iv ++**param[in] pExtend ++**param[in] exLen ++** ++** ++**return HTTP_OK / HTTP_ERROR ++*/ ++int aes_enBufToFile(char * pfile, char *pIn, unsigned int inLen, unsigned char *Key, unsigned char *Iv,unsigned char*pExtend, unsigned int exLen) ++{ ++ //int ret = 0; ++ FILE * fp ; ++ ++ ++ unsigned char pOutBuff[HTTP_DATA_EN_LEN] = {0}; // 128 * 3 + 8 + 1 ++ unsigned char pAesEncrypt[HTTP_DATA_EN_LEN] = {0}; // 128 * 3 + 8 + 1 ++ unsigned char Base64AesEncrypt[HTTP_DATA_BASE64_LEN + 1]={0}; // 128 * 3 * 4 / 3 + 1 ++ ++ char * pSend; ++ unsigned char * pExSend; ++ ++ unsigned char tmpIv[AES_KEY_LEN + 1] = {0}; ++ ++ int sendLen = 0; ++ int outBuflen = 0; ++ int outExBuflen = 0; ++ int aesLen = 0; ++ int totalLen = 0; ++ ++ //unsigned char * ptmp; ++ ++ sendLen = inLen; ++ pSend = pIn; ++ pExSend = pExtend; ++ outExBuflen = exLen; ++ ++ fp = fopen(pfile, "w"); ++ if (NULL == fp) ++ { ++ GDPR_DEBUG("open %s fail\n", pfile); ++ return HTTP_ERROR; ++ } ++ ++ memcpy(tmpIv, Iv, AES_KEY_LEN); ++ while ( sendLen > HTTP_DATA_AES_LEN ) ++ { ++ memset(pOutBuff, 0, AES_BLOCK_SIZE+1); ++ memcpy(pOutBuff, pSend, HTTP_DATA_AES_LEN) ; ++ ++ outBuflen = HTTP_DATA_AES_LEN; ++ aesLen = outBuflen; ++ ++ aes_cbc_encrypt_intface(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv, 1); ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, aesLen); ++ ++ fwrite(Base64AesEncrypt, outBuflen, 1 , fp); ++ totalLen += outBuflen; ++ ++ pSend += HTTP_DATA_AES_LEN; ++ sendLen -= HTTP_DATA_AES_LEN; ++ ++ memset(Base64AesEncrypt, 0, HTTP_DATA_BASE64_LEN); ++ memset(pAesEncrypt, 0, HTTP_DATA_AES_LEN); ++ } ++ ++ /*********************************Send the addr + pExtend ******************************************/ ++ if(sendLen > 0) ++ { ++ memset(pOutBuff, 0, HTTP_DATA_AES_LEN); ++ memcpy(pOutBuff, pSend, sendLen); ++ outBuflen = sendLen; ++ if(exLen > 0) ++ { ++ outExBuflen = (exLen + sendLen > HTTP_DATA_AES_LEN) ? (HTTP_DATA_AES_LEN - sendLen) : exLen; ++ strncat((char *)pOutBuff, (char *)pExSend, outExBuflen); ++ ++ pExSend += outExBuflen; ++ exLen -= outExBuflen; ++ outBuflen+= outExBuflen; ++ } ++ aesLen = outBuflen; ++ ++ if(aesLen < HTTP_DATA_AES_LEN || ( aesLen == HTTP_DATA_AES_LEN && exLen==0 ) ) ++ { ++ aes_tmp_encrypt_buf_nopadding_new(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv); ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, aesLen); ++ } ++ else ++ { ++ aes_cbc_encrypt_intface(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv, 1); ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, aesLen); ++ } ++ ++ ++ ++ fwrite(Base64AesEncrypt, outBuflen, 1 , fp); ++ totalLen += outBuflen; ++ ++ memset(Base64AesEncrypt, 0, HTTP_DATA_BASE64_LEN + 1); ++ memset(pAesEncrypt, 0, HTTP_DATA_AES_LEN); ++ } ++ ++ while( exLen > HTTP_DATA_AES_LEN ) ++ { ++ memset(pOutBuff, 0, HTTP_DATA_AES_LEN); ++ memcpy(pOutBuff, pExSend, HTTP_DATA_AES_LEN); ++ ++ outBuflen = HTTP_DATA_AES_LEN; ++ aesLen = outBuflen; ++ ++ aes_cbc_encrypt_intface(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv, 1); ++ ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, outBuflen); ++ fwrite(Base64AesEncrypt, outBuflen, 1 , fp); ++ totalLen += outBuflen; ++ ++ pExSend += HTTP_DATA_AES_LEN; ++ exLen -= HTTP_DATA_AES_LEN; ++ ++ memset(Base64AesEncrypt, 0, HTTP_DATA_BASE64_LEN); ++ memset(pAesEncrypt, 0, HTTP_DATA_AES_LEN); ++ } ++ ++ if(exLen > 0) ++ { ++ memset(pOutBuff, 0, HTTP_DATA_AES_LEN); ++ memcpy(pOutBuff, pExSend, exLen); ++ outBuflen = exLen; ++ aesLen = outBuflen; ++ ++ aes_tmp_encrypt_buf_nopadding_new(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv); ++ ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, aesLen); ++ fwrite(Base64AesEncrypt, outBuflen, 1 , fp); ++ totalLen += outBuflen; ++ ++ pExSend += aesLen; ++ exLen -= aesLen; ++ } ++ ++ /*********************************Send the pExtend******************************************/ ++ ++ fclose(fp); ++ return totalLen; ++} ++ ++ ++/* ++**Function: int aes_enBufToFile_ByArgList(char * pfile, AES_ARGS_ENTRY_HEAD * pAesArgsList, unsigned char *Key, unsigned char *Iv) ++**Des: Encrypt the Buff to File ++**param[in] pfile ++**param[in] pAesArgsList ++**param[in] Key ++**param[in] Iv ++** ++** ++**return HTTP_OK / HTTP_ERROR ++*/ ++int aes_enBufToFile_ByArgList(char * pfile, AES_ARGS_ENTRY_HEAD * pAesArgsList, unsigned char *Key, unsigned char *Iv) ++{ ++ //int ret = 0; ++ FILE * fp ; ++ unsigned char pOutBuff[HTTP_DATA_EN_LEN] = {0}; // 128 * 3 + 8 + 1 ++ unsigned char pAesEncrypt[HTTP_DATA_EN_LEN] = {0}; // 128 * 3 + 8 + 1 ++ unsigned char Base64AesEncrypt[HTTP_DATA_BASE64_LEN + 1]={0}; // 128 * 3 * 4 / 3 + 1 ++ ++ unsigned char * pSend; ++ unsigned char * pExSend; ++ ++ unsigned char tmpIv[AES_KEY_LEN + 1] = {0}; ++ ++ unsigned int sendLen = 0; ++ unsigned int outBuflen = 0; ++ ++ unsigned int outExBuflen = 0; ++ ++ int aesLen = 0; ++ unsigned int exLen = 0; ++ ++ unsigned int totalLen = 0; ++ AES_ARGS_ENTRY * pAesArgsEntry = pAesArgsList->next; ++ AES_ARGS_ENTRY * pTmpAesArgsEntry; ++ ++ //unsigned char * ptmp; ++ ++ ++ fp = fopen(pfile, "w"); ++ if (NULL == fp) ++ { ++ GDPR_DEBUG("open %s fail\n", pfile); ++ return HTTP_ERROR; ++ } ++ ++ memcpy(tmpIv, Iv, AES_KEY_LEN); ++ ++ ++ while(pAesArgsEntry != NULL) ++ { ++ pSend = pAesArgsEntry->addr; ++ sendLen = pAesArgsEntry->len; ++ ++ /********************************* HTTP_DATA_AES_LEN ******************************************/ ++ while ( sendLen > HTTP_DATA_AES_LEN ) ++ { ++ memset(pOutBuff, 0, AES_BLOCK_SIZE+1); ++ memcpy(pOutBuff, pSend, HTTP_DATA_AES_LEN); ++ ++ outBuflen = HTTP_DATA_AES_LEN; ++ aesLen = outBuflen; ++ ++ aes_cbc_encrypt_intface(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv, 1); ++ ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, outBuflen); ++ fwrite(Base64AesEncrypt, outBuflen, 1 , fp); ++ totalLen += outBuflen; ++ ++ pSend += HTTP_DATA_AES_LEN; ++ sendLen -= HTTP_DATA_AES_LEN; ++ ++ memset(Base64AesEncrypt, 0, HTTP_DATA_BASE64_LEN); ++ memset(pAesEncrypt, 0, HTTP_DATA_AES_LEN); ++ } ++ if(sendLen > 0) ++ { ++ memset(pOutBuff, 0, HTTP_DATA_AES_LEN); ++ memcpy(pOutBuff, pSend, sendLen); ++ outBuflen = sendLen; ++ aesLen = outBuflen; ++ pSend += aesLen; ++ sendLen -= aesLen; ++ if(pAesArgsEntry->next==NULL) ++ { ++ ++ /*********************************Send the addr + pExtend ******************************************/ ++ aes_tmp_encrypt_buf_nopadding_new(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv); ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, aesLen); ++ fwrite(Base64AesEncrypt, outBuflen, 1 , fp); ++ totalLen += outBuflen; ++ break; //the pAesArgsEntry flush ++ } ++ else ++ { ++ pTmpAesArgsEntry = pAesArgsEntry->next; ++ while( pTmpAesArgsEntry !=NULL ) ++ { ++ pExSend = pTmpAesArgsEntry->addr; ++ exLen = pTmpAesArgsEntry->len; ++ sendLen = strlen((char *)pOutBuff); ++ outExBuflen = (exLen + sendLen > HTTP_DATA_AES_LEN) ? (HTTP_DATA_AES_LEN - sendLen) : exLen; ++ ++ if(strlen((char *)pOutBuff) != 0) ++ { ++ strncat((char *)pOutBuff, (char *)pExSend, outExBuflen); ++ } ++ else ++ { ++ memcpy(pOutBuff, pExSend, outExBuflen); ++ } ++ ++ outBuflen += outExBuflen; ++ aesLen = outBuflen; ++ ++ pTmpAesArgsEntry->addr += outExBuflen; ++ pTmpAesArgsEntry->len -= outExBuflen; ++ ++ if(outBuflen < HTTP_DATA_AES_LEN && pTmpAesArgsEntry->next != NULL) // pTmpAesArgsEntry->len == 0 ++ { ++ sendLen = outBuflen; ++ pTmpAesArgsEntry = pTmpAesArgsEntry->next; ++ } ++ else if(pTmpAesArgsEntry->next == NULL) ++ { ++ if(pTmpAesArgsEntry->len == 0) ++ { ++ aes_tmp_encrypt_buf_nopadding_new(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv); ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, aesLen); ++ pTmpAesArgsEntry = pTmpAesArgsEntry->next; ++ } ++ else ++ { ++ aes_cbc_encrypt_intface(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv, 1); ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, aesLen); ++ } ++ fwrite(Base64AesEncrypt, outBuflen, 1 , fp); ++ totalLen += outBuflen; ++ sendLen = 0; ++ outBuflen=0; ++ memset(Base64AesEncrypt, 0, HTTP_DATA_BASE64_LEN + 1); ++ memset(pAesEncrypt, 0, HTTP_DATA_AES_LEN); ++ memset(pOutBuff, 0, HTTP_DATA_AES_LEN); ++ continue; ++ } ++ else ++ { ++ aes_cbc_encrypt_intface(pOutBuff, pAesEncrypt, &aesLen, Key, tmpIv, 1); ++ outBuflen = b64_encode(Base64AesEncrypt, HTTP_DATA_BASE64_LEN, pAesEncrypt, aesLen); ++ fwrite(Base64AesEncrypt, outBuflen, 1 , fp); ++ totalLen += outBuflen; ++ memset(Base64AesEncrypt, 0, HTTP_DATA_BASE64_LEN + 1); ++ memset(pAesEncrypt, 0, HTTP_DATA_AES_LEN); ++ memset(pOutBuff, 0, HTTP_DATA_AES_LEN); ++ break; ++ } ++ } ++ pAesArgsEntry = pTmpAesArgsEntry; ++ } ++ ++ } ++ else // won't be exec ++ { ++ pAesArgsEntry = pAesArgsEntry->next; ++ } ++ } ++ /*********************************Send the pExtend******************************************/ ++ ++ fclose(fp); ++ return totalLen; ++} ++ ++ ++/* ++**Function: int aes_argList_add(AES_ARGS_ENTRY_HEAD* pAesArgsList, unsigned char * raw_buf, unsigned int len) ++**Des: Add the addr and len AES_ARGS_ENTRY_HEAD* pAesArgsList ++**param[in] pAesArgsList ++**param[in] raw_buf ++**param[in] len ++** ++**return HTTP_OK / HTTP_ERROR ++*/ ++int aes_argList_add(AES_ARGS_ENTRY_HEAD* pAesArgsList, unsigned char * raw_buf, unsigned int len) ++{ ++ AES_ARGS_ENTRY* pAesArgsEntry = pAesArgsList->next; ++ AES_ARGS_ENTRY* Item; ++ ++ Item = (AES_ARGS_ENTRY *)malloc(sizeof(AES_ARGS_ENTRY)); ++ ++ if(Item == NULL) ++ { ++ GDPR_DEBUG("malloc is null "); ++ return HTTP_ERROR; ++ } ++ ++ Item->addr = raw_buf; ++ Item->len = len; ++ Item->next = NULL; ++ Item->prev = NULL; ++ ++ if(pAesArgsEntry != NULL) ++ { ++ while(pAesArgsEntry->next !=NULL ) ++ { ++ pAesArgsEntry = pAesArgsEntry->next; ++ } ++ pAesArgsEntry->next = Item; ++ Item->prev = pAesArgsEntry; ++ } ++ else ++ { ++ pAesArgsList->next=Item; ++ Item->prev = NULL; ++ } ++ ++ return HTTP_OK; ++} ++ ++/* ++**Function: int aes_argList_add(AES_ARGS_ENTRY_HEAD* pAesArgsList, unsigned char * raw_buf, unsigned int len) ++**Des: Encrypt the Buff to File ++**param[in] pAesArgsList ++**param[in] raw_buf ++**param[in] len ++** ++**return HTTP_OK / HTTP_ERROR ++*/ ++int aes_argList_flush(AES_ARGS_ENTRY_HEAD* pAesArgsList) ++{ ++ AES_ARGS_ENTRY* pAesArgsEntry = pAesArgsList->next; ++ AES_ARGS_ENTRY* pAesArgsEntry2 = pAesArgsEntry; ++ ++ if(pAesArgsEntry == NULL) ++ { ++ GDPR_DEBUG("aes_argList_add Error pAesArgsList is null!"); ++ return HTTP_ERROR; ++ } ++ ++ while(pAesArgsEntry->next !=NULL ) ++ { ++ pAesArgsEntry = pAesArgsEntry->next; ++ } ++ pAesArgsEntry2 = pAesArgsEntry; ++ while(pAesArgsEntry2->prev != NULL) ++ { ++ pAesArgsEntry2 = pAesArgsEntry->prev; ++ free(pAesArgsEntry); ++ pAesArgsEntry=pAesArgsEntry2; ++ } ++ ++ return HTTP_OK; ++} ++ ++ ++ ++ ++ ++int uci_encrypt(char * raw_data_buf, unsigned int raw_data_buf_len, char * encry_data_buf, unsigned int encry_data_buf_len) ++{ ++ int ret = 0; ++ int len = raw_data_buf_len + AES_BLOCK_SIZE + 1; ++ char *ptr = NULL; ++ ++ GDPR_DEBUG("raw data=%s, len=%d\n",raw_data_buf, raw_data_buf_len); ++ ++ char * aes_data_buf = (char *) malloc(len); ++ if(aes_data_buf == NULL) ++ { ++ GDPR_DEBUG("uci_encrypt malloc space error \n"); ++ return -1; ++ } ++ ++ memset(aes_data_buf,0,len); ++ ++ ptr = aes_data_buf; ++ ++ memcpy( ptr, raw_data_buf, raw_data_buf_len); ++ ++ aes_data_buf[raw_data_buf_len] = '\0'; ++ ++ len = raw_data_buf_len; ++ ++ ret = aes_cbc_encrypt_intface_bypart((unsigned char*)aes_data_buf, &len, l_key, l_v); ++ if (ret < 0) ++ { ++ GDPR_DEBUG("aes_encrypt error\n"); ++ goto ERROR; ++ } ++ GDPR_DEBUG("aes data=%s, len=%d\n",aes_data_buf, len); ++ ++ memcpy(encry_data_buf,gmark,strlen((const char *)gmark)); ++ ++ ret = b64_encode((unsigned char *)encry_data_buf+strlen((const char *)gmark), encry_data_buf_len, aes_data_buf, len); ++ if(ret < 0) ++ { ++ GDPR_DEBUG("b64 encode error \n"); ++ goto ERROR; ++ } ++ GDPR_DEBUG("base64 data=%s, len=%d\n",encry_data_buf, encry_data_buf_len); ++ ++ free(aes_data_buf); ++ return 0; ++ ++ERROR: ++ free(aes_data_buf); ++ return -1; ++} ++ ++int uci_decrypt(char * decrypt_data_buf, unsigned int decrypt_data_buf_len,char* encrypt_data_buf, unsigned int encrypt_data_buf_len) ++{ ++ int ret = 0; ++ ++ GDPR_DEBUG(" GDPR_DEBUG encrypt_data_buf = %s, encrypt_data_buf_len = %d",encrypt_data_buf,encrypt_data_buf_len); ++ ++ if( strncmp(encrypt_data_buf,(const char *)gmark, strlen((const char *)gmark)) != 0) ++ { ++ memset(decrypt_data_buf,0,decrypt_data_buf_len); ++ decrypt_data_buf_len = encrypt_data_buf_len; ++ memcpy(decrypt_data_buf, encrypt_data_buf,encrypt_data_buf_len); ++ GDPR_DEBUG("not find mark=%s, decrypt_data_buf = %s , len=%d\n", gmark, decrypt_data_buf, encrypt_data_buf_len); ++ return 0; ++ } ++ //base64 decrypt ++ decrypt_data_buf_len = b64_decode(decrypt_data_buf, (int)decrypt_data_buf_len, encrypt_data_buf+strlen((const char *)gmark), encrypt_data_buf_len-strlen((const char *)gmark)); ++ ++ if( decrypt_data_buf_len == -1) ++ { ++ GDPR_DEBUG("b64 decode fail\n"); ++ return -1; ++ } ++ GDPR_DEBUG("after base64 decode data= %s, len = %d",decrypt_data_buf,decrypt_data_buf_len); ++ ++ //aes decrypt ++ ret = aes_cbc_decrypt_intface_bypart((unsigned char *)decrypt_data_buf, (int *)&decrypt_data_buf_len, l_key, l_v); ++ decrypt_data_buf[decrypt_data_buf_len]='\0'; ++ if( ret != 0 ) ++ { ++ GDPR_DEBUG("aes decrypt fail\n"); ++ return -1; ++ } ++ GDPR_DEBUG("after aes decrypt data=%s,len = %d \n",decrypt_data_buf,decrypt_data_buf_len); ++ ++ return 0; ++} ++ +diff --git a/gdpr_aes_interface.h b/gdpr_aes_interface.h +new file mode 100755 +index 0000000..390aae9 +--- /dev/null ++++ b/gdpr_aes_interface.h +@@ -0,0 +1,201 @@ ++/* Copyright(c) 2009-2018 Shenzhen TP-LINK Technologies Co.Ltd. ++ * ++ * file gdpr_aes_interface.h ++ * brief AES handle ++ * details lcrypto ++ * ++ * author Li Qiang ++ * version 1.0.1 ++ * date 26Apr18 ++ * ++ * warning ++ * ++ * history \arg 1.0.0, 25May18, Li Qiang, Create the file. ++ * history \arg 1.0.1 10JUL18, Liao Xingwei, merge functions from http_aes.h ++ */ ++#ifndef __GDPR_AES_INTERFACE_H__ ++#define __GDPR_AES_INTERFACE_H__ ++ ++#include "openssl/aes.h" ++/**************************************************************************************************/ ++/* DEFINES */ ++/**************************************************************************************************/ ++#define AES_KEY_LEN 32 ++ ++#define AES_STRNCPY(dest, src, len) memcpy(dest, src, len); ++ ++#define ITEM_LEN 128 ++ ++#define HTTP_DATA_AES_LEN 128*3 // 512 = 128 * 4 need padding ==> 128*4 + 16 = 16*(32 + 1) Base64 : ( 16 * 33 ) * 4 /3 = 16 * 44 = 704 ++ ++#define HTTP_DATA_BASE64_LEN 1024 // 128 * 3 ==> Base64 : ( 128 * 3 ) * 4 /3 = 512 ++ ++#define HTTP_DATA_EN_LEN HTTP_DATA_AES_LEN+16 + 1 //128 * 3 + 16 +1 ++ ++/**************************************************************************************************/ ++/* TYPES */ ++/**************************************************************************************************/ ++typedef struct _AES_ARGS_ENTRY{ ++ struct _AES_ARGS_ENTRY * next; ++ struct _AES_ARGS_ENTRY * prev; ++ unsigned char * addr; ++ unsigned int len; ++} AES_ARGS_ENTRY; ++ ++typedef struct _AES_ARGS_ENTRY_HEAD{ ++ struct _AES_ARGS_ENTRY * next; ++ struct _AES_ARGS_ENTRY * prev; ++} AES_ARGS_ENTRY_HEAD; ++ ++/**************************************************************************************************/ ++/* VARIABLES */ ++/**************************************************************************************************/ ++ ++/**************************************************************************************************/ ++/* FUNCTIONS */ ++/**************************************************************************************************/ ++/* ++**Function: int remove_padding(unsigned char *buff, int dataLen, int blockSize) ++**Des: padding buf ++**param[in] buf - enough buffer ++**param[in] dataLen ++**param[in] blockSize block size 16 ++** ++**ret buff padding size need remove ++*/ ++int remove_padding(unsigned char *buff, int dataLen, int blockSize); ++ ++void printf_buff(unsigned char *buff,int size) ; ++ ++/* ++**Function: unsigned char *real_padding_buf(unsigned char *buf,int size, int *final_size) ++**Des: padding buf ++**param[in] buf - enough buffer padding the buffer ++**param[in] size ++**param[in] final_size ++** ++**ret the after buff padding ++*/ ++void real_padding_buf(unsigned char *buf, int size, int *final_size); ++ ++/* ++**Des: flag : 1 Encrypt 0 or other : Decrypt ++** input : raw_buf ++** output: encrypt_buf ++**ret£ºvoid ++*/ ++int aes_cbc_encrypt_intface(unsigned char *raw_buf, unsigned char *encrypt_buf, int* len , unsigned char *ptmpKey, unsigned char * ptmpIv, int flag); ++ ++/* ++**Des: Encrypt and Decrypt with temp Key and Iv ++*/ ++int aes_tmp_encrypt_buf_nopadding_new(unsigned char *raw_buf, unsigned char *encrypt_buf, int* len , unsigned char *ptmpKey, unsigned char * ptmpIv); ++int aes_tmp_decrypt_buf_nopadding_new(unsigned char *raw_buf, unsigned char *encrypt_buf, int* len , unsigned char *ptmpKey, unsigned char * ptmpIv); ++ ++/* ++**Des: flag : Encrypt ++** input : raw_buf ++** output: raw_buf ++**ret£ºvoid ++*/ ++int aes_cbc_encrypt_intface_bypart(unsigned char *raw_buf, int* len, unsigned char *ptmpKey, unsigned char * ptmpIv); ++ ++/* ++**Des: flag : Decrypt ++** input : raw_buf ++** output: raw_buf ++**ret£ºvoid ++*/ ++int aes_cbc_decrypt_intface_bypart(unsigned char *raw_buf, int* len, unsigned char *ptmpKey, unsigned char * ptmpIv); ++ ++/* ++**Des: SetKey and Iv ++*/ ++int aes_set_KeyandIv(unsigned char * Keystr, unsigned char *Ivstr); ++ ++/* ++**Des: Free the System Key And Iv ++*/ ++int aes_free_KeyandIv(); ++ ++/* ++**Des: Get the System Key And Iv ++**return TTP_OK / HTTP_ERROR ++*/ ++int aes_getKey(unsigned char *key, unsigned char *iv); ++ ++/* ++**Function: int aes_enBufToFile(char * pfile, char *pIn, unsigned int inLen, unsigned char *Key, unsigned char *Iv,unsigned char*pExtend, unsigned int exLen) ++**Des: Encrypt the Buff to File ++**param[in] pfile ++**param[in] pIn ++**param[in] Key ++**param[in] Iv ++**param[in] pExtend ++**param[in] exLen ++** ++** ++**return HTTP_OK / HTTP_ERROR ++*/ ++int aes_enBufToFile(char * pfile, char *pIn, unsigned int inLen, unsigned char *Key, unsigned char *Iv,unsigned char*pExtend, unsigned int exLen); ++ ++/* ++**Function: int aes_enBufToFile_ByArgList(char * pfile, AES_ARGS_ENTRY_HEAD * pAesArgsList, unsigned char *Key, unsigned char *Iv) ++**Des: Encrypt the Buff to File ++**param[in] pfile ++**param[in] pAesArgsList ++**param[in] Key ++**param[in] Iv ++** ++** ++**return HTTP_OK / HTTP_ERROR ++*/ ++int aes_enBufToFile_ByArgList(char * pfile, AES_ARGS_ENTRY_HEAD * pAesArgsList, unsigned char *Key, unsigned char *Iv); ++ ++/* ++**Function: int aes_argList_add(AES_ARGS_ENTRY_HEAD* pAesArgsList, unsigned char * raw_buf, unsigned int len) ++**Des: Add the addr and len AES_ARGS_ENTRY_HEAD* pAesArgsList ++**param[in] pAesArgsList ++**param[in] raw_buf ++**param[in] len ++** ++**return HTTP_OK / HTTP_ERROR ++*/ ++int aes_argList_add(AES_ARGS_ENTRY_HEAD* pAesArgsList, unsigned char * raw_buf, unsigned int len); ++ ++/* ++**Function: int aes_argList_flush(AES_ARGS_ENTRY_HEAD* pAesArgsList) ++**Des: flush the AES_ARGS_ENTRY_HEAD* pAesArgsList ++**param[in] pAesArgsList ++** ++**return HTTP_OK / HTTP_ERROR ++*/ ++int aes_argList_flush(AES_ARGS_ENTRY_HEAD* pAesArgsList); ++ ++/* ++**Function: int uci_encrypt(char * raw_data_buf, unsigned int raw_data_buf_len, char * encrypt_data_buf, unsigned int encrypt_data_buf_len) ++**Des: encrypt uci data ++**param[in] raw_data_buf ++**param[in] raw_data_buf_len ++**param[in/out] encrypt_data_buf ++**param[in] encrypt_data_buf_len ++** ++**return 0 / -1 ++*/ ++int uci_encrypt(char * raw_data_buf, unsigned int raw_data_buf_len, char * encrypt_data_buf, unsigned int encrypt_data_buf_len); ++ ++/* ++**Function: int uci_decrypt(char * decrypt_data_buf, unsigned int decrypt_data_buf_len,char* encrypt_data_buf, unsigned int encrypt_data_buf_len) ++**Des: decrpty uci data ++**param[in] decrypt_data_buf ++**param[in] decrypt_data_buf_len ++**param[in/out] encrypt_data_buf ++**param[in] encrypt_data_buf_len ++** ++**return 0 / -1 ++*/ ++ ++int uci_decrypt(char * decrypt_data_buf, unsigned int decrypt_data_buf_len,char* encrypt_data_buf, unsigned int encrypt_data_buf_len); ++ ++#endif /*__GDPR_AES_INTERFACE_H__*/ ++ +diff --git a/gdpr_log.h b/gdpr_log.h +new file mode 100644 +index 0000000..426826a +--- /dev/null ++++ b/gdpr_log.h +@@ -0,0 +1,37 @@ ++#ifndef __GDPR_LOG_H_ ++#define __GDPR_LOG_H_ ++/******************************************************************************/ ++/* INCLUDE_FILES */ ++/******************************************************************************/ ++#include ++ ++/**************************************************************************************************/ ++/* DEFINES */ ++/**************************************************************************************************/ ++#define UCI_LOG_TAG "UCI_GDPR" ++ ++#ifdef DEBUG ++#define GDPR_DEBUG(_fmt, ...) \ ++ {\ ++ printf("[ %s ] %d: ", __FUNCTION__, __LINE__); \ ++ printf(_fmt, ##__VA_ARGS__); \ ++ /*LOG_PRI(ANDROID_LOG_INFO, UCI_LOG_TAG, _fmt, ## __VA_ARGS__); */\ ++ } ++#else ++#define GDPR_DEBUG(_fmt,...) {} ++#endif ++ ++/**************************************************************************************************/ ++/* TYPES */ ++/**************************************************************************************************/ ++ ++/**************************************************************************************************/ ++/* VARIABLES */ ++/**************************************************************************************************/ ++ ++/**************************************************************************************************/ ++/* FUNCTIONS */ ++/**************************************************************************************************/ ++ ++ ++#endif /* __GDPR_LOG_H_ */ +diff --git a/libuci.c b/libuci.c +index b17cda1..1f382e7 100644 +--- a/libuci.c ++++ b/libuci.c +@@ -35,6 +35,10 @@ static const char *uci_errstr[] = { + [UCI_ERR_PARSE] = "Parse error", + [UCI_ERR_DUPLICATE] = "Duplicate entry", + [UCI_ERR_UNKNOWN] = "Unknown error", ++#ifdef TP_FEATURE_GDPR ++ [UCI_ERR_ENCRYPT] = "encrypt data error", ++ [UCI_ERR_DECRYPT] = "decrypt data error", ++#endif + }; + + #include "uci_internal.h" +diff --git a/list.c b/list.c +index faf4494..1509205 100644 +--- a/list.c ++++ b/list.c +@@ -693,9 +693,11 @@ int uci_set(struct uci_context *ctx, struct uci_ptr *ptr) + ptr->s = uci_alloc_section(ptr->p, ptr->value, ptr->section); + ptr->last = &ptr->s->e; + } else if (ptr->o && ptr->option) { /* update option */ ++#ifndef TP_FEATURE_GDPR + if ((ptr->o->type == UCI_TYPE_STRING) && + !strcmp(ptr->o->v.string, ptr->value)) + return 0; ++#endif + uci_free_option(ptr->o); + ptr->o = uci_alloc_option(ptr->s, ptr->option, ptr->value); + ptr->last = &ptr->o->e; +diff --git a/uci.h b/uci.h +index 36c8890..d7de962 100644 +--- a/uci.h ++++ b/uci.h +@@ -50,6 +50,10 @@ enum + UCI_ERR_PARSE, + UCI_ERR_DUPLICATE, + UCI_ERR_UNKNOWN, ++#ifdef TP_FEATURE_GDPR ++ UCI_ERR_ENCRYPT, ++ UCI_ERR_DECRYPT, ++#endif + UCI_ERR_LAST + }; + diff --git a/oe-core/meta-tp/recipes/uci/uci.bb b/oe-core/meta-tp/recipes/uci/uci.bb index 4c38d98c2..622f736a9 100755 --- a/oe-core/meta-tp/recipes/uci/uci.bb +++ b/oe-core/meta-tp/recipes/uci/uci.bb @@ -8,7 +8,8 @@ SRCREV="393bc2b908ef44cb8b417126a35d4915c4cdfbc9" SRC_URI = "git://nbd.name/uci.git;protocol=git \ file://hack_uci_save.patch \ file://unspport_lua.patch \ - file://change_default_confdir.patch" + file://change_default_confdir.patch\ + file://gdpr.patch" S="${WORKDIR}/git" @@ -17,6 +18,13 @@ INHIBIT_PACKAGE_DEBUG_SPLIT = "1" PACKAGES = "${PN}" DEPENDS = "libubox" +DEPENDS += "${@base_conditional('TP_FEATURE_GDPR', 'y', 'openssl', '', d)}" +DEPENDS += "${@base_conditional('TP_FEATURE_GDPR', 'y', 'system-core', '', d)}" + #RDEPENDS += "libubox" inherit cmake + +OECMAKE_C_FLAGS += "${@base_conditional('TP_FEATURE_GDPR', 'y', '-DTP_FEATURE_GDPR', '', d)}" + + diff --git a/oe-core/meta/files/common-licenses/TPLink-Corporation-Limited.-Proprietary b/oe-core/meta/files/common-licenses/TPLink-Corporation-Limited.-Proprietary new file mode 100755 index 000000000..84656a27b --- /dev/null +++ b/oe-core/meta/files/common-licenses/TPLink-Corporation-Limited.-Proprietary @@ -0,0 +1,2 @@ +Copyright (c) 2020 TPLINK CORPORATION LIMITED. All Rights Reserved. +TP-Link Corporation Limited Proprietary and Confidential. diff --git a/oe-core/meta/files/common-licenses/TPLink-Technologies-Inc.-Proprietary b/oe-core/meta/files/common-licenses/TPLink-Technologies-Inc.-Proprietary deleted file mode 100755 index 35b7ce313..000000000 --- a/oe-core/meta/files/common-licenses/TPLink-Technologies-Inc.-Proprietary +++ /dev/null @@ -1,2 +0,0 @@ -Copyright (c) 2015 TPLINK TECHNOLOGIES CO., LTD. All Rights Reserved. -TP-Link Technologies Proprietary and Confidential. diff --git a/oe-core/meta/recipes-support/curl/curl/configure_ac.patch b/oe-core/meta/recipes-support/curl/curl/configure_ac.patch old mode 100644 new mode 100755 index b8bd304d7..98d83871f --- a/oe-core/meta/recipes-support/curl/curl/configure_ac.patch +++ b/oe-core/meta/recipes-support/curl/curl/configure_ac.patch @@ -1,5 +1,3 @@ -Upstream-Status: Pending - --- a/configure.ac +++ b/configure.ac @@ -281,7 +281,7 @@ dnl ************************************ diff --git a/oe-core/meta/recipes-support/curl/curl_7.30.0.bb b/oe-core/meta/recipes-support/curl/curl_7.30.0.bb new file mode 100755 index 000000000..fbfc211fd --- /dev/null +++ b/oe-core/meta/recipes-support/curl/curl_7.30.0.bb @@ -0,0 +1,62 @@ +DESCRIPTION = "Command line tool and library for client-side URL transfers." +HOMEPAGE = "http://curl.haxx.se/" +BUGTRACKER = "http://curl.haxx.se/mail/list.cgi?list=curl-tracker" +SECTION = "console/network" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://COPYING;beginline=7;md5=3a34942f4ae3fbf1a303160714e664ac" + +DEPENDS = "zlib gnutls" +DEPENDS_class-native = "zlib-native openssl-native" +DEPENDS_class-nativesdk = "nativesdk-zlib" +PR = "r0" + +SRC_URI = "http://curl.haxx.se/download/curl-${PV}.tar.bz2 \ + file://pkgconfig_fix.patch \ +" + +# curl likes to set -g0 in CFLAGS, so we stop it +# from mucking around with debug options +# +SRC_URI += " file://configure_ac.patch" + +SRC_URI[md5sum] = "0db5ec03a5001b42a2edc03bf63b5ceb" +SRC_URI[sha256sum] = "6b1c410387bea82601baec85d6aa61955794672e36766407e99ade8d55aaaf11" + +inherit autotools pkgconfig binconfig + +EXTRA_OECONF = "--with-zlib=${STAGING_LIBDIR}/../ \ + --without-libssh2 \ + --with-random=/dev/urandom \ + --without-libidn \ + --enable-crypto-auth \ + --disable-ldap \ + --disable-ldaps \ + ${CURLGNUTLS} \ + " + +CURLGNUTLS = " --with-gnutls=${STAGING_LIBDIR}/../ --without-ssl" +CURLGNUTLS_class-native = "--without-gnutls --with-ssl" +CURLGNUTLS_class-nativesdk = "--without-gnutls --without-ssl" + +do_configure_prepend() { + sed -i s:OPT_GNUTLS/bin:OPT_GNUTLS:g ${S}/configure.ac +} + +PACKAGES =+ "${PN}-certs libcurl libcurl-dev libcurl-staticdev libcurl-doc" + +FILES_${PN}-certs = "${datadir}/curl/curl-*" +PACKAGE_ARCH_${PN}-certs = "all" + +FILES_lib${BPN} = "${libdir}/lib*.so.*" +RRECOMMENDS_lib${BPN} += "${PN}-certs" +FILES_lib${BPN}-dev = "${includedir} \ + ${libdir}/lib*.so \ + ${libdir}/lib*.la \ + ${libdir}/pkgconfig \ + ${datadir}/aclocal \ + ${bindir}/*-config" +FILES_lib${BPN}-staticdev = "${libdir}/lib*.a" +FILES_lib${BPN}-doc = "${mandir}/man3 \ + ${mandir}/man1/curl-config.1" + +BBCLASSEXTEND = "native nativesdk" diff --git a/oe-core/meta/recipes-support/curl/curl_7.40.0.bb b/oe-core/meta/recipes-support/curl/curl_7.40.0.bb deleted file mode 100644 index d4b4ee350..000000000 --- a/oe-core/meta/recipes-support/curl/curl_7.40.0.bb +++ /dev/null @@ -1,59 +0,0 @@ -SUMMARY = "Command line tool and library for client-side URL transfers" -HOMEPAGE = "http://curl.haxx.se/" -BUGTRACKER = "http://curl.haxx.se/mail/list.cgi?list=curl-tracker" -SECTION = "console/network" -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://COPYING;beginline=7;md5=3a34942f4ae3fbf1a303160714e664ac" - -SRC_URI = "http://curl.haxx.se/download/curl-${PV}.tar.bz2 \ - file://pkgconfig_fix.patch \ - " - -# curl likes to set -g0 in CFLAGS, so we stop it -# from mucking around with debug options -# -SRC_URI += " file://configure_ac.patch" - -SRC_URI[md5sum] = "8d30594212e65657a5c32030f0998fa9" -SRC_URI[sha256sum] = "899109eb3900fa6b8a2f995df7f449964292776a04763e94fae640700f883fba" - -inherit autotools pkgconfig binconfig multilib_header - -PACKAGECONFIG ??= "${@bb.utils.contains("DISTRO_FEATURES", "ipv6", "ipv6", "", d)} gnutls zlib" -PACKAGECONFIG_class-native = "ipv6 ssl zlib" -PACKAGECONFIG_class-nativesdk = "ipv6 ssl zlib" - -PACKAGECONFIG[ipv6] = "--enable-ipv6,--disable-ipv6," -PACKAGECONFIG[ssl] = "--with-ssl --with-random=/dev/urandom,--without-ssl,openssl" -PACKAGECONFIG[gnutls] = "--with-gnutls,--without-gnutls,gnutls" -PACKAGECONFIG[zlib] = "--with-zlib=${STAGING_LIBDIR}/../,--without-zlib,zlib" -PACKAGECONFIG[rtmpdump] = "--with-librtmp,--without-librtmp,rtmpdump" -PACKAGECONFIG[libssh2] = "--with-libssh2,--without-libssh2,libssh2" -PACKAGECONFIG[smb] = "--enable-smb,--disable-smb,samba" - -EXTRA_OECONF = "--without-libidn \ - --enable-crypto-auth \ - --disable-ldap \ - --disable-ldaps \ - --with-ca-bundle=${sysconfdir}/ssl/certs/ca-certificates.crt \ -" - -do_install_append() { - oe_multilib_header curl/curlbuild.h -} - -PACKAGES =+ "lib${BPN} lib${BPN}-dev lib${BPN}-staticdev lib${BPN}-doc" - -FILES_lib${BPN} = "${libdir}/lib*.so.*" -RRECOMMENDS_lib${BPN} += "ca-certificates" -FILES_lib${BPN}-dev = "${includedir} \ - ${libdir}/lib*.so \ - ${libdir}/lib*.la \ - ${libdir}/pkgconfig \ - ${datadir}/aclocal \ - ${bindir}/*-config" -FILES_lib${BPN}-staticdev = "${libdir}/lib*.a" -FILES_lib${BPN}-doc = "${mandir}/man3 \ - ${mandir}/man1/curl-config.1" - -BBCLASSEXTEND = "native nativesdk" diff --git a/shortcut-fe/fast-classifier/fast-classifier.c b/shortcut-fe/fast-classifier/fast-classifier.c old mode 100644 new mode 100755 index 5c64b1f3b..bb43d4b53 --- a/shortcut-fe/fast-classifier/fast-classifier.c +++ b/shortcut-fe/fast-classifier/fast-classifier.c @@ -1353,6 +1353,7 @@ static const struct device_attribute fast_classifier_debug_info_attr = static const struct device_attribute fast_classifier_skip_bridge_ingress = __ATTR(skip_to_bridge_ingress, S_IWUGO | S_IRUGO, fast_classifier_get_skip_bridge_ingress, fast_classifier_set_skip_bridge_ingress); + /* * fast_classifier_init() */ diff --git a/shortcut-fe/shortcut-fe/Makefile b/shortcut-fe/shortcut-fe/Makefile old mode 100644 new mode 100755 index a23524dd4..5f298492a --- a/shortcut-fe/shortcut-fe/Makefile +++ b/shortcut-fe/shortcut-fe/Makefile @@ -35,6 +35,7 @@ shortcut-fe-cm-objs := \ sfe_cm.o ccflags-y += -D__CHECK_ENDIAN__ + ccflags-y += -DSFE_CONFIG_MARK CDEFINES += -D__CHECK_ENDIAN__ diff --git a/shortcut-fe/shortcut-fe/sfe.h b/shortcut-fe/shortcut-fe/sfe.h old mode 100644 new mode 100755 diff --git a/shortcut-fe/shortcut-fe/sfe_cm.c b/shortcut-fe/shortcut-fe/sfe_cm.c old mode 100644 new mode 100755 index 25f6d7441..8b4806e8e --- a/shortcut-fe/shortcut-fe/sfe_cm.c +++ b/shortcut-fe/shortcut-fe/sfe_cm.c @@ -30,6 +30,12 @@ #include #include +//[zhangguosong start] +#ifdef TP_FEATURE_WLANTC +#include +#endif +//[zhangguosong end] + #include "sfe.h" #include "sfe_cm.h" #include "sfe_backport.h" @@ -551,6 +557,20 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) sic.dest_port = orig_tuple.dst.u.udp.port; sic.src_port_xlate = reply_tuple.dst.u.udp.port; sic.dest_port_xlate = reply_tuple.src.u.udp.port; + + //[zhangguosong start] 2018-06-21 + /* Do not use package from reply to build sfe connection */ + if (likely(is_v4)) + { + struct iphdr* iph = ip_hdr(skb); + if (iph && ntohl(iph->saddr) != ntohl(sic.src_ip_xlate.ip) + && ntohl(iph->saddr) != ntohl(sic.src_ip.ip)) + { + DEBUG_TRACE("%s: Ignore reply package\n", __FUNCTION__); + return NF_ACCEPT; + } + } + //[zhangguosong end] break; default: @@ -665,9 +685,34 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4) sic.src_dev = src_dev_use; sic.dest_dev = dest_dev_use; + //[zhangguosong start] 2018-07-30 + /* Fix#241362 + * ÃèÊö: µ±Ìí¼ÓÁËÏÞËÙ¹æÔòµÄ¿Í»§¶Ë±»ÉèÖÃΪDMZÖ÷»úʱ,Íⲿ¿Í»§¶ËÖ÷¶¯·¢ÆðÁ¬½ÓÇëÇóÅÜÍÌÍÂÁ¿Ê±,¸Ã¿Í»§¶ËÎÞ·¨±»ÏÞËÙ + * Ô­Òò: ÓÉÓÚÊÇÍⲿ¿Í»§¶ËÖ÷¶¯·¢ÆðÁ¬½ÓÇëÇó,´Ó¶øµ¼ÖÂconntrackÖÐorigin_tupleµÄsrc_ipΪÍⲿ¿Í»§¶Ë,½ö½öͨ¹ýipµØÖ· + * À´ÅжÏÔ­·½ÏòºÍ·´·½Ïò,ÎÞ·¨×¼È·Åжϳö¶ÔÓÚÄÚ²¿±»ÏÞËٵĿͻ§¶ËÀ´ËµÊÇÉÏÐÐÁ÷Á¿»¹ÊÇÏÂÐÐÁ÷Á¿,´Ó¶øµ¼ÖÂSFEÒÀÈ» + * ʹÓÃʵ¼ÊÏÂÐÐÁ÷Á¿´´½¨SFE¿ìËÙת·¢¹æÔò,µ«ÏÂÐÐÊý¾Ý°üûÓÐÌí¼ÓÕë¶Ô¿Í»§¶ËµÄMark±ê¼Ç,´Ó¶øµ¼ÖÂÏÞËÙÎÞ·¨ÉúЧ. + * ½â¾ö·½Ê½: 1. ɾ³ýÔ­±¾Õë¶ÔSpeedTestµÄÐÞ¸Ä; + * 2. ÔÚ´´½¨SFEת·¢¹æÔò֮ǰ¶ÔskbÖеÄmark±ê¼Ç½øÐÐÅжÏ,Èç¹û°üº¬wan2lan±ê¼Ç(0x00008000),Ôò˵Ã÷¸ÃÊý¾Ý°ü + * ΪÏÂÐÐÊý¾Ý°ü,²»´´½¨¹æÔò²¢½«Æä·µ»Ø¸øЭÒéÕ»; + */ + DEBUG_TRACE("%s: sic.src_dev->name = %s\n", __FUNCTION__, sic.src_dev->name); + DEBUG_TRACE("%s: skb->mark = 0x%x\n", __FUNCTION__, skb->mark); + if (skb->mark & MASK_FOR_WAN2LAN) + { + DEBUG_TRACE("%s: Download link package, ignore it.\n", __FUNCTION__); + return NF_ACCEPT; + } + //[zhangguosong end] + sic.src_mtu = src_dev_use->mtu; sic.dest_mtu = dest_dev_use->mtu; + //[zhangguosong start] 2018-05-08 get mark + sic.mark = ct->mark; + sic.mark |= (skb->mark & 0x8FFF); + //sic.mark |= skb->mark; + //[zhangguosong end] + if (likely(is_v4)) { if (sfe_ipv4_create_rule(&sic) == 0) { ct->sfe_entry = (void *)(&sic); @@ -1008,6 +1053,50 @@ static ssize_t sfe_cm_get_exceptions(struct device *dev, */ static const struct device_attribute sfe_cm_exceptions_attr = __ATTR(exceptions, S_IRUGO, sfe_cm_get_exceptions, NULL); +#ifdef TP_FEATURE_CLOUD +int do_sfe_cloud_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) +{ + int ret = 0; + int status = 1; + printk("%s: hande msg: %d\n", __FUNCTION__, cmd); + + switch(cmd) + { + case SFE_ENABLE_CLOUD_BLCOK: + if (NULL == user || len != 4) + { + printk("%s: invalid params.", __FUNCTION__); + ret = -1; + break; + } + copy_from_user(&status, user, len); + printk("%s: sfe change cloud block status to %d.", __FUNCTION__, status); + sfe_update_enable_block_status(status); + break; + default: + DEBUG_ERROR("Receive an unknown set ctl command. cmd = %d\n", cmd); + ret = -1; + break; + } + return ret; +} + +int do_sfe_cloud_get_ctl(struct sock* sk, int cmd, void __user *user, int *len) +{ + return 0; +} + +static struct nf_sockopt_ops cloud_sockopts = { + .pf = PF_INET, + .set_optmin = SFE_CLOUD_BASE_CTL, + .set_optmax = SFE_CLOUD_SET_MAX+1, + .set = do_sfe_cloud_set_ctl, + .get_optmin = SFE_CLOUD_BASE_CTL, + .get_optmax = SFE_CLOUD_GET_MAX+1, + .get = do_sfe_cloud_get_ctl, +}; +#endif + /* * sfe_cm_init() @@ -1056,7 +1145,16 @@ static int __init sfe_cm_init(void) DEBUG_ERROR("can't register nf post routing hook: %d\n", result); goto exit3; } +#ifdef TP_FEATURE_CLOUD + result = nf_register_sockopt(&cloud_sockopts); + if (result < 0) + { + DEBUG_ERROR("can't register nf sockopts for cloud: %d\n", result); + goto exit3; + } +#endif + printk("%s: sfe register sockopt success.", __FUNCTION__); spin_lock_init(&sc->lock); /* diff --git a/shortcut-fe/shortcut-fe/sfe_cm.h b/shortcut-fe/shortcut-fe/sfe_cm.h old mode 100644 new mode 100755 index dc939adbb..df4537cbd --- a/shortcut-fe/shortcut-fe/sfe_cm.h +++ b/shortcut-fe/shortcut-fe/sfe_cm.h @@ -15,6 +15,8 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + #include + /* * connection flags. */ @@ -27,6 +29,13 @@ #define SFE_SUPPORT_IPV6 #endif + +//for test +#ifndef TP_FEATURE_WLANTC +#define TP_FEATURE_WLANTC +#endif + + /* * IPv6 address structure */ @@ -165,6 +174,29 @@ struct sfe_connection_mark { uint32_t mark; }; + +#ifdef TP_FEATURE_CLOUD +#define SFE_CLOUD_BASE_CTL 512 +#define SFE_ENABLE_CLOUD_BLCOK (SFE_CLOUD_BASE_CTL) +#define SFE_CLOUD_SET_MAX (SFE_ENABLE_CLOUD_BLCOK) +#define SFE_CLOUD_GET_MAX (SFE_CLOUD_BASE_CTL) +#endif + + +//[zhangguosong start] +#ifdef TP_FEATURE_WLANTC +#define MAX_TC_RULES_NUM 20 + +/* + * brief: this marco is used to mark the download packet(from WAN to LAN) + */ +#define MASK_FOR_WAN2LAN 0X00008000 + +static DEFINE_SPINLOCK(tc_lock); +#endif +//[zhangguosong end] + + /* * Type used for a sync rule callback. */ @@ -181,6 +213,10 @@ extern void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t callba extern void sfe_ipv4_update_rule(struct sfe_connection_create *sic); extern void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark); +#ifdef TP_FEATURE_CLOUD +extern void sfe_update_enable_block_status(int status); +#endif + #ifdef SFE_SUPPORT_IPV6 /* * IPv6 APIs used by connection manager diff --git a/shortcut-fe/shortcut-fe/sfe_ipv4.c b/shortcut-fe/shortcut-fe/sfe_ipv4.c old mode 100644 new mode 100755 index 3c535ea5d..499de7dd5 --- a/shortcut-fe/shortcut-fe/sfe_ipv4.c +++ b/shortcut-fe/shortcut-fe/sfe_ipv4.c @@ -35,7 +35,7 @@ int var_thresh = PKT_THRESHOLD; int skip_mtu_check = 1; int threshold_count; int timeout_count; - +int enable_cloud_block = 0; #define XDBG_ADD_PROC_ENTRY(it, name, xdata) \ { \ .procname = (name), \ @@ -543,6 +543,7 @@ typedef bool (*sfe_ipv4_debug_xml_write_method_t)(struct sfe_ipv4 *si, char *buf struct sfe_ipv4 __si; + /* When the timer expires this callback function is called*/ void sfe_timer_callback(unsigned long data) { @@ -1250,6 +1251,12 @@ static void sfe_ipv4_flush_sfe_ipv4_connection(struct sfe_ipv4 *si, struct sfe_i kfree(c); } +//[zhangguosong start] 2018-05-10 Export sfe_stat_cb function to ipt-stat to record stat +int (*sfe_stat_cb)(struct sk_buff *skb) __rcu __read_mostly; +EXPORT_SYMBOL_GPL(sfe_stat_cb); +//[zhangguosong end] + + /* * sfe_ipv4_recv_udp() * Handle UDP packet receives and forwarding. @@ -1265,11 +1272,21 @@ static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne struct sfe_ipv4_connection_match *cm; uint8_t ttl; struct net_device *xmit_dev; + + int (*stat_cb)(struct sk_buff *skb); + struct sk_buff *new_skb ; int k; const struct net_device_ops *ops; int queue_index = 0; struct sfe_ipv4_connection *c; + + //[zhangguosong start] +#ifdef TP_FEATURE_WLANTC + struct sfe_ipv4_connection_match *counter_cm; + int idx = 0; +#endif + //[zhangguosong end] /* * Is our packet too short to contain a valid UDP header? */ @@ -1397,6 +1414,15 @@ static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne if (unlikely(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) { uint16_t udp_csum; + //[zhangguosong start] 2018-05-10 update stats in ipt-stat + stat_cb = rcu_dereference(sfe_stat_cb); + if (stat_cb) { + if (NF_DROP == stat_cb(skb)) { /* if ipt-stat return NF_DROP, it means reach limit data-usaged */ + return 0; + } + } + //[zhangguosong end] + iph->saddr = cm->xlate_src_ip; udph->source = cm->xlate_src_port; @@ -1445,8 +1471,35 @@ static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne sum = (sum & 0xffff) + (sum >> 16); udph->check = (uint16_t)sum; } + + //[zhangguosong start] 2018-05-10 update stats in ipt-stat + stat_cb = rcu_dereference(sfe_stat_cb); + if (stat_cb) { + if (NF_DROP == stat_cb(skb)) { + return 0; + } + } + //[zhangguosong end] } + //[zhangguosong start] 2018-05-10 Move from MR6400V3 + /** + * add by wuchao, 18.03.21, fix bug#215239. + * topology: lan pc - vpn server on dut - vpn client on wan pc + * no need to do SNAT & DNAT + */ + if (unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) && + unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST))) + { + stat_cb = rcu_dereference(sfe_stat_cb); + if (stat_cb) { + if (NF_DROP == stat_cb(skb)) { + return 0; + } + } + } + //[zhangguosong end] + /* * Replace the IP checksum. */ @@ -1509,7 +1562,13 @@ static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne /* * Mark outgoing packet. */ - skb->mark = cm->connection->mark; + DEBUG_TRACE("%s: cm->connection->mark = 0x%x\n", __FUNCTION__, cm->connection->mark); + if (cm->connection->mark != 0) { + skb->mark = skb->mark | cm->connection->mark /*| MASK_FOR_WAN2LAN*/; + DEBUG_TRACE("%s: skb-mark = 0x%x", __FUNCTION__, skb->mark); + } + + //skb->mark = cm->connection->mark; if (skb->mark) { DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); } @@ -1680,7 +1739,15 @@ static bool sfe_ipv4_process_tcp_option_sack(const struct sfe_ipv4_tcp_hdr *th, return true; } - +#ifdef TP_FEATURE_CLOUD +void sfe_update_enable_block_status(int status) +{ + struct sfe_ipv4 *si = &__si; + spin_lock_bh(&si->lock); + enable_cloud_block = status; + spin_unlock_bh(&si->lock); +} +#endif /* * sfe_ipv4_recv_tcp() * Handle TCP packet receives and forwarding. @@ -1698,11 +1765,15 @@ static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne uint8_t ttl; uint32_t flags; struct net_device *xmit_dev; + + int (*stat_cb)(struct sk_buff *skb); + struct sk_buff *new_skb ; int k; const struct net_device_ops *ops; int queue_index = 0; struct sfe_ipv4_connection *c; + int idx = 0; //[zhangguosong add] /* * Is our packet too short to contain a valid UDP header? @@ -1732,6 +1803,21 @@ static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne spin_lock_bh(&si->lock); +// [ lxw start] +#ifdef TP_FEATURE_CLOUD + if (enable_cloud_block == 1) + { + if (ntohs(src_port) == 80 || ntohs(dest_port) == 80) + { + si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UNHANDLED_PROTOCOL]++; + si->packets_not_forwarded++; + spin_unlock_bh(&si->lock); + DEBUG_TRACE("Enable to tip cloud upgrade, not forward http packet\n"); + return 0; + } + } +#endif + // [lxw end] /* * Look for a connection match. */ @@ -2022,6 +2108,15 @@ static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne uint16_t tcp_csum; uint32_t sum; + //[zhangguosong start] 2018-05-10 Update stats in ipt-stat + stat_cb = rcu_dereference(sfe_stat_cb); + if (stat_cb) { + if (NF_DROP == stat_cb(skb)) { + return 0; + } + } + //[zhangguosong end] + iph->saddr = cm->xlate_src_ip; tcph->source = cm->xlate_src_port; @@ -2063,8 +2158,30 @@ static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne sum = (sum & 0xffff) + (sum >> 16); tcph->check = (uint16_t)sum; + + //[zhangguosong start] 2018-05-10 Update stats in ipt-stat + stat_cb = rcu_dereference(sfe_stat_cb); + if (stat_cb) { + if (NF_DROP == stat_cb(skb)) { + return 0; + } + } + //[zhangguosong end] } + //[zhangguosong start] 2018-05-10 Move from MR6400V3 + if (unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_SRC)) && + unlikely(!(cm->flags & SFE_IPV4_CONNECTION_MATCH_FLAG_XLATE_DEST))) + { + stat_cb = rcu_dereference(sfe_stat_cb); + if (stat_cb) { + if (NF_DROP == stat_cb(skb)) { + return 0; + } + } + } + //[zhangguosong end] + /* * Replace the IP checksum. */ @@ -2127,7 +2244,12 @@ static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne /* * Mark outgoing packet */ - skb->mark = cm->connection->mark; + DEBUG_TRACE("%s: cm->connection->mark = 0x%x\n", __FUNCTION__, cm->connection->mark); + if (cm->connection->mark != 0) { + skb->mark = skb->mark | cm->connection->mark/* | MASK_FOR_WAN2LAN*/; + DEBUG_TRACE("%s: skb->mark = 0x%x\n", __FUNCTION__, skb->mark); + } + // skb->mark = cm->connection->mark; if (skb->mark) { DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); } @@ -3850,6 +3972,9 @@ EXPORT_SYMBOL(sfe_ipv4_update_rule); EXPORT_SYMBOL(sfe_register_flow_cookie_cb); EXPORT_SYMBOL(sfe_unregister_flow_cookie_cb); #endif +#ifdef TP_FEATURE_CLOUD +EXPORT_SYMBOL(sfe_update_enable_block_status); +#endif MODULE_AUTHOR("Qualcomm Atheros Inc."); MODULE_DESCRIPTION("Shortcut Forwarding Engine - IPv4 edition"); diff --git a/shortcut-fe/shortcut-fe/sfe_ipv6.c b/shortcut-fe/shortcut-fe/sfe_ipv6.c old mode 100644 new mode 100755 index e30b9b60a..b730fe328 --- a/shortcut-fe/shortcut-fe/sfe_ipv6.c +++ b/shortcut-fe/shortcut-fe/sfe_ipv6.c @@ -29,6 +29,8 @@ #define PKT_THRESHOLD 10 #define TIMEOUT 100 +#define __OPEN_SUPPORT__IPV6__ 1 + struct sfe_wlan_aggr_params aggr_params[MAX_WLAN_INDEX]; int var_timeout = TIMEOUT; @@ -1315,6 +1317,9 @@ static void sfe_ipv6_flush_connection(struct sfe_ipv6 *si, struct sfe_ipv6_conne kfree(c); } +int (*sfe_ipv6_stat_cb)(struct sk_buff *skb) __rcu __read_mostly; +EXPORT_SYMBOL_GPL(sfe_ipv6_stat_cb); + /* * sfe_ipv6_recv_udp() * Handle UDP packet receives and forwarding. @@ -1334,6 +1339,8 @@ static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne int queue_index = 0; struct sfe_ipv6_connection *c; + int (*stat_cb)(struct skb_buff *skb); + /* * Is our packet too short to contain a valid UDP header? */ @@ -1456,6 +1463,19 @@ static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne if (unlikely(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC)) { uint16_t udp_csum; + //[zhangguosong add] 2018-06-26 +#if __OPEN_SUPPORT__IPV6__ + stat_cb = rcu_dereference(sfe_ipv6_stat_cb); + if (stat_cb) + { + if (NF_DROP == stat_cb(skb)) + { + return 0; + } + } +#endif + //[zhangguosong end] + iph->saddr = cm->xlate_src_ip[0]; udph->source = cm->xlate_src_port; @@ -1490,8 +1510,36 @@ static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne sum = (sum & 0xffff) + (sum >> 16); udph->check = (uint16_t)sum; } + + //[zhangguosong add] 2016-06-26 +#if __OPEN_SUPPORT__IPV6__ + stat_cb = rcu_dereference(sfe_ipv6_stat_cb); + if (stat_cb) + { + if (NF_DROP == stat_cb(skb)) + { + return 0; + } + } +#endif + //[zhangguosong end] } +#if __OPEN_SUPPORT_IPV6__ + if (unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC)) && + unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST))) + { + stat_cb = rcu_dereference(sfe_ipv6_stat_cb); + if (stat_cb) + { + if (NF_DROP == stat_cb(skb)) + { + return 0; + } + } + } +#endif + /* * Update traffic stats. */ @@ -1548,9 +1596,15 @@ static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne /* * Mark outgoing packet. */ - skb->mark = cm->connection->mark; + DEBUG_TRACE("%s: cm->connection->mark = 0x%x\n", __FUNCTION__, cm->connection->mark); + if (0 != cm->connection->mark) + { + skb->mark = skb->mark | cm->connection->mark; + DEBUG_TRACE("%s: skb->mark = 0x%x\n", __FUNCTION__, skb->mark); + } + if (skb->mark) { - DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + DEBUG_TRACE("%s: SKB MARK is NON ZERO %x\n", __FUNCTION__, skb->mark); } #endif @@ -1741,6 +1795,8 @@ static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne int queue_index = 0; struct sfe_ipv6_connection *c; + int (*stat_cb)(struct skb_buff *skb); + /* * Is our packet too short to contain a valid UDP header? */ @@ -2055,6 +2111,19 @@ static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne uint16_t tcp_csum; uint32_t sum; + //[zhangguosong start] 2018-06-26 +#if __OPEN_SUPPORT__IPV6__ + stat_cb = rcu_dereference(sfe_ipv6_stat_cb); + if (stat_cb) + { + if (NF_DROP == stat_cb(skb)) + { + return 0; + } + } +#endif + //[zhangguosong end] + iph->saddr = cm->xlate_src_ip[0]; tcph->source = cm->xlate_src_port; @@ -2086,8 +2155,38 @@ static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne sum = tcp_csum + cm->xlate_dest_csum_adjustment; sum = (sum & 0xffff) + (sum >> 16); tcph->check = (uint16_t)sum; + + //[zhangguosong start] 2018-06-27 +#if __OPEN_SUPPORT__IPV6__ + stat_cb = rcu_dereference(sfe_ipv6_stat_cb); + if (stat_cb) + { + if (NF_DROP == stat_cb(skb)) + { + return 0; + } + } +#endif + //[zhangguosong end] } + //[zhangguosong start] 2018-06-26 +#if __OPEN_SUPPORT__IPV6__ + if (unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC)) && + unlikely(!(cm->flags & SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST))) + { + stat_cb = rcu_dereference(sfe_ipv6_stat_cb); + if (stat_cb) + { + if (NF_DROP == stat_cb(skb)) + { + return 0; + } + } + } +#endif + //[zhangguosong end] + /* * Update traffic stats. */ @@ -2144,9 +2243,15 @@ static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne /* * Mark outgoing packet */ - skb->mark = cm->connection->mark; + DEBUG_TRACE("%s: cm->connection->mark = 0x%x\n", __FUNCTION__, cm->connection->mark); + if (0 != cm->connection->mark) + { + skb->mark = skb->mark | cm->connection->mark; + DEBUG_TRACE("%s: skb->mark = 0x%x\n", __FUNCTION__, skb->mark); + } + if (skb->mark) { - DEBUG_TRACE("SKB MARK is NON ZERO %x\n", skb->mark); + DEBUG_TRACE("%s: SKB MARK is NON ZERO %x\n", __FUNCTION__, skb->mark); } #endif diff --git a/system/core/liblog/logprint.c b/system/core/liblog/logprint.c old mode 100644 new mode 100755 index 4149c43db..d4a6a74c2 --- a/system/core/liblog/logprint.c +++ b/system/core/liblog/logprint.c @@ -359,6 +359,11 @@ int android_log_processLogBuffer(struct logger_entry *buf, entry->tid = buf->tid; entry->tag = buf->msg + 1; tag_len = strlen(entry->tag); + if(buf->len < (tag_len + 3)) + { + + return -1; + } entry->messageLen = buf->len - tag_len - 3; entry->message = entry->tag + tag_len + 1; diff --git a/tp-product/m7350v5/build/modules_image.inc b/tp-product/m7350v6/build/modules_image.inc similarity index 85% rename from tp-product/m7350v5/build/modules_image.inc rename to tp-product/m7350v6/build/modules_image.inc index cb8a4de04..5f7cd8eaa 100755 --- a/tp-product/m7350v5/build/modules_image.inc +++ b/tp-product/m7350v6/build/modules_image.inc @@ -1,21 +1,25 @@ # Packages installed to the root file system -IMAGE_INSTALL += "tp-domain" - -IMAGE_INSTALL += "uci" -IMAGE_INSTALL += "data-manager" - -IMAGE_INSTALL += "npd6" -IMAGE_INSTALL += "radvd" -IMAGE_INSTALL += "wide-dhcpv6" IMAGE_INSTALL += "libcjson" -IMAGE_INSTALL += "cgic" -IMAGE_INSTALL += "libghttp" +IMAGE_INSTALL += "uci" + +IMAGE_INSTALL += "npd6" + +IMAGE_INSTALL += "radvd" + +IMAGE_INSTALL += "wide-dhcpv6" IMAGE_INSTALL += "samba" + IMAGE_INSTALL += "bftpd" + IMAGE_INSTALL += "ntfs-3g" -IMAGE_INSTALL += "lighttpd" +IMAGE_INSTALL += "tp-domain" + +IMAGE_INSTALL += "cgic" + +IMAGE_INSTALL += "libghttp" + diff --git a/tp-product/m7350v5/build/product.config b/tp-product/m7350v6/build/product.config similarity index 94% rename from tp-product/m7350v5/build/product.config rename to tp-product/m7350v6/build/product.config index 6f95f35f2..72a7365d6 100755 --- a/tp-product/m7350v5/build/product.config +++ b/tp-product/m7350v6/build/product.config @@ -2,13 +2,13 @@ # Product configuration for TP-Link ################################################################################ BOARD_TYPE="mdm9207" -PRODUCT_TYPE="m7350-eu-v5" -PRODUCT_ID="73500005" -PRODUCT_NAME="M7350(EU) 5.0" +PRODUCT_TYPE="m7350-eu-v6" +PRODUCT_ID="73502006" +PRODUCT_NAME="M7350(EU) 6.2" PRODUCT_SERIES="M7350" -PRODUCT_VER="5.0.0" +PRODUCT_VER="6.2.0" PRODUCT_REGION="EU" -PRODUCT_TPNAME="m7350v5" +PRODUCT_TPNAME="m7350v6" ################################################################################ @@ -54,7 +54,7 @@ WIRELESS_WPS_DISABLE="n" WIRELESS_5G_DISABLE="y" WIRELESS_ADAPTIVITY_ENABLE="n" TP_WIRELESS_PASSPHRASE_ON_OLED="y" -TP_FEATURE_RTL8192ES="n" +TP_FEATURE_RTL8192ES="y" TP_FEATURE_QCACLD="n" #------------------------------------------------------------------------------- diff --git a/tp-product/m7350v5/config/product b/tp-product/m7350v6/config/product similarity index 92% rename from tp-product/m7350v5/config/product rename to tp-product/m7350v6/config/product index de6115158..0ae70106d 100755 --- a/tp-product/m7350v5/config/product +++ b/tp-product/m7350v6/config/product @@ -3,17 +3,18 @@ ################################################################################ config product info option board_type "mdm9207" - option product_type "m7350-eu-v5" - option product_id "73500005" + option product_type "m7350-eu-v6" + option product_id "73502006" option product_name "M7350" - option hardware_ver "5.0" - option firmware_ver "1.0.5" + option hardware_ver "7.0" + option firmware_ver "7.0.4" option firmware_ver_build "Build 000000 Rel.0000n" option product_region "EU" option product_series "M7350" - option vendor_name "TP-Link Technologies Co., Ltd." + option vendor_name "TP-Link Corporation Limited." option ssid_prefix "TP-Link_" + ################################################################################ # Feature configuration #------------------------------------------------------------------------------- diff --git a/tp-product/m7350v5/kernel/kernel_diff.patch b/tp-product/m7350v6/kernel/kernel_diff.patch old mode 100644 new mode 100755 similarity index 84% rename from tp-product/m7350v5/kernel/kernel_diff.patch rename to tp-product/m7350v6/kernel/kernel_diff.patch index 5ecddb337..7e5a50f4c --- a/tp-product/m7350v5/kernel/kernel_diff.patch +++ b/tp-product/m7350v6/kernel/kernel_diff.patch @@ -5,7 +5,7 @@ index 698a935..ef0170b 100644 @@ -45,6 +45,10 @@ status = "ok"; }; - + +&spi_5 { + status = "ok"; +}; @@ -38,12 +38,12 @@ index 6674491..4deed09 100644 + status = "ok"; +}; diff --git a/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi b/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi -index 5e6d2f2..0301f63 100644 +index 5e6d2f2..9498828 100644 --- a/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi -@@ -27,6 +27,17 @@ +@@ -27,6 +27,18 @@ }; - + &soc { + mp2617 { + cell-index = <0>; @@ -55,18 +55,19 @@ index 5e6d2f2..0301f63 100644 + mps,chg-m0-gpio = <&tlmm_pinmux 26 0>; + mps,ac-ok-gpio = <&tlmm_pinmux 4 0>; + qcom,client-vadc = <&pm8019_vadc>; ++ status = "disabled"; + }; }; - + &blsp1_uart5 { -@@ -36,10 +47,14 @@ +@@ -36,10 +48,14 @@ }; - + &i2c_4 { - status = "ok"; + status = "disabled"; }; - + &spi_1 { + status = "disabled"; +}; @@ -74,11 +75,11 @@ index 5e6d2f2..0301f63 100644 +&spi_5 { status = "ok"; }; - -@@ -55,14 +70,15 @@ + +@@ -55,14 +71,15 @@ status = "ok"; }; - + -/* MPP pin 2 configs for SMB358 interrupt line */ +/* MPP pin 2 configs for MP2617 interrupt line */ &pm8019_mpps { @@ -96,11 +97,11 @@ index 5e6d2f2..0301f63 100644 + qcom,invert = <1>; }; }; - -@@ -141,21 +157,21 @@ + +@@ -141,21 +158,21 @@ }; }; - + -&i2c_4 { +/*&i2c_4 { /* SMB358 charger configuration */ @@ -120,26 +121,26 @@ index 5e6d2f2..0301f63 100644 }; -}; +};*/ - + &sdhc_2 { vdd-supply = <&sdcard_ext_vreg>; -@@ -175,7 +191,7 @@ +@@ -175,7 +192,7 @@ 1 &intc 0 221 0 2 &tlmm_pinmux 26 0>; interrupt-names = "hc_irq", "pwr_irq", "status_irq"; - cd-gpios = <&tlmm_pinmux 26 0x1>; + /*cd-gpios = <&tlmm_pinmux 26 0x1>;*/ - + pinctrl-names = "active", "sleep"; pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; diff --git a/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi b/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi -index 6d4344b..7fce96d 100644 +index 6d4344b..285c284 100644 --- a/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi @@ -123,6 +123,68 @@ }; }; - + + spi5 { + + spi5_default: spi5_default { @@ -203,7 +204,7 @@ index 6d4344b..7fce96d 100644 + }; + /* SDC pin type */ - + pmx_sdc1_cmd { @@ -166,7 +228,7 @@ config { @@ -213,7 +214,7 @@ index 6d4344b..7fce96d 100644 + drive-strength = <16>; }; }; - + @@ -182,11 +244,11 @@ sdc1_wlan_gpio { sdc1_wlan_gpio_active: sdc1_wlan_gpio_active { @@ -229,7 +230,7 @@ index 6d4344b..7fce96d 100644 drive-strength = <8>; bias-pull-up; @@ -195,11 +257,11 @@ - + sdc1_wlan_gpio_sleep: sdc1_wlan_gpio_sleep { mux { - pins = "gpio38", "gpio25"; @@ -256,7 +257,7 @@ index 6d4344b..7fce96d 100644 drive-strength = <2>; bias-disable; }; -@@ -224,11 +286,11 @@ +@@ -224,17 +286,43 @@ i2c_4_sleep: i2c_4_sleep { /* suspended state */ mux { @@ -270,7 +271,39 @@ index 6d4344b..7fce96d 100644 drive-strength = <2>; bias-pull-down; }; -@@ -1013,5 +1075,32 @@ + }; + }; + ++ i2c_2 { ++ i2c_2_active: i2c_2_active { ++ mux { ++ pins = "gpio6", "gpio7"; ++ function = "blsp_i2c2"; ++ }; ++ config { ++ pins = "gpio6", "gpio7"; ++ drive-strength = <2>; ++ bias-pull-up; ++ }; ++ }; ++ ++ i2c_2_sleep: i2c_2_sleep { ++ mux { ++ pins = "gpio6", "gpio7"; ++ function = "blsp_i2c2"; ++ }; ++ config { ++ pins = "gpio6", "gpio7"; ++ drive-strength = <2>; ++ bias-pull-up; ++ }; ++ }; ++ }; ++ + codec_reset { + codec_reset_active: codec_reset_active { + mux { +@@ -1013,5 +1101,32 @@ output-low; }; }; @@ -304,7 +337,7 @@ index 6d4344b..7fce96d 100644 }; }; diff --git a/arch/arm/boot/dts/qcom/mdm9607.dtsi b/arch/arm/boot/dts/qcom/mdm9607.dtsi -index 1a9e273..ab5fdd1 100644 +index 1a9e273..ac96a27 100644 --- a/arch/arm/boot/dts/qcom/mdm9607.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9607.dtsi @@ -36,13 +36,14 @@ @@ -314,14 +347,14 @@ index 1a9e273..ab5fdd1 100644 - reg = <0x82a00000 0x5000000>; + reg = <0x82a00000 0x3600000>; }; - + cnss_debug_mem: cnss_debug_region@0 { compatible = "removed-dma-pool"; no-map; reg = <0x87a00000 0x200000>; + status = "disabled"; }; - + external_image_mem: external_image_region@0 { @@ -56,6 +57,7 @@ reusable; @@ -330,33 +363,104 @@ index 1a9e273..ab5fdd1 100644 + status = "disabled"; }; }; - -@@ -68,6 +70,7 @@ + +@@ -68,7 +70,9 @@ smd36 = &smdtty_loopback; /* spi device */ spi1 = &spi_1; + spi5 = &spi_5; i2c4 = &i2c_4; ++ i2c2 = &i2c_2; // new charge IC: BQ25601 sdhc2 = &sdhc_2; /* SDC2 SD card slot */ }; -@@ -586,7 +589,7 @@ + +@@ -355,7 +359,7 @@ + dma_blsp1: qcom,sps-dma@7884000 { /* BLSP1 */ + #dma-cells = <4>; + compatible = "qcom,sps-dma"; +- reg = <0x7884000 0x2b000>; ++ reg = <0x7884000 0x23000>; + interrupts = <0 238 0>; + qcom,summing-threshold = <10>; + }; +@@ -519,6 +523,59 @@ + }; + }; + ++ /* refer to doc: 80-nu767-1 (qcom) & Documentation/devicetree/bindings/i2c/i2c-msm-v2.txt (kernel) */ ++ i2c_2: i2c@78b6000 { /* BLSP1 QUP1 */ ++ compatible = "qcom,i2c-msm-v2"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg-names = "qup_phys_addr"; ++ reg = <0x78b6000 0x1000>; ++ ++ interrupt-names = "qup_irq"; ++ interrupts = <0 96 0>; ++ ++ dmas = <&dma_blsp1 14 32 0x20000020 0x20>, ++ <&dma_blsp1 15 64 0x20000020 0x20>; ++ dma-names = "tx", "rx"; ++ ++ qcom,clk-freq-out = <100000>; // 100 KHz ++ qcom,clk-freq-in = <19200000>; ++ ++ clock-names = "iface_clk", "core_clk"; ++ clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>, ++ <&clock_gcc clk_gcc_blsp1_qup2_i2c_apps_clk>; ++ ++ pinctrl-names = "i2c_active", "i2c_sleep"; ++ pinctrl-0 = <&i2c_2_active>; ++ pinctrl-1 = <&i2c_2_sleep>; ++ ++ qcom,noise-rjct-scl = <0>; ++ qcom,noise-rjct-sda = <0>; ++ qcom,fs-clk-div = <96>; ++ qcom,high-time-clk-div = <90>; ++ qcom,master-id = <86>; ++ ++ bq25601: bq25601-charger@6b { ++ compatible = "ti,bq25601-charger"; ++ reg = <0x6b>; ++ ++ ti,irq-gpio = <&tlmm_pinmux 28 0>; ++ ti,chg-en-gpio = <&tlmm_pinmux 27 0>; ++ ti,chg-vbat-div = <3>; ++ qcom,chg-vadc = <&pm8019_vadc>; ++ }; ++ ++ sgm41513-charger@1a { ++ compatible = "ti,sgm41513-charger"; ++ reg = <0x1a>; ++ ++ ti,irq-gpio = <&tlmm_pinmux 28 0>; ++ ti,chg-en-gpio = <&tlmm_pinmux 27 0>; ++ ti,chg-vbat-div = <3>; ++ qcom,chg-vadc = <&pm8019_vadc>; ++ }; ++ }; ++ + blsp1_uart3: uart@78b1000 { + compatible = "qcom,msm-hsuart-v14"; + reg = <0x78b1000 0x200>, +@@ -586,7 +643,7 @@ <0x44 0x80 0x38 0x81 0x24 0x82 0x13 0x83 0xffffffff>; - + qcom,hsusb-otg-phy-type = <3>; /* SNPS Femto PHY */ - qcom,hsusb-otg-mode = <3>; /* OTG mode */ + qcom,hsusb-otg-mode = <1>; /* PERIPHERAL mode */ qcom,hsusb-otg-otg-control = <2>; /* PMIC control */ qcom,usbid-gpio = <&pm8019_mpps 1 0>; qcom,hsusb-log2-itc = <4>; -@@ -829,6 +832,7 @@ +@@ -829,6 +886,7 @@ sound-9330 { compatible = "qcom,mdm9607-audio-tomtom"; qcom,model = "mdm9607-tomtom-i2s-snd-card"; + status = "disabled"; - + qcom,audio-routing = "RX_BIAS", "MCLK", -@@ -1202,6 +1206,12 @@ +@@ -1202,6 +1260,12 @@ qcom,sensor-type = "adc"; qcom,sensor-name = "xo_therm_amux"; }; @@ -367,9 +471,9 @@ index 1a9e273..ab5fdd1 100644 + qcom,scaling-factor = <100>; + }; }; - + mitigation_profile0: qcom,limit_info-0 { -@@ -1346,7 +1356,7 @@ +@@ -1346,7 +1410,7 @@ reg = <0x4044000 0x19000>; interrupts = <0 29 1>; qcom,rx-ring-size = <32>; @@ -377,11 +481,11 @@ index 1a9e273..ab5fdd1 100644 + qcom,max-rx-mtu = <2048>; qcom,fast-shutdown; }; - -@@ -1396,6 +1406,49 @@ + +@@ -1396,6 +1460,51 @@ status = "disabled"; }; - + + spi_5: spi@78ba000 { /* BLSP1 QUP6 */ + compatible = "qcom,spi-qup-v2"; + #address-cells = <1>; @@ -415,20 +519,22 @@ index 1a9e273..ab5fdd1 100644 + }; + }; + -+ oled_s90319_pt { ++ oled_s90319_pt { + compatible = "qcom,oled_s90319_pt"; + qcom,oled-cs-gpio = <&tlmm_pinmux 22 0>; + qcom,oled-rsx-gpio = <&tlmm_pinmux 25 0>; + qcom,oled-reset-gpio = <&tlmm_pinmux 24 0>; + qcom,oled-vdd0-gpio = <&tlmm_pinmux 18 0>; + qcom,oled-vdd1-gpio = <&tlmm_pinmux 19 0>; -+ qcom,oled-boost-en-gpio = <&tlmm_pinmux 6 0>; ++ qcom,oled-mosi-gpio = <&tlmm_pinmux 20 0>; ++ qcom,oled-clk-gpio = <&tlmm_pinmux 23 0>; ++ qcom,oled-boost-en-gpio = <&tlmm_pinmux 4 0>; + }; + qcom,mss@4080000 { compatible = "qcom,pil-q6v55-mss"; reg = <0x04080000 0x100>, -@@ -1525,6 +1578,35 @@ +@@ -1525,6 +1634,35 @@ phy-addr = <0>; status = "disable"; }; @@ -462,24 +568,24 @@ index 1a9e273..ab5fdd1 100644 + }; + /* [yangjihong end] */ }; - + #include "mdm9607-rpm-regulator.dtsi" -@@ -1543,9 +1625,9 @@ +@@ -1543,9 +1681,9 @@ }; }; - + -&usb_otg { +/*&usb_otg { vbus_otg-supply = <&smb358_otg_vreg>; -}; +};*/ - + &pm8019_vadc { chan@6 { -@@ -1570,6 +1652,17 @@ +@@ -1570,6 +1708,17 @@ qcom,fast-avg-setup = <0>; }; - + + chan@11 { + label = "batt_voltage"; + reg = <0x11>; @@ -520,7 +626,7 @@ index d385ae6..e87ef38 100644 +CONFIG_TIMER_STATS=y +CONFIG_SUPPORT_RTL_SDIO3=y diff --git a/arch/arm/configs/mdm9607_defconfig b/arch/arm/configs/mdm9607_defconfig -index 1e33537..267a303 100644 +index 1e33537..2cbd806 100644 --- a/arch/arm/configs/mdm9607_defconfig +++ b/arch/arm/configs/mdm9607_defconfig @@ -1,21 +1,23 @@ @@ -582,10 +688,10 @@ index 1e33537..267a303 100644 CONFIG_NF_CONNTRACK_NETBIOS_NS=y CONFIG_NF_CONNTRACK_SNMP=y -CONFIG_NF_CONNTRACK_PPTP=y -+CONFIG_NF_CONNTRACK_PPTP=m -CONFIG_NF_CONNTRACK_SIP=y -+CONFIG_NF_CONNTRACK_SIP=m -CONFIG_NF_CONNTRACK_TFTP=y ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m CONFIG_NF_CT_NETLINK=y CONFIG_NF_CT_NETLINK_TIMEOUT=y @@ -679,17 +785,20 @@ index 1e33537..267a303 100644 CONFIG_SERIAL_MSM_SMD=y CONFIG_DIAG_CHAR=y CONFIG_HW_RANDOM=y -@@ -225,7 +229,8 @@ CONFIG_GPIO_SYSFS=y +@@ -224,8 +228,10 @@ CONFIG_DEBUG_GPIO=y + CONFIG_GPIO_SYSFS=y CONFIG_GPIO_QPNP_PIN=y CONFIG_POWER_SUPPLY=y - CONFIG_SMB1351_USB_CHARGER=y +-CONFIG_SMB1351_USB_CHARGER=y -CONFIG_SMB358_CHARGER=y ++CONFIG_SMB1351_USB_CHARGER=n +CONFIG_SMB358_CHARGER=n -+CONFIG_MP2617_CHARGER=y ++CONFIG_MP2617_CHARGER=n ++CONFIG_BQ25601_CHARGER=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_MSM=y CONFIG_MSM_DLOAD_MODE=y -@@ -234,37 +239,37 @@ CONFIG_THERMAL=y +@@ -234,37 +240,37 @@ CONFIG_THERMAL=y CONFIG_THERMAL_TSENS8974=y CONFIG_THERMAL_MONITOR=y CONFIG_THERMAL_QPNP_ADC_TM=y @@ -753,7 +862,7 @@ index 1e33537..267a303 100644 CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DEBUG_FILES=y -@@ -274,7 +279,6 @@ CONFIG_USB_CI13XXX_MSM=y +@@ -274,7 +280,6 @@ CONFIG_USB_CI13XXX_MSM=y CONFIG_USB_CI13XXX_MSM_HSIC=y CONFIG_USB_G_ANDROID=y CONFIG_MMC=y @@ -761,7 +870,7 @@ index 1e33537..267a303 100644 CONFIG_MMC_CLKGATE=y CONFIG_MMC_PARANOID_SD_INIT=y CONFIG_MMC_BLOCK_MINORS=32 -@@ -299,16 +303,15 @@ CONFIG_QPNP_REVID=y +@@ -299,16 +304,15 @@ CONFIG_QPNP_REVID=y CONFIG_SPS=y CONFIG_USB_BAM=y CONFIG_SPS_SUPPORT_NDP_BAM=y @@ -782,7 +891,7 @@ index 1e33537..267a303 100644 CONFIG_MSM_WATCHDOG_V2=y CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y CONFIG_MSM_RPM_LOG=y -@@ -332,20 +335,20 @@ CONFIG_MSM_PIL_MSS_QDSP6V5=y +@@ -332,20 +336,20 @@ CONFIG_MSM_PIL_MSS_QDSP6V5=y CONFIG_TRACER_PKT=y CONFIG_MSM_BAM_DMUX=y CONFIG_REMOTE_SPINLOCK_MSM=y @@ -817,7 +926,7 @@ index 1e33537..267a303 100644 CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_UBIFS_FS=y -@@ -354,27 +357,37 @@ CONFIG_NLS_CODEPAGE_437=y +@@ -354,27 +358,52 @@ CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y CONFIG_PRINTK_TIME=y @@ -875,3 +984,18 @@ index 1e33537..267a303 100644 +CONFIG_SUPPORT_RTL_SDIO3=y +#[wuchao add] modify pkt_threshold for rtl wifi +CONFIG_TP_FEATURE_RTL8192ES=y ++#[zhangguosong add start] ++CONFIG_NET_SCH_HTB=y ++CONFIG_NET_SCH_SFQ=y ++CONFIG_NET_SCH_FIFO=y ++CONFIG_NET_CLS=y ++CONFIG_NET_CLS_FW=y ++CONFIG_NET_CLS_U32=y ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_MIRRED=y ++CONFIG_BRIDGE_EBT_MARK=y ++CONFIG_BRIDGE_EBT_VLAN=y ++CONFIG_BRIDGE_EBT_FTOS=y ++CONFIG_BRIDGE_EBT_MARK_T=y ++CONFIG_IFB=y ++#[zhangguosong add end] diff --git a/tp-proprietary/tp-domain/Makefile b/tp-proprietary/tp-domain/Makefile new file mode 100644 index 000000000..8e8493cd3 --- /dev/null +++ b/tp-proprietary/tp-domain/Makefile @@ -0,0 +1,16 @@ +# If KERNELRELEASE is defined, we've been invoked from the +# kernel build system and can use its language. + +obj-m += tp_domain.o + +PWD := $(shell pwd) + +all: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules + +modules_install: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules_install + +.PHONY:clean +clean: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean diff --git a/tp-proprietary/tp-domain/tp_domain.c b/tp-proprietary/tp-domain/tp_domain.c new file mode 100755 index 000000000..22530e02d --- /dev/null +++ b/tp-proprietary/tp-domain/tp_domain.c @@ -0,0 +1,1111 @@ +/****************************************************************************** +* +* Copyright (c) 2013 TP-LINK Technologies CO.,LTD. +* All rights reserved. +* +* FILE NAME : tp_domain.c +* VERSION : 1.0 +* DESCRIPTION: ´¦Àí·ÓÉÆ÷Ò³ÃæµÄÓòÃûµÇ¼. +* +* AUTHOR : wangbing +* CREATE DATE: 27/02/2013 +* +* HISTORY : +* 2013-02-27 wangbing revised for adsl router. +* This file is originally created by huangwenzhong . +* +* +******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) +#include <../net/bridge/br_private.h> +#endif +#include +#include "./tp_domain.h" +#ifdef INCLUDE_DOMAIN_INTERCEPT +#include "./domain_intercept.h" +#endif /*INCLUDE_DOMAIN_INTERCEPT*/ + + +#define MAX_LAN_DOMAIN_LEN (64) +#define DOT_CHAR '.' +#define IPV6_HDR_LEN 40 + +static __u32 lan_ip = 0xc0a80001; /* default value */ +#if defined(CONFIG_TP_MODEL_MR400V1) +static char *lan_domain = "tplinkmodem.net"; +#else +static char *lan_domain = "tplinkmifi.net"; +#if 0 +#define DOMAIN_NUMBER (2) +#define DOMAIN_LENGTH (32) +static char lan_domain[DOMAIN_NUMBER][DOMAIN_LENGTH] = {"tplinklogin.net", "tplinkwifi.net"}; +#endif +#endif + +static unsigned short lan_ip6[] = {0xfe80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}; + +module_param( lan_ip, uint, 0 ); +module_param(lan_domain, charp, 0); + +#if 1 +static char query[MAX_LAN_DOMAIN_LEN] = {0}; + + +#define DNS_QUERY_LEN (strlen(query)) +#define DNS_DATA_LEN (DNS_QUERY_LEN + 1 + 4 + 16) + +#else +static char query[DOMAIN_NUMBER][MAX_LAN_DOMAIN_LEN] = {0}; + +int DNS_QUERY_LEN[DOMAIN_NUMBER]; +int DNS_HIT_NUMBER = 0; +#define DNS_DATA_LEN (DNS_QUERY_LEN[DNS_HIT_NUMBER] + 1 + 4 + 16); +#endif + +static void parse_domain(void) +{ +#if 1 + char *pstr = NULL; + char *tmp = query; + + strncpy(query + 1, lan_domain, MAX_LAN_DOMAIN_LEN - 1); + + pstr = strchr(tmp + 1, DOT_CHAR); + while (NULL != pstr) + { + *tmp = pstr - tmp - 1; + tmp = pstr; + pstr = strchr(tmp + 1, DOT_CHAR); + } + + *tmp = strlen(query) - (tmp - query) - 1; + + return; + +#else + char *pstr = NULL; + char *tmp = NULL; + int i = 0; + int len = 0; + + for (i=0; i +* DESCRIPTION : ÓÃÓÚ»ñÈ¡´«Èëdev¶ÔÓ¦½Ó¿ÚµÄIPv6µØÖ·, ½öÖ¸»ñÈ¡Á´Â·±¾µØµØÖ·(ÒÔfe80::¿ªÍ·µÄ) +* INPUT : dev - »ñÈ¡µØÖ·Ëù´¦µÄ½Ó¿Ú¶ÔÓ¦µÄinet6_devÉ豸 +* OUTPUT : addr - ´æ´¢IPv6µØÖ·µÄÄÚ´æ +* RETURN : N/A +* OTHERS : Èç¹ûûÓÐÇŽӿÚ,Ö±½Ó»ñÈ¡µ±Ç°µÄµØÖ·.·ñÔò»ñÈ¡ÇÅÏÂÃæµÚÒ»¸öportµÄµØÖ· +******************************************************************************/ +static inline void get_idev_ip6_addr(struct inet6_dev *idev, struct in6_addr *addr) +{ + struct inet6_ifaddr *ifa = NULL; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) ) + struct list_head *p = NULL; + if (idev) + { + /* + * Each device address list is sorted in order of scope - + * global before linklocal. + */ + + list_for_each(p, &idev->addr_list) + { + ifa = list_entry(p, struct inet6_ifaddr, if_list); + if (ifa->addr.s6_addr[0] == 0xFE && ifa->addr.s6_addr[1] == 0x80) + { + //get the link local address for this port + memcpy(addr->s6_addr, ifa->addr.s6_addr, 16); + return; + } + } + } +#else + if (idev) + { + for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) + { + if (ifa->addr.s6_addr[0] == 0xFE && ifa->addr.s6_addr[1] == 0x80) + { + //get the link local address for this port + memcpy(addr->s6_addr, ifa->addr.s6_addr, 16); + return; + } + } + } +#endif + return; +} + +/****************************************************************************** +* FUNCTION : get_dev_ip6_addr() +* AUTHOR : chenming +* DESCRIPTION : ÓÃÓÚ»ñÈ¡´«Èëdev¶ÔÓ¦½Ó¿ÚµÄIPv6µØÖ·, ½öÖ¸»ñÈ¡Á´Â·±¾µØµØÖ·(ÒÔfe80::¿ªÍ·µÄ) +* INPUT : dev - »ñÈ¡µØÖ·Ëù´¦µÄ½Ó¿Ú¶ÔÓ¦µÄÍøÂçÉ豸 +* OUTPUT : addr - ´æ´¢IPv6µØÖ·µÄÄÚ´æ +* RETURN : N/A +* OTHERS : Èç¹ûûÓÐÇŽӿÚ,Ö±½Ó»ñÈ¡µ±Ç°µÄµØÖ·.·ñÔò»ñÈ¡ÇÅÏÂÃæµÚÒ»¸öportµÄµØÖ· +******************************************************************************/ +static inline void get_dev_ip6_addr(struct net_device *dev, struct in6_addr *addr) +{ + struct inet6_dev * in6_dev = NULL; + struct net_bridge_port * br_port = NULL; + if(dev) + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) + if (!br_port_exists(dev) && dev->ip6_ptr) + { + in6_dev = (struct inet6_dev*)dev->ip6_ptr; + get_idev_ip6_addr(in6_dev, addr); + return; + } + br_port = br_port_get_rcu(dev); +#else + br_port = dev->br_port; +#endif + + if(br_port && br_port->br && br_port->br->dev) + { + in6_dev = (struct inet6_dev*)br_port->br->dev->ip6_ptr; + get_idev_ip6_addr(in6_dev, addr); + } + } +} + +/****************************************************************************** +* FUNCTION : get_dev_ip_addr() +* AUTHOR : chenming +* DESCRIPTION : ÓÃÓÚ»ñÈ¡´«Èëdev¶ÔÓ¦½Ó¿ÚµÄIPv4µØÖ· +* INPUT : dev - »ñÈ¡µØÖ·Ëù´¦µÄ½Ó¿Ú¶ÔÓ¦µÄÍøÂçÉ豸 +* OUTPUT : addr - ´æ´¢IPv4µØÖ·µÄÄÚ´æ +* RETURN : N/A +* OTHERS : Èç¹ûûÓÐÇŽӿÚ,Ö±½Ó»ñÈ¡µ±Ç°µÄµØÖ·.·ñÔò»ñÈ¡ÇÅÏÂÃæµÚÒ»¸öportµÄµØÖ· +******************************************************************************/ +static inline void get_dev_ip_addr(struct net_device *dev, __u32 *addr) +{ + struct in_device *in_dev; + struct net_bridge_port *br_port; + struct in_ifaddr *ifap = NULL; + if(dev) + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) + if (!br_port_exists(dev) && dev->ip_ptr) + { + in_dev = (struct in_device *)dev->ip_ptr; + if(in_dev) + { + ifap = in_dev->ifa_list; + while(ifap != NULL) + { + if (!strcmp(ifap->ifa_label, dev->name)) + break; + ifap = ifap->ifa_next; + } + if (ifap != NULL) + { + *addr = ifap->ifa_local; + } + } + return; + } + + br_port = br_port_get_rcu(dev); +#else + br_port = dev->br_port; +#endif + if(br_port && br_port->br && br_port->br->dev && br_port->br->dev->ip_ptr) + { + in_dev = (struct in_device *)br_port->br->dev->ip_ptr; + ifap = in_dev->ifa_list; + while(ifap != NULL) + { + if (!strcmp(ifap->ifa_label, br_port->br->dev->name)) + break; + ifap = ifap->ifa_next; + } + *addr = ifap->ifa_local; + } + } + return; +} + +/****************************************************************************** +* FUNCTION : udp_csum_calc() +* AUTHOR : huangwenzhong +* DESCRIPTION : ÓÃÓÚ¼ÆËãUDPµÄ¼ìÑéºÍ +* INPUT : iph - IPÍ·Ö¸Õë(»òÕßIPv6Í·Ö¸Õë) +* udp - UDPÍ·Ö¸Õë +* payload_len - UDPÔغɳ¤¶È +* sa_family - ´«ÈëµÄÍ·²¿Ö¸ÕëµÄÀàÐÍΪIP/IPv6 (È¡Öµ:AF_INET/AF_INET6) +* OUTPUT : N/A +* RETURN : N/A +* OTHERS : +******************************************************************************/ +static unsigned short udp_csum_calc( void *iph, struct udphdr *udph, int payload_len, int sa_family) +{ + unsigned long csum = 0; + struct iphdr *pIpHdr = (struct iphdr *)iph; + struct ipv6hdr *pIp6Hdr = (struct ipv6hdr *)iph; + unsigned long csumed_len = payload_len + sizeof( *udph ); + unsigned short *word_ptr = ( unsigned short * )udph; + int index = 0; + + while ( csumed_len >1 ) + { + csum += htons(*word_ptr++); + csumed_len -= sizeof( unsigned short ); + } + + if ( csumed_len ) + { + csum += ( *( ( unsigned char * )word_ptr ) ) << 8; + } + + if (AF_INET == sa_family) + { //ip src addr + csum += ( htonl(pIpHdr->saddr) ) & 0x0000ffff; + csum += ( (htonl(pIpHdr->saddr)) >> 16 ) & 0x0000ffff; + //ip dst addr + csum += ( htonl(pIpHdr->daddr) ) & 0x0000ffff; + csum += ( (htonl(pIpHdr->daddr)) >> 16 ) & 0x0000ffff; + //udp hdr len + csum += htons(udph->len); + //udp proto + csum += IPPROTO_UDP & 0x00ff; + } + else if (AF_INET6 == sa_family) + { + //ipv6 src addr + for(index = 0; index < 8; index++) + csum += htons(pIp6Hdr->saddr.s6_addr16[index]); + //ipv6 dst addr + for(index = 0; index < 8; index++) + csum += htons(pIp6Hdr->daddr.s6_addr16[index]); + //up section length, here dns packet with no extern head is the payload length + csum += htons(pIp6Hdr->payload_len); + //next head type + csum += pIp6Hdr->nexthdr & 0x00ff; + } + + while(csum > 0x10000) + { + csum = (csum & 0x0000ffff) + (csum >> 16); + } + return ( unsigned short )( ~csum ); +} + +/****************************************************************************** +* FUNCTION : create_ip6_hdr() +* AUTHOR : chenming +* DESCRIPTION : ¸ù¾ÝԭʼIPv6Êý¾Ý±¨Í·ÏòSKBÖÐÌî³äIPv6Êý¾ÝÍ· +* INPUT : skb - ±»Ìî³äÊý¾Ý±¨ÎÄÍ·²¿µÄSKB +* old_ip6hdr - ԭʼIPv6±¨ÎÄÍ·²¿Ö¸Õë, ¸ù¾Ý´ËÄÚÈÝÉú³ÉеÄIPv6±¨ÎÄÍ·²¿ +* data_len - IPv6µÄÔغɳ¤¶È +* OUTPUT : N/A +* RETURN : Ö¸ÏòÌî³äºÃºóµÄÐÂIPv6±¨ÎÄÍ·²¿µÄÖ¸Õë +* OTHERS : ÐÂIPv6Êý¾Ý±¨ÎÄÍ·²¿½»»»Ô­Ê¼Êý¾Ý±¨Í·ÖеÄÔ´Ä¿µÄIPv6µØÖ·, ÐÞ¸ÄÔغɳ¤¶È, ÆäÓàÄÚÈÝÓëԭʼ°üÍ·±£³Ö²»±ä +******************************************************************************/ +static inline struct ipv6hdr *create_ip6_hdr(struct sk_buff *skb, struct ipv6hdr *old_ip6hdr, unsigned short data_len) +{ + struct ipv6hdr *new_ip6hdr; + + if (IPV6_HDR_LEN > skb_tailroom(skb)) + return NULL; + + new_ip6hdr = (struct ipv6hdr *)skb_put(skb, IPV6_HDR_LEN); + + /* we must specify the network header to avoid kernel panic. + when ip_nat hook was called, it use iphr(skb)to get network header. + by HouXB, 12May11 */ + skb_set_network_header(skb, ETH_HEADER_LEN); + + memcpy( ( unsigned char * )new_ip6hdr, ( unsigned char * )old_ip6hdr, IPV6_HDR_LEN); + new_ip6hdr->hop_limit = IP6_PACKET_HOPLIMIT; + new_ip6hdr->payload_len = htons(data_len); + new_ip6hdr->saddr = old_ip6hdr->daddr; + new_ip6hdr->daddr = old_ip6hdr->saddr; + return new_ip6hdr; +} + +/****************************************************************************** +* FUNCTION : create_ip_hdr() +* AUTHOR : chenming +* DESCRIPTION : ¸ù¾ÝԭʼIPÊý¾Ý±¨Í·ÏòSKBÖÐÌî³äIPÊý¾ÝÍ· +* INPUT : skb - ±»Ìî³äÊý¾Ý±¨ÎÄÍ·²¿µÄSKB +* old_iphdr - ԭʼIP±¨ÎÄÍ·²¿Ö¸Õë, ¸ù¾Ý´ËÄÚÈÝÉú³ÉеÄIP±¨ÎÄÍ·²¿ +* data_len - IPµÄÔغɳ¤¶È +* OUTPUT : N/A +* RETURN : Ö¸ÏòÌî³äºÃºóµÄÐÂIP±¨ÎÄÍ·²¿µÄÖ¸Õë +* OTHERS : ÐÂIPÊý¾Ý±¨ÎÄÍ·²¿½»»»Ô­Ê¼Êý¾Ý±¨Í·ÖеÄÔ´Ä¿µÄIPµØÖ·, ÐÞ¸ÄÔغɳ¤¶È, ÆäÓàÄÚÈÝÓëԭʼ°üÍ·±£³Ö²»±ä +* ×¢ÒâÓÉÓÚûÓÐÉèÖÃÍ·²¿µÄidÓò, Òò´Ëµ÷ÓÃÕßÐèÒªÖØмÆËãchecksum. +******************************************************************************/ +static inline struct iphdr * create_ip_hdr(struct sk_buff *skb, struct iphdr *old_iphdr, unsigned short data_len) +{ + struct iphdr *new_iphdr; + + if (sizeof(struct iphdr) > skb_tailroom(skb)) + return NULL; + new_iphdr = ( struct iphdr * )skb_put( skb, sizeof( struct iphdr ) ); +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) ) + + /* we must specify the network header to avoid kernel panic. + when ip_nat hook was called, it use iphr(skb)to get network header. + by HouXB, 12May11 */ + //skb_set_network_header(dns_skb, ETH_HEADER_LEN); + //here sk_buff_data_t is typeof (unsigned char*), not offset + //but in the kernel definition, dns_skb->network_header is offset + //so cause the error + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,20)) + skb->network_header = ETH_HEADER_LEN; +#else + skb->network_header = (sk_buff_data_t)new_iphdr; +#endif +#else + skb->nh.iph = new_iphdr; +#endif + + memcpy( ( unsigned char * )new_iphdr, ( unsigned char * )old_iphdr, old_iphdr->ihl *4 ); + new_iphdr->ttl = IP_PACKET_TTL; + new_iphdr->frag_off |= htons( 0x4000 ); + new_iphdr->saddr = ((struct iphdr *)old_iphdr)->daddr; + new_iphdr->daddr = ((struct iphdr *)old_iphdr)->saddr; + new_iphdr->tot_len = htons(new_iphdr->ihl * 4 + data_len); + new_iphdr->check = 0x0000; + + return new_iphdr; +} + +/****************************************************************************** +* FUNCTION : create_udp_hdr() +* AUTHOR : chenming +* DESCRIPTION : ¸ù¾ÝԭʼUDPÊý¾Ý±¨Í·ÏòSKBÖÐÌî³äUDPÊý¾ÝÍ· +* INPUT : skb - ±»Ìî³äÊý¾Ý±¨ÎÄÍ·²¿µÄSKB +* old_udphdr - ԭʼUDP±¨ÎÄÍ·²¿Ö¸Õë, ¸ù¾Ý´ËÄÚÈÝÉú³ÉеÄUDP±¨ÎÄÍ·²¿ +* data_len - UDPµÄÔغɳ¤¶È +* OUTPUT : N/A +* RETURN : Ö¸ÏòÌî³äºÃºóµÄÐÂUDP±¨ÎÄÍ·²¿µÄÖ¸Õë +* OTHERS : ÐÂUDPÊý¾Ý±¨ÎÄÍ·²¿½»»»Ô­Ê¼Êý¾Ý±¨Í·ÖеÄÔ´Ä¿µÄ¶Ë¿Ú, ÐÞ¸ÄÔغɳ¤¶È, ÆäÓàÄÚÈÝÓëԭʼ°üÍ·±£³Ö²»±ä +* ×¢Òâµ÷ÓÃÕßÐèÒª¼ÆËãchecksum. +******************************************************************************/ +static inline struct udphdr* create_udp_hdr(struct sk_buff *skb, struct udphdr *old_udphdr, unsigned short data_len) +{ + struct udphdr *new_udphdr; + /* create udp header */ + if (sizeof(struct udphdr) > skb_tailroom(skb)) + return NULL; + new_udphdr = ( struct udphdr * )skb_put( skb, sizeof( struct udphdr ) ); + + memcpy( ( unsigned char * )&new_udphdr->dest, + ( unsigned char *)&old_udphdr->source, PORT_LEN ); + memcpy( ( unsigned char * )&new_udphdr->source, + ( unsigned char *)&old_udphdr->dest, PORT_LEN ); + new_udphdr->len = htons( UDP_HEADER_LEN + data_len ); + new_udphdr->check = 0x0000; + + return new_udphdr; +} + +/****************************************************************************** +* FUNCTION : create_dns_hdr() +* AUTHOR : chenming +* DESCRIPTION : ¸ù¾ÝԭʼDNSÊý¾Ý±¨Í·ÏòSKBÖÐÌî³äеÄDNSÊý¾ÝÍ· +* INPUT : skb - ±»Ìî³äÊý¾Ý±¨ÎÄÍ·²¿µÄSKB +* old_dnshdr - ԭʼDNS±¨ÎÄÍ·²¿Ö¸Õë, ¸ù¾Ý´ËÄÚÈÝÉú³ÉеÄDNS±¨ÎÄÍ·²¿ +* OUTPUT : N/A +* RETURN : Ö¸ÏòÌî³äºÃºóµÄÐÂDNS±¨ÎÄÍ·²¿µÄÖ¸Õë +* OTHERS : ÐÂDNSÊý¾Ý±¨ÎÄÍ·²¿ÐÞ¸ÄFLAGÔö¼ÓÁËDNS_RESPONSE_FLAG, ÆäÓàÄÚÈÝÓëԭʼ°üÍ·±£³Ö²»±ä +******************************************************************************/ +static inline DNS_HEADER * create_dns_hdr(struct sk_buff *skb, DNS_HEADER *old_dnshdr) +{ + DNS_HEADER *new_dnshdr; + + /* create dns header */ + if (sizeof(struct udphdr) > skb_tailroom(skb)) + return NULL; + new_dnshdr = ( DNS_HEADER * )skb_put( skb, sizeof( DNS_HEADER ) ); + + memcpy( ( unsigned char * )&new_dnshdr->transaction_id, + ( unsigned char * )&old_dnshdr->transaction_id, sizeof( __u16 ) ); + memcpy( ( unsigned char * )&new_dnshdr->flag, + ( unsigned char * )&old_dnshdr->flag, sizeof( __u16 ) ); + new_dnshdr->flag |= htons( DNS_RESPONSE_FLAG ); + memcpy( ( unsigned char * )&new_dnshdr->questions, + ( unsigned char * )&old_dnshdr->questions, sizeof( __u16 ) ); + new_dnshdr->answers_rrs = htons( 0x0001 ); + new_dnshdr->authority_rrs = 0x0000; + new_dnshdr->additional_rrs = 0x0000; + + return new_dnshdr; +} + +/****************************************************************************** +* FUNCTION : fill_dns_payload() +* AUTHOR : chenming +* DESCRIPTION : ÏòSKBÖÐÌî³äDNSµÄÔØºÉ +* INPUT : skb - ±»Ìî³äÊý¾Ý±¨ÎĵÄSKB +* dev - ÓÃÓÚ»ñÈ¡ÏìÓ¦µØÖ·½âÎöµÄIP»òÕßIPv6µØÖ·µÄÍøÂçÉ豸. +* query_str - DNS²éѯÇëÇó×Ö·û´®, ¶ÔÓ¦DNSÇëÇó½âÎöµÄÓòÃû +* query_type - DNSÇëÇóµÄÀàÐÍ(A/AAAA) +* data_len - DNSÔغÉ×ܳ¤¶È(Ô¤ÏȼÆËãºÃÁ˵Ä) +* OUTPUT : N/A +* RETURN : Ö¸ÏòÌî³äºÃºóµÄÐÂDNSÔغÉÆðʼµØÖ·µÄÖ¸Õë +* OTHERS : µ÷ÓÃÕßÐèÒª±£Ö¤Ôغɳ¤¶Èdata_lenµÄÕýÈ·ÐÔ +******************************************************************************/ +static inline unsigned char * fill_dns_payload(struct sk_buff *skb, + struct net_device *dev, + unsigned char *query_str, + int query_type, + unsigned short data_len) +{ + unsigned char *dns_payload = NULL; + unsigned char *tmp = NULL; + struct in6_addr addr6; + unsigned int addr = 0; + __u32 int_val = 0; + __u16 short_val = 0; + + //init the address value + addr = htonl(lan_ip); + memcpy(addr6.s6_addr, lan_ip6, 16); + + /* create dns questions */ + if (data_len > skb_tailroom(skb)) + { + return NULL; + } + dns_payload = ( unsigned char * )skb_put( skb, data_len ); + tmp = dns_payload; + + memcpy( tmp, query_str, DNS_QUERY_LEN ); + tmp = dns_payload + DNS_QUERY_LEN; + + *tmp = 0x00; + tmp++; + + short_val = htons( query_type ); + memcpy( tmp, &short_val, sizeof( short_val ) ); + tmp += sizeof( short_val ); + + short_val = htons( DNS_QUERY_CLASS ); + memcpy( tmp, &short_val, sizeof( short_val ) ); + tmp += sizeof( short_val ); + + /* create dns answer */ + short_val = htons( DNS_RESPONSE_POINTER ); + memcpy( tmp, &short_val, sizeof( short_val ) ); + tmp += sizeof( short_val ); + + short_val = htons( query_type ); + memcpy( tmp, &short_val, sizeof( short_val ) ); + tmp += sizeof( short_val ); + + short_val = htons( DNS_QUERY_CLASS ); + memcpy( tmp, &short_val, sizeof( short_val ) ); + tmp += sizeof( short_val ); + + int_val = htonl( DNS_ANSWER_TTL ); + memcpy( tmp, &int_val, sizeof( int_val ) ); + tmp += sizeof( int_val ); + + if (query_type == DNS_QUERY_TYPE_AAAA) + short_val = htons( DNS_RESOURCE_LEN_AAAA ); + else + short_val = htons( DNS_RESOURCE_LEN_A ); + memcpy( tmp, &short_val, sizeof( short_val ) ); + tmp += sizeof( short_val ); + + /*get lan ip as answer*/ + if (query_type == DNS_QUERY_TYPE_AAAA) + { + get_dev_ip6_addr(dev, &addr6); + //ipv6 address should always be fe80::1 + memcpy(tmp, addr6.s6_addr, DNS_RESOURCE_LEN_AAAA); + tmp+= DNS_RESOURCE_LEN_AAAA; + } + else + { + get_dev_ip_addr(dev, &addr); + int_val = addr; + memcpy( tmp, &int_val, sizeof( int_val ) ); + tmp+= sizeof(int_val); + } + + return dns_payload; +} + +/****************************************************************************** +* FUNCTION : tp_send_dns6_packet() +* AUTHOR : chenming +* DESCRIPTION : ÓÃÓÚ¹¹½¨ºÍ·¢ËÍDNSv6Ó¦´ð°ü +* INPUT : skb - DNSv6ÇëÇó°ü +* old_iphdr - DNSv6ÇëÇó°üµÄIPv6Í·Ö¸Õë +* old_udphdr - DNSv6ÇëÇó°üµÄUDPÍ·Ö¸Õë +* old_dnshdr - DNSv6ÇëÇó°üµÄDNSÍ·Ö¸Õë +* query_type - ÇëÇóµÄÓòÃûµÄÀàÐÍ, A/AAAA +* +* OUTPUT : N/A +* RETURN : N/A +* OTHERS : +******************************************************************************/ +static void tp_send_dns6_packet(struct sk_buff *skb, + struct ipv6hdr *old_iphdr, + struct udphdr *old_udphdr, + DNS_HEADER *old_dnshdr, + unsigned short query_type) +{ + struct sk_buff *dns_skb = NULL; + struct ipv6hdr *new_iphdr = NULL; /* Òª´´½¨µÄDNS»Ø´ð±¨ÎĵÄIPV6Í· */ + struct udphdr *new_udphdr = NULL; + DNS_HEADER *new_dnshdr = NULL; + unsigned char *dns_payload = NULL; + struct dst_entry *dst = NULL; + + int skb_len = 0; + int data_len = 0; + int ret = 0; + __u16 udp_sum = 0;/* ÓÃÓÚÔÝ´æUDPµÄ¼ìÑéºÍ */ + +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,8) ) + struct flowi fl = { + .u = { + .ip6 = { + .daddr = old_iphdr->saddr, + }, + }, + }; +#else + struct flowi fl = { + /* .oif = 0, */ + .nl_u = { + .ip6_u = { + .daddr = old_iphdr->saddr, + + } + }, + /* .proto = IPPROTO_UDP, + .uli_u = { + .ports = { + .dport = old_udphdr->source, + .sport = old_udphdr->dest, + + }, + },*/ + }; +#endif + + /* create route info, if not send success, we need release before return */ +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,8) ) + dst = ip6_route_output(dev_net(skb->dev), NULL, &(fl.u.ip6)); +#else + dst = ip6_route_output(dev_net(skb->dev), NULL, &fl); +#endif + + if (NULL == dst) + { + return; + } + + /* calculate the packet length and alloc sk buffer */ + data_len = DNS_DATA_LEN; + if (query_type == DNS_QUERY_TYPE_AAAA) + data_len += DNS_RESOURCE_LEN_AAAA - DNS_RESOURCE_LEN_A; //for ipv6 address len + + skb_len = ETH_HEADER_LEN + IPV6_HDR_LEN + UDP_HEADER_LEN + DNS_HEADER_LEN + data_len; + dns_skb = alloc_skb( skb_len, GFP_ATOMIC ); + if ( !dns_skb ) + { + goto fail_releasert6; + return; + } + + /* init the packet info */ + nf_reset( dns_skb ); + dns_skb->mark = 0; + dns_skb->pkt_type = PACKET_OTHERHOST; + dns_skb->protocol = htons(ETH_P_IPV6); + dns_skb->ip_summed = CHECKSUM_NONE; + dns_skb->priority = 0; + + skb_dst_set(dns_skb, dst); + + skb_reserve( dns_skb, ETH_HEADER_LEN ); + + /* create IP6 header */ + new_iphdr = create_ip6_hdr(dns_skb, (struct ipv6hdr *)old_iphdr, data_len + UDP_HEADER_LEN + DNS_HEADER_LEN); + if (new_iphdr == NULL) + { + goto fail_freeskb6; + } + + /* create udp header */ + new_udphdr = create_udp_hdr(dns_skb, old_udphdr, data_len + DNS_HEADER_LEN); + if (new_udphdr == NULL) + { + goto fail_freeskb6; + } + + /* create dns header */ + new_dnshdr = create_dns_hdr(dns_skb, old_dnshdr); + if (new_dnshdr == NULL) + { + goto fail_freeskb6; + } + + /* create dns payload data */ + dns_payload = fill_dns_payload(dns_skb, (struct net_device *)skb->dev, query, query_type, data_len); + if (NULL == dns_payload) + { + goto fail_freeskb6; + } + + /* calculate the udp checksum */ + udp_sum = udp_csum_calc(new_iphdr, new_udphdr, DNS_HEADER_LEN + data_len, AF_INET6 ); + new_udphdr->check = htons( udp_sum ); + + /* send dns packet */ + ret = dst_output( dns_skb ); + return; +fail_freeskb6: + /* free skb before return */ + kfree_skb(dns_skb); +fail_releasert6: + /* free route info before return */ + dst_release(dst); + + return; +} + +/****************************************************************************** +* FUNCTION : tp_send_dns_packet() +* AUTHOR : huangwenzhong +* DESCRIPTION : ÓÃÓÚ¹¹½¨ºÍ·¢ËÍDNSÓ¦´ð°ü +* INPUT : skb - DNSÇëÇó°ü +* old_iphdr - DNSÇëÇó°üµÄIPÍ·Ö¸Õë +* old_udphdr - DNSÇëÇó°üµÄUDPÍ·Ö¸Õë +* old_dnshdr - DNSÇëÇó°üµÄDNSÍ·Ö¸Õë +* query_type - ÇëÇóµÄÓòÃûµÄÀàÐÍ£¬DNS_QUERY_TYPE_A or DNS_QUERY_TYPE_AAAA +* +* OUTPUT : N/A +* RETURN : N/A +* OTHERS : +******************************************************************************/ +static void tp_send_dns_packet( struct sk_buff *skb, + struct iphdr *old_iphdr, + struct udphdr *old_udphdr, + DNS_HEADER *old_dnshdr, + unsigned short query_type) +{ + + struct sk_buff *dns_skb; + + int skb_len; + int data_len; + int ret = 0; + + struct iphdr *new_iphdr; /* Òª´´½¨µÄDNS»Ø´ð±¨ÎĵÄIPÍ· */ + + struct net_device *br0_dev; + /*added by wangbing for get LAN ip*/ + //struct net_device *skb_dev;/*»ñÈ¡lan¶Ëip:skb->dev->br_port->br->dev->ip_ptr->ifa_list->ifa_address*/ + //struct net_bridge_port *br_port; + //struct net_bridge *br; + //struct net_device *br_dev; + + //struct in_device * in_dev = NULL; + + struct udphdr *new_udphdr; + DNS_HEADER *new_dnshdr; + unsigned char *dns_payload; + //unsigned char *tmp; + + //__u16 short_val; + __u16 udp_sum;/* ÓÃÓÚÔÝ´æUDPµÄ¼ìÑéºÍ */ + //__u32 int_val; + + struct rtable *rt; + +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,8) ) + + struct flowi fl = { + .u = { + .ip4 = { + .daddr = old_iphdr->saddr, + }, + }, + }; +#else + struct flowi fl = { + /* .oif = 0, */ + .nl_u = { + .ip4_u = { + .daddr = old_iphdr->saddr, + /* .saddr = in_aton( LAN_IP ), */ + + } + }, + /* .proto = IPPROTO_UDP, + .uli_u = { + .ports = { + .dport = old_udphdr->source, + .sport = old_udphdr->dest, + + }, + },*/ + }; +#endif + +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,8) ) + br0_dev = dev_get_by_name(&init_net, "bridge0"); + rt = ip_route_output_key(dev_net(br0_dev), &(fl.u.ip4)); + if (IS_ERR(rt)) + ret = (int)rt; + dev_put(br0_dev); +#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) ) + br0_dev = dev_get_by_name(&init_net, "bridge0"); + ret = ip_route_output_key(dev_net(br0_dev), &rt, &fl); + dev_put(br0_dev); +#else + ret = ip_route_output_key( &rt, &fl ); +#endif + if (ret) + { + printk("ip_route_output_key() failed in file create_tp_dns_skb.c, ret = %d\r\n", ret); + return; + } + + data_len = DNS_DATA_LEN; + if (DNS_QUERY_TYPE_AAAA == query_type) + data_len += DNS_RESOURCE_LEN_AAAA - DNS_RESOURCE_LEN_A; //for ipv6 address len + + skb_len = ETH_HEADER_LEN + old_iphdr->ihl *4 + + UDP_HEADER_LEN + DNS_HEADER_LEN + data_len; + + dns_skb = alloc_skb( skb_len, GFP_ATOMIC ); + if ( !dns_skb ) + { + goto fail_releasert; + return; + } + nf_reset( dns_skb ); + +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) ) + dns_skb->mark = 0; +#else + dns_skb->nfmark = 0; +#endif + + nf_ct_attach(dns_skb, skb); /* needed by NAT */ + dns_skb->pkt_type = PACKET_OTHERHOST; + dns_skb->protocol = htons( ETH_P_IP); + dns_skb->ip_summed = CHECKSUM_NONE; + dns_skb->priority = 0; +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) + skb_dst_set(dns_skb, &rt->dst); +#elif( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)) + skb_dst_set(dns_skb, &rt->u.dst); +#else + dns_skb->dst = &rt->u.dst; +#endif + + skb_reserve( dns_skb, ETH_HEADER_LEN ); + + /* create IP header */ + new_iphdr = create_ip_hdr(dns_skb, old_iphdr, data_len + UDP_HEADER_LEN + DNS_HEADER_LEN ); + if (new_iphdr == NULL) + { + goto fail_freeskb; + } + +/* dbs: add for kernel 3.4.103 */ +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) ) + ip_select_ident(dns_skb, NULL); +#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) ) + ip_select_ident(dns_skb, &rt->dst, NULL); +#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,103) ) + ip_select_ident( dns_skb, NULL ); +#elif ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) ) + ip_select_ident( new_iphdr, &rt->dst, NULL ); +#else + ip_select_ident( new_iphdr, &rt->u.dst, NULL );/* always 0 */ +#endif + + /* need calc the ipv4 head checksum here, as the ip_select_ident would change the ip header */ + new_iphdr->check = 0x0000; + new_iphdr->check = ip_fast_csum( (unsigned char * )new_iphdr, new_iphdr->ihl ); + + /* create udp header */ + new_udphdr = create_udp_hdr(dns_skb, old_udphdr, data_len + DNS_HEADER_LEN); + if (new_udphdr == NULL) + { + goto fail_freeskb; + } + + /* create dns header */ + new_dnshdr = create_dns_hdr(dns_skb, old_dnshdr); + if (new_dnshdr == NULL) + { + goto fail_freeskb; + } + + /* create dns answer */ + dns_payload = fill_dns_payload(dns_skb, (struct net_device *)skb->dev, query, query_type, data_len); + if (NULL == dns_payload) + { + goto fail_freeskb; + } + + udp_sum = udp_csum_calc( new_iphdr, new_udphdr, DNS_HEADER_LEN + data_len,AF_INET); + new_udphdr->check = htons( udp_sum ); + + dst_output( dns_skb ); + return; + +fail_freeskb: + kfree_skb(dns_skb); +fail_releasert: + ip_rt_put(rt); + return; +} + + +/****************************************************************************** +* FUNCTION : tp_dns_handler() +* AUTHOR : huangwenzhong +* DESCRIPTION : ¹ÒÔص½FORWARDÁ´µÄ¹³×Óº¯Êý£¬ + ÓÃÓÚÀ¹½Øtplinkmodem.netÓòÃûÇëÇóµÄ°ü²¢·¢³öÓ¦´ð°ü +* INPUT : N/A +* +* OUTPUT : N/A +* RETURN : N/A +* OTHERS : +******************************************************************************/ +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) ) +static unsigned int tp_dns_handler( unsigned int hooknum, + struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + int ( *okfn )(struct sk_buff *) ) +{ + struct sk_buff *pskb = skb; +#else + +static unsigned int tp_dns_handler( unsigned int hooknum, + struct sk_buff **skb, + const struct net_device *in, + const struct net_device *out, + int ( *okfn )(struct sk_buff *) ) +{ + struct sk_buff *pskb = *skb; +#endif + struct iphdr *iph = NULL; + struct ipv6hdr *ip6h = NULL; + struct udphdr *udp_hdr = NULL; + DNS_HEADER *dns_hdr= NULL; + unsigned char * dns_payload = NULL; + unsigned char * tmp = NULL; + + __u16 query_type; + +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) ) + iph = ip_hdr(pskb); + ip6h = ipv6_hdr(pskb); +#else + iph = pskb->nh.iph; + ip6h = ipv6_hdr(pskb); +#endif + + switch(ntohs(pskb->protocol)) + { + case ETH_P_IPV6: + if (NULL != ip6h && 6 == ip6h->version && IPPROTO_UDP == ip6h->nexthdr) + udp_hdr = (struct udphdr *)((unsigned char *) ip6h + sizeof(struct ipv6hdr)); + else + return NF_ACCEPT; + break; + case ETH_P_IP: + if ( NULL != iph && 4 == iph->version && IPPROTO_UDP == iph->protocol) + udp_hdr = ( struct udphdr * )( ( unsigned char * )iph + iph->ihl * 4 ); + else + return NF_ACCEPT; + break; + default: + return NF_ACCEPT; + } + if ( NULL == udp_hdr || (DOMAIN_PORT != (ntohs(udp_hdr->dest)))) //not dns packet? + { + return NF_ACCEPT; + } + dns_hdr = ( DNS_HEADER * )( ( unsigned char * )udp_hdr + UDP_HEADER_LEN ); + if ( (NULL == dns_hdr) || ( ntohs( dns_hdr->flag ) & DNS_RESPONSE_PACKET )) //not dns query? + { + return NF_ACCEPT; + } + + dns_payload = ( unsigned char * )( ( unsigned char * )dns_hdr + DNS_HEADER_LEN ); + if ( NULL == dns_payload || 0 != memcmp( dns_payload, query, DNS_QUERY_LEN )) //not the target query? + { + return NF_ACCEPT; + } + else + { + tmp = dns_payload + DNS_QUERY_LEN + 1; + } + + memcpy( &query_type, tmp, sizeof( query_type ) ); + query_type = ntohs( query_type ); + + if( DNS_QUERY_TYPE_A != query_type && DNS_QUERY_TYPE_AAAA != query_type )/* is query type not A (or AAAA)? */ + { + return NF_ACCEPT; + } + if (ETH_P_IPV6 == ntohs( pskb->protocol)) + { + tp_send_dns6_packet(pskb, ip6h, udp_hdr, dns_hdr, query_type); + } + else + { + tp_send_dns_packet(pskb, iph, udp_hdr, dns_hdr, query_type); + } + + return NF_DROP; + +} +static struct nf_hook_ops tp_dns_br_hook_ops = { + .hook = tp_dns_handler, + .owner = THIS_MODULE, + .pf = PF_BRIDGE, + .hooknum = NF_BR_PRE_ROUTING, + .priority = NF_BR_PRI_FIRST, +}; + +static struct nf_hook_ops tp_dns_ip_hook_ops = { + .hook = tp_dns_handler, + .owner = THIS_MODULE, + .pf = PF_INET, +#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) ) + .hooknum = NF_INET_PRE_ROUTING, +#else + .hooknum = NF_IP_PRE_ROUTING, +#endif + .priority = NF_IP_PRI_NAT_DST - 1, /* before DNAT */ +}; + +static struct nf_hook_ops tp_dns_ip6_hook_ops = { + .hook = tp_dns_handler, + .owner = THIS_MODULE, + .pf = PF_INET6, + .hooknum = NF_INET_PRE_ROUTING, + .priority = NF_IP6_PRI_FIRST, +}; + +static int dns_init(void) +{ + int ret; + + ret = nf_register_hook( &tp_dns_br_hook_ops ); + if ( ret < 0 ) + { + return ret; + } + + ret = nf_register_hook(&tp_dns_ip_hook_ops); + if ( ret < 0 ) + { + return ret; + } + + ret = nf_register_hook(&tp_dns_ip6_hook_ops); + if ( ret < 0 ) + { + return ret; + } + + printk( "dns_init\n"); + printk( "domain_name:%s\n",lan_domain); + parse_domain(); +#ifdef INCLUDE_DOMAIN_INTERCEPT + return domain_intercept_init(); +#else + return 0; +#endif /*INCLUDE_DOMAIN_INTERCEPT*/ +} + +static void dns_exit(void) +{ + + nf_unregister_hook( &tp_dns_br_hook_ops ); + nf_unregister_hook( &tp_dns_ip_hook_ops ); + nf_unregister_hook( &tp_dns_ip6_hook_ops); +#ifdef INCLUDE_DOMAIN_INTERCEPT + domain_intercept_exit(); +#endif /*INCLUDE_DOMAIN_INTERCEPT*/ + return; +} +module_init( dns_init ); +module_exit( dns_exit ); + + +/* module license 'BSD' will taints kernel, so change it to GPL. by HouXB, 12May11 */ +//MODULE_LICENSE( "BSD" ); +MODULE_LICENSE( "GPL" ); + +MODULE_AUTHOR( "Huang Wenzhong "); +MODULE_DESCRIPTION( "The default domain name tplinkmodem.net."); + +/* by HouXB, 12May11 */ +MODULE_ALIAS("tp_domain"); + + diff --git a/tp-proprietary/tp-domain/tp_domain.h b/tp-proprietary/tp-domain/tp_domain.h new file mode 100644 index 000000000..6d4f6c07f --- /dev/null +++ b/tp-proprietary/tp-domain/tp_domain.h @@ -0,0 +1,158 @@ +/****************************************************************************** + * + * Copyright (c) 2009 TP-LINK Technologies CO.,LTD. + * All rights reserved. + * + * FILE NAME : tp_domain.h + * VERSION : 1.0 + * DESCRIPTION: ÓÃÓÚʵÏÖÎÒ˾·ÓÉÆ÷²úÆ·¿ÉÒÔÓòÃûµÇ¼½øweb¹ÜÀíÒ³Ãæ. + * + * AUTHOR : huangwenzhong + * CREATE DATE: 11/30/2010 + * + * HISTORY : + * 01 11/30/2010 huangwenzhong Create. + * + ******************************************************************************/ +#ifndef _TP_DOMAIN_H +#define _TP_DOMAIN_H + + +#define DOMAIN_PORT 53 + + +#define ETH_HEADER_LEN ( 2 + 14 ) +#define IP_PACKET_TTL 128 + +#define IP6_PACKET_HOPLIMIT 64 + +#define BR_STATE_DISABLED 0 +#define BR_STATE_LISTENING 1 +#define BR_STATE_LEARNING 2 +#define BR_STATE_FORWARDING 3 +#define BR_STATE_BLOCKING 4 + +#define BR_HASH_BITS 8 +#define BR_HASH_SIZE (1 << BR_HASH_BITS) + +typedef __u16 port_id; +typedef struct bridge_id bridge_id; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) +struct bridge_id +{ + unsigned char prio[2]; + unsigned char addr[6]; +}; + +struct net_bridge_port +{ + struct net_bridge *br; + struct net_device *dev; + struct list_head list; + + /* STP */ + u8 priority; + u8 state; + u16 port_no; + unsigned char topology_change_ack; + unsigned char config_pending; + port_id port_id; + port_id designated_port; + bridge_id designated_root; + bridge_id designated_bridge; + u32 path_cost; + u32 designated_cost; + + struct timer_list forward_delay_timer; + struct timer_list hold_timer; + struct timer_list message_age_timer; + struct kobject kobj; + struct rcu_head rcu; +}; + +struct net_bridge +{ + spinlock_t lock; + struct list_head port_list; + struct net_device *dev; + spinlock_t hash_lock; + struct hlist_head hash[BR_HASH_SIZE]; + struct list_head age_list; + unsigned long feature_mask; +#ifdef CONFIG_BRIDGE_NETFILTER + struct rtable fake_rtable; +#endif + unsigned long flags; +#define BR_SET_MAC_ADDR 0x00000001 + + /* STP */ + bridge_id designated_root; + bridge_id bridge_id; + u32 root_path_cost; + unsigned long max_age; + unsigned long hello_time; + unsigned long forward_delay; + unsigned long bridge_max_age; + unsigned long ageing_time; + unsigned long bridge_hello_time; + unsigned long bridge_forward_delay; + + u8 group_addr[ETH_ALEN]; + u16 root_port; + + enum { + BR_NO_STP, /* no spanning tree */ + BR_KERNEL_STP, /* old STP in kernel */ + BR_USER_STP, /* new RSTP in userspace */ + } stp_enabled; + + unsigned char topology_change; + unsigned char topology_change_detected; + + struct timer_list hello_timer; + struct timer_list tcn_timer; + struct timer_list topology_change_timer; + struct timer_list gc_timer; + struct kobject *ifobj; +}; +#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) */ + +#if 0 +#define DNS_ANSWER_TTL 0 +#else +#define DNS_ANSWER_TTL ( 2 * 24 * 60 *60 ) +#endif + +#define IP_ADDR_LEN sizeof( __u32 ) +#define IP6_ADDR_LEN 16 +#define PORT_LEN sizeof( __u16 ) +#define UDP_HEADER_LEN sizeof( struct udphdr ) +#define DNS_HEADER_LEN sizeof( DNS_HEADER ) + +#define DNS_RESPONSE_PACKET ( 0x8000 ) /* response packet flag */ +#define DNS_QUERY_TYPE_A ( 0x0001 ) /* query type,type A */ +#define DNS_QUERY_TYPE_AAAA ( 0x001c ) /* query type,type AAAA */ +#define DNS_QUERY_CLASS ( 0x0001 ) /* query class,clase internet */ +#define DNS_RESPONSE_FLAG ( 0x8080 ) /* response flag value */ +#define DNS_RESPONSE_POINTER ( 0xc00c )/* response field pointer */ +#define DNS_RESOURCE_LEN_A ( 0x0004 ) /* response field IPv4 length */ +#define DNS_RESOURCE_LEN_AAAA ( 0x0010 ) /* response field IPv6 length */ +/* DNS±¨ÎÄÍ·²¿½á¹¹.added by huangwenzhong. 11/30/2010. */ + +#define br_port_get_rcu(dev) \ + ((struct net_bridge_port *) rcu_dereference(dev->rx_handler_data)) +#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT) + +typedef struct +{ + __u16 transaction_id; + __u16 flag; + __u16 questions; + __u16 answers_rrs; + __u16 authority_rrs; + __u16 additional_rrs; +}__attribute__ ((__packed__))DNS_HEADER; + +#endif /* #ifndef _TP_DOMAIN_H */ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/HowToMake.txt b/wlan/8192es/DriverSrcPkg/Driver/HowToMake.txt new file mode 100755 index 000000000..731818d49 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/HowToMake.txt @@ -0,0 +1,6 @@ +How to build ? + 1. Modify the "platform.mk" to select you platform or add an configuration for your platform. + 2. Modify the "config.mk" to configure the driver option(select the chip, features, ...). + 3. Overwirte "Makefile" by "Makefile_nrs" if your platform is not realtek system. + 4. Run "make". + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_kmsm_aes.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_kmsm_aes.c new file mode 100755 index 000000000..271e2e8fc --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_kmsm_aes.c @@ -0,0 +1,743 @@ + +/* This is an independent implementation of the encryption algorithm: */ +/* */ +/* RIJNDAEL by Joan Daemen and Vincent Rijmen */ +/* */ +/* which is a candidate algorithm in the Advanced Encryption Standard */ +/* programme of the US National Institute of Standards and Technology. */ +/* */ +/* Copyright in this implementation is held by Dr B R Gladman but I */ +/* hereby give permission for its free direct or derivative use subject */ +/* to acknowledgment of its origin and compliance with any conditions */ +/* that the originators of the algorithm place on its exploitation. */ +/* */ +/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */ + +#if 0 +#include "stdafx.h" +#include +#include +#include +#endif + +#ifdef __KERNEL__ +#include +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#if defined(INCLUDE_WPA_PSK) || (defined(RTK_NL80211) && defined(CONFIG_IEEE80211W)) +#ifdef RTL_WPA2 +//#define MODULE_TEST + +/*#include "aes_defs.h" */ +#ifdef _SHOW_ +#define _VERBOSE_ 1 +#elif !defined(_VERBOSE_) +#define _VERBOSE_ 0 +#endif + +// david, move define to Makefile +// kenny +//#define BIG_ENDIAN 1 + +#if defined(__BORLANDC__) /* show what compiler we used */ +#define COMPILER_ID "Borland" +//#define LITTLE_ENDIAN 1 +// modified by chilong +#define AUTH_LITTLE_ENDIAN 1 +#elif defined(_MSC_VER) +#define COMPILER_ID "Microsoft" +//#define LITTLE_ENDIAN 1 +// modified by chilong +#define AUTH_LITTLE_ENDIAN 1 +#elif defined(__GNUC__) +#define COMPILER_ID "GNU" +/* marked by chilong +#ifndef BIG_ENDIAN // assume gcc = little-endian, unless told otherwise +#define LITTLE_ENDIAN 1 +#endif +*/ +// modified by chilong +#ifndef _BIG_ENDIAN_ // assume gcc = little-endian, unless told otherwise +#define AUTH_LITTLE_ENDIAN 1 +#endif +// modified by chilong + +#else /* assume big endian, if compiler is unknown */ +#define COMPILER_ID "Unknown" +#endif + +/* 1. Standard types for AES cryptography source code */ + +typedef unsigned char u08b; /* an 8 bit unsigned character type */ +typedef unsigned short u16b; /* a 16 bit unsigned integer type */ +typedef unsigned int u32b; /* a 32 bit unsigned integer type */ + +#ifndef _RTL_WPA_WINDOW +#ifndef __LINUX_2_6__ +#ifndef __ECOS +typedef int bool; +#endif +#endif +#endif + +/* 2. Standard interface for AES cryptographic routines */ + +/* These are all based on 32-bit unsigned values and will therefore */ +/* require endian conversions for big-endian architectures */ + +#ifdef __cplusplus + extern "C" + { +#endif + u32b * AES_SetKey (const u32b in_key[ ], const u32b key_len); + void AES_Encrypt(const u32b in_blk[4], u32b out_blk[4]); + void AES_Decrypt(const u32b in_blk[4], u32b out_blk[4]); +#ifdef __cplusplus + }; +#endif + +/* 3. Basic macros for speeding up generic operations */ + +/* Circular rotate of 32 bit values */ + +#ifdef _MSC_VER + +#include +#pragma intrinsic(_lrotr,_lrotl) +#define rotr(x,n) _lrotr(x,n) +#define rotl(x,n) _lrotl(x,n) + +#else + +#define rotr(x,n) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n)))) +#define rotl(x,n) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n)))) + +#endif + +/* Extract byte from a 32 bit quantity (little endian notation) */ + +#define byte(x,n) ((u08b)((x) >> (8 * n))) + +/* For inverting byte order in input/output 32 bit words, if needed */ + +// #ifdef LITTLE_ENDIAN +// modified by chilong +#ifdef AUTH_LITTLE_ENDIAN +#define bswap(x) (x) +#else +#define bswap(x) ((rotl((x), 8) & 0x00ff00ff) | (rotr((x), 8) & 0xff00ff00)) +#endif + + +//end of aes_def.h + +/*------------------ DLW debug code */ +#if _VERBOSE_ +#include +int rNum; + + +void ShowBlk(const u32b *b,int final) + { + int i,j; + u32b x; + u08b a; + + printf("%s %2d: ",(final) ? "Final" : "Round",rNum++); + for (i=0;i<4;i++) + { + printf(" "); + x = b[i]; /* always used internally as "little-endian" */ + for (j=0;j<4;j++) + { + a = byte(x,j); + printf(" %02X",a); + } + } + printf("\n"); + } + +void ShowKeySched(const u32b *key,int cnt,const char *hdrMsg) + { + int i,j; + u32b x; + u08b a; + + printf("%s\n",hdrMsg); + for (i=0;i<4*cnt;i++) + { + x = key[i]; /* key always used as "little-endian" */ + printf(" "); + for (j=0;j<4;j++) + { + a = byte(x,j); + printf(" %02X",a); + } + if ((i%4) == 3) printf("\n"); + } + } +#define SetR(r) { rNum = r; } +#else +#define ShowBlk(b,f) +#define SetR(r) +#define ShowKeySched(key,cnt,hdrMsg) +#endif +/*---------------- end of DLW debug */ + + +#define LARGE_TABLES + +u08b pow_tab[256]; +u08b log_tab[256]; +u08b sbx_tab[256]; +u08b isb_tab[256]; +u32b rco_tab[ 10]; +u32b ft_tab[4][256]; +u32b it_tab[4][256]; + +#ifdef LARGE_TABLES + u32b fl_tab[4][256]; + u32b il_tab[4][256]; +#endif + +u32b tab_gen = 0; + +u32b k_len; +u32b e_key[64]; +u32b d_key[64]; + +#define ff_mult(a,b) (a && b ? pow_tab[(log_tab[a] + log_tab[b]) % 255] : 0) + +#define f_rn(bo, bi, n, k) \ + bo[n] = ft_tab[0][byte(bi[n],0)] ^ \ + ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rn(bo, bi, n, k) \ + bo[n] = it_tab[0][byte(bi[n],0)] ^ \ + it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +#ifdef LARGE_TABLES + +#define ls_box(x) \ + ( fl_tab[0][byte(x, 0)] ^ \ + fl_tab[1][byte(x, 1)] ^ \ + fl_tab[2][byte(x, 2)] ^ \ + fl_tab[3][byte(x, 3)] ) + +#define f_rl(bo, bi, n, k) \ + bo[n] = fl_tab[0][byte(bi[n],0)] ^ \ + fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rl(bo, bi, n, k) \ + bo[n] = il_tab[0][byte(bi[n],0)] ^ \ + il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +#else + +#define ls_box(x) \ + ((u32b)sbx_tab[byte(x, 0)] << 0) ^ \ + ((u32b)sbx_tab[byte(x, 1)] << 8) ^ \ + ((u32b)sbx_tab[byte(x, 2)] << 16) ^ \ + ((u32b)sbx_tab[byte(x, 3)] << 24) + +#define f_rl(bo, bi, n, k) \ + bo[n] = (u32b)sbx_tab[byte(bi[n],0)] ^ \ + rotl(((u32b)sbx_tab[byte(bi[(n + 1) & 3],1)]), 8) ^ \ + rotl(((u32b)sbx_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \ + rotl(((u32b)sbx_tab[byte(bi[(n + 3) & 3],3)]), 24) ^ *(k + n) + +#define i_rl(bo, bi, n, k) \ + bo[n] = (u32b)isb_tab[byte(bi[n],0)] ^ \ + rotl(((u32b)isb_tab[byte(bi[(n + 3) & 3],1)]), 8) ^ \ + rotl(((u32b)isb_tab[byte(bi[(n + 2) & 3],2)]), 16) ^ \ + rotl(((u32b)isb_tab[byte(bi[(n + 1) & 3],3)]), 24) ^ *(k + n) + +#endif + +void gen_tabs(void) +{ u32b i, t; + u08b p, q; + + /* log and power tables for GF(2**8) finite field with */ + /* 0x11b as modular polynomial - the simplest prmitive */ + /* root is 0x11, used here to generate the tables */ + + for(i = 0,p = 1; i < 256; ++i) + { + pow_tab[i] = (u08b)p; log_tab[p] = (u08b)i; + + p = p ^ (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + log_tab[1] = 0; p = 1; + + for(i = 0; i < 10; ++i) + { + rco_tab[i] = p; + + p = (p << 1) ^ (p & 0x80 ? 0x1b : 0); + } + + /* note that the affine byte transformation matrix in */ + /* rijndael specification is in big endian format with */ + /* bit 0 as the most significant bit. In the remainder */ + /* of the specification the bits are numbered from the */ + /* least significant end of a byte. */ + + for(i = 0; i < 256; ++i) + { + p = (i ? pow_tab[255 - log_tab[i]] : 0); q = p; + q = (q >> 7) | (q << 1); p ^= q; + q = (q >> 7) | (q << 1); p ^= q; + q = (q >> 7) | (q << 1); p ^= q; + q = (q >> 7) | (q << 1); p ^= q ^ 0x63; + sbx_tab[i] = (u08b)p; isb_tab[p] = (u08b)i; + } + + for(i = 0; i < 256; ++i) + { + p = sbx_tab[i]; + +#ifdef LARGE_TABLES + + t = p; fl_tab[0][i] = t; + fl_tab[1][i] = rotl(t, 8); + fl_tab[2][i] = rotl(t, 16); + fl_tab[3][i] = rotl(t, 24); +#endif + t = ((u32b)ff_mult(2, p)) | + ((u32b)p << 8) | + ((u32b)p << 16) | + ((u32b)ff_mult(3, p) << 24); + + ft_tab[0][i] = t; + ft_tab[1][i] = rotl(t, 8); + ft_tab[2][i] = rotl(t, 16); + ft_tab[3][i] = rotl(t, 24); + + p = isb_tab[i]; + +#ifdef LARGE_TABLES + + t = p; il_tab[0][i] = t; + il_tab[1][i] = rotl(t, 8); + il_tab[2][i] = rotl(t, 16); + il_tab[3][i] = rotl(t, 24); +#endif + t = ((u32b)ff_mult(14, p)) | + ((u32b)ff_mult( 9, p) << 8) | + ((u32b)ff_mult(13, p) << 16) | + ((u32b)ff_mult(11, p) << 24); + + it_tab[0][i] = t; + it_tab[1][i] = rotl(t, 8); + it_tab[2][i] = rotl(t, 16); + it_tab[3][i] = rotl(t, 24); + +#if _VERBOSE_ + if (i<4) /* helpful for debugging on new platform */ + { /* (compare with results from known platform) */ + if (i==0) + printf("%8s : %08X %08X %08X %08X\n","rco_tab", + rco_tab[0],rco_tab[1],rco_tab[2],rco_tab[3]); +#define _ShowTab(tName) printf("%8s[%d]: %08X %08X %08X %08X\n",#tName,i, \ + tName[0][i],tName[1][i],tName[2][i],tName[3][i]); + _ShowTab(it_tab); + _ShowTab(ft_tab); +#ifdef LARGE_TABLES + _ShowTab(il_tab); + _ShowTab(fl_tab); +#endif + } +#endif + } + + tab_gen = 1; +}; + +#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) + +#define imix_col(y,x) \ + u = star_x(x); \ + v = star_x(u); \ + w = star_x(v); \ + t = w ^ (x); \ + (y) = u ^ v ^ w; \ + (y) ^= rotr(u ^ t, 8) ^ \ + rotr(v ^ t, 16) ^ \ + rotr(t,24) + +/* initialise the key schedule from the user supplied key */ + +#define loop4(i) \ +{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ + t ^= e_key[4 * i]; e_key[4 * i + 4] = t; \ + t ^= e_key[4 * i + 1]; e_key[4 * i + 5] = t; \ + t ^= e_key[4 * i + 2]; e_key[4 * i + 6] = t; \ + t ^= e_key[4 * i + 3]; e_key[4 * i + 7] = t; \ +} + +#define loop6(i) \ +{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ + t ^= e_key[6 * i]; e_key[6 * i + 6] = t; \ + t ^= e_key[6 * i + 1]; e_key[6 * i + 7] = t; \ + t ^= e_key[6 * i + 2]; e_key[6 * i + 8] = t; \ + t ^= e_key[6 * i + 3]; e_key[6 * i + 9] = t; \ + t ^= e_key[6 * i + 4]; e_key[6 * i + 10] = t; \ + t ^= e_key[6 * i + 5]; e_key[6 * i + 11] = t; \ +} + +#define loop8(i) \ +{ t = ls_box(rotr(t, 8)) ^ rco_tab[i]; \ + t ^= e_key[8 * i]; e_key[8 * i + 8] = t; \ + t ^= e_key[8 * i + 1]; e_key[8 * i + 9] = t; \ + t ^= e_key[8 * i + 2]; e_key[8 * i + 10] = t; \ + t ^= e_key[8 * i + 3]; e_key[8 * i + 11] = t; \ + t = e_key[8 * i + 4] ^ ls_box(t); \ + e_key[8 * i + 12] = t; \ + t ^= e_key[8 * i + 5]; e_key[8 * i + 13] = t; \ + t ^= e_key[8 * i + 6]; e_key[8 * i + 14] = t; \ + t ^= e_key[8 * i + 7]; e_key[8 * i + 15] = t; \ +} + +u32b *AES_SetKey(const u32b in_key[], const u32b key_len) +{ u32b i, t, u, v, w; + + if(!tab_gen) + gen_tabs(); + + k_len = (key_len + 31) / 32; + + for (i=0;i 6) + { + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + } + + if(k_len > 4) + { + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + } + + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + f_nround(b1, b0, kp); f_nround(b0, b1, kp); + f_nround(b1, b0, kp); f_lround(b0, b1, kp); + + out_blk[0] = bswap(b0[0]); + out_blk[1] = bswap(b0[1]); + out_blk[2] = bswap(b0[2]); + out_blk[3] = bswap(b0[3]); +}; + +/* decrypt a block of text */ + +#define i_nround(bo, bi, k) \ + i_rn(bo, bi, 0, k); \ + i_rn(bo, bi, 1, k); \ + i_rn(bo, bi, 2, k); \ + i_rn(bo, bi, 3, k); \ + k -= 4 + +#define i_lround(bo, bi, k) \ + i_rl(bo, bi, 0, k); \ + i_rl(bo, bi, 1, k); \ + i_rl(bo, bi, 2, k); \ + i_rl(bo, bi, 3, k) + +void AES_Decrypt(const u32b in_blk[4], u32b out_blk[4]) +{ u32b b0[4], b1[4], *kp; + + b0[0] = bswap(in_blk[0]) ^ e_key[4 * k_len + 24]; + b0[1] = bswap(in_blk[1]) ^ e_key[4 * k_len + 25]; + b0[2] = bswap(in_blk[2]) ^ e_key[4 * k_len + 26]; + b0[3] = bswap(in_blk[3]) ^ e_key[4 * k_len + 27]; + + kp = d_key + 4 * (k_len + 5); + + if(k_len > 6) + { + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + } + + if(k_len > 4) + { + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + } + + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + i_nround(b1, b0, kp); i_nround(b0, b1, kp); + i_nround(b1, b0, kp); i_lround(b0, b1, kp); + + out_blk[0] = bswap(b0[0]); + out_blk[1] = bswap(b0[1]); + out_blk[2] = bswap(b0[2]); + out_blk[3] = bswap(b0[3]); +}; + +enum + { + BLK_SIZE = 16, // # octets in an AES block + MAX_PACKET = 3*512, // largest packet size + N_RESERVED = 0, // reserved nonce octet value + A_DATA = 0x40, // the Adata bit in the flags + M_SHIFT = 3, // how much to shift the 3-bit M field + L_SHIFT = 0, // how much to shift the 3-bit L field + L_SIZE = 2 // size of the l(m) length field (in octets) + }; + +typedef union _block // AES cipher block + { + u32b x[BLK_SIZE/4]; // access as 8-bit octets or 32-bit words + u08b b[BLK_SIZE]; + }block; + +typedef struct _packet + { + BOOLEAN encrypted; // TRUE if encrypted + u08b TA[6]; // xmit address + int micLength; // # octets of MIC appended to plaintext (M) + int clrCount; // # cleartext octets covered by MIC + u32b pktNum[2]; // unique packet sequence number (like WEP IV) + block key; // the encryption key (K) + int length; // # octets in data[] + u08b data[MAX_PACKET+2*BLK_SIZE]; // packet contents + }packet; + + +/* + input : 256 bits, 32 bytes, 4 block for TKIP + 128 bits, 16 bytes, 2 block for CCMP, WRAP, and WEP + up to 32 block for WPA2 + output: 8 bytes MIC | Wraped key data +*/ +#define BLOCKSIZE8 8 +void AES_WRAP(u08b * plain, int plain_len, + u08b * iv, int iv_len, + u08b * kek, int kek_len, + u08b *cipher, u16b *cipher_len) + +{ + int i, j, k, nblock = plain_len/BLOCKSIZE8; +#ifdef RTL_WPA2 + static u08b R[32][BLOCKSIZE8], A[BLOCKSIZE8], xor[BLOCKSIZE8]; +#else + u08b R[4][BLOCKSIZE8], A[BLOCKSIZE8], xor[BLOCKSIZE8]; +#endif + + static packet p; + static block m,x; + + memcpy(&p.key.b , kek, kek_len); + AES_SetKey(p.key.x, BLK_SIZE*8); // run the key schedule + + //Initialize Variable + memcpy(A, iv, BLOCKSIZE8); + for(i = 0; i < nblock ; i++) + memcpy(&R[i], plain + i*BLOCKSIZE8, BLOCKSIZE8); + + //Caalculate Intermediate Values + + for(j = 0 ; j < 6 ; j++ ) + for (i = 0 ; i < nblock ; i++) + { + memcpy(&m.b, A, BLOCKSIZE8); + memcpy((&m.b[0]) + BLOCKSIZE8, &(R[i]), BLOCKSIZE8); + // => B = AES(K, A|R[i]) + AES_Encrypt(m.x,x.x); + // => A = MSB(64,B) ^t where t = (n*j) + i + memset(xor, 0, sizeof xor); + xor[7] |= ((nblock * j) + i + 1); + for(k = 0 ; k < 8 ; k++) + A[k] = x.b[k] ^ xor[k]; + // => R[i] = LSB(64,B) + for(k = 0 ; k < 8 ; k++) + R[i][k] = x.b[k + BLOCKSIZE8]; + + } + + //Output the result + memcpy(cipher, A, BLOCKSIZE8); + for(i = 0; i 32) { + printk("AES_UnWRAP Error: cipher len exceeds!\n"); + return; + } + + u08b R[32][BLOCKSIZE8], A[BLOCKSIZE8], xor[BLOCKSIZE8]; +#else + if (nblock > 4) { + printk("AES_UnWRAP Error: cipher len exceeds!\n"); + return; + } + + u08b R[4][BLOCKSIZE8], A[BLOCKSIZE8], xor[BLOCKSIZE8]; +#endif + packet *p; + block m,x; + + if ((plain_len < BLOCKSIZE8) || (plain_len < cipher_len)) { + printk("AES_UnWRAP Error: cipher len exceeds plain len!\n"); + return; + } + + p = (packet *)kmalloc(sizeof(packet), GFP_ATOMIC); + if (p == NULL) + return; + + memcpy(p->key.b , kek, kek_len); + AES_SetKey(p->key.x, BLK_SIZE*8); // run the key schedule + + //Initialize Variable + memcpy(A, cipher, BLOCKSIZE8); + for(i = 0; i < nblock ; i++) + memcpy(&R[i], cipher + (i+1)*BLOCKSIZE8, BLOCKSIZE8); + + //Compute internediate Value + for(j=5 ; j>=0 ; j--) + for(i= nblock-1 ; i>=0 ; i--) + { + // => B = AES-1((A^t) |R[i]) + + memset(xor, 0, sizeof xor); + xor[7] |= ((nblock * j) + i + 1); + for(k = 0 ; k < 8 ; k++) + x.b[k] = A[k] ^ xor[k]; + memcpy((&x.b[0]) + BLOCKSIZE8, &(R[i]), BLOCKSIZE8); + + AES_Decrypt(x.x,m.x); + + memcpy(A, &m.b[0], BLOCKSIZE8); + //for(k=0 ; k +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#include +#else +#include +#endif + +#include "./8192cd_cfg.h" + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + +//#define MODULE_TEST + +#include "1x_md5c.h" + +//sc_yang +//typedef unsigned char *POINTER; +//typedef unsigned long int UINT4; +typedef unsigned char BYTE; + +typedef struct +{ + UINT4 digest[ 5 ]; /* Message digest */ + UINT4 countLo, countHi; /* 64-bit bit count */ + UINT4 data[ 16 ]; /* SHS data buffer */ + int Endianness; +} SHA_CTX; + + +void SHAInit(SHA_CTX *); +void SHAUpdate(SHA_CTX *, BYTE *buffer, int count); +void SHAFinal(BYTE *output, SHA_CTX *); +void endianTest(int *endianness); +static void SHAtoByte(BYTE *output, UINT4 *input, unsigned int len); + +/* The SHS block size and message digest sizes, in bytes */ + +#define SHS_DATASIZE 64 +#define SHS_DIGESTSIZE 20 + +#ifndef TRUE + #define FALSE 0 + #define TRUE ( !FALSE ) +#endif + +/* The SHS f()-functions. The f1 and f3 functions can be optimized to + save one boolean operation each - thanks to Rich Schroeppel, + rcs@cs.arizona.edu for discovering this */ + +/*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) ) // Rounds 0-19 */ +#define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +/*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) // Rounds 40-59 */ +#define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + +/* The SHS Mysterious Constants */ + +#define K1 0x5A827999L /* Rounds 0-19 */ +#define K2 0x6ED9EBA1L /* Rounds 20-39 */ +#define K3 0x8F1BBCDCL /* Rounds 40-59 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ + +/* SHS initial values */ + +#define h0init 0x67452301L +#define h1init 0xEFCDAB89L +#define h2init 0x98BADCFEL +#define h3init 0x10325476L +#define h4init 0xC3D2E1F0L + +/* Note that it may be necessary to add parentheses to these macros if they + are to be called with expressions as arguments */ +/* 32-bit rotate left - kludged with shifts */ + +#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) ) + +/* The initial expanding function. The hash function is defined over an + 80-UINT2 expanded input array W, where the first 16 are copies of the input + data, and the remaining 64 are defined by + + W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] + + This implementation generates these values on the fly in a circular + buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this + optimization. + + The updated SHS changes the expanding function by adding a rotate of 1 + bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor + for this information */ + +#define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ + W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) ) + + +/* The prototype SHS sub-round. The fundamental sub-round is: + + a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; + b' = a; + c' = ROTL( 30, b ); + d' = c; + e' = d; + + but this is implemented by unrolling the loop 5 times and renaming the + variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. + This code is then replicated 20 times for each of the 4 functions, using + the next 20 values from the W[] array each time */ + +#define subRound(a, b, c, d, e, f, k, data) \ + ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) + +/* Initialize the SHS values */ + +void SHAInit(SHA_CTX *shsInfo) +{ + endianTest(&shsInfo->Endianness); + /* Set the h-vars to their initial values */ + shsInfo->digest[ 0 ] = h0init; + shsInfo->digest[ 1 ] = h1init; + shsInfo->digest[ 2 ] = h2init; + shsInfo->digest[ 3 ] = h3init; + shsInfo->digest[ 4 ] = h4init; + + /* Initialise bit count */ + shsInfo->countLo = shsInfo->countHi = 0; +} + + +/* Perform the SHS transformation. Note that this code, like MD5, seems to + break some optimizing compilers due to the complexity of the expressions + and the size of the basic block. It may be necessary to split it into + sections, e.g. based on the four subrounds + + Note that this corrupts the shsInfo->data area */ + +static void SHSTransform( UINT4 *digest,UINT4 *data ) + { + UINT4 A, B, C, D, E; /* Local vars */ + UINT4 eData[ 16 ]; /* Expanded data */ + + /* Set up first buffer and local data buffer */ + A = digest[ 0 ]; + B = digest[ 1 ]; + C = digest[ 2 ]; + D = digest[ 3 ]; + E = digest[ 4 ]; + memcpy( (POINTER)eData, (POINTER)data, SHS_DATASIZE ); + + /* Heavy mangling, in 4 sub-rounds of 20 interations each. */ + subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 2 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 3 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 4 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 5 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 6 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 7 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 8 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 9 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 10 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 11 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 12 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 13 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 14 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 15 ] ); + subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) ); + subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) ); + subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) ); + subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) ); + + subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) ); + + subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) ); + + subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); + + /* Build message digest */ + digest[ 0 ] += A; + digest[ 1 ] += B; + digest[ 2 ] += C; + digest[ 3 ] += D; + digest[ 4 ] += E; + } + +/* When run on a little-endian CPU we need to perform byte reversal on an + array of long words. */ + +static void longReverse(UINT4 *buffer, int byteCount, int Endianness ) +{ + UINT4 value; + + if (Endianness==(int)TRUE) return; + byteCount /= sizeof( UINT4 ); + while( byteCount-- ) + { + value = *buffer; + value = ( ( value & 0xFF00FF00L ) >> 8 ) | \ + ( ( value & 0x00FF00FFL ) << 8 ); + *buffer++ = ( value << 16 ) | ( value >> 16 ); + } +} + +/* Update SHS for a block of data */ + +void SHAUpdate(SHA_CTX *shsInfo, BYTE *buffer, int count) +{ + UINT4 tmp; + int dataCount; + + /* Update bitcount */ + tmp = shsInfo->countLo; + if ( ( shsInfo->countLo = tmp + ( ( UINT4 ) count << 3 ) ) < tmp ) + shsInfo->countHi++; /* Carry from low to high */ + shsInfo->countHi += count >> 29; + + /* Get count of bytes already in data */ + dataCount = ( int ) ( tmp >> 3 ) & 0x3F; + + /* Handle any leading odd-sized chunks */ + if( dataCount ) + { + BYTE *p = ( BYTE * ) shsInfo->data + dataCount; + + dataCount = SHS_DATASIZE - dataCount; + if( count < dataCount ) + { + memcpy( p, buffer, count ); + return; + } + memcpy( p, buffer, dataCount ); + longReverse( shsInfo->data, SHS_DATASIZE, shsInfo->Endianness); + SHSTransform( shsInfo->digest, shsInfo->data ); + buffer += dataCount; + count -= dataCount; + } + + /* Process data in SHS_DATASIZE chunks */ + while( count >= SHS_DATASIZE ) + { + memcpy( (POINTER)shsInfo->data, (POINTER)buffer, SHS_DATASIZE ); + longReverse( shsInfo->data, SHS_DATASIZE, shsInfo->Endianness ); + SHSTransform( shsInfo->digest, shsInfo->data ); + buffer += SHS_DATASIZE; + count -= SHS_DATASIZE; + } + + /* Handle any remaining bytes of data. */ + memcpy( (POINTER)shsInfo->data, (POINTER)buffer, count ); + } + +/* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bit pattern + 1 0* (64-bit count of bits processed, MSB-first) */ + +void SHAFinal(BYTE *output, SHA_CTX *shsInfo) +{ + int count; + BYTE *dataPtr; + + /* Compute number of bytes mod 64 */ + count = ( int ) shsInfo->countLo; + count = ( count >> 3 ) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + dataPtr = ( BYTE * ) shsInfo->data + count; + *dataPtr++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = SHS_DATASIZE - 1 - count; + + /* Pad out to 56 mod 64 */ + if( count < 8 ) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset( dataPtr, 0, count ); + longReverse( shsInfo->data, SHS_DATASIZE, shsInfo->Endianness ); + SHSTransform( shsInfo->digest, shsInfo->data ); + + /* Now fill the next block with 56 bytes */ + memset( (POINTER)shsInfo->data, 0, SHS_DATASIZE - 8 ); + } + else + /* Pad block to 56 bytes */ + memset( dataPtr, 0, count - 8 ); + + /* Append length in bits and transform */ + shsInfo->data[ 14 ] = shsInfo->countHi; + shsInfo->data[ 15 ] = shsInfo->countLo; + + longReverse( shsInfo->data, SHS_DATASIZE - 8, shsInfo->Endianness ); + SHSTransform( shsInfo->digest, shsInfo->data ); + + /* Output to an array of bytes */ + SHAtoByte(output, shsInfo->digest, SHS_DIGESTSIZE); + + /* Zeroise sensitive stuff */ + memset((POINTER)shsInfo, 0, sizeof(shsInfo)); +} + +static void SHAtoByte(BYTE *output, UINT4 *input, unsigned int len) +{ /* Output SHA digest in byte array */ + unsigned int i, j; + + for(i = 0, j = 0; j < len; i++, j += 4) + { + output[j+3] = (BYTE)( input[i] & 0xff); + output[j+2] = (BYTE)((input[i] >> 8 ) & 0xff); + output[j+1] = (BYTE)((input[i] >> 16) & 0xff); + output[j ] = (BYTE)((input[i] >> 24) & 0xff); + } +} + + +unsigned char digest[20]; +unsigned char message[3] = {'a', 'b', 'c' }; +unsigned char mess56[] = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + +/* Correct solutions from FIPS PUB 180-1 */ +char *dig1 = "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D"; +char *dig2 = "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1"; +char *dig3 = "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"; + +/* Output should look like:- + a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D <= correct + 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1 + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 <= correct + 34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F <= correct +*/ + + +/* endian.c */ + +void endianTest(int *endian_ness) +{ + if((*(unsigned short *) ("#S") >> 8) == '#') + { + /* printf("Big endian = no change\n"); */ + *endian_ness = !(0); + } + else + { + /* printf("Little endian = swap\n"); */ + *endian_ness = 0; + } +} + +/*main() +{ + SHA_CTX sha; + int i; + BYTE big[1000]; + + SHAInit(&sha); + SHAUpdate(&sha, message, 3); + SHAFinal(digest, &sha); + + for (i = 0; i < 20; i++) + { + if ((i % 4) == 0) printf(" "); + printf("%02x", digest[i]); + } + printf("\n"); + printf(" %s <= correct\n", dig1); + + SHAInit(&sha); + SHAUpdate(&sha, mess56, 56); + SHAFinal(digest, &sha); + + for (i = 0; i < 20; i++) + { + if ((i % 4) == 0) printf(" "); + printf("%02x", digest[i]); + } + printf("\n"); + printf(" %s <= correct\n", dig2); + + // Fill up big array + for (i = 0; i < 1000; i++) + big[i] = 'a'; + + SHAInit(&sha); + // Digest 1 million x 'a' + for (i = 0; i < 1000; i++) + SHAUpdate(&sha, big, 1000); + SHAFinal(digest, &sha); + + for (i = 0; i < 20; i++) + { + if ((i % 4) == 0) printf(" "); + printf("%02x", digest[i]); + } + printf("\n"); + printf(" %s <= correct\n", dig3); + + return 0; +}*/ + + +//== hmac_sha function ============================== +#ifndef SHA_DIGESTSIZE +#define SHA_DIGESTSIZE 20 +#endif + +#ifndef SHA_BLOCKSIZE +#define SHA_BLOCKSIZE 64 +#endif + +#ifndef MD5_DIGESTSIZE +#define MD5_DIGESTSIZE 16 +#endif + +#ifndef MD5_BLOCKSIZE +#define MD5_BLOCKSIZE 64 +#endif + + + +void truncate( + unsigned char* d1, /* data to be truncated */ + unsigned char* d2, /* truncated data */ + int len /* length in bytes to keep */ + ) +{ + int i ; + for (i = 0 ; i < len ; i++) d2[i] = d1[i]; +} + +void hmac_sha( + unsigned char* k, /* secret key */ + int lk, /* length of the key in bytes */ + unsigned char* d, /* data */ + int ld, /* length of data in bytes */ + unsigned char* out, /* output buffer, at least "t" bytes */ + int t + ) +{ + SHA_CTX ictx, octx ; + unsigned char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE] ; + unsigned char key[SHA_DIGESTSIZE] ; + unsigned char buf[SHA_BLOCKSIZE] ; + int i ; + + if (lk > SHA_BLOCKSIZE) + { + SHA_CTX tctx ; + + SHAInit(&tctx) ; + SHAUpdate(&tctx, k, lk) ; + SHAFinal(key, &tctx) ; + + k = key ; + lk = SHA_DIGESTSIZE ; + } + + /**** Inner Digest ****/ + + SHAInit(&ictx) ; + + /* Pad the key for inner digest */ + for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x36 ; + for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x36 ; + + SHAUpdate(&ictx, buf, SHA_BLOCKSIZE) ; + SHAUpdate(&ictx, d, ld) ; + + SHAFinal(isha, &ictx) ; + + /**** Outter Digest ****/ + + SHAInit(&octx) ; + + for (i = 0 ; i < lk ; ++i) buf[i] = k[i] ^ 0x5C ; + for (i = lk ; i < SHA_BLOCKSIZE ; ++i) buf[i] = 0x5C ; + + SHAUpdate(&octx, buf, SHA_BLOCKSIZE) ; + SHAUpdate(&octx, isha, SHA_DIGESTSIZE) ; + + SHAFinal(osha, &octx) ; + + /* truncate and print the results */ + t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t ; + truncate(osha, out, t) ; + //pr_sha(stdout, out, t) ; +} +//==================================================== + +/*void main() +{ + unsigned char secret[100]="Jefe"; + unsigned char data[100]="what do ya want for nothing?"; + unsigned char output[1000]; + hmac_sha(secret,4,data,28,output,20); +}*/ + +//////////////////////////////////////////////////////////////////// +//Added by emily +/* + * sha1.c + * + * Description: + * This file implements the Secure Hashing Algorithm 1 as + * defined in FIPS PUB 180-1 published April 17, 1995. + * + * The SHA-1, produces a 160-bit message digest for a given + * data stream. It should take about 2**n steps to find a + * message with the same digest as a given message and + * 2**(n/2) to find any two messages with the same digest, + * when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code + * uses (included via "sha1.h" to define 32 and 8 + * bit unsigned integer types. If your C compiler does not + * support 32 bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated + * for messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is + * a multiple of the size of an 8-bit character. + * + */ + +/* + * sha1.h + * + * Description: + * This is the header file for code which implements the Secure + * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published + * April 17, 1995. + * + * Many of the variable names in this code, especially the + * single character names, were used because those were the names + * used in the publication. + * + * Please read the file sha1.c for more information. + * + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +//#include +/* + * If you do not have the ISO standard stdint.h header file, then you + * must typdef the following: + * name meaning + * uint32_t unsigned 32 bit integer + * uint8_t unsigned 8 bit integer (i.e., unsigned char) + * int_least16_t integer of >= 16 bits + * + */ + +#ifndef _SHA_enum_ +#define _SHA_enum_ +enum +{ + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError /* called Input after Result */ +}; +#endif +#define SHA1HashSize 20 + +#if !defined( __KERNEL__) && !defined(__ECOS) + typedef unsigned int uint32_t; + typedef unsigned char uint8_t; +#endif +typedef unsigned short int_least16_t; +/* + * This structure will hold context information for the SHA-1 + * hashing operation + */ +typedef struct SHA1Context +{ + uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ + + uint32_t Length_Low; /* Message length in bits */ + uint32_t Length_High; /* Message length in bits */ + + /* Index into message block array */ + int_least16_t Message_Block_Index; + uint8_t Message_Block[64]; /* 512-bit message blocks */ + + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corrupted? */ +} SHA1Context; + +/* + * Function Prototypes + */ + + +int SHA1Reset( SHA1Context *); +int SHA1Input( SHA1Context *, + const uint8_t *, + unsigned int); +int SHA1Result( SHA1Context *, + uint8_t Message_Digest[SHA1HashSize]); + +#endif + +/* + * Define the SHA1 circular left shift macro + */ +#define SHA1CircularShift(bits,word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) + +/* Local Function Prototyptes */ +void SHA1PadMessage(SHA1Context *); +void SHA1ProcessMessageBlock(SHA1Context *); + +/* + * SHA1Reset + * + * Description: + * This function will initialize the SHA1Context in preparation + * for computing a new SHA1 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Reset(SHA1Context *context) +{ + if (!context) + { + return shaNull; + } + + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Intermediate_Hash[0] = 0x67452301; + context->Intermediate_Hash[1] = 0xEFCDAB89; + context->Intermediate_Hash[2] = 0x98BADCFE; + context->Intermediate_Hash[3] = 0x10325476; + context->Intermediate_Hash[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; + + return shaSuccess; +} + +/* + * SHA1Result + * + * Description: + * This function will return the 160-bit message digest into the + * Message_Digest array provided by the caller. + * NOTE: The first octet of hash is stored in the 0th element, + * the last octet of hash in the 19th element. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Result( SHA1Context *context, + uint8_t Message_Digest[SHA1HashSize]) +{ + int i; + + if (!context || !Message_Digest) + { + return shaNull; + } + + if (context->Corrupted) + { + return context->Corrupted; + } + + if (!context->Computed) + { + SHA1PadMessage(context); + for(i=0; i<64; ++i) + { + /* message may be sensitive, clear it out */ + context->Message_Block[i] = 0; + } + context->Length_Low = 0; /* and clear length */ + context->Length_High = 0; + context->Computed = 1; + + } + + for(i = 0; i < SHA1HashSize; ++i) + { + Message_Digest[i] = context->Intermediate_Hash[i>>2] + >> 8 * ( 3 - ( i & 0x03 ) ); + } + + return shaSuccess; +} + +/* + * SHA1Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update + * message_array: [in] + * An array of characters representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * sha Error Code. + * + */ +int SHA1Input( SHA1Context *context, + const uint8_t *message_array, + unsigned length) +{ + if (!length) + { + return shaSuccess; + } + + if (!context || !message_array) + { + return shaNull; + } + + if (context->Computed) + { + context->Corrupted = shaStateError; + + return shaStateError; + } + + if (context->Corrupted) + { + return context->Corrupted; + } + while(length-- && !context->Corrupted) + { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + if (context->Length_Low == 0) + { + context->Length_High++; + if (context->Length_High == 0) + { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) + { + SHA1ProcessMessageBlock(context); + } + + message_array++; + } + + return shaSuccess; +} + +/* + * SHA1ProcessMessageBlock + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the publication. + * + * + */ +void SHA1ProcessMessageBlock(SHA1Context *context) +{ + const uint32_t K[] = { /* Constants defined in SHA-1 */ + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + uint32_t temp; /* Temporary word value */ + uint32_t W[80]; /* Word sequence */ + uint32_t A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for(t = 0; t < 16; t++) + { + W[t] = context->Message_Block[t * 4] << 24; + W[t] |= context->Message_Block[t * 4 + 1] << 16; + W[t] |= context->Message_Block[t * 4 + 2] << 8; + W[t] |= context->Message_Block[t * 4 + 3]; + } + + for(t = 16; t < 80; t++) + { + W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + + for(t = 0; t < 20; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + + B = A; + A = temp; + } + + for(t = 20; t < 40; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 40; t < 60; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 60; t < 80; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + + context->Message_Block_Index = 0; +} + +/* + * SHA1PadMessage + * + + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call the ProcessMessageBlock function + * provided appropriately. When it returns, it can be assumed that + * the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * ProcessMessageBlock: [in] + * The appropriate SHA*ProcessMessageBlock function + * Returns: + * Nothing. + * + */ + +void SHA1PadMessage(SHA1Context *context) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 64) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + + SHA1ProcessMessageBlock(context); + + while(context->Message_Block_Index < 56) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + else + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 56) + { + + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = context->Length_High >> 24; + context->Message_Block[57] = context->Length_High >> 16; + context->Message_Block[58] = context->Length_High >> 8; + context->Message_Block[59] = (unsigned char)context->Length_High; + context->Message_Block[60] = context->Length_Low >> 24; + context->Message_Block[61] = context->Length_Low >> 16; + context->Message_Block[62] = context->Length_Low >> 8; + context->Message_Block[63] = (unsigned char)context->Length_Low; + + SHA1ProcessMessageBlock(context); +} + +// using a sha1 library +// +void +hmac_sha1(unsigned char *text, int text_len, unsigned char *key, + int key_len, unsigned char *digest) +{ + + SHA1Context context; + unsigned char k[20]; + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + int i; + /* if key is longer than 64 bytes reset it to key=SHA1(key) */ + if (key_len > 64) { + SHA1Context tctx; + + SHA1Reset(&tctx); + SHA1Input(&tctx, key, key_len); + SHA1Result(&tctx, k); + + key = k; + key_len = 20; + } + + /* + * the HMAC_SHA1 transform looks like: + * + * SHA1(K XOR opad, SHA1(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + memset( k_ipad, 0, sizeof k_ipad); + memset( k_opad, 0, sizeof k_opad); + memcpy( k_ipad, key, key_len); + memcpy( k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner SHA1 + */ + SHA1Reset(&context); /* init context for 1st * pass */ + SHA1Input(&context, k_ipad, 64); /* start with inner pad */ + SHA1Input(&context, text, text_len); /* then text of datagram */ + SHA1Result(&context, digest); /* finish up 1st pass */ + /* + * perform outer SHA1 + */ + SHA1Reset(&context); /* init context for 2nd pass */ + SHA1Input(&context, k_opad, 64); /* start with outer pad */ + SHA1Input(&context, digest, 20); /* then results of 1st hash */ + SHA1Result(&context, digest); /* finish up 2nd pass */ + + +} +////////////////////////////////////////////////////////////////////////////////////// +/* + * sha1test.c + * + * Description: + * This file will exercise the SHA-1 code performing the three + * tests documented in FIPS PUB 180-1 plus one which calls + * SHA1Input with an exact multiple of 512 bits, plus a few + * error test checks. + * + * Portability Issues: + * None. + * + */ + +//#include +#ifndef __KERNEL__ +#ifndef __ECOS +#include +#endif +#include +#endif +//#include "sha1.h" + +/* + * Define patterns for testing + */ +#define TEST1 "abc" +#define TEST2a "abcdbcdecdefdefgefghfghighijhi" + +#define TEST2b "jkijkljklmklmnlmnomnopnopq" +#define TEST2 TEST2a TEST2b +#define TEST3 "a" +#define TEST4a "01234567012345670123456701234567" +#define TEST4b "01234567012345670123456701234567" + /* an exact multiple of 512 bits */ +#define TEST4 TEST4a TEST4b +char *testarray[4] = +{ + TEST1, + TEST2, + TEST3, + TEST4 +}; +long int repeatcount[4] = { 1, 1, 1000000, 10 }; +char *resultarray[4] = +{ + "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D", + "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1", + "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F", + "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52" +}; + +#ifdef MODULE_TEST +int SHA1main() +{ + SHA1Context sha; + int i, j, err; + uint8_t Message_Digest[20]; + + /* + * Perform SHA-1 tests + */ + for(j = 0; j < 4; ++j) + { + /* + printf( "\nTest %d: %d, '%s'\n", + j+1, + repeatcount[j], + testarray[j]); + */ + err = SHA1Reset(&sha); + if (err) + { + /*fprintf(stderr, "SHA1Reset Error %d.\n", err );*/ + break; /* out of for j loop */ + } + + for(i = 0; i < repeatcount[j]; ++i) + { + + err = SHA1Input(&sha, + (const unsigned char *) testarray[j], + strlen(testarray[j])); + if (err) + { + /*fprintf(stderr, "SHA1Input Error %d.\n", err );*/ + break; /* out of for i loop */ + } + } + + err = SHA1Result(&sha, Message_Digest); + if (err) + { + /*fprintf(stderr, + "SHA1Result Error %d, could not compute message digest.\n", + err );*/ + } + else + { + /* + for(i = 0; i < 20 ; ++i) + { + printf("%02X ", Message_Digest[i]); + } + printf("\n"); + */ + } + /* + printf("Should match:\n"); + printf("\t%s\n", resultarray[j]); + */ + } + + /* Test some error returns */ + err = SHA1Input(&sha,(const unsigned char *) testarray[1], 1); + /*printf ("\nError %d. Should be %d.\n", err, shaStateError );*/ + err = SHA1Reset(0); + /*printf ("\nError %d. Should be %d.\n", err, shaNull );*/ + return 0; +} +#endif + +//////////////////////////////////////////////// +/// hmac_md5 +//////////////////////////////////////////////// +void +hmac_md5(unsigned char *text, int text_len, unsigned char *key, + int key_len, void * digest) +{ + MD5_CTX context; + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + wlan_MD5_Init(&tctx); + wlan_MD5_Update(&tctx, key, key_len); + wlan_MD5_Final(key, &tctx); + + //key = tctx.digest; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + memset( k_ipad, 0, sizeof k_ipad); + memset( k_opad, 0, sizeof k_opad); + memcpy( k_ipad, key, key_len); + memcpy( k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + wlan_MD5_Init(&context); /* init context for 1st * pass */ + wlan_MD5_Update(&context, k_ipad, 64); /* start with inner pad */ + wlan_MD5_Update(&context, text, text_len); /* then text of datagram */ + wlan_MD5_Final((unsigned char*)digest, &context); /* finish up 1st pass */ + //memcpy(digest, context.digest, 16); + /* + * perform outer MD5 + */ + wlan_MD5_Init(&context); /* init context for 2nd * pass */ + wlan_MD5_Update(&context, k_opad, 64); /* start with outer pad */ + wlan_MD5_Update(&context, digest, 16); /* then results of 1st * hash */ + wlan_MD5_Final((unsigned char*)digest, &context); /* finish up 2nd pass */ + //memcpy(digest, context.digest, 16); +} + +#ifdef MODULE_TEST +//Test hmac_md5 +// test vectors from rfc2202 +unsigned char key0[20] = { +0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; +unsigned char digest0[16] = { +0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d }; +unsigned char digest01[20] = { +0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00 }; +unsigned char prf01[] = { + 0xbc, 0xd4, 0xc6, 0x50, 0xb3, 0x0b, 0x96, 0x84, 0x95, 0x18, 0x29, 0xe0, 0xd7, 0x5f, 0x9d, 0x54, 0xb8, 0x62, 0x17, 0x5e, 0xd9, 0xf0, 0x06, 0x06, 0xe1, 0x7d, + 0x8d, 0xa3, 0x54, 0x02, 0xff, 0xee, 0x75, 0xdf, 0x78, 0xc3, 0xd3, 0x1e, 0x0f, 0x88, 0x9f, 0x01, 0x21, 0x20, 0xc0, 0x86, 0x2b, 0xeb, 0x67, 0x75, 0x3e, 0x74, + 0x39, 0xae, 0x24, 0x2e, 0xdb, 0x83, 0x73, 0x69, 0x83, 0x56, 0xcf, 0x5a +}; +unsigned char key1[] = "Jefe"; +unsigned char data1[] = "what do ya want for nothing?"; +unsigned char digest1[] = { 0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 }; +unsigned char digest11[] = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 }; +unsigned char prf11[] = { + 0x51, 0xf4, 0xde, 0x5b, 0x33, 0xf2, 0x49, 0xad, 0xf8, 0x1a, 0xeb, 0x71, 0x3a, 0x3c, 0x20, 0xf4, 0xfe, 0x63, 0x14, 0x46, 0xfa, 0xbd, 0xfa, 0x58, + 0x24, 0x47, 0x59, 0xae, 0x58, 0xef, 0x90, 0x09, 0xa9, 0x9a, 0xbf, 0x4e, 0xac, 0x2c, + 0xa5, 0xfa, 0x87, 0xe6, 0x92, 0xc4, 0x40, 0xeb, 0x40, 0x02, 0x3e, 0x7b, 0xab, 0xb2, 0x06, 0xd6, 0x1d, 0xe7, 0xb9, 0x2f, 0x41, 0x52, 0x90, 0x92, 0xb8, 0xfc +}; +unsigned char key2[] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }; +unsigned char data2[] = { + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD +}; +unsigned char digest2[] = { +0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 }; +unsigned char digest21[] = { +0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 }; +unsigned char prf21[] = { +0xe1, 0xac, 0x54, 0x6e, 0xc4, 0xcb, 0x63, 0x6f, 0x99, 0x76, 0x48, 0x7b, 0xe5, 0xc8, 0x6b, 0xe1, 0x7a, 0x02, 0x52, 0xca, 0x5d, 0x8d, 0x8d, 0xf1, 0x2c, 0xfb, +0x04, 0x73, 0x52, 0x52, 0x49, 0xce, 0x9d, 0xd8, 0xd1, 0x77, 0xea, 0xd7, 0x10, 0xbc, 0x9b, 0x59, 0x05, 0x47, 0x23, 0x91, 0x07, 0xae, 0xf7, 0xb4, 0xab, 0xd4, +0x3d, 0x87, 0xf0, 0xa6, 0x8f, 0x1c, 0xbd, 0x9e, 0x2b, 0x6f, 0x76, 0x07 +}; + +struct { + unsigned char *key; + int key_len; + unsigned char *data; + int data_len; + unsigned char* digest; + unsigned char* digest1; + unsigned char* prf; +} tests[] = { + { key0, + 16, // note for SHA1 this is 20 - code sets it to 20 + (unsigned char *)"Hi There", + 8, + digest0, + digest01, + prf01 + }, + { key1, + 4, + data1, + 28, + digest1, + digest11, + prf11 + }, + { key2, + 16, // sha1 20 + data2, + 50, + digest2, + digest21, + prf21 + } +}; + +extern void i_PRF( + unsigned char* secret, + int secret_len, + unsigned char* prefix, + int prefix_len, + unsigned char* random, + int random_len, + unsigned char* digest, // caller digest to be filled in + int digest_len // in byte + ); +int _tmain_hmac() +{ + unsigned char digest[20]; + unsigned char output[64+20]; + int c; + hmac_md5(tests[0].data, tests[0].data_len, tests[0].key, tests[0].key_len, digest); + c = memcmp(digest, tests[0].digest, 16); + printf("HMAC_MD5 %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n", + digest[0], digest[1], digest[2], digest[3], + digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15], !c?"Pass":"Fail"); + hmac_sha1(tests[0].data, tests[0].data_len, tests[0].key, tests[0].key_len+4, digest); + c = memcmp(digest, tests[0].digest1, 20); printf("HMAC_SHA1 %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n", + digest[0], digest[1], digest[2], digest[3], + digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15], + digest[16], digest[17], digest[18], digest[19], !c?"Pass":"Fail"); + + memset(output, 0, 64); + i_PRF(tests[0].key, tests[0].key_len+4, (unsigned char *)"prefix", 6, tests[0].data, tests[0].data_len, output, 16); + c = memcmp(output, tests[0].prf, 16); + printf("PRF %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n", + output[0], output[1], output[2], output[3], + output[4], output[5], output[6], output[7], + output[8], output[9], output[10], output[11], + output[12], output[13], output[14], output[15], + !c?"Pass":"Fail"); + + memset(output, 0, 64); + i_PRF(tests[0].key, tests[0].key_len+4, (unsigned char *)"prefix", 6, tests[0].data, tests[0].data_len, output, 64); + c = memcmp(output, tests[0].prf, 64); + printf("PRF %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ +%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ +%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ + %s\n", + output[0], output[1], output[2], output[3], + output[4], output[5], output[6], output[7], + output[8], output[9], output[10], output[11], + output[12], output[13], output[14], output[15], + output[16], output[17], output[18], output[19], + output[20], output[21], output[22], output[23], + output[24], output[25], output[26], output[27], + output[28], output[29], output[30], output[31], + output[32], output[33], output[34], output[35], + output[36], output[37], output[38], output[39], + output[40], output[41], output[42], output[43], + output[44], output[45], output[46], output[47], + output[48], output[49], output[50], output[51], + output[52], output[53], output[54], output[55], + output[56], output[57], output[58], output[59], + output[60], output[61], output[62], output[63], + !c?"Pass":"Fail"); + + + + hmac_md5(tests[1].data, tests[1].data_len, tests[1].key, tests[1].key_len, digest); + c = memcmp(digest, tests[1].digest, 16); + printf("HMAC_MD5 %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n", + digest[0], digest[1], digest[2], digest[3], + digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15], !c?"Pass":"Fail"); + hmac_sha1(tests[1].data, tests[1].data_len, tests[1].key, tests[1].key_len, digest); + c = memcmp(digest, tests[1].digest1, 20); + printf("HMAC_SHA1 %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n", + digest[0], digest[1], digest[2], digest[3], + digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15], + digest[16], digest[17], digest[18], digest[19], !c?"Pass":"Fail"); + + memset(output, 0, 64); + i_PRF(tests[1].key, tests[1].key_len, (unsigned char *)"prefix", 6, tests[1].data, tests[1].data_len, output, 16); + c = memcmp(output, tests[1].prf, 16); + printf("PRF %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n", + output[0], output[1], output[2], output[3], + output[4], output[5], output[6], output[7], + output[8], output[9], output[10], output[11], + output[12], output[13], output[14], output[15], + !c?"Pass":"Fail"); + + memset(output, 0, 64); + i_PRF(tests[1].key, tests[1].key_len, (unsigned char *)"prefix", 6, tests[1].data, tests[1].data_len, output, 64); + c = memcmp(output, tests[1].prf, 64); + printf("PRF %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ +%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ +%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ + %s\n", + output[0], output[1], output[2], output[3], + output[4], output[5], output[6], output[7], + output[8], output[9], output[10], output[11], + output[12], output[13], output[14], output[15], + output[16], output[17], output[18], output[19], + output[20], output[21], output[22], output[23], + output[24], output[25], output[26], output[27], + output[28], output[29], output[30], output[31], + output[32], output[33], output[34], output[35], + output[36], output[37], output[38], output[39], + output[40], output[41], output[42], output[43], + output[44], output[45], output[46], output[47], + output[48], output[49], output[50], output[51], + output[52], output[53], output[54], output[55], + output[56], output[57], output[58], output[59], + output[60], output[61], output[62], output[63], + !c?"Pass":"Fail"); + + + hmac_md5(tests[2].data, tests[2].data_len, tests[2].key, tests[2].key_len, digest); + c = memcmp(digest, tests[2].digest, 16); + printf("HMAC_MD5 %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n", + digest[0], digest[1], digest[2], digest[3], + digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15], !c?"Pass":"Fail"); + hmac_sha1(tests[2].data, tests[2].data_len, tests[2].key, tests[2].key_len+4, digest); + c = memcmp(digest, tests[2].digest1, 20); + printf("HMAC_SHA1 %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n", + digest[0], digest[1], digest[2], digest[3], + digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], + digest[12], digest[13], digest[14], digest[15], + digest[16], digest[17], digest[18], digest[19], !c?"Pass":"Fail"); + + memset(output, 0, 64); + i_PRF(tests[2].key, tests[2].key_len+4, (unsigned char *)"prefix", 6, tests[2].data, tests[2].data_len, output, 16); + c = memcmp(output, tests[2].prf, 16); + printf("PRF %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n", + output[0], output[1], output[2], output[3], + output[4], output[5], output[6], output[7], + output[8], output[9], output[10], output[11], + output[12], output[13], output[14], output[15], + !c?"Pass":"Fail"); + + memset(output, 0, 64); + i_PRF(tests[2].key, tests[2].key_len+4, (unsigned char *)"prefix", 6, tests[2].data, tests[2].data_len, output, 64); + c = memcmp(output, tests[2].prf, 64); + printf("PRF %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ +%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ +%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\ + %s\n", + output[0], output[1], output[2], output[3], + output[4], output[5], output[6], output[7], + output[8], output[9], output[10], output[11], + output[12], output[13], output[14], output[15], + output[16], output[17], output[18], output[19], + output[20], output[21], output[22], output[23], + output[24], output[25], output[26], output[27], + output[28], output[29], output[30], output[31], + output[32], output[33], output[34], output[35], + output[36], output[37], output[38], output[39], + output[40], output[41], output[42], output[43], + output[44], output[45], output[46], output[47], + output[48], output[49], output[50], output[51], + output[52], output[53], output[54], output[55], + output[56], output[57], output[58], output[59], + output[60], output[61], output[62], output[63], + !c?"Pass":"Fail"); + + /* + int j; + char key[80]; + for(j=0;j<80;j++) + key[j] = 0xaa; + //hmac_sha1((unsigned char*)"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + // , 73, (unsigned char*)key, 80, digest); + + hmac_sha( + (unsigned char*) key, + 80, + (unsigned char*)"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", + 73, + digest, + 20 + ); + */ + return 0; +} +#endif +#endif // INCLUDE_WPA_PSK diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_md5c.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_md5c.c new file mode 100755 index 000000000..be2f848b5 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_md5c.c @@ -0,0 +1,418 @@ +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +//#include "8021x.h" +#include "./8192cd_cfg.h" + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + +#include "1x_md5c.h" + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform(UINT4 [4], UINT8 [64]); +static void Encode(UINT8 *, UINT4 *, UINT32); +static void Decode(UINT4 *, UINT8 *, UINT32); +static void MD5_memcpy(POINTER, POINTER, UINT32); +static void MD5_memset(POINTER, int, UINT32); + +static UINT8 PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void wlan_MD5_Init (context) +MD5_CTX *context; /* context */ +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void wlan_MD5_Update (context, input, inputLen) +MD5_CTX *context; /* context */ +UINT8 *input; /* input block */ +UINT32 inputLen; /* length of input block */ +{ + UINT32 i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (UINT32)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) + + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. +*/ + if (inputLen >= partLen) { + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)&input[i], + inputLen-i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +void wlan_MD5_Final (digest, context) +UINT8 digest[16]; /* message digest */ +MD5_CTX *context; /* context */ +{ + UINT8 bits[8]; + UINT32 index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. +*/ + index = (UINT32)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + wlan_MD5_Update (context, PADDING, padLen); + + /* Append length (before padding) */ + wlan_MD5_Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. +*/ + MD5_memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void MD5Transform (state, block) +UINT4 state[4]; +UINT8 block[64]; +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. + +*/ + MD5_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (UINT8). Assumes len is + a multiple of 4. + */ +static void Encode (output, input, len) +UINT8 *output; +UINT4 *input; +UINT32 len; +{ + UINT32 i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (UINT8)(input[i] & 0xff); + output[j+1] = (UINT8)((input[i] >> 8) & 0xff); + output[j+2] = (UINT8)((input[i] >> 16) & 0xff); + output[j+3] = (UINT8)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (UINT8) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void Decode (output, input, len) +UINT4 *output; +UINT8 *input; +UINT32 len; +{ + UINT32 i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); +} + +/* Note: Replace "for loop" with standard memcpy if possible. + */ + +static void MD5_memcpy (output, input, len) +POINTER output; +POINTER input; +UINT32 len; +{ + UINT32 i; + + for (i = 0; i < len; i++) + + output[i] = input[i]; +} + +/* Note: Replace "for loop" with standard memset if possible. + */ +static void MD5_memset (output, value, len) +POINTER output; +int value; +UINT32 len; +{ + UINT32 i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} + + + +#if 0 +/* +UINT8* text; pointer to data stream +int text_len; length of data stream +UINT8* key; pointer to authentication key +int key_len; length of authentication key +UINT8* digest; caller digest to be filled in +*/ +void hmac_md5(UINT8 *text, INT32 text_len, UINT8 *key, INT32 key_len,UINT8 *digest) +{ + MD5_CTX context; + UINT8 k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + UINT8 k_opad[65]; /* outer padding - + * key XORd with opad + */ + UINT8 tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + memset(k_ipad, 0x0, sizeof(k_ipad)); + memset(k_opad, 0x0, sizeof(k_opad)); + memcpy(k_ipad, key, key_len); + memcpy(k_opad, key, key_len); + + //bzero( k_ipad, sizeof k_ipad); + //bzero( k_opad, sizeof k_opad); + //bcopy( key, k_ipad, key_len); + //bcopy( key, k_opad, key_len); + + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + MD5Init(&context); /* init context for 1st + * pass */ + MD5Update(&context, k_ipad, 64); /* start with inner pad */ + MD5Update(&context, text, text_len); /* then text of datagram */ + MD5Final(digest, &context); /* finish up 1st pass */ + /* + * perform outer MD5 + */ + MD5Init(&context); /* init context for 2nd + * pass */ + MD5Update(&context, k_opad, 64); /* start with outer pad */ + MD5Update(&context, digest, 16); /* then results of 1st + * hash */ + MD5Final(digest, &context); /* finish up 2nd pass */ +} +#endif +#endif // INCLUDE_WPA_PSK diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_md5c.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_md5c.h new file mode 100755 index 000000000..2283bb2a9 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_md5c.h @@ -0,0 +1,63 @@ +/* + * 8021x_md5c.h - header file for MD5C.C + */ + +#ifndef P8021X_MD5C_H +#define P8021X_MD5C_H + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this + +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + + +/* MD5_TYPE.H - RSAREF types and constants */ + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +/* UINT4 defines a four byte word */ +typedef unsigned int UINT4; + +#if 0 +typedef unsigned char UINT8; +typedef unsigned long UINT32; +typedef int INT32; +#endif + + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void wlan_MD5_Init(MD5_CTX *); +void wlan_MD5_Update(MD5_CTX *, UINT8 *, UINT32); +void wlan_MD5_Final(unsigned char [16], MD5_CTX *); +//void hmac_md5(UINT8 *, INT32, UINT8 * , INT32, UINT8 * ); + + +#endif diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_rc4.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_rc4.c new file mode 100755 index 000000000..289abb35b --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_rc4.c @@ -0,0 +1,371 @@ +/* crypto/rc4/rc4_enc.c */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +#include "./8192cd_cfg.h" + +#ifdef INCLUDE_WPA_PSK + +#include "1x_rc4.h" + +/* RC4 as implemented from a posting from + * Newsgroups: sci.crypt + * From: sterndark@netcom.com (David Sterndark) + * Subject: RC4 Algorithm revealed. + * Message-ID: + * Date: Wed, 14 Sep 1994 06:35:31 GMT + */ + +void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata, + unsigned char *outdata) + { + register RC4_INT *d; + register RC4_INT x,y,tx,ty; + int i; + + x=key->x; + y=key->y; + d=key->data; + +#if defined(RC4_CHUNK) + /* + * The original reason for implementing this(*) was the fact that + * pre-21164a Alpha CPUs don't have byte load/store instructions + * and e.g. a byte store has to be done with 64-bit load, shift, + * and, or and finally 64-bit store. Peaking data and operating + * at natural word size made it possible to reduce amount of + * instructions as well as to perform early read-ahead without + * suffering from RAW (read-after-write) hazard. This resulted + * in ~40%(**) performance improvement on 21064 box with gcc. + * But it's not only Alpha users who win here:-) Thanks to the + * early-n-wide read-ahead this implementation also exhibits + * >40% speed-up on SPARC and 20-30% on 64-bit MIPS (depending + * on sizeof(RC4_INT)). + * + * (*) "this" means code which recognizes the case when input + * and output pointers appear to be aligned at natural CPU + * word boundary + * (**) i.e. according to 'apps/openssl speed rc4' benchmark, + * crypto/rc4/rc4speed.c exhibits almost 70% speed-up... + * + * Cavets. + * + * - RC4_CHUNK="unsigned long long" should be a #1 choice for + * UltraSPARC. Unfortunately gcc generates very slow code + * (2.5-3 times slower than one generated by Sun's WorkShop + * C) and therefore gcc (at least 2.95 and earlier) should + * always be told that RC4_CHUNK="unsigned long". + * + * + */ + +# define RC4_STEP ( \ + x=(x+1) &0xff, \ + tx=d[x], \ + y=(tx+y)&0xff, \ + ty=d[y], \ + d[y]=tx, \ + d[x]=ty, \ + (RC4_CHUNK)d[(tx+ty)&0xff]\ + ) + + if ( ( ((unsigned long)indata & (sizeof(RC4_CHUNK)-1)) | + ((unsigned long)outdata & (sizeof(RC4_CHUNK)-1)) ) == 0 ) + { + RC4_CHUNK ichunk,otp; + const union { long one; char little; } is_endian = {1}; + + /* + * I reckon we can afford to implement both endian + * cases and to decide which way to take at run-time + * because the machine code appears to be very compact + * and redundant 1-2KB is perfectly tolerable (i.e. + * in case the compiler fails to eliminate it:-). By + * suggestion from Terrel Larson + * who also stands for the is_endian union:-) + * + * Special notes. + * + * - is_endian is declared automatic as doing otherwise + * (declaring static) prevents gcc from eliminating + * the redundant code; + * - compilers (those I've tried) don't seem to have + * problems eliminating either the operators guarded + * by "if (sizeof(RC4_CHUNK)==8)" or the condition + * expressions themselves so I've got 'em to replace + * corresponding #ifdefs from the previous version; + * - I chose to let the redundant switch cases when + * sizeof(RC4_CHUNK)!=8 be (were also #ifdefed + * before); + * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in + * [LB]ESHFT guards against "shift is out of range" + * warnings when sizeof(RC4_CHUNK)!=8 + * + * + */ + if (!is_endian.little) + { /* BIG-ENDIAN CASE */ +# define BESHFT(c) (((sizeof(RC4_CHUNK)-(c)-1)*8)&(sizeof(RC4_CHUNK)*8-1)) + for (;len&-sizeof(RC4_CHUNK);len-=sizeof(RC4_CHUNK)) + { + ichunk = *(RC4_CHUNK *)indata; + otp = RC4_STEP<x=x; + key->y=y; + return; + } + else + { /* LITTLE-ENDIAN CASE */ +# define LESHFT(c) (((c)*8)&(sizeof(RC4_CHUNK)*8-1)) + for (;len&-sizeof(RC4_CHUNK);len-=sizeof(RC4_CHUNK)) + { + ichunk = *(RC4_CHUNK *)indata; + otp = RC4_STEP; + otp |= RC4_STEP<<8; + otp |= RC4_STEP<<16; + otp |= RC4_STEP<<24; + if (sizeof(RC4_CHUNK)==8) + { + otp |= RC4_STEP<>= (sizeof(RC4_CHUNK)-len)<<3; + switch (len&(sizeof(RC4_CHUNK)-1)) + { + case 7: otp = RC4_STEP, i+=8; + case 6: otp |= RC4_STEP<x=x; + key->y=y; + return; + } + } +#endif +#define LOOP(in,out) \ + x=((x+1)&0xff); \ + tx=d[x]; \ + y=(tx+y)&0xff; \ + d[x]=ty=d[y]; \ + d[y]=tx; \ + (out) = d[(tx+ty)&0xff]^ (in); + +#ifndef RC4_INDEX +#define RC4_LOOP(a,b,i) LOOP(*((a)++),*((b)++)) +#else +#define RC4_LOOP(a,b,i) LOOP(a[i],b[i]) +#endif + + i=(int)(len>>3L); + if (i) + { + for (;;) + { + RC4_LOOP(indata,outdata,0); + RC4_LOOP(indata,outdata,1); + RC4_LOOP(indata,outdata,2); + RC4_LOOP(indata,outdata,3); + RC4_LOOP(indata,outdata,4); + RC4_LOOP(indata,outdata,5); + RC4_LOOP(indata,outdata,6); + RC4_LOOP(indata,outdata,7); +#ifdef RC4_INDEX + indata+=8; + outdata+=8; +#endif + if (--i == 0) break; + } + } + i=(int)len&0x07; + if (i) + { + for (;;) + { + RC4_LOOP(indata,outdata,0); if (--i == 0) break; + RC4_LOOP(indata,outdata,1); if (--i == 0) break; + RC4_LOOP(indata,outdata,2); if (--i == 0) break; + RC4_LOOP(indata,outdata,3); if (--i == 0) break; + RC4_LOOP(indata,outdata,4); if (--i == 0) break; + RC4_LOOP(indata,outdata,5); if (--i == 0) break; + RC4_LOOP(indata,outdata,6); if (--i == 0) break; + } + } + key->x=x; + key->y=y; + } +#ifndef COMPACK_SIZE +const char *RC4_options(void) + { +#ifdef RC4_INDEX + if (sizeof(RC4_INT) == 1) + return("rc4(idx,char)"); + else + return("rc4(idx,int)"); +#else + if (sizeof(RC4_INT) == 1) + return("rc4(ptr,char)"); + else + return("rc4(ptr,int)"); +#endif + } +#endif +/* RC4 as implemented from a posting from + * Newsgroups: sci.crypt + * From: sterndark@netcom.com (David Sterndark) + * Subject: RC4 Algorithm revealed. + * Message-ID: + * Date: Wed, 14 Sep 1994 06:35:31 GMT + */ + +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data) +{ + register RC4_INT tmp; + register int id1,id2; + register RC4_INT *d; + unsigned int i; + + d= &(key->data[0]); + for (i=0; i<256; i++) + d[i]=i; + key->x = 0; + key->y = 0; + id1=id2=0; + +#define SK_LOOP(n) { \ + tmp=d[(n)]; \ + id2 = (data[id1] + tmp + id2) & 0xff; \ + if (++id1 == len) id1=0; \ + d[(n)]=d[id2]; \ + d[id2]=tmp; } + + for (i=0; i < 256; i+=4) + { + SK_LOOP(i+0); + SK_LOOP(i+1); + SK_LOOP(i+2); + SK_LOOP(i+3); + } +} +#endif // INCLUDE_WPA_PSK diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_rc4.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_rc4.h new file mode 100755 index 000000000..97124e8e6 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/1x_rc4.h @@ -0,0 +1,89 @@ +/* crypto/rc4/rc4.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RC4_H +#define HEADER_RC4_H + +#ifdef OPENSSL_NO_RC4 +#error RC4 is disabled. +#endif + +//#include /* RC4_INT */ +#define RC4_INT unsigned int + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct rc4_key_st + { + RC4_INT x,y; + RC4_INT data[256]; + } RC4_KEY; + + +const char *RC4_options(void); +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data); +void RC4(RC4_KEY *key, unsigned long len, const unsigned char *indata, + unsigned char *outdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8188e_hw.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8188e_hw.c new file mode 100755 index 000000000..da03f312d --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8188e_hw.c @@ -0,0 +1,1779 @@ +/* + * Routines to access hardware + * + * $Id: 8188e_hw.c,v 1.1 2012/05/16 13:21:01 jimmylin Exp $ + * + * Copyright (c) 2012 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifdef __ECOS +#include +#include +#include +#include +#endif + + +#define _8188E_HW_C_ + +#include "8192cd_cfg.h" +#include "8192cd.h" +#include "8192cd_util.h" + +#include "8192c_reg.h" +#include "8188e_reg.h" + +#ifdef CONFIG_RTL_88E_SUPPORT + +#ifdef TXREPORT +#ifdef __KERNEL__ +#include +#endif +#include "8192cd_debug.h" +#include "8192cd_headers.h" + + + +void RTL8188E_EnableTxReport(struct rtl8192cd_priv *priv) +{ + DEBUG_INFO("%s %d\n", __FUNCTION__, __LINE__); + RTL_W16(REG_88E_TXRPT_TIM, 0xffff); /* unit: 32us */ + RTL_W32(REG_88E_TXRPT_CTRL, TXRPT_CTRL_88E_TXRPT_EN); +} + + +void RTL8188E_DisableTxReport(struct rtl8192cd_priv *priv) +{ + DEBUG_INFO("%s %d\n", __FUNCTION__, __LINE__); + RTL_W32(REG_88E_TXRPT_CTRL, 0); + RTL_W16(REG_88E_TXRPT_TIM, 0); +} + + +void RTL8188E_ResumeTxReport(struct rtl8192cd_priv *priv) +{ + DEBUG_INFO("%s %d\n", __FUNCTION__, __LINE__); + RTL_W32(REG_88E_TXRPT_CTRL, RTL_R32(REG_88E_TXRPT_CTRL) | TXRPT_CTRL_88E_TXRPT_TIM_EN); +} + + +void RTL8188E_SuspendTxReport(struct rtl8192cd_priv *priv) +{ + DEBUG_INFO("%s %d\n", __FUNCTION__, __LINE__); + RTL_W32(REG_88E_TXRPT_CTRL, RTL_R32(REG_88E_TXRPT_CTRL) & ~TXRPT_CTRL_88E_TXRPT_TIM_EN); +} + + +static unsigned int findout_max_macid(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + struct list_head *phead, *plist; + unsigned int max_macid = 0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while(plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if(pstat->sta_in_firmware != 1) + continue; + + if (REMAP_AID(pstat) > max_macid) + max_macid = REMAP_AID(pstat); + } + + SMP_UNLOCK_ASOC_LIST(flags); + + return max_macid; +} + +#ifdef RATEADAPTIVE_BY_ODM +void RTL8188E_SetStationTxRateInfo(PDM_ODM_T pDM_Odm, PODM_RA_INFO_T pRAInfo, int MacID) +{ + struct rtl8192cd_priv *priv = pDM_Odm->priv; + PSTA_INFO_T pstat = pDM_Odm->pODM_StaInfo[MacID]; +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + struct aid_obj *aidobj; +#endif + + if( !MacID || !pstat) + return; + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + aidobj = container_of(pstat, struct aid_obj, station); + priv = aidobj->priv; +#endif + + if (priv->pmib->dot11StationConfigEntry.autoRate) { + if (pRAInfo->RateSGI) + pstat->ht_current_tx_info |= TX_USE_SHORT_GI; + else + pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; + + if (pstat->ht_cap_len) { + if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40)) + pstat->ht_current_tx_info |= TX_USE_40M_MODE; + else + pstat->ht_current_tx_info &= ~TX_USE_40M_MODE; + } + + if ((pRAInfo->DecisionRate&0x3f) < 12) + pstat->current_tx_rate = dot11_rate_table[pRAInfo->DecisionRate&0x3f]; + else if ((pRAInfo->DecisionRate&0x3f) <= 27) + pstat->current_tx_rate = HT_RATE_ID|((pRAInfo->DecisionRate&0x3f) -12); + else + DEBUG_WARN("%s %d, DecisionRate mismatched as 0x%02x\n", __FUNCTION__, __LINE__, pRAInfo->DecisionRate); + + priv->pshare->current_tx_rate = pstat->current_tx_rate; + priv->pshare->ht_current_tx_info = pstat->ht_current_tx_info; + } +} +#else +static void RTL8188E_SetStationTxRateInfo(struct rtl8192cd_priv *priv, PSTATION_RA_INFO pRaInfo) +{ + if (pRaInfo->RateSGI) + pRaInfo->pstat->ht_current_tx_info |= TX_USE_SHORT_GI; + else + pRaInfo->pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; + + if (pRaInfo->pstat->ht_cap_len) { + if (priv->pshare->is_40m_bw && (pRaInfo->pstat->tx_bw == HT_CHANNEL_WIDTH_20_40)) + pRaInfo->pstat->ht_current_tx_info |= TX_USE_40M_MODE; + else + pRaInfo->pstat->ht_current_tx_info &= ~TX_USE_40M_MODE; + } + + if ((pRaInfo->DecisionRate&0x3f) < 12) + pRaInfo->pstat->current_tx_rate = dot11_rate_table[pRaInfo->DecisionRate]; + else if ((pRaInfo->DecisionRate&0x3f) <= 27) + pRaInfo->pstat->current_tx_rate = HT_RATE_ID|((pRaInfo->DecisionRate&0x3f) -12); + else + DEBUG_WARN("%s %d, DecisionRate mismatched as 0x%02x\n", __FUNCTION__, __LINE__, pRaInfo->DecisionRate); + + priv->pshare->current_tx_rate = pRaInfo->pstat->current_tx_rate; + priv->pshare->ht_current_tx_info = pRaInfo->pstat->ht_current_tx_info; +} + +#endif + +void RTL8188E_AssignTxReportMacId(struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_priv *tmp_root_priv = GET_ROOT(priv); + unsigned int max_macid = 0; +#ifdef MBSSID + unsigned int i = 0; +#endif +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + unsigned int temp_macid = 0; +#endif + + /* find out the largest macid */ + max_macid = findout_max_macid(tmp_root_priv); +#ifdef UNIVERSAL_REPEATER + if (GET_VXD_PRIV(tmp_root_priv) && netif_running(GET_VXD_PRIV(tmp_root_priv)->dev)) { + temp_macid = findout_max_macid(GET_VXD_PRIV(tmp_root_priv)); + if (temp_macid > max_macid) + max_macid = temp_macid; + } +#endif +#ifdef MBSSID + if (tmp_root_priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) { + temp_macid = findout_max_macid(tmp_root_priv->pvap_priv[i]); + if (temp_macid > max_macid) + max_macid = temp_macid; + } + } + } +#endif + + /* assign new macid for tx report setting iff it is different from the previous one */ + if (max_macid && (priv->pshare->txRptMacid != max_macid)) { + RTL_W32(REG_88E_TXRPT_CTRL, (RTL_R32(REG_88E_TXRPT_CTRL) + & (~(TXRPT_CTRL_88E_RPT_MACID_Mask << TXRPT_CTRL_88E_RPT_MACID_SHIFT))) + | (((max_macid+1) & TXRPT_CTRL_88E_RPT_MACID_Mask) << TXRPT_CTRL_88E_RPT_MACID_SHIFT) +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + | TXRPT_CTRL_88E_TXRPT_TIM_EN +#endif + ); + + DEBUG_INFO("%s %d, preTxRptMacid: %d, newTxRptMacid: %d\n", __FUNCTION__, __LINE__, priv->pshare->txRptMacid, max_macid); + priv->pshare->txRptMacid = max_macid; + } +} + +#ifdef DETECT_STA_EXISTANCE +void RTL8188E_DetectSTAExistance(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat) +{ + const unsigned int txFailSecThr= 3; // threshold of Tx Fail Time (in second) + + if(OPMODE & WIFI_STATION_STATE) + return; + + if (report->txok) + { // Reset Counter + pstat->tx_conti_fail_cnt = 0; + pstat->tx_last_good_time = priv->up_time; + if (pstat->leave!= 0) { + pstat->leave = 0; + RTL8188E_MACID_NOLINK(priv, 0, REMAP_AID(pstat)); + } + } + else if (report->txfail) + { + if (pstat->leave) + return; + + pstat->tx_conti_fail_cnt += report->txfail; + if((pstat->tx_conti_fail_cnt >= priv->pshare->rf_ft_var.max_pkt_fail) || + (pstat->tx_conti_fail_cnt >= priv->pshare->rf_ft_var.min_pkt_fail && priv->up_time >= (pstat->tx_last_good_time+txFailSecThr) ) + ) { + DEBUG_INFO("sta aid:%d leave\n", pstat->aid); + ++(pstat->leave); + RTL8188E_MACID_NOLINK(priv, 1, REMAP_AID(pstat)); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + free_sta_tx_skb(priv, pstat); +#endif + + // Reset Counter + pstat->tx_conti_fail_cnt = 0; + pstat->tx_last_good_time = priv->up_time; + } + } +} +#endif +#ifndef RATEADAPTIVE_BY_ODM + +void RTL8188E_TxReportHandler(struct rtl8192cd_priv *priv, struct sk_buff *pskb, unsigned int bitmapLowByte, + unsigned int bitmapHighByte, struct rx_desc* pdesc) +{ + PSTATION_RA_INFO pRaInfo = NULL; + unsigned char* Buffer= NULL; + unsigned char i = 0; + unsigned int offset = 0; + unsigned short minRptTime = 0xffff /*0x927c*/; + struct rx_frinfo *pfrinfo = get_pfrinfo(pskb); + + struct rtl8192cd_priv *priv_root = priv; + struct stat_info *pstat; + struct tx_rpt rpt1; + + for(i = 1; i <= priv->pshare->txRptMacid; i++) { + if (i >= 32) { + if (!(bitmapHighByte & BIT(i-32))) + continue; + } else { + if (!(bitmapLowByte & BIT(i))) + continue; + } + + do { + pstat = get_macidinfo(priv_root, i); + if (pstat) { + priv = priv_root; + break; + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv_root))) { + pstat = get_macidinfo(GET_VXD_PRIV(priv_root), i); + if (pstat) { + priv = GET_VXD_PRIV(priv_root); + break; + } + } +#endif +#ifdef MBSSID + if (priv_root->pmib->miscEntry.vap_enable) { + int idx; + for (idx=0; idxpvap_priv[idx])) { + pstat = get_macidinfo(priv_root->pvap_priv[idx], i); + if (pstat) { + priv = priv_root->pvap_priv[idx]; + break; + } + } + } + } +#endif + } while (0); + + if (NULL == pstat) + continue; + + pRaInfo = &(priv_root->pshare->RaInfo[pstat->aid]); + if (!pRaInfo->pstat) + continue; + + offset = i << 3; // Start of entry RA data + DEBUG_INFO("%s %d, MacId=%d offset=%d\n", __FUNCTION__, __LINE__, i, offset); + + if(offset + 8 > pfrinfo->pktlen) { + DEBUG_WARN("%s %d, offset + 8 > pfrinfo->pktlen, break!!\n", __FUNCTION__, __LINE__); + break; + } else { + Buffer = pskb->data + offset; + if (!Buffer[0] && !Buffer[1] && !Buffer[2] && !Buffer[3] && !Buffer[4] && !Buffer[5] && !Buffer[6] && !Buffer[7]) { + printk("\n%s %d, rpt but not update for aid:%d\n", __FUNCTION__, __LINE__, i); +#ifdef CONFIG_PCI_HCI + RTL_W8(0x3a, 0xff); /* for CATC triggering only, meaningless */ +#endif + printk("=====rxdesc=====\n"); + printk("D0:0x%08x, D1:0x%08x, D2:0x%08x, D3:0x%08x, \nD4:0x%08x, D5:0x%08x", + get_desc(pdesc->Dword0), get_desc(pdesc->Dword1), get_desc(pdesc->Dword2), get_desc(pdesc->Dword3), + get_desc(pdesc->Dword4), get_desc(pdesc->Dword5)); +#ifdef CONFIG_PCI_HCI + printk(", D6:0x%08x, D7:0x%08x", get_desc(pdesc->Dword6), get_desc(pdesc->Dword7)); +#endif + printk("\n=====rxdesc=====\n"); + printk("=====buffer=====\n"); + /* printk("B0:0x%08x, B1:0x%08x, B2:0x%08x, B3:0x%08x\n", + (unsigned int)(pskb->data[0]), (unsigned int)(pskb->data[4]), (unsigned int)(pskb->data[8]), (unsigned int)(pskb->data[12]));*/ + printk("B0:0x%02x, B1:0x%02x, B2:0x%02x, B3:0x%02x, B4:0x%02x, B5:0x%02x, B6:0x%02x, B7:0x%02x, B8:0x%02x, B9:0x%02x, B10:0x%02x, B11:0x%02x, B12:0x%02x, B13:0x%02x, B14:0x%02x, B15:0x%02x\n", + pskb->data[0], pskb->data[1], pskb->data[2], pskb->data[3], + pskb->data[4], pskb->data[5], pskb->data[6], pskb->data[7], + pskb->data[8], pskb->data[9], pskb->data[10], pskb->data[11], + pskb->data[12], pskb->data[13], pskb->data[14], pskb->data[15]); + printk("=====buffer=====\n\n"); + continue; + } + + pRaInfo->RTY[0] = (unsigned short)(Buffer[1] << 8 | Buffer[0]); + pRaInfo->RTY[1] = Buffer[2]; + pRaInfo->RTY[2] = Buffer[3]; + pRaInfo->RTY[3] = Buffer[4]; + pRaInfo->RTY[4] = Buffer[5]; + pRaInfo->DROP = Buffer[6]; + + pRaInfo->TOTAL = pRaInfo->RTY[0] + pRaInfo->RTY[1] + pRaInfo->RTY[2] + pRaInfo->RTY[3] + + pRaInfo->RTY[4] + pRaInfo->DROP; + + DEBUG_INFO("%s %d, macid %d R0=%d R1=%d R2=%d R3=%d R4=%d D0=%d Total=%d, HB: 0x%08x LB: 0x%08x vld_hi:0x%08x, vld_lo:0x%08x\n", + __FUNCTION__, __LINE__, i, + pRaInfo->RTY[0], + pRaInfo->RTY[1], + pRaInfo->RTY[2], + pRaInfo->RTY[3], + pRaInfo->RTY[4], + pRaInfo->DROP, + pRaInfo->TOTAL, + (unsigned int)(Buffer[7] << 24 | Buffer[6]<<16|Buffer[5] << 8 | Buffer[4]), + (unsigned int)(Buffer[3] << 24 | Buffer[2]<<16|Buffer[1] << 8 | Buffer[0]), + bitmapHighByte, bitmapLowByte); + + if (priv->pmib->dot11StationConfigEntry.autoRate) { + RateDecision(priv, pRaInfo); + RTL8188E_SetStationTxRateInfo(priv, pRaInfo); + } + + rpt1.macid = i; + rpt1.txok = pRaInfo->RTY[0] + pRaInfo->RTY[1] + pRaInfo->RTY[2] + pRaInfo->RTY[3] + pRaInfo->RTY[4]; + rpt1.txfail = pRaInfo->DROP; + _txrpt_handler(priv, pstat, &rpt1); + } + + if(minRptTime > pRaInfo->RptTime) + minRptTime = pRaInfo->RptTime; + } + + if (minRptTime != 0xffff) { +#if defined(CONFIG_PCI_HCI) + RTL_W16(REG_88E_TXRPT_TIM, minRptTime); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_tx_report_interval_change(priv, minRptTime); +#endif + } +} + + +void RTL8188E_SetTxReportTimeByRA(struct rtl8192cd_priv *priv, int extend) +{ +// extern unsigned short DynamicTxRPTTiming[]; + extern unsigned char TxRPTTiming_idx; + +// unsigned short WriteTxRPTTiming; + unsigned char idx; + + idx=TxRPTTiming_idx; + if (extend==0) { // back to default timing + idx=1; //400ms + } else if (extend==1) {// increase the timing + idx+=1; + if (idx>5) + idx=5; + } else if (extend==2) {// decrease the timing + if(idx!=0) + idx-=1; + } +// WriteTxRPTTiming=DynamicTxRPTTiming[idx]; + TxRPTTiming_idx=idx; +} +#endif +#endif + +#ifdef CONFIG_PCI_HCI +static inline +#endif +void __RTL8188E_MACID_NOLINK(struct rtl8192cd_priv *priv, unsigned int nolink, unsigned int aid) +{ + if (nolink) { + if (aid > 31) + RTL_W32(REG_88E_MACID_NOLINK+4, RTL_R32(REG_88E_MACID_NOLINK+4) | BIT(aid -31)); + else + RTL_W32(REG_88E_MACID_NOLINK, RTL_R32(REG_88E_MACID_NOLINK) | BIT(aid)); + } else { + if (aid > 31) + RTL_W32(REG_88E_MACID_NOLINK+4, RTL_R32(REG_88E_MACID_NOLINK+4) & ~BIT(aid-31)); + else + RTL_W32(REG_88E_MACID_NOLINK, RTL_R32(REG_88E_MACID_NOLINK) & ~BIT(aid)); + } +} + +void RTL8188E_MACID_NOLINK(struct rtl8192cd_priv *priv, unsigned int nolink, unsigned int aid) +{ + if (!priv->pshare->rf_ft_var.disable_pkt_nolink) { +#if defined(CONFIG_PCI_HCI) + __RTL8188E_MACID_NOLINK(priv, nolink, aid); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_macid_no_link_change(priv, aid, nolink); +#endif + } +} + +#ifdef CONFIG_PCI_HCI +static inline +#endif +void __RTL8188E_MACID_PAUSE(struct rtl8192cd_priv *priv, unsigned int pause, unsigned int aid) +{ + if (pause) { + if (aid > 31) + RTL_W32(REG_88E_MACID_PAUSE+4, RTL_R32(REG_88E_MACID_PAUSE+4) | BIT(aid -31)); + else + RTL_W32(REG_88E_MACID_PAUSE, RTL_R32(REG_88E_MACID_PAUSE) | BIT(aid)); + } else { + if (aid > 31) + RTL_W32(REG_88E_MACID_PAUSE+4, RTL_R32(REG_88E_MACID_PAUSE+4) & ~BIT(aid -31)); + else + RTL_W32(REG_88E_MACID_PAUSE, RTL_R32(REG_88E_MACID_PAUSE) & ~BIT(aid)); + } +} + +void RTL8188E_MACID_PAUSE(struct rtl8192cd_priv *priv, unsigned int pause, unsigned int aid) +{ + if (!priv->pshare->rf_ft_var.disable_pkt_pause) { +#if defined(CONFIG_PCI_HCI) + __RTL8188E_MACID_PAUSE(priv, pause, aid); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_macid_pause_change(priv, aid, pause); +#endif + } +} + + +#ifdef SUPPORT_RTL8188E_TC +void check_RTL8188E_testChip(struct rtl8192cd_priv *priv) +{ + if (!priv->pshare->rtl8188e_testchip_checked) { + if (RTL_R8(AFE_XTAL_CTRL+3) == 0x3F) + priv->pshare->version_id |= 0x100; + + priv->pshare->rtl8188e_testchip_checked++; + } +} +#endif + +#ifndef CALIBRATE_BY_ODM + + +#define IQK_DELAY_TIME_88E 10 + +#define bRFRegOffsetMask 0xfffff + + +void _PHY_PathAStandBy(struct rtl8192cd_priv *priv) +{ + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x0); + PHY_SetBBReg(priv, 0x840, bMaskDWord, 0x00010000); + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); +} + +void _PHY_PathAFillIQKMatrix(struct rtl8192cd_priv *priv, char bIQKOK, int result[][8], unsigned char final_candidate, char bTxOnly) +{ + int Oldval_0, X, TX0_A, reg; + int Y, TX0_C; + + if(final_candidate == 0xFF) + return; + + else if(bIQKOK) { + Oldval_0 = (PHY_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF; + + X = result[final_candidate][0]; + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + TX0_A = (X * Oldval_0) >> 8; + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(31), ((X* Oldval_0>>7) & 0x1)); + + Y = result[final_candidate][1]; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + TX0_C = (Y * Oldval_0) >> 8; + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6)); + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C&0x3F)); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(29), ((Y* Oldval_0>>7) & 0x1)); + + if(bTxOnly) { +// RTPRINT(FINIT, INIT_IQK, ("_PHY_PathAFillIQKMatrix only Tx OK\n")); + return; + } + + reg = result[final_candidate][2]; + if( RTL_ABS(reg ,0x100) >= 16) + reg = 0x100; + PHY_SetBBReg(priv, rOFDM0_XARxIQImbalance, 0x3FF, reg); + + reg = result[final_candidate][3] & 0x3F; + PHY_SetBBReg(priv, rOFDM0_XARxIQImbalance, 0xFC00, reg); + + reg = (result[final_candidate][3] >> 6) & 0xF; + PHY_SetBBReg(priv, 0xca0, 0xF0000000, reg); + } +} + + +void _PHY_PIModeSwitch(struct rtl8192cd_priv *priv, char PIMode) +{ + unsigned int mode; + + DEBUG_INFO("BB Switch to %s mode!\n", (PIMode ? "PI" : "SI")); + + mode = PIMode ? 0x01000100 : 0x01000000; + PHY_SetBBReg(priv, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode); + PHY_SetBBReg(priv, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode); +} + + +//bit0 = 1 => Tx OK, bit1 = 1 => Rx OK +unsigned char phy_PathA_IQK_8188E(struct rtl8192cd_priv *priv, unsigned char configPathB) +{ + unsigned int regEAC, regE94, regE9C, regEA4; + unsigned char result = 0x00; + + DEBUG_INFO("Path A IQK!\n"); + + //path-A IQK setting + DEBUG_INFO("Path-A IQK setting!\n"); + PHY_SetBBReg(priv, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c); + PHY_SetBBReg(priv, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c); + PHY_SetBBReg(priv, rTx_IQK_PI_A, bMaskDWord, 0x8214032a); + PHY_SetBBReg(priv, rRx_IQK_PI_A, bMaskDWord, 0x28160000); + + //LO calibration setting + DEBUG_INFO("LO calibration setting!\n"); + PHY_SetBBReg(priv, rIQK_AGC_Rsp, bMaskDWord, 0x00462911); //0x001028d1 + + //One shot, path A LOK & IQK + DEBUG_INFO("One shot, path A LOK & IQK!\n"); + PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); + PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); + + // delay x ms + DEBUG_INFO("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E); + delay_ms(IQK_DELAY_TIME_88E); + + // Check failed + regEAC = PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord); + DEBUG_INFO("0xeac = 0x%x\n", regEAC); + regE94 = PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord); + DEBUG_INFO("0xe94 = 0x%x\n", regE94); + regE9C= PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord); + DEBUG_INFO("0xe9c = 0x%x\n", regE9C); + regEA4= PHY_QueryBBReg(priv, rRx_Power_Before_IQK_A_2, bMaskDWord); + DEBUG_INFO("0xea4 = 0x%x\n", regEA4); + + if(!(regEAC & BIT(28)) && + (((regE94 & 0x03FF0000)>>16) != 0x142) && + (((regE9C & 0x03FF0000)>>16) != 0x42) ) + result |= 0x01; + else //if Tx not OK, ignore Rx + return result; + +#if 0 + if(!(regEAC & BIT27) && //if Tx is OK, check whether Rx is OK + (((regEA4 & 0x03FF0000)>>16) != 0x132) && + (((regEAC & 0x03FF0000)>>16) != 0x36)) + result |= 0x02; + else + RTPRINT(FINIT, INIT_IQK, ("Path A Rx IQK fail!!\n")); +#endif + + return result; + +} + + +//bit0 = 1 => Tx OK, bit1 = 1 => Rx OK +unsigned char phy_PathA_RxIQK(struct rtl8192cd_priv *priv, char configPathB) +{ + int regEAC, regE94, regE9C, regEA4, u4tmp; + unsigned char result = 0x00; + + DEBUG_INFO("Path A Rx IQK!\n"); + + //get TXIMR setting + //modify RXIQK mode table + DEBUG_INFO("Path-A Rx IQK modify RXIQK mode table!\n"); + PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0); + PHY_SetRFReg(priv, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0 ); + PHY_SetRFReg(priv, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000 ); + PHY_SetRFReg(priv, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f ); + PHY_SetRFReg(priv, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B ); + PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0x808000); + + //IQK setting + PHY_SetBBReg(priv, rTx_IQK, bMaskDWord, 0x01007c00); + PHY_SetBBReg(priv, rRx_IQK, bMaskDWord, 0x81004800); + + //path-A IQK setting + PHY_SetBBReg(priv, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c); + PHY_SetBBReg(priv, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c); + PHY_SetBBReg(priv, rTx_IQK_PI_A, bMaskDWord, 0x82160804); + PHY_SetBBReg(priv, rRx_IQK_PI_A, bMaskDWord, 0x28160000); + + //LO calibration setting + DEBUG_INFO("LO calibration setting!\n"); + PHY_SetBBReg(priv, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); //0x0010a8d1 + + //One shot, path A LOK & IQK + DEBUG_INFO("One shot, path A LOK & IQK!\n"); + PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); + PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); + + // delay x ms + DEBUG_INFO("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E); + delay_ms(IQK_DELAY_TIME_88E); + + // Check failed + regEAC = PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord); + DEBUG_INFO("0xeac = 0x%x\n", regEAC); + regE94 = PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord); + DEBUG_INFO("0xe94 = 0x%x\n", regE94); + regE9C = PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord); + DEBUG_INFO("0xe9c = 0x%x\n", regE9C); + + if(!(regEAC & BIT(28)) && + (((regE94 & 0x03FF0000)>>16) != 0x142) && + (((regE9C & 0x03FF0000)>>16) != 0x42) ) + result |= 0x01; + else //if Tx not OK, ignore Rx + return result; + + u4tmp = 0x80007C00 | (regE94&0x3FF0000) | ((regE9C&0x3FF0000) >> 16); + PHY_SetBBReg(priv, rTx_IQK, bMaskDWord, u4tmp); + DEBUG_INFO("0xe40 = 0x%x u4tmp = 0x%x \n", PHY_QueryBBReg(priv, rTx_IQK, bMaskDWord), u4tmp); + + + //RX IQK + //modify RXIQK mode table + DEBUG_INFO("Path-A Rx IQK modify RXIQK mode table 2!\n"); + PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0); + PHY_SetRFReg(priv, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0 ); + PHY_SetRFReg(priv, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000 ); + PHY_SetRFReg(priv, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f ); + PHY_SetRFReg(priv, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa ); + PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0x808000); + + //IQK setting + PHY_SetBBReg(priv, rRx_IQK, bMaskDWord, 0x01004800); + + //path-A IQK setting + PHY_SetBBReg(priv, rTx_IQK_Tone_A, bMaskDWord, 0x30008c1c); + PHY_SetBBReg(priv, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1c); + PHY_SetBBReg(priv, rTx_IQK_PI_A, bMaskDWord, 0x82160c05); + PHY_SetBBReg(priv, rRx_IQK_PI_A, bMaskDWord, 0x28160c05); + + //LO calibration setting + DEBUG_INFO("LO calibration setting!\n"); + PHY_SetBBReg(priv, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911); //0x0010a8d1 + + //One shot, path A LOK & IQK + DEBUG_INFO("One shot, path A LOK & IQK!\n"); + PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf9000000); + PHY_SetBBReg(priv, rIQK_AGC_Pts, bMaskDWord, 0xf8000000); + + // delay x ms + DEBUG_INFO("Delay %d ms for One shot, path A LOK & IQK.\n", IQK_DELAY_TIME_88E); + delay_ms(IQK_DELAY_TIME_88E); + + // Check failed + regEAC = PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord); + DEBUG_INFO("0xeac = 0x%x\n", regEAC); + regE94 = PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord); + DEBUG_INFO("0xe94 = 0x%x\n", regE94); + regE9C= PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord); + DEBUG_INFO("0xe9c = 0x%x\n", regE9C); + regEA4= PHY_QueryBBReg(priv, rRx_Power_Before_IQK_A_2, bMaskDWord); + DEBUG_INFO("0xea4 = 0x%x\n", regEA4); + +#if 0 + if(!(regEAC & BIT28) && + (((regE94 & 0x03FF0000)>>16) != 0x142) && + (((regE9C & 0x03FF0000)>>16) != 0x42) ) + result |= 0x01; + else //if Tx not OK, ignore Rx + return result; +#endif + + if(!(regEAC & BIT(27)) && //if Tx is OK, check whether Rx is OK + (((regEA4 & 0x03FF0000)>>16) != 0x132) && + (((regEAC & 0x03FF0000)>>16) != 0x36)) + result |= 0x02; + else + DEBUG_INFO("Path A Rx IQK fail!!\n"); + + return result; + + +} + +//bit0 = 1 => Tx OK, bit1 = 1 => Rx OK +unsigned char phy_PathB_IQK_8188E(struct rtl8192cd_priv *priv) +{ + unsigned int regEAC, regEB4, regEBC, regEC4, regECC; + unsigned char result = 0x00; + DEBUG_INFO("Path B IQK!\n"); + + //One shot, path B LOK & IQK + DEBUG_INFO("One shot, path A LOK & IQK!\n"); + PHY_SetBBReg(priv, rIQK_AGC_Cont, bMaskDWord, 0x00000002); + PHY_SetBBReg(priv, rIQK_AGC_Cont, bMaskDWord, 0x00000000); + + // delay x ms + DEBUG_INFO("Delay %d ms for One shot, path B LOK & IQK.\n", IQK_DELAY_TIME_88E); + delay_ms(IQK_DELAY_TIME_88E); + + // Check failed + regEAC = PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord); + DEBUG_INFO("0xeac = 0x%x\n", regEAC); + regEB4 = PHY_QueryBBReg(priv, rTx_Power_Before_IQK_B, bMaskDWord); + DEBUG_INFO("0xeb4 = 0x%x\n", regEB4); + regEBC= PHY_QueryBBReg(priv, rTx_Power_After_IQK_B, bMaskDWord); + DEBUG_INFO("0xebc = 0x%x\n", regEBC); + regEC4= PHY_QueryBBReg(priv, rRx_Power_Before_IQK_B_2, bMaskDWord); + DEBUG_INFO("0xec4 = 0x%x\n", regEC4); + regECC= PHY_QueryBBReg(priv, rRx_Power_After_IQK_B_2, bMaskDWord); + DEBUG_INFO("0xecc = 0x%x\n", regECC); + + if(!(regEAC & BIT(31)) && + (((regEB4 & 0x03FF0000)>>16) != 0x142) && + (((regEBC & 0x03FF0000)>>16) != 0x42)) + result |= 0x01; + else + return result; + + if(!(regEAC & BIT(30)) && + (((regEC4 & 0x03FF0000)>>16) != 0x132) && + (((regECC & 0x03FF0000)>>16) != 0x36)) + result |= 0x02; + else + DEBUG_INFO("Path B Rx IQK fail!!\n"); + + + return result; + +} + + +void phy_IQCalibrate_8188E(struct rtl8192cd_priv *priv, int result[][8], unsigned char t, char is2T) +{ + unsigned int i; + unsigned char PathAOK, PathBOK; + unsigned int ADDA_REG[IQK_ADDA_REG_NUM] = { + rFPGA0_XCD_SwitchControl, rBlue_Tooth, + rRx_Wait_CCA, rTx_CCK_RFON, + rTx_CCK_BBON, rTx_OFDM_RFON, + rTx_OFDM_BBON, rTx_To_Rx, + rTx_To_Tx, rRx_CCK, + rRx_OFDM, rRx_Wait_RIFS, + rRx_TO_Rx, rStandby, + rSleep, rPMPD_ANAEN }; + + unsigned int IQK_MAC_REG[IQK_MAC_REG_NUM] = { + REG_TXPAUSE, REG_BCN_CTRL, + REG_BCN_CTRL_1, REG_GPIO_MUXCFG}; + + //since 92C & 92D have the different define in IQK_BB_REG + unsigned int IQK_BB_REG_92C[IQK_BB_REG_NUM] = { + rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar, + rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB, + rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE, + rFPGA0_XB_RFInterfaceOE, /*rFPGA0_RFMOD*/ rCCK0_AFESetting + }; + + unsigned int retryCount = 0; + +// unsigned int bbvalue; + +#ifdef MP_TEST + if(priv->pshare->rf_ft_var.mp_specific) + retryCount = 9; //original 9 + else + retryCount = 2; +#else + retryCount = 2; +#endif + + // Note: IQ calibration must be performed after loading + // PHY_REG.txt , and radio_a, radio_b.txt + + if(t == 0) + { +// bbvalue = PHY_QueryBBReg(pAdapter, rFPGA0_RFMOD, bMaskDWord); +// RTPRINT(FINIT, INIT_IQK, ("phy_IQCalibrate_8188E()==>0x%08x\n",bbvalue)); + + //RTPRINT(FINIT, INIT_IQK, ("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t)); + DEBUG_INFO("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t); + + // Save ADDA parameters, turn Path A ADDA on + _PHY_SaveADDARegisters(priv, ADDA_REG, priv->pshare->ADDA_backup, IQK_ADDA_REG_NUM); + _PHY_SaveMACRegisters(priv, IQK_MAC_REG, priv->pshare->IQK_MAC_backup); + _PHY_SaveADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup, IQK_BB_REG_NUM); + + } + DEBUG_INFO("IQ Calibration for %s for %d times\n", (is2T ? "2T2R" : "1T1R"), t); + + + _PHY_PathADDAOn(priv, ADDA_REG, TRUE, is2T); + + + if(t==0) + { + priv->pshare->bRfPiEnable = (unsigned char)PHY_QueryBBReg(priv, rFPGA0_XA_HSSIParameter1, BIT(8)); + } + + if(!priv->pshare->bRfPiEnable){ + // Switch BB to PI mode to do IQ Calibration. + _PHY_PIModeSwitch(priv, TRUE); + } + + //MAC settings + _PHY_MACSettingCalibration(priv, IQK_MAC_REG, priv->pshare->IQK_MAC_backup); + + //BB setting + //PHY_SetBBReg(priv, rFPGA0_RFMOD, BIT(24), 0x00); + PHY_SetBBReg(priv, rCCK0_AFESetting, bMaskDWord, (0x0f000000 | (PHY_QueryBBReg(priv, rCCK0_AFESetting, bMaskDWord))) ); + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600); + PHY_SetBBReg(priv, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4); + PHY_SetBBReg(priv, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000); + + PHY_SetBBReg(priv, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01); + PHY_SetBBReg(priv, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01); + PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00); + PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00); + + + if(is2T) + { + PHY_SetBBReg(priv, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00010000); + PHY_SetBBReg(priv, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00010000); + } + + //Page B init + //AP or IQK + PHY_SetBBReg(priv, rConfig_AntA, bMaskDWord, 0x0f600000); + + if(is2T) + { + PHY_SetBBReg(priv, rConfig_AntB, bMaskDWord, 0x0f600000); + } + + // IQ calibration setting + DEBUG_INFO("IQK setting!\n"); + PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0x808000); + PHY_SetBBReg(priv, rTx_IQK, bMaskDWord, 0x01007c00); + PHY_SetBBReg(priv, rRx_IQK, bMaskDWord, 0x81004800); + + for(i = 0 ; i < retryCount ; i++){ + PathAOK = phy_PathA_IQK_8188E(priv, is2T); +// if(PathAOK == 0x03){ + if(PathAOK == 0x01){ + DEBUG_INFO("Path A Tx IQK Success!!\n"); + result[t][0] = (PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16; + result[t][1] = (PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16; + break; + } +#if 0 + else if (i == (retryCount-1) && PathAOK == 0x01) //Tx IQK OK + { + DEBUG_INFO("Path A IQK Only Tx Success!!\n"); + + result[t][0] = (PHY_QueryBBReg(priv, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16; + result[t][1] = (PHY_QueryBBReg(priv, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16; + } +#endif + } + + for(i = 0 ; i < retryCount ; i++){ + PathAOK = phy_PathA_RxIQK(priv, is2T); + + //printk("\n\nPathAOK = 0x%x\n\n", PathAOK); + + if(PathAOK == 0x03){ + DEBUG_INFO("Path A Rx IQK Success!!\n"); +// result[t][0] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16; +// result[t][1] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16; + result[t][2] = (PHY_QueryBBReg(priv, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16; + result[t][3] = (PHY_QueryBBReg(priv, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16; + break; + } + else + { + DEBUG_INFO("Path A Rx IQK Fail!!\n"); + } + } + + if(0x00 == PathAOK){ + DEBUG_INFO("Path A IQK failed!!\n"); + } + + if(is2T){ + _PHY_PathAStandBy(priv); + + // Turn Path B ADDA on + _PHY_PathADDAOn(priv, ADDA_REG, FALSE, is2T); + + for(i = 0 ; i < retryCount ; i++){ + PathBOK = phy_PathB_IQK_8188E(priv); + if(PathBOK == 0x03){ + DEBUG_INFO("Path B IQK Success!!\n"); + result[t][4] = (PHY_QueryBBReg(priv, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16; + result[t][5] = (PHY_QueryBBReg(priv, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16; + result[t][6] = (PHY_QueryBBReg(priv, rRx_Power_Before_IQK_B_2, bMaskDWord)&0x3FF0000)>>16; + result[t][7] = (PHY_QueryBBReg(priv, rRx_Power_After_IQK_B_2, bMaskDWord)&0x3FF0000)>>16; + break; + } + else if (i == (retryCount - 1) && PathBOK == 0x01) //Tx IQK OK + { + DEBUG_INFO("Path B Only Tx IQK Success!!\n"); + result[t][4] = (PHY_QueryBBReg(priv, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16; + result[t][5] = (PHY_QueryBBReg(priv, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16; + } + } + + if(0x00 == PathBOK){ + DEBUG_INFO("Path B IQK failed!!\n"); + } + } + + //Back to BB mode, load original value + DEBUG_INFO("IQK:Back to BB mode, load original value!\n"); + PHY_SetBBReg(priv, rFPGA0_IQK, 0xffffff00, 0); + + if(t != 0) + { + if(!priv->pshare->bRfPiEnable){ + // Switch back BB to SI mode after finish IQ Calibration. + _PHY_PIModeSwitch(priv, FALSE); + } + + // Reload ADDA power saving parameters + _PHY_ReloadADDARegisters(priv, ADDA_REG, priv->pshare->ADDA_backup, IQK_ADDA_REG_NUM); + + // Reload MAC parameters + _PHY_ReloadMACRegisters(priv, IQK_MAC_REG, priv->pshare->IQK_MAC_backup); + + _PHY_ReloadADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup, IQK_BB_REG_NUM); + + // Restore RX initial gain + PHY_SetBBReg(priv, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00032ed3); + if(is2T){ + PHY_SetBBReg(priv, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00032ed3); + } + + //load 0xe30 IQC default value + PHY_SetBBReg(priv, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00); + PHY_SetBBReg(priv, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00); + + } + DEBUG_INFO("phy_IQCalibrate_8188E() <==\n"); + +} + + +unsigned char phy_SimularityCompare_8188E(struct rtl8192cd_priv *priv, int result[][8], unsigned char c1, unsigned char c2) +{ + unsigned int i, j, diff, SimularityBitMap, bound = 0; + unsigned char final_candidate[2] = {0xFF, 0xFF}; //for path A and path B + unsigned char bResult = TRUE, is2T = FALSE; + + if(is2T) + bound = 8; + else + bound = 4; + + DEBUG_INFO("===> IQK:phy_SimularityCompare_8188E c1 %d c2 %d!!!\n", c1, c2); + + + SimularityBitMap = 0; + + for( i = 0; i < bound; i++ ) + { + diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - result[c2][i]) : (result[c2][i] - result[c1][i]); + if (diff > MAX_TOLERANCE) + { + DEBUG_INFO("IQK:phy_SimularityCompare_8188E differnece overflow index %d compare1 0x%x compare2 0x%x!!!\n", i, result[c1][i], result[c2][i]); + + if((i == 2 || i == 6) && !SimularityBitMap) + { + if(result[c1][i]+result[c1][i+1] == 0) + final_candidate[(i/4)] = c2; + else if (result[c2][i]+result[c2][i+1] == 0) + final_candidate[(i/4)] = c1; + else + SimularityBitMap = SimularityBitMap|(1<pshare->rf_ft_var.mp_specific) + { + if((OPMODE & WIFI_MP_CTX_PACKET) || (OPMODE & WIFI_MP_CTX_ST)) + return; + } +#endif + +#if 1 + if(priv->pshare->IQK_88E_done) + { +#ifdef __ECOS + _PHY_ReloadADDARegisters(priv, (unsigned int*)IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9); +#else + _PHY_ReloadADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9); +#endif + return; + } + + priv->pshare->IQK_88E_done = 1; +#endif + +#if 0 + if(bReCovery) + { + _PHY_ReloadADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9); + return; + } +#endif + + printk("DO 8188E IQK !!!\n"); + DEBUG_INFO("IQK:Start!!!\n"); + + for(i = 0; i < 8; i++) + { + result[0][i] = 0; + result[1][i] = 0; + result[2][i] = 0; + result[3][i] = 0; + } + final_candidate = 0xff; + bPathAOK = FALSE; + bPathBOK = FALSE; + is12simular = FALSE; + is23simular = FALSE; + is13simular = FALSE; + + + //RTPRINT(("IQK !!!interface %d currentband %d ishardwareD %d \n", pAdapter->interfaceIndex, pHalData->CurrentBandType92D, IS_HARDWARE_TYPE_8192D(pAdapter))); + //RT_TRACE(COMP_INIT,DBG_LOUD,("Acquire Mutex in IQCalibrate \n")); + + for (i=0; i<3; i++) + { + + // For 88C 1T1R //_eric ?? + phy_IQCalibrate_8188E(priv, result, i, FALSE); + + if(i == 1) + { + is12simular = phy_SimularityCompare_8188E(priv, result, 0, 1); + if(is12simular) + { + final_candidate = 0; + DEBUG_INFO("IQK: is12simular final_candidate is %x\n",final_candidate); + break; + } + } + + if(i == 2) + { + is13simular = phy_SimularityCompare_8188E(priv, result, 0, 2); + if(is13simular) + { + final_candidate = 0; + DEBUG_INFO("IQK: is13simular final_candidate is %x\n",final_candidate); + + break; + } + + is23simular = phy_SimularityCompare_8188E(priv, result, 1, 2); + if(is23simular) + { + final_candidate = 1; + DEBUG_INFO("IQK: is23simular final_candidate is %x\n",final_candidate); + } + else + { + for(i = 0; i < 8; i++) + RegTmp += result[3][i]; + + if(RegTmp != 0) + final_candidate = 3; + else + final_candidate = 0xFF; + } + } + } +// RT_TRACE(COMP_INIT,DBG_LOUD,("Release Mutex in IQCalibrate \n")); + + for (i=0; i<4; i++) + { + RegE94 = result[i][0]; + RegE9C = result[i][1]; + RegEA4 = result[i][2]; + RegEAC = result[i][3]; + RegEB4 = result[i][4]; + RegEBC = result[i][5]; + RegEC4 = result[i][6]; + RegECC = result[i][7]; + DEBUG_INFO("IQK: RegE94=%x RegE9C=%x RegEA4=%x RegEAC=%x RegEB4=%x RegEBC=%x RegEC4=%x RegECC=%x\n ", RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC); + } + + if(final_candidate != 0xff) + { + priv->pshare->RegE94 = RegE94 = result[final_candidate][0]; + priv->pshare->RegE9C = RegE9C = result[final_candidate][1]; + RegEA4 = result[final_candidate][2]; + RegEAC = result[final_candidate][3]; + priv->pshare->RegEB4 = RegEB4 = result[final_candidate][4]; + priv->pshare->RegEBC = RegEBC = result[final_candidate][5]; + RegEC4 = result[final_candidate][6]; + RegECC = result[final_candidate][7]; + DEBUG_INFO("IQK: final_candidate is %x\n",final_candidate); + DEBUG_INFO("IQK: RegE94=%x RegE9C=%x RegEA4=%x RegEAC=%x RegEB4=%x RegEBC=%x RegEC4=%x RegECC=%x\n ", RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC); + bPathAOK = bPathBOK = TRUE; + } + else + { + DEBUG_INFO("IQK: FAIL use default value\n"); + + priv->pshare->RegE94 = priv->pshare->RegEB4 = 0x100; //X default value + priv->pshare->RegE9C = priv->pshare->RegEBC = 0x0; //Y default value + } + + + + if((RegE94 != 0)/*&&(RegEA4 != 0)*/) + { + _PHY_PathAFillIQKMatrix(priv, bPathAOK, result, final_candidate, (RegEA4 == 0)); + } + +#if 0 + if (IS_92C_SERIAL(pHalData->VersionID)) + { + if((RegEB4 != 0)/*&&(RegEC4 != 0)*/) + { + _PHY_PathBFillIQKMatrix(pAdapter, bPathBOK, result, final_candidate, (RegEC4 == 0)); + } + } +#endif + Indexforchannel = 0; + + for(i = 0; i < IQK_Matrix_REG_NUM; i++) + priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][i] = result[final_candidate][i]; + + priv->pshare->IQKMatrixRegSetting[Indexforchannel].bIQKDone = TRUE; +#ifdef __ECOS + _PHY_SaveADDARegisters(priv, (unsigned int*)IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9); +#else + _PHY_SaveADDARegisters(priv, IQK_BB_REG_92C, priv->pshare->IQK_BB_backup_recover, 9); +#endif + +} + +void ODM_ResetIQKResult(struct rtl8192cd_priv *priv) +{ +/* +#if (DM_ODM_SUPPORT_TYPE == ODM_WIN || DM_ODM_SUPPORT_TYPE == ODM_CE) + PADAPTER Adapter = pDM_Odm->Adapter; + u1Byte i; + + if (!IS_HARDWARE_TYPE_8192D(Adapter)) + return; +#endif +*/ + + unsigned char i; + + //printk("PHY_ResetIQKResult:: settings regs %d default regs %d\n", sizeof(priv->pshare->IQKMatrixRegSetting)/sizeof(IQK_MATRIX_REGS_SETTING), IQK_Matrix_Settings_NUM); + //0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc + + for(i = 0; i < IQK_Matrix_Settings_NUM; i++) + { + { + priv->pshare->IQKMatrixRegSetting[i].Value[0][0] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][2] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][4] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][6] = 0x100; + + priv->pshare->IQKMatrixRegSetting[i].Value[0][1] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][3] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][5] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][7] = 0x0; + + priv->pshare->IQKMatrixRegSetting[i].bIQKDone = FALSE; + + } + } + +} + +#define OFDM_TABLE_SIZE_92D 43 + +#define bRFRegOffsetMask 0xfffff + +extern unsigned int OFDMSwingTable[]; +extern const int OFDM_TABLE_SIZE; +extern const int CCK_TABLE_SIZE; +extern unsigned char CCKSwingTable_Ch14 [][8]; +extern unsigned char CCKSwingTable_Ch1_Ch13[][8]; + + +//091212 chiyokolin +void odm_TXPowerTrackingCallback_ThermalMeter_8188E(struct rtl8192cd_priv *priv) +{ + + //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + unsigned char ThermalValue = 0, delta, delta_LCK, delta_IQK, offset; + unsigned char ThermalValue_AVG_count = 0; + unsigned int ThermalValue_AVG = 0; + int ele_A=0, ele_D, /* TempCCk,*/ X, value32; + int Y, ele_C=0; + s1Byte OFDM_index[2]={0}, CCK_index=0, OFDM_index_old[2]={0}, CCK_index_old=0, index; + unsigned int i = 0, j = 0; + char is2T = FALSE; +// char bInteralPA = FALSE; + + unsigned char OFDM_min_index = 6, rf; //OFDM BB Swing should be less than +3.0dB, which is required by Arthur + unsigned char Indexforchannel = 0/*GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/; + s1Byte OFDM_index_mapping[2][index_mapping_NUM_88E] = { + {0, 0, 2, 3, 4, 4, //2.4G, decrease power + 5, 6, 7, 7, 8, 9, + 10, 10, 11}, // For lower temperature, 20120220 updated on 20120220. + {0, 0, -1, -2, -3, -4, //2.4G, increase power + -4, -4, -4, -5, -7, -8, + -9, -9, -10}, + }; + unsigned char Thermal_mapping[2][index_mapping_NUM_88E] = { + {0, 2, 4, 6, 8, 10, //2.4G, decrease power + 12, 14, 16, 18, 20, 22, + 24, 26, 27}, + {0, 2, 4, 6, 8, 10, //2.4G,, increase power + 12, 14, 16, 18, 20, 22, + 25, 25, 25}, + }; + + priv->pshare->TXPowerTrackingCallbackCnt++; //cosa add for debug + priv->pshare->bTXPowerTrackingInit = TRUE; + +#if 1 //(MP_DRIVER == 1) //_eric_?? + priv->pshare->TxPowerTrackControl = 1; //priv->pshare->TxPowerTrackControl; //_eric_?? // We should keep updating the control variable according to HalData. + // pshare->RegA24 will be initialized when ODM HW configuring, but MP configures with para files. + priv->pshare->RegA24 = 0x090e1317; +#endif + + +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { + if(priv->pshare->mp_txpwr_tracking == FALSE) + return; + } +#endif +#if 0 + if(priv->pshare->Power_tracking_on_88E == 0) + { + priv->pshare->Power_tracking_on_88E = 1; + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x42, (BIT(17) | BIT(16)), 0x03); + return; + } + else +#endif + { + +// priv->pshare->Power_tracking_on_88E = 0; + + //printk("===>dm_TXPowerTrackingCallback_ThermalMeter_8188E txpowercontrol %d\n", priv->pshare->TxPowerTrackControl); + + ThermalValue = (unsigned char)PHY_QueryRFReg(priv, RF_PATH_A, RF_T_METER_88E, 0xfc00, 1); //0x42: RF Reg[15:10] 88E + + //printk("\nReadback Thermal Meter = 0x%x pre thermal meter 0x%x EEPROMthermalmeter 0x%x\n", ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther); + + } + + + if(is2T) + rf = 2; + else + rf = 1; + + //if(ThermalValue) + { +// if(!pHalData->ThermalValue) + { + //Query OFDM path A default setting + ele_D = PHY_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D; + + for(i=0; ipshare->RegA24; + + for(i=0 ; ipshare->bCCKinCH14) + { + if(memcmp((void*)&TempCCk, (void*)&CCKSwingTable_Ch14[i][2], 4)==0) + { + CCK_index_old =(unsigned char) i; + //printk("Initial reg0x%x = 0x%x, CCK_index=0x%x, ch 14 %d\n", + //rCCK0_TxFilter2, TempCCk, CCK_index_old, priv->pshare->bCCKinCH14); + break; + } + } + else + { + //printk("RegA24: 0x%X, CCKSwingTable_Ch1_Ch13[%d][2]: CCKSwingTable_Ch1_Ch13[i][2]: 0x%X\n", TempCCk, i, CCKSwingTable_Ch1_Ch13[i][2]); + if(memcmp((void*)&TempCCk, (void*)&CCKSwingTable_Ch1_Ch13[i][2], 4)==0) + { + CCK_index_old =(unsigned char) i; + //printk("Initial reg0x%x = 0x%x, CCK_index=0x%x, ch14 %d\n", + //rCCK0_TxFilter2, TempCCk, CCK_index_old, priv->pshare->bCCKinCH14); + break; + } + } + } +#endif + } + + if(!priv->pshare->ThermalValue) + { + CCK_index_old = get_CCK_swing_index(priv); + priv->pshare->ThermalValue = priv->pmib->dot11RFEntry.ther; + priv->pshare->ThermalValue_LCK = ThermalValue; + priv->pshare->ThermalValue_IQK = ThermalValue; + + for(i = 0; i < rf; i++) + priv->pshare->OFDM_index[i] = OFDM_index_old[i]; + priv->pshare->CCK_index = CCK_index_old; + } + + if(priv->pshare->bReloadtxpowerindex) + { + printk("reload ofdm index for band switch\n"); + } + + //calculate average thermal meter + { + priv->pshare->ThermalValue_AVG[priv->pshare->ThermalValue_AVG_index] = ThermalValue; + priv->pshare->ThermalValue_AVG_index++; + if(priv->pshare->ThermalValue_AVG_index == AVG_THERMAL_NUM_88E) + priv->pshare->ThermalValue_AVG_index = 0; + + for(i = 0; i < AVG_THERMAL_NUM_88E; i++) + { + if(priv->pshare->ThermalValue_AVG[i]) + { + ThermalValue_AVG += priv->pshare->ThermalValue_AVG[i]; + ThermalValue_AVG_count++; + } + } + + if(ThermalValue_AVG_count) + { + ThermalValue = (unsigned char)(ThermalValue_AVG / ThermalValue_AVG_count); + //printk("AVG Thermal Meter = 0x%x \n", ThermalValue); + } + } + } + + if(priv->pshare->bReloadtxpowerindex) + { + delta = ThermalValue > priv->pmib->dot11RFEntry.ther?(ThermalValue - priv->pmib->dot11RFEntry.ther):(priv->pmib->dot11RFEntry.ther - ThermalValue); + priv->pshare->bReloadtxpowerindex = FALSE; + priv->pshare->bDoneTxpower = FALSE; + } + else if(priv->pshare->bDoneTxpower) + { + delta = (ThermalValue > priv->pshare->ThermalValue)?(ThermalValue - priv->pshare->ThermalValue):(priv->pshare->ThermalValue - ThermalValue); + } + else + { + delta = ThermalValue > priv->pmib->dot11RFEntry.ther?(ThermalValue - priv->pmib->dot11RFEntry.ther):(priv->pmib->dot11RFEntry.ther - ThermalValue); + } + delta_LCK = (ThermalValue > priv->pshare->ThermalValue_LCK)?(ThermalValue - priv->pshare->ThermalValue_LCK):(priv->pshare->ThermalValue_LCK - ThermalValue); + delta_IQK = (ThermalValue > priv->pshare->ThermalValue_IQK)?(ThermalValue - priv->pshare->ThermalValue_IQK):(priv->pshare->ThermalValue_IQK - ThermalValue); + + //printk("Readback Thermal Meter = 0x%x \npre thermal meter 0x%x EEPROMthermalmeter 0x%x delta 0x%x \ndelta_LCK 0x%x delta_IQK 0x%x \n", ThermalValue, priv->pshare->ThermalValue, priv->pshare->EEPROMThermalMeter, delta, delta_LCK, delta_IQK); + //printk("pre thermal meter LCK 0x%x \npre thermal meter IQK 0x%x \ndelta_LCK_bound 0x%x delta_IQK_bound 0x%x\n", priv->pshare->ThermalValue_LCK, priv->pshare->ThermalValue_IQK, priv->pshare->Delta_LCK, priv->pshare->Delta_IQK); + + + //if((delta_LCK > pHalData->Delta_LCK) && (pHalData->Delta_LCK != 0)) + if (delta_LCK >= 8) // Delta temperature is equal to or larger than 20 centigrade. + { + priv->pshare->ThermalValue_LCK = ThermalValue; + PHY_LCCalibrate(priv); + } + + + if(delta > 0 && priv->pshare->TxPowerTrackControl) + { + delta = ThermalValue > priv->pmib->dot11RFEntry.ther?(ThermalValue - priv->pmib->dot11RFEntry.ther):(priv->pmib->dot11RFEntry.ther - ThermalValue); + + //calculate new OFDM / CCK offset + { + { + if(ThermalValue > priv->pmib->dot11RFEntry.ther) + j = 1; + else + j = 0; + + for(offset = 0; offset < index_mapping_NUM_88E; offset++) + { + if(delta < Thermal_mapping[j][offset]) + { + if(offset != 0) + offset--; + break; + } + } + if(offset >= index_mapping_NUM_88E) + offset = index_mapping_NUM_88E-1; + + index = OFDM_index_mapping[j][offset]; + + printk("\nj = %d delta = %d, index = %d\n\n", j, delta, index); + + for(i = 0; i < rf; i++) + OFDM_index[i] = priv->pshare->OFDM_index[i] + OFDM_index_mapping[j][offset]; + CCK_index = priv->pshare->CCK_index + OFDM_index_mapping[j][offset]; + } + + if(is2T) + { + printk("temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n", + priv->pshare->OFDM_index[0], priv->pshare->OFDM_index[1], priv->pshare->CCK_index); + } + else + { + printk("temp OFDM_A_index=0x%x, CCK_index=0x%x\n", + priv->pshare->OFDM_index[0], priv->pshare->CCK_index); + } + + for(i = 0; i < rf; i++) + { + if(OFDM_index[i] > OFDM_TABLE_SIZE_92D-1) + { + OFDM_index[i] = OFDM_TABLE_SIZE_92D-1; + } + else if (OFDM_index[i] < OFDM_min_index) + { + OFDM_index[i] = OFDM_min_index; + } + } + + { + if(CCK_index > CCK_TABLE_SIZE-1) + CCK_index = CCK_TABLE_SIZE-1; + else if (CCK_index < 0) + CCK_index = 0; + } + + if(is2T) + { + printk("new OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n", + OFDM_index[0], OFDM_index[1], CCK_index); + } + else + { + printk("new OFDM_A_index=0x%x, CCK_index=0x%x\n", + OFDM_index[0], CCK_index); + } + } + + //2 temporarily remove bNOPG + //Config by SwingTable + if(priv->pshare->TxPowerTrackControl /*&& !pHalData->bNOPG*/) + { + priv->pshare->bDoneTxpower = TRUE; + + //Adujst OFDM Ant_A according to IQK result + ele_D = (OFDMSwingTable[(unsigned char)OFDM_index[0]] & 0xFFC00000)>>22; + X = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][0]; + Y = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][1]; + + if(X != 0) + { + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + ele_A = ((X * ele_D)>>8)&0x000003FF; + + //new element C = element D x Y + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + ele_C = ((Y * ele_D)>>8)&0x000003FF; + + //wirte new elements A, C, D to regC80 and regC94, element B is always 0 + value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, value32); + + value32 = (ele_C&0x000003C0)>>6; + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, value32); + + value32 = ((X * ele_D)>>7)&0x01; + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), value32); + + } + else + { + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned char)OFDM_index[0]]); + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), 0x00); + } + + //printk("TxPwrTracking for path A: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x 0xe94 = 0x%x 0xe9c = 0x%x\n", + //(unsigned int)X, (unsigned int)Y, (unsigned int)ele_A, (unsigned int)ele_C, (unsigned int)ele_D, (unsigned int)X, (unsigned int)Y); + + { + //Adjust CCK according to IQK result + if(!priv->pshare->bCCKinCH14){ + RTL_W8(0xa22, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][0]); + RTL_W8(0xa23, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][1]); + RTL_W8(0xa24, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][2]); + RTL_W8(0xa25, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][3]); + RTL_W8(0xa26, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][4]); + RTL_W8(0xa27, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][5]); + RTL_W8(0xa28, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][6]); + RTL_W8(0xa29, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][7]); + } + else{ + RTL_W8(0xa22, CCKSwingTable_Ch14[(unsigned char)CCK_index][0]); + RTL_W8(0xa23, CCKSwingTable_Ch14[(unsigned char)CCK_index][1]); + RTL_W8(0xa24, CCKSwingTable_Ch14[(unsigned char)CCK_index][2]); + RTL_W8(0xa25, CCKSwingTable_Ch14[(unsigned char)CCK_index][3]); + RTL_W8(0xa26, CCKSwingTable_Ch14[(unsigned char)CCK_index][4]); + RTL_W8(0xa27, CCKSwingTable_Ch14[(unsigned char)CCK_index][5]); + RTL_W8(0xa28, CCKSwingTable_Ch14[(unsigned char)CCK_index][6]); + RTL_W8(0xa29, CCKSwingTable_Ch14[(unsigned char)CCK_index][7]); + } + } + + if(is2T) + { + ele_D = (OFDMSwingTable[(unsigned char)OFDM_index[1]] & 0xFFC00000)>>22; + + //new element A = element D x X + X = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][4]; + Y = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][5]; + + //if(X != 0 && pHalData->CurrentBandType92D == ODM_BAND_ON_2_4G) + if((X != 0) && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G)) + + { + if ((X & 0x00000200) != 0) //consider minus + X = X | 0xFFFFFC00; + ele_A = ((X * ele_D)>>8)&0x000003FF; + + //new element C = element D x Y + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + ele_C = ((Y * ele_D)>>8)&0x00003FF; + + //wirte new elements A, C, D to regC88 and regC9C, element B is always 0 + value32=(ele_D<<22)|((ele_C&0x3F)<<16) |ele_A; + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, value32); + + value32 = (ele_C&0x000003C0)>>6; + PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, value32); + + value32 = ((X * ele_D)>>7)&0x01; + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), value32); + + } + else + { + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned char)OFDM_index[1]]); + PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), 0x00); + } + + //printk("TxPwrTracking path B: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x 0xeb4 = 0x%x 0xebc = 0x%x\n", + //(unsigned int)X, (unsigned int)Y, (unsigned int)ele_A, (unsigned int)ele_C, (unsigned int)ele_D, (unsigned int)X, (unsigned int)Y); + } + + printk("TxPwrTracking 0xc80 = 0x%x, 0xc94 = 0x%x RF 0x24 = 0x%x\n\n", PHY_QueryBBReg(priv, 0xc80, bMaskDWord), PHY_QueryBBReg(priv, 0xc94, bMaskDWord), PHY_QueryRFReg(priv, RF_PATH_A, 0x24, bRFRegOffsetMask, 1)); + } + } + +#if 0 //DO NOT do IQK during 88E power tracking + // if((delta_IQK > pHalData->Delta_IQK) && (pHalData->Delta_IQK != 0)) + if (delta_IQK >= 8) // Delta temperature is equal to or larger than 20 centigrade. + { + ODM_ResetIQKResult(priv); + +/* +#if(DM_ODM_SUPPORT_TYPE & ODM_WIN) +#if (DEV_BUS_TYPE == RT_PCI_INTERFACE) +#if USE_WORKITEM + PlatformAcquireMutex(&pHalData->mxChnlBwControl); +#else + PlatformAcquireSpinLock(Adapter, RT_CHANNEL_AND_BANDWIDTH_SPINLOCK); +#endif +#elif((DEV_BUS_TYPE == RT_USB_INTERFACE) || (DEV_BUS_TYPE == RT_SDIO_INTERFACE)) + PlatformAcquireMutex(&pHalData->mxChnlBwControl); +#endif +#endif +*/ + priv->pshare->ThermalValue_IQK= ThermalValue; + PHY_IQCalibrate_8188E(priv, FALSE); + +/* +#if(DM_ODM_SUPPORT_TYPE & ODM_WIN) +#if (DEV_BUS_TYPE == RT_PCI_INTERFACE) +#if USE_WORKITEM + PlatformReleaseMutex(&pHalData->mxChnlBwControl); +#else + PlatformReleaseSpinLock(Adapter, RT_CHANNEL_AND_BANDWIDTH_SPINLOCK); +#endif +#elif((DEV_BUS_TYPE == RT_USB_INTERFACE) || (DEV_BUS_TYPE == RT_SDIO_INTERFACE)) + PlatformReleaseMutex(&pHalData->mxChnlBwControl); +#endif +#endif +*/ + } +#endif + //update thermal meter value + if(priv->pshare->TxPowerTrackControl) + { + //Adapter->HalFunc.SetHalDefVarHandler(Adapter, HAL_DEF_THERMAL_VALUE, &ThermalValue); + priv->pshare->ThermalValue = ThermalValue; + } + + } + + //printk("<===dm_TXPowerTrackingCallback_ThermalMeter_8188E\n"); + + priv->pshare->TXPowercount = 0; + +} + + +#endif // CALIBRATE_BY_ODM + + +#endif // CONFIG_RTL_88E_SUPPORT + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8188e_reg.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8188e_reg.h new file mode 100755 index 000000000..4e4b741b0 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8188e_reg.h @@ -0,0 +1,1774 @@ +/* + * Header file of 8188E register + * + * $Id: 8188e_reg.h,v 1.1 2011/06/30 11:02:56 victoryman Exp $ + * + * Copyright (c) 2011 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8188E_REG_H_ +#define _8188E_REG_H_ + +#ifndef WLAN_HAL_INTERNAL_USED + + +//============================================================ +// 8188E Regsiter offset definition +//============================================================ + + +/* + * Project RTL8188E follows most of registers in Project RTL8192c + * This file includes additional registers for RTL8188E only + * Header file of RTL8192C registers should always be included + */ + +// +// 1. System Configure Register. (Offset 0x000 - 0x0FFh) +// +#define REG_88E_BB_PAD_CTRL 0x64 +#define REG_88E_HMEBOX_E0 0x88 +#define REG_88E_HMEBOX_E1 0x8A +#define REG_88E_HMEBOX_E2 0x8C +#define REG_88E_HMEBOX_E3 0x8E +#define REG_88E_WLLPS_CTRL 0x90 +#define REG_88E_RPWM2 0x9E +#define REG_88E_HIMR 0xB0 +#define REG_88E_HISR 0xB4 +#define REG_88E_HIMRE 0xB8 +#define REG_88E_HISRE 0xBC +#define REG_88E_EFUSE_DATA1 0xCC +#define REG_88E_EFUSE_DATA0 0xCD +#define REG_88E_EPPR 0xCF +#define REG_88E_TXDMA_TH 0x218 +#define REG_88E_LQ_TH 0x21C + +#define REG_88E_WATCHDOG 0x368 + +#define REG_88E_MACID_NOLINK 0x484 +#define REG_88E_MACID_PAUSE 0x48C +#define REG_88E_TXRPT_CTRL 0x4EC +#define REG_88E_TXRPT_TIM 0x4F0 +#define REG_88E_TXRPT_STSSET 0x4F2 +#define REG_88E_TXRPT_STSVLD 0x4F4 +#define REG_88E_TXRPT_STSINF 0x4F8 + + + +//============================================================ +// Registers for 8188E IQK +//============================================================ + + +#define rFPGA0_IQK 0xe28 +#define rTx_IQK_Tone_A 0xe30 +#define rRx_IQK_Tone_A 0xe34 +#define rTx_IQK_PI_A 0xe38 +#define rRx_IQK_PI_A 0xe3c + +#define rTx_IQK 0xe40 +#define rRx_IQK 0xe44 +#define rIQK_AGC_Pts 0xe48 +#define rIQK_AGC_Rsp 0xe4c +#define rTx_IQK_Tone_B 0xe50 +#define rRx_IQK_Tone_B 0xe54 +#define rTx_IQK_PI_B 0xe58 +#define rRx_IQK_PI_B 0xe5c +#define rIQK_AGC_Cont 0xe60 + +#define rRx_Power_Before_IQK_A 0xea0 +#define rRx_Power_Before_IQK_A_2 0xea4 +#define rRx_Power_After_IQK_A 0xea8 +#define rRx_Power_After_IQK_A_2 0xeac + +#define rTx_Power_Before_IQK_A 0xe94 +#define rTx_Power_After_IQK_A 0xe9c + + +#define rTx_Power_Before_IQK_B 0xeb4 +#define rTx_Power_After_IQK_B 0xebc + +#define rRx_Power_Before_IQK_B 0xec0 +#define rRx_Power_Before_IQK_B_2 0xec4 +#define rRx_Power_After_IQK_B 0xec8 +#define rRx_Power_After_IQK_B_2 0xecc + + +#define RF_RCK_OS 0x30 // RF TX PA control +#define RF_TXPA_G1 0x31 // RF TX PA control +#define RF_TXPA_G2 0x32 // RF TX PA control +#define RF_TXPA_G3 0x33 // RF TX PA control +#define RF_TX_BIAS_A 0x35 +#define RF_TX_BIAS_D 0x36 +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C // +#define RF_TRSW 0x3F + +#define RF_TXRF_A2 0x41 +#define RF_TXPA_G4 0x46 +#define RF_TXPA_A4 0x4B + +#define RF_WE_LUT 0xEF + + +//#define rFPGA0_XAB_SwitchControl 0x858 // RF Channel switch +//#define rFPGA0_XCD_SwitchControl 0x85c + +//#define rFPGA0_XAB_RFInterfaceSW 0x870 // RF Interface Software Control +//#define rFPGA0_XCD_RFInterfaceSW 0x874 + +//#define rFPGA0_XAB_RFParameter 0x878 // RF Parameter +//#define rFPGA0_XCD_RFParameter 0x87c + +//#define rFPGA0_AnalogParameter1 0x880 // Crystal cap setting RF-R/W protection for parameter4?? +//#define rFPGA0_AnalogParameter2 0x884 +//#define rFPGA0_AnalogParameter3 0x888 +//#define rFPGA0_AdDaClockEn 0x888 // enable ad/da clock1 for dual-phy +//#define rFPGA0_AnalogParameter4 0x88c + +//#define rFPGA0_XA_LSSIReadBack 0x8a0 // Tranceiver LSSI Readback +//#define rFPGA0_XB_LSSIReadBack 0x8a4 +#define rFPGA0_XC_LSSIReadBack 0x8a8 +#define rFPGA0_XD_LSSIReadBack 0x8ac + +//#define rFPGA0_PSDReport 0x8b4 // Useless now +//#define TransceiverA_HSPI_Readback 0x8b8 // Transceiver A HSPI Readback +//#define TransceiverB_HSPI_Readback 0x8bc // Transceiver B HSPI Readback +//#define rFPGA0_XAB_RFInterfaceRB 0x8e0 // Useless now // RF Interface Readback Value +#define rFPGA0_XCD_RFInterfaceRB 0x8e4 // Useless now + + +#define rBlue_Tooth 0xe6c +#define rRx_Wait_CCA 0xe70 +#define rTx_CCK_RFON 0xe74 +#define rTx_CCK_BBON 0xe78 +#define rTx_OFDM_RFON 0xe7c +#define rTx_OFDM_BBON 0xe80 +#define rTx_To_Rx 0xe84 +#define rTx_To_Tx 0xe88 +#define rRx_CCK 0xe8c + +#define rRx_OFDM 0xed0 +#define rRx_Wait_RIFS 0xed4 +#define rRx_TO_Rx 0xed8 +#define rStandby 0xedc +#define rSleep 0xee0 +#define rPMPD_ANAEN 0xeec + + +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_TSFTR_SNC_OFFSET 0x0518 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 + + +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_BCN_CTRL_1 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 // The same as REG_MBSSID_BCN_SPACE +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_TSFTR1 0x0568 // HW Port 1 TSF Register +#define REG_P2P_CTWIN 0x0572 // 1 Byte long (in unit of TU) +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACMHWCTRL 0x05C0 +#define REG_NOA_DESC_SEL 0x05CF +#define REG_NOA_DESC_DURATION 0x05E0 +#define REG_NOA_DESC_INTERVAL 0x05E4 +#define REG_NOA_DESC_START 0x05E8 +#define REG_NOA_DESC_COUNT 0x05EC + + +#define REG_SYS_ISO_CTRL 0x0000 +//#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS0_CTRL_6 0x0016 +#define REG_POWER_OFF_IN_PROCESS 0x0017 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001C +//#define REG_RF_CTRL 0x001F +#define REG_LDOA15_CTRL 0x0020 +#define REG_LDOV12D_CTRL 0x0021 +//#define REG_LDOHCI12_CTRL 0x0022 +#define REG_LPLDO_CTRL 0x0023 +//#define REG_AFE_XTAL_CTRL 0x0024 +//#define REG_AFE_PLL_CTRL 0x0028 +#define REG_MAC_PHY_CTRL 0x002c //for 92d, DMDP,SMSP,DMSP contrl +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_HSIMR 0x0058 +#define REG_HSISR 0x005c +#define REG_GPIO_PIN_CTRL_2 0x0060 // RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. +#define REG_GPIO_IO_SEL_2 0x0062 // RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. +#define REG_MULTI_FUNC_CTRL 0x0068 // RTL8723 WIFI/BT/GPS Multi-Function control source. +#define REG_GPIO_OUTPUT 0x006c +#define REG_AFE_XTAL_CTRL_EXT 0x0078 //RTL8188E +#define REG_XCK_OUT_CTRL 0x007c //RTL8188E +//#define REG_MCUFWDL 0x0080 +#define REG_WOL_EVENT 0x0081 //RTL8188E +#define REG_MCUTSTCFG 0x0084 +#define REG_HMEBOX_EXT_0 0x0088 +#define REG_HMEBOX_EXT_1 0x008A +#define REG_HMEBOX_EXT_2 0x008C +#define REG_HMEBOX_EXT_3 0x008E +#define REG_HOST_SUSP_CNT 0x00BC // RTL8192C Host suspend counter on FPGA platform +#define REG_HIMR_88E 0x00B0 //RTL8188E +#define REG_HISR_88E 0x00B4 //RTL8188E +#define REG_HIMRE_88E 0x00B8 //RTL8188E +#define REG_HISRE_88E 0x00BC //RTL8188E +#define REG_EFUSE_ACCESS 0x00CF // Efuse access protection for RTL8723 +#define REG_BIST_SCAN 0x00D0 +#define REG_BIST_RPT 0x00D4 +#define REG_BIST_ROM_RPT 0x00D8 +#define REG_USB_SIE_INTF 0x00E0 +#define REG_PCIE_MIO_INTF 0x00E4 +#define REG_PCIE_MIO_INTD 0x00E8 +#define REG_HPON_FSM 0x00EC +#define REG_SYS_CFG 0x00F0 +#define REG_GPIO_OUTSTS 0x00F4 // For RTL8723 only. +#define REG_TYPE_ID 0x00FC + +#define REG_32K_CTRL 0x0194 //RTL8188E + +#define rConfig_AntA 0xb68 +#define rConfig_AntB 0xb6c + + +//============================================================================ +// 8188E Regsiter Bit and Content definition +//============================================================================ + + +//---------------------------------------------------------------------------- +// 8188E REG_88E_BB_PAD_CTRL bits (Offset 0x64-66, 24 bits) +//---------------------------------------------------------------------------- +#define BB_PAD_CTRL_88E_PAPE_EN BIT(19) // PAD ¡§P_LNAON¡¨ output enable +#define BB_PAD_CTRL_88E_PAPE_DRV BIT(18) // PAD ¡§P_LNAON¡¨ output value +#define BB_PAD_CTRL_88E_LNAON_SR BIT(17) // Control SR of PAD ¡§P_LNAON¡¨ to control the slew rate +#define BB_PAD_CTRL_88E_LNAON_E2 BIT(16) // Control E2 of PAD ¡§P_LNAON¡¨ for its output driving capability +#define BB_PAD_CTRL_88E_TRSW_EN BIT(11) // PAD ¡§P_TRSWP¡¨ and ¡§P_TRSWN¡¨ output enable +#define BB_PAD_CTRL_88E_TRSW_DRV BIT(10) // PADs ¡§P_TRSWP¡¨ and ¡§P_TRSWN¡¨ outputs values + + +//---------------------------------------------------------------------------- +// 8188E REG_88E_WLLPS_CTRL bits (Offset 0x90-93, 32 bits) +//---------------------------------------------------------------------------- +#define WLLPS_CTRL_88E_EABM BIT(31) +#define WLLPS_CTRL_88E_ACKF BIT(30) +#define WLLPS_CTRL_88E_ESWR BIT(28) +#define WLLPS_CTRL_88E_PWMM BIT(27) +#define WLLPS_CTRL_88E_EECK BIT(26) +#define WLLPS_CTRL_88E_ELDO BIT(25) +#define WLLPS_CTRL_88E_EXTAL BIT(24) +#define WLLPS_CTRL_88E_LPS_EN BIT(0) + + +//---------------------------------------------------------------------------- +// 8188E REG_88E_HIMR bits (Offset 0xB0-B3, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8188E REG_88E_HISR bits (Offset 0xB4-B7, 32 bits) +//---------------------------------------------------------------------------- +#define HIMR_88E_TXCCK BIT(30) // TXRPT interrupt when CCX bit of the packet is set +#define HIMR_88E_PSTIMEOUT BIT(29) // Power Save Time Out Interrupt +#define HIMR_88E_GTINT4 BIT(28) // When GTIMER4 expires, this bit is set to 1 +#define HIMR_88E_GTINT3 BIT(27) // When GTIMER3 expires, this bit is set to 1 +#define HIMR_88E_TBDER BIT(26) // Transmit Beacon0 Error +#define HIMR_88E_TBDOK BIT(25) // Transmit Beacon0 OK, ad hoc only +#define HIMR_88E_TSF_BIT32_TOGGLE BIT(24) // TSF Timer BIT32 toggle indication interrupt +#define HIMR_88E_BcnInt BIT(20) // Beacon DMA Interrupt 0 +#define HIMR_88E_BDOK BIT(16) // Beacon Queue DMA OK0 +#define HIMR_88E_HSISR_IND_ON_INT BIT(15) // HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) +#define HIMR_88E_BCNDMAINT_E BIT(14) // Beacon DMA Interrupt Extension for Win7 +#define HIMR_88E_ATIMEND BIT(12) // CTWidnow End or ATIM Window End +#define HIMR_88E_HISR1_IND_INT BIT(11) // HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1) +#define HIMR_88E_C2HCMD BIT(10) // CPU to Host Command INT Status, Write 1 clear +#define HIMR_88E_CPWM2 BIT(9) // CPU power Mode exchange INT Status, Write 1 clear +#define HIMR_88E_CPWM BIT(8) // CPU power Mode exchange INT Status, Write 1 clear +#define HIMR_88E_HIGHDOK BIT(7) // High Queue DMA OK +#define HIMR_88E_MGNTDOK BIT(6) // Management Queue DMA OK +#define HIMR_88E_BKDOK BIT(5) // AC_BK DMA OK +#define HIMR_88E_BEDOK BIT(4) // AC_BE DMA OK +#define HIMR_88E_VIDOK BIT(3) // AC_VI DMA OK +#define HIMR_88E_VODOK BIT(2) // AC_VO DMA OK +#define HIMR_88E_RDU BIT(1) // Rx Descriptor Unavailable +#define HIMR_88E_ROK BIT(0) // Receive DMA OK + + +//---------------------------------------------------------------------------- +// 8188E REG_88E_HIMRE bits (Offset 0xB8-BB, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8188E REG_88E_HIMSE bits (Offset 0xBC-BF, 32 bits) +//---------------------------------------------------------------------------- +#define HIMRE_88E_BCNDMAINT7 BIT(27) // Beacon DMA Interrupt 7 +#define HIMRE_88E_BCNDMAINT6 BIT(26) // Beacon DMA Interrupt 6 +#define HIMRE_88E_BCNDMAINT5 BIT(25) // Beacon DMA Interrupt 5 +#define HIMRE_88E_BCNDMAINT4 BIT(24) // Beacon DMA Interrupt 4 +#define HIMRE_88E_BCNDMAINT3 BIT(23) // Beacon DMA Interrupt 3 +#define HIMRE_88E_BCNDMAINT2 BIT(22) // Beacon DMA Interrupt 2 +#define HIMRE_88E_BCNDMAINT1 BIT(21) // Beacon DMA Interrupt 1 +#define HIMRE_88E_BCNDOK7 BIT(20) // Beacon Queue DMA OK Interrup 7 +#define HIMRE_88E_BCNDOK6 BIT(19) // Beacon Queue DMA OK Interrup 6 +#define HIMRE_88E_BCNDOK5 BIT(18) // Beacon Queue DMA OK Interrup 5 +#define HIMRE_88E_BCNDOK4 BIT(17) // Beacon Queue DMA OK Interrup 4 +#define HIMRE_88E_BCNDOK3 BIT(16) // Beacon Queue DMA OK Interrup 3 +#define HIMRE_88E_BCNDOK2 BIT(15) // Beacon Queue DMA OK Interrup 2 +#define HIMRE_88E_BCNDOK1 BIT(14) // Beacon Queue DMA OK Interrup 1 +#define HIMRE_88E_ATIMEND_E BIT(13) // ATIM Window End Extension for Win7 +#define HIMRE_88E_TXERR BIT(11) // Tx Error Flag Interrupt Status, write 1 clear. +#define HIMRE_88E_RXERR BIT(10) // Rx Error Flag INT Status, Write 1 clear +#define HIMRE_88E_TXFOVW BIT(9) // Transmit FIFO Overflow +#define HIMRE_88E_RXFOVW BIT(8) // Receive FIFO Overflow + + +//---------------------------------------------------------------------------- +// 8188E REG_EFUSE_ACCESS (Offset 0xCF, 8 bits) +//---------------------------------------------------------------------------- +#define EFUSE_ACCESS_ON 0x69 // For RTL8723 only. +#define EFUSE_ACCESS_OFF 0x00 // For RTL8723 only. + + +//---------------------------------------------------------------------------- +// 8188E REG_88E_WATCHDOG bits (Offset 0x368-369, 16 bits) +//---------------------------------------------------------------------------- +#define WATCHDOG_88E_ENABLE BIT(15) // Enable lbc timeout watchdog +#define WATCHDOG_88E_R_IO_TIMEOUT_FLAG BIT(14) // Lbc timeout flag.Write ¡§1¡¨ to clear +#define WATCHDOG_88E_RECORD_Mask 0x3FFF // Time out register address + + +//---------------------------------------------------------------------------- +// 8188E REG_88E_TXRPT_CTRL bits (Offset 0x4EC-4EF, 32 bits) +//---------------------------------------------------------------------------- +#define TXRPT_CTRL_88E_CNT_TH_SHIFT 16 +#define TXRPT_CTRL_88E_CNT_TH_Mask 0xFFFF +#define TXRPT_CTRL_88E_RPT_MACID_SHIFT 8 +#define TXRPT_CTRL_88E_RPT_MACID_Mask 0x7F +#define TXRPT_CTRL_88E_BCN_EN BIT(4) +#define TXRPT_CTRL_88E_TXRPT_DIS BIT(3) +#define TXRPT_CTRL_88E_CNT_OVER_EN BIT(2) +#define TXRPT_CTRL_88E_TXRPT_TIM_EN BIT(1) +#define TXRPT_CTRL_88E_TXRPT_EN BIT(0) + + +//---------------------------------------------------------------------------- +// 8188E REG_88E_TXRPT_STSSET bits (Offset 0x4F2-4F3, 16 bits) +//---------------------------------------------------------------------------- +#define TXRPT_STSSET_88E_TX_STS_SEL_SHIFT 11 +#define TXRPT_STSSET_88E_TX_STS_SEL_Mask 0x1F +#define TXRPT_STSSET_88E_TX_STS_CLR BIT(10) +#define TXRPT_STSSET_88E_TX_STS_EN BIT(8) +#define TXRPT_STSSET_88E_TX_STS_SET BIT(7) +#define TXRPT_STSSET_88E_TX_STS_PORT BIT(6) +#define TXRPT_STSSET_88E_TX_STS_SUBTPY_SHIFT 2 +#define TXRPT_STSSET_88E_TX_STS_SUBTPY_Mask 0xF +#define TXRPT_STSSET_88E_TX_STS_TPY_SHIFT 0 +#define TXRPT_STSSET_88E_TX_STS_TPY_Mask 0x3 + + +//---------------------------------------------------------------------------- +// 8188E REG_88E_TXRPT_STSVLD bits (Offset 0x4F4-4F6, 24 bits) +//---------------------------------------------------------------------------- +#define TXRPT_STSVLD_88E_TX_TPY7_VLD BIT(23) +#define TXRPT_STSVLD_88E_TX_TPY6_VLD BIT(22) +#define TXRPT_STSVLD_88E_TX_TPY5_VLD BIT(21) +#define TXRPT_STSVLD_88E_TX_TPY4_VLD BIT(20) +#define TXRPT_STSVLD_88E_TX_TPY3_VLD BIT(19) +#define TXRPT_STSVLD_88E_TX_TPY2_VLD BIT(18) +#define TXRPT_STSVLD_88E_TX_TPY1_VLD BIT(17) +#define TXRPT_STSVLD_88E_TX_TPY0_VLD BIT(16) +#define TXRPT_STSVLD_88E_TX_BCN7_FAIL BIT(15) +#define TXRPT_STSVLD_88E_TX_BCN6_FAIL BIT(14) +#define TXRPT_STSVLD_88E_TX_BCN5_FAIL BIT(13) +#define TXRPT_STSVLD_88E_TX_BCN4_FAIL BIT(12) +#define TXRPT_STSVLD_88E_TX_BCN3_FAIL BIT(11) +#define TXRPT_STSVLD_88E_TX_BCN2_FAIL BIT(10) +#define TXRPT_STSVLD_88E_TX_BCN1_FAIL BIT(9) +#define TXRPT_STSVLD_88E_TX_BCN0_FAIL BIT(8) +#define TXRPT_STSVLD_88E_TX_BCN7_OK BIT(7) +#define TXRPT_STSVLD_88E_TX_BCN6_OK BIT(6) +#define TXRPT_STSVLD_88E_TX_BCN5_OK BIT(5) +#define TXRPT_STSVLD_88E_TX_BCN4_OK BIT(4) +#define TXRPT_STSVLD_88E_TX_BCN3_OK BIT(3) +#define TXRPT_STSVLD_88E_TX_BCN2_OK BIT(2) +#define TXRPT_STSVLD_88E_TX_BCN1_OK BIT(1) +#define TXRPT_STSVLD_88E_TX_BCN0_OK BIT(0) + + +//---------------------------------------------------------------------------- +// 8188E REG_88E_TX_STS_INF bits (Offset 0x4F8-4F9, 16 bits) +//---------------------------------------------------------------------------- +#define TX_STS_INF_88E_TX_STS_INF_EN BIT(8) +#define TX_STS_INF_88E_TX_STS_SET_INF BIT(7) +#define TX_STS_INF_88E_TX_STS_PORT_INF BIT(6) +#define TX_STS_INF_88E_TX_STS_SUBTPY_INF_SHIFT 2 +#define TX_STS_INF_88E_TX_STS_SUBTPY_INF_Mask 0xF +#define TX_STS_INF_88E_TX_STS_TPY_INF_SHIFT 0 +#define TX_STS_INF_88E_TX_STS_TPY_INF_Mask 0x3 + + +//---------------------------------------------------------------------------- +// 8192C EEPROM/EFUSE share register definition. +//---------------------------------------------------------------------------- + +//==================================================== +// EEPROM/Efuse PG Offset for 88EE/88EU/88ES +//==================================================== +#define EEPROM_TX_PWR_INX_88E 0x10 + +#define EEPROM_ChannelPlan_88E 0xB8 +#define EEPROM_XTAL_88E 0xB9 +#define EEPROM_THERMAL_METER_88E 0xBA +#define EEPROM_IQK_LCK_88E 0xBB +#define EEPROM_88E_SDIOTYPE 0xD0 + +#define EEPROM_RF_BOARD_OPTION_88E 0xC1 +#define EEPROM_RF_FEATURE_OPTION_88E 0xC2 +#define EEPROM_RF_BT_SETTING_88E 0xC3 +#define EEPROM_VERSION_88E 0xC4 +#define EEPROM_CUSTOMERID_88E 0xC5 +#define EEPROM_RF_ANTENNA_OPT_88E 0xC9 + +// RTL88EE +#define EEPROM_MAC_ADDR_88EE 0xD0 +#define EEPROM_VID_88EE 0xD6 +#define EEPROM_DID_88EE 0xD8 +#define EEPROM_SVID_88EE 0xDA +#define EEPROM_SMID_88EE 0xDC + +//RTL88EU +#define EEPROM_MAC_ADDR_88EU 0xD7 +#define EEPROM_VID_88EU 0xD0 +#define EEPROM_PID_88EU 0xD2 + +// RTL88ES +#define EEPROM_MAC_ADDR_88ES 0x11A + + +//----------------------------------------------------- +// +// RTL8188E SDIO Configuration +// +//----------------------------------------------------- + +// I/O bus domain address mapping +#define SDIO_LOCAL_BASE 0x10250000 +#define WLAN_IOREG_BASE 0x10260000 +#define FIRMWARE_FIFO_BASE 0x10270000 +#define TX_HIQ_BASE 0x10310000 +#define TX_MIQ_BASE 0x10320000 +#define TX_LOQ_BASE 0x10330000 +#define RX_RX0FF_BASE 0x10340000 + +// SDIO host local register space mapping. +#define SDIO_LOCAL_MSK 0x0FFF +#define WLAN_IOREG_MSK 0x7FFF +#define WLAN_FIFO_MSK 0x1FFF // Aggregation Length[12:0] +#define WLAN_RX0FF_MSK 0x0003 + +#define SDIO_WITHOUT_REF_DEVICE_ID 0 // Without reference to the SDIO Device ID +#define SDIO_LOCAL_DEVICE_ID 0 // 0b[16], 000b[15:13] +#define WLAN_TX_HIQ_DEVICE_ID 4 // 0b[16], 100b[15:13] +#define WLAN_TX_MIQ_DEVICE_ID 5 // 0b[16], 101b[15:13] +#define WLAN_TX_LOQ_DEVICE_ID 6 // 0b[16], 110b[15:13] +#define WLAN_RX0FF_DEVICE_ID 7 // 0b[16], 111b[15:13] +#define WLAN_IOREG_DEVICE_ID 8 // 1b[16] + +// SDIO Tx Free Page Index +#define HI_QUEUE_IDX 0 +#define MID_QUEUE_IDX 1 +#define LOW_QUEUE_IDX 2 +#define PUBLIC_QUEUE_IDX 3 + +#define SDIO_MAX_TX_QUEUE 3 // HIQ, MIQ and LOQ +#define SDIO_MAX_RX_QUEUE 1 + +#define SDIO_REG_TX_CTRL 0x0000 // SDIO Tx Control +#define SDIO_REG_HIMR 0x0014 // SDIO Host Interrupt Mask +#define SDIO_REG_HISR 0x0018 // SDIO Host Interrupt Service Routine +#define SDIO_REG_HCPWM 0x0019 // HCI Current Power Mode +#define SDIO_REG_RX0_REQ_LEN 0x001C // RXDMA Request Length +#define SDIO_REG_FREE_TXPG 0x0020 // Free Tx Buffer Page +#define SDIO_REG_HCPWM1 0x0024 // HCI Current Power Mode 1 +#define SDIO_REG_OQT_FREE_SPACE 0x0025 // OQT Free Space +#define SDIO_REG_HCPWM2 0x0026 // HCI Current Power Mode 2 +#define SDIO_REG_HTSFR_INFO 0x0030 // HTSF Informaion +#define SDIO_REG_HRPWM1 0x0080 // HCI Request Power Mode 1 +#define SDIO_REG_HRPWM2 0x0082 // HCI Request Power Mode 2 +#define SDIO_REG_HPS_CLKR 0x0084 // HCI Power Save Clock +#define SDIO_REG_HSUS_CTRL 0x0086 // SDIO HCI Suspend Control +#define SDIO_REG_HIMR_ON 0x0090 // SDIO Host Extension Interrupt Mask Always +#define SDIO_REG_HISR_ON 0x0091 // SDIO Host Extension Interrupt Status Always + +#define SDIO_HIMR_DISABLED 0 + +// RTL8188E SDIO Host Interrupt Mask Register +#define SDIO_HIMR_RX_REQUEST_MSK BIT0 +#define SDIO_HIMR_AVAL_MSK BIT1 +#define SDIO_HIMR_TXERR_MSK BIT2 +#define SDIO_HIMR_RXERR_MSK BIT3 +#define SDIO_HIMR_TXFOVW_MSK BIT4 +#define SDIO_HIMR_RXFOVW_MSK BIT5 +#define SDIO_HIMR_TXBCNOK_MSK BIT6 +#define SDIO_HIMR_TXBCNERR_MSK BIT7 +#define SDIO_HIMR_BCNERLY_INT_MSK BIT16 +#define SDIO_HIMR_C2HCMD_MSK BIT17 +#define SDIO_HIMR_CPWM1_MSK BIT18 +#define SDIO_HIMR_CPWM2_MSK BIT19 +#define SDIO_HIMR_HSISR_IND_MSK BIT20 +#define SDIO_HIMR_GTINT3_IND_MSK BIT21 +#define SDIO_HIMR_GTINT4_IND_MSK BIT22 +#define SDIO_HIMR_PSTIMEOUT_MSK BIT23 +#define SDIO_HIMR_OCPINT_MSK BIT24 +#define SDIO_HIMR_ATIMEND_MSK BIT25 +#define SDIO_HIMR_ATIMEND_E_MSK BIT26 +#define SDIO_HIMR_CTWEND_MSK BIT27 + +//RTL8188E SDIO Specific +#define SDIO_HIMR_MCU_ERR_MSK BIT28 +#define SDIO_HIMR_TSF_BIT32_TOGGLE_MSK BIT29 + +// SDIO Host Interrupt Service Routine +#define SDIO_HISR_RX_REQUEST BIT0 +#define SDIO_HISR_AVAL BIT1 +#define SDIO_HISR_TXERR BIT2 +#define SDIO_HISR_RXERR BIT3 +#define SDIO_HISR_TXFOVW BIT4 +#define SDIO_HISR_RXFOVW BIT5 +#define SDIO_HISR_TXBCNOK BIT6 +#define SDIO_HISR_TXBCNERR BIT7 +#define SDIO_HISR_BCNERLY_INT BIT16 +#define SDIO_HISR_C2HCMD BIT17 +#define SDIO_HISR_CPWM1 BIT18 +#define SDIO_HISR_CPWM2 BIT19 +#define SDIO_HISR_HSISR_IND BIT20 +#define SDIO_HISR_GTINT3_IND BIT21 +#define SDIO_HISR_GTINT4_IND BIT22 +#define SDIO_HISR_PSTIMEOUT BIT23 +#define SDIO_HISR_OCPINT BIT24 +#define SDIO_HISR_ATIMEND BIT25 +#define SDIO_HISR_ATIMEND_E BIT26 +#define SDIO_HISR_CTWEND BIT27 + +//RTL8188E SDIO Specific +#define SDIO_HISR_MCU_ERR BIT28 +#define SDIO_HISR_TSF_BIT32_TOGGLE BIT29 + +#define MASK_SDIO_HISR_CLEAR (SDIO_HISR_TXERR |\ + SDIO_HISR_RXERR |\ + SDIO_HISR_TXFOVW |\ + SDIO_HISR_RXFOVW |\ + SDIO_HISR_TXBCNOK |\ + SDIO_HISR_TXBCNERR |\ + SDIO_HISR_C2HCMD |\ + SDIO_HISR_CPWM1 |\ + SDIO_HISR_CPWM2 |\ + SDIO_HISR_HSISR_IND |\ + SDIO_HISR_GTINT3_IND |\ + SDIO_HISR_GTINT4_IND |\ + SDIO_HISR_PSTIMEOUT |\ + SDIO_HISR_OCPINT) + +// SDIO HCI Suspend Control Register +#define HCI_RESUME_PWR_RDY BIT1 +#define HCI_SUS_CTRL BIT0 + +// SDIO Tx FIFO related +#define SDIO_TX_FREE_PG_QUEUE 4 // The number of Tx FIFO free page +#define SDIO_TX_FIFO_PAGE_SZ 128 + +//----------------------------------------------------- +// +// 0xFE00h ~ 0xFE55h USB Configuration +// +//----------------------------------------------------- + +//2 Special Option +// 0; Use interrupt endpoint to upload interrupt pkt +// 1; Use bulk endpoint to upload interrupt pkt, +#define INT_BULK_SEL BIT(4) + +//======================================================== +// General definitions +//======================================================== + +#define LAST_ENTRY_OF_TX_PKT_BUFFER_88E 176 // 22k 22528 bytes + +#ifdef USE_OUT_SRC + + +/*--------------------------Define Parameters-------------------------------*/ + + +// +// BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF +// 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF +// 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 +// 3. RF register 0x00-2E +// 4. Bit Mask for BB/RF register +// 5. Other defintion for BB/RF R/W +// + + +// +// 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF +// 1. Page1(0x100) +// +#define rPMAC_Reset 0x100 +#define rPMAC_TxStart 0x104 +#define rPMAC_TxLegacySIG 0x108 +#define rPMAC_TxHTSIG1 0x10c +#define rPMAC_TxHTSIG2 0x110 +#define rPMAC_PHYDebug 0x114 +#define rPMAC_TxPacketNum 0x118 +#define rPMAC_TxIdle 0x11c +#define rPMAC_TxMACHeader0 0x120 +#define rPMAC_TxMACHeader1 0x124 +#define rPMAC_TxMACHeader2 0x128 +#define rPMAC_TxMACHeader3 0x12c +#define rPMAC_TxMACHeader4 0x130 +#define rPMAC_TxMACHeader5 0x134 +#define rPMAC_TxDataType 0x138 +#define rPMAC_TxRandomSeed 0x13c +#define rPMAC_CCKPLCPPreamble 0x140 +#define rPMAC_CCKPLCPHeader 0x144 +#define rPMAC_CCKCRC16 0x148 +#define rPMAC_OFDMRxCRC32OK 0x170 +#define rPMAC_OFDMRxCRC32Er 0x174 +#define rPMAC_OFDMRxParityEr 0x178 +#define rPMAC_OFDMRxCRC8Er 0x17c +#define rPMAC_CCKCRxRC16Er 0x180 +#define rPMAC_CCKCRxRC32Er 0x184 +#define rPMAC_CCKCRxRC32OK 0x188 +#define rPMAC_TxStatus 0x18c + +// +// 2. Page2(0x200) +// +// The following two definition are only used for USB interface. +#define RF_BB_CMD_ADDR 0x02c0 // RF/BB read/write command address. +#define RF_BB_CMD_DATA 0x02c4 // RF/BB read/write command data. + +// +// 3. Page8(0x800) +// +#define rFPGA0_RFMOD 0x800 //RF mode & CCK TxSC // RF BW Setting?? + +#define rFPGA0_TxInfo 0x804 // Status report?? +#define rFPGA0_PSDFunction 0x808 + +#define rFPGA0_TxGainStage 0x80c // Set TX PWR init gain? + +#define rFPGA0_RFTiming1 0x810 // Useless now +#define rFPGA0_RFTiming2 0x814 + +#define rFPGA0_XA_HSSIParameter1 0x820 // RF 3 wire register +#define rFPGA0_XA_HSSIParameter2 0x824 +#define rFPGA0_XB_HSSIParameter1 0x828 +#define rFPGA0_XB_HSSIParameter2 0x82c + +#define rFPGA0_XA_LSSIParameter 0x840 +#define rFPGA0_XB_LSSIParameter 0x844 + +#define rFPGA0_RFWakeUpParameter 0x850 // Useless now +#define rFPGA0_RFSleepUpParameter 0x854 + +#define rFPGA0_XAB_SwitchControl 0x858 // RF Channel switch +#define rFPGA0_XCD_SwitchControl 0x85c + +#define rFPGA0_XA_RFInterfaceOE 0x860 // RF Channel switch +#define rFPGA0_XB_RFInterfaceOE 0x864 + +#define rFPGA0_XAB_RFInterfaceSW 0x870 // RF Interface Software Control +#define rFPGA0_XCD_RFInterfaceSW 0x874 + +#define rFPGA0_XAB_RFParameter 0x878 // RF Parameter +#define rFPGA0_XCD_RFParameter 0x87c + +#define rFPGA0_AnalogParameter1 0x880 // Crystal cap setting RF-R/W protection for parameter4?? +#define rFPGA0_AnalogParameter2 0x884 +#define rFPGA0_AnalogParameter3 0x888 +#define rFPGA0_AdDaClockEn 0x888 // enable ad/da clock1 for dual-phy +#define rFPGA0_AnalogParameter4 0x88c + +#define rFPGA0_XA_LSSIReadBack 0x8a0 // Tranceiver LSSI Readback +#define rFPGA0_XB_LSSIReadBack 0x8a4 +#define rFPGA0_XC_LSSIReadBack 0x8a8 +#define rFPGA0_XD_LSSIReadBack 0x8ac + +#define rFPGA0_PSDReport 0x8b4 // Useless now +#define TransceiverA_HSPI_Readback 0x8b8 // Transceiver A HSPI Readback +#define TransceiverB_HSPI_Readback 0x8bc // Transceiver B HSPI Readback +#define rFPGA0_XAB_RFInterfaceRB 0x8e0 // Useless now // RF Interface Readback Value +#define rFPGA0_XCD_RFInterfaceRB 0x8e4 // Useless now + +// +// 4. Page9(0x900) +// +#define rFPGA1_RFMOD 0x900 //RF mode & OFDM TxSC // RF BW Setting?? + +#define rFPGA1_TxBlock 0x904 // Useless now +#define rFPGA1_DebugSelect 0x908 // Useless now +#define rFPGA1_TxInfo 0x90c // Useless now // Status report?? + +// +// 5. PageA(0xA00) +// +// Set Control channel to upper or lower. These settings are required only for 40MHz +#define rCCK0_System 0xa00 + +#define rCCK0_AFESetting 0xa04 // Disable init gain now // Select RX path by RSSI +#define rCCK0_CCA 0xa08 // Disable init gain now // Init gain + +#define rCCK0_RxAGC1 0xa0c //AGC default value, saturation level // Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now. Not the same as 90 series +#define rCCK0_RxAGC2 0xa10 //AGC & DAGC + +#define rCCK0_RxHP 0xa14 + +#define rCCK0_DSPParameter1 0xa18 //Timing recovery & Channel estimation threshold +#define rCCK0_DSPParameter2 0xa1c //SQ threshold + +#define rCCK0_TxFilter1 0xa20 +#define rCCK0_TxFilter2 0xa24 +#define rCCK0_DebugPort 0xa28 //debug port and Tx filter3 +#define rCCK0_FalseAlarmReport 0xa2c //0xa2d useless now 0xa30-a4f channel report +#define rCCK0_TRSSIReport 0xa50 +#define rCCK0_RxReport 0xa54 //0xa57 +#define rCCK0_FACounterLower 0xa5c //0xa5b +#define rCCK0_FACounterUpper 0xa58 //0xa5c + +// +// PageB(0xB00) +// +#define rPdp_AntA 0xb00 +#define rPdp_AntA_4 0xb04 +#define rPdp_AntA_8 0xb08 +#define rPdp_AntA_C 0xb0c +#define rPdp_AntA_10 0xb10 +#define rPdp_AntA_14 0xb14 +#define rPdp_AntA_18 0xb18 +#define rPdp_AntA_1C 0xb1c +#define rPdp_AntA_20 0xb20 +#define rPdp_AntA_24 0xb24 + +#define rConfig_Pmpd_AntA 0xb28 +#define rConfig_ram64x16 0xb2c + +#define rBndA 0xb30 +#define rHssiPar 0xb34 + +#define rConfig_AntA 0xb68 +#define rConfig_AntB 0xb6c + +#define rPdp_AntB 0xb70 +#define rPdp_AntB_4 0xb74 +#define rPdp_AntB_8 0xb78 +#define rPdp_AntB_C 0xb7c +#define rPdp_AntB_10 0xb80 +#define rPdp_AntB_14 0xb84 +#define rPdp_AntB_18 0xb88 +#define rPdp_AntB_1C 0xb8c +#define rPdp_AntB_20 0xb90 +#define rPdp_AntB_24 0xb94 + +#define rConfig_Pmpd_AntB 0xb98 + +#define rBndB 0xba0 + +#define rAPK 0xbd8 +#define rPm_Rx0_AntA 0xbdc +#define rPm_Rx1_AntA 0xbe0 +#define rPm_Rx2_AntA 0xbe4 +#define rPm_Rx3_AntA 0xbe8 +#define rPm_Rx0_AntB 0xbec +#define rPm_Rx1_AntB 0xbf0 +#define rPm_Rx2_AntB 0xbf4 +#define rPm_Rx3_AntB 0xbf8 + + + +// +// 6. PageC(0xC00) +// +#define rOFDM0_LSTF 0xc00 + +#define rOFDM0_TRxPathEnable 0xc04 +#define rOFDM0_TRMuxPar 0xc08 +#define rOFDM0_TRSWIsolation 0xc0c + +#define rOFDM0_XARxAFE 0xc10 //RxIQ DC offset, Rx digital filter, DC notch filter +#define rOFDM0_XARxIQImbalance 0xc14 //RxIQ imblance matrix +#define rOFDM0_XBRxAFE 0xc18 +#define rOFDM0_XBRxIQImbalance 0xc1c +#define rOFDM0_XCRxAFE 0xc20 +#define rOFDM0_XCRxIQImbalance 0xc24 +#define rOFDM0_XDRxAFE 0xc28 +#define rOFDM0_XDRxIQImbalance 0xc2c + +#define rOFDM0_RxDetector1 0xc30 //PD,BW & SBD // DM tune init gain +#define rOFDM0_RxDetector2 0xc34 //SBD & Fame Sync. +#define rOFDM0_RxDetector3 0xc38 //Frame Sync. +#define rOFDM0_RxDetector4 0xc3c //PD, SBD, Frame Sync & Short-GI + +#define rOFDM0_RxDSP 0xc40 //Rx Sync Path +#define rOFDM0_CFOandDAGC 0xc44 //CFO & DAGC +#define rOFDM0_CCADropThreshold 0xc48 //CCA Drop threshold +#define rOFDM0_ECCAThreshold 0xc4c // energy CCA + +#define rOFDM0_XAAGCCore1 0xc50 // DIG +#define rOFDM0_XAAGCCore2 0xc54 +#define rOFDM0_XBAGCCore1 0xc58 +#define rOFDM0_XBAGCCore2 0xc5c +#define rOFDM0_XCAGCCore1 0xc60 +#define rOFDM0_XCAGCCore2 0xc64 +#define rOFDM0_XDAGCCore1 0xc68 +#define rOFDM0_XDAGCCore2 0xc6c + +#define rOFDM0_AGCParameter1 0xc70 +#define rOFDM0_AGCParameter2 0xc74 +#define rOFDM0_AGCRSSITable 0xc78 +#define rOFDM0_HTSTFAGC 0xc7c + +#define rOFDM0_XATxIQImbalance 0xc80 // TX PWR TRACK and DIG +#define rOFDM0_XATxAFE 0xc84 +#define rOFDM0_XBTxIQImbalance 0xc88 +#define rOFDM0_XBTxAFE 0xc8c +#define rOFDM0_XCTxIQImbalance 0xc90 +#define rOFDM0_XCTxAFE 0xc94 +#define rOFDM0_XDTxIQImbalance 0xc98 +#define rOFDM0_XDTxAFE 0xc9c + +#define rOFDM0_RxIQExtAnta 0xca0 +#define rOFDM0_TxCoeff1 0xca4 +#define rOFDM0_TxCoeff2 0xca8 +#define rOFDM0_TxCoeff3 0xcac +#define rOFDM0_TxCoeff4 0xcb0 +#define rOFDM0_TxCoeff5 0xcb4 +#define rOFDM0_TxCoeff6 0xcb8 +#define rOFDM0_RxHPParameter 0xce0 +#define rOFDM0_TxPseudoNoiseWgt 0xce4 +#define rOFDM0_FrameSync 0xcf0 +#define rOFDM0_DFSReport 0xcf4 + + +// +// 7. PageD(0xD00) +// +#define rOFDM1_LSTF 0xd00 +#define rOFDM1_TRxPathEnable 0xd04 + +#define rOFDM1_CFO 0xd08 // No setting now +#define rOFDM1_CSI1 0xd10 +#define rOFDM1_SBD 0xd14 +#define rOFDM1_CSI2 0xd18 +#define rOFDM1_CFOTracking 0xd2c +#define rOFDM1_TRxMesaure1 0xd34 +#define rOFDM1_IntfDet 0xd3c +#define rOFDM1_PseudoNoiseStateAB 0xd50 +#define rOFDM1_PseudoNoiseStateCD 0xd54 +#define rOFDM1_RxPseudoNoiseWgt 0xd58 + +#define rOFDM_PHYCounter1 0xda0 //cca, parity fail +#define rOFDM_PHYCounter2 0xda4 //rate illegal, crc8 fail +#define rOFDM_PHYCounter3 0xda8 //MCS not support + +#define rOFDM_ShortCFOAB 0xdac // No setting now +#define rOFDM_ShortCFOCD 0xdb0 +#define rOFDM_LongCFOAB 0xdb4 +#define rOFDM_LongCFOCD 0xdb8 +#define rOFDM_TailCFOAB 0xdbc +#define rOFDM_TailCFOCD 0xdc0 +#define rOFDM_PWMeasure1 0xdc4 +#define rOFDM_PWMeasure2 0xdc8 +#define rOFDM_BWReport 0xdcc +#define rOFDM_AGCReport 0xdd0 +#define rOFDM_RxSNR 0xdd4 +#define rOFDM_RxEVMCSI 0xdd8 +#define rOFDM_SIGReport 0xddc + + +// +// 8. PageE(0xE00) +// +#define rTxAGC_A_Rate18_06 0xe00 +#define rTxAGC_A_Rate54_24 0xe04 +#define rTxAGC_A_CCK1_Mcs32 0xe08 +#define rTxAGC_A_Mcs03_Mcs00 0xe10 +#define rTxAGC_A_Mcs07_Mcs04 0xe14 +#define rTxAGC_A_Mcs11_Mcs08 0xe18 +#define rTxAGC_A_Mcs15_Mcs12 0xe1c + +#define rTxAGC_B_Rate18_06 0x830 +#define rTxAGC_B_Rate54_24 0x834 +#define rTxAGC_B_CCK1_55_Mcs32 0x838 +#define rTxAGC_B_Mcs03_Mcs00 0x83c +#define rTxAGC_B_Mcs07_Mcs04 0x848 +#define rTxAGC_B_Mcs11_Mcs08 0x84c +#define rTxAGC_B_Mcs15_Mcs12 0x868 +#define rTxAGC_B_CCK11_A_CCK2_11 0x86c + +#define rFPGA0_IQK 0xe28 +#define rTx_IQK_Tone_A 0xe30 +#define rRx_IQK_Tone_A 0xe34 +#define rTx_IQK_PI_A 0xe38 +#define rRx_IQK_PI_A 0xe3c + +#define rTx_IQK 0xe40 +#define rRx_IQK 0xe44 +#define rIQK_AGC_Pts 0xe48 +#define rIQK_AGC_Rsp 0xe4c +#define rTx_IQK_Tone_B 0xe50 +#define rRx_IQK_Tone_B 0xe54 +#define rTx_IQK_PI_B 0xe58 +#define rRx_IQK_PI_B 0xe5c +#define rIQK_AGC_Cont 0xe60 + +#define rBlue_Tooth 0xe6c +#define rRx_Wait_CCA 0xe70 +#define rTx_CCK_RFON 0xe74 +#define rTx_CCK_BBON 0xe78 +#define rTx_OFDM_RFON 0xe7c +#define rTx_OFDM_BBON 0xe80 +#define rTx_To_Rx 0xe84 +#define rTx_To_Tx 0xe88 +#define rRx_CCK 0xe8c + +#define rTx_Power_Before_IQK_A 0xe94 +#define rTx_Power_After_IQK_A 0xe9c + +#define rRx_Power_Before_IQK_A 0xea0 +#define rRx_Power_Before_IQK_A_2 0xea4 +#define rRx_Power_After_IQK_A 0xea8 +#define rRx_Power_After_IQK_A_2 0xeac + +#define rTx_Power_Before_IQK_B 0xeb4 +#define rTx_Power_After_IQK_B 0xebc + +#define rRx_Power_Before_IQK_B 0xec0 +#define rRx_Power_Before_IQK_B_2 0xec4 +#define rRx_Power_After_IQK_B 0xec8 +#define rRx_Power_After_IQK_B_2 0xecc + +#define rRx_OFDM 0xed0 +#define rRx_Wait_RIFS 0xed4 +#define rRx_TO_Rx 0xed8 +#define rStandby 0xedc +#define rSleep 0xee0 +#define rPMPD_ANAEN 0xeec + +// +// 7. RF Register 0x00-0x2E (RF 8256) +// RF-0222D 0x00-3F +// +//Zebra1 +#define rZebra1_HSSIEnable 0x0 // Useless now +#define rZebra1_TRxEnable1 0x1 +#define rZebra1_TRxEnable2 0x2 +#define rZebra1_AGC 0x4 +#define rZebra1_ChargePump 0x5 +#define rZebra1_Channel 0x7 // RF channel switch + +//#endif +#define rZebra1_TxGain 0x8 // Useless now +#define rZebra1_TxLPF 0x9 +#define rZebra1_RxLPF 0xb +#define rZebra1_RxHPFCorner 0xc + +//Zebra4 +#define rGlobalCtrl 0 // Useless now +#define rRTL8256_TxLPF 19 +#define rRTL8256_RxLPF 11 + +//RTL8258 +#define rRTL8258_TxLPF 0x11 // Useless now +#define rRTL8258_RxLPF 0x13 +#define rRTL8258_RSSILPF 0xa + +// +// RL6052 Register definition +// +#define RF_AC 0x00 // + +#define RF_IQADJ_G1 0x01 // +#define RF_IQADJ_G2 0x02 // +#define RF_BS_PA_APSET_G1_G4 0x03 +#define RF_BS_PA_APSET_G5_G8 0x04 +#define RF_POW_TRSW 0x05 // + +#define RF_GAIN_RX 0x06 // +#define RF_GAIN_TX 0x07 // + +#define RF_TXM_IDAC 0x08 // +#define RF_IPA_G 0x09 // +#define RF_TXBIAS_G 0x0A +#define RF_TXPA_AG 0x0B +#define RF_IPA_A 0x0C // +#define RF_TXBIAS_A 0x0D +#define RF_BS_PA_APSET_G9_G11 0x0E +#define RF_BS_IQGEN 0x0F // + +#define RF_MODE1 0x10 // +#define RF_MODE2 0x11 // + +#define RF_RX_AGC_HP 0x12 // +#define RF_TX_AGC 0x13 // +#define RF_BIAS 0x14 // +#define RF_IPA 0x15 // +#define RF_TXBIAS 0x16 +#define RF_POW_ABILITY 0x17 // +#define RF_CHNLBW 0x18 // RF channel and BW switch +#define RF_TOP 0x19 // + +#define RF_RX_G1 0x1A // +#define RF_RX_G2 0x1B // + +#define RF_RX_BB2 0x1C // +#define RF_RX_BB1 0x1D // + +#define RF_RCK1 0x1E // +#define RF_RCK2 0x1F // + +#define RF_TX_G1 0x20 // +#define RF_TX_G2 0x21 // +#define RF_TX_G3 0x22 // + +#define RF_TX_BB1 0x23 // + +//#if HARDWARE_TYPE_IS_RTL8192D == 1 +#define RF_T_METER_92D 0x42 // +#define RF_T_METER_88E 0x42 // +//#else +#define RF_T_METER 0x24 // +//#endif + +#define RF_SYN_G1 0x25 // RF TX Power control +#define RF_SYN_G2 0x26 // RF TX Power control +#define RF_SYN_G3 0x27 // RF TX Power control +#define RF_SYN_G4 0x28 // RF TX Power control +#define RF_SYN_G5 0x29 // RF TX Power control +#define RF_SYN_G6 0x2A // RF TX Power control +#define RF_SYN_G7 0x2B // RF TX Power control +#define RF_SYN_G8 0x2C // RF TX Power control + +#define RF_RCK_OS 0x30 // RF TX PA control + +#define RF_RCK_OS 0x30 // RF TX PA control +#define RF_TXPA_G1 0x31 // RF TX PA control +#define RF_TXPA_G2 0x32 // RF TX PA control +#define RF_TXPA_G3 0x33 // RF TX PA control +#define RF_TX_BIAS_A 0x35 +#define RF_TX_BIAS_D 0x36 +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C // +#define RF_TRSW 0x3F + +#define RF_TXRF_A2 0x41 +#define RF_TXPA_G4 0x46 +#define RF_TXPA_A4 0x4B + +// +//Bit Mask +// +// 1. Page1(0x100) +#define bBBResetB 0x100 // Useless now? +#define bGlobalResetB 0x200 +#define bOFDMTxStart 0x4 +#define bCCKTxStart 0x8 +#define bCRC32Debug 0x100 +#define bPMACLoopback 0x10 +#define bTxLSIG 0xffffff +#define bOFDMTxRate 0xf +#define bOFDMTxReserved 0x10 +#define bOFDMTxLength 0x1ffe0 +#define bOFDMTxParity 0x20000 +#define bTxHTSIG1 0xffffff +#define bTxHTMCSRate 0x7f +#define bTxHTBW 0x80 +#define bTxHTLength 0xffff00 +#define bTxHTSIG2 0xffffff +#define bTxHTSmoothing 0x1 +#define bTxHTSounding 0x2 +#define bTxHTReserved 0x4 +#define bTxHTAggreation 0x8 +#define bTxHTSTBC 0x30 +#define bTxHTAdvanceCoding 0x40 +#define bTxHTShortGI 0x80 +#define bTxHTNumberHT_LTF 0x300 +#define bTxHTCRC8 0x3fc00 +#define bCounterReset 0x10000 +#define bNumOfOFDMTx 0xffff +#define bNumOfCCKTx 0xffff0000 +#define bTxIdleInterval 0xffff +#define bOFDMService 0xffff0000 +#define bTxMACHeader 0xffffffff +#define bTxDataInit 0xff +#define bTxHTMode 0x100 +#define bTxDataType 0x30000 +#define bTxRandomSeed 0xffffffff +#define bCCKTxPreamble 0x1 +#define bCCKTxSFD 0xffff0000 +#define bCCKTxSIG 0xff +#define bCCKTxService 0xff00 +#define bCCKLengthExt 0x8000 +#define bCCKTxLength 0xffff0000 +#define bCCKTxCRC16 0xffff +#define bCCKTxStatus 0x1 +#define bOFDMTxStatus 0x2 + +#define IS_BB_REG_OFFSET_92S(_Offset) ((_Offset >= 0x800) && (_Offset <= 0xfff)) + +// 2. Page8(0x800) +#define bRFMOD 0x1 // Reg 0x800 rFPGA0_RFMOD +#define bJapanMode 0x2 +#define bCCKTxSC 0x30 +#define bCCKEn 0x1000000 +#define bOFDMEn 0x2000000 + +#define bOFDMRxADCPhase 0x10000 // Useless now +#define bOFDMTxDACPhase 0x40000 +#define bXATxAGC 0x3f + +#define bAntennaSelect 0x0300 + +#define bXBTxAGC 0xf00 // Reg 80c rFPGA0_TxGainStage +#define bXCTxAGC 0xf000 +#define bXDTxAGC 0xf0000 + +#define bPAStart 0xf0000000 // Useless now +#define bTRStart 0x00f00000 +#define bRFStart 0x0000f000 +#define bBBStart 0x000000f0 +#define bBBCCKStart 0x0000000f +#define bPAEnd 0xf //Reg0x814 +#define bTREnd 0x0f000000 +#define bRFEnd 0x000f0000 +#define bCCAMask 0x000000f0 //T2R +#define bR2RCCAMask 0x00000f00 +#define bHSSI_R2TDelay 0xf8000000 +#define bHSSI_T2RDelay 0xf80000 +#define bContTxHSSI 0x400 //chane gain at continue Tx +#define bIGFromCCK 0x200 +#define bAGCAddress 0x3f +#define bRxHPTx 0x7000 +#define bRxHPT2R 0x38000 +#define bRxHPCCKIni 0xc0000 +#define bAGCTxCode 0xc00000 +#define bAGCRxCode 0x300000 + +#define b3WireDataLength 0x800 // Reg 0x820~84f rFPGA0_XA_HSSIParameter1 +#define b3WireAddressLength 0x400 + +#define b3WireRFPowerDown 0x1 // Useless now +//#define bHWSISelect 0x8 +#define b5GPAPEPolarity 0x40000000 +#define b2GPAPEPolarity 0x80000000 +#define bRFSW_TxDefaultAnt 0x3 +#define bRFSW_TxOptionAnt 0x30 +#define bRFSW_RxDefaultAnt 0x300 +#define bRFSW_RxOptionAnt 0x3000 +#define bRFSI_3WireData 0x1 +#define bRFSI_3WireClock 0x2 +#define bRFSI_3WireLoad 0x4 +#define bRFSI_3WireRW 0x8 +#define bRFSI_3Wire 0xf + +#define bRFSI_RFENV 0x10 // Reg 0x870 rFPGA0_XAB_RFInterfaceSW + +#define bRFSI_TRSW 0x20 // Useless now +#define bRFSI_TRSWB 0x40 +#define bRFSI_ANTSW 0x100 +#define bRFSI_ANTSWB 0x200 +#define bRFSI_PAPE 0x400 +#define bRFSI_PAPE5G 0x800 +#define bBandSelect 0x1 +#define bHTSIG2_GI 0x80 +#define bHTSIG2_Smoothing 0x01 +#define bHTSIG2_Sounding 0x02 +#define bHTSIG2_Aggreaton 0x08 +#define bHTSIG2_STBC 0x30 +#define bHTSIG2_AdvCoding 0x40 +#define bHTSIG2_NumOfHTLTF 0x300 +#define bHTSIG2_CRC8 0x3fc +#define bHTSIG1_MCS 0x7f +#define bHTSIG1_BandWidth 0x80 +#define bHTSIG1_HTLength 0xffff +#define bLSIG_Rate 0xf +#define bLSIG_Reserved 0x10 +#define bLSIG_Length 0x1fffe +#define bLSIG_Parity 0x20 +#define bCCKRxPhase 0x4 + +#define bLSSIReadAddress 0x7f800000 // T65 RF + +#define bLSSIReadEdge 0x80000000 //LSSI "Read" edge signal + +#define bLSSIReadBackData 0xfffff // T65 RF + +#define bLSSIReadOKFlag 0x1000 // Useless now +#define bCCKSampleRate 0x8 //0: 44MHz, 1:88MHz +#define bRegulator0Standby 0x1 +#define bRegulatorPLLStandby 0x2 +#define bRegulator1Standby 0x4 +#define bPLLPowerUp 0x8 +#define bDPLLPowerUp 0x10 +#define bDA10PowerUp 0x20 +#define bAD7PowerUp 0x200 +#define bDA6PowerUp 0x2000 +#define bXtalPowerUp 0x4000 +#define b40MDClkPowerUP 0x8000 +#define bDA6DebugMode 0x20000 +#define bDA6Swing 0x380000 + +#define bADClkPhase 0x4000000 // Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ + +#define b80MClkDelay 0x18000000 // Useless +#define bAFEWatchDogEnable 0x20000000 + +#define bXtalCap01 0xc0000000 // Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap +#define bXtalCap23 0x3 +#define bXtalCap92x 0x0f000000 +#define bXtalCap 0x0f000000 + +#define bIntDifClkEnable 0x400 // Useless +#define bExtSigClkEnable 0x800 +#define bBandgapMbiasPowerUp 0x10000 +#define bAD11SHGain 0xc0000 +#define bAD11InputRange 0x700000 +#define bAD11OPCurrent 0x3800000 +#define bIPathLoopback 0x4000000 +#define bQPathLoopback 0x8000000 +#define bAFELoopback 0x10000000 +#define bDA10Swing 0x7e0 +#define bDA10Reverse 0x800 +#define bDAClkSource 0x1000 +#define bAD7InputRange 0x6000 +#define bAD7Gain 0x38000 +#define bAD7OutputCMMode 0x40000 +#define bAD7InputCMMode 0x380000 +#define bAD7Current 0xc00000 +#define bRegulatorAdjust 0x7000000 +#define bAD11PowerUpAtTx 0x1 +#define bDA10PSAtTx 0x10 +#define bAD11PowerUpAtRx 0x100 +#define bDA10PSAtRx 0x1000 +#define bCCKRxAGCFormat 0x200 +#define bPSDFFTSamplepPoint 0xc000 +#define bPSDAverageNum 0x3000 +#define bIQPathControl 0xc00 +#define bPSDFreq 0x3ff +#define bPSDAntennaPath 0x30 +#define bPSDIQSwitch 0x40 +#define bPSDRxTrigger 0x400000 +#define bPSDTxTrigger 0x80000000 +#define bPSDSineToneScale 0x7f000000 +#define bPSDReport 0xffff + +// 3. Page9(0x900) +#define bOFDMTxSC 0x30000000 // Useless +#define bCCKTxOn 0x1 +#define bOFDMTxOn 0x2 +#define bDebugPage 0xfff //reset debug page and also HWord, LWord +#define bDebugItem 0xff //reset debug page and LWord +#define bAntL 0x10 +#define bAntNonHT 0x100 +#define bAntHT1 0x1000 +#define bAntHT2 0x10000 +#define bAntHT1S1 0x100000 +#define bAntNonHTS1 0x1000000 + +// 4. PageA(0xA00) +#define bCCKBBMode 0x3 // Useless +#define bCCKTxPowerSaving 0x80 +#define bCCKRxPowerSaving 0x40 + +#define bCCKSideBand 0x10 // Reg 0xa00 rCCK0_System 20/40 switch + +#define bCCKScramble 0x8 // Useless +#define bCCKAntDiversity 0x8000 +#define bCCKCarrierRecovery 0x4000 +#define bCCKTxRate 0x3000 +#define bCCKDCCancel 0x0800 +#define bCCKISICancel 0x0400 +#define bCCKMatchFilter 0x0200 +#define bCCKEqualizer 0x0100 +#define bCCKPreambleDetect 0x800000 +#define bCCKFastFalseCCA 0x400000 +#define bCCKChEstStart 0x300000 +#define bCCKCCACount 0x080000 +#define bCCKcs_lim 0x070000 +#define bCCKBistMode 0x80000000 +#define bCCKCCAMask 0x40000000 +#define bCCKTxDACPhase 0x4 +#define bCCKRxADCPhase 0x20000000 //r_rx_clk +#define bCCKr_cp_mode0 0x0100 +#define bCCKTxDCOffset 0xf0 +#define bCCKRxDCOffset 0xf +#define bCCKCCAMode 0xc000 +#define bCCKFalseCS_lim 0x3f00 +#define bCCKCS_ratio 0xc00000 +#define bCCKCorgBit_sel 0x300000 +#define bCCKPD_lim 0x0f0000 +#define bCCKNewCCA 0x80000000 +#define bCCKRxHPofIG 0x8000 +#define bCCKRxIG 0x7f00 +#define bCCKLNAPolarity 0x800000 +#define bCCKRx1stGain 0x7f0000 +#define bCCKRFExtend 0x20000000 //CCK Rx Iinital gain polarity +#define bCCKRxAGCSatLevel 0x1f000000 +#define bCCKRxAGCSatCount 0xe0 +#define bCCKRxRFSettle 0x1f //AGCsamp_dly +#define bCCKFixedRxAGC 0x8000 +//#define bCCKRxAGCFormat 0x4000 //remove to HSSI register 0x824 +#define bCCKAntennaPolarity 0x2000 +#define bCCKTxFilterType 0x0c00 +#define bCCKRxAGCReportType 0x0300 +#define bCCKRxDAGCEn 0x80000000 +#define bCCKRxDAGCPeriod 0x20000000 +#define bCCKRxDAGCSatLevel 0x1f000000 +#define bCCKTimingRecovery 0x800000 +#define bCCKTxC0 0x3f0000 +#define bCCKTxC1 0x3f000000 +#define bCCKTxC2 0x3f +#define bCCKTxC3 0x3f00 +#define bCCKTxC4 0x3f0000 +#define bCCKTxC5 0x3f000000 +#define bCCKTxC6 0x3f +#define bCCKTxC7 0x3f00 +#define bCCKDebugPort 0xff0000 +#define bCCKDACDebug 0x0f000000 +#define bCCKFalseAlarmEnable 0x8000 +#define bCCKFalseAlarmRead 0x4000 +#define bCCKTRSSI 0x7f +#define bCCKRxAGCReport 0xfe +#define bCCKRxReport_AntSel 0x80000000 +#define bCCKRxReport_MFOff 0x40000000 +#define bCCKRxRxReport_SQLoss 0x20000000 +#define bCCKRxReport_Pktloss 0x10000000 +#define bCCKRxReport_Lockedbit 0x08000000 +#define bCCKRxReport_RateError 0x04000000 +#define bCCKRxReport_RxRate 0x03000000 +#define bCCKRxFACounterLower 0xff +#define bCCKRxFACounterUpper 0xff000000 +#define bCCKRxHPAGCStart 0xe000 +#define bCCKRxHPAGCFinal 0x1c00 +#define bCCKRxFalseAlarmEnable 0x8000 +#define bCCKFACounterFreeze 0x4000 +#define bCCKTxPathSel 0x10000000 +#define bCCKDefaultRxPath 0xc000000 +#define bCCKOptionRxPath 0x3000000 + +// 5. PageC(0xC00) +#define bNumOfSTF 0x3 // Useless +#define bShift_L 0xc0 +#define bGI_TH 0xc +#define bRxPathA 0x1 +#define bRxPathB 0x2 +#define bRxPathC 0x4 +#define bRxPathD 0x8 +#define bTxPathA 0x1 +#define bTxPathB 0x2 +#define bTxPathC 0x4 +#define bTxPathD 0x8 +#define bTRSSIFreq 0x200 +#define bADCBackoff 0x3000 +#define bDFIRBackoff 0xc000 +#define bTRSSILatchPhase 0x10000 +#define bRxIDCOffset 0xff +#define bRxQDCOffset 0xff00 +#define bRxDFIRMode 0x1800000 +#define bRxDCNFType 0xe000000 +#define bRXIQImb_A 0x3ff +#define bRXIQImb_B 0xfc00 +#define bRXIQImb_C 0x3f0000 +#define bRXIQImb_D 0xffc00000 +#define bDC_dc_Notch 0x60000 +#define bRxNBINotch 0x1f000000 +#define bPD_TH 0xf +#define bPD_TH_Opt2 0xc000 +#define bPWED_TH 0x700 +#define bIfMF_Win_L 0x800 +#define bPD_Option 0x1000 +#define bMF_Win_L 0xe000 +#define bBW_Search_L 0x30000 +#define bwin_enh_L 0xc0000 +#define bBW_TH 0x700000 +#define bED_TH2 0x3800000 +#define bBW_option 0x4000000 +#define bRatio_TH 0x18000000 +#define bWindow_L 0xe0000000 +#define bSBD_Option 0x1 +#define bFrame_TH 0x1c +#define bFS_Option 0x60 +#define bDC_Slope_check 0x80 +#define bFGuard_Counter_DC_L 0xe00 +#define bFrame_Weight_Short 0x7000 +#define bSub_Tune 0xe00000 +#define bFrame_DC_Length 0xe000000 +#define bSBD_start_offset 0x30000000 +#define bFrame_TH_2 0x7 +#define bFrame_GI2_TH 0x38 +#define bGI2_Sync_en 0x40 +#define bSarch_Short_Early 0x300 +#define bSarch_Short_Late 0xc00 +#define bSarch_GI2_Late 0x70000 +#define bCFOAntSum 0x1 +#define bCFOAcc 0x2 +#define bCFOStartOffset 0xc +#define bCFOLookBack 0x70 +#define bCFOSumWeight 0x80 +#define bDAGCEnable 0x10000 +#define bTXIQImb_A 0x3ff +#define bTXIQImb_B 0xfc00 +#define bTXIQImb_C 0x3f0000 +#define bTXIQImb_D 0xffc00000 +#define bTxIDCOffset 0xff +#define bTxQDCOffset 0xff00 +#define bTxDFIRMode 0x10000 +#define bTxPesudoNoiseOn 0x4000000 +#define bTxPesudoNoise_A 0xff +#define bTxPesudoNoise_B 0xff00 +#define bTxPesudoNoise_C 0xff0000 +#define bTxPesudoNoise_D 0xff000000 +#define bCCADropOption 0x20000 +#define bCCADropThres 0xfff00000 +#define bEDCCA_H 0xf +#define bEDCCA_L 0xf0 +#define bLambda_ED 0x300 +#define bRxInitialGain 0x7f +#define bRxAntDivEn 0x80 +#define bRxAGCAddressForLNA 0x7f00 +#define bRxHighPowerFlow 0x8000 +#define bRxAGCFreezeThres 0xc0000 +#define bRxFreezeStep_AGC1 0x300000 +#define bRxFreezeStep_AGC2 0xc00000 +#define bRxFreezeStep_AGC3 0x3000000 +#define bRxFreezeStep_AGC0 0xc000000 +#define bRxRssi_Cmp_En 0x10000000 +#define bRxQuickAGCEn 0x20000000 +#define bRxAGCFreezeThresMode 0x40000000 +#define bRxOverFlowCheckType 0x80000000 +#define bRxAGCShift 0x7f +#define bTRSW_Tri_Only 0x80 +#define bPowerThres 0x300 +#define bRxAGCEn 0x1 +#define bRxAGCTogetherEn 0x2 +#define bRxAGCMin 0x4 +#define bRxHP_Ini 0x7 +#define bRxHP_TRLNA 0x70 +#define bRxHP_RSSI 0x700 +#define bRxHP_BBP1 0x7000 +#define bRxHP_BBP2 0x70000 +#define bRxHP_BBP3 0x700000 +#define bRSSI_H 0x7f0000 //the threshold for high power +#define bRSSI_Gen 0x7f000000 //the threshold for ant diversity +#define bRxSettle_TRSW 0x7 +#define bRxSettle_LNA 0x38 +#define bRxSettle_RSSI 0x1c0 +#define bRxSettle_BBP 0xe00 +#define bRxSettle_RxHP 0x7000 +#define bRxSettle_AntSW_RSSI 0x38000 +#define bRxSettle_AntSW 0xc0000 +#define bRxProcessTime_DAGC 0x300000 +#define bRxSettle_HSSI 0x400000 +#define bRxProcessTime_BBPPW 0x800000 +#define bRxAntennaPowerShift 0x3000000 +#define bRSSITableSelect 0xc000000 +#define bRxHP_Final 0x7000000 +#define bRxHTSettle_BBP 0x7 +#define bRxHTSettle_HSSI 0x8 +#define bRxHTSettle_RxHP 0x70 +#define bRxHTSettle_BBPPW 0x80 +#define bRxHTSettle_Idle 0x300 +#define bRxHTSettle_Reserved 0x1c00 +#define bRxHTRxHPEn 0x8000 +#define bRxHTAGCFreezeThres 0x30000 +#define bRxHTAGCTogetherEn 0x40000 +#define bRxHTAGCMin 0x80000 +#define bRxHTAGCEn 0x100000 +#define bRxHTDAGCEn 0x200000 +#define bRxHTRxHP_BBP 0x1c00000 +#define bRxHTRxHP_Final 0xe0000000 +#define bRxPWRatioTH 0x3 +#define bRxPWRatioEn 0x4 +#define bRxMFHold 0x3800 +#define bRxPD_Delay_TH1 0x38 +#define bRxPD_Delay_TH2 0x1c0 +#define bRxPD_DC_COUNT_MAX 0x600 +//#define bRxMF_Hold 0x3800 +#define bRxPD_Delay_TH 0x8000 +#define bRxProcess_Delay 0xf0000 +#define bRxSearchrange_GI2_Early 0x700000 +#define bRxFrame_Guard_Counter_L 0x3800000 +#define bRxSGI_Guard_L 0xc000000 +#define bRxSGI_Search_L 0x30000000 +#define bRxSGI_TH 0xc0000000 +#define bDFSCnt0 0xff +#define bDFSCnt1 0xff00 +#define bDFSFlag 0xf0000 +#define bMFWeightSum 0x300000 +#define bMinIdxTH 0x7f000000 +#define bDAFormat 0x40000 +#define bTxChEmuEnable 0x01000000 +#define bTRSWIsolation_A 0x7f +#define bTRSWIsolation_B 0x7f00 +#define bTRSWIsolation_C 0x7f0000 +#define bTRSWIsolation_D 0x7f000000 +#define bExtLNAGain 0x7c00 + +// 6. PageE(0xE00) +#define bSTBCEn 0x4 // Useless +#define bAntennaMapping 0x10 +#define bNss 0x20 +#define bCFOAntSumD 0x200 +#define bPHYCounterReset 0x8000000 +#define bCFOReportGet 0x4000000 +#define bOFDMContinueTx 0x10000000 +#define bOFDMSingleCarrier 0x20000000 +#define bOFDMSingleTone 0x40000000 +//#define bRxPath1 0x01 +//#define bRxPath2 0x02 +//#define bRxPath3 0x04 +//#define bRxPath4 0x08 +//#define bTxPath1 0x10 +//#define bTxPath2 0x20 +#define bHTDetect 0x100 +#define bCFOEn 0x10000 +#define bCFOValue 0xfff00000 +#define bSigTone_Re 0x3f +#define bSigTone_Im 0x7f00 +#define bCounter_CCA 0xffff +#define bCounter_ParityFail 0xffff0000 +#define bCounter_RateIllegal 0xffff +#define bCounter_CRC8Fail 0xffff0000 +#define bCounter_MCSNoSupport 0xffff +#define bCounter_FastSync 0xffff +#define bShortCFO 0xfff +#define bShortCFOTLength 12 //total +#define bShortCFOFLength 11 //fraction +#define bLongCFO 0x7ff +#define bLongCFOTLength 11 +#define bLongCFOFLength 11 +#define bTailCFO 0x1fff +#define bTailCFOTLength 13 +#define bTailCFOFLength 12 +#define bmax_en_pwdB 0xffff +#define bCC_power_dB 0xffff0000 +#define bnoise_pwdB 0xffff +#define bPowerMeasTLength 10 +#define bPowerMeasFLength 3 +#define bRx_HT_BW 0x1 +#define bRxSC 0x6 +#define bRx_HT 0x8 +#define bNB_intf_det_on 0x1 +#define bIntf_win_len_cfg 0x30 +#define bNB_Intf_TH_cfg 0x1c0 +#define bRFGain 0x3f +#define bTableSel 0x40 +#define bTRSW 0x80 +#define bRxSNR_A 0xff +#define bRxSNR_B 0xff00 +#define bRxSNR_C 0xff0000 +#define bRxSNR_D 0xff000000 +#define bSNREVMTLength 8 +#define bSNREVMFLength 1 +#define bCSI1st 0xff +#define bCSI2nd 0xff00 +#define bRxEVM1st 0xff0000 +#define bRxEVM2nd 0xff000000 +#define bSIGEVM 0xff +#define bPWDB 0xff00 +#define bSGIEN 0x10000 + +#define bSFactorQAM1 0xf // Useless +#define bSFactorQAM2 0xf0 +#define bSFactorQAM3 0xf00 +#define bSFactorQAM4 0xf000 +#define bSFactorQAM5 0xf0000 +#define bSFactorQAM6 0xf0000 +#define bSFactorQAM7 0xf00000 +#define bSFactorQAM8 0xf000000 +#define bSFactorQAM9 0xf0000000 +#define bCSIScheme 0x100000 + +#define bNoiseLvlTopSet 0x3 // Useless +#define bChSmooth 0x4 +#define bChSmoothCfg1 0x38 +#define bChSmoothCfg2 0x1c0 +#define bChSmoothCfg3 0xe00 +#define bChSmoothCfg4 0x7000 +#define bMRCMode 0x800000 +#define bTHEVMCfg 0x7000000 + +#define bLoopFitType 0x1 // Useless +#define bUpdCFO 0x40 +#define bUpdCFOOffData 0x80 +#define bAdvUpdCFO 0x100 +#define bAdvTimeCtrl 0x800 +#define bUpdClko 0x1000 +#define bFC 0x6000 +#define bTrackingMode 0x8000 +#define bPhCmpEnable 0x10000 +#define bUpdClkoLTF 0x20000 +#define bComChCFO 0x40000 +#define bCSIEstiMode 0x80000 +#define bAdvUpdEqz 0x100000 +#define bUChCfg 0x7000000 +#define bUpdEqz 0x8000000 + +//Rx Pseduo noise +#define bRxPesudoNoiseOn 0x20000000 // Useless +#define bRxPesudoNoise_A 0xff +#define bRxPesudoNoise_B 0xff00 +#define bRxPesudoNoise_C 0xff0000 +#define bRxPesudoNoise_D 0xff000000 +#define bPesudoNoiseState_A 0xffff +#define bPesudoNoiseState_B 0xffff0000 +#define bPesudoNoiseState_C 0xffff +#define bPesudoNoiseState_D 0xffff0000 + +//7. RF Register +//Zebra1 +#define bZebra1_HSSIEnable 0x8 // Useless +#define bZebra1_TRxControl 0xc00 +#define bZebra1_TRxGainSetting 0x07f +#define bZebra1_RxCorner 0xc00 +#define bZebra1_TxChargePump 0x38 +#define bZebra1_RxChargePump 0x7 +#define bZebra1_ChannelNum 0xf80 +#define bZebra1_TxLPFBW 0x400 +#define bZebra1_RxLPFBW 0x600 + +//Zebra4 +#define bRTL8256RegModeCtrl1 0x100 // Useless +#define bRTL8256RegModeCtrl0 0x40 +#define bRTL8256_TxLPFBW 0x18 +#define bRTL8256_RxLPFBW 0x600 + +//RTL8258 +#define bRTL8258_TxLPFBW 0xc // Useless +#define bRTL8258_RxLPFBW 0xc00 +#define bRTL8258_RSSILPFBW 0xc0 + + +// +// Other Definition +// + +//byte endable for sb_write +#define bByte0 0x1 // Useless +#define bByte1 0x2 +#define bByte2 0x4 +#define bByte3 0x8 +#define bWord0 0x3 +#define bWord1 0xc +#define bDWord 0xf + +//for PutRegsetting & GetRegSetting BitMask +#define bMaskByte0 0xff // Reg 0xc50 rOFDM0_XAAGCCore~0xC6f +#define bMaskByte1 0xff00 +#define bMaskByte2 0xff0000 +#define bMaskByte3 0xff000000 +#define bMaskHWord 0xffff0000 +#define bMaskLWord 0x0000ffff +#define bMaskDWord 0xffffffff +#define bMask12Bits 0xfff +#define bMaskH4Bits 0xf0000000 +#define bMaskH3Bytes 0xffffff00 +#define bMaskOFDM_D 0xffc00000 +#define bMaskCCK 0x3f3f3f3f + +//for PutRFRegsetting & GetRFRegSetting BitMask +//#define bMask12Bits 0xfffff // RF Reg mask bits +//#define bMask20Bits 0xfffff // RF Reg mask bits T65 RF +#define bRFRegOffsetMask 0xfffff + +//#define bEnable 0x1 // Useless +//#define bDisable 0x0 + +#define LeftAntenna 0x0 // Useless +#define RightAntenna 0x1 + +#define tCheckTxStatus 500 //500ms // Useless +#define tUpdateRxCounter 100 //100ms + +#define rateCCK 0 // Useless +#define rateOFDM 1 +#define rateHT 2 + +//define Register-End +#define bPMAC_End 0x1ff // Useless +#define bFPGAPHY0_End 0x8ff +#define bFPGAPHY1_End 0x9ff +#define bCCKPHY0_End 0xaff +#define bOFDMPHY0_End 0xcff +#define bOFDMPHY1_End 0xdff + +//define max debug item in each debug page +//#define bMaxItem_FPGA_PHY0 0x9 +//#define bMaxItem_FPGA_PHY1 0x3 +//#define bMaxItem_PHY_11B 0x16 +//#define bMaxItem_OFDM_PHY0 0x29 +//#define bMaxItem_OFDM_PHY1 0x0 + +#define bPMACControl 0x0 // Useless +#define bWMACControl 0x1 +#define bWNICControl 0x2 + +#define PathA 0x0 // Useless +#define PathB 0x1 +#define PathC 0x2 +#define PathD 0x3 + +/*--------------------------Define Parameters-------------------------------*/ +#endif + +#endif //#ifndef WLAN_HAL_INTERNAL_USED + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192c_reg.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192c_reg.h new file mode 100755 index 000000000..84117b41f --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192c_reg.h @@ -0,0 +1,2484 @@ +/* + * Header file of 8192C register + * + * $Id: 8192c_reg.h,v 1.7.2.2 2010/09/20 09:00:10 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192C_REG_H_ +#define _8192C_REG_H_ + +#ifndef WLAN_HAL_INTERNAL_USED + + +//============================================================ +// 8192C Regsiter offset definition +//============================================================ + + +// +// MAC register 0x000 - 0x6AFh +// 1. System Configure Register. (Offset 0x000 - 0x0FFh) +// 2. MACTOP General Configuration. (Offset 0x100 - 0x1FFh) +// General Purpose Timer. (Offset 0x150 - 0x16Fh) +// 3. TXDMA/RXDMA Configuration. (Offset 0x200 - 0x2FFh) +// 4. PCIE EMAC Reserved Region. (Offset 0x300 - 0x3FFh) +// 5. PTCL/EDCA Configuration. (Offset 0x400 - 0x4FFh) +// 6. WMAC Configuration. (Offset 0x600 - 0x7FFh) +// MACID Setting Register. (Offset 0x610 - 0x62Fh) +// Timing Control Register. (Offset 0x630 - 0x64Fh) +// WMAC, BA, CCX Related Register. (Offset 0x650 - 0x66Fh) +// Security Control Register. (Offset 0x670 - 0x68Fh) +// Power Save Control Register. (Offset 0x690 - 0x69Fh) +// General Purpose Register. (Offset 0x6A0 - 0x6AFh) +// + + +// +// 1. System Configure Register. (Offset 0x000 - 0x0FFh) +// +#define SYS_ISO_CTRL 0x000 // System Isolation Interface Control. +#define SYS_FUNC_EN 0x002 // System Function Enable. +#define APS_FSMCO 0x004 // Auto Power Sequence Control/Option. +#define SYS_CLKR 0x008 // System Clock. +#define CR9346 0x00A // 93C46 (93C56) Command. +#define EE_VPD 0x00C // EEPROM VPD Data. +#define AFE_MISC 0x010 // AFE Misc. +#define SPS0_CTRL 0x011 // Switching Power Supply 0 Control. +#define SPS_OCP_CFG 0x018 // SPS Over Current Protection Configuration. +#define RSV_CTRL0 0x01C // Reserved Control. +#define RF_CTRL 0x01F // RF Block Control. +#define LDOA15_CTRL 0x020 // V15 Digital LDO Control. +#define LDOV12D_CTRL 0x021 // V12 Digital LDO Control. +#define LDOHCI12_CTRL 0x022 // V12 Digital LDO Control. +#define LPLDO_CTRL 0x023 // Low Power LDO Control. +#define AFE_XTAL_CTRL 0x024 // AFE Crystal Control. +#define AFE_PLL_CTRL 0x028 // AFE_PLL_CTRL Enable. +#define RSV_CTRL1 0x02C // Reserved Control. +#define EFUSE_CTRL 0x030 // E-Fuse Control. +#define EFUSE_TEST 0x034 // E-Fuse Test Control. +#define PWR_DATA 0x038 // Power on Data. +#define CAL_TIMER 0x03C // Hardware Calibration Timer. +#define ACLK_MON 0x03E // Analog Clock Monitor. +#define GPIO_MUXCFG 0x040 // GPIO_MUX Configuration. +#define GPIO_PIN_CTRL 0x044 // GPIO[7:0] PIN Control. +#define GPIO_INTM 0x048 // GPIO Interrupt Monitor Register. +#define LEDCFG 0x04C // System PINMUX Configuration. +#define FSIMR 0x050 // Firmware System Interrupt Mask. +#define FSISR 0x054 // Firmware System Interrupt Status. + +#define MCUFWDL 0x080 // MCU Firmware Down Load Control. +#define MCUTSTCFG 0x084 // MCU Firmware Test Configuration. +#define MCUDMSG_I 0x088 // MCU Firmware Debug Message. +#define MCUDMSG_II 0x08C // MCU Firmware Debug Message. + +#define BIST_CTRL 0x0D0 // BIST/SCAN CONTROL +#define C_BIST_RPT 0x0D4 // BIST Report +#define BIST_ROM_RPT 0x0D8 // BIST ROM Report +#define USB_SIE_INTF 0x0E0 // USB SIE Access Interface +#define PCIE_MIO_INTF 0x0E4 // PCIE MIO Access Interface +#define PCIE_MIO_INTD 0x0E8 // PCIE MIO Access Interface DATA. +#define HPON_FSM 0x0EC // Power On FSM Monitor/Control. +#define SYS_CFG 0x0F0 // System Configuration Status + + +// +// 2. MACTOP General Configuration. (Offset 0x100 - 0x1FFh) +// +#define CR 0x100 // Command Register. +#define PBP 0x104 // Packet Buffer Page. +#define TRXDMA_CTRL 0x10C // TRXDMA Control. +#define TRXFF_BNDY 0x114 // TX/RX FIFO Boundary +#define TRXFF_STATUS 0x118 // PKTFF Status +#define RXFF_PTR 0x11C // RXFF Write/Read Pointer +#define HIMR 0x120 // Host Interrupt Mask. +#define HISR 0x124 // Host Interrupt Status. +#define HIMRE 0x128 // Host Interrupt Mask Extension. +#define HISRE 0x12C // Host Interrupt Status Extension. +#define CPWM 0x12F // Current Power Mode. +#define FWIMR 0x130 // Firmware WLAN Interrupt Mask. +#define FWISR 0x134 // Firmware WLAN Interrupt Status. +#define FTIMR 0x138 // Firmware Timer Interrupt Mask. +#define FTISR 0x13C // Firmware Timer Interrupt Status. +#define PKTBUF_DBG_CTRL 0x140 // TX/RX Packet Buffer Debug Control. +#define PKTBUF_DBG_DATA_L 0x144 // TX/RX Packet Buffer Debug Data. +#define PKTBUF_DBG_DATA_H 0x148 // TX/RX Packet Buffer Debug Data. +// General Purpose Timer. (Offset 0x150 - 0x16Fh) +#define TC0_CTRL 0x150 // Timer/Counter 0 Control. +#define TC1_CTRL 0x154 // Timer/Counter 1 Control. +#define TC2_CTRL 0x158 // Timer/Counter 2 Control. +#define TC3_CTRL 0x15C // Timer/Counter 3 Control. +#define TC4_CTRL 0x160 // Timer/Counter 4 Control. +#define TCUNIT_BASE 0x164 // Timer/Counter Unit Base. +// General Purpose Timer. (Offset 0x150 - 0x16Fh) +#define MBIST_START 0x174 // MACTOP BIST START Pulse. +#define MBIST_DONE 0x178 // MACTOP BIST DONE. +#define MBIST_FAIL 0x17C // MACTOP BIST FAIL. + +#define C2H_SYNC_BYTE 0x1AF // 8051 set to 0xFF, Driver set to 0x0 after read C2H content +#define MCUTST_I 0x1C0 // MCU Firmware TST-I. +#define MCUTST_II 0x1C4 // MCU Firmware TST-II. +#define MCU_UNLOCK 0x01C7 // is used for Unlock MCU infinite-loop +#define FMETHR 0x1C8 // Firmware Message Exchange to Host. +#define HMETFR 0x1CC // Host Message Interrupt to Firmware. +#define HMEBOX_0 0x1D0 // Host Message BOX_0 to Firmware. +#define HMEBOX_1 0x1D4 // Host Message BOX_1 to Firmware. +#define HMEBOX_2 0x1D8 // Host Message BOX_2 to Firmware. +#define HMEBOX_3 0x1DC // Host Message BOX_3 to Firmware. +#define LLT_INI 0x1E0 // LLT Entries Initial Indirect Access Control. +#define BB_ACCEESS_CTRL 0x1E8 // BB Indirect Access Control. +#define BB_ACCESS_DATA 0x1EC // BaseBand Indirect Access Data. +#define MREG_HCIDBG 0x1F0 // MAC REG for HCI debug. +#define MREG_CPUDBG 0x1F4 // MAC REG for CPU debug. + + +// +// 3. TXDMA/RXDMA Configuration. (Offset 0x200 - 0x2FFh) +// +#define RQPN 0x200 // Reserved Queue Page Number. +#define FIFOPAGE 0x204 // Available FIFO Page Number. +#define TDECTRL 0x208 // Tx DMA Engine Control. +#define TXDMA_OFFSET_CHK 0x20C // TXDMA Offset Check. +#define TXDMA_STATUS 0x210 // TXDMA Status. +#define RQPN_NPQ 0x214 // RQPN for Normal Queue Register + +#define RXDMA_AGG_PG_TH 0x280 // RXDMA AGG PG Threshold. +#define RXPKT_NUM 0x284 // RX Packet Number. +#define RXDMA_STATUS 0x288 // RXDMA Status. + + +// +// 4. PCIE EMAC Reserved Region. (Offset 0x300 - 0x3FFh) +// +#define PCIE_CTRL_REG 0x300 // PCIE DMA Control. +#define INT_MIG 0x304 // Interrupt Migration. +#define BCNQ_DESA 0x308 // TX Beacon Descriptor Address. +#define HQ_DESA 0x310 // TX High Queue Descriptor. +#define MGQ_DESA 0x318 // TX Manage Queue Descriptor Address. +#define VOQ_DESA 0x320 // TX VO Queue Descriptor Address. +#define VIQ_DESA 0x328 // TX VI Queue Descriptor Address. +#define BEQ_DESA 0x330 // TX BE Queue Descriptor Address. +#define BKQ_DESA 0x338 // TX BK Queue Descriptor Address. +#define RX_DESA 0x340 // RX Queue Descriptor Address. +#define DBI 0x348 // Backdoor REG for Access Configuration SPACE. +#define MDIO 0x354 // MDIO for Access PCIE PHY. +#define DBG_SEL 0x360 // Debug Selection +#define UART_CTRL 0x364 // UART Control. +#define UART_TX_DESA 0x370 // UART TX Descriptor Address. +#define UART_RX_DESA 0x378 // UART RX Descriptor Address. + + +// +// 5. PTCL/EDCA Configuration. (Offset 0x400 - 0x4FFh) +// +#define VOQ_INFO 0x400 // +#define VIQ_INFO 0x404 // +#define BEQ_INFO 0x408 // +#define BKQ_INFO 0x40C // +#define MGQ_INFO 0x410 // +#define HIQ_INFO 0x414 // +#define BCNQ_INFO 0x418 // +#define TXPKT_EMPTY 0x41B // TXPKTBUF Packet Empty. +#define CPU_MGQ_INFO 0x41C // TXPKTBUF Packet Empty. +#define FWHW_TXQ_CTRL 0x420 // FWHW TX Queue Control. +#define HWSEQ_CTRL 0x423 // HW Sequence Number Control. +#define TXPKTBUF_BCNQ_BDNY 0x424 // BCNQ Boundary. +#define TXPKTBUF_MGQ_BDNY 0x425 // MGQ Boundary. +#define MULTI_BCNQ_EN 0x426 // +#define MULTI_BCNQ_OFFSET 0x427 // +#define SPEC_SIFS_A 0x428 // +#define RL 0x42A // +#define DARFRC 0x430 // Data Auto Rate Fallback Retry Count. +#define RARFRC 0x438 // Response Auto Rate Fallback Retry Count. +#define RRSR 0x440 // Response Rate Set. +#define ARFR0 0x444 // Data Auto Rate Fallback 0. +#define ARFR1 0x448 // Auto Rate Fallback 1. +#define ARFR2 0x44C // Auto Rate Fallback 2. +#define ARFR3 0x450 // Auto Rate Fallback 3. +#define AGGLEN_LMT 0x458 // Aggregation Length. +#define AMPDU_MIN_SPACE 0x45C // AMPDU Min Space. +#define TXPKTBUF_WMAC_LBK_BF_HD 0x45D // LBK Buffer Head Page +#define FAST_EDCA_CTRL 0x460 // Fast EDCA Mode. +#define RD_RESP_PKT_TH 0x463 // RD Responder Packet Threshold. +#define INIRTS_RATE_SEL 0x480 // Initial RTS Rate SEL. +#define INIDATA_RATE_SEL 0x484 // Initial Data Rate SEL. +#define POWER_STATUS 0x4A4 // POWER STATUS. +#define POWER_STAGE1 0x4B4 // POWER STAGE1. +#define POWER_STAGE2 0x4B8 // POWER STAGE2.---------------??? +#define PKT_LIFE_TIME 0x4C0 // PKT LIFT TIME. +#define STBC_SETTING 0x4C4 // STBC. +#define PROT_MODE_CTRL 0x4C8 // PROTECT MODE Control. +#define BAR_MODE_CTRL 0x4CC // BAR MODE Control. +#define RA_TRY_RATE_AGG_LMT 0x4CF // Rate Adaptive Try Rate Aggregation Limit. +#define NQOS_SEQ 0x4DC // Non-QoS SEQ Number. +#define QOS_SEQ 0x4DE // QoS SEQ Number. +#define NEED_CPU_HANDLE 0x4E0 // Need CPU Handle. +#define PTCL_ERR_STATUS 0x4E1 // Protocol Function Error Status. +#define PKT_LOSE_RPT 0x4E2 // PKT Lose Report. +#define Dummy 0x4FC // Dummy. + +#define EDCA_VO_PARA 0x500 // EDCA Parameter. +#define EDCA_VI_PARA 0x504 // EDCA Parameter. +#define EDCA_BE_PARA 0x508 // EDCA Parameter. +#define EDCA_BK_PARA 0x50C // EDCA Parameter. +#define BCNTCFG 0x510 // Beacon Time Configuration. +#define PIFS 0x512 // PIFS. +#define RDG_PIFS 0x513 // RDG PIFS. +#define SIFS_CCK 0x514 // SIFS for CCK. +#define SIFS_OFDM 0x516 // SIFS for OFDM. +#define AGGR_BK_TIME 0x51A // AGGR BREAK TIME. +#define SLOT_TIME 0x51B // Slot Time. +#define TX_PTCL_CTRL 0x520 // TX Protocol Control. +#define TXPAUSE 0x522 // Transmission Pause. +#define DIS_TXREQ_CLR 0x523 // Disable TX Request Clear Function. +#define RD_CTRL 0x524 // RD Control. +#define REG_MBSSID_CTRL 0x526 // MBSSID Control. + +#define TBTT_PROHIBIT 0x540 // TBTT Prohibit. +#define RD_NAV_NXT 0x544 // RD NAV Protect Next Time. +#define NAV_PROT_LEN 0x546 // NAV Protection Length. +#define BCN_CTRL 0x550 // Bcnq Control. +#define BCN_CTRL1 0x551 +#define USTIME_TSF 0x551 // US Time Tuning for TSF. +#define MBID_NUM 0x552 // MBSSID Beacon Number. +#define DUAL_TSF_RST 0x553 +#define MBSSID_BCN_SPACE 0x554 // MBSSID Beacon Space. +#define DRVERLYINT 0x558 // Beacon Driver Early Interrupt. +#define BCNDMATIM 0x559 // BCN DMA and ATIM INT Time.-----------------??? +#define ATIMWND 0x55A // ATIM Window Time. +#define BCN_MAX_ERR 0x55D // BCN MAX ERROR. +#define RXTSF_OFFSET_CCK 0x55E // CCK BCN OFFSET. +#define RXTSF_OFFSET_OFDM 0x55F // OFDM BCN OFFSET. +#define TSFTR 0x560 // TSF Timer. +#define INIT_TSFTR 0x564 // TSF Timer Initial Value. +#define PSTIMER 0x580 // PS TIMER and Timeout INT. +#define TIMER0 0x584 // TIMER0 INT. +#define TIMER1 0x588 // TIMER1 INT. +#define ACMHWCTRL 0x5C0 // ACM HW Control. +#define ACMRSTCTRL 0x5C1 // ACM RST. +#define ACMAVG 0x5C2 // ACM Average. +#define VO_ADMTIME 0x5C4 // VO Admission Time. +#define VI_ADMTIME 0x5C6 // VI Admission Time. +#define BE_ADMTIME 0x5C8 // BE Admission Time. +#define EDCA_RANDOM_GEN 0x5CC // EDCA Random Number Generator. +#define C_SCH_TXCMD 0x5D0 // TX_CMD. +#define NOA_PARAM 0x5E0 // P2P NoA Parameter + + +// +// 6. WMAC Configuration. (Offset 0x600 - 0x7FFh) +// +#define APSD_CTRL 0x600 // APSD Control. +#define BWOPMODE 0x603 // BW Operation Mode. +#define TCR 0x604 // Transmission Configuration. +#define RCR 0x608 // Receive Configuration. +#define RX_PKT_LIMIT 0x60C // RX Packet Length Limit. +#define RX_DLK_TIME 0x60D // RX Deadlock Time. +#define RX_DRVINFO_SZ 0x60F // RX Driver INFO Size Register. +// MACID Setting Register. (Offset 0x610 - 0x62Fh) +#define MACID 0x610 // MAC ID. +#define BSSIDR 0x618 // BSSID. +#define MAR 0x620 // Multicast Address. +#define MBIDCAMCFG 0x628 // MBSSID CAM Configuration. +// MACID Setting Register. (Offset 0x610 - 0x62Fh) + +// Timing Control Register. (Offset 0x630 - 0x64Fh) +#define USTIME_EDCA 0x638 // US Time Tuning for EDCA. +#define SPEC_SIFS_B 0x63A // Specification SIFS. +#define RESP_SIFS_CCK 0x63C // Response SIFS for CCK. +#define RESP_SIFS_OFDM 0x63E // Response SIFS for OFDM. +#define ACKTO 0x640 // ACK Timeout. +#define CTS2TO 0x641 // CTS2 Timeout. +#define EIFS 0x642 // EIFS. +// Timing Control Register. (Offset 0x630 - 0x64Fh) + +// WMAC, BA, CCX Related Register. (Offset 0x650 - 0x66Fh) +#define NAV_CTRL 0x650 // NAV Control. +#define BACAMCMD 0x654 // Block ACK CAM Command. +#define BACAMCONTENT 0x658 // Block ACK CAM Content. +#define LBDLY 0x660 // Loopback Delay. +#define FWDLY 0x661 // FW Delay. +#define RXERR_RPT 0x664 // RX Error Report. +#define WMAC_TRXPTCL_CTL 0x668 // WMAC TX/RX Protocol Control. +// WMAC, BA, CCX Related Register. (Offset 0x650 - 0x66Fh) + +// Security Control Register. (Offset 0x670 - 0x68Fh) +#define CAMCMD 0x670 // CAM Command. +#define CAMWRITE 0x674 // CAM Write. +#define CAMREAD 0x678 // CAM Read. +#define CAMDBG 0x67C // CAM Debug. +#define SECCFG 0x680 // Security Configuration. +// Security Control Register. (Offset 0x670 - 0x68Fh) + +// Power Save Control Register. (Offset 0x690 - 0x69Fh) +#define WOW_CTRL 0x690 // Wake On WLAN Control. +#define PSSTATUS 0x691 // Power Save Status. +#define PS_RX_INFO 0x692 // Power Save RX Information. +#define LPNAV_CTRL 0x694 // Low Power NAV Control. +#define WKFMCAM_CMD 0x698 // Wakeup Frame CAM Command. +#define WKFMCAM_RWD 0x69C // Wakeup Frame Read/Write Data. +// Power Save Control Register. (Offset 0x690 - 0x69Fh) + +// General Purpose Register. (Offset 0x6A0 - 0x6AFh) +#define RXFLTMAP0 0x6A0 // RX Filter Map Group 0. +#define RXFLTMAP1 0x6A2 // RX Filter Map Group 1. +#define RXFLTMAP2 0x6A4 // RX Filter Map Group 2. +#define BCN_PSR_RPT 0x6A8 // Beacon Parser Report. +#define CALB32K_CTRL 0x6AC // Calibration 32K Control. +// General Purpose Register. (Offset 0x6A0 - 0x6AFh) +#define PKT_MON_CTRL 0x6B4 // Packet Monitor Control. +#define BT_COEX_TABLE 0x6C0 // BT-Coexistence Control. +#define WMAC_RESP_TXINFO 0x6D8 // Response TXINFO. + +#define MACID1 0x700 // MAC ID1 Register (Offset 0700h~0705h) +#define BSSIDR1 0x708 + +//----------------------------------------------------- +// +// 0xFE00h ~ 0xFE55h USB Configuration +// +//----------------------------------------------------- +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_USB_VID 0xFE60 +#define REG_USB_PID 0xFE62 +#define REG_USB_OPTIONAL 0xFE64 +#define REG_USB_CHIRP_K 0xFE65 +#define REG_USB_PHY 0xFE66 +#define REG_USB_MAC_ADDR 0xFE70 + +#define REG_USB_HRPWM 0xFE58 +#define REG_USB_HCPWM 0xFE57 + +// For test chip +#define REG_TEST_USB_TXQS 0xFE48 +#define REG_TEST_SIE_VID 0xFE60 // 0xFE60~0xFE61 +#define REG_TEST_SIE_PID 0xFE62 // 0xFE62~0xFE63 +#define REG_TEST_SIE_OPTIONAL 0xFE64 +#define REG_TEST_SIE_CHIRP_K 0xFE65 +#define REG_TEST_SIE_PHY 0xFE66 // 0xFE66~0xFE6B +#define REG_TEST_SIE_MAC_ADDR 0xFE70 // 0xFE70~0xFE75 +#define REG_TEST_SIE_STRING 0xFE80 // 0xFE80~0xFEB9 + + +// For normal chip +#define REG_NORMAL_SIE_VID 0xFE60 // 0xFE60~0xFE61 +#define REG_NORMAL_SIE_PID 0xFE62 // 0xFE62~0xFE63 +#define REG_NORMAL_SIE_OPTIONAL 0xFE64 +#define REG_NORMAL_SIE_EP 0xFE65 // 0xFE65~0xFE67 +#define REG_NORMAL_SIE_PHY 0xFE68 // 0xFE68~0xFE6B +#define REG_NORMAL_SIE_OPTIONAL2 0xFE6C +#define REG_NORMAL_SIE_GPS_EP 0xFE6D // 0xFE6D, for RTL8723 only. +#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 // 0xFE70~0xFE75 +#define REG_NORMAL_SIE_STRING 0xFE80 // 0xFE80~0xFEDF + + + +//============================================================================ +// 8192C Regsiter Bit and Content definition +//============================================================================ + + +// +// 1. System Configure Register. (Offset 0x000 - 0x0FFh) +// +//---------------------------------------------------------------------------- +// 8192C SYS_ISO_CTRL bits (Offset 0x0, 16bit) +//---------------------------------------------------------------------------- +#define PWC_EV12V BIT(15) // Power Cut for eFuse 1.2V, 1: Power valid; 0: Power invalid. +#define PWC_EV25V BIT(14) // Power Cut for eFuse 2.5V, 1: force PSW open; 0: PSW turn on by efuse ctrl. +#define ISO_DIOR BIT(9) // RF Digital I/O to Power On, 1: isolation; 0: attach. +#define ISO_EB2CORE BIT(8) // eFuse cell output to Power On, 1: isolation; 0: attach. +#define ISO_DIOE BIT(7) // Extra Digital I/O to Power On, 1: isolation; 0: attach. +#define ISO_DIOP BIT(6) // PCIe Digital I/O to Power On, 1: isolation; 0: attach. +#define ISO_IP2MAC BIT(5) // Analog Ips to Digital 1.2V, 1: isolation; 0: attach (no used). +#define ISO_PD2CORE BIT(4) // PCIe Digital 1.2V to Power On/Core 1.2V, 1: isolation; 0: attach. +#define ISO_PA2PCIE BIT(3) // PCIe Analog 1.2V to PCIe 3.3V and Digital 1.2V, 1: isolation; 0: attach. +#define ISO_UD2CORE BIT(2) // USB Digital 1.2V to Power On/Core 1.2V, 1: isolation; 0: attach. +#define ISO_UA2USB BIT(1) // USB Analog 1.2V to USB 3.3V and Digital 1.2V, 1: isolation; 0: attach. +#define ISO_MD2PP BIT(0) // MACTOP/BB/PCIe Digital to Power On, 1: isolation; 0: attach. + +//---------------------------------------------------------------------------- +// 8192C SYS_FUNC_EN bits (Offset 0x2, 16bit) +//---------------------------------------------------------------------------- +#define FEN_MREGEN BIT(15) // MAC I/O Registers Enable. +#define FEN_HWPDN BIT(14) // 0 : force All analog blocks shutdown, 1 : keep Analog Blocks alive. +#define FEN_DIO_RF BIT(13) // Enable RF Digital I/O. +#define FEN_ELDR BIT(12) // Enable EEPROM Loader (Loader POR). +#define FEN_DCORE BIT(11) // enable Core Digital (MACTOP POR). +#define FEN_CPUEN BIT(10) // Enable MCU Core (CPU RST). +#define FEN_DIOE BIT(9) // Extra Debug I/O PAD Enable. +#define FEN_PCIED BIT(8) // enable PCIe eMAC. +#define FEN_PPLL BIT(7) // Enable PCIe PHY_PLL (no used). +#define FEN_PCIEA BIT(6) // Enable PCIe PHY. +#define FEN_DIO_PCIE BIT(5) // Enable PCIe Digital I/O (no used). +#define FEN_USBD BIT(4) // Enable USB_SIE. +#define FEN_UPLL BIT(3) // Enable USB PHY_PLL (no used). +#define FEN_USBA BIT(2) // Enable USB PHY. +#define FEN_BB_GLB_RST BIT(1) // When this bit is set to "0", whole BB is reset. When this bit is set, BB is enabled. +#define FEN_BBRSTB BIT(0) // When this bit is set to "0", CCK and OFDM are disabled, + // and clock are gated. Otherwise, CCK and OFDM are enabled. + +//---------------------------------------------------------------------------- +// 8192C APS_FSMCO bits (Offset 0x4, 32bit) +//---------------------------------------------------------------------------- +#define XOP_BTCK BIT(31) // BT Option for never turn off XTAL & SPS. +#define SOP_A8M BIT(30) // Suspend option not to turn analog Clock Mode to 500K Hz, 1: keep 8M, 0: 500K. +#define SOP_RCK BIT(29) // Suspend option not to turn off Hreg Clock (8M/500KHz), 1: clock on, 0: clock off. +#define SOP_AMB BIT(28) // Suspend option not to turn off AFE MB, 1: MB on, 0: MB off. +#define SOP_ABG BIT(27) // Suspend option not to turn off AFE BG, 1: BG on, 0: BG off. +#define SOP_FUSE BIT(26) // Suspend option to turn off Efuse Power or reset Loader, 1: Fuse Pwr Off, 0: Fuse Pwr On. +#define SOP_MRST BIT(25) // Suspend option not to turn off MAC Reset, 1: MAC not reset, 0: MaC reset. +#define SOP_CRST BIT(24) // Susoend option not to turn off 8051 clock, 1: 8051 clock on, 0:8051 clock off. +#define ROP_SPS BIT(22) // Resume option to skip turn On SPS. +#define ROP_PWR BIT(21) // Resume option to skip wait Power Ready, 1: pwr up no delay, 0: wait pwr stable. +#define ROP_ALD BIT(20) // Resume option to skip autoload, 1: not autoload, 0: autoload. +#define OP_SWRST BIT(19) // Option for Software Reset to Reset 8051. +#define SUS_HOST BIT(17) // Power FSM turn to HOST SUS. +#define RDY_MACON BIT(16) // Power FSM turn all power, clock ready for MAC. +#define APDM_HPDN BIT(15) // Auto Power Down to CHIP-off State (Power-Down). +#define APDM_HOST BIT(14) // Auto Power Down to HOST-off State (Card-Disable). +#define APDM_MAC BIT(13) // Auto Power Down to WLAN-Off State (Radio-off). +#define AFSM_PCIE BIT(12) // When this bit is set, PCIE suspends via HW FSM control flow. +#define AFSM_HSUS BIT(11) // 1: Host Suspend through FSM operation; 0: Host Suspend by gated. +#define APFM_RSM BIT(10) // Auto Power On State Machine Resume, auto clear when EE load done. +#define APFM_OFF BIT(9) // Auto FSM to Turn Off, include clock, isolation, power control. +#define APFM_ONMAC BIT(8) // Auto FSM to Turn On, include clock, isolation, power control for MAC only. +#define BT_SUSEN BIT(7) // Enable BT suspend control. +#define RDY_MACDIS BIT(6) // Disable MAC power Ready Output for Test Mode. +#define PDN_PL BIT(5) // PDn polarity control, 0: Low active, 1: High active. +#define PDN_EN BIT(4) // Enable GPIO-11 as Hardware PowerDown/Resume Source. +#define PFM_WOWL BIT(3) // Wake On Lan indicator for H/W FSM. +#define PFM_LDKP BIT(2) // Loader Initial data when re-enable loader. +#define PFM_ALDN BIT(1) // HCI Region load done, inform HCI block. +#define PFM_LDALL BIT(0) // EEPROM autoload 0x00~60h Enable. + +//---------------------------------------------------------------------------- +// 8192C SYS_CLKR bits (Offset 0x8, 16bit) +//---------------------------------------------------------------------------- +#define RING_CLK_EN BIT(13) // HPON Ring Clock Enable, 1: Enable; 0 : Disable. +#define SYS_CLK_EN BIT(12) // MCU Clock Enable, 1: Enable; 0 : Disable. +#define MAC_CLK_EN BIT(11) // MAC Clock Enable, 1: Enable, 0 : Disable. +#define SEC_CLK_EN BIT(10) // SEC Clock Enable, 1 :Enable, 0 :Disable. +#define PHY_SSC_RSTB BIT(9) // PHY SSC Enable (0: Disable, 1: Enable). +#define CLKR_80M_SSC_EN_HOLD_PHS0 BIT(8) // 80M Clock Hold phase 0. +#define CLKR_80M_SSC_DIS BIT(7) // 80M Clock SSC Disable. +#define LOADER_CLK_EN BIT(5) // Loader (eFuse/EEPROM) Clock Enable. +#define MACSLP BIT(4) // MAC SLEEP. +#define ROMD16V_EN BIT(2) // Analog Clock source Divide 16 Mode for EEPROM. +#define ANA8M BIT(1) // Analog Clock source rate, 1: 8M Hz, 0: 500K Hz. +#define CNTD16V_EN BIT(0) // Analog Clock source Divide 16 Mode for Hardware Timer. + +//---------------------------------------------------------------------------- +// 8192C CR9346 bits (Offset 0xA, 16bit) +//---------------------------------------------------------------------------- +#define VPDIDX_SHIFT 8 // VPD mode, EEPROM Index. +#define VPDIDX_Mask 0x0FF +#define EEM1_0_SHIFT 6 // Operating Mode. +#define EEM1_0_Mask 0x03 +#define EEPROM_EN BIT(5) // EEPROM/Efuse is found when set to 1. +#define EERPOMSEL BIT(4) // System EEPROM select (power on selected by GPIO-0). +#define EECS BIT(3) // reflect the state of the EECS. +#define EESK BIT(2) // reflect the state of the EESK. +#define EEDI BIT(1) // reflect the state of the EEDI. +#define EEDO BIT(0) // reflect the state of the EEDO. + + +#ifdef EN_EFUSE +#define CmdEEPROM_En BIT(5) // EEPROM enable when set 1 +#define CmdEERPOMSEL BIT(4) // System EEPROM select, 0: boot from E-FUSE, 1: The EEPROM used is 9346 +#define AutoLoadEEPROM (CmdEEPROM_En|CmdEERPOMSEL) +#define AutoLoadEFUSE CmdEEPROM_En + + +#ifdef CONFIG_RTL_92C_SUPPORT + +#ifdef CONFIG_PCI_HCI +#define EEPROM_VID 0x0A // SE Vendor ID.A-B +#define EEPROM_DID 0x0C // SE Device ID. C-D +#define EEPROM_SVID 0x0E // SE Vendor ID.E-F +#define EEPROM_SMID 0x10 // SE PCI Subsystem ID. 10-11 +#endif +#define EEPROM_TxPowerCCK 0x5A // CCK Tx Power base +#define EEPROM_TxPowerHT40_1S 0x60 // HT40 Tx Power base +#define EEPROM_TxPowerHT40_2SDiff 0x66 // HT40 Tx Power diff +#define EEPROM_TxPowerHT20Diff 0x69 // HT20 Tx Power diff +#define EEPROM_TxPowerOFDMDiff 0x6C // OFDM Tx Power diff +#define EEPROM_MACADDRESS 0x16 + +#define EEPROM_CHANNEL_PLAN 0x75 +#define EEPROM_TSSI_A 0x76 +#define EEPROM_TSSI_B 0x77 +#define EEPROM_THERMAL_METER 0x78 //[4:0] +#define EEPROM_RF_OPT1 0x79 +#define EEPROM_RF_OPT2 0x7A +#define EEPROM_RF_OPT3 0x7B +#define EEPROM_RF_OPT4 0x7C +#define EEPROM_VERSION 0x7E +#define EEPROM_CUSTOMER_ID 0x7F + +#define EEPROM_NORMAL_BoardType EEPROM_RF_OPT1 //[7:5] + +#ifdef CONFIG_USB_HCI + +#define EEPROM_VID 0x0A +#define EEPROM_PID 0x0C +#define EEPROM_SUBCUSTOMER_ID 0x59 + +//should be renamed and moved to another file +typedef enum _BOARD_TYPE_8192CUSB{ + BOARD_USB_DONGLE = 0, // USB dongle + BOARD_USB_High_PA = 1, // USB dongle with high power PA + BOARD_MINICARD = 2, // Minicard + BOARD_USB_SOLO = 3, // USB solo-Slim module + BOARD_USB_COMBO = 4, // USB Combo-Slim module +} BOARD_TYPE_8192CUSB, *PBOARD_TYPE_8192CUSB; + +#endif // CONFIG_USB_HCI +#endif // CONFIG_RTL_92C_SUPPORT + +#ifdef CONFIG_USB_HCI +#define BOARD_TYPE_NORMAL_MASK 0xE0 + +#define EEPROM_Default_PID 0x1234 +#define EEPROM_Default_VID 0x5678 +#define EEPROM_Default_CustomerID 0xAB +#define EEPROM_Default_SubCustomerID 0xCD +#endif // CONFIG_USB_HCI + +#endif // EN_EFUSE + + +//---------------------------------------------------------------------------- +// 8192S AFE_MISC bits (Offset 0x10, 8bits) +//---------------------------------------------------------------------------- +#define MAC_ID_EN BIT(7) // Reserved for RF_ID selection to be MAC. +#define AFE_MBEN BIT(1) // Enable AFE Macro Block's Mbias. +#define AFE_BGEN BIT(0) // Enable AFE Macro Block's Bandgap. + +//---------------------------------------------------------------------------- +// 8192C SPS0_CTRL bits (Offset 0x11-17, 56bits) +//---------------------------------------------------------------------------- +#define SW18_LDO_R BIT(19) // LDO_R_L1 = 1 => LDO resistor connect. +#define SW18_V15ADJ_SHIFT 16 // v15adj_L1<2:0> output. +#define SW18_V15ADJ_Mask 0x07 +#define SW18_VOL_SHIFT 12 // VOL_L1<3:0> output. +#define SW18_VOL_Mask 0x0F +#define SW18_IN_SHIFT 9 // IN_L1<2:0> output. +#define SW18_IN_Mask 0x07 +#define SW18_TBOX_SHIFT 7 // TBOC_L1<1:0> output. +#define SW18_TBOX_Mask 0x03 +#define SW18_SET_DELAY BIT(6) // SET_DELAY_L1=1=> nonoverlap delay increases. +#define SW18_SEL BIT(5) // SD_L1 = 1 => turn off quickly. +#define SW18_STD_SHIFT 3 // STD_L1<1:0> time. +#define SW18_STD_Mask 0x03 +#define SW18_SD BIT(2) // SD_L1 = 1 => turn off quickly. +#define SW18_AREN BIT(1) // 3.3->1.8 for PFM Anti-ring. +#define SW18_R3_B1 BIT(0) // + +#define SW18_R3_B0 BIT(31) // +#define SW18_R2_SHIFT 29 // +#define SW18_R2_Mask 0x03 +#define SW18_R1_SHIFT 27 // +#define SW18_R1_Mask 0x03 +#define SW18_C3_SHIFT 25 // +#define SW18_C3_Mask 0x03 +#define SW18_C2_SHIFT 23 // +#define SW18_C2_Mask 0x03 +#define SW18_C1_SHIFT 21 // +#define SW18_C1_Mask 0x03 +#define SW18_SCREF_SHIFT 19 // For FDUAL, tune reference frequency. +#define SW18_SCREF_Mask 0x03 +#define SW18_SCPFM_SHIFT 17 // For FDUAL, tune pfm frequency. +#define SW18_SCPFM_Mask 0x03 +#define SW18_PWFMTUNE_SHIFT 14 // +#define SW18_PWFMTUNE_Mask 0x07 +#define SW18_SELSTOP BIT(13) // SEL_STOP_L1 = 0 => no delay. +#define SW18_SELD_SHIFT 11 // Bit(1)=1 enable clamp maximum duty, bit(0)=1 enable clamp minimum duty +#define SW18_SELD_Mask 0x03 +#define SW18_POWOCP BIT(10) // POWOCP_L1=1=> enable over current protection. +#define SW18_OCP_SHIFT 7 // +#define SW18_OCP_Mask 0x07 +#define SW18_SFREQ_SHIFT 5 // +#define SW18_SFREQ_Mask 0x03 +#define SW18_SFREQC BIT(4) // +#define SW18_FPWM BIT(3) // FPWM_L1 = 1 => force PWM, FPWM_L1 = 0 => force PFM. +#define SW18_FDUAL BIT(2) // FDUAL_L1 =1 => PWM or PFM. +#define SW18_SWEN BIT(1) // Enable VSPS18_SW Macro Block. +#define SW18_LDEN BIT(0) // Enable VSPS18_LDO Macro Block. + +//---------------------------------------------------------------------------- +// 8192C SPS_OCP_CFG bits (Offset 0x18-1B, 32bits) +//---------------------------------------------------------------------------- +#define SPS18_OCP_DIS BIT(31) // sps18 ocp, 0:enable, 1:disable. +#define SPS18_OCP_TH_SHIFT 16 // Sps18 ocp threshold. +#define SPS18_OCP_TH_Mask 0x07FFF +#define OCP_WINDOW_SHIFT 0 // Ocp monitor window width configure, count on ana_clk/16. +#define OCP_WINDOW_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C RSV_CTRL0 bits (Offset 0x1C-1E, 24bits) +//---------------------------------------------------------------------------- +#define HREG_DBG_SHIFT 8 // HREG Access Debug. +#define HREG_DBG_Mask 0x0FFFF +#define LOCK_ALL_EN BIT(7) // 1:Enable 'Locked All' setting by Hardware, 0: Hardware Enable 'Locked All' denied. +#define R_DIS_PRST_1 BIT(6) // Control if PERST can reset MACCORE. +#define R_DIS_PRST_0 BIT(5) // Control if PERST can reset MACCORE. +#define WLOCK_40 BIT(4) // 1:Register Write Locked, 0: Register Accessible by SW/FW. +#define WLOCK_08 BIT(3) // 1:Register Write Locked, 0: Register Accessible by SW/FW. +#define WLOCK_04 BIT(2) // 1:Register Write Locked, 0: Register Accessible by SW/FW. +#define WLOCK_00 BIT(1) // 1:Register Write Locked, 0: Register Accessible by SW/FW. +#define WLOCK_ALL BIT(0) // 1:Register Write Locked, 0: Register Accessible by SW/FW. + +//---------------------------------------------------------------------------- +// 8192C RF_CTRL bits (Offset 0x1F, 8bits) +//---------------------------------------------------------------------------- +#define RF_SDMRSTB BIT(2) // Reset RF SDM Module (low active). +#define RF_RSTB BIT(1) // Reset RF Module (low active). +#define RF_EN BIT(0) // Enable RF Module. + +//---------------------------------------------------------------------------- +// 8192C LDOA15_CTRL bits (Offset 0x20, 8bits) +//---------------------------------------------------------------------------- +#define LDA15_VOADJ_SHIFT 4 // +#define LDA15_VOADJ_Mask 0x0F +#define LDA15_STBY BIT(3) // LDOA15 Standby Mode. +#define LDA15_OBUF BIT(2) // LDOA15 Output Buffered. +#define REG_VOS BIT(1) // LDOA15 Add Offset voltage. +#define LDA15_EN BIT(0) // Enable LDOA15 Macro Block. + +//---------------------------------------------------------------------------- +// 8192C LDOV12D_CTRL bits (Offset 0x21, 8bits) +//---------------------------------------------------------------------------- +#define LDV12_VADJ_SHIFT 4 // LDOVD12 voltage adjust. +#define LDV12_VADJ_Mask 0x0F +#define LDV12_BUFO BIT(2) // LDOVD12 buffer output Mode. +#define LDV12_SDBY BIT(1) // LDOVD12 standby mode. +#define LDV12_EN BIT(0) // Enable LDOA12 Macro Block. + +//---------------------------------------------------------------------------- +// 8192C LDOHCI12_CTRL bits (Offset 0x22, 8bits) +//---------------------------------------------------------------------------- +#define LDH12_SDBY BIT(5) // LDOHCI12 standby mode. +#define LDH12_OBUF BIT(4) // Enable LDOHCI12 Macro Block. +#define LDH12_VADJ_SHIFT 1 // LDOHCI12 voltage adjust. +#define LDH12_VADJ_Mask 0x07 +#define LDH12_EN BIT(0) // Enable LDOHCI12 Macro Block. + +//---------------------------------------------------------------------------- +// 8192C LPLDO_CTRL bits (Offset 0x23, 8bits) +//---------------------------------------------------------------------------- +#define LPLDH12_SLP BIT(4) // LPLDOH12 Sleep Mode. +#define LPLDH12_VADJ_SHIFT 0 // LPLDOH12 voltage adjust. +#define LPLDH12_VADJ_Mask 0x0F + +//---------------------------------------------------------------------------- +// 8192C AFE_XTAL_CTRL bits (Offset 0x24-27, 32bits) +//---------------------------------------------------------------------------- +#define CKDLY_BT BIT(29) // Delay time of CLK_BT relate to CLK_DIG, 0: long time, 1: short time. +#define CKDLY_DIG BIT(28) // Delay time of CLK_DIG relate to CLK_AFE, 0: long time, 1: short time. +#define CKDLY_USB BIT(27) // Delay time of CLK_USB relate to CLK_AFE, 0: long time, 1: short time. +#define CKDLY_AFE BIT(26) // Delay time of CLK_AFE relate to CLK_RF, 0: long time, 1: short time. +#define XTAL_GPIO_SHIFT 23 // +#define XTAL_GPIO_Mask 0x07 +#define XTAL_BT_DRV_SHIFT 21 // BT clock source Driving current: 11:most current, 00: less current. +#define XTAL_BT_DRV_Mask 0x03 +#define XTAL_BT_GATE BIT(20) // Gated control: 1: BT Clock source gated, 0: clock enable (auto setting by trap data). +#define XTAL_DIG_DRV_SHIFT 18 // DIG clock source 11:most current, 00: less current. +#define XTAL_DIG_DRV_Mask 0x03 +#define XTAL_GATE_DIG BIT(17) // Gated control:1: DIG Clock source gated, 0: clock enable. +#define XTAL_RF_DRV_SHIFT 15 // RF PLL Driving current: 11:most current, 00: less current. +#define XTAL_RF_DRV_Mask 0x03 +#define XTAL_RF_GATE BIT(14) // Gated control: 1: RF Clock source gated, 0: clock enable. +#define XTAL_AFE_DRV_SHIFT 12 // AFE PLL Driving current: 11:most current, 00: less current. +#define XTAL_AFE_DRV_Mask 0x03 +#define XTAL_GATE_AFE BIT(11) // Gated control:1: USB Clock source gated, 0: clock enable. +#define XTAL_USB_DRV_SHIFT 9 // USB PLL Driving current: 11:most current, 00: less current. +#define XTAL_USB_DRV_Mask 0x03 +#define XTAL_GATE_USB BIT(8) // Gated control:1: USB Clock source gated, 0: clock enable. +#define XTAL_CADJ_XI_SHIFT 4 // 1:add cap, 0:degrade cap. +#define XTAL_CADJ_XI_Mask 0x0F +#define XTAL_BOSC_SHIFT 2 // The bias current control of VCO block. +#define XTAL_BOSC_Mask 0x03 +#define XTAL_BSEL BIT(1) // 1: schmitt trigger, 0:nand. +#define XTAL_EN BIT(0) // Enable XTAL Macro block. + +//---------------------------------------------------------------------------- +// 8192C AFE_PLL_CTRL bits (Offset 0x28-2B, 32bits) +//---------------------------------------------------------------------------- +#define AFE_DUMMY_SHIFT 25 // Dummy Registers. +#define AFE_DUMMY_Mask 0x07 +#define APLL_1MEN BIT(24) // 1:Enable 0:output "1". +#define APLL_40DRV_SHIFT 22 // clk diving 00: weak 11:strong. +#define APLL_40DRV_Mask 0x03 +#define APLL_PLLDRV_SHIFT 20 // clk diving 00: weak 11:strong. +#define APLL_PLLDRV_Mask 0x03 +#define APLL_88DRV_SHIFT 18 // clk diving 00: weak 11:strong. +#define APLL_88DRV_Mask 0x03 +#define APLL_80DRV_SHIFT 16 // clk diving 00: weak 11:strong. +#define APLL_80DRV_Mask 0x03 +#define APLL_80EN BIT(15) // 1:Enable 0:output "1". +#define APLL_320EN BIT(14) // 1:Enable 0:output "1". +#define APLL_320BIAS_SHIFT 11 // pll320 CP current selection. +#define APLL_320BIAS_Mask 0x07 +#define APLL_BIAS_SHIFT 8 // pll CP current selection. +#define APLL_BIAS_Mask 0x07 +#define APLL_KVCO_SHIFT 6 // pll VCO KVCO selection. +#define APLL_KVCO_Mask 0x03 +#define APLL_LPFEN BIT(5) // enable PLL Bias Current LPF. +#define APLL_WDOGB BIT(4) // enable watch dog 0: enable 1:disable. +#define APLL_EDGE_SEL BIT(3) // Reference clock: 1 : negative edge, 0 : positive edge. +#define APLL_FREF_SEL BIT(2) // Reference clock: 1 : 20MHz, 0 : 40MHz. +#define APLL_320_EN BIT(1) // Enable AFE 320 PLL Macro Block. +#define APLL_EN BIT(0) // Enable AFE PLL Macro Block. + +//---------------------------------------------------------------------------- +// 8192C EFUSE_CTRL bits (Offset 0x30-33, 32bits) +//---------------------------------------------------------------------------- +#define EF_FLAG BIT(31) // Access Flag. Write "1" for Program; Write "0" for Read Access. +#define EF_PGPD_SHIFT 28 // E-fuse program time. +#define EF_PGPD_Mask 0x07 +#define EF_RDT_SHIFT 24 // E-fuse read time: in the unit of cycle time. +#define EF_RDT_Mask 0x0F +#define EF_PGT_SHIFT 20 // Programming setup time. In the unit of cycle time.(125ns). +#define EF_PGT_Mask 0x0F +#define EF_PD BIT(19) // Efuse power down. +#define ALD_EN BIT(18) // Autoload Enable. +#define EF_ADDR_SHIFT 8 // Access Address. +#define EF_ADDR_Mask 0x03FF +#define EF_DATA_SHIFT 0 // Access Data. +#define EF_DATA_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C EFUSE_TEST bits (Offset 0x34-37, 32bits) +//---------------------------------------------------------------------------- +#define LDOE25_EN BIT(31) // Enable LDOE25 Macro Block. +#define LDOE25_VADJ_SHIFT 28 // LDOE25 voltage adjust. +#define LDOE25_VADJ_Mask 0x07 +#define ADDR_END_Shift 25 // 92D_REG, Scan effuse end (1023-addr_end) +#define ADDR_END_Mask 0x07 +#define ADDR_STR_Shift 18 // 92D_REG, Scan efuse from (addr_str*8) +#define ADDR_STR_Mask 0x07F +#define BYTE_CNT_EN BIT(17) // 92D_REG, 1: scan efuse in byte; 0: scan efuse in bit +#define EF_SCAN_EN BIT(16) // 92D_REG, 1: efuse in scan process. 0: not in scan process +#define EDATA1_SHIFT 8 // EEPROM offset 1 data (EE Byte-1). +#define EDATA1_Mask 0x0FF +#define EF_TRPT BIT(7) // Test Scan Report: 1 : Fail, 0 : OK. +#define EF_TTHD_SHIFT 0 // Bit number for all cells scan test. +#define EF_TTHD_Mask 0x07F + +//---------------------------------------------------------------------------- +// 8192C PWR_DATA bits (Offset 0x38-3B, 32bits) +//---------------------------------------------------------------------------- +#define EDATA0_SHIFT 24 // EEPROM offset 0 data (EE Byte-0). +#define EDATA0_Mask 0x0FF +#define HTEST_SEL_SHIFT 16 // TEST Mode Select (EE Byte-7). +#define HTEST_SEL_Mask 0x0FF +#define HPON_STBP2_SHIFT 8 // HPON Stable time parameter (EE Byte-5). +#define HPON_STBP2_Mask 0x0FF +#define HPON_STBP1_SHIFT 0 // HPON Stable time parameter (EE Byte-2). +#define HPON_STBP1_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C CAL_TIMER bits (Offset 0x3C-3D, 16bits) +//---------------------------------------------------------------------------- +#define MATCH_CNT_SHIFT 8 // match counter for sleep mode. +#define MATCH_CNT_Mask 0x0FF +#define CAL_SCAL_SHIFT 0 // scaler fine tune for sleep mode (tune in Time unit). +#define CAL_SCAL_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C ACLK_MON bits (Offset 0x3E-3F, 16bits) +//---------------------------------------------------------------------------- +#define RCLK_MON_SHIFT 5 // ring clock monitor (with DPSTU scale). +#define RCLK_MON_Mask 0x07FF +#define CAL_TIMER_EN BIT(4) // calibration timer enable. This shall be turned off before sleep mode enable. +#define DPSTU_SHIFT 2 // Deep Power Save Time Unit: 00: 64us, 01: 128us, 10: 192us, 11: 256 us. +#define DPSTU_Mask 0x03 +#define SUS_16X BIT(1) // Scale timer 16x when suspend mode, (~250 S). +#define RSM_EN BIT(0) // When Timer Expired, Resume Hardware StateMachine. + +//---------------------------------------------------------------------------- +// 8192C GPIO_MUXCFG bits (Offset 0x40-43, 32 bits) +//---------------------------------------------------------------------------- +#define GPIO_MOD_H_SHIFT 28 // When bit is zero, corresponding port configured to data port; + // otherwise, when a bit is set, and GPIO_IO_SEL is set to "0", + // then it is interrupt mode.. +#define GPIO_MOD_H_Mask 0x0F +#define GPIO_IO_SEL_H_SHIFT 24 // GPIO_IO_SEL[11:8], output when bit=1;input when bit=0. +#define GPIO_IO_SEL_H_Mask 0x0F +#define GPIO_OUT_H_SHIFT 20 // GPIO_OUT[11:8], GPIO pins output value. +#define GPIO_OUT_H_Mask 0x0F +#define GPIO_IN_H_SHIFT 16 // GPIO_IN[11:8], GPIO pins input value. +#define GPIO_IN_H_Mask 0x0F +#define SIC_LBK BIT(15) // Enable SIC_Loop_Back Mode, (auto set by ICFG). +#define HTP_EN BIT(14) // 0 : Enable as Host Debug Port, 1 : Enable as Host Test Port. +#define SIC_23 BIT(13) // Enable SIC at 0: GPIO 9,10 pins ; 1 : GPIO 2,3 pins. +#define SIC_EN BIT(12) // Enable GPIO Pins as SIC, (auto set by ICFG). +#define SIC_SWRST BIT(11) // 0 : Reset SIC by SW, prevent SIC Dead Lock. +#define PMAC_EN BIT(10) // PMAC Enable (auto set by ICFG). +#define UART_SEL BIT(9) // Enable UART at 0: GPIO 6,7 pins; 1 : GPIO 9,10 pins. +#define UART_EN BIT(8) // Enable GPIO Pins as UART. +#define BTMode_SHIFT 6 // Bluetooth Mode. +#define BTMode_Mask 0x03 +#define BT_EN BIT(5) // Enable GPIO0,1,2,3,8 Pins for Bluetooth. +#define EROM_EN BIT(4) // Enable GPIO6 for EEDO, GPIO7 for EEDI, default Enable when 9346 selected +#define TRSW1EN BIT(3) // Enable GPIO9,10 for TRSWN1, TRSWP1. +#define TRSW0EN BIT(2) // Enable GPIO8 for TRSWN0. +#define GPIOSEL_SHIFT 0 // GPIO Select. +#define GPIOSEL_Mask 0x03 + +//---------------------------------------------------------------------------- +// 8192C GPIO_PIN_CTRL bits (Offset 0x44-47, 32 bits) +//---------------------------------------------------------------------------- +#define GPIO_MOD_L_SHIFT 24 // When bit is 0, corresponding port set as data port; + // otherwise, when a bit=1, and GPIO_IO_SEL is set to "0", + // then it is interrupt mode.. +#define GPIO_MOD_L_Mask 0x0FF +#define GPIO_IO_SEL_L_SHIFT 16 // GPIO_IO_SEL[7:0], output when bit=1;input when bit=0. +#define GPIO_IO_SEL_L_Mask 0x0FF +#define GPIO_OUT_L_SHIFT 8 // GPIO_OUT[7:0], GPIO pins output value. +#define GPIO_OUT_L_Mask 0x0FF +#define GPIO_IN_L_SHIFT 0 // GPIO_IN[7:0], GPIO pins input value. +#define GPIO_IN_L_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C GPIO_INTM bits (Offset 0x48-4B, 32 bits) +//---------------------------------------------------------------------------- +#define MDBG_SEL_SHIFT 30 // +#define MDBG_SEL_Mask 0x03 +#define GPIO_EXT_WOL_SHIFT 12 // External WOL source control. +#define GPIO_EXT_WOL_Mask 0x0F +#define GPIOB_INT_MD BIT(11) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIOA_INT_MD BIT(10) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO9_INT_MD BIT(9) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO8_INT_MD BIT(8) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO7_INT_MD BIT(7) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO6_INT_MD BIT(6) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO5_INT_MD BIT(5) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO4_INT_MD BIT(4) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO3_INT_MD BIT(3) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO2_INT_MD BIT(2) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO1_INT_MD BIT(1) // 0=positive edge, 1=negative edge, is sensed as interrupt. +#define GPIO0_INT_MD BIT(0) // 0=positive edge, 1=negative edge, is sensed as interrupt. + +//---------------------------------------------------------------------------- +// 8192C LEDCFG bits (Offset 0x4C-4F, 32 bits) +//---------------------------------------------------------------------------- +#define GP8_LED BIT(22) // Enable GPIO-8 as LED2. +#define LED2EN BIT(21) // Enable GPIO-10/GPIO-8 as LED2. +#define LED2PL BIT(20) // LED2 polarity control. +#define LED2SV BIT(19) // LED2 software value. +#define LED2CM_SHIFT 16 // LED2 Control Mode. +#define LED2CM_Mask 0x07 +#define LED1DIS BIT(15) // LED1 Disabled for analog signal usage, + // 1: disable (input mode), 0:Enable (output mode). +#define LED1PL BIT(12) // LED1 polarity control (auto-load configurable). +#define LED1SV BIT(11) // LED1 software value. +#define LED1CM_SHIFT 8 // LED1 Control Mode. +#define LED1CM_Mask 0x07 +#define LED0DIS BIT(7) // LED1 Disabled for analog signal usage, + // 1: disable (input mode), 0:Enable (output mode). +#define LED0PL BIT(4) // LED0 polarity control (auto-load configurable). +#define LED0SV BIT(3) // LED0 software value. +#define LED0CM_SHIFT 0 // LED0 Control Mode. +#define LED0CM_Mask 0x07 + +#define LED_SW_CTRL 0 +#define LED_OFF 1 +#define LED_TX_RX_EVENT_ON 2 +#define LED_TX_RX_EVENT_OFF 3 +#define LED_TX_EVENT_ON 4 +#define LED_TX_EVENT_OFF 5 +#define LED_RX_EVENT_ON 6 +#define LED_RX_EVENT_OFF 7 + +//---------------------------------------------------------------------------- +// 8192C FSIMR bits (Offset 0x50-53, 32 bits) +//---------------------------------------------------------------------------- +#define PDNINT_EN BIT(31) // Enable Hardware Power Down interrupt source. +#define SYS_TIMER_EN BIT(30) // Enable Hardware System Timer interrupt source. +#define SPS_OCP_INT_EN BIT(29) // Enable SPS OCP alarm interrupt source. +#define HPON_WRE_EN BIT(28) // Enable Continue access HPON registers interrupt source. +#define GPIOB_INT_EN BIT(23) // Enable GPIOB interrupt source. +#define GPIOA_INT_EN BIT(22) // Enable GPIOA interrupt source. +#define GPIO9_INT_EN BIT(21) // Enable GPIO9 interrupt source. +#define GPIO8_INT_EN BIT(20) // Enable GPIO8 interrupt source. +#define GPIO7_INT_EN BIT(19) // Enable GPIO7 interrupt source. +#define GPIO6_INT_EN BIT(18) // Enable GPIO6 interrupt source. +#define GPIO5_INT_EN BIT(17) // Enable GPIO5 interrupt source. +#define GPIO4_INT_EN BIT(16) // Enable GPIO4 interrupt source. +#define GPIO3_INT_EN BIT(15) // Enable GPIO3 interrupt source. +#define GPIO2_INT_EN BIT(14) // Enable GPIO2 interrupt source. +#define GPIO1_INT_EN BIT(13) // Enable GPIO1 interrupt source. +#define GPIO0_INT_EN BIT(12) // Enable GPIO0 interrupt source. + +//---------------------------------------------------------------------------- +// 8192C FSISR bits (Offset 0x54-57, 32 bits) +//---------------------------------------------------------------------------- +#define PDNINT BIT(31) // Hardware Power Down interrupt. +#define HWSYS_TIMER_INT BIT(30) // Hardware System Timer interrupt. +#define SPS_OCP_INT BIT(29) // SPS OCP alarm interrupt. +#define HPON_WRE BIT(28) // Continue access HPON registers interrupt. Write 1 clear. +#define GPIOB_INT BIT(23) // GPIOB INT Status. Write 1 clear. +#define GPIOA_INT BIT(22) // GPIOA INT Status. Write 1 clear. +#define GPIO9_INT BIT(21) // GPIO9 INT Status. Write 1 clear. +#define GPIO8_INT BIT(20) // GPIO8 INT Status. Write 1 clear. +#define GPIO7_INT BIT(19) // GPIO7 INT Status. Write 1 clear. +#define GPIO6_INT BIT(18) // GPIO6 INT Status. Write 1 clear. +#define GPIO5_INT BIT(17) // GPIO5 INT Status. Write 1 clear. +#define GPIO4_INT BIT(16) // GPIO4 INT Status. Write 1 clear. +#define GPIO3_INT BIT(15) // GPIO3 INT Status. Write 1 clear. +#define GPIO2_INT BIT(14) // GPIO2 INT Status. Write 1 clear. +#define GPIO1_INT BIT(13) // GPIO1 INT Status. Write 1 clear. +#define GPIO0_INT BIT(12) // GPIO0 INT Status. Write 1 clear. + +//---------------------------------------------------------------------------- +// 8192C MCUFWDL bits (Offset 0x80-83, 32 bits) +//---------------------------------------------------------------------------- +#define RPWM_SHIFT 24 // Host Request Power State. +#define RPWM_Mask 0x0FF +#define CPRST BIT(23) // 8051 Reset Status. +#define ROM_DLEN BIT(19) // ROM Download Enable (8051 Core will be reseted) FPGA only. +#define ROM_PGE_SHIFT 16 // ROM Page (FPGA only). +#define ROM_PGE_Mask 0x07 +#define MAC1_RFINI_RDY BIT(10) // 92D_REG, MAC1 MCU Initial RF ready +#define MAC1_BBINI_RDY BIT(9) // 92D_REG, MAC1 MCU Initial BB ready +#define MAC1_MACINI_RDY BIT(8) // 92D_REG, MAC1 MCU Initial MAC ready +#define MCU_STATUS BIT(7) // 92D_REG, 1: SRAM, 0: ROM +#define WINTINI_RDY BIT(6) // WLAN Interrupt Initial ready. +#define MAC0_RFINI_RDY BIT(5) // MAC0 MCU Initial RF ready. +#define MAC0_BBINI_RDY BIT(4) // MAC0 MCU Initial BB ready. +#define MAC0_MACINI_RDY BIT(3) // MAC0 MCU Initial MAC ready. +#define FWDL_CHKSUM_RPT BIT(2) // FWDL CheckSum report, 1: OK, 0 : Faill. +#define MCUFWDL_RDY BIT(1) // Driver set this bit to notify MCU FW Download OK. +#define MCUFWDL_EN BIT(0) // MCU Firmware download enable. 1:Enable, 0:Disable. + +//---------------------------------------------------------------------------- +// 8192C MCUTSTCFG bits (Offset 0x84-87, 32 bits) +//---------------------------------------------------------------------------- +#define LBKTST_SHIFT 0 // LBK TST indicator. +#define LBKTST_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C BIST_CTRL bits (Offset 0xD0-D3, 32 bits) +//---------------------------------------------------------------------------- +#define BB_SPEED_SCAN BIT(31) // BB at speed scan mode Enable. +#define SCAN_PLL_BYPASS BIT(30) // 92D_REG +#define MBIST_RSTNI_Shift 8 // 92D_REG +#define MBIST_RSTNI_Mask 0x07FF +#define BIST_RESUME_PS BIT(5) +#define BIST_RESUME BIT(4) +#define BIST_DRF BIT(3) // 92D_REG +#define BIST_RETEN BIT(3) +#define BIST_NORMAL BIT(2) +#define BIST_RSTN BIT(1) +#define BIST_CLK_EN BIT(0) + +//---------------------------------------------------------------------------- +// 8192C C_BIST_RPT bits (Offset 0xD4-D7, 32 bits) +//---------------------------------------------------------------------------- +#define C_MAC_BIST_FAIL BIT(31) // MAC_BIST_FAIL. +#define C_USB_IRAM_FAIL BIT(26) // USB IRAM BIST FAIL. +#define C_USB_RAM1_FAIL BIT(25) // USB RAM1 BIST FAIL. +#define C_USB_PROM_FAIL BIT(24) // USB PROM BIST FAIL. +#define C_PCIE_RETRY_BIST_FAIL BIT(20) // PCIE RETRY RAM BIST FAIL. +#define C_PCIE_SOT_BIST_FAIL BIT(19) // PCIE RETRY SOT RAM BIST FAIL. +#define C_PCIE_PH1_BIST_FAIL BIT(18) // PCIE PHDR RAM1 BIST FAIL. +#define C_PCIE_PH0_BIST_FAIL BIT(17) // PCIE PHDR RAM0 BIST FAIL. +#define C_PCIE_PD_BIST_FAIL BIT(16) // PCIE PDATA RAM BIST FAIL. +#define C_MAC_BIST_RDY BIT(10) // MAC MBIST Test report Ready. +#define C_USB_BIST_RDY BIT(9) // USB MBIST Test report Ready. +#define C_PCIE_BIST_RDY BIT(8) // PCIE MBIST Test report Ready. +#define C_MAC_BIST_START BIT(2) // MAC MBIST START PULSE. +#define C_USB_BIST_START BIT(1) // USB MBIST START PULSE. +#define C_PCIE_BIST_START BIT(0) // PCIE MBIST START PULSE. + +//---------------------------------------------------------------------------- +// 8192C USB_SIE_INTF bits (Offset 0xE0-E3, 32 bits) +//---------------------------------------------------------------------------- +#define USB_SIE_INTF_WE BIT(25) // Write Enable of SIE interface. +#define USB_SIE_INTF_BYIOREG BIT(24) // SIE Bypass IOREG interface. +#define USB_SIE_INTF_ADDR_SHIFT 16 // The address of SIE register. +#define USB_SIE_INTF_ADDR_Mask 0x0FF +#define USB_SIE_INTF_RD_SHIFT 8 // The read data from USB SIE. +#define USB_SIE_INTF_RD_Mask 0x0FF +#define USB_SIE_INTF_WD_SHIFT 0 // The write data to USB SIE. +#define USB_SIE_INTF_WD_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C PCIE_MIO_INTF bits (Offset 0xE4-E7, 32 bits) +//---------------------------------------------------------------------------- +#define PCIE_MIO_BYIOREG BIT(13) // MIO bypass IOREG interface. +#define PCIE_MIO_RE BIT(12) // Read Enable of MIO interface. +#define PCIE_MIO_WE_SHIFT 8 // Write Byte Enable of MIO interface. +#define PCIE_MIO_WE_Mask 0x0F +#define PCIE_MIO_ADDR_SHIFT 0 // The address of PCIE MIO Access register. +#define PCIE_MIO_ADDR_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C HPON_FSM bits (Offset 0xEC-EF, 32 bits) +//---------------------------------------------------------------------------- +#define EVENT_FSM_SHIFT 16 // The State Machine Trigger Events. +#define EVENT_FSM_Mask 0x0FFFF +#define PMC_ADDR_SHIFT 8 // The Hardware Access HPON Register Addr. +#define PMC_ADDR_Mask 0x0FF +#define PMC_WR BIT(7) // The Hardware Access HPON Register Write Pulse. +#define PMC_DATA BIT(6) // The Hardware Access HPON Register Data. +#define FSM_STATE_SHIFT 0 // The State Machine Data. +#define FSM_STATE_Mask 0x03F + +//---------------------------------------------------------------------------- +// 8192C SYS_CFG bits (Offset 0xF0-F3, 32 bits) +//---------------------------------------------------------------------------- +#define TRP_ICFG_SHIFT 28 // Trapped ICFG data value. +#define TRP_ICFG_Mask 0x0F +#define TYPE_ID BIT(27) // 1: 8191C/8192C ; 0: 8188C. +#define BD_HCI_SEL BIT(26) // Trapped HCI_SEL value. +#define BD_PKG_SEL BIT(25) // Trapped PKG_ENG_SEL value. +#define TRP_BT_EN BIT(24) // Trapped BT Chip Valid need XTAL & SPS resource. +#define TRP_VAUX_EN BIT(23) // Trapped VAUX_EN. +#define PAD_HWPD_IDN BIT(22) // HWPDN PAD status Indicator. +#define PSC_TESTCFG_SHIFT 20 // Test Pin configuration. +#define PSC_TESTCFG_Mask 0x03 +#define CHIP_VER_RL_SHIFT 16 // Chip version (RL6111). +#define CHIP_VER_RL_Mask 0x0F +#define CHIP_VER_RTL_SHIFT 12 // Test Chip version - 8188C (RLE0307) / 8191C (RLE0308). +#define CHIP_VER_RTL_Mask 0x0F +#define IC_MACPHY_MODE BIT(11) // 0: IC Normal Mode, 1: force IC PHY_ASIC Mode. +#define BD_MAC1 BIT(10) // Bonding option for MAC function-1 Enable. +#define BD_MAC2 BIT(9) // Bonding option for MAC function-2 Enable. +#define SIC_IDLE BIT(8) // Indicator of SIC idle state. +#define TRP_B15V_EN BIT(7) // Trapped option for 1.5V of board. +#define OCP_SHUTDN BIT(6) // SPS OCP shutdown Chip. +#define V15_VLD BIT(5) // 1.5V Power Ready, 1: Power Ready. +#define PCIRSTB BIT(4) // PCIE External PERST, Pin Status. +#define PCLK_VLD BIT(3) // PCIE PHY Clock Stable, 1: Clock Stable. +#define UCLK_VLD BIT(2) // USB PHY Clock Stable, 1: Clock Stable. +#define ACLK_VLD BIT(1) // AFE Clock Stable, 1: Clock Stable. +#define XCLK_VLD BIT(0) // Xtal Clock Stable, 1: Clock Stable. + + +// +// 2. MACTOP General Configuration. (Offset 0x100 - 0x1FFh) +// +//---------------------------------------------------------------------------- +// 8192C CR bits (Offset 0x100-103, 32 bits) +//---------------------------------------------------------------------------- +#define LBMODE_SHIFT 24 // Loopback mode. +#define LBMODE_Mask 0x0F +#define NETYPE_SHIFT 16 // Network Type. +#define NETYPE_SHIFT1 18 +#define NETYPE_Mask 0x03 +#define CALTMR_EN BIT(10) // for 8723 & 88E only +#define MAC_SEC_EN BIT(9) // Enable MAC security engine. +#define ENSWBCN BIT(8) // Enable SW TX beacon. +#define MACRXEN BIT(7) // MAC Receiver Enable. +#define MACTXEN BIT(6) // MAC Transmitter Enable. +#define SCHEDULE_EN BIT(5) // Schedule Enable. +#define PROTOCOL_EN BIT(4) // protocol Block Function Enable. +#define RXDMA_EN BIT(3) // RXDMA Function Enable. +#define TXDMA_EN BIT(2) // TXDMA Function Enable. +#define HCI_RXDMA_EN BIT(1) // HCI to RXDMA Interface Enable. +#define HCI_TXDMA_EN BIT(0) // HCI to TXDMA Interface Enable. +// Loopback mode. +#define LB_NORMAL 0x00 +#define LB_MAC 0x0B +#define LB_MAC_DLY 0x03 +#define LB_PHY 0x01 +#define LB_DMA 0x07 +#define LB_DUAL_MAC 0x1B // 92D_REG +// Network Type. +#define NETYPE_NOLINK 0x00 +#define NETYPE_ADHOC 0x01 +#define NETYPE_INFRA 0x02 +#define NETYPE_AP 0x03 + +//---------------------------------------------------------------------------- +// 8192C PBP bits (Offset 0x104-107, 32 bits) +//---------------------------------------------------------------------------- +#define PSTX_SHIFT 4 // Page size of transmit packet buffer. +#define PSTX_Mask 0x0F +#define PSRX_SHIFT 0 // Page size of receive packet buffer and C2HCMD buffer. +#define PSRX_Mask 0x0F +// Page size +#define PBP_64B 0x00 +#define PBP_128B 0x01 +#define PBP_256B 0x02 +#define PBP_512B 0x03 +#define PBP_1024B 0x04 + +//---------------------------------------------------------------------------- +// 8192C TRXDMA_CTRL bits (Offset 0x10C-10D, 16 bits) +//---------------------------------------------------------------------------- +#define HPQ_SEL_SHIFT 8 // High Priority Queue Selection. +#define HPQ_SEL_Mask 0x03F +#define RXDMA_AGG_EN BIT(2) // +#define RXSHFT_EN BIT(1) // When this bit is set, RX shift to fit alignment is enable. +#define RXDMA_ARBBW_EN BIT(0) // Enable RXDMA Arbitrator priority for Host interface. +// High Priority Queue Selection. +#define HPQ_SEL_VOQ BIT(0) +#define HPQ_SEL_VIQ BIT(1) +#define HPQ_SEL_BEQ BIT(2) +#define HPQ_SEL_BKQ BIT(3) +#define HPQ_SEL_MGQ BIT(4) +#define HPQ_SEL_HIQ BIT(5) + +// For normal driver, 0x10C +#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) +#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) +#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) +#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8 ) +#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6 ) +#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4 ) + +#define QUEUE_LOW 1 +#define QUEUE_NORMAL 2 +#define QUEUE_HIGH 3 + +//---------------------------------------------------------------------------- +// 8192C TRXFF_BNDY bits (Offset 0x114-117, 32 bits) +//---------------------------------------------------------------------------- +#define RXFF0_BNDY_SHIFT 16 // upper boundary of RXFF0. +#define RXFF0_BNDY_Mask 0x0FFFF +#define TXPKTBUF_PGBNDY_SHIFT 0 // From FWHW offload, sets the max pages controlled by TXDMA. +#define TXPKTBUF_PGBNDY_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C TRXFF_STATUS bits (Offset 0x118-11B, 32 bits) +//---------------------------------------------------------------------------- +#define TXPKTFF_FULL BIT(16) // TXDMA block the current TX pkt due to TXPKTBUF full, status bit will be set. +#define RXFF1_OVF BIT(1) // When this bit is "1", RXFF1 is under overflow condition. +#define RXFF0_OVF BIT(0) // When this bit is "1", RXFF0 is under overflow condition. + +//---------------------------------------------------------------------------- +// 8192C RXFF_PTR bits (Offset 0x11C-11F, 32 bits) +//---------------------------------------------------------------------------- +#define RXFF0_RDPTR_SHIFT 16 // The read pointer address of RXFF0. +#define RXFF0_RDPTR_Mask 0x0FFFF +#define RXFF0_WTPTR_SHIFT 0 // The write pointer address of RXFF0. +#define RXFF0_WTPTR_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C HIMR bits (Offset 0x120-123, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C HISR bits (Offset 0x124-127, 32 bits) +//---------------------------------------------------------------------------- +#define HIMR_BCNDMA7 BIT(31) // Beacon DMA Interrupt 7. +#define HIMR_BCNDMA6 BIT(30) // Beacon DMA Interrupt 6. +#define HIMR_BCNDMA5 BIT(29) // Beacon DMA Interrupt 5. +#define HIMR_BCNDMA4 BIT(28) // Beacon DMA Interrupt 4. +#define HIMR_BCNDMA3 BIT(27) // Beacon DMA Interrupt 3. +#define HIMR_BCNDMA2 BIT(26) // Beacon DMA Interrupt 2. +#define HIMR_BCNDMA1 BIT(25) // Beacon DMA Interrupt 1. +#define HIMR_BCNDOK7 BIT(24) // Beacon Queue DMA OK Interrupt7. +#define HIMR_BCNDOK6 BIT(23) // Beacon Queue DMA OK Interrupt6. +#define HIMR_BCNDOK5 BIT(22) // Beacon Queue DMA OK Interrupt5. +#define HIMR_BCNDOK4 BIT(21) // Beacon Queue DMA OK Interrupt4. +#define HIMR_BCNDOK3 BIT(20) // Beacon Queue DMA OK Interrupt3. +#define HIMR_BCNDOK2 BIT(19) // Beacon Queue DMA OK Interrupt2. +#define HIMR_BCNDOK1 BIT(18) // Beacon Queue DMA OK Interrupt1. +#define HIMR_TIMEOUT2 BIT(17) // Time Out Interrupt 2. +#define HIMR_TIMEOUT1 BIT(16) // Time Out Interrupt 1. +#define HIMR_TXFOVW BIT(15) // Transmit packet buffer Overflow. +#define HIMR_PSTIMEOUT BIT(14) // Power Save Time Out Interrupt. +#define HIMR_BCNDMA0 BIT(13) // Beacon DMA Interrupt 0. +#define HIMR_RXFOVW BIT(12) // Receive packet buffer Overflow. +#define HIMR_RDU BIT(11) // Receive Descriptor Unavailable. +#define HIMR_ATIM_END BIT(10) // ATIM Window End Interrupt. +#define HIMR_BCNDOK0 BIT(9) // Beacon Queue DMA OK Interrupt0. +#define HIMR_HIGHDOK BIT(8) // High Queue DMA OK Interrupt. +#define HIMR_TXBCNOK BIT(7) // Transmit Beacon OK Interrupt. +#define HIMR_MGTDOK BIT(6) // Management Queue DMA OK Interrupt. +#define HIMR_TXBCNERR BIT(5) // Transmit Beacon Error Interrupt. +#define HIMR_BKDOK BIT(4) // AC_BK DMA OK Interrupt. +#define HIMR_BEDOK BIT(3) // AC_BE DMA OK Interrupt. +#define HIMR_VIDOK BIT(2) // AC_VI DMA OK Interrupt. +#define HIMR_VODOK BIT(1) // AC_VO DMA Interrupt. +#define HIMR_ROK BIT(0) // Receive DMA OK Interrupt. + +//---------------------------------------------------------------------------- +// 8192C HIMRE bits (Offset 0x128-12A, 24 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C HISRE bits (Offset 0x12C-12E, 24 bits) +//---------------------------------------------------------------------------- +#define HIMRE_TXERR BIT(11) // Enable Tx Error Flag Interrupt. +#define HIMRE_RXERR BIT(10) // Enable Rx Error Flag Interrupt. +#define HIMRE_C2HCMD BIT(9) // Enable CPU to Host Command Interrupt. +#define HIMRE_CPWM BIT(8) // Enable CPU power Mode exchange Interrupt. +#define HIMRE_HBT_CMD BIT(7) // 92D_REG, Host BT_CMD interrupt mask +#define HIMRE_OCPINT BIT(1) // Enable SPS_OCP Interrupt. +#define HIMRE_WLANOFF BIT(0) // Enable WLAN power down Interrupt. + +//---------------------------------------------------------------------------- +// 8192C CPWM bits (Offset 0x12F, 8 bits) +//---------------------------------------------------------------------------- +#define CPWM_TOGGLING BIT(7) // When this bit is toggled, interrtup is send to HISRE.CPWMINT. +#define CPWM_MOD_SHIFT 0 // The current power mode index. +#define CPWM_MOD_Mask 0x07F + +//---------------------------------------------------------------------------- +// 8192C FWIMR bits (Offset 0x130-133, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C FWISR bits (Offset 0x134-137, 32 bits) +//---------------------------------------------------------------------------- +#define FWIMR_VOQ BIT(31) // +#define FWIMR_VIQ BIT(30) // +#define FWIMR_BEQ BIT(29) // +#define FWIMR_BKQ BIT(28) // +#define FWIMR_MGTQ BIT(27) // +#define FWIMR_HIQ BIT(26) // +#define FWIMR_TXPKTIN BIT(25) // interrupt is issued to inform MCU. +#define FWIMR_TXBCNOK BIT(24) // interrupt is issued when a beacon frame is transmitted. +#define FWIMR_TXBCNERR BIT(23) // interrupt is issued when beacon in TXPKTBUF fails to send out. +#define FWIMR_RX_UMD0 BIT(22) // receiving unicast data frame with More Data=0. +#define FWIMR_RX_UMD1 BIT(21) // receiving unicast data frame with More Data=1. +#define FWIMR_RX_BMD0 BIT(20) // receiving broadcast data frame with More Data=0. +#define FWIMR_RX_BMD1 BIT(19) // receiving broadcast data frame with More Data=1. +#define FWIMR_BCN_RX BIT(18) // When receiving Beacon frame. +#define FWIMR_TBTT BIT(17) // The exact TBTT time interrupt. +#define FWIMR_BCNERLY BIT(16) // This interrupt is issue at the time set by DRVERLYINT register before TBTT time. +#define FWIMR_BCNDMA7 BIT(15) // When BCNDMA interval arrives before TBTT7, informs MCU to prepare beacon. +#define FWIMR_BCNDMA6 BIT(14) // When BCNDMA interval arrives before TBTT6, informs MCU to prepare beacon. +#define FWIMR_BCNDMA5 BIT(13) // When BCNDMA interval arrives before TBTT5, informs MCU to prepare beacon. +#define FWIMR_BCNDMA4 BIT(12) // When BCNDMA interval arrives before TBTT4, informs MCU to prepare beacon. +#define FWIMR_BCNDMA3 BIT(11) // When BCNDMA interval arrives before TBTT3, informs MCU to prepare beacon. +#define FWIMR_BCNDMA2 BIT(10) // When BCNDMA interval arrives before TBTT2, informs MCU to prepare beacon. +#define FWIMR_BCNDMA1 BIT(9) // When BCNDMA interval arrives before TBTT1, informs MCU to prepare beacon. +#define FWIMR_BCNDMA0 BIT(8) // When BCNDMA interval arrives before TBTT0, informs MCU to prepare beacon. +#define FWIMR_LP_STBY BIT(7) // Low Power Standby Wake interrupt. +#define FWIMR_ATIM BIT(6) // This interrupt is issued when it is at the time ATIM ms before ATIMWND expiring. +#define FWIMR_HRCV BIT(5) // Host Recover CPU Loop Instruction. +#define FWIMR_H2CCMD BIT(4) // Host To CPU Message Interrupt. +#define FWIMR_RXDONE BIT(3) // +#define FWIMR_ERRORHDL BIT(2) // FWHW/ TXDMA/ RXDMA/ WMAC error status interrupt. +#define FWIMR_TXCCX BIT(1) // +#define FWIMR_TXCLOSE BIT(0) // + +//---------------------------------------------------------------------------- +// 8192C FTIMR bits (Offset 0x138-13B, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C FTISR bits (Offset 0x13C-13F, 32 bits) +//---------------------------------------------------------------------------- +#define FTIMR_FWBT_CMD BIT(18) // 92D_REG, FW BT_CMD interrupt mask +#define FTIMR_RPWM BIT(8) // RPWM INT Status. Write 1 clear. +#define FTIMR_PSTIMER BIT(7) // Enable PSTimer interrupt. +#define FTIMR_TIMEOUT1 BIT(6) // Enable Timer1 interrupt. +#define FTIMR_TIMEOUT0 BIT(5) // Enable Timer0 interrupt. +#define FTIMR_GT4 BIT(4) // Enable General Timer[4] interrupt. +#define FTIMR_GT3 BIT(3) // Enable General Timer[3] interrupt. +#define FTIMR_GT2 BIT(2) // Enable General Timer[2] interrupt. +#define FTIMR_GT1 BIT(1) // Enable General Timer[1] interrupt. +#define FTIMR_GT0 BIT(0) // Enable General Timer[0] interrupt. + +//---------------------------------------------------------------------------- +// 8192C PKTBUF_DBG_CTRL bits (Offset 0x140-143, 32 bits) +//---------------------------------------------------------------------------- +#define RXPKTBUF_DBG BIT(14) // 1: Enable RXPKTBUF debug mode. +#define TXPKTBUF_DBG BIT(13) // 1: Enable TXPKTBUF debug mode. +#define PKTBUF_DBG_ADDR_SHIFT 0 // The address of TRXPKTBUF to be read. +#define PKTBUF_DBG_ADDR_Mask 0x01FFF + +// General Purpose Timer. (Offset 0x150 - 0x16Fh) +//---------------------------------------------------------------------------- +// 8192C TC0_CTRL bits (Offset 0x150-153, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C TC1_CTRL bits (Offset 0x154-157, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C TC2_CTRL bits (Offset 0x158-15B, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C TC3_CTRL bits (Offset 0x15C-15F, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C TC4_CTRL bits (Offset 0x160-163, 32 bits) +//---------------------------------------------------------------------------- +#define TCINT_EN BIT(26) // When write "1" to this bit, Counter starts counting down. +#define TCMODE BIT(25) // Timer/Counter mode. +#define TCEN BIT(24) // Timer/Counter enable. +#define TCData_SHIFT 0 // Timer/Counter data register. It specifies the time-out duration. +#define TCData_Mask 0x0FFFFFF + +//---------------------------------------------------------------------------- +// 8192C TCUNIT_BASE bits (Offset 0x164-165, 16 bits) +//---------------------------------------------------------------------------- +#define TCUNIT_BASE_TIME_SHIFT 0 // num of clocks that equals to the base time unit of timer/counter. +#define TCUNIT_BASE_TIME_Mask 0x03FFF +// General Purpose Timer. (Offset 0x150 - 0x16Fh) + +//---------------------------------------------------------------------------- +// 8192C MBIST_START bits (Offset 0x174-177, 32 bits) +//---------------------------------------------------------------------------- +#define TXLLT_BISTP BIT(10) // TXLLT BIST Start Pulse. +#define TXOQT_BISTP BIT(9) // TXOQT BIST Start Pulse. +#define TXPKT_BISTP BIT(8) // TXPKT Buffer BIST Start Pulse. +#define RXPKT_BISTP BIT(7) // RXPKT Buffer BIST Start Pulse. +#define TXDBUF_BISTP BIT(6) // TXDBUF BIST Start Pulse. +#define TXFIFO_BISTP BIT(5) // TXFIFO BIST Start Pulse. +#define RXFIFO_BISTP BIT(4) // RXFIFO BIST Start Pulse. +#define WKEYLLT_BISTP BIT(3) // WKEY BIST Start Pulse. +#define WRXBA_BISTP BIT(2) // WRXBA BIST Start Pulse. + +//---------------------------------------------------------------------------- +// 8192C MBIST_DONE bits (Offset 0x178-17B, 32 bits) +//---------------------------------------------------------------------------- +#define TXLLT_BISTD BIT(10) // TXLLT BIST Done. +#define TXOQT_BISTD BIT(9) // TXOQT BIST Done. +#define TXPKT_BISTD BIT(8) // TXPKT Buffer BIST Done. +#define RXPKT_BISTD BIT(7) // RXPKT Buffer BIST Done. +#define TXDBUF_BISTD BIT(6) // TXDBUF BIST Done. +#define TXFIFO_BISTD BIT(5) // TXFIFO BIST Done. +#define RXFIFO_BISTD BIT(4) // RXFIFO BIST Done. +#define WKEYLLT_BISTD BIT(3) // WKEY BIST Done. +#define WRXBA_BISTD BIT(2) // WRXBA BIST Done. + +//---------------------------------------------------------------------------- +// 8192C MBIST_FAIL bits (Offset 0x17C-17F, 32 bits) +//---------------------------------------------------------------------------- +#define TXLLT_BISTF BIT(10) // TXLLT BIST Fail. +#define TXOQT_BISTF BIT(9) // TXOQT BIST Fail. +#define TXPKT_BISTF BIT(8) // TXPKT Buffer BIST Fail. +#define RXPKT_BISTF BIT(7) // RXPKT Buffer BIST Fail. +#define TXDBUF_BISTF BIT(6) // TXDBUF BIST Fail. +#define TXFIFO_BISTF BIT(5) // TXFIFO BIST Fail. +#define RXFIFO_BISTF BIT(4) // RXFIFO BIST Fail. +#define WKEYLLT_BISTF BIT(3) // WKEY BIST Fail. +#define WRXBA_BISTF BIT(2) // WRXBA BIST Fail. + +//---------------------------------------------------------------------------- +// 8192C FMETHR bits (Offset 0x1C8-1CB, 32 bits) +//---------------------------------------------------------------------------- +#define FMSG_INT BIT(31) // Toggle this bit will generate interrupt to Host. +#define FW_MSG_SHIFT 0 // User Defined Message. +#define FW_MSG_Mask 0x07FFFFFFF + +//---------------------------------------------------------------------------- +// 8192C HMETFR bits (Offset 0x1CC-1CF, 32 bits) +//---------------------------------------------------------------------------- +#define HRCV_MSG_SHIFT 24 // User Defined Message. +#define HRCV_MSG_Mask 0x0FF +#define INT_BOX3 BIT(3) // MSG_BOX_3 Valid. Enable when the Entry is write. +#define INT_BOX2 BIT(2) // MSG_BOX_2 Valid. Enable when the Entry is write. +#define INT_BOX1 BIT(1) // MSG_BOX_1 Valid. Enable when the Entry is write. +#define INT_BOX0 BIT(0) // MSG_BOX_0 Valid. Enable when the Entry is write. + +//---------------------------------------------------------------------------- +// 8192C LLT_INI bits (Offset 0x1E0-1E3, 32 bits) +//---------------------------------------------------------------------------- +#define LLTE_RWM_SHIFT 30 // +#define LLTE_RWM_Mask 0x03 +#define LLTINI_PDATA_SHIFT 16 // LLT Entry Write/Read DATA for MCU. +#define LLTINI_PDATA_Mask 0x0FF +#define LLTINI_ADDR_SHIFT 8 // LLT Entry Access Offset. +#define LLTINI_ADDR_Mask 0x0FF +#define LLTINI_HDATA_SHIFT 0 // LLT Entry Write/Read DATA for HCI. +#define LLTINI_HDATA_Mask 0x0FF +// LLTE_RWM +#define LLTE_RWM_NO_ACTIVE 0x00 +#define LLTE_RWM_WR 0x01 +#define LLTE_RWM_RD 0x03 + +//---------------------------------------------------------------------------- +// 8192C BB_ACCEESS_CTRL bits (Offset 0x1E8-1EB, 32 bits) +//---------------------------------------------------------------------------- +#define BB_WRITE_READ_SHIFT 30 // +#define BB_WRITE_READ_Mask 0x03 +#define BB_WRITE_EN_SHIFT 12 // Byte Write Enable. +#define BB_WRITE_EN_Mask 0x0F +#define BB_ADDR_SHIFT 2 // Baseband Access Write/Read Address (in DW unit). +#define BB_ADDR_Mask 0x03FF +#define BB_ERRACC BIT(0) // Duplicate Access when previous cycle pending (write one clear). + + +// +// 3. TXDMA/RXDMA Configuration. (Offset 0x200 - 0x2FFh) +// +//---------------------------------------------------------------------------- +// 8192C RQPN bits (Offset 0x200-203, 32 bits) +//---------------------------------------------------------------------------- +#define LD_RQPN BIT(31) // Write 1 to set RQPN bit[79:0] value to page numbers for initialization. +#define LPQ_PUBLIC_DIS BIT(25) // bit=1, available Tx page size excludes the public queue. +#define HPQ_PUBLIC_DIS BIT(24) // bit=1, available Tx page size excludes the public queue. +#define PUBQ_SHIFT 16 // Public Reserved Page Number. +#define PUBQ_Mask 0x0FF +#define LPQ_SHIFT 8 // Low Priority Queue Reserved Page Number. +#define LPQ_Mask 0x0FF +#define HPQ_SHIFT 0 // High Priority Queue Reserved Page Number. +#define HPQ_Mask 0x0FF + +#define _HPQ(x) ((x) & HPQ_Mask) +#define _LPQ(x) (((x) & LPQ_Mask) << LPQ_SHIFT) +#define _PUBQ(x) (((x) & PUBQ_Mask) << PUBQ_SHIFT) +#define _NPQ(x) ((x) & 0xFF) // NOTE: in RQPN_NPQ register + + +//---------------------------------------------------------------------------- +// 8192C FIFOPAGE bits (Offset 0x204-207, 32 bits) +//---------------------------------------------------------------------------- +#define TXPKTNUM_SHIFT 24 // Packet number in TXPKTBUF. +#define TXPKTNUM_Mask 0x0FF +#define PUB_AVAL_PG_SHIFT 16 // Available Public Queue Page Number. +#define PUB_AVAL_PG_Mask 0x0FF +#define LPQ_AVAL_PG_SHIFT 8 // Available Low Priority Queue Page Number. +#define LPQ_AVAL_PG_Mask 0x0FF +#define HPQ_AVAL_PG_SHIFT 0 // Available High Priority Queue Page Number. +#define HPQ_AVAL_PG_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C TDECTRL bits (Offset 0x208-20B, 32 bits) +//---------------------------------------------------------------------------- +#define LLT_FREE_PAGE_SHIFT 24 // LLT Free Page. +#define LLT_FREE_PAGE_Mask 0x0FF +#define BCN_VALID BIT(16) // bit=1, beacon packet has finished to write to txpktbuffer. +#define BCN_HEAD_SHIFT 8 // head page of Bcnq packet which is Tx DMA filled. +#define BCN_HEAD_Mask 0x0FF +#define BLK_DESC_NUM_SHIFT 4 // The Most Number of Tx Descriptor per Bulk Out Only for USB. +#define BLK_DESC_NUM_Mask 0x0F + +//---------------------------------------------------------------------------- +// 8192C TXDMA_OFFSET_CHK bits (Offset 0x20C-20F, 32 bits) +//---------------------------------------------------------------------------- +#define PG_UNDER_TH_SHIFT 16 // Page threshold value is check by Tx DMA engine. +#define PG_UNDER_TH_Mask 0x0FF +#define CHK_PG_TH_EN BIT(10) // Enable Tx DMA to check total pages if it is under page threshold. +#define DROP_DATA_EN BIT(9) // Enable Tx DMA to drop the redundant data of packet. +#define CHECK_OFFSET_EN BIT(8) // Enable Tx DMA to check offset value. +#define CHECK_OFFSET_SHIFT 0 // Offset value is check by Tx DMA engine. +#define CHECK_OFFSET_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C TXDMA_STATUS bits (Offset 0x210-213, 32 bits) +//---------------------------------------------------------------------------- +#define PAYLOAD_UDN BIT(14) // Payload is under the packet length of Tx descriptor. +#define PAYLOAD_OVF BIT(13) // Payload is over the packet length of Tx descriptor. +#define DSC_CHKSUM_FAIL BIT(12) // Tx descriptor checksum error. +#define UNKNOWN_QSEL BIT(11) // An unknown QSEL of Tx descriptor is detected. +#define EP_QSEL_DIFF BIT(10) // Tx Endpoint is unmatched with the QSEL of descriptor. +#define TX_OFFS_UNMATCH BIT(9) // Tx offset is unmatched. +#define TXOQT_UDN BIT(8) // TXOQT Underflow. +#define TXOQT_OVF BIT(7) // TXOQT Overflow. +#define TXDMA_SFF_UDN BIT(6) // TXDMA Sync FIFO Underflow. +#define TXDMA_SFF_OVF BIT(5) // TXDMA Sync FIFO Overflow. +#define LLT_NULL_PG BIT(4) // TXDMA reads NULL page. +#define PAGE_UDN BIT(3) // Total pages included PTCL un-return pages under the total reserved pages. +#define PAGE_OVF BIT(2) // Total pages included PTCL un-return pages over the total reserved pages. +#define TXFF_PG_UDN BIT(1) // TXFF page underflow in TDE page controller. +#define TXFF_PG_OVF BIT(0) // TXFF page overflow in TDE page controller. + +//---------------------------------------------------------------------------- +// 8192C RXDMA_AGG_PG_TH bits (Offset 0x280-283, 32 bits) +//---------------------------------------------------------------------------- +#define RXDMA_AGG_PG_TH_LMT(x) ((x & 0x0FF)<<0) // DMA inform host to receive pkts, when exceeds the threshold. + +//---------------------------------------------------------------------------- +// 8192C RXPKT_NUM bits (Offset 0x284-287, 32 bits) +//---------------------------------------------------------------------------- +#define RXPKT_NUM_LMT_SHIFT 24 // number of packets in RXPKTBUF. +#define RXPKT_NUM_LMT_Mask 0x0FF +#define RW_RELEASE_EN BIT(18) // bit=1, RXDMA will enter this mode after RXDMA packet to host completed and stop. +#define RXDMA_IDLE BIT(17) // RXDMA finishes DMA will report idle state in this bit. +#define RXPKT_RELEASE_POLL BIT(16) // bit=1, RXDMA will decrease RX PKT counter by one. +#define FW_UPD_RDPTR_SHIFT 0 // FW updates before write RXPKT_RELEASE_POLL to 1. +#define FW_UPD_RDPTR_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C RXDMA_STATUS bits (Offset 0x288-28B, 32 bits) +//---------------------------------------------------------------------------- +#define FW_POLL_ISSUE BIT(5) // FW Release Poll Error. +#define RX_DATA_UDN BIT(4) // RX Data Underflow. Clear by SW. +#define RX_SFF_UDN BIT(3) // RX Sync FIFO Underflow. +#define RX_SFF_OVF BIT(2) // RX Sync FIFO Overflow. +#define USB_REQ_LEN_OVF BIT(1) // USB RXAGGEN Error due to RX length overflow. +#define RXPKT_OVF BIT(0) // When RX Packet is more than 255 packets remaining in FF. + + +// +// 4. PCIE EMAC Reserved Region. (Offset 0x300 - 0x3FFh) +// +//---------------------------------------------------------------------------- +// 8192C PCIE_CTRL_REG bits (Offset 0x300-303, 32 bits) +//---------------------------------------------------------------------------- +#define MAX_RXDMA_SHIFT 28 // RXDMA Burst Size selection. +#define MAX_RXDMA_Mask 0x07 +#define MAX_TXDMA_SHIFT 24 // TXDMA Burst Size selection. +#define MAX_TXDMA_Mask 0x07 +#define En_HWENTRL BIT(19) // Enable HW call EMAC to enter L23 actively. +#define EN_SWENTR_L23 BIT(17) // Enable SW call EMAC to enter L23. +#define EN_HWEXITL1 BIT(16) // Enable HW call EMAC to exit L1. +#define BCNQSTOP BIT(15) // BCNQ DMA STOP. +#define HQSTOP BIT(14) // HQ DMA STOP. +#define MGQSTOP BIT(13) // VOKQ DMA STOP. +#define VOQSTOP BIT(12) // VOKQ DMA STOP. +#define VIQSTOP BIT(11) // VIQ DMA STOP. +#define BEQSTOP BIT(10) // BEQ DMA STOP. +#define BKQSTOP BIT(9) // BKQ DMA STOP. +#define RXQSTOP BIT(8) // RX DMA STOP. +#define HQ_POLL BIT(7) // High Queue Polling bit, read result will be hpqflag. +#define MGQ_POLL BIT(6) // Manag Queue Polling bit, read result will be mgqflag. +#define BCNQ_POLL BIT(4) // BCNQ Polling bit, read result will be bpqflag. +#define VOQ_POLL BIT(3) // VOQ Polling bit, read result will be voqflag. +#define VIQ_POLL BIT(2) // VIQ Polling bit, read result will be viqflag. +#define BEQ_POLL BIT(1) // BEQ Polling bit, read result will be beqflag. +#define BKQ_POLL BIT(0) // BKQ Polling bit, read result will be bkqflag. + +//---------------------------------------------------------------------------- +// 8192C INT_MIG bits (Offset 0x304-307, 32 bits) +//---------------------------------------------------------------------------- +#define TTMRMIT_Shift 28 // 92D_REG, Tx timer mitigation +#define TTMRMIT_Mask 0x0F +#define TNUMMIT_Shift 24 // 92D_REG, Tx number mitigation +#define TNUMMIT_Mask 0x0F +#define RTMRMIT_Shift 20 // 92D_REG, Rx timer mitigation +#define RTMRMIT_Mask 0x0F +#define RNUMMIT_Shift 16 // 92D_REG, Rx number mitigation +#define RNUMMIT_Mask 0x0F +#define INTMT_SHIFT 16 // Interrupt Couter for setting Interrupt Migration. +#define INTMT_Mask 0x0FFFF +#define MIGRATE_TIMER_SHIFT 0 // Timer for setting Interrupt Migration. +#define MIGRATE_TIMER_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C DBI bits (Offset 0x348-353, 96 bits) +//---------------------------------------------------------------------------- +#define DBI_ACC_EXT BIT(19) // 92D_REG, DBI access external register on ELBI +#define DBI_MACSEL BIT(18) // 92D_REG, DBI access MAC1 select +#define DBI_RFLAG BIT(17) // DBI Read Flag. +#define DBI_WFLAG BIT(16) // DBI Write Flag. +#define DBI_WREN_SHIFT 12 // DBI Write Enable, High active. +#define DBI_WREN_Mask 0x0F +#define DBI_ADDR_SHIFT 0 // DBI Address. +#define DBI_ADDR_Mask 0x0FFF + +//----------------------------------------------------------------------------// +// 8192C MDIO bits (Offset 0x354-35B, 64 bits) +//---------------------------------------------------------------------------- +#define ECRC_EN BIT(7) // ECRC Enable. +#define MDIO_RFLAG BIT(6) // MDIO Read Flag. +#define MDIO_WFLAG BIT(5) // MDIO Write Flag. +#define MDIO_ADDR_SHIFT 0 // MDIO Address. +#define MDIO_ADDR_Mask 0x01F + +#define MDIO_RDATA_SHIFT 16 // MDIO Read Data. +#define MDIO_RDATA_Mask 0x0FFFF +#define MDIO_WDATA_SHIFT 0 // MDIO Write Data. +#define MDIO_WDATA_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C UART_CTRL bits (Offset 0x364-36B, 64 bits) +//---------------------------------------------------------------------------- +#define UART_WDATA_H_SHIFT 0 // UART Write Data [31:8], read will be UART Read Data[31:8]. +#define UART_WDATA_H_Mask 0x0FFFFFF + +#define UART_DMA_STS_SHIFT 24 // UART DMA Status. +#define UART_DMA_STS_Mask 0x07 +#define UART_DMA_MOD BIT(20) // UART DMA Mode. +#define UART_RDMA BIT(19) // UART RX DMA Flag. +#define UART_TDMA BIT(18) // UART TX DMA Flag. +#define UART_RCMD BIT(17) // UART Read Command. +#define UART_WCMD BIT(16) // UART Write Command. +#define UART_ADDR_SHIFT 10 // UART Address. +#define UART_ADDR_Mask 0x03F +#define UART_WDATA_L_SHIFT 0 // UART Write Data [7:0], read will be UART Read Data[7:0]. +#define UART_WDATA_L_Mask 0x0FF + + +// +// 5. PTCL/EDCA Configuration. (Offset 0x400 - 0x4FFh) +// +//---------------------------------------------------------------------------- +// 8192C VOQ_INFO bits (Offset 0x400-403, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C VIQ_INFO bits (Offset 0x404-407, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C BEQ_INFO bits (Offset 0x408-40B, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C BKQ_INFO bits (Offset 0x40C-40F, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C MGQ_INFO bits (Offset 0x410-413, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C HIQ_INFO bits (Offset 0x414-417, 32 bits) +//---------------------------------------------------------------------------- +#define Q_CPU_HEAD_SHIFT 24 // MCU will handle q_pkt head. +#define Q_CPU_HEAD_Mask 0x0FF +#define Q_PKT_NUM_SHIFT 16 // total Q pkt number in TxPktbuffer. +#define Q_PKT_NUM_Mask 0x0FF +#define Q_FW_NUM_SHIFT 8 // total Q FW number in TxPktbuffer. +#define Q_FW_NUM_Mask 0x0FF +#define Q_HEAD_PG_SHIFT 0 // head page of the first packet of Q. +#define Q_HEAD_PG_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C BCNQ_INFO bits (Offset 0x418-41A, 24 bits) +//---------------------------------------------------------------------------- +#define BCNQ_PKT_NUM_SHIFT 16 // total BCNQ pkt number in TxPktbuffer. +#define BCNQ_PKT_NUM_Mask 0x0FF +#define BCNQ_FW_NUM_SHIFT 8 // total BCNQ FW number in TxPktbuffer. +#define BCNQ_FW_NUM_Mask 0x0FF +#define BCNQ_HEAD_PG_SHIFT 0 // head page of the first packet of BCNQ. +#define BCNQ_HEAD_PG_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C TXPKT_EMPTY bits (Offset 0x41B, 8 bits) +//---------------------------------------------------------------------------- +#define BCNQ_EMPTY BIT(7) // queue is empty. Report by MAC. +#define HQQ_EMPTY BIT(6) // queue is empty. Report by MAC. +#define HMGQ_EMPTY BIT(5) // queue is empty. Report by MAC. +#define CMGQ_EMPTY BIT(4) // queue is empty. Report by MAC. +#define BKQ_EMPTY BIT(3) // queue is empty. Report by MAC. +#define BEQ_EMPTY BIT(2) // queue is empty. Report by MAC. +#define VIQ_EMPTY BIT(1) // queue is empty. Report by MAC. +#define VOQ_EMPTY BIT(0) // queue is empty. Report by MAC. + +//---------------------------------------------------------------------------- +// 8192C CPU_MGQ_INFO bits (Offset 0x41C-41F, 32 bits) +//---------------------------------------------------------------------------- +#define CPUMGQ_FW_NUM_SHIFT 8 // total CPU MGQ fw number in TxPktbuffer. +#define CPUMGQ_FW_NUM_Mask 0x0FF +#define CPUMGQ_HEAD_PG_SHIFT 0 // head page of CPU MGQ. +#define CPUMGQ_HEAD_PG_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C FWHW_TXQ_CTRL bits (Offset 0x420-422, 24 bits) +//---------------------------------------------------------------------------- +#define RTS_LIMIT_IN_OFDM BIT(23) // 92D_REG, rts rate will not down to cck rate +#define EN_BCNQ_DL BIT(22) // 92D_REG, 1: ptcl consider there is bcn pkt in txbuf; 0: mask bcn pkt num in bcnq +#define EN_RD_RESP_NAV_BK BIT(21) // Control the RD responder NAV criteria for TX. +#define EN_WR_FREE_TAIL BIT(20) // 1:Drive wirte Bcnq_boundary,Hw set free_tail in Boundary-1; 0:no update. +#define CHK_LOSS_QSEL_SHIFT 17 // +#define CHK_LOSS_QSEL_Mask 0x07 +#define EN_CHECK_LOSS BIT(16) // bit=1, HW will monitor packet loss from TXDMA. +#define EN_QUEUE_RPT_SHIFT 8 // 1: HW will report tx_status 0: no report. +#define EN_QUEUE_RPT_Mask 0x07F +#define EN_AMPDU_RTY_NEW BIT(7) // AMPDU aggregation mode with retry MPDUs and new MPDUs. +#define LIFETIME_EN BIT(6) // Enable lift time drop. +#define EN_CPU_HANDLE_SHIFT 0 // PKT need cpu handle. +#define EN_CPU_HANDLE_Mask 0x03F + +//---------------------------------------------------------------------------- +// 8192C HWSEQ_CTRL bits (Offset 0x423, 8 bits) +//---------------------------------------------------------------------------- +#define HWSEQ_BCN_EN BIT(6) // +#define HWSEQ_HI_EN BIT(5) // +#define HWSEQ_MGT_EN BIT(4) // +#define HWSEQ_BK_EN BIT(3) // +#define HWSEQ_BE_EN BIT(2) // +#define HWSEQ_VI_EN BIT(1) // +#define HWSEQ_VO_EN BIT(0) // + +//---------------------------------------------------------------------------- +// 8192C MULTI_BCNQ_EN bits (Offset 0x426, 8 bits) +//---------------------------------------------------------------------------- +#define MBID_BCNQ7_EN BIT(7) // +#define MBID_BCNQ6_EN BIT(6) // +#define MBID_BCNQ5_EN BIT(5) // +#define MBID_BCNQ4_EN BIT(4) // +#define MBID_BCNQ3_EN BIT(3) // +#define MBID_BCNQ2_EN BIT(2) // +#define MBID_BCNQ1_EN BIT(1) // +#define MBID_BCNQ0_EN BIT(0) // + +//---------------------------------------------------------------------------- +// 8192C MULTI_BCNQ_OFFSET bits (Offset 0x427, 8 bits) +//---------------------------------------------------------------------------- +#define MBCNQ_OFFSET_SHIFT 0 // page number between two consecutive BCNQ head page. +#define MBCNQ_OFFSET_Mask 0x03 + +//---------------------------------------------------------------------------- +// 8192C SPEC_SIFS bits (Offset 0x428-429, 16 bits) +//---------------------------------------------------------------------------- +#define SPEC_SIFS_OFDM_SHIFT 8 // spec SIFS value for duration calculation. +#define SPEC_SIFS_OFDM_Mask 0x0FF +#define SPEC_SIFS_CCK_SHIFT 0 // spec SIFS value for duration calculation. +#define SPEC_SIFS_CCK_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C RL bits (Offset 0x42A-42B, 16 bits) +//---------------------------------------------------------------------------- +#define SRL_SHIFT 8 // Short Retry Limit. +#define SRL_Mask 0x03F +#define LRL_SHIFT 0 // Long Retry Limit. +#define LRL_Mask 0x03F + +//---------------------------------------------------------------------------- +// 8192C DARFRC bits (Offset 0x430-437, 64 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C RARFRC bits (Offset 0x438-43F, 64 bits) +//---------------------------------------------------------------------------- +#define ARF_RC8_SHIFT 24 // Response Auto Rate Fallback Retry Count. +#define ARF_RC8_Mask 0x01F +#define ARF_RC7_SHIFT 16 // Response Auto Rate Fallback Retry Count. +#define ARF_RC7_Mask 0x01F +#define ARF_RC6_SHIFT 8 // Response Auto Rate Fallback Retry Count. +#define ARF_RC6_Mask 0x01F +#define ARF_RC5_SHIFT 0 // Response Auto Rate Fallback Retry Count. +#define ARF_RC5_Mask 0x01F + +#define ARF_RC4_SHIFT 24 // Response Auto Rate Fallback Retry Count. +#define ARF_RC4_Mask 0x01F +#define ARF_RC3_SHIFT 16 // Response Auto Rate Fallback Retry Count. +#define ARF_RC3_Mask 0x01F +#define ARF_RC2_SHIFT 8 // Response Auto Rate Fallback Retry Count. +#define ARF_RC2_Mask 0x01F +#define ARF_RC1_SHIFT 0 // Response Auto Rate Fallback Retry Count. +#define ARF_RC1_Mask 0x01F + +//---------------------------------------------------------------------------- +// 8192C RRSR bits (Offset 0x440-442, 24 bits) +//---------------------------------------------------------------------------- +#define RRSR_SHORT BIT(23) // Respond with short preamble packet. Default is long preamble. +#define RRSR_RSC_SHIFT 21 // Response frame sub-channel configuration. +#define RRSR_RSC_Mask 0x03 +#define RRSC_BITMAP_SHIFT 0 // Response Auto Rate Fallback Retry Count. +#define RRSC_BITMAP_Mask 0x0FFFFF + +//---------------------------------------------------------------------------- +// 8192C AGGLEN_LMT bits (Offset 0x458-45B, 32 bits) +//---------------------------------------------------------------------------- +#define AGGLMT_MCS15S_SHIFT 28 // Aggregation Limit for MCS 15 SGI in the units of number of MPDUs. +#define AGGLMT_MCS15S_Mask 0x0F +#define AGGLMT_MCS15_SHIFT 24 // Aggregation Limit for MCS 13~15 in the units of number of MPDUs. +#define AGGLMT_MCS15_Mask 0x0F +#define AGGLMT_MCS12_SHIFT 20 // Aggregation Limit for MCS 11~12 in the units of number of MPDUs. +#define AGGLMT_MCS12_Mask 0x0F +#define AGGLMT_MCS10_SHIFT 16 // Aggregation Limit for MCS 8~10 in the units of number of MPDUs. +#define AGGLMT_MCS10_Mask 0x0F +#define AGGLMT_MCS7S_SHIFT 12 // Aggregation Limit for MCS 7 SGI in the units of number of MPDUs. +#define AGGLMT_MCS7S_Mask 0x0F +#define AGGLMT_MCS7_SHIFT 8 // Aggregation Limit for MCS 6~7 in the units of number of MPDUs. +#define AGGLMT_MCS7_Mask 0x0F +#define AGGLMT_MCS5_SHIFT 4 // Aggregation Limit for MCS 3~5 in the units of number of MPDUs. +#define AGGLMT_MCS5_Mask 0x0F +#define AGGLMT_MCS2_SHIFT 0 // Aggregation Limit for MCS 0~2 in the units of number of MPDUs. +#define AGGLMT_MCS2_Mask 0x0F + +//---------------------------------------------------------------------------- +// 8192C AMPDU_MIN_SPACE bits (Offset 0x45C, 8 bits) +//---------------------------------------------------------------------------- +#define MIN_SPACE_SHIFT 0 // The spacing between sub-frame. +#define MIN_SPACE_Mask 0x07 + +//---------------------------------------------------------------------------- +// 8192C FAST_EDCA_CTRL bits (Offset 0x460-462, 24 bits) +//---------------------------------------------------------------------------- +#define FAST_EDCA_TO_SHIFT 16 // If pkt timeout, HW will contend channel using fast backoff. +#define FAST_EDCA_TO_Mask 0x01F +#define FAST_EDCA_PKT_TH_SHIFT 0 // If pkt in txpktbuffer over thrs. HW will fast backoff. +#define FAST_EDCA_PKT_TH_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C RD_RESP_PKT_TH bits (Offset 0x463, 8 bits) +//---------------------------------------------------------------------------- +#define RD_RESP_PKT_TH_LMT_SHIFT 0 // granted ACq pkt num beyond this, responder set More PPDU=1 & piggyback. +#define RD_RESP_PKT_TH_LMT_Mask 0x01F + +//---------------------------------------------------------------------------- +// 8192C INIRTS_RATE_SEL bits (Offset 0x480, 8 bits) +//---------------------------------------------------------------------------- +#define INIRTSMCS_SEL_SHIFT 0 // initial rate for Control type frame transmitted as EDCA originator. +#define INIRTSMCS_SEL_Mask 0x03F + +//---------------------------------------------------------------------------- +// 8192C POWER_STAGE1 bits (Offset 0x4B4-4B6, 24 bits) +//---------------------------------------------------------------------------- +#define PWR_STAGE1_SHIFT 0 // User define Power Stage1. +#define PWR_STAGE1_Mask 0x0FFFFFF + +//---------------------------------------------------------------------------- +// 8192C POWER_STAGE2 bits (Offset 0x4B8-4BA, 24 bits) +//---------------------------------------------------------------------------- +#define PWR_STAGE2_SHIFT 0 // User define Power Stage2. +#define PWR_STAGE2_Mask 0x0FFFFFF + +//---------------------------------------------------------------------------- +// 8192C STBC_SETTING bits (Offset 0x4C4, 8 bits) +//---------------------------------------------------------------------------- +#define NESS_SHIFT 2 // +#define NESS_Mask 0x03 +#define STBC_CFEND_SHIFT 0 // CFEND STBC. +#define STBC_CFEND_Mask 0x03 + +//---------------------------------------------------------------------------- +// 8192C PROT_MODE_CTRL bits (Offset 0x4C8-4C9, 16 bits) +//---------------------------------------------------------------------------- +#define RTS_TXTIME_TH_SHIFT 8 // RTS pkt txtime thrs +#define RTS_TXTIME_TH_Mask 0x0FF +#define RTS_LEN_TH_SHIFT 0 // RTS Length thrs. +#define RTS_LEN_TH_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C BAR_MODE_CTRL bits (Offset 0x4CC-4CE, 24 bits) +//---------------------------------------------------------------------------- +#define BAR_RTY_LMT_SHIFT 16 // BAR retry limit. +#define BAR_RTY_LMT_Mask 0x03 +#define BAR_PKT_TXTIME_TH_SHIFT 8 // BAR pkt txtime thrs. +#define BAR_PKT_TXTIME_TH_Mask 0x0FF +#define BAR_PKTNUM_TH_SHIFT 0 // BAR Pktnum Thrs. +#define BAR_PKTNUM_TH_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C RA_TRY_RATE_AGG_LMT bits (Offset 0x4CF, 8 bits) +//---------------------------------------------------------------------------- +#define RA_BAR_RTY_LMT_SHIFT 5 // BAR retry limit. +#define RA_BAR_RTY_LMT_Mask 0x07 +#define RA_TRY_RATE_AGG_LMT_NUM_SHIFT 0 // aggr pkt num limit for try up rate of when desc try bit=1. +#define RA_TRY_RATE_AGG_LMT_NUM_Mask 0x01F + +//---------------------------------------------------------------------------- +// 8192C NQOS_SEQ bits (Offset 0x4DC-4DD, 16 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C QOS_SEQ bits (Offset 0x4DE-4DF, 16 bits) +//---------------------------------------------------------------------------- +#define N_QOS_SSN_SHIFT 0 // TXDESC HWSEQEN is set, MAC will overwrite SEQ control by this. + // TXDESC HWSEQEN is set and QoS field is also set, + // MAC will overwrite SEQ control by this. +#define N_QOS_SSN_Mask 0x0FFF + +//---------------------------------------------------------------------------- +// 8192C NEED_CPU_HANDLE bits (Offset 0x4E0, 8 bits) +//---------------------------------------------------------------------------- +#define NEED_CPU_HANDLE_Q_SHIFT 0 // 1:HW prepare ok, this q need cpu handle & poll. +#define NEED_CPU_HANDLE_Q_Mask 0x03F + +//---------------------------------------------------------------------------- +// 8192C PTCL_ERR_STATUS bits (Offset 0x4E1, 8 bits) +//---------------------------------------------------------------------------- +#define PTCL_TL_PG_OVF BIT(7) // Protocol Total Page out of range. +#define TXHANG_ERR BIT(5) // TX time is greater than 32ms. +#define HW_RD_NULL_STATUS_ERR BIT(4) // HW read null page counter error. +#define HW_RD_NULL_CTN_ERR BIT(3) // HW Contention read null page counter error. +#define HW_RD_NULL_CNT_ERR BIT(2) // HW read null page counter error. +#define PTCL_TL_PG_ERR BIT(1) // Protocol Total page number error. +#define DESC_QSEL_ERR BIT(0) // TXDESC QSEL field mismatch error. + +//---------------------------------------------------------------------------- +// 8192C PKT_LOSE_RPT bits (Offset 0x4E2, 8 bits) +//---------------------------------------------------------------------------- +#define PKT_LOSE_BK BIT(3) // 1:queue happen pkt lose, 0:no lose. +#define PKT_LOSE_BE BIT(2) // 1:queue happen pkt lose, 0:no lose. +#define PKT_LOSE_VI BIT(1) // 1:queue happen pkt lose, 0:no lose. +#define PKT_LOSE_VO BIT(0) // 1:queue happen pkt lose, 0:no lose. + + +//---------------------------------------------------------------------------- +// 8192C EDCA_VO_PARA bits (Offset 0x500-503, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C EDCA_VI_PARA bits (Offset 0x504-507, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C EDCA_BE_PARA bits (Offset 0x508-50B, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C EDCA_BK_PARA bits (Offset 0x50C-50F, 32 bits) +//---------------------------------------------------------------------------- +#define TXOP_SHIFT 16 // TXOP Limit. +#define TXOP_Mask 0x0FFFF +#define CW_SHIFT 8 // ECWmax/ECWmin +#define CW_Mask 0x0FF +#define AIFS_SHIFT 0 // Arbitrary Inter frame space. +#define AIFS_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C BCNTCFG bits (Offset 0x510-511, 16 bits) +//---------------------------------------------------------------------------- +#define BCNECW_SHIFT 8 // Beacon Contention Window. +#define BCNECW_Mask 0x0F +#define BCNIFS_SHIFT 0 // Beacon Interframe Space. +#define BCNIFS_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C SIFS_CCK bits (Offset 0x514-515, 16 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C SIFS_OFDM bits (Offset 0x516-517, 16 bits) +//---------------------------------------------------------------------------- +#define SIFS_TRX_SHIFT 8 // SIFS time required for any immediate response. +#define SIFS_TRX_Mask 0x0FF +#define SIFS_CTX_SHIFT 0 // SIFS time required for consecutive TX events. +#define SIFS_CTX_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C TX_PTCL_CTRL bits (Offset 0x520-521, 16 bits) +//---------------------------------------------------------------------------- +#define DIS_CCA BIT(15) // bit=1, disable CCA. +#define SIFS_BK_EN BIT(12) // SIFS Break Check Criteria enable for AMPDU aggregation. +#define TXQ_NAV_MSK_SHIFT 8 // 1:Queue BKF must wait TX Nav finished, 0:Queue not need wait. +#define TXQ_NAV_MSK_Mask 0x0F +#define DIS_CW BIT(7) // bit=1, disable CW. +#define RDG_END_TXOP BIT(6) // 1:Nav protect all txop, 0:Nav protect to next pkt. +#define NAV_END_TXOP BIT(5) // 1:Nav protect all txop, 0:Nav protect to next pkt. +#define AC_INBCN_HOLD BIT(4) // bit=1, HI queue will be sent first, and then AC queue will be sent. +#define MGTQ_TXOP_EN BIT(3) // bit=1, MGTQ may sent packets by using ACQ TXOP. +#define MGTQ_RTSMF_HOLD BIT(2) // bit=1, MGTQ will be hold until RTS or MF transaction finished. +#define HIQ_RTSMF_HOLD BIT(1) // bit=1, HIQ will be hold until RTS or MF transaction finished. +#define BCN_RTSMF_HOLD BIT(0) // bit=1, BCNQ will be hold until RTS or MF transaction finished. + +//---------------------------------------------------------------------------- +// 8192C TXPAUSE bits (Offset 0x522, 8 bits) +//---------------------------------------------------------------------------- +#define STOP_BCN BIT(6) // Stop BCNQ Queue. +#define STOP_HI BIT(5) // Stop High Queue. +#define STOP_MGT BIT(4) // Stop Management Queue. +#define STOP_BK BIT(3) // Stop BK Queue. +#define STOP_BE BIT(2) // Stop BE Queue. +#define STOP_VI BIT(1) // Stop VI Queue. +#define STOP_VO BIT(0) // Stop VO Queue. + +//---------------------------------------------------------------------------- +// 8192C DIS_TXREQ_CLR bits (Offset 0x523, 8 bits) +//---------------------------------------------------------------------------- +#define DIS_TXREQ_CLR_BCN BIT(7) // 1:if queue can't own channel ,txcmd will be cleared;0:Only TX_finish can clear txreq. +#define DIS_TXREQ_CLR_HI BIT(5) // 1:if queue can't own channel ,txcmd will be cleared;0:Only TX_finish can clear txreq. +#define DIS_TXREQ_CLR_MGQ BIT(4) // 1:if queue can't own channel ,txcmd will be cleared;0:Only TX_finish can clear txreq. +#define DIS_TXREQ_CLR_VO BIT(3) // 1:if queue can't own channel ,txcmd will be cleared;0:Only TX_finish can clear txreq. +#define DIS_TXREQ_CLR_VI BIT(2) // 1:if queue can't own channel ,txcmd will be cleared;0:Only TX_finish can clear txreq. +#define DIS_TXREQ_CLR_BE BIT(1) // 1:if queue can't own channel ,txcmd will be cleared;0:Only TX_finish can clear txreq. +#define DIS_TXREQ_CLR_BK BIT(0) // 1:if queue can't own channel ,txcmd will be cleared;0:Only TX_finish can clear txreq. + +//---------------------------------------------------------------------------- +// 8192C RD_CTRL bits (Offset 0x524-525, 16 bits) +//---------------------------------------------------------------------------- +#define HIQ_NO_LMT_EN BIT(12) +#define EDCCA_MSK_CNTDWN BIT(11) // 1: disable, 0: enable, EDCCA count down. +#define DIS_TXOP_CFE BIT(10) // Disable TXOP_CFE function. +#define DIS_LSIG_CFE BIT(9) // Disable LSIG_TXOP CF-END function. +#define DIS_STBC_CFE BIT(8) // Disable STBC CF-END function. +#define BKQ_RD_INIT_EN BIT(7) // +#define BEQ_RD_INIT_EN BIT(6) // +#define VIQ_RD_INIT_EN BIT(5) // +#define VOQ_RD_INIT_EN BIT(4) // +#define BKQ_RD_RESP_EN BIT(3) // +#define BEQ_RD_RESP_EN BIT(2) // +#define VIQ_RD_RESP_EN BIT(1) // +#define VOQ_RD_RESP_EN BIT(0) // + +//---------------------------------------------------------------------------- +// 8192C TBTT_PROHIBIT bits (Offset 0x540-541, 16 bits) +//---------------------------------------------------------------------------- +#define TBTT_HOLD_TIME_SHIFT 8 // TBTT_prohibit_hold, unit is 32 us. +#define TBTT_HOLD_TIME_Mask 0xFFFFFF +#define TBTT_PROHIBIT_SETUP_SHIFT 0 // TBTT_prohibit_setup, unit is 32us. +#define TBTT_PROHIBIT_SETUP_Mask 0x0F + +//---------------------------------------------------------------------------- +// 8192C BCN_CTRL bits (Offset 0x550, 8 bits) +//---------------------------------------------------------------------------- + +#define DIS_SUB_STATE BIT(4) +#define DIS_SUB_STATE_N BIT(1) +#define DIS_TSF_UPDATE BIT(5) +#define DIS_TSF_UPDATE_N BIT(4) +#define DIS_ATIM BIT(0) + + +#define BCN0_AUTO_SYNC BIT(5) // When this bit is set, TSFTR will update the timestamp in Beacon matched BSSID. +#define DIS_TSF_UPT BIT(4) // 92D_REG, When this bit is set, tsf will not update +#define EN_BCN_FUNCTION BIT(3) // bit=1, TSF and other beacon related functions are then enabled. +#define EN_TXBCN_RPT BIT(2) // +#define EN_MBSSID BIT(1) // +#define PBCNQSEL BIT(0) // + +//---------------------------------------------------------------------------- +// 8192C USTIME_TSF bits (Offset 0x551, 8 bits) +//---------------------------------------------------------------------------- +#define USTIME_TSF_TIME_SHIFT 0 // Set the microsecond time unit used by MAC TSF clock. +#define USTIME_TSF_TIME_Mask 0x03F + +//---------------------------------------------------------------------------- +// 8192C MBID_NUM bits (Offset 0x552, 8 bits) +//---------------------------------------------------------------------------- +#define MBID_BCN_NUM_SHIFT 0 // num of virtual interface num excluding the root. +#define MBID_BCN_NUM_Mask 0x07 + +//---------------------------------------------------------------------------- +// 8192C MBSSID_BCN_SPACE bits (Offset 0x554-557, 32 bits) +//---------------------------------------------------------------------------- +#define BCN_SPACE2_SHIFT 16 // +#define BCN_SPACE2_Mask 0x0FFFF +#define BCN_SPACE1_SHIFT 0 // +#define BCN_SPACE1_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C ACMHWCTRL bits (Offset 0x5C0, 8 bits) +//---------------------------------------------------------------------------- +#define VOQ_ACM_STATUS BIT(6) // indicates if the used_time >= admitted_time of AC VO when HW ACM. +#define VIQ_ACM_STATUS BIT(5) // indicates if the used_time >= admitted_time of AC VI when HW ACM. +#define BEQ_ACM_STATUS BIT(4) // indicates if the used_time >= admitted_time of AC BE when HW ACM. +#define VOQ_ACM_EN BIT(3) // enable ACM of VO queue. +#define VIQ_ACM_EN BIT(2) // enable ACM of VI queue. +#define BEQ_ACM_EN BIT(1) // enable ACM of BE queue. +#define ACMHWEN BIT(0) // enable hardware to take control of ACM. + +//---------------------------------------------------------------------------- +// 8192C ACMRSTCTRL bits (Offset 0x5C1, 8 bits) +//---------------------------------------------------------------------------- +#define VO_ACM_RST_USED_TIME BIT(2) // HwEn enabled, sw set this to inform hw to reset used_time. +#define BE_ACM_RST_USED_TIME BIT(1) // HwEn enabled, sw set this to inform hw to reset used_time. +#define VI_ACM_RST_USED_TIME BIT(0) // HwEn enabled, sw set this to inform hw to reset used_time. + + +// +// 6. WMAC Configuration. (Offset 0x600 - 0x7FFh) +// +//---------------------------------------------------------------------------- +// 8192C APSD_CTRL bits (Offset 0x600, 8 bits) +//---------------------------------------------------------------------------- +#define APSDOFF_STATUS BIT(7) // +#define APSDOFF BIT(6) // bit=1, MAC issue sleep signal to disable BB/AFE/RF TRX function. + +//---------------------------------------------------------------------------- +// 8192C BWOPMODE bits (Offset 0x603, 8 bits) +//---------------------------------------------------------------------------- +#define BW_20M BIT(2) // bit=1 indicate operating in 20Mhz bandwidth. + +//---------------------------------------------------------------------------- +// 8192C TCR bits (Offset 0x604-607, 32 bits) +//---------------------------------------------------------------------------- +#define TSFT_CMP_SHIFT 16 // TSFT insertion compensation value. +#define TSFT_CMP_Mask 0x0FF +#define WMAC_TCR_ERRSTEN3 BIT(15) // 92D_REG, Use phytxend_ps to reset mactx state machine +#define WMAC_TCR_ERRSTEN2 BIT(14) // 92D_REG, If txd fifo underflow when txtype is cmpba, reset mactx state machine +#define WMAC_TCR_ERRSTEN1 BIT(13) // 92D_REG, If txd fifo underflow, reset mactx state machine +#define WMAC_TCR_ERRSTEN0 BIT(12) // 92D_REG, Phytxend_ps comes but mactx still active, reset mactx state machine +#define WMAC_TCR_TXSK_PERPKT BIT(11) // 92D_REG, Serche key for each mpdu +#define ICV BIT(10) // Integrity Check Value. +#define CFE_FORM BIT(9) // CF-End Frame Format. +#define CRC BIT(8) // Append 32-bit Cyclic Redundancy Check. +#define PWRBIT_OW_EN BIT(7) // bit=1, MAC overwrite pwr bit according to PWR_ST for data frame. +#define PWR_ST BIT(6) // MAC will overwrite pwr bit accroding to PWR_ST for data frame. +#define PAD_SEL BIT(2) // AMPDU Padding pattern selection. +#define DIS_GCLK BIT(1) // Disable MACTX clock gating control. +#define TSFRST BIT(0) // Reset TSF Timer to zero. + +//---------------------------------------------------------------------------- +// 8192C RCR bits (Offset 0x608-60B, 32 bits) +//---------------------------------------------------------------------------- +#define RCR_APP_FCS BIT(31) // wmac RX will append FCS after payload. +#define RCR_APP_MIC BIT(30) // bit=1, MACRX will retain the MIC at the bottom of the packet. +#define RCR_APP_ICV BIT(29) // bit=1, MACRX will retain the ICV at the bottom of the packet. +#define RCR_APP_PHYSTS BIT(28) // Append RXFF0 PHY Status Enable. +#define RCR_APP_BASSN BIT(27) // Append SSN of previous TXBA Enable. +#define RCR_MBID_EN BIT(24) // Enable Multiple BssId. +#define RCR_LSIGEN BIT(23) // Enable LSIG TXOP Protection function. +#define RCR_MFBEN BIT(22) // Enable immediate MCS Feedback function. +#define RCR_BM_DATA_EN BIT(17) // BM_DATA_EN. +#define RCR_UC_DATA_EN BIT(16) // Unicast data packet interrupt enable. +#define RCR_HTC_LOC_CTRL BIT(14) // 1: HTC -> MFC, 0: MFC-> HTC. +#define RCR_AMF BIT(13) // Accept Management Frame. +#define RCR_ACF BIT(12) // Accept Control Frame. +#define RCR_ADF BIT(11) // Accept Data Frame. +#define RCR_AICV BIT(9) // Accept Integrity Check Value Error packets. +#define RCR_ACRC32 BIT(8) // Accept CRC32 Error packets. + +#define RCR_CBSSID_ADHOC (BIT(6)|BIT(7)) // Check BSSID. +#define RCR_CBSSID BIT(6) // Check BSSID. +#define RCR_APWRMGT BIT(5) // Accept Power Management Packet. +#define RCR_ADD3 BIT(4) // Accept Address 3 Match Packets. +#define RCR_AB BIT(3) // Accept Broadcast packets. +#define RCR_AM BIT(2) // Accept Multicast packets. +#define RCR_APM BIT(1) // Accept Physical Match packets. +#define RCR_AAP BIT(0) // Accept Destination Address packets. + +//---------------------------------------------------------------------------- +// 8192C RX_PKT_LIMIT bits (Offset 0x60C, 8 bits) +//---------------------------------------------------------------------------- +#define RXPKTLMT_SHIFT 0 // RX PKT Upper Limit. +#define RXPKTLMT_Mask 0x03F + +// MACID Setting Register. (Offset 0x610 - 0x62Fh) +//---------------------------------------------------------------------------- +// 8192C MBIDCAMCFG bits (Offset 0x628-62F, 64 bits) +//---------------------------------------------------------------------------- +#define MBIDCAM_POLL BIT(31) // Pooling bit. +#define MBIDWRITE_EN BIT(30) // Write Enable. +#define MBIDCAM_ADDR_SHIFT 24 // CAM Address. +#define MBIDCAM_ADDR_Mask 0x01F +#define MBIDCAM_VALID BIT(23) // CAM Valid bit. + +// MACID Setting Register. (Offset 0x610 - 0x62Fh) + +// Timing Control Register. (Offset 0x630 - 0x64Fh) +//---------------------------------------------------------------------------- +// 8192C SPEC_SIFS bits (Offset 0x63A-63B, 16 bits) +//---------------------------------------------------------------------------- +#define SPEC_SIFS_OFDM_SHIFT 8 // SIFS value for duration calculation. +#define SPEC_SIFS_OFDM_Mask 0x0FF +#define SPEC_SIFS_CCK_SHIFT 0 // SIFS value for duration calculation. +#define SPEC_SIFS_CCK_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C RESP_SIFS_CCK bits (Offset 0x63C-63D, 16 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192C RESP_SIFS_OFDM bits (Offset 0x63E-63F, 16 bits) +//---------------------------------------------------------------------------- +#define SIFS_R2T_SHIFT 8 // SIFS time required for any immediate response. +#define SIFS_R2T_Mask 0x0FF +#define SIFS_T2T_SHIFT 0 // SIFS time required for consecutive TX events. +#define SIFS_T2T_Mask 0x0FF + +// Timing Control Register. (Offset 0x630 - 0x64Fh) + +// WMAC, BA, CCX Related Register. (Offset 0x650 - 0x66Fh) +//---------------------------------------------------------------------------- +// 8192C NAV_CTRL bits (Offset 0x650-651, 16 bits) +//---------------------------------------------------------------------------- +#define NAV_UPPER_SHIFT 8 // When NAV update is beyond this, then update is aborted. +#define NAV_UPPER_Mask 0x0FF +#define RTSRST_SHIFT 0 // RTS NAV Reset Time. +#define RTSRST_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C BACAMCMD bits (Offset 0x654-657, 32 bits) +//---------------------------------------------------------------------------- +#define BACAM_POLL BIT(31) // Polling bit BA CAM. +#define BACAM_RST BIT(17) // 1 to reset BA CAM. HW set invalid bit for all entries. +#define BACAM_RW BIT(16) // 1=Write, 0=Read. +#define BACAM_ADDR_SHIFT 0 // BA CAM address. Memory is double-word access. +#define BACAM_ADDR_Mask 0x03F + +//---------------------------------------------------------------------------- +// 8192C LBDLY bits (Offset 0x660, 8 bits) +//---------------------------------------------------------------------------- +#define LBDLY_LMT_SHIFT 0 // Loopback Delay. +#define LBDLY_LMT_Mask 0x01F + +//---------------------------------------------------------------------------- +// 8192C FWDLY bits (Offset 0x661, 8 bits) +//---------------------------------------------------------------------------- +#define FWDLY_LMT_SHIFT 0 // Firmware Delay. +#define FWDLY_LMT_Mask 0x0F + +//---------------------------------------------------------------------------- +// 8192C RXERR_RPT bits (Offset 0x664-667, 32 bits) +//---------------------------------------------------------------------------- +#define RXERR_RPT_SEL_SHIFT 28 // +#define RXERR_RPT_SEL_Mask 0x0F +#define RXERR_RPT_RST BIT(27) // Write "one" to set the counter to zero. +#define RPT_COUNTER_SHIFT 0 // reported value corresponding to Report type selected. +#define RPT_COUNTER_Mask 0x0FFFFF + +//---------------------------------------------------------------------------- +// 8192C WMAC_TRXPTCL_CTL bits (Offset 0x668-66F, 64 bits) +//---------------------------------------------------------------------------- +#define ACKBA_TYPSEL_SHIFT 28 // Determine response type for RX BA. +#define ACKBA_TYPSEL_Mask 0x0F +#define ACKBA_ACKPCHK_SHIFT 24 // +#define ACKBA_ACKPCHK_Mask 0x0F +#define ACKBAR_ACKPCHK_SHIFT 12 // +#define ACKBAR_ACKPCHK_Mask 0x0F +#define DIS_TXBA_AMPDUFCSERR BIT(4) // Disable to send BA for responding RX AMPDU with FCS error subframe. +#define DIS_TXBA_RXBARINFULL BIT(3) // Disable send BA for responding RX control wrapper BAR dropped by rxpkbuffer full. +#define DIS_TXCFE_INFULL BIT(2) // Disable send CFE for responding RX control wrapper CFE dropped by rxpktbuffer full. +#define DIS_TXCTS_INFULL BIT(1) // Disable send CTS for responding RX control wrapper RTS dropped by rxpktbuffer full. +#define EN_TXCTS_INTXOP BIT(0) // Enable send CTS for responding RX RTS during our TXOP period. + +#define RESP_CHNBUSY_SHIFT 20 // Define channel busy condition in responder to determine RX busy. +#define RESP_CHNBUSY_Mask 0x03 +#define RESP_DCTS_EN BIT(19) // Enable responder send dual CTS for responding Rx RTS. +#define RESP_DCFE_EN BIT(18) // Enable responder send dual CF-END for responding RX CF-END. +#define RESP_SPLCPEN BIT(17) // Enable responder send SPLCP CCK rsp for acknowledging Rx SPLCP CCK. +#define RESP_SGIEN BIT(16) // Enable responder send SGI HT-OFDM rsp for acknowledging Rx SGI HT-OFDM pkt. + +// WMAC, BA, CCX Related Register. (Offset 0x650 - 0x66Fh) + +// Security Control Register. (Offset 0x670 - 0x68Fh) +//---------------------------------------------------------------------------- +// 8192C CAMCMD bits (Offset 0x670-673, 32 bits) +//---------------------------------------------------------------------------- +#define SECCAM_POLL BIT(31) // Security CAM Polling. +#define SECCAM_CLR BIT(30) // Set 1 to clear all valid bits in CAM. +#define MFBCAM_CLR BIT(29) // Write 1 to clear all MFB value in CAM. +#define SECCAM_WE BIT(16) // Security CAM Write Enable. +#define SECCAM_ADDR_SHIFT 0 // Security CAM Address Offset. +#define SECCAM_ADDR_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192C CAMDBG bits (Offset 0x67C-67F, 32 bits) +//---------------------------------------------------------------------------- +#define SECCAM_INFO BIT(31) // Select TX/RX CAM Information. +#define SEC_KEYFOUND BIT(30) // Security Key Found in CAM. +#define SEC_CONFIG_SHIFT 24 // Security Configuration. +#define SEC_CONFIG_Mask 0x03F +#define SEC_KEYCONTENT_SHIFT 0 // Security CAM Address Offset. +#define SEC_KEYCONTENT_Mask 0x0FFFFFF + +//---------------------------------------------------------------------------- +// 8192C SECCFG bits (Offset 0x680, 8 bits) +//---------------------------------------------------------------------------- +#define CHK_KEYID BIT(8) // Key search engine need to check if key ID matched +#define RXBCUSEDK BIT(7) // Force RX Broadcast packets Use Default Key +#define TXBCUSEDK BIT(6) // Force Tx Broadcast packets Use Default Key +#define NOSKMC BIT(5) // No Key Search for Multicast. +#define SKBYA2 BIT(4) // Search Key by A2. +#define RXDEC BIT(3) // Enable Rx Decryption. +#define TXENC BIT(2) // Enable Tx Encryption. +#define RXUSEDK BIT(1) // Force Rx Use Default Key. +#define TXUSEDK BIT(0) // Force Tx Use Default Key. + +// Security Control Register. (Offset 0x670 - 0x68Fh) + +// Power Save Control Register. (Offset 0x690 - 0x69Fh) +//---------------------------------------------------------------------------- +// 8192C WOW_CTRL bits (Offset 0x690, 8 bits) +//---------------------------------------------------------------------------- +#define FORCE_WAKEUP BIT(7) // Let Wakeup PIN be controllable by FW/Driver. +#define UWF BIT(3) // Unicast Wakeup Frame. +#define MAGIC BIT(2) // Magic Packet. +#define WOWEN BIT(1) // WoW function on or off. +#define PMEN BIT(0) // Power Management Enable. + +//---------------------------------------------------------------------------- +// 8192C PSSTATUS bits (Offset 0x691, 8 bits) +//---------------------------------------------------------------------------- +#define PSSTATUS_SEL_SHIFT 0 // Indicate the present power save mode. +#define PSSTATUS_SEL_Mask 0x0F + +//---------------------------------------------------------------------------- +// 8192C PS_RX_INFO bits (Offset 0x692, 8 bits) +//---------------------------------------------------------------------------- +#define RXCTRLIN0 BIT(4) // set to 1 if NIC received control frame with correct BSSID and DA. +#define RXMGTIN0 BIT(3) // set to 1 if NIC received management frame with correct BSSID and DA. +#define RXDATAIN2 BIT(2) // set to 1 if NIC received data frame with correct BSSID and DA. +#define RXDATAIN1 BIT(1) // set to 1 if NIC received data frame with correct BSSID and DA. +#define RXDATAIN0 BIT(0) // set to 1 if NIC received data frame with correct BSSID and DA. + +//---------------------------------------------------------------------------- +// 8192C LPNAV_CTRL bits (Offset 0x694-697, 32 bits) +//---------------------------------------------------------------------------- +#define LPNAV_EN BIT(31) // Low Power NAV Mode Enable. +#define LPNAV_EARLY_SHIFT 16 // in LPNAV mode, MAC will recall BB & RF into RX idle mode. +#define LPNAV_EARLY_Mask 0x07FFF +#define LPNAV_TH_SHIFT 0 // When NAV received is greater than this, then MAC enters LPNAV mode. +#define LPNAV_TH_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C WKFMCAM_CMD bits (Offset 0x698-69B, 32 bits) +//---------------------------------------------------------------------------- +#define WKFCAM_POLL BIT(31) // Wakeup Mask CAM Polling. +#define WKFCAM_CLR BIT(30) // Set to one to clear all valid bits in CAM. After reset will self clear to 0. +#define WKFCAM_WE BIT(16) // Wakeup Mask CAM Write Enable. +#define WKFCAM_ADDR_SHIFT 0 // Wakeup Mask CAM Address Offset. +#define WKFCAM_ADDR_Mask 0x03F + +// Power Save Control Register. (Offset 0x690 - 0x69Fh) + +// General Purpose Register. (Offset 0x6A0 - 0x6AFh) +//---------------------------------------------------------------------------- +// 8192C RXFLTMAP0 bits (Offset 0x6A0-6A1, 16 bits) +//---------------------------------------------------------------------------- +#define MGTFLTD_EN BIT(13) // +#define MGTFLTC_EN BIT(12) // +#define MGTFLTB_EN BIT(11) // +#define MGTFLTA_EN BIT(10) // +#define MGTFLT9_EN BIT(9) // +#define MGTFLT8_EN BIT(8) // +#define MGTFLT5_EN BIT(5) // +#define MGTFLT4_EN BIT(4) // +#define MGTFLT3_EN BIT(3) // +#define MGTFLT2_EN BIT(2) // +#define MGTFLT1_EN BIT(1) // +#define MGTFLT0_EN BIT(0) // + +//---------------------------------------------------------------------------- +// 8192C RXFLTMAP1 bits (Offset 0x6A2-6A3, 16 bits) +//---------------------------------------------------------------------------- +#define CTRLFLTF_EN BIT(15) // +#define CTRLFLTE_EN BIT(14) // +#define CTRLFLTD_EN BIT(13) // +#define CTRLFLTC_EN BIT(12) // +#define CTRLFLTB_EN BIT(11) // +#define CTRLFLTA_EN BIT(10) // +#define CTRLFLT9_EN BIT(9) // +#define CTRLFLT8_EN BIT(8) // +#define CTRLFLT7_EN BIT(7) // +#define CTRLFLT6_EN BIT(6) // + +//---------------------------------------------------------------------------- +// 8192C RXFLTMAP2 bits (Offset 0x6A4-6A5, 16 bits) +//---------------------------------------------------------------------------- +#define DATAFLTF_EN BIT(15) // +#define DATAFLTE_EN BIT(14) // +#define DATAFLTD_EN BIT(13) // +#define DATAFLTC_EN BIT(12) // +#define DATAFLTB_EN BIT(11) // +#define DATAFLTA_EN BIT(10) // +#define DATAFLT9_EN BIT(9) // +#define DATAFLT8_EN BIT(8) // +#define DATAFLT7_EN BIT(7) // +#define DATAFLT6_EN BIT(6) // +#define DATAFLT5_EN BIT(5) // +#define DATAFLT4_EN BIT(4) // +#define DATAFLT3_EN BIT(3) // +#define DATAFLT2_EN BIT(2) // +#define DATAFLT1_EN BIT(1) // +#define DATAFLT0_EN BIT(0) // + +//---------------------------------------------------------------------------- +// 8192C BCN_PSR_RPT bits (Offset 0x6A8-6AB, 32 bits) +//---------------------------------------------------------------------------- +#define DTIM_CNT_SHIFT 24 // +#define DTIM_CNT_Mask 0x0FF +#define DTIM_PERIOD_SHIFT 16 // +#define DTIM_PERIOD_Mask 0x0FF +#define DTIM BIT(15) // +#define TIM BIT(14) // +#define PS_AID_SHIFT 0 // +#define PS_AID_Mask 0x07FF + +//---------------------------------------------------------------------------- +// 8192C CALB32K_CTRL bits (Offset 0x6AC-6AF, 32 bits) +//---------------------------------------------------------------------------- +#define CALB32K_POLL BIT(31) // +#define CALB32K_DONE BIT(30) // +#define CAL_TIME_SHIFT 20 // Calibration time. +#define CAL_TIME_Mask 0x03FF +#define CAL_REPORT_SHIFT 0 // +#define CAL_REPORT_Mask 0x0FFFFF + +// General Purpose Register. (Offset 0x6A0 - 0x6AFh) + +//---------------------------------------------------------------------------- +// 8192C BT_COEX_TABLE bits (Offset 0x6C0-6CF, 128 bits) +//---------------------------------------------------------------------------- +#define PRI_MASK_RX_RSP BIT(30) // Priority Mask for Rx Response Packet. +#define PRI_MASK_RX_OFDM BIT(29) // Priority Mask for Rx OFDM. +#define PRI_MASK_RX_CCK BIT(28) // Priority Mask for Rx CCK. +#define PRI_MASK_TX_Q_SHIFT 21 // Priority Mask for Tx Queue. +#define PRI_MASK_TX_Q_Mask 0x07F +#define PRI_MASK_TX_NAV_SHIFT 13 // Priority Mask for Tx NAV. +#define PRI_MASK_TX_NAV_Mask 0x0FF +#define PRI_MASK_TX_CCK BIT(12) // Priority Mask for Tx CCK. +#define PRI_MASK_TX_OFDM BIT(11) // Priority Mask for Tx OFDM. +#define PRI_MASK_TX_RTY BIT(10) // Priority Mask for Tx Retry packet. +#define PRI_MASK_TX_NUM_SHIFT 6 // Priority Mask for Tx packet num. +#define PRI_MASK_TX_NUM_Mask 0x0F +#define PRI_MASK_TX_TYPE_SHIFT 2 // Priority Mask for Tx packet type. +#define PRI_MASK_TX_TYPE_Mask 0x0F +#define C_OOB BIT(1) // out of band indication (0:in band,1:out of band). +#define ANT_SEL BIT(0) // single or dual antenna selection (0:single,1:dual). + +#define BREAK_TABLE2_SHIFT 16 // Table used to break WLAN activity. +#define BREAK_TABLE2_Mask 0x0FFFF +#define BREAK_TABLE1_SHIFT 0 // Table used to break BT activity. +#define BREAK_TABLE1_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192C WMAC_RESP_TXINFO bits (Offset 0x6D8-6DA, 24 bits) +//---------------------------------------------------------------------------- +#define RESP_TXAGC_B_SHIFT 13 // +#define RESP_TXAGC_B_Mask 0x01F +#define RESP_TXAGC_A_SHIFT 8 // +#define RESP_TXAGC_A_Mask 0x01F +#define RESP_ANTSEL_B BIT(7) // +#define RESP_ANTSEL_A BIT(6) // +#define RESP_TXANT_CCK_SHIFT 4 // +#define RESP_TXANT_CCK_Mask 0x03 +#define RESP_TXANT_L_SHIFT 2 // +#define RESP_TXANT_L_Mask 0x03 +#define RESP_TXANT_HT_SHIFT 0 // +#define RESP_TXANT_HT_Mask 0x03 + +//======================================================== +// General definitions +//======================================================== + +#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 + +//----------------------------------------------------- +// +// 0xFE00h ~ 0xFE55h USB Configuration +// +//----------------------------------------------------- + +//2 USB Information (0xFE17) +#define USB_IS_HIGH_SPEED 0 +#define USB_IS_FULL_SPEED 1 +#define USB_SPEED_MASK BIT(5) + +#define USB_NORMAL_SIE_EP_MASK 0xF +#define USB_NORMAL_SIE_EP_SHIFT 4 + +#define USB_TEST_EP_MASK 0x30 +#define USB_TEST_EP_SHIFT 4 + +//2 Special Option +#define USB_AGG_EN BIT(3) + + +//2REG_C2HEVT_CLEAR +#define C2H_EVT_HOST_CLOSE 0x00 // Set by driver and notify FW that the driver has read the C2H command message +#define C2H_EVT_FW_CLOSE 0xFF // Set by FW indicating that FW had set the C2H command message and it's not yet read by driver. + +/* +//---------------------------------------------------------------------------- +// 8192C Rate Definition +//---------------------------------------------------------------------------- +//CCK +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +//OFDM +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +//MCS 1 Spatial Stream +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +//MCS 2 Spatial Stream +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 +// ALL CCK Rate +#define RATE_ALL_CCK RATR_1M|RATR_2M|RATR_55M|RATR_11M +#define RATE_ALL_OFDM_AG RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M|\ + RATR_36M|RATR_48M|RATR_54M +#define RATE_ALL_OFDM_1SS RATR_MCS0|RATR_MCS1|RATR_MCS2|RATR_MCS3 |\ + RATR_MCS4|RATR_MCS5|RATR_MCS6 |RATR_MCS7 +#define RATE_ALL_OFDM_2SS RATR_MCS8|RATR_MCS9 |RATR_MCS10|RATR_MCS11|\ + RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15 +*/ + +#endif //WLAN_HAL_INTERNAL_USED + +#endif // #ifndef __INC_HAL8192SEREG_H + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd.h new file mode 100755 index 000000000..09cc5864f --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd.h @@ -0,0 +1,5396 @@ +/* + * Header file defines some private structures and macro + * + * $Id: 8192cd.h,v 1.56.2.38 2011/01/13 14:38:36 pluswang Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_H_ +#define _8192CD_H_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include <../net/bridge/br_private.h> +#endif + +#ifdef __DRAYTEK_OS__ +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#if !defined(__KERNEL__) && !defined(__ECOS) +#include "./sys-support.h" +#endif + +#ifdef __ECOS +#include +#include +#include +#ifdef CONFIG_RTL_ALP +#include +#endif +#endif + +#ifdef SUPPORT_SNMP_MIB +#include "./8192cd_mib.h" +#endif + +#ifdef P2P_SUPPORT +#include "./8192cd_p2p.h" +#endif + +#define TRUE 1 +#define FALSE 0 + +#define CONGESTED 2 +#ifdef SUCCESS +#undef SUCCESS +#endif +#define SUCCESS 1 +#define FAIL 0 + +#ifdef __ECOS +#ifndef FAILED +#define FAILED -1 +#endif +#endif + +#ifndef CONFIG_RTL_WLAN_STATUS +#define CONFIG_RTL_WLAN_STATUS +#endif + +#if 0 +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned long UINT32; + +typedef signed char INT8; +typedef signed short INT16; +typedef signed long INT32; + +typedef unsigned int UINT; +typedef signed int INT; + +typedef unsigned long long UINT64; +typedef signed long long INT64; +#endif + + +#ifdef __KERNEL__ +#include "./ieee802_mib.h" +#elif defined(__ECOS) +#include +#endif + +#include "./wifi.h" +#ifdef CONFIG_WLAN_HAL +#include "./Wlan_TypeDef.h" +#include "./Wlan_QoSType.h" +#endif +#include "./8192cd_security.h" + +#ifdef RTK_BR_EXT +#include "./8192cd_br_ext.h" +#endif + +#include "./8192cd_hw.h" + +#if defined(CONFIG_USB_HCI) +#include "./osdep_service.h" +#include "./usb/8188eu/8192cd_usb.h" +#elif defined(CONFIG_SDIO_HCI) +#ifdef __ECOS +#include +#else +#include "./osdep_service.h" +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#include "./sdio/8189es/8188e_sdio.h" +#endif +#ifdef CONFIG_WLAN_HAL_8192EE +#include "./sdio/8192es/8192e_sdio.h" +#endif +#ifdef CONFIG_POWER_SAVE +#include "./8192cd_pwrctrl.h" +#endif +#ifdef __ECOS +#include +#endif +#endif + +#ifdef RTK_NL80211 +#include "./osdep_service.h" +#endif + +#ifdef USE_OUT_SRC +#include "OUTSRC/phydm_types.h" +#include "./odm_inc.h" +#include "OUTSRC/phydm.h" +#include "./EdcaTurboCheck.h" +#endif + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) +#include "./8192cd_psk.h" +#endif + +#ifdef WIFI_SIMPLE_CONFIG +#ifdef INCLUDE_WPS +#include "./wps/wsc.h" +#endif +#endif + +//RTK_NL80211 +#ifdef RTK_NL80211 +#include +#endif + +#if defined(WIFI_WPAS) || defined(RTK_NL80211) +#ifdef RTK_NL80211 +#define MAX_WPA_IE_LEN 60+5 +#define MAX_RSN_IE_LEN 60+5 +#define MAX_HS_IE_LEN 60+5 +#else +#define MAX_WPA_IE_LEN 255+5 +#define MAX_RSN_IE_LEN 255+5 +#define MAX_HS_IE_LEN 255+5 +#endif +#endif + +#if defined(CONFIG_RTL_WAPI_SUPPORT) +#include "wapi_wai.h" +#include "wapiCrypto.h" +#endif + +#ifdef CONFIG_RTK_MESH +#include "../mesh_ext/mesh.h" +#include "../mesh_ext/hash_table.h" +#include "../mesh_ext/mesh_route.h" +#include "../mesh_ext/mesh_security.h" +#endif +#define DWNGRADE_PROBATION_TIME 3 +#define UPGRADE_PROBATION_TIME 3 +#define TRY_RATE_FREQ 6 + +#ifdef CONFIG_RTL8190_PRIV_SKB +#define MAX_PRE_ALLOC_SKB_NUM 160 +#else +#define MAX_PRE_ALLOC_SKB_NUM 32 +#endif + +#define NR_NET80211_UP 8 +#define NET80211_TU_TO_US 1024 // unit:us + +#if defined(__LINUX_2_6__) +#if defined(CONFIG_PRINTK) +#define panic_printk printk +#elif !defined(CONFIG_PANIC_PRINTK) +#define panic_printk scrlog_printk +#endif +#endif + +#ifdef HIGH_POWER_EXT_PA +#define HP_OFDM_POWER_MAX (priv->pshare->rf_ft_var.hp_ofdm_pwr_max) +#define HP_CCK_POWER_MAX (priv->pshare->rf_ft_var.hp_cck_pwr_max) +#define HP_OFDM_POWER_DEFAULT 8//20 +#define HP_CCK_POWER_DEFAULT 10//16 +#endif + +#ifdef USB_POWER_SUPPORT +#define USB_HT_2S_DIFF 14 +#define USB_RA_MASK 0x1e0fffff // disable MCS 12, 11, 10, 9, 8 +#endif + +#ifdef BEAMFORMING_SUPPORT + +#define BEAMFORMEE_ENTRY_NUM 2 +#define BEAMFORMER_ENTRY_NUM 2 + + +typedef struct _DEL_ENTRY_LIST_BY_MACADDR{ + u1Byte BFerEntry_Idx0[6]; + u1Byte BFerEntry_Idx1[6]; + u1Byte BFeeEntry_Idx0[6]; + u1Byte BFeeEntry_Idx1[6]; +}DEL_ENTRY_LIST_BY_MACADDR,*PDEL_ENTRY_LIST_BY_MACADDR; + + +typedef enum _DEL_ENTRY_TYPE_SEL{ + BFerEntry , + BFeeEntry , + BFerBFeeEntry , +}DEL_ENTRY_TYPE_SEL,*PDEL_ENTRY_TYPE_SEL; + + +typedef enum _ACT_CATEGORY { + ACT_CAT_SPECTRUM_MGNT = 0, // Spectrum management + ACT_CAT_QOS = 1, // Qos + ACT_CAT_DLS = 2, // Direct Link Protocol (DLS) + ACT_CAT_BA = 3, // Block Ack + ACT_CAT_PUBLIC = 4, // Public + ACT_CAT_RM = 5, // Radio Measurement (RM) + ACT_CAT_FT = 6, // Fast BSS Transition + ACT_CAT_HT = 7, // High Throughput + ACT_CAT_SAQ = 8, // Security Association Query + ACT_CAT_SAQ_PD_PUBLIC = 9, // Protected Dual of Public Action + ACT_CAT_TDLS = 12, // Tunneled Direct Link Setup + ACT_CAT_WMM = 17, // WMM + ACT_CAT_VHT = 21, // VHT + ACT_CAT_VENDOR_PROTECT = 126, // Vendor-specific Protected + ACT_CAT_VENDOR = 127, // Vendor-specific +} ACT_CATEGORY, *PACT_CATEGORY; + + +typedef enum _TYPE_SUBTYPE { + // Management Frame + Type_Asoc_Req = 0x00, + Type_Asoc_Rsp = 0x10, + Type_Reasoc_Req = 0x20, + Type_Reasoc_Rsp = 0x30, + Type_Probe_Req = 0x40, + Type_Probe_Rsp = 0x50, + Type_Beacon = 0x80, + Type_Atim = 0x90, + Type_Disasoc = 0xa0, + Type_Auth = 0xb0, + Type_Deauth = 0xc0, + Type_Action = 0xd0, + Type_Action_No_Ack = 0xe0, + + // Control Frame + Type_Beamforming_Report_Poll = 0x44, //= MkString(S8(0,0,1,0,0,0,1,0)); + Type_NDPA = 0x54,//= MkString(S8(0,0,1,0,1,0,1,0)); + Type_BlockAckReq = 0x84,//= MkString(S8(0,0,1,0,0,0,0,1)); + Type_BlockAck = 0x94,//= MkString(S8(0,0,1,0,1,0,0,1)); + Type_PS_poll = 0xa4,//= MkString(S8(0,0,1,0,0,1,0,1)); + Type_RTS = 0xb4,//= MkString(S8(0,0,1,0,1,1,0,1)); + Type_CTS = 0xc4,//= MkString(S8(0,0,1,0,0,0,1,1)); + Type_Ack = 0xd4,//= MkString(S8(0,0,1,0,1,0,1,1)); + Type_Cfend = 0xe4,//= MkString(S8(0,0,1,0,0,1,1,1)); + Type_Cfend_Ack = 0xf4,//= MkString(S8(0,0,1,0,1,1,1,1)); + + // Data Frame + Type_Data = 0x08,//= MkString(S8(0,0,0,1,0,0,0,0)); + Type_Data_Ack = 0x18,//= MkString(S8(0,0,0,1,1,0,0,0)); + Type_Data_Poll = 0x28,//= MkString(S8(0,0,0,1,0,1,0,0)); + Type_Data_Poll_Ack = 0x38,//= MkString(S8(0,0,0,1,1,1,0,0)); + Type_Null_Frame = 0x48,//= MkString(S8(0,0,0,1,0,0,1,0)); + Type_Cfack = 0x58,//= MkString(S8(0,0,0,1,1,0,1,0)); + Type_Cfpoll = 0x68,//= MkString(S8(0,0,0,1,0,1,1,0)); + Type_Cfpoll_Ack = 0x78,//= MkString(S8(0,0,0,1,1,1,1,0)); + Type_QosData = 0x88,//= MkString(S8(0,0,0,1,0,0,0,1)); + Type_QData_Ack = 0x98,//= MkString(S8(0,0,0,1,1,0,0,1)); + Type_QData_Poll = 0xa8,//= MkString(S8(0,0,0,1,0,1,0,1)); + Type_QData_Poll_Ack = 0xb8, //= MkString(S8(0,0,0,1,1,1,0,1)); + Type_QosNull = 0xc8,//= MkString(S8(0,0,0,1,0,0,1,1)); + // Note: 0xd8 is reserved in 11e/13.0. + Type_QosCfpoll = 0xe8,//= MkString(S8(0,0,0,1,0,1,1,1)); + Type_QosCfpoll_Ack = 0xf8,//= MkString(S8(0,0,0,1,1,1,1,1)); +} TYPE_SUBTYPE, *PTYPE_SUBTYPE; + + +typedef enum _BEAMFORMING_ENTRY_STATE +{ + BEAMFORMING_ENTRY_STATE_UNINITIALIZE, + BEAMFORMING_ENTRY_STATE_INITIALIZEING, + BEAMFORMING_ENTRY_STATE_INITIALIZED, + BEAMFORMING_ENTRY_STATE_PROGRESSING, + BEAMFORMING_ENTRY_STATE_PROGRESSED, +}BEAMFORMING_ENTRY_STATE, *PBEAMFORMING_ENTRY_STATE; +typedef enum _BEAMFORMING_STATE +{ + BEAMFORMING_STATE_END, + BEAMFORMING_STATE_START_1BFee, + BEAMFORMING_STATE_START_2BFee +} BEAMFORMING_STATE, *PBEAMFORMING_STATE; + +typedef enum _BEAMFORMING_NOTIFY_STATE +{ + BEAMFORMING_NOTIFY_NONE, + BEAMFORMING_NOTIFY_ADD, + BEAMFORMING_NOTIFY_DELETE, + BEAMFORMING_NOTIFY_RESET +} BEAMFORMING_NOTIFY_STATE, *PBEAMFORMING_NOTIFY_STATE; + +typedef enum _BEAMFORMING_CAP +{ + BEAMFORMING_CAP_NONE = 0x0, + BEAMFORMER_CAP_HT_EXPLICIT = 0x1, + BEAMFORMEE_CAP_HT_EXPLICIT = 0x2, + BEAMFORMER_CAP_VHT_SU = 0x4, // Self has er Cap, because Reg er & peer ee + BEAMFORMEE_CAP_VHT_SU = 0x8, // Self has ee Cap, because Reg ee & peer er + BEAMFORMER_CAP = 0x10, + BEAMFORMEE_CAP = 0x20, +}BEAMFORMING_CAP, *PBEAMFORMING_CAP; +typedef enum _SOUNDING_MODE +{ + SOUNDING_SW_VHT_TIMER = 0x0, + SOUNDING_SW_HT_TIMER = 0x1, + SOUNDING_STOP_All_TIMER = 0x2, + SOUNDING_HW_VHT_TIMER = 0x3, + SOUNDING_HW_HT_TIMER = 0x4, + SOUNDING_STOP_OID_TIMER = 0x5, + SOUNDING_AUTO_VHT_TIMER = 0x6, + SOUNDING_AUTO_HT_TIMER = 0x7, + SOUNDING_FW_VHT_TIMER = 0x8, + SOUNDING_FW_HT_TIMER = 0x9 +}SOUNDING_MODE, *PSOUNDING_MODE; +typedef struct _RT_BEAMFORMING_ENTRY { + BOOLEAN bUsed; + BOOLEAN bTxBF; + BOOLEAN bSound; + u2Byte AID; + u2Byte MacId; // Used to Set Reg42C in IBSS mode. + u2Byte P_AID; + u1Byte MacAddr[6]; + ODM_BW_E BW; // Sounding BandWidth + BEAMFORMING_CAP BeamformEntryCap; + BEAMFORMING_ENTRY_STATE BeamformEntryState; + BOOLEAN bBeamformingInProgress; + + // LogStatusFailCnt is used to record if we receive CSI or not + u1Byte LogStatusFailCnt; + u1Byte CompSteeringNumofBFer; + struct stat_info *pSTA; +} RT_BEAMFORMING_ENTRY, *PRT_BEAMFORMING_ENTRY; +typedef struct _RT_BEAMFORMER_ENTRY { + BOOLEAN bUsed; + u2Byte P_AID; + u1Byte MacAddr[6]; + BEAMFORMING_CAP BeamformEntryCap; + u1Byte NumofSoundingDim; + u1Byte ClockResetTimes; + // Below variable are used to record if BFer retry NDPA or not + u1Byte NDPAPreLogSeq; + u1Byte NDPALogSeq; + u1Byte NDPALogRetryCnt; + u1Byte NDPALogSuccess; +} RT_BEAMFORMER_ENTRY, *PRT_BEAMFORMER_ENTRY; +typedef struct _RT_BEAMFORMING_TIMER_INFO { + u1Byte Mode; + ODM_BW_E BW; + u1Byte BeamCount; + u2Byte BeamPeriod; +} RT_BEAMFORMING_TIMER_INFO, *PRT_BEAMFORMING_TIMER_INFO; +typedef struct _RT_BEAMFORMING_TEST_INFO { + BOOLEAN bBeamAutoTest; + u1Byte BeamTestCount; + u1Byte BeamTestThreshold; + u2Byte BeamTestPeriod; +} RT_BEAMFORMING_TEST_INFO, *PRT_BEAMFORMING_TEST_INFO; +typedef struct _RT_BEAMFORMING_PERIOD_INFO { + u1Byte Idx; + SOUNDING_MODE Mode; + u1Byte BW; + u2Byte BeamPeriod; +} RT_BEAMFORMING_PERIOD_INFO, *PRT_BEAMFORMING_PERIOD_INFO; +typedef struct _RT_BEAMFORMING_INFO { + BEAMFORMING_CAP BeamformCap; + BEAMFORMING_STATE BeamformState; + RT_BEAMFORMING_ENTRY BeamformeeEntry[BEAMFORMEE_ENTRY_NUM]; + RT_BEAMFORMER_ENTRY BeamformerEntry[BEAMFORMER_ENTRY_NUM]; + u1Byte BeamformeeCurIdx; + RT_TIMER BeamformingTimer; + RT_BEAMFORMING_TIMER_INFO BeamformingTimerInfo[BEAMFORMEE_ENTRY_NUM]; + RT_BEAMFORMING_PERIOD_INFO BeamformingPeriodInfo; + u1Byte BeamformingPeriodState; // add by Gary + DEL_ENTRY_TYPE_SEL CurDelBFerBFeeEntrySel; // add by Jeffery + DEL_ENTRY_LIST_BY_MACADDR DelEntryListByMACAddr; +} RT_BEAMFORMING_INFO, *PRT_BEAMFORMING_INFO; + +typedef struct _RT_NDPA_STA_INFO { + u2Byte AID: 12; + u2Byte FeedbackType: 1; + u2Byte NcIndex: 3; +} RT_NDPA_STA_INFO, *PRT_NDPA_STA_INFO; + +#endif +#ifdef CONFIG_RTL_8812_SUPPORT +#include "8812_vht_gen.h" +#endif +#ifdef PCIE_POWER_SAVING + +#define PABCD_ISR 0xB8003510 + +enum ap_pwr_state { + L0, + L1, + L2, + ASPM_L0s_L1, +}; + +enum ps_enable { + L1_en = BIT(0), + L2_en = BIT(1), + ASPM_en = BIT(2), + _1x1_en = BIT(4), + offload_en = BIT(5), + stop_dma_en = BIT(6), +}; + +enum pwr_state_change { +// Renamed by Annie for ODM OUTSRC porting and conflict naming issue, 2011-09-22 + PWR_STATE_IN = 1, + PWR_STATE_OUT = 2 +}; +#endif + +#if defined(HS2_SUPPORT) +/* Hotspot 2.0 Release 1 */ +#define ETHER_TDLS 0x890d +#endif + +#define RF_PATH_A 0 //Radio Path A +#define RF_PATH_B 1 //Radio Path B +#define RF_PATH_C 2 //Radio Path C +#define RF_PATH_D 3 //Radio Path D + + +// for packet aggregation +#define FG_AGGRE_MPDU 1 +#define FG_AGGRE_MPDU_BUFFER_FIRST 2 +#define FG_AGGRE_MPDU_BUFFER_MID 3 +#define FG_AGGRE_MPDU_BUFFER_LAST 4 +#define FG_AGGRE_MSDU_FIRST 5 +#define FG_AGGRE_MSDU_MIDDLE 6 +#define FG_AGGRE_MSDU_LAST 7 + +#ifdef SDIO_AP_OFFLOAD +#define OFFLOAD_BUF ((RTL8192CD_NUM_VWLAN+1)*1024) +#define OFFLOAD_DURATION 128 // UNIT:us, min:128us + +enum { + TRIGGER_TIME_NONE = 0, + TRIGGER_TIME_8MILISEC, + TRIGGER_TIME_2SEC, +}; + +#if OFFLOAD_DURATION <= 8000 +#define PULSE_DURATION (OFFLOAD_DURATION/64) //duration unit: 64us +#define REPEAT_TRIGGER_UNIT TRIGGER_TIME_8MILISEC +#define REPEAT_TRIGGER_DURATION 50 +#elif OFFLOAD_DURATION < 32000 +#define PULSE_DURATION (128 + 1) //duration unit: 32ms +#define REPEAT_TRIGGER_UNIT TRIGGER_TIME_2SEC +#define REPEAT_TRIGGER_DURATION 1 +#else +#define PULSE_DURATION (128 + OFFLOAD_DURATION/32000) +#define REPEAT_TRIGGER_UNIT TRIGGER_TIME_2SEC +#define REPEAT_TRIGGER_DURATION (OFFLOAD_DURATION/2000000 + 1) +#endif + +enum { + RTW_STS_SUSPEND=0, + RTW_STS_NORMAL, + RTW_STS_REP, +}; + +enum { + RTW_PM_AWAKE=0, + RTW_PM_PREPROCESS, + RTW_PM_START, + RTW_PM_SUSPEND, +}; + +enum { + RTW_ACT_IDLE=0, + RTW_ACT_ASSOC, + RTW_ACT_DISASSOC, + RTW_ACT_POWERON, + RTW_ACT_POWERDOWN, + RTW_ACT_SETREP, +}; + +enum { + OFFLOAD_PROHIBIT_USER = BIT0, + OFFLOAD_PROHIBIT_SITE_SURVEY = BIT1, + OFFLOAD_PROHIBIT_WPS = BIT2, + OFFLOAD_PROHIBIT_DEV_OPS = BIT3, + OFFLOAD_PROHIBIT_JOIN = BIT4, + OFFLOAD_PROHIBIT_MGT = BIT5, + OFFLOAD_PROHIBIT_COMAPI = BIT6, + OFFLOAD_PROHIBIT_MP = BIT7, + OFFLOAD_PROHIBIT_HANGUP = BIT8, +}; + +struct ap_offload_resource { + u16 beacon_offset; + u16 probe_offset; +}; + +#ifdef CONFIG_POWER_SAVE +struct ap_pwrctrl_priv{ + u1Byte h2c_done; + u1Byte en_32k; + u1Byte sleep_time; // apps sleep time + u4Byte suspend_processing; +}; +#endif +#endif // SDIO_AP_OFFLOAD + +#ifdef USE_PREALLOC_MODULE +enum { + PREALLOC_TYPE_XMITBUF = 0, + PREALLOC_TYPE_RECVMEM, +}; +#endif + +#define MANAGEMENT_AID 0 + +enum wifi_state { + WIFI_NULL_STATE = 0x00000000, + WIFI_ASOC_STATE = 0x00000001, + WIFI_REASOC_STATE = 0x00000002, + WIFI_SLEEP_STATE = 0x00000004, + WIFI_STATION_STATE = 0x00000008, + WIFI_AP_STATE = 0x00000010, + WIFI_ADHOC_STATE = 0x00000020, + WIFI_AUTH_NULL = 0x00000100, + WIFI_AUTH_STATE1 = 0x00000200, + WIFI_AUTH_SUCCESS = 0x00000400, + WIFI_SITE_MONITOR = 0x00000800, //to indicate the station is under site surveying +#ifdef WDS + WIFI_WDS = 0x00001000, + WIFI_WDS_RX_BEACON = 0x00002000, // already rx WDS AP beacon +#ifdef LAZY_WDS + WIFI_WDS_LAZY = 0x00004000, +#endif +#endif + +#ifdef MP_TEST + WIFI_MP_STATE = 0x00010000, + WIFI_MP_CTX_BACKGROUND = 0x00020000, // in continuous tx background + WIFI_MP_CTX_BACKGROUND_PENDING = 0x00040000, // pending in continuous tx background due to out of skb + WIFI_MP_CTX_PACKET = 0x00080000, // in packet mode + WIFI_MP_CTX_ST = 0x00100000, // in continuous tx with single-tone + WIFI_MP_CTX_SCR = 0x00200000, // in continuous tx with single-carrier + WIFI_MP_CTX_CCK_CS = 0x00400000, // in cck continuous tx with carrier suppression + WIFI_MP_CTX_OFDM_HW = 0x00800000, // in ofdm continuous tx + WIFI_MP_RX = 0x01000000, + WIFI_MP_ARX_FILTER = 0x02000000, +#if 1//def CONFIG_RTL8672 + WIFI_MP_CTX_BACKGROUND_STOPPING = 0x04000000, // stopping ctx +#endif +#endif + +#ifdef WIFI_SIMPLE_CONFIG +#ifdef INCLUDE_WPS + WIFI_WPS = 0x02000000, + WIFI_WPS_JOIN = 0x04000000, +#else + WIFI_WPS = 0x01000000, + WIFI_WPS_JOIN = 0x02000000, +#endif +#endif + +#ifdef A4_STA + WIFI_A4_STA = 0x04000000, +#endif + + +#ifdef CONFIG_RTL8672 + WIFI_WAIT_FOR_CHANNEL_SELECT = 0x04000000, +#endif + +#ifdef P2P_SUPPORT + WIFI_P2P_SUPPORT = 0x08000000 +#endif +}; + +enum frag_chk_state { + NO_FRAG = 0x0, + UNDER_FRAG = 0x1, + CHECK_FRAG = 0x2, +}; + +enum led_type { + LEDTYPE_HW_TX_RX, + LEDTYPE_HW_LINKACT_INFRA, + LEDTYPE_SW_LINK_TXRX, + LEDTYPE_SW_LINKTXRX, + LEDTYPE_SW_LINK_TXRXDATA, + LEDTYPE_SW_LINKTXRXDATA, + LEDTYPE_SW_ENABLE_TXRXDATA, + LEDTYPE_SW_ENABLETXRXDATA, + LEDTYPE_SW_ADATA_GDATA, + LEDTYPE_SW_ENABLETXRXDATA_1, + LEDTYPE_SW_CUSTOM1, + LEDTYPE_SW_LED2_GPIO8_LINKTXRX, // 11 + LEDTYPE_SW_LED2_GPIO8_ENABLETXRXDATA, // 12 + LEDTYPE_SW_LED2_GPIO10_LINKTXRX, // 13 + LEDTYPE_SW_RESERVED, // 14, redirect to 52 + LEDTYPE_SW_LED2_GPIO8_LINKTXRXDATA, // 15 + LEDTYPE_SW_LED2_GPIO8_ASOCTXRXDATA, // 16, mark_led + LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA, // 17 LED Control = LED_TYPE 7 + // Latest 92D customized LED types start from 50 + LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA_92D = 50, // 50 for 92D, LED Control = 92C LED_TYPE 7 + LEDTYPE_SW_LED1_GPIO9_LINKTXRX_92D = 51, // 51 for 92D, LED Control = 92C LED_TYPE 13 + LEDTYPE_SW_LED2_GPIO10_LINKTXRX_92D = 52, // 52 for 92D, LED Control = 92C LED_TYPE 13 + LEDTYPE_SW_MAX, +}; + +enum Synchronization_Sta_State { + STATE_Sta_Min = 0, + STATE_Sta_No_Bss = 1, + STATE_Sta_Bss = 2, + STATE_Sta_Ibss_Active = 3, + STATE_Sta_Ibss_Idle = 4, + STATE_Sta_Auth_Success = 5, + STATE_Sta_Roaming_Scan = 6, +}; + +// Realtek proprietary IE +enum Realtek_capability_IE_bitmap { + RTK_CAP_IE_TURBO_AGGR = 0x01, + RTK_CAP_IE_USE_LONG_SLOT = 0x02, + RTK_CAP_IE_USE_AMPDU = 0x04, +#ifdef RTK_WOW + RTK_CAP_IE_USE_WOW = 0x08, +#endif + RTK_CAP_IE_SOFTAP = 0x10, + RTK_CAP_IE_WLAN_8192SE = 0x20, + RTK_CAP_IE_WLAN_88C92C = 0x40, + RTK_CAP_IE_AP_CLIENT = 0x80, + RTK_CAP_IE_VIDEO_ENH = 0x01, + RTK_CAP_IE_8812_BCUT = 0x02, + RTK_CAP_IE_8812_CCUT = 0x04, +}; + +enum CW_STATE { + CW_STATE_NORMAL = 0x00000000, + CW_STATE_AGGRESSIVE = 0x00010000, + CW_STATE_DIFSEXT = 0x00020000, + CW_STATE_AUTO_TRUBO = 0x01000000, +}; + +enum {TURBO_AUTO = 0, TURBO_ON = 1, TURBO_OFF = 2}; + +enum NETWORK_TYPE { + WIRELESS_11B = 1, + WIRELESS_11G = 2, + WIRELESS_11A = 4, + WIRELESS_11N = 8, + WIRELESS_11AC = 64 +}; + +enum FREQUENCY_BAND { + BAND_2G, + BAND_5G +}; + +enum _HT_CHANNEL_WIDTH { + HT_CHANNEL_WIDTH_20 = 0, + HT_CHANNEL_WIDTH_20_40 = 1, + HT_CHANNEL_WIDTH_80 = 2, + HT_CHANNEL_WIDTH_160 = 3, + HT_CHANNEL_WIDTH_10 = 4, + HT_CHANNEL_WIDTH_5 = 5 +}; + + +#ifdef RTK_AC_SUPPORT +enum _HT_CHANNEL_WIDTH_AC { + HT_CHANNEL_WIDTH_AC_20 = 0, + HT_CHANNEL_WIDTH_AC_40 = 1, + HT_CHANNEL_WIDTH_AC_80 = 2, + HT_CHANNEL_WIDTH_AC_160 = 3, + HT_CHANNEL_WIDTH_AC_10 = 4, + HT_CHANNEL_WIDTH_AC_5 = 5 +}; + +enum _SUB_CHANNEL_INDEX_80M { + _20_B_40_A = 1, + _20_A_40_B = 2, + _20_A_40_A = 3, + _20_B_40_B = 4, + _40_A = 9, + _40_B = 10 +}; + +enum _AC_SIGMA_MODE { + AC_SIGMA_NONE = 0, //normal mode + AC_SIGMA_APUT = 1, //running ac logo sigma test, AP DUT mode + AC_SIGMA_APTB = 2 //running ac logo sigma test, AP Testbed mode +}; + +//t_stamp[1], b5-b7 = channel width information, mapping to _HT_CHANNEL_WIDTH_AC +#define BSS_BW_SHIFT 5 +#define BSS_BW_MASK 0x7 +#endif + + +enum SECONDARY_CHANNEL_OFFSET { + HT_2NDCH_OFFSET_DONTCARE = 0, + HT_2NDCH_OFFSET_BELOW = 1, // secondary channel is below primary channel, ex. primary:5 2nd:1 + HT_2NDCH_OFFSET_ABOVE = 2 // secondary channel is above primary channel, ex. primary:5 2nd:9 +}; + +enum AGGREGATION_METHOD { + AGGRE_MTHD_NONE = 0, + AGGRE_MTHD_MPDU = 1, + AGGRE_MTHD_MSDU = 2, + AGGRE_MTHD_MPDU_AMSDU = 3 +}; + +enum _HT_CURRENT_TX_INFO_ { + TX_USE_40M_MODE = BIT(0), + TX_USE_SHORT_GI = BIT(1), + TX_USE_80M_MODE = BIT(2), + TX_USE_160M_MODE = BIT(3) +}; + +/* +enum _ADD_RATID_UPDATE_CONTENT_ { + RATID_NONE_UPDATE = 0, + RATID_GENERAL_UPDATE = 1, + RATID_INFO_UPDATE = 2 +}; +*/ + +enum _DC_TH_CURRENT_STATE_ { + DC_TH_USE_NONE = 0, + DC_TH_USE_UPPER = 1, + DC_TH_USE_LOWER = 2 +}; + +enum _H2C_CMD_ID_ { + _AP_OFFLOAD_CMD_ = 0 , /*0*/ + _SETPWRMODE_CMD_, + _JOINBSSRPT_CMD_, + _RSVDPAGE_CMD_, + _SET_RSSI_4_CMD_, + H2C_CMD_RSSI = 5, + H2C_CMD_MACID = 6, + H2C_CMD_PS = 7, + _P2P_PS_OFFLOAD_CMD_ = 8, + SELECTIVE_SUSPEND_ROF = 9, + AP_OFFLOAD_RFCTRL = 10, + AP_REQ_RPT = 11, + BT_COEX_DUTY_CYCLE = 12, + H2C_CMD_INFO_PKT = 13, + H2C_CMD_SMCC = 14, +#if defined(SOFTAP_PS_DURATION) || defined(CONFIG_POWER_SAVE) + H2C_PS_SOFTAP = 38, +#endif + H2C_CMD_AP_WPS_CTRL = 64 +}; + +enum _ANTENNA_ { + ANTENNA_A = 0x1, + ANTENNA_B = 0x2, + ANTENNA_C = 0x4, + ANTENNA_D = 0x8, + ANTENNA_AC = 0x5, + ANTENNA_AB = 0x3, + ANTENNA_BD = 0xA, + ANTENNA_CD = 0xC, + ANTENNA_ABC = 0x7, + ANTENNA_ABCD = 0xF +}; + +enum qos_prio { BK, BE, VI, VO, VI_AG, VO_AG }; + +#ifdef WIFI_HAPD +enum HAPD_EVENT { + HAPD_EXIRED = 0, + HAPD_REGISTERED = 1, + HAPD_MIC_FAILURE = 2, + HAPD_TRAFFIC_STAT = 3, + HAPD_PUSH_BUTTON = 4, + HAPD_WPS_PROBEREQ = 5, + HAPD_WDS_SETWPA = 6 +}; +#endif + +#ifdef RTK_NL80211 +enum RTK_CFG80211_EVENT { + CFG80211_CONNECT_RESULT = 0, + CFG80211_ROAMED = 1, + CFG80211_DISCONNECTED = 2, + CFG80211_IBSS_JOINED = 3, + CFG80211_NEW_STA = 4, + CFG80211_SCAN_DONE = 5, + CFG80211_SCAN_ABORTED = 6, + CFG80211_DEL_STA = 7, + CFG80211_RADAR_CAC_FINISHED = 8, + CFG80211_RADAR_DETECTED = 9, + CFG80211_RADAR_CAC_ABORTED = 10, + CFG80211_REMAIN_CHANNEL = 11, + CFG80211_MIC_FAILURE = 12 +}; +#endif + +enum ACL_MODE { + ACL_allow = 1, + ACL_deny = 2 +}; + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(RTK_NL80211) +enum WAKE_EVENT { + WAKE_EVENT_CMD = 0, + WAKE_EVENT_XMIT = 1, + WAKE_EVENT_CMD_NL80211 = 2, +}; +#endif + +enum _PA_TYPE { + PA_SKYWORKS_5022 = 0, + PA_RFMD_4501 = 1, + PA_SKYWORKS_5023 = 2, + PA_RTC5634 = 3, + PA_SKYWORKS_85712_HP = 4, + PA_INTERNAL = 0x10, +}; + + +#ifdef WIFI_WPAS +enum WPAS_EVENT { + WPAS_EXIRED = 10, + WPAS_REGISTERED = 11, + WPAS_MIC_FAILURE = 12, + WPAS_ASSOC_INFO = 13, + WPAS_SCAN_DONE = 14, +#ifdef WIFI_WPAS_CLI + WPAS_DISCON = 15, +#endif +}; + +#define REQIELEN 123 +#define RESPIELEN 123 + +typedef struct _WPAS_ASSOCIATION_INFO { + unsigned short ReqIELen; + char ReqIE[REQIELEN]; + unsigned short RespIELen; + char RespIE[RESPIELEN]; +} WPAS_ASSOCIATION_INFO; +#endif + +static const struct ParaRecord rtl_ap_EDCA[] = { +//ACM,AIFSN, ECWmin, ECWmax, TXOplimit + {0, 7, 4, 10, 0}, + {0, 3, 4, 6, 0}, + {0, 1, 3, 4, 188}, + {0, 1, 2, 3, 102}, + {0, 1, 3, 4, 94}, + {0, 1, 2, 3, 47}, +}; + +static const struct ParaRecord rtl_sta_EDCA[] = { +//ACM,AIFSN, ECWmin, ECWmax, TXOplimit + {0, 7, 4, 10, 0}, + {0, 3, 4, 10, 0}, + {0, 2, 3, 4, 188}, + {0, 2, 2, 3, 102}, + {0, 2, 3, 4, 94}, + {0, 2, 2, 3, 47}, +}; + +#if 1 +// +// Indicate different AP vendor for IOT issue. +// +typedef enum _HT_IOT_PEER { + HT_IOT_PEER_UNKNOWN = 0, + HT_IOT_PEER_REALTEK = 1, + HT_IOT_PEER_REALTEK_92SE = 2, + HT_IOT_PEER_BROADCOM = 3, + HT_IOT_PEER_RALINK = 4, + HT_IOT_PEER_ATHEROS = 5, + HT_IOT_PEER_CISCO = 6, + HT_IOT_PEER_MERU = 7, + HT_IOT_PEER_MARVELL = 8, + HT_IOT_PEER_REALTEK_SOFTAP = 9,// peer is RealTek SOFT_AP, by Bohn, 2009.12.17 + HT_IOT_PEER_SELF_SOFTAP = 10, // Self is SoftAP + HT_IOT_PEER_AIRGO = 11, + HT_IOT_PEER_INTEL = 12, + HT_IOT_PEER_RTK_APCLIENT = 13, + HT_IOT_PEER_REALTEK_81XX = 14, + HT_IOT_PEER_REALTEK_WOW = 15, + HT_IOT_PEER_HTC = 16, + HT_IOT_PEER_REALTEK_8812 = 17, + HT_IOT_PEER_CMW = 18, + HT_IOT_PEER_MAX = 19 +} HT_IOT_PEER_E, *PHTIOT_PEER_E; +#endif + +struct pkt_queue { + struct sk_buff *pSkb[NUM_TXPKT_QUEUE]; + int head; + int tail; +}; + +#if defined(WIFI_WMM) && defined(WMM_APSD) +struct apsd_pkt_queue { + struct sk_buff *pSkb[NUM_APSD_TXPKT_QUEUE]; + int head; + int tail; +}; +#endif + +#if defined(WIFI_WMM) +struct dz_mgmt_queue { + struct tx_insn *ptx_insn[NUM_DZ_MGT_QUEUE]; + int head; + int tail; +}; + +#ifdef DZ_ADDBA_RSP +// dz addba +struct dz_addba_info { + unsigned char used; + unsigned char dialog_token; + unsigned char TID; + unsigned short status_code; + unsigned short timeout; +}; +#endif +#endif + +#ifdef USER_ADDIE +#define MAX_USER_IE 4 +struct user_ie { + unsigned int used; + unsigned int ie_len; + unsigned char ie[256]; +}; +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +struct tx_servq { + _list tx_pending; + _queue xframe_queue; + int q_num; +#ifdef CONFIG_SDIO_HCI + unsigned int ts_used; +#endif +}; + +#ifdef CONFIG_TCP_ACK_TXAGG +struct tcpack_servq { + _list tx_pending; + _queue xframe_queue; + int q_num; + unsigned long start_time; +}; +#endif +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#ifdef RSSI_MIN_ADV_SEL +#define NR_RSSI_MIN_DATA 10 // must > 1 + +struct rssi_search_entry { + unsigned char rssi; + unsigned char tx_rate; + unsigned short throughput; +}; +#endif + +#ifdef WIFI_SIMPLE_CONFIG +enum WSC_ISSUE_DISCON_STATE { + WSC_DISCON_STATE_RECV_EAP_FAIL = 0, + WSC_DISCON_STATE_IGNORE = 1, +}; + +struct wsc_disconn_entry { + struct list_head list; + unsigned char addr[MACADDRLEN]; + int state; + int expire_to; +}; +#endif + +#if defined(GREEN_HILL) || defined(PACK_STRUCTURE) || defined(__ECOS) +#pragma pack(1) +#endif + + +/** + * @brief MAC Frame format - wlan_hdr (wireless LAN header) + * + * Dcscription: 802.11 MAC Frame (header). See textbook P.46 + * p.s : memory aligment by BYTE, + * __PACK : not need 4 bytes aligment + */ +__PACK struct wlan_hdr { + unsigned short fmctrl; + unsigned short duration; + unsigned char addr1[MACADDRLEN]; + unsigned char addr2[MACADDRLEN]; + unsigned char addr3[MACADDRLEN]; + unsigned short sequence; + unsigned char addr4[MACADDRLEN]; + unsigned short qosctrl; +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + struct lls_mesh_header meshhdr; // 11s, mesh header, 4~16 bytes +#endif + unsigned char iv[8]; +} __WLAN_ATTRIB_PACK__; + +#ifdef RTK_NL80211 +struct ieee80211_mgmt_hrd { + u16 frame_control; + u16 duration; + u8 da[6]; + u8 sa[6]; + u8 bssid[6]; + u16 seq_ctrl; +} __attribute__ ((packed)); +/*cfg p2p cfg p2p*/ +#endif + +#if defined(GREEN_HILL) || defined(PACK_STRUCTURE) || defined(__ECOS) +#pragma pack() +#endif + +struct wlan_hdrnode { + struct list_head list; +#ifdef TX_EARLY_MODE + unsigned char em_info[8]; // early mode info +#endif + struct wlan_hdr hdr; +}; + +struct wlan_hdr_poll { + struct wlan_hdrnode hdrnode[PRE_ALLOCATED_HDR]; + int count; +}; + +#if defined(GREEN_HILL) || defined(PACK_STRUCTURE) || defined(__ECOS) +#pragma pack(1) +#endif + +__PACK struct wlanllc_hdr { + struct wlan_hdr wlanhdr; +#if defined(CONFIG_RTL_WAPI_SUPPORT) + wpiSMS4Hdr sms4hdr; //always be used for wapi wlan hdr: iv [and mic] +#endif + struct llc_snap llcsnaphdr; +} __WLAN_ATTRIB_PACK__; + +#if defined(GREEN_HILL) || defined(PACK_STRUCTURE) || defined(__ECOS) +#pragma pack() +#endif + +struct wlanllc_node { + struct list_head list; +#ifdef TX_EARLY_MODE + unsigned char em_info[8]; // early mode info +#endif + struct wlanllc_hdr hdr; + +#ifdef CONFIG_RTK_MESH + unsigned char amsdu_header[30]; +#else + unsigned char amsdu_header[14]; +#endif + +}; + +struct wlanllc_hdr_poll { + struct wlanllc_node hdrnode[PRE_ALLOCATED_HDR]; + int count; +}; + +struct wlanbuf_node { + struct list_head list; + unsigned int buf[PRE_ALLOCATED_BUFSIZE]; // 4 bytes alignment! +}; + +struct wlanbuf_poll { + struct wlanbuf_node hdrnode[PRE_ALLOCATED_MMPDU]; + int count; +}; + +struct wlanicv_node { + struct list_head list; + unsigned int icv[2]; +}; + +struct wlanicv_poll { + struct wlanicv_node hdrnode[PRE_ALLOCATED_HDR]; + int count; +}; + +struct wlanmic_node { + struct list_head list; + unsigned int mic[2]; +}; + +struct wlanmic_poll { + struct wlanmic_node hdrnode[PRE_ALLOCATED_HDR]; + int count; +}; + +struct wlan_acl_node { + struct list_head list; + unsigned char addr[MACADDRLEN]; + unsigned char mode; +}; + +struct wlan_acl_poll { + struct wlan_acl_node aclnode[NUM_ACL]; +}; + +#if defined(CONFIG_RTK_MESH) && defined(_MESH_ACL_ENABLE_) +struct mesh_acl_poll { + struct wlan_acl_node meshaclnode[NUM_MESH_ACL]; +}; +#endif +struct tx_insn { + unsigned int q_num; + void *pframe; + unsigned char *phdr; //in case of mgt frame, phdr is wlan_hdr, + //in case of data, phdr = wlan + llc + unsigned int hdr_len; + unsigned int fr_type; + unsigned int fr_len; + unsigned int frg_num; + unsigned int need_ack; + unsigned int frag_thrshld; + unsigned int rts_thrshld; + unsigned int privacy; + unsigned int iv; + unsigned int icv; + unsigned int mic; + unsigned char llc; + unsigned char tx_rate; + unsigned char lowest_tx_rate; + unsigned char fixed_rate; + unsigned char retry; + unsigned char aggre_en; +// unsigned char tpt_pkt; + unsigned char one_txdesc; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + unsigned char is_dhcp; + unsigned char is_mcast; +#endif +#ifdef WDS + int wdsIdx; +#endif +#ifdef CONFIG_IEEE80211W + unsigned char isPMF; +#endif + struct stat_info *pstat; + +#ifdef CONFIG_RTK_MESH + unsigned char is_11s; // for transmitting 11s data frame (to rewrite 4 addresses) + unsigned char nhop_11s[MACADDRLEN]; // to record "da" in start_xmit + unsigned char prehop_11s[MACADDRLEN]; + struct lls_mesh_header mesh_header; + DRV_PRIV * priv; +#endif + +#ifdef SUPPORT_TX_MCAST2UNI + unsigned char isMC2UC; +#endif +#ifdef BEAMFORMING_SUPPORT + unsigned char ndpa; +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + // From here, data will not be overwritten by tx_sc_entry.txcfg when matching TX shortcut condition + struct xmit_frame *pxmitframe; + struct xmit_buf *pxmitbuf; + unsigned char is_pspoll; + unsigned char is_urgent; + unsigned char next_txpath; +#endif +}; + +#ifdef CONFIG_USB_HCI +#include "./usb/8188eu/8192cd_usb_xmit.h" +#endif + +#ifdef CONFIG_SDIO_HCI +#ifdef CONFIG_RTL_88E_SUPPORT +#include "./sdio/8189es/8188e_sdio_xmit.h" +#endif +#ifdef CONFIG_WLAN_HAL_8192EE +#include "./sdio/8192es/8192e_sdio_xmit.h" +#endif +#endif + +#ifdef CONFIG_RTK_MESH +struct mesh_txcache_t { + unsigned char dirty,ether_da[MACADDRLEN],ether_sa[MACADDRLEN]; + struct proxy_table_entry *da_proxy; + struct tx_insn txcfg; +}; +#endif + +struct reorder_ctrl_entry { + struct sk_buff *packet_q[RC_ENTRY_NUM]; + unsigned char start_rcv; + short rc_timer_id; + unsigned short win_start; + unsigned short last_seq; +}; + +#ifdef SUPPORT_TX_MCAST2UNI +struct ip_mcast_info { + int used; + unsigned char mcmac[MACADDRLEN]; +}; +#endif + +#ifdef TX_SHORTCUT +#if defined(CONFIG_PCI_HCI) +struct tx_sc_entry { + struct tx_insn txcfg; + struct wlanllc_hdr wlanhdr; +#ifdef CONFIG_WLAN_HAL +// PVOID phw_desc1; +// 40 is SIZE_TXDESC_88XX + u1Byte hal_hw_desc[40]; +#endif // CONFIG_WLAN_HAL + struct tx_desc hwdesc1; + struct tx_desc hwdesc2; + struct tx_desc_info swdesc1; + struct tx_desc_info swdesc2; +#ifdef TX_SCATTER + struct tx_desc hwdesc3; + struct tx_desc_info swdesc3; + int has_desc3; +#endif + int sc_keyid; + struct wlan_ethhdr_t ethhdr; + unsigned char pktpri; +}; + +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +struct tx_sc_entry { + struct tx_insn txcfg; + struct wlanllc_hdr wlanhdr; + struct tx_desc hwdesc1; + struct tx_desc_info swdesc1; + int sc_keyid; + struct wlan_ethhdr_t ethhdr; +}; +#endif +#endif // TX_SHORTCUT + +#ifdef RX_SHORTCUT +struct rx_sc_entry { + int rx_payload_offset; + int rx_trim_pad; + struct wlan_ethhdr_t rx_ethhdr; + struct wlan_hdr rx_wlanhdr; +}; +#endif + +#ifdef SW_TX_QUEUE +#define CHECK_DEC_AGGN 0 +#define CHECK_INC_AGGN 1 +#define MAX_BACKOFF_CNT 8 + +struct sw_tx_q { + struct sk_buff_head be_queue; + struct sk_buff_head bk_queue; + struct sk_buff_head vi_queue; + struct sk_buff_head vo_queue; + struct timer_list beq_timer; + struct timer_list bkq_timer; + struct timer_list viq_timer; + struct timer_list voq_timer; + int beq_empty; //0:empty; 1:not empty + int bkq_empty; + int viq_empty; + int voq_empty; + int q_aggnum[8]; + int q_TOCount[8]; + unsigned char q_used[8]; + unsigned char q_aggnumIncSlow[8]; +}; +#endif + +struct stat_info { + struct list_head hash_list; // always keep the has_list as the first item, to accelerat searching + struct list_head asoc_list; + struct list_head auth_list; + struct list_head sleep_list; + struct list_head defrag_list; + struct list_head wakeup_list; + struct list_head frag_list; +#ifdef CONFIG_PCI_HCI + struct list_head addRAtid_list; // to avoid add RAtid fail + struct list_head addrssi_list; + struct list_head addps_list; +#endif +#if defined(CONFIG_PCI_HCI) + struct sk_buff_head dz_queue; // Queue for sleeping mode +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct list_head pspoll_list; +#endif + +#ifdef SW_TX_QUEUE + struct sw_tx_q swq; +#endif + +#ifdef CONFIG_RTK_MESH + struct list_head mesh_mp_ptr; // MESH MP list +#endif + +#ifdef A4_STA + struct list_head a4_sta_list; +#endif + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + WPA_STA_INFO *wpa_sta_info; +#endif + +#ifdef TLN_STATS + unsigned int enterpise_wpa_info; +#endif + +#if defined(WIFI_HAPD) || defined(RTK_NL80211) + u_int8_t wpa_ie[256]; +#ifndef HAPD_DRV_PSK_WPS + u_int8_t wps_ie[256]; +#endif +#endif + +#if defined(WIFI_WMM) && defined(WMM_APSD) + unsigned char apsd_bitmap; // bit 0: VO, bit 1: VI, bit 2: BK, bit 3: BE + unsigned int apsd_pkt_buffering; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + unsigned int apsd_trigger; +#endif +#endif + +#ifdef CONFIG_PCI_HCI +#if defined(WIFI_WMM) && defined(WMM_APSD) + struct apsd_pkt_queue *VO_dz_queue; + struct apsd_pkt_queue *VI_dz_queue; + struct apsd_pkt_queue *BE_dz_queue; + struct apsd_pkt_queue *BK_dz_queue; +#endif + +#if defined(WIFI_WMM) + struct dz_mgmt_queue *MGT_dz_queue; +#ifdef DZ_ADDBA_RSP + struct dz_addba_info dz_addba; +#endif +#endif +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct tx_servq tx_queue[MAX_STA_TX_SERV_QUEUE]; // Mgnt/BK/BE/VI/VO +#ifdef CONFIG_TCP_ACK_TXAGG + struct tcpack_servq tcpack_queue[MAX_STA_TX_SERV_QUEUE]; // Mgnt(unused)/BK/BE/VI/VO +#endif + unsigned long pending_cmd; + int asoc_list_refcnt; +#ifdef __ECOS + cyg_flag_t asoc_unref_done; +#else + struct completion asoc_unref_done; +#endif +#endif + + struct reorder_ctrl_entry rc_entry[8]; + + /**************************************************************** + * from here on, data will be clear in init_stainfo() except "aid" and "hwaddr" * + ****************************************************************/ + unsigned int auth_seq; + unsigned char chg_txt[128]; + + unsigned int frag_to; + unsigned int frag_count; + unsigned int sleep_to; + unsigned short tpcache[8][TUPLE_WINDOW]; + unsigned short tpcache_mgt; // mgt cache number + +#ifdef CLIENT_MODE + unsigned short tpcache_mcast; // for client mode broadcast or multicast used +#endif + +#ifdef _DEBUG_RTL8192CD_ + unsigned int rx_amsdu_err; + unsigned int rx_amsdu_1pkt; + unsigned int rx_amsdu_2pkt; + unsigned int rx_amsdu_3pkt; + unsigned int rx_amsdu_4pkt; + unsigned int rx_amsdu_5pkt; + unsigned int rx_amsdu_gt5pkt; + + unsigned int rx_rc_drop1; + unsigned int rx_rc_drop3; + unsigned int rx_rc_drop4; + unsigned int rx_rc_reorder3; + unsigned int rx_rc_reorder4; + unsigned int rx_rc_passup2; + unsigned int rx_rc_passup3; + unsigned int rx_rc_passup4; + unsigned int rx_rc_passupi; +#endif + +#if defined(CLIENT_MODE) || defined(WDS) + unsigned int beacon_num; +#endif + +#ifdef TX_SHORTCUT +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct tx_sc_entry tx_sc_ent[NR_NET80211_UP][TX_SC_ENTRY_NUM]; + int tx_sc_replace_idx[NR_NET80211_UP]; +#else + struct tx_sc_entry tx_sc_ent[TX_SC_ENTRY_NUM]; + int tx_sc_replace_idx; +#endif + int protection; + unsigned int ht_protection; + unsigned int tx_sc_pkts_lv1; + unsigned int tx_sc_pkts_lv2; + unsigned int tx_sc_pkts_slow; +#endif + +#ifdef RX_SHORTCUT + struct rx_sc_entry rx_sc_ent[RX_SC_ENTRY_NUM]; + int rx_sc_replace_idx; + int rx_privacy; + unsigned int rx_sc_pkts; + unsigned int rx_sc_pkts_slow; +#endif + +#ifdef SUPPORT_TX_AMSDU + struct sk_buff_head amsdu_tx_que[8]; + int amsdu_timer_id[8]; + int amsdu_size[8]; +#endif + + /****************************************************************** + * from here to end, data will be backup when doing FAST_RECOVERY * + ******************************************************************/ + unsigned short aid; + + unsigned short remapped_aid;// support up to 64 clients + int sta_in_firmware; + + unsigned char hwaddr[MACADDRLEN]; +#ifdef WIFI_WMM + unsigned int QosEnabled; + unsigned short AC_seq[8]; +#endif + enum wifi_state state; +#ifdef HW_DETEC_POWER_STATE + unsigned char pwr_state; +#endif + unsigned int AuthAlgrthm; // could be open/shared key + unsigned int ieee8021x_ctrlport; // 0 for blocked, 1 for open + unsigned int keyid; // this could only be valid in legacy wep + unsigned int keylen; + struct Dot11KeyMappingsEntry dot11KeyMapping; + unsigned char bssrateset[32]; + unsigned int bssratelen; + unsigned int useShortPreamble; + unsigned int expire_to; + unsigned int idle_count; + unsigned char rssi; + unsigned char sq; + unsigned char rx_rate; + unsigned char rx_bw; + unsigned char rx_splcp; + struct rf_misc_info rf_info; + unsigned short seq_backup; + unsigned char rssi_backup; + unsigned char sq_backup; + unsigned char rx_rate_backup; + unsigned char rx_bw_backup; + unsigned char rx_splcp_backup; + struct rf_misc_info rf_info_backup; + int cck_mimorssi_total[4]; + unsigned char cck_rssi_num; + unsigned char highest_rx_rate; + unsigned char rssi_level; + unsigned char hp_level; + unsigned char is_realtek_sta; +#if 1 + UINT8 IOTPeer; // Enum value. HT_IOT_PEER_E +#else +//#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) + unsigned char is_apclient; + unsigned char is_rtl8192s_sta; + unsigned char is_rtl8192cd_apclient; + unsigned char is_rtl81xxc_sta; + unsigned char is_broadcom_sta; + unsigned char is_ralink_sta; + unsigned char is_marvell_sta; + unsigned char is_intel_sta; +#ifdef RTK_WOW + unsigned char is_rtk_wow_sta; +#endif + +#endif + unsigned char leave; + unsigned char no_rts; + unsigned char disable_ldpc; + unsigned char is_2t_mimo_sta; + unsigned int check_init_tx_rate; + + unsigned char is_forced_ampdu; + unsigned char is_forced_rts; + unsigned char aggre_mthd; + unsigned char tx_bw; + unsigned char tx_bw_fw; + unsigned char ht_current_tx_info; // bit0: 0=20M mode, 1=40M mode; bit1: 0=longGI, 1=shortGI + unsigned char tmp_rmv_key; + unsigned long link_time; + unsigned char private_ie[32]; + unsigned int private_ie_len; + unsigned int tx_ra_bitmap; + + unsigned int txrpt_tx_bytes_pre; + unsigned int txrpt_tx_ok_chk_cnt; + + unsigned int tx_bytes; + unsigned int rx_bytes; +#ifdef RADIUS_ACCOUNTING + unsigned int tx_bytes_1m; + unsigned int rx_bytes_1m; +#endif + unsigned int tx_pkts; + unsigned int rx_pkts; + unsigned int tx_fail; + unsigned int tx_pkts_pre; + unsigned int rx_pkts_pre; + unsigned int tx_fail_pre; + unsigned int current_tx_rate; + unsigned int tx_byte_cnt; + unsigned int tx_byte_cnt_odm; + unsigned int tx_byte_cnt_LowMAW; // TX byte conter with lower moving average weighting + unsigned int tx_avarage; + unsigned int rx_byte_cnt; + unsigned int rx_byte_cnt_odm; + unsigned int rx_byte_cnt_LowMAW; //RX byte conter with lower moving average weighting + unsigned int rx_avarage; + unsigned int tx_conti_fail_cnt; // continuous tx fail count; added by Annie, 2010-08-10. + unsigned long tx_last_good_time; // up_time record for last good tx; added by Annie, 2010-08-10. + unsigned long rx_last_good_time; // up_time record for rx resume time, added by Eric, 2013-01-18. +#ifdef CONFIG_WLAN_HAL + unsigned char bDrop; +#endif + // bcm old 11n chipset iot debug, and TXOP enlarge + unsigned int current_tx_bytes; + unsigned int current_rx_bytes; + +#ifdef PREVENT_BROADCAST_STORM + unsigned int rx_pkts_bc; +#endif + +#ifdef WDS + int wds_idx; + unsigned int wds_probe_done; + unsigned int idle_time; +#endif + +#ifdef RTK_AC_SUPPORT + struct vht_cap_elmt vht_cap_buf; + unsigned int vht_cap_len; + struct vht_oper_elmt vht_oper_buf; + unsigned int vht_oper_len; + unsigned char nss; +#endif +#ifdef BEAMFORMING_SUPPORT + unsigned int p_aid; + unsigned char g_id; + unsigned int bf_score; +#endif + + unsigned char ratr_idx; + unsigned char ratr_idx_init; + + struct ht_cap_elmt ht_cap_buf; + unsigned int ht_cap_len; + struct ht_info_elmt ht_ie_buf; + unsigned int ht_ie_len; + unsigned char cam_id; + unsigned char MIMO_ps; + unsigned char dialog_token; + unsigned char is_8k_amsdu; + unsigned char ADDBA_ready[8]; + unsigned char ADDBA_req_num[8]; + unsigned char ADDBA_sent[8]; + unsigned int diffAmpduSz; + unsigned int amsdu_level; + unsigned char tmp_mic_key[8]; + +#ifdef GBWC + unsigned char GBWC_in_group; +#endif +#ifdef INDICATE_LINK_CHANGE + unsigned char link_up; +#endif + + unsigned int is_legacy_encrpt; // 1: TKIP, 2: WEP + +#ifdef SUPPORT_TX_MCAST2UNI + int ipmc_num; + struct ip_mcast_info ipmc[MAX_IP_MC_ENTRY]; +#endif + +#ifdef USB_PKT_RATE_CTRL_SUPPORT + unsigned int change_toggle; +#endif + +#ifdef CONFIG_RTK_MESH + struct MESH_Neighbor_Entry mesh_neighbor_TBL; //mesh_neighbor + + // Throughput statistics (sounder) + // struct flow_stats f_stats; +#endif +#ifdef CONFIG_RTL_WAPI_SUPPORT + wapiStaInfo *wapiInfo; +#endif +#if defined (HW_ANT_SWITCH) && (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + int hwRxAntSel[2]; + int AntRSSI[2]; + int cckPktCount[2]; + char CurAntenna; +#endif + unsigned int retry_inc; + +#if defined(HS2_SUPPORT) || defined(UNIVERSAL_REPEATER) + /* Hotspot 2.0 Release 1 */ + unsigned char sta_ip[4]; +#endif +#ifdef CONFIG_IEEE80211W + unsigned char isPMF; + unsigned short SA_TID[SA_QUERY_MAX_NUM+1]; // Security Association Transaction ID + struct timer_list SA_timer; // SA_timer: Security Association timer + unsigned long sa_query_start; + unsigned long sa_query_end; + int sa_query_timed_out; + int sa_query_count; +#endif +#if defined(HS2_SUPPORT) + struct in6_addr sta_v6ip; +#endif +#ifdef P2P_SUPPORT + unsigned char is_p2p_client; +#endif + +#ifdef TX_EARLY_MODE + int empkt_num; // how many pending packet in next + int emextra_len; // extra 802.11 length for each 802.3 pkt + int empkt_len[10]; // packet length for next pending packet +#endif + unsigned long def_expired_time; + unsigned long def_expired_throughput; +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + unsigned char txpause_flag; + unsigned long txpause_time; +#endif + UINT8 WirelessMode; // + +#ifdef USE_OUT_SRC + // Driver Write +// BOOLEAN bValid; // record the sta status link or not? +// UINT8 IOTPeer; // Enum value. HT_IOT_PEER_E + + // ODM Write + //1 PHY_STATUS_INFO + UINT8 RSSI_Path[4]; // + UINT8 RSSI_Ave; + UINT8 RXEVM[4]; + UINT8 RXSNR[4]; + RSSI_STA rssi_stat; +#endif + unsigned int low_tp_disable_ampdu; + unsigned long uk_timeout; +#ifdef MULTI_MAC_CLONE + int mclone_id; + unsigned char sa_addr[MACADDRLEN]; +#endif +#ifdef RTK_NL80211//survey_dump + unsigned int tx_time_total; + unsigned int tx_byte_last; + unsigned int rx_time_total; + unsigned int rx_byte_last; +#endif +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + unsigned long sleep_time; +#endif +}; + + +/* + * Driver open, alloc whole amount of aid_obj, avoid memory fragmentation + * If STA Association , The aid_obj will chain to stat_info. + */ +struct aid_obj { + struct stat_info station; + unsigned int used; // used == TRUE => has been allocated, used == FALSE => can be allocated + struct rtl8192cd_priv *priv; +}; + +/* Note: always calculate the WLAN average throughput, if the throughput is larger than TP_HIGH_WATER_MARK, + gCpuCanSuspend will be FALSE. If the throughput is smaller than TP_LOW_WATER_MARK, + gCpuCanSuspend will be TRUE. + However, you can undefine the CONFIG_RTL8190_THROUGHPUT. The gCpuCanSuspend will always be + TRUE in this case. + */ +#define CONFIG_RTL8190_THROUGHPUT + +struct extra_stats { + unsigned long tx_retrys; + unsigned long tx_drops; + unsigned long rx_retrys; + unsigned long rx_decache; + unsigned long rx_data_drops; + unsigned long beacon_ok; + unsigned long beacon_er; + unsigned long beacon_dma_err; + unsigned long beaconQ_sts; +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8190_THROUGHPUT) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + unsigned long tx_peak; + unsigned long rx_peak; +#endif +#if 0 + unsigned long tx_dma_err; + unsigned long rx_dma_err; + unsigned long tx_dma_status; + unsigned long rx_dma_status; +#endif + + unsigned long tx_byte_cnt; + unsigned long tx_avarage; + unsigned long rx_byte_cnt; + unsigned long rx_avarage; + unsigned long rx_fifoO; + unsigned long rx_rdu; + unsigned long rx_reuse; + unsigned long freeskb_err; + unsigned long reused_skb; +#if defined(CONFIG_RTL_NOISE_CONTROL) || defined(CONFIG_RTL_NOISE_CONTROL_92C) + unsigned int tp_average_pre; +#endif + +#if defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + unsigned long tx_cnt_nosc; + unsigned long tx_cnt_sc1; + unsigned long tx_cnt_sc2; + unsigned long rx_cnt_nosc; + unsigned long rx_cnt_sc; + unsigned long br_cnt_nosc; + unsigned long br_cnt_sc; +#endif +}; + +enum { + fourWaystep1 = 1, + fourWaystep2, + fourWaystep3, + fourWaystep4 +}; + +#ifdef TLN_STATS +struct tln_wifi_stats { + unsigned long connected_sta; + unsigned long max_sta; + unsigned long max_sta_timestamp; + unsigned long rejected_sta; +}; + + +struct tln_ext_wifi_stats { + unsigned long rson_UNSPECIFIED_1; + unsigned long rson_AUTH_INVALID_2; + unsigned long rson_DEAUTH_STA_LEAVING_3; + unsigned long rson_INACTIVITY_4; + unsigned long rson_RESOURCE_INSUFFICIENT_5; + unsigned long rson_UNAUTH_CLS2FRAME_6; + unsigned long rson_UNAUTH_CLS3FRAME_7; + unsigned long rson_DISASSOC_STA_LEAVING_8; + unsigned long rson_ASSOC_BEFORE_AUTH_9; + unsigned long rson_INVALID_IE_13; + unsigned long rson_MIC_FAILURE_14; + unsigned long rson_4WAY_TIMEOUT_15; + unsigned long rson_GROUP_KEY_TIMEOUT_16; + unsigned long rson_DIFF_IE_17; + unsigned long rson_MCAST_CIPHER_INVALID_18; + unsigned long rson_UCAST_CIPHER_INVALID_19; + unsigned long rson_AKMP_INVALID_20; + unsigned long rson_UNSUPPORT_RSNIE_VER_21; + unsigned long rson_RSNIE_CAP_INVALID_22; + unsigned long rson_802_1X_AUTH_FAIL_23; + unsigned long rson_OUT_OF_SCOPE; + + unsigned long status_FAILURE_1; + unsigned long status_CAP_FAIL_10; + unsigned long status_NO_ASSOC_11; + unsigned long status_OTHER_12; + unsigned long status_NOT_SUPPORT_ALG_13; + unsigned long status_OUT_OF_AUTH_SEQ_14; + unsigned long status_CHALLENGE_FAIL_15; + unsigned long status_AUTH_TIMEOUT_16; + unsigned long status_RESOURCE_INSUFFICIENT_17; + unsigned long status_RATE_FAIL_18; + unsigned long status_OUT_OF_SCOPE; +}; +#endif + + +#ifdef WIFI_SIMPLE_CONFIG +#ifndef INCLUDE_WPS +/* this struct no sync with wsc daemon ; + add ssid for sorting by ssid intent ; wps_ie_info2 is sync with wsc daemon;take care*/ +struct wps_ie_info { + unsigned char rssi; + unsigned int wps_ie_len; + unsigned char data[MAX_WSC_IE_LEN]; + char ssid[33]; +}; + +/* this struct sync with wsc daemon ; when report wsc ie to daemon use this*/ +struct wps_ie_info2{ + unsigned char rssi; + unsigned char data[MAX_WSC_IE_LEN]; +}; +#endif + +#if defined(WIFI_WPAS) || defined(RTK_NL80211) +struct wpa_ie_info { + unsigned char rssi; + unsigned int wpa_ie_len; + unsigned char data[MAX_WPA_IE_LEN]; + char ssid[33]; + +}; +struct rsn_ie_info { + unsigned char rssi; + unsigned int rsn_ie_len ; + unsigned char data[MAX_RSN_IE_LEN]; + char ssid[33]; + +}; +struct p2p_ie_info { + unsigned char rssi; + unsigned int p2p_ie_len ; + unsigned char data[MAX_RSN_IE_LEN]; + char ssid[33]; + +}; +#ifdef RTK_NL80211_HS_CLI +struct hs_ie_info { + unsigned char rssi; + unsigned int hs_ie_len; + unsigned char data[MAX_RSN_IE_LEN]; + char ssid[33]; + +}; +#endif +#endif +#endif + +struct ss_res { + unsigned int ss_channel; + unsigned int count; + struct bss_desc bss[MAX_BSS_NUM]; + unsigned int count_backup; + struct bss_desc bss_backup[MAX_BSS_NUM]; + unsigned int count_target; + struct bss_desc bss_target[MAX_BSS_NUM]; +#ifdef WIFI_SIMPLE_CONFIG + struct wps_ie_info *wscie; + + /* this struct sync with wsc daemon ; when report wsc ie to daemon use this*/ + struct wps_ie_info2 *wscie_backup; +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + //unsigned char bk_nwtype; + //unsigned int bk_iqc[11]; +#endif +#if defined(WIFI_WPAS) || defined(RTK_NL80211) + struct wpa_ie_info wpa_ie[MAX_BSS_NUM]; + struct wpa_ie_info wpa_ie_backup[MAX_BSS_NUM]; + struct rsn_ie_info rsn_ie[MAX_BSS_NUM]; + struct rsn_ie_info rsn_ie_backup[MAX_BSS_NUM]; + struct p2p_ie_info rtk_p2p_ie[MAX_BSS_NUM]; +#endif +#ifdef CONFIG_RTL_NEW_AUTOCH + unsigned int to_scan_40M; + unsigned int start_ch_40M; +#endif + unsigned int hidden_ap_found; + unsigned int target_ap_found; + + unsigned char defered_ss; +}; + +#if defined(CONFIG_RTL_NEW_AUTOCH) && defined(SS_CH_LOAD_PROC) + +struct ss_report { + unsigned char channel; + unsigned char is40M; + unsigned char rssi; + unsigned short fa_count; + unsigned short cca_count; + unsigned int ch_load; +}; + +#endif + + +//struct stat_info_cache { +// struct stat_info *pstat; +// unsigned char hwaddr[6]; +//}; + +struct mc2u_flood_mac_entry { + unsigned char macAddr[MACADDRLEN]; +}; + +struct rf_finetune_var { + unsigned char ofdm_1ss_oneAnt;// for 2T2R + unsigned char pathB_1T; // for 1T2R, 1T1R + unsigned char rssi_dump; + unsigned char rxfifoO; + unsigned char raGoDownUpper; + unsigned char raGoDown20MLower; + unsigned char raGoDown40MLower; + unsigned char raGoUpUpper; + unsigned char raGoUp20MLower; + unsigned char raGoUp40MLower; + unsigned char dig_enable; + unsigned char adaptivity_enable; + unsigned char digGoLowerLevel; + unsigned char digGoUpperLevel; + unsigned char dcThUpper; + unsigned char dcThLower; + unsigned char rssiTx20MUpper; + unsigned char rssiTx20MLower; + unsigned char rssi_expire_to; + unsigned char dig_cov_enable; +//#ifdef INTERFERENCE_CONTROL + unsigned char nbi_filter_enable; +//#endif + unsigned char rts_init_rate; + unsigned char auto_rts_rate; + + unsigned char cck_pwr_max; + unsigned char cck_tx_pathB; + unsigned char min_pwr_idex; + + // dynamic Tx power control + unsigned char tx_pwr_ctrl; + + // 11n ap AES debug + unsigned char aes_check_th; + + // Tx power tracking + unsigned int tpt_period; + + // TXOP enlarge + unsigned char txop_enlarge_upper; + unsigned char txop_enlarge_lower; +#ifdef LOW_TP_TXOP + unsigned char low_tp_txop; + unsigned int low_tp_txop_thd_n; + unsigned int low_tp_txop_thd_g; + unsigned int low_tp_txop_thd_low; + unsigned char low_tp_txop_close; + unsigned char low_tp_txop_count; + unsigned char low_tp_txop_delay; + unsigned int cwmax_enhance_thd; +#endif + + // 2.3G support + unsigned char use_frq_2_3G; + + // for mp test +#ifdef MP_TEST + unsigned char mp_specific; +#endif + + //Support IP multicast->unicast +#ifdef SUPPORT_TX_MCAST2UNI + unsigned char mc2u_disable; +#ifdef IGMP_FILTER_CMO + unsigned char igmp_deny; +#endif + unsigned char mc2u_drop_unknown; + unsigned int mc2u_flood_ctrl; + struct mc2u_flood_mac_entry mc2u_flood_mac[MAX_FLOODING_MAC_NUM]; + unsigned int mc2u_flood_mac_num __attribute__ ((packed)); + +#endif + +#ifdef HIGH_POWER_EXT_PA + unsigned char hp_ofdm_pwr_max; + unsigned char hp_cck_pwr_max; +#endif +#if defined(RF_MIMO_SWITCH) || defined(RF_MIMO_PS) + unsigned char rf_mode; +#endif +#ifdef PCIE_POWER_SAVING + unsigned char power_save; +#endif +#ifdef HIGH_POWER_EXT_PA + unsigned char use_ext_pa; +#endif +#ifdef HIGH_POWER_EXT_LNA + unsigned char use_ext_lna; + unsigned char ext_lna_gain; +#endif + unsigned char NDSi_support; + + // for adaptivity + u1Byte IGI_target; + s1Byte IGI_Base; + s1Byte TH_L2H_ini; + s1Byte TH_L2H_ini_mode2; + s1Byte TH_L2H_ini_backup; + s1Byte TH_EDCCA_HL_diff; + s1Byte TH_EDCCA_HL_diff_mode2; + s1Byte TH_EDCCA_HL_diff_backup; + u2Byte NHM_cnt_0; + u2Byte NHM_cnt_1; + BOOLEAN adaptivity_flag; + s1Byte H2L_lb; + s1Byte L2H_lb; + u1Byte Adaptivity_IGI_upper; + u1Byte NHMWait; + BOOLEAN bFirstLink; + BOOLEAN bCheck; + u1Byte dcbackoff; + BOOLEAN adap_debug; + BOOLEAN DynamicLinkAdaptivity; + BOOLEAN Adaptivity_enable; + BOOLEAN bLinked; + // for adaptivity + +#ifdef ADD_TX_POWER_BY_CMD + char txPowerPlus_cck_1; + char txPowerPlus_cck_2; + char txPowerPlus_cck_5; + char txPowerPlus_cck_11; + char txPowerPlus_ofdm_6; + char txPowerPlus_ofdm_9; + char txPowerPlus_ofdm_12; + char txPowerPlus_ofdm_18; + char txPowerPlus_ofdm_24; + char txPowerPlus_ofdm_36; + char txPowerPlus_ofdm_48; + char txPowerPlus_ofdm_54; + char txPowerPlus_mcs_0; + char txPowerPlus_mcs_1; + char txPowerPlus_mcs_2; + char txPowerPlus_mcs_3; + char txPowerPlus_mcs_4; + char txPowerPlus_mcs_5; + char txPowerPlus_mcs_6; + char txPowerPlus_mcs_7; + char txPowerPlus_mcs_8; + char txPowerPlus_mcs_9; + char txPowerPlus_mcs_10; + char txPowerPlus_mcs_11; + char txPowerPlus_mcs_12; + char txPowerPlus_mcs_13; + char txPowerPlus_mcs_14; + char txPowerPlus_mcs_15; +#endif + + unsigned char rootFwBeacon; // use FW to send beacon + unsigned char ledBlinkingFreq; + + unsigned char diffAmpduSz; + unsigned char one_path_cca; // 0: 2-path, 1: path-A, 2: path-B +#ifdef CONFIG_1RCCA_RF_POWER_SAVING + unsigned char _1rcca_ps; // 0: disable, 1: enable, 2: auto + unsigned char _1rcca_ps_rssi_thd; +#endif +#ifdef DFS + unsigned char dfsdbgmode; + unsigned char dfs_force_TP_mode; + unsigned char dfsdelayiqk; + unsigned int dfs_next_ch; + unsigned int dfsdbgcnt; + unsigned long dfsrctime; + unsigned char dfs_det_off; + unsigned char dfs_det_reset; + unsigned char dfs_fa_cnt_lower; + unsigned char dfs_fa_cnt_mid; + unsigned int dfs_fa_cnt_upper; + unsigned char dfs_fa_cnt_inc_ratio; + unsigned char dfs_psd_delay; + unsigned char dfs_crc32_cnt_lower; + unsigned char dfs_fa_ratio_th; + unsigned char dfs_det_period; + unsigned char dfs_det_period_jp_w53; + unsigned char dfs_det_print; + unsigned char dfs_det_print1; + unsigned char dfs_det_print2; + unsigned char dfs_det_print3; + unsigned char dfs_det_print4; +#if defined(CONFIG_WLAN_HAL_8814AE) + unsigned char dfs_radar_diff_on; + unsigned char dfs_radar_diff_print; + unsigned char dfs_print_hist_report; +#endif + unsigned char dfs_det_print_psd; + unsigned char dfs_pulse_print; + unsigned char dfs_det_hist_len; + unsigned char dfs_det_sum_th; + unsigned char dfs_det_flag_offset; + unsigned int dfs_dpt_fa_th_upper; + unsigned char dfs_dpt_fa_th_lower; + unsigned int dfs_fa_hist; + unsigned char dfs_dpt_pulse_th_mid; + unsigned char dfs_dpt_pulse_th_lower; + unsigned char dfs_dpt_st_l2h_max; + unsigned char dfs_dpt_st_l2h_min; + unsigned char dfs_dpt_st_l2h_add; + unsigned char dfs_dpt_st_l2h_idle_offset; + unsigned char dpt_ini_gain_th; + unsigned char dfs_pwdb_th; + unsigned char dfs_pwdb_scalar_factor; + unsigned char dfs_psd_pw_th; + unsigned char psd_skip_lookup_table; + unsigned char dfs_psd_fir_decay; + unsigned char dfs_skip_iqk; + unsigned char dfs_scan_inband; + unsigned char dfs_psd_op; + unsigned char dfs_psd_idle_on; + unsigned char dfs_psd_TP_on; + unsigned char dfs_psd_tp_th; + unsigned char dfs_pc0_th_idle_w53; + unsigned char dfs_pc0_th_idle_w56; + unsigned char dfs_max_sht_pusle_cnt_th; +#endif + +#ifdef SW_TX_QUEUE + int swq_en_highthd; + int swq_dis_lowthd; + int swq_enable; + int swq_dbg; + int swq_aggnum; + int timeout_thd; + int timeout_thd2; + int timeout_thd3; +#endif + +#ifdef A4_STA + unsigned char a4_enable; +#endif + +#ifdef SW_ANT_SWITCH + unsigned char antSw_enable; +#endif + +#ifdef HW_ANT_SWITCH + unsigned char antHw_enable; + unsigned char CurAntenna; +#endif +#if defined(HW_ANT_SWITCH) || defined(SW_ANT_SWITCH) + unsigned char antSw_select; + unsigned char ant_dump; +#endif + +#ifdef RTL8192D_INT_PA + unsigned char use_intpa92d; +#endif +#ifdef CONFIG_WLAN_HAL_8881A + unsigned char use_intpa8881A; +#endif +#if defined(CONFIG_RTL_NOISE_CONTROL) || defined(CONFIG_RTL_NOISE_CONTROL_92C) + unsigned char dnc_enable; +#endif +#if defined(WIFI_11N_2040_COEXIST_EXT) + unsigned int bws_Thd; + unsigned char bws_enable; +#endif + unsigned char pwr_by_rate; +#ifdef _TRACKING_TABLE_FILE + unsigned char pwr_track_file; +#ifdef CONFIG_WLAN_HAL_8881A + unsigned char pwrtrk_TxAGC_enable; + char pwrtrk_TxAGC; +#endif +#endif +#ifdef DPK_92D + unsigned char dpk_on; +#endif + unsigned char disable_pwr_by_rate; +#if defined(TXPWR_LMT) + unsigned char disable_txpwrlmt; + unsigned char disable_txpwrlmt2path; +#endif +#ifdef CONFIG_RTL_92D_DMDP + unsigned char peerReinit; +#endif +#ifdef CONFIG_SDIO_TX_FILTER_BY_PRI + unsigned char tx_filter_enable; +#endif +#ifdef WIFI_WMM + unsigned char wifi_beq_iot; +#endif + unsigned char bcast_to_dzq; +#ifdef TLN_STATS + unsigned int stats_time_interval; +#endif +#ifdef TX_EARLY_MODE + unsigned char em_enable; + unsigned char em_que_num; + unsigned int em_swq_thd_high; + unsigned int em_swq_thd_low; +#endif +#ifdef CONFIG_TCP_ACK_TXAGG + unsigned char tcpack_agg; + unsigned char tcpack_merge; +#endif +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + unsigned char low_traffic_xmit_thd; +#endif + unsigned char low_retry_rssi_thd; + unsigned char low_rate_low_retry; +#ifdef RSSI_MIN_ADV_SEL + unsigned char rssi_min_advsel; +#endif +#ifdef CLIENT_MODE + unsigned char sta_mode_ps; +#endif +#ifdef CONFIG_RTL_WLAN_DOS_FILTER + unsigned int dos_block_time; +#endif + + unsigned int intel_rtylmt_tp_margin; + + unsigned char enable_macid_sleep; + +#ifdef CONFIG_RTL_88E_SUPPORT + unsigned char disable_pkt_pause; + unsigned char disable_pkt_nolink; + unsigned char max_pkt_fail; + unsigned char min_pkt_fail; +#endif + unsigned char low_tp_no_aggr; + +#ifdef BEAMFORMING_SUPPORT + unsigned int dumpcsi; + unsigned int csi_counter; + unsigned int soundingPeriod; + unsigned char soundingEnable; + unsigned char ndparate; + unsigned char ndpaaid; + unsigned char applyVmatrix; + unsigned char Nsnding3SS; +#endif + unsigned char use_cca; + + unsigned char oper_mode_field; + unsigned char opmtest; + +// channel switch announcement + unsigned char csa; + +// power constraint + unsigned char lpwrc; + unsigned int lgirate; + unsigned char no_rtscts; + unsigned char sigma_mode; + + unsigned char cca_rts; + + unsigned char txforce; + unsigned char sgiforce; +#ifdef CONFIG_WLAN_HAL_8192EE + unsigned int delay_8b4; + unsigned int thrd_8b4; + unsigned char loop_8b4; + unsigned char disable_ACPR; + unsigned char ldpc_92e; +#endif +#ifdef RTK_NL80211 +//mark_priv + unsigned int rtk_uci_AcEnable; + unsigned char rtk_uci_PrivBandwidth[6]; //5M,10M ,80M-,80M+ . +#endif +// unsigned char mp_dig_enable; + +#ifdef AC2G_256QAM + unsigned char ac2g_enable; //enable 11ac mode in phyband = 2g + unsigned char ac2g_phy_type; //0 = LNA, 1 = PA+LNA + unsigned int ac2g_thd_ldpc; //threshlod to enable/disable ldpc (by rssi level) +#endif + +#ifdef CHECK_HANGUP + unsigned int check_hang; +#endif + unsigned char auto_cipher; +#ifdef MCR_WIRELESS_EXTEND + unsigned char mcr_ft; + unsigned char disable_ldpc_thd; +#endif + unsigned char bcn_dont_ignore_edcca; // 0: disable, 1: when edcca on, bcn will not xmit +}; + +//Filen +// MESH WDS Type ACCESS_SWAP +// [9:8] [7:4] [3:2] [1:0] +// + +/* Bit mask value of type */ +#define ACCESS_SWAP_IO 0x01 /* Do bye-swap in access IO register */ +#define ACCESS_SWAP_MEM 0x02 /* Do byte-swap in access memory space */ + +#define ACCESS_MASK 0x3 +#define TYPE_SHIFT 2 +#define TYPE_MASK 0x3 + +#ifdef WDS +#define WDS_SHIFT 4 +#define WDS_MASK 0xf +#define WDS_NUM_CFG NUM_WDS +#ifdef LAZY_WDS +#define WDS_LAZY_ENABLE 2 +#endif + +#else +#define WDS_SHIFT 0 +#define WDS_NUM_CFG 0 +#endif + + +enum { + TYPE_EMBEDDED = 0, /* embedded wlan controller */ + TYPE_PCI_DIRECT = 1, /* PCI wlan controller and enable PCI bridge directly */ + TYPE_PCI_BIOS = 2 /* PCI wlan controller and enable PCI by BIOS */ +}; + + +enum { + DRV_STATE_INIT = 1, /* driver has been init */ + DRV_STATE_OPEN = 2, /* driver is opened */ +#if defined( UNIVERSAL_REPEATER) || defined(MBSSID) + DRV_STATE_VXD_INIT = 4, /* vxd driver has been opened */ + DRV_STATE_VXD_AP_STARTED = 8, /* vxd ap has been started */ +#endif +}; + +#ifdef RX_BUFFER_GATHER +enum { + GATHER_STATE_NO = 0, /* no data pending */ + GATHER_STATE_FIRST = 1, /* first segment */ + GATHER_STATE_MIDDLE = 2, /* niether first nor last segment */ + GATHER_STATE_LAST = 3 /* last segment */ +}; +#endif + +#ifdef CHECK_TX_HANGUP +#define PENDING_PERIOD 60 // max time of pending period + + +struct desc_check_info { + int pending_tick; // tick value when pending is detected + int pending_tail; // descriptor tail number when pending is detected + int idle_tick; // tick value when detect idle (tx desc is not free) +}; +#endif + + +// MAC access control log definition +#define MAX_AC_LOG 32 // max number of log entry +#define AC_LOG_TIME 300 // log time in sec +#define AC_LOG_EXPIRE RTL_SECONDS_TO_JIFFIES(3) // entry expire time + +struct ac_log_info { + int used; // <>0: in use + int cur_cnt; // current attack counter + int last_cnt; // counter of last time log + unsigned long last_attack_time; // jiffies time of last attack + unsigned char addr[MACADDRLEN]; // mac address +}; + +#ifdef WIFI_SIMPLE_CONFIG +struct wsc_probe_request_info { + unsigned char addr[MACADDRLEN]; // mac address + char ProbeIE[PROBEIELEN]; + unsigned short ProbeIELen; + unsigned long time_stamp; // jiffies time of last probe request + unsigned char used; + unsigned char pbcactived; /* 0528pbc */ +}; +#endif + +struct sta_mac_rssi { + unsigned char addr[MACADDRLEN]; + unsigned char rssi; + unsigned char used; + unsigned char Entry; +}; + +struct reorder_ctrl_timer { + struct rtl8192cd_priv *priv; + struct stat_info *pstat; + unsigned char tid; + unsigned int timeout; +}; + +#ifdef RTK_QUE +struct ring_que { + int qlen; + int qmax; + int head; + int tail; + struct sk_buff *ring[MAX_PRE_ALLOC_SKB_NUM + 1]; +}; +#endif + +#ifdef USE_TXQUEUE +struct txq_node { + struct list_head list; + struct sk_buff *skb; + struct net_device *dev; +}; +struct txq_list_head { + struct list_head list; + unsigned int qlen; +}; + +#define init_txq_head(_q) \ + do { \ + INIT_LIST_HEAD(&((_q)->list)); \ + (_q)->qlen = 0; \ + }while(0) +#define is_txq_empty(_q) ((_q)->qlen ? 0 : 1) +#define txq_len(_q) ((_q)->qlen) +#define add_txq_tail(_q, _n) \ + do { \ + list_add_tail(&((_n)->list), &((_q)->list)); \ + (_q)->qlen ++; \ + }while(0) +#define add_txq_head(_q, _n) \ + do { \ + list_add(&((_n)->list), &((_q)->list)); \ + (_q)->qlen ++; \ + }while(0) +#define unlink_txq(_q, _n) \ + do { \ + list_del(&((_n)->list)); \ + (_q)->qlen --; \ + }while(0) +#define deq_txq(_q) \ + ( (_q)->qlen ? (struct txq_node *)((_q)->list.next) : NULL ); \ + unlink_txq(_q, (struct txq_node *)((_q)->list.next)); +#endif + +#ifdef A4_STA +#define A4_STA_HASH_BITS 3 +#define A4_STA_HASH_SIZE (1 << A4_STA_HASH_BITS) +#define A4_STA_AGEING_TIME 300 +#define MAX_A4_TBL_NUM 32 + +struct a4_sta_db_entry { + struct a4_sta_db_entry *next_hash; + struct a4_sta_db_entry **pprev_hash; + unsigned char mac[6]; + unsigned long ageing_timer; + struct stat_info *stat; +}; + +struct a4_tbl_entry { + int used; + struct a4_sta_db_entry entry; +}; +#endif + +#ifdef SW_ANT_SWITCH + +// 20100503 Joseph: +// Add new function SwAntDivCheck8192C(). +// This is the main function of Antenna diversity function before link. +// Mainly, it just retains last scan result and scan again. +// After that, it compares the scan result to see which one gets better RSSI. +// It selects antenna with better receiving power and returns better scan result. +// +#define TP_MODE 0 +#define RSSI_MODE 1 +#define TRAFFIC_LOW 0 +#define TRAFFIC_HIGH 1 +#define TRAFFIC_THRESHOLD 6600000 // 16 Mbps +#define TP_MODE_THD 200000 //500 kbps + +#define SELANT_MAP_SIZE 8 + +// 20100514 Joseph: Add definition for antenna switching test after link. +// This indicates two different the steps. +// In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. +// In SWAW_STEP_DETERMINE, driver just compares the signal captured in SWAW_STEP_PEAK +// with original RSSI to determine if it is necessary to switch antenna. +#define SWAW_STEP_PEAK 0 +#define SWAW_STEP_DETERMINE 1 +#define SWAW_STEP_RESET 0xff + +typedef struct _SW_Antenna_Switch_ { + unsigned char try_flag; + unsigned char CurAntenna; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + unsigned char NextAntenna; +#endif + unsigned char RSSI_Trying; + unsigned char TestMode; + int SelectAntennaMap[2][SELANT_MAP_SIZE]; + unsigned char mapIndex; +} SWAT_T; + +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#if defined(SW_ANT_SWITCH) || defined(HW_ANT_SWITCH) + +typedef enum tag_SW_Antenna_Switch_Definition { + Antenna_L = 1, + Antenna_R = 2, + Antenna_MAX = 3, +} DM_SWAS_E; +#endif +#endif + + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) +typedef struct StationInfoRAStruct { + unsigned char RateID; // old rate id, by every conn per station + unsigned int RateMask; // old rate mask + unsigned int RAUseRate; + unsigned char RateSGI; // use SGI by decision + unsigned char RssiStaRA; + unsigned char PreRssiStaRA; + unsigned char SGIEnable; // set if station support SGI, by every conn per station + unsigned char DecisionRate; // update txrate info for desc setting + unsigned char PreRate; + unsigned char HighestRate; + unsigned char LowestRate; + unsigned int NscUp; + unsigned int NscDown; + unsigned short RTY[5]; + unsigned int TOTAL; + unsigned short DROP; + unsigned char Active; + unsigned short RptTime; +#if 1 + unsigned char RAWaitingCounter; + unsigned char RAPendingCounter; +#endif +#if 0 + unsigned char TryingState; + unsigned char RateBeforeTrying; +#endif + struct stat_info *pstat; +} STATION_RA_INFO, *PSTATION_RA_INFO; +#endif + + +#if defined(CONFIG_RTL_88E_SUPPORT) && !defined(CALIBRATE_BY_ODM) //for 88e tx power tracking + +#define IQK_Matrix_REG_NUM 8 + +typedef struct _IQK_MATRIX_REGS_SETTING { + char bIQKDone; + int Value[1][IQK_Matrix_REG_NUM]; +} IQK_MATRIX_REGS_SETTING, *PIQK_MATRIX_REGS_SETTING; + +#endif + + +#ifdef MULTI_MAC_CLONE +#define MAX_MBIDCAM_NUM 20 +#define MAX_MAC_CLONE_NUM 16 +#define MAC_CLONE_MBIDCAM_START (MAX_MBIDCAM_NUM - MAX_MAC_CLONE_NUM) +#define MCLONE_STA_ADDR_DEFAULT "\x0\xe0\x4c\xff\xff\xf0" + +#define MAC_CLONE_NOCARE_FIND 0 +#define MAC_CLONE_DA_FIND 1 +#define MAC_CLONE_SA_FIND 2 +#define MAC_CLONE_MSA_FIND 3 + +struct mclone_timer_data { + struct rtl8192cd_priv *priv; + unsigned long active_id; +}; + +struct mclone_sta_addr { + unsigned char clone_addr[MACADDRLEN]; // mac address + unsigned char used; // used or not +}; + +struct mclone_sta_info { + unsigned char hwaddr[MACADDRLEN]; // addr used in 802.11 mac header + unsigned char sa_addr[MACADDRLEN]; // original STA's mac addr + unsigned char usedStaAddrId; // sync to which mclone_sta_addr used + unsigned char isTimerInit; // timer initialized or not + unsigned short aid; + struct mclone_timer_data timer_data; + struct timer_list reauth_timer; + int reauth_count; + struct timer_list reassoc_timer; + int reassoc_count; + int auth_seq; + unsigned int opmode; + unsigned int join_res; + unsigned int join_req_ongoing; + unsigned char chg_txt[128]; + int authModeToggle; + int authModeRetry; + struct rtl8192cd_priv *priv; // 1)associated interface 2)used or not +}; +#endif + +typedef struct _sta_bitmap_{ + unsigned int _staMap_; + #if (NUM_STAT >32) + unsigned int _staMap_ext_1; + #if (NUM_STAT >64) + unsigned int _staMap_ext_2; + unsigned int _staMap_ext_3; + #endif + #endif +} STA_BITMAP, *PSTA_BITMAP; + +// common private structure which info are shared between root interface and virtual interface +struct priv_shared_info { + +#ifdef RTK_NL80211 /*cfg p2p cfg p2p*/ + /*=for========remain on channel=============*/ + int deny_scan_myself; // when p2p on nego with other peer , deny scan my self + int rtk_remain_on_channel; + + /*=for========remain on channel=============*/ +#endif + unsigned int type; + unsigned long ioaddr; + unsigned int version_id; +#ifdef IO_MAPPING + unsigned int io_mapping; +#endif + +#ifdef USE_CHAR_DEV + struct rtl8192cd_chr_priv *chr_priv; +#endif +#ifdef USE_PID_NOTIFY + pid_t wlanapp_pid; +#endif + +#ifdef CONFIG_RTL_WAPI_SUPPORT + pid_t wlanwapi_pid; +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_NET_PCI + struct pci_dev *pdev; +#endif +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI + //For 92D, DMDP have 2 interface. + u8 InterfaceNumber; + u8 NumInterfaces; + + u8 nr_endpoint; + u8 ishighspeed; + u8 RtNumInPipes; + u8 RtNumOutPipes; + int ep_num[5]; //endpoint number + +#ifdef CONFIG_USB_VENDOR_REQ_MUTEX + _mutex usb_vendor_req_mutex; +#endif + +#ifdef CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC + u8 * usb_alloc_vendor_req_buf; + u8 * usb_vendor_req_buf; +#endif +#ifdef MBSSID + _mutex mbssid_lock; + u32 inter_bcn_space; +#endif // MBSSID + int nr_bcn; + struct rtl8192cd_priv *bcn_priv[RTL8192CD_NUM_VWLAN+1]; + + struct usb_interface *pusbintf; + struct usb_device *pusbdev; + + atomic_t continual_urb_error; + + u8 bDriverStopped; + u8 bSurpriseRemoved; +#ifdef CONFIG_RTL_92C_SUPPORT + u8 bCardDisableWOHSM; +#endif + + u8 bReadPortCancel; + u8 bWritePortCancel; + + u8 BoardType; + + u16 EEPROMVID; + u16 EEPROMPID; + u8 EEPROMCustomerID; + u8 EEPROMSubCustomerID; + + HAL_INTF_DATA_TYPE *pHalData; + + // xmit priv + _queue tx_pending_sta_queue[MAX_HW_TX_QUEUE]; + _queue tx_urb_waiting_queue[MAX_HW_TX_QUEUE]; + _queue tx_urgent_queue; + struct tx_servq pspoll_sta_queue; + volatile unsigned long use_hw_queue_bitmap; // each bit corresponds to one HW TX queue + + _queue free_xmit_queue; + u8 *pallocated_frame_buf; + u8 *pxmit_frame_buf; + + _queue free_xmitbuf_queue; + u8 *pallocated_xmitbuf; + u8 *pxmitbuf; + + _queue free_xmit_extbuf_queue; + u8 *pallocated_xmit_extbuf; + u8 *pxmit_extbuf; + + _queue free_urg_xmitbuf_queue; + u8 *pallocated_urg_xmitbuf; + u8 *pxmitbuf_urg; + + _queue free_bcn_xmitbuf_queue; + u8 *pallocated_bcn_xmitbuf; + u8 *pbcn_xmitbuf; + +#ifdef CONFIG_TCP_ACK_TXAGG + _queue tcpack_queue; +#endif + // CONFIG_XMITBUF_TXAGG_ADV + unsigned long txagg_timeout[MAX_STA_TX_SERV_QUEUE]; + volatile unsigned long need_sched_xmit; + unsigned long low_traffic_xmit; + unsigned int low_traffic_xmit_stats[MAX_STA_TX_SERV_QUEUE]; + struct timer_list xmit_check_timer; + + struct tasklet_struct xmit_tasklet; + + // cmd priv + unsigned long cmd_wake; + wait_queue_head_t waitqueue; + struct task_struct *cmd_thread; + struct completion cmd_thread_done; + _queue cmd_queue; + _queue rx_mgt_queue; +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + _queue h2c_cmd_queue; + struct timer_list chk_h2c_buf_timer; +#endif + unsigned long pending_cmd[BITS_TO_LONGS(MAX_RTW_CMD_CODE)]; +#ifdef CMD_THREAD_FUNC_DEBUG + void *cur_cmd_func; // reocrd which function is doing in cmd_thread +#endif + + _queue timer_evt_queue; +#if defined(CONFIG_RTL_92C_SUPPORT) || (!defined(CONFIG_SUPPORT_USB_INT) || !defined(CONFIG_INTERRUPT_BASED_TXBCN)) + struct timer_list beacon_timer; + struct timer_event_entry beacon_timer_event; +#endif +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI +#ifdef SDIO_AP_OFFLOAD + u8 offload_function_ctrl; + u8 ps_ctrl; + u8 pwr_state; + struct timer_list ps_timer; + unsigned long ps_timer_expires; + unsigned long offload_prohibited; + _lock offload_lock; + struct ap_offload_resource ap_offload_res[RTL8192CD_NUM_VWLAN+1]; + unsigned int offload_buf[OFFLOAD_BUF/4]; +#ifdef CONFIG_POWER_SAVE + _mutex apps_lock; + int xfer_seq; + int ps_xfer_seq; + u2Byte wake_irq; +#endif +#endif + int nr_bcn; + struct rtl8192cd_priv *bcn_priv[RTL8192CD_NUM_VWLAN+1]; +#ifdef MBSSID + _mutex mbssid_lock; + u32 inter_bcn_space; +#endif // MBSSID + + u8 tx_block_mode; + u8 rx_block_mode; + u32 block_transfer_len; + + struct sdio_func *psdio_func; + + u8 bDriverStopped; + u8 bSurpriseRemoved; + + HAL_INTF_DATA_TYPE *pHalData; + + // xmit priv + _queue tx_pending_sta_queue[MAX_HW_TX_QUEUE]; + _queue tx_xmitbuf_waiting_queue[MAX_HW_TX_QUEUE]; + _queue tx_urgent_queue; + struct tx_servq pspoll_sta_queue; + volatile unsigned long use_hw_queue_bitmap; // each bit corresponds to one HW TX queue + + _queue free_xmit_queue; + u8 *pallocated_frame_buf; + u8 *pxmit_frame_buf; + + _queue free_xmitbuf_queue; + u8 *pallocated_xmitbuf; + u8 *pxmitbuf; + + _queue free_xmit_extbuf_queue; + u8 *pallocated_xmit_extbuf; + u8 *pxmit_extbuf; + + _queue free_urg_xmitbuf_queue; + u8 *pallocated_urg_xmitbuf; + u8 *pxmitbuf_urg; + + _queue free_bcn_xmitbuf_queue; + u8 *pallocated_bcn_xmitbuf; + u8 *pbcn_xmitbuf; + +#ifdef CONFIG_TCP_ACK_TXAGG + _queue tcpack_queue; +#endif + // CONFIG_XMITBUF_TXAGG_ADV + unsigned long txagg_timeout[MAX_STA_TX_SERV_QUEUE]; + volatile unsigned long need_sched_xmit; + unsigned long low_traffic_xmit; + unsigned int low_traffic_xmit_stats[MAX_STA_TX_SERV_QUEUE]; + struct timer_list xmit_check_timer; + +#ifdef __KERNEL__ + struct tasklet_struct xmit_tasklet; +#endif + + unsigned int ts_used[MAX_HW_TX_QUEUE]; + + struct xmit_buf *last_urg_xmitbuf; + _queue pending_xmitbuf_queue; +#ifdef CONFIG_SDIO_TX_INTERRUPT + volatile unsigned long freepage_updated; +#ifdef CONFIG_SDIO_TX_IN_INTERRUPT + volatile unsigned long freepage_updated_seq; + volatile int xmit_thread_state; +#endif +#endif // CONFIG_SDIO_TX_INTERRUPT + unsigned long xmit_wake; +#ifdef __ECOS + cyg_flag_t xmit_flag; + cyg_handle_t *xmit_thread; + cyg_flag_t xmit_thread_done; +#else + wait_queue_head_t xmit_waitqueue; + struct task_struct *xmit_thread; + struct completion xmit_thread_done; +#endif + + // cmd priv + unsigned long cmd_wake; +#ifdef __ECOS + cyg_flag_t cmd_flag; + cyg_handle_t *cmd_thread; + cyg_flag_t cmd_thread_done; +#else + wait_queue_head_t waitqueue; + struct task_struct *cmd_thread; + struct completion cmd_thread_done; +#endif + _queue cmd_queue; + _queue rx_mgt_queue; + unsigned long pending_cmd[BITS_TO_LONGS(MAX_RTW_CMD_CODE)]; +#ifdef CMD_THREAD_FUNC_DEBUG + void *cur_cmd_func; // reocrd which function is doing in cmd_thread +#endif + + _queue timer_evt_queue; + struct timer_list beacon_timer; + struct timer_event_entry beacon_timer_event; +#endif // CONFIG_SDIO_HCI + +#if defined(CONCURRENT_MODE) || defined(CONFIG_RTL_92D_SUPPORT) + int wlandev_idx; +#endif + +#ifdef __KERNEL__ +#ifdef CONFIG_PCI_HCI + struct tasklet_struct rx_tasklet; + struct tasklet_struct tx_tasklet; + struct tasklet_struct oneSec_tasklet; +#endif +#ifdef PCIE_POWER_SAVING + struct tasklet_struct ps_tasklet; +#endif +#endif +#if defined(PCIE_POWER_SAVING) || defined(RF_MIMO_SWITCH) || defined(RF_MIMO_PS) + unsigned int rf_phy_bb_backup[26]; +#endif + + struct wlan_hdr_poll *pwlan_hdr_poll; + struct list_head wlan_hdrlist; + + struct wlanllc_hdr_poll *pwlanllc_hdr_poll; + struct list_head wlanllc_hdrlist; + + struct wlanbuf_poll *pwlanbuf_poll; + struct list_head wlanbuf_list; + + struct wlanicv_poll *pwlanicv_poll; + struct list_head wlanicv_list; + + struct wlanmic_poll *pwlanmic_poll; + struct list_head wlanmic_list; + + struct rtl8192cd_hw *phw; +#ifdef CONFIG_PCI_HCI + struct rtl8192cd_tx_desc_info *pdesc_info; +#endif + unsigned int have_hw_mic; + + struct aid_obj *aidarray[NUM_STAT]; + unsigned int max_fw_macid; + +#ifdef _11s_TEST_MODE_ + struct Galileo_poll *galileo_poll; + struct list_head galileo_list; +#endif + + unsigned char agc_tab_buf[AGC_TAB_SIZE]; + unsigned char mac_reg_buf[MAC_REG_SIZE]; + unsigned char phy_reg_buf[PHY_REG_SIZE]; + +#ifdef MP_TEST + unsigned char phy_reg_mp_buf[PHY_REG_SIZE]; +#endif + + unsigned char phy_reg_pg_buf[PHY_REG_PG_SIZE]; + unsigned char txpwr_pg_format_abs; +#ifdef TXPWR_LMT + unsigned char txpwr_lmt_buf[MAC_REG_SIZE]; + unsigned int txpwr_lmt_CCK; + unsigned int txpwr_lmt_OFDM; + unsigned int txpwr_lmt_HT1S; + unsigned int txpwr_lmt_HT2S; + unsigned char ch_pwr_lmtCCK[SUPPORT_CH_NUM]; + unsigned char ch_pwr_lmtOFDM[SUPPORT_CH_NUM]; + unsigned char ch_pwr_lmtHT20_1S[SUPPORT_CH_NUM]; + unsigned char ch_pwr_lmtHT20_2S[SUPPORT_CH_NUM]; + unsigned char ch_pwr_lmtHT40_1S[SUPPORT_CH_NUM]; + unsigned char ch_pwr_lmtHT40_2S[SUPPORT_CH_NUM]; + unsigned char ch_tgpwr_CCK[SUPPORT_CH_NUM]; + unsigned char ch_tgpwr_OFDM[SUPPORT_CH_NUM]; + unsigned char ch_tgpwr_HT20_1S[SUPPORT_CH_NUM]; + unsigned char ch_tgpwr_HT20_2S[SUPPORT_CH_NUM]; + unsigned char ch_tgpwr_HT40_1S[SUPPORT_CH_NUM]; + unsigned char ch_tgpwr_HT40_2S[SUPPORT_CH_NUM]; + unsigned int tgpwr_CCK; + unsigned int tgpwr_OFDM; + unsigned int tgpwr_HT1S; + unsigned int tgpwr_HT2S; +#if defined(TXPWR_LMT_8812) || defined(TXPWR_LMT_88E) || defined(CONFIG_WLAN_HAL) + unsigned int txpwr_lmt_VHT1S; + unsigned int txpwr_lmt_VHT2S; + unsigned char ch_pwr_lmtVHT80_1S[SUPPORT_CH_NUM]; + unsigned char ch_pwr_lmtVHT80_2S[SUPPORT_CH_NUM]; +#endif +#endif // TXPWR_LMT + +#if 1//defined(CONFIG_RTL_8812_SUPPORT) || defined(TXPWR_LMT_88E) || defined(CONFIG_WLAN_HAL) + unsigned char tgpwr_CCK_new[2]; + unsigned char tgpwr_OFDM_new[2]; + unsigned char tgpwr_HT1S_new[2]; + unsigned char tgpwr_HT2S_new[2]; + unsigned char tgpwr_VHT1S_new[2]; + unsigned char tgpwr_VHT2S_new[2]; +#endif + +#ifdef _TRACKING_TABLE_FILE + unsigned char txpwr_tracking_2G_CCK[4][index_mapping_NUM_MAX]; + unsigned char txpwr_tracking_2G_OFDM[4][index_mapping_NUM_MAX]; + unsigned char txpwr_tracking_5GL[4][index_mapping_NUM_MAX]; + unsigned char txpwr_tracking_5GM[4][index_mapping_NUM_MAX]; + unsigned char txpwr_tracking_5GH[4][index_mapping_NUM_MAX]; + unsigned char tracking_table_new; +#endif + +// unsigned char phy_reg_2to1[PHY_REG_1T2R]; + unsigned short fw_IMEM_len; + unsigned short fw_EMEM_len; + unsigned short fw_DMEM_len; + +#if defined(__KERNEL__) + spinlock_t lock; +#ifdef SMP_SYNC + unsigned long irq_save; +#endif +#endif + +#ifdef SMP_SYNC + spinlock_t lock_xmit; + spinlock_t lock_skb; +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + _mutex lock_buf; +#else + spinlock_t lock_buf; +#endif + spinlock_t lock_recv; + int lock_owner; + int lock_recv_owner; + int lock_xmit_owner; + unsigned long lock_xmit_flags; + unsigned long lock_flags; + unsigned char lock_xmit_func[50]; + unsigned char lock_func[50]; +#endif + + // for RF fine tune + struct rf_finetune_var rf_ft_var; + + // bcm 11n chipset iot debug + unsigned int reg_810_state; // 0=default, 1=set for bcm + + unsigned int skip_mic_chk; + // TXOP enlarge + unsigned int txop_enlarge; // 0=no txop, 1=half txop enlarged, 2=full txop enlarged, e=for Intel, f=for 8192S sta + + struct stat_info *highTP_found_pstat; + struct stat_info *txpause_pstat; + unsigned long txpause_time; + unsigned char rssi_min; +#ifdef RSSI_MIN_ADV_SEL + unsigned char rssi_min_prev; + unsigned char min_rssi_data_cnt; + struct rssi_search_entry min_rssi_data[NR_RSSI_MIN_DATA]; +#endif + + unsigned char agg_to; +#ifdef WIFI_WMM + unsigned char iot_mode_enable; + unsigned int iot_mode_VI_exist; + unsigned int iot_mode_VO_exist; + unsigned char wifi_beq_lower; +#ifdef WMM_VIBE_PRI + unsigned int iot_mode_BE_exist; +#endif +#ifdef WMM_BEBK_PRI + unsigned int iot_mode_BK_exist; +#endif +#endif + +#ifdef LOW_TP_TXOP + unsigned char BE_cwmax_enhance; +#endif + + +#ifdef RTK_AC_SUPPORT// defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + char txsc_20; // { 1, 2, 3, 4 } + char txsc_40; // { 9, 10 } +#endif +// unsigned int current_rsp_rate; + + +#ifdef CONFIG_WLAN_HAL_8192EE + char txsc_20_92e; // {1, 2} +#endif + + int is_40m_bw; + int is_40m_bw_bak; + char offset_2nd_chan; +// int is_giga_exist; + +#ifdef CONFIG_RTK_MESH + struct MESH_Share meshare; // mesh share data + spinlock_t lock_queue; // lock for DOT11_EnQueue2/DOT11_DeQueue2 + spinlock_t lock_Rreq; // lock for rreq_retry. Some function like aodv_expire/tx use lock_queue simultaneously +#endif + + unsigned int curr_band; // remember the current band to save switching time + unsigned short fw_signature; + unsigned char fw_category; + unsigned char fw_function; + unsigned short fw_version; +// unsigned short fw_src_version; + unsigned short fw_sub_version; + unsigned char fw_date_month; + unsigned char fw_date_day; + unsigned char fw_date_hour; + unsigned char fw_date_minute; +#ifdef CONFIG_WLAN_HAL + unsigned int h2c_box_full; +#endif + unsigned int CamEntryOccupied; // how many entries in CAM? + unsigned char rtk_ie_buf[16]; + unsigned int rtk_ie_len; + unsigned char *rtk_cap_ptr; + unsigned short rtk_cap_val; + unsigned char use_long_slottime; + + // for Tx power control + unsigned char working_channel; + unsigned char ra40MLowerMinus; + unsigned char raThdHP_Minus; + +#ifdef INCLUDE_WPS + struct wsc_context WSC_CONT_S; +#endif + + unsigned int current_num_tx_desc; + +#ifdef USE_OUT_SRC + DM_ODM_T _dmODM; +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#ifdef SUPPORT_RTL8188E_TC + unsigned int rtl8188e_testchip_checked; +#endif +#if defined(TXREPORT) && !defined(RATEADAPTIVE_BY_ODM) + STATION_RA_INFO RaInfo[RTL8188E_NUM_STAT]; +#endif +#endif + +#if defined(USE_OUT_SRC) + unsigned char use_outsrc; +#endif + +#ifdef TPT_THREAD + struct task_struct *tpt_task; // Tx Power Tracking task + atomic_t do_tpt; // Do Tx Power Tracking function +#endif + + unsigned char use_hal; + +#if defined(DFS) || defined(RTK_AC_SUPPORT) + unsigned int dfsSwitchChannel; +#endif + +#if defined(__ECOS) || defined(CONFIG_RTL865X_WTDOG) || defined(CONFIG_RTL_WTDOG) + unsigned long wtval; +#endif + +#ifdef AUTO_CHANNEL_TIMEOUT + unsigned long autoch_timeout_count; + unsigned char autoch_trigger_by_timeout; +#endif + + unsigned long tx_dma_err; + unsigned long rx_dma_err; + unsigned long tx_dma_status; + unsigned long rx_dma_status; + +#ifdef MULTI_MAC_CLONE + int mclone_ok; + int mclone_num; +#if defined(SMP_SYNC) + int mclone_active_id[10];//number of cpu +#else + int mclone_active_id; +#endif + int mclone_init_seq; + struct mclone_sta_info mclone_sta[MAX_MAC_CLONE_NUM]; + struct mclone_sta_addr mclone_sta_fixed_addr[MAX_MAC_CLONE_NUM]; + struct rtl8192cd_priv *root_repeater; +#endif + +#if defined(RTK_NL80211) + volatile struct cfg80211_chan_def *dfs_chan_def; +#endif + + /********************************************************* + * from here on, data will be clear in rtl8192cd_init_sw() * + *********************************************************/ + + // for SW LED + struct timer_list LED_Timer; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct timer_event_entry LED_Timer_event; +#endif + unsigned int LED_Interval; + unsigned char LED_Toggle; + unsigned char LED_ToggleStart; + unsigned int LED_tx_cnt_log; + unsigned int LED_rx_cnt_log; + unsigned int LED_tx_cnt; + unsigned int LED_rx_cnt; + unsigned char LED_cnt_mgn_pkt; + + //for TxPwrTracking + + unsigned char Thermal_idx; + unsigned char Thermal_log[8]; + + unsigned char ThermalValue; + unsigned char ThermalValue_LCK; + unsigned char ThermalValue_IQK; + unsigned char CCK_index; + unsigned char OFDM_index[2]; + unsigned char CCK_index0; + unsigned char OFDM_index0[2]; +#ifdef CONFIG_WLAN_HAL_8881A + unsigned char AddTxAGC; + unsigned char AddTxAGC_index; +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + unsigned char Delta_IQK; + unsigned char Delta_LCK; + unsigned char pwr_trk_ongoing; +#ifdef RX_GAIN_TRACK_92D + unsigned int RegRF3C[2]; //pathA / pathB + unsigned char ThermalValue_RxGain; +#endif + unsigned char ThermalValue_Crystal; +#ifdef DPK_92D + unsigned char ThermalValue_DPK; + unsigned char ThermalValue_DPKstore; + unsigned char ThermalValue_DPKtrack; + unsigned char bDPKworking; + struct timer_list DPKTimer; + unsigned char bDPKdone[2]; + unsigned char bDPKstore; + short index_mapping_DPK_current[4][index_mapping_DPK_NUM]; + unsigned char OFDM_min_index_internalPA_DPK[2]; + unsigned char TxPowerLevelDPK[2]; +#endif + unsigned int RegRF18[2]; + unsigned int RegRF28[2]; +#endif // CONFIG_RTL_92D_SUPPORT + +#if 1// defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + unsigned char No_RF_Write; + unsigned char No_BB_Write; + unsigned int RegCB0; + unsigned int RegEB0; +#endif + + + unsigned int RegE94; + unsigned int RegE9C; + unsigned int RegEB4; + unsigned int RegEBC; + + //for IQK + unsigned int RegC04; + unsigned int Reg874; + unsigned int RegC08; + unsigned int ADDA_backup[IQK_ADDA_REG_NUM]; + unsigned int IQK_MAC_backup[IQK_MAC_REG_NUM]; + +#ifdef CONFIG_RTL_88E_SUPPORT + //for 8188E IQK + unsigned int IQK_BB_backup[IQK_BB_REG_NUM]; + unsigned int IQK_BB_backup_recover[IQK_BB_REG_NUM]; + unsigned char bRfPiEnable; + unsigned char IQK_88E_done; + // for 8188E phy para + +#endif + + //for IQK debug + unsigned int IQK_total_cnt; + unsigned int IQK_fail_cnt; + unsigned int PhyVersion; + + +#ifdef CONFIG_RTL_88E_SUPPORT //for 88e tx power tracking + + unsigned char Power_tracking_on_88E; + + unsigned int TXPowerTrackingCallbackCnt; //cosa add for debug + unsigned int RegA24; // for TempCCK + unsigned char EEPROMThermalMeter; // EEPROM default ThermalMeter value. + + //u1Byte bTXPowerTracking; + unsigned char TXPowercount; + char bTXPowerTrackingInit; + char bTXPowerTracking; + unsigned char TxPowerTrackControl; //for mp mode, turn off txpwrtracking as default + unsigned char TM_Trigger; + unsigned char InternalPA5G[2]; //pathA / pathB + + unsigned char ThermalMeter[2]; // ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 + unsigned char ThermalValue_AVG[AVG_THERMAL_NUM]; + unsigned char ThermalValue_AVG_index; + unsigned char ThermalValue_RxGain; + unsigned char ThermalValue_Crystal; + unsigned char ThermalValue_DPKstore; + unsigned char ThermalValue_DPKtrack; + char TxPowerTrackingInProgress; + char bDPKenable; + + char bReloadtxpowerindex; + //unsigned char bRfPiEnable; + //unsigned int TXPowerTrackingCallbackCnt; //cosa add for debug + + unsigned char bCCKinCH14; + char bDoneTxpower; + + unsigned char ThermalValue_HP[HP_THERMAL_NUM]; + unsigned char ThermalValue_HP_index; + IQK_MATRIX_REGS_SETTING IQKMatrixRegSetting[IQK_Matrix_Settings_NUM]; + + unsigned char Delta_IQK; + unsigned char Delta_LCK; + +#endif + // MP DIG +#ifdef CONFIG_RTL_92D_SUPPORT + struct timer_list MP_DIGTimer; +#endif + unsigned char mp_dig_on; + unsigned char mp_dig_reg_backup; + unsigned int RxPWDBAve; + unsigned int NumQryPhyStatus; + unsigned int LastNumQryPhyStatusAll; + unsigned int NumQryPhyStatusCCK; + unsigned int NumQryPhyStatusOFDM; + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) //for 8812 tx power tracking + unsigned char Power_tracking_on_8812; + unsigned char ThermalValue_AVG_8812[AVG_THERMAL_NUM_8812]; + unsigned char ThermalValue_AVG_index_8812; +#endif + +#ifdef CONFIG_WLAN_HAL + unsigned char Power_tracking_on_88XX; + unsigned char ThermalValue_AVG_88XX[AVG_THERMAL_NUM_88XX]; + unsigned char ThermalValue_AVG_index_88XX; + unsigned int RxTagPollingCount; + unsigned int RxTagMismatchCount; +#endif +#if defined(RF_MIMO_SWITCH) || defined(RF_MIMO_PS) + unsigned char rf_status; +#endif + + unsigned int current_rsp_rate; +//#ifdef MBSSID + struct rtl8192cd_priv *bcnDOk_priv; +//#endif + +#if defined(TXREPORT) + int sta_query_idx; +#endif +#ifdef BEAMFORMING_SUPPORT + RT_BEAMFORMING_INFO BeamformingInfo; + unsigned char soundingLock; +#endif + + // for Rx dynamic tasklet + unsigned int rxInt_useTsklt; + unsigned int rxInt_data_delta; + +#ifdef CHECK_HANGUP +#ifdef CHECK_TX_HANGUP +#ifdef CONFIG_WLAN_HAL + struct desc_check_info Q_info[13]; +#else + struct desc_check_info Q_info[6]; +#endif +#endif +#ifdef CHECK_RX_DMA_ERROR + unsigned int rx_dma_err_cnt; + unsigned short rxff_pkt; + unsigned short rxff_rdptr; + unsigned int rx_byte_cnt; +#endif +#ifdef CHECK_FW_ERROR + unsigned int mcu_tst2; + unsigned int mcu_pending_cnt; +#endif +#ifdef CHECK_RX_HANGUP + unsigned int rx_hang_checking; + unsigned int rx_cntreg_log; + unsigned int rx_stop_pending_tick; + struct rtl8192cd_priv *selected_priv; +#endif +#ifdef CHECK_BEACON_HANGUP + unsigned int beacon_ok_cnt; + unsigned int beacon_pending_cnt; + unsigned int beacon_wait_cnt; +#endif +#ifdef CHECK_AFTER_RESET + unsigned int reset_monitor_cnt_down; + unsigned int reset_monitor_pending; + unsigned int reset_monitor_rx_pkt_cnt; +#endif +#endif + +#ifdef HW_DETEC_POWER_STATE + unsigned char HWPwrState[128]; + unsigned char HWPwroldState[128]; + unsigned char HWPwrStateUpdate[128]; +#endif //#ifdef HW_DETEC_POWER_STATE + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef CONFIG_USB_HCI +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + unsigned int nr_h2c_cmd_miss; + unsigned int nr_h2c_cmd; +#endif +#endif // CONFIG_USB_HCI + unsigned int nr_cmd_miss; + unsigned int nr_cmd; + unsigned int nr_rx_mgt_cmd_miss; + unsigned int nr_rx_mgt_cmd; + unsigned int nr_timer_evt_miss; + unsigned int nr_timer_evt; + unsigned int nr_out_of_xmitframe; +#ifdef CONFIG_SDIO_TX_FILTER_BY_PRI + unsigned int nr_tx_filter_vo; + unsigned int nr_tx_filter_vi; + unsigned int nr_tx_filter_be; + unsigned int nr_tx_filter_bk; +#endif +#ifdef __ECOS + unsigned int nr_out_of_xmitbuf; + unsigned int nr_out_of_xmit_extbuf; +#endif + unsigned int nr_stop_netif_tx_queue; + u8 stop_netif_tx_queue; +#ifdef CONFIG_SDIO_HCI + unsigned int nr_interrupt; + unsigned int nr_xmit_thread_run; + unsigned int nr_out_of_txoqt_space; + + unsigned short xmitbuf_agg_num; + unsigned short nr_xmitbuf_handled_in_thread; + unsigned short nr_xmitbuf_handled_in_irq; + unsigned short nr_recvbuf_handled_in_irq; + unsigned short nr_recvbuf_handled_in_tasklet; + unsigned short nr_recvframe_in_recvbuf; +#ifdef SDIO_AP_OFFLOAD + unsigned int nr_update_bcn_fail; +#ifdef CONFIG_POWER_SAVE + unsigned int nr_leave_32k_fail; +#endif +#endif +#ifdef SDIO_STATISTICS + unsigned long statistic_update_time; + unsigned int writeport_total_count[MAX_XMITBUF_PKT]; + unsigned int writeport_avg_count[MAX_XMITBUF_PKT]; +#ifdef SDIO_STATISTICS_TIME + unsigned long writeport_total_time[MAX_XMITBUF_PKT]; + unsigned long writeport_avg_time[MAX_XMITBUF_PKT]; +#endif +#endif +#endif // CONFIG_SDIO_HCI +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#ifdef CONFIG_1RCCA_RF_POWER_SAVING + unsigned char _1rcca_ps_active; +#endif + +#ifdef MP_TEST + unsigned char mp_datarate; + unsigned char mp_antenna_tx; + unsigned char mp_antenna_rx; + unsigned char mp_txpwr_patha; + unsigned char mp_txpwr_pathb; + unsigned char mp_cck_txpwr_odd; + + unsigned char mp_rx_rate; + unsigned int mp_FA_cnt; + unsigned int mp_CCA_cnt; + unsigned int mp_rssi_weight; + + void *skb_pool_ptr; + struct sk_buff *skb_pool[NUM_MP_SKB]; + int skb_head; + int skb_tail; + + unsigned int mp_ctx_count; + unsigned int mp_ctx_pkt; + unsigned char mp_rssi; + unsigned char mp_sq; + struct rf_misc_info mp_rf_info; + + unsigned char mp_ofdm_swing_idx; + unsigned char mp_cck_swing_idx; + unsigned char mp_txpwr_tracking; + int mp_pkt_len; +#ifdef MP_SWITCH_LNA + unsigned char rx_packet_ss_a; + unsigned char rx_packet_ss_b; +#endif + +#ifdef B2B_TEST + volatile unsigned long mp_rx_ok, mp_rx_sequence, mp_rx_lost_packet, mp_rx_dup; + volatile unsigned short mp_cached_seq; + int mp_rx_waiting; + volatile unsigned int mp_mac_changed; + unsigned long txrx_elapsed_time; + unsigned long txrx_start_time; +#endif +//arx parameters + unsigned int mp_filter_flag; + unsigned char mp_filter_DA[6]; + unsigned char mp_filter_SA[6]; + unsigned char mp_filter_BSSID[6]; + +#endif // MP_TEST + + // monitor Tx and Rx + unsigned long tx_packets_pre; + unsigned long rx_packets_pre; + + // bcm old 11n chipset iot debug, and TXOP enlarge + unsigned long current_tx_bytes; + unsigned long current_rx_bytes; + + //For collecting probe request infomation + unsigned int ProbeReqEntryOccupied; + unsigned int ProbeReqEntryNum; + + + u8Byte NumTxBytesUnicast; + u8Byte NumRxBytesUnicast; +#ifdef USE_OUT_SRC + unsigned char bScanInProcess; + u8Byte dummy; +#endif + + unsigned char CurrentChannelBW; +#ifdef CONFIG_PCI_HCI + unsigned char *txcmd_buf; + unsigned long cmdbuf_phyaddr; +#endif + unsigned int InterruptMask; + unsigned int InterruptMaskExt; + unsigned int rx_rpt_ofdm; + unsigned int rx_rpt_cck; + unsigned int rx_rpt_ht; + unsigned int successive_bb_hang; +#ifdef CLIENT_MODE + int AP_BW; +#endif + + unsigned long rxFiFoO_pre; +// unsigned int pkt_in_hiQ; + +#if !(defined(__ECOS) && defined(CONFIG_SDIO_HCI)) +#ifdef RTK_QUE + struct ring_que skb_queue; +#else + struct sk_buff_head skb_queue; +#endif +#endif + + struct timer_list rc_sys_timer; + struct reorder_ctrl_timer rc_timer[RC_TIMER_NUM]; + unsigned short rc_timer_head; + unsigned short rc_timer_tail; + unsigned short rc_timer_tick; + + struct reorder_ctrl_timer amsdu_timer[AMSDU_TIMER_NUM]; + unsigned short amsdu_timer_head; + unsigned short amsdu_timer_tail; + + // ht associated client statistic +#ifdef WIFI_WMM + unsigned int ht_sta_num; + STA_BITMAP mimo_ps_dynamic_sta; +#endif + + unsigned int set_led_in_progress; + + struct stat_info* CurPstat[4]; // for tx desc break field +// STA_BITMAP has_2r_sta; // Used when AP is 2T2R. bitmap of 2R aid + int has_triggered_rx_tasklet; + int has_triggered_tx_tasklet; +#ifdef __ECOS + int call_dsr; + int has_triggered_process_mcast_dzqueue; +#ifdef MBSSID + int has_triggered_vap_process_mcast_dzqueue[RTL8192CD_NUM_VWLAN]; +#endif +#if defined(TXREPORT) + int has_triggered_C2H_isr; +#endif +#ifdef DFS + int has_triggered_dfs_switch_channel; +#endif +#endif + + unsigned short total_cam_entry; + unsigned short fw_support_sta_num; + unsigned char fw_free_space; + unsigned char remapped_aidarray[NUM_STAT]; + + // for DIG + unsigned char DIG_on; + unsigned char restore; + unsigned short threshold0; + unsigned short threshold1; + unsigned short threshold2; + unsigned char FA_upper; + unsigned char FA_lower; + unsigned short ofdm_FA_cnt1; + unsigned short ofdm_FA_cnt2; + unsigned short ofdm_FA_cnt3; + unsigned short ofdm_FA_cnt4; + unsigned short cck_FA_cnt; +#ifdef INTERFERENCE_CONTROL + unsigned int ofdm_FA_total_cnt; +#endif + unsigned int FA_total_cnt; + unsigned int CCA_total_cnt; + +#if defined(CONFIG_RTL_NOISE_CONTROL) || defined(CONFIG_RTL_NOISE_CONTROL_92C) + unsigned char DNC_on; +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + unsigned char DNC_chk_cnt; + unsigned char DNC_chk; +// unsigned short F90_cnt; + unsigned short F94_cnt; + unsigned short F94_cntOK; + unsigned int Reg664_cnt; + unsigned int Reg664_cntOK; +#endif + + int digDownCount; + int digDeadPoint; + int digDeadPointCandidate; + int digDeadPointHitCount; + + unsigned char cca_path; + unsigned char fw_q_fifo_count; + + unsigned int current_tx_rate; + unsigned char ht_current_tx_info; // bit0: 0=20M mode, 1=40M mode; bit1: 0=longGI, 1=shortGI + + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + unsigned int num_txdesc_cnt; // less or equal max available tx desc + unsigned int num_txdesc_upper_limit; + unsigned int num_txdesc_lower_limit; +#ifdef USE_TXQUEUE + unsigned int num_txq_cnt; + unsigned int num_txq_upper_limit; + unsigned int num_txq_lower_limit; +#endif +#endif + + // Retry Limit register content + unsigned short RL_setting; + +#ifdef SW_ANT_SWITCH + SWAT_T DM_SWAT_Table; + struct stat_info *RSSI_target; + struct timer_list swAntennaSwitchTimer; + + unsigned int RSSI_sum_R; + unsigned int RSSI_cnt_R; + unsigned int RSSI_sum_L; + unsigned int RSSI_cnt_L; + unsigned int RSSI_test; + unsigned int lastTxOkCnt; + unsigned int lastRxOkCnt; + unsigned int TXByteCnt_R; + unsigned int TXByteCnt_L; + unsigned int RXByteCnt_R; + unsigned int RXByteCnt_L; + unsigned int TrafficLoad; +#endif + +#ifdef DETECT_STA_EXISTANCE + unsigned char bRLShortened; +#endif + +#if defined(DFS) || defined(RTK_AC_SUPPORT) + unsigned int dfsSwitchChCountDown; + unsigned int dfsSwCh_ongoing; +#endif + +#ifdef RX_BUFFER_GATHER + unsigned int gather_state; + struct list_head gather_list; + int gather_len; +#ifdef CONFIG_WLAN_HAL + int pkt_total_len; +#endif // CONFIG_WLAN_HAL +#endif + +#ifdef USE_TXQUEUE + struct txq_list_head txq_list[7]; + unsigned int txq_isr; + unsigned int txq_stop; + unsigned int txq_check; + struct list_head txq_pool; + unsigned char *txq_pool_addr; +#endif + + unsigned char Reg_RRSR_2; + unsigned char Reg_81b; + STA_BITMAP marvellMapBit; +#if defined(WIFI_11N_2040_COEXIST_EXT) + STA_BITMAP _40m_staMap; +#endif + STA_BITMAP intel_sta_bitmap; + +#ifdef TX_EARLY_MODE + unsigned int em_waitq_on; + unsigned int em_tx_byte_cnt; + unsigned int reach_tx_limit_cnt; +#endif + unsigned short aggrmax_bak; + unsigned char aggrmax_change; + + unsigned int iqk_2g_done; +#ifdef CONFIG_RTL_92D_SUPPORT + unsigned int iqk_5g_done; +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + unsigned char pre_channel; +#endif + + unsigned int intel_active_sta; + unsigned int intel_rty_lmt; + + unsigned int total_assoc_num; +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + unsigned int txRptMacid; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + unsigned short txRptTime; +#endif +#endif + +#if defined( UNIVERSAL_REPEATER) || defined(MBSSID) + unsigned int switch_chan_rp; + unsigned int switch_2ndchoff_rp; + unsigned int band_width_rp; +#endif + +#ifdef RTK_NL80211 //wrt-adhoc + struct timer_list vxd_ibss_beacon; //timer to issue beacon for vxd_adhoc +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + BOOLEAN PLL_reset_ok; +#endif +#ifdef MCR_WIRELESS_EXTEND + unsigned int cmw_link; +#endif + +#ifdef CONFIG_POWER_SAVE + struct ap_pwrctrl_priv ap_ps_handle; +#endif +}; + + +#ifdef SUPPORT_MONITOR +struct rtl_wifi_header { + unsigned char rt_frame_type; // Frame type + unsigned char rt_sub_frame_type; //Sub frame type + unsigned char rt_rssi; //RSSI + unsigned char rt_noise; //Noise + unsigned char rt_addr1[6]; //DA mac addr + unsigned char rt_addr2[6]; //SA mac addr + unsigned char rt_rate; //Rx_rate + unsigned char rt_channel_num; //Channel Num +} __attribute__ ((packed)); +#endif + + +#ifdef CONFIG_RTL8186_KB +typedef struct guestmac { + unsigned char macaddr[6]; + unsigned char valid; +} GUESTMAC_T; +#endif + + +#ifdef RTK_NL80211 +struct nl_context { + /*=========remain on channel related========*/ + struct timer_list remain_on_ch_timer; + u8 restore_channel; + struct ieee80211_channel remain_on_ch_channel; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + enum nl80211_channel_type remain_on_ch_type; +#endif + u64 remain_on_ch_cookie; + + /*=========remain on channel related========*/ + struct timer_list scan_deny_timer; + u64 send_action_id; + //struct cfg80211_wifidirect_info cfg80211_wdinfo; + char p2p_listen_channel; +}; +#endif + +typedef struct rtl8192cd_priv { +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + wifi_link_status_cb_func_t *link_status_cb_func; // for client mode + wifi_sta_status_cb_func_t *sta_status_cb_func; // for AP mode +#endif +#ifdef NETDEV_NO_PRIV + struct rtl8192cd_priv* wlan_priv; //This element shall be put at top of this struct +#endif + +#ifdef CONFIG_WLAN_HAL + void * HalFunc; + void * HalData; +#endif + int drv_state; // bit0 - init, bit1 - open/close + struct net_device *dev; + +#ifdef RTK_NL80211 + //struct wiphy *wiphy; + struct rtknl *rtk; + struct wireless_dev wdev; + struct cfg80211_scan_request *scan_req; + //struct pci_dev *pdev; + //struct net init_net; + //dev_t rtk88e; + //struct class *c1; + //struct device *tmp_device; + unsigned char receive_connect_cmd; + unsigned char cfg80211_interface_add; + bool probe_req_report; + unsigned char is_cfg80211_iface; +#endif + + struct wifi_mib *pmib; + + struct wlan_acl_poll *pwlan_acl_poll; + struct list_head wlan_aclpolllist; // this is for poll management + struct list_head wlan_acl_list; // this is for auth checking +#ifdef SMP_SYNC + spinlock_t wlan_acl_list_lock; +#ifdef RTK_NL80211 + spinlock_t cfg80211_lock; +#endif +#endif + + DOT11_QUEUE *pevent_queue; +#ifdef CONFIG_RTL_WAPI_SUPPORT + DOT11_QUEUE *wapiEvent_queue; +#endif + DOT11_EAP_PACKET *Eap_packet; +#ifdef INCLUDE_WPS +#ifndef CONFIG_MSC + DOT11_EAP_PACKET *upnp_packet; +#endif +#endif + +#ifdef _INCLUDE_PROC_FS_ + struct proc_dir_entry *proc_root; + unsigned int txdesc_num; + unsigned char *phypara_file_start; + unsigned char *phypara_file_end; +#elif defined(__ECOS) + unsigned int txdesc_num; +#endif + +#ifdef ENABLE_RTL_SKB_STATS + atomic_t rtl_tx_skb_cnt; + atomic_t rtl_rx_skb_cnt; +#endif + + struct priv_shared_info *pshare; // pointer of shared info, david +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct recv_priv recvpriv; +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + struct rtl8192cd_priv *proot_priv; // ptr of private structure of root interface +#if defined(CONFIG_WLAN_HAL) +#ifdef RESERVE_TXDESC_FOR_EACH_IF + unsigned int use_txdesc_cnt[14]; +#ifdef USE_TXQUEUE + unsigned int use_txq_cnt[14]; +#endif +#endif +#else +#ifdef RESERVE_TXDESC_FOR_EACH_IF + unsigned int use_txdesc_cnt[7]; +#ifdef USE_TXQUEUE + unsigned int use_txq_cnt[7]; +#endif +#endif +#endif +#endif +#ifdef UNIVERSAL_REPEATER + struct rtl8192cd_priv *pvxd_priv; // ptr of private structure of virtual interface +#endif +#ifdef MBSSID + struct rtl8192cd_priv *pvap_priv[RTL8192CD_NUM_VWLAN]; // ptr of private structure of vap interface + short vap_id; + short vap_init_seq; + short vap_count; + int bcn_period_bak; +#endif + +#ifdef DFS + /* + * timer for the blocked channel if radar detected + */ + struct timer_list ch52_timer; + struct timer_list ch56_timer; + struct timer_list ch60_timer; + struct timer_list ch64_timer; + struct timer_list ch100_timer; + struct timer_list ch104_timer; + struct timer_list ch108_timer; + struct timer_list ch112_timer; + struct timer_list ch116_timer; + struct timer_list ch120_timer; + struct timer_list ch124_timer; + struct timer_list ch128_timer; + struct timer_list ch132_timer; + struct timer_list ch136_timer; + struct timer_list ch140_timer; + struct timer_list ch144_timer; + + /* + * blocked channel will be removed from available_chnl[32] and placed in this list + */ + unsigned int NOP_chnl[15]; + unsigned int NOP_chnl_num; + + unsigned int Not_DFS_chnl[32]; + unsigned int Not_DFS_chnl_num; +#endif + +#if defined(DOT11D) || defined(DOT11H) + unsigned char countryTableIdx; +#endif + +#ifdef SUPPORT_MONITOR + struct timer_list chan_switch_timer; + BOOLEAN is_monitor_mode; + unsigned int chan_num; +#endif + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + WPA_GLOBAL_INFO *wpa_global_info; +#endif + struct ss_res *site_survey; + +#ifdef CHECK_HANGUP + int reset_hangup; + unsigned int check_cnt_tx; + unsigned int check_cnt_rx; + unsigned int check_cnt_isr; + unsigned int check_cnt_bcn; + unsigned int check_cnt_rst; + unsigned int check_cnt_bb; + unsigned int check_cnt_cca; + unsigned int check_cnt_fw; +#endif + +#ifdef WDS + struct net_device_stats wds_stats[NUM_WDS]; + struct net_device *wds_dev[NUM_WDS]; +#endif + unsigned int auto_channel; // 0: not auto, 1: auto select this time, 2: auto select next time + unsigned int auto_channel_backup; + unsigned long up_time; + unsigned int auto_channel_step; + +#ifdef CONFIG_RTK_MESH + struct timer_list mesh_expire_timer; + struct wlan_ethhdr_t ethhdr; + unsigned char RreqMAC[AODV_RREQ_TABLE_SIZE][MACADDRLEN]; + unsigned int RreqBegin; + unsigned int RreqEnd; + + struct hash_table *proxy_table, *mesh_rreq_retry_queue; +#ifdef PU_STANDARD + struct hash_table *proxyupdate_table; +#endif + struct hash_table *pathsel_table; // add by chuangch 2007.09.13 + struct mpp_tb *pann_mpp_tb; + + struct MESH_FAKE_MIB_T mesh_fake_mib; + unsigned char root_mac[MACADDRLEN]; // Tree Base root MAC + + + UINT16 seqNum; // record for recently sent multicast packet + /* + dev->priv->base_addr = 0 is wds + dev->priv->base_addr = 1 is mesh + We provide only one mesh device now. Although it is possible that more than one + mesh devices bind with one physical interface simultaneously. RTL8186 shares the + same MAC address with multiple virtual devices. Hence, the mesh data frame can't + be handled (rx) by mesh devices correctly. + */ + + struct net_device *mesh_dev; + struct rtl8192cd_priv *mesh_priv_sc; + struct rtl8192cd_priv *mesh_priv_first; +#ifdef _MESH_ACL_ENABLE_ + struct mesh_acl_poll *pmesh_acl_poll; + struct list_head mesh_aclpolllist; // this is for poll management + struct list_head mesh_acl_list; // this is for auth checking +#if defined(SMP_SYNC) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + spinlock_t mesh_acl_list_lock; +#endif +#endif + + DOT11_QUEUE2 *pathsel_queue; // pathselection QUEUE +#ifdef _11s_TEST_MODE_ + DOT11_QUEUE2 *receiver_queue; // pathselection QUEUE + struct list_head mtb_list; +#endif + int pid_pathsel; + + struct net_device_stats mesh_stats; + +#ifdef _11s_TEST_MODE_ + char rvTestPacket[3000]; +#endif + + UINT8 mesh_Version; + // WLAN Mesh Capability + INT16 mesh_PeerCAP_cap; // peer capability-Cap number (Signed!) + UINT8 mesh_PeerCAP_flags; // peer capability-flags + UINT8 mesh_PowerSaveCAP; // Power Save capability + UINT8 mesh_SyncCAP; // Synchronization capability + UINT8 mesh_MDA_CAP; // MDA capability + UINT32 mesh_ChannelPrecedence; // Channel Precedence + UINT8 mesh_fix_channel; // for Mesh auto channel scan used + + UINT8 mesh_HeaderFlags; // mesh header in mesh flags field + + //for mesh channel switch + UINT8 mesh_swchnl_channel; //0:do not need to switch channel, others: the channel switch procedure is ongoing + UINT8 mesh_swchnl_offset; + UINT8 mesh_swchnl_ttl; + UINT8 mesh_swchnl_flag; + UINT16 mesh_swchnl_reason; + UINT32 mesh_swchnl_precedence; + UINT8 mesh_swchnl_counter; + +#ifdef MESH_BOOTSEQ_AUTH + struct timer_list mesh_auth_timer; ///< for unestablish (And establish to unestablish) MP mesh_auth_hdr + + // mesh_auth_hdr: + // It is a list structure, only stores unAuth MP entry + // Each entry is a pointer pointing to an entry in "stat_info->mesh_mp_ptr" + // and removed by successful "Auth" or "Expired" + struct list_head mesh_auth_hdr; +#endif + + struct timer_list mesh_peer_link_timer; ///< for unestablish (And establish to unestablish) MP mesh_unEstablish_hdr + + // mesh_unEstablish_hdr: + // It is a list structure, only stores unEstablish (or Establish -> unEstablish [MP_HOLDING])MP entry + // Each entry is a pointer pointing to an entry in "stat_info->mesh_mp_ptr" + // and removed by successful "Peer link setup" or "Expired" + struct list_head mesh_unEstablish_hdr; + + // mesh_mp_hdr: + // It is a list of MP/MAP/MPP who has already passed "Peer link setup" + // Each entry is a pointer pointing to an entry in "stat_info->mesh_mp_ptr" + // Every entry is inserted by "successful peer link setup" + // and removed by "Expired" + struct list_head mesh_mp_hdr; + +#if defined(SMP_SYNC) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + spinlock_t mesh_mp_hdr_lock; // protect mesh_auth_hdr, mesh_unEstablish_hdr, mesh_mp_hdr +#endif + + struct MESH_Profile mesh_profile[1]; // Configure by WEB in the future, Maybe delete, Preservation before delete + + +#ifdef MESH_BOOTSEQ_STRESS_TEST + unsigned long mesh_stressTestCounter; +#endif // MESH_BOOTSEQ_STRESS_TEST + + // Throughput statistics (sounder) + unsigned int mesh_log; + unsigned long log_time; + +#ifdef _MESH_ACL_ENABLE_ + unsigned char meshAclCacheAddr[MACADDRLEN]; + unsigned char meshAclCacheMode; +#endif + struct vlan_info mesh_vlan; +#if defined(RTL_MESH_TXCACHE) + struct mesh_txcache_t mesh_txcache; +#endif + +#ifdef MESH_USE_METRICOP + UINT32 toMeshMetricAuto; // timeout, check mesh_fake_mib for further description +#endif + +#endif // CONFIG_RTK_MESH + +#ifdef EN_EFUSE + unsigned char AutoloadFailFlag; + unsigned char *EfuseMap[2]; + unsigned short EfuseUsedBytes; + unsigned short EfuseRealContentLen; + unsigned short EfuseMapLen; + unsigned short EfuseMaxSection; + unsigned short EfuseOobProtectBytes; + char **EfuseCmd; + unsigned char EfuseCmdNum; +#endif + + +#ifdef CONFIG_RTL_WAPI_SUPPORT + uint8 *wapiCachedBuf; + uint8 wapiNMK[WAPI_KEY_LEN]; + uint8 txMCast[WAPI_PN_LEN]; + uint8 rxMCast[WAPI_PN_LEN]; + uint8 keyNotify[WAPI_PN_LEN]; + uint8 aeWapiIE[256]; + uint8 wapiCachedLen; + uint8 aeWapiIELength; + uint8 wapiMCastKeyId: 1; + uint8 wapiMCastKeyUpdateAllDone: 1; + uint8 wapiMCastKeyUpdate: 1; + uint8 wapiMCastNeedInit: 1; + uint16 wapiWaiTxSeq; + wapiKey wapiMCastKey[2]; + unsigned long wapiMCastKeyUpdateCnt; + struct timer_list waiMCastKeyUpdateTimer; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct timer_event_entry waiMCastKeyUpdateTimerEvent; +#endif +#endif + +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU) + struct net_device *pWlanDev; +#endif +#if defined(CONFIG_RTL_NEW_AUTOCH) && defined(SS_CH_LOAD_PROC) + unsigned int ch_ss_rpt_cnt; + struct ss_report ch_ss_rpt[MAX_BSS_NUM]; +#endif +#ifdef P2P_SUPPORT + struct timer_list p2p_listen_timer_t; + struct timer_list p2p_search_timer_t; + struct p2p_context* p2pPtr; +#endif + +#ifdef SDIO_AP_OFFLOAD + struct work_struct ap_cmd_queue; +#endif + /* asoc_list_lock is used in proc file, so don't zero out in open */ +#if defined(SMP_SYNC) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) +#ifdef __ECOS + _mutex asoc_list_lock; +#else + spinlock_t asoc_list_lock; +#endif +#endif + + /********************************************************* + * from here on, data will be clear in rtl8192cd_init_sw() * + *********************************************************/ + struct net_device_stats net_stats; + struct extra_stats ext_stats; +#ifdef TLN_STATS + struct tln_wifi_stats wifi_stats; + struct tln_ext_wifi_stats ext_wifi_stats; + unsigned int stats_time_countdown; +#endif + int reperater_idx; + int bIntMigration; + + struct timer_list frag_to_filter; + unsigned int frag_to; + + struct timer_list expire_timer; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct timer_event_entry expire_timer_event; +#endif +#if defined(PCIE_POWER_SAVING) || defined(RF_MIMO_SWITCH) + struct timer_list ps_timer; +#endif + +#ifdef BEAMFORMING_SUPPORT + struct timer_list txbf_timer; + struct timer_list txbf_swtimer; +#endif + unsigned int auth_to; // second. time to expire in authenticating + unsigned int assoc_to; // second. time to expire before associating + unsigned int expire_to; // second. time to expire after associating +#ifdef MULTI_MAC_CLONE + unsigned int repeater_to;// second. time to expire for repeater to send null data +#endif + + struct timer_list ss_timer; //ss_timer: site_survey timer +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct timer_event_entry ss_timer_event; +#endif + +#ifdef RTK_NL80211 + struct nl_context nl_ctx; +#endif + + int rescantype; + unsigned int site_survey_times; + unsigned char ss_ssid[32]; + unsigned int ss_ssidlen; + unsigned char ss_req_ongoing; +#if defined( WIFI_SIMPLE_CONFIG ) && defined(UNIVERSAL_REPEATER) + unsigned char wsc_ss_delay; //for VXD WPS Scan delay +#endif +#ifdef CONFIG_RTL_COMAPI_WLTOOLS + wait_queue_head_t ss_wait; +#endif + + unsigned int auth_seq; + unsigned char chg_txt[128]; + + struct list_head stat_hash[NUM_STAT]; + struct list_head asoc_list; + struct list_head auth_list; + struct list_head defrag_list; + struct list_head sleep_list; + struct list_head wakeup_list; +#ifdef CONFIG_PCI_HCI + struct list_head addRAtid_list; // to avoid add RAtid fail + struct list_head addrssi_list; + struct list_head addps_list; +#endif +#if defined(SMP_SYNC) +#if (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) +#ifdef __ECOS + _mutex hash_list_lock; + _mutex auth_list_lock; + _mutex sleep_list_lock; + _mutex wakeup_list_lock; +#else + spinlock_t hash_list_lock; + spinlock_t auth_list_lock; + spinlock_t sleep_list_lock; + spinlock_t wakeup_list_lock; +#endif +#elif defined(CONFIG_PCI_HCI) + spinlock_t hash_list_lock; +#endif +#endif +#ifdef WIFI_SIMPLE_CONFIG + struct list_head wsc_disconn_list; + spinlock_t wsc_disconn_list_lock; +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct tx_desc tx_descB; +#endif +#ifdef WIFI_SIMPLE_CONFIG + unsigned int beaconbuf[MAX_WSC_IE_LEN]; + struct wsc_probe_request_info wsc_sta[MAX_WSC_PROBE_STA]; + unsigned int wps_issue_join_req; + unsigned int recover_join_req; + struct bss_desc dot11Bss_original; + int hidden_ap_mib_backup; + unsigned char *pbeacon_ssid; + + unsigned char orig_SSID[33]; + int orig_SSID_LEN; + +#else + unsigned int beaconbuf[128]; +#endif + +#ifdef RTK_NL80211 //wrt-adhoc + unsigned int beaconbuf_ibss_vxd[128]; //beacon data for vxd_adhoc + unsigned int beaconbuf_ibss_vxd_len; +#endif + + struct sta_mac_rssi probe_sta[32]; + + struct ht_cap_elmt ht_cap_buf; + unsigned int ht_cap_len; + struct ht_info_elmt ht_ie_buf; + unsigned int ht_ie_len; + unsigned int ht_legacy_obss_to; + unsigned int ht_nomember_legacy_sta_to; + unsigned int ht_legacy_sta_num; + unsigned int ht_protection; + unsigned int dc_th_current_state; + + +#ifdef RTK_AC_SUPPORT //defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + struct vht_cap_elmt vht_cap_buf; + unsigned int vht_cap_len; + struct vht_oper_elmt vht_oper_buf; + unsigned int vht_oper_len; +#endif + +#ifdef CONFIG_PCI_HCI + // to avoid add RAtid fail +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + struct timer_list add_RATid_timer; + struct timer_list add_rssi_timer; +#endif + struct timer_list add_ps_timer; +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + struct timer_list dnc_timer; +#endif + + unsigned short timoffset; + unsigned char dtimcount; + unsigned char pkt_in_dtimQ; + unsigned char pkt_in_hiQ; + + //struct stat_info_cache stainfo_cache; + struct stat_info *pstat_cache; + + struct list_head rx_datalist; + struct list_head rx_mgtlist; + struct list_head rx_ctrllist; +#ifdef SMP_SYNC +#ifdef __KERNEL__ + spinlock_t rx_datalist_lock; + spinlock_t rx_mgtlist_lock; + spinlock_t rx_ctrllist_lock; +#endif +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + _mutex rc_packet_q_lock; +#else + spinlock_t rc_packet_q_lock; + spinlock_t psk_gkrekey_lock; + spinlock_t psk_resend_lock; +#endif +#endif + spinlock_t defrag_lock; + + int assoc_num; // association client number + int link_status; +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + int link_status_bak; +#endif + + unsigned short *pBeaconCapability; // ptr of capability field in beacon buf +// unsigned char *pBeaconErp; // ptr of ERP field in beacon buf + + unsigned int available_chnl[MAX_CHANNEL_NUM]; // all available channel we can use + unsigned int available_chnl_num; // record the number +#ifdef MBSSID + unsigned int MultiSTA_available_chnl[MAX_CHANNEL_NUM]; /*when more than one VAP interface as STA mode*/ + unsigned int MultiSTA_available_chnl_num; + unsigned int MultiSTA_available_backup; +#endif + +#ifdef CONFIG_RTL_NEW_AUTOCH + unsigned int chnl_ss_fa_count[MAX_CHANNEL_NUM]; // record FA count while ss + unsigned int chnl_ss_cca_count[MAX_CHANNEL_NUM]; // record CCA count while ss +#ifdef SS_CH_LOAD_PROC + unsigned char chnl_ss_load[MAX_CHANNEL_NUM]; // record noise level while ss +#endif + unsigned int chnl_ss_mac_rx_count[MAX_CHANNEL_NUM]; + unsigned int chnl_ss_mac_rx_count_40M[MAX_CHANNEL_NUM]; + unsigned int nhm_cnt[14][10]; +#endif +#ifdef P2P_SUPPORT + unsigned int back_available_chnl[MAX_CHANNEL_NUM]; // all available channel we can use + unsigned int back_available_chnl_num; // record the number +#endif + + + //unsigned int oper_band; // remember the operating bands + unsigned int supported_rates; + unsigned int basic_rates; + + // for MIC check + struct timer_list MIC_check_timer; + struct timer_list assoc_reject_timer; + unsigned int MIC_timer_on; + unsigned int assoc_reject_on; + unsigned char assoc_reject_mac[6]; + +#ifdef CLIENT_MODE + struct timer_list reauth_timer; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct timer_event_entry reauth_timer_event; +#endif + unsigned int reauth_count; + + struct timer_list reassoc_timer; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct timer_event_entry reassoc_timer_event; +#endif + unsigned int reassoc_count; + + struct timer_list idle_timer; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + struct timer_event_entry idle_timer_event; +#endif +#ifdef DFS + struct timer_list dfs_cntdwn_timer; +#endif + + unsigned int join_req_ongoing; + int join_index; + unsigned long jiffies_pre; + unsigned int ibss_tx_beacon; + unsigned int rxBeaconNumInPeriod; + unsigned int rxBeaconCntArray[ROAMING_DECISION_PERIOD_ARRAY]; + unsigned int rxBeaconCntArrayIdx; // current index of array + unsigned int rxBeaconCntArrayWindow; // Is slide windows full + unsigned int rxBeaconPercentage; + unsigned int rxDataNumInPeriod; + unsigned int rxDataCntArray[ROAMING_DECISION_PERIOD_ARRAY]; + unsigned int rxMlcstDataNumInPeriod; +// unsigned int rxDataNumInPeriod_pre; +// unsigned int rxMlcstDataNumInPeriod_pre; + unsigned int dual_band; + unsigned int supported_rates_alt; + unsigned int basic_rates_alt; + unsigned char rx_timestamp[8]; + UINT64 prev_tsf; + unsigned int dot114WayStatus; +#endif + + int authModeToggle; // auth mode toggle referred when auto-auth mode is set under client mode, david + int authModeRetry; // auth mode retry sequence when auto-auth mode is set under client mode + + int acLogCountdown; // log count-down time + struct ac_log_info acLog[MAX_AC_LOG]; + + struct tx_desc *amsdu_first_desc; + + unsigned int bcnTxAGC; + unsigned int bcnTxAGC_bak; + unsigned short tx_beacon_len; + +#ifdef WIFI_11N_2040_COEXIST + struct obss_scan_para_elmt obss_scan_para_buf; + unsigned int obss_scan_para_len; + unsigned int bg_ap_timeout; +#ifdef CLIENT_MODE + unsigned int bg_ap_timeout_ch[14]; + unsigned int intolerant_timeout; + unsigned int coexist_connection; +#endif + STA_BITMAP force_20_sta; + STA_BITMAP switch_20_sta; +#endif + + /********************************************************************* + * from here on till EE_Cached will be backup during hang up reset * + *********************************************************************/ +#ifdef CLIENT_MODE + unsigned int join_res; + unsigned int beacon_period; + unsigned short aid; + unsigned int ps_state; +#if defined(WIFI_WMM) && defined (WMM_APSD) + unsigned int uapsd_assoc; +#endif +#ifdef RTK_BR_EXT + unsigned int macclone_completed; + struct nat25_network_db_entry *nethash[NAT25_HASH_SIZE]; + int pppoe_connection_in_progress; + unsigned char pppoe_addr[MACADDRLEN]; + unsigned char scdb_mac[MACADDRLEN]; + unsigned char scdb_ip[4]; + struct nat25_network_db_entry *scdb_entry; + unsigned char br_mac[MACADDRLEN]; + unsigned char br_ip[4]; + unsigned char ukpro_mac[MACADDRLEN]; // mac address of unknown protocol + unsigned char ukpro_mac_valid; // if the above entry is valid +#endif + unsigned char up_flag; +#endif + +#ifdef MICERR_TEST + unsigned int micerr_flag; +#endif + +#ifdef DFS + struct timer_list DFS_timer; /* timer for radar detection */ + struct timer_list DFS_TXPAUSE_timer; /* timer for checking whether restarting TX or not*/ + struct timer_list ch_avail_chk_timer; /* timer for channel availability check */ + struct timer_list dfs_chk_timer; /* timer for dfs trigger */ + struct timer_list dfs_det_chk_timer; /* timer for channel busy check under dfs */ + unsigned int FA_count_pre; + unsigned int FA_count_inc_pre; + unsigned int VHT_CRC_ok_cnt_pre; + unsigned int HT_CRC_ok_cnt_pre; + unsigned int LEG_CRC_ok_cnt_pre; +#if defined(CONFIG_WLAN_HAL_8814AE) + unsigned char g_ti_pre[16]; + unsigned char g_pw_pre[6]; + unsigned char g_pri_pre[6]; +#endif + unsigned char radar_det_mask_hist[10]; + unsigned char mask_idx; + unsigned char mask_hist_checked; + unsigned char pulse_flag_hist[10]; + unsigned char det_asoc_clear; + unsigned int short_pulse_cnt_pre; + unsigned int long_pulse_cnt_pre; + unsigned int st_L2H_cur; + unsigned char idle_flag; + unsigned char ini_gain_pre; + unsigned char ini_gain_cur; + unsigned char peak_th; + unsigned char short_pulse_cnt_th; + unsigned char long_pulse_cnt_th; + unsigned char peak_window; + unsigned char nb2wb_th; + unsigned char three_peak_opt; + unsigned char three_peak_th2; + unsigned char ch_120_132_CAC_end; + int pwdb_th; + int PSD_report_right[10][20]; + int PSD_report_left[10][20]; + int max_hold_right[20]; + int max_hold_left[20]; + int fa_inc_hist[5]; +#endif + +#ifdef GBWC + struct timer_list GBWC_timer; + struct pkt_queue GBWC_tx_queue; + struct pkt_queue GBWC_rx_queue; + unsigned int GBWC_tx_count; + unsigned int GBWC_rx_count; + unsigned int GBWC_consuming_Q; +#endif + +#ifdef SUPPORT_SNMP_MIB + struct mib_snmp snmp_mib; +#endif + +#ifdef CONFIG_PCI_HCI + struct pkt_queue dz_queue; // Queue for multicast pkts when there is sleeping sta +#endif + unsigned char release_mcast; + unsigned char func_off_already; + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + unsigned int tx_mc_pkt_num; + struct tx_servq tx_mc_queue; + struct tx_servq tx_mgnt_queue; +#endif + +#ifndef USE_RTL8186_SDK + unsigned int amsdu_first_dma_desc; +// unsigned int ampdu_first_dma_desc; +#endif + int amsdu_len; + int ampdu_len; + +#ifdef CHECK_RX_HANGUP + unsigned long rx_packets_pre1; + unsigned long rx_packets_pre2; + unsigned int rx_start_monitor_running; +#endif + +#ifdef USB_PKT_RATE_CTRL_SUPPORT + unsigned int change_toggle; + unsigned int pre_pkt_cnt; + unsigned int pkt_nsec_diff; + unsigned int poll_usb_cnt; + unsigned int auto_rate_mask; +#endif + +#ifdef CONFIG_RTL8186_KB + GUESTMAC_T guestMac[MAX_GUEST_NUM]; +#endif + +#ifdef CONFIG_RTK_VLAN_SUPPORT + int global_vlan_enable; + struct vlan_info vlan_setting; +#endif + +#ifdef SUPPORT_TX_MCAST2UNI + int stop_tx_mcast2uni; +#endif + +#ifdef CONFIG_OFFLOAD_FUNCTION + unsigned int offload_function_ctrl; + unsigned char offload_bcn_page; + unsigned char offload_proc_page; +#endif //#ifdef CONFIG_OFFLOAD_FUNCTION + +#ifdef CONFIG_8814_AP_MAC_VERI + unsigned char macID_temp; + unsigned char lowestRate_TXDESCen; + unsigned int lowestRate; + unsigned char RXMACIDTestEn; + unsigned char pwrState[128]; + unsigned char pwrHWState[128]; + unsigned char pwroldHWState[128]; + unsigned int pwrStateCnt[128]; + unsigned int pwrStateHWCnt[128]; + unsigned char testResult; + unsigned short hw_seq[128]; + unsigned short sw_seq; + unsigned char test_seq_MACID; + unsigned char sw_Carrier; + unsigned char hw_Carrier; +#endif //#ifdef CONFIG_OFFLOAD_FUNCTION + +#ifdef PCIE_POWER_SAVING + unsigned int offload_ctrl; + unsigned char pwr_state; + unsigned char ps_ctrl; +#ifdef PCIE_POWER_SAVING_DEBUG + char firstPkt; +#endif +#endif + +#ifdef SW_TX_QUEUE + unsigned char record_mac[6]; + int record_qnum; + int swq_txmac_chg; + int swq_en; + int swq_decision; + unsigned short record_aid; + unsigned long swqen_keeptime; +#ifdef SW_TX_QUEUE_SMALL_PACKET_CHECK + int swq_boost_delay; +#endif +#endif + int em_txop_tp_high; +#ifdef A4_STA + struct list_head a4_sta_list; + struct a4_sta_db_entry *machash[A4_STA_HASH_SIZE]; + struct a4_tbl_entry a4_ent[MAX_A4_TBL_NUM]; +#endif + +#ifdef WIFI_WPAS + unsigned char wpas_manual_assoc; //_Eric ?? +#endif + int update_bcn_period; + +#ifdef SUPPORT_MULTI_PROFILE + int profile_idx; // indicate next used profile. + int mask_n_band; +#endif +#ifdef SWITCH_CHAN + int chan_backup; + int bw_backup; + int offset_backup; + int func_backup; +#endif +#if defined(CONFIG_RTL_8812_SUPPORT)||defined(CONFIG_WLAN_HAL_8881A) + char bFWReady; +#endif +#ifdef HS2_SUPPORT + /* Hotspot 2.0 Release 1 */ + unsigned char timeadvt_dtimcount; + unsigned char channel_utilization; + unsigned int dgaf_disable; + unsigned int proxy_arp; + unsigned int cu_initialcnt; + unsigned int cu_cntdwn; + int chbusytime; + struct timer_list cu_cntdwn_timer; +#endif +#ifdef CONFIG_IEEE80211W_CLI // all ap's cap + unsigned char support_sha256; + unsigned char support_pmf; +#endif +#ifdef CONFIG_RTL_WLAN_STATUS + int wlan_status_flag; +#endif +#ifdef USER_ADDIE + struct user_ie user_ie_list[MAX_USER_IE]; +#endif +#ifdef CONFIG_RTL_SIMPLE_CONFIG + int simple_config_status; + int simple_config_time; + int simple_config_could_fix; +#endif +#ifdef RTK_NL80211 + u8 default_mgmt_key_idx; +#endif +} RTL8192CD_PRIV, *PRTL8192CD_PRIV; + +struct rtl8192cd_chr_priv { + unsigned int major; + unsigned int minor; + struct rtl8192cd_priv* wlan_priv; + struct fasync_struct* asoc_fasync; // asynch notification +}; + +#ifdef NETDEV_NO_PRIV +struct rtl8192cd_wds_priv { + struct rtl8192cd_priv* wlan_priv; //This element shall be put at top of this struct +}; +#endif + +/* station info, reported to web server */ +typedef struct _sta_info_2_web { + unsigned short aid; + unsigned char addr[6]; + unsigned long tx_packets; + unsigned long rx_packets; + unsigned long expired_time; // 10 msec unit + unsigned short flags; + unsigned char TxOperaRate; + unsigned char rssi; + unsigned long link_time; // 1 sec unit + unsigned long tx_fail; + unsigned long tx_bytes; + unsigned long rx_bytes; + unsigned char network; + unsigned char ht_info; // bit0: 0=20M mode, 1=40M mode; bit1: 0=longGI, 1=shortGI + unsigned char RxOperaRate; +#ifdef TLN_STATS + unsigned char auth_type; + unsigned char enc_type; + unsigned char resv[1]; +#else + unsigned char resv[3]; +#endif + unsigned short acTxOperaRate; +} sta_info_2_web; + +#define NULL_MAC_ADDR ("\x0\x0\x0\x0\x0\x0") + +// Macros +#define GET_MIB(priv) (priv->pmib) +#define GET_HW(priv) (priv->pshare->phw) +#if !defined(CONFIG_PCI_HCI) +#define GET_HAL_INTF_DATA(priv) (priv->pshare->pHalData) +#endif + +#define AP_BSSRATE ((GET_MIB(priv))->dot11StationConfigEntry.dot11OperationalRateSet) +#define AP_BSSRATE_LEN ((GET_MIB(priv))->dot11StationConfigEntry.dot11OperationalRateSetLen) + +#ifdef RTK_AC_SUPPORT //vht rate +#define AP_BSSRATE_AC (priv->pshare->rf_ft_var.dot11OperationalRateSet_AC) +#define AP_BSSRATE_LEN_AC (priv->pshare->rf_ft_var.dot11OperationalRateSetLen_AC) +#define AC_SIGMA_MODE (priv->pshare->rf_ft_var.sigma_mode) +#endif + + +#define STAT_OPRATE (pstat->bssrateset) +#define STAT_OPRATE_LEN (pstat->bssratelen) + +#define BSSID ((GET_MIB(priv))->dot11StationConfigEntry.dot11Bssid) + +#define SSID ((GET_MIB(priv))->dot11StationConfigEntry.dot11DesiredSSID) + +#define SSID_LEN ((GET_MIB(priv))->dot11StationConfigEntry.dot11DesiredSSIDLen) + +#ifdef MULTI_MAC_CLONE +#if defined(SMP_SYNC) +#define ACTIVE_ID (priv->pshare->mclone_active_id[smp_processor_id()]) +#else +#define ACTIVE_ID (priv->pshare->mclone_active_id) +#endif +#define MCLONE_NUM (priv->pshare->mclone_num) + +#define OPMODE_VXD (((ACTIVE_ID > 0) && ((GET_MIB((GET_VXD_PRIV(priv))))->dot11OperationEntry.opmode & WIFI_STATION_STATE)) ? priv->pshare->mclone_sta[ACTIVE_ID-1].opmode : (GET_MIB(priv))->dot11OperationEntry.opmode) + +#define OPMODE (((ACTIVE_ID > 0) && ((GET_MIB(priv))->dot11OperationEntry.opmode & WIFI_STATION_STATE)) ? priv->pshare->mclone_sta[ACTIVE_ID-1].opmode : (GET_MIB(priv))->dot11OperationEntry.opmode) +#define OPMODE_VAL(mod) do {\ + if ( (ACTIVE_ID > 0) && ((GET_MIB(priv))->dot11OperationEntry.opmode & WIFI_STATION_STATE)) \ + priv->pshare->mclone_sta[ACTIVE_ID-1].opmode = mod;\ + else\ + (GET_MIB(priv))->dot11OperationEntry.opmode = mod;\ + } while (0) +#else +#define ACTIVE_ID (0) +#define OPMODE_VXD ((GET_MIB((GET_VXD_PRIV(priv))))->dot11OperationEntry.opmode) +#define OPMODE ((GET_MIB(priv))->dot11OperationEntry.opmode) +#define OPMODE_VAL(mod) do {\ + (GET_MIB(priv))->dot11OperationEntry.opmode = mod;\ + } while (0) +#endif + +#define HIDDEN_AP ((GET_MIB(priv))->dot11OperationEntry.hiddenAP) + +#define RTSTHRSLD ((GET_MIB(priv))->dot11OperationEntry.dot11RTSThreshold) + +#define FRAGTHRSLD ((GET_MIB(priv))->dot11OperationEntry.dot11FragmentationThreshold) + +#define EXPIRETIME ((GET_MIB(priv))->dot11OperationEntry.expiretime) + +#define LED_TYPE ((GET_MIB(priv))->dot11OperationEntry.ledtype) + +#ifdef RTL8190_SWGPIO_LED +#define LED_ROUTE ((GET_MIB(priv))->dot11OperationEntry.ledroute) +#endif + +#define IAPP_ENABLE ((GET_MIB(priv))->dot11OperationEntry.iapp_enable) + +#define SWCRYPTO ((GET_MIB(priv))->dot11StationConfigEntry.dot11swcrypto) + +#define IEEE8021X_FUN ((GET_MIB(priv))->dot118021xAuthEntry.dot118021xAlgrthm) + +#define ACCT_FUN ((GET_MIB(priv))->dot118021xAuthEntry.acct_enabled) + +#define ACCT_FUN_TIME ((GET_MIB(priv))->dot118021xAuthEntry.acct_timeout_period) + +#define ACCT_FUN_TP ((GET_MIB(priv))->dot118021xAuthEntry.acct_timeout_throughput) + +#define ACCT_TP_INT 60 + +#define SHORTPREAMBLE ((GET_MIB(priv))->dot11RFEntry.shortpreamble) + +#define SSID2SCAN ((GET_MIB(priv))->dot11StationConfigEntry.dot11SSIDtoScan) + +#define SSID2SCAN_LEN ((GET_MIB(priv))->dot11StationConfigEntry.dot11SSIDtoScanLen) + +#define RX_BUF_LEN ((GET_MIB(priv))->dot11nConfigEntry.dot11nAMSDURecvMax?(MAX_RX_BUF_LEN):(MIN_RX_BUF_LEN)) + +#ifdef WIFI_WMM +#define QOS_ENABLE ((GET_MIB(priv))->dot11QosEntry.dot11QosEnable) + +#define APSD_ENABLE ((GET_MIB(priv))->dot11QosEntry.dot11QosAPSD) + +#define GET_WMM_IE ((GET_MIB(priv))->dot11QosEntry.WMM_IE) + +#define GET_WMM_PARA_IE ((GET_MIB(priv))->dot11QosEntry.WMM_PARA_IE) + +#define GET_EDCA_PARA_UPDATE ((GET_MIB(priv))->dot11QosEntry.EDCAparaUpdateCount) + +#define GET_STA_AC_BE_PARA ((GET_MIB(priv))->dot11QosEntry.STA_AC_BE_paraRecord) + +#define GET_STA_AC_BK_PARA ((GET_MIB(priv))->dot11QosEntry.STA_AC_BK_paraRecord) + +#define GET_STA_AC_VI_PARA ((GET_MIB(priv))->dot11QosEntry.STA_AC_VI_paraRecord) + +#define GET_STA_AC_VO_PARA ((GET_MIB(priv))->dot11QosEntry.STA_AC_VO_paraRecord) +#endif + +#define COUNTRY_CODE_ENABLED ((GET_MIB(priv))->dot11dCountry.dot11CountryCodeSwitch) + +#ifdef P2P_SUPPORT +#define P2PMODE ((GET_MIB(priv))->p2p_mib.p2p_type) +#define P2P_STATE ((GET_MIB(priv))->p2p_mib.p2p_state) +#define P2P_DISCOVERY ((GET_MIB(priv))->p2p_mib.p2p_on_discovery) +#define P2P_EVENT_INDICATE ((GET_MIB(priv))->p2p_mib.p2p_event_indiate) + +#endif + + +#define AMPDU_ENABLE ((GET_MIB(priv))->dot11nConfigEntry.dot11nAMPDU) +#define AMSDU_ENABLE ((GET_MIB(priv))->dot11nConfigEntry.dot11nAMSDU) + +#define TSF_LESS(a, b) (((a - b) & 0x80000000) != 0) +#define TSF_DIFF(a, b) ((a >= b)? (a - b):(0xffffffff - b + a + 1)) + +#define GET_GROUP_MIC_KEYLEN ((GET_MIB(priv))->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKeyLen) +#define GET_GROUP_TKIP_MIC1_KEY ((GET_MIB(priv))->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKey1.skey) +#define GET_GROUP_TKIP_MIC2_KEY ((GET_MIB(priv))->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKey2.skey) + +#define GET_UNICAST_MIC_KEYLEN (pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKeyLen) +#define GET_UNICAST_TKIP_MIC1_KEY (pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKey1.skey) +#define GET_UNICAST_TKIP_MIC2_KEY (pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKey2.skey) + +#define GET_GROUP_ENCRYP_KEY ((GET_MIB(priv))->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey) +#define GET_UNICAST_ENCRYP_KEY (pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKey.skey) +#ifdef CONFIG_IEEE80211W +#define GET_IGROUP_ENCRYP_KEY ((GET_MIB(priv))->dot11IGTKTable.dot11EncryptKey.dot11TTKey.skey) +#endif + +#define GET_GROUP_ENCRYP_KEYLEN ((GET_MIB(priv))->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen) +#define GET_UNICAST_ENCRYP_KEYLEN (pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen) + +#ifdef MULTI_MAC_CLONE +#define GET_MY_HWADDR ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].hwaddr : (GET_MIB(priv))->dot11OperationEntry.hwaddr) +#define AUTH_SEQ ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].auth_seq : priv->auth_seq) +#define AUTH_SEQ_VAL(res) do {\ + if (ACTIVE_ID > 0)\ + priv->pshare->mclone_sta[ACTIVE_ID-1].auth_seq = res;\ + else \ + priv->auth_seq = res;\ + } while(0) +#define REAUTH_COUNT ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].reauth_count : priv->reauth_count) +#define REAUTH_COUNT_VAL(res) do {\ + if (ACTIVE_ID > 0)\ + priv->pshare->mclone_sta[ACTIVE_ID-1].reauth_count = res;\ + else \ + priv->reauth_count = res;\ + } while(0) +#define REASSOC_COUNT ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].reassoc_count : priv->reassoc_count) +#define REASSOC_COUNT_VAL(res) do {\ + if (ACTIVE_ID > 0)\ + priv->pshare->mclone_sta[ACTIVE_ID-1].reassoc_count = res;\ + else \ + priv->reassoc_count = res;\ + } while(0) +#define AUTH_MODE_TOGGLE ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].authModeToggle : priv->authModeToggle) +#define AUTH_MODE_TOGGLE_VAL(res) do {\ + if (ACTIVE_ID > 0)\ + priv->pshare->mclone_sta[ACTIVE_ID-1].authModeToggle = res;\ + else \ + priv->authModeToggle = res;\ + } while(0) +#define AUTH_MODE_RETRY ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].authModeRetry : priv->authModeRetry) +#define AUTH_MODE_RETRY_VAL(res) do {\ + if (ACTIVE_ID > 0)\ + priv->pshare->mclone_sta[ACTIVE_ID-1].authModeRetry = res;\ + else \ + priv->authModeRetry = res;\ + } while(0) + +#define JOIN_RES ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].join_res : priv->join_res) +#define JOIN_RES_VAL(res) do {\ + if (ACTIVE_ID > 0)\ + priv->pshare->mclone_sta[ACTIVE_ID-1].join_res = res;\ + else \ + priv->join_res = res;\ + } while(0) +#define JOIN_REQ_ONGOING ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].join_req_ongoing : priv->join_req_ongoing) +#define JOIN_REQ_ONGOING_VAL(res) do {\ + if (ACTIVE_ID > 0)\ + priv->pshare->mclone_sta[ACTIVE_ID-1].join_req_ongoing = res;\ + else \ + priv->join_req_ongoing = res;\ + } while(0) +#define CHG_TXT ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].chg_txt : priv->chg_txt) +#define _AID ((ACTIVE_ID > 0) ? \ + priv->pshare->mclone_sta[ACTIVE_ID-1].aid : priv->aid) +#define AID_VAL(res) do {\ + if (ACTIVE_ID > 0)\ + priv->pshare->mclone_sta[ACTIVE_ID-1].aid = res;\ + else \ + priv->aid = res;\ + } while(0) +#define PENDING_REAUTH_TIMER ((ACTIVE_ID > 0) ? \ + timer_pending(&priv->pshare->mclone_sta[ACTIVE_ID-1].reauth_timer) : \ + timer_pending(&priv->reauth_timer)) +#define DELETE_REAUTH_TIMER ((ACTIVE_ID > 0) ? \ + del_timer(&priv->pshare->mclone_sta[ACTIVE_ID-1].reauth_timer) : \ + del_timer(&priv->reauth_timer)) +#define PENDING_REASSOC_TIMER ((ACTIVE_ID > 0) ? \ + timer_pending(&priv->pshare->mclone_sta[ACTIVE_ID-1].reassoc_timer) : \ + timer_pending(&priv->reassoc_timer)) +#define DELETE_REASSOC_TIMER ((ACTIVE_ID > 0) ? \ + del_timer(&priv->pshare->mclone_sta[ACTIVE_ID-1].reassoc_timer) : \ + del_timer(&priv->reassoc_timer)) + +#define MOD_REAUTH_TIMER(t) ((ACTIVE_ID > 0) ? \ + mod_timer (&priv->pshare->mclone_sta[ACTIVE_ID-1].reauth_timer, jiffies+t) : \ + mod_timer(&priv->reauth_timer, jiffies+t)) +#define MOD_REASSOC_TIMER(t) ((ACTIVE_ID > 0) ? \ + mod_timer (&priv->pshare->mclone_sta[ACTIVE_ID-1].reassoc_timer, jiffies+t) : \ + mod_timer(&priv->reassoc_timer, jiffies+t)) +#else +#define GET_MY_HWADDR ((GET_MIB(priv))->dot11OperationEntry.hwaddr) +#define AUTH_SEQ (priv->auth_seq) +#define AUTH_SEQ_VAL(res) (priv->auth_seq=res) +#define REAUTH_COUNT (priv->reauth_count) +#define REAUTH_COUNT_VAL(res) (priv->reauth_count=res) +#define REASSOC_COUNT (priv->reassoc_count) +#define REASSOC_COUNT_VAL(res) (priv->reassoc_count=res) +#define AUTH_MODE_TOGGLE (priv->authModeToggle) +#define AUTH_MODE_TOGGLE_VAL(res) (priv->authModeToggle=res) +#define AUTH_MODE_RETRY (priv->authModeRetry) +#define AUTH_MODE_RETRY_VAL(res) (priv->authModeRetry=res) +#define JOIN_RES (priv->join_res) +#define JOIN_RES_VAL(res) (priv->join_res=res) +#define JOIN_REQ_ONGOING (priv->join_req_ongoing) +#define JOIN_REQ_ONGOING_VAL(res) (priv->join_req_ongoing=res) +#define CHG_TXT (priv->chg_txt) +#define _AID (priv->aid) +#define AID_VAL(res) (priv->aid=res) +#define PENDING_REAUTH_TIMER (timer_pending(&priv->reauth_timer)) +#define DELETE_REAUTH_TIMER (del_timer(&priv->reauth_timer)) +#define PENDING_REASSOC_TIMER (timer_pending(&priv->reassoc_timer)) +#define DELETE_REASSOC_TIMER (del_timer(&priv->reassoc_timer)) +#define MOD_REAUTH_TIMER(t) (mod_timer(&priv->reauth_timer, jiffies+t)) +#define MOD_REASSOC_TIMER(t) (mod_timer(&priv->reassoc_timer, jiffies+t)) +#endif + +#define GET_GROUP_ENCRYP_PN (&((GET_MIB(priv))->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48)) +#define GET_UNICAST_ENCRYP_PN (&(pstat->dot11KeyMapping.dot11EncryptKey.dot11TXPN48)) +#ifdef CONFIG_IEEE80211W +#define GET_UNICAST_ENCRYP_MPN (&(pstat->dot11KeyMapping.dot11EncryptKey.dot11MTXPN48)) +#define GET_IGROUP_ENCRYP_PN (&((GET_MIB(priv))->dot11IGTKTable.dot11EncryptKey.dot11TXPN48)) +#endif + +#define SET_SHORTSLOT_IN_BEACON_CAP \ + do { \ + if (priv->pBeaconCapability != NULL) \ + *priv->pBeaconCapability |= cpu_to_le16(BIT(10)); \ + } while(0) + +#define RESET_SHORTSLOT_IN_BEACON_CAP \ + do { \ + if (priv->pBeaconCapability != NULL) \ + *priv->pBeaconCapability &= ~cpu_to_le16(BIT(10)); \ + } while(0) + +#define IS_DRV_OPEN(priv) ((priv==NULL) ? 0 : ((priv->drv_state & DRV_STATE_OPEN) ? 1 : 0)) + +#ifdef NETDEV_NO_PRIV + #define GET_DEV_PRIV(dev) ((struct rtl8192cd_priv *)netdev_priv(dev))->wlan_priv +#else + #define GET_DEV_PRIV(dev) (struct rtl8192cd_priv *)dev->priv +#endif + +#ifdef CONFIG_RTL_PROC_NEW + #define PROC_GET_DEV() (struct net_device *)(s->private) +#else + #define PROC_GET_DEV() (struct net_device *)data +#endif + + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) +//#define GET_ROOT_PRIV(priv) (priv->proot_priv) +#define IS_ROOT_INTERFACE(priv) ((priv->proot_priv) ? 0 : 1) +#define GET_ROOT(priv) ((priv->proot_priv) ? priv->proot_priv : priv) +#else +#define IS_ROOT_INTERFACE(priv) (1) +#define GET_ROOT(priv) (priv) +#endif +#ifdef UNIVERSAL_REPEATER +#define GET_VXD_PRIV(priv) (priv->pvxd_priv) +#ifdef MBSSID +#define IS_VXD_INTERFACE(priv) (((priv->proot_priv) ? 1 : 0) && (priv->vap_id < 0)) +#else +#define IS_VXD_INTERFACE(priv) ((priv->proot_priv) ? 1 : 0) +#endif +#else +#define GET_VXD_PRIV(priv) (NULL) +#define IS_VXD_INTERFACE(priv) 0 +#endif // UNIVERSAL_REPEATER +#ifdef MBSSID +#define GET_VAP_PRIV(priv, i) (GET_ROOT(priv)->pvap_priv[i]) +#define IS_VAP_INTERFACE(priv) (!IS_ROOT_INTERFACE(priv) && (priv->vap_id >= 0)) +#else +#define IS_VAP_INTERFACE(priv) 0 +#endif + +#if defined(RTK_NL80211) +#if defined(NON_NL80211_AP) || defined(NON_NL80211_WPAS) +#define IS_CFG80211_IFACE(priv) (priv->is_cfg80211_iface) +#else +#define IS_CFG80211_IFACE(priv) 1 +#endif +#endif + +#define MANAGE_QUE_NUM MGNT_QUEUE + +#ifdef DFS +#define DFS_TO RTL_10MILISECONDS_TO_JIFFIES(priv->pmib->dot11DFSEntry.DFS_timeout) +#define NONE_OCCUPANCY_PERIOD RTL_10MILISECONDS_TO_JIFFIES(priv->pmib->dot11DFSEntry.NOP_timeout) +#define DFS_TXPAUSE_TO RTL_10MILISECONDS_TO_JIFFIES(priv->pmib->dot11DFSEntry.DFS_TXPAUSE_timeout) +#endif + +#ifdef TX_EARLY_MODE +#define GET_TX_EARLY_MODE (priv->pshare->rf_ft_var.em_enable) +#define GET_EM_SWQ_ENABLE (priv->pshare->em_waitq_on) +#define MAX_EM_QUE_NUM (priv->pshare->rf_ft_var.em_que_num) +#define EM_TP_UP_BOUND (priv->pshare->rf_ft_var.em_swq_thd_high) +#define EM_TP_LOW_BOUND (priv->pshare->rf_ft_var.em_swq_thd_low) +#define WAIT_TP_TIME 3 /* wait TP limit for this period in sec */ +#endif + + +#ifdef __ECOS +#undef ASSERT +#endif + +#ifdef _DEBUG_RTL8192CD_ +#define ASSERT(expr) \ + if(!(expr)) { \ + printk( "\033[33;41m%s:%d: assert(%s)\033[m\n", \ + __FILE__,__LINE__,#expr); \ + } +#else +#define ASSERT(expr) +#endif + +#ifdef USE_OUT_SRC +#define ODMPTR (&(priv->pshare->_dmODM)) +#endif + +#ifdef RTL8190_SWGPIO_LED +/* ===================================================================== + LED route configuration: + + Currently, LOW 10 bits of this MIB are used. + + +---+---+---+---+---+---+---+---+---+---+ + | E1| H1| Route 1 | E0| H0| Route 0 | + +---+---+---+---+---+---+---+---+---+---+ + + E0 : Indicates if the field route 0 is valid or not. + E1 : Indicates if the field route 1 is valid or not. + H0 : Indicate the GPIO indicated by route 0 is Active HIGH or Active LOW. ( 0: Active LOW, 1: Active HIGH) + H1 : Indicate the GPIO indicated by route 1 is Active HIGH or Active LOW. ( 0: Active LOW, 1: Active HIGH) + Route0 : The GPIO number (0~6) which used by LED0. Only used when E0=0b'1 + Route1 : The GPIO number (0~6) which used by LED1. Only used when E1=0b'1 + + Unused bits : reserved for further extension, must set to 0. + + Currently RTL8185 AP driver supports LED0/LED1, and RTL8185 has 7 GPIOs in it. + So we need a routing-mechanism to decide what GPIO is used for LED0/LED1. + The bit-field pairs {E0, H0, Route0}, {E1, H0, Route1} is used to set it. + Ex. + One customer only use GPIO0 for LED1 (Active LOW) and don't need LED0, + he can set the route being: + ---------------------------------- + E0 = 0 + E1 = 1 + H0 = 0 ( Driver would ignore it ) + H1 = 0 ( Driver would ignore it ) + Route 0 = 0 ( Driver would ignore it ) + Route 1 = 0 ( GPIO0 ) + + ledroute = 0x10 << 5; : LED1 -Active LOW, GPIO0 + ledroute |= 0; : LED0 -Disabled + ---------------------------------- + ===================================================================== */ +#define SWLED_GPIORT_CNT 2 /* totally we have max 3 GPIOs reserved for LED route usage */ +#define SWLED_GPIORT_RTBITMSK 0x07 /* bit mask of routing field = 0b'111 */ +#define SWLED_GPIORT_HLMSK 0x08 /* bit mask of Active high/low field = 0b'1000 */ +#define SWLED_GPIORT_ENABLEMSK 0x10 /* bit mask of enable filed = 0b'10000 */ +#define SWLED_GPIORT_ITEMBITCNT 5 /* total bit count of each item */ +#define SWLED_GPIORT_ITEMBITMASK ( SWLED_GPIORT_RTBITMSK |\ + SWLED_GPIORT_HLMSK |\ + SWLED_GPIORT_ENABLEMSK) /* bit mask of each item */ +#define SWLED_GPIORT_ITEM(ledroute, x) (((ledroute) >> ((x)*SWLED_GPIORT_ITEMBITCNT)) & SWLED_GPIORT_ITEMBITMASK) +#endif // RTL8190_SWGPIO_LED + +#ifdef SUPPORT_SNMP_MIB +#define SNMP_MIB(f) (priv->snmp_mib.f) +#define SNMP_MIB_ASSIGN(f,v) (SNMP_MIB(f)=v) +#define SNMP_MIB_COPY(f,v,len) (memcpy(&SNMP_MIB(f), v, len)) +#define SNMP_MIB_INC(f,v) (SNMP_MIB(f)+=v) +#define SNMP_MIB_DEC(f,v) (SNMP_MIB(f)-=v) + +#else + +#define SNMP_MIB(f) +#define SNMP_MIB_ASSIGN(f,v) +#define SNMP_MIB_COPY(f,v,len) +#define SNMP_MIB_INC(f,v) +#define SNMP_MIB_DEC(f,v) +#endif //SUPPORT_SNMP_MIB + + +#ifdef USB_PKT_RATE_CTRL_SUPPORT +typedef unsigned int (*usb_pktCnt_fn)(void); +typedef unsigned int (*register_usb_pkt_cnt_fn)(void *); +extern register_usb_pkt_cnt_fn register_usb_hook; +#endif + + +#ifdef CONFIG_RTK_VLAN_SUPPORT +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) +extern int rx_vlan_process(struct net_device *dev, struct VlanConfig *info_ori, struct sk_buff *skb, struct sk_buff **new_skb); +extern int tx_vlan_process(struct net_device *dev, struct VlanConfig *info_ori, struct sk_buff *skb, int wlan_pri); +#else +extern int rx_vlan_process(struct net_device *dev, struct VlanConfig *info, struct sk_buff *skb); +extern int tx_vlan_process(struct net_device *dev, struct VlanConfig *info, struct sk_buff *skb, int wlan_pri); +#endif +#endif + +#ifdef __ECOS +#ifdef CONFIG_RTL_VLAN_SUPPORT +extern int rtl_vlan_support_enable; +#ifdef CONFIG_RTL_BRIDGE_VLAN_SUPPORT +extern int rtl_vlanIngressProcess(struct sk_buff *skb, unsigned char *dev_name, struct sk_buff **new_skb); +extern int rtl_vlanEgressProcess(struct sk_buff *skb, unsigned char *dev_name, int wlan_pri); +#else +extern int rtl_vlanIngressProcess(struct sk_buff *skb, unsigned char *dev_name); +extern int rtl_vlanEgressProcess(struct sk_buff *skb, unsigned char *dev_name, int wlan_pri); +#endif +#endif +#endif + +//#ifdef SUPPORT_TX_MCAST2UNI +#define IP_MCAST_MAC(mac) ((mac[0]==0x01)&&(mac[1]==0x00)&&(mac[2]==0x5e)) +#define IPV6_MCAST_MAC(mac) ((mac[0]==0x33)&&(mac[1]==0x33)) + +/*match is (1)ipv4 && (2)(IGMP control/management packet) */ +#define IS_IGMP_PROTO(mac) ((mac[12]==0x08) && (mac[13]==0x00) && (mac[23]==0x02)) +/* for Hotspot 2.0 Release 1 */ +#define IS_ICMPV4_PROTO(mac) ((mac[12]==0x08) && (mac[13]==0x00) && (mac[23]==0x01)) +#define IS_ICMPV4_ECHO_TYPE(mac) (mac[34]==0x08 || mac[34]==0x00) + +#define IS_ICMPV6_PROTO(mac) ( (mac[12]==0x86)&&(mac[13]==0xdd) && ((mac[20]==0x3a)||(mac[54]==0x3a))) +#define IS_MDNSV4_MAC(mac) ((mac[0]==0x01)&&(mac[1]==0x00)&&(mac[2]==0x5e)&& (mac[3]==0x00)&&(mac[4]==0x00)&&(mac[5]==0xFB)&&(mac[12]==0x08)&&(mac[13]==0x00)) +#define IS_MDNSV6_MAC(mac) ((mac[0]==0x33)&&(mac[1]==0x33)&&(mac[2]==0x00)&& (mac[3]==0x00)&&(mac[4]==0x00)&&(mac[5]==0xFB)&&(mac[12]==0x86)&&(mac[13]==0xdd)) + +//#ifdef TX_SUPPORT_IPV6_MCAST2UNI +#define ICMPV6_MCAST_MAC(mac) ((mac[0]==0x33)&&(mac[1]==0x33)&&(mac[2]!=0xff)) +/* for Hotspot 2.0 Release 1 */ +#define ICMPV6_MCAST_SOLI_MAC(mac) ((mac[0]==0x33)&&(mac[1]==0x33)&&(mac[2]==0xff)) + +#define ICMPV6_PROTO1A_VALN(mac) ( (mac[12+4]==0x86)&&(mac[13+4]==0xdd)&& (mac[54+4]==0x3a)) +#define ICMPV6_PROTO1B_VALN(mac) ( (mac[12+4]==0x86)&&(mac[13+4]==0xdd)&& (mac[20+4]==0x3a)) +#define ICMPV6_PROTO2X_VALN(mac) ( (mac[12+4]==0x86)&&(mac[13+4]==0xdd)&& (mac[54+4]==0x3a || mac[20+4]==0x3a)) + +#define ICMPV6_PROTO1A(mac) ( (mac[12]==0x86)&&(mac[13]==0xdd)&& (mac[54]==0x3a)) +#define ICMPV6_PROTO1B(mac) ( (mac[12]==0x86)&&(mac[13]==0xdd)&& (mac[20]==0x3a)) +#define ICMPV6_PROTO2X(mac) ( (mac[12]==0x86)&&(mac[13]==0xdd)&& (mac[54]==0x3a || mac[20]==0x3a)) + +//#endif +//#endif + +#if defined(TXREPORT) //&& (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) +struct tx_rpt { + unsigned short txfail; + unsigned short txok; + unsigned short macid; + unsigned char initil_tx_rate; //add for 8812 +}; +#endif + +struct _device_info_ { + int type; + unsigned long conf_addr; + unsigned long base_addr; + int irq; + struct rtl8192cd_priv *priv; +}; + +#define HIDE_AP_FOUND 1 +#define HIDE_AP_FOUND_DO_ACTIVE_SSAN 2 + + +#ifdef GBWC +#define GBWC_MODE_DISABLE 0 +#define GBWC_MODE_LIMIT_MAC_INNER 1 // limit bw by mac address +#define GBWC_MODE_LIMIT_MAC_OUTTER 2 // limit bw by excluding the mac +#define GBWC_MODE_LIMIT_IF_TX 3 // limit bw by interface tx +#define GBWC_MODE_LIMIT_IF_RX 4 // limit bw by interface rx +#define GBWC_MODE_LIMIT_IF_TRX 5 // limit bw by interface tx/rx +#endif + +// andrew, define a compatible data macro +#if defined(__ECOS) +// This marco is OK in RX flow, but TX flow need to confirm +#define SKB_MAC_HEADER(s) (s)->data +#elif defined(LINUX_2_6_22_) +#define SKB_MAC_HEADER(s) skb_mac_header(s) +#else // older 2.6 header +#define SKB_MAC_HEADER(s) (s)->mac.raw +#endif +#define SKB_IP_HEADER(s) (struct iphdr *)(SKB_MAC_HEADER(s) + ETH_HLEN); + +#if !defined(__KERNEL__) || (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35)) +#define GET_BR_PORT(netdev) (netdev)->br_port +#else +#define GET_BR_PORT(netdev) br_port_get_rcu(netdev) +#endif + + +#ifdef __KERNEL__ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) +static inline void skb_reset_network_header(struct sk_buff *skb) +{ + skb->nh.raw = skb->data; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) +#include +static inline int arp_hdr_len(struct net_device *dev) +{ + /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ + return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, + void *daddr, void *saddr, + unsigned len) +{ + return dev->hard_header(skb, dev, type, daddr, saddr, len); +} +#endif +#endif // __KERNEL__ + +#ifdef BEAMFORMING_SUPPORT + +#define IsCtrlNDPA(pdu) ( ((EF1Byte(pdu[0]) & 0xFC) == Type_NDPA) ? TRUE : FALSE) +#define IsMgntActionNoAck(pdu) ( ((EF1Byte(pdu[0]) & 0xFC) == Type_Action_No_Ack ) ? TRUE : FALSE) +#define GET_80211_HDR_ORDER(_hdr) LE_BITS_TO_2BYTE(_hdr, 15, 1) +#endif + +#ifdef __ECOS +extern struct _device_info_ wlan_device[]; +#endif + +#ifdef CONFIG_WLAN_HAL +#include "WlanHAL/Output/HalLib.h" + +//#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV +enum _HW_TX_SHORTCUT_ { + // for header conversion ( 802.3 -> 802.11 ) + HW_TX_SC_NORMAL = 0, + HW_TX_SC_BACKUP_HEADER = 1, + HW_TX_SC_HEADER_CONV = 2, +}; +//#endif + + +#endif //CONFIG_WLAN_HAL + +#define RESCAN 1 +#define DONTRESCAN 0 + +#define RESCAN_ROAMING 2 + +#define RESCAN_BY_NEXTTIME 0 + +#define SSFROM_WEB 1 +#define SSFROM_WSC 2 +#define SSFROM_REPEATER_VXD 3 +#define SSFROM_WPAS 4 + +/*sorting by profile*/ +enum { + COMPARE_BSS = 0, + COMPARE_WSCIE = 1, + COMPARE_WPAIE = 2, + COMPARE_RSNIE = 3 +}; + +enum { + SS_LV_WSTA = 0, + SS_LV_WOSTA = 1, + SS_LV_ROOTFUNCOFF = 2 +}; + + +#define CHECK_VXD_AP_TIMEOUT RTL_SECONDS_TO_JIFFIES(60) +#define CHECK_VXD_RUN_DELAY RTL_SECONDS_TO_JIFFIES(15) +#define CHECK_VXD_24G_AP_NOSTA_TIMEOUT RTL_SECONDS_TO_JIFFIES(15) +#define CHECK_VXD_5G_AP_NOSTA_TIMEOUT RTL_SECONDS_TO_JIFFIES(30) + +#if defined(CONFIG_RTL_SIMPLE_CONFIG) +#define CHECK_VXD_SC_GOT_TIMEOUT 1 //RTL_MILISECONDS_TO_JIFFIES(10) +#define CHECK_VXD_SC_TIMEOUT RTL_SECONDS_TO_JIFFIES(10) +#endif + +struct brsc_cache_t { + int occupy; + unsigned long timestamp; + unsigned char cached_br_sta_mac[MACADDRLEN]; + struct net_device *cached_br_sta_dev; +}; + +#endif // _8192CD_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_11h.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_11h.c new file mode 100755 index 000000000..a181357fd --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_11h.c @@ -0,0 +1,438 @@ +/* + * Software TKIP encryption/descryption routines + * + * $Id: 8192cd_tkip.c,v 1.4.4.2 2010/09/30 05:27:28 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_11H_C_ + +#ifdef __KERNEL__ +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#if !defined(__KERNEL__) && !defined(__ECOS) +#include "./sys-support.h" +#endif + +#include "./8192cd.h" +#ifdef __KERNEL__ +#include "./ieee802_mib.h" +#elif defined(__ECOS) +#include +#endif +#include "./8192cd_util.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + +#if (defined(DOT11D) || defined(DOT11H)) + +#define MAX_CHANNEL_SET_NUMBER 20 + +typedef struct _PER_CHANNEL_ENTRY_ { + unsigned char firstChannel; + unsigned char numberOfChannel; + unsigned char maxTxDbm; +} PER_CHANNEL_ENTRY; + +typedef struct _BAND_TABLE_ELEMENT_ { + unsigned char channel_set_number; + PER_CHANNEL_ENTRY channel_set[MAX_CHANNEL_SET_NUMBER]; +} BAND_TABLE_ELEMENT; + + +typedef struct _COUNTRY_IE_ELEMENT_ { + unsigned int countryNumber; + unsigned char countryA2[3]; + unsigned char A_Band_Region; //if support 5G A band? ; 0 == no support ; aBandRegion == real region domain + unsigned char G_Band_Region; //if support 2.4G G band? ; 0 == no support ; bBandRegion == real region domain +} COUNTRY_IE_ELEMENT; + + +static const COUNTRY_IE_ELEMENT countryIEArray[] = +{ + /* + format: countryNumber | CountryCode(A2) + */ + {8,"AL ", 3, 3}, /*ALBANIA*/ + {12,"DZ ", 3, 3}, /*ALGERIA*/ + {32,"AR ", 3, 3}, /*ARGENTINA*/ + {51,"AM ", 3, 3}, /*ARMENIA*/ + {36,"AU ", 3, 3}, /*AUSTRALIA*/ + {40,"AT ", 3, 3}, /*AUSTRIA*/ + {31,"AZ ", 3, 3}, /*AZERBAIJAN*/ + {48,"BH ", 3, 3}, /*BAHRAIN*/ + {112,"BY", 3, 3}, /*BELARUS*/ + {56,"BE ", 3, 3}, /*BELGIUM*/ + {84,"BZ ", 3, 3}, /*BELIZE*/ + {68,"BO ", 3, 3}, /*BOLIVIA*/ + {76,"BR ", 3, 3}, /*BRAZIL*/ + {96,"BN ", 3, 3}, /*BRUNEI*/ + {100,"BG ", 3, 3}, /*BULGARIA*/ + {124,"CA ", 1, 1}, /*CANADA*/ + {152,"CL ", 3, 3}, /*CHILE*/ + {156,"CN ",13,13}, /*CHINA*/ + {170,"CO ", 1, 1}, /*COLOMBIA*/ + {188,"CR ", 3, 3}, /*COSTA RICA*/ + {191,"HR ", 3, 3}, /*CROATIA*/ + {196,"CY ", 3, 3}, /*CYPRUS*/ + {203,"CZ ", 3, 3}, /*CZECH REPUBLIC*/ + {208,"DK ", 3, 3}, /*DENMARK*/ + {214,"DO ", 1, 1}, /*DOMINICAN REPUBLIC*/ + {218,"EC ", 3, 3}, /*ECUADOR*/ + {818,"EG ", 3, 3}, /*EGYPT*/ + {222,"SV ", 3, 3}, /*EL SALVADOR*/ + {233,"EE ", 3, 3}, /*ESTONIA*/ + {246,"FI ", 3, 3}, /*FINLAND*/ + {250,"FR ", 3, 3}, /*FRANCE*/ + {268,"GE ", 3, 3}, /*GEORGIA*/ + {276,"DE ", 3, 3}, /*GERMANY*/ + {300,"GR ", 3, 3}, /*GREECE*/ + {320,"GT ", 1, 1}, /*GUATEMALA*/ + {340,"HN ", 3, 3}, /*HONDURAS*/ + {344,"HK ", 3, 3}, /*HONG KONG*/ + {348,"HU ", 3, 3}, /*HUNGARY*/ + {352,"IS ", 3, 3}, /*ICELAND*/ + {356,"IN ", 3, 3}, /*INDIA*/ + {360,"ID ", 3, 3}, /*INDONESIA*/ + {364,"IR ", 3, 3}, /*IRAN*/ + {372,"IE ", 3, 3}, /*IRELAND*/ + {376,"IL ", 7, 7}, /*ISRAEL*/ + {380,"IT ", 3, 3}, /*ITALY*/ + {392,"JP ", 6, 6}, /*JAPAN*/ + {400,"JO ", 3, 3}, /*JORDAN*/ + {398,"KZ ", 3, 3}, /*KAZAKHSTAN*/ + {410,"KR ", 3, 3}, /*NORTH KOREA*/ + {408,"KP ", 3, 3}, /*KOREA REPUBLIC*/ + {414,"KW ", 3, 3}, /*KUWAIT*/ + {428,"LV ", 3, 3}, /*LATVIA*/ + {422,"LB ", 3, 3}, /*LEBANON*/ + {438,"LI ", 3, 3}, /*LIECHTENSTEIN*/ + {440,"LT ", 3, 3}, /*LITHUANIA*/ + {442,"LU ", 3, 3}, /*LUXEMBOURG*/ + {446,"MO ", 3, 3}, /*CHINA MACAU*/ + {807,"MK ", 3, 3}, /*MACEDONIA*/ + {458,"MY ", 3, 3}, /*MALAYSIA*/ + {484,"MX ", 1, 1}, /*MEXICO*/ + {492,"MC ", 3, 3}, /*MONACO*/ + {504,"MA ", 3, 3}, /*MOROCCO*/ + {528,"NL ", 3, 3}, /*NETHERLANDS*/ + {554,"NZ ", 3, 3}, /*NEW ZEALAND*/ + {578,"NO ", 3, 3}, /*NORWAY*/ + {512,"OM ", 3, 3}, /*OMAN*/ + {586,"PK ", 3, 3}, /*PAKISTAN*/ + {591,"PA ", 1, 1}, /*PANAMA*/ + {604,"PE ", 3, 3}, /*PERU*/ + {608,"PH ", 3, 3}, /*PHILIPPINES*/ + {616,"PL ", 3, 3}, /*POLAND*/ + {620,"PT ", 3, 3}, /*PORTUGAL*/ + {630,"PR ", 1, 1}, /*PUERTO RICO*/ + {634,"QA ", 3, 3}, /*QATAR*/ + {642,"RO ", 3, 3}, /*ROMANIA*/ + {643,"RU ",12,12}, /*RUSSIAN*/ + {682,"SA ", 3, 3}, /*SAUDI ARABIA*/ + {702,"SG ", 3, 3}, /*SINGAPORE*/ + {703,"SK ", 3, 3}, /*SLOVAKIA*/ + {705,"SI ", 3, 3}, /*SLOVENIA*/ + {710,"ZA ", 3, 3}, /*SOUTH AFRICA*/ + {724,"ES ", 3, 3}, /*SPAIN*/ + {752,"SE ", 3, 3}, /*SWEDEN*/ + {756,"CH ", 3, 3}, /*SWITZERLAND*/ + {760,"SY ", 3, 3}, /*SYRIAN ARAB REPUBLIC*/ + {158,"TW ",11,11}, /*TAIWAN*/ + {764,"TH ", 3, 3}, /*THAILAND*/ + {780,"TT ", 3, 3}, /*TRINIDAD AND TOBAGO*/ + {788,"TN ", 3, 3}, /*TUNISIA*/ + {792,"TR ", 3, 3}, /*TURKEY*/ + {804,"UA ", 3, 3}, /*UKRAINE*/ + {784,"AE ", 3, 3}, /*UNITED ARAB EMIRATES*/ + {826,"GB ", 3, 3}, /*UNITED KINGDOM*/ + {840,"US ", 1, 1}, /*UNITED STATES*/ + {858,"UY ", 3, 3}, /*URUGUAY*/ + {860,"UZ ", 1, 1}, /*UZBEKISTAN*/ + {862,"VE ", 3, 3}, /*VENEZUELA*/ + {704,"VN ", 3, 3}, /*VIET NAM*/ + {887,"YE ", 3, 3}, /*YEMEN*/ + {716,"ZW ", 3, 3}, /*ZIMBABWE*/ +}; + + +static const BAND_TABLE_ELEMENT country_ie_channel_2_4g[] = { + /* number of channel set | array of channel sets{first channel, num of channel, tx power} + transmit tx power is copy from CAMEO + */ + + /* (1) FCC */ {1, {{1, 11, 30}}}, + /* (2) IC */ {1, {{1, 11, 30}}}, + /* (3) ETSI */ {1, {{1, 13, 30}}}, + /* (4) SPAIN */ {1, {{1, 13, 30}}}, + /* (5) FRANCE */ {1, {{10, 4, 30}}}, + /* (6) MKK */ {1, {{1, 14, 30}}}, + /* (7) ISRAEL */ {1, {{3, 11, 30}}}, + /* (8) MKK1 */ {1, {{1, 14, 30}}}, + /* (9) MKK2 */ {1, {{1, 14, 30}}}, + /* (10) MKK3 */ {1, {{1, 14, 30}}}, + /* (11) NCC (Taiwan) */ {1, {{1, 11, 30}}}, + /* (12) RUSSIAN */ {1, {{1, 13, 30}}}, + /* (13) CN */ {1, {{1, 13, 30}}}, + /* (14) Global */ {1, {{1, 14, 30}}}, + /* (15) World_wide */ {1, {{1, 13, 30}}}, + /* (16) Test */ {1, {{1, 14, 30}}}, +}; + +static const BAND_TABLE_ELEMENT country_ie_channel_5g[] = { + /* number of channel set | array of channel sets {first channel, num of channel, tx power}, + transmit tx power is copy from CAMEO + */ + + /*(1) FCC */ {20, {{36,1,30}, {40,1,30}, {44,1,30}, {48,1,30}, + {52,1,30}, {56,1,30}, {60,1,30}, {64,1,30}, + {100,1,20},{104,1,20},{108,1,20},{112,1,20},{116,1,20},{136,1,20},{140,1,20}, + {149,1,30},{153,1,30},{157,1,30},{161,1,30},{165,1,30} } + }, + /* (2) IC */ {12, {{36,1,30}, {40,1,30}, {44,1,30}, {48,1,30}, + {52,1,30}, {56,1,30}, {60,1,30}, {64,1,30}, + {149,1,30},{153,1,30},{157,1,30},{161,1,30} } + }, + /* (3) ETSI */ {19, {{36,1,30}, {40,1,30}, {44,1,30}, {48,1,30}, + {52,1,30}, {56,1,30}, {60,1,30}, {64,1,30}, + {100,1,20},{104,1,20},{108,1,20},{112,1,20},{116,1,20},{120,1,20},{124,1,20},{128,1,20},{132,1,20},{136,1,20},{140,1,20} } + }, + /* (4) SPAIN */ {3, {{36,4,30}, //36, 40, 44, 48 + {52,4,30}, //52, 56, 60, 64 + {100,11,20} } //100, 104, 108, 112, 116,120,124,128,132,136,140 + }, + /* (5) FRANCE */ {3, {{36,4,30}, //36, 40, 44, 48 + {52,4,30}, //52, 56, 60, 64 + {100,11,20} } //100, 104, 108, 112, 116,120,124,128,132,136,140 + }, + /* (6) MKK */ {19, {{36,1,30}, {40,1,30}, {44,1,30}, {48,1,30}, + {52,1,30}, {56,1,30}, {60,1,30}, {64,1,30}, + {100,1,20},{104,1,20},{108,1,20},{112,1,20},{116,1,20},{120,1,20},{124,1,20},{128,1,20},{132,1,20},{136,1,20},{140,1,20} } + }, + /* (7) ISRAEL */ {19, {{36,1,30}, {40,1,30}, {44,1,30}, {48,1,30}, + {52,1,30}, {56,1,30}, {60,1,30}, {64,1,30}, + {100,1,30},{104,1,30},{108,1,30},{112,1,30},{116,1,30},{120,1,30},{124,1,30},{128,1,30},{132,1,30},{136,1,30},{140,1,30} } + }, + /* (8) MKK1 */ {1, {{34,4,30} } // 34, 38, 42, 46 + }, + /* (9) MKK2 */ {1, {{36,4,30} } //36, 40, 44, 48 + }, + /* (10) MKK3 */ {2, {{36,4,30}, //36, 40, 44, 48 + {52,4,30} } //52, 56, 60, 64 + }, + /* (11) NCC (Taiwan) */ + {15, {{56,1,30}, {60,1,30}, {64,1,30}, + {100,1,20},{104,1,20},{108,1,20},{112,1,20},{116,1,20},{136,1,20},{140,1,20}, + {149,1,30},{153,1,30},{157,1,30},{161,1,30},{165,1,30} } + }, + /* (12) RUSSIAN */{16, {{36,1,20}, {40,1,20}, {44,1,20}, {48,1,20}, + {52,1,20}, {56,1,20}, {60,1,20}, {64,1,20}, + {132,1,30},{136,1,30},{140,1,30}, + {149,1,30},{153,1,30},{157,1,30},{161,1,30},{165,1,30}} + }, + /* (13) CN */ {13, {{36,1,30}, {40,1,30}, {44,1,30}, {48,1,30}, + {52,1,30}, {56,1,30}, {60,1,30}, {64,1,30}, + {149,1,30},{153,1,30},{157,1,30},{161,1,30},{165,1,30} } + }, + /* (14) Global */ {20, {{36,1,30}, {40,1,30}, {44,1,30}, {48,1,30}, + {52,1,30}, {56,1,30}, {60,1,30}, {64,1,30}, + {100,1,30},{104,1,30},{108,1,30},{112,1,30},{116,1,30},{136,1,30},{140,1,30}, + {149,1,30},{153,1,30},{157,1,30},{161,1,30},{165,1,30} } + }, + /* (15) World_wide */ + {20, {{36,1,30}, {40,1,30}, {44,1,30}, {48,1,30}, + {52,1,30}, {56,1,30}, {60,1,30}, {64,1,30}, + {100,1,30},{104,1,30},{108,1,30},{112,1,30},{116,1,30},{136,1,30},{140,1,30}, + {149,1,30},{153,1,30},{157,1,30},{161,1,30},{165,1,30} } + }, + /* (16) Test */ {4, {{36,4,30}, //36, 40, 44, 48 + {52,4,30}, //52, 56, 60, 64 + {100,12,30}, //100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144 + {149,8,30} } //149, 153, 157, 161, 165, 169, 173, 177 + }, + /* (17) 5M10M */ {1, {{146,25,30} } // 146 ~ 170 + }, +}; + +void check_country_channel_table(struct rtl8192cd_priv *priv) { + + unsigned char i = 0, country_num; + priv->countryTableIdx = 0; + if(COUNTRY_CODE_ENABLED || priv->pmib->dot11hTPCEntry.tpc_enable) + { + country_num = sizeof(countryIEArray)/sizeof(COUNTRY_IE_ELEMENT); + for (i=0; ipmib->dot11dCountry.dot11CountryString, countryIEArray[i].countryA2, 2)) { + priv->countryTableIdx = i + 1; + break; + } + } + + if (priv->countryTableIdx == 0) { + printk("can't found country code(%s)\n", priv->pmib->dot11dCountry.dot11CountryString); + } + } +} + +unsigned char * construct_country_ie(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen) { + const COUNTRY_IE_ELEMENT * country_ie; + const BAND_TABLE_ELEMENT * band_table = NULL; + unsigned char temp[MAX_CHANNEL_SET_NUMBER*3 + 3 + 1];/*channel sets + country code + 1 possible padding*/ + unsigned int len = 0; + country_ie = &(countryIEArray[priv->countryTableIdx-1]); + if ( priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) { + if(country_ie->G_Band_Region) { + band_table = &(country_ie_channel_2_4g[country_ie->G_Band_Region-1]); + } + } + else { + if(country_ie->A_Band_Region) { + band_table = &(country_ie_channel_5g[country_ie->A_Band_Region-1]); + } + } + + if(band_table) { + memcpy(temp + len, country_ie->countryA2, 3); + len += 3; + + memcpy(temp + len, (unsigned char *)band_table->channel_set, band_table->channel_set_number*3); + len += band_table->channel_set_number*3; + + /*add padding, the length of country ie must divided by two*/ + if(len%2) { + temp[len] = 0; + len++; + } + + pbuf = set_ie(pbuf, _COUNTRY_IE_, len, temp, frlen); + } + return pbuf; +} + + +#endif + + + +#ifdef DOT11H +#if defined(CLIENT_MODE) || defined(CONFIG_RTK_MESH) +unsigned char * construct_power_capability_ie(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen) { + unsigned char temp[2]; + temp[0] = priv->pmib->dot11hTPCEntry.min_tx_power; + temp[1] = priv->pmib->dot11hTPCEntry.max_tx_power; + pbuf = set_ie(pbuf, _PWR_CAPABILITY_IE_, 2, temp, frlen); + return pbuf; +} + +unsigned char * construct_supported_channel_ie(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen) { + const COUNTRY_IE_ELEMENT * country_ie; + const BAND_TABLE_ELEMENT * band_table = NULL; + unsigned char temp[MAX_CHANNEL_SET_NUMBER*2];/*channel sets*/ + unsigned int i,j = 0; + if(priv->countryTableIdx) { + country_ie = &(countryIEArray[priv->countryTableIdx-1]); + if ( priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) { + if(country_ie->G_Band_Region) { + band_table = &(country_ie_channel_2_4g[country_ie->G_Band_Region-1]); + } + } + else { + if(country_ie->A_Band_Region) { + band_table = &(country_ie_channel_5g[country_ie->A_Band_Region-1]); + } + } + if(band_table) { + for(i = 0; i < band_table->channel_set_number; i++) { + temp[j++] = band_table->channel_set[i].firstChannel; + temp[j++] = band_table->channel_set[i].numberOfChannel; + } + pbuf = set_ie(pbuf, _SUPPORTED_CHANNEL_IE_, j, temp, frlen); + } + } + return pbuf; +} + +#endif + +unsigned char * construct_TPC_report_ie(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen) { + unsigned char temp[2]; + temp[0] = priv->pmib->dot11hTPCEntry.tpc_tx_power; + temp[1] = priv->pmib->dot11hTPCEntry.tpc_link_margin; + pbuf = set_ie(pbuf, _TPC_REPORT_IE_, 2, temp, frlen); + return pbuf; +} + + +void issue_TPC_report(struct rtl8192cd_priv *priv, unsigned char *da, unsigned char dialog_token) { + unsigned char *pbuf; + unsigned int frlen; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_TPC_report_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_TPC_report_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _SPECTRUM_MANAGEMENT_CATEGORY_ID_; + pbuf[1] = _TPC_REPORT_ACTION_ID_; + pbuf[2] = dialog_token; + frlen = 3; + + construct_TPC_report_ie(priv, pbuf + frlen, &frlen); + + txinsn.fr_len += frlen; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +issue_TPC_report_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return; + +} + + +#endif + + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_a4_sta.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_a4_sta.c new file mode 100755 index 000000000..f1d3f036c --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_a4_sta.c @@ -0,0 +1,242 @@ +/* + * a4 sta functions + * + * $Id: 8192cd_a4_sta.c,v 1.1 2010/10/13 06:38:58 davidhsu Exp $ + * + * Copyright (c) 2010 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_A4_STA_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#ifdef A4_STA + +#include "./8192cd.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + + +//#define A4_STA_DEBUG + +static struct a4_sta_db_entry *alloc_entry(struct rtl8192cd_priv *priv) +{ + int i; + + for (i=0; ia4_ent[i].used) { + priv->a4_ent[i].used = 1; + return &priv->a4_ent[i].entry; + } + } + return NULL; +} + +static void free_entry(struct rtl8192cd_priv *priv, struct a4_sta_db_entry *entry) +{ + int i; + + for (i=0; ia4_ent[i].used && (entry == &priv->a4_ent[i].entry)) { + priv->a4_ent[i].used = 0; + break; + } + } +} + +static int mac_hash(unsigned char *networkAddr) +{ + unsigned long x; + + x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5]; + + return x & (A4_STA_HASH_SIZE - 1); +} + +static void mac_hash_link(struct rtl8192cd_priv *priv, struct a4_sta_db_entry *ent, int hash) +{ + ent->next_hash = priv->machash[hash]; + + if (ent->next_hash != NULL) + ent->next_hash->pprev_hash = &ent->next_hash; + priv->machash[hash] = ent; + ent->pprev_hash = &priv->machash[hash]; +} + +static void mac_hash_unlink(struct a4_sta_db_entry *ent) +{ + *(ent->pprev_hash) = ent->next_hash; + if (ent->next_hash != NULL) + ent->next_hash->pprev_hash = ent->pprev_hash; + ent->next_hash = NULL; + ent->pprev_hash = NULL; +} + +static unsigned long _timeout(struct rtl8192cd_priv *priv) +{ + unsigned long timeout; + + timeout = jiffies - A4_STA_AGEING_TIME*HZ; + return timeout; +} + +static int has_expired(struct rtl8192cd_priv *priv, struct a4_sta_db_entry *fdb) +{ + if (time_before_eq(fdb->ageing_timer, _timeout(priv))) + return 1; + + return 0; +} + +void a4_sta_cleanup(struct rtl8192cd_priv *priv) +{ + int i; + + if (priv->pshare->rf_ft_var.a4_enable) { + for (i=0; imachash[i]; + + while (f != NULL) { + struct a4_sta_db_entry *g; + + g = f->next_hash; + mac_hash_unlink(f); + free_entry(priv, f); + f = g; + } + } + } +} + +void a4_sta_expire(struct rtl8192cd_priv *priv) +{ + int i; + + if (priv->pshare->rf_ft_var.a4_enable) { + for (i=0; imachash[i]; + + while (f != NULL) { + struct a4_sta_db_entry *g; + g = f->next_hash; + + if (has_expired(priv, f)) { +#ifdef A4_STA_DEBUG + panic_printk("A4 STA Expire (%02d) emac:%02x%02x%02x%02x%02x%02x, wmac:%02x%02x%02x%02x%02x%02x\n", + i, + f->mac[0], + f->mac[1], + f->mac[2], + f->mac[3], + f->mac[4], + f->mac[5], + f->stat->hwaddr[0], + f->stat->hwaddr[1], + f->stat->hwaddr[2], + f->stat->hwaddr[3], + f->stat->hwaddr[4], + f->stat->hwaddr[5]); +#endif + mac_hash_unlink(f); + free_entry(priv, f); + } + f = g; + } + } + } +} + +void a4_sta_add(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char *mac) +{ + struct a4_sta_db_entry *db; + int hash; + + ASSERT(mac); + + hash = mac_hash(mac); + db = priv->machash[hash]; + + while (db != NULL) { + if (!memcmp(db->mac, mac, ETH_ALEN)) { + db->stat = pstat; + db->ageing_timer = jiffies; + return; + } + db = db->next_hash; + } + + db = alloc_entry(priv); + if (db == NULL) { + DEBUG_ERR("alloc_entry() failed for a4_sta_db_entry!\n"); + return; + } + memcpy(db->mac, mac, ETH_ALEN); + db->stat = pstat; + db->ageing_timer = jiffies; + +#ifdef A4_STA_DEBUG + panic_printk("A4 STA Add emac:%02x%02x%02x%02x%02x%02x, wmac:%02x%02x%02x%02x%02x%02x\n", + db->mac[0], + db->mac[1], + db->mac[2], + db->mac[3], + db->mac[4], + db->mac[5], + db->stat->hwaddr[0], + db->stat->hwaddr[1], + db->stat->hwaddr[2], + db->stat->hwaddr[3], + db->stat->hwaddr[4], + db->stat->hwaddr[5]); +#endif + + mac_hash_link(priv, db, hash); +} + +struct stat_info *a4_sta_lookup(struct rtl8192cd_priv *priv, unsigned char *mac) +{ + struct a4_sta_db_entry *db; + + ASSERT(mac); + + db = priv->machash[mac_hash(mac)]; + + while (db != NULL) { + if (!memcmp(db->mac, mac, ETH_ALEN)) { + +#ifdef A4_STA_DEBUG + panic_printk("A4 STA LOOKUP emac:%02x%02x%02x%02x%02x%02x, wmac:%02x%02x%02x%02x%02x%02x\n", + db->mac[0], + db->mac[1], + db->mac[2], + db->mac[3], + db->mac[4], + db->mac[5], + db->stat->hwaddr[0], + db->stat->hwaddr[1], + db->stat->hwaddr[2], + db->stat->hwaddr[3], + db->stat->hwaddr[4], + db->stat->hwaddr[5]); +#endif + return db->stat; + } + + db = db->next_hash; + } + return NULL; +} + +#endif /* A4_STA */ diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_aes.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_aes.c new file mode 100755 index 000000000..450163ba4 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_aes.c @@ -0,0 +1,1495 @@ +/* + * Software AES encryption/descryption routines + * + * $Id: 8192cd_aes.c,v 1.1.4.2 2010/11/29 12:23:52 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_AES_C_ + +#ifdef __KERNEL__ +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#if !defined(__KERNEL__) && !defined(__ECOS) +#include "./sys-support.h" +#endif + +#include "./8192cd.h" +#ifdef __KERNEL__ +#include "./ieee802_mib.h" +#elif defined(__ECOS) +#include +#endif +#include "./8192cd_util.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + +#define SHOW_INIT_BLOCKS +#define SHOW_HEADER_FIELDS +#define SHOW_CTR_PRELOAD + +#define MAX_MSG_SIZE 2048 +/*****************************/ +/******** SBOX Table *********/ +/*****************************/ + + unsigned char sbox_table[256] = + { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 + }; + +/*****************************/ +/**** Function Prototypes ****/ +/*****************************/ + +void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out); +void construct_mic_iv( + unsigned char *mic_header1, + int qc_exists, + int a4_exists, + unsigned char *mpdu, + unsigned int payload_length, + unsigned char * pn_vector +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ); +void construct_mic_header1( + unsigned char *mic_header1, + int header_length, + unsigned char *mpdu +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ); +void construct_mic_header2( + unsigned char *mic_header2, + unsigned char *mpdu, + int a4_exists, + int qc_exists); +void construct_ctr_preload( + unsigned char *ctr_preload, + int a4_exists, + int qc_exists, + unsigned char *mpdu, + unsigned char *pn_vector, + int c +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ); +void xor_128(unsigned char *a, unsigned char *b, unsigned char *out); +void xor_32(unsigned char *a, unsigned char *b, unsigned char *out); +unsigned char sbox(unsigned char a); +void next_key(unsigned char *key, int round); +void byte_sub(unsigned char *in, unsigned char *out); +void shift_row(unsigned char *in, unsigned char *out); +void mix_column(unsigned char *in, unsigned char *out); +void add_round_key( unsigned char *shiftrow_in, + unsigned char *mcol_in, + unsigned char *block_in, + int round, + unsigned char *out); +void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext); + + +/****************************************/ +/* aes128k128d() */ +/* Performs a 128 bit AES encrypt with */ +/* 128 bit data. */ +/****************************************/ +void xor_128(unsigned char *a, unsigned char *b, unsigned char *out) +{ + int i; + for (i=0;i<16; i++) + { + out[i] = a[i] ^ b[i]; + } +} + + +void xor_32(unsigned char *a, unsigned char *b, unsigned char *out) +{ + int i; + for (i=0;i<4; i++) + { + out[i] = a[i] ^ b[i]; + } +} + + +unsigned char sbox(unsigned char a) +{ + return sbox_table[(int)a]; +} + + +void next_key(unsigned char *key, int round) +{ + unsigned char rcon; + unsigned char sbox_key[4]; + unsigned char rcon_table[12] = + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x36, 0x36 + }; + + sbox_key[0] = sbox(key[13]); + sbox_key[1] = sbox(key[14]); + sbox_key[2] = sbox(key[15]); + sbox_key[3] = sbox(key[12]); + + rcon = rcon_table[round]; + + xor_32(&key[0], sbox_key, &key[0]); + key[0] = key[0] ^ rcon; + + xor_32(&key[4], &key[0], &key[4]); + xor_32(&key[8], &key[4], &key[8]); + xor_32(&key[12], &key[8], &key[12]); +} + + +void byte_sub(unsigned char *in, unsigned char *out) +{ + int i; + for (i=0; i< 16; i++) + { + out[i] = sbox(in[i]); + } +} + + +void shift_row(unsigned char *in, unsigned char *out) +{ + out[0] = in[0]; + out[1] = in[5]; + out[2] = in[10]; + out[3] = in[15]; + out[4] = in[4]; + out[5] = in[9]; + out[6] = in[14]; + out[7] = in[3]; + out[8] = in[8]; + out[9] = in[13]; + out[10] = in[2]; + out[11] = in[7]; + out[12] = in[12]; + out[13] = in[1]; + out[14] = in[6]; + out[15] = in[11]; +} + + +void mix_column(unsigned char *in, unsigned char *out) +{ + int i; + unsigned char add1b[4]; + unsigned char add1bf7[4]; + unsigned char rotl[4]; + unsigned char swap_halfs[4]; + unsigned char andf7[4]; + unsigned char rotr[4]; + unsigned char temp[4]; + unsigned char tempb[4]; + + for (i=0 ; i<4; i++) + { + if ((in[i] & 0x80)== 0x80) + add1b[i] = 0x1b; + else + add1b[i] = 0x00; + } + + swap_halfs[0] = in[2]; /* Swap halfs */ + swap_halfs[1] = in[3]; + swap_halfs[2] = in[0]; + swap_halfs[3] = in[1]; + + rotl[0] = in[3]; /* Rotate left 8 bits */ + rotl[1] = in[0]; + rotl[2] = in[1]; + rotl[3] = in[2]; + + andf7[0] = in[0] & 0x7f; + andf7[1] = in[1] & 0x7f; + andf7[2] = in[2] & 0x7f; + andf7[3] = in[3] & 0x7f; + + for (i = 3; i>0; i--) /* logical shift left 1 bit */ + { + andf7[i] = andf7[i] << 1; + if ((andf7[i-1] & 0x80) == 0x80) + { + andf7[i] = (andf7[i] | 0x01); + } + } + andf7[0] = andf7[0] << 1; + andf7[0] = andf7[0] & 0xfe; + + xor_32(add1b, andf7, add1bf7); + + xor_32(in, add1bf7, rotr); + + temp[0] = rotr[0]; /* Rotate right 8 bits */ + rotr[0] = rotr[1]; + rotr[1] = rotr[2]; + rotr[2] = rotr[3]; + rotr[3] = temp[0]; + + xor_32(add1bf7, rotr, temp); + xor_32(swap_halfs, rotl,tempb); + xor_32(temp, tempb, out); +} + + +void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext) +{ + int round; + int i; + unsigned char intermediatea[16]; + unsigned char intermediateb[16]; + unsigned char round_key[16]; + + for(i=0; i<16; i++) round_key[i] = key[i]; + + for (round = 0; round < 11; round++) + { + if (round == 0) + { + xor_128(round_key, data, ciphertext); + next_key(round_key, round); + } + else if (round == 10) + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + xor_128(intermediateb, round_key, ciphertext); + } + else /* 1 - 9 */ + { + byte_sub(ciphertext, intermediatea); + shift_row(intermediatea, intermediateb); + mix_column(&intermediateb[0], &intermediatea[0]); + mix_column(&intermediateb[4], &intermediatea[4]); + mix_column(&intermediateb[8], &intermediatea[8]); + mix_column(&intermediateb[12], &intermediatea[12]); + xor_128(intermediatea, round_key, ciphertext); + next_key(round_key, round); + } + } + +} + +#ifdef CONFIG_IEEE80211W +extern void AES_Encrypt(const unsigned long *in_blk, unsigned long *out_blk); +extern unsigned long *AES_SetKey(const unsigned long *in_key, const unsigned long key_len); +#define AES_BLOCK_SIZE 16 +static void gf_mulx(unsigned char *pad) +{ + int i, carry; + + carry = pad[0] & 0x80; + for (i = 0; i < AES_BLOCK_SIZE - 1; i++) + pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); + pad[AES_BLOCK_SIZE - 1] <<= 1; + if (carry) + pad[AES_BLOCK_SIZE - 1] ^= 0x87; +} + +/** + * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 + * @key: 128-bit key for the hash operation + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_128_vector(const unsigned char *key, int num_elem, + const unsigned char *addr[], const int *len, unsigned char *mac) +{ + void *ctx; + unsigned char cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; + const unsigned char *pos, *end; + int i, e, left, total_len; + + ctx = AES_SetKey(key, 128); + if (ctx == NULL) + return -1; + memset(cbc, 0, AES_BLOCK_SIZE); + + total_len = 0; + for (e = 0; e < num_elem; e++) + total_len += len[e]; + left = total_len; + + + e = 0; + pos = addr[0]; + end = pos + len[0]; + + while (left >= AES_BLOCK_SIZE) { + for (i = 0; i < AES_BLOCK_SIZE; i++) { + cbc[i] ^= *pos++; + if (pos >= end) { + e++; + pos = addr[e]; + end = pos + len[e]; + } + } + if (left > AES_BLOCK_SIZE) + AES_Encrypt(cbc, cbc); + left -= AES_BLOCK_SIZE; + } + + memset(pad, 0, AES_BLOCK_SIZE); + + AES_Encrypt(pad, pad); + gf_mulx(pad); + + if (left || total_len == 0) { + for (i = 0; i < left; i++) { + cbc[i] ^= *pos++; + if (pos >= end) { + e++; + pos = addr[e]; + end = pos + len[e]; + } + } + cbc[left] ^= 0x80; + gf_mulx(pad); + } + + for (i = 0; i < AES_BLOCK_SIZE; i++) + pad[i] ^= cbc[i]; + AES_Encrypt(pad, mac); + + return 0; +} + + +/** + * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) + * @key: 128-bit key for the hash operation + * @data: Data buffer for which a MAC is determined + * @data_len: Length of data buffer in bytes + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_128(const unsigned char *key, const unsigned char *data, int data_len, unsigned char *mac) +{ + return omac1_aes_128_vector(key, 1, &data, &data_len, mac); +} +#endif + +/************************************************/ +/* construct_mic_iv() */ +/* Builds the MIC IV from header fields and PN */ +/************************************************/ +void construct_mic_iv( + unsigned char *mic_iv, + int qc_exists, + int a4_exists, + unsigned char *mpdu, + unsigned int payload_length, + unsigned char *pn_vector +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ) +{ + int i; + + mic_iv[0] = 0x59; + if (qc_exists && a4_exists) mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ + if (qc_exists && !a4_exists) mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ + if (!qc_exists) mic_iv[1] = 0x00; + +#ifdef CONFIG_IEEE80211W + if (isMgmt) mic_iv[1] |= BIT(4); // Management fields of Nonce. Figure 11-20 in IEEE 802.11-2012 +#endif + + for (i = 2; i < 8; i++) + mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ +#ifdef CONSISTENT_PN_ORDER + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */ +#else + for (i = 8; i < 14; i++) + mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ +#endif + mic_iv[14] = (unsigned char) (payload_length / 256); + mic_iv[15] = (unsigned char) (payload_length % 256); +} + + +/************************************************/ +/* construct_mic_header1() */ +/* Builds the first MIC header block from */ +/* header fields. */ +/************************************************/ +void construct_mic_header1( + unsigned char *mic_header1, + int header_length, + unsigned char *mpdu +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ) +{ + mic_header1[0] = (unsigned char)((header_length - 2) / 256); + mic_header1[1] = (unsigned char)((header_length - 2) % 256); + +#ifdef CONFIG_IEEE80211W + if (isMgmt) + mic_header1[2] = mpdu[0]; + else +#endif + mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ + mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ + mic_header1[4] = mpdu[4]; /* A1 */ + mic_header1[5] = mpdu[5]; + mic_header1[6] = mpdu[6]; + mic_header1[7] = mpdu[7]; + mic_header1[8] = mpdu[8]; + mic_header1[9] = mpdu[9]; + mic_header1[10] = mpdu[10]; /* A2 */ + mic_header1[11] = mpdu[11]; + mic_header1[12] = mpdu[12]; + mic_header1[13] = mpdu[13]; + mic_header1[14] = mpdu[14]; + mic_header1[15] = mpdu[15]; +} + + +/************************************************/ +/* construct_mic_header2() */ +/* Builds the last MIC header block from */ +/* header fields. */ +/************************************************/ +void construct_mic_header2( + unsigned char *mic_header2, + unsigned char *mpdu, + int a4_exists, + int qc_exists + ) +{ + int i; + + for (i = 0; i<16; i++) mic_header2[i]=0x00; + + mic_header2[0] = mpdu[16]; /* A3 */ + mic_header2[1] = mpdu[17]; + mic_header2[2] = mpdu[18]; + mic_header2[3] = mpdu[19]; + mic_header2[4] = mpdu[20]; + mic_header2[5] = mpdu[21]; + + //mic_header2[6] = mpdu[22] & 0xf0; /* SC */ + mic_header2[6] = 0x00; + mic_header2[7] = 0x00; /* mpdu[23]; */ + + + if (!qc_exists && a4_exists) + { + for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + + } + + if (qc_exists && !a4_exists) + { + mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ + mic_header2[9] = mpdu[25] & 0x00; + } + + if (qc_exists && a4_exists) + { + for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */ + + mic_header2[14] = mpdu[30] & 0x0f; + mic_header2[15] = mpdu[31] & 0x00; + } + + +} + + +/************************************************/ +/* construct_mic_header2() */ +/* Builds the last MIC header block from */ +/* header fields. */ +/************************************************/ +void construct_ctr_preload( + unsigned char *ctr_preload, + int a4_exists, + int qc_exists, + unsigned char *mpdu, + unsigned char *pn_vector, + int c +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ) +{ + int i = 0; + for (i=0; i<16; i++) ctr_preload[i] = 0x00; + i = 0; + + ctr_preload[0] = 0x01; /* flag */ + if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ + if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f; + +#ifdef CONFIG_IEEE80211W + if (isMgmt) ctr_preload[1] |= BIT(4); +#endif + + for (i = 2; i < 8; i++) + ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ +#ifdef CONSISTENT_PN_ORDER + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */ +#else + for (i = 8; i < 14; i++) + ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ +#endif + ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */ + ctr_preload[15] = (unsigned char) (c % 256); +} + + +/************************************/ +/* bitwise_xor() */ +/* A 128 bit, bitwise exclusive or */ +/************************************/ +void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out) +{ + int i; + for (i=0; i<16; i++) + { + out[i] = ina[i] ^ inb[i]; + } +} + + +/*----------------------------------------------------------------------------- +hdr: wlanhdr +llc: llc_snap +pframe: raw data payload +plen: length of raw data payload +mic: mic of AES +------------------------------------------------------------------------------*/ +static void aes_tx(struct rtl8192cd_priv *priv, UINT8 *key, UINT8 keyid, + union PN48 *pn48, UINT8 *hdr, UINT8 *llc, + UINT8 *pframe, UINT32 plen, UINT8* txmic +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt + ,unsigned char checkmic +#endif + ) +{ + static UINT8 message[MAX_MSG_SIZE]; + UINT32 qc_exists, a4_exists, i, j, payload_remainder, + num_blocks,payload_length, payload_index; + + UINT8 pn_vector[6]; + UINT8 mic_iv[16]; + UINT8 mic_header1[16]; + UINT8 mic_header2[16]; + UINT8 ctr_preload[16]; + + /* Intermediate Buffers */ + UINT8 chain_buffer[16]; + UINT8 aes_out[16]; + UINT8 padded_buffer[16]; + UINT8 mic[8]; + + UINT32 offset = 0; + UINT32 hdrlen = get_hdrlen(priv, hdr); + + memset((void *)mic_iv, 0, 16); + memset((void *)mic_header1, 0, 16); + memset((void *)mic_header2, 0, 16); + memset((void *)ctr_preload, 0, 16); + memset((void *)chain_buffer, 0, 16); + memset((void *)aes_out, 0, 16); + memset((void *)padded_buffer, 0, 16); + + if (get_tofr_ds(hdr) != 0x03) + a4_exists = 0; + else + a4_exists = 1; + + if (is_qos_data(hdr)) { + qc_exists = 1; + //hdrlen += 2; // these 2 bytes has already added + } + else + qc_exists = 0; + + // below is to collecting each frag(hdr, llc, pay, and mic into single message buf) + + // extiv (8 bytes long) should have been appended + pn_vector[0] = hdr[hdrlen] = pn48->_byte_.TSC0; + pn_vector[1] = hdr[hdrlen+1] = pn48->_byte_.TSC1; + hdr[hdrlen+2] = 0x00; + hdr[hdrlen+3] = (0x20 | (keyid << 6)); + pn_vector[2] = hdr[hdrlen+4] = pn48->_byte_.TSC2; + pn_vector[3] = hdr[hdrlen+5] = pn48->_byte_.TSC3; + pn_vector[4] = hdr[hdrlen+6] = pn48->_byte_.TSC4; + pn_vector[5] = hdr[hdrlen+7] = pn48->_byte_.TSC5; + + memcpy((void *)message, hdr, (hdrlen + 8)); //8 is for ext iv len + offset = (hdrlen + 8); +#ifdef CONFIG_IEEE80211W + if (isMgmt) + llc = 0; +#endif + + if (llc) + { + memcpy((void *)(message + offset), (void *)llc, 8); + offset += 8; + } + memcpy((void *)(message + offset), (void *)pframe, plen); + offset += plen; + + // now we have collecting all the bytes into single message buf + + payload_length = plen; // 8 is for llc + + if (llc) + payload_length += 8; + + construct_mic_iv( + mic_iv, + qc_exists, + a4_exists, + message, + (payload_length), + pn_vector +#ifdef CONFIG_IEEE80211W + ,isMgmt +#endif + ); + + construct_mic_header1( + mic_header1, + hdrlen, + message +#ifdef CONFIG_IEEE80211W + ,isMgmt +#endif + ); + construct_mic_header2( + mic_header2, + message, + a4_exists, + qc_exists + ); + + + payload_remainder = (payload_length) % 16; + num_blocks = (payload_length) / 16; + + /* Find start of payload */ + payload_index = (hdrlen + 8); + + /* Calculate MIC */ + aes128k128d(key, mic_iv, aes_out); + bitwise_xor(aes_out, mic_header1, chain_buffer); + aes128k128d(key, chain_buffer, aes_out); + bitwise_xor(aes_out, mic_header2, chain_buffer); + aes128k128d(key, chain_buffer, aes_out); + + for (i = 0; i < num_blocks; i++) + { + bitwise_xor(aes_out, &message[payload_index], chain_buffer); + + payload_index += 16; + aes128k128d(key, chain_buffer, aes_out); + } + + /* Add on the final payload block if it needs padding */ + if (payload_remainder > 0) + { + for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; + for (j = 0; j < payload_remainder; j++) + { + padded_buffer[j] = message[payload_index++]; + } + bitwise_xor(aes_out, padded_buffer, chain_buffer); + aes128k128d(key, chain_buffer, aes_out); + + } + + for (j = 0 ; j < 8; j++) mic[j] = aes_out[j]; + + /* Insert MIC into payload */ + for (j = 0; j < 8; j++) + message[payload_index+j] = mic[j]; + + payload_index = hdrlen + 8; + for (i=0; i< num_blocks; i++) + { + construct_ctr_preload( + ctr_preload, + a4_exists, + qc_exists, + message, + pn_vector, + i+1 +#ifdef CONFIG_IEEE80211W + ,isMgmt +#endif + ); + aes128k128d(key, ctr_preload, aes_out); + bitwise_xor(aes_out, &message[payload_index], chain_buffer); + for (j=0; j<16;j++) message[payload_index++] = chain_buffer[j]; + } + + if (payload_remainder > 0) /* If there is a short final block, then pad it,*/ + { /* encrypt it and copy the unpadded part back */ + construct_ctr_preload( + ctr_preload, + a4_exists, + qc_exists, + message, + pn_vector, + num_blocks+1 +#ifdef CONFIG_IEEE80211W + ,isMgmt +#endif + ); + + for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; + for (j = 0; j < payload_remainder; j++) + { + padded_buffer[j] = message[payload_index+j]; + } + aes128k128d(key, ctr_preload, aes_out); + bitwise_xor(aes_out, padded_buffer, chain_buffer); + for (j=0; jval48 == 0xffffffffffffULL) + pn48->val48 = 0; + else + pn48->val48++; +} + +#ifdef CONFIG_IEEE80211W +void BIP_encrypt(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, + unsigned char *frag1, + unsigned char *frag2, unsigned int frag2_len, + unsigned char *frag3, + unsigned char isMgmt) +{ +#ifdef CONFIG_IEEE80211W_BIPTEST + unsigned char BIP_data[40]={0xc0,0x00,0xff,0xff,0xff,0xff,0xff,0xff, + 0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00, + 0x00,0x00,0x00,0x00,0x02,0x00,0x4c,0x10, + 0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + + // Test Data + + unsigned char IGTK[16]={0x4e,0xa9,0x54,0x3e,0x09,0xcf,0x2b,0x1e,0xca,0x66,0xff,0xc5,0x8b,0xde,0xcb,0xcf}; + unsigned char Addr[6]={0x02,0x00,0x00,0x00,0x00,0x00}; +#else +unsigned char *BIP_data; +#endif + unsigned char IMIC[16]; + + int i; + union PN48 *pn48; + union PN48 BIPPN; + + unsigned char *da; + unsigned char *ttkey = NULL; + unsigned int keyid = 0; + struct stat_info *pstat = NULL; + UINT32 hdrlen = get_hdrlen(priv, pwlhdr); + + unsigned char *pn; + unsigned int offset; + unsigned char pn_vector[6]; + + printk("frag2_len=%d\n",frag2_len); + frag2_len -= 10; // payload length = frag2_len - 10, MMIE Length = 10 + ttkey = GET_IGROUP_ENCRYP_KEY; + PMFDEBUG("IGTK="); + for (i=0;i<16;i++) + PMFDEBUG("%x",priv->pmib->dot11IGTKTable.dot11EncryptKey.dot11TTKey.skey[i]); + PMFDEBUG("\n"); + pn48 = GET_IGROUP_ENCRYP_PN; +#ifdef CONFIG_IEEE80211W_BIPTEST + // test data + memcpy(pwlhdr+10,Addr,6); + memcpy(pwlhdr+16,Addr,6); + ttkey = IGTK; + BIPPN.val48 = 4; + pn48 = &BIPPN; +#endif + pn_vector[0] = pn48->_byte_.TSC0; + pn_vector[1] = pn48->_byte_.TSC1; + pn_vector[2] = pn48->_byte_.TSC2; + pn_vector[3] = pn48->_byte_.TSC3; + pn_vector[4] = pn48->_byte_.TSC4; + pn_vector[5] = pn48->_byte_.TSC5; + + keyid = 4; +#ifndef CONFIG_IEEE80211W_BIPTEST + BIP_data = (unsigned char *)kmalloc(20+ frag2_len + 18, GFP_ATOMIC); +#endif + + // Generate BIP AAD (FC | A1 | A2 | A3) + BIP_data[0] = pwlhdr[0]; + pwlhdr[1] &= 0xBF; + BIP_data[1] = pwlhdr[1]; + memcpy(BIP_data+2,pwlhdr+4,18); // A1 | A2 | A3 (18 bytes) + // Generate Management Frame Body + memcpy(BIP_data+20,frag2,frag2_len); + + // Generate MMIE + offset = 20 + frag2_len; + BIP_data[offset++] = 0x4c; // element ID (Management MIC frame) + BIP_data[offset++] = 0x10; // MMIC length + BIP_data[offset++] = 0x04; // Key ID + BIP_data[offset++] = 0x00; // Key ID + memcpy(BIP_data+offset,pn_vector,6); // IPN + offset += 6; + memset(BIP_data+offset,0,8); +#ifdef CONFIG_IEEE80211W_BIPTEST + printk("BIP_data len=%d data=",frag2_len); + for (i=0;i<20+ frag2_len + 18;i++) + printk("%02x ",BIP_data[i]); + printk("\n"); +#endif + memcpy(frag2+frag2_len,BIP_data+20+frag2_len,10); + // Use AES-128-CMAC to generate IMIC + omac1_aes_128(ttkey,BIP_data,20+ frag2_len + 18,IMIC); +#ifdef CONFIG_IEEE80211W_BIPTEST + printk("IMIC="); + for (i=0;i<16;i++) + printk("%02x",IMIC[i]); + printk("\n"); +#endif + memcpy(frag3,IMIC,8); +#ifdef CONFIG_PCI_HCI + rtl_cache_sync_wback(priv, (unsigned long)pwlhdr, hdrlen, PCI_DMA_TODEVICE); + rtl_cache_sync_wback(priv, (unsigned long)frag2, frag2_len+10, PCI_DMA_TODEVICE); + rtl_cache_sync_wback(priv, (unsigned long)frag3, 8, PCI_DMA_TODEVICE); +#endif + + kfree(BIP_data); + + if (pn48->val48 == 0xffffffffffffULL) + pn48->val48 = 0; + else + pn48->val48++; +} + +/*when STA mode rx broadcast deauth , check Management MIC Information Element (MMIE) +campare least 8 bytes(MIC) +ret:1 success +ret:0 fail +*/ + +int MMIE_check(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + +#define FC_LEN 2 +#define DUR_LEN 2 +#define A1A2A3_LEN 18 +#define SEQ_LEN 2 +#define REASON_LEN 2 +#define MMIE_LEN 10 +#define MIC_LEN 8 +#define _SUCCESS 1 +#define _FAIL 0 + + unsigned char *pframe = get_pframe(pfrinfo); + unsigned char *ttkey = NULL; + unsigned char BIP_data[40]; + unsigned char MIC_be_chk[16]; // 16 ? why not 8? +#ifdef CONFIG_IEEE80211W_CLI_DEBUG + int i=0; +#endif + + memset(BIP_data,0,40); + memset(MIC_be_chk,0,16); + + ttkey = GET_IGROUP_ENCRYP_KEY; + +#ifdef CONFIG_IEEE80211W_CLI_DEBUG + panic_printk("IGTK="); + for (i=0;i<16;i++) + panic_printk("%x ",priv->pmib->dot11IGTKTable.dot11EncryptKey.dot11TTKey.skey[i]); + panic_printk("\n"); +#endif + + /*cp BIP AAD (FC | A1 | A2 | A3)*/ + memcpy(&BIP_data[0],pframe,FC_LEN); // cp FC + memcpy(&BIP_data[FC_LEN],pframe+FC_LEN+DUR_LEN ,A1A2A3_LEN ); // cp A1 , A2 ,A3 + + /*cp Management Frame Body*/ + memcpy(&BIP_data[FC_LEN + A1A2A3_LEN],pframe+FC_LEN+DUR_LEN+A1A2A3_LEN+SEQ_LEN ,REASON_LEN ); + + /*cp MMIE */ + memcpy(&BIP_data[FC_LEN + A1A2A3_LEN + REASON_LEN],pframe+FC_LEN+DUR_LEN+A1A2A3_LEN+SEQ_LEN+REASON_LEN ,MMIE_LEN ); + + + /*Use AES-128-CMAC to generate IMIC*/ + omac1_aes_128(ttkey,BIP_data,FC_LEN + A1A2A3_LEN + REASON_LEN + MMIE_LEN + MIC_LEN , MIC_be_chk ); + +#ifdef CONFIG_IEEE80211W_CLI_DEBUG + PMFDEBUG("IMIC="); + for(i=0;i<16;i++) + panic_printk("%02x",MIC_be_chk[i]); + panic_printk("\n"); +#endif + + + if (!memcmp(MIC_be_chk, pframe + BIP_HEADER_LEN + 10, MIC_LEN)) + return _SUCCESS ; //match! + else + return _FAIL ; +} + +int aesccmp_checkmic(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, unsigned char *pmic) +{ + unsigned char *sa; + unsigned char *ttkey = NULL; + union PN48 pn48; + unsigned int keyid = 0; + struct stat_info *pstat = NULL; + unsigned int i; + unsigned char *pframe = get_pframe(pfrinfo); + unsigned char calmic[8]; + unsigned char data[1460]; + sa = get_sa(pframe); + + if (OPMODE & WIFI_AP_STATE +#ifdef CONFIG_IEEE80211W_CLI + || (OPMODE & WIFI_STATION_STATE) +#endif + ) + { + if (!IS_MCAST(sa)) + { + pstat = get_stainfo(priv, sa); + + if (pstat == NULL) { + DEBUG_ERR("tx aes pstat == NULL\n"); + return 0; + } + + ttkey = GET_UNICAST_ENCRYP_KEY; + + pn48._byte_.TSC0 = pframe[pfrinfo->hdr_len]; + pn48._byte_.TSC1 = pframe[pfrinfo->hdr_len+1]; + pn48._byte_.TSC2 = pframe[pfrinfo->hdr_len+4]; + pn48._byte_.TSC3 = pframe[pfrinfo->hdr_len+5]; + pn48._byte_.TSC4 = pframe[pfrinfo->hdr_len+6]; + pn48._byte_.TSC5 = pframe[pfrinfo->hdr_len+7]; + keyid = 0; + + } + } + + if ((ttkey == NULL)) { + DEBUG_ERR("no encrypt key for AES due to ttkey=NULL\n"); + return 0; + } + + memcpy(data, pframe + pfrinfo->hdr_len + 8, pfrinfo->pktlen - pfrinfo->hdr_len - 8 - 8); + + aes_tx(priv, ttkey, keyid, + &pn48, pframe, 0, + pframe + pfrinfo->hdr_len + 8, pfrinfo->pktlen - pfrinfo->hdr_len - 8 - 8, + calmic, 1, 1); + + if (!memcmp(pmic, calmic,8)) + return 1; + else + return 0; +} +#endif // CONFIG_IEEE80211W + +void aesccmp_encrypt(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, + unsigned char *frag1, + unsigned char *frag2, unsigned int frag2_len, + unsigned char *frag3 +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ) +{ +#ifdef CONFIG_IEEE80211W_TEST + unsigned char CCMPTK[16]={0x66,0xed,0x21,0x04,0x2f,0x9f,0x26,0xd7,0x11,0x57,0x06,0xe4,0x04,0x14,0xcf,0x2e}; // test for PMF + unsigned char testDa[6]={0x02,0x00,0x00,0x00,0x01,0x00};// test for PMF (unicast Deauth frame) + //unsigned char testDa[6]={0xff,0xff,0xff,0xff,0xff,0xff};// test for PMF (broadcast Deauth frame) + unsigned char testSa[6]={0x02,0x00,0x00,0x00,0x00,0x00};// test for PMF + union PN48 CCMPPN;// test for PMF +#endif + + unsigned char *da; + unsigned char *ttkey = NULL; + union PN48 *pn48 = NULL; + unsigned int keyid = 0; + struct stat_info *pstat = NULL; + +#ifdef CONFIG_IEEE80211W_TEST + if (isMgmt) { + printk("isMgmt\n"); + memcpy(pwlhdr+4,testDa,6);// test for PMF + memcpy(pwlhdr+10,testSa,6); + // test for PMF + memcpy(pwlhdr+16,testSa,6);// test for PMF + CCMPPN.val48 = 1;// test for PMF (unicast) + } +#endif + + da = get_da(pwlhdr); + + if (OPMODE & WIFI_AP_STATE) + { +#if defined(WDS) || defined(CONFIG_RTK_MESH) || defined(A4_STA) + unsigned int to_fr_ds = (GetToDs(pwlhdr) << 1) | GetFrDs(pwlhdr); + if (to_fr_ds == 3) + da = GetAddr1Ptr(pwlhdr); +#endif + + if (IS_MCAST(da)) + { + ttkey = GET_GROUP_ENCRYP_KEY; + pn48 = GET_GROUP_ENCRYP_PN; + //keyid = 1; + keyid = priv->pmib->dot11GroupKeysTable.keyid;//use mib keyid + } + else + { +#ifdef CONFIG_IEEE80211W_TEST + // marked test for PMF + if (isMgmt) { // when test and Mgmt frame + ttkey = CCMPTK; + pn48 = &CCMPPN; + } + else +#endif + { + pstat = get_stainfo(priv, da); + if (pstat == NULL) { + DEBUG_ERR("tx aes pstat == NULL\n"); + return; + } + ttkey = GET_UNICAST_ENCRYP_KEY; + pn48 = GET_UNICAST_ENCRYP_PN; + } +#ifdef CONFIG_IEEE80211W_TEST + if (isMgmt) { + printk("isUnicast\n"); + printk("ttkey="); + for(i=0;i<16;i++) + printk("%02x",ttkey[i]); + printk("\n"); + printk("pn48=%02x%02x%02x%02x%02x%02x\n",pn48->_byte_.TSC0,pn48->_byte_.TSC1,pn48->_byte_.TSC2,pn48->_byte_.TSC3,pn48->_byte_.TSC4,pn48->_byte_.TSC5); + } +#endif + keyid = 0; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + + if (IS_MCAST(da)) //eric-ath + { + ttkey = GET_GROUP_ENCRYP_KEY; + pn48 = GET_GROUP_ENCRYP_PN; + keyid = GET_ROOT(priv)->pmib->dot11GroupKeysTable.keyid; + + } + else + { + pstat = get_stainfo(priv, BSSID); + if (pstat == NULL) { + DEBUG_ERR("tx aes pstat == NULL\n"); + return; + } + ttkey = GET_UNICAST_ENCRYP_KEY; + pn48 = GET_UNICAST_ENCRYP_PN; + + keyid = 0; + + } + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + ttkey = GET_GROUP_ENCRYP_KEY; + pn48 = GET_GROUP_ENCRYP_PN; + keyid = 0; + } +#endif + + if ((ttkey == NULL) || (pn48 == NULL)) { + DEBUG_ERR("no encrypt key for AES due to ttkey=NULL or pn48=NULL\n"); + return; + } +#ifdef CONFIG_IEEE80211W + if (isMgmt) + frag1 = 0; +#endif + + aes_tx(priv, ttkey, keyid, pn48, pwlhdr, frag1, frag2, frag2_len, frag3 +#ifdef CONFIG_IEEE80211W + ,isMgmt + ,0 +#endif + ); +} + + +static void aes_rx(UINT8 *ttkey, UINT8 qc_exists, UINT8 a4_exists, + UINT8 *pframe, UINT32 hdrlen, UINT32 plen +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ) +{ + UINT32 i, j, payload_remainder, + num_blocks, payload_index; + + UINT8 pn_vector[6]; + UINT8 mic_iv[16]; + UINT8 mic_header1[16]; + UINT8 mic_header2[16]; + UINT8 ctr_preload[16]; + + UINT8 chain_buffer[16]; + UINT8 aes_out[16]; + UINT8 padded_buffer[16]; + UINT8 mic[8]; + + memset((void *)mic_iv, 0, 16); + memset((void *)mic_header1, 0, 16); + memset((void *)mic_header2, 0, 16); + memset((void *)ctr_preload, 0, 16); + memset((void *)chain_buffer, 0, 16); + memset((void *)aes_out, 0, 16); + memset((void *)mic, 0, 8); + + num_blocks = plen / 16; //(plen including llc, payload_length and mic ) + + payload_remainder = plen % 16; + + pn_vector[0] = pframe[hdrlen]; + pn_vector[1] = pframe[hdrlen+1]; + pn_vector[2] = pframe[hdrlen+4]; + pn_vector[3] = pframe[hdrlen+5]; + pn_vector[4] = pframe[hdrlen+6]; + pn_vector[5] = pframe[hdrlen+7]; + + // now, decrypt pframe with hdrlen offset and plen long + + payload_index = hdrlen + 8; // 8 is for extiv + for (i=0; i< num_blocks; i++) + { + construct_ctr_preload( + ctr_preload, + a4_exists, + qc_exists, + pframe, + pn_vector, + i+1 +#ifdef CONFIG_IEEE80211W + ,isMgmt +#endif + ); + + aes128k128d(ttkey, ctr_preload, aes_out); + bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); + + for (j=0; j<16;j++) pframe[payload_index++] = chain_buffer[j]; + } + + if (payload_remainder > 0) /* If there is a short final block, then pad it,*/ + { /* encrypt it and copy the unpadded part back */ + construct_ctr_preload( + ctr_preload, + a4_exists, + qc_exists, + pframe, + pn_vector, + num_blocks+1 +#ifdef CONFIG_IEEE80211W + ,isMgmt +#endif + ); + + for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; + for (j = 0; j < payload_remainder; j++) + { + padded_buffer[j] = pframe[payload_index+j]; + } + aes128k128d(ttkey, ctr_preload, aes_out); + bitwise_xor(aes_out, padded_buffer, chain_buffer); + for (j=0; jsa; + UINT8 *pframe = get_pframe(pfrinfo); + UINT8 to_fr_ds = pfrinfo->to_fr_ds; + struct stat_info *pstat = NULL; +#ifdef CONFIG_IEEE80211W_TEST + unsigned char CCMPTK[16]={0x66,0xed,0x21,0x04,0x2f,0x9f,0x26,0xd7,0x11,0x57,0x06,0xe4,0x04,0x14,0xcf,0x2e}; // test for PMF + unsigned char testDa[6]={0x02,0x00,0x00,0x00,0x01,0x00};// test for PMF (unicast Deauth frame) + //unsigned char testDa[6]={0xff,0xff,0xff,0xff,0xff,0xff};// test for PMF (broadcast Deauth frame) + unsigned char testSa[6]={0x02,0x00,0x00,0x00,0x00,0x00};// test for PMF + unsigned char testIV[8]={0x01,0x00,0x00,0x20,0x00,0x00,0x00,0x00}; + unsigned char testdata[10]={0x1d,0x07,0xca,0xfd,0x04,0x09,0xbb,0x8b,0xaf,0xef}; + + if (isMgmt) { + printk("isMgmt\n"); + pframe[0]=0xc0; + pframe[1]=0x00; + memcpy(pframe+4,testDa,6);// test for PMF + memcpy(pframe+10,testSa,6); + // test for PMF + memcpy(pframe+16,testSa,6);// test for PMF + memcpy(pframe+24,testIV,8); + memcpy(pframe+32,testdata,10); + pfrinfo->pktlen = 42; + } +#endif + + if (to_fr_ds != 0x03) { + hdrlen = WLAN_HDR_A3_LEN; + a4_exists = 0; + } + else { + hdrlen = WLAN_HDR_A4_LEN; + a4_exists = 1; + } + + if (is_qos_data(pframe)) { + qc_exists = 1; + hdrlen += 2; + } + else + qc_exists = 0; + + if (OPMODE & WIFI_AP_STATE) + { +#if defined(WDS) || defined(CONFIG_RTK_MESH) + if (to_fr_ds == 3) + pstat = get_stainfo (priv, GetAddr2Ptr(pframe)); + else +#endif + +#ifdef A4_STA + if (to_fr_ds == 3) + pstat = get_stainfo (priv, GetAddr2Ptr(pframe)); + else +#endif + pstat = get_stainfo (priv, sa); + +#ifdef CONFIG_IEEE80211W_TEST + // marked test for PMF + if (isMgmt) { // when test and Mgmt frame + ttkey = CCMPTK; + keylen = 16; + } + else +#endif + { + if (pstat == NULL) + { + DEBUG_ERR("AES Rx fails! sa=%02X%02X%02X%02X%02X%02X\n", + sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); + return FALSE; + } + + keylen = GET_UNICAST_ENCRYP_KEYLEN; + ttkey = GET_UNICAST_ENCRYP_KEY; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + if (IS_MCAST(pfrinfo->da)) + { + keylen = GET_GROUP_ENCRYP_KEYLEN; + ttkey = GET_GROUP_ENCRYP_KEY; + } + else + { + pstat = get_stainfo(priv, BSSID); + if (pstat == NULL) { + DEBUG_ERR("rx aes pstat == NULL\n"); + return FALSE; + } + keylen = GET_UNICAST_ENCRYP_KEYLEN; + ttkey = GET_UNICAST_ENCRYP_KEY; + } + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + keylen = GET_GROUP_ENCRYP_KEYLEN; + ttkey = GET_GROUP_ENCRYP_KEY; + } +#endif + + if (keylen == 0) { + DEBUG_ERR("no descrypt key for AES due to keylen=0\n"); + return FALSE; + } +#ifdef CONFIG_IEEE80211W_TEST + if (isMgmt) { + int i; + printk("pframe="); + for (i=0;ipktlen;i++) + printk("%02x ",pframe[i]); + printk("\n"); + printk("ttkey="); + for (i=0;ipktlen-hdrlen-8 +#ifdef CONFIG_IEEE80211W + ,isMgmt +#endif + ); + return TRUE; +} + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_br_ext.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_br_ext.c new file mode 100755 index 000000000..d09529d6b --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_br_ext.c @@ -0,0 +1,2602 @@ +/* + * bridge extention functions + * + * $Id: 8192cd_br_ext.c,v 1.1.4.3 2010/12/22 09:08:59 pluswang Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_BR_EXT_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +typedef struct udphdr udphdr; +#elif defined(__ECOS) +//#include +#include +#include +#include +typedef struct udp_hdr udphdr; +#endif + +#include "./8192cd_cfg.h" + +#ifndef __KERNEL__ +#ifdef __ECOS +#include +#else +#include "./sys-support.h" +#endif +#endif + +#include "./8192cd.h" +#include "./8192cd_headers.h" +#include "./8192cd_br_ext.h" +#include "./8192cd_debug.h" + +#ifdef CL_IPV6_PASS +#ifdef __KERNEL__ +#include +#include +#include +#include +#endif +#endif + +#ifdef RTK_BR_EXT + +//#define BR_EXT_DEBUG + +#define NAT25_IPV4 01 +#define NAT25_IPV6 02 +#define NAT25_IPX 03 +#define NAT25_APPLE 04 +#define NAT25_PPPOE 05 + +#define RTL_RELAY_TAG_LEN (ETH_ALEN) +#define TAG_HDR_LEN 4 + +#define MAGIC_CODE 0x8186 +#define MAGIC_CODE_LEN 2 +#define WAIT_TIME_PPPOE 5 // waiting time for pppoe server in sec + +#ifdef __ECOS +#ifdef CL_IPV6_PASS + +#include + +#define NDISC_ROUTER_SOLICITATION 133 +#define NDISC_ROUTER_ADVERTISEMENT 134 +#define NDISC_NEIGHBOUR_SOLICITATION 135 +#define NDISC_NEIGHBOUR_ADVERTISEMENT 136 +#define NDISC_REDIRECT 137 +#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ + +struct ipv6hdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 priority:4, + version:4; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u8 version:4, + priority:4; +#else +#error "Please fix " +#endif + __u8 flow_lbl[3]; + + __u16 payload_len; + __u8 nexthdr; + __u8 hop_limit; + + struct in6_addr saddr; + struct in6_addr daddr; +}; +#endif /* CL_IPV6_PASS */ + +#define MAX_DB_NUM 32 +#define __constant_htonl(x) htonl(x) + +#define ADJUST_CHKSUM(port_mod, port_org, chksum) \ + do { \ + s32 accumulate = 0; \ + accumulate += (port_org); \ + accumulate -= (port_mod); \ + accumulate += ntohs(chksum); \ + if (accumulate < 0) { \ + accumulate = -accumulate; \ + accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ + accumulate += accumulate >> 16; \ + chksum = htons((u16) ~accumulate); \ + } else { \ + accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ + accumulate += accumulate >> 16; \ + chksum = htons((u16) accumulate); \ + } \ + }while(0) /* Checksum adjustment */ + +static struct nat25_network_db_entry sta_db[MAX_DB_NUM]; + + +void nat25_db_init(void) +{ + memset(sta_db, '\0', sizeof(sta_db)); +} + + +static struct nat25_network_db_entry *nat25_db_get(void) +{ + int i; + + for (i=0; iused = 0; +} +#endif /* __ECOS */ + + +/*-------------------------------------------------------------------------------------------- + How database records network address: + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + |----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----| + IPv4 |type| | IP addr | + IPv6 |type| IPv6 addr | + IPX |type| Net addr | Node addr | + IPX |type| Net addr |Sckt addr| + Apple |type| Network |node| + PPPoE |type| SID | AC MAC | +--------------------------------------------------------------------------------------------*/ + + +//Find a tag in pppoe frame and return the pointer +static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type) +{ + unsigned char *cur_ptr, *start_ptr; + unsigned short tagLen, tagType; + + start_ptr = cur_ptr = (unsigned char *)ph->tag; + while((cur_ptr - start_ptr) < ntohs(ph->length)) { + // prevent un-alignment access + tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]); + tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]); + if(tagType == type) + return cur_ptr; + cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen; + } + return 0; +} + + +static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag) +{ + struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); + int data_len; + + data_len = ntohs(tag->tag_len) + TAG_HDR_LEN; + if (skb_tailroom(skb) < data_len) { + _DEBUG_ERR("skb_tailroom() failed in add SID tag!\n"); + return -1; + } + + skb_put(skb, data_len); + // have a room for new tag + memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length)); + ph->length = htons(ntohs(ph->length) + data_len); + memcpy((unsigned char *)ph->tag, tag, data_len); + return data_len; +} + + +static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len) +{ + int tail_len; + unsigned long end, tail; + + if ((src+len) > skb->tail || skb->len < len) + return -1; + + tail = (unsigned long)skb->tail; + end = (unsigned long)src+len; + if (tail < end) + return -1; + + tail_len = (int)(tail-end); + if (tail_len > 0) + memmove(src, src+len, tail_len); + + skb_trim(skb, skb->len-len); + return 0; +} + + +static __inline__ unsigned long __nat25_timeout(struct rtl8192cd_priv *priv) +{ + unsigned long timeout; + + timeout = jiffies - NAT25_AGEING_TIME*HZ; + + return timeout; +} + + +static __inline__ int __nat25_has_expired(struct rtl8192cd_priv *priv, + struct nat25_network_db_entry *fdb) +{ + if(time_before_eq(fdb->ageing_timer, __nat25_timeout(priv))) + return 1; + + return 0; +} + + +static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr, +#ifdef __ECOS + unsigned char *ipAddr +#else + unsigned int *ipAddr +#endif + ) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPV4; + memcpy(networkAddr+7, (unsigned char *)ipAddr, 4); +} + + +static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr, +#ifdef __ECOS + unsigned char *ipxNetAddr, unsigned char *ipxNodeAddr +#else + unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr +#endif + ) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPX; + memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4); + memcpy(networkAddr+5, ipxNodeAddr, 6); +} + + +static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr, +#ifdef __ECOS + unsigned char *ipxNetAddr, unsigned char *ipxSocketAddr +#else + unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr +#endif + ) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPX; + memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4); + memcpy(networkAddr+5, (unsigned char *)ipxSocketAddr, 2); +} + + +static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr, +#ifdef __ECOS + unsigned char *network, unsigned char *node +#else + unsigned short *network, unsigned char *node +#endif + ) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_APPLE; + memcpy(networkAddr+1, (unsigned char *)network, 2); + networkAddr[3] = *node; +} + + +static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr, + unsigned char *ac_mac, unsigned short *sid) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_PPPOE; + memcpy(networkAddr+1, (unsigned char *)sid, 2); + memcpy(networkAddr+3, (unsigned char *)ac_mac, 6); +} + + +#ifdef CL_IPV6_PASS +static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr, +#ifdef __ECOS + unsigned char *ipAddr +#else + unsigned int *ipAddr +#endif + ) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPV6; + memcpy(networkAddr+1, (unsigned char *)ipAddr, 16); +} + + +static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b) +{ + while (len > 0) { + if (*data == tag && *(data+1) == len8b && len >= len8b*8) + return data+2; + + len -= (*(data+1))*8; + data += (*(data+1))*8; + } + return NULL; +} + + +#ifdef __ECOS +static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac, unsigned char *org_mac) +#else +static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac) +#endif +{ + struct icmp6hdr *icmphdr = (struct icmp6hdr *)data; + unsigned char *mac; + + if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { + if (len >= 8) { + mac = scan_tlv(&data[8], len-8, 1, 1); + if (mac) { + _DEBUG_INFO("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5], + replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]); +#ifdef __ECOS + memcpy(org_mac, mac, 6); +#endif + memcpy(mac, replace_mac, 6); + return 1; + } + } + } + else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) { + if (len >= 16) { + mac = scan_tlv(&data[16], len-16, 1, 1); + if (mac) { + _DEBUG_INFO("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5], + replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]); +#ifdef __ECOS + memcpy(org_mac, mac, 6); +#endif + memcpy(mac, replace_mac, 6); + return 1; + } + } + } + else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { + if (len >= 24) { + mac = scan_tlv(&data[24], len-24, 1, 1); + if (mac) { + _DEBUG_INFO("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5], + replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]); +#ifdef __ECOS + memcpy(org_mac, mac, 6); +#endif + memcpy(mac, replace_mac, 6); + return 1; + } + } + } + else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { + if (len >= 24) { + mac = scan_tlv(&data[24], len-24, 2, 1); + if (mac) { + _DEBUG_INFO("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5], + replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]); +#ifdef __ECOS + memcpy(org_mac, mac, 6); +#endif + memcpy(mac, replace_mac, 6); + return 1; + } + } + } + else if (icmphdr->icmp6_type == NDISC_REDIRECT) { + if (len >= 40) { + mac = scan_tlv(&data[40], len-40, 2, 1); + if (mac) { + _DEBUG_INFO("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5], + replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]); +#ifdef __ECOS + memcpy(org_mac, mac, 6); +#endif + memcpy(mac, replace_mac, 6); + return 1; + } + } + } + return 0; +} + + +#ifdef SUPPORT_RX_UNI2MCAST +static void convert_ipv6_mac_to_mc(struct sk_buff *skb) +{ + struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); + unsigned char *dst_mac = skb->data; + + //dst_mac[0] = 0xff; + //dst_mac[1] = 0xff; + /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/ + dst_mac[0] = 0x33; + dst_mac[1] = 0x33; + memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4); +#if defined(__LINUX_2_6__) + /*modified by qinjunjie,warning:should not remove next line*/ + skb->pkt_type = PACKET_MULTICAST; +#endif +} +#endif +#endif /* CL_IPV6_PASS */ + + +static __inline__ int __nat25_network_hash(unsigned char *networkAddr) +{ + if(networkAddr[0] == NAT25_IPV4) + { + unsigned long x; + + x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; + + return x & (NAT25_HASH_SIZE - 1); + } + else if(networkAddr[0] == NAT25_IPX) + { + unsigned long x; + + x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ + networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; + + return x & (NAT25_HASH_SIZE - 1); + } + else if(networkAddr[0] == NAT25_APPLE) + { + unsigned long x; + + x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3]; + + return x & (NAT25_HASH_SIZE - 1); + } + else if(networkAddr[0] == NAT25_PPPOE) + { + unsigned long x; + + x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8]; + + return x & (NAT25_HASH_SIZE - 1); + } +#ifdef CL_IPV6_PASS + else if(networkAddr[0] == NAT25_IPV6) + { + unsigned long x; + + x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ + networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^ + networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^ + networkAddr[16]; + + return x & (NAT25_HASH_SIZE - 1); + } +#endif + else + { + unsigned long x = 0; + int i; + + for (i=0; inext_hash = priv->nethash[hash]; + if(ent->next_hash != NULL) + ent->next_hash->pprev_hash = &ent->next_hash; + priv->nethash[hash] = ent; + ent->pprev_hash = &priv->nethash[hash]; +} + + +static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent) +{ + *(ent->pprev_hash) = ent->next_hash; + if(ent->next_hash != NULL) + ent->next_hash->pprev_hash = ent->pprev_hash; + ent->next_hash = NULL; + ent->pprev_hash = NULL; +} + + +static int __nat25_db_network_lookup_and_replace(struct rtl8192cd_priv *priv, + struct sk_buff *skb, unsigned char *networkAddr) +{ + struct nat25_network_db_entry *db; + + db = priv->nethash[__nat25_network_hash(networkAddr)]; + while (db != NULL) + { + if(!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) + { + if(!__nat25_has_expired(priv, db)) + { + // replace the destination mac address + memcpy(skb->data, db->macAddr, ETH_ALEN); + atomic_inc(&db->use_count); + +#ifdef CL_IPV6_PASS + DEBUG_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x\n", + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10], + db->networkAddr[11], + db->networkAddr[12], + db->networkAddr[13], + db->networkAddr[14], + db->networkAddr[15], + db->networkAddr[16]); +#else + DEBUG_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10]); +#endif + } + return 1; + } + + db = db->next_hash; + } + + return 0; +} + + +static void __nat25_db_network_insert(struct rtl8192cd_priv *priv, + unsigned char *macAddr, unsigned char *networkAddr) +{ + struct nat25_network_db_entry *db; + int hash; + + hash = __nat25_network_hash(networkAddr); + db = priv->nethash[hash]; + while (db != NULL) + { + if(!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) + { + memcpy(db->macAddr, macAddr, ETH_ALEN); + db->ageing_timer = jiffies; + return; + } + + db = db->next_hash; + } + +#ifdef __ECOS + db = nat25_db_get(); +#else + db = kmalloc(sizeof(*db), GFP_ATOMIC); +#endif + if(db == NULL) { +#ifdef __ECOS + diag_printf("run out nat25 table!\n"); +#endif + return; + } + + memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN); + memcpy(db->macAddr, macAddr, ETH_ALEN); + atomic_set(&db->use_count, 1); + db->ageing_timer = jiffies; + + __network_hash_link(priv, db, hash); +} + + +#ifdef CONFIG_RTL_ULINKER +int __nat25_db_query(struct rtl8192cd_priv *priv , unsigned char* MacAddr) +{ + + static int counter = 0; + int i, j , retVal; + struct nat25_network_db_entry *db; + retVal=0; + + counter++; + if((counter <16)) + return 0; + + + for(i=0, j=0; inethash[i]; + while (db != NULL) + { + if(!memcmp(db->macAddr, MacAddr, MACADDRLEN)){ + return 1; + } + j++; + db = db->next_hash; + } + } + + return 0; +} +#endif + +static void __nat25_db_print(struct rtl8192cd_priv *priv) +{ +#ifdef BR_EXT_DEBUG + static int counter = 0; + int i, j; + struct nat25_network_db_entry *db; + + counter++; + if((counter % 16) != 0) + return; + + for(i=0, j=0; inethash[i]; + + while (db != NULL) + { +#ifdef CL_IPV6_PASS + panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x\n", + j, + i, + atomic_read(&db->use_count), + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10], + db->networkAddr[11], + db->networkAddr[12], + db->networkAddr[13], + db->networkAddr[14], + db->networkAddr[15], + db->networkAddr[16]); +#else + panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + j, + i, + atomic_read(&db->use_count), + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10]); +#endif + j++; + + db = db->next_hash; + } + } +#endif +} + + + + +/* + * NAT2.5 interface + */ + +void nat25_db_cleanup(struct rtl8192cd_priv *priv) +{ + int i; + + for(i=0; inethash[i]; + while (f != NULL) { + struct nat25_network_db_entry *g; + + g = f->next_hash; + __network_hash_unlink(f); +#ifdef __ECOS + nat25_db_free(f); +#else + kfree(f); +#endif + f = g; + } + } +} + + +void nat25_db_expire(struct rtl8192cd_priv *priv) +{ + int i; + + if(!priv->pmib->ethBrExtInfo.nat25_disable) + { + for (i=0; inethash[i]; + + while (f != NULL) + { + struct nat25_network_db_entry *g; + g = f->next_hash; + + if(__nat25_has_expired(priv, f)) + { + if(atomic_dec_and_test(&f->use_count)) + { +#ifdef BR_EXT_DEBUG +#ifdef CL_IPV6_PASS + panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x\n", + i, + f->macAddr[0], + f->macAddr[1], + f->macAddr[2], + f->macAddr[3], + f->macAddr[4], + f->macAddr[5], + f->networkAddr[0], + f->networkAddr[1], + f->networkAddr[2], + f->networkAddr[3], + f->networkAddr[4], + f->networkAddr[5], + f->networkAddr[6], + f->networkAddr[7], + f->networkAddr[8], + f->networkAddr[9], + f->networkAddr[10], + f->networkAddr[11], + f->networkAddr[12], + f->networkAddr[13], + f->networkAddr[14], + f->networkAddr[15], + f->networkAddr[16]); +#else + + panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + i, + f->macAddr[0], + f->macAddr[1], + f->macAddr[2], + f->macAddr[3], + f->macAddr[4], + f->macAddr[5], + f->networkAddr[0], + f->networkAddr[1], + f->networkAddr[2], + f->networkAddr[3], + f->networkAddr[4], + f->networkAddr[5], + f->networkAddr[6], + f->networkAddr[7], + f->networkAddr[8], + f->networkAddr[9], + f->networkAddr[10]); +#endif +#endif + if (!memcmp(priv->scdb_mac, f->macAddr, ETH_ALEN)) { + memset(priv->scdb_mac, 0, ETH_ALEN); + memset(priv->scdb_ip, 0, 4); + } + __network_hash_unlink(f); +#ifdef __ECOS + nat25_db_free(f); +#else + kfree(f); +#endif + } + } + + f = g; + } + } + } +} + + +#ifdef SUPPORT_TX_MCAST2UNI +#ifdef __ECOS +static int checkIPMcAndReplace(struct rtl8192cd_priv *priv, struct sk_buff *skb, unsigned char *dst_ip) +#else +static int checkIPMcAndReplace(struct rtl8192cd_priv *priv, struct sk_buff *skb, unsigned int *dst_ip) +#endif +{ + struct stat_info *pstat; + struct list_head *phead, *plist; + int i, result = 0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if (pstat->ipmc_num == 0) + continue; + + for (i=0; iipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip)+1, 3)) { + memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN); + result = 1; + goto exit; + } + } + } + +exit: + SMP_UNLOCK_ASOC_LIST(flags); + + return result; +} +#endif + +#ifdef MULTI_MAC_CLONE +// return 0: not replaced +// 1: dst mac replaced +int mclone_checkMacAndReplace(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + unsigned char *da=skb->data; + int id = mclone_find_address(priv, da, NULL, MAC_CLONE_NOCARE_FIND); + + if (id > 0) { + memcpy(skb->data, priv->pshare->mclone_sta[id-1].sa_addr, ETH_ALEN); + return 1; + } + + return 0; +} +#endif + +int nat25_db_handle(struct rtl8192cd_priv *priv, struct sk_buff *skb, int method) +{ + unsigned short protocol; + unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; + int macclone_da=0; + + if(skb == NULL) + return -1; + + if((method <= NAT25_MIN) || (method >= NAT25_MAX)) + return -1; + + if(priv->pmib->ethBrExtInfo.macclone_enable && priv->macclone_completed){ + //WSC_DEBUG("NAT25:no handle macclone packet\n"); + macclone_da=1; + } + protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); + + /*---------------------------------------------------*/ + /* Handle IP frame */ + /*---------------------------------------------------*/ + if(protocol == __constant_htons(ETH_P_IP)) + { + struct iphdr* iph = (struct iphdr *)(skb->data + ETH_HLEN); + + if(((unsigned char*)(iph) + (iph->ihl<<2)) >= (skb->data + ETH_HLEN + skb->len)) + { + DEBUG_WARN("NAT25: malformed IP packet !\n"); + return -1; + } + + switch(method) + { + case NAT25_CHECK: + if (IS_MCAST(skb->data)) + return 0; + else + return -1; + + case NAT25_INSERT: + { + DEBUG_INFO("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); +#ifdef __ECOS + __nat25_generate_ipv4_network_addr(networkAddr, (unsigned char *)&iph->saddr); +#else + __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr); +#endif + __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: + { + DEBUG_INFO("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); +#ifdef SUPPORT_TX_MCAST2UNI +#ifdef MULTI_MAC_CLONE + if (mclone_checkMacAndReplace(priv, skb)) + ; + else +#endif + if (priv->pshare->rf_ft_var.mc2u_disable || + ((((OPMODE & (WIFI_STATION_STATE|WIFI_ASOC_STATE)) + == (WIFI_STATION_STATE|WIFI_ASOC_STATE)) && + !checkIPMcAndReplace(priv, skb, &iph->daddr)) || + (OPMODE & WIFI_ADHOC_STATE))) +#endif + { +#ifdef __ECOS + __nat25_generate_ipv4_network_addr(networkAddr, (unsigned char *)&iph->daddr); +#else + __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr); +#endif + if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) { + if (*((unsigned char *)&iph->daddr + 3) == 0xff) { + // L2 is unicast but L3 is broadcast, make L2 bacome broadcast + DEBUG_INFO("NAT25: Set DA as boardcast\n"); + memset(skb->data, 0xff, ETH_ALEN); + } + else { + + if(macclone_da){ + /*RX path ,the maccloned packet don't Replace it's DA with BR's MAC*/ + }else + { // NAT25 only (maclone is disabled) + // forward unknow IP packet to upper TCP/IP + DEBUG_INFO("NAT25: Replace DA with BR's MAC\n"); + memcpy(skb->data, priv->br_mac, ETH_ALEN); + } + + } + } + } +#ifdef MULTI_MAC_CLONE + mclone_dhcp_caddr(priv, skb); +#endif + dhcp_dst_bcast(priv, skb); + } + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle ARP frame */ + /*---------------------------------------------------*/ + else if(protocol == __constant_htons(ETH_P_ARP)) + { + struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); + unsigned char *arp_ptr = (unsigned char *)(arp + 1); + unsigned int *sender, *target; + + if(arp->ar_pro != __constant_htons(ETH_P_IP)) + { + DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro)); + return -1; + } + + switch(method) + { + case NAT25_CHECK: + return 0; // skb_copy for all ARP frame + + case NAT25_INSERT: + { + DEBUG_INFO("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0], + arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]); + + // change to ARP sender mac address to wlan STA address + memcpy(arp_ptr, GET_MY_HWADDR, ETH_ALEN); + + arp_ptr += arp->ar_hln; + sender = (unsigned int *)arp_ptr; +#ifdef __ECOS + __nat25_generate_ipv4_network_addr(networkAddr, (unsigned char *)sender); +#else + __nat25_generate_ipv4_network_addr(networkAddr, sender); +#endif + __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: + { + DEBUG_INFO("NAT25: Lookup ARP\n"); + + arp_ptr += arp->ar_hln; + sender = (unsigned int *)arp_ptr; + arp_ptr += (arp->ar_hln + arp->ar_pln); + target = (unsigned int *)arp_ptr; +#ifdef __ECOS + __nat25_generate_ipv4_network_addr(networkAddr, (unsigned char *)target); +#else + __nat25_generate_ipv4_network_addr(networkAddr, target); +#endif + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + + // change to ARP target mac address to Lookup result + arp_ptr = (unsigned char *)(arp + 1); + arp_ptr += (arp->ar_hln + arp->ar_pln); + memcpy(arp_ptr, skb->data, ETH_ALEN); + } + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle IPX and Apple Talk frame */ + /*---------------------------------------------------*/ + else if((protocol == __constant_htons(ETH_P_IPX)) || + (ntohs(protocol) <= ETH_FRAME_LEN)) + { + unsigned char ipx_header[2] = {0xFF, 0xFF}; + struct ipxhdr *ipx = NULL; + struct elapaarp *ea = NULL; + struct ddpehdr *ddp = NULL; + unsigned char *framePtr = skb->data + ETH_HLEN; + + if(protocol == __constant_htons(ETH_P_IPX)) + { + DEBUG_INFO("NAT25: Protocol=IPX (Ethernet II)\n"); + ipx = (struct ipxhdr *)framePtr; + } + else if(ntohs(protocol) <= ETH_FRAME_LEN) + { + if(!memcmp(ipx_header, framePtr, 2)) + { + DEBUG_INFO("NAT25: Protocol=IPX (Ethernet 802.3)\n"); + ipx = (struct ipxhdr *)framePtr; + } + else + { + unsigned char ipx_8022_type = 0xE0; + unsigned char snap_8022_type = 0xAA; + + if(*framePtr == snap_8022_type) + { + unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; // IPX SNAP ID + unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; // Apple Talk AARP SNAP ID + unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; // Apple Talk DDP SNAP ID + + framePtr += 3; // eliminate the 802.2 header + + if(!memcmp(ipx_snap_id, framePtr, 5)) + { + framePtr += 5; // eliminate the SNAP header + + DEBUG_INFO("NAT25: Protocol=IPX (Ethernet SNAP)\n"); + ipx = (struct ipxhdr *)framePtr; + } + else if(!memcmp(aarp_snap_id, framePtr, 5)) + { + framePtr += 5; // eliminate the SNAP header + + ea = (struct elapaarp *)framePtr; + } + else if(!memcmp(ddp_snap_id, framePtr, 5)) + { + framePtr += 5; // eliminate the SNAP header + + ddp = (struct ddpehdr *)framePtr; + } + else + { + DEBUG_WARN("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0], + framePtr[1], framePtr[2], framePtr[3], framePtr[4]); + return -1; + } + } + else if(*framePtr == ipx_8022_type) + { + framePtr += 3; // eliminate the 802.2 header + + if(!memcmp(ipx_header, framePtr, 2)) + { + DEBUG_INFO("NAT25: Protocol=IPX (Ethernet 802.2)\n"); + ipx = (struct ipxhdr *)framePtr; + } + else + return -1; + } + else + return -1; + } + } + else + return -1; + + /* IPX */ + if(ipx != NULL) + { + switch(method) + { + case NAT25_CHECK: + if(!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) + { + DEBUG_INFO("NAT25: Check IPX skb_copy\n"); + return 0; + } + return -1; + + case NAT25_INSERT: + { + DEBUG_INFO("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n", + ipx->ipx_dest.net, + ipx->ipx_dest.node[0], + ipx->ipx_dest.node[1], + ipx->ipx_dest.node[2], + ipx->ipx_dest.node[3], + ipx->ipx_dest.node[4], + ipx->ipx_dest.node[5], + ipx->ipx_dest.sock, + ipx->ipx_source.net, + ipx->ipx_source.node[0], + ipx->ipx_source.node[1], + ipx->ipx_source.node[2], + ipx->ipx_source.node[3], + ipx->ipx_source.node[4], + ipx->ipx_source.node[5], + ipx->ipx_source.sock); + + if(!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) + { + DEBUG_INFO("NAT25: Use IPX Net, and Socket as network addr\n"); +#ifdef __ECOS + __nat25_generate_ipx_network_addr_with_socket(networkAddr, (unsigned char *)&ipx->ipx_source.net, (unsigned char *)&ipx->ipx_source.sock); +#else + __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock); +#endif + // change IPX source node addr to wlan STA address + memcpy(ipx->ipx_source.node, GET_MY_HWADDR, ETH_ALEN); + } + else + { +#ifdef __ECOS + __nat25_generate_ipx_network_addr_with_node(networkAddr, (unsigned char *)&ipx->ipx_source.net, ipx->ipx_source.node); +#else + __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node); +#endif + } + + __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: + { + if(!memcmp(GET_MY_HWADDR, ipx->ipx_dest.node, ETH_ALEN)) + { + DEBUG_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n"); +#ifdef __ECOS + __nat25_generate_ipx_network_addr_with_socket(networkAddr, (unsigned char *)&ipx->ipx_dest.net, (unsigned char *)&ipx->ipx_dest.sock); +#else + __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock); +#endif + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + + // replace IPX destination node addr with Lookup destination MAC addr + memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN); + } + else + { +#ifdef __ECOS + __nat25_generate_ipx_network_addr_with_node(networkAddr, (unsigned char *)&ipx->ipx_dest.net, ipx->ipx_dest.node); +#else + __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node); +#endif + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + } + } + return 0; + + default: + return -1; + } + } + + /* AARP */ + else if(ea != NULL) + { + /* Sanity check fields. */ + if(ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) + { + DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n"); + return -1; + } + + switch(method) + { + case NAT25_CHECK: + return 0; + + case NAT25_INSERT: + { + // change to AARP source mac address to wlan STA address + memcpy(ea->hw_src, GET_MY_HWADDR, ETH_ALEN); + + DEBUG_INFO("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n", + ea->pa_src_net, + ea->pa_src_node, + ea->pa_dst_net, + ea->pa_dst_node); +#ifdef __ECOS + __nat25_generate_apple_network_addr(networkAddr, (unsigned char *)&ea->pa_src_net, &ea->pa_src_node); +#else + __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node); +#endif + __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: + { + DEBUG_INFO("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n", + ea->pa_src_net, + ea->pa_src_node, + ea->pa_dst_net, + ea->pa_dst_node); +#ifdef __ECOS + __nat25_generate_apple_network_addr(networkAddr, (unsigned char *)&ea->pa_dst_net, &ea->pa_dst_node); +#else + __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node); +#endif + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + + // change to AARP destination mac address to Lookup result + memcpy(ea->hw_dst, skb->data, ETH_ALEN); + } + return 0; + + default: + return -1; + } + } + + /* DDP */ + else if(ddp != NULL) + { + switch(method) + { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: + { + DEBUG_INFO("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n", + ddp->deh_snet, + ddp->deh_snode, + ddp->deh_dnet, + ddp->deh_dnode); +#ifdef __ECOS + __nat25_generate_apple_network_addr(networkAddr, (unsigned char *)&ddp->deh_snet, &ddp->deh_snode); +#else + __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode); +#endif + __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + } + return 0; + + case NAT25_LOOKUP: + { + DEBUG_INFO("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n", + ddp->deh_snet, + ddp->deh_snode, + ddp->deh_dnet, + ddp->deh_dnode); +#ifdef __ECOS + __nat25_generate_apple_network_addr(networkAddr, (unsigned char *)&ddp->deh_dnet, &ddp->deh_dnode); +#else + __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode); +#endif + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + } + return 0; + + default: + return -1; + } + } + + return -1; + } + + /*---------------------------------------------------*/ + /* Handle PPPoE frame */ + /*---------------------------------------------------*/ + else if((protocol == __constant_htons(ETH_P_PPP_DISC)) || + (protocol == __constant_htons(ETH_P_PPP_SES))) + { + struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); + unsigned short *pMagic; +#ifdef __ECOS + unsigned short num; + char *tmp_magic; +#endif + + switch(method) + { + case NAT25_CHECK: + if (ph->sid == 0) + return 0; + return 1; + + case NAT25_INSERT: + if(ph->sid == 0) // Discovery phase according to tag + { + if(ph->code == PADI_CODE || ph->code == PADR_CODE) + { + if (priv->pmib->ethBrExtInfo.addPPPoETag) { + struct pppoe_tag *tag, *pOldTag; + unsigned char tag_buf[40]; + int old_tag_len=0; + + tag = (struct pppoe_tag *)tag_buf; + pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); + if (pOldTag) { // if SID existed, copy old value and delete it + old_tag_len = ntohs(pOldTag->tag_len); + if (old_tag_len+TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN > sizeof(tag_buf)) { + DEBUG_ERR("SID tag length too long!\n"); + return -1; + } + + memcpy(tag->tag_data+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN, + pOldTag->tag_data, old_tag_len); + + if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN+old_tag_len) < 0) { + DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n"); + return -1; + } + ph->length = htons(ntohs(ph->length)-TAG_HDR_LEN-old_tag_len); + } + + tag->tag_type = PTT_RELAY_SID; + tag->tag_len = htons(MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN+old_tag_len); + + // insert the magic_code+client mac in relay tag +#ifdef __ECOS + num = htons(MAGIC_CODE); + tmp_magic = (char *)# + memcpy(tag->tag_data, tmp_magic, 2); +#else + pMagic = (unsigned short *)tag->tag_data; + *pMagic = htons(MAGIC_CODE); +#endif + memcpy(tag->tag_data+MAGIC_CODE_LEN, skb->data+ETH_ALEN, ETH_ALEN); + + //Add relay tag + if(__nat25_add_pppoe_tag(skb, tag) < 0) + return -1; + + DEBUG_INFO("NAT25: Insert PPPoE, forward %s packet\n", + (ph->code == PADI_CODE ? "PADI" : "PADR")); + } + else { // not add relay tag + if (priv->pppoe_connection_in_progress && + memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) { + DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n"); + return -2; + } + + if (priv->pppoe_connection_in_progress == 0) + memcpy(priv->pppoe_addr, skb->data+ETH_ALEN, ETH_ALEN); + + priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE; + } + } + else + return -1; + } + else // session phase + { + DEBUG_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name); + + __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid)); + + __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); + + __nat25_db_print(priv); + + if (!priv->pmib->ethBrExtInfo.addPPPoETag && + priv->pppoe_connection_in_progress && + !memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) + priv->pppoe_connection_in_progress = 0; + } + return 0; + + case NAT25_LOOKUP: + if(ph->code == PADO_CODE || ph->code == PADS_CODE) + { + if (priv->pmib->ethBrExtInfo.addPPPoETag) { + struct pppoe_tag *tag; + unsigned char *ptr; + unsigned short tagType, tagLen; + int offset=0; + + if((ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID))) == 0) { + DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n"); + return -1; + } + + tag = (struct pppoe_tag *)ptr; + tagType = (unsigned short)((ptr[0] << 8) + ptr[1]); + tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]); + + if((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN))) { + DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen); + return -1; + } + +#ifdef __ECOS + memcpy(&num, tag->tag_data, 2); + pMagic = # +#else + pMagic = (unsigned short *)tag->tag_data; +#endif + if (*pMagic != htons(MAGIC_CODE)) { + DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n", + (ph->code == PADO_CODE ? "PADO" : "PADS")); + return -1; + } + + memcpy(skb->data, tag->tag_data+MAGIC_CODE_LEN, ETH_ALEN); + + if (tagLen > MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN) + offset = TAG_HDR_LEN; + + if (skb_pull_and_merge(skb, ptr+offset, TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset) < 0) { + DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n"); + return -1; + } + ph->length = htons(ntohs(ph->length)-(TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset)); + if (offset > 0) + tag->tag_len = htons(tagLen-MAGIC_CODE_LEN-RTL_RELAY_TAG_LEN); + + DEBUG_INFO("NAT25: Lookup PPPoE, forward %s Packet from %s\n", + (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name); + } + else { // not add relay tag + if (!priv->pppoe_connection_in_progress) { + DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n"); + return -1; + } + memcpy(skb->data, priv->pppoe_addr, ETH_ALEN); + priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE; + } + } + else { + if(ph->sid != 0) + { + DEBUG_INFO("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name); + __nat25_generate_pppoe_network_addr(networkAddr, skb->data+ETH_ALEN, &(ph->sid)); + + __nat25_db_network_lookup_and_replace(priv, skb, networkAddr); + + __nat25_db_print(priv); + } + else + return -1; + + } + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle EAP frame */ + /*---------------------------------------------------*/ + else if(protocol == __constant_htons(0x888e)) + { + switch(method) + { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: + return 0; + + case NAT25_LOOKUP: + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle LLTD frame */ + /*---------------------------------------------------*/ + else if(protocol == __constant_htons(0x88d9)) + { + switch(method) + { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: + return 0; + + case NAT25_LOOKUP: + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle C-Media proprietary frame */ + /*---------------------------------------------------*/ + else if((protocol == __constant_htons(0xe2ae)) || + (protocol == __constant_htons(0xe2af))) + { + switch(method) + { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: + return 0; + + case NAT25_LOOKUP: + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle IPV6 frame */ + /*---------------------------------------------------*/ +#ifdef CL_IPV6_PASS + else if(protocol == __constant_htons(ETH_P_IPV6)) + { + struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); + + if (sizeof(*iph) >= (skb->len - ETH_HLEN)) + { + DEBUG_WARN("NAT25: malformed IPv6 packet !\n"); + return -1; + } + + switch(method) + { + case NAT25_CHECK: + if (IS_MCAST(skb->data)) + return 0; + else + return -1; + + case NAT25_INSERT: + { + DEBUG_INFO("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," + " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", + iph->saddr.s6_addr16[0],iph->saddr.s6_addr16[1],iph->saddr.s6_addr16[2],iph->saddr.s6_addr16[3], + iph->saddr.s6_addr16[4],iph->saddr.s6_addr16[5],iph->saddr.s6_addr16[6],iph->saddr.s6_addr16[7], + iph->daddr.s6_addr16[0],iph->daddr.s6_addr16[1],iph->daddr.s6_addr16[2],iph->daddr.s6_addr16[3], + iph->daddr.s6_addr16[4],iph->daddr.s6_addr16[5],iph->daddr.s6_addr16[6],iph->daddr.s6_addr16[7]); + + if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) { +#ifdef __ECOS + __nat25_generate_ipv6_network_addr(networkAddr, (unsigned char *)&iph->saddr); +#else + __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr); +#endif + __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr); + __nat25_db_print(priv); + + if (iph->nexthdr == IPPROTO_ICMPV6 && + skb->len > (ETH_HLEN + sizeof(*iph) + 4)) { +#ifdef __ECOS + unsigned char org_mac[6]; + if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), + skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR, org_mac)) { + u16 *p1 = (u16 *)GET_MY_HWADDR; + u16 *p2 = (u16 *)org_mac; + struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); + ADJUST_CHKSUM(*p1++, *p2++, hdr->icmp6_cksum); + ADJUST_CHKSUM(*p1++, *p2++, hdr->icmp6_cksum); + ADJUST_CHKSUM(*p1, *p2, hdr->icmp6_cksum); + } +#else + if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), + skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR)) { + struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); + int len = ntohs(iph->payload_len); + hdr->icmp6_cksum = 0; + hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr, + len, + IPPROTO_ICMPV6, + csum_partial((__u8 *)hdr, len, 0)); + } +#endif + } + } + } + return 0; + + case NAT25_LOOKUP: + DEBUG_INFO("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," + " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", + iph->saddr.s6_addr16[0],iph->saddr.s6_addr16[1],iph->saddr.s6_addr16[2],iph->saddr.s6_addr16[3], + iph->saddr.s6_addr16[4],iph->saddr.s6_addr16[5],iph->saddr.s6_addr16[6],iph->saddr.s6_addr16[7], + iph->daddr.s6_addr16[0],iph->daddr.s6_addr16[1],iph->daddr.s6_addr16[2],iph->daddr.s6_addr16[3], + iph->daddr.s6_addr16[4],iph->daddr.s6_addr16[5],iph->daddr.s6_addr16[6],iph->daddr.s6_addr16[7]); + +#ifdef __ECOS + __nat25_generate_ipv6_network_addr(networkAddr, (unsigned char *)&iph->daddr); +#else + __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr); +#endif + if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) { +#ifdef SUPPORT_RX_UNI2MCAST + if (iph->daddr.s6_addr[0] == 0xff) + convert_ipv6_mac_to_mc(skb); +#endif + } + return 0; + + default: + return -1; + } + } +#endif + + /*---------------------------------------------------*/ + /* Handle all other unknown format */ + /*---------------------------------------------------*/ + else + { + DEBUG_INFO("NAT25: Unknown protocol: 0x%04x\n", ntohs(protocol)); + switch(method) + { + case NAT25_CHECK: + if (IS_MCAST(skb->data)) + return 0; + else + return -1; + + case NAT25_INSERT: + if (memcmp(skb->data+ETH_ALEN, GET_MY_HWADDR, ETH_ALEN) && + memcmp(skb->data+ETH_ALEN, priv->br_mac, ETH_ALEN)) + { + if (memcmp(skb->data+ETH_ALEN, priv->ukpro_mac, ETH_ALEN)) { + memcpy(priv->ukpro_mac, skb->data+ETH_ALEN, ETH_ALEN); + priv->ukpro_mac_valid = 1; + DEBUG_INFO("NAT25: Insert unknown protocol, MAC=%02x%02x%02x%02x%02x%02x\n", + priv->ukpro_mac[0], priv->ukpro_mac[1], priv->ukpro_mac[2], + priv->ukpro_mac[3], priv->ukpro_mac[4], priv->ukpro_mac[5]); + } + } + return 0; + + case NAT25_LOOKUP: + // replace the destination mac address + if (priv->ukpro_mac_valid) { + memcpy(skb->data, priv->ukpro_mac, ETH_ALEN); + DEBUG_INFO("NAT25: Lookup unknown protocol, MAC=%02x%02x%02x%02x%02x%02x\n", + priv->ukpro_mac[0], priv->ukpro_mac[1], priv->ukpro_mac[2], + priv->ukpro_mac[3], priv->ukpro_mac[4], priv->ukpro_mac[5]); + } + return 0; + + default: + return -1; + } + } +} + + +int nat25_handle_frame(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ +#ifdef NOT_RTK_BSP + /* not check EAPOL key because it is not inserted into DB */ + if ( (*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(0x888e)) ) + return 0; +#endif +#ifdef BR_EXT_DEBUG + if((!priv->pmib->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1))) + { + panic_printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n", + skb->data[0], + skb->data[1], + skb->data[2], + skb->data[3], + skb->data[4], + skb->data[5], + skb->data[6], + skb->data[7], + skb->data[8], + skb->data[9], + skb->data[10], + skb->data[11]); + } +#endif + + if(!(skb->data[0] & 1)) + { + int is_vlan_tag=0, i, retval=0; + unsigned short vlan_hdr=0; + + if (*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_8021Q)) { + is_vlan_tag = 1; + vlan_hdr = *((unsigned short *)(skb->data+ETH_ALEN*2+2)); + for (i=0; i<6; i++) + *((unsigned short *)(skb->data+ETH_ALEN*2+2-i*2)) = *((unsigned short *)(skb->data+ETH_ALEN*2-2-i*2)); + skb_pull(skb, 4); + } + + if (!priv->pmib->ethBrExtInfo.nat25_disable +#ifdef MULTI_MAC_CLONE + && ((ACTIVE_ID == 0) || (ACTIVE_ID > 0 && priv->pshare->mclone_sta[ACTIVE_ID-1].usedStaAddrId != 0xff)) +#endif + ) + { + /* + * This function look up the destination network address from + * the NAT2.5 database. Return value = -1 means that the + * corresponding network protocol is NOT support. + */ + if (!priv->pmib->ethBrExtInfo.nat25sc_disable && + (*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_IP)) && + !memcmp(priv->scdb_ip, skb->data+ETH_HLEN+16, 4)) { + memcpy(skb->data, priv->scdb_mac, ETH_ALEN); +#ifdef MULTI_MAC_CLONE + mclone_dhcp_caddr(priv, skb); +#endif + } + else + retval = nat25_db_handle(priv, skb, NAT25_LOOKUP); + } + else { + if (((*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_IP)) && + !memcmp(priv->br_ip, skb->data+ETH_HLEN+16, 4)) || + ((*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_ARP)) && + !memcmp(priv->br_ip, skb->data+ETH_HLEN+24, 4))) { + // for traffic to upper TCP/IP + retval = nat25_db_handle(priv, skb, NAT25_LOOKUP); + } + } + + if (is_vlan_tag) { + skb_push(skb, 4); + for (i=0; i<6; i++) + *((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2)); + *((unsigned short *)(skb->data+ETH_ALEN*2)) = __constant_htons(ETH_P_8021Q); + *((unsigned short *)(skb->data+ETH_ALEN*2+2)) = vlan_hdr; + } + + if(retval == -1) { + DEBUG_ERR("NAT25: Lookup fail!\n"); + return -1; + } + } +#ifdef MULTI_MAC_CLONE + else if ((skb!=NULL) && (skb->data[0]==0xff) + && (*((unsigned short *)(skb->data+ETH_ALEN*2))==__constant_htons(ETH_P_IP))) + mclone_dhcp_caddr(priv, skb); +#endif + + return 0; +} + + +void mac_clone(struct rtl8192cd_priv *priv, unsigned char *addr) +{ +#ifdef __KERNEL__ + struct sockaddr sa; + memcpy(sa.sa_data, addr, ETH_ALEN); +#endif + + DEBUG_INFO("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); +#ifdef __KERNEL__ + rtl8192cd_set_hwaddr(priv->dev, &sa); +#else + rtl8192cd_set_hwaddr(priv->dev, (void *)addr); +#endif +} + +#ifdef MULTI_MAC_CLONE +unsigned char mclone_find_staFixedAddr(struct rtl8192cd_priv *priv) +{ + unsigned char i; + + for (i=0; ipshare->mclone_sta_fixed_addr[i].used == 0) + return i; + } + return 0xff; +} + +unsigned char FindWiFiSta(struct rtl8192cd_priv *inPriv, unsigned char *addr) +{ + struct rtl8192cd_priv *priv; + struct list_head *phead, *plist; + struct stat_info *pstat; + unsigned char idx=0; + + if (inPriv ==NULL){ + return 0; + } + + priv = GET_ROOT(inPriv); + + phead = &priv->asoc_list; + plist = phead->next; + + for (idx=0; idx<=RTL8192CD_NUM_VWLAN; idx++) { + while( ( (((GET_MIB(priv))->dot11OperationEntry.opmode) & WIFI_AP_STATE) == WIFI_AP_STATE ) && (plist != phead)) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + if (pstat && (!memcmp(addr, pstat->hwaddr, ETH_ALEN)) ){ + return 1; + } + } +#ifdef MBSSID + priv = GET_VAP_PRIV(GET_ROOT(priv), idx); + phead = &priv->asoc_list; + plist = phead->next; +#else + break; +#endif + } + + return 0; +} + +int mclone_find_unused_id(struct rtl8192cd_priv *priv) +{ + int i=0; + for (i=0; ipshare->mclone_sta[i].priv == NULL) + return i+1; + } + return -1; +} + +//direction-- SA:1, DA:2, donotcare:0 +int mclone_find_address(struct rtl8192cd_priv *priv, unsigned char *addr, struct sk_buff *pskb, unsigned char direction) +{ + int i; + + if (direction == MAC_CLONE_SA_FIND){ + if ((pskb == NULL) || + #ifdef __ECOS + (pskb && *(unsigned int *)&(pskb->cb[8]) == 0x86518190) + #else + (pskb && *(unsigned int *)&(pskb->cb[40]) == 0x86518192) + #endif + ) { + // from wifi, src MAC A1 -> A1' + // compare with mclone_sta[].sa_addr + for (i=0; ipshare->mclone_sta[i].priv) && priv->pshare->mclone_sta[i].usedStaAddrId!=0xff + && (!memcmp(addr, priv->pshare->mclone_sta[i].sa_addr, ETH_ALEN))) { + return i+1; + } + } + }else{ + // from ethernet, src MAC A1 -> A1 + // compare with mclone_sta[].hwaddr + // printk("it does not come from wifi%02x%02x%02x%02x%02x%02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + } + }else if (direction == MAC_CLONE_MSA_FIND && pskb){ + for (i=0; ipshare->mclone_sta[i].usedStaAddrId!=0xff && + !memcmp(addr, priv->pshare->mclone_sta[i].hwaddr, ETH_ALEN)) + return i+1; + } + }else if (direction == MAC_CLONE_DA_FIND && pskb){ + } + + if (!memcmp(addr, priv->pmib->dot11OperationEntry.hwaddr, ETH_ALEN)) + return 0; + + for (i=0; ipshare->mclone_sta[i].priv) && (!memcmp(addr, priv->pshare->mclone_sta[i].hwaddr, ETH_ALEN)) ) + return i+1; + } + + return -1; +} +#endif + +int mac_clone_handle_frame(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + struct stat_info *pstat=NULL; + if(priv->pmib->ethBrExtInfo.macclone_enable && !priv->macclone_completed) + { + if(!(skb->data[ETH_ALEN] & 1)) //// check any other particular MAC add + { +#ifdef MULTI_MAC_CLONE + #ifdef __ECOS + struct net_device* eth0_dev=rtl_getDevByName("eth0"); + memcpy(priv->br_mac,eth0_dev->dev_addr,6); + STADEBUG("macclone_completed =1 \n\n"); + priv->macclone_completed = 1; + #else + #ifdef __KERNEL__ + struct net_bridge_port *br_port = GET_BR_PORT(priv->dev); + + if (br_port) { + memcpy(priv->br_mac, br_port->br->dev->dev_addr, MACADDRLEN); + STADEBUG("br mac=[%02X%02X%02X:%02X%02X%02X]\n", + priv->br_mac[0],priv->br_mac[1],priv->br_mac[2],priv->br_mac[3],priv->br_mac[4],priv->br_mac[5]); + } + STADEBUG("macclone_completed =1 \n\n"); + priv->macclone_completed = 1; + #endif + #endif +#else // !MULTI_MAC_CLONE + pstat = get_stainfo(priv, skb->data+ETH_ALEN); + if(memcmp(skb->data+ETH_ALEN, GET_MY_HWADDR, ETH_ALEN) && ( + #ifdef __KERNEL__ + GET_BR_PORT(priv->dev) && + #endif + memcmp(skb->data+ETH_ALEN, priv->br_mac, ETH_ALEN) && + (pstat==NULL))) + { + #ifdef __KERNEL__ + #ifdef CONFIG_RTL_ULINKER + if(__nat25_db_query(priv , priv->br_mac)) + #endif + #endif + { +#if defined(CONFIG_PCI_HCI) + //found nat25 entry of br0 + mac_clone(priv, skb->data+ETH_ALEN); + priv->macclone_completed = 1; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_mac_clone(priv, skb->data+ETH_ALEN); +#endif + } + } +#endif // MULTI_MAC_CLONE + } + } + +#ifdef MULTI_MAC_CLONE + if (ACTIVE_ID == 0 && priv->pmib->ethBrExtInfo.macclone_enable) + { + int id; + struct net_bridge_port *br_port; + + priv = GET_DEV_PRIV(skb->dev); + + if (!memcmp(&skb->data[ETH_ALEN], GET_MY_HWADDR, ETH_ALEN)) + return 0; + + if ((skb->data[ETH_ALEN] & 1) || !memcmp(&skb->data[ETH_ALEN], NULL_MAC_ADDR, ETH_ALEN)) + return 0; + + #ifndef __ECOS + br_port = GET_BR_PORT(priv->dev); + #endif + //from br but not br mac + if ( + #ifdef __ECOS + (((Rltk819x_t *)(skb->dev->info))->sc->sc_arpcom.ac_if.if_bridge) && + #else + br_port && + #endif + memcmp(skb->data+ETH_ALEN, priv->br_mac, ETH_ALEN)) + { + if (MCLONE_NUM >= MAX_MAC_CLONE_NUM) + return 1; + + if ((*(unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_PPP_MP)) + return 1; // skip this packet (protocol=0x0008) + + id = mclone_find_unused_id(priv); + + if (id == -1) + return 1; + + MCLONE_NUM++; + + if ( + #ifdef __ECOS + *(unsigned int *)&(skb->cb[8]) == 0x86518190 + #else + *(unsigned int *)&(skb->cb[40]) == 0x86518192 + #endif + ) + { //from wifi AP + unsigned char usedID=0xff; + + memcpy(priv->pshare->mclone_sta[id-1].sa_addr, skb->data+ETH_ALEN, ETH_ALEN);//wifi sta addr + + usedID = mclone_find_staFixedAddr(priv);//should always have free entry + if (usedID == 0xff){ + panic_printk("clone mac -- should always have value for wifi sta addr, err!!!!\n"); + } else { + panic_printk("clone mac -- wifi sta addr: %d!!!!\n", usedID); + priv->pshare->mclone_sta_fixed_addr[usedID].used =1; + } + memcpy(priv->pshare->mclone_sta[id-1].hwaddr, priv->pshare->mclone_sta_fixed_addr[usedID].clone_addr, ETH_ALEN);//wifi sta addr + priv->pshare->mclone_sta[id-1].usedStaAddrId = usedID; + //memcpy(skb->data+ETH_ALEN, priv->pshare->mclone_sta[id-1].hwaddr, MACADDRLEN);//replace the src mac + } else { + memcpy(priv->pshare->mclone_sta[id-1].hwaddr, skb->data+ETH_ALEN, ETH_ALEN); + } + + priv->pshare->mclone_sta[id-1].priv = priv; + + #ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->McloneSetMBSSIDHandler(priv, priv->pshare->mclone_sta[id-1].hwaddr, (id-1)); + else + #endif + mclone_set_mbssid(priv, priv->pshare->mclone_sta[id-1].hwaddr); + + ACTIVE_ID = id; + + panic_printk("clone mac - %02x:%02x:%02x:%02x:%02x:%02x (ACTIVE_ID=%d)\n", + *GET_MY_HWADDR, *(GET_MY_HWADDR+1), *(GET_MY_HWADDR+2), + *(GET_MY_HWADDR+3), *(GET_MY_HWADDR+4), *(GET_MY_HWADDR+5), ACTIVE_ID); + + start_clnt_join(priv); + } + } +#endif + + return 0; +} + + +#define SERVER_PORT 67 +#define CLIENT_PORT 68 +#define DHCP_MAGIC 0x63825363 +#define BROADCAST_FLAG 0x8000 + +#define OPT_CODE 0 +#define OPT_LEN 1 +#define OPT_DATA 2 +#define OPTION_FIELD 0 +#define FILE_FIELD 1 +#define SNAME_FIELD 2 + +/* DHCP option codes (partial list) */ +#define DHCP_PADDING 0x00 +#define DHCP_REQUESTED_IP 0x32 +#define DHCP_OPTION_OVER 0x34 +#define DHCP_CLIENT_ID 0x3d +#define DHCP_END 0xFF + +struct dhcpMessage { + u_int8_t op; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + u_int32_t ciaddr; + u_int32_t yiaddr; + u_int32_t siaddr; + u_int32_t giaddr; + u_int8_t chaddr[16]; + u_int8_t sname[64]; + u_int8_t file[128]; + u_int32_t cookie; + u_int8_t options[308]; /* 312 - cookie */ +}; + + +static int end_option(unsigned char *optionptr) +{ + int i = 0; + + while (optionptr[i] != DHCP_END) { + if (optionptr[i] == DHCP_PADDING) i++; + else i += optionptr[i + OPT_LEN] + 2; + } + return i; +} + + +unsigned char *get_dhcp_option(struct dhcpMessage *packet, int code) +{ + int i, length; + unsigned char *optionptr=NULL; + int over = 0, done = 0, curr = OPTION_FIELD; + + optionptr = packet->options; + i = 0; + length = 308; + while (!done) { + if (i >= length) { + return NULL; + } + + if (optionptr[i + OPT_CODE] == code) { + if (i + 1 + optionptr[i + OPT_LEN] >= length) { + return NULL; + } + return optionptr + i + 2; + } + + switch (optionptr[i + OPT_CODE]) { + case DHCP_PADDING: + i++; + break; + case DHCP_OPTION_OVER: + if (i + 1 + optionptr[i + OPT_LEN] >= length) { + return NULL; + } + over = optionptr[i + 3]; + i += optionptr[OPT_LEN] + 2; + break; + case DHCP_END: + if (curr == OPTION_FIELD && over & FILE_FIELD) { + optionptr = packet->file; + i = 0; + length = 128; + curr = FILE_FIELD; + } else if (curr == FILE_FIELD && over & SNAME_FIELD) { + optionptr = packet->sname; + i = 0; + length = 64; + curr = SNAME_FIELD; + } else done = 1; + break; + default: + i += optionptr[OPT_LEN + i] + 2; + } + } + return NULL; +} + + +void dhcp_add_reqip_option(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + struct iphdr* iph = (struct iphdr *)(skb->data + ETH_HLEN); + udphdr *udph = (udphdr *)((unsigned long)iph + (iph->ihl << 2)); + struct dhcpMessage *dhcph = (struct dhcpMessage *)((unsigned long)udph + sizeof(udphdr)); + unsigned char opt[6] = {0}; + unsigned char *opt_end; + unsigned int end_offset; + + DEBUG_INFO("=======> %s - chaddr : %02X:%02X:%02X:%02X:%02X:%02X\n", __FUNCTION__, dhcph->chaddr[0], dhcph->chaddr[1], + dhcph->chaddr[2], dhcph->chaddr[3], dhcph->chaddr[4], dhcph->chaddr[5]); + + opt[0] = (unsigned char)DHCP_REQUESTED_IP; + opt[1] = (unsigned char)4; +#ifdef __ECOS + rtk_put_unaligned_u32(rtk_get_unaligned_u32((char *)&dhcph->ciaddr), (char *)&opt[2]); + rtk_put_unaligned_u32(0, (char *)&dhcph->ciaddr); +#else + memcpy(&opt[2], &(dhcph->ciaddr), 4); + dhcph->ciaddr = 0; +#endif + + skb_put(skb, 6); + + end_offset = end_option(dhcph->options); + if (end_offset + dhcph->options[OPT_LEN] + 2 + 1 >= 308) { + DEBUG_ERR("*** %s add option error!!! ***\n", __FUNCTION__); + return; + } + + opt_end = (unsigned char *)&(dhcph->options) + end_offset; + + memcpy(opt_end, opt, 6); + dhcph->options[end_offset+6] = DHCP_END; + udph->len = htons(ntohs(udph->len) + 6); + iph->tot_len = htons(ntohs(iph->tot_len) + 6); +} + + +void dhcp_flag_bcast(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + unsigned int ip_check_recalc = 0; + unsigned int udp_check_recalc = 0; + struct iphdr* iph=NULL; + udphdr *udph=NULL; + struct dhcpMessage *dhcph=NULL; + + if(skb == NULL) + return; + + if(!priv->pmib->ethBrExtInfo.dhcp_bcst_disable) { + unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); + + if(protocol == __constant_htons(ETH_P_IP)) { + iph = (struct iphdr *)(skb->data + ETH_HLEN); + + if(iph->protocol == IPPROTO_UDP) { + udph = (udphdr *)((unsigned long)iph + (iph->ihl << 2)); + + if((udph->source == __constant_htons(CLIENT_PORT)) && (udph->dest == __constant_htons(SERVER_PORT))) {// DHCP request + dhcph = (struct dhcpMessage *)((unsigned long)udph + sizeof(udphdr)); + +#ifdef __ECOS + if(rtk_get_unaligned_u32((char *)&dhcph->cookie) == __constant_htonl(DHCP_MAGIC)) +#else + if(dhcph->cookie == __constant_htonl(DHCP_MAGIC)) +#endif + { + if(!(dhcph->flags & htons(BROADCAST_FLAG))) { + DEBUG_INFO("DHCP: change flag of DHCP request to broadcast.\n"); + // or BROADCAST flag + dhcph->flags |= htons(BROADCAST_FLAG); + udp_check_recalc++; + } + +#ifdef __ECOS + if (rtk_get_unaligned_u32((char *)&dhcph->ciaddr) && memcmp(dhcph->chaddr, GET_MY_HWADDR, MACADDRLEN)) +#else + if (dhcph->ciaddr && memcmp(dhcph->chaddr, GET_MY_HWADDR, MACADDRLEN)) +#endif + { + if (!get_dhcp_option(dhcph, DHCP_REQUESTED_IP)) { + dhcp_add_reqip_option(priv, skb); + udp_check_recalc++; + ip_check_recalc++; + } else { +#ifdef __ECOS + rtk_put_unaligned_u32(0, (char *)&dhcph->ciaddr); +#else + dhcph->ciaddr = 0; +#endif + udp_check_recalc++; + } + } + } + } + + if (udph->check && udp_check_recalc) { +#ifdef __ECOS + ADJUST_CHKSUM(dhcph->flags, (dhcph->flags&(~htons(BROADCAST_FLAG))), udph->check); +#else + udph->check = 0; + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, + cpu_to_be16(udph->len), IPPROTO_UDP, + csum_partial((void *)udph, cpu_to_be16(udph->len), 0)); +#endif + } + } + + if (ip_check_recalc) { +#ifdef __ECOS + udph->check = 0; + ADJUST_CHKSUM(iph->tot_len, (iph->tot_len-6), iph->check); +#else + ip_send_check(iph); +#endif + } + } + } +} + + +void dhcp_dst_bcast(struct rtl8192cd_priv * priv,struct sk_buff * skb) +{ + unsigned int ip_check_recalc = 0; + unsigned int udp_check_recalc = 0; + struct iphdr* iph=NULL; + udphdr *udph=NULL; + struct dhcpMessage *dhcph=NULL; + + if(skb == NULL) + return; + + if(!priv->pmib->ethBrExtInfo.dhcp_bcst_disable) { + iph = (struct iphdr *)(skb->data + ETH_HLEN); + + if(iph->protocol == IPPROTO_UDP) { + udph = (udphdr *)((unsigned long)iph + (iph->ihl << 2)); + + if((udph->source == __constant_htons(SERVER_PORT)) && (udph->dest == __constant_htons(CLIENT_PORT))) {// DHCP request + dhcph = (struct dhcpMessage *)((unsigned long)udph + sizeof(udphdr)); + +#ifdef __ECOS + if(rtk_get_unaligned_u32((char *)&dhcph->cookie) == __constant_htonl(DHCP_MAGIC)) +#else + if(dhcph->cookie == __constant_htonl(DHCP_MAGIC)) +#endif + { + + unsigned char *daddr = (unsigned char *)&(iph->daddr); + if((daddr[0] != 0xff)) + { + //we set bootp flags to broadcast, but the DHCP server reply a unicast packets, so we reset the dst to broadcast + daddr[0] = 0xff; + daddr[1] = 0xff; + daddr[2] = 0xff; + daddr[3] = 0xff; + if(skb->data[0] != 0xff) + { + skb->data[0] = 0xff; + skb->data[1] = 0xff; + skb->data[2] = 0xff; + skb->data[3] = 0xff; + skb->data[4] = 0xff; + skb->data[5] = 0xff; + memcpy(&skb->cb[10], skb->data, 6); + } + ip_check_recalc++; + udp_check_recalc++; + } + + } + } + + if (udph->check && udp_check_recalc) { +#ifdef __ECOS + ADJUST_CHKSUM(dhcph->flags, (dhcph->flags&(~htons(BROADCAST_FLAG))), udph->check); +#else + udph->check = 0; + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, + cpu_to_be16(udph->len), IPPROTO_UDP, + csum_partial((void *)udph, cpu_to_be16(udph->len), 0)); +#endif + } + + if (ip_check_recalc) { +#ifdef __ECOS + udph->check = 0; + ADJUST_CHKSUM(iph->tot_len, (iph->tot_len-6), iph->check); +#else + ip_send_check(iph); +#endif + } + } + } +} + + +#ifdef MULTI_MAC_CLONE +int mclone_dhcp_caddr(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + unsigned short protocol; + unsigned char *dhcpopt=NULL; + struct iphdr *iph; + udphdr *udph; + struct dhcpMessage *dhcph; + int active_id; + unsigned int udp_check_recalc = 0; + unsigned int opt61changed =0,posOdd=0; + unsigned char *caddr, *opt61; + unsigned char oldchaddr[ETH_ALEN],oldopt61[ETH_ALEN+2]; + + if(skb == NULL) + return 0; + + iph = (struct iphdr *)(skb->data + ETH_HLEN); + + if(iph->protocol == IPPROTO_UDP) + { + udph = (udphdr *)((unsigned int)iph + (iph->ihl << 2)); + if((udph->source == __constant_htons(CLIENT_PORT)) + && (udph->dest == __constant_htons(SERVER_PORT))) // BootP request + { + dhcph = (struct dhcpMessage *)((unsigned int)udph + sizeof(udphdr)); + if(dhcph->cookie == __constant_htonl(DHCP_MAGIC)) + { + active_id = mclone_find_address(priv, dhcph->chaddr, skb, MAC_CLONE_SA_FIND); + if ((active_id>0) && (priv->pshare->mclone_sta[active_id-1].usedStaAddrId!=0xff)) { + caddr = priv->pshare->mclone_sta[active_id-1].hwaddr; + udp_check_recalc++; + DEBUG_INFO("BootP Request: (active_id %d) %02x:%02x:%02x:%02x:%02x:%02x => %02x:%02x:%02x:%02x:%02x:%02x\n", + active_id, dhcph->chaddr[0], dhcph->chaddr[1], dhcph->chaddr[2], dhcph->chaddr[3], dhcph->chaddr[4], dhcph->chaddr[5], + caddr[0], caddr[1], caddr[2], caddr[3], caddr[4], caddr[5]); + } + else if (!memcmp(dhcph->chaddr, priv->br_mac, ETH_ALEN)) { + caddr = GET_MY_HWADDR; + udp_check_recalc++; + DEBUG_INFO("BootP Request: (br_mac)%02x:%02x:%02x:%02x:%02x:%02x => %02x:%02x:%02x:%02x:%02x:%02x\n", + dhcph->chaddr[0], dhcph->chaddr[1], dhcph->chaddr[2], dhcph->chaddr[3], dhcph->chaddr[4], dhcph->chaddr[5], + caddr[0], caddr[1], caddr[2], caddr[3], caddr[4], caddr[5]); + } + } + } + else if((udph->source == __constant_htons(SERVER_PORT)) + && (udph->dest == __constant_htons(CLIENT_PORT))) // BootP reply + { + dhcph = (struct dhcpMessage *)((unsigned int)udph + sizeof(udphdr)); + if(dhcph->cookie == __constant_htonl(DHCP_MAGIC)) + { + active_id = mclone_find_address(priv, dhcph->chaddr, skb, MAC_CLONE_SA_FIND); + if ((active_id>0) && (priv->pshare->mclone_sta[active_id-1].usedStaAddrId!=0xff)) { + caddr = priv->pshare->mclone_sta[active_id-1].sa_addr; + udp_check_recalc++; + DEBUG_INFO("BootP Response: %02x:%02x:%02x:%02x:%02x:%02x => (active_id %d)%02x:%02x:%02x:%02x:%02x:%02x\n", + dhcph->chaddr[0], dhcph->chaddr[1], dhcph->chaddr[2], dhcph->chaddr[3], dhcph->chaddr[4], dhcph->chaddr[5], + active_id, caddr[0], caddr[1], caddr[2], caddr[3], caddr[4], caddr[5]); + } + else if (!memcmp(dhcph->chaddr, GET_MY_HWADDR, ETH_ALEN) && memcmp(priv->br_mac, NULL_MAC_ADDR, ETH_ALEN)) { + caddr = priv->br_mac; + udp_check_recalc++; + DEBUG_INFO("BootP Response: %02x:%02x:%02x:%02x:%02x:%02x => (br_mac)%02x:%02x:%02x:%02x:%02x:%02x\n", + dhcph->chaddr[0], dhcph->chaddr[1], dhcph->chaddr[2], dhcph->chaddr[3], dhcph->chaddr[4], dhcph->chaddr[5], + caddr[0], caddr[1], caddr[2], caddr[3], caddr[4], caddr[5]); + } + } + } + + if (udp_check_recalc) { + memcpy(oldchaddr,dhcph->chaddr,ETH_ALEN); + memcpy(dhcph->chaddr, caddr, ETH_ALEN); + if (((opt61=get_dhcp_option(dhcph, DHCP_CLIENT_ID))!=NULL) + && (*(unsigned char *)(opt61-1)==7) && (opt61[0]==1)) { + DEBUG_INFO("DHCP opt61: %d %02x:%02x:%02x:%02x:%02x:%02x\n", opt61[0], opt61[1], opt61[2], opt61[3], opt61[4], opt61[5], opt61[6]); + + if(0 != ((opt61+1-dhcph->options)%2)) + posOdd=1; + if(posOdd) + memcpy(oldopt61, opt61, ETH_ALEN+2); + else + memcpy(oldopt61, opt61+1, ETH_ALEN); + + memcpy(opt61+1, caddr, ETH_ALEN); + opt61changed =1; + } + if (udph->check) { + #ifdef __ECOS + u16 *p1 = (u16 *)dhcph->chaddr; + u16 *p2 = (u16 *)oldchaddr; + ADJUST_CHKSUM(*p1++, *p2++, udph->check); + ADJUST_CHKSUM(*p1++, *p2++, udph->check); + ADJUST_CHKSUM(*p1, *p2, udph->check); + + if(1==opt61changed) { + if(posOdd) + p1 = (u16 *) opt61; + else + p1 = (u16 *) (opt61+1); + p2 = (u16 *)oldopt61; + ADJUST_CHKSUM(*p1++, *p2++, udph->check); + ADJUST_CHKSUM(*p1++, *p2++, udph->check); + if(posOdd) ADJUST_CHKSUM(*p1++, *p2++, udph->check); + ADJUST_CHKSUM(*p1, *p2, udph->check); + } + #else + udph->check = 0; + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, htons(udph->len), IPPROTO_UDP, + csum_partial((char *)udph, htons(udph->len), 0)); + #endif + } + } + } + + return 1; +} +#endif + +void *scdb_findEntry(struct rtl8192cd_priv *priv, unsigned char *macAddr, + unsigned char *ipAddr) +{ + unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; + struct nat25_network_db_entry *db; + int hash; + +#ifdef __ECOS + __nat25_generate_ipv4_network_addr(networkAddr, (unsigned char *)ipAddr); +#else + __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr); +#endif + hash = __nat25_network_hash(networkAddr); + db = priv->nethash[hash]; + while (db != NULL) + { + if(!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) + return (void *)db; + + db = db->next_hash; + } + return NULL; +} + +#endif // RTK_BR_EXT + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_br_ext.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_br_ext.h new file mode 100755 index 000000000..e8bf4a53e --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_br_ext.h @@ -0,0 +1,49 @@ +/* + * Headler file defines some data structure and macro of bridge extention + * + * $Id: 8192cd_br_ext.h,v 1.1.4.1 2010/07/28 13:15:27 davidhsu Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_BR_EXT_H_ +#define _8192CD_BR_EXT_H_ + +#define NAT25_HASH_BITS 4 +#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS) +#define NAT25_AGEING_TIME 300 + +#ifdef CL_IPV6_PASS +#define MAX_NETWORK_ADDR_LEN 17 +#else +#define MAX_NETWORK_ADDR_LEN 11 +#endif + +struct nat25_network_db_entry +{ + struct nat25_network_db_entry *next_hash; + struct nat25_network_db_entry **pprev_hash; + atomic_t use_count; + unsigned char macAddr[6]; + unsigned long ageing_timer; +#ifdef __ECOS + unsigned int used; +#endif + unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; +}; + +enum NAT25_METHOD { + NAT25_MIN, + NAT25_CHECK, + NAT25_INSERT, + NAT25_LOOKUP, + NAT25_PARSE, + NAT25_MAX +}; + +#endif // _8192CD_BR_EXT_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_cfg.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_cfg.h new file mode 100755 index 000000000..a94bc7f20 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_cfg.h @@ -0,0 +1,2875 @@ +/* + * Headler file defines some configure options and basic types + * + * $Id: 8192cd_cfg.h,v 1.59.2.26 2011/01/10 07:49:07 jerryko Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_CFG_H_ +#define _8192CD_CFG_H_ + +#if defined(CONFIG_RTL_ULINKER_BRSC) +#include "linux/ulinker_brsc.h" +#endif + +//#define _LITTLE_ENDIAN_ +//#define _BIG_ENDIAN_ + +//this is for WLAN HAL driver coexist with not HAL driver for code size reduce +#ifdef CONFIG_RTL_WLAN_HAL_NOT_EXIST +#define CONFIG_WLAN_NOT_HAL_EXIST 1 +#else +#define CONFIG_WLAN_NOT_HAL_EXIST 0//96e_92e, 8881a_92e, 8881a_only, 96d_92er, is only HAL driver +#endif + +#ifdef __MIPSEB__ + +#ifndef _BIG_ENDIAN_ + #define _BIG_ENDIAN_ +#endif + +#ifdef _LITTLE_ENDIAN_ +#undef _LITTLE_ENDIAN_ +#endif +//### add by sen_liu 2011.4.14 CONFIG_NET_PCI defined in V2.4 and CONFIG_PCI +// define now to replace it. However,some modules still use CONFIG_NET_PCI +#ifdef CONFIG_PCI +#define CONFIG_NET_PCI +#endif + +//### end +#endif //__MIPSEB__ + +#ifdef __KERNEL__ +#include + +#if LINUX_VERSION_CODE >= 0x020614 // linux 2.6.20 + #define LINUX_2_6_20_ +#endif + +#if LINUX_VERSION_CODE >= 0x020615 // linux 2.6.21 + #define LINUX_2_6_21_ +#endif + +#if LINUX_VERSION_CODE >= 0x020616 // linux 2.6.22 + #define LINUX_2_6_22_ +#endif + +#if LINUX_VERSION_CODE >= 0x020618 // linux 2.6.24 + #define LINUX_2_6_24_ +#endif + +#if LINUX_VERSION_CODE >= 0x02061B // linux 2.6.27 + #define LINUX_2_6_27_ +#endif + +#if LINUX_VERSION_CODE > 0x020600 + #define __LINUX_2_6__ +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) + #define __LINUX_3_4__ +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + #define __LINUX_3_10__ + #define CONFIG_RTL_PROC_NEW +#endif + +#if defined(LINUX_2_6_20_) || defined(__LINUX_3_4__) +#if defined(CPTCFG_CFG80211_MODULE) && !defined(NOT_RTK_BSP) +#include "../../../../../linux-3.10.32/include/generated/autoconf.h" +#else //CPTCFG_CFG80211_MODULE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) +#include +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) +#include +#else +#include +#endif +#endif //CPTCFG_CFG80211_MODULE +#include +#include +#else +#include +#endif +#endif // __KERNEL__ + +//------------------------------------------------------------- +// Type definition +//------------------------------------------------------------- +#include "typedef.h" + +#ifdef __ECOS + #include + #include + #include + #include +#endif +#ifdef __LINUX_3_4__ // linux 2.6.29 +#define NETDEV_NO_PRIV +#endif + +/* + * Following Definition Sync 2.4/2.6 SDK Definitions + */ + +#if !defined(__LINUX_2_6__) && !defined(__ECOS) + +#if defined(CONFIG_RTL8196B) || defined(CONFIG_RTL8196C) || defined(CONFIG_RTL8198) +#define CONFIG_RTL_819X +#endif +#if defined(CONFIG_RTL8198) +#define CONFIG_RTL_8198 +#endif +#if defined(CONFIG_RTL8196C) +#define CONFIG_RTL_8196C +#endif + +#define BSP_PCIE0_D_CFG0 PCIE0_D_CFG0 +#define BSP_PCIE1_D_CFG0 PCIE0_D_CFG0 +#define BSP_PCIE0_H_CFG PCIE0_H_CFG +#define BSP_PCIE0_H_EXT PCIE0_RC_EXT_BASE +#define BSP_PCIE0_H_MDIO (BSP_PCIE0_H_EXT + 0x00) +#define BSP_PCIE0_H_INTSTR (BSP_PCIE0_H_EXT + 0x04) +#define BSP_PCIE0_H_PWRCR (BSP_PCIE0_H_EXT + 0x08) +#define BSP_PCIE0_H_IPCFG (BSP_PCIE0_H_EXT + 0x0C) +#define BSP_PCIE0_H_MISC (BSP_PCIE0_H_EXT + 0x10) +#define BSP_PCIE1_H_CFG PCIE1_H_CFG +#define BSP_PCIE1_H_EXT PCIE1_RC_EXT_BASE +#define BSP_PCIE1_H_MDIO (BSP_PCIE1_H_EXT + 0x00) +#define BSP_PCIE1_H_INTSTR (BSP_PCIE1_H_EXT + 0x04) +#define BSP_PCIE1_H_PWRCR (BSP_PCIE1_H_EXT + 0x08) +#define BSP_PCIE1_H_IPCFG (BSP_PCIE1_H_EXT + 0x0C) +#define BSP_PCIE1_H_MISC (BSP_PCIE1_H_EXT + 0x10) + +#endif // !defined(__LINUX_2_6__) + +#ifdef __ECOS +//add macro for Realsil WLAN modification +//move the macro definition to cdl file now +//#ifndef CONFIG_RTL_819X_ECOS +//#define CONFIG_RTL_819X_ECOS +//#endif +#endif + +#if !defined(__ECOS) && !(defined(CONFIG_OPENWRT_SDK) && defined(__LINUX_3_10__)) //eric-sync ?? +#define CONFIG_RTL_CUSTOM_PASSTHRU +#endif + +#ifdef CONFIG_RTL_819X_ECOS +#define CONFIG_RTL_CUSTOM_PASSTHRU +#define CONFIG_RTL_CUSTOM_PASSTHRU_PPPOE +#endif + +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU) +//#define CONFIG_RTL_CUSTOM_PASSTHRU_PPPOE + +#define IP6_PASSTHRU_MASK 0x1 +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU_PPPOE) +#define PPPOE_PASSTHRU_MASK 0x1<<1 +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT)||defined (CONFIG_RTL_8881A) +#define WISP_WLAN_IDX_MASK 0xF0 +#define WISP_WLAN_IDX_RIGHT_SHIFT 4 +#endif + +#endif /* CONFIG_RTL_CUSTOM_PASSTHRU */ + +#if defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1) +#if defined(CONFIG_RTL_92D_SUPPORT) +#define CONFIG_RTL_DUAL_PCIESLOT_BIWLAN_D 1 +#else +#define CONFIG_RTL_DUAL_PCIESLOT_BIWLAN 1 +#endif +#endif + +#if defined(CONFIG_RTL_92D_DMDP) \ +|| defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN)\ +|| (defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_WLAN_HAL_8881A)) \ +|| (defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1)) +#define CONCURRENT_MODE + +#if defined(CONFIG_RTL_92D_DMDP) && !defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN) && !defined(CONFIG_RTL_92C_SUPPORT) && !defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN_D) +#define DUALBAND_ONLY +#endif +#endif + + +#ifdef CONFIG_RTK_VOIP_BOARD + #define RTL_MAX_PCIE_SLOT_NUM 1 + #define RTL_USED_PCIE_SLOT 0 +#elif defined(CONFIG_RTL_8198) + #define RTL_MAX_PCIE_SLOT_NUM 2 + #ifdef CONFIG_SLOT_0_92D + #define RTL_USED_PCIE_SLOT 0 + #else + #define RTL_USED_PCIE_SLOT 1 + #endif +#elif defined(CONFIG_RTL_8197D) || defined(CONFIG_RTL_8197DL) || defined(CONFIG_RTL_8198C) + #define RTL_MAX_PCIE_SLOT_NUM 2 + #ifdef CONFIG_SLOT_0_92D + #define RTL_USED_PCIE_SLOT 0 + #elif defined(CONFIG_USE_PCIE_SLOT_1) + #define RTL_USED_PCIE_SLOT 1 + #else + #define RTL_USED_PCIE_SLOT 0 + #endif +#else + #define RTL_MAX_PCIE_SLOT_NUM 1 + #define RTL_USED_PCIE_SLOT 0 +#endif + +#ifdef CONFIG_RTK_MESH +#include "../mesh_ext/mesh_cfg.h" +#define RTL_MESH_TXCACHE +#define RTK_MESH_MANUALMETRIC +#define RTK_MESH_AODV_STANDALONE_TIMER +//#define RTK_MESH_REDIRECT_TO_ROOT +#define RTK_MESH_REMOVE_PATH_AFTER_AODV_TIMEOUT +#endif + +#if defined(CONFIG_RTL8196B) || defined(CONFIG_RTL_819X) + #if defined(CONFIG_RTL8196B_AP_ROOT) || defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196B_GW) || defined(CONFIG_RTL_8196C_GW) || defined(CONFIG_RTL_8198_GW) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196B_TLD) || defined(CONFIG_RTL8196C_AP_ROOT) || defined(CONFIG_RTL8196C_AP_HCM) || defined(CONFIG_RTL8198_AP_ROOT) || defined(CONFIG_RTL_8198_AP_ROOT) || defined(CONFIG_RTL8196C_CLIENT_ONLY) || defined(CONFIG_RTL_8198_NFBI_BOARD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) || defined(CONFIG_RTL_8196C_iNIC) || defined(CONFIG_RTL_8198_INBAND_AP) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_8198B) || defined(__ECOS) || defined(CONFIG_RTL_8198C) + #define USE_RTL8186_SDK + #endif +#endif + +#if !defined(_BIG_ENDIAN_) && !defined(_LITTLE_ENDIAN_) + #error "Please specify your ENDIAN type!\n" +#elif defined(_BIG_ENDIAN_) && defined(_LITTLE_ENDIAN_) + #error "Only one ENDIAN should be specified\n" +#endif + +#define PCI_CONFIG_COMMAND (wdev->conf_addr+4) +#define PCI_CONFIG_LATENCY (wdev->conf_addr+0x0c) +#define PCI_CONFIG_BASE0 (wdev->conf_addr+0x10) +#define PCI_CONFIG_BASE1 (wdev->conf_addr+0x18) + +#define MAX_NUM(_x_, _y_) (((_x_)>(_y_))? (_x_) : (_y_)) +#define MIN_NUM(_x_, _y_) (((_x_)<(_y_))? (_x_) : (_y_)) + +#define POWER_MIN_CHECK(a,b) (((a) > (b)) ? (b) : (a)) +#define POWER_RANGE_CHECK(val) (((s1Byte)(val) > 0x3f)? 0x3f : (((s1Byte)(val) < 0) ? 0 : (s1Byte)(val))) +#define COUNT_SIGN_OFFSET(val, oft) (((oft & 0x08) == 0x08)? (val - (0x10 - oft)) : (val + oft)) + +//------------------------------------------------------------- +// Driver version information +//------------------------------------------------------------- +#define DRV_VERSION_H 1 +#define DRV_VERSION_L 7 +#define DRV_RELDATE "2017-03-08" +#define DRV_NAME "Realtek WLAN driver" + + +//------------------------------------------------------------- +// Will check type for endian issue when access IO and memory +//------------------------------------------------------------- +#define CHECK_SWAP + + +//------------------------------------------------------------- +// Defined when include proc file system +//------------------------------------------------------------- +#define INCLUDE_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(INCLUDE_PROC_FS) + #define _INCLUDE_PROC_FS_ +#endif + + +//------------------------------------------------------------- +// Debug function +//------------------------------------------------------------- +//#define _DEBUG_RTL8192CD_ // defined when debug print is used +#define _IOCTL_DEBUG_CMD_ // defined when read/write register/memory command is used in ioctl + + +//------------------------------------------------------------- +// Defined when internal DRAM is used for sw encryption/decryption +//------------------------------------------------------------- +#ifdef __MIPSEB__ + // disable internal ram for nat speedup + //#define _USE_DRAM_ +#endif + + +//------------------------------------------------------------- +// Support 8188C/8192C test chip +//------------------------------------------------------------- +#if !defined(CONFIG_RTL8196B_GW_8M) //&&!defined(CONFIG_RTL_92D_SUPPORT) +#define TESTCHIP_SUPPORT +#endif + +//------------------------------------------------------------- +// Support software tx queue +// ------------------------------------------------------------ +#ifdef CONFIG_PCI_HCI +#define SW_TX_QUEUE +#endif + +//------------------------------------------------------------- +// RF MIMO SWITCH +// ------------------------------------------------------------ +#ifdef CONFIG_PCI_HCI +#define RF_MIMO_SWITCH +#define IDLE_T0 (10*HZ) +#endif + +//------------------------------------------------------------- +// Support Tx Report +//------------------------------------------------------------- +#define TXREPORT +#ifdef TXREPORT +#define DETECT_STA_EXISTANCE +#endif +//#define LEAVESTADETECT + + +//------------------------------------------------------------- +// PCIe power saving function +//------------------------------------------------------------- +#ifdef CONFIG_PCIE_POWER_SAVING +#if !defined(CONFIG_NET_PCI) && !defined(CONFIG_RTL_8196CS) && !defined(CONFIG_RTL_88E_SUPPORT) +#define PCIE_POWER_SAVING +#endif + +#endif + +#ifdef _SINUX_ +#define PCIE_POWER_SAVING +#endif + +#ifdef PCIE_POWER_SAVING + #define GPIO_WAKEPIN + #define FIB_96C +// #define PCIE_POWER_SAVING_DEBUG +// #define ASPM_ENABLE +#ifdef PCIE_POWER_SAVING_DEBUG + #define PCIE_L2_ENABLE +#endif + +#define CONFIG_SLOT0H 0xb8b00000 +#define CONFIG_SLOT0S 0xb8b10000 +#define CONFIG_SLOT1H 0xb8b20000 +#define CONFIG_SLOT1S 0xb8b30000 + + +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) +#define CFG_92C_SLOTH CONFIG_SLOT0H +#define CFG_92C_SLOTS CONFIG_SLOT0S +#if (RTL_USED_PCIE_SLOT==1) +#define CFG_92D_SLOTH CONFIG_SLOT1H +#define CFG_92D_SLOTS CONFIG_SLOT1S +#else +#define CFG_92D_SLOTH CONFIG_SLOT0H +#define CFG_92D_SLOTS CONFIG_SLOT0S +#endif +#elif defined(CONFIG_RTL_8196C) +#define CFG_92C_SLOTH CONFIG_SLOT0H +#define CFG_92C_SLOTS CONFIG_SLOT0S +#define CFG_92D_SLOTH CONFIG_SLOT0H +#define CFG_92D_SLOTS CONFIG_SLOT0S +#endif + + +#endif + + +//------------------------------------------------------------- +// WDS function support +//------------------------------------------------------------- +#if defined(CONFIG_RTL_WDS_SUPPORT) +#define WDS +// #define LAZY_WDS +#endif + + +//------------------------------------------------------------- +// Pass EAP packet by event queue +//------------------------------------------------------------- +#define EAP_BY_QUEUE +#undef EAPOLSTART_BY_QUEUE // jimmylin: don't pass eapol-start up + // due to XP compatibility issue +//#define USE_CHAR_DEV +#define USE_PID_NOTIFY + + +//------------------------------------------------------------- +// WPA Supplicant +//------------------------------------------------------------- +//#define WIFI_WPAS + +#ifdef WIFI_WPAS +#ifndef WIFI_HAPD +#define WIFI_HAPD +#endif + +#ifndef CLIENT_MODE +#define CLIENT_MODE +#endif +#endif + +#ifdef WIFI_WPAS_CLI +#define WIFI_WPAS +#define RF_MIMO_PS +//#define IDLE_T0 (3*HZ) + +#ifndef CLIENT_MODE +#define CLIENT_MODE +#endif +#endif + +//------------------------------------------------------------- +// Client mode function support +//------------------------------------------------------------- +#if defined(CONFIG_RTL_CLIENT_MODE_SUPPORT) +#define CLIENT_MODE +#endif + +#ifdef CLIENT_MODE + #define RTK_BR_EXT // Enable NAT2.5 and MAC clone support + #define CL_IPV6_PASS // Enable IPV6 pass-through. RTK_BR_EXT must be defined +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + #undef RTK_BR_EXT + #undef CL_IPV6_PASS +#endif +#endif + +#if defined(CONFIG_RTL_MULTI_CLONE_SUPPORT) + #define MULTI_MAC_CLONE // Enable mac clone to multiple Ethernet MAC address +#endif +#ifdef MULTI_MAC_CLONE +#define REPEATER_TO RTL_SECONDS_TO_JIFFIES(10) +#endif + +#ifdef CONFIG_RTL_SUPPORT_MULTI_PROFILE + #define SUPPORT_MULTI_PROFILE // support multiple AP profile +#endif + + +//------------------------------------------------------------- +// Defined when WPA2 is used +//------------------------------------------------------------- +#define RTL_WPA2 +#define RTL_WPA2_PREAUTH + +//------------------------------------------------------------- +// MCR test +//------------------------------------------------------------- +//#define MCR_WIRELESS_EXTEND + + +//------------------------------------------------------------- +// MP test +//------------------------------------------------------------- +#if (!defined(CONFIG_RTL8196B_GW_8M) || defined(CONFIG_RTL8196B_GW_MP)) +#define MP_TEST +#ifdef CONFIG_RTL_92D_SUPPORT +#endif +#endif + + +//------------------------------------------------------------- +// MIC error test +//------------------------------------------------------------- +//#define MICERR_TEST + + +//------------------------------------------------------------- +// Log event +//------------------------------------------------------------- +#define EVENT_LOG + + +//------------------------------------------------------------- +// Tx/Rx data path shortcut +//------------------------------------------------------------- +#define TX_SHORTCUT +#define RX_SHORTCUT +#if defined(CONFIG_RTK_MESH) && defined(RX_SHORTCUT) +#define RX_RL_SHORTCUT +#endif +#ifdef __ECOS +#ifdef RTLPKG_DEVS_ETH_RLTK_819X_BRSC +#define BR_SHORTCUT +#endif +#elif !defined(CONFIG_RTL_FASTBRIDGE) +#ifdef CONFIG_RTL8672 +#ifndef CONFIG_RTL8672_BRIDGE_FASTPATH +//#define BR_SHORTCUT +#endif +#else +#define BR_SHORTCUT //mark_apo +#if 0 //jwj +#if !defined(CONFIG_RTL_8198B) && !defined(CONFIG_RTL8196C_KLD) +#define BR_SHORTCUT_C2 +#define BR_SHORTCUT_C3 +#define BR_SHORTCUT_C4 +#endif +#endif +#endif +#endif +#if defined(CONFIG_RTK_MESH) && defined(TX_SHORTCUT) + #define MESH_TX_SHORTCUT +#endif + +#define TX_SC_ENTRY_NUM 4 +#define RX_SC_ENTRY_NUM 4 + +//Filen +//#define SHORTCUT_STATISTIC + +//------------------------------------------------------------- +// Mininal Memory usage +//------------------------------------------------------------- +#if defined(CONFIG_MEM_LIMITATION) || defined(CONFIG_RTL_NFJROM_MP) +#define WIFI_LIMITED_MEM +#endif + +#ifdef WIFI_LIMITED_MEM +#define WIFI_MIN_IMEM_USAGE // Mininal IMEM usage +#undef TESTCHIP_SUPPORT +#endif + + +//------------------------------------------------------------- +// back to back test +//------------------------------------------------------------- +//#define B2B_TEST + + +//------------------------------------------------------------- +// enable e-fuse read write +//------------------------------------------------------------- +#ifdef CONFIG_ENABLE_EFUSE +#define EN_EFUSE +#endif + + +//------------------------------------------------------------- +// new Auto channel +//------------------------------------------------------------- +#define CONFIG_RTL_NEW_AUTOCH +#define MAC_RX_COUNT_THRESHOLD 200 +#ifdef CONFIG_SDIO_HCI +#define AUTOCH_SS_SPEEDUP +#endif + +//------------------------------------------------------------- +// new IQ calibration for 92c / 88c +//------------------------------------------------------------- +#define CONFIG_RTL_NEW_IQK + + +//------------------------------------------------------------- +// noise control +//------------------------------------------------------------- +#ifdef CONFIG_RTL_92C_SUPPORT +//#define CONFIG_RTL_NOISE_CONTROL_92C +#endif + + +//------------------------------------------------------------- +// Universal Repeater (support AP + Infra client concurrently) +//------------------------------------------------------------- +#if defined(CONFIG_RTL_REPEATER_MODE_SUPPORT) +#define UNIVERSAL_REPEATER +#define SMART_REPEATER_MODE +#define SWITCH_CHAN + +#endif + +//------------------------------------------------------------- +// Check hangup for Tx queue +//------------------------------------------------------------- +//#define CHECK_HANGUP +#ifdef CHECK_HANGUP + #define CHECK_TX_HANGUP 1 + #define CHECK_RX_DMA_ERROR 2 + #define CHECK_RX_TAG_ERROR 4 + #define CHECK_LX_DMA_ERROR 8 + #define CHECK_FW_ERROR 16 + #define FAST_RECOVERY +#endif + + +//------------------------------------------------------------- +// DFS +//------------------------------------------------------------- +#ifdef CONFIG_RTL_DFS_SUPPORT +#define DFS +#endif + + +//------------------------------------------------------------- +// Driver based WPA PSK feature +//------------------------------------------------------------- +#define INCLUDE_WPA_PSK + + +//eric-sync ?? bind with openwrt-sdk ?? +//------------------------------------------------------------- +// NL80211 +//------------------------------------------------------------- +// +#ifdef CONFIG_OPENWRT_SDK +#define NETDEV_NO_PRIV 1 //mark_wrt +#undef EVENT_LOG //mark_wrt + +#if defined(CPTCFG_CFG80211_MODULE) +#define RTK_NL80211 1 +#endif + +#ifdef RTK_NL80211 +//#define CONFIG_NET_PCI +#undef EAP_BY_QUEUE +#undef INCLUDE_WPA_PSK + +#undef BR_SHORTCUT_C2 +#undef BR_SHORTCUT_C3 +#undef BR_SHORTCUT_C4 + +#ifndef CONFIG_RTL_VAP_SUPPORT +#define CONFIG_RTL_VAP_SUPPORT 1 +#endif + +#ifndef CONFIG_RTL_REPEATER_MODE_SUPPORT +#define CONFIG_RTL_REPEATER_MODE_SUPPORT 1 +#endif + +#endif //RTK_NL80211 +#endif //CONFIG_OPENWRT_SDK + +//------------------------------------------------------------- +// RF Fine Tune +//------------------------------------------------------------- +//#define RF_FINETUNE + + +//------------------------------------------------------------- +// Wifi WMM +//------------------------------------------------------------- +#define WIFI_WMM +#ifdef WIFI_WMM + #define WMM_APSD // WMM Power Save + #ifndef WIFI_LIMITED_MEM + #define RTL_MANUAL_EDCA // manual EDCA parameter setting + #endif +#endif + +//------------------------------------------------------------- +// Hotspot 2.0 +//------------------------------------------------------------- +#ifdef CONFIG_RTL_HS2_SUPPORT +#define HS2_SUPPORT +//#define HS2_CLIENT_TEST +#define CONFIG_IEEE80211W +//#define DRVMAC_LB +//#define CONFIG_IEEE80211W_TEST +#endif + +//------------------------------------------------------------- +// Hostapd +//------------------------------------------------------------- +#ifdef CONFIG_RTL_HOSTAPD_SUPPORT +#define WIFI_HAPD +#endif +#ifdef CONFIG_RTL_P2P_SUPPORT +#define P2P_SUPPORT // support for WIFI_Direct +//#define P2P_DEBUGMSG +#endif + +#ifdef CONFIG_PACP_SUPPORT +#define SUPPORT_MONITOR // for packet capture function +#ifndef CONFIG_RTL_COMAPI_WLTOOLS +#define CONFIG_RTL_COMAPI_WLTOOLS +#endif +#endif + +#ifdef CONFIG_RTL_TDLS_SUPPORT +#define TDLS_SUPPORT +#endif + +#ifdef WIFI_HAPD + +//#define HAPD_DRV_PSK_WPS + +#ifndef CONFIG_WEXT_PRIV +#define CONFIG_WEXT_PRIV +#endif + +#ifndef CONFIG_RTL_COMAPI_WLTOOLS +#define CONFIG_RTL_COMAPI_WLTOOLS +#endif + +#ifndef HAPD_DRV_PSK_WPS +#undef EAP_BY_QUEUE +#undef INCLUDE_WPA_PSK +#endif + +#endif + + +//------------------------------------------------------------- +// IO mapping access +//------------------------------------------------------------- +//#define IO_MAPPING + + +//------------------------------------------------------------- +// Wifi Simple Config support +//------------------------------------------------------------- +#define WIFI_SIMPLE_CONFIG +/* WPS2DOTX */ +#define WPS2DOTX +#define OUI_LEN 4 + +#ifdef WPS2DOTX +#define SUPPORT_PROBE_REQ_REASSEM //for AP mode +#define SUPPORT_PROBE_RSP_REASSEM // for STA mode +//#define WPS2DOTX_DEBUG +#endif + +#ifdef WPS2DOTX_DEBUG //0614 for wps2.0 trace +#define SECU_DEBUG(fmt, args...) printk("[secu]%s %d:"fmt, __FUNCTION__,__LINE__, ## args) +#define SME_DEBUG(fmt, args...) printk("[sme]%s %d:"fmt,__FUNCTION__ , __LINE__ , ## args) + +#else +#define SECU_DEBUG(fmt, args...) +#define SME_DEBUG(fmt, args...) +#endif +/* WPS2DOTX */ + +//------------------------------------------------------------- +// Support Multiple BSSID +//------------------------------------------------------------- +#if defined(CONFIG_RTL_VAP_SUPPORT) +#define MBSSID +#endif + +#ifndef NOT_RTK_BSP +#ifdef MBSSID +#if !defined(CONFIG_RTL_SDRAM_GE_32M) && defined(CONFIG_RTL_8196E) +#define RTL8192CD_NUM_VWLAN 1 +#else +#define RTL8192CD_NUM_VWLAN 4 +#endif +#else +#define RTL8192CD_NUM_VWLAN 0 +#endif +#endif // !NOT_RTK_BSP + + +//------------------------------------------------------------- +// Support Tx Descriptor Reservation for each interface +//------------------------------------------------------------- +#ifdef CONFIG_RTL_TX_RESERVE_DESC +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) +#define RESERVE_TXDESC_FOR_EACH_IF +#endif +#endif + + +//------------------------------------------------------------- +// Group BandWidth Control +//------------------------------------------------------------- +#ifdef CONFIG_PCI_HCI +#define GBWC +#endif + + +//------------------------------------------------------------- +// RSSI_MIN Advanced Selection +//------------------------------------------------------------- +#define RSSI_MIN_ADV_SEL + + +//------------------------------------------------------------- +// Support add or remove ACL list at run time +//------------------------------------------------------------- +#define D_ACL + +//------------------------------------------------------------- +// Support 802.11 SNMP MIB +//------------------------------------------------------------- +//#define SUPPORT_SNMP_MIB + + +//------------------------------------------------------------- +// Driver-MAC loopback +//------------------------------------------------------------- +//#define DRVMAC_LB + + +//------------------------------------------------------------- +// Use perfomance profiling +//------------------------------------------------------------- +//#define PERF_DUMP +#ifdef PERF_DUMP +//3 Definition +//Check List Selection +#define PERF_DUMP_INIT_ORI 0 +#define PERF_DUMP_INIT_WLAN_TRX 1 + +//CP3 of MIPS series count event format selection +#define PERF_DUMP_CP3_OLD 0 +#define PERF_DUMP_CP3_NEW 1 + +//3 Control Setting +#define PERF_DUMP_INIT_SELECT PERF_DUMP_INIT_WLAN_TRX + +// TODO: Filen, I am not sure that which type these are for 97D/96E/96D +#if defined(CONFIG_RTL_8881A) +#define PERF_DUMP_CP3_SELECT PERF_DUMP_CP3_NEW +#else +// 96C / ... +#define PERF_DUMP_CP3_SELECT PERF_DUMP_CP3_OLD +#endif + +//Dual Counter mode, only new chip support +#if (PERF_DUMP_CP3_SELECT == PERF_DUMP_CP3_NEW) +#define PERF_DUMP_CP3_DUAL_COUNTER_EN +#else +#undef PERF_DUMP_CP3_DUAL_COUNTER_EN +#endif +#endif //PERF_DUMP + + +//------------------------------------------------------------- +// 1x1 Antenna Diversity +//------------------------------------------------------------- +#if defined (CONFIG_ANT_SWITCH) || defined(CONFIG_RTL_8881A_ANT_SWITCH) || defined(CONFIG_SLOT_0_ANT_SWITCH) || defined(CONFIG_SLOT_1_ANT_SWITCH) +//#define SW_ANT_SWITCH +#define HW_ANT_SWITCH +//#define GPIO_ANT_SWITCH +#ifdef HW_ANT_SWITCH +#define HW_DIV_ENABLE (priv->pshare->rf_ft_var.antHw_enable&1) +#endif +#ifdef SW_ANT_SWITCH +#define SW_DIV_ENABLE (priv->pshare->rf_ft_var.antSw_enable&1) +#endif +#endif + + +//------------------------------------------------------------- +// WPAI performance issue +//------------------------------------------------------------- +#ifdef CONFIG_RTL_WAPI_SUPPORT + //#define IRAM_FOR_WIRELESS_AND_WAPI_PERFORMANCE + #if defined(CONFIG_RTL8192CD) + // if CONFIG_RTL_HW_WAPI_SUPPORT defined, { SWCRYPTO=1: sw wapi; SWCRYPTO=0: hw wapi. } + // if CONFIG_RTL_HW_WAPI_SUPPORT not defined, { SWCRYPTO=1: sw wapi; SWCRYPTO=0: should not be used! } + #define CONFIG_RTL_HW_WAPI_SUPPORT 1 + #endif +#endif + + +//------------------------------------------------------------- +// Use local ring for pre-alloc Rx buffer. +// If no defined, will use kernel skb que +//------------------------------------------------------------- +#ifndef __ECOS +#define RTK_QUE +#endif + + +//------------------------------------------------------------- +//Support IP multicast->unicast +//------------------------------------------------------------- +#ifndef __ECOS +#define SUPPORT_TX_MCAST2UNI +#define MCAST2UI_REFINE +#endif + +#ifdef CONFIG_RTL_819X_ECOS +#define SUPPORT_TX_MCAST2UNI +//#define MCAST2UI_REFINE +#endif + +#ifdef CLIENT_MODE +#define SUPPORT_RX_UNI2MCAST +#endif + +/* for cameo feature*/ +#ifdef CONFIG_RTL865X_CMO + #define IGMP_FILTER_CMO +#endif + +// Support IPV6 multicast->unicast +#ifdef SUPPORT_TX_MCAST2UNI + #define TX_SUPPORT_IPV6_MCAST2UNI +#endif + + +//------------------------------------------------------------- +// Support USB tx rate adaptive +//------------------------------------------------------------- +// define it always for object code release +#if defined(CONFIG_USB) && !defined(NOT_RTK_BSP) + #define USB_PKT_RATE_CTRL_SUPPORT +#endif + + +//------------------------------------------------------------- +// Support Tx AMSDU +//------------------------------------------------------------- +//#define SUPPORT_TX_AMSDU + + +//------------------------------------------------------------- +// Mesh Network +//------------------------------------------------------------- +#ifdef CONFIG_RTK_MESH +#define _MESH_ACL_ENABLE_ + +/*need check Tx AMSDU dependency ; 8196B no support now */ +#ifdef SUPPORT_TX_AMSDU +#define MESH_AMSDU +#endif +//#define MESH_ESTABLISH_RSSI_THRESHOLD +//#define MESH_BOOTSEQ_AUTH +#endif // CONFIG_RTK_MESH + + +//------------------------------------------------------------- +// Realtek proprietary wake up on wlan mode +//------------------------------------------------------------- +//#define RTK_WOW + + +//------------------------------------------------------------- +// Use static buffer for STA private buffer +//------------------------------------------------------------- +#if !defined(CONFIG_RTL8196B_GW_8M) && !defined(CONFIG_WIRELESS_LAN_MODULE) && !defined(WIFI_LIMITED_MEM) +#define PRIV_STA_BUF +#endif + +//------------------------------------------------------------- +// Do not drop packet immediately when rx buffer empty +//------------------------------------------------------------- + +#ifdef __ECOS +#ifdef CONFIG_RTL_DELAY_REFILL +#define DELAY_REFILL_RX_BUF +#endif +#endif + + +#ifdef CONFIG_RTL8190_PRIV_SKB + #define DELAY_REFILL_RX_BUF +#endif + + +//------------------------------------------------------------- +// WiFi 11n 20/40 coexistence +//------------------------------------------------------------- +#define WIFI_11N_2040_COEXIST +#define WIFI_11N_2040_COEXIST_EXT + +//------------------------------------------------------------- +// Add TX power by command +//------------------------------------------------------------- +#define ADD_TX_POWER_BY_CMD + + +//------------------------------------------------------------- +// Do Rx process in tasklet +//------------------------------------------------------------- +//#define RX_TASKLET + + +//------------------------------------------------------------- +// Support external high power PA +//------------------------------------------------------------- +#if defined(CONFIG_SLOT_0_EXT_PA) || defined(CONFIG_SLOT_1_EXT_PA) +#define HIGH_POWER_EXT_PA +#endif + + +//------------------------------------------------------------- +// Support external LNA +//------------------------------------------------------------- +#if defined(CONFIG_SLOT_0_EXT_LNA) || defined(CONFIG_SLOT_1_EXT_LNA) +#define HIGH_POWER_EXT_LNA +#endif + + +//------------------------------------------------------------- +// Cache station info for bridge +//------------------------------------------------------------- +#define RTL_CACHED_BR_STA + + +//------------------------------------------------------------- +// Bridge shortcut for AP to AP case +//------------------------------------------------------------- +#define AP_2_AP_BRSC + +//------------------------------------------------------------- +// Use default keys of WEP (instead of keymapping keys) +//------------------------------------------------------------- +//#define USE_WEP_DEFAULT_KEY + + +//------------------------------------------------------------- +// Auto test support +//------------------------------------------------------------- +//#ifdef CONFIG_RTL_92C_SUPPORT +#define AUTO_TEST_SUPPORT +//#endif + + +//------------------------------------------------------------- +// to prevent broadcast storm attacks +//------------------------------------------------------------- +#define PREVENT_BROADCAST_STORM 1 + +//------------------------------------------------------------- +// to prevent ARP spoofing attacks +//------------------------------------------------------------- +#ifdef __KERNEL__ +#define PREVENT_ARP_SPOOFING +#endif + +#ifdef PREVENT_BROADCAST_STORM +/* + * NOTE: The driver will skip the other broadcast packets if the system free memory is less than FREE_MEM_LOWER_BOUND + * and the broadcast packet amount is larger than BROADCAST_STORM_THRESHOLD in one second period. + */ + +#define BROADCAST_STORM_THRESHOLD 16 +#define FREE_MEM_LOWER_BOUND 800 //uint: KBytes +#endif + + +//------------------------------------------------------------- +// Video streaming refine +//------------------------------------------------------------- +#ifdef CONFIG_RTK_VLC_SPEEDUP_SUPPORT + #define VIDEO_STREAMING_REFINE +#endif + + +//------------------------------------------------------------- +// Rx buffer gather feature +//------------------------------------------------------------- +#define RX_BUFFER_GATHER + +//------------------------------------------------------------- +// A4 client support +//------------------------------------------------------------- +//#define A4_STA + +#if defined(A4_STA) && defined(WDS) + #error "A4_STA and WDS can't be used together\n" +#endif + + +//------------------------------------------------------------- +// Avoid deadlock for SMP(Symmetrical Multi-Processing) architecture +//------------------------------------------------------------- +#if defined(CONFIG_SMP) && !defined(SMP_SYNC) +#define SMP_SYNC +#endif + + +//------------------------------------------------------------- +// NOT use Realtek specified BSP +//------------------------------------------------------------- +//#define NOT_RTK_BSP + + +//------------------------------------------------------------- +// No padding between members in the structure for specified CPU +//------------------------------------------------------------- +//#define PACK_STRUCTURE + + +//------------------------------------------------------------- +// customers proprietary info display +//------------------------------------------------------------- +//#define TLN_STATS + + +//------------------------------------------------------------- +// Tx early mode +//------------------------------------------------------------- +#ifdef CONFIG_RTL_TX_EARLY_MODE_SUPPORT +#ifdef CONFIG_RTL_88E_SUPPORT + #define TX_EARLY_MODE +#endif +#endif + +//------------------------------------------------------------- +// Dynamically switch LNA for 97d High Power in MP mode to pass Rx Test +//------------------------------------------------------------- +#if defined(CONFIG_RTL_819XD) && !defined(CONFIG_RTL_8196D) && defined(CONFIG_HIGH_POWER_EXT_PA) //for 97d High Power only +//#define MP_SWITCH_LNA +#endif + + +//------------------------------------------------------------- +// RTL8188E GPIO Control +//------------------------------------------------------------- +#define RTLWIFINIC_GPIO_CONTROL + +//------------------------------------------------------------- +// General interface of add user defined IE. +//------------------------------------------------------------- +//#define USER_ADDIE + + +//------------------------------------------------------------- +// Tx power limit function +//------------------------------------------------------------- +#ifdef CONFIG_TXPWR_LMT +#define TXPWR_LMT +#ifdef CONFIG_RTL_8812_SUPPORT +#define TXPWR_LMT_8812 +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#define TXPWR_LMT_88E +#endif +#ifdef CONFIG_WLAN_HAL_8881A +#define TXPWR_LMT_8881A +#endif +#ifdef CONFIG_WLAN_HAL_8192EE +#define TXPWR_LMT_92EE +#endif + +#if defined(TXPWR_LMT_8812) || defined(TXPWR_LMT_88E) || defined(CONFIG_WLAN_HAL) +#define TXPWR_LMT_NEWFILE +#endif + +#endif // CONFIG_TXPWR_LMT + +#if 0 +#define PWR_BY_RATE_92E_HP +#endif + +//------------------------------------------------------------- +// RADIUS Accounting supportive functions +//------------------------------------------------------------- +//#define RADIUS_ACCOUNTING + +//------------------------------------------------------------- +// Client mixed mode security +//------------------------------------------------------------- +#ifdef CLIENT_MODE + +#if 1/*def CONFIG_SUPPORT_CLIENT_MIXED_SECURITY*/ +#define SUPPORT_CLIENT_MIXED_SECURITY +#endif + +#endif + +//------------------------------------------------------------- +// FW Test Function +//------------------------------------------------------------- +#ifdef CONFIG_WLAN_HAL +#define CONFIG_OFFLOAD_FUNCTION +#endif + +//------------------------------------------------------------- +// 8814 AP MAC function verification +//------------------------------------------------------------- +#ifdef CONFIG_WLAN_HAL_8814AE +#define HW_FILL_MACID +#define HW_DETEC_POWER_STATE +//#define RTL8814_FPGA_TEMP +//#define DISABLE_BB_RF +//#define CONFIG_8814_AP_MAC_VERI +//#define VERIFY_AP_FAST_EDCA + +#define del_timer_sync del_timer + +#endif + +//------------------------------------------------------------- +// WLAN HAL +//------------------------------------------------------------- +#ifdef CONFIG_WLAN_HAL + +// Add by Eric and Pedro, this compile flag is temp for 8814 FPGA tunning +// Must remove after driver ready +#ifdef RTL8814_FPGA_TEMP +#define DISABLE_BB_RF +#endif + +#ifdef CONFIG_RTL_8198C +#define TRXBD_CACHABLE_REGION +#endif +//#undef CHECK_HANGUP +//#undef FAST_RECOVERY +//#undef SW_TX_QUEUE +//#undef DELAY_REFILL_RX_BUF +#undef RESERVE_TXDESC_FOR_EACH_IF +//#undef CONFIG_NET_PCI +#undef TX_EARLY_MODE +//#undef CONFIG_OFFLOAD_FUNCTION +//#undef PREVENT_BROADCAST_STORM +//#undef DETECT_STA_EXISTANCE +//#undef RX_BUFFER_GATHER +//#undef GBWC +#define _TRACKING_TABLE_FILE +#define AVG_THERMAL_NUM_88XX 4 +//#define WLANHAL_MACDM +#endif + +#if defined(CONFIG_WLAN_HAL_8814AE) && defined(TX_SHORTCUT) +//#define WLAN_HAL_HW_TX_SHORTCUT_REUSE_TXDESC +//#define WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV +// TODO: temporary for only turn on WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV +//#define WLAN_HAL_HW_TX_SHORTCUT_DISABLE_REUSE_TXDESC_FOR_DEBUG + +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV +// TODO: turn on REUSE + HDR_CONV +// TODO: recycle problem (sw desc) for HDR_CONV +#define WLAN_HAL_HW_SEQ +#define WLAN_HAL_HW_AES_IV +#undef TX_SC_ENTRY_NUM +#define TX_SC_ENTRY_NUM 1 +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV +#endif // defined(CONFIG_WLAN_HAL_8814AE) && defined(TX_SHORTCUT) + + +#ifdef CONFIG_RTL_8881A +#define WLAN_HAL_TXDESC_CHECK_ADDR_LEN 1 +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE +//#define BEAMFORMING_SUPPORT 1 +#endif + +//#define WMM_DSCP_C42 + +/*********************************************************************/ +/* some definitions in 8192cd driver, we set them as NULL definition */ +/*********************************************************************/ +#ifdef USE_RTL8186_SDK +#if defined(CONFIG_WIRELESS_LAN_MODULE) || defined(CONFIG_RTL_8198C) +#define __DRAM_IN_865X +#define __IRAM_IN_865X +#else +#define __DRAM_IN_865X __attribute__ ((section(".dram-rtkwlan"))) +#define __IRAM_IN_865X __attribute__ ((section(".iram-rtkwlan"))) +#endif + +#define RTL8190_DIRECT_RX /* For packet RX : directly receive the packet instead of queuing it */ +#define RTL8190_ISR_RX /* process RXed packet in interrupt service routine: It become useful only when RTL8190_DIRECT_RX is defined */ + +#ifndef CONFIG_WIRELESS_LAN_MODULE +#ifndef CONCURRENT_MODE +#define RTL8192CD_VARIABLE_USED_DMEM /* Use DMEM for some critical variables */ +#endif +#endif + +#else // not USE_RTL8186_SDK + +#define __DRAM_IN_865X +#define __IRAM_IN_865X +#endif + + +#undef __MIPS16 +#ifdef __ECOS +#if defined(RTLPKG_DEVS_ETH_RLTK_819X_USE_MIPS16) || !defined(CONFIG_RTL_8198C) +#define __MIPS16 __attribute__ ((mips16)) +#else +#define __MIPS16 +#endif +#else +#if defined(CONFIG_WIRELESS_LAN_MODULE) || defined(CONFIG_RTL_8198C) +#define __MIPS16 +#else +#define __MIPS16 __attribute__ ((mips16)) +#endif +#endif + +#ifdef IRAM_FOR_WIRELESS_AND_WAPI_PERFORMANCE +#ifdef CONFIG_RTL_8198C +#define __IRAM_WLAN_HI //__attribute__ ((section(".iram-wapi"))) +#define __DRAM_WLAN_HI //__attribute__ ((section(".dram-wapi"))) +#else +#define __IRAM_WLAN_HI __attribute__ ((section(".iram-wapi"))) +#define __DRAM_WLAN_HI __attribute__ ((section(".dram-wapi"))) +#endif +#endif + + +//------------------------------------------------------------- +// Kernel 2.6 specific config +//------------------------------------------------------------- +#ifdef __LINUX_2_6__ + +#define USE_RLX_BSP +#ifndef CONCURRENT_MODE +#define RTL8192CD_VARIABLE_USED_DMEM +#endif + +#ifndef RX_TASKLET + #define RX_TASKLET +#endif + +#endif + + +#if 0 +//------------------------------------------------------------- +// TR define flag +//------------------------------------------------------------- +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196C_EC) + +#ifndef INCLUDE_WPA_PSK + #define INCLUDE_WPA_PSK +#endif + +#ifdef UNIVERSAL_REPEATER + #undef UNIVERSAL_REPEATER +#endif + +#ifdef CLIENT_MODE + #undef CLIENT_MODE + #undef RTK_BR_EXT +#endif + +#ifndef WIFI_SIMPLE_CONFIG + #define WIFI_SIMPLE_CONFIG +#endif + +#ifdef GBWC + #undef GBWC +#endif + +#ifdef SUPPORT_SNMP_MIB + #undef SUPPORT_SNMP_MIB +#endif + +#endif // CONFIG_RTL8196B_TR + + +//------------------------------------------------------------- +// AC define flag +//------------------------------------------------------------- +#ifdef CONFIG_RTL865X_AC + +#ifndef INCLUDE_WPA_PSK + #define INCLUDE_WPA_PSK +#endif + +#ifdef UNIVERSAL_REPEATER + #undef UNIVERSAL_REPEATER +#endif + +#ifdef CLIENT_MODE + #undef CLIENT_MODE + #undef RTK_BR_EXT +#endif + +#ifndef WIFI_SIMPLE_CONFIG + #define WIFI_SIMPLE_CONFIG +#endif + +#ifdef GBWC + #undef GBWC +#endif + +#ifdef SUPPORT_SNMP_MIB + #undef SUPPORT_SNMP_MIB +#endif + +#endif // CONFIG_RTL865X_AC +#endif //#if 0 + + +//------------------------------------------------------------- +// Config Little Endian CPU +//------------------------------------------------------------- +#ifdef _LITTLE_ENDIAN_ + +#ifndef NOT_RTK_BSP +#define NOT_RTK_BSP +#endif + +#ifndef CONFIG_WIRELESS_LAN_MODULE +#define CONFIG_WIRELESS_LAN_MODULE +#endif + +#ifdef __MIPSEB__ + #undef __MIPSEB__ +#endif + +#ifdef _BIG_ENDIAN_ + #undef _BIG_ENDIAN_ +#endif + +#endif //_LITTLE_ENDIAN_ + +//------------------------------------------------------------- +// Config if NOT use Realtek specified BSP +//------------------------------------------------------------- +#ifdef NOT_RTK_BSP + +#if defined(CONFIG_PCI_HCI) && !defined(CONFIG_NET_PCI) +#define CONFIG_NET_PCI +#endif + +#ifndef __LINUX_2_6__ +#ifndef __ECOS +#define del_timer_sync del_timer +#endif +#endif + +#ifdef __KERNEL__ +#if LINUX_VERSION_CODE >= 0x02061D // linux 2.6.29 +#define NETDEV_NO_PRIV +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) +#define CONFIG_COMPAT_NET_DEV_OPS +#endif +#endif + +#ifdef CONFIG_RTL_CUSTOM_PASSTHRU +#undef CONFIG_RTL_CUSTOM_PASSTHRU +#endif + +#ifdef CONFIG_RTL_CUSTOM_PASSTHRU_PPPOE +#undef CONFIG_RTL_CUSTOM_PASSTHRU_PPPOE +#endif + +#ifdef _USE_DRAM_ + #undef _USE_DRAM_ +#endif + +#ifdef _BIG_ENDIAN_ +#ifndef CHECK_SWAP + #define CHECK_SWAP +#endif +#else // !_BIG_ENDIAN_ +#ifdef CHECK_SWAP + #undef CHECK_SWAP +#endif +#endif + +#ifdef EVENT_LOG + #undef EVENT_LOG +#endif + +#ifdef BR_SHORTCUT + #undef BR_SHORTCUT +#endif + +#if defined(NOT_RTK_BSP) && defined(BR_SHORTCUT_SUPPORT) +#define BR_SHORTCUT +#endif // NOT_RTK_BSP && BR_SHORTCUT_SUPPORT + +//#ifdef RTK_BR_EXT +// #undef RTK_BR_EXT +//#endif + +//#ifdef UNIVERSAL_REPEATER +// #undef UNIVERSAL_REPEATER +//#endif + +#ifdef GBWC + #undef GBWC +#endif + +#ifdef USE_IO_OPS + #undef USE_IO_OPS +#endif + +#ifdef IO_MAPPING + #undef IO_MAPPING +#endif + +#ifdef RTK_QUE + #undef RTK_QUE +#endif + +#ifdef USE_RLX_BSP +#undef USE_RLX_BSP +#endif + +#ifdef __ECOS +#ifdef RTLWIFINIC_GPIO_CONTROL +#undef RTLWIFINIC_GPIO_CONTROL +#endif +#endif + +// 2013/07/04, Lucien, Enable RX_BUFFER_GATHER to have lower RX_BUF_LEN +// Because pci_map_single/pci_unmap_single has higher time consumption in some non-RTK platforms. +//#ifdef RX_BUFFER_GATHER +//#undef RX_BUFFER_GATHER +//#endif +#define POWER_PERCENT_ADJUSTMENT + +// If the CPU's crystal is shared with WIFI, unmark this line +//#define DONT_DISABLE_XTAL_ON_CLOSE + +// use seq_file to display big file to avoid buffer overrun when using create_proc_entry +#define CONFIG_RTL_PROC_NEW + +#if defined(CPTCFG_CFG80211_MODULE) +#define RTK_NL80211 1 +#if !defined(NON_NL80211_AP) +#undef EAP_BY_QUEUE +#undef INCLUDE_WPA_PSK +#endif +#endif + +#endif //NOT_RTK_BSP + + +//------------------------------------------------------------- +// Define flag of EC system +//------------------------------------------------------------- +#ifdef CONFIG_RTL8196C_EC + +#ifndef USE_WEP_DEFAULT_KEY + #define USE_WEP_DEFAULT_KEY +#endif + +#ifdef TESTCHIP_SUPPORT + #undef TESTCHIP_SUPPORT +#endif + +#endif + + +//------------------------------------------------------------- +// MSC define flag +//------------------------------------------------------------- +#ifdef _SINUX_ +#define CONFIG_MSC +#endif + +#ifdef CONFIG_MSC +#define INCLUDE_WPS + +#ifdef CHECK_HANGUP + #undef CHECK_HANGUP +#endif +#ifndef USE_WEP_DEFAULT_KEY //2010.4.23 Fred Fu open it to support wep key index 1 2 3 + #define USE_WEP_DEFAULT_KEY +#endif + +#ifdef WIFI_SIMPLE_CONFIG +#ifdef INCLUDE_WPS +#define USE_PORTING_OPENSSL +#endif +#endif + +#endif + +//------------------------------------------------------------- +// Define flag of 8672 system +//------------------------------------------------------------- +#ifdef CONFIG_RTL8672 + +#ifndef RX_TASKLET + #define RX_TASKLET +#endif + +#ifdef RTL8190_DIRECT_RX + #undef RTL8190_DIRECT_RX +#endif + +#ifdef RTL8190_ISR_RX + #undef RTL8190_ISR_RX +#endif + +#if defined(USE_RLX_BSP) && !defined(LINUX_2_6_22_) + #undef USE_RLX_BSP +#endif + +#undef TX_SC_ENTRY_NUM +#define TX_SC_ENTRY_NUM 2 + +#ifdef __DRAM_IN_865X + #undef __DRAM_IN_865X +#endif +#ifdef CONFIG_RTL_8198C +#define __DRAM_IN_865X //__attribute__ ((section(".dram-rtkwlan"))) +#else +#define __DRAM_IN_865X __attribute__ ((section(".dram-rtkwlan"))) +#endif +#ifdef __IRAM_IN_865X + #undef __IRAM_IN_865X +#endif +#ifdef CONFIG_RTL_8198C +#define __IRAM_IN_865X //__attribute__ ((section(".iram-rtkwlan"))) +#else +#define __IRAM_IN_865X __attribute__ ((section(".iram-rtkwlan"))) +#endif + +#ifdef __IRAM_IN_865X_HI + #undef __IRAM_IN_865X_HI +#endif +#ifdef CONFIG_RTL_8198C +#define __IRAM_IN_865X_HI //__attribute__ ((section(".iram-tx"))) +#else +#define __IRAM_IN_865X_HI __attribute__ ((section(".iram-tx"))) +#endif + +//#define USE_TXQUEUE +#ifdef USE_TXQUEUE + #define TXQUEUE_SIZE 512 +#endif + +// Support dynamically adjust TXOP in low throughput feature +#define LOW_TP_TXOP + +// Support four different AC stream +#define WMM_VIBE_PRI + +// Resist interference +#ifdef CONFIG_RTL_92C_SUPPORT + #define INTERFERENCE_CONTROL +#endif + +#ifdef PCIE_POWER_SAVING + #undef PCIE_POWER_SAVING +#endif + +#ifdef CONFIG_RTL_8196C + #undef CONFIG_RTL_8196C +#endif +#ifdef CONFIG_RTL8196C_REVISION_B + #undef CONFIG_RTL8196C_REVISION_B +#endif + +#ifdef RTL_MANUAL_EDCA + #undef RTL_MANUAL_EDCA +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) && defined(CONFIG_WLAN_HAL_8192EE) +#define RX_LOOP_LIMIT +#endif + +#define RTLWIFINIC_GPIO_CONTROL + +#ifdef CONFIG_RTL8686 +#define _FULLY_WIFI_IGMP_SNOOPING_SUPPORT_ +#endif + +// use seq_file to display big file to avoid buffer overrun when using create_proc_entry +#define CONFIG_RTL_PROC_NEW + +#endif // CONFIG_RTL8672 + + +//------------------------------------------------------------- +// Define flag of rtl8192d features +//------------------------------------------------------------- +#ifdef CONFIG_RTL_92D_SUPPORT +#define SW_LCK_92D +#define DPK_92D + +#define RX_GAIN_TRACK_92D +//#define CONFIG_RTL_NOISE_CONTROL +#ifdef CONFIG_RTL_92D_DMDP +//#define NON_INTR_ANTDIV +#endif + +//#ifdef CONFIG_RTL_92D_INT_PA +#define RTL8192D_INT_PA +//#endif + +#ifdef RTL8192D_INT_PA +//Use Gain Table with suffix '_new' for purpose +//1. refine the large gap between power index 39 &40 +//#define RTL8192D_INT_PA_GAIN_TABLE_NEW //for both Non-USB & USB Power + +//Use Gain Table with suffix '_new1' for purpose +//1. refine the large gap between power index 39 &40 +//2. increase tx power +//#define RTL8192D_INT_PA_GAIN_TABLE_NEW1 //for USB Power only +#endif + +#endif + +//------------------------------------------------------------- +// OUT SOURCE +//------------------------------------------------------------- +#ifdef CONFIG_RTL_ODM_WLAN_DRIVER +#define USE_OUT_SRC 1 +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) +#define _OUTSRC_COEXIST +#endif +#endif + + +//------------------------------------------------------------- +// Define flag of RTL8188E features +//------------------------------------------------------------- +#ifdef CONFIG_RTL_88E_SUPPORT +/* RTL8188E test chip support*/ +//#define SUPPORT_RTL8188E_TC +#ifdef USE_OUT_SRC +#define RATEADAPTIVE_BY_ODM 1 +#define CALIBRATE_BY_ODM 1 +#endif + +// Support four different AC stream +#ifndef WMM_VIBE_PRI +#define WMM_VIBE_PRI +#endif +#define WMM_BEBK_PRI + +#ifndef CALIBRATE_BY_ODM +//for 8188E IQK +#define IQK_BB_REG_NUM 9 + +//for 88e tx power tracking +#define index_mapping_NUM_88E 15 +#define AVG_THERMAL_NUM_88E 4 +#define IQK_Matrix_Settings_NUM 1+24+21 +#define AVG_THERMAL_NUM 8 +#define HP_THERMAL_NUM 8 + +#define RF_T_METER_88E 0x42 +//=== +#endif + +#endif // CONFIG_RTL_88E_SUPPORT + +#if 0 +//------------------------------------------------------------- +// TLD define flag +//------------------------------------------------------------- +#ifdef CONFIG_RTL8196B_TLD + +#ifdef GBWC + #undef GBWC +#endif + +#ifdef SUPPORT_SNMP_MIB + #undef SUPPORT_SNMP_MIB +#endif + +#ifdef DRVMAC_LB + #undef DRVMAC_LB +#endif + +#ifdef HIGH_POWER_EXT_PA + #undef HIGH_POWER_EXT_PA +#endif + +#ifdef ADD_TX_POWER_BY_CMD + #undef ADD_TX_POWER_BY_CMD +#endif + +#endif // CONFIG_RTL8196B_TLD +#endif + + + +//------------------------------------------------------------- +// KLD define flag +//------------------------------------------------------------- +#if defined(CONFIG_RTL8196C_KLD) + +#ifndef INCLUDE_WPA_PSK + #define INCLUDE_WPA_PSK +#endif + +#ifdef UNIVERSAL_REPEATER + #undef UNIVERSAL_REPEATER + #undef SMART_REPEATER_MODE +#endif + +#ifndef WIFI_SIMPLE_CONFIG + #define WIFI_SIMPLE_CONFIG +#endif + +#ifdef GBWC + #undef GBWC +#endif + +#ifdef SUPPORT_SNMP_MIB + #undef SUPPORT_SNMP_MIB +#endif + +#ifdef DRVMAC_LB + #undef DRVMAC_LB +#endif + +#ifdef MBSSID + #undef RTL8192CD_NUM_VWLAN + #define RTL8192CD_NUM_VWLAN 1 +#endif + +//#ifdef HIGH_POWER_EXT_PA +// #undef HIGH_POWER_EXT_PA +//#endif + +//#ifdef ADD_TX_POWER_BY_CMD +// #undef ADD_TX_POWER_BY_CMD +//#endif + +#endif // CONFIG_RTL8196C_KLD + + +//------------------------------------------------------------- +// eCos define flag +//------------------------------------------------------------- +#ifdef __ECOS + #undef USE_PID_NOTIFY + //#undef EAP_BY_QUEUE +#ifdef RTK_SYSLOG_SUPPORT + #define EVENT_LOG +#else +// #undef EVENT_LOG + #define EVENT_LOG +#endif + //#undef SUPPORT_TX_MCAST2UNI //support m2u hx + //#undef AUTO_TEST_SUPPORT + //#undef SUPPORT_RX_UNI2MCAST +#if !defined(UNIVERSAL_REPEATER) && !defined(MBSSID) + #define USE_WEP_DEFAULT_KEY +#endif +#ifndef RX_TASKLET + #define RX_TASKLET +#endif + +#ifdef RTL8192CD_NUM_VWLAN + #undef RTL8192CD_NUM_VWLAN +#ifdef CONFIG_RTL_VAP_SUPPORT + #define RTL8192CD_NUM_VWLAN RTLPKG_DEVS_ETH_RLTK_819X_WLAN_MBSSID_NUM +#else + #define RTL8192CD_NUM_VWLAN 0 +#endif +#endif + +#if defined(CYGSEM_HAL_IMEM_SUPPORT) && !defined(CONFIG_RTL_8198C) + #define __IRAM_IN_865X __attribute__ ((section(".iram-rtkwlan"))) +#else + #define __IRAM_IN_865X +#endif +#if defined(CYGSEM_HAL_DMEM_SUPPORT) && !defined(CONFIG_RTL_8198C) + #define __DRAM_IN_865X __attribute__ ((section(".dram-rtkwlan"))) +#else + #define __DRAM_IN_865X +#endif + #define dev_kfree_skb_any(skb) wlan_dev_kfree_skb_any(skb) +#endif /* __ECOS */ + + +//------------------------------------------------------------- +// Dependence check of define flag +//------------------------------------------------------------- +#if defined(B2B_TEST) && !defined(MP_TEST) + #error "Define flag error, MP_TEST is not defined!\n" +#endif + + +#if defined(UNIVERSAL_REPEATER) && !defined(CLIENT_MODE) + #error "Define flag error, CLIENT_MODE is not defined!\n" +#endif + + +#if defined(TX_EARLY_MODE) && !defined(SW_TX_QUEUE) + #error "Define flag error, SW_TX_QUEUE is not defined!\n" +#endif + + +/*=============================================================*/ +/*------ Compiler Portability Macros --------------------------*/ +/*=============================================================*/ +#ifdef EVENT_LOG +#ifdef RTK_SYSLOG_SUPPORT + extern int wlanlog_printk(const char *fmt, ...); +#else + extern int scrlog_printk(const char * fmt, ...); +#endif +#ifdef CONFIG_RTK_MESH +/* + * NOTE: dot1180211sInfo.log_enabled content from webpage MIB_LOG_ENABLED (bitmap) (in AP/goahead-2.1.1/LINUX/fmmgmt.c formSysLog) + */ +#ifndef RTK_SYSLOG_SUPPORT + #define _LOG_MSG(fmt, args...) if (1 & GET_MIB(priv)->dot1180211sInfo.log_enabled) scrlog_printk(fmt, ## args) +#else + #define _LOG_MSG(fmt, args...) if (1 & GET_MIB(priv)->dot1180211sInfo.log_enabled) wlanlog_printk(fmt, ## args) +#endif + + #define LOG_MESH_MSG(fmt, args...) if (16 & GET_MIB(priv)->dot1180211sInfo.log_enabled) _LOG_MSG("%s: " fmt, priv->mesh_dev->name, ## args) +#else +#ifndef RTK_SYSLOG_SUPPORT +#ifdef __ECOS + #define _LOG_MSG(fmt, args...) diag_printf(fmt, ## args) +#else + #define _LOG_MSG(fmt, args...) scrlog_printk(fmt, ## args) +#endif +#else + #define _LOG_MSG(fmt, args...) wlanlog_printk(fmt, ## args) +#endif +#endif +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196C_EC) + #define _NOTICE "NOTICElog_num:13;msg:" + #define _DROPT "DROPlog_num:13;msg:" + #define _SYSACT "SYSACTlog_num:13;msg:" + + #define LOG_MSG_NOTICE(fmt, args...) _LOG_MSG("%s" fmt, _NOTICE, ## args) + #define LOG_MSG_DROP(fmt, args...) _LOG_MSG("%s" fmt, _DROPT, ## args) + #define LOG_MSG_SYSACT(fmt, args...) _LOG_MSG("%s" fmt, _SYSACT, ## args) + #define LOG_MSG(fmt, args...) {} + + #define LOG_START_MSG() { \ + char tmpbuf[10]; \ + LOG_MSG_NOTICE("Access Point: %s started at channel %d;\n", \ + priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, \ + priv->pmib->dot11RFEntry.dot11channel); \ + if (priv->pmib->dot11StationConfigEntry.autoRate) \ + strcpy(tmpbuf, "best"); \ + else \ + sprintf(tmpbuf, "%d", get_rate_from_bit_value(priv->pmib->dot11StationConfigEntry.fixedTxRate)/2); \ + LOG_MSG_SYSACT("AP 2.4GHz mode Ready. Channel : %d TxRate : %s SSID : %s;\n", \ + priv->pmib->dot11RFEntry.dot11channel, \ + tmpbuf, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID); \ + } + +#elif defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) + #define _NOTICE "NOTICElog_num:13;msg:" + #define _DROPT "DROPlog_num:13;msg:" + #define _SYSACT "SYSACTlog_num:13;msg:" + + #define LOG_MSG_NOTICE(fmt, args...) _LOG_MSG("%s" fmt, _NOTICE, ## args) + #define LOG_MSG_DROP(fmt, args...) _LOG_MSG("%s" fmt, _DROPT, ## args) + #define LOG_MSG_SYSACT(fmt, args...) _LOG_MSG("%s" fmt, _SYSACT, ## args) + #define LOG_MSG(fmt, args...) {} + + #define LOG_START_MSG() { \ + char tmpbuf[10]; \ + LOG_MSG_NOTICE("Access Point: %s started at channel %d;\n", \ + priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, \ + priv->pmib->dot11RFEntry.dot11channel); \ + if (priv->pmib->dot11StationConfigEntry.autoRate) \ + strcpy(tmpbuf, "best"); \ + else \ + sprintf(tmpbuf, "%d", get_rate_from_bit_value(priv->pmib->dot11StationConfigEntry.fixedTxRate)/2); \ + LOG_MSG_SYSACT("AP 2.4GHz mode Ready. Channel : %d TxRate : %s SSID : %s;\n", \ + priv->pmib->dot11RFEntry.dot11channel, \ + tmpbuf, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID); \ + } +#elif defined(CONFIG_RTL8196B_TLD) + #define LOG_MSG_DEL(fmt, args...) _LOG_MSG(fmt, ## args) + #define LOG_MSG(fmt, args...) {} +#else + #define LOG_MSG(fmt, args...) _LOG_MSG("%s: "fmt, priv->dev->name, ## args) +#endif +#else + #if defined(__GNUC__) || defined(GREEN_HILL) + #define LOG_MSG(fmt, args...) {} + #else + #define LOG_MSG + #endif +#endif // EVENT_LOG + +#ifdef _USE_DRAM_ + #define DRAM_START_ADDR 0x81000000 // start address of internal data ram +#endif + +#ifndef __ECOS +#ifdef __GNUC__ +#define __WLAN_ATTRIB_PACK__ __attribute__ ((packed)) +#define __PACK +#endif +#endif + +#ifdef __arm +#define __WLAN_ATTRIB_PACK__ +#define __PACK __packed +#endif + +#if defined(GREEN_HILL) || defined(__ECOS) +#define __WLAN_ATTRIB_PACK__ +#define __PACK +#endif + + +/*=============================================================*/ +/*-----------_ Driver module flags ----------------------------*/ +/*=============================================================*/ +#if defined(CONFIG_WIRELESS_LAN_MODULE) || defined(CONFIG_RTL_ULINKER_WLAN_DELAY_INIT) + #define MODULE_NAME "Realtek WirelessLan Driver" +#ifndef NOT_RTK_BSP + #define MODULE_VERSION "v1.00" +#endif + + #define MDL_DEVINIT + #define MDL_DEVEXIT + #define MDL_INIT + #define MDL_EXIT + #define MDL_DEVINITDATA +#else +#ifdef CONFIG_RTL_8198C + #define MDL_DEVINIT //__devinit + #define MDL_DEVEXIT //__devexit + #define MDL_INIT //__init + #define MDL_EXIT //__exit + #define MDL_DEVINITDATA //__devinitdata +#else + #define MDL_DEVINIT __devinit + #define MDL_DEVEXIT __devexit + #define MDL_INIT __init + #define MDL_EXIT __exit + #define MDL_DEVINITDATA __devinitdata +#endif +#endif + + +/*=============================================================*/ +/*----------- System configuration ----------------------------*/ +/*=============================================================*/ +#if defined(CONFIG_RTL8196B_GW_8M) +#define NUM_TX_DESC 200 +#else +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8198C) || defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_8198B) || (defined(CONFIG_LUNA_DUAL_LINUX) || defined(CONFIG_ARCH_LUNA_SLAVE)) || defined(CONFIG_RTL8672) +#if defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN_D) +#define NUM_TX_DESC 640 +#elif defined(__ECOS) && defined(CYGNUM_RAM_SIZE_0x00800000) +#define NUM_TX_DESC 256 +#else +#ifdef CONFIG_RTL_8812_SUPPORT + #ifdef CONFIG_RTL_8812AR_VN_SUPPORT + #define NUM_TX_DESC 480 + #else + #define NUM_TX_DESC 768 + #endif +#elif defined(CONFIG_RTL_8196E) + #define NUM_TX_DESC 300//256 +#elif defined(CONFIG_WLAN_HAL_8881A) + #define NUM_TX_DESC 480 +#elif defined(CONFIG_WLAN_HAL_8814AE) + #define NUM_TX_DESC 768 +#else +#define NUM_TX_DESC 512 +#endif +#endif +#elif defined(NOT_RTK_BSP) +#if defined(CONFIG_WLAN_HAL_8814AE) +#define NUM_TX_DESC 2176 //512 // kmalloc max size issue +#else +#define NUM_TX_DESC 512 +#endif +#else +#define NUM_TX_DESC 256 // kmalloc max size issue +#endif +#endif + +//#define NUM_TX_DESC_HQ 64 +#if defined (CONFIG_SLOT_0_TX_BEAMFORMING) || defined (CONFIG_SLOT_1_TX_BEAMFORMING) +#define BEAMFORMING_SUPPORT 1 +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) +#define RTK_AC_SUPPORT +#endif + +#ifdef CONFIG_RTL_NFJROM_MP + #define NUM_RX_DESC 64 +#elif defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8198C) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_LUNA_DUAL_LINUX) || defined(CONFIG_ARCH_LUNA_SLAVE)) || defined(CONFIG_RTL8672) + #if defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN_D) + #define NUM_RX_DESC 256 + #elif defined(__ECOS) && defined(CYGNUM_RAM_SIZE_0x00800000) + #define NUM_RX_DESC 320 + #else + #ifdef CONFIG_RTL_8812_SUPPORT + #ifdef CONFIG_RTL_8812AR_VN_SUPPORT + #define NUM_RX_DESC 256 + #else + #define NUM_RX_DESC 512 + #endif + #elif defined(CONFIG_RTL_8196E) + #ifdef MULTI_MAC_CLONE + #define NUM_RX_DESC 512 + #else + #define NUM_RX_DESC 256 + #endif + #elif defined(CONFIG_WLAN_HAL_8881A) + #define NUM_RX_DESC 480 //256 + #elif defined(CONFIG_WLAN_HAL_8814AE) + #define NUM_RX_DESC 512 //256 + #elif defined(CONFIG_RTL_8196D) + #define NUM_RX_DESC 512 + #else + #define NUM_RX_DESC 128 + #endif + #endif +#elif defined(CONFIG_RTL_92D_SUPPORT) + #define NUM_RX_DESC 80 +#elif defined(__ECOS) + #define NUM_RX_DESC 64 + #undef NUM_TX_DESC + #define NUM_TX_DESC 512 +#elif defined(NOT_RTK_BSP) + #ifdef CONFIG_WLAN_HAL_8814AE + #define NUM_RX_DESC 2048 + #elif defined(CONFIG_RTL_8812_SUPPORT) + #define NUM_RX_DESC 2048 + #else + #define NUM_RX_DESC 128 + #endif +#else + #ifdef RX_BUFFER_GATHER + #define NUM_RX_DESC 64 + #else + #define NUM_RX_DESC 32 + #endif +#endif + +#define CURRENT_NUM_TX_DESC priv->pshare->current_num_tx_desc +#if defined (CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_92D_DMDP) +#define MAX_NUM_TX_DESC_DMDP 256 +#endif + +#ifdef DELAY_REFILL_RX_BUF + #define REFILL_THRESHOLD NUM_RX_DESC +#endif + + +#ifdef CONFIG_RTL_88E_SUPPORT +#if defined(__ECOS) || defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#define RTL8188E_NUM_STAT 32 +#else +#define RTL8188E_NUM_STAT 64 +#endif +#endif + +/* do not modify this*/ +#define RTL8192CD_NUM_STAT 32 //92c / 92d // 88c +#define FW_NUM_STAT 128 // 8812 / 8192E / 8881A / Other new ic FW_NUM_STAT + +#if (defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD)) && defined(MBSSID) +#define NUM_CMD_DESC 2 +#else +#define NUM_CMD_DESC 16 +#endif + +#ifdef HW_DETEC_POWER_STATE +#define HW_MACID_SEARCH_NOT_READY 0x7E +#define HW_MACID_SEARCH_FAIL 0x7F +#define HW_MACID_SEARCH_SUPPORT_NUM (HW_MACID_SEARCH_FAIL-1) +#endif + +#ifdef CONFIG_RTL_NFJROM_MP + #define NUM_STAT 8 +#elif defined(MULTI_MAC_CLONE) && defined(CONFIG_WLAN_HAL_8192EE) + #define NUM_STAT 63 +#elif defined(CONFIG_RTL_88E_SUPPORT) + #define NUM_STAT (RTL8188E_NUM_STAT - 1) +#else + #define NUM_STAT 31 //127 +#endif + + +#define MAX_GUEST_NUM NUM_STAT + +#define NUM_TXPKT_QUEUE 64 +#define NUM_APSD_TXPKT_QUEUE 32 +#define NUM_DZ_MGT_QUEUE 16 + +#ifdef CONFIG_WLAN_HAL +#define PRE_ALLOCATED_HDR (NUM_TX_DESC*2) +#else +#define PRE_ALLOCATED_HDR NUM_TX_DESC +#endif + +#ifdef DRVMAC_LB +#define PRE_ALLOCATED_MMPDU 32 +#define PRE_ALLOCATED_BUFSIZE (2048/4) // 600 bytes long should be enough for mgt! Declare as unsigned int +#else +#define PRE_ALLOCATED_MMPDU 64 +#define PRE_ALLOCATED_BUFSIZE ((600+128)/4) // 600 bytes long should be enough for mgt! Declare as unsigned int +#endif + +#ifdef RTK_NL80211 //eric-sync ?? +#define MAX_BSS_NUM 32 +#else +#define MAX_BSS_NUM 64 +#endif + +#define MAX_NUM_WLANIF 4 +#define WLAN_MISC_MAJOR 13 + +#define MAX_FRAG_COUNT 16 + +#define NUM_MP_SKB 32 + +#define SUPPORT_CH_NUM 59 + +// unit of time out: 10 msec +#define AUTH_TO RTL_SECONDS_TO_JIFFIES(5) +#define ASSOC_TO RTL_SECONDS_TO_JIFFIES(5) +#define FRAG_TO RTL_SECONDS_TO_JIFFIES(20) +#define SS_TO RTL_MILISECONDS_TO_JIFFIES(50) +#define SS_PSSV_TO RTL_MILISECONDS_TO_JIFFIES(120) // passive scan for 120 ms + + + +#define P2P_SEARCH_TIME_V 200 +#define P2P_SEARCH_TIME RTL_MILISECONDS_TO_JIFFIES(P2P_SEARCH_TIME_V) + + +#ifdef CONFIG_RTL_11W_SUPPORT +#ifdef CONFIG_RTL_11W_CLI_SUPPORT +#define CONFIG_IEEE80211W_CLI +//#define CONFIG_IEEE80211W_CLI_DEBUG +#endif +#define CONFIG_IEEE80211W +#define CONFIG_IEEE80211W_CMD +//#define CONFIG_IEEE80211W_AP_DEBUG +//#define PMF_DEBUGMSG +#endif + +#ifdef HS2_SUPPORT +#define CU_TO RTL_MILISECONDS_TO_JIFFIES(210) // 200ms to calculate bbp channel load +#define CU_Intval 200 +#endif + +#ifdef CONFIG_IEEE80211W +#define SA_QUERY_RETRY_TO 201 +#define SA_QUERY_MAX_TO 1000 +#define SA_QUERY_MAX_NUM 5 +#endif + +#ifdef CONFIG_RTL_NEW_AUTOCH +#define SS_AUTO_CHNL_TO RTL_MILISECONDS_TO_JIFFIES(200) +#define SS_AUTO_CHNL_NHM_TO RTL_MILISECONDS_TO_JIFFIES(100) +#endif + +#ifdef CONFIG_RTK_MESH +//GANTOE for automatic site survey 2008/12/10 +#define SS_RAND_DEFER 300 +#if defined(RTK_MESH_AODV_STANDALONE_TIMER) +#define MESH_AODV_EXPIRE_TO RTL_MILISECONDS_TO_JIFFIES(100) +#endif +#endif +#ifdef LINUX_2_6_22_ +#define EXPIRE_TO RTL_SECONDS_TO_JIFFIES(1) +#else +#define EXPIRE_TO RTL_SECONDS_TO_JIFFIES(1) +#endif +#define REAUTH_TO RTL_SECONDS_TO_JIFFIES(5) +#define REASSOC_TO RTL_SECONDS_TO_JIFFIES(5) +#define REAUTH_LIMIT 6 +#define REASSOC_LIMIT 6 + +#define DEFAULT_OLBC_EXPIRE 60 + +#define GBWC_TO RTL_MILISECONDS_TO_JIFFIES(250) + +#ifdef __DRAYTEK_OS__ +#define SS_COUNT 2 +#else +#define SS_COUNT 3 +#endif + +#define TUPLE_WINDOW 64 + +#define RC_TIMER_NUM 64 +#define RC_ENTRY_NUM 128 +#define AMSDU_TIMER_NUM 64 +#define AMPDU_TIMER_NUM 64 + +#define ROAMING_DECISION_PERIOD_INFRA 5 +#define ROAMING_DECISION_PERIOD_ADHOC 10 +#define ROAMING_DECISION_PERIOD_ARRAY (MAX_NUM(ROAMING_DECISION_PERIOD_ADHOC,ROAMING_DECISION_PERIOD_INFRA)+1) +#define ROAMING_THRESHOLD 1 // roaming will be triggered when rx + // beacon percentage is less than the value +#define FAST_ROAMING_THRESHOLD 40 + +/* below is for security.h */ +#define MAXDATALEN 1560 +#define MAXQUEUESIZE 8 //WPS2DOTX +#define MAXRSNIELEN 128 +#define E_DOT11_2LARGE -1 +#define E_DOT11_QFULL -2 +#define E_DOT11_QEMPTY -3 +#ifdef WIFI_SIMPLE_CONFIG +#define PROBEIELEN 260 +#endif + +// for SW LED +#define LED_MAX_PACKET_CNT_B 400 +#define LED_MAX_PACKET_CNT_AG 1200 +#define LED_MAX_SCALE 100 +#define LED_NOBLINK_TIME RTL_SECONDS_TO_JIFFIES(15)/10 // time more than watchdog interval +#define LED_INTERVAL_TIME RTL_MILISECONDS_TO_JIFFIES(500) // 500ms +#define LED_ON_TIME RTL_MILISECONDS_TO_JIFFIES(40) // 40ms +#define LED_ON 0 +#define LED_OFF 1 +#define LED_0 0 +#define LED_1 1 +#define LED_2 2 + +// for counting association number +#define INCREASE 1 +#define DECREASE 0 + +// DFS +#define CH_AVAIL_CHK_TO RTL_SECONDS_TO_JIFFIES(62) // 62 seconds +#define CH_AVAIL_CHK_TO_CE RTL_SECONDS_TO_JIFFIES(602) // 602 seconds + + +/*adjusted for support AMSDU*/ +#if defined(RTK_AC_SUPPORT) //&& !defined(CONFIG_RTL_8198B) + +#ifdef CONFIG_RTL_AC2G_256QAM +#define AC2G_256QAM +#endif + +#ifdef __ECOS +#define MAX_SKB_BUF MCLBYTES //2048 +#define MAX_RX_BUF_LEN (MAX_SKB_BUF -sizeof(struct skb_shared_info) - 32) +#define MIN_RX_BUF_LEN MAX_RX_BUF_LEN +#else +#ifdef RX_BUFFER_GATHER +#ifdef CONFIG_RTL_8812_SUPPORT +#define MAX_RX_BUF_LEN 3000 +#define MIN_RX_BUF_LEN 3000 +#else +#define MAX_RX_BUF_LEN 2600 +#define MIN_RX_BUF_LEN 2600 +#endif +#else +#define MAX_RX_BUF_LEN 12000 +#define MIN_RX_BUF_LEN 4600 +#endif +#endif + +#else // ! RTK_AC_SUPPORT + +#ifdef RX_BUFFER_GATHER +#ifdef __LINUX_2_6__ +#define MAX_SKB_BUF 2280 +#elif defined(__ECOS) +#define MAX_SKB_BUF MCLBYTES //2048 +#else +#define MAX_SKB_BUF 2048 +#endif + +#ifdef __ECOS +#define MAX_RX_BUF_LEN (MAX_SKB_BUF -sizeof(struct skb_shared_info) - 32) +#else +#define MAX_RX_BUF_LEN (MAX_SKB_BUF -sizeof(struct skb_shared_info) - 128) +#endif +#define MIN_RX_BUF_LEN MAX_RX_BUF_LEN +#else //#ifdef RX_BUFFER_GATHER +#if defined(__ECOS) //mark_ecos +#define MAX_SKB_BUF MCLBYTES //2048 +#define MAX_RX_BUF_LEN (MAX_SKB_BUF -sizeof(struct skb_shared_info) - 32) +#define MIN_RX_BUF_LEN MAX_RX_BUF_LEN +#else // +#define MAX_RX_BUF_LEN 8400 +#define MIN_RX_BUF_LEN 4400 +#endif +#endif //#ifdef RX_BUFFER_GATHER +#endif + +/* for RTL865x suspend mode */ +#define TP_HIGH_WATER_MARK 55 //80 /* unit: Mbps */ +#define TP_LOW_WATER_MARK 35 //40 /* unit: Mbps */ + +#define FW_BOOT_SIZE 400 +#define FW_MAIN_SIZE 52000 +#define FW_DATA_SIZE 850 + +#ifdef CONFIG_WLAN_HAL_8881A +#define AGC_TAB_SIZE 2400 +#else +#define AGC_TAB_SIZE 1600 +#endif +#define PHY_REG_SIZE 2048 +//#define MAC_REG_SIZE 1200 +#define MAC_REG_SIZE 1420 +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) +#define PHY_REG_PG_SIZE 2560 +#else +#define PHY_REG_PG_SIZE 256 +#endif + +#ifdef CONFIG_WLAN_HAL_8814AE +// TODO: temporary for 8814AE file size +#define AGC_TAB_SIZE 5120 +#define PHY_REG_SIZE 18432 +#define MAC_REG_SIZE 2048 +#define PHY_REG_PG_SIZE 9216 +#endif + +#define PHY_REG_1T2R 256 +#define PHY_REG_1T1R 256 +#define FW_IMEM_SIZE 40*(1024) +#define FW_EMEM_SIZE 50*(1024) +#define FW_DMEM_SIZE 48 + +// for PCIe power saving +#define POWER_DOWN_T0 (10*HZ) +#define PKT_PAGE_SZ 128 +#define TX_DESC_SZ 32 + + +#ifdef SUPPORT_TX_MCAST2UNI +#define MAX_IP_MC_ENTRY 8 +#define MAX_FLOODING_MAC_NUM 32 +#endif + +#ifndef CALIBRATE_BY_ODM +#define IQK_ADDA_REG_NUM 16 +#define MAX_TOLERANCE 5 +#if defined(HIGH_POWER_EXT_PA) && defined(CONFIG_RTL_92C_SUPPORT) +#define IQK_DELAY_TIME 20 //ms +#else +#define IQK_DELAY_TIME 1 //ms +#endif +#define IQK_MAC_REG_NUM 4 +#endif + + +#define SKIP_MIC_NUM 300 + + +// for dynamic mechanism of reserving tx desc +#ifdef RESERVE_TXDESC_FOR_EACH_IF +#define IF_TXDESC_UPPER_LIMIT 70 // percentage +#ifdef USE_TXQUEUE +#define IF_TXQ_UPPER_LIMIT 85 // percentage +#endif +#endif + +// for dynamic mechanism of retry count +#define RETRY_TRSHLD_H 3750000 +#define RETRY_TRSHLD_L 3125000 +#define MP_PSD_SUPPORT 1 +//------------------------------------------------------------- +// Define flag for 8M gateway configuration +//------------------------------------------------------------- +#if defined(CONFIG_RTL8196B_GW_8M) + +#ifdef MBSSID + #undef RTL8192CD_NUM_VWLAN + #define RTL8192CD_NUM_VWLAN 1 +#endif + +#undef NUM_STAT +#define NUM_STAT 16 + +#endif // CONFIG_RTL8196B_GW_8M + + +#if defined(CONFIG_RTL8196C_AP_ROOT) || defined(CONFIG_RTL8198_AP_ROOT) + +#ifdef DOT11D + #undef DOT11D +#endif + + +#ifdef MBSSID + #undef RTL8192CD_NUM_VWLAN + #define RTL8192CD_NUM_VWLAN 1 +#endif + +#undef NUM_STAT +#define NUM_STAT 16 + + +#endif //defined(CONFIG_RTL8196C_AP_ROOT) +#ifdef CONFIG_RTL_8198_NFBI_RTK_INBAND_AP //mark_nfbi_inband_ap +#ifdef MBSSID + #undef RTL8192CD_NUM_VWLAN + #define RTL8192CD_NUM_VWLAN 7 +#endif +#endif + + +#if defined(CONFIG_RTL8196C_CLIENT_ONLY) + +#ifdef DOT11D + #undef DOT11D +#endif + +#endif + +#ifdef CONCURRENT_MODE +#define NUM_WLAN_IFACE 2 +#endif + +#ifdef CONFIG_NET_PCI +#ifndef NUM_WLAN_IFACE +#define NUM_WLAN_IFACE 2 +#endif +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_USB_POWER_BUS) +#define USB_POWER_SUPPORT +#endif + +#ifdef WIFI_SIMPLE_CONFIG +#define MAX_WSC_IE_LEN (256+128) +#define MAX_WSC_PROBE_STA 10 +#endif + +#define MAX_PROBE_REQ_STA 32 + +#ifdef CONFIG_WIRELESS_LAN_MODULE //BE_MODULE +#undef __DRAM_IN_865X +#undef __IRAM_IN_865X +#undef __MIPS16 + +#define __DRAM_IN_865X +#define __IRAM_IN_865X +#define __MIPS16 +#ifndef RTK_NL80211 +#undef BR_SHORTCUT +#endif +#if defined(NOT_RTK_BSP) && defined(BR_SHORTCUT_SUPPORT) +#define BR_SHORTCUT +#endif // NOT_RTK_BSP && BR_SHORTCUT_SUPPORT +#undef CONFIG_RTL865X_ETH_PRIV_SKB +#undef CONFIG_RTL_ETH_PRIV_SKB +#undef CONFIG_RTK_VLAN_SUPPORT +#endif +#if defined(CONFIG_RTL8672) && defined(LINUX_2_6_22_) && defined(WIFI_LIMITED_MEM) + #undef NUM_STAT + #define NUM_STAT 16 +#endif + +//------------------------------------------------------------- +// Option: Use kernel thread to execute Tx Power Tracking function. +//------------------------------------------------------------- +#ifdef CONFIG_RTL_TPT_THREAD +#define TPT_THREAD +#endif + + +//------------------------------------------------------------- +// Define flag of RTL8812 features +//------------------------------------------------------------- +#ifdef CONFIG_RTL_8812_SUPPORT + +//#undef DETECT_STA_EXISTANCE + +#define USE_OUT_SRC 1 + +//#ifdef CONFIG_RTL_92C_SUPPORT +//#define _OUTSRC_COEXIST +//#endif + +//for 11ac logo +++ +//#define BEAMFORMING_SUPPORT 1 +#ifndef __ECOS +//#define SUPPORT_TX_AMSDU //disable this, because aput only needs rx amsdu. (but testbed needs both rx & tx amsdu) +#endif +//for 11ac logo --- + +#define _TRACKING_TABLE_FILE +#define TX_PG_8812 + +#endif + +//------------------------------------------------------------- +// SKB NUM +//------------------------------------------------------------- +#ifdef CONFIG_RTL8190_PRIV_SKB + #ifdef DELAY_REFILL_RX_BUF + #if defined(CONFIG_RTL8196B_GW_8M) + #define MAX_SKB_NUM 100 + #elif defined(CONFIG_RTL8672) + #if defined(WIFI_LIMITED_MEM) + #if defined(LINUX_2_6_22_) + #define MAX_SKB_NUM 96 + #else + #define MAX_SKB_NUM 160 + #endif + #else + #define MAX_SKB_NUM 768 + #endif + #elif defined(CONFIG_RTL_8196E) + #if defined(CONFIG_WLAN_HAL_8192EE) + #ifdef MULTI_MAC_CLONE + #define MAX_SKB_NUM (NUM_RX_DESC + 64) + #else + #define MAX_SKB_NUM 400 //256 + #endif + #else + #define MAX_SKB_NUM 256 + #endif + #elif defined(CONFIG_WLAN_HAL_8881A) + #define MAX_SKB_NUM 480 + #elif defined(CONFIG_RTL_8198C) + #define MAX_SKB_NUM 512 + #elif defined(CONFIG_RTL_8198_GW) || defined(CONFIG_RTL_8198_AP_ROOT) || defined(CONFIG_RTL_819XD) + #ifdef CONFIG_RTL_8812_SUPPORT + #ifdef CONFIG_RTL_8812AR_VN_SUPPORT + #define MAX_SKB_NUM 480 + #else + #define MAX_SKB_NUM 768 + #endif + #elif defined(CONFIG_WLAN_HAL_8814AE) + #define MAX_SKB_NUM 768 + #else + #define MAX_SKB_NUM 480//256 + #endif + #elif defined(CONFIG_RTL_92D_SUPPORT) + #ifdef CONFIG_RTL_8198_AP_ROOT + #define MAX_SKB_NUM 210 + #else + #define MAX_SKB_NUM 256 + #endif + #elif defined( __ECOS) + #define MAX_SKB_NUM 256 + #else + #ifdef UNIVERSAL_REPEATER + #define MAX_SKB_NUM 256 + #else + #define MAX_SKB_NUM 160 + #endif + #endif + #else + #define MAX_SKB_NUM 580 + #endif + + +#endif + + +//------------------------------------------------------------- +// NFJROM CONFIG +//------------------------------------------------------------- +#ifdef CONFIG_RTL_NFJROM_MP +#undef NUM_TX_DESC +#undef NUM_RX_DESC +#undef NUM_STAT +#undef NUM_TXPKT_QUEUE +#undef NUM_APSD_TXPKT_QUEUE +#undef NUM_DZ_MGT_QUEUE +#ifdef __ECOS +/*Ecos's skb buffer is limited to cluster size.using the value in MP the same as in normal driver*/ +#else +#undef MAX_RX_BUF_LEN +#undef MIN_RX_BUF_LEN +#endif + +#define NUM_TX_DESC 64 +#define NUM_RX_DESC 64 +#define NUM_STAT 1 +#define NUM_TXPKT_QUEUE 8 +#define NUM_APSD_TXPKT_QUEUE 1 +#define NUM_DZ_MGT_QUEUE 1 +#ifdef __ECOS +/*Ecos's skb buffer is limited to cluster size. using the value in MP the same as in normal driver*/ +#else +#define MAX_RX_BUF_LEN 3000 +#define MIN_RX_BUF_LEN 3000 +#endif +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) +#define RTK_5G_SUPPORT +#endif + +#ifdef RTK_5G_SUPPORT +#define MAX_CHANNEL_NUM 76 +#else +#define MAX_CHANNEL_NUM MAX_2G_CHANNEL_NUM +#endif + +#define NUM_TX_DESC_HQ (NUM_TX_DESC>>3) + + +//------------------------------------------------------------- +// 802.11h TPC +//------------------------------------------------------------- +#ifdef RTK_5G_SUPPORT +#define DOT11H +#endif + +//------------------------------------------------------------- +// Support 802.11d +//------------------------------------------------------------- +#if defined(RTK_5G_SUPPORT) || defined(CONFIG_RTL_80211D_SUPPORT) +#define DOT11D +#endif + +//#define CHK_RX_ISR_TAKES_TOO_LONG + +//This is for LUNA SDK - Apollo to config 8812 in slave CPU and shift mem 33M +#if defined(CONFIG_ARCH_LUNA_SLAVE) && !defined(CONFIG_WLAN_HAL) +#define CONFIG_LUNA_SLAVE_PHYMEM_OFFSET CONFIG_RTL8686_DSP_MEM_BASE +#else +#define CONFIG_LUNA_SLAVE_PHYMEM_OFFSET 0x0 +#endif + +#if !defined(CONFIG_LUNA_DUAL_LINUX) && defined(CONFIG_ARCH_LUNA_SLAVE) +#define CONFIG_LUNA_DUAL_LINUX +#endif + +#ifdef CONFIG_USB_HCI +#define USB_INTERFERENCE_ISSUE // this should be checked in all usb interface +//#define USB_LOCK_ENABLE +//#define CONFIG_USB_VENDOR_REQ_MUTEX +#define CONFIG_VENDOR_REQ_RETRY +//#define CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC +#define CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE +#define SUPPORTED_BLOCK_IO +#define CONFIG_USE_VMALLOC +//#define CMD_THREAD_FUNC_DEBUG + +// USB TX +//#define CONFIG_IRQ_LEVEL_XMIT_LOCK +#define CONFIG_USB_TX_AGGREGATION +#define CONFIG_TCP_ACK_TXAGG +#define CONFIG_TCP_ACK_MERGE +#define CONFIG_NETDEV_MULTI_TX_QUEUE +//#define CONFIG_TX_RECYCLE_EARLY + +// USB RX +//#define CONFIG_USE_USB_BUFFER_ALLOC_RX +#define CONFIG_PREALLOC_RECV_SKB +#define CONFIG_USB_RX_AGGREGATION +#define DBG_CONFIG_ERROR_DETECT +//#define CONFIG_USB_INTERRUPT_IN_PIPE // Has bug on 92C +#ifdef CONFIG_RTL_88E_SUPPORT +//#define CONFIG_SUPPORT_USB_INT +#define CONFIG_INTERRUPT_BASED_TXBCN // Tx Beacon when driver BCN_OK ,BCN_ERR interrupt occurs +#endif + +#undef TX_SC_ENTRY_NUM +#define TX_SC_ENTRY_NUM 3 + +#undef RX_SC_ENTRY_NUM +#define RX_SC_ENTRY_NUM 3 + +#undef SW_TX_QUEUE +#define RTL8190_DIRECT_RX +#undef RTL8190_ISR_RX +#define RX_TASKLET +#undef RX_BUFFER_GATHER // this is a tip. You must define/undef it in above to make it available +#undef CONFIG_OFFLOAD_FUNCTION +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI +#undef RTL_MANUAL_EDCA +#undef CONFIG_OFFLOAD_FUNCTION +#ifdef __KERNEL__ +#define CONFIG_USE_VMALLOC +#endif +#define DONT_COUNT_PROBE_PACKET +#ifdef CONFIG_WLAN_HAL_8192EE +#define CONFIG_1RCCA_RF_POWER_SAVING +#endif +#if defined(CONFIG_POWER_SAVE) && (defined(CONFIG_WAKELOCK) || defined(CONFIG_PM_WAKELOCKS)) +#define USE_WAKELOCK_MECHANISM +#endif +//#define CMD_THREAD_FUNC_DEBUG +//#define INDICATE_LINK_CHANGE + +// SDIO TX +//#define CONFIG_IRQ_LEVEL_XMIT_LOCK +#define CONFIG_SDIO_TX_AGGREGATION +#define CONFIG_TCP_ACK_TXAGG +#define CONFIG_TCP_ACK_MERGE +#define CONFIG_SDIO_TX_INTERRUPT +#define CONFIG_SDIO_TX_IN_INTERRUPT +#define CONFIG_SDIO_RESERVE_MASSIVE_PUBLIC_PAGE // only 88E available +#define CONFIG_NETDEV_MULTI_TX_QUEUE +#define CONFIG_TX_RECYCLE_EARLY +#ifdef __ECOS +#define CONFIG_SDIO_TX_FILTER_BY_PRI +#endif +//#define SDIO_STATISTICS +//#define SDIO_STATISTICS_TIME + +// SDIO RX +#define RTL8190_DIRECT_RX +#undef RTL8190_ISR_RX +#define RX_TASKLET +#undef RX_BUFFER_GATHER // this is a tip. You must define/undef it in above to make it available + +#undef TX_SC_ENTRY_NUM +#define TX_SC_ENTRY_NUM 3 + +#undef RX_SC_ENTRY_NUM +#define RX_SC_ENTRY_NUM 3 + +// Validate SDIO flag combination +#if defined(CONFIG_SDIO_TX_IN_INTERRUPT) && !defined(CONFIG_SDIO_TX_INTERRUPT) +#error "CONFIG_SDIO_TX_IN_INTERRUPT must under TX INT mode" +#endif +#if defined(SDIO_AP_OFFLOAD) && defined(MBSSID) && (RTL8192CD_NUM_VWLAN > 2) +#error "AP offload only support at most three SSIDs" +#endif +#endif // CONFIG_SDIO_HCI + +#if defined(WIFI_WPAS_CLI) && defined(SMART_REPEATER_MODE) +#undef SMART_REPEATER_MODE +#endif + +// select_queue (of net_device) is available above Linux 2.6.27 +#if defined(CONFIG_NETDEV_MULTI_TX_QUEUE) && !defined(LINUX_2_6_27_) +#undef CONFIG_NETDEV_MULTI_TX_QUEUE +#endif + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) +#undef __DRAM_IN_865X +#undef __IRAM_IN_865X +#undef __MIPS16 + +#define __DRAM_IN_865X +#define __IRAM_IN_865X +#define __MIPS16 +#undef BR_SHORTCUT +#undef CONFIG_RTL865X_ETH_PRIV_SKB +#undef CONFIG_RTL_ETH_PRIV_SKB +#undef CONFIG_RTK_VLAN_SUPPORT +#endif + + + + +//#ifdef BR_SHORTCUT +#define MAX_REPEATER_SC_NUM 2 +#define MAX_BRSC_NUM 8 +//#endif + +#if defined(RTK_NL80211) || defined(WIFI_HAPD) +#ifdef SUPPORT_CLIENT_MIXED_SECURITY +#undef SUPPORT_CLIENT_MIXED_SECURITY //because 8192cd_psk_hapd.c not patched this fun yet +#endif + +#endif + + +#ifdef RTK_NL80211 + +#ifdef CPTCFG_CFG80211_MODULE +//#define RTK_NL80211_DMA //eric-sync ?? backfire comapt +#endif + +#ifdef CONFIG_PCI_HCI +#if 0 //ndef RTK_NL80211_DMA +//use SLUB to overcome the kmalloc issue , no need RTK_NL80211_DMA anymore! +#undef NUM_RX_DESC +#undef NUM_TX_DESC +#undef RTL8192CD_NUM_VWLAN + +#define NUM_RX_DESC 128 +#define NUM_TX_DESC 128 +#define RTL8192CD_NUM_VWLAN 4 +#else +#define RTL8192CD_NUM_VWLAN (3+1) //eric-vap, add one more for open-wrt scan iface +#endif +#endif + +#endif //RTK_NL80211 + +#endif // _8192CD_CFG_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_cfg80211.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_cfg80211.c new file mode 100755 index 000000000..f9f2c7a68 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_cfg80211.c @@ -0,0 +1,6598 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * Copyright (c) 2011-2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#ifdef RTK_NL80211 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) +#include +#else +#include +#endif +#include + + + +//#include "./nl80211_copy.h" + +#ifdef __LINUX_2_6__ +#include +#include +#endif + +#include "./8192cd.h" +#include "./8192cd_debug.h" +#include "./8192cd_cfg80211.h" +#include "./8192cd_headers.h" +#include "./8192cd_p2p.h" + +#include "net80211/ieee80211.h" +#include "net80211/ieee80211_crypto.h" +#include "net80211/ieee80211_ioctl.h" +#include "./8192cd_net80211.h" + +//#define DEBUG_NL80211 +#ifdef DEBUG_NL80211 +//#define NLENTER {} +//#define NLEXIT {} +#define NLENTER printk("[RTKNL][%s][%s] +++ \n", priv->dev->name, (char *)__FUNCTION__) +#define NLEXIT printk("[RTKNL][%s][%s] --- \n\n", priv->dev->name, (char *)__FUNCTION__) +#define NLINFO(fmt, args...) printk("[RTKNL][%s %d]"fmt, __FUNCTION__,__LINE__, ## args) +#define NLNOT printk("[RTKNL][%s %d] !!! NOT implement YET !!!\n", (char *)__FUNCTION__,__LINE__) +#else +#define NLENTER +#define NLEXIT +#define NLINFO(fmt, args...) +#define NLNOT +#endif + +void void_printk_nl80211(const char *fmt, ...) +{ + ; +} + +static void rtk_destroy_dev(struct rtknl *rtk); + +#ifdef DEBUG_NL80211 +#define NLMSG panic_printk +#else +#define NLMSG void_printk_nl80211 +#endif + +//#define SIGNAL_TYPE_UNSPEC + +extern unsigned char WFA_OUI_PLUS_TYPE[]; + +#define RTK_MAX_WIFI_PHY 2 +static int rtk_phy_idx=0; +struct rtknl *rtk_phy[RTK_MAX_WIFI_PHY]; +static dev_t rtk_wifi_dev[RTK_MAX_WIFI_PHY]; +static char *rtk_dev_name[RTK_MAX_WIFI_PHY]={"RTKWiFi0","RTKWiFi1"}; + +char rtk_fake_addr[6]={0x00,0xe0,0x4c,0xcc,0xdd,0x01}; //mark_dual , FIXME if wlan_mac readable + +#define MAX_5G_DIFF_NUM 14 +#define PIN_LEN 8 +#define SIGNATURE_LEN 4 +#if 0 +#ifdef CONFIG_RTL_HW_SETTING_OFFSET +#define HW_SETTING_OFFSET CONFIG_RTL_HW_SETTING_OFFSET +#else +#define HW_SETTING_OFFSET 0x6000 +#endif +#endif +extern unsigned int HW_SETTING_OFFSET; //mark_hw,from rtl819x_flash.c +#define HW_WLAN_SETTING_OFFSET 13 + +__PACK struct hw_wlan_setting { + unsigned char macAddr[6] ; + unsigned char macAddr1[6] ; + unsigned char macAddr2[6] ; + unsigned char macAddr3[6] ; + unsigned char macAddr4[6] ; + unsigned char macAddr5[6] ; + unsigned char macAddr6[6] ; + unsigned char macAddr7[6] ; + unsigned char pwrlevelCCK_A[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrlevelCCK_B[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrlevelHT40_1S_A[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrlevelHT40_1S_B[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiffHT40_2S[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiffHT20[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiffOFDM[MAX_2G_CHANNEL_NUM] ; + unsigned char regDomain ; + unsigned char rfType ; + unsigned char ledType ; // LED type, see LED_TYPE_T for definition + unsigned char xCap ; + unsigned char TSSI1 ; + unsigned char TSSI2 ; + unsigned char Ther ; + unsigned char Reserved1 ; + unsigned char Reserved2 ; + unsigned char Reserved3 ; + unsigned char Reserved4 ; + unsigned char Reserved5 ; + unsigned char Reserved6 ; + unsigned char Reserved7 ; + unsigned char Reserved8 ; + unsigned char Reserved9 ; + unsigned char Reserved10 ; + unsigned char pwrlevel5GHT40_1S_A[MAX_5G_CHANNEL_NUM] ; + unsigned char pwrlevel5GHT40_1S_B[MAX_5G_CHANNEL_NUM] ; + unsigned char pwrdiff5GHT40_2S[MAX_5G_CHANNEL_NUM] ; + unsigned char pwrdiff5GHT20[MAX_5G_CHANNEL_NUM] ; + unsigned char pwrdiff5GOFDM[MAX_5G_CHANNEL_NUM] ; + + + unsigned char wscPin[PIN_LEN+1] ; + +#ifdef RTK_AC_SUPPORT + unsigned char pwrdiff_20BW1S_OFDM1T_A[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_40BW2S_20BW2S_A[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_OFDM2T_CCK2T_A[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_40BW3S_20BW3S_A[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_4OFDM3T_CCK3T_A[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_40BW4S_20BW4S_A[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_OFDM4T_CCK4T_A[MAX_2G_CHANNEL_NUM] ; + + unsigned char pwrdiff_5G_20BW1S_OFDM1T_A[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_40BW2S_20BW2S_A[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_40BW3S_20BW3S_A[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_40BW4S_20BW4S_A[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_RSVD_OFDM4T_A[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_80BW1S_160BW1S_A[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_80BW2S_160BW2S_A[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_80BW3S_160BW3S_A[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_80BW4S_160BW4S_A[MAX_5G_DIFF_NUM] ; + + + unsigned char pwrdiff_20BW1S_OFDM1T_B[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_40BW2S_20BW2S_B[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_OFDM2T_CCK2T_B[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_40BW3S_20BW3S_B[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_OFDM3T_CCK3T_B[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_40BW4S_20BW4S_B[MAX_2G_CHANNEL_NUM] ; + unsigned char pwrdiff_OFDM4T_CCK4T_B[MAX_2G_CHANNEL_NUM] ; + + unsigned char pwrdiff_5G_20BW1S_OFDM1T_B[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_40BW2S_20BW2S_B[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_40BW3S_20BW3S_B[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_40BW4S_20BW4S_B[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_RSVD_OFDM4T_B[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_80BW1S_160BW1S_B[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_80BW2S_160BW2S_B[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_80BW3S_160BW3S_B[MAX_5G_DIFF_NUM] ; + unsigned char pwrdiff_5G_80BW4S_160BW4S_B[MAX_5G_DIFF_NUM] ; + + unsigned char pwrdiff_20BW1S_OFDM1T_C[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_40BW2S_20BW2S_C[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_OFDM2T_CCK2T_C[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_40BW3S_20BW3S_C[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_4OFDM3T_CCK3T_C[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_40BW4S_20BW4S_C[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_OFDM4T_CCK4T_C[MAX_2G_CHANNEL_NUM]; + + unsigned char pwrdiff_5G_20BW1S_OFDM1T_C[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_40BW2S_20BW2S_C[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_40BW3S_20BW3S_C[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_40BW4S_20BW4S_C[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_RSVD_OFDM4T_C[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_80BW1S_160BW1S_C[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_80BW2S_160BW2S_C[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_80BW3S_160BW3S_C[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_80BW4S_160BW4S_C[MAX_5G_CHANNEL_NUM]; + + unsigned char pwrdiff_20BW1S_OFDM1T_D[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_40BW2S_20BW2S_D[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_OFDM2T_CCK2T_D[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_40BW3S_20BW3S_D[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_4OFDM3T_CCK3T_D[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_40BW4S_20BW4S_D[MAX_2G_CHANNEL_NUM]; + unsigned char pwrdiff_OFDM4T_CCK4T_D[MAX_2G_CHANNEL_NUM]; + + unsigned char pwrdiff_5G_20BW1S_OFDM1T_D[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_40BW2S_20BW2S_D[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_40BW3S_20BW3S_D[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_40BW4S_20BW4S_D[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_RSVD_OFDM4T_D[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_80BW1S_160BW1S_D[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_80BW2S_160BW2S_D[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_80BW3S_160BW3S_D[MAX_5G_CHANNEL_NUM]; + unsigned char pwrdiff_5G_80BW4S_160BW4S_D[MAX_5G_CHANNEL_NUM]; + + unsigned char pwrlevelCCK_C[MAX_2G_CHANNEL_NUM]; + unsigned char pwrlevelCCK_D[MAX_2G_CHANNEL_NUM]; + unsigned char pwrlevelHT40_1S_C[MAX_2G_CHANNEL_NUM]; + unsigned char pwrlevelHT40_1S_D[MAX_2G_CHANNEL_NUM]; + unsigned char pwrlevel5GHT40_1S_C[MAX_5G_CHANNEL_NUM]; + unsigned char pwrlevel5GHT40_1S_D[MAX_5G_CHANNEL_NUM]; +#endif +}__WLAN_ATTRIB_PACK__; + +__PACK struct param_header { + unsigned char signature[SIGNATURE_LEN]; // Tag + version + unsigned short len ; +} __WLAN_ATTRIB_PACK__; + +unsigned char is_WRT_scan_iface(const char* if_name) +{ +#ifdef CONFIG_OPENWRT_SDK + if((strcmp(if_name, "tmp.wlan0")==0) || (strcmp(if_name, "tmp.wlan1")==0)) + return 1; + else +#endif + return 0; +} + +int is_zero_mac(const unsigned char *mac) +{ + return !(mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]| mac[6]| mac[7]); +} + +void dump_mac(struct rtl8192cd_priv *priv, unsigned char *mac) +{ + if(mac && !is_zero_mac(mac)){ + NDEBUG(" %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); + } +} + +#if defined(P2P_SUPPORT) || defined(HS_WPA_CLI) +// function declaration +int realtek_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *channel, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, + u64 *cookie); + +static int realtek_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie); + +#endif //CONFIG_P2P + +#if defined(VAP_MAC_DRV_READ_FLASH) +int read_flash_hw_mac_vap(unsigned char *mac, int vap_idx) +{ + unsigned int offset; + + //NLENTER; + + if(!mac) + return -1; + + vap_idx +=1; + + if(vap_idx > 7) + return -1; + + offset = HW_SETTING_OFFSET+ sizeof(struct param_header)+ HW_WLAN_SETTING_OFFSET + sizeof(struct hw_wlan_setting) * (rtk_phy_idx-1); + offset += (vap_idx*ETH_ALEN); + offset |= 0xbd000000; + memcpy(mac,(unsigned char *)offset,ETH_ALEN); + + if(is_zero_mac(mac)) + return -1; + + DEBUG_INFO("VAP[%d][%d]=%02x:%02x:%02x:%02x:%02x:%02x\n", (rtk_phy_idx-1), vap_idx, mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); + + return 0; +} +#endif + +//brian, get MAC address from utility, rtk_tx_calr +#if 0 +void read_flash_hw_mac( unsigned char *mac,int idx) +{ + unsigned int offset; + if(!mac) + return; + offset = HW_SETTING_OFFSET+ sizeof(struct param_header)+ HW_WLAN_SETTING_OFFSET + sizeof(struct hw_wlan_setting) * idx; + offset |= 0xbd000000; + memcpy(mac,(unsigned char *)offset,ETH_ALEN); +} +#endif +//#define CPTCFG_CFG80211_MODULE 1 // mark_com + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) +void chan_type_to_name(enum nl80211_channel_type type, char *type_name) +{ + switch (type) { + case NL80211_CHAN_NO_HT: + strcpy(type_name, "RTK_NL80211_CHAN_NO_HT"); + break; + case NL80211_CHAN_HT20: + strcpy(type_name, "RTK_NL80211_CHAN_HT20"); + break; + case NL80211_CHAN_HT40MINUS: + strcpy(type_name, "RTK_NL80211_CHAN_HT40MINUS"); + break; + case NL80211_CHAN_HT40PLUS: + strcpy(type_name, "RTK_NL80211_CHAN_HT40PLUS"); + break; + default: + strcpy(type_name, "NOT SUPPORT TYPE"); + } +} + +enum nl80211_chan_width convert_chan_type2width(enum nl80211_channel_type channel_type) +{ + unsigned char type_name[32]; + enum nl80211_chan_width width; + + chan_type_to_name(channel_type, type_name); + + printk("channel_type:%x %s\n", channel_type, type_name); + + switch (channel_type) { + case NL80211_CHAN_NO_HT: + width = NL80211_CHAN_WIDTH_20_NOHT; + break; + case NL80211_CHAN_HT20: + width = NL80211_CHAN_WIDTH_20; + break; + case NL80211_CHAN_HT40MINUS: + case NL80211_CHAN_HT40PLUS: + width = NL80211_CHAN_WIDTH_40; + break; + default: + width = NL80211_CHAN_WIDTH_20_NOHT; + break; + } + + return width; +} +#endif + +#if 1 //_eric_nl event + +struct rtl8192cd_priv* realtek_get_priv(struct wiphy *wiphy, struct net_device *dev) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + + return (dev) ? (GET_DEV_PRIV(dev)) : (rtk->priv); +} + +struct ieee80211_channel *rtk_get_iee80211_channel(struct wiphy *wiphy, unsigned int channel) +{ + unsigned int freq = 0; + + if(channel >= 34) + freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ); + else + freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ); + + return ieee80211_get_channel(wiphy, freq); + +} + +int translate_ss_result_rssi(int rssi) +{ +#if !defined(SIGNAL_TYPE_UNSPEC) + //reference libiwinfo/iwinfo_nl80211.c - scan_cb + return ((rssi-100+0x100)*100); +#else + return rssi; +#endif +} + +void realtek_cfg80211_inform_bss(struct rtl8192cd_priv *priv) +{ + struct wiphy *wiphy = priv->rtk->wiphy; + struct ieee80211_channel *channel = NULL; + struct cfg80211_bss *bss = NULL; + char tmpbuf[33]; + UINT8 *mac = NULL; + u64 timestamp = 0; + unsigned char ie[MAX_IE_LEN]; + unsigned char ie_len = 0; + unsigned char wpa_ie_len = 0; + unsigned char rsn_ie_len = 0; + unsigned int freq = 0; + + mac = priv->pmib->dot11Bss.bssid; + wpa_ie_len = priv->rtk->clnt_info.wpa_ie.wpa_ie_len; + rsn_ie_len = priv->rtk->clnt_info.rsn_ie.rsn_ie_len; + + channel = rtk_get_iee80211_channel(wiphy, priv->pmib->dot11Bss.channel); + + if(channel == NULL) + { + printk("Null channel!!\n"); + return; + } + + timestamp = priv->pmib->dot11Bss.timestamp; + + ie[0]= _SSID_IE_; + ie[1]= priv->pmib->dot11Bss.ssidlen; + memcpy(ie+2, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + ie_len += (priv->pmib->dot11Bss.ssidlen + 2); + + if((ie_len + wpa_ie_len + rsn_ie_len) < MAX_IE_LEN) + { + if(wpa_ie_len) + { + memcpy(ie+ie_len, priv->rtk->clnt_info.wpa_ie.data, wpa_ie_len); + ie_len += wpa_ie_len; + } + + if(rsn_ie_len) + { + memcpy(ie+ie_len, priv->rtk->clnt_info.rsn_ie.data, rsn_ie_len); + ie_len += rsn_ie_len; + } + } + else + printk("ie_len too long !!!\n"); +#if 1 + NDEBUG2("bss[%s],hw_value[%03d],timestamp[0x%llx]", + priv->pmib->dot11Bss.ssid, + channel->hw_value, + timestamp); + + NDEBUG2("capa[0x%02x],beacon_prd[%d],ie_len[%d],rssi[%d]\n", + priv->pmib->dot11Bss.capability, + priv->pmib->dot11Bss.beacon_prd, + ie_len, + priv->pmib->dot11Bss.rssi); +#endif + + bss = cfg80211_inform_bss(wiphy, channel, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) + CFG80211_BSS_FTYPE_UNKNOWN, +#endif + mac, timestamp, + priv->pmib->dot11Bss.capability, + priv->pmib->dot11Bss.beacon_prd, + ie, ie_len, translate_ss_result_rssi(priv->pmib->dot11Bss.rssi), GFP_ATOMIC); + + if(bss) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + cfg80211_put_bss(wiphy, bss); +#else + cfg80211_put_bss(bss); +#endif + } else { + printk("%s bss = null\n",__func__); + } +} + +void realtek_cfg80211_inform_bss_ies(unsigned char *ie_buf, unsigned int *total_ie_len, + unsigned char ie_id, unsigned char *ie, unsigned char ie_len) +{ + ie_buf[*total_ie_len] = ie_id; + ie_buf[*total_ie_len+1] = ie_len; + *total_ie_len += 2; + memcpy(ie_buf+*total_ie_len,ie,ie_len); + *total_ie_len += ie_len; +} + +#ifdef NOT_RTK_BSP +extern void vxd_copy_ss_result_from_root(struct rtl8192cd_priv *priv); +#endif + +void realtek_cfg80211_inform_ss_result(struct rtl8192cd_priv *priv) +{ + int i; + struct wiphy *wiphy = NULL; + struct ieee80211_channel *channel = NULL; + struct cfg80211_bss *bss = NULL; + + if ( priv->rtk == NULL) + { + printk("inform_ss_result: rtk null\n"); + return; + } + + wiphy = priv->rtk->wiphy; + NLMSG("SiteSurvey Count=%d dev:%s\n", priv->site_survey->count, priv->dev->name); + //printk("SSID BSSID ch prd cap bsc oper ss sq bd 40m\n"); + + if (!priv->scan_req) + { + NLMSG("[%s][%s] No scan_req, No report to NL80211!!\n", priv->dev->name, __FUNCTION__); + return; + } + + for(i=0; isite_survey->count; i++) + { + char tmpbuf[33]; + UINT8 *mac = priv->site_survey->bss[i].bssid; + u64 timestamp = 0; + unsigned char report_ie[MAX_IE_LEN]; + unsigned int report_ie_len = 0; + unsigned char wpa_ie_len = priv->site_survey->bss[i].wpa_ie_len; + unsigned char rsn_ie_len = priv->site_survey->bss[i].rsn_ie_len; +#ifdef WIFI_SIMPLE_CONFIG + unsigned char wps_ie_len = priv->site_survey->wscie[i].wps_ie_len; //wrt-wps-clnt +#endif + unsigned char rtk_p2p_ie_len = priv->site_survey->rtk_p2p_ie[i].p2p_ie_len; //wrt-wps-clnt + +#ifdef NOT_RTK_BSP + unsigned int all_ie_len = priv->site_survey->bss[i].all_ie_len; +#endif + unsigned int total_len = 0; + unsigned int freq = 0; + + channel = rtk_get_iee80211_channel(wiphy, priv->site_survey->bss[i].channel); + + if(channel == NULL) + { + NDEBUG("Null channel!!\n"); + continue; + } + + timestamp = priv->site_survey->bss[i].timestamp; + +#ifdef NOT_RTK_BSP + memcpy(report_ie + report_ie_len, priv->site_survey->bss[i].all_ie, all_ie_len); + report_ie_len += all_ie_len; +#else + report_ie[0]= _SSID_IE_; + report_ie[1]= priv->site_survey->bss[i].ssidlen; + memcpy(report_ie+2, priv->site_survey->bss[i].ssid, priv->site_survey->bss[i].ssidlen); + report_ie_len += (priv->site_survey->bss[i].ssidlen + 2); + + if((report_ie_len + wpa_ie_len + rsn_ie_len + wps_ie_len + rtk_p2p_ie_len) < MAX_IE_LEN) + { + //NDEBUG("\n"); + if(wpa_ie_len) + { + + memcpy(report_ie+report_ie_len, priv->site_survey->bss[i].wpa_ie, wpa_ie_len); + report_ie_len += wpa_ie_len; + //NDEBUG("\n"); + } + + if(rsn_ie_len) + { + + memcpy(report_ie+report_ie_len, priv->site_survey->bss[i].rsn_ie, rsn_ie_len); + report_ie_len += rsn_ie_len; + //NDEBUG("\n"); + } + + if(wps_ie_len) + { + memcpy(report_ie+report_ie_len, priv->site_survey->bss[i].wscie, wps_ie_len); + report_ie_len += wps_ie_len; + NDEBUG2("bss include wps ie[%d]\n",wps_ie_len); + } + + if(rtk_p2p_ie_len) + { + memcpy(report_ie+report_ie_len, priv->site_survey->bss[i].p2p_ie, rtk_p2p_ie_len); + report_ie_len += rtk_p2p_ie_len; + NDEBUG2("scan include p2p ie[%d]\n",rtk_p2p_ie_len); + } + //for DSSET IE + realtek_cfg80211_inform_bss_ies(report_ie,&report_ie_len,_DSSET_IE_,&priv->site_survey->bss[i].channel,DSSET_IE_LEN); + //for ht cap + realtek_cfg80211_inform_bss_ies(report_ie,&report_ie_len,_HT_CAP_,&priv->site_survey->bss[i].ht_cap,HTCAP_IE_LEN); + //for ht oper + realtek_cfg80211_inform_bss_ies(report_ie,&report_ie_len,_HT_IE_,&priv->site_survey->bss[i].ht_info,HTINFO_IE_LEN); + } + else{ + NDEBUG("report_ie_len too long !!!\n"); + } + + #if 0 + printk("[%d=%s] %03d 0x%08x 0x%02x %d %d %d\n", i, priv->site_survey->bss[i].ssid, + channel->hw_value, timestamp, + priv->site_survey->bss[i].capability, + priv->site_survey->bss[i].beacon_prd, report_ie_len, + priv->site_survey->bss[i].rssi); + #endif +#endif + + bss = cfg80211_inform_bss(wiphy, channel, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) + CFG80211_BSS_FTYPE_UNKNOWN, +#endif + mac, timestamp, + priv->site_survey->bss[i].capability, + priv->site_survey->bss[i].beacon_prd, + report_ie, report_ie_len, translate_ss_result_rssi(priv->site_survey->bss[i].rssi), GFP_ATOMIC); + + if(bss) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + cfg80211_put_bss(wiphy, bss); +#else + cfg80211_put_bss(bss); +#endif + } else { + //printk("%s bss = null\n",__func__); + } + } +} + +// static void realtek_cfg80211_sscan_disable(struct rtl8192cd_priv *priv) rename to easy understand name rtk_abort_scan +static void rtk_abort_scan(struct rtl8192cd_priv *priv, enum scan_abort_case abort_case) +{ + struct rtl8192cd_priv *priv_root = GET_ROOT(priv); + struct cfg80211_scan_request *scan_req = priv_root->scan_req; + + NLMSG("[%s] rtk_abort_scan [%p]+++ \n", priv->dev->name, scan_req); + + if(priv_root->scan_req) + { + priv_root->ss_req_ongoing = 0; + priv_root->scan_req = NULL; + } + + if(priv->scan_req) //VXD can also do scan + { + priv->ss_req_ongoing = 0; + priv->scan_req = NULL; + } + + //event_indicate_cfg80211(priv, NULL, CFG80211_SCAN_ABORDED, NULL); + //cfg80211_sched_scan_stopped(wiphy); +} + + + +#define HAPD_READY_RX_EVENT 5 + +void event_to_name(int event, char *event_name) +{ + + switch (event) { + case CFG80211_CONNECT_RESULT: + strcpy(event_name, "CFG80211_CONNECT_RESULT"); + break; + case CFG80211_ROAMED: + strcpy(event_name, "CFG80211_ROAMED"); + break; + case CFG80211_DISCONNECTED: + strcpy(event_name, "CFG80211_DISCONNECTED"); + break; + case CFG80211_IBSS_JOINED: + strcpy(event_name, "CFG80211_IBSS_JOINED"); + break; + case CFG80211_NEW_STA: + strcpy(event_name, "CFG80211_NEW_STA"); + break; + case CFG80211_SCAN_DONE: + strcpy(event_name, "CFG80211_SCAN_DONE"); + break; + case CFG80211_SCAN_ABORTED: + strcpy(event_name, "CFG80211_SCAN_ABORTED"); + break; + case CFG80211_DEL_STA: + strcpy(event_name, "CFG80211_DEL_STA"); + break; + case CFG80211_RADAR_CAC_FINISHED: + strcpy(event_name, "CFG80211_RADAR_CAC_FINISHED"); + break; + case CFG80211_RADAR_DETECTED: + strcpy(event_name, "CFG80211_RADAR_DETECTED"); + break; + case CFG80211_RADAR_CAC_ABORTED: + strcpy(event_name, "CFG80211_RADAR_CAC_ABORTED"); + break; + default: + strcpy(event_name, "UNKNOWN EVENT"); + break; + } + +} + +int event_indicate_cfg80211(struct rtl8192cd_priv *priv, unsigned char *mac, int event, void *extra) +{ + struct net_device *dev = (struct net_device *)priv->dev; + struct stat_info *pstat = NULL; + struct station_info sinfo; + struct wiphy *wiphy = priv->rtk->wiphy; + + u8 assoc_req_ies_buf[256*3]; + u8* ie_pos=assoc_req_ies_buf; + unsigned long flags; + //NLENTER; + + + { + char event_name[32]; + event_to_name(event, event_name); + NLMSG("EVENT [%s][%s=%d]\n", priv->dev->name, event_name, event); + } + + /*cfg p2p 2014-0330 , report CFG80211_NEW_STA , ASAP*/ + if( (event != CFG80211_SCAN_DONE) && (event != CFG80211_NEW_STA) && (event != CFG80211_DEL_STA) && (event != CFG80211_RADAR_CAC_FINISHED) ) { //eric-bb + if( (OPMODE & WIFI_AP_STATE) && (priv->up_time <= HAPD_READY_RX_EVENT) ) + { + NLMSG("ignore cfg event,up_time[%ld],event[%d]\n", priv->up_time,event); + return -1; + } + } + + printk("event_indicate_cfg80211 ++++++ \n"); + + if(mac) + pstat = get_stainfo(priv, mac); + + SMP_LOCK_CFG80211(flags); + + switch(event) { + case CFG80211_CONNECT_RESULT: + { + struct cfg80211_bss *bss = NULL; + NDEBUG3("[%s][CFG80211_CONNECT_RESULT][%d]\n", priv->dev->name, event); + + if(priv->receive_connect_cmd == 0) + { + NDEBUG3("Not received connect cmd yet !! No report CFG80211_CONNECT_RESULT\n"); + break; + } + +#if 0 + bss = cfg80211_get_bss(wiphy, + priv->pmib->dot11Bss.channel, priv->pmib->dot11Bss.bssid, + priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + + if(bss==NULL) + { + NDEBUG2("report this bss\n"); + realtek_cfg80211_inform_bss(priv); + } +#endif + + cfg80211_connect_result(priv->dev, BSSID, + priv->rtk->clnt_info.assoc_req, priv->rtk->clnt_info.assoc_req_len, + priv->rtk->clnt_info.assoc_rsp, priv->rtk->clnt_info.assoc_rsp_len, + WLAN_STATUS_SUCCESS, GFP_KERNEL); + } + break; + case CFG80211_ROAMED: + { + NDEBUG3("[%s][CFG80211_ROAMED][%d]\n", priv->dev->name, event); + break; + } + break; + case CFG80211_DISCONNECTED: + { + //_eric_nl ?? disconnect event no mac, for station mode only ?? + NDEBUG3("[%s][CFG80211_DISCONNECTED][%d]\n", priv->dev->name, event); + cfg80211_disconnected(priv->dev, 0, NULL, 0, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0) + 1, +#endif + GFP_KERNEL); + break; + } + break; + case CFG80211_IBSS_JOINED: + { + struct cfg80211_bss *bss = NULL; + struct ieee80211_channel *channel = NULL; + + bss = cfg80211_get_bss(wiphy, + channel, priv->pmib->dot11Bss.bssid, + priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen, + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + + if(bss==NULL) + { + printk("report this bss\n"); + realtek_cfg80211_inform_bss(priv); + } + + channel = rtk_get_iee80211_channel(wiphy, priv->pmib->dot11Bss.channel); + + cfg80211_ibss_joined(priv->dev, BSSID, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) + channel, +#endif + GFP_KERNEL); + } + break; + case CFG80211_NEW_STA: + { + NDEBUG3("[%s][CFG80211_NEW_STA][%d]\n", priv->dev->name, event); + /* send event to application */ + memset(&sinfo, 0, sizeof(struct station_info)); + memset(assoc_req_ies_buf, 0, sizeof(256*3)); + sinfo.assoc_req_ies = assoc_req_ies_buf; + + if(pstat == NULL) + { + NDEBUG3("!!PSTA = NULL, MAC = %02x:%02x:%02x:%02x:%02x:%02x\n",mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + if(extra == NULL){ + NDEBUG3("NO PSTA for CFG80211_NEW_STA\n"); + break; + } else + pstat = extra; + } + + /* TODO: sinfo.generation ???*/ + if(pstat->wpa_ie[1] > 0){ + sinfo.assoc_req_ies_len += pstat->wpa_ie[1]+2; + memcpy(ie_pos,pstat->wpa_ie, pstat->wpa_ie[1]+2); + ie_pos+=pstat->wpa_ie[1]+2; + } + + + if(pstat->wps_ie[1] > 0) // for wrt-wps + { + sinfo.assoc_req_ies_len += pstat->wps_ie[1]+2; + memcpy(ie_pos,pstat->wps_ie, pstat->wps_ie[1]+2); + ie_pos+=pstat->wps_ie[1]+2; + } + +#if defined(P2P_SUPPORT) + /*p2p support , cfg p2p , 2014 0330 , report p2p_ie included in assoc_req*/ + if(pstat->p2p_ie[1] > 0) + { + sinfo.assoc_req_ies_len += pstat->p2p_ie[1]+2; + memcpy(ie_pos,pstat->p2p_ie, pstat->p2p_ie[1]+2); + ie_pos += (pstat->p2p_ie[1]+2); + } + /*p2p support , cfg p2p , 2014 0330 , report p2p_ie included in assoc_req*/ +#endif + + if(sinfo.assoc_req_ies_len) + sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; + + SMP_UNLOCK_CFG80211(flags); + NDEBUG2("cfg80211_new_sta assoc req,[idx=%d] Rx assoc_req_ies_len = %d\n", priv->dev->ifindex, sinfo.assoc_req_ies_len); + cfg80211_new_sta(priv->dev, mac, &sinfo, GFP_KERNEL); + NDEBUG3("cfg80211_new_sta ,STA[%02x%02x%02x:%02x%02x%02x]\n",mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] ); + netif_wake_queue(priv->dev); //wrt-vap + SMP_LOCK_CFG80211(flags); + + } + break; + case CFG80211_SCAN_ABORTED: + { + //NDEBUG2("[%s][CFG80211_SCAN_ABORTED][%d]\n", priv->dev->name, event); + priv->ss_req_ongoing = 0; +#ifdef USE_OUT_SRC + priv->pshare->bScanInProcess = FALSE; +#endif + + if (priv->scan_req) + { + struct cfg80211_scan_request *scan_req = priv->scan_req; + + priv->scan_req = NULL; + + cfg80211_scan_done(scan_req, true); + } + } + break; + case CFG80211_SCAN_DONE: + { + //NDEBUG2("[%s][CFG80211_SCAN_DONE][%d]\n", priv->dev->name, event); + priv->ss_req_ongoing = 0; + priv->site_survey->count_backup = priv->site_survey->count; + memcpy(priv->site_survey->bss_backup, priv->site_survey->bss, sizeof(struct bss_desc)*priv->site_survey->count); +#if defined(P2P_SUPPORT) + if(rtk_p2p_is_enabled(priv)==CFG80211_P2P){ + rtk_p2p_set_role(priv,priv->p2pPtr->pre_p2p_role); + rtk_p2p_set_state(priv,priv->p2pPtr->pre_p2p_state); + + NDEBUG2("role[%d]\n",rtk_p2p_get_role(priv)); + NDEBUG2("state[%d]\n",rtk_p2p_get_state(priv)); + } +#endif + + if (priv->scan_req) + { + struct cfg80211_scan_request *scan_req = priv->scan_req; + priv->scan_req = NULL; + cfg80211_scan_done(scan_req, false); + } + } + break; + case CFG80211_DEL_STA: + NDEBUG("[%s][CFG80211_DEL_STA][%d]\n", priv->dev->name, event); + cfg80211_del_sta(priv->dev, mac, GFP_KERNEL); + break; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + case CFG80211_RADAR_CAC_FINISHED: + if (priv->pshare->dfs_chan_def && priv->wdev.cac_started) { + NDEBUG("[%s][CFG80211_RADAR_CAC_FINISHED][%d]\n", priv->dev->name, event); + cfg80211_cac_event(priv->dev, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) + priv->pshare->dfs_chan_def, +#endif + NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); + } + break; + case CFG80211_RADAR_DETECTED: + if (priv->pshare->dfs_chan_def && priv->wdev.cac_started) { + NDEBUG("[%s][CFG80211_RADAR_DETECTED][%d]\n", priv->dev->name, event); + cfg80211_radar_event(wiphy, priv->pshare->dfs_chan_def, GFP_KERNEL); + } + break; + case CFG80211_RADAR_CAC_ABORTED: + if (priv->pshare->dfs_chan_def) { + NDEBUG("[%s][CFG80211_RADAR_CAC_ABORTED][%d]\n", priv->dev->name, event); + cfg80211_cac_event(priv->dev, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) + priv->pshare->dfs_chan_def, +#endif + NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); + } + break; +#endif + case CFG80211_REMAIN_CHANNEL: + { + struct wireless_dev *wdev = &priv->wdev; + cfg80211_remain_on_channel_expired( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + wdev, +#else + priv->dev, +#endif + priv->nl_ctx.remain_on_ch_cookie, + &priv->nl_ctx.remain_on_ch_channel, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->nl_ctx.remain_on_ch_type, +#endif + GFP_KERNEL); + } + break; + case CFG80211_MIC_FAILURE: + NDEBUG("[%s][CFG80211_MIC_FAILURE][%d]\n", priv->dev->name, event); + //cfg80211_michael_mic_failure(priv->dev,GFP_KERNEL); + default: + NDEBUG("[%s][Unknown Event !!][%d]\n", priv->dev->name, event); + } + + SMP_UNLOCK_CFG80211(flags); + + printk("event_indicate_cfg80211 -----\n"); + + return -1; +} + + +#endif + +#if 0 +void realtek_ap_calibration(struct rtl8192cd_priv *priv) +{ + NLENTER; + +#if 0 + unsigned char CCK_A[3] = {0x2a,0x2a,0x28}; + unsigned char CCK_B[3] = {0x2a,0x2a,0x28}; + unsigned char HT40_A[3] = {0x2b,0x2b,0x29}; + unsigned char HT40_B[3] = {0x2b,0x2b,0x29}; + unsigned char DIFF_HT40_2S[3] = {0x0,0x0,0x0}; + unsigned char DIFF_20[3] = {0x02,0x02,0x02}; + unsigned char DIFF_OFDM[3] = {0x04,0x04,0x04}; + unsigned int thermal = 0x19; + unsigned int crystal = 32; +#else + unsigned char CCK_A[3] = {0x2b,0x2a,0x29}; + unsigned char CCK_B[3] = {0x2b,0x2a,0x29}; + unsigned char HT40_A[3] = {0x2c,0x2b,0x2a}; + unsigned char HT40_B[3] = {0x2c,0x2b,0x2a}; + unsigned char DIFF_HT40_2S[3] = {0x0,0x0,0x0}; + unsigned char DIFF_20[3] = {0x02,0x02,0x02}; + unsigned char DIFF_OFDM[3] = {0x04,0x04,0x04}; + unsigned int thermal = 0x16; + unsigned int crystal = 32; +#endif + + int tmp = 0; + int tmp2 = 0; + + for(tmp = 0; tmp <=13; tmp ++) + { + if(tmp < 3) + tmp2 = 0; + else if(tmp < 9) + tmp2 = 1; + else + tmp2 = 2; + + priv->pmib->dot11RFEntry.pwrlevelCCK_A[tmp] = CCK_A[tmp2]; + priv->pmib->dot11RFEntry.pwrlevelCCK_B[tmp] = CCK_B[tmp2]; + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[tmp] = HT40_A[tmp2]; + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[tmp] = HT40_B[tmp2]; + priv->pmib->dot11RFEntry.pwrdiffHT40_2S[tmp] = DIFF_HT40_2S[tmp2]; + priv->pmib->dot11RFEntry.pwrdiffHT20[tmp] = DIFF_20[tmp2]; + priv->pmib->dot11RFEntry.pwrdiffOFDM[tmp] = DIFF_OFDM[tmp2]; + } + + priv->pmib->dot11RFEntry.ther = thermal; + priv->pmib->dot11RFEntry.xcap = crystal; + + NLEXIT; +} +#endif + + +//mark_swc +static void rtk_set_phy_channel(struct rtl8192cd_priv *priv,unsigned int channel,unsigned int bandwidth,unsigned int chan_offset) +{ + NDEBUG3("ch[%d]bw[%d]offset[%d]\n",channel,bandwidth,chan_offset); + //priv , share part + priv->pshare->CurrentChannelBW = bandwidth; + priv->pshare->offset_2nd_chan =chan_offset ; + + // wifi chanel hw settting API + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, channel, priv->pshare->offset_2nd_chan); + //printk("rtk_set_phy_channel end !!!\n chan=%d \n",channel ); + +} + +static void rtk_get_band_capa(struct rtl8192cd_priv *priv,BOOLEAN *band_2gig ,BOOLEAN *band_5gig) +{ + //default register as 2.4GHz + *band_2gig = true; + *band_5gig = false; + + if ((GET_CHIP_VER(priv) == VERSION_8812E) +#if defined(CONFIG_WLAN_HAL_8814AE) + || (GET_CHIP_VER(priv) == VERSION_8814A) +#endif + ) + { +#if defined(CONFIG_WLAN_HAL_8814AE) + if(priv->pshare->is5g) +#endif + { + *band_2gig = false; + *band_5gig = true; + } + } + else if (GET_CHIP_VER(priv) == VERSION_8192D) + { + *band_2gig = false; + *band_5gig = true; + } + else if (GET_CHIP_VER(priv) == VERSION_8881A) + { +#if defined(CONFIG_RTL_8881A_SELECTIVE) + //8881A selective mode + *band_2gig = true; + *band_5gig = true; +#else + //use pcie slot 0 for 2.4G 88E/92E, 8881A is 5G now + *band_2gig = false; + *band_5gig = true; +#endif + } + //mark_sel + //if 881a , then it is possible to *band_2gig = true ,*band_5gig = true in selective mode(FLAG?) + //FIXME +} + +void realtek_ap_default_config(struct rtl8192cd_priv *priv) +{ + //short GI default + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M = 1; + //APMDU + priv->pmib->dot11nConfigEntry.dot11nAMPDU = 1; + +#ifdef MBSSID + if(IS_ROOT_INTERFACE(priv)) + { + priv->pmib->miscEntry.vap_enable = 1; //eric-vap //eric-brsc + } + else + { +#if 0 + if(IS_VAP_INTERFACE(priv)) + { + struct rtl8192cd_priv *priv_root = GET_ROOT(priv); + struct rtl8192cd_priv *priv_vxd = GET_VXD_PRIV(priv_root); + unsigned char is_vxd_running = 0; + + if(priv_vxd) + is_vxd_running = netif_running(priv_vxd->dev); + + if(priv_root->pmib->miscEntry.vap_enable == 0) + { + priv_root->pmib->miscEntry.vap_enable = 1; + + if(is_vxd_running) + rtl8192cd_close(priv_vxd->dev); + + rtl8192cd_close(priv_root->dev); + rtl8192cd_open(priv_root->dev); + + if(is_vxd_running) + rtl8192cd_open(priv_vxd->dev); + + } + } +#endif + //vif copy settings from root + priv->pmib->dot11BssType.net_work_type = GET_ROOT(priv)->pmib->dot11BssType.net_work_type; + priv->pmib->dot11RFEntry.phyBandSelect = GET_ROOT(priv)->pmib->dot11RFEntry.phyBandSelect; + priv->pmib->dot11RFEntry.dot11channel = GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel; + priv->pmib->dot11nConfigEntry.dot11nUse40M = GET_ROOT(priv)->pmib->dot11nConfigEntry.dot11nUse40M; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = GET_ROOT(priv)->pmib->dot11nConfigEntry.dot11n2ndChOffset; + + priv->pmib->dot11OperationEntry.dot11FragmentationThreshold = GET_ROOT(priv)->pmib->dot11OperationEntry.dot11FragmentationThreshold; + priv->pmib->dot11OperationEntry.dot11RTSThreshold = GET_ROOT(priv)->pmib->dot11OperationEntry.dot11RTSThreshold; + priv->pmib->dot11OperationEntry.dot11ShortRetryLimit = GET_ROOT(priv)->pmib->dot11OperationEntry.dot11ShortRetryLimit; + priv->pmib->dot11OperationEntry.dot11LongRetryLimit = GET_ROOT(priv)->pmib->dot11OperationEntry.dot11LongRetryLimit; + } +#endif + +} + +//mark_priv +#define RTK_PRIV_BW_5M 1 +#define RTK_PRIV_BW_10M 2 +#define RTK_PRIV_BW_80M_MINUS 3 +#define RTK_PRIV_BW_80M_PLUS 4 + +static inline int is_hw_vht_support(struct rtl8192cd_priv *priv) +{ + int support=0; + + if (GET_CHIP_VER(priv) == VERSION_8812E) + support=1; + else if (GET_CHIP_VER(priv) == VERSION_8881A) + support=1; + + return support; +} +//priv low bandwidth +static inline int is_hw_lbw_support(struct rtl8192cd_priv *priv) +{ + int support=0; + + if (GET_CHIP_VER(priv) == VERSION_8812E) + support=1; +#if defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv) == VERSION_8192E) && (_GET_HAL_DATA(priv)->cutVersion == ODM_CUT_C)) + support=1; +#endif + if(!support) + printk("This IC NOT support 5M10M !! \n"); + + return support; +} + +static inline int convert_privBW(char *str_bw) //mark_priv +{ + int priv_bw=0; + + if(!strcmp(str_bw,"5M")) + priv_bw = RTK_PRIV_BW_5M; + else if(!strcmp(str_bw,"10M")) + priv_bw = RTK_PRIV_BW_10M; + //future 160M + + return priv_bw; +} + +int check_5M10M_config(struct rtl8192cd_priv *priv) +{ + + int priv_bw=0; + int ret = 0; + + priv_bw = convert_privBW(priv->pshare->rf_ft_var.rtk_uci_PrivBandwidth); + //printk("rtk_set_channel_mode , priv_band= %s , val=%d \n", priv->pshare->rf_ft_var.rtk_uci_PrivBandwidth, priv_bw); + + //first check if priv_band is set + if(priv_bw) + { + //check 5/10M + if( (priv_bw == RTK_PRIV_BW_10M) && is_hw_lbw_support(priv)) + { + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_10; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_DONTCARE; + ret = 1; + NDEBUG("Force config bandwidth=10M\n"); + } + else if( (priv_bw == RTK_PRIV_BW_5M) && is_hw_lbw_support(priv)) + { + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_5; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_DONTCARE; + ret = 1; + NDEBUG("Force config bandwidth=5M\n"); + } + else + NDEBUG("No such priv channel type !!!\n"); + + } + + return ret; + +} + +int is_support_ac(struct rtl8192cd_priv *priv) +{ + int ret=0; + + switch(GET_CHIP_VER(priv)) { + case VERSION_8812E: + case VERSION_8881A: + ret=1; + break; +#if defined(CONFIG_WLAN_HAL_8814AE) + case VERSION_8814A: + if(priv->pshare->is5g) + ret=1; +#endif + } + + return ret; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +static void rtk_set_band_mode(struct rtl8192cd_priv *priv, enum ieee80211_band band ,enum nl80211_chan_width channel_width) +#else +static void rtk_set_band_mode(struct rtl8192cd_priv *priv, int band, int channel_width) +#endif +{ + NDEBUG2("\n"); + + if(band == IEEE80211_BAND_2GHZ) + { + priv->pmib->dot11BssType.net_work_type = WIRELESS_11B|WIRELESS_11G; + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; + } + else if(band == IEEE80211_BAND_5GHZ) + { + priv->pmib->dot11BssType.net_work_type = WIRELESS_11A; + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; + } + + if(channel_width != NL80211_CHAN_WIDTH_20_NOHT) { + priv->pmib->dot11BssType.net_work_type |= WIRELESS_11N; + } else { + if((OPMODE & WIFI_AP_STATE) +#ifdef UNIVERSAL_REPEATER + && !under_apmode_repeater(priv) +#endif + ) + priv->rtk->keep_legacy = 1; + } + + if(channel_width == NL80211_CHAN_WIDTH_80 || is_support_ac(priv)) { + priv->pmib->dot11BssType.net_work_type |= WIRELESS_11AC; + } + +#ifdef UNIVERSAL_REPEATER + if(IS_ROOT_INTERFACE(priv) && priv->pvxd_priv) + { + priv->pvxd_priv->pmib->dot11BssType.net_work_type = priv->pmib->dot11BssType.net_work_type; + priv->pvxd_priv->pmib->dot11RFEntry.phyBandSelect = priv->pmib->dot11RFEntry.phyBandSelect; + } +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +static void rtk_set_channel_mode(struct rtl8192cd_priv *priv, struct cfg80211_chan_def *chandef) +#else +static void rtk_set_channel_mode(struct rtl8192cd_priv *priv, int channel, enum nl80211_channel_type channel_type) +#endif +{ + int config_BW5m10m=0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + int upper_ch = chandef->center_freq1 > chandef->chan->center_freq; + enum nl80211_chan_width width = chandef->width; +#else + int upper_ch = (channel_type == NL80211_CHAN_HT40PLUS); + enum nl80211_chan_width width = convert_chan_type2width(channel_type); +#endif + + config_BW5m10m = check_5M10M_config(priv); + + //printk("[%s]rtk_set_channel_mode , priv_band= %s , val=%d \n", priv->dev->name, priv->pshare->rf_ft_var.rtk_uci_PrivBandwidth, priv_bw); + + //first check if priv_band is set + if(!config_BW5m10m) + { + //normal channel setup path from cfg80211 + if(width == NL80211_CHAN_WIDTH_40) { + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20_40; + if ( upper_ch ) { + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE; //above + } else { + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW; //below + } + } else if(width == NL80211_CHAN_WIDTH_80) { + //printk("NL80211_CHAN_WIDTH_80\n"); + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_80; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_DONTCARE; //dontcare + } else { +#if 0 + if(chandef->width == NL80211_CHAN_WIDTH_20 || chandef->width == NL80211_CHAN_WIDTH_20_NOHT) + printk("NL80211_CHAN_WIDTH_20\/NL80211_CHAN_WIDTH_20_NOHT\n"); + else + printk("Unknown bandwidth: %d, use 20Mhz be default\n", chandef->width); +#endif + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_DONTCARE; + } + +#ifdef UNIVERSAL_REPEATER + if(IS_ROOT_INTERFACE(priv) && priv->pvxd_priv) + { + priv->pvxd_priv->pmib->dot11nConfigEntry.dot11nUse40M = priv->pmib->dot11nConfigEntry.dot11nUse40M; + priv->pvxd_priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = priv->pmib->dot11nConfigEntry.dot11n2ndChOffset; + } +#endif + + } +} + +void realtek_ap_config_apply(struct rtl8192cd_priv *priv) +{ + #if 0 //def P2P_SUPPORT + int keep_go_state=0; + + if(priv->pmib->p2p_mib.p2p_enabled==CFG80211_P2P){ + keep_go_state=1; + } + #endif + + NLENTER; + +#ifdef UNIVERSAL_REPEATER + if(under_apmode_repeater(priv) && (GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.opmode & WIFI_ASOC_STATE)) { + NLINFO("Repeater! STA is alive, skip down-up\n"); + } + else +#endif + { + NLINFO("[%s][down up]\n",priv->dev->name); + + rtl8192cd_close(priv->dev); +#ifndef NOT_RTK_BSP + priv->dev->flags &= ~IFF_UP; +#endif + #if 0 //def P2P_SUPPORT + if(keep_go_state){ + NDEBUG3("[P2P GO mode]\n"); + priv->pmib->p2p_mib.p2p_enabled=CFG80211_P2P; + } + #endif + rtl8192cd_open(priv->dev); + } + +} + +int realtek_cfg80211_ready(struct rtl8192cd_priv *priv) +{ + + if (netif_running(priv->dev)) + return 1; + else + return 0; +} + +void realtek_reset_security(struct rtl8192cd_priv *priv) +{ + NLENTER; + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + priv->pmib->dot11GroupKeysTable.dot11Privacy = 0; + priv->pmib->dot11RsnIE.rsnielen = 0; // reset RSN IE length +#ifdef CONFIG_IEEE80211W + priv->pmib->dot1180211AuthEntry.dot11IEEE80211W = 0; + priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = 0; +#endif +} + +void realtek_auth_wep(struct rtl8192cd_priv *priv, int cipher) +{ + //_eric_nl ?? wep auto/shared/open ?? + NLENTER; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = cipher; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + NLEXIT; +} + +void realtek_auth_wpa(struct rtl8192cd_priv *priv, int wpa, int psk, int cipher) +{ + int wpa_cipher = 0; + + if(cipher & BIT(_TKIP_PRIVACY_)) + wpa_cipher |= BIT(1); + if(cipher & BIT(_CCMP_PRIVACY_)) + wpa_cipher |= BIT(3); + + NLENTER; + NDEBUG3("%s wpa[%d] psk[%d] cipher[0x%x] wpa_cipher[0x%x]\n",priv->dev->name ,wpa ,psk ,cipher ,wpa_cipher); + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 2; + + if(psk) + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = wpa; + + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1; + + if(wpa & PSK_WPA) + priv->pmib->dot1180211AuthEntry.dot11WPACipher = wpa_cipher; + if(wpa & PSK_WPA2) + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = wpa_cipher; + NLEXIT; +} + +void realtek_get_security(struct rtknl *rtk, struct cfg80211_crypto_settings crypto) +{ + int i = 0; + + rtk->cipher = rtk->wpa = rtk->psk = rtk->sha256 = 0; + + NDEBUG2("n_akm_suites=[%d], n_ciphers_pairwise=[%d]\n", crypto.n_akm_suites, crypto.n_ciphers_pairwise); + + for (i = 0; i < crypto.n_akm_suites; i++) { + switch (crypto.akm_suites[i]) { + case WLAN_AKM_SUITE_8021X: + if (crypto.wpa_versions & NL80211_WPA_VERSION_1) + rtk->wpa |= PSK_WPA; + if (crypto.wpa_versions & NL80211_WPA_VERSION_2) + rtk->wpa |= PSK_WPA2; + break; + case WLAN_AKM_SUITE_PSK: + rtk->psk = 1; + if (crypto.wpa_versions & NL80211_WPA_VERSION_1) + rtk->wpa |= PSK_WPA; + if (crypto.wpa_versions & NL80211_WPA_VERSION_2) + rtk->wpa |= PSK_WPA2; + break; + case WLAN_AKM_SUITE_PSK_SHA256: + rtk->psk = 1; + rtk->sha256 = 1; + if (crypto.wpa_versions & NL80211_WPA_VERSION_1) + rtk->wpa |= PSK_WPA; + if (crypto.wpa_versions & NL80211_WPA_VERSION_2) + rtk->wpa |= PSK_WPA2; + break; + default: + NDEBUG2("[akm_suites]=0x%08x not support\n", crypto.akm_suites[i]); + break; + } + } + +//_eric_nl ?? multiple ciphers ?? + for (i = 0; i < crypto.n_ciphers_pairwise; i++) { + switch (crypto.ciphers_pairwise[i]) { + case WLAN_CIPHER_SUITE_WEP40: + rtk->cipher = BIT(_WEP_40_PRIVACY_); + NDEBUG3("WEP40[%d]\n", i); + break; + case WLAN_CIPHER_SUITE_WEP104: + rtk->cipher = BIT(_WEP_104_PRIVACY_); + NDEBUG3("WEP104[%d]\n", i); + break; + case WLAN_CIPHER_SUITE_TKIP: + rtk->cipher |= BIT(_TKIP_PRIVACY_); + NDEBUG3("TKIP[%d]\n", i); + break; + case WLAN_CIPHER_SUITE_CCMP: + rtk->cipher |= BIT(_CCMP_PRIVACY_); + NDEBUG3("CCMP[%d]\n", i); + break; + default: + NDEBUG3("[ciphers_pairwise]=0x%08x not support\n", crypto.ciphers_pairwise[i]); + break; + } + } + + switch (crypto.cipher_group) { + case WLAN_CIPHER_SUITE_WEP40: + rtk->cipher = BIT(_WEP_40_PRIVACY_); + NDEBUG3("WEP GROUP\n"); + break; + case WLAN_CIPHER_SUITE_WEP104: + rtk->cipher = BIT(_WEP_104_PRIVACY_); + NDEBUG3("WEP GROUP\n"); + break; + case WLAN_CIPHER_SUITE_TKIP: + NDEBUG3("TKIP GROUP\n"); + break; + case WLAN_CIPHER_SUITE_CCMP: + NDEBUG3("CCMP GROUP\n"); + break; + case WLAN_CIPHER_SUITE_SMS4: + NDEBUG3("WAPI GROUP\n"); + break; + default: + NDEBUG3("NONE GROUP\n"); + break; + } +} + +void realtek_set_security(struct rtl8192cd_priv *priv, struct rtknl *rtk) +{ + if (rtk->wpa) + realtek_auth_wpa(priv, rtk->wpa, rtk->psk, rtk->cipher); + else { + if (rtk->cipher & BIT(_WEP_40_PRIVACY_)) + realtek_auth_wep(priv, _WEP_40_PRIVACY_); + else if (rtk->cipher & BIT(_WEP_104_PRIVACY_)) + realtek_auth_wep(priv, _WEP_104_PRIVACY_); + } +} + +void realtek_set_security_ap(struct rtl8192cd_priv *priv, struct rtknl *rtk, struct cfg80211_crypto_settings crypto) +{ + realtek_get_security(rtk, crypto); + +#ifdef CONFIG_IEEE80211W + /* + * hostapd don't set 11w in akm_suites, workaround here + * check dot11IEEE80211W @realtek_set_band + */ + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != NO_MGMT_FRAME_PROTECTION) { + rtk->psk = 1; + rtk->wpa = PSK_WPA2; + } +#endif /* CONFIG_IEEE80211W */ + + realtek_set_security(priv, rtk); +} + +void realtek_set_security_cli(struct rtl8192cd_priv *priv, struct rtknl *rtk, struct cfg80211_connect_params *sme) +{ + realtek_get_security(rtk, sme->crypto); + +#ifdef CONFIG_IEEE80211W_CLI + if (sme->mfp == NL80211_MFP_REQUIRED) + { + if (rtk->sha256 == true) + priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = 1; + else + priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = 0; + + priv->pmib->dot1180211AuthEntry.dot11IEEE80211W = MGMT_FRAME_PROTECTION_OPTIONAL; + } +#endif /* CONFIG_IEEE80211W_CLI */ + + realtek_set_security(priv, rtk); +} + +void realtek_get_key_from_sta(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct key_params *params, u8 key_index) +{ + unsigned int cipher = 0; + struct Dot11EncryptKey *pEncryptKey; + + //_eric_cfg ?? key len data seq for get_key ?? + if(pstat == NULL) + { + if (key_index == priv->default_mgmt_key_idx) + { + NDEBUG("get default mgnt key\n"); + cipher = priv->pmib->dot11IGTKTable.dot11Privacy; + pEncryptKey = &priv->pmib->dot11IGTKTable.dot11EncryptKey; + } + else + { + cipher = priv->pmib->dot11GroupKeysTable.dot11Privacy; + pEncryptKey = &priv->pmib->dot11GroupKeysTable.dot11EncryptKey; + } + } + else + { + cipher = pstat->dot11KeyMapping.dot11Privacy; + pEncryptKey = &pstat->dot11KeyMapping.dot11EncryptKey; + } + + switch (cipher) { + case DOT11_ENC_WEP40: + params->cipher = WLAN_CIPHER_SUITE_WEP40; + params->key_len = 5; + memcpy(params->key, pEncryptKey->dot11TTKey.skey, pEncryptKey->dot11TTKeyLen); + break; + case DOT11_ENC_WEP104: + params->cipher = WLAN_CIPHER_SUITE_WEP104; + params->key_len = 10; + memcpy(params->key, pEncryptKey->dot11TTKey.skey, pEncryptKey->dot11TTKeyLen); + break; + case DOT11_ENC_CCMP: + params->cipher = WLAN_CIPHER_SUITE_CCMP;/*eric refine*/ + params->key_len = 32; + memcpy(params->key, pEncryptKey->dot11TTKey.skey, pEncryptKey->dot11TTKeyLen); + memcpy(params->key+16, pEncryptKey->dot11TMicKey1.skey, pEncryptKey->dot11TMicKeyLen); + break; + case DOT11_ENC_TKIP: + params->cipher = WLAN_CIPHER_SUITE_TKIP;/*eric refine*/ + params->key_len = 32; + memcpy(params->key, pEncryptKey->dot11TTKey.skey, pEncryptKey->dot11TTKeyLen); + memcpy(params->key+16, pEncryptKey->dot11TMicKey1.skey, pEncryptKey->dot11TMicKeyLen); + memcpy(params->key+24, pEncryptKey->dot11TMicKey2.skey, pEncryptKey->dot11TMicKeyLen); + break; + case DOT11_ENC_BIP: + params->cipher = WLAN_CIPHER_SUITE_AES_CMAC; + params->key_len = 32; + memcpy(params->key, pEncryptKey->dot11TTKey.skey, pEncryptKey->dot11TTKeyLen); + memcpy(params->key+16, pEncryptKey->dot11TMicKey1.skey, pEncryptKey->dot11TMicKeyLen); + break; + default: + NDEBUG("cipher(%d) not support!!\n", cipher); + } +} + +void clear_wps_ies(struct rtl8192cd_priv *priv) +{ + priv->pmib->wscEntry.wsc_enable = 0; + + priv->pmib->wscEntry.beacon_ielen = 0; + priv->pmib->wscEntry.probe_rsp_ielen = 0; + priv->pmib->wscEntry.probe_req_ielen = 0; + priv->pmib->wscEntry.assoc_ielen = 0; +} + + +/*void copy_wps_ie(struct rtl8192cd_priv *priv, unsigned char *wps_ie, unsigned char mgmt_type) move to 8192cd_util.c*/ +/*the function can be replaced by rtk_cfg80211_set_wps_p2p_ie*/ +//void rtk_set_ie(struct rtl8192cd_priv *priv, unsigned char *pies, unsigned int ies_len, unsigned char mgmt_type) + + +//static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtl8192cd_priv *priv, char *buf, int len) +int rtk_cfg80211_set_wps_p2p_ie(struct rtl8192cd_priv *priv, const char *buf, int len, int mgmt_type) +{ + int ret = 0; + int wps_ielen = 0; + u8 *wps_ie; + u32 p2p_ielen = 0; + u8 *p2p_ie; + //u32 wfd_ielen = 0; + //u8 *wfd_ie; + u8* p2p_ie_listen_tag_ptr=NULL; + int p2p_ie_listen_tag; + + if(len<=0) + return -1; + + NDEBUG2("mgmt_type=[%d]\n",mgmt_type); + + /*set WPS IE*/ + if((wps_ie = rtk_get_wps_ie(buf, len, NULL, &wps_ielen))) + { + copy_wps_ie(priv,wps_ie,mgmt_type); + } + +#if defined(P2P_SUPPORT) + /*set P2P IE*/ + if((p2p_ie = rtk_get_p2p_ie(buf, len, NULL, &p2p_ielen))) + { + copy_p2p_ie(priv,p2p_ie,mgmt_type); + + if(mgmt_type == MGMT_PROBEREQ){ + /*check if listen channel from cfg80211 equl my keep*/ + p2p_ie_listen_tag_ptr = p2p_search_tag(p2p_ie, p2p_ielen ,TAG_LISTEN_CHANNEL, &p2p_ie_listen_tag); + if(p2p_ie_listen_tag_ptr && p2p_ie_listen_tag==5){ + if( priv->pmib->p2p_mib.p2p_listen_channel != p2p_ie_listen_tag_ptr[4]){ + NDEBUG("listen ch no equl\n"); + priv->pmib->p2p_mib.p2p_listen_channel = p2p_ie_listen_tag_ptr[4]; + } + } + } + + } +#endif + /*set WFD IE to do */ + + return 0; +} + +void dump_ies(struct rtl8192cd_priv *priv, + unsigned char *pies, unsigned int ies_len, unsigned char mgmt_type) +{ + unsigned char *pie = pies; + unsigned int len, total_len = 0; + int i = 0; + + while(1) + { + len = pie[1]; + + total_len += (len+2); + if(total_len > ies_len) + { + printk("Exceed !!\n"); + break; + } + + if(pie[0] == _WPS_IE_) + copy_wps_ie(priv, pie, mgmt_type); + + //printk("[Tag=0x%02x Len=%d(0x%x)]\n", pie[0], len, len); + pie+=2; + +#if 0 + for(i=0; ibeacon_ies) + { + NDEBUG2("beacon_ies_len[%d]\n", info->beacon_ies_len); + rtk_cfg80211_set_wps_p2p_ie(priv, info->beacon_ies, info->beacon_ies_len, MGMT_BEACON); + } + + if(info->proberesp_ies) + { + NDEBUG2("proberesp_ies_len[%d]\n", info->proberesp_ies_len); + rtk_cfg80211_set_wps_p2p_ie(priv, info->proberesp_ies, info->proberesp_ies_len, MGMT_PROBERSP); + } + + if(info->assocresp_ies) + { + NDEBUG2("assocresp_ies_len[%d]\n", info->assocresp_ies_len); + rtk_cfg80211_set_wps_p2p_ie(priv, info->assocresp_ies, info->assocresp_ies_len, MGMT_ASSOCRSP); + } +} + +static int realtek_set_bss(struct rtl8192cd_priv *priv, struct cfg80211_ap_settings *info) +{ + NDEBUG3("SSID[%s]\n", info->ssid); + memcpy(SSID, info->ssid, info->ssid_len); + SSID_LEN = info->ssid_len; + + switch(info->hidden_ssid) + { + case NL80211_HIDDEN_SSID_NOT_IN_USE: + HIDDEN_AP=0; + break; + case NL80211_HIDDEN_SSID_ZERO_CONTENTS: + HIDDEN_AP=1; + break; + case NL80211_HIDDEN_SSID_ZERO_LEN: + HIDDEN_AP=2; + break; + default: + NDEBUG("fail, unknown hidden SSID option[%d]\n", info->hidden_ssid); + return -EOPNOTSUPP; + } + + priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod = info->beacon_interval; + + return 0; +} + +static int realtek_set_auth_type(struct rtl8192cd_priv *priv, enum nl80211_auth_type auth_type) +{ + //NDEBUG3("auth_type[0x%02X]\n", auth_type); + + switch (auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + NDEBUG3("NL80211_AUTHTYPE_OPEN_SYSTEM\n"); + break; + case NL80211_AUTHTYPE_SHARED_KEY: + NDEBUG3("NL80211_AUTHTYPE_SHARED_KEY\n"); + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 1; + break; + case NL80211_AUTHTYPE_NETWORK_EAP: + NDEBUG3("NL80211_AUTHTYPE_NETWORK_EAP\n"); + break; + case NL80211_AUTHTYPE_AUTOMATIC: + NDEBUG3("NL80211_AUTHTYPE_AUTOMATIC\n"); + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + break; + + default: + NDEBUG("no support auth type[0x%02x]\n",auth_type); + return -ENOTSUPP; + } + + return 0; +} + +static void config_ssid_from_beacon(struct rtl8192cd_priv *priv, struct cfg80211_beacon_data *beacon) +{ + u8 *p, *skip_hdr, *ssid; + s32 len, remain_len; + + skip_hdr = beacon->head + (WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_); + remain_len = beacon->head_len - (WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_); + + p = get_ie(skip_hdr, _SSID_IE_, &len, remain_len); + + if (p) + { + ssid = p + 2; + + /* ssid changed */ + if ((len != SSID_LEN) || memcmp(ssid, SSID, len)) + { + memset(SSID, 0, sizeof(SSID)); + memcpy(SSID, ssid, len); + SSID_LEN = len; + init_beacon(priv); + } + } +} + +static void config_security_from_beacon(struct rtl8192cd_priv *priv, + struct cfg80211_beacon_data *beacon) +{ + u8 *p; + s32 len; + u16 cap_info; + bool privacy_enable = false; + + u8 dot11EnablePSK = 0, dot11WPACipher = 0, dot11WPA2Cipher = 0, dot11PrivacyAlgrthm = 0, dot118021xAlgrthm = 0; +#ifdef CONFIG_IEEE80211W + u8 dot11IEEE80211W = 0; + bool dot11EnableSHA256 = false; +#endif + + u16 count, i; + + DOT11_RSN_IE_HEADER *pDot11RSNIEHeader; + DOT11_RSN_IE_SUITE *pDot11RSNIESuite; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite; + DOT11_RSN_CAPABILITY *pDot11RSNCapability; + + if (beacon->head) + { + /* get capability info */ + p = beacon->head + _BEACON_CAP_OFFSET_; + cap_info = le16_to_cpu(*((u16 *)p)); + privacy_enable = (cap_info & BIT4) ? true : false; + } + + if (privacy_enable && beacon->tail_len) + { + /* parse wpa2 */ + p = get_ie(beacon->tail, _RSN_IE_2_, &len, beacon->tail_len); + if (p) + { + /* header */ + p += sizeof(DOT11_WPA2_IE_HEADER); + + /* group chipher */ + pDot11RSNIESuite = (DOT11_RSN_IE_SUITE *)p; + p += sizeof(DOT11_RSN_IE_SUITE); + + /* pairwise chiper */ + pDot11RSNIECountSuite = (DOT11_RSN_IE_COUNT_SUITE *)p; + count = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + + for (i = 0 ; i < count ; ++i) + { + if (pDot11RSNIECountSuite->dot11RSNIESuite[i].Type == DOT11_ENC_TKIP) + dot11WPA2Cipher |= BIT1; + else if (pDot11RSNIECountSuite->dot11RSNIESuite[i].Type == DOT11_ENC_CCMP) + dot11WPA2Cipher |= BIT3; + } + + p += (2 + count * sizeof(DOT11_RSN_IE_SUITE)); + +#ifdef CONFIG_IEEE80211W + /* check akm */ + pDot11RSNIECountSuite = (DOT11_RSN_IE_COUNT_SUITE *)p; + count = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + for (i = 0 ; i < count ; ++i) + if (pDot11RSNIECountSuite->dot11RSNIESuite[i].Type == DOT11_ENC_BIP) + dot11EnableSHA256 = true; + p += (2 + count * sizeof(DOT11_RSN_IE_SUITE)); + + /* rsn cap */ + pDot11RSNCapability = (DOT11_RSN_CAPABILITY *)p; + if (pDot11RSNCapability->field.MFPC && pDot11RSNCapability->field.MFPR) + dot11IEEE80211W = MGMT_FRAME_PROTECTION_REQUIRED; + else if (pDot11RSNCapability->field.MFPC) + dot11IEEE80211W = MGMT_FRAME_PROTECTION_OPTIONAL; + else + dot11IEEE80211W = NO_MGMT_FRAME_PROTECTION; +#endif + } + + /* parse wpa */ + u8 wpa_oui[] = {0x00, 0x50, 0xf2, 0x01}; + size_t offset = 0; + + do + { + p = get_ie(beacon->tail + offset, _RSN_IE_1_, &len, beacon->tail_len - offset); + if (!p) break; + + offset = (p - beacon->tail) + 2 + len; + pDot11RSNIEHeader = (DOT11_RSN_IE_HEADER *)p; + + if (memcmp(pDot11RSNIEHeader->OUI, wpa_oui, sizeof(wpa_oui))) + continue; + + p += sizeof(DOT11_RSN_IE_HEADER); + + /* group cipher */ + p += sizeof(DOT11_RSN_IE_SUITE); + + /* unicast cipher */ + pDot11RSNIECountSuite = (DOT11_RSN_IE_COUNT_SUITE *)p; + count = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + for (i = 0 ; i != count ; ++i) + { + if (pDot11RSNIECountSuite->dot11RSNIESuite[i].Type == DOT11_ENC_TKIP) + dot11WPACipher |= BIT1; + else if (pDot11RSNIECountSuite->dot11RSNIESuite[i].Type == DOT11_ENC_CCMP) + dot11WPACipher |= BIT3; + } + } while (p); + + if (dot11WPACipher) dot11EnablePSK |= PSK_WPA; + if (dot11WPA2Cipher) dot11EnablePSK |= PSK_WPA2; + + if (dot11EnablePSK) + { + if ((dot11WPACipher & BIT3) || (dot11WPA2Cipher & BIT3)) + dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + else + dot11PrivacyAlgrthm = _TKIP_PRIVACY_; + + dot118021xAlgrthm = 1; + +#ifdef CONFIG_IEEE80211W + if (!(dot11EnablePSK == PSK_WPA2) || !(dot11WPA2Cipher & BIT3)) + { + dot11IEEE80211W = 0; + dot11EnableSHA256 = 0; + } +#endif + } + else if (privacy_enable) /* wep encryption */ + { + NDEBUG("wep encryption, need to check dot11PrivacyAlgrthm\n"); + } + + NDEBUG("dot11PrivacyAlgrthm=%d, dot11EnablePSK=%d, dot11WPACipher=%d, dot11WPA2Cipher=%d, dot118021xAlgrthm=%d\n", + dot11PrivacyAlgrthm, dot11EnablePSK, dot11WPACipher, dot11WPA2Cipher, dot118021xAlgrthm); +#ifdef CONFIG_IEEE80211W + NDEBUG("dot11IEEE80211W=%d, dot11EnableSHA256=%d\n", dot11IEEE80211W, dot11EnableSHA256); +#endif + + /* apply setting */ + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = dot11PrivacyAlgrthm; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = dot11EnablePSK; + priv->pmib->dot1180211AuthEntry.dot11WPACipher = dot11WPACipher; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = dot11WPA2Cipher; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = dot118021xAlgrthm; +#ifdef CONFIG_IEEE80211W + priv->pmib->dot1180211AuthEntry.dot11IEEE80211W = dot11IEEE80211W; + priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = dot11EnableSHA256; +#endif + + if (dot11EnablePSK) + nl80211_psk_init(priv); + } +} + +static int realtek_change_beacon(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_beacon_data *beacon) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + + if (!realtek_cfg80211_ready(priv)) + return -EIO; + + if ((OPMODE & WIFI_AP_STATE) == 0) + return -EOPNOTSUPP; + + realtek_set_ies_apmode(priv, beacon);/*cfg p2p*/ + + config_ssid_from_beacon(priv, beacon); + realtek_reset_security(priv); + config_security_from_beacon(priv, beacon); + + NLEXIT; + + return 0; +} + +static int realtek_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + + if(priv->pmib->p2p_mib.p2p_enabled){ + OPMODE = WIFI_STATION_STATE; + priv->pmib->p2p_mib.p2p_enabled=0; + } + + if ((OPMODE & WIFI_AP_STATE) == 0) + return -EOPNOTSUPP; + + rtl8192cd_close(priv->dev); +#ifndef NOT_RTK_BSP + priv->dev->flags &= ~IFF_UP; +#endif + + NLEXIT; + return 0; +} + + +static int realtek_stop_ap(struct wiphy *wiphy, struct net_device *dev) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + int ret = 0; + + NLENTER; +#ifdef UNIVERSAL_REPEATER + if(under_apmode_repeater(priv)) { + NLINFO("Repeater! Do nothing\n"); + } else +#endif + { + ret = realtek_cfg80211_del_beacon(wiphy, dev); + } + + NLEXIT; + return ret; +} + +#if 0 +static int realtek_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + + realtek_ap_beacon(wiphy, dev, info, true); + realtek_ap_config_apply(priv); + + NLEXIT; + return 0; +} + +//_eric_nl ?? what's the diff between st & add beacon?? +static int realtek_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + + realtek_ap_beacon(wiphy, dev, info, false); + + NLEXIT; + return 0; + +} + +//_eric_nl ?? what's the purpose of del_beacon ?? +static int realtek_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + + if (OPMODE & WIFI_AP_STATE == 0) + return -EOPNOTSUPP; + if (priv->assoc_num == 0) + return -ENOTCONN; + + rtl8192cd_close(priv->dev); + + NLEXIT; + return 0; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +static int realtek_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_chan_def *chandef) +#else +static int realtek_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) +#endif +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + int channel = 0; + enum nl80211_band band; + enum nl80211_chan_width width; + + NLENTER; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + channel = ieee80211_frequency_to_channel(chandef->chan->center_freq); + + NDEBUG3("[%s]center_freq=[%u] channel=[%d] hw_value=[%u] bandwidth=[%d]\n", priv->dev->name, + chandef->chan->center_freq, channel, chandef->chan->hw_value, chandef->width); +#else + channel = ieee80211_frequency_to_channel(chan->center_freq); + NDEBUG3("[%s]center_freq=[%u] channel=[%d] hw_value=[%u] bandwidth=[%d] ch_type=[%d]\n", priv->dev->name, + chan->center_freq, channel, chan->hw_value, chan->flags,channel_type); +#endif + + priv->pmib->dot11RFEntry.dot11channel = channel; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + band = chandef->chan->band; + width = chandef->width; + rtk_set_band_mode(priv, band, width); + rtk_set_channel_mode(priv, chandef); +#else + band = chan->band; + width = convert_chan_type2width(channel_type); + rtk_set_band_mode(priv, band, width); + rtk_set_channel_mode(priv, channel, channel_type); +#endif + +// realtek_ap_default_config(priv); +// realtek_ap_config_apply(priv); + + NLEXIT; + return 0; +} + + +//Not in ath6k +static int realtek_cfg80211_change_bss(struct wiphy *wiphy, + struct net_device *dev, + struct bss_parameters *params) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + unsigned char dot11_rate_table[]={2,4,11,22,12,18,24,36,48,72,96,108,0}; + + NLENTER; + +#if 0 +if (params->use_cts_prot >= 0) { + sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; + changed |= BSS_CHANGED_ERP_CTS_PROT; +} +#endif + + priv->pmib->dot11RFEntry.shortpreamble = params->use_short_preamble; + changePreamble(priv, params->use_short_preamble); +#if 0 +if (params->use_short_slot_time >= 0) { + sdata->vif.bss_conf.use_short_slot = + params->use_short_slot_time; + changed |= BSS_CHANGED_ERP_SLOT; +} +#endif + + if (params->basic_rates) { + int i, j; + u32 rates = 0; + + //printk("rate = "); + for (i = 0; i < params->basic_rates_len; i++) { + int rate = params->basic_rates[i]; + //printk("%d ", rate); + + for (j = 0; j < 13; j++) { + if ((dot11_rate_table[j]) == rate) + { + //printk("BIT(%d) ", j); + rates |= BIT(j); + } + + } + } + //printk("\n"); + priv->pmib->dot11StationConfigEntry.dot11BasicRates = rates; + } + + NLEXIT; + return 0; +} + + + +#if 0 + +static int realtek_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_idx, const u8 *mac_addr, + struct key_params *params) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = rtk->priv; + + NLENTER; + return 0; + +} + + +static int realtek_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_idx, const u8 *mac_addr) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = rtk->priv; + + NLENTER; + return 0; +} + +static int realtek_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_idx, const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, + struct key_params *params)) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = rtk->priv; + + NLENTER; + return 0; +} + +#else + + +void set_pairwise_key_for_ibss(struct rtl8192cd_priv *priv, union iwreq_data *wrqu) +{ + int i = 0; + struct stat_info *pstat = NULL; + struct ieee80211req_key *wk = (struct ieee80211req_key *)wrqu->data.pointer; + + printk("set_pairwise_key_for_ibss +++ \n"); + + for(i=0; ipshare->aidarray[i] && (priv->pshare->aidarray[i]->used == TRUE)) + { + pstat = get_stainfo(priv, priv->pshare->aidarray[i]->station.hwaddr); + + if(pstat) + { + memcpy(wk->ik_macaddr, priv->pshare->aidarray[i]->station.hwaddr, ETH_ALEN); + rtl_net80211_setkey(priv->dev, NULL, wrqu, NULL); + } + } + } +} + +//#define TOTAL_CAM_ENTRY (priv->pshare->total_cam_entry) + +static int realtek_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, bool pairwise, + const u8 *mac_addr, + struct key_params *params) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + union iwreq_data wrqu; + struct ieee80211req_key wk; + + NLENTER; + + if (!realtek_cfg80211_ready(priv)) + return -EIO; + + NDEBUG("cipher=0x%x key_len=%d seq_len=%d key_index=%d pairwise=%d for %pM\n", + params->cipher, params->key_len, params->seq_len, + key_index, pairwise, mac_addr); + +#if 0 + if (key_index > TOTAL_CAM_ENTRY) { + NDEBUG("key index [%d] out of bounds\n", key_index); + return -ENOENT; + } + + if(mac_addr == NULL) { + printk("NO MAC Address !!\n"); + return -ENOENT;; + } +#endif + + memset(&wk, 0, sizeof(struct ieee80211req_key)); + + wk.ik_keyix = key_index; + + if(mac_addr != NULL) + memcpy(wk.ik_macaddr, mac_addr, ETH_ALEN); + else + memset(wk.ik_macaddr, 0, ETH_ALEN); + +#if 1 + if (!pairwise) //in rtl_net80211_setkey(), group identification is by mac address + { + unsigned char MULTICAST_ADD[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + + memcpy(wk.ik_macaddr, MULTICAST_ADD, ETH_ALEN); + } +#endif + + switch (params->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + wk.ik_type = IEEE80211_CIPHER_WEP; + //printk("WEP !!\n"); + break; + case WLAN_CIPHER_SUITE_TKIP: + wk.ik_type = IEEE80211_CIPHER_TKIP; + //printk("TKIP !!\n"); + break; + case WLAN_CIPHER_SUITE_CCMP: + wk.ik_type = IEEE80211_CIPHER_AES_CCM; + //printk("AES !!\n"); + break; +#ifdef CONFIG_IEEE80211W + case WLAN_CIPHER_SUITE_AES_CMAC: + wk.ik_type = IEEE80211_CIPHER_AES_CMAC; + break; +#endif + default: + NDEBUG("cipher(0x%08x) not support\n", params->cipher); + return -EINVAL; + } + +#if 0 + switch (rtk->cipher) { //_eric_cfg ?? mixed mode ?? + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + wk.ik_type = IEEE80211_CIPHER_WEP; + break; + case WLAN_CIPHER_SUITE_TKIP: + wk.ik_type = IEEE80211_CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + wk.ik_type = IEEE80211_CIPHER_AES_CCM; + break; + default: + return -ENOTSUPP; + } +#endif + wk.ik_keylen = params->key_len; + memcpy(wk.ik_keydata, params->key, params->key_len); + +#if 0 +{ + int tmp = 0; + printk("keylen = %d: ", wk.ik_keylen); + for(tmp = 0; tmp < wk.ik_keylen; tmp ++) + printk("%02x ", wk.ik_keydata[tmp]); + printk("\n"); +} + + //_eric_cfg ?? key seq is not used ?? + + printk("[%s] add keyid = %d, mac = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + priv->dev->name , wk.ik_keyix, wk.ik_macaddr[0], wk.ik_macaddr[1], wk.ik_macaddr[2], + wk.ik_macaddr[3], wk.ik_macaddr[4], wk.ik_macaddr[5]); + printk("type = 0x%x, flags = 0x%x, keylen = 0x%x \n" + , wk.ik_type, wk.ik_flags, wk.ik_keylen); +#endif + + + wrqu.data.pointer = &wk; + + rtl_net80211_setkey(priv->dev, NULL, &wrqu, NULL); + +#if 1 //wrt-adhoc + if(OPMODE & WIFI_ADHOC_STATE) + { + if(!pairwise) + set_pairwise_key_for_ibss(priv, &wrqu); //or need to apply set_default_key + } +#endif + + NLEXIT; + return 0; + +} + +static int realtek_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, bool pairwise, + const u8 *mac_addr) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + union iwreq_data wrqu; + struct ieee80211req_del_key wk; + int ret=0; + + NLENTER; + + if(!pairwise) + { + // NDEBUG2("No need to delete Groupe key !!\n"); + goto realtek_cfg80211_del_key_end; + } + + + if (!realtek_cfg80211_ready(priv)){ + NDEBUG("No realtek_cfg80211_ready !!\n"); + ret = -EIO; + goto realtek_cfg80211_del_key_end; + } + +#if 0 + if (key_index > TOTAL_CAM_ENTRY) { + NDEBUG("key index %d out of bounds\n" ,key_index); + return -ENOENT; + } +#endif + + memset(&wk, 0, sizeof(struct ieee80211req_del_key)); + + wk.idk_keyix = key_index; + + if(mac_addr != NULL) + memcpy(wk.idk_macaddr, mac_addr, ETH_ALEN); + else + memset(wk.idk_macaddr, 0, ETH_ALEN); + +#if 0 + if (!pairwise) //in rtl_net80211_delkey(), group identification is by mac address + { + unsigned char MULTICAST_ADD[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + unsigned char GROUP_ADD[6]={0x0,0x0,0x0,0x0,0x0,0x0}; + + if(OPMODE & WIFI_AP_STATE) + memcpy(wk->idk_macaddr, GROUP_ADD, ETH_ALEN); + } + + printk("keyid = %d, mac = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n" + , wk.idk_keyix, wk.idk_macaddr[0], wk.idk_macaddr[1], wk.idk_macaddr[2], + wk.idk_macaddr[3], wk.idk_macaddr[4], wk.idk_macaddr[5]); +#endif + + + wrqu.data.pointer = &wk; + + rtl_net80211_delkey(priv->dev, NULL, &wrqu, NULL); + +realtek_cfg80211_del_key_end: + NLEXIT; + return ret; + +} + + + +static int realtek_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, bool pairwise, + const u8 *mac_addr, void *cookie, + void (*callback) (void *cookie, struct key_params *)) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + struct key_params params; + struct stat_info *pstat = NULL; + unsigned int cipher = 0; + + NLENTER; + + if(mac_addr) + pstat = get_stainfo(priv, mac_addr); + + NDEBUG2("key_index [%d]\n", key_index); + + if (!realtek_cfg80211_ready(priv)) + return -EIO; + +#if 0 + if (key_index > TOTAL_CAM_ENTRY) { + NDEBUG("key index [%d] out of bounds\n" , key_index); + return -ENOENT; + } +#endif + + #if 0 + if(pairwise) + { + pstat = get_stainfo(priv, mac_addr); + if (pstat == NULL) + return -ENOENT; + } + #endif + + memset(¶ms, 0, sizeof(params)); + +#ifdef NOT_RTK_BSP + params.key = rtw_zmalloc(64); + params.seq = rtw_zmalloc(64); +#endif + + realtek_get_key_from_sta(priv, pstat, ¶ms, key_index); + + //_eric_cfg ?? key seq is not used ?? + #if 0 + params.seq_len = key->seq_len; + params.seq = key->seq; + #endif + + callback(cookie, ¶ms); + + NLEXIT; + + return 0; +} + +static int realtek_cfg80211_set_default_key(struct wiphy *wiphy, + struct net_device *dev, + u8 key_index, bool unicast, + bool multicast) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + NDEBUG2("defaukt key_index[%d] unicast[%d] multicast[%d] \n", key_index, unicast, multicast); + NLEXIT; + return 0; +} + +static int realtek_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, + struct net_device *dev, + u8 key_idx) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + NDEBUG2(" key_index[%d]\n", key_idx); + priv->default_mgmt_key_idx = key_idx; + return 0; +} + +//not in ath6k +static int realtek_cfg80211_auth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_auth_request *req) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + return 0; +} + +static int realtek_cfg80211_assoc(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_assoc_request *req) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + return 0; +} + +static int realtek_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_deauth_request *req, + void *cookie) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + return 0; +} + +static int realtek_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_disassoc_request *req, + void *cookie) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + return 0; +} + +//Not in ath6k +static int realtek_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_parameters *params) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + + NLEXIT; + return 0; +} + + +void realtek_del_station(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned long flags; + NDEBUG3("\n"); + if(pstat->state & WIFI_ASOC_STATE){ + // if we even received dis_assoc from this STA don't send dis_assoc to it again + NDEBUG3("\n"); + issue_disassoc(priv, pstat->hwaddr, _RSON_AUTH_NO_LONGER_VALID_); + } + + SAVE_INT_AND_CLI(flags); + + if (!SWCRYPTO && pstat->dot11KeyMapping.keyInCam) { + if (CamDeleteOneEntry(priv, pstat->hwaddr, 0, 0)) { + pstat->dot11KeyMapping.keyInCam = FALSE; + pstat->tmp_rmv_key = TRUE; + priv->pshare->CamEntryOccupied--; + } + } + + if (asoc_list_del(priv, pstat)) + { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + LOG_MSG("A STA is rejected by nl80211 - %02X:%02X:%02X:%02X:%02X:%02X\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + } + } + free_stainfo(priv, pstat); + RESTORE_INT(flags); + +} + +//eric ?? can apply to disconnect ?? +static int realtek_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) + struct station_del_parameters *params +#else + u8 *mac +#endif + ) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + struct stat_info *pstat; + int ret=0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) + const u8 *mac = params->mac; +#endif + + NLENTER; + + if(!IS_DRV_OPEN(priv)) { + NLMSG("[%s]%s is not open\n", __func__, priv->dev->name); + goto realtek_cfg80211_del_station_end; + } + + pstat = get_stainfo(priv, mac); + + if (pstat == NULL) { + goto realtek_cfg80211_del_station_end; + } + + NDEBUG("try disassoc sta[%02X%02X%02X%02X%02X%02X]\n", + mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); + + realtek_del_station(priv, pstat); + +realtek_cfg80211_del_station_end: + NLEXIT; + return ret; +} + +static int realtek_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *dev, + u8 *mac, + struct station_parameters *params) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + struct stat_info *pstat = NULL; + union iwreq_data wrqu; + struct ieee80211req_mlme mlme; + int err = 0; + + NLENTER; + + if (! (dev->flags & IFF_UP) ) + return 0; + + if(mac) + { + //dump_mac(priv, mac); + pstat = get_stainfo(priv, mac); + } + + if(pstat == NULL) + goto realtek_cfg80211_change_station_end; + +#if 0 + if ((OPMODE & WIFI_AP_STATE) == 0) + { + return -EOPNOTSUPP; + } +#endif + + memcpy(mlme.im_macaddr, mac, ETH_ALEN); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + err = cfg80211_check_station_change(wiphy, params, + CFG80211_STA_AP_MLME_CLIENT); + + if (err) + { + NDEBUG(" error(%d)!!\n", err); + goto realtek_cfg80211_change_station_end; + } +#else + /* Use this only for authorizing/unauthorizing a station */ + if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) + return -EOPNOTSUPP; +#endif + + if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) + mlme.im_op = IEEE80211_MLME_AUTHORIZE; + else + mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; + + wrqu.data.pointer = &mlme; + +#if 0 + printk("NO SET PORT !!\n"); +#else + + if(mlme.im_op == IEEE80211_MLME_AUTHORIZE){ + NDEBUG3("IEEE80211_MLME_AUTHORIZE(4-way success!)\n"); +#ifdef CONFIG_IEEE80211W + if (OPMODE & WIFI_AP_STATE) { + NDEBUG3("[mgmt_frame_prot]=%d\n", pstat->wpa_sta_info->mgmt_frame_prot); + pstat->isPMF = (pstat->wpa_sta_info->mgmt_frame_prot) ? 1 : 0; + } +#ifdef CONFIG_IEEE80211W_CLI + else if (OPMODE & WIFI_STATION_STATE) { + pstat->isPMF = (priv->support_pmf) ? 1 : 0; + } +#endif +#endif + }else{ + NDEBUG3("IEEE80211_MLME_UNAUTHORIZE(clean port)\n"); + } + + if(priv->pmib->dot1180211AuthEntry.dot11EnablePSK || priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm)//OPENWRT_RADIUS + rtl_net80211_setmlme(priv->dev, NULL, &wrqu, NULL); +#endif + +realtek_cfg80211_change_station_end: + NLEXIT; + return err; +} + +static void realtek_cfg80211_set_rate_info(struct rate_info *r_info, unsigned int rate, unsigned char bw, unsigned char isSgi) +{ + r_info->flags = 0; + +#if defined(RTK_AC_SUPPORT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)) + if (is_VHT_rate(rate)) + { + r_info->flags |= RATE_INFO_FLAGS_VHT_MCS; + r_info->mcs = (rate - VHT_RATE_ID) % 10; + r_info->nss = (rate - VHT_RATE_ID) / 10 + 1; + } + else +#endif + if (is_MCS_rate(rate)) + { + r_info->flags |= RATE_INFO_FLAGS_MCS; + r_info->mcs = (rate - HT_RATE_ID); + } + else + r_info->legacy = (rate&0x7f) * 5; + + if(isSgi) + r_info->flags |= RATE_INFO_FLAGS_SHORT_GI; + + switch(bw) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) + case HT_CHANNEL_WIDTH_160: + r_info->bw = RATE_INFO_BW_160; + break; + case HT_CHANNEL_WIDTH_80: + r_info->bw = RATE_INFO_BW_80; + break; + case HT_CHANNEL_WIDTH_20_40: + r_info->bw = RATE_INFO_BW_40; + break; + case HT_CHANNEL_WIDTH_20: + r_info->bw = RATE_INFO_BW_20; + break; + case HT_CHANNEL_WIDTH_10: + r_info->bw = RATE_INFO_BW_10; + break; + case HT_CHANNEL_WIDTH_5: + r_info->bw = RATE_INFO_BW_5; + break; + default: + NDEBUG2("Unknown bw(=%d)\n", bw); + r_info->bw = RATE_INFO_BW_20; + break; +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + case HT_CHANNEL_WIDTH_160: + r_info->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; + break; + case HT_CHANNEL_WIDTH_80: + r_info->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; + break; +#else + case HT_CHANNEL_WIDTH_20_40: + r_info->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + break; +#endif + } + +} + +static int realtek_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + struct stat_info *pstat = NULL; + + unsigned int tx_rate, rx_rate; + unsigned char tx_bw, rx_bw, tx_sgi, rx_sgi; + + if(mac) + pstat = get_stainfo(priv, mac); + + if(pstat==NULL) + return -ENOENT; + + tx_rate = pstat->current_tx_rate; + rx_rate = pstat->rx_rate; + tx_bw = pstat->tx_bw; + rx_bw = pstat->rx_bw; + tx_sgi = (pstat->ht_current_tx_info&BIT(1))?TRUE:FALSE; + rx_sgi = (pstat->rx_splcp)?TRUE:FALSE; + + + sinfo->filled = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) + sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME) | + BIT(NL80211_STA_INFO_CONNECTED_TIME)| + BIT(NL80211_STA_INFO_RX_BYTES64) | + BIT(NL80211_STA_INFO_RX_PACKETS) | + BIT(NL80211_STA_INFO_TX_BYTES64) | + BIT(NL80211_STA_INFO_TX_PACKETS) | + BIT(NL80211_STA_INFO_SIGNAL) | + BIT(NL80211_STA_INFO_TX_BITRATE) | + BIT(NL80211_STA_INFO_RX_BITRATE) | + 0; +#else + sinfo->filled = STATION_INFO_INACTIVE_TIME | + STATION_INFO_CONNECTED_TIME | +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) + STATION_INFO_RX_BYTES | + STATION_INFO_TX_BYTES | +#else + STATION_INFO_RX_BYTES64 | + STATION_INFO_TX_BYTES64 | +#endif + STATION_INFO_RX_PACKETS | + STATION_INFO_TX_PACKETS | + STATION_INFO_SIGNAL | + STATION_INFO_TX_BITRATE | + STATION_INFO_RX_BITRATE | + 0; +#endif + + sinfo->inactive_time = pstat->idle_count*1000; + sinfo->connected_time = pstat->link_time; + sinfo->rx_bytes = pstat->rx_bytes; + sinfo->rx_packets = pstat->rx_pkts; + sinfo->tx_bytes = pstat->tx_bytes; + sinfo->tx_packets = pstat->tx_pkts; +#if defined(SIGNAL_TYPE_UNSPEC) + sinfo->signal = pstat->rssi; +#else + if(pstat->rssi > 100) + sinfo->signal = -20; + else + sinfo->signal = pstat->rssi-100; +#endif + + realtek_cfg80211_set_rate_info(&sinfo->txrate, tx_rate, tx_bw, tx_sgi); + realtek_cfg80211_set_rate_info(&sinfo->rxrate, rx_rate, rx_bw, rx_sgi); + +#if 0 //_eric_nl ?? sinfo->bss_param ?? + if(OPMODE & WIFI_STATION_STATE) + { + sinfo->filled |= STATION_INFO_BSS_PARAM; + sinfo->bss_param.flags = 0; + sinfo->bss_param.dtim_period = priv->pmib->dot11Bss.dtim_prd; + sinfo->bss_param.beacon_interval = priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod; + } +#endif + + //NLEXIT; + return 0; +} + + +static int realtek_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, + int idx, u8 *mac, struct station_info *sinfo) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + int num = 0; + struct list_head *phead, *plist; + struct stat_info *pstat; + int ret = -ENOENT; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + //NDEBUG2("\n"); + //printk("try dump sta[%d]\n", idx); + + if(idx >= priv->assoc_num) + return -ENOENT; + + phead = &priv->asoc_list; + if (!(priv->drv_state & DRV_STATE_OPEN) || list_empty(phead)) { + return -ENOENT; + } + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + if (num == idx) { + pstat = list_entry(plist, struct stat_info, asoc_list); + if(mac) + memcpy(mac, pstat->hwaddr, ETH_ALEN); + else + mac = pstat->hwaddr; + + ret = realtek_cfg80211_get_station(wiphy, dev, pstat->hwaddr, sinfo); + break; + } + num++; + plist = plist->next; + } + + SMP_UNLOCK_ASOC_LIST(flags); + + //NLEXIT; + return ret; +} + +#if 0 +//not in ath6k +static int realtek_cfg80211_set_txq_params(struct wiphy *wiphy, + struct ieee80211_txq_params *params) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + + NLENTER; + NLNOT; + + printk("queue = %d\n", params->queue); + + return 0; + +} +#endif + +static int realtek_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + + NLENTER; + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) + priv->pmib->dot11OperationEntry.dot11FragmentationThreshold = wiphy->frag_threshold; + if (changed & WIPHY_PARAM_RTS_THRESHOLD) + priv->pmib->dot11OperationEntry.dot11RTSThreshold = wiphy->rts_threshold; + if (changed & WIPHY_PARAM_RETRY_SHORT) + priv->pmib->dot11OperationEntry.dot11ShortRetryLimit = wiphy->retry_short; + if (changed & WIPHY_PARAM_RETRY_LONG) + priv->pmib->dot11OperationEntry.dot11LongRetryLimit = wiphy->retry_long; + +#ifdef UNIVERSAL_REPEATER + if(under_apmode_repeater(priv)) { + priv = GET_VXD_PRIV(priv); + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) + priv->pmib->dot11OperationEntry.dot11FragmentationThreshold = wiphy->frag_threshold; + if (changed & WIPHY_PARAM_RTS_THRESHOLD) + priv->pmib->dot11OperationEntry.dot11RTSThreshold = wiphy->rts_threshold; + if (changed & WIPHY_PARAM_RETRY_SHORT) + priv->pmib->dot11OperationEntry.dot11ShortRetryLimit = wiphy->retry_short; + if (changed & WIPHY_PARAM_RETRY_LONG) + priv->pmib->dot11OperationEntry.dot11LongRetryLimit = wiphy->retry_long; + + NLMSG("Apply advanced settings to VXD(%s)\n",priv->dev->name); + } +#endif + + NLEXIT; + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) +static int realtek_cfg80211_set_ap_chanwidth(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + + NLENTER; + return realtek_cfg80211_set_channel(wiphy, dev, chandef); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +static int realtek_cfg80211_set_monitor_channel(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +#else +static int realtek_cfg80211_set_monitor_channel(struct wiphy *wiphy, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) +#endif +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + + NLENTER; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + return realtek_cfg80211_set_channel(wiphy, priv->dev, chandef); +#else + return realtek_cfg80211_set_channel(wiphy, priv->dev, chan, channel_type); +#endif +} +#endif + +#define MAX_2G_CHANNEL_NUM_MIB 14 +#define MAX_5G_CHANNEL_NUM_MIB 196 + +#define MAX_2G_POWER_dBm 20 //defined by OpenWrt Webpage +#define MAX_5G_POWER_dBm 20 //defined by OpenWrt Webpage + + +unsigned int get_max_power(struct rtl8192cd_priv *priv) +{ + int max_power = 0; + +#ifdef TXPWR_LMT + if(!priv->pshare->rf_ft_var.disable_txpwrlmt) { + if((priv->pshare->txpwr_lmt_HT1S) + && (priv->pshare->txpwr_lmt_HT1S <= priv->pshare->tgpwr_HT1S_new[RF_PATH_A])) + max_power = priv->pshare->txpwr_lmt_HT1S; + else + max_power = priv->pshare->tgpwr_HT1S_new[RF_PATH_A]; + } + else + max_power = priv->pshare->tgpwr_HT1S_new[RF_PATH_A]; +#else + max_power = priv->pshare->tgpwr_HT1S_new[RF_PATH_A]; +#endif + + max_power = (max_power/2); + + //panic_printk("[%s][%s][%d] max_power=%d dBm \n", priv->dev->name, __FUNCTION__, __LINE__, max_power); + + return max_power; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +static int realtek_cfg80211_set_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +#else +static int realtek_cfg80211_set_tx_power(struct wiphy *wiphy, + enum nl80211_tx_power_setting type, int mbm) +#endif +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + int dbm = MBM_TO_DBM(mbm); + int max_pwr=0, rfuoput=0, new_rfuoput=0, i; + + NLENTER; + + max_pwr = get_max_power(priv); + + if(max_pwr == 0) { + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + max_pwr=MAX_5G_POWER_dBm; + else + max_pwr=MAX_2G_POWER_dBm; + } + + //panic_printk("### max_pwr=%d dbm=%d(mbm=%d) \n", max_pwr, dbm, mbm); + + rtk->pwr_set_dbm = dbm; + + if(dbm >= max_pwr) + { + rfuoput = 0; + rtk->pwr_rate = 100; + } +#if defined(DEC_PWR_BY_PERCENTAGE) + else if(dbm >= ((max_pwr*70)/100)) + { + rfuoput = 1; + rtk->pwr_rate = 70; + } + else if(dbm >= ((max_pwr*50)/100)) + { + rfuoput = 2; + rtk->pwr_rate = 50; + } + else if(dbm >= ((max_pwr*35)/100)) + { + rfuoput = 3; + rtk->pwr_rate = 35; + } + else + { + rfuoput = 4; + rtk->pwr_rate = 15; + } + //panic_printk("### rfuoput idx=%d rtk->pwr_rate=%d(percent) \n", rfuoput, rtk->pwr_rate); + + if(rfuoput == 1) + rfuoput = -3; + else if(rfuoput == 2) + rfuoput = -6; + else if(rfuoput == 3) + rfuoput = -9; + else if(rfuoput == 4) + rfuoput = -17; +#else + else{ + rfuoput = (dbm-max_pwr)*2; + } +#endif + new_rfuoput = rfuoput; + + //panic_printk("### from cur_pwr=%d to rfuoput=%d \n",rtk->pwr_cur, rfuoput); + + rfuoput = rfuoput - rtk->pwr_cur; + rtk->pwr_cur = new_rfuoput; + + //panic_printk("### adjust power=%d\n", rfuoput); + + if(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) { + for (i=0; ipmib->dot11RFEntry.pwrlevelCCK_A[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevelCCK_A[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevelCCK_A[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevelCCK_A[i] = 1; + } + if(priv->pmib->dot11RFEntry.pwrlevelCCK_B[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevelCCK_B[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevelCCK_B[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevelCCK_B[i] = 1; + } + #if 0 + if(priv->pmib->dot11RFEntry.pwrlevelCCK_C[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevelCCK_C[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevelCCK_C[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevelCCK_C[i] = 1; + } + if(priv->pmib->dot11RFEntry.pwrlevelCCK_D[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevelCCK_D[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevelCCK_D[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevelCCK_D[i] = 1; + } + #endif + + if(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] = 1; + } + if(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] = 1; + } + #if 0 + if(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_C[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevelHT40_1S_C[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_C[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_C[i] = 1; + } + if(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_D[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevelHT40_1S_D[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_D[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_D[i] = 1; + } + #endif + } + } else { + for (i=0; ipmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = 1; + } + if(priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = 1; + } + #if 0 + if(priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_C[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_C[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_C[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_C[i] = 1; + } + if(priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_D[i] != 0){ + if ((priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_D[i] + rfuoput) >= 1) + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_D[i] += rfuoput; + else + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_D[i] = 1; + } + #endif + } + } + + //Apply config immediately for AP mode + if(OPMODE & WIFI_AP_STATE) + { + if(priv->pmib->dot11RFEntry.dot11channel) + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pmib->dot11nConfigEntry.dot11n2ndChOffset); + } + + return 0; +} + +struct rtl8192cd_priv* get_priv_from_wdev(struct rtknl *rtk, struct wireless_dev *wdev) +{ + struct rtl8192cd_priv *priv = NULL; + int tmp = 0; + + for(tmp = 0; tmp<(IF_NUM); tmp++) + { + if(rtk->rtk_iface[tmp].priv) + if(wdev == &(rtk->rtk_iface[tmp].priv->wdev)) + { + priv = rtk->rtk_iface[tmp].priv; + break; + } + } + + //printk("wdev = 0x%x priv = 0x%x \n", wdev, priv); + + return priv; +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +static int realtek_cfg80211_get_tx_power(struct wiphy *wiphy, + struct wireless_dev *wdev, int *dbm) +#else +static int realtek_cfg80211_get_tx_power(struct wiphy *wiphy, int *dbm) +#endif +{ + struct rtknl *rtk = wiphy_priv(wiphy); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); +#endif + + //NLENTER; + + if(rtk->pwr_set_dbm) + *dbm = rtk->pwr_set_dbm; + else + *dbm = 13; + + //NLEXIT; + return 0; + +} + + +#endif + + +#if 1 +//_eric_nl ?? suspend/resume use open/close ?? +static int realtek_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + + NLENTER; + NLNOT; + + return 0; +} + +static int realtek_cfg80211_resume(struct wiphy *wiphy) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + + NLENTER; + NLNOT; + + return 0; +} + + +/*cfg p2p*/ +void realtek_cfg80211_fill_available_channel(struct rtl8192cd_priv *priv, + struct cfg80211_scan_request *request) +{ + int idx=0; + //NDEBUG("\n"); + if (request->n_channels > 0) { + //request should scan only one band, apply band here cliW + rtk_set_band_mode(priv, request->channels[0]->band, NL80211_CHAN_WIDTH_20_NOHT); + // rtk_set_band_mode(priv, request->channels[0]->band, request->scan_width); + + if(IS_HAL_CHIP(priv) && request->channels[0]->band == IEEE80211_BAND_5GHZ && !(RTL_R8(0x454) & BIT(7))) { + //To prevent treated as 2.4GHz at CheckBand88XX_AC(), Hal88XXPhyCfg.c + //0x454 is configured at rtl8192cd_init_hw_PCI(), rtl8192cd_hw.c + RTL_W8(0x454, RTL_R8(0x454) | BIT(7)); + } + + if(request->n_channels == 3 && + request->channels[0]->hw_value == 1 && + request->channels[1]->hw_value == 6 && + request->channels[2]->hw_value == 11 + ){ + NDEBUG2("social_channel from cfg80211\n"); + } + + priv->available_chnl_num = request->n_channels; + //NDEBUG2("n_channels[%d]\n",n_channels); + if (request->n_channels==1) { + NDEBUG2("n_channels[%d],ch[%d]\n", request->n_channels,ieee80211_frequency_to_channel(request->channels[0]->center_freq)); + } + for (idx = 0; idx < request->n_channels; idx++){ + priv->available_chnl[idx] = ieee80211_frequency_to_channel(request->channels[idx]->center_freq); + } + } +} + +/*cfg p2p*/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) +static int realtek_cfg80211_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request) +#else +static int realtek_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_scan_request *request) +#endif +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv; + struct cfg80211_ssid *ssids = request->ssids; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + priv = get_priv_from_wdev(rtk, request->wdev); + NLMSG("request->flags = 0x%x \n", request->flags); +#else + // priv = rtk->priv; + priv = get_priv_from_wdev(rtk, &rtk->priv->wdev); +#endif + + NLENTER; + + if(is_WRT_scan_iface(priv->dev->name)) + priv = GET_ROOT(priv); + + if ( request->wiphy == NULL ) + request->wiphy = wiphy; + + if (TRUE == priv->pshare->bScanInProcess) { + NLMSG("scan disable (bScanInProcess %s)\n", priv->dev->name); + rtk_abort_scan(priv, SCAN_ABORT_START_AP); + return -EBUSY; + } + + if (!netif_running(priv->dev)){ + NLMSG("scan disable (!netif_running %s)\n", priv->dev->name); + return -ENETDOWN; + } + + if (priv->ss_req_ongoing ){ + NLMSG("scan disable (ss_req_ongoing %s)\n", priv->dev->name); + return -EBUSY; + } + + if (priv->scan_req){ + NLMSG("scan disable (scan_req %s)\n", priv->dev->name); + return -EBUSY; + } + +#if defined(DFS) + if (timer_pending(&GET_ROOT(priv)->ch_avail_chk_timer)) { + NLMSG("%s ch_avail_chk_timer pending\n", priv->dev->name); + return -EBUSY; + } +#endif + + if (request->n_channels == 0) { + NDEBUG("start_scan\n"); + goto start_scan; + } + + #if 0 + { + unsigned char idx; + if(ssids->ssid != NULL ){ + NDEBUG("p2pssid=[%s]\n",ssids->ssid); + } + + if (request->ie) { + printk("request->ie = "); + for(idx=0; idxie_len; idx++) + { + printk(" %02x", request->ie); + } + printk("\n"); + } + + printk("\n"); + + if (request->n_channels > 0) { + unsigned char n_channels = 0; + n_channels = request->n_channels; + for (idx = 0; idx < n_channels; idx++){ + NDEBUG("channel[%d]=%d\n", idx, ieee80211_frequency_to_channel(request->channels[idx]->center_freq)); + } + } + } + #endif + + //rtk_abort_scan(priv); + + priv->ss_ssidlen = 0; + memset(priv->ss_ssid, 0, 32); + +#if defined(P2P_SUPPORT) + if(ssids->ssid != NULL + && !memcmp(ssids->ssid, "DIRECT-", 7) + && rtk_get_p2p_ie((u8 *)request->ie, request->ie_len, NULL, NULL)) + { + NDEBUG("Ssid=[%s],len[%d]...\n",ssids->ssid,ssids->ssid_len); + + priv->ss_ssidlen = ssids->ssid_len; + memcpy(priv->ss_ssid,ssids->ssid,ssids->ssid_len); + + if(!rtk_p2p_is_enabled(priv)){ + NDEBUG3("==>rtk_p2p_enable(CFG80211_P2P)\n"); + rtk_p2p_enable(priv , P2P_DEVICE , CFG80211_P2P); + } + + priv->p2pPtr->pre_p2p_role=rtk_p2p_get_role(priv); + priv->p2pPtr->pre_p2p_state=rtk_p2p_get_state(priv); + + rtk_p2p_set_role(priv,P2P_DEVICE); + rtk_p2p_set_state(priv, P2P_S_SEARCH); + //GET_ROOT(priv)->site_survey_times = SS_COUNT-2; // pre-channel just scan twice + } else +#endif + if(ssids->ssid != NULL) { + NDEBUG3("Ssid=[%s],len[%d]...\n", ssids->ssid, ssids->ssid_len); + priv->ss_ssidlen = ssids->ssid_len; + memcpy(priv->ss_ssid, ssids->ssid, ssids->ssid_len); + priv->site_survey->hidden_ap_found = HIDE_AP_FOUND_DO_ACTIVE_SSAN; + + SSID2SCAN_LEN = (ssids->ssid_len > 32) ? 32 : ssids->ssid_len; + memcpy(SSID2SCAN, ssids->ssid, SSID2SCAN_LEN); + } else + priv->site_survey->hidden_ap_found = 0; + +#if defined(P2P_SUPPORT) + /*set WPS P2P IE to probe_req*/ + if(request->ie && request->ie_len>0) + { + rtk_cfg80211_set_wps_p2p_ie(priv, (u8 *)request->ie, request->ie_len ,MGMT_PROBEREQ ); + } +#endif +#ifdef CUSTOMIZE_SCAN_HIDDEN_AP + //scan for HiddenAP + if(request->n_ssids && request->ssids[0].ssid_len) + { + priv->ss_ssidlen = request->ssids[0].ssid_len; + memcpy(priv->ss_ssid, request->ssids[0].ssid, request->ssids[0].ssid_len); + } +#endif + + #if 0//def WIFI_SIMPLE_CONFIG + if (len == 2) + priv->ss_req_ongoing = 2; // WiFi-Simple-Config scan-req + else + #endif + +start_scan: + if(IS_VXD_INTERFACE(priv)) + priv->ss_req_ongoing = SSFROM_REPEATER_VXD; + else + priv->ss_req_ongoing = SSFROM_WEB; + + priv->scan_req = request; + if(request->n_channels > 0) { + /*use channels from cfg80211 parameter*/ + realtek_cfg80211_fill_available_channel(priv,request); + } else { + /*use rtk default available channels*/ + get_available_channel(priv); + } + + NDEBUG("start_clnt_ss\n"); + start_clnt_ss(priv); + + NLEXIT; + return 0; +} + +static void realtek_set_band(struct rtl8192cd_priv *priv, struct cfg80211_beacon_data *beacon) +{ +#ifdef CONFIG_IEEE80211W + enum mfp_options dot11IEEE80211W = NO_MGMT_FRAME_PROTECTION; + bool dot11EnableSHA256 = false; +#endif + bool is_b_only = true, is_ht_enable = false, is_vht_enable = false; + bool dot11nShortGIfor20M = false, dot11nShortGIfor40M = false, dot11nShortGIfor80M = false, dot11nAMPDU = false; + u8 net_work_type = WIRELESS_11B; + u8 phyBandSelect; + + NLENTER; + + if (beacon->tail_len) + { + unsigned char *p; + unsigned int len; + + /* after TIM IE */ + // mem_dump("beacon tail", beacon->tail, beacon->tail_len); + + p = get_ie(beacon->tail, _EXT_SUPPORTEDRATES_IE_, &len, beacon->tail_len); + if (p) + is_b_only = false; + + p = get_ie(beacon->tail, _HT_CAP_, &len, beacon->tail_len); + if (p) + { + struct ht_cap_elmt *ht_cap = (p + 2); + + is_ht_enable = true; + dot11nAMPDU = true; + + if (ht_cap->ht_cap_info & HT_CAP_INFO_SHORT_GI20MHZ) + dot11nShortGIfor20M = true; + + if (ht_cap->ht_cap_info & HT_CAP_INFO_SHORT_GI40MHZ) + dot11nShortGIfor40M = true; + } + +#ifdef RTK_AC_SUPPORT + p = get_ie(beacon->tail, EID_VHTCapability, &len, beacon->tail_len); + if (p) + { + struct vht_cap_elmt *vht_cap = (p + 2); + + is_vht_enable = true; + + if (vht_cap->vht_cap_info & VHT_CAP_SHORT_GI_80) + dot11nShortGIfor80M = true; + } +#endif + +#ifdef CONFIG_IEEE80211W + /* check 11w configuration */ + p = get_ie(beacon->tail, _RSN_IE_2_, &len, beacon->tail_len); + if (p) + { + unsigned short count, i; + signed short valid_len = len + 2; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite; + DOT11_RSN_CAPABILITY *pDot11RSNCapability; + unsigned char oui[4] = {0x00, 0x0f, 0xac, 0x06}; + + /* skip hdr and group chipher */ + p += sizeof(DOT11_WPA2_IE_HEADER) + sizeof(DOT11_RSN_IE_SUITE); + valid_len -= sizeof(DOT11_WPA2_IE_HEADER) + sizeof(DOT11_RSN_IE_SUITE); + if (valid_len < 0) goto check_end; + + /* skip pairwise chiper */ + pDot11RSNIECountSuite = (DOT11_RSN_IE_COUNT_SUITE *)p; + count = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + p += (2 + count * sizeof(DOT11_RSN_IE_SUITE)); + valid_len -= (2 + count * sizeof(DOT11_RSN_IE_SUITE)); + if (valid_len < 0) goto check_end; + +#ifdef CONFIG_IEEE80211W + /* check akm */ + pDot11RSNIECountSuite = (DOT11_RSN_IE_COUNT_SUITE *)p; + count = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + for (i = 0 ; i < count ; ++i) + if (!memcmp(&pDot11RSNIECountSuite->dot11RSNIESuite[i], oui, sizeof(DOT11_RSN_IE_SUITE))) + dot11EnableSHA256 = true; + p += (2 + count * sizeof(DOT11_RSN_IE_SUITE)); + valid_len -= (2 + count * sizeof(DOT11_RSN_IE_SUITE)); + if (valid_len < 0) goto check_end; + + /* rsn cap */ + pDot11RSNCapability = (DOT11_RSN_CAPABILITY *)p; + if (pDot11RSNCapability->field.MFPC && pDot11RSNCapability->field.MFPR) + dot11IEEE80211W = MGMT_FRAME_PROTECTION_REQUIRED; + else if (pDot11RSNCapability->field.MFPC) + dot11IEEE80211W = MGMT_FRAME_PROTECTION_OPTIONAL; + else + dot11IEEE80211W = NO_MGMT_FRAME_PROTECTION; +#endif //CONFIG_IEEE80211W + } +check_end: + ; +#endif + } + + NDEBUG(" sgi 20(%d), 40(%d), 80(%d)\n", dot11nShortGIfor20M, dot11nShortGIfor40M, dot11nShortGIfor80M); +#ifdef CONFIG_IEEE80211W + NDEBUG(" 11w(%d), sha256(%d)\n", dot11IEEE80211W, dot11EnableSHA256); +#endif + + /* apply setting */ + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = dot11nShortGIfor20M; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = dot11nShortGIfor40M; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M = dot11nShortGIfor80M; + priv->pmib->dot11nConfigEntry.dot11nAMPDU = dot11nAMPDU; +#ifdef CONFIG_IEEE80211W + priv->pmib->dot1180211AuthEntry.dot11IEEE80211W = dot11IEEE80211W; + priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = dot11EnableSHA256; +#endif + +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv) == VERSION_8814A) + priv->pmib->dot11nConfigEntry.dot11nAMSDU = 2; +#endif + +#ifdef UNIVERSAL_REPEATER + if(IS_ROOT_INTERFACE(priv) && priv->pvxd_priv) + { + priv->pvxd_priv->pmib->dot11nConfigEntry.dot11nAMPDU = priv->pmib->dot11nConfigEntry.dot11nAMPDU; + priv->pvxd_priv->pmib->dot11nConfigEntry.dot11nSTBC = priv->pmib->dot11nConfigEntry.dot11nSTBC; + priv->pvxd_priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M; + priv->pvxd_priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M; + priv->pvxd_priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M = priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M; +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv) == VERSION_8814A) + priv->pvxd_priv->pmib->dot11nConfigEntry.dot11nAMSDU = priv->pmib->dot11nConfigEntry.dot11nAMSDU; +#endif + } +#endif +} + +static int realtek_start_ap(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ap_settings *info) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + struct cfg80211_scan_request *scan_req_pending = NULL; + int ret = 0; + + NLENTER; + + if (!realtek_cfg80211_ready(priv)) + return -EIO; + + if ((OPMODE & (WIFI_AP_STATE | WIFI_ADHOC_STATE)) == 0) //wrt-adhoc + return -EOPNOTSUPP; + + if (info->ssid == NULL) + return -EINVAL; + + scan_req_pending = priv->scan_req; + + if(IS_ROOT_INTERFACE(priv)) + rtk_abort_scan(priv, SCAN_ABORT_START_AP); + + /*fixme, should not enable carrier here. + Under mac80211 architecture will be invoked by compatible-wireless */ + netif_carrier_on(priv->dev); + + realtek_reset_security(priv); + + realtek_set_band(priv, &info->beacon); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) + realtek_cfg80211_set_channel(wiphy, dev, &info->chandef); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + realtek_cfg80211_set_channel(wiphy, dev, info->channel, info->channel_type); +#endif + realtek_set_ies_apmode(priv, &info->beacon); + + ret = realtek_set_bss(priv, info); + + ret = realtek_set_auth_type(priv, info->auth_type); + + realtek_set_security_ap(priv, rtk, info->crypto); + + realtek_ap_default_config(priv); + + realtek_ap_config_apply(priv); + + //start sending beacon, blocked while init_beacon() + priv->pmib->miscEntry.func_off = 0; + + NDEBUG("start ap band=%d channel=%d\n", + priv->pmib->dot11BssType.net_work_type, priv->pmib->dot11RFEntry.dot11channel); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +#if defined(DFS) + if((OPMODE&WIFI_AP_STATE) && info->chandef.chan->dfs_state == NL80211_DFS_AVAILABLE) { + printk("*** [%s]Under DFS channel, radar detection is active ***\n",priv->dev->name); + /* DFS activated after 1 sec; prevent switching channel due to DFS false alarm */ + init_timer(&priv->DFS_timer); + priv->DFS_timer.data = (unsigned long) priv; + priv->DFS_timer.function = rtl8192cd_DFS_timer; + mod_timer(&priv->DFS_timer, jiffies + RTL_SECONDS_TO_JIFFIES(1)); + + init_timer(&priv->dfs_det_chk_timer); + priv->dfs_det_chk_timer.data = (unsigned long) priv; + priv->dfs_det_chk_timer.function = rtl8192cd_dfs_det_chk_timer; + mod_timer(&priv->dfs_det_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pshare->rf_ft_var.dfs_det_period*10)); + + DFS_SetReg(priv); + RTL_W8(TXPAUSE, 0x00); + } +#endif +#endif + + if(scan_req_pending) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + realtek_cfg80211_scan(wiphy, scan_req_pending); +#else + realtek_cfg80211_scan(wiphy, dev, scan_req_pending); +#endif + } + + if(ret){ + NDEBUG("fail[%d]\n",ret); + } + + NLEXIT; + + return ret; +} + + +static int realtek_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *ibss_param) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + + if (!realtek_cfg80211_ready(priv)) + return -EIO; + + if ((OPMODE & WIFI_ADHOC_STATE) == 0) + return -EOPNOTSUPP; + + //printk("Ad-Hoc join [%s] \n", ibss_param->ssid); + + memcpy(SSID, ibss_param->ssid, ibss_param->ssid_len); + SSID_LEN = ibss_param->ssid_len; + + realtek_reset_security(priv); + + if (ibss_param->privacy) + { + realtek_auth_wep(priv, _WEP_40_PRIVACY_); + } + +#if 0 + if (ibss_param->chandef.chan) + { + realtek_cfg80211_set_channel(wiphy, dev, ibss_param->chandef.chan, ibss_param->channel_type); + } +#endif + +#if 0 + + if (ibss_param->channel_fixed) { + /* + * TODO: channel_fixed: The channel should be fixed, do not + * search for IBSSs to join on other channels. Target + * firmware does not support this feature, needs to be + * updated. + */ + return -EOPNOTSUPP; + } + + memset(vif->req_bssid, 0, sizeof(vif->req_bssid)); + if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid)) + memcpy(vif->req_bssid, ibss_param->bssid, + sizeof(vif->req_bssid)); +#endif + +#if defined(CLIENT_MODE) && !defined(NON_NL80211_WPAS) + if(IS_VXD_INTERFACE(priv)) + { + //printk("launch vxd_ibss_beacon timer !!\n"); + construct_ibss_beacon(priv); + issue_beacon_ibss_vxd((unsigned long)priv); + } + + priv->join_res = STATE_Sta_No_Bss; + start_clnt_lookup(priv, 1); +#endif + + NLEXIT; + + return 0; +} + +static int realtek_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + return 0; +} + + +static int realtek_cfg80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, + u8 *addr) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + return 0; +} + +static void realtek_cfg80211_rfkill_poll(struct wiphy *wiphy) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + + NLENTER; +} + + +static int realtek_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, + BOOLEAN enabled, int timeout) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + return 0; +} + +//not in ath6k +static int realtek_cfg80211_set_bitrate_mask(struct wiphy *wiphy, + struct net_device *dev, + const u8 *addr, + const struct cfg80211_bitrate_mask *mask) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + NLNOT; + + //printk("fixed=%d, maxrate=%d\n", mask->fixed, mask->maxrate); //mark_com + + return 0; +} +#endif + +static int apply_acl_rules(struct rtl8192cd_priv *priv) +{ + unsigned int i=0; + + for (i=0; ipmib->dot11StationConfigEntry.dot11AclNum; i++) + { + struct list_head *pnewlist; + struct wlan_acl_node *paclnode; + + pnewlist = priv->wlan_aclpolllist.next; + list_del_init(pnewlist); + + paclnode = list_entry(pnewlist, struct wlan_acl_node, list); + memcpy((void *)paclnode->addr, priv->pmib->dot11StationConfigEntry.dot11AclAddr[i], MACADDRLEN); + paclnode->mode = (unsigned char)priv->pmib->dot11StationConfigEntry.dot11AclMode; + NDEBUG("[Drv]Sync MAC ACL entry[%d]: %02x:%02x:%02x:%02x:%02x:%02x,%s from MIB\n",i, + paclnode->addr[0],paclnode->addr[1],paclnode->addr[2], + paclnode->addr[3],paclnode->addr[4],paclnode->addr[5], + (paclnode->mode&1U)? "Allowed":"Denied"); + list_add_tail(pnewlist, &priv->wlan_acl_list); + } + + return 0; +} + +static int realtek_reset_mac_acl(struct rtl8192cd_priv *priv) +{ + int i, cnt = 0; + struct list_head *phead, *plist; + struct wlan_acl_node *paclnode; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + for(i=0;ipmib->dot11StationConfigEntry.dot11AclNum;i++) { + NDEBUG("Reset MAC ACL entry[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n",i, + priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][0],priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][1], + priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][2],priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][3], + priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][4],priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][5]); + memset(priv->pmib->dot11StationConfigEntry.dot11AclAddr[i],0,MACADDRLEN); + } + + // clear list + phead = &priv->wlan_acl_list; + + if (list_empty(phead)) // nothing to remove + goto exit; + + SMP_LOCK_ACL(flags); + + plist = phead->next; + + while(plist != phead) + { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + list_del_init(&paclnode->list); + list_add_tail(&paclnode->list, &priv->wlan_aclpolllist); + ++cnt; + } + + SMP_UNLOCK_ACL(flags); + +exit: + priv->pmib->dot11StationConfigEntry.dot11AclNum = 0; + priv->pmib->dot11StationConfigEntry.dot11AclMode = 0; + + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) +static int realtek_set_mac_acl(struct wiphy *wiphy, struct net_device *dev, + const struct cfg80211_acl_data *params) +{ + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + int i; + + NLENTER; + + realtek_reset_mac_acl(priv); + + NDEBUG("MAC ACL mode:%s configured\n",(params->acl_policy&NL80211_ACL_POLICY_DENY_UNLESS_LISTED)? "Allow":"Deny"); + priv->pmib->dot11StationConfigEntry.dot11AclMode = (params->acl_policy&NL80211_ACL_POLICY_DENY_UNLESS_LISTED)? 1:2; + + for(i=0;in_acl_entries;i++) { + priv->pmib->dot11StationConfigEntry.dot11AclNum++; + memcpy(priv->pmib->dot11StationConfigEntry.dot11AclAddr[i],params->mac_addrs[i].addr,MACADDRLEN); + NDEBUG("Append MAC ACL entry[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n",i, + priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][0],priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][1], + priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][2],priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][3], + priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][4],priv->pmib->dot11StationConfigEntry.dot11AclAddr[i][5]); + } + NDEBUG("MAC ACL total entry number:%d\n",priv->pmib->dot11StationConfigEntry.dot11AclNum); + + apply_acl_rules(priv); + + NLEXIT; + return 0; +} + +#if defined(DFS) +static int realtek_start_radar_detection (struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_chan_def *chandef, + u32 cac_time_ms) +{ + int ret=0; + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, NULL); + int channel = 0; + + NLENTER; + + /*fixme, should not enable carrier here. + Under mac80211 architecture will be invoked by compatible-wireless */ + netif_carrier_on(priv->dev); + + if(priv->pshare->dfs_chan_def) { + if(priv->pshare->dfs_chan_def->chan) + kfree(priv->pshare->dfs_chan_def->chan); + + kfree(priv->pshare->dfs_chan_def); + } + + priv->pshare->dfs_chan_def = (struct cfg80211_chan_def *)kmalloc(sizeof(*chandef), GFP_KERNEL); + if(priv->pshare->dfs_chan_def) + memset(priv->pshare->dfs_chan_def, 0, sizeof(*chandef)); + else + return -1; + + priv->pshare->dfs_chan_def->chan = (struct ieee80211_channel *)kmalloc(sizeof(struct ieee80211_channel), GFP_KERNEL); + if(priv->pshare->dfs_chan_def->chan) + memset(priv->pshare->dfs_chan_def->chan, 0, sizeof(struct ieee80211_channel)); + else + return -1; + + //backup chandef for DFS report + memcpy(priv->pshare->dfs_chan_def,chandef,sizeof(*chandef)); + memcpy(priv->pshare->dfs_chan_def->chan,chandef->chan,sizeof(struct ieee80211_channel)); + + channel = ieee80211_frequency_to_channel(chandef->chan->center_freq); + + NDEBUG3("center_freq=[%u] channel=[%d] hw_value=[%u] bandwidth=[%d]\n", + chandef->chan->center_freq, channel, chandef->chan->hw_value, chandef->width); + + priv->pmib->dot11RFEntry.dot11channel = channel; + + rtk_set_band_mode(priv,chandef->chan->band , chandef->width); + rtk_set_channel_mode(priv,chandef); + SwChnl(priv, channel, priv->pmib->dot11nConfigEntry.dot11n2ndChOffset); + + init_timer(&priv->ch_avail_chk_timer); + priv->ch_avail_chk_timer.data = (unsigned long) priv; + priv->ch_avail_chk_timer.function = rtl8192cd_ch_avail_chk_timer; + mod_timer(&priv->ch_avail_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(cac_time_ms)); + printk("*** [%s]Activate DFS-CAC for %d miliseconds ***\n",priv->dev->name,cac_time_ms); + + init_timer(&priv->DFS_timer); + priv->DFS_timer.data = (unsigned long) priv; + priv->DFS_timer.function = rtl8192cd_DFS_timer; + + init_timer(&priv->DFS_TXPAUSE_timer); + priv->DFS_TXPAUSE_timer.data = (unsigned long) priv; + priv->DFS_TXPAUSE_timer.function = rtl8192cd_DFS_TXPAUSE_timer; + + /* DFS activated after 5 sec; prevent switching channel due to DFS false alarm */ + mod_timer(&priv->DFS_timer, jiffies + RTL_SECONDS_TO_JIFFIES(5)); + + init_timer(&priv->dfs_det_chk_timer); + priv->dfs_det_chk_timer.data = (unsigned long) priv; + priv->dfs_det_chk_timer.function = rtl8192cd_dfs_det_chk_timer; + mod_timer(&priv->dfs_det_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pshare->rf_ft_var.dfs_det_period*10)); + + DFS_SetReg(priv); + + if (!priv->pmib->dot11DFSEntry.CAC_enable) { + del_timer_sync(&priv->ch_avail_chk_timer); + mod_timer(&priv->ch_avail_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(200)); + } + + priv->pmib->dot11DFSEntry.disable_tx = 1; + + return ret; +} +#endif +#endif + +void copy_bss_ie(struct rtl8192cd_priv *priv, int ix) +{ + int wpa_ie_len = priv->site_survey->bss[ix].wpa_ie_len; + int rsn_ie_len = priv->site_survey->bss[ix].rsn_ie_len; + + priv->rtk->clnt_info.wpa_ie.wpa_ie_len = wpa_ie_len; + memcpy(priv->rtk->clnt_info.wpa_ie.data, priv->site_survey->bss[ix].wpa_ie, wpa_ie_len); + + priv->rtk->clnt_info.rsn_ie.rsn_ie_len = rsn_ie_len; + memcpy(priv->rtk->clnt_info.rsn_ie.data, priv->site_survey->bss[ix].rsn_ie, rsn_ie_len); +} + +int get_bss_by_bssid(struct rtl8192cd_priv *priv, unsigned char* bssid, unsigned int bssdb_count, struct bss_desc *bssdb) +{ + int ix = 0, found = 0; + + STADEBUG("count = %d %02x:%02x:%02x:%02x:%02x:%02x\n", bssdb_count, bssid[0],bssid[1],bssid[2],bssid[3],bssid[4],bssid[5]); + //dump_mac(priv, bssid); + + for(ix = 0 ; ix < bssdb_count ; ix++) //_Eric ?? will bss_backup be cleaned?? -> Not found in codes + { + STADEBUG("[%d]Match %02x:%02x:%02x:%02x:%02x:%02x with %02x:%02x:%02x:%02x:%02x:%02x\n", + ix,bssdb[ix].bssid[0],bssdb[ix].bssid[1], + bssdb[ix].bssid[2],bssdb[ix].bssid[3], + bssdb[ix].bssid[4],bssdb[ix].bssid[5], + bssid[0],bssid[1],bssid[2],bssid[3],bssid[4],bssid[5]); + + if(!memcmp(bssdb[ix].bssid , bssid, 6)) + { + found = 1; + copy_bss_ie(priv, ix); + break; + } + } + + if(found == 0) + { + STADEBUG("%s BSSID NOT Found !!\n",__func__); + return -EINVAL; + } + else + return ix; + +} + + +int get_bss_by_ssid(struct rtl8192cd_priv *priv, const char* ssid, int ssid_len, unsigned int bssdb_count, struct bss_desc *bssdb) +{ + int ix = 0, found = 0; + + STADEBUG("count[%d] ssid[%s]\n", bssdb_count, ssid); + + for(ix = 0 ; ix < bssdb_count ; ix++) //_Eric ?? will bss_backup be cleaned?? -> Not found in codes + { + STADEBUG("[%d]Match %s to %s\n", ix, bssdb[ix].ssid, ssid); + if( ! memcmp(bssdb[ix].ssid , ssid, ssid_len) ) + { + found = 1; + copy_bss_ie(priv, ix); + break; + } + } + + if(found == 0) + { + STADEBUG("SSID NOT Found !!\n"); + return -EINVAL; + } + else + return ix; + +} + +void vxd_copy_ss_result_from_root(struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_priv *priv_root = GET_ROOT(priv); + + priv->site_survey->count_backup = priv_root->site_survey->count_backup; + memcpy(priv->site_survey->bss_backup, priv_root->site_survey->bss_backup, + sizeof(struct bss_desc)*priv_root->site_survey->count_backup); +} + +void vxd_copy_ss_result_to_target(struct rtl8192cd_priv *priv) +{ + priv->site_survey->count_target = priv->site_survey->count_backup; + + memcpy(priv->site_survey->bss_target, priv->site_survey->bss_backup, + sizeof(struct bss_desc)*priv->site_survey->count_backup); +} + +static int realtek_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + unsigned int bssdb_count=0; + struct bss_desc *bssdb=NULL; + int bss_num = -1; + int ret = 0; + + NLENTER; + + if(dev){ + //dump_mac(priv, GET_MY_HWADDR); + } +#ifdef UNIVERSAL_REPEATER //wrt-vxd + if((!IS_ROOT_INTERFACE(priv)) && (!IS_VXD_INTERFACE(priv))) +#else + if(!IS_ROOT_INTERFACE(priv)) +#endif + { + NDEBUG("vap can not connect, switch to root\n"); + priv = GET_ROOT(priv); + } + + if (!realtek_cfg80211_ready(priv)){ + NDEBUG3("return!\n"); + return -EIO; + } + +#if 1 //wrt_clnt + if((OPMODE & WIFI_STATION_STATE) == 0) + { + printk("NOT in Client Mode, can NOT Associate !!!\n"); + return -1; + } +#endif + + //rtk_abort_scan(priv); + + priv->receive_connect_cmd = 1; + +#if 1 //wrt-wps-clnt + priv->pmib->wscEntry.assoc_ielen = 0; + priv->pmib->wscEntry.wsc_enable = 0; + + if (sme->ie && (sme->ie_len > 0)) { + NDEBUG("ie from cfg,len=[%d]\n", sme->ie_len); + /*set WPS P2P IE to Assoc_Req*/ + rtk_cfg80211_set_wps_p2p_ie(priv, sme->ie, sme->ie_len, MGMT_ASSOCREQ); + } + + if(priv->pmib->wscEntry.wsc_enable) + priv->wps_issue_join_req = 1; +#endif + +//=== check parameters + if((sme->bssid == NULL) && (sme->ssid == NULL)) + { + NDEBUG("No bssid&ssid from request !!!\n"); + return -1; + } + + if(OPMODE & WIFI_STATION_STATE) { + bssdb_count = priv->site_survey->count_target; + bssdb = priv->site_survey->bss_target; + } else { + bssdb_count = priv->site_survey->count_backup; + bssdb = priv->site_survey->bss_backup; + } + + if(sme->bssid) { + bss_num = get_bss_by_bssid(priv, sme->bssid, bssdb_count, bssdb); + } else if(sme->ssid) { //?? channel parameter check ?? + bss_num = get_bss_by_ssid(priv, sme->ssid, sme->ssid_len, bssdb_count, bssdb); + } else { + NDEBUG("Unknown rule to search BSS!!\n"); + return -1; + } + + if(bss_num < 0) + { + NDEBUG("Can not found this bss from SiteSurvey result!!\n"); + return -1; + } + + priv->ss_req_ongoing = 0; //found bss, no need to scan ... + +//=== set security + realtek_reset_security(priv); + + realtek_set_security_cli(priv, rtk, sme); + + if(priv->pmib->dot1180211AuthEntry.dot11EnablePSK) { + nl80211_psk_init(priv); // rsn_init(priv); + } + +//=== set key (for wep only) + if(sme->key_len && + (rtk->cipher & (BIT(_WEP_40_PRIVACY_) | BIT(_WEP_104_PRIVACY_)))) + { + NDEBUG2("Set wep key to connect ! \n"); + + if(rtk->cipher & BIT(_WEP_40_PRIVACY_)) + { + priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_WEP40; + + } + else if(rtk->cipher & BIT(_WEP_104_PRIVACY_)) + { + priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_WEP104; + + } + + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[sme->key_idx].skey[0], sme->key, sme->key_len); + + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen = sme->key_len; + memcpy(&priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey[0], sme->key, sme->key_len); + + if(sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 1; + } + + syncMulticastCipher(priv, &bssdb[bss_num]); /*eric refine 23277*/ + + if((OPMODE&(WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE))==(WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE)) { + NDEBUG3("try issue deauth to...\n"); + if(memcmp(priv->pmib->dot11StationConfigEntry.dot11Bssid , bssdb[bss_num].bssid , 6)==0) { + NDEBUG3("issue deauth to...\n"); + //dump_mac(priv,priv->site_survey->bss_target[bss_num].bssid); + issue_deauth(priv,priv->site_survey->bss_target[bss_num].bssid,_RSON_DEAUTH_STA_LEAVING_); + OPMODE &= (~(WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE)) ; + } + } + +#ifdef CLIENT_MODE + //=== connect + ret = rtl_wpas_join(priv, bss_num); +#endif + + NLEXIT; + return ret; +} + + +static int realtek_cfg80211_disconnect(struct wiphy *wiphy, + struct net_device *dev, u16 reason_code) +{ + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + //rtk_abort_scan(priv); + + event_indicate_cfg80211(priv, NULL, CFG80211_DISCONNECTED, NULL); + + if(IS_VXD_INTERFACE(priv)) + rtl8192cd_close(priv->dev); + + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) +static int realtek_cfg80211_channel_switch(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_csa_settings *params) + +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = realtek_get_priv(wiphy, dev); + + NLENTER; + return 0; +} +#endif + +static void realtek_mgmt_frame_register(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else + struct net_device *wdev, +#endif + u16 frame_type, bool reg) +{ + struct rtknl *rtk = wiphy_priv(wiphy); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); +#else + struct rtl8192cd_priv *priv = GET_DEV_PRIV(wdev); +#endif + if ((frame_type == IEEE80211_STYPE_PROBE_REQ) && (OPMODE & WIFI_AP_STATE)) + priv->probe_req_report = reg; +} + +static struct device_type wiphy_type = { + .name = "wlan", +}; + + +int register_netdevice_name_rtk(struct net_device *dev) +{ + int err; + + if (strchr(dev->name, '%')) { + err = dev_alloc_name(dev, dev->name); + if (err < 0) + return err; + } + + return register_netdevice(dev); +} + +#if 1 //wrt-vap + +static int realtek_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type) +{ + switch (type) { + case NL80211_IFTYPE_STATION: + //case NL80211_IFTYPE_P2P_CLIENT: + *nw_type = INFRA_NETWORK; + break; + case NL80211_IFTYPE_ADHOC: + *nw_type = ADHOC_NETWORK; + break; + case NL80211_IFTYPE_AP: + //case NL80211_IFTYPE_P2P_GO: + *nw_type = AP_NETWORK; + break; + default: + printk("invalid interface type %u\n", type); + return -ENOTSUPP; + } + + return 0; +} + +static bool realtek_is_valid_iftype(struct rtknl *rtk, enum nl80211_iftype type, + u8 *if_idx, u8 *nw_type) +{ + if (realtek_nliftype_to_drv_iftype(type, nw_type)) + return false; + + if ( type == NL80211_IFTYPE_AP + || type == NL80211_IFTYPE_STATION + || type == NL80211_IFTYPE_ADHOC +#if defined(P2P_SUPPORT) + || type == NL80211_IFTYPE_P2P_CLIENT + || type == NL80211_IFTYPE_P2P_GO + || type == NL80211_IFTYPE_P2P_DEVICE +#endif + ) //wrt-adhoc + return true; + + return false; +} + +char check_vif_existed(struct rtl8192cd_priv *priv, struct rtknl *rtk, unsigned char *name) +{ + int tmp = 0; + + for(tmp =0; tmp < VIF_NUM; tmp++) + { + if(!strcmp(name, rtk->ndev_name[tmp])) + { + printk("%s = %s, existed in vif[%d]\n", name, rtk->ndev_name[tmp], tmp); + return 1; + } + } + + return 0; +} + +unsigned char check_vif_type_match(struct rtl8192cd_priv *priv, unsigned char is_vxd) +{ + unsigned char ret = 0; + + NDEBUG3("priv[%p],(root=%d vxd=%d vap=%d)\n", priv, IS_ROOT_INTERFACE(priv), IS_VXD_INTERFACE(priv), IS_VAP_INTERFACE(priv)); +#ifdef MBSSID + NDEBUG3("proot_priv[%p],vap_id[%d]\n", priv->proot_priv, priv->vap_id); +#endif + + if(is_vxd && IS_VXD_INTERFACE(priv)) + ret = 1; + + if((!is_vxd) && IS_VAP_INTERFACE(priv)) + ret = 1; + + if(ret){ + NDEBUG2("is_vxd[%d],type OK \n", is_vxd); + }else{ + NDEBUG2("is_vxd[%d],type NOT match \n", is_vxd); + } + + return ret; +} + +void rtk_change_netdev_name(struct rtl8192cd_priv *priv, unsigned char *name) +{ +#if 1 + printk("rtk_change_netdev_name for priv = %p (root=%d vxd=%d vap=%d) +++ \n", + priv, IS_ROOT_INTERFACE(priv), IS_VXD_INTERFACE(priv), IS_VAP_INTERFACE(priv)); + printk("from %s to %s \n", priv->dev->name, name); +#else + dev_change_name(priv->dev, name); //Need to modify kernel code to export this API +#endif +} + +struct rtl8192cd_priv* get_priv_vxd_from_rtk(struct rtknl *rtk) +{ + struct rtl8192cd_priv *priv = NULL; + int tmp = 0; + + for(tmp = 0; tmp<(IF_NUM); tmp++) + { + if(rtk->rtk_iface[tmp].priv) + if(IS_VXD_INTERFACE(rtk->rtk_iface[tmp].priv)) + { + priv = rtk->rtk_iface[tmp].priv; + break; + } + } + + //printk("name = %s priv_vxd = 0x%x \n", priv->dev->name, priv); + + return priv; +} + +struct rtl8192cd_priv* get_priv_from_rtk(struct rtknl *rtk, const char *name) +{ + struct rtl8192cd_priv *priv = NULL; + int tmp = 0; + + for(tmp = 0; tmp<(IF_NUM); tmp++) + { + if(rtk->rtk_iface[tmp].priv) + if(!strcmp(rtk->rtk_iface[tmp].priv->dev->name, name)) + { + priv = rtk->rtk_iface[tmp].priv; + break; + } + } + +#if 0 + if(priv) //rtk_vap + printk("get_priv_from_rtk name = %s priv = 0x%x %s\n", name, priv, priv->dev->name); + else + printk("get_priv_from_rtk = NULL !!\n"); +#endif + + return priv; +} + + +struct rtl8192cd_priv* get_priv_from_ndev(struct rtknl *rtk, struct net_device *ndev) +{ + struct rtl8192cd_priv *priv = NULL; + int tmp = 0; + + for(tmp = 0; tmp<(IF_NUM); tmp++) + { + if(rtk->rtk_iface[tmp].priv) + if(ndev == rtk->rtk_iface[tmp].priv->dev) + { + priv = rtk->rtk_iface[tmp].priv; + break; + } + } + + //printk("ndev = 0x%x priv = 0x%x \n", ndev, priv); + + return priv; +} + +void rtk_add_priv(struct rtl8192cd_priv *priv_add, struct rtknl *rtk) +{ + int tmp = 0; + + for(tmp = 0; tmp<(IF_NUM); tmp++) + { + if(rtk->rtk_iface[tmp].priv == NULL) + { + rtk->rtk_iface[tmp].priv = priv_add; + strcpy(rtk->rtk_iface[tmp].ndev_name, priv_add->dev->name); /*eric refine 23390*/ + break; + } + } +} + +void rtk_del_priv(struct rtl8192cd_priv *priv_del, struct rtknl *rtk) +{ + int tmp = 0; + + for(tmp = 0; tmp<(IF_NUM); tmp++) + { + if(rtk->rtk_iface[tmp].priv == priv_del) + { + rtk->rtk_iface[tmp].priv = NULL; + memset(rtk->rtk_iface[tmp].ndev_name, 0, 32);/*eric refine 23390*/ + break; + } + } +} + +unsigned char find_ava_vif_idx(struct rtknl *rtk) +{ + unsigned char idx = 0; + + for(idx = 0; idx < VIF_NUM; idx ++) + { + if(rtk->ndev_name[idx][0] == 0) + return idx; + } + + return -1; +} + +unsigned char get_vif_idx(struct rtknl *rtk, unsigned char *name) +{ + unsigned char idx = 0; + + for(idx = 0; idx < VIF_NUM; idx ++) + { + if(rtk->ndev_name[idx][0] != 0) + if(strcmp(name, rtk->ndev_name[idx])==0) + return idx; + } + + return -1; +} + + +void realtek_create_vap_iface(struct rtknl *rtk, unsigned char *name) +{ + struct rtl8192cd_priv *priv = rtk->priv; + + if(check_vif_existed(priv, rtk, name)) + { + printk("vif interface already existed !! \n"); + return; + } + + if (rtk->num_vif == VIF_NUM) + { + printk("Reached maximum number of supported vif\n"); + return; + } + + rtk->idx_vif = find_ava_vif_idx(rtk); + + printk("rtk->idx_vif = %d\n", rtk->idx_vif); + + if(rtk->idx_vif < 0) + { + printk("rtk->idx_vif < 0 \n"); + return; + } + + if(name){ + if(dev_valid_name(name)) + strcpy(rtk->ndev_name[rtk->idx_vif], name); + } + else + { + printk("No interface name !!\n"); + return; + } + + rtl8192cd_init_one_cfg80211(rtk); + rtk->num_vif++; +} + +#endif + +int realtek_interface_add(struct rtl8192cd_priv *priv, + struct rtknl *rtk, const char *name, + enum nl80211_iftype type, + u8 fw_vif_idx, u8 nw_type) +{ + struct net_device *ndev; + + NLENTER; + + NDEBUG("type[%d]\n", type); + + ndev = priv->dev; + + //dump_mac(priv, ndev->dev_addr); + + if (!ndev) + { + NDEBUG("ndev = NULL !!\n"); + free_netdev(ndev); + return -1; + } + + strcpy(ndev->name, name); + realtek_change_iftype(priv, type); + + dev_net_set(ndev, wiphy_net(rtk->wiphy)); + + priv->wdev.wiphy = rtk->wiphy; + + ndev->ieee80211_ptr = &priv->wdev; + + SET_NETDEV_DEV(ndev, wiphy_dev(rtk->wiphy)); + + priv->wdev.netdev = ndev; + priv->wdev.iftype = type; + + SET_NETDEV_DEVTYPE(ndev, &wiphy_type); + + priv->cfg80211_interface_add = FALSE; + priv->is_cfg80211_iface = 1; + + register_netdev(ndev); + +#if 0 + if(IS_ROOT_INTERFACE(priv)) + register_netdev(ndev); +#ifdef UNIVERSAL_REPEATER //wrt-vxd + else if(IS_VXD_INTERFACE(priv)) + register_netdev(ndev); +#endif + else + register_netdevice_name_rtk(ndev); +#endif + + rtk->ndev_add = ndev; + + NDEBUG2(" priv=[%p] wdev=[%p] ndev=[%p] rtk=[%p]\n", priv, &priv->wdev, ndev, rtk); + rtk_add_priv(priv, rtk); + + NLEXIT; + + return 0; + +} + +int realtek_interface_del(struct rtl8192cd_priv *priv, struct rtknl *rtk, struct net_device *ndev) +{ + NDEBUG2(" priv=[%p] wdev=[%p] ndev=[%p] rtk=[%p]\n", priv, &priv->wdev, ndev, rtk); + + unregister_netdev(ndev); + + //SET_NETDEV_DEVTYPE(ndev, NULL); + + dev_net_set(ndev, NULL); + + rtk_del_priv(priv, rtk); + + return 0; +} + +#ifdef SUPPORT_MONITOR +void rtk_enable_monitor_mode(struct rtl8192cd_priv *priv) +{ + //if(priv->pmib->miscEntry.scan_enable) + priv->chan_num = 0; + + priv->is_monitor_mode = TRUE; + RTL_W32(RCR, RCR_APP_FCS | RCR_APP_MIC | RCR_APP_ICV | RCR_APP_PHYSTS | RCR_HTC_LOC_CTRL + | RCR_AMF | RCR_ADF | RCR_AICV | RCR_ACRC32 | RCR_CBSSID_ADHOC | RCR_AB | RCR_AM | RCR_APM | RCR_AAP); + + init_timer(&priv->chan_switch_timer); + priv->chan_switch_timer.data = (unsigned long) priv; + priv->chan_switch_timer.function = rtl8192cd_chan_switch_timer; + mod_timer(&priv->chan_switch_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.chan_switch_time)); +} + +void rtk_disable_monitor_mode(struct rtl8192cd_priv *priv) +{ + priv->is_monitor_mode = FALSE; + if (timer_pending(&priv->chan_switch_timer)) + del_timer(&priv->chan_switch_timer); +} +#endif + +void realtek_change_iftype(struct rtl8192cd_priv *priv ,enum nl80211_iftype type) +{ + //OPMODE &= ~(WIFI_STATION_STATE|WIFI_ADHOC_STATE|WIFI_AP_STATE); +#if defined(P2P_SUPPORT) + if(IS_ROOT_INTERFACE(priv) && IS_DRV_OPEN(priv)) { + if(type != NL80211_IFTYPE_P2P_CLIENT) + rtl8192cd_close(priv->dev); + } +#endif + switch (type) { + case NL80211_IFTYPE_STATION: + OPMODE = WIFI_STATION_STATE; + priv->pmib->p2p_mib.p2p_enabled=0; + priv->wdev.iftype = type; + _NDEBUG("switch to [NL80211_IFTYPE_STATION]\n"); + break; + case NL80211_IFTYPE_ADHOC: + OPMODE = WIFI_ADHOC_STATE; + priv->wdev.iftype = type; + priv->pmib->p2p_mib.p2p_enabled=0; + _NDEBUG("switch to [NL80211_IFTYPE_ADHOC]\n"); + break; + case NL80211_IFTYPE_AP: + OPMODE = WIFI_AP_STATE; + priv->wdev.beacon_interval = 0; + priv->pmib->miscEntry.func_off = 1; + priv->pmib->p2p_mib.p2p_enabled=0; + priv->wdev.iftype = type; +#ifdef SUPPORT_MONITOR + rtk_disable_monitor_mode(priv); +#endif +#if defined(DFS) + /*fixme, should not disable carrier here. + Under mac80211 architecture will be invoked by compatible-wireless */ + netif_carrier_off(priv->dev); +#endif + _NDEBUG("switch to [NL80211_IFTYPE_AP]\n"); + break; +#if defined(P2P_SUPPORT) + case NL80211_IFTYPE_P2P_CLIENT: + OPMODE = (WIFI_STATION_STATE ); + rtk_p2p_set_role(priv,P2P_DEVICE); + priv->pmib->p2p_mib.p2p_enabled=CFG80211_P2P; + priv->wdev.iftype = type; + _NDEBUG("switch to [NL80211_IFTYPE_P2P_CLIENT]\n"); + break; + case NL80211_IFTYPE_P2P_GO: + OPMODE = (WIFI_AP_STATE ); + rtk_p2p_set_role(priv,P2P_TMP_GO); + priv->pmib->p2p_mib.p2p_enabled=CFG80211_P2P; + priv->wdev.iftype = type; + _NDEBUG("switch to [NL80211_IFTYPE_P2P_GO]\n"); + break; + + case NL80211_IFTYPE_P2P_DEVICE: + OPMODE = (WIFI_STATION_STATE); + rtk_p2p_set_role(priv,P2P_DEVICE); + priv->pmib->p2p_mib.p2p_enabled=CFG80211_P2P; + priv->wdev.iftype = type; + _NDEBUG("switch to [NL80211_IFTYPE_P2P_DEVICE]\n"); + break; +#endif +#ifdef SUPPORT_MONITOR + case NL80211_IFTYPE_MONITOR: + OPMODE = (WIFI_SITE_MONITOR); + priv->wdev.iftype = type; + priv->pmib->p2p_mib.p2p_enabled=0; + rtk_enable_monitor_mode(priv); + _NDEBUG("switch to [NL80211_IFTYPE_MONITOR]\n"); + break; +#endif + default: + NDEBUG("invalid interface type [%d]\n", type); + OPMODE = WIFI_AP_STATE; + } +} + +void type_to_name(enum nl80211_iftype type, unsigned char* type_name) +{ + switch (type) { + case NL80211_IFTYPE_STATION: + strcpy(type_name, "NL80211_IFTYPE_STATION"); + break; + case NL80211_IFTYPE_ADHOC: + strcpy(type_name, "NL80211_IFTYPE_ADHOC"); + break; + case NL80211_IFTYPE_AP: + strcpy(type_name, "NL80211_IFTYPE_AP"); + break; + case NL80211_IFTYPE_P2P_CLIENT: + strcpy(type_name, "NL80211_IFTYPE_P2P_CLIENT"); + break; + case NL80211_IFTYPE_P2P_GO: + strcpy(type_name, "NL80211_IFTYPE_P2P_GO"); + break; + case NL80211_IFTYPE_MONITOR: + strcpy(type_name, "NL80211_IFTYPE_MONITOR"); + break; + default: + strcpy(type_name, "NOT SUPPORT TYPE"); + } +} + +static struct wireless_dev *realtek_cfg80211_add_iface(struct wiphy *wiphy, + const char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params) +{ + struct rtknl *rtk = wiphy_priv(wiphy); //return &wiphy->priv; + struct rtl8192cd_priv *priv = rtk->priv; + struct rtl8192cd_priv *priv_add = NULL; + unsigned char type_name[32]; + + NLENTER; + + type_to_name(type, type_name); + NLMSG("ADD [%s][%s=%d]\n", name, type_name, type); + +#if 0//def WDS + if(params) + { + printk("use_4addr = %d \n", params->use_4addr); + } +#endif + + if((strcmp(name, "wlan0")==0) || (strcmp(name, "wlan1")==0)) + { + NLMSG("Root interface, just change type: %d\n", type); + priv->cfg80211_interface_add = TRUE; + realtek_change_iftype(priv, type); + return &rtk->priv->wdev; + } + + priv_add = get_priv_from_rtk(rtk, name); + + if(priv_add) + { + unsigned char type_match = 0; + unsigned char is_vxd = 0; + + if(is_WRT_scan_iface(name)) + { + printk("Add Scan interface, do nothing\n"); + return &priv_add->wdev; + } + + if(type == NL80211_IFTYPE_AP) + { + is_vxd = 0; + rtk->num_vap ++ ; + } + else + { + is_vxd = 1; + rtk->num_vxd = 1; + } + + type_match = check_vif_type_match(priv_add, is_vxd); + + if(!type_match) + { + unsigned char name_vxd[32]; + unsigned char name_vap[32]; + unsigned char name_tmp[32]; + struct rtl8192cd_priv *priv_vxd = NULL; + struct rtl8192cd_priv *priv_vap = NULL; + struct rtl8192cd_priv *priv_tmp = NULL; + + printk("Type NOT Match !!! need to change name\n"); + + if(is_vxd) + { + priv_vap = priv_add; + priv_vxd = get_priv_vxd_from_rtk(rtk); + } + else + { + sprintf(name_vap, "%s-%d", rtk->priv->dev->name, (RTL8192CD_NUM_VWLAN)); + priv_vap = get_priv_from_rtk(rtk, name_vap); + priv_vxd = priv_add; + } + + sprintf(name_tmp, "%s-%d", rtk->priv->dev->name, (RTL8192CD_NUM_VWLAN+10)); + + strcpy(name_vap, priv_vap->dev->name); + strcpy(name_vxd, priv_vxd->dev->name); + +#if 0 + printk(" [BEFORE] +++ \n"); + printk("VAP = 0x%x(0x%x) name=%s \n", priv_vap, priv_vap->dev, priv_vap->dev->name); + printk("VXD = 0x%x(0x%x) name=%s \n", priv_vxd, priv_vxd->dev, priv_vxd->dev->name); +#endif + + rtk_change_netdev_name(priv_vap, name_tmp); + rtk_change_netdev_name(priv_vxd, name_vap); + rtk_change_netdev_name(priv_vap, name_vxd); + +#if 0 + printk(" [AFTER] --- \n"); + printk("VAP = 0x%x(0x%x) name=%s \n", priv_vap, priv_vap->dev, priv_vap->dev->name); + printk("VXD = 0x%x(0x%x) name=%s \n", priv_vxd, priv_vxd->dev, priv_vxd->dev->name); +#endif + + + if(is_vxd) + { +#if 1 //wrt-adhoc + { + NDEBUG("\n\nVXD change type to %d \n\n", type); + realtek_change_iftype(priv_vxd, type); + } +#endif + priv_vxd->cfg80211_interface_add = TRUE; + return &priv_vxd->wdev; + } + else { + priv_vap->cfg80211_interface_add = TRUE; + return &priv_vap->wdev; + } + + } + else + { + printk("Type OK, do nothing\n"); + +#if 1 //wrt-adhoc + if(is_vxd) + { + NDEBUG("\n\nVXD change type to %d \n\n", type); + realtek_change_iftype(priv_add, type); + } +#endif + priv_add->cfg80211_interface_add = TRUE; + return &priv_add->wdev; + } + + } + else + { + printk("Can not find correspinding priv for %s !!\n", name); + return ERR_PTR(-ENODEV); + } + + NLEXIT; + + return &rtk->priv->wdev; + +} + + +void close_vxd_vap(struct rtl8192cd_priv *priv_root) +{ + int i = 0; + +//#ifdef UNIVERSAL_REPEATER +#if 0 //prevent drop vxd connection + if(IS_DRV_OPEN(priv_root->pvxd_priv)) + rtl8192cd_close(priv_root->pvxd_priv->dev); +#endif + +#ifdef MBSSID + for (i=0; ipvap_priv[i])) + rtl8192cd_close(priv_root->pvap_priv[i]->dev); + } +#endif + +} + +static int realtek_cfg80211_del_iface(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev +#else + struct net_device *wdev +#endif + ) +{ + struct rtknl *rtk = wiphy_priv(wiphy); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); +#else + struct rtl8192cd_priv *priv = GET_DEV_PRIV(wdev); +#endif + unsigned char *name = NULL; + + NLENTER; + + if(priv) + { + name = priv->dev->name; + NDEBUG3("del_iface:name[%s] priv[%p] wdev[%p]\n", name, priv, wdev); + } + else + { + NDEBUG3("Can NOT find priv from wdev[%p]", wdev); + return -1; + } + + netif_stop_queue(priv->dev); + + if(priv->cfg80211_interface_add == FALSE) { + NDEBUG3("del_iface:name[%s] is already closed\n", name); + return 0; + } +#ifdef MBSSID + if(IS_ROOT_INTERFACE(priv)) + { + close_vxd_vap(priv); + } + +#ifdef UNIVERSAL_REPEATER + if(IS_VXD_INTERFACE(priv)) + rtk->num_vxd = 0; +#endif + + if(IS_VAP_INTERFACE(priv)) + rtk->num_vap --; +#endif + priv->cfg80211_interface_add = FALSE; + + priv->receive_connect_cmd = 0; + + rtk_abort_scan(priv, SCAN_ABORT_DEL_IFACE); + + if(IS_ROOT_INTERFACE(priv)) + rtl8192cd_close(priv->dev); + else + dev_change_flags(priv->dev, (priv->dev->flags&~IFF_UP) ); //disable virtual interface. + + NLEXIT; + + return 0; +} + +//survey_dump +static int realtek_dump_survey(struct wiphy *wiphy, + struct net_device *dev, + int idx, + struct survey_info *survey) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = rtk->priv; + struct ieee80211_supported_band *sband=NULL; + int freq, band=0; + + //NLENTER; + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + sband = wiphy->bands[band]; + + if (sband) + break;; + } + + if(!sband) { + NDEBUG("%s under unknown band!!\n",dev->name); + return -1; + } else { + //this ops will be invoked several times, until statistic of all channels reported + if(idx > sband->n_channels-1) + { + NDEBUG2("Exceed maximum:%d, statistic of all channels were reported \n", sband->n_channels-1); + return -1; + } + } + + if(sband->band == IEEE80211_BAND_2GHZ) + freq = ieee80211_channel_to_frequency(priv->rtk->survey_info[idx].channel, IEEE80211_BAND_2GHZ); + else + freq = ieee80211_channel_to_frequency(priv->rtk->survey_info[idx].channel, IEEE80211_BAND_5GHZ); + + survey->channel = ieee80211_get_channel(wiphy, freq); + survey->noise = priv->rtk->survey_info[idx].noise; + survey->channel_time = 1000; + survey->channel_time_busy = priv->rtk->survey_info[idx].chbusytime; + survey->channel_time_rx = priv->rtk->survey_info[idx].rx_time; + survey->channel_time_tx = priv->rtk->survey_info[idx].tx_time; + survey->filled = SURVEY_INFO_NOISE_DBM|SURVEY_INFO_CHANNEL_TIME|SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX|SURVEY_INFO_CHANNEL_TIME_TX; +#if 0 + if(priv->rtk->survey_info[idx].chbusytime > priv->rtk->survey_info[idx].rx_time) + { + survey->channel_time_busy = priv->rtk->survey_info[idx].chbusytime + priv->rtk->survey_info[idx].tx_time; + survey->channel_time_rx = priv->rtk->survey_info[idx].rx_time; + } + else + { + survey->channel_time_busy = priv->rtk->survey_info[idx].rx_time + priv->rtk->survey_info[idx].tx_time; + survey->channel_time_rx = priv->rtk->survey_info[idx].rx_time - priv->rtk->survey_info[idx].chbusytime; + } + survey->channel_time_tx = priv->rtk->tx_time; +#endif + + //NLEXIT; + + return 0; +} + + +static int realtek_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = get_priv_from_ndev(rtk, ndev); //rtk->priv; + unsigned char type_name[32]; + + NLENTER; + + type_to_name(type, type_name); + NLMSG("CHANGE [%s][%s=%d]\n", priv->dev->name, type_name, type); + realtek_change_iftype(priv, type); + + NLEXIT; + return 0; +} + + + + +#if 0 +static int realtek_cfg80211_sscan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request) +{ + + return 0; +} + +static int realtek_cfg80211_sscan_stop(struct wiphy *wiphy, + struct net_device *dev) +{ + + return 0; +} + +static int realtek_cfg80211_set_bitrate(struct wiphy *wiphy, + struct net_device *dev, + const u8 *addr, + const struct cfg80211_bitrate_mask *mask) +{ + + return 0; +} + +static int realtek_cfg80211_set_txe_config(struct wiphy *wiphy, + struct net_device *dev, + u32 rate, u32 pkts, u32 intvl) +{ + + return 0; +} +#endif + +void rtk_cfg80211_rx_mgmt(struct rtl8192cd_priv *priv , struct rx_frinfo *pfrinfo, unsigned char channel) +{ + int freq; + NDEBUG3("\n"); + + printk("cliw: rx mgmt to nl80211\n"); + + if (channel <= MAX_2G_CHANNEL_NUM) + freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ); + else + freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ); + + // rtk_set_scan_deny(priv,2000); + cfg80211_rx_mgmt( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + &priv->wdev, +#else + priv->dev, +#endif + freq, 0, get_pframe(pfrinfo), pfrinfo->pktlen +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) + ,0 +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) + ,GFP_KERNEL +#endif + ); +} + +#if defined(NOT_RTK_BSP) && defined(RTK_NL80211_HS_CLI) + +enum rtk_nl80211_rxmgmt_flags { + RTK_NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0, +}; + +int realtek_remain_on_channel( + struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else + struct net_device *wdev, +#endif + struct ieee80211_channel *channel, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, + u64 *cookie) +{ + struct rtknl *rtk = wiphy_priv(wiphy); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); +#else + struct rtl8192cd_priv *priv = GET_DEV_PRIV(wdev); +#endif + // struct wireless_dev *wdev = (&priv->wdev); + + u8 remain_ch = (u8) ieee80211_frequency_to_channel(channel->center_freq); + + NLENTER; + + printk("realtek_remain_on_channel : %d\n", remain_ch); + + if (timer_pending(&priv->nl_ctx.remain_on_ch_timer)) + del_timer(&priv->nl_ctx.remain_on_ch_timer); + + memcpy(&priv->nl_ctx.remain_on_ch_channel, channel, sizeof(struct ieee80211_channel)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->nl_ctx.remain_on_ch_type = channel_type; +#endif + priv->nl_ctx.remain_on_ch_cookie = *cookie; + priv->nl_ctx.restore_channel = GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel; /*restore orignal channel*/ + + priv->nl_ctx.p2p_listen_channel = remain_ch; /*set listen channel to remain channel */ + + priv->pshare->rtk_remain_on_channel = 1; // for lock channel switch and indicate now under remain channel mode + + /* siwtch to */ + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + + if(priv->pmib->dot11RFEntry.dot11channel != priv->nl_ctx.p2p_listen_channel) + priv->pmib->dot11RFEntry.dot11channel = priv->nl_ctx.p2p_listen_channel; + + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->nl_ctx.p2p_listen_channel, priv->pshare->offset_2nd_chan); + + cfg80211_ready_on_channel(wdev, *cookie, channel, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + channel_type, +#endif + duration, GFP_KERNEL); + + mod_timer(&priv->nl_ctx.remain_on_ch_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(duration)); + //NDEBUG("ch[%d],for[%d]ms\n",remain_ch,duration); + + return 0; +} + +static int realtek_cancel_remain_on_channel ( + struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else + struct net_device *wdev, +#endif + u64 cookie ) +{ + + struct rtknl *rtk = wiphy_priv(wiphy); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); +#else + struct rtl8192cd_priv *priv = GET_DEV_PRIV(wdev); +#endif + NLENTER; + + printk("realtek_cancel_remain_on_channel \n"); + if(timer_pending(&priv->nl_ctx.remain_on_ch_timer)){ + del_timer(&priv->nl_ctx.remain_on_ch_timer); + } + NDEBUG("\n"); + + priv->pmib->dot11RFEntry.dot11channel = priv->nl_ctx.restore_channel; + + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + + priv->pshare->rtk_remain_on_channel = 0; // for unlock channel switch +} + +void realtek_cfg80211_RemainOnChExpire( unsigned long task_priv ) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + struct wireless_dev *wdev = &priv->wdev; + + printk("realtek_cfg80211_RemainOnChExpire \n"); + priv->pshare->rtk_remain_on_channel = 0; // for unlock channel switch + //NDEBUG2("\n"); + + notify_cfg_evt(priv, NULL, CFG80211_REMAIN_CHANNEL, NULL); +/* + cfg80211_remain_on_channel_expired(wdev, priv->nl_ctx.remain_on_ch_cookie, + &priv->nl_ctx.remain_on_ch_channel, GFP_KERNEL); +*/ + return; +} + +#define WLAN_ACT_CAT_CODE_GAS 4 + +int rtk_cfg80211_mgmt_tx(struct rtl8192cd_priv *priv, int tx_ch, const u8 *mgmt_buf_from_cfg, int mgmt_buf_from_cfg_len) +{ + unsigned char *pbuf; + unsigned char *frame_after_wlan_hrd=NULL; + int frame_after_wlan_hrd_len = 0; + int sizeof_mgmt_wlan_hrd = 0; + struct ieee80211_mgmt *mgmt; + int idx=0; + u8 category,action; + u8 OUI_Subtype; + u8 dialogToken; + unsigned char P2P_OUI[] = {0x50,0x6F,0x9A,0x09}; + u8* p2p_ie_start; + int p2p_ie_len; + int my_p2p_role; + unsigned char* p2p_capa; + // struct ieee80211_mgmt_hrd mgmt_hrd; + + DECLARE_TXINSN(txinsn); + + printk("rtk_cfg80211_mgmt_tx ++ \n"); +#if 0 + if(priv->pshare->working_channel2 != tx_ch){ + NDEBUG(" chk , our working ch != assigned by cfg\n\n"); + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, tx_ch, priv->pshare->offset_2nd_chan); + } +#endif + + // rtk_set_scan_deny(priv,300); // deny channel switch for 300 ms + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto fail; + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; +#ifndef TX_LOWESTRATE + txinsn.lowest_tx_rate = txinsn.tx_rate; +#endif + txinsn.fixed_rate = true; + txinsn.need_ack = true; + txinsn.retry = true; + + sizeof_mgmt_wlan_hrd = sizeof(struct ieee80211_mgmt_hrd); + frame_after_wlan_hrd = mgmt_buf_from_cfg + sizeof_mgmt_wlan_hrd; + frame_after_wlan_hrd_len = mgmt_buf_from_cfg_len - sizeof_mgmt_wlan_hrd; + + + /*-------------parse p2p_ie and do some handling----------------*/ + category = frame_after_wlan_hrd[0]; + if(category == WLAN_CATEGORY_PUBLIC) // 0x4 p2p public action frame + { + + } + else if(category == WLAN_CATEGORY_VENDOR_SPECIFIC) // 0x7F action frame + { + + } + else if( category == WLAN_ACT_CAT_CODE_GAS ) // 0x7F action frame + { + action = frame_after_wlan_hrd[1]; + printk("GAS: action code:%d\n", action); + } + else + { + NDEBUG("unknown action frame\n"); + } + + /*fill wlan head*/ + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + memcpy((void *)(txinsn.phdr) , mgmt_buf_from_cfg , sizeof(struct ieee80211_mgmt_hrd)); + + /*fill frame content after wlan head*/ + memcpy((void *)pbuf , frame_after_wlan_hrd , frame_after_wlan_hrd_len); + + txinsn.fr_len += frame_after_wlan_hrd_len; + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) { + printk("rtk_cfg80211_mgmt_tx: ok --\n"); + return SUCCESS; + } else { + P2P_DEBUG("TX action fail\n"); + } + +fail: + NDEBUG("fail !!!\n"); + printk("rtk_cfg80211_mgmt_tx: ng--\n"); + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) +static int realtek_mgmt_tx ( + struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie ) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); + int tx_ch = ieee80211_frequency_to_channel(params->chan->center_freq); + + int ret = 0; + u32 cookie_id; + const struct ieee80211_mgmt *mgmt; + NLENTER; + + *cookie = 0; + + priv->nl_ctx.send_action_id++; + if( priv->nl_ctx.send_action_id == 0 ) + priv->nl_ctx.send_action_id++; + + *cookie = priv->nl_ctx.send_action_id; + + mgmt = (const struct ieee80211_mgmt *)params->buf; + + if (ieee80211_is_mgmt(mgmt->frame_control)) { + if (ieee80211_is_probe_resp(mgmt->frame_control)) { + s32 ie_offset = WLAN_HDR_A3_LEN + _PROBERSP_IE_OFFSET_; + s32 ie_len = params->len - ie_offset; + NDEBUG("!!!set probe rsp from cfg80211\n"); + rtk_cfg80211_set_wps_p2p_ie(priv,params->buf+ie_offset,ie_len,MGMT_PROBERSP); + cfg80211_mgmt_tx_status(wdev, *cookie, params->buf, params->len, TRUE, GFP_KERNEL); //GFP_ATOMIC + return 0; + } else if (ieee80211_is_disassoc(mgmt->frame_control) || + ieee80211_is_deauth(mgmt->frame_control)) { + NDEBUG("Disconnect STA[%02X%02X%02X:%02X%02X%02X] reason[%d]\n", + mgmt->da[0],mgmt->da[1],mgmt->da[2], + mgmt->da[3],mgmt->da[4],mgmt->da[5],mgmt->u.disassoc.reason_code); + + issue_deauth(priv,mgmt->da, mgmt->u.disassoc.reason_code); + cfg80211_mgmt_tx_status(wdev, *cookie, params->buf, params->len, TRUE, GFP_KERNEL); //GFP_ATOMIC + return 0; + } else if (ieee80211_is_action(mgmt->frame_control)) { + + /* indicate ack before issue frame to avoid racing with rsp frame */ + + // rtk_abort_scan(priv); // abort on going scan + rtk_cfg80211_mgmt_tx(priv, tx_ch, params->buf, params->len); + cfg80211_mgmt_tx_status(wdev, *cookie, params->buf, params->len, TRUE, GFP_KERNEL); //GFP_ATOMIC + // NDEBUG("cookie_id[%02X]\n",priv->p2pPtr->send_action_id); + } + } + return 0; +} +#else // LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) +static int realtek_mgmt_tx( + struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else + struct net_device *wdev, +#endif + struct ieee80211_channel *chan, bool offchan, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + enum nl80211_channel_type channel_type, + bool channel_type_valid, +#endif + unsigned int wait, const u8 *buf, size_t len, + bool no_cck, bool dont_wait_for_ack, u64 *cookie) +{ + struct rtknl *rtk = wiphy_priv(wiphy); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); +#else + struct rtl8192cd_priv *priv = GET_DEV_PRIV(wdev); +#endif + + int tx_ch = ieee80211_frequency_to_channel(chan->center_freq); + NDEBUG3("[%s]center_freq=[%u] channel=[%d] hw_value=[%u] bandwidth=[%d] \n", + priv->dev->name, chan->center_freq, tx_ch, chan->hw_value, chan->flags); + printk("realtek_mgmt_tx:[%s] center_freq=[%u] channel=[%d] hw_value=[%u]\n", + priv->dev->name, chan->center_freq, tx_ch, chan->hw_value); + + int ret = 0; + u32 cookie_id; + const struct ieee80211_mgmt *mgmt; + NLENTER; + + *cookie = 0; + + priv->nl_ctx.send_action_id++; + if( priv->nl_ctx.send_action_id == 0 ) + priv->nl_ctx.send_action_id++; + + *cookie = priv->nl_ctx.send_action_id; + + mgmt = (const struct ieee80211_mgmt *)buf; + + printk("realtek_mgmt_tx:mgmt->frame_control:%x\n", mgmt->frame_control); + + if (ieee80211_is_mgmt(mgmt->frame_control)) { + printk(" is ieee80211_is_mgmt \n"); + if (ieee80211_is_probe_resp(mgmt->frame_control)) { + s32 ie_offset = WLAN_HDR_A3_LEN + _PROBERSP_IE_OFFSET_; + s32 ie_len = len - ie_offset; + NDEBUG("!!!set probe rsp from cfg80211\n"); + printk("!!!set probe rsp from cfg80211\n"); + rtk_cfg80211_set_wps_p2p_ie(priv, buf + ie_offset, ie_len, MGMT_PROBERSP); + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, TRUE, GFP_KERNEL); //GFP_ATOMIC + return 0; + } else if (ieee80211_is_disassoc(mgmt->frame_control) || + ieee80211_is_deauth(mgmt->frame_control)) { + NDEBUG("Disconnect STA[%02X%02X%02X:%02X%02X%02X] reason[%d]\n", + mgmt->da[0],mgmt->da[1],mgmt->da[2], + mgmt->da[3],mgmt->da[4],mgmt->da[5],mgmt->u.disassoc.reason_code); + + printk("Disconnect STA[%02X%02X%02X:%02X%02X%02X] reason[%d]\n", + mgmt->da[0],mgmt->da[1],mgmt->da[2], + mgmt->da[3],mgmt->da[4],mgmt->da[5],mgmt->u.disassoc.reason_code); + + issue_deauth(priv, mgmt->da, mgmt->u.disassoc.reason_code); + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, TRUE, GFP_KERNEL);//GFP_ATOMIC + return 0; + } else if (ieee80211_is_action(mgmt->frame_control)) { + printk(" is_action \n"); + /* indicate ack before issue frame to avoid racing with rsp frame */ + //rtk_abort_scan(priv); // abort on going scan + rtk_cfg80211_mgmt_tx(priv, tx_ch, buf, len); + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, TRUE, GFP_KERNEL);//GFP_ATOMIC + //NDEBUG("cookie_id[%02X]\n",priv->p2pPtr->send_action_id); + } + } + return 0; +} +#endif + +#elif defined(P2P_SUPPORT) +int realtek_remain_on_channel(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else + struct net_device *wdev, +#endif + struct ieee80211_channel *channel, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + enum nl80211_channel_type channel_type, +#endif + unsigned int duration, + u64 *cookie) + +{ + struct rtknl *rtk = wiphy_priv(wiphy); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); +#else + struct rtl8192cd_priv *priv = GET_DEV_PRIV(wdev); +#endif + // struct wireless_dev *wdev = (&priv->wdev); + u8 remain_ch = (u8) ieee80211_frequency_to_channel(channel->center_freq); + + NLENTER; + + if (timer_pending(&priv->p2pPtr->remain_on_ch_timer)) + del_timer(&priv->p2pPtr->remain_on_ch_timer); + + //rtk_abort_scan(priv); // abort on going scan + memcpy(&priv->p2pPtr->remain_on_ch_channel, channel, sizeof(struct ieee80211_channel)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->p2pPtr->remain_on_ch_type = channel_type; +#endif + priv->p2pPtr->remain_on_ch_cookie= *cookie; + priv->p2pPtr->restore_channel=GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel; /*restore orignal channel*/ + + priv->pmib->p2p_mib.p2p_listen_channel=remain_ch; /*set listen channel to remain channel */ + + priv->p2pPtr->pre_p2p_role=rtk_p2p_get_role(priv); + priv->p2pPtr->pre_p2p_state=rtk_p2p_get_state(priv); + + //priv->p2pPtr->pre_opmode = OPMODE; + #if 0 //before 0326 1450 + if(rtk_p2p_is_enabled(priv)==CFG80211_P2P){ // rdy under p2p mode + if(!rtk_p2p_chk_role(priv,P2P_DEVICE)){ + NDEBUG("change mode to p2p-device\n"); + rtk_p2p_set_role(priv,P2P_DEVICE); + } + }else{ + NDEBUG("rtk_p2p_enable\n"); + rtk_p2p_enable(priv,P2P_DEVICE, CFG80211_P2P); + } + #else + if(!rtk_p2p_is_enabled(priv)){ + NDEBUG3("==>rtk_p2p_enable(CFG80211_P2P)\n"); + rtk_p2p_enable(priv,P2P_DEVICE, CFG80211_P2P); + } + #endif + + rtk_p2p_set_role(priv,P2P_DEVICE); // role to device + P2P_listen(priv,NULL); //state to listen + + + NDEBUG3("role[%d]\n",rtk_p2p_get_role(priv)); + NDEBUG3("state[%d]\n",rtk_p2p_get_state(priv)); + priv->pshare->rtk_remain_on_channel=1; // for lock channel switch and indicate now under remain channel mode + + cfg80211_ready_on_channel(wdev, *cookie, channel, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + channel_type, +#endif + duration, GFP_KERNEL); + + if(duration < 400) + duration = duration*3;//extend from exper. unit ms + + mod_timer(&priv->p2pPtr->remain_on_ch_timer,jiffies + RTL_MILISECONDS_TO_JIFFIES(duration)); + //NDEBUG("ch[%d],for[%d]ms\n",remain_ch,duration); + return 0; + +} +static int realtek_cancel_remain_on_channel(struct wiphy *wiphy, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct wireless_dev *wdev, +#else + struct net_device *wdev, +#endif + u64 cookie) +{ + struct rtknl *rtk = wiphy_priv(wiphy); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); +#else + struct rtl8192cd_priv *priv = GET_DEV_PRIV(wdev); +#endif + NLENTER; + + if(timer_pending(&priv->p2pPtr->remain_on_ch_timer)){ + del_timer(&priv->p2pPtr->remain_on_ch_timer); + } + NDEBUG("\n"); + + priv->pshare->rtk_remain_on_channel=0; // for unlock channel switch + rtk_p2p_set_role(priv,priv->p2pPtr->pre_p2p_role); + rtk_p2p_set_state(priv,priv->p2pPtr->pre_p2p_state); + return 0; +} + +void realtek_cfg80211_RemainOnChExpire(unsigned long task_priv) +{ + + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + struct wireless_dev *wdev = &priv->wdev; + + priv->pshare->rtk_remain_on_channel=0; // for unlock channel switch + rtk_p2p_set_role(priv,priv->p2pPtr->pre_p2p_role); + rtk_p2p_set_state(priv,priv->p2pPtr->pre_p2p_state); + //NDEBUG2("\n"); + cfg80211_remain_on_channel_expired( +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + wdev, +#else + priv->dev, +#endif + priv->p2pPtr->remain_on_ch_cookie, + &priv->p2pPtr->remain_on_ch_channel, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) + priv->p2pPtr->remain_on_ch_type, +#endif + GFP_KERNEL); + return; +} + +int rtk_cfg80211_mgmt_tx(struct rtl8192cd_priv *priv,int tx_ch,const u8 *mgmt_buf_from_cfg, int mgmt_buf_from_cfg_len) +{ + unsigned char *pbuf; + unsigned char *frame_after_wlan_hrd=NULL; + int frame_after_wlan_hrd_len = 0; + int sizeof_mgmt_wlan_hrd = 0; + struct ieee80211_mgmt *mgmt; + int idx=0; + u8 category,action; + u8 OUI_Subtype; + u8 dialogToken; + unsigned char P2P_OUI[] = {0x50,0x6F,0x9A,0x09}; + u8* p2p_ie_start; + int p2p_ie_len; + int my_p2p_role; + unsigned char* p2p_capa; + //struct ieee80211_mgmt_hrd mgmt_hrd; + + DECLARE_TXINSN(txinsn); + + if(priv->pshare->working_channel2 != tx_ch){ + NDEBUG(" chk , our working ch != assigned by cfg\n\n"); + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, tx_ch, priv->pshare->offset_2nd_chan); + } + //rtk_set_scan_deny(priv,300); // deny channel switch for 300 ms + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto fail; + + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; +#ifndef TX_LOWESTRATE + txinsn.lowest_tx_rate = txinsn.tx_rate; +#endif + txinsn.fixed_rate = true; + txinsn.need_ack = true; + txinsn.retry = true; + + sizeof_mgmt_wlan_hrd = sizeof(struct ieee80211_mgmt_hrd); + frame_after_wlan_hrd = mgmt_buf_from_cfg + sizeof_mgmt_wlan_hrd; + frame_after_wlan_hrd_len = mgmt_buf_from_cfg_len-sizeof_mgmt_wlan_hrd; + + + /*-------------parse p2p_ie and do some handling----------------*/ + category = frame_after_wlan_hrd[0]; + if(category == WLAN_CATEGORY_PUBLIC) // 0x4 p2p public action frame + { + action = frame_after_wlan_hrd[1]; + if (action == _P2P_PUBLIC_ACTION_FIELD_ && !memcmp(frame_after_wlan_hrd+2, WFA_OUI_PLUS_TYPE, 4)) + { + OUI_Subtype = frame_after_wlan_hrd[6]; + dialogToken = frame_after_wlan_hrd[7]; + switch(OUI_Subtype){ + case P2P_GO_NEG_REQ: + NDEBUG("P2P_GO_NEG_REQ ,dialog[%d]\n",dialogToken); + break; + case P2P_GO_NEG_RESP: + NDEBUG("P2P_GO_NEG_RESP \n"); + + break; + case P2P_GO_NEG_CONF: + NDEBUG("P2P_GO_NEG_CONF\n"); + + break; + case P2P_INVITATION_REQ: + NDEBUG("P2P_INVITATION_REQ,dialog[%d]\n",dialogToken); + break; + case P2P_INVITATION_RESP: + NDEBUG("P2P_INVITATION_RESP,dialog[%d]\n",dialogToken); + break; + case P2P_DEV_DISC_REQ: + NDEBUG("P2P_INVITATION_RESP,dialog[%d]\n",dialogToken); + rtk_p2p_set_state(priv,P2P_S_IDLE); + break; + case P2P_DEV_DISC_RESP: + NDEBUG("P2P_DEV_DISC_RESP,dialog[%d]\n",dialogToken); + rtk_p2p_set_state(priv,P2P_S_IDLE); + break; + case P2P_PROV_DISC_REQ: + NDEBUG("P2P_PROV_DISC_REQ,dialog[%d]\n",dialogToken); + break; + case P2P_PROV_DISC_RSP: + NDEBUG("P2P_PROV_DISC_RSP,dialog[%d]\n",dialogToken); + break; + default: + NDEBUG("unknown [%d]\n",dialogToken); + break; + } + } + + } + else if(category == WLAN_CATEGORY_VENDOR_SPECIFIC) // 0x7F action frame + { + OUI_Subtype = frame_after_wlan_hrd[5]; + dialogToken = frame_after_wlan_hrd[6]; + switch(OUI_Subtype) + { + case P2P_NOA: + NDEBUG("P2P_NOA,dialog[%d]\n",dialogToken); + break; + case P2P_PRESENCE_REQ: + NDEBUG("P2P_PRESENCE_REQ,dialog[%d]\n",dialogToken); + break; + case P2P_PRESENCE_RSP: + NDEBUG("P2P_PRESENCE_RSP,dialog[%d]\n",dialogToken); + break; + case P2P_GO_DISCOVERY: + NDEBUG("P2P_GO_DISCOVERY,dialog[%d]\n",dialogToken); + break; + default: + NDEBUG("unknown,dialog[%d]\n",dialogToken); + break; + } + + } + else + { + NDEBUG("unknown action frame\n"); + } + /*-------------parse p2p_ie and do some handling----------------*/ + + + /* fill wlan head */ + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + memcpy((void *)(txinsn.phdr) , mgmt_buf_from_cfg , sizeof(struct ieee80211_mgmt_hrd)); + + /* fill frame content after wlan head */ + memcpy((void *)pbuf , frame_after_wlan_hrd , frame_after_wlan_hrd_len); + + txinsn.fr_len += frame_after_wlan_hrd_len; + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + return SUCCESS; + } else { + P2P_DEBUG("TX action fail\n"); + } + +fail: + NDEBUG("fail !!!\n"); + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; +} + +static int realtek_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + struct rtknl *rtk = wiphy_priv(wiphy); + struct rtl8192cd_priv *priv = get_priv_from_wdev(rtk, wdev); + int tx_ch = ieee80211_frequency_to_channel(params->chan->center_freq); + + int ret = 0; + u32 cookie_id; + const struct ieee80211_mgmt *mgmt; + NLENTER; + + *cookie = 0; + + priv->p2pPtr->send_action_id++; + if(priv->p2pPtr->send_action_id==0) + priv->p2pPtr->send_action_id++; + + + *cookie = priv->p2pPtr->send_action_id; + + mgmt = (const struct ieee80211_mgmt *)params->buf; + + if (ieee80211_is_mgmt(mgmt->frame_control)) { + if (ieee80211_is_probe_resp(mgmt->frame_control)) { + s32 ie_offset = WLAN_HDR_A3_LEN + _PROBERSP_IE_OFFSET_; + s32 ie_len = params->len - ie_offset; + NDEBUG("!!!set probe rsp from cfg80211\n"); + rtk_cfg80211_set_wps_p2p_ie(priv,params->buf+ie_offset,ie_len,MGMT_PROBERSP); + cfg80211_mgmt_tx_status(wdev, *cookie, params->buf, params->len, TRUE, GFP_KERNEL);//GFP_ATOMIC + return 0; + } else if (ieee80211_is_disassoc(mgmt->frame_control) || + ieee80211_is_deauth(mgmt->frame_control)) { + NDEBUG("Disconnect STA[%02X%02X%02X:%02X%02X%02X] reason[%d]\n", + mgmt->da[0],mgmt->da[1],mgmt->da[2], + mgmt->da[3],mgmt->da[4],mgmt->da[5],mgmt->u.disassoc.reason_code); + + issue_deauth(priv,mgmt->da,mgmt->u.disassoc.reason_code); + cfg80211_mgmt_tx_status(wdev, *cookie, params->buf, params->len, TRUE, GFP_KERNEL);//GFP_ATOMIC + return 0; + } else if (ieee80211_is_action(mgmt->frame_control)) { + + /* indicate ack before issue frame to avoid racing with rsp frame */ + + //rtk_abort_scan(priv); // abort on going scan + rtk_cfg80211_mgmt_tx(priv, tx_ch, params->buf, params->len); + cfg80211_mgmt_tx_status(wdev, *cookie, params->buf, params->len, TRUE, GFP_KERNEL);//GFP_ATOMIC + //NDEBUG("cookie_id[%02X]\n",priv->p2pPtr->send_action_id); + + } + + } + return 0; + +} +#endif //CONFIG_P2P + +struct cfg80211_ops realtek_cfg80211_ops = { + .add_virtual_intf = realtek_cfg80211_add_iface, + .del_virtual_intf = realtek_cfg80211_del_iface, + .change_virtual_intf = realtek_cfg80211_change_iface, + .add_key = realtek_cfg80211_add_key, + .del_key = realtek_cfg80211_del_key, + .get_key = realtek_cfg80211_get_key, + .set_default_key = realtek_cfg80211_set_default_key, + .set_default_mgmt_key = realtek_cfg80211_set_default_mgmt_key, + //.add_beacon = realtek_cfg80211_add_beacon, + //.set_beacon = realtek_cfg80211_set_beacon, + //.del_beacon = realtek_cfg80211_del_beacon, + .add_station = realtek_cfg80211_add_station, + .del_station = realtek_cfg80211_del_station, + .change_station = realtek_cfg80211_change_station, + .get_station = realtek_cfg80211_get_station, + .dump_station = realtek_cfg80211_dump_station, +#if 0//def CONFIG_MAC80211_MESH + .add_mpath = realtek_cfg80211_add_mpath, + .del_mpath = realtek_cfg80211_del_mpath, + .change_mpath = realtek_cfg80211_change_mpath, + .get_mpath = realtek_cfg80211_get_mpath, + .dump_mpath = realtek_cfg80211_dump_mpath, + .set_mesh_params = realtek_cfg80211_set_mesh_params, + .get_mesh_params = realtek_cfg80211_get_mesh_params, +#endif + .change_bss = realtek_cfg80211_change_bss, + //.set_txq_params = realtek_cfg80211_set_txq_params, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) + .set_channel = realtek_cfg80211_set_channel, +#endif +#ifndef NOT_RTK_BSP + .suspend = realtek_cfg80211_suspend, + .resume = realtek_cfg80211_resume, +#endif + .scan = realtek_cfg80211_scan, +#if 0 + .auth = realtek_cfg80211_auth, + .assoc = realtek_cfg80211_assoc, + .deauth = realtek_cfg80211_deauth, + .disassoc = realtek_cfg80211_disassoc, +#endif + +#ifndef NOT_RTK_BSP + .join_ibss = realtek_cfg80211_join_ibss, + .leave_ibss = realtek_cfg80211_leave_ibss, +#endif + .set_wiphy_params = realtek_cfg80211_set_wiphy_params, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) + .set_ap_chanwidth = realtek_cfg80211_set_ap_chanwidth, +#endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + .set_monitor_channel = realtek_cfg80211_set_monitor_channel, +#endif +#ifndef NOT_RTK_BSP + .set_tx_power = realtek_cfg80211_set_tx_power, + .get_tx_power = realtek_cfg80211_get_tx_power, + .set_power_mgmt = realtek_cfg80211_set_power_mgmt, + .set_wds_peer = realtek_cfg80211_set_wds_peer, + .rfkill_poll = realtek_cfg80211_rfkill_poll, + //CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) + .set_bitrate_mask = realtek_cfg80211_set_bitrate_mask, +#endif + .connect = realtek_cfg80211_connect, + .disconnect = realtek_cfg80211_disconnect, +#if defined(P2P_SUPPORT) || defined(RTK_NL80211_HS_CLI) + .remain_on_channel = realtek_remain_on_channel, + .cancel_remain_on_channel = realtek_cancel_remain_on_channel, + .mgmt_tx = realtek_mgmt_tx, +#endif + .mgmt_frame_register = realtek_mgmt_frame_register, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) + // .channel_switch = realtek_cfg80211_channel_switch, +#endif + .dump_survey = realtek_dump_survey,//survey_dump + .start_ap = realtek_start_ap, + .change_beacon = realtek_change_beacon, + .stop_ap = realtek_stop_ap, +#if 0 + .sched_scan_start = realtek_cfg80211_sscan_start, + .sched_scan_stop = realtek_cfg80211_sscan_stop, + .set_bitrate_mask = realtek_cfg80211_set_bitrate, + .set_cqm_txe_config = realtek_cfg80211_set_txe_config, +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + .set_mac_acl = realtek_set_mac_acl, +#if defined(DFS) + .start_radar_detection = realtek_start_radar_detection, +#endif +#endif +}; + +static void rtk_destroy_dev(struct rtknl *rtk) +{ + device_del( rtk->dev ); + class_destroy( rtk->cl ); +} + +static void rtk_create_dev(struct rtknl *rtk,int idx) +{ + /* define class here */ + unsigned char zero[] = {0, 0, 0, 0, 0, 0}; + rtk->cl = class_create(THIS_MODULE, rtk_dev_name[idx]); + + /* create first device */ + rtk->dev = device_create(rtk->cl, NULL, rtk_wifi_dev[idx], NULL, rtk_dev_name[idx]); + + dev_set_name(rtk->dev, rtk_dev_name[idx]); + printk("Device Name = %s \n", dev_name(rtk->dev)); + + printk("VIF_NUM=%d\n", VIF_NUM); + memset(rtk->ndev_name, 0, VIF_NUM*VIF_NAME_SIZE); + + //init rtk phy root name + sprintf(rtk->root_ifname, "wlan%d", idx); + + //mark_dual ,init with fake mac for diff phy + rtk_fake_addr[3] += ((unsigned char)idx) ; + memcpy(rtk->root_mac, rtk_fake_addr, ETH_ALEN); +} + +int realtek_cfg80211_destroy(struct rtknl *rtk) +{ + struct wiphy *wiphy; + + if ( NULL == rtk ) + return -1; + + wiphy = rtk->wiphy; + + // wiphy_unregister(wiphy); + + rtk_destroy_dev(rtk); + + wiphy_free(wiphy); + + return 0; +} + + +//struct rtknl *realtek_cfg80211_create(struct rtl8192cd_priv *priv) +struct rtknl *realtek_cfg80211_create(void) +{ + struct wiphy *wiphy; + struct rtknl *rtk; + + //NLENTER; + + /* create a new wiphy for use with cfg80211 */ + wiphy = wiphy_new(&realtek_cfg80211_ops, sizeof(struct rtknl)); + + if (!wiphy) { + printk("couldn't allocate wiphy device\n"); + return NULL; + } + + rtk = wiphy_priv(wiphy); + rtk->wiphy = wiphy; + //rtk->priv = priv; //mark_dual2 + + //sync to global rtk_phy + if(rtk_phy_idx > RTK_MAX_WIFI_PHY) + { + printk("ERROR!! rtk_phy_idx > RTK_MAX_WIFI_PHY\n"); + wiphy_free(wiphy); + return NULL; + } + rtk_create_dev(rtk,rtk_phy_idx); + rtk_phy[rtk_phy_idx] = rtk; + rtk_phy_idx++; + + //priv->rtk = rtk ; //mark_dual2 + + //NLEXIT; + return rtk; +} + +/*cfg p2p*/ +#if 1 +static const struct ieee80211_txrx_stypes rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + }, +#if defined(P2P_SUPPORT) + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_ACTION >> 4) + }, +#endif +}; +#endif + +#define MAX_REMAIN_ON_CHANNEL_DURATION 5000 //ms +#define SCAN_IE_LEN_MAX 2304 +#define SSID_SCAN_AMOUNT 1 // for WEXT_CSCAN_AMOUNT 9 +#define MAX_NUM_PMKIDS 32 +#define NL_MAX_INTF 9 + +static const struct ieee80211_iface_limit rtk_if_limits[] = { + { .max = 8, .types = BIT(NL80211_IFTYPE_AP) }, + { .max = 1, .types = BIT(NL80211_IFTYPE_STATION) }, +}; + +static const struct ieee80211_iface_combination rtk_2g_comb = { + .limits = rtk_if_limits, + .n_limits = ARRAY_SIZE(rtk_if_limits), + .max_interfaces = NL_MAX_INTF, + .num_different_channels = 1, +}; + +static const struct ieee80211_iface_combination rtk_5g_comb = { + .limits = rtk_if_limits, + .n_limits = ARRAY_SIZE(rtk_if_limits), + .max_interfaces = NL_MAX_INTF, + .num_different_channels = 1, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80), +#endif +}; + +/** + * enum wiphy_flags - wiphy capability flags + * + * @WIPHY_FLAG_CUSTOM_REGULATORY: tells us the driver for this device + * has its own custom regulatory domain and cannot identify the + * ISO / IEC 3166 alpha2 it belongs to. When this is enabled + * we will disregard the first regulatory hint (when the + * initiator is %REGDOM_SET_BY_CORE). + + * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will + * ignore regulatory domain settings until it gets its own regulatory + * domain via its regulatory_hint() unless the regulatory hint is + * from a country IE. After its gets its own regulatory domain it will + * only allow further regulatory domain settings to further enhance + * compliance. For example if channel 13 and 14 are disabled by this + * regulatory domain no user regulatory domain can enable these channels + * at a later time. This can be used for devices which do not have + * calibration information guaranteed for frequencies or settings + * outside of its regulatory domain. If used in combination with + * WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings + * will be followed. + + * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure + * that passive scan flags and beaconing flags may not be lifted by + * cfg80211 due to regulatory beacon hints. For more information on beacon + * hints read the documenation for regulatory_hint_found_beacon() + + * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this + * wiphy at all + + * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled + * by default -- this flag will be set depending on the kernel's default + * on wiphy_new(), but can be changed by the driver if it has a good + * reason to override the default + + * @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station + * on a VLAN interface) + + * @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station + + * @WIPHY_FLAG_CONTROL_PORT_PROTOCOL: This device supports setting the + * control port protocol ethertype. The device also honours the + * control_port_no_encrypt flag. + + * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. + + * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing + * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH. + + * @WIPHY_FLAG_SUPPORTS_SCHED_SCAN: The device supports scheduled scans. + + * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the firmware. + * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP. + * @WIPHY_FLAG_SUPPORTS_TDLS: The device supports TDLS (802.11z) operation. + * @WIPHY_FLAG_TDLS_EXTERNAL_SETUP: The device does not handle TDLS (802.11z) + * link setup/discovery operations internally. Setup, discovery and + * teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT + * command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be + * used for asking the driver/firmware to perform a TDLS operation. + * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME + * @WIPHY_FLAG_REPORTS_OBSS: the device will report beacons from other BSSes + * when there are virtual interfaces in AP mode by calling + * cfg80211_report_obss_beacon(). + * @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD: When operating as an AP, the device + * responds to probe-requests in hardware. + * @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX. + * @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call. + */ +int realtek_cfg80211_init(struct rtknl *rtk,struct rtl8192cd_priv *priv) +{ + struct wiphy *wiphy = rtk->wiphy; + BOOLEAN band_2gig = FALSE, band_5gig = FALSE; + int ret; +#ifdef EN_EFUSE + char efusemac[ETH_ALEN]; +#endif + char zero[ETH_ALEN] = {0,0,0,0,0,0}; + unsigned char txbf_max_ant, txbf_sounding_dim; + NLENTER; + + rtk->priv = priv; //mark_dual + + rtk_get_band_capa(priv,&band_2gig,&band_5gig); + + //wiphy->mgmt_stypes = realtek_mgmt_stypes; //_eric_cfg ?? + wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes; /*cfg p2p*/ + +#if defined(SIGNAL_TYPE_UNSPEC) + wiphy->signal_type=CFG80211_SIGNAL_TYPE_UNSPEC; +#else + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; //mark_priv +#endif + /* max num of ssids that can be probed during scanning */ + //wiphy->max_scan_ssids = MAX_PROBED_SSIDS; + wiphy->max_scan_ssids = SSID_SCAN_AMOUNT; + + /* max num of ssids that can be matched after scan */ + //wiphy->max_match_sets = MAX_PROBED_SSIDS; + + //wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ + wiphy->max_scan_ie_len = SCAN_IE_LEN_MAX; + wiphy->max_num_pmkids = MAX_NUM_PMKIDS; + wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION; /*cfg p2p p2p related*/ + + switch(get_rf_mimo_mode(priv)) { + case MIMO_1T1R: + wiphy->available_antennas_tx = 0x1; + wiphy->available_antennas_rx = 0x1; + break; + case MIMO_3T3R: + wiphy->available_antennas_tx = 0x3; + wiphy->available_antennas_rx = 0x3; + break; + default: + wiphy->available_antennas_tx = 0x2; + wiphy->available_antennas_rx = 0x2; + } + + /*The device supports roaming feature in the firmware*/ //_eric_cfg ?? support these features ?? + wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM ; + /*device integrates AP SME*/ + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME ; + wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL ;/*cfg p2p ; p2p must use it*/ + if(band_2gig){ + wiphy->interface_modes = BIT(NL80211_IFTYPE_AP)| + BIT(NL80211_IFTYPE_STATION) | //_eric_cfg station mandatory ?? + BIT(NL80211_IFTYPE_ADHOC) | //wrt-adhoc +#if defined(P2P_SUPPORT) + BIT(NL80211_IFTYPE_P2P_CLIENT)| + BIT(NL80211_IFTYPE_P2P_GO)| + BIT(NL80211_IFTYPE_P2P_DEVICE)| +#endif + BIT(NL80211_IFTYPE_MONITOR); + }else{ + wiphy->interface_modes = BIT(NL80211_IFTYPE_AP)| + BIT(NL80211_IFTYPE_STATION) | //_eric_cfg station mandatory ?? + BIT(NL80211_IFTYPE_ADHOC)| + BIT(NL80211_IFTYPE_MONITOR); + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + wiphy->max_acl_mac_addrs = NUM_STAT; +#endif + //printk("set_wiphy_dev +++ \n"); + set_wiphy_dev(wiphy, rtk->dev); //return wiphy->dev.parent; + //printk("set_wiphy_dev --- \n"); + +#if defined(EN_EFUSE) && !defined(CUSTOMIZE_FLASH_EFUSE) +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv) != VERSION_8881A) +#endif + { + extern void read_efuse_mac_address(struct rtl8192cd_priv * priv,char * efusemac); + memset(efusemac,0,ETH_ALEN); + read_efuse_mac_address(priv,efusemac); + if( memcmp(efusemac,zero,ETH_ALEN) && !IS_MCAST(efusemac)) + memcpy(rtk->root_mac,efusemac,ETH_ALEN); + } +#endif + memcpy(wiphy->perm_addr, rtk->root_mac, ETH_ALEN); + memcpy(priv->pmib->dot11Bss.bssid, wiphy->perm_addr, ETH_ALEN); + + /* + * Even if the fw has HT support, advertise HT cap only when + * the firmware has support to override RSN capability, otherwise + * 4-way handshake would fail. + */ + if(band_2gig) + { + wiphy->bands[IEEE80211_BAND_2GHZ] = &realtek_band_2ghz; + switch (get_rf_mimo_mode(priv)) { + case MIMO_1T1R: + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_highest = cpu_to_le16(150); + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_mask[0] = 0xff; + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_mask[1] = 0; + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_mask[2] = 0; + break; + case MIMO_2T2R: + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_highest = cpu_to_le16(300); + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_mask[0] = 0xff; + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_mask[1] = 0xff; + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_mask[2] = 0; + break; + case MIMO_3T3R: + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_highest = cpu_to_le16(450); + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_mask[0] = 0xff; + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_mask[1] = 0xff; + wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.mcs.rx_mask[2] = 0xff; + break; + default: + NDEBUG(" Waring, mimo(%d) not support\n", get_rf_mimo_mode(priv)); + break; + } + wiphy->iface_combinations = &rtk_2g_comb; + wiphy->n_iface_combinations = 1; + } + + if (band_5gig) + { + wiphy->bands[IEEE80211_BAND_5GHZ] = &realtek_band_5ghz; + switch (get_rf_mimo_mode(priv)) + { + case MIMO_1T1R: + wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.mcs.rx_highest = cpu_to_le16(150); + wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.mcs.rx_mask[0] = 0xff; + wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.mcs.rx_mask[1] = 0; + wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.mcs.rx_mask[2] = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0xfffe); + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0xfffe); + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.vht_mcs.rx_highest = cpu_to_le16(390); + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.vht_mcs.tx_highest = cpu_to_le16(390); + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap &= ~(IEEE80211_VHT_CAP_TXSTBC); +#endif + break; + case MIMO_2T2R: + /* skip default setting */ + break; + case MIMO_3T3R: + wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.mcs.rx_highest = cpu_to_le16(450); + wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.mcs.rx_mask[0] = 0xff; + wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.mcs.rx_mask[1] = 0xff; + wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap.mcs.rx_mask[2] = 0xff; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0xffea); + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0xffea); + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.vht_mcs.rx_highest = cpu_to_le16(1170); + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.vht_mcs.tx_highest = cpu_to_le16(1170); + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap |= (IEEE80211_VHT_CAP_RXLDPC); +#endif + break; + default: + NDEBUG(" Waring, mimo(%d) not support\n", get_rf_mimo_mode(priv)); + break; + } + +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv)==VERSION_8814A) { + if (priv->pshare->rf_ft_var.bf_sup_val != 0) { + txbf_max_ant = priv->pshare->rf_ft_var.bf_sup_val; + txbf_sounding_dim = priv->pshare->rf_ft_var.bf_sup_val; + } else if (get_rf_mimo_mode(priv) == MIMO_4T4R) { + txbf_max_ant = 3; + txbf_sounding_dim = 3; + } else if (get_rf_mimo_mode(priv) == MIMO_3T3R) { + txbf_max_ant = 2; + txbf_sounding_dim = 3; + } else if ((get_rf_mimo_mode(priv) == MIMO_2T4R) || (get_rf_mimo_mode(priv) == MIMO_2T2R)) { + txbf_max_ant = 2; + txbf_sounding_dim = 1; + } else { + txbf_max_ant = 1; + txbf_sounding_dim = 1; + } + + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap &= ~IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap |= (txbf_max_ant << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT); + + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap &= ~IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; + wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap.cap |= (txbf_sounding_dim << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT); + } +#endif + + wiphy->iface_combinations = &rtk_5g_comb; + wiphy->n_iface_combinations = 1; + } + + wiphy->cipher_suites = cipher_suites; + wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + +#if 0//def CONFIG_PM + wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_4WAY_HANDSHAKE; + wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; + wiphy->wowlan.pattern_min_len = 1; + wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; + + wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS; + + + wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; + wiphy->probe_resp_offload = + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) + wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; +#endif + //printk("wiphy_register +++ \n"); + ret = wiphy_register(wiphy); + //printk("wiphy_register --- \n"); + + if (ret < 0) { + printk("couldn't register wiphy device\n"); + return ret; + } else + printk("register wiphy device:%p\n", wiphy); + + rtk->wiphy_registered = true; + + NLEXIT; + return 0; +} + +int realtek_cfg80211_deinit(struct rtl8192cd_priv *priv, struct rtknl *rtk) +{ + struct wiphy *wiphy = rtk->wiphy; + + set_wiphy_dev(wiphy, NULL); + + printk("deinit wiphy: [%p]:[%p]\n", rtk, wiphy); + + if (rtk->wiphy_registered) { + wiphy_unregister(wiphy); + rtk->wiphy_registered = false; + } + + return 0; +} + +#endif //RTK_NL80211 + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_cfg80211.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_cfg80211.h new file mode 100755 index 000000000..a0b37f0da --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_cfg80211.h @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2011 Atheros Communications Inc. + * Copyright (c) 2011-2012 Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef RTK_NL80211 +#define RTK_NL80211 +#endif + +#ifdef RTK_NL80211 +#include "./wifi.h"/*cfg p2p cfg p2p*/ +#include "osdep_service.h" + +#define DSSET_IE_LEN 1 +#define HTCAP_IE_LEN 26 +#define HTINFO_IE_LEN 22 +#define MAX_PROBED_SSIDS 32 + +#define VIF_NUM RTL8192CD_NUM_VWLAN //eric-vap +#define IF_NUM (VIF_NUM+2) //#vap + root + vxd +#define VIF_NAME_SIZE 10 +/*cfg p2p cfg p2p*/ +#define MAX_IE_LEN 768 + +#define MAX_ASSOC_REQ_LEN 512 +#define MAX_ASSOC_RSP_LEN 512 + +// cliWW +extern void notify_cfg_evt(struct rtl8192cd_priv *priv, unsigned char *mac, int event, unsigned char *extra); + +#define RATETAB_ENT(_rate, _rateid, _flags) { \ + .bitrate = (_rate), \ + .flags = (_flags), \ + .hw_value = (_rateid), \ +} + + +static struct ieee80211_rate realtek_rates[] = { + RATETAB_ENT(10, 0x1, 0), + RATETAB_ENT(20, 0x2, 0), + RATETAB_ENT(55, 0x4, 0), + RATETAB_ENT(110, 0x8, 0), + RATETAB_ENT(60, 0x10, 0), + RATETAB_ENT(90, 0x20, 0), + RATETAB_ENT(120, 0x40, 0), + RATETAB_ENT(180, 0x80, 0), + RATETAB_ENT(240, 0x100, 0), + RATETAB_ENT(360, 0x200, 0), + RATETAB_ENT(480, 0x400, 0), + RATETAB_ENT(540, 0x800, 0), +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) +enum nl80211_chan_width { + NL80211_CHAN_WIDTH_20_NOHT, + NL80211_CHAN_WIDTH_20, + NL80211_CHAN_WIDTH_40, + NL80211_CHAN_WIDTH_80, + NL80211_CHAN_WIDTH_80p80, + NL80211_CHAN_WIDTH_160, +}; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) +#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) +#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06 +#endif + + + +#define realtek_g_rates (realtek_rates + 0) +#define realtek_g_rates_size 12 + +#define realtek_a_rates (realtek_rates + 4) +#define realtek_a_rates_size 8 + +#define realtek_g_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ + IEEE80211_HT_CAP_SGI_20 | \ + IEEE80211_HT_CAP_SGI_40) + +#define realtek_a_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ + IEEE80211_HT_CAP_SGI_20 | \ + IEEE80211_HT_CAP_SGI_40) + +#define realtek_a_vhtcap (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_80MHZ) + + +/* WMI_CONNECT_CMDID */ +enum network_type { + INFRA_NETWORK = 0x01, + ADHOC_NETWORK = 0x02, + ADHOC_CREATOR = 0x04, + AP_NETWORK = 0x10, +}; + +enum scan_abort_case { + SCAN_ABORT_DEL_IFACE = 0, + SCAN_ABORT_START_AP, +}; + +#if 0/*cfg p2p cfg p2p*/ +enum mgmt_type { + MGMT_BEACON = 0, + MGMT_PROBERSP = 1, + MGMT_ASSOCRSP = 2, + MGMT_ASSOCREQ = 3, + MGMT_PROBEREQ = 4, +}; +#endif + +static const u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + WLAN_CIPHER_SUITE_AES_CMAC, + WLAN_CIPHER_SUITE_GCMP, + //CCKM_KRK_CIPHER_SUITE, + //WLAN_CIPHER_SUITE_SMS4, +}; + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .hw_value = (_channel), \ + .center_freq = (_freq), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .hw_value = (_channel), \ + .center_freq = 5000 + (5 * (_channel)), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + + +static struct ieee80211_channel realtek_2ghz_channels[] = { + CHAN2G(1, 2412, IEEE80211_CHAN_NO_HT40MINUS), + CHAN2G(2, 2417, IEEE80211_CHAN_NO_HT40MINUS), + CHAN2G(3, 2422, IEEE80211_CHAN_NO_HT40MINUS), + CHAN2G(4, 2427, IEEE80211_CHAN_NO_HT40MINUS), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, IEEE80211_CHAN_NO_HT40PLUS), + CHAN2G(9, 2452, IEEE80211_CHAN_NO_HT40PLUS), + CHAN2G(10, 2457, IEEE80211_CHAN_NO_HT40PLUS), + CHAN2G(11, 2462, IEEE80211_CHAN_NO_HT40PLUS), + CHAN2G(12, 2467, IEEE80211_CHAN_NO_HT40PLUS), + CHAN2G(13, 2472, IEEE80211_CHAN_NO_HT40PLUS), + CHAN2G(14, 2484, IEEE80211_CHAN_NO_HT40PLUS | + IEEE80211_CHAN_NO_HT40MINUS +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + | IEEE80211_CHAN_NO_OFDM +#endif + ) +}; + +static struct ieee80211_channel realtek_5ghz_a_channels[] = { + /* UNII-1 */ + CHAN5G(36, IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(40, IEEE80211_CHAN_NO_HT40PLUS), + CHAN5G(44, IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(48, IEEE80211_CHAN_NO_HT40PLUS), + /* UNII-2 */ + CHAN5G(52, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(56, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40PLUS), + CHAN5G(60, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(64, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40PLUS), + /* MID */ + CHAN5G(100, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(104, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40PLUS), + CHAN5G(108, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(112, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40PLUS), + CHAN5G(116, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(120, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40PLUS), + CHAN5G(124, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(128, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40PLUS), + CHAN5G(132, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(136, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40PLUS), + CHAN5G(140, + IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_HT40PLUS | + IEEE80211_CHAN_NO_HT40MINUS), + /* UNII-3 */ + CHAN5G(149, IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(153, IEEE80211_CHAN_NO_HT40PLUS), + CHAN5G(157, IEEE80211_CHAN_NO_HT40MINUS), + CHAN5G(161, IEEE80211_CHAN_NO_HT40PLUS), + CHAN5G(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) +}; + +static struct ieee80211_supported_band realtek_band_2ghz = { + .band = NL80211_BAND_2GHZ, + .n_channels = ARRAY_SIZE(realtek_2ghz_channels), + .channels = realtek_2ghz_channels, + .n_bitrates = realtek_g_rates_size, + .bitrates = realtek_g_rates, + .ht_cap = { + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40, + .ht_supported = true, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ampdu_density = 7, + .mcs = { + .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, + .rx_highest = cpu_to_le16(300), + .tx_params = IEEE80211_HT_MCS_TX_DEFINED + } + } +}; + +static struct ieee80211_supported_band realtek_band_5ghz = { + .band = NL80211_BAND_5GHZ, + .n_channels = ARRAY_SIZE(realtek_5ghz_a_channels), + .channels = realtek_5ghz_a_channels, + .n_bitrates = realtek_a_rates_size, + .bitrates = realtek_a_rates, + .ht_cap = { + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_RX_STBC, + .ht_supported = true, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ampdu_density = 7, + .mcs = { + .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}, + .rx_highest = cpu_to_le16(300), + .tx_params = IEEE80211_HT_MCS_TX_DEFINED + } + }, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) + .vht_cap = { + .vht_supported = true, + .cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | IEEE80211_VHT_CAP_SHORT_GI_80 | + IEEE80211_VHT_CAP_TXSTBC | IEEE80211_VHT_CAP_RXSTBC_1 | +#ifdef BEAMFORMING_SUPPORT + IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | + (1 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT) | (1 << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT) | +#endif + IEEE80211_VHT_CAP_HTC_VHT | (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT), + .vht_mcs = { + .rx_mcs_map = cpu_to_le16(0xfffa), + .tx_mcs_map = cpu_to_le16(0xfffa), + .rx_highest = cpu_to_le16(780), + .tx_highest = cpu_to_le16(780), + } + } +#endif +}; + +struct rtk_clnt_info { + struct wpa_ie_info wpa_ie; + struct rsn_ie_info rsn_ie; + unsigned char assoc_req[MAX_ASSOC_REQ_LEN]; + unsigned short assoc_req_len; + unsigned char assoc_rsp[MAX_ASSOC_RSP_LEN]; + unsigned short assoc_rsp_len; +}; + +struct rtk_iface_info { + unsigned char used; + unsigned char ndev_name[32]; + struct rtl8192cd_priv *priv; +}; + +struct survey_info_t { + unsigned int channel; + unsigned int chbusytime; + unsigned int rx_time; + unsigned int tx_time; + s8 noise; +}; + +struct rtknl { + struct class *cl; + struct device *dev; + struct wiphy *wiphy; + struct rtl8192cd_priv *priv; + struct net_device *ndev_add; + struct rtk_clnt_info clnt_info; + unsigned char num_vif; + int idx_vif; + unsigned char num_vap; + unsigned char num_vxd; + unsigned int vif_flag; + unsigned char wiphy_registered; + unsigned int cipher; + unsigned int wpa; + unsigned int psk; + unsigned int sha256; + unsigned char ndev_name[VIF_NUM][VIF_NAME_SIZE]; + unsigned char ndev_name_vxd[VIF_NAME_SIZE]; + unsigned char root_ifname[VIF_NAME_SIZE]; + unsigned char root_mac[ETH_ALEN]; + unsigned char vap_mac[VIF_NUM][ETH_ALEN]; + struct rtl8192cd_priv *priv_root; + struct rtl8192cd_priv *priv_vxd; + struct rtk_iface_info rtk_iface[VIF_NUM+2]; + //for survey_dump + struct survey_info_t survey_info[ARRAY_SIZE(realtek_5ghz_a_channels)]; + /* By brian, to support per channel statistic + unsigned int chbusytime; + unsigned int rx_time; + unsigned int tx_time; + */ + //openwrt_psd + unsigned int psd_chnl; + unsigned int psd_bw; + unsigned int psd_pts; + unsigned int psd_fft_info[1040]; + //openwrt_tx_power_use + unsigned int pwr_rate; + int pwr_cur; + int pwr_set_dbm; + unsigned char keep_legacy; +}; + +/* HT Capabilities Info field within HT Capabilities element */ +#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5)) +#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6)) + +/* VHT Defines */ +#define VHT_CAP_SHORT_GI_80 ((u32) BIT(5)) + +#if defined(VAP_MAC_DRV_READ_FLASH) +int read_flash_hw_mac_vap( unsigned char *mac, int vap_idx); +#endif +unsigned char is_WRT_scan_iface(const char* if_name); //eric-vap +void realtek_cfg80211_inform_ss_result(struct rtl8192cd_priv *priv); +struct rtknl *realtek_cfg80211_create(void); +int realtek_rtknl_init(struct rtknl *rtk); +int realtek_cfg80211_init(struct rtknl *rtk,struct rtl8192cd_priv *priv); +int realtek_interface_add(struct rtl8192cd_priv *priv, struct rtknl *rtk, const char *name, + enum nl80211_iftype type, u8 fw_vif_idx, u8 nw_type); + +int realtek_cfg80211_deinit(struct rtl8192cd_priv *priv, struct rtknl *rtk); +int realtek_interface_del(struct rtl8192cd_priv *priv, struct rtknl *rtk, struct net_device *ndev); +int realtek_cfg80211_destroy(struct rtknl *rtk); + +int event_indicate_cfg80211(struct rtl8192cd_priv *priv, unsigned char *mac, int event, void *extra); +void close_vxd_vap(struct rtl8192cd_priv *priv_root); +int check_5M10M_config(struct rtl8192cd_priv *priv); +void realtek_change_iftype(struct rtl8192cd_priv *priv ,enum nl80211_iftype type); + +void rtk_cfg80211_rx_mgmt(struct rtl8192cd_priv *priv , struct rx_frinfo *pfrinfo, unsigned char channel); +#ifdef RTK_NL80211_HS_CLI +void realtek_cfg80211_RemainOnChExpire(unsigned long task_priv); +#endif + + +#endif /* RTK_NL80211 */ diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_comapi.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_comapi.c new file mode 100755 index 000000000..0c1b93e26 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_comapi.c @@ -0,0 +1,3994 @@ +/* + * API-compatible handling routines + * + * + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_COMAPI_C_ + + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#endif + +#ifdef __LINUX_2_6__ +#include +#include +#endif + +#include "./8192cd_debug.h" +#include "./8192cd_comapi.h" +#include "./8192cd_headers.h" + +#ifdef CONFIG_RTL_COMAPI_WLTOOLS +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_A, _B, _C, _D, _E) +#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_A, _B, _C, _D, _E) +#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_A, _B, _C, _D, _E, _F) +#else +#define IWE_STREAM_ADD_EVENT(_A, _B, _C, _D, _E) iwe_stream_add_event(_B, _C, _D, _E) +#define IWE_STREAM_ADD_POINT(_A, _B, _C, _D, _E) iwe_stream_add_point(_B, _C, _D, _E) +#define IWE_STREAM_ADD_VALUE(_A, _B, _C, _D, _E, _F) iwe_stream_add_value(_B, _C, _D, _E, _F) +#endif + +typedef struct _CH_FREQ_MAP_{ + UINT16 channel; + UINT16 freqKHz; +}CH_FREQ_MAP; + +CH_FREQ_MAP CH_HZ_ID_MAP[] = +{ + {1, 2412}, + {2, 2417}, + {3, 2422}, + {4, 2427}, + {5, 2432}, + {6, 2437}, + {7, 2442}, + {8, 2447}, + {9, 2452}, + {10, 2457}, + {11, 2462}, + {12, 2467}, + {13, 2472}, + {14, 2484}, + + /* UNII */ + {36, 5180}, + {40, 5200}, + {44, 5220}, + {48, 5240}, + {52, 5260}, + {56, 5280}, + {60, 5300}, + {64, 5320}, + {149, 5745}, + {153, 5765}, + {157, 5785}, + {161, 5805}, + {165, 5825}, + {167, 5835}, + {169, 5845}, + {171, 5855}, + {173, 5865}, + + /* HiperLAN2 */ + {100, 5500}, + {104, 5520}, + {108, 5540}, + {112, 5560}, + {116, 5580}, + {120, 5600}, + {124, 5620}, + {128, 5640}, + {132, 5660}, + {136, 5680}, + {140, 5700}, + + /* Japan MMAC */ + {34, 5170}, + {38, 5190}, + {42, 5210}, + {46, 5230}, + + /* Japan */ + {184, 4920}, + {188, 4940}, + {192, 4960}, + {196, 4980}, + + {208, 5040}, /* Japan, means J08 */ + {212, 5060}, /* Japan, means J12 */ + {216, 5080}, /* Japan, means J16 */ +}; + +int CH_HZ_ID_MAP_NUM = (sizeof(CH_HZ_ID_MAP)/sizeof(CH_FREQ_MAP)); + + +#define MAP_CHANNEL_ID_TO_KHZ(_ch, _khz) \ + do{ \ + int _chIdx; \ + for (_chIdx = 0; _chIdx < CH_HZ_ID_MAP_NUM; _chIdx++)\ + { \ + if ((_ch) == CH_HZ_ID_MAP[_chIdx].channel) \ + { \ + (_khz) = CH_HZ_ID_MAP[_chIdx].freqKHz * 1000; \ + break; \ + } \ + } \ + if (_chIdx == CH_HZ_ID_MAP_NUM) \ + (_khz) = 2412000; \ + }while(0) + +#define MAP_KHZ_TO_CHANNEL_ID(_khz, _ch) \ + do{ \ + int _chIdx; \ + for (_chIdx = 0; _chIdx < CH_HZ_ID_MAP_NUM; _chIdx++)\ + { \ + if ((_khz) == CH_HZ_ID_MAP[_chIdx].freqKHz) \ + { \ + (_ch) = CH_HZ_ID_MAP[_chIdx].channel; \ + break; \ + } \ + } \ + if (_chIdx == CH_HZ_ID_MAP_NUM) \ + (_ch) = 1; \ + }while(0) + +/* +struct iw_statistics *rtl8192cd_get_wireless_stats(struct net_device *net_dev) +{ + // client mode only + return NULL; +} +*/ + +#ifdef WIFI_WPAS_CLI +extern void clean_for_join(struct rtl8192cd_priv *priv); + +void use_ap_scan( RTL_PRIV *priv ) +{ + RTL_PRIV *r_priv; + + priv->pshare->bScanInProcess = FALSE; + + if ( IS_ROOT_INTERFACE(priv) ) { + printk("cliW: ss_req\n"); + priv->ss_req_ongoing = 1; + start_clnt_ss(priv); + } else { + printk("cliW: vxd req\n"); + r_priv = GET_ROOT(priv); + r_priv->ss_ssidlen = 0; + r_priv->ss_req_ongoing = SSFROM_WPAS; + start_clnt_ss(r_priv); + } +} + +#if 0 +void switch_chan(struct rtl8192cd_priv *priv, struct bss_desc *bss_desp) +{ + struct rtl8192cd_priv *root_priv; + u8 is_40m, channel, ch_offset; + int bw; + unsigned long flags; + + printk("vxd chan follows\n"); + + //RTL_W8(TXPAUSE, 0xff); + + channel = bss_desp->channel; + priv->pmib->dot11RFEntry.dot11channel = channel; + + if ((bss_desp->t_stamp[1] & (BIT(1) | BIT(2))) == (BIT(1) | BIT(2))) + ch_offset = HT_2NDCH_OFFSET_BELOW; + else if ((bss_desp->t_stamp[1] & (BIT(1)|BIT(2))) == BIT(1)) + ch_offset = HT_2NDCH_OFFSET_ABOVE; + else + ch_offset = HT_2NDCH_OFFSET_DONTCARE; + + if ( ch_offset != 0 ) + is_40m = 1; + + if ( IS_VXD_INTERFACE(priv) ) { + root_priv = GET_ROOT(priv); + bw = (root_priv->pmib->dot11nConfigEntry.dot11nUse40M && is_40m); + if (0 == bw) + ch_offset = HT_2NDCH_OFFSET_DONTCARE; + + priv->pshare->is_40m_bw = bw; + priv->pshare->CurrentChannelBW = bw; + priv->pshare->offset_2nd_chan = ch_offset; + + priv->pmib->dot11RFEntry.dot11channel = channel; + priv->pmib->dot11nConfigEntry.dot11nUse40M = bw; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = ch_offset; + + root_priv->pmib->dot11RFEntry.dot11channel = channel; + root_priv->pmib->dot11nConfigEntry.dot11nUse40M = bw; + root_priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = ch_offset; + root_priv->ht_cap_len = 0; // re-construct HT IE + init_beacon(root_priv); +#ifdef MBSSID + if (root_priv->pmib->miscEntry.vap_enable) { + struct rtl8192cd_priv *vap_priv; + int i; + + for (i = 0; i < RTL8192CD_NUM_VWLAN; i++) { + vap_priv = root_priv->pvap_priv[i]; + if (IS_DRV_OPEN(vap_priv)) { + vap_priv->pmib->dot11RFEntry.dot11channel = channel; + vap_priv->pmib->dot11nConfigEntry.dot11nUse40M = bw; + vap_priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = ch_offset; + vap_priv->ht_cap_len = 0; // re-construct HT IE + init_beacon(vap_priv); + } + } + } +#endif // MBSSID + } else { + root_priv = priv; + + priv->pshare->is_40m_bw = is_40m; + priv->pshare->CurrentChannelBW = is_40m; + priv->pshare->offset_2nd_chan = ch_offset; + + priv->pmib->dot11RFEntry.dot11channel = channel; + priv->pmib->dot11nConfigEntry.dot11nUse40M = is_40m; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = ch_offset; +#ifdef UNIVERSAL_REPEATER + // TO DO ... +#endif + } + + SwBWMode(root_priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(root_priv, channel, priv->pshare->offset_2nd_chan); + + // RTL_W8(TXPAUSE, 0x00); + + // update_beacon +} +#endif + +int rtl_wx_dummy(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + return -1; +} + + +int rtl_wx_join(struct rtl8192cd_priv *priv, struct bss_desc *bss_desp) +{ + char tmpbuf[33]; + + printk("cliW: join opmode: %x res:%x \n", OPMODE, priv->join_res); + if (!netif_running(priv->dev)) + { + printk("WiFi driver is NOT open!!\n"); + return 1; + } + else if (priv->ss_req_ongoing) + { + printk("Site Survey is not finished yet!!\n"); + return 2; + } + + //if ( priv->join_res == STATE_Sta_No_Bss ) + // goto cnti_join; + + // memcpy((void *)&(priv->pmib->dot11Bss) , + // (void *)&priv->site_survey->bss_backup[bss_num] , sizeof(struct bss_desc)); + + memcpy(&(priv->pmib->dot11Bss), bss_desp, sizeof(struct bss_desc)); + +#if 0 + if ( priv->join_req_ongoing ) { + printk("cliW: no join under connecinting \n"); + return 0; + } +#endif + + if( ( priv->pmib->dot11Bss.ssidlen < 0) || (priv->pmib->dot11Bss.ssidlen > 32) ) { + printk("cliW: wrong ssid len\n"); + return 3; + } +#if 0 + if (priv->ss_req_ongoing || priv->join_req_ongoing ) { + printk("cliW: no join under scanning \n"); + return 0; + } +#endif + + if ( OPMODE & ( WIFI_AUTH_STATE1 | WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE) ) { + printk("cliW: no joining when in auth\n"); + return 4; + } + +#if 0 + if ( OPMODE & WIFI_ASOC_STATE || (priv->join_res == STATE_Sta_Bss) ) { + printk("cliW: no joining when in asso\n"); + return 0; + } +#endif + +#ifdef WIFI_SIMPLE_CONFIG + //_Eric if (priv->pmib->wscEntry.wsc_enable && (priv->pmib->dot11Bss.bsstype&WIFI_WPS)) + if (priv->pmib->wscEntry.wsc_enable) + { + //priv->pmib->dot11Bss.bsstype &= ~WIFI_WPS; + priv->wps_issue_join_req = 1; + } + else +#endif + { + if (check_bss_encrypt(priv) == FAIL) + { + printk("Encryption mismatch!\n"); + return 5; + } + } + + if ((priv->pmib->dot11Bss.ssidlen == 0) || (priv->pmib->dot11Bss.ssid[0] == '\0')) + { + printk("Error !! Join to a hidden AP!\n"); + return 6; + } + +#ifdef UNIVERSAL_REPEATER + disable_vxd_ap(GET_VXD_PRIV(priv)); +#endif + + memcpy(tmpbuf, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + tmpbuf[priv->pmib->dot11Bss.ssidlen] = '\0'; + printk("going to join bss: %s\n", tmpbuf); + + memcpy(SSID2SCAN, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + SSID2SCAN_LEN = priv->pmib->dot11Bss.ssidlen; + + SSID_LEN = SSID2SCAN_LEN; + memcpy(SSID, SSID2SCAN, SSID_LEN); + memset(BSSID, 0, MACADDRLEN); + +#ifdef INCLUDE_WPA_PSK //_Eric ?? + //if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) + //derivePSK(priv); +#endif + + priv->join_req_ongoing = 1; + priv->authModeRetry = 0; + + // switch_chan() is replaced with clnt_switch_chan_to_bss in start_clnt_auth + //switch_chan(priv, bss_desp); + + printk("cliw: start join... in ch:%d\n", bss_desp->channel); +#if defined(CONFIG_PCI_HCI) + start_clnt_join(priv); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + // avoid IQK handling race condition between start_clnt_auth and TXPowerTracking + // so we indicate WPAS_JOIN event to cmd_thread to do start_clnt_join() + notify_wpas_join(priv); +#endif + + return 0; +} + +int rtl_wx_get_name(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + struct stat_info *pstat; + struct wifi_mib *pmib; + char *p; + + DEBUG_INFO("cmd_code=%x\n", info->cmd); + + DBFENTER; + + pstat = priv->pstat_cache; + if (pstat == NULL) { + DEBUG_INFO("pstat is NULL\n"); + return 0; + } + + pmib = GET_MIB(priv); + + if ((pstat->state & (WIFI_ASOC_STATE | WIFI_AUTH_SUCCESS)) == ((WIFI_ASOC_STATE | WIFI_AUTH_SUCCESS))) + { + p = wrqu->name; + p += sprintf(p, "IEEE 802.11"); + + if (pmib->dot11BssType.net_work_type & WIRELESS_11A) { + p += sprintf(p, "a"); + } + + if (pmib->dot11BssType.net_work_type & WIRELESS_11B) { + p += sprintf(p, "b"); + } + + if (pmib->dot11BssType.net_work_type & WIRELESS_11G) { + p += sprintf(p, "g"); + } + + if (pmib->dot11BssType.net_work_type & WIRELESS_11N) { + p += sprintf(p, "n"); + } + + if (pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + p += sprintf(p, "ac"); + } + } + else + { + //prates = &padapter->registrypriv.dev_network.SupportedRates; + //snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11g"); + snprintf(wrqu->name, IFNAMSIZ, "off/any"); + } + + DBFEXIT; + + return 0; +} + +int rtl_wx_set_mode(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret = 0; + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + switch(wrqu->mode) + { + case IW_MODE_AUTO: + if (OPMODE & WIFI_STATION_STATE) { + OPMODE = WIFI_STATION_STATE; + printk("set_mode = IW_MODE_AUTO ==> WIFI_STATION_STATE\n"); + } else { + OPMODE = WIFI_AP_STATE; + printk("set_mode = IW_MODE_AUTO ==> WIFI_AP_STATE\n"); + } + break; + case IW_MODE_ADHOC: + OPMODE = WIFI_ADHOC_STATE; + printk("set_mode = IW_MODE_ADHOC\n"); + break; + case IW_MODE_MASTER: + OPMODE = WIFI_AP_STATE; + printk("set_mode = IW_MODE_MASTER\n"); + break; + case IW_MODE_INFRA: + OPMODE = WIFI_STATION_STATE; + printk("set_mode = IW_MODE_INFRA\n"); + break; + + default : + ret = -EINVAL; + DEBUG_WARN("Mode: %d is not supported\n", wrqu->mode); + break; + } + + // TODO: Active the Operation Mode + return ret; +} + +int rtl_wx_get_sens(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wrqu->sens.value = 0; + wrqu->sens.fixed = 0; /* no auto select */ + wrqu->sens.disabled = 1; + return 0; +} + +void clean_conn_var(RTL_PRIV *priv) +{ + if (timer_pending(&priv->reauth_timer)) + del_timer_sync (&priv->reauth_timer); + + if (timer_pending(&priv->reassoc_timer)) + del_timer_sync (&priv->reassoc_timer); +#if 0 + priv->reauth_count = 0; + priv->reassoc_count = 0; + priv->auth_seq = 0; + + priv->join_res = STATE_Sta_No_Bss; + priv->reauth_count = 0; + priv->reassoc_count = 0; +#endif + priv->join_req_ongoing = 0; + priv->ss_req_ongoing = 0; + + clean_for_join(priv); +} + +#if WIRELESS_EXT >= 18 +int rtl_wx_set_mlme( + struct net_device *dev, + struct iw_request_info *info, + struct iw_point *erq, + char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + struct iw_mlme *wextmlme = (struct iw_mlme *)extra; + struct stat_info *pstat; + +#ifdef SDIO_AP_OFFLOAD + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_COMAPI); +#endif + switch(wextmlme->cmd) { + case IW_MLME_DEAUTH: + printk("Set MLME: IW_MLME_DEAUTH, Reason=%d\n", wextmlme->reason_code); + + if (OPMODE & (WIFI_AUTH_SUCCESS)) + { + issue_deauth(priv,BSSID,wextmlme->reason_code); + delay_ms(50); //Give some time to wait TX done + OPMODE &= ~(WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE) ; + + pstat = get_stainfo(priv, BSSID); + if (pstat != NULL) + { + if (asoc_list_del(priv, pstat)) + { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + } + } + + free_stainfo(priv, pstat); + } + + event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL); + } + clean_conn_var(priv); + break; + + case IW_MLME_DISASSOC: + printk("Set MLME: IW_MLME_DISASSOC, Reason=%d\n", wextmlme->reason_code); + + if((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + { + pstat = get_stainfo(priv, BSSID); + issue_disassoc(priv, BSSID, wextmlme->reason_code); + + if (pstat != NULL) + { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + } + + free_stainfo(priv, pstat); + +/* memset(&priv->pmib->dot11Bss, 0, sizeof(struct bss_desc)); + memset(priv->pmib->dot11StationConfigEntry.dot11Bssid, 0, MACADDRLEN); + memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID)); + priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = 0; + memset(priv->pmib->dot11StationConfigEntry.dot11DefaultSSID, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID)); + priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen = 0; + memset(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan)); + priv->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen = 0; + memset(priv->pmib->dot11StationConfigEntry.dot11DesiredBssid, 0, 6); + + priv->wpas_manual_assoc = 1; //_Eric ?? when to let driver auto-connect ?? +*/ + priv->join_res = STATE_Sta_No_Bss; +// pstat->state &= (~WIFI_ASOC_STATE); + } + } + OPMODE &= ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE); + event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL); + clean_conn_var(priv); + break; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + case IW_MLME_AUTH: + case IW_MLME_ASSOC: + break; +#endif + + default: +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_COMAPI); +#endif + return -EINVAL; + } + +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_COMAPI); +#endif + return 0; +} +#endif + +int rtl_wx_get_freq(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + unsigned int ch; + unsigned long khz; + + if (priv == NULL) { + /* if 1st open fail, pAd will be free; + * So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + ch = priv->pmib->dot11RFEntry.dot11channel; + + MAP_CHANNEL_ID_TO_KHZ(ch, khz); + wrqu->freq.m = khz * 100; + wrqu->freq.e = 1; + wrqu->freq.i = ch; + + return 0; +} +#endif // WIFI_WPAS_CLI + +int rtl_siwfreq(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + unsigned int chan=0; + +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + if (wrqu->freq.e > 1) + return -EINVAL; + + if((wrqu->freq.e == 0) && (wrqu->freq.m <= 1000)) + chan = wrqu->freq.m; // Setting by channel number + else +#ifdef WIFI_WPAS_CLI + MAP_KHZ_TO_CHANNEL_ID( (wrqu->freq.m /100000) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G, +#else + MAP_KHZ_TO_CHANNEL_ID( (wrqu->freq.m /100) , chan); // Setting by frequency - search the table , like 2.412G, 2.422G, +#endif + + priv->pmib->dot11RFEntry.dot11channel = chan; + +#ifdef WIFI_WPAS_CLI + printk("cliW: wrqu->freq.m: %d chan:%d \n", wrqu->freq.m, chan); +#else +#ifdef WIFI_HAPD + if (!netif_running(priv->dev)) + return 0; + else +#endif + SwChnl(priv, chan, priv->pshare->offset_2nd_chan); +#endif + + return 0; +} + +int rtl_giwfreq(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + unsigned int ch; + //unsigned long m = 2412000; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + ch = priv->pmib->dot11RFEntry.dot11channel; +/* + MAP_CHANNEL_ID_TO_KHZ(ch, m); + wrqu->freq.m = m * 100; + wrqu->freq.e = 1; + wrqu->freq.i = 0; +*/ + wrqu->freq.m = ch; + wrqu->freq.e = 0; + wrqu->freq.i = 0; + + return 0; +} + +int rtl_siwmode(struct net_device *dev, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int ret = 0; + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } +#ifndef SUPPORT_MONITOR +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif +#endif + + switch(wrqu->mode) + { + case IW_MODE_AUTO: // 0 +#ifdef WIFI_WPAS_CLI + if (OPMODE & WIFI_STATION_STATE) { + OPMODE_VAL(OPMODE & WIFI_STATION_STATE); + printk("set_mode = IW_MODE_AUTO ==> WIFI_STATION_STATE\n"); + } else { + OPMODE_VAL(OPMODE & WIFI_AP_STATE); + printk("set_mode = IW_MODE_AUTO ==> WIFI_AP_STATE\n"); + } +#else + OPMODE_VAL(OPMODE & WIFI_AP_STATE); + printk("set_mode = IW_MODE_AUTO\n"); +#endif + break; + case IW_MODE_ADHOC: // 1 + OPMODE_VAL(OPMODE & WIFI_ADHOC_STATE); + printk("set_mode = IW_MODE_ADHOC\n"); + break; + case IW_MODE_MASTER: // 3 + OPMODE_VAL(OPMODE & WIFI_AP_STATE); +#ifdef SUPPORT_MONITOR + priv->is_monitor_mode = FALSE; + panic_printk("priv->is_monitor_mode = %d,\n", priv->is_monitor_mode); + del_timer(&priv->chan_switch_timer); +#endif + printk("set_mode = IW_MODE_MASTER\n"); +// setopmode_cmd(padapter, networkType); + break; + case IW_MODE_INFRA: // 2 + OPMODE_VAL(OPMODE & WIFI_STATION_STATE); + printk("set_mode = IW_MODE_INFRA\n"); + break; +#ifdef SUPPORT_MONITOR + case IW_MODE_MONITOR: + OPMODE |= WIFI_SITE_MONITOR; + priv->is_monitor_mode = TRUE; + priv->chan_num = 0; + RTL_W32(RCR, RCR_APP_FCS | RCR_APP_MIC | RCR_APP_ICV | RCR_APP_PHYSTS | RCR_HTC_LOC_CTRL + | RCR_AMF | RCR_ADF | RCR_AICV | RCR_ACRC32 | RCR_CBSSID_ADHOC | RCR_AB | RCR_AM | RCR_APM | RCR_AAP); + init_timer(&priv->chan_switch_timer); + priv->chan_switch_timer.data = (unsigned long) priv; + priv->chan_switch_timer.function = rtl8192cd_chan_switch_timer; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->available_chnl[priv->chan_num], priv->pshare->offset_2nd_chan); + mod_timer(&priv->chan_switch_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.chan_switch_time)); + panic_printk("priv->is_monitor_mode = %d \n", priv->is_monitor_mode); + panic_printk("set_mode = IW_MODE_MONITOR\n"); + break; +#endif + default : + ret = -EINVAL; + } + + return ret; + +} + +int rtl_giwmode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + if (OPMODE & WIFI_AP_STATE) + wrqu->mode = IW_MODE_MASTER; + else if (OPMODE & WIFI_STATION_STATE) + wrqu->mode = IW_MODE_INFRA; + else if (OPMODE & WIFI_ADHOC_STATE) + wrqu->mode = IW_MODE_ADHOC; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) + else if (OPMODE & WIFI_SITE_MONITOR) + wrqu->mode = IW_MODE_MONITOR; +#endif + else + wrqu->mode = IW_MODE_AUTO; + + return 0; +} + +#define MAX_FRAG_THRESHOLD 2346 +#define MIN_FRAG_THRESHOLD 256 + +#define MAX_RTS_THRESHOLD 2347 + +#ifdef BALONG_PLT +enum ANDROID_WIFI_CMD { + ANDROID_WIFI_CMD_START, + ANDROID_WIFI_CMD_STOP, + ANDROID_WIFI_CMD_SCAN_ACTIVE, + ANDROID_WIFI_CMD_SCAN_PASSIVE, + ANDROID_WIFI_CMD_RSSI, + ANDROID_WIFI_CMD_LINKSPEED, + ANDROID_WIFI_CMD_RXFILTER_START, + ANDROID_WIFI_CMD_RXFILTER_STOP, + ANDROID_WIFI_CMD_RXFILTER_ADD, + ANDROID_WIFI_CMD_RXFILTER_REMOVE, + ANDROID_WIFI_CMD_BTCOEXSCAN_START, + ANDROID_WIFI_CMD_BTCOEXSCAN_STOP, + ANDROID_WIFI_CMD_BTCOEXMODE, + ANDROID_WIFI_CMD_SETSUSPENDOPT, + ANDROID_WIFI_CMD_P2P_DEV_ADDR, + ANDROID_WIFI_CMD_SETFWPATH, + ANDROID_WIFI_CMD_SETBAND, + ANDROID_WIFI_CMD_GETBAND, + ANDROID_WIFI_CMD_COUNTRY, + ANDROID_WIFI_CMD_P2P_SET_NOA, + ANDROID_WIFI_CMD_P2P_GET_NOA, + ANDROID_WIFI_CMD_P2P_SET_PS, + ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE, +#ifdef PNO_SUPPORT + ANDROID_WIFI_CMD_PNOSSIDCLR_SET, + ANDROID_WIFI_CMD_PNOSETUP_SET, + ANDROID_WIFI_CMD_PNOENABLE_SET, + ANDROID_WIFI_CMD_PNODEBUG_SET, +#endif + + ANDROID_WIFI_CMD_MACADDR, + + ANDROID_WIFI_CMD_BLOCK, + + ANDROID_WIFI_CMD_WFD_ENABLE, + ANDROID_WIFI_CMD_WFD_DISABLE, + + ANDROID_WIFI_CMD_WFD_SET_TCPPORT, + ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT, + ANDROID_WIFI_CMD_WFD_SET_DEVTYPE, + + ANDROID_WIFI_CMD_SET_KEEP_ALIVE, + + PRIV_WIFI_CMD_CSCAN_S, + + ANDROID_WIFI_CMD_MAX +}; + +const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = { + "START", + "STOP", + "SCAN-ACTIVE", + "SCAN-PASSIVE", + "RSSI", + "LINKSPEED", + "RXFILTER-START", + "RXFILTER-STOP", + "RXFILTER-ADD", + "RXFILTER-REMOVE", + "BTCOEXSCAN-START", + "BTCOEXSCAN-STOP", + "BTCOEXMODE", + "SETSUSPENDOPT", + "P2P_DEV_ADDR", + "SETFWPATH", + "SETBAND", + "GETBAND", + "COUNTRY", + "P2P_SET_NOA", + "P2P_GET_NOA", + "P2P_SET_PS", + "SET_AP_WPS_P2P_IE", +#ifdef PNO_SUPPORT + "PNOSSIDCLR", + "PNOSETUP ", + "PNOFORCE", + "PNODEBUG", +#endif + "MACADDR", + "BLOCK", + "WFD-ENABLE", + "WFD-DISABLE", + "WFD-SET-TCPPORT", + "WFD-SET-MAXTPUT", + "WFD-SET-DEVTYPE", + "KEEP_ALIVE", + "CSCAN S" +}; + +int rtw_android_cmdstr_to_num(char *cmdstr) +{ + int cmd_num; + int i; + + if ( cmdstr == NULL ) { + printk("cliw: no comp str\n"); + return 0; + } + + // printk("cliW: ANDROID_WIFI_CMD=%s\n", cmdstr); + + for(cmd_num=0 ; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++) { + if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) ) + break; + } + return cmd_num; +} + +char tmp_str[256]; + +int rtl_sipriv(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL ) + return -ENETDOWN; + + printk("cliW: rtl_sipriv\n"); +} + +#define WEXT_CSCAN_HEADER_SIZE 12 +#define WEXT_CSCAN_HEADER "CSCAN S\x01\x00\x00S\x00" + +#define WEXT_CSCAN_SSID_SECTION 'S' +// format : len - 1B , ssid +#define WEXT_CSCAN_CHANNEL_SECTION 'C' +// ch: 1B +#define WEXT_CSCAN_NPROBE_SECTION 'N' +// 1B +#define WEXT_CSCAN_ACTV_DWELL_SECTION 'A' +// 2B +#define WEXT_CSCAN_PASV_DWELL_SECTION 'P' +// 2B +#define WEXT_CSCAN_HOME_DWELL_SECTION 'H' +// 2B + +struct combo_scan ssid_scan_list[CSCAN_MAXNUM]; + +void parse_combo_ssid_info(char *ext) +{ + int ssid_cnt = 0; + int i; + unsigned char ssid_len; + char *bp = ext; + char buf[256]; + +#if 0 + if ( strlen(ext) < WEXT_CSCAN_HEADER_SIZE + 3 ) { + printk("cliW: combo scan erro format: %d\n"); + return; + } +#endif + printk("cliQ: start parse combo scan\n"); + + for (i=0 ; i< CSCAN_MAXNUM; i++); + memset(&ssid_scan_list[0], 0, sizeof(struct combo_scan)); + + bp = ext + WEXT_CSCAN_HEADER_SIZE; + + while( bp != NULL ) { + // printk("cliW: %x %x %x %x\n", *bp, *(bp+1), *(bp+2), 'S'); + if ( *bp == WEXT_CSCAN_SSID_SECTION ) { + if ( *(bp + 1) == 0 ) { + printk("cliW: ssid ==0 \n"); + return; + } + + ssid_len = *(bp + 1); + //memcpy(buf, (bp + 2) , ssid_len); + //buf[ssid_len] = '\0'; + + memcpy(ssid_scan_list[ssid_cnt].ssid, (bp + 2) , ssid_len); + ssid_scan_list[ssid_cnt].ssid[ssid_len] = '\0'; + ssid_scan_list[ssid_cnt].ssid_len = ssid_len; + ssid_scan_list[ssid_cnt].used = 1; + + if ( ssid_cnt > CSCAN_MAXNUM ) { + printk("cliQ: ssid list more than max, skip\n"); + bp += ssid_len + 1; + continue; + } + + printk("cliQ:ssid %d %s\n", ssid_len, ssid_scan_list[ssid_cnt].ssid); + ssid_cnt++; + bp += ssid_len + 2; + + } else if ( *bp == WEXT_CSCAN_CHANNEL_SECTION || *bp == WEXT_CSCAN_NPROBE_SECTION ) { + i = *(bp + 1); + + if ( *bp == WEXT_CSCAN_CHANNEL_SECTION ) + printk("cliQ: scan ch:%d\n", i); + + if ( *bp == WEXT_CSCAN_NPROBE_SECTION ) + printk("cliQ: scan np probe:%d\n", i); + + bp += 2; + } else { + i = *(bp + 1); + + if ( *bp == WEXT_CSCAN_ACTV_DWELL_SECTION ) { + printk("cliQ: scan active dwell time:%d\n", i); + } else if ( *bp == WEXT_CSCAN_PASV_DWELL_SECTION ) { + printk("cliQ: scan passive dwell time:%d\n", i); + } else if ( *bp == WEXT_CSCAN_HOME_DWELL_SECTION ) { + printk("cliQ: scan home dwell time:%d\n", i); + printk("cliQ: parse done\n"); + return; + } else { + printk("cliQ: parse parm error \n"); + return; + } + + bp += 3; + } + } +} + +int rtl_gipriv(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + struct stat_info *pstat; + int ret = 0, len = 0; + int i; + char *ext; + struct iw_point *dwrq = (struct iw_point*)awrq; + + if (priv == NULL ) + return -ENETDOWN; + +#if !(defined(WIFI_HAPD) || defined (WIFI_WPAS)) + if (!netif_running(priv->dev)) + return -ENETDOWN; +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if ((TRUE == priv->pshare->bDriverStopped) || (TRUE == priv->pshare->bSurpriseRemoved)) + return -ENETDOWN; +#endif + + len = dwrq->length; + ext = tmp_str; + + if (copy_from_user(ext, dwrq->pointer, len)) { + return -EFAULT; + } + + i = rtw_android_cmdstr_to_num(ext); + + // printk("acli: gipriv 1 num:%d\n", i); + + switch(i) { + case ANDROID_WIFI_CMD_SET_KEEP_ALIVE : + if ( (OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE) ) + { + char *pch, *ptmp, *token, *tmp[3]={0x00,0x00,0x00}; + u32 prd; + + pch = ext; + i = 0; + + printk("get cmd SET_KEEP_ALIVE \n"); + while ((token = strsep(&pch, " ")) != NULL) { + if (i > 2) break; + tmp[i] = token; + i++; + } +#if 0 + if ( i >=2 ) { + // printk("s1:%s s2:%s s3:%s\n", tmp[0], tmp[1], tmp[2]); + + prd = simple_strtoul(tmp[1], &ptmp, 10); + // printk("prd:%d\n", prd); + + if ( prd >= 1000 ) { + priv->keep_alive_time = prd / 1000; + } + } +#endif + sprintf(ext, "OK"); + } + break; + + case ANDROID_WIFI_CMD_RSSI : + if ( (OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE) ) + { + pstat = get_stainfo(priv, BSSID); + sprintf(ext, "%s rssi %d", SSID, (pstat->rssi - 100) ); +#if 0 + printk("cliW: %s\n", ext); + printk("cliW: dbm: %d\n", translate_percentage_to_dbm(pstat->rssi)); + printk("cliW: sg %d\n", pstat->sq); +#endif + } else { + sprintf(ext, "OK"); + // printk("cliW: %s\n", ext); + } + break; + + case PRIV_WIFI_CMD_CSCAN_S: + parse_combo_ssid_info(ext); + if (IS_VXD_INTERFACE(priv)) { + priv->ss_req_ongoing = 1; + use_ap_scan(priv); + } else { + priv->ss_req_ongoing = 1; + start_clnt_ss(priv); + } + sprintf(ext, "OK"); + break; + + default : + printk("cmd not found: %s\n", ext); + sprintf(ext, "OK"); + } + + if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (u16)(strlen(ext)+1)) ) ) + ret = -EFAULT; +out: + return 0; +} +#endif // BALONG_PLT + +int rtl_giwrange(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_range *range = (struct iw_range *)extra; + int i; + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL || range == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + wrqu->data.length = sizeof(*range); + memset(range, 0, sizeof(*range)); + + /* Let's try to keep this struct in the same order as in + * linux/include/wireless.h + */ + + /* TODO: See what values we can set, and remove the ones we can't + * set, or fill them with some default data. + */ + + /* ~5 Mb/s real (802.11b) */ + range->throughput = 5 * 1000 * 1000; + + // TODO: Not used in 802.11b? +// range->min_nwid; /* Minimal NWID we are able to set */ + // TODO: Not used in 802.11b? +// range->max_nwid; /* Maximal NWID we are able to set */ + + /* Old Frequency (backward compat - moved lower ) */ +// range->old_num_channels; +// range->old_num_frequency; +// range->old_freq[6]; /* Filler to keep "version" at the same offset */ + + /* signal level threshold range */ + + + //percent values between 0 and 100. + range->max_qual.qual = 100; + //range->max_qual.level = 100; + //range->max_qual.noise = 100; + range->max_qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID; /* Updated only qual b'coz not sure */ + + + range->avg_qual.qual = 60; + /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ + //range->avg_qual.level = 20; + //range->avg_qual.noise = 0; + range->avg_qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID; /* Updated only qual b'coz not sure */ + + range->num_bitrates = AP_BSSRATE_LEN; + + for(i=0; ibitrate[i] = (AP_BSSRATE[i]&0x7f)* 500000; + } + + range->min_frag = MIN_FRAG_THRESHOLD; + range->max_frag = MAX_FRAG_THRESHOLD; + + range->pm_capa = 0; + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 12; + +// range->retry_capa; /* What retry options are supported */ +// range->retry_flags; /* How to decode max/min retry limit */ +// range->r_time_flags; /* How to decode max/min retry life */ +// range->min_retry; /* Minimal number of retries */ +// range->max_retry; /* Maximal number of retries */ +// range->min_r_time; /* Minimal retry lifetime */ +// range->max_r_time; /* Maximal retry lifetime */ + + range->encoding_size[0]=5; + range->encoding_size[1]=13; + range->num_encoding_sizes = 2; + range->max_encoding_tokens = 4; + range->num_channels = priv->available_chnl_num; + range->num_frequency = priv->available_chnl_num; + + for (i = 0; i < priv->available_chnl_num && i < IW_MAX_FREQUENCIES; i++) { + u32 m = 0; + range->freq[i].i = i + 1; + //range->freq[val].m = CH_HZ_ID_MAP[i].freqKHz * 100000; + MAP_CHANNEL_ID_TO_KHZ(priv->available_chnl[i], m); + range->freq[i].m = m* 100; + range->freq[i].e = 1; + } + +// Commented by Albert 2009/10/13 +// The following code will proivde the security capability to network manager. +// If the driver doesn't provide this capability to network manager, +// the WPA/WPA2 routers can't be choosen in the network manager. + +/* +#define IW_SCAN_CAPA_NONE 0x00 +#define IW_SCAN_CAPA_ESSID 0x01 +#define IW_SCAN_CAPA_BSSID 0x02 +#define IW_SCAN_CAPA_CHANNEL 0x04 +#define IW_SCAN_CAPA_MODE 0x08 +#define IW_SCAN_CAPA_RATE 0x10 +#define IW_SCAN_CAPA_TYPE 0x20 +#define IW_SCAN_CAPA_TIME 0x40 +*/ + +#if WIRELESS_EXT > 17 + range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| + IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; +#endif + +#ifdef IW_SCAN_CAPA_ESSID + range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE |IW_SCAN_CAPA_BSSID| + IW_SCAN_CAPA_CHANNEL|IW_SCAN_CAPA_MODE|IW_SCAN_CAPA_RATE; +#endif + return 0; +} + +#ifdef WIFI_WPAS_CLI +int rtl_siwap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + if (priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) { + memset(&priv->pmib->dot11OperationEntry.hwaddr, 0, WLAN_ADDR_LEN); + memcpy(&priv->pmib->dot11OperationEntry.hwaddr, wrqu->ap_addr.sa_data, MACADDRLEN); + clean_for_join(priv); + return 0; + } +#if defined (WIFI_WPAS)//_Eric ?? + else if ( (priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) || + (priv->pmib->dot11OperationEntry.opmode & WIFI_ADHOC_STATE) ) + { + unsigned char null_mac[] = {0,0,0,0,0,0}; + struct bss_desc bss_desp; + + if ( memcmp(wrqu->ap_addr.sa_data, null_mac, MACADDRLEN) ) { + int i, found=0, ret=0; + for(i = 0 ; i < priv->site_survey->count_backup ; i++) + { + if(!memcmp(priv->site_survey->bss_backup[i].bssid , wrqu->ap_addr.sa_data, MACADDRLEN)) + { + memcpy((void *)&bss_desp, + (void *)&priv->site_survey->bss_backup[i], sizeof(struct bss_desc)); + found = 1; + break; + } + } + + if(found == 0) { + printk("BSSID NOT Found !!\n"); + } else { + ret = rtl_wx_join(priv, &bss_desp); + if(ret != 0) + printk("cliW: rtl_wpas_join Failed: err:%d !!\n", ret); + } + } + return 0; + } +#endif + else + return -EOPNOTSUPP; +} + +#else // !WIFI_WPAS_CLI +int rtl_siwap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + if (priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) { + memset(&priv->pmib->dot11OperationEntry.hwaddr, 0, WLAN_ADDR_LEN); + memcpy(&priv->pmib->dot11OperationEntry.hwaddr, wrqu->ap_addr.sa_data, MACADDRLEN); + return 0; + } else { +#ifdef WIFI_WPAS //_Eric ?? + if ( (priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) || + (priv->pmib->dot11OperationEntry.opmode & WIFI_ADHOC_STATE) ) + { + memset(&priv->pmib->dot11Bss.bssid, 0, WLAN_ADDR_LEN); + memcpy(&priv->pmib->dot11Bss.bssid, wrqu->ap_addr.sa_data, MACADDRLEN); + return 0; + } + else + return -EOPNOTSUPP; +#else + //memset(&priv->pmib->dot11Bss.bssid, 0, WLAN_ADDR_LEN); + //memcpy(&priv->pmib->dot11Bss.bssid, ap_addr->sa_data, MACADDRLEN); + return -EOPNOTSUPP; +#endif + } + +} +#endif // WIFI_WPAS_CLI + +int rtl_giwap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS)) + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + wrqu->ap_addr.sa_family = ARPHRD_ETHER; + if (priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) + memcpy(wrqu->ap_addr.sa_data, priv->pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + else + memcpy(wrqu->ap_addr.sa_data, priv->pmib->dot11Bss.bssid, MACADDRLEN); + + return 0; +} + +int rtl_iwaplist(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + struct sockaddr addr[IW_MAX_AP]; + struct iw_quality qual[IW_MAX_AP]; + int i; + struct list_head *phead, *plist; + struct stat_info *pstat; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + i = 0; + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead && i < IW_MAX_AP) { + pstat = list_entry(plist, struct stat_info, asoc_list); + addr[i].sa_family = ARPHRD_ETHER; + memcpy(addr[i].sa_data, &pstat->hwaddr, WLAN_ADDR_LEN); + + qual[i].qual = pstat->rssi; + //qual[i].level = pstat->sq; + //qual[i].noise = 0 + qual[i].updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID; + + plist = plist->next; + i++; + } + + SMP_UNLOCK_ASOC_LIST(flags); + + data->length = i; + memcpy(extra, &addr, i*sizeof(addr[0])); + data->flags = 1; /* signal quality present (sort of) */ + memcpy(extra + i*sizeof(addr[0]), &qual, i*sizeof(qual[i])); + + return 0; +} + +int rtl_siwessid(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *essid) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + char str[100]; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS)) + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if ((TRUE == priv->pshare->bDriverStopped) || (TRUE == priv->pshare->bSurpriseRemoved)) + return -ENETDOWN; +#endif + +#ifdef WIFI_WPAS_CLI + if (!memcmp(priv->pmib->dot11Bss.bssid, NULL_MAC_ADDR, MACADDRLEN)) + return 0; +#endif + + snprintf(str, sizeof(str), "ssid=%s", essid); + return set_mib(priv, str); +} + +int rtl_giwessid(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *essid) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + wrqu->essid.flags = 1; + wrqu->essid.length = SSID_LEN; + memcpy(essid, SSID, SSID_LEN); + + return 0; +} + +int rtl_siwrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + UINT32 rate = wrqu->bitrate.value, fixed = wrqu->bitrate.fixed; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS)) + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + //printk("rtl_siwrate::(rate = %d, fixed = %d)\n", rate, fixed); + /* rate = -1 => auto rate + rate = X, fixed = 1 => (fixed rate X) + */ + + if (rate == -1) + { + //Auto Rate + priv->pmib->dot11StationConfigEntry.autoRate = TRUE; + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + } + else + { + if (fixed) + { + unsigned int txRate = rate / 10000000; + int i, len; + unsigned char *rateset, *p; + rateset = AP_BSSRATE; + len = AP_BSSRATE_LEN; + + for(i=0,p=rateset; ipmib->dot11StationConfigEntry.autoRate = FALSE; + priv->pmib->dot11StationConfigEntry.fixedTxRate = *p; + return 0; + } + } + return -EOPNOTSUPP; + + } + else + { + // TODO: rate = X, fixed = 0 => (rates <= X) + return -EOPNOTSUPP; + } + } + + return 0; +} + +int rtl_giwrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + unsigned int txRate; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS)) + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + if (priv->pmib->dot11StationConfigEntry.autoRate) + txRate = find_rate(priv, NULL, 1, 0); + else + txRate = get_rate_from_bit_value(priv->pmib->dot11StationConfigEntry.fixedTxRate); + + //printk ("txRate = %d\n", txRate); + wrqu->bitrate.value = txRate * 1000000; + wrqu->bitrate.disabled = 0; + + return 0; +} + +#define MAX_RTS_THRESHOLD 2347 + +int rtl_siwrts(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + u16 val; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#ifndef WIFI_HAPD + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + if (wrqu->rts.disabled) + val = MAX_RTS_THRESHOLD; + else if (wrqu->rts.value < 0 || wrqu->rts.value > MAX_RTS_THRESHOLD) + return -EINVAL; + else if (wrqu->rts.value == 0) + val = MAX_RTS_THRESHOLD; + else + val = wrqu->rts.value; + + if (val != RTSTHRSLD) + RTSTHRSLD = val; + + return 0; +} + +int rtl_giwrts(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS)) + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + wrqu->rts.value = RTSTHRSLD; + wrqu->rts.disabled = (wrqu->rts.value == MAX_RTS_THRESHOLD); + wrqu->rts.fixed = 1; + + return 0; +} + +int rtl_siwfrag(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + u16 val; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS)) + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + if (wrqu->frag.disabled) + val = MAX_FRAG_THRESHOLD; + else if (wrqu->frag.value >= MIN_FRAG_THRESHOLD || wrqu->frag.value <= MAX_FRAG_THRESHOLD) + val = __cpu_to_le16(wrqu->frag.value & ~0x1); /* even numbers only */ + else if (wrqu->frag.value == 0) + val = MAX_FRAG_THRESHOLD; + else + return -EINVAL; + + FRAGTHRSLD = val; + + return 0; +} + +int rtl_giwfrag(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS)) + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + + wrqu->frag.value = FRAGTHRSLD; + wrqu->frag.disabled = (wrqu->frag.value == MAX_FRAG_THRESHOLD); + wrqu->frag.fixed = 1; + + return 0; +} + + +int rtl_siwretry(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + priv->pmib->dot11OperationEntry.dot11ShortRetryLimit = wrqu->retry.value; + + return 0; +} + + +int rtl_giwretry(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + wrqu->retry.value = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + wrqu->retry.fixed = 0; /* no auto select */ + wrqu->retry.flags |= (IW_RETRY_LIMIT |IW_RETRY_ON); + wrqu->retry.disabled = 0; + + return 0; +} + +int rtl_siwencode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *keybuf) +{ + u32 key, ret = 0; + u32 keyindex_provided; + int i; +// NDIS_802_11_WEP wep; +// NDIS_802_11_AUTHENTICATION_MODE authmode; + + struct iw_point *erq = &(wrqu->encoding); + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + printk("rtl_siwencode: erq->flags=0x%x erq->length=%d keybuf=%02x%02x%02x%02x%02x\n", erq->flags, erq->length, + keybuf[0],keybuf[1],keybuf[2],keybuf[3],keybuf[4]); + + if (erq->flags & IW_ENCODE_DISABLED) + { + printk("rtl_siwencode: EncryptionDisabled\n"); + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; //open system + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + goto exit; + } + + key = erq->flags & IW_ENCODE_INDEX; + + if (key) { + if (key > 4) + return -EINVAL; + key--; + keyindex_provided = 1; + } + else + { + keyindex_provided = 0; + key = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + printk("rtl_siwencode, key=%d\n", key); + } + + //set authentication mode + if (erq->flags & IW_ENCODE_OPEN) + { + printk("rtl_siwencode: IW_ENCODE_OPEN\n"); + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; //open system + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + } + else if (erq->flags & IW_ENCODE_RESTRICTED) + { + printk("rtl_siwencode: IW_ENCODE_RESTRICTED\n"); + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 1; //shared system + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + } + else + { + printk("rtl_siwencode: IW_ENCODE_OPEN\n"); + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; //open system + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + } + + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex = key; + + if (erq->length > 0) { + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = erq->length <= 5 ? _WEP_40_PRIVACY_ : _WEP_104_PRIVACY_; + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen = erq->length <= 5 ? 8 : 16; + } else { + + if (keyindex_provided == 1)// set key_id only, no given KeyMaterial(erq->length==0). + { + printk("rtl_siwencode: keyindex provided, keyid=%d, key_len=%d\n", key, erq->length); + + switch (priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen) + { + case 5: + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_40_PRIVACY_; + break; + case 13: + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_104_PRIVACY_; + break; + default: + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + break; + } + + goto exit; + } + } + +#ifdef WIFI_WPAS_CLI + memcpy(priv->pmib->dot11DefaultKeysTable.keytype[key].skey, keybuf, erq->length); + CamAddOneEntry(priv, priv->pmib->dot11Bss.bssid, key, + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm)<<2, + 0, priv->pmib->dot11DefaultKeysTable.keytype[key].skey); +#else + for (i=0; i<4; i++) { + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[i].skey[0], keybuf, erq->length); + } +#endif + +exit: + + return ret; +} + + +int rtl_giwencode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + struct iw_point *erq = &(wrqu->encoding); + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + +#if !(defined (WIFI_HAPD) || defined (WIFI_WPAS)) + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } +#endif + + if ((OPMODE & (WIFI_AP_STATE|WIFI_STATION_STATE|WIFI_ADHOC_STATE)) && + !priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm && + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_)) { + int key_len; + priv->pmib->dot11GroupKeysTable.dot11Privacy = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) + key_len = 5; + else + key_len = 13; + + // copy wep key + erq->flags = (priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex + 1) & IW_ENCODE_INDEX; + erq->length = key_len; + memcpy(key, &priv->pmib->dot11DefaultKeysTable.keytype[priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex].skey[0], key_len); + + if (priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm == 1) + erq->flags |= IW_ENCODE_RESTRICTED; /* XXX */ + else + erq->flags |= IW_ENCODE_OPEN; /* XXX */ + + erq->flags |= IW_ENCODE_ENABLED; /* XXX */ + } + else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _NO_PRIVACY_) { + erq->length = 0; + erq->flags = IW_ENCODE_DISABLED; + } + + return 0; +} + +int rtl_giwpower(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + //_adapter *padapter = netdev_priv(dev); + + wrqu->power.value = 0; + wrqu->power.fixed = 0; /* no auto select */ + wrqu->power.disabled = 1; + + return 0; +} + +#ifdef WIFI_WPAS_CLI +int rtl_siwscan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + struct iw_point *data = &wrqu->data; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if ((TRUE == priv->pshare->bDriverStopped) || (TRUE == priv->pshare->bSurpriseRemoved)) + return -ENETDOWN; +#endif + + // TODO: If traffic is busy, we may need to skip this scanning + if ( OPMODE & WIFI_ASOC_STATE ) { + printk("cliW: try scanning in association\n"); + goto ind_done; + } + if ( OPMODE & ( WIFI_AUTH_STATE1 | WIFI_AUTH_SUCCESS) ) { + printk("cliW: no scanning when connecting\n"); + goto ind_done; + } + + if (data && (data->flags & IW_SCAN_THIS_ESSID)) { + struct iw_scan_req* req = (struct iw_scan_req*)extra; + + if (req->essid_len) + { + priv->ss_ssidlen = req->essid_len; + if (priv->ss_ssidlen > 32) + priv->ss_ssidlen = 32; + + memset(priv->ss_ssid, 0, 32); + memcpy(priv->ss_ssid, req->essid, priv->ss_ssidlen); + + SSID2SCAN_LEN = (req->essid_len > 32) ? 32 : req->essid_len; + memcpy(SSID2SCAN, req->essid, SSID2SCAN_LEN); + + use_ap_scan(priv); + } + } else { + printk("cliW: wildcard ssid \n"); + priv->ss_ssidlen = 0; + use_ap_scan(priv); + } +done: + return 0; + +ind_done: + event_indicate_wpas(priv, NULL, WPAS_SCAN_DONE, NULL); + return 0; +} +#else // !WIFI_WPAS_CLI +int rtl_siwscan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + INT8 ret=-1; + RTL_PRIV *priv = GET_DEV_PRIV(dev); + unsigned long flags; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } + ret=rtl8192cd_ss_req(priv, (unsigned char *) &wrqu->data, 0); + if(0!=wrqu->data.length) + { + if(extra!=NULL && (!strcmp(extra,"rtl8192cd_ioctl")))//called from rtl8192cd_ioctl + { + #ifdef WIFI_WPAS //_Eric ?? + if (ioctl_copy_to_user((void *)wrqu->data.pointer, (void *)&ret, 1)) + memcpy(wrqu->data.pointer, &ret, 1); + #else + if (ioctl_copy_to_user((void *)wrqu->data.pointer, (void *)&ret, 1)) + return -1; + #endif + } + else //called from iwhandler. + { + #ifdef WIFI_WPAS //_Eric ?? + if (copy_to_user((void *)wrqu->data.pointer, (void *)&ret, 1)) + memcpy(data, &ret, 1); + #else + if (copy_to_user((void *)wrqu->data.pointer, (void *)&ret, 1)) + return -1; + #endif + + } + } + + //wait ss done + wait_event_interruptible_timeout(priv->ss_wait,(!priv->ss_req_ongoing),RTL_SECONDS_TO_JIFFIES(5)); + return 0; +} +#endif // WIFI_WPAS_CLI + +#ifdef WIFI_WPAS //_Eric ?? AP mode (HAPD) will attemp to scan or not ?? +int rtl_giwscan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + int i=0, j=0; + char * current_ev = extra; + char * previous_ev = extra; + char * end_buf; + char * current_val; +#ifndef IWEVGENIE + unsigned char idx; +#endif // IWEVGENIE // + struct iw_event iwe; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + //check if the interface is down + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if ((TRUE == priv->pshare->bDriverStopped) || (TRUE == priv->pshare->bSurpriseRemoved)) { + printk("cliw: driver shutdown now\n"); + return -ENETDOWN; + } +#endif + + if (priv->site_survey->count_backup== 0) + { + wrqu->data.length = 0; + return 0; + } + +#if WIRELESS_EXT >= 17 + if (wrqu->data.length > 0) + end_buf = extra + wrqu->data.length; + else + end_buf = extra + IW_SCAN_MAX_DATA; +#else + end_buf = extra + IW_SCAN_MAX_DATA; +#endif + memset(extra, 0, wrqu->data.length); + + for (i = 0; i < priv->site_survey->count_backup; i++) + { + if ((current_ev >= end_buf) || ( (wrqu->data.length - (current_ev - extra)) <= 200)) + { +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + // The first entry must be the MAC address + //MAC address + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, priv->site_survey->bss_backup[i].bssid, MACADDRLEN); + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //ESSID + //================================ + memset(&iwe, 0, sizeof(iwe)); + + //printk("ESSID %s %d\n",priv->site_survey->bss_backup[i].ssid, priv->site_survey->bss_backup[i].ssidlen); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = (priv->site_survey->bss_backup[i].ssidlen <= 32) ? priv->site_survey->bss_backup[i].ssidlen : 32; + iwe.u.data.flags = 1; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, (char *)priv->site_survey->bss_backup[i].ssid); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Network Type + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (priv->site_survey->bss_backup[i].bsstype & WIFI_ADHOC_STATE) + { + iwe.u.mode = IW_MODE_ADHOC; + } + else if (priv->site_survey->bss_backup[i].bsstype & WIFI_STATION_STATE) + { + iwe.u.mode = IW_MODE_INFRA; + } + else if (priv->site_survey->bss_backup[i].bsstype & WIFI_AP_STATE) + { + iwe.u.mode = IW_MODE_MASTER; + } + else + { + iwe.u.mode = IW_MODE_AUTO; + } + iwe.len = IW_EV_UINT_LEN; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Channel and Frequency + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + { + u8 ch = priv->site_survey->bss_backup[i].channel; + u32 m = 0; + + MAP_CHANNEL_ID_TO_KHZ(ch, m); + iwe.u.freq.m = m; + iwe.u.freq.e = 3; + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + //Add quality statistics + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + iwe.u.qual.level = priv->site_survey->bss_backup[i].rssi - 100; + iwe.u.qual.qual = priv->site_survey->bss_backup[i].sq; + iwe.u.qual.noise = 0; /* cliW */ + + // not sure about signal level and noise level, To Do: determin the SNR + //iwe.u.qual.noise = signal_todbm((u8)(100-priv->site_survey->bss[i].rssi)) -25; +// iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID; + iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID | IW_QUAL_DBM ; + + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + #define WLAN_CAPABILITY_PRIVACY (1<<4) + + // Encryption capability + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + if (priv->site_survey->bss_backup[i].capability & WLAN_CAPABILITY_PRIVACY) // if Privacy + iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (u8 *)&priv->pmib->dot11DefaultKeysTable.keytype[priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex].skey[0]); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + // support rate + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = 0; + iwe.u.bitrate.disabled = 0; + iwe.u.bitrate.value = 0; + current_val = current_ev + IW_EV_LCP_LEN; + + for (j=0; dot11_rate_table[j]; j++) + { + if (priv->site_survey->bss_backup[i].supportrate & (BIT(j))) + { + iwe.u.bitrate.value = dot11_rate_table[j]*500000; + current_val = IWE_STREAM_ADD_VALUE(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); + } + } + + if (priv->site_survey->bss_backup[i].network & WIRELESS_11N) + { + // TODO: Report MCS Rate + } + + /* remove fixed header if no rates were added */ + if ((current_val - current_ev) > IW_EV_LCP_LEN) + current_ev = current_val; + + + /* Add WPA/RSN IE */ +#if WIRELESS_EXT >= 18 + //WPAIE + //================================ + if(priv->site_survey->wpa_ie_backup[i].wpa_ie_len > 0){ + memset(&iwe, 0, sizeof(iwe)); + + iwe.cmd = IWEVGENIE; + iwe.u.data.length = priv->site_survey->wpa_ie_backup[i].wpa_ie_len; + iwe.u.data.flags = 1; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, (char *)priv->site_survey->wpa_ie_backup[i].data); + if (current_ev == previous_ev) { +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + } + + //RSNIE + //================================ + if(priv->site_survey->rsn_ie_backup[i].rsn_ie_len > 0) { + memset(&iwe, 0, sizeof(iwe)); + + iwe.cmd = IWEVGENIE; + iwe.u.data.length = priv->site_survey->rsn_ie_backup[i].rsn_ie_len; + iwe.u.data.flags = 1; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, (char *)priv->site_survey->rsn_ie_backup[i].data); + if (current_ev == previous_ev) { +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + } +#endif + + /* + Protocol: + it will show scanned AP's WirelessMode . + it might be + 802.11a + 802.11a/n + 802.11g/n + 802.11b/g/n + 802.11g + 802.11b/g + */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWNAME; + + { + struct bss_desc *pBss=&priv->site_survey->bss_backup[i]; + //int rateCnt=0; + + if (pBss->network==WIRELESS_11B) + strcpy(iwe.u.name, "802.11b"); + else if (pBss->network==WIRELESS_11G) + strcpy(iwe.u.name, "802.11g"); + else if (pBss->network==(WIRELESS_11G|WIRELESS_11B)) + strcpy(iwe.u.name, "802.11b/g"); + else if (pBss->network==(WIRELESS_11N)) + strcpy(iwe.u.name, "802.11n"); + else if (pBss->network==(WIRELESS_11G|WIRELESS_11N)) + strcpy(iwe.u.name, "802.11g/n"); + else if (pBss->network==(WIRELESS_11G|WIRELESS_11B | WIRELESS_11N)) + strcpy(iwe.u.name, "802.11b/g/n"); + else if(pBss->network== WIRELESS_11A) + strcpy(iwe.u.name, "802.11a"); + else + strcpy(iwe.u.name, "---"); + } + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + +#ifdef WIFI_SIMPLE_CONFIG + //WPSIE + //================================ + if (priv->site_survey->bss_backup[i].t_stamp[1] & BIT(8)) { + memset(&iwe, 0, sizeof(iwe)); + + iwe.cmd = IWEVGENIE; + iwe.u.data.length = priv->site_survey->wscie[i].wps_ie_len; + iwe.u.data.flags = 1; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, + end_buf, &iwe, (char *)priv->site_survey->wscie[i].data); + + if (current_ev == previous_ev) { +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + } +#endif // WIFI_SIMPLE_CONFIG + } + + wrqu->data.length = current_ev - extra; + + return 0; +} + +#else +int rtl_giwscan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + int i=0; + char * current_ev = extra; + char * previous_ev = extra; + char * end_buf; + //char * current_val; +#ifndef IWEVGENIE + unsigned char idx; +#endif // IWEVGENIE // + struct iw_event iwe; + + if (priv == NULL) + { + /* if 1st open fail, pAd will be free; + So the net_dev->priv will be NULL in 2rd open */ + return -ENETDOWN; + } + + //check if the interface is down + if (!netif_running(priv->dev)) + { + //printk("\nFail: interface not opened\n"); + return -ENETDOWN; + } + + if (priv->site_survey->count == 0) + { + wrqu->data.length = 0; + return 0; + } + +#if WIRELESS_EXT >= 17 + if (wrqu->data.length > 0) + end_buf = extra + wrqu->data.length; + else + end_buf = extra + IW_SCAN_MAX_DATA; +#else + end_buf = extra + IW_SCAN_MAX_DATA; +#endif + + for (i = 0; i < priv->site_survey->count; i++) + { + if (current_ev >= end_buf) + { +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + //MAC address + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, &priv->site_survey->bss[i].bssid, MACADDRLEN); + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + /* + Protocol: + it will show scanned AP's WirelessMode . + it might be + 802.11a + 802.11a/n + 802.11g/n + 802.11b/g/n + 802.11g + 802.11b/g + */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWNAME; + + { + struct bss_desc *pBss=&priv->site_survey->bss[i]; + //int rateCnt=0; + + if (pBss->network==WIRELESS_11B) + strcpy(iwe.u.name, "802.11b"); + else if (pBss->network==WIRELESS_11G) + strcpy(iwe.u.name, "802.11g"); + else if (pBss->network==(WIRELESS_11G|WIRELESS_11B)) + strcpy(iwe.u.name, "802.11b/g"); + else if (pBss->network==(WIRELESS_11N)) + strcpy(iwe.u.name, "802.11n"); + else if (pBss->network==(WIRELESS_11G|WIRELESS_11N)) + strcpy(iwe.u.name, "802.11g/n"); + else if (pBss->network==(WIRELESS_11G|WIRELESS_11B | WIRELESS_11N)) + strcpy(iwe.u.name, "802.11b/g/n"); + else if(pBss->network== WIRELESS_11A) + strcpy(iwe.u.name, "802.11a"); + else + strcpy(iwe.u.name, "---"); + } + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_ADDR_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //ESSID + //================================ + memset(&iwe, 0, sizeof(iwe)); + + //printk("ESSID %s %d\n",priv->site_survey->bss[i].ssid, priv->site_survey->bss[i].ssidlen); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = priv->site_survey->bss[i].ssidlen; + iwe.u.data.flags = 1; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf, &iwe, (char *)priv->site_survey->bss[i].ssid); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Network Type + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (priv->site_survey->bss[i].bsstype & WIFI_ADHOC_STATE) + { + iwe.u.mode = IW_MODE_ADHOC; + } + else if (priv->site_survey->bss[i].bsstype & WIFI_STATION_STATE) + { + iwe.u.mode = IW_MODE_INFRA; + } + else if (priv->site_survey->bss[i].bsstype & WIFI_AP_STATE) + { + iwe.u.mode = IW_MODE_MASTER; + } + else + { + iwe.u.mode = IW_MODE_AUTO; + } + iwe.len = IW_EV_UINT_LEN; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + + //Channel and Frequency + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + { + u8 ch = priv->site_survey->bss[i].channel; + //u32 m = 0; + //MAP_CHANNEL_ID_TO_KHZ(ch, m); + //iwe.u.freq.m = m * 100; + //iwe.u.freq.e = 1; + iwe.u.freq.m = ch; + iwe.u.freq.e = 0; + iwe.u.freq.i = 0; + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev,end_buf, &iwe, IW_EV_FREQ_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif + } + + //Add quality statistics + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + iwe.u.qual.qual = priv->site_survey->bss[i].rssi; + + // not sure about signal level and noise level + //iwe.u.qual.level = (u8) priv->site_survey->bss[i].sq; + //iwe.u.qual.noise = signal_todbm((u8)(100-priv->site_survey->bss[i].rssi)) -25; + iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID; + + current_ev = IWE_STREAM_ADD_EVENT(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif +#if 0 + //Encyption key + //================================ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + if (priv->site_survey->bss[i].capability & 0x0010) + iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + + previous_ev = current_ev; + current_ev = IWE_STREAM_ADD_POINT(info, current_ev, end_buf,&iwe, (u8 *)priv->pmib->dot11DefaultKeysTable.keytype[priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex].skey[0]); + if (current_ev == previous_ev) +#if WIRELESS_EXT >= 17 + return -E2BIG; +#else + break; +#endif +#endif + } + + wrqu->data.length = current_ev - extra; + return 0; +} +#endif + +#ifdef WIFI_WPAS_CLI +const u1Byte WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; +const u1Byte WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 }; +const u1Byte WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 }; +const u1Byte WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 }; +const u1Byte WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 }; +const u1Byte WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 }; + +const u1Byte RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 }; +const u1Byte RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 }; +const u1Byte RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 }; +//const u1Byte RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 }; +const u1Byte RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 }; +const u1Byte RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 }; + +unsigned char rtw_get_wpa_cipher_suite(u1Byte *s) +{ + unsigned char cipher = 0; + + if (memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == 0) + cipher = _NO_PRIVACY_; + else if (memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == 0) + cipher = _WEP_40_PRIVACY_; + else if (memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == 0) + cipher = _TKIP_PRIVACY_; + else if (memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == 0) + cipher = _CCMP_PRIVACY_; + else if (memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == 0) + cipher = _WEP_104_PRIVACY_; + + return cipher; +} + +unsigned char rtw_get_wpa2_cipher_suite(u1Byte *s) +{ + unsigned char cipher = 0; + + if (memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == 0) + cipher = _NO_PRIVACY_; + else if (memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == 0) + cipher = _WEP_40_PRIVACY_; + else if (memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == 0) + cipher = _TKIP_PRIVACY_; + else if (memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == 0) + cipher = _CCMP_PRIVACY_; + else if (memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == 0) + cipher = _WEP_104_PRIVACY_; + + return cipher; +} + +int rtw_parse_wpa_ie(u1Byte* wpa_ie, int wpa_ie_len, unsigned char *group_cipher, unsigned char *pairwise_cipher) +{ + int i, ret=0; + int left, count; + pu1Byte pos; + + if (wpa_ie_len <= 0) { + /* No WPA IE - fail silently */ + return 1; + } + + if ((*wpa_ie != WPA_IE_ID) || (*(wpa_ie+1) != (u1Byte)(wpa_ie_len - 2)) || + (memcmp(wpa_ie+2, WPA_OUI_TYPE, WPA_SELECTOR_LEN) != 0) ) + { + return 1; + } + + pos = wpa_ie; + + pos += 8; + left = wpa_ie_len - 8; + + + //group_cipher + if (left >= WPA_SELECTOR_LEN) + { + *group_cipher = rtw_get_wpa_cipher_suite(pos); + + pos += WPA_SELECTOR_LEN; + left -= WPA_SELECTOR_LEN; + } + else if (left > 0) + { + DEBUG_INFO("%s: ie length mismatch, %u too much", __FUNCTION__, left); + return 1; + } + + + //pairwise_cipher + if (left >= 2) + { + count = le16_to_cpu(*(u2Byte*)pos);// + pos += 2; + left -= 2; + + if (count == 0 || left < count * WPA_SELECTOR_LEN) { + DEBUG_INFO("%s: ie count botch (pairwise), " + "count %u left %u", __FUNCTION__, count, left); + return 1; + } + + for (i = 0; i < count; i++) + { + *pairwise_cipher = rtw_get_wpa_cipher_suite(pos); + + pos += WPA_SELECTOR_LEN; + left -= WPA_SELECTOR_LEN; + } + + } + else if (left == 1) + { + DEBUG_INFO("%s: ie too short (for key mgmt)", __FUNCTION__); + return 1; + } + + + return ret; + +} + +int rtw_parse_wpa2_ie(u1Byte* rsn_ie, int rsn_ie_len, unsigned char *group_cipher, unsigned char *pairwise_cipher) +{ + int i, ret=0; + int left, count; + u1Byte *pos; + + if (rsn_ie_len <= 0) + { + /* No RSN IE - fail silently */ + return 1; + } + + + if ((*rsn_ie!= WPA2_IE_ID) || (*(rsn_ie+1) != (u1Byte)(rsn_ie_len - 2))) + { + return 1; + } + + pos = rsn_ie; + pos += 4; + left = rsn_ie_len - 4; + + //group_cipher + if (left >= RSN_SELECTOR_LEN) { + + *group_cipher = rtw_get_wpa2_cipher_suite(pos); + + pos += RSN_SELECTOR_LEN; + left -= RSN_SELECTOR_LEN; + + } else if (left > 0) { + DEBUG_INFO("%s: ie length mismatch, %u too much", __FUNCTION__, left); + return 1; + } + + //pairwise_cipher + if (left >= 2) + { + count = le16_to_cpu(*(u16*)pos);// + pos += 2; + left -= 2; + + if (count == 0 || left < count * RSN_SELECTOR_LEN) { + DEBUG_INFO("%s: ie count botch (pairwise), " + "count %u left %u", __FUNCTION__, count, left); + return 1; + } + + for (i = 0; i < count; i++) + { + *pairwise_cipher = rtw_get_wpa2_cipher_suite(pos); + + pos += RSN_SELECTOR_LEN; + left -= RSN_SELECTOR_LEN; + } + + } + else if (left == 1) + { + DEBUG_INFO("%s: ie too short (for key mgmt)", __FUNCTION__); + + return 1; + } + + return ret; + +} + +void rtw_set_wpa_cipher_bit(struct rtl8192cd_priv *priv, unsigned char enc_type) +{ + switch (enc_type) { + case _WEP_40_PRIVACY_: + priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(0); + break; + + case _TKIP_PRIVACY_: + priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(1); + break; + + case _WRAP_PRIVACY_: + priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(2); + break; + + case _CCMP_PRIVACY_: + priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(3); + break; + + case _WEP_104_PRIVACY_: + priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(4); + break; + + default: + break; + } +} + + +int rtl_siwgenie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + u1Byte *buf=NULL; + unsigned char group_cipher = 0, pairwise_cipher = 0; + int ret = 0; + u2Byte ielen; + WPA_GLOBAL_INFO *pGblInfo = priv->wpa_global_info; + + DEBUG_INFO("%s:IE_Len=%d\n", __FUNCTION__, wrqu->data.length); + + ielen = wrqu->data.length; + if((ielen > MAX_WPA_IE_LEN) || (extra == NULL)){ + priv->pmib->wscEntry.wsc_enable = 0; + priv->pmib->wscEntry.assoc_ielen = 0; + if(extra == NULL) + return ret; + else + return -EINVAL; + } + + printk("rtl_siwgenie\n"); + + if ( ielen == 0 ) { + priv->pmib->dot11RsnIE.rsnielen = 0; + } else { +#if 0 + if (wrqu->data.length < sizeof(DOT11_RSN_IE_HEADER)) + { + DEBUG_ERR("Invalid IE Length(%d) or Null data pointer\n", wrqu->data.length); + return -EINVAL; + } +#endif + buf = kzalloc(ielen, GFP_KERNEL); + if (buf == NULL){ + return -ENOMEM; + } + + memcpy(buf, extra, ielen); + if (rtw_parse_wpa_ie(buf, ielen, &group_cipher, &pairwise_cipher) == 0) + { + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = pairwise_cipher; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1; + priv->pmib->dot1180211AuthEntry.dot11WPACipher |= 1 << (pairwise_cipher-1); + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + priv->pmib->dot11GroupKeysTable.dot11Privacy = group_cipher; + pGblInfo->MulticastCipher = group_cipher ; + pGblInfo->UnicastCipher[0] = pairwise_cipher ; + + BUG_ON(sizeof(priv->pmib->dot11RsnIE.rsnie) < ielen); + memcpy(priv->pmib->dot11RsnIE.rsnie, &buf[0], ielen); + priv->pmib->dot11RsnIE.rsnielen = ielen; + } + else if (rtw_parse_wpa2_ie(buf, ielen, &group_cipher, &pairwise_cipher) == 0) + { + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = pairwise_cipher; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA2; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1; + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher |= 1 << (pairwise_cipher-1); + priv->pmib->dot11GroupKeysTable.dot11Privacy = group_cipher; + pGblInfo->MulticastCipher = group_cipher ; + pGblInfo->UnicastCipherWPA2[0] = pairwise_cipher; + + BUG_ON(sizeof(priv->pmib->dot11RsnIE.rsnie) < ielen); + memcpy(priv->pmib->dot11RsnIE.rsnie, &buf[0], ielen); + priv->pmib->dot11RsnIE.rsnielen = ielen; + } + + {//set wps_ie + int cnt = 0; + unsigned char wps_ie_found=0; + unsigned char eid, wps_oui[4]={0x0,0x50,0xf2,0x04}; + + while( cnt < ielen ) + { + eid = buf[cnt]; + + if((eid==VENDOR_SPECIFIC_IE)&&(memcmp(&buf[cnt+2], wps_oui, 4)==0)) + { + DEBUG_INFO("%s: SET WPS_IE\n",__FUNCTION__); + priv->pmib->wscEntry.wsc_enable = 1; + priv->pmib->wscEntry.assoc_ielen = ( (buf[cnt+1]+2) < (256)) ? (buf[cnt+1]+2):(256); + memset(priv->pmib->wscEntry.assoc_ie, 0x0, 256); + memcpy(priv->pmib->wscEntry.assoc_ie, &buf[cnt], priv->pmib->wscEntry.assoc_ielen); + wps_ie_found = 1; + break; + } + cnt += buf[cnt+1]+2; //goto next + } + + if (!wps_ie_found) + { + priv->pmib->wscEntry.wsc_enable = 0; + priv->pmib->wscEntry.assoc_ielen = 0; + } + } + + kfree(buf); + } + + return ret; +} + + +int rtl_siwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + struct iw_param *param = (struct iw_param*)&(wrqu->param); + int value = param->value; + int ret = 0; + + printk("rtl_siwauth : cmd:%d val:%d\n", (param->flags & IW_AUTH_INDEX), param->value); + + switch (param->flags & IW_AUTH_INDEX) { + + case IW_AUTH_WPA_VERSION: +#ifdef CONFIG_RTL_WAPI_SUPPORT + priv->pmib->wapiInfo.wapiType = wapiDisable; + if(value == IW_AUTH_WAPI_VERSION_1) + { + priv->pmib->wapiInfo.wapiType = wapiTypePSK; + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == 0; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + } else +#endif + if (value == IW_AUTH_WPA_VERSION_DISABLED) { + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + } + else if (value == IW_AUTH_WPA_VERSION_WPA) + { + priv->pmib->wapiInfo.wapiType = wapiDisable; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA; + } + else if (value == IW_AUTH_WPA_VERSION_WPA2) + { + priv->pmib->wapiInfo.wapiType = wapiDisable; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA2; + } + break; + + case IW_AUTH_CIPHER_PAIRWISE: + DEBUG_INFO("set_auth(IW_AUTH_CIPHER_PAIRWISE) value=%d\n", param->value); + if (param->value & IW_AUTH_CIPHER_WEP40) + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_40_PRIVACY_; + else if (param->value & IW_AUTH_CIPHER_WEP104) + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_104_PRIVACY_; + else if (param->value & IW_AUTH_CIPHER_TKIP) + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _TKIP_PRIVACY_; + else if (param->value & IW_AUTH_CIPHER_CCMP) + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + else if (param->value & IW_AUTH_CIPHER_NONE) + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + else { + return -EINVAL; + } + break; + + case IW_AUTH_CIPHER_GROUP: + DEBUG_INFO("set_auth(IW_AUTH_CIPHER_GROUP) value=%d\n", value); + + if (value & IW_AUTH_CIPHER_WEP40) + priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_WEP40; + else if (value & IW_AUTH_CIPHER_WEP104) + priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_WEP104; + else if (value & IW_AUTH_CIPHER_TKIP) + priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_TKIP; + else if (value & IW_AUTH_CIPHER_CCMP) + priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_CCMP; + else if (value & IW_AUTH_CIPHER_NONE) + priv->pmib->dot11GroupKeysTable.dot11Privacy = DOT11_ENC_NONE; + else { + return -EINVAL; + } + + break; + + case IW_AUTH_KEY_MGMT: +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType != wapiDisable) + { + if(value == IW_AUTH_KEY_MGMT_WAPI_PSK) + priv->pmib->wapiInfo.wapiType = wapiTypePSK; + else + priv->pmib->wapiInfo.wapiType = wapiTypeCert; + DEBUG_INFO("%s: IW_AUTH_KEY_MGMT wapiType %d \n", __FUNCTION__, priv->pmib->wapiInfo.wapiType); + } else +#endif +#if 0 + if (value & IW_AUTH_KEY_MGMT_802_1X) + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1; + else + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; +#endif + break; + + case IW_AUTH_TKIP_COUNTERMEASURES: + // TODO: TKIP countermeasures + break; + + case IW_AUTH_DROP_UNENCRYPTED: + break; + + case IW_AUTH_80211_AUTH_ALG: + if ((param->value & IW_AUTH_ALG_SHARED_KEY)&&(param->value & IW_AUTH_ALG_OPEN_SYSTEM)) + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; // Auto + else if(param->value & IW_AUTH_ALG_OPEN_SYSTEM) + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; // Open + else if (param->value & IW_AUTH_ALG_SHARED_KEY) + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 1; // Shared + else if (param->value & IW_AUTH_ALG_LEAP) + { + DEBUG_WARN("%s: wpa_set_auth_algs, AUTH_ALG_LEAP\n", __FUNCTION__); + } + else + ret = -EINVAL; + break; + + case IW_AUTH_WPA_ENABLED: + if ( param->value == 0 ) { + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0; + priv->pmib->dot11GroupKeysTable.dot11Privacy = 0; + + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + priv->pmib->dot11RsnIE.rsnielen = 0; + } + + break; + + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + //ieee->ieee802_1x = param->value; + break; + + case IW_AUTH_PRIVACY_INVOKED: + //ieee->privacy_invoked = param->value; + break; + +#ifdef CONFIG_RTL_WAPI_SUPPORT + case IW_AUTH_WAPI_ENABLED: + break; +#endif + + default: + return -EOPNOTSUPP; + } + return ret; +} + + +int rtl_giwauth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + struct iw_param *param = (struct iw_param*)&(wrqu->param); + int ret = 0; + + + DEBUG_INFO("%s: get_auth: flags=0x%x authmode=%d\n", __FUNCTION__, wrq->flags, authmode); + param->value = 0; + + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType != wapiDisable) + { + param->value |= IW_AUTH_WAPI_VERSION_1; + } +#endif + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) + { + param->value |= IW_AUTH_WPA_VERSION_WPA; + } + + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2) + { + param->value |= IW_AUTH_WPA_VERSION_WPA2; + } + break; + + case IW_AUTH_CIPHER_PAIRWISE: + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) + { + param->value |= IW_AUTH_CIPHER_WEP40; + } + else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) + { + param->value |= IW_AUTH_CIPHER_WEP104; + } + else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) + { + param->value |= IW_AUTH_CIPHER_TKIP; + } + else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_) + { + param->value |= IW_AUTH_CIPHER_CCMP; + } + else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _NO_PRIVACY_) + { + param->value |= IW_AUTH_CIPHER_NONE; + } + break; + + case IW_AUTH_KEY_MGMT: +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType != wapiDisable) + { + if (priv->pmib->wapiInfo.wapiType == wapiTypePSK) + param->value = IW_AUTH_KEY_MGMT_WAPI_PSK; + else + param->value = IW_AUTH_KEY_MGMT_WAPI_CERT; + } else +#endif + if (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm) + { + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) + param->value = IW_AUTH_KEY_MGMT_PSK; + else + param->value = IW_AUTH_KEY_MGMT_802_1X; + } + break; +// TODO:==> + case IW_AUTH_80211_AUTH_ALG: + switch (priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm) { + case 0: + param->value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + + case 1: + param->value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + + default: + DEBUG_ERR("%s: invalid auth_alg(%d)\n", __FUNCTION__,priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm); + param->value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + } + break; + + case IW_AUTH_WPA_ENABLED: + // TODO: + break; + + default: + ret = -EOPNOTSUPP; + } + DEBUG_INFO("%s: flags=0x%x value=%d ret=%d\n", __FUNCTION__, param->flags, param->value, ret); + + return ret; +} + + +int rtl_siwencodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + s4Byte alg = ext->alg; + u1Byte EncAlgorithm = DOT11_ENC_NONE; + s4Byte KeyIndex; + u4Byte KeyLength=0; + BOOLEAN IsDefaultKey = FALSE; + pu1Byte KeyMaterial = ext->key; + BOOLEAN IsGroupKey = FALSE; +// u8Byte KeyRSC; + int ret=0; + DOT11_SET_KEY Set_Key; + struct stat_info *pstat; + + memset((char *)&Set_Key, 0, sizeof(Set_Key)); + + if (encoding->flags & IW_ENCODE_DISABLED) { + alg = IW_ENCODE_ALG_NONE; + } + + /* Get Key Index and convet to our own defined key index */ + KeyIndex = (encoding->flags & IW_ENCODE_INDEX) - 1; + KeyLength = ext->key_len; + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + IsDefaultKey = TRUE; + } + + //if ((ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) || (IS_BCAST(ext->addr.sa_data))) { + if ( (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) ) { + IsGroupKey = TRUE; + } + + printk("siwencode alg:%x ext_flags:%x/ len:%u\n", (u4Byte)alg, ext->ext_flags, KeyLength); + + DEBUG_INFO("%s: \n", __FUNCTION__); + DEBUG_INFO("KeyIndex = %d\n", KeyIndex); + DEBUG_INFO("KeyLength = %u\n", KeyLength); + //DEBUG_INFO("KeyMaterial = %32s\n", KeyMaterial); + DEBUG_INFO("IsDefaultKey = %d\n", IsDefaultKey); + DEBUG_INFO("IsGroupKey = %d\n", IsGroupKey); + +#ifdef SDIO_AP_OFFLOAD + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_COMAPI); +#endif + + switch (alg) { + case IW_ENCODE_ALG_NONE: + /* Clear all keys */ + EncAlgorithm = DOT11_ENC_NONE; + break; + + case IW_ENCODE_ALG_WEP: + if ((KeyIndex < 0) || (KeyIndex >= 4)) + { + ret = -EINVAL; + goto set_encodeext_end; + } + + if(KeyLength == 5){ + EncAlgorithm = DOT11_ENC_WEP40; + } + else if(KeyLength == 13) { + EncAlgorithm = DOT11_ENC_WEP104; + } + else + { + ret = -EINVAL; + goto set_encodeext_end; + } + + break; + + case IW_ENCODE_ALG_TKIP: + EncAlgorithm = DOT11_ENC_TKIP; + // Check key length for TKIP. + if(KeyLength != 32) { + if (IsGroupKey && (KeyLength == 5 || KeyLength == 13)) { + // 5 = WEP40 13 = WEP104 16 = CKIP + if(KeyLength == 5) { + EncAlgorithm = DOT11_ENC_WEP40; + } else { + EncAlgorithm = DOT11_ENC_WEP104; + } + DEBUG_WARN("%s: Check key length 5 or 13 for Mix-mode WEP.\n", __FUNCTION__); + } else { + DEBUG_ERR("TKIP KeyLength:%u != 32\n", KeyLength); + ret = -EINVAL; + goto set_encodeext_end; + } + } + + break; + + case IW_ENCODE_ALG_CCMP: + EncAlgorithm = DOT11_ENC_CCMP; + if(KeyLength != 16) { + // For our supplicant, EAPPkt9x.vxd, cannot differentiate TKIP and AES case. + if(KeyLength == 32) + KeyLength = 16; + } + + if((KeyLength != 16) && (KeyLength != 32)) { + if (IsGroupKey && (KeyLength == 5 || KeyLength == 13)) { + // 5 = WEP40 13 = WEP104 16 = CKIP + if(KeyLength == 5) { + EncAlgorithm = DOT11_ENC_WEP40; + } else { + EncAlgorithm = DOT11_ENC_WEP104; + } + DEBUG_WARN("%s: Check key length 5 or 13 for Mix-mode WEP.\n", __FUNCTION__); + } else { + DEBUG_ERR("AES_CCM KeyLength:%u != 16\n", KeyLength); + ret = -EINVAL; + goto set_encodeext_end; + } + } + break; + + default: + ret = -EINVAL; + goto set_encodeext_end; + } + + if (KeyLength > 0) { + if ((EncAlgorithm == DOT11_ENC_WEP40) || (EncAlgorithm == DOT11_ENC_WEP104)) { + memcpy(priv->pmib->dot11DefaultKeysTable.keytype[KeyIndex].skey, KeyMaterial, KeyLength); + } + + if (IsDefaultKey) { + if ((EncAlgorithm == DOT11_ENC_WEP40) || (EncAlgorithm == DOT11_ENC_WEP104)) { + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = KeyLength <= 5 ? _WEP_40_PRIVACY_ : _WEP_104_PRIVACY_; + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen = KeyLength <= 5 ? 8 : 16; + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex = KeyIndex; + + // don't setup PTK CAM because BSSID is unavailable before first join. + // PTK CAM will be set on set_keymapping_wep when association success. + if (IsGroupKey) { + struct Dot11EncryptKey *pEncryptKey; + + priv->pmib->dot11GroupKeysTable.dot11Privacy = EncAlgorithm; + priv->pmib->dot11GroupKeysTable.keyid = KeyIndex; + + pEncryptKey = &priv->pmib->dot11GroupKeysTable.dot11EncryptKey; + pEncryptKey->dot11TTKeyLen = KeyLength <= 5 ? 5 : 13; + pEncryptKey->dot11TMicKeyLen = 0; + memset(pEncryptKey->dot11TTKey.skey, 0, sizeof(pEncryptKey->dot11TTKey.skey)); + memcpy(pEncryptKey->dot11TTKey.skey, KeyMaterial, pEncryptKey->dot11TTKeyLen); + } + goto set_encodeext_end; + } + } + + if (IsGroupKey) { + /* cliW: not set group key in wep key */ + if ((EncAlgorithm == DOT11_ENC_WEP40) || (EncAlgorithm == DOT11_ENC_WEP104)) { + goto set_encodeext_end; + } + /* cliW: fix group key for wpa_supplicant rekey use toogle index */ + if ((EncAlgorithm == DOT11_ENC_TKIP) || (EncAlgorithm == DOT11_ENC_CCMP)) + KeyIndex = 1; + + priv->pmib->dot11GroupKeysTable.dot11Privacy = EncAlgorithm; + priv->pmib->dot11GroupKeysTable.keyid = KeyIndex; + } + + /* cliW test supplicant using [ len : tx : rx ] key format */ + if ( EncAlgorithm == DOT11_ENC_TKIP ) { + char tmp[8]; +#if 1 + WPA_GLOBAL_INFO *pGblInfo = priv->wpa_global_info; + + if ( IsDefaultKey ) { + pGblInfo->GkeyReady = TRUE; + pGblInfo->GN = KeyIndex; + } + pGblInfo->MulticastCipher = _TKIP_PRIVACY_; +#endif + memcpy(tmp, KeyMaterial+16, 8); + memcpy(KeyMaterial+16, KeyMaterial+24, 8); + memcpy(KeyMaterial+24, tmp, 8); + } + + memcpy(Set_Key.MACAddr, ext->addr.sa_data, MACADDRLEN); + if (IsDefaultKey) + Set_Key.KeyType = DOT11_KeyType_Pairwise; + else + Set_Key.KeyType = (IsGroupKey ? DOT11_KeyType_Group : DOT11_KeyType_Pairwise); + + Set_Key.EncType = EncAlgorithm; + Set_Key.KeyIndex = KeyIndex; + Set_Key.KeyLen = KeyLength; + ret = DOT11_Process_Set_Key(dev, NULL, &Set_Key, KeyMaterial); + + if ((EncAlgorithm == DOT11_ENC_TKIP) || (EncAlgorithm == DOT11_ENC_CCMP)) + { + pstat = get_stainfo(priv, ext->addr.sa_data); + if ((pstat != NULL) && (pstat->state & WIFI_ASOC_STATE)) + pstat->ieee8021x_ctrlport = 1; + } + } + else if (EncAlgorithm == DOT11_ENC_NONE) + { + // Remove Key + DOT11_DELETE_KEY Delete_Key; + struct iw_point wrq; + + if ((EncAlgorithm == DOT11_ENC_WEP40) || (EncAlgorithm == DOT11_ENC_WEP104)) + { + memset(priv->pmib->dot11DefaultKeysTable.keytype[KeyIndex].skey, 0, 16); + } + + if (IsDefaultKey) + { + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen = 0; + } + + wrq.pointer = (caddr_t)&Delete_Key; + wrq.length = sizeof(DOT11_DELETE_KEY); + + memset(&Delete_Key, 0, sizeof(Delete_Key)); + Delete_Key.EventId = DOT11_EVENT_DELETE_KEY; + Delete_Key.IsMoreEvent = FALSE; + + Delete_Key.KeyType = (IsGroupKey ? DOT11_KeyType_Group : DOT11_KeyType_Pairwise); + memcpy(Delete_Key.MACAddr, ext->addr.sa_data, MACADDRLEN); + + // check root intf is up before deleting key to avoid stuck in CAM_read_mac_config + if (IS_DRV_OPEN(GET_ROOT(priv))) + ret = DOT11_Process_Delete_Key(priv->dev, &wrq); + } + +set_encodeext_end: +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_COMAPI); +#endif + + return ret; +} + +int rtl_giwencodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + s4Byte key_index; + s4Byte ret = 0; + s4Byte max_key_len; + char *pkey=NULL; +// char keybuf[32]; + int keylen=0; + + DEBUG_INFO("rtwlan_ioctl: rtioctl_get_encodeext: \n"); + + max_key_len = encoding->length - sizeof(struct iw_encode_ext); + if (max_key_len < 0) + return -EINVAL; + key_index = (encoding->flags & IW_ENCODE_INDEX) - 1; + + memset(ext, 0, sizeof(struct iw_encode_ext)); + + switch (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) { + case _WEP_40_PRIVACY_: + case _WEP_104_PRIVACY_: + ext->alg = IW_ENCODE_ALG_WEP; + encoding->flags |= IW_ENCODE_ENABLED; + pkey = priv->pmib->dot11DefaultKeysTable.keytype[key_index].skey; + keylen = 16; + break; + + case _TKIP_PRIVACY_: + ext->alg = IW_ENCODE_ALG_TKIP; + encoding->flags |= IW_ENCODE_ENABLED; + // TODO: get key + break; + + case _CCMP_PRIVACY_: + ext->alg = IW_ENCODE_ALG_CCMP; + encoding->flags |= IW_ENCODE_ENABLED; + // TODO: get key + break; + + case _NO_PRIVACY_: + default: + ext->alg = IW_ENCODE_ALG_NONE; + encoding->flags |= IW_ENCODE_NOKEY; + break; + } + + if (!(encoding->flags & IW_ENCODE_NOKEY)) { + if (max_key_len < keylen) { + ret = -E2BIG; + goto out; + } + if (pkey) + memcpy (ext->key, pkey, keylen); + } + + out: + return ret; +} + +int rtl_siwpmkid(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + unsigned char j,blInserted = _FALSE; + int ret=0; + +#if 0 + struct iw_pmksa* pPMK = ( struct iw_pmksa* ) extra; + unsigned char strZeroMacAddress[ ETH_ALEN ] = { 0x00 }; + unsigned char strIssueBssid[ ETH_ALEN ] = { 0x00 }; + + /* + struct iw_pmksa + { + __u32 cmd; + struct sockaddr bssid; + __u8 pmkid[IW_PMKID_LEN]; //IW_PMKID_LEN=16 + } + There are the BSSID information in the bssid.sa_data array. + If cmd is IW_PMKSA_FLUSH, it means the wpa_suppplicant wants to clear all the PMKID information. + If cmd is IW_PMKSA_ADD, it means the wpa_supplicant wants to add a PMKID/BSSID to driver. + If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to remove a PMKID/BSSID from driver. + */ + + memcpy( strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN); + if ( pPMK->cmd == IW_PMKSA_ADD ) + { + DEBUG_INFO( "%s: IW_PMKSA_ADD!\n", __FUNCTION__ ); + if (!memcmp( strIssueBssid, strZeroMacAddress, ETH_ALEN )) + { + return (-EINVAL); + } + + blInserted = _FALSE; + + //overwrite PMKID + for(j=0 ; jPMKIDList[j].Bssid, strIssueBssid, ETH_ALEN) ) + { // BSSID is matched, the same AP => rewrite with new PMKID. + + DEBUG_INFO( "%s: BSSID exists in the PMKList.\n", __FUNCTION__ ); + + memcpy( priv->PMKIDList[j].PMKID, pPMK->pmkid, IW_PMKID_LEN); + priv->PMKIDList[ j ].bUsed = _TRUE; + priv->PMKIDIndex = j+1; + blInserted = _TRUE; + break; + } + } + + if(!blInserted) + { + // Find a new entry + DEBUG_INFO( "[%s] Use the new entry index = %d for this PMKID.\n", __FUNCTION__, + priv->PMKIDIndex ); + + memcpy(priv->PMKIDList[priv->PMKIDIndex].Bssid, strIssueBssid, ETH_ALEN); + memcpy(priv->PMKIDList[priv->PMKIDIndex].PMKID, pPMK->pmkid, IW_PMKID_LEN); + + priv->PMKIDList[priv->PMKIDIndex ].bUsed = _TRUE; + priv->PMKIDIndex++ ; + if(priv->PMKIDIndex == NUM_PMKID_CACHE) + { + priv->PMKIDIndex = 0; + } + } + } + else if ( pPMK->cmd == IW_PMKSA_REMOVE ) + { + DEBUG_INFO( "[%s] IW_PMKSA_REMOVE!\n", __FUNCTION__ ); + for(j=0 ; jPMKIDList[j].Bssid, strIssueBssid, ETH_ALEN)) + { // BSSID is matched, the same AP => Remove this PMKID information and reset it. + memset( priv->PMKIDList[ j ].Bssid, 0x00, ETH_ALEN ); + priv->PMKIDList[ j ].bUsed = _FALSE; + break; + } + } + } + else if ( pPMK->cmd == IW_PMKSA_FLUSH ) + { + DEBUG_INFO( "[%s] IW_PMKSA_FLUSH!\n", __FUNCTION__ ); + memset( &priv->PMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE ); + priv->PMKIDIndex = 0; + } +#endif + return( ret ); +} +#endif // WIFI_WPAS_CLI +#endif // CONFIG_RTL_COMAPI_WLTOOLS + +#ifdef CONFIG_RTL_COMAPI_CFGFILE + +#define CFG_FILE_PATH "/etc/Wireless/RTL8192CD.dat" + +void del_mib_list(struct net_device *dev); +int CfgFileSetMib(struct net_device *dev, char *buf); + +int CfgFileProc(struct net_device *dev) +{ + //RTL_PRIV *priv = dev->priv; + unsigned char *mem_ptr; + int ret = 0; + + printk("-------> Set MIB from " CFG_FILE_PATH "\n"); + if((mem_ptr = (unsigned char *)kmalloc(MAX_CONFIG_FILE_SIZE, GFP_ATOMIC)) == NULL) { + printk("%s: not enough memory\n", __FUNCTION__); + return -1; + } + + memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE); + + ret = CfgFileRead(dev, mem_ptr); + + if (ret < 0) + { + printk("%s: ReadCfgFile failed (%d)\n", __FUNCTION__, ret); + goto proc_exit; + } + + //printk("%s\n", mem_ptr); + + del_mib_list(dev); + + CfgFileSetMib(dev, mem_ptr); + + printk("<------- Set MIB from " CFG_FILE_PATH " Success\n"); + +proc_exit: + kfree(mem_ptr); + return ret; + +} + +int CfgFileRead(struct net_device *dev, char *buf) +{ + //RTL_PRIV *priv = dev->priv; + struct file *fp; + mm_segment_t oldfs; + //size_t len; + + //int read_bytes = 0; + int ret = 0; + + oldfs = get_fs(); + set_fs(get_ds()); + fp = filp_open(CFG_FILE_PATH, O_RDONLY, 0); + if(IS_ERR(fp)) { + ret = PTR_ERR(fp); + printk("Fail to open configuration file. (%d)\n", ret); + goto err_exit; + } + + if (!(fp->f_op && fp->f_op->read)) { + printk("Fail to support file ops: read\n"); + ret = -1; + goto err_close; + } + + if ((ret = fp->f_op->read(fp, buf, MAX_CONFIG_FILE_SIZE, &fp->f_pos))< 0){ + printk("Fail to read file. (%d)\n", ret); + goto err_close; + } + +err_close: + filp_close(fp, NULL); +err_exit: + set_fs(oldfs); + return ret; + +} + +static int rewrite_line (unsigned char **dst, unsigned char **src) +{ + int cnt=0; + char *s = *src; + char *d = *dst; + char *loc=NULL, *vl_s=NULL, *vl_e=NULL; + unsigned char quoted = 0; + + //printk("src = %s(%d)\n", *src, strlen(*src)); + loc=strchr(s, '"'); + if (loc) { + unsigned int i = strlen(*src); + vl_s=loc; + while (i>0){ + char *t = (char *)((unsigned long)s+i-1); + if (*t=='"' && t > vl_s ){ + vl_e = t; + quoted = 1; + break; + } + i--; + } + } + + while (*s) { + u8 noop = 0; + if (quoted ==1 && (vl_s < s && s < vl_e)) + noop = 1; + + if ( noop == 0 ) { + if ((*s=='\r') || (*s=='\n') || (*s=='#') || (*s=='\0')) + break; + if ((*s == '\t')||(*s == ' ')||(*s == '"')){ + s++; + continue; + } + } + + *d = *s; + s++; + d++; + cnt++; + + } + *d = '\0'; + //printk(" dst = %s\n", *dst); + return cnt; +} + + +int CfgFileSetMib(struct net_device *dev, char *buf) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + unsigned char *line_head, *next_head; + unsigned char *cmd_buf, *mibstr, *valstr, *mibstart; + //struct mib_cfg_func *tmp_mibcfg; + int ret = 0; +#ifdef VENDOR_PARAM_COMPATIBLE + int arg_num = sizeof(RTL_SUPPORT_MIBCFG)/sizeof(struct mib_cfg_func); +#endif //VENDOR_PARAM_COMPATIBLE + + if((cmd_buf = (unsigned char *)kmalloc(MAX_PARAM_BUF_SIZE, GFP_ATOMIC)) == NULL) { + printk("%s(%d): not enough memory\n", __FUNCTION__, __LINE__); + return -1; + } + + if((mibstr = (unsigned char *)kmalloc(20, GFP_ATOMIC)) == NULL) { + printk("%s(%d): not enough memory\n", __FUNCTION__, __LINE__); + return -1; + } + + if((valstr = (unsigned char *)kmalloc(MAX_PARAM_BUF_SIZE, GFP_ATOMIC)) == NULL) { + printk("%s(%d): not enough memory\n", __FUNCTION__, __LINE__); + return -1; + } + + next_head = buf; + + do { + char *loc; + int len = 0, miblen = 0, vallen = 0; + //int i=0; + + memset(cmd_buf, 0, MAX_PARAM_BUF_SIZE); + memset(mibstr, 0, 20); + memset(valstr, 0, MAX_PARAM_BUF_SIZE); + + line_head = next_head; + next_head = get_line(&line_head); + if (line_head == NULL) + break; + + if (line_head[0] == '#') + continue; + + len = rewrite_line(&cmd_buf, &line_head); + //printk("%s (%d)\n", cmd_buf, len); + +#ifdef VENDOR_PARAM_COMPATIBLE + /* To compatible with other vendor's parameters, each parameter must have its own process function - chris*/ + loc = strchr(mibstart, '='); + miblen = (u32)loc - (u32)mibstart; + vallen = len - miblen -1; + if (vallen>0) { + for (i=0; i>>>>>>> cmd=%s , %s, %c \n",cmd_buf, dev->name, cmd_buf[strlen(dev->name)]); + if (!strncmp(dev->name, cmd_buf, strlen(dev->name))&&(cmd_buf[strlen(dev->name)]!='-')) { + mibstart = cmd_buf + strlen(dev->name)+1; + } else + continue; + + loc = strchr(mibstart, '='); + miblen = (u32)loc - (u32)mibstart; + vallen = len - (strlen(dev->name)+1) - (miblen+1); + + if (vallen>0) { + + ret = set_mib(priv, mibstart); + if (ret < 0) { + strncpy(mibstr, mibstart, miblen); + strncpy(valstr, (char*)((u32)loc+1), vallen); + //printk("(%s) = (%s) (%d)\n", mibstr, valstr, vallen); + printk("CFGFILE set_mib \"%s\" failed \n", mibstart); + //return -1; + } + +#endif // VENDOR_PARAM_COMPATIBLE + } + + } while (1); + + kfree(cmd_buf); + kfree(mibstr); + kfree(valstr); + + return ret; +} + +void del_mib_list(struct net_device *dev) +{ + RTL_PRIV *priv = GET_DEV_PRIV(dev); + + + if (priv->pmib) { +#ifdef WDS + priv->pmib->dot11WdsInfo.wdsNum = 0; +#endif + priv->pmib->dot11StationConfigEntry.dot11AclNum=0; + } + +} + +#endif //CONFIG_RTL_COMAPI_CFGFILE + + + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_comapi.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_comapi.h new file mode 100755 index 000000000..1c3e95c97 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_comapi.h @@ -0,0 +1,113 @@ +/* + * Header file for API-compatible handling routines + * + * + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + + +#ifndef _8192CD_COMAPI_H_ +#define _8192CD_COMAPI_H_ + +#include "./8192cd.h" + +typedef struct rtl8192cd_priv RTL_PRIV; +#define MAX_CONFIG_FILE_SIZE (64*1024) // for 8192, added to 64k +#define MAX_PARAM_BUF_SIZE (1024) // for 8192, added to 20k + +#ifdef CONFIG_RTL_COMAPI_CFGFILE + +/* Following is a example for PARAMETERs completely compatible to other vendors' + * configure file - chris 2010/02/01 */ +#undef VENDOR_PARAM_COMPATIBLE +#ifdef VENDOR_PARAM_COMPATIBLE + +int Set_CountryRegion_Proc (RTL_PRIV *priv, char *arg); +int Set_CountryRegionABand_Proc (RTL_PRIV *priv, char *arg); +int Set_SSID_Proc (RTL_PRIV *priv, char *arg); + + +struct mib_cfg_func{ + char name[20]; /*mib name*/ + int (*set_proc)(RTL_PRIV *priv, char *arg); +}; + +static struct mib_cfg_func *TMP_MIBCFG, RTL_SUPPORT_MIBCFG[] = { + {"CountryRegion", Set_CountryRegion_Proc}, + {"CountryRegionABand", Set_CountryRegionABand_Proc}, + {"SSID", Set_SSID_Proc} +}; + +int Set_CountryRegion_Proc(RTL_PRIV *priv, char *arg) +{ + int val = simple_strtol(arg, 0 ,10); + if (DOMAIN_FCC <= val && val <= DOMAIN_MAX ) { + priv->pmib->dot11StationConfigEntry.dot11RegDomain = val; + return TRUE; + } else { + printk("contry region out of range [%d-%d]\n", DOMAIN_FCC, DOMAIN_MAX); + return FALSE; + } +} + +int Set_CountryRegionABand_Proc(RTL_PRIV *priv, char *arg) +{ + int val = simple_strtol(arg, 0 ,10); + priv->pmib->dot11StationConfigEntry.dot11RegDomainABand = val; + return TRUE; +} + +int Set_SSID_Proc(RTL_PRIV *priv, char *arg) +{ + strcpy(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, arg); + return TRUE; +} + +#else +extern int set_mib(struct rtl8192cd_priv *priv, unsigned char *data); + +#endif //VENDOR_PARAM_COMPATIBLE + +#endif //CONFIG_RTL_COMAPI_CFGFILE + +#ifdef WIFI_WPAS_CLI + +#define WPA_IE_ID 0xdd +#define WPA2_IE_ID 0x30 +#define RSN_HEADER_LEN 4 +#define WPA_SELECTOR_LEN 4 +#define RSN_SELECTOR_LEN 4 +#define VENDOR_SPECIFIC_IE 221 + +#ifdef CONFIG_RTL_WAPI_SUPPORT +#ifndef IW_AUTH_WAPI_VERSION_1 +#define IW_AUTH_WAPI_VERSION_1 0x00000008 +#endif + +#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK +#define IW_AUTH_KEY_MGMT_WAPI_PSK 0x04 +#endif + +#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT +#define IW_AUTH_KEY_MGMT_WAPI_CERT 0x08 +#endif + +#ifndef IW_AUTH_WAPI_ENABLED +#define IW_AUTH_WAPI_ENABLED 0x20 +#endif + +#ifndef IW_ENCODE_ALG_SM4 +#define IW_ENCODE_ALG_SM4 0x20 +#endif +#endif // CONFIG_RTL_WAPI_SUPPORT +#endif // WIFI_WPAS_CLI + +#endif // _8192CD_COMAPI_H_ + + + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_debug.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_debug.h new file mode 100755 index 000000000..9b5486509 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_debug.h @@ -0,0 +1,386 @@ +/* + * Debug headler file. It defines various print out method + * + * $Id: 8192cd_debug.h,v 1.2.4.2 2010/12/01 13:38:00 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_DEBUG_H_ +#define _8192CD_DEBUG_H_ + +#if 1 +//#define _MESH_MOD_ +#define printMac(da) printk("%02X:%02X:%02X:%02X:%02X:%02X\n", 0xff&*(da), 0xff&*(da+1), 0xff&*(da+2), 0xff&*(da+3), 0xff&*(da+4), 0xff&*(da+5)); + +#define printMac4(pframe) {\ + printMac(GetAddr1Ptr(pframe));\ + printMac(GetAddr2Ptr(pframe));\ + printMac(GetAddr3Ptr(pframe));\ + printMac(GetAddr4Ptr(pframe));\ +} + + +#define printHex(d,n) {int i; \ + for(i=0; i\n", name, (char *)__FUNCTION__); +#define __DEBUG_INFO(name, fmt, args...) \ + if (rtl8192cd_debug_info&_MODULE_DEFINE) \ + printk("%s-"_MODULE_NAME"-info: " fmt, name, ## args); +#define __DEBUG_WARN(name, fmt, args...) \ + if (rtl8192cd_debug_warn&_MODULE_DEFINE) \ + printk("%s-"_MODULE_NAME"-warn: " fmt, name, ## args); + +#define DEBUG_ERR(fmt, args...) __DEBUG_ERR(priv->dev->name, fmt, ## args) +#define DEBUG_INFO(fmt, args...) __DEBUG_INFO(priv->dev->name, fmt, ## args) +#define DEBUG_TRACE __DEBUG_TRACE(priv->dev->name) +#define DEBUG_WARN(fmt, args...) __DEBUG_WARN(priv->dev->name, fmt, ## args) + +#define _DEBUG_ERR(fmt, args...) __DEBUG_ERR("wlan", fmt, ## args) +#define _DEBUG_INFO(fmt, args...) __DEBUG_INFO("wlan", fmt, ## args) +#define _DEBUG_TRACE __DEBUG_TRACE("wlan") +#define _DEBUG_WARN(fmt, args...) __DEBUG_WARN("wlan", fmt, ## args) + +#define DBFENTER printk("----->%s\n", (char *)__FUNCTION__) +#define DBFEXIT printk("%s----->\n", (char *)__FUNCTION__) +#define PRINT_INFO(fmt, args...) printk(fmt, ## args) +#endif +#endif // __GNUC__ + +/* +#ifdef __DRAYTEK_OS__ +#define __FUNCTION__ "" + +#define DEBUG_ERR Print +#define DEBUG_INFO Print +#define DEBUG_TRACE +#define DEBUG_WARN Print + +#define _DEBUG_ERR DEBUG_ERR +#define _DEBUG_INFO DEBUG_INFO +#define _DEBUG_TRACE DEBUG_TRACE +#define _DEBUG_WARN DEBUG_WARN + +#define DBFENTER +#define DBFEXIT +#define PRINT_INFO Print +#endif // __DRAYTEK_OS__ + +#ifdef GREEN_HILL +#define DEBUG_ERR printk +#define DEBUG_INFO printk +#define DEBUG_TRACE printk +#define DEBUG_WARN printk + +#define _DEBUG_ERR printk +#define _DEBUG_INFO printk +#define _DEBUG_TRACE printk +#define _DEBUG_WARN printk + +#define DBFENTER printk +#define DBFEXIT printk +#define PRINT_INFO printk +#endif // GREEN_HILL +*/ + + +#else // not _DEBUG_RTL8192CD_ + + +#ifdef __GNUC__ +#define DEBUG_ERR(fmt, args...) {} +#define DEBUG_INFO(fmt, args...) {} +#define DEBUG_TRACE {} +#define DEBUG_WARN(fmt, args...) {} + +#define _DEBUG_ERR(fmt, args...) {} +#define _DEBUG_INFO(fmt, args...) {} +#define _DEBUG_TRACE {} +#define _DEBUG_WARN(fmt, args...) {} + +#define DBFENTER {} +#define DBFEXIT {} +#define PRINT_INFO(fmt, args...) {} +#endif // __GNUC__ + +/* +#ifdef __DRAYTEK_OS__ +#define __FUNCTION__ "" + +#define DEBUG_ERR +#define DEBUG_INFO +#define DEBUG_TRACE +#define DEBUG_WARN + +#define _DEBUG_ERR +#define _DEBUG_INFO +#define _DEBUG_TRACE +#define _DEBUG_WARN + +#define DBFENTER +#define DBFEXIT +#define PRINT_INFO +#endif // __DRAYTEK_OS__ + +#ifdef GREEN_HILL +#define DEBUG_ERR(fmt, args...) {} +#define DEBUG_INFO(fmt, args...) {} +#define DEBUG_TRACE {} +#define DEBUG_WARN(fmt, args...) {} + +#define _DEBUG_ERR(fmt, args...) {} +#define _DEBUG_INFO(fmt, args...) {} +#define _DEBUG_TRACE {} +#define _DEBUG_WARN(fmt, args...) {} + +#define DBFENTER {} +#define DBFEXIT {} +#define PRINT_INFO(fmt, args...) {} +#endif // GREEN_HILL +*/ + + +#endif // _DEBUG_RTL8192CD_ +#endif // _8192CD_DEBUG_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dfs.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dfs.c new file mode 100755 index 000000000..fa250836e --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dfs.c @@ -0,0 +1,1380 @@ +/* + * Handling routines for DFS (Dynamic Frequency Selection) functions + * + * $Id: 8192cd_dfs.c,v 1.1 2012/05/04 12:49:07 jimmylin Exp $ + * + * Copyright (c) 2012 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_DFS_C_ + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" +#ifdef RTK_NL80211 +#include "8192cd_cfg80211.h" +#endif + +#ifdef DFS + + +#define DFS_VERSION "2.0.5" + + +void rtl8192cd_dfs_chk_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (timer_pending(&priv->dfs_chk_timer)){ + del_timer_sync(&priv->dfs_chk_timer); + } + + if (GET_CHIP_VER(priv) == VERSION_8192D) + PHY_SetBBReg(priv, 0xcdc, BIT(8)|BIT(9), 1); + PRINT_INFO("DFS CP END.\n"); +} + +void set_CHXX_timer(struct rtl8192cd_priv *priv, unsigned int channel) +{ + switch(channel) { + case 52: + mod_timer(&priv->ch52_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 56: + mod_timer(&priv->ch56_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 60: + mod_timer(&priv->ch60_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 64: + mod_timer(&priv->ch64_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 100: + mod_timer(&priv->ch100_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 104: + mod_timer(&priv->ch104_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 108: + mod_timer(&priv->ch108_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 112: + mod_timer(&priv->ch112_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 116: + mod_timer(&priv->ch116_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 120: + mod_timer(&priv->ch120_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 124: + mod_timer(&priv->ch124_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 128: + mod_timer(&priv->ch128_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 132: + mod_timer(&priv->ch132_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 136: + mod_timer(&priv->ch136_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 140: + mod_timer(&priv->ch140_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + case 144: + mod_timer(&priv->ch144_timer, jiffies + NONE_OCCUPANCY_PERIOD); + break; + default: + DEBUG_ERR("DFS_timer: Channel match none!\n"); + break; + } +} + +void rtl8192cd_DFS_TXPAUSE_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned int which_channel; + + printk("rtl8192cd_DFS_TXPAUSE_timer\n"); + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (priv->available_chnl_num != 0) { + if (timer_pending(&priv->DFS_TXPAUSE_timer)) + del_timer_sync(&priv->DFS_TXPAUSE_timer); + + printk("rtl8192cd_DFS_TXPAUSE_timer PATH2\n"); +#if defined(UNIVERSAL_REPEATER) + if (!under_apmode_repeater(priv)) +#endif + { + + /* select a channel */ + which_channel = DFS_SelectChannel(priv); + + priv->pshare->dfsSwitchChannel = which_channel; + + if (priv->pshare->dfsSwitchChannel == 0) { + panic_printk("It should not run to here\n"); + return; + } + else + priv->pmib->dot11DFSEntry.DFS_detected = 1; + panic_printk("rtl8192cd_DFS_TXPAUSE_timer,dfsSwitchChannel=%d\n",priv->pshare->dfsSwitchChannel); +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) + priv->pshare->dfsSwitchChCountDown = 6; + else +#endif + priv->pshare->dfsSwitchChCountDown = 5; + } + + if (priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod >= priv->pshare->dfsSwitchChCountDown) + priv->pshare->dfsSwitchChCountDown = priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod+1; + + } + else { + printk("rtl8192cd_DFS_TXPAUSE_timer PATH3\n"); + mod_timer(&priv->DFS_TXPAUSE_timer, jiffies + DFS_TXPAUSE_TO); + } + + +} + +void rtl8192cd_DFS_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned int radar_type = 0; /* 0 for short, 1 for long */ + unsigned int dfs_chk = 0; + unsigned long throughput = 0; + int j; + int tp_th = ((priv->pshare->is_40m_bw)?45:20); +#ifdef SMP_SYNC + unsigned long flags; +#endif + + SMP_LOCK(flags); + if (!(priv->drv_state & DRV_STATE_OPEN)) { + SMP_UNLOCK(flags); + return; + } + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) + goto exit_timer; +#endif + throughput = priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage; + +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + for (j=0; jpvap_priv[j])) { + throughput += priv->pvap_priv[j]->ext_stats.tx_avarage+priv->pvap_priv[j]->ext_stats.rx_avarage; + } + } + } +#endif + + if (throughput>>17>tp_th) { + if (GET_CHIP_VER(priv) == VERSION_8192D){ + dfs_chk = 1; + PHY_SetBBReg(priv, 0xcdc, BIT(8)|BIT(9), 0); + } + } else { + dfs_chk = 0; + if (GET_CHIP_VER(priv) == VERSION_8192D) + PHY_SetBBReg(priv, 0xcdc, BIT(8)|BIT(9), 1); + } + + if (!(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI)) + { + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (PHY_QueryBBReg(priv, 0xcf8, BIT(31))) { + radar_type++; + priv->pmib->dot11DFSEntry.DFS_detected = 1; + } + } + else if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + if (priv->pshare->rf_ft_var.dfs_det_off == 1) { + if (PHY_QueryBBReg(priv, 0xf98, BIT(19))) { + radar_type++; + priv->pmib->dot11DFSEntry.DFS_detected = 1; + + } + } + } + } + + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (PHY_QueryBBReg(priv, 0xcf8, BIT(23))) + priv->pmib->dot11DFSEntry.DFS_detected = 1; + } + else if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + if (priv->pshare->rf_ft_var.dfs_det_off == 1) { + if (PHY_QueryBBReg(priv, 0xf98, BIT(17))) + priv->pmib->dot11DFSEntry.DFS_detected = 1; + } + } + + + + /* + * DFS debug mode for logo test + */ + if (!priv->pmib->dot11DFSEntry.disable_DFS && priv->pshare->rf_ft_var.dfsdbgmode + && priv->pmib->dot11DFSEntry.DFS_detected) { + if ((jiffies - priv->pshare->rf_ft_var.dfsrctime)>RTL_SECONDS_TO_JIFFIES(10)) + priv->pshare->rf_ft_var.dfsdbgcnt = 1; + else + priv->pshare->rf_ft_var.dfsdbgcnt++; + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (priv->pshare->rf_ft_var.dfs_det_print1) + panic_printk("[%d] DFS dbg mode, Radar is detected as %x %08x (%d)!\n", priv->pshare->rf_ft_var.dfsdbgcnt, + radar_type, PHY_QueryBBReg(priv, 0xcf4, bMaskDWord), (unsigned int)RTL_JIFFIES_TO_MILISECONDS(jiffies)); + } + else if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + if (priv->pshare->rf_ft_var.dfs_det_print1) + panic_printk("[%d] DFS dbg mode, Radar is detected as %x %08x (%d)!\n", priv->pshare->rf_ft_var.dfsdbgcnt, + radar_type, PHY_QueryBBReg(priv, 0xf98, 0xffffffff), (unsigned int)RTL_JIFFIES_TO_MILISECONDS(jiffies)); + RTL_W32(0x920, RTL_R32(0x920) | (BIT(24) | BIT(25) | BIT(28))); + RTL_W32(0x920, RTL_R32(0x920) & ~(BIT(24) | BIT(25) | BIT(28))); + } + priv->pshare->rf_ft_var.dfsrctime = jiffies; + priv->pmib->dot11DFSEntry.DFS_detected = 0; + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, 0xc84, BIT(25), 0); + PHY_SetBBReg(priv, 0xc84, BIT(25), 1); + } + goto exit_timer; + } + + + if (!priv->pmib->dot11DFSEntry.disable_DFS && priv->pmib->dot11DFSEntry.DFS_detected) { + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PRINT_INFO("Radar is detected as %x %08x (%d)!\n", + radar_type, PHY_QueryBBReg(priv, 0xcf4, bMaskDWord), (unsigned int)RTL_JIFFIES_TO_MILISECONDS(jiffies)); + } + else if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + PRINT_INFO("Radar is detected as %x %08x (%d)!\n", + radar_type, PHY_QueryBBReg(priv, 0xf98, 0xffffffff), (unsigned int)RTL_JIFFIES_TO_MILISECONDS(jiffies)); + } + + if (timer_pending(&priv->dfs_chk_timer)) { + del_timer(&priv->dfs_chk_timer); + if (GET_CHIP_VER(priv) == VERSION_8192D) + PHY_SetBBReg(priv, 0xcdc, BIT(8)|BIT(9), 1); + PRINT_INFO("DFS CP2. Switch channel!\n"); + } else { + if (dfs_chk){ + // reset dfs flag and counter + priv->pmib->dot11DFSEntry.DFS_detected = 0; + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, 0xc84, BIT(25), 0); + PHY_SetBBReg(priv, 0xc84, BIT(25), 1); + } + + PRINT_INFO("DFS CP1.\n"); + + init_timer(&priv->dfs_chk_timer); + priv->dfs_chk_timer.data = (unsigned long) priv; + priv->dfs_chk_timer.function = rtl8192cd_dfs_chk_timer; + + mod_timer(&priv->dfs_chk_timer, jiffies + RTL_SECONDS_TO_JIFFIES(300)); + + goto exit_timer; + } + } + + priv->pmib->dot11DFSEntry.disable_tx = 1; + + if (timer_pending(&priv->ch_avail_chk_timer)) { + del_timer(&priv->ch_avail_chk_timer); + RTL_W8(TXPAUSE, 0xff); + } + else + RTL_W8(TXPAUSE, 0xf); /* disable transmitter */ +#if !defined(RTK_NL80211) + //For OpwenWRT SDK, do not consider block channel list + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_80 && + priv->pmib->dot11RFEntry.band5GSelected == PHY_BAND_5G_3) { + int i, channel; + channel = priv->pmib->dot11RFEntry.dot11channel; + + if ((channel >= 104) && (channel <= 112)) + channel = 100; + else if ((channel >= 120) && (channel <= 128)) + channel = 116; + else if ((channel >= 136) && (channel <= 144)) + channel = 132; + + for(i=0;i<4;i++) { + set_CHXX_timer(priv, channel+i*4); + } + } + else { + set_CHXX_timer(priv,priv->pmib->dot11RFEntry.dot11channel); + } + + /* add the channel in the blocked-channel list */ + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_80 && + priv->pmib->dot11RFEntry.band5GSelected == PHY_BAND_5G_3) { + int i, channel; + channel = priv->pmib->dot11RFEntry.dot11channel; + + if ((channel >= 104) && (channel <= 112)) + channel = 100; + else if ((channel >= 120) && (channel <= 128)) + channel = 116; + else if ((channel >= 136) && (channel <= 144)) + channel = 132; + + for (i=0;i<4;i++) { + if (RemoveChannel(priv, priv->available_chnl, &priv->available_chnl_num, channel+i*4)) + InsertChannel(priv->NOP_chnl, &priv->NOP_chnl_num, channel+i*4); +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && (RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, channel+i*4)) ) + InsertChannel(priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, channel+i*4); +#endif + } + } + else { + int j; + InsertChannel(priv->NOP_chnl, &priv->NOP_chnl_num, priv->pmib->dot11RFEntry.dot11channel); + RemoveChannel(priv, priv->available_chnl, &priv->available_chnl_num, priv->pmib->dot11RFEntry.dot11channel); +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))){ + RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, priv->pmib->dot11RFEntry.dot11channel); + InsertChannel(priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, priv->pmib->dot11RFEntry.dot11channel); + } +#endif + } +#endif + if (timer_pending(&priv->DFS_timer)) + del_timer(&priv->DFS_timer); + +#if !defined(RTK_NL80211) + //For OpenWRT, do not select another channel automatically + /* select a channel */ + priv->pshare->dfsSwitchChannel = DFS_SelectChannel(priv); + if(priv->pshare->dfsSwitchChannel == 0) { + priv->pmib->dot11DFSEntry.DFS_detected = 0; + + if (priv->pmib->dot11RFEntry.band5GSelected == PHY_BAND_5G_3) { + // when band 2 is selected, AP does not come back to band2 + // even when NOP (NONE_OCCUPANCY_PERIOD) timer is expired. + RTL_W8(TXPAUSE, 0xff);// after cac, still has to pause if channel is run out + mod_timer(&priv->DFS_TXPAUSE_timer, jiffies + DFS_TXPAUSE_TO); + } + } +#else + //Clear disable_tx here becoz turnkey do it at DFS_SelectChannel() + priv->pmib->dot11DFSEntry.disable_tx = 0; +#endif + +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) + priv->pshare->dfsSwitchChCountDown = 6; + else +#endif + priv->pshare->dfsSwitchChCountDown = 5; + + + if (priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod >= priv->pshare->dfsSwitchChCountDown) + priv->pshare->dfsSwitchChCountDown = priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod+1; + +#if defined(RTK_NL80211) + event_indicate_cfg80211(priv, NULL, CFG80211_RADAR_DETECTED, NULL); +#endif + + SMP_UNLOCK(flags); + return; + } + +exit_timer: + mod_timer(&priv->DFS_timer, jiffies + DFS_TO); + SMP_UNLOCK(flags); +} + + +#ifdef CLIENT_MODE +void rtl8192cd_dfs_cntdwn_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; +#ifdef SMP_SYNC + unsigned long flags; +#endif + + SMP_LOCK(flags); + if (!(priv->drv_state & DRV_STATE_OPEN)) { + SMP_UNLOCK(flags); + return; + } + + DEBUG_INFO("rtl8192cd_dfs_cntdwn_timer timeout!\n"); + + priv->pshare->dfsSwCh_ongoing = 0; + SMP_UNLOCK(flags); +} +#endif + +void rtl8192cd_ch_avail_chk_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; +#ifdef SMP_SYNC + unsigned long flags; +#endif + + SMP_LOCK(flags); + if (!(priv->drv_state & DRV_STATE_OPEN)) { + SMP_UNLOCK(flags); + return; + } + + priv->pmib->dot11DFSEntry.disable_tx = 0; + +if (GET_CHIP_VER(priv) == VERSION_8192D || GET_CHIP_VER(priv) == VERSION_8881A || GET_CHIP_VER(priv) == VERSION_8812E || (GET_CHIP_VER(priv) == VERSION_8814A)) { + if (GET_CHIP_VER(priv) == VERSION_8881A){ + PHY_SetBBReg(priv, 0xcb0, 0x000000f0, 4); + } + if (priv->pshare->rf_ft_var.dfsdelayiqk) + PHY_IQCalibrate(priv); + if (GET_CHIP_VER(priv) == VERSION_8881A){ + PHY_SetBBReg(priv, 0xcb0, 0x000000f0, 5); + } + } + +#ifdef DPK_92D + if (GET_CHIP_VER(priv) == VERSION_8192D){ + if (priv->pshare->rf_ft_var.dfsdelayiqk && priv->pshare->rf_ft_var.dpk_on) + PHY_DPCalibrate(priv); + } +#endif + + if (GET_CHIP_VER(priv) == VERSION_8192D) + RTL_W16(PCIE_CTRL_REG, RTL_R16(PCIE_CTRL_REG) & (~BCNQSTOP)); + else + RTL_W8(TXPAUSE, 0); + + SMP_UNLOCK(flags); + if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI){ + if((priv->pmib->dot11RFEntry.dot11channel >= 120) && + (priv->pmib->dot11RFEntry.dot11channel <= 132)){ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c17acdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c17ecdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a480); + } + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x0fa21a20); + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0f69204); + priv->ch_120_132_CAC_end = 1; + } + } + priv->pmib->dot11DFSEntry.CAC_ss_counter = 3; + panic_printk("Transmitter is enabled!\n"); +#if defined(RTK_NL80211) + event_indicate_cfg80211(priv, NULL, CFG80211_RADAR_CAC_FINISHED, NULL); +#endif +} + + +void rtl8192cd_ch52_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + //still block channel 52 if in adhoc mode in Japan + if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) || + (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK3)) && + (OPMODE & WIFI_ADHOC_STATE)) + return; + + //remove the channel from NOP_chnl[4] and place it in available_chnl[32] + if (RemoveChannel(priv,priv->NOP_chnl, &priv->NOP_chnl_num, 52)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 52); + DEBUG_INFO("Channel 52 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 52)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 52); + } +#endif +} + +void rtl8192cd_ch56_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) || + (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK3)) && + (OPMODE & WIFI_ADHOC_STATE)) + return; + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 56)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 56); + DEBUG_INFO("Channel 56 is released!\n"); +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 56)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 56); + } +#endif + } +} + +void rtl8192cd_ch60_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) || + (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK3)) && + (OPMODE & WIFI_ADHOC_STATE)) + return; + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 60)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 60); + DEBUG_INFO("Channel 60 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 60)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 60); + } +#endif +} + +void rtl8192cd_ch64_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) || + (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK3)) && + (OPMODE & WIFI_ADHOC_STATE)) + return; + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 64)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 64); + DEBUG_INFO("Channel 64 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 64)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 64); + } +#endif +} + +void rtl8192cd_ch100_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 100)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 100); + DEBUG_INFO("Channel 100 is released!\n"); +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 100)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 100); + } +#endif + } +} + +void rtl8192cd_ch104_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 104)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 104); + DEBUG_INFO("Channel 104 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 104)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 104); + } +#endif +} + +void rtl8192cd_ch108_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 108)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 108); + DEBUG_INFO("Channel 108 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 108)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 108); + } +#endif +} + +void rtl8192cd_ch112_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 112)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 112); + DEBUG_INFO("Channel 112 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 112)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 112); + } +#endif +} + +void rtl8192cd_ch116_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 116)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 116); + DEBUG_INFO("Channel 116 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 116)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 116); + } +#endif +} + +void rtl8192cd_ch120_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 120)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 120); + DEBUG_INFO("Channel 120 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 120)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 120); + } +#endif +} + +void rtl8192cd_ch124_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 124)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 124); + DEBUG_INFO("Channel 124 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 124)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 124); + } +#endif +} + +void rtl8192cd_ch128_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 128)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 128); + DEBUG_INFO("Channel 128 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 128)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 128); + } +#endif +} + +void rtl8192cd_ch132_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 132)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 132); + DEBUG_INFO("Channel 132 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 132)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 132); + } +#endif +} + +void rtl8192cd_ch136_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 136)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 136); + DEBUG_INFO("Channel 136 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 136)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 136); + } +#endif +} + +void rtl8192cd_ch140_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 140)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 140); + DEBUG_INFO("Channel 140 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 140)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 140); + } +#endif +} + +void rtl8192cd_ch144_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 144)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->available_chnl, &priv->available_chnl_num, 144); + DEBUG_INFO("Channel 144 is released!\n"); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && RemoveChannel(priv->pvxd_priv, priv->pvxd_priv->NOP_chnl, &priv->pvxd_priv->NOP_chnl_num, 144)) { + if (priv->pvxd_priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + InsertChannel(priv->pvxd_priv->available_chnl, &priv->pvxd_priv->available_chnl_num, 144); +} +#endif +} + +unsigned int DFS_SelectChannel(struct rtl8192cd_priv *priv) +{ + unsigned int random; + unsigned int num, random_base, which_channel = -1; + int reg = priv->pmib->dot11StationConfigEntry.dot11RegDomain; + + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80){ + // When user select band 3 with 80M channel bandwidth + which_channel = find80MChannel(priv->available_chnl,priv->available_chnl_num); + + if(which_channel == -1) // select non-DFS band 80M (ch 36 or 149) or down to 40/20M + { +#ifdef __ECOS + // generate random number + { + unsigned int random_buf[4]; + get_random_bytes(random_buf, 4); + random = random_buf[3]; + } +#else + get_random_bytes(&random, 4); +#endif + if(random % 2 == 0){ // try ch155 if not available choose ch36 + if(is80MChannel(priv->available_chnl, priv->available_chnl_num, 149)){ + which_channel = 149; + } + else{ + if(is80MChannel(priv->available_chnl, priv->available_chnl_num, 36)){ + which_channel = 36; + } + } + } + else{ + if(is80MChannel(priv->available_chnl, priv->available_chnl_num, 36)){ + which_channel = 36; + } + else{ + if(is80MChannel(priv->available_chnl, priv->available_chnl_num, 149)){ + which_channel = 149; + } + } + } + } + } + + + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80 || + priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20_40) { + if(which_channel == -1){ // down to 40M + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20_40; + which_channel = find40MChannel(priv->available_chnl,priv->available_chnl_num); + } + } + + + if(which_channel == -1){ // down to 20M + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20; +#ifdef __ECOS + unsigned int random_buf[4]; + get_random_bytes(random_buf, 4); + random = random_buf[3]; +#else + get_random_bytes(&random, 4); +#endif + if(priv->available_chnl_num){ + num = random % priv->available_chnl_num; + which_channel = priv->available_chnl[num]; + }else{ + which_channel = 0; + } + } + + return which_channel; +} + + +//insert the channel into the channel list +//if successful, return 1, else return 0 +int InsertChannel(unsigned int chnl_list[], unsigned int *chnl_num, unsigned int channel) +{ + unsigned int i, j; + + if (*chnl_num==0) { + chnl_list[0] = channel; + (*chnl_num)++; + return SUCCESS; + } + + for (i=0; i < *chnl_num; i++) { + if (chnl_list[i] == channel) { + _DEBUG_INFO("Inserting channel failed: channel %d already exists!\n", channel); + return FAIL; + } else if (chnl_list[i] > channel) { + break; + } + } + + if (i == *chnl_num) { + chnl_list[(*chnl_num)++] = channel; + } else { + for (j=*chnl_num; j > i; j--) + chnl_list[j] = chnl_list[j-1]; + chnl_list[j] = channel; + (*chnl_num)++; + } + + return SUCCESS; +} + + +/* + * remove the channel from the channel list + * if successful, return 1, else return 0 + */ +int RemoveChannel(struct rtl8192cd_priv *priv, unsigned int chnl_list[], unsigned int *chnl_num, unsigned int channel) +{ + unsigned int i, j; + + if (*chnl_num) { + for (i=0; i < *chnl_num; i++) + if (channel == chnl_list[i]) + break; + if (i == *chnl_num) { + _DEBUG_INFO("Can not remove channel %d!\n", channel); + return FAIL; + } else { + for (j=i; j < (*chnl_num-1); j++) + chnl_list[j] = chnl_list[j+1]; + (*chnl_num)--; + return SUCCESS; + } + } else { + _DEBUG_INFO("Can not remove channel %d!\n", channel); + return FAIL; + } +} + +void DFS_SwChnl_clnt(struct rtl8192cd_priv *priv) +{ + /* signin non-DFS channel */ + priv->pmib->dot11RFEntry.dot11channel = priv->pshare->dfsSwitchChannel; + priv->pshare->dfsSwitchChannel = 0; + RTL_W8(TXPAUSE, 0xff); + panic_printk("1. Swiching channel to %d!\n", priv->pmib->dot11RFEntry.dot11channel); + reload_txpwr_pg(priv); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + RTL_W8(TXPAUSE, 0x00); + + if (is_DFS_channel(priv->pmib->dot11RFEntry.dot11channel)) { + panic_printk("Switched to DFS band (ch %d) again!!\n", priv->pmib->dot11RFEntry.dot11channel); + } + +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11Bss.channel > 14)) { + priv->pshare->iqk_5g_done = 0; + PHY_IQCalibrate(priv); + } +#endif +} + + +void DFS_SwitchChannel(struct rtl8192cd_priv *priv) +{ + int ch = priv->pshare->dfsSwitchChannel; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + priv->pmib->dot11RFEntry.dot11channel = ch; + priv->pshare->dfsSwitchChannel = 0; + RTL_W8(TXPAUSE, 0xff); + + DEBUG_INFO("2. Swiching channel to %d!\n", priv->pmib->dot11RFEntry.dot11channel); + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw = priv->pmib->dot11nConfigEntry.dot11nUse40M; + + if( (ch>144) ? ((ch-1)%8) : (ch%8)) { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + } else { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + } + + //priv->pshare->No_RF_Write = 0; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + PHY_IQCalibrate(priv); //FOR_8812_IQK + + //priv->pshare->No_RF_Write = 1; + GET_ROOT(priv)->pmib->dot11DFSEntry.DFS_detected = priv->pshare->dfsSwitchChannel = 0; + GET_ROOT(priv)->pmib->dot11DFSEntry.disable_tx = priv->pmib->dot11DFSEntry.disable_tx = 0; + priv->ht_cap_len = 0; + update_beacon(priv); + RTL_W8(TXPAUSE, 0x00); +} + + +void rtl8192cd_dfs_det_chk_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned long throughput = 0; + int j; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + priv->ini_gain_cur = RTL_R8(0xc50); + + priv->st_L2H_cur = PHY_QueryBBReg(priv, 0x91c, 0x000000ff); + + throughput = priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage; + +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + for (j=0; jpvap_priv[j])) { + throughput += priv->pvap_priv[j]->ext_stats.tx_avarage+priv->pvap_priv[j]->ext_stats.rx_avarage; + } + } + } +#endif + + if ((throughput >> 17) <= priv->pshare->rf_ft_var.dfs_psd_tp_th) { + priv->idle_flag = 1; + if(priv->pshare->rf_ft_var.dfs_force_TP_mode) + priv->idle_flag = 0; + } + else{ + priv->idle_flag = 0; + } + +#if !defined(CONFIG_RTL_92D_SUPPORT) + // dfs_det.c + if((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) + { + if (priv->pshare->rf_ft_var.dfs_det_off == 0) { + #if defined(CONFIG_WLAN_HAL_8814AE) + if(GET_CHIP_VER(priv) == VERSION_8814A){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_on){ + rtl8192cd_radar_type_differentiation(priv); + } + } + #endif + rtl8192cd_dfs_det_chk(priv); + rtl8192cd_dfs_dynamic_setting(priv); + } + } +#endif + + // dynamic pwdb calibration + if (priv->ini_gain_pre != priv->ini_gain_cur) { + priv->pwdb_th = ((int)priv->st_L2H_cur - (int)priv->ini_gain_cur)/2 + priv->pshare->rf_ft_var.dfs_pwdb_scalar_factor; + priv->pwdb_th = MAX_NUM(priv->pwdb_th, (int)priv->pshare->rf_ft_var.dfs_pwdb_th); // limit the pwdb value to absoulte lower bound 0xa + priv->pwdb_th = MIN_NUM(priv->pwdb_th, 0x1f); // limit the pwdb value to absoulte upper bound 0x1f + PHY_SetBBReg(priv, 0x918, 0x00001f00, priv->pwdb_th); + } + + priv->ini_gain_pre = priv->ini_gain_cur; + + if(((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)) && (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK)){ + mod_timer(&priv->dfs_det_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pshare->rf_ft_var.dfs_det_period_jp_w53*10)); + } + else{ + mod_timer(&priv->dfs_det_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pshare->rf_ft_var.dfs_det_period*10)); + } +} + + +void DFS_SetReg(struct rtl8192cd_priv *priv) +{ + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, 0xc38, BIT(23) | BIT(22), 2); + PHY_SetBBReg(priv, 0x814, bMaskDWord, 0x04cc4d10); + } + else if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + PHY_SetBBReg(priv, 0x814, 0x3fffffff, 0x04cc4d10); + PHY_SetBBReg(priv, 0x834, bMaskByte0, 0x06); + + if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_FCC) { + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20){ + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x64741a20); + } + else{ + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x68741a20); + } + if(priv->pshare->rf_ft_var.dfs_det_off == 1){ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c166cdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16acdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a480); + } + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0d67231); + } + else{ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c176cdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c17acdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a480); + } + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0d6d231); + } + } + else if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) { + if(priv->pshare->rf_ft_var.dfs_det_off == 1){ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16acdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16ecdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a400); + } + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x0fa21a20); + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0f57204); + } + else{ + if((priv->pmib->dot11RFEntry.dot11channel >= 120) && + (priv->pmib->dot11RFEntry.dot11channel <= 132)){ + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80 || priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20){ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16acdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16ecdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a400); + } + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x0fa21a20); + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0f87204); + } + else{ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16acdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16ecdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x01528480); + } + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x0fa21a20); + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0f77204); + } + priv->ch_120_132_CAC_end = 0; + } + else{ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c17acdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c17ecdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a480); + } + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x0fa21a20); + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0f79204); + } + } + } + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK){ + if(priv->pshare->rf_ft_var.dfs_det_off == 1){ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a480); + } + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0d67234); + if((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16ecdf); + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x0f141a20); + } + else{ + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20){ + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x64721a20); + } + else{ + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x68721a20); + } + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c166cdf); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16acdf); + } + } + } + else{ + if((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)){ + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0fe7234); + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x0f141a20); + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c17ecdf); + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a480); + } + } + else{ + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0d67234); + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c176cdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c17acdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x01528480); + } + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20){ + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x64721a20); + } + else{ + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x68721a20); + } + } + } + } + else{ // default: FCC + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20){ + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x64741a20); + } + else{ + PHY_SetBBReg(priv, 0x91c, bMaskDWord, 0x68741a20); + } + if(priv->pshare->rf_ft_var.dfs_det_off == 1){ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c166cdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c16acdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a480); + } + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0d67231); + } + else{ + if (GET_CHIP_VER(priv) == VERSION_8814A){ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c176cdf); + PHY_SetBBReg(priv, 0x924, 0xfffffff, 0x095aa480); + } + else{ + PHY_SetBBReg(priv, 0x918, bMaskDWord, 0x1c17acdf); + PHY_SetBBReg(priv, 0x924, bMaskDWord, 0x0152a480); + } + PHY_SetBBReg(priv, 0x920, bMaskDWord, 0xe0d6d231); + } + } + + priv->st_L2H_cur = PHY_QueryBBReg(priv, 0x91c, 0x000000ff); + priv->pwdb_th = (int)PHY_QueryBBReg(priv, 0x918, 0x00001f00); + priv->peak_th = PHY_QueryBBReg(priv, 0x918, 0x00030000); + priv->short_pulse_cnt_th = PHY_QueryBBReg(priv, 0x920, 0x000f0000); + priv->long_pulse_cnt_th = PHY_QueryBBReg(priv, 0x920, 0x00f00000); + priv->peak_window = PHY_QueryBBReg(priv, 0x920, 0x00000300); + priv->nb2wb_th = PHY_QueryBBReg(priv, 0x920, 0x0000e000); + + //panic_printk("peak_th: %d\n", priv->peak_th); + + if (GET_CHIP_VER(priv) == VERSION_8881A) + PHY_SetBBReg(priv, 0xb00, 0xc0000000, 3); + + if (GET_CHIP_VER(priv) == VERSION_8814A){ // for 8814 new dfs mechanism setting + PHY_SetBBReg(priv, 0x19e4, 0x1fff, 0x1600); // DFS backoff factor=0.375 + PHY_SetBBReg(priv, 0x19e4, 0x30000, 1); //NonDC peak_th = 2times DC peak_th + PHY_SetBBReg(priv, 0x9f8, 0xc0000000, 3); // power for debug and auto test flow latch after ST + PHY_SetBBReg(priv, 0x9f4, 0x80000000, 1); // enable peak index should the same during the same short pulse (new mechanism) + PHY_SetBBReg(priv, 0x924, 0x20000000, 0); // disable peak index should the same during the same short pulse (old mechanism) + PHY_SetBBReg(priv, 0x19e4, 0xe000, 2); // if peak index diff >=2, then drop the result + if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) { + if((priv->pmib->dot11RFEntry.dot11channel >= 52) && (priv->pmib->dot11RFEntry.dot11channel <= 64)){ + // pulse width hist th setting + PHY_SetBBReg(priv, 0x19e4, 0xff000000, 2); // th1=2*04us + PHY_SetBBReg(priv, 0x19e8, bMaskDWord, 0xff080604); // set th2 = 4*0.4us, th3 = 6*0.4us, th4 = 8*0.4, th5 to max + // pulse repetition interval hist th setting + PHY_SetBBReg(priv, 0x19b8, 0x00007f80, 86); // th1=86*32us + PHY_SetBBReg(priv, 0x19ec, bMaskDWord, 0xffffffff); // set th2, th3, th4, th5 to max + } + else{ + // pulse width hist th setting + PHY_SetBBReg(priv, 0x19e4, 0xff000000, 2); // th1=2*04us + PHY_SetBBReg(priv, 0x19e8, bMaskDWord, 0x1a0e0604); // set th2 = 4*0.4us, th3 = 6*0.4us, th4 = 14*0.4us, th5 = 26*0.4us + // pulse repetition interval hist th setting + PHY_SetBBReg(priv, 0x19b8, 0x00007f80, 27); // th1=27*32us + PHY_SetBBReg(priv, 0x19ec, bMaskDWord, 0xffffffff); // set th2, th3, th4, th5 to max + } + } + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI){ + // pulse width hist th setting + PHY_SetBBReg(priv, 0x19e4, 0xff000000, 9); // th1=9*04us + PHY_SetBBReg(priv, 0x19e8, bMaskDWord, 0xffff2c19); // // set th2 = 25*0.4us, th3 = 44*0.4us, th4, th5 = max + // pulse repetition interval hist th setting + //PHY_SetBBReg(priv, 0x19b8, 0x00007f80, 86); // th1=86*32us + //PHY_SetBBReg(priv, 0x19ec, bMaskDWord, 0xffffffff); // set th2, th3, th4, th5 to max + } + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_FCC){ + // pulse width hist th setting + PHY_SetBBReg(priv, 0x19e4, 0xff000000, 2); // th1=2*04us + PHY_SetBBReg(priv, 0x19e8, bMaskDWord, 0x331a0e03); // // set th2 = 3*0.4us, th3 = 14*0.4us, th4 = 26*0.4us, th5 = 51*0.4us + // pulse repetition interval hist th setting + //PHY_SetBBReg(priv, 0x19b8, 0x00007f80, 86); // th1=86*32us + //PHY_SetBBReg(priv, 0x19ec, bMaskDWord, 0xffffffff); // set th2, th3, th4, th5 to max + } + else{ + } + } + + RTL_W8(TXPAUSE, 0xff); + } + + if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) { + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, 0xc8c, BIT(23) | BIT(22), 3); + PHY_SetBBReg(priv, 0xc30, 0xf, 0xa); + PHY_SetBBReg(priv, 0xcdc, 0xf0000, 4); + } + } else { + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, 0xc8c, BIT(23) | BIT(22), 0); + PHY_SetBBReg(priv, 0xcd8, 0xffff, 0x1a1f); + } + } + + /* + * Enable h/w DFS detect + */ + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, 0xc84, BIT(25), 1); + + if (!priv->pshare->rf_ft_var.dfsdbgmode){ + PHY_SetBBReg(priv, 0xc7c, BIT(28), 1); // ynlin dbg + } + } +} + +unsigned char *get_DFS_version(void) +{ + return DFS_VERSION; +} +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dfs_det.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dfs_det.c new file mode 100755 index 000000000..8ad197caf --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dfs_det.c @@ -0,0 +1,1256 @@ +/* + * Handling routines for DFS DET functions + * + * $Id: 8192cd_dfs_det.c,v 1.1 2012/05/04 12:49:07 jimmylin Exp $ + * + * Copyright (c) 2012 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_DFS_DET_C_ + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + + +#if defined(DFS) && !defined(CONFIG_RTL_92D_SUPPORT) +extern u2Byte dB_Invert_Table[8][12]; + +static u4Byte +ConvertTo_dB( + u4Byte Value) +{ + u1Byte i; + u1Byte j; + u4Byte dB; + + Value = Value & 0xFFFF; + + for (i=0;i<8;i++) + { + if (Value <= dB_Invert_Table[i][11]) + { + break; + } + } + + if (i >= 8) + { + return (96); // maximum 96 dB + } + + for (j=0;j<12;j++) + { + if (Value <= dB_Invert_Table[i][j]) + { + break; + } + } + + dB = i*12 + j + 1; + + return (dB); +} + + +static int +GetPSDData_8812( + IN PDM_ODM_T pDM_Odm, + unsigned int point, + u1Byte initial_gain_psd) +{ + int psd_report; + struct rtl8192cd_priv *priv=pDM_Odm->priv; + + //Set DCO frequency index, offset=(40MHz/SamplePts)*point + ODM_SetBBReg(pDM_Odm, 0x910, 0x3FF, point); + + //Start PSD calculation, Reg808[22]=0->1 + ODM_SetBBReg(pDM_Odm, 0x910, BIT22, 1); + + //Need to wait for HW PSD report + delay_us(priv->pshare->rf_ft_var.dfs_psd_delay); + + ODM_SetBBReg(pDM_Odm, 0x910, BIT22, 0); + + //Read PSD report, Reg8B4[15:0] + psd_report = (int)ODM_GetBBReg(pDM_Odm,0xf44, bMaskDWord) & 0x0000FFFF; + if(priv->pshare->rf_ft_var.psd_skip_lookup_table){ + if(psd_report >=14) + psd_report = 23; + else + psd_report = 8; + } + else{ + psd_report = (int)(ConvertTo_dB((u4Byte)psd_report)); + } + + return psd_report; + +} + + +void Scan_BB_PSD( + IN PDM_ODM_T pDM_Odm, + int *PSD_report_right, + int *PSD_report_left, + int len, + int initial_gain) +{ + struct rtl8192cd_priv *priv=pDM_Odm->priv; + pDIG_T pDM_DigTable = &pDM_Odm->DM_DigTable; + u1Byte ST_TH_origin; + u1Byte idx[20]={//96,99,102,106,109,112,115,118,122,125, + 224,227,230,234,237,240,243,246,250,253, + 0,3,6,10,13,16,19,22,26,29}; + int tone_idx, channel_org, channel, i; + + // set DFS ST_TH to max value + ST_TH_origin = RTL_R8(0x91c); + RTL_W8(0x91c, 0x4e); + + // Turn off CCK + ODM_SetBBReg(pDM_Odm, 0x808, BIT28, 0); //808[28] + + // Turn off TX + // Pause TX Queue + if (!priv->pmib->dot11DFSEntry.disable_tx) + ODM_Write1Byte(pDM_Odm, 0x522, 0xFF); //REG_TXPAUSE §ï¬°0x522 + + // Turn off CCA + if(GET_CHIP_VER(priv) == VERSION_8814A){ + ODM_SetBBReg(pDM_Odm, 0x838, BIT1, 0x1); //838[1] ³]¬°1 + } + else{ + ODM_SetBBReg(pDM_Odm, 0x838, BIT3, 0x1); //838[3] ³]¬°1 + } + + // PHYTXON while loop + PHY_SetBBReg(priv, 0x8fc, 0xfff, 0); + i = 0; + while (ODM_GetBBReg(pDM_Odm, 0xfa0, BIT18)) { + i++; + if (i > 1000000) { + panic_printk("Wait in %s() more than %d times!\n", __FUNCTION__, i); + break; + } + } + + // backup IGI_origin , set IGI = 0x3e; + pDM_DigTable->bPSDInProgress = TRUE; + odm_PauseDIG(pDM_Odm, PHYDM_PAUSE, PHYDM_PAUSE_LEVEL_7, initial_gain); + + // Turn off 3-wire + ODM_SetBBReg(pDM_Odm, 0xC00, BIT1|BIT0, 0x0); //c00[1:0] ¼g0 + + // pts value = 128, 256, 512, 1024 + ODM_SetBBReg(pDM_Odm, 0x910, BIT14|BIT15, 0x1); //910[15:14]³]¬°1, ¥Î256ÂI + ODM_SetBBReg(pDM_Odm, 0x910, BIT12|BIT13, 0x1); //910[13:12]³]¬°1, avg 8 ¦¸ + + // scan in-band PSD + channel_org = ODM_GetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, 0x3FF); + if(priv, priv->pshare->CurrentChannelBW != HT_CHANNEL_WIDTH_20){ + priv->pshare->No_RF_Write = 0; + SwBWMode(priv, HT_CHANNEL_WIDTH_20, 0); + priv->pshare->No_RF_Write = 1; + } + + if (priv->pshare->rf_ft_var.dfs_scan_inband) { + int PSD_report_inband[20]; + for (tone_idx=0;tone_idxpshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + channel = channel_org + 4; + else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + channel = channel_org + 6; + else + channel = channel_org + 10; + delay_us(300); // for idle 20M, it will emit signal in right 20M channel + priv->pshare->No_RF_Write = 0; + ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, 0x3FF, channel); + priv->pshare->No_RF_Write = 1; + + for (tone_idx=0;tone_idxpshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + channel = channel_org - 4; + else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + channel = channel_org - 6; + else + channel = channel_org - 10; + priv->pshare->No_RF_Write = 0; + ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, 0x3FF, channel); + priv->pshare->No_RF_Write = 1; + + for (tone_idx=0;tone_idxpshare->CurrentChannelBW != HT_CHANNEL_WIDTH_20){ + priv->pshare->No_RF_Write = 0; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + priv->pshare->No_RF_Write = 1; + } + priv->pshare->No_RF_Write = 0; + ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, 0x3FF, channel_org); + priv->pshare->No_RF_Write = 1; + + // Turn on 3-wire + ODM_SetBBReg(pDM_Odm, 0xc00, BIT1|BIT0, 0x3); //c00[1:0] ¼g3 + + // Restore Current Settings + // Resume DIG + pDM_DigTable->bPSDInProgress = FALSE; + odm_PauseDIG(pDM_Odm, PHYDM_RESUME, PHYDM_PAUSE_LEVEL_7, NONE); + + //Turn on CCA + if(GET_CHIP_VER(priv) == VERSION_8814A){ + ODM_SetBBReg(pDM_Odm, 0x838, BIT1, 0); //838[1] ³]¬°0 + } + else{ + ODM_SetBBReg(pDM_Odm, 0x838, BIT3, 0); //838[3] ³]¬°0 + } + + + // Turn on TX + // Resume TX Queue + if (!priv->pmib->dot11DFSEntry.disable_tx) + ODM_Write1Byte(pDM_Odm, 0x522, 0x00); //REG_TXPAUSE §ï¬°0x522 + + // CCK on + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) + ODM_SetBBReg(pDM_Odm, 0x808, BIT28, 1); //808[28] + + // Resume DFS ST_TH + RTL_W8(0x91c, ST_TH_origin); +} + + +void rtl8192cd_dfs_det_chk(struct rtl8192cd_priv *priv) +{ + unsigned int regf98_value; + unsigned int reg918_value; + unsigned int reg91c_value; + unsigned int reg920_value; + unsigned int reg924_value; + unsigned int FA_count_cur=0, FA_count_inc=0; + unsigned int VHT_CRC_ok_cnt_cur=0, VHT_CRC_ok_cnt_inc=0; + unsigned int HT_CRC_ok_cnt_cur=0, HT_CRC_ok_cnt_inc=0; + unsigned int LEG_CRC_ok_cnt_cur=0, LEG_CRC_ok_cnt_inc=0; + unsigned int Total_CRC_OK_cnt_inc=0, FA_CRCOK_ratio=0; + unsigned char DFS_tri_short_pulse=0, DFS_tri_long_pulse=0, fa_mask_mid_th=0, fa_mask_lower_th=0; + unsigned char radar_type = 0; /* 0 for short, 1 for long */ + unsigned int short_pulse_cnt_cur=0, short_pulse_cnt_inc=0; + unsigned int long_pulse_cnt_cur=0, long_pulse_cnt_inc=0; + unsigned int total_pulse_count_inc=0, max_sht_pusle_cnt_th=0; + unsigned int sum, k, fa_flag=0; + unsigned int st_L2H_new=0, st_L2H_tmp, index=0, fault_flag_det, fault_flag_psd; + int flags=0; + unsigned long throughput = 0; + int j; + + int i, PSD_report_right[20], PSD_report_left[20]; + int max_right, max_left; + int max_fa_in_hist=0, total_fa_in_hist=0, pre_post_now_acc_fa_in_hist=0; + + if (priv->det_asoc_clear > 0) { + priv->det_asoc_clear--; + priv->pmib->dot11DFSEntry.DFS_detected = 0; + priv->FA_count_pre = 0; + priv->VHT_CRC_ok_cnt_pre = 0; + priv->HT_CRC_ok_cnt_pre = 0; + priv->LEG_CRC_ok_cnt_pre = 0; + priv->mask_idx = 0; + priv->mask_hist_checked = 0; + memset(priv->radar_det_mask_hist, 0, sizeof(priv->radar_det_mask_hist)); + memset(priv->pulse_flag_hist, 0, sizeof(priv->pulse_flag_hist)); + mod_timer(&priv->dfs_det_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pshare->rf_ft_var.dfs_det_period*10)); + return; + } + + throughput = priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage; + +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + for (j=0; jpvap_priv[j])) { + throughput += priv->pvap_priv[j]->ext_stats.tx_avarage+priv->pvap_priv[j]->ext_stats.rx_avarage; + } + } + } +#endif + + // Get FA count during past 100ms + FA_count_cur = PHY_QueryBBReg(priv, 0xf48, 0x0000ffff); + + if (priv->FA_count_pre == 0) + FA_count_inc = 0; + else if (FA_count_cur >= priv->FA_count_pre) + FA_count_inc = FA_count_cur - priv->FA_count_pre; + else + FA_count_inc = FA_count_cur; + priv->FA_count_pre = FA_count_cur; + + priv->fa_inc_hist[priv->mask_idx] = FA_count_inc; + for (i=0; i<5; i++) { + total_fa_in_hist = total_fa_in_hist + priv->fa_inc_hist[i]; + if (priv->fa_inc_hist[i] > max_fa_in_hist) + max_fa_in_hist = priv->fa_inc_hist[i]; + } + if (priv->mask_idx >= priv->pshare->rf_ft_var.dfs_det_flag_offset) + index = priv->mask_idx - priv->pshare->rf_ft_var.dfs_det_flag_offset; + else + index = priv->pshare->rf_ft_var.dfs_det_hist_len + priv->mask_idx - priv->pshare->rf_ft_var.dfs_det_flag_offset; + if (index == 0) + pre_post_now_acc_fa_in_hist = priv->fa_inc_hist[index] + priv->fa_inc_hist[index+1] + priv->fa_inc_hist[4]; + else if (index == 4) + pre_post_now_acc_fa_in_hist = priv->fa_inc_hist[index] + priv->fa_inc_hist[0] + priv->fa_inc_hist[index-1]; + else + pre_post_now_acc_fa_in_hist = priv->fa_inc_hist[index] + priv->fa_inc_hist[index+1] + priv->fa_inc_hist[index-1]; + + // Get VHT CRC32 ok count during past 100ms + VHT_CRC_ok_cnt_cur = PHY_QueryBBReg(priv, 0xf0c, 0x00003fff); + if (VHT_CRC_ok_cnt_cur >= priv->VHT_CRC_ok_cnt_pre) + VHT_CRC_ok_cnt_inc = VHT_CRC_ok_cnt_cur - priv->VHT_CRC_ok_cnt_pre; + else + VHT_CRC_ok_cnt_inc = VHT_CRC_ok_cnt_cur; + priv->VHT_CRC_ok_cnt_pre = VHT_CRC_ok_cnt_cur; + + // Get HT CRC32 ok count during past 100ms + HT_CRC_ok_cnt_cur = PHY_QueryBBReg(priv, 0xf10, 0x00003fff); + if (HT_CRC_ok_cnt_cur >= priv->HT_CRC_ok_cnt_pre) + HT_CRC_ok_cnt_inc = HT_CRC_ok_cnt_cur - priv->HT_CRC_ok_cnt_pre; + else + HT_CRC_ok_cnt_inc = HT_CRC_ok_cnt_cur; + priv->HT_CRC_ok_cnt_pre = HT_CRC_ok_cnt_cur; + + // Get Legacy CRC32 ok count during past 100ms + LEG_CRC_ok_cnt_cur = PHY_QueryBBReg(priv, 0xf14, 0x00003fff); + if (LEG_CRC_ok_cnt_cur >= priv->LEG_CRC_ok_cnt_pre) + LEG_CRC_ok_cnt_inc = LEG_CRC_ok_cnt_cur - priv->LEG_CRC_ok_cnt_pre; + else + LEG_CRC_ok_cnt_inc = LEG_CRC_ok_cnt_cur; + priv->LEG_CRC_ok_cnt_pre = LEG_CRC_ok_cnt_cur; + + if ((VHT_CRC_ok_cnt_cur == 0x3fff) || + (HT_CRC_ok_cnt_cur == 0x3fff) || + (LEG_CRC_ok_cnt_cur == 0x3fff)) { + PHY_SetBBReg(priv, 0xb58, BIT(0), 1); + PHY_SetBBReg(priv, 0xb58, BIT(0), 0); + } + + Total_CRC_OK_cnt_inc = VHT_CRC_ok_cnt_inc + HT_CRC_ok_cnt_inc + LEG_CRC_ok_cnt_inc; + + // check if the FA occrus frequencly during 100ms + // FA_count_inc is divided by Total_CRC_OK_cnt_inc, which helps to distinguish normal trasmission from interference + if (Total_CRC_OK_cnt_inc > 0) + FA_CRCOK_ratio = FA_count_inc / Total_CRC_OK_cnt_inc; + + //=====dynamic power threshold (DPT) ======== + // Get short pulse count, need carefully handle the counter overflow + regf98_value = PHY_QueryBBReg(priv, 0xf98, 0xffffffff); + short_pulse_cnt_cur = regf98_value & 0x000000ff; + if (short_pulse_cnt_cur >= priv->short_pulse_cnt_pre) + short_pulse_cnt_inc = short_pulse_cnt_cur - priv->short_pulse_cnt_pre; + else + short_pulse_cnt_inc = short_pulse_cnt_cur; + priv->short_pulse_cnt_pre = short_pulse_cnt_cur; + + // Get long pulse count, need carefully handle the counter overflow + long_pulse_cnt_cur = (regf98_value & 0x0000ff00) >> 8; + if (long_pulse_cnt_cur >= priv->long_pulse_cnt_pre) + long_pulse_cnt_inc = long_pulse_cnt_cur - priv->long_pulse_cnt_pre; + else + long_pulse_cnt_inc = long_pulse_cnt_cur; + priv->long_pulse_cnt_pre = long_pulse_cnt_cur; + + total_pulse_count_inc = short_pulse_cnt_inc + long_pulse_cnt_inc; + + if (priv->pshare->rf_ft_var.dfs_det_print) { + panic_printk("=====================================================================\n"); + panic_printk("Total_CRC_OK_cnt_inc[%d] VHT_CRC_ok_cnt_inc[%d] HT_CRC_ok_cnt_inc[%d] LEG_CRC_ok_cnt_inc[%d] FA_count_inc[%d] FA_CRCOK_ratio[%d]\n", + Total_CRC_OK_cnt_inc, VHT_CRC_ok_cnt_inc, HT_CRC_ok_cnt_inc, LEG_CRC_ok_cnt_inc, FA_count_inc, FA_CRCOK_ratio); + panic_printk("Init_Gain[%x] 0x91c[%x] 0xf98[%08x] short_pulse_cnt_inc[%d] long_pulse_cnt_inc[%d]\n", + priv->ini_gain_cur, priv->st_L2H_cur, regf98_value, short_pulse_cnt_inc, long_pulse_cnt_inc); + panic_printk("Throughput: %luMbps\n", (throughput>>17)); + reg918_value = PHY_QueryBBReg(priv, 0x918, 0xffffffff); + reg91c_value = PHY_QueryBBReg(priv, 0x91c, 0xffffffff); + reg920_value = PHY_QueryBBReg(priv, 0x920, 0xffffffff); + reg924_value = PHY_QueryBBReg(priv, 0x924, 0xffffffff); + printk("0x918[%08x] 0x91c[%08x] 0x920[%08x] 0x924[%08x]\n", reg918_value, reg91c_value, reg920_value, reg924_value); + } + + DFS_tri_short_pulse = (regf98_value & BIT(17))? 1 : 0; + DFS_tri_long_pulse = (regf98_value & BIT(19))? 1 : 0; + + if(DFS_tri_short_pulse) + radar_type = 0; + else if(DFS_tri_long_pulse) + radar_type = 1; + + if (DFS_tri_short_pulse) { + //RTL_W32(0x920, RTL_R32(0x920) | BIT(24)); + //RTL_W32(0x920, RTL_R32(0x920) & ~BIT(24)); + RTL_W32(0x924, RTL_R32(0x924) & ~BIT(15)); + RTL_W32(0x924, RTL_R32(0x924) | BIT(15)); + } + if (DFS_tri_long_pulse) { + //RTL_W32(0x920, RTL_R32(0x920) | BIT(25)); + //RTL_W32(0x920, RTL_R32(0x920) & ~BIT(25)); + RTL_W32(0x924, RTL_R32(0x924) & ~BIT(15)); + RTL_W32(0x924, RTL_R32(0x924) | BIT(15)); + if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) { + if ((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)) { + DFS_tri_long_pulse = 0; + } + } + if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) { + DFS_tri_long_pulse = 0; + } + } + + st_L2H_new = priv->st_L2H_cur; + priv->pulse_flag_hist[priv->mask_idx] = DFS_tri_short_pulse | DFS_tri_long_pulse; + + //max_sht_pusle_cnt_th = PHY_QueryBBReg(priv, 0x920, 0x000f0000)-1; //read 920[19:16] + max_sht_pusle_cnt_th = priv->pshare->rf_ft_var.dfs_max_sht_pusle_cnt_th; + if (priv->pshare->rf_ft_var.dfs_det_print3) + panic_printk("max_sht_pusle_cnt_th = %d\n", max_sht_pusle_cnt_th); + + if(priv->idle_flag == 1){ + if(priv->pshare->rf_ft_var.dfs_psd_idle_on == 1){ + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + Scan_BB_PSD(ODMPTR, PSD_report_right, PSD_report_left, 20, 0x3e); + SMP_UNLOCK(flags); + RESTORE_INT(flags); + } + else{ + for (i=0; i<20; i++) { + PSD_report_right[i] = 0; + PSD_report_left[i] = 0; + } + } + } + else{ + if(priv->pshare->rf_ft_var.dfs_psd_TP_on == 1){ + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + Scan_BB_PSD(ODMPTR, PSD_report_right, PSD_report_left, 20, 0x3e); + SMP_UNLOCK(flags); + RESTORE_INT(flags); + } + else{ + for (i=0; i<20; i++) { + PSD_report_right[i] = 0; + PSD_report_left[i] = 0; + } + } + } + + for (i=0; i<20; i++) { + PSD_report_right[i] = (-110 + 0x3e) - 39 + PSD_report_right[i]; + PSD_report_left[i] = (-110 + 0x3e) - 39 + PSD_report_left[i]; + } + if (priv->pshare->rf_ft_var.dfs_det_print_psd) { + panic_printk("PSD right: "); + for (i=0; i<20; i++) + panic_printk("%d ", PSD_report_right[i]); + //panic_printk("\n"); + panic_printk(" PSD left: "); + for (i=0; i<20; i++) + panic_printk("%d ", PSD_report_left[i]); + panic_printk("\n"); + } + + fault_flag_det = 0; + fault_flag_psd = 0; + fa_flag = 0; + if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI){ + fa_mask_mid_th = priv->pshare->rf_ft_var.dfs_fa_cnt_mid + 20; + fa_mask_lower_th = priv->pshare->rf_ft_var.dfs_fa_cnt_lower + 40; + } + else{ + fa_mask_mid_th = priv->pshare->rf_ft_var.dfs_fa_cnt_mid; + fa_mask_lower_th = priv->pshare->rf_ft_var.dfs_fa_cnt_lower; + } + if (max_fa_in_hist >= fa_mask_mid_th || total_fa_in_hist >= priv->pshare->rf_ft_var.dfs_fa_hist || pre_post_now_acc_fa_in_hist >= fa_mask_mid_th){ + /*if (priv->mask_idx >= priv->pshare->rf_ft_var.dfs_det_flag_offset) + index = priv->mask_idx - priv->pshare->rf_ft_var.dfs_det_flag_offset; + else + index = priv->pshare->rf_ft_var.dfs_det_hist_len + priv->mask_idx - priv->pshare->rf_ft_var.dfs_det_flag_offset; */ + priv->radar_det_mask_hist[index] = 1; + if (priv->pulse_flag_hist[index] == 1){ + priv->pulse_flag_hist[index] = 0; + if (priv->pshare->rf_ft_var.dfs_det_print4){ + panic_printk("Radar is masked : FA mask case3\n"); + } + } + fa_flag = 1; + } + if (((FA_count_inc >= priv->pshare->rf_ft_var.dfs_dpt_fa_th_upper) && (short_pulse_cnt_inc > max_sht_pusle_cnt_th)) || + (priv->ini_gain_cur >= priv->pshare->rf_ft_var.dpt_ini_gain_th)) { + st_L2H_new = priv->pshare->rf_ft_var.dfs_dpt_st_l2h_max; + if (priv->pshare->rf_ft_var.dfs_det_print3) + panic_printk("[1] st_L2H_new %x\n", st_L2H_new); + priv->radar_det_mask_hist[priv->mask_idx] = 1; + if (priv->pulse_flag_hist[priv->mask_idx] == 1){ + priv->pulse_flag_hist[priv->mask_idx] = 0; + if (priv->pshare->rf_ft_var.dfs_det_print4){ + panic_printk("Radar is masked : FA mask case1\n"); + } + } + fa_flag = 1; + } + else if (((FA_count_inc >= fa_mask_mid_th) || + ((FA_count_inc >= fa_mask_lower_th) && + (FA_count_inc >= priv->pshare->rf_ft_var.dfs_fa_cnt_inc_ratio * priv->FA_count_inc_pre))) + && (short_pulse_cnt_inc > max_sht_pusle_cnt_th)) { + if (priv->pshare->rf_ft_var.dfs_dpt_st_l2h_add) + st_L2H_new += 2; + if (priv->pshare->rf_ft_var.dfs_det_print3) + panic_printk("[2] st_L2H_new %x\n", st_L2H_new); + priv->radar_det_mask_hist[priv->mask_idx] = 1; + if (priv->pulse_flag_hist[priv->mask_idx] == 1){ + priv->pulse_flag_hist[priv->mask_idx] = 0; + if (priv->pshare->rf_ft_var.dfs_det_print4){ + panic_printk("Radar is masked : FA mask case2\n"); + } + } + fa_flag = 1; + } + else + { + if (((FA_CRCOK_ratio > priv->pshare->rf_ft_var.dfs_fa_ratio_th) && + (FA_count_inc >= priv->pshare->rf_ft_var.dfs_fa_cnt_lower) && + (Total_CRC_OK_cnt_inc > priv->pshare->rf_ft_var.dfs_crc32_cnt_lower)) || + ((short_pulse_cnt_inc <= max_sht_pusle_cnt_th) && (short_pulse_cnt_inc != 0) && + (priv->idle_flag == 1) && (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK)) || + (FA_count_inc >= priv->pshare->rf_ft_var.dfs_fa_cnt_upper)) + priv->radar_det_mask_hist[priv->mask_idx] = 1; + else + priv->radar_det_mask_hist[priv->mask_idx] = 0; + } + + if (priv->pshare->rf_ft_var.dfs_det_print2) { + panic_printk("mask_idx: %d\n", priv->mask_idx); + panic_printk("radar_det_mask_hist: "); + for (i=0; ipshare->rf_ft_var.dfs_det_hist_len; i++) + panic_printk("%d ", priv->radar_det_mask_hist[i]); + panic_printk("pulse_flag_hist: "); + for (i=0; ipshare->rf_ft_var.dfs_det_hist_len; i++) + panic_printk("%d ", priv->pulse_flag_hist[i]); + panic_printk("fa_inc_hist: "); + for (i=0; i<5; i++) + panic_printk("%d ", priv->fa_inc_hist[i]); + panic_printk("\n"); + panic_printk("max_fa_in_hist: %d pre_post_now_acc_fa_in_hist: %d ",max_fa_in_hist,pre_post_now_acc_fa_in_hist); + } + + memcpy(&priv->PSD_report_right[priv->mask_idx][0], PSD_report_right, 20*sizeof(int)); + memcpy(&priv->PSD_report_left[priv->mask_idx][0], PSD_report_left, 20*sizeof(int)); + + for (i=0; i<20; i++) { + priv->max_hold_right[i] = -1000; + priv->max_hold_left[i] = -1000; + } + + for (k=0; k<5; k++) { + for (i=0; i<20; i++) { + if (priv->PSD_report_right[k][i] > priv->max_hold_right[i]) + priv->max_hold_right[i] = priv->PSD_report_right[k][i]; + if (priv->PSD_report_left[k][i] > priv->max_hold_left[i]) + priv->max_hold_left[i] = priv->PSD_report_left[k][i]; + } + } + + if ((priv->pshare->rf_ft_var.dfs_psd_op == 1) && (priv->idle_flag == 0)) + { + int right_index_start, left_index_end; + int avg_1 = (priv->max_hold_right[0]+priv->max_hold_right[1]+priv->max_hold_right[2])/3; + int avg_2 = (priv->max_hold_right[17]+priv->max_hold_right[18]+priv->max_hold_right[19])/3; + max_right = -1000; + if(RTL_ABS(avg_1, avg_2) <= 3) + right_index_start=2; + else + right_index_start=11; + for (i=right_index_start; i<20; i++) { + if ((i != 10) && (max_right < priv->max_hold_right[i])) + max_right = priv->max_hold_right[i]; + } + + avg_1 = (priv->max_hold_left[0]+priv->max_hold_left[1]+priv->max_hold_left[2])/3; + avg_2 = (priv->max_hold_left[17]+priv->max_hold_left[18]+priv->max_hold_left[19])/3; + max_left = -1000; + if (RTL_ABS(avg_1, avg_2) <= 3) + left_index_end=20; + else + left_index_end=8; + for (i=0; imax_hold_left[i])) + max_left = priv->max_hold_left[i]; + } + if(max_right == 0){ + max_right = -99; + } + if(max_left == 0){ + max_left = -99; + } + } + else + { + max_right = -1000; + for (i=2; i<20; i++) { + if ((i != 10) && (max_right < priv->max_hold_right[i])) + max_right = priv->max_hold_right[i]; + } + max_left = -1000; + for (i=0; i<20; i++) { + if ((i != 10) && (max_left < priv->max_hold_left[i])) + max_left = priv->max_hold_left[i]; + } + if(max_right == 0){ + max_right = -99; + } + if(max_left == 0){ + max_left = -99; + } + } + + if (priv->pshare->rf_ft_var.dfs_det_print) + panic_printk("max_right %d, max_left %d\n", max_right, max_left); + + /*if (priv->mask_idx >= priv->pshare->rf_ft_var.dfs_det_flag_offset) + index = priv->mask_idx - priv->pshare->rf_ft_var.dfs_det_flag_offset; + else + index = priv->pshare->rf_ft_var.dfs_det_hist_len + priv->mask_idx - priv->pshare->rf_ft_var.dfs_det_flag_offset;*/ + + // use PSD detection result + if ((max_right > (0-(int)priv->pshare->rf_ft_var.dfs_psd_pw_th)) || (max_left > (0-(int)priv->pshare->rf_ft_var.dfs_psd_pw_th))) { + if (priv->pshare->rf_ft_var.dfs_dpt_st_l2h_add) { + st_L2H_tmp = 110 + ((max_right > max_left)? max_right:max_left) - priv->pshare->rf_ft_var.dfs_psd_fir_decay; + if (st_L2H_tmp > priv->st_L2H_cur) + st_L2H_new = st_L2H_tmp; + } + if (priv->pshare->rf_ft_var.dfs_det_print3) + panic_printk("[3] st_L2H_new %x\n", st_L2H_new); + + if (priv->pshare->rf_ft_var.dfs_det_print) + panic_printk("st_L2H_cur %x pwdb_th %x\n", st_L2H_new, priv->pwdb_th); + + fault_flag_psd = 1; + if (priv->pulse_flag_hist[index] == 1){ + priv->pulse_flag_hist[index] = 0; + if (priv->pshare->rf_ft_var.dfs_det_print4){ + panic_printk("Radar is masked : PSD mask\n"); + } + } + priv->radar_det_mask_hist[index] = 1; + } + + sum = 0; + for (k=0; kpshare->rf_ft_var.dfs_det_hist_len; k++) { + if (priv->radar_det_mask_hist[k] == 1) + sum++; + } + + if (priv->mask_hist_checked <= priv->pshare->rf_ft_var.dfs_det_hist_len) + priv->mask_hist_checked++; + + //only the decision result of short pulse needs to refer the FA decision results + if ((priv->mask_hist_checked >= priv->pshare->rf_ft_var.dfs_det_hist_len) && + //(DFS_tri_long_pulse || DFS_tri_short_pulse) && + priv->pulse_flag_hist[index]) + { + //if ((sum <= priv->pshare->rf_ft_var.dfs_det_sum_th) && + // (fa_flag == 0)) + if (sum <= priv->pshare->rf_ft_var.dfs_det_sum_th) + { + priv->pmib->dot11DFSEntry.DFS_detected = 1 ; // DFS detect + panic_printk("%s %d %d DFS detected\n", __FUNCTION__, __LINE__,radar_type); + } + else { + fault_flag_det = 1; + if (priv->pshare->rf_ft_var.dfs_det_print4){ + panic_printk("Radar is masked : mask_hist large than thd\n"); + } + } + } + + priv->mask_idx++; + if (priv->mask_idx == priv->pshare->rf_ft_var.dfs_det_hist_len) + priv->mask_idx = 0; + + if ((fault_flag_det == 0) && (fault_flag_psd == 0) && (fa_flag ==0)) { + //if (total_pulse_count_inc < priv->pshare->rf_ft_var.dfs_dpt_pulse_th_lower) { + // // limit the ST value to absoulte lower bound 0x1c + // st_L2H_new -= 4; + // if (priv->pshare->rf_ft_var.dfs_det_print3) + // panic_printk("[4] st_L2H_new %x\n", st_L2H_new); + //} + ///*else if (total_pulse_count_inc < priv->pshare->rf_ft_var.dfs_dpt_pulse_th_mid) { + // // limit the ST value to absoulte lower bound 0x1c + // st_L2H_new -= 2; + // if (priv->pshare->rf_ft_var.dfs_det_print3) + // panic_printk("[5] st_L2H_new %x\n", st_L2H_new); + //}*/ + //else if (ini_gain_inc < 0){ + // st_L2H_new += ini_gain_inc; + // if (priv->pshare->rf_ft_var.dfs_det_print3) + // panic_printk("[6] st_L2H_new %x\n", st_L2H_new); + //} + ///*else if ((total_pulse_count_inc < max_sht_pusle_cnt_th) && + // (((priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17) <= priv->pshare->rf_ft_var.dfs_psd_tp_th)) { + // st_L2H_new += priv->pshare->rf_ft_var.dfs_dpt_st_l2h_idle_th; + //}*/ + if (priv->ini_gain_cur < priv->pshare->rf_ft_var.dpt_ini_gain_th) { + if ((priv->idle_flag == 1) && (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK)) + st_L2H_new = priv->pshare->rf_ft_var.dfs_dpt_st_l2h_min + priv->pshare->rf_ft_var.dfs_dpt_st_l2h_idle_offset; + else + st_L2H_new = priv->pshare->rf_ft_var.dfs_dpt_st_l2h_min; + } + } + else{ + + + if (priv->pshare->rf_ft_var.dfs_dpt_st_l2h_add) + st_L2H_new += 2; + if (priv->pshare->rf_ft_var.dfs_det_print3) + panic_printk("[7] st_L2H_new %x\n", st_L2H_new); + + + if (DFS_tri_short_pulse) { + //RTL_W32(0x920, RTL_R32(0x920) | (BIT(24) | BIT(28))); + //RTL_W32(0x920, RTL_R32(0x920) & ~(BIT(24) | BIT(28))); + RTL_W32(0x924, RTL_R32(0x924) & ~BIT(15)); + RTL_W32(0x924, RTL_R32(0x924) | BIT(15)); + } + if (DFS_tri_long_pulse) { + //RTL_W32(0x920, RTL_R32(0x920) | (BIT(25) | BIT(28))); + //RTL_W32(0x920, RTL_R32(0x920) & ~(BIT(25) | BIT(28))); + RTL_W32(0x924, RTL_R32(0x924) & ~BIT(15)); + RTL_W32(0x924, RTL_R32(0x924) | BIT(15)); + } + } + + if ((st_L2H_new != priv->st_L2H_cur)) { + // limit the ST value to absoulte lower bound 0x22 + // limit the ST value to absoulte upper bound 0x4e + if (st_L2H_new < priv->pshare->rf_ft_var.dfs_dpt_st_l2h_min) { + if ((priv->idle_flag == 1) && (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK)) + priv->st_L2H_cur = priv->pshare->rf_ft_var.dfs_dpt_st_l2h_min + priv->pshare->rf_ft_var.dfs_dpt_st_l2h_idle_offset; + else + priv->st_L2H_cur = priv->pshare->rf_ft_var.dfs_dpt_st_l2h_min; + //priv->st_L2H_cur = priv->pshare->rf_ft_var.dfs_dpt_st_l2h_min; + } + else if (st_L2H_new > priv->pshare->rf_ft_var.dfs_dpt_st_l2h_max) + priv->st_L2H_cur = priv->pshare->rf_ft_var.dfs_dpt_st_l2h_max; + else + priv->st_L2H_cur = st_L2H_new; + RTL_W8(0x91c, priv->st_L2H_cur); + + priv->pwdb_th = ((int)priv->st_L2H_cur - (int)priv->ini_gain_cur)/2 + priv->pshare->rf_ft_var.dfs_pwdb_scalar_factor; + priv->pwdb_th = MAX_NUM(priv->pwdb_th, (int)priv->pshare->rf_ft_var.dfs_pwdb_th); // limit the pwdb value to absoulte lower bound 0xa + priv->pwdb_th = MIN_NUM(priv->pwdb_th, 0x1f); // limit the pwdb value to absoulte upper bound 0x1f + PHY_SetBBReg(priv, 0x918, 0x00001f00, priv->pwdb_th); + } + + if (priv->pshare->rf_ft_var.dfs_det_print2) { + panic_printk("fault_flag_det[%d], fault_flag_psd[%d], DFS_detected [%d]\n",fault_flag_det, fault_flag_psd, priv->pmib->dot11DFSEntry.DFS_detected ); + } + + priv->FA_count_inc_pre = FA_count_inc; +} + + +void rtl8192cd_dfs_dynamic_setting(struct rtl8192cd_priv *priv) +{ + unsigned char peak_th_cur=0, short_pulse_cnt_th_cur=0, long_pulse_cnt_th_cur=0, three_peak_opt_cur=0, three_peak_th2_cur=0; + unsigned char peak_window_cur=0, nb2wb_th_cur=0; + + if ((priv->idle_flag == 1)) { // idle (no traffic) + peak_th_cur = 3; + short_pulse_cnt_th_cur = 6; + long_pulse_cnt_th_cur = 13; + peak_window_cur = 2; + nb2wb_th_cur = 6; + three_peak_opt_cur = 1; + three_peak_th2_cur = 2; + if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK){ + if ((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)) { + short_pulse_cnt_th_cur = priv->pshare->rf_ft_var.dfs_pc0_th_idle_w53; + long_pulse_cnt_th_cur = 15; + peak_window_cur = 2; + nb2wb_th_cur = 3; + three_peak_th2_cur = 0; + } + else { + short_pulse_cnt_th_cur = priv->pshare->rf_ft_var.dfs_pc0_th_idle_w56; + peak_window_cur = 2; + nb2wb_th_cur = 3; + three_peak_th2_cur = 0; + } + } + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_FCC){ + } + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI){ + long_pulse_cnt_th_cur = 15; + if((priv->ch_120_132_CAC_end == 0) && (priv->pmib->dot11RFEntry.dot11channel >= 120) && + (priv->pmib->dot11RFEntry.dot11channel <= 132)){ + peak_th_cur = 2; + peak_window_cur = 2; + nb2wb_th_cur = 3; + three_peak_opt_cur = 0; + short_pulse_cnt_th_cur = 8; + } + else{ + three_peak_opt_cur = 0; + short_pulse_cnt_th_cur = 10; + nb2wb_th_cur = 4; + } + } + else{ // default: FCC + } + } + else{ // in service (with TP) + peak_th_cur = 2; + short_pulse_cnt_th_cur = 6; + long_pulse_cnt_th_cur = 9; + peak_window_cur = 2; + nb2wb_th_cur = 3; + three_peak_opt_cur = 1; + three_peak_th2_cur = 2; + if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK){ + if ((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)) { + long_pulse_cnt_th_cur = 15; + three_peak_th2_cur = 0; + } + else { + three_peak_opt_cur = 0; + three_peak_th2_cur = 0; + } + } + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_FCC){ + } + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI){ + long_pulse_cnt_th_cur = 15; + short_pulse_cnt_th_cur = 5; + three_peak_opt_cur = 0; + } + else{ + } + } + if((priv->peak_th != peak_th_cur)){ + PHY_SetBBReg(priv, 0x918, 0x00030000, peak_th_cur); + } + if((priv->short_pulse_cnt_th != short_pulse_cnt_th_cur)){ + PHY_SetBBReg(priv, 0x920, 0x000f0000, short_pulse_cnt_th_cur); + } + if((priv->long_pulse_cnt_th != long_pulse_cnt_th_cur)){ + PHY_SetBBReg(priv, 0x920, 0x00f00000, long_pulse_cnt_th_cur); + } + if((priv->peak_window != peak_window_cur)){ + PHY_SetBBReg(priv, 0x920, 0x00000300, peak_window_cur); + } + if((priv->nb2wb_th != nb2wb_th_cur)){ + PHY_SetBBReg(priv, 0x920, 0x0000e000, nb2wb_th_cur); + } + if((priv->three_peak_opt != three_peak_opt_cur)){ + PHY_SetBBReg(priv, 0x924, 0x00000180, three_peak_opt_cur); + } + if((priv->three_peak_th2 != three_peak_th2_cur)){ + PHY_SetBBReg(priv, 0x924, 0x00007000, three_peak_th2_cur); + } + + priv->peak_th = peak_th_cur; + priv->short_pulse_cnt_th = short_pulse_cnt_th_cur; + priv->long_pulse_cnt_th = long_pulse_cnt_th_cur; + priv->peak_window = peak_window_cur; + priv->nb2wb_th = nb2wb_th_cur; + priv->three_peak_opt = three_peak_opt_cur; + priv->three_peak_th2 = three_peak_th2_cur; +} + +#if defined(CONFIG_WLAN_HAL_8814AE) +void rtl8192cd_radar_type_differentiation(struct rtl8192cd_priv *priv) +{ + unsigned char i, need_reset, g_ti_cur[16], g_pw_cur[6], g_pri_cur[6], g_ti_inc[16], g_pw_inc[6], g_pri_inc[6]; // ti = tone index, pw = pulse width, pri = pulse repetition interval + unsigned int g_total, g0_ratio, g1_ratio, g2_ratio, g3_ratio, g4_ratio, g5_ratio; + unsigned int regf98_value; + unsigned char DFS_tri_short_pulse=0, DFS_tri_long_pulse=0, short_pulse_th; + + regf98_value = PHY_QueryBBReg(priv, 0xf98, 0xffffffff); + DFS_tri_short_pulse = (regf98_value & BIT(17))? 1 : 0; + DFS_tri_long_pulse = (regf98_value & BIT(19))? 1 : 0; + short_pulse_th = PHY_QueryBBReg(priv, 0x920, 0x000f0000); + + PHY_SetBBReg(priv, 0x19b8, 0x40, 0); // switch 0xf5c & 0xf74 to DFS report + // read peak index hist report + PHY_SetBBReg(priv, 0x19e4, 0x00c00000, 0); // report selection = 0 (peak index) + g_ti_cur[0] = PHY_QueryBBReg(priv, 0xf74, 0xf0000000); + if (g_ti_cur[0] >= priv->g_ti_pre[0]) + g_ti_inc[0] = g_ti_cur[0] - priv->g_ti_pre[0]; + else + g_ti_inc[0] = g_ti_cur[0]; + priv->g_ti_pre[0] = g_ti_cur[0]; + + g_ti_cur[1] = PHY_QueryBBReg(priv, 0xf74, 0x0f000000); + if (g_ti_cur[1] >= priv->g_ti_pre[1]) + g_ti_inc[1] = g_ti_cur[1] - priv->g_ti_pre[1]; + else + g_ti_inc[1] = g_ti_cur[1]; + priv->g_ti_pre[1] = g_ti_cur[1]; + + g_ti_cur[2] = PHY_QueryBBReg(priv, 0xf74, 0x00f00000); + if (g_ti_cur[2] >= priv->g_ti_pre[2]) + g_ti_inc[2] = g_ti_cur[2] - priv->g_ti_pre[2]; + else + g_ti_inc[2] = g_ti_cur[2]; + priv->g_ti_pre[2] = g_ti_cur[2]; + + g_ti_cur[3] = PHY_QueryBBReg(priv, 0xf74, 0x000f0000); + if (g_ti_cur[3] >= priv->g_ti_pre[3]) + g_ti_inc[3] = g_ti_cur[3] - priv->g_ti_pre[3]; + else + g_ti_inc[3] = g_ti_cur[3]; + priv->g_ti_pre[3] = g_ti_cur[3]; + + g_ti_cur[4] = PHY_QueryBBReg(priv, 0xf74, 0x0000f000); + if (g_ti_cur[4] >= priv->g_ti_pre[4]) + g_ti_inc[4] = g_ti_cur[4] - priv->g_ti_pre[4]; + else + g_ti_inc[4] = g_ti_cur[4]; + priv->g_ti_pre[4] = g_ti_cur[4]; + + g_ti_cur[5] = PHY_QueryBBReg(priv, 0xf74, 0x00000f00); + if (g_ti_cur[5] >= priv->g_ti_pre[5]) + g_ti_inc[5] = g_ti_cur[5] - priv->g_ti_pre[5]; + else + g_ti_inc[5] = g_ti_cur[5]; + priv->g_ti_pre[5] = g_ti_cur[5]; + + g_ti_cur[6] = PHY_QueryBBReg(priv, 0xf74, 0x000000f0); + if (g_ti_cur[6] >= priv->g_ti_pre[6]) + g_ti_inc[6] = g_ti_cur[6] - priv->g_ti_pre[6]; + else + g_ti_inc[6] = g_ti_cur[6]; + priv->g_ti_pre[6] = g_ti_cur[6]; + + g_ti_cur[7] = PHY_QueryBBReg(priv, 0xf74, 0x0000000f); + if (g_ti_cur[7] >= priv->g_ti_pre[7]) + g_ti_inc[7] = g_ti_cur[7] - priv->g_ti_pre[7]; + else + g_ti_inc[7] = g_ti_cur[7]; + priv->g_ti_pre[7] = g_ti_cur[7]; + + g_ti_cur[8] = PHY_QueryBBReg(priv, 0xf5c, 0xf0000000); + if (g_ti_cur[8] >= priv->g_ti_pre[8]) + g_ti_inc[8] = g_ti_cur[8] - priv->g_ti_pre[8]; + else + g_ti_inc[8] = g_ti_cur[8]; + priv->g_ti_pre[8] = g_ti_cur[8]; + + g_ti_cur[9] = PHY_QueryBBReg(priv, 0xf5c, 0x0f000000); + if (g_ti_cur[9] >= priv->g_ti_pre[9]) + g_ti_inc[9] = g_ti_cur[9] - priv->g_ti_pre[9]; + else + g_ti_inc[9] = g_ti_cur[9]; + priv->g_ti_pre[9] = g_ti_cur[9]; + + g_ti_cur[10] = PHY_QueryBBReg(priv, 0xf5c, 0x00f00000); + if (g_ti_cur[10] >= priv->g_ti_pre[10]) + g_ti_inc[10] = g_ti_cur[10] - priv->g_ti_pre[10]; + else + g_ti_inc[10] = g_ti_cur[10]; + priv->g_ti_pre[10] = g_ti_cur[10]; + + g_ti_cur[11] = PHY_QueryBBReg(priv, 0xf5c, 0x000f0000); + if (g_ti_cur[11] >= priv->g_ti_pre[0]) + g_ti_inc[11] = g_ti_cur[11] - priv->g_ti_pre[11]; + else + g_ti_inc[11] = g_ti_cur[11]; + priv->g_ti_pre[11] = g_ti_cur[11]; + + g_ti_cur[12] = PHY_QueryBBReg(priv, 0xf5c, 0x0000f000); + if (g_ti_cur[12] >= priv->g_ti_pre[12]) + g_ti_inc[12] = g_ti_cur[12] - priv->g_ti_pre[12]; + else + g_ti_inc[12] = g_ti_cur[12]; + priv->g_ti_pre[12] = g_ti_cur[12]; + + g_ti_cur[13] = PHY_QueryBBReg(priv, 0xf5c, 0x00000f00); + if (g_ti_cur[13] >= priv->g_ti_pre[13]) + g_ti_inc[13] = g_ti_cur[13] - priv->g_ti_pre[13]; + else + g_ti_inc[13] = g_ti_cur[13]; + priv->g_ti_pre[13] = g_ti_cur[13]; + + g_ti_cur[14] = PHY_QueryBBReg(priv, 0xf5c, 0x000000f0); + if (g_ti_cur[14] >= priv->g_ti_pre[14]) + g_ti_inc[14] = g_ti_cur[14] - priv->g_ti_pre[14]; + else + g_ti_inc[14] = g_ti_cur[14]; + priv->g_ti_pre[14] = g_ti_cur[14]; + + g_ti_cur[15] = PHY_QueryBBReg(priv, 0xf5c, 0x0000000f); + if (g_ti_cur[15] >= priv->g_ti_pre[15]) + g_ti_inc[15] = g_ti_cur[15] - priv->g_ti_pre[15]; + else + g_ti_inc[15] = g_ti_cur[15]; + priv->g_ti_pre[15] = g_ti_cur[15]; + + // read pulse width hist report + PHY_SetBBReg(priv, 0x19e4, 0x00c00000, 1); // report selection = 1 (pulse width) + + g_pw_cur[0] = PHY_QueryBBReg(priv, 0xf74, 0xff000000); + if (g_pw_cur[0] >= priv->g_pw_pre[0]) + g_pw_inc[0] = g_pw_cur[0] - priv->g_pw_pre[0]; + else + g_pw_inc[0] = g_pw_cur[0]; + priv->g_pw_pre[0] = g_pw_cur[0]; + + g_pw_cur[1] = PHY_QueryBBReg(priv, 0xf74, 0x00ff0000); + if (g_pw_cur[1] >= priv->g_pw_pre[1]) + g_pw_inc[1] = g_pw_cur[1] - priv->g_pw_pre[1]; + else + g_pw_inc[1] = g_pw_cur[1]; + priv->g_pw_pre[1] = g_pw_cur[1]; + + g_pw_cur[2] = PHY_QueryBBReg(priv, 0xf74, 0x0000ff00); + if (g_pw_cur[2] >= priv->g_pw_pre[2]) + g_pw_inc[2] = g_pw_cur[2] - priv->g_pw_pre[2]; + else + g_pw_inc[2] = g_pw_cur[2]; + priv->g_pw_pre[2] = g_pw_cur[2]; + + g_pw_cur[3] = PHY_QueryBBReg(priv, 0xf74, 0x000000ff); + if (g_pw_cur[3] >= priv->g_pw_pre[3]) + g_pw_inc[3] = g_pw_cur[3] - priv->g_pw_pre[3]; + else + g_pw_inc[3] = g_pw_cur[3]; + priv->g_pw_pre[3] = g_pw_cur[3]; + + g_pw_cur[4] = PHY_QueryBBReg(priv, 0xf5c, 0xff000000); + if (g_pw_cur[4] >= priv->g_pw_pre[4]) + g_pw_inc[4] = g_pw_cur[4] - priv->g_pw_pre[4]; + else + g_pw_inc[4] = g_pw_cur[4]; + priv->g_pw_pre[4] = g_pw_cur[4]; + + g_pw_cur[5] = PHY_QueryBBReg(priv, 0xf5c, 0x00ff0000); + if (g_pw_cur[5] >= priv->g_pw_pre[5]) + g_pw_inc[5] = g_pw_cur[5] - priv->g_pw_pre[5]; + else + g_pw_inc[5] = g_pw_cur[5]; + priv->g_pw_pre[5] = g_pw_cur[5]; + + g_total = g_pw_inc[0] + g_pw_inc[1] + g_pw_inc[2] + g_pw_inc[3] + g_pw_inc[4] + g_pw_inc[5]; + if(g_pw_inc[0] == 0) g0_ratio = 0; + else g0_ratio = g_total / g_pw_inc[0]; + if(g_pw_inc[1] == 0) g1_ratio = 0; + else g1_ratio = g_total / g_pw_inc[1]; + if(g_pw_inc[2] == 0) g2_ratio = 0; + else g2_ratio = g_total / g_pw_inc[2]; + if(g_pw_inc[3]== 0) g3_ratio = 0; + else g3_ratio = g_total / g_pw_inc[3]; + if(g_pw_inc[4]== 0) g4_ratio = 0; + else g4_ratio = g_total / g_pw_inc[4]; + if(g_pw_inc[5] == 0) g5_ratio = 0; + else g5_ratio = g_total / g_pw_inc[5]; + + // read pulse repetition interval hist report + PHY_SetBBReg(priv, 0x19e4, 0x00c00000, 3); // report selection = 3 (pulse repetition interval) + g_pri_cur[0] = PHY_QueryBBReg(priv, 0xf74, 0xff000000); + if (g_pri_cur[0] >= priv->g_pri_pre[0]) + g_pri_inc[0] = g_pri_cur[0] - priv->g_pri_pre[0]; + else + g_pri_inc[0] = g_pri_cur[0]; + priv->g_pri_pre[0] = g_pri_cur[0]; + + g_pri_cur[1] = PHY_QueryBBReg(priv, 0xf74, 0x00ff0000); + if (g_pri_cur[1] >= priv->g_pri_pre[1]) + g_pri_inc[1] = g_pri_cur[1] - priv->g_pri_pre[1]; + else + g_pri_inc[1] = g_pri_cur[1]; + priv->g_pri_pre[1] = g_pri_cur[1]; + + g_pri_cur[2] = PHY_QueryBBReg(priv, 0xf74, 0x0000ff00); + if (g_pri_cur[2] >= priv->g_pri_pre[2]) + g_pri_inc[2] = g_pri_cur[2] - priv->g_pri_pre[2]; + else + g_pri_inc[2] = g_pri_cur[2]; + priv->g_pri_pre[2] = g_pri_cur[2]; + + g_pri_cur[3] = PHY_QueryBBReg(priv, 0xf74, 0x000000ff); + if (g_pri_cur[3] >= priv->g_pri_pre[3]) + g_pri_inc[3] = g_pri_cur[3] - priv->g_pri_pre[3]; + else + g_pri_inc[3] = g_pri_cur[3]; + priv->g_pri_pre[3] = g_pri_cur[3]; + + g_pri_cur[4] = PHY_QueryBBReg(priv, 0xf5c, 0xff000000); + if (g_pri_cur[4] >= priv->g_pri_pre[4]) + g_pri_inc[4] = g_pri_cur[4] - priv->g_pri_pre[4]; + else + g_pri_inc[4] = g_pri_cur[4]; + priv->g_pri_pre[4] = g_pri_cur[4]; + + g_pri_cur[5] = PHY_QueryBBReg(priv, 0xf5c, 0x00ff0000); + if (g_pri_cur[5] >= priv->g_pri_pre[5]) + g_pri_inc[5] = g_pri_cur[5] - priv->g_pri_pre[5]; + else + g_pri_inc[5] = g_pri_cur[5]; + priv->g_pri_pre[5] = g_pri_cur[5]; + + need_reset = 0; + for(i = 0; i < 6; i++){ + if((priv->g_pw_pre[i]==255) || (priv->g_pri_pre[i] == 255)){ + need_reset = 1; + } + } + if(need_reset){ + PHY_SetBBReg(priv, 0x19b4, 0x10000000, 1); // reset histogram report + PHY_SetBBReg(priv, 0x19b4, 0x10000000, 0); // continue histogram report + for(i = 0; i < 6; i++){ + priv->g_pw_pre[i]=0; + priv->g_pri_pre[i]=0; + } + for(i = 0; i < 16; i++){ + priv->g_ti_pre[i]=0; + } + } + + if(DFS_tri_short_pulse || DFS_tri_long_pulse){ + if(priv->pshare->rf_ft_var.dfs_print_hist_report){ + panic_printk("peak index hist\n"); + panic_printk("g0 = %d, g1 = %d, g2 = %d, g3 = %d, g4 = %d, g5 = %d, g6 = %d, g7 = %d\n", g_ti_inc[0], g_ti_inc[1], g_ti_inc[2], g_ti_inc[3], g_ti_inc[4], g_ti_inc[5], g_ti_inc[6], g_ti_inc[7]); + panic_printk("g8 = %d, g9 = %d, g10 = %d, g11 = %d, g12 = %d, g13 = %d, g14 = %d, g15 = %d\n", g_ti_inc[8], g_ti_inc[9], g_ti_inc[10], g_ti_inc[11], g_ti_inc[12], g_ti_inc[13], g_ti_inc[14], g_ti_inc[15]); + panic_printk("pulse width hist\n"); + panic_printk("g0 = %d, g1 = %d, g2 = %d, g3 = %d, g4 = %d, g5 = %d\n",g_pw_inc[0], g_pw_inc[1], g_pw_inc[2], g_pw_inc[3], g_pw_inc[4], g_pw_inc[5]); + panic_printk("g0_ratio = %d, g1_ratio = %d, g2_ratio = %d, g3_ratio = %d, g4_ratio = %d, g5_ratio = %d\n", g0_ratio, g1_ratio, g2_ratio, g3_ratio, g4_ratio, g5_ratio); + panic_printk("pulse repetition interval hist\n"); + panic_printk("g0 = %d, g1 = %d, g2 = %d, g3 = %d, g4 = %d, g5 = %d\n",g_pri_inc[0], g_pri_inc[1], g_pri_inc[2], g_pri_inc[3], g_pri_inc[4], g_pri_inc[5]); + } + + if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) { + if((priv->pmib->dot11RFEntry.dot11channel >= 52) && (priv->pmib->dot11RFEntry.dot11channel <= 64)){ + // classify radar by pulse width hist + if(g_pw_inc[1] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("MKK w53 radar type1 is detected!\n"); + } + } + else if(g_pw_inc[3] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("MKK w53 radar type2 is detected!\n"); + } + } + else{ + DFS_tri_long_pulse = 0; + DFS_tri_short_pulse = 0; + } + } + else{ + if (DFS_tri_long_pulse){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("MKK w56 radar type7 is detected!\n"); + } + } + else{ + if(g_pw_inc[0] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("MKK w56 radar type1 is detected!\n"); + } + } + else if(g_pw_inc[1] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("MKK w56 radar type2 or type8 is detected!\n"); + } + } + else if(g_pw_inc[2] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("MKK w56 radar type3 is detected!\n"); + } + } + else if(g_pw_inc[1]+g_pw_inc[2]+g_pw_inc[3] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("MKK w56 radar type4 is detected!\n"); + } + } + else if(g_pw_inc[4] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("MKK w56 radar type5 is detected!\n"); + } + } + else if(g_pw_inc[5] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("MKK w56 radar type6 is detected!\n"); + } + } + else{ + DFS_tri_short_pulse = 0; + } + } + } + } + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI){ + } + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_FCC){ + if (DFS_tri_long_pulse){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("FCC radar type5 is detected!\n"); + } + } + else{ + if(g_pw_inc[1] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("FCC radar type1 or type6 is detected!\n"); + } + } + else if(g_pw_inc[1] + g_pw_inc[2]>= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("FCC radar type2 is detected!\n"); + } + } + else if(g_pw_inc[3] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("FCC radar type3 is detected!\n"); + } + } + else if(g_pw_inc[4] >= short_pulse_th + 1){ + if(priv->pshare->rf_ft_var.dfs_radar_diff_print){ + panic_printk("FCC radar type4 is detected!\n"); + } + } + else{ + DFS_tri_short_pulse = 0; + } + } + } + else{ + } + } + +} +#endif //#if defined(CONFIG_WLAN_HAL_8814AE) + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dmem.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dmem.c new file mode 100755 index 000000000..9993e8622 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dmem.c @@ -0,0 +1,286 @@ +/* + * D-MEM supporting module for RTL8190 802.11N wireless NIC on RTL865x platform + * + * $Id: 8192cd_dmem.c,v 1.2 2010/01/19 06:04:03 jimmylin Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifdef __ECOS +#include +#include +#include +#include +#endif + +#ifndef _8192CD_DMEM_C_ +#define _8192CD_DMEM_C_ + +#include "./8192cd.h" +//#include "./8190n_fastExtDev.h" +#include "./8192cd_cfg.h" + +#ifdef RTL8192CD_VARIABLE_USED_DMEM +#include "./8192cd_dmem.h" + +#define RTL8192CD_MAX_SPEEDUP_STA 2 +#define RTL8192CD_SPEEDUP_PRIV_COUNT 1 + +/* ========================== All variables using D-MEM ========================== */ +static void rtl8192cd_dmem_AID_OBJ_init(void); +static void *rtl8192cd_dmem_AID_OBJ_alloc(void *miscInfo); +static void rtl8192cd_dmem_AID_OBJ_free(void *miscInfo); + +static void rtl8192cd_dmem_pmib_init(void); +static void *rtl8192cd_dmem_pmib_alloc(void *miscInfo); +static void rtl8192cd_dmem_pmib_free(void *miscInfo); + +#ifdef PRIV_STA_BUF + extern struct aid_obj *alloc_sta_obj(struct rtl8192cd_priv*); + extern void free_sta_obj(struct rtl8192cd_priv *priv, struct aid_obj *obj); +#endif + +static _rtl8192cd_dmem_callBack_t _8192cd_dmem_callBack_list[] = +{ + /* ID Init CallBack Allocate CallBack Free CallBack */ + { AID_OBJ, rtl8192cd_dmem_AID_OBJ_init, rtl8192cd_dmem_AID_OBJ_alloc, rtl8192cd_dmem_AID_OBJ_free}, + { PMIB, rtl8192cd_dmem_pmib_init, rtl8192cd_dmem_pmib_alloc, rtl8192cd_dmem_pmib_free}, + /* ==================================================================== */ + { _RTL8192CD_DMEM_ITEM_MAX, NULL, NULL}, +}; + +/* ========================== External APIs of D-MEM module ========================== */ + +/* + Initiation function for DMEM library +*/ +void rtl8192cd_dmem_init( void ) +{ + _rtl8192cd_dmem_callBack_t *ptr; + + ptr = &_8192cd_dmem_callBack_list[0]; + + while ( (ptr->id > _RTL8192CD_DMEM_ITEM_MIN) && + (ptr->id < _RTL8192CD_DMEM_ITEM_MAX)) + { + /* Call the Callback function to decide the memory of allocated */ + if (ptr->initCallBackFunc) + { + ((_dummyFunc_void_void)(ptr->initCallBackFunc))(); + } + + /* Next Entry */ + ptr ++; + } +} + +void *rtl8192cd_dmem_alloc( enum _RTL8192CD_DMEM_ITEM_ID id, void *miscInfo ) +{ + void *retval; + _rtl8192cd_dmem_callBack_t *ptr; + + retval = NULL; + + if ( (id <= _RTL8192CD_DMEM_ITEM_MIN) || + (id >= _RTL8192CD_DMEM_ITEM_MAX)) + { + printk("%s %d : ERROR (%d)\n", __FUNCTION__, __LINE__, id); + goto out; + } + + ptr = &_8192cd_dmem_callBack_list[0]; + + while ( ptr->allcateCallBackFunc ) + { + if ( ptr->id == id ) + { + /* Call the Callback function to decide the memory of allocated */ + retval = ((_dummyFunc_voidStar_voidStar)(ptr->allcateCallBackFunc))(miscInfo); + goto out; + } + /* Next Entry */ + ptr ++; + } + +out: + return retval; +} + +void rtl8192cd_dmem_free( enum _RTL8192CD_DMEM_ITEM_ID id, void *miscInfo ) +{ + _rtl8192cd_dmem_callBack_t *ptr; + + if ( (id <= _RTL8192CD_DMEM_ITEM_MIN) || + (id >= _RTL8192CD_DMEM_ITEM_MAX)) + { + printk("%s %d : ERROR (%d)\n", __FUNCTION__, __LINE__, id); + goto out; + } + + ptr = &_8192cd_dmem_callBack_list[0]; + + while ( ptr->freeCallBackFunc ) + { + if ( ptr->id == id ) + { + /* Call the Callback function to decide the memory of allocated */ + ((_dummyFunc_void_voidStar)(ptr->freeCallBackFunc))(miscInfo); + goto out; + } + /* Next Entry */ + ptr ++; + } + +out: + return; +} + + +/* ========================== Internal APIs for per-variable of D-MEM module ========================== */ + +/* ============================================== + * + * AID_OBJ + * + * + * ============================================== */ +__DRAM_IN_865X struct aid_obj _rtl8192cd_aid_Array[RTL8192CD_MAX_SPEEDUP_STA]; +void *_rtl8192cd_aid_externalMem_Array[NUM_STAT]; + +static void rtl8192cd_dmem_AID_OBJ_init(void) +{ + memset(_rtl8192cd_aid_Array, 0, sizeof(struct aid_obj) * RTL8192CD_MAX_SPEEDUP_STA); + memset(_rtl8192cd_aid_externalMem_Array, 0, sizeof(_rtl8192cd_aid_externalMem_Array)); +} + +static void *rtl8192cd_dmem_AID_OBJ_alloc(void *miscInfo) +{ + /* For AID_OBJ : miscInfo would be [unsigned int *] to decision the index of aidarray to allocate */ + unsigned int index = *((unsigned int*)miscInfo); + + if ( (index < 0) || + (index >= NUM_STAT)) + { + printk("%s %d : ERROR ( Index : %d )\n", __FUNCTION__, __LINE__, index); + return NULL; + } + + /* Allocate from external memory */ + if ( index >= RTL8192CD_MAX_SPEEDUP_STA ) + { +#ifdef PRIV_STA_BUF + _rtl8192cd_aid_externalMem_Array[index] = alloc_sta_obj(NULL); +#else + _rtl8192cd_aid_externalMem_Array[index] = kmalloc(sizeof(struct aid_obj), GFP_ATOMIC); +#endif + if (_rtl8192cd_aid_externalMem_Array[index] == NULL) + { + printk("%s %d : Error : Allocation FAILED!\n", __FUNCTION__, __LINE__); + return NULL; + } + return _rtl8192cd_aid_externalMem_Array[index]; + } + + memset(&(_rtl8192cd_aid_Array[index]), 0, sizeof(struct aid_obj)); + + return (void*)(&(_rtl8192cd_aid_Array[index])); +} + +static void rtl8192cd_dmem_AID_OBJ_free(void *miscInfo) +{ + /* For AID_OBJ : miscInfo would be [unsigned int *] to decision the index of aidarray to free */ + unsigned int index = *((unsigned int*)miscInfo); + + if ( (index < 0) || + (index >= NUM_STAT)) + { + printk("%s %d : ERROR ( Index : %d )\n", __FUNCTION__, __LINE__, index); + return; + } + + /* Free memory to external memory module */ + if ( index >= RTL8192CD_MAX_SPEEDUP_STA ) + { + if ( _rtl8192cd_aid_externalMem_Array[index] ) + { +#ifdef PRIV_STA_BUF + free_sta_obj(NULL, _rtl8192cd_aid_externalMem_Array[index]); +#else + kfree(_rtl8192cd_aid_externalMem_Array[index]); +#endif + _rtl8192cd_aid_externalMem_Array[index] = NULL; + } + + return; + } + + memset(&(_rtl8192cd_aid_Array[index]), 0, sizeof(struct aid_obj)); +} + + +/* =================== The following variable are mapped to PRIV =================== */ + +/* ============================================== + * + * PMIB + * + * + * ============================================== */ +__DRAM_IN_865X struct wifi_mib _rtl8192cd_pmib[RTL8192CD_SPEEDUP_PRIV_COUNT]; +int _rtl8192cd_pmib_usageMap[RTL8192CD_SPEEDUP_PRIV_COUNT]; + +static void rtl8192cd_dmem_pmib_init(void) +{ + memset(_rtl8192cd_pmib_usageMap, 0, sizeof(int) * RTL8192CD_SPEEDUP_PRIV_COUNT); + memset(_rtl8192cd_pmib, 0, sizeof(struct wifi_mib) * RTL8192CD_SPEEDUP_PRIV_COUNT); +} + +static void *rtl8192cd_dmem_pmib_alloc(void *miscInfo) +{ + int idx ; + + /* miscInfo is useless */ + for ( idx = 0 ; idx < RTL8192CD_SPEEDUP_PRIV_COUNT ; idx ++ ) + { + if ( _rtl8192cd_pmib_usageMap[idx] == 0 ) + { /* Unused entry : use it */ + _rtl8192cd_pmib_usageMap[idx] = 1; + memset(&(_rtl8192cd_pmib[idx]), 0, sizeof(struct wifi_mib)); + return &(_rtl8192cd_pmib[idx]); + } + } + + /* Allocate from externel memory if speedup PMIB is exhausted */ + return kmalloc(sizeof(struct wifi_mib), GFP_ATOMIC); + +} + +static void rtl8192cd_dmem_pmib_free(void *miscInfo) +{ + int idx; + + /* miscInfo is pointed to the address of PMIB to free */ + + /* Free PMIB if it is speeded up by DMEM */ + for ( idx = 0 ; idx < RTL8192CD_SPEEDUP_PRIV_COUNT ; idx ++ ) + { + if ( (unsigned long)(&(_rtl8192cd_pmib[idx])) == (unsigned long)miscInfo ) + { /* Entry is found : free it */ + memset(&(_rtl8192cd_pmib[idx]), 0, sizeof(struct wifi_mib)); + _rtl8192cd_pmib_usageMap[idx] = 0; + return; + } + } + + /* It would be allocated from external memory: kfree it */ + kfree(miscInfo); + +} +#endif // RTL8192CD_VARIABLE_USED_DMEM + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dmem.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dmem.h new file mode 100755 index 000000000..5754202ea --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_dmem.h @@ -0,0 +1,44 @@ +/* + * Header of D-MEM supporting module for RTL8190 802.11N wireless NIC on RTL865x platform + * + * $Id: 8192cd_dmem.h,v 1.1 2009/11/06 12:26:48 victoryman Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_DMEM_H +#define _8192CD_DMEM_H + +/* ========================= External ========================= */ + +enum _RTL8192CD_DMEM_ITEM_ID { + _RTL8192CD_DMEM_ITEM_MIN, + /* ============================== Add here ============================== */ + AID_OBJ, + PMIB, + /* =================================================================== */ + _RTL8192CD_DMEM_ITEM_MAX, +}; + +void rtl8192cd_dmem_init( void ); +void *rtl8192cd_dmem_alloc( enum _RTL8192CD_DMEM_ITEM_ID id, void *miscInfo ); +void rtl8192cd_dmem_free( enum _RTL8192CD_DMEM_ITEM_ID id, void *miscInfo ); + + +/* ========================= Internal ========================= */ +typedef void* (*_dummyFunc_voidStar_voidStar)(void*); +typedef void (*_dummyFunc_void_voidStar)(void*); +typedef void (*_dummyFunc_void_void)(void); +typedef struct _rtl8192cd_dmem_list_s +{ + int id; + void * initCallBackFunc; + void * allcateCallBackFunc; + void * freeCallBackFunc; +} _rtl8192cd_dmem_callBack_t; + +#endif /* _8192CD_DMEM_H */ diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_eeprom.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_eeprom.c new file mode 100755 index 000000000..03163d35b --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_eeprom.c @@ -0,0 +1,579 @@ +/* + * Routines to read and write eeprom + * + * $Id: 8192cd_eeprom.c,v 1.1 2009/11/06 12:26:48 victoryman Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_EEPROM_C_ +#if 0 +#ifdef __KERNEL__ +#include +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_hw.h" +#include "./8192cd_util.h" +#include "./8192cd_debug.h" + + + +#define VOID void +#define EEPROM_MAX_SIZE 256 +#define CSR_EEPROM_CONTROL_REG _9346CR_ +#define CLOCK_RATE 50 //100us + + +static VOID ShiftOutBits(struct rtl8192cd_priv *priv, USHORT data, USHORT count); +static USHORT ShiftInBits(struct rtl8192cd_priv *priv); +static VOID RaiseClock(struct rtl8192cd_priv *priv, USHORT *x); +static VOID LowerClock(struct rtl8192cd_priv *priv, USHORT *x); +static VOID EEpromCleanup(struct rtl8192cd_priv *priv); +static USHORT WaitEEPROMCmdDone(struct rtl8192cd_priv *priv); +static VOID StandBy(struct rtl8192cd_priv *priv); + + +//***************************************************************************** +// +// I/O based Read EEPROM Routines +// +//***************************************************************************** +//----------------------------------------------------------------------------- +// Procedure: ReadEEprom +// +// Description: This routine serially reads one word out of the EEPROM. +// +// Arguments: +// Reg - EEPROM word to read. +// +// Returns: +// Contents of EEPROM word (Reg). +//----------------------------------------------------------------------------- +static USHORT +ReadEEprom( + struct rtl8192cd_priv *priv, + UCHAR AddressSize, + USHORT Reg) +{ + USHORT x; + USHORT data; + + // select EEPROM, reset bits, set EECS + x = RTL_R8(CSR_EEPROM_CONTROL_REG); + + x &= ~(EEDI | EEDO | EESK | CR9346_EEM0); + x |= CR9346_EEM1 | EECS; + RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)x); + + // write the read opcode and register number in that order + // The opcode is 3bits in length, reg is 6 bits long + ShiftOutBits(priv, EEPROM_READ_OPCODE, 3); + ShiftOutBits(priv, Reg, AddressSize); + + // Now read the data (16 bits) in from the selected EEPROM word + data = ShiftInBits(priv); + + EEpromCleanup(priv); + return data; +} + +//----------------------------------------------------------------------------- +// Procedure: ShiftOutBits +// +// Description: This routine shifts data bits out to the EEPROM. +// +// Arguments: +// data - data to send to the EEPROM. +// count - number of data bits to shift out. +// +// Returns: (none) +//----------------------------------------------------------------------------- + +static VOID +ShiftOutBits( + struct rtl8192cd_priv *priv, + USHORT data, + USHORT count) +{ + USHORT x,mask; + + mask = 0x01 << (count - 1); + x = RTL_R8(CSR_EEPROM_CONTROL_REG); + + x &= ~(EEDO | EEDI); + + do + { + x &= ~EEDI; + if(data & mask) + x |= EEDI; + + RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)x); + delay_us(CLOCK_RATE); + RaiseClock(priv, &x); + LowerClock(priv, &x); + mask = mask >> 1; + } while(mask); + + x &= ~EEDI; + RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)x); +} + +//----------------------------------------------------------------------------- +// Procedure: ShiftInBits +// +// Description: This routine shifts data bits in from the EEPROM. +// +// Arguments: +// +// Returns: +// The contents of that particular EEPROM word +//----------------------------------------------------------------------------- + +static USHORT +ShiftInBits( + struct rtl8192cd_priv *priv) +{ + USHORT x,d,i; + x = RTL_R8(CSR_EEPROM_CONTROL_REG); + + x &= ~( EEDO | EEDI); + d = 0; + + for(i=0; i<16; i++) + { + d = d << 1; + RaiseClock(priv, &x); + + x = RTL_R8(CSR_EEPROM_CONTROL_REG); + + x &= ~(EEDI); + if(x & EEDO) + d |= 1; + + LowerClock(priv, &x); + } + + return d; +} + +//----------------------------------------------------------------------------- +// Procedure: RaiseClock +// +// Description: This routine raises the EEPOM's clock input (EESK) +// +// Arguments: +// x - Ptr to the EEPROM control register's current value +// +// Returns: (none) +//----------------------------------------------------------------------------- + +static VOID +RaiseClock( + struct rtl8192cd_priv *priv, + USHORT *x) +{ + *x = *x | EESK; + RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)(*x)); + delay_us(CLOCK_RATE); +} + + +//----------------------------------------------------------------------------- +// Procedure: LowerClock +// +// Description: This routine lower's the EEPOM's clock input (EESK) +// +// Arguments: +// x - Ptr to the EEPROM control register's current value +// +// Returns: (none) +//----------------------------------------------------------------------------- + +static VOID +LowerClock( + struct rtl8192cd_priv *priv, + USHORT *x) +{ + *x = *x & ~EESK; + RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)(*x)); + delay_us(CLOCK_RATE); +} + +//----------------------------------------------------------------------------- +// Procedure: EEpromCleanup +// +// Description: This routine returns the EEPROM to an idle state +// +// Arguments: +// +// Returns: (none) +//----------------------------------------------------------------------------- + +static VOID +EEpromCleanup( + struct rtl8192cd_priv *priv) +{ + USHORT x; + x = RTL_R8(CSR_EEPROM_CONTROL_REG); + + x &= ~(EECS | EEDI); + RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)x); + + RaiseClock(priv, &x); + LowerClock(priv, &x); +} + +//***************************************************************************** +// +// EEPROM Write Routines +// +//***************************************************************************** + +//----------------------------------------------------------------------------- +// Procedure: D100UpdateChecksum +// +// Description: Calculates the checksum and writes it to the EEProm. This +// routine assumes that the checksum word is the last word in +// a 64 word EEPROM. It calculates the checksum accroding to +// the formula: Checksum = 0xBABA - (sum of first 63 words). +// +// Arguments: +// Adapter - Ptr to this card's adapter data structure +// +// Returns: (none) +//----------------------------------------------------------------------------- + +/*static VOID +UpdateChecksum( + struct rtl8192cd_priv *priv) +{ + USHORT Checksum=0; +// USHORT Iter; + +// for (Iter = 0; Iter < 0x3F; Iter++) +// Checksum += ReadEEprom( CSRBaseIoAddress, Iter ); + + Checksum = (USHORT)0xBABA - Checksum; +// WriteEEprom( CSRBaseIoAddress, 0x3F, Checksum ); +}*/ + +//----------------------------------------------------------------------------- +// Procedure: WriteEEprom +// +// Description: This routine writes a word to a specific EEPROM location. +// +// Arguments: +// Adapter - Ptr to this card's adapter data structure. +// reg - The EEPROM word that we are going to write to. +// data - The data (word) that we are going to write to the EEPROM. +// +// Returns: (none) +//----------------------------------------------------------------------------- + +static VOID +WriteEEprom( + struct rtl8192cd_priv *priv, + UCHAR AddressSize, + USHORT reg, + USHORT data) +{ + UCHAR x; + + // select EEPROM, mask off ASIC and reset bits, set EECS + x = RTL_R8(CSR_EEPROM_CONTROL_REG); + + x &= ~(EEDI | EEDO | EESK | CR9346_EEM0); + x |= CR9346_EEM1 | EECS; + RTL_W8(CSR_EEPROM_CONTROL_REG, x); + + ShiftOutBits(priv, EEPROM_EWEN_OPCODE, 5); + /////ShiftOutBits(CSRBaseIoAddress, reg, 4); + ShiftOutBits(priv, 0, 6); + + StandBy(priv); + + // Erase this particular word. Write the erase opcode and register + // number in that order. The opcode is 3bits in length; reg is 6 bits long. + ShiftOutBits(priv, EEPROM_ERASE_OPCODE, 3); + ShiftOutBits(priv, reg, AddressSize); + + if (WaitEEPROMCmdDone(priv) == FALSE) + { + return; + } + + StandBy(priv); + + // write the new word to the EEPROM + + // send the write opcode the EEPORM + ShiftOutBits(priv, EEPROM_WRITE_OPCODE, 3); + + // select which word in the EEPROM that we are writing to. + ShiftOutBits(priv, reg, AddressSize); + + // write the data to the selected EEPROM word. + ShiftOutBits(priv, data, 16); + + if (WaitEEPROMCmdDone(priv) == FALSE) + { +// DbgPrint("D100: Failed EEPROM Write"); + return; + } + + StandBy(priv); + + ShiftOutBits(priv, EEPROM_EWDS_OPCODE, 5); + ShiftOutBits(priv, reg, 4); + + EEpromCleanup(priv); + return; +} + +//----------------------------------------------------------------------------- +// Procedure: WaitEEPROMCmdDone +// +// Description: This routine waits for the the EEPROM to finish its command. +// Specifically, it waits for EEDO (data out) to go high. +// +// Arguments: +// Adapter - Ptr to this card's adapter data structure. +// +// Returns: +// TRUE - If the command finished +// FALSE - If the command never finished (EEDO stayed low) +//----------------------------------------------------------------------------- + +static USHORT +WaitEEPROMCmdDone( + struct rtl8192cd_priv *priv) +{ + UCHAR x; + USHORT i; + + StandBy(priv); + for (i=0; i<200; i++) + { + x = RTL_R8(CSR_EEPROM_CONTROL_REG); + if (x & EEDO) + return (TRUE); + delay_us(CLOCK_RATE); + } + return FALSE; +} + + +//----------------------------------------------------------------------------- +// Procedure: StandBy +// +// Description: This routine lowers the EEPROM chip select (EECS) for a few +// microseconds. +// +// Arguments: +// Adapter - Ptr to this card's adapter data structure. +// +// Returns: (none) +//----------------------------------------------------------------------------- + +static VOID +StandBy( + struct rtl8192cd_priv *priv) +{ + UCHAR x; + + x = RTL_R8(CSR_EEPROM_CONTROL_REG); + + x &= ~(EECS | EESK); + RTL_W8(CSR_EEPROM_CONTROL_REG, x); + + delay_us(CLOCK_RATE); + x |= EECS; + RTL_W8(CSR_EEPROM_CONTROL_REG, x); + delay_us(CLOCK_RATE); +} + + +//***************************************************************************** +// +// Main routines to read and write EEPROM +// +//***************************************************************************** +#define NUM_11A_CHANNEL 46 +const UCHAR ChannelNumberListOf11a[] = { + 26, 28, 30, 32, + 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, + 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, + 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, + 149, 153, 157, 161 +}; +#define READ_EEPROM(addr) ReadEEprom(priv, EepromAddressSize, addr) +#define WRITE_EEPROM(a,d) WriteEEprom(priv, EepromAddressSize, a, d) + +int ReadAdapterInfo(struct rtl8192cd_priv *priv, int entry_id, void *data) +{ + USHORT Index; + USHORT usValue; + ULONG curRCR; + UCHAR EepromAddressSize; + UCHAR TxPowerLevel[64]; + + if (!priv->EE_Cached) + { + curRCR = RTL_R32(_RCR_); + EepromAddressSize = (curRCR & _9356SEL_)? 8 : 6; + + // ID + priv->EE_ID = (unsigned int)READ_EEPROM(EEPROM_ID); + DEBUG_INFO("ID 0x%04X\n", (USHORT)priv->EE_ID); + if (priv->EE_ID != RTL8180_EEPROM_ID) { + DEBUG_INFO("ID is invalid\n"); + priv->EE_AutoloadFail = TRUE; + } + else + priv->EE_AutoloadFail = FALSE; + + // Version +// priv->EE_Version = (unsigned int)READ_EEPROM((USHORT)(EEPROM_VERSION >> 1)); + usValue = READ_EEPROM(0x7C >> 1); + priv->EE_Version = ((usValue&0xff00)>>8); + DEBUG_INFO("Version 0x%x\n", (USHORT)priv->EE_Version); + + // MAC address + for (Index = 0; Index < 6; Index += 2) { + usValue = READ_EEPROM((USHORT)((EEPROM_NODE_ADDRESS_BYTE_0 + Index)>>1)); + priv->EE_Mac[Index] = usValue & 0xff; + priv->EE_Mac[Index+1] = ((usValue&0xff00) >> 8); + } + DEBUG_INFO("Mac %02X-%02X-%02X-%02X-%02X-%02X\n", + priv->EE_Mac[0], priv->EE_Mac[1], priv->EE_Mac[2], priv->EE_Mac[3], + priv->EE_Mac[4], priv->EE_Mac[5]); + + // for identifying empty EEPROM + if (!priv->EE_AutoloadFail) + { + // Tx Power Level + memset(priv->EE_TxPower_CCK, 0, sizeof(priv->EE_TxPower_CCK)); + for (Index = 0; Index < MAX_CCK_CHANNEL_NUM; Index += 2) { + usValue = READ_EEPROM((USHORT)((EEPROM_TX_POWER_LEVEL_0 + Index) >> 1)); + *((USHORT *)(&priv->EE_TxPower_CCK[Index])) = usValue; + } + + memset(priv->EE_TxPower_OFDM, 0, sizeof(priv->EE_TxPower_OFDM)); + for (Index = 0; Index < NUM_11A_CHANNEL; Index += 2) { + usValue = READ_EEPROM((USHORT)((EEPROM_11A_CHANNEL_TX_POWER_LEVEL_OFFSET + Index) >> 1)); + *((USHORT *)(&TxPowerLevel[Index])) = usValue; + } + for (Index = 0; Index < NUM_11A_CHANNEL; Index++) + priv->EE_TxPower_OFDM[ChannelNumberListOf11a[Index] - 1] = TxPowerLevel[Index]; + + for (Index = 0; Index < MAX_CCK_CHANNEL_NUM; Index += 2) { + usValue = READ_EEPROM((USHORT)((EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET + Index) >> 1)); + *((USHORT *)(&TxPowerLevel[Index])) = usValue; + } + for (Index = 0; Index < MAX_CCK_CHANNEL_NUM; Index++) + priv->EE_TxPower_OFDM[Index] = TxPowerLevel[Index]; + + #ifdef _DEBUG_RTL8192CD_ + if (rtl8192cd_debug_info & _MODULE_DEFINE) { + extern void debug_out(char *label, unsigned char *data, int data_length); + debug_out("EEProm CCK TxPower", priv->EE_TxPower_CCK, MAX_CCK_CHANNEL_NUM); + debug_out("EEProm OFDM TxPower", priv->EE_TxPower_OFDM, MAX_OFDM_CHANNEL_NUM); + } + #endif + + // RF chip id +// priv->EE_RFTypeID = (unsigned int)(READ_EEPROM((USHORT)(EEPROM_RF_CHIP_ID >> 1)) & 0x00f); + priv->EE_RFTypeID = (unsigned int)(READ_EEPROM((USHORT)(0x28 >> 1)) & 0x80 ) >> 7; + DEBUG_INFO("RF ID 0x%02X\n", (UCHAR)priv->EE_RFTypeID); + + // AnaParm + usValue = READ_EEPROM((USHORT)((EEPROM_ANA_PARM + 2) >> 1)); + priv->EE_AnaParm = (unsigned int)(usValue << 16); + usValue = READ_EEPROM((USHORT)(EEPROM_ANA_PARM >> 1)); + priv->EE_AnaParm |= usValue; + DEBUG_INFO("AnaParm 0x%08X\n", priv->EE_AnaParm); + usValue = READ_EEPROM((USHORT)((EEPROM_ANA_PARM2 + 2) >> 1)); + priv->EE_AnaParm2 = (unsigned int)(usValue << 16); + usValue = READ_EEPROM((USHORT)(EEPROM_ANA_PARM2 >> 1)); + priv->EE_AnaParm2 |= usValue; + DEBUG_INFO("AnaParm2 0x%08X\n", priv->EE_AnaParm2); + //add CrystalCap, joshua 20080502 + priv->EE_CrystalCap = (((unsigned int) READ_EEPROM( 0x2A >> 1)) & 0xf000) >> 12; + priv->pmib->dot11RFEntry.crystalCap = priv->EE_CrystalCap; + DEBUG_INFO("CrystalCap 0x%08X\n", priv->EE_CrystalCap); + } + + priv->EE_Cached = 1; + } + + if ((data != NULL) && (!priv->EE_AutoloadFail)) + { + switch(entry_id) + { + case EEPROM_RF_CHIP_ID: + *((UCHAR *)data) = (UCHAR)priv->EE_RFTypeID; + break; + + case EEPROM_NODE_ADDRESS_BYTE_0: + memcpy(data, priv->EE_Mac, MACADDRLEN); + break; + + case EEPROM_TX_POWER_LEVEL_0: + memcpy(data, priv->EE_TxPower_CCK, MAX_CCK_CHANNEL_NUM); + break; + + case EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET: + memcpy(data, priv->EE_TxPower_OFDM, MAX_OFDM_CHANNEL_NUM); + break; + + default: + DEBUG_INFO("not support this id yet\n"); + return 0; + } + return 1; + } + else + return 0; +} + + +int WriteAdapterInfo(struct rtl8192cd_priv *priv, int entry_id, void *data) +{ + USHORT Index; + USHORT usValue; + ULONG curRCR; + UCHAR EepromAddressSize; + + priv->EE_Cached = 0; + curRCR = RTL_R32(_RCR_); + EepromAddressSize = (curRCR & _9356SEL_)? 8 : 6; + + switch(entry_id) + { + case EEPROM_TX_POWER_LEVEL_0: + Index = ((USHORT)((int)data)) & 0xfffe; + usValue = *((USHORT *)(&priv->EE_TxPower_CCK[Index])); + WRITE_EEPROM((USHORT)((EEPROM_TX_POWER_LEVEL_0 + Index) >> 1), usValue); + break; + + case EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET: + Index = ((USHORT)((int)data)) & 0xfffe; + usValue = *((USHORT *)(&priv->EE_TxPower_OFDM[Index])); + WRITE_EEPROM((USHORT)((EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET + Index) >> 1), usValue); + break; + + default: + return 0; + } + return 1; +} +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_headers.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_headers.h new file mode 100755 index 000000000..6ccb7b450 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_headers.h @@ -0,0 +1,2626 @@ +/* + * Headler file defines global functions PROTO types + * + * $Id: 8192cd_headers.h,v 1.32.2.22 2011/01/11 13:48:37 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/*----------------------------------------------------------------------------- + This file define the header files +------------------------------------------------------------------------------*/ + +#ifndef _8192CD_HEADERS_H_ +#define _8192CD_HEADERS_H_ + +#ifdef __KERNEL__ +#include +#endif + +#ifdef __ECOS +#include +#include +#include +#endif + +#include "./8192cd_tx.h" + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) +#include "HalPwrSeqCmd.h" +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE +#if defined(CONFIG_PCI_HCI) +#include "./WlanHAL/RTL88XX/RTL8192E/RTL8192EE/Hal8192EEDef.h" +#elif defined(CONFIG_SDIO_HCI) +#include "./WlanHAL/RTL88XX/RTL8192E/RTL8192ES/Hal8192ESDef.h" +#endif +#endif + +#ifdef CONFIG_WLAN_HAL_8814AE +#include "./WlanHAL/RTL88XX/RTL8814A/RTL8814AE/Hal8814AEDef.h" +#endif + +#ifdef BEAMFORMING_SUPPORT +#include "Beamforming.h" +#endif + +#ifdef SMP_SYNC +#include +#endif + +#ifdef P2P_DEBUGMSG +#define P2P_DEBUG(fmt, args...) (panic_printk("[%s %d][%s]:"fmt,__FUNCTION__ , __LINE__ ,priv->dev->name, ## args)) +#define P2P_TAG_PRINT(fmt, args...) (panic_printk("Tag:"fmt, ## args)) +#define P2P_PRINT(fmt, args...) ( panic_printk(" "fmt,## args)) +#define MAC_PRINT(fmt) ( panic_printk("%02X%02X%02X:%02X%02X%02X\n",fmt[0],fmt[1],fmt[2],fmt[3],fmt[4],fmt[5])) + +#define PDEBUG(fmt, args...) (panic_printk(""fmt, ## args)) +#else +#define P2P_TAG_PRINT(fmt, args...) {} + +#define P2P_PRINT(fmt, args...) {} +#define MAC_PRINT(fmt) {} +#define PDEBUG(fmt, args...) {} +#define P2P_DEBUG(fmt, args...) {} + +#endif + +#ifdef HS2_DEBUGMSG +extern unsigned int _HS2_debug_info; +extern unsigned int _HS2_debug_err; /* err flag */ +extern unsigned int _HS2_debug_trace; /* trace flag */ +extern unsigned int _HS2_debug_warn; /* warn flag */ + +#define HS2_DEBUG_INFO(fmt, args...) if(_HS2_debug_info) panic_printk("[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#define HS2_DEBUG_ERR(fmt, args...) if(_HS2_debug_err) panic_printk("[%s %d]Err: "fmt,__FUNCTION__,__LINE__,## args) +#define HS2_DEBUG_TRACE(level, fmt, args...) if(_HS2_debug_trace >= level) panic_printk("[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#define HS2_DEBUG_WARN(fmt, args...) if(_HS2_debug_warn) panic_printk("[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#else +#define HS2_DEBUG_INFO(fmt, args...) +#define HS2_DEBUG_ERR(fmt, args...) +#define HS2_DEBUG_TRACE(level, fmt, args...) +#define HS2_DEBUG_INFO(fmt, args...) +#endif + +#ifdef PMF_DEBUGMSG +#define PMFDEBUG(fmt, args...) panic_printk("[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#else +#define PMFDEBUG(fmt, args...) {} +#endif +#define EDEBUG(fmt, args...) {} +//#define SDEBUG(fmt, args...) panic_printk("[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#define SDEBUG(fmt, args...) { } +//#define STADEBUG(fmt, args...) panic_printk("[%d %s ][%s]"fmt,__LINE__, __FUNCTION__,priv->dev->name,## args) +#define STADEBUG(fmt, args...) { } +#define PSKDEBUG(fmt, args...) { } +//#define PSKDEBUG(fmt, args...) panic_printk("[%d %s ][%s]"fmt,__LINE__, __FUNCTION__,priv->dev->name,## args) + +#define NDEBUG(fmt, args...) { } +//#define NDEBUG(fmt, args...) printk("[%s %d][%s]"fmt,__FUNCTION__,__LINE__,priv->dev->name,## args) +#define _NDEBUG(fmt, args...) { } +//#define _NDEBUG(fmt, args...) printk("[%s][%s]"fmt,__FUNCTION__,priv->dev->name,## args) + +#define GDEBUG(fmt, args...) panic_printk("[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#define HALDEBUG(fmt, args...) panic_printk("[%s %d][%s]"fmt,__FUNCTION__,__LINE__,Adapter->dev->name,## args) + +//#define NDEBUG2(fmt, args...) printk("[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#define NDEBUG2(fmt, args...) {} +//#define NDEBUG3(fmt, args...) printk("[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#define NDEBUG3(fmt, args...) {} + + +#ifdef USE_PREALLOC_MODULE +extern void *rtw_pre_malloc(int type, size_t size); +extern void rtw_pre_free(const void *p); +#endif + +/*----------------------------------------------------------------------------- + 8192cd_util.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_UTILS_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +#ifdef RTK_NL80211 +EXTERN u8* rtk_get_ie_with_oui(u8 *in_ie, int in_len, u8 ie_to_search, u8* oui_input ,int oui_len, int *report_ielen); +EXTERN int rtk_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, int *wfd_ielen); +EXTERN u8* rtk_get_wps_ie(u8 *in_ie, int in_len, u8 *wps_ie, int *wps_ielen); +EXTERN void copy_wps_ie(struct rtl8192cd_priv *priv, unsigned char *wps_ie, unsigned char mgmt_type); +EXTERN void convert_bin_to_str(unsigned char *bin, int len, char *out); +#endif + +#ifdef TXREPORT +#ifdef CONFIG_WLAN_HAL +EXTERN void APReqTXRptHandler(struct rtl8192cd_priv *priv,unsigned char* C2HContent); +#endif +EXTERN void _txrpt_handler(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct tx_rpt *report); +EXTERN void txrpt_handler(struct rtl8192cd_priv *priv, struct tx_rpt *report); +#endif + +EXTERN int is_passive_channel(struct rtl8192cd_priv *priv , int domain, int chan);//20131218 add +EXTERN int is_DFS_channel(int channelVal); + + +EXTERN void mem_dump(unsigned char *ptitle, unsigned char *pbuf, int len); +EXTERN int enque(struct rtl8192cd_priv *priv, int *head, int *tail, unsigned long ffptr, int ffsize, void *elm); +EXTERN void* deque(struct rtl8192cd_priv *priv, int *head, int *tail, unsigned long ffptr, int ffsize); +EXTERN void initque(struct rtl8192cd_priv *priv, int *head, int *tail); +EXTERN int isFFempty(int head, int tail); +EXTERN unsigned int find_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat, int mode, int isBasicRate); +EXTERN unsigned int find_rate_MP(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct ht_cap_elmt * peer_ht_cap, int peer_ht_cap_len, char * peer_rate, int peer_rate_len, int mode, int isBasicRate); +EXTERN void init_stainfo(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void release_stainfo(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN struct stat_info *alloc_stainfo(struct rtl8192cd_priv *priv, unsigned char *hwaddr, int id); +EXTERN void free_sta_tx_skb(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void free_sta_skb(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void free_sta_frag_list(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN int del_station(struct rtl8192cd_priv *priv, struct stat_info *pstat, int send_disasoc); +EXTERN int free_stainfo(struct rtl8192cd_priv *priv, struct stat_info *pstat); +__MIPS16 +__IRAM_IN_865X +EXTERN struct stat_info *get_stainfo(struct rtl8192cd_priv *priv, const unsigned char *hwaddr); +#ifdef HW_DETEC_POWER_STATE +__MIPS16 +__IRAM_IN_865X +EXTERN struct stat_info *get_HW_mapping_sta(struct rtl8192cd_priv *priv, unsigned char macID); +#endif +EXTERN struct stat_info *get_aidinfo (struct rtl8192cd_priv *priv, unsigned int aid); +#ifdef TXREPORT +EXTERN struct stat_info *get_macidinfo(struct rtl8192cd_priv *priv, unsigned int aid); +#endif +EXTERN int IS_BSSID(struct rtl8192cd_priv *priv, unsigned char *da); +EXTERN int IS_BCAST2(unsigned char *da); +EXTERN int IS_MCAST(unsigned char *da); +EXTERN int p80211_stt_findproto(UINT16 proto); +EXTERN int skb_ether_to_p80211(struct sk_buff *skb, UINT32 ethconv); +EXTERN int skb_p80211_to_ether(struct net_device *dev, int wep_mode, struct rx_frinfo *pfrinfo); +EXTERN int strip_amsdu_llc(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat); +EXTERN unsigned char *get_da(unsigned char *pframe); +EXTERN unsigned char *get_bssid_mp(unsigned char *pframe); +__MIPS16 +__IRAM_IN_865X +EXTERN unsigned char get_hdrlen(struct rtl8192cd_priv *priv, UINT8 *pframe); +EXTERN unsigned int get_mcast_privacy(struct rtl8192cd_priv *priv, unsigned int *iv, unsigned int *icv, + unsigned int *mic); +EXTERN unsigned int get_privacy(struct rtl8192cd_priv *priv, struct stat_info *pstat, + unsigned int *iv, unsigned int *icv, unsigned int *mic); +EXTERN unsigned char *get_mgtbuf_from_poll(struct rtl8192cd_priv *priv); +EXTERN void release_mgtbuf_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf); +EXTERN unsigned char *get_wlanhdr_from_poll(struct rtl8192cd_priv *priv); +EXTERN void release_wlanhdr_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf); +EXTERN unsigned char *get_wlanllchdr_from_poll(struct rtl8192cd_priv *priv); +EXTERN void release_wlanllchdr_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf); +EXTERN unsigned char *get_icv_from_poll(struct rtl8192cd_priv *priv); +EXTERN void release_icv_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf); +EXTERN unsigned char *get_mic_from_poll(struct rtl8192cd_priv *priv); +EXTERN void release_mic_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf); +EXTERN unsigned short get_pnl(union PN48 *ptsc); +EXTERN unsigned int get_pnh(union PN48 *ptsc); +EXTERN void eth_2_llc(struct wlan_ethhdr_t *pethhdr, struct llc_snap *pllc_snap); +EXTERN void eth2_2_wlanhdr(struct rtl8192cd_priv *priv, struct wlan_ethhdr_t *pethhdr, struct tx_insn *txcfg); +EXTERN unsigned char *get_sa(unsigned char *pframe); +EXTERN unsigned int get_mcast_encrypt_algthm(struct rtl8192cd_priv *priv); +EXTERN unsigned int get_sta_encrypt_algthm(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN UINT8 get_rate_from_bit_value(int bit_val); +EXTERN int get_rate_index_from_ieee_value(UINT8 val); +EXTERN int get_bit_value_from_ieee_value(UINT8 val); +EXTERN int UseSwCrypto(struct rtl8192cd_priv *priv, struct stat_info *pstat, int isMulticast +#ifdef CONFIG_IEEE80211W + ,int isPMF +#endif + ); + +#ifdef WDS +EXTERN int getWdsIdxByDev(struct rtl8192cd_priv *priv, struct net_device *dev); +EXTERN struct net_device *getWdsDevByAddr(struct rtl8192cd_priv *priv, unsigned char *addr); +#endif + +EXTERN void check_protection_shortslot(struct rtl8192cd_priv *priv); +EXTERN void check_sta_characteristic(struct rtl8192cd_priv *priv, struct stat_info *pstat, int act); +EXTERN int should_forbid_Nmode(struct rtl8192cd_priv *priv); +EXTERN int should_restrict_Nrate(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void validate_oper_rate(struct rtl8192cd_priv *priv); +EXTERN void get_oper_rate(struct rtl8192cd_priv *priv); +EXTERN int get_bssrate_set(struct rtl8192cd_priv *priv, int bssrate_ie, unsigned char **pbssrate, int *bssrate_len); +EXTERN int get_available_channel(struct rtl8192cd_priv *priv); +EXTERN int is80MChannel(unsigned int chnl_list[], unsigned int chnl_num,unsigned int channel); +EXTERN int is40MChannel(unsigned int chnl_list[], unsigned int chnl_num,unsigned int channel); +EXTERN int find80MChannel(unsigned int chnl_list[], unsigned int chnl_num); +EXTERN int find40MChannel(unsigned int chnl_list[], unsigned int chnl_num); +EXTERN void cnt_assoc_num(struct rtl8192cd_priv *priv, struct stat_info *pstat, int act, char *func); +#ifdef INDICATE_LINK_CHANGE +EXTERN void indicate_sta_link_change(struct rtl8192cd_priv *priv, struct stat_info *pstat, int act, char *func); +#endif +EXTERN int get_assoc_sta_num(struct rtl8192cd_priv *priv, int mode); +EXTERN void event_indicate(struct rtl8192cd_priv *priv, unsigned char *mac, int event); +#ifdef WIFI_HAPD +EXTERN int event_indicate_hapd(struct rtl8192cd_priv *priv, unsigned char *mac, int event, unsigned char *extra); +#endif +#ifdef WIFI_WPAS +EXTERN int event_indicate_wpas(struct rtl8192cd_priv *priv, unsigned char *mac, int event, unsigned char *extra); +#endif +#ifdef USE_WEP_DEFAULT_KEY +EXTERN void init_DefaultKey_Enc(struct rtl8192cd_priv *priv, unsigned char *key, int algorithm); +#endif + +#if defined(RTK_NL80211) +EXTERN int changePreamble(struct rtl8192cd_priv *priv, int preamble); +EXTERN int HideAP(struct rtl8192cd_priv *priv); +EXTERN int DehideAP(struct rtl8192cd_priv *priv); +#endif + +#if defined( UNIVERSAL_REPEATER) || defined(MBSSID) +EXTERN void disable_vxd_ap(struct rtl8192cd_priv *priv); +EXTERN void enable_vxd_ap(struct rtl8192cd_priv *priv); +EXTERN int under_apmode_repeater(struct rtl8192cd_priv *priv); +EXTERN int get_ss_level(struct rtl8192cd_priv *priv); +EXTERN int send_arp_response(struct rtl8192cd_priv *priv, unsigned int *dip, unsigned int *sip, unsigned char *dmac, unsigned char *smac); +EXTERN void snoop_STA_IP(struct sk_buff *pskb, struct rtl8192cd_priv *priv); +#endif +EXTERN unsigned int isDHCPpkt(struct sk_buff *pskb); +EXTERN void syncMulticastCipher(struct rtl8192cd_priv *priv, struct bss_desc *bss_target); +#ifdef GBWC +EXTERN void rtl8192cd_GBWC_timer(unsigned long task_priv); +#endif + +EXTERN void update_remapAid(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void release_remapAid(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN unsigned char fw_was_full(struct rtl8192cd_priv *priv); +EXTERN int realloc_RATid(struct rtl8192cd_priv * priv); + +// to avoid add RAtid fail +EXTERN unsigned int is_h2c_buf_occupy(struct rtl8192cd_priv *priv); +EXTERN short signin_h2c_cmd(struct rtl8192cd_priv *priv, unsigned int content, unsigned short ext_content); +#ifdef CONFIG_PCI_HCI +EXTERN void add_ps_timer(unsigned long task_priv); + +EXTERN void add_update_ps(struct rtl8192cd_priv *priv, struct stat_info *pstat); +#endif +EXTERN void send_h2c_cmd_detect_wps_gpio(struct rtl8192cd_priv *priv, unsigned int gpio_num, unsigned int enable, unsigned int high_active); + +#ifdef SDIO_AP_OFFLOAD +EXTERN void set_ap_ps_mode(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void ap_offload_deactivate(struct rtl8192cd_priv *priv, int reason); +EXTERN void ap_offload_activate(struct rtl8192cd_priv *priv, int reason); +#endif + + +EXTERN void refill_skb_queue(struct rtl8192cd_priv *priv); +EXTERN void free_skb_queue(struct rtl8192cd_priv *priv, struct sk_buff_head *skb_que); + +#ifdef FAST_RECOVERY +EXTERN void *backup_sta(struct rtl8192cd_priv *priv); +EXTERN void restore_backup_sta(struct rtl8192cd_priv *priv, void *pInfo); +#endif + +#ifdef RTK_QUE +EXTERN void rtk_queue_init(struct ring_que *que); +EXTERN void free_rtk_queue(struct rtl8192cd_priv *priv, struct ring_que *skb_que); +#endif + + +#ifdef CONFIG_RTL8190_PRIV_SKB +EXTERN void init_priv_skb_buf(struct rtl8192cd_priv *priv); +EXTERN int is_rtl8190_priv_buf(unsigned char *head); +EXTERN void free_rtl8190_priv_buf(unsigned char *head); +#endif + +EXTERN unsigned int orForce20_Switch20Map(struct rtl8192cd_priv * priv); +EXTERN unsigned int orSTABitMap(STA_BITMAP *map); +EXTERN unsigned char getSTABitMap(STA_BITMAP *map, int bitIdx); +EXTERN void setSTABitMap(STA_BITMAP *map, int bitIdx); +EXTERN void clearSTABitMap(STA_BITMAP *map, int bitIdx); + +EXTERN void update_intel_sta_bitmap(struct rtl8192cd_priv *priv, struct stat_info *pstat, int release); + +#if defined(WIFI_11N_2040_COEXIST_EXT) +EXTERN void update_40m_staMap(struct rtl8192cd_priv *priv, struct stat_info *pstat, int release); +EXTERN void checkBandwidth(struct rtl8192cd_priv *priv); +#endif + +// global variables +EXTERN UINT8 Realtek_OUI[]; +EXTERN UINT8 dot11_rate_table[]; + +/* +EXTERN unsigned int set_fw_reg(struct rtl8192cd_priv *priv, unsigned int cmd, unsigned int val, unsigned int with_val); +EXTERN void set_fw_A2_entry(struct rtl8192cd_priv * priv, unsigned int cmd, unsigned char * addr); +*/ + + +#ifdef CONFIG_RTK_MESH +EXTERN int expire_mesh_txcache(struct rtl8192cd_priv*, unsigned char *); +EXTERN int append_proxy_table(struct rtl8192cd_priv*, unsigned char *); +EXTERN int remove_proxy_table(struct rtl8192cd_priv*, unsigned char *); +#ifdef _11s_TEST_MODE_ +EXTERN __inline__ unsigned char *get_buf_from_poll(struct rtl8192cd_priv *priv, struct list_head *phead, unsigned int *count); +EXTERN __inline__ void release_buf_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf, struct list_head *phead, unsigned int *count); +#endif + +EXTERN UINT8 oui_rfc1042[]; +EXTERN UINT8 oui_8021h[]; +EXTERN unsigned char SNAP_ETH_TYPE_IPX[]; +EXTERN unsigned char SNAP_ETH_TYPE_APPLETALK_AARP[]; +EXTERN unsigned char SNAP_ETH_TYPE_APPLETALK_DDP[]; +EXTERN unsigned char SNAP_HDR_APPLETALK_DDP[]; + +#define WLAN_PKT_FORMAT_SNAP_RFC1042 0x02 +#define WLAN_PKT_FORMAT_SNAP_TUNNEL 0x03 +#define WLAN_PKT_FORMAT_IPX_TYPE4 0x04 +#define WLAN_PKT_FORMAT_APPLETALK 0x05 +#define WLAN_PKT_FORMAT_OTHERS 0x07 +#endif + +#ifdef PRIV_STA_BUF +EXTERN void init_priv_sta_buf(struct rtl8192cd_priv *priv); +EXTERN struct aid_obj *alloc_sta_obj(struct rtl8192cd_priv*); +EXTERN void free_sta_obj(struct rtl8192cd_priv *priv, struct aid_obj *obj); +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) +//EXTERN void free_wpa_buf(struct rtl8192cd_priv *priv, WPA_STA_INFO *buf); +EXTERN void free_wpa_buf(struct rtl8192cd_priv *priv, struct _wpa_sta_info *buf); +#endif +#if defined(WIFI_WMM) && defined(WMM_APSD) +EXTERN void free_sta_que(struct rtl8192cd_priv *priv, struct apsd_pkt_queue *que); +#endif +#if defined(WIFI_WMM) +EXTERN void free_sta_mgt_que(struct rtl8192cd_priv *priv, struct dz_mgmt_queue *que); +#endif +#endif + + +EXTERN int rtl_string_to_hex(char *string, unsigned char *key, int len); + + +#if defined(TXREPORT) +EXTERN void requestTxReport(struct rtl8192cd_priv *priv); +EXTERN void C2H_isr(struct rtl8192cd_priv *priv); +#endif + +EXTERN struct stat_info* findNextSTA(struct rtl8192cd_priv *priv, int *idx); + +#if defined(DUALBAND_ONLY) && defined(CONFIG_RTL8190_PRIV_SKB) +void merge_pool(struct rtl8192cd_priv *priv); +void split_pool(struct rtl8192cd_priv *priv); +#endif + +#ifdef TLN_STATS +EXTERN void stats_conn_rson_counts(struct rtl8192cd_priv * priv, unsigned int reason); +EXTERN void stats_conn_status_counts(struct rtl8192cd_priv * priv, unsigned int status); +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +EXTERN void _init_txservq(struct tx_servq *ptxservq, int q_num); + +EXTERN struct list_head* asoc_list_get_next(struct rtl8192cd_priv *priv, struct list_head *plist); +EXTERN void asoc_list_unref(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN int asoc_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN int asoc_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat); +#endif + +#if defined(RF_MIMO_SWITCH) || defined(RF_MIMO_PS) +EXTERN void RF_MIMO_check_timer(unsigned long task_priv); +EXTERN int assign_MIMO_TR_Mode(struct rtl8192cd_priv *priv, unsigned char *data); +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) +EXTERN void update_RAMask_to_FW(struct rtl8192cd_priv *priv, int legacy); +#endif + +EXTERN BOOLEAN CheckCts2SelfEnable(UINT8 rtsTxRate); +EXTERN UINT8 find_rts_rate(struct rtl8192cd_priv *priv, UINT8 TxRate, BOOLEAN bErpProtect); + +EXTERN void Assert_BB_Reset(struct rtl8192cd_priv *priv); +EXTERN void Release_BB_Reset(struct rtl8192cd_priv *priv); + +#ifdef WIFI_SIMPLE_CONFIG +void wsc_disconn_list_add(struct rtl8192cd_priv *priv, unsigned char *hwaddr); +void wsc_disconn_list_expire(struct rtl8192cd_priv *priv); +void wsc_disconn_list_update(struct rtl8192cd_priv *priv, unsigned char *hwaddr); +int wsc_disconn_list_check(struct rtl8192cd_priv *priv, unsigned char *hwaddr); +void wsc_disconn_list_flush(struct rtl8192cd_priv *priv); +#endif + +#ifdef TX_SHORTCUT +EXTERN void clearTxShortCutBufSize(struct rtl8192cd_priv *priv, struct stat_info *pstat); +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_tx.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_TX_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN __MIPS16 __IRAM_IN_865X void assign_wlanseq(struct rtl8192cd_hw *phw, unsigned char *pframe, struct stat_info *pstat, struct wifi_mib *pmib +#ifdef CONFIG_RTK_MESH // For message if broadcast data frame via mesh (ex:ARP requst) + , unsigned char is_11s +#endif + ); +#if 0 +EXTERN void signin_txdesc(struct rtl8190_priv *priv, struct tx_insn* txcfg); +#endif +EXTERN int rtl8192cd_start_xmit(struct sk_buff *skb, struct net_device *dev); +#ifdef SUPPORT_TX_MCAST2UNI +EXTERN int rtl8192cd_start_xmit_noM2U(struct sk_buff *skb, struct net_device *dev); +#else +#define rtl8192cd_start_xmit_noM2U rtl8192cd_start_xmit +#endif +EXTERN int rtl8192cd_wlantx(struct rtl8192cd_priv *priv, struct tx_insn *txcfg); +EXTERN void rtl8192cd_tx_dsr(unsigned long task_priv); + +EXTERN int rtl8192cd_firetx(struct rtl8192cd_priv *priv, struct tx_insn *txcfg); +EXTERN int __rtl8192cd_firetx(struct rtl8192cd_priv *priv, struct tx_insn* txcfg); +#ifdef CONFIG_PCI_HCI +EXTERN int rtl8192cd_signin_txdesc(struct rtl8192cd_priv *priv, struct tx_insn* txcfg); +#endif + +#ifdef TX_SHORTCUT +//EXTERN void signin_txdesc_shortcut(struct rtl8190_priv *priv, struct tx_insn *txcfg); +#ifdef CONFIG_WLAN_HAL +EXTERN __MIPS16 int rtl88XX_signin_txdesc_shortcut(struct rtl8192cd_priv *priv, struct tx_insn *txcfg, int idx); +#endif // CONFIG_WLAN_HAL + +#ifdef CONFIG_8814_AP_MAC_VERI +void RX_MAC_Verify_8814(struct rtl8192cd_priv *priv,unsigned char * pframe,struct rx_frinfo *pfrinfo); +#endif +#ifdef HW_DETEC_POWER_STATE +EXTERN void detect_hw_pwr_state(struct rtl8192cd_priv *priv, unsigned char macIDGroup); +EXTERN __IRAM_IN_865X void pwr_state_enhaced(struct rtl8192cd_priv *priv, unsigned char macID, unsigned char PwrBit); +#endif +#ifdef CONFIG_PCI_HCI +EXTERN __MIPS16 __IRAM_IN_865X +int rtl8192cd_signin_txdesc_shortcut(struct rtl8192cd_priv *priv, struct tx_insn *txcfg, int idx); +#endif +#endif +EXTERN int SetupOneCmdPacket(struct rtl8192cd_priv *priv, unsigned char *dat_content, + unsigned short txLength, unsigned char LastPkt); +EXTERN void amsdu_timeout(struct rtl8192cd_priv *priv, unsigned int current_time); + +EXTERN int rtl8192cd_SetupOneCmdPacket(struct rtl8192cd_priv *priv, unsigned char *dat_content, unsigned short txLength, unsigned char LastPkt); + +#ifdef CONFIG_RTK_MESH +__MIPS16 +__IRAM_IN_865X +EXTERN int __rtl8192cd_start_xmit_out(struct sk_buff *skb, struct stat_info *pstat, struct tx_insn *ptxcfg); +//#ifdef MESH_AMSDU //plus mark it for build error +EXTERN int amsdu_check(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat, struct tx_insn *txcfg); +//#endif +EXTERN unsigned int get_tx_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN unsigned int get_lowest_tx_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned int tx_rate); +EXTERN int isSpecialFloodMac(struct rtl8192cd_priv *priv, struct sk_buff *skb); +EXTERN int isICMPv6Mng(struct sk_buff *skb); +EXTERN inline int isMDNS(unsigned char *data); +#endif + +#if defined(DRVMAC_LB) && defined(WIFI_WMM) +EXTERN void SendLbQosData(struct rtl8192cd_priv *priv); +EXTERN void SendLbQosNullData(struct rtl8192cd_priv *priv); +#endif + +EXTERN void wep_fill_iv(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, unsigned int hdrlen, unsigned long keyid); +EXTERN void tkip_fill_encheader(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, unsigned int hdrlen, unsigned long keyid_out); +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +EXTERN void aes_fill_encheader(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, unsigned int hdrlen, unsigned long keyid); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef RTL_MANUAL_EDCA +EXTERN unsigned int PRI_TO_QNUM(struct rtl8192cd_priv *priv, int priority); +#endif +EXTERN __MIPS16 __IRAM_IN_865X unsigned int get_skb_priority(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat); +EXTERN unsigned int get_tx_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN unsigned int get_lowest_tx_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat, + unsigned int tx_rate); +EXTERN void RtsCheck(struct rtl8192cd_priv *priv, struct tx_insn* txcfg, + BOOLEAN *bRtsEnable, BOOLEAN *bCts2SelfEnable, BOOLEAN *bHwRts, BOOLEAN *bErpProtect, BOOLEAN *bNProtect); +EXTERN void rtl8192cd_fill_fwinfo(struct rtl8192cd_priv *priv, struct tx_insn* txcfg, struct tx_desc *pdesc, unsigned int frag_idx); +EXTERN int __rtl8192cd_usb_start_xmit(struct rtl8192cd_priv *priv, struct tx_insn* txcfg); +EXTERN int rtl8192cd_tx_slowPath(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat, + struct net_device *dev, struct net_device *wdsDev, struct tx_insn *txcfg); +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_sme.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_SME_C_ +#define EXTERN extern +#else +#define EXTERN +#endif +EXTERN unsigned int get_ava_2ndchoff(struct rtl8192cd_priv *priv, unsigned int channel, unsigned int bandwidth); +EXTERN void unchainned_all_frag(struct rtl8192cd_priv *priv, struct list_head *phead); +EXTERN void rtl8192cd_expire_timer(unsigned long task_priv); +EXTERN void rtl8192cd_frag_timer(unsigned long task_priv); +EXTERN void rtl8192cd_1sec_timer(unsigned long task_priv); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +EXTERN void pre_rtl8192cd_1sec_timer(unsigned long task_priv); +EXTERN void fill_bcn_desc(struct rtl8192cd_priv *priv, struct tx_desc *pdesc, void *dat_content, unsigned short txLength, char forceUpdate); +EXTERN int signin_beacon_desc(struct rtl8192cd_priv * priv,unsigned int * beaconbuf,unsigned int frlen); +#endif + +EXTERN void mgt_handler(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN void pwr_state(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +#ifdef CONFIG_WLAN_HAL +EXTERN void check_PS_set_HIQLMT(struct rtl8192cd_priv *priv); +#endif +EXTERN void update_beacon(struct rtl8192cd_priv *priv); +EXTERN void init_beacon(struct rtl8192cd_priv *priv); +#ifdef CONFIG_PCI_HCI +EXTERN void signin_beacon_desc(struct rtl8192cd_priv * priv,unsigned int * beaconbuf,unsigned int frlen); +#endif +EXTERN void issue_deauth(struct rtl8192cd_priv *priv, unsigned char *da, int reason); +EXTERN void start_clnt_ss(struct rtl8192cd_priv *priv); + +EXTERN void rtl8192cd_ss_timer(unsigned long task_priv); + +EXTERN void process_dzqueue(struct rtl8192cd_priv *priv); +EXTERN void issue_asocrsp(struct rtl8192cd_priv *priv, unsigned short status, struct stat_info *pstat, int pkt_type); +EXTERN void issue_disassoc(struct rtl8192cd_priv *priv, unsigned char *da, int reason); +#if defined(WIFI_WMM) +EXTERN int issue_ADDBArsp(struct rtl8192cd_priv *priv, unsigned char *da, unsigned char dialog_token, + unsigned char TID, unsigned short status_code, unsigned short timeout); +#endif +EXTERN int fill_probe_rsp_content(struct rtl8192cd_priv*, UINT8*, UINT8*, UINT8*, int , int , UINT8, UINT8); +EXTERN void assign_tx_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct rx_frinfo *pfrinfo); +EXTERN void assign_aggre_mthod(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void assign_aggre_size(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN int isErpSta(struct stat_info *pstat); +EXTERN int chklink_wkstaQ(struct rtl8192cd_priv *priv); + +#ifdef CLIENT_MODE +EXTERN void start_clnt_join(struct rtl8192cd_priv *priv); +EXTERN void start_clnt_lookup(struct rtl8192cd_priv *priv, int rescan); + +EXTERN void rtl8192cd_reauth_timer(unsigned long task_priv); +EXTERN void rtl8192cd_reassoc_timer(unsigned long task_priv); +EXTERN void rtl8192cd_idle_timer(unsigned long task_priv); +#ifdef DFS +EXTERN void rtl8192cd_dfs_cntdwn_timer(unsigned long task_priv); +#endif +EXTERN void issue_PsPoll(struct rtl8192cd_priv *priv); +#endif +#ifdef MULTI_MAC_CLONE +void issue_NullData(struct rtl8192cd_priv *priv, unsigned char *da); +#endif + +#ifdef WIFI_WMM +EXTERN void init_WMM_Para_Element(struct rtl8192cd_priv *priv, unsigned char *temp); +EXTERN void issue_ADDBAreq(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char TID); +#endif + +EXTERN void process_mcast_dzqueue(struct rtl8192cd_priv *priv); +EXTERN void construct_ht_ie(struct rtl8192cd_priv *priv, int use_40m, int offset); + +EXTERN int check_adaptivity_test(struct rtl8192cd_priv *priv); +#ifdef CHECK_HANGUP +EXTERN int check_hangup(struct rtl8192cd_priv *priv); +#endif + +#ifndef USE_WEP_DEFAULT_KEY +EXTERN void set_keymapping_wep(struct rtl8192cd_priv *priv, struct stat_info *pstat); +#endif + +#ifdef USB_PKT_RATE_CTRL_SUPPORT +EXTERN void register_usb_pkt_cnt_f(void *usbPktFunc); +EXTERN void usbPkt_timer_handler(struct rtl8192cd_priv *priv); +#endif + +#ifdef RTK_WOW +EXTERN void issue_rtk_wow(struct rtl8192cd_priv * priv, unsigned char * da); +#endif + +#ifdef SUPPORT_MONITOR +EXTERN void rtl8192cd_chan_switch_timer(unsigned long task_priv); +EXTERN unsigned char *get_ie(unsigned char *pbuf, int index, int *len, int limit); +#endif +EXTERN unsigned char *set_ie(unsigned char *pbuf, int index, unsigned int len, unsigned char *source, unsigned int *frlen); +EXTERN unsigned char *get_ie(unsigned char *pbuf, int index, int *len, int limit); + +#ifdef CONFIG_RTK_MESH +EXTERN unsigned char WMM_IE[]; +EXTERN unsigned char WMM_PARA_IE[]; +EXTERN int check_basic_rate(struct rtl8192cd_priv *priv, unsigned char *pRate, int pLen); +EXTERN int collect_bss_info(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN unsigned char *construct_ht_ie_old_form(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen); +EXTERN void get_matched_rate(struct rtl8192cd_priv *priv, unsigned char *pRate, int *pLen, int which); +EXTERN void issue_auth(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned short status); +EXTERN void issue_deauth_MP(struct rtl8192cd_priv *priv, unsigned char *da, int reason, UINT8 is_11s); +EXTERN void issue_probersp_MP(struct rtl8192cd_priv *priv, unsigned char *da, UINT8 *ssid, int ssid_len, int set_privacy, UINT8 is_11s, UINT8 legacy_b_sta); +EXTERN unsigned char *set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source, unsigned int *frlen); +EXTERN void update_support_rate(struct stat_info *pstat, unsigned char* buf, int len); +EXTERN void proxy_table_chkcln(struct rtl8192cd_priv* priv, struct sk_buff *pskb); +EXTERN int fire_data_frame(struct sk_buff *skb, struct net_device *dev, struct tx_insn* txinsn); +#endif + +EXTERN void default_WMM_para(struct rtl8192cd_priv *priv); +EXTERN unsigned char *search_wsc_tag(unsigned char *data, unsigned short id, int len, int *out_len); +#ifdef CONFIG_RTL_92D_DMDP +EXTERN void reset_dmdp_peer(struct rtl8192cd_priv *from); +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +int clnt_ss_check_band(struct rtl8192cd_priv *priv, unsigned int channel); +#endif + +#if defined(RTK_NL80211) && defined(CLIENT_MODE) //wrt-adhoc +EXTERN void construct_ibss_beacon(struct rtl8192cd_priv *priv); +#ifdef __KERNEL__ +void issue_beacon_ibss_vxd(unsigned long task_priv); +#elif defined(__ECOS) +EXTERN void issue_beacon_ibss_vxd(void *task_priv); +#endif +#endif + +#if (defined( UNIVERSAL_REPEATER) || defined(MBSSID)) && defined(CLIENT_MODE) +//EXTERN void set_vxd_rescan(struct rtl8192cd_priv *priv); +EXTERN void set_vxd_rescan(struct rtl8192cd_priv *priv,int rescantype); +EXTERN void switch_profile(struct rtl8192cd_priv *priv, int idx); +EXTERN void sync_channel_2ndch_bw(struct rtl8192cd_priv *priv); +void start_repeater_ss(struct rtl8192cd_priv *priv); +#endif + +#ifdef AUTO_CHANNEL_TIMEOUT +EXTERN void auto_channel_timeout_expire(struct rtl8192cd_priv *priv); +#endif + +#if defined(TXREPORT) && defined(CONFIG_WLAN_HAL) +EXTERN void requestTxReport88XX(struct rtl8192cd_priv *priv); +#endif + +#if defined(HS2_SUPPORT) +EXTERN int issue_BSS_TSM_req(struct rtl8192cd_priv *priv, DOT11_HS2_TSM_REQ *tsm_req); +#endif +EXTERN int get_center_channel(struct rtl8192cd_priv *priv, int channel, int offset, int cur); + +#if defined(MULTI_MAC_CLONE) || defined(CONFIG_RTK_MESH) +EXTERN void rtl8192cd_mclone_reauth_timer(unsigned long data); +EXTERN void rtl8192cd_mclone_reassoc_timer(unsigned long data); +EXTERN void start_clnt_auth(struct rtl8192cd_priv *priv); +extern void clear_Multi_Mac_Clone(struct rtl8192cd_priv *priv, int idx); +EXTERN int __del_mclone_addr(struct rtl8192cd_priv *priv, unsigned char *buf); +EXTERN void ap_sync_chan_to_bss(struct rtl8192cd_priv *priv, int bss_channel, int bss_bw, int bss_offset); +#endif +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_led.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_LED_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void enable_sw_LED(struct rtl8192cd_priv *priv, int init); +EXTERN void disable_sw_LED(struct rtl8192cd_priv *priv); +EXTERN void calculate_sw_LED_interval(struct rtl8192cd_priv *priv); +EXTERN void control_wireless_led(struct rtl8192cd_priv *priv, int enable); + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_dfs.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_DFS_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +#ifdef DFS +EXTERN void rtl8192cd_DFS_timer(unsigned long task_priv); +EXTERN void rtl8192cd_DFS_TXPAUSE_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch_avail_chk_timer(unsigned long task_priv); +EXTERN void rtl8192cd_dfs_det_chk_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch52_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch56_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch60_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch64_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch100_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch104_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch108_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch112_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch116_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch120_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch124_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch128_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch132_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch136_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch140_timer(unsigned long task_priv); +EXTERN void rtl8192cd_ch144_timer(unsigned long task_priv); + +EXTERN unsigned int DFS_SelectChannel(struct rtl8192cd_priv *priv); +EXTERN int RemoveChannel(struct rtl8192cd_priv *priv, unsigned int chnl_list[], unsigned int *chnl_num, unsigned int channel); +EXTERN int InsertChannel(unsigned int chnl_list[], unsigned int *chnl_num, unsigned int channel); +EXTERN void DFS_SwChnl_clnt(struct rtl8192cd_priv *priv); +EXTERN void DFS_SwitchChannel(struct rtl8192cd_priv *priv); +EXTERN void DFS_SetReg(struct rtl8192cd_priv *priv); +EXTERN unsigned char *get_DFS_version(void); +#if defined(UNIVERSAL_REPEATER) +EXTERN int under_apmode_repeater(struct rtl8192cd_priv *priv); +#endif +EXTERN int should_defer_ss(struct rtl8192cd_priv *priv); +#endif + +#if defined(DFS) || defined(RTK_AC_SUPPORT) +EXTERN void DFS_SwitchChannel(struct rtl8192cd_priv *priv); +#endif +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_dfs_det.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_DFS_DET_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +#ifdef DFS +EXTERN void rtl8192cd_dfs_det_chk(struct rtl8192cd_priv *priv); +EXTERN void rtl8192cd_dfs_dynamic_setting(struct rtl8192cd_priv *priv); +#if defined(CONFIG_WLAN_HAL_8814AE) +EXTERN void rtl8192cd_radar_type_differentiation(struct rtl8192cd_priv *priv); +#endif +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_rx.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_RX_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN __MIPS16 __IRAM_IN_865X int validate_mpdu(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef USE_OUT_SRC +EXTERN void translate_rssi_sq_outsrc(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, char rate); +#endif +EXTERN void translate_CRC32_outsrc(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, BOOLEAN CRC32,u2Byte PKT_LEN); +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +EXTERN void translate_rssi_sq(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +#endif +EXTERN void rx_pkt_exception(struct rtl8192cd_priv *priv, unsigned int cmd); +#if defined(WIFI_WMM) && defined(WMM_APSD) +EXTERN void SendQosNullData(struct rtl8192cd_priv *priv, unsigned char *da); +#endif +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#ifdef CONFIG_PCI_HCI +#if !defined(__LINUX_2_6__) && !defined(__ECOS) +__MIPS16 +#endif +EXTERN void rtl88XX_rx_isr(struct rtl8192cd_priv *priv); +#if defined(RX_TASKLET) || defined(__ECOS) +EXTERN void rtl8192cd_rx_tkl_isr(unsigned long task_priv); +#endif +#if !defined(__LINUX_2_6__) && !defined(__ECOS) +__MIPS16 +#endif +EXTERN void rtl8192cd_rx_isr(struct rtl8192cd_priv *priv); +EXTERN void rtl8192cd_rx_dsr(unsigned long task_priv); +#endif // CONFIG_PCI_HCI +#ifndef CONFIG_RTL_8196E +EXTERN /*__MIPS16*/ __IRAM_IN_865X void rtl_netif_rx(struct rtl8192cd_priv *priv, struct sk_buff *pskb, struct stat_info *pstat); +#else +EXTERN __MIPS16 __IRAM_IN_865X void rtl_netif_rx(struct rtl8192cd_priv *priv, struct sk_buff *pskb, struct stat_info *pstat); +#endif +//EXTERN void rtl8190_rxcmd_isr(struct rtl8190_priv *priv); +EXTERN void reorder_ctrl_timeout(unsigned long task_priv); + +EXTERN void rtl8192cd_rx_mgntframe(struct rtl8192cd_priv*, struct list_head *,struct rx_frinfo*); +#ifdef CONFIG_RTK_MESH +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +EXTERN int reorder_ctrl_check(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct rx_frinfo *pfrinfo); +__MIPS16 +__IRAM_IN_865X +EXTERN void rtl8192cd_rx_dataframe(struct rtl8192cd_priv*, struct list_head *,struct rx_frinfo*); +#endif + +#ifdef PREVENT_BROADCAST_STORM +EXTERN unsigned int get_free_memory(void); +#endif + +#ifdef RX_BUFFER_GATHER +EXTERN void flush_rx_list(struct rtl8192cd_priv *priv); +#endif +#if !(defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX)) +EXTERN void flush_rx_queue(struct rtl8192cd_priv *priv); +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_hw.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_HW_C_ +#define EXTERN extern +#else +#define EXTERN +#endif +#ifdef CONFIG_WLAN_HAL +EXTERN BOOLEAN compareAvailableTXBD(struct rtl8192cd_priv * priv, unsigned int num, unsigned int qNum, int compareFlag); +#endif +EXTERN void check_chipID_MIMO(struct rtl8192cd_priv *priv); +#ifdef EN_EFUSE +EXTERN int efuse_get(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int efuse_set(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int efuse_sync(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void ReadTxPowerInfoFromHWPG(struct rtl8192cd_priv *priv); +EXTERN void ReadThermalMeterFromEfuse(struct rtl8192cd_priv *priv); +EXTERN void ReadCrystalCalibrationFromEfuse(struct rtl8192cd_priv *priv); +EXTERN void ReadTxBBSwingFromEfuse(struct rtl8192cd_priv *priv); +EXTERN void ReadDeltaValFromEfuse(struct rtl8192cd_priv * priv); +EXTERN void ReadTRSWPAPEFromEfuse(struct rtl8192cd_priv * priv); +EXTERN int ReadAdapterInfo8192CE(struct rtl8192cd_priv *priv); +#ifdef CONFIG_SDIO_HCI +EXTERN void rtw_bb_rf_gain_offset(struct rtl8192cd_priv *priv); +#endif +#endif +#if defined(CONFIG_OFFLOAD_FUNCTION) || defined(SDIO_AP_OFFLOAD) +EXTERN int offloadTestFunction(struct rtl8192cd_priv *priv, unsigned char *data); +#endif + +#if defined(RF_MIMO_SWITCH) || defined(PCIE_POWER_SAVING) || defined(RF_MIMO_PS) +EXTERN int MIMO_mode_switch(struct rtl8192cd_priv *priv, int mode) ; +#endif + +#ifdef PCIE_POWER_SAVING +EXTERN void PCIE_reset_procedure3(struct rtl8192cd_priv *priv); +EXTERN void PCIe_power_save_timer(unsigned long task_priv); +EXTERN void PCIe_power_save_tasklet(unsigned long task_priv); +EXTERN void init_pcie_power_saving(struct rtl8192cd_priv *priv); +EXTERN void switch_to_1x1(struct rtl8192cd_priv *priv, int mode) ; +EXTERN void PCIeWakeUp(struct rtl8192cd_priv *priv, unsigned int expTime); +EXTERN void radio_off(struct rtl8192cd_priv *priv); +#ifdef PCIE_POWER_SAVING_DEBUG +EXTERN int PCIE_PowerDown(struct rtl8192cd_priv *priv, unsigned char *data); +#endif +#ifdef GPIO_WAKEPIN +EXTERN int request_irq_for_wakeup_pin(struct net_device *dev); +#endif +#endif + +EXTERN void set_slot_time(struct rtl8192cd_priv *priv, int use_short); +EXTERN void SetTxPowerLevel(struct rtl8192cd_priv *priv); +EXTERN void SwChnl(struct rtl8192cd_priv *priv, unsigned char channel, int offset); +#ifdef CONFIG_WLAN_HAL_8192EE +EXTERN void Check_92E_Spur_Valid(struct rtl8192cd_priv *priv, BOOLEAN long_delay); +#endif +EXTERN void enable_hw_LED(struct rtl8192cd_priv *priv, unsigned int led_type); + +EXTERN unsigned int PHY_QueryRFReg(struct rtl8192cd_priv *priv, RF92CD_RADIO_PATH_E eRFPath, + unsigned int RegAddr, unsigned int BitMask, unsigned int dbg_avoid); +EXTERN unsigned int PHY_QueryBBReg(struct rtl8192cd_priv *priv, unsigned int RegAddr, unsigned int BitMask); +EXTERN void PHY_SetBBReg(struct rtl8192cd_priv *priv, unsigned int RegAddr, unsigned int BitMask, unsigned int Data); +EXTERN void PHY_SetRFReg(struct rtl8192cd_priv *priv, RF92CD_RADIO_PATH_E eRFPath, unsigned int RegAddr, + unsigned int BitMask, unsigned int Data); +EXTERN int phy_RF8256_Config_ParaFile(struct rtl8192cd_priv *priv); +//EXTERN int PHY_ConfigMACWithParaFile(struct rtl8192cd_priv *priv); +EXTERN void SwBWMode(struct rtl8192cd_priv *priv, unsigned int bandwidth, int offset); + +EXTERN void setup_timer1(struct rtl8192cd_priv *priv, int timeout); +EXTERN void cancel_timer1(struct rtl8192cd_priv *priv); +EXTERN void setup_timer2(struct rtl8192cd_priv *priv, unsigned int timeout); +EXTERN void cancel_timer2(struct rtl8192cd_priv *priv); + + +//EXTERN void CCK_txpower_by_rssi(struct rtl8192cd_priv *priv, unsigned char rssi_strength); +EXTERN void reload_txpwr_pg(struct rtl8192cd_priv *priv); +EXTERN int rtl8192cd_init_hw_PCI(struct rtl8192cd_priv *priv); +EXTERN int rtl8192cd_stop_hw(struct rtl8192cd_priv *priv); +EXTERN int check_MAC_IO_Enable(struct rtl8192cd_priv *priv); +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) +EXTERN int PHY_ConfigBBWithParaFile(struct rtl8192cd_priv *priv, int reg_file); +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + +EXTERN unsigned int get_mean_of_2_close_value(unsigned int *val_array); +#endif +#ifdef _TRACKING_TABLE_FILE +EXTERN int PHY_ConfigTXPwrTrackingWithParaFile(struct rtl8192cd_priv * priv); +#endif + +#ifdef TXPWR_LMT +EXTERN int PHY_ConfigTXLmtWithParaFile(struct rtl8192cd_priv * priv); +#ifdef TXPWR_LMT_NEWFILE +EXTERN int PHY_ConfigTXLmtWithParaFile_new(struct rtl8192cd_priv * priv); +#endif +#endif + +//EXTERN void tx_path_by_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char enable); +//EXTERN void rx_path_by_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat, int enable); +//EXTERN void rx_path_by_rssi_cck_v2(struct rtl8192cd_priv *priv, struct stat_info *pstat); +//EXTERN void rtl8192cd_tpt_timer(unsigned long task_priv); + + + +//EXTERN void SwitchExtAnt(struct rtl8192cd_priv *priv, unsigned char EXT_ANT_PATH); +//EXTERN void rtl8192cd_ePhyInit(struct rtl8192cd_priv * priv); +//EXTERN void Switch_1SS_Antenna(struct rtl8192cd_priv *priv, unsigned int antPath ); +//EXTERN void Switch_OFDM_Antenna(struct rtl8192cd_priv *priv, unsigned int antPath ); +#ifdef MCR_WIRELESS_EXTEND +#ifdef CONFIG_WLAN_HAL_8814AE +EXTERN int Switch_Antenna_8814(struct rtl8192cd_priv *priv, unsigned char *data); +#endif +#endif +EXTERN void TXPowerTracking(struct rtl8192cd_priv *priv); +EXTERN int get_tx_tracking_index(struct rtl8192cd_priv *priv, int channel, int i, int delta, int is_decrease, int is_CCK); + +// CAM related functions +EXTERN int CamAddOneEntry(struct rtl8192cd_priv *priv, unsigned char *pucMacAddr, + unsigned long ulKeyId, unsigned long ulEncAlg, unsigned long ulUseDK, + unsigned char *pucKey); +EXTERN int CamDeleteOneEntry(struct rtl8192cd_priv *priv, unsigned char *pucMacAddr, + unsigned long ulKeyId, unsigned int useDK); +EXTERN void CamResetAllEntry(struct rtl8192cd_priv *priv); +EXTERN void CamDumpAll(struct rtl8192cd_priv *priv); +EXTERN void CAM_read_entry(struct rtl8192cd_priv *priv, unsigned char index, unsigned char *macad, + unsigned char *key128, unsigned short *config); +EXTERN int get_offset_val(unsigned char *line_head, unsigned int *u4bRegOffset, unsigned int *u4bRegValue); +EXTERN unsigned char *get_line(unsigned char **line); + +#ifdef TXPWR_LMT +EXTERN int ch2idx(int ch); +EXTERN void find_pwr_limit(struct rtl8192cd_priv *priv, int channel, int offset); +#ifdef TXPWR_LMT_NEWFILE +EXTERN void find_pwr_limit_new(struct rtl8192cd_priv *priv, int channel, int offset); +#endif +#endif + +#ifdef POWER_PERCENT_ADJUSTMENT +EXTERN s1Byte PwrPercent2PwrLevel(int percentage); +#endif +#ifdef _DEBUG_RTL8192CD_ +//_TXPWR_REDEFINE +EXTERN int Read_PG_File(struct rtl8192cd_priv *priv, int reg_file, int table_number, + char *MCSTxAgcOffset_A, char *MCSTxAgcOffset_B, char *OFDMTxAgcOffset_A, + char *OFDMTxAgcOffset_B, char *CCKTxAgc_A, char *CCKTxAgc_B); +#endif + + +#ifdef CONFIG_RTL_92D_SUPPORT + EXTERN unsigned char *data_MACPHY_REG_start, *data_MACPHY_REG_end; + EXTERN unsigned char *data_PHY_REG_n_start, *data_PHY_REG_n_end; + EXTERN unsigned char *data_PHY_REG_MP_n_start, *data_PHY_REG_MP_n_end; + EXTERN unsigned char *data_PHY_REG_PG_start, *data_PHY_REG_PG_end; + EXTERN unsigned char *data_PHY_REG_PG_FCC_start, *data_PHY_REG_PG_FCC_end; + EXTERN unsigned char *data_PHY_REG_PG_CE_start, *data_PHY_REG_PG_CE_end; + +#ifdef _TRACKING_TABLE_FILE + EXTERN unsigned char *data_REG_TXPWR_TRK_n_92d_start, *data_REG_TXPWR_TRK_n_92d_end; + EXTERN unsigned char *data_REG_TXPWR_TRK_n_92d_hp_start, *data_REG_TXPWR_TRK_n_92d_hp_end; +#endif + EXTERN unsigned char *data_AGC_TAB_n_start, *data_AGC_TAB_n_end; + EXTERN unsigned char *data_AGC_TAB_2G_n_start, *data_AGC_TAB_2G_n_end; + EXTERN unsigned char *data_AGC_TAB_5G_n_start, *data_AGC_TAB_5G_n_end; + EXTERN unsigned char *data_radio_a_n_start, *data_radio_a_n_end; + EXTERN unsigned char *data_radio_b_n_start, *data_radio_b_n_end; +#ifdef RTL8192D_INT_PA +#ifdef USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) + EXTERN unsigned char *data_radio_a_intPA_GM_new_start, *data_radio_a_intPA_GM_new_end; + EXTERN unsigned char *data_radio_b_intPA_GM_new_start, *data_radio_b_intPA_GM_new_end; +#elif defined (RTL8192D_INT_PA_GAIN_TABLE_NEW1) + EXTERN unsigned char *data_radio_a_intPA_GM_new1_start, *data_radio_a_intPA_GM_new1_end; + EXTERN unsigned char *data_radio_b_intPA_GM_new1_start, *data_radio_b_intPA_GM_new1_end; +#else + EXTERN unsigned char *data_radio_a_intPA_GM_start, *data_radio_a_intPA_GM_end; + EXTERN unsigned char *data_radio_b_intPA_GM_start, *data_radio_b_intPA_GM_end; +#endif + +#else // USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) + EXTERN unsigned char *data_radio_a_intPA_new_start, *data_radio_a_intPA_new_end; + EXTERN unsigned char *data_radio_b_intPA_new_start, *data_radio_b_intPA_new_end; +#else + EXTERN unsigned char *data_radio_a_intPA_start, *data_radio_a_intPA_end; + EXTERN unsigned char *data_radio_b_intPA_start, *data_radio_b_intPA_end; +#endif + +#endif // USB_POWER_SUPPORT +#endif // RTL8192D_INT_PA + +//_TXPWR_REDEFINE +#ifdef HIGH_POWER_EXT_PA + EXTERN unsigned char *data_AGC_TAB_n_92d_hp_start, *data_AGC_TAB_n_92d_hp_end; + EXTERN unsigned char *data_PHY_REG_PG_92d_hp_start, *data_PHY_REG_PG_92d_hp_end; + EXTERN unsigned char *data_PHY_REG_n_92d_hp_start, *data_PHY_REG_n_92d_hp_end; + EXTERN unsigned char *data_radio_a_n_92d_hp_start, *data_radio_a_n_92d_hp_end; + EXTERN unsigned char *data_radio_b_n_92d_hp_start, *data_radio_b_n_92d_hp_end; +#endif + + EXTERN unsigned char *data_rtl8192dfw_n_start, *data_rtl8192dfw_n_end; +#endif // CONFIG_RTL_92D_SUPPORT + +#ifdef CONFIG_RTL_92C_SUPPORT +#ifdef TESTCHIP_SUPPORT + EXTERN unsigned char *data_AGC_TAB_start, *data_AGC_TAB_end; + EXTERN unsigned char *data_PHY_REG_2T_start, *data_PHY_REG_2T_end; + EXTERN unsigned char *data_PHY_REG_1T_start, *data_PHY_REG_1T_end; + EXTERN unsigned char *data_radio_a_1T_start, *data_radio_a_1T_end; + EXTERN unsigned char *data_radio_a_2T_start, *data_radio_a_2T_end; + EXTERN unsigned char *data_radio_b_2T_start, *data_radio_b_2T_end; + EXTERN unsigned char *data_rtl8192cfw_start, *data_rtl8192cfw_end; +#endif + +EXTERN unsigned char *data_AGC_TAB_n_92C_start, *data_AGC_TAB_n_92C_end; +EXTERN unsigned char *data_PHY_REG_2T_n_start, *data_PHY_REG_2T_n_end; +EXTERN unsigned char *data_PHY_REG_1T_n_start, *data_PHY_REG_1T_n_end; +EXTERN unsigned char *data_radio_a_2T_n_start, *data_radio_a_2T_n_end; +EXTERN unsigned char *data_radio_b_2T_n_start, *data_radio_b_2T_n_end; +EXTERN unsigned char *data_radio_a_1T_n_start, *data_radio_a_1T_n_end; +EXTERN unsigned char *data_rtl8192cfw_n_start, *data_rtl8192cfw_n_end; +EXTERN unsigned char *data_rtl8192cfw_ua_start, *data_rtl8192cfw_ua_end; + +EXTERN unsigned char *data_MACPHY_REG_92C_start, *data_MACPHY_REG_92C_end; +EXTERN unsigned char *data_PHY_REG_PG_92C_start, *data_PHY_REG_PG_92C_end; +EXTERN unsigned char *data_PHY_REG_MP_n_92C_start, *data_PHY_REG_MP_n_92C_end; + +EXTERN unsigned char *data_AGC_TAB_n_hp_start, *data_AGC_TAB_n_hp_end; +EXTERN unsigned char *data_PHY_REG_2T_n_lna_start, *data_PHY_REG_2T_n_lna_end; +EXTERN unsigned char *data_PHY_REG_2T_n_hp_start, *data_PHY_REG_2T_n_hp_end; +EXTERN unsigned char *data_PHY_REG_1T_n_hp_start, *data_PHY_REG_1T_n_hp_end; +EXTERN unsigned char *data_radio_a_2T_n_lna_start, *data_radio_a_2T_n_lna_end; +EXTERN unsigned char *data_radio_b_2T_n_lna_start, *data_radio_b_2T_n_lna_end; + +#ifdef HIGH_POWER_EXT_PA + EXTERN unsigned char *data_radio_a_2T_n_hp_start, *data_radio_a_2T_n_hp_end; + EXTERN unsigned char *data_radio_b_2T_n_hp_start, *data_radio_b_2T_n_hp_end; + EXTERN unsigned char *data_PHY_REG_PG_hp_start, *data_PHY_REG_PG_hp_end; +#endif + +#ifdef _TRACKING_TABLE_FILE + EXTERN unsigned char *data_REG_TXPWR_TRK_start, *data_REG_TXPWR_TRK_end; + EXTERN unsigned char *data_REG_TXPWR_TRK_hp_start, *data_REG_TXPWR_TRK_hp_end; +#endif + +#endif // CONFIG_RTL_92C_SUPPORT + +#ifdef CONFIG_RTL_88E_SUPPORT +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +//For 8188E IQK +EXTERN unsigned char *data_AGC_TAB_1T_88E_start, *data_AGC_TAB_1T_88E_end; +EXTERN unsigned char *data_MAC_REG_88E_start, *data_MAC_REG_88E_end; +EXTERN unsigned char *data_PHY_REG_1T_88E_start, *data_PHY_REG_1T_88E_end; +EXTERN unsigned char *data_PHY_REG_MP_88E_start, *data_PHY_REG_MP_88E_end; +EXTERN unsigned char *data_PHY_REG_PG_88E_start, *data_PHY_REG_PG_88E_end; +EXTERN unsigned char *data_radio_a_1T_88E_start, *data_radio_a_1T_88E_end; +#ifdef SUPPORT_RTL8188E_TC +EXTERN unsigned char *data_MAC_REG_88E_TC_start, *data_MAC_REG_88E_TC_end; +EXTERN unsigned char *data_PHY_REG_1T_88E_TC_start, *data_PHY_REG_1T_88E_TC_end; +EXTERN unsigned char *data_radio_a_1T_88E_TC_start, *data_radio_a_1T_88E_TC_end; +#endif +EXTERN unsigned char *data_PHY_REG_PG_88E_new_start, *data_PHY_REG_PG_88E_new_end; +#ifdef TXPWR_LMT_88E +EXTERN unsigned char *data_TXPWR_LMT_88E_new_start, *data_TXPWR_LMT_88E_new_end; +#endif +#endif +#endif // CONFIG_RTL_88E_SUPPORT +#ifdef CONFIG_RTL_8812_SUPPORT +EXTERN unsigned char *data_AGC_TAB_8812_start, *data_AGC_TAB_8812_end; +EXTERN unsigned char *data_MAC_REG_8812_start, *data_MAC_REG_8812_end; +EXTERN unsigned char *data_PHY_REG_8812_start, *data_PHY_REG_8812_end; +EXTERN unsigned char *data_PHY_REG_MP_8812_start, *data_PHY_REG_MP_8812_end; +EXTERN unsigned char *data_PHY_REG_PG_8812_start, *data_PHY_REG_PG_8812_end; +EXTERN unsigned char *data_RadioA_8812_start, *data_RadioA_8812_end; +EXTERN unsigned char *data_RadioB_8812_start, *data_RadioB_8812_end; +#ifdef _TRACKING_TABLE_FILE +EXTERN unsigned char *data_REG_TXPWR_TRK_8812_start, *data_REG_TXPWR_TRK_8812_end; +#ifdef HIGH_POWER_EXT_PA +EXTERN unsigned char *data_REG_TXPWR_TRK_8812_hp_start, *data_REG_TXPWR_TRK_8812_hp_end; +EXTERN unsigned char *data_PHY_REG_PG_8812_hp_start, *data_PHY_REG_PG_8812_hp_end; +#endif +#endif + +//FOR_8812_MP_CHIP +EXTERN unsigned char *data_MAC_REG_8812_n_start, *data_MAC_REG_8812_n_end; +EXTERN unsigned char *data_AGC_TAB_8812_n_default_start, *data_AGC_TAB_8812_n_default_end; +EXTERN unsigned char *data_PHY_REG_8812_n_default_start, *data_PHY_REG_8812_n_default_end; +EXTERN unsigned char *data_RadioA_8812_n_default_start, *data_RadioA_8812_n_default_end; +EXTERN unsigned char *data_RadioB_8812_n_default_start, *data_RadioB_8812_n_default_end; + +EXTERN unsigned char *data_AGC_TAB_8812_n_extlna_start, *data_AGC_TAB_8812_n_extlna_end; +EXTERN unsigned char *data_PHY_REG_8812_n_extlna_start, *data_PHY_REG_8812_n_extlna_end; +EXTERN unsigned char *data_RadioA_8812_n_extlna_start, *data_RadioA_8812_n_extlna_end; +EXTERN unsigned char *data_RadioB_8812_n_extlna_start, *data_RadioB_8812_n_extlna_end; + +EXTERN unsigned char *data_AGC_TAB_8812_n_extpa_start, *data_AGC_TAB_8812_n_extpa_end; +EXTERN unsigned char *data_PHY_REG_8812_n_extpa_start, *data_PHY_REG_8812_n_extpa_end; +EXTERN unsigned char *data_RadioA_8812_n_extpa_start, *data_RadioA_8812_n_extpa_end; +EXTERN unsigned char *data_RadioB_8812_n_extpa_start, *data_RadioB_8812_n_extpa_end; + +EXTERN unsigned char *data_AGC_TAB_8812_hp_start, *data_AGC_TAB_8812_hp_end; +EXTERN unsigned char *data_RadioA_8812_hp_start, *data_RadioA_8812_hp_end; +EXTERN unsigned char *data_RadioB_8812_hp_start, *data_RadioB_8812_hp_end; + +//FOR_8812_MP_CHIP +EXTERN unsigned char *data_AGC_TAB_8812_n_hp_start, *data_AGC_TAB_8812_n_hp_end; +EXTERN unsigned char *data_PHY_REG_8812_n_hp_start, *data_PHY_REG_8812_n_hp_end; +EXTERN unsigned char *data_RadioA_8812_n_hp_start, *data_RadioA_8812_n_hp_end; +EXTERN unsigned char *data_RadioB_8812_n_hp_start, *data_RadioB_8812_n_hp_end; +EXTERN unsigned char *data_RadioA_8812_n_ultra_hp_start, *data_RadioA_8812_n_ultra_hp_end; +EXTERN unsigned char *data_RadioB_8812_n_ultra_hp_start, *data_RadioB_8812_n_ultra_hp_end; + +EXTERN unsigned char *data_PHY_REG_PG_8812_new_start, *data_PHY_REG_PG_8812_new_end; +#ifdef TXPWR_LMT_8812 +EXTERN unsigned char *data_TXPWR_LMT_8812_new_start, *data_TXPWR_LMT_8812_new_end; +#endif + +#endif + +EXTERN void PHY_IQCalibrate(struct rtl8192cd_priv *priv); + +#ifdef TX_EARLY_MODE +EXTERN void enable_em(struct rtl8192cd_priv *priv); +EXTERN void disable_em(struct rtl8192cd_priv *priv); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(CALIBRATE_BY_ODM) +EXTERN void PHY_RF6052SetCCKTxPower(struct rtl8192cd_priv *priv, unsigned int channel); +EXTERN void PHY_RF6052SetOFDMTxPower(struct rtl8192cd_priv *priv, unsigned int channel); +#endif +#ifdef RTLWIFINIC_GPIO_CONTROL +EXTERN void RTLWIFINIC_GPIO_init_priv(struct rtl8192cd_priv *priv); +EXTERN void RTLWIFINIC_GPIO_config(unsigned int gpio_num, unsigned int direction); +EXTERN void RTLWIFINIC_GPIO_write(unsigned int gpio_num, unsigned int value); +EXTERN int RTLWIFINIC_GPIO_read(unsigned int gpio_num); +#endif + + +#ifdef AC2G_256QAM +EXTERN char is_ac2g(struct rtl8192cd_priv* priv); +#endif + +#ifdef CONFIG_1RCCA_RF_POWER_SAVING +void set_1rcca_ps(struct rtl8192cd_priv *priv, int enable); +#endif + +#if defined(HS2_SUPPORT) || defined(RTK_NL80211)//survey_dump +EXTERN void start_bbp_ch_load(struct rtl8192cd_priv *priv, unsigned int units); +EXTERN int read_bbp_ch_load(struct rtl8192cd_priv *priv); +#endif + + +#undef EXTERN + + + + +#ifdef CONFIG_RTL_92D_SUPPORT +/*----------------------------------------------------------------------------- + 8192d_hw.c +------------------------------------------------------------------------------*/ +#ifndef _8192D_HW_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +#ifdef CONFIG_RTL_92D_DMDP +EXTERN unsigned int DMDP_RTL_R32(unsigned int phy,unsigned int reg); +EXTERN unsigned short DMDP_RTL_R16(unsigned int phy,unsigned int reg); +EXTERN unsigned char DMDP_RTL_R8(unsigned int phy,unsigned int reg); +EXTERN void DMDP_RTL_W32(unsigned int phy,unsigned int reg,unsigned int val32); +EXTERN void DMDP_RTL_W16(unsigned int phy,unsigned int reg,unsigned short val16); +EXTERN void DMDP_RTL_W8(unsigned int phy,unsigned int reg,unsigned char val8); +EXTERN unsigned int DMDP_PHY_QueryBBReg(unsigned int phy,unsigned int RegAddr,unsigned int BitMask); +EXTERN void DMDP_PHY_SetBBReg(unsigned int phy,unsigned int RegAddr,unsigned int BitMask,unsigned int Data); +EXTERN unsigned int DMDP_PHY_QueryRFReg(unsigned int phy,RF92CD_RADIO_PATH_E eRFPath,unsigned int RegAddr,unsigned int BitMask,unsigned int dbg_avoid); +EXTERN void DMDP_PHY_SetRFReg(unsigned int phy,RF92CD_RADIO_PATH_E eRFPath,unsigned int RegAddr,unsigned int BitMask,unsigned int Data); +EXTERN void clnt_load_IQK_res(struct rtl8192cd_priv * priv); +#endif + +EXTERN int Load_92D_Firmware(struct rtl8192cd_priv *priv); +EXTERN void UpdateBBRFVal8192DE(struct rtl8192cd_priv *priv); +EXTERN void Update92DRFbyChannel(struct rtl8192cd_priv * priv,unsigned char channel); + + +EXTERN void SetSYN_para(struct rtl8192cd_priv *priv, unsigned char channel); +EXTERN void SetIMR_n(struct rtl8192cd_priv * priv, unsigned char channel); +EXTERN void IQK_92D_2G(struct rtl8192cd_priv * priv); +EXTERN void IQK_92D_5G_n(struct rtl8192cd_priv * priv); +#ifdef CONFIG_RTL_92D_DMDP +EXTERN void IQK_92D_5G_phy0_n(struct rtl8192cd_priv * priv); +#endif + +#ifdef DPK_92D +EXTERN void rtl8192cd_DPK_timer(unsigned long task_priv); +EXTERN void PHY_DPCalibrate(struct rtl8192cd_priv *priv); +#endif + +#undef EXTERN + +#endif //CONFIG_RTL_92D_SUPPORT + + + +/*----------------------------------------------------------------------------- + 8192cd_ioctl.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_IOCTL_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +#if defined (CONFIG_RTL_COMAPI_WLTOOLS) || defined (WIFI_WPAS) +EXTERN const struct iw_handler_def rtl8192cd_iw_handler_def; + +#endif + +EXTERN int _convert_2_pwr_dot(char *s, int base); +EXTERN int _atoi(char *s, int base); +EXTERN void set_mib_default_tbl(struct rtl8192cd_priv *priv); +EXTERN int get_array_val (unsigned char *dst, char *src, int len); +EXTERN int del_sta(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void drvmac_loopback(struct rtl8192cd_priv *priv); +EXTERN int rtl8192cd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +#ifdef SUPPORT_TX_MCAST2UNI +EXTERN int ioctl_AddDelMCASTGroup2STA(struct net_device *dev, struct ifreq *ifr, int cmd); +#endif + + +#ifdef INCLUDE_WPS +EXTERN int set_mib(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int get_mib(struct rtl8192cd_priv *priv, unsigned char *data); +#endif + +#ifdef CONFIG_RTL8186_KB +EXTERN int set_guestmacinvalid(struct rtl8192cd_priv *priv, char *buf); +#endif + +#ifdef CONFIG_RTL8672 +// MBSSID Port Mapping +struct port_map { + struct net_device *dev_pointer; + int dev_ifgrp_member; +}; +#endif + +#ifdef CONFIG_RTL_COMAPI_WLTOOLS +EXTERN int set_mib(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int rtl8192cd_ss_req(struct rtl8192cd_priv *priv, unsigned char *data, int len); +#endif +EXTERN void delay_us(unsigned int t); +EXTERN void delay_ms(unsigned int t); + +#if defined(WIFI_WPAS) || defined(RTK_NL80211) +EXTERN int check_bss_encrypt(struct rtl8192cd_priv *priv); +#endif + +#ifdef RTK_NL80211 +EXTERN void rtl8192cd_init_one_cfg80211(struct rtknl *rtk); +#endif + +#if defined(SMP_SYNC) && defined(__KERNEL__) & defined(CONFIG_PCI_HCI) +EXTERN unsigned long _ioctl_copy_from_user (struct rtl8192cd_priv *priv, void * to, const void * from, unsigned long n); +EXTERN unsigned long _ioctl_copy_to_user (struct rtl8192cd_priv *priv, void * to, const void * from, unsigned long n); + +#define ioctl_copy_from_user(to,from,n) _ioctl_copy_from_user(priv,to,from,n) +#define ioctl_copy_to_user(to,from,n) _ioctl_copy_to_user(priv,to,from,n) +#else +#define ioctl_copy_from_user(to,from,n) copy_from_user(to,from,n) +#define ioctl_copy_to_user(to,from,n) copy_to_user(to,from,n) +#endif + +#undef EXTERN + + + + +#if 0 //move to hw.c +/*----------------------------------------------------------------------------- + 8190n_cam.c +------------------------------------------------------------------------------*/ +#ifndef _8190N_CAM_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int CamAddOneEntry(struct rtl8190_priv *priv, unsigned char *pucMacAddr, + unsigned long ulKeyId, unsigned long ulEncAlg, unsigned long ulUseDK, + unsigned char *pucKey); +EXTERN int CamDeleteOneEntry(struct rtl8190_priv *priv, unsigned char *pucMacAddr, + unsigned long ulKeyId, unsigned int useDK); +EXTERN void CamResetAllEntry(struct rtl8190_priv *priv); +EXTERN void CamDumpAll(struct rtl8190_priv *priv); +EXTERN void CAM_read_entry(struct rtl8190_priv *priv, unsigned char index, unsigned char *macad, + unsigned char *key128, unsigned short *config); + +#undef EXTERN +#endif + + + + +/*----------------------------------------------------------------------------- + 8192cd_security.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_SECURITY_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int DOT11_Indicate_MIC_Failure(struct net_device *dev, struct stat_info *pstat); +EXTERN void DOT11_Indicate_MIC_Failure_Clnt(struct rtl8192cd_priv *priv, unsigned char *sa); + +EXTERN void DOT11_Process_MIC_Timerup(unsigned long data); +EXTERN void DOT11_Process_Reject_Assoc_Timerup(unsigned long data); + +EXTERN int rtl8192cd_ioctl_priv_daemonreq(struct net_device *dev, struct iw_point *data); +EXTERN int DOT11_Process_Delete_Key(struct net_device *dev, struct iw_point *data); +EXTERN int DOT11_Process_Set_Key(struct net_device *dev, struct iw_point *data, + DOT11_SET_KEY *pSetKey, unsigned char *pKey); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +EXTERN int __DOT11_Indicate_MIC_Failure(struct net_device *dev, struct stat_info *pstat); +EXTERN void __DOT11_Indicate_MIC_Failure_Clnt(struct rtl8192cd_priv *priv, unsigned char *sa); +EXTERN int __DOT11_Process_Disconnect_Req(struct net_device *dev, struct iw_point *data); +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_tkip.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_TKIP_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void tkip_icv(unsigned char *picv, unsigned char *frag1, unsigned int frag1_len, + unsigned char *frag2,unsigned int frag2_len); +EXTERN void tkip_encrypt(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, + unsigned int hdrlen, unsigned char *frag1, unsigned int frag1_len, + unsigned char *frag2, unsigned int frag2_len, unsigned char *frag3, + unsigned int frag3_len); +EXTERN void michael(struct rtl8192cd_priv *priv, unsigned char *key, unsigned char *hdr, + unsigned char *llc, unsigned char *message, int message_length, unsigned char *mic, int tx); +EXTERN unsigned int tkip_decrypt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, + unsigned int fr_len); +EXTERN int tkip_rx_mic(struct rtl8192cd_priv *priv, unsigned char *pframe, unsigned char *da, + unsigned char *sa, unsigned char priority, unsigned char *pbuf, unsigned int len, + unsigned char *tkipmic, int no_wait); +EXTERN void debug_out(unsigned char *label, unsigned char *data, int data_length); +EXTERN unsigned int wep_decrypt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, + unsigned int fr_len, int type, int keymap); +EXTERN void wep_encrypt(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, unsigned int hdrlen, + unsigned char *frag1, unsigned int frag1_len, + unsigned char *frag2, unsigned int frag2_len, + unsigned char *frag3, unsigned int frag3_len, + int type); +EXTERN void init_crc32_table(void); + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_aes.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_AES_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void aesccmp_encrypt(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, + unsigned char *frag1,unsigned char *frag2, unsigned int frag2_len, + unsigned char *frag3 +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ); +EXTERN unsigned int aesccmp_decrypt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo +#ifdef CONFIG_IEEE80211W + ,unsigned char isMgmt +#endif + ); + +EXTERN int omac1_aes_128(const unsigned char *key, const unsigned char *data, + int data_len, unsigned char *mac); +EXTERN void sha256_prf(const unsigned char *key, size_t key_len, const char *label, + const unsigned char *data, size_t data_len, unsigned char *buf, size_t buf_len); +EXTERN int hmac_sha256_vector(const unsigned char *key, size_t key_len, size_t num_elem, + const unsigned char *addr[], const size_t *len, unsigned char *mac); +EXTERN int aesccmp_checkmic(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, unsigned char *pmic); +EXTERN int hmac_sha256(const unsigned char *key, size_t key_len, const unsigned char *data, + size_t data_len, unsigned char *mac); + +#ifdef CONFIG_IEEE80211W +EXTERN void BIP_encrypt(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, + unsigned char *frag1, + unsigned char *frag2, unsigned int frag2_len, + unsigned char *frag3, + unsigned char isMgmt); +EXTERN int MMIE_check(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN int issue_SA_Query_Rsp(struct net_device *dev, unsigned char *da, unsigned char *trans_id); +EXTERN int issue_SA_Query_Req(struct net_device *dev, unsigned char *da); +EXTERN void rtl8192cd_sa_query_timer(unsigned long task_priv); +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_proc.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_PROC_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +#ifdef _INCLUDE_PROC_FS_ +EXTERN void rtl8192cd_proc_init (struct net_device *dev); +EXTERN void rtl8192cd_proc_remove (struct net_device *dev); +#endif + +#if defined(_INCLUDE_PROC_FS_) || defined(__ECOS) +#ifdef __ECOS +EXTERN const char* MCS_DATA_RATEStr[2][2][24]; +#else +EXTERN const unsigned char* MCS_DATA_RATEStr[2][2][24]; +#endif +#endif + +#ifdef RTK_AC_SUPPORT +EXTERN int query_vht_rate(struct stat_info *pstat); +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_br_ext.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_BR_EXT_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +#ifdef RTK_BR_EXT +EXTERN void nat25_db_cleanup(struct rtl8192cd_priv *priv); +EXTERN void nat25_db_expire(struct rtl8192cd_priv *priv); +EXTERN int nat25_db_handle(struct rtl8192cd_priv *priv, struct sk_buff *skb, int method); +EXTERN int nat25_handle_frame(struct rtl8192cd_priv *priv, struct sk_buff *skb); +EXTERN int mac_clone_handle_frame(struct rtl8192cd_priv *priv, struct sk_buff *skb); +EXTERN void dhcp_flag_bcast(struct rtl8192cd_priv *priv, struct sk_buff *skb); +EXTERN void dhcp_dst_bcast(struct rtl8192cd_priv * priv,struct sk_buff * skb); +EXTERN void *scdb_findEntry(struct rtl8192cd_priv *priv, unsigned char *macAddr, unsigned char *ipAddr); +#ifdef __ECOS +EXTERN void nat25_db_init(void); +#endif +#ifdef MULTI_MAC_CLONE +EXTERN int mclone_find_address(struct rtl8192cd_priv *priv, unsigned char *addr, struct sk_buff *pskb, unsigned char direction); +EXTERN int mclone_dhcp_caddr(struct rtl8192cd_priv *priv, struct sk_buff *skb); +#endif +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_eeprom.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_EEPROM_C_ +#define EXTERN extern +#else +#define EXTERN +#endif +/* +EXTERN int ReadAdapterInfo(struct rtl8192cd_priv *priv, int entry_id, void *data); +EXTERN int WriteAdapterInfo(struct rtl8192cd_priv *priv, int entry_id, void *data); +*/ +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_osdep.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_OSDEP_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int rtl8192cd_set_hwaddr(struct net_device *dev, void *addr); +EXTERN int rtl8192cd_open (struct net_device *dev); +EXTERN int rtl8192cd_close(struct net_device *dev); +EXTERN void update_fwtbl_asoclst(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void clear_shortcut_cache(void); +#ifdef CONFIG_WLAN_HAL +EXTERN BOOLEAN Wlan_HAL_Link(struct rtl8192cd_priv *priv); +#endif +#ifdef WDS +#ifdef LAZY_WDS +EXTERN void delete_wds_entry(struct rtl8192cd_priv *priv, struct stat_info *pstat); +#endif +EXTERN struct stat_info *add_wds_entry(struct rtl8192cd_priv *priv, int idx, unsigned char *mac); +#endif + +EXTERN int get_bonding_type_8881A(void); + +EXTERN void rtl8192cd_set_mbssid(struct rtl8192cd_priv *priv, unsigned char *macAddr, unsigned char index); +EXTERN void rtl8192cd_clear_mbssid(struct rtl8192cd_priv *priv, unsigned char index); +#ifdef MULTI_MAC_CLONE +EXTERN void mclone_set_mbssid(struct rtl8192cd_priv *priv, unsigned char *macAddr); +EXTERN void mclone_stop_mbssid(struct rtl8192cd_priv *priv, int entIdx); +#endif + +#ifdef TPT_THREAD +EXTERN int kTPT_thread(void *p); +EXTERN int kTPT_task_init(struct rtl8192cd_priv *priv); +EXTERN void kTPT_task_stop(struct rtl8192cd_priv *priv); +#endif + +#ifdef BR_SHORTCUT +#ifdef RTL_CACHED_BR_STA +EXTERN void release_brsc_cache(unsigned char* da); +#endif +EXTERN __MIPS16 __IRAM_IN_865X struct net_device *get_shortcut_dev(unsigned char *da); +#endif // BR_SHORTCUT + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_host.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_HOST_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int PCIE_reset_procedure(int portnum, int ext_clk, int mdio_reset, unsigned long conf_addr); +EXTERN void HostPCIe_Close(void); + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_psk.c +------------------------------------------------------------------------------*/ +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) +#ifndef _8192CD_PSK_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void ConstructIE(struct rtl8192cd_priv *priv, unsigned char *pucOut, int *usOutLen); +EXTERN void derivePSK(struct rtl8192cd_priv *priv); +EXTERN void psk_init(struct rtl8192cd_priv *priv); +EXTERN int psk_indicate_evt(struct rtl8192cd_priv *priv, int id, + unsigned char *mac, unsigned char *msg, int len); + +EXTERN void nl80211_psk_init(struct rtl8192cd_priv *priv); +EXTERN int nl80211_psk_indicate_evt(struct rtl8192cd_priv *priv, int id, + unsigned char *mac, unsigned char *msg, int len); + +EXTERN void ToDrv_SetGTK(struct rtl8192cd_priv *priv); +#ifdef WDS +EXTERN void wds_psk_init(struct rtl8192cd_priv *priv); +EXTERN void wds_psk_set(struct rtl8192cd_priv *priv, int idx, unsigned char *key); +#if defined(WIFI_HAPD) || defined(RTK_NL80211) +EXTERN void hapd_set_wdskey(struct net_device *dev, char *wdsPskPassPhrase, char *ssid, int wds_num); +#endif +#endif +#ifdef CLIENT_MODE +EXTERN void ClientSendEAPOL(struct rtl8192cd_priv *priv, struct stat_info *pstat, int resend); +#ifdef SUPPORT_CLIENT_MIXED_SECURITY +EXTERN void choose_cipher(struct rtl8192cd_priv *priv, struct bss_desc *bss_target); +#endif +#endif //CLIENT_MODE +#endif // INCLUDE_WPA_PSK + +EXTERN void UKRekeyTimeout(struct rtl8192cd_priv *priv, struct stat_info *pstat); + +#ifdef CONFIG_RTK_MESH +EXTERN void dot11s_mp_set_key(DRV_PRIV *priv, unsigned char *mac); +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_mp.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_MP_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN char *get_value_by_token(char *data, char *token); +EXTERN void mp_start_test(struct rtl8192cd_priv *priv); +EXTERN void mp_stop_test(struct rtl8192cd_priv *priv); +EXTERN void mp_set_datarate(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_set_channel(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_set_bandwidth(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_set_tx_power(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_ctx(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int mp_query_stats(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_txpower_tracking(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int mp_query_tssi(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int mp_query_ther(struct rtl8192cd_priv *priv, unsigned char *data); +#ifdef MP_PSD_SUPPORT +EXTERN int mp_query_psd(struct rtl8192cd_priv *priv, unsigned char * data); +#endif +EXTERN int mp_tx(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_validate_rx_packet(struct rtl8192cd_priv *priv, unsigned char *data, int len); +EXTERN int mp_brx(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int mp_arx(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_set_bssid(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_set_ant_tx(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_set_ant_rx(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void mp_set_phypara(struct rtl8192cd_priv *priv, unsigned char *data); + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) +EXTERN void mp_set_phyBand(struct rtl8192cd_priv * priv, unsigned char * data); +#endif + +EXTERN void mp_reset_stats(struct rtl8192cd_priv * priv); +EXTERN int mp_get_txpwr(struct rtl8192cd_priv *priv, unsigned char *data); +#if defined(CONFIG_RTL_8812_SUPPORT) +EXTERN void mp_dig(struct rtl8192cd_priv *priv, unsigned char *data); +#endif +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8192cd_mib.c +------------------------------------------------------------------------------*/ +#ifdef SUPPORT_SNMP_MIB + +#ifndef _8192CD_MIB_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int mib_get(struct rtl8192cd_priv *priv, char *oid, unsigned char *data, int *pLen); +EXTERN void mib_init(struct rtl8192cd_priv *priv); + +#undef EXTERN + +#endif // SUPPORT_SNMP_MIB + + + + +/*----------------------------------------------------------------------------- + 8192cd_comapi.c +------------------------------------------------------------------------------*/ + +#ifndef _8192CD_COMAPI_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +#ifdef CONFIG_RTL_COMAPI_WLTOOLS +#include +/* +EXTERN struct iw_statistics *rtl8192cd_get_wireless_stats(struct net_device *net_dev); +*/ +#ifdef WIFI_WPAS_CLI +EXTERN int rtl_wx_dummy(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_wx_get_name(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_wx_set_mode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_wx_get_sens(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +#if WIRELESS_EXT >= 18 +EXTERN int rtl_wx_set_mlme(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *extra); +#endif +EXTERN int rtl_wx_get_freq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + +EXTERN int rtl_gipriv(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_sipriv(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +#endif // WIFI_WPAS_CLI + +EXTERN int rtl_siwfreq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwfreq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwmode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwmode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwrange(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwap(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwap(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_iwaplist(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra); +EXTERN int rtl_siwessid(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *essid); +EXTERN int rtl_giwessid(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *essid); +EXTERN int rtl_siwrate(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwrate(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwrts(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwrts(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwfrag(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwfrag(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwretry(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwretry(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwencode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *keybuf); +EXTERN int rtl_giwencode(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *key); +EXTERN int rtl_giwpower(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwscan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwscan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + +#ifdef WIFI_WPAS_CLI +EXTERN int rtl_siwgenie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwauth(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwauth(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwencodeext(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_giwencodeext(struct net_device *ndev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_siwpmkid(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +#endif // WIFI_WPAS_CLI + +#endif + +#ifdef CONFIG_RTL_COMAPI_CFGFILE + +EXTERN int CfgFileProc(struct net_device *dev); +EXTERN int CfgFileRead(struct net_device *dev, char *buf); + +#endif // CONFIG_RTL_COMAPI_CFGFILE + +#undef EXTERN + + +#define EXTERN extern +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU) +/*----------------------------------------------------------------------------- + passthrough/8192cd_osdep.c +------------------------------------------------------------------------------*/ +EXTERN int passThruStatusWlan; +EXTERN int passThruWanIdx; +#endif +EXTERN struct _device_info_ wlan_device[]; +#undef EXTERN + +#ifdef WIFI_WPAS + +#define EXTERN extern +EXTERN int rtl_net80211_setoptie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +EXTERN int rtl_wpas_custom(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + +#undef EXTERN + +#endif + + + + +#ifdef CONFIG_RTK_MESH +/*----------------------------------------------------------------------------- + mesh_ext/mesh_proc.c +------------------------------------------------------------------------------*/ +#ifndef _MESH_PROC_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int dump_mesh_one_mpflow_sta(int num, struct stat_info *pstat, char *buf, char **start, off_t offset, int length, int *eof, void *data); +EXTERN int mesh_proc_flow_stats(char *buf, char **start, off_t offset, int length, int *eof, void *data); +EXTERN int mesh_proc_flow_stats_write(struct file *file, const char *buffer, unsigned long count, void *data); +EXTERN int mesh_assoc_mpinfo(char *buf, char **start, off_t offset, int length, int *eof, void *data); + +#ifdef MESH_BOOTSEQ_AUTH +EXTERN int mesh_auth_mpinfo(char *buf, char **start, off_t offset, int length, int *eof, void *data); +#endif + +EXTERN int mesh_unEstablish_mpinfo(char *buf, char **start, off_t offset, int length, int *eof, void *data); +EXTERN int mesh_pathsel_routetable_info(char *buf, char **start, off_t offset, int length, int *eof, void *data); +EXTERN int mesh_portal_table_info(char *buf, char **start, off_t offset, int length, int *eof, void *data); +EXTERN int mesh_stats(char *buf, char **start, off_t offset, int length, int *eof, void *data); +EXTERN int mesh_proxy_table_info(char *buf, char **start, off_t offset, int length, int *eof, void *data); +EXTERN int mesh_root_info(char *buf, char **start, off_t offset, int length, int *eof, void *data); +#ifdef MESH_USE_METRICOP +EXTERN int mesh_metric_w (struct file *file, const char *buffer, unsigned long count, void *data); +EXTERN int mesh_metric_r(char *buf, char **start, off_t offset, int length, int *eof, void *data); +#endif +#if DBG_NCTU_MESH +EXTERN int mesh_setDebugLevel (struct file *file, const char *buffer, unsigned long count, void *data); +EXTERN int mesh_hasDebugLevel (int lv); +EXTERN int mesh_clearDebugLevel (int lv); +EXTERN int mesh_showAllSkbs(char *buf, char **start, off_t offset, int length, int *eof, void *data); +EXTERN int mesh_decMySkb(struct sk_buff *); +EXTERN int mesh_tagMySkb(struct sk_buff *, UINT8); +EXTERN int mesh_isMySkb(struct sk_buff *); +EXTERN int mesh_showSpecificSkbs(UINT8 type); +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + mesh_ext/mesh_route.c +------------------------------------------------------------------------------*/ +#ifndef _MESH_ROUTE_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void mesh_standalone_timer_expire(struct rtl8192cd_priv*); +EXTERN void aodv_expire(void *task_priv); +EXTERN unsigned short chkMeshSeq(struct path_sel_entry *pPathselEntry, unsigned char *srcMac, unsigned short seq); +EXTERN void GEN_PREQ_PACKET(char *targetMac, struct rtl8192cd_priv *priv, char insert); +EXTERN unsigned short getMeshSeq(struct rtl8192cd_priv *priv); +EXTERN unsigned short getMeshMulticastSeq(DRV_PRIV *priv); +EXTERN void init_mpp_pool(struct mpp_tb* pTB); +EXTERN void notifyPathSelection(struct rtl8192cd_priv *priv); +EXTERN struct path_sel_entry *pathsel_query_table(struct rtl8192cd_priv* ,unsigned char destaddr[MACADDRLEN] ); +EXTERN int pathsel_modify_table_entry(struct rtl8192cd_priv *priv, struct path_sel_entry *pEntry); +EXTERN int pathsel_table_entry_insert_tail(struct rtl8192cd_priv *priv, struct path_sel_entry *pEntry); +EXTERN int remove_path_entry(struct rtl8192cd_priv *priv,unsigned char invalid_addr[MACADDRLEN]); +EXTERN int sync_proxy_info(struct rtl8192cd_priv *priv,unsigned char *sta, unsigned char action); +EXTERN int set_metric_manually(struct rtl8192cd_priv *,unsigned char *); + +#ifdef MESH_ROUTE_MAINTENANCE +EXTERN void route_maintenance(struct rtl8192cd_priv *priv); +#endif + +#ifdef PU_STANDARD +EXTERN UINT8 getPUSeq(struct rtl8192cd_priv *priv); +#endif + +EXTERN unsigned char* getMeshHeader(struct rtl8192cd_priv *priv, int wep_mode, unsigned char* pframe); + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + mesh_ext/mesh_rx.c +------------------------------------------------------------------------------*/ +#ifndef _MESH_RX_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int process_11s_datafrme(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, struct stat_info *pstat); +EXTERN int rx_dispatch_mesh(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN int mesh_shortcut_update(DRV_PRIV *priv, struct rx_frinfo *pfrinfo, struct stat_info *pstat, int idx, struct path_sel_entry **pEntry, struct MESH_HDR ** meshHdrPtr); + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + mesh_ext/mesh_tx.c +------------------------------------------------------------------------------*/ +#ifndef _MESH_TX_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void do_aodv_routing(struct rtl8192cd_priv *priv, struct sk_buff *skb, unsigned char *Mesh_dest); +#if defined(MESH_TX_SHORTCUT) +//EXTERN int mesh_txsc_decision(struct stat_info * pstat, struct tx_insn *txcfg); +EXTERN int mesh_txsc_decision(struct tx_insn* cfgNew, struct tx_insn* cfgOld); +#endif + +__IRAM_IN_865X +EXTERN int mesh_start_xmit(struct sk_buff *skb, struct net_device *dev); +EXTERN int dot11s_datapath_decision(struct sk_buff *skb, /*struct net_device *dev,*/ struct tx_insn* ptxinsn, int isUpdateProxyTable); +EXTERN int notify_path_found(unsigned char *destaddr, struct rtl8192cd_priv *priv); +EXTERN int relay_11s_dataframe(DRV_PRIV *priv, struct sk_buff *skb, int privacy, struct rx_frinfo *pfrinfo); +EXTERN void toAllPortal(struct sk_buff *pskb,struct rtl8192cd_priv *priv); + +#ifdef _11s_TEST_MODE_ +EXTERN void galileo_timer(unsigned long task_priv); +EXTERN void issue_test_traffic(struct sk_buff *skb); +EXTERN void signin_txdesc_galileo(struct rtl8192cd_priv *priv, struct tx_insn* txcfg); +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + mesh_ext/mesh_sme.c +------------------------------------------------------------------------------*/ +#ifndef _MESH_SME_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int init_mesh(struct rtl8192cd_priv *priv); +EXTERN unsigned int acl_query(struct rtl8192cd_priv *priv, unsigned char *sa); +EXTERN int close_MeshPeerLink(struct rtl8192cd_priv *priv, UINT8 *da); +EXTERN int is_11s_mgt_frame(int num, struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN unsigned int issue_assocreq_MP(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void issue_assocrsp_MP(struct rtl8192cd_priv *priv, unsigned short status, struct stat_info *pstat, int pkt_type); +EXTERN void issue_disassoc_MP(struct rtl8192cd_priv * priv, struct stat_info * pstat, int reason, UINT8 peerLinkReason); +EXTERN void issue_probereq_MP(struct rtl8192cd_priv *priv, unsigned char *ssid, int ssid_len, unsigned char *da, int is_11s); + +#ifdef MESH_BOOTSEQ_AUTH +EXTERN void mesh_auth_timer(unsigned long pVal); +#endif + +EXTERN void mesh_expire(struct rtl8192cd_priv* priv); +EXTERN void mesh_proxy_update(struct rtl8192cd_priv *priv, unsigned char *pframe); +EXTERN unsigned int mesh_ie_MeshID(struct rtl8192cd_priv *priv, UINT8 meshiearray[], UINT8 isWildcard); +EXTERN unsigned int mesh_ie_WLANMeshCAP(struct rtl8192cd_priv *priv, UINT8 meshiearray[]); +EXTERN unsigned int mesh_ie_OFDM(struct rtl8192cd_priv *priv, UINT8 meshiearray[]); +EXTERN unsigned int mesh_ie_MeshChannelSwitch(DRV_PRIV *priv, UINT8 meshiearray[]); +EXTERN unsigned int mesh_ie_ChannelSwitchAnnoun(DRV_PRIV *priv, UINT8 meshiearray[]); +EXTERN unsigned int mesh_ie_SecondaryChannelOffset(DRV_PRIV *priv, UINT8 meshiearray[]); +EXTERN void mesh_peer_link_timer(unsigned long pVal); +EXTERN unsigned int OnAssocReq_MP(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN unsigned int OnAssocRsp_MP(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN unsigned int OnBeacon_MP(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN unsigned int OnDisassoc_MP(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN unsigned int OnProbeReq_MP(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN unsigned int OnProbeRsp_MP(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN unsigned int OnPathSelectionManagFrame(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, int Is_6Addr); +EXTERN void OnLocalLinkStateANNOU_MP(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN int start_MeshPeerLink(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, struct stat_info *pstat, UINT16 cap); +EXTERN int mesh_channel_switch_initiate(struct rtl8192cd_priv *priv); + +#ifdef PU_STANDARD +EXTERN void issue_proxyupdate_MP(struct rtl8192cd_priv *priv, struct proxyupdate_table_entry *); +EXTERN void issue_proxyupdate_ADD(struct rtl8192cd_priv *, unsigned char *); +EXTERN void OnProxyUpdate_MP(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN void OnProxyUpdateConfirm_MP(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +#endif +//#ifdef _11s_TEST_MODE_ +EXTERN void mac12_to_6(unsigned char *in, unsigned char *out); +//#endif + +EXTERN int check_dz_mgmt(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct tx_insn* txcfg); +EXTERN int issue_BSS_TxMgmt_req(struct rtl8192cd_priv *priv, unsigned char *da); +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + mesh_ext/mesh_util.c +------------------------------------------------------------------------------*/ +#ifndef _MESH_UTIL_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void mesh_cnt_ASSOC_PeerLink_CAP(struct rtl8192cd_priv *priv, struct stat_info *pstat, int act); +EXTERN void mesh_set_PeerLink_CAP(struct rtl8192cd_priv *priv, UINT16 meshCapSetValue); + + +#ifdef _11s_TEST_MODE_ +EXTERN void mac12_to_6(unsigned char*, unsigned char*); +#endif + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + mesh_ext/mesh_security.c +------------------------------------------------------------------------------*/ +#ifndef _MESH_SECURITY_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int DOT11_EnQueue2(unsigned long task_priv, DOT11_QUEUE2 *q, unsigned char *item, int itemsize); +EXTERN int DOT11_DeQueue2(unsigned long task_priv, DOT11_QUEUE2 *q, unsigned char *item, int *itemsize); +EXTERN void DOT11_InitQueue2(DOT11_QUEUE2 * q, int szMaxItem, int szMaxData); + +#undef EXTERN + +#endif // CONFIG_RTK_MESH + + + + +/*----------------------------------------------------------------------------- + 8192cd_a4_sta.c +------------------------------------------------------------------------------*/ +#ifdef A4_STA +#ifndef _8192CD_A4_STA_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void a4_sta_cleanup(struct rtl8192cd_priv *priv); +EXTERN void a4_sta_expire(struct rtl8192cd_priv *priv); +EXTERN void a4_sta_add(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char *mac); +EXTERN struct stat_info *a4_sta_lookup(struct rtl8192cd_priv *priv, unsigned char *mac); + +#undef EXTERN + +#endif + + + + +/*----------------------------------------------------------------------------- + HALDM_OUTSRC.c +------------------------------------------------------------------------------*/ +#ifndef _HALDM_COMMON_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +// Rate Adaptive +EXTERN void check_RA_by_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void add_RATid(struct rtl8192cd_priv *priv, struct stat_info *pstat); + +EXTERN int getIGIFor1RCCA(int value_IGI); +EXTERN void PHY_LCCalibrate(struct rtl8192cd_priv *priv); +EXTERN int get_CCK_swing_index(struct rtl8192cd_priv *priv); +EXTERN void set_CCK_swing_index(struct rtl8192cd_priv * priv,short CCK_index); +EXTERN void set_DIG_state(struct rtl8192cd_priv *priv, int state); +EXTERN void check_DIG_by_rssi(struct rtl8192cd_priv *priv, unsigned char rssi_strength); +EXTERN void DIG_for_site_survey(struct rtl8192cd_priv *priv, int do_ss); +EXTERN void check_EDCCA(struct rtl8192cd_priv * priv, short rssi); +EXTERN void rtl8192cd_Adaptivity(struct rtl8192cd_priv *priv, unsigned char IGI); +EXTERN void rtl8192cd_NHMBBInit(struct rtl8192cd_priv *priv); +EXTERN void rtl8192cd_AdaptivityInit(struct rtl8192cd_priv *priv); +EXTERN void rtl8192cd_CheckAdaptivity(struct rtl8192cd_priv *priv); + +#ifndef CALIBRATE_BY_ODM +EXTERN void _PHY_SaveADDARegisters(struct rtl8192cd_priv *priv, unsigned int *ADDAReg, unsigned int *ADDABackup, unsigned int RegisterNum); +EXTERN void _PHY_SetADDARegisters(struct rtl8192cd_priv *priv, unsigned int* ADDAReg, unsigned int* ADDASettings, unsigned int RegisterNum); +EXTERN void _PHY_SaveMACRegisters(struct rtl8192cd_priv *priv, unsigned int *MACReg, unsigned int *MACBackup); +EXTERN void _PHY_ReloadADDARegisters(struct rtl8192cd_priv *priv, unsigned int *ADDAReg, unsigned int *ADDABackup, unsigned int RegiesterNum); +EXTERN void _PHY_ReloadMACRegisters(struct rtl8192cd_priv *priv,unsigned int *MACReg, unsigned int *MACBackup); +EXTERN void _PHY_MACSettingCalibration(struct rtl8192cd_priv *priv, unsigned int* MACReg, unsigned int* MACBackup); +EXTERN void _PHY_PathADDAOn(struct rtl8192cd_priv *priv, unsigned int* ADDAReg, char isPathAOn, char is2T); +#endif + +// FA +EXTERN void FA_statistic(struct rtl8192cd_priv * priv); +#ifdef CONFIG_RTL_NEW_AUTOCH +EXTERN void _FA_statistic(struct rtl8192cd_priv* priv); +EXTERN void reset_FA_reg(struct rtl8192cd_priv* priv); +EXTERN void hold_CCA_FA_counter(struct rtl8192cd_priv* priv); +EXTERN void release_CCA_FA_counter(struct rtl8192cd_priv* priv); +#endif + +#ifdef WIFI_WMM +EXTERN void check_NAV_prot_len(struct rtl8192cd_priv * priv, struct stat_info * pstat, unsigned int disassoc); +#endif + +#if defined(DETECT_STA_EXISTANCE) +EXTERN void DetectSTAExistance(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat ); +#endif + + +EXTERN void check_NBI_by_rssi(struct rtl8192cd_priv *priv, unsigned char rssi_strength); +EXTERN void NBI_filter_on(struct rtl8192cd_priv *priv); +EXTERN void NBI_filter_off(struct rtl8192cd_priv *priv); + +#if defined(CONFIG_WLAN_HAL_8192EE) +EXTERN void RRSR_power_control_11n(struct rtl8192cd_priv *priv, int lower); +#endif + +#ifdef CONFIG_WLAN_HAL_8814AE +EXTERN void RRSR_power_control_14(struct rtl8192cd_priv *priv, int lower); +#endif + + +#undef EXTERN + + + +/*----------------------------------------------------------------------------- + HAL_8192CDMl.c +------------------------------------------------------------------------------*/ +#ifndef _HAL8192CDM_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +// DIG +EXTERN void DIG_process(struct rtl8192cd_priv *priv); +#ifdef CONFIG_RTL_92D_SUPPORT +EXTERN void MP_DIG_process(unsigned long task_priv); +#endif +// Tx Power +#ifdef HIGH_POWER_EXT_PA +EXTERN void tx_power_control(struct rtl8192cd_priv *priv); +#endif +EXTERN void tx_power_tracking(struct rtl8192cd_priv *priv); + +#ifdef CONFIG_RTL_92D_SUPPORT +EXTERN void tx_power_tracking_92D(struct rtl8192cd_priv * priv); +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT //for 88e tx power tracking + +#ifndef CALIBRATE_BY_ODM +EXTERN void odm_TXPowerTrackingCallback_ThermalMeter_8188E(struct rtl8192cd_priv * priv); +#endif +#endif + +// EDCA +#ifdef USE_OUT_SRC +EXTERN void EdcaParaInit(struct rtl8192cd_priv *priv); +EXTERN unsigned char *Get_Adaptivity_Version(void); +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +EXTERN void init_EDCA_para(struct rtl8192cd_priv *priv, int mode); +EXTERN void choose_IOT_main_sta(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void rxBB_dm(struct rtl8192cd_priv *priv); +EXTERN void IOT_engine(struct rtl8192cd_priv *priv); +#endif + +#ifdef SW_TX_QUEUE +EXTERN void adjust_swq_setting(struct rtl8192cd_priv *priv, struct stat_info *pstat, int i, int mode); +#endif +#ifdef WIFI_WMM +EXTERN void IOT_EDCA_switch(struct rtl8192cd_priv *priv, int mode, char enable); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) +EXTERN void check_txrate_by_reg(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void set_RATid_cmd(struct rtl8192cd_priv * priv, unsigned int macid, unsigned int rateid, unsigned int ratemask); +EXTERN void add_update_RATid(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void add_update_rssi(struct rtl8192cd_priv * priv, struct stat_info * pstat); +#ifdef CONFIG_PCI_HCI +EXTERN void add_RATid_timer(unsigned long task_priv); +EXTERN void add_rssi_timer(unsigned long task_priv); +#endif +#endif + + +// Antenna diversity +#ifdef SW_ANT_SWITCH +EXTERN void dm_SW_AntennaSwitchCallback(unsigned long task_priv) ; +EXTERN void dm_SWAW_RSSI_Check(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN void dm_SW_AntennaSwitchInit(struct rtl8192cd_priv *priv); +EXTERN void dm_SW_AntennaSwitch(struct rtl8192cd_priv *priv, char Step); +#endif +#if defined(SW_ANT_SWITCH) || defined(HW_ANT_SWITCH) +EXTERN int diversity_antenna_select(struct rtl8192cd_priv *priv, unsigned char *data); +#endif +#if defined(HW_ANT_SWITCH) +EXTERN void dm_HW_AntennaSwitchInit(struct rtl8192cd_priv *priv); +EXTERN void setRxIdleAnt(struct rtl8192cd_priv *priv, char nextAnt) ; +EXTERN void dm_STA_Ant_Select(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN void dm_HW_IdleAntennaSelect(struct rtl8192cd_priv *priv); +#endif + +// Dynamic Noise Control +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) +EXTERN void dnc_timer(unsigned long task_priv); +#endif + +// Leaving STA check +#if defined(TXREPORT) +EXTERN void DetectSTAExistance(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat ); +#ifdef CONFIG_WLAN_HAL +EXTERN void DetectSTAExistance88XX(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat ); +#endif + +EXTERN void RetryLimitRecovery(unsigned long task_priv); +EXTERN void LeavingSTA_RLCheck(struct rtl8192cd_priv *priv); +#endif + +/* Hotspot 2.0 Release 1 */ +#ifdef HS2_SUPPORT +EXTERN int issue_GASrsp(struct rtl8192cd_priv *priv, DOT11_HS2_GAS_RSP *gas_rsp); +EXTERN void rtl8192cd_cu_cntdwn_timer(unsigned long task_priv); +EXTERN int issue_BSS_TSM_req(struct rtl8192cd_priv *priv, DOT11_HS2_TSM_REQ *tsm_req); +#ifdef HS2_CLIENT_TEST +EXTERN int issue_BSS_TSM_query(struct rtl8192cd_priv *priv, unsigned char *list, unsigned char list_len); +#endif +#endif + +#ifdef CONFIG_RTL_92C_SUPPORT +EXTERN void APK_MAIN(struct rtl8192cd_priv *priv, unsigned int is2T); +EXTERN void PHY_IQCalibrate_92C(struct rtl8192cd_priv *priv); +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef SW_LCK_92D +EXTERN void PHY_LCCalibrate_92D(struct rtl8192cd_priv *priv); +EXTERN void phy_ReloadLCKSetting(struct rtl8192cd_priv *priv); +#endif +#ifdef CONFIG_RTL_92D_DMDP +EXTERN void IQK_92D_2G_phy1(struct rtl8192cd_priv * priv); +#endif +#endif + +EXTERN void CCK_CCA_dynamic_enhance(struct rtl8192cd_priv *priv, unsigned char rssi_strength); + +#undef EXTERN + + + + +// P2P_SUPPORT +/*----------------------------------------------------------------------------- + 8192cd_p2p.c +------------------------------------------------------------------------------*/ +#ifdef P2P_SUPPORT +#undef EXTERN +#ifndef _8192CD_P2P_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void issue_probersp(struct rtl8192cd_priv *priv, unsigned char *da, + UINT8 *ssid, int ssid_len, int set_privacy, UINT8 is_11b_only); + +EXTERN unsigned char *get_ie(unsigned char *pbuf, int index, int *len, int limit); +EXTERN int process_p2p_cmd(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int P2P_on_public_action(struct rtl8192cd_priv *priv,struct rx_frinfo *pfrinfo); + +EXTERN void P2P_on_probe_req( + struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, + unsigned char *IEaddr, unsigned int IElen ); + +EXTERN void p2p_init(struct rtl8192cd_priv *priv); + + +EXTERN int P2P_scan(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void P2P_1sec_timer(struct rtl8192cd_priv *priv); +EXTERN void P2P_listen_timer(unsigned long task_priv); +EXTERN void p2p_start_timer(unsigned long task_priv); +EXTERN void p2p_search_timer(unsigned long task_priv); + +EXTERN int req_p2p_wsc_confirm(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN int req_p2p_provision_req(struct rtl8192cd_priv *priv,unsigned char *data); + +EXTERN int p2p_get_role(struct rtl8192cd_priv *priv,unsigned char *p2p_ie ,int p2pIElen ); +EXTERN void p2p_get_device_info(struct rtl8192cd_priv *priv, + unsigned char *p2p_ie ,int p2pIElen ,struct device_info_s* devinfo_ptr); + +EXTERN int p2p_get_GO_p2p_info(struct rtl8192cd_priv *priv, + unsigned char *p2p_ie ,int p2pIElen ,struct device_info_s* devinfo_ptr); + +EXTERN void p2p_get_GO_wsc_info(struct rtl8192cd_priv *priv, + unsigned char *wsc_ie ,int wscIElen ,struct device_info_s *devinfo_ptr); + + +EXTERN int p2p_build_beacon_ie(struct rtl8192cd_priv *priv, unsigned char *data); + +EXTERN void P2P_on_assoc_req(struct rtl8192cd_priv *priv, + unsigned char *IEaddr, unsigned int IElen ,unsigned char *sa); +EXTERN int p2pcmd_apply(struct rtl8192cd_priv *priv, unsigned char *data); +EXTERN void P2P_client_on_beacon(struct rtl8192cd_priv *priv, + unsigned char *IEaddr, unsigned int IElen, int seq); +EXTERN void p2p_noa_timer(struct rtl8192cd_priv *priv); +EXTERN int P2P_on_action(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN void p2p_client_remove(struct rtl8192cd_priv *priv , struct stat_info *pstat ); +EXTERN int p2p_build_assocRsp_ie(struct rtl8192cd_priv *priv, unsigned char *data + ,unsigned char status); +EXTERN void P2P_on_assoc_rsp(struct rtl8192cd_priv *priv,unsigned char *sa); +EXTERN int P2P_filter_manage_ap(struct rtl8192cd_priv *priv, + unsigned char *IEaddr, unsigned int IElen ); +EXTERN void p2p_debug_out(unsigned char *label, unsigned char *data, int data_length); + +#undef EXTERN + +#endif + + + + +#ifdef CONFIG_RTL_88E_SUPPORT +/*----------------------------------------------------------------------------- + HalPwrSeqCmd.c +------------------------------------------------------------------------------*/ +#define EXTERN extern +EXTERN unsigned int HalPwrSeqCmdParsing(struct rtl8192cd_priv *priv, unsigned char CutVersion, + unsigned char FabVersion, unsigned char InterfaceType, WLAN_PWR_CFG PwrSeqCmd[ ]); +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + 8188e_hw.c +------------------------------------------------------------------------------*/ +#ifndef _8188E_HW_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void RTL8188E_MACID_NOLINK(struct rtl8192cd_priv * priv, unsigned int nolink, unsigned int aid); +EXTERN void RTL8188E_MACID_PAUSE(struct rtl8192cd_priv * priv, unsigned int pause, unsigned int aid); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +EXTERN void __RTL8188E_MACID_NOLINK(struct rtl8192cd_priv * priv, unsigned int nolink, unsigned int aid); +EXTERN void __RTL8188E_MACID_PAUSE(struct rtl8192cd_priv * priv, unsigned int pause, unsigned int aid); +#endif + +#ifdef SUPPORT_RTL8188E_TC +EXTERN void check_RTL8188E_testChip(struct rtl8192cd_priv * priv); +#endif + +#ifdef TXREPORT +EXTERN void RTL8188E_EnableTxReport(struct rtl8192cd_priv *priv); +EXTERN void RTL8188E_DisableTxReport(struct rtl8192cd_priv *priv); +EXTERN void RTL8188E_ResumeTxReport(struct rtl8192cd_priv *priv); +EXTERN void RTL8188E_SuspendTxReport(struct rtl8192cd_priv *priv); +EXTERN void RTL8188E_AssignTxReportMacId(struct rtl8192cd_priv *priv); +#ifdef DETECT_STA_EXISTANCE +EXTERN void RTL8188E_DetectSTAExistance(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat); +#endif +EXTERN void RTL8188E_TxReportHandler(struct rtl8192cd_priv *priv, struct sk_buff *pskb, unsigned int bitmapLowByte, + unsigned int bitmapHighByte, struct rx_desc *pdesc); +EXTERN void RTL8188E_SetTxReportTimeByRA(struct rtl8192cd_priv *priv, int extend); +#endif // TXREPORT + +#ifndef CALIBRATE_BY_ODM +EXTERN void PHY_IQCalibrate_8188E(struct rtl8192cd_priv *priv, char bReCovery); +#endif + + + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + RateAdaptive.c +------------------------------------------------------------------------------*/ +#define EXTERN extern + +#ifdef TXREPORT +EXTERN int RateAdaptiveInfoInit(PSTATION_RA_INFO pRaInfo); +EXTERN int ARFBRefresh(struct rtl8192cd_priv *priv, PSTATION_RA_INFO pRaInfo); +EXTERN void RateDecision(struct rtl8192cd_priv *priv, PSTATION_RA_INFO pRaInfo); +#endif + +#undef EXTERN +#endif + + +/*----------------------------------------------------------------------------- + 8192cd_11h.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_11H_C_ +#define EXTERN extern +#else +#define EXTERN +#endif +EXTERN void check_country_channel_table(struct rtl8192cd_priv *priv); +EXTERN unsigned char * construct_country_ie(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen); +EXTERN unsigned char * construct_power_capability_ie(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen); +EXTERN unsigned char * construct_supported_channel_ie(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen); +EXTERN unsigned char * construct_TPC_report_ie(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen); +EXTERN void issue_TPC_report(struct rtl8192cd_priv *priv, unsigned char *da, unsigned char dialog_token); + +#undef EXTERN + + + + +/*----------------------------------------------------------------------------- + ODM +------------------------------------------------------------------------------*/ + +#ifdef USE_OUT_SRC +#include "OUTSRC/phydm_precomp.h" +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + +#define EXTERN extern + +/*----------------------------------------------------------------------------- + HalPwrSeqCmd.c +------------------------------------------------------------------------------*/ +#ifndef CONFIG_WLAN_HAL_8881A +EXTERN unsigned int HalPwrSeqCmdParsing(struct rtl8192cd_priv *priv, unsigned char CutVersion, + unsigned char FabVersion, unsigned char InterfaceType, WLAN_PWR_CFG PwrSeqCmd[ ]); +#endif //CONFIG_WLAN_HAL_8881A + + + +/*----------------------------------------------------------------------------- + 8812_hw.c +------------------------------------------------------------------------------*/ + +EXTERN void UpdateBBRFVal8812(struct rtl8192cd_priv *priv, unsigned char channel); +EXTERN void SpurCheck8812(struct rtl8192cd_priv *priv, unsigned char ch_bw, unsigned char channel, unsigned int bandwidth); +EXTERN void PHY_SetOFDMTxPower_8812(struct rtl8192cd_priv *priv, unsigned char channel); +EXTERN void PHY_SetCCKTxPower_8812(struct rtl8192cd_priv *priv, unsigned char channel); +//EXTERN void UpdateHalMSRRPT8812(struct rtl8192cd_priv *priv, unsigned short aid, unsigned char opmode); +EXTERN void UpdateHalMSRRPT8812(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char opmode); + +EXTERN VOID UpdateHalRAMask8812(struct rtl8192cd_priv*, struct stat_info*, u1Byte); +//EXTERN void check_txrate_by_reg_8812(struct rtl8192cd_priv *priv, struct stat_info *pstat); +EXTERN u1Byte FillH2CCmd8812(struct rtl8192cd_priv *, u1Byte , u4Byte , pu1Byte ); + +EXTERN void odm_TXPowerTrackingCallback_ThermalMeter_8812E(struct rtl8192cd_priv * priv); +EXTERN int get_tx_tracking_index(struct rtl8192cd_priv *priv, int channel, int i, int delta, int is_decrease, int is_CCK); +EXTERN void requestTxReport_8812(struct rtl8192cd_priv *priv); +EXTERN void C2H_isr_8812(struct rtl8192cd_priv *priv); +EXTERN VOID C2HPacketHandler_8812(struct rtl8192cd_priv *priv, pu1Byte, u1Byte); + +#ifdef BEAMFORMING_SUPPORT +EXTERN void TXBF_timer_callback(unsigned long task_priv); +EXTERN VOID SetBeamformStatus8812(struct rtl8192cd_priv *priv, u1Byte Idx ); +EXTERN VOID SetBeamformEnter8812(struct rtl8192cd_priv *priv, u1Byte Idx); + +EXTERN VOID SetBeamformLeave8812(struct rtl8192cd_priv *priv, u1Byte Idx); + +EXTERN void C2H_isr8812(struct rtl8192cd_priv *priv) ; +EXTERN VOID Beamforming_NDPARate_8812(struct rtl8192cd_priv *priv, BOOLEAN mode, u1Byte BW, u1Byte rate); + +EXTERN VOID HW_VAR_HW_REG_TIMER_START_8812(struct rtl8192cd_priv *priv); +EXTERN VOID HW_VAR_HW_REG_TIMER_INIT_8812(struct rtl8192cd_priv *priv, int t); +EXTERN VOID HW_VAR_HW_REG_TIMER_STOP_8812(struct rtl8192cd_priv *priv); +#endif + +EXTERN void SwitchChannel(struct rtl8192cd_priv *priv); + +EXTERN VOID RTL8812_MACID_PAUSE(struct rtl8192cd_priv *priv, BOOLEAN bSleep, u4Byte aid); +#ifdef BEAMFORMING_SUPPORT +EXTERN VOID SetBeamformStatus8812(struct rtl8192cd_priv *priv, u1Byte Idx); +EXTERN VOID _Beamforming_CLK(struct rtl8192cd_priv *priv); +#endif + +#undef EXTERN +#endif + +/*----------------------------------------------------------------------------- + 8812_vht_gen.c +------------------------------------------------------------------------------*/ +#ifdef RTK_AC_SUPPORT +#define EXTERN extern +EXTERN void construct_vht_ie(struct rtl8192cd_priv *priv, unsigned char channel_center); +#ifdef MCR_WIRELESS_EXTEND +EXTERN void construct_vht_ie_mcr(struct rtl8192cd_priv *priv, unsigned char channel_center, struct stat_info *pstat); +#endif +#endif + + +#ifdef __ECOS +/*----------------------------------------------------------------------------- + 8192cd_ecos.c +------------------------------------------------------------------------------*/ +#ifndef _8192CD_ECOS_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN void interrupt_dsr(struct net_device *dev); +EXTERN int can_xmit(struct net_device *dev); + +#undef EXTERN + +#endif // __ECOS + +/*----------------------------------------------------------------------------- + 8192cd_config.c +------------------------------------------------------------------------------*/ +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + +#ifndef _8192CD_ECOS_C_ +#define EXTERN extern +#else +#define EXTERN +#endif + +EXTERN int rtk_sc_init(struct rtl8192cd_priv *priv); +EXTERN int rtk_sc_start_simple_config(struct rtl8192cd_priv *priv); +EXTERN int rtk_sc_start_parse_packet(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +EXTERN int rtk_sc_check_security(struct rtl8192cd_priv *priv, struct bss_desc *bss); +EXTERN int rtk_sc_stop_simple_config(struct rtl8192cd_priv *priv); +EXTERN int rtk_sc_start_connect_target(struct rtl8192cd_priv *priv); +EXTERN int rtk_sc_restart_simple_config(struct rtl8192cd_priv *priv); +EXTERN int rtk_sc_sync_vxd_to_root(struct rtl8192cd_priv * priv); +EXTERN int rtk_sc_clean_profile_value(); +EXTERN int rtk_sc_set_value(unsigned int id, unsigned int mib_value); +EXTERN int rtk_sc_get_value(unsigned int id); +EXTERN int rtk_sc_set_string_value(unsigned int id, unsigned char *mib_value); +EXTERN int rtk_sc_get_string_value(unsigned int id, unsigned char *mib_value); +EXTERN int rtk_sc_get_security_type(); +EXTERN int rtk_sc_get_magic(unsigned int *magic, unsigned int len); +EXTERN int rtk_sc_set_para(struct rtl8192cd_priv *priv); +EXTERN int rtk_sc_is_channel_fixed(struct rtl8192cd_priv * priv); +EXTERN int rtk_sc_get_scan_offset(struct rtl8192cd_priv * priv, int channel, int bw); +EXTERN int rtk_sc_during_simple_config_scan(struct rtl8192cd_priv * priv); + +#undef EXTERN + +#endif + + +/*----------------------------------------------------------------------------- + inline function +------------------------------------------------------------------------------*/ + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +static inline void update_STA_RATid(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + notify_update_sta_RATid(priv, pstat); +} +#endif + +#endif // _8192CD_HEADERS_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_host.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_host.c new file mode 100755 index 000000000..299eb4a07 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_host.c @@ -0,0 +1,1703 @@ +/* + * Routines to handle host CPU related functions + * + * $Id: 8192cd_host.c,v 1.1 2012/05/04 13:48:37 jimmylin Exp $ + * + * Copyright (c) 2012 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_HOST_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#ifdef __KERNEL__ +#ifdef __LINUX_2_6__ +#include +#include +#include +#endif +#elif defined(__ECOS) +#include +#include +#include +#include +#include +#else +#include "./sys-support.h" +#endif + +#include "./8192cd.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + +#ifdef CONFIG_RTL8672 + #ifdef USE_RLX_BSP + #include + #include + + #ifdef CONFIG_RTL_8196C + #undef CONFIG_RTL_8196C + #endif + #ifdef CONFIG_RTL8196C_REVISION_B + #undef CONFIG_RTL8196C_REVISION_B + #endif + #else + #include + #include "../../../arch/mips/realtek/rtl8672/gpio.h" + #endif +#elif defined(__ECOS) +#else +#if !defined(CONFIG_NET_PCI) && defined(CONFIG_RTL8196B) +#include +#endif + +#if !defined(CONFIG_NET_PCI) && defined(CONFIG_RTL8196C) +#include +#endif +#endif + +#if defined(CONFIG_RTL_819X) && defined(__LINUX_2_6__) +#if !defined(USE_RLX_BSP) +#include +#else +#if defined(CONFIG_OPENWRT_SDK) && !defined(CONFIG_ARCH_CPU_RLX) +#include +#else +#include +#endif //CONFIG_OPENWRT_SDK +#endif +#endif + +#ifndef REG32 + #define REG32(reg) (*(volatile unsigned int *)(reg)) +#endif + + +#ifdef CONFIG_RTL_92D_DMDP +void Sw_PCIE_Func(int func) +{ +#if (RTL_USED_PCIE_SLOT==1) + REG32(0xb8b2100c)=REG32(0xb8b2100c)|func; // switch to function # +#else + REG32(0xb8b0100c)=REG32(0xb8b0100c)|func; // switch to function # +#endif +} +#endif + +#if !defined(CONFIG_NET_PCI) && (defined(CONFIG_RTL8196B) || defined(CONFIG_RTL_819X)) +#define MAX_PAYLOAD_SIZE_128B 0x00 + +#ifndef __ECOS +#if !(defined(CONFIG_RTL8196C) || defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_8196E)) +int rtl8196b_pci_reset(unsigned long conf_addr) +{ + /* If PCI needs to be reset, put code here. + * Note: + * Software may need to do hot reset for a period of time, say ~100us. + * Here we put 2ms. + */ + //Modified for PCIE PHY parameter due to RD center suggestion by Jason 12252009 + WRITE_MEM32(0xb8000044, 0x9);//Enable PCIE PLL + delay_ms(10); + REG32(0xb8000010)=REG32(0xb8000010)|(0x500); //Active LX & PCIE Clock in 8196B system register + delay_ms(10); + WRITE_MEM32(0xb800003C, 0x1);//PORT0 PCIE PHY MDIO Reset + delay_ms(10); + WRITE_MEM32(0xb800003C, 0x3);//PORT0 PCIE PHY MDIO Reset + delay_ms(10); + WRITE_MEM32(0xb8000040, 0x1);//PORT1 PCIE PHY MDIO Reset + delay_ms(10); + WRITE_MEM32(0xb8000040, 0x3);//PORT1 PCIE PHY MDIO Reset + delay_ms(10); + WRITE_MEM32(0xb8b01008, 0x1);// PCIE PHY Reset Close:Port 0 + delay_ms(10); + WRITE_MEM32(0xb8b01008, 0x81);// PCIE PHY Reset On:Port 0 + delay_ms(10); +#ifdef PIN_208 + WRITE_MEM32(0xb8b21008, 0x1);// PCIE PHY Reset Close:Port 1 + delay_ms(10); + WRITE_MEM32(0xb8b21008, 0x81);// PCIE PHY Reset On:Port 1 + delay_ms(10); +#endif +#ifdef OUT_CYSTALL + WRITE_MEM32(0xb8b01000, 0xcc011901);// PCIE PHY Reset On:Port 0 + delay_ms(10); +#ifdef PIN_208 + WRITE_MEM32(0xb8b21000, 0xcc011901);// PCIE PHY Reset On:Port 1 + delay_ms(10); +#endif +#endif + REG32(0xb8000010)=REG32(0xb8000010)|(0x01000000); //PCIE PHY Reset On:Port 0 + delay_ms(10); + +#if (defined(__LINUX_2_6__) && defined(USE_RLX_BSP)) || defined(__ECOS) + WRITE_MEM32(BSP_PCIE0_H_PWRCR, READ_MEM32(BSP_PCIE0_H_PWRCR) & 0xFFFFFF7F); +#ifdef PIN_208 + WRITE_MEM32(BSP_PCIE1_H_PWRCR, READ_MEM32(BSP_PCIE1_H_PWRCR) & 0xFFFFFF7F); +#endif + delay_ms(100); + WRITE_MEM32(BSP_PCIE0_H_PWRCR, READ_MEM32(BSP_PCIE0_H_PWRCR) | 0x00000080); +#ifdef PIN_208 + WRITE_MEM32(BSP_PCIE1_H_PWRCR, READ_MEM32(BSP_PCIE1_H_PWRCR) | 0x00000080); +#endif +#else + WRITE_MEM32(PCIE0_H_PWRCR, READ_MEM32(PCIE0_H_PWRCR) & 0xFFFFFF7F); +#ifdef PIN_208 + WRITE_MEM32(PCIE1_H_PWRCR, READ_MEM32(PCIE1_H_PWRCR) & 0xFFFFFF7F); +#endif + delay_ms(100); + WRITE_MEM32(PCIE0_H_PWRCR, READ_MEM32(PCIE0_H_PWRCR) | 0x00000080); +#ifdef PIN_208 + WRITE_MEM32(PCIE1_H_PWRCR, READ_MEM32(PCIE1_H_PWRCR) | 0x00000080); +#endif +#endif + + delay_ms(10); + + if ((READ_MEM32(0xb8b00728)&0x1f)!=0x11) + { + _DEBUG_INFO("PCIE LINK FAIL\n"); + return FAIL; + } + + // Enable PCIE host +#if (defined(__LINUX_2_6__) && defined(USE_RLX_BSP)) || defined(__ECOS) + WRITE_MEM32(BSP_PCIE0_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(BSP_PCIE0_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#else + WRITE_MEM32(PCIE0_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE0_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#endif + return SUCCESS; +} +#endif // !defined(CONFIG_NET_PCI) && (defined(CONFIG_RTL8196B) || defined(CONFIG_RTL_819X)) +#endif +#endif + + +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL8196C) || defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_8198B) || defined(CONFIG_RTL_8198C) //CONFIG_RTL_8198C +#define MAX_PAYLOAD_SIZE_128B 0x00 + +#ifndef CONFIG_RTL_8198B +#define CLK_MANAGE 0xb8000010 +#endif +#define PCIE0_RC_EXT_BASE (0xb8b01000) +#define PCIE1_RC_EXT_BASE (0xb8b21000) +//RC Extended register +#define PCIE0_MDIO (PCIE0_RC_EXT_BASE+0x00) +#define PCIE1_MDIO (PCIE1_RC_EXT_BASE+0x00) +//MDIO +#define PCIE_MDIO_DATA_OFFSET (16) +#define PCIE_MDIO_DATA_MASK (0xffff <>24; + printk("UPHY: 8198c ASIC u2 of u3 %s phy patch\n", (phy40M==1) ? "40M" : "25M"); + if(phy40M) + { + delay_ms(500); + HostPCIe_SetPhyMdioWrite(portnum, 0x3, 0x7b31); + HostPCIe_SetPhyMdioWrite(portnum, 0x6, 0xe258);// e2b8 + HostPCIe_SetPhyMdioWrite(portnum, 0xF, 0x400F); + HostPCIe_SetPhyMdioWrite(portnum, 0xd, 0x1764);// e2b8 + HostPCIe_SetPhyMdioWrite(portnum, 0x19, 0xFC70); + + panic_printk("\r\n40MHz PCIe Parameters\r\n"); + + } + else + { + HostPCIe_SetPhyMdioWrite(portnum, 0x3, 0x3031); + HostPCIe_SetPhyMdioWrite(portnum, 0x6, 0xe058); //Hannah + HostPCIe_SetPhyMdioWrite(portnum, 0xF, 0x400F); + HostPCIe_SetPhyMdioWrite(portnum, 0x19, 0xFC70); + printk("\r\n25MHz PCIe Parameters\r\n"); + + + } + } +#endif + + + + + #else +#ifdef CONFIG_WLAN_HAL_8881A + + REG32(0xb8000050)=0xa; + delay_ms(500); + + REG32(0xb8000050)=0xb; + + HostPCIe_SetPhyMdioWrite(portnum, 0xb, 0x7cff); //bokai tell, and fix + HostPCIe_SetPhyMdioWrite(portnum, 0xb, 0x7bff); //bokai tell, and fix + //HostPCIe_SetPhyMdioWrite(portnum, 0xb, 0x7bff); //bokai tell, and fix + + if(REG32(0xb8000000)&0xf>=0x01) + { + #ifdef CONFIG_RTL_88E_SUPPORT + //HostPCIe_SetPhyMdioWrite(portnum, 0xa, 0x4437); + //HostPCIe_SetPhyMdioWrite(portnum, 0x1, 0x36a3); + #endif + + HostPCIe_SetPhyMdioWrite(portnum, 0x3, 0x0486); + HostPCIe_SetPhyMdioWrite(portnum, 0x4, 0xf144); + HostPCIe_SetPhyMdioWrite(portnum, 0xc, 0x097f); + } + else + { + HostPCIe_SetPhyMdioWrite(portnum, 0xc, 0x0171); + HostPCIe_SetPhyMdioWrite(portnum, 0x4, 0xf544); + } + + HostPCIe_SetPhyMdioWrite(portnum, 0x6, 0x7081); + HostPCIe_SetPhyMdioWrite(portnum, 0x8, 0x901c); + HostPCIe_SetPhyMdioWrite(portnum, 0x9, 0x0ebc); +#else + #if defined(CONFIG_RTL_8196E) + if ((REG32(BSP_REVR) & 0xFFFFF000) == BSP_RTL8196E) + #else + if ((REG32(BSP_REVR) >= BSP_RTL8198_REVISION_B) || ((REG32(BSP_REVR) & 0xFFFFF000) == BSP_RTL8197D)) + #endif + { +#if defined(CONFIG_RTL_88E_SUPPORT) || (defined(SLOT_0_92C) && defined(CONFIG_SLOT_0_EXT_PA)) || (defined(SLOT_1_92C) && defined(CONFIG_SLOT_1_EXT_PA)) + HostPCIe_SetPhyMdioWrite(portnum, 0, 0xD086); //bokai tell, and fix +#else + HostPCIe_SetPhyMdioWrite(portnum, 0, 0xD087); //bokai tell, and fix +#endif + HostPCIe_SetPhyMdioWrite(portnum, 1, 0x0003); + HostPCIe_SetPhyMdioWrite(portnum, 2, 0x4d19); ///1119 bokai + #ifdef CONFIG_WLAN_HAL_8192EE + HostPCIe_SetPhyMdioWrite(portnum, 4, 0x5000); // disable spread spectrum in 92E + #else +#if defined(CONFIG_RTL_88E_SUPPORT) || (defined(SLOT_0_92C) && defined(CONFIG_SLOT_0_EXT_PA)) || (defined(SLOT_1_92C) && defined(CONFIG_SLOT_1_EXT_PA)) + #ifdef CONFIG_PHY_EAT_40MHZ + HostPCIe_SetPhyMdioWrite(portnum, 4, 0x7C00); + #else + HostPCIe_SetPhyMdioWrite(portnum, 4, 0x7000); + #endif +#endif + #endif + #if defined(CONFIG_AUTO_PCIE_PHY_SCAN) && (defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_819XD)) + + if ((REG32(0xb8000008)&0x2000000)==0x2000000) //40MHz + { +#if defined(CONFIG_RTL_88E_SUPPORT) || (defined(SLOT_0_92C) && defined(CONFIG_SLOT_0_EXT_PA)) || (defined(SLOT_1_92C) && defined(CONFIG_SLOT_1_EXT_PA)) + HostPCIe_SetPhyMdioWrite(portnum, 4, 0x7C00); + HostPCIe_SetPhyMdioWrite(portnum, 5, 0x09DB); //40M //1119 bokai + HostPCIe_SetPhyMdioWrite(portnum, 6, 0x4048); //40M +#else + HostPCIe_SetPhyMdioWrite(portnum, 5, 0x0BCB); //40M + HostPCIe_SetPhyMdioWrite(portnum, 6, 0x2148); //40M +#endif + HostPCIe_SetPhyMdioWrite(portnum, 7, 0x41ff); + HostPCIe_SetPhyMdioWrite(portnum, 8, 0x13F6); + } + else //25MHz + { + printk("98 - 25MHz Clock Source\n"); +#if defined(CONFIG_RTL_88E_SUPPORT) || (defined(SLOT_0_92C) && defined(CONFIG_SLOT_0_EXT_PA)) || (defined(SLOT_1_92C) && defined(CONFIG_SLOT_1_EXT_PA)) + HostPCIe_SetPhyMdioWrite(portnum, 4, 0x7000); + HostPCIe_SetPhyMdioWrite(portnum, 5, 0x0B13); + HostPCIe_SetPhyMdioWrite(portnum, 6, 0xf048); //25M +#else + HostPCIe_SetPhyMdioWrite(portnum, 6, 0xf848); //25M +#endif + HostPCIe_SetPhyMdioWrite(portnum, 7, 0xa7ff); //-0.5% + HostPCIe_SetPhyMdioWrite(portnum, 8, 0x0c56); + + } + #else + + #ifdef CONFIG_PHY_EAT_40MHZ + printk("98 - 40MHz Clock Source\n"); +#if defined(CONFIG_RTL_88E_SUPPORT) || (defined(SLOT_0_92C) && defined(CONFIG_SLOT_0_EXT_PA)) || (defined(SLOT_1_92C) && defined(CONFIG_SLOT_1_EXT_PA)) + HostPCIe_SetPhyMdioWrite(portnum, 5, 0x09DB); //40M //1119 bokai + HostPCIe_SetPhyMdioWrite(portnum, 6, 0xf048); //40M +#else + HostPCIe_SetPhyMdioWrite(portnum, 5, 0x0BCB); //40M + HostPCIe_SetPhyMdioWrite(portnum, 6, 0x2148); //40M +#endif + //HostPCIe_SetPhyMdioWrite(portnum, 5, 0x08db); //40M + //HostPCIe_SetPhyMdioWrite(portnum, 6, 0xF148); //40M + #else + printk("98 - 25MHz Clock Source\n"); +#if defined(CONFIG_RTL_88E_SUPPORT) || (defined(SLOT_0_92C) && defined(CONFIG_SLOT_0_EXT_PA)) || (defined(SLOT_1_92C) && defined(CONFIG_SLOT_1_EXT_PA)) + HostPCIe_SetPhyMdioWrite(portnum, 5, 0x0B13); + HostPCIe_SetPhyMdioWrite(portnum, 6, 0xf048); //25M +#else + HostPCIe_SetPhyMdioWrite(portnum, 6, 0xf848); //25M +#endif + #endif + #endif + + + +#if defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) + #else + HostPCIe_SetPhyMdioWrite(portnum, 8, 0x18d7); //peisi tune +#endif + //saving more power, 8196c pe-si tune + HostPCIe_SetPhyMdioWrite(portnum, 0x09, 0x539c); + HostPCIe_SetPhyMdioWrite(portnum, 0x0a, 0x20eb); + HostPCIe_SetPhyMdioWrite(portnum, 0x0d, 0x1766); +#if defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) + + #ifdef CONFIG_WLAN_HAL_8881A + HostPCIe_SetPhyMdioWrite(portnum, 0x0b, 0x0311); //for sloving low performance + #else + HostPCIe_SetPhyMdioWrite(portnum, 0x0b, 0x0711); //for sloving low performance + #endif +#else + HostPCIe_SetPhyMdioWrite(portnum, 0x0b, 0x0511); //for sloving low performance +#endif + +#if defined(CONFIG_RTL_8196E) + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0f0f); +#else + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0a00); +#endif + HostPCIe_SetPhyMdioWrite(portnum, 0x19, 0xFCE0); + + HostPCIe_SetPhyMdioWrite(portnum, 0x1a, 0x7e40); //formal chip, reg 0x1a.4=0 + HostPCIe_SetPhyMdioWrite(portnum, 0x1b, 0xFC01); //formal chip reg 0x1b.0=1 + + HostPCIe_SetPhyMdioWrite(portnum, 0x1e, 0xC280); + } + else + #endif + { + #ifndef CONFIG_WLAN_HAL_8881A + HostPCIe_SetPhyMdioWrite(portnum, 0, 0xD087); + + HostPCIe_SetPhyMdioWrite(portnum, 1, 0x0003); + HostPCIe_SetPhyMdioWrite(portnum, 6, 0xf448); //new + HostPCIe_SetPhyMdioWrite(portnum, 6, 0x408); //avoid noise infuse //15-12=0, 7-5=0, 0448 + + HostPCIe_SetPhyMdioWrite(portnum, 7, 0x31ff); + HostPCIe_SetPhyMdioWrite(portnum, 8, 0x18d5); //new + HostPCIe_SetPhyMdioWrite(portnum, 9, 0x531c); + + HostPCIe_SetPhyMdioWrite(portnum, 0xd, 0x1766); + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0010);//ori + + HostPCIe_SetPhyMdioWrite(portnum, 0x19, 0xFCE0); + HostPCIe_SetPhyMdioWrite(portnum, 0x1e, 0xC280); + #endif + } + #endif + #endif + } + + //--------------------------------------- + PCIE_Device_PERST(portnum); + PCIE_PHY_Reset(portnum); + +#ifdef CONFIG_RTL_ULINKER + { + extern void eth_led_recover(void); + eth_led_recover(); + } +#endif + + delay_ms(500); + delay_ms(500); + status=PCIE_Check_Link(portnum); + if(status==FAIL) + { + retry--; + if(retry==0) + return FAIL; + else + goto TRY_AGAIN; + } + +SET_BAR: + if (portnum==0) + { + // Enable PCIE host + if (pcie_reset_done[portnum] == 0) { +#if (defined(__LINUX_2_6__) && defined(USE_RLX_BSP)) || defined(__ECOS) + WRITE_MEM32(BSP_PCIE0_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(BSP_PCIE0_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#else + WRITE_MEM32(PCIE0_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE0_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#endif + pcie_reset_done[portnum] = 1; + } +#ifdef CONFIG_RTL_92D_DMDP + else { + Sw_PCIE_Func(1); + //choose the PCIE port number + WRITE_MEM32(PCIE0_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE0_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B + Sw_PCIE_Func(0); + } +#endif + } + else if (portnum==1) + { + // Enable PCIE host +#if (defined(__LINUX_2_6__) && defined(USE_RLX_BSP)) || defined(__ECOS) + if (pcie_reset_done[portnum] == 0) { + WRITE_MEM32(BSP_PCIE1_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(BSP_PCIE1_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B + pcie_reset_done[portnum] = 1; + } + #ifdef CONFIG_RTL_92D_DMDP + else { + Sw_PCIE_Func(1); + //choose the PCIE port number + WRITE_MEM32(BSP_PCIE1_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(BSP_PCIE1_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B + Sw_PCIE_Func(0); + } + #endif + #else /* defined(__LINUX_2_6__) && defined(USE_RLX_BSP) */ + WRITE_MEM32(PCIE1_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE1_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B + #endif /* defined(__LINUX_2_6__) && defined(USE_RLX_BSP) */ + } + else + return FAIL; + + delay_ms(500); + return SUCCESS; + +} +#endif +#elif defined(CONFIG_RTL8196C) || defined(CONFIG_RTL_8196C) + + +static int pcie_reset_done[2] = {0}; +#ifdef CONFIG_RTL8672 +#ifdef USE_RLX_BSP +#define PCI_MISC BSP_PCI_MISC +#define MISC_IP_SEL BSP_IP_SEL +#define EN_PCIE BSP_EN_PCIE +#define PCI_MISC BSP_PCI_MISC +#define MISC_PINSR BSP_MISC_PINSR +#define CLKSEL BSP_CLKSEL +#endif //USE_RLX_BSP + +unsigned char clk_src_40M = 0; + +struct pcie_para{ + unsigned char port; + unsigned char reg; + unsigned short value; +}; + +enum clk_source{ + CLK35_328_6166 = 0, //6166 35.328M clk + CLK25_6166, //6166 25M clk + CLK35_328_8676, //8676 35.328M clk + CLK40_8676, //8676 40M clk + CLK40_8686, //8686 40M clk + CLK25_8686, //8686 25M clk + CLK35_328_8676S, //8676S 35.328M clk + CLK40_8676S, //8676S 40M clk + CLK35_328_0562, //0562 35.328M clk + CLK40_0562, //0562 40M clk + CLK25_8685_P0, //8685 25M clk + CLK25_8685_P1, //8685 25M clk + NOT_DEFINED_CLK +}; + +struct pcie_para ePHY[][29] = { + { {0, 1, 0x0003}, {0, 2, 0x2d18}, {0, 3, 0x6d09}, {0, 4, 0x5000}, + {0, 0, 0x1046}, {0, 6, 0x0068}, {0, 5, 0x0bcb}, {0, 7, 0x30ff}, + {0, 8, 0x18d7}, {0, 9, 0x530c}, {0, 0xa, 0x00e8}, {0, 0xb, 0x0511}, + {0, 0xc, 0x0828}, {0, 0xd, 0x17a6}, {0, 0xe, 0x98c5}, {0, 0xf, 0x0f0f}, + {0, 0x10, 0x000c}, {0, 0x11, 0x3c00}, {0, 0x12, 0xfc00}, {0, 0x13, 0x0c81}, + {0, 0x14, 0xde01}, {0, 0x19, 0xfc20}, {0, 0x1a, 0xfc00}, {0, 0x1b, 0xfc00}, + {0, 0x1c, 0xfc00}, {0, 0x1d, 0xa0eb}, {0, 0x1e, 0xc280}, {0, 0x1f, 0x05e0}, + {0xff,0xff,0xffff}}, //6166 35.328M clk + { {0, 1, 0x0003}, {0, 2, 0x2d18}, {0, 3, 0x6d09}, {0, 4, 0x5000}, + {0, 0, 0x1047}, {0, 6, 0xf848}, {0, 5, 0x08ab}, {0, 7, 0x30ff}, + {0, 8, 0x18d7}, {0, 9, 0x530c}, {0, 0xa, 0x00e8}, {0, 0xb, 0x0511}, + {0, 0xc, 0x0828}, {0, 0xd, 0x17a6}, {0, 0xe, 0x98c5}, {0, 0xf, 0x0f0f}, + {0, 0x10, 0x000c}, {0, 0x11, 0x3c00}, {0, 0x12, 0xfc00}, {0, 0x13, 0x0c81}, + {0, 0x14, 0xde01}, {0, 0x19, 0xfc20}, {0, 0x1a, 0xfc00}, {0, 0x1b, 0xfc00}, + {0, 0x1c, 0xfc00}, {0, 0x1d, 0xa0eb}, {0, 0x1e, 0xc280}, {0, 0x1f, 0x05e0}, + {0xff,0xff,0xffff}}, //6166 25M clk + { {0, 1, 0x0003}, {0, 2, 0x2d18}, {0, 3, 0x4d09}, {0, 4, 0x5c3f}, + {0, 0, 0x1046}, {0, 6, 0x9048}, {0, 5, 0x2213}, {0, 7, 0x31ff}, + {0, 8, 0x18d7}, {0, 9, 0x539c}, {0, 0xa, 0x00e8}, {0, 0xb, 0x0711}, + {0, 0xc, 0x0828}, {0, 0xd, 0x17a6}, {0, 0xe, 0x98c5}, {0, 0xf, 0x0f0f}, + {0, 0x10, 0x000c}, {0, 0x11, 0x3c00}, {0, 0x12, 0xfc00}, {0, 0x13, 0x0c81}, + {0, 0x14, 0xde01}, {0, 0x19, 0xfce0}, {0, 0x1a, 0x7c00}, {0, 0x1b, 0xfc00}, + {0, 0x1c, 0xfc00}, {0, 0x1d, 0xa0eb}, {0, 0x1e, 0xc280}, {0, 0x1f, 0x0600}, + {0xff,0xff,0xffff}}, //8676 35.328M clk + { {0, 1, 0x0003}, {0, 2, 0x2d18}, {0, 3, 0x4d09}, {0, 4, 0x5000}, + {0, 0, 0x1047}, {0, 6, 0x9148}, {0, 5, 0x23cb}, {0, 7, 0x31ff}, + {0, 8, 0x18d7}, {0, 9, 0x539c}, {0, 0xa, 0x00e8}, {0, 0xb, 0x0711}, + {0, 0xc, 0x0828}, {0, 0xd, 0x17a6}, {0, 0xe, 0x98c5}, {0, 0xf, 0x0f0f}, + {0, 0x10, 0x000c}, {0, 0x11, 0x3c00}, {0, 0x12, 0xfc00}, {0, 0x13, 0x0c81}, + {0, 0x14, 0xde01}, {0, 0x19, 0xfce0}, {0, 0x1a, 0x7c00}, {0, 0x1b, 0xfc00}, + {0, 0x1c, 0xfc00}, {0, 0x1d, 0xa0eb}, {0, 0x1e, 0xc280}, {0, 0x1f, 0x0600}, + {0xff,0xff,0xffff}}, //8676 40M clk + { {0, 0, 0x1086}, {0, 4, 0x5800}, {0, 5, 0x05d3}, {0, 6, 0xf048}, + {0, 0xb, 0x0711}, {0, 0xd, 0x1766}, {0, 0xf, 0x0a00}, {0, 0x1d, 0xa0eb}, + {0xff,0xff,0xffff}},//8686 40M clk + { {0, 6, 0xf848}, {0, 0xb, 0x0711}, {0, 0xd, 0x1766}, {0, 0xf, 0x0a00}, + {0, 0x01d, 0xa0eb}, + {1, 6, 0xf848}, {1, 0xb, 0x0711}, {1, 0xd, 0x1766}, {1, 0xf, 0x0a00}, + {1, 0x01d, 0xa0eb}, + {0xff,0xff,0xffff}},//8686 25M clk + { {0, 1, 0x0002}, {0, 2, 0x4300}, {0, 3, 0x0400}, {0, 4, 0x4644}, + {0, 0, 0x0000}, {0, 6, 0x30c0}, {0, 5, 0x8101}, {0, 7, 0x7440}, + {0, 8, 0x901c}, {0, 9, 0x0c9c}, {0, 0xa, 0x4037}, {0, 0xb, 0x2bb0}, + {0, 0xc, 0x8649}, {0, 0xd, 0x130d}, {0, 0xe, 0x0000}, {0, 0xf, 0x0026}, + {0xff,0xff,0xffff}}, //8676S 35.328M clk + { {0, 1, 0x0002}, {0, 2, 0x4300}, {0, 3, 0x0400}, {0, 4, 0x4644}, + {0, 0, 0x0000}, {0, 6, 0x30c0}, {0, 5, 0x8101}, {0, 7, 0x7440}, + {0, 8, 0x901c}, {0, 9, 0x0c9c}, {0, 0xa, 0x4037}, {0, 0xb, 0x2bb0}, + {0, 0xc, 0x8649}, {0, 0xd, 0x130d}, {0, 0xe, 0x0000}, {0, 0xf, 0x0026}, + {0xff,0xff,0xffff}}, //8676S 40M clk + { {0, 1, 0x06a3}, {0, 2, 0x4300}, {0, 3, 0x0400}, {0, 4, 0xd546}, + {0, 0, 0x0000}, {0, 6, 0xb880}, {0, 5, 0x8101}, {0, 7, 0x7c40}, + {0, 8, 0x901c}, {0, 9, 0x0c9c}, {0, 0xa, 0x4037}, {0, 0xb, 0x03b0}, + {0, 0xc, 0x0261}, + {0xff,0xff,0xffff}}, //0562 35.328M clk + { {0, 1, 0x06a3}, {0, 2, 0x4300}, {0, 3, 0x0400}, {0, 4, 0xd546}, + {0, 0, 0x0000}, {0, 6, 0xb880}, {0, 5, 0x8101}, {0, 7, 0x7c40}, + {0, 8, 0x901c}, {0, 9, 0x0c9c}, {0, 0xa, 0x4037}, {0, 0xb, 0x03b0}, + {0, 0xc, 0x0261}, + {0xff,0xff,0xffff}}, //0562 40M clk + { {0, 0, 0x404c}, {0, 1, 0x16a3}, {0, 2, 0x6340}, {0, 3, 0x370d}, + {0, 4, 0x856a}, {0, 5, 0x8109}, {0, 6, 0x6081}, {0, 7, 0x5400}, + {0, 8, 0x9000}, {0, 9, 0x0ccc}, {0, 0xa, 0x4437}, {0, 0xb, 0x0230}, + {0, 0xc, 0x0021}, {0, 0xd, 0x0000}, {0, 0xe, 0x0000}, {0, 0x1f, 0x0000}, + {0xff,0xff,0xffff}}, //8685 25M clk + { {1, 0, 0x404c}, {1, 1, 0x16a3}, {1, 2, 0x6340}, {1, 3, 0x370d}, + {1, 4, 0x856a}, {1, 5, 0x8109}, {1, 6, 0x6081}, {1, 7, 0x5400}, + {1, 8, 0x9000}, {1, 9, 0x0ccc}, {1, 0xa, 0x4437}, {1, 0xb, 0x0230}, + {1, 0xc, 0x0021}, {1, 0xd, 0x0000}, {1, 0xe, 0x0000}, {1, 0x1f, 0x0000}, + {0xff,0xff,0xffff}}, //8685 25M clk + {{0, 0, 0x404c}, {0, 1, 0x16a3}, {0, 2, 0x6340}, {0, 3, 0x370d}, + {0, 4, 0x856a}, {0, 5, 0x8109}, {0, 6, 0x6081}, {0, 7, 0x5400}, + {0, 8, 0x9000}, {0, 9, 0x0ccc}, {0, 0xa, 0x4437}, {0, 0xb, 0x0230}, + {0, 0xc, 0x0021}, {0, 0xd, 0x0000}, {0, 0xe, 0x0000}, {0, 0x1f, 0x0000}, + {0xff,0xff,0xffff}} //8685S 25M clk +}; + +int PCIE_reset_procedure(int portnum, int Use_External_PCIE_CLK, int mdio_reset, unsigned long conf_addr) +{ + extern void PCIE_reset_pin(int *reset); +#ifdef CONFIG_USE_PCIE_SLOT_1 + extern void PCIE1_reset_pin(int *reset); +#endif + int PCIE_gpio_RST, i, idx; + unsigned int PCIE_D_CFG0, PCIE_H_CFG, PCIE_H_PWRCR; + unsigned int ENABLE_PCIE = EN_PCIE; + + if (portnum==0) { + PCIE_D_CFG0 = BSP_PCIE0_D_CFG0; + PCIE_H_CFG = BSP_PCIE0_H_CFG; + PCIE_H_PWRCR = BSP_PCIE0_H_PWRCR; +#ifdef CONFIG_USE_PCIE_SLOT_1 + } else if(portnum==1) { + PCIE_D_CFG0 = BSP_PCIE1_D_CFG0; + PCIE_H_CFG = BSP_PCIE1_H_CFG; + PCIE_H_PWRCR = BSP_PCIE1_H_PWRCR; + ENABLE_PCIE = BSP_ENABLE_PCIE1; +#endif + } else { + printk("Error: portnum=%d\n", portnum); + return FAIL; + } + + if (pcie_reset_done[portnum]) + goto SET_BAR; + +#ifdef CONFIG_USE_PCIE_SLOT_1 + if (portnum==1) + PCIE1_reset_pin(&PCIE_gpio_RST); + else +#endif + PCIE_reset_pin(&PCIE_gpio_RST); + + // 0. Assert PCIE Device Reset + gpioClear(PCIE_gpio_RST); + gpioConfig(PCIE_gpio_RST, GPIO_FUNC_OUTPUT); + delay_ms(10); + + // 1. PCIE phy mdio reset +#if !defined(CONFIG_ARCH_LUNA_SLAVE) || !defined(CONFIG_MASTER_WLAN0_ENABLE) +#if defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1) + if(pcie_reset_done[0]==0 && pcie_reset_done[1]==0){ +#endif + + #ifndef CONFIG_RTL8676S + REG32(PCI_MISC) = BSP_PCI_MDIO_RESET_ASSERT; + REG32(PCI_MISC) = BSP_PCI_MDIO_RESET_RELEASE; + #endif +#if defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1) + } +#endif +#endif + // 2. PCIE MAC reset + REG32(MISC_IP_SEL) &= ~ENABLE_PCIE; + REG32(MISC_IP_SEL) |= ENABLE_PCIE; +#if !defined(CONFIG_ARCH_LUNA_SLAVE) || !defined(CONFIG_MASTER_WLAN0_ENABLE) +#if defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1) + if(pcie_reset_done[0]==0 && pcie_reset_done[1]==0){ +#endif + if(mdio_reset) + { + //printk("Do MDIO_RESET\n"); + // 5.MDIO Reset + #ifndef CONFIG_RTL8676S + REG32(PCI_MISC) = BSP_PCI_MDIO_RESET_RELEASE; + #endif + } +#if defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1) + } +#endif +#endif + // 6. PCIE PHY Reset + REG32(PCIE_H_PWRCR) = 0x1; //bit7 PHY reset=0 bit0 Enable LTSSM=1 + REG32(PCIE_H_PWRCR) = 0x81; //bit7 PHY reset=1 bit0 Enable LTSSM=1 + delay_ms(100); + + //---------------------------------------- + if (mdio_reset) + { + if (IS_6166 && (REG32(MISC_PINSR) & CLKSEL)) + idx = CLK35_328_6166; + else if (IS_6166 && !(REG32(MISC_PINSR) & CLKSEL)) + idx = CLK25_6166; + else if (IS_RTL8676 && !(REG32(MISC_PINSR) & CLKSEL)) + idx = CLK35_328_8676; + else if (IS_RTL8676 && (REG32(MISC_PINSR) & CLKSEL)) + idx = CLK40_8676; + else if (IS_RTL8686 && (REG32(MISC_PINSR) & CLKSEL)){ + printk("8686 40Mhz\n"); + idx = CLK40_8686; + } + else if(IS_RTL8686 && !(REG32(MISC_PINSR) & CLKSEL)){ + printk("8686 25Mhz\n"); + idx = CLK25_8686; + } + else if (IS_8676S_6333 && !(REG32(MISC_PINSR) & CLKSEL)) + idx = CLK35_328_8676S; + else if (IS_8676S_6333 && (REG32(MISC_PINSR) & CLKSEL)) + idx = CLK40_8676S; + else if (IS_8676S_0562 && !(REG32(MISC_PINSR) & CLKSEL)) + idx = CLK35_328_0562; + else if (IS_8676S_0562 && (REG32(MISC_PINSR) & CLKSEL)) + idx = CLK40_0562; + else if (IS_RTL8685){ + if (portnum==0){ + printk("8685 pcie port 0\n"); + idx = CLK25_8685_P0; + } + else{ + printk("8685 pcie port 1\n"); + idx = CLK25_8685_P1; + } + } + else + idx = NOT_DEFINED_CLK; + + if (CLK40_8676 == idx) + clk_src_40M = 1; + + for (i = 0; NOT_DEFINED_CLK != idx; ) { + if(ePHY[idx][i].port != 0xff){ + if(portnum == ePHY[idx][i].port) + HostPCIe_SetPhyMdioWrite(ePHY[idx][i].port, ePHY[idx][i].reg, ePHY[idx][i].value); + + i++; + } + else + break; + } + } + + // 7. PCIE Device Reset + gpioSet(PCIE_gpio_RST); + + // wait for LinkUP + i = 100; + while(--i) + { + if((REG32(PCIE_H_CFG + 0x0728)&0x1f)==0x11) + break; + delay_ms(10); + } + + if (i == 0) + { + printk("Warring!! Port %d WLan device PCIE Link Failed, State=0x%x\n", portnum, REG32(PCIE_H_CFG + 0x0728)); + printk("Reset PCIE Host PHY and try again...\n"); + // 4. PCIE PHY Reset + REG32(PCIE_H_PWRCR) = 0x1; //bit7 PHY reset=0 bit0 Enable LTSSM=1 + REG32(PCIE_H_PWRCR) = 0x81; //bit7 PHY reset=1 bit0 Enable LTSSM=1 + + // wait for LinkUP + i = 100; + while(--i) + { + if( (REG32(PCIE_H_CFG + 0x0728)&0x1f)==0x11) + break; + delay_ms(100); + } + + if (i == 0){ + printk("%s[%d]: Error!! Port %d WLan device PCIE Link failed, State=0x%x\n", __FUNCTION__, __LINE__, portnum, REG32(PCIE_H_CFG + 0x0728)); + //check pcie link fail~ + return FAIL; + } + } + delay_ms(100); + + // 8. Set BAR + REG32(PCIE_D_CFG0 + 0x10) = 0x18c00001; + REG32(PCIE_D_CFG0 + 0x18) = 0x19000004; + REG32(PCIE_D_CFG0 + 0x04) = 0x00180007; + REG32(PCIE_H_CFG + 0x04) = 0x00100007; + + printk("Find Port_num=%d, Vender_Device_ID=0x%X\n", portnum, REG32(PCIE_D_CFG0 + 0x00) ); + + if(i==0) + { + printk("Cannot LinkUP (0x%08X)\n", REG32(PCIE_H_CFG + 0x0728)); + return FAIL; + } + +SET_BAR: + // Enable PCIE host + if (pcie_reset_done[portnum] == 0) { + WRITE_MEM32(PCIE_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +// set_rtl8192cd_gpio(); + pcie_reset_done[portnum] = 1; + } +#ifdef CONFIG_RTL_92D_DMDP + else { + Sw_PCIE_Func(1); //choose the PCIE port number + WRITE_MEM32(PCIE_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); + Sw_PCIE_Func(0); + } +#endif + return SUCCESS; +} + + +#else + +int PCIE_reset_procedure(int portnum, int Use_External_PCIE_CLK, int mdio_reset,unsigned long conf_addr) +{ + + int i=100; +#define SYS_PCIE_PHY0 (0xb8000000 +0x50) + //PCIE Register +#define CLK_MANAGE 0xb8000010 +#define PCIE_PHY0_REG 0xb8b01000 + //#define PCIE_PHY1_REG 0xb8b21000 +#define PCIE_PHY0 0xb8b01008 + // #define PCIE_PHY1 0xb8b21008 + int port =0; + + if (pcie_reset_done[portnum]) + goto SET_BAR; + + //2.Active LX & PCIE Clock + REG32(CLK_MANAGE) |= (1<<11); //enable active_pcie0 + delay_ms(100); + +#if 1 + if(mdio_reset) + { + //printk("Do MDIO_RESET\n"); + // 3.MDIO Reset + REG32(SYS_PCIE_PHY0) = (1<<3) |(0<<1) | (0<<0); //mdio reset=0, + REG32(SYS_PCIE_PHY0) = (1<<3) |(0<<1) | (1<<0); //mdio reset=1, + REG32(SYS_PCIE_PHY0) = (1<<3) |(1<<1) | (1<<0); //bit1 load_done=1 + } + //4. PCIE PHY Reset + REG32(PCIE_PHY0) = 0x1; //bit7 PHY reset=0 bit0 Enable LTSSM=1 + REG32(PCIE_PHY0) = 0x81; //bit7 PHY reset=1 bit0 Enable LTSSM=1 + delay_ms(100); +#endif + + delay_ms(100); + + //---------------------------------------- + if(mdio_reset) + { + if (REG32(REVR) == RTL8196C_REVISION_A) + { + HostPCIe_SetPhyMdioWrite(port, 0, 0x5027); + HostPCIe_SetPhyMdioWrite(port, 2, 0x6d18); + HostPCIe_SetPhyMdioWrite(port, 6, 0x8828); + HostPCIe_SetPhyMdioWrite(port, 7, 0x30ff); + HostPCIe_SetPhyMdioWrite(port, 8, 0x18d7); + HostPCIe_SetPhyMdioWrite(port, 0xa, 0xe9); + HostPCIe_SetPhyMdioWrite(port, 0xb, 0x0511); + HostPCIe_SetPhyMdioWrite(port, 0xd, 0x15b6); + HostPCIe_SetPhyMdioWrite(port, 0xf, 0x0f0f); +#if 1 // PHY_EAT_40MHZ + HostPCIe_SetPhyMdioWrite(port, 5, 0xbcb); //[9:3]=1111001 (binary) 121 (10) + HostPCIe_SetPhyMdioWrite(port, 6, 0x8128); //[11]=0 [9:8]=01 +#endif + /* + emdiow 0 5027 + emdiow 2 6d18 + emdiow 6 8828 + emdiow 7 30ff + emdiow 8 18dd + emdiow a e9 + emdiow b 0511 + emdiow d 15b6 + emdiow f 0f0f + */ + } + else + { + HostPCIe_SetPhyMdioWrite(port, 0, 0xD087); + HostPCIe_SetPhyMdioWrite(port, 1, 0x0003); + HostPCIe_SetPhyMdioWrite(port, 2, 0x4d18); + +#ifdef CONFIG_PHY_EAT_40MHZ + + printk("96C - 40MHz Clock Source\n"); +#ifdef HIGH_POWER_EXT_PA + HostPCIe_SetPhyMdioWrite(port, 5, 0x0BF3); //40M +#else + HostPCIe_SetPhyMdioWrite(port, 5, 0x0BCB); //40M +#endif + HostPCIe_SetPhyMdioWrite(port, 6, 0xF148); //40M + +#else + + printk("96C - 25MHz Clock Source\n"); + HostPCIe_SetPhyMdioWrite(port, 6, 0xf848); //25M +#endif + + HostPCIe_SetPhyMdioWrite(port, 7, 0x31ff); + HostPCIe_SetPhyMdioWrite(port, 8, 0x18d7); + HostPCIe_SetPhyMdioWrite(port, 9, 0x539c); + HostPCIe_SetPhyMdioWrite(port, 0xa, 0x20eb); + HostPCIe_SetPhyMdioWrite(port, 0xb, 0x0511); + HostPCIe_SetPhyMdioWrite(port, 0xd, 0x1764); + HostPCIe_SetPhyMdioWrite(port, 0xf, 0x0a00); + +#ifdef HAVING_FIB + HostPCIe_SetPhyMdioWrite(port,8, 0x18dd); + HostPCIe_SetPhyMdioWrite(port, 0xd, 0x1776); +#endif + + HostPCIe_SetPhyMdioWrite(port, 0x19, 0xFCE0); + HostPCIe_SetPhyMdioWrite(port, 0x1e, 0xC280); + } + } + + //--------------------------------------- + // 6. PCIE Device Reset +#ifndef CONFIG_RTL_8196C_iNIC + REG32(CLK_MANAGE) &= ~(1<<12); //perst=0 off. + delay_ms(300); +#endif + //mark_inic , from jason patch +#ifdef CONFIG_RTL_8196C_iNIC + iNIC_PCIE_Device_PERST(); +#endif +#if defined(CONFIG_RTL_8196CS) || defined(CONFIG_RTL_8197B) + GPIO6_PCIE_Device_PERST(); +#endif + //4. PCIE PHY Reset + REG32(PCIE_PHY0) = 0x1; //bit7 PHY reset=0 bit0 Enable LTSSM=1 + REG32(PCIE_PHY0) = 0x81; //bit7 PHY reset=1 bit0 Enable LTSSM=1 + delay_ms(300); +#ifndef CONFIG_RTL_8196C_iNIC + REG32(CLK_MANAGE) |= (1<<12); //PERST=1 +#endif + //4. PCIE PHY Reset + + //prom_printf("\nCLK_MANAGE(0x%x)=0x%x\n\n",CLK_MANAGE,READ_MEM32(CLK_MANAGE)); + delay_ms(100); +#if 1 //wait for LinkUP + while(--i) + { + if( (REG32(0xb8b00728)&0x1f)==0x11) + break; + delay_ms(100); + } + if(i==0) + { + printk("i=%x Cannot LinkUP \n",i); + return FAIL; + } +#endif + +SET_BAR: + if (port==0) + { + // Enable PCIE host + if (pcie_reset_done[portnum] == 0) { +#if defined(__LINUX_2_6__) && defined(USE_RLX_BSP) + WRITE_MEM32(BSP_PCIE0_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(BSP_PCIE0_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#else + WRITE_MEM32(PCIE0_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE0_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#endif + pcie_reset_done[portnum] = 1; + } +#ifdef CONFIG_RTL_92D_DMDP + else { + Sw_PCIE_Func(1); + //choose the PCIE port number +#if defined(__LINUX_2_6__) && defined(USE_RLX_BSP) + WRITE_MEM32(BSP_PCIE0_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(BSP_PCIE0_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#else + WRITE_MEM32(PCIE0_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE0_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#endif + Sw_PCIE_Func(0); + } +#endif + } + else if (port==1) + { + // Enable PCIE host + if (pcie_reset_done[portnum] == 0) { +#if defined(__LINUX_2_6__) && defined(USE_RLX_BSP) + WRITE_MEM32(BSP_PCIE1_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(BSP_PCIE1_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#else + WRITE_MEM32(PCIE1_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE1_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#endif + pcie_reset_done[portnum] = 1; + } +#ifdef CONFIG_RTL_92D_DMDP + else { + Sw_PCIE_Func(1); +#if defined(__LINUX_2_6__) && defined(USE_RLX_BSP) + //choose the PCIE port number + WRITE_MEM32(BSP_PCIE1_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(BSP_PCIE1_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#else + WRITE_MEM32(PCIE1_H_CFG + 0x04, 0x00100007); + WRITE_MEM8(PCIE1_H_CFG + 0x78, (READ_MEM8(conf_addr + 0x78) & (~0xE0)) | MAX_PAYLOAD_SIZE_128B); // Set MAX_PAYLOAD_SIZE to 128B +#endif + Sw_PCIE_Func(0); + } +#endif + } + else + return FAIL; + return SUCCESS; +} + +#endif + + +void HostPCIe_Close(void) +{ + REG32(0xb8b10044) &= (~(3)); + REG32(0xb8b10044) |= (3); + HostPCIe_SetPhyMdioWrite(0, 0xf, 0x0708); + //.DeActive LX & PCIE Clock +#ifdef CONFIG_RTL8672 + REG32(MISC_IP_SEL) &= ~EN_PCIE; //enable active_pcie0 +#else + REG32(CLK_MANAGE) &=(0xFFFFFFFF- (1<<11)); //enable active_pcie0 +#endif + pcie_reset_done[0]=0; +} +#endif /* #elif (defined(CONFIG_RTL8196C) || defined(CONFIG_RTL_8196C)) */ + +#endif /* !defined(CONFIG_NET_PCI) */ +#endif + + +#ifdef CONFIG_RTL8671 +/*6/7/04 hrchen, invalidate the dcache with a 0->1 transition*/ + +#ifdef CONFIG_CPU_RLX4181 +int r3k_flush_dcache_range(int a, int b) +{ + int garbage_tmp; + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0 %0, $20\n\t" + "nop\n\t" + "nop\n\t" + "andi %0, 0xFDFF\n\t" + "mtc0 %0, $20\n\t" + "nop\n\t" + "nop\n\t" + "ori %0, 0x200\n\t" + "mtc0 %0, $20\n\t" + "nop\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (garbage_tmp)); + return 0; +} +#else +int r3k_flush_dcache_range(int a, int b) +{ + int garbage_tmp; + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0 %0, $20\n\t" + "nop\n\t" + "nop\n\t" + "andi %0, 0xFFFE\n\t" + "mtc0 %0, $20\n\t" + "nop\n\t" + "nop\n\t" + "ori %0, 1\n\t" + "mtc0 %0, $20\n\t" + "nop\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (garbage_tmp)); + return 0; +} +#endif + +#ifdef _USE_DRAM_ +//init DRAM +void r3k_enable_DRAM(void) +{ + int tmp, tmp1; + //--- initialize and start COP3 + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mfc0 %0,$12\n\t" + "nop\n\t" + "lui %1,0x8000\n\t" + "or %1,%0\n\t" + "mtc0 %1,$12\n\t" + "nop\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (tmp), "=r" (tmp1)); + + //set base + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mtc3 %0, $4 # $4: d-ram base\n\t" + "nop\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : + : "r" (DRAM_START_ADDR&0x0fffffff)); + + //set size + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "mtc3 %0, $5 # $5: d-ram top\n\t" + "nop\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : + : "r" (R3K_DRAM_SIZE-1)); + + //clear DRAM + __asm__ __volatile__( +"1:\n\t" + "sw $0,0(%1)\n\t" + "addiu %1,4\n\t" + "bne %0,%1,1b\n\t" + "nop\n\t" + ".set\tat\n\t" + ".set\treorder" + : + : "r" (DRAM_START_ADDR+R3K_DRAM_SIZE), "r" (DRAM_START_ADDR)); +} +#endif // _USE_DRAM_ +#endif // CONFIG_RTL8671 + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_hw.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_hw.c new file mode 100755 index 000000000..abdfaabce --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_hw.c @@ -0,0 +1,21372 @@ +/* + * Routines to access hardware + * + * $Id: 8192cd_hw.c,v 1.107.2.43 2011/01/17 13:21:01 victoryman Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_HW_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_hw.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" +#ifdef CONFIG_RTL_88E_SUPPORT +#include "Hal8188EPwrSeq.h" +#endif +#ifdef CONFIG_RTL_8812_SUPPORT +#include "Hal8812PwrSeq.h" +#endif + +#ifdef __KERNEL__ +#ifdef __LINUX_2_6__ +#include +#else +#include +#endif +#endif + +#ifdef USE_RTL8186_SDK +#ifdef CONFIG_RTL8672 + #ifdef USE_RLX_BSP + #include + #include + + #ifdef CONFIG_RTL_8196C + #undef CONFIG_RTL_8196C + #endif + #ifdef CONFIG_RTL8196C_REVISION_B + #undef CONFIG_RTL8196C_REVISION_B + #endif + + #else + #include + #include "../../../arch/mips/realtek/rtl8672/gpio.h" + #endif +#else + +#if defined(__LINUX_2_6__) +#if defined(CONFIG_OPENWRT_SDK) && !defined(CONFIG_ARCH_CPU_RLX) +#include +#else +#include +#endif //CONFIG_OPENWRT_SDK +#else +#ifndef __ECOS +#include +#endif +#endif +#endif + +#endif // USE_RTL8186_SDK + + +#define MAX_CONFIG_FILE_SIZE (20*1024) // for 8192, added to 20k + +int rtl8192cd_fileopen(const char *filename, int flags, int mode); +void selectMinPowerIdex(struct rtl8192cd_priv *priv); +void PHY_RF6052SetOFDMTxPower(struct rtl8192cd_priv *priv, unsigned int channel); +void PHY_RF6052SetCCKTxPower(struct rtl8192cd_priv *priv, unsigned int channel); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) || (defined(CONFIG_RTL_88E_SUPPORT) && defined(__KERNEL__) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI))) || defined(CONFIG_RTL_8812_SUPPORT) +static void rtl8192cd_ReadFwHdr(struct rtl8192cd_priv * priv); +#endif +#ifdef CONFIG_RTL_92C_SUPPORT +static int Load_92C_Firmware(struct rtl8192cd_priv *priv); +#endif + + + +#define VAR_MAPPING(dst,src) \ +unsigned char *data_##dst##_start = &data_##src[0]; \ +unsigned char *data_##dst##_end = &data_##src[sizeof(data_##src)]; \ + +#ifdef CONFIG_RTL_92D_SUPPORT +#include "data_PHY_REG_n.c" +#include "data_AGC_TAB_n.c" +#include "data_AGC_TAB_2G_n.c" +#include "data_AGC_TAB_5G_n.c" +#include "data_radio_a_n.c" +#include "data_radio_b_n.c" +#ifdef RTL8192D_INT_PA +#ifdef USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) +#include "data_radio_a_intPA_GM_new.c" +#include "data_radio_b_intPA_GM_new.c" +#elif defined (RTL8192D_INT_PA_GAIN_TABLE_NEW1) +#include "data_radio_a_intPA_GM_new1.c" +#include "data_radio_b_intPA_GM_new1.c" +#else +#include "data_radio_a_intPA_GM.c" +#include "data_radio_b_intPA_GM.c" +#endif + +#else // USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) +#include "data_radio_a_intPA_new.c" +#include "data_radio_b_intPA_new.c" +#else +#include "data_radio_a_intPA.c" +#include "data_radio_b_intPA.c" +#endif + +#endif // USB_POWER_SUPPORT +#endif // RTL8192D_INT_PA +//_TXPWR_REDEFINE +#ifdef HIGH_POWER_EXT_PA +#include "data_AGC_TAB_n_92d_hp.c" +#include "data_PHY_REG_n_92d_hp.c" +#include "data_radio_a_n_92d_hp.c" +#include "data_radio_b_n_92d_hp.c" +#include "data_PHY_REG_PG_92d_hp.c" +#endif +#include "data_PHY_REG_PG.c" +#include "data_PHY_REG_PG_FCC.c" +#include "data_PHY_REG_PG_CE.c" + +#ifdef _TRACKING_TABLE_FILE +#include "data_REG_TXPWR_TRK_n_92d.c" +#include "data_REG_TXPWR_TRK_n_92d_hp.c" +#endif +#include "data_PHY_REG_MP_n.c" +#include "data_MACPHY_REG.c" +#include "data_rtl8192dfw_n.c" +VAR_MAPPING(PHY_REG_n, PHY_REG_n); +VAR_MAPPING(AGC_TAB_n, AGC_TAB_n); +VAR_MAPPING(AGC_TAB_2G_n, AGC_TAB_2G_n); +VAR_MAPPING(AGC_TAB_5G_n, AGC_TAB_5G_n); +VAR_MAPPING(radio_a_n, radio_a_n); +VAR_MAPPING(radio_b_n, radio_b_n); +#ifdef RTL8192D_INT_PA +#ifdef USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) +VAR_MAPPING(radio_a_intPA_GM_new, radio_a_intPA_GM_new); +VAR_MAPPING(radio_b_intPA_GM_new, radio_b_intPA_GM_new); +#elif defined (RTL8192D_INT_PA_GAIN_TABLE_NEW1) +VAR_MAPPING(radio_a_intPA_GM_new1, radio_a_intPA_GM_new1); +VAR_MAPPING(radio_b_intPA_GM_new1, radio_b_intPA_GM_new1); +#else +VAR_MAPPING(radio_a_intPA_GM, radio_a_intPA_GM); +VAR_MAPPING(radio_b_intPA_GM, radio_b_intPA_GM); +#endif + +#else // USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) +VAR_MAPPING(radio_a_intPA_new, radio_a_intPA_new); +VAR_MAPPING(radio_b_intPA_new, radio_b_intPA_new); +#else +VAR_MAPPING(radio_a_intPA, radio_a_intPA); +VAR_MAPPING(radio_b_intPA, radio_b_intPA); +#endif + +#endif // USB_POWER_SUPPORT +#endif // RTL8192D_INT_PA +//_TXPWR_REDEFINE +#ifdef HIGH_POWER_EXT_PA +VAR_MAPPING(AGC_TAB_n_92d_hp, AGC_TAB_n_92d_hp); +VAR_MAPPING(PHY_REG_n_92d_hp, PHY_REG_n_92d_hp); +VAR_MAPPING(radio_a_n_92d_hp, radio_a_n_92d_hp); +VAR_MAPPING(radio_b_n_92d_hp, radio_b_n_92d_hp); +VAR_MAPPING(PHY_REG_PG_92d_hp, PHY_REG_PG_92d_hp); +#endif +VAR_MAPPING(PHY_REG_PG, PHY_REG_PG); +VAR_MAPPING(PHY_REG_PG_FCC, PHY_REG_PG_FCC); +VAR_MAPPING(PHY_REG_PG_CE, PHY_REG_PG_CE); +#ifdef TXPWR_LMT +#include "TXPWR_92D.h" +#endif // TXPWR_LMT +#ifdef _TRACKING_TABLE_FILE +VAR_MAPPING(REG_TXPWR_TRK_n_92d, REG_TXPWR_TRK_n_92d); +VAR_MAPPING(REG_TXPWR_TRK_n_92d_hp, REG_TXPWR_TRK_n_92d_hp); +#endif +VAR_MAPPING(PHY_REG_MP_n, PHY_REG_MP_n); +VAR_MAPPING(MACPHY_REG, MACPHY_REG); +VAR_MAPPING(rtl8192dfw_n, rtl8192dfw_n); +#endif // CONFIG_RTL_92D_SUPPORT + +#ifdef CONFIG_RTL_92C_SUPPORT + +#ifdef TESTCHIP_SUPPORT +#include "data_AGC_TAB.c" +#include "data_PHY_REG_1T.c" +#include "data_PHY_REG_2T.c" +#include "data_radio_a_1T.c" +#include "data_radio_a_2T.c" +#include "data_radio_b_2T.c" +#include "data_rtl8192cfw.c" +#endif + +#include "data_AGC_TAB_n_92C.c" +#include "data_PHY_REG_1T_n.c" +#include "data_PHY_REG_2T_n.c" +#include "data_PHY_REG_2T_n_lna.c" +#include "data_radio_a_2T_n.c" +#include "data_radio_b_2T_n.c" +#include "data_radio_a_1T_n.c" +#include "data_rtl8192cfwn.c" +#include "data_rtl8192cfwua.c" + + +#include "data_PHY_REG_PG_92C.c" +#include "data_MACPHY_REG_92C.c" +#include "data_PHY_REG_MP_n_92C.c" + +#include "data_AGC_TAB_n_hp.c" +#include "data_PHY_REG_2T_n_hp.c" +#include "data_radio_a_2T_n_lna.c" +#include "data_radio_b_2T_n_lna.c" +#include "data_PHY_REG_1T_n_hp.c" + +#ifdef HIGH_POWER_EXT_PA +#include "data_radio_a_2T_n_hp.c" +#include "data_radio_b_2T_n_hp.c" +#include "data_PHY_REG_PG_hp.c" +#endif + +#ifdef _TRACKING_TABLE_FILE +#include "data_REG_TXPWR_TRK.c" +#include "data_REG_TXPWR_TRK_hp.c" +#endif + +#ifdef TXPWR_LMT +#include "TXPWR_92C.h" +#endif // TXPWR_LMT + + + + +#define VAR_MAPPING(dst,src) \ + unsigned char *data_##dst##_start = &data_##src[0]; \ + unsigned char *data_##dst##_end = &data_##src[sizeof(data_##src)]; \ + +#ifdef TESTCHIP_SUPPORT +VAR_MAPPING(AGC_TAB, AGC_TAB); +VAR_MAPPING(PHY_REG_1T, PHY_REG_1T); +VAR_MAPPING(PHY_REG_2T, PHY_REG_2T); +VAR_MAPPING(radio_a_1T, radio_a_1T); +VAR_MAPPING(radio_a_2T, radio_a_2T); +VAR_MAPPING(radio_b_2T, radio_b_2T); +VAR_MAPPING(rtl8192cfw, rtl8192cfw); +#endif + +VAR_MAPPING(AGC_TAB_n_92C, AGC_TAB_n_92C); +VAR_MAPPING(PHY_REG_1T_n, PHY_REG_1T_n); +VAR_MAPPING(PHY_REG_2T_n, PHY_REG_2T_n); +VAR_MAPPING(PHY_REG_2T_n_lna, PHY_REG_2T_n_lna); +VAR_MAPPING(radio_a_1T_n, radio_a_1T_n); +VAR_MAPPING(radio_a_2T_n, radio_a_2T_n); +VAR_MAPPING(radio_b_2T_n, radio_b_2T_n); +VAR_MAPPING(rtl8192cfw_n, rtl8192cfwn); +VAR_MAPPING(rtl8192cfw_ua, rtl8192cfwua); + +VAR_MAPPING(MACPHY_REG_92C, MACPHY_REG_92C); +VAR_MAPPING(PHY_REG_PG_92C, PHY_REG_PG_92C); +VAR_MAPPING(PHY_REG_MP_n_92C, PHY_REG_MP_n_92C); + +VAR_MAPPING(AGC_TAB_n_hp, AGC_TAB_n_hp); +VAR_MAPPING(PHY_REG_2T_n_hp, PHY_REG_2T_n_hp); +VAR_MAPPING(PHY_REG_1T_n_hp, PHY_REG_1T_n_hp); +VAR_MAPPING(radio_a_2T_n_lna, radio_a_2T_n_lna); +VAR_MAPPING(radio_b_2T_n_lna, radio_b_2T_n_lna); + +#ifdef HIGH_POWER_EXT_PA +VAR_MAPPING(radio_a_2T_n_hp, radio_a_2T_n_hp); +VAR_MAPPING(radio_b_2T_n_hp, radio_b_2T_n_hp); +VAR_MAPPING(PHY_REG_PG_hp, PHY_REG_PG_hp); +#endif + +#ifdef _TRACKING_TABLE_FILE +VAR_MAPPING(REG_TXPWR_TRK, REG_TXPWR_TRK); +VAR_MAPPING(REG_TXPWR_TRK_hp, REG_TXPWR_TRK_hp); +#endif + +#endif // CONFIG_RTL_92C_SUPPORT + +#ifdef CONFIG_RTL_88E_SUPPORT +#include "data_PHY_REG_PG_88E.c" + +VAR_MAPPING(PHY_REG_PG_88E, PHY_REG_PG_88E); + +#include "data_PHY_REG_PG_88E_new.c" +VAR_MAPPING(PHY_REG_PG_88E_new, PHY_REG_PG_88E_new); +#ifdef TXPWR_LMT_88E +#include "data_TXPWR_LMT_88E_new.c" +VAR_MAPPING(TXPWR_LMT_88E_new, TXPWR_LMT_88E_new); +#endif + +#endif // CONFIG_RTL_88E_SUPPORT + +#ifdef CONFIG_RTL_8812_SUPPORT +#include "data_AGC_TAB_8812.c" +#include "data_MAC_REG_8812.c" +#include "data_PHY_REG_8812.c" +#include "data_PHY_REG_MP_8812.c" +#include "data_PHY_REG_PG_8812.c" +#include "data_RadioA_8812.c" +#include "data_RadioB_8812.c" +#include "data_rtl8812fw.c" +#ifdef _TRACKING_TABLE_FILE +#include "data_REG_TXPWR_TRK_8812.c" +#ifdef HIGH_POWER_EXT_PA +#include "data_REG_TXPWR_TRK_8812_hp.c" +#include "data_PHY_REG_PG_8812_hp.c" +VAR_MAPPING(PHY_REG_PG_8812_hp, PHY_REG_PG_8812_hp); +#endif + +#include "data_PHY_REG_PG_8812_new.c" +VAR_MAPPING(PHY_REG_PG_8812_new, PHY_REG_PG_8812_new); +#ifdef TXPWR_LMT_8812 +#include "data_TXPWR_LMT_8812_new.c" +VAR_MAPPING(TXPWR_LMT_8812_new, TXPWR_LMT_8812_new); +#endif + +#endif + +VAR_MAPPING(rtl8812fw, rtl8812fw); +VAR_MAPPING(AGC_TAB_8812, AGC_TAB_8812); +VAR_MAPPING(MAC_REG_8812, MAC_REG_8812); +VAR_MAPPING(PHY_REG_8812, PHY_REG_8812); +VAR_MAPPING(PHY_REG_MP_8812, PHY_REG_MP_8812); +VAR_MAPPING(PHY_REG_PG_8812, PHY_REG_PG_8812); +VAR_MAPPING(RadioA_8812, RadioA_8812); +VAR_MAPPING(RadioB_8812, RadioB_8812); +#ifdef _TRACKING_TABLE_FILE +VAR_MAPPING(REG_TXPWR_TRK_8812, REG_TXPWR_TRK_8812); +#ifdef HIGH_POWER_EXT_PA +VAR_MAPPING(REG_TXPWR_TRK_8812_hp, REG_TXPWR_TRK_8812_hp); +#endif +#endif + +//FOR_8812_MP_CHIP +#include "data_MAC_REG_8812_n.c" +#include "data_AGC_TAB_8812_n_default.c" +#include "data_PHY_REG_8812_n_default.c" +#include "data_RadioA_8812_n_default.c" +#include "data_RadioB_8812_n_default.c" +#include "data_rtl8812fw_n.c" +#ifdef AC2G_256QAM +#include "data_rtl8812fw_n_2g.c" +VAR_MAPPING(rtl8812fw_n_2g, rtl8812fw_n_2g); +#endif +VAR_MAPPING(MAC_REG_8812_n, MAC_REG_8812_n); +VAR_MAPPING(rtl8812fw_n, rtl8812fw_n); +VAR_MAPPING(AGC_TAB_8812_n_default, AGC_TAB_8812_n_default); +VAR_MAPPING(PHY_REG_8812_n_default, PHY_REG_8812_n_default); +VAR_MAPPING(RadioA_8812_n_default, RadioA_8812_n_default); +VAR_MAPPING(RadioB_8812_n_default, RadioB_8812_n_default); +#include "data_AGC_TAB_8812_n_extlna.c" +#include "data_PHY_REG_8812_n_extlna.c" +#include "data_RadioA_8812_n_extlna.c" +#include "data_RadioB_8812_n_extlna.c" +VAR_MAPPING(AGC_TAB_8812_n_extlna, AGC_TAB_8812_n_extlna); +VAR_MAPPING(PHY_REG_8812_n_extlna, PHY_REG_8812_n_extlna); +VAR_MAPPING(RadioA_8812_n_extlna, RadioA_8812_n_extlna); +VAR_MAPPING(RadioB_8812_n_extlna, RadioB_8812_n_extlna); +#include "data_AGC_TAB_8812_n_extpa.c" +#include "data_PHY_REG_8812_n_extpa.c" +#include "data_RadioA_8812_n_extpa.c" +#include "data_RadioB_8812_n_extpa.c" +VAR_MAPPING(AGC_TAB_8812_n_extpa, AGC_TAB_8812_n_extpa); +VAR_MAPPING(PHY_REG_8812_n_extpa, PHY_REG_8812_n_extpa); +VAR_MAPPING(RadioA_8812_n_extpa, RadioA_8812_n_extpa); +VAR_MAPPING(RadioB_8812_n_extpa, RadioB_8812_n_extpa); + +#ifdef HIGH_POWER_EXT_PA //FOR_8812_HP +#include "data_AGC_TAB_8812_hp.c" +#include "data_RadioA_8812_hp.c" +#include "data_RadioB_8812_hp.c" +VAR_MAPPING(AGC_TAB_8812_hp, AGC_TAB_8812_hp); +VAR_MAPPING(RadioA_8812_hp, RadioA_8812_hp); +VAR_MAPPING(RadioB_8812_hp, RadioB_8812_hp); + +//FOR_8812_MP_CHIP +#include "data_AGC_TAB_8812_n_hp.c" +#include "data_PHY_REG_8812_n_hp.c" +#include "data_RadioA_8812_n_hp.c" +#include "data_RadioB_8812_n_hp.c" +#include "data_RadioA_8812_n_ultra_hp.c" +#include "data_RadioB_8812_n_ultra_hp.c" + +VAR_MAPPING(AGC_TAB_8812_n_hp, AGC_TAB_8812_n_hp); +VAR_MAPPING(PHY_REG_8812_n_hp, PHY_REG_8812_n_hp); +VAR_MAPPING(RadioA_8812_n_hp, RadioA_8812_n_hp); +VAR_MAPPING(RadioB_8812_n_hp, RadioB_8812_n_hp); +VAR_MAPPING(RadioA_8812_n_ultra_hp, RadioA_8812_n_ultra_hp); +VAR_MAPPING(RadioB_8812_n_ultra_hp, RadioB_8812_n_ultra_hp); + +#endif +#endif + +/*----------------------------------------------------------------------------- + * Function: PHYCheckIsLegalRfPath8192cPci() + * + * Overview: Check different RF type to execute legal judgement. If RF Path is illegal + * We will return false. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/15/2007 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +int PHYCheckIsLegalRfPath8192cPci(struct rtl8192cd_priv *priv, unsigned int eRFPath) +{ + unsigned int rtValue = TRUE; + + if (get_rf_mimo_mode(priv) == MIMO_2T2R) { + if ((eRFPath == RF92CD_PATH_A) || (eRFPath == RF92CD_PATH_B)) + rtValue = TRUE; + else + rtValue = FALSE; + } else if (get_rf_mimo_mode(priv) == MIMO_1T1R) { + if (eRFPath == RF92CD_PATH_A) + rtValue = TRUE; + else + rtValue = FALSE; + } else { + rtValue = FALSE; + } + + return rtValue; +} +#if defined(CONFIG_RTL_8196CS) +void setBaseAddressRegister(void) +{ + int tmp32 = 0, status; + while (++tmp32 < 100) { + REG32(0xb8b00004) = 0x00100007; + REG32(0xb8b10004) = 0x00100007; + REG32(0xb8b10010) = 0x18c00001; + REG32(0xb8b10018) = 0x19000004; + status = (REG32(0xb8b10010) ^ 0x18c00001) | ( REG32(0xb8b10018) ^ 0x19000004); + if (!status) + break; + else { + printk("set BAR fail,%x\n", status); + printk("%x %x %x %x \n", + REG32(0xb8b00004) , REG32(0xb8b10004) , REG32(0xb8b10010), REG32(0xb8b10018) ); + } + } ; +} +#endif +/** +* Function: phy_CalculateBitShift +* +* OverView: Get shifted position of the BitMask +* +* Input: +* u4Byte BitMask, +* +* Output: none +* Return: u4Byte Return the shift bit bit position of the mask +*/ +unsigned int phy_CalculateBitShift(unsigned int BitMask) +{ + unsigned int i; + + for (i = 0; i <= 31; i++) { + if (((BitMask >> i) & 0x1) == 1) + break; + } + + return (i); +} + +/** +* Function: PHY_QueryBBReg +* +* OverView: Read "sepcific bits" from BB register +* +* Input: +* PADAPTER Adapter, +* u4Byte RegAddr, //The target address to be readback +* u4Byte BitMask //The target bit position in the target address +* //to be readback +* Output: None +* Return: u4Byte Data //The readback register value +* Note: This function is equal to "GetRegSetting" in PHY programming guide +*/ +unsigned int PHY_QueryBBReg(struct rtl8192cd_priv *priv, unsigned int RegAddr, unsigned int BitMask) +{ + unsigned int ReturnValue = 0, OriginalValue, BitShift; + +#ifdef DISABLE_BB_RF + return 0; +#endif //DISABLE_BB_RF + +#ifdef CONFIG_RTL_92D_DMDP + unsigned char reg; + reg = MAC_PHY_CTRL_MP; + if (!(RTL_R8(reg) & BIT(1)) && priv->pshare->wlandev_idx == 1) { + return DMDP_PHY_QueryBBReg(0, RegAddr, BitMask); + } +#endif + + OriginalValue = RTL_R32(RegAddr); + BitShift = phy_CalculateBitShift(BitMask); + ReturnValue = (OriginalValue & BitMask) >> BitShift; + + return (ReturnValue); +} + + +/** +* Function: PHY_SetBBReg +* +* OverView: Write "Specific bits" to BB register (page 8~) +* +* Input: +* PADAPTER Adapter, +* u4Byte RegAddr, //The target address to be modified +* u4Byte BitMask //The target bit position in the target address +* //to be modified +* u4Byte Data //The new register value in the target bit position +* //of the target address +* +* Output: None +* Return: None +* Note: This function is equal to "PutRegSetting" in PHY programming guide +*/ +void PHY_SetBBReg(struct rtl8192cd_priv *priv, unsigned int RegAddr, unsigned int BitMask, unsigned int Data) +{ + unsigned int OriginalValue, BitShift, NewValue; + +#ifdef DISABLE_BB_RF + return; +#endif //DISABLE_BB_RF + +#ifdef CONFIG_RTL_92D_DMDP + unsigned char reg; + reg = MAC_PHY_CTRL_MP; + + if (!(RTL_R8(reg) & BIT(1)) && priv->pshare->wlandev_idx == 1) { + DMDP_PHY_SetBBReg(0, RegAddr, BitMask, Data); + return; + } +#endif + + if (BitMask != bMaskDWord) { + //if not "double word" write + //_TXPWR_REDEFINE ?? if have original value, how to count tx power index from PG file ?? + OriginalValue = RTL_R32(RegAddr); + BitShift = phy_CalculateBitShift(BitMask); + NewValue = ((OriginalValue & (~BitMask)) | ((Data << BitShift) & BitMask)); + RTL_W32(RegAddr, NewValue); + } else + RTL_W32(RegAddr, Data); + + return; +} + + + +/** +* Function: phy_RFSerialWrite +* +* OverView: Write data to RF register (page 8~) +* +* Input: +* PADAPTER Adapter, +* RF92CD_RADIO_PATH_E eRFPath, //Radio path of A/B/C/D +* u4Byte Offset, //The target address to be read +* u4Byte Data //The new register Data in the target bit position +* //of the target to be read +* +* Output: None +* Return: None +* Note: Threre are three types of serial operations: (1) Software serial write +* (2) Hardware LSSI-Low Speed Serial Interface (3) Hardware HSSI-High speed +* serial write. Driver need to implement (1) and (2). +* This function is equal to the combination of RF_ReadReg() and RFLSSIRead() + * + * Note: For RF8256 only + * The total count of RTL8256(Zebra4) register is around 36 bit it only employs + * 4-bit RF address. RTL8256 uses "register mode control bit" (Reg00[12], Reg00[10]) + * to access register address bigger than 0xf. See "Appendix-4 in PHY Configuration + * programming guide" for more details. + * Thus, we define a sub-finction for RTL8526 register address conversion + * =========================================================== + * Register Mode RegCTL[1] RegCTL[0] Note + * (Reg00[12]) (Reg00[10]) + * =========================================================== + * Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf) + * ------------------------------------------------------------------ + * Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf) + * ------------------------------------------------------------------ + * Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf) + * ------------------------------------------------------------------ +*/ +void phy_RFSerialWrite(struct rtl8192cd_priv *priv, RF92CD_RADIO_PATH_E eRFPath, unsigned int Offset, unsigned int Data) +{ + struct rtl8192cd_hw *phw = GET_HW(priv); + unsigned int DataAndAddr = 0; + BB_REGISTER_DEFINITION_T *pPhyReg = &phw->PHYRegDef[eRFPath]; + unsigned int NewOffset; + +#if defined(CONFIG_RTL_88E_SUPPORT) + if(GET_CHIP_VER(priv) == VERSION_8188E) + Offset &= 0xff; + else +#endif + Offset &= 0x7f; + // + // Switch page for 8256 RF IC + // + NewOffset = Offset; + + // + // Put write addr in [5:0] and write data in [31:16] + // + //DataAndAddr = (Data<<16) | (NewOffset&0x3f); + DataAndAddr = ((NewOffset << 20) | (Data & 0x000fffff)) & 0x0fffffff; // T65 RF + + // + // Write Operation + // + PHY_SetBBReg(priv, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr); +} + + +/** +* Function: phy_RFSerialRead +* +* OverView: Read regster from RF chips +* +* Input: +* PADAPTER Adapter, +* RF92CD_RADIO_PATH_E eRFPath, //Radio path of A/B/C/D +* u4Byte Offset, //The target address to be read +* u4Byte dbg_avoid, //set bitmask in reg 0 to prevent RF switchs to debug mode +* +* Output: None +* Return: u4Byte reback value +* Note: Threre are three types of serial operations: (1) Software serial write +* (2) Hardware LSSI-Low Speed Serial Interface (3) Hardware HSSI-High speed +* serial write. Driver need to implement (1) and (2). +* This function is equal to the combination of RF_ReadReg() and RFLSSIRead() +*/ +unsigned int phy_RFSerialRead(struct rtl8192cd_priv *priv, RF92CD_RADIO_PATH_E eRFPath, unsigned int Offset, unsigned int dbg_avoid) +{ + struct rtl8192cd_hw *phw = GET_HW(priv); + unsigned int tmplong, tmplong2; + unsigned int retValue = 0; + BB_REGISTER_DEFINITION_T *pPhyReg = &phw->PHYRegDef[eRFPath]; + unsigned int NewOffset; + + // + // Make sure RF register offset is correct + // +#if defined(CONFIG_RTL_88E_SUPPORT) + if(GET_CHIP_VER(priv) == VERSION_8188E) + Offset &= 0xff; + else +#endif + Offset &= 0x7f; + + // + // Switch page for 8256 RF IC + // + NewOffset = Offset; + +#if 0 // 92E use PHY_QueryRFReg & PHY_WriteRFReg callback function +//#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + int RfPiEnable = 0; + if (eRFPath == RF_PATH_A) { + tmplong2 = PHY_QueryBBReg(priv, rFPGA0_XA_HSSIParameter2, bMaskDWord);; + tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset << 23) | bLSSIReadEdge; //T65 RF + PHY_SetBBReg(priv, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong2 & (~bLSSIReadEdge)); + } else { + tmplong2 = PHY_QueryBBReg(priv, rFPGA0_XB_HSSIParameter2, bMaskDWord); + tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset << 23) | bLSSIReadEdge; //T65 RF + PHY_SetBBReg(priv, rFPGA0_XB_HSSIParameter2, bMaskDWord, tmplong2 & (~bLSSIReadEdge)); + } + + tmplong2 = PHY_QueryBBReg(priv, rFPGA0_XA_HSSIParameter2, bMaskDWord); + PHY_SetBBReg(priv, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong2 & (~bLSSIReadEdge)); + PHY_SetBBReg(priv, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong2 | bLSSIReadEdge); + + delay_us(20); + } else +#endif + { + + // For 92S LSSI Read RFLSSIRead + // For RF A/B write 0x824/82c(does not work in the future) + // We must use 0x824 for RF A and B to execute read trigger + tmplong = RTL_R32(rFPGA0_XA_HSSIParameter2); + tmplong2 = RTL_R32(pPhyReg->rfHSSIPara2); + tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | ((NewOffset << 23) | bLSSIReadEdge); //T65 RF + + RTL_W32(rFPGA0_XA_HSSIParameter2, tmplong & (~bLSSIReadEdge)); + delay_us(20); + RTL_W32(pPhyReg->rfHSSIPara2, tmplong2); + delay_us(20); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + ) { + RTL_W32(rFPGA0_XA_HSSIParameter2, tmplong | bLSSIReadEdge); + delay_us(20); + RTL_W32(rFPGA0_XA_HSSIParameter2, tmplong & (~bLSSIReadEdge)); + } +#endif + + } + //Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF + if (((eRFPath == RF92CD_PATH_A) && (RTL_R32(0x820)&BIT(8))) + || ((eRFPath == RF92CD_PATH_B) && (RTL_R32(0x828)&BIT(8)))) + retValue = PHY_QueryBBReg(priv, pPhyReg->rfLSSIReadBackPi, bLSSIReadBackData); + else + retValue = PHY_QueryBBReg(priv, pPhyReg->rfLSSIReadBack, bLSSIReadBackData); + + return retValue; +} + + +#ifdef AC2G_256QAM +char is_ac2g(struct rtl8192cd_priv * priv) +{ + + unsigned char ac2g = 0; + + if((GET_CHIP_VER(priv)== VERSION_8812E) || (GET_CHIP_VER(priv)== VERSION_8881A)) + { + if(priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC + && ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) == 0) + && (priv->pshare->rf_ft_var.ac2g_enable) + ) + ac2g = 1; + + if((OPMODE&WIFI_STATION_STATE) + && (priv->pmib->dot11BssType.net_work_type == (WIRELESS_11A|WIRELESS_11B|WIRELESS_11G|WIRELESS_11N|WIRELESS_11AC)) + && ((priv->pmib->dot11RFEntry.dot11channel != 0) && (priv->pmib->dot11RFEntry.dot11channel<36))) + ac2g = 1; + } + + return ac2g; + +} +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) + +unsigned int PHY_QueryRFReg_8812(struct rtl8192cd_priv *priv, RF92CD_RADIO_PATH_E eRFPath, + unsigned int RegAddr, unsigned int BitMask, unsigned int dbg_avoid) +{ + unsigned int Original_Value = 0, Readback_Value, BitShift; + unsigned int dwTmp; + + PHY_SetBBReg(priv, 0x838, 0xf, 0xc); // CCA off + + RTL_W8(0x8b0, RegAddr); + + if (IS_TEST_CHIP(priv)) { //for_8812_mp_chip + dwTmp = RTL_R32(0x8b0); + dwTmp &= ~BIT(8); + RTL_W32(0x8b0, dwTmp); + //printk("0x8b0 = 0x%x\n", dwTmp); + dwTmp |= BIT(8); + RTL_W32(0x8b0, dwTmp); + //printk("0x8b0 = 0x%x\n", dwTmp); + } + + delay_us(50); + + if (eRFPath == RF92CD_PATH_A) + Original_Value = RTL_R32(0xd04); + else if (eRFPath == RF92CD_PATH_B) + Original_Value = RTL_R32(0xd44); + + //printk("_eric_8812 rf_%x = 0x%x \n", RegAddr, Original_Value); + + Original_Value &= 0xfffff; + + BitShift = phy_CalculateBitShift(BitMask); + Readback_Value = (Original_Value & BitMask) >> BitShift; + + PHY_SetBBReg(priv, 0x838, 0xf, 0x4); // CCA on + + return (Readback_Value); +} + +void phy_RFSerialWrite_8812(struct rtl8192cd_priv *priv, RF92CD_RADIO_PATH_E eRFPath, unsigned int Offset, unsigned int Data) +{ + unsigned int dwTmp = 0; + unsigned int value = ((Offset << 20) | Data); + + //printk("_eric_8182 phy_RFSerialWrite_8812 +++ \n"); + + PHY_SetBBReg(priv, 0x838, 0xf, 0xc); // CCA off + + if (eRFPath == RF92CD_PATH_A) { + dwTmp = RTL_R32(0xc90); + dwTmp &= 0xf0000000; + dwTmp |= value; + //printk("_eric_8812 0xc90 = 0x%x \n", dwTmp); + RTL_W32(0xc90, dwTmp); + } else if (eRFPath == RF92CD_PATH_B) { + dwTmp = RTL_R32(0xe90); + dwTmp &= 0xf0000000; + dwTmp |= value; + //printk("_eric_8812 0xe90 = 0x%x \n", dwTmp); + RTL_W32(0xe90, dwTmp); + } + + PHY_SetBBReg(priv, 0x838, 0xf, 0x4); // CCA on +} + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +void PHY_SetRFReg_8812(struct rtl8192cd_priv *priv, RF92CD_RADIO_PATH_E eRFPath, unsigned int RegAddr, + unsigned int BitMask, unsigned int Data) +{ + unsigned int Original_Value, BitShift, New_Value; +#ifndef SMP_SYNC + unsigned long flags; +#endif +#if 0 + if (priv->pshare->No_RF_Write == 1 +#ifdef MP_TEST + && (!priv->pshare->rf_ft_var.mp_specific) +#endif + ) + return; +#endif + SAVE_INT_AND_CLI(flags); + if (BitMask != bMask20Bits) { + Original_Value = PHY_QueryRFReg_8812(priv, eRFPath, RegAddr, bMask20Bits, 0); + BitShift = phy_CalculateBitShift(BitMask); + New_Value = ((Original_Value & (~BitMask)) | (Data << BitShift)); + phy_RFSerialWrite_8812(priv, eRFPath, RegAddr, New_Value); + } else { + phy_RFSerialWrite_8812(priv, eRFPath, RegAddr, Data); + } + + delay_us(1); // At least 500ns delay to avoid RF write fail. + RESTORE_INT(flags); +} + +#endif + + +/** +* Function: PHY_QueryRFReg +* +* OverView: Query "Specific bits" to RF register (page 8~) +* +* Input: +* PADAPTER Adapter, +* RF92CD_RADIO_PATH_E eRFPath, //Radio path of A/B/C/D +* u4Byte RegAddr, //The target address to be read +* u4Byte BitMask //The target bit position in the target address +* //to be read +* u4Byte dbg_avoid //set bitmask in reg 0 to prevent RF switchs to debug mode +* +* Output: None +* Return: u4Byte Readback value +* Note: This function is equal to "GetRFRegSetting" in PHY programming guide +*/ +unsigned int PHY_QueryRFReg(struct rtl8192cd_priv *priv, RF92CD_RADIO_PATH_E eRFPath, + unsigned int RegAddr, unsigned int BitMask, unsigned int dbg_avoid) +{ +#ifdef DISABLE_BB_RF + return 0; +#endif //DISABLE_BB_RF + +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + return PHY_QueryRFReg_8812(priv, eRFPath, RegAddr, BitMask, dbg_avoid); + } +#endif + +#if defined(CONFIG_WLAN_HAL) + if(IS_HAL_CHIP(priv)) { + return GET_HAL_INTERFACE(priv)->PHYQueryRFRegHandler(priv, eRFPath, RegAddr, BitMask); + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + unsigned int Original_Value, Readback_Value, BitShift; + +#ifdef CONFIG_RTL_92D_DMDP + unsigned char reg; + reg = MAC_PHY_CTRL_MP; + if (!(RTL_R8(reg) & BIT(1)) && priv->pshare->wlandev_idx == 1) { + return DMDP_PHY_QueryRFReg(0, eRFPath, RegAddr, BitMask, dbg_avoid); + } +#endif + + Original_Value = phy_RFSerialRead(priv, eRFPath, RegAddr, dbg_avoid); + BitShift = phy_CalculateBitShift(BitMask); + Readback_Value = (Original_Value & BitMask) >> BitShift; + return (Readback_Value); + } +} + + +/** +* Function: PHY_SetRFReg +* +* OverView: Write "Specific bits" to RF register (page 8~) +* +* Input: +* PADAPTER Adapter, +* RF92CD_RADIO_PATH_E eRFPath, //Radio path of A/B/C/D +* u4Byte RegAddr, //The target address to be modified +* u4Byte BitMask //The target bit position in the target address +* //to be modified +* u4Byte Data //The new register Data in the target bit position +* //of the target address +* +* Output: None +* Return: None +* Note: This function is equal to "PutRFRegSetting" in PHY programming guide +*/ +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +void PHY_SetRFReg(struct rtl8192cd_priv *priv, RF92CD_RADIO_PATH_E eRFPath, unsigned int RegAddr, + unsigned int BitMask, unsigned int Data) +{ +#ifdef DISABLE_BB_RF + return; +#endif //DISABLE_BB_RF + +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + return PHY_SetRFReg_8812(priv, eRFPath, RegAddr, BitMask, Data); + } +#endif + +#if defined(CONFIG_WLAN_HAL) + if(IS_HAL_CHIP(priv)) { + return GET_HAL_INTERFACE(priv)->PHYSSetRFRegHandler(priv, eRFPath, RegAddr, BitMask, Data); + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + unsigned int Original_Value, BitShift, New_Value; +#ifndef SMP_SYNC + unsigned long flags; +#endif + +#ifdef CONFIG_RTL_92D_DMDP + unsigned char reg; + reg = MAC_PHY_CTRL_MP; + + if (!(RTL_R8(reg) & BIT(1)) && priv->pshare->wlandev_idx == 1) { + DMDP_PHY_SetRFReg(0, eRFPath, RegAddr, BitMask, Data); + return; + } +#endif + + SAVE_INT_AND_CLI(flags); + + if (BitMask != bMask20Bits) { + Original_Value = phy_RFSerialRead(priv, eRFPath, RegAddr, 1); + BitShift = phy_CalculateBitShift(BitMask); + New_Value = ((Original_Value & (~BitMask)) | (Data << BitShift)); + + phy_RFSerialWrite(priv, eRFPath, RegAddr, New_Value); + } else { + phy_RFSerialWrite(priv, eRFPath, RegAddr, Data); + } + + RESTORE_INT(flags); + delay_us(2); // At least 500ns delay to avoid RF write fail. + } +} + + +#ifdef TXPWR_LMT_NEWFILE +static int is_NA(char* s) +{ + if (( s[0] == 'N' || s[0] == 'n') && ( s[1] == 'A' || s[1] == 'a')) + return 1; + else + return 0; +} +#endif + +static int is_hex(char s) +{ + if (( s >= '0' && s <= '9') || ( s >= 'a' && s <= 'f') || (s >= 'A' && s <= 'F') || (s == 'x' || s == 'X')) + return 1; + else + return 0; +} + + +static int is_item(char s) +{ + if (s == 't' || s == 'a' || s == 'b' || s == 'l' || s == 'e' || s == ':') + return 1; + else + return 0; +} + +static unsigned char *get_digit(unsigned char **data) +{ + unsigned char *buf = *data; + int i = 0; + + while (buf[i] && ((buf[i] == ' ') || (buf[i] == '\t'))) + i++; + *data = &buf[i]; + + while (buf[i]) { + if ((buf[i] == ' ') || (buf[i] == '\t')) { + buf[i] = '\0'; + break; + } + if (buf[i] >= 'A' && buf[i] <= 'Z') + buf[i] += 32; + + if (!is_hex(buf[i]) && !is_item(buf[i])) + return NULL; + i++; + } + if (i == 0) + return NULL; + else + return &buf[i + 1]; +} + +#ifdef TXPWR_LMT_NEWFILE + +static unsigned char *get_digit_dot_8812(unsigned char **data) +{ + unsigned char *buf=*data; + int i=0; + + while(buf[i] && ((buf[i] == ' ') || (buf[i] == '\t'))) + i++; + + *data = &buf[i]; + + while(buf[i]) { + if(buf[i] == '.'){ +// while((buf[i]==' ') ||(buf[i]=='\t') || (buf[i]=='\0') || (buf[i]=='/')) +// i++; + + i++; + } + + if ((buf[i] == ' ') || (buf[i] == '\t')) { + buf[i] = '\0'; + break; + } + + if (buf[i]>='A' && buf[i]<='Z') + buf[i] += 32; + + if (!is_hex(buf[i])&&!is_item(buf[i]) + && !is_NA((char *)&buf[i])) + return NULL; + + i++; + } + if (i == 0) + return NULL; + else + { + return &buf[i+1]; + } +} + + +#define LMT_NUM 256 +static int get_chnl_lmt_dot_new(struct rtl8192cd_priv *priv, unsigned char *line_head, unsigned int *channel, unsigned int *limit, unsigned int *table_idx) +{ + unsigned char *next, *next2, *next3; + int base, idx; + int num=0; + int num_index; + int val; + int i; // for loop + unsigned char *ch; + unsigned char lmt[LMT_NUM]; + unsigned char *twpwr_lmt_index_array; + unsigned char lmtIndex; + extern int _atoi(char *s, int base); + + *channel = '\0'; + base = 10; + + //find limit table index first + if (!memcmp(line_head+2,"Table",5)) { + *channel = 0; + //printk("found idx\n"); + goto find_idx; + } + else if (!memcmp(line_head,"CH0",3)) { + //printk("found channel\n"); + ch = line_head+3; + } + else if (!memcmp(line_head,"CH",2)) { + //printk("found channel\n"); + ch = line_head+2; + } + else + return 0; + + *channel = _atoi(ch, base); + + + num = 0; + next = get_digit_dot_8812(&ch); + + while(next != NULL) + { + num++; + if(is_NA(next)) + lmt[num] = 0; //No limit + else { + val = _convert_2_pwr_dot(next, base); + if(val == -1) + num --; + else + lmt[num] = val; + } + next = get_digit_dot_8812(&next); + + } + if(num == 0) + panic_printk("TX Power Porfile format Error\n"); + + //printk("channel = %d, lmt = %d %d %d\n", *channel, lmt[0], lmt[1], lmt[2]); + + + if(priv->pmib->dot11StationConfigEntry.txpwr_lmt_index <= 0) { + if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) + lmtIndex = 3; + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) + lmtIndex = 2; + else + lmtIndex = 1; + } else { + lmtIndex = priv->pmib->dot11StationConfigEntry.txpwr_lmt_index; + } + + *limit = lmt[lmtIndex]; + + return 1; + +find_idx: + + *channel = 0; + *limit = 0; + *table_idx = 0; + + line_head = line_head + 8; + + *table_idx = _atoi(line_head, base); //In this condition, 'limit' represents "# of table" + //printk("\n[table_idx = %d]\n", *table_idx); + + return 1; + +} +#endif + + +static unsigned char *get_digit_dot(unsigned char **data) +{ + unsigned char *buf = *data; + int i = 0; + + while (buf[i] && ((buf[i] == ' ') || (buf[i] == '\t'))) + i++; + + *data = &buf[i]; + + while (buf[i]) { + if (buf[i] == '.') { +// while ((buf[i] == ' ') || (buf[i] == '\t') || (buf[i] == '\0') || (buf[i] == '/')) +// i++; + + i++; + } + + if ((buf[i] == ' ') || (buf[i] == '\t')) { + buf[i] = '\0'; + break; + } + if (buf[i] >= 'A' && buf[i] <= 'Z') + buf[i] += 32; + + if (!is_hex(buf[i]) && !is_item(buf[i])) + return NULL; + i++; + } + if (i == 0) + return NULL; + else + { + return &buf[i + 1]; + } +} + + +#ifdef TXPWR_LMT +static int get_chnl_lmt_dot(unsigned char *line_head, unsigned int *ch_start, unsigned int *ch_end, unsigned int *limit, unsigned int *target) +{ + unsigned char *next, *next2; + int base, idx; + int num = 0; + unsigned char *ch; + extern int _atoi(char * s, int base); + + *ch_start = *ch_start = '\0'; + + // remove comments + ch = line_head; + while (1) { + if ((*ch == '\0') || (*ch == '\n') || (*ch == '\r')) + break; + else if (*ch == '/') { + *ch = '\0'; + break; + } else { + ch++; + } + } + + next = get_digit_dot(&line_head); + if (next == NULL) + return num; + num++; + + if (!memcmp(line_head, "table", 5)) { + *ch_start = 0; + *ch_end = 0; + } else { +// char *s; + int format = 0; + int idx2; + + if ((!memcmp(line_head, "0x", 2)) || (!memcmp(line_head, "0X", 2))) { + base = 16; + idx = 2; + } else { + base = 10; + idx = 0; + } + idx2 = idx; + while (line_head[idx2] != '\0') { + //printk("(%c)",line_head[idx2]); + if (line_head[idx2] == ':') { + line_head[idx2] = '\0'; + format = 1; // format - start:end + break; + } + idx2++; + } + *ch_start = _atoi((char *)&line_head[idx], base); + if (format == 0) { + *ch_end = *ch_start; + } else { + *ch_end = _atoi((char *)&line_head[idx2 + 1], base); + } + } + + + *limit = 0; + if (next) { + if (!(next2 = get_digit_dot(&next))) + return num; + num++; + + base = 10; + idx = 0; + + if ( (*ch_start == 0) && (*ch_end == 0) ) + *limit = _atoi((char *)&next[idx], base); //In this condition, 'limit' represents "# of table" + else + *limit = _convert_2_pwr_dot((char *)&next[idx], base); + } + + + *target = 0; + if (next2) { + if (!get_digit_dot(&next2)) + return num; + num++; + + base = 10; + idx = 0; + + *target = _convert_2_pwr_dot((char *)&next2[idx], base); + } + + + return num; +} +#endif + +//static +int get_offset_val(unsigned char *line_head, unsigned int *u4bRegOffset, unsigned int *u4bRegValue) +{ + unsigned char *next; + int base, idx; + int num = 0; + unsigned char *ch; + extern int _atoi(char * s, int base); + + *u4bRegOffset = *u4bRegValue = '\0'; + + ch = line_head; + while (1) { + if ((*ch == '\0') || (*ch == '\n') || (*ch == '\r')) + break; + else if (*ch == '/') { + *ch = '\0'; + break; + } else { + ch++; + } + } + + next = get_digit(&line_head); + if (next == NULL) + return num; + num++; + if ((!memcmp(line_head, "0x", 2)) || (!memcmp(line_head, "0X", 2))) { + base = 16; + idx = 2; + } else { + base = 10; + idx = 0; + } + *u4bRegOffset = _atoi((char *)&line_head[idx], base); + + if (next) { + if (!get_digit(&next)) + return num; + num++; + if ((!memcmp(next, "0x", 2)) || (!memcmp(next, "0X", 2))) { + base = 16; + idx = 2; + } else { + base = 10; + idx = 0; + } + *u4bRegValue = _atoi((char *)&next[idx], base); + } else + *u4bRegValue = 0; + + return num; +} + + +#if 0//defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) +void assign_target_value_88e_new(struct rtl8192cd_priv *priv, unsigned int *u4bRegOffset, unsigned char *tmp_byte) +{ + //CCK-11M + if(*u4bRegOffset == rTxAGC_A_CCK11_2_B_CCK11) + if(tmp_byte[3] != 0) + priv->pshare->tgpwr_CCK_new[RF_PATH_A] = tmp_byte[3]; + + if(*u4bRegOffset == rTxAGC_A_CCK11_2_B_CCK11) + if(tmp_byte[0] != 0) + priv->pshare->tgpwr_CCK_new[RF_PATH_B] = tmp_byte[0]; + + //OFDM-54M + if(*u4bRegOffset == rTxAGC_A_Rate54_24) + priv->pshare->tgpwr_OFDM_new[RF_PATH_A] = tmp_byte[3]; + + if(*u4bRegOffset == rTxAGC_B_Rate54_24) + priv->pshare->tgpwr_OFDM_new[RF_PATH_B] = tmp_byte[3]; + + //HT-MCS7 + if(*u4bRegOffset == rTxAGC_A_Mcs07_Mcs04) + priv->pshare->tgpwr_HT1S_new[RF_PATH_A] = tmp_byte[3]; + + if(*u4bRegOffset == rTxAGC_B_Mcs07_Mcs04) + priv->pshare->tgpwr_HT1S_new[RF_PATH_B] = tmp_byte[3]; + + //HT-MCS15 + if(*u4bRegOffset == rTxAGC_A_Mcs15_Mcs12) + priv->pshare->tgpwr_HT2S_new[RF_PATH_A] = tmp_byte[3]; + + if(*u4bRegOffset == rTxAGC_B_Mcs15_Mcs12) + priv->pshare->tgpwr_HT2S_new[RF_PATH_B] = tmp_byte[3]; + + +} +#endif +#if 0//defined( CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) +void assign_target_value_8812_new(struct rtl8192cd_priv *priv, unsigned int *u4bRegOffset, unsigned char *tmp_byte) +{ + //CCK-11M + if(*u4bRegOffset == rTxAGC_A_CCK11_CCK1_JAguar) + priv->pshare->tgpwr_CCK_new[RF_PATH_A] = tmp_byte[3]; + + if(*u4bRegOffset == rTxAGC_B_CCK11_CCK1_JAguar) + priv->pshare->tgpwr_CCK_new[RF_PATH_B] = tmp_byte[3]; + + //OFDM-54M + if(*u4bRegOffset == rTxAGC_A_Ofdm54_Ofdm24_JAguar) + priv->pshare->tgpwr_OFDM_new[RF_PATH_A] = tmp_byte[3]; + + if(*u4bRegOffset == rTxAGC_B_Ofdm54_Ofdm24_JAguar) + priv->pshare->tgpwr_OFDM_new[RF_PATH_B] = tmp_byte[3]; + + //HT-MCS7 + if(*u4bRegOffset == rTxAGC_A_MCS7_MCS4_JAguar) + priv->pshare->tgpwr_HT1S_new[RF_PATH_A] = tmp_byte[3]; + + if(*u4bRegOffset == rTxAGC_B_MCS7_MCS4_JAguar) + priv->pshare->tgpwr_HT1S_new[RF_PATH_B] = tmp_byte[3]; + + //HT-MCS15 + if(*u4bRegOffset == rTxAGC_A_MCS15_MCS12_JAguar) + priv->pshare->tgpwr_HT2S_new[RF_PATH_A] = tmp_byte[3]; + + if(*u4bRegOffset == rTxAGC_B_MCS15_MCS12_JAguar) + priv->pshare->tgpwr_HT2S_new[RF_PATH_B] = tmp_byte[3]; + + //VHT-NSS1-MCS7 + if(*u4bRegOffset == rTxAGC_A_Nss1Index7_Nss1Index4_JAguar) + priv->pshare->tgpwr_VHT1S_new[RF_PATH_A] = tmp_byte[3]; + + if(*u4bRegOffset == rTxAGC_B_Nss1Index7_Nss1Index4_JAguar) + priv->pshare->tgpwr_VHT1S_new[RF_PATH_B] = tmp_byte[3]; + + //VHT-NSS2-MCS7 + if(*u4bRegOffset == rTxAGC_A_Nss2Index9_Nss2Index6_JAguar) + priv->pshare->tgpwr_VHT2S_new[RF_PATH_A] = tmp_byte[1]; + + if(*u4bRegOffset == rTxAGC_B_Nss2Index9_Nss2Index6_JAguar) + priv->pshare->tgpwr_VHT2S_new[RF_PATH_B] = tmp_byte[1]; + +} +#endif + +unsigned int gen_reg_value(unsigned char* tmp_reg) +{ + return (tmp_reg[0] | (tmp_reg[1]<<8) | (tmp_reg[2]<<16) | (tmp_reg[3]<<24)) ; +} + +unsigned int gen_reg_value_2(unsigned char target, unsigned char* tmp_byte, unsigned char* tmp_reg) +{ + unsigned char i =0; + + for(i=0; i<4; i++) + { + if(target < tmp_byte[i]) + tmp_reg[i] = tmp_byte[i] - target; + else + tmp_reg[i] = target - tmp_byte[i]; + } + + return (tmp_reg[0] | (tmp_reg[1]<<8) | (tmp_reg[2]<<16) | (tmp_reg[3]<<24)) ; +} + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) +unsigned int generate_u4bRegValue_88e_new(struct rtl8192cd_priv *priv, unsigned int *u4bRegOffset, unsigned char *tmp_byte) +{ + unsigned char tmp_reg[4]; + unsigned int reg_value = 0; + unsigned char target = 0; + + if(*u4bRegOffset == rTxAGC_A_CCK1_Mcs32) //{NA NA 1M NA} + { + reg_value = RTL_R32(rTxAGC_A_CCK1_Mcs32); + + tmp_reg[0]= (reg_value & (0xff)); + tmp_reg[1]= tmp_byte[1]- priv->pshare->tgpwr_CCK_new[RF_PATH_A]; + tmp_reg[2]= ((reg_value & (0xff0000)) >> 16); + tmp_reg[3]= ((reg_value & (0xff000000)) >> 24); + + reg_value = gen_reg_value(tmp_reg); + return reg_value; + } + else if(*u4bRegOffset == rTxAGC_B_CCK5_1_Mcs32) // {5.5M 2M 1M NA} + { + reg_value = RTL_R32(rTxAGC_B_CCK5_1_Mcs32); + tmp_reg[0]= (reg_value & (0xff)); + tmp_reg[1]= tmp_byte[1]- priv->pshare->tgpwr_CCK_new[RF_PATH_B]; + tmp_reg[2]= tmp_byte[2]- priv->pshare->tgpwr_CCK_new[RF_PATH_B]; + tmp_reg[3]= tmp_byte[3]- priv->pshare->tgpwr_CCK_new[RF_PATH_B]; + + reg_value = gen_reg_value(tmp_reg); + return reg_value; + } + else if(*u4bRegOffset == rTxAGC_A_CCK11_2_B_CCK11) //{11M 5.5M 2M NA} {NA NA NA NA 11M} + { + reg_value = RTL_R32(rTxAGC_A_CCK11_2_B_CCK11); + if (tmp_byte[3] > 0) + tmp_reg[3] = tmp_byte[3] - priv->pshare->tgpwr_CCK_new[RF_PATH_A]; + else + tmp_reg[3] = ((reg_value & (0xff000000)) >> 24); + + if (tmp_byte[0] > 0) + tmp_reg[0] = tmp_byte[0] - priv->pshare->tgpwr_CCK_new[RF_PATH_B]; + else + tmp_reg[0] = (reg_value & 0xff); + + if(tmp_byte[1] > 0) + tmp_reg[1]= tmp_byte[1]- priv->pshare->tgpwr_CCK_new[RF_PATH_A]; + else + tmp_reg[1]=((reg_value & (0xff00)) >> 8); + + if(tmp_byte[2] > 0) + tmp_reg[2]= tmp_byte[2]- priv->pshare->tgpwr_CCK_new[RF_PATH_A]; + else + tmp_reg[2]=((reg_value & (0xff0000)) >> 16); + + reg_value = gen_reg_value(tmp_reg); + RTL_W32(rTxAGC_A_CCK11_2_B_CCK11, reg_value); + return reg_value; + } + + switch (*u4bRegOffset) { + case rTxAGC_A_Rate18_06: + case rTxAGC_A_Rate54_24: + target = priv->pshare->tgpwr_OFDM_new[RF_PATH_A]; + break; + case rTxAGC_A_Mcs03_Mcs00: + case rTxAGC_A_Mcs07_Mcs04: + target = priv->pshare->tgpwr_HT1S_new[RF_PATH_A]; + break; + case rTxAGC_A_Mcs11_Mcs08: + case rTxAGC_A_Mcs15_Mcs12: + target = priv->pshare->tgpwr_HT2S_new[RF_PATH_A]; + break; + case rTxAGC_B_Rate18_06: + case rTxAGC_B_Rate54_24: + target = priv->pshare->tgpwr_OFDM_new[RF_PATH_B]; + break; + case rTxAGC_B_Mcs03_Mcs00: + case rTxAGC_B_Mcs07_Mcs04: + target = priv->pshare->tgpwr_HT1S_new[RF_PATH_B]; + break; + case rTxAGC_B_Mcs11_Mcs08: + case rTxAGC_B_Mcs15_Mcs12: + target = priv->pshare->tgpwr_HT2S_new[RF_PATH_B]; + break; + } + + reg_value = gen_reg_value_2(target, tmp_byte, tmp_reg); + return reg_value; + +} +#endif + +#if defined(RTK_AC_SUPPORT) +unsigned int generate_u4bRegValue_8812_new(struct rtl8192cd_priv *priv, unsigned int *u4bRegOffset, unsigned char *tmp_byte) +{ + unsigned char tmp_reg[4]; + unsigned int reg_value = 0; + unsigned char target = 0; + + if(*u4bRegOffset == rTxAGC_A_Nss2Index1_Nss1Index8_JAguar) + { + tmp_reg[0]= tmp_byte[0]- priv->pshare->tgpwr_VHT1S_new[RF_PATH_A]; + tmp_reg[1]= tmp_byte[1]- priv->pshare->tgpwr_VHT1S_new[RF_PATH_A]; + tmp_reg[2]= tmp_byte[2]- priv->pshare->tgpwr_VHT2S_new[RF_PATH_A]; + tmp_reg[3]= tmp_byte[3]- priv->pshare->tgpwr_VHT2S_new[RF_PATH_A]; + + reg_value = gen_reg_value(tmp_reg); + return reg_value; + } + else if(*u4bRegOffset == rTxAGC_B_Nss2Index1_Nss1Index8_JAguar) + { + tmp_reg[0]= tmp_byte[0]- priv->pshare->tgpwr_VHT1S_new[RF_PATH_B]; + tmp_reg[1]= tmp_byte[1]- priv->pshare->tgpwr_VHT1S_new[RF_PATH_B]; + tmp_reg[2]= tmp_byte[2]- priv->pshare->tgpwr_VHT2S_new[RF_PATH_B]; + tmp_reg[3]= tmp_byte[3]- priv->pshare->tgpwr_VHT2S_new[RF_PATH_B]; + + reg_value = gen_reg_value(tmp_reg); + return reg_value; + } + + switch (*u4bRegOffset) { + case rTxAGC_A_CCK11_CCK1_JAguar: + target = priv->pshare->tgpwr_CCK_new[RF_PATH_A]; + break; + case rTxAGC_A_Ofdm18_Ofdm6_JAguar: + target = priv->pshare->tgpwr_OFDM_new[RF_PATH_A]; + break; + case rTxAGC_A_Ofdm54_Ofdm24_JAguar: + target = priv->pshare->tgpwr_OFDM_new[RF_PATH_A]; + break; + case rTxAGC_A_MCS3_MCS0_JAguar: + target = priv->pshare->tgpwr_HT1S_new[RF_PATH_A]; + break; + case rTxAGC_A_MCS7_MCS4_JAguar: + target = priv->pshare->tgpwr_HT1S_new[RF_PATH_A]; + break; + case rTxAGC_A_MCS11_MCS8_JAguar: + target = priv->pshare->tgpwr_HT2S_new[RF_PATH_A]; + break; + case rTxAGC_A_MCS15_MCS12_JAguar: + target = priv->pshare->tgpwr_HT2S_new[RF_PATH_A]; + break; + case rTxAGC_A_Nss1Index3_Nss1Index0_JAguar: + target = priv->pshare->tgpwr_VHT1S_new[RF_PATH_A]; + break; + case rTxAGC_A_Nss1Index7_Nss1Index4_JAguar: + target = priv->pshare->tgpwr_VHT1S_new[RF_PATH_A]; + break; + case rTxAGC_A_Nss2Index1_Nss1Index8_JAguar: + break; + case rTxAGC_A_Nss2Index5_Nss2Index2_JAguar: + target = priv->pshare->tgpwr_VHT2S_new[RF_PATH_A]; + break; + case rTxAGC_A_Nss2Index9_Nss2Index6_JAguar: + target = priv->pshare->tgpwr_VHT2S_new[RF_PATH_A]; + break; + case rTxAGC_B_CCK11_CCK1_JAguar: + target = priv->pshare->tgpwr_CCK_new[RF_PATH_B]; + break; + case rTxAGC_B_Ofdm18_Ofdm6_JAguar: + target = priv->pshare->tgpwr_OFDM_new[RF_PATH_B]; + break; + case rTxAGC_B_Ofdm54_Ofdm24_JAguar: + target = priv->pshare->tgpwr_OFDM_new[RF_PATH_B]; + break; + case rTxAGC_B_MCS3_MCS0_JAguar: + target = priv->pshare->tgpwr_HT1S_new[RF_PATH_B]; + break; + case rTxAGC_B_MCS7_MCS4_JAguar: + target = priv->pshare->tgpwr_HT1S_new[RF_PATH_B]; + break; + case rTxAGC_B_MCS11_MCS8_JAguar: + target = priv->pshare->tgpwr_HT2S_new[RF_PATH_B]; + break; + case rTxAGC_B_MCS15_MCS12_JAguar: + target = priv->pshare->tgpwr_HT2S_new[RF_PATH_B]; + break; + case rTxAGC_B_Nss1Index3_Nss1Index0_JAguar: + target = priv->pshare->tgpwr_VHT1S_new[RF_PATH_B]; + break; + case rTxAGC_B_Nss1Index7_Nss1Index4_JAguar: + target = priv->pshare->tgpwr_VHT1S_new[RF_PATH_B]; + break; + case rTxAGC_B_Nss2Index1_Nss1Index8_JAguar: + break; + case rTxAGC_B_Nss2Index5_Nss2Index2_JAguar: + target = priv->pshare->tgpwr_VHT2S_new[RF_PATH_B]; + break; + case rTxAGC_B_Nss2Index9_Nss2Index6_JAguar: + target = priv->pshare->tgpwr_VHT2S_new[RF_PATH_B]; + break; + } + + reg_value = gen_reg_value_2(target, tmp_byte, tmp_reg); + return reg_value; + +} +#endif + + +static int find_str(char *line, char *str) +{ + int len=0, idx=0; + char *ch = NULL; + + if (!line ||!str || (strlen(str)>strlen(line))) + return 0; + + ch = line; + while(1) { + if (strlen(line) - strlen(str) < (idx+1)) + break; + + if (!memcmp(&(line[idx]), str, strlen(str))) { + return idx; + //break; + } + idx++; + } + + return 0; +} + +#if 0 +static int get_target_val_new(struct rtl8192cd_priv *priv, unsigned char *line_head, unsigned int *u4bRegOffset, unsigned int *u4bMask, unsigned int *u4bRegValue) +{ + int base, idx; + unsigned char *ch, *next, *pMask, *pValue; + extern int _atoi(char *s, int base); + + unsigned char *b3, *b2, *b1, *b0; + unsigned char tmp_byte[4]; + unsigned char lable = 0; //lable = {0: none, 1: 1Tx, 2: 2Tx} + + + *u4bRegOffset = *u4bRegValue = *u4bMask = '\0'; + + ch = line_head; + + while (1) { + if ((*ch == '\0') || (*ch == '\n') || (*ch == '\r')) + break; + else if (*ch == '/') { + *ch = '\0'; + break; + } else { + ch++; + } + } + + if ((!memcmp(line_head, "0xff", 4)) || (!memcmp(line_head, "0XFF", 4))) + return 0; + + if ((!memcmp(line_head, "0x", 2)) || (!memcmp(line_head, "0X", 2))) + { + base = 16; + idx = 2; + } + else if (!memcmp(line_head, "[1Tx]", 5)) + { + lable = 1; + idx = find_str(line_head, "0x"); + } + else if (!memcmp(line_head, "[2Tx]", 5)) + { + lable = 2; + idx = find_str(line_head, "0x"); + } + else + { + return 0; + } + + if (lable) + { + *u4bRegOffset = _atoi((char *)&line_head[idx+2], base); + + next = &(line_head[idx+2]); + pMask = get_digit(&next); + if (pMask) { + //*u4bMask = _atoi((char *)&pMask[2], 16); + + if ((b3 = get_digit_dot(&pMask)) == NULL) + return 0; + //panic_printk("\nb3:%s\n", b3); + if ((b2 = get_digit_dot(&b3)) == NULL) + return 0; + //panic_printk("b2:%s\n", b2); + if ((b1 = get_digit_dot(&b2)) == NULL) + return 0; + //panic_printk("b1:%s\n", b1); + + if ((b0 = get_digit_dot(&b1)) == NULL) + return 0; + //panic_printk("b0:%s\n", b0); + } + } + else + { + *u4bRegOffset = _atoi((char *)&line_head[idx], base); + + b3 = get_digit_dot(&line_head); + if (b3 == NULL) + return 0; + //panic_printk("b3:%s\n", b3); + b2 = get_digit_dot(&b3); + if (b2 == NULL) + return 0; + //panic_printk("b2:%s\n", b2); + b1 = get_digit_dot(&b2); + if (b1 == NULL) + return 0; + //panic_printk("b1:%s\n", b1); + b0 = get_digit_dot(&b1); + if (b0 == NULL) + return 0; + //panic_printk("b0:%s\n", b0); + } + + base = 10; + idx = 0; + +#if 1 + tmp_byte[3] = _convert_2_pwr_dot(b3, base); + tmp_byte[2] = _convert_2_pwr_dot(b2, base); + tmp_byte[1] = _convert_2_pwr_dot(b1, base); + tmp_byte[0] = _convert_2_pwr_dot(b0, base); +#else + tmp_byte[3] = _atoi(b3, base); + tmp_byte[2] = _atoi(b2, base); + tmp_byte[1] = _atoi(b1, base); + tmp_byte[0] = _atoi(b0, base); +#endif + + //printk("[%s] 0x%x: %d %d %d %d\n", __FUNCTION__, *u4bRegOffset, tmp_byte[3], tmp_byte[2], tmp_byte[1], tmp_byte[0]); + +#if 0 + panic_printk("[0x%x] tmp_byte = %02d-%02d-%02d-%02d\n", *u4bRegOffset, + tmp_byte[3], tmp_byte[2], tmp_byte[1], tmp_byte[0]); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE)//CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv)==VERSION_8192E) + assign_target_value_88e_new(priv, u4bRegOffset, tmp_byte); +#endif +#if defined( CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if(GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv)==VERSION_8881A) + assign_target_value_8812_new(priv, u4bRegOffset, tmp_byte); +#endif + return 1; +} +#endif + +static int get_offset_mask_val_new(struct rtl8192cd_priv *priv, unsigned char *line_head, unsigned int *u4bRegOffset, unsigned int *u4bMask, unsigned int *u4bRegValue) +{ + int base, idx; + unsigned char *ch, *next, *pMask, *pValue; + extern int _atoi(char *s, int base); + + unsigned char *b3, *b2, *b1, *b0; + unsigned char tmp_byte[4]; + + *u4bRegOffset = *u4bRegValue = *u4bMask = '\0'; + + ch = line_head; + + while (1) { + if ((*ch == '\0') || (*ch == '\n') || (*ch == '\r')) + break; + else if (*ch == '/') { + *ch = '\0'; + break; + } else { + ch++; + } + } + + if ((!memcmp(line_head, "0xff", 4)) || (!memcmp(line_head, "0XFF", 4))) + return 0; + + if ((!memcmp(line_head, "0x", 2)) || (!memcmp(line_head, "0X", 2))) + { + base = 16; + idx = 2; + } + else + { + return 0; + } + + *u4bRegOffset = _atoi((char *)&line_head[idx], base); + + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8192E)) + *u4bMask = 0xffffffff; + else if (GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv)==VERSION_8881A) + *u4bMask = 0x7f7f7f7f; + + b3 = get_digit_dot(&line_head); + if (b3 == NULL) + return 0; + + b2 = get_digit_dot(&b3); + if (b2 == NULL) + return 0; + + b1 = get_digit_dot(&b2); + if (b1 == NULL) + return 0; + + b0 = get_digit_dot(&b1); + if (b0 == NULL) + return 0; + + base = 10; + idx = 0; + +#if 1 + tmp_byte[3] = _convert_2_pwr_dot(b3, base); + tmp_byte[2] = _convert_2_pwr_dot(b2, base); + tmp_byte[1] = _convert_2_pwr_dot(b1, base); + tmp_byte[0] = _convert_2_pwr_dot(b0, base); +#else + tmp_byte[3] = _atoi(b3, base); + tmp_byte[2] = _atoi(b2, base); + tmp_byte[1] = _atoi(b1, base); + tmp_byte[0] = _atoi(b0, base); +#endif + + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) //CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv) == VERSION_8192E) + *u4bRegValue = generate_u4bRegValue_88e_new(priv, u4bRegOffset, tmp_byte); +#endif +#if defined( CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if(GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv)==VERSION_8881A) + *u4bRegValue = generate_u4bRegValue_8812_new(priv, u4bRegOffset, tmp_byte); + +#endif + +#if 0 + panic_printk("[0x%x] tmp_byte = %02d-%02d-%02d-%02d ", *u4bRegOffset, + tmp_byte[3], tmp_byte[2], tmp_byte[1], tmp_byte[0]); + + panic_printk(" [0x%08x]\n", *u4bRegValue); +#endif + + return 1; +} + + +static int get_offset_mask_val(unsigned char *line_head, unsigned int *u4bRegOffset, unsigned int *u4bMask, unsigned int *u4bRegValue) +{ + unsigned char *next, *n1; + int base, idx; + int num = 0; + unsigned char *ch; + extern int _atoi(char * s, int base); + + *u4bRegOffset = *u4bRegValue = *u4bMask = '\0'; + + ch = line_head; + while (1) { + if ((*ch == '\0') || (*ch == '\n') || (*ch == '\r')) + break; + else if (*ch == '/') { + *ch = '\0'; + break; + } else { + ch++; + } + } + + next = get_digit(&line_head); + if (next == NULL) + return num; + num++; + if ((!memcmp(line_head, "0x", 2)) || (!memcmp(line_head, "0X", 2))) { + base = 16; + idx = 2; + } else { + base = 10; + idx = 0; + } + *u4bRegOffset = _atoi((char *)&line_head[idx], base); + + if (next) { + n1 = get_digit(&next); + if (n1 == NULL) + return num; + num++; + if ((!memcmp(next, "0x", 2)) || (!memcmp(next, "0X", 2))) { + base = 16; + idx = 2; + } else { + base = 10; + idx = 0; + } + *u4bMask = _atoi((char *)&next[idx], base); + + if (n1) { + if (!get_digit(&n1)) + return num; + num++; + if ((!memcmp(n1, "0x", 2)) || (!memcmp(n1, "0X", 2))) { + base = 16; + idx = 2; + } else { + base = 10; + idx = 0; + } + *u4bRegValue = _atoi((char *)&n1[idx], base); + } else + *u4bRegValue = 0; + } else + *u4bMask = 0; + + return num; +} + + +unsigned char *get_line(unsigned char **line) +{ + unsigned char *p = *line; + + while (*p && ((*p == '\n') || (*p == '\r'))) + p++; + + if (*p == '\0') { + *line = NULL; + return NULL; + } + *line = p; + + while (*p && (*p != '\n') && (*p != '\r')) + p++; + + *p = '\0'; + return p + 1; +} + +int ch2idx(int ch) +{ + int val = -1; + // |1~14|36, 38, 40, ..., 64|100, 102, ..., 140|149, 151, ..., 165| + if (ch <= 14) + val = ch - 1; + else if (ch <= 64) + val = ((ch - 36) >> 1) + 14; + else if (ch <= 140) + val = ((ch - 100) >> 1) + 29; + else if (ch <= 165) + val = ((ch - 149) >> 1) + 50; + + return val; +} + +#ifdef TXPWR_LMT +#ifdef TXPWR_LMT_NEWFILE +void find_pwr_limit_new(struct rtl8192cd_priv *priv, int channel, int offset) +{ + int chidx_20 = 0, chidx_40 = 0, chidx_80 = 0; + int working_channel_40m = 0; + int working_channel_80m = get_center_channel(priv, channel, offset,1); + + working_channel_40m = (priv->pshare->CurrentChannelBW ? ((offset==1) ? (channel-2) : (channel+2)) : channel); + + chidx_20 = ch2idx(channel); + chidx_40 = ch2idx(working_channel_40m); + chidx_80 = ch2idx(working_channel_80m); + +#if 0 + panic_printk("[BW%dM]: central channel %d %d %d ==> index %d %d %d:\n", + 20*(1 << priv->pshare->CurrentChannelBW), + channel, working_channel_40m, working_channel_80m, + chidx_20, chidx_40, chidx_80); +#endif + + if ((chidx_20>=0) && (chidx_40>=0) && (chidx_80>=0)) { + priv->pshare->txpwr_lmt_CCK = priv->pshare->ch_pwr_lmtCCK[chidx_20]; + priv->pshare->txpwr_lmt_OFDM = priv->pshare->ch_pwr_lmtOFDM[chidx_20]; + + if (priv->pshare->CurrentChannelBW == 2){ //BW=80M + priv->pshare->txpwr_lmt_HT1S = priv->pshare->ch_pwr_lmtHT40_1S[chidx_40]; + priv->pshare->txpwr_lmt_HT2S = priv->pshare->ch_pwr_lmtHT40_2S[chidx_40]; + priv->pshare->txpwr_lmt_VHT1S = priv->pshare->ch_pwr_lmtVHT80_1S[chidx_80]; + priv->pshare->txpwr_lmt_VHT2S = priv->pshare->ch_pwr_lmtVHT80_2S[chidx_80]; + } else if (priv->pshare->CurrentChannelBW == 1){ //BW=40M + priv->pshare->txpwr_lmt_HT1S = priv->pshare->ch_pwr_lmtHT40_1S[chidx_40]; + priv->pshare->txpwr_lmt_HT2S = priv->pshare->ch_pwr_lmtHT40_2S[chidx_40]; + priv->pshare->txpwr_lmt_VHT1S = priv->pshare->ch_pwr_lmtHT40_1S[chidx_40]; + priv->pshare->txpwr_lmt_VHT2S = priv->pshare->ch_pwr_lmtHT40_2S[chidx_40]; + } else { //BW=20M + priv->pshare->txpwr_lmt_HT1S = priv->pshare->ch_pwr_lmtHT20_1S[chidx_20]; + priv->pshare->txpwr_lmt_HT2S = priv->pshare->ch_pwr_lmtHT20_2S[chidx_20]; + priv->pshare->txpwr_lmt_VHT1S = priv->pshare->ch_pwr_lmtHT20_1S[chidx_20]; + priv->pshare->txpwr_lmt_VHT2S = priv->pshare->ch_pwr_lmtHT20_2S[chidx_20]; + } + + if (priv->pmib->dot11RFEntry.tx2path && !priv->pshare->rf_ft_var.disable_txpwrlmt2path) { + if (priv->pshare->txpwr_lmt_CCK) + priv->pshare->txpwr_lmt_CCK -= 6; + if (priv->pshare->txpwr_lmt_OFDM) + priv->pshare->txpwr_lmt_OFDM -= 6; + if (priv->pshare->txpwr_lmt_HT1S) + priv->pshare->txpwr_lmt_HT1S -= 6; + if (priv->pshare->txpwr_lmt_VHT1S) + priv->pshare->txpwr_lmt_VHT1S -= 6; + } + } else { + priv->pshare->txpwr_lmt_CCK = 0; + priv->pshare->txpwr_lmt_OFDM = 0; + priv->pshare->txpwr_lmt_HT1S = 0; + priv->pshare->txpwr_lmt_HT2S = 0; + priv->pshare->txpwr_lmt_VHT1S = 0; + priv->pshare->txpwr_lmt_VHT2S = 0; + DEBUG_INFO("Cannot map current working channel to find power limit!\n"); + } + +} + +#endif + +void find_pwr_limit(struct rtl8192cd_priv *priv, int channel, int offset) +{ + int chidx_20 = 0, chidx_40 = 0; + int working_channel_40m = get_center_channel(priv, channel, offset,1); + + chidx_20 = ch2idx(channel); + chidx_40 = ch2idx(working_channel_40m); + +#if 0 + panic_printk("[BW%dM]: central channel[ %d %d ]==> index[ %d %d %d ]\n", + 20*(1 << priv->pshare->CurrentChannelBW), + channel, working_channel_40m, + chidx_20, chidx_40); +#endif + + if ((chidx_20 >= 0) && (chidx_40 >= 0)) { + priv->pshare->txpwr_lmt_CCK = priv->pshare->ch_pwr_lmtCCK[chidx_20]; + priv->pshare->txpwr_lmt_OFDM = priv->pshare->ch_pwr_lmtOFDM[chidx_20]; + priv->pshare->tgpwr_CCK = priv->pshare->ch_tgpwr_CCK[chidx_20]; + priv->pshare->tgpwr_OFDM = priv->pshare->ch_tgpwr_OFDM[chidx_20]; + + if (priv->pshare->CurrentChannelBW) { + priv->pshare->txpwr_lmt_HT1S = priv->pshare->ch_pwr_lmtHT40_1S[chidx_40]; + priv->pshare->txpwr_lmt_HT2S = priv->pshare->ch_pwr_lmtHT40_2S[chidx_40]; + priv->pshare->tgpwr_HT1S = priv->pshare->ch_tgpwr_HT40_1S[chidx_40]; + priv->pshare->tgpwr_HT2S = priv->pshare->ch_tgpwr_HT40_2S[chidx_40]; + } else { //if 20M bw, tmp == tmp2 ?? + priv->pshare->txpwr_lmt_HT1S = priv->pshare->ch_pwr_lmtHT20_1S[chidx_20]; + priv->pshare->txpwr_lmt_HT2S = priv->pshare->ch_pwr_lmtHT20_2S[chidx_20]; + priv->pshare->tgpwr_HT1S = priv->pshare->ch_tgpwr_HT20_1S[chidx_20]; + priv->pshare->tgpwr_HT2S = priv->pshare->ch_tgpwr_HT20_2S[chidx_20]; + } + } else { + priv->pshare->txpwr_lmt_CCK = 0; + priv->pshare->txpwr_lmt_OFDM = 0; + priv->pshare->txpwr_lmt_HT1S = 0; + priv->pshare->txpwr_lmt_HT2S = 0; + + printk("Cannot map current working channel to find power limit!\n"); + } + + //printk("txpwr_lmt_OFDM %d tgpwr_OFDM %d\n", priv->pshare->txpwr_lmt_OFDM, priv->pshare->tgpwr_OFDM); + +} + +#ifdef TXPWR_LMT_NEWFILE +#define LMT_TABLE_NUM 13 + +#define BAND2G_20M_1T_CCK 1 +#define BAND2G_20M_1T_OFDM 2 +#define BAND2G_20M_1T_HT 3 +#define BAND2G_20M_2T_HT 4 +#define BAND2G_40M_1T_HT 5 +#define BAND2G_40M_2T_HT 6 + +#define BAND5G_20M_1T_OFDM 7 +#define BAND5G_20M_1T_HT 8 +#define BAND5G_20M_2T_HT 9 +#define BAND5G_40M_1T_HT 10 +#define BAND5G_40M_2T_HT 11 +#define BAND5G_80M_1T_VHT 12 +#define BAND5G_80M_2T_VHT 13 + +int PHY_ConfigTXLmtWithParaFile_new(struct rtl8192cd_priv *priv) +{ + int read_bytes, found, num, len=0; + unsigned int channel, limit, table_idx = 0; + unsigned char *mem_ptr, *line_head, *next_head; + int tbl_idx[13], set_en=0, type=-1; + struct TxPwrLmtTable_new *reg_table; + + unsigned int tmp =0; + + priv->pshare->txpwr_lmt_CCK = 0; + priv->pshare->txpwr_lmt_OFDM = 0; + priv->pshare->txpwr_lmt_HT1S = 0; + priv->pshare->txpwr_lmt_HT2S = 0; + priv->pshare->txpwr_lmt_VHT1S = 0; + priv->pshare->txpwr_lmt_VHT2S = 0; + + reg_table = (struct TxPwrLmtTable *)priv->pshare->txpwr_lmt_buf; + + if((mem_ptr = (unsigned char *)rtw_vmalloc(MAX_CONFIG_FILE_SIZE)) == NULL) { + printk("PHY_ConfigMACWithParaFile(): not enough memory\n"); + return -1; + } + + DEBUG_INFO("regdomain=%d\n",priv->pmib->dot11StationConfigEntry.dot11RegDomain); + + memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE); // clear memory + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8812E){ + panic_printk("[TXPWR_LMT_8812_new]\n"); + next_head = data_TXPWR_LMT_8812_new_start; + read_bytes = (int)(data_TXPWR_LMT_8812_new_end - data_TXPWR_LMT_8812_new_start); + } + else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8188E){ + panic_printk("[TXPWR_LMT_88E_new]\n"); + next_head = data_TXPWR_LMT_88E_new_start; + read_bytes = (int)(data_TXPWR_LMT_88E_new_end - data_TXPWR_LMT_88E_new_start); + } + else +#endif +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv) ) { +#ifdef PWR_BY_RATE_92E_HP +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa && GET_CHIP_VER(priv) == VERSION_8192E) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERLIMITFILE_HP_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERLIMITFILE_HP_START, (pu1Byte)&next_head); + } else +#endif +#endif + { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERLIMITFILE_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERLIMITFILE_START, (pu1Byte)&next_head); + } + } else +#endif + { + printk("This WiFi IC not support Tx Power limit !!\n"); + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + return -1; + } + + memcpy(mem_ptr, next_head, read_bytes); + + next_head = mem_ptr; + while (1) { + line_head = next_head; + next_head = get_line(&line_head); + + if (line_head == NULL) + break; + + if ((line_head[0] == '/') && (line_head[2] != 'T')) + continue; + + found = get_chnl_lmt_dot_new(priv, line_head, &channel, &limit, &table_idx); + + if (found > 0) { + reg_table[len].channel = channel; + reg_table[len].limit = limit; + reg_table[len].table_idx = table_idx; + + len++; + if ((len * sizeof(struct TxPwrLmtTable_new)) > MAC_REG_SIZE) + break; + } + } + + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + + if ((len * sizeof(struct TxPwrLmtTable_new)) > MAC_REG_SIZE) { + printk("TXPWR_LMT table buffer not large enough!\n"); + return -1; + } + + num = 0; + + memset(priv->pshare->ch_pwr_lmtOFDM, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_pwr_lmtHT20_1S, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_pwr_lmtHT20_2S, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_pwr_lmtHT40_1S, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_pwr_lmtHT40_2S, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_pwr_lmtVHT80_1S, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_pwr_lmtVHT80_2S, 0, SUPPORT_CH_NUM); + + while (1) { + channel = reg_table[num].channel; + limit = reg_table[num].limit; + table_idx = reg_table[num].table_idx; + + if(channel > 0) + { + //printk(">> [%02d]-%03d-%02d\n", table_idx, channel , limit); + + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) + if ((table_idx >= BAND2G_20M_1T_CCK) && (table_idx <= BAND2G_40M_2T_HT)){ + + int j = ch2idx(channel); + + if (table_idx == BAND2G_20M_1T_CCK){ + priv->pshare->ch_pwr_lmtCCK[j] = limit; + }else if (table_idx == BAND2G_20M_1T_OFDM){ + priv->pshare->ch_pwr_lmtOFDM[j] = limit; + }else if (table_idx == BAND2G_20M_1T_HT){ + priv->pshare->ch_pwr_lmtHT20_1S[j] = limit; + }else if (table_idx == BAND2G_20M_2T_HT){ + priv->pshare->ch_pwr_lmtHT20_2S[j] = limit; + }else if (table_idx == BAND2G_40M_1T_HT){ + priv->pshare->ch_pwr_lmtHT40_1S[j] = limit; + }else if (table_idx == BAND2G_40M_2T_HT){ + priv->pshare->ch_pwr_lmtHT40_2S[j] = limit; + } + } + + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + if ( (table_idx >= BAND5G_20M_1T_OFDM) && (table_idx <= BAND5G_80M_2T_VHT)){ + + int j = ch2idx(channel); + + if (table_idx == BAND5G_20M_1T_OFDM){ + priv->pshare->ch_pwr_lmtOFDM[j] = limit; + }else if (table_idx == BAND5G_20M_1T_HT){ + priv->pshare->ch_pwr_lmtHT20_1S[j] = limit; + }else if (table_idx == BAND5G_20M_2T_HT){ + priv->pshare->ch_pwr_lmtHT20_2S[j] = limit; + }else if (table_idx == BAND5G_40M_1T_HT){ + priv->pshare->ch_pwr_lmtHT40_1S[j] = limit; + }else if (table_idx == BAND5G_40M_2T_HT){ + priv->pshare->ch_pwr_lmtHT40_2S[j] = limit; + }else if (table_idx == BAND5G_80M_1T_VHT){ + priv->pshare->ch_pwr_lmtVHT80_1S[j] = limit; + }else if (table_idx == BAND5G_80M_2T_VHT){ + priv->pshare->ch_pwr_lmtVHT80_2S[j] = limit; + } + } + + } + + num++; + + if(num >= len) + break; + + } + + return 0; +} + +#endif + +int PHY_ConfigTXLmtWithParaFile(struct rtl8192cd_priv *priv) +{ + int read_bytes, num, len = 0; + unsigned int ch_start, ch_end, limit, target = 0; + unsigned char *mem_ptr, *line_head, *next_head; + int tbl_idx[6], set_en = 0, type = -1; + struct TxPwrLmtTable *reg_table; + + priv->pshare->txpwr_lmt_CCK = 0; + priv->pshare->txpwr_lmt_OFDM = 0; + priv->pshare->txpwr_lmt_HT1S = 0; + priv->pshare->txpwr_lmt_HT2S = 0; + + reg_table = (struct TxPwrLmtTable *)priv->pshare->txpwr_lmt_buf; + + if ((GET_CHIP_VER(priv) != VERSION_8192D) && (GET_CHIP_VER(priv) != VERSION_8192C) && (GET_CHIP_VER(priv) != VERSION_8188C)) { + printk("[%s]NOT support! TXPWR_LMT is for RTL8192D & 92C/88C ONLY!\n", __FUNCTION__); + return -1; + } + + if ((mem_ptr = (unsigned char *)rtw_vmalloc(MAX_CONFIG_FILE_SIZE)) == NULL) { + printk("PHY_ConfigTXLmtWithParaFile(): not enough memory\n"); + return -1; + } + + + tbl_idx[0] = 1; + tbl_idx[1] = 2; + tbl_idx[2] = 3; + tbl_idx[3] = 4; + tbl_idx[4] = 5; + tbl_idx[5] = 6; + + + DEBUG_INFO("regdomain=%d tbl_idx=%d,%d\n", priv->pmib->dot11StationConfigEntry.dot11RegDomain, tbl_idx[0], tbl_idx[1]); + + + memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE); // clear memory + + printk("[%s][TXPWR_LMT]\n", __FUNCTION__); + + +#ifdef CONFIG_RTL_92C_SUPPORT + if((GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C)) + { + int txpwr_lmt_index; + + if(priv->pmib->dot11StationConfigEntry.txpwr_lmt_index <= 0) { + // if mib txpwr_lmt_index is default value + if(priv->pmib->dot11StationConfigEntry.dot11RegDomain==DOMAIN_FCC) + txpwr_lmt_index = 1; + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain==DOMAIN_ETSI) + txpwr_lmt_index = 2; + else + txpwr_lmt_index = TXPWR_LMT_92c_MAX + 1; + } + else { + txpwr_lmt_index = priv->pmib->dot11StationConfigEntry.txpwr_lmt_index; + } + + if(txpwr_lmt_index <= TXPWR_LMT_92c_MAX && + data_TXPWR_LMT_92c_array[txpwr_lmt_index]) + { + + next_head = data_TXPWR_LMT_92c_array[txpwr_lmt_index]; + read_bytes = data_TXPWR_LMT_92c_array_end[txpwr_lmt_index] - data_TXPWR_LMT_92c_array[txpwr_lmt_index]; + } + else + { + // When compiling error is "undefine data_TXPWR_LMT_92c" + // Please check if the file,rtl8192cd/data/TXPWR_LMT_92c.txt, exits. + next_head = data_TXPWR_LMT_92c; + read_bytes = (int)sizeof(data_TXPWR_LMT_92c); + } + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if(GET_CHIP_VER(priv)==VERSION_8192D) + { + + int txpwr_lmt_index; + + if(priv->pmib->dot11StationConfigEntry.txpwr_lmt_index <= 0) { + // if mib txpwr_lmt_index is default value + if(priv->pmib->dot11StationConfigEntry.dot11RegDomain==DOMAIN_FCC) + txpwr_lmt_index = 1; + else if(priv->pmib->dot11StationConfigEntry.dot11RegDomain==DOMAIN_ETSI) + txpwr_lmt_index = 2; + else + txpwr_lmt_index = TXPWR_LMT_92d_MAX + 1; + } + else { + txpwr_lmt_index = priv->pmib->dot11StationConfigEntry.txpwr_lmt_index; + } + + if(txpwr_lmt_index <= TXPWR_LMT_92d_MAX && + data_TXPWR_LMT_92d_array[txpwr_lmt_index]) + { + + next_head = data_TXPWR_LMT_92d_array[txpwr_lmt_index]; + read_bytes = data_TXPWR_LMT_92d_array_end[txpwr_lmt_index] - + data_TXPWR_LMT_92d_array[txpwr_lmt_index]; + } else + { + // Note: default TX Power Limit + // When compiling error is "undefine data_TXPWR_LMT_92d" + // Please check if the file,rtl8192cd/data/TXPWR_LMT_92d.txt, exits. + next_head = data_TXPWR_LMT_92d; + read_bytes = (int)sizeof(data_TXPWR_LMT_92d); + } + } +#endif + + memcpy(mem_ptr, next_head, read_bytes); + + next_head = mem_ptr; + while (1) { + line_head = next_head; + next_head = get_line(&line_head); + + if (line_head == NULL) + break; + + if (line_head[0] == '/') + continue; + + num = get_chnl_lmt_dot(line_head, &ch_start, &ch_end, &limit, &target); + + if (num > 0) { + reg_table[len].start = ch_start; + reg_table[len].end = ch_end; + reg_table[len].limit = limit; + reg_table[len].target = target; + + len++; + if ((len * sizeof(struct TxPwrLmtTable)) > MAC_REG_SIZE) + break; + } + } + + reg_table[len].start = 0xff; + + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + + if ((len * sizeof(struct TxPwrLmtTable)) > MAC_REG_SIZE) { + printk("TXPWR_LMT table buffer not large enough!\n"); + return -1; + } + + num = 0; + while (1) { + ch_start = reg_table[num].start; + ch_end = reg_table[num].end; + limit = reg_table[num].limit; + target = reg_table[num].target; + + //printk(">> %d-%d-%d-%d\n",ch_start,ch_end,limit,target); + if (ch_start == 0xff) + break; + + if (ch_start == 0 && ch_end == 0) { + if (limit == tbl_idx[0]) { + set_en = 1; + type = 0; + memset(priv->pshare->ch_pwr_lmtCCK, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_tgpwr_CCK, 0, SUPPORT_CH_NUM); + } else if (limit == tbl_idx[1]) { + set_en = 1; + type = 1; + memset(priv->pshare->ch_pwr_lmtOFDM, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_tgpwr_OFDM, 0, SUPPORT_CH_NUM); + } else if (limit == tbl_idx[2]) { + set_en = 1; + type = 2; + memset(priv->pshare->ch_pwr_lmtHT20_1S, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_tgpwr_HT20_1S, 0, SUPPORT_CH_NUM); + } else if (limit == tbl_idx[3]) { + set_en = 1; + type = 3; + memset(priv->pshare->ch_pwr_lmtHT20_2S, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_tgpwr_HT20_2S, 0, SUPPORT_CH_NUM); + } else if (limit == tbl_idx[4]) { + set_en = 1; + type = 4; + memset(priv->pshare->ch_pwr_lmtHT40_1S, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_tgpwr_HT40_1S, 0, SUPPORT_CH_NUM); + } else if (limit == tbl_idx[5]) { + set_en = 1; + type = 5; + memset(priv->pshare->ch_pwr_lmtHT40_2S, 0, SUPPORT_CH_NUM); + memset(priv->pshare->ch_tgpwr_HT40_2S, 0, SUPPORT_CH_NUM); + } else { + set_en = 0; + } + } + + if (set_en && ch_start) { + int j; + for (j = ch2idx(ch_start); j <= ch2idx(ch_end); j++) { + if (j < 0 || j >= SUPPORT_CH_NUM) { + panic_printk("channel out of bound!!\n"); + break; + } + + if (type == 0) { + priv->pshare->ch_pwr_lmtCCK[j] = limit; + priv->pshare->ch_tgpwr_CCK[j] = target; + } else if (type == 1) { + priv->pshare->ch_pwr_lmtOFDM[j] = limit; + priv->pshare->ch_tgpwr_OFDM[j] = target; + } else if (type == 2) { + priv->pshare->ch_pwr_lmtHT20_1S[j] = limit; + priv->pshare->ch_tgpwr_HT20_1S[j] = target; + } else if (type == 3) { + priv->pshare->ch_pwr_lmtHT20_2S[j] = limit; + priv->pshare->ch_tgpwr_HT20_2S[j] = target; + } else if (type == 4) { + priv->pshare->ch_pwr_lmtHT40_1S[j] = limit; + priv->pshare->ch_tgpwr_HT40_1S[j] = target; + } else if (type == 5) { + priv->pshare->ch_pwr_lmtHT40_2S[j] = limit; + priv->pshare->ch_tgpwr_HT40_2S[j] = target; + } + } + } + + num++; + } + + return 0; +} + +#endif + + +#ifdef _TRACKING_TABLE_FILE + +static char TXPWR_TRACKING_NAME[][32] = { + "2GCCKA_P", + "2GCCKA_N", + "2GCCKB_P", + "2GCCKB_N", + "2GA_P", + "2GA_N", + "2GB_P", + "2GB_N", + "5GLA_P", + "5GLA_N", + "5GLB_P", + "5GLB_N", + "5GMA_P", + "5GMA_N", + "5GMB_P", + "5GMB_N", + "5GHA_P", + "5GHA_N", + "5GHB_P", + "5GHB_N", +}; + +#if 1// not used +static char TXPWR_TRACKING_NAME_NEW[][32] = { + "[2G][A][+][CCK]", + "[2G][A][-][CCK]", + "[2G][B][+][CCK]", + "[2G][B][-][CCK]", + "[2G][A][+][ALL]", + "[2G][A][-][ALL]", + "[2G][B][+][ALL]", + "[2G][B][-][ALL]", + "[5G][A][+][ALL][0]", + "[5G][A][-][ALL][0]", + "[5G][B][+][ALL][0]", + "[5G][B][-][ALL][0]", + "[5G][A][+][ALL][1]", + "[5G][A][-][ALL][1]", + "[5G][B][+][ALL][1]", + "[5G][B][-][ALL][1]", + "[5G][A][+][ALL][2]", + "[5G][A][-][ALL][2]", + "[5G][B][+][ALL][2]", + "[5G][B][-][ALL][2]", +}; +#endif + +//#ifndef TXPWR_LMT + +int _convert_2_pwr_tracking(char *s, int base) +{ + int k = 0; + + k = 0; + if (base == 10) { + while (*s >= '0' && *s <= '9') { + k = 10 * k + (*s - '0'); + s++; + } + } else + return 0; + + return k; +} + + +static unsigned char *get_digit_tracking(unsigned char **data) +{ + unsigned char *buf = *data; + int i = 0; + + *data = &buf[i]; + + while (buf[i]) { + if ((buf[i] == '\n') || (buf[i] == '\r')) { + return NULL; + } + + if ((buf[i] == ' ') || (buf[i] == '\t')) + break; + + i++; + } + + while (buf[i]) { + + if ((buf[i] == '\n') || (buf[i] == '\r')) { + return NULL; + } + + if ((buf[i] >= '0') && (buf[i] <= '9')) { + //printk("found buf[i] = %c \n", buf[i]); + return &buf[i]; + } + + i++; + } + + return NULL; +} + +//#endif + + +void input_tracking_value(struct rtl8192cd_priv *priv, int offset, int num, int value) +{ + + switch (offset) { + case CCKA_P: + case CCKA_N: + case CCKB_P: + case CCKB_N: + offset = (offset % 4); + priv->pshare->txpwr_tracking_2G_CCK[offset][num] = value; + break; + case A_P: + case A_N: + case B_P: + case B_N: + offset = (offset % 4); + priv->pshare->txpwr_tracking_2G_OFDM[offset][num] = value; + break; + case LA_P: + case LA_N: + case LB_P: + case LB_N: + offset = (offset % 4); + priv->pshare->txpwr_tracking_5GL[offset][num] = value; + //printk("txpwr_tracking_5GL[%d][%d]=%d\n", offset, num,value); + break; + case MA_P: + case MA_N: + case MB_P: + case MB_N: + offset = (offset % 4); + priv->pshare->txpwr_tracking_5GM[offset][num] = value; + //printk("txpwr_tracking_5GM[%d][%d]=%d\n", offset, num,value); + break; + case HA_P: + case HA_N: + case HB_P: + case HB_N: + offset = (offset % 4); + priv->pshare->txpwr_tracking_5GH[offset][num] = value; + //printk("txpwr_tracking_5GH[%d][%d]=%d\n", offset, num,value); + break; + default: + break; + + } + + +} + + +int get_tx_tracking_index(struct rtl8192cd_priv *priv, int channel, int i, int delta, int is_decrease, int is_CCK) +{ + int index = 0; + + if (delta == 0) + return 0; + + if (delta > index_mapping_NUM_MAX) + delta = index_mapping_NUM_MAX; + + //printk("\n_eric_tracking +++ channel = %d, i = %d, delta = %d, is_decrease = %d, is_CCK = %d\n", channel, i, delta, is_decrease, is_CCK); + + if (!priv->pshare->tracking_table_new) + delta = delta - 1; + + if (channel > 14) { + if (channel <= 99) { + index = priv->pshare->txpwr_tracking_5GL[(i * 2) + is_decrease][delta]; + } else if (channel <= 140) { + + index = priv->pshare->txpwr_tracking_5GM[(i * 2) + is_decrease][delta]; + } else { + index = priv->pshare->txpwr_tracking_5GH[(i * 2) + is_decrease][delta]; + } + } else { + if (is_CCK) { + index = priv->pshare->txpwr_tracking_2G_CCK[(i * 2) + is_decrease][delta]; + } else { + index = priv->pshare->txpwr_tracking_2G_OFDM[(i * 2) + is_decrease][delta]; + } + } + + //printk("_eric_tracking +++ offset = %d\n", index); + + return index; + +} + +static int get_tracking_table(struct rtl8192cd_priv *priv, unsigned char *line_head) +{ + unsigned char *next; + int base, idx; + int num = 0; + int offset = 0; + unsigned char *swim; + extern int _atoi(char * s, int base); + + // remove comments + swim = line_head + 1; + priv->pshare->tracking_table_new = 0; + + for (offset = 0; offset < TXPWR_TRACKING_NAME_NUM; offset++) { + if (!memcmp(line_head, TXPWR_TRACKING_NAME[offset], strlen(TXPWR_TRACKING_NAME[offset]))) + break; + } + + if (offset >= TXPWR_TRACKING_NAME_NUM) { + for (offset = 0; offset < TXPWR_TRACKING_NAME_NUM; offset++) { + if (!memcmp(line_head, TXPWR_TRACKING_NAME_NEW[offset], strlen(TXPWR_TRACKING_NAME_NEW[offset]))) + break; + } + + if (offset >= TXPWR_TRACKING_NAME_NUM) + return offset; + + priv->pshare->tracking_table_new = 1; + } + + if (offset >= TXPWR_TRACKING_NAME_NUM) + return offset; + + //printk("_Eric offset = %d \n", offset); + //printk("_Eric line_head = %s \n", line_head); + + next = get_digit_tracking(&swim); + + while (1) { + + if (next == NULL) + break; + + if (next) { + + base = 10; + idx = 0; + + //printk("num#%d = %d \n", num, _convert_2_pwr_tracking((char *)&next[idx], base)); + input_tracking_value(priv, offset, num, _convert_2_pwr_tracking((char *)&next[idx], base)); + + num++; + } else + break; + + if (num >= index_mapping_NUM_MAX) + break; + + next = get_digit_tracking(&next); + + } + + + return offset; + +} + + +void check_tracking_table(struct rtl8192cd_priv *priv) +{ + + int tmp = 0; + int tmp2 = 0; + + for (tmp = 0; tmp < 4; tmp++) { + for (tmp2 = 1; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + if (priv->pshare->txpwr_tracking_2G_CCK[tmp][tmp2] < priv->pshare->txpwr_tracking_2G_CCK[tmp][tmp2 - 1]) + priv->pshare->txpwr_tracking_2G_CCK[tmp][tmp2] = priv->pshare->txpwr_tracking_2G_CCK[tmp][tmp2 - 1]; + } + } + + for (tmp = 0; tmp < 4; tmp++) { + for (tmp2 = 1; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + if (priv->pshare->txpwr_tracking_2G_OFDM[tmp][tmp2] < priv->pshare->txpwr_tracking_2G_OFDM[tmp][tmp2 - 1]) + priv->pshare->txpwr_tracking_2G_OFDM[tmp][tmp2] = priv->pshare->txpwr_tracking_2G_OFDM[tmp][tmp2 - 1]; + } + } + + for (tmp = 0; tmp < 4; tmp++) { + for (tmp2 = 1; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + if (priv->pshare->txpwr_tracking_5GL[tmp][tmp2] < priv->pshare->txpwr_tracking_5GL[tmp][tmp2 - 1]) + priv->pshare->txpwr_tracking_5GL[tmp][tmp2] = priv->pshare->txpwr_tracking_5GL[tmp][tmp2 - 1]; + } + } + + for (tmp = 0; tmp < 4; tmp++) { + for (tmp2 = 1; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + if (priv->pshare->txpwr_tracking_5GM[tmp][tmp2] < priv->pshare->txpwr_tracking_5GM[tmp][tmp2 - 1]) + priv->pshare->txpwr_tracking_5GM[tmp][tmp2] = priv->pshare->txpwr_tracking_5GM[tmp][tmp2 - 1]; + } + } + + for (tmp = 0; tmp < 4; tmp++) { + for (tmp2 = 1; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + if (priv->pshare->txpwr_tracking_5GH[tmp][tmp2] < priv->pshare->txpwr_tracking_5GH[tmp][tmp2 - 1]) + priv->pshare->txpwr_tracking_5GH[tmp][tmp2] = priv->pshare->txpwr_tracking_5GH[tmp][tmp2 - 1]; + } + } + +} + +int PHY_ConfigTXPwrTrackingWithParaFile(struct rtl8192cd_priv *priv) +{ + int read_bytes, num; + unsigned char *mem_ptr, *line_head, *next_head; + + memset(priv->pshare->txpwr_tracking_2G_CCK, 0, (4 * index_mapping_NUM_MAX)); + memset(priv->pshare->txpwr_tracking_2G_OFDM, 0, (4 * index_mapping_NUM_MAX)); + memset(priv->pshare->txpwr_tracking_5GL, 0, (4 * index_mapping_NUM_MAX)); + memset(priv->pshare->txpwr_tracking_5GM, 0, (4 * index_mapping_NUM_MAX)); + memset(priv->pshare->txpwr_tracking_5GH, 0, (4 * index_mapping_NUM_MAX)); + + if ((mem_ptr = (unsigned char *)rtw_vmalloc(MAX_CONFIG_FILE_SIZE)) == NULL) { + printk("PHY_ConfigTXPwrTrackingWithParaFile(): not enough memory\n"); + return -1; + } + + memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE); // clear memory + + + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { //_Eric_?? any other IC types ?? +#ifdef CONFIG_RTL_92C_SUPPORT +#ifdef HIGH_POWER_EXT_PA + printk("[%s][REG_TXPWR_TRK_hp]\n", __FUNCTION__); + next_head = data_REG_TXPWR_TRK_hp_start; + read_bytes = (int)(data_REG_TXPWR_TRK_hp_end - data_REG_TXPWR_TRK_hp_start); +#else + printk("[%s][REG_TXPWR_TRK]\n", __FUNCTION__); + next_head = data_REG_TXPWR_TRK_start; + read_bytes = (int)(data_REG_TXPWR_TRK_end - data_REG_TXPWR_TRK_start); +#endif +#endif + } +#ifdef CONFIG_RTL_92D_SUPPORT + else if (GET_CHIP_VER(priv) == VERSION_8192D) { +#ifdef HIGH_POWER_EXT_PA + printk("[%s][REG_TXPWR_TRK_n_92d_hp]\n", __FUNCTION__); + next_head = data_REG_TXPWR_TRK_n_92d_hp_start; + read_bytes = (int)(data_REG_TXPWR_TRK_n_92d_hp_end - data_REG_TXPWR_TRK_n_92d_hp_start); +#else + printk("[%s][REG_TXPWR_TRK_n_92d]\n", __FUNCTION__); + next_head = data_REG_TXPWR_TRK_n_92d_start; + read_bytes = (int)(data_REG_TXPWR_TRK_n_92d_end - data_REG_TXPWR_TRK_n_92d_start); +#endif + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + else if (GET_CHIP_VER(priv) == VERSION_8812E) { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + panic_printk("[REG_TXPWR_TRK_8812_hp]\n"); + next_head = data_REG_TXPWR_TRK_8812_hp_start; + read_bytes = (int)(data_REG_TXPWR_TRK_8812_hp_end - data_REG_TXPWR_TRK_8812_hp_start); + } else +#endif + { + panic_printk("[REG_TXPWR_TRK_8812]\n"); + next_head = data_REG_TXPWR_TRK_8812_start; + read_bytes = (int)(data_REG_TXPWR_TRK_8812_end - data_REG_TXPWR_TRK_8812_start); + } + } +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + else if (GET_CHIP_VER(priv) == VERSION_8192E) { + //panic_printk("[REG_TXPWR_TRK_8192E]\n"); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERTRACKINGFILE_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERTRACKINGFILE_START, (pu1Byte)&next_head); + } +#endif +#ifdef CONFIG_WLAN_HAL_8881A + else if (GET_CHIP_VER(priv) == VERSION_8881A) { + //panic_printk("[REG_TXPWR_TRK_8881A]\n"); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERTRACKINGFILE_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERTRACKINGFILE_START, (pu1Byte)&next_head); + } +#endif +#ifdef CONFIG_WLAN_HAL_8814AE + else if (GET_CHIP_VER(priv) == VERSION_8814A) { + //printk("[%s][REG_TXPWR_TRK_8814A]\n", __FUNCTION__); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERTRACKINGFILE_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_POWERTRACKINGFILE_START, (pu1Byte)&next_head); + } +#endif + else { + //printk("[%s][NOT SUPPORT]\n", __FUNCTION__); + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + return -1; + } + + memcpy(mem_ptr, next_head, read_bytes); + + next_head = mem_ptr; + + while (1) { + line_head = next_head; + next_head = get_line(&line_head); + + if (line_head == NULL) + break; + + if (line_head[0] == '/') + continue; + + num = get_tracking_table(priv, line_head); + + } + + check_tracking_table(priv); + +#if 0 + + { + int tmp = 0; + int tmp2 = 0; + + for (tmp = 0; tmp < 4; tmp++) { + printk("txpwr_tracking_2G_CCK #%d = ", tmp); + for (tmp2 = 0; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + printk("%d ", priv->pshare->txpwr_tracking_2G_CCK[tmp][tmp2]); + } + printk("\n"); + } + + for (tmp = 0; tmp < 4; tmp++) { + printk("txpwr_tracking_2G_OFDM #%d = ", tmp); + for (tmp2 = 0; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + printk("%d ", priv->pshare->txpwr_tracking_2G_OFDM[tmp][tmp2]); + } + printk("\n"); + } + + for (tmp = 0; tmp < 4; tmp++) { + printk("txpwr_tracking_5GL #%d = ", tmp); + for (tmp2 = 0; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + printk("%d ", priv->pshare->txpwr_tracking_5GL[tmp][tmp2]); + } + printk("\n"); + } + + for (tmp = 0; tmp < 4; tmp++) { + printk("txpwr_tracking_5GM #%d = ", tmp); + for (tmp2 = 0; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + printk("%d ", priv->pshare->txpwr_tracking_5GM[tmp][tmp2]); + } + printk("\n"); + } + + for (tmp = 0; tmp < 4; tmp++) { + printk("txpwr_tracking_5GH #%d = ", tmp); + for (tmp2 = 0; tmp2 < index_mapping_NUM_MAX; tmp2 ++) { + printk("%d ", priv->pshare->txpwr_tracking_5GH[tmp][tmp2]); + } + printk("\n"); + } + + } + +#endif + + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + + return 0; +} +#endif + +void TXPowerTracking(struct rtl8192cd_priv *priv) +{ + if (priv->up_time % priv->pshare->rf_ft_var.tpt_period == 0) { +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if (!IS_OUTSRC_CHIP(priv)) +#endif + { +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C)) + tx_power_tracking(priv); +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) + tx_power_tracking_92D(priv); +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + odm_TXPowerTrackingCallback_ThermalMeter_8188E(priv); +#endif + } +#endif +#if defined(USE_OUT_SRC) + { + if (IS_OUTSRC_CHIP(priv)) { + #ifndef TPT_THREAD + ODM_TXPowerTrackingCheck(ODMPTR); + #else + rtl_atomic_set(&priv->pshare->do_tpt, 1); + #endif + } + } +#endif + } + else if ((priv->up_time % (priv->pshare->rf_ft_var.tpt_period)) == (priv->pshare->rf_ft_var.tpt_period -1)) + { + // It will execute the TX power tracking at next Sec, so Trigger the Thermo Meter update first. +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192C || GET_CHIP_VER(priv) == VERSION_8188C) + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_T_METER, bMask20Bits, 0x60); + else +#endif + // for 8192D, 8188E, 8192E, 8821 serious, the Thermo meter register address is 0x42 + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_T_METER_92D, BIT(16)|BIT(17), 0x3); + + //panic_printk("%s:%d trigger thermalmeter!\n", __FUNCTION__, __LINE__); + return; + } +} + +void SetTxPowerLevel(struct rtl8192cd_priv *priv) +{ + unsigned int channel = priv->pmib->dot11RFEntry.dot11channel; + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + PHY_SetOFDMTxPower_8812(priv, channel); + if (priv->pshare->curr_band == BAND_2G) + PHY_SetCCKTxPower_8812(priv, channel); + priv->pshare->No_RF_Write = 1; + + } +#endif + +#if defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + if ((GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + GET_HAL_INTERFACE(priv)->PHYSetOFDMTxPowerHandler(priv, channel); + if (priv->pshare->curr_band == BAND_2G) { + if (RT_STATUS_FAILURE == GET_HAL_INTERFACE(priv)->PHYSetCCKTxPowerHandler(priv, channel)) { + DEBUG_WARN("PHYSetCCKTxPower Fail !\n"); + } + } + priv->pshare->No_RF_Write = 1; + } +#endif //#if defined(CONFIG_WLAN_HAL_8881A) + +#if defined(CONFIG_WLAN_HAL_8192EE) + if (GET_CHIP_VER(priv) == VERSION_8192E) { + GET_HAL_INTERFACE(priv)->PHYSetOFDMTxPowerHandler(priv, channel); + if (priv->pshare->curr_band == BAND_2G) { + GET_HAL_INTERFACE(priv)->PHYSetCCKTxPowerHandler(priv, channel); + } + selectMinPowerIdex(priv); + } +#endif //#if defined(CONFIG_WLAN_HAL_8192EE) + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) + if (GET_CHIP_VER(priv) <= VERSION_8188E) { + PHY_RF6052SetOFDMTxPower(priv, channel); + if (priv->pshare->curr_band == BAND_2G) + PHY_RF6052SetCCKTxPower(priv, channel); + + selectMinPowerIdex(priv); + } +#endif + + return; +} + +#ifdef _DEBUG_RTL8192CD_ + +//_TXPWR_REDEFINE +int Read_PG_File(struct rtl8192cd_priv *priv, int reg_file, int table_number, + char *MCSTxAgcOffset_A, char *MCSTxAgcOffset_B, char *OFDMTxAgcOffset_A, + char *OFDMTxAgcOffset_B, char *CCKTxAgc_A, char *CCKTxAgc_B) +{ + int read_bytes = 0, num, len = 0; + unsigned int u4bRegOffset, u4bRegValue, u4bRegMask; + unsigned char *mem_ptr, *line_head, *next_head = NULL; + struct PhyRegTable *phyreg_table = NULL; + struct MacRegTable *macreg_table = NULL; + unsigned short max_len = 0; + int file_format = TWO_COLUMN; +#ifdef CONFIG_RTL_92D_SUPPORT + int idx = 0, pg_tbl_idx = table_number, write_en = 0; + + int tmp_rTxAGC_A_CCK1_Mcs32 = 0; + int tmp_rTxAGC_B_CCK5_1_Mcs32 = 0; + int prev_reg = 0; +#endif + + //printk("PHYREG_PG = %d\n", PHYREG_PG); + + if (reg_file == PHYREG_PG) { + //printk("[%s][PHY_REG_PG]\n",__FUNCTION__); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + + if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_FCC) { + //printk("\nFCC PG!!!\n"); + next_head = data_PHY_REG_PG_FCC_start; + read_bytes = (int)(data_PHY_REG_PG_FCC_end - data_PHY_REG_PG_FCC_start); + } else if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) { + //printk("\nCE PG!!!\n"); + next_head = data_PHY_REG_PG_CE_start; + read_bytes = (int)(data_PHY_REG_PG_CE_end - data_PHY_REG_PG_CE_start); + } else { + //printk("\nOTHER PG!!!\n"); + next_head = data_PHY_REG_PG_start; + read_bytes = (int)(data_PHY_REG_PG_end - data_PHY_REG_PG_start); + } + +#ifdef HIGH_POWER_EXT_PA + if ( priv->pshare->rf_ft_var.use_ext_pa) { + //printk("[%s][data_PHY_REG_PG_92d_hp]\n", __FUNCTION__); + next_head = data_PHY_REG_PG_92d_hp_start; + read_bytes = (int)(data_PHY_REG_PG_92d_hp_end - data_PHY_REG_PG_92d_hp_start); + } +#endif + + } +#endif //CONFIG_RTL_92D_SUPPORT + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { +#ifdef HIGH_POWER_EXT_PA + if ( priv->pshare->rf_ft_var.use_ext_pa) { + //printk("[%s][data_PHY_REG_PG_hp]\n", __FUNCTION__); + next_head = data_PHY_REG_PG_hp_start; + read_bytes = (int)(data_PHY_REG_PG_hp_end - data_PHY_REG_PG_hp_start); + + } else +#endif + { + //printk("[%s][data_PHY_REG_PG_92C]\n", __FUNCTION__); + next_head = data_PHY_REG_PG_92C_start; + read_bytes = (int)(data_PHY_REG_PG_92C_end - data_PHY_REG_PG_92C_start); + } + } +#endif //CONFIG_RTL_92C_SUPPORT + macreg_table = (struct MacRegTable *)priv->pshare->phy_reg_pg_buf; + max_len = PHY_REG_PG_SIZE; + file_format = THREE_COLUMN; + } + +#ifdef CONFIG_RTL_92D_SUPPORT + else if (reg_file == PHYREG) { + if (GET_CHIP_VER(priv) == VERSION_8192D) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_buf; + //printk("[%s][PHY_REG_n]\n",__FUNCTION__); + next_head = data_PHY_REG_n_start; + read_bytes = (int)(data_PHY_REG_n_end - data_PHY_REG_n_start); + max_len = PHY_REG_SIZE; + } + } +#endif // CONFIG_RTL_92D_SUPPORT + +#ifdef MP_TEST + else if (reg_file == PHYREG_MP) { +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_mp_buf; + //printk("[%s][PHY_REG_MP_n]\n",__FUNCTION__); + next_head = data_PHY_REG_MP_n_start; + read_bytes = (int)(data_PHY_REG_MP_n_end - data_PHY_REG_MP_n_start); + max_len = PHY_REG_SIZE; + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_mp_buf; + next_head = data_PHY_REG_MP_n_92C_start; + read_bytes = (int)(data_PHY_REG_MP_n_92C_end - data_PHY_REG_MP_n_92C_start); + max_len = PHY_REG_SIZE; + } +#endif + } +#endif + + { + if ((mem_ptr = (unsigned char *)rtw_vmalloc(MAX_CONFIG_FILE_SIZE)) == NULL) { + printk("PHY_ConfigBBWithParaFile(): not enough memory\n"); + return -1; + } + + memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE); // clear memory + memcpy(mem_ptr, next_head, read_bytes); + + next_head = mem_ptr; + while (1) { + line_head = next_head; + next_head = get_line(&line_head); + if (line_head == NULL) + break; + + if (line_head[0] == '/') + continue; + + if (file_format == TWO_COLUMN) { + num = get_offset_val(line_head, &u4bRegOffset, &u4bRegValue); + if (num > 0) { + phyreg_table[len].offset = u4bRegOffset; + phyreg_table[len].value = u4bRegValue; + len++; + + if (u4bRegOffset == 0xff) + break; + if ((len * sizeof(struct PhyRegTable)) > max_len) + break; + } + } else { + num = get_offset_mask_val(line_head, &u4bRegOffset, &u4bRegMask , &u4bRegValue); + if (num > 0) { + macreg_table[len].offset = u4bRegOffset; + macreg_table[len].mask = u4bRegMask; + macreg_table[len].value = u4bRegValue; + len++; + if (u4bRegOffset == 0xff) + break; + if ((len * sizeof(struct MacRegTable)) > max_len) + break; + } + } + } + + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + + if ((len * sizeof(struct PhyRegTable)) > max_len) { + printk("PHY REG table buffer not large enough!\n"); + return -1; + } + } + + num = 0; + while (1) { + if (file_format == THREE_COLUMN) { + u4bRegOffset = macreg_table[num].offset; + u4bRegValue = macreg_table[num].value; + u4bRegMask = macreg_table[num].mask; + } else { + u4bRegOffset = phyreg_table[num].offset; + u4bRegValue = phyreg_table[num].value; + } + + if (u4bRegOffset == 0xff) + break; + else if (file_format == THREE_COLUMN) { + +#ifdef CONFIG_RTL_92D_SUPPORT + if (reg_file == PHYREG_PG && GET_CHIP_VER(priv) == VERSION_8192D) { + if (u4bRegOffset == 0xe00) { + if (idx == pg_tbl_idx) + write_en = 1; + idx++; + } + if (write_en) { + //PHY_SetBBReg(priv, u4bRegOffset, u4bRegMask, u4bRegValue); + //printk("3C- 92D %x %x %x \n", u4bRegOffset, u4bRegMask, u4bRegValue); + if (u4bRegMask != bMaskDWord) { + int BitShift = phy_CalculateBitShift(u4bRegMask); + u4bRegValue = (u4bRegValue << BitShift); + } + + //=== PATH A === + + if (u4bRegOffset == rTxAGC_A_Mcs03_Mcs00) + *(unsigned int *)(&MCSTxAgcOffset_A[0]) = cpu_to_be32(u4bRegValue); + if (u4bRegOffset == rTxAGC_A_Mcs07_Mcs04) + *(unsigned int *)(&MCSTxAgcOffset_A[4]) = cpu_to_be32(u4bRegValue); + if (u4bRegOffset == rTxAGC_A_Mcs11_Mcs08) + *(unsigned int *)(&MCSTxAgcOffset_A[8]) = cpu_to_be32(u4bRegValue); + if (u4bRegOffset == rTxAGC_A_Mcs15_Mcs12) + *(unsigned int *)(&MCSTxAgcOffset_A[12]) = cpu_to_be32(u4bRegValue); + + if (u4bRegOffset == rTxAGC_A_Rate18_06) + *(unsigned int *)(&OFDMTxAgcOffset_A[0]) = cpu_to_be32(u4bRegValue); + if (u4bRegOffset == rTxAGC_A_Rate54_24) + *(unsigned int *)(&OFDMTxAgcOffset_A[4]) = cpu_to_be32(u4bRegValue); + + if (u4bRegOffset == rTxAGC_A_CCK1_Mcs32) { + tmp_rTxAGC_A_CCK1_Mcs32 = ((u4bRegValue & 0xff00) >> phy_CalculateBitShift(0xff00)); + prev_reg = rTxAGC_A_CCK1_Mcs32; + } + + if (u4bRegOffset == rTxAGC_A_CCK11_2_B_CCK11) { + if (prev_reg == rTxAGC_A_CCK1_Mcs32) { + //printk("\n%x %x %x\n", tmp_rTxAGC_A_CCK1_Mcs32, u4bRegValue, cpu_to_be32((u4bRegValue & 0xffffff00) | tmp_rTxAGC_A_CCK1_Mcs32)); + + *(unsigned int *)(&CCKTxAgc_A[0]) = + cpu_to_be32((u4bRegValue & 0xffffff00) | tmp_rTxAGC_A_CCK1_Mcs32); + } + } + + //=== PATH B === + + if (u4bRegOffset == rTxAGC_B_Mcs03_Mcs00) + *(unsigned int *)(&MCSTxAgcOffset_B[0]) = cpu_to_be32(u4bRegValue); + if (u4bRegOffset == rTxAGC_B_Mcs07_Mcs04) + *(unsigned int *)(&MCSTxAgcOffset_B[4]) = cpu_to_be32(u4bRegValue); + if (u4bRegOffset == rTxAGC_B_Mcs11_Mcs08) + *(unsigned int *)(&MCSTxAgcOffset_B[8]) = cpu_to_be32(u4bRegValue); + if (u4bRegOffset == rTxAGC_B_Mcs15_Mcs12) + *(unsigned int *)(&MCSTxAgcOffset_B[12]) = cpu_to_be32(u4bRegValue); + + if (u4bRegOffset == rTxAGC_B_Rate18_06) + *(unsigned int *)(&OFDMTxAgcOffset_B[0]) = cpu_to_be32(u4bRegValue); + if (u4bRegOffset == rTxAGC_B_Rate54_24) + *(unsigned int *)(&OFDMTxAgcOffset_B[4]) = cpu_to_be32(u4bRegValue); + + if (u4bRegOffset == rTxAGC_B_CCK5_1_Mcs32) { + tmp_rTxAGC_B_CCK5_1_Mcs32 = u4bRegValue; + prev_reg = rTxAGC_B_CCK5_1_Mcs32; + } + + if (u4bRegOffset == rTxAGC_A_CCK11_2_B_CCK11) { + if (prev_reg == rTxAGC_B_CCK5_1_Mcs32) { + //printk("\n%x %x %x\n", tmp_rTxAGC_B_CCK5_1_Mcs32, u4bRegValue, cpu_to_be32((u4bRegValue << 24) | (tmp_rTxAGC_B_CCK5_1_Mcs32 >> 8))); + *(unsigned int *)(&CCKTxAgc_B[0]) = cpu_to_be32((u4bRegValue << 24) | (tmp_rTxAGC_B_CCK5_1_Mcs32 >> 8)); + } + } + + if (u4bRegOffset == 0x868) { + write_en = 0; + break; + } + } + } else +#endif + { + //PHY_SetBBReg(priv, u4bRegOffset, u4bRegMask, u4bRegValue); + //printk("3C - 92C %x %x %x \n", u4bRegOffset, u4bRegMask, u4bRegValue); + } + } else { + //printk("Not 3C - %x %x %x \n", u4bRegOffset, bMaskDWord, u4bRegValue); + //PHY_SetBBReg(priv, u4bRegOffset, bMaskDWord, u4bRegValue); + } + num++; + } + + return 0; +} + +#endif + +/*----------------------------------------------------------------------------- + * Function: PHY_ConfigBBWithParaFile() + * + * Overview: This function read BB parameters from general file format, and do register + * Read/Write + * + * Input: PADAPTER Adapter + * ps1Byte pFileName + * + * Output: NONE + * + * Return: RT_STATUS_SUCCESS: configuration file exist + * + *---------------------------------------------------------------------------*/ +int PHY_ConfigBBWithParaFile(struct rtl8192cd_priv *priv, int reg_file) +{ + int read_bytes = 0, num = 0, len = 0; + unsigned int u4bRegOffset, u4bRegValue, u4bRegMask = 0; + int file_format = TWO_COLUMN; + unsigned char *mem_ptr, *line_head, *next_head = NULL; +#if 1//defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL)//TXPWR_LMT_8812 TXPWR_LMT_88E + unsigned char *mem_ptr2, *next_head2=NULL; +#endif + struct PhyRegTable *phyreg_table = NULL; + struct MacRegTable *macreg_table = NULL; + unsigned short max_len = 0; + unsigned int regstart, regend; +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + int idx = 0, pg_tbl_idx = BGN_2040_ALL, write_en = 0; +#endif + + if (reg_file == AGCTAB) { + phyreg_table = (struct PhyRegTable *)priv->pshare->agc_tab_buf; +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { +#ifdef HIGH_POWER_EXT_PA //_eric_?? DMDP & SMSP ?? + if (priv->pshare->rf_ft_var.use_ext_pa) { + //printk("[%s][AGC_TAB_n_92d_hp]\n",__FUNCTION__); + next_head = data_AGC_TAB_n_92d_hp_start; + read_bytes = (int)(data_AGC_TAB_n_92d_hp_end - data_AGC_TAB_n_92d_hp_start); + } else { + //printk("[%s][AGC_TAB_n]\n",__FUNCTION__); + next_head = data_AGC_TAB_n_start; + read_bytes = (int)(data_AGC_TAB_n_end - data_AGC_TAB_n_start); + } +#else //HIGH_POWER_EXT_PA +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + //printk("[%s][AGC_TAB_5G_n]\n",__FUNCTION__); + next_head = data_AGC_TAB_5G_n_start; + read_bytes = (int)(data_AGC_TAB_5G_n_end - data_AGC_TAB_5G_n_start); + } else { + //printk("[%s][AGC_TAB_2G_n]\n",__FUNCTION__); + next_head = data_AGC_TAB_2G_n_start; + read_bytes = (int)(data_AGC_TAB_2G_n_end - data_AGC_TAB_2G_n_start); + } + } else +#endif + { + //printk("[%s][AGC_TAB_n]\n",__FUNCTION__); + next_head = data_AGC_TAB_n_start; + read_bytes = (int)(data_AGC_TAB_n_end - data_AGC_TAB_n_start); + } +#endif //HIGH_POWER_EXT_PA + } +#endif //CONFIG_RTL_92D_SUPPORT + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { +#ifdef TESTCHIP_SUPPORT + if (IS_TEST_CHIP(priv)) { + next_head = data_AGC_TAB_start; + read_bytes = (int)(data_AGC_TAB_end - data_AGC_TAB_start); + } else +#endif + +#if defined(HIGH_POWER_EXT_PA) || defined(HIGH_POWER_EXT_LNA) + if ( +#ifdef HIGH_POWER_EXT_PA + priv->pshare->rf_ft_var.use_ext_pa +#else + priv->pshare->rf_ft_var.use_ext_lna +#endif + ) { + next_head = data_AGC_TAB_n_hp_start; + read_bytes = (int)(data_AGC_TAB_n_hp_end - data_AGC_TAB_n_hp_start); + } else +#endif + { + next_head = data_AGC_TAB_n_92C_start; + read_bytes = (int)(data_AGC_TAB_n_92C_end - data_AGC_TAB_n_92C_start); + } + } +#endif + + + +#ifdef CONFIG_RTL_8812_SUPPORT //8812 agc + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (IS_TEST_CHIP(priv)) { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + printk("[AGC_TAB_8812_hp]\n"); + next_head = data_AGC_TAB_8812_hp_start; + read_bytes = (int)(data_AGC_TAB_8812_hp_end - data_AGC_TAB_8812_hp_start); + } else +#endif + { + printk("[AGC_TAB_8812]\n"); + next_head = data_AGC_TAB_8812_start; + read_bytes = (int)(data_AGC_TAB_8812_end - data_AGC_TAB_8812_start); + } + } else { //for_8812_mp_chip +#ifdef HIGH_POWER_EXT_PA +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[AGC_TAB_8812_n_hp]\n"); + next_head = data_AGC_TAB_8812_n_hp_start; + read_bytes = (int)(data_AGC_TAB_8812_n_hp_end - data_AGC_TAB_8812_n_hp_start); + } else if (priv->pshare->rf_ft_var.use_ext_pa && !priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[AGC_TAB_8812_n_extpa]\n"); + next_head = data_AGC_TAB_8812_n_extpa_start; + read_bytes = (int)(data_AGC_TAB_8812_n_extpa_end - data_AGC_TAB_8812_n_extpa_start); + } else if (!priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[AGC_TAB_8812_n_extlna]\n"); + next_head = data_AGC_TAB_8812_n_extlna_start; + read_bytes = (int)(data_AGC_TAB_8812_n_extlna_end - data_AGC_TAB_8812_n_extlna_start); + } else +#else + if (priv->pshare->rf_ft_var.use_ext_pa) { + panic_printk("[AGC_TAB_8812_n_extpa]\n"); + next_head = data_AGC_TAB_8812_n_extpa_start; + read_bytes = (int)(data_AGC_TAB_8812_n_extpa_end - data_AGC_TAB_8812_n_extpa_start); + } else +#endif +#else //HIGH_POWER_EXT_PA=n +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[AGC_TAB_8812_n_extlna]\n"); + next_head = data_AGC_TAB_8812_n_extlna_start; + read_bytes = (int)(data_AGC_TAB_8812_n_extlna_end - data_AGC_TAB_8812_n_extlna_start); + } else +#endif +#endif + { + printk("[AGC_TAB_8812_n_default]\n"); + next_head = data_AGC_TAB_8812_n_default_start; + read_bytes = (int)(data_AGC_TAB_8812_n_default_end - data_AGC_TAB_8812_n_default_start); + } + } + } +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { +#ifdef HIGH_POWER_EXT_PA +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_HP_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_HP_START, (pu1Byte)&next_head); + } else if (priv->pshare->rf_ft_var.use_ext_pa && !priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_EXTPA_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_EXTPA_START, (pu1Byte)&next_head); + } else if (!priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_EXTLNA_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_EXTLNA_START, (pu1Byte)&next_head); + } else +#else + if (priv->pshare->rf_ft_var.use_ext_pa) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_EXTPA_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_EXTPA_START, (pu1Byte)&next_head); + } else +#endif +#else +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_EXTLNA_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_EXTLNA_START, (pu1Byte)&next_head); + } else +#endif +#endif + { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_AGC_START, (pu1Byte)&next_head); + } + } +#endif //CONFIG_WLAN_HAL + + max_len = AGC_TAB_SIZE; + } else if (reg_file == PHYREG_PG) { + //printk("[%s][PHY_REG_PG]\n",__FUNCTION__); +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + + if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_FCC) { + //printk("\nFCC PG!!!\n"); + next_head = data_PHY_REG_PG_FCC_start; + read_bytes = (int)(data_PHY_REG_PG_FCC_end - data_PHY_REG_PG_FCC_start); + } else if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) { + //printk("\nCE PG!!!\n"); + next_head = data_PHY_REG_PG_CE_start; + read_bytes = (int)(data_PHY_REG_PG_CE_end - data_PHY_REG_PG_CE_start); + } else { + //printk("\nOTHER PG!!!\n"); + next_head = data_PHY_REG_PG_start; + read_bytes = (int)(data_PHY_REG_PG_end - data_PHY_REG_PG_start); + } + +#ifdef HIGH_POWER_EXT_PA + if ( priv->pshare->rf_ft_var.use_ext_pa) { + //printk("[%s][data_PHY_REG_PG_92d_hp]\n", __FUNCTION__); + next_head = data_PHY_REG_PG_92d_hp_start; + read_bytes = (int)(data_PHY_REG_PG_92d_hp_end - data_PHY_REG_PG_92d_hp_start); + } +#endif + +//_TXPWR_REDEFINE ?? Why 5G no need working channel ?? +//_TXPWR_REDEFINE in MP Tool, 3 Groups: 36-99 100-148 149-165 + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + if (priv->pshare->is_40m_bw == 0) { + if (priv->pmib->dot11RFEntry.dot11channel <= 99) + pg_tbl_idx = AN_20_CH_36_64; + else if (priv->pmib->dot11RFEntry.dot11channel <= 148) + pg_tbl_idx = AN_20_CH_100_140; + else + pg_tbl_idx = AN_20_CH_149_165; + } else { + //_TXPWR_REDEFINE ?? + int val = priv->pmib->dot11RFEntry.dot11channel; + + if (priv->pshare->offset_2nd_chan == 1) + val -= 2; + else + val += 2; + + if (priv->pmib->dot11RFEntry.dot11channel <= 99) + pg_tbl_idx = AN_40_CH_36_64; + else if (priv->pmib->dot11RFEntry.dot11channel <= 148) + pg_tbl_idx = AN_40_CH_100_140; + else + pg_tbl_idx = AN_40_CH_149_165; + } + } else { + if (priv->pshare->is_40m_bw == 0) { + if (priv->pmib->dot11RFEntry.dot11channel <= 3) + pg_tbl_idx = BGN_20_CH1_3; + else if (priv->pmib->dot11RFEntry.dot11channel <= 9) + pg_tbl_idx = BGN_20_CH4_9; + else + pg_tbl_idx = BGN_20_CH10_14; + } else { + int val = priv->pmib->dot11RFEntry.dot11channel; + + if (priv->pshare->offset_2nd_chan == 1) + val -= 2; + else + val += 2; + + if (val <= 3) + pg_tbl_idx = BGN_40_CH1_3; + else if (val <= 9) + pg_tbl_idx = BGN_40_CH4_9; + else + pg_tbl_idx = BGN_40_CH10_14; + } + } +#ifdef MP_TEST + //In Noraml Driver mode, and if mib 'pwr_by_rate' = 0 >> Use default power by rate table + if ( (priv->pshare->rf_ft_var.mp_specific == 0) && (priv->pshare->rf_ft_var.pwr_by_rate == 0) ) + pg_tbl_idx = BGN_2040_ALL; +#endif + DEBUG_INFO("channel=%d pg_tbl_idx=%d\n", priv->pmib->dot11RFEntry.dot11channel, pg_tbl_idx); + + } +#endif //CONFIG_RTL_92D_SUPPORT + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { +#ifdef HIGH_POWER_EXT_PA + if ( priv->pshare->rf_ft_var.use_ext_pa) { + //printk("[%s][data_PHY_REG_PG_hp]\n", __FUNCTION__); + next_head = data_PHY_REG_PG_hp_start; + read_bytes = (int)(data_PHY_REG_PG_hp_end - data_PHY_REG_PG_hp_start); + + } else +#endif + { + //printk("[%s][data_PHY_REG_PG_92C]\n", __FUNCTION__); + next_head = data_PHY_REG_PG_92C_start; + read_bytes = (int)(data_PHY_REG_PG_92C_end - data_PHY_REG_PG_92C_start); + } + } +#endif //CONFIG_RTL_92C_SUPPORT + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { +#ifdef SUPPORT_RTL8188E_TC + if (IS_TEST_CHIP(priv)) + return 0; +#endif + +#ifdef TXPWR_LMT_88E +#ifdef __ECOS + DEBUG_INFO("[%s][PHY_REG_PG_88E_new]\n", __FUNCTION__); +#else + printk("[%s][PHY_REG_PG_88E_new]\n", __FUNCTION__); +#endif + next_head = data_PHY_REG_PG_88E_new_start; + read_bytes = (int)(data_PHY_REG_PG_88E_new_end - data_PHY_REG_PG_88E_new_start); + + pg_tbl_idx = 0; +#else + + printk("[%s][PHY_REG_PG_88E]\n", __FUNCTION__); + next_head = data_PHY_REG_PG_88E_start; + read_bytes = (int)(data_PHY_REG_PG_88E_end - data_PHY_REG_PG_88E_start); + + /* In Noraml Driver mode, and if mib 'pwr_by_rate' = 0 >> Use default power by rate table */ + if ( +#ifdef MP_TEST + priv->pshare->rf_ft_var.mp_specific || +#endif + priv->pshare->rf_ft_var.pwr_by_rate) { + if (priv->pshare->is_40m_bw == 0) { + if (priv->pmib->dot11RFEntry.dot11channel <= 3) + pg_tbl_idx = BGN_20_CH1_3; + else if (priv->pmib->dot11RFEntry.dot11channel <= 9) + pg_tbl_idx = BGN_20_CH4_9; + else + pg_tbl_idx = BGN_20_CH10_14; + } else { + int val = priv->pmib->dot11RFEntry.dot11channel; + + if (priv->pshare->offset_2nd_chan == 1) + val -= 2; + else + val += 2; + + if (val <= 3) + pg_tbl_idx = BGN_40_CH1_3; + else if (val <= 9) + pg_tbl_idx = BGN_40_CH4_9; + else + pg_tbl_idx = BGN_40_CH10_14; + } + } +#endif + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) + pg_tbl_idx = 0; +#endif + + DEBUG_INFO("channel=%d pg_tbl_idx=%d\n", priv->pmib->dot11RFEntry.dot11channel, pg_tbl_idx); + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT //eric_8812 pg + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + pg_tbl_idx = 1; + else + pg_tbl_idx = 0; + + +#ifdef HIGH_POWER_EXT_PA + if(priv->pmib->dot11RFEntry.pa_type == PA_SKYWORKS_85712_HP){ + panic_printk("[PHY_REG_PG_8812_hp]\n"); + next_head = data_PHY_REG_PG_8812_hp_start; + read_bytes = (int)(data_PHY_REG_PG_8812_hp_end - data_PHY_REG_PG_8812_hp_start); + }else +#endif + { +#ifdef TXPWR_LMT_8812 + panic_printk("[PHY_REG_PG_8812_new]\n"); + next_head = data_PHY_REG_PG_8812_new_start; + read_bytes = (int)(data_PHY_REG_PG_8812_new_end - data_PHY_REG_PG_8812_new_start); +#else + panic_printk("[PHY_REG_PG_8812]\n"); + next_head = data_PHY_REG_PG_8812_start; + read_bytes = (int)(data_PHY_REG_PG_8812_end - data_PHY_REG_PG_8812_start); +#endif + } + + DEBUG_INFO("channel=%d pg_tbl_idx=%d\n", priv->pmib->dot11RFEntry.dot11channel, pg_tbl_idx); + } +#endif //CONFIG_RTL_8812_SUPPORT + +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv) ) { + //printk("[%s][PHY_REG_PG_HAL]\n", __FUNCTION__); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_PG_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_PG_START, (pu1Byte)&next_head); +#if defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_WLAN_HAL_8814AE) + if ((GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G){ + pg_tbl_idx = 1; + //printk("phyBandSelect == PHY_BAND_5G\n"); + } + else{ + pg_tbl_idx = 0; + //printk("phyBandSelect == PHY_BAND_2G\n"); + } + } else +#endif + { + /* In Noraml Driver mode, and if mib 'pwr_by_rate' = 0 >> Use default power by rate table */ + if ( +#ifdef MP_TEST + priv->pshare->rf_ft_var.mp_specific || +#endif + priv->pshare->rf_ft_var.pwr_by_rate) { + if (priv->pshare->is_40m_bw == 0) { + if (priv->pmib->dot11RFEntry.dot11channel <= 3) + pg_tbl_idx = BGN_20_CH1_3; + else if (priv->pmib->dot11RFEntry.dot11channel <= 9) + pg_tbl_idx = BGN_20_CH4_9; + else + pg_tbl_idx = BGN_20_CH10_14; + } else { + int val = priv->pmib->dot11RFEntry.dot11channel; + + if (priv->pshare->offset_2nd_chan == 1) + val -= 2; + else + val += 2; + + if (val <= 3) + pg_tbl_idx = BGN_40_CH1_3; + else if (val <= 9) + pg_tbl_idx = BGN_40_CH4_9; + else + pg_tbl_idx = BGN_40_CH10_14; + } + } + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) + pg_tbl_idx = 0; +#endif + } + DEBUG_INFO("channel=%d pg_tbl_idx=%d\n", priv->pmib->dot11RFEntry.dot11channel, pg_tbl_idx); + } +#endif //CONFIG_WLAN_HAL + + macreg_table = (struct MacRegTable *)priv->pshare->phy_reg_pg_buf; + max_len = PHY_REG_PG_SIZE; + file_format = THREE_COLUMN; + priv->pshare->txpwr_pg_format_abs = 0; + + unsigned char *mem_ptr_tmp, *next_head_tmp=NULL; + if ((mem_ptr_tmp= (unsigned char *)rtw_vmalloc(MAX_CONFIG_FILE_SIZE)) == NULL) { + printk("PHY_ConfigBBWithParaFile(): not enough memory\n"); + return -1; + } + + memset(mem_ptr_tmp, 0, MAX_CONFIG_FILE_SIZE); // clear memory + memcpy(mem_ptr_tmp, next_head, read_bytes); + + next_head_tmp= mem_ptr_tmp; + while(1) { + line_head = next_head_tmp; + next_head_tmp= get_line(&line_head); + + if (line_head == NULL) + break; + if (line_head[0] == '/') + continue; + + if (line_head[0] == '#') { + int line_idx = 1; //line_len = strlen(line_head); + + while (line_idx <= strlen(line_head)) + { + if (!memcmp(&(line_head[line_idx]), "Exact", 5)) { + //panic_printk("\n******** PG Exact format !!! ********\n"); + priv->pshare->txpwr_pg_format_abs = 1; + file_format = FIVE_COLUMN; + break; + } + line_idx++; + } + } + + if (!memcmp(line_head, "0x", 2) || !memcmp(line_head, "0X", 2)) + break; + } + + rtw_vmfree(mem_ptr_tmp, MAX_CONFIG_FILE_SIZE); + + //panic_printk("PG file_format : %s\n", ((file_format == THREE_COLUMN) ? "THREE_COLUMN" : "FIVE_COLUMN")); + +#ifdef TXPWR_LMT_NEWFILE + if ((file_format == THREE_COLUMN) && (GET_CHIP_VER(priv) >= VERSION_8188E)) { + panic_printk("%s() fail !!!: Wrong PHY_REG_PG format\n", __FUNCTION__); + return -1; + } +#endif + memset(priv->pshare->tgpwr_CCK_new, 0, 2); + memset(priv->pshare->tgpwr_OFDM_new, 0, 2); + memset(priv->pshare->tgpwr_HT1S_new, 0, 2); + memset(priv->pshare->tgpwr_HT2S_new, 0, 2); + memset(priv->pshare->tgpwr_VHT1S_new, 0, 2); + memset(priv->pshare->tgpwr_VHT2S_new, 0, 2); + } +#if 0 + else if (reg_file == PHYREG_1T2R) { + macreg_table = (struct MacRegTable *)priv->pshare->phy_reg_2to1; + max_len = PHY_REG_1T2R; + file_format = THREE_COLUMN; + if (priv->pshare->rf_ft_var.pathB_1T == 0) { // PATH A + next_head = __PHY_to1T2R_start; + read_bytes = (int)(__PHY_to1T2R_end - __PHY_to1T2R_start); + } else { // PATH B + next_head = __PHY_to1T2R_b_start; + read_bytes = (int)(__PHY_to1T2R_b_end - __PHY_to1T2R_b_start); + } + } +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) || defined (CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + else if (reg_file == PHYREG) { +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_buf; +#ifdef HIGH_POWER_EXT_PA + //printk("[%s][PHY_REG_n_92d_hp]\n",__FUNCTION__); + next_head = data_PHY_REG_n_92d_hp_start; + read_bytes = (int)(data_PHY_REG_n_92d_hp_end - data_PHY_REG_n_92d_hp_start); +#else + //printk("[%s][PHY_REG_n]\n",__FUNCTION__); + next_head = data_PHY_REG_n_start; + read_bytes = (int)(data_PHY_REG_n_end - data_PHY_REG_n_start); +#endif + max_len = PHY_REG_SIZE; + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT //8812 phy + if (GET_CHIP_VER(priv) == VERSION_8812E) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_buf; + if (IS_TEST_CHIP(priv)) { //for_8812_mp_chip + panic_printk("[%s][PHY_REG_8812]\n",__FUNCTION__); + next_head = data_PHY_REG_8812_start; + read_bytes = (int)(data_PHY_REG_8812_end - data_PHY_REG_8812_start); + } else { +#ifdef HIGH_POWER_EXT_PA +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[PHY_REG_8812_n_hp]\n"); + next_head = data_PHY_REG_8812_n_hp_start; + read_bytes = (int)(data_PHY_REG_8812_n_hp_end - data_PHY_REG_8812_n_hp_start); + } else if (priv->pshare->rf_ft_var.use_ext_pa && !priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[PHY_REG_8812_n_extpa]\n"); + next_head = data_PHY_REG_8812_n_extpa_start; + read_bytes = (int)(data_PHY_REG_8812_n_extpa_end - data_PHY_REG_8812_n_extpa_start); + } else if (!priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[PHY_REG_8812_n_extlna]\n"); + next_head = data_PHY_REG_8812_n_extlna_start; + read_bytes = (int)(data_PHY_REG_8812_n_extlna_end - data_PHY_REG_8812_n_extlna_start); + } else +#else + if (priv->pshare->rf_ft_var.use_ext_pa) { + panic_printk("[PHY_REG_8812_n_extpa]\n"); + next_head = data_PHY_REG_8812_n_extpa_start; + read_bytes = (int)(data_PHY_REG_8812_n_extpa_end - data_PHY_REG_8812_n_extpa_start); + } else +#endif +#else +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[PHY_REG_8812_n_extlna]\n"); + next_head = data_PHY_REG_8812_n_extlna_start; + read_bytes = (int)(data_PHY_REG_8812_n_extlna_end - data_PHY_REG_8812_n_extlna_start); + } else +#endif +#endif + { + panic_printk("[PHY_REG_8812_n_default]\n"); + next_head = data_PHY_REG_8812_n_default_start; + read_bytes = (int)(data_PHY_REG_8812_n_default_end - data_PHY_REG_8812_n_default_start); + } + } + max_len = PHY_REG_SIZE; + } +#endif + +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv) ) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_buf; +#ifdef HIGH_POWER_EXT_PA +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_HP_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_HP_START, (pu1Byte)&next_head); + } else if (priv->pshare->rf_ft_var.use_ext_pa && !priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_EXTPA_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_EXTPA_START, (pu1Byte)&next_head); + } else if (!priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_EXTLNA_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_EXTLNA_START, (pu1Byte)&next_head); + } else +#else + if (priv->pshare->rf_ft_var.use_ext_pa) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_EXTPA_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_EXTPA_START, (pu1Byte)&next_head); + } else +#endif +#else +#ifdef HIGH_POWER_EXT_LNA + if ( priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_EXTLNA_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_EXTLNA_START, (pu1Byte)&next_head); + } else +#endif +#endif + { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_START, (pu1Byte)&next_head); + } + + max_len = PHY_REG_SIZE; + } +#endif //CONFIG_WLAN_HAL + + } +#endif // CONFIG_RTL_92D_SUPPORT +#ifdef MP_TEST + else if (reg_file == PHYREG_MP) { +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_mp_buf; + //printk("[%s][PHY_REG_MP_n]\n",__FUNCTION__); + next_head = data_PHY_REG_MP_n_start; + read_bytes = (int)(data_PHY_REG_MP_n_end - data_PHY_REG_MP_n_start); + max_len = PHY_REG_SIZE; + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_mp_buf; + next_head = data_PHY_REG_MP_n_92C_start; + read_bytes = (int)(data_PHY_REG_MP_n_92C_end - data_PHY_REG_MP_n_92C_start); + max_len = PHY_REG_SIZE; + } +#endif + + +#ifdef CONFIG_RTL_8812_SUPPORT //8812 phy mp + if (GET_CHIP_VER(priv) == VERSION_8812E) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_mp_buf; + printk("[%s][PHY_REG_MP_8812]\n", __FUNCTION__); + next_head = data_PHY_REG_MP_8812_start; + read_bytes = (int)(data_PHY_REG_MP_8812_end - data_PHY_REG_MP_8812_start); + max_len = PHY_REG_SIZE; + } +#endif + +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv) ) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_mp_buf; + printk("[%s][PHY_REG_MP_HAL]\n", __FUNCTION__); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_MP_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_MP_START, (pu1Byte)&next_head); + max_len = PHY_REG_SIZE; + } +#endif //CONFIG_WLAN_HAL + + } +#endif +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL) + else if (reg_file == PHYREG_1T1R) { // PATH A + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_buf; +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { +#ifdef TESTCHIP_SUPPORT + if ( IS_TEST_CHIP(priv) ) { + next_head = data_PHY_REG_1T_start; + read_bytes = (int)(data_PHY_REG_1T_end - data_PHY_REG_1T_start); + } else +#endif + { +#if defined(HIGH_POWER_EXT_PA) || defined(HIGH_POWER_EXT_LNA) + if ( +#ifdef HIGH_POWER_EXT_PA + priv->pshare->rf_ft_var.use_ext_pa +#else + priv->pshare->rf_ft_var.use_ext_lna +#endif + ) { + //printk("[%s][PHY_REG_1T_n_hp]\n", __FUNCTION__); + next_head = data_PHY_REG_1T_n_hp_start; + read_bytes = (int)(data_PHY_REG_1T_n_hp_end - data_PHY_REG_1T_n_hp_start); + } else +#endif + { + //printk("[%s][PHY_REG_1T_n]\n", __FUNCTION__); + next_head = data_PHY_REG_1T_n_start; + read_bytes = (int)(data_PHY_REG_1T_n_end - data_PHY_REG_1T_n_start); + } + } + } +#endif + + +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv) ) { + printk("[%s][PHY_REG_1T_HAL]\n", __FUNCTION__); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_1T_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_1T_START, (pu1Byte)&next_head); + } +#endif //CONFIG_WLAN_HAL + + max_len = PHY_REG_SIZE; +#if 0 + if (priv->pshare->rf_ft_var.pathB_1T == 0) { + next_head = __PHY_to1T1R_start; + read_bytes = (int)(__PHY_to1T1R_end - __PHY_to1T1R_start); + } else { // PATH B + next_head = __PHY_to1T1R_b_start; + read_bytes = (int)(__PHY_to1T1R_b_end - __PHY_to1T1R_b_start); + } +#endif + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + else if (reg_file == PHYREG_2T2R) { +#ifdef TESTCHIP_SUPPORT + if (IS_TEST_CHIP(priv)) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_buf; + next_head = data_PHY_REG_2T_start; + read_bytes = (int)(data_PHY_REG_2T_end - data_PHY_REG_2T_start); + } else +#endif + { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_buf; +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) + { + panic_printk("[%s][PHY_REG_2T_n_hp]\n", __FUNCTION__); + next_head = data_PHY_REG_2T_n_hp_start; + read_bytes = (int)(data_PHY_REG_2T_n_hp_end - data_PHY_REG_2T_n_hp_start); + } else +#endif +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) + { + panic_printk("[%s][PHY_REG_2T_n_lna]\n", __FUNCTION__); + next_head = data_PHY_REG_2T_n_lna_start; + read_bytes = (int)(data_PHY_REG_2T_n_lna_end - data_PHY_REG_2T_n_lna_start); + } else +#endif + { + //printk("[%s][PHY_REG_2T_n]\n", __FUNCTION__); + next_head = data_PHY_REG_2T_n_start; + read_bytes = (int)(data_PHY_REG_2T_n_end - data_PHY_REG_2T_n_start); + } + } + max_len = PHY_REG_SIZE; + } +#endif + + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if (GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv)==VERSION_8881A) { + if (pg_tbl_idx == 0) { + regstart = 0xc20; + regend = 0xe38; + } else { + regstart = 0xc24; + regend = 0xe4c; + } + } else { + regstart = 0xe00; + regend = 0x868; + } +#endif +#if 0 + if (file_format == FIVE_COLUMN) + { + + if ((mem_ptr2 = (unsigned char *)kmalloc(MAX_CONFIG_FILE_SIZE, GFP_ATOMIC)) == NULL) { + printk("PHY_ConfigBBWithParaFile(): not enough memory\n"); + return -1; + } + + memset(mem_ptr2, 0, MAX_CONFIG_FILE_SIZE); // clear memory + memcpy(mem_ptr2, next_head, read_bytes); + + next_head2 = mem_ptr2; + while(1) { + line_head = next_head2; + next_head2 = get_line(&line_head); + + if (line_head == NULL) + break; + if (line_head[0] == '/') + continue; + get_target_val_new(priv, line_head, &u4bRegOffset, &u4bRegMask ,&u4bRegValue); + } + + kfree(mem_ptr2); + } +#endif + if((mem_ptr = (unsigned char *)rtw_vmalloc(MAX_CONFIG_FILE_SIZE)) == NULL) { + printk("PHY_ConfigBBWithParaFile(): not enough memory\n"); + return -1; + } + + memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE); // clear memory + memcpy(mem_ptr, next_head, read_bytes); + + next_head = mem_ptr; + while (1) { + line_head = next_head; + next_head = get_line(&line_head); + if (line_head == NULL) + break; + + if (line_head[0] == '/') + continue; + + if (file_format == TWO_COLUMN) { + num = get_offset_val(line_head, &u4bRegOffset, &u4bRegValue); + if (num > 0) { + if (((len+1) * sizeof(struct PhyRegTable)) > max_len) + break; + phyreg_table[len].offset = u4bRegOffset; + phyreg_table[len].value = u4bRegValue; + len++; + + if ((len & 0x7ff) == 0) + watchdog_kick(); + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT)|| defined(CONFIG_WLAN_HAL) //_eric_8812 ?? u4bRegOffset + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) { + if (u4bRegOffset == 0xffff) + break; + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (u4bRegOffset == 0xff) + break; + } + } + } else { + if (reg_file == PHYREG_PG) { + if (file_format == THREE_COLUMN) + num = get_offset_mask_val(line_head, &u4bRegOffset, &u4bRegMask , &u4bRegValue); + else + num = get_offset_mask_val_new(priv, line_head, &u4bRegOffset, &u4bRegMask , &u4bRegValue); + } + + if (num > 0) { + if (((len+1) * sizeof(struct MacRegTable)) > max_len) + break; + macreg_table[len].offset = u4bRegOffset; + macreg_table[len].mask = u4bRegMask; + macreg_table[len].value = u4bRegValue; + len++; +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) { + if (u4bRegOffset == 0xffff) + break; + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (u4bRegOffset == 0xff) + break; + } + + if ((len & 0x7ff) == 0) + watchdog_kick(); + } + } + } + + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + + if ((len * sizeof(struct PhyRegTable)) > max_len) { + printk("PHY REG table buffer not large enough!\n"); + return -1; + } + } + + num = 0; + while (1) { + if (file_format == THREE_COLUMN || file_format == FIVE_COLUMN) { + u4bRegOffset = macreg_table[num].offset; + u4bRegValue = macreg_table[num].value; + u4bRegMask = macreg_table[num].mask; + } else { + u4bRegOffset = phyreg_table[num].offset; + u4bRegValue = phyreg_table[num].value; + } + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) { + if (u4bRegOffset == 0xffff) + break; + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (u4bRegOffset == 0xff) + break; + } + + if (file_format == THREE_COLUMN || file_format == FIVE_COLUMN) { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if (reg_file == PHYREG_PG && ( +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + (GET_CHIP_VER(priv) == VERSION_8192D)||(GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv)) +#endif + )) { + + if (u4bRegOffset == regstart) { + if (idx == pg_tbl_idx) + write_en = 1; + idx++; + } + if (write_en) { + //panic_printk("0x%03x 0x%08x\n", u4bRegOffset, u4bRegValue); + PHY_SetBBReg(priv, u4bRegOffset, u4bRegMask, u4bRegValue); + if (u4bRegOffset == regend) { + write_en = 0; + break; + } + } + + } else +#endif + { + PHY_SetBBReg(priv, u4bRegOffset, u4bRegMask, u4bRegValue); + } + } + else + { + PHY_SetBBReg(priv, u4bRegOffset, bMaskDWord, u4bRegValue); + } +#ifdef USE_OUT_SRC + if (reg_file == AGCTAB && priv->pshare->_dmODM.print_agc) + { + panic_printk("Reg %x [31:0] = %x \n", u4bRegOffset, u4bRegValue); + } +#endif + num++; + } + + return 0; +} + + +/*----------------------------------------------------------------------------- + * Function: PHY_ConfigRFWithParaFile() + * + * Overview: This function read RF parameters from general file format, and do RF 3-wire + * + * Input: PADAPTER Adapter + * ps1Byte pFileName + * RF92CD_RADIO_PATH_E eRFPath + * + * Output: NONE + * + * Return: RT_STATUS_SUCCESS: configuration file exist + * + * Note: Delay may be required for RF configuration + *---------------------------------------------------------------------------*/ +int PHY_ConfigRFWithParaFile(struct rtl8192cd_priv *priv, + unsigned char *start, int read_bytes, + RF92CD_RADIO_PATH_E eRFPath) +{ + int num; + unsigned int u4bRegOffset, u4bRegValue; + unsigned char *mem_ptr, *line_head, *next_head; + + if ((mem_ptr = (unsigned char *)rtw_vmalloc(MAX_CONFIG_FILE_SIZE)) == NULL) { + printk("PHY_ConfigRFWithParaFile(): not enough memory\n"); + return -1; + } + + memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE); // clear memory + memcpy(mem_ptr, start, read_bytes); + + next_head = mem_ptr; + while (1) { + line_head = next_head; + next_head = get_line(&line_head); + if (line_head == NULL) + break; + + if (line_head[0] == '/') + continue; + + num = get_offset_val(line_head, &u4bRegOffset, &u4bRegValue); + if (num > 0) { +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) //_eric_8812 ?? rf paras ?? + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) { + if (u4bRegOffset == 0xffff) { + break; + } else if ((u4bRegOffset == 0xfe) || (u4bRegOffset == 0xffe)) { + delay_ms(50); // Delay 50 ms. Only RF configuration require delay + } else if (num == 2) { + PHY_SetRFReg(priv, eRFPath, u4bRegOffset, bMask20Bits, u4bRegValue); + delay_ms(1); + } + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (u4bRegOffset == 0xff) { + break; + } else if (u4bRegOffset == 0xfe) { + delay_ms(50); // Delay 50 ms. Only RF configuration require delay + } else if (num == 2) { + PHY_SetRFReg(priv, eRFPath, u4bRegOffset, bMask20Bits, u4bRegValue); + delay_ms(1); + } + } + } + + watchdog_kick(); + } + + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + + return 0; +} + +#if 1 +int PHY_ConfigMACWithParaFile(struct rtl8192cd_priv *priv) +{ + int read_bytes, num, len = 0; + unsigned int u4bRegOffset, u4bRegValue; + unsigned char *mem_ptr, *line_head, *next_head; + struct PhyRegTable *reg_table = (struct PhyRegTable *)priv->pshare->mac_reg_buf; + + { + if ((mem_ptr = (unsigned char *)rtw_vmalloc(MAX_CONFIG_FILE_SIZE)) == NULL) { + printk("PHY_ConfigMACWithParaFile(): not enough memory\n"); + return -1; + } + + memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE); // clear memory +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + u8 *pMACRegStart; + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_MACREGFILE_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_MACREGFILE_START, (pu1Byte)&pMACRegStart); + memcpy(mem_ptr, pMACRegStart, read_bytes); + } +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + printk("[%s][MACPHY_REG]\n", __FUNCTION__); + read_bytes = (int)(data_MACPHY_REG_end - data_MACPHY_REG_start); + memcpy(mem_ptr, data_MACPHY_REG_start, read_bytes); + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + printk("[%s][MACPHY_REG_92C]\n", __FUNCTION__); + read_bytes = (int)(data_MACPHY_REG_92C_end - data_MACPHY_REG_92C_start); + memcpy(mem_ptr, data_MACPHY_REG_92C_start, read_bytes); + } +#endif + + +#ifdef CONFIG_RTL_8812_SUPPORT //mac reg + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (IS_TEST_CHIP(priv)) { + panic_printk("[MAC_REG_8812]\n"); + read_bytes = (int)(data_MAC_REG_8812_end - data_MAC_REG_8812_start); + memcpy(mem_ptr, data_MAC_REG_8812_start, read_bytes); + } else { + panic_printk("[MAC_REG_8812_n]\n"); + read_bytes = (int)(data_MAC_REG_8812_n_end - data_MAC_REG_8812_n_start); + memcpy(mem_ptr, data_MAC_REG_8812_n_start, read_bytes); + } + } +#endif + next_head = mem_ptr; + while (1) { + line_head = next_head; + next_head = get_line(&line_head); + if (line_head == NULL) + break; + + if (line_head[0] == '/') + continue; + + num = get_offset_val(line_head, &u4bRegOffset, &u4bRegValue); + if (num > 0) { + reg_table[len].offset = u4bRegOffset; + reg_table[len].value = u4bRegValue; + len++; +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) { + if (u4bRegOffset == 0xffff) + break; + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (u4bRegOffset == 0xff) + break; + } + if ((len * sizeof(struct MacRegTable)) > MAC_REG_SIZE) + break; + } + } +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) + reg_table[len].offset = 0xffff; + else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + reg_table[len].offset = 0xff; + + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + + if ((len * sizeof(struct MacRegTable)) > MAC_REG_SIZE) { + printk("MAC REG table buffer not large enough!\n"); + return -1; + } + } + + num = 0; + while (1) { + u4bRegOffset = reg_table[num].offset; + u4bRegValue = reg_table[num].value; + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) { + if (u4bRegOffset == 0xffff) + break; + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (u4bRegOffset == 0xff) + break; + } + + RTL_W8(u4bRegOffset, u4bRegValue); + num++; + } + +#if 0 //defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (priv->pmib->dot11nConfigEntry.dot11nSTBC && priv->pmib->dot11nConfigEntry.dot11nLDPC) + RTL_W16(REG_RESP_SIFS_OFDM_8812, 0x0c0c); + } +#endif + + return 0; +} +#endif + +#ifdef UNIVERSAL_REPEATER +static struct rtl8192cd_priv *get_another_interface_priv(struct rtl8192cd_priv *priv) +{ + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + return GET_VXD_PRIV(priv); + else if (IS_DRV_OPEN(GET_ROOT(priv))) + return GET_ROOT(priv); + else + return NULL; +} + + +static int get_shortslot_for_another_interface(struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_priv *p_priv; + + p_priv = get_another_interface_priv(priv); + if (p_priv) { + if (p_priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) + return (p_priv->pmib->dot11ErpInfo.shortSlot); + else { + if (p_priv->pmib->dot11OperationEntry.opmode & WIFI_ASOC_STATE) + return (p_priv->pmib->dot11ErpInfo.shortSlot); + } + } + return -1; +} +#endif // UNIVERSAL_REPEATER + + +void set_slot_time(struct rtl8192cd_priv *priv, int use_short) +{ +#ifdef UNIVERSAL_REPEATER + int is_short; + is_short = get_shortslot_for_another_interface(priv); + if (is_short != -1) { // not abtained + use_short &= is_short; + } +#endif + +#if defined(CONFIG_PCI_HCI) + if (use_short) + RTL_W8(SLOT_TIME, 0x09); + else + RTL_W8(SLOT_TIME, 0x14); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_slot_time_change(priv, use_short); +#endif +} + +void SwChnl(struct rtl8192cd_priv *priv, unsigned char channel, int offset) +{ + unsigned int val = channel, eRFPath, curMaxRFPath; + +#ifdef RTK_NL80211 /*cfg p2p cfg p2p*/ + if( priv->pshare->rtk_remain_on_channel ) { + NDEBUG("deny rtk_remain_on_channel\n"); + return; + } +#endif + +#if defined(DFS) && !defined(RTK_NL80211) +#ifdef UNIVERSAL_REPEATER + unsigned int no_beacon = 0; + if(under_apmode_repeater(priv)) + { + if(!priv->pmib->dot11DFSEntry.disable_DFS && is_DFS_channel(channel)) + { + if(!priv->site_survey->hidden_ap_found){ + no_beacon = 1; + } + } + } +#endif +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + priv->pshare->No_RF_Write = 0; + UpdateBBRFVal8812(priv, channel); + } +#endif + +// TODO: 8814AE BB/RF +// TODO: after all BB/RF init ready, change (8881A || 8814AE) to (WLAN_HAL && 11AC_SUPPORT) ?? +#if defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + if ((GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + priv->pshare->No_RF_Write = 0; + GET_HAL_INTERFACE(priv)->PHYUpdateBBRFValHandler(priv, channel, offset); + } +#endif + +#ifdef AC2G_256QAM + if(is_ac2g(priv)) //for 8812 & 8881a + { + RTL_W32(0x8c0, RTL_R32(0x8c0) & (~BIT(17))); //enable tx vht rates + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { +#ifdef MP_TEST + if ( (priv->pshare->rf_ft_var.mp_specific == 0) || (priv->pshare->rf_ft_var.pwr_by_rate == 1) ) + reload_txpwr_pg(priv); +#endif + } +#endif + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + curMaxRFPath = RF92CD_PATH_B; + else +#endif + curMaxRFPath = RF92CD_PATH_MAX; + + if (channel > 14) + priv->pshare->curr_band = BAND_5G; + else + priv->pshare->curr_band = BAND_2G; + +//_TXPWR_REDEFINE ?? Working channel also apply to 5G ?? what if channel = 165 + 2 or 36 -2 ?? +#if 0 +#ifdef RTK_AC_SUPPORT //todo, find working channel for 80M + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_80) { +#ifdef AC2G_256QAM + if(is_ac2g(priv)) + val = 7; //in 2g band, only channel 7 can expand to 80M bw + else +#endif + if (channel <= 48) + val = 42; + else if (channel <= 64) + val = 58; + else if (channel <= 112) + val = 106; + else if (channel <= 128) + val = 122; + else if (channel <= 144) + val = 138; + else if (channel <= 161) + val = 155; + else if (channel <= 177) + val = 171; + } else +#endif + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) { + if (offset == 1) + val -= 2; + else + val += 2; + } +#else + val = get_center_channel(priv, channel, offset, 1); +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) +#endif + if (priv->pshare->rf_ft_var.use_frq_2_3G) + val += 14; + + for (eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + priv->pshare->RegRF18[eRFPath] = RTL_SET_MASK(priv->pshare->RegRF18[eRFPath], 0xff, val, 0); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, 0xff, val); + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + /* + * Set Bit18 when channel >= 100, for 5G only + */ + if (val >= 100) + priv->pshare->RegRF18[eRFPath] |= BIT(18); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(18), 1); + else + priv->pshare->RegRF18[eRFPath] &= (~(BIT(18))); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(18), 0); + + priv->pshare->RegRF18[eRFPath] |= BIT(16); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(16), 1); + priv->pshare->RegRF18[eRFPath] |= BIT(8); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(8), 1); + // CLOAD for RF paht_A/B (MP-chip) + if (val < 149) + PHY_SetRFReg(priv, eRFPath, 0xB, BIT(16) | BIT(15) | BIT(14), 0x7); + else + PHY_SetRFReg(priv, eRFPath, 0xB, BIT(16) | BIT(15) | BIT(14), 0x2); + } else { + priv->pshare->RegRF18[eRFPath] &= (~(BIT(18))); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(18, 0); + priv->pshare->RegRF18[eRFPath] &= (~(BIT(16))); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(16), 0); + priv->pshare->RegRF18[eRFPath] &= (~(BIT(8))); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(8), 0); + // CLOAD for RF paht_A/B (MP-chip) + PHY_SetRFReg(priv, eRFPath, 0xB, BIT(16) | BIT(15) | BIT(14), 0x7); + } + + PHY_SetRFReg(priv, eRFPath, rRfChannel, bMask20Bits, priv->pshare->RegRF18[eRFPath]); + //printk("%s(%d) RF 18 = 0x%05x[0x%05x]\n",__FUNCTION__,__LINE__,priv->pshare->RegRF18[eRFPath], + //PHY_QueryRFReg(priv,eRFPath,rRfChannel,bMask20Bits,1)); +#ifdef RX_GAIN_TRACK_92D + priv->pshare->RegRF3C[eRFPath] = PHY_QueryRFReg(priv, eRFPath, 0x3C, bMask20Bits, 1); +#endif + } else +#endif + { + PHY_SetRFReg(priv, eRFPath, rRfChannel, 0xff, val); + } + + } + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + SetSYN_para(priv, val); +#ifdef SW_LCK_92D + phy_ReloadLCKSetting(priv); +#endif + SetIMR_n(priv, val); + + Update92DRFbyChannel(priv, val); + + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) +#endif + if (priv->pshare->rf_ft_var.use_frq_2_3G) + val -= 14; + + priv->pshare->working_channel = val; + +#ifdef TXPWR_LMT + { + if (!priv->pshare->rf_ft_var.disable_txpwrlmt) { + + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188E)) //92c_pwrlmt + { + //printk("reload_txpwr_pg\n"); + reload_txpwr_pg(priv); + } + +#ifdef TXPWR_LMT_NEWFILE + if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8188E) || IS_HAL_CHIP(priv)) + find_pwr_limit_new(priv, channel, offset); + else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + find_pwr_limit(priv, channel, offset); + } + } +#endif + + +#if defined(DFS) && !defined(RTK_NL80211) +#ifdef UNIVERSAL_REPEATER + if(under_apmode_repeater(priv)) + { + if(no_beacon == 1) + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | STOP_BCN); + else + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & ~STOP_BCN); + } +#endif +#endif + SetTxPowerLevel(priv); + + return; +} + +#ifdef MCR_WIRELESS_EXTEND +#ifdef CONFIG_WLAN_HAL_8814AE +int Switch_Antenna_8814(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned int rx_ss=0, ant=0; + unsigned char*val=NULL; + + if (strlen(data)==0) { + GDEBUG("Null data !!!\n"); + return 1; + } else + GDEBUG("data: %s\n", data); + + + val = get_value_by_token((char *)data, "ss="); + if (val) { + rx_ss = _atoi(val,10); + if (rx_ss < 1 || rx_ss > 4) { + GDEBUG("not support ss=%d !\n", rx_ss); + return 1; + } + } else { + GDEBUG("no specific ss !\n"); + return 1; + } + + val = get_value_by_token((char *)data, "path="); + if (val) { + if (rx_ss == 1) { + if (priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_80) { + PHY_SetBBReg(priv, 0x838, BIT0, 0x1); + PHY_SetBBReg(priv, 0x82C, 0x00f00000, 0xb); + PHY_SetBBReg(priv, 0x82C, 0x000f0000, 0xb); + PHY_SetBBReg(priv, 0x838, 0x0f000000, 0x9); + PHY_SetBBReg(priv, 0x838, 0x00f00000, 0x9); + PHY_SetBBReg(priv, 0x838, 0x000f0000, 0x9); + PHY_SetBBReg(priv, 0x840, 0x0000f000, 0x7); + } else { + PHY_SetBBReg(priv, 0x82c, BIT27|BIT26|BIT25|BIT24, 0x5); + RTL_W8(0x830,0xa); + } + if (!strcmp(val,"a")) + ant = ANTENNA_A; + else if (!strcmp(val,"b")) + ant = ANTENNA_B; + else if (!strcmp(val,"c")) + ant = ANTENNA_C; + else if (!strcmp(val,"d")) + ant = ANTENNA_D; + } + else if (rx_ss == 2) { + if (priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_80) { + PHY_SetBBReg(priv, 0x838, BIT0, 0x1); + PHY_SetBBReg(priv, 0x82C, 0x00f00000, 0xa); + PHY_SetBBReg(priv, 0x82C, 0x000f0000, 0x9); + PHY_SetBBReg(priv, 0x838, 0x0f000000, 0x9); + PHY_SetBBReg(priv, 0x838, 0x00f00000, 0x9); + PHY_SetBBReg(priv, 0x838, 0x000f0000, 0x9); + PHY_SetBBReg(priv, 0x840, 0x0000f000, 0x6); + } else { + PHY_SetBBReg(priv, 0x82c, BIT27|BIT26|BIT25|BIT24, 0x5); + RTL_W8(0x830,0xa); + } + if (!strcmp(val,"ab")) + ant = 0; //ANTENNA_AB; + else if (!strcmp(val,"bc")) + ant = ANTENNA_BC; + else if (!strcmp(val,"cd")) + ant = 0; //ANTENNA_CD; + } + else if (rx_ss == 3) { + if (priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_80) { + PHY_SetBBReg(priv, 0x838, BIT0, 0x1); + PHY_SetBBReg(priv, 0x82C, 0x00f00000, 0xa); + PHY_SetBBReg(priv, 0x82C, 0x000f0000, 0x8); + PHY_SetBBReg(priv, 0x838, 0x0f000000, 0x7); + PHY_SetBBReg(priv, 0x838, 0x00f00000, 0x7); + PHY_SetBBReg(priv, 0x838, 0x000f0000, 0x7); + PHY_SetBBReg(priv, 0x840, 0x0000f000, 0x6); + } else { + PHY_SetBBReg(priv, 0x82c, BIT27|BIT26|BIT25|BIT24, 0x3); + RTL_W8(0x830,0x8); + } + + if (!strcmp(val,"abc")) + ant = 0; //ANTENNA_ABC; + else if (!strcmp(val,"bcd")) + ant = ANTENNA_BCD; + } + else if (rx_ss == 4) { + if (priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_80) { + PHY_SetBBReg(priv, 0x838, BIT0, 0x1); + PHY_SetBBReg(priv, 0x82C, 0x00f00000, 0xa); + PHY_SetBBReg(priv, 0x82C, 0x000f0000, 0x8); + PHY_SetBBReg(priv, 0x838, 0x0f000000, 0x7); + PHY_SetBBReg(priv, 0x838, 0x00f00000, 0x7); + PHY_SetBBReg(priv, 0x838, 0x000f0000, 0x7); + PHY_SetBBReg(priv, 0x840, 0x0000f000, 0x7); + } else { + PHY_SetBBReg(priv, 0x82c, BIT27|BIT26|BIT25|BIT24, 0x3); + RTL_W8(0x830,0x8); + } + if (!strcmp(val,"abcd")) + ant = ANTENNA_ABCD; + } + + if (!ant) { + GDEBUG("no support ant=%s ! (rx_ss=%d)\n", val, rx_ss); + return 1; + } + } else { + GDEBUG("no specific path !\n"); + return 1; + } + + + switch(ant) + { + case ANTENNA_A: + //Tx + PHY_SetBBReg(priv, 0x93c, 0xfff00000, 0x001); // 0x93C[31:20]=12'b0000_0000_0001 + + //Rx + PHY_SetBBReg(priv, 0x808, 0xff, 0x11); + break; + + case ANTENNA_B: + //Tx + PHY_SetBBReg(priv, 0x93c, 0xfff00000, 0x002); // 0x93C[31:20]=12'b0000_0000_0001 + + //Rx + PHY_SetBBReg(priv, 0x808, 0xff, 0x22); + break; + + case ANTENNA_C: + //Tx + PHY_SetBBReg(priv, 0x93c, 0xfff00000, 0x004); // 0x93C[31:20]=12'b0000_0000_0001 + + //Rx + PHY_SetBBReg(priv, 0x808, 0xff, 0x44); + break; + + case ANTENNA_D: + //Tx + PHY_SetBBReg(priv, 0x93c, 0xfff00000, 0x008); // 0x93C[31:20]=12'b0000_0000_0001 + + //Rx + PHY_SetBBReg(priv, 0x808, 0xff, 0x88); + break; + + case ANTENNA_BC: + //Tx + PHY_SetBBReg(priv, 0x93c, 0xfff00000, 0x002); // 0x93C[31:20]=12'b0000_0000_0001 + + //Rx + PHY_SetBBReg(priv, 0x808, 0xff, 0x66); + break; + + case ANTENNA_BCD: + //Tx + PHY_SetBBReg(priv, 0x93c, 0xfff00000, 0x002); // 0x93C[31:20]=12'b0000_0000_0001 + + //Rx + PHY_SetBBReg(priv, 0x808, 0xff, 0xee); + break; + + case ANTENNA_ABCD: + //Tx + PHY_SetBBReg(priv, 0x93c, 0xfff00000, 0x002); // 0x93C[31:20]=12'b0000_0000_0001 + + //Rx + PHY_SetBBReg(priv, 0x808, 0xff, 0xff); + break; + } + + return 0; +} +#endif +#endif + +#ifdef EXPERIMENTAL_WIRELESS_EXTEND +// switch 1 spatial stream path +//antPath: 01 for PathA,10 for PathB, 11for Path AB +void Switch_1SS_Antenna(struct rtl8192cd_priv *priv, unsigned int antPath ) +{ + unsigned int dword = 0; + if (get_rf_mimo_mode(priv) != MIMO_2T2R) + return; + + if(GET_CHIP_VER(priv) == VERSION_8812E) { + switch (antPath) { + case 1: + dword = RTL_R32(0x80C); + if ((dword & 0xf000) == 0x1000) + goto switch_1ss_end; + dword &= 0xffff0fff; + dword |= 0x1000; // Path A + RTL_W32(0x80C, dword); + break; + case 2: + dword = RTL_R32(0x80C); + if ((dword & 0xf000) == 0x2000) + goto switch_1ss_end; + dword &= 0xffff0fff; + dword |= 0x2000; // Path B + RTL_W32(0x80C, dword); + break; + + case 3: + if (priv->pshare->rf_ft_var.ofdm_1ss_oneAnt == 1) // use one ANT for 1ss + goto switch_1ss_end;// do nothing + dword = RTL_R32(0x80C); + if ((dword & 0xf000) == 0x3000) + goto switch_1ss_end; + dword &= 0xffff0fff; + dword |= 0x3000; // Path A, B + RTL_W32(0x80C, dword); + break; + + default:// do nothing + break; + } + + } else { + + switch (antPath) { + case 1: + dword = RTL_R32(0x90C); + if ((dword & 0x0ff00000) == 0x01100000) + goto switch_1ss_end; + dword &= 0xf00fffff; + dword |= 0x01100000; // Path A + RTL_W32(0x90C, dword); + break; + case 2: + dword = RTL_R32(0x90C); + if ((dword & 0x0ff00000) == 0x02200000) + goto switch_1ss_end; + dword &= 0xf00fffff; + dword |= 0x02200000; // Path B + RTL_W32(0x90C, dword); + break; + + case 3: + if (priv->pshare->rf_ft_var.ofdm_1ss_oneAnt == 1) // use one ANT for 1ss + goto switch_1ss_end;// do nothing + dword = RTL_R32(0x90C); + if ((dword & 0x0ff00000) == 0x03300000) + goto switch_1ss_end; + dword &= 0xf00fffff; + dword |= 0x03300000; // Path A,B + RTL_W32(0x90C, dword); + break; + + default:// do nothing + break; + } + } +switch_1ss_end: + return; + +} + +// switch OFDM path +//antPath: 01 for PathA,10 for PathB, 11for Path AB +void Switch_OFDM_Antenna(struct rtl8192cd_priv *priv, unsigned int antPath ) +{ + unsigned int dword = 0; + if (get_rf_mimo_mode(priv) != MIMO_2T2R) + return; + + if(GET_CHIP_VER(priv) == VERSION_8812E) { + + switch (antPath) { + case 1: + dword = RTL_R32(0x80C); + if ((dword & 0xf00) == 0x100) + goto switch_OFDM_end; + dword &= 0xfffff0ff; + dword |= 0x100; // Path A + RTL_W32(0x80C, dword); + break; + case 2: + dword = RTL_R32(0x80C); + if ((dword & 0xf00) == 0x200) + goto switch_OFDM_end; + dword &= 0xfffff0ff; + dword |= 0x200; // Path B + RTL_W32(0x80C, dword); + break; + + case 3: + if (priv->pshare->rf_ft_var.ofdm_1ss_oneAnt == 1) // use one ANT for 1ss + goto switch_OFDM_end;// do nothing + dword = RTL_R32(0x80C); + if ((dword & 0xf00) == 0x300) + goto switch_OFDM_end; + dword &= 0xfffff0ff; + dword |= 0x300; // Path A, B + RTL_W32(0x80C, dword); + break; + + default:// do nothing + break; + } + + } else { + + switch (antPath) { + case 1: + dword = RTL_R32(0x90C); + if ((dword & 0x000000f0) == 0x00000010) + goto switch_OFDM_end; + dword &= 0xffffff0f; + dword |= 0x00000010; // Path A + RTL_W32(0x90C, dword); + break; + case 2: + dword = RTL_R32(0x90C); + if ((dword & 0x000000f0) == 0x00000020) + goto switch_OFDM_end; + dword &= 0xffffff0f; + dword |= 0x00000020; // Path B + RTL_W32(0x90C, dword); + break; + + case 3: + if (priv->pshare->rf_ft_var.ofdm_1ss_oneAnt == 1) // use one ANT for 1ss + goto switch_OFDM_end;// do nothing + dword = RTL_R32(0x90C); + if ((dword & 0x000000f0) == 0x00000030) + goto switch_OFDM_end; + dword &= 0xffffff0f; + dword |= 0x00000030; // Path A,B + RTL_W32(0x90C, dword); + break; + + default:// do nothing + break; + } + } +switch_OFDM_end: + return; + +} + + + +#endif + +void enable_hw_LED(struct rtl8192cd_priv *priv, unsigned int led_type) +{ + +#if (defined(HW_ANT_SWITCH) || defined(SW_ANT_SWITCH))&&( defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + int b23 = RTL_R32(LEDCFG) & BIT(23); +#endif + +#ifdef CONFIG_WLAN_HAL + // TODO: we should check register then set + if (IS_HAL_CHIP(priv)) + return; + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + switch (led_type) { + case LEDTYPE_HW_TX_RX: +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + RTL_W32(LEDCFG, LED_TX_RX_EVENT_ON << LED1CM_SHIFT_92D | LED1DIS_92D); +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) + RTL_W32(LEDCFG, LED_RX_EVENT_ON << LED1CM_SHIFT | LED_TX_EVENT_ON << LED0CM_SHIFT); +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xffff00ff) | BIT(13) | (LED_TX_RX_EVENT_ON << LED1CM_SHIFT)); +#endif + break; + case LEDTYPE_HW_LINKACT_INFRA: + RTL_W32(LEDCFG, LED_TX_RX_EVENT_ON << LED0CM_SHIFT); + if ((OPMODE & WIFI_AP_STATE) || (OPMODE & WIFI_STATION_STATE)) + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0x0ff); + else + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfffff0ff) | LED1SV); + break; + default: + break; + } + +#if (defined(HW_ANT_SWITCH) || defined(SW_ANT_SWITCH))&&( defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + RTL_W32(LEDCFG, b23 | RTL_R32(LEDCFG)); +#endif + } +} + + +/** +* Function: phy_InitBBRFRegisterDefinition +* +* OverView: Initialize Register definition offset for Radio Path A/B/C/D +* +* Input: +* PADAPTER Adapter, +* +* Output: None +* Return: None +* Note: The initialization value is constant and it should never be changes +*/ +void phy_InitBBRFRegisterDefinition(struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_hw *phw = GET_HW(priv); + + // RF Interface Sowrtware Control + phw->PHYRegDef[RF92CD_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 LSBs if read 32-bit from 0x870 + phw->PHYRegDef[RF92CD_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) + + // RF Interface Readback Value + phw->PHYRegDef[RF92CD_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB; // 16 LSBs if read 32-bit from 0x8E0 + phw->PHYRegDef[RF92CD_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB;// 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) + + // RF Interface Output (and Enable) + phw->PHYRegDef[RF92CD_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; // 16 LSBs if read 32-bit from 0x860 + phw->PHYRegDef[RF92CD_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; // 16 LSBs if read 32-bit from 0x864 + + // RF Interface (Output and) Enable + phw->PHYRegDef[RF92CD_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; // 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) + phw->PHYRegDef[RF92CD_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; // 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) + + //Addr of LSSI. Wirte RF register by driver + phw->PHYRegDef[RF92CD_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; //LSSI Parameter + phw->PHYRegDef[RF92CD_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter; + + // RF parameter + phw->PHYRegDef[RF92CD_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter; //BB Band Select + phw->PHYRegDef[RF92CD_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter; + + // Tx AGC Gain Stage (same for all path. Should we remove this?) + phw->PHYRegDef[RF92CD_PATH_A].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage + phw->PHYRegDef[RF92CD_PATH_B].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage + + // Tranceiver A~D HSSI Parameter-1 + phw->PHYRegDef[RF92CD_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1; //wire control parameter1 + phw->PHYRegDef[RF92CD_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1; //wire control parameter1 + + // Tranceiver A~D HSSI Parameter-2 + phw->PHYRegDef[RF92CD_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; //wire control parameter2 + phw->PHYRegDef[RF92CD_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; //wire control parameter2 + + // RF switch Control + phw->PHYRegDef[RF92CD_PATH_A].rfSwitchControl = rFPGA0_XAB_SwitchControl; //TR/Ant switch control + phw->PHYRegDef[RF92CD_PATH_B].rfSwitchControl = rFPGA0_XAB_SwitchControl; + + // AGC control 1 + phw->PHYRegDef[RF92CD_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1; + phw->PHYRegDef[RF92CD_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1; + + // AGC control 2 + phw->PHYRegDef[RF92CD_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2; + phw->PHYRegDef[RF92CD_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2; + + // RX AFE control 1 + phw->PHYRegDef[RF92CD_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance; + phw->PHYRegDef[RF92CD_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance; + + // RX AFE control 1 + phw->PHYRegDef[RF92CD_PATH_A].rfRxAFE = rOFDM0_XARxAFE; + phw->PHYRegDef[RF92CD_PATH_B].rfRxAFE = rOFDM0_XBRxAFE; + + // Tx AFE control 1 + phw->PHYRegDef[RF92CD_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance; + phw->PHYRegDef[RF92CD_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance; + + // Tx AFE control 2 + phw->PHYRegDef[RF92CD_PATH_A].rfTxAFE = rOFDM0_XATxAFE; + phw->PHYRegDef[RF92CD_PATH_B].rfTxAFE = rOFDM0_XBTxAFE; + + // Tranceiver LSSI Readback SI mode + phw->PHYRegDef[RF92CD_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack; + phw->PHYRegDef[RF92CD_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack; + + // Tranceiver LSSI Readback PI mode + phw->PHYRegDef[RF92CD_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback; + phw->PHYRegDef[RF92CD_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback; +} + + +void check_chipID_MIMO(struct rtl8192cd_priv *priv) +{ +#ifdef CONFIG_WLAN_HAL + if (GET_CHIP_VER(priv) == VERSION_8881A) { + priv->pshare->version_id |= (RTL_R16(0xf0)>>8) & 0x0f0; // save b[15:12] + goto exit_func; + }else if (GET_CHIP_VER(priv) == VERSION_8192E) { + priv->pshare->version_id |= (RTL_R16(0xf0)>>8) & 0x0f0; // 92E c-cut + goto exit_func; + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT //FOR_8812_MP_CHIP + if (GET_CHIP_VER(priv) == VERSION_8812E) { + unsigned int val32; + val32 = RTL_R32(SYS_CFG); + if (val32 & BIT(23)) { + panic_printk("8812 test chip !! \n"); + priv->pshare->version_id |= 0x100; //is 8812 test chip + } else { + panic_printk("8812 mp chip !! \n"); + if (((val32 & 0xf000) >> 12) == 1) { // [15:12] :1 --> C-cut + priv->pshare->version_id |= 0x10; + } + } + priv->pshare->phw->MIMO_TR_hw_support = MIMO_2T2R; + goto exit_func; + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + priv->pshare->phw->MIMO_TR_hw_support = MIMO_1T1R; + goto exit_func; + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + priv->pshare->phw->MIMO_TR_hw_support = MIMO_1T1R; + else + priv->pshare->phw->MIMO_TR_hw_support = MIMO_2T2R; + goto exit_func; + } +#endif + +#ifdef CONFIG_RTL_92C_SUPPORT + { + unsigned int val32; + val32 = RTL_R32(SYS_CFG); + if (val32 & BIT(27)) { + priv->pshare->version_id = VERSION_8192C; + priv->pshare->phw->MIMO_TR_hw_support = MIMO_2T2R; + } else { + priv->pshare->version_id = VERSION_8188C; + priv->pshare->phw->MIMO_TR_hw_support = MIMO_1T1R; + + if ((0x3 & (RTL_R32(0xec) >> 22)) == 0x01) + priv->pshare->version_id |= 0x200; // 88RE + } + + if (val32 & BIT(23)) { + priv->pshare->version_id |= 0x100; + } + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + if (val32 & BIT(19)) { + priv->pshare->version_id |= 0x400; // UMC + priv->pshare->version_id |= (0xf0 & (val32 >> 8)); // 0: a-cut + } + if (((0x0f & (val32 >> 16)) == 0) && ((0x0f & (val32 >> 12)) == 1)) { //6195B + priv->pshare->version_id |= 0x400; + priv->pshare->version_id |= 0x10; // 0x10: b-cut + } + } + } + +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) +exit_func: +#endif + return; +} + +void selectMinPowerIdex(struct rtl8192cd_priv *priv) +{ + int i = 0, idx, pwr_min = 0xff; + unsigned int val32; + unsigned int pwr_regA[] = {0xe00, 0xe04, 0xe08, 0x86c, 0xe10, 0xe14, 0xe18, 0xe1c}; +//#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + unsigned int pwr_regB[] = {0x830, 0x834, 0x838, 0x86c, 0x83c, 0x848, 0x84c, 0x868}; +//#endif + + for (idx = 0 ; idx < 8 ; idx++) { + val32 = RTL_R32(pwr_regA[idx]); + switch (pwr_regA[idx]) { + case 0xe08: + pwr_min = POWER_MIN_CHECK(pwr_min, (val32 >> 8) & 0xff); + break; + + case 0x86c: + for (i = 8 ; i < 32 ; i += 8) + pwr_min = POWER_MIN_CHECK(pwr_min, (val32 >> i) & 0xff); + break; + + default: + for (i = 0 ; i < 32 ; i += 8) + pwr_min = POWER_MIN_CHECK(pwr_min, (val32 >> i) & 0xff); + break; + } + } + +/* +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + ((GET_CHIP_VER(priv) == VERSION_8192D) +#ifdef CONFIG_RTL_92D_DMDP + && (priv->pmib->dot11RFEntry.macPhyMode == SINGLEMAC_SINGLEPHY) +#endif + ) +#endif + ) +*/ + if(get_rf_mimo_mode(priv) == MIMO_2T2R) + { + for (idx = 0 ; idx < 8 ; idx++) { + val32 = RTL_R32(pwr_regB[idx]); + switch (pwr_regB[idx]) { + case 0x86c: + pwr_min = POWER_MIN_CHECK(pwr_min, val32 & 0xff); + break; + + case 0x838: + for (i = 8 ; i < 32 ; i += 8) + pwr_min = POWER_MIN_CHECK(pwr_min, (val32 >> i) & 0xff); + break; + + default: + for (i = 0 ; i < 32 ; i += 8) + pwr_min = POWER_MIN_CHECK(pwr_min, (val32 >> i) & 0xff); + break; + } + } + } +//#endif + + priv->pshare->rf_ft_var.min_pwr_idex = pwr_min; +} + +#ifdef POWER_PERCENT_ADJUSTMENT +s1Byte PwrPercent2PwrLevel(int percentage) +{ +#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0])) + + const int percent_threshold[] = {95, 85, 75, 67, 60, 54, 48, 43, 38, 34, 30, 27, 24, 22, 19, 17, 15, 14, 12, 11, 10}; + const s1Byte pwrlevel_diff[9] = { -40, -34, -30, -28, -26, -24, -23, -22, -21}; // for < 10% case + int i; + + for (i = 0; i < ARRAYSIZE(percent_threshold); ++i) { + if (percentage >= percent_threshold[i]) { + return (s1Byte) - i; + } + } + + if (percentage < 1) percentage = 1; + + return pwrlevel_diff[percentage - 1]; +} +#endif + +void PHY_RF6052SetOFDMTxPower(struct rtl8192cd_priv *priv, unsigned int channel) +{ + unsigned int writeVal, defValue = 0x28 ; + unsigned char offset; + unsigned char base, byte0, byte1, byte2, byte3; + unsigned char pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[channel - 1]; + unsigned char pwrlevelHT40_1S_B = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[channel - 1]; + unsigned char pwrdiffHT40_2S = priv->pmib->dot11RFEntry.pwrdiffHT40_2S[channel - 1]; + unsigned char pwrdiffHT20 = priv->pmib->dot11RFEntry.pwrdiffHT20[channel - 1]; + unsigned char pwrdiffOFDM = priv->pmib->dot11RFEntry.pwrdiffOFDM[channel - 1]; +#ifdef USB_POWER_SUPPORT +//_TXPWR_REDEFINE + unsigned char pwrlevelHT40_6dBm_1S_A; + unsigned char pwrlevelHT40_6dBm_1S_B; + unsigned char pwrdiffHT40_6dBm_2S; + unsigned char pwrdiffHT20_6dBm; + unsigned char pwrdiffOFDM_6dBm; + unsigned char offset_6dBm; + s1Byte base_6dBm; +#endif +#ifdef POWER_PERCENT_ADJUSTMENT + s1Byte pwrdiff_percent = PwrPercent2PwrLevel(priv->pmib->dot11RFEntry.power_percent); +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + unsigned int ori_channel = channel; //Keep the original channel setting +#endif + + + +#ifdef CONFIG_RTL_88E_SUPPORT + /* for testchip only */ + if (GET_CHIP_VER(priv) == VERSION_8188E) { + defValue = 0x21; + + +#if defined(CALIBRATE_BY_ODM) +#ifdef MP_TEST + if ((priv->pshare->rf_ft_var.mp_specific) && priv->pshare->mp_txpwr_patha) + defValue = priv->pshare->mp_txpwr_patha; +#endif + if (ODMPTR->RFCalibrateInfo.ThermalValue > GET_ROOT(priv)->pmib->dot11RFEntry.ther) + defValue += (ODMPTR->RFCalibrateInfo.BbSwingIdxOfdm[RF_PATH_A] - ODMPTR->RFCalibrateInfo.DefaultOfdmIndex); +#endif + } +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_8198B) + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + defValue = 0x28; + else + defValue = 0x2d; +#else + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + defValue = 0x26; + else + defValue = 0x30; +#endif + + //TXPWR_REDEFINE + //FLASH GROUP [36-99] [100-148] [149-165] + //Special Cases: [34-2, 34, 34+2, 36-2, 165+2]:No DATA , [149-2]:FLASH DATA OF Channel-146-6dBm + //Use Flash data of channel 36 & 140 & 165 for these special cases. + if ((channel > 30) && (channel < 36)) + channel = 36; + else if (channel == (149 - 2)) + channel = 140; + else if (channel > 165) + channel = 165; + + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[channel - 1]; + pwrlevelHT40_1S_B = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel - 1]; + pwrdiffHT40_2S = priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[channel - 1]; + pwrdiffHT20 = priv->pmib->dot11RFEntry.pwrdiff5GHT20[channel - 1]; + pwrdiffOFDM = priv->pmib->dot11RFEntry.pwrdiff5GOFDM[channel - 1]; + } + +#ifdef USB_POWER_SUPPORT +//_TXPWR_REDEFINE +//MCS 8 - 15: No Power By Rate +//Others: Power by Rate (Add Power) +//Remove PWR_5G_DIFF + +//?? phyBandSelect will auto swtich or 2G | 5G ?? + { + int i; + + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + pwrlevelHT40_6dBm_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[channel]; + pwrlevelHT40_6dBm_1S_B = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel]; + pwrdiffHT40_6dBm_2S = priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[channel]; + pwrdiffHT20_6dBm = priv->pmib->dot11RFEntry.pwrdiff5GHT20[channel]; + pwrdiffOFDM_6dBm = priv->pmib->dot11RFEntry.pwrdiff5GOFDM[channel]; + } else { + pwrlevelHT40_6dBm_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[channel - 1]; + pwrlevelHT40_6dBm_1S_B = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel - 1]; + pwrdiffHT40_6dBm_2S = priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[channel - 1]; + pwrdiffHT20_6dBm = priv->pmib->dot11RFEntry.pwrdiff5GHT20[channel - 1]; + pwrdiffOFDM_6dBm = priv->pmib->dot11RFEntry.pwrdiff5GOFDM[channel - 1]; + } + } +#endif + + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && + priv->pshare->wlandev_idx == 1) { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel - 1]; + else { + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[channel - 1]; + } +//_TXPWR_REDEFINE +#ifdef USB_POWER_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + pwrlevelHT40_6dBm_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel]; + } else { + pwrlevelHT40_6dBm_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel - 1]; + } +#endif + } +#endif + + channel = ori_channel; //_TXPWR_REDEFINE Restore the channel setting + + } +#endif + + +#ifdef TXPWR_LMT +#ifdef TXPWR_LMT_88E + if(GET_CHIP_VER(priv) == VERSION_8188E) { + if(!priv->pshare->rf_ft_var.disable_txpwrlmt){ + int i; + int max_idx_a, max_idx_b =0; + + if (!priv->pshare->txpwr_lmt_OFDM || !priv->pshare->tgpwr_OFDM_new[RF_PATH_A]) { + //printk("No limit for OFDM TxPower\n"); + max_idx_a = 255; + max_idx_b = 255; + } else { + // maximum additional power index + max_idx_a = (priv->pshare->txpwr_lmt_OFDM - priv->pshare->tgpwr_OFDM_new[RF_PATH_A]); + max_idx_b = (priv->pshare->txpwr_lmt_OFDM - priv->pshare->tgpwr_OFDM_new[RF_PATH_B]); + } + + for (i = 0; i <= 7; i++) { + //printk("priv->pshare->phw->OFDMTxAgcOffset_A[%d]=0x%x max=0x%x\n",i, priv->pshare->phw->OFDMTxAgcOffset_A[i], max_idx_a); + priv->pshare->phw->OFDMTxAgcOffset_A[i] = POWER_MIN_CHECK(priv->pshare->phw->OFDMTxAgcOffset_A[i], max_idx_a); + priv->pshare->phw->OFDMTxAgcOffset_B[i] = POWER_MIN_CHECK(priv->pshare->phw->OFDMTxAgcOffset_B[i], max_idx_b); + //printk("priv->pshare->phw->OFDMTxAgcOffset_B[%d]=%x\n",i, priv->pshare->phw->OFDMTxAgcOffset_B[i]); + } + + if (!priv->pshare->txpwr_lmt_HT1S || !priv->pshare->tgpwr_HT1S_new[RF_PATH_A]) { + //printk("No limit for HT1S TxPower\n"); + max_idx_a = 255; + max_idx_b = 255; + } else { + // maximum additional power index + max_idx_a = (priv->pshare->txpwr_lmt_HT1S - priv->pshare->tgpwr_HT1S_new[RF_PATH_A]); + max_idx_b = (priv->pshare->txpwr_lmt_HT1S - priv->pshare->tgpwr_HT1S_new[RF_PATH_B]); + } + + for (i = 0; i <= 7; i++) { + //printk("priv->pshare->phw->MCSTxAgcOffset_A[%d]=0x%x max=0x%x\n",i, priv->pshare->phw->MCSTxAgcOffset_A[i], max_idx_a); + priv->pshare->phw->MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_A[i], max_idx_a); + priv->pshare->phw->MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_B[i], max_idx_b); + //printk("priv->pshare->phw->MCSTxAgcOffset_B[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_B[i]); + } + + if (!priv->pshare->txpwr_lmt_HT2S || !priv->pshare->tgpwr_HT2S_new[RF_PATH_A]) { + //printk("No limit for HT2S TxPower\n"); + max_idx_a = 255; + max_idx_b = 255; + } else { + // maximum additional power index + max_idx_a = (priv->pshare->txpwr_lmt_HT2S - priv->pshare->tgpwr_HT2S_new[RF_PATH_A]); + max_idx_b = (priv->pshare->txpwr_lmt_HT2S - priv->pshare->tgpwr_HT2S_new[RF_PATH_B]); + } + + for (i = 8; i <= 15; i++) { + //printk("priv->pshare->phw->MCSTxAgcOffset_A[%d]=%x max=0x%x\n",i, priv->pshare->phw->MCSTxAgcOffset_A[i], max_idx_a); + priv->pshare->phw->MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_A[i], max_idx_a); + priv->pshare->phw->MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_B[i], max_idx_b); + //printk("priv->pshare->phw->MCSTxAgcOffset_B[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_B[i]); + } + } + } + else +#endif + if ((GET_CHIP_VER(priv) == VERSION_8192D) || (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) + if (!priv->pshare->rf_ft_var.disable_txpwrlmt) { + int i; + int max_idx; + + if (!priv->pshare->txpwr_lmt_OFDM || !priv->pshare->tgpwr_OFDM) { + //printk("No limit for OFDM TxPower\n"); + max_idx = 255; + } else { + // maximum additional power index + max_idx = (priv->pshare->txpwr_lmt_OFDM - priv->pshare->tgpwr_OFDM); + } + + for (i = 0; i <= 7; i++) { + priv->pshare->phw->OFDMTxAgcOffset_A[i] = POWER_MIN_CHECK(priv->pshare->phw->OFDMTxAgcOffset_A[i], max_idx); + priv->pshare->phw->OFDMTxAgcOffset_B[i] = POWER_MIN_CHECK(priv->pshare->phw->OFDMTxAgcOffset_B[i], max_idx); + //printk("priv->pshare->phw->OFDMTxAgcOffset_A[%d]=%x\n",i, priv->pshare->phw->OFDMTxAgcOffset_A[i]); + //printk("priv->pshare->phw->OFDMTxAgcOffset_B[%d]=%x\n",i, priv->pshare->phw->OFDMTxAgcOffset_B[i]); + } + + if (!priv->pshare->txpwr_lmt_HT1S || !priv->pshare->tgpwr_HT1S) { + //printk("No limit for HT1S TxPower\n"); + max_idx = 255; + } else { + // maximum additional power index + max_idx = (priv->pshare->txpwr_lmt_HT1S - priv->pshare->tgpwr_HT1S); + } + + for (i = 0; i <= 7; i++) { + priv->pshare->phw->MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_A[i], max_idx); + priv->pshare->phw->MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_B[i], max_idx); + //printk("priv->pshare->phw->MCSTxAgcOffset_A[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_A[i]); + //printk("priv->pshare->phw->MCSTxAgcOffset_B[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_B[i]); + } + + if (!priv->pshare->txpwr_lmt_HT2S || !priv->pshare->tgpwr_HT2S) { + //printk("No limit for HT2S TxPower\n"); + max_idx = 255; + } else { + // maximum additional power index + max_idx = (priv->pshare->txpwr_lmt_HT2S - priv->pshare->tgpwr_HT2S); + } + + for (i = 8; i <= 15; i++) { + priv->pshare->phw->MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_A[i], max_idx); + priv->pshare->phw->MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_B[i], max_idx); + //printk("priv->pshare->phw->MCSTxAgcOffset_A[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_A[i]); + //printk("priv->pshare->phw->MCSTxAgcOffset_B[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_B[i]); + } + } +#endif + + + if ((pwrlevelHT40_1S_A == 0) +#if defined(MP_TEST) && defined(CONFIG_RTL_88E_SUPPORT) && defined(CALIBRATE_BY_ODM) + || ((priv->pshare->rf_ft_var.mp_specific) || (OPMODE & WIFI_MP_STATE)) +#endif + ) + + { + // use default value + +#ifdef HIGH_POWER_EXT_PA + if(!(priv->pshare->rf_ft_var.mp_specific) && !(OPMODE & WIFI_MP_STATE)) + if (priv->pshare->rf_ft_var.use_ext_pa) + defValue = HP_OFDM_POWER_DEFAULT ; +#endif +#ifndef ADD_TX_POWER_BY_CMD + writeVal = (defValue << 24) | (defValue << 16) | (defValue << 8) | (defValue); + RTL_W32(rTxAGC_A_Rate18_06, writeVal); + RTL_W32(rTxAGC_A_Rate54_24, writeVal); + RTL_W32(rTxAGC_A_Mcs03_Mcs00, writeVal); + RTL_W32(rTxAGC_A_Mcs07_Mcs04, writeVal); + RTL_W32(rTxAGC_B_Rate18_06, writeVal); + RTL_W32(rTxAGC_B_Rate54_24, writeVal); + RTL_W32(rTxAGC_B_Mcs03_Mcs00, writeVal); + RTL_W32(rTxAGC_B_Mcs07_Mcs04, writeVal); + +#ifdef USB_POWER_SUPPORT +//_TXPWR_REDEFINE, pwrlevelHT40_1S_A == 0 >> No 6dBm Power >> default value >> so USB = def - 14 + writeVal = POWER_RANGE_CHECK(defValue - USB_HT_2S_DIFF); + writeVal |= (writeVal << 24) | (writeVal << 16) | (writeVal << 8); +#endif + RTL_W32(rTxAGC_A_Mcs11_Mcs08, writeVal); + RTL_W32(rTxAGC_A_Mcs15_Mcs12, writeVal); + RTL_W32(rTxAGC_B_Mcs11_Mcs08, writeVal); + RTL_W32(rTxAGC_B_Mcs15_Mcs12, writeVal); +#else + base = defValue; + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_ofdm_18); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_ofdm_12); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_ofdm_9); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_ofdm_6); + + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Rate18_06, writeVal); + RTL_W32(rTxAGC_B_Rate18_06, writeVal); + + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_ofdm_54); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_ofdm_48); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_ofdm_36); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_ofdm_24); + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Rate54_24, writeVal); + RTL_W32(rTxAGC_B_Rate54_24, writeVal); + + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_mcs_3); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_mcs_2); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_mcs_1); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_mcs_0); + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Mcs03_Mcs00, writeVal); + RTL_W32(rTxAGC_B_Mcs03_Mcs00, writeVal); + + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_mcs_7); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_mcs_6); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_mcs_5); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_mcs_4); + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Mcs07_Mcs04, writeVal); + RTL_W32(rTxAGC_B_Mcs07_Mcs04, writeVal); + +//_TXPWR_REDEFINE +#ifdef USB_POWER_SUPPORT + byte0 = byte1 = byte2 = byte3 = -USB_HT_2S_DIFF; +#else + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_mcs_11); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_mcs_10); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_mcs_9); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_mcs_8); +#endif + + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Mcs11_Mcs08, writeVal); + RTL_W32(rTxAGC_B_Mcs11_Mcs08, writeVal); + +//_TXPWR_REDEFINE +#ifdef USB_POWER_SUPPORT + byte0 = byte1 = byte2 = byte3 = -USB_HT_2S_DIFF; +#else + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_mcs_15); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_mcs_14); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_mcs_13); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_mcs_12); +#endif + + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Mcs15_Mcs12, writeVal); + RTL_W32(rTxAGC_B_Mcs15_Mcs12, writeVal); + +#endif // ADD_TX_POWER_BY_CMD + return; // use default + } + + /****************************** PATH A ******************************/ + base = pwrlevelHT40_1S_A; + offset = (pwrdiffOFDM & 0x0f); +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) +//_TXPWR_REDEFINE?? + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset = ((pwrdiffOFDM & 0xf0) >> 4); + } +#endif + base = COUNT_SIGN_OFFSET(base, offset); +#ifdef POWER_PERCENT_ADJUSTMENT + base = POWER_RANGE_CHECK(base + pwrdiff_percent); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(CALIBRATE_BY_ODM) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + if (ODMPTR->RFCalibrateInfo.ThermalValue > GET_ROOT(priv)->pmib->dot11RFEntry.ther) + base += (ODMPTR->RFCalibrateInfo.BbSwingIdxOfdm[RF_PATH_A] - ODMPTR->RFCalibrateInfo.DefaultOfdmIndex); + } +#endif + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_A[0]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_A[1]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_A[2]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_A[3]); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Rate18_06, writeVal); + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_A[4]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_A[5]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_A[6]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_A[7]); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Rate54_24, writeVal); + + base = pwrlevelHT40_1S_A; + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + offset = (pwrdiffHT20 & 0x0f); +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) +//_TXPWR_REDEFINE?? + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset = ((pwrdiffHT20 & 0xf0) >> 4); + } +#endif + base = COUNT_SIGN_OFFSET(base, offset); + } +#ifdef POWER_PERCENT_ADJUSTMENT + base = POWER_RANGE_CHECK(base + pwrdiff_percent); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(CALIBRATE_BY_ODM) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + if (ODMPTR->RFCalibrateInfo.ThermalValue > GET_ROOT(priv)->pmib->dot11RFEntry.ther) + base += (ODMPTR->RFCalibrateInfo.BbSwingIdxOfdm[RF_PATH_A] - ODMPTR->RFCalibrateInfo.DefaultOfdmIndex); + } +#endif + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[0]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[1]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[2]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[3]); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Mcs03_Mcs00, writeVal); + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[4]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[5]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[6]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[7]); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Mcs07_Mcs04, writeVal); + + offset = (pwrdiffHT40_2S & 0x0f); +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) +//_TXPWR_REDEFINE?? + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset = ((pwrdiffHT40_2S & 0xf0) >> 4); + } +#endif + base = COUNT_SIGN_OFFSET(base, offset); + +//_TXPWR_REDEFINE +#ifdef USB_POWER_SUPPORT + + base_6dBm = pwrlevelHT40_6dBm_1S_A; + + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + offset_6dBm = (pwrdiffHT20_6dBm & 0x0f); + +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset_6dBm = ((pwrdiffHT20_6dBm & 0xf0) >> 4); + } +#endif + + base_6dBm = COUNT_SIGN_OFFSET(base_6dBm, offset_6dBm); + } + + offset_6dBm = (pwrdiffHT40_6dBm_2S & 0x0f); + +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset_6dBm = ((pwrdiffHT40_6dBm_2S & 0xf0) >> 4); + } +#endif + + base_6dBm = COUNT_SIGN_OFFSET(base_6dBm, offset_6dBm); + + if ((pwrlevelHT40_6dBm_1S_A != 0) && (pwrlevelHT40_6dBm_1S_A != pwrlevelHT40_1S_A)) + byte0 = byte1 = byte2 = byte3 = base_6dBm; + else if ((base - USB_HT_2S_DIFF) > 0) + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(base - USB_HT_2S_DIFF); + else + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(defValue - USB_HT_2S_DIFF); + +#else +//_TXPWR_REDEFINE ?? MCS 8 - 11, shall NOT add power by rate even NOT USB power ?? + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[8]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[9]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[10]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[11]); +#endif + + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + + //DEBUG_INFO("debug e18:%x,%x,[%x,%x,%x,%x],%x\n", offset, base, byte0, byte1, byte2, byte3, writeVal); + RTL_W32(rTxAGC_A_Mcs11_Mcs08, writeVal); + +#ifdef USB_POWER_SUPPORT +//_TXPWR_REDEFINE + if ((pwrlevelHT40_6dBm_1S_A != 0) && (pwrlevelHT40_6dBm_1S_A != pwrlevelHT40_1S_A)) + byte0 = byte1 = byte2 = byte3 = base_6dBm; + else if ((base - USB_HT_2S_DIFF) > 0) + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(base - USB_HT_2S_DIFF); + else + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(defValue - USB_HT_2S_DIFF); + +#else + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[12]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[13]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[14]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[15]); +#endif + + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_A_Mcs15_Mcs12, writeVal); + + /****************************** PATH B ******************************/ + base = pwrlevelHT40_1S_B; + offset = ((pwrdiffOFDM & 0xf0) >> 4); + base = COUNT_SIGN_OFFSET(base, offset); +#ifdef POWER_PERCENT_ADJUSTMENT + base = POWER_RANGE_CHECK(base + pwrdiff_percent); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(CALIBRATE_BY_ODM) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + if (ODMPTR->RFCalibrateInfo.ThermalValue > GET_ROOT(priv)->pmib->dot11RFEntry.ther) + base += (ODMPTR->RFCalibrateInfo.BbSwingIdxOfdm[RF_PATH_A] - ODMPTR->RFCalibrateInfo.DefaultOfdmIndex); + } +#endif + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_B[0]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_B[1]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_B[2]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_B[3]); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_B_Rate18_06, writeVal); + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_B[4]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_B[5]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_B[6]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->OFDMTxAgcOffset_B[7]); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_B_Rate54_24, writeVal); + + base = pwrlevelHT40_1S_B; + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + offset = ((pwrdiffHT20 & 0xf0) >> 4); + base = COUNT_SIGN_OFFSET(base, offset); + } +#ifdef POWER_PERCENT_ADJUSTMENT + base = POWER_RANGE_CHECK(base + pwrdiff_percent); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(CALIBRATE_BY_ODM) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + if (ODMPTR->RFCalibrateInfo.ThermalValue > GET_ROOT(priv)->pmib->dot11RFEntry.ther) + base += (ODMPTR->RFCalibrateInfo.BbSwingIdxOfdm[RF_PATH_A] - ODMPTR->RFCalibrateInfo.DefaultOfdmIndex); + } +#endif + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[0]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[1]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[2]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[3]); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_B_Mcs03_Mcs00, writeVal); + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[4]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[5]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[6]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[7]); + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_B_Mcs07_Mcs04, writeVal); + + offset = ((pwrdiffHT40_2S & 0xf0) >> 4); + base = COUNT_SIGN_OFFSET(base, offset); + +#ifdef USB_POWER_SUPPORT +//_TXPWR_REDEFINE ?? 2.4G + base_6dBm = pwrlevelHT40_6dBm_1S_B; + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + offset_6dBm = ((pwrdiffHT20_6dBm & 0xf0) >> 4); + base_6dBm = COUNT_SIGN_OFFSET(base_6dBm, offset_6dBm); + } + + offset_6dBm = ((pwrdiffHT40_6dBm_2S & 0xf0) >> 4); + base_6dBm = COUNT_SIGN_OFFSET(base_6dBm, offset_6dBm); + + if (( pwrlevelHT40_6dBm_1S_B != 0 ) && (pwrlevelHT40_6dBm_1S_B != pwrlevelHT40_1S_B)) + byte0 = byte1 = byte2 = byte3 = base_6dBm; + else if ((base - USB_HT_2S_DIFF) > 0) + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(base - USB_HT_2S_DIFF); + else + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(defValue - USB_HT_2S_DIFF); + +#else + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[8]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[9]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[10]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[11]); +#endif + + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_B_Mcs11_Mcs08, writeVal); + +#ifdef USB_POWER_SUPPORT +//_TXPWR_REDEFINE ?? 2.4G + if (( pwrlevelHT40_6dBm_1S_B != 0 ) && (pwrlevelHT40_6dBm_1S_B != pwrlevelHT40_1S_B)) + byte0 = byte1 = byte2 = byte3 = base_6dBm; + else if ((base - USB_HT_2S_DIFF) > 0) + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(base - USB_HT_2S_DIFF); + else + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(defValue - USB_HT_2S_DIFF); + +#else + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[12]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[13]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[14]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[15]); +#endif + + writeVal = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3; + RTL_W32(rTxAGC_B_Mcs15_Mcs12, writeVal); +} /* PHY_RF6052SetOFDMTxPower */ + + +void PHY_RF6052SetCCKTxPower(struct rtl8192cd_priv *priv, unsigned int channel) +{ + unsigned int writeVal = 0; + u1Byte byte, byte1, byte2; + u1Byte pwrlevelCCK_A = priv->pmib->dot11RFEntry.pwrlevelCCK_A[channel - 1]; + u1Byte pwrlevelCCK_B = priv->pmib->dot11RFEntry.pwrlevelCCK_B[channel - 1]; +#ifdef POWER_PERCENT_ADJUSTMENT + s1Byte pwrdiff_percent = PwrPercent2PwrLevel(priv->pmib->dot11RFEntry.power_percent); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_92D_DMDP) + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && + priv->pshare->wlandev_idx == 1) { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) { + pwrlevelCCK_A = priv->pmib->dot11RFEntry.pwrlevelCCK_B[channel - 1]; + } + } + } +#endif +#ifdef TXPWR_LMT + if (!priv->pshare->rf_ft_var.disable_txpwrlmt) { +#ifdef TXPWR_LMT_88E + if(GET_CHIP_VER(priv) == VERSION_8188E) { + int max_idx_a, max_idx_b, i; + if (!priv->pshare->txpwr_lmt_CCK || + !priv->pshare->tgpwr_CCK_new[RF_PATH_A]) { + DEBUG_INFO("No limit for CCK TxPower\n"); + max_idx_a = 255; + max_idx_b = 255; + } else { + // maximum additional power index + max_idx_a = (priv->pshare->txpwr_lmt_CCK - priv->pshare->tgpwr_CCK_new[RF_PATH_A]); + max_idx_b = (priv->pshare->txpwr_lmt_CCK - priv->pshare->tgpwr_CCK_new[RF_PATH_B]); + } + for (i = 0; i <= 3; i++) { + //printk("priv->pshare->phw->CCKTxAgc_A[%d]=0x%x max=0x%x\n",i, priv->pshare->phw->CCKTxAgc_A[i], max_idx_a); + //printk("priv->pshare->phw->CCKTxAgc_B[%d]=%x\n",i, priv->pshare->phw->CCKTxAgc_B[i]); + priv->pshare->phw->CCKTxAgc_A[i] = POWER_MIN_CHECK(priv->pshare->phw->CCKTxAgc_A[i], max_idx_a); + priv->pshare->phw->CCKTxAgc_B[i] = POWER_MIN_CHECK(priv->pshare->phw->CCKTxAgc_B[i], max_idx_b); + } + } + else +#endif + { + int max_idx, i; + if (!priv->pshare->txpwr_lmt_CCK || !priv->pshare->tgpwr_CCK) { + DEBUG_INFO("No limit for CCK TxPower\n"); + max_idx = 255; + } else { + // maximum additional power index + max_idx = (priv->pshare->txpwr_lmt_CCK - priv->pshare->tgpwr_CCK); + } + + for (i = 0; i <= 3; i++) { + priv->pshare->phw->CCKTxAgc_A[i] = POWER_MIN_CHECK(priv->pshare->phw->CCKTxAgc_A[i], max_idx); + priv->pshare->phw->CCKTxAgc_B[i] = POWER_MIN_CHECK(priv->pshare->phw->CCKTxAgc_B[i], max_idx); + //printk("priv->pshare->phw->CCKTxAgc_A[%d]=%x\n",i, priv->pshare->phw->CCKTxAgc_A[i]); + //printk("priv->pshare->phw->CCKTxAgc_B[%d]=%x\n",i, priv->pshare->phw->CCKTxAgc_B[i]); + } + } + } +#endif + + if (priv->pshare->rf_ft_var.cck_pwr_max) { + //byte = POWER_RANGE_CHECK(priv->pshare->rf_ft_var.cck_pwr_max); + byte = (priv->pshare->rf_ft_var.cck_pwr_max > 0x3f) ? 0x3f : priv->pshare->rf_ft_var.cck_pwr_max; + writeVal = byte; + PHY_SetBBReg(priv, rTxAGC_A_CCK1_Mcs32, 0x0000ff00, writeVal); + writeVal = (byte << 16) | (byte << 8) | byte; + PHY_SetBBReg(priv, rTxAGC_B_CCK5_1_Mcs32, 0xffffff00, writeVal); + writeVal = (byte << 24) | (byte << 16) | (byte << 8) | byte; + PHY_SetBBReg(priv, rTxAGC_A_CCK11_2_B_CCK11, 0xffffffff, writeVal); + return; + } + + if ((pwrlevelCCK_A == 0 && pwrlevelCCK_B == 0) +#if defined(MP_TEST) && defined(CONFIG_RTL_88E_SUPPORT) && defined(CALIBRATE_BY_ODM) + || ((priv->pshare->rf_ft_var.mp_specific) || (OPMODE & WIFI_MP_STATE)) +#endif + ) { + // use default value +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) + byte = HP_CCK_POWER_DEFAULT; + else +#endif + byte = 0x24; + +#ifdef CONFIG_RTL_88E_SUPPORT + /* for testchip only */ + if (GET_CHIP_VER(priv) == VERSION_8188E) { + byte = 0x21; + +#if defined(CALIBRATE_BY_ODM) +#ifdef MP_TEST + if ((priv->pshare->rf_ft_var.mp_specific) && priv->pshare->mp_txpwr_patha) + byte = priv->pshare->mp_txpwr_patha; +#endif + if (ODMPTR->RFCalibrateInfo.ThermalValue > GET_ROOT(priv)->pmib->dot11RFEntry.ther) + byte += (ODMPTR->RFCalibrateInfo.BbSwingIdxCck - ODMPTR->RFCalibrateInfo.DefaultCckIndex); +#endif + } +#endif + +#ifndef ADD_TX_POWER_BY_CMD + writeVal = byte; + PHY_SetBBReg(priv, rTxAGC_A_CCK1_Mcs32, 0x0000ff00, writeVal); + writeVal = (byte << 16) | (byte << 8) | byte; + PHY_SetBBReg(priv, rTxAGC_B_CCK5_1_Mcs32, 0xffffff00, writeVal); + writeVal = (byte << 24) | (byte << 16) | (byte << 8) | byte; + PHY_SetBBReg(priv, rTxAGC_A_CCK11_2_B_CCK11, 0xffffffff, writeVal); +#else + pwrlevelCCK_A = pwrlevelCCK_B = byte; + byte = 0; + ASSIGN_TX_POWER_OFFSET(byte, priv->pshare->rf_ft_var.txPowerPlus_cck_1); + writeVal = POWER_RANGE_CHECK(pwrlevelCCK_A + byte); + PHY_SetBBReg(priv, rTxAGC_A_CCK1_Mcs32, 0x0000ff00, writeVal); + + byte = byte1 = byte2 = 0; + ASSIGN_TX_POWER_OFFSET(byte, priv->pshare->rf_ft_var.txPowerPlus_cck_1); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_cck_2); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_cck_5); + byte = POWER_RANGE_CHECK(pwrlevelCCK_B + byte); + byte1 = POWER_RANGE_CHECK(pwrlevelCCK_B + byte1); + byte2 = POWER_RANGE_CHECK(pwrlevelCCK_B + byte2); + writeVal = ((byte2 << 16) | (byte1 << 8) | byte); + PHY_SetBBReg(priv, rTxAGC_B_CCK5_1_Mcs32, 0xffffff00, writeVal); + + byte = byte1 = byte2 = 0; + ASSIGN_TX_POWER_OFFSET(byte, priv->pshare->rf_ft_var.txPowerPlus_cck_2); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_cck_5); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_cck_11); + byte = POWER_RANGE_CHECK(pwrlevelCCK_A + byte); + byte1 = POWER_RANGE_CHECK(pwrlevelCCK_A + byte1); + byte2 = POWER_RANGE_CHECK(pwrlevelCCK_A + byte2); + writeVal = ((byte2 << 24) | (byte1 << 16) | (byte << 8) | byte2); + PHY_SetBBReg(priv, rTxAGC_A_CCK11_2_B_CCK11, 0xffffffff, writeVal); +#endif + return; // use default + } + + if ((get_rf_mimo_mode(priv) == MIMO_2T2R) && (pwrlevelCCK_B == 0)) { + pwrlevelCCK_B = pwrlevelCCK_A + + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[channel - 1] - priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[channel - 1]; + } + +#ifdef POWER_PERCENT_ADJUSTMENT + pwrlevelCCK_A = POWER_RANGE_CHECK(pwrlevelCCK_A + pwrdiff_percent); + pwrlevelCCK_B = POWER_RANGE_CHECK(pwrlevelCCK_B + pwrdiff_percent); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(CALIBRATE_BY_ODM) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + if (ODMPTR->RFCalibrateInfo.ThermalValue > GET_ROOT(priv)->pmib->dot11RFEntry.ther) + pwrlevelCCK_A += (ODMPTR->RFCalibrateInfo.BbSwingIdxCck - ODMPTR->RFCalibrateInfo.DefaultCckIndex); + } +#endif + + writeVal = POWER_RANGE_CHECK(pwrlevelCCK_A + priv->pshare->phw->CCKTxAgc_A[3] + priv->pmib->dot11RFEntry.add_cck1M_pwr); + PHY_SetBBReg(priv, rTxAGC_A_CCK1_Mcs32, 0x0000ff00, writeVal); + writeVal = (POWER_RANGE_CHECK(pwrlevelCCK_B + priv->pshare->phw->CCKTxAgc_B[1]) << 16) | + (POWER_RANGE_CHECK(pwrlevelCCK_B + priv->pshare->phw->CCKTxAgc_B[2]) << 8) | + POWER_RANGE_CHECK(pwrlevelCCK_B + priv->pshare->phw->CCKTxAgc_B[3] + priv->pmib->dot11RFEntry.add_cck1M_pwr); + PHY_SetBBReg(priv, rTxAGC_B_CCK5_1_Mcs32, 0xffffff00, writeVal); + writeVal = (POWER_RANGE_CHECK(pwrlevelCCK_A + priv->pshare->phw->CCKTxAgc_A[0]) << 24) | + (POWER_RANGE_CHECK(pwrlevelCCK_A + priv->pshare->phw->CCKTxAgc_A[1]) << 16) | + (POWER_RANGE_CHECK(pwrlevelCCK_A + priv->pshare->phw->CCKTxAgc_A[2]) << 8) | + POWER_RANGE_CHECK(pwrlevelCCK_B + priv->pshare->phw->CCKTxAgc_B[0]); + PHY_SetBBReg(priv, rTxAGC_A_CCK11_2_B_CCK11, 0xffffffff, writeVal); +} + + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + +int PHY_CheckBBWithParaFile(struct rtl8192cd_priv *priv, int reg_file) +{ + int read_bytes = 0, num, len = 0; + unsigned int u4bRegOffset, u4bRegValue, u4bRegMask; + int file_format = TWO_COLUMN; + unsigned char *mem_ptr, *line_head, *next_head = NULL; + struct PhyRegTable *phyreg_table = NULL; + struct MacRegTable *macreg_table = NULL; + unsigned short max_len = 0; + unsigned int regstart, regend; + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + int idx = 0, pg_tbl_idx = BGN_2040_ALL, write_en = 0; +#endif + + + if (reg_file == PHYREG) { +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv) == VERSION_8881A) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_buf; + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_SIZE, (pu1Byte)&read_bytes); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_PHYREGFILE_START, (pu1Byte)&next_head); + max_len = PHY_REG_SIZE; + } +#endif //CONFIG_WLAN_HAL + +#ifdef CONFIG_RTL_8812_SUPPORT //8812 phy + if (GET_CHIP_VER(priv) == VERSION_8812E) { + phyreg_table = (struct PhyRegTable *)priv->pshare->phy_reg_buf; + max_len = PHY_REG_SIZE; + + if (IS_TEST_CHIP(priv)) { //for_8812_mp_chip + printk("[%s][PHY_REG_8812]\n", __FUNCTION__); + next_head = data_PHY_REG_8812_start; + read_bytes = (int)(data_PHY_REG_8812_end - data_PHY_REG_8812_start); + } else { +#ifdef HIGH_POWER_EXT_PA +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + printk("[%s][PHY_REG_8812_n_hp]\n", __FUNCTION__); + next_head = data_PHY_REG_8812_n_hp_start; + read_bytes = (int)(data_PHY_REG_8812_n_hp_end - data_PHY_REG_8812_n_hp_start); + } else if (priv->pshare->rf_ft_var.use_ext_pa && !priv->pshare->rf_ft_var.use_ext_lna) { + printk("[%s][PHY_REG_8812_n_extpa]\n", __FUNCTION__); + next_head = data_PHY_REG_8812_n_extpa_start; + read_bytes = (int)(data_PHY_REG_8812_n_extpa_end - data_PHY_REG_8812_n_extpa_start); + } else if (!priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + printk("[%s][PHY_REG_8812_n_extlna]\n", __FUNCTION__); + next_head = data_PHY_REG_8812_n_extlna_start; + read_bytes = (int)(data_PHY_REG_8812_n_extlna_end - data_PHY_REG_8812_n_extlna_start); + } else +#else + if (priv->pshare->rf_ft_var.use_ext_pa) { + printk("[%s][PHY_REG_8812_n_hp]\n", __FUNCTION__); + next_head = data_PHY_REG_8812_n_hp_start; + read_bytes = (int)(data_PHY_REG_8812_n_hp_end - data_PHY_REG_8812_n_hp_start); + } else +#endif +#else +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + printk("[%s][PHY_REG_8812_n_extlna]\n", __FUNCTION__); + next_head = data_PHY_REG_8812_n_extlna_start; + read_bytes = (int)(data_PHY_REG_8812_n_extlna_end - data_PHY_REG_8812_n_extlna_start); + } else +#endif +#endif + { + printk("[%s][PHY_REG_8812_n_default]\n", __FUNCTION__); + next_head = data_PHY_REG_8812_n_default_start; + read_bytes = (int)(data_PHY_REG_8812_n_default_end - data_PHY_REG_8812_n_default_start); + } + } + } +#endif + } + + { + if ((mem_ptr = (unsigned char *)rtw_vmalloc(MAX_CONFIG_FILE_SIZE)) == NULL) { + printk("PHY_ConfigBBWithParaFile(): not enough memory\n"); + return -1; + } + + memset(mem_ptr, 0, MAX_CONFIG_FILE_SIZE); // clear memory + + memcpy(mem_ptr, next_head, read_bytes); + + next_head = mem_ptr; + while (1) { + line_head = next_head; + next_head = get_line(&line_head); + if (line_head == NULL) + break; + + if (line_head[0] == '/') + continue; + + if (file_format == TWO_COLUMN) { + num = get_offset_val(line_head, &u4bRegOffset, &u4bRegValue); + if (num > 0) { + phyreg_table[len].offset = u4bRegOffset; + phyreg_table[len].value = u4bRegValue; + len++; + + if ((len & 0x7ff) == 0) + watchdog_kick(); + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) { + if (u4bRegOffset == 0xffff) + break; + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (u4bRegOffset == 0xff) + break; + } + if ((len * sizeof(struct PhyRegTable)) > max_len) + break; + } + } else { + num = get_offset_mask_val(line_head, &u4bRegOffset, &u4bRegMask , &u4bRegValue); + if (num > 0) { + macreg_table[len].offset = u4bRegOffset; + macreg_table[len].mask = u4bRegMask; + macreg_table[len].value = u4bRegValue; + len++; +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) { + if (u4bRegOffset == 0xffff) + break; + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (u4bRegOffset == 0xff) + break; + } + if ((len * sizeof(struct MacRegTable)) > max_len) + break; + + if ((len & 0x7ff) == 0) + watchdog_kick(); + } + } + } + + rtw_vmfree(mem_ptr, MAX_CONFIG_FILE_SIZE); + + if ((len * sizeof(struct PhyRegTable)) > max_len) { + + printk("PHY REG table buffer not large enough!\n"); + + return -1; + } + } + + num = 0; + while (1) { + if (file_format == THREE_COLUMN) { + u4bRegOffset = macreg_table[num].offset; + u4bRegValue = macreg_table[num].value; + u4bRegMask = macreg_table[num].mask; + } else { + u4bRegOffset = phyreg_table[num].offset; + u4bRegValue = phyreg_table[num].value; + } + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv))) { + if (u4bRegOffset == 0xffff) + break; + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (u4bRegOffset == 0xff) + break; + } + + if (file_format == THREE_COLUMN) { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if (reg_file == PHYREG_PG && ( +#ifdef CONFIG_RTL_92D_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) +#ifdef CONFIG_RTL_92D_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (IS_HAL_CHIP(priv)) +#endif + )) { + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (pg_tbl_idx == 0) { + regstart = 0xc20; + regend = 0xe38; + } else { + regstart = 0xc24; + regend = 0xe4c; + } + printk("[%d]pg_tbl_idx=%d\n", __LINE__, pg_tbl_idx); + if (u4bRegOffset == regstart) { + if (idx == pg_tbl_idx) { + write_en = 1; + } + idx++; + } + if (write_en) { + PHY_SetBBReg(priv, u4bRegOffset, u4bRegMask, u4bRegValue); + if (u4bRegOffset == regend) { + write_en = 0; + break; + } + } + } else { + regstart = 0xe00; + regend = 0x868; + if (u4bRegOffset == regstart) { + if (idx == pg_tbl_idx) + write_en = 1; + idx++; + } + if (write_en) { + PHY_SetBBReg(priv, u4bRegOffset, u4bRegMask, u4bRegValue); + if (u4bRegOffset == regend) { + write_en = 0; + break; + } + } + } + } else +#endif + { + PHY_SetBBReg(priv, u4bRegOffset, u4bRegMask, u4bRegValue); + } + } else { + unsigned int tmp = RTL_R32(u4bRegOffset); + //PHY_SetBBReg(priv, u4bRegOffset, bMaskDWord, u4bRegValue); + + if (tmp != u4bRegValue) { +// printk("[0x%x] 0x%08x 0x%08x \n", u4bRegOffset, u4bRegValue, tmp); + PHY_SetBBReg(priv, u4bRegOffset, bMaskDWord, u4bRegValue); + } + } + num++; + } + + return 0; +} + +/* +static void phy_BB8192CD_Check_ParaFile(struct rtl8192cd_priv *priv) +{ + int rtStatus=0; + unsigned short val16; + unsigned int val32; + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A)) + rtStatus = PHY_CheckBBWithParaFile(priv, PHYREG); +#endif +} +*/ +#endif + +#ifdef CONFIG_WLAN_HAL +// TODO: Filen, comfirm register setting below +static int phy_BB88XX_Config_ParaFile(struct rtl8192cd_priv *priv) +{ + int rtStatus = 0; + unsigned short val16; + unsigned int val32; + + phy_InitBBRFRegisterDefinition(priv); + +#if defined(CONFIG_SDIO_HCI) && defined(HIGH_POWER_EXT_LNA) + if (priv->pshare->rf_ft_var.use_ext_lna) { + RTL_W8(0x11, 0xeb); + RTL_W8(0x12, 0x07); + RTL_W8(0x14, 0x75); + } +#endif + + // Enable BB and RF + val16 = RTL_R16(REG_SYS_FUNC_EN); + RTL_W16(REG_SYS_FUNC_EN, val16 | BIT(13) | BIT(0) | BIT(1)); + + RTL_W8(REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + + /*----Check chip ID and hw TR MIMO config----*/ +// check_chipID_MIMO(priv); + +#if 0// eric-8814 def CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv) ) { + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { +#if defined(CONFIG_MACBBRF_BY_ODM) + printk("%s(%d), HAL PHY_ConfigBBWithParaFile\n", __FUNCTION__, __LINE__); + rtStatus = ODM_ConfigBBWithHeaderFile(ODMPTR, CONFIG_BB_PHY_REG); +#else + printk("%s(%d), HAL PHY_ConfigBBWithParaFile\n", __FUNCTION__, __LINE__); + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG); +#endif + } +#endif //CONFIG_WLAN_HAL_8192EE + +#if defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + if ((GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + printk("%s(%d), HAL PHY_ConfigBBWithParaFile\n", __FUNCTION__, __LINE__); + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG); + } +#endif //CONFIG_WLAN_HAL_8881A + } +#endif //CONFIG_WLAN_HAL + + if(ODMPTR->ConfigBBRF) + rtStatus = ODM_ConfigBBWithHeaderFile(ODMPTR, CONFIG_BB_PHY_REG); + else + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG); + +#if 1 //Filen, BB have no release these files +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) { + delay_ms(10); + if(ODMPTR->ConfigBBRF) + rtStatus |= ODM_ConfigBBWithHeaderFile(ODMPTR, CONFIG_BB_PHY_REG_MP); + else + rtStatus |= PHY_ConfigBBWithParaFile(priv, PHYREG_MP); + } +#endif + + if (rtStatus) { + printk("phy_BB88XX_Config_ParaFile(): PHYREG_MP Reg Fail!!\n"); + return rtStatus; + } + + /*----If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt----*/ + if (0) + rtStatus = ODM_ConfigBBWithHeaderFile(ODMPTR, CONFIG_BB_PHY_REG_PG); + else + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG_PG); + + if (rtStatus) { + printk("phy_BB88XX_Config_ParaFile():BB_PG Reg Fail!!\n"); + return rtStatus; + } +#endif + + /*----BB AGC table Initialization----*/ + if(ODMPTR->ConfigBBRF) + rtStatus = ODM_ConfigBBWithHeaderFile(ODMPTR, CONFIG_BB_AGC_TAB); + else + rtStatus = PHY_ConfigBBWithParaFile(priv, AGCTAB); + + if (rtStatus) { + printk("phy_BB8192CD_Config_ParaFile(): Write BB AGC Table Fail!!\n"); + return rtStatus; + } + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn, 1); + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, 1); + } +#endif //CONFIG_WLAN_HAL_8192EE + + if(ODMPTR->ConfigBBRF) + priv->pshare->PhyVersion = ODM_GetHWImgVersion(ODMPTR); + DEBUG_INFO("PHY-BB Initialization Success\n"); + + return 0; +} +#endif //#ifdef CONFIG_WLAN_HAL + +#if(CONFIG_WLAN_NOT_HAL_EXIST==1) +static int phy_BB8192CD_Config_ParaFile(struct rtl8192cd_priv *priv) +{ + int rtStatus = 0; + unsigned short val16; + unsigned int val32; + + phy_InitBBRFRegisterDefinition(priv); + + // Enable BB and RF + val16 = RTL_R16(REG_SYS_FUNC_EN); + RTL_W16(REG_SYS_FUNC_EN, val16 | BIT(13) | BIT(0) | BIT(1)); + + // 20090923 Joseph: Advised by Steven and Jenyu. Power sequence before init RF. +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + ) { + RTL_W8(REG_AFE_PLL_CTRL, 0x83); + RTL_W8(REG_AFE_PLL_CTRL + 1, 0xdb); + } +#endif + RTL_W8(REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + RTL_W8(0x76, 0x7); //enable RF Path B +#endif + +#if defined(CONFIG_PCI_HCI) + //RTL_W8(REG_SYS_FUNC_EN, FEN_PPLL|FEN_PCIEA|FEN_DIO_PCIE|FEN_USBA|FEN_BB_GLB_RST|FEN_BBRSTB); + //RTL_W8(REG_LDOHCI12_CTRL, 0x1f); +#elif defined(CONFIG_SDIO_HCI) + RTL_W8(REG_SYS_FUNC_EN, FEN_PPLL|FEN_PCIEA|FEN_DIO_PCIE|FEN_BB_GLB_RST|FEN_BBRSTB); +#endif + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + ) { + RTL_W8(REG_AFE_XTAL_CTRL + 1, 0x80); + + val32 = RTL_R32(REG_AFE_XTAL_CTRL); + val32 = (val32 & (~(BIT(11) | BIT(14)))) | (BIT(18) | BIT(19) | BIT(21) | BIT(22)); + RTL_W32(REG_AFE_XTAL_CTRL, val32); + } + +#endif + + /*----Check chip ID and hw TR MIMO config----*/ +// check_chipID_MIMO(priv); +#ifdef USE_OUT_SRC + if(ODMPTR->ConfigBBRF) + rtStatus = ODM_ConfigBBWithHeaderFile(ODMPTR, CONFIG_BB_PHY_REG); + else +#endif + { + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) + { + if (get_rf_mimo_mode(priv) == MIMO_2T2R) + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG_2T2R); + else if (get_rf_mimo_mode(priv) == MIMO_1T1R) + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG_1T1R); + } + else + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG); + } + +#ifdef MP_TEST + if ((priv->pshare->rf_ft_var.mp_specific) +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + && ( +#ifdef CONFIG_RTL_92C_SUPPORT + !IS_TEST_CHIP(priv) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + ) +#endif + ) { + delay_ms(10); +#ifdef USE_OUT_SRC + if(ODMPTR->ConfigBBRF) + rtStatus |= ODM_ConfigBBWithHeaderFile(ODMPTR, CONFIG_BB_PHY_REG_MP); + else +#endif + rtStatus |= PHY_ConfigBBWithParaFile(priv, PHYREG_MP); + } +#endif + + if (rtStatus) { + printk("phy_BB8192CD_Config_ParaFile(): Write BB Reg Fail!!\n"); + return rtStatus; + } + + /*----If EEPROM or EFUSE autoload OK, We must config by PHY_REG_PG.txt----*/ +#ifdef USE_OUT_SRC + if (0) + rtStatus = ODM_ConfigBBWithHeaderFile(ODMPTR, CONFIG_BB_PHY_REG_PG); + else +#endif + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG_PG); + + if (rtStatus) { + printk("phy_BB8192CD_Config_ParaFile():BB_PG Reg Fail!!\n"); + return rtStatus; + } + + /*----BB AGC table Initialization----*/ +#ifdef CONFIG_RTL_92D_SUPPORT + + if (GET_CHIP_VER(priv) == VERSION_8192D) + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn | bCCKEn, 0); +#endif +#ifdef USE_OUT_SRC + if(ODMPTR->ConfigBBRF) + rtStatus = ODM_ConfigBBWithHeaderFile(ODMPTR, CONFIG_BB_AGC_TAB); + else +#endif + rtStatus = PHY_ConfigBBWithParaFile(priv, AGCTAB); + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) != VERSION_8812E) +#endif + { + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn, 1); +#ifdef CONFIG_RTL_92D_SUPPORT + if (!(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) + +#endif + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, 1); + } + + if (rtStatus) { + printk("phy_BB8192CD_Config_ParaFile(): Write BB AGC Table Fail!!\n"); + return rtStatus; + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + // Check if the CCK HighPower is turned ON. + // This is used to calculate PWDB. + priv->pshare->phw->reg824_bit9 = (unsigned char)PHY_QueryBBReg(priv, rFPGA0_XA_HSSIParameter2, 0x200); +#endif + +#if 0 + /*----For 1T2R Config----*/ + if (get_rf_mimo_mode(priv) == MIMO_1T2R) { + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG_1T2R); + if (rtStatus) { + printk("phy_BB8192CD_Config_ParaFile(): Write BB Reg for 1T2R Fail!!\n"); + return rtStatus; + } + } else if (get_rf_mimo_mode(priv) == MIMO_1T1R) { + delay_ms(100); + rtStatus = PHY_ConfigBBWithParaFile(priv, PHYREG_1T1R); + if (rtStatus) { + printk("phy_BB8192CD_Config_ParaFile(): Write BB Reg for 1T1R Fail!!\n"); + return rtStatus; + } + } +#endif + + DEBUG_INFO("PHY-BB Initialization Success\n"); + return 0; +} +#else +static int phy_BB8192CD_Config_ParaFile(struct rtl8192cd_priv *priv) +{ + return 0; +} +#endif//CONFIG_WLAN_NOT_HAL_EXIST + +#if 1 +//#if !defined(CONFIG_MACBBRF_BY_ODM) || !defined(CONFIG_RTL_88E_SUPPORT) + +int phy_RF6052_Config_ParaFile(struct rtl8192cd_priv *priv) +{ + int rtStatus = 0; + RF92CD_RADIO_PATH_E eRFPath; + BB_REGISTER_DEFINITION_T *pPhyReg; + unsigned int u4RegValue = 0; +#ifndef SMP_SYNC + unsigned long x; +#endif + +#ifdef CONFIG_WLAN_HAL +#if defined(HIGH_POWER_EXT_PA) && defined(HIGH_POWER_EXT_LNA) + HW_VARIABLES RF_REG_FILE_RADIO_HP_SIZE[RF92CD_PATH_MAX] = { + HW_VAR_RFREGFILE_RADIO_A_HP_SIZE, HW_VAR_RFREGFILE_RADIO_B_HP_SIZE, +#ifdef CONFIG_WLAN_HAL_8814AE + HW_VAR_RFREGFILE_RADIO_C_HP_SIZE, HW_VAR_RFREGFILE_RADIO_D_HP_SIZE +#endif + }; + HW_VARIABLES RF_REG_FILE_RADIO_HP_START[RF92CD_PATH_MAX] = { + HW_VAR_RFREGFILE_RADIO_A_HP_START, HW_VAR_RFREGFILE_RADIO_B_HP_START, +#ifdef CONFIG_WLAN_HAL_8814AE + HW_VAR_RFREGFILE_RADIO_C_HP_START, HW_VAR_RFREGFILE_RADIO_D_HP_START +#endif + }; +#endif // HIGH_POWER_EXT_PA && HIGH_POWER_EXT_LNA + + HW_VARIABLES RF_REG_FILE_RADIO_SIZE[RF92CD_PATH_MAX] = { + HW_VAR_RFREGFILE_RADIO_A_SIZE, HW_VAR_RFREGFILE_RADIO_B_SIZE, +#ifdef CONFIG_WLAN_HAL_8814AE + HW_VAR_RFREGFILE_RADIO_C_SIZE, HW_VAR_RFREGFILE_RADIO_D_SIZE +#endif + }; + HW_VARIABLES RF_REG_FILE_RADIO_START[RF92CD_PATH_MAX] = { + HW_VAR_RFREGFILE_RADIO_A_START, HW_VAR_RFREGFILE_RADIO_B_START, +#ifdef CONFIG_WLAN_HAL_8814AE + HW_VAR_RFREGFILE_RADIO_C_START, HW_VAR_RFREGFILE_RADIO_D_START +#endif + }; + +#ifdef HIGH_POWER_EXT_PA + HW_VARIABLES RF_REG_FILE_RADIO_EXTPA_SIZE[RF92CD_PATH_MAX] = { + HW_VAR_RFREGFILE_RADIO_A_EXTPA_SIZE, HW_VAR_RFREGFILE_RADIO_B_EXTPA_SIZE, +#ifdef CONFIG_WLAN_HAL_8814AE + HW_VAR_RFREGFILE_RADIO_C_EXTPA_SIZE, HW_VAR_RFREGFILE_RADIO_D_EXTPA_SIZE +#endif + }; + HW_VARIABLES RF_REG_FILE_RADIO_EXTPA_START[RF92CD_PATH_MAX] = { + HW_VAR_RFREGFILE_RADIO_A_EXTPA_START, HW_VAR_RFREGFILE_RADIO_B_EXTPA_START, +#ifdef CONFIG_WLAN_HAL_8814AE + HW_VAR_RFREGFILE_RADIO_C_EXTPA_START, HW_VAR_RFREGFILE_RADIO_D_EXTPA_START +#endif + }; +#endif // HIGH_POWER_EXT_PA + +#ifdef HIGH_POWER_EXT_LNA + HW_VARIABLES RF_REG_FILE_RADIO_EXTLNA_SIZE[RF92CD_PATH_MAX] = { + HW_VAR_RFREGFILE_RADIO_A_EXTLNA_SIZE, HW_VAR_RFREGFILE_RADIO_B_EXTLNA_SIZE, +#ifdef CONFIG_WLAN_HAL_8814AE + HW_VAR_RFREGFILE_RADIO_C_EXTLNA_SIZE, HW_VAR_RFREGFILE_RADIO_D_EXTLNA_SIZE +#endif + }; + + HW_VARIABLES RF_REG_FILE_RADIO_EXTLNA_START[RF92CD_PATH_MAX] = { + HW_VAR_RFREGFILE_RADIO_A_EXTLNA_START, HW_VAR_RFREGFILE_RADIO_B_EXTLNA_START, +#ifdef CONFIG_WLAN_HAL_8814AE + HW_VAR_RFREGFILE_RADIO_C_EXTLNA_START, HW_VAR_RFREGFILE_RADIO_D_EXTLNA_START +#endif + }; +#endif // HIGH_POWER_EXT_LNA +#endif // CONFIG_WLAN_HAL + +// SAVE_INT_AND_CLI(x); + +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY)) + priv->pshare->phw->NumTotalRFPath = 1; + else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + priv->pshare->phw->NumTotalRFPath = 1; + else +#endif +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_NUM_TOTAL_RF_PATH, (pu1Byte)&priv->pshare->phw->NumTotalRFPath); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + priv->pshare->phw->NumTotalRFPath = 2; + + for (eRFPath = RF92CD_PATH_A; eRFPath < priv->pshare->phw->NumTotalRFPath; eRFPath++) { + pPhyReg = &priv->pshare->phw->PHYRegDef[eRFPath]; + + /*----Store original RFENV control type----*/ + switch (eRFPath) { + case RF92CD_PATH_A: + u4RegValue = PHY_QueryBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV); + break; + case RF92CD_PATH_B : + u4RegValue = PHY_QueryBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV << 16); + break; +#ifdef CONFIG_WLAN_HAL_8814AE + case RF92CD_PATH_C: + // TODO: 8814AE BB/RF + break; + case RF92CD_PATH_D: + break; +#endif + case RF92CD_PATH_MAX: + break; + } + + /*----Set RF_ENV enable----*/ + PHY_SetBBReg(priv, pPhyReg->rfintfe, bRFSI_RFENV << 16, 0x1); + + /*----Set RF_ENV output high----*/ + PHY_SetBBReg(priv, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); + + /* Set bit number of Address and Data for RF register */ + PHY_SetBBReg(priv, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); + PHY_SetBBReg(priv, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); + + /*----Initialize RF fom connfiguration file----*/ +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + switch (eRFPath) { + case RF92CD_PATH_A: +#ifdef CONFIG_RTL_92D_DMDP + if ((priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) && + (priv->pshare->wlandev_idx == 1)) { +#ifdef RTL8192D_INT_PA + if (priv->pshare->rf_ft_var.use_intpa92d) { +#ifdef USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) + printk("[%s][radio_b_intPA_GM_new]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_GM_new_start, + (int)(data_radio_b_intPA_GM_new_end - data_radio_b_intPA_GM_new_start), eRFPath); +#elif defined (RTL8192D_INT_PA_GAIN_TABLE_NEW1) + printk("[%s][radio_b_intPA_GM_new1]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_GM_new1_start, + (int)(data_radio_b_intPA_GM_new1_end - data_radio_b_intPA_GM_new1_start), eRFPath); +#else + printk("[%s][radio_b_intPA_GM]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_GM_start, + (int)(data_radio_b_intPA_GM_end - data_radio_b_intPA_GM_start), eRFPath); +#endif + +#else //USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) + printk("[%s][radio_b_intPA_new]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_new_start, + (int)(data_radio_b_intPA_new_end - data_radio_b_intPA_new_start), eRFPath); +#else + printk("[%s][radio_b_intPA]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_start, + (int)(data_radio_b_intPA_end - data_radio_b_intPA_start), eRFPath); +#endif + +#endif //USB_POWER_SUPPORT + + } else +#endif + { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + printk("[%s][radio_b_n_92d_hp]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_n_92d_hp_start, + (int)(data_radio_b_n_92d_hp_end - data_radio_b_n_92d_hp_start), eRFPath); + } else +#endif + { + printk("[%s] [radio_b_n]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_n_start, + (int)(data_radio_b_n_end - data_radio_b_n_start), eRFPath); + } + } + } else +#endif + { +#ifdef RTL8192D_INT_PA + if (priv->pshare->rf_ft_var.use_intpa92d) { +#ifdef USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) + printk("[%s][radio_a_intPA_GM_new]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_intPA_GM_new_start, + (int)(data_radio_a_intPA_GM_new_end - data_radio_a_intPA_GM_new_start), eRFPath); +#elif defined (RTL8192D_INT_PA_GAIN_TABLE_NEW1) + printk("[%s][radio_a_intPA_GM_new1]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_intPA_GM_new1_start, + (int)(data_radio_a_intPA_GM_new1_end - data_radio_a_intPA_GM_new1_start), eRFPath); +#else + printk("[%s][radio_a_intPA_GM]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_intPA_GM_start, + (int)(data_radio_a_intPA_GM_end - data_radio_a_intPA_GM_start), eRFPath); +#endif + +#else //USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) + + printk("[%s][radio_a_intPA_new]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_intPA_new_start, + (int)(data_radio_a_intPA_new_end - data_radio_a_intPA_new_start), eRFPath); + +#else + printk("[%s][radio_a_intPA]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_intPA_start, + (int)(data_radio_a_intPA_end - data_radio_a_intPA_start), eRFPath); +#endif + +#endif //USB_POWER_SUPPORT + } else +#endif + { +//_TXPWR_REDEFINE +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + printk("[%s][radio_a_n_92d_hp]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_n_92d_hp_start, + (int)(data_radio_a_n_92d_hp_end - data_radio_a_n_92d_hp_start), eRFPath); + } else +#endif + { + printk("[%s][radio_a_n]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_n_start, + (int)(data_radio_a_n_end - data_radio_a_n_start), eRFPath); + } + } + } + break; + case RF92CD_PATH_B: +#ifdef RTL8192D_INT_PA + if (priv->pshare->rf_ft_var.use_intpa92d) { +#ifdef USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) + printk("[%s][radio_b_intPA_GM_new]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_GM_new_start, + (int)(data_radio_b_intPA_GM_new_end - data_radio_b_intPA_GM_new_start), eRFPath); +#elif defined (RTL8192D_INT_PA_GAIN_TABLE_NEW1) + printk("[%s][radio_b_intPA_GM_new1]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_GM_new1_start, + (int)(data_radio_b_intPA_GM_new1_end - data_radio_b_intPA_GM_new1_start), eRFPath); +#else + printk("[%s][radio_b_intPA_GM]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_GM_start, + (int)(data_radio_b_intPA_GM_end - data_radio_b_intPA_GM_start), eRFPath); +#endif + + +#else //USB_POWER_SUPPORT + +#if defined (RTL8192D_INT_PA_GAIN_TABLE_NEW) + printk("[%s][radio_b_intPA_new]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_new_start, + (int)(data_radio_b_intPA_new_end - data_radio_b_intPA_new_start), eRFPath); +#else + printk("[%s][radio_b_intPA]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_intPA_start, + (int)(data_radio_b_intPA_end - data_radio_b_intPA_start), eRFPath); +#endif + +#endif //USB_POWER_SUPPORT + } else +#endif + { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + printk("[%s][radio_b_n_92d_hp]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_n_92d_hp_start, + (int)(data_radio_b_n_92d_hp_end - data_radio_b_n_92d_hp_start), eRFPath); + } else +#endif + { + printk("[%s][radio_b_n]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_n_start, + (int)(data_radio_b_n_end - data_radio_b_n_start), eRFPath); + } + } + break; + default: + break; + } + } +#endif //!CONFIG_RTL_92D_SUPPORT +#if defined(CONFIG_RTL_92C_SUPPORT) + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + switch (eRFPath) { + case RF92CD_PATH_A: + if (get_rf_mimo_mode(priv) == MIMO_2T2R) { +#ifdef TESTCHIP_SUPPORT + if (IS_TEST_CHIP(priv)) + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_2T_start, + (int)(data_radio_a_2T_end - data_radio_a_2T_start), eRFPath); + else +#endif + { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + //printk("[%s][data_radio_a_2T_n_hp]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_2T_n_hp_start, + (int)(data_radio_a_2T_n_hp_end - data_radio_a_2T_n_hp_start), eRFPath); + } else +#endif +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + //printk("[%s][data_radio_a_2T_n_lna]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_2T_n_lna_start, + (int)(data_radio_a_2T_n_lna_end - data_radio_a_2T_n_lna_start), eRFPath); + } else +#endif + { + //printk("[%s][data_radio_a_2T_n]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_2T_n_start, + (int)(data_radio_a_2T_n_end - data_radio_a_2T_n_start), eRFPath); + } + } + } else if (get_rf_mimo_mode(priv) == MIMO_1T1R) { +#ifdef TESTCHIP_SUPPORT + if (IS_TEST_CHIP(priv)) + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_1T_start, + (int)(data_radio_a_1T_end - data_radio_a_1T_start), eRFPath); + else +#endif + { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + //printk("[%s][data_radio_a_2T_n_hp]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_2T_n_hp_start, + (int)(data_radio_a_2T_n_hp_end - data_radio_a_2T_n_hp_start), eRFPath); + } else +#endif + { + //printk("[%s][data_radio_a_1T_n]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_a_1T_n_start, + (int)(data_radio_a_1T_n_end - data_radio_a_1T_n_start), eRFPath); + } + + } + } + break; + case RF92CD_PATH_B: + if (get_rf_mimo_mode(priv) == MIMO_2T2R) { +#ifdef TESTCHIP_SUPPORT + if (IS_TEST_CHIP(priv)) + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_2T_start, + (int)(data_radio_b_2T_end - data_radio_b_2T_start), eRFPath); + else +#endif + { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + //printk("[%s][data_radio_b_2T_n_hp]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_2T_n_hp_start, + (int)(data_radio_b_2T_n_hp_end - data_radio_b_2T_n_hp_start), eRFPath); + } else +#endif +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + //printk("[%s][data_radio_b_2T_n_lna]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_2T_n_lna_start, + (int)(data_radio_b_2T_n_lna_end - data_radio_b_2T_n_lna_start), eRFPath); + } else +#endif + { + //printk("[%s][data_radio_b_2T_n]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_radio_b_2T_n_start, + (int)(data_radio_b_2T_n_end - data_radio_b_2T_n_start), eRFPath); + } + } + } else if (get_rf_mimo_mode(priv) == MIMO_1T1R) + rtStatus = 0; + break; + default: + break; + } + } +#endif + + + +#ifdef CONFIG_RTL_8812_SUPPORT //data radio + if (GET_CHIP_VER(priv) == VERSION_8812E) { + switch (eRFPath) { + case RF92CD_PATH_A://for_8812_mp_chip + if (IS_TEST_CHIP(priv)) { +#ifdef HIGH_POWER_EXT_PA //FOR_8812_HP + if ( priv->pshare->rf_ft_var.use_ext_pa) { + printk("[RadioA_8812_hp]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioA_8812_hp_start, + (int)(data_RadioA_8812_hp_end - data_RadioA_8812_hp_start), eRFPath); + } else +#endif + { + printk("[RadioA_8812]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioA_8812_start, + (int)(data_RadioA_8812_end - data_RadioA_8812_start), eRFPath); + } + } else { +#ifdef HIGH_POWER_EXT_PA +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + if (priv->pmib->dot11RFEntry.pa_type == PA_SKYWORKS_5023 || priv->pmib->dot11RFEntry.pa_type == PA_SKYWORKS_85712_HP) { + panic_printk("[RadioA_8812_n_ultra_hp]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioA_8812_n_ultra_hp_start, + (int)(data_RadioA_8812_n_ultra_hp_end - data_RadioA_8812_n_ultra_hp_start), eRFPath); + } else { + panic_printk("[RadioA_8812_n_hp]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioA_8812_n_hp_start, + (int)(data_RadioA_8812_n_hp_end - data_RadioA_8812_n_hp_start), eRFPath); + } + } else if (priv->pshare->rf_ft_var.use_ext_pa && !priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[RadioA_8812_n_extpa]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioA_8812_n_extpa_start, + (int)(data_RadioA_8812_n_extpa_end - data_RadioA_8812_n_extpa_start), eRFPath); + } else if (!priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[RadioA_8812_n_extlna]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioA_8812_n_extlna_start, + (int)(data_RadioA_8812_n_extlna_end - data_RadioA_8812_n_extlna_start), eRFPath); + } else +#else + if (priv->pshare->rf_ft_var.use_ext_pa) { + panic_printk("[RadioA_8812_n_extpa]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioA_8812_n_extpa_start, + (int)(data_RadioA_8812_n_extpa_end - data_RadioA_8812_n_extpa_start), eRFPath); + } else +#endif +#else +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[RadioA_8812_n_extlna]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioA_8812_n_extlna_start, + (int)(data_RadioA_8812_n_extlna_end - data_RadioA_8812_n_extlna_start), eRFPath); + + } else +#endif +#endif + { + panic_printk("[RadioA_8812_n_default]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioA_8812_n_default_start, + (int)(data_RadioA_8812_n_default_end - data_RadioA_8812_n_default_start), eRFPath); + } + } + break; + case RF92CD_PATH_B: + if (IS_TEST_CHIP(priv)) { +#ifdef HIGH_POWER_EXT_PA //FOR_8812_HP + if ( priv->pshare->rf_ft_var.use_ext_pa) { + panic_printk("[RadioB_8812_hp]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioB_8812_hp_start, + (int)(data_RadioB_8812_hp_end - data_RadioB_8812_hp_start), eRFPath); + } else +#endif + { + panic_printk("[RadioB_8812]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioB_8812_start, + (int)(data_RadioB_8812_end - data_RadioB_8812_start), eRFPath); + } + } else { +#ifdef HIGH_POWER_EXT_PA +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + if (priv->pmib->dot11RFEntry.pa_type == PA_SKYWORKS_5023 || priv->pmib->dot11RFEntry.pa_type == PA_SKYWORKS_85712_HP) { + panic_printk("[RadioB_8812_n_ultra_hp]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioB_8812_n_ultra_hp_start, + (int)(data_RadioB_8812_n_ultra_hp_end - data_RadioB_8812_n_ultra_hp_start), eRFPath); + } else { + panic_printk("[RadioB_8812_n_hp]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioB_8812_n_hp_start, + (int)(data_RadioB_8812_n_hp_end - data_RadioB_8812_n_hp_start), eRFPath); + } + } else if (priv->pshare->rf_ft_var.use_ext_pa && !priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[RadioB_8812_n_extpa]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioB_8812_n_extpa_start, + (int)(data_RadioB_8812_n_extpa_end - data_RadioB_8812_n_extpa_start), eRFPath); + } else if (!priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[RadioB_8812_n_extlna]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioB_8812_n_extlna_start, + (int)(data_RadioB_8812_n_extlna_end - data_RadioB_8812_n_extlna_start), eRFPath); + } else +#else + if (priv->pshare->rf_ft_var.use_ext_pa) { + panic_printk("[RadioB_8812_n_extpa]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioB_8812_n_extpa_start, + (int)(data_RadioB_8812_n_extpa_end - data_RadioB_8812_n_extpa_start), eRFPath); + } else +#endif +#else +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + panic_printk("[RadioB_8812_n_extlna]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioB_8812_n_extlna_start, + (int)(data_RadioB_8812_n_extlna_end - data_RadioB_8812_n_extlna_start), eRFPath); + } else +#endif +#endif + { + panic_printk("[RadioB_8812_n_default]\n"); + rtStatus = PHY_ConfigRFWithParaFile(priv, data_RadioB_8812_n_default_start, + (int)(data_RadioB_8812_n_default_end - data_RadioB_8812_n_default_start), eRFPath); + } + } + break; + default: + break; + } + } +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + pu4Byte FileStartPtr; + u4Byte FileLength; +#ifdef HIGH_POWER_EXT_PA +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + //printk("[%s][Radio_HAL_hp] path%d\n",__FUNCTION__,eRFPath+1); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_HP_SIZE[eRFPath], (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_HP_START[eRFPath], (pu1Byte)&FileStartPtr); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } else if (priv->pshare->rf_ft_var.use_ext_pa && !priv->pshare->rf_ft_var.use_ext_lna) { + //printk("[%s][Radio_HAL_extpa] path%d\n",__FUNCTION__,eRFPath+1); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_EXTPA_SIZE[eRFPath], (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_EXTPA_START[eRFPath], (pu1Byte)&FileStartPtr); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } else if (!priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { + //printk("[%s][Radio_HAL_extlna] path%d\n",__FUNCTION__,eRFPath+1); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_EXTLNA_SIZE[eRFPath], (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_EXTLNA_START[eRFPath], (pu1Byte)&FileStartPtr); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } else +#else + if (priv->pshare->rf_ft_var.use_ext_pa) { + //printk("[%s][Radio_HAL_extpa] path%d\n",__FUNCTION__,eRFPath+1); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_EXTPA_SIZE[eRFPath], (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_EXTPA_START[eRFPath], (pu1Byte)&FileStartPtr); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + }else +#endif //HIGH_POWER_EXT_LNA +#else +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + //printk("[%s][Radio_HAL_extlna] path%d\n",__FUNCTION__,eRFPath+1); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_EXTLNA_SIZE[eRFPath], (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_EXTLNA_START[eRFPath], (pu1Byte)&FileStartPtr); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } else +#endif +#endif //HIGH_POWER_EXT_PA + { + //printk("[%s][Radio_HAL] path%d\n",__FUNCTION__,eRFPath+1); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_SIZE[eRFPath], (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, RF_REG_FILE_RADIO_START[eRFPath], (pu1Byte)&FileStartPtr); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } +#if 0 // TODO: can be removed after 8814A test ok + switch (eRFPath) { + case RF92CD_PATH_A: +#ifdef HIGH_POWER_EXT_PA + if ( priv->pshare->rf_ft_var.use_ext_pa) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_A_HP_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_A_HP_START, (pu1Byte)&FileStartPtr); + printk("[%s][%s][RadioA_HAL_hp]\n", __FUNCTION__, ((GET_CHIP_VER(priv) == VERSION_8881A) ? "RTL_8881A" : "RTL_8192E")); + rtStatus = PHY_ConfigRFWithParaFile(priv, FileStartPtr, + (int)FileLength, eRFPath); + } else +#endif +#ifdef HIGH_POWER_EXT_LNA + if ( priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_A_EXTLNA_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_A_EXTLNA_START, (pu1Byte)&FileStartPtr); + printk("[%s][%s][RadioA_HAL_extlna]\n", __FUNCTION__, ((GET_CHIP_VER(priv) == VERSION_8881A) ? "RTL_8881A" : "RTL_8192E")); + rtStatus = PHY_ConfigRFWithParaFile(priv, FileStartPtr, + (int)FileLength, eRFPath); + } else +#endif + { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_A_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_A_START, (pu1Byte)&FileStartPtr); + printk("[%s][RadioA_HAL]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } + break; + case RF92CD_PATH_B: +#ifdef HIGH_POWER_EXT_PA + if ( priv->pshare->rf_ft_var.use_ext_pa) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_B_HP_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_B_HP_START, (pu1Byte)&FileStartPtr); + printk("[%s][%s][RadioB_HAL_hp]\n", __FUNCTION__, ((GET_CHIP_VER(priv) == VERSION_8881A) ? "RTL_8881A" : "RTL_8192E")); + rtStatus = PHY_ConfigRFWithParaFile(priv, FileStartPtr, + (int)FileLength, eRFPath); + } else +#endif +#ifdef HIGH_POWER_EXT_LNA + if ( priv->pshare->rf_ft_var.use_ext_lna) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_B_EXTLNA_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_B_EXTLNA_START, (pu1Byte)&FileStartPtr); + printk("[%s][%s][RadioB_HAL_extlna]\n", __FUNCTION__, ((GET_CHIP_VER(priv) == VERSION_8881A) ? "RTL_8881A" : "RTL_8192E")); + rtStatus = PHY_ConfigRFWithParaFile(priv, FileStartPtr, + (int)FileLength, eRFPath); + } else +#endif + { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_B_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_B_START, (pu1Byte)&FileStartPtr); + printk("[%s][RadioB_HAL]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, + (int)FileLength, eRFPath); + } + break; +#ifdef CONFIG_WLAN_HAL_8814AE +// TODO: 8814AE BB/RF + case RF92CD_PATH_C: +#ifdef HIGH_POWER_EXT_PA + if ( priv->pshare->rf_ft_var.use_ext_pa) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_C_HP_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_C_HP_START, (pu1Byte)&FileStartPtr); + printk("[%s][RadioC_HAL_hp]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } else +#endif + { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_C_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_C_START, (pu1Byte)&FileStartPtr); + printk("[%s][RadioC_HAL]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } + break; + // TODO: 8814AE BB/RF + case RF92CD_PATH_D: +#ifdef HIGH_POWER_EXT_PA + if ( priv->pshare->rf_ft_var.use_ext_pa) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_D_HP_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_D_HP_START, (pu1Byte)&FileStartPtr); + printk("[%s][RadioD_HAL_hp]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } else +#endif + { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_D_SIZE, (pu1Byte)&FileLength); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_RFREGFILE_RADIO_D_START, (pu1Byte)&FileStartPtr); + printk("[%s][RadioD_HAL]\n", __FUNCTION__); + rtStatus = PHY_ConfigRFWithParaFile(priv, (pu1Byte)FileStartPtr, (int)FileLength, eRFPath); + } + break; +#endif // CONFIG_WLAN_HAL_8814AE + + default: + break; + } +#endif // end if 0 + + } +#endif + + + + /*----Restore RFENV control type----*/; + switch (eRFPath) { + case RF92CD_PATH_A: + PHY_SetBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue); + break; + case RF92CD_PATH_B : + PHY_SetBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV << 16, u4RegValue); + break; +#ifdef CONFIG_WLAN_HAL_8814AE + // TODO: 8814AE BB/RF + case RF92CD_PATH_C: + break; + case RF92CD_PATH_D: + break; +#endif // CONFIG_WLAN_HAL_8814AE + case RF92CD_PATH_MAX: + break; + } + } + + DEBUG_INFO("PHY-RF Initialization Success\n"); + +// RESTORE_INT(x); + return rtStatus; +} +#endif + +// +// Description: +// Set the MAC offset [0x09] and prevent all I/O for a while (about 20us~200us, suggested from SD4 Scott). +// If the protection is not performed well or the value is not set complete, the next I/O will cause the system hang. +// Note: +// This procudure is designed specifically for 8192S and references the platform based variables +// which violates the stucture of multi-platform. +// Thus, we shall not extend this procedure to common handler. +// By Bruce, 2009-01-08. +// +unsigned char +HalSetSysClk8192CD( struct rtl8192cd_priv *priv, unsigned char Data) +{ + RTL_W8((SYS_CLKR + 1), Data); + delay_us(200); + return TRUE; +} + + +#ifdef CONFIG_RTL_8812_SUPPORT + +#define MAX_RX_DMA_BUFFER_SIZE_8812 0x3E80 //0x3FFF // RX 16K + + +static void LLT_table_init_8812(struct rtl8192cd_priv *priv) +{ + unsigned int i;//, maxPage = 255; + unsigned int count = 0; +// unsigned int value32; //High+low page number + unsigned char txpktbuf_bndy = 0xfc, bufBd = 0xff; + + + printk("=====>LLT_table_init_8812\n"); + + // 12. TXRKTBUG_PG_BNDY 0x114[31:0] = 0x27FF00F6 //TXRKTBUG_PG_BNDY + RTL_W8(TRXFF_BNDY, txpktbuf_bndy); + + RTL_W16(TRXFF_BNDY + 2, MAX_RX_DMA_BUFFER_SIZE_8812 - 1); + + // 13. TDECTRL[15:8] 0x209[7:0] = 0xF6 // Beacon Head for TXDMA + RTL_W8(TDECTRL + 1, txpktbuf_bndy); + + // 14. BCNQ_PGBNDY 0x424[7:0] = 0xF6 //BCNQ_PGBNDY + // 2009/12/03 Why do we set so large boundary. confilct with document V11. + RTL_W8(TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + RTL_W8(TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + + // 15. WMAC_LBK_BF_HD 0x45D[7:0] = 0xF6 //WMAC_LBK_BF_HD + RTL_W8(TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); + + // Set Tx/Rx page size (Tx must be 128 Bytes, Rx can be 64,128,256,512,1024 bytes) + // 16. PBP [7:0] = 0x11 // TRX page size + RTL_W8(PBP, 0x31); + + // 17. DRV_INFO_SZ = 0x04 + RTL_W8(RX_DRVINFO_SZ, 0x4); + + // 18. LLT_table_init(Adapter); + for ( i = 0; i < txpktbuf_bndy - 1; i++) { + RTL_W32(LLT_INI, ((LLTE_RWM_WR & LLTE_RWM_Mask) << LLTE_RWM_SHIFT) | (i & LLTINI_ADDR_Mask) << LLTINI_ADDR_SHIFT + | ((i + 1)&LLTINI_HDATA_Mask) << LLTINI_HDATA_SHIFT); + + count = 0; + do { + if (!(RTL_R32(LLT_INI) & ((LLTE_RWM_RD & LLTE_RWM_Mask) << LLTE_RWM_SHIFT))) + break; + if (++count >= 100) { + printk("LLT_init, section 01, i=%d\n", i); + printk("LLT Polling failed 01 !!!\n"); + return; + } + } while (count < 100); + } + + RTL_W32(LLT_INI, ((LLTE_RWM_WR & LLTE_RWM_Mask) << LLTE_RWM_SHIFT) + | ((txpktbuf_bndy - 1)&LLTINI_ADDR_Mask) << LLTINI_ADDR_SHIFT | (255 & LLTINI_HDATA_Mask) << LLTINI_HDATA_SHIFT); + + count = 0; + do { + if (!(RTL_R32(LLT_INI) & ((LLTE_RWM_RD & LLTE_RWM_Mask) << LLTE_RWM_SHIFT))) + break; + if (++count >= 100) { + printk("LLT Polling failed 02 !!!\n"); + return; + } + } while (count < 100); + + + for (i = txpktbuf_bndy; i < bufBd; i++) { + RTL_W32(LLT_INI, ((LLTE_RWM_WR & LLTE_RWM_Mask) << LLTE_RWM_SHIFT) | (i & LLTINI_ADDR_Mask) << LLTINI_ADDR_SHIFT + | ((i + 1)&LLTINI_HDATA_Mask) << LLTINI_HDATA_SHIFT); + + do { + if (!(RTL_R32(LLT_INI) & ((LLTE_RWM_RD & LLTE_RWM_Mask) << LLTE_RWM_SHIFT))) + break; + if (++count >= 100) { + printk("LLT Polling failed 03 !!!\n"); + return; + } + } while (count < 100); + } + + RTL_W32(LLT_INI, ((LLTE_RWM_WR & LLTE_RWM_Mask) << LLTE_RWM_SHIFT) | (bufBd & LLTINI_ADDR_Mask) << LLTINI_ADDR_SHIFT + | (txpktbuf_bndy & LLTINI_HDATA_Mask) << LLTINI_HDATA_SHIFT); + + count = 0; + do { + if (!(RTL_R32(LLT_INI) & ((LLTE_RWM_RD & LLTE_RWM_Mask) << LLTE_RWM_SHIFT))) + break; + if (++count >= 100) { + printk("LLT Polling failed 04 !!!\n"); + return; + } + } while (count < 100); + + + // Set reserved page for each queue + // 11. RQPN 0x200[31:0] = 0x80BD1C1C // load RQPN + + if (priv->pmib->dot11OperationEntry.wifi_specific != 0) { + RTL_W8(RQPN_NPQ, 0x29); + RTL_W32(RQPN, 0x80a92004); + } else { + RTL_W32(RQPN, 0x80EB0808);//0x80cb1010);//0x80711010);//0x80cb1010); + RTL_W8(RQPN_NPQ, 0x0); + } + + printk("LLT_table_init_8812<=====\n"); + + return; + +} + +#endif //CONFIG_RTL_8812_SUPPORT + +static void LLT_table_init(struct rtl8192cd_priv *priv) +{ + unsigned txpktbufSz, bufBd; + unsigned int i, count = 0; + +#ifdef CONFIG_PCI_HCI +#if 1 +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode != SINGLEMAC_SINGLEPHY) { + txpktbufSz = 120; //0x7C + bufBd = 127; + } else +#endif + { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { +#ifdef DRVMAC_LB + txpktbufSz = 83; // 0x53 + bufBd = 87; +#else + txpktbufSz = 171; // 0xAB + bufBd = 175; +#endif + } else +#endif + { + txpktbufSz = 246; // 0xF6 + bufBd = 255; + } + } +#else + unsigned txpktbufSz = 252; //174(0xAE) 120(0x78) 252(0xFC) +#endif +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_RTL_88E_SUPPORT) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + if (!priv->pmib->dot11OperationEntry.wifi_specific) { + txpktbufSz = TX_PAGE_BOUNDARY_88E; + } else { + txpktbufSz = WMM_NORMAL_TX_PAGE_BOUNDARY_88E; + } + bufBd = LAST_ENTRY_OF_TX_PKT_BUFFER_88E; +#endif + + for ( i = 0; i < txpktbufSz - 1; i++) { + RTL_W32(LLT_INI, ((LLTE_RWM_WR & LLTE_RWM_Mask) << LLTE_RWM_SHIFT) | (i & LLTINI_ADDR_Mask) << LLTINI_ADDR_SHIFT + | ((i + 1)&LLTINI_HDATA_Mask) << LLTINI_HDATA_SHIFT); + + count = 0; + do { + if (!(RTL_R32(LLT_INI) & ((LLTE_RWM_RD & LLTE_RWM_Mask) << LLTE_RWM_SHIFT))) + break; + if (++count >= 100) { + printk("LLT_init, section 01, i=%d\n", i); + printk("LLT Polling failed 01 !!!\n"); + return; + } + } while (count < 100); + } + + RTL_W32(LLT_INI, ((LLTE_RWM_WR & LLTE_RWM_Mask) << LLTE_RWM_SHIFT) + | ((txpktbufSz - 1)&LLTINI_ADDR_Mask) << LLTINI_ADDR_SHIFT | (255 & LLTINI_HDATA_Mask) << LLTINI_HDATA_SHIFT); + + count = 0; + do { + if (!(RTL_R32(LLT_INI) & ((LLTE_RWM_RD & LLTE_RWM_Mask) << LLTE_RWM_SHIFT))) + break; + if (++count >= 100) { + printk("LLT Polling failed 02 !!!\n"); + return; + } + } while (count < 100); + + + for (i = txpktbufSz; i < bufBd; i++) { + RTL_W32(LLT_INI, ((LLTE_RWM_WR & LLTE_RWM_Mask) << LLTE_RWM_SHIFT) | (i & LLTINI_ADDR_Mask) << LLTINI_ADDR_SHIFT + | ((i + 1)&LLTINI_HDATA_Mask) << LLTINI_HDATA_SHIFT); + + do { + if (!(RTL_R32(LLT_INI) & ((LLTE_RWM_RD & LLTE_RWM_Mask) << LLTE_RWM_SHIFT))) + break; + if (++count >= 100) { + printk("LLT Polling failed 03 !!!\n"); + return; + } + } while (count < 100); + } + + RTL_W32(LLT_INI, ((LLTE_RWM_WR & LLTE_RWM_Mask) << LLTE_RWM_SHIFT) | (bufBd & LLTINI_ADDR_Mask) << LLTINI_ADDR_SHIFT + | (txpktbufSz & LLTINI_HDATA_Mask) << LLTINI_HDATA_SHIFT); + + count = 0; + do { + if (!(RTL_R32(LLT_INI) & ((LLTE_RWM_RD & LLTE_RWM_Mask) << LLTE_RWM_SHIFT))) + break; + if (++count >= 100) { + printk("LLT Polling failed 04 !!!\n"); + return; + } + } while (count < 100); + +// Set reserved page for each queue + +#ifdef CONFIG_PCI_HCI +#if 1 + /* normal queue init MUST be previoius of RQPN enable */ + //RTL_W8(RQPN_NPQ, 4); //RQPN_NPQ +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode != SINGLEMAC_SINGLEPHY ) { + if (priv->pmib->dot11OperationEntry.wifi_specific == 1) { + RTL_W8(RQPN_NPQ, 0x29); + RTL_W32(RQPN, 0x802f1c04); + } else { + //RTL_W32(RQPN, 0x80501010); + RTL_W8(RQPN_NPQ, 0x10); + //RTL_W32(RQPN, 0x80630410); + RTL_W32(RQPN, 0x80600404); + } + } else +#endif + { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + //RTL_W8(RQPN_NPQ, 4); + RTL_W8(RQPN_NPQ, 0x29); +#ifdef DRVMAC_LB + RTL_W32(RQPN, 0x80460404); +#else + //RTL_W32(RQPN, 0x805d2029); + if (priv->pmib->dot11OperationEntry.wifi_specific == 1) + RTL_W32(RQPN, 0x805d2004); + else + RTL_W32(RQPN, 0x807d0004); +#endif + } else +#endif + { + RTL_W8(RQPN_NPQ, 0x29); + //RTL_W32(RQPN, 0x809f2929); + //RTL_W32(RQPN, 0x80a82029); +#ifdef DRVMAC_LB + RTL_W8(RQPN_NPQ + 2, 0x4); + RTL_W32(RQPN, 0x80380404); +#else + if (priv->pmib->dot11OperationEntry.wifi_specific == 0) { + RTL_W32(RQPN, 0x80C50404); + } else { + RTL_W32(RQPN, 0x80a92004); + } +#endif + } + } +#else + if (txpktbufSz == 120) + RTL_W32(RQPN, 0x80272828); + else if (txpktbufSz == 252) { + //RTL_W32(RQPN, 0x80c31c1c); + + // Joseph test + //RTL_W32(RQPN, 0x80838484); + RTL_W32(RQPN, 0x80bd1c1c); + } else + RTL_W32(RQPN, 0x80393a3a); +#endif +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_RTL_88E_SUPPORT) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + _InitQueueReservedPage(priv); +#endif + + //RTL_W32(TDECTRL, RTL_R32(TDECTRL)|(txpktbufSz&BCN_HEAD_Mask)<>"); + + RTL_W8(RSV_CTRL0, 0x00); +#if 0 + if(RTL_R8(RSV_CTRL0) == 0) + RTL_W8(SPS0_CTRL, (RTL_R8(SPS0_CTRL) & 0xc3) | 0x10); // b[5:2] = 4 + else + panic_printk("MAC reg unlock fail\n"); +#endif + + //Auto Power Down to CHIP-off State + bytetmp = RTL_R8(APS_FSMCO + 1); + bytetmp &= (~BIT(7)); //PlatformEFIORead1Byte(Adapter, REG_APS_FSMCO_8812+1) & (~BIT7) + RTL_W8(APS_FSMCO + 1, bytetmp); + + //printk("_eric HalPwrSeqCmdParsing +++ \n"); + //HW power on sequence + if (!HalPwrSeqCmdParsing(priv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, rtl8812_card_enable_flow)) + panic_printk("!!! [%s %d]HalPwrSeqCmdParsing init fail!!!\n", __FUNCTION__, __LINE__); + + //printk("_eric HalPwrSeqCmdParsing --- \n"); + +#if 0 + RTL_W32(0x500, 0x7f); + RTL_W32(0x504, 0x7f); + RTL_W32(0x508, 0x7f); + RTL_W32(0x50c, 0x7f); + + printk("0x%x, 0x%x, 0x%x, 0x%x \n", RTL_R32(0x500), RTL_R32(0x504), RTL_R32(0x508), RTL_R32(0x50c)); +#endif + + // Release MAC IO register reset + RTL_W32(CR, RTL_R32(CR) | MACRXEN | MACTXEN | SCHEDULE_EN | PROTOCOL_EN + | RXDMA_EN | TXDMA_EN | HCI_RXDMA_EN | HCI_TXDMA_EN); + delay_ms(2); + + RTL_W8(HWSEQ_CTRL, 0x7f); + delay_ms(2); + + + // Add for wakeup online + bytetmp = RTL_R8(SYS_CLKR); + bytetmp |= BIT(3); + RTL_W8(SYS_CLKR, bytetmp); + + bytetmp = RTL_R8(GPIO_MUXCFG + 1); + bytetmp &= (~BIT(4)); + RTL_W8(GPIO_MUXCFG + 1, bytetmp); + + + // Release MAC IO register reset + // 9. CR 0x100[7:0] = 0xFF; + // 10. CR 0x101[1] = 0x01; // Enable SEC block + RTL_W16(CR, 0x2ff); + + + //System init + LLT_table_init_8812(priv); + + //printk("\n\n 0x%.x, 0x%.8x \n\n\n", RTL_R32(0x200), RTL_R32(0x204)); + + // Enable interrupt + RTL_W32(REG_HISR0_8812, 0xffffffff); + RTL_W32(REG_HISR1_8812, 0xffffffff); + + Qbytetmp = RTL_R16(REG_TRXDMA_CTRL_8812); + Qbytetmp &= 0xf; + Qbytetmp |= 0x5663; //0xF5B1; + RTL_W16(REG_TRXDMA_CTRL_8812, Qbytetmp); + + + // Reported Tx status from HW for rate adaptive. + // 2009/12/03 MH This should be realtive to power on step 14. But in document V11 + // still not contain the description.!!! + RTL_W8(REG_FWHW_TXQ_CTRL_8812 + 1, 0x1F); + + // disable earlymode + RTL_W8(0x4d0, 0x0); + +#if 0 // 2012-07-06 +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + RTL_W32(TRXFF_BNDY, (RTL_R32(TRXFF_BNDY) & 0x0000FFFF) | (0x13ff & RXFF0_BNDY_Mask) << RXFF0_BNDY_SHIFT); + } else +#endif + { + // Set Rx FF0 boundary : 9K/10K + RTL_W32(TRXFF_BNDY, (RTL_R32(TRXFF_BNDY) & 0x0000FFFF) | (0x27FF & RXFF0_BNDY_Mask) << RXFF0_BNDY_SHIFT); + } +#endif +// RTL_W8(TDECTRL, 0x11); // need to confirm + + // Set Network type: ap mod + //RTL_W32(CR, RTL_R32(CR) | BIT(8)); + + RTL_W32(CR, RTL_R32(CR) | ((NETYPE_AP & NETYPE_Mask) << NETYPE_SHIFT)); + + // Set SLOT time + RTL_W8(SLOT_TIME, 0x09); + + // Set AMPDU min space + RTL_W8(AMPDU_MIN_SPACE, 0); // need to confirm + + // Set Tx/Rx page size (Tx must be 128 Bytes, Rx can be 64,128,256,512,1024 bytes) + //RTL_W8(PBP, (PBP_256B&PSTX_Mask)<pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + /* + * PHY_BAND_5G + */ + RTL_W16(RRSR, 0x150); + } else { + /* + * PHY_BAND_2G + */ + RTL_W16(RRSR, 0x15F); //Set 0x15F for NDSi Client Connection Issue + } + RTL_W8(RRSR + 2, 0); + + } + + // Set Spec SIFS (used in NAV) + // Joseph test + RTL_W16(SPEC_SIFS_A, (0x10 & SPEC_SIFS_OFDM_Mask) << SPEC_SIFS_OFDM_SHIFT + | (0x0A & SPEC_SIFS_CCK_Mask) << SPEC_SIFS_CCK_SHIFT); + + // Set SIFS for CCK + // Joseph test + RTL_W16(SIFS_CCK, (0x0E & SIFS_TRX_Mask) << SIFS_TRX_SHIFT | (0x0A & SIFS_CTX_Mask) << SIFS_CTX_SHIFT); + + // Set SIFS for OFDM + // Joseph test + RTL_W16(SIFS_OFDM, (0x0E & SIFS_TRX_Mask) << SIFS_TRX_SHIFT | (0x0A & SIFS_CTX_Mask) << SIFS_CTX_SHIFT); + + // Set retry limit + if (priv->pmib->dot11OperationEntry.dot11LongRetryLimit) + priv->pshare->RL_setting = priv->pmib->dot11OperationEntry.dot11LongRetryLimit & 0xff; + else { +#ifdef CLIENT_MODE + if (priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) + priv->pshare->RL_setting = 0x30; + else +#endif + priv->pshare->RL_setting = 0x10; + } + if (priv->pmib->dot11OperationEntry.dot11ShortRetryLimit) + priv->pshare->RL_setting |= ((priv->pmib->dot11OperationEntry.dot11ShortRetryLimit & 0xff) << 8); + else { +#ifdef CLIENT_MODE + if (priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) + priv->pshare->RL_setting |= (0x30 << 8); + else +#endif + priv->pshare->RL_setting |= (0x10 << 8); + } + RTL_W16(REG_RL_8812, priv->pshare->RL_setting); + + +#if 0 //eric_8812 ?? + + RTL_W16(TRXDMA_CTRL, (0xC660 | RXSHFT_EN | RXDMA_ARBBW_EN)); + //RTL_W8(PBP, (PBP_256B&PSTX_Mask)<pshare->phw->tx_bufringB_addr); + RTL_W32(REG_92E_MGQ_DESA, priv->pshare->phw->tx_bufring0_addr); + RTL_W32(REG_92E_VOQ_DESA, priv->pshare->phw->tx_bufring4_addr); + RTL_W32(REG_92E_VIQ_DESA, priv->pshare->phw->tx_bufring3_addr); + RTL_W32(REG_92E_BEQ_DESA, priv->pshare->phw->tx_bufring2_addr); + RTL_W32(REG_92E_BKQ_DESA, priv->pshare->phw->tx_bufring1_addr); + RTL_W32(REG_92E_HI0Q_DESA, priv->pshare->phw->tx_bufring5_addr); + + RTL_W32(REG_92E_HI1Q_DESA, priv->pshare->phw->tx_bufring6_addr); + RTL_W32(REG_92E_HI2Q_DESA, priv->pshare->phw->tx_bufring7_addr); + RTL_W32(REG_92E_HI3Q_DESA, priv->pshare->phw->tx_bufring8_addr); + RTL_W32(REG_92E_HI4Q_DESA, priv->pshare->phw->tx_bufring9_addr); + RTL_W32(REG_92E_HI5Q_DESA, priv->pshare->phw->tx_bufring10_addr); + RTL_W32(REG_92E_HI6Q_DESA, priv->pshare->phw->tx_bufring11_addr); + RTL_W32(REG_92E_HI7Q_DESA, priv->pshare->phw->tx_bufring12_addr); + + RTL_W32(RX_DESA, priv->pshare->phw->rx_ring_addr); + printk("0x%x,0x%x,0x%x,0x%x,0x%x\n", priv->pshare->phw->tx_bufring0_addr, priv->pshare->phw->tx_bufring1_addr, priv->pshare->phw->tx_bufring2_addr, priv->pshare->phw->tx_bufring3_addr, priv->pshare->phw->tx_bufring4_addr); + printk("1clean hw host point,0x%x,0x%x\n", priv->pshare->phw->tx_bufring5_addr, priv->pshare->phw->tx_bufringB_addr); + printk("2clean hw host point,0x%x,0x%x\n", priv->pshare->phw->tx_bufring6_addr, priv->pshare->phw->tx_bufring7_addr); + printk("3clean hw host point,0x%x,0x%x\n", priv->pshare->phw->tx_bufring8_addr, priv->pshare->phw->tx_bufring9_addr); + printk("4clean hw host point,0x%x,0x%x\n", priv->pshare->phw->tx_bufring10_addr, priv->pshare->phw->tx_bufring11_addr); + printk("5clean hw host point,0x%x,0x%x\n", priv->pshare->phw->tx_bufring12_addr, priv->pshare->phw->tx_bufringB_addr); + RTL_W32(REG_92E_ACQ_DES_NUM0, (((NUM_TX_DESC & ACQ_92E_VIQ_DESC_NUM_MASK) << ACQ_92E_VIQ_DESC_NUM_SHIFT) | ((NUM_TX_DESC & ACQ_92E_VOQ_DESC_NUM_MASK) << ACQ_92E_VOQ_DESC_NUM_SHIFT))); + RTL_W32(REG_92E_ACQ_DES_NUM1, (((NUM_TX_DESC & ACQ_92E_BKQ_DESC_NUM_MASK) << ACQ_92E_BKQ_DESC_NUM_SHIFT) | ((NUM_TX_DESC & ACQ_92E_BEQ_DESC_NUM_MASK) << ACQ_92E_BEQ_DESC_NUM_SHIFT))); + RTL_W32(REG_92E_HQ_DES_NUM0, (((NUM_TX_DESC & ACQ_92E_H1Q_DESC_NUM_MASK) << ACQ_92E_H1Q_DESC_NUM_SHIFT) | ((NUM_TX_DESC & ACQ_92E_H0Q_DESC_NUM_MASK) << ACQ_92E_H0Q_DESC_NUM_SHIFT))); + RTL_W32(REG_92E_HQ_DES_NUM1, (((NUM_TX_DESC & ACQ_92E_H3Q_DESC_NUM_MASK) << ACQ_92E_H3Q_DESC_NUM_SHIFT) | ((NUM_TX_DESC & ACQ_92E_H2Q_DESC_NUM_MASK) << ACQ_92E_H2Q_DESC_NUM_SHIFT))); + RTL_W32(REG_92E_HQ_DES_NUM2, (((NUM_TX_DESC & ACQ_92E_H5Q_DESC_NUM_MASK) << ACQ_92E_H5Q_DESC_NUM_SHIFT) | ((NUM_TX_DESC & ACQ_92E_H4Q_DESC_NUM_MASK) << ACQ_92E_H4Q_DESC_NUM_SHIFT))); + RTL_W32(REG_92E_HQ_DES_NUM3, (((NUM_TX_DESC & ACQ_92E_H7Q_DESC_NUM_MASK) << ACQ_92E_H7Q_DESC_NUM_SHIFT) | ((NUM_TX_DESC & ACQ_92E_H6Q_DESC_NUM_MASK) << ACQ_92E_H6Q_DESC_NUM_SHIFT))); + + RTL_W32(REG_92E_ACQ_DES_NUM2, (((NUM_RX_DESC & ACQ_92E_RXQ_DESC_NUM_MASK) << ACQ_92E_RXQ_DESC_NUM_SHIFT) | ((NUM_TX_DESC & ACQ_92E_MGQ_DESC_NUM_MASK) << ACQ_92E_MGQ_DESC_NUM_SHIFT))); + //RTL_W32(0x3be, 64); + RTL_W32(REG_92E_TSFT_CLRQ, CLRQ_92E_ALL_IDX); + RTL_W8(REG_92E_UPD_HGQMD, RTL_R8(REG_92E_UPD_HGQMD) | BIT(5) | BIT(4)); + //RTL_W16(0x3be, 64); + //RTL_W16(0x3b8, 64); + //RTL_W8(0x229, 0xf6); + //RTL_W8(0x457, 0xf6); + //RTL_W8(0x5a7,0xff); +#else + RTL_W32(BCNQ_DESA, priv->pshare->phw->tx_ringB_addr); + RTL_W32(MGQ_DESA, priv->pshare->phw->tx_ring0_addr); + RTL_W32(VOQ_DESA, priv->pshare->phw->tx_ring4_addr); + RTL_W32(VIQ_DESA, priv->pshare->phw->tx_ring3_addr); + RTL_W32(BEQ_DESA, priv->pshare->phw->tx_ring2_addr); + printk("BEQ_DESA = 0x%08x 0x%08x \n", RTL_R32(BEQ_DESA), (unsigned int)priv->pshare->phw->tx_ring2_addr); + RTL_W32(BKQ_DESA, priv->pshare->phw->tx_ring1_addr); + RTL_W32(HQ_DESA, priv->pshare->phw->tx_ring5_addr); + RTL_W32(RX_DESA, priv->pshare->phw->ring_dma_addr); +#endif + +// RTL_W32(RCDA, priv->pshare->phw->rxcmd_ring_addr); +// RTL_W32(TCDA, priv->pshare->phw->txcmd_ring_addr); +// RTL_W32(TCDA, phw->tx_ring5_addr); + // 2009/03/13 MH Prevent incorrect DMA write after accident reset !!! +// RTL_W16(CMDR, 0x37FC); + + + RTL_W32(PCIE_CTRL_REG, RTL_R32(PCIE_CTRL_REG) | (0x07 & MAX_RXDMA_Mask) << MAX_RXDMA_SHIFT + | (0x07 & MAX_TXDMA_Mask) << MAX_TXDMA_SHIFT | BCNQSTOP); + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5){ + RTL_W8(0x303,0x80); + } + // 20090928 Joseph + // Reconsider when to do this operation after asking HWSD. + RTL_W8(APSD_CTRL, RTL_R8(APSD_CTRL) & ~ BIT(6)); + retry = 0; + do { + retry++; + bytetmp = RTL_R8(APSD_CTRL); + } while ((retry < 200) && (bytetmp & BIT(7))); //polling until BIT7 is 0. by tynli + + if (bytetmp & BIT(7)) { + DEBUG_ERR("%s ERROR: APSD_CTRL=0x%02X\n", __FUNCTION__, bytetmp); + } + // disable BT_enable + RTL_W8(GPIO_MUXCFG, 0); + + + + printk("DONE\n"); +} +#endif + + +#if(CONFIG_WLAN_NOT_HAL_EXIST==1) +static int MacInit(struct rtl8192cd_priv *priv) +{ + volatile unsigned char bytetmp; + unsigned short retry; + + DEBUG_INFO("CP: MacInit===>>"); + +#ifdef CONFIG_PCI_HCI + + RTL_W8(RSV_CTRL0, 0x00); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + #if 0 + if(RTL_R8(RSV_CTRL0) == 0) + RTL_W8(SPS0_CTRL, (RTL_R8(SPS0_CTRL) & 0xc3) | 0x10); // b[5:2] = 4 + else + panic_printk("MAC reg unlock fail\n"); + #endif + if (!HalPwrSeqCmdParsing(priv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, rtl8188E_card_enable_flow)) + panic_printk("%s %d, HalPwrSeqCmdParsing init fail!!!\n", __FUNCTION__, __LINE__); + +#ifdef SUPPORT_RTL8188E_TC + check_RTL8188E_testChip(priv); +#endif + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT //_eric_8812 mac init + if (GET_CHIP_VER(priv) == VERSION_8812E) { + //set RF register as PI mode + RTL_W8(0xc00, RTL_R8(0xc00) | BIT(2)); + RTL_W8(0xe00, RTL_R8(0xe00) | BIT(2)); + + MacInit_8812(priv); + return; + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + RTL_W8(SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE); + + /* Enable PLL Power (LDOA15V) */ + RTL_W8(LDOA15_CTRL, LDA15_OBUF | LDA15_EN); + + /* advise by MAC team */ + RTL_W8(LDOHCI12_CTRL, 0x1f); + +#ifndef NOT_RTK_BSP +#if !defined(CONFIG_RTL_8198) && !defined(CONFIG_RTL_819XD) && !defined(CONFIG_RTL_8196E) && !defined(CONFIG_RTL_8198B) + { + /* temp modifying, for 96c pocket ap better performance */ + volatile unsigned int Qbytetmp; + Qbytetmp = REG32(0xb8000048); + Qbytetmp &= ~(BIT(10) | BIT(8)); + Qbytetmp |= BIT(19); + REG32(0xb8000048) = Qbytetmp; + } +#endif +#endif + } + +#endif + + // Power on when re-enter from IPS/Radio off/card disable +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + volatile unsigned int Qbytetmp; + RTL_W8(AFE_XTAL_CTRL, RTL_R8(AFE_XTAL_CTRL) | BIT(0)); + + Qbytetmp = RTL_R16(APS_FSMCO); + Qbytetmp &= 0xE7ff; + Qbytetmp |= 0x0800; + RTL_W16(APS_FSMCO, Qbytetmp); + + while (!((Qbytetmp = RTL_R32(APS_FSMCO)) & 0x00020000)); + + Qbytetmp = RTL_R16(APS_FSMCO); + Qbytetmp &= 0x7FFF; + RTL_W16(APS_FSMCO, Qbytetmp); + + Qbytetmp = RTL_R16(APS_FSMCO); + Qbytetmp &= 0xE7ff; + Qbytetmp |= 0x0000; + RTL_W16(APS_FSMCO, Qbytetmp); + } else +#endif + { +#ifdef CONFIG_RTL8672 + RTL_W8(AFE_XTAL_CTRL, RTL_R8(AFE_XTAL_CTRL) | BIT(0)); // enable XTAL +#else + /* just don't change BIT(1),Crystal engine setting refine*/ + //RTL_W8(AFE_XTAL_CTRL, 0x0d); // enable XTAL // clk inverted +#endif + RTL_W8(SPS0_CTRL, 0x2b); // enable SPS into PWM + } + delay_ms(1); + +#if 0 + // Enable AFE BANDGAP + RTL_W8(AFE_MISC, RTL_R8(AFE_MISC) | AFE_BGEN); + DEBUG_INFO("AFE_MISC = 0x%02x\n", RTL_R8(AFE_MISC)); + + // Enable AFE MBIAS + RTL_W8(AFE_MISC, RTL_R8(AFE_MISC) | AFE_MBEN); + DEBUG_INFO("AFE_MISC = 0x%02x\n", RTL_R8(AFE_MISC)); + + // Enable PLL Power (LDOA15V) +#ifdef CONFIG_RTL_92C_SUPPORT //#ifndef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) + RTL_W8(LDOA15_CTRL, RTL_R8(LDOA15_CTRL) | LDA15_EN); +#endif + + // Enable VDDCORE (LDOD12V) + RTL_W8(LDOV12D_CTRL, RTL_R8(LDOV12D_CTRL) | LDV12_EN); + + // Release XTAL Gated for AFE PLL +// RTL_W32(AFE_XTAL_CTRL, RTL_R32(AFE_XTAL_CTRL)|XTAL_GATE_AFE); + RTL_W32(AFE_XTAL_CTRL, RTL_R32(AFE_XTAL_CTRL) & ~XTAL_GATE_AFE); + + // Enable AFE PLL + RTL_W32(AFE_PLL_CTRL, RTL_R32(AFE_PLL_CTRL) | APLL_EN); + + // Release Isolation AFE PLL & MD + RTL_W16(SYS_ISO_CTRL, RTL_R16(SYS_ISO_CTRL) & ~ISO_MD2PP); + + // Enable WMAC Clock + RTL_W16(SYS_CLKR, RTL_R16(SYS_CLKR) | MAC_CLK_EN | SEC_CLK_EN); + + // Release WMAC reset & register reset + RTL_W16(SYS_FUNC_EN, RTL_R16(SYS_FUNC_EN) | FEN_MREGEN | FEN_DCORE); + + // Release IMEM Isolation + RTL_W16(SYS_ISO_CTRL, RTL_R16(SYS_ISO_CTRL) & ~(BIT(10) | ISO_DIOR)); // need to confirm + + /* // need double setting??? + // Enable MAC IO registers + RTL_W16(SYS_FUNC_EN, RTL_R16(SYS_FUNC_EN)|FEN_MREGEN); + */ + + // Switch HWFW select + RTL_W16(SYS_CLKR, (RTL_R16(SYS_CLKR) | CLKR_80M_SSC_DIS) & ~BIT(6)); // need to confirm +#else + // auto enable WLAN + + // Power On Reset for MAC Block + bytetmp = RTL_R8(APS_FSMCO + 1) | BIT(0); + delay_us(2); + RTL_W8(APS_FSMCO + 1, bytetmp); + delay_us(2); + + bytetmp = RTL_R8(APS_FSMCO + 1); + delay_us(2); + retry = 0; + while ((bytetmp & BIT(0)) && retry < 1000) { + retry++; + delay_us(50); + bytetmp = RTL_R8(APS_FSMCO + 1); + delay_us(50); + } + + if (bytetmp & BIT(0)) { + DEBUG_ERR("%s ERROR: auto enable WLAN failed!!(0x%02X)\n", __FUNCTION__, bytetmp); + } + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + RTL_W16(SYS_FUNC_EN, RTL_R16(SYS_FUNC_EN) & ~FEN_CPUEN); + else /*Enable Radio off, GPIO, and LED function*/ +#endif + RTL_W16(APS_FSMCO, 0x1012); // when enable HWPDN + + // release RF digital isolation +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + ) + RTL_W8(SYS_ISO_CTRL + 1, 0x82); +#endif + + delay_us(2); +#endif + + // Release MAC IO register reset + RTL_W32(CR, RTL_R32(CR) | MACRXEN | MACTXEN | SCHEDULE_EN | PROTOCOL_EN + | RXDMA_EN | TXDMA_EN | HCI_RXDMA_EN | HCI_TXDMA_EN); + +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI +#ifdef CONFIG_RTL_92C_SUPPORT + if (rtl8192cu_InitPowerOn(priv) == FALSE) + return FALSE; +#elif defined(CONFIG_RTL_88E_SUPPORT) + if (rtl8188eu_InitPowerOn(priv) == FALSE) + return FALSE; +#endif +#endif // CONFIG_USB_HCI + +#if defined(CONFIG_SDIO_HCI) && defined(CONFIG_RTL_88E_SUPPORT) + if (rtl8188es_InitPowerOn(priv) == FALSE) + return FALSE; +#endif + + //System init + LLT_table_init(priv); + + // Clear interrupt and enable interrupt +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + RTL_W32(REG_88E_HISR, 0xFFFFFFFF); + RTL_W32(REG_88E_HISRE, 0xFFFFFFFF); + } else +#endif + { + RTL_W32(HISR, 0xFFFFFFFF); + RTL_W16(HISRE, 0xFFFF); + } + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + + switch (priv->pmib->dot11RFEntry.macPhyMode) { + case SINGLEMAC_SINGLEPHY: + RTL_W8(MAC_PHY_CTRL_T, 0xfc); + RTL_W8(MAC_PHY_CTRL_MP, 0xfc); //enable super mac + RTL_W32(AGGLEN_LMT, 0xb972a841); + break; + case DUALMAC_SINGLEPHY: + RTL_W8(MAC_PHY_CTRL_T, 0xf1); + RTL_W8(MAC_PHY_CTRL_MP, 0xf1); //enable supermac + RTL_W32(AGGLEN_LMT, 0x54325521); + break; + case DUALMAC_DUALPHY: + RTL_W8(MAC_PHY_CTRL_T, 0xf3); + RTL_W8(MAC_PHY_CTRL_MP, 0xf3); //DMDP + RTL_W32(AGGLEN_LMT, 0x54325521); + break; + default: + DEBUG_ERR("Unknown 92D macPhyMode selection!\n"); + } + /* + * Set Rx FF0 boundary, half sized for testchip & dual MAC + */ +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode != SINGLEMAC_SINGLEPHY) + RTL_W32(TRXFF_BNDY, (RTL_R32(TRXFF_BNDY) & 0x0000FFFF) | (0x13ff & RXFF0_BNDY_Mask) << RXFF0_BNDY_SHIFT); + else +#endif + RTL_W32(TRXFF_BNDY, (RTL_R32(TRXFF_BNDY) & 0x0000FFFF) | (0x27ff & RXFF0_BNDY_Mask) << RXFF0_BNDY_SHIFT); + + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + RTL_W32(TRXFF_BNDY, (RTL_R32(TRXFF_BNDY) & 0x0000FFFF) | (0x25ff & RXFF0_BNDY_Mask) << RXFF0_BNDY_SHIFT); + } else +#endif + { + // Set Rx FF0 boundary : 9K/10K + RTL_W32(TRXFF_BNDY, (RTL_R32(TRXFF_BNDY) & 0x0000FFFF) | (0x27FF & RXFF0_BNDY_Mask) << RXFF0_BNDY_SHIFT); + } + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_RTL_92C_SUPPORT + if (IS_TEST_CHIP(priv)) { + // Set High priority queue select : HPQ:BC/H/VO/VI/MG, LPQ:BE/BK + // [5]:H, [4]:MG, [3]:BK, [2]:BE, [1]:VI, [0]:VO + RTL_W16(TRXDMA_CTRL, ((HPQ_SEL_HIQ | HPQ_SEL_MGQ | HPQ_SEL_VIQ | HPQ_SEL_VOQ)&HPQ_SEL_Mask) << HPQ_SEL_SHIFT); + + /* + * Enable ampdu rx check error, and enable rx byte shift + */ + RTL_W8(TRXDMA_CTRL, RTL_R8(TRXDMA_CTRL) | RXSHFT_EN | RXDMA_ARBBW_EN); + } else +#endif + { +#if 0//def CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + RTL_W16(TRXDMA_CTRL, (/*0xF5B1*/ 0xB5B1 | RXSHFT_EN | RXDMA_ARBBW_EN)); + else +#endif + //RTL_W16(TRXDMA_CTRL, (0xB770 | RXSHFT_EN | RXDMA_ARBBW_EN)); + +#if defined(CONFIG_RTL_ULINKER_BRSC) + RTL_W16(TRXDMA_CTRL, (0x5660 | RXDMA_ARBBW_EN)); //disable IP(layer3) auto aligne to 4bytes +#else +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E && priv->pmib->dot11OperationEntry.wifi_specific != 1) + RTL_W16(TRXDMA_CTRL, (0x56a0 | RXSHFT_EN | RXDMA_ARBBW_EN)); + else +#endif + RTL_W16(TRXDMA_CTRL, (0x5660 | RXSHFT_EN | RXDMA_ARBBW_EN)); +#endif + } +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI + _InitQueuePriority(priv); + + // Enable TXDMA to drop incorrect Bulk out packet + RTL_W32(TXDMA_OFFSET_CHK, RTL_R32(TXDMA_OFFSET_CHK) | DROP_DATA_EN); + +#ifdef CONFIG_RTL_92C_SUPPORT + if (BOARD_USB_DONGLE == priv->pshare->BoardType) + priv->pmib->dot11RFEntry.trswitch = 1; +#endif +#endif // CONFIG_USB_HCI + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(CONFIG_SDIO_HCI) + _InitQueuePriority(priv); +#endif + +// RTL_W8(TDECTRL, 0x11); // need to confirm + + // Set Network type: ap mode + RTL_W32(CR, RTL_R32(CR) | ((NETYPE_AP & NETYPE_Mask) << NETYPE_SHIFT)); + + // Set SLOT time + RTL_W8(SLOT_TIME, 0x09); + + // Set AMPDU min space + RTL_W8(AMPDU_MIN_SPACE, 0); // need to confirm + + // Set Tx/Rx page size (Tx must be 128 Bytes, Rx can be 64,128,256,512,1024 bytes) + RTL_W8(PBP, (PBP_128B & PSTX_Mask) << PSTX_SHIFT | (PBP_128B & PSRX_Mask) << PSRX_SHIFT); + + // Set RCR register + RTL_W32(RCR, RCR_APP_FCS | RCR_APP_MIC | RCR_APP_ICV | RCR_APP_PHYSTS | RCR_HTC_LOC_CTRL + | RCR_AMF | RCR_ADF | RCR_ACRC32 | RCR_AB | RCR_AM | RCR_APM | RCR_AAP); + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8192D || GET_CHIP_VER(priv) == VERSION_8192C || GET_CHIP_VER(priv) == VERSION_8188C) { + RTL_W32(RCR, RTL_R32(RCR) | RCR_AICV); /*force accept icv error packet in 92D, 92C and 88C*/ + } +#endif + + // Set Driver info size + RTL_W8(RX_DRVINFO_SZ, 4); + + // This part is not in WMAC InitMAC() + // Set SEC register + RTL_W16(SECCFG, RTL_R16(SECCFG) & ~(RXUSEDK | TXUSEDK)); + + // Set TCR register +// RTL_W32(TCR, RTL_R32(TCR)|CRC|CFE_FORM); + RTL_W32(TCR, RTL_R32(TCR) | CFE_FORM); + + // Set TCR to avoid deadlock + RTL_W32(TCR, RTL_R32(TCR) | BIT(15) | BIT(14) | BIT(13) | BIT(12)); + + // Set RRSR (response rate set reg) + //SetResponseRate(); + // Set RRSR (response rate set reg) + // Set RRSR to all legacy rate and HT rate + // CCK rate is supported by default. + // CCK rate will be filtered out only when associated AP does not support it. + // Only enable ACK rate to OFDM 24M +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + /* + * Set RRSR at here before MACPHY_REG.txt is ready + */ + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + /* + * PHY_BAND_5G + */ + RTL_W16(RRSR, 0x150); + } else { + /* + * PHY_BAND_2G + */ + RTL_W16(RRSR, 0x15F); //Set 0x15F for NDSi Client Connection Issue + } + RTL_W8(RRSR + 2, 0); + + RTL_W8(RCR, 0x0e); //follow 92c MACPHY_REG + RTL_W8(RCR + 1, 0x2a); //follow 92c MACPHY_REG + } else +#endif + { + RTL_W16(RRSR, 0xFFFF); + RTL_W8(RRSR + 2, 0xFF); + } + + // Set Spec SIFS (used in NAV) + // Joseph test + RTL_W16(SPEC_SIFS_A, (0x0A & SPEC_SIFS_OFDM_Mask) << SPEC_SIFS_OFDM_SHIFT + | (0x0A & SPEC_SIFS_CCK_Mask) << SPEC_SIFS_CCK_SHIFT); + + // Set SIFS for CCK + // Joseph test + RTL_W16(SIFS_CCK, (0x0A & SIFS_TRX_Mask) << SIFS_TRX_SHIFT | (0x0A & SIFS_CTX_Mask) << SIFS_CTX_SHIFT); + + // Set SIFS for OFDM + // Joseph test + RTL_W16(SIFS_OFDM, (0x0A & SIFS_TRX_Mask) << SIFS_TRX_SHIFT | (0x0A & SIFS_CTX_Mask) << SIFS_CTX_SHIFT); + + // Set retry limit + if (priv->pmib->dot11OperationEntry.dot11LongRetryLimit) + priv->pshare->RL_setting = priv->pmib->dot11OperationEntry.dot11LongRetryLimit & 0xff; + else { +#ifdef CLIENT_MODE + if (priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) + priv->pshare->RL_setting = 0x30; + else +#endif + priv->pshare->RL_setting = 0x10; + } + if (priv->pmib->dot11OperationEntry.dot11ShortRetryLimit) + priv->pshare->RL_setting |= ((priv->pmib->dot11OperationEntry.dot11ShortRetryLimit & 0xff) << 8); + else { +#ifdef CLIENT_MODE + if (priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) + priv->pshare->RL_setting |= (0x30 << 8); + else +#endif + priv->pshare->RL_setting |= (0x10 << 8); + } + RTL_W16(RL, priv->pshare->RL_setting); + +#ifdef CONFIG_PCI_HCI + //Set Desc Address + RTL_W32(BCNQ_DESA, priv->pshare->phw->tx_ringB_addr); + RTL_W32(MGQ_DESA, priv->pshare->phw->tx_ring0_addr); + RTL_W32(VOQ_DESA, priv->pshare->phw->tx_ring4_addr); + RTL_W32(VIQ_DESA, priv->pshare->phw->tx_ring3_addr); + RTL_W32(BEQ_DESA, priv->pshare->phw->tx_ring2_addr); + RTL_W32(BKQ_DESA, priv->pshare->phw->tx_ring1_addr); + RTL_W32(HQ_DESA, priv->pshare->phw->tx_ring5_addr); + RTL_W32(RX_DESA, priv->pshare->phw->ring_dma_addr); +// RTL_W32(RCDA, priv->pshare->phw->rxcmd_ring_addr); +// RTL_W32(TCDA, priv->pshare->phw->txcmd_ring_addr); +// RTL_W32(TCDA, phw->tx_ring5_addr); + // 2009/03/13 MH Prevent incorrect DMA write after accident reset !!! +// RTL_W16(CMDR, 0x37FC); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + RTL_W32(PCIE_CTRL_REG, (RTL_R32(PCIE_CTRL_REG) & 0x00ffffff) | (0x03 & MAX_RXDMA_Mask) << MAX_RXDMA_SHIFT + | (0x03 & MAX_TXDMA_Mask) << MAX_TXDMA_SHIFT | BCNQSTOP); + else +#endif + RTL_W32(PCIE_CTRL_REG, RTL_R32(PCIE_CTRL_REG) | (0x07 & MAX_RXDMA_Mask) << MAX_RXDMA_SHIFT + | (0x07 & MAX_TXDMA_Mask) << MAX_TXDMA_SHIFT | BCNQSTOP); +#endif // CONFIG_PCI_HCI + + // 20090928 Joseph + // Reconsider when to do this operation after asking HWSD. + RTL_W8(APSD_CTRL, RTL_R8(APSD_CTRL) & ~ BIT(6)); + retry = 0; + do { + retry++; + bytetmp = RTL_R8(APSD_CTRL); + } while ((retry < 200) && (bytetmp & BIT(7))); //polling until BIT7 is 0. by tynli + + if (bytetmp & BIT(7)) { + DEBUG_ERR("%s ERROR: APSD_CTRL=0x%02X\n", __FUNCTION__, bytetmp); + } + // disable BT_enable + RTL_W8(GPIO_MUXCFG, 0); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + RTL_W16(TCR, RTL_R16(TCR) | WMAC_TCR_ERRSTEN3 | WMAC_TCR_ERRSTEN2 + | WMAC_TCR_ERRSTEN1 | WMAC_TCR_ERRSTEN0); + /* + * For 92DE,Mac0 and Mac1 power off. + * 0x1F BIT6: 0 mac0 off, 1: mac0 on + * BIT7: 0 mac1 off, 1: mac1 on. + */ +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pshare->wlandev_idx == 0) +#endif + { + RTL_W8(RSV_MAC0_CTRL, RTL_R8(RSV_MAC0_CTRL) | MAC0_EN); + + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + RTL_W8(RSV_MAC0_CTRL, RTL_R8(RSV_MAC0_CTRL) & (~BAND_STAT)); + else + RTL_W8(RSV_MAC0_CTRL, RTL_R8(RSV_MAC0_CTRL) | BAND_STAT); + } + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pshare->wlandev_idx == 1) { + RTL_W8(RSV_MAC1_CTRL, RTL_R8(RSV_MAC1_CTRL) | MAC1_EN); + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + RTL_W8(RSV_MAC1_CTRL, RTL_R8(RSV_MAC1_CTRL) & (~BAND_STAT)); + else + RTL_W8(RSV_MAC1_CTRL, RTL_R8(RSV_MAC1_CTRL) | BAND_STAT); + } +#endif + } +#endif //CONFIG_RTL_92D_SUPPORT + +#if defined(CONFIG_USB_HCI) + InitUsbAggregationSetting(priv); +#elif defined(CONFIG_SDIO_HCI) + _initSdioAggregationSetting(priv); +#endif + +#ifdef CONFIG_EXT_CLK_26M + _InitClockTo26MHz(priv); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + // Enable MACTXEN/MACRXEN block + RTL_W32(CR, RTL_R32(CR) | (MACTXEN | MACRXEN)); +#endif + + DEBUG_INFO("DONE\n"); + + return TRUE; +} // MacInit +#else +static int MacInit(struct rtl8192cd_priv *priv) +{ + return TRUE; +} +#endif//CONFIG_WLAN_NOT_HAL_EXIST + +#if(CONFIG_WLAN_NOT_HAL_EXIST==1) +static void MacConfig(struct rtl8192cd_priv *priv) +{ + //RTL_W8(INIRTS_RATE_SEL, 0x8); // 24M + priv->pshare->phw->RTSInitRate_Candidate = priv->pshare->phw->RTSInitRate = 0x8; // 24M + RTL_W8(INIRTS_RATE_SEL, priv->pshare->phw->RTSInitRate); + + // 2007/02/07 Mark by Emily becasue we have not verify whether this register works + //For 92C,which reg? + // RTL_W8(BWOPMODE, BW_20M); // set if work at 20m + + // Ack timeout. + if ((priv->pmib->miscEntry.ack_timeout > 0) && (priv->pmib->miscEntry.ack_timeout < 0xff)) + RTL_W8(ACKTO, priv->pmib->miscEntry.ack_timeout); + else + RTL_W8(ACKTO, 0x40); + + // clear for mbid beacon tx + RTL_W8(MULTI_BCNQ_EN, 0); + RTL_W8(MULTI_BCNQ_OFFSET, 0); + +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) { + RTL_W32(ARFR0, 0xFF010); // 40M mode + RTL_W32(ARFR1, 0xFF010); // 20M mode + } else +#endif +#if defined(CONFIG_RTL_88E_SUPPORT) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + if (GET_CHIP_VER(priv) == VERSION_8188E) + { + RTL_W32(ARFR0, 0xFF00F); // 40M mode + RTL_W32(ARFR1, 0xFF00F); // 20M mode + } else +#endif + { + // set user defining ARFR table for 11n 1T + RTL_W32(ARFR0, 0xFF015); // 40M mode + RTL_W32(ARFR1, 0xFF005); // 20M mode + } + /* + * Disable TXOP CFE + */ + RTL_W16(RD_CTRL, RTL_R16(RD_CTRL) | DIS_TXOP_CFE); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + RTL_W8(MAC_SEL, 0); + RTL_W8(0x526, 0xff); /* enable all MBID interface beacon */ + + RTL_W32(0x024, 0x0011800d); //syn CLK enable, Xtal_bsel=nand + RTL_W32(0x028, 0x00ffdb83); //320MHz CLK enable + RTL_W32(0x014, 0x088ba955); //SPS=1.537V + RTL_W32(0x010, 0x49022b03); + + /* + * Protection mode control for hw RTS + */ + RTL_W16(PROT_MODE_CTRL, 0xff0D); + } +#endif + + /* + * RA try rate aggr limit + */ + RTL_W8(RA_TRY_RATE_AGG_LMT, 0); + + /* + * Max mpdu number per aggr + */ + RTL_W16(PROT_MODE_CTRL + 2, 0x0909); + + if(!CHIP_VER_92X_SERIES(priv)) + RTL_W8(RESP_SIFS_OFDM+1, 0x0a); //R2T + +#if (defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT)) && defined(TX_EARLY_MODE) + if ( +#ifdef CONFIG_RTL_92D_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#ifdef CONFIG_RTL_92D_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8188E) +#endif + ) + disable_em(priv); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E) + RTL8188E_EnableTxReport(priv); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(CONFIG_SDIO_HCI) + // + // Configure SDIO TxRx Control to enable Rx DMA timer masking. + // 2010.02.24. + // +// value8 = SdioLocalCmd52Read1Byte(priv, SDIO_REG_TX_CTRL); + SdioLocalCmd52Write4Byte(priv, SDIO_REG_TX_CTRL, 0x02); + +#ifdef CONFIG_SDIO_TX_INTERRUPT + // Invalidate All TX Free Page Threshold + RTL_W32(REG_88E_TXDMA_TH, 0xFFFFFFFF); + RTL_W16(REG_88E_LQ_TH, 0xFFFF); +#endif + // + // Update current Tx FIFO page status. + // + sdio_query_txbuf_status(priv); + sdio_query_txoqt_status(priv); +#endif // CONFIG_RTL_88E_SUPPORT && CONFIG_SDIO_HCI +} +#else +static void MacConfig(struct rtl8192cd_priv *priv) +{ + return; +} +#endif//CONFIG_WLAN_NOT_HAL_EXIST + + +unsigned int get_mean_of_2_close_value(unsigned int *val_array) +{ + unsigned int tmp1, tmp2; + + //printk("v1 %08x v2 %08x v3 %08x\n", val_array[0], val_array[1], val_array[2]); + if (val_array[0] > val_array[1]) { + tmp1 = val_array[1]; + val_array[1] = val_array[0]; + val_array[0] = tmp1; + } + if (val_array[1] > val_array[2]) { + tmp1 = val_array[2]; + val_array[2] = val_array[1]; + val_array[1] = tmp1; + } + if (val_array[0] > val_array[1]) { + tmp1 = val_array[1]; + val_array[1] = val_array[0]; + val_array[0] = tmp1; + } + //printk("v1 %08x v2 %08x v3 %08x\n", val_array[0], val_array[1], val_array[2]); + + tmp1 = val_array[1] - val_array[0]; + tmp2 = val_array[2] - val_array[1]; + if (tmp1 < tmp2) + tmp1 = (val_array[0] + val_array[1]) / 2; + else + tmp1 = (val_array[1] + val_array[2]) / 2; + + //printk("final %08x\n", tmp1); + return tmp1; +} + +#ifdef CONFIG_RTL_92C_SUPPORT + +void PHY_APCalibrate(struct rtl8192cd_priv *priv) +{ +#ifdef HIGH_POWER_EXT_PA + if (!priv->pshare->rf_ft_var.use_ext_pa) +#endif + if (!IS_TEST_CHIP(priv)) { + if (GET_CHIP_VER(priv) == VERSION_8192C) + APK_MAIN(priv, 1); + else if (GET_CHIP_VER(priv) == VERSION_8188C) + APK_MAIN(priv, 0); + } +} + +#ifdef CONFIG_RTL_92C_SUPPORT +#ifndef CONFIG_RTL_NEW_IQK +static void IQK_92CD(struct rtl8192cd_priv *priv) +{ + unsigned int cal_num = 0, cal_retry = 0, Oldval = 0, temp_c04 = 0, temp_c08 = 0, temp_874 = 0, temp_eac; + unsigned int cal_e94, cal_e9c, cal_ea4, cal_eac, cal_eb4, cal_ebc, cal_ec4, cal_ecc, adda_on_reg; + unsigned int X, Y, val_e94[3], val_e9c[3], val_ea4[3], val_eac[3], val_eb4[3], val_ebc[3], val_ec4[3], val_ecc[3]; +#ifdef HIGH_POWER_EXT_PA + unsigned int temp_870 = 0, temp_860 = 0, temp_864 = 0; +#endif + + // step 1: save ADDA power saving parameters + unsigned int temp_85c = RTL_R32(0x85c); + unsigned int temp_e6c = RTL_R32(0xe6c); + unsigned int temp_e70 = RTL_R32(0xe70); + unsigned int temp_e74 = RTL_R32(0xe74); + unsigned int temp_e78 = RTL_R32(0xe78); + unsigned int temp_e7c = RTL_R32(0xe7c); + unsigned int temp_e80 = RTL_R32(0xe80); + unsigned int temp_e84 = RTL_R32(0xe84); + unsigned int temp_e88 = RTL_R32(0xe88); + unsigned int temp_e8c = RTL_R32(0xe8c); + unsigned int temp_ed0 = RTL_R32(0xed0); + unsigned int temp_ed4 = RTL_R32(0xed4); + unsigned int temp_ed8 = RTL_R32(0xed8); + unsigned int temp_edc = RTL_R32(0xedc); + unsigned int temp_ee0 = RTL_R32(0xee0); + unsigned int temp_eec = RTL_R32(0xeec); + +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + { + if (priv->pshare->iqk_2g_done) + return; + priv->pshare->iqk_2g_done = 1; + } + + printk(">> %s \n", __FUNCTION__); + +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + temp_870 = RTL_R32(0x870); + temp_860 = RTL_R32(0x860); + temp_864 = RTL_R32(0x864); + } +#endif + + // step 2: Path-A ADDA all on + adda_on_reg = 0x04db25a4; + + RTL_W32(0x85c, adda_on_reg); + RTL_W32(0xe6c, adda_on_reg); + RTL_W32(0xe70, adda_on_reg); + RTL_W32(0xe74, adda_on_reg); + RTL_W32(0xe78, adda_on_reg); + RTL_W32(0xe7c, adda_on_reg); + RTL_W32(0xe80, adda_on_reg); + RTL_W32(0xe84, adda_on_reg); + RTL_W32(0xe88, adda_on_reg); + RTL_W32(0xe8c, adda_on_reg); + RTL_W32(0xed0, adda_on_reg); + RTL_W32(0xed4, adda_on_reg); + RTL_W32(0xed8, adda_on_reg); + RTL_W32(0xedc, adda_on_reg); + RTL_W32(0xee0, adda_on_reg); + RTL_W32(0xeec, adda_on_reg); + + // step 3: IQ&LO calibration Setting + // BB switch to PI mode + //RTL_W32(0x820, 0x01000100); + //RTL_W32(0x828, 0x01000100); + //BB setting + temp_c04 = RTL_R32(0xc04); + temp_c08 = RTL_R32(0xc08); + temp_874 = RTL_R32(0x874); + RTL_W32(0xc04, 0x03a05600); + RTL_W32(0xc08, 0x000800e4); + RTL_W32(0x874, 0x00204000); + +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + PHY_SetBBReg(priv, 0x870, BIT(10), 1); + PHY_SetBBReg(priv, 0x870, BIT(26), 1); + PHY_SetBBReg(priv, 0x860, BIT(10), 0); + PHY_SetBBReg(priv, 0x864, BIT(10), 0); + } +#endif + RTL_W32(0x840, 0x00010000); + RTL_W32(0x844, 0x00010000); + + //AP or IQK + RTL_W32(0xb68 , 0x00080000); + RTL_W32(0xb6c , 0x00080000); + + // IQK setting + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); + RTL_W32(0xe40, 0x01007c00); + RTL_W32(0xe44, 0x01004800); + // path-A IQK setting + RTL_W32(0xe30, 0x10008c1f); + RTL_W32(0xe34, 0x10008c1f); + RTL_W32(0xe38, 0x82140102); + RTL_W32(0xe3c, 0x28160202); + // path-B IQK setting + RTL_W32(0xe50, 0x10008c22); + RTL_W32(0xe54, 0x10008c22); + RTL_W32(0xe58, 0x82140102); + RTL_W32(0xe5c, 0x28160202); + // LO calibration setting + RTL_W32(0xe4c, 0x001028d1); + + // delay to ensure Path-A IQK success + delay_ms(300); + + // step 4: One shot, path A LOK & IQK + while (cal_num < 3) { + // One shot, path A LOK & IQK + RTL_W32(0xe48, 0xf9000000); + RTL_W32(0xe48, 0xf8000000); + // delay 1ms + delay_ms(10); + + // check fail bit and check abnormal condition, then fill BB IQ matrix + cal_e94 = (RTL_R32(0xe94) >> 16) & 0x3ff; + cal_e9c = (RTL_R32(0xe9c) >> 16) & 0x3ff; + cal_ea4 = (RTL_R32(0xea4) >> 16) & 0x3ff; + temp_eac = RTL_R32(0xeac); + cal_eac = (temp_eac >> 16) & 0x3ff; + if (!(temp_eac & BIT(28)) && !(temp_eac & BIT(27)) && + (cal_e94 != 0x142) && (cal_e9c != 0x42) && + (cal_ea4 != 0x132) && (cal_eac != 0x36)) { + val_e94[cal_num] = cal_e94; + val_e9c[cal_num] = cal_e9c; + val_ea4[cal_num] = cal_ea4; + val_eac[cal_num] = cal_eac; + cal_num++; + } else { + if (++cal_retry >= 10) { + printk("%s Path-A Check\n", __FUNCTION__); + break; + } + } + } + + if (cal_num == 3) { + cal_e94 = get_mean_of_2_close_value(val_e94); + cal_e9c = get_mean_of_2_close_value(val_e9c); + cal_ea4 = get_mean_of_2_close_value(val_ea4); + cal_eac = get_mean_of_2_close_value(val_eac); + + priv->pshare->RegE94 = cal_e94; + priv->pshare->RegE9C = cal_e9c; + + Oldval = (RTL_R32(0xc80) >> 22) & 0x3ff; + + X = cal_e94; + PHY_SetBBReg(priv, 0xc80, 0x3ff, X * (Oldval / 0x100)); + PHY_SetBBReg(priv, 0xc4c, BIT(24), ((X * Oldval) >> 7) & 0x1); + + Y = cal_e9c; + PHY_SetBBReg(priv, 0xc94, 0xf0000000, ((Y * (Oldval / 0x100)) >> 6) & 0xf); + PHY_SetBBReg(priv, 0xc80, 0x003f0000, (Y * (Oldval / 0x100)) & 0x3f); + PHY_SetBBReg(priv, 0xc4c, BIT(26), ((Y * Oldval) >> 7) & 0x1); + + PHY_SetBBReg(priv, 0xc14, 0x3ff, cal_ea4); + + PHY_SetBBReg(priv, 0xc14, 0xfc00, cal_eac & 0x3f); + + PHY_SetBBReg(priv, 0xca0, 0xf0000000, (cal_eac >> 6) & 0xf); + } else { + priv->pshare->RegE94 = 0x100; + priv->pshare->RegE9C = 0x00; + } + + // step 5: Path-A standby mode + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + RTL_W32(0x840, 0x00010000); + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); + + // step 6: Path-B ADDA all on + adda_on_reg = 0x0b1b25a4; + + RTL_W32(0x85c, adda_on_reg); + RTL_W32(0xe6c, adda_on_reg); + RTL_W32(0xe70, adda_on_reg); + RTL_W32(0xe74, adda_on_reg); + RTL_W32(0xe78, adda_on_reg); + RTL_W32(0xe7c, adda_on_reg); + RTL_W32(0xe80, adda_on_reg); + RTL_W32(0xe84, adda_on_reg); + RTL_W32(0xe88, adda_on_reg); + RTL_W32(0xe8c, adda_on_reg); + RTL_W32(0xed0, adda_on_reg); + RTL_W32(0xed4, adda_on_reg); + RTL_W32(0xed8, adda_on_reg); + RTL_W32(0xedc, adda_on_reg); + RTL_W32(0xee0, adda_on_reg); + RTL_W32(0xeec, adda_on_reg); + + // step 7: One shot, path B LOK & IQK + cal_num = 0; + cal_retry = 0; + while (cal_num < 3) { + // One shot, path B LOK & IQK + RTL_W32(0xe60, 2); + RTL_W32(0xe60, 0); + // delay 1ms + delay_ms(10); + + // check fail bit and check abnormal condition, then fill BB IQ matrix + cal_eb4 = (RTL_R32(0xeb4) >> 16) & 0x3ff; + cal_ebc = (RTL_R32(0xebc) >> 16) & 0x3ff; + cal_ec4 = (RTL_R32(0xec4) >> 16) & 0x3ff; + cal_ecc = (RTL_R32(0xecc) >> 16) & 0x3ff; + temp_eac = RTL_R32(0xeac); + if (!(temp_eac & BIT(31)) && !(temp_eac & BIT(30)) && + (cal_eb4 != 0x142) && (cal_ebc != 0x42) && + (cal_ec4 != 0x132) && (cal_ecc != 0x36)) { + val_eb4[cal_num] = cal_eb4; + val_ebc[cal_num] = cal_ebc; + val_ec4[cal_num] = cal_ec4; + val_ecc[cal_num] = cal_ecc; + cal_num++; + } else { + if (++cal_retry >= 10) { + printk("%s Path-B Check\n", __FUNCTION__); + break; + } + } + } + + if (cal_num == 3) { + cal_eb4 = get_mean_of_2_close_value(val_eb4); + cal_ebc = get_mean_of_2_close_value(val_ebc); + cal_ec4 = get_mean_of_2_close_value(val_ec4); + cal_ecc = get_mean_of_2_close_value(val_ecc); + + priv->pshare->RegEB4 = cal_eb4; + priv->pshare->RegEBC = cal_ebc; + + Oldval = (RTL_R32(0xc88) >> 22) & 0x3ff; + + X = cal_eb4; + PHY_SetBBReg(priv, 0xc88, 0x3ff, X * (Oldval / 0x100)); + PHY_SetBBReg(priv, 0xc4c, BIT(28), ((X * Oldval) >> 7) & 0x1); + + Y = cal_ebc; + PHY_SetBBReg(priv, 0xc9c, 0xf0000000, ((Y * (Oldval / 0x100)) >> 6) & 0xf); + PHY_SetBBReg(priv, 0xc88, 0x003f0000, (Y * (Oldval / 0x100)) & 0x3f); + PHY_SetBBReg(priv, 0xc4c, BIT(30), ((Y * Oldval) >> 7) & 0x1); + + PHY_SetBBReg(priv, 0xc1c, 0x3ff, cal_ec4); + + PHY_SetBBReg(priv, 0xc1c, 0xfc00, cal_ecc & 0x3f); + + PHY_SetBBReg(priv, 0xc78, 0xf000, (cal_ecc >> 6) & 0xf); + } else { + priv->pshare->RegEB4 = 0x100; + priv->pshare->RegEBC = 0x00; + } + + + // step 8: back to BB mode, load original values + RTL_W32(0xc04, temp_c04); + RTL_W32(0x874, temp_874); + RTL_W32(0xc08, temp_c08); + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + RTL_W32(0x840, 0x32ed3); + RTL_W32(0x844, 0x32ed3); +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + RTL_W32(0x870, temp_870); + RTL_W32(0x860, temp_860); + RTL_W32(0x864, temp_864); + } +#endif + // return to SI mode + //RTL_W32(0x820, 0x01000000); + //RTL_W32(0x828, 0x01000000); + + // step 9: reload ADDA power saving parameters + RTL_W32(0x85c, temp_85c); + RTL_W32(0xe6c, temp_e6c); + RTL_W32(0xe70, temp_e70); + RTL_W32(0xe74, temp_e74); + RTL_W32(0xe78, temp_e78); + RTL_W32(0xe7c, temp_e7c); + RTL_W32(0xe80, temp_e80); + RTL_W32(0xe84, temp_e84); + RTL_W32(0xe88, temp_e88); + RTL_W32(0xe8c, temp_e8c); + RTL_W32(0xed0, temp_ed0); + RTL_W32(0xed4, temp_ed4); + RTL_W32(0xed8, temp_ed8); + RTL_W32(0xedc, temp_edc); + RTL_W32(0xee0, temp_ee0); + RTL_W32(0xeec, temp_eec); + +} + + +static void IQK_88C(struct rtl8192cd_priv *priv) +{ + unsigned int cal_num = 0, cal_retry = 0; + unsigned int Oldval_0 = 0, temp_c04 = 0, temp_c08 = 0, temp_874 = 0; + unsigned int cal_e94, cal_e9c, cal_ea4, cal_eac, temp_eac; + unsigned int X, Y, val_e94[3], val_e9c[3], val_ea4[3], val_eac[3]; + +#ifdef HIGH_POWER_EXT_PA + unsigned int temp_870 = 0, temp_860 = 0, temp_864 = 0; +#endif + // step 1: save ADDA power saving parameters + unsigned int temp_85c = RTL_R32(0x85c); + unsigned int temp_e6c = RTL_R32(0xe6c); + unsigned int temp_e70 = RTL_R32(0xe70); + unsigned int temp_e74 = RTL_R32(0xe74); + unsigned int temp_e78 = RTL_R32(0xe78); + unsigned int temp_e7c = RTL_R32(0xe7c); + unsigned int temp_e80 = RTL_R32(0xe80); + unsigned int temp_e84 = RTL_R32(0xe84); + unsigned int temp_e88 = RTL_R32(0xe88); + unsigned int temp_e8c = RTL_R32(0xe8c); + unsigned int temp_ed0 = RTL_R32(0xed0); + unsigned int temp_ed4 = RTL_R32(0xed4); + unsigned int temp_ed8 = RTL_R32(0xed8); + unsigned int temp_edc = RTL_R32(0xedc); + unsigned int temp_ee0 = RTL_R32(0xee0); + unsigned int temp_eec = RTL_R32(0xeec); + +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + { + if (priv->pshare->iqk_2g_done) + return; + priv->pshare->iqk_2g_done = 1; + } + +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + temp_870 = RTL_R32(0x870); + temp_860 = RTL_R32(0x860); + temp_864 = RTL_R32(0x864); + } +#endif + + // step 2: ADDA all on + RTL_W32(0x85c, 0x0b1b25a0); + RTL_W32(0xe6c, 0x0bdb25a0); + RTL_W32(0xe70, 0x0bdb25a0); + RTL_W32(0xe74, 0x0bdb25a0); + RTL_W32(0xe78, 0x0bdb25a0); + RTL_W32(0xe7c, 0x0bdb25a0); + RTL_W32(0xe80, 0x0bdb25a0); + RTL_W32(0xe84, 0x0bdb25a0); + RTL_W32(0xe88, 0x0bdb25a0); + RTL_W32(0xe8c, 0x0bdb25a0); + RTL_W32(0xed0, 0x0bdb25a0); + RTL_W32(0xed4, 0x0bdb25a0); + RTL_W32(0xed8, 0x0bdb25a0); + RTL_W32(0xedc, 0x0bdb25a0); + RTL_W32(0xee0, 0x0bdb25a0); + RTL_W32(0xeec, 0x0bdb25a0); + + // step 3: start IQK + // BB switch to PI mode + //RTL_W32(0x820, 0x01000100); + //RTL_W32(0x828, 0x01000100); + //BB setting + temp_c04 = RTL_R32(0xc04); + temp_c08 = RTL_R32(0xc08); + temp_874 = RTL_R32(0x874); + RTL_W32(0xc04, 0x03a05600); + RTL_W32(0xc08, 0x000800e4); + RTL_W32(0x874, 0x00204000); +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + PHY_SetBBReg(priv, 0x870, BIT(10), 1); + PHY_SetBBReg(priv, 0x870, BIT(26), 1); + PHY_SetBBReg(priv, 0x860, BIT(10), 0); + PHY_SetBBReg(priv, 0x864, BIT(10), 0); + } +#endif + + //AP or IQK +// RTL_W32(0xb68, 0x0f600000); + RTL_W32(0xb68, 0x00080000); + + // IQK setting + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); + RTL_W32(0xe40, 0x01007c00); + RTL_W32(0xe44, 0x01004800); + // path-A IQK setting + RTL_W32(0xe30, 0x10008c1f); + RTL_W32(0xe34, 0x10008c1f); + RTL_W32(0xe38, 0x82140102); + //RTL_W32(0xe3c, 0x28160502); + RTL_W32(0xe3c, 0x28160202); + + // LO calibration setting + RTL_W32(0xe4c, 0x001028d1); + + while (cal_num < 3) { + // One shot, path A LOK & IQK + RTL_W32(0xe48, 0xf9000000); + RTL_W32(0xe48, 0xf8000000); + // delay 1ms + delay_ms(150); + + // step 4: check fail bit and check abnormal condition, then fill BB IQ matrix + cal_e94 = (RTL_R32(0xe94) >> 16) & 0x3ff; + cal_e9c = (RTL_R32(0xe9c) >> 16) & 0x3ff; + cal_ea4 = (RTL_R32(0xea4) >> 16) & 0x3ff; + temp_eac = RTL_R32(0xeac); + cal_eac = (temp_eac >> 16) & 0x3ff; + if (!(temp_eac & BIT(28)) && !(temp_eac & BIT(27)) && + (cal_e94 != 0x142) && (cal_e9c != 0x42) && + (cal_ea4 != 0x132) && (cal_eac != 0x36)) { + val_e94[cal_num] = cal_e94; + val_e9c[cal_num] = cal_e9c; + val_ea4[cal_num] = cal_ea4; + val_eac[cal_num] = cal_eac; + cal_num++; + } else { + if (++cal_retry >= 10) { + printk("IQK Check\n"); + break; + } + } + } + + if (cal_num == 3) { + cal_e94 = get_mean_of_2_close_value(val_e94); + cal_e9c = get_mean_of_2_close_value(val_e9c); + cal_ea4 = get_mean_of_2_close_value(val_ea4); + cal_eac = get_mean_of_2_close_value(val_eac); + + priv->pshare->RegE94 = cal_e94; + priv->pshare->RegE9C = cal_e9c; + + Oldval_0 = (RTL_R32(0xc80) >> 22) & 0x3ff; + + X = cal_e94; + PHY_SetBBReg(priv, 0xc80, 0x3ff, X * (Oldval_0 / 0x100)); + PHY_SetBBReg(priv, 0xc4c, BIT(24), ((X * Oldval_0) >> 7) & 0x1); + + Y = cal_e9c; + PHY_SetBBReg(priv, 0xc94, 0xf0000000, ((Y * (Oldval_0 / 0x100)) >> 6) & 0xf); + PHY_SetBBReg(priv, 0xc80, 0x003f0000, (Y * (Oldval_0 / 0x100)) & 0x3f); + PHY_SetBBReg(priv, 0xc4c, BIT(26), ((Y * Oldval_0) >> 7) & 0x1); + + PHY_SetBBReg(priv, 0xc14, 0x3ff, cal_ea4); + + PHY_SetBBReg(priv, 0xc14, 0xfc00, cal_eac & 0x3f); + + PHY_SetBBReg(priv, 0xca0, 0xf0000000, (cal_eac >> 6) & 0xf); + } else { + priv->pshare->RegE94 = 0x100; + priv->pshare->RegE9C = 0x00; + } + + // back to BB mode + RTL_W32(0xc04, temp_c04); + RTL_W32(0x874, temp_874); + RTL_W32(0xc08, temp_c08); + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + RTL_W32(0x840, 0x00032ed3); +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + RTL_W32(0x870, temp_870); + RTL_W32(0x860, temp_860); + RTL_W32(0x864, temp_864); + } +#endif + // return to SI mode + //RTL_W32(0x820, 0x01000000); + //RTL_W32(0x828, 0x01000000); + + // step 5: reload ADDA power saving parameters + RTL_W32(0x85c, temp_85c); + RTL_W32(0xe6c, temp_e6c); + RTL_W32(0xe70, temp_e70); + RTL_W32(0xe74, temp_e74); + RTL_W32(0xe78, temp_e78); + RTL_W32(0xe7c, temp_e7c); + RTL_W32(0xe80, temp_e80); + RTL_W32(0xe84, temp_e84); + RTL_W32(0xe88, temp_e88); + RTL_W32(0xe8c, temp_e8c); + RTL_W32(0xed0, temp_ed0); + RTL_W32(0xed4, temp_ed4); + RTL_W32(0xed8, temp_ed8); + RTL_W32(0xedc, temp_edc); + RTL_W32(0xee0, temp_ee0); + RTL_W32(0xeec, temp_eec); +} // IQK +#endif +#endif + +#endif + +void PHY_IQCalibrate(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long x; +#endif + +#ifdef RF_MIMO_SWITCH + MIMO_mode_switch(priv, MIMO_2T2R); +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + SAVE_INT_AND_CLI(x); +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { +#ifdef DFS + if ((priv->pshare->rf_ft_var.dfsdelayiqk) && + (OPMODE & WIFI_AP_STATE) && + !priv->pmib->dot11DFSEntry.disable_DFS && + (timer_pending(&priv->ch_avail_chk_timer) || + priv->pmib->dot11DFSEntry.disable_tx)) { + RESTORE_INT(x); + return; + } +#endif + IQK_92D_5G_phy0_n(priv); + } else + IQK_92D_2G_phy1(priv); + } else +#endif + { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { +#ifdef DFS + if ((priv->pshare->rf_ft_var.dfsdelayiqk) && + (OPMODE & WIFI_AP_STATE) && + !priv->pmib->dot11DFSEntry.disable_DFS && + (timer_pending(&priv->ch_avail_chk_timer) || + priv->pmib->dot11DFSEntry.disable_tx)) { + RESTORE_INT(x); + return; + } +#endif + IQK_92D_5G_n(priv); + } else + IQK_92D_2G(priv); + } + RESTORE_INT(x); + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + SAVE_INT_AND_CLI(x); +#ifdef CONFIG_RTL_NEW_IQK + PHY_IQCalibrate_92C(priv); +#else + if ( IS_UMC_A_CUT_88C(priv) +#ifdef HIGH_POWER_EXT_PA + || (priv->pshare->rf_ft_var.use_ext_pa) +#endif + ) { + PHY_IQCalibrate_92C(priv); + } else { + if (GET_CHIP_VER(priv) == VERSION_8192C) + IQK_92CD(priv); + else + IQK_88C(priv); + } +#endif + RESTORE_INT(x); + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) +#ifdef USE_OUT_SRC + PHY_IQCalibrate_8188E(ODMPTR, FALSE); +#else + PHY_IQCalibrate_8188E(priv, FALSE); +#endif +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT //FOR_8812_IQK +#ifdef USE_OUT_SRC + if (GET_CHIP_VER(priv) == VERSION_8812E) { +#ifdef DFS + if (priv->pshare->rf_ft_var.dfs_skip_iqk) + return; + + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + if ((priv->pshare->rf_ft_var.dfsdelayiqk) && + (OPMODE & WIFI_AP_STATE) && + !priv->pmib->dot11DFSEntry.disable_DFS && + (timer_pending(&priv->ch_avail_chk_timer) || + priv->pmib->dot11DFSEntry.disable_tx)) + return; + } +#endif + SAVE_INT_AND_CLI(x); + priv->pshare->No_RF_Write = 0; + phy_IQCalibrate_8812A(ODMPTR, priv->pshare->working_channel); + priv->pshare->No_RF_Write = 1; + RESTORE_INT(x); + + } +#endif +#endif + +#ifdef CONFIG_WLAN_HAL_8881A +#ifdef USE_OUT_SRC + if (GET_CHIP_VER(priv) == VERSION_8881A) { +#ifdef DFS + if (priv->pshare->rf_ft_var.dfs_skip_iqk) + return; + + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + if ((priv->pshare->rf_ft_var.dfsdelayiqk) && + (OPMODE & WIFI_AP_STATE) && + !priv->pmib->dot11DFSEntry.disable_DFS && + (timer_pending(&priv->ch_avail_chk_timer) || + priv->pmib->dot11DFSEntry.disable_tx)) + return; + } +#endif + SAVE_INT_AND_CLI(x); + priv->pshare->No_RF_Write = 0; + phy_IQCalibrate_8821A(ODMPTR); + priv->pshare->No_RF_Write = 1; + RESTORE_INT(x); + } +#endif +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE +#ifdef USE_OUT_SRC + if (GET_CHIP_VER(priv) == VERSION_8192E) { +// SAVE_INT_AND_CLI(x); + PHY_IQCalibrate_8192E(ODMPTR, FALSE); +// RESTORE_INT(x); + } +#endif +#endif +} + + +#ifdef ADD_TX_POWER_BY_CMD +static void assign_txpwr_offset(struct rtl8192cd_priv *priv) +{ + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->CCKTxAgc_A[0], priv->pshare->rf_ft_var.txPowerPlus_cck_11); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->CCKTxAgc_A[1], priv->pshare->rf_ft_var.txPowerPlus_cck_5); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->CCKTxAgc_A[2], priv->pshare->rf_ft_var.txPowerPlus_cck_2); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->CCKTxAgc_A[3], priv->pshare->rf_ft_var.txPowerPlus_cck_1); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->CCKTxAgc_B[0], priv->pshare->rf_ft_var.txPowerPlus_cck_11); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->CCKTxAgc_B[1], priv->pshare->rf_ft_var.txPowerPlus_cck_5); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->CCKTxAgc_B[2], priv->pshare->rf_ft_var.txPowerPlus_cck_2); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->CCKTxAgc_B[3], priv->pshare->rf_ft_var.txPowerPlus_cck_1); + + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_A[0], priv->pshare->rf_ft_var.txPowerPlus_ofdm_18); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_A[1], priv->pshare->rf_ft_var.txPowerPlus_ofdm_12); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_A[2], priv->pshare->rf_ft_var.txPowerPlus_ofdm_9); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_A[3], priv->pshare->rf_ft_var.txPowerPlus_ofdm_6); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_B[0], priv->pshare->rf_ft_var.txPowerPlus_ofdm_18); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_B[1], priv->pshare->rf_ft_var.txPowerPlus_ofdm_12); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_B[2], priv->pshare->rf_ft_var.txPowerPlus_ofdm_9); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_B[3], priv->pshare->rf_ft_var.txPowerPlus_ofdm_6); + + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_A[4], priv->pshare->rf_ft_var.txPowerPlus_ofdm_54); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_A[5], priv->pshare->rf_ft_var.txPowerPlus_ofdm_48); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_A[6], priv->pshare->rf_ft_var.txPowerPlus_ofdm_36); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_A[7], priv->pshare->rf_ft_var.txPowerPlus_ofdm_24); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_B[4], priv->pshare->rf_ft_var.txPowerPlus_ofdm_54); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_B[5], priv->pshare->rf_ft_var.txPowerPlus_ofdm_48); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_B[6], priv->pshare->rf_ft_var.txPowerPlus_ofdm_36); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->OFDMTxAgcOffset_B[7], priv->pshare->rf_ft_var.txPowerPlus_ofdm_24); + + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[0], priv->pshare->rf_ft_var.txPowerPlus_mcs_3); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[1], priv->pshare->rf_ft_var.txPowerPlus_mcs_2); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[2], priv->pshare->rf_ft_var.txPowerPlus_mcs_1); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[3], priv->pshare->rf_ft_var.txPowerPlus_mcs_0); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[0], priv->pshare->rf_ft_var.txPowerPlus_mcs_3); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[1], priv->pshare->rf_ft_var.txPowerPlus_mcs_2); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[2], priv->pshare->rf_ft_var.txPowerPlus_mcs_1); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[3], priv->pshare->rf_ft_var.txPowerPlus_mcs_0); + + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[4], priv->pshare->rf_ft_var.txPowerPlus_mcs_7); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[5], priv->pshare->rf_ft_var.txPowerPlus_mcs_6); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[6], priv->pshare->rf_ft_var.txPowerPlus_mcs_5); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[7], priv->pshare->rf_ft_var.txPowerPlus_mcs_4); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[4], priv->pshare->rf_ft_var.txPowerPlus_mcs_7); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[5], priv->pshare->rf_ft_var.txPowerPlus_mcs_6); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[6], priv->pshare->rf_ft_var.txPowerPlus_mcs_5); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[7], priv->pshare->rf_ft_var.txPowerPlus_mcs_4); + + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[8], priv->pshare->rf_ft_var.txPowerPlus_mcs_11); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[9], priv->pshare->rf_ft_var.txPowerPlus_mcs_10); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[10], priv->pshare->rf_ft_var.txPowerPlus_mcs_9); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[11], priv->pshare->rf_ft_var.txPowerPlus_mcs_8); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[8], priv->pshare->rf_ft_var.txPowerPlus_mcs_11); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[9], priv->pshare->rf_ft_var.txPowerPlus_mcs_10); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[10], priv->pshare->rf_ft_var.txPowerPlus_mcs_9); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[11], priv->pshare->rf_ft_var.txPowerPlus_mcs_8); + + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[12], priv->pshare->rf_ft_var.txPowerPlus_mcs_15); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[13], priv->pshare->rf_ft_var.txPowerPlus_mcs_14); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[14], priv->pshare->rf_ft_var.txPowerPlus_mcs_13); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_A[15], priv->pshare->rf_ft_var.txPowerPlus_mcs_12); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[12], priv->pshare->rf_ft_var.txPowerPlus_mcs_15); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[13], priv->pshare->rf_ft_var.txPowerPlus_mcs_14); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[14], priv->pshare->rf_ft_var.txPowerPlus_mcs_13); + ASSIGN_TX_POWER_OFFSET(priv->pshare->phw->MCSTxAgcOffset_B[15], priv->pshare->rf_ft_var.txPowerPlus_mcs_12); +} +#endif + + +void reload_txpwr_pg(struct rtl8192cd_priv *priv) +{ + int i; + + PHY_ConfigBBWithParaFile(priv, PHYREG_PG); + +#if 0 //def HIGH_POWER_EXT_PA + if (!priv->pshare->rf_ft_var.use_ext_pa) +#endif + { + // get default Tx AGC offset + //_TXPWR_REDEFINE ?? CCKTxAgc_A[1] [2] [3] ?? + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_Mcs03_Mcs00)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_Mcs07_Mcs04)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[8]) = cpu_to_be32(RTL_R32(rTxAGC_A_Mcs11_Mcs08)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[12]) = cpu_to_be32(RTL_R32(rTxAGC_A_Mcs15_Mcs12)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_Rate18_06)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_Rate54_24)); + *(unsigned int *)(&priv->pshare->phw->CCKTxAgc_A[0]) = cpu_to_be32((RTL_R32(rTxAGC_A_CCK11_2_B_CCK11) & 0xffffff00) + | RTL_R8(rTxAGC_A_CCK1_Mcs32 + 1)); + +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs03_Mcs00)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs07_Mcs04)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[8]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs11_Mcs08)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[12]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs15_Mcs12)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Rate18_06)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Rate54_24)); + *(unsigned int *)(&priv->pshare->phw->CCKTxAgc_A[0]) = cpu_to_be32((RTL_R8(rTxAGC_A_CCK11_2_B_CCK11) << 24) + | (RTL_R32(rTxAGC_B_CCK5_1_Mcs32) >> 8)); + } +#endif + + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs03_Mcs00)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs07_Mcs04)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[8]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs11_Mcs08)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[12]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs15_Mcs12)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_B[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Rate18_06)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_B[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Rate54_24)); + *(unsigned int *)(&priv->pshare->phw->CCKTxAgc_B[0]) = cpu_to_be32((RTL_R8(rTxAGC_A_CCK11_2_B_CCK11) << 24) + | (RTL_R32(rTxAGC_B_CCK5_1_Mcs32) >> 8)); + + } + + +#ifdef TXPWR_LMT + if (!priv->pshare->rf_ft_var.disable_txpwrlmt) { + //4 Set Target Power from PG table values + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188E)) //92c_pwrlmt + { + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { + //CCK + priv->pshare->tgpwr_CCK_new[RF_PATH_A] = priv->pshare->phw->CCKTxAgc_A[0]; + priv->pshare->tgpwr_CCK_new[RF_PATH_B] = priv->pshare->phw->CCKTxAgc_B[0]; + //4 Set PG table values to difference + for (i=0;i<4;i++) { + priv->pshare->phw->CCKTxAgc_A[i] -= priv->pshare->tgpwr_CCK_new[RF_PATH_A]; + priv->pshare->phw->CCKTxAgc_B[i] -= priv->pshare->tgpwr_CCK_new[RF_PATH_B]; + } + } + //OFDM + priv->pshare->tgpwr_OFDM_new[RF_PATH_A] = priv->pshare->phw->OFDMTxAgcOffset_A[4]; + priv->pshare->tgpwr_OFDM_new[RF_PATH_B] = priv->pshare->phw->OFDMTxAgcOffset_B[4]; + for (i=0;i<8;i++) { + priv->pshare->phw->OFDMTxAgcOffset_A[i] -= priv->pshare->tgpwr_OFDM_new[RF_PATH_A]; + priv->pshare->phw->OFDMTxAgcOffset_B[i] -= priv->pshare->tgpwr_OFDM_new[RF_PATH_B]; + } + + //HT-1S + priv->pshare->tgpwr_HT1S_new[RF_PATH_A] = priv->pshare->phw->MCSTxAgcOffset_A[4]; + priv->pshare->tgpwr_HT1S_new[RF_PATH_B] = priv->pshare->phw->MCSTxAgcOffset_B[4]; + for (i=0;i<8;i++) { + priv->pshare->phw->MCSTxAgcOffset_A[i] -= priv->pshare->tgpwr_HT1S_new[RF_PATH_A]; + priv->pshare->phw->MCSTxAgcOffset_B[i] -= priv->pshare->tgpwr_HT1S_new[RF_PATH_B]; + } + + //HT-2S + priv->pshare->tgpwr_HT2S_new[RF_PATH_A] = priv->pshare->phw->MCSTxAgcOffset_A[12]; + priv->pshare->tgpwr_HT2S_new[RF_PATH_B] = priv->pshare->phw->MCSTxAgcOffset_B[12]; + for (i=8;i<16;i++) { + priv->pshare->phw->MCSTxAgcOffset_A[i] -= priv->pshare->tgpwr_HT2S_new[RF_PATH_A]; + priv->pshare->phw->MCSTxAgcOffset_B[i] -= priv->pshare->tgpwr_HT2S_new[RF_PATH_B]; + } + } + } +#endif + +#ifdef ADD_TX_POWER_BY_CMD + assign_txpwr_offset(priv); +#endif +} + +#ifdef USE_OUT_SRC + +void ODM_software_init(struct rtl8192cd_priv *priv) +{ + unsigned long ability; + unsigned int BoardType = ODM_BOARD_DEFAULT; + priv->pshare->_dmODM.priv = priv; + + // + // Init Value + // + // 1. u1Byte SupportPlatform + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_PLATFORM, ODM_AP); + +#if 0// defined(CONFIG_RTL_92E_SUPPORT) && defined(CONFIG_HW_ANTENNA_DIVERSITY) + ODM_CmnInfoInit(ODMPTR,ODM_CMNINFO_RF_ANTENNA_TYPE,CGCS_RX_HW_ANTDIV); +#endif + // 2. u4Byte SupportAbility + ability = \ + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_BB_RATE_ADAPTIVE | + ODM_MAC_EDCA_TURBO | + ODM_RF_RX_GAIN_TRACK | + ODM_RF_CALIBRATION | + ODM_BB_DYNAMIC_TXPWR | + ODM_RF_TX_PWR_TRACK | + ODM_BB_NHM_CNT | + ODM_BB_PRIMARY_CCA | + 0; + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + ability = \ + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_MAC_EDCA_TURBO | + ODM_BB_RSSI_MONITOR | + ODM_BB_DYNAMIC_TXPWR | + ODM_RF_TX_PWR_TRACK | + ODM_RF_CALIBRATION | + ODM_BB_NHM_CNT | + 0; + } +#endif + +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv) == VERSION_8881A) { + ability = \ + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_MAC_EDCA_TURBO | + ODM_BB_RSSI_MONITOR | + ODM_BB_DYNAMIC_TXPWR | + ODM_RF_TX_PWR_TRACK | + ODM_RF_CALIBRATION | + ODM_BB_NHM_CNT | + 0; + } +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + ability = \ + ODM_BB_DIG | + ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + ODM_MAC_EDCA_TURBO | + ODM_BB_DYNAMIC_TXPWR | + ODM_RF_TX_PWR_TRACK | + ODM_RF_CALIBRATION | + ODM_BB_CCK_PD | + ODM_BB_NHM_CNT | + 0; + } +#endif + +#ifdef CONFIG_WLAN_HAL_8814AE + if (GET_CHIP_VER(priv) == VERSION_8814A) { + ability = ODM_BB_DIG | +// ODM_BB_RA_MASK | + ODM_BB_FA_CNT | + ODM_BB_RSSI_MONITOR | + //ODM_MAC_EDCA_TURBO | + ODM_BB_DYNAMIC_TXPWR | + ODM_RF_TX_PWR_TRACK | +// ODM_RF_CALIBRATION | + ODM_BB_CCK_PD | + 0; + } +#endif + + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { + ability = \ + ODM_RF_CALIBRATION | + ODM_RF_TX_PWR_TRACK | + ODM_BB_FA_CNT | + 0; + } + +#if defined(SW_ANT_SWITCH) + if (priv->pshare->rf_ft_var.antSw_enable) + ability |= ODM_BB_ANT_DIV; +#endif +#ifdef TX_EARLY_MODE + ability |= ODM_MAC_EARLY_MODE; +#endif + + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_ABILITY, ability); + ODM_CmnInfoUpdate(ODMPTR, ODM_CMNINFO_ABILITY, ability); + + // 3. u1Byte SupportInterface +#ifdef CONFIG_PCI_HCI + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_INTERFACE, ODM_ITRF_PCIE); +#elif defined(CONFIG_USB_HCI) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_INTERFACE, ODM_ITRF_USB); +#elif defined(CONFIG_SDIO_HCI) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_INTERFACE, ODM_ITRF_SDIO); +#endif + + // 4. u4Byte SupportICType + if (GET_CHIP_VER(priv) == VERSION_8188E) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_IC_TYPE, ODM_RTL8188E); + else if (GET_CHIP_VER(priv) == VERSION_8812E) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_IC_TYPE, ODM_RTL8812); + else if (GET_CHIP_VER(priv) == VERSION_8881A) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_IC_TYPE, ODM_RTL8881A); + else if (GET_CHIP_VER(priv) == VERSION_8192E) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_IC_TYPE, ODM_RTL8192E); + else if (GET_CHIP_VER(priv) == VERSION_8814A) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_IC_TYPE, ODM_RTL8814A); + + // 5. u1Byte CutVersion + if (IS_TEST_CHIP(priv)) { + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_CUT_VER, ODM_CUT_TEST); + } else { + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_CUT_VER, (RTL_R32(SYS_CFG) >> 12) & 0xF); + + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_MP_TEST_CHIP, 1); + } + + // 6. u1Byte FabVersion + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_FAB_VER, ODM_TSMC); + + // 7. u1Byte RFType + if (get_rf_mimo_mode(priv) == MIMO_1T1R) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_1T1R); + else if (get_rf_mimo_mode(priv) == MIMO_1T2R) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_1T2R); + else if (get_rf_mimo_mode(priv) == MIMO_2T2R) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_2T2R); + //else if (get_rf_mimo_mode(priv) == MIMO_2T2R_GREEN) + //ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_2T2R_GREEN); + else if (get_rf_mimo_mode(priv) == MIMO_2T3R) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_2T3R); + else if (get_rf_mimo_mode(priv) == MIMO_2T4R) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_2T4R); + else if (get_rf_mimo_mode(priv) == MIMO_3T3R) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_3T3R); + else if (get_rf_mimo_mode(priv) == MIMO_3T4R) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_3T4R); + else if (get_rf_mimo_mode(priv) == MIMO_4T4R) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_4T4R); + else + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RF_TYPE, ODM_XTXR); + + // 8. u1Byte BoardType +#if defined(HIGH_POWER_EXT_PA) && defined(HIGH_POWER_EXT_LNA) + if(priv->pshare->rf_ft_var.use_ext_pa && priv->pshare->rf_ft_var.use_ext_lna) { //For 88C/92C only + priv->pmib->dot11RFEntry.trswitch = 1; + } +#endif + +#ifdef HIGH_POWER_EXT_PA + if(priv->pshare->rf_ft_var.use_ext_pa) + { + if(GET_CHIP_VER(priv) == VERSION_8814A) + BoardType |= (ODM_BOARD_EXT_LNA|ODM_BOARD_EXT_LNA_5G|ODM_BOARD_EXT_PA|ODM_BOARD_EXT_PA_5G); + else if((GET_CHIP_VER(priv) == VERSION_8812E)||(GET_CHIP_VER(priv) == VERSION_8881A)) + BoardType |= ODM_BOARD_EXT_PA_5G; + else //2G Chip: 92C/88E/92E + BoardType |= (ODM_BOARD_EXT_LNA|ODM_BOARD_EXT_PA); + } +#endif +#ifdef HIGH_POWER_EXT_LNA + if(priv->pshare->rf_ft_var.use_ext_lna){ + if((GET_CHIP_VER(priv) == VERSION_8812E)||(GET_CHIP_VER(priv) == VERSION_8881A)) + BoardType |= ODM_BOARD_EXT_LNA_5G; + else if((GET_CHIP_VER(priv) == VERSION_8188E)||(GET_CHIP_VER(priv) == VERSION_8192E)) + BoardType |= ODM_BOARD_EXT_LNA; + } +#endif + if(priv->pmib->dot11RFEntry.trswitch) + BoardType |= ODM_BOARD_EXT_TRSW; + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_BOARD_TYPE, BoardType); + + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_RFE_TYPE, priv->pmib->dot11RFEntry.rfe_type); + + // ExtLNA & ExtPA Type + if(GET_CHIP_VER(priv) == VERSION_8812E) + { + if(priv->pmib->dot11RFEntry.pa_type == PA_SKYWORKS_5023) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_APA, 0x05); + else + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_APA, 0x00); + + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GPA, 0x00); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GLNA, 0x00); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_ALNA, 0x00); + } + else if(GET_CHIP_VER(priv) == VERSION_8814A) + { + if(priv->pmib->dot11RFEntry.rfe_type == 2) { + panic_printk("PHY paratemters: RFE type 2 APA1+ALNA1+GPA1+GLNA1\n"); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GPA, TYPE_GPA1); // path (A,B,C,D) = (1,1,1,1) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_APA, TYPE_APA1); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GLNA, TYPE_GLNA1); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_ALNA, TYPE_ALNA1); + } else if(priv->pmib->dot11RFEntry.rfe_type == 3) { + panic_printk("PHY paratemters: RFE type 3 APA2+ALNA2+GPA2+GLNA2\n"); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GPA, TYPE_GPA2); // path (A,B,C,D) = (2,2,2,2) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_APA, TYPE_APA2); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GLNA, TYPE_GLNA2); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_ALNA, TYPE_ALNA2); + } else if(priv->pmib->dot11RFEntry.rfe_type == 4) { + panic_printk("PHY paratemters: RFE type 4 APA1+ALNA3+GPA1+GLNA1\n"); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GPA, TYPE_GPA1); // path (A,B,C,D) = (2,2,2,2) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_APA, TYPE_APA1); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GLNA, TYPE_GLNA1); // path (A,B,C,D) = (3,3,3,3) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_ALNA, TYPE_ALNA3); + } else if(priv->pmib->dot11RFEntry.rfe_type == 5) { + panic_printk("PHY paratemters: RFE type 5 APA2+ALNA4+GPA2+GLNA2\n"); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GPA, TYPE_GPA2); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_APA, TYPE_APA2); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GLNA, TYPE_GLNA2); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_ALNA, TYPE_ALNA4); + } else if(priv->pmib->dot11RFEntry.rfe_type == 0){ + panic_printk("PHY paratemters: RFE type 0\n"); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GPA, TYPE_GPA0); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_APA, TYPE_APA0); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GLNA, TYPE_GLNA0); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_ALNA, TYPE_ALNA0); + }else { + panic_printk("PHY paratemters: Unknow RFE type!!\n"); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GPA, TYPE_GPA0); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_APA, TYPE_APA0); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_GLNA, TYPE_GLNA0); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_ALNA, TYPE_ALNA0); + } + } + //Package Type => To Be Done! + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_PACKAGE_TYPE, 0); +#ifdef HIGH_POWER_EXT_PA + //priv->pshare->rf_ft_var.use_ext_lna is useless + if(priv->pshare->rf_ft_var.use_ext_pa) + { + // 9. u1Byte ExtLNA + if ((GET_CHIP_VER(priv) == VERSION_8188E)||(GET_CHIP_VER(priv) == VERSION_8192E)) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_EXT_LNA, TRUE); + else + { + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_EXT_LNA, TRUE); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_5G_EXT_LNA, TRUE); + } + + // 10. u1Byte ExtPA + if ((GET_CHIP_VER(priv) == VERSION_8188E)||(GET_CHIP_VER(priv) == VERSION_8192E)) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_EXT_PA, TRUE); + else + { + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_EXT_PA, TRUE); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_5G_EXT_PA, TRUE); + } + } +#endif +#ifdef HIGH_POWER_EXT_LNA + if(priv->pshare->rf_ft_var.use_ext_lna){ + // 9. u1Byte ExtLNA + if ((GET_CHIP_VER(priv) == VERSION_8188E)||(GET_CHIP_VER(priv) == VERSION_8192E)){ + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_EXT_LNA, TRUE); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_EXT_LNA_GAIN, + priv->pshare->rf_ft_var.ext_lna_gain); + }else{ + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_EXT_LNA, TRUE); + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_5G_EXT_LNA, TRUE); + } + } +#endif + + // 11. u1Byte ExtTRSW, ODM_CMNINFO_EXT_TRSW: + // follows variable "trswitch" which is modified in rtl8192cd_init_hw_PCI(). + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_EXT_TRSW, priv->pmib->dot11RFEntry.trswitch); + + // 12. u1Byte PatchID + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_PATCH_ID, 0); + + // 13. BOOLEAN bInHctTest + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_BINHCT_TEST, FALSE); + + // 14. BOOLEAN bWIFITest + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_BWIFI_TEST, (priv->pmib->dot11OperationEntry.wifi_specific > 0)); + + // 15. BOOLEAN bDualMacSmartConcurrent + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_SMART_CONCURRENT, FALSE); + + // Config BB/RF by ODM + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8814A)) + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_CONFIG_BB_RF, TRUE); + else + ODM_CmnInfoInit(ODMPTR, ODM_CMNINFO_CONFIG_BB_RF, FALSE); + + // + // Dynamic Value + // + + // 1. u1Byte *pMacPhyMode + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_MAC_PHY_MODE, &priv->pmib->dot11RFEntry.macPhyMode); + + // 2. u8Byte *pNumTxBytesUnicast + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_TX_UNI, &priv->pshare->NumTxBytesUnicast); + + // 3. u8Byte *pNumRxBytesUnicast + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_RX_UNI, &priv->pshare->NumRxBytesUnicast); + + // 4. u1Byte *pWirelessMode + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_WM_MODE, &priv->pmib->dot11BssType.net_work_type); + + // 5. u1Byte *pBandType + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_BAND, &priv->pmib->dot11RFEntry.phyBandSelect); + + // 6. u1Byte *pSecChOffset + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_SEC_CHNL_OFFSET, &priv->pshare->offset_2nd_chan); + + // 7. u1Byte *pSecurity + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_SEC_MODE, &priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm); + + // 8. u1Byte *pBandWidth + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_BW, &priv->pshare->CurrentChannelBW); + + // 9. u1Byte *pChannel +// ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_CHNL, &priv->pshare->working_channel); + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_CHNL, &priv->pmib->dot11RFEntry.dot11channel); + + // 10. BOOLEAN *pbMasterOfDMSP +// ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_DMSP_IS_MASTER, NULL); + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_DMSP_IS_MASTER, &priv->pshare->dummy); + + + // 11. BOOLEAN *pbGetValueFromOtherMac +// ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_DMSP_GET_VALUE, NULL); + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_DMSP_GET_VALUE, &priv->pshare->dummy); + + // 12. PADAPTER *pBuddyAdapter + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_BUDDY_ADAPTOR, NULL); + + // 13. BOOLEAN *pbBTOperation +// ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_BT_OPERATION, NULL); + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_BT_OPERATION, &priv->pshare->dummy); + + // 14. BOOLEAN *pbBTDisableEDCATurbo +// ODM_CmnInfoHook(pOdm, ODM_CMNINFO_BT_DISABLE_EDCA, NULL); + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_BT_DISABLE_EDCA, &priv->pshare->dummy); + + + // 15. BOOLEAN *pbScanInProcess + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_SCAN, &priv->pshare->bScanInProcess); + + // 16. pU4byte force data rate add by YuChen + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_FORCED_RATE, &priv->pshare->current_tx_rate); + + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_POWER_SAVING, &priv->pshare->dummy); + + + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_ONE_PATH_CCA, &priv->pshare->rf_ft_var.one_path_cca); + + +// dummy + + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_DRV_STOP, &priv->pshare->dummy); + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_PNP_IN, &priv->pshare->dummy); + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_INIT_ON, &priv->pshare->dummy); + ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_BT_BUSY, &priv->pshare->dummy); +// ODM_CmnInfoHook(ODMPTR, ODM_CMNINFO_ANT_DIV, &priv->pshare->dummy); + + //For Phy para verison + ODM_GetHWImgVersion(ODMPTR); + + +// DM parameters init +// ODM_DMInit(ODMPTR); + + ODM_InitAllTimers(ODMPTR); + +#ifdef TPT_THREAD +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif +#ifdef SMART_REPEATER_MODE + if (!priv->pshare->switch_chan_rp) +#endif + ODM_InitAllThreads(ODMPTR); +#endif +} + +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + +unsigned int getval_8b4(struct rtl8192cd_priv *priv, unsigned char rf_path) +{ + unsigned int tmp_8b4 = 0; + unsigned int delay = priv->pshare->rf_ft_var.delay_8b4; +#if 1 + if (rf_path == RF_PATH_A) + RTL_W8(0x804, 0x3); + else if (rf_path == RF_PATH_B) + RTL_W8(0x804, 0x13); + + RTL_W32(0x808, 0xfccd); + RTL_W32(0x808, 0x40fccd); +#else + if(rf_path == RF_PATH_A) + { + RTL_W8(0xc50, 0x20); + PHY_SetRFReg(priv, RF_PATH_A, 0, bRFRegOffsetMask, 0x33e00); + RTL_W8(0x804, 0x3); + RTL_W32(0x808, 0xfccd); + RTL_W32(0x808, 0x40fccd); + } + else if(rf_path == RF_PATH_B) + { + RTL_W8(0xc58, 0x20); + PHY_SetRFReg(priv, RF_PATH_B, 0, bRFRegOffsetMask, 0x33e00); + RTL_W8(0x804, 0x13); + RTL_W32(0x808, 0xfccd); + RTL_W32(0x808, 0x40fccd); + } +#endif + delay_ms(delay); + tmp_8b4 = RTL_R32(0x8b4); + + //printk("tmp_8b4[%d] = 0x%x \n", rf_path, tmp_8b4); + + return tmp_8b4; +} + + +void Check_92E_Spur_Valid(struct rtl8192cd_priv * priv, BOOLEAN long_delay) +{ +#ifdef CONFIG_PCI_HCI + unsigned char tmp_loop = 0; + unsigned int path_a_8b4 = 0, Reg0x804 = 0, Reg0x808 = 0; + unsigned int path_b_8b4 = 0; +// unsigned long flags; + unsigned int channel_bak, bw_bak, Offset2nd_bak; + + watchdog_kick(); +// watchdog_stop(priv); + + Reg0x804 = RTL_R32(0x804); + Reg0x808 = RTL_R32(0x808); + bw_bak = priv->pshare->CurrentChannelBW; + Offset2nd_bak = priv->pshare->offset_2nd_chan; + channel_bak = priv->pmib->dot11RFEntry.dot11channel; + //RESTORE_INT(flags); + + // Switch to channel 13, bw = 20M + SwBWMode(priv, HT_CHANNEL_WIDTH_20, HT_2NDCH_OFFSET_DONTCARE); + SwChnl(priv, 13, HT_2NDCH_OFFSET_DONTCARE); + + RTL_W8(0xc50, 0x30); + RTL_W8(0xc58, 0x30); + + //PHY_SetRFReg(priv, RF_PATH_A, 0x0, bMask20Bits, 0x0); + RTL_W32(0x88c, 0xccf000c0); //disable 3-wire + + + path_a_8b4 = getval_8b4(priv, RF92CD_PATH_A); + path_b_8b4 = getval_8b4(priv, RF92CD_PATH_B); + + for(tmp_loop = 0 ; tmp_loop < priv->pshare->rf_ft_var.loop_8b4 ; tmp_loop ++) { + if (path_a_8b4 > priv->pshare->rf_ft_var.thrd_8b4 || path_b_8b4 > priv->pshare->rf_ft_var.thrd_8b4) { + //PLL reset + if (long_delay) + delay_ms(10); + RTL_W8(0x29, 0x7); + if (long_delay) + delay_ms(10); + RTL_W8(0x29, 0x47); + + path_a_8b4 = getval_8b4(priv, RF92CD_PATH_A); + path_b_8b4 = getval_8b4(priv, RF92CD_PATH_B); + } else { + break; + } + watchdog_kick(); + } + + if (tmp_loop == priv->pshare->rf_ft_var.loop_8b4) { + priv->pshare->PLL_reset_ok = false; + printk("\n[Loop#%d] 0x8b4 = 0x%x[A] 0x%x[B], FAIL1 !!\n\n", tmp_loop, path_a_8b4, path_b_8b4); +#if 0 + if (long_delay) { + for(tmp_loop = 0 ; tmp_loop < priv->pshare->rf_ft_var.loop_8b4 ; tmp_loop ++) { + if (path_a_8b4 > priv->pshare->rf_ft_var.thrd_8b4 || path_b_8b4 > priv->pshare->rf_ft_var.thrd_8b4) { + //PLL reset + delay_ms(20); + RTL_W8(0x29, 0x7); + delay_ms(20); + RTL_W8(0x29, 0x47); + + path_a_8b4 = getval_8b4(priv, RF92CD_PATH_A); + path_b_8b4 = getval_8b4(priv, RF92CD_PATH_B); + } else { + break; + } + } + + if (tmp_loop == priv->pshare->rf_ft_var.loop_8b4) { + priv->pshare->PLL_reset_ok = false; + printk("\n[Loop#%d] 0x8b4 = 0x%x[A] 0x%x[B], FAIL2 !!\n\n", tmp_loop, path_a_8b4, path_b_8b4); + } else { + priv->pshare->PLL_reset_ok = true; + printk("\n[Loop#%d] 0x8b4 = 0x%x[A] 0x%x[B], OK2 !!\n\n", tmp_loop+1, path_a_8b4, path_b_8b4); + } + } +#endif + } else { + printk("\n[Loop#%d] 0x8b4 = 0x%x[A] 0x%x[B], OK !!\n\n", tmp_loop+1, path_a_8b4, path_b_8b4); + priv->pshare->PLL_reset_ok = true; + } + + RTL_W32(0x88c, 0xcc0000c0); //enable 3-wire + + RTL_W8(0xc50, 0x20); + RTL_W8(0xc58, 0x20); + RTL_W32(0x804, Reg0x804); + RTL_W32(0x808, Reg0x808); + + SwBWMode(priv, bw_bak, Offset2nd_bak); + SwChnl(priv, channel_bak, Offset2nd_bak); + //SAVE_INT_AND_CLI(flags); +#endif // CONFIG_PCI_HCI + + if (priv->pmib->dot11RFEntry.dot11channel == 13) { + PHY_SetBBReg(priv, 0xd18, BIT(27), 1); + PHY_SetBBReg(priv, 0xd2C, BIT(28), 1); + PHY_SetBBReg(priv, 0xd40, BIT(26), 1); + } else { + PHY_SetBBReg(priv, 0xd18, BIT(27), 0); + PHY_SetBBReg(priv, 0xd2C, BIT(28), 0); + PHY_SetBBReg(priv, 0xd40, BIT(26), 0); + } + +// watchdog_resume(priv); +} + +#endif // CONFIG_WLAN_HAL_8192EE + +// Note: Not all FW version support H2C cmd for disable beacon when edcca on +// 92e -> v28+, 8812 -> v43+, 8881a -> v10+ +void set_bcn_dont_ignore_edcca(struct rtl8192cd_priv *priv) +{ + BOOLEAN carrier_sense_enable = FALSE, + bcn_dont_ignore_edcca = priv->pshare->rf_ft_var.bcn_dont_ignore_edcca, + adaptivity_enable = priv->pshare->rf_ft_var.adaptivity_enable; + +#ifdef USE_OUT_SRC + if (IS_OUTSRC_CHIP(priv)) + carrier_sense_enable = ODMPTR->Carrier_Sense_enable; +#endif + + if ( carrier_sense_enable || (adaptivity_enable && bcn_dont_ignore_edcca) ) { + + DEBUG_INFO("set bcn care edcca\n"); + +#if defined(deCONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8192EE) + if ( (GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv)== VERSION_8192E) ) { + unsigned char H2CCommand[1]={0}; + GET_HAL_INTERFACE(priv)->FillH2CCmdHandler(priv, H2C_88XX_BCN_IGNORE_EDCCA, 1, H2CCommand); + } +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + unsigned char H2CCommand[1]={0}; + FillH2CCmd8812(priv, H2C_8812_BCN_IGNORE_EDCCA, 1, H2CCommand); + } +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + unsigned int content = 0; + unsigned int h2c_cmd_bcn_ignore_edcca = 0xC2; + + content |= h2c_cmd_bcn_ignore_edcca; + signin_h2c_cmd(priv, content, 0); + } +#endif +#endif + } +} + +int rtl8192cd_init_hw_PCI(struct rtl8192cd_priv *priv) +{ + struct wifi_mib *pmib; + unsigned int opmode; + unsigned long val32; + unsigned short val16; + int i; +#ifdef CONFIG_WLAN_HAL + unsigned int errorFlag = 0; +#endif +#ifndef SMP_SYNC + unsigned long x; +#endif +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + unsigned int fwStatus = 0, dwnRetry = 5; +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + unsigned int c50_bak, e50_bak; +#endif + SAVE_INT_AND_CLI(x); + + pmib = GET_MIB(priv); + opmode = priv->pmib->dot11OperationEntry.opmode; + + DBFENTER; + +//1 For Test, Firmware Downloading + +// MacConfigBeforeFwDownload(priv); + +#if 0 // ==========>> later + // =========================================================================================== + // Download Firmware + // allocate memory for tx cmd packet + if ((priv->pshare->txcmd_buf = (unsigned char *)kmalloc((LoadPktSize), GFP_ATOMIC)) == NULL) { + printk("not enough memory for txcmd_buf\n"); + return -1; + } + + priv->pshare->cmdbuf_phyaddr = get_physical_addr(priv, priv->pshare->txcmd_buf, + LoadPktSize, PCI_DMA_TODEVICE); + + if (LoadFirmware(priv) == FALSE) { +// panic_printk("Load Firmware Fail!\n"); + panic_printk("Load Firmware check!\n"); + return -1; + } else { +// delay_ms(20); + PRINT_INFO("Load firmware successful! \n"); + } +#endif +// MacConfigAfterFwDownload(priv); + +#if 0 // defined(CONFIG_RTL_92D_SUPPORT) && defined(MP_TEST) // 92D MP DUAL-PHY SETTING + if (priv->pshare->rf_ft_var.mp_specific && (GET_CHIP_VER(priv) == VERSION_8192D)) + priv->pmib->dot11RFEntry.macPhyMode = DUALMAC_DUALPHY; + //priv->pmib->dot11RFEntry.macPhyMode = SINGLEMAC_SINGLEPHY; +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + check_chipID_MIMO(priv); + } +#endif +#if 0 //def CONFIG_RTL_92D_SUPPORT + if (check_MacPhyMode(priv) < 0) { + printk("Check macPhyMode Fail!\n"); + return -1; + } +#endif + +#ifdef USE_OUT_SRC + if (IS_OUTSRC_CHIP(priv)) + ODM_software_init(priv); +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + + unsigned int ClkSel = XTAL_CLK_SEL_40M; + +#if defined(CONFIG_AUTO_PCIE_PHY_SCAN) + // Get XTAL information from platform +#if defined(CONFIG_RTL_8881A) + if ((REG32(0xb8000008) & 0x1000000) != 0x1000000) + ClkSel = XTAL_CLK_SEL_25M; + else + ClkSel = XTAL_CLK_SEL_40M; +#elif defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_819XD) + if ((REG32(0xb8000008) & 0x2000000) != 0x2000000) + ClkSel = XTAL_CLK_SEL_25M; + else + ClkSel = XTAL_CLK_SEL_40M; +#endif + +#else + // independent with platform +#ifdef CONFIG_PHY_WLAN_EAT_40MHZ + ClkSel = XTAL_CLK_SEL_40M; +#else + ClkSel = XTAL_CLK_SEL_25M; +#endif //CONFIG_PHY_EAT_40MHZ +#endif //defined(CONFIG_AUTO_PCIE_PHY_SCAN) + + + if ( RT_STATUS_SUCCESS != GET_HAL_INTERFACE(priv)->InitPONHandler(priv, ClkSel) ) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_INIT_PON; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + panic_printk("InitPON Failed\n"); + } else { + printk("InitPON OK\n"); + } + + if ( RT_STATUS_SUCCESS != GET_HAL_INTERFACE(priv)->InitMACHandler(priv) ) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_INIT_MAC; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + panic_printk("InitMAC Failed\n"); + RESTORE_INT(x); + return -1; + } else { + + printk("InitMAC OK\n"); + } + +#ifdef CONFIG_PCI_HCI + if ( RT_STATUS_SUCCESS != GET_HAL_INTERFACE(priv)->InitHCIDMARegHandler(priv) ) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_INIT_HCIDMA; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + panic_printk("InitHCIDMAReg Failed\n"); + } else { + printk("InitHCIDMAReg OK\n"); + } +#endif + +#ifdef CONFIG_WLAN_HAL_8881A + //Filen, according to RLE0538 setting + if (GET_CHIP_VER(priv) == VERSION_8881A) { + //set RF register as PI mode + RTL_W8(0xc00, RTL_R8(0xc00) | BIT(2)); + RTL_W8(0xe00, RTL_R8(0xe00) | BIT(2)); + } +#endif // CONFIG_WLAN_HAL_8881A + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#ifdef CONFIG_RTL_8812_SUPPORT + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5){ + unsigned int dwTmp1,dwTmp2,dwTmp3 = 0; + dwTmp1 = RTL_R8(0x301); + dwTmp2 = RTL_R32(0x808); + dwTmp2 &= ~(BIT(28) | BIT(29)); + RTL_W8(REG_RSV_CTRL_8812, 0x0); // Enable to write page 3 reg + RTL_W8(0x301,0xff); // Close dma before clock set to 5M + RTL_W8(0x303,0x80); + RTL_W32 (0x808,dwTmp2); + dwTmp3 = RTL_R8(0x8); + dwTmp3 &= ~(BIT(7) | BIT(6)); + dwTmp3 |= BIT(7); + RTL_W8(0x8,dwTmp3); + RTL_W8(0x301,dwTmp1);// rewrite 301 to default + RTL_W8(REG_RSV_CTRL_8812, 0x0e); + } +#endif + if (MacInit(priv) == FALSE) { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + printk("Mac Init failed!!\n"); + RESTORE_INT(x); + return -1; +#endif + } + } + +// RTL_W32(AGGLEN_LMT, RTL_R32(AGGLEN_LMT)|(0x0F&AGGLMT_MCS15S_Mask)<ConfigBBRF) + { + ODM_ConfigMACWithHeaderFile(ODMPTR); + }else +#endif + { + panic_printk("\n\n************* Initialize MAC/PHY parameter *************\n"); + if (PHY_ConfigMACWithParaFile(priv) < 0) { + #ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_INIT_MACPHYREGFILE; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + } + #endif + printk("Initialize MAC/PHY Config failure\n"); + RESTORE_INT(x); + return -1; + } + + } + if(IS_C_CUT_8192E(priv)) + { + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5 + || priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_10) + RTL_W8(0x303,0x80); + } + + // + // 3. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt + // + +#ifdef DRVMAC_LB + if (!priv->pmib->miscEntry.drvmac_lb) +#endif + { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + RESTORE_INT(x); + val32 = phy_BB88XX_Config_ParaFile(priv); + SAVE_INT_AND_CLI(x); + if (val32) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_INIT_BBEGFILE; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + printk("Initialize phy_BB88XX_Config_ParaFile failure\n"); + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + val32 = phy_BB8192CD_Config_ParaFile(priv); + if (val32) { + RESTORE_INT(x); + return -1; + } + } + + if (priv->pmib->dot11nConfigEntry.dot11nLDPC) + RTL_W8(0x913, RTL_R8(0x913)|0x02); + else + RTL_W8(0x913, RTL_R8(0x913)&~0x02); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (priv->pmib->dot11RFEntry.xcap != 0xff) { + PHY_SetBBReg(priv, 0x24, 0xF0, priv->pmib->dot11RFEntry.xcap & 0x0F); + PHY_SetBBReg(priv, 0x28, 0xF0000000, ((priv->pmib->dot11RFEntry.xcap & 0xF0) >> 4)); + } + } +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + if (priv->pmib->dot11RFEntry.xcap > 0 && priv->pmib->dot11RFEntry.xcap < 0x3F) { + int org_val, tmp_val; + org_val = (RTL_R32(0x24) >> 11) & 0x3F; + if (org_val > priv->pmib->dot11RFEntry.xcap) { + for (tmp_val=org_val; tmp_val>=priv->pmib->dot11RFEntry.xcap; tmp_val--) { + PHY_SetBBReg(priv, 0x24, BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16), tmp_val & 0x3F); + PHY_SetBBReg(priv, 0x24, BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22), tmp_val & 0x3F); + } + } + else { + for (tmp_val=org_val; tmp_val<=priv->pmib->dot11RFEntry.xcap; tmp_val++) { + PHY_SetBBReg(priv, 0x24, BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16), tmp_val & 0x3F); + PHY_SetBBReg(priv, 0x24, BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22), tmp_val & 0x3F); + } + } + } + } +#endif + +#if defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_WLAN_HAL_8881A) + if ((GET_CHIP_VER(priv)== VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + if (priv->pmib->dot11RFEntry.xcap > 0 && priv->pmib->dot11RFEntry.xcap < 0x3F) { + int org_val, tmp_val; + org_val = (RTL_R32(0x2C) >> 12) & 0x3F; + if (org_val > priv->pmib->dot11RFEntry.xcap) { + for (tmp_val=org_val; tmp_val>=priv->pmib->dot11RFEntry.xcap; tmp_val--) { + PHY_SetBBReg(priv, 0x2C, BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17), tmp_val & 0x3F); + PHY_SetBBReg(priv, 0x2C, BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23), tmp_val & 0x3F); + } + } + else { + for (tmp_val=org_val; tmp_val<=priv->pmib->dot11RFEntry.xcap; tmp_val++) { + PHY_SetBBReg(priv, 0x2C, BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17), tmp_val & 0x3F); + PHY_SetBBReg(priv, 0x2C, BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23), tmp_val & 0x3F); + } + } + } + } +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (priv->pmib->dot11RFEntry.xcap > 0 && priv->pmib->dot11RFEntry.xcap < 0x3F) { + int org_val, tmp_val; + org_val = (RTL_R32(0x2C) >> 19) & 0x3F; + if (org_val > priv->pmib->dot11RFEntry.xcap) { + for (tmp_val=org_val; tmp_val>=priv->pmib->dot11RFEntry.xcap; tmp_val--) { + PHY_SetBBReg(priv, 0x2C, BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23) | BIT(24), tmp_val & 0x3F); + PHY_SetBBReg(priv, 0x2C, BIT(25) | BIT(26) | BIT(27) | BIT(28) | BIT(29) | BIT(30), tmp_val & 0x3F); + } + } + else { + for (tmp_val=org_val; tmp_val<=priv->pmib->dot11RFEntry.xcap; tmp_val++) { + PHY_SetBBReg(priv, 0x2C, BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23) | BIT(24), tmp_val & 0x3F); + PHY_SetBBReg(priv, 0x2C, BIT(25) | BIT(26) | BIT(27) | BIT(28) | BIT(29) | BIT(30), tmp_val & 0x3F); + } + } + } + + // chang initial gain to avoid loading wrong AGC table, by Arthur + c50_bak = RTL_R8(0xc50); + e50_bak = RTL_R8(0xe50); + + RTL_W8(0xc50, 0x22); + RTL_W8(0xe50, 0x22); + + RTL_W8(0xc50, c50_bak); + RTL_W8(0xe50, e50_bak); + } +#endif + + // support up to MCS7 for 1T1R, modify rx capability here + /* + if (get_rf_mimo_mode(priv) == MIMO_1T1R) + pmib->dot11nConfigEntry.dot11nSupportedMCS &= 0x00ff; + + */ + /* + // Set NAV protection length + // CF-END Threshold + if (priv->pmib->dot11OperationEntry.wifi_specific) { + RTL_W16(NAV_PROT_LEN, 0x80); + // RTL_W8(CFEND_TH, 0x2); + } + else { + RTL_W16(NAV_PROT_LEN, 0x01C0); + // RTL_W8(CFEND_TH, 0xFF); + } + */ + // + // 4. Initiailze RF RAIO_A.txt RF RAIO_B.txt + // + // 2007/11/02 MH Before initalizing RF. We can not use FW to do RF-R/W. + // close loopback, normal mode + + // For RF test only from Scott's suggestion +// RTL_W8(0x27, 0xDB); // ==========>> ??? +// RTL_W8(0x1B, 0x07); // ACUT + + /* + // set RCR: RX_SHIFT and disable ACF + // RTL_W8(0x48, 0x3e); + // RTL_W32(0x48, RTL_R32(0x48) & ~ RCR_ACF & ~RCR_ACRC32); + RTL_W16(RCR, RCR_AAP | RCR_APM | RCR_ACRC32); + RTL_W32(RCR, RTL_R32(RCR) & ~ RCR_ACF & ~RCR_ACRC32); + // for debug by victoryman, 20081119 + // RTL_W32(RCR, RTL_R32(RCR) | RCR_APP_PHYST_RXFF); + RTL_W32(RCR, RTL_R32(RCR) | RCR_APP_PHYSTS); + */ +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { +#if defined(RTL8192D_INT_PA) + u8 c9 = priv->pmib->dot11RFEntry.trsw_pape_C9; + u8 cc = priv->pmib->dot11RFEntry.trsw_pape_CC; + if ((c9 == 0xAA && cc == 0xA0) || // Type 2 : 5G TRSW+Int. PA, 2G TR co-matched + (c9 == 0xAA && cc == 0xAF) || // Type 3 : 5G SP3TSW+ Ext.(or Int.)PA, 2G TR co-matched + (c9 == 0x00 && cc == 0xA0)) { // Type 4 : 5G TRSW+ Ext( or Int.)PA, 2G TRSW+ Ext.(or Int.)PA + + panic_printk("\n**********************************\n"); + panic_printk("\n** NOTE!! RTL8192D INTERNAL PA! **\n"); + panic_printk("\n**********************************\n"); + + + priv->pshare->rf_ft_var.use_intpa92d = 1; + priv->pshare->phw->InternalPA5G[0] = 1; + priv->pshare->phw->InternalPA5G[1] = 1; + } else { + // if using default setting, set as external PA for safe. + priv->pshare->rf_ft_var.use_intpa92d = 0; + priv->pmib->dot11RFEntry.trsw_pape_C9 = 0x00; + priv->pmib->dot11RFEntry.trsw_pape_CC = 0xFF; + priv->pshare->phw->InternalPA5G[0] = 0; + priv->pshare->phw->InternalPA5G[1] = 0; + } +#else + // to ignore flash setting for external PA + priv->pmib->dot11RFEntry.trsw_pape_C9 = 0x00; + priv->pmib->dot11RFEntry.trsw_pape_CC = 0xFF; + priv->pshare->phw->InternalPA5G[0] = 0; + priv->pshare->phw->InternalPA5G[1] = 0; +#endif + } +#endif + + RESTORE_INT(x); + +#ifdef DRVMAC_LB + if (priv->pmib->miscEntry.drvmac_lb) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + RT_OP_MODE OP_Mode = RT_OP_MODE_NO_LINK; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_MEDIA_STATUS, (pu1Byte)&OP_Mode); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT)); + } + drvmac_loopback(priv); + } else +#endif + { +//#ifdef CHECK_HANGUP +#if 0 + if (!priv->reset_hangup +#ifdef CLIENT_MODE + || (!(OPMODE & WIFI_AP_STATE) && + (priv->join_res != STATE_Sta_Bss) && (priv->join_res != STATE_Sta_Ibss_Active)) +#endif + ) +#endif + { + + //panic_printk("-----------GET_CHIP_VER(priv) = 0x%x----------\n", GET_CHIP_VER(priv)); +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if(ODMPTR->ConfigBBRF) + { + val32 = ODM_ConfigRFWithHeaderFile(ODMPTR, CONFIG_RF_RADIO, ODM_RF_PATH_A); + val32 |= ODM_ConfigRFWithHeaderFile(ODMPTR, CONFIG_RF_RADIO, ODM_RF_PATH_B); + val32 |= ODM_ConfigRFWithHeaderFile(ODMPTR, CONFIG_RF_RADIO, ODM_RF_PATH_C); + val32 |= ODM_ConfigRFWithHeaderFile(ODMPTR, CONFIG_RF_RADIO, ODM_RF_PATH_D); + } + else + val32 = phy_RF6052_Config_ParaFile(priv); + + +#if defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + if ((GET_CHIP_VER(priv) == VERSION_8881A) ||(GET_CHIP_VER(priv) == VERSION_8814A)) + { + if (val32) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_INIT_PHYRF; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + } + priv->pshare->No_RF_Write = 1; + } + //eric-8814 else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + + if (val32) + return -1; + } + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#if 0 //eric-8814 defined(CONFIG_MACBBRF_BY_ODM) && defined(CONFIG_RTL_88E_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + priv->pshare->phw->NumTotalRFPath = 1; + val32 = ODM_ConfigRFWithHeaderFile(ODMPTR, CONFIG_RF_RADIO, ODM_RF_PATH_A); + } else +#endif +#ifdef USE_OUT_SRC + if(ODMPTR->ConfigBBRF) + { + val32 = ODM_ConfigRFWithHeaderFile(ODMPTR, CONFIG_RF_RADIO, ODM_RF_PATH_A); + val32 |= ODM_ConfigRFWithHeaderFile(ODMPTR, CONFIG_RF_RADIO, ODM_RF_PATH_B); + val32 |= ODM_ConfigRFWithHeaderFile(ODMPTR, CONFIG_RF_RADIO, ODM_RF_PATH_C); + val32 |= ODM_ConfigRFWithHeaderFile(ODMPTR, CONFIG_RF_RADIO, ODM_RF_PATH_D); + } + else +#endif + val32 = phy_RF6052_Config_ParaFile(priv); + + if (GET_CHIP_VER(priv) == VERSION_8188E) + priv->pshare->phw->NumTotalRFPath = 1; + else +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv)) { //8881A, 92E + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_NUM_TOTAL_RF_PATH, (pu1Byte)&priv->pshare->phw->NumTotalRFPath); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + priv->pshare->phw->NumTotalRFPath = 2; //8812A + +#ifdef CONFIG_RTL_8812_SUPPORT //eric_test + if (GET_CHIP_VER(priv) == VERSION_8812E) + priv->pshare->No_RF_Write = 1; +#endif + if (val32) + return -1; + + SAVE_INT_AND_CLI(x); + +#ifdef CONFIG_RTL_92C_SUPPORT + if (IS_UMC_A_CUT_88C(priv)) { + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_RX_G1, bMask20Bits, 0x30255); + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_RX_G2, bMask20Bits, 0x50a00); + } else if (IS_UMC_B_CUT_88C(priv)) { + + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x1e, bMask20Bits, 0x03 | (PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x1e, bMaskDWord, 1) & 0xff0f0)); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x1f, bMask20Bits, 0x200 | (PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x1f, bMaskDWord, 1) & 0xff0ff)); +#if 0 + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x0c, bMask20Bits, 0x0008992f); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x0a, bMask20Bits, 0x0001aef1); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x15, bMask20Bits, 0x0008f425); +#endif + } +#endif + RESTORE_INT(x); + } + } + } + + SAVE_INT_AND_CLI(x); + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + //Do nothing + //MacConfig() is integrated in code below + //Don't enable BB here + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + unsigned int eRFPath, curMaxRFPath = ((priv->pmib->dot11RFEntry.macPhyMode == SINGLEMAC_SINGLEPHY) ? RF92CD_PATH_MAX : RF92CD_PATH_B); + for (eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { + priv->pshare->RegRF18[eRFPath] = PHY_QueryRFReg(priv, eRFPath, 0x18, bMask20Bits, 1); + priv->pshare->RegRF28[eRFPath] = PHY_QueryRFReg(priv, eRFPath, 0x28, bMask20Bits, 1); + } + UpdateBBRFVal8192DE(priv); + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) != VERSION_8812E) +#endif + { + /*---- Set CCK and OFDM Block "ON"----*/ + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn, 1); +#if defined(CONFIG_RTL_92D_SUPPORT) + if (!(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) +#endif + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, 1); + + MacConfig(priv); + } + + /* + * Force CCK CCA for High Power products + */ +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) + RTL_W8(0xa0a, 0xcd); +#endif + } + +// RTL_W8(BW_OPMODE, BIT(2)); // 40Mhz:0 20Mhz:1 +// RTL_W32(MACIDR,0x0); + + // under loopback mode +// RTL_W32(MACIDR,0xffffffff); // need to confirm + /* + #ifdef CONFIG_NET_PCI + if (IS_PCIBIOS_TYPE) + pci_unmap_single(priv->pshare->pdev, priv->pshare->cmdbuf_phyaddr, + (LoadPktSize), PCI_DMA_TODEVICE); + #endif + */ +#if 0 +// RTL_W32(0x230, 0x40000000); //for test +//////////////////////////////////////////////////////////// + + printk("init_hw: 1\n"); + + RTL_W16(SIFS_OFDM, 0x1010); + RTL_W8(SLOT_TIME, 0x09); + + RTL_W8(MSR, MSR_AP); + +// RTL_W8(MSR,MSR_INFRA); + // for test, loopback +// RTL_W8(MSR, MSR_NOLINK); +// RTL_W8(LBKMD_SEL, BIT(0)| BIT(1) ); +// RTL_W16(LBDLY, 0xffff); + + //beacon related + RTL_W16(BCN_INTERVAL, pmib->dot11StationConfigEntry.dot11BeaconPeriod); + RTL_W16(ATIMWND, 2); //0 + RTL_W16(BCN_DRV_EARLY_INT, 10 << 4); // 2 + RTL_W16(BCN_DMATIME, 256); // 0xf + RTL_W16(SIFS_OFDM, 0x0e0e); + RTL_W8(SLOT_TIME, 0x10); + +// CamResetAllEntry(priv); + RTL_W16(SECR, 0x0000); + +// By H.Y. advice +// RTL_W16(_BCNTCFG_, 0x060a); +// if (OPMODE & WIFI_AP_STATE) +// RTL_W16(BCNTCFG, 0x000a); +// else +// for debug +// RTL_W16(_BCNTCFG_, 0x060a); +// RTL_W16(BCNTCFG, 0x0204); + + init_beacon(priv); + + priv->pshare->InterruptMask = (IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK | \ + IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK | \ + IMR_BDOK | /*IMR_RXCMDOK | IMR_TIMEOUT0 |*/ IMR_RDU | IMR_RXFOVW | \ + IMR_BcnInt/* | IMR_TXFOVW*/ /*| IMR_TBDOK | IMR_TBDER*/) ;// IMR_ROK | IMR_BcnInt | IMR_RDU | IMR_RXFOVW | IMR_RXCMDOK; + +// priv->pshare->InterruptMask = IMR_ROK| IMR_BDOK | IMR_BcnInt | IMR_MGNTDOK | IMR_TBDOK | IMR_RDU ; +// priv->pshare->InterruptMask = 0; + priv->pshare->InterruptMaskExt = 0; + RTL_W32(IMR, priv->pshare->InterruptMask); + RTL_W32(IMR + 4, priv->pshare->InterruptMaskExt); + +////////////////////////////////////////////////////////////// + printk("end of init hw\n"); + + return 0; + +#endif +// clear TPPoll +// RTL_W16(TPPoll, 0x0); +// Should 8192SE do this initialize? I don't know yet, 080812. Joshua + // PJ 1-5-2007 Reset PHY parameter counters +// RTL_W32(0xD00, RTL_R32(0xD00)|BIT(27)); +// RTL_W32(0xD00, RTL_R32(0xD00)&(~(BIT(27)))); + /* + // configure timing parameter + RTL_W8(ACK_TIMEOUT, 0x30); + RTL_W8(PIFS_TIME,0x13); + // RTL_W16(LBDLY, 0x060F); + // RTL_W16(SIFS_OFDM, 0x0e0e); + // RTL_W8(SLOT_TIME, 0x10); + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + RTL_W16(SIFS_OFDM, 0x0a0a); + RTL_W8(SLOT_TIME, 0x09); + } + else if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { + RTL_W16(SIFS_OFDM, 0x0a0a); + RTL_W8(SLOT_TIME, 0x09); + } + else if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + RTL_W16(SIFS_OFDM, 0x0a0a); + RTL_W8(SLOT_TIME, 0x09); + } + else { // WIRELESS_11B + RTL_W16(SIFS_OFDM, 0x0a0a); + RTL_W8(SLOT_TIME, 0x14); + } + */ + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + RT_OP_MODE OP_Mode; + MACCONFIG_PARA MacCfgPara; + u2Byte beaconPeriod; + + if (opmode & WIFI_AP_STATE) { + DEBUG_INFO("AP-mode enabled...\n"); +#if defined(CONFIG_RTK_MESH) //Mesh Mode but mesh not enable + if (priv->pmib->dot11WdsInfo.wdsPure || priv->pmib->dot1180211sInfo.meshSilence ) +#else + if (priv->pmib->dot11WdsInfo.wdsPure) +#endif + { + OP_Mode = RT_OP_MODE_NO_LINK; + } else { + OP_Mode = RT_OP_MODE_AP; + } + } else if (opmode & WIFI_STATION_STATE) { + DEBUG_INFO("Station-mode enabled...\n"); + OP_Mode = RT_OP_MODE_INFRASTRUCTURE; + } else if (opmode & WIFI_ADHOC_STATE) { + DEBUG_INFO("Adhoc-mode enabled...\n"); + OP_Mode = RT_OP_MODE_IBSS; + } else { + printk("Operation mode error!\n"); + RESTORE_INT(x); + return 2; + } + + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_MEDIA_STATUS, (pu1Byte)&OP_Mode); + + MacCfgPara.AckTO = priv->pmib->miscEntry.ack_timeout; + MacCfgPara.vap_enable = GET_ROOT(priv)->pmib->miscEntry.vap_enable; + MacCfgPara.OP_Mode = OP_Mode; + MacCfgPara.dot11DTIMPeriod = priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod; + beaconPeriod = pmib->dot11StationConfigEntry.dot11BeaconPeriod; + + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_BEACON_INTERVAL, (pu1Byte)&beaconPeriod); + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_MAC_CONFIG, (pu1Byte)&MacCfgPara); + } +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if (!IS_OUTSRC_CHIP(priv)) +#endif + init_EDCA_para(priv, pmib->dot11BssType.net_work_type); +#endif + + // we don't have EEPROM yet, Mark this for FPGA Platform +// RTL_W8(_9346CR_, CR9346_CFGRW); + +// 92SE Windows driver does not set the PCIF as 0x77, seems HW bug? + // Set Tx and Rx DMA burst size +// RTL_W8(PCIF, 0x77); + // Enable byte shift +// RTL_W8(_PCIF_+2, 0x01); + + /* + // Retry Limit + if (priv->pmib->dot11OperationEntry.dot11LongRetryLimit) + val16 = priv->pmib->dot11OperationEntry.dot11LongRetryLimit & 0xff; + else { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + val16 = 0x30; + else + val16 = 0x06; + } + if (priv->pmib->dot11OperationEntry.dot11ShortRetryLimit) + val16 |= ((priv->pmib->dot11OperationEntry.dot11ShortRetryLimit & 0xff) << 8); + else { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + val16 |= (0x30 << 8); + else + val16 |= (0x06 << 8); + } + RTL_W16(RETRY_LIMIT, val16); + + This should be done later, but Windows Driver not done yet. + // Response Rate Set + // let ACK sent by highest of 24Mbps + val32 = 0x1ff; + if (pmib->dot11RFEntry.shortpreamble) + val32 |= BIT(23); + RTL_W32(_RRSR_, val32); + */ + + + + +// panic_printk("0x2c4 = bitmap = 0x%08x\n", (unsigned int)val32); +// panic_printk("0x2c0 = cmd | macid | band = 0x%08x\n", 0xfd0000a2 | (1<<9 | (sta_band & 0xf))<<8); +// panic_printk("Add id %d val %08x to ratr\n", 0, (unsigned int)val32); + + /* for (i = 0; i < 8; i++) + RTL_W32(ARFR0+i*4, val32 & 0x1f0ff0f0); + */ + + //settting initial rate for control frame to 24M +// RTL_W8(INIRTSMCS_SEL, 8); // ==========>> later + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + u8 MulticastAddr[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_MULTICAST_REG, (pu1Byte)MulticastAddr); + + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_BSSID, (pu1Byte)pmib->dot11OperationEntry.hwaddr); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + //setting MAR + RTL_W32(MAR, 0xffffffff); + RTL_W32((MAR + 4), 0xffffffff); + + //setting BSSID, not matter AH/AP/station + memcpy((void *)&val32, (pmib->dot11OperationEntry.hwaddr), 4); + memcpy((void *)&val16, (pmib->dot11OperationEntry.hwaddr + 4), 2); + RTL_W32(BSSIDR, cpu_to_le32(val32)); + RTL_W16((BSSIDR + 4), cpu_to_le16(val16)); + // RTL_W32(BSSIDR, 0x814ce000); + // RTL_W16((BSSIDR + 4), 0xee92); + } + + //setting TCR + //TCR, use default value + + //setting RCR // set in MacConfigAfterFwDownload +// RTL_W32(_RCR_, _APWRMGT_ | _AMF_ | _ADF_ | _AICV_ | _ACRC32_ | _AB_ | _AM_ | _APM_); +// if (pmib->dot11OperationEntry.crc_log) +// RTL_W32(_RCR_, RTL_R32(_RCR_) | _ACRC32_); + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + //3 Integrated into SetHwRegHandler(priv, HW_VAR_MAC_CONFIG, &MacCfgPara); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + // setting network type + if (opmode & WIFI_AP_STATE) { + DEBUG_INFO("AP-mode enabled...\n"); + +#if defined(CONFIG_RTK_MESH) //Mesh Mode but mesh not enable + if (priv->pmib->dot11WdsInfo.wdsPure || priv->pmib->dot1180211sInfo.meshSilence ) +#else + if (priv->pmib->dot11WdsInfo.wdsPure) +#endif + { +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + //WDEBUG("pure WDS mode\n"); + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_INFRA & NETYPE_Mask) << NETYPE_SHIFT)); + } else +#endif + { + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT)); + } + + } else { + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_AP & NETYPE_Mask) << NETYPE_SHIFT)); + } + // Move init beacon after f/w download +#if 0 + if (priv->auto_channel == 0) { + DEBUG_INFO("going to init beacon\n"); + init_beacon(priv); + } +#endif + } +#ifdef CLIENT_MODE + else if (opmode & WIFI_STATION_STATE) { + DEBUG_INFO("Station-mode enabled...\n"); + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_INFRA & NETYPE_Mask) << NETYPE_SHIFT)); + } else if (opmode & WIFI_ADHOC_STATE) { + DEBUG_INFO("Adhoc-mode enabled...\n"); + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_ADHOC & NETYPE_Mask) << NETYPE_SHIFT)); + } +#endif + else { + printk("Operation mode error!\n"); + RESTORE_INT(x); + return 2; + } + } + + + //3 Security Related + + CamResetAllEntry(priv); +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + SECURITY_CONFIG_OPERATION SCO = 0; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_SECURITY_CONFIG, (pu1Byte)&SCO); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + RTL_W16(SECCFG, 0); + } + if ((OPMODE & (WIFI_AP_STATE | WIFI_STATION_STATE | WIFI_ADHOC_STATE)) && + !priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm && + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ || + pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_)) { + pmib->dot11GroupKeysTable.dot11Privacy = pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + if (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) + i = 5; + else + i = 13; +#ifdef USE_WEP_DEFAULT_KEY + memcpy(pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey, + &priv->pmib->dot11DefaultKeysTable.keytype[pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex].skey[0], i); + pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen = i; + pmib->dot11GroupKeysTable.keyid = pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + pmib->dot11GroupKeysTable.keyInCam = 0; +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + SECURITY_CONFIG_OPERATION SCO; + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_SECURITY_CONFIG, (pu1Byte)&SCO); + SCO |= SCO_NOSKMC; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_SECURITY_CONFIG, (pu1Byte)&SCO); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + RTL_W16(SECCFG, RTL_R16(SECCFG) | NOSKMC); // no search multicast + } +#else +#if defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) + memcpy(pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey, + &priv->pmib->dot11DefaultKeysTable.keytype[pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex].skey[0], i); +#else + memcpy(pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey, + &priv->pmib->dot11DefaultKeysTable.keytype[0].skey[0], i); +#endif + pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen = i; + pmib->dot11GroupKeysTable.keyid = pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + pmib->dot11GroupKeysTable.keyInCam = 0; +#endif + } + +// for debug +#if 0 +// when hangup reset, re-init TKIP/AES key in ad-hoc mode +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_ADHOC_STATE) && pmib->dot11OperationEntry.keep_rsnie && + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_ || + pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)) { + DOT11_SET_KEY Set_Key; + Set_Key.KeyType = DOT11_KeyType_Group; + Set_Key.EncType = pmib->dot11GroupKeysTable.dot11Privacy; + DOT11_Process_Set_Key(priv->dev, NULL, &Set_Key, pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey); + } else +#endif +//-------------------------------------- david+2006-06-30 + // restore group key if it has been set before open, david + if (pmib->dot11GroupKeysTable.keyInCam) { + int retVal; + retVal = CamAddOneEntry(priv, (unsigned char *)"\xff\xff\xff\xff\xff\xff", + pmib->dot11GroupKeysTable.keyid, + pmib->dot11GroupKeysTable.dot11Privacy << 2, + 0, pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey); + if (retVal) + priv->pshare->CamEntryOccupied++; + else { + DEBUG_ERR("Add group key failed!\n"); + } + } +#endif + //here add if legacy WEP + // if 1x is enabled, do not set default key, david +#ifdef USE_WEP_DEFAULT_KEY +#ifdef MBSSID + if (!(OPMODE & WIFI_AP_STATE) || !priv->pmib->miscEntry.vap_enable) +#endif + { + if (!SWCRYPTO && !IEEE8021X_FUN && + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_ || + pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_)) + init_DefaultKey_Enc(priv, NULL, 0); + } +#endif + + + //3 MAC Beacon Tming Related + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + //Do Nothing + // Integrated into code above + //3 Integrated into SetHwRegHandler(priv, HW_VAR_MAC_CONFIG, &MacCfgPara); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + + //Setup Beacon Interval/interrupt interval, ATIM-WIND ATIM-Interrupt + RTL_W32(MBSSID_BCN_SPACE, pmib->dot11StationConfigEntry.dot11BeaconPeriod); + //Setting BCNITV is done by firmware now +// set_fw_reg(priv, (0xF1000000 | (pmib->dot11StationConfigEntry.dot11BeaconPeriod << 8)), 0, 0); + // Set max AMPDU aggregation time +// int max_aggre_time = 0xc0; // in 4us +// set_fw_reg(priv, (0xFD0000B1|((max_aggre_time << 8) & 0xff00)), 0 ,0); + +// RTL_W32(0x2A4, 0x00006300); +// RTL_W32(0x2A0, 0xb026007C); +// delay_ms(1); +// while(RTL_R32(0x2A0) != 0){}; + //RTL_W16(TBTT_PROHIBIT, 0xc804); + + if((OPMODE & WIFI_AP_STATE )) + { // for pure AP mode + repeater mode + APWDS + Mbssid + if ( (priv->pmib->miscEntry.vap_enable) || (priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod <= 40)){ + RTL_W32(TBTT_PROHIBIT, 0x1df04); +#if defined(CONFIG_RTL_88E_SUPPORT) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + if (GET_CHIP_VER(priv) == VERSION_8188E) + RTL_W16(ATIMWND, 18); +#endif + }else{ + RTL_W32(TBTT_PROHIBIT, 0x40004); +#if defined(CONFIG_RTL_88E_SUPPORT) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + if (GET_CHIP_VER(priv) == VERSION_8188E) + RTL_W16(ATIMWND, 35); +#endif + } + // for pure WDS + if((priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsPure)) // pure wds mode + { + RTL_W32(TBTT_PROHIBIT, 0x104); + } + }else{ + // for STA mode only + RTL_W32(TBTT_PROHIBIT, 0x104); + } + + + RTL_W8(DRVERLYINT, 10); + RTL_W8(BCNDMATIM, 1); + /* + if (priv->pshare->rf_ft_var.bcast_to_dzq) + RTL_W16(ATIMWND, 0x0a); + else + RTL_W16(ATIMWND, 5); + */ + +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + RTL_W16(ATIMWND, 0x10); + RTL_W8(REG_92E_DTIM_COUNT_ROOT, priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod); + RTL_W32(REG_92E_PKT_LIFETIME_CTRL, RTL_R32(REG_92E_PKT_LIFETIME_CTRL) & ~BIT(19)); + } else +#endif + { +#if defined(CONFIG_PCI_HCI) + RTL_W16(ATIMWND, 1); +#endif + } + + /* + if (!((OPMODE & WIFI_AP_STATE) + #if defined(WDS) && defined(CONFIG_RTK_MESH) + && ((priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsPure) || priv->pmib->dot1180211sInfo.meshSilence)) + #elif defined(WDS) + && priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsPure ) + #elif defined(CONFIG_RTK_MESH) //Mesh Mode but mesh not enable + && priv->pmib->dot1180211sInfo.meshSilence ) + #else + ) + #endif + ) + + RTL_W16(BCN_DRV_EARLY_INT, RTL_R16(BCN_DRV_EARLY_INT)|BIT(15)); // sw beacon + */ +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable && RTL8192CD_NUM_VWLAN == 1 && + priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod < 30) + //RTL_W16(BCN_DRV_EARLY_INT, (RTL_R16(BCN_DRV_EARLY_INT)&0xf00f) | ((6<<4)&0xff0)); + RTL_W8(DRVERLYINT, 6); +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) + RTL_W8(REG_92E_PRE_DL_BCN_ITV, RTL_R8(DRVERLYINT) + 1); +#endif + +#ifdef CONFIG_RTL_92C_SUPPORT + if (IS_TEST_CHIP(priv) && ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C))) { + RTL_W8(BCN_CTRL, 0); + RTL_W8(0x553, 1); + RTL_W8(BCN_CTRL, EN_BCN_FUNCTION); + // RTL_W16(BCN_DMATIME, 0x400); // 1ms + + // for debug +#ifdef CLIENT_MODE + if (OPMODE & WIFI_ADHOC_STATE) + RTL_W8(BCN_MAX_ERR, 0xff); +#endif + } else +#endif + { + RTL_W8(BCN_CTRL, DIS_TSF_UPDATE_N | DIS_SUB_STATE_N ); + RTL_W8(BCN_MAX_ERR, 0xff); + RTL_W16(0x518, 0); + RTL_W8(0x553, 3); + if (OPMODE & WIFI_STATION_STATE) + RTL_W8(0x422, RTL_R8(0x422) ^ BIT(6)); + + if ((priv->pmib->dot11WdsInfo.wdsPure == 0) +#ifdef MP_TEST + && (!priv->pshare->rf_ft_var.mp_specific) +#endif + ) { + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) | EN_BCN_FUNCTION | EN_TXBCN_RPT); + } else { + +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + //WDEBUG("pure WDS mode\n"); + RTL_W8(BCN_CTRL, 0); + } +#endif + } + } + + +//-------------- + +// By H.Y. advice +// RTL_W16(_BCNTCFG_, 0x060a); + if (OPMODE & WIFI_AP_STATE) + RTL_W16(BCNTCFG, 0x320c); //RTL_W16(BCNTCFG, 0x000a); + else +// for debug +// RTL_W16(_BCNTCFG_, 0x060a); + RTL_W16(BCNTCFG, 0x0204); + } + + //3 IMR Related + //3 Download Firmware Related + // Ack ISR, and then unmask IMR +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if (opmode & WIFI_AP_STATE) { + GET_HAL_INTERFACE(priv)->InitIMRHandler(priv, RT_OP_MODE_AP); + } else if (opmode & WIFI_STATION_STATE) { + GET_HAL_INTERFACE(priv)->InitIMRHandler(priv, RT_OP_MODE_INFRASTRUCTURE); + } else if (opmode & WIFI_ADHOC_STATE) { + GET_HAL_INTERFACE(priv)->InitIMRHandler(priv, RT_OP_MODE_IBSS); + } + + // TODO: Filen, no need to sync !? + priv->pshare->InterruptMask = _GET_HAL_DATA(priv)->IntMask[0]; + priv->pshare->InterruptMask = _GET_HAL_DATA(priv)->IntMask[1]; + + // TODO: Filen, check download 8051 firmware + //Download Firmware + + RESTORE_INT(x); + if ( RT_STATUS_SUCCESS != GET_HAL_INTERFACE(priv)->InitFirmwareHandler(priv)) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_INIT_DLFW; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + printk("InitDownload FW Fail\n"); + } else { + printk("InitDownload FW OK \n"); + } + SAVE_INT_AND_CLI(x); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#if 1 +#ifdef CONFIG_PCI_HCI + // Ack ISR, and then unmask IMR +#if 0 + RTL_W32(ISR, RTL_R32(ISR)); + RTL_W32(ISR + 4, RTL_R16(ISR + 4)); + RTL_W32(IMR, 0x0); + RTL_W32(IMR + 4, 0x0); + priv->pshare->InterruptMask = _ROK_ | _BCNDMAINT_ | _RDU_ | _RXFOVW_ | _RXCMDOK_; + priv->pshare->InterruptMask = (IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK | \ + IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK | \ + IMR_BDOK | IMR_RXCMDOK | /*IMR_TIMEOUT0 |*/ IMR_RDU | IMR_RXFOVW | \ + IMR_BcnInt/* | IMR_TXFOVW*/ /*| IMR_TBDOK | IMR_TBDER*/);// IMR_ROK | IMR_BcnInt | IMR_RDU | IMR_RXFOVW | IMR_RXCMDOK; +#endif + //priv->pshare->InterruptMask = HIMR_ROK | HIMR_BCNDMA0 | HIMR_RDU | HIMR_RXFOVW; + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + priv->pshare->InterruptMask = HIMR_88E_ROK | HIMR_88E_HISR1_IND_INT; + priv->pshare->InterruptMaskExt = HIMRE_88E_RXFOVW; + } else +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + priv->pshare->InterruptMask = HIMR_92E_ROK | HIMR_92E_HISR1_IND_INT; + priv->pshare->InterruptMaskExt = HIMRE_92E_RXFOVW; +#ifdef BEAMFORMING_SUPPORT + if (priv->pmib->dot11RFEntry.txbf == 1) { + priv->pshare->InterruptMask |= IMR_GTINT3_8812; + } +#endif + } else +#endif + { + priv->pshare->InterruptMask = HIMR_ROK | HIMR_BCNDMA0 | HIMR_RXFOVW; + priv->pshare->InterruptMaskExt = 0; + } + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + priv->pshare->InterruptMask |= HIMR_88E_BEDOK; + else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + priv->pshare->InterruptMask |= IMR_BEDOK_8812; + else +#endif +#ifdef CONFIG_WLAN_HAL + //3 Integrated into HAL code +#endif + priv->pshare->InterruptMask |= HIMR_BEDOK; + } +#endif + + if (opmode & WIFI_AP_STATE) { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + priv->pshare->InterruptMask |= HIMR_88E_BcnInt | HIMR_88E_TBDOK | HIMR_88E_TBDER; + else +#endif +#if defined(CONFIG_RTL_92E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + if ((GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8812E)) { + if (priv->pmib->dot11WdsInfo.wdsPure) { + //WDEBUG("pure-WDS mode don't enable HIMR_92E_BcnInt | HIMR_92E_TBDOK | HIMR_92E_TBDER \n"); + } else { + priv->pshare->InterruptMask |= HIMR_92E_BcnInt | HIMR_92E_TBDOK | HIMR_92E_TBDER; + } + } else +#endif + { + priv->pshare->InterruptMask |= HIMR_BCNDOK0 | HIMR_TXBCNERR; + } + } +#ifdef CLIENT_MODE + else if (opmode & WIFI_ADHOC_STATE) { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + priv->pshare->InterruptMask |= HIMR_88E_BcnInt | HIMR_88E_TBDOK | HIMR_88E_TBDER; + else +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) + priv->pshare->InterruptMask |= HIMR_92E_BcnInt | HIMR_92E_TBDOK | HIMR_92E_TBDER; + else +#endif + priv->pshare->InterruptMask |= (HIMR_TXBCNERR | HIMR_TXBCNOK); + } +#endif + +#endif // CONFIG_PCI_HCI +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT +#ifdef CONFIG_USB_HCI +#ifdef CONFIG_SUPPORT_USB_INT + priv->pshare->InterruptMask = 0; + priv->pshare->InterruptMaskExt = HIMRE_88E_TXERR | HIMRE_88E_RXERR | HIMRE_88E_TXFOVW | HIMRE_88E_RXFOVW; + +#ifdef CONFIG_INTERRUPT_BASED_TXBCN + if (opmode & WIFI_AP_STATE) + priv->pshare->InterruptMask |= HIMR_88E_BcnInt | HIMR_88E_TBDOK | HIMR_88E_TBDER; + else if (opmode & WIFI_ADHOC_STATE) + priv->pshare->InterruptMask |= HIMR_88E_BcnInt | HIMR_88E_TBDOK | HIMR_88E_TBDER; +#endif +#endif // CONFIG_SUPPORT_USB_INT +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI + // + // Initialize and enable SDIO Host Interrupt. + // + InitSdioInterrupt(priv); +#endif +#endif // CONFIG_RTL_88E_SUPPORT + + // FGPA does not have eeprom now +// RTL_W8(_9346CR_, 0); + /* + // =========================================================================================== + // Download Firmware + // allocate memory for tx cmd packet + if((priv->pshare->txcmd_buf = (unsigned char *)kmalloc((LoadPktSize), GFP_ATOMIC)) == NULL) { + printk("not enough memory for txcmd_buf\n"); + return -1; + } + + priv->pshare->cmdbuf_phyaddr = get_physical_addr(priv, priv->pshare->txcmd_buf, + LoadPktSize, PCI_DMA_TODEVICE); + */ + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + ) { + /* currently need not to download fw */ + rtl8192cd_ReadFwHdr(priv); + + while (dwnRetry-- && !fwStatus) { +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + fwStatus = Load_92D_Firmware(priv); +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) + fwStatus = Load_92C_Firmware(priv); +#endif + delay_ms(20); + }; + if (fwStatus) { + DEBUG_INFO("Load firmware successful!\n"); + } else { + DEBUG_INFO("Load firmware check!\n"); +#ifdef PCIE_POWER_SAVING + priv->pshare->rf_ft_var.power_save &= ~( L1_en | L2_en); +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (RTL_R8(0x1c5) == 0xE0) { + DEBUG_INFO("RTL8192D part number failed!!\n"); + RESTORE_INT(x); + return -1; + } + } +#endif + } + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT +#if defined(__KERNEL__) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + rtl8192cd_ReadFwHdr(priv); + + fwStatus = Load_88E_Firmware(priv); + if (fwStatus) { + DEBUG_INFO("Load firmware successful!\n"); + } else { + DEBUG_INFO("Load firmware check!\n"); + } + } +#endif +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + extern RT_STATUS FirmwareDownload8812(struct rtl8192cd_priv * priv); + rtl8192cd_ReadFwHdr(priv); + priv->bFWReady = ! (0 ^ FirmwareDownload8812(priv)); + } +#endif + } + +#ifdef CONFIG_WLAN_HAL + if (errorFlag) { + panic_printk("%s, %d, errorFlag:%08x \n", __FUNCTION__, __LINE__, errorFlag); + RESTORE_INT(x); + return -1; + } +#endif + /* + MacConfigAfterFwDownload(priv); + */ + + // Adaptive Rate Table for Basic Rate + val32 = 0; + for (i = 0; i < 32; i++) { + if (AP_BSSRATE[i]) { + if (AP_BSSRATE[i] & 0x80) + val32 |= get_bit_value_from_ieee_value(AP_BSSRATE[i] & 0x7f); + } + } + val32 |= (priv->pmib->dot11nConfigEntry.dot11nBasicMCS << 12); + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + // Do Nothing + // Filen: it is not necessary to check !? + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + unsigned int delay_count = 10; + do { + if (!is_h2c_buf_occupy(priv)) + break; + delay_us(5); + delay_count--; + } while (delay_count); + } + +#ifdef P2P_SUPPORT + if (OPMODE & WIFI_P2P_SUPPORT) { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + P2P_DEBUG("managment frame G only \n"); + set_RATid_cmd(priv, 0, ARFR_G_ONLY, val32); // under P2P mode +#endif + } else +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { +#ifdef USB_POWER_SUPPORT + val32 &= USB_RA_MASK; +#endif + set_RATid_cmd(priv, 0, ARFR_Band_A_BMC, val32); + } else + set_RATid_cmd(priv, 0, ARFR_BMC, val32); + } +#ifdef CONFIG_RTL_92C_SUPPORT + else if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + set_RATid_cmd(priv, 0, ARFR_BMC, val32); + } +#endif + else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + set_RATid_cmd(priv, 0, ARFR_BMC, val32); +#endif + } + +// kfree(priv->pshare->txcmd_buf); + +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + if (opmode & WIFI_AP_STATE) { + if (priv->auto_channel == 0) { + DEBUG_INFO("going to init beacon\n"); + init_beacon(priv); + } + } + + //3 Enable IMR +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { +#if 0 //Filen: defer to open after drv_open + GET_HAL_INTERFACE(priv)->EnableIMRHandler(priv); +#endif + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#ifdef CONFIG_PCI_HCI + //enable interrupt +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask); + RTL_W32(REG_88E_HIMRE, priv->pshare->InterruptMaskExt); + } else +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { +#ifdef DRVMAC_LB + priv->pshare->InterruptMask &= ~HIMR_92E_BcnInt; +#endif +#ifdef TXREPORT + priv->pshare->InterruptMask |= HIMR_92E_C2HCMD; +#endif + RTL_W32(REG_HIMR0_8812, priv->pshare->InterruptMask); + RTL_W32(REG_HIMR1_8812, priv->pshare->InterruptMaskExt); + } else +#endif + { + RTL_W32(HIMR, priv->pshare->InterruptMask); + } +// RTL_W32(IMR+4, priv->pshare->InterruptMaskExt); +// RTL_W32(IMR, 0xffffffff); +// RTL_W8(IMR+4, 0x3f); +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) && defined(CONFIG_RTL_88E_SUPPORT) +#ifdef CONFIG_SUPPORT_USB_INT + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask); + RTL_W32(REG_88E_HIMRE, priv->pshare->InterruptMaskExt); + + // REG_USB_SPECIAL_OPTION - BIT(4) + // 0; Use interrupt endpoint to upload interrupt pkt + // 1; Use bulk endpoint to upload interrupt pkt, + +#ifdef CONFIG_USB_INTERRUPT_IN_PIPE + if(pHalData->RtIntInPipe == 0x05) + RTL_W8(REG_USB_SPECIAL_OPTION, RTL_R8(REG_USB_SPECIAL_OPTION) & (~INT_BULK_SEL)); + else +#endif + RTL_W8(REG_USB_SPECIAL_OPTION, RTL_R8(REG_USB_SPECIAL_OPTION) | (INT_BULK_SEL)); +#endif // CONFIG_SUPPORT_USB_INT +#endif // CONFIG_USB_HCI && CONFIG_RTL_88E_SUPPORT + } + + // =========================================================================================== + +#ifdef CHECK_HANGUP + if (priv->reset_hangup) + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; + else +#endif + { + if (opmode & WIFI_AP_STATE) + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; + else + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + } + + if (!priv->pshare->rf_ft_var.disable_pwr_by_rate +#ifdef SUPPORT_RTL8188E_TC + && (!((GET_CHIP_VER(priv) == VERSION_8188E) && IS_TEST_CHIP(priv))) +#endif + ) + { +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8812E) { + *(unsigned int *)(&priv->pshare->phw->CCKTxAgc_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_CCK11_CCK1_JAguar)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_Ofdm18_Ofdm6_JAguar)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_Ofdm54_Ofdm24_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_MCS3_MCS0_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_MCS7_MCS4_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[8]) = cpu_to_be32(RTL_R32(rTxAGC_A_MCS11_MCS8_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[12]) = cpu_to_be32(RTL_R32(rTxAGC_A_MCS15_MCS12_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss1Index3_Nss1Index0_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[8]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[12]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss2Index5_Nss2Index2_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[16]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar)); + *(unsigned int *)(&priv->pshare->phw->CCKTxAgc_B[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_CCK11_CCK1_JAguar)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_B[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Ofdm18_Ofdm6_JAguar)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_B[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Ofdm54_Ofdm24_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_MCS3_MCS0_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_MCS7_MCS4_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[8]) = cpu_to_be32(RTL_R32(rTxAGC_B_MCS11_MCS8_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[12]) = cpu_to_be32(RTL_R32(rTxAGC_B_MCS15_MCS12_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_B[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Nss1Index3_Nss1Index0_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_B[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_B[8]) = cpu_to_be32(RTL_R32(rTxAGC_B_Nss2Index1_Nss1Index8_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_B[12]) = cpu_to_be32(RTL_R32(rTxAGC_B_Nss2Index5_Nss2Index2_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_B[16]) = cpu_to_be32(RTL_R32(rTxAGC_B_Nss2Index9_Nss2Index6_JAguar)); + } else +#endif +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv)==VERSION_8881A) { + *(unsigned int *)(&priv->pshare->phw->CCKTxAgc_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_CCK11_CCK1_JAguar)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_Ofdm18_Ofdm6_JAguar)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_Ofdm54_Ofdm24_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_MCS3_MCS0_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_MCS7_MCS4_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[8]) = cpu_to_be32(RTL_R32(rTxAGC_A_MCS11_MCS8_JAguar)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[12]) = cpu_to_be32(RTL_R32(rTxAGC_A_MCS15_MCS12_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss1Index3_Nss1Index0_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[8]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[12]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss2Index5_Nss2Index2_JAguar)); + *(unsigned int *)(&priv->pshare->phw->VHTTxAgcOffset_A[16]) = cpu_to_be32(RTL_R32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar)); + } else +#endif + { + // get default Tx AGC offset + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_Mcs03_Mcs00)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_Mcs07_Mcs04)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[8]) = cpu_to_be32(RTL_R32(rTxAGC_A_Mcs11_Mcs08)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[12]) = cpu_to_be32(RTL_R32(rTxAGC_A_Mcs15_Mcs12)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_A_Rate18_06)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_A_Rate54_24)); + *(unsigned int *)(&priv->pshare->phw->CCKTxAgc_A[0]) = cpu_to_be32((RTL_R32(rTxAGC_A_CCK11_2_B_CCK11) & 0xffffff00) + | RTL_R8(rTxAGC_A_CCK1_Mcs32 + 1)); + +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs03_Mcs00)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs07_Mcs04)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[8]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs11_Mcs08)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_A[12]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs15_Mcs12)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Rate18_06)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_A[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Rate54_24)); + *(unsigned int *)(&priv->pshare->phw->CCKTxAgc_A[0]) = cpu_to_be32((RTL_R8(rTxAGC_A_CCK11_2_B_CCK11) << 24) + | (RTL_R32(rTxAGC_B_CCK5_1_Mcs32) >> 8)); + } +#endif + + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs03_Mcs00)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs07_Mcs04)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[8]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs11_Mcs08)); + *(unsigned int *)(&priv->pshare->phw->MCSTxAgcOffset_B[12]) = cpu_to_be32(RTL_R32(rTxAGC_B_Mcs15_Mcs12)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_B[0]) = cpu_to_be32(RTL_R32(rTxAGC_B_Rate18_06)); + *(unsigned int *)(&priv->pshare->phw->OFDMTxAgcOffset_B[4]) = cpu_to_be32(RTL_R32(rTxAGC_B_Rate54_24)); + *(unsigned int *)(&priv->pshare->phw->CCKTxAgc_B[0]) = cpu_to_be32((RTL_R8(rTxAGC_A_CCK11_2_B_CCK11) << 24) + | (RTL_R32(rTxAGC_B_CCK5_1_Mcs32) >> 8)); + } + + if (priv->pshare->txpwr_pg_format_abs) + { + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { + //CCK + priv->pshare->tgpwr_CCK_new[RF_PATH_A] = priv->pshare->phw->CCKTxAgc_A[0]; + priv->pshare->tgpwr_CCK_new[RF_PATH_B] = priv->pshare->phw->CCKTxAgc_B[0]; + for (i=0;i<4;i++) { + priv->pshare->phw->CCKTxAgc_A[i] -= priv->pshare->tgpwr_CCK_new[RF_PATH_A]; + priv->pshare->phw->CCKTxAgc_B[i] -= priv->pshare->tgpwr_CCK_new[RF_PATH_B]; + } + } + //OFDM + priv->pshare->tgpwr_OFDM_new[RF_PATH_A] = priv->pshare->phw->OFDMTxAgcOffset_A[4]; + priv->pshare->tgpwr_OFDM_new[RF_PATH_B] = priv->pshare->phw->OFDMTxAgcOffset_B[4]; + for (i=0;i<8;i++) { + priv->pshare->phw->OFDMTxAgcOffset_A[i] -= priv->pshare->tgpwr_OFDM_new[RF_PATH_A]; + priv->pshare->phw->OFDMTxAgcOffset_B[i] -= priv->pshare->tgpwr_OFDM_new[RF_PATH_B]; + } + + //HT-1S + priv->pshare->tgpwr_HT1S_new[RF_PATH_A] = priv->pshare->phw->MCSTxAgcOffset_A[4]; + priv->pshare->tgpwr_HT1S_new[RF_PATH_B] = priv->pshare->phw->MCSTxAgcOffset_B[4]; + for (i=0;i<8;i++) { + priv->pshare->phw->MCSTxAgcOffset_A[i] -= priv->pshare->tgpwr_HT1S_new[RF_PATH_A]; + priv->pshare->phw->MCSTxAgcOffset_B[i] -= priv->pshare->tgpwr_HT1S_new[RF_PATH_B]; + } + + //HT-2S + priv->pshare->tgpwr_HT2S_new[RF_PATH_A] = priv->pshare->phw->MCSTxAgcOffset_A[12]; + priv->pshare->tgpwr_HT2S_new[RF_PATH_B] = priv->pshare->phw->MCSTxAgcOffset_B[12]; + for (i=8;i<16;i++) { + priv->pshare->phw->MCSTxAgcOffset_A[i] -= priv->pshare->tgpwr_HT2S_new[RF_PATH_A]; + priv->pshare->phw->MCSTxAgcOffset_B[i] -= priv->pshare->tgpwr_HT2S_new[RF_PATH_B]; + } +#ifdef RTK_AC_SUPPORT + if ((GET_CHIP_VER(priv)==VERSION_8812E) || (GET_CHIP_VER(priv)==VERSION_8881A)) { + //VHT-1S + priv->pshare->tgpwr_VHT1S_new[RF_PATH_A] = priv->pshare->phw->VHTTxAgcOffset_A[4]; + priv->pshare->tgpwr_VHT1S_new[RF_PATH_B] = priv->pshare->phw->VHTTxAgcOffset_B[4]; + //VHT-2S + priv->pshare->tgpwr_VHT2S_new[RF_PATH_A] = priv->pshare->phw->VHTTxAgcOffset_A[18]; + priv->pshare->tgpwr_VHT2S_new[RF_PATH_B] = priv->pshare->phw->VHTTxAgcOffset_B[18]; + + for (i=0 ; i<20 ; i++) { + if (i<8) { + priv->pshare->phw->VHTTxAgcOffset_A[i] -= priv->pshare->tgpwr_HT1S_new[RF_PATH_A]; + priv->pshare->phw->VHTTxAgcOffset_B[i] -= priv->pshare->tgpwr_HT1S_new[RF_PATH_B]; + } else if (i==10 || i==11) { + priv->pshare->phw->VHTTxAgcOffset_A[i] = priv->pshare->tgpwr_HT1S_new[RF_PATH_A] - priv->pshare->phw->VHTTxAgcOffset_A[i]; + priv->pshare->phw->VHTTxAgcOffset_B[i] = priv->pshare->tgpwr_HT1S_new[RF_PATH_B] - priv->pshare->phw->VHTTxAgcOffset_B[i]; + } else if (i==16 || i==17) { + priv->pshare->phw->VHTTxAgcOffset_A[i] = priv->pshare->tgpwr_HT2S_new[RF_PATH_A] - priv->pshare->phw->VHTTxAgcOffset_A[i]; + priv->pshare->phw->VHTTxAgcOffset_B[i] = priv->pshare->tgpwr_HT2S_new[RF_PATH_B] - priv->pshare->phw->VHTTxAgcOffset_B[i]; + } else { + priv->pshare->phw->VHTTxAgcOffset_A[i] -= priv->pshare->tgpwr_HT2S_new[RF_PATH_A]; + priv->pshare->phw->VHTTxAgcOffset_B[i] -= priv->pshare->tgpwr_HT2S_new[RF_PATH_B]; + } + } + } +#endif + } + + } + +#ifdef ADD_TX_POWER_BY_CMD + assign_txpwr_offset(priv); +#endif + +#ifdef TXPWR_LMT + if (!priv->pshare->rf_ft_var.disable_txpwrlmt) + { +#ifdef TXPWR_LMT_NEWFILE + if((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8188E) || IS_HAL_CHIP(priv)) + PHY_ConfigTXLmtWithParaFile_new(priv); + else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + PHY_ConfigTXLmtWithParaFile(priv); + } +#endif + RESTORE_INT(x); + +#ifdef _TRACKING_TABLE_FILE + if (priv->pshare->rf_ft_var.pwr_track_file) { + if((ODMPTR->ConfigBBRF) && (GET_CHIP_VER(priv) != VERSION_8188E)) + ODM_ConfigRFWithTxPwrTrackHeaderFile(ODMPTR); + else + PHY_ConfigTXPwrTrackingWithParaFile(priv); + } +#endif + + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192D)) { + if ((priv->pmib->dot11RFEntry.ther < 0x07) || (priv->pmib->dot11RFEntry.ther > 0x1d)) { + DEBUG_ERR("TPT: unreasonable target ther %d, disable tpt\n", priv->pmib->dot11RFEntry.ther); + priv->pmib->dot11RFEntry.ther = 0; + } + } else +#endif + { + if ((priv->pmib->dot11RFEntry.ther < 0x07) || (priv->pmib->dot11RFEntry.ther > 0x32)) { + DEBUG_ERR("TPT: unreasonable target ther %d, disable tpt\n", priv->pmib->dot11RFEntry.ther); + priv->pmib->dot11RFEntry.ther = 0; + } + } + + + /* + if (opmode & WIFI_AP_STATE) + { + if (priv->auto_channel == 0) { + DEBUG_INFO("going to init beacon\n"); + init_beacon(priv); + } + } + */ + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv) == VERSION_8881A) { + //Don't enable BB here + } +#endif // CONFIG_WLAN_HAL_8881A + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + // TODO: Filen, check 8192E BB/RF control + //Don't enable BB here + } +#endif //CONFIG_WLAN_HAL_8192EE + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) != VERSION_8812E) +#endif + { + /*---- Set CCK and OFDM Block "ON"----*/ + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn, 1); +#if defined(CONFIG_RTL_92D_SUPPORT) + if (!(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) +#endif + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, 1); + } + } + + delay_ms(2); + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) { +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv) ) { + u4Byte MACAddr = 0x87654321; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_ETHER_ADDR, (pu1Byte)&MACAddr); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + RTL_W32(MACID, 0x87654321); + + delay_ms(150); + } +#endif +// RESTORE_INT(x); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) { + SAVE_INT_AND_CLI(x); +#ifdef DPK_92D + if (((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) + && priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_5G && !priv->pshare->rf_ft_var.dpk_on) { + panic_printk(">>> DPK ON!!!"); + priv->pshare->rf_ft_var.dpk_on = 1; + } +#endif +#ifdef SW_LCK_92D + PHY_LCCalibrate_92D(priv); +#endif + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + + if (priv->pmib->dot11RFEntry.macPhyMode == SINGLEMAC_SINGLEPHY) + clnt_ss_check_band(priv, priv->pmib->dot11RFEntry.dot11channel); + RESTORE_INT(x); + /* + * IQK + */ + PHY_IQCalibrate(priv); + +#ifdef DPK_92D + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G && priv->pshare->rf_ft_var.dpk_on) + PHY_DPCalibrate(priv); +#endif + } +#endif // CONFIG_RTL_92D_SUPPORT + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8188E) +#endif + ) { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + // switch to channel 7 before doing IQK + printk("Switch to channel 7 before doing 88E IQK\n"); + SAVE_INT_AND_CLI(x); + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, 7, priv->pshare->offset_2nd_chan); + RESTORE_INT(x); + } +#endif + PHY_IQCalibrate(priv); // IQK_92C IQK_88c IQK_88e + + watchdog_kick(); + + //Do NOT perform APK fot RF team's request + //PHY_APCalibrate(priv); // APK_92C APK_88C +#ifdef CALIBRATE_BY_ODM + if (GET_CHIP_VER(priv) == VERSION_8188E) { + PHY_LCCalibrate_8188E(ODMPTR); + } else +#endif + { + SAVE_INT_AND_CLI(x); + PHY_LCCalibrate(priv); + RESTORE_INT(x); + } + + SAVE_INT_AND_CLI(x); + + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + + /* + * Set RF & RRSR depends on band in use + */ + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G | WIRELESS_11N)) { + if ((priv->pmib->dot11StationConfigEntry.autoRate) || !(priv->pmib->dot11StationConfigEntry.fixedTxRate & 0xf)) { +#ifdef CONFIG_RTL_92C_SUPPORT + if ( IS_UMC_A_CUT_88C(priv) || GET_CHIP_VER(priv) == VERSION_8192C ) + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x4f000); + else +#endif + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x4f200); + +// RTL_W32(RRSR, RTL_R32(RRSR) & ~(0x0c)); + } else { + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x0f400); + } + } else { + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x0f400); + } + + RESTORE_INT(x); + } +#endif // CONFIG_RTL_92C_SUPPORT || CONFIG_RTL_88E_SUPPORT + /* + if(priv->pshare->rf_ft_var.ofdm_1ss_oneAnt == 1){// use one PATH for ofdm and 1SS + Switch_1SS_Antenna(priv, 2); + Switch_OFDM_Antenna(priv, 2); + } + */ + + watchdog_kick(); + delay_ms(100); + SAVE_INT_AND_CLI(x); + + //RTL_W32(0x100, RTL_R32(0x100) | BIT(14)); //for 8190 fw debug + + // init DIG variables +// val32 = 0x40020064; // 0x20010020 + val32 = 0x20010064; // 0x20010020 +// + priv->pshare->threshold0 = (unsigned short)(val32 & 0x000000FF); + priv->pshare->threshold1 = (unsigned short)((val32 & 0x000FFF00) >> 8); + priv->pshare->threshold2 = (unsigned short)((val32 & 0xFFF00000) >> 20); + priv->pshare->digDownCount = 0; + priv->pshare->digDeadPoint = 0; + priv->pshare->digDeadPointHitCount = 0; + + if (priv->pshare->rf_ft_var.nbi_filter_enable && + (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G)) { + NBI_filter_on(priv); + } + + set_DIG_state(priv, 1); // DIG on + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if ((GET_CHIP_VER(priv) == VERSION_8812E) || IS_HAL_CHIP(priv)) { + if (GET_CHIP_VER(priv) == VERSION_8192E) { + if (priv->pmib->dot11RFEntry.tx2path) + { + RTL_W32(0x90C, 0x83321333); + RTL_W32(0x80C, RTL_R32(0x80C) & ~BIT(31)); + RTL_W8(0x6D8, RTL_R8(0x6D8) | 0x3F); + + RTL_W8(0xA07, 0xC1); + RTL_W8(0xA11, RTL_R8(0xA11) & ~BIT(5)); + //RTL_W8(0xA20, (RTL_R8(0xA20) & ~BIT(5)) | BIT(4)); + //RTL_W8(0xA2E, RTL_R8(0xA2E) | BIT(3) | BIT(2)); + //RTL_W8(0xA2F, (RTL_R8(0xA2F) & ~BIT(5)) | BIT(4)); + //RTL_W8(0xA75, RTL_R8(0xA75) | BIT(0)); + RTL_W32(0xC8C, 0xa0240000); + RTL_W8(0x800, RTL_R8(0x800) & ~BIT(1)); + } + PHY_SetBBReg(priv, 0x90C, BIT(30), 0); + if (priv->pmib->dot11RFEntry.bcn2path){ + RTL_W32(0x80c,RTL_R32(0x80c)|BIT(31)); + RTL_W8(0x6D8, RTL_R8(0x6D8) | 0xCF); + } + } + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { +// 2009.09.10 + if (priv->pshare->rf_ft_var.cck_tx_pathB) { + RTL_W8(0xa07, 0x40); // 0x80 -> 0x40 CCK path B Tx + RTL_W8(0xa0b, 0x84); // 0x88 -> 0x84 CCK path B Tx + } + +// CCK path A Tx +#ifdef CONFIG_POCKET_ROUTER_SUPPORT +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) +#endif + { + RTL_W8(0xa07, (RTL_R8(0xa07) & 0xbf)); + RTL_W8(0xa0b, (RTL_R8(0xa0b) & 0xfb)); + } +#endif + +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_8198B) + RTL_W8(AGGR_BK_TIME, 0x18); + RTL_W16(0x4ca, 0x0a0a); +// RTL_W32(RESP_SIFS_CCK, 0x0e0e0a0a); + //RTL_W32(ACKTO, 0x40001440); + RTL_W16(ACKTO, 0x1440); + RTL_W16(RXFLTMAP2, 0xffff); + //RTL_W16(RCR, RTL_R16(RCR)&(~ BIT(11))); +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + //CBN debug + if (GET_CHIP_VER(priv) == VERSION_8192D) { +// RTL_W32(RD_CTRL, RTL_R32(RD_CTRL)|BIT(13)); // enable force tx beacon + RTL_W8(BCN_MAX_ERR, 0); // tx beacon error threshold +// RTL_W16(EIFS, 0x0040); // eifs < tbtt_prohibit + if (opmode & WIFI_AP_STATE) + RTL_W16(rFPGA0_RFTiming1, 0x5388); + } +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + {//not HAL + RTL_W16(EIFS, 0x0040); // eifs = 40 us + +#ifdef CONFIG_PCI_HCI + RTL_W32(0x350, RTL_R32(0x350) | BIT(26)); // tx status check +#endif + } + +#ifdef HIGH_POWER_EXT_PA + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + if (priv->pshare->rf_ft_var.use_ext_pa) { + priv->pmib->dot11RFEntry.trswitch = 1; + PHY_SetBBReg(priv, 0x870, BIT(10), 0); + if (GET_CHIP_VER(priv) == VERSION_8192C) + PHY_SetBBReg(priv, 0x870, BIT(26), 0); + } + } +#endif + +#if defined(SW_ANT_SWITCH) || defined(HW_ANT_SWITCH) +// priv->pmib->dot11RFEntry.trswitch = 1; +#endif + if(GET_CHIP_VER(priv) != VERSION_8188E){ + if (priv->pmib->dot11RFEntry.trswitch) + RTL_W8(GPIO_MUXCFG, RTL_R8(GPIO_MUXCFG) | TRSW0EN); + else + RTL_W8(GPIO_MUXCFG, RTL_R8(GPIO_MUXCFG) & ~TRSW0EN); + } + +#ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS) { + RTL_W8(0xc50, 0x24); + delay_us(10); + RTL_W8(0xc50, 0x20); + } +#endif + + if (get_rf_mimo_mode(priv) == MIMO_2T2R) { + RTL_W8(0xA20, (RTL_R8(0xA20) & ~BIT(5)) | BIT(4)); + RTL_W8(0xA2E, RTL_R8(0xA2E) | BIT(3) | BIT(2)); + RTL_W8(0x800, RTL_R8(0x800) & ~BIT(1)); + + if (priv->pmib->dot11RFEntry.tx2path) { + RTL_W32(0x90C, 0x83321333); + RTL_W32(0x80C, RTL_R32(0x80C) & ~BIT(31)); + RTL_W8(0x6D8, RTL_R8(0x6D8) | 0x3F); + RTL_W8(0xA07, 0xC1); + RTL_W8(0xA11, RTL_R8(0xA11) & ~BIT(5)); + RTL_W8(0xA2F, (RTL_R8(0xA2F) & ~BIT(5)) | BIT(4)); + RTL_W8(0xA75, RTL_R8(0xA75) | BIT(0)); + RTL_W32(0xC8C, 0xa0240000); + } + PHY_SetBBReg(priv, 0x90C, BIT(30), 0); + } else if (get_rf_mimo_mode(priv) == MIMO_1T1R) { + if (priv->pmib->dot11RFEntry.tx2path) { + DEBUG_INFO("Not 2T2R, disable tx2path\n"); + priv->pmib->dot11RFEntry.tx2path = 0; + } + if (priv->pmib->dot11RFEntry.txbf) { + DEBUG_INFO("Not 2T2R, disable txbf\n"); + priv->pmib->dot11RFEntry.txbf = 0; + } + } + + } + + +{ + //Set 0x55d=0 except ADHOC Mode for all IC (BCN_MAX_ERR) + #ifdef CLIENT_MODE + if (OPMODE & WIFI_ADHOC_STATE) + RTL_W8(0x55d, 0xff); + else + #endif + if(OPMODE & WIFI_AP_STATE) { + if((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C)) + RTL_W8(0x55d, 0xff); //Set 92C to MAX value to avoid init fail for some un-healthy demo boards. + else + RTL_W8(0x55d, 0x1); //Allow 1 Beacon Error only //Always Tx Beacon within PIFS + } + +// printk("0x55d = 0x%x\n", RTL_R8(0x55d)); +} + +#if defined(CONFIG_WLAN_HAL_8814AE) + if (GET_CHIP_VER(priv) == VERSION_8814A) { + if (get_rf_mimo_mode(priv) == MIMO_2T2R) + { + RTL_W8(0x82f, (RTL_R8(0x82f)&0xf0) | 0x5); + RTL_W8(0x830, (RTL_R8(0x830)&0xf0) | 0xa); + RTL_W8(0x808, 0x66); + RTL_W8(0x1002, 0x2); + RTL_W8(0x1002, 0x3); + if(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) + RTL_W8(0xa07, 0x46); + } + } +#endif + +#ifdef DRVMAC_LB + if (!priv->pmib->miscEntry.drvmac_lb) +#endif + { +#ifdef USE_OUT_SRC + if (IS_OUTSRC_CHIP(priv)) { + ODM_DMInit(ODMPTR); // DM parameters init + EdcaParaInit(priv); + } + else +#endif + { + rtl8192cd_AdaptivityInit(priv); + } + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { +// ? did twice ? +// phy_BB8192CD_Check_ParaFile(priv); +#if defined(CONFIG_WLAN_HAL_8881A) + if ((GET_CHIP_VER(priv) == VERSION_8881A) && _GET_HAL_DATA(priv)->bTestChip ) + { + PHY_CheckBBWithParaFile(priv, PHYREG); + } +#endif + + priv->pshare->No_RF_Write = 0; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + priv->pshare->No_RF_Write = 1; + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + RTL_W32(0x808, RTL_R32(0x808) | BIT(29)); + RTL_W8(0x454, RTL_R8(0x454) | BIT(7)); + } else { //PHY_BAND_2G + RTL_W32(0x808, RTL_R32(0x808) | BIT(29) | BIT(28)); + RTL_W8(0x454, RTL_R8(0x454) & ~ BIT(7)); + } +#if defined(CONFIG_WLAN_HAL_8814AE) + if (GET_CHIP_VER(priv) != VERSION_8814A) +#endif + { + RTL_W16(0x4ca, 0x1f1f); + RTL_W8(REG_RA_TRY_RATE_AGG_LMT_8812, 0x0); // try rate agg limit + } + +#if defined(CONFIG_WLAN_HAL_8814AE) + if (GET_CHIP_VER(priv) == VERSION_8814A) { + if(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) + RTL_W16(0x4ca, 0x1f1f); + /* + if (get_rf_mimo_mode(priv) == MIMO_2T2R) { + RTL_W8(0x82f, (RTL_R8(0x82f)&0xf0) | 0x5); + RTL_W8(0x830, (RTL_R8(0x830)&0xf0) | 0xa); + RTL_W8(0x808, 0x66); + RTL_W8(0x1002, 0x2); + RTL_W8(0x1002, 0x3); + if(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) + RTL_W8(0xa07, 0x46); + }*/ + } +#endif + + +// RTL_W32(0x2c, 0x28a3e200); +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (IS_TEST_CHIP(priv)) { + RTL_W8(0x44b, 0x3e); // 2SS MCS7~MCS3 + } else { + + RTL_W32(0x448, 0xfffff010); // 2SS MCS9~MCS3 + RTL_W8(0x452, 0x1f); // 1SS MCS8 + + } + // RTL_W32(0x2c, 0x4103e200); + RTL_W8(0x577, RTL_R8(0x577) | 3); //disable CCA in TXOp + RTL_W32(0x608, RTL_R32(0x608) | BIT(26)); +// RTL_W8(REG_RESP_SIFS_OFDM_8812+1, 0x0a); //R2T +#ifdef BEAMFORMING_SUPPORT + if (priv->pmib->dot11RFEntry.txbf == 1) { + RTL_W8(0x71b, 0x50); // ndp_rx_standby_timer + RTL_W16(0x718, RTL_R16(0x718) | 0x2cb); // Disable SIG-B CRC8 check + RTL_W32(0x604, RTL_R32(0x604) | BIT(26)); // Disable SIG-B CRC8 check + +#ifdef BEAMFORMING_SUPPORT + RTL_W32(RCR, RTL_R32(RCR) | RCR_ACF); +#endif + } +#endif + } +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) + + + RTL_W8(REG_RX_PKT_LIMIT_8812, 0x20); // rx pkt limit = 16k + +// Path A only + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (get_rf_mimo_mode(priv) == MIMO_1T1R) { + + if(AC_SIGMA_MODE==AC_SIGMA_NONE){ + RTL_W8(0x808, 0x11); + RTL_W16(0x80c, 0x1111); + RTL_W8(0xa07, (RTL_R8(0xa07) & 0xf3)); // [3:2] = 2'b 00 + RTL_W32(0x8bc, (RTL_R32(0x8bc) & 0x3FFFFF9F) | BIT(30) ); + RTL_W8(0xe00, (RTL_R8(0xe00) & 0xf0) | 0x04 ); + RTL_W8(0xe90, 0); + RTL_W32(0xe60, 0); + RTL_W32(0xe64, 0); + + } +#ifdef AC2G_256QAM + if(1) //if(is_ac2g(priv)) + { + RTL_W32(0x48c, 0x00000015); + RTL_W32(0x48c+4, 0x003ff000); + } +#endif + } else if (get_rf_mimo_mode(priv) == MIMO_2T2R) { + if (!((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) { + if (priv->pmib->dot11RFEntry.tx2path) { + printk("8812 Enable Tx 2 Path\n"); + RTL_W16(0x80c, 0x3333); + } else { + printk("8812 Disable Tx 2 Path\n"); + RTL_W16(0x80c, 0x1113); + } + } + } +#ifdef AC2G_256QAM + if(1) //if(is_ac2g(priv)) + { + RTL_W32(0x48c, 0x00000015); + RTL_W32(0x48c+4, 0x003ff000); + RTL_W32(0x494, 0x00000015); + RTL_W32(0x494+4, 0xffcff000); + } +#endif + } +#endif + + PHY_IQCalibrate(priv); //FOR_8812_IQK + +#if 1 //for 8812 IOT issue with 11N NICs + printk("0x838 B(1)= 0, 0x456 = 0x32 \n"); + RTL_W8(0x838, (RTL_R8(0x838)& ~ BIT(0))); //Disbale CCA +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (IS_TEST_CHIP(priv)) + RTL_W8(0x456, 0x32); //Refine AMPDU MAX duration + else if(get_rf_mimo_mode(priv) == MIMO_1T1R) + RTL_W8(0x456, 0xe0); + else + RTL_W8(0x456, 0x70); //8812_11n_iot, increase 0x456 for ampdu number + + RTL_W8(0x480, 0x20); //Enable duplicate RTS to whole bandwidth + + //RTL_W32(0x458, 0xffff); // aggregation max length + RTL_W32(0x458, 0x7fff); // agg size 64k->32k + + RTL_W8(0x420, 0x00); // Enable Retry + New frames for AMPDU + + if (IS_C_CUT_8812(priv)) { + RTL_W8(0x640, 0x40); + RTL_W8(0x45b, 0x80); + } else { + RTL_W8(0x640, 0x80); + } + +#ifdef EN_EFUSE + PHY_SetBBReg(priv, 0xc1c, 0xffe00000, OFDMSwingTable_8812[priv->pshare->OFDM_index0[0]]); + PHY_SetBBReg(priv, 0xe1c, 0xffe00000, OFDMSwingTable_8812[priv->pshare->OFDM_index0[1]]); +#else + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G){ + // 2G OFDM base index should be 0dB + PHY_SetBBReg(priv, 0xc1c, 0xffe00000, OFDMSwingTable_8812[12]); + PHY_SetBBReg(priv, 0xe1c, 0xffe00000, OFDMSwingTable_8812[12]); + priv->pshare->OFDM_index0[0] = 12; + priv->pshare->OFDM_index0[1] = 12; + }else{ +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + // ext_pa OFDM base index should be -4dB + PHY_SetBBReg(priv, 0xc1c, 0xffe00000, OFDMSwingTable_8812[20]); + PHY_SetBBReg(priv, 0xe1c, 0xffe00000, OFDMSwingTable_8812[20]); + priv->pshare->OFDM_index0[0] = 20; + priv->pshare->OFDM_index0[1] = 20; + } else +#endif + { + //int_pa OFDM base index should be -3dB + PHY_SetBBReg(priv, 0xc1c, 0xffe00000, OFDMSwingTable_8812[18]); + PHY_SetBBReg(priv, 0xe1c, 0xffe00000, OFDMSwingTable_8812[18]); + priv->pshare->OFDM_index0[0] = 18; + priv->pshare->OFDM_index0[1] = 18; + } + } +#endif +#ifdef MCR_WIRELESS_EXTEND + RTL_W32(0x10 , 0x2aab5e0c); //Enhance the Vcore for reviewing the function on + RTL_W32(0x830,0x2aaa6c88); +#endif + } +#endif +#endif + } +#endif + } + + RESTORE_INT(x); +#if defined(CONFIG_WLAN_HAL_8192EE) + + if (GET_CHIP_VER(priv) == VERSION_8192E) { + PHY_SetRFReg(priv, RF92CD_PATH_A, 0xb1, bMask20Bits, 0x55418); // LCK +// RESTORE_INT(x); + PHY_IQCalibrate(priv); + // TX power tracking init +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + priv->pshare->OFDM_index0[0] = 30; + priv->pshare->OFDM_index0[1] = 30; + priv->pshare->CCK_index0 = 30; + } else +#endif + { + priv->pshare->OFDM_index0[0] = 20; + priv->pshare->OFDM_index0[1] = 20; + priv->pshare->CCK_index0 = 20; + } + // printk("Init OFDM_index0 base index = %x \n",priv->pshare->OFDM_index0[0]); + // printk("Init OFDM_index0 base index = %x \n",priv->pshare->OFDM_index0[1]); + // printk("priv->pshare->CCK_index0 = %x \n",priv->pshare->CCK_index0); +// +// PHY_ConfigBBWithParaFile(priv, PHYREG); + + //LCCalibrate #20130301 Anchi +// printk("Do 8192E LCK!! RF 0xB6 = 0x%x\n", PHY_QueryRFReg(priv, RF_PATH_A, 0xB6, bMaskDWord, 1)); + for (i=0 ; i<10 ; i++) { + if (PHY_QueryRFReg(priv, RF_PATH_A, 0xB6, 0xff000, 1) == 0x8) + break; + + PHY_SetRFReg(priv, RF_PATH_A, 0x18, bMaskDWord, 0x0FC07); //LCK + delay_ms(50); + PHY_SetRFReg(priv, RF_PATH_A, 0xB6, bMaskDWord, 0x0803E); + printk("==> RF 0xB6 = 0x%x\n", PHY_QueryRFReg(priv, RF_PATH_A, 0xB6, bMaskDWord, 1)); + } + + for (i=0 ; i<10 ; i++) { + if (PHY_QueryRFReg(priv, RF_PATH_A, 0xB2, bMaskDWord, 1) == 0x8CC00) + break; + PHY_SetRFReg(priv, RF_PATH_A, 0x18, bMaskDWord, 0x0FC07); //LCK + delay_ms(50); + PHY_SetRFReg(priv, RF_PATH_A, 0xB2, bMaskDWord, 0x8CC00); + printk("==> RF 0xB2 = 0x%x\n", PHY_QueryRFReg(priv, RF_PATH_A, 0xB2, bMaskDWord, 1)); + } + printk("8192E LCK done!!\n"); +// SAVE_INT_AND_CLI(x); + + //Increse 92E rx gain #20130301 Anchi + PHY_SetRFReg(priv, RF_PATH_A, 0x0, bMaskDWord, 0x33e74); + + //2013-0717 VCO 9.6G supr #Anchi + //PHY_SetRFReg(priv, RF_PATH_A, 0xb2, bMaskDWord, 0xCC00); + //PHY_SetRFReg(priv, RF_PATH_A, 0x18, bMaskDWord, 0xFC07); + + RTL_W8(0xa2f, 0x10); //CDD for CCK + RTL_W8(0xa10, 0x7c); // for ACPR +#if 0 //disable CCK 2R CCA due to DC tone + if (_GET_HAL_DATA(priv)->cutVersion == ODM_CUT_D) { + //CCK-2RCCA+path selection + RTL_W8(0xa2e, 0xd6); + RTL_W8(0xa01, 0x47); + + PHY_SetBBReg(priv,0xa04,BIT(24)|BIT(25),1); + PHY_SetBBReg(priv,0xa04,BIT(26)|BIT(27),0); + PHY_SetBBReg(priv,0xa74,BIT(8),1); + PHY_SetBBReg(priv,0xa08,BIT(28),1); + } +#endif + + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + } +#endif + + +#if 1 // TODO: Filen, tmp setting for tuning TP +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv) == VERSION_8881A) { + unsigned int c50_bak = RTL_R8(0xc50); + RTL_W8(0xc50, 0x22); + RTL_W8(0xc50, c50_bak); +#if 0 + if (get_bonding_type_8881A()==BOND_8881AB) { + RTL_W32(0x460, 0x03086666); + } else { + RTL_W32(0x460, 0x0320ffff); + } +#endif + RTL_W32(0x460, 0x03014444); + RTL_W16(0x4ca, 0x1414); + RTL_W8(0x456, 0x30); + priv->pshare->OFDM_index0[0] = 22; // -5dB + priv->pshare->AddTxAGC = 0; + priv->pshare->AddTxAGC_index = 0; + priv->pshare->rf_ft_var.pwrtrk_TxAGC = 0; + + if (get_bonding_type_8881A() == BOND_8881AN) + { + unsigned int ch_band = PHY_QueryRFReg(priv, RF_PATH_A, 0x18, BIT(17)|BIT(18), 1); + if (ch_band == 0) + PHY_SetRFReg(priv, RF_PATH_A, 0x63, bMaskDWord, 0x114eb); + else if (ch_band == 1) + PHY_SetRFReg(priv, RF_PATH_A, 0x63, bMaskDWord, 0x116e7); + else if (ch_band = 2) + PHY_SetRFReg(priv, RF_PATH_A, 0x63, bMaskDWord, 0x11aeb); + } + + if ((get_bonding_type_8881A() == BOND_8881AM ||get_bonding_type_8881A() == BOND_8881AN) + && priv->pshare->rf_ft_var.use_intpa8881A && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G)) { + PHY_SetBBReg(priv, 0xc1c, 0xffe00000, OFDMSwingTable_8812[16]); //int_pa OFDM base index should be -2dB + priv->pshare->OFDM_index0[0] = 16; + } + + +#ifdef AC2G_256QAM + if(1) //if(is_ac2g(priv)) + { + RTL_W32(0x48c, 0x00000015); + RTL_W32(0x48c+4, 0x003ff000); + } +#endif + + } +#endif //CONFIG_WLAN_HAL_8881A +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + if (priv->pmib->dot11RFEntry.trswitch +#if defined(HIGH_POWER_EXT_PA) + || priv->pshare->rf_ft_var.use_ext_pa +#endif +#if defined (HIGH_POWER_EXT_LNA) + || priv->pshare->rf_ft_var.use_ext_lna +#endif + ) { +#if defined(CONFIG_PCI_HCI) + PHY_SetBBReg(priv,0x4c,0xfffffff,0x628282); + PHY_SetBBReg(priv,0x930,0xff000f,0x540000);//930[3:0] =0 for RFE_CTRL_0 and 54 for tr switch + PHY_SetBBReg(priv,0x93c,0xffff,0x0); + + //if (IS_HAL_TEST_CHIP(priv)) + RTL_W32(0x938, 0x540); //938[27:24]=0 for RFE_CTRL_6 and 54 for tr switch + //else + // RTL_W32(0x938, 0x450); + RTL_W32(0x940, 0x15); + RTL_W32(0x944, 0xffff); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + RTL_W32(0x4c, 0x70628282); + RTL_W32(0x930, 0x5000); + RTL_W32(0x934, 0x4000); + RTL_W32(0x93c, 0x0); + RTL_W32(0x938, 0x540); //938[27:24]=0 for RFE_CTRL_6 and 54 for tr switch + RTL_W32(0x940, 0x15); + RTL_W32(0x944, 0x83f); +#endif + printk("8192E ext PA or ext LNA !!!\n"); + } + + if (OPMODE & WIFI_AP_STATE) { + if ((priv->pshare->CurrentChannelBW==0 && priv->pmib->dot11RFEntry.dot11channel==13) + ||(priv->pshare->CurrentChannelBW==1 && priv->pmib->dot11RFEntry.dot11channel>=11)) + Check_92E_Spur_Valid(priv, false); + } + RTL_W8(0x462, 0x02); +#if defined(CONFIG_PCI_HCI) + RTL_W16(0x4ca, 0x1414); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + RTL_W16(0x4ca, 0x0a0a); +#ifdef SDIO_AP_OFFLOAD + RTL_W16(0x454 , RTL_R16(0x454) & ~(BIT6|BIT3)); + RTL_W16(0x100 , RTL_R16(0x100) | BIT(8)); +#endif +#endif +#if defined(HIGH_POWER_EXT_PA) + if (priv->pshare->rf_ft_var.use_ext_pa) + set_CCK_swing_index(priv, 30); +#endif + } +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + RTL_W8(0x462, 0x02); +#ifdef USE_OUT_SRC + if (IS_OUTSRC_CHIP(priv)) + set_CCK_swing_index(priv, ODMPTR->RFCalibrateInfo.DefaultCckIndex); +#endif + } +#endif + if (get_rf_mimo_mode(priv) == MIMO_1T1R){ +#ifdef CONFIG_WLAN_HAL_8881A + if(GET_CHIP_VER(priv) == VERSION_8881A){ // AC chip & 1T1R + unsigned int tmp1=0; + tmp1 = PHY_QueryBBReg(priv, 0x8b8, bMaskDWord); + tmp1 &= ~(BIT(19)|BIT(13)); /*bit13 control HT,bit19 controlVHT , 0:cca no black,1:cca black*/ + PHY_SetBBReg(priv, 0x8b8, 0xffffffff, tmp1); + + tmp1 = PHY_QueryBBReg(priv, 0x8bc, bMaskDWord); + tmp1 &= ~(BIT(6)|BIT(5)); /*[6:5]=0x0, control by group;group0=mcs0~7*/ + tmp1 &= ~(BIT(17)|BIT(15)); /*[18:15]=0xa;support mcs<10(0xa)*/ + tmp1 |= (BIT(18) | BIT(16)); + PHY_SetBBReg(priv, 0x8bc, 0xffffffff, tmp1); + } +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) + { + /* + when 1T1R let 0xd00[20:19] = 2'b 00 ==> Support < MCS8 + when 2T2R let 0xd00[20:19] = 2'b 01 ==> Support < MCS16 + 2. 0xd08[3] = 1'b 1 ==> Not support, break*/ + unsigned int bbtmp1=0; + bbtmp1 = PHY_QueryBBReg(priv, 0xd00, 0xffffffff); + bbtmp1 &= ~(BIT(19)|BIT(20)); + PHY_SetBBReg(priv, 0xd00, 0xffffffff, bbtmp1); + + bbtmp1 = PHY_QueryBBReg(priv, 0xd08, 0xffffffff); + bbtmp1 |= BIT(3); + PHY_SetBBReg(priv, 0xd08, 0xffffffff, bbtmp1); + } +#endif // CONFIG_RTL_92D_SUPPORT + } + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { // AC chip & 1T1R + unsigned int delay_count = 100; + unsigned char val_8b = 0; + unsigned char valtmp = 0; + do { + val_8b = RTL_R8(0x8B); + if ( val_8b & BIT(7)){ + break; + } + delay_us(50); + delay_count--; + if(delay_count==0){ + panic_printk("check 0x8B expire!!\n"); + } + } while (delay_count); + + //SDEBUG("net_work_type:%d\n",priv->pmib->dot11BssType.net_work_type); + + if (val_8b & BIT(7)) { + //SDEBUG("0x8B=[%02x],delay_count=%d\n",val_8b,delay_count); + /*------------------------------------------------*/ + valtmp = (val_8b&(BIT(4)|BIT(5)|BIT(6)))>> 4 ; + if(valtmp==1 && priv->pshare->phw->MIMO_TR_hw_support==MIMO_2T2R){ + panic_printk("Antenna munber not match[%d]\n",valtmp); +// RESTORE_INT(x); + return -1; + } + /*---------------------TYPES;AC or N---------------------------*/ + valtmp = (val_8b&(BIT(2)|BIT(3)))>>2 ; + //SDEBUG("%s\n",valtmp==3?"AC":(valtmp==2?"11N":"unknow")); + if(valtmp==2){ + if(priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC){ + //priv->pmib->dot11BssType.net_work_type &= ~(WIRELESS_11AC); + panic_printk("Not support AC!!\n"); +// RESTORE_INT(x); + return -1; + } + if( priv->pshare->is_40m_bw == 2 ){ + //priv->pshare->is_40m_bw=1; + panic_printk("Not support 80M BW!!\n"); +// RESTORE_INT(x); + return -1; + } + } + //SDEBUG("net_work_type:%d\n",priv->pmib->dot11BssType.net_work_type); + /*------------------------------------------------*/ + valtmp = val_8b&(BIT(1)|BIT(0)) ; + //panic_printk("Chip:%s\n",valtmp==3?"AE/AU":(valtmp==2?"AR-VN":"unknow")); + /*------------------------------------------------*/ + } + } +#endif // CONFIG_RTL_8812_SUPPORT +#ifdef WMM_DSCP_C42 + priv->pshare->aggrmax_bak = RTL_R16(PROT_MODE_CTRL + 2); +#endif + +#ifdef USE_OUT_SRC + if (IS_OUTSRC_CHIP(priv)) + RTL_W16( RD_CTRL, RTL_R16( RD_CTRL) & ~(DIS_TXOP_CFE)); +#endif + + //Tego added power on protection to avoid wlan hang after suddenly wdg reboot, button reviewed +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_WLAN_HAL_8881A)|| defined(CONFIG_WLAN_HAL_8814AE) + if ((GET_CHIP_VER(priv) == VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8192E)|| + (GET_CHIP_VER(priv) == VERSION_8881A)||(GET_CHIP_VER(priv) == VERSION_8814A)){ + RTL_W8(0x1c, RTL_R8(0x1c)|0x02); + } +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + { + if(priv->pmib->dot11RFEntry.tx2path) + { + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_WE_LUT, 0x80000,0x1); // RF Mode table write enable + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_WE_LUT, 0x80000,0x1); // RF Mode table write enable + + // Paath_A + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_RCK_OS, 0xfffff,0x18000); // Select RX mode 0x30=0x18000 + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_TXPA_G1, 0xfffff,0x0000f); // Set Table data + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_TXPA_G2, 0xfffff,0x77fc2); // Enable TXIQGEN in RX mode + // Path_B + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_RCK_OS, 0xfffff,0x18000); // Select RX mode + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_TXPA_G1, 0xfffff,0x0000f); // Set Table data + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_TXPA_G2, 0xfffff,0x77fc2); // Enable TXIQGEN in RX mode + + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_WE_LUT, 0x80000,0x0); // RF Mode table write disable + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_WE_LUT, 0x80000,0x0); // RF Mode table write disable + RTL_W8(0xA2F, 0x10); + } + } +#endif + +#ifdef WIFI_11N_2040_COEXIST + if (priv->pmib->dot11nConfigEntry.dot11nCoexist && (OPMODE & WIFI_AP_STATE) + && (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G)) + && priv->pshare->is_40m_bw) { + RTL_W8(0xa70, RTL_R8(0xa70) | BIT(7)); // Enable Concurrent CCA at LSB & USB + } +#endif + +#ifdef CONFIG_1RCCA_RF_POWER_SAVING +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + if (priv->pshare->rf_ft_var._1rcca_ps) + set_1rcca_ps(priv, 1); +#endif + + set_bcn_dont_ignore_edcca(priv); + +#ifdef USB_INTERFERENCE_ISSUE +#ifdef CONFIG_RTL_92C_SUPPORT + //fixed USB interface interference issue + RTL_W8(0xfe40, 0xe0); + RTL_W8(0xfe41, 0x8d); + RTL_W8(0xfe42, 0x80); + RTL_W32(0x20c,0xfd0320); +#if 1 + //2011/01/07 ,suggest by Johnny,for solved the problem that too many protocol error on USB bus + if(!IS_UMC_A_CUT(priv) )//&& !IS_92C_SERIAL(pHalData->VersionID))// TSMC , 8188 + { + // 0xE6=0x94 + RTL_W8(0xFE40, 0xE6); + RTL_W8(0xFE41, 0x94); + RTL_W8(0xFE42, 0x80); + + // 0xE0=0x19 + RTL_W8(0xFE40, 0xE0); + RTL_W8(0xFE41, 0x19); + RTL_W8(0xFE42, 0x80); + + // 0xE5=0x91 + RTL_W8(0xFE40, 0xE5); + RTL_W8(0xFE41, 0x91); + RTL_W8(0xFE42, 0x80); + + // 0xE2=0x81 + RTL_W8(0xFE40, 0xE2); + RTL_W8(0xFE41, 0x81); + RTL_W8(0xFE42, 0x80); + + } + +#endif +#endif // CONFIG_RTL_92C_SUPPORT +#endif // USB_INTERFERENCE_ISSUE + +// RESTORE_INT(x); + DBFEXIT; + + return 0; + +} + + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) || (defined(CONFIG_RTL_88E_SUPPORT) && defined(__KERNEL__) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI))) || defined(CONFIG_RTL_8812_SUPPORT) +static void rtl8192cd_ReadFwHdr(struct rtl8192cd_priv *priv) +{ + struct __RTL8192C_FW_HDR__ *pFwHdr = NULL; + unsigned char *swap_arr; + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) + return; +#endif +#ifdef __ECOS + unsigned char hdr_buf[RT_8192CD_FIRMWARE_HDR_SIZE]; + swap_arr = hdr_buf; +#endif +#ifdef __KERNEL__ + swap_arr = kmalloc(RT_8192CD_FIRMWARE_HDR_SIZE, GFP_ATOMIC); + if (swap_arr == NULL) + return; +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + memcpy(swap_arr, data_rtl8192dfw_n_start, RT_8192CD_FIRMWARE_HDR_SIZE); + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (IS_TEST_CHIP(priv)) + memcpy(swap_arr, data_rtl8812fw_start, RT_8192CD_FIRMWARE_HDR_SIZE); +#ifdef AC2G_256QAM + else if(is_ac2g(priv)) + memcpy(swap_arr, data_rtl8812fw_n_2g_start, RT_8192CD_FIRMWARE_HDR_SIZE); +#endif + else + memcpy(swap_arr, data_rtl8812fw_n_start, RT_8192CD_FIRMWARE_HDR_SIZE); + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { +#ifdef TESTCHIP_SUPPORT + if (IS_TEST_CHIP(priv)) + memcpy(swap_arr, data_rtl8192cfw_start, RT_8192CD_FIRMWARE_HDR_SIZE); + else +#endif + { + if ( IS_UMC_A_CUT_88C(priv) ) + memcpy(swap_arr, data_rtl8192cfw_ua_start, RT_8192CD_FIRMWARE_HDR_SIZE); + else + memcpy(swap_arr, data_rtl8192cfw_n_start, RT_8192CD_FIRMWARE_HDR_SIZE); + } + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + if ( RTL_R16(0xF0) > 0x8000 ) + memcpy(swap_arr, Array_8188E_FW_AP_S, RT_8192CD_FIRMWARE_HDR_SIZE); + else + memcpy(swap_arr, Array_8188E_FW_AP_T, RT_8192CD_FIRMWARE_HDR_SIZE); + } +#endif + + pFwHdr = (struct __RTL8192C_FW_HDR__ *)swap_arr; +#ifdef _BIG_ENDIAN_ + pFwHdr->signature = le16_to_cpu(pFwHdr->signature); + pFwHdr->version = le16_to_cpu(pFwHdr->version); + pFwHdr->year = le16_to_cpu(pFwHdr->year); // ready on after v33.1 +#endif + + priv->pshare->fw_signature = pFwHdr->signature; + priv->pshare->fw_category = pFwHdr->category; + priv->pshare->fw_function = pFwHdr->function; + priv->pshare->fw_version = pFwHdr->version; + priv->pshare->fw_sub_version = pFwHdr->subversion; + priv->pshare->fw_date_month = pFwHdr->month; + priv->pshare->fw_date_day = pFwHdr->day; + priv->pshare->fw_date_hour = pFwHdr->hour; + priv->pshare->fw_date_minute = pFwHdr->minute; +#ifdef __KERNEL__ + kfree(swap_arr); +#endif + /* + printk("fw_signature: "); + if (priv->pshare->fw_signature == RTL8192C_TEST_CHIP) + printk("92C_TEST_CHIP"); + else if (priv->pshare->fw_signature == RTL8188C_TEST_CHIP) + printk("88C_TEST_CHIP"); + else if (priv->pshare->fw_signature == RTL8192C_MP_CHIP_A) + printk("92C_MP_CHIP_A"); + else if (priv->pshare->fw_signature == RTL8188C_MP_CHIP_A) + printk("88C_MP_CHIP_A"); + else if (priv->pshare->fw_signature == RTL8192C_MP_CHIP_B) + printk("92C_MP_CHIP_B"); + else if (priv->pshare->fw_signature == RTL8188C_MP_CHIP_B) + printk("88C_MP_CHIP_B"); + printk(", "); + + printk("fw_category: "); + if (priv->pshare->fw_category == RTL8192C_NIC_PCIE) + printk("92C_NIC_PCIE"); + else if (priv->pshare->fw_category == RTL8192C_NIC_USB) + printk("92C_NIC_USB"); + else if (priv->pshare->fw_category == RTL8192C_AP_PCIE) + printk("92C_AP_PCIE"); + else if (priv->pshare->fw_category == RTL8192C_AP_USB) + printk("92C_AP_USB"); + printk(", "); + + printk("fw_function: "); + if (priv->pshare->fw_function == RTL8192C_NIC_NORMAL) + printk("92C_NIC_NORMAL"); + else if (priv->pshare->fw_function == RTL8192C_NIC_WWLAN) + printk("92C_NIC_WWLAN"); + else if (priv->pshare->fw_function == RTL8192C_AP_NORMAL) + printk("92C_AP_NORMAL"); + else if (priv->pshare->fw_function == RTL8192C_AP_SUSPEND) + printk("92C_AP_SUSPEND"); + printk("\n"); + + printk("fw_version: %d.%d, ", priv->pshare->fw_version, priv->pshare->fw_sub_version); + printk("fw_date: %02x-%02x %02x:%02x\n", priv->pshare->fw_date_month, priv->pshare->fw_date_day, + priv->pshare->fw_date_hour, priv->pshare->fw_date_minute); + */ +} +#endif + + +#ifdef CONFIG_RTL_92C_SUPPORT +static int Load_92C_Firmware(struct rtl8192cd_priv *priv) +{ + int fw_len, wait_cnt = 0; +#ifdef CONFIG_PCI_HCI + unsigned int CurPtr = 0; +#endif + unsigned int WriteAddr; + unsigned int Temp; + unsigned char *ptmp; + +#ifdef CONFIG_RTL8672 + printk("val=%x\n", RTL_R8(0x80)); +#endif + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) + return TRUE; +#endif + + printk("===> %s\n", __FUNCTION__); + +#ifdef TESTCHIP_SUPPORT + if (IS_TEST_CHIP(priv)) { + ptmp = data_rtl8192cfw_start + 32; + fw_len = (int)(data_rtl8192cfw_end - ptmp); + + } else +#endif + { + if ( IS_UMC_A_CUT_88C(priv) ) { + ptmp = data_rtl8192cfw_ua_start + 32; + fw_len = (int)(data_rtl8192cfw_ua_end - ptmp); + + } else { + ptmp = data_rtl8192cfw_n_start + 32; + fw_len = (int)(data_rtl8192cfw_n_end - ptmp); + } + } + + // Disable SIC + RTL_W8(0x41, 0x40); + delay_ms(1); + + // Enable MCU + + RTL_W8(SYS_FUNC_EN + 1, RTL_R8(SYS_FUNC_EN + 1) | 0x04); + delay_ms(1); + +#ifdef CONFIG_RTL8672 + RTL_W8(0x04, RTL_R8(0x04) | 0x02); + delay_ms(1); //czyao +#endif + + // Load SRAM + WriteAddr = 0x1000; + RTL_W8(MCUFWDL, RTL_R8(MCUFWDL) | MCUFWDL_EN); + delay_ms(1); + +// if (IS_TEST_CHIP(priv)) +// RTL_W8(0x82, RTL_R8(0x82) & 0xf7); +// else + RTL_W32(MCUFWDL, RTL_R32(MCUFWDL) & 0xfff0ffff); + + delay_ms(1); + +#ifdef CONFIG_PCI_HCI + while (CurPtr < fw_len) { + if ((CurPtr + 4) > fw_len) { + // Reach the end of file. + while (CurPtr < fw_len) { + Temp = *(ptmp + CurPtr); + RTL_W8(WriteAddr, (unsigned char)Temp); + WriteAddr++; + CurPtr++; + } + } else { + // Write FW content to memory. + Temp = *((unsigned int *)(ptmp + CurPtr)); + Temp = cpu_to_le32(Temp); + RTL_W32(WriteAddr, Temp); + WriteAddr += 4; + + if ((IS_TEST_CHIP(priv) == 0) && (WriteAddr == 0x2000)) { + unsigned char tmp = RTL_R8(MCUFWDL + 2); + tmp += 1; + WriteAddr = 0x1000; + RTL_W8(MCUFWDL + 2, tmp) ; + delay_ms(10); +// printk("\n[CurPtr=%x, 0x82=%x]\n", CurPtr, RTL_R8(0x82)); + } + CurPtr += 4; + } + } +#else + if (IS_ERR_VALUE(_WriteFW(priv, ptmp, fw_len))) + printk("WriteFW FAIL !\n"); +#endif + + Temp = RTL_R8(0x80); + Temp &= 0xfe; + Temp |= 0x02; + RTL_W8(0x80, (unsigned char)Temp); + delay_ms(1); + RTL_W8(0x81, 0x00); + + printk("<=== %s\n", __FUNCTION__); + + // check if firmware is ready + while (!(RTL_R8(MCUFWDL) & WINTINI_RDY)) { + if (++wait_cnt > 10) { + printk("8192c firmware not ready\n"); + return FALSE; + } + + delay_ms(1); + } +#ifdef CONFIG_RTL8672 + printk("val=%x\n", RTL_R8(MCUFWDL)); +#endif + + return TRUE; +} +#endif // CONFIG_RTL_92C_SUPPORT + + +#define SET_RTL8192CD_RF_HALT(priv) \ +{ \ + unsigned char u1bTmp; \ + \ + do \ + { \ + u1bTmp = RTL_R8(LDOV12D_CTRL); \ + u1bTmp |= BIT(0); \ + RTL_W8(LDOV12D_CTRL, u1bTmp); \ + RTL_W8(SPS1_CTRL, 0x0); \ + RTL_W8(TXPAUSE, 0xFF); \ + RTL_W16(CMDR, 0x57FC); \ + delay_us(100); \ + RTL_W16(CMDR, 0x77FC); \ + RTL_W8(PHY_CCA, 0x0); \ + delay_us(10); \ + RTL_W16(CMDR, 0x37FC); \ + delay_us(10); \ + RTL_W16(CMDR, 0x77FC); \ + delay_us(10); \ + RTL_W16(CMDR, 0x57FC); \ + RTL_W16(CMDR, 0x0000); \ + u1bTmp = RTL_R8((SYS_CLKR + 1)); \ + if (u1bTmp & BIT(7)) \ + { \ + u1bTmp &= ~(BIT(6) | BIT(7)); \ + if (!HalSetSysClk8192CD(priv, u1bTmp)) \ + break; \ + } \ + RTL_W8(0x03, 0x71); \ + RTL_W8(0x09, 0x70); \ + RTL_W8(0x29, 0x68); \ + RTL_W8(0x28, 0x00); \ + RTL_W8(0x20, 0x50); \ + RTL_W8(0x26, 0x0E); \ + } while (FALSE); \ +} + +void Unlock_MCU(struct rtl8192cd_priv *priv) +{ + // 1. To clear C2H + RTL_W8(C2H_SYNC_BYTE, 0x0); + // 2. Unlock Overall MCU while(1) + RTL_W8(MCU_UNLOCK, 0xFF); +} + +void FirmwareSelfReset(struct rtl8192cd_priv *priv) +{ + unsigned char u1bTmp; + unsigned int Delay = 1000; + if (priv->pshare->fw_version > 0x21 +#ifdef CONFIG_RTL_92D_SUPPORT + || GET_CHIP_VER(priv) == VERSION_8192D +#endif + ) { + RTL_W32(FWIMR, 0x20); + RTL_W8(REG_HMETFR + 3, 0x20); + u1bTmp = RTL_R8( REG_SYS_FUNC_EN + 1); + while (u1bTmp & BIT(2)) { + Delay--; + DEBUG_INFO("polling 0x03[2] Delay = %d \n", Delay); + if (Delay == 0) + break; + delay_us(50); + Unlock_MCU(priv); + u1bTmp = RTL_R8( REG_SYS_FUNC_EN + 1); + } + // restore MCU internal while(1) loop + RTL_W8(MCU_UNLOCK, 0); + if (u1bTmp & BIT(2)) { + DEBUG_ERR("FirmwareSelfReset fail: 0x03=%02x, 0x1EB=0x%02x\n", u1bTmp, RTL_R8(0x1EB)); +#ifdef CONFIG_USB_HCI + RTL_W8(SYS_FUNC_EN+1, 0x50); //Reset MAC and Enable 8051 + delay_ms(10); +#endif + } else { + DEBUG_INFO("FirmwareSelfReset success: 0x03 = %x\n", u1bTmp); + } + } +} + +//Return Value: +// 1: MAC I/O Registers Enable +// 0: MAC I/O Registers Disable +int check_MAC_IO_Enable(struct rtl8192cd_priv *priv) +{ + //Check PON register to decide + return ( (RTL_R16(SYS_FUNC_EN) & (FEN_MREGEN | FEN_DCORE)) == (FEN_MREGEN | FEN_DCORE) ); +} +#ifdef CONFIG_RTL8672 +extern unsigned char clk_src_40M; +#endif + +#ifdef CONFIG_PCI_HCI +int rtl8192cd_stop_hw(struct rtl8192cd_priv *priv) +{ + RTL_W8(0x1c, RTL_R8(0x1c)& ~BIT(1));// unlock reg0x00~0x03 for 8812 + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { +#ifdef TXREPORT + RTL8188E_DisableTxReport(priv); +#endif + RTL_W32(REG_88E_HIMR, 0); + RTL_W32(REG_88E_HIMRE, 0); + HalPwrSeqCmdParsing(priv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, rtl8188E_leave_lps_flow); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + RTL_W32(REG_HIMR0_8812, 0); + RTL_W32(REG_HIMR1_8812, 0); + HalPwrSeqCmdParsing(priv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, rtl8812_enter_lps_flow); + } else +#endif + { + RTL_W32(HIMR, 0); + RTL_W16(HIMRE, 0); + RTL_W16(HIMRE + 2, 0); + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT)); + } + + RTL_W8(RCR, 0); + RTL_W8(TXPAUSE, 0xff); // Pause MAC TX queue +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + ) { + // RTL_W8(CR, RTL_R8(CR) & ~(MACTXEN|MACRXEN)); + RTL_W8(CR, 0); + } +#endif + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pshare->wlandev_idx == 0) + RTL_W8(RSV_MAC0_CTRL, RTL_R8(RSV_MAC0_CTRL) & (~MAC0_EN)); + else + RTL_W8(RSV_MAC1_CTRL, RTL_R8(RSV_MAC1_CTRL) & (~MAC1_EN)); + + if ((RTL_R8(RSV_MAC0_CTRL)& MAC0_EN) || (RTL_R8(RSV_MAC1_CTRL)& MAC1_EN)) { // check if another interface exists + DEBUG_INFO("Another MAC exists, cannot stop hw!!\n"); + } else +#endif + { +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + ) { + //3 2.) ==== RF Off Sequence ==== + phy_InitBBRFRegisterDefinition(priv); // preparation for read/write RF register + + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x00, bMask20Bits, 0x00); // disable RF + RTL_W8(RF_CTRL, 0x00); + RTL_W8(APSD_CTRL, 0x40); + RTL_W8(SYS_FUNC_EN, 0xe2); // reset BB state machine + RTL_W8(SYS_FUNC_EN, 0xe0); // reset BB state machine + + + + //3 3.) ==== Reset digital sequence ==== + if (RTL_R8(MCUFWDL) & BIT(1)) { + //Make sure that Host Recovery Interrupt is handled by 8051 ASAP. + RTL_W32(FSIMR, 0); // clear FSIMR + RTL_W32(FWIMR, 0x20); // clear FWIMR except HRCV_INT + RTL_W32(FTIMR, 0); // clear FTIMR + FirmwareSelfReset(priv); + + //Clear FWIMR to guarantee if 8051 runs in ROM, it is impossible to run FWISR Interrupt handler + RTL_W32(FWIMR, 0x0); // clear All FWIMR + } else { + //Critical Error. + //the operation that reset 8051 is necessary to be done by 8051 + DEBUG_ERR("%s %d ERROR: (RTL_R8(MCUFWDL) & BIT(1))=0\n", __FUNCTION__, __LINE__); + DEBUG_ERR("%s %d ERROR: the operation that reset 8051 is necessary to be done by 8051,%d\n", __FUNCTION__, __LINE__, RTL_R8(MCUFWDL)); + } + } +#endif + + // ==== Reset digital sequence ==== + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E)) + RTL_W8(SYS_FUNC_EN + 1, RTL_R8(SYS_FUNC_EN + 1) & ~BIT(2)); + else +#endif + RTL_W8(SYS_FUNC_EN + 1, 0x51); // reset MCU, MAC register, DCORE + RTL_W8(MCUFWDL, 0); // reset MCU ready status + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + unsigned char u1bTmp = 0; + // 0x1F[7:0] = 0 // turn off RF + RTL_W8(REG_RF_CTRL_8812, 0x00); + + // Reset MCU. Suggested by Filen. 2011.01.26. by tynli. + u1bTmp = RTL_R8(REG_SYS_FUNC_EN_8812 + 1); + RTL_W8(REG_SYS_FUNC_EN_8812 + 1, (u1bTmp & (~BIT(2)))); + + // MCUFWDL 0x80[1:0]=0 // reset MCU ready status + RTL_W8(REG_MCUFWDL_8812, 0x00); + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + HalPwrSeqCmdParsing(priv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, rtl8188E_card_disable_flow); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + HalPwrSeqCmdParsing(priv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, rtl8812_card_disable_flow); + } else +#endif + { + //3 4.) ==== Disable analog sequence ==== + RTL_W8(AFE_PLL_CTRL, 0x80); // disable PLL + +#if defined(CONFIG_RTL_92C_SUPPORT) && defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8192C) { + RTL_W8(SPS0_CTRL, 0x2b); + } else +#endif + { +#ifdef CONFIG_RTL_92C_SUPPORT + if (IS_UMC_B_CUT_88C(priv)) + RTL_W8(SPS0_CTRL, 0x2b); + else +#endif + RTL_W8(SPS0_CTRL, 0x23); + } + } +#ifdef CONFIG_RTL8672 + if (!clk_src_40M) + RTL_W8(AFE_XTAL_CTRL, RTL_R8(AFE_XTAL_CTRL)&~BIT(0)); // only for ADSL platform because 40M crystal is only used by WiFi chip // disable XTAL, if No BT COEX +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + unsigned char u1bTmp = 0; + + // Reset MCU IO Wrapper + u1bTmp = RTL_R8(REG_RSV_CTRL_8812 + 1); + RTL_W8(REG_RSV_CTRL_8812 + 1, (u1bTmp & (~BIT(0)))); + u1bTmp = RTL_R8(REG_RSV_CTRL_8812 + 1); + RTL_W8(REG_RSV_CTRL_8812 + 1, u1bTmp | BIT(0)); + + // RSV_CTRL 0x1C[7:0] = 0x0E // lock ISO/CLK/Power control register + RTL_W8(REG_RSV_CTRL_8812, 0x0e); + } +#endif +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E)) { + // Reset MCU IO Wrapper + RTL_W8(RSV_CTRL0 + 1, RTL_R8(RSV_CTRL0 + 1) & ~BIT(3)); + RTL_W8(RSV_CTRL0 + 1, RTL_R8(RSV_CTRL0 + 1) | BIT(3)); + } else +#endif + { + RTL_W8(APS_FSMCO + 1, 0x10); + } + RTL_W8(RSV_CTRL0, 0x0e); // lock ISO/CLK/Power control register + + //3 5.) ==== interface into suspend ==== +// RTL_W16(APS_FSMCO, (RTL_R16(APS_FSMCO) & 0x00ff) | (0x18 << 8)); // PCIe suspend mode + +#ifdef CONFIG_RTL8672 + // 6.) Switch to XTAL_BSEL: NAND + RTL_W8(AFE_XTAL_CTRL, RTL_R8(AFE_XTAL_CTRL) & ~ BIT(1)); +#endif + } + return SUCCESS; +} +#endif // CONFIG_PCI_HCI + + +#ifdef RTK_AC_SUPPORT //#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + +#ifdef AC2G_256QAM +#define MAX_NUM_80M 8 + +unsigned char available_channel_AC_80m[MAX_NUM_80M][4] = { + {36, 40, 44, 48}, + {52, 56, 60, 64}, + {100, 104, 108, 112}, + {116, 120, 124, 128}, + {132, 136, 140, 144}, + {149, 153, 157, 161}, + {165, 169, 173, 177}, + {1, 5, 9, 13}, +}; +#else +#define MAX_NUM_80M 7 + +unsigned char available_channel_AC_80m[MAX_NUM_80M][4] = { + {36, 40, 44, 48}, + {52, 56, 60, 64}, + {100, 104, 108, 112}, + {116, 120, 124, 128}, + {132, 136, 140, 144}, + {149, 153, 157, 161}, + {165, 169, 173, 177}, +}; +#endif + + +void get_txsc_AC(struct rtl8192cd_priv *priv, unsigned char channel) +{ + unsigned char tmp, i, found = 0; + + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_80) { + for (tmp = 0; tmp < MAX_NUM_80M; tmp ++) { + for (i = 0; i < 4; i++) { + if (channel == available_channel_AC_80m[tmp][i]) { + found = 1; + //printk("found channel[%d] at [%d][%d]\n", channel, tmp, i); + break; + } + } + + if (found) + break; + } + + switch (i) { + case 0: + //printk("case 0 \n"); + priv->pshare->txsc_20 = _20_B_40_B; + priv->pshare->txsc_40 = _40_B; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + break; + case 1: + priv->pshare->txsc_20 = _20_A_40_B; + priv->pshare->txsc_40 = _40_B; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + break; + case 2: + priv->pshare->txsc_20 = _20_B_40_A; + priv->pshare->txsc_40 = _40_A; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + break; + case 3: + priv->pshare->txsc_20 = _20_A_40_A; + priv->pshare->txsc_40 = _40_A; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + break; + default: + break; + } + } else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + priv->pshare->txsc_20 = 1; + else + priv->pshare->txsc_20 = 2; + + priv->pshare->txsc_40 = 0; + } else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + priv->pshare->txsc_20 = 0; + priv->pshare->txsc_40 = 0; + } + + //printk("get_txsc_8812= %d %d \n", priv->pshare->txsc_20, priv->pshare->txsc_40); + +} + +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + +void SwBWMode_AC(struct rtl8192cd_priv *priv, unsigned int bandwidth, int offset) +{ + unsigned char bTmp = 0, bTmp2 = 0; + unsigned int dwTmp = 0, dwTmp2 = 0,dwTmp3 = 0, tmp_rf = 0; + unsigned char primary_channel = 0; + unsigned int eRFPath, curMaxRFPath; + +// printk("SwBWMode_AC +++ BW = %d txsc_20 = %d txsc_40 = %d\n", bandwidth, priv->pshare->txsc_20, priv->pshare->txsc_40); + + curMaxRFPath = RF92CD_PATH_MAX; + + primary_channel = priv->pshare->txsc_20; + +//3 ========== <1> Set rf_mode 0x8ac & 0x668 & 0x8 + dwTmp = RTL_R32(0x8ac); + dwTmp2 = RTL_R32(0x668); + dwTmp3 = RTL_R32(0x830); + + dwTmp &= ~(BIT(0) | BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(20) | BIT(21)); + dwTmp2 &= ~(BIT(7) | BIT(8)); + dwTmp3 &= ~(BIT(3) | BIT(2) | BIT(1)); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_AC_5: + dwTmp |= (BIT(6) | BIT(20)); + dwTmp3 |= (BIT(3) | BIT(1)); + RTL_W32(0x8ac, dwTmp); + + RTL_W32(0x668, dwTmp2); + RTL_W32(0x830, dwTmp3); + break; + case HT_CHANNEL_WIDTH_AC_10: + dwTmp |= (BIT(7) | BIT(8) | BIT(21)); + RTL_W32(0x8ac, dwTmp); + + RTL_W32(0x668, dwTmp2); + + dwTmp3 |= BIT(3); + RTL_W32(0x830, dwTmp3); + break; + case HT_CHANNEL_WIDTH_AC_20: + dwTmp |= (BIT(9) | BIT(20) | BIT(21)); + RTL_W32(0x8ac, dwTmp); + + RTL_W32(0x668, dwTmp2); + break; + case HT_CHANNEL_WIDTH_AC_40: + dwTmp |= (BIT(0) | BIT(9) | BIT(20) | BIT(21)); + RTL_W32(0x8ac, dwTmp); + + dwTmp2 |= BIT(7); + RTL_W32(0x668, dwTmp2); + break; + case HT_CHANNEL_WIDTH_AC_80: + dwTmp |= (BIT(1) | BIT(9) | BIT(20) | BIT(21)); + RTL_W32(0x8ac, dwTmp); + + dwTmp2 |= BIT(8); + RTL_W32(0x668, dwTmp2); + break; + } + + +//3 ========== <2> Set adc buff clk 0x8c4 , rf_mode 0x8 + if (IS_C_CUT_8812(priv)) { + switch (bandwidth) + { + case HT_CHANNEL_WIDTH_AC_5: + PHY_SetBBReg(priv, 0x8c4, BIT(30), 0); + PHY_SetBBReg(priv, 0x8, BIT(7)|BIT(6), 0x2); + break; + case HT_CHANNEL_WIDTH_AC_10: + PHY_SetBBReg(priv, 0x8c4, BIT(30), 0); + PHY_SetBBReg(priv, 0x8, BIT(7)|BIT(6), 0x1); + break; + case HT_CHANNEL_WIDTH_AC_20: + PHY_SetBBReg(priv, 0x8c4, BIT(30), 0); + PHY_SetBBReg(priv, 0x8, BIT(7)|BIT(6), 0x0); + break; + case HT_CHANNEL_WIDTH_AC_40: + PHY_SetBBReg(priv, 0x8c4, BIT(30), 0); + PHY_SetBBReg(priv, 0x8, BIT(7)|BIT(6), 0x0); + break; + case HT_CHANNEL_WIDTH_AC_80: + PHY_SetBBReg(priv, 0x8c4, BIT(30), 1); + PHY_SetBBReg(priv, 0x8, BIT(7)|BIT(6), 0x0); + break; + } + } + + +//3 ========== <3> Set primary channel 0x8ac & 0xa00, txsc 0x483 + + dwTmp = RTL_R32(0x8ac); + dwTmp &= ~(BIT(2)|BIT(3)|BIT(4)|BIT(5)); + + bTmp = RTL_R8(0xa00); + bTmp2= RTL_R8(0x483); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_AC_5: + case HT_CHANNEL_WIDTH_AC_10: + case HT_CHANNEL_WIDTH_AC_20: + break; + case HT_CHANNEL_WIDTH_AC_40: + dwTmp |= (primary_channel << 2); + RTL_W32(0x8ac, dwTmp); + RTL_W32(0x838, (RTL_R32(0x838) & 0x0fffffff) | (primary_channel << 28)); + + if (primary_channel == 1) + bTmp |= BIT(4); + else + bTmp &= ~(BIT(4)); + + RTL_W8(0xa00, bTmp); + + bTmp2 &= 0xf0; + bTmp2 |= priv->pshare->txsc_20; + RTL_W8(0x483, bTmp2); + + break; + case HT_CHANNEL_WIDTH_AC_80: + dwTmp |= (primary_channel << 2); + RTL_W32(0x8ac, dwTmp); + RTL_W32(0x838, (RTL_R32(0x838) & 0x0fffffff) | (primary_channel << 28)); + + bTmp2 = ( priv->pshare->txsc_20 | (priv->pshare->txsc_40 << 4)); + RTL_W8(0x483, bTmp2); + + break; + } + + SpurCheck8812(priv, 0, 0, bandwidth); + +//3 ========== <4> Set RRSR_RSC 0x440 + + dwTmp = RTL_R32(0x440); + dwTmp &= ~(BIT(21) | BIT(22)); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_AC_5: + case HT_CHANNEL_WIDTH_AC_10: + case HT_CHANNEL_WIDTH_AC_20: + break; + case HT_CHANNEL_WIDTH_AC_40: + RTL_W32(0x440, dwTmp); + break; + case HT_CHANNEL_WIDTH_AC_80: + + //dwTmp |= (0x3 << 21); + //dwTmp |= (0x2 << 21); // duplicate ? + RTL_W32(0x440, dwTmp); + break; + } + +//3 ========== <5> 0821, L1_peak_th 0x848 + dwTmp = RTL_R32(0x848); + dwTmp &= ~(BIT(22)|BIT(23)|BIT(24)|BIT(25)); + + switch (bandwidth) { + + case HT_CHANNEL_WIDTH_AC_5: + if (get_rf_mimo_mode(priv) == MIMO_1T1R) + dwTmp |= (7<<22); + else + dwTmp |= (6<<22); + break; + + case HT_CHANNEL_WIDTH_AC_10: + if (get_rf_mimo_mode(priv) == MIMO_1T1R) + dwTmp |= (8<<22); + else + dwTmp |= (7<<22); + break; + + case HT_CHANNEL_WIDTH_AC_20: + if (get_rf_mimo_mode(priv) == MIMO_1T1R) + dwTmp |= (8<<22); + else + dwTmp |= (7<<22); + break; + case HT_CHANNEL_WIDTH_AC_40: + dwTmp |= (6<<22); + break; + case HT_CHANNEL_WIDTH_AC_80: + dwTmp |= (5<<22); + break; + } + RTL_W32(0x848, dwTmp); + +//3 ========== <6> Set RF TRX_BW rf_0x18 + switch (bandwidth) + { + case HT_CHANNEL_WIDTH_AC_5: + case HT_CHANNEL_WIDTH_AC_10: + case HT_CHANNEL_WIDTH_AC_20: + tmp_rf = 0x03; + break; + case HT_CHANNEL_WIDTH_AC_40: + tmp_rf = 0x01; + break; + case HT_CHANNEL_WIDTH_AC_80: + tmp_rf = 0x00; + break; + } + + for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { + unsigned int orig_val = PHY_QueryRFReg(priv, eRFPath, rRfChannel, bMask20Bits, 1); + orig_val &= ~(BIT(10)|BIT(11)); + orig_val |= (tmp_rf << 10); + PHY_SetRFReg(priv, eRFPath, rRfChannel, bMask20Bits, orig_val); + } + +} +#endif // #if defined(CONFIG_RTL_8812_SUPPORT) + +#ifdef CONFIG_WLAN_HAL_8192EE +void get_txsc_92e(struct rtl8192cd_priv *priv, unsigned char channel) +{ + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + priv->pshare->txsc_20_92e = 1; + else + priv->pshare->txsc_20_92e = 2; + } else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + priv->pshare->txsc_20_92e = 0; + } +} +#endif + +void SwBWMode(struct rtl8192cd_priv *priv, unsigned int bandwidth, int offset) +{ + unsigned char regBwOpMode, regRRSR_RSC, nCur40MhzPrimeSC; + unsigned int eRFPath, curMaxRFPath, val; + +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + priv->pshare->No_RF_Write = 0; + get_txsc_AC(priv, priv->pmib->dot11RFEntry.dot11channel); + SwBWMode_AC(priv, bandwidth, offset); + priv->pshare->No_RF_Write = 1; + return; + } +#endif //#if defined(CONFIG_RTL_8812_SUPPORT) + +#if defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + if ((GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) { + priv->pshare->No_RF_Write = 0; + get_txsc_AC(priv, priv->pmib->dot11RFEntry.dot11channel); + GET_HAL_INTERFACE(priv)->PHYSwBWModeHandler(priv, bandwidth, offset); + priv->pshare->No_RF_Write = 1; + return; + } +#endif //#if defined(CONFIG_WLAN_HAL_8881A) +#if defined(CONFIG_WLAN_HAL_8192EE) + if (GET_CHIP_VER(priv) == VERSION_8192E) { + get_txsc_92e(priv, priv->pmib->dot11RFEntry.dot11channel); + GET_HAL_INTERFACE(priv)->PHYSwBWModeHandler(priv, bandwidth, offset); + return; + } +#endif + + DEBUG_INFO("SwBWMode(): Switch to %s bandwidth\n", bandwidth ? "40MHz" : "20MHz"); + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + curMaxRFPath = RF92CD_PATH_B; + else +#endif + curMaxRFPath = RF92CD_PATH_MAX; + + if (offset == 1) + nCur40MhzPrimeSC = 2; + else + nCur40MhzPrimeSC = 1; + + //3 <1> Set MAC register + regBwOpMode = RTL_R8(BWOPMODE); + regRRSR_RSC = RTL_R8(RRSR + 2); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + regBwOpMode |= BW_OPMODE_20MHZ; + RTL_W8(BWOPMODE, regBwOpMode); + break; + case HT_CHANNEL_WIDTH_20_40: + regBwOpMode &= ~BW_OPMODE_20MHZ; + RTL_W8(BWOPMODE, regBwOpMode); + regRRSR_RSC = (regRRSR_RSC & 0x90) | (nCur40MhzPrimeSC << 5); + RTL_W8(RRSR + 2, regRRSR_RSC); + + // Let 812cd_rx, re-assign value + if (priv->pshare->is_40m_bw) { + priv->pshare->Reg_RRSR_2 = 0; + priv->pshare->Reg_81b = 0; + } + break; + default: + DEBUG_ERR("SwBWMode(): bandwidth mode error!\n"); + return; + break; + } + + //3 <2> Set PHY related register + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + PHY_SetBBReg(priv, rFPGA0_RFMOD, bRFMOD, 0x0); + PHY_SetBBReg(priv, rFPGA1_RFMOD, bRFMOD, 0x0); +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, rFPGA0_AnalogParameter2, BIT(11) | BIT(10), 3);// SET BIT10 BIT11 for receive cck + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + PHY_SetBBReg(priv, rFPGA0_AnalogParameter2, BIT(10), 1); + } +#endif + break; + case HT_CHANNEL_WIDTH_20_40: + PHY_SetBBReg(priv, rFPGA0_RFMOD, bRFMOD, 0x1); + PHY_SetBBReg(priv, rFPGA1_RFMOD, bRFMOD, 0x1); + // Set Control channel to upper or lower. These settings are required only for 40MHz + PHY_SetBBReg(priv, rCCK0_System, bCCKSideBand, (nCur40MhzPrimeSC >> 1)); + PHY_SetBBReg(priv, rOFDM1_LSTF, 0xC00, nCur40MhzPrimeSC); +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, rFPGA0_AnalogParameter2, BIT(11) | BIT(10), 0);// SET BIT10 BIT11 for receive cck + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + PHY_SetBBReg(priv, rFPGA0_AnalogParameter2, BIT(10), 0); + } +#endif + PHY_SetBBReg(priv, 0x818, (BIT(26) | BIT(27)), (nCur40MhzPrimeSC == 2) ? 1 : 2); + break; + default: + DEBUG_ERR("SwBWMode(): bandwidth mode error! %d\n", __LINE__); + return; + break; + } + + //3<3> Set RF related register + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + val = 3; + else +#endif + val = 1; + } + break; + case HT_CHANNEL_WIDTH_20_40: + val = 0; + break; + default: + DEBUG_ERR("SwBWMode(): bandwidth mode error! %d\n", __LINE__); + return; + break; + } + + for (eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + PHY_SetRFReg(priv, eRFPath, rRfChannel, (BIT(11) | BIT(10)), val); + } +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + priv->pshare->RegRF18[eRFPath] = RTL_SET_MASK(priv->pshare->RegRF18[eRFPath], (BIT(11) | BIT(10)), val, 10); + PHY_SetRFReg(priv, eRFPath, rRfChannel, bMask20Bits, priv->pshare->RegRF18[eRFPath]); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, (BIT(11)|BIT(10)), val); + } +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, rRfChannel, (BIT(11) | BIT(10)), val); + } +#endif + } + +#if 0 + if (priv->pshare->rf_ft_var.use_frq_2_3G) + PHY_SetRFReg(priv, RF90_PATH_C, 0x2c, 0x60, 0); +#endif +#ifdef TX_EARLY_MODE +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + if ((bandwidth == HT_CHANNEL_WIDTH_20) && GET_TX_EARLY_MODE) { + GET_TX_EARLY_MODE = 0; + //printk("[%s:%d] 88E 20M mpde ===> turn off early mode!\n", __FUNCTION__, __LINE__); + } + } +#endif +#endif +} + + +#if defined(SUPPORT_TX_AMSDU) || defined (P2P_SUPPORT) +void setup_timer2(struct rtl8192cd_priv *priv, unsigned int timeout) +{ + unsigned int current_value = RTL_R32(TSFTR); + + if (TSF_LESS(timeout, current_value)) + timeout = current_value + 20; + + RTL_W32(TIMER1, timeout); + +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv) ) { + GET_HAL_INTERFACE(priv)->AddInterruptMaskHandler(priv, HAL_INT_TYPE_PSTIMEOUT2); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + {//not HAL +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + RTL_W32(REG_HIMR0_8812, RTL_R32(REG_HIMR0_8812) | IMR_TIMER2_8812); + else +#endif + RTL_W32(HIMR, RTL_R32(HIMR) | HIMR_TIMEOUT2); + } +} + + +void cancel_timer2(struct rtl8192cd_priv *priv) +{ + +#ifdef CONFIG_WLAN_HAL + if ( IS_HAL_CHIP(priv) ) { + GET_HAL_INTERFACE(priv)->RemoveInterruptMaskHandler(priv, HAL_INT_TYPE_PSTIMEOUT2); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + {//not HAL +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + RTL_W32(REG_HIMR0_8812, RTL_R32(REG_HIMR0_8812) & ~IMR_TIMER2_8812); + else +#endif + RTL_W32(HIMR, RTL_R32(HIMR) & ~HIMR_TIMEOUT2); + } +} +#endif + + + +#if 0 +void tx_path_by_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char enable) +{ + + if ((get_rf_mimo_mode(priv) != MIMO_2T2R)) + return; // 1T2R, 1T1R; do nothing + + if (pstat == NULL) + return; + + if (pstat->sta_in_firmware != 1 || getSTABitMap(&priv->pshare->has_2r_sta, REMAP_AID(pstat))) // 2r STA + return; // do nothing + + // for debug, by victoryman 20090623 + if (pstat->tx_ra_bitmap & 0xff00000) { + // this should be a 2r station!!! + return; + } + + if (pstat->tx_ra_bitmap & 0xffff000) { // 11n 1R client + if (enable) { + if (pstat->rf_info.mimorssi[0] > pstat->rf_info.mimorssi[1]) + Switch_1SS_Antenna(priv, 1); + else + Switch_1SS_Antenna(priv, 2); + } else + Switch_1SS_Antenna(priv, 3); + } else if (pstat->tx_ra_bitmap & 0xff0) { // 11bg client + if (enable) { + if (pstat->rf_info.mimorssi[0] > pstat->rf_info.mimorssi[1]) + Switch_OFDM_Antenna(priv, 1); + else + Switch_OFDM_Antenna(priv, 2); + } else + Switch_OFDM_Antenna(priv, 3); + } + +#if 0 // original setup + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { // for 11n 1ss sta + if (enable) { + if (pstat->rf_info.mimorssi[0] > pstat->rf_info.mimorssi[1]) + Switch_1SS_Antenna(priv, 1); + else + Switch_1SS_Antenna(priv, 2); + } else + Switch_1SS_Antenna(priv, 3); + } else if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { // for 11g + if (enable) { + if (pstat->rf_info.mimorssi[0] > pstat->rf_info.mimorssi[1]) + Switch_OFDM_Antenna(priv, 1); + else + Switch_OFDM_Antenna(priv, 2); + } else + Switch_OFDM_Antenna(priv, 3); + } +#endif + + +} +//#endif + + +// dynamic Rx path selection by signal strength +void rx_path_by_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat, int enable) +{ + unsigned char highest_rssi = 0, higher_rssi = 0, under_ss_th_low = 0; + RF92CD_RADIO_PATH_E eRFPath, eRFPath_highest = 0, eRFPath_higher = 0; + int ant_on_processing = 0; +#ifdef _DEBUG_RTL8192CD_ + char path_name[] = {'A', 'B'}; +#endif + + if (enable == FALSE) { + if (priv->pshare->phw->ant_off_num) { + priv->pshare->phw->ant_off_num = 0; + priv->pshare->phw->ant_off_bitmap = 0; + RTL_W8(rOFDM0_TRxPathEnable, 0x0f); + RTL_W8(rOFDM1_TRxPathEnable, 0x0f); + DEBUG_INFO("More than 1 sta, turn on all path\n"); + } + return; + } + + for (eRFPath = RF92CD_PATH_A; eRFPath < priv->pshare->phw->NumTotalRFPath; eRFPath++) { + if (priv->pshare->phw->ant_off_bitmap & BIT(eRFPath)) + continue; + + if (pstat->rf_info.mimorssi[eRFPath] > highest_rssi) { + higher_rssi = highest_rssi; + eRFPath_higher = eRFPath_highest; + highest_rssi = pstat->rf_info.mimorssi[eRFPath]; + eRFPath_highest = eRFPath; + } + + else if (pstat->rf_info.mimorssi[eRFPath] > higher_rssi) { + higher_rssi = pstat->rf_info.mimorssi[eRFPath]; + eRFPath_higher = eRFPath; + } + + if (pstat->rf_info.mimorssi[eRFPath] < priv->pshare->rf_ft_var.ss_th_low) + under_ss_th_low = 1; + } + + // for OFDM + if (priv->pshare->phw->ant_off_num > 0) { + for (eRFPath = RF92CD_PATH_A; eRFPath < priv->pshare->phw->NumTotalRFPath; eRFPath++) { + if (!(priv->pshare->phw->ant_off_bitmap & BIT(eRFPath))) + continue; + + if (highest_rssi >= priv->pshare->phw->ant_on_criteria[eRFPath]) { + priv->pshare->phw->ant_off_num--; + priv->pshare->phw->ant_off_bitmap &= (~BIT(eRFPath)); + RTL_W8(rOFDM0_TRxPathEnable, ~(priv->pshare->phw->ant_off_bitmap) & 0x0f); + RTL_W8(rOFDM1_TRxPathEnable, ~(priv->pshare->phw->ant_off_bitmap) & 0x0f); + DEBUG_INFO("Path %c is on due to >= %d%%\n", + path_name[eRFPath], priv->pshare->phw->ant_on_criteria[eRFPath]); + ant_on_processing = 1; + } + } + } + + if (!ant_on_processing) { + if (priv->pshare->phw->ant_off_num < 2) { + for (eRFPath = RF92CD_PATH_A; eRFPath < priv->pshare->phw->NumTotalRFPath; eRFPath++) { + if ((eRFPath == eRFPath_highest) || (priv->pshare->phw->ant_off_bitmap & BIT(eRFPath))) + continue; + + if ((pstat->rf_info.mimorssi[eRFPath] < priv->pshare->rf_ft_var.ss_th_low) && + ((highest_rssi - pstat->rf_info.mimorssi[eRFPath]) > priv->pshare->rf_ft_var.diff_th)) { + priv->pshare->phw->ant_off_num++; + priv->pshare->phw->ant_off_bitmap |= BIT(eRFPath); + priv->pshare->phw->ant_on_criteria[eRFPath] = highest_rssi + 5; + RTL_W8(rOFDM0_TRxPathEnable, ~(priv->pshare->phw->ant_off_bitmap) & 0x0f); + RTL_W8(rOFDM1_TRxPathEnable, ~(priv->pshare->phw->ant_off_bitmap) & 0x0f); + DEBUG_INFO("Path %c is off due to under th_low %d%% and diff %d%%, will be on at %d%%\n", + path_name[eRFPath], priv->pshare->rf_ft_var.ss_th_low, + (highest_rssi - pstat->rf_info.mimorssi[eRFPath]), + priv->pshare->phw->ant_on_criteria[eRFPath]); + break; + } + } + } + } + + // For CCK + if (priv->pshare->rf_ft_var.cck_sel_ver == 1) { + if (under_ss_th_low && (pstat->rx_pkts > 20)) { + if (priv->pshare->phw->ant_cck_sel != ((eRFPath_highest << 2) | eRFPath_higher)) { + priv->pshare->phw->ant_cck_sel = ((eRFPath_highest << 2) | eRFPath_higher); + RTL_W8(0xa07, (RTL_R8(0xa07) & 0xf0) | priv->pshare->phw->ant_cck_sel); + DEBUG_INFO("CCK select default: path %c, optional: path %c\n", + path_name[eRFPath_highest], path_name[eRFPath_higher]); + } + } + } +} + + +// dynamic Rx path selection by signal strength +void rx_path_by_rssi_cck_v2(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int highest_rssi = -1000, higher_rssi = -1000; + RF92CD_RADIO_PATH_E eRFPath, eRFPath_highest = 0, eRFPath_higher = 0; +#ifdef _DEBUG_RTL8192CD_ + char path_name[] = {'A', 'B'}; +#endif + + for (eRFPath = RF92CD_PATH_A; eRFPath < priv->pshare->phw->NumTotalRFPath; eRFPath++) { + if (pstat->cck_mimorssi_total[eRFPath] > highest_rssi) { + higher_rssi = highest_rssi; + eRFPath_higher = eRFPath_highest; + highest_rssi = pstat->cck_mimorssi_total[eRFPath]; + eRFPath_highest = eRFPath; + } + + else if (pstat->cck_mimorssi_total[eRFPath] > higher_rssi) { + higher_rssi = pstat->cck_mimorssi_total[eRFPath]; + eRFPath_higher = eRFPath; + } + } + + if (priv->pshare->phw->ant_cck_sel != ((eRFPath_highest << 2) | eRFPath_higher)) { + priv->pshare->phw->ant_cck_sel = ((eRFPath_highest << 2) | eRFPath_higher); + RTL_W8(0xa07, (RTL_R8(0xa07) & 0xf0) | priv->pshare->phw->ant_cck_sel); + DEBUG_INFO("CCK rssi A:%d B:%d C:%d D:%d accu %d pkts\n", pstat->cck_mimorssi_total[0], + pstat->cck_mimorssi_total[1], pstat->cck_mimorssi_total[2], pstat->cck_mimorssi_total[3], pstat->cck_rssi_num); + DEBUG_INFO("CCK select default: path %c, optional: path %c\n", + path_name[eRFPath_highest], path_name[eRFPath_higher]); + } +} + + +// Tx power control +void tx_power_control(struct rtl8192cd_priv *priv, struct stat_info *pstat, int enable) +{ + if (enable) { + if (!priv->pshare->phw->lower_tx_power) { + // TX High power enable +// set_fw_reg(priv, 0xfd000009, 0, 0); + if (!priv->pshare->bcnTxAGC) + RTL_W8(0x364, RTL_R8(0x364) | FW_REG364_HP); + priv->pshare->phw->lower_tx_power++; + + if ((!priv->pshare->is_40m_bw || (pstat->tx_bw == HT_CHANNEL_WIDTH_20)) && + (!pstat->is_rtl8190_sta && !pstat->is_broadcom_sta && !pstat->is_marvell_sta && !pstat->is_intel_sta)) + set_fw_reg(priv, 0xfd004314, 0, 0); + else + set_fw_reg(priv, 0xfd000015, 0, 0); + } + } else { + if (priv->pshare->phw->lower_tx_power) { + //TX High power disable +// set_fw_reg(priv, 0xfd000008, 0, 0); + RTL_W8(0x364, RTL_R8(0x364) & ~FW_REG364_HP); + priv->pshare->phw->lower_tx_power = 0; + } + } +} + + +void tx_power_tracking(struct rtl8192cd_priv *priv) +{ + if (priv->pmib->dot11RFEntry.ther) { + DEBUG_INFO("TPT: triggered(every %d seconds)\n", priv->pshare->rf_ft_var.tpt_period); + + // enable rf reg 0x24 power and trigger, to get ther value in 1 second + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x24, bMask20Bits, 0x60); + mod_timer(&priv->pshare->phw->tpt_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(1000)); // 1000ms + } +} + + +void rtl8192cd_tpt_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned int val32; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (timer_pending(&priv->pshare->phw->tpt_timer)) + del_timer_sync(&priv->pshare->phw->tpt_timer); + + if (priv->pmib->dot11RFEntry.ther) { + // query rf reg 0x24[4:0], for thermal meter value + val32 = PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x24, bMask20Bits, 1) & 0x01f; + + if (val32) { + set_fw_reg(priv, 0xfd000019 | (priv->pmib->dot11RFEntry.ther & 0xff) << 8 | val32 << 16, 0, 0); + DEBUG_INFO("TPT: finished once (ther: current=0x%02x, target=0x%02x)\n", + val32, priv->pmib->dot11RFEntry.ther); + } else { + DEBUG_WARN("TPT: cannot finish, since wrong current ther value report\n"); + } + } +} +#endif + + +/* + * + * CAM related functions + * + */ + +/*******************************************************/ +/*CAM related utility */ +/*CamAddOneEntry */ +/*CamDeleteOneEntry */ +/*CamResetAllEntry */ +/*******************************************************/ +#define TOTAL_CAM_ENTRY (priv->pshare->total_cam_entry) + +#define CAM_CONTENT_COUNT 8 +#define CAM_CONTENT_USABLE_COUNT 6 + +#define CFG_VALID BIT(15) +#define CFG_RPT_MD BIT(8) + + +static UCHAR CAM_find_usable(struct rtl8192cd_priv *priv) +{ + unsigned long command = 0, content = 0; + unsigned char index; + int for_begin = 4; +#ifdef CONFIG_WLAN_HAL + u4Byte retVal; +#endif // CONFIG_WLAN_HAL + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + for_begin = 3; + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + for_begin = 0; +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + for_begin = 0; + } else { + if (IS_ROOT_INTERFACE(priv)) { + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + for_begin = 0; + } + } +#endif + } +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + retVal = GET_HAL_INTERFACE(priv)->CAMFindUsableHandler(priv, for_begin); + return (unsigned char)retVal; + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + for (index = for_begin; index < TOTAL_CAM_ENTRY; index++) { + // polling bit, and No Write enable, and address + command = CAM_CONTENT_COUNT * index; + RTL_W32(CAMCMD, (SECCAM_POLL | command)); + + // Check polling bit is clear + while (1) { + command = RTL_R32(CAMCMD); + if (command & SECCAM_POLL) + continue; + else + break; + } + content = RTL_R32(CAMREAD); + + // check valid bit. if not valid, + if ((content & CFG_VALID) == 0) { + return index; + } + } + } + return TOTAL_CAM_ENTRY; +} + + +static void CAM_program_entry(struct rtl8192cd_priv *priv, unsigned char index, unsigned char* macad, + unsigned char* key128, unsigned short config) +{ + unsigned long target_command = 0, target_content = 0; + signed char entry_i = 0; + struct stat_info *pstat; + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->CAMProgramEntryHandler( + priv, + index, + macad, + key128, + config + ); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + for (entry_i = (CAM_CONTENT_USABLE_COUNT-1); entry_i >= 0; entry_i--) { + // polling bit, and write enable, and address + target_command = entry_i + CAM_CONTENT_COUNT * index; + target_command = target_command | SECCAM_POLL | SECCAM_WE; + if (entry_i == 0) { + //first 32-bit is MAC address and CFG field + target_content = (ULONG)(*(macad + 0)) << 16 + | (ULONG)(*(macad + 1)) << 24 + | (ULONG)config; + target_content = target_content | config; + } else if (entry_i == 1) { + //second 32-bit is MAC address + target_content = (ULONG)(*(macad + 5)) << 24 + | (ULONG)(*(macad + 4)) << 16 + | (ULONG)(*(macad + 3)) << 8 + | (ULONG)(*(macad + 2)); + } else { + target_content = (ULONG)(*(key128 + (entry_i * 4 - 8) + 3)) << 24 + | (ULONG)(*(key128 + (entry_i * 4 - 8) + 2)) << 16 + | (ULONG)(*(key128 + (entry_i * 4 - 8) + 1)) << 8 + | (ULONG)(*(key128 + (entry_i * 4 - 8) + 0)); + } + + RTL_W32(CAMWRITE, target_content); + RTL_W32(CAMCMD, target_command); + } + + target_content = RTL_R32(CR); + if ((target_content & MAC_SEC_EN) == 0) + RTL_W32(CR, (target_content | MAC_SEC_EN)); + } + + pstat = get_stainfo(priv, macad); + if (pstat) { + pstat->cam_id = index; + } +// move above +#if 0 + target_content = RTL_R32(CR); + if ((target_content & MAC_SEC_EN) == 0) + RTL_W32(CR, (target_content | MAC_SEC_EN)); +#endif +} + + +int CamAddOneEntry(struct rtl8192cd_priv *priv, unsigned char *pucMacAddr, unsigned long keyId, + unsigned long encAlg, unsigned long useDK, unsigned char *pKey) +{ + unsigned char retVal = 0, camIndex = 0, wpaContent = 0; + unsigned short usConfig = 0; + unsigned int set_dk_margin = 4; + + //use Hardware Polling to check the valid bit. + //in reality it should be done by software link-list + if ((!memcmp(pucMacAddr, "\xff\xff\xff\xff\xff\xff", 6)) || (useDK +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + && ((encAlg >> 2) != DOT11_ENC_WAPI) +#endif + )) + camIndex = keyId; + else + camIndex = CAM_find_usable(priv); + + if (camIndex == TOTAL_CAM_ENTRY) + return retVal; + + usConfig = usConfig | CFG_VALID | ((USHORT)(encAlg)) | (UCHAR)keyId; +#ifdef MULTI_MAC_CLONE + if ((OPMODE&WIFI_STATION_STATE) && priv->pmib->ethBrExtInfo.macclone_enable) + usConfig |= CFG_RPT_MD; +#endif + +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + if ((encAlg >> 2) == DOT11_ENC_WAPI) { + //ulUseDK is used to diff Parwise and Group + if (camIndex < 4) //is group key + usConfig |= BIT(6); + + if (useDK == 1) // ==0 sec key; == 1mic key + usConfig |= BIT(5); + + useDK = 0; + } +#endif + + CAM_program_entry(priv, camIndex, pucMacAddr, pKey, usConfig); + + if (priv->pshare->CamEntryOccupied == 0) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + SECURITY_CONFIG_OPERATION SCO; + + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_SECURITY_CONFIG, (pu1Byte)&SCO); + if (useDK == 1) { + SCO |= SCO_RXUSEDK | SCO_TXUSEDK; + } + SCO |= SCO_RXDEC | SCO_TXENC | SCO_NOSKMC | SCO_CHK_KEYID; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_SECURITY_CONFIG, (pu1Byte)&SCO); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + if (useDK == 1) + wpaContent = RXUSEDK | TXUSEDK; + RTL_W16(SECCFG, RTL_R16(SECCFG) | RXDEC | TXENC | wpaContent | NOSKMC | CHK_KEYID); + } + } + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + set_dk_margin = 3; + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + set_dk_margin = 0; +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + set_dk_margin = 0; + } else { + if (IS_ROOT_INTERFACE(priv)) { + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + set_dk_margin = 0; + } + } +#endif + } +#endif + + if (camIndex < set_dk_margin) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + SECURITY_CONFIG_OPERATION SCO; + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_SECURITY_CONFIG, (pu1Byte)&SCO); + SCO = (SCO & ~SCO_NOSKMC) | (SCO_RXBCUSEDK | SCO_TXBCUSEDK); + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_SECURITY_CONFIG, (pu1Byte)&SCO); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + RTL_W16(SECCFG, (RTL_R16(SECCFG) & ~NOSKMC) | (RXBCUSEDK | TXBCUSEDK)); + } + } + + return 1; +} + +#if(CONFIG_WLAN_NOT_HAL_EXIST==1) +void CAM_read_mac_config(struct rtl8192cd_priv *priv, unsigned char index, unsigned char* pMacad, + unsigned short* pTempConfig) +{ + unsigned long command = 0, content = 0; + + // polling bit, and No Write enable, and address + // cam address... + // first 32-bit + command = CAM_CONTENT_COUNT * index + 0; + command = command | SECCAM_POLL; + RTL_W32(CAMCMD, command); + + //Check polling bit is clear + while (1) { +#ifdef CONFIG_SDIO_HCI + { + s32 err; + command = sdio_read32(priv, CAMCMD, &err); + if (-ENOMEDIUM == err) + return; + } +#else + command = RTL_R32(CAMCMD); +#endif + if (command & SECCAM_POLL) + continue; + else + break; + } + content = RTL_R32(CAMREAD); + + //first 32-bit is MAC address and CFG field + *(pMacad + 0) = (UCHAR)((content >> 16) & 0x000000FF); + *(pMacad + 1) = (UCHAR)((content >> 24) & 0x000000FF); + *pTempConfig = (USHORT)(content & 0x0000FFFF); + + command = CAM_CONTENT_COUNT * index + 1; + command = command | SECCAM_POLL; + RTL_W32(CAMCMD, command); + + //Check polling bit is clear + while (1) { +#ifdef CONFIG_SDIO_HCI + { + s32 err; + command = sdio_read32(priv, CAMCMD, &err); + if (-ENOMEDIUM == err) + return; + } +#else + command = RTL_R32(CAMCMD); +#endif + if (command & SECCAM_POLL) + continue; + else + break; + } + content = RTL_R32(CAMREAD); + + *(pMacad + 5) = (UCHAR)((content >> 24) & 0x000000FF); + *(pMacad + 4) = (UCHAR)((content >> 16) & 0x000000FF); + *(pMacad + 3) = (UCHAR)((content >> 8) & 0x000000FF); + *(pMacad + 2) = (UCHAR)((content) & 0x000000FF); +} +#else +void CAM_read_mac_config(struct rtl8192cd_priv *priv, unsigned char index, unsigned char* pMacad, + unsigned short* pTempConfig) +{ + return; +} +#endif//CONFIG_WLAN_NOT_HAL_EXIST + + +#if 0 +void CAM_mark_invalid(struct rtl8192cd_priv *priv, UCHAR ucIndex) +{ + ULONG ulCommand = 0; + ULONG ulContent = 0; + + // polling bit, and No Write enable, and address + ulCommand = CAM_CONTENT_COUNT * ucIndex; + ulCommand = ulCommand | _CAM_POLL_ | _CAM_WE_; + // write content 0 is equall to mark invalid + RTL_W32(_CAM_W_, ulContent); + RTL_W32(_CAMCMD_, ulCommand); +} +#endif + + +static void CAM_empty_entry(struct rtl8192cd_priv *priv, unsigned char index) +{ + unsigned long command = 0, content = 0; + unsigned int i; + + for (i = 0; i < CAM_CONTENT_COUNT; i++) { + // polling bit, and No Write enable, and address + command = CAM_CONTENT_COUNT * index + i; + command = command | SECCAM_POLL | SECCAM_WE; + // write content 0 is equal to mark invalid + RTL_W32(CAMWRITE, content); + RTL_W32(CAMCMD, command); + } +} + + +int CamDeleteOneEntry(struct rtl8192cd_priv *priv, unsigned char *pMacAddr, unsigned long keyId, unsigned int useDK) +{ + unsigned char ucIndex; + unsigned char ucTempMAC[6]; + unsigned short usTempConfig = 0; + int for_begin = 4; + +#ifdef CONFIG_WLAN_HAL + CAM_ENTRY_CFG CamEntryCfg; +#endif + + // group key processing + if ((!memcmp(pMacAddr, "\xff\xff\xff\xff\xff\xff", 6)) || (useDK)) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->CAMReadMACConfigHandler(priv, keyId, ucTempMAC, &CamEntryCfg); + if ( _TRUE == CamEntryCfg.bValid ) { + GET_HAL_INTERFACE(priv)->CAMEmptyEntryHandler(priv, keyId); + + if (priv->pshare->CamEntryOccupied == 1) { + SECURITY_CONFIG_OPERATION SCO = 0; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_SECURITY_CONFIG, (pu1Byte)&SCO); + } + + return 1; + } else { + return 0; + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + CAM_read_mac_config(priv, keyId, ucTempMAC, &usTempConfig); + if (usTempConfig & CFG_VALID) { + CAM_empty_entry(priv, keyId); + if (priv->pshare->CamEntryOccupied == 1) + RTL_W16(SECCFG, 0); + return 1; + } else + return 0; + } + } +#ifdef CONFIG_WLAN_HAL + // TODO: check 8881A desgin below +#endif //CONFIG_WLAN_HAL + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + for_begin = 3; + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + for_begin = 0; +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + for_begin = 0; + } else { + if (IS_ROOT_INTERFACE(priv)) { + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + for_begin = 0; + } + } +#endif + } +#endif + + // unicast key processing + // key processing for RTL818X(B) series + for (ucIndex = for_begin; ucIndex < TOTAL_CAM_ENTRY; ucIndex++) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->CAMReadMACConfigHandler(priv, ucIndex, ucTempMAC, &CamEntryCfg); + if (!memcmp(pMacAddr, ucTempMAC, 6)) { +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + if ( (CamEntryCfg.EncAlgo == DOT11_ENC_WAPI) && (CamEntryCfg.KeyID != keyId)) { + continue; + } +#endif + + GET_HAL_INTERFACE(priv)->CAMEmptyEntryHandler(priv, ucIndex); + + if (priv->pshare->CamEntryOccupied == 1) { + SECURITY_CONFIG_OPERATION SCO = 0; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_SECURITY_CONFIG, (pu1Byte)&SCO); + } + return 1; + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + CAM_read_mac_config(priv, ucIndex, ucTempMAC, &usTempConfig); + if (!memcmp(pMacAddr, ucTempMAC, 6)) { + +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + if ((((usTempConfig & 0x1c) >> 2) == DOT11_ENC_WAPI) && ((usTempConfig & 0x3) != keyId)) + continue; +#endif + CAM_empty_entry(priv, ucIndex); // reset MAC address, david+2007-1-15 + + if (priv->pshare->CamEntryOccupied == 1) + RTL_W16(SECCFG, 0); + + return 1; + } + } + } + return 0; +} + + +/*now use empty to fill in the first 4 entries*/ +void CamResetAllEntry(struct rtl8192cd_priv *priv) +{ +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_CAM_RESET_ALL_ENTRY, NULL); + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + unsigned char index; + + RTL_W32(CAMCMD, SECCAM_CLR); + + for (index = 0; index < TOTAL_CAM_ENTRY; index++) + CAM_empty_entry(priv, index); + + RTL_W32(CR, RTL_R32(CR) & (~MAC_SEC_EN)); + } + priv->pshare->CamEntryOccupied = 0; + priv->pmib->dot11GroupKeysTable.keyInCam = 0; + +// RTL_W32(CR, RTL_R32(CR) & (~MAC_SEC_EN)); +} + + +void CAM_read_entry(struct rtl8192cd_priv *priv, unsigned char index, unsigned char* macad, + unsigned char* key128, unsigned short* config) +{ + unsigned long target_command = 0, target_content = 0; + unsigned char entry_i = 0; + unsigned long status; + + for (entry_i = 0; entry_i < CAM_CONTENT_USABLE_COUNT; entry_i++) { + // polling bit, and No Write enable, and address + target_command = (unsigned long)(entry_i + CAM_CONTENT_COUNT * index); + target_command = target_command | SECCAM_POLL; + + RTL_W32(CAMCMD, target_command); + //Check polling bit is clear + while (1) { + status = RTL_R32(CAMCMD); + if (status & SECCAM_POLL) + continue; + else + break; + } + target_content = RTL_R32(CAMREAD); + + if (entry_i == 0) { + //first 32-bit is MAC address and CFG field + *(config) = (unsigned short)((target_content) & 0x0000FFFF); + *(macad + 0) = (unsigned char)((target_content >> 16) & 0x000000FF); + *(macad + 1) = (unsigned char)((target_content >> 24) & 0x000000FF); + } else if (entry_i == 1) { + *(macad + 5) = (unsigned char)((target_content >> 24) & 0x000000FF); + *(macad + 4) = (unsigned char)((target_content >> 16) & 0x000000FF); + *(macad + 3) = (unsigned char)((target_content >> 8) & 0x000000FF); + *(macad + 2) = (unsigned char)((target_content) & 0x000000FF); + } else { + *(key128 + (entry_i * 4 - 8) + 3) = (unsigned char)((target_content >> 24) & 0x000000FF); + *(key128 + (entry_i * 4 - 8) + 2) = (unsigned char)((target_content >> 16) & 0x000000FF); + *(key128 + (entry_i * 4 - 8) + 1) = (unsigned char)((target_content >> 8) & 0x000000FF); + *(key128 + (entry_i * 4 - 8) + 0) = (unsigned char)(target_content & 0x000000FF); + } + + target_content = 0; + } +} + + +#if 0 +void debug_cam(UCHAR*TempOutputMac, UCHAR*TempOutputKey, USHORT TempOutputCfg) +{ + printk("MAC Address\n"); + printk(" %X %X %X %X %X %X\n", *TempOutputMac + , *(TempOutputMac + 1) + , *(TempOutputMac + 2) + , *(TempOutputMac + 3) + , *(TempOutputMac + 4) + , *(TempOutputMac + 5)); + printk("Config:\n"); + printk(" %X\n", TempOutputCfg); + + printk("Key:\n"); + printk("%X %X %X %X,%X %X %X %X,\n%X %X %X %X,%X %X %X %X\n" + , *TempOutputKey, *(TempOutputKey + 1), *(TempOutputKey + 2) + , *(TempOutputKey + 3), *(TempOutputKey + 4), *(TempOutputKey + 5) + , *(TempOutputKey + 6), *(TempOutputKey + 7), *(TempOutputKey + 8) + , *(TempOutputKey + 9), *(TempOutputKey + 10), *(TempOutputKey + 11) + , *(TempOutputKey + 12), *(TempOutputKey + 13), *(TempOutputKey + 14) + , *(TempOutputKey + 15)); +} + + +void CamDumpAll(struct rtl8192cd_priv *priv) +{ + UCHAR TempOutputMac[6]; + UCHAR TempOutputKey[16]; + USHORT TempOutputCfg = 0; + unsigned long flags; + int i; + + SAVE_INT_AND_CLI(flags); + for (i = 0; i < TOTAL_CAM_ENTRY; i++) { + printk("%X-", i); + CAM_read_entry(priv, i, TempOutputMac, TempOutputKey, &TempOutputCfg); + debug_cam(TempOutputMac, TempOutputKey, TempOutputCfg); + printk("\n\n"); + } + RESTORE_INT(flags); +} + + +void CamDump4(struct rtl8192cd_priv *priv) +{ + UCHAR TempOutputMac[6]; + UCHAR TempOutputKey[16]; + USHORT TempOutputCfg = 0; + unsigned long flags; + int i; + + SAVE_INT_AND_CLI(flags); + for (i = 0; i < 4; i++) { + printk("%X", i); + CAM_read_entry(priv, i, TempOutputMac, TempOutputKey, &TempOutputCfg); + debug_cam(TempOutputMac, TempOutputKey, TempOutputCfg); + printk("\n\n"); + } + RESTORE_INT(flags); +} +#endif + +#ifdef SDIO_AP_OFFLOAD +int offloadTestFunction(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int mode; + mode = _atoi(data, 16); + + if (strlen(data) == 0) { + printk("Usage:\n"); + printk("offload 6 - Leave offload\n"); + return 0; + } + + if (mode == 0x6) { + schedule_work(&GET_ROOT(priv)->ap_cmd_queue); + } + + return 0; +} +#endif // SDIO_AP_OFFLOAD + +#ifdef CONFIG_OFFLOAD_FUNCTION +int offloadTestFunction(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int mode = 0; + mode = _atoi(data, 16); + + if (strlen(data) == 0) { + printk("offloadTest 0x1 downlaod Rsvd page\n"); + printk("offloadTest 0x2: AP offload enable \n"); + + return 0; + } + + if (mode == 0x0) { + u1Byte reg_val; + //clear the non-valid bit + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_REG_CCK_CHECK, (pu1Byte)®_val); + reg_val = reg_val & ~BIT(6); + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_REG_CCK_CHECK, (pu1Byte)®_val); + } + + if (mode == 0x1) { + printk("epdn 6e: download probe rsp\n"); + priv->offload_function_ctrl = 1; + //RTL_W16(0x100 , RTL_R16(0x100) | BIT(8)); // enable sw beacon +// tasklet_hi_schedule(&priv->pshare->rx_tasklet); + //RTL_W8(HWSEQ_CTRL,RTL_R8(HWSEQ_CTRL) | BIT(6)); // HW SEQ + + u4Byte u4_val; + + // enable sw beacon + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_REG_CR, (pu4Byte)&u4_val); + u4_val = u4_val | BIT(8); + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_REG_CR, (pu4Byte)&u4_val); + + u1Byte u1_val; + +#if (IS_RTL8192E_SERIES | IS_RTL8881A_SERIES) + // HW SEQ + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HWSEQ_CTRL, (pu1Byte)&u1_val); + u1_val = u1_val | BIT(6); + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_HWSEQ_CTRL, (pu1Byte)&u1_val); +#endif + + } + + + if (mode == 0x2) { + + unsigned char loc_bcn[1]; + unsigned char loc_probe[1]; + + loc_bcn[0] = priv->offload_bcn_page; + loc_probe[0] = priv->offload_proc_page; + + printk("loc_bcn[0]= %x \n", loc_bcn[0]); + printk("loc_probe[0]= %x \n", loc_probe[0]); + + GET_HAL_INTERFACE(priv)->SetAPOffloadHandler(priv, 1, 1, 0, 0, loc_bcn, loc_probe); + + + delay_ms(10); + } + + if (mode == 0x3) { + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 1 , 1); + } + + if (mode == 0x4) { + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0 , 1); + } + + return 0; +} +#endif //#ifdef CONFIG_OFFLOAD_FUNCTION + + +/* + * + * Power Saving related functions + * + */ +#ifdef PCIE_POWER_SAVING + +#ifdef CONFIG_RTL_92D_DMDP +extern u32 if_priv[]; +#endif + +#ifdef CONFIG_RTL_92D_DMDP + +void Sw_PCIE_Func2(int func) +{ +#if (RTL_USED_PCIE_SLOT==1) + int reg = 0xb8b2100c; +#else + int reg = 0xb8b0100c; +#endif + + REG32(reg) &= ~(1); + REG32(reg) |= func; // switch to function # +} +#endif + +#if defined(__LINUX_2_6__) +extern void HostPCIe_SetPhyMdioWrite(unsigned int , unsigned int , unsigned short ); +#endif +#ifdef ASPM_ENABLE +void ASPM_on_off(struct rtl8192cd_priv *priv) ; +#endif + +#ifndef CONFIG_RTL_8198B +#define CLK_MANAGE 0xb8000010 +#endif +#ifdef PCIE_POWER_SAVING_DEBUG +int PCIE_PowerDown(struct rtl8192cd_priv *priv, unsigned char *data) +{ +// #define PCIE_PHY0 0xb8b01008 + +#define dprintf printk + int tmp, mode, portnum = 0; + unsigned int PCIE_PHY0, linkstatus; + unsigned int haddr, saddr; + + if (GET_CHIP_VER(priv) == VERSION_8192D) { + haddr = CFG_92D_SLOTH; + saddr = CFG_92D_SLOTS; + } else { + haddr = CFG_92C_SLOTH; + saddr = CFG_92C_SLOTS; + } + + PCIE_PHY0 = haddr + 0x1008; + linkstatus = haddr + 0x728; + +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(priv->pshare->wlandev_idx); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) + portnum = RTL_USED_PCIE_SLOT; +#endif + + mode = _atoi(data, 16); + + if (strlen(data) == 0) { + dprintf("epdn mode.\n"); + dprintf("epdn 0: D0 ->L0 \n"); + dprintf("epdn 3: D3hot ->L1 \n"); + dprintf("epdn 4: board cast PME_TurnOff \n"); + dprintf("epdn 7: enable aspm and L0 entry \n"); + dprintf("epdn 8: enable aspm and L1 entry \n"); + dprintf("epdn 9: diable aspm \n"); + dprintf("epdn 5a: pcie reset \n"); + dprintf("epdn 6a: L0 -> L2 \n"); + dprintf("epdn 6b: L2 -> L0\n"); + dprintf("epdn 6c: L0 -> L1 \n"); + dprintf("epdn 6d: L1 -> L0\n"); + dprintf("epdn 6e: download probe rsp\n"); + dprintf("epdn a3: wake pin test\n"); + dprintf("epdn b: bar\n"); + dprintf("epdn b1: offload enable \n"); + dprintf("epdn b2: offload disable\n"); + dprintf("epdn c1: swith to 1T\n"); + dprintf("epdn c2: switch to 2T\n"); + dprintf("Link status=%x \n", REG32(linkstatus) & 0x1f ); + return 0; + } + + if (mode == 0) { + +#ifdef CONFIG_RTL_92D_DMDP + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (priv->pshare->wlandev_idx != 0) { + dprintf("not Root Interface!! \n"); + return 0; + } + Sw_PCIE_Func2(0); + } +#endif + +#ifdef SAVING_MORE_PWR + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0f0f); +#endif + tmp = REG32(0xb8b10044) & ( ~(3)); + REG32(0xb8b10044) = tmp | (0); //D0 + delay_ms(1); + REG32(0xb8b10044) = tmp | (0); //D0 + dprintf("D0 \n"); + priv->pwr_state = L0; + +#if defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8192D) { +#ifdef CONFIG_RTL_92D_DMDP +// if(priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + { + Sw_PCIE_Func2(1); +#ifdef SAVING_MORE_PWR + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0f0f); +#endif + tmp = REG32(0xb8b10044) & ( ~(3)); //D0 + REG32(0xb8b10044) = tmp | (0); //D0 + delay_ms(1); + REG32(0xb8b10044) = tmp | (0); //D0 + dprintf("D0 wlan1\n"); + ((struct rtl8192cd_priv *)if_priv[1])->pwr_state = L0; + } + Sw_PCIE_Func2(0); +#endif + delay_ms(1); + } +#endif + + } + + if (mode == 3) { + +#if defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8192D) { +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pshare->wlandev_idx != 0) { + dprintf("not Root Interface!! \n"); + return 0; + } +// if(priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + { + + dprintf("DMDP, disable wlan1 !!\n"); + Sw_PCIE_Func2(1); +#ifdef SAVING_MORE_PWR + REG32(0xb8b10080) |= (0x100); //enable clock PM +#endif + tmp = REG32(0xb8b10044) & ( ~(3)); + REG32(0xb8b10044) = tmp | (3); //D3 + + ((struct rtl8192cd_priv *)if_priv[1])->pwr_state = L1; +#ifdef SAVING_MORE_PWR + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0708); +#endif + } + Sw_PCIE_Func2(0); +#endif + delay_ms(1); + + } +#endif + +#ifdef SAVING_MORE_PWR + REG32(0xb8b10080) |= (0x100); //enable clock PM +#endif + tmp = REG32(0xb8b10044) & ( ~(3)); + REG32(0xb8b10044) = tmp | (3); //D3 + //HostPCIe_SetPhyMdioWrite(0xd, 0x15a6); + dprintf("D3 hot \n"); + priv->pwr_state = L1; +#ifdef SAVING_MORE_PWR + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0708); +#endif + } + + if (mode == 4) { + + RTL_W8(0x1c, 0xe1); // reg lock, dis_prst + RTL_W8(0x1c, 0xe1); + +#ifdef SAVING_MORE_PWR + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0f0f); +#endif + + REG32(0xb8b01008) |= (0x200); + dprintf("Host boardcase PME_TurnOff \n"); + priv->pwr_state = L2; + } + + + if (mode == 0xd) { + + RTL_W8(0x1c, 0x0); + priv->pshare->phw->cur_rx = 0; +#ifdef DELAY_REFILL_RX_BUF + priv->pshare->phw->cur_rx_refill = 0; +#endif + memset(&(priv->pshare->phw->txhead0), 0, sizeof(int) * 12); + + RTL_W8(SPS0_CTRL, 0x2b); + RTL_W32(BCNQ_DESA, priv->pshare->phw->tx_ringB_addr); + RTL_W32(MGQ_DESA, priv->pshare->phw->tx_ring0_addr); + RTL_W32(VOQ_DESA, priv->pshare->phw->tx_ring4_addr); + RTL_W32(VIQ_DESA, priv->pshare->phw->tx_ring3_addr); + RTL_W32(BEQ_DESA, priv->pshare->phw->tx_ring2_addr); + RTL_W32(BKQ_DESA, priv->pshare->phw->tx_ring1_addr); + RTL_W32(HQ_DESA, priv->pshare->phw->tx_ring5_addr); + RTL_W32(RX_DESA, priv->pshare->phw->ring_dma_addr); + + } + + if (mode == 7) { + REG32(0xb8b1070c) &= ~ ((0x7 << 27) | (0x7 << 24)); + REG32(0xb8b1070c) |= ((3) << 27) | ((1) << 24); //L1=8us, L0s=2us + + REG32(0xb8b00080) &= ~(0x3); + REG32(0xb8b10080) &= ~(0x3); + + REG32(0xb8b00080) |= 1; //L0s + REG32(0xb8b10080) |= 1; + priv->pwr_state = ASPM_L0s_L1; + } + + if (mode == 8) { + REG32(0xb8b1070c) &= ~ ((0x7 << 27) | (0x7 << 24)); + REG32(0xb8b1070c) |= ((1) << 27) | ((3) << 24); //L1=2us, L0s=4us + + REG32(0xb8b00080) &= ~(0x3); + REG32(0xb8b10080) &= ~(0x3); + + REG32(0xb8b00080) |= 3; //L1 + REG32(0xb8b10080) |= 3; //L1 + priv->pwr_state = ASPM_L0s_L1; + + } + + if (mode == 9) { + REG32(0xb8b00080) &= ~(0x3); + REG32(0xb8b10080) &= ~(0x3); + priv->pwr_state = L0; + } + + + if (mode == 0x6a) { + priv->ps_ctrl = 1 | 32 | 0x80; + mod_timer(&priv->ps_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(100)); + } + + if (mode == 0x6c) { + priv->ps_ctrl = 1 | 16 | 0x80; +// mod_timer(&priv->ps_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(100)); + PCIe_power_save_tasklet((unsigned long)priv); + } + + if ((mode == 0x6b) || (mode == 0x6d)) { + priv->ps_ctrl = 0x82 | (priv->pwr_state << 4); + priv->pshare->rf_ft_var.power_save &= 0xf0; + +#ifdef CONFIG_RTL_92D_DMDP + ((struct rtl8192cd_priv *)if_priv[1])->pshare->rf_ft_var.power_save &= 0xf0; +#endif + PCIe_power_save_tasklet((unsigned long)priv); + signin_h2c_cmd(priv, _AP_OFFLOAD_CMD_ , 0 ); +#ifdef CONFIG_RTL_92D_DMDP + signin_h2c_cmd(((struct rtl8192cd_priv *)if_priv[1]), _AP_OFFLOAD_CMD_ , 0 ); +#endif + } + + if (mode == 0x6e) { + priv->offload_ctrl = 1; + RTL_W16(0x100 , RTL_R16(0x100) | BIT(8)); // enable sw beacon + tasklet_hi_schedule(&priv->pshare->rx_tasklet); + } + + if (mode == 0xc1) { +// PHY_ConfigBBWithParaFile(priv, PATHB_OFF); + switch_to_1x1(priv, PWR_STATE_IN); + + } + + if (mode == 0xc2) { +// PHY_ConfigBBWithParaFile(priv, PATHB_ON); + switch_to_1x1(priv, PWR_STATE_OUT); + } + + if (mode == 0xb) { + REG32(0xb8b00004) = 0x00100007; + REG32(0xb8b10004) = 0x00100007; + REG32(0xb8b10010) = 0x18c00001; + REG32(0xb8b10018) = 0x19000004; + printk("b1-00=%x, b0-04=%x, b1-04=%x, b1-10=%x, b1-18=%x\n", REG32(0xb8b10000), + REG32(0xb8b00004), REG32(0xb8b10004), REG32(0xb8b10010), REG32(0xb8b10018) ); + } + + if (mode == 0xb1) { + unsigned int cmd = _AP_OFFLOAD_CMD_ | (1 << 8) | (HIDDEN_AP << 16) | ((GET_MIB(priv))->dot11OperationEntry.deny_any) << 24; + int page = ((priv->offload_ctrl) >> 7) & 0xff; + int cmd2 = 0, cmd2e = 0; + + if (!page) { + page = 2; + } + + if (GET_CHIP_VER(priv) != VERSION_8192D) { + cmd2 = (_RSVDPAGE_CMD_ | page << 8) ; + } else { + cmd2 = ( _RSVDPAGE_CMD_ | BIT(7) | (page << 8)); + cmd2e = (page << 8) | (page) ; + } + +// RTL_W16(PCIE_CTRL_REG, 0xff00 ); + REG32(saddr + 0x44) |= 0x8108; + + printk("cmd: %x %x\n", cmd2, cmd2e); + signin_h2c_cmd(priv, cmd2, cmd2e); + delay_ms(10); + signin_h2c_cmd(priv, cmd, 0 ); + printk("sign in h2c cmd:%x, 0x284=%x\n", cmd, RTL_R32(0x284)); + +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) + REG32(0xb8003000) |= BIT(16); // GIMR +#else + REG32(0xb8003000) |= BIT(9); // GIMR +#endif + + delay_ms(10); + } + + if (mode == 0xb2) { + signin_h2c_cmd(priv, 0x0000, 0); // offload disable + RTL_W8(0x423, 0x0); // mac seq disable + RTL_W8(0x286, 0); // RW_RELEASE_ENABLE + RTL_W16(PCIE_CTRL_REG, 0x00ff ); + } + + //static unsigned int Buffer[9]; + + if (mode == 0xa3) { + unsigned char tmp; +#ifdef RTL8676_WAKE_GPIO + int gpio_num, irq_num; + + get_wifi_wake_pin(&gpio_num); + irq_num = gpioGetBspIRQNum(gpio_num); + + gpioConfig(gpio_num, GPIO_FUNC_INPUT); + gpioSetIMR(gpio_num, EN_FALL_EDGE_ISR); // enable interrupt in falling-edge + REG32(BSP_GIMR) |= BIT(irq_num); + +#else + +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) + + if (GET_CHIP_VER(priv) == VERSION_8192D) { + REG32(0xb8000044) |= BIT(16) | BIT(17); //LEDPHASE1 + REG32(0xb8003500) &= ~(BIT(17)); //PABCD_CNR , gpio pin + REG32(0xb8003508) &= ~(BIT(17)); //PABCD_DIR + REG32(0xb8003518) &= (~(0x03 << 2)); + REG32(0xb8003518) |= (0x01 << 2); // PCD_IMR + } else { + REG32(0xb8000044) |= BIT(24); //LEDPHASE4 + REG32(0xb8003500) &= ~(BIT(20)); //PABCD_CNR , gpio pin + REG32(0xb8003508) &= ~(BIT(20)); //PABCD_DIR + REG32(0xb8003518) &= (~(0x03 << 8)); + REG32(0xb8003518) |= (0x01 << 8); // PCD_IMR + } + + REG32(0xb8003000) |= BIT(16); // GIMR +#else + REG32(0xb8000040) |= 0x0c00; //LEDPHASE1 :GPIOB7 + REG32(0xb8003500) &= ~(BIT(15));; //PABCD_CNR , gpio pin + REG32(0xb8003508) &= ~(BIT(15)); //PABCD_DIR + REG32(0xb8003514) &= (~(0x03 << 30)); + REG32(0xb8003514) |= (0x01 << 30); // PAB_IMR // enable interrupt in falling-edge + REG32(0xb8003000) |= BIT(9); // GIMR +#endif + +#endif + // clear wake pin status +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(priv->pshare->wlandev_idx); +#endif + + REG32(saddr + 0x44) = 0x8108; + tmp = RTL_R8(0x690); + if (tmp & 1) { + tmp ^= 0x1; + RTL_W8(0x690, tmp); + } + dprintf("0xb8b10044=%x,690=%x,3000=%x, 3514=%x\n", REG32(saddr + 0x44), RTL_R8(0x690), REG32(0xb8003000), REG32(0xb8003514) ); + RTL_W8(0x690, tmp | 0x1 ); + dprintf("0xb8b10044=%x,690=%x\n", REG32(saddr + 0x44), RTL_R8(0x690) ); + } + + if (mode == 0x5a) + PCIE_reset_procedure3(priv); + + //------------------------------------------------------------- + if (mode == 0x010) { //L0->L1->L0 + tmp = REG32(0xb8b10044) & ( ~(3)); //D0 + REG32(0xb8b10044) = tmp | (3); //D3 + REG32(0xb8b10044) = tmp | (0); //D0, wakeup + + while (1) { + if ((REG32(linkstatus) & 0x1f) == 0x11) //wait to L0 + break; + } + + dprintf("DID/VID=%x\n", REG32(0xb8b10000)); + } + //------------------------------------------------------------- + if (mode == 0x020) { //L0->L2->L0 + tmp = REG32(0xb8b10044) & ( ~(3)); //D0 + + REG32(0xb8b10044) = tmp | (3); //D3 + delay_ms(100); + + REG32(0xb8b01008) |= (0x200); + delay_ms(100); + + //wakeup + REG32(CLK_MANAGE) &= ~(1 << 12); //perst=0 off. + //dprintf("CLK_MANAGE=%x \n", REG32(CLK_MANAGE)); + delay_ms(100); + delay_ms(100); + delay_ms(100); + + REG32(CLK_MANAGE) |= (1 << 12); //PERST=1 + //prom_printf("\nCLK_MANAGE(0x%x)=0x%x\n\n",CLK_MANAGE,READ_MEM32(CLK_MANAGE)); + + //4. PCIE PHY Reset + REG32(PCIE_PHY0) = 0x01; //bit7 PHY reset=0 bit0 Enable LTSSM=1 + REG32(PCIE_PHY0) = 0x81; //bit7 PHY reset=1 bit0 Enable LTSSM=1 + + while (1) { + if ( (REG32(linkstatus) & 0x1f) == 0x11) + break; + } + + dprintf("DID/VID=%x\n", REG32(0xb8b10000)); + } + + dprintf("Link status=%x\n", READ_MEM32(linkstatus) & 0x1f/*, READ_MEM32(linkstatus), REG32(linkstatus)*/ ); + + return 0; +} +#endif + + +void switch_to_1x1(struct rtl8192cd_priv *priv, int mode) +{ + + if (mode == PWR_STATE_IN) { + + priv->pshare->rf_phy_bb_backup[21] = RTL_R32(0x88c); + + priv->pshare->rf_phy_bb_backup[0] = RTL_R32(0x844); + priv->pshare->rf_phy_bb_backup[1] = RTL_R32(0x85c); + priv->pshare->rf_phy_bb_backup[2] = RTL_R32(0xe6c); + + priv->pshare->rf_phy_bb_backup[3] = RTL_R32(0xe70); + priv->pshare->rf_phy_bb_backup[4] = RTL_R32(0xe74); + priv->pshare->rf_phy_bb_backup[5] = RTL_R32(0xe78); + priv->pshare->rf_phy_bb_backup[6] = RTL_R32(0xe7c); + + priv->pshare->rf_phy_bb_backup[7] = RTL_R32(0xe80); + priv->pshare->rf_phy_bb_backup[8] = RTL_R32(0xe84); + priv->pshare->rf_phy_bb_backup[9] = RTL_R32(0xe88); + priv->pshare->rf_phy_bb_backup[10] = RTL_R32(0xe8c); + + priv->pshare->rf_phy_bb_backup[11] = RTL_R32(0xed0); + priv->pshare->rf_phy_bb_backup[12] = RTL_R32(0xed4); + priv->pshare->rf_phy_bb_backup[13] = RTL_R32(0xed8); + priv->pshare->rf_phy_bb_backup[14] = RTL_R32(0xedc); + + priv->pshare->rf_phy_bb_backup[15] = RTL_R32(0xee0); + priv->pshare->rf_phy_bb_backup[16] = RTL_R32(0xeec); + + priv->pshare->rf_phy_bb_backup[17] = RTL_R32(0xc04); + priv->pshare->rf_phy_bb_backup[18] = RTL_R32(0xd04); + priv->pshare->rf_phy_bb_backup[19] = RTL_R32(0x90c); + priv->pshare->rf_phy_bb_backup[20] = RTL_R32(0x804); + priv->pshare->rf_phy_bb_backup[22] = RTL_R32(0xa04); + +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D)) { + unsigned int mask = 0xB4FFFFFF, path = 0x11; + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { + mask = 0xDB3FFFFF; + path = 0x22; + RTL_W8(0xa07, 0x45); + } + PHY_SetBBReg(priv, 0x85c, bMaskDWord, priv->pshare->rf_phy_bb_backup[1] & mask); + PHY_SetBBReg(priv, 0xe6c, bMaskDWord, priv->pshare->rf_phy_bb_backup[2] & mask); + + PHY_SetBBReg(priv, 0xe70, bMaskDWord, priv->pshare->rf_phy_bb_backup[3] & mask); + PHY_SetBBReg(priv, 0xe74, bMaskDWord, priv->pshare->rf_phy_bb_backup[4] & mask); + PHY_SetBBReg(priv, 0xe78, bMaskDWord, priv->pshare->rf_phy_bb_backup[5] & mask); + PHY_SetBBReg(priv, 0xe7c, bMaskDWord, priv->pshare->rf_phy_bb_backup[6] & mask); + + PHY_SetBBReg(priv, 0xe80, bMaskDWord, priv->pshare->rf_phy_bb_backup[7] & mask); + PHY_SetBBReg(priv, 0xe84, bMaskDWord, priv->pshare->rf_phy_bb_backup[8] & mask); + PHY_SetBBReg(priv, 0xe88, bMaskDWord, priv->pshare->rf_phy_bb_backup[9] & mask); + PHY_SetBBReg(priv, 0xe8c, bMaskDWord, priv->pshare->rf_phy_bb_backup[10] & mask); + + PHY_SetBBReg(priv, 0xed0, bMaskDWord, priv->pshare->rf_phy_bb_backup[11] & mask); + PHY_SetBBReg(priv, 0xed4, bMaskDWord, priv->pshare->rf_phy_bb_backup[12] & mask); + PHY_SetBBReg(priv, 0xed8, bMaskDWord, priv->pshare->rf_phy_bb_backup[13] & mask); + PHY_SetBBReg(priv, 0xedc, bMaskDWord, priv->pshare->rf_phy_bb_backup[14] & mask); + + PHY_SetBBReg(priv, 0xee0, bMaskDWord, priv->pshare->rf_phy_bb_backup[15] & mask); + PHY_SetBBReg(priv, 0xeec, bMaskDWord, priv->pshare->rf_phy_bb_backup[16] & mask); + + PHY_SetBBReg(priv, 0xc04, 0x000000ff, path); + PHY_SetBBReg(priv, 0xd04, 0x0000000f, path & 0x01); + PHY_SetBBReg(priv, 0x90c, 0x000000ff, path); + PHY_SetBBReg(priv, 0x90c, 0x0ff00000, path); + + } else +#endif + { + PHY_SetBBReg(priv, 0x88c, 0x00c00000 , 0x3); + +#if 1 + // standby + PHY_SetBBReg(priv, 0x844, bMaskDWord, 0x00010000); +#else + // power off + PHY_SetBBReg(priv, 0x844, bMaskDWord, 0x00000000); +#endif + + PHY_SetBBReg(priv, 0x85c, bMaskDWord, 0x00db25a4); + PHY_SetBBReg(priv, 0xe6c, bMaskDWord, 0x20db25a4); + + PHY_SetBBReg(priv, 0xe70, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xe74, bMaskDWord, 0x041b25a4); + PHY_SetBBReg(priv, 0xe78, bMaskDWord, 0x041b25a4); + PHY_SetBBReg(priv, 0xe7c, bMaskDWord, 0x041b25a4); + + PHY_SetBBReg(priv, 0xe80, bMaskDWord, 0x041b25a4); + PHY_SetBBReg(priv, 0xe84, bMaskDWord, 0x63db25a4); + PHY_SetBBReg(priv, 0xe88, bMaskDWord, 0x041b25a4); + PHY_SetBBReg(priv, 0xe8c, bMaskDWord, 0x20db25a4); + + PHY_SetBBReg(priv, 0xed0, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xed4, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xed8, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xedc, bMaskDWord, 0x001b25a4); + + PHY_SetBBReg(priv, 0xee0, bMaskDWord, 0x001b25a4); + PHY_SetBBReg(priv, 0xeec, bMaskDWord, 0x24db25a4); + + PHY_SetBBReg(priv, 0xc04, 0x000000ff , 0x11); + PHY_SetBBReg(priv, 0xd04, 0x0000000f , 0x1); + PHY_SetBBReg(priv, 0x90c, 0x000000ff , 0x11); + PHY_SetBBReg(priv, 0x90c, 0x0ff00000 , 0x11); + + PHY_SetBBReg(priv, 0x804, 0x000000f , 0x1); + } + } else if (mode == PWR_STATE_OUT) { + +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192C) { + PHY_SetBBReg(priv, 0x88c, bMaskDWord, priv->pshare->rf_phy_bb_backup[21]); + PHY_SetBBReg(priv, 0x844, bMaskDWord, priv->pshare->rf_phy_bb_backup[0]); + } +#endif + PHY_SetBBReg(priv, 0x85c, bMaskDWord, priv->pshare->rf_phy_bb_backup[1]); + PHY_SetBBReg(priv, 0xe6c, bMaskDWord, priv->pshare->rf_phy_bb_backup[2]); + + PHY_SetBBReg(priv, 0xe70, bMaskDWord, priv->pshare->rf_phy_bb_backup[3]); + PHY_SetBBReg(priv, 0xe74, bMaskDWord, priv->pshare->rf_phy_bb_backup[4]); + PHY_SetBBReg(priv, 0xe78, bMaskDWord, priv->pshare->rf_phy_bb_backup[5]); + PHY_SetBBReg(priv, 0xe7c, bMaskDWord, priv->pshare->rf_phy_bb_backup[6]); + + PHY_SetBBReg(priv, 0xe80, bMaskDWord, priv->pshare->rf_phy_bb_backup[7]); + PHY_SetBBReg(priv, 0xe84, bMaskDWord, priv->pshare->rf_phy_bb_backup[8]); + PHY_SetBBReg(priv, 0xe88, bMaskDWord, priv->pshare->rf_phy_bb_backup[9]); + PHY_SetBBReg(priv, 0xe8c, bMaskDWord, priv->pshare->rf_phy_bb_backup[10]); + + PHY_SetBBReg(priv, 0xed0, bMaskDWord, priv->pshare->rf_phy_bb_backup[11]); + PHY_SetBBReg(priv, 0xed4, bMaskDWord, priv->pshare->rf_phy_bb_backup[12]); + PHY_SetBBReg(priv, 0xed8, bMaskDWord, priv->pshare->rf_phy_bb_backup[13]); + PHY_SetBBReg(priv, 0xedc, bMaskDWord, priv->pshare->rf_phy_bb_backup[14]); + + PHY_SetBBReg(priv, 0xee0, bMaskDWord, priv->pshare->rf_phy_bb_backup[15]); + PHY_SetBBReg(priv, 0xeec, bMaskDWord, priv->pshare->rf_phy_bb_backup[16]); + + PHY_SetBBReg(priv, 0xc04, bMaskDWord , priv->pshare->rf_phy_bb_backup[17]); + PHY_SetBBReg(priv, 0xd04, bMaskDWord , priv->pshare->rf_phy_bb_backup[18]); + PHY_SetBBReg(priv, 0x90c, bMaskDWord , priv->pshare->rf_phy_bb_backup[19]); + PHY_SetBBReg(priv, 0xa04, bMaskDWord , priv->pshare->rf_phy_bb_backup[22]); + +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192C) + PHY_SetBBReg(priv, 0x804, bMaskDWord , priv->pshare->rf_phy_bb_backup[20]); +#endif + } +} + +#ifdef __LINUX_2_6__ +irqreturn_t gpio_wakeup_isr(int irq, void *dev_instance); +#else +void gpio_wakeup_isr(int irq, void *dev_instance, struct pt_regs *regs); +#endif + +//const unsigned int CLK_MANAGE = 0xb8000010; +//const unsigned int SYS_PCIE_PHY0 =(0xb8000000 +0x50); +void PCIE_reset_procedure3(struct rtl8192cd_priv *priv) + +{ + + //PCIE Register + unsigned int PCIE_PHY0_REG, PCIE_PHY0, linkstatus, haddr; + int status = 0, counter = 0; + + if (GET_CHIP_VER(priv) == VERSION_8192D) + haddr = CFG_92D_SLOTH; + else + haddr = CFG_92C_SLOTH; + + PCIE_PHY0_REG = haddr + 0x1000; + PCIE_PHY0 = haddr + 0x1008; + linkstatus = haddr + 0x728; + + +#if 0 + REG32(CLK_MANAGE) &= ~(1 << 12); //perst=0 off. + //dprintf("CLK_MANAGE=%x \n", REG32(CLK_MANAGE)); + delay_ms(3); + delay_ms(3); + + REG32(CLK_MANAGE) |= (1 << 12); //PERST=1 + //prom_printf("\nCLK_MANAGE(0x%x)=0x%x\n\n",CLK_MANAGE,READ_MEM32(CLK_MANAGE)); + + //4. PCIE PHY Reset + REG32(PCIE_PHY0) = 0x01; //bit7 PHY reset=0 bit0 Enable LTSSM=1 + REG32(PCIE_PHY0) = 0x81; //bit7 PHY reset=1 bit0 + // + delay_ms(3); + +#else + do { + //2.Active LX & PCIE Clock + REG32(CLK_MANAGE) &= (~(1 << 11)); //enable active_pcie0 + delay_ms(2); + + //4. PCIE PHY Reset + REG32(PCIE_PHY0) = 0x1; //bit7 PHY reset=0 bit0 Enable LTSSM=1 + delay_ms(2); + + REG32(CLK_MANAGE) &= ~(1 << 12); //perst=0 off. + delay_ms(5); + + REG32(PCIE_PHY0) = 0x81; //bit7 PHY reset=1 bit0 Enable LTSSM=1 + delay_ms(5); + + REG32(CLK_MANAGE) |= (1 << 11); //enable active_pcie0 + + //--------------------------------------- + // 6. PCIE Device Reset + + delay_ms(5); + REG32(CLK_MANAGE) |= (1 << 12); //PERST=1 + delay_ms(5); + status = REG32(linkstatus) & 0x1f; + + if ( status == 0x11 ) { + break; + } else { + delay_ms(100); +// printk("status=%x\n", status); + if ( ++counter > 1000) { +// panic_printk("PCIe reset fail!!!!\n"); + break; + } + } + } while (1); + + + +#endif + +// printk("PCIE_reset_procedure3\t devid=%x\n",REG32(0xb8b10000)); + +} + +#ifdef ASPM_ENABLE +void ASPM_on_off(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + SAVE_INT_AND_CLI(flags); + unsigned int haddr, saddr; + if (GET_CHIP_VER(priv) == VERSION_8192D) { + haddr = CFG_92D_SLOTH; + saddr = CFG_92D_SLOTS; + } else { + haddr = CFG_92C_SLOTH; + saddr = CFG_92C_SLOTS; + } +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(priv->pshare->wlandev_idx); +#endif + + if (priv->pshare->rf_ft_var.power_save & ASPM_en) { + if (priv->pwr_state == L0) { + + REG32(haddr + 0x70c) &= ~ ((0x7 << 27) | (0x7 << 24)); + REG32(haddr + 0x70c) |= ((3) << 27) | ((1) << 24); //L1=8us, L0s=2us + + REG32(haddr + 0x80) &= ~(0x3); + REG32(saddr + 0x80) &= ~(0x3); + REG32(haddr + 0x80) |= 1; //L0s + REG32(saddr + 0x80) |= 1; + + priv->pwr_state = ASPM_L0s_L1; + } + } else if (priv->pwr_state == ASPM_L0s_L1) { + REG32(haddr + 0x80) &= ~(0x3); + REG32(saddr + 0x80) &= ~(0x3); + priv->pwr_state = L0; + } + + RESTORE_INT(flags); +} +#endif + +#ifdef GPIO_WAKEPIN +int request_irq_for_wakeup_pin(struct net_device *dev) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + unsigned int saddr; + + if (GET_CHIP_VER(priv) == VERSION_8192D) + saddr = CFG_92D_SLOTS; + else + saddr = CFG_92C_SLOTS; + +#if defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) + +#if defined(CONFIG_RTL_ULINKER) + { + // GPIO B5, b8000044 [10:9] = 2'b 11 + REG32(0xb8000044) = (REG32(0xb8000044) & ~0x600) | 0x600; //LEDPHASE1 + REG32(0xb8003500) &= ~(BIT(13)); //PABCD_CNR , gpio pin + REG32(0xb8003508) &= ~(BIT(13)); //PABCD_DIR + REG32(0xb8003514) &= (~(0x03 << 26)); + REG32(0xb8003514) |= (0x01 << 26); // enable interrupt in falling-edge + REG32(PABCD_ISR) = BIT(13) ; // clear int status + } +#else + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_8197D) + if (GET_CHIP_VER(priv) == VERSION_8192D) { + // GPIO B7, b8000044 [17:15] =3'b 100 + REG32(0xb8000044) = (REG32(0xb8000044) & ~0x00038000) | BIT(17); //LEDPHASE1 + REG32(0xb8003500) &= ~(BIT(15)); //PABCD_CNR , gpio pin + REG32(0xb8003508) &= ~(BIT(15)); //PABCD_DIR + REG32(0xb8003514) &= (~(0x03 << 30)); + REG32(0xb8003514) |= (0x01 << 30); // enable interrupt in falling-edge + REG32(PABCD_ISR) = BIT(15) ; // clear int status + + } else +#endif + { + // GPIO A4, b8000040 [2:0] = 3'b 110 + REG32(0xb8000040) = (REG32(0xb8000040) & ~0x7) | 0x6; //JTAG_TMS + REG32(0xb8003500) &= ~(BIT(4)); //PABCD_CNR , gpio pin + REG32(0xb8003508) &= ~(BIT(4)); //PABCD_DIR + REG32(0xb8003514) &= (~(0x03 << 8)); + REG32(0xb8003514) |= (0x01 << 8); // enable interrupt in falling-edge + REG32(PABCD_ISR) = BIT(4) ; // clear int status + } +#endif /* #if defined(CONFIG_RTL_ULINKER) */ + + REG32(0xb8003000) |= BIT(16); // GIMR + +#elif defined(CONFIG_RTL_8198) +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { +// GPIO C1 + REG32(0xb8000044) |= BIT(16) | BIT(17); //LEDPHASE1 + REG32(0xb8003500) &= ~(BIT(17)); //PABCD_CNR , gpio pin + REG32(0xb8003508) &= ~(BIT(17)); //PABCD_DIR + REG32(0xb8003518) &= (~(0x03 << 2)); + REG32(0xb8003518) |= (0x01 << 2); // enable interrupt in falling-edge + REG32(PABCD_ISR) = BIT(17) ; // clear int status + + } else +#endif + { +// GPIO C4 + REG32(0xb8000044) |= BIT(24); //LEDPHASE4 + REG32(0xb8003500) &= ~(BIT(20)); //PABCD_CNR , gpio pin + REG32(0xb8003508) &= ~(BIT(20)); //PABCD_DIR + REG32(0xb8003518) &= (~(0x03 << 8)); + REG32(0xb8003518) |= (0x01 << 8); // enable interrupt in falling-edge + REG32(PABCD_ISR) = BIT(20) ; // clear int status + } + REG32(0xb8003000) |= BIT(16); // GIMR +#else +// GPIO B7 + REG32(0xb8000040) |= 0x0c00; //LEDPHASE1 :GPIOB7 + REG32(0xb8003500) &= ~(BIT(15));; //PABCD_CNR , gpio pin + REG32(0xb8003508) &= ~(BIT(15)); //PABCD_DIR + REG32(0xb8003514) &= (~(0x03 << 30)); + REG32(0xb8003514) |= (0x01 << 30); // PAB_IMR // enable interrupt in falling-edge + REG32(0xb8003000) |= BIT(9); // GIMR + + REG32(PABCD_ISR) = BIT(15) ; // clear int status +#endif + +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(priv->pshare->wlandev_idx); +#endif + + REG32(saddr + 0x44) = 0x8108; // clear pme status + +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(0); +#endif + +#if defined(__LINUX_2_6__) + return request_irq(BSP_GPIO_ABCD_IRQ, gpio_wakeup_isr, IRQF_SHARED, "rtk_gpio", dev); +#else + return request_irq(1, gpio_wakeup_isr, SA_SHIRQ, "rtl_gpio", dev); +#endif + +} +#endif + + +void init_pcie_power_saving(struct rtl8192cd_priv *priv) +{ + + unsigned int saddr; + if (GET_CHIP_VER(priv) == VERSION_8192D) + saddr = CFG_92D_SLOTS; + else + saddr = CFG_92C_SLOTS; + +// Jason : clk req +#if 0 + REG32(0xb9000354) = 8; + REG32(0xb9000358) = 0x30; +#endif + +#ifdef FIB_96C + if (REG32(SYSTEM_BASE ) == 0x80000001) { +#if defined(__LINUX_2_6__) +#else + extern void HostPCIe_SetPhyMdioWrite(unsigned int , unsigned int , unsigned short ); +#endif + HostPCIe_SetPhyMdioWrite(0, 8, 0x18d5); // 18dd -> 18d5 + HostPCIe_SetPhyMdioWrite(0, 0xd, 0x15a6); // 15b6 -> 15a6 + } +#endif + +// Jason , for ASPM read_reg + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + RTL_W16(0x354, 0x18e); + RTL_W16(0x358, 0x23); + + if ((GET_CHIP_VER(priv) == VERSION_8188C) ) { + RTL_W16(0x354, 0x20eb); + RTL_W16(0x358, 0x3d); + } + } + +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(priv->pshare->wlandev_idx); +#endif + + REG32(saddr + 0x80) |= 0x0100; +#ifdef ASPM_ENABLE + REG32(saddr + 0x80) |= 0x43; +#endif + REG32(saddr + 0x0778) |= BIT(5) << 8; + +#ifdef CONFIG_RTL_92C_SUPPORT + +// 92c backdoor + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + REG32(saddr + 0x70c) |= BIT(7) << 24; + REG32(saddr + 0x718) |= (BIT(3) | BIT(4)) << 8; +// dprintf("70f=%x,719=%x\n", REG32(0xb8b1070f), REG32(0xb8b10719) ); + } +#endif + + RTL_W8(0x690, 0x2); // WoW + RTL_W8(0x302, 0x2); // sw L123 + RTL_W8(0x5, 0x0); // AFSM_PCIE + RTL_W16(PCIE_CTRL_REG, 0xff ); + +// RTL_W16(0x558, 0x040a); +// RTL_W16(0x100 , RTL_R16(0x100) | BIT(8)); // enable sw beacon + +#ifdef CONFIG_RTL_92C_SUPPORT + if (IS_TEST_CHIP(priv)) { + priv->pshare->rf_ft_var.power_save &= (~ L2_en); + priv->pshare->rf_ft_var.power_save &= (~ASPM_en); + } else +#endif + { + RTL_W8(0x08, RTL_R8(0x08) | BIT(3)); // WAKEPAN_EN +#ifdef CONFIG_RTL_92C_SUPPORT + if (IS_UMC_A_CUT_88C(priv)) + priv->pshare->rf_ft_var.power_save &= (~ASPM_en); +#endif + + } +#ifdef ASPM_ENABLE + ASPM_on_off(priv); +#endif + +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(1); +#endif + +} + + +int isPSConditionMatch(struct rtl8192cd_priv *priv) +{ + +// temporary disable Active ECO when 1 interfcae is disabled +#ifdef CONFIG_RTL_92D_DMDP + if ( (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) && + (!IS_DRV_OPEN(((struct rtl8192cd_priv *)if_priv[1 & (priv->pshare->wlandev_idx ^ 1)])))) + return 0; +#endif + + if (!IS_DRV_OPEN(priv)) + return 1; + + if ( (priv->assoc_num == 0) + && (priv->pshare->rf_ft_var.power_save & (L1_en | L2_en)) +#ifdef MBSSID + && (!priv->pmib->miscEntry.vap_enable) +#endif +#ifdef WDS + && (!priv->pmib->dot11WdsInfo.wdsEnabled) +#endif +#ifdef UNIVERSAL_REPEATER + && (!IS_DRV_OPEN(GET_VXD_PRIV(priv))) +#endif +#ifdef CLIENT_MODE + && !((OPMODE & WIFI_STATION_STATE) || (OPMODE & WIFI_ADHOC_STATE)) +#endif + ) + return 1; + else + return 0; + +} + +void PCIe_power_save_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + char force; + force = priv->ps_ctrl & 0x80; + priv->ps_ctrl &= 0x7f; + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) + return ; +#endif + + if (!IS_DRV_OPEN(priv)) + return; + + if (force == 0) { +#ifdef CONFIG_RTL_92D_DMDP + if (isPSConditionMatch((struct rtl8192cd_priv *)if_priv[0]) && isPSConditionMatch((struct rtl8192cd_priv *)if_priv[1])) +#else + if (isPSConditionMatch(priv)) +#endif + { + if (priv->pwr_state != L1 && priv->pwr_state != L2) { + if ((priv->offload_ctrl >> 7) && (priv->offload_ctrl & 1) == 0) { + if (priv->pshare->rf_ft_var.power_save & L2_en) + priv->ps_ctrl = 0x21; + else + priv->ps_ctrl = 0x11; +#ifdef CONFIG_RTL_92D_DMDP + if ((priv->pshare->wlandev_idx == 1) && + (!IS_DRV_OPEN(((struct rtl8192cd_priv *)if_priv[0]))) ) { + ((struct rtl8192cd_priv *)if_priv[0])->ps_ctrl = priv->ps_ctrl; + tasklet_schedule(&((struct rtl8192cd_priv *)if_priv[0])->pshare->ps_tasklet); + } else if ((priv->pshare->wlandev_idx == 0) && + ((!IS_DRV_OPEN(((struct rtl8192cd_priv *)if_priv[1]))) || (((struct rtl8192cd_priv *)if_priv[1])->offload_ctrl >> 7))) +#endif + tasklet_schedule(&priv->pshare->ps_tasklet); + } else { + priv->offload_ctrl = 1; + RTL_W16(CR , RTL_R16(CR) | ENSWBCN); // enable sw beacon + mod_timer(&priv->ps_timer, jiffies + RTL_SECONDS_TO_JIFFIES(1)); + return; + } + } + } else { + priv->offload_ctrl = 0; + } + + } else { + if (priv->pwr_state == L0) + tasklet_schedule(&priv->pshare->ps_tasklet); + } + mod_timer(&priv->ps_timer, jiffies + POWER_DOWN_T0); + +#ifdef ASPM_ENABLE + ASPM_on_off(priv); +#endif + +} + +void setBaseAddressRegister(void) +{ + int tmp32 = 0, status; + while (++tmp32 < 100) { + REG32(0xb8b00004) = 0x00100007; + REG32(0xb8b10004) = 0x00100007; + REG32(0xb8b10010) = 0x18c00001; + REG32(0xb8b10018) = 0x19000004; + status = (REG32(0xb8b10010) ^ 0x18c00001) | ( REG32(0xb8b10018) ^ 0x19000004); + if (!status) + break; + else { + printk("set BAR fail,%x\n", status); + printk("%x %x %x %x \n", + REG32(0xb8b00004) , REG32(0xb8b10004) , REG32(0xb8b10010), REG32(0xb8b10018) ); + } + } ; +} + +void PCIe_power_save_tasklet(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + char in_out, L1_L2; + unsigned int tmp32 = 0, status = 0, page = 0, ctr; +#ifdef CONFIG_RTL_92D_SUPPORT + unsigned int portnum = 0, i; +#endif +#ifndef SMP_SYNC + unsigned long flags; +#endif + + unsigned int saddr, haddr; +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + saddr = CFG_92D_SLOTS; + haddr = CFG_92D_SLOTH; + + portnum = RTL_USED_PCIE_SLOT; + } else +#endif + { + saddr = CFG_92C_SLOTS; + haddr = CFG_92C_SLOTH; + } + + priv->ps_ctrl &= 0x7f; + in_out = priv->ps_ctrl & 0xf; + L1_L2 = (priv->ps_ctrl >> 4) & 0x7; + +#if defined(CONFIG_RTL_92D_DMDP) + if ((in_out == PWR_STATE_IN) && (priv->pshare->wlandev_idx == 0) && (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY)) { + struct rtl8192cd_priv *priv1 = ((struct rtl8192cd_priv *)if_priv[1]); + priv1->ps_ctrl = priv->ps_ctrl; + PCIe_power_save_tasklet((unsigned long )priv1); + } +#endif + + DEBUG_INFO("%s, %s, L%d\n", __FUNCTION__, (in_out == PWR_STATE_IN ? "in" : "out") , L1_L2); + + if ( in_out == PWR_STATE_IN) { + SAVE_INT_AND_CLI(flags); + +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(priv->pshare->wlandev_idx); + + if (!IS_DRV_OPEN(priv)) { +#ifdef ASPM_ENABLE + if ( priv->pwr_state == ASPM_L0s_L1) { + REG32(haddr + 0x80) &= ~(0x3); + REG32(saddr + 0x80) &= ~(0x3); + } +#endif + RTL_W8(PCIE_CTRL_REG + 2, 0x2); // sw L123 + RTL_W16(PCIE_CTRL_REG, 0xff00 ); + REG32(saddr + 0x44) |= 0x8108; + + if (L1_L2 == L1) { + priv->pwr_state = L1; + } else { + RTL_W8(RSV_CTRL0, 0xe1); // reg lock, dis_prst + RTL_W8(RSV_CTRL0, 0xe1); + priv->pwr_state = L2; + } + RESTORE_INT(flags); + return; + } +#endif + +#ifdef ASPM_ENABLE + if ( priv->pwr_state == ASPM_L0s_L1) { + REG32(haddr + 0x80) &= ~(0x3); + REG32(saddr + 0x80) &= ~(0x3); + } +#endif + +// RTL_W8(0x286, 4); + RTL_W8(PCIE_CTRL_REG + 2, 0x2); // sw L123 + REG32(saddr + 0x44) |= 0x8108; // clear pme status + + RTL_W16(NQOS_SEQ, priv->pshare->phw->seq); + RTL_W8(HWSEQ_CTRL, 0x7f); // mac seq + + ctr = 3000; + do { + delay_us(100); + if (!RTL_R8(PCIE_CTRL_REG)) { + RTL_W8(PCIE_CTRL_REG + 1, 0xfe ); + break; + } + } while (--ctr); + if (!ctr) { + status = 1; + } + ctr = 3000; + do { + delay_us(100); + if ( ((RTL_R32(0x200) ^ RTL_R32(0x204)) == 0) && + (((RTL_R32(VOQ_INFO) | RTL_R32(VIQ_INFO) | RTL_R32(BEQ_INFO) | RTL_R32(BKQ_INFO) + | RTL_R32(MGQ_INFO) | RTL_R32(HIQ_INFO)) & 0xffff00) == 0) + ) { + break; + } + } while (--ctr); + if (!ctr) { + status = 1; + } + RTL_W8(TXPAUSE, 0x2f); + delay_ms(1); + +#ifdef PCIE_L2_ENABLE + if (L1_L2 == L2) { + int tx_head, tx_tail, q_num; + struct tx_desc *phdesc, *pdesc; + for (q_num = MGNT_QUEUE; q_num <= HIGH_QUEUE; q_num++) { + tx_head = get_txhead(GET_HW(priv), q_num); + tx_tail = get_txtail(GET_HW(priv), q_num); + phdesc = get_txdesc(GET_HW(priv), q_num); + while (tx_tail != tx_head) { + pdesc = phdesc + (tx_tail); + pdesc->Dword0 &= set_desc(~TX_OWN); + tx_tail = (tx_tail + 1) % CURRENT_NUM_TX_DESC; + } + } +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + rtl8192cd_rx_isr(priv); + } +#endif + if ((get_rf_mimo_mode(priv) == MIMO_2T2R) && (priv->pshare->rf_ft_var.power_save & _1x1_en)) + switch_to_1x1(priv, PWR_STATE_IN); + + page = ((priv->offload_ctrl) >> 7) & 0xff; + RTL_W16(RCR, RTL_R16(RCR) & ~(BIT(11) | BIT(12) | BIT(13))); + RTL_W16(RXFLTMAP0, RTL_R16(RXFLTMAP0) | BIT(11) | BIT(4)); + + if (priv->pshare->rf_ft_var.power_save & offload_en) { + + if (GET_CHIP_VER(priv) != VERSION_8192D) + status |= signin_h2c_cmd(priv, _RSVDPAGE_CMD_ | page << 8, 0); + else + status |= signin_h2c_cmd(priv, _RSVDPAGE_CMD_ | BIT(7) | (page << 8), (page << 8) | (page) ); + + status |= signin_h2c_cmd(priv, _AP_OFFLOAD_CMD_ | (1 << 8) | (HIDDEN_AP << 16) | ((GET_MIB(priv))->dot11OperationEntry.deny_any) << 24, 0 ); +#if defined(__LINUX_2_6__) + RTL_W32(HIMR, 0); +#endif + DEBUG_INFO("%s, LINE:%d, h2c %x, %x, %x\n", __FUNCTION__, __LINE__, + (_RSVDPAGE_CMD_ | page << 8), (_RSVDPAGE_CMD_ | BIT(7) | (page << 8), (page << 8) | (page)), + (_AP_OFFLOAD_CMD_ | (1 << 8) | (HIDDEN_AP << 16) | ((GET_MIB(priv))->dot11OperationEntry.deny_any) << 24) + ); + ctr = 3000; + do { + delay_us(10); + page = RTL_R8(RXPKT_NUM + 2) & 6 ; + if (page == 6) + break; + } while (--ctr); + + if (status || (page != 6)) { + DEBUG_INFO("signin_h2c_cmd fail(ap offload), 286=%x\n", page); +#if defined(__LINUX_2_6__) + RTL_W32(HIMR, priv->pshare->InterruptMask); +#endif + if ((get_rf_mimo_mode(priv) == MIMO_2T2R) && (priv->pshare->rf_ft_var.power_save & _1x1_en)) + switch_to_1x1(priv, PWR_STATE_OUT); + RTL_W8(HWSEQ_CTRL, 0x0); // mac seq disable + RTL_W8(RXPKT_NUM + 2, 0); + + RTL_W16(RCR, RTL_R16(RCR) | (BIT(11) | BIT(13))); + RTL_W16(RXFLTMAP0, RTL_R16(RXFLTMAP0) & ~(BIT(11) | BIT(4))); + + RTL_W8(PCIE_CTRL_REG + 1, 0x00); // enable DMA + RTL_W8(TXPAUSE, 0x0); + + priv->offload_ctrl = 0; + RESTORE_INT(flags); + return; + } + } + RTL_W16(CR , RTL_R16(CR) | ENSWBCN); // enable sw beacon + + if ( L1_L2 == L1) { + +#ifdef CONFIG_RTL_92D_DMDP + if ((priv->pshare->wlandev_idx) && (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + && IS_DRV_OPEN(((struct rtl8192cd_priv *)if_priv[0]))) { + RESTORE_INT(flags); + return ; + } + Sw_PCIE_Func2(1); + tmp32 = REG32(saddr + 0x44) & ( ~(3)); + REG32(saddr + 0x44) = tmp32 | (3); //D3 + + if (!priv->pshare->wlandev_idx) + ((struct rtl8192cd_priv *)if_priv[1])->pwr_state = L1; + Sw_PCIE_Func2(0); + delay_ms(1); +#endif + priv->pwr_state = L1; + + tmp32 = REG32(saddr + 0x44) & ( ~(3)); //D0 + REG32(saddr + 0x44) = tmp32 | (3); //D3 + //HostPCIe_SetPhyMdioWrite(0xd, 0x15a6); + printk("D3 hot -> L1\n"); + delay_ms(1); +#if 0 //saving more power + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0708); +#endif + } + RESTORE_INT(flags); + + +#ifdef PCIE_L2_ENABLE + if ( L1_L2 == L2) { +#if 0 //saving more power leave L1 write + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0f0f); +#endif + RTL_W8(RSV_CTRL0, 0xe1); // reg lock, dis_prst + RTL_W8(RSV_CTRL0, 0xe1); + priv->pwr_state = L2; +#ifdef CONFIG_RTL_92D_DMDP + if (!priv->pshare->wlandev_idx) +#endif + REG32(haddr + 0x1008) |= (0x200); + printk("PME turn off -> L2\n"); + } +#endif +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) + REG32(0xb8003000) |= BIT(16); // GIMR +#else + REG32(0xb8003000) |= BIT(9); // GIMR +#endif + } else if (in_out == PWR_STATE_OUT) { +#ifdef PCIE_L2_ENABLE + if ( L1_L2 == L2) { + +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(priv->pshare->wlandev_idx); + if (!priv->pshare->wlandev_idx ) +#endif + PCIE_reset_procedure3(priv); + setBaseAddressRegister(); + + SAVE_INT_AND_CLI(flags); + priv->pwr_state = L0; +#ifdef CONFIG_RTL_92D_DMDP + ((struct rtl8192cd_priv *)if_priv[1])->pwr_state = L0; +#endif + RTL_W8(RSV_CTRL0, 0x0); + tmp32 = 0; + while (1) { + if ( !(RTL_R8(SPS0_CTRL) & BIT(3)) || (++tmp32 > 20) ) { + RTL_W8(SPS0_CTRL, 0x2b); + break; + } + } + DEBUG_INFO("SPS0_CTRL=%d !!\n", RTL_R8(SPS0_CTRL)); + } else +#endif + { + + SAVE_INT_AND_CLI(flags); + if ( priv->pwr_state == L1) { + +#ifdef CONFIG_RTL_92D_DMDP + for (i = 0; i < 2; i++) { + Sw_PCIE_Func2(i); +#endif + ctr = 3000; +#if 0 //saving more power, leave L1 write + HostPCIe_SetPhyMdioWrite(portnum, 0xf, 0x0f0f); +#endif + tmp32 = REG32(saddr + 0x44) & ( ~(3)); //D0 + do { + REG32(saddr + 0x44) = tmp32 | (0); //D0 + delay_us(1); + REG32(saddr + 0x44) = tmp32 | (0); //D0 + status = REG32(haddr + 0x728) & 0x1f; + if (status == 0x11) + break; + } while (--ctr); + + if (status != 0x11) + panic_printk("change to L0 fail!!!, status=%x, MAC0\n", status); + else +#ifdef CONFIG_RTL_92D_DMDP + ((struct rtl8192cd_priv *)if_priv[i])->pwr_state = L0; + } +#else + priv->pwr_state = L0; +#endif + } + } + + +#ifdef CONFIG_RTL_92D_DMDP + if ((priv->pshare->wlandev_idx == 0) && (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) && !IS_DRV_OPEN(priv) ) { + goto OEPN_MAC1; + } +#endif + + if (priv->pshare->rf_ft_var.power_save & offload_en) { + +#if defined(__LINUX_2_6__) + RTL_W32(HIMR, priv->pshare->InterruptMask); +#endif + signin_h2c_cmd(priv, _AP_OFFLOAD_CMD_ , 0 ); // offload + delay_ms(2); + } + + if ((get_rf_mimo_mode(priv) == MIMO_2T2R) && (priv->pshare->rf_ft_var.power_save & _1x1_en)) + switch_to_1x1(priv, PWR_STATE_OUT); +#ifdef PCIE_L2_ENABLE + if ( L1_L2 == L2) { + priv->pshare->phw->cur_rx = 0; +#ifdef DELAY_REFILL_RX_BUF + priv->pshare->phw->cur_rx_refill = 0; +#endif + memset(&(priv->pshare->phw->txhead0), 0, sizeof(int) * 12); + RTL_W32(BCNQ_DESA, priv->pshare->phw->tx_ringB_addr); + RTL_W32(MGQ_DESA, priv->pshare->phw->tx_ring0_addr); + RTL_W32(VOQ_DESA, priv->pshare->phw->tx_ring4_addr); + RTL_W32(VIQ_DESA, priv->pshare->phw->tx_ring3_addr); + RTL_W32(BEQ_DESA, priv->pshare->phw->tx_ring2_addr); + RTL_W32(BKQ_DESA, priv->pshare->phw->tx_ring1_addr); + RTL_W32(HQ_DESA, priv->pshare->phw->tx_ring5_addr); + RTL_W32(RX_DESA, priv->pshare->phw->ring_dma_addr); + } +#endif + // wait until FW stop parsing packet + ctr = 1000; + do { + if (!(RTL_R8(FWIMR) & FWIMR_RXDONE)) + break; + delay_us(200); + } while (--ctr) ; + if (!ctr) + DEBUG_ERR("stop offload fail\n"); + + RTL_W8(HWSEQ_CTRL, 0x0); // mac seq disable + RTL_W8(RXPKT_NUM + 2, 0); // RW_RELEASE_ENABLE + RTL_W16(RCR, RTL_R16(RCR) | (BIT(11) | BIT(13))); + RTL_W16(RXFLTMAP0, RTL_R16(RXFLTMAP0) & ~(BIT(11) | BIT(4))); + RTL_W8(PCIE_CTRL_REG + 1, 0x00); // enable DMA + RTL_W8(PCIE_CTRL_REG + 2, 0x3); // sw L123 + RTL_W8(TXPAUSE, 0x0); + RTL_W16(CR , RTL_R16(CR) & ~ENSWBCN); + +#ifdef CONFIG_RTL_92D_DMDP + if ((priv->pshare->wlandev_idx == 0) && (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY)) { + struct rtl8192cd_priv *priv1; +OEPN_MAC1: + priv1 = ((struct rtl8192cd_priv *)if_priv[1]); + if (IS_DRV_OPEN(priv1) ) { + priv1->ps_ctrl = priv->ps_ctrl; + PCIe_power_save_tasklet((unsigned long )priv1); + } + } +#endif + +#if defined(RX_TASKLET) + if (IS_DRV_OPEN(priv)) { + tasklet_hi_schedule(&priv->pshare->rx_tasklet); + } +#endif + +#ifdef ASPM_ENABLE + ASPM_on_off(priv); +#endif + RESTORE_INT(flags); + } +} + + +void PCIeWakeUp(struct rtl8192cd_priv *priv, unsigned int expTime) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + SAVE_INT_AND_CLI(flags); + + if ( (priv->pwr_state == L1) || (priv->pwr_state == L2)) { + + if (timer_pending(&priv->ps_timer)) + del_timer_sync(&priv->ps_timer); + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pshare->wlandev_idx == 1) { + struct rtl8192cd_priv *priv0 = ((struct rtl8192cd_priv *)if_priv[0]); + PCIeWakeUp(priv0, expTime); + } else +#endif + { + priv->ps_ctrl = 0x02 | (priv->pwr_state << 4); + PCIe_power_save_tasklet((unsigned long)priv); + } + + mod_timer(&priv->ps_timer, jiffies + expTime); + priv->offload_ctrl = 0; +#ifdef CONFIG_RTL_92D_DMDP + ((struct rtl8192cd_priv *)if_priv[priv->pshare->wlandev_idx ^ 1])->offload_ctrl = 0; +#endif + } + RESTORE_INT(flags); +} + +#ifdef __LINUX_2_6__ +irqreturn_t gpio_wakeup_isr(int irq, void *dev_instance) +#else +void gpio_wakeup_isr(int irq, void *dev_instance, struct pt_regs *regs) +#endif +{ + struct net_device *dev = NULL; + struct rtl8192cd_priv *priv = NULL; + + unsigned int saddr; + + dev = (struct net_device *)dev_instance; + priv = (struct rtl8192cd_priv *)dev->priv; + + if (GET_CHIP_VER(priv) == VERSION_8192D) { + saddr = CFG_92D_SLOTS; + } else { + saddr = CFG_92C_SLOTS; + } + +#ifdef CONFIG_RTL_92D_DMDP + Sw_PCIE_Func2(priv->pshare->wlandev_idx); +#endif + + DEBUG_INFO("%s, PABCD_ISR=%x\t", dev->name, REG32(PABCD_ISR)); + +#if defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) + +#if defined(CONFIG_RTL_ULINKER) + REG32(PABCD_ISR) = BIT(13) ; // clear int status +#else +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_8197D) + if (GET_CHIP_VER(priv) == VERSION_8192D) + REG32(PABCD_ISR) = BIT(15) ; + else +#endif + REG32(PABCD_ISR) = BIT(4) ; // clear int status +#endif /* #if defined(CONFIG_RTL_ULINKER) */ + +#elif defined(CONFIG_RTL_8198) +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + REG32(PABCD_ISR) = BIT(17) ; + else +#endif + REG32(PABCD_ISR) = BIT(20) ; // clear int status +#else + REG32(PABCD_ISR) = BIT(15) ; // clear int status +#endif + + DEBUG_INFO(", PABCD_ISR=%x,0xb8100044=%x\n", REG32(PABCD_ISR), REG32(saddr + 0x44)); + +#ifdef GPIO_WAKEPIN +#ifdef PCIE_POWER_SAVING_DEBUG + priv->firstPkt = 1; +#endif + if (timer_pending(&priv->ps_timer)) + del_timer_sync(&priv->ps_timer); + + if ( priv->pwr_state == L1 || priv->pwr_state == L2) { + priv->ps_ctrl = 0x02 | (priv->pwr_state << 4); + PCIe_power_save_tasklet((unsigned long)priv); + } + + priv->offload_ctrl = 0; + mod_timer(&priv->ps_timer, jiffies + (POWER_DOWN_T0)); + +#endif +#ifdef __LINUX_2_6__ + return IRQ_HANDLED; +#endif +} + + +void radio_off(struct rtl8192cd_priv *priv) +{ +#if 0 + extern void HostPCIe_Close(void); + printk("Radio Off======>\n"); + HostPCIe_Close(); +#endif +} +#endif + + +#if defined(RF_MIMO_SWITCH) || defined(PCIE_POWER_SAVING) || defined(RF_MIMO_PS) +int MIMO_mode_switch(struct rtl8192cd_priv *priv, int mode) +{ + if(get_rf_mimo_mode(priv) != MIMO_2T2R) + return 0; +#ifdef MP_TEST + if (((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) + return 0; +#endif + if ((mode == MIMO_1T1R) && (priv->pshare->rf_status!= MIMO_1T1R)) { + + //panic_printk("switch to 1x1\n"); +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + Assert_BB_Reset(priv); + priv->pshare->rf_phy_bb_backup[0] = RTL_R32(0x808); + priv->pshare->rf_phy_bb_backup[1] = RTL_R32(0x80c); + priv->pshare->rf_phy_bb_backup[2] = RTL_R32(0xa04); + priv->pshare->rf_phy_bb_backup[3] = RTL_R32(0x8bc); + priv->pshare->rf_phy_bb_backup[4] = RTL_R32(0xe00); + priv->pshare->rf_phy_bb_backup[5] = RTL_R32(0xe90); + priv->pshare->rf_phy_bb_backup[6] = RTL_R32(0xe60); + priv->pshare->rf_phy_bb_backup[7] = RTL_R32(0xe64); + RTL_W8(0x808, 0x11); + RTL_W16(0x80c, 0x1111); + RTL_W8(0xa07, (RTL_R8(0xa07) & 0xf3)); // [3:2] = 2'b 00 + RTL_W32(0x8bc, (RTL_R32(0x8bc) & 0x3FFFFF9F) | BIT(30) ); + RTL_W8(0xe00, (RTL_R8(0xe00) & 0xf0) | 0x04 ); + RTL_W8(0xe90, 0); + RTL_W32(0xe60, 0); + RTL_W32(0xe64, 0); + Release_BB_Reset(priv); + } +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv) == VERSION_8192E) { + priv->pshare->rf_phy_bb_backup[0] = RTL_R32(0xd00); + priv->pshare->rf_phy_bb_backup[23] = RTL_R32(0xe68); + priv->pshare->rf_phy_bb_backup[24] = RTL_R32(0x82c); + priv->pshare->rf_phy_bb_backup[25] = RTL_R32(0xa00); + } +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8192D)) { + priv->pshare->rf_phy_bb_backup[0] = RTL_R32(0x844); + priv->pshare->rf_phy_bb_backup[20] = RTL_R32(0x804); + priv->pshare->rf_phy_bb_backup[21] = RTL_R32(0x88c); + } +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8192D) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + priv->pshare->rf_phy_bb_backup[1] = RTL_R32(0x85c); + priv->pshare->rf_phy_bb_backup[2] = RTL_R32(0xe6c); + priv->pshare->rf_phy_bb_backup[3] = RTL_R32(0xe70); + priv->pshare->rf_phy_bb_backup[4] = RTL_R32(0xe74); + priv->pshare->rf_phy_bb_backup[5] = RTL_R32(0xe78); + priv->pshare->rf_phy_bb_backup[6] = RTL_R32(0xe7c); + priv->pshare->rf_phy_bb_backup[7] = RTL_R32(0xe80); + priv->pshare->rf_phy_bb_backup[8] = RTL_R32(0xe84); + priv->pshare->rf_phy_bb_backup[9] = RTL_R32(0xe88); + priv->pshare->rf_phy_bb_backup[10] = RTL_R32(0xe8c); + priv->pshare->rf_phy_bb_backup[11] = RTL_R32(0xed0); + priv->pshare->rf_phy_bb_backup[12] = RTL_R32(0xed4); + priv->pshare->rf_phy_bb_backup[13] = RTL_R32(0xed8); + priv->pshare->rf_phy_bb_backup[14] = RTL_R32(0xedc); + priv->pshare->rf_phy_bb_backup[15] = RTL_R32(0xee0); + priv->pshare->rf_phy_bb_backup[16] = RTL_R32(0xeec); + priv->pshare->rf_phy_bb_backup[17] = RTL_R32(0xc04); + priv->pshare->rf_phy_bb_backup[18] = RTL_R32(0xd04); + priv->pshare->rf_phy_bb_backup[19] = RTL_R32(0x90c); + priv->pshare->rf_phy_bb_backup[22] = RTL_R32(0xa04); + + } +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + unsigned int mask = 0xB4FFFFFF, path = 0x11; + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { + mask = 0xDB3FFFFF; + path = 0x22; + RTL_W8(0xa07, 0x45); + } + PHY_SetBBReg(priv, 0x85c, bMaskDWord, priv->pshare->rf_phy_bb_backup[1] & mask); + PHY_SetBBReg(priv, 0xe6c, bMaskDWord, priv->pshare->rf_phy_bb_backup[2] & mask); + PHY_SetBBReg(priv, 0xe70, bMaskDWord, priv->pshare->rf_phy_bb_backup[3] & mask); + PHY_SetBBReg(priv, 0xe74, bMaskDWord, priv->pshare->rf_phy_bb_backup[4] & mask); + PHY_SetBBReg(priv, 0xe78, bMaskDWord, priv->pshare->rf_phy_bb_backup[5] & mask); + PHY_SetBBReg(priv, 0xe7c, bMaskDWord, priv->pshare->rf_phy_bb_backup[6] & mask); + PHY_SetBBReg(priv, 0xe80, bMaskDWord, priv->pshare->rf_phy_bb_backup[7] & mask); + PHY_SetBBReg(priv, 0xe84, bMaskDWord, priv->pshare->rf_phy_bb_backup[8] & mask); + PHY_SetBBReg(priv, 0xe88, bMaskDWord, priv->pshare->rf_phy_bb_backup[9] & mask); + PHY_SetBBReg(priv, 0xe8c, bMaskDWord, priv->pshare->rf_phy_bb_backup[10] & mask); + PHY_SetBBReg(priv, 0xed0, bMaskDWord, priv->pshare->rf_phy_bb_backup[11] & mask); + PHY_SetBBReg(priv, 0xed4, bMaskDWord, priv->pshare->rf_phy_bb_backup[12] & mask); + PHY_SetBBReg(priv, 0xed8, bMaskDWord, priv->pshare->rf_phy_bb_backup[13] & mask); + PHY_SetBBReg(priv, 0xedc, bMaskDWord, priv->pshare->rf_phy_bb_backup[14] & mask); + PHY_SetBBReg(priv, 0xee0, bMaskDWord, priv->pshare->rf_phy_bb_backup[15] & mask); + PHY_SetBBReg(priv, 0xeec, bMaskDWord, priv->pshare->rf_phy_bb_backup[16] & mask); + PHY_SetBBReg(priv, 0xc04, 0x000000ff, path); + PHY_SetBBReg(priv, 0xd04, 0x0000000f, path & 0x01); + PHY_SetBBReg(priv, 0x90c, 0x000000ff, path); + PHY_SetBBReg(priv, 0x90c, 0x0ff00000, path); + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192C) { + PHY_SetBBReg(priv, 0x88c, 0x00c00000 , 0x3); + PHY_SetBBReg(priv, 0x844, bMaskDWord, 0x00010000); // standby + PHY_SetBBReg(priv, 0x85c, bMaskDWord, 0x00db25a4); + PHY_SetBBReg(priv, 0xe6c, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xe70, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xe74, bMaskDWord, 0x041b25a4); + PHY_SetBBReg(priv, 0xe78, bMaskDWord, 0x041b25a4); + PHY_SetBBReg(priv, 0xe7c, bMaskDWord, 0x041b25a4); + PHY_SetBBReg(priv, 0xe80, bMaskDWord, 0x041b25a4); + PHY_SetBBReg(priv, 0xe84, bMaskDWord, 0x63db25a4); + PHY_SetBBReg(priv, 0xe88, bMaskDWord, 0x041b25a4); + PHY_SetBBReg(priv, 0xe8c, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xed0, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xed4, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xed8, bMaskDWord, 0x20db25a4); + PHY_SetBBReg(priv, 0xedc, bMaskDWord, 0x001b25a4); + PHY_SetBBReg(priv, 0xee0, bMaskDWord, 0x001b25a4); + PHY_SetBBReg(priv, 0xeec, bMaskDWord, 0x24db25a4); + PHY_SetBBReg(priv, 0xc04, 0x000000ff , 0x11); + PHY_SetBBReg(priv, 0xd04, 0x0000000f , 0x1); + PHY_SetBBReg(priv, 0x90c, 0x000000ff , 0x11); + PHY_SetBBReg(priv, 0x90c, 0x0ff00000 , 0x11); + PHY_SetBBReg(priv, 0x804, 0x000000f , 0x1); + } +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + unsigned int mask = 0xB4FFFFFF; + int pathB=0; + if((RTL_R8(0xa07) & 0x80) == 0) + pathB=1; + PHY_SetBBReg(priv, 0x85c, bMaskDWord, priv->pshare->rf_phy_bb_backup[1] & mask); + PHY_SetBBReg(priv, 0xe6c, bMaskDWord, priv->pshare->rf_phy_bb_backup[2] & mask); + PHY_SetBBReg(priv, 0xe70, bMaskDWord, priv->pshare->rf_phy_bb_backup[3] & mask); + PHY_SetBBReg(priv, 0xe74, bMaskDWord, priv->pshare->rf_phy_bb_backup[4] & mask); + PHY_SetBBReg(priv, 0xe78, bMaskDWord, priv->pshare->rf_phy_bb_backup[5] & mask); + PHY_SetBBReg(priv, 0xe7c, bMaskDWord, priv->pshare->rf_phy_bb_backup[6] & mask); + PHY_SetBBReg(priv, 0xe80, bMaskDWord, priv->pshare->rf_phy_bb_backup[7] & mask); + PHY_SetBBReg(priv, 0xe84, bMaskDWord, priv->pshare->rf_phy_bb_backup[8] & mask); + PHY_SetBBReg(priv, 0xe88, bMaskDWord, priv->pshare->rf_phy_bb_backup[9] & mask); + PHY_SetBBReg(priv, 0xe8c, bMaskDWord, priv->pshare->rf_phy_bb_backup[10] & mask); + PHY_SetBBReg(priv, 0xed0, bMaskDWord, priv->pshare->rf_phy_bb_backup[11] & mask); + PHY_SetBBReg(priv, 0xed4, bMaskDWord, priv->pshare->rf_phy_bb_backup[12] & mask); + PHY_SetBBReg(priv, 0xed8, bMaskDWord, priv->pshare->rf_phy_bb_backup[13] & mask); + PHY_SetBBReg(priv, 0xedc, bMaskDWord, priv->pshare->rf_phy_bb_backup[14] & mask); + PHY_SetBBReg(priv, 0xee0, bMaskDWord, priv->pshare->rf_phy_bb_backup[15] & mask); + PHY_SetBBReg(priv, 0xeec, bMaskDWord, priv->pshare->rf_phy_bb_backup[16] & mask); + PHY_SetBBReg(priv, 0xe68, bMaskDWord, priv->pshare->rf_phy_bb_backup[23] & mask); + + PHY_SetBBReg(priv, 0xc04, 0x000000ff , 0x11); + PHY_SetBBReg(priv, 0xd04, 0x0000000f , 0x1); + PHY_SetBBReg(priv, 0x90c, 0x000000ff , 0x11); + PHY_SetBBReg(priv, 0x90c, 0x0ff00000 , 0x11); + PHY_SetBBReg(priv, 0xd00, 0x00180000, 0); + PHY_SetBBReg(priv, 0x82c, (BIT22 | BIT21| BIT20), 1); + PHY_SetBBReg(priv, 0xa00, BIT7, 0); // ant div disable + + if(pathB) { + RTL_W8(0xa07, 0x40); + PHY_SetBBReg(priv, 0xe74, BIT27, 1); + + } else { + RTL_W8(0xa07, 0x80); + } + + } +#endif + priv->pshare->rf_status= MIMO_1T1R; + return 1; + + } else if ((mode == MIMO_2T2R) && (priv->pshare->rf_status == MIMO_1T1R)) { + //panic_printk("switch to 2x2\n"); +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + Assert_BB_Reset(priv); + RTL_W32(0x808, priv->pshare->rf_phy_bb_backup[0]); + RTL_W32(0x80c, priv->pshare->rf_phy_bb_backup[1]); + RTL_W32(0xa04, priv->pshare->rf_phy_bb_backup[2]); + RTL_W32(0x8bc, priv->pshare->rf_phy_bb_backup[3]); + RTL_W32(0xe00, priv->pshare->rf_phy_bb_backup[4]); + RTL_W32(0xe90, priv->pshare->rf_phy_bb_backup[5]); + RTL_W32(0xe60, priv->pshare->rf_phy_bb_backup[6]); + RTL_W32(0xe64, priv->pshare->rf_phy_bb_backup[7]); + Release_BB_Reset(priv); + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192C) { + PHY_SetBBReg(priv, 0x88c, bMaskDWord, priv->pshare->rf_phy_bb_backup[21]); + PHY_SetBBReg(priv, 0x844, bMaskDWord, priv->pshare->rf_phy_bb_backup[0]); + } +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv) == VERSION_8192D) || (GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8192E)) { + PHY_SetBBReg(priv, 0x85c, bMaskDWord, priv->pshare->rf_phy_bb_backup[1]); + PHY_SetBBReg(priv, 0xe6c, bMaskDWord, priv->pshare->rf_phy_bb_backup[2]); + PHY_SetBBReg(priv, 0xe70, bMaskDWord, priv->pshare->rf_phy_bb_backup[3]); + PHY_SetBBReg(priv, 0xe74, bMaskDWord, priv->pshare->rf_phy_bb_backup[4]); + PHY_SetBBReg(priv, 0xe78, bMaskDWord, priv->pshare->rf_phy_bb_backup[5]); + PHY_SetBBReg(priv, 0xe7c, bMaskDWord, priv->pshare->rf_phy_bb_backup[6]); + PHY_SetBBReg(priv, 0xe80, bMaskDWord, priv->pshare->rf_phy_bb_backup[7]); + PHY_SetBBReg(priv, 0xe84, bMaskDWord, priv->pshare->rf_phy_bb_backup[8]); + PHY_SetBBReg(priv, 0xe88, bMaskDWord, priv->pshare->rf_phy_bb_backup[9]); + PHY_SetBBReg(priv, 0xe8c, bMaskDWord, priv->pshare->rf_phy_bb_backup[10]); + PHY_SetBBReg(priv, 0xed0, bMaskDWord, priv->pshare->rf_phy_bb_backup[11]); + PHY_SetBBReg(priv, 0xed4, bMaskDWord, priv->pshare->rf_phy_bb_backup[12]); + PHY_SetBBReg(priv, 0xed8, bMaskDWord, priv->pshare->rf_phy_bb_backup[13]); + PHY_SetBBReg(priv, 0xedc, bMaskDWord, priv->pshare->rf_phy_bb_backup[14]); + PHY_SetBBReg(priv, 0xee0, bMaskDWord, priv->pshare->rf_phy_bb_backup[15]); + PHY_SetBBReg(priv, 0xeec, bMaskDWord, priv->pshare->rf_phy_bb_backup[16]); + PHY_SetBBReg(priv, 0xc04, bMaskDWord , priv->pshare->rf_phy_bb_backup[17]); + PHY_SetBBReg(priv, 0xd04, bMaskDWord , priv->pshare->rf_phy_bb_backup[18]); + PHY_SetBBReg(priv, 0x90c, bMaskDWord , priv->pshare->rf_phy_bb_backup[19]); + PHY_SetBBReg(priv, 0xa04, bMaskDWord , priv->pshare->rf_phy_bb_backup[22]); + + } +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv) == VERSION_8192E) { + PHY_SetBBReg(priv, 0xd00, bMaskDWord, priv->pshare->rf_phy_bb_backup[0]); + PHY_SetBBReg(priv, 0xe68, bMaskDWord , priv->pshare->rf_phy_bb_backup[23]); + PHY_SetBBReg(priv, 0x82c, bMaskDWord , priv->pshare->rf_phy_bb_backup[24]); + PHY_SetBBReg(priv, 0xa00, bMaskDWord , priv->pshare->rf_phy_bb_backup[25]); + } +#endif +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192C) + PHY_SetBBReg(priv, 0x804, bMaskDWord , priv->pshare->rf_phy_bb_backup[20]); +#endif + priv->pshare->rf_status = MIMO_2T2R; + return 1; + + } + return 0; +} +#endif + +#ifdef EN_EFUSE +#define VOLTAGE_V25 0x03 + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) +#define MAX_2G_CHNLGRP 6 +#define MAX_5G_CHNLGRP 14 + +struct channel_group { + unsigned char low; + unsigned char high; +}; + +static struct channel_group chnl_pwrlvlgp_2G[] = { + //decrease 1 for array index + {0, 1}, + {2, 4}, + {5, 7}, + {8, 10}, + {11, 12}, + {13, 13} +}; + +static struct channel_group chnl_pwrlvlgp_5G[] = { + //decrease 1 for array index + {35, 39}, + {43, 47}, + {51, 55}, + {59, 63}, + {99, 103}, + {107, 111}, + {115, 119}, + {123, 127}, + {131, 135}, + {139, 143}, + {148, 152}, + {156, 160}, + {164, 168}, + {172, 176} +}; + +int find_2gchnlgroup(int chnl) +{ + int index = 0; + + for (index = 0; index < MAX_2G_CHNLGRP; index++) { + if ( (chnl >= chnl_pwrlvlgp_2G[index].low) + && (chnl <= chnl_pwrlvlgp_2G[index].high) ) + return index; + } + + return -1; +} + +#ifdef CONFIG_RTL_8812_SUPPORT +int find_5gchnlgroup(int chnl) +{ + int index = 0; + + for (index = 0; index < MAX_5G_CHNLGRP; index++) { + if ( (chnl >= chnl_pwrlvlgp_5G[index].low) + && (chnl <= chnl_pwrlvlgp_5G[index].high) ) + return index; + } + + return -1; +} + +void read_efusemap_2gtxpwrdiff(struct rtl8192cd_priv *priv, unsigned int chnl) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + if (GET_CHIP_VER(priv) == VERSION_8812E) { + priv->pmib->dot11RFEntry.pwrdiff_20BW1S_OFDM1T_A[chnl] + = hwinfo[EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_A[chnl] + = hwinfo[EEPROM_2G_HT402S_TxPowerDiff + PATHA_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_OFDM2T_CCK2T_A[chnl] + = hwinfo[EEPROM_2G_OFDM2T_TxPowerDiff + PATHA_OFFSET]; + + priv->pmib->dot11RFEntry.pwrdiff_20BW1S_OFDM1T_B[chnl] + = hwinfo[EEPROM_2G_HT201S_TxPowerDiff + PATHB_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_B[chnl] + = hwinfo[EEPROM_2G_HT402S_TxPowerDiff + PATHB_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_OFDM2T_CCK2T_B[chnl] + = hwinfo[EEPROM_2G_OFDM2T_TxPowerDiff + PATHB_OFFSET]; + } +} + +void read_efusemap_5gtxpwrdiff(struct rtl8192cd_priv *priv, unsigned int chnl) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + if (GET_CHIP_VER(priv) == VERSION_8812E) { + priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_A[chnl] + = hwinfo[EEPROM_5G_HT201S_TxPowerDiff + PATHA_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_A[chnl] + = hwinfo[EEPROM_5G_HT402S_TxPowerDiff + PATHA_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_A[chnl] + = hwinfo[EEPROM_5G_HT801S_TxPowerDiff + PATHA_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_A[chnl] + = hwinfo[EEPROM_5G_HT802S_TxPowerDiff + PATHA_OFFSET]; + + priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_B[chnl] + = hwinfo[EEPROM_5G_HT201S_TxPowerDiff + PATHB_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_B[chnl] + = hwinfo[EEPROM_5G_HT402S_TxPowerDiff + PATHB_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_B[chnl] + = hwinfo[EEPROM_5G_HT801S_TxPowerDiff + PATHB_OFFSET]; + priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_B[chnl] + = hwinfo[EEPROM_5G_HT802S_TxPowerDiff + PATHB_OFFSET]; + } +} + +int clear_5g_pwr_params(struct rtl8192cd_priv *priv, int index) +{ + if (GET_CHIP_VER(priv) == VERSION_8812E) { + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[index] = 0; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[index] = 0; + priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_A[index] = 0; + priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_A[index] = 0; + priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_A[index] = 0; + priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_A[index] = 0; + + priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_B[index] = 0; + priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_B[index] = 0; + priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_B[index] = 0; + priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_B[index] = 0; + } + + return 0; +} +#endif // CONFIG_RTL_8812_SUPPORT +#endif // CONFIG_RTL_8812_SUPPORT || CONFIG_WLAN_HAL_8192EE + +/*----------------------------------------------------------------------------- + * Function: efuse_PowerSwitch + * + * Overview: When we want to enable write operation, we should change to + * pwr on state. When we stop write, we should switch to 500k mode + * and disable LDO 2.5V. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/17/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +static void efuse_PowerSwitch(struct rtl8192cd_priv *priv, unsigned char bWrite, unsigned char PwrState) +{ + unsigned char tempval; + short tmpV16; + if (PwrState == TRUE) { +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + tempval = 0x69; + RTL_W8(REG_PG_PASSWD_8812, tempval); + } +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + RTL_W8(REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + RTL_W8(REG_EFUSE_ACCESS, EFUSE_ACCESS_ON_8192E); +#endif + + // 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) != VERSION_8812E) +#endif + + { + tmpV16 = RTL_R16(SYS_ISO_CTRL); + if (!(tmpV16 & PWC_EV12V)) { + RTL_W8(0x1c, RTL_R8(0x1c)& ~BIT(1)); + tmpV16 |= PWC_EV12V; + RTL_W16(SYS_ISO_CTRL, tmpV16); + RTL_W8(0x1c, RTL_R8(0x1c)|0x02); + } + } + + // Reset: 0x0000h[28], default valid + tmpV16 = RTL_R16(REG_SYS_FUNC_EN); + if (!(tmpV16 & FEN_ELDR)) { + RTL_W8(0x1c, RTL_R8(0x1c)|0x02); + tmpV16 |= FEN_ELDR; + RTL_W16(REG_SYS_FUNC_EN, tmpV16); + RTL_W8(0x1c, RTL_R8(0x1c)|0x02); + } + // Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid + tmpV16 = RTL_R16(SYS_CLKR); + if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) { + tmpV16 |= (LOADER_CLK_EN | ANA8M); + RTL_W16(SYS_CLKR, tmpV16); + } + + if (bWrite == TRUE) { + // Enable LDO 2.5V before read/write action + tempval = RTL_R8(EFUSE_TEST + 3); +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + tempval &= ~(BIT3 | BIT4 | BIT5 | BIT6); + tempval |= (VOLTAGE_V25 << 3); + tempval |= BIT7; + RTL_W8(EFUSE_TEST + 3, tempval); + } else +#endif + { + tempval &= 0x0F; + tempval |= (VOLTAGE_V25 << 4); + RTL_W8(EFUSE_TEST + 3, (tempval | 0x80)); + } + } + } else { +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + tempval = 0x0; + RTL_W8(REG_PG_PASSWD_8812, tempval); + } +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + RTL_W8(REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF); +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + RTL_W8(REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF_8192E); +#endif + + + if (bWrite == TRUE) { + // Disable LDO 2.5V after read/write action + tempval = RTL_R8(EFUSE_TEST + 3); + RTL_W8(EFUSE_TEST + 3, (tempval & 0x7F)); + } + } +} /* efuse_PowerSwitch */ + +static void ReadEFuseByte(struct rtl8192cd_priv *priv, unsigned short _offset, unsigned char *pbuf) +{ + unsigned int value32; + unsigned char readbyte; + unsigned short retry; + +#if defined(CONFIG_WLAN_HAL_8192EE) + if( GET_CHIP_VER(priv) == VERSION_8192E ) + { + if (!IS_TEST_CHIP(priv) && IS_HARDWARE_TYPE_8192E(priv) && + (_GET_HAL_DATA(priv)->cutVersion != ODM_CUT_A) ) + { + //0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) + RTL_W8(EFUSE_TEST + 1, (RTL_R8(EFUSE_TEST + 1) & 0xf7) | (0x00 << 3)); + } + } +#endif + + //Write Address + RTL_W8(EFUSE_CTRL + 1, (_offset & 0xff)); + readbyte = RTL_R8(EFUSE_CTRL + 2); + RTL_W8(EFUSE_CTRL + 2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); + + //Write bit 32 0 + readbyte = RTL_R8(EFUSE_CTRL + 3); + RTL_W8(EFUSE_CTRL + 3, 0x72); //read cmd + //RTL_W8(EFUSE_CTRL+3, (readbyte & 0x7f)); + + //Check bit 32 read-ready + retry = 0; + value32 = RTL_R32(EFUSE_CTRL); + + while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) { + value32 = RTL_R32(EFUSE_CTRL); + retry++; + } + + // 20100205 Joseph: Add delay suggested by SD1 Victor. + // This fix the problem that Efuse read error in high temperature condition. + // Designer says that there shall be some delay after ready bit is set, or the + // result will always stay on last data we read. + delay_us(50); + value32 = RTL_R32(EFUSE_CTRL); + + *pbuf = (unsigned char)(value32 & 0xff); +} /* ReadEFuseByte */ + + +// +// Description: +// 1. Execute E-Fuse read byte operation according as map offset and +// save to E-Fuse table. +// 2. Refered from SD1 Richard. +// +// Assumption: +// 1. Boot from E-Fuse and successfully auto-load. +// 2. PASSIVE_LEVEL (USB interface) +// +// Created by Roger, 2008.10.21. +// 2008/12/12 MH 1. Reorganize code flow and reserve bytes. and add description. +// 2. Add efuse utilization collect. +// 2008/12/22 MH Read Efuse must check if we write section 1 data again!!! Sec1 +// write addr must be after sec5. +// +static void ReadEFuse(struct rtl8192cd_priv *priv, unsigned short _offset, int _size_byte, unsigned char *pbuf) +{ + unsigned char efuseTbl[priv->EfuseMapLen]; + unsigned char rtemp8[1]; + unsigned short eFuse_Addr = 0; + unsigned char offset, wren; + unsigned short i, j; + unsigned short eFuseWord[priv->EfuseMaxSection][EFUSE_MAX_WORD_UNIT]; + unsigned short efuse_utilized = 0; +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + UINT8 bSupportExtendHdr = ((GET_CHIP_VER(priv) == VERSION_8192D) || (GET_CHIP_VER(priv) == VERSION_8188E) + || (GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8812E)); +#endif + + // + // Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. + // + if ((_offset + _size_byte) > priv->EfuseMapLen) { + // total E-Fuse table is 128bytes + DEBUG_INFO("ReadEFuse(): Invalid offset(%#x) with read bytes(%#x)!!\n", _offset, _size_byte); + return; + } + + // 0. Refresh efuse init map as all oxFF. + for (i = 0; i < priv->EfuseMaxSection; i++) + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) + eFuseWord[i][j] = 0xFFFF; + + // + // 1. Read the first byte to check if efuse is empty!!! + // + // + ReadEFuseByte(priv, eFuse_Addr, rtemp8); + if (*rtemp8 != 0xFF) { + efuse_utilized++; + eFuse_Addr++; + } else { + //RTPRINT(FEEPROM, EFUSE_READ_ALL, ("EFUSE is empty efuse_Addr-%d efuse_data=%x\n", eFuse_Addr, *rtemp8)); + return; + } + + // + // 2. Read real efuse content. Filter PG header and every section data. + // + while ((*rtemp8 != 0xFF) && (eFuse_Addr < priv->EfuseRealContentLen)) { + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + // Check PG header for section num. + if (bSupportExtendHdr && ((*rtemp8 & 0x1F) == 0x0F)) { //extended header + unsigned char u1temp = ((*rtemp8 & 0xE0) >> 5); + ReadEFuseByte(priv, eFuse_Addr, rtemp8); + if ((*rtemp8 & 0x0F) == 0x0F) { + eFuse_Addr++; + ReadEFuseByte(priv, eFuse_Addr, rtemp8); + if (*rtemp8 != 0xFF && (eFuse_Addr < priv->EfuseRealContentLen)) { + eFuse_Addr++; + } + break; + } else { + offset = ((*rtemp8 & 0xF0) >> 1) | u1temp; + wren = (*rtemp8 & 0x0F); + eFuse_Addr++; + } + } else +#endif + { + offset = ((*rtemp8 >> 4) & 0x0f); + wren = (*rtemp8 & 0x0f); + } + + if (offset < priv->EfuseMaxSection) { + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + // Check word enable condition in the section + if (!(wren & 0x01)) { + ReadEFuseByte(priv, eFuse_Addr, rtemp8); + DEBUG_INFO("ReadEFuse, Addr=%x, %02x\n", eFuse_Addr, *rtemp8); + eFuse_Addr++; + efuse_utilized++; + eFuseWord[offset][i] = (*rtemp8 & 0xff); + if (eFuse_Addr >= priv->EfuseRealContentLen) + break; + ReadEFuseByte(priv, eFuse_Addr, rtemp8); + DEBUG_INFO("ReadEFuse, Addr=%x, %02x\n", eFuse_Addr, *rtemp8); + eFuse_Addr++; + efuse_utilized++; + eFuseWord[offset][i] |= (((UINT16) * rtemp8 << 8) & 0xff00); + if (eFuse_Addr >= priv->EfuseRealContentLen) + break; + } + wren >>= 1; + } + } + + // Read next PG header + ReadEFuseByte(priv, eFuse_Addr, rtemp8); + if (*rtemp8 != 0xFF && (eFuse_Addr < priv->EfuseRealContentLen)) { + efuse_utilized++; + DEBUG_INFO("ReadEFuse, Addr=%x, %02x\n", eFuse_Addr, *rtemp8); + eFuse_Addr++; + } + } + + // + // 3. Collect 16 sections and 4 word unit into Efuse map. + // + for (i = 0; i < priv->EfuseMaxSection; i++) { + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { + efuseTbl[(i << 3) + (j << 1)] = (eFuseWord[i][j] & 0xff); + efuseTbl[(i << 3) + (j << 1) + 1] = ((eFuseWord[i][j] >> 8) & 0xff); + } + } + + // + // 4. Copy from Efuse map to output pointer memory!!! + // + for (i = 0; i < _size_byte; i++) { + pbuf[i] = efuseTbl[_offset + i]; + } + + // + // 5. Calculate Efuse utilization. + // + //efuse_usage = (unsigned char)((efuse_utilized*100)/priv->EfuseRealContentLen); + priv->EfuseUsedBytes = efuse_utilized; + +} + + +/*----------------------------------------------------------------------------- + * Function: efuse_ReadAllMap + * + * Overview: Read All Efuse content + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/11/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +static void efuse_ReadAllMap(struct rtl8192cd_priv *priv, unsigned char *Efuse) +{ + // + // We must enable clock and LDO 2.5V otherwise, read all map will be fail!!!! + // + efuse_PowerSwitch(priv, FALSE, TRUE); + ReadEFuse(priv, 0, priv->EfuseMapLen, Efuse); + efuse_PowerSwitch(priv, FALSE, FALSE); +} + + +/*----------------------------------------------------------------------------- + * Function: EFUSE_ShadowMapUpdate + * + * Overview: Transfer current EFUSE content to shadow init and modify map. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/13/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +static void EFUSE_ShadowMapUpdate(struct rtl8192cd_priv *priv) +{ + /* + if (priv->AutoloadFailFlag == TRUE ) { + DEBUG_INFO("AutoloadFailFlag=TRUE"); + memset((&priv->EfuseMap[EFUSE_INIT_MAP][0]), 0xFF, 128); + } else + */ + { + efuse_ReadAllMap(priv, &priv->EfuseMap[EFUSE_INIT_MAP][0]); + } + + memcpy(&priv->EfuseMap[EFUSE_MODIFY_MAP][0], + &priv->EfuseMap[EFUSE_INIT_MAP][0], priv->EfuseMapLen); + +} + +#ifdef CONFIG_RTL_88E_SUPPORT +static void ReadTxPowerInfoFromHWPG_8188E(struct rtl8192cd_priv *priv) +{ + const int MAX_CHNL_GROUP_24G_88E = 6; // ch1~2, ch3~5, ch6~8,ch9~11,ch12~13,CH 14 total six groups + const int chnl_group[MAX_2G_CHANNEL_NUM] = {0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5}; + + unsigned int eeAddr = EEPROM_TX_PWR_INX_88E; + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + u8 IndexCCK_Base[MAX_CHNL_GROUP_24G_88E]; + u8 IndexBW40_Base[MAX_CHNL_GROUP_24G_88E-1]; + //If only one tx, only BW20 and OFDM are used. + u8 OFDM_Diff, BW20_Diff; + u8 group, ch, index; + +// if (!isPGValueValid(priv, hwinfo)) +// return; + + if (/*priv->AutoloadFailFlag==FALSE &&*/ priv->pmib->efuseEntry.enable_efuse==1) { + for (group = 0 ; group < MAX_CHNL_GROUP_24G_88E; ++group) { + IndexCCK_Base[group] = hwinfo[eeAddr++]; + } + + for (group = 0 ; group < MAX_CHNL_GROUP_24G_88E-1; ++group) { + IndexBW40_Base[group] = hwinfo[eeAddr++]; + } + + BW20_Diff = (hwinfo[eeAddr] & 0xf0) >> 4; // 4-bit field and MSB(bit3) is sign number + OFDM_Diff = (hwinfo[eeAddr] & 0x0f); // 4-bit field and MSB(bit3) is sign number + eeAddr++; + + for (ch = 1; ch <= MAX_2G_CHANNEL_NUM; ++ch) + { + index = ch -1; + group = chnl_group[index]; + + priv->pmib->dot11RFEntry.pwrlevelCCK_A[index] = IndexCCK_Base[group]; + + if (ch == 14) + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[index] = IndexBW40_Base[4]; + else + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[index] = IndexBW40_Base[group]; + } + + memset(priv->pmib->dot11RFEntry.pwrdiffHT20, BW20_Diff, sizeof(priv->pmib->dot11RFEntry.pwrdiffHT20)); + memset(priv->pmib->dot11RFEntry.pwrdiffOFDM, OFDM_Diff, sizeof(priv->pmib->dot11RFEntry.pwrdiffOFDM)); + memset(priv->pmib->dot11RFEntry.pwrlevelCCK_B, 0x00, sizeof(priv->pmib->dot11RFEntry.pwrlevelCCK_B)); + memset(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B, 0x00, sizeof(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B)); + memset(priv->pmib->dot11RFEntry.pwrdiffHT40_2S, 0x00, sizeof(priv->pmib->dot11RFEntry.pwrdiffHT40_2S)); + + DEBUG_INFO("EFUSE Autoload success!\n"); + } +} +#endif // CONFIG_RTL_88E_SUPPORT + +#ifdef CONFIG_WLAN_HAL_8192EE +static void ReadTxPowerInfoFromHWPG_8192E(struct rtl8192cd_priv *priv) +{ + int i, ch_gp; + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + if ( GET_CHIP_VER(priv)==VERSION_8192E ) + { + for (i=0; i -1) + { + if (hwinfo[EEPROM_2G_CCK1T_TxPower+PATHA_OFFSET+ch_gp] <= 63 ) + priv->pmib->dot11RFEntry.pwrlevelCCK_A[i]= hwinfo[EEPROM_2G_CCK1T_TxPower+PATHA_OFFSET+ch_gp]; + else + priv->pmib->dot11RFEntry.pwrlevelCCK_A[i]= 0; + if (hwinfo[EEPROM_2G_CCK1T_TxPower+PATHB_OFFSET+ch_gp] <= 63 ) + priv->pmib->dot11RFEntry.pwrlevelCCK_B[i]= hwinfo[EEPROM_2G_CCK1T_TxPower+PATHB_OFFSET+ch_gp]; + else + priv->pmib->dot11RFEntry.pwrlevelCCK_B[i]= 0; + + if (i==13)//ch 14 + ch_gp -= 1; + + if (hwinfo[EEPROM_2G_HT401S_TxPower+PATHA_OFFSET+ch_gp] <= 63 ) + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] = hwinfo[EEPROM_2G_HT401S_TxPower+PATHA_OFFSET+ch_gp]; + else + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] = 0; + if (hwinfo[EEPROM_2G_HT401S_TxPower+PATHB_OFFSET+ch_gp] <= 63 ) + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] = hwinfo[EEPROM_2G_HT401S_TxPower+PATHB_OFFSET+ch_gp]; + else + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] = 0; + } + + if (priv->pmib->dot11RFEntry.pwrlevelCCK_A[0] != 0) + { + priv->pmib->dot11RFEntry.pwrdiffHT40_2S[i] = ((hwinfo[EEPROM_2G_HT402S_TxPowerDiff+PATHA_OFFSET] & 0xf0) >> 4) | + (hwinfo[EEPROM_2G_HT402S_TxPowerDiff+PATHB_OFFSET] & 0xf0); + priv->pmib->dot11RFEntry.pwrdiffHT20[i] = ((hwinfo[EEPROM_2G_HT201S_TxPowerDiff+PATHA_OFFSET] & 0xf0) >> 4) | + (hwinfo[EEPROM_2G_HT201S_TxPowerDiff+PATHB_OFFSET] & 0xf0); + priv->pmib->dot11RFEntry.pwrdiffOFDM[i] = (hwinfo[EEPROM_2G_OFDM1T_TxPowerDiff+PATHA_OFFSET] & 0x0f) | + ((hwinfo[EEPROM_2G_OFDM1T_TxPowerDiff+PATHB_OFFSET] & 0x0f) << 4); + } + else + { + priv->pmib->dot11RFEntry.pwrdiffHT40_2S[i] = 0; + priv->pmib->dot11RFEntry.pwrdiffHT20[i] = 0; + priv->pmib->dot11RFEntry.pwrdiffOFDM[i] = 0; + } + } + } + +#if 0 + const int MAX_CHNL_GROUP_24G_92E = 6; // ch1~2, ch3~5, ch6~8,ch9~11,ch12~13,CH 14 total six groups + const int chnl_group[MAX_2G_CHANNEL_NUM] = {0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5}; + + unsigned int eeAddr_A = EEPROM_TX_PWR_INX_8192E+PATHA_OFFSET, eeAddr_B = EEPROM_TX_PWR_INX_8192E+PATHB_OFFSET; + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + u8 IndexCCK_Base_A[MAX_CHNL_GROUP_24G_92E], IndexCCK_Base_B[MAX_CHNL_GROUP_24G_92E]; + u8 IndexBW40_Base_A[MAX_CHNL_GROUP_24G_92E-1], IndexBW40_Base_B[MAX_CHNL_GROUP_24G_92E-1]; + //If only one tx, only BW20 and OFDM are used. + u8 OFDM_Diff, BW20_Diff, BW40_2S_DIFF, BW20_2S_DIFF; + u8 group, ch, index; + +// if (!isPGValueValid(priv, hwinfo)) +// return; + + if (/*priv->AutoloadFailFlag==FALSE &&*/ priv->pmib->efuseEntry.enable_efuse==1) { + for (group = 0 ; group < MAX_CHNL_GROUP_24G_92E; ++group) { + IndexCCK_Base_A[group] = hwinfo[eeAddr_A++]; + IndexCCK_Base_B[group] = hwinfo[eeAddr_B++]; + } + + for (group = 0 ; group < MAX_CHNL_GROUP_24G_92E-1; ++group) { + IndexBW40_Base_A[group] = hwinfo[eeAddr_A++]; + IndexBW40_Base_B[group] = hwinfo[eeAddr_B++]; + } + + BW20_Diff = (hwinfo[eeAddr_A] & 0xf0) >> 4; // 4-bit field and MSB(bit3) is sign number + OFDM_Diff = (hwinfo[eeAddr_A] & 0x0f); // 4-bit field and MSB(bit3) is sign number + + eeAddr_A++; + + BW40_2S_DIFF = (hwinfo[eeAddr_A] & 0xf0) >> 4; // 4-bit field and MSB(bit3) is sign number + BW20_2S_DIFF = (hwinfo[eeAddr_A] & 0x0f); // 4-bit field and MSB(bit3) is sign number + + for (ch = 1; ch <= MAX_2G_CHANNEL_NUM; ++ch) + { + index = ch -1; + group = chnl_group[index]; + + priv->pmib->dot11RFEntry.pwrlevelCCK_A[index] = IndexCCK_Base_A[group]; + priv->pmib->dot11RFEntry.pwrlevelCCK_B[index] = IndexCCK_Base_B[group]; + + if (ch == 14){ + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[index] = IndexBW40_Base_A[4]; + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[index] = IndexBW40_Base_B[4]; + } + else{ + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[index] = IndexBW40_Base_A[group]; + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[index] = IndexBW40_Base_B[group]; + } + } + + memset(priv->pmib->dot11RFEntry.pwrdiffHT20, BW20_Diff, sizeof(priv->pmib->dot11RFEntry.pwrdiffHT20)); + memset(priv->pmib->dot11RFEntry.pwrdiffOFDM, OFDM_Diff, sizeof(priv->pmib->dot11RFEntry.pwrdiffOFDM)); + memset(priv->pmib->dot11RFEntry.pwrdiffHT40_2S, BW40_2S_DIFF, sizeof(priv->pmib->dot11RFEntry.pwrdiffHT40_2S)); + + DEBUG_INFO("EFUSE Autoload success!\n"); + } +#endif +} +#endif // CONFIG_WLAN_HAL_8192EE + +static int isPGValueValid(struct rtl8192cd_priv *priv, unsigned char *hwinfo) +{ + int j=0; +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + for (j = EEPROM_TxPowerCCK; j < EEPROM_TxPowerCCK + 3; j++) { + if (hwinfo[j] > 63) + return 0; + } + for (j = EEPROM_TxPowerHT40_1S; j < EEPROM_TxPowerHT40_1S + 3; j++) { + if (hwinfo[j] > 63) + return 0; + } + } +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + for (j = EEPROM_2G_TxPowerCCK; j < EEPROM_2G_TxPowerCCK + 3; j++) { + if (hwinfo[j] > 63) + return 0; + } + for (j = EEPROM_2G_TxPowerHT40_1S; j < EEPROM_2G_TxPowerHT40_1S + 3; j++) { + if (hwinfo[j] > 63) + return 0; + } + for (j = EEPROM_5GL_TxPowerHT40_1S; j < EEPROM_5GL_TxPowerHT40_1S + 3; j++) { + if (hwinfo[j] > 63) + return 0; + } + for (j = EEPROM_5GM_TxPowerHT40_1S; j < EEPROM_5GM_TxPowerHT40_1S + 3; j++) { + if (hwinfo[j] > 63) + return 0; + } + for (j = EEPROM_5GH_TxPowerHT40_1S; j < EEPROM_5GH_TxPowerHT40_1S + 3; j++) { + if (hwinfo[j] > 63) + return 0; + } + } +#endif // CONFIG_RTL_92D_SUPPORT + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + for (j = EEPROM_TX_PWR_INX_88E; j < EEPROM_TX_PWR_INX_88E+11; j++) { + if (hwinfo[j] > 63) + return 0; + } + } +#endif // CONFIG_RTL_88E_SUPPORT +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + for (j = EEPROM_2G_CCK1T_TxPower+PATHA_OFFSET; j < EEPROM_2G_CCK1T_TxPower+PATHA_OFFSET+11; j++) { // path A CCK and HT40-1S + if (hwinfo[j] > 63){ + return 0; + } + } + for (j = EEPROM_2G_CCK1T_TxPower+PATHB_OFFSET; j < EEPROM_2G_CCK1T_TxPower+PATHB_OFFSET+11; j++) { // path B CCK and HT40-1S + if (hwinfo[j] > 63) + return 0; + } + } +#endif // CONFIG_WLAN_HAL_8192EE + return 1; +} + + +void ReadTxPowerInfoFromHWPG(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + int i; + + if (!isPGValueValid(priv, hwinfo)) + return; + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + ReadTxPowerInfoFromHWPG_8188E(priv); + return; + } +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + ReadTxPowerInfoFromHWPG_8192E(priv); + return; + } +#endif + + if (/*priv->AutoloadFailFlag==FALSE &&*/ priv->pmib->efuseEntry.enable_efuse == 1) { +#if defined(CONFIG_RTL_8812_SUPPORT) + if ( GET_CHIP_VER(priv) == VERSION_8812E ) { + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + int ch_gp = -1; + ch_gp = find_2gchnlgroup(i); + + if (ch_gp > -1) { + priv->pmib->dot11RFEntry.pwrlevelCCK_A[i] = hwinfo[EEPROM_2G_CCK1T_TxPower + PATHA_OFFSET + ch_gp]; + priv->pmib->dot11RFEntry.pwrlevelCCK_B[i] = hwinfo[EEPROM_2G_CCK1T_TxPower + PATHB_OFFSET + ch_gp]; + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] = hwinfo[EEPROM_2G_HT401S_TxPower + PATHA_OFFSET + ch_gp]; + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] = hwinfo[EEPROM_2G_HT401S_TxPower + PATHB_OFFSET + ch_gp]; + + read_efusemap_2gtxpwrdiff(priv, i); + } + } + + for (i = 0; i < MAX_5G_CHANNEL_NUM; i++) { + int ch_gp = -1; + ch_gp = find_5gchnlgroup(i); + + if (ch_gp > -1) { + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5G_HT401S_TxPower + PATHA_OFFSET + ch_gp]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5G_HT401S_TxPower + PATHB_OFFSET + ch_gp]; + + read_efusemap_5gtxpwrdiff(priv, i); + } else { + clear_5g_pwr_params(priv, i); + } + } + } else +#endif //#if defined(CONFIG_RTL_8812_SUPPORT) + { +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + u8 TxPwrCCK = 0, TxPwrHT40_1S = 0, TxPwrHT40_2SDiff = 0, TxPwrHT20Diff = 0, TxPwrOFDMDiff = 0; +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + TxPwrCCK = EEPROM_TxPowerCCK; + TxPwrHT40_1S = EEPROM_TxPowerHT40_1S; + TxPwrHT40_2SDiff = EEPROM_TxPowerHT40_2SDiff; + TxPwrHT20Diff = EEPROM_TxPowerHT20Diff; + TxPwrOFDMDiff = EEPROM_TxPowerOFDMDiff; + } +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + // 2.4G Setting + TxPwrCCK = EEPROM_2G_TxPowerCCK; + TxPwrHT40_1S = EEPROM_2G_TxPowerHT40_1S; + TxPwrHT40_2SDiff = EEPROM_2G_TxPowerHT40_2SDiff; + TxPwrHT20Diff = EEPROM_2G_TxPowerHT20Diff; + TxPwrOFDMDiff = EEPROM_2G_TxPowerOFDMDiff; + + // 5G Setting + for (i = 0; i < MAX_5G_CHANNEL_NUM; i++) { + if (i >= 35 && i <= 63) { // ch 36 ~ 64 + if (i >= 35 && i <= 43) { // ch 36 ~ 44 + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5GL_TxPowerHT40_1S]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5GL_TxPowerHT40_1S + 3]; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = hwinfo[EEPROM_5GL_TxPowerHT40_2SDiff]; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = hwinfo[EEPROM_5GL_TxPowerHT20Diff]; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = hwinfo[EEPROM_5GL_TxPowerOFDMDiff]; + } else if (i >= 45 && i <= 53) { // ch 46 ~ 54 + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5GL_TxPowerHT40_1S + 1]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5GL_TxPowerHT40_1S + 4]; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = hwinfo[EEPROM_5GL_TxPowerHT40_2SDiff + 1]; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = hwinfo[EEPROM_5GL_TxPowerHT20Diff + 1]; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = hwinfo[EEPROM_5GL_TxPowerOFDMDiff + 1]; + } else if (i >= 55 && i <= 63) { // ch 56 ~ 64 + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5GL_TxPowerHT40_1S + 2]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5GL_TxPowerHT40_1S + 5]; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = hwinfo[EEPROM_5GL_TxPowerHT40_2SDiff + 2]; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = hwinfo[EEPROM_5GL_TxPowerHT20Diff + 2]; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = hwinfo[EEPROM_5GL_TxPowerOFDMDiff + 2]; + } else { + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = 0; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = 0; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = 0; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = 0; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = 0; + } + } else if (i >= 99 && i <= 139) { // ch 100 ~ 140 + if (i >= 99 && i <= 111) { // ch 100 ~ 112 + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5GM_TxPowerHT40_1S]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5GM_TxPowerHT40_1S + 3]; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = hwinfo[EEPROM_5GM_TxPowerHT40_2SDiff]; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = hwinfo[EEPROM_5GM_TxPowerHT20Diff]; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = hwinfo[EEPROM_5GM_TxPowerOFDMDiff]; + } else if (i >= 113 && i <= 125) { // ch 114 ~ 126 + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5GM_TxPowerHT40_1S + 1]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5GM_TxPowerHT40_1S + 4]; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = hwinfo[EEPROM_5GM_TxPowerHT40_2SDiff + 1]; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = hwinfo[EEPROM_5GM_TxPowerHT20Diff + 1]; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = hwinfo[EEPROM_5GM_TxPowerOFDMDiff + 1]; + } else if (i >= 127 && i <= 139) { // ch 128 ~ 140 + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5GM_TxPowerHT40_1S + 2]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5GM_TxPowerHT40_1S + 5]; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = hwinfo[EEPROM_5GM_TxPowerHT40_2SDiff + 2]; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = hwinfo[EEPROM_5GM_TxPowerHT20Diff + 2]; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = hwinfo[EEPROM_5GM_TxPowerOFDMDiff + 2]; + } else { + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = 0; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = 0; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = 0; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = 0; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = 0; + } + } else if (i >= 148 && i <= 164 ) { // ch 149 ~ 165 + if (i >= 148 && i <= 152) { // ch 149 ~ 153 + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5GH_TxPowerHT40_1S]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5GH_TxPowerHT40_1S + 3]; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = hwinfo[EEPROM_5GH_TxPowerHT40_2SDiff]; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = hwinfo[EEPROM_5GH_TxPowerHT20Diff]; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = hwinfo[EEPROM_5GH_TxPowerOFDMDiff]; + } else if (i >= 154 && i <= 158) { // ch 155 ~ 159 + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5GH_TxPowerHT40_1S + 1]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5GH_TxPowerHT40_1S + 4]; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = hwinfo[EEPROM_5GH_TxPowerHT40_2SDiff + 1]; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = hwinfo[EEPROM_5GH_TxPowerHT20Diff + 1]; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = hwinfo[EEPROM_5GH_TxPowerOFDMDiff + 1]; + } else if (i >= 160 && i <= 164) { // ch 161 ~ 165 + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = hwinfo[EEPROM_5GH_TxPowerHT40_1S + 2]; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = hwinfo[EEPROM_5GH_TxPowerHT40_1S + 5]; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = hwinfo[EEPROM_5GH_TxPowerHT40_2SDiff + 2]; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = hwinfo[EEPROM_5GH_TxPowerHT20Diff + 2]; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = hwinfo[EEPROM_5GH_TxPowerOFDMDiff + 2]; + } else { + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i] = 0; + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[i] = 0; + + priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[i] = 0; + priv->pmib->dot11RFEntry.pwrdiff5GHT20[i] = 0; + priv->pmib->dot11RFEntry.pwrdiff5GOFDM[i] = 0; + } + } + } + } +#endif + + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + if (i < 3) { + priv->pmib->dot11RFEntry.pwrlevelCCK_A[i] = hwinfo[TxPwrCCK]; + priv->pmib->dot11RFEntry.pwrlevelCCK_B[i] = hwinfo[TxPwrCCK + 3]; + + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] = hwinfo[TxPwrHT40_1S]; + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] = hwinfo[TxPwrHT40_1S + 3]; + + priv->pmib->dot11RFEntry.pwrdiffHT40_2S[i] = hwinfo[TxPwrHT40_2SDiff]; + priv->pmib->dot11RFEntry.pwrdiffHT20[i] = hwinfo[TxPwrHT20Diff]; + priv->pmib->dot11RFEntry.pwrdiffOFDM[i] = hwinfo[TxPwrOFDMDiff]; + + } else if (i < 9) { + priv->pmib->dot11RFEntry.pwrlevelCCK_A[i] = hwinfo[TxPwrCCK + 1]; + priv->pmib->dot11RFEntry.pwrlevelCCK_B[i] = hwinfo[TxPwrCCK + 4]; + + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] = hwinfo[TxPwrHT40_1S + 1]; + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] = hwinfo[TxPwrHT40_1S + 4]; + + priv->pmib->dot11RFEntry.pwrdiffHT40_2S[i] = hwinfo[TxPwrHT40_2SDiff + 1]; + priv->pmib->dot11RFEntry.pwrdiffHT20[i] = hwinfo[TxPwrHT20Diff + 1]; + priv->pmib->dot11RFEntry.pwrdiffOFDM[i] = hwinfo[TxPwrOFDMDiff + 1]; + } else { + priv->pmib->dot11RFEntry.pwrlevelCCK_A[i] = hwinfo[TxPwrCCK + 2]; + priv->pmib->dot11RFEntry.pwrlevelCCK_B[i] = hwinfo[TxPwrCCK + 5]; + + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] = hwinfo[TxPwrHT40_1S + 2]; + priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[i] = hwinfo[TxPwrHT40_1S + 5]; + + priv->pmib->dot11RFEntry.pwrdiffHT40_2S[i] = hwinfo[TxPwrHT40_2SDiff + 2]; + priv->pmib->dot11RFEntry.pwrdiffHT20[i] = hwinfo[TxPwrHT20Diff + 2]; + priv->pmib->dot11RFEntry.pwrdiffOFDM[i] = hwinfo[TxPwrOFDMDiff + 2]; + + } + } +#endif // CONFIG_RTL_92C_SUPPORT || CONFIG_RTL_92D_SUPPORT + } + DEBUG_INFO("EFUSE Autoload success!\n"); + } +} + + +static void ReadMacAddressFromEfuse(struct rtl8192cd_priv *priv) +{ + u16 efuse_MAC=0; //sdio +#ifdef __KERNEL__ + struct sockaddr addr; +#endif + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + efuse_MAC = EEPROM_MACADDRESS; + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pshare->wlandev_idx == 0) { + efuse_MAC = EEPROM_MAC0_MACADDRESS; + } else { + efuse_MAC = EEPROM_MAC1_MACADDRESS; + } +#else + efuse_MAC = EEPROM_MAC0_MACADDRESS; +#endif + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + efuse_MAC = EEPROM_MAC_ADDR_88E; +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + efuse_MAC = EEPROM_92E_MACADDRESS; +#endif + + + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + efuse_MAC = EEPROM_8812_MACADDRESS; +#endif + + if (/*priv->AutoloadFailFlag==FALSE &&*/ priv->pmib->efuseEntry.enable_efuse == 1) { + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + unsigned char *efuse_mac = hwinfo + efuse_MAC; + unsigned char zero[] = {0, 0, 0, 0, 0, 0}, mac[6]; + + memcpy(mac, efuse_mac, MACADDRLEN); + /* printk("wlan%d EFUSE MAC [%02x:%02x:%02x:%02x:%02x:%02x]\n", priv->pshare->wlandev_idx, + *mac, *(mac+1), *(mac+2), *(mac+3), *(mac+4), *(mac+5)); */ +#if 0 + if (memcmp(mac, zero, MACADDRLEN) && !IS_MCAST(mac)) { +#ifdef __KERNEL__ + memcpy(addr.sa_data, mac, MACADDRLEN); + rtl8192cd_set_hwaddr(priv->dev, (void *)&addr); +#else + rtl8192cd_set_hwaddr(priv->dev, (void *)mac); +#endif + } +#else + if (!memcmp(mac, zero, MACADDRLEN) || IS_MCAST(mac)) { + memcpy(mac, zero, MACADDRLEN); + } + +#ifdef __KERNEL__ + memcpy(addr.sa_data, mac, MACADDRLEN); + rtl8192cd_set_hwaddr(priv->dev, (void *)&addr); +#else + rtl8192cd_set_hwaddr(priv->dev, (void *)mac); +#endif +#endif + } +} + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) +int get_mac_addr_from_efuse(struct rtl8192cd_priv *priv, char *mac) +{ + u16 efuse_MAC=0; //sdio + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + efuse_MAC = EEPROM_MAC_ADDR_88E; +#endif + + if (/*priv->AutoloadFailFlag==FALSE &&*/ priv->pmib->efuseEntry.enable_efuse == 1) { + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + unsigned char *efuse_mac = hwinfo + efuse_MAC; + + memcpy(mac, efuse_mac, MACADDRLEN); + /* printk("wlan%d EFUSE MAC [%02x:%02x:%02x:%02x:%02x:%02x]\n", priv->pshare->wlandev_idx, + *mac, *(mac+1), *(mac+2), *(mac+3), *(mac+4), *(mac+5)); */ + return 0; + } + else { + memset((void *)mac, 0, 6); + return -1; + } +} +#endif // __ECOS && CONFIG_SDIO_HCI + +void ReadThermalMeterFromEfuse(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + u8 efuse_Ther = 0, TherMask = 0x1f; + + if (!priv->pmib->efuseEntry.enable_efuse) + return; + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + efuse_Ther = EEPROM_THERMAL_METER; + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + efuse_Ther = EEPROM_92D_THERMAL_METER; + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + efuse_Ther = EEPROM_THERMAL_METER_88E; + TherMask = 0xff; + } +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + efuse_Ther = EEPROM_92E_THERMAL_METER; + TherMask = 0xff; + } +#endif + + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + efuse_Ther = EEPROM_8812_THERMAL_METER; + TherMask = 0xff; + } +#endif + + priv->pmib->dot11RFEntry.ther = (hwinfo[efuse_Ther] & TherMask); + DEBUG_INFO("ThermalMeter = 0x%x\n", priv->pmib->dot11RFEntry.ther); + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8192E)) { + if ((priv->pmib->dot11RFEntry.ther < 0x07) || (priv->pmib->dot11RFEntry.ther > 0x32)) { + DEBUG_ERR("TPT: unreasonable target ther %d, disable tpt\n", priv->pmib->dot11RFEntry.ther); + priv->pmib->dot11RFEntry.ther = 0; + } + } else +#endif + if ((priv->pmib->dot11RFEntry.ther < 0x07) || (priv->pmib->dot11RFEntry.ther > 0x1d)) { + priv->pmib->dot11RFEntry.ther = 0; + } +} + + +#ifdef CONFIG_USB_HCI +static void ReadBoardTypeFromEfuse(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + u8 efuse_boardType; + + if (!priv->pmib->efuseEntry.enable_efuse) + return; + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv)== VERSION_8188C) || (GET_CHIP_VER(priv)== VERSION_8192C)) { + efuse_boardType = EEPROM_NORMAL_BoardType; + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + efuse_boardType = EEPROM_RF_BOARD_OPTION_88E; + } +#endif + + priv->pshare->BoardType = (hwinfo[efuse_boardType] & BOARD_TYPE_NORMAL_MASK) >> 5; + DEBUG_INFO("BoardType = %d\n", priv->pshare->BoardType); +} + +static void ReadIDFromEfuse(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + if (FALSE == priv->AutoloadFailFlag) { +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192C) { + // VID, PID + priv->pshare->EEPROMVID = le16_to_cpu( *(u16 *)&hwinfo[EEPROM_VID]); + priv->pshare->EEPROMPID = le16_to_cpu( *(u16 *)&hwinfo[EEPROM_PID]); + + // Customer ID, 0x00 and 0xff are reserved for Realtek. + priv->pshare->EEPROMCustomerID = hwinfo[EEPROM_CUSTOMER_ID]; + priv->pshare->EEPROMSubCustomerID = hwinfo[EEPROM_SUBCUSTOMER_ID]; + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + // VID, PID + priv->pshare->EEPROMVID = EF2Byte( *(u16 *)&hwinfo[EEPROM_VID_88EU] ); + priv->pshare->EEPROMPID = EF2Byte( *(u16 *)&hwinfo[EEPROM_PID_88EU] ); + + // Customer ID, 0x00 and 0xff are reserved for Realtek. + priv->pshare->EEPROMCustomerID = hwinfo[EEPROM_CUSTOMERID_88E]; + priv->pshare->EEPROMSubCustomerID = EEPROM_Default_SubCustomerID; + } +#endif + } else{ + priv->pshare->EEPROMVID = EEPROM_Default_VID; + priv->pshare->EEPROMPID = EEPROM_Default_PID; + + // Customer ID, 0x00 and 0xff are reserved for Realtek. + priv->pshare->EEPROMCustomerID = EEPROM_Default_CustomerID; + priv->pshare->EEPROMSubCustomerID = EEPROM_Default_SubCustomerID; + } + + DEBUG_INFO("EEPROMVID = 0x%04x\n", priv->pshare->EEPROMVID); + DEBUG_INFO("EEPROMPID = 0x%04x\n", priv->pshare->EEPROMPID); + DEBUG_INFO("EEPROMCustomerID : 0x%02x\n", priv->pshare->EEPROMCustomerID); + DEBUG_INFO("EEPROMSubCustomerID: 0x%02x\n", priv->pshare->EEPROMSubCustomerID); +} +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI +#define RF_GAIN_OFFSET_ON BIT4 +#define REG_RF_BB_GAIN 0x55 +#define RF_GAIN_OFFSET_MASK 0xfffff +#define EFUSE_GAIN_FLAG_OFFSET 0xC1 + +#if defined(CONFIG_WLAN_HAL_8192EE) +#define EFUSE_GAIN_OFFSET 0x1F6 +#else +#define EFUSE_GAIN_OFFSET 0xF6 +#endif + +void rtw_bb_rf_gain_offset(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + u8 efuse_gain_offset, val, valb; + u32 res, resb; + + if (!priv->pmib->efuseEntry.enable_efuse) + return; + + efuse_gain_offset = (hwinfo[EFUSE_GAIN_FLAG_OFFSET]); + ReadEFuseByte(priv, EFUSE_GAIN_OFFSET, &val); + +#if defined(CONFIG_WLAN_HAL_8192EE) + valb = ((val & 0xF0) >> 4); +#endif + + if (efuse_gain_offset & RF_GAIN_OFFSET_ON) { + if ( val == 0xFF ) { + printk("gain offset : invalid data\n"); + return ; + } + /* + ** REG-0xF6 = [1:3]:gain [0]:+/- + ** REG-0x55 = [16:18]:gain [15]:+/- + **/ + + res = PHY_QueryRFReg(priv, RF92CD_PATH_A, REG_RF_BB_GAIN, bMask20Bits, 1); + res &= 0xfff87fff; + res |= (val & 0x0f)<< 15; + PHY_SetRFReg(priv, RF92CD_PATH_A, REG_RF_BB_GAIN, bMask20Bits, res); + val = PHY_QueryRFReg(priv, RF92CD_PATH_A, REG_RF_BB_GAIN, bMask20Bits, 1); + +#if defined(CONFIG_WLAN_HAL_8192EE) + resb = PHY_QueryRFReg(priv, RF92CD_PATH_B, REG_RF_BB_GAIN, bMask20Bits, 1); + resb &= 0xfff87fff; + resb |= (valb & 0x0f)<< 15; + PHY_SetRFReg(priv, RF92CD_PATH_B, REG_RF_BB_GAIN, bMask20Bits, resb); + val = PHY_QueryRFReg(priv, RF92CD_PATH_B, REG_RF_BB_GAIN, bMask20Bits, 1); +#endif + printk("write RF %d offset 0x%02x val [0x%05x], read back [0x%05x]\n", + RF92CD_PATH_A, REG_RF_BB_GAIN, res&0xfffff, val&0xfffff); + +#if defined(CONFIG_WLAN_HAL_8192EE) + printk("write RF %d offset 0x%02x val [0x%05x], read back [0x%05x]\n", + RF92CD_PATH_B, REG_RF_BB_GAIN, resb&0xfffff, valb&0xfffff); +#endif + } +} +#endif // CONFIG_SDIO_HCI + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) +void ReadCrystalCalibrationFromEfuse(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + if (!priv->pmib->efuseEntry.enable_efuse) + return; +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (hwinfo[EEPROM_8812_XTAL_K] == 0xff) + priv->pmib->dot11RFEntry.xcap = 0x0; + else + priv->pmib->dot11RFEntry.xcap = hwinfo[EEPROM_8812_XTAL_K] & 0x3f; //[5:0] + } +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + priv->pmib->dot11RFEntry.xcap = (hwinfo[EEPROM_XTAL_88E]); //[7:0] + } +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv) == VERSION_8192E) + { + if( hwinfo[EEPROM_92E_XTAL_K] > 0x3f ) + priv->pmib->dot11RFEntry.xcap = 0; + else + priv->pmib->dot11RFEntry.xcap = hwinfo[EEPROM_92E_XTAL_K] & 0x3f; // [5:0] + } +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8192D) { + priv->pmib->dot11RFEntry.xcap = (hwinfo[EEPROM_92D_XTAL_K]); //[7:0] + } +#endif +} +#endif + +#ifdef CONFIG_SDIO_HCI +void ReadChannelPlanFromEfuse(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + if (!priv->pmib->efuseEntry.enable_efuse) + return; + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + if (0x20 == hwinfo[EEPROM_ChannelPlan_88E]) + priv->pmib->dot11StationConfigEntry.dot11RegDomain = DOMAIN_WORLD_WIDE; + else if (0x21 == hwinfo[EEPROM_ChannelPlan_88E]) + priv->pmib->dot11StationConfigEntry.dot11RegDomain = DOMAIN_ETSI; + else if (0x22 == hwinfo[EEPROM_ChannelPlan_88E]) + priv->pmib->dot11StationConfigEntry.dot11RegDomain = DOMAIN_FCC; + else if (0x23 == hwinfo[EEPROM_ChannelPlan_88E]) + priv->pmib->dot11StationConfigEntry.dot11RegDomain = DOMAIN_MKK1; + else if (0x24 == hwinfo[EEPROM_ChannelPlan_88E]) + priv->pmib->dot11StationConfigEntry.dot11RegDomain = DOMAIN_FRANCE; + else if (0x41 == hwinfo[EEPROM_ChannelPlan_88E]) + priv->pmib->dot11StationConfigEntry.dot11RegDomain = DOMAIN_GLOBAL; + } +#endif +} +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) +void ReadTxBBSwingFromEfuse(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + unsigned int swing_setting[4] = {12, 18, 24, 30}; +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + int idx = 0; + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { + idx = hwinfo[EEPROM_2G_TxBBSwing] & 0x3; // 2G PathA OFDM + priv->pshare->OFDM_index0[0] = swing_setting[idx]; + idx = (hwinfo[EEPROM_2G_TxBBSwing]>>2) & 0x3; // 2G PathB OFDM + priv->pshare->OFDM_index0[1] = swing_setting[idx]; + } else if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + idx = hwinfo[EEPROM_5G_TxBBSwing] & 0x3; // 5G PathA OFDM + priv->pshare->OFDM_index0[0] = swing_setting[idx]; + idx = (hwinfo[EEPROM_5G_TxBBSwing]>>2) & 0x3; // 5G PathB OFDM + priv->pshare->OFDM_index0[1] = swing_setting[idx]; + } + } +#endif +} +#endif + + +#ifdef CONFIG_RTL_92D_SUPPORT +void ReadDeltaValFromEfuse(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + if (!priv->pmib->efuseEntry.enable_efuse) + return; + + priv->pmib->dot11RFEntry.deltaIQK = (hwinfo[EEPROM_92D_IQK_DELTA] & 0x03); //[1:0] + priv->pmib->dot11RFEntry.deltaLCK = (hwinfo[EEPROM_92D_LCK_DELTA] & 0x0C) >> 2; //[3:2] +} + +void ReadTRSWPAPEFromEfuse(struct rtl8192cd_priv *priv) +{ + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + + if (!priv->pmib->efuseEntry.enable_efuse) + return; + + priv->pmib->dot11RFEntry.trsw_pape_C9 = (hwinfo[EEPROM_92D_TRSW_CTRL] & 0xff); + priv->pmib->dot11RFEntry.trsw_pape_CC = (hwinfo[EEPROM_92D_PAPE_CTRL] & 0xff); + + if (priv->pmib->dot11RFEntry.trsw_pape_C9 == 0xff) + priv->pmib->dot11RFEntry.trsw_pape_C9 = 0; +} + +#endif + +int EfuseMapAlloc(struct rtl8192cd_priv *priv) +{ + int i; + for( i = 0 ; i < 2 ; i++ ) { + priv->EfuseMap[i] = (unsigned char*)kmalloc(sizeof(unsigned char)*priv->EfuseMapLen, GFP_ATOMIC); + if (NULL == priv->EfuseMap[i]) + return FAIL; + memset((void *)priv->EfuseMap[i], 0xff, sizeof(unsigned char)*priv->EfuseMapLen); + } + + return SUCCESS; +} + +int EfuseCmdInit(struct rtl8192cd_priv *priv) +{ + priv->EfuseCmd = (char**)kmalloc(sizeof(char*)*priv->EfuseCmdNum, GFP_ATOMIC); + if (NULL == priv->EfuseCmd) + return FAIL; + +#ifdef CONFIG_RTL_88E_SUPPORT + if( GET_CHIP_VER(priv) == VERSION_8188E ) + { + priv->EfuseCmd[0] = "HW_TX_POWER_CCK_A"; + priv->EfuseCmd[1] = "HW_TX_POWER_HT40_1S_A"; + priv->EfuseCmd[2] = "HW_TX_POWER_DIFF_HT20_OFDM"; + priv->EfuseCmd[3] = "HW_WLAN0_WLAN_ADDR"; + priv->EfuseCmd[4] = "EFUSE_MAP0"; + priv->EfuseCmd[5] = "EFUSE_MAP1"; + priv->EfuseCmd[6] = "HW_11N_THER"; + priv->EfuseCmd[7] = "HW_11N_XCAP"; +#ifdef CONFIG_SDIO_HCI + priv->EfuseCmd[8] = "HW_REG_DOMAIN"; + priv->EfuseCmd[9] = "SD"; +#endif + + } +#endif + +#ifdef CONFIG_RTL_92C_SUPPORT + if( GET_CHIP_VER(priv) == VERSION_8192C || GET_CHIP_VER(priv) == VERSION_8188C ) + { + priv->EfuseCmd[0] = "HW_TX_POWER_CCK_A"; + priv->EfuseCmd[1] = "HW_TX_POWER_CCK_B"; + priv->EfuseCmd[2] = "HW_TX_POWER_HT40_1S_A"; + priv->EfuseCmd[3] = "HW_TX_POWER_HT40_1S_B"; + priv->EfuseCmd[4] = "HW_TX_POWER_DIFF_HT40_2S"; + priv->EfuseCmd[5] = "HW_TX_POWER_DIFF_HT20"; + priv->EfuseCmd[6] = "HW_TX_POWER_DIFF_OFDM"; + priv->EfuseCmd[7] = "HW_WLAN0_WLAN_ADDR"; + priv->EfuseCmd[8] = "EFUSE_MAP0"; + priv->EfuseCmd[9] = "EFUSE_MAP1"; + priv->EfuseCmd[10] = "HW_11N_THER"; + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if( GET_CHIP_VER(priv) == VERSION_8192D ) + { + priv->EfuseCmd[0] = "HW_TX_POWER_CCK_A"; + priv->EfuseCmd[1] = "HW_TX_POWER_CCK_B"; + priv->EfuseCmd[2] = "HW_TX_POWER_HT40_1S_A"; + priv->EfuseCmd[3] = "HW_TX_POWER_HT40_1S_B"; + priv->EfuseCmd[4] = "HW_TX_POWER_DIFF_HT40_2S"; + priv->EfuseCmd[5] = "HW_TX_POWER_DIFF_HT20"; + priv->EfuseCmd[6] = "HW_TX_POWER_DIFF_OFDM"; + priv->EfuseCmd[7] = "HW_WLAN0_WLAN_ADDR"; + priv->EfuseCmd[8] = "EFUSE_MAP0"; + priv->EfuseCmd[9] = "EFUSE_MAP1"; + priv->EfuseCmd[10] = "HW_11N_THER"; + priv->EfuseCmd[11] = "HW_TX_POWER_5G_HT40_1S_A"; + priv->EfuseCmd[12] = "HW_TX_POWER_5G_HT40_1S_B"; + priv->EfuseCmd[13] = "HW_TX_POWER_DIFF_5G_HT40_2S"; + priv->EfuseCmd[14] = "HW_TX_POWER_DIFF_5G_HT20"; + priv->EfuseCmd[15] = "HW_TX_POWER_DIFF_5G_OFDM"; + priv->EfuseCmd[16] = "HW_11N_TRSWPAPE_C9"; + priv->EfuseCmd[17] = "HW_11N_TRSWPAPE_CC"; + priv->EfuseCmd[18] = "HW_11N_XCAP"; + } +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if( GET_CHIP_VER(priv) == VERSION_8192E ) + { + priv->EfuseCmd[0] = "HW_TX_POWER_CCK_A"; + priv->EfuseCmd[1] = "HW_TX_POWER_CCK_B"; + priv->EfuseCmd[2] = "HW_TX_POWER_HT40_1S_A"; + priv->EfuseCmd[3] = "HW_TX_POWER_HT40_1S_B"; + priv->EfuseCmd[4] = "HW_TX_POWER_DIFF_HT20_A"; + priv->EfuseCmd[5] = "HW_TX_POWER_DIFF_HT20_B"; + priv->EfuseCmd[6] = "HW_TX_POWER_DIFF_HT20_OFDM_A"; + priv->EfuseCmd[7] = "HW_TX_POWER_DIFF_HT20_OFDM_B"; + priv->EfuseCmd[8] = "HW_TX_POWER_DIFF_HT40_2S_A"; + priv->EfuseCmd[9] = "HW_TX_POWER_DIFF_HT40_2S_B"; + priv->EfuseCmd[10] = "HW_WLAN0_WLAN_ADDR"; + priv->EfuseCmd[11] = "EFUSE_MAP0"; + priv->EfuseCmd[12] = "EFUSE_MAP1"; + priv->EfuseCmd[13] = "HW_11N_THER"; + priv->EfuseCmd[14] = "HW_11N_XCAP"; + priv->EfuseCmd[15] = "EFUSE_TEST"; +#ifdef CONFIG_SDIO_HCI + priv->EfuseCmd[16] = "SD"; +#endif + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if( GET_CHIP_VER(priv) == VERSION_8812E ) + { + priv->EfuseCmd[0] = "HW_TX_POWER_CCK_A"; + priv->EfuseCmd[1] = "HW_TX_POWER_CCK_B"; + priv->EfuseCmd[2] = "HW_TX_POWER_HT40_1S_A"; + priv->EfuseCmd[3] = "HW_TX_POWER_HT40_1S_B"; + priv->EfuseCmd[4] = "HW_TX_POWER_DIFF_HT40_2S"; + priv->EfuseCmd[5] = "HW_TX_POWER_DIFF_HT20"; + priv->EfuseCmd[6] = "HW_TX_POWER_DIFF_OFDM"; + priv->EfuseCmd[7] = "HW_WLAN0_WLAN_ADDR"; + priv->EfuseCmd[8] = "EFUSE_MAP0"; + priv->EfuseCmd[9] = "EFUSE_MAP1"; + priv->EfuseCmd[10] = "HW_11N_THER"; + priv->EfuseCmd[11] = "HW_TX_POWER_5G_HT40_1S_A"; + priv->EfuseCmd[12] = "HW_TX_POWER_5G_HT40_1S_B"; + priv->EfuseCmd[13] = "HW_TX_POWER_DIFF_5G_HT40_2S"; + priv->EfuseCmd[14] = "HW_TX_POWER_DIFF_5G_HT20"; + priv->EfuseCmd[15] = "HW_TX_POWER_DIFF_5G_OFDM"; + priv->EfuseCmd[16] = "HW_11N_TRSWPAPE_C9"; + priv->EfuseCmd[17] = "HW_11N_TRSWPAPE_CC"; + priv->EfuseCmd[18] = "HW_11N_XCAP"; + priv->EfuseCmd[19] = "HW_TX_POWER_DIFF_5G_20BW1S_OFDM1T_A"; + priv->EfuseCmd[20] = "HW_TX_POWER_DIFF_5G_20BW1S_OFDM1T_B"; + priv->EfuseCmd[21] = "HW_TX_POWER_DIFF_5G_40BW2S_20BW2S_A"; + priv->EfuseCmd[22] = "HW_TX_POWER_DIFF_5G_40BW2S_20BW2S_B"; + priv->EfuseCmd[23] = "HW_TX_POWER_DIFF_5G_80BW1S_160BW1S_A"; + priv->EfuseCmd[24] = "HW_TX_POWER_DIFF_5G_80BW1S_160BW1S_B"; + priv->EfuseCmd[25] = "HW_TX_POWER_DIFF_5G_80BW2S_160BW2S_A"; + priv->EfuseCmd[26] = "HW_TX_POWER_DIFF_5G_80BW2S_160BW2S_B"; + priv->EfuseCmd[27] = "HW_TX_POWER_DIFF_20BW1S_OFDM1T_A"; + priv->EfuseCmd[28] = "HW_TX_POWER_DIFF_20BW1S_OFDM1T_B"; + priv->EfuseCmd[29] = "HW_TX_POWER_DIFF_40BW2S_20BW2S_A"; + priv->EfuseCmd[30] = "HW_TX_POWER_DIFF_40BW2S_20BW2S_B"; + } +#endif + + return SUCCESS; +} + +void EfuseInit(struct rtl8192cd_priv *priv) +{ + +#ifdef CONFIG_RTL_88E_SUPPORT + if( GET_CHIP_VER(priv) == VERSION_8188E ) + { + priv->EfuseRealContentLen = 256; + priv->EfuseMapLen = 512; + priv->EfuseMaxSection= 64; + priv->EfuseOobProtectBytes= 18; +#ifdef CONFIG_SDIO_HCI + priv->EfuseCmdNum = 10; +#else + priv->EfuseCmdNum = 8; +#endif + } +#endif + +#ifdef CONFIG_RTL_92C_SUPPORT + if( GET_CHIP_VER(priv) == VERSION_8192C || GET_CHIP_VER(priv) == VERSION_8188C ) + { + priv->EfuseRealContentLen = 512; + priv->EfuseMapLen = 128; + priv->EfuseMaxSection= 16; + priv->EfuseOobProtectBytes= 15; + priv->EfuseCmdNum = 11; + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if( GET_CHIP_VER(priv) == VERSION_8192D ) + { + priv->EfuseRealContentLen = 1024; + priv->EfuseMapLen= 256; + priv->EfuseMaxSection= 32; + priv->EfuseOobProtectBytes= 18; + priv->EfuseCmdNum = 19; + } +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if( GET_CHIP_VER(priv) == VERSION_8192E ) + { + priv->EfuseRealContentLen = 512; + priv->EfuseMapLen = 512; + priv->EfuseMaxSection = 64; + priv->EfuseOobProtectBytes = 15; +#ifdef CONFIG_SDIO_HCI + priv->EfuseCmdNum = 17; +#else + priv->EfuseCmdNum = 16; +#endif + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if( GET_CHIP_VER(priv) == VERSION_8812E ) + { + priv->EfuseRealContentLen = 1024; + priv->EfuseMapLen= 512; + priv->EfuseMaxSection= 64; + priv->EfuseOobProtectBytes= 506; + priv->EfuseCmdNum = 31; + } +#endif +} + +// +// Description: +// Read HW adapter information by E-Fuse or EEPROM according CR9346 reported. +// +// Assumption: +// 1. CR9346 regiser has verified. +// 2. PASSIVE_LEVEL (USB interface) +// +// Created by Roger, 2008.10.21. +// +int ReadAdapterInfo8192CE(struct rtl8192cd_priv *priv) +{ +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + unsigned char tmpU1b; + tmpU1b = RTL_R8(CR9346); + + // To check system boot selection. + if (tmpU1b & CmdEERPOMSEL) { + DEBUG_INFO("Boot from EEPROM\n"); + } else { + DEBUG_INFO("Boot from EFUSE\n"); + } + + // To check autoload success or not. + if (tmpU1b & CmdEEPROM_En) { + DEBUG_INFO("Autoload OK!!\n"); + priv->AutoloadFailFlag = FALSE; +#if 0 + EFUSE_ShadowMapUpdate(priv); + ReadTxPowerInfoFromHWPG(priv); + ReadMacAddressFromEfuse(priv); +#endif + } else { // Auto load fail. + DEBUG_INFO("AutoLoad Fail reported from CR9346!!\n"); + priv->AutoloadFailFlag = TRUE; + } + +#ifdef CONFIG_SDIO_HCI + // card enable before eFuse access + if(_CardEnable(priv) == FAIL) { + printk(KERN_ERR "%s: run power on flow fail\n", __func__); + return -EIO; + } +#endif + + EfuseInit(priv); + if (EfuseMapAlloc(priv) == FAIL) { + printk(KERN_ERR "%s: can't allocate efuse map\n", __func__); + return -ENOMEM; + } + if (EfuseCmdInit(priv) == FAIL) { + printk(KERN_ERR "%s: can't allocate efuse cmd\n", __func__); + return -ENOMEM; + } + EFUSE_ShadowMapUpdate(priv); + +#ifdef CONFIG_SDIO_HCI + // card disable after finishing eFuse access +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->StopHWHandler(priv); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + rtl8192cd_stop_hw(priv); +#endif // CONFIG_SDIO_HCI + } +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + else { + int i; + + EfuseInit(priv); + for( i = 0 ; i < 2 ; i++ ) + priv->EfuseMap[i] = priv->proot_priv->EfuseMap[i]; + priv->EfuseCmd = priv->proot_priv->EfuseCmd; + } +#endif + + ReadTxPowerInfoFromHWPG(priv); + ReadThermalMeterFromEfuse(priv); + ReadMacAddressFromEfuse(priv); +#ifdef CONFIG_USB_HCI + ReadIDFromEfuse(priv); + ReadBoardTypeFromEfuse(priv); +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + ReadCrystalCalibrationFromEfuse(priv); + ReadDeltaValFromEfuse(priv); + ReadTRSWPAPEFromEfuse(priv); + } +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv)==VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv)==VERSION_8192E)) + ReadCrystalCalibrationFromEfuse(priv); +#endif + +#ifdef CONFIG_SDIO_HCI + if (GET_CHIP_VER(priv)==VERSION_8188E) + ReadChannelPlanFromEfuse(priv); +#endif + + return 0; +} +#if 0 +#ifdef CONFIG_RTL_88E_SUPPORT +static char FLASH_NAME_PARAM[][50] = { + "HW_TX_POWER_CCK_A", + "HW_TX_POWER_HT40_1S_A", + "HW_TX_POWER_DIFF_HT20_OFDM", + "HW_WLAN0_WLAN_ADDR", + "EFUSE_MAP0", + "EFUSE_MAP1", + "HW_11N_THER", + "HW_11N_XCAP", +#ifdef CONFIG_SDIO_HCI + "HW_REG_DOMAIN", +#endif +}; +#elif defined(CONFIG_WLAN_HAL_8192EE) +static char FLASH_NAME_PARAM[][50] = { + "HW_TX_POWER_CCK_A", + "HW_TX_POWER_CCK_B", + "HW_TX_POWER_HT40_1S_A", + "HW_TX_POWER_HT40_1S_B", + "HW_TX_POWER_DIFF_HT20_OFDM", + "HW_TX_POWER_DIFF_HT40_2S", + "HW_WLAN0_WLAN_ADDR", + "EFUSE_MAP0", + "EFUSE_MAP1", + "HW_11N_THER", + "HW_11N_XCAP" //there's more +}; +#else +static char FLASH_NAME_PARAM[][50] = { + "HW_TX_POWER_CCK_A", + "HW_TX_POWER_CCK_B", + "HW_TX_POWER_HT40_1S_A", + "HW_TX_POWER_HT40_1S_B", + "HW_TX_POWER_DIFF_HT40_2S", + "HW_TX_POWER_DIFF_HT20", + "HW_TX_POWER_DIFF_OFDM", + "HW_WLAN0_WLAN_ADDR", + "EFUSE_MAP0", + "EFUSE_MAP1", + "HW_11N_THER", +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + "HW_TX_POWER_5G_HT40_1S_A", + "HW_TX_POWER_5G_HT40_1S_B", + "HW_TX_POWER_DIFF_5G_HT40_2S", + "HW_TX_POWER_DIFF_5G_HT20", + "HW_TX_POWER_DIFF_5G_OFDM", + "HW_11N_TRSWPAPE_C9", + "HW_11N_TRSWPAPE_CC", + "HW_11N_XCAP", +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) + "HW_TX_POWER_DIFF_5G_20BW1S_OFDM1T_A", + "HW_TX_POWER_DIFF_5G_20BW1S_OFDM1T_B", + "HW_TX_POWER_DIFF_5G_40BW2S_20BW2S_A", + "HW_TX_POWER_DIFF_5G_40BW2S_20BW2S_B", + "HW_TX_POWER_DIFF_5G_80BW1S_160BW1S_A", + "HW_TX_POWER_DIFF_5G_80BW1S_160BW1S_B", + "HW_TX_POWER_DIFF_5G_80BW2S_160BW2S_A", + "HW_TX_POWER_DIFF_5G_80BW2S_160BW2S_B", + "HW_TX_POWER_DIFF_20BW1S_OFDM1T_A", + "HW_TX_POWER_DIFF_20BW1S_OFDM1T_B", + "HW_TX_POWER_DIFF_40BW2S_20BW2S_A", + "HW_TX_POWER_DIFF_40BW2S_20BW2S_B" +#endif +}; +#endif + +#define EFUSECMD_NUM_92C 11 +#define EFUSECMD_NUM_92D 19 +#define EFUSECMD_NUM_8812 31 +#ifdef CONFIG_SDIO_HCI +#define EFUSECMD_NUM_88E 9 +#else +#define EFUSECMD_NUM_88E 8 +#endif +#define EFUSECMD_NUM_92E 11 + +#endif + +static int getEEPROMOffset(struct rtl8192cd_priv *priv, int type) +{ + int offset = 0; + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + switch (type) { + case 0: + offset = EEPROM_TxPowerCCK; + break; + case 1: + offset = EEPROM_TxPowerCCK + 3; + break; + case 2: + offset = EEPROM_TxPowerHT40_1S; + break; + case 3: + offset = EEPROM_TxPowerHT40_1S + 3; + break; + case 4: + offset = EEPROM_TxPowerHT40_2SDiff; + break; + case 5: + offset = EEPROM_TxPowerHT20Diff; + break; + case 6: + offset = EEPROM_TxPowerOFDMDiff; + break; + case 7: + offset = EEPROM_MACADDRESS; + break; + case 10: + offset = EEPROM_THERMAL_METER; + break; + default: + offset = -1; + panic_printk("NOT SUPPORT!!\n"); + break; + } + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + switch (type) { + case 0: + offset = EEPROM_2G_TxPowerCCK; + break; + case 1: + offset = EEPROM_2G_TxPowerCCK + 3; + break; + case 2: + offset = EEPROM_2G_TxPowerHT40_1S; + break; + case 3: + offset = EEPROM_2G_TxPowerHT40_1S + 3; + break; + case 4: + offset = EEPROM_2G_TxPowerHT40_2SDiff; + break; + case 5: + offset = EEPROM_2G_TxPowerHT20Diff; + break; + case 6: + offset = EEPROM_2G_TxPowerOFDMDiff; + break; + case 7: +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pshare->wlandev_idx == 1) + offset = EEPROM_MAC1_MACADDRESS; + else +#endif + offset = EEPROM_MAC0_MACADDRESS; + break; + case 8: + offset = 0x00; + break; + case 9: + offset = 0x32; + break; + case 10: + offset = EEPROM_92D_THERMAL_METER; + break; + case 11: + offset = EEPROM_5GL_TxPowerHT40_1S; + break; + case 12: + offset = EEPROM_5GL_TxPowerHT40_1S + 3; + break; + case 13: + offset = EEPROM_5GL_TxPowerHT40_2SDiff; + break; + case 14: + offset = EEPROM_5GL_TxPowerHT20Diff; + break; + case 15: + offset = EEPROM_5GL_TxPowerOFDMDiff; + break; + case 16: + offset = EEPROM_92D_TRSW_CTRL; + break; + case 17: + offset = EEPROM_92D_PAPE_CTRL; + break; + case 18: + offset = EEPROM_92D_XTAL_K; + break; + default: + offset = -1; + panic_printk("NOT SUPPORT!!\n"); + break; + } + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + switch (type) { + case 0: + offset = EEPROM_2G_CCK1T_TxPower + PATHA_OFFSET; + break; + case 1: + offset = EEPROM_2G_CCK1T_TxPower + PATHB_OFFSET; + break; + case 2: + offset = EEPROM_2G_HT401S_TxPower + PATHA_OFFSET; + break; + case 3: + offset = EEPROM_2G_HT401S_TxPower + PATHA_OFFSET; + break; + case 4: + offset = EEPROM_2G_HT402S_TxPowerDiff + PATHA_OFFSET; + break; + case 5: + offset = EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET; + break; + case 6: + offset = EEPROM_2G_OFDM1T_TxPowerDiff + PATHA_OFFSET; + break; + case 7: + offset = EEPROM_8812_MACADDRESS; + break; + case 8: + offset = 0x00; + break; + case 9: + offset = 0x32; + break; + case 10: + offset = EEPROM_8812_THERMAL_METER; + break; + case 11: + offset = EEPROM_5G_HT401S_TxPower + PATHA_OFFSET; + break; + case 12: + offset = EEPROM_5G_HT401S_TxPower + PATHB_OFFSET; + break; + case 18: + offset = EEPROM_8812_XTAL_K; + break; + case 19: + offset = EEPROM_5G_HT201S_TxPowerDiff + PATHA_OFFSET; + break; + case 20: + offset = EEPROM_5G_HT201S_TxPowerDiff + PATHB_OFFSET; + break; + case 21: + offset = EEPROM_5G_HT402S_TxPowerDiff + PATHA_OFFSET; + break; + case 22: + offset = EEPROM_5G_HT402S_TxPowerDiff + PATHB_OFFSET; + break; + case 23: + offset = EEPROM_5G_HT801S_TxPowerDiff + PATHA_OFFSET; + break; + case 24: + offset = EEPROM_5G_HT801S_TxPowerDiff + PATHB_OFFSET; + break; + case 25: + offset = EEPROM_5G_HT802S_TxPowerDiff + PATHA_OFFSET; + break; + case 26: + offset = EEPROM_5G_HT802S_TxPowerDiff + PATHB_OFFSET; + break; + case 27: + offset = EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET; + break; + case 28: + offset = EEPROM_2G_HT201S_TxPowerDiff + PATHB_OFFSET; + break; + case 29: + offset = EEPROM_2G_HT402S_TxPowerDiff + PATHA_OFFSET; + break; + case 30: + offset = EEPROM_2G_HT402S_TxPowerDiff + PATHB_OFFSET; + break; + default: + offset = -1; + panic_printk("NOT SUPPORT!!\n"); + break; + } + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + switch (type) { + case 0: + offset = EEPROM_TX_PWR_INX_88E; //HW_TX_POWER_CCK_A + break; + case 1: + offset = EEPROM_TX_PWR_INX_88E + 6; //HW_TX_POWER_HT40_1S_A + break; + case 2: + offset = EEPROM_TX_PWR_INX_88E + 11; //HW_TX_POWER_DIFF_HT20_OFDM + break; + case 3: + offset = EEPROM_MAC_ADDR_88E; // HW_WLAN0_WLAN_ADDR + break; + case 4: + offset = 0x00; + break; + case 5: + offset = 0x32; + break; + case 6: + offset = EEPROM_THERMAL_METER_88E; //HW_11N_THER + break; + case 7: + offset = EEPROM_XTAL_88E; //HW_11N_XCAP + break; +#ifdef CONFIG_SDIO_HCI + case 8: + offset = EEPROM_ChannelPlan_88E; //HW_REG_DOMAIN + break; + case 9: + offset = EEPROM_88E_SDIOTYPE; + break; +#endif + default: + offset = -1; + panic_printk("NOT SUPPORT!!\n"); + break; + } + } +#endif + +#if defined(CONFIG_WLAN_HAL_8192EE) + if(GET_CHIP_VER(priv) == VERSION_8192E) + { + switch(type) + { + case 0: // HW_TX_POWER_CCK_A + offset = EEPROM_2G_CCK1T_TxPower + PATHA_OFFSET; + break; + case 1: // HW_TX_POWER_CCK_B + offset = EEPROM_2G_CCK1T_TxPower + PATHB_OFFSET; + break; + case 2: // HW_TX_POWER_HT40_1S_A + offset = EEPROM_2G_HT401S_TxPower + PATHA_OFFSET; + break; + case 3: // HW_TX_POWER_HT40_1S_B + offset = EEPROM_2G_HT401S_TxPower + PATHB_OFFSET; + break; + case 4: // HW_TX_POWER_DIFF_HT20_A + offset = EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET; + break; + case 5: // HW_TX_POWER_DIFF_HT20_B + offset = EEPROM_2G_HT201S_TxPowerDiff + PATHB_OFFSET; + break; + case 6: // HW_TX_POWER_DIFF_HT20_OFDM_A + offset = EEPROM_2G_OFDM1T_TxPowerDiff + PATHA_OFFSET; + break; + case 7: // HW_TX_POWER_DIFF_HT20_OFDM_B + offset = EEPROM_2G_OFDM1T_TxPowerDiff + PATHB_OFFSET; + break; + case 8: // HW_TX_POWER_DIFF_HT40_2S_A + offset = EEPROM_2G_HT402S_TxPowerDiff + PATHA_OFFSET; + break; + case 9: // HW_TX_POWER_DIFF_HT40_2S_B + offset = EEPROM_2G_HT402S_TxPowerDiff + PATHB_OFFSET; + break; + case 10: // HW_WLAN0_WLAN_ADDR + offset = EEPROM_92E_MACADDRESS; + break; + case 11: // EFUSE_MAP0 + offset = 0x00; + break; + case 12: // EFUSE_MAP1 + offset = 0x32; + break; + case 13: // HW_11N_THER + offset = EEPROM_92E_THERMAL_METER; + break; + case 14: // HW_11N_XCAP + offset = EEPROM_92E_XTAL_K; + break; + case 15: // EFUSE_TEST + offset = 0x02; + break; +#ifdef CONFIG_SDIO_HCI + case 16: + offset = EEPROM_92E_SDIOTYPE; + break; +#endif + default: + offset = -1; + panic_printk("NOT SUPPORT!!\n"); + break; + } + } +#endif + return offset; +} + + +/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */ +static UINT8 efuse_CalculateWordCnts( UINT8 word_en) +{ + UINT8 word_cnts = 0; + if (!(word_en & BIT(0))) word_cnts++; // 0 : write enable + if (!(word_en & BIT(1))) word_cnts++; + if (!(word_en & BIT(2))) word_cnts++; + if (!(word_en & BIT(3))) word_cnts++; + return word_cnts; +} // efuse_CalculateWordCnts + + +/*----------------------------------------------------------------------------- + * Function: efuse_GetCurrentSize + * + * Overview: Get current efuse size!!! + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/16/2008 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +static UINT16 efuse_GetCurrentSize(struct rtl8192cd_priv *priv) +{ + INT32 bContinual = TRUE; + UINT16 efuse_addr = 0; + UINT8 hoffset = 0, hworden = 0; + UINT8 efuse_data, word_cnts = 0; +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + UINT8 bSupportExtendHdr = ((GET_CHIP_VER(priv) == VERSION_8192D) || (GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8192E) + || (GET_CHIP_VER(priv) == VERSION_8812E)); +#endif + + + do { + ReadEFuseByte(priv, efuse_addr, &efuse_data) ; + if (efuse_data != 0xFF) { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if (bSupportExtendHdr && ((efuse_data & 0x1F) == 0x0F)) { //extended header + hoffset = efuse_data; + efuse_addr++; + ReadEFuseByte(priv, efuse_addr , &efuse_data); + if ((efuse_data & 0x0F) == 0x0F) { + efuse_addr++; + continue; + } else { + hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + hworden = efuse_data & 0x0F; + } + } else +#endif + { + hoffset = (efuse_data >> 4) & 0x0F; + hworden = efuse_data & 0x0F; + } + word_cnts = efuse_CalculateWordCnts(hworden); + //read next header + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + } else { + bContinual = FALSE ; + } + } while (bContinual && (efuse_addr < priv->EfuseRealContentLen) ); + + return efuse_addr; + +} // efuse_GetCurrentSize} + + +/*----------------------------------------------------------------------------- + * Function: efuse_WordEnableDataRead + * + * Overview: Read allowed word in current efuse section data. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/16/2008 MHC Create Version 0. + * 11/21/2008 MHC Fix Write bug when we only enable late word. + * + *---------------------------------------------------------------------------*/ +static void efuse_WordEnableDataRead(UINT8 word_en, UINT8 *sourdata, UINT8 *targetdata) +{ + if (!(word_en & BIT(0))) { + targetdata[0] = sourdata[0]; + targetdata[1] = sourdata[1]; + } + if (!(word_en & BIT(1))) { + targetdata[2] = sourdata[2]; + targetdata[3] = sourdata[3]; + } + if (!(word_en & BIT(2))) { + targetdata[4] = sourdata[4]; + targetdata[5] = sourdata[5]; + } + if (!(word_en & BIT(3))) { + targetdata[6] = sourdata[6]; + targetdata[7] = sourdata[7]; + } +} // efuse_WordEnableDataRead + + +/*----------------------------------------------------------------------------- + * Function: efuse_PgPacketRead + * + * Overview: Receive dedicated Efuse are content. For92s, we support 16 + * area now. It will return 8 bytes content for every area. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/16/2008 MHC Reorganize code Arch and assign as local API. + * + *---------------------------------------------------------------------------*/ +static INT32 efuse_PgPacketRead(struct rtl8192cd_priv *priv, UINT8 offset, UINT8 *data) +{ + UINT8 ReadState = PG_STATE_HEADER; + INT32 bContinual = TRUE, bDataEmpty = TRUE ; + UINT16 efuse_addr = 0; + UINT8 hoffset = 0, hworden = 0, efuse_data, word_cnts = 0, tmpidx = 0; + UINT8 tmpdata[8]; +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_RTL_8812_SUPPORT) + UINT8 tmp_header; + UINT8 bSupportExtendHdr = ((GET_CHIP_VER(priv) == VERSION_8192D) || (GET_CHIP_VER(priv) == VERSION_8188E) + || (GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8812E)); +#endif + + if (data == NULL) + return FALSE; + if (offset > priv->EfuseMaxSection) + return FALSE; + + memset(data, 0xff, sizeof(UINT8)*PGPKT_DATA_SIZE); + memset(tmpdata, 0xff, sizeof(UINT8)*PGPKT_DATA_SIZE); + + // + // Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. + // Skip dummy parts to prevent unexpected data read from Efuse. + // By pass right now. 2009.02.19. + // + while (bContinual && (efuse_addr < priv->EfuseRealContentLen) ) { + //------- Header Read ------------- + if (ReadState & PG_STATE_HEADER) { + ReadEFuseByte(priv, efuse_addr , &efuse_data); + if (efuse_data != 0xFF) { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_RTL_8812_SUPPORT) + if (bSupportExtendHdr && ((efuse_data & 0x1F) == 0x0F)) { + tmp_header = efuse_data; + efuse_addr++; + ReadEFuseByte(priv, efuse_addr , &efuse_data); + if ((efuse_data & 0x0F) != 0x0F) { + hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + hworden = efuse_data & 0x0F; + } else { + efuse_addr++; + continue; + } + + } else +#endif + { + hoffset = (efuse_data >> 4) & 0x0F; + hworden = efuse_data & 0x0F; + } + word_cnts = efuse_CalculateWordCnts(hworden); + bDataEmpty = TRUE ; + + if (hoffset == offset) { + for (tmpidx = 0; tmpidx < word_cnts * 2 ; tmpidx++) { + ReadEFuseByte(priv, efuse_addr + 1 + tmpidx , &efuse_data); + tmpdata[tmpidx] = efuse_data; + if (efuse_data != 0xff) { + bDataEmpty = FALSE; + } + } + if (bDataEmpty == FALSE) { + ReadState = PG_STATE_DATA; + } else { //read next header + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + ReadState = PG_STATE_HEADER; + } + } else { //read next header + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + ReadState = PG_STATE_HEADER; + } + } else { + bContinual = FALSE ; + } + } + //------- Data section Read ------------- + else if (ReadState & PG_STATE_DATA) { + efuse_WordEnableDataRead(hworden, tmpdata, data); + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + ReadState = PG_STATE_HEADER; + } + } + if ( (data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff) && (data[3] == 0xff) && + (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff) && (data[7] == 0xff)) + return FALSE; + else + return TRUE; + +} // efuse_PgPacketRead + + +/* 11/16/2008 MH Write one byte to reald Efuse. */ +static INT32 WriteEFuseByte(struct rtl8192cd_priv *priv, UINT16 addr, UINT8 data) +{ + UINT8 tmpidx = 0; + INT32 bResult; + u4Byte efuseValue = 0; + +// DEBUG_INFO("Addr = %x Data=%x\n", addr, data); + + // -----------------e-fuse reg ctrl --------------------------------- + //address +#if defined(CONFIG_WLAN_HAL_8192EE) + if( GET_CHIP_VER(priv) == VERSION_8192E && !IS_TEST_CHIP(priv) && IS_HARDWARE_TYPE_8192E(priv) && + (_GET_HAL_DATA(priv)->cutVersion != ODM_CUT_A) ) + { + //0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) + RTL_W8(EFUSE_TEST + 1, (RTL_R8(EFUSE_TEST + 1) & 0xf7) | (0x01 << 3)); + RTL_W32(EFUSE_CTRL, 0x90600000|(addr<<8 | data)); + } + else +#endif + { + efuseValue = RTL_R32(EFUSE_CTRL); + efuseValue |= (BIT21|BIT31); + efuseValue &= ~(0x3FFFF); + efuseValue |= ((addr<<8 | data) & 0x3FFFF); + RTL_W32(EFUSE_CTRL, efuseValue); + +#if 0 + RTL_W8( EFUSE_CTRL + 1, (UINT8)(addr & 0xff)); + RTL_W8( EFUSE_CTRL + 2, (RTL_R8(EFUSE_CTRL + 2) & 0xFC ) | (UINT8)((addr >> 8) & 0x03)); + RTL_W8( EFUSE_CTRL, data);//data + + RTL_W8( EFUSE_CTRL + 3, 0xF2 ); //write cmd +#endif + } + + while ((0x80 & RTL_R8(EFUSE_CTRL + 3)) && (tmpidx < 100) ) { + delay_ms(1); + tmpidx++; + } + + if (tmpidx < 100) { + bResult = TRUE; + } else { + bResult = FALSE; + } + +#if defined(CONFIG_WLAN_HAL_8192EE) + if( GET_CHIP_VER(priv) == VERSION_8192E ) + { + if (!IS_TEST_CHIP(priv) && IS_HARDWARE_TYPE_8192E(priv) && + ( _GET_HAL_DATA(priv)->cutVersion != ODM_CUT_A ) ) + { + //0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8]) + RTL_W8(EFUSE_TEST + 1, (RTL_R8(EFUSE_TEST + 1) & 0xf7) | (0x00 << 3)); + } + } +#endif + + return bResult; +} // + + +/*----------------------------------------------------------------------------- + * Function: efuse_WordEnableDataWrite + * + * Overview: Write necessary word unit into current efuse section! + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/16/2008 MHC Reorganize Efuse operate flow!!. + * + *---------------------------------------------------------------------------*/ +static UINT8 efuse_WordEnableDataWrite(struct rtl8192cd_priv *priv, + UINT16 efuse_addr, UINT8 word_en, UINT8 *data) +{ + UINT16 tmpaddr = 0; + UINT16 start_addr = efuse_addr; + UINT8 badworden = 0x0F; + UINT8 tmpdata[8]; + + //memset(tmpdata,0xff,PGPKT_DATA_SIZE); + memset(tmpdata, 0xff, PGPKT_DATA_SIZE); + DEBUG_INFO("word_en = %x efuse_addr=%x\n", word_en, efuse_addr); + + if (!(word_en & BIT(0))) { + tmpaddr = start_addr; + WriteEFuseByte(priv, start_addr++, data[0]); + WriteEFuseByte(priv, start_addr++, data[1]); + ReadEFuseByte(priv, tmpaddr, &tmpdata[0]); + ReadEFuseByte(priv, tmpaddr + 1, &tmpdata[1]); + if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) { + badworden &= (~ BIT(0)); + } + } + if (!(word_en & BIT(1))) { + tmpaddr = start_addr; + WriteEFuseByte(priv, start_addr++, data[2]); + WriteEFuseByte(priv, start_addr++, data[3]); + ReadEFuseByte(priv, tmpaddr , &tmpdata[2]); + ReadEFuseByte(priv, tmpaddr + 1, &tmpdata[3]); + if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) { + badworden &= ( ~ BIT(1)); + } + } + if (!(word_en & BIT(2))) { + tmpaddr = start_addr; + WriteEFuseByte(priv, start_addr++, data[4]); + WriteEFuseByte(priv, start_addr++, data[5]); + ReadEFuseByte(priv, tmpaddr, &tmpdata[4]); + ReadEFuseByte(priv, tmpaddr + 1, &tmpdata[5]); + if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) { + badworden &= ( ~ BIT(2)); + } + } + if (!(word_en & BIT(3))) { + tmpaddr = start_addr; + WriteEFuseByte(priv, start_addr++, data[6]); + WriteEFuseByte(priv, start_addr++, data[7]); + ReadEFuseByte(priv, tmpaddr, &tmpdata[6]); + ReadEFuseByte(priv, tmpaddr + 1, &tmpdata[7]); + if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) { + badworden &= ( ~ BIT(3)); + } + } + return badworden; +} // efuse_WordEnableDataWrite + + +// +// Description: +// This routine will calculate current shadow map that +// how much bytes needs to be updated. +// +// Assumption: +// We shall call this routine before programming physical Efuse content. +// +// Return Value: +// TRUE: Efuse has enough capacity to program. +// FALSE: Efuse do NOT has enough capacity to program. +// +// Created by Roger, 2008.04.21. +// +static int EFUSE_ShadowUpdateChk(struct rtl8192cd_priv *priv) +{ + UINT8 SectionIdx, i, Base; + UINT16 WordsNeed = 0, HdrNum = 0, TotalBytes = 0, EfuseUsed = 0; + UINT8 bWordChanged, bResult = TRUE; + + // Efuse contain total 16 sections. + for (SectionIdx = 0; SectionIdx < priv->EfuseMaxSection; SectionIdx++) { + Base = SectionIdx * 8; + bWordChanged = FALSE; + + // One section contain 4 words = 8 bytes. + for (i = 0; i < 8; i = i + 2) { + if ((priv->EfuseMap[EFUSE_INIT_MAP][Base + i] != priv->EfuseMap[EFUSE_MODIFY_MAP][Base + i]) || + (priv->EfuseMap[EFUSE_INIT_MAP][Base + i + 1] != priv->EfuseMap[EFUSE_MODIFY_MAP][Base + i + 1])) { + WordsNeed++; + bWordChanged = TRUE; + } + } + + // We shall append Efuse header If any WORDs changed in this section. + if (bWordChanged == TRUE) { + if (SectionIdx >= EFUSE_MAX_SECTION_BASE) + HdrNum += 2; + else + HdrNum++; + } + } + + TotalBytes = HdrNum + WordsNeed * 2; + EfuseUsed = priv->EfuseUsedBytes; + + // Calculate whether updated map has enough capacity. + if ((TotalBytes + EfuseUsed) >= (priv->EfuseRealContentLen - priv->EfuseOobProtectBytes)) + bResult = FALSE; + + DEBUG_INFO("EFUSE_ShadowUpdateChk(): TotalBytes(%#x), HdrNum(%#x), WordsNeed(%#x), EfuseUsed(%d)\n", + TotalBytes, HdrNum, WordsNeed, EfuseUsed); + + return bResult; +} + + +/*----------------------------------------------------------------------------- + * Function: efuse_PgPacketWrite + * + * Overview: Send A G package for different section in real efuse area. + * For 92S, One PG package contain 8 bytes content and 4 word + * unit. PG header = 0x[bit7-4=offset][bit3-0word enable] + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/16/2008 MHC Reorganize code Arch and assign as local API. + * + *---------------------------------------------------------------------------*/ +static int efuse_PgPacketWrite(struct rtl8192cd_priv *priv, + UINT8 offset, UINT8 word_en, UINT8 *data) +{ + UINT8 WriteState = PG_STATE_HEADER; + INT32 bContinual = TRUE, bDataEmpty = TRUE, bResult = TRUE, bExtendedHeader = FALSE; + UINT16 efuse_addr = 0; + UINT8 efuse_data, pg_header = 0, pg_header_temp = 0; + + UINT8 tmp_word_cnts = 0, target_word_cnts = 0; + UINT8 tmp_header, match_word_en, tmp_word_en; + + PGPKT_STRUCT target_pkt; + PGPKT_STRUCT tmp_pkt; + + UINT8 originaldata[sizeof(UINT8) * 8]; + UINT8 tmpindex = 0, badworden = 0x0F; + static INT32 repeat_times = 0; + + // + // Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. + // So we have to prevent unexpected data string connection, which will cause + // incorrect data auto-load from HW. The total size is equal or smaller than 498bytes + // (i.e., offset 0~497, and dummy 1bytes) expected after CP test. + // 2009.02.19. + // + if ( efuse_GetCurrentSize(priv) >= (priv->EfuseRealContentLen - priv->EfuseOobProtectBytes)) { + DEBUG_INFO ("efuse_PgPacketWrite error \n"); + return FALSE; + } + + tmp_pkt.offset = 0; + tmp_pkt.word_en = 0; + // Init the 8 bytes content as 0xff + target_pkt.offset = offset; + target_pkt.word_en = word_en; + memset(target_pkt.data, 0xFF, sizeof(UINT8) * 8); + + efuse_WordEnableDataRead(word_en, data, target_pkt.data); + target_word_cnts = efuse_CalculateWordCnts(target_pkt.word_en); + + // + // Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. + // So we have to prevent unexpected data string connection, which will cause + // incorrect data auto-load from HW. Dummy 1bytes is additional. + // 2009.02.19. + // + while ( bContinual && (efuse_addr < (priv->EfuseRealContentLen - priv->EfuseOobProtectBytes)) ) { + if (WriteState == PG_STATE_HEADER) { + bDataEmpty = TRUE; + badworden = 0x0F; + //************ so ******************* + DEBUG_INFO("EFUSE PG_STATE_HEADER\n"); + ReadEFuseByte(priv, efuse_addr , &efuse_data); + if (efuse_data != 0xFF) { + if ((efuse_data & 0x1F) == 0x0F) { //extended header + tmp_header = efuse_data; + efuse_addr++; + ReadEFuseByte(priv, efuse_addr , &efuse_data); + if ((efuse_data & 0x0F) == 0x0F) { //wren fail + efuse_addr++; + continue; + } else { + tmp_pkt.offset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1); + tmp_pkt.word_en = efuse_data & 0x0F; + } + } else { + tmp_header = efuse_data; + tmp_pkt.offset = (tmp_header >> 4) & 0x0F; + tmp_pkt.word_en = tmp_header & 0x0F; + } + + tmp_word_cnts = efuse_CalculateWordCnts(tmp_pkt.word_en); + + //************ so-1 ******************* + if (tmp_pkt.offset != target_pkt.offset) { + efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; //Next pg_packet +#ifdef EFUSE_ERROE_HANDLE + WriteState = PG_STATE_HEADER; +#endif + } else { + //************ so-2 ******************* + for (tmpindex = 0 ; tmpindex < (tmp_word_cnts * 2) ; tmpindex++) { + ReadEFuseByte(priv, (efuse_addr + 1 + tmpindex) , &efuse_data); + if (efuse_data != 0xFF) + bDataEmpty = FALSE; + } + //************ so-2-1 ******************* + if (bDataEmpty == FALSE) { + efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; //Next pg_packet +#ifdef EFUSE_ERROE_HANDLE + WriteState = PG_STATE_HEADER; +#endif + } else { + //************ so-2-2 ******************* + match_word_en = 0x0F; + if ( !( (target_pkt.word_en & BIT(0)) | (tmp_pkt.word_en & BIT(0)) )) { + match_word_en &= (~ BIT(0)); + } + if ( !( (target_pkt.word_en & BIT(1)) | (tmp_pkt.word_en & BIT(1)) )) { + match_word_en &= (~ BIT(1)); + } + if ( !( (target_pkt.word_en & BIT(2)) | (tmp_pkt.word_en & BIT(2)) )) { + match_word_en &= (~ BIT(2)); + } + if ( !( (target_pkt.word_en & BIT(3)) | (tmp_pkt.word_en & BIT(3)) )) { + match_word_en &= (~ BIT(3)); + } + + //************ so-2-2-A ******************* + if ((match_word_en & 0x0F) != 0x0F) { + badworden = efuse_WordEnableDataWrite(priv, efuse_addr + 1, tmp_pkt.word_en , target_pkt.data); + + //************ so-2-2-A-1 ******************* + if (0x0F != (badworden & 0x0F)) { + UINT8 reorg_offset = offset; + UINT8 reorg_worden = badworden; + efuse_PgPacketWrite(priv, reorg_offset, reorg_worden, originaldata); + } + + tmp_word_en = 0x0F; + if ( (target_pkt.word_en & BIT(0)) ^ (match_word_en & BIT(0)) ) { + tmp_word_en &= (~ BIT(0)); + } + if ( (target_pkt.word_en & BIT(1)) ^ (match_word_en & BIT(1)) ) { + tmp_word_en &= (~ BIT(1)); + } + if ( (target_pkt.word_en & BIT(2)) ^ (match_word_en & BIT(2)) ) { + tmp_word_en &= (~ BIT(2)); + } + if ( (target_pkt.word_en & BIT(3)) ^ (match_word_en & BIT(3)) ) { + tmp_word_en &= (~ BIT(3)); + } + + //************ so-2-2-A-2 ******************* + if ((tmp_word_en & 0x0F) != 0x0F) { + //reorganize other pg packet + efuse_addr = efuse_GetCurrentSize(priv); + target_pkt.offset = offset; + target_pkt.word_en = tmp_word_en; + } else { + bContinual = FALSE; + } +#ifdef EFUSE_ERROE_HANDLE + WriteState = PG_STATE_HEADER; + repeat_times++; + if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { + bContinual = FALSE; + bResult = FALSE; + } +#endif + } else { //************ so-2-2-B ******************* + //reorganize other pg packet + efuse_addr = efuse_addr + (2 * tmp_word_cnts) + 1; //next pg packet addr + target_pkt.offset = offset; + target_pkt.word_en = target_pkt.word_en; +#ifdef EFUSE_ERROE_HANDLE + WriteState = PG_STATE_HEADER; +#endif + } + } + } + DEBUG_INFO("EFUSE PG_STATE_HEADER-1\n"); + } else { + //************ s1: header == oxff ******************* + bExtendedHeader = FALSE; + + if (target_pkt.offset >= EFUSE_MAX_SECTION_BASE) { + pg_header = ((target_pkt.offset & 0x07) << 5) | 0x0F; + + DEBUG_INFO("efuse_PgPacketWrite extended pg_header[2:0] |0x0F 0x%x \n", pg_header); + + WriteEFuseByte(priv, efuse_addr, pg_header); + ReadEFuseByte(priv, efuse_addr, &tmp_header); + + while (tmp_header == 0xFF) { + DEBUG_INFO("efuse_PgPacketWrite extended pg_header[2:0] wirte fail \n"); + + repeat_times++; + + if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { + bContinual = FALSE; + bResult = FALSE; + efuse_addr++; + break; + } + WriteEFuseByte(priv, efuse_addr, pg_header); + ReadEFuseByte(priv, efuse_addr, &tmp_header); + } + + if (!bContinual) + break; + + if (tmp_header == pg_header) { + efuse_addr++; + pg_header_temp = pg_header; + pg_header = ((target_pkt.offset & 0x78) << 1 ) | target_pkt.word_en; + + DEBUG_INFO("efuse_PgPacketWrite extended pg_header[6:3] | worden 0x%x word_en 0x%x \n", pg_header, target_pkt.word_en); + + WriteEFuseByte(priv, efuse_addr, pg_header); + ReadEFuseByte(priv, efuse_addr, &tmp_header); + + while (tmp_header == 0xFF) { + repeat_times++; + + if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { + bContinual = FALSE; + bResult = FALSE; + break; + } + WriteEFuseByte(priv, efuse_addr, pg_header); + ReadEFuseByte(priv, efuse_addr, &tmp_header); + } + + if (!bContinual) + break; + + if ((tmp_header & 0x0F) == 0x0F) { //wren PG fail + repeat_times++; + + if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { + bContinual = FALSE; + bResult = FALSE; + break; + } else { + efuse_addr++; + continue; + } + } else if (pg_header != tmp_header) { //offset PG fail + bExtendedHeader = TRUE; + tmp_pkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1); + tmp_pkt.word_en = tmp_header & 0x0F; + tmp_word_cnts = efuse_CalculateWordCnts(tmp_pkt.word_en); + } + } else if ((tmp_header & 0x1F) == 0x0F) { //wrong extended header + efuse_addr += 2; + continue; + } + } else { + pg_header = ((target_pkt.offset << 4) & 0xf0) | target_pkt.word_en; + WriteEFuseByte(priv, efuse_addr, pg_header); + ReadEFuseByte(priv, efuse_addr, &tmp_header); + } + if (tmp_header == pg_header) { //************ s1-1******************* + WriteState = PG_STATE_DATA; + } else +#ifdef EFUSE_ERROE_HANDLE + if (tmp_header == 0xFF) { //************ s1-3: if Write or read func doesn't work ******************* + //efuse_addr doesn't change + WriteState = PG_STATE_HEADER; + repeat_times++; + if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { + bContinual = FALSE; + bResult = FALSE; + } + } else +#endif + { + //************ s1-2 : fixed the header procedure ******************* + if (!bExtendedHeader) { + tmp_pkt.offset = (tmp_header >> 4) & 0x0F; + tmp_pkt.word_en = tmp_header & 0x0F; + tmp_word_cnts = efuse_CalculateWordCnts(tmp_pkt.word_en); + } + + //************ s1-2-A :cover the exist data ******************* + //memset(originaldata,0xff,sizeof(UINT8)*8); + memset(originaldata, 0xff, sizeof(UINT8) * 8); + + if (efuse_PgPacketRead( priv, tmp_pkt.offset, originaldata)) { //check if data exist + badworden = efuse_WordEnableDataWrite(priv, efuse_addr + 1, tmp_pkt.word_en, originaldata); + if (0x0F != (badworden & 0x0F)) { + UINT8 reorg_offset = tmp_pkt.offset; + UINT8 reorg_worden = badworden; + efuse_PgPacketWrite(priv, reorg_offset, reorg_worden, originaldata); + efuse_addr = efuse_GetCurrentSize(priv); + } else { + efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; //Next pg_packet + } + } else { + //************ s1-2-B: wrong address******************* + efuse_addr = efuse_addr + (tmp_word_cnts * 2) + 1; //Next pg_packet + } + +#ifdef EFUSE_ERROE_HANDLE + WriteState = PG_STATE_HEADER; + repeat_times++; + if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { + bContinual = FALSE; + bResult = FALSE; + } +#endif + DEBUG_INFO("EFUSE PG_STATE_HEADER-2\n"); + } + + } + } + //write data state + else if (WriteState == PG_STATE_DATA) { + //************ s1-1 ******************* + DEBUG_INFO("EFUSE PG_STATE_DATA\n"); + badworden = 0x0f; + badworden = efuse_WordEnableDataWrite(priv, efuse_addr + 1, target_pkt.word_en, target_pkt.data); + if ((badworden & 0x0F) == 0x0F) { + //************ s1-1-A ******************* + bContinual = FALSE; + } else { + //reorganize other pg packet //************ s1-1-B ******************* + efuse_addr = efuse_addr + (2 * target_word_cnts) + 1; //next pg packet addr + //=========================== + target_pkt.offset = offset; + target_pkt.word_en = badworden; + target_word_cnts = efuse_CalculateWordCnts(target_pkt.word_en); + //=========================== +#ifdef EFUSE_ERROE_HANDLE + WriteState = PG_STATE_HEADER; + repeat_times++; + if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { + bContinual = FALSE; + bResult = FALSE; + } +#endif + DEBUG_INFO("EFUSE PG_STATE_HEADER-3\n"); + } + } + } + + if (efuse_addr >= (priv->EfuseRealContentLen - priv->EfuseOobProtectBytes)) { + DEBUG_INFO("efuse_PgPacketWrite(): efuse_addr(%#x) Out of size!!\n", efuse_addr); + } + + return TRUE; +} // efuse_PgPacketWrite + + +/*----------------------------------------------------------------------------- + * Function: EFUSE_ShadowUpdate + * + * Overview: Compare init and modify map to update Efuse!!!!! + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/12/2008 MHC Create Version 0. + * 12/11/2008 MHC 92SE PH workaround to prevent HW autoload fail. + * 12/30/2008 Roger Fix the bug that EFUSE will writed out-of boundary. + * 02/16/2009 Roger Revise PCIe autoload fail case and compatible with USB interface to + * overcome MP issue. + * + *---------------------------------------------------------------------------*/ +static int EFUSE_ShadowUpdate(struct rtl8192cd_priv *priv) +{ + UINT16 i, offset, base = 0; + UINT8 word_en = 0x0F; + + // + // We have to check whether current Efuse capacity is big enough to program!! + // 2009.04.21. + // + if (!EFUSE_ShadowUpdateChk(priv)) { + // + // We shall reload current Efuse all map and synchronize current modified + // map to prevent inconsistent Efuse content. + // 2009.04.21. + // + EFUSE_ShadowMapUpdate(priv); + DEBUG_INFO("<---EFUSE_ShadowUpdate(): Efuse out of capacity!!\n"); + return FALSE; + } + // For Efuse write action, we must enable LDO2.5V and 40MHZ clk. + efuse_PowerSwitch(priv, TRUE, TRUE); + + // + // Efuse support 16 write are with PG header packet!!!! + // + for (offset = 0; offset < priv->EfuseMaxSection; offset++) { + // From section(0) to section(15) sequential write. + word_en = 0x0F; + base = offset * 8; + // + // Decide Word Enable Bit for the Efuse section + // One section contain 4 words = 8 bytes!!!!! + // + for (i = 0; i < 8; i++) { + if (priv->EfuseMap[EFUSE_INIT_MAP][base + i] != priv->EfuseMap[EFUSE_MODIFY_MAP][base + i]) { + word_en &= ~(BIT(i / 2)); + DEBUG_INFO("Section(%#x) Addr[%x] %x update to %x, Word_En=%02x\n", + offset, base + i, priv->EfuseMap[EFUSE_INIT_MAP][base + i], priv->EfuseMap[EFUSE_MODIFY_MAP][base + i], word_en); + } + } + + // + // This section will need to update, call Efuse real write section !!!! + // + if (word_en != 0x0F) { + UINT8 tmpdata[8]; + memcpy(tmpdata, (&priv->EfuseMap[EFUSE_MODIFY_MAP][base]), 8); + + // + // Break programming process if efuse capacity is NOT available. + // 2009.04.20. + // + if (!efuse_PgPacketWrite(priv, (UINT8)offset, word_en, tmpdata)) { + DEBUG_INFO("EFUSE_ShadowUpdate(): PG section(%#x) fail!!\n", offset); + break; + } + } + } + + // For warm reboot, we must resume Efuse clock to 500K. + efuse_PowerSwitch(priv, TRUE, FALSE); + + // + // We update both init shadow map again and modified map + // while WPG do loading operation after previous programming. + // 2008.12.30. + // + EFUSE_ShadowMapUpdate(priv); + + ReadTxPowerInfoFromHWPG(priv); + ReadThermalMeterFromEfuse(priv); +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + ReadCrystalCalibrationFromEfuse(priv); + ReadDeltaValFromEfuse(priv); + ReadTRSWPAPEFromEfuse(priv); + } +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv)==VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv)==VERSION_8192E)) + ReadCrystalCalibrationFromEfuse(priv); +#endif + + DEBUG_INFO ("<---EFUSE_ShadowUpdate()\n"); + return TRUE; +} // EFUSE_ShadowUpdate + + +static void shadowMapWrite(struct rtl8192cd_priv *priv, int type, char *value, unsigned char *hwinfo) +{ + int i, offset ; + offset = getEEPROMOffset(priv, type); + + if (offset < 0) + return; + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + if (offset == EEPROM_MACADDRESS) { + for (i = 0; i < MACADDRLEN; i++) { + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + } else if (offset == EEPROM_THERMAL_METER) { + get_array_val(hwinfo + offset, value, 2); + } else { + get_array_val(hwinfo + offset, value, 2); + get_array_val(hwinfo + offset + 1, value + 3 * 2, 2); + get_array_val(hwinfo + offset + 2, value + 9 * 2, 2); + } + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (offset == 0 || offset == 0x32) { + for (i = 0; i < 0x32; i++) { + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + } else if (offset == EEPROM_MAC0_MACADDRESS || offset == EEPROM_MAC1_MACADDRESS) { + for (i = 0; i < MACADDRLEN; i++) { + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + } else if (offset == EEPROM_92D_THERMAL_METER || + offset == EEPROM_92D_TRSW_CTRL || + offset == EEPROM_92D_PAPE_CTRL || + offset == EEPROM_92D_XTAL_K ) { + get_array_val(hwinfo + offset, value, 2); + } else if ((offset == EEPROM_2G_TxPowerCCK) || + (offset == EEPROM_2G_TxPowerCCK + 3) || + (offset == EEPROM_2G_TxPowerHT40_1S) || + (offset == EEPROM_2G_TxPowerHT40_1S + 3) || + (offset == EEPROM_2G_TxPowerHT40_2SDiff) || + (offset == EEPROM_2G_TxPowerHT20Diff) || + (offset == EEPROM_2G_TxPowerOFDMDiff)) { + get_array_val(hwinfo + offset, value, 2); + get_array_val(hwinfo + offset + 1, value + 3 * 2, 2); + get_array_val(hwinfo + offset + 2, value + 9 * 2, 2); + } else if (offset == EEPROM_5GL_TxPowerHT40_1S) { + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT40_1S, value + 35 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT40_1S + 1, value + 45 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT40_1S + 2, value + 55 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT40_1S, value + 99 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT40_1S + 1, value + 113 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT40_1S + 2, value + 127 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT40_1S, value + 148 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT40_1S + 1, value + 154 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT40_1S + 2, value + 160 * 2, 2); + } else if (offset == EEPROM_5GL_TxPowerHT40_1S + 3) { + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT40_1S + 3, value + 35 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT40_1S + 4, value + 45 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT40_1S + 5, value + 55 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT40_1S + 3, value + 99 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT40_1S + 4, value + 113 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT40_1S + 5, value + 127 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT40_1S + 3, value + 148 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT40_1S + 4, value + 154 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT40_1S + 5, value + 160 * 2, 2); + } else if (offset == EEPROM_5GL_TxPowerHT40_2SDiff) { + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT40_2SDiff, value + 35 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT40_2SDiff + 1, value + 45 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT40_2SDiff + 2, value + 55 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT40_2SDiff, value + 99 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT40_2SDiff + 1, value + 113 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT40_2SDiff + 2, value + 127 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT40_2SDiff, value + 148 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT40_2SDiff + 1, value + 154 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT40_2SDiff + 2, value + 160 * 2, 2); + } else if (offset == EEPROM_5GL_TxPowerHT20Diff) { + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT20Diff, value + 35 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT20Diff + 1, value + 45 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerHT20Diff + 2, value + 55 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT20Diff, value + 99 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT20Diff + 1, value + 113 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerHT20Diff + 2, value + 127 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT20Diff, value + 148 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT20Diff + 1, value + 154 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerHT20Diff + 2, value + 160 * 2, 2); + } else if (offset == EEPROM_5GL_TxPowerOFDMDiff) { + get_array_val(hwinfo + EEPROM_5GL_TxPowerOFDMDiff, value + 35 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerOFDMDiff + 1, value + 45 * 2, 2); + get_array_val(hwinfo + EEPROM_5GL_TxPowerOFDMDiff + 2, value + 55 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerOFDMDiff, value + 99 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerOFDMDiff + 1, value + 113 * 2, 2); + get_array_val(hwinfo + EEPROM_5GM_TxPowerOFDMDiff + 2, value + 127 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerOFDMDiff, value + 148 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerOFDMDiff + 1, value + 154 * 2, 2); + get_array_val(hwinfo + EEPROM_5GH_TxPowerOFDMDiff + 2, value + 160 * 2, 2); + } + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (offset == 0 || offset == 0x32) { + for (i = 0; i < 0x32; i++) { + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + } else if (offset == EEPROM_8812_MACADDRESS) { + for (i = 0; i < MACADDRLEN; i++) { + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + } else if (offset == EEPROM_8812_THERMAL_METER || + offset == EEPROM_8812_XTAL_K ) { + get_array_val(hwinfo + offset, value, 2); + } else if ((offset == EEPROM_2G_CCK1T_TxPower + PATHA_OFFSET) || + (offset == EEPROM_2G_CCK1T_TxPower + PATHB_OFFSET) || + (offset == EEPROM_2G_HT401S_TxPower + PATHA_OFFSET) || + (offset == EEPROM_2G_HT401S_TxPower + PATHB_OFFSET) || + (offset == EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET) || + (offset == EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET) || + (offset == EEPROM_2G_OFDM1T_TxPowerDiff + PATHA_OFFSET)) { + get_array_val(hwinfo + offset, value, 2); + get_array_val(hwinfo + offset + 1, value + 3 * 2, 2); + get_array_val(hwinfo + offset + 2, value + 9 * 2, 2); + } else if (offset == EEPROM_5G_HT401S_TxPower + PATHA_OFFSET) { + for (i = 0 ; i < MAX_5G_CHNLGRP ; i++) + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } else if (offset == EEPROM_5G_HT401S_TxPower + PATHB_OFFSET) { + for (i = 0 ; i < MAX_5G_CHNLGRP ; i++) + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } else if (offset == EEPROM_5G_HT201S_TxPowerDiff + PATHA_OFFSET) { + get_array_val(hwinfo + offset, value, 2); + } else if (offset == EEPROM_5G_HT201S_TxPowerDiff + PATHB_OFFSET) { + get_array_val(hwinfo + offset, value, 2); + } else if (offset == EEPROM_5G_HT402S_TxPowerDiff + PATHA_OFFSET) { + get_array_val(hwinfo + offset, value, 2); + } else if (offset == EEPROM_5G_HT402S_TxPowerDiff + PATHB_OFFSET) { + get_array_val(hwinfo + offset, value, 2); + } else if (offset == EEPROM_5G_HT801S_TxPowerDiff + PATHA_OFFSET) { + get_array_val(hwinfo + offset, value, 2); + } else if (offset == EEPROM_5G_HT801S_TxPowerDiff + PATHB_OFFSET) { + get_array_val(hwinfo + offset, value, 2); + } else if (offset == EEPROM_5G_HT802S_TxPowerDiff + PATHA_OFFSET) { + get_array_val(hwinfo + offset, value, 2); + } else if (offset == EEPROM_5G_HT802S_TxPowerDiff + PATHB_OFFSET) { + get_array_val(hwinfo + offset, value, 2); + } else if (offset == EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET) { + for (i = 0 ; i < MAX_2G_CHNLGRP ; i++) + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } else if (offset == EEPROM_2G_HT201S_TxPowerDiff + PATHB_OFFSET) { + for (i = 0 ; i < MAX_2G_CHNLGRP ; i++) + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } else if (offset == EEPROM_2G_HT402S_TxPowerDiff + PATHA_OFFSET) { + for (i = 0 ; i < MAX_2G_CHNLGRP ; i++) + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } else if (offset == EEPROM_2G_HT402S_TxPowerDiff + PATHB_OFFSET) { + for (i = 0 ; i < MAX_2G_CHNLGRP ; i++) + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8188E){ + if (offset == 0 || offset == 0x32) { + for (i = 0; i < 0x32; i++) { + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + }else if (offset == EEPROM_MAC_ADDR_88E) { + for (i = 0; i < MACADDRLEN; i++) { + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + } else if (offset == EEPROM_THERMAL_METER_88E || + offset == EEPROM_XTAL_88E) { + get_array_val(hwinfo + offset, value, 2); + } +#ifdef CONFIG_SDIO_HCI + else if (offset == EEPROM_ChannelPlan_88E) { + get_array_val(hwinfo + offset, value, 2); + } + else if( offset == EEPROM_88E_SDIOTYPE ) { + printk("val=%c\n", *value); + + if ( *value == '2' ) { + hwinfo[offset] = 0x3F; + hwinfo[offset+1] = 0x00; + hwinfo[offset+2] = 0xFF; + hwinfo[offset+3] = 0x02; + hwinfo[offset+4] = 0x32; + hwinfo[offset+5] = 0x00; + hwinfo[offset+6] = 0x00; + } else if ( *value == '3' ) { + hwinfo[offset] = 0x6E; + //hwinfo[offset+1] = 0x51; + hwinfo[offset+1] = 0x50; // no DDR + hwinfo[offset+2] = 0x01; + hwinfo[offset+3] = 0x03; + hwinfo[offset+4] = 0x43; + hwinfo[offset+5] = 0xFF; + hwinfo[offset+6] = 0xFF; + } + } +#endif + else if (offset == EEPROM_TX_PWR_INX_88E){ // CCK_A + get_array_val(hwinfo + offset, value, 2); + get_array_val(hwinfo + offset + 1, value + 2 * 2, 2); + get_array_val(hwinfo + offset + 2, value + 5 * 2, 2); + get_array_val(hwinfo + offset + 3, value + 8 * 2, 2); + get_array_val(hwinfo + offset + 4, value + 11 * 2, 2); + get_array_val(hwinfo + offset + 5, value + 13 * 2, 2); + + } else if (offset == EEPROM_TX_PWR_INX_88E + 6){ // HT40_1S_A + get_array_val(hwinfo + offset, value, 2); + get_array_val(hwinfo + offset + 1, value + 2 * 2, 2); + get_array_val(hwinfo + offset + 2, value + 5 * 2, 2); + get_array_val(hwinfo + offset + 3, value + 8 * 2, 2); + get_array_val(hwinfo + offset + 4, value + 11 * 2, 2); + } else if (offset == EEPROM_TX_PWR_INX_88E + 11){ //DIFF_HT20_OFDM + get_array_val(hwinfo + offset, value, 2); + } + } +#endif + +#if 0 +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv) == VERSION_8192E){ + if (offset == 0 || offset == 0x32) { + for (i = 0; i < 0x32; i++) { + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + }else if (offset == EEPROM_MAC_ADDR_8192EE) { + for (i = 0; i < MACADDRLEN; i++) { + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + } else if (offset == EEPROM_THERMAL_METER_8192E || + offset == EEPROM_XTAL_8192E) { + get_array_val(hwinfo + offset, value, 2); + } else if ((offset == EEPROM_TX_PWR_INX_8192E + PATHA_OFFSET)|| + (offset == EEPROM_TX_PWR_INX_8192E + PATHB_OFFSET)){ // CCK_A and CCK_B + get_array_val(hwinfo + offset, value, 2); + get_array_val(hwinfo + offset + 1, value + 2 * 2, 2); + get_array_val(hwinfo + offset + 2, value + 5 * 2, 2); + get_array_val(hwinfo + offset + 3, value + 8 * 2, 2); + get_array_val(hwinfo + offset + 4, value + 11 * 2, 2); + get_array_val(hwinfo + offset + 5, value + 13 * 2, 2); + + } else if ((offset == EEPROM_TX_PWR_INX_8192E + PATHA_OFFSET + 6)|| + (offset == EEPROM_TX_PWR_INX_8192E + PATHB_OFFSET + 6)){ // HT40_1S_A and HT40_1S_B + get_array_val(hwinfo + offset, value, 2); + get_array_val(hwinfo + offset + 1, value + 2 * 2, 2); + get_array_val(hwinfo + offset + 2, value + 5 * 2, 2); + get_array_val(hwinfo + offset + 3, value + 8 * 2, 2); + get_array_val(hwinfo + offset + 4, value + 11 * 2, 2); + } else if (offset == EEPROM_TX_PWR_INX_8192E + PATHA_OFFSET + 11){ //DIFF_HT20_OFDM + get_array_val(hwinfo + offset, value, 2); + } else if (offset == EEPROM_TX_PWR_INX_8192E + PATHA_OFFSET + 12){ //DIFF_HT40_2S_HT20_2S + get_array_val(hwinfo + offset, value, 2); + } + } +#endif +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv) == VERSION_8192E) + { + if (offset == 0 || offset == 0x32) + { + for (i = 0; i < 0x32; i++) + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + else if (offset == EEPROM_92E_MACADDRESS) + { + for (i = 0; i < MACADDRLEN; i++) + get_array_val(hwinfo + offset + i, value + i * 2, 2); + } + else if (offset == EEPROM_92E_THERMAL_METER || offset == EEPROM_92E_XTAL_K) + { + get_array_val(hwinfo + offset, value, 2); + } + else if ( (offset == EEPROM_2G_CCK1T_TxPower + PATHA_OFFSET) || // CCK_A and CCK_B + (offset == EEPROM_2G_CCK1T_TxPower + PATHB_OFFSET)) + { + get_array_val(hwinfo + offset, value, 2); + get_array_val(hwinfo + offset + 1, value + 2 * 2, 2); + get_array_val(hwinfo + offset + 2, value + 5 * 2, 2); + get_array_val(hwinfo + offset + 3, value + 8 * 2, 2); + get_array_val(hwinfo + offset + 4, value + 11 * 2, 2); + get_array_val(hwinfo + offset + 5, value + 13 * 2, 2); + } + else if ( (offset == EEPROM_2G_HT401S_TxPower + PATHA_OFFSET) || // HT40_1S_A and HT40_1S_B + (offset == EEPROM_2G_HT401S_TxPower + PATHB_OFFSET)) + { + get_array_val(hwinfo + offset, value, 2); + get_array_val(hwinfo + offset + 1, value + 2 * 2, 2); + get_array_val(hwinfo + offset + 2, value + 5 * 2, 2); + get_array_val(hwinfo + offset + 3, value + 8 * 2, 2); + get_array_val(hwinfo + offset + 4, value + 11 * 2, 2); + } + else if( (offset == EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET) || // TX_POWER_DIFF_HT20_A & TX_POWER_DIFF_HT20_OFDM_A + (offset == EEPROM_2G_HT201S_TxPowerDiff + PATHB_OFFSET) || // TX_POWER_DIFF_HT20_B & TX_POWER_DIFF_HT20_OFDM_B + (offset == EEPROM_2G_HT402S_TxPowerDiff + PATHA_OFFSET) || // TX_POWER_DIFF_HT40_2S_A + (offset == EEPROM_2G_HT402S_TxPowerDiff + PATHB_OFFSET)) // TX_POWER_DIFF_HT40_2S_B + { + unsigned char orig_value = hwinfo[offset], + input_value = (unsigned char)_atoi(value, 16); + + if( (strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT20_A") == 0) || // write [7:4] + (strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT20_B") == 0) || + (strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT40_2S_A") == 0) || + (strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT40_2S_B") == 0)) + { + hwinfo[offset] = (orig_value & 0x0f) | ((input_value << 4) & 0xf0); + } + else if((strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT20_OFDM_A") == 0) || // write [3:0] + (strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT20_OFDM_B") == 0)) + { + hwinfo[offset] = (orig_value & 0xf0) | (input_value & 0x0f); + } + } +#ifdef CONFIG_SDIO_HCI + else if( offset == EEPROM_92E_SDIOTYPE ) { + printk("val=%c\n", *value); + + if ( *value == '2' ) { + hwinfo[offset] = 0x3F; + hwinfo[offset+1] = 0x00; + // hwinfo[offset+2] = 0xFF; + hwinfo[offset+3] = 0x02; + hwinfo[offset+4] = 0x23; + hwinfo[offset+5] = 0x00; + hwinfo[offset+6] = 0x00; + } else if ( *value == '3' ) { + hwinfo[offset] = 0x6E; + hwinfo[offset+1] = 0x50; // [0] DDR50=0, avoid Data CRC error issue in DDR50 + // hwinfo[offset+2] = 0xFF; + hwinfo[offset+3] = 0x03; + hwinfo[offset+4] = 0x34; + hwinfo[offset+5] = 0xFF; + hwinfo[offset+6] = 0xFF; + } + } +#endif + #if 0 + else if (offset == 0x02 ) // EFUSE_TEST + { + unsigned char tmp_efuse[priv->EfuseMapLen]; + int is_fail = 0; + int exec_cnt = _atoi(value, 10); + unsigned int j; + + printk("***EFUSE_TEST BEGIN***\n"); + for( j = 0 ; j != exec_cnt ; ++j ) + { + if( (j != 0) && (j % 1000 == 0) ) + printk("EFUSE_TEST execute %d times\n", j); + efuse_ReadAllMap(priv, &tmp_efuse[0]); + if( memcmp(&tmp_efuse[0], &priv->EfuseMap[EFUSE_INIT_MAP][0], priv->EfuseMapLen) != 0 ) + { + is_fail = 1; + break; + } + } + printk("***EFUSE_TEST END***\n"); + + if( is_fail ) + printk("EFUSE_TEST FAIL!!\n"); + else + printk("EFUSE_TEST SUCCESS!!\n"); + } + #endif + } +#endif + + +} + + +static int converToFlashFormat(struct rtl8192cd_priv *priv, unsigned char *out, unsigned char *hwinfo, int type) +{ + int i, offset, len = 0; + offset = getEEPROMOffset(priv, type); + + if (offset < 0) + return 0; + + len += sprintf(out, "%s=", priv->EfuseCmd[type]); + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + if (offset == EEPROM_MACADDRESS) { + for (i = 0; i < MACADDRLEN; i++) { + sprintf(out + len, "%02x", hwinfo[offset + i]); + len += 2; + } + } else if (offset == EEPROM_THERMAL_METER) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } else { + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + if (i < 3) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } else if (i < 9) { + sprintf(out + len, "%02x", hwinfo[offset + 1]); + len += 2; + } else { + sprintf(out + len, "%02x", hwinfo[offset + 2]); + len += 2; + } + } + } + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (offset == EEPROM_MAC0_MACADDRESS || offset == EEPROM_MAC1_MACADDRESS) { + for (i = 0; i < MACADDRLEN; i++) { + sprintf(out + len, "%02x", hwinfo[offset + i]); + len += 2; + } + } else if (offset == EEPROM_92D_THERMAL_METER || + offset == EEPROM_92D_TRSW_CTRL || + offset == EEPROM_92D_PAPE_CTRL || + offset == EEPROM_92D_XTAL_K ) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } else if ((offset == EEPROM_2G_TxPowerCCK) || + (offset == EEPROM_2G_TxPowerCCK + 3) || + (offset == EEPROM_2G_TxPowerHT40_1S) || + (offset == EEPROM_2G_TxPowerHT40_1S + 3) || + (offset == EEPROM_2G_TxPowerHT40_2SDiff) || + (offset == EEPROM_2G_TxPowerHT20Diff) || + (offset == EEPROM_2G_TxPowerOFDMDiff)) { + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + if (i < 3) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } else if (i < 9) { + sprintf(out + len, "%02x", hwinfo[offset + 1]); + len += 2; + } else { + sprintf(out + len, "%02x", hwinfo[offset + 2]); + len += 2; + } + } + } else if (offset == EEPROM_5GL_TxPowerHT40_1S) { + for (i = 0; i < MAX_5G_CHANNEL_NUM; i++) { + if (i >= 35 && i <= 63) { // ch 36 ~ 64 + if (i >= 35 && i <= 43) { // ch 36 ~ 44 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT40_1S]); + len += 2; + } else if (i >= 45 && i <= 53) { // ch 46 ~ 54 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT40_1S + 1]); + len += 2; + } else if (i >= 55 && i <= 63) { // ch 56 ~ 64 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT40_1S + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 99 && i <= 139) { // ch 100 ~ 140 + if (i >= 99 && i <= 111) { // ch 100 ~ 112 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT40_1S]); + len += 2; + } else if (i >= 113 && i <= 125) { // ch 114 ~ 126 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT40_1S + 1]); + len += 2; + } else if (i >= 127 && i <= 139) { // ch 128 ~ 140 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT40_1S + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 148 && i <= 164 ) { // ch 149 ~ 165 + if (i >= 148 && i <= 152) { // ch 149 ~ 153 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT40_1S]); + len += 2; + } else if (i >= 154 && i <= 158) { // ch 155 ~ 159 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT40_1S + 1]); + len += 2; + } else if (i >= 160 && i <= 164) { // ch 161 ~ 165 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT40_1S + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else { + sprintf(out + len, "00"); + len += 2; + } + } + } else if (offset == EEPROM_5GL_TxPowerHT40_1S + 3) { + for (i = 0; i < MAX_5G_CHANNEL_NUM; i++) { + if (i >= 35 && i <= 63) { // ch 36 ~ 64 + if (i >= 35 && i <= 43) { // ch 36 ~ 44 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT40_1S + 3]); + len += 2; + } else if (i >= 45 && i <= 53) { // ch 46 ~ 54 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT40_1S + 4]); + len += 2; + } else if (i >= 55 && i <= 63) { // ch 56 ~ 64 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT40_1S + 5]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 99 && i <= 139) { // ch 100 ~ 140 + if (i >= 99 && i <= 111) { // ch 100 ~ 112 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT40_1S + 3]); + len += 2; + } else if (i >= 113 && i <= 125) { // ch 114 ~ 126 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT40_1S + 4]); + len += 2; + } else if (i >= 127 && i <= 139) { // ch 128 ~ 140 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT40_1S + 5]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 148 && i <= 164 ) { // ch 149 ~ 165 + if (i >= 148 && i <= 152) { // ch 149 ~ 153 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT40_1S + 3]); + len += 2; + } else if (i >= 154 && i <= 158) { // ch 155 ~ 159 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT40_1S + 4]); + len += 2; + } else if (i >= 160 && i <= 164) { // ch 161 ~ 165 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT40_1S + 5]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else { + sprintf(out + len, "00"); + len += 2; + } + } + } else if (offset == EEPROM_5GL_TxPowerHT40_2SDiff) { + for (i = 0; i < MAX_5G_CHANNEL_NUM; i++) { + if (i >= 35 && i <= 63) { // ch 36 ~ 64 + if (i >= 35 && i <= 43) { // ch 36 ~ 44 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT40_2SDiff]); + len += 2; + } else if (i >= 45 && i <= 53) { // ch 46 ~ 54 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT40_2SDiff + 1]); + len += 2; + } else if (i >= 55 && i <= 63) { // ch 56 ~ 64 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT40_2SDiff + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 99 && i <= 139) { // ch 100 ~ 140 + if (i >= 99 && i <= 111) { // ch 100 ~ 112 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT40_2SDiff]); + len += 2; + } else if (i >= 113 && i <= 125) { // ch 114 ~ 126 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT40_2SDiff + 1]); + len += 2; + } else if (i >= 127 && i <= 139) { // ch 128 ~ 140 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT40_2SDiff + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 148 && i <= 164 ) { // ch 149 ~ 165 + if (i >= 148 && i <= 152) { // ch 149 ~ 153 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT40_2SDiff]); + len += 2; + } else if (i >= 154 && i <= 158) { // ch 155 ~ 159 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT40_2SDiff + 1]); + len += 2; + } else if (i >= 160 && i <= 164) { // ch 161 ~ 165 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT40_2SDiff + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else { + sprintf(out + len, "00"); + len += 2; + } + } + } else if (offset == EEPROM_5GL_TxPowerHT20Diff) { + for (i = 0; i < MAX_5G_CHANNEL_NUM; i++) { + if (i >= 35 && i <= 63) { // ch 36 ~ 64 + if (i >= 35 && i <= 43) { // ch 36 ~ 44 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT20Diff]); + len += 2; + } else if (i >= 45 && i <= 53) { // ch 46 ~ 54 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT20Diff + 1]); + len += 2; + } else if (i >= 55 && i <= 63) { // ch 56 ~ 64 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerHT20Diff + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 99 && i <= 139) { // ch 100 ~ 140 + if (i >= 99 && i <= 111) { // ch 100 ~ 112 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT20Diff]); + len += 2; + } else if (i >= 113 && i <= 125) { // ch 114 ~ 126 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT20Diff + 1]); + len += 2; + } else if (i >= 127 && i <= 139) { // ch 128 ~ 140 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerHT20Diff + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 148 && i <= 164 ) { // ch 149 ~ 165 + if (i >= 148 && i <= 152) { // ch 149 ~ 153 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT20Diff]); + len += 2; + } else if (i >= 154 && i <= 158) { // ch 155 ~ 159 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT20Diff + 1]); + len += 2; + } else if (i >= 160 && i <= 164) { // ch 161 ~ 165 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerHT20Diff + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else { + sprintf(out + len, "00"); + len += 2; + } + } + } else if (offset == EEPROM_5GL_TxPowerOFDMDiff) { + for (i = 0; i < MAX_5G_CHANNEL_NUM; i++) { + if (i >= 35 && i <= 63) { // ch 36 ~ 64 + if (i >= 35 && i <= 43) { // ch 36 ~ 44 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerOFDMDiff]); + len += 2; + } else if (i >= 45 && i <= 53) { // ch 46 ~ 54 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerOFDMDiff + 1]); + len += 2; + } else if (i >= 55 && i <= 63) { // ch 56 ~ 64 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GL_TxPowerOFDMDiff + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 99 && i <= 139) { // ch 100 ~ 140 + if (i >= 99 && i <= 111) { // ch 100 ~ 112 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerOFDMDiff]); + len += 2; + } else if (i >= 113 && i <= 125) { // ch 114 ~ 126 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerOFDMDiff + 1]); + len += 2; + } else if (i >= 127 && i <= 139) { // ch 128 ~ 140 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GM_TxPowerOFDMDiff + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else if (i >= 148 && i <= 164 ) { // ch 149 ~ 165 + if (i >= 148 && i <= 152) { // ch 149 ~ 153 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerOFDMDiff]); + len += 2; + } else if (i >= 154 && i <= 158) { // ch 155 ~ 159 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerOFDMDiff + 1]); + len += 2; + } else if (i >= 160 && i <= 164) { // ch 161 ~ 165 + sprintf(out + len, "%02x", hwinfo[EEPROM_5GH_TxPowerOFDMDiff + 2]); + len += 2; + } else { + sprintf(out + len, "00"); + len += 2; + } + } else { + sprintf(out + len, "00"); + len += 2; + } + } + } + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if (offset == EEPROM_8812_MACADDRESS) { + for (i = 0; i < MACADDRLEN; i++) { + sprintf(out + len, "%02x", hwinfo[offset + i]); + len += 2; + } + } else if (offset == EEPROM_8812_THERMAL_METER || + offset == EEPROM_8812_XTAL_K ) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } else if ((offset == EEPROM_2G_CCK1T_TxPower + PATHA_OFFSET) || + (offset == EEPROM_2G_CCK1T_TxPower + PATHB_OFFSET) || + (offset == EEPROM_2G_HT401S_TxPower + PATHA_OFFSET) || + (offset == EEPROM_2G_HT401S_TxPower + PATHB_OFFSET) ) { + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + int chnl_gp = find_2gchnlgroup(i); + + if (chnl_gp > -1) { + sprintf(out + len, "%02x", hwinfo[offset + chnl_gp]); + len += 2; + } else { + sprintf(out + len, "%02x", 0); + len += 2; + } + } + } else if (offset == EEPROM_5G_HT401S_TxPower + PATHA_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + sprintf(out + len, "%02x", hwinfo[offset + i]); + len += 2; + } + } else if (offset == EEPROM_5G_HT401S_TxPower + PATHB_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + sprintf(out + len, "%02x", hwinfo[offset + i]); + len += 2; + } + } else if (offset == EEPROM_5G_HT201S_TxPowerDiff + PATHA_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_5G_HT201S_TxPowerDiff + PATHB_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_5G_HT402S_TxPowerDiff + PATHA_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_5G_HT402S_TxPowerDiff + PATHB_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_5G_HT801S_TxPowerDiff + PATHA_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_5G_HT801S_TxPowerDiff + PATHB_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_5G_HT802S_TxPowerDiff + PATHA_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_5G_HT802S_TxPowerDiff + PATHB_OFFSET) { + for (i = 0; i < MAX_5G_CHNLGRP; i++) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET) { + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_2G_HT201S_TxPowerDiff + PATHB_OFFSET) { + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_2G_HT402S_TxPowerDiff + PATHA_OFFSET) { + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } else if (offset == EEPROM_2G_HT402S_TxPowerDiff + PATHA_OFFSET) { + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8188E){ + if (offset == EEPROM_MAC_ADDR_88E) { + for (i = 0; i < MACADDRLEN; i++) { + sprintf(out + len, "%02x", hwinfo[offset + i]); + len += 2; + } + } else if (offset == EEPROM_THERMAL_METER_88E || + offset == EEPROM_XTAL_88E) { + + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } +#ifdef CONFIG_SDIO_HCI + else if (offset == EEPROM_ChannelPlan_88E) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } +#endif + else if (offset == EEPROM_TX_PWR_INX_88E || // CCK_A + offset == EEPROM_TX_PWR_INX_88E + 6){ // HT40_1S_A + + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + if (i < 2) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } else if (i < 5) { + sprintf(out + len, "%02x", hwinfo[offset + 1]); + len += 2; + } else if (i < 8) { + sprintf(out + len, "%02x", hwinfo[offset + 2]); + len += 2; + } else if (i < 11) { + sprintf(out + len, "%02x", hwinfo[offset + 3]); + len += 2; + } else if (i < 13) { + sprintf(out + len, "%02x", hwinfo[offset + 4]); + len += 2; + } else { + if( offset == EEPROM_TX_PWR_INX_88E) + sprintf(out + len, "%02x", hwinfo[offset + 5]); + else + sprintf(out + len, "%02x", hwinfo[offset + 4]); + len += 2; + } + } + } + else if (offset == EEPROM_TX_PWR_INX_88E + 11 ){ // DIFF_HT20_OFDM + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } +#ifdef CONFIG_SDIO_HCI + else if ( offset == EEPROM_88E_SDIOTYPE ) { + for( i = 0 ; i < SDIOTYPELEN; i++ ) + len += sprintf(out + len, "%02x", hwinfo[offset + i]); + } +#endif + + } +#endif + +#if defined(CONFIG_WLAN_HAL_8192EE) + if ( GET_CHIP_VER(priv)==VERSION_8192E ) + { + switch(offset) + { + case EEPROM_2G_CCK1T_TxPower + PATHA_OFFSET: // HW_TX_POWER_CCK_A + case EEPROM_2G_CCK1T_TxPower + PATHB_OFFSET: // HW_TX_POWER_CCK_B + for ( i = 0; i < MAX_2G_CHANNEL_NUM ; i++ ) + { + int ch_gp = find_2gchnlgroup(i); + if(ch_gp > -1) + len += sprintf(out + len, "%02x", hwinfo[offset + ch_gp]); + } + break; + case EEPROM_2G_HT401S_TxPower + PATHA_OFFSET: // HW_TX_POWER_HT40_1S_A + case EEPROM_2G_HT401S_TxPower + PATHB_OFFSET: // HW_TX_POWER_HT40_1S_B + for ( i = 0; i < MAX_2G_CHANNEL_NUM ; i++ ) + { + int ch_gp = find_2gchnlgroup(i); + if(ch_gp > -1) + { + if(i == 13) + ch_gp -= 1; + len += sprintf(out + len, "%02x", hwinfo[offset + ch_gp]); + } + } + break; + case EEPROM_2G_HT201S_TxPowerDiff + PATHA_OFFSET: // HW_TX_POWER_DIFF_HT20_A and HW_TX_POWER_DIFF_HT20_OFDM_A + for ( i = 0; i < MAX_2G_CHANNEL_NUM ; i++ ) + { + if( strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT20_A") == 0 ) + len += sprintf(out + len, "%02x", (hwinfo[offset]&0xf0) >> 4); + else if( strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT20_OFDM_A") == 0 ) + len += sprintf(out + len, "%02x", (hwinfo[offset]&0x0f) ); + } + break; + case EEPROM_2G_HT201S_TxPowerDiff + PATHB_OFFSET: // HW_TX_POWER_DIFF_HT20_B and HW_TX_POWER_DIFF_HT20_OFDM_B + for ( i = 0; i < MAX_2G_CHANNEL_NUM ; i++ ) + { + if( strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT20_B") == 0 ) + len += sprintf(out + len, "%02x", (hwinfo[offset]&0xf0)); + else if( strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT20_OFDM_B") == 0 ) + len += sprintf(out + len, "%02x", (hwinfo[offset]&0x0f) << 4 ); + } + break; + case EEPROM_2G_HT402S_TxPowerDiff + PATHA_OFFSET: // HW_TX_POWER_DIFF_HT40_2S_A + case EEPROM_2G_HT402S_TxPowerDiff + PATHB_OFFSET: // HW_TX_POWER_DIFF_HT40_2S_B + for ( i = 0; i < MAX_2G_CHANNEL_NUM ; i++ ) + { + if( strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT40_2S_A") == 0 ) + len += sprintf(out + len, "%02x", (hwinfo[offset]&0xf0) >> 4); + else if( strcmp(priv->EfuseCmd[type], "HW_TX_POWER_DIFF_HT40_2S_B") == 0 ) + len += sprintf(out + len, "%02x", (hwinfo[offset]&0xf0)); + } + break; + case EEPROM_92E_MACADDRESS: // HW_WLAN0_WLAN_ADDR + for( i = 0 ; i < MACADDRLEN ; i++ ) + len += sprintf(out + len, "%02x", hwinfo[offset + i]); + break; + case EEPROM_92E_THERMAL_METER: // HW_11N_THER + case EEPROM_92E_XTAL_K: // HW_11N_XCAP + len += sprintf(out + len, "%02x", hwinfo[offset]); + break; +#ifdef CONFIG_SDIO_HCI + case EEPROM_92E_SDIOTYPE: + for( i = 0 ; i < SDIOTYPELEN; i++ ) + len += sprintf(out + len, "%02x", hwinfo[offset + i]); + break; +#endif + default: + break; + } + } +#endif + +#if 0 +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv) == VERSION_8192E){ + if (offset == EEPROM_MAC_ADDR_8192EE) { + for (i = 0; i < MACADDRLEN; i++) { + sprintf(out + len, "%02x", hwinfo[offset + i]); + len += 2; + } + } else if (offset == EEPROM_THERMAL_METER_8192E || + offset == EEPROM_XTAL_8192E) { + + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } else if ((offset == EEPROM_TX_PWR_INX_8192E + PATHA_OFFSET)|| // CCK_A + (offset == EEPROM_TX_PWR_INX_8192E + PATHB_OFFSET)|| // CCK_B + (offset == EEPROM_TX_PWR_INX_8192E + PATHA_OFFSET + 6)|| // HT40_1S_A + (offset == EEPROM_TX_PWR_INX_8192E + PATHB_OFFSET + 6)){ // HT40_1S_B + + for (i = 0; i < MAX_2G_CHANNEL_NUM; i++) { + if (i < 2) { + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } else if (i < 5) { + sprintf(out + len, "%02x", hwinfo[offset + 1]); + len += 2; + } else if (i < 8) { + sprintf(out + len, "%02x", hwinfo[offset + 2]); + len += 2; + } else if (i < 11) { + sprintf(out + len, "%02x", hwinfo[offset + 3]); + len += 2; + } else if (i < 13) { + sprintf(out + len, "%02x", hwinfo[offset + 4]); + len += 2; + } else { + if((offset == EEPROM_TX_PWR_INX_8192E + PATHA_OFFSET)|| // CCK_A + (offset == EEPROM_TX_PWR_INX_8192E + PATHB_OFFSET)) // CCK_B + sprintf(out + len, "%02x", hwinfo[offset + 5]); + else + sprintf(out + len, "%02x", hwinfo[offset + 4]); + len += 2; + } + } + } + else if (offset == EEPROM_TX_PWR_INX_8192E + PATHA_OFFSET + 11 ){ // DIFF_HT20_OFDM + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + else if (offset == EEPROM_TX_PWR_INX_8192E + PATHA_OFFSET + 12 ){ // DIFF_HT40_2S_HT20_2S + sprintf(out + len, "%02x", hwinfo[offset]); + len += 2; + } + } +#endif +#endif + + out[len] = '\0'; + return len + 1; +} + + +int efuse_get(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int j, len; +#if 0 +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) + para_num = EFUSECMD_NUM_92C; +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8192D) + para_num = EFUSECMD_NUM_92D; +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) + para_num = EFUSECMD_NUM_8812; +#endif +#if defined(CONFIG_RTL_88E_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E) + para_num = EFUSECMD_NUM_88E; +#endif +#if defined(CONFIG_WLAN_HAL_8192EE) + if (GET_CHIP_VER(priv) == VERSION_8192E) + para_num = EFUSECMD_NUM_92E; +#endif +#endif + + for( j = 0 ; j < priv->EfuseCmdNum ; j++ ) + { + if (strcmp(data, priv->EfuseCmd[j]) == 0) + { + len = converToFlashFormat(priv, data, &(priv->EfuseMap[EFUSE_INIT_MAP][0]), j); + //printk("%s\n", data); + return len; + } + } + return 0; +} + + +int efuse_set(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char *val; + int j; +#if 0 +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) + para_num = EFUSECMD_NUM_92C; +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + if ((GET_CHIP_VER(priv) == VERSION_8192D) || (GET_CHIP_VER(priv) == VERSION_8812E)) + para_num = EFUSECMD_NUM_92D; +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + para_num = EFUSECMD_NUM_88E; +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + para_num = EFUSECMD_NUM_92E; +#endif +#endif + + for( j = 0 ; j < priv->EfuseCmdNum ; j++ ) + { + val = get_value_by_token(data, priv->EfuseCmd[j]); + if(val) + shadowMapWrite(priv, j, val + 1, &(priv->EfuseMap[EFUSE_MODIFY_MAP][0])); + } + return 0; +} + + +int efuse_sync(struct rtl8192cd_priv *priv, unsigned char *data) +{ + DEBUG_INFO("efuse sync\n"); + EFUSE_ShadowUpdate(priv); + return 0; +} + +#ifdef RTK_NL80211 +void read_efuse_mac_address(struct rtl8192cd_priv *priv,char * efusemac) +{ + u16 efuse_MAC = 0; + if(!efusemac) + return; + + EfuseInit(priv); + if (EfuseMapAlloc(priv) == FAIL) { + printk(KERN_ERR "%s: can't allocate efuse map\n", __func__); + return -ENOMEM; + } + + if (EfuseCmdInit(priv) == FAIL) { + printk(KERN_ERR "%s: can't allocate efuse cmd\n", __func__); + return -ENOMEM; + } + + EFUSE_ShadowMapUpdate(priv); +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188C) || (GET_CHIP_VER(priv) == VERSION_8192C)) { + efuse_MAC = EEPROM_MACADDRESS; + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pshare->wlandev_idx == 0) { + efuse_MAC = EEPROM_MAC0_MACADDRESS; + } else { + efuse_MAC = EEPROM_MAC1_MACADDRESS; + } +#else + efuse_MAC = EEPROM_MAC0_MACADDRESS; +#endif + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + efuse_MAC = EEPROM_MAC_ADDR_88E; +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + efuse_MAC = EEPROM_92E_MACADDRESS; + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + efuse_MAC = EEPROM_8812_MACADDRESS; +#endif + //if (/*priv->AutoloadFailFlag==FALSE &&*/ priv->pmib->efuseEntry.enable_efuse == 1) + { + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + unsigned char *efuse_mac = hwinfo + efuse_MAC; + unsigned char zero[] = {0, 0, 0, 0, 0, 0}, mac[6]; + + memcpy(mac,efuse_mac, MACADDRLEN); + /*printk("wlan%d EFUSE MAC [%02x:%02x:%02x:%02x:%02x:%02x]\n", priv->pshare->wlandev_idx, + *mac, *(mac+1), *(mac+2), *(mac+3), *(mac+4), *(mac+5));*/ + + if (!memcmp(mac, zero, MACADDRLEN) || IS_MCAST(mac)) { + memcpy(mac, zero, MACADDRLEN); + } + memcpy(efusemac,mac,MACADDRLEN); + + } +} +#endif + +#endif // EN_EFUSE + +#ifdef TX_EARLY_MODE +void enable_em(struct rtl8192cd_priv *priv) +{ +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + RTL_W32(EARLY_MODE_CTRL, RTL_R32(EARLY_MODE_CTRL) | 0x8000001f); + priv->pshare->aggrmax_bak = RTL_R16(PROT_MODE_CTRL + 2); + //RTL_W16(PROT_MODE_CTRL+2, 0x0808); + RTL_W16(PROT_MODE_CTRL+2, 0x0c0c); + } else +#endif + { + RTL_W32(EARLY_MODE_CTRL, RTL_R32(EARLY_MODE_CTRL) | 0x8000000f); // enable signel AMPDU, early mode for vi/vo/be/bk queue + } + + RTL_W16(TCR, RTL_R16(TCR) | WMAC_TCR_ERRSTEN2); +} + +void disable_em(struct rtl8192cd_priv *priv) +{ +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + RTL_W32(EARLY_MODE_CTRL, RTL_R32(EARLY_MODE_CTRL) & ~0x8000001f); + if (priv->pshare->aggrmax_bak != 0) + RTL_W16(PROT_MODE_CTRL + 2, (priv->pshare->aggrmax_bak & 0xffff)); + } else +#endif + { + RTL_W32(EARLY_MODE_CTRL, RTL_R32(EARLY_MODE_CTRL) & ~0x8000000f); // disable signel AMPDU, early mode for vi/vo/be/bk queue + } + + RTL_W16(TCR, RTL_R16(TCR) & ~WMAC_TCR_ERRSTEN2 ); +} +#endif + + + +#ifdef RTLWIFINIC_GPIO_CONTROL +struct rtl8192cd_priv *root_priv; + +void RTLWIFINIC_GPIO_init_priv(struct rtl8192cd_priv *priv) +{ + root_priv = priv; +} + +void RTLWIFINIC_GPIO_config(unsigned int gpio_num, unsigned int direction) +{ + struct rtl8192cd_priv *priv = root_priv; + if (!root_priv) + return; + +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); +#endif + + if ((gpio_num >= 0) && (gpio_num <= 7)) { + priv->pshare->phw->GPIO_dir[gpio_num] = direction; + + if (direction == 0x01) { + RTL_W32(GPIO_PIN_CTRL, RTL_R32(GPIO_PIN_CTRL) & ~(BIT(gpio_num + 24) | BIT(gpio_num + 16))); + return; + } else if (direction == 0x10) { + RTL_W32(GPIO_PIN_CTRL, (RTL_R32(GPIO_PIN_CTRL) & ~BIT(gpio_num + 24)) | (BIT(gpio_num + 16) | BIT(gpio_num + 8))); + return; + } + } + + if ((GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + if ((gpio_num >= 8) && (gpio_num <= 15)) { + priv->pshare->phw->GPIO_dir[gpio_num] = direction; + + if (direction == 0x01) { + RTL_W32(0x060, RTL_R32(0x060) & ~(BIT(gpio_num + 16) | BIT(gpio_num + 8))); + return; + } else if (direction == 0x10) { + RTL_W32(0x060, (RTL_R32(0x060) & ~BIT(gpio_num + 16)) | (BIT(gpio_num + 8) | BIT(gpio_num))); + return; + } + } + } + else { + if ((gpio_num >= 8) && (gpio_num <= 11)) { + priv->pshare->phw->GPIO_dir[gpio_num] = direction; + + if (direction == 0x01) { + RTL_W32(GPIO_MUXCFG, RTL_R32(GPIO_MUXCFG) & ~(BIT(gpio_num + 20) | BIT(gpio_num + 16))); + return; + } else if (direction == 0x10) { + RTL_W32(GPIO_MUXCFG, (RTL_R32(GPIO_MUXCFG) & ~BIT(gpio_num + 20)) | (BIT(gpio_num + 16) | BIT(gpio_num + 12))); + return; + } + } + } + + panic_printk("GPIO %d action %d not support!\n", gpio_num, direction); + return; +} + +void RTLWIFINIC_GPIO_write(unsigned int gpio_num, unsigned int value) +{ + struct rtl8192cd_priv *priv = root_priv; + if (!root_priv) + return; +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); +#endif + + if (priv->pshare->phw->GPIO_dir[gpio_num] != 0x10) + RTLWIFINIC_GPIO_config(gpio_num, 0x10); + + if (((gpio_num >= 0) && (gpio_num <= 7)) && (priv->pshare->phw->GPIO_dir[gpio_num] == 0x10)) { + if (value) + RTL_W32(GPIO_PIN_CTRL, RTL_R32(GPIO_PIN_CTRL) & ~BIT(gpio_num + 8)); + else + RTL_W32(GPIO_PIN_CTRL, RTL_R32(GPIO_PIN_CTRL) | BIT(gpio_num + 8)); + return; + } + + if ((GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + if (((gpio_num >= 8) && (gpio_num <= 15)) && (priv->pshare->phw->GPIO_dir[gpio_num] == 0x10)) { + if (value) + RTL_W32(0x060, RTL_R32(0x060) & ~BIT(gpio_num)); + else + RTL_W32(0x060, RTL_R32(0x060) | BIT(gpio_num)); + return; + } + } + else { + if (((gpio_num >= 8) && (gpio_num <= 11)) && (priv->pshare->phw->GPIO_dir[gpio_num] == 0x10)) { + if (value) + RTL_W32(GPIO_MUXCFG, RTL_R32(GPIO_MUXCFG) & ~BIT(gpio_num + 12)); + else + RTL_W32(GPIO_MUXCFG, RTL_R32(GPIO_MUXCFG) | BIT(gpio_num + 12)); + return; + } + } + + panic_printk("GPIO %d set value %d not support!\n", gpio_num, value); + return; +} + + +int RTLWIFINIC_GPIO_read(unsigned int gpio_num) +{ + struct rtl8192cd_priv *priv = root_priv; + unsigned int val32; + if (!root_priv) + return -1; + + if (priv->pshare->phw->GPIO_dir[gpio_num] != 0x01) + RTLWIFINIC_GPIO_config(gpio_num, 0x01); + + if (((gpio_num >= 0) && (gpio_num <= 7)) && (priv->pshare->phw->GPIO_dir[gpio_num] == 0x01)) { +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) + val32 = priv->pshare->phw->GPIO_cache[0]; + else +#endif + val32 = RTL_R32(GPIO_PIN_CTRL); + if (val32 & BIT(gpio_num)) + return 0; + else + return 1; + } + + if ((GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + if (((gpio_num >= 8) && (gpio_num <= 15)) && (priv->pshare->phw->GPIO_dir[gpio_num] == 0x01)) { + val32 = RTL_R32(0x060); + if (val32 & BIT(gpio_num - 8)) + return 0; + else + return 1; + } + } + else { + if (((gpio_num >= 8) && (gpio_num <= 11)) && (priv->pshare->phw->GPIO_dir[gpio_num] == 0x01)) { +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) + val32 = priv->pshare->phw->GPIO_cache[1]; + else +#endif + val32 = RTL_R32(GPIO_MUXCFG); + if (val32 & BIT(gpio_num + 8)) + return 0; + else + return 1; + } + } + + panic_printk("GPIO %d get value not support!\n", gpio_num); + return -1; +} +#endif + +#ifdef CONFIG_RTL8672 +// Note: The following GPIO enumeration must have the same order with the RTL8192CD_GPIO of +// GPIO_DEF enumeration in gpio.h +enum WIFI_GPIO { + WIFI_GPIO_0 = 0, WIFI_GPIO_1, WIFI_GPIO_2, WIFI_GPIO_3, + WIFI_GPIO_4, WIFI_GPIO_5, WIFI_GPIO_6, WIFI_GPIO_7, + WIFI_GPIO_8, WIFI_GPIO_9, WIFI_GPIO_10, WIFI_GPIO_11, + WIFI_GPIO_12, WIFI_GPIO_13, WIFI_GPIO_14, WIFI_GPIO_15, + WIFI_GPIO_92E_ANTSEL_P +}; + +void rtl8192cd_gpio_config(unsigned int wlan_idx, unsigned int gpio_num, int direction) +{ + struct rtl8192cd_priv *priv; + unsigned int regval, mask; + +// if (wlan_idx >= sizeof(wlan_device)/sizeof(struct _device_info_)) +// return; +#if defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1) + if (wlan_idx >= 2) + return; +#else + wlan_idx = 0; +#endif + + priv = wlan_device[wlan_idx].priv; + if (NULL == priv) + return; + + if ((gpio_num >= 0) && (gpio_num <= 7)) { + regval = RTL_R32(GPIO_PIN_CTRL); + mask = BIT(gpio_num + 16); + if (regval & mask) { + if ((regval & BIT(gpio_num + 24)) || (direction == 0x01)) // input + RTL_W32(GPIO_PIN_CTRL, regval & ~(BIT(gpio_num + 24) | mask)); + } else { + if ((regval & BIT(gpio_num + 24)) || (direction == 0x10)) // output + RTL_W32(GPIO_PIN_CTRL, (regval & ~ BIT(gpio_num + 24)) | mask); + } + return; + } + + if ((GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + if ((gpio_num >= 8) && (gpio_num <= 15)) { + regval = RTL_R32(0x060); + mask = BIT(gpio_num + 8); + if (regval & mask) { + if ((regval & BIT(gpio_num + 16)) || (direction == 0x01)) // input + RTL_W32(0x060, regval & ~(BIT(gpio_num + 16) | mask)); + } else { + if ((regval & BIT(gpio_num + 16)) || (direction == 0x10)) // output + RTL_W32(0x060, (regval & ~ BIT(gpio_num + 16)) | mask); + } + return; + } else if (gpio_num == WIFI_GPIO_92E_ANTSEL_P) { + if (GET_CHIP_VER(priv) == VERSION_8192E) { + regval = RTL_R32(LEDCFG); + if (!(regval & BIT23)) + RTL_W32(LEDCFG, regval | BIT23); // SW control ANT_SEL[P:N] + return; + } + } + } + else { + if ((gpio_num >= 8) && (gpio_num <= 11)) { + regval = RTL_R32(GPIO_MUXCFG); + mask = BIT(gpio_num + 16); + if (regval & mask) { + if ((regval & BIT(gpio_num + 20)) || (direction == 0x01)) // input + RTL_W32(GPIO_MUXCFG, regval & ~(BIT(gpio_num + 20) | mask)); + } else { + if ((regval & BIT(gpio_num + 20)) || (direction == 0x10)) // output + RTL_W32(GPIO_MUXCFG, (regval & ~ BIT(gpio_num + 20)) | mask); + } + return; + } + } +} +EXPORT_SYMBOL(rtl8192cd_gpio_config); + +void rtl8192cd_gpio_write(unsigned int wlan_idx, unsigned int gpio_num, int value) +{ + struct rtl8192cd_priv *priv; + unsigned int regval, mask; + +// if (wlan_idx >= sizeof(wlan_device)/sizeof(struct _device_info_)) +// return; +#if defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1) + if (wlan_idx >= 2) + return; +#else + wlan_idx = 0; +#endif + + priv = wlan_device[wlan_idx].priv; + if (NULL == priv) + return; + + if ((gpio_num >= 0) && (gpio_num <= 7)) { + regval = RTL_R32(GPIO_PIN_CTRL); + mask = BIT(gpio_num + 8); + if (regval & mask) { + if (!value) + RTL_W32(GPIO_PIN_CTRL, regval & ~mask); + } else { + if (value) + RTL_W32(GPIO_PIN_CTRL, regval | mask); + } + return; + } + + if ((GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + if ((gpio_num >= 8) && (gpio_num <= 15)) { + regval = RTL_R32(0x060); + mask = BIT(gpio_num); + if (regval & mask) { + if (!value) + RTL_W32(0x060, regval & ~mask); + } else { + if (value) + RTL_W32(0x060, regval | mask); + } + return; + } else if (gpio_num == WIFI_GPIO_92E_ANTSEL_P) { + if (GET_CHIP_VER(priv) == VERSION_8192E) { + regval = RTL_R32(0x064); + if (regval & BIT0) { + if (!value) + RTL_W32(0x064, regval & ~BIT0); + } else { + if (value) + RTL_W32(0x064, regval | BIT0); + } + return; + } + } + } + else { + if ((gpio_num >= 8) && (gpio_num <= 11)) { + regval = RTL_R32(GPIO_MUXCFG); + mask = BIT(gpio_num + 12); + if (regval & mask) { + if (!value) + RTL_W32(GPIO_MUXCFG, regval & ~mask); + } else { + if (value) + RTL_W32(GPIO_MUXCFG, regval | mask); + } + return; + } + } +} +EXPORT_SYMBOL(rtl8192cd_gpio_write); + +int rtl8192cd_gpio_read(unsigned int wlan_idx, unsigned int gpio_num) +{ + struct rtl8192cd_priv *priv; + unsigned int val32; + +// if (wlan_idx >= sizeof(wlan_device)/sizeof(struct _device_info_)) +// return -1; +#if defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1) + if (wlan_idx >= 2) + return -1; +#else + wlan_idx = 0; +#endif + + priv = wlan_device[wlan_idx].priv; + if (NULL == priv) + return -1; + + if ((gpio_num >= 0) && (gpio_num <= 7)) { + val32 = RTL_R32(GPIO_PIN_CTRL); + if (val32 & BIT(gpio_num + 16)) + return (val32 & BIT(gpio_num + 8)) ? 1 : 0; + else + return (val32 & BIT(gpio_num)) ? 1 : 0; + } + + if ((GET_CHIP_VER(priv) == VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + if ((gpio_num >= 8) && (gpio_num <= 15)) { + val32 = RTL_R32(0x060); + if (val32 & BIT(gpio_num + 8)) // output + return (val32 & BIT(gpio_num)) ? 1 : 0; + else // input + return (val32 & BIT(gpio_num - 8)) ? 1 : 0; + } else if (gpio_num == WIFI_GPIO_92E_ANTSEL_P) { + if (GET_CHIP_VER(priv) == VERSION_8192E) + return (RTL_R32(0x064) & BIT0) ? 1 : 0; + } + } + else { + if ((gpio_num >= 8) && (gpio_num <= 11)) { + val32 = RTL_R32(GPIO_MUXCFG); + if (val32 & BIT(gpio_num + 16)) + return (val32 & BIT(gpio_num + 12)) ? 1 : 0; + else + return (val32 & BIT(gpio_num + 8)) ? 1 : 0; + } + } + + return -1; +} +EXPORT_SYMBOL(rtl8192cd_gpio_read); +#endif // CONFIG_RTL8672 + +#if defined(CONFIG_WLAN_HAL) && defined(CONFIG_PCI_HCI) +// TODO: move into HAL +BOOLEAN +compareAvailableTXBD( + struct rtl8192cd_priv *priv, + unsigned int num, + unsigned int qNum, + int compareFlag +) +{ + PHCI_TX_DMA_MANAGER_88XX ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + unsigned int halQnum = GET_HAL_INTERFACE(priv)->MappingTxQueueHandler(priv, qNum); +#ifndef SMP_SYNC + unsigned long avail_txbd_flag; +#endif + + SAVE_INT_AND_CLI(avail_txbd_flag); + + if (compareFlag == 1) { + if (ptx_dma->tx_queue[halQnum].avail_txbd_num > num) { + RESTORE_INT(avail_txbd_flag); + return TRUE; + } else { + RESTORE_INT(avail_txbd_flag); + return FALSE; + } + } else if (compareFlag == 2) { + if (ptx_dma->tx_queue[halQnum].avail_txbd_num < num) { + RESTORE_INT(avail_txbd_flag); + return TRUE; + } else { + RESTORE_INT(avail_txbd_flag); + return FALSE; + } + } else { + printk("%s(%d): Error setting !!! \n", __FUNCTION__, __LINE__); + } + + RESTORE_INT(avail_txbd_flag); + + return FALSE; +} + +#endif // CONFIG_WLAN_HAL && CONFIG_PCI_HCI + +/* Hotsport 2.0 Release 1 */ +#if defined(HS2_SUPPORT) || defined(RTK_NL80211)//survey_dump +void start_bbp_ch_load(struct rtl8192cd_priv *priv, unsigned int units) +{ + unsigned short chip_ver = GET_CHIP_VER(priv); + if(chip_ver == VERSION_8188C || chip_ver == VERSION_8192C || chip_ver ==VERSION_8192D || + chip_ver == VERSION_8188E || chip_ver == VERSION_8192E) /*all N-series ic*/ + { + RTL_W16(0x894, units); //set ch load period time units*4 usec + RTL_W32(0x890, 0x0); //reset + RTL_W32(0x890, 0x100); + RTL_W32(0x890, 0x101); + } + else /* 8812, 8881A, 8814A, all AC-series ic*/ + { + RTL_W16(0x990, units); //set ch load period time units*4 usec + RTL_W32(0x994, 0x0); //reset + RTL_W32(0x994, 0x100); + RTL_W32(0x994, 0x101); + } +} + +int read_bbp_ch_load(struct rtl8192cd_priv *priv) +{ + unsigned short chip_ver = GET_CHIP_VER(priv); + unsigned char retry = 0; + if(chip_ver == VERSION_8188C || chip_ver == VERSION_8192C || chip_ver ==VERSION_8192D || + chip_ver == VERSION_8188E || chip_ver == VERSION_8192E) /*all N-series ic*/ + { + do { + if (RTL_R32(0x8b4) & BIT16) + return (RTL_R32(0x8d0) & 0xffff)*4; + delay_ms(1); + } while(++retry < 20); + } + else /* 8812, 8881A, 8813, all AC-series ic*/ + { + do { + if (RTL_R32(0xfa4) & BIT16) + return (RTL_R32(0xfa4) & 0xffff)*4; + delay_ms(1); + } while(++retry < 20); + } + + return -1; +} +#endif + +#ifdef CONFIG_1RCCA_RF_POWER_SAVING +void set_1rcca_ps(struct rtl8192cd_priv *priv, int enable) +{ + if (enable && !priv->pshare->_1rcca_ps_active) { + priv->pshare->_1rcca_ps_active = 1; + RTL_W8(0x800, RTL_R8(0x800) | BIT1); + RTL_W8(0xc04, 0x13); + } else if (!enable && priv->pshare->_1rcca_ps_active) { + priv->pshare->_1rcca_ps_active = 0; + RTL_W8(0x800, RTL_R8(0x800) & ~BIT1); + RTL_W8(0xc04, 0x33); + } +} +#endif // CONFIG_1RCCA_RF_POWER_SAVING + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_hw.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_hw.h new file mode 100755 index 000000000..77dbcb8b0 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_hw.h @@ -0,0 +1,2392 @@ +/* + * Header file for hardware related definitions + * + * $Id: 8192cd_hw.h,v 1.11.2.6 2010/11/11 07:54:36 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_HW_H_ +#define _8192CD_HW_H_ + +#ifdef __ECOS +#include +#endif + +#ifdef __KERNEL__ +#include +#include +#include +#endif + +#ifdef __DRAYTEK_OS__ +#include +#endif + +#include "./8192c_reg.h" +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) +#include "./8192d_reg.h" +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#include "./8188e_reg.h" +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) +#include "./8192e_reg.h" +#endif +#include "./8192cd_cfg.h" + +#if 1 +#include "./8812_reg.h" +#endif + +#if !defined(__KERNEL__) && !defined(__ECOS) +#include "./sys-support.h" +#endif +#ifdef __ECOS +#include +#include +#endif + +#include "./wifi.h" +#include "./8192cd_phyreg.h" + + +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG; + +//#define RTL8192CD_REGS_SIZE ((0xff + 1) * 16) + +#ifdef CONFIG_RTL_88E_SUPPORT +#if defined(CONFIG_PCI_HCI) +#define EEPROM_MAC_ADDR_88E EEPROM_MAC_ADDR_88EE +#elif defined(CONFIG_USB_HCI) +#define EEPROM_MAC_ADDR_88E EEPROM_MAC_ADDR_88EU +#elif defined(CONFIG_SDIO_HCI) +#define EEPROM_MAC_ADDR_88E EEPROM_MAC_ADDR_88ES +#endif +#endif + +#if 0 +enum _RF_TYPE_ { + _11BG_RF_ZEBRA_ = 0x07, + _11ABG_RF_OMC8255_ = 0x08, + _11ABG_RF_OMC8255B_ = 0x09, + _11BGN_RF_8256_ = 0x0a, +}; +#endif + +#define VERSION_MASK 0xf00f +enum _CHIP_VERSION_ { + VERSION_8188C = 0x1000, + VERSION_8192C = 0x1001, + VERSION_8192D = 0x1002, + VERSION_8188E = 0x1003, + VERSION_8812E = 0x1004, //CONFIG_RTL_8812_SUPPORT + VERSION_8192E = 0x1005, + VERSION_8881A = 0x1006, + VERSION_8814A = 0x1007 //CONFIG_WLAN_HAL_8814AE +}; + + +enum _BOND_TYPE_8881A_ { + BOND_8881AB, + BOND_8881AQ, + BOND_8881AN, + BOND_8881AL, + BOND_8881AM, +}; + +#if 0 +enum _ZEBRA_VERSION_ { + VERSION_ZEBRA_A = 0, + VERSION_ZEBRA_B = 1, + VERSION_ZEBRA_C = 2, + VERSION_ZEBRA_E = 3, + VERSION_ZEBRA2_A = 4, +}; + +enum _TCR_CONFIG_ { + _DIS_REQ_QSZ_ = BIT(28), + _SAT_ = BIT(24), + + _TX_DMA16_ = 0x0, + _TX_DMA32_ = BIT(21), + _TX_DMA64_ = BIT(22), + _TX_DMA128_ = BIT(22) | BIT(21), + _TX_DMA256_ = BIT(23), + _TX_DMA512_ = BIT(23) | BIT(21), + _TX_DMA1K_ = BIT(23) | BIT(22), + _TX_DMA2K_ = BIT(23) | BIT(22) | BIT(21), + + _DISCW_ = BIT(20), + _ICV_APP_ = BIT(19), + + _MAC_LBK_ = BIT(17), + _BB_LBK_ = BIT(18), + _CNT_TX_ = BIT(18) | BIT(17), + + _DURPROCMODE_SHIFT_ = 30, + _SRL_SHIFT_ = 8, + _LRL_SHIFT_ = 0, +}; + +enum _RCR_CONFIG_ { + _ERLYRXEN_ = BIT(31), + _ENCS2_ = BIT(30), + _ENCS1_ = BIT(29), + _ENMARP_ = BIT(28), + _ENMBID_ = BIT(27), + _CAM_SEARCH_ = BIT(26), + + _CBSSID_ = BIT(23), + _APWRMGT_ = BIT(22), + _ADD3_ = BIT(21), + _AMF_ = BIT(20), + _ACF_ = BIT(19), + _ADF_ = BIT(18), + + _RX_ERLY64_ = BIT(14), + _RX_ERLY128_ = BIT(13) | BIT(14), + _RX_ERLY256_ = BIT(15), + _RX_ERLY512_ = BIT(15) | BIT(13), + _RX_ERLY1K_ = BIT(15) | BIT(14), + _NO_ERLYRX_ = BIT(15) | BIT(14) | BIT(13), + + _AICV_ = BIT(12), + + _RX_DMA16_ = 0x0, + _RX_DMA32_ = BIT(8), + _RX_DMA64_ = BIT(9), + _RX_DMA128_ = BIT(9) | BIT(8), + _RX_DMA256_ = BIT(10), + _RX_DMA512_ = BIT(10) | BIT(8), + _RX_DMA1K_ = BIT(10) | BIT(9), + _RX_DMA2K_ = BIT(10) | BIT(9) | BIT(8), + + _9356SEL_ = BIT(6), + _ACRC32_ = BIT(5), + _AB_ = BIT(3), + _AM_ = BIT(2), + _APM_ = BIT(1), + _AAP_ = BIT(0), +}; + +enum _SCR_CONFIG_ { + _PRIVACY_WEP40_ = BIT(0), + _PRIVACY_WEP104_ = BIT(4), +}; + + +#define ENC_NONE 0 +#define ENC_WEP40 BIT(2)//|BIT(5)//FIX for DEFAULT KEY +#define ENC_TKIP_NO_MIC BIT(3) +#define ENC_TKIP_MIC BIT(3)|BIT(2) +#define ENC_AES BIT(4) +#define ENC_WEP104 BIT(4)|BIT(2)//|BIT(5)//FIX for DEFAULT KEY + +//#if defined(RTL8190) || defined(RTL8192E) +#if 0 +enum _RTL8190_AP_HW_ { + _IDR0_ = 0x0, + _PCIF_ = 0x9, // PCI Function Register + _9346CR_ = 0x0E, + _ANAPAR_ = 0x17, //NOTE: 8192 only register, for triggering pll on ... joshua + _BBGLBRESET_ = 0x20, + + _BSSID_ = 0x2e, + _CR_ = 0x37, + _SIFS_CCK_ = 0x3c, + _SIFS_OFDM_ = 0x3e, + _TCR_ = 0x40, + _RCR_ = 0x44, + _SLOT_ = 0x49, + _EIFS_ = 0x4a, + _ACKTIMEOUT_ = 0x4c, + + _ACBE_PARM_ = 0x50, // BE Parameter + _ACBK_PARM_ = 0x54, // BK Parameter + _ACVO_PARM_ = 0x58, // VO Parameter + _ACVI_PARM_ = 0x5C, // VI Parameter + + _BCNTCFG_ = 0x62, + _TIMER1_ = 0x68, + _TIMER2_ = 0x6c, + _BCNITV_ = 0x70, + _ATIMWIN_ = 0x72, + _DRVERLYINT_ = 0x74, + _BCNDMA_ = 0x76, + + _MBIDCAMCFG_ = 0xc0, + _MBIDCAMCONTENT_ = 0xc4, + + _IMR_ = 0xF4, // Interrupt Mask Register + _ISR_ = 0xF8, // Interrupt Status Register + _DBS_ = 0xFC, // Debug Select + _TXPOLL_ = 0xFD, // Transmit Polling + _TXPOLL_H_ = 0xFE, + _PSR_ = 0xFF, // Page Select Register + _CPURST_ = 0x100, // CPU Reset + _BLDTIME_ = 0x124, +// _BLDUSER0_ = 0x128, +// _BLDUSER1_ = 0x12c, + _TXPKTNUM_ = 0x128, + _RXPKTNUM_ = 0x130, + + _LED1CFG_ = 0x154, + _LED0CFG_ = 0x155, + + _ACM_CTRL_ = 0x171, + + _RQPN1_ = 0x180, + _RQPN2_ = 0x184, + _RQPN3_ = 0x188, + + _TBDA_ = 0x200, // Transmit Beacon Desc Addr + _THPDA_ = 0x204, // Transmit High Priority Desc Addr + _TCDA_ = 0x208, // Transmit Command Desc Addr + _TMGDA_ = 0x20C, // Transmit Management Desc Addr + _HDA_ = 0x210, // HCCA Desc Addr + _TNPDA_ = 0x214, // Transmit VO Desc Addr + _TLPDA_ = 0x218, // Transmit VI Desc Addr + _TBEDA_ = 0x21C, // Transmit BE Desc Addr + _TBKDA_ = 0x220, // Transmit BK Desc Addr + _RCDSA_ = 0x224, // Receive Command Desc Addr + _RDSAR_ = 0x228, // Receive Desc Starting Addr + _MAR0_ = 0x240, + _MAR4_ = 0x244, + _MBIDCTRL_ = 0x260, + _BWOPMODE_ = 0x300, + _MSR_ = 0x303, + _RETRYCNT_ = 0x304, + _TSFTR_L_ = 0x308, + _TSFTR_H_ = 0x30c, + _RRSR_ = 0x310, + _RATR_POLL_ = 0x318, + _RATR0_ = 0x320, + _RATR1_ = 0x324, + _RATR2_ = 0x328, + _RATR3_ = 0x32c, + _RATR4_ = 0x330, + _RATR5_ = 0x334, + _RATR6_ = 0x338, + _RATR7_ = 0x33c, +#ifdef RTL8190 + _MCS_TXAGC_0_ = 0x340, + _MCS_TXAGC_1_ = 0x344, + _CCK_TXAGC_ = 0x348, +#elif defined(RTL8192E) + _ISRD_CPU_ = 0x350, + _FWIMR_ = 0x354, +#endif + _FWPSR_ = 0x3FF, +}; +#endif +//#elif defined(RTL8192SE) + +enum _RTL8190_AP_HW_ { + _RCR_ = RCR, + _MBIDCTRL_ = MBIDCTRL, + _BSSID_ = BSSIDR, + _MBIDCAMCONTENT_ = MBIDCAMCONTENT, + _MBIDCAMCFG_ = MBIDCAMCFG, + _SLOT_ = SLOT_TIME, + _ACBE_PARM_ = EDCAPARA_BE, // BE Parameter + _ACBK_PARM_ = EDCAPARA_BK, // BK Parameter + _ACVO_PARM_ = EDCAPARA_VO, // VO Parameter + _ACVI_PARM_ = EDCAPARA_VI, // VI Parameter + _TIMER1_ = TIMER0, + _TIMER2_ = TIMER1, + _IMR_ = IMR, // Interrupt Mask Register + _ISR_ = ISR, // Interrupt Status Register + _ACM_CTRL_ = ACMHWCTRL, + _TBDA_ = TBDA, // Transmit Beacon Desc Addr + _THPDA_ = THPDA, // Transmit High Priority Desc Addr + _TCDA_ = TCDA, // Transmit Command Desc Addr + _TMGDA_ = TMDA, // Transmit Management Desc Addr + _HDA_ = HDA, // HCCA Desc Addr + _TNPDA_ = TVODA, // Transmit VO Desc Addr + _TLPDA_ = TVIDA, // Transmit VI Desc Addr + _TBEDA_ = TBEDA, // Transmit BE Desc Addr + _TBKDA_ = TBKDA, // Transmit BK Desc Addr + _RCDSA_ = RCDA, // Receive Command Desc Addr + _RDSAR_ = RDSA, // Receive Desc Starting Addr + _BWOPMODE_ = BW_OPMODE, + _MSR_ = MSR, + _TSFTR_L_ = TSFR, + _TSFTR_H_ = (TSFR+4), +#ifdef CONFIG_RTK_MESH + _RRSR_ = RRSR, +#endif + _RATR_POLL_ = 0x320, // need to fix + _RATR0_ = 0x320, // need to fix + _RATR1_ = 0x320, // need to fix + _RATR2_ = 0x320, // need to fix + _RATR3_ = 0x320, // need to fix + _RATR4_ = 0x320, // need to fix + _RATR5_ = 0x320, // need to fix + _RATR6_ = 0x320, // need to fix + _RATR7_ = 0x320, // need to fix +}; +//#endif + + +//#if defined(RTL8190) || defined(RTL8192E) +//enum _AP_SECURITY_REGS_ { +// _CAMCMD_ = 0xa0, +// _CAM_W_ = 0xa4, +// _CAM_R_ = 0xa8, +// _CAMDBG_ = 0xac, +// _WPACFG_ = 0xb0, +//}; +//#elif defined(RTL8192SE) + +enum _AP_SECURITY_REGS_ { + _CAMCMD_ = RWCAM, + _CAM_W_ = WCAMI, + _CAM_R_ = RCAMO, + _CAMDBG_ = CAMDBG, + _WPACFG_ = SECR, +}; + +//#endif + +enum _RTL8190_DESC_CMD_ { + // TX and common + _OWN_ = BIT(31), + _LINIP_ = BIT(30), + _FS_ = BIT(29), + _LS_ = BIT(28), + _CMDINIT_ = BIT(27), + _PIFS_ = BIT(15), + _NOENC_ = BIT(14), + _MFRAG_ = BIT(13), + _USERATE_ = BIT(12), + _DISFB_ = BIT(11), + _RATID_ = BIT(8), + _RATIDSHIFT_ = 8, + _OFFSETSHIFT_ = 16, + _QSELECTSHIFT_ = 16, + + // RX + _EOR_ = BIT(30), + _SWDEC_ = BIT(27), + _PHYST_ = BIT(26), + _SHIFT1_ = BIT(25), + _SHIFT0_ = BIT(24), + _ICV_ = BIT(15), + _CRC32_ = BIT(14), + _RXFRLEN_MSK_ = 0x3fff, + _RXDRVINFOSZ_SHIFT_ = 16, +}; + +enum _IMR_BITFIELD_90_ { +//#ifdef RTL8190 +// _CPUERR_ = BIT(29), +//#elif defined(RTL8192E) + _IllAcess_ = BIT(30), + _BTEvent_ = BIT(29), +//#endif + _ATIMEND_ = BIT(28), + _TBDOK_ = BIT(27), + _TBDER_ = BIT(26), + _BCNDMAINT5_ = BIT(25), + _BCNDMAINT4_ = BIT(24), + _BCNDMAINT3_ = BIT(23), + _BCNDMAINT2_ = BIT(22), + _BCNDOK5_ = BIT(21), + _BCNDOK4_ = BIT(20), + _BCNDOK3_ = BIT(19), + _BCNDOK2_ = BIT(18), + _TIMEOUT2_ = BIT(17), + _TIMEOUT1_ = BIT(16), + _TXFOVW_ = BIT(15), + _PSTIMEOUT_ = BIT(14), + _BCNDMAINT_ = BIT(13), + _RXFOVW_ = BIT(12), + _RDU_ = BIT(11), + _RXCMDOK_ = BIT(10), + _BCNDOK_ = BIT(9), + _THPDOK_ = BIT(8), + _COMDOK_ = BIT(7), + _MGTDOK_ = BIT(6), + _HCCADOK_ = BIT(5), + _TBKDOK_ = BIT(4), + _TBEDOK_ = BIT(3), + _TVIDOK_ = BIT(2), + _TVODOK_ = BIT(1), + _ROK_ = BIT(0), +}; +enum _AP_SECURITY_SETTINGS_ { + //CAM CMD + _CAM_POLL_ = BIT(31), + _CAM_CLR_ = BIT(30), + _CAM_WE_ = BIT(16), + + //CAM DBG + _CAM_INFO_ = BIT(31), + _KEY_FOUND_ = BIT(30), + + //SEC CFG + _NO_SK_MC_ = BIT(5), + _SK_A2_ = BIT(4), + _RX_DEC_ = BIT(3), + _TX_ENC_ = BIT(2), + _RX_USE_DK_ = BIT(1), + _TX_USE_DK_ = BIT(0), +}; +#endif + +#define MAX_SUPPORT_ANT 3 + +#define HT_RATE_ID 0x80 //must >= 0x80 +#define HT_RATE_NUM (MAX_SUPPORT_ANT*8) // Dynamic define by rf capability ?? + +#define VHT_RATE_ID 0xA0 +#define VHT_RATE_NUM (MAX_SUPPORT_ANT*10) // Dynamic define by rf capability ?? //must >= (HT_RATE_ID+HT_RATE_NUM) + +enum _RF_TX_RATE_ { + _1M_RATE_ = 2, + _2M_RATE_ = 4, + _5M_RATE_ = 11, + _6M_RATE_ = 12, + _9M_RATE_ = 18, + _11M_RATE_ = 22, + _12M_RATE_ = 24, + _18M_RATE_ = 36, + _22M_RATE_ = 44, + _24M_RATE_ = 48, + _33M_RATE_ = 66, + _36M_RATE_ = 72, + _48M_RATE_ = 96, + _54M_RATE_ = 108, + + _MCS0_RATE_ = (HT_RATE_ID + 0), + _MCS1_RATE_ = (HT_RATE_ID + 1), + _MCS2_RATE_ = (HT_RATE_ID + 2), + _MCS3_RATE_ = (HT_RATE_ID + 3), + _MCS4_RATE_ = (HT_RATE_ID + 4), + _MCS5_RATE_ = (HT_RATE_ID + 5), + _MCS6_RATE_ = (HT_RATE_ID + 6), + _MCS7_RATE_ = (HT_RATE_ID + 7), + _MCS8_RATE_ = (HT_RATE_ID + 8), + _MCS9_RATE_ = (HT_RATE_ID + 9), + _MCS10_RATE_= (HT_RATE_ID + 10), + _MCS11_RATE_= (HT_RATE_ID + 11), + _MCS12_RATE_= (HT_RATE_ID + 12), + _MCS13_RATE_= (HT_RATE_ID + 13), + _MCS14_RATE_= (HT_RATE_ID + 14), + _MCS15_RATE_= (HT_RATE_ID + 15), + _MCS16_RATE_= (HT_RATE_ID + 16), + _MCS17_RATE_= (HT_RATE_ID + 17), + _MCS18_RATE_= (HT_RATE_ID + 18), + _MCS19_RATE_= (HT_RATE_ID + 19), + _MCS20_RATE_= (HT_RATE_ID + 20), + _MCS21_RATE_= (HT_RATE_ID + 21), + _MCS22_RATE_= (HT_RATE_ID + 22), + _MCS23_RATE_= (HT_RATE_ID + 23), + _MCS24_RATE_= (HT_RATE_ID + 24), + _MCS25_RATE_= (HT_RATE_ID + 25), + _MCS26_RATE_= (HT_RATE_ID + 26), + _MCS27_RATE_= (HT_RATE_ID + 27), + _MCS28_RATE_= (HT_RATE_ID + 28), + _MCS29_RATE_= (HT_RATE_ID + 29), + _MCS30_RATE_= (HT_RATE_ID + 30), + _MCS31_RATE_= (HT_RATE_ID + 31), + + + + _NSS1_MCS0_RATE_ = (VHT_RATE_ID + 0), + _NSS1_MCS1_RATE_ = (VHT_RATE_ID + 1), + _NSS1_MCS2_RATE_ = (VHT_RATE_ID + 2), + _NSS1_MCS3_RATE_ = (VHT_RATE_ID + 3), + _NSS1_MCS4_RATE_ = (VHT_RATE_ID + 4), + _NSS1_MCS5_RATE_ = (VHT_RATE_ID + 5), + _NSS1_MCS6_RATE_ = (VHT_RATE_ID + 6), + _NSS1_MCS7_RATE_ = (VHT_RATE_ID + 7), + _NSS1_MCS8_RATE_ = (VHT_RATE_ID + 8), + _NSS1_MCS9_RATE_ = (VHT_RATE_ID + 9), + _NSS2_MCS0_RATE_ = (VHT_RATE_ID + 10), + _NSS2_MCS1_RATE_ = (VHT_RATE_ID + 11), + _NSS2_MCS2_RATE_ = (VHT_RATE_ID + 12), + _NSS2_MCS3_RATE_ = (VHT_RATE_ID + 13), + _NSS2_MCS4_RATE_ = (VHT_RATE_ID + 14), + _NSS2_MCS5_RATE_ = (VHT_RATE_ID + 15), + _NSS2_MCS6_RATE_ = (VHT_RATE_ID + 16), + _NSS2_MCS7_RATE_ = (VHT_RATE_ID + 17), + _NSS2_MCS8_RATE_ = (VHT_RATE_ID + 18), + _NSS2_MCS9_RATE_ = (VHT_RATE_ID + 19), + _NSS3_MCS0_RATE_ = (VHT_RATE_ID + 20), + _NSS3_MCS1_RATE_ = (VHT_RATE_ID + 21), + _NSS3_MCS2_RATE_ = (VHT_RATE_ID + 22), + _NSS3_MCS3_RATE_ = (VHT_RATE_ID + 23), + _NSS3_MCS4_RATE_ = (VHT_RATE_ID + 24), + _NSS3_MCS5_RATE_ = (VHT_RATE_ID + 25), + _NSS3_MCS6_RATE_ = (VHT_RATE_ID + 26), + _NSS3_MCS7_RATE_ = (VHT_RATE_ID + 27), + _NSS3_MCS8_RATE_ = (VHT_RATE_ID + 28), + _NSS3_MCS9_RATE_ = (VHT_RATE_ID + 29), + _NSS4_MCS0_RATE_ = (VHT_RATE_ID + 30), + _NSS4_MCS1_RATE_ = (VHT_RATE_ID + 31), + _NSS4_MCS2_RATE_ = (VHT_RATE_ID + 32), + _NSS4_MCS3_RATE_ = (VHT_RATE_ID + 33), + _NSS4_MCS4_RATE_ = (VHT_RATE_ID + 34), + _NSS4_MCS5_RATE_ = (VHT_RATE_ID + 35), + _NSS4_MCS6_RATE_ = (VHT_RATE_ID + 36), + _NSS4_MCS7_RATE_ = (VHT_RATE_ID + 37), + _NSS4_MCS8_RATE_ = (VHT_RATE_ID + 38), + _NSS4_MCS9_RATE_ = (VHT_RATE_ID + 39), + +}; + +#if 0 +enum _HW_STATE_ { + _HW_STATE_STATION_ = 0x02, + _HW_STATE_ADHOC_ = 0x01, + _HW_STATE_AP_ = 0x03, + _HW_STATE_NOLINK_ = 0x0, +}; +#endif + +enum BANDWIDTH_MODE +{ + BW_OPMODE_11J = BIT(0), + BW_OPMODE_5G = BIT(1), + BW_OPMODE_20MHZ = BIT(2) +}; + +#if 0 +//#ifdef RTL8192SE +enum _FW_REG364_MASK_ +{ + FW_REG364_DIG = BIT(0), + FW_REG364_HP = BIT(1), + FW_REG364_RSSI = BIT(2), +// FW_REG364_IQK = BIT(3) +}; +#endif +enum _ARFR_TABLE_SET_ +{ + ARFR_2T_40M = 0, + ARFR_2T_Band_A_40M = 1, + ARFR_2T_Band_A_20M = 1, + ARFR_2T_20M = 2, + ARFR_1T_40M = 12, + ARFR_1T_20M = 13, + ARFR_BG_MIX = 4, + ARFR_G_ONLY = 5, + ARFR_Band_A_BMC = 5, + ARFR_B_ONLY = 6, + ARFR_BMC = 6, +}; + +#if (defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT)) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_WLAN_HAL_8814AE) +typedef enum _RATR_TABLE_MODE{ + RATR_INX_WIRELESS_NGB = 0, // BGN 40 Mhz 2SS 1SS + RATR_INX_WIRELESS_NG = 1, // GN or N + RATR_INX_WIRELESS_NB = 2, // BGN 20 Mhz 2SS 1SS or BN + RATR_INX_WIRELESS_N = 3, + RATR_INX_WIRELESS_GB = 4, + RATR_INX_WIRELESS_G = 5, + RATR_INX_WIRELESS_B = 6, + RATR_INX_WIRELESS_MC = 7, + RATR_INX_WIRELESS_AC_N = 8, +}RATR_TABLE_MODE, *PRATR_TABLE_MODE; +#endif + +//#define HP_UPPER 0x4B //SS = 75% +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#define HP_LOWER 0x3F //0x46 //SS = 70% +#endif +#define RSSI_DIFF_PA 10 +#define RSSI_DIFF_LNA 8 + +//---------------------------------------------------------------------------- +// 8192C Rate Definition +//---------------------------------------------------------------------------- +//CCK +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +//OFDM +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +//MCS 1 Spatial Stream +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +//MCS 2 Spatial Stream +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 +// ALL CCK Rate +#define RATE_ALL_CCK RATR_1M|RATR_2M|RATR_55M|RATR_11M +#define RATE_ALL_OFDM_AG RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M|\ + RATR_36M|RATR_48M|RATR_54M +#define RATE_ALL_OFDM_1SS RATR_MCS0|RATR_MCS1|RATR_MCS2|RATR_MCS3 |\ + RATR_MCS4|RATR_MCS5|RATR_MCS6 |RATR_MCS7 +#define RATE_ALL_OFDM_2SS RATR_MCS8|RATR_MCS9 |RATR_MCS10|RATR_MCS11|\ + RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15 + + +#if 0 +//---------------------------------------------------------------------------- +// 8139 (CR9346) 9346 command register bits (offset 0x50, 1 byte) +//---------------------------------------------------------------------------- +#define CR9346_EEDO 0x01 // 9346 data out +#define CR9346_EEDI 0x02 // 9346 data in +#define CR9346_EESK 0x04 // 9346 serial clock +#define CR9346_EECS 0x08 // 9346 chip select +#define CR9346_EEM0 0x40 // select 8139 operating mode +#define CR9346_EEM1 0x80 // 00: normal + // 01: autoload + // 10: 9346 programming + // 11: config write enable +#define CR9346_CFGRW 0xC0 // Config register write +#define CR9346_NORM 0x0 // +//------------------------------------------------------------------------- +// EEPROM bit definitions +//------------------------------------------------------------------------- +//- EEPROM control register bits +#define EN_TRNF 0x10 // Enable turnoff +#define EEDO CR9346_EEDO // EEPROM data out +#define EEDI CR9346_EEDI // EEPROM data in (set for writing data) +#define EECS CR9346_EECS // EEPROM chip select (1=high, 0=low) +#define EESK CR9346_EESK // EEPROM shift clock (1=high, 0=low) + +//- EEPROM opcodes +#define EEPROM_READ_OPCODE 06 +#define EEPROM_WRITE_OPCODE 05 +#define EEPROM_ERASE_OPCODE 07 +#define EEPROM_EWEN_OPCODE 19 // Erase/write enable +#define EEPROM_EWDS_OPCODE 16 // Erase/write disable + +//- EEPROM data locations +#define RTL8180_EEPROM_ID 0x8129 +#define EEPROM_ID 0x0 +//#define EEPROM_RF_CHIP_ID 0x0C +#define EEPROM_RF_CHIP_ID 0x28 +//#define EEPROM_NODE_ADDRESS_BYTE_0 0x0E +#define EEPROM_NODE_ADDRESS_BYTE_0 0x0C // modified by joshua +#define EEPROM_CONFIG2 0x18 +#define EEPROM_ANA_PARM 0x1a +//#define EEPROM_TX_POWER_LEVEL_0 0x20 +#define EEPROM_TX_POWER_LEVEL_0 0x2C // modified by joshua +//#define EEPROM_CHANNEL_PLAN 0x2E +#define EEPROM_CHANNEL_PLAN 0x7C +#define EEPROM_CS_THRESHOLD 0x2F +#define EEPROM_ANA_PARM2 0x32 +#define EEPROM_RF_PARAM 0x32 +#define EEPROM_VERSION 0x3c +#define EEPROM_CIS_DATA 0x80 +//#define EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET 0x40 +#define EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET 0x3A +//#define EEPROM_11A_CHANNEL_TX_POWER_LEVEL_OFFSET 0x4e +#define EEPROM_11A_CHANNEL_TX_POWER_LEVEL_OFFSET 0x2C + +#define EEPROM_FLAGS_WORD_3 3 +#define EEPROM_FLAG_10MC BIT(0) +#define EEPROM_FLAG_100MC BIT(1) + + +#ifdef RTL8192E +#define EEPROM_RFInd_PowerDiff 0x28 +#define EEPROM_ThermalMeter 0x29 +#define EEPROM_TxPwDiff_CrystalCap 0x2A //0x2A~0x2B +#define EEPROM_TxPwIndex_CCK 0x2C //0x2C~0x39 +#define EEPROM_TxPwIndex_OFDM_24G 0x3A //0x3A~0x47 +#endif + + +//---------------------------------------------------------------------------- +// 8180 Config3 Regsiter (offset 0x59, 1 byte) +//---------------------------------------------------------------------------- +#define Config3_GNTSel 0x80 +#define Config3_ParmEn 0x40 // enable write to ANA_PARM + // (0x54) register +#define Config3_Magic 0x20 // Enable Magic Packet Wakeup +#define Config3_CardBEn 0x08 // Cardbus Enable +#define Config3_CLKRUN_En 0x04 // CLKRUN(clock run) Enable +#define Config3_FuncRegEn 0x02 // Function Register Enable +#define Config3_FBtBEn 0x01 // Enable PCI fast-back-to-back +#endif + +#ifdef RX_BUFFER_GATHER +enum { + GATHER_FIRST = 1, + GATHER_MIDDLE = 2, + GATHER_LAST = 4, +}; +#endif + +#ifdef CONFIG_PCI_HCI +struct rx_desc { + +//#if defined(RTL8190) || defined(RTL8192) +// volatile unsigned int cmd; +// volatile unsigned int rsvd0; +// volatile unsigned int rsvd1; +// volatile unsigned int paddr; +//#elif defined(RTL8192SE) + + volatile unsigned int Dword0; + volatile unsigned int Dword1; + volatile unsigned int Dword2; + volatile unsigned int Dword3; + volatile unsigned int Dword4; // IV1 + volatile unsigned int Dword5; // TSFL + volatile unsigned int Dword6; // BufferAddress + volatile unsigned int Dword7; // NextRxDescAddress; +// volatile unsigned int Dword8; +//#endif + +}; +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +struct rx_desc { + unsigned int Dword0; + unsigned int Dword1; + unsigned int Dword2; + unsigned int Dword3; + unsigned int Dword4; // IV1 + unsigned int Dword5; // TSFL +}; +#endif + +struct rx_desc_info { + void* pbuf; + unsigned long paddr; +}; + +__PACK struct rf_misc_info { +#ifdef USE_OUT_SRC + u1Byte mimorssi[4]; + s1Byte mimosq[4]; + s1Byte RxSNRdB[4]; +#ifdef CONFIG_WLAN_HAL_8822B + u1Byte RxCount; +#endif + u1Byte BandWidth; +#else + unsigned char mimorssi[4]; + signed char mimosq[4]; + int RxSNRdB[4]; +#endif +} __WLAN_ATTRIB_PACK__; + +#ifdef CONFIG_RTK_MESH +struct MESH_HDR { + unsigned char mesh_flag; + INT8 TTL; + UINT16 segNum; + unsigned char DestMACAddr[MACADDRLEN]; // modify for 6 address + unsigned char SrcMACAddr[MACADDRLEN]; +}; +#endif + +struct rx_frinfo { + struct sk_buff* pskb; + struct list_head mpdu_list; + unsigned int pktlen; + struct list_head rx_list; + unsigned char *da; + unsigned char *sa; + unsigned int hdr_len; + unsigned short seq; + unsigned short tid; + unsigned char to_fr_ds; +// ODM PODM_PHY_INFO_T + unsigned char rssi; + unsigned char sq; + struct rf_misc_info rf_info; +// + unsigned char rx_rate; + unsigned char rx_bw; + unsigned char rx_splcp; + unsigned char driver_info_size; + unsigned char rxbuf_shift; + unsigned char sw_dec; + unsigned char faggr; + unsigned char paggr; +#ifdef HW_FILL_MACID + unsigned char macid; +#endif +//#ifdef RTL8192SE + unsigned int physt; +//#endif +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + unsigned char is_br_mgnt; // is a broadcast management frame (beacon and probe-rsp) +#endif + struct RxFWInfo *driver_info; + signed char cck_mimorssi[4]; + +#ifdef CONFIG_RTK_MESH + // it's a mandatory field, for rx (e.g., validate_mpdu) to distinguish an 11s frame + unsigned char is_11s; ///< 1: 11s + + struct MESH_HDR mesh_header; //modify by Joule for MESH HEADER + + unsigned char prehop_11s[MACADDRLEN]; + +#endif // CONFIG_RTK_MESH + +#ifdef RX_BUFFER_GATHER + int gather_flag; + int gather_len; +#endif +}; + + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_RTL_8812_SUPPORT //8812_desc +struct tx_desc { + volatile unsigned int Dword0; + volatile unsigned int Dword1; + volatile unsigned int Dword2; + volatile unsigned int Dword3; + volatile unsigned int Dword4; + volatile unsigned int Dword5; + volatile unsigned int Dword6; + volatile unsigned int Dword7; + volatile unsigned int Dword8; + volatile unsigned int Dword9; + volatile unsigned int Dword10; //TxBufferAddr; + volatile unsigned int Dword11; + volatile unsigned int Dword12; + volatile unsigned int Dword13; //NextTxDescAddress; + unsigned int Reserve_Pass_92S_PCIE_MM_Limit[2]; +}; + +#else //CONFIG_RTL_8812_SUPPORT +struct tx_desc { +/* +#if defined(RTL8190) || defined(RTL8192) + volatile unsigned int cmd; + volatile unsigned int opt; + volatile unsigned int flen; + volatile unsigned int paddr; + volatile unsigned int n_desc; + volatile unsigned int rsvd0; + volatile unsigned int rsvd1; + volatile unsigned int rsvd2; +#elif defined(RTL8192SE) +*/ + volatile unsigned int Dword0; + volatile unsigned int Dword1; + volatile unsigned int Dword2; + volatile unsigned int Dword3; + volatile unsigned int Dword4; + volatile unsigned int Dword5; + volatile unsigned int Dword6; + volatile unsigned int Dword7; + volatile unsigned int Dword8; //TxBufferAddr; + volatile unsigned int Dword9; + volatile unsigned int Dword10; //NextTxDescAddress; + volatile unsigned int Dword11; + + // 2008/05/15 MH Because PCIE HW memory R/W 4K limit. And now, our descriptor + // size is 40 bytes. If you use more than 102 descriptor( 103*40>4096), HW will execute + // memoryR/W CRC error. And then all DMA fetch will fail. We must decrease descriptor + // number or enlarge descriptor size as 64 bytes. + unsigned int Reserve_Pass_92S_PCIE_MM_Limit[4]; +//#endif + +}; + +#endif //CONFIG_RTL_8812_SUPPORT +#endif // CONFIG_PCI_HCI + +struct tx_desc_info { + // for cur_txbd->TXBD_ELE[1].Dword1 : packet header + // for WlanHAL, paddr does not use currently. + unsigned int type; + void *pframe; +#if defined(CONFIG_PCI_HCI) + unsigned long paddr; + unsigned int len; +#ifdef CONFIG_WLAN_HAL + // buf_pframe[0]: cur_txbd->TXBD_ELE[2].Dword1 : packet payload + // buf_pframe[1]: cur_txbd->TXBD_ELE[3].Dword1 : icv/mic + // Currently, buf_paddr and buf_len do not use... + unsigned int buf_type[2]; + unsigned int buf_paddr[2]; + void *buf_pframe[2]; + unsigned int buf_len[2]; +#endif // CONFIG_WLAN_HAL +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + u8 *buf_ptr; + u32 buf_len; +#endif + struct stat_info *pstat; + unsigned int rate; + struct rtl8192cd_priv *priv; +}; + +typedef struct _BB_REGISTER_DEFINITION { + unsigned int rfintfs; // set software control: + // 0x870~0x877[8 bytes] + unsigned int rfintfi; // readback data: + // 0x8e0~0x8e7[8 bytes] + unsigned int rfintfo; // output data: + // 0x860~0x86f [16 bytes] + unsigned int rfintfe; // output enable: + // 0x860~0x86f [16 bytes] + unsigned int rf3wireOffset; // LSSI data: + // 0x840~0x84f [16 bytes] + unsigned int rfLSSI_Select; // BB Band Select: + // 0x878~0x87f [8 bytes] + unsigned int rfTxGainStage; // Tx gain stage: + // 0x80c~0x80f [4 bytes] + unsigned int rfHSSIPara1; // wire parameter control1 : + // 0x820~0x823,0x828~0x82b, 0x830~0x833, 0x838~0x83b [16 bytes] + unsigned int rfHSSIPara2; // wire parameter control2 : + // 0x824~0x827,0x82c~0x82f, 0x834~0x837, 0x83c~0x83f [16 bytes] + unsigned int rfSwitchControl; //Tx Rx antenna control : + // 0x858~0x85f [16 bytes] + unsigned int rfAGCControl1; //AGC parameter control1 : + // 0xc50~0xc53,0xc58~0xc5b, 0xc60~0xc63, 0xc68~0xc6b [16 bytes] + unsigned int rfAGCControl2; //AGC parameter control2 : + // 0xc54~0xc57,0xc5c~0xc5f, 0xc64~0xc67, 0xc6c~0xc6f [16 bytes] + unsigned int rfRxIQImbalance; //OFDM Rx IQ imbalance matrix : + // 0xc14~0xc17,0xc1c~0xc1f, 0xc24~0xc27, 0xc2c~0xc2f [16 bytes] + unsigned int rfRxAFE; //Rx IQ DC ofset and Rx digital filter, Rx DC notch filter : + // 0xc10~0xc13,0xc18~0xc1b, 0xc20~0xc23, 0xc28~0xc2b [16 bytes] + unsigned int rfTxIQImbalance; //OFDM Tx IQ imbalance matrix + // 0xc80~0xc83,0xc88~0xc8b, 0xc90~0xc93, 0xc98~0xc9b [16 bytes] + unsigned int rfTxAFE; //Tx IQ DC Offset and Tx DFIR type + // 0xc84~0xc87,0xc8c~0xc8f, 0xc94~0xc97, 0xc9c~0xc9f [16 bytes] + unsigned int rfLSSIReadBack; //LSSI RF readback data + // 0x8a0~0x8af [16 bytes] + unsigned int rfLSSIReadBackPi; //LSSI RF readback data + // 0x8b8~0x8bc [8 bytes] +}BB_REGISTER_DEFINITION_T, *PBB_REGISTER_DEFINITION_T; + +#if 1 + + +#define DESC_DMA_SIZE (NUM_RX_DESC *(sizeof(struct rx_desc))+\ + NUM_TX_DESC *(sizeof(struct tx_desc))*6 +\ + (RTL8192CD_NUM_VWLAN+1) * (sizeof(struct tx_desc))) + + +#else +#define DESC_DMA_SIZE (NUM_RX_DESC *(sizeof(struct rx_desc))+\ + NUM_TX_DESC *(sizeof(struct tx_desc))*6 +\ + NUM_CMD_DESC *(sizeof(struct rx_desc)) + \ + NUM_CMD_DESC *(sizeof(struct tx_desc))) +\ + 6 * (sizeof(struct tx_desc)) +#endif + +#ifdef CONFIG_WLAN_HAL +#define DESC_DMA_PAGE_SIZE ((DESC_DMA_SIZE + PAGE_SIZE) > DESC_DMA_PAGE_SIZE_MAX_HAL ? (DESC_DMA_SIZE + PAGE_SIZE) : DESC_DMA_PAGE_SIZE_MAX_HAL) +#else +//#define DESC_DMA_PAGE_SIZE ((DESC_DMA_SIZE + (2*PAGE_SIZE - 1)) & (~(PAGE_SIZE - 1))) +#define DESC_DMA_PAGE_SIZE ((DESC_DMA_SIZE + PAGE_SIZE)) +#endif //CONFIG_WLAN_HAL + +struct rtl8192cd_tx_desc_info { + //enum _TX_QUEUE_ { + struct tx_desc_info tx_info0[NUM_TX_DESC]; + struct tx_desc_info tx_info1[NUM_TX_DESC]; + struct tx_desc_info tx_info2[NUM_TX_DESC]; + struct tx_desc_info tx_info3[NUM_TX_DESC]; + struct tx_desc_info tx_info4[NUM_TX_DESC]; + struct tx_desc_info tx_info5[NUM_TX_DESC]; +#if 0 +//#if defined(CONFIG_WLAN_HAL) + //high queue 1~7 + struct tx_desc_info tx_info6[NUM_TX_DESC_HQ]; + struct tx_desc_info tx_info7[NUM_TX_DESC_HQ]; + struct tx_desc_info tx_info8[NUM_TX_DESC_HQ]; + struct tx_desc_info tx_info9[NUM_TX_DESC_HQ]; + struct tx_desc_info tx_info10[NUM_TX_DESC_HQ]; + struct tx_desc_info tx_info11[NUM_TX_DESC_HQ]; + struct tx_desc_info tx_info12[NUM_TX_DESC_HQ]; +#endif +}; + +struct rtl8192cd_hw { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + atomic_t seq; +#elif defined(CONFIG_PCI_HCI) + unsigned short seq; // sw seq +#endif +#ifdef BEAMFORMING_SUPPORT + unsigned short sounding_seq; +#endif + +#ifdef WIFI_WMM +// unsigned short AC_seq[8]; + +// switch BE to VI + unsigned int VO_pkt_count; + unsigned int VI_pkt_count; + unsigned int VI_rx_pkt_count; +#ifdef WMM_VIBE_PRI + unsigned int BE_pkt_count; +#endif + unsigned int BK_pkt_count; +#endif + +#if defined(RTLWIFINIC_GPIO_CONTROL) + unsigned char GPIO_dir[16]; // bit[0-1] 0x01: input, 0x10: output +#ifdef PCIE_POWER_SAVING + unsigned int GPIO_cache[2]; +#endif +#endif + +#ifndef PRIV_STA_BUF + unsigned long alloc_dma_buf; +#endif + +#ifdef CONFIG_PCI_HCI + unsigned long ring_dma_addr; + unsigned long ring_virt_addr; + unsigned int ring_buf_len; + unsigned int cur_rx; +#ifdef DELAY_REFILL_RX_BUF + unsigned int cur_rx_refill; +#endif + struct rx_desc *rx_descL; + unsigned long rx_ring_addr; + struct rx_desc_info rx_infoL[NUM_RX_DESC]; + + /* For TX DMA Synchronization */ + unsigned long rx_descL_dma_addr[NUM_RX_DESC]; + + unsigned int txhead0; + unsigned int txhead1; + unsigned int txhead2; + unsigned int txhead3; + unsigned int txhead4; + unsigned int txhead5; + + unsigned int txtail0; + unsigned int txtail1; + unsigned int txtail2; + unsigned int txtail3; + unsigned int txtail4; + unsigned int txtail5; + + struct tx_desc *tx_desc0; + struct tx_desc *tx_desc1; + struct tx_desc *tx_desc2; + struct tx_desc *tx_desc3; + struct tx_desc *tx_desc4; + struct tx_desc *tx_desc5; + struct tx_desc *tx_descB; + + /* For TX DMA Synchronization */ + unsigned long tx_desc0_dma_addr[NUM_TX_DESC]; + unsigned long tx_desc1_dma_addr[NUM_TX_DESC]; + unsigned long tx_desc2_dma_addr[NUM_TX_DESC]; + unsigned long tx_desc3_dma_addr[NUM_TX_DESC]; + unsigned long tx_desc4_dma_addr[NUM_TX_DESC]; + unsigned long tx_desc5_dma_addr[NUM_TX_DESC]; + unsigned long tx_descB_dma_addr[NUM_TX_DESC]; + + unsigned long tx_ring0_addr; + unsigned long tx_ring1_addr; + unsigned long tx_ring2_addr; + unsigned long tx_ring3_addr; + unsigned long tx_ring4_addr; + unsigned long tx_ring5_addr; + unsigned long tx_ringB_addr; +#if 0//no use now + unsigned int cur_rxcmd; + struct rx_desc *rxcmd_desc; + unsigned long rxcmd_ring_addr; + struct rx_desc_info rxcmd_info[NUM_CMD_DESC]; + unsigned long rxcmd_desc_dma_addr[NUM_CMD_DESC]; + + unsigned int txcmdhead; + unsigned int txcmdtail; + struct tx_desc *txcmd_desc; + unsigned long txcmd_desc_dma_addr[NUM_CMD_DESC]; + unsigned long txcmd_ring_addr; +#endif +#endif // CONFIG_PCI_HCI + + char MCSTxAgcOffset_A[16]; + char MCSTxAgcOffset_B[16]; + char OFDMTxAgcOffset_A[8]; + char OFDMTxAgcOffset_B[8]; + char VHTTxAgcOffset_A[20]; + char VHTTxAgcOffset_B[20]; + //_TXPWR_REDEFINE ?? int or char ?? +#if 0 + int CCKTxAgc_A[4]; + int CCKTxAgc_B[4]; +#endif + char CCKTxAgc_A[4]; + char CCKTxAgc_B[4]; + + unsigned int NumTotalRFPath; + /*PHY related*/ + BB_REGISTER_DEFINITION_T PHYRegDef[4]; //Radio A/B/C/D + + // Joseph test for shorten RF config. + unsigned int RfReg0Value[4]; + + // for DIG checking + unsigned char signal_strength; // 1=low and dig off, 2=normal and dig on, 3=high power and dig on + +//#ifdef INTERFERENCE_CONTROL + // for NBI filter checking + unsigned char nbi_filter_on; +//#endif + + // dynamic CCK Tx power by rssi + unsigned char CCKTxAgc_enhanced; + + // dynamic CCK CCA enhance by rssi + unsigned char CCK_CCA_enhanced; + + unsigned char EDCCA_on; + + // for Multicast Rx dynamic mechanism + unsigned char rxmlcst_rssi; + unsigned char initial_gain; + + // MIMO TR hw support checking + unsigned char MIMO_TR_hw_support; + + // dynamic Rx path selection by signal strength + unsigned char ant_off_num; + unsigned char ant_off_bitmap; + unsigned char ant_on_criteria[4]; + unsigned char ant_cck_sel; + + // Tx power control + unsigned char lower_tx_power; + unsigned int power_backup[15]; +/* + // Tx power tracking +#if defined(RTL8190) || defined(RTL8192E) + unsigned char tpt_inited; + unsigned char tpt_ofdm_swing_idx; + unsigned char tpt_cck_swing_idx; + unsigned char tpt_tssi_total; + unsigned char tpt_tssi_num; + unsigned char tpt_tssi_waiting; + unsigned char tpt_tracking_num; +#endif +*/ +// struct timer_list tpt_timer; +#ifdef CONFIG_PCI_HCI + struct rtl8192cd_tx_desc_info tx_info; +#endif + + unsigned char check_reg824; + unsigned int reg824_bit9; + + unsigned char InternalPA5G[2]; + unsigned char bNewTxGainTable; + + unsigned char RTSInitRate; + unsigned char RTSInitRate_Candidate; + unsigned char LowestInitRate; +// unsigned char bErpProtection; + +#if defined(CONFIG_USB_HCI) && defined(CONFIG_RTL_92C_SUPPORT) + unsigned char HIQ_nolimit_en; +#endif +}; + +//1------------------------------------------------------------------- +//1RTL_8192CD related definition +//1--------------------------------------------------------------------- + +//-------------------------------------------------------------------------------- +// 8192S Firmware related +//-------------------------------------------------------------------------------- +typedef struct __RTL8192C_FW_HDR__ { + unsigned int signature:16; + unsigned int category:8; + unsigned int function:8; + + unsigned int version:16; + unsigned int subversion:8; + unsigned int rsvd1:8; + + unsigned int month:8; + unsigned int day:8; + unsigned int hour:8; + unsigned int minute:8; + + unsigned int ram_code_size:16; + unsigned int year:16; + + unsigned int svnidx; + unsigned int rsvd5; + unsigned int rsvd6; + unsigned int rsvd7; +} RTL8192C_FW_HDR, *PRTL8192C_FW_HDR; + +enum __RTL8192C_SIGNATURE__ +{ + RTL8192C_TEST_CHIP = 0x92C0, + RTL8188C_TEST_CHIP = 0x88C0, + RTL8192C_MP_CHIP_A = 0x92C1, + RTL8188C_MP_CHIP_A = 0x88C1, + RTL8192C_MP_CHIP_B = 0x92C2, + RTL8188C_MP_CHIP_B = 0x88C2 +}; + +enum __RTL8192C_FW_CATEGORY__ +{ + RTL8192C_NIC_PCIE = 0, + RTL8192C_NIC_USB = 1, + RTL8192C_AP_PCIE = 4, + RTL8192C_AP_USB = 5 +}; + +enum __RTL8192C_FW_FUNCTION__ +{ + RTL8192C_NIC_NORMAL = 0, + RTL8192C_NIC_WWLAN = 1, + RTL8192C_AP_NORMAL = 2, + RTL8192C_AP_SUSPEND = 3 +}; + +#define RT_8192CD_FIRMWARE_HDR_SIZE 32 + +enum _RTL8192CD_TX_DESC_ { + // TX cmd desc + // Dword 0 + TX_OWN = BIT(31), + TX_GF = BIT(30), + TX_NoACM = BIT(29), + TX_LINIP = BIT(28), + TX_FirstSeg = BIT(27), + TX_LastSeg = BIT(26), + TX_HTC = BIT(25), + TX_BMC = BIT(24), + TX_OffsetSHIFT = 16, + TX_OffsetMask = 0x0FF, + TX_PktSizeSHIFT = 0, + TX_PktSizeMask = 0x0FFFF, + +// TX_AMSDU = BIT(29), +// TX_TYPESHIFT = 24, +// TX_TYPEMask = 0x3, + + + // Dword 1 +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_MOREDATA = BIT(29), +#endif +// TX_PaddingSHIFT = 24, +// TX_PaddingMask = 0x0FF, + TX_PktOffsetSHIFT = 26, + TX_PktOffsetMask = 0x01F, + TX_SecTypeSHIFT = 22, + TX_SecTypeMask = 0x03, + TX_EnDescID = BIT(21), + TX_NAVUSEHDR = BIT(20), + TX_RateIDSHIFT = 16 , +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_RateIDMask = 0x1F, +#endif + TX_RateIDMask = 0x0F, + TX_PIFS = BIT(15), + TX_LSigTxopEn = BIT(14), + TX_RdNavExt = BIT(13), + TX_QSelSHIFT = 8, + TX_QSelMask = 0x01F, + TX_RdEn = BIT(7), + TX_BK = BIT(6), + TX_AggEn = BIT(5), + TX_MacIdSHIFT = 0, + TX_MacIdMask = 0x01F, +#ifdef CONFIG_RTL_88E_SUPPORT + TXdesc_88E_MacIdSHIFT = 0, + TXdesc_88E_MacIdMask = 0x03F, +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_MacIdMask = 0x07F, +#endif +// TX_MoreData = BIT(5), +// TX_MoreFrag = BIT(6), +// TX_AckPolicySHIFT = 13, +// TX_AckPolicyMask = 0x3, // 2 bits +// TX_NoACM = BIT(15), +// TX_NonQos = BIT(16), +// TX_KeyIDSHIFT = 17 , +// TX_OUI = BIT(19), +// TX_PktType = BIT(20), +// TX_HTC = BIT(24), //padding0 +// TX_WDS = BIT(25), //padding1 +// TX_HWPC = BIT(31), + + + // DWORD 2 + TX_TxAntHtSHIFT = 30, + TX_TxAntHtMask = 0x03, + TX_TxAntlSHIFT = 28, + TX_TxAntlMask = 0x03, + TX_TxAntCckSHIFT = 26, + TX_TxAntCckMask = 0x03, + TX_AntSelB = BIT(25), + TX_AntSelA = BIT(24), +#ifdef CONFIG_RTL_88E_SUPPORT + TXdesc_88E_BtInt = BIT(23), +#endif + TX_AmpduDstySHIFT = 20, + TX_AmpduDstyMask = 0x07, + TX_CCX = BIT(19), + TX_RAW = BIT(18), + TX_MoreFrag = BIT(17), +#ifdef CONFIG_RTL_88E_SUPPORT + TXdesc_88E_BK = BIT(16), +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_BK = BIT(16), +#endif + TX_BarRtyThSHIFT = 14, + TX_BarRtyThMask = 0x03, +#ifdef CONFIG_RTL_88E_SUPPORT + TXdesc_88E_RdEn = BIT(13), + TXdesc_88E_AggEn = BIT(12), +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_RdEn = BIT(13), + TXdesc_92E_AggEn = BIT(12), +#endif + TX_DataRcSHIFT = 6, + TX_DataRcMask = 0x03F, + TX_RtsRcSHIFT = 0, + TX_RtsRcMask = 0x03F, + + + TX_8812_CcaRtsSHIFT = 10, + TX_8812_CcaRtsMask = 0x03, + +#ifdef BEAMFORMING_SUPPORT + TX_8812_PAIDSHIFT = 0, + TX_8812_PAIDMask = 0x1ff, + TX_8812_GIDSHIFT = 24, + TX_8812_GIDMask = 0x3f, +#endif + +// TX_DataRetryLmtSHIFT = 0, +// TX_DataRetryLmtMask = 0x3F, // 6 bits +// TX_RetryLmtEn = BIT(6), +// TX_TSFLSHIFT = 7, +// TX_TSFLMask = 0x1f, +// TX_RTSRCSHIFT = 12, +// TX_RTSRCMask = 0x3F, // Reserved for HW RTS Retry Count. +// TX_DATARCSHIFT = 18, +// TX_DATARCMask = 0x3F , // Reserved for HW DATA Retry Count. + //TX_Rsvd1:5; +// TX_AggEn =BIT(29), +// TX_BK = BIT(30), //Aggregation break. +// TX_OwnMAC = BIT(31), + + + //DWORD3 +#ifdef CONFIG_RTL_88E_SUPPORT + TXdesc_88E_EnHwSeq = BIT(31), + TXdesc_88E_TriggerInt = BIT(30), + TXdesc_88E_Tagi = BIT(29), + TXdesc_88E_CpuHandle = BIT(28), +#endif + TX_PktIdSHIFT = 28, + TX_PktIdMask = 0x0F, + TX_SeqSHIFT = 16, + TX_SeqMask = 0x0FFF, +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_NDPASHIFT = 22, + TXdesc_92E_NDPAMASK = 0x03, + TXdesc_92E_NAVUSEHDR = BIT(15), + TXdesc_92E_PortId = BIT(14), + TXdesc_92E_HwRtsEn = BIT(13), + TXdesc_92E_RtsEn = BIT(12), + TXdesc_92E_CTS2Self = BIT(11), + TXdesc_92E_DisDataFB = BIT(10), + TXdesc_92E_DisRtsFB = BIT(9), + TXdesc_92E_UseRate = BIT(8), +#endif + TX_TailPageSHIFT = 8, + TX_TailPageMask = 0x0FF, + TX_NextHeadPageSHIFT = 0, + TX_NextHeadPageMask = 0x0FF, + +// TX_FragSHIFT = 28, +// TX_FragMask = 0xF, + + + // DWORD 4 + TX_CtrlStbcSHIFT = 30, + TX_CtrlStbcMask = 0x03, + TX_RtsScSHIFT = 28, + TX_RtsScMask = 0x3, + TX_RtsBw = BIT(27), + TX_RtsShort = BIT(26), + TX_DataBw = BIT(25), + TX_DataShort = BIT(24), +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_RtsRateSHIFT = 24, + TXdesc_92E_RtsRateMask = 0x01F, +#endif + TX_DataStbcSHIFT = 22, + TX_DataStbcMask = 0x03, + TX_DataScSHIFT = 20, + TX_DataScMask = 0x03, + TX_CTS2AP = BIT(19), + TX_WaitDCTS = BIT(18), +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_DataRtyLmtSHIFT = 18, + TXdesc_92E_DataRtyLmtMask = 0x03F, +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + TXdesc_88E_PwrStatusSHIFT = 15, + TXdesc_88E_PwrStatusMask = 0x07, + TXdesc_88E_PortId = BIT(14), +#endif + TX_HwRtsEn = BIT(13), +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_RtyLmtEn = BIT(17), + + TXdesc_92E_RtsRateFBLmtSHIFT = 13, + TXdesc_92E_RtsRateFBLmtMask = 0x0f, + +#endif + TX_RtsEn = BIT(12), + TX_CTS2Self = BIT(11), + TX_DisDataFB = BIT(10), + TX_DisRtsFB = BIT(9), + TX_UseRate = BIT(8), +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_DataRateFBLmtSHIFT = 8, + TXdesc_92E_DataRateFBLmtMask = 0x01F, +#endif + TX_HwSeqEn = BIT(7), + TX_QOS = BIT(6), +#ifdef CONFIG_RTL_88E_SUPPORT + TXdesc_88E_HwSeqSelSHIFT = 6, + TXdesc_88E_HwSeqSelMask = 0x03, +#endif + TX_ApDCFE = BIT(5), + TX_RtsRateSHIFT = 0, + TX_RtsRateMask = 0x01F, +#ifdef CONFIG_RTL_8812_SUPPORT + TX_RtsRateSHIFT_8812 = 24, + TX_RtsRateMask_8812 = 0x01F, + TXdesc_92E_DataRateSHIFT = 0, + TXdesc_92E_DataRateMask = 0x7F, +#endif +// TX_RTSRateFBLmtSHIFT = 7, +// TX_RTSRateFBLmtMask = 0xF, +// TX_RaBRSRIDSHIFT = 13, //Rate adaptive BRSR ID. +// TX_RaBRSRIDMask = 0x7, // 3bits +// TX_TXHT = BIT(16), +// TX_RD = BIT(23), +// TX_RTSHT = BIT(24), +// TX_RTSSTBCSHIFT = 29, +// TX_RTSSTBCMask = 0x3, + + + // DWORD 5 + TX_UsbAggNumSHIFT = 24, + TX_UsbAggNumMask = 0x0FF, + TX_DataRtyLmtSHIFT = 18, + TX_DataRtyLmtMask = 0x03F, + TX_RtyLmtEn = BIT(17), + TX_RtsRateFBLmtSHIFT = 13, + TX_RtsRateFBLmtMask = 0x0F, +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_RtsScSHIFT = 13, + TXdesc_92E_RtsScMask = 0xf, + TXdesc_92E_RtsShort = BIT(12), + TXdesc_92E_DataLDPCSHIFT = 7, + TXdesc_92E_DataStbcSHIFT = 8, + TXdesc_92E_DataStbcMask = 0x03, +#endif + TX_DataRateFBLmtSHIFT = 8, + TX_DataRateFBLmtMask = 0x01F, + TX_CcxTag = BIT(7), +#ifdef CONFIG_RTL_88E_SUPPORT + TXdesc_88E_TryRate = BIT(7), +#endif + TX_SGI = BIT(6), + TX_DataRateSHIFT = 0, + TX_DataRateMask = 0x03F, + +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_DataBwSHIFT = 5, + TXdesc_92E_DataBwMask = 0x03, + TXdesc_92E_DataShort = BIT(4), + TXdesc_92E_DataScSHIFT = 0, + TXdesc_92E_DataScMask = 0x0f, + TXdesc_92E_DataLDPC = BIT(7), + DATA_RATE_FB_LIMIT = 8, + RTS_RATE_FB_LIMIT = 13, + + TXdesc_8812_TxPwrOffetSHIFT = 28, + TXdesc_8812_TxPwrOffetMask = 0x7, +#endif + +// TX_PktIDSHIFT = 0, +// TX_PktIDMask = 0x1FF, +// TX_DISFB = BIT(15), +// TX_TxAGCSHIFT = 21, +// TX_TxAGCMask = 0x7FF, + + + // DWORD 6 + TX_MCS7SgiMaxSHIFT = 28, + TX_MCS7SgiMaxMask = 0x0F, + TX_MCS3gMaxSHIFT = 24, + TX_MCS3gMaxMask = 0x0F, + TX_MCS2gMaxSHIFT = 20, + TX_MCS2gMaxMask = 0x0F, + TX_MCS1gMaxSHIFT = 16, + TX_MCS1gMaxMask = 0x0F, + TX_MaxAggNumSHIFT = 11, + TX_MaxAggNumMask = 0x01F, + TX_UseMaxLen = BIT(10), + TX_TxAgcBSHIFT = 5, + TX_TxAgcBMask = 0x01F, + TX_TxAgcASHIFT = 0, + TX_TxAgcAMask = 0x01F, + +// TX_IPChkSumSHIFT = 0, +// TX_IPChkSumMask = 0xFFFF, +// TX_TCPChkSumSHIFT = 16, +// TX_TCPChkSumMask = 0xFFFF, + + + // DWORD 7 +#ifdef CONFIG_RTL_88E_SUPPORT + TXdesc_88E_Null1 = BIT(31), + TXdesc_88E_Null0 = BIT(30), + TXdesc_88E_AntSelC = BIT(29), + TXdesc_88E_SwOffset31SHIFT = 27, + TXdesc_88E_SwOffset31Mask = 0x0F, + TXdesc_88E_SwOffset30SHIFT = 23, + TXdesc_88E_SwOffset30Mask = 0x0F, + TXdesc_88E_SwOffset29SHIFT = 19, + TXdesc_88E_SwOffset29Mask = 0x0F, +#endif + TX_MCS15SgiMaxSHIFT = 28, + TX_MCS15SgiMaxMask = 0x0F, + TX_MCS6gMaxSHIFT = 24, + TX_MCS6gMaxMask = 0x0F, + TX_MCS5gMaxSHIFT = 20, + TX_MCS5gMaxMask = 0x0F, + TX_MCS4gMaxSHIFT = 16, + TX_MCS4gMaxMask = 0x0F, + TX_TxBufSizeSHIFT = 0, + TX_TxBufSizeMask = 0x0FFFF, + +// TX_IPHdrOffsetSHIFT = 16, +// TX_IPHdrOffsetMask = 0xFF, +// unsigned int Rsvd2:7; +// TX_TCPEn = BIT(31), + + // DWORD 9 +#if defined(CONFIG_RTL_8812_SUPPORT) + TXdesc_92E_TX_SeqSHIFT = 12, + TXdesc_92E_TX_SeqMask = 0x0FFF, + TXdesc_92E_TX_GroupIEEnable = BIT(7), + TXdesc_92E_TX_GroupIESHIFT = 0, + TXdesc_92E_TX_GroupIEMask = 0xFF, +#endif +}; + + + +enum _RTL8192CD_RX_DESC_ { + // RX cmd desc + // Dword 0 + RX_OWN = BIT(31), + RX_EOR = BIT(30), + RX_FirstSeg = BIT(29), + RX_LastSeg = BIT(28), + RX_SwDec = BIT(27), + RX_PHYST = BIT(26), + RX_ShiftSHIFT = 24, + RX_ShiftMask = 0x03, + RX_QOS = BIT(23), + RX_SecuritySHIFT = 20, + RX_SecurityMask = 0x07, + RX_DrvInfoSizeSHIFT = 16, + RX_DrvInfoSizeMask = 0x0F, + RX_ICVERR = BIT(15), + RX_CRC32 = BIT(14), +#if defined(CONFIG_RTL_8812_SUPPORT) + RXdesc_92E_FirstSeg = BIT(15), + RXdesc_92E_LastSeg = BIT(14), +#endif + RX_PktLenSHIFT = 0, + RX_PktLenMask = 0x03FFF, + + + // Dword 1 + RX_BC = BIT(31), + RX_MC = BIT(30), + RX_TypeSHIFT = 28, + RX_TypeMask = 0x03, + RX_MoreFrag = BIT(27), + RX_MoreData = BIT(26), + RX_PWRMGT = BIT(25), + RX_PAM = BIT(24), + RX_A2FitSHIFT = 20, + RX_A2FitSHIFMask = 0x0F, + RX_A1FitSHIFT = 16, + RX_A1FitSHIFMask = 0x0F, + RX_FAGGR = BIT(15), +#if defined(CONFIG_RTL_8812_SUPPORT) + RXdesc_92E_PAGGR = BIT(15), +#endif + RX_PAGGR = BIT(14), + RX_AMSDU = BIT(13), + RX_HwRsvdSHIFT = 9, + RX_HwRsvdMask = 0x0F, +#ifdef CONFIG_RTL_88E_SUPPORT + RXdesc_88E_TidSHIFT = 8, +#endif + RX_TidSHIFT = 5, + RX_TidMask = 0x0F, + RX_MacIdSHIFT = 0, + RX_MacIdMask = 0x01F, +#ifdef CONFIG_RTL_88E_SUPPORT + RXdesc_88E_MacIdMask = 0x03F, +#endif + + + // DWORD 2 + RX_NextInd = BIT(30), + RX_NextPktLenSHIFT = 16, +#ifdef CONFIG_RTL_88E_SUPPORT + RXdesc_88E_NextPktLenMask = 0x0FF, +#endif + RX_NextPktLenMask = 0x03FFF, + RX_FragSHIFT = 12, + RX_FragMask = 0x0F, + RX_SeqSHIFT = 0, + RX_SeqMask = 0x0FFF, + + + //DWORD3 +#ifdef CONFIG_RTL_88E_SUPPORT + RXdesc_88E_MagicWake = BIT(31), + RXdesc_88E_UCwake = BIT(30), + RXdesc_88E_PtnMatch = BIT(29), +#endif + RX_IV0SHIFT = 16, + RX_IV0Mask = 0x0FFFF, +#ifdef CONFIG_RTL_88E_SUPPORT + RXdesc_88E_RptSelSHIFT = 14, + RXdesc_88E_RptSelMask = 0x03, +#endif + RX_HwPCInd = BIT(15), + RX_HwPCErr = BIT(14), + RX_TCPChkValid = BIT(13), + RX_IPChkRpt = BIT(12), + RX_TCPChkRpt = BIT(11), + RX_HTC = BIT(10), + RX_BW = BIT(9), + RX_SPLCP = BIT(8), + RX_GF = BIT(7), + RX_RxHT = BIT(6), + RX_RxMcsSHIFT = 0, + RX_RxMcsMask = 0x03F, + + + //DWORD8 + RX_BaVld = BIT(11), + RX_BaSsnSHIFT = 0, + RX_BaSsnMask = 0x07FF, +}; + +#ifdef ADD_TX_POWER_BY_CMD +#define ASSIGN_TX_POWER_OFFSET(offset, setting) { \ + if (setting != 0x7f) \ + offset = setting; \ +} +#endif + +/*------------------------------------------------------------------------------ + Below we define some useful readline functions... +------------------------------------------------------------------------------*/ +static __inline__ struct sk_buff *get_skb_frlist(struct list_head *list,unsigned int offset) +{ + unsigned long pobj; + + pobj = ((unsigned long)list - offset); + + return ((struct rx_frinfo *)pobj)->pskb; +} + +#ifdef CONFIG_PCI_HCI +static __inline__ int get_txhead(struct rtl8192cd_hw *phw, int q_num) +{ + return *(int *)((unsigned long)&(phw->txhead0) + sizeof(int)*q_num); +} + +static __inline__ int get_txtail(struct rtl8192cd_hw *phw, int q_num) +{ + return *(int *)((unsigned long)&(phw->txtail0) + sizeof(int)*q_num); +} + +static __inline__ int *get_txhead_addr(struct rtl8192cd_hw *phw, int q_num) +{ + return (int *)((unsigned long)&(phw->txhead0) + sizeof(int)*q_num); +} + +static __inline__ int *get_txtail_addr(struct rtl8192cd_hw *phw, int q_num) +{ + return (int *)((unsigned long)&(phw->txtail0) + sizeof(int)*q_num); +} + +static __inline__ struct tx_desc *get_txdesc(struct rtl8192cd_hw *phw, int q_num) +{ + return (struct tx_desc *)(*(unsigned int *)((unsigned long)&(phw->tx_desc0) + sizeof(struct tx_desc *)*q_num)); +} + +#if 0 +static __inline__ struct tx_desc_info *get_txdesc_info(struct rtl8192cd_tx_desc_info*pdesc, int q_num) +{ + return (struct tx_desc_info *)((unsigned long)(pdesc->tx_info0) + sizeof(struct tx_desc_info)*q_num*NUM_TX_DESC); +} +#else +#define TXDESC_HIGH_QUEUE_NUM 5 +static __inline__ struct tx_desc_info *get_txdesc_info(struct rtl8192cd_tx_desc_info*pdesc, int q_num) +{ + // code below that depend on structure of rtl8192cd_tx_desc_info + unsigned int NumOfOffsetBytes; + + if (q_num < TXDESC_HIGH_QUEUE_NUM) { + NumOfOffsetBytes = sizeof(struct tx_desc_info)*q_num*NUM_TX_DESC; + } + else { + NumOfOffsetBytes = sizeof(struct tx_desc_info)*(TXDESC_HIGH_QUEUE_NUM*NUM_TX_DESC + (q_num-TXDESC_HIGH_QUEUE_NUM)*NUM_TX_DESC_HQ); + } + + return (struct tx_desc_info *)((unsigned long)(pdesc->tx_info0) + NumOfOffsetBytes); +} +#endif + +static __inline__ unsigned long *get_txdma_addr(struct rtl8192cd_hw *phw, int q_num) +{ + return (unsigned long *)((unsigned long)&(phw->tx_desc0_dma_addr) + (sizeof(unsigned long)*q_num*NUM_TX_DESC)); +} +#endif // CONFIG_PCI_HCI + +#define RTL8192CD_REGS_SIZE ((0xff + 1) * 16) //16 pages + + +//---------------------------------------------------------------------------- +// 8192SE EFUSE +//---------------------------------------------------------------------------- +#ifdef EN_EFUSE + +#define EFUSE_MAX_SECTION_BASE 16 +#if 0 +#ifdef CONFIG_RTL_88E_SUPPORT +#define EFUSE_REAL_CONTENT_LEN 256 +#define EFUSE_MAP_LEN 512 +#define EFUSE_MAX_SECTION 64 +// To prevent out of boundary programming case, leave 1byte and program full section +// 9bytes + 1byt + 5bytes and pre 1byte. +// For worst case: +// | 2byte|----8bytes----|1byte|--7bytes--| //92D +#define EFUSE_OOB_PROTECT_BYTES 18 // PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte. +#elif defined(CONFIG_WLAN_HAL_8192EE) +#define EFUSE_REAL_CONTENT_LEN 512 +#define EFUSE_MAP_LEN 512 +#define EFUSE_MAX_SECTION 64 +#define EFUSE_OOB_PROTECT_BYTES 15 +#elif defined(CONFIG_RTL_92D_SUPPORT) +#define EFUSE_REAL_CONTENT_LEN 1024 +#define EFUSE_MAP_LEN 256 +#define EFUSE_MAX_SECTION 32 +// To prevent out of boundary programming case, leave 1byte and program full section +// 9bytes + 1byt + 5bytes and pre 1byte. +// For worst case: +// | 2byte|----8bytes----|1byte|--7bytes--| //92D +#define EFUSE_OOB_PROTECT_BYTES 18 // PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte. +#elif defined(CONFIG_RTL_8812_SUPPORT) +#define EFUSE_REAL_CONTENT_LEN 1024 +#define EFUSE_MAP_LEN 512 +#define EFUSE_MAX_SECTION 64 +#define EFUSE_OOB_PROTECT_BYTES 506 //For some inferiority IC purpose. added by Roger, 2009.09.02. +#else +#define EFUSE_REAL_CONTENT_LEN 512 +#define EFUSE_MAP_LEN 128 +#define EFUSE_MAX_SECTION 16 +// | 1byte|----8bytes----|1byte|--5bytes--| +#define EFUSE_OOB_PROTECT_BYTES 15 // PG data exclude header, dummy 5 bytes frome CP test and reserved 1byte. +#endif +#endif +#define EFUSE_MAX_WORD_UNIT 4 +#define EFUSE_INIT_MAP 0 +#define EFUSE_MODIFY_MAP 1 + +#define EFUSE_ERROE_HANDLE +#define PG_STATE_HEADER 0x01 +#define PG_STATE_DATA 0x20 +#define EFUSE_REPEAT_THRESHOLD_ 3 +#define PGPKT_DATA_SIZE 8 +typedef struct PG_PKT_STRUCT_A{ + UINT8 offset; + UINT8 word_en; + UINT8 data[8]; +}PGPKT_STRUCT,*PPGPKT_STRUCT; + +#endif + + +//#if defined(RTL8190) || defined(RTL8192E) + +//#define LoadPktSize 1024 + +//#elif defined(RTL8192SE) + +#define LoadPktSize 32000 + +//#endif + +/* +typedef enum _HW90_BLOCK { + HW90_BLOCK_MAC = 0, + HW90_BLOCK_PHY0 = 1, + HW90_BLOCK_PHY1 = 2, + HW90_BLOCK_RF = 3, + HW90_BLOCK_MAXIMUM = 4, // Never use this +} HW90_BLOCK_E, *PHW90_BLOCK_E; +*/ + +typedef enum _RF92CD_RADIO_PATH_ { + RF92CD_PATH_A = 0, //Radio Path A + RF92CD_PATH_B = 1, //Radio Path B +#if defined(CONFIG_WLAN_HAL_8814AE) + RF92CD_PATH_C = 2, //Radio Path C + RF92CD_PATH_D = 3, //Radio Path D +#endif + RF92CD_PATH_MAX //Max RF number 92cd support +} RF92CD_RADIO_PATH_E, *PRF92CD_RADIO_PATH_E; +/* +typedef enum _FW_LOAD_FILE { + BOOT = 0, + MAIN = 1, + DATA = 2, +//#ifdef RTL8192SE + LOAD_IMEM = 3, + LOAD_EMEM = 4, + LOAD_DMEM = 5, +//#endif +} FW_LOAD_FILE; +*/ +typedef enum _PHY_REG_FILE { + AGCTAB, + PHYREG_1T2R, + PHYREG_2T2R, + PHYREG_1T1R, + PHYREG_PG, + PHYREG_MP, + PHYREG, +} PHY_REG_FILE; + +enum REG_FILE_FORMAT { + TWO_COLUMN, + THREE_COLUMN, + FIVE_COLUMN +}; + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) +typedef enum _PHYREG_PG_TBL_IDX_ { + BGN_2040_ALL = 0, + BGN_20_CH1_3 = 1, + BGN_20_CH4_9 = 2, + BGN_20_CH10_14 = 3, + BGN_40_CH1_3 = 4, + BGN_40_CH4_9 = 5, + BGN_40_CH10_14 = 6, + AN_20_CH_36_64 = 7, + AN_20_CH_100_140 = 8, + AN_20_CH_149_165 = 9, + AN_40_CH_36_64 = 10, + AN_40_CH_100_140 = 11, + AN_40_CH_149_165 = 12 +}PHYREG_PG_TBL_IDX; + +typedef enum _TXPWR_LMT_TBL_IDX_ { + NO_RESTRICT = 0, + FCC_CCK = 1, + FCC_OFDM = 2, + FCC_20M1S = 3, + FCC_20M2S = 4, + FCC_40M1S = 5, + FCC_40M2S = 6, +}TXPWR_LMT_TBL_IDX; +#endif + +#ifndef CONFIG_WLAN_HAL +typedef enum _MIMO_TR_STATUS { + MIMO_1T2R = 1, + MIMO_2T4R = 2, + MIMO_2T2R = 3, + MIMO_2T3R = 4, + MIMO_1T1R = 5, + MIMO_3T3R = 6, + MIMO_3T4R = 7, + MIMO_4T4R = 8, +} MIMO_TR_STATUS; +#endif + +typedef enum _PHY_BAND_SELECT_ { + PHY_BAND_2G = BIT(0), + PHY_BAND_5G = BIT(1) +} PHY_BAND_SELECT; + +typedef enum _band5GSelected_ { + PHY_BAND_5G_1 = BIT(0), // CH 36,40,44,48 + PHY_BAND_5G_2 = BIT(1), // CH 52,56,60,64 + PHY_BAND_5G_3 = BIT(2), // CH 100,104,...,144 + PHY_BAND_5G_4 = BIT(3) // CH 149,153,..,177 +} BAND5GSELECT; + +typedef enum _MAC_PHY_MODE_ { + SINGLEMAC_SINGLEPHY = 0, + DUALMAC_SINGLEPHY = 1, + DUALMAC_DUALPHY = 2 +} MAC_PHY_MODE; + +struct MacRegTable { + unsigned int offset; + unsigned int mask; + unsigned int value; +}; + +#ifdef TXPWR_LMT +struct TxPwrLmtTable { + unsigned int start; + unsigned int end; + unsigned int limit; + unsigned int target; +}; + +#ifdef TXPWR_LMT_NEWFILE +struct TxPwrLmtTable_new { + unsigned char channel; + unsigned char limit; + unsigned char table_idx; +}; +#endif +#endif + +struct PhyRegTable { + unsigned int offset; + unsigned int value; +}; + +#ifdef _LITTLE_ENDIAN_ +struct FWtemplate { + unsigned char txRate:7; + unsigned char ctsEn:1; + unsigned char rtsTxRate:7; + unsigned char rtsEn:1; + unsigned char txHt:1; //txCtrl; // {MSB to LSB} + unsigned char txshort:1; + unsigned char txbw:1; + unsigned char txSC:2; + unsigned char txSTBC:2; + unsigned char aggren:1; + unsigned char rtsHt:1; + unsigned char rtsShort:1; + unsigned char rtsbw:1; + unsigned char rtsSC:2; + unsigned char rtsSTBC:2; + unsigned char enCPUDur:1; + unsigned char rxMF:2; + unsigned char rxAMD:3; + unsigned char ccx:1; + unsigned char rsvd0:2; + unsigned char txAGCOffset:4; + unsigned char txAGCSign:1; + unsigned char txRaw:1; + unsigned char retryLimit1:2; + unsigned char retryLimit2:2; + unsigned char rsvd1:6; + unsigned char rsvd2; +}; + +struct RxFWInfo { + unsigned char RSVD0; + unsigned char RSVD1:4; + unsigned char PAGGR:1; + unsigned char FAGGR:1; + unsigned char RSVD2:2; + unsigned char RxMCS:7; + unsigned char HT:1; + unsigned char BW:1; + unsigned char SPLCP:1; + unsigned char RSVD3:2; + unsigned char PAM:1; + unsigned char MC:1; + unsigned char BC:1; + unsigned char RxCmd:1; + unsigned long TSFL; +}; + +#else // _BIG_ENDIAN_ + +struct FWtemplate { + unsigned char ctsEn:1; + unsigned char txRate:7; + unsigned char rtsEn:1; + unsigned char rtsTxRate:7; + unsigned char aggren:1; + unsigned char txSTBC:2; + unsigned char txSC:2; + unsigned char txbw:1; + unsigned char txshort:1; + unsigned char txHt:1; //txCtrl; // {MSB to LSB} + unsigned char enCPUDur:1; + unsigned char rtsSTBC:2; + unsigned char rtsSC:2; + unsigned char rtsbw:1; + unsigned char rtsShort:1; + unsigned char rtsHt:1; + unsigned char rsvd0:2; + unsigned char ccx:1; + unsigned char rxAMD:3; + unsigned char rxMF:2; + unsigned char retryLimit1:2; + unsigned char txRaw:1; + unsigned char txAGCSign:1; + unsigned char txAGCOffset:4; + unsigned char rsvd1:6; + unsigned char retryLimit2:2; + unsigned char rsvd2; +}; + +struct RxFWInfo { + unsigned char RSVD0; + unsigned char RSVD2:2; + unsigned char FAGGR:1; + unsigned char PAGGR:1; + unsigned char RSVD1:4; + unsigned char HT:1; + unsigned char RxMCS:7; + unsigned char RxCmd:1; + unsigned char BC:1; + unsigned char MC:1; + unsigned char PAM:1; + unsigned char RSVD3:2; + unsigned char SPLCP:1; + unsigned char BW:1; + unsigned long TSFL; +}; +#endif + +typedef struct _Phy_OFDM_Rx_Status_Report_8192cd +{ + unsigned char trsw_gain_X[4]; + unsigned char pwdb_all; + unsigned char cfosho_X[4]; + unsigned char cfotail_X[4]; + unsigned char rxevm_X[2]; + unsigned char rxsnr_X[4]; + unsigned char pdsnr_X[2]; + unsigned char csi_current_X[2]; + unsigned char csi_target_X[2]; + unsigned char sigevm; + unsigned char max_ex_pwr; +//#ifdef RTL8192SE +#ifdef _LITTLE_ENDIAN_ + unsigned char ex_intf_flg:1; + unsigned char sgi_en:1; + unsigned char rxsc:2; + unsigned char rsvd:4; +#else // _BIG_ENDIAN_ + unsigned char rsvd:4; + unsigned char rxsc:2; + unsigned char sgi_en:1; + unsigned char ex_intf_flg:1; +#endif +//#else // RTL8190, RTL8192E +// unsigned char sgi_en; +// unsigned char rxsc_sgien_exflg; +//#endif +} PHY_STS_OFDM_8192CD_T; + +typedef struct _Phy_CCK_Rx_Status_Report_8192cd +{ + /* For CCK rate descriptor. This is a signed 8:1 variable. LSB bit presend + 0.5. And MSB 7 bts presend a signed value. Range from -64~+63.5. */ + char adc_pwdb_X[4]; + unsigned char SQ_rpt; + char cck_agc_rpt; +} PHY_STS_CCK_8192CD_T; + +/* +enum _8190_POLL_BITFIELD_ { + POLL_BK = BIT(0), + POLL_BE = BIT(1), + POLL_VI = BIT(2), + POLL_VO = BIT(3), + POLL_BCN = BIT(4), + POLL_CMD = BIT(5), + POLL_MGT = BIT(6), + POLL_HIGH = BIT(7), + + POLL_HCCA = BIT(0), + STOP_BK = BIT(1), + STOP_BE = BIT(2), + STOP_VI = BIT(3), + STOP_VO = BIT(4), + STOP_MGT = BIT(5), + STOP_HIGH = BIT(6), + STOP_HCCA = BIT(7), +}; + +enum _8190_CPU_RESET_BITFIELD_ { + CPURST_SysRst = BIT(0), + CPURST_RegRst = BIT(1), + CPURST_Pwron = BIT(2), + CPURST_FwRst = BIT(3), + CPURST_Brdy = BIT(4), + CPURST_FwRdy = BIT(5), + CPURST_BaseChg = BIT(6), + CPURST_PutCode = BIT(7), + CPURST_BBRst = BIT(8), + CPURST_EnUart = BIT(14), + CPURST_EnJtag = BIT(15), +}; +*/ + +// +// Firmware Queue Layout +// +#define NUM_OF_FIRMWARE_QUEUE 10 +#define NUM_OF_PAGES_IN_FW 0x100 +#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x006 +#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x024 +#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x024 +#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x006 +#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0 +#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x2 +#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x1d +#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0 +#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x4 +#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0x88 +#define APPLIED_RESERVED_QUEUE_IN_FW 0x80000000 +#define RSVD_FW_QUEUE_PAGE_BK_SHIFT 0x00 +#define RSVD_FW_QUEUE_PAGE_BE_SHIFT 0x08 +#define RSVD_FW_QUEUE_PAGE_VI_SHIFT 0x10 +#define RSVD_FW_QUEUE_PAGE_VO_SHIFT 0x18 +#define RSVD_FW_QUEUE_PAGE_MGNT_SHIFT 0x10 +#define RSVD_FW_QUEUE_PAGE_BCN_SHIFT 0x00 +#define RSVD_FW_QUEUE_PAGE_PUB_SHIFT 0x08 + +#ifndef CALIBRATE_BY_ODM +// Tx power tracking +#define TxPwrTrk_OFDM_SwingTbl_Len 37 +#define TxPwrTrk_CCK_SwingTbl_Len 23 +#define TxPwrTrk_E_Val 3 +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + +#define OFDM_TABLE_SIZE_92D 43 +#define index_mapping_NUM 13 +#define index_mapping_DPK_NUM 15 +#define Rx_index_mapping_NUM 15 +#define CCK_TABLE_SIZE_92D 33 + +#endif + +#ifdef _TRACKING_TABLE_FILE +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) +#define index_mapping_NUM_MAX 30 +#else +#define index_mapping_NUM_MAX 20 +#endif +#define TXPWR_TRACKING_NAME_NUM 20 + +enum txpwr_tracking_offset { + CCKA_P, //"2GCCKA_P" + CCKA_N, //"2GCCKA_N" + CCKB_P, //"2GCCKB_P" + CCKB_N, //"2GCCKB_N" + A_P, //"2GA_P" + A_N, //"2GA_N" + B_P, //"2GB_P" + B_N, //"2GB_N" + LA_P, //"5GLA_P" + LA_N, //"5GLA_N" + LB_P, //"5GLB_P" + LB_N, //"5GLB_N" + MA_P, //"5GMA_P" + MA_N, //"5GMA_N" + MB_P, //"5GMB_P" + MB_N, //"5GMB_N" + HA_P, //"5GHA_P" + HA_N, //"5GHA_N" + HB_P, //"5GHB_P" + HB_N, //"5GHB_N" +}; + + +#endif + + +#define RTL_ABS(a,b) ((a>b) ? (a-b) : (b-a)) + + +// +// For 8651C H/W MIC engine +// +#ifndef _ASICREGS_H +#define SYSTEM_BASE (0xB8000000) +/* Generic DMA */ +#define GDMA_BASE (SYSTEM_BASE+0xA000) /* 0xB800A000 */ +#define GDMACNR (GDMA_BASE+0x00) /* Generic DMA Control Register */ +#define GDMAIMR (GDMA_BASE+0x04) /* Generic DMA Interrupt Mask Register */ +#define GDMAISR (GDMA_BASE+0x08) /* Generic DMA Interrupt Status Register */ +#define GDMAICVL (GDMA_BASE+0x0C) /* Generic DMA Initial Checksum Value (Left Part) Register */ +#define GDMAICVR (GDMA_BASE+0x10) /* Generic DMA Initial Checksum Value (Right Part) Register */ +#define GDMASBP0 (GDMA_BASE+0x20) /* Generic DMA Source Block Pointer 0 Register */ +#define GDMASBL0 (GDMA_BASE+0x24) /* Generic DMA Source Block Length 0 Register */ +#define GDMASBP1 (GDMA_BASE+0x28) /* Generic DMA Source Block Pointer 1 Register */ +#define GDMASBL1 (GDMA_BASE+0x2C) /* Generic DMA Source Block Length 1 Register */ +#define GDMASBP2 (GDMA_BASE+0x30) /* Generic DMA Source Block Pointer 2 Register */ +#define GDMASBL2 (GDMA_BASE+0x34) /* Generic DMA Source Block Length 2 Register */ +#define GDMASBP3 (GDMA_BASE+0x38) /* Generic DMA Source Block Pointer 3 Register */ +#define GDMASBL3 (GDMA_BASE+0x3C) /* Generic DMA Source Block Length 3 Register */ +#define GDMASBP4 (GDMA_BASE+0x40) /* Generic DMA Source Block Pointer 4 Register */ +#define GDMASBL4 (GDMA_BASE+0x44) /* Generic DMA Source Block Length 4 Register */ +#define GDMASBP5 (GDMA_BASE+0x48) /* Generic DMA Source Block Pointer 5 Register */ +#define GDMASBL5 (GDMA_BASE+0x4C) /* Generic DMA Source Block Length 5 Register */ +#define GDMASBP6 (GDMA_BASE+0x50) /* Generic DMA Source Block Pointer 6 Register */ +#define GDMASBL6 (GDMA_BASE+0x54) /* Generic DMA Source Block Length 6 Register */ +#define GDMASBP7 (GDMA_BASE+0x58) /* Generic DMA Source Block Pointer 7 Register */ +#define GDMASBL7 (GDMA_BASE+0x5C) /* Generic DMA Source Block Length 7 Register */ +#define GDMADBP0 (GDMA_BASE+0x60) /* Generic DMA Destination Block Pointer 0 Register */ +#define GDMADBL0 (GDMA_BASE+0x64) /* Generic DMA Destination Block Length 0 Register */ +#define GDMADBP1 (GDMA_BASE+0x68) /* Generic DMA Destination Block Pointer 1 Register */ +#define GDMADBL1 (GDMA_BASE+0x6C) /* Generic DMA Destination Block Length 1 Register */ +#define GDMADBP2 (GDMA_BASE+0x70) /* Generic DMA Destination Block Pointer 2 Register */ +#define GDMADBL2 (GDMA_BASE+0x74) /* Generic DMA Destination Block Length 2 Register */ +#define GDMADBP3 (GDMA_BASE+0x78) /* Generic DMA Destination Block Pointer 3 Register */ +#define GDMADBL3 (GDMA_BASE+0x7C) /* Generic DMA Destination Block Length 3 Register */ +#define GDMADBP4 (GDMA_BASE+0x80) /* Generic DMA Destination Block Pointer 4 Register */ +#define GDMADBL4 (GDMA_BASE+0x84) /* Generic DMA Destination Block Length 4 Register */ +#define GDMADBP5 (GDMA_BASE+0x88) /* Generic DMA Destination Block Pointer 5 Register */ +#define GDMADBL5 (GDMA_BASE+0x8C) /* Generic DMA Destination Block Length 5 Register */ +#define GDMADBP6 (GDMA_BASE+0x90) /* Generic DMA Destination Block Pointer 6 Register */ +#define GDMADBL6 (GDMA_BASE+0x94) /* Generic DMA Destination Block Length 6 Register */ +#define GDMADBP7 (GDMA_BASE+0x98) /* Generic DMA Destination Block Pointer 7 Register */ +#define GDMADBL7 (GDMA_BASE+0x9C) /* Generic DMA Destination Block Length 7 Register */ + +/* Generic DMA Control Register */ +#define GDMA_ENABLE (1<<31) /* Enable GDMA */ +#define GDMA_POLL (1<<30) /* Kick off GDMA */ +#define GDMA_FUNCMASK (0xf<<24) /* GDMA Function Mask */ +#define GDMA_MEMCPY (0x0<<24) /* Memory Copy */ +#define GDMA_CHKOFF (0x1<<24) /* Checksum Offload */ +#define GDMA_STCAM (0x2<<24) /* Sequential T-CAM */ +#define GDMA_MEMSET (0x3<<24) /* Memory Set */ +#define GDMA_B64ENC (0x4<<24) /* Base 64 Encode */ +#define GDMA_B64DEC (0x5<<24) /* Base 64 Decode */ +#define GDMA_QPENC (0x6<<24) /* Quoted Printable Encode */ +#define GDMA_QPDEC (0x7<<24) /* Quoted Printable Decode */ +#define GDMA_MIC (0x8<<24) /* Wireless MIC */ +#define GDMA_MEMXOR (0x9<<24) /* Memory XOR */ +#define GDMA_MEMCMP (0xa<<24) /* Memory Compare */ +#define GDMA_BYTESWAP (0xb<<24) /* Byte Swap */ +#define GDMA_PATTERN (0xc<<24) /* Pattern Match */ +#define GDMA_SWAPTYPE0 (0<<22) /* Original:{0,1,2,3} => {1,0,3,2} */ +#define GDMA_SWAPTYPE1 (1<<22) /* Original:{0,1,2,3} => {3,2,1,0} */ +#define GDMA_ENTSIZMASK (3<<20) /* T-CAM Entry Size Mask */ +#define GDMA_ENTSIZ32 (0<<20) /* T-CAM Entry Size 32 bits */ +#define GDMA_ENTSIZ64 (1<<20) /* T-CAM Entry Size 64 bits */ +#define GDMA_ENTSIZ128 (2<<20) /* T-CAM Entry Size 128 bits */ +#define GDMA_ENTSIZ256 (3<<20) /* T-CAM Entry Size 256 bits */ + +/* Generic DMA Interrupt Mask Register */ +#define GDMA_COMPIE (1<<31) /* Completed Interrupt Enable */ +#define GDMA_NEEDCPUIE (1<<28) /* Need-CPU Interrupt Enable */ + +/* Generic DMA Interrupt Status Register */ +#define GDMA_COMPIP (1<<31) /* Completed Interrupt Status (write 1 to clear) */ +#define GDMA_NEEDCPUIP (1<<28) /* Need-CPU Interrupt Status (write 1 to clear) */ + +/* Generic DMA Source Block Length n. Register */ +#define GDMA_LDB (1<<31) /* Last Data Block */ +#define GDMA_BLKLENMASK (0x1fff) /* Block Length (valid value: from 1 to 8K-1 bytes) */ + +/* + * Some bits in GDMACNR are only for internal used. + * However, driver needs to configure them. + * + * burstSize[7:6] -- 00:4W, 01:8W, 10:16W, 11:32W. + * enough[5:4] -- 00:>16, 01:>10, 10:>4, 00:>0 + * dlow[3:2] -- 00:>24, 01:>20. 10:>16, 11:>8 + * slow[1:0] -- 00:>24, 01:>20. 10:>16, 11:>8 + */ +#define internalUsedGDMACNR (0x000000C0) +#endif // _ASICREGS_H + + +#ifdef CONFIG_RTL_8812_SUPPORT +typedef enum _RTL8812_H2C_CMD +{ + H2C_8812_RSVDPAGE = 0, + H2C_8812_MSRRPT = 1, + H2C_8812_KEEP_ALIVE_CTRL = 3, + H2C_8812_WO_WLAN = 5, // Wake on Wlan. + H2C_8812_REMOTE_WAKEUP = 7, + H2C_8812_AP_OFFLOAD = 8, + H2C_8812_SETPWRMODE = 0x20, + H2C_8812_P2P_PS_MODE = 0x24, + H2C_8812_RA_MASK = 0x40, + H2C_8812_RSSI_REPORT = 0x42, + H2C_8812_TX_REPORT = 0x43, + H2C_8812_RA_PARA_ADJUST = 0x46, + H2C_8812_FW_TRACE_EN = 0x49, + H2C_8812_NHM = 0xc1, + MAX_8812_H2CCMD +}RTL8812_H2C_CMD; + +typedef enum _RTL8812_C2H_CMD +{ + C2H_8812_TX_REPORT=0x4, +}RTL8812_C2H_CMD; + +#endif +#ifndef __LINUX_2_6__ +#ifndef __ECOS +#define BSP_REVR REVR +#endif +#endif + +#endif // _8192CD_HW_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_ioctl.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_ioctl.c new file mode 100755 index 000000000..b1e652394 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_ioctl.c @@ -0,0 +1,11260 @@ +/* + * io-control handling routines + * + * $Id: 8192cd_ioctl.c,v 1.36.2.14 2011/01/06 07:50:09 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_IOCTL_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#ifdef __LINUX_2_6__ +#include +#include +#endif + +#if !defined(__KERNEL__) && !defined(__ECOS) +#include "./sys-support.h" +#endif + +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + +#ifdef CONFIG_RTL_COMAPI_WLTOOLS +#include +#include +#include "./8192cd_comapi.h" +#endif +#ifdef CONFIG_RTK_MESH +// for commu with 802.11s path selection deamon;plus note +#include "../mesh_ext/mesh_route.h" +#include "../mesh_ext/hash_table.h" +#endif + +#if defined(WIFI_HAPD) || defined(RTK_NL80211) +#include +#include "net80211/ieee80211.h" +#include "net80211/ieee80211_crypto.h" +#include "net80211/ieee80211_ioctl.h" +#include "./8192cd_net80211.h" + +#ifdef RTK_NL80211 +#include "8192cd_cfg80211.h" +#endif + +#define HAPD_IOCTL_SETCONFIG SIOCIWLASTPRIV //0x8BFF +#endif + +#ifdef WIFI_WPAS +#define WPAS_IOCTL_CUSTOM SIOCIWLASTPRIV //0x8BFF +#endif + + +#define RTL8192CD_IOCTL_SET_MIB (SIOCDEVPRIVATE + 0x1) // 0x89f1 +#define RTL8192CD_IOCTL_GET_MIB (SIOCDEVPRIVATE + 0x2) // 0x89f2 +#define RTL8192CD_IOCTL_WRITE_REG (SIOCDEVPRIVATE + 0x3) // 0x89f3 +#define RTL8192CD_IOCTL_READ_REG (SIOCDEVPRIVATE + 0x4) // 0x89f4 +#define RTL8192CD_IOCTL_WRITE_MEM (SIOCDEVPRIVATE + 0x5) // 0x89f5 +#define RTL8192CD_IOCTL_READ_MEM (SIOCDEVPRIVATE + 0x6) // 0x89f6 +#define RTL8192CD_IOCTL_DEL_STA (SIOCDEVPRIVATE + 0x7) // 0x89f7 +#define RTL8192CD_IOCTL_WRITE_EEPROM (SIOCDEVPRIVATE + 0x8) // 0x89f8 +#define RTL8192CD_IOCTL_READ_EEPROM (SIOCDEVPRIVATE + 0x9) // 0x89f9 +#define RTL8192CD_IOCTL_WRITE_BB_REG (SIOCDEVPRIVATE + 0xa) // 0x89fa +#define RTL8192CD_IOCTL_READ_BB_REG (SIOCDEVPRIVATE + 0xb) // 0x89fb +#define RTL8192CD_IOCTL_WRITE_RF_REG (SIOCDEVPRIVATE + 0xc) // 0x89fc +#define RTL8192CD_IOCTL_READ_RF_REG (SIOCDEVPRIVATE + 0xd) // 0x89fd +#define RTL8192CD_IOCTL_USER_DAEMON_REQUEST (SIOCDEVPRIVATE + 0xf) // 0x89ff + +#ifdef CONFIG_RTK_MESH +#define RTL8192CD_IOCTL_STATIC_ROUTE (SIOCDEVPRIVATE + 0xe) +#define RTL8192CD_IOCTL_MANUAL_METRIC 0x8BCA +#endif +#define RTL8192CD_IOCTL_SHOWSC 0x8BCD + + +#define SIOCGIWRTLSTAINFO 0x8B30 +#define SIOCGIWRTLSTANUM 0x8B31 +#define SIOCGIWRTLDRVVERSION 0x8B32 +#define SIOCGIWRTLSCANREQ 0x8B33 +#define SIOCGIWRTLGETBSSDB 0x8B34 +#define SIOCGIWRTLJOINREQ 0x8B35 +#define SIOCGIWRTLJOINREQSTATUS 0x8B36 +#define SIOCGIWRTLGETBSSINFO 0x8B37 +#ifdef WDS +#define SIOCGIWRTLGETWDSINFO 0x8B38 +#endif +#define SIOCSIWRTLSTATXRATE 0x8B39 +#ifdef MICERR_TEST +#define SIOCSIWRTLMICERROR 0x8B3A +#define SIOCSIWRTLMICREPORT 0x8B3B +#endif +#ifdef SUPPORT_SNMP_MIB +#define SIOCGSNMPMIB 0x8B3D +#endif +#ifdef USE_PID_NOTIFY +#define SIOCSIWRTLSETPID 0x8B3E +#endif +#ifdef CONFIG_RTL_WAPI_SUPPORT +#define SIOCSIWRTLSETWAPIPID 0x8B3F +#endif +#define SIOCSMIBDATA 0x8B41 +#define SIOCMIBINIT 0x8B42 +#define SIOCMIBSYNC 0x8B43 +#define SIOCGMIBDATA 0x8B44 +#define SIOCSACLADD 0x8B45 +#define SIOCSACLDEL 0x8B46 +#define SIOCSACLQUERY 0x8B47 + +#define SIOCGMISCDATA 0x8B48 + +#ifdef RTK_WOW +#define SIOCGRTKWOW 0x8B49 +#define SIOCGRTKWOWSTAINFO 0x8B5A +#endif + +#define SIOCSRFPWRADJ 0x8B5B +#ifdef AUTO_TEST_SUPPORT +#define SIOCSSREQ 0x8B5C +#define SIOCJOINREQ 0x8B5D +#endif +#ifdef MCR_WIRELESS_EXTEND +#ifdef CONFIG_WLAN_HAL_8814AE +#define SIORXANTSELECT 0x8B5E +#endif +#endif +#ifdef BT_COEXIST +#define SIOBTCH2C 0x8B60 +#endif +#ifdef MP_TEST +#define MP_START_TEST 0x8B61 +#define MP_STOP_TEST 0x8B62 +#define MP_SET_RATE 0x8B63 +#define MP_SET_CHANNEL 0x8B64 +#define MP_SET_TXPOWER 0x8B65 +#define MP_CONTIOUS_TX 0x8B66 +#define MP_ARX 0x8B67 +#define MP_SET_BSSID 0x8B68 +#define MP_ANTENNA_TX 0x8B69 +#define MP_ANTENNA_RX 0x8B6A +#define MP_SET_BANDWIDTH 0x8B6B +#define MP_SET_PHYPARA 0x8B6C +#define MP_QUERY_STATS 0x8B6D +#define MP_TXPWR_TRACK 0x8B6E +#define MP_QUERY_TSSI 0x8B6F +#define MP_QUERY_THER 0x8B77 +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) +#define MP_SET_BAND 0x8B85 +#endif +#define MP_RESET_STATS 0x8B86 +#define MP_GET_TXPOWER 0x8B87 +#if defined(CONFIG_RTL_8812_SUPPORT) +#define MP_DIG 0x8B88 +#endif +#ifdef B2B_TEST +// set/get convention: set(even number) get (odd number) +#define MP_TX_PACKET 0x8B71 +#define MP_RX_PACKET 0x8B70 +#define MP_BRX_PACKET 0x8B73 +#endif + +#endif // MP_TEST + +#if (defined(SW_ANT_SWITCH) || defined(HW_ANT_SWITCH)) +#define SIOCANTSELECT 0x8b9d +#endif + +#define SIOCGIWRTLREGDUMP 0x8B78 + +#if defined(MBSSID) || defined(UNIVERSAL_REPEATER) +#define SIOCSICOPYMIB 0x8B79 +#endif + +#ifdef SUPPORT_TX_MCAST2UNI +#define SIOCGIMCAST_ADD 0x8B80 +#define SIOCGIMCAST_DEL 0x8B81 +#endif + +#ifdef CONFIG_RTL8186_KB +#define SIOCGIREADGUESTMAC 0x8B82 +#define SIOCSIWRTGUESTMAC 0x8B83 +#endif + +#if defined(CONFIG_RTL8186_KB_N) +#define SIOCGIWRTLAUTH 0x8B84//To get wireless auth result +#endif + +#ifdef MULTI_MAC_CLONE +#define SIOCSIMCLONE 0x8B8a +#define SIOCGIMCLONE 0x8B8b +#define SIOCSIMCLONE_DEL 0x8B8c // io come from user space +#define SIOCSIMCLONE_DEL2 0x8B8d // io come from bridge +#endif + + +#define SIOCRADIOOFF 0x8B8E + +#if defined(PCIE_POWER_SAVING) || defined(RF_MIMO_SWITCH) || defined(RF_MIMO_PS) +#define SIOCEPDN 0x8B8F +#endif + +#ifdef EN_EFUSE +#define SIOCEFUSE_GET 0x8b9b +#define SIOCEFUSE_SET 0x8b9a +#define SIOCEFUSE_SYNC 0x8b9c +#endif + +#define SIOCANTSTS 0x8b9d +#define SIOCACS 0x8b9f + +#ifdef P2P_SUPPORT +#define SIOCP2PCMD 0x8BD1 // command for p2p +#define SIOCP2PSCANREQ 0x8BD2 // issue p2p discovery request +#define SIOCP2PGETRESULT 0x8BD3 // get p2p discovery result +#define SIOCP2PPROVREQ 0x8BD4 // issue provision discovery request +#define SIOCP2WSCMETHODCONF 0x8BD5 // report event and state +#define SIOCP2PPGETEVNIND 0x8BD6 // get event and state + +#define SIOCP2P_WSC_REPORT_STATE 0x8BD7 +#define SIOCP2P_REPORT_CLIENT_STATE 0x8BD8 // report client connect state +#endif + +#define SIOCSTOPPS 0x8b90 +#ifdef BR_SHORTCUT +#define SIOCLEARBRSC 0x8B91 +#define SIOCLONEEARBRSC 0x8B92 +#endif + +#ifdef D_ACL//tsananiu +#define RTL8192CD_IOCTL_ADD_ACL_TABLE 0x8B96 +#define RTL8192CD_IOCTL_REMOVE_ACL_TABLE 0x8B97 +#define RTL8192CD_IOCTL_GET_ACL_TABLE 0x8B98 +#define RTL8192CD_IOCTL_CLEAR_ACL_TABLE 0x8B9E +#define ACL_allow 1 +#define ACL_deny 2 +#endif//tsananiu//d + +#ifdef CONFIG_RTK_MESH + +#ifdef _11s_TEST_MODE_ +#define SAVE_RECEIBVER_PID 0x8B92 //PID ioctl +#define DEQUEUE_RECEIBVER_IOCTL 0x8B93 //DEQUEUE ioctl +#endif +// ==== inserted by GANTOE for manual site survey 2008/12/25 ==== +#define SIOCJOINMESH 0x8B94 +#define SIOCCHECKMESHLINK 0x8B95 // This OID might be removed when the mesh peerlink precedure has been completed +// GANTOE + + + +#define SIOCQPATHTABLE 0x8BA0 // query pathselection table +#define SIOCUPATHTABLE 0x8BA1 // update existing entry's date in pathselection table +#define SIOCAPATHTABLE 0x8BA2 // add a new entry into pathselection table + +#define GET_STA_LIST 0x8BA6 +#define SET_PORTAL_POOL 0x8BA8 +#define SIOC_NOTIFY_PATH_CREATE 0x8BA9 // path selection daemon notify dirver that the path to des mac has created +#define SIOC_UPDATE_ROOT_INFO 0x8BAA // update root mac into driver +#define SIOC_GET_ROUTING_INFO 0x8BAB // send routing info to user space +#define REMOVE_PATH_ENTRY 0x8BAC // remove specified path entry +#define SIOC_SET_ROUTING_INFO 0x8BAD // set MESH routing info from user space + +#define SAVEPID_IOCTL 0x8BB0 //PID ioctl +#define DEQUEUEDATA_IOCTL 0x8BB1 //DEQUEUE ioctl + +#ifdef _MESH_ACL_ENABLE_ +#define SIOCSMESHACLADD 0x8BB5 +#define SIOCSMESHACLDEL 0x8BB6 +#define SIOCSMESHACLQUERY 0x8BB7 +#endif + +#define SIOCSMESHPXADD 0x8BB8 +#define SIOCSMESHPXDEL 0x8BB9 + +#endif // CONFIG_RTK_MESH + +#define SIOC92DAUTOCH 0x8BC5 // manual auto channel + +#if defined(CONFIG_OFFLOAD_FUNCTION) || defined(SDIO_AP_OFFLOAD) +#define SIOOFFLOADTEST 0x8BC6 +#endif + +#ifdef CONFIG_8814_AP_MAC_VERI +#define SIO_8814_AP_MAC_VERI 0x8BC8 +#endif //#ifdef CONFIG_8814_AP_MAC_VERI + + +#ifdef CONFIG_RTL_COMAPI_CFGFILE +#define SIOCCOMAPIFILE 0x8BC0 +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#define SIOC92DIQK 0x8BC1 +#ifdef EN_EFUSE +#define SIOC92DSBANDADDR 0x8BC4 // set hwaddr by band +#endif +#ifdef NON_INTR_ANTDIV +#define SIOC92DATNDIV 0x8BC6 // set hwaddr by band +#endif +#ifdef DPK_92D +#define SIOC92DDPK 0x8BC7 // dpk +#endif +#endif + +#ifdef MP_PSD_SUPPORT +#define MP_QUERY_PSD 0x8BC9 +#endif + +#if defined(RTK_AC_SUPPORT) || defined(HS2_SUPPORT) || defined(CONFIG_IEEE80211W) +/* SIOC8812SIGMA for Hotsport 2.0 Release 1 */ +#define SIOC8812SIGMA 0x8BCB +#endif + +#if defined(RTK_AC_SUPPORT) +#define SIOC8812SIGMATB 0x8BCC +#endif + +#define SIOCRESETNOPCHANNEL 0x8BCE +#define SIOCTXPWRAPPLY 0x8BCF + + +#define _OFFSET(field) ((int)(long *)&(((struct wifi_mib *)0)->field)) +#define _SIZE(field) sizeof(((struct wifi_mib *)0)->field) + +#define _OFFSET_RFFT(field) ((int)(long *)&(((struct rf_finetune_var *)0)->field)) +#define _SIZE_RFFT(field) sizeof(((struct rf_finetune_var *)0)->field) + + +#ifdef USE_OUT_SRC +#define ODEBUG(fmt, args...) printk("odm[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#define _OFFSET_ODM_DM(field) ((int)(long *)&((( struct DM_Out_Source_Dynamic_Mechanism_Structure *)0)->field)) +#define _SIZE_ODM_DM(field) sizeof((( struct DM_Out_Source_Dynamic_Mechanism_Structure *)0)->field) +#endif + +#if defined (NOT_RTK_BSP) && defined(SMP_SYNC) && defined(__KERNEL__) +unsigned long _ioctl_copy_from_user (struct rtl8192cd_priv *priv, void * to, const void * from, unsigned long n); +unsigned long _ioctl_copy_to_user (struct rtl8192cd_priv *priv, void * to, const void * from, unsigned long n); +#endif + +typedef enum {BYTE_T, INT_T, SSID_STRING_T, BYTE_ARRAY_T, ACL_T, IDX_BYTE_ARRAY_T, MULTI_BYTE_T, +#ifdef _DEBUG_RTL8192CD_ + DEBUG_T, +#endif + DEF_SSID_STRING_T, STRING_T, RFFT_T, VARLEN_BYTE_T, +#ifdef WIFI_SIMPLE_CONFIG + PIN_IND_T, + /* WPS2DOTX */ + WSC_SELF_PIN_IND_T, + WSC_SEPC_SSID_CONN_IND_T, + WSC_SEPC_MAC_CONN_IND_T, + /* WPS2DOTX */ +#ifdef INCLUDE_WPS +#ifndef CONFIG_MSC + WSC_IND_T, +#endif + FLASH_RESTORE_T, +#endif + +#ifdef CONFIG_RTL_COMAPI_CFGFILE + WSC_START_IND_T, + //EV_MODE, EV_STATUS, EV_MEHOD, EV_STEP, EV_OOB + WSC_MODE_IND_T, + WSC_STATUS_IND_T, + WSC_METHOD_IND_T, + WSC_STEP_IND_T, + WSC_OOB_IND_T, +#endif //ifdef CONFIG_RTL_COMAPI_CFGFILE +#endif +#ifdef CONFIG_RTK_MESH + WORD_T, +#endif + ACL_INT_T, // mac address + 1 int +#ifdef CONFIG_RTL_WAPI_SUPPORT + INT_ARRAY_T, + WAPI_KEY_T, +#endif +#ifdef CONFIG_RTL_COMAPI_CFGFILE + SSID2SCAN_STRING_T, +#endif + RFFT_ACL_T, +#ifdef SUPPORT_MULTI_PROFILE + AP_PROFILE_T, +#endif + +#ifdef SWITCH_CHAN + SWITCH_CHAN_T, +#endif +#ifdef USE_OUT_SRC + ODM_DM_1UT, + ODM_DM_2UT, + ODM_DM_4UT, + ODM_DM_8UT, +#endif +} TYPE_T; + + +struct iw_priv_args privtab[] = { + { RTL8192CD_IOCTL_SET_MIB, IW_PRIV_TYPE_CHAR | 450, 0, "set_mib" }, + { RTL8192CD_IOCTL_GET_MIB, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "get_mib" }, +#ifdef _IOCTL_DEBUG_CMD_ + { RTL8192CD_IOCTL_WRITE_REG, IW_PRIV_TYPE_CHAR | 128, 0, "write_reg" }, + { RTL8192CD_IOCTL_READ_REG, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_reg" }, + { RTL8192CD_IOCTL_WRITE_MEM, IW_PRIV_TYPE_CHAR | 128, 0, "write_mem" }, + { RTL8192CD_IOCTL_READ_MEM, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_mem" }, + { RTL8192CD_IOCTL_WRITE_BB_REG, IW_PRIV_TYPE_CHAR | 128, 0, "write_bb" }, + { RTL8192CD_IOCTL_READ_BB_REG, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_bb" }, + { RTL8192CD_IOCTL_WRITE_RF_REG, IW_PRIV_TYPE_CHAR | 128, 0, "write_rf" }, + { RTL8192CD_IOCTL_READ_RF_REG, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_rf" }, +#endif + { RTL8192CD_IOCTL_DEL_STA, IW_PRIV_TYPE_CHAR | 128, 0, "del_sta" }, + { RTL8192CD_IOCTL_WRITE_EEPROM, IW_PRIV_TYPE_CHAR | 128, 0, "write_eeprom" }, + { RTL8192CD_IOCTL_READ_EEPROM, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_BYTE | 128, "read_eeprom" }, + +#ifdef SUPPORT_SNMP_MIB + { SIOCGSNMPMIB, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "get_snmp_mib" }, +#endif + + { SIOCSRFPWRADJ, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "rf_pwr" }, +#ifdef AUTO_TEST_SUPPORT + { SIOCSSREQ, IW_PRIV_TYPE_NONE,0,"at_ss" }, + { SIOCJOINREQ, IW_PRIV_TYPE_CHAR|40,0,"at_join" }, +#endif +#ifdef MCR_WIRELESS_EXTEND +#ifdef CONFIG_WLAN_HAL_8814AE + { SIORXANTSELECT, IW_PRIV_TYPE_CHAR | 40, 0, "set_ant_rx" }, +#endif +#endif +#ifdef CONFIG_RTL_COMAPI_CFGFILE + { SIOCCOMAPIFILE, IW_PRIV_TYPE_NONE, 0, "cfgfile" }, +#endif + +#ifdef MP_TEST + { MP_START_TEST, IW_PRIV_TYPE_NONE, 0, "mp_start" }, + { MP_STOP_TEST, IW_PRIV_TYPE_NONE, 0, "mp_stop" }, + { MP_SET_RATE, IW_PRIV_TYPE_CHAR | 40, 0, "mp_rate" }, + { MP_SET_CHANNEL, IW_PRIV_TYPE_CHAR | 40, 0, "mp_channel" }, + { MP_SET_TXPOWER, IW_PRIV_TYPE_CHAR | 40, 0, "mp_txpower" }, + { MP_CONTIOUS_TX, IW_PRIV_TYPE_CHAR | 128, 0, "mp_ctx" }, + { MP_ARX, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "mp_arx" }, + { MP_SET_BSSID, IW_PRIV_TYPE_CHAR | 40, 0, "mp_bssid" }, + { MP_ANTENNA_TX, IW_PRIV_TYPE_CHAR | 40, 0, "mp_ant_tx" }, + { MP_ANTENNA_RX, IW_PRIV_TYPE_CHAR | 40, 0, "mp_ant_rx" }, + { MP_SET_BANDWIDTH, IW_PRIV_TYPE_CHAR | 40, 0, "mp_bandwidth" }, + { MP_SET_PHYPARA, IW_PRIV_TYPE_CHAR | 40, 0, "mp_phypara" }, +#ifdef B2B_TEST + { MP_TX_PACKET, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | 128, "mp_tx" }, + { MP_BRX_PACKET, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "mp_brx" }, +#if 0 + { MP_RX_PACKET, IW_PRIV_TYPE_CHAR | 40, 0, "mp_rx" }, +#endif +#endif + { MP_QUERY_STATS, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "mp_query" }, + { MP_TXPWR_TRACK, IW_PRIV_TYPE_CHAR | 40, 0, "mp_pwrtrk" }, + { MP_QUERY_TSSI, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "mp_tssi" }, +#ifdef MP_PSD_SUPPORT + { MP_QUERY_PSD, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "mp_psd" }, +#endif + { MP_QUERY_THER, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "mp_ther" }, +#ifdef CONFIG_RTL_92D_SUPPORT + { MP_SET_BAND, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "mp_phyband" }, +#endif + { MP_RESET_STATS, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "mp_reset_stats" }, + { MP_GET_TXPOWER, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "mp_get_pwr" }, +#if defined(CONFIG_RTL_8812_SUPPORT) + { MP_DIG, IW_PRIV_TYPE_CHAR | 40, 0, "mp_dig" }, +#endif +#endif // MP_TEST + +#if (defined(SW_ANT_SWITCH) || defined(HW_ANT_SWITCH)) + { SIOCANTSELECT, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | 128, "dvyAnt_set" }, +#endif + +#ifdef MICERR_TEST + { SIOCSIWRTLMICERROR, IW_PRIV_TYPE_CHAR | 40, 0, "mic_error" }, + { SIOCSIWRTLMICREPORT, IW_PRIV_TYPE_CHAR | 40, 0, "mic_report" }, +#endif + { SIOCGIWRTLREGDUMP, IW_PRIV_TYPE_CHAR | 40, 0, "reg_dump" }, + +#if defined(MBSSID) || defined(UNIVERSAL_REPEATER) + { SIOCSICOPYMIB, IW_PRIV_TYPE_CHAR | 40, 0, "copy_mib" }, +#endif + +#ifdef CONFIG_RTL8186_KB + { SIOCGIREADGUESTMAC, IW_PRIV_TYPE_CHAR | 40, 0, "read_guestmac" }, + { SIOCSIWRTGUESTMAC, IW_PRIV_TYPE_CHAR | 40, 0, "write_guestmac" }, +#endif + +#ifdef MULTI_MAC_CLONE + { SIOCGIMCLONE, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_CHAR | 128, "get_mclone" }, + { SIOCSIMCLONE, IW_PRIV_TYPE_CHAR | 40, 0, "set_mclone" }, + { SIOCSIMCLONE_DEL, IW_PRIV_TYPE_CHAR | 40, 0, "del_mclone" }, +#endif + +#ifdef CONFIG_RTK_MESH + { RTL8192CD_IOCTL_STATIC_ROUTE, IW_PRIV_TYPE_CHAR | 40, 0, "strt" }, + { RTL8192CD_IOCTL_MANUAL_METRIC, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "manual_metric" }, + { RTL8192CD_IOCTL_SHOWSC, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "showsc" }, +#endif +#ifdef D_ACL//tsananiu + { RTL8192CD_IOCTL_ADD_ACL_TABLE, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "add_acl_table" }, + { RTL8192CD_IOCTL_REMOVE_ACL_TABLE, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "del_acl_table" }, + { RTL8192CD_IOCTL_GET_ACL_TABLE, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "get_acl_table" }, + { RTL8192CD_IOCTL_CLEAR_ACL_TABLE, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "clear_acl_table" }, +#endif//tsananiu// +#ifdef BR_SHORTCUT + { SIOCLEARBRSC, IW_PRIV_TYPE_CHAR | 40, 0, "clear_brsc" }, + { SIOCLONEEARBRSC, IW_PRIV_TYPE_CHAR | 40, 0, "clear_onebrsc" }, +#endif + + + { SIOCRADIOOFF, IW_PRIV_TYPE_CHAR | 128, 0, "radio_off" }, + +#ifdef PCIE_POWER_SAVING +#ifdef PCIE_POWER_SAVING_DEBUG + { SIOCEPDN, IW_PRIV_TYPE_CHAR | 128, 128, "epdn" }, +#else + { SIOCEPDN, IW_PRIV_TYPE_CHAR | 128, 128, "stopps" }, +#endif +#elif defined(RF_MIMO_SWITCH) || defined(RF_MIMO_PS) + { SIOCEPDN, IW_PRIV_TYPE_CHAR | 128, 128, "mimo" }, +#endif +#ifdef SDIO_AP_OFFLOAD + { SIOCSTOPPS, IW_PRIV_TYPE_CHAR | 128, 128, "stopps" }, +#endif + { SIOCACS, IW_PRIV_TYPE_CHAR | 128, 128, "acs" }, + + { SIOCANTSTS, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | 512, "ant_sts" }, +#ifdef EN_EFUSE + { SIOCEFUSE_GET, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | 512, "efuse_get" }, + { SIOCEFUSE_SET, IW_PRIV_TYPE_CHAR | 512, IW_PRIV_TYPE_CHAR | 128, "efuse_set" }, + { SIOCEFUSE_SYNC, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | 128, "efuse_sync" }, +#endif +#ifdef P2P_SUPPORT + { SIOCP2PCMD, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | 128, "p2pcmd" }, +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + { SIOC92DIQK, IW_PRIV_TYPE_CHAR | 128, 0, "iqk" }, +#ifdef EN_EFUSE + { SIOC92DSBANDADDR, IW_PRIV_TYPE_CHAR | 128, IW_PRIV_TYPE_CHAR | 128, "bandadd" }, +#endif +#ifdef NON_INTR_ANTDIV + { SIOC92DATNDIV, IW_PRIV_TYPE_CHAR | 128, 0 | 128, "antdiv" }, +#endif +#ifdef DPK_92D + { SIOC92DDPK, IW_PRIV_TYPE_CHAR | 128, 0 | 128, "dpk" }, +#endif +#endif // CONFIG_RTL_92D_SUPPORT +#if defined(RTK_AC_SUPPORT) || defined(HS2_SUPPORT) || defined(CONFIG_IEEE80211W) //for 11ac logo, hs2.0 release 1 logo + { SIOC8812SIGMA, IW_PRIV_TYPE_CHAR | 128, 0 | 128, "sigma_default" }, +#endif +#if defined(RTK_AC_SUPPORT) + { SIOC8812SIGMATB, IW_PRIV_TYPE_CHAR | 128, 0 | 128, "sigma_default_tb" }, +#endif + { SIOC92DAUTOCH, IW_PRIV_TYPE_CHAR | 128, 0, "autoch" }, + +#if defined(CONFIG_OFFLOAD_FUNCTION) || defined(SDIO_AP_OFFLOAD) + { SIOOFFLOADTEST, IW_PRIV_TYPE_CHAR | 128, 0, "offload" }, +#endif + +#ifdef CONFIG_8814_AP_MAC_VERI + { SIO_8814_AP_MAC_VERI, IW_PRIV_TYPE_CHAR | 128, 0, "apTest" }, +#endif //#ifdef CONFIG_8814_AP_MAC_VERI + +#ifdef D_ACL//tsananiu + { RTL8192CD_IOCTL_ADD_ACL_TABLE, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "add_acl_table" }, + { RTL8192CD_IOCTL_REMOVE_ACL_TABLE, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "del_acl_table" }, + { RTL8192CD_IOCTL_GET_ACL_TABLE, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "get_acl_table" }, + { RTL8192CD_IOCTL_CLEAR_ACL_TABLE, IW_PRIV_TYPE_CHAR | 40, IW_PRIV_TYPE_BYTE | 128, "clear_acl_table" }, +#endif//tsananiu// + + { SIOCRESETNOPCHANNEL, IW_PRIV_TYPE_CHAR | 128, 0 | 128, "reset_nop" }, + { SIOCTXPWRAPPLY, IW_PRIV_TYPE_CHAR | 128, 0 | 128, "txpwr_apply" }, +}; + +#if defined (CONFIG_RTL_COMAPI_WLTOOLS) || defined(SUPPORT_MONITOR) + +static const iw_handler rtl_iwhandler[] = +{ + (iw_handler) NULL, /* SIOCSIWCOMMIT */ +#ifdef WIFI_WPAS_CLI + (iw_handler) rtl_wx_get_name, /* SIOCGIWNAME */ + (iw_handler) rtl_wx_dummy, /* SIOCSIWNWID */ + (iw_handler) rtl_wx_dummy, /* SIOCGIWNWID */ +#else + (iw_handler) NULL /* supported */, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ +#endif + (iw_handler) rtl_siwfreq, /* SIOCSIWFREQ */ +#ifdef WIFI_WPAS_CLI + (iw_handler) rtl_wx_get_freq, /* SIOCGIWFREQ */ + (iw_handler) rtl_wx_set_mode, /* SIOCSIWMODE */ +#else + (iw_handler) rtl_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) rtl_siwmode, /* SIOCSIWMODE */ +#endif + (iw_handler) rtl_giwmode, /* SIOCGIWMODE */ +#ifdef WIFI_WPAS_CLI + (iw_handler) rtl_wx_dummy, /* SIOCSIWSENS */ + (iw_handler) rtl_wx_get_sens, /* SIOCGIWSENS */ +#else + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ +#endif + (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ + (iw_handler) rtl_giwrange, /* SIOCGIWRANGE */ +#ifdef BALONG_PLT + (iw_handler) rtl_gipriv, /* SIOCSIWPRIV */ + (iw_handler) rtl_sipriv /* kernel code */, /* SIOCGIWPRIV */ +#else + (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ + (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ +#endif + (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ + (iw_handler) NULL /*rtl8192cd_get_wireless_stats*//* kernel code */, /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* SIOCSIWTHRSPY */ + (iw_handler) NULL, /* SIOCGIWTHRSPY */ + (iw_handler) rtl_siwap, /* SIOCSIWAP */ + (iw_handler) rtl_giwap, /* SIOCGIWAP */ +#ifdef WIFI_WPAS_CLI + (iw_handler) rtl_wx_set_mlme, /* SIOCSIWMLME */ +#else +#ifdef SIOCSIWMLME + (iw_handler) NULL, // rt_ioctl_siwmlme, /* SIOCSIWMLME */ //chris: deauth, disassoc for client mode +#else + (iw_handler) NULL, /* SIOCSIWMLME */ +#endif // SIOCSIWMLME // +#endif + (iw_handler) rtl_iwaplist, /* SIOCGIWAPLIST */ +#ifdef SIOCGIWSCAN + (iw_handler) rtl_siwscan, /* SIOCSIWSCAN */ + (iw_handler) rtl_giwscan, /* SIOCGIWSCAN */ +#else + (iw_handler) NULL, /* SIOCSIWSCAN */ + (iw_handler) NULL, /* SIOCGIWSCAN */ +#endif /* SIOCGIWSCAN */ + (iw_handler) rtl_siwessid, /* SIOCSIWESSID */ + (iw_handler) rtl_giwessid, /* SIOCGIWESSID */ + (iw_handler) NULL, // rt_ioctl_siwnickn, /* SIOCSIWNICKN */ + (iw_handler) NULL, // rt_ioctl_giwnickn, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) rtl_siwrate, /* SIOCSIWRATE */ + (iw_handler) rtl_giwrate, /* SIOCGIWRATE */ + (iw_handler) rtl_siwrts, /* SIOCSIWRTS */ + (iw_handler) rtl_giwrts, /* SIOCGIWRTS */ + (iw_handler) rtl_siwfrag, /* SIOCSIWFRAG */ + (iw_handler) rtl_giwfrag, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) rtl_siwretry, /* SIOCSIWRETRY */ + (iw_handler) rtl_giwretry, /* SIOCGIWRETRY */ + (iw_handler) rtl_siwencode, /* SIOCSIWENCODE */ + (iw_handler) rtl_giwencode, /* SIOCGIWENCODE */ + (iw_handler) NULL, /* SIOCSIWPOWER */ + (iw_handler) rtl_giwpower, /* SIOCGIWPOWER */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ +#if WIRELESS_EXT > 17 // for wpa_supplicant +#ifdef WIFI_WPAS_CLI + (iw_handler) rtl_siwgenie, /* SIOCSIWGENIE */ + (iw_handler) NULL, /* SIOCGIWGENIE */ + (iw_handler) rtl_siwauth, /* SIOCSIWAUTH */ + (iw_handler) rtl_giwauth, /* SIOCGIWAUTH */ + (iw_handler) rtl_siwencodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) rtl_giwencodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) rtl_siwpmkid, /* SIOCSIWPMKSA */ +#else + (iw_handler) NULL, //rt_ioctl_siwgenie, /* SIOCSIWGENIE */ + (iw_handler) NULL, //rt_ioctl_giwgenie, /* SIOCGIWGENIE */ + (iw_handler) NULL, //rt_ioctl_siwauth, /* SIOCSIWAUTH */ + (iw_handler) NULL, //rt_ioctl_giwauth, /* SIOCGIWAUTH */ + (iw_handler) NULL, //rt_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) NULL, //rt_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ + (iw_handler) NULL, //rt_ioctl_siwpmksa, /* SIOCSIWPMKSA */ +#endif +#endif +}; + +static iw_handler rtl_private_handler[] = +{ +#if 0 + NULL, //set_mib, + NULL, //get_mib, +#ifdef _IOCTL_DEBUG_CMD_ + NULL, //read_reg, + NULL, //read_mem, + NULL, //read_bb, + NULL, //read_rf, +#endif + NULL, //del_sta, + NULL, //write_eeprom, + NULL, //read_eeprom, +#ifdef SUPPORT_SNMP_MIB + NULL, //get_snmp_mib, +#endif + NULL, //rf_pwr, +#ifdef AUTO_TEST_SUPPORT + NULL, //at_ss, + NULL, //at_join, +#endif +#ifdef CONFIG_RTL_COMAPI_CFGFILE + NULL, //cfgfile, +#endif +#ifdef MP_TEST + NULL, //mp_start, + NULL, //mp_stop, + NULL, //mp_rate, + NULL, //mp_channel, + NULL, //mp_txpower, + NULL, //mp_ctx, + NULL, //mp_arx, + NULL, //mp_bssid, + NULL, //mp_ant_tx, + NULL, //mp_ant_rx, + NULL, //mp_bandwidth, + NULL, //mp_phypara, + +#ifdef B2B_TEST + NULL, //mp_tx, + NULL, //mp_brx, +#if 0 + mp_rx, +#endif +#endif + NULL, //mp_query, + NULL, //mp_tssi, +#ifdef RTL8192SE + NULL, //mp_ther, +#endif +#endif // MP_TEST +#if (defined(CONFIG_RTL865X) && defined(CONFIG_RTL865X_CLE) && defined(MP_TEST)) || defined(MP_TEST_CFG) + NULL, //mp_cfg, +#endif +#ifdef MICERR_TEST + NULL, //mic_error, + NULL, //mic_report, +#endif +#ifdef DEBUG_8190 + NULL, //reg_dump, +#endif + +#if defined(MBSSID) || defined(UNIVERSAL_REPEATER) + NULL, //copy_mib, +#endif +#ifdef CONFIG_RTL8186_KB + NULL, //read_guestmac, + NULL, //write_guestmac, +#endif + +#ifdef CONFIG_RTK_MESH + NULL, //strt, +#ifdef D_ACL //tsananiu + NULL, //add_acl_table, + NULL, //remove_acl_table, + NULL, //get_acl_table, +#endif +#endif +#ifdef BR_SHORTCUT + NULL, //clear_brsc, +#endif +#else + NULL, // return NULL to redirect to dev->ioctl +#endif +}; + +const struct iw_handler_def rtl8192cd_iw_handler_def = +{ +#define N(a) (sizeof (a) / sizeof (a[0])) + .standard = (iw_handler *) rtl_iwhandler, + .num_standard = sizeof(rtl_iwhandler) / sizeof(iw_handler), + .private = rtl_private_handler, + .private_args = (struct iw_priv_args *)privtab, + .num_private = sizeof(rtl_private_handler) / sizeof(iw_handler), + .num_private_args = sizeof(privtab) / sizeof(struct iw_priv_args), +#if 0 // IW_HANDLER_VERSION >= 6 + .get_wireless_stats = rtl8192cd_get_wireless_stats, +#endif +}; + +#endif + + +struct iwpriv_arg { + char name[32]; /* mib name */ + TYPE_T type; /* Type and number of args */ + int offset; /* mib offset */ + int len; /* mib byte len */ + int Default; /* mib default value */ +}; + +/* Bit mask value for flags, compatiable with old driver */ +#define STA_INFO_FLAG_AUTH_OPEN 0x01 +#define STA_INFO_FLAG_AUTH_WEP 0x02 +#define STA_INFO_FLAG_ASOC 0x04 +#define STA_INFO_FLAG_ASLEEP 0x08 + +/* BSS info, reported to web server */ +typedef struct _bss_info_2_web { + unsigned char state; + unsigned char channel; + unsigned char txRate; + unsigned char bssid[6]; + unsigned char rssi, sq; + unsigned char ssid[33]; +} bss_info_2_web; + +typedef enum _wlan_mac_state { + STATE_DISABLED=0, STATE_IDLE, STATE_SCANNING, STATE_STARTED, STATE_CONNECTED, STATE_WAITFORKEY +} wlan_mac_state; + +#ifdef WDS +typedef enum _wlan_wds_state { + STATE_WDS_EMPTY=0, STATE_WDS_DISABLED, STATE_WDS_ACTIVE +} wlan_wds_state; + +typedef struct _wds_info { + unsigned char state; + unsigned char addr[6]; + unsigned long tx_packets; + unsigned long rx_packets; + unsigned long tx_errors; + unsigned char TxOperaRate; +} web_wds_info; +#endif + +struct _wlan_sta_rateset { + unsigned char mac[6]; + unsigned char txrate; +}; + +struct _misc_data_ { + unsigned char mimo_tr_hw_support; + unsigned char mimo_tr_used; + unsigned char resv[30]; +}; + + +/* MIB table */ +static struct iwpriv_arg mib_table[] = { + // struct Dot11RFEntry + {"channel", BYTE_T, _OFFSET(dot11RFEntry.dot11channel), _SIZE(dot11RFEntry.dot11channel), 0}, + {"ch_low", INT_T, _OFFSET(dot11RFEntry.dot11ch_low), _SIZE(dot11RFEntry.dot11ch_low), 0}, + {"ch_hi", INT_T, _OFFSET(dot11RFEntry.dot11ch_hi), _SIZE(dot11RFEntry.dot11ch_hi), 0}, + {"pwrlevelCCK_A", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrlevelCCK_A), _SIZE(dot11RFEntry.pwrlevelCCK_A), 0}, + {"pwrlevelCCK_B", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrlevelCCK_B), _SIZE(dot11RFEntry.pwrlevelCCK_B), 0}, + {"pwrlevelHT40_1S_A", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrlevelHT40_1S_A), _SIZE(dot11RFEntry.pwrlevelHT40_1S_A), 0}, + {"pwrlevelHT40_1S_B", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrlevelHT40_1S_B), _SIZE(dot11RFEntry.pwrlevelHT40_1S_B), 0}, + {"pwrdiffHT40_2S", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiffHT40_2S), _SIZE(dot11RFEntry.pwrdiffHT40_2S), 0}, + {"pwrdiffHT20", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiffHT20), _SIZE(dot11RFEntry.pwrdiffHT20), 0}, + {"pwrdiffOFDM", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiffOFDM), _SIZE(dot11RFEntry.pwrdiffOFDM), 0}, +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + {"pwrlevel5GHT40_1S_A", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrlevel5GHT40_1S_A), _SIZE(dot11RFEntry.pwrlevel5GHT40_1S_A), 0}, + {"pwrlevel5GHT40_1S_B", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrlevel5GHT40_1S_B), _SIZE(dot11RFEntry.pwrlevel5GHT40_1S_B), 0}, +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + {"pwrdiff5GHT40_2S", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff5GHT40_2S), _SIZE(dot11RFEntry.pwrdiff5GHT40_2S), 0}, + {"pwrdiff5GHT20", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff5GHT20), _SIZE(dot11RFEntry.pwrdiff5GHT20), 0}, + {"pwrdiff5GOFDM", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff5GOFDM), _SIZE(dot11RFEntry.pwrdiff5GOFDM), 0}, +#endif +#ifdef POWER_PERCENT_ADJUSTMENT + {"powerpercent", BYTE_T, _OFFSET(dot11RFEntry.power_percent), _SIZE(dot11RFEntry.power_percent), 100}, +#endif + {"preamble", INT_T, _OFFSET(dot11RFEntry.shortpreamble), _SIZE(dot11RFEntry.shortpreamble), 0}, + {"trswitch", INT_T, _OFFSET(dot11RFEntry.trswitch), _SIZE(dot11RFEntry.trswitch), 0}, + {"disable_ch14_ofdm", INT_T, _OFFSET(dot11RFEntry.disable_ch14_ofdm), _SIZE(dot11RFEntry.disable_ch14_ofdm), 0}, + {"disable_ch1213", INT_T, _OFFSET(dot11RFEntry.disable_ch1213), _SIZE(dot11RFEntry.disable_ch1213), 1}, + {"xcap", INT_T, _OFFSET(dot11RFEntry.xcap), _SIZE(dot11RFEntry.xcap), 0}, + {"tssi1", INT_T, _OFFSET(dot11RFEntry.tssi1), _SIZE(dot11RFEntry.tssi1), 0}, + {"tssi2", INT_T, _OFFSET(dot11RFEntry.tssi2), _SIZE(dot11RFEntry.tssi2), 0}, + {"ther", INT_T, _OFFSET(dot11RFEntry.ther), _SIZE(dot11RFEntry.ther), 0}, + {"deltaIQK", INT_T, _OFFSET(dot11RFEntry.deltaIQK), _SIZE(dot11RFEntry.deltaIQK), 0}, + {"deltaLCK", INT_T, _OFFSET(dot11RFEntry.deltaLCK), _SIZE(dot11RFEntry.deltaLCK), 0}, + {"MIMO_TR_mode", INT_T, _OFFSET(dot11RFEntry.MIMO_TR_mode), _SIZE(dot11RFEntry.MIMO_TR_mode), MIMO_2T2R}, + {"phyBandSelect", BYTE_T, _OFFSET(dot11RFEntry.phyBandSelect), _SIZE(dot11RFEntry.phyBandSelect), PHY_BAND_2G}, + {"band5GSelected", BYTE_T, _OFFSET(dot11RFEntry.band5GSelected), _SIZE(dot11RFEntry.band5GSelected), PHY_BAND_5G_1 | PHY_BAND_5G_2 | PHY_BAND_5G_3 | PHY_BAND_5G_4}, + {"macPhyMode", BYTE_T, _OFFSET(dot11RFEntry.macPhyMode), _SIZE(dot11RFEntry.macPhyMode), SINGLEMAC_SINGLEPHY}, + {"smcc", INT_T, _OFFSET(dot11RFEntry.smcc), _SIZE(dot11RFEntry.smcc), 1}, + {"smcc_t", INT_T, _OFFSET(dot11RFEntry.smcc_t), _SIZE(dot11RFEntry.smcc_t), 6}, +#ifdef PHASE2_TEST + {"smcc_p", INT_T, _OFFSET(dot11RFEntry.smcc_p), _SIZE(dot11RFEntry.smcc_p), 18}, +#endif + {"trsw_pape_C9", BYTE_T, _OFFSET(dot11RFEntry.trsw_pape_C9), _SIZE(dot11RFEntry.trsw_pape_C9), 0x0}, + {"trsw_pape_CC", BYTE_T, _OFFSET(dot11RFEntry.trsw_pape_CC), _SIZE(dot11RFEntry.trsw_pape_CC), 0xFF}, + {"tx2path", INT_T, _OFFSET(dot11RFEntry.tx2path), _SIZE(dot11RFEntry.tx2path), 1}, + {"txbf", INT_T, _OFFSET(dot11RFEntry.txbf), _SIZE(dot11RFEntry.txbf), 1}, + {"txbfer", INT_T, _OFFSET(dot11RFEntry.txbfer), _SIZE(dot11RFEntry.txbfer), 1}, + {"txbfee", INT_T, _OFFSET(dot11RFEntry.txbfee), _SIZE(dot11RFEntry.txbfee), 1}, + {"target_pwr", INT_T, _OFFSET(dot11RFEntry.target_pwr), _SIZE(dot11RFEntry.target_pwr), 0}, + {"pa_type", INT_T, _OFFSET(dot11RFEntry.pa_type), _SIZE(dot11RFEntry.pa_type), 0}, + {"bcn2path", BYTE_T, _OFFSET(dot11RFEntry.bcn2path), _SIZE(dot11RFEntry.bcn2path), 0}, + {"add_cck1M_pwr", BYTE_T, _OFFSET(dot11RFEntry.add_cck1M_pwr), _SIZE(dot11RFEntry.add_cck1M_pwr), 0}, + {"rfe_type", BYTE_T, _OFFSET(dot11RFEntry.rfe_type), _SIZE(dot11RFEntry.rfe_type), 0}, + {"acs_type", INT_T, _OFFSET(dot11RFEntry.acs_type), _SIZE(dot11RFEntry.acs_type), 1}, + + // struct Dot11StationConfigEntry + {"ssid", SSID_STRING_T, _OFFSET(dot11StationConfigEntry.dot11DesiredSSID), _SIZE(dot11StationConfigEntry.dot11DesiredSSID), 0}, + {"defssid", DEF_SSID_STRING_T, _OFFSET(dot11StationConfigEntry.dot11DefaultSSID), _SIZE(dot11StationConfigEntry.dot11DefaultSSID), 0}, + {"bssid2join", BYTE_ARRAY_T, _OFFSET(dot11StationConfigEntry.dot11DesiredBssid), _SIZE(dot11StationConfigEntry.dot11DesiredBssid), 0}, + {"bcnint", INT_T, _OFFSET(dot11StationConfigEntry.dot11BeaconPeriod), _SIZE(dot11StationConfigEntry.dot11BeaconPeriod), 100}, + {"dtimperiod", INT_T, _OFFSET(dot11StationConfigEntry.dot11DTIMPeriod), _SIZE(dot11StationConfigEntry.dot11DTIMPeriod), 1}, + {"swcrypto", INT_T, _OFFSET(dot11StationConfigEntry.dot11swcrypto), _SIZE(dot11StationConfigEntry.dot11swcrypto), 0}, + {"aclmode", INT_T, _OFFSET(dot11StationConfigEntry.dot11AclMode), _SIZE(dot11StationConfigEntry.dot11AclMode), 0}, + {"aclnum", INT_T, _OFFSET(dot11StationConfigEntry.dot11AclNum), _SIZE(dot11StationConfigEntry.dot11AclNum), 0}, + {"acladdr", ACL_T, _OFFSET(dot11StationConfigEntry.dot11AclAddr), _SIZE(dot11StationConfigEntry.dot11AclAddr), 0}, + {"oprates", INT_T, _OFFSET(dot11StationConfigEntry.dot11SupportedRates), _SIZE(dot11StationConfigEntry.dot11SupportedRates), 0xfff}, + {"basicrates", INT_T, _OFFSET(dot11StationConfigEntry.dot11BasicRates), _SIZE(dot11StationConfigEntry.dot11BasicRates), 0xf}, +#if defined(RTK_NL80211) + {"regdomain", INT_T, _OFFSET(dot11StationConfigEntry.dot11RegDomain), _SIZE(dot11StationConfigEntry.dot11RegDomain), DOMAIN_TEST}, +#else + {"regdomain", INT_T, _OFFSET(dot11StationConfigEntry.dot11RegDomain), _SIZE(dot11StationConfigEntry.dot11RegDomain), 1}, +#endif + {"txpwr_lmt_index", INT_T, _OFFSET(dot11StationConfigEntry.txpwr_lmt_index), _SIZE(dot11StationConfigEntry.txpwr_lmt_index), 0}, + {"autorate", INT_T, _OFFSET(dot11StationConfigEntry.autoRate), _SIZE(dot11StationConfigEntry.autoRate), 1}, + {"fixrate", INT_T, _OFFSET(dot11StationConfigEntry.fixedTxRate), _SIZE(dot11StationConfigEntry.fixedTxRate), 0}, + {"swTkipMic", INT_T, _OFFSET(dot11StationConfigEntry.swTkipMic), _SIZE(dot11StationConfigEntry.swTkipMic), 1}, + {"disable_protection", INT_T, _OFFSET(dot11StationConfigEntry.protectionDisabled), _SIZE(dot11StationConfigEntry.protectionDisabled), 0}, + {"disable_olbc", INT_T, _OFFSET(dot11StationConfigEntry.olbcDetectDisabled), _SIZE(dot11StationConfigEntry.olbcDetectDisabled), 0}, + {"disable_nmlsc", INT_T, _OFFSET(dot11StationConfigEntry.nmlscDetectDisabled), _SIZE(dot11StationConfigEntry.nmlscDetectDisabled), 0}, + {"deny_legacy", INT_T, _OFFSET(dot11StationConfigEntry.legacySTADeny), _SIZE(dot11StationConfigEntry.legacySTADeny), 0}, + {"probe_info_enable", INT_T, _OFFSET(dot11StationConfigEntry.probe_info_enable), _SIZE(dot11StationConfigEntry.probe_info_enable), 0}, +#ifdef CLIENT_MODE + {"fast_roaming", INT_T, _OFFSET(dot11StationConfigEntry.fastRoaming), _SIZE(dot11StationConfigEntry.fastRoaming), 0}, +#endif + {"lowestMlcstRate", INT_T, _OFFSET(dot11StationConfigEntry.lowestMlcstRate), _SIZE(dot11StationConfigEntry.lowestMlcstRate), 0}, + {"stanum", INT_T, _OFFSET(dot11StationConfigEntry.supportedStaNum), _SIZE(dot11StationConfigEntry.supportedStaNum), 0}, +#ifdef RX_LOOP_LIMIT + {"limit_rxloop", INT_T, _OFFSET(dot11StationConfigEntry.limit_rxloop), _SIZE(dot11StationConfigEntry.limit_rxloop), 0}, +#endif +#ifdef CONFIG_RTL_SIMPLE_CONFIG + {"sc_enabled", INT_T, _OFFSET(dot11StationConfigEntry.sc_enabled), _SIZE(dot11StationConfigEntry.sc_enabled), 0}, + {"sc_duration_time", INT_T, _OFFSET(dot11StationConfigEntry.sc_duration_time), _SIZE(dot11StationConfigEntry.sc_duration_time), -1}, + {"sc_get_sync_time", INT_T, _OFFSET(dot11StationConfigEntry.sc_get_sync_time), _SIZE(dot11StationConfigEntry.sc_get_sync_time), 30}, + {"sc_get_profile_time", INT_T, _OFFSET(dot11StationConfigEntry.sc_get_profile_time), _SIZE(dot11StationConfigEntry.sc_get_profile_time), 30}, + {"sc_connect_timeout", INT_T, _OFFSET(dot11StationConfigEntry.sc_connect_timeout), _SIZE(dot11StationConfigEntry.sc_connect_timeout), 60}, + {"sc_vxd_rescan_time", INT_T, _OFFSET(dot11StationConfigEntry.sc_vxd_rescan_time), _SIZE(dot11StationConfigEntry.sc_vxd_rescan_time), 10}, + {"sc_pin_enabled", INT_T, _OFFSET(dot11StationConfigEntry.sc_pin_enabled), _SIZE(dot11StationConfigEntry.sc_pin_enabled), 1}, + {"sc_status", INT_T, _OFFSET(dot11StationConfigEntry.sc_status), _SIZE(dot11StationConfigEntry.sc_status), 0}, + {"sc_pin", STRING_T, _OFFSET(dot11StationConfigEntry.sc_pin), _SIZE(dot11StationConfigEntry.sc_pin), 0}, + {"sc_default_pin", STRING_T, _OFFSET(dot11StationConfigEntry.sc_default_pin), _SIZE(dot11StationConfigEntry.sc_default_pin), 0}, + {"sc_passwd", STRING_T, _OFFSET(dot11StationConfigEntry.sc_passwd), _SIZE(dot11StationConfigEntry.sc_passwd), 0}, + {"sc_device_name", STRING_T, _OFFSET(dot11StationConfigEntry.sc_device_name), _SIZE(dot11StationConfigEntry.sc_device_name), 0}, + {"sc_ack_round", INT_T, _OFFSET(dot11StationConfigEntry.sc_ack_round), _SIZE(dot11StationConfigEntry.sc_ack_round), 0}, + {"sc_check_link_time", INT_T, _OFFSET(dot11StationConfigEntry.sc_check_link_time), _SIZE(dot11StationConfigEntry.sc_check_link_time), 10}, + {"sc_sync_vxd_to_root", INT_T, _OFFSET(dot11StationConfigEntry.sc_sync_vxd_to_root), _SIZE(dot11StationConfigEntry.sc_sync_vxd_to_root), 0}, + {"sc_control_ip", INT_T, _OFFSET(dot11StationConfigEntry.sc_control_ip), _SIZE(dot11StationConfigEntry.sc_control_ip), 0}, + {"sc_debug", INT_T, _OFFSET(dot11StationConfigEntry.sc_debug), _SIZE(dot11StationConfigEntry.sc_debug), 1}, + {"sc_check_level", INT_T, _OFFSET(dot11StationConfigEntry.sc_check_level), _SIZE(dot11StationConfigEntry.sc_check_level), 2}, + {"sc_ignore_overlap", INT_T, _OFFSET(dot11StationConfigEntry.sc_ignore_overlap), _SIZE(dot11StationConfigEntry.sc_ignore_overlap), 0}, + {"sc_reset_beacon_psk", INT_T, _OFFSET(dot11StationConfigEntry.sc_reset_beacon_psk), _SIZE(dot11StationConfigEntry.sc_reset_beacon_psk), 1}, + {"sc_security_type", INT_T, _OFFSET(dot11StationConfigEntry.sc_security_type), _SIZE(dot11StationConfigEntry.sc_security_type), 0}, + {"sc_fix_channel", INT_T, _OFFSET(dot11StationConfigEntry.sc_fix_channel), _SIZE(dot11StationConfigEntry.sc_fix_channel), 0}, +#endif + +#ifdef CONFIG_RTK_MESH + {"mesh_enable", BYTE_T, _OFFSET(dot1180211sInfo.mesh_enable), _SIZE(dot1180211sInfo.mesh_enable), 0}, + {"mesh_root_enable", BYTE_T, _OFFSET(dot1180211sInfo.mesh_root_enable), _SIZE(dot1180211sInfo.mesh_root_enable), 0}, + {"mesh_ap_enable", BYTE_T, _OFFSET(dot1180211sInfo.mesh_ap_enable), _SIZE(dot1180211sInfo.mesh_ap_enable), 0}, + {"mesh_portal_enable", BYTE_T, _OFFSET(dot1180211sInfo.mesh_portal_enable), _SIZE(dot1180211sInfo.mesh_portal_enable), 0}, + {"mesh_id", STRING_T, _OFFSET(dot1180211sInfo.mesh_id), _SIZE(dot1180211sInfo.mesh_id), 0}, + {"mesh_max_neightbor", WORD_T, _OFFSET(dot1180211sInfo.mesh_max_neightbor), _SIZE(dot1180211sInfo.mesh_max_neightbor), MAX_MPP_NUM}, + {"log_enabled", BYTE_T, _OFFSET(dot1180211sInfo.log_enabled), _SIZE(dot1180211sInfo.log_enabled), 0}, + {"mesh_privacy", INT_T, _OFFSET(dot11sKeysTable.dot11Privacy), _SIZE(dot11sKeysTable.dot11Privacy), 0}, + {"mesh_passphrase", STRING_T, _OFFSET(dot1180211sInfo.dot11PassPhrase), _SIZE(dot1180211sInfo.dot11PassPhrase), 0}, + {"mesh_igmp_enable", BYTE_T, _OFFSET(dot1180211sInfo.mesh_igmp_enable), _SIZE(dot1180211sInfo.mesh_igmp_enable), 1}, +#ifdef _MESH_ACL_ENABLE_ + {"meshaclmode", INT_T, _OFFSET(dot1180211sInfo.mesh_acl_mode), _SIZE(dot1180211sInfo.mesh_acl_mode), 0}, + {"meshaclnum", INT_T, _OFFSET(dot1180211sInfo.mesh_acl_num), _SIZE(dot1180211sInfo.mesh_acl_num), 0}, + {"meshacladdr", ACL_T, _OFFSET(dot1180211sInfo.mesh_acl_addr), _SIZE(dot1180211sInfo.mesh_acl_addr), 0}, +#endif + +#ifdef _11s_TEST_MODE_ + {"mesh_reserved1", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserved1), _SIZE(dot1180211sInfo.mesh_reserved1), 0}, + {"mesh_reserved2", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserved2), _SIZE(dot1180211sInfo.mesh_reserved2), 0}, + {"mesh_reserved3", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserved3), _SIZE(dot1180211sInfo.mesh_reserved3), 0}, + {"mesh_reserved4", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserved4), _SIZE(dot1180211sInfo.mesh_reserved4), 0}, + {"mesh_reserved5", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserved5), _SIZE(dot1180211sInfo.mesh_reserved5), 0}, + {"mesh_reserved6", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserved6), _SIZE(dot1180211sInfo.mesh_reserved6), 0}, + {"mesh_reserved7", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserved7), _SIZE(dot1180211sInfo.mesh_reserved7), 0}, + {"mesh_reserved8", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserved8), _SIZE(dot1180211sInfo.mesh_reserved8), 0}, + {"mesh_reserved9", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserved9), _SIZE(dot1180211sInfo.mesh_reserved9), 0}, + {"mesh_reserveda", WORD_T, _OFFSET(dot1180211sInfo.mesh_reserveda), _SIZE(dot1180211sInfo.mesh_reserveda), 0}, + {"mesh_reservedb", WORD_T, _OFFSET(dot1180211sInfo.mesh_reservedb), _SIZE(dot1180211sInfo.mesh_reservedb), 0}, + {"mesh_reservedc", WORD_T, _OFFSET(dot1180211sInfo.mesh_reservedc), _SIZE(dot1180211sInfo.mesh_reservedc), 0}, + {"mesh_reservedd", WORD_T, _OFFSET(dot1180211sInfo.mesh_reservedd), _SIZE(dot1180211sInfo.mesh_reservedd), 0}, + {"mesh_reservede", WORD_T, _OFFSET(dot1180211sInfo.mesh_reservede), _SIZE(dot1180211sInfo.mesh_reservede), 0}, + {"mesh_reservedf", WORD_T, _OFFSET(dot1180211sInfo.mesh_reservedf), _SIZE(dot1180211sInfo.mesh_reservedf), 0}, + {"mesh_reservedstr1", STRING_T, _OFFSET(dot1180211sInfo.mesh_reservedstr1), _SIZE(dot1180211sInfo.mesh_reservedstr1), 0}, +#endif + +#endif + + // struct Dot1180211AuthEntry + {"authtype", INT_T, _OFFSET(dot1180211AuthEntry.dot11AuthAlgrthm), _SIZE(dot1180211AuthEntry.dot11AuthAlgrthm), 0}, + {"encmode", BYTE_T, _OFFSET(dot1180211AuthEntry.dot11PrivacyAlgrthm), _SIZE(dot1180211AuthEntry.dot11PrivacyAlgrthm), 0}, + {"wepdkeyid", INT_T, _OFFSET(dot1180211AuthEntry.dot11PrivacyKeyIndex), _SIZE(dot1180211AuthEntry.dot11PrivacyKeyIndex), 0}, +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + {"psk_enable", INT_T, _OFFSET(dot1180211AuthEntry.dot11EnablePSK), _SIZE(dot1180211AuthEntry.dot11EnablePSK), 0}, + {"wpa_cipher", INT_T, _OFFSET(dot1180211AuthEntry.dot11WPACipher), _SIZE(dot1180211AuthEntry.dot11WPACipher), 0}, +#ifdef RTL_WPA2 + {"wpa2_cipher", INT_T, _OFFSET(dot1180211AuthEntry.dot11WPA2Cipher), _SIZE(dot1180211AuthEntry.dot11WPA2Cipher), 0}, +#endif + {"passphrase", STRING_T, _OFFSET(dot1180211AuthEntry.dot11PassPhrase), _SIZE(dot1180211AuthEntry.dot11PassPhrase), 0}, +#ifdef CONFIG_RTL8186_KB + {"passphrase_guest", STRING_T, _OFFSET(dot1180211AuthEntry.dot11PassPhraseGuest), _SIZE(dot1180211AuthEntry.dot11PassPhraseGuest), 0}, +#endif + {"gk_rekey", INT_T, _OFFSET(dot1180211AuthEntry.dot11GKRekeyTime), _SIZE(dot1180211AuthEntry.dot11GKRekeyTime), 0}, + {"uk_rekey", INT_T, _OFFSET(dot1180211AuthEntry.dot11UKRekeyTime), _SIZE(dot1180211AuthEntry.dot11UKRekeyTime), 0}, +#endif + + // struct Dot118021xAuthEntry + {"802_1x", INT_T, _OFFSET(dot118021xAuthEntry.dot118021xAlgrthm), _SIZE(dot118021xAuthEntry.dot118021xAlgrthm), 0}, + {"default_port",INT_T, _OFFSET(dot118021xAuthEntry.dot118021xDefaultPort), _SIZE(dot118021xAuthEntry.dot118021xDefaultPort), 0}, + {"acct_enabled",INT_T, _OFFSET(dot118021xAuthEntry.acct_enabled), _SIZE(dot118021xAuthEntry.acct_enabled), 0}, + {"acct_timeout_INT",INT_T,_OFFSET(dot118021xAuthEntry.acct_timeout_period), _SIZE(dot118021xAuthEntry.acct_timeout_period), 0}, + {"acct_timeout_TP",INT_T,_OFFSET(dot118021xAuthEntry.acct_timeout_throughput), _SIZE(dot118021xAuthEntry.acct_timeout_throughput), 0}, + + // struct Dot11DefaultKeysTable + {"wepkey1", BYTE_ARRAY_T, _OFFSET(dot11DefaultKeysTable.keytype[0]), _SIZE(dot11DefaultKeysTable.keytype[0]), 0}, + {"wepkey2", BYTE_ARRAY_T, _OFFSET(dot11DefaultKeysTable.keytype[1]), _SIZE(dot11DefaultKeysTable.keytype[1]), 0}, + {"wepkey3", BYTE_ARRAY_T, _OFFSET(dot11DefaultKeysTable.keytype[2]), _SIZE(dot11DefaultKeysTable.keytype[2]), 0}, + {"wepkey4", BYTE_ARRAY_T, _OFFSET(dot11DefaultKeysTable.keytype[3]), _SIZE(dot11DefaultKeysTable.keytype[3]), 0}, + + // struct Dot11OperationEntry + {"opmode", INT_T, _OFFSET(dot11OperationEntry.opmode), _SIZE(dot11OperationEntry.opmode), 0x10}, + {"hiddenAP", INT_T, _OFFSET(dot11OperationEntry.hiddenAP), _SIZE(dot11OperationEntry.hiddenAP), 0}, + {"rtsthres", INT_T, _OFFSET(dot11OperationEntry.dot11RTSThreshold), _SIZE(dot11OperationEntry.dot11RTSThreshold), 2347}, +#ifdef __ECOS + {"fragthres", INT_T, _OFFSET(dot11OperationEntry.dot11FragmentationThreshold), _SIZE(dot11OperationEntry.dot11FragmentationThreshold), 2346}, +#else + {"fragthres", INT_T, _OFFSET(dot11OperationEntry.dot11FragmentationThreshold), _SIZE(dot11OperationEntry.dot11FragmentationThreshold), 2347}, +#endif + {"shortretry", INT_T, _OFFSET(dot11OperationEntry.dot11ShortRetryLimit), _SIZE(dot11OperationEntry.dot11ShortRetryLimit), 0}, + {"longretry", INT_T, _OFFSET(dot11OperationEntry.dot11LongRetryLimit), _SIZE(dot11OperationEntry.dot11LongRetryLimit), 0}, + {"expired_time",INT_T, _OFFSET(dot11OperationEntry.expiretime), _SIZE(dot11OperationEntry.expiretime), 30000}, /*in 10ms*/ +#if defined(CONFIG_RTL8672) + {"led_type", INT_T, _OFFSET(dot11OperationEntry.ledtype), _SIZE(dot11OperationEntry.ledtype), LEDTYPE_SW_LED2_GPIO8_LINKTXRX}, +#else + {"led_type", INT_T, _OFFSET(dot11OperationEntry.ledtype), _SIZE(dot11OperationEntry.ledtype), 0}, +#endif +#ifdef RTL8190_SWGPIO_LED + {"led_route", INT_T, _OFFSET(dot11OperationEntry.ledroute), _SIZE(dot11OperationEntry.ledroute), 0}, +#endif + {"iapp_enable", INT_T, _OFFSET(dot11OperationEntry.iapp_enable), _SIZE(dot11OperationEntry.iapp_enable), 0}, + {"block_relay", INT_T, _OFFSET(dot11OperationEntry.block_relay), _SIZE(dot11OperationEntry.block_relay), 0}, + {"deny_any", INT_T, _OFFSET(dot11OperationEntry.deny_any), _SIZE(dot11OperationEntry.deny_any), 0}, + {"crc_log", INT_T, _OFFSET(dot11OperationEntry.crc_log), _SIZE(dot11OperationEntry.crc_log), 0}, + {"wifi_specific",INT_T, _OFFSET(dot11OperationEntry.wifi_specific), _SIZE(dot11OperationEntry.wifi_specific), 2}, +#ifdef TX_SHORTCUT + {"disable_txsc",INT_T, _OFFSET(dot11OperationEntry.disable_txsc), _SIZE(dot11OperationEntry.disable_txsc), 0}, +#endif +#ifdef RX_SHORTCUT + {"disable_rxsc",INT_T, _OFFSET(dot11OperationEntry.disable_rxsc), _SIZE(dot11OperationEntry.disable_rxsc), 0}, +#endif +#ifdef BR_SHORTCUT + {"disable_brsc",INT_T, _OFFSET(dot11OperationEntry.disable_brsc), _SIZE(dot11OperationEntry.disable_brsc), 0}, +#endif + {"keep_rsnie", INT_T, _OFFSET(dot11OperationEntry.keep_rsnie), _SIZE(dot11OperationEntry.keep_rsnie), 0}, + {"guest_access",INT_T, _OFFSET(dot11OperationEntry.guest_access), _SIZE(dot11OperationEntry.guest_access), 0}, + {"tdls_prohibited",INT_T, _OFFSET(dot11OperationEntry.tdls_prohibited), _SIZE(dot11OperationEntry.tdls_prohibited), 0}, + {"tdls_cs_prohibited",INT_T, _OFFSET(dot11OperationEntry.tdls_cs_prohibited), _SIZE(dot11OperationEntry.tdls_cs_prohibited), 0}, +#ifdef CONFIG_POWER_SAVE + {"ps_level",INT_T, _OFFSET(dot11OperationEntry.ps_level), _SIZE(dot11OperationEntry.ps_level), 2}, + {"ps_32k_en",INT_T, _OFFSET(dot11OperationEntry.ps_32k_en), _SIZE(dot11OperationEntry.ps_32k_en), 1}, + {"ps_timeout",INT_T, _OFFSET(dot11OperationEntry.ps_timeout), _SIZE(dot11OperationEntry.ps_timeout), 1000}, + {"ps_sleep_time",INT_T, _OFFSET(dot11OperationEntry.ps_sleep_time), _SIZE(dot11OperationEntry.ps_sleep_time), 0}, +#endif + // struct bss_type + {"band", BYTE_T, _OFFSET(dot11BssType.net_work_type), _SIZE(dot11BssType.net_work_type), 3}, + + // struct erp_mib + {"cts2self", INT_T, _OFFSET(dot11ErpInfo.ctsToSelf), _SIZE(dot11ErpInfo.ctsToSelf), 0}, + +#ifdef WDS + // struct wds_info + {"wds_enable", INT_T, _OFFSET(dot11WdsInfo.wdsEnabled), _SIZE(dot11WdsInfo.wdsEnabled), 0}, + {"wds_pure", INT_T, _OFFSET(dot11WdsInfo.wdsPure), _SIZE(dot11WdsInfo.wdsPure), 0}, + {"wds_priority",INT_T, _OFFSET(dot11WdsInfo.wdsPriority), _SIZE(dot11WdsInfo.wdsPriority), 0}, + {"wds_num", INT_T, _OFFSET(dot11WdsInfo.wdsNum), _SIZE(dot11WdsInfo.wdsNum), 0}, + {"wds_add", ACL_INT_T, _OFFSET(dot11WdsInfo.entry), _SIZE(dot11WdsInfo.entry), 0}, + {"wds_encrypt", INT_T, _OFFSET(dot11WdsInfo.wdsPrivacy), _SIZE(dot11WdsInfo.wdsPrivacy), 0}, + {"wds_wepkey", BYTE_ARRAY_T, _OFFSET(dot11WdsInfo.wdsWepKey), _SIZE(dot11WdsInfo.wdsWepKey), 0}, + {"wds_keyid", INT_T, _OFFSET(dot11WdsInfo.wdsKeyId), _SIZE(dot11WdsInfo.wdsKeyId), 0}, +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + {"wds_passphrase", STRING_T, _OFFSET(dot11WdsInfo.wdsPskPassPhrase), _SIZE(dot11WdsInfo.wdsPskPassPhrase), 0}, +#endif +#endif + +#ifdef RTK_BR_EXT + // struct br_ext_info + {"nat25_disable", INT_T, _OFFSET(ethBrExtInfo.nat25_disable), _SIZE(ethBrExtInfo.nat25_disable), 0}, + {"macclone_enable", INT_T, _OFFSET(ethBrExtInfo.macclone_enable), _SIZE(ethBrExtInfo.macclone_enable), 0}, + {"dhcp_bcst_disable", INT_T, _OFFSET(ethBrExtInfo.dhcp_bcst_disable), _SIZE(ethBrExtInfo.dhcp_bcst_disable), 0}, + {"add_pppoe_tag", INT_T, _OFFSET(ethBrExtInfo.addPPPoETag), _SIZE(ethBrExtInfo.addPPPoETag), 1}, + {"clone_mac_addr", BYTE_ARRAY_T, _OFFSET(ethBrExtInfo.nat25_dmzMac), _SIZE(ethBrExtInfo.nat25_dmzMac), 0}, + {"nat25sc_disable", INT_T, _OFFSET(ethBrExtInfo.nat25sc_disable), _SIZE(ethBrExtInfo.nat25sc_disable), 0}, +#endif + +#ifdef DFS + //struct Dot11DFSEntry + {"disable_DFS", INT_T, _OFFSET(dot11DFSEntry.disable_DFS), _SIZE(dot11DFSEntry.disable_DFS), 0}, + {"disable_tx", INT_T, _OFFSET(dot11DFSEntry.disable_tx), _SIZE(dot11DFSEntry.disable_tx), 0}, + {"DFS_timeout", INT_T, _OFFSET(dot11DFSEntry.DFS_timeout), _SIZE(dot11DFSEntry.DFS_timeout), 10}, /*in 10ms*/ + {"DFS_detected",INT_T, _OFFSET(dot11DFSEntry.DFS_detected), _SIZE(dot11DFSEntry.DFS_detected), 0}, + {"NOP_timeout", INT_T, _OFFSET(dot11DFSEntry.NOP_timeout), _SIZE(dot11DFSEntry.NOP_timeout), 180500}, /*in 10ms*/ + {"DFS_TXPAUSE_timeout", INT_T, _OFFSET(dot11DFSEntry.DFS_TXPAUSE_timeout), _SIZE(dot11DFSEntry.DFS_TXPAUSE_timeout), 1000}, /*in 10ms*/ + {"CAC_enable", INT_T, _OFFSET(dot11DFSEntry.CAC_enable), _SIZE(dot11DFSEntry.CAC_enable), 1}, +#endif + + //struct miscEntry + {"show_hidden_bss",INT_T, _OFFSET(miscEntry.show_hidden_bss), _SIZE(miscEntry.show_hidden_bss), 0}, + {"ack_timeout", INT_T, _OFFSET(miscEntry.ack_timeout), _SIZE(miscEntry.ack_timeout), 0}, + {"private_ie", VARLEN_BYTE_T, _OFFSET(miscEntry.private_ie), _SIZE(miscEntry.private_ie), 0}, + {"rxInt", INT_T, _OFFSET(miscEntry.rxInt_thrd), _SIZE(miscEntry.rxInt_thrd), 300}, +#ifdef DRVMAC_LB + {"dmlb", INT_T, _OFFSET(miscEntry.drvmac_lb), _SIZE(miscEntry.drvmac_lb), 1}, + {"lb_da", BYTE_ARRAY_T, _OFFSET(miscEntry.lb_da), _SIZE(miscEntry.lb_da), 0}, + {"lb_tps", INT_T, _OFFSET(miscEntry.lb_tps), _SIZE(miscEntry.lb_tps), 0}, + {"lb_mlmp", INT_T, _OFFSET(miscEntry.lb_mlmp), _SIZE(miscEntry.lb_mlmp), 0}, +#endif + {"groupID", INT_T, _OFFSET(miscEntry.groupID), _SIZE(miscEntry.groupID), 0}, +#ifdef MBSSID + {"vap_enable", INT_T, _OFFSET(miscEntry.vap_enable), _SIZE(miscEntry.vap_enable), 0}, +#endif +#ifdef RESERVE_TXDESC_FOR_EACH_IF + {"rsv_txdesc", INT_T, _OFFSET(miscEntry.rsv_txdesc), _SIZE(miscEntry.rsv_txdesc), 1}, +#endif +#ifdef USE_TXQUEUE + {"use_txq", INT_T, _OFFSET(miscEntry.use_txq), _SIZE(miscEntry.use_txq), 1}, +#endif + {"func_off", INT_T, _OFFSET(miscEntry.func_off), _SIZE(miscEntry.func_off), 0}, +#ifdef AUTO_CHANNEL_TIMEOUT + {"autoch_timeout", INT_T, _OFFSET(miscEntry.autoch_timeout), _SIZE(miscEntry.autoch_timeout), 0}, +#endif + {"ss_loop_delay", INT_T, _OFFSET(miscEntry.ss_loop_delay), _SIZE(miscEntry.ss_loop_delay), 0}, +#ifdef SUPPORT_MONITOR + {"chan_switch_time", BYTE_T, _OFFSET(miscEntry.chan_switch_time), _SIZE(miscEntry.chan_switch_time), 500}, +#endif +#ifdef DFS + {"passive_ss_int", INT_T, _OFFSET(miscEntry.passive_ss_int), _SIZE(miscEntry.passive_ss_int), 120}, + {"ss_delay", INT_T, _OFFSET(miscEntry.ss_delay), _SIZE(miscEntry.ss_delay), 3000}, +#endif +#ifdef AUTOCH_SS_SPEEDUP + {"autoch_ss_to", INT_T, _OFFSET(miscEntry.autoch_ss_to), _SIZE(miscEntry.autoch_ss_to), 0}, + {"autoch_ss_cnt", INT_T, _OFFSET(miscEntry.autoch_ss_cnt), _SIZE(miscEntry.autoch_ss_cnt), 0}, + {"autoch_1611_enable", INT_T, _OFFSET(miscEntry.autoch_1611_enable), _SIZE(miscEntry.autoch_1611_enable), 0}, +#endif +#if defined(CONFIG_USB_TX_AGGREGATION) || defined(CONFIG_SDIO_TX_AGGREGATION) + {"max_xmitbuf_agg", INT_T, _OFFSET(miscEntry.max_xmitbuf_agg), _SIZE(miscEntry.max_xmitbuf_agg), MAX_XMITBUF_PKT}, +#endif +#ifdef CONFIG_SDIO_HCI + {"max_recvbuf_agg", INT_T, _OFFSET(miscEntry.max_recvbuf_agg), _SIZE(miscEntry.max_recvbuf_agg), 1}, + {"max_handle_xmitbuf", INT_T, _OFFSET(miscEntry.max_handle_xmitbuf), _SIZE(miscEntry.max_handle_xmitbuf), 6}, + {"max_handle_recvbuf", INT_T, _OFFSET(miscEntry.max_handle_recvbuf), _SIZE(miscEntry.max_handle_recvbuf), 2}, +#endif + //struct Dot11QosEntry +#ifdef WIFI_WMM + {"qos_enable", INT_T, _OFFSET(dot11QosEntry.dot11QosEnable), _SIZE(dot11QosEntry.dot11QosEnable), 1}, +#ifdef WMM_APSD + {"apsd_enable", INT_T, _OFFSET(dot11QosEntry.dot11QosAPSD), _SIZE(dot11QosEntry.dot11QosAPSD), 0}, +#ifdef CLIENT_MODE + {"apsd_sta_be", INT_T, _OFFSET(dot11QosEntry.UAPSD_AC_BE), _SIZE(dot11QosEntry.UAPSD_AC_BE), 0}, + {"apsd_sta_bk", INT_T, _OFFSET(dot11QosEntry.UAPSD_AC_BK), _SIZE(dot11QosEntry.UAPSD_AC_BK), 0}, + {"apsd_sta_vi", INT_T, _OFFSET(dot11QosEntry.UAPSD_AC_VI), _SIZE(dot11QosEntry.UAPSD_AC_VI), 0}, + {"apsd_sta_vo", INT_T, _OFFSET(dot11QosEntry.UAPSD_AC_VO), _SIZE(dot11QosEntry.UAPSD_AC_VO), 0}, +#endif +#endif + +#ifdef RTL_MANUAL_EDCA + {"manual_edca", INT_T, _OFFSET(dot11QosEntry.ManualEDCA), _SIZE(dot11QosEntry.ManualEDCA), 0}, + {"sta_bkq_acm", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BK].ACM), _SIZE(dot11QosEntry.STA_manualEDCA[BK].ACM), 0}, + {"sta_bkq_aifsn", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BK].AIFSN), _SIZE(dot11QosEntry.STA_manualEDCA[BK].AIFSN), 7}, + {"sta_bkq_cwmin", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BK].ECWmin), _SIZE(dot11QosEntry.STA_manualEDCA[BK].ECWmin), 4}, + {"sta_bkq_cwmax", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BK].ECWmax), _SIZE(dot11QosEntry.STA_manualEDCA[BK].ECWmax), 10}, + {"sta_bkq_txoplimit", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BK].TXOPlimit), _SIZE(dot11QosEntry.STA_manualEDCA[BK].TXOPlimit), 0}, + {"sta_beq_acm", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BE].ACM), _SIZE(dot11QosEntry.STA_manualEDCA[BE].ACM), 0}, + {"sta_beq_aifsn", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BE].AIFSN), _SIZE(dot11QosEntry.STA_manualEDCA[BE].AIFSN), 3}, + {"sta_beq_cwmin", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BE].ECWmin), _SIZE(dot11QosEntry.STA_manualEDCA[BE].ECWmin), 4}, + {"sta_beq_cwmax", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BE].ECWmax), _SIZE(dot11QosEntry.STA_manualEDCA[BE].ECWmax), 10}, + {"sta_beq_txoplimit", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[BE].TXOPlimit), _SIZE(dot11QosEntry.STA_manualEDCA[BE].TXOPlimit), 0}, + {"sta_viq_acm", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VI].ACM), _SIZE(dot11QosEntry.STA_manualEDCA[VI].ACM), 0}, + {"sta_viq_aifsn", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VI].AIFSN), _SIZE(dot11QosEntry.STA_manualEDCA[VI].AIFSN), 2}, + {"sta_viq_cwmin", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VI].ECWmin), _SIZE(dot11QosEntry.STA_manualEDCA[VI].ECWmin), 3}, + {"sta_viq_cwmax", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VI].ECWmax), _SIZE(dot11QosEntry.STA_manualEDCA[VI].ECWmax), 4}, + {"sta_viq_txoplimit", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VI].TXOPlimit), _SIZE(dot11QosEntry.STA_manualEDCA[VI].TXOPlimit), 188}, + //{"ap_viq_txoplimit", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VI].TXOPlimit), _SIZE(dot11QosEntry.AP_manualEDCA[VI].TXOPlimit), (B band)?188:94}, + {"sta_voq_acm", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VO].ACM), _SIZE(dot11QosEntry.STA_manualEDCA[VO].ACM), 0}, + {"sta_voq_aifsn", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VO].AIFSN), _SIZE(dot11QosEntry.STA_manualEDCA[VO].AIFSN), 2}, + {"sta_voq_cwmin", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VO].ECWmin), _SIZE(dot11QosEntry.STA_manualEDCA[VO].ECWmin), 2}, + {"sta_voq_cwmax", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VO].ECWmax), _SIZE(dot11QosEntry.STA_manualEDCA[VO].ECWmax), 3}, + {"sta_voq_txoplimit", INT_T, _OFFSET(dot11QosEntry.STA_manualEDCA[VO].TXOPlimit), _SIZE(dot11QosEntry.STA_manualEDCA[VO].TXOPlimit), 102}, + //{"ap_voq_txoplimit", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VO].TXOPlimit), _SIZE(dot11QosEntry.AP_manualEDCA[VO].TXOPlimit), (B band)?102:47}, + //{"ap_beq_acm", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BE].ACM), _SIZE(dot11QosEntry.AP_manualEDCA[BE].ACM), 0}, + {"ap_beq_aifsn", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BE].AIFSN), _SIZE(dot11QosEntry.AP_manualEDCA[BE].AIFSN), 3}, + {"ap_beq_cwmin", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BE].ECWmin), _SIZE(dot11QosEntry.AP_manualEDCA[BE].ECWmin), 4}, + {"ap_beq_cwmax", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BE].ECWmax), _SIZE(dot11QosEntry.AP_manualEDCA[BE].ECWmax), 6}, + {"ap_beq_txoplimit", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BE].TXOPlimit), _SIZE(dot11QosEntry.AP_manualEDCA[BE].TXOPlimit), 0}, + //{"ap_bkq_acm", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BK].ACM), _SIZE(dot11QosEntry.AP_manualEDCA[BK].ACM), 0}, + {"ap_bkq_aifsn", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BK].AIFSN), _SIZE(dot11QosEntry.AP_manualEDCA[BK].AIFSN), 7}, + {"ap_bkq_cwmin", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BK].ECWmin), _SIZE(dot11QosEntry.AP_manualEDCA[BK].ECWmin), 4}, + {"ap_bkq_cwmax", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BK].ECWmax), _SIZE(dot11QosEntry.AP_manualEDCA[BK].ECWmax), 10}, + {"ap_bkq_txoplimit", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[BK].TXOPlimit), _SIZE(dot11QosEntry.AP_manualEDCA[BK].TXOPlimit), 0}, + //{"ap_viq_acm", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VI].ACM), _SIZE(dot11QosEntry.AP_manualEDCA[VI].ACM), 0}, + {"ap_viq_aifsn", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VI].AIFSN), _SIZE(dot11QosEntry.AP_manualEDCA[VI].AIFSN), 1}, + {"ap_viq_cwmin", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VI].ECWmin), _SIZE(dot11QosEntry.AP_manualEDCA[VI].ECWmin), 3}, + {"ap_viq_cwmax", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VI].ECWmax), _SIZE(dot11QosEntry.AP_manualEDCA[VI].ECWmax), 4}, + {"ap_viq_txoplimit", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VI].TXOPlimit), _SIZE(dot11QosEntry.AP_manualEDCA[VI].TXOPlimit), 188}, + //{"ap_viq_txoplimit", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VI].TXOPlimit), _SIZE(dot11QosEntry.AP_manualEDCA[VI].TXOPlimit), (B band)?188:94}, + //{"ap_voq_acm", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VO].ACM), _SIZE(dot11QosEntry.AP_manualEDCA[VO].ACM), 0}, + {"ap_voq_aifsn", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VO].AIFSN), _SIZE(dot11QosEntry.AP_manualEDCA[VO].AIFSN), 1}, + {"ap_voq_cwmin", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VO].ECWmin), _SIZE(dot11QosEntry.AP_manualEDCA[VO].ECWmin), 2}, + {"ap_voq_cwmax", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VO].ECWmax), _SIZE(dot11QosEntry.AP_manualEDCA[VO].ECWmax), 3}, + {"ap_voq_txoplimit", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VO].TXOPlimit), _SIZE(dot11QosEntry.AP_manualEDCA[VO].TXOPlimit), 102}, + //{"ap_voq_txoplimit", INT_T, _OFFSET(dot11QosEntry.AP_manualEDCA[VO].TXOPlimit), _SIZE(dot11QosEntry.AP_manualEDCA[VO].TXOPlimit), (B band)?102:47}, + + {"tid0_mapping", BYTE_T, _OFFSET(dot11QosEntry.TID_mapping[0]), _SIZE(dot11QosEntry.TID_mapping[0]), BE_QUEUE}, + {"tid1_mapping", BYTE_T, _OFFSET(dot11QosEntry.TID_mapping[1]), _SIZE(dot11QosEntry.TID_mapping[1]), BK_QUEUE}, + {"tid2_mapping", BYTE_T, _OFFSET(dot11QosEntry.TID_mapping[2]), _SIZE(dot11QosEntry.TID_mapping[2]), BK_QUEUE}, + {"tid3_mapping", BYTE_T, _OFFSET(dot11QosEntry.TID_mapping[3]), _SIZE(dot11QosEntry.TID_mapping[3]), BE_QUEUE}, + {"tid4_mapping", BYTE_T, _OFFSET(dot11QosEntry.TID_mapping[4]), _SIZE(dot11QosEntry.TID_mapping[4]), VI_QUEUE}, + {"tid5_mapping", BYTE_T, _OFFSET(dot11QosEntry.TID_mapping[5]), _SIZE(dot11QosEntry.TID_mapping[5]), VI_QUEUE}, + {"tid6_mapping", BYTE_T, _OFFSET(dot11QosEntry.TID_mapping[6]), _SIZE(dot11QosEntry.TID_mapping[6]), VO_QUEUE}, + {"tid7_mapping", BYTE_T, _OFFSET(dot11QosEntry.TID_mapping[7]), _SIZE(dot11QosEntry.TID_mapping[7]), VO_QUEUE}, +#endif //RTL_MANUAL_EDCA + +#endif //WIFI_WMM + +#ifdef WIFI_SIMPLE_CONFIG + // struct WifiSimpleConfigEntry + {"wsc_enable", INT_T, _OFFSET(wscEntry.wsc_enable), _SIZE(wscEntry.wsc_enable), 0}, + {"pin", PIN_IND_T, 0, 0}, + /* WPS2DOTX */ + /* support Assigned MAC Addr,Assigned SSID,dymanic change STA's PIN code, 2011-0505 */ + {"wsc_mypin", WSC_SELF_PIN_IND_T, 0, 0}, + {"wsc_specssid",WSC_SEPC_SSID_CONN_IND_T, 0, 0}, + {"wsc_specmac", WSC_SEPC_MAC_CONN_IND_T, 0, 0}, + /* WPS2DOTX */ +#ifdef INCLUDE_WPS +#ifndef CONFIG_MSC + {"wsc_start2", WSC_IND_T, 0, 0}, + {"wsc_end", WSC_IND_T, 0, 0}, + {"wsc_soap_action", WSC_IND_T, 0, 0}, + {"wps_led_control", WSC_IND_T, 0, 0}, + {"wps_get_config", WSC_IND_T, 0, 0}, + {"wps_debug", WSC_IND_T, 0, 0}, + {"wps_reinit", WSC_IND_T, 0, 0}, +#endif +#endif +#ifdef CONFIG_RTL_COMAPI_CFGFILE + {"wsc_start", WSC_START_IND_T, 0, 0}, + {"wsc_mode", WSC_MODE_IND_T, 0, 0}, + {"wsc_status", WSC_STATUS_IND_T, 0, 0}, + {"wsc_method", WSC_METHOD_IND_T, 0, 0}, + {"wsc_step", WSC_STEP_IND_T, 0, 0}, + {"wsc_oob", WSC_OOB_IND_T, 0, 0}, +#endif //CONFIG_RTL_COMAPI_CFGFILE +#endif + +#ifdef GBWC + // struct GroupBandWidthControl + {"gbwcmode", INT_T, _OFFSET(gbwcEntry.GBWCMode), _SIZE(gbwcEntry.GBWCMode), 0}, + {"gbwcnum", INT_T, _OFFSET(gbwcEntry.GBWCNum), _SIZE(gbwcEntry.GBWCNum), 0}, + {"gbwcaddr", ACL_T, _OFFSET(gbwcEntry.GBWCAddr), _SIZE(gbwcEntry.GBWCAddr), 0}, + {"gbwcthrd_tx", INT_T, _OFFSET(gbwcEntry.GBWCThrd_tx), _SIZE(gbwcEntry.GBWCThrd_tx), 30000}, + {"gbwcthrd_rx", INT_T, _OFFSET(gbwcEntry.GBWCThrd_rx), _SIZE(gbwcEntry.GBWCThrd_rx), 30000}, +#endif + + // struct Dot11nConfigEntry + {"supportedmcs",INT_T, _OFFSET(dot11nConfigEntry.dot11nSupportedMCS), _SIZE(dot11nConfigEntry.dot11nSupportedMCS), 0xffff}, + {"basicmcs", INT_T, _OFFSET(dot11nConfigEntry.dot11nBasicMCS), _SIZE(dot11nConfigEntry.dot11nBasicMCS), 0}, + {"use40M", INT_T, _OFFSET(dot11nConfigEntry.dot11nUse40M), _SIZE(dot11nConfigEntry.dot11nUse40M), 0}, + {"2ndchoffset", INT_T, _OFFSET(dot11nConfigEntry.dot11n2ndChOffset), _SIZE(dot11nConfigEntry.dot11n2ndChOffset), 1}, + {"shortGI20M", INT_T, _OFFSET(dot11nConfigEntry.dot11nShortGIfor20M), _SIZE(dot11nConfigEntry.dot11nShortGIfor20M), 0}, + {"shortGI40M", INT_T, _OFFSET(dot11nConfigEntry.dot11nShortGIfor40M), _SIZE(dot11nConfigEntry.dot11nShortGIfor40M), 0}, + {"shortGI80M", INT_T, _OFFSET(dot11nConfigEntry.dot11nShortGIfor80M), _SIZE(dot11nConfigEntry.dot11nShortGIfor80M), 0}, + {"stbc", INT_T, _OFFSET(dot11nConfigEntry.dot11nSTBC), _SIZE(dot11nConfigEntry.dot11nSTBC), 1}, +#if defined(CONFIG_RTL8672) && defined(CONFIG_WLAN_HAL_8192EE) + {"ldpc", INT_T, _OFFSET(dot11nConfigEntry.dot11nLDPC), _SIZE(dot11nConfigEntry.dot11nLDPC), 0}, +#else + {"ldpc", INT_T, _OFFSET(dot11nConfigEntry.dot11nLDPC), _SIZE(dot11nConfigEntry.dot11nLDPC), 1}, +#endif + {"ampdu", INT_T, _OFFSET(dot11nConfigEntry.dot11nAMPDU), _SIZE(dot11nConfigEntry.dot11nAMPDU), 0}, + {"amsdu", INT_T, _OFFSET(dot11nConfigEntry.dot11nAMSDU), _SIZE(dot11nConfigEntry.dot11nAMSDU), 0}, + // for support SIGMA_TEST + {"addba_reject",INT_T, _OFFSET(dot11nConfigEntry.dot11nAddBAreject), _SIZE(dot11nConfigEntry.dot11nAddBAreject), 0}, + {"ampduSndSz", INT_T, _OFFSET(dot11nConfigEntry.dot11nAMPDUSendSz), _SIZE(dot11nConfigEntry.dot11nAMPDUSendSz), 0}, +#ifdef CONFIG_WLAN_HAL_8814AE + {"supportedvht",INT_T, _OFFSET(dot11acConfigEntry.dot11SupportedVHT), _SIZE(dot11acConfigEntry.dot11SupportedVHT), 0xffea}, +#else + {"supportedvht",INT_T, _OFFSET(dot11acConfigEntry.dot11SupportedVHT), _SIZE(dot11acConfigEntry.dot11SupportedVHT), 0xfffa}, +#endif + {"vht_txmap",INT_T, _OFFSET(dot11acConfigEntry.dot11VHT_TxMap), _SIZE(dot11acConfigEntry.dot11VHT_TxMap), 0x3fffffff}, + +#ifdef RX_BUFFER_GATHER + {"amsduMax", INT_T, _OFFSET(dot11nConfigEntry.dot11nAMSDURecvMax), _SIZE(dot11nConfigEntry.dot11nAMSDURecvMax), 1}, +#else +#if defined(CONFIG_RTL8196B_GW_8M) || defined(CONFIG_RTL8196C_AP_ROOT) || defined(CONFIG_RTL_8198_AP_ROOT) || defined(CONFIG_RTL8196C_CLIENT_ONLY) + {"amsduMax", INT_T, _OFFSET(dot11nConfigEntry.dot11nAMSDURecvMax), _SIZE(dot11nConfigEntry.dot11nAMSDURecvMax), 0}, +#else + {"amsduMax", INT_T, _OFFSET(dot11nConfigEntry.dot11nAMSDURecvMax), _SIZE(dot11nConfigEntry.dot11nAMSDURecvMax), 0}, +#endif +#endif + {"amsduTimeout",INT_T, _OFFSET(dot11nConfigEntry.dot11nAMSDUSendTimeout), _SIZE(dot11nConfigEntry.dot11nAMSDUSendTimeout), 400}, /*in us*/ + {"amsduNum", INT_T, _OFFSET(dot11nConfigEntry.dot11nAMSDUSendNum), _SIZE(dot11nConfigEntry.dot11nAMSDUSendNum), 15}, + {"lgyEncRstrct",INT_T, _OFFSET(dot11nConfigEntry.dot11nLgyEncRstrct), _SIZE(dot11nConfigEntry.dot11nLgyEncRstrct), 15}, +#ifdef WIFI_11N_2040_COEXIST +#ifdef CONFIG_SDIO_HCI + {"coexist", INT_T, _OFFSET(dot11nConfigEntry.dot11nCoexist), _SIZE(dot11nConfigEntry.dot11nCoexist), 1}, +#else + {"coexist", INT_T, _OFFSET(dot11nConfigEntry.dot11nCoexist), _SIZE(dot11nConfigEntry.dot11nCoexist), 0}, + {"coexist_ch_chk", INT_T, _OFFSET(dot11nConfigEntry.dot11nCoexist_ch_chk), _SIZE(dot11nConfigEntry.dot11nCoexist_ch_chk), 0}, +#endif + {"bg_ap_rssi_chk_th", INT_T, _OFFSET(dot11nConfigEntry.dot11nBGAPRssiChkTh), _SIZE(dot11nConfigEntry.dot11nBGAPRssiChkTh), 20}, +#endif + {"txnoack", INT_T, _OFFSET(dot11nConfigEntry.dot11nTxNoAck), _SIZE(dot11nConfigEntry.dot11nTxNoAck), 0}, + + // struct ReorderControlEntry + {"rc_enable", INT_T, _OFFSET(reorderCtrlEntry.ReorderCtrlEnable), _SIZE(reorderCtrlEntry.ReorderCtrlEnable), 1}, + {"rc_winsz", INT_T, _OFFSET(reorderCtrlEntry.ReorderCtrlWinSz), _SIZE(reorderCtrlEntry.ReorderCtrlWinSz), RC_ENTRY_NUM}, + {"rc_timeout", INT_T, _OFFSET(reorderCtrlEntry.ReorderCtrlTimeout), _SIZE(reorderCtrlEntry.ReorderCtrlTimeout), 30000}, /*in us*/ + +#ifdef CONFIG_RTK_VLAN_SUPPORT + // struct VlanConfig + {"global_vlan", INT_T, _OFFSET(vlan.global_vlan), _SIZE(vlan.global_vlan), 0}, + {"is_lan", INT_T, _OFFSET(vlan.is_lan), _SIZE(vlan.is_lan), 1}, + {"vlan_enable", INT_T, _OFFSET(vlan.vlan_enable), _SIZE(vlan.vlan_enable), 0}, + {"vlan_tag", INT_T, _OFFSET(vlan.vlan_tag), _SIZE(vlan.vlan_tag), 0}, + {"vlan_id", INT_T, _OFFSET(vlan.vlan_id), _SIZE(vlan.vlan_id), 0}, + {"vlan_pri", INT_T, _OFFSET(vlan.vlan_pri), _SIZE(vlan.vlan_pri), 0}, + {"vlan_cfi", INT_T, _OFFSET(vlan.vlan_cfi), _SIZE(vlan.vlan_cfi), 0}, +#endif + +#ifdef CONFIG_RTL_WAPI_SUPPORT + {"wapiType", INT_T, _OFFSET(wapiInfo.wapiType), _SIZE(wapiInfo.wapiType), 0}, +#ifdef WAPI_SUPPORT_MULTI_ENCRYPT + {"wapiUCastEncodeType", INT_T, _OFFSET(wapiInfo.wapiUCastEncodeType), _SIZE(wapiInfo.wapiUCastEncodeType), 0}, + {"wapiMCastEncodeType", INT_T, _OFFSET(wapiInfo.wapiMCastEncodeType), _SIZE(wapiInfo.wapiMCastEncodeType), 0}, +#endif + {"wapiPsk", WAPI_KEY_T, _OFFSET(wapiInfo.wapiPsk), _SIZE(wapiInfo.wapiPsk), 0}, + {"wapiPsklen", INT_T, _OFFSET(wapiInfo.wapiPsk.len), _SIZE(wapiInfo.wapiPsk.len), 0}, + {"wapiUCastKeyType", INT_T, _OFFSET(wapiInfo.wapiUpdateUCastKeyType), _SIZE(wapiInfo.wapiUpdateUCastKeyType), 0}, + {"wapiUCastKeyTimeout", INT_T, _OFFSET(wapiInfo.wapiUpdateUCastKeyTimeout), _SIZE(wapiInfo.wapiUpdateUCastKeyTimeout), 0}, + {"wapiUCastKeyPktNum", INT_T, _OFFSET(wapiInfo.wapiUpdateUCastKeyPktNum), _SIZE(wapiInfo.wapiUpdateUCastKeyPktNum), 0}, + {"wapiMCastKeyType", INT_T, _OFFSET(wapiInfo.wapiUpdateMCastKeyType), _SIZE(wapiInfo.wapiUpdateMCastKeyType), 0}, + {"wapiMCastKeyTimeout", INT_T, _OFFSET(wapiInfo.wapiUpdateMCastKeyTimeout), _SIZE(wapiInfo.wapiUpdateMCastKeyTimeout), 0}, + {"wapiMCastKeyPktNum", INT_T, _OFFSET(wapiInfo.wapiUpdateMCastKeyPktNum), _SIZE(wapiInfo.wapiUpdateMCastKeyPktNum), 0}, + {"wapiTimeout", INT_ARRAY_T, _OFFSET(wapiInfo.wapiTimeout), _SIZE(wapiInfo.wapiTimeout), 0}, +#endif + +#ifdef DOT11D + {"countrycode", INT_T, _OFFSET(dot11dCountry.dot11CountryCodeSwitch), _SIZE(dot11dCountry.dot11CountryCodeSwitch), 1}, +#endif +#if defined(DOT11D) || defined(DOT11H) + {"countrystr", STRING_T, _OFFSET(dot11dCountry.dot11CountryString), _SIZE(dot11dCountry.dot11CountryString), 0}, +#endif + +#ifdef SUPPORT_MULTI_PROFILE + {"ap_profile_enable", INT_T, _OFFSET(ap_profile.enable_profile), _SIZE(ap_profile.enable_profile), 0}, + {"ap_profile_num", INT_T, _OFFSET(ap_profile.profile_num), _SIZE(ap_profile.profile_num), 0}, + {"ap_profile_add", AP_PROFILE_T, _OFFSET(ap_profile), _SIZE(ap_profile), 0}, + {"sortbyprofile", INT_T, _OFFSET(ap_profile.sortbyprofile), _SIZE(ap_profile.sortbyprofile), 0}, +#endif + +/* Hotspot 2.0 */ +#ifdef HS2_SUPPORT +/* Release 1 */ + {"cubeaconintval", INT_T, _OFFSET(hs2Entry.channel_utili_beaconIntval), _SIZE(hs2Entry.channel_utili_beaconIntval), 10}, + {"timedtimintval", INT_T, _OFFSET(hs2Entry.timeadvt_DTIMIntval), _SIZE(hs2Entry.timeadvt_DTIMIntval), 1}, + {"reqmode", INT_T, _OFFSET(hs2Entry.reqmode), _SIZE(hs2Entry.reqmode), 16}, + {"distime", INT_T, _OFFSET(hs2Entry.disassoc_timer), _SIZE(hs2Entry.disassoc_timer), 10}, + {"valintval", INT_T, _OFFSET(hs2Entry.validity_intval), _SIZE(hs2Entry.validity_intval), 0}, + {"surl", STRING_T, _OFFSET(hs2Entry.session_url), _SIZE(hs2Entry.session_url), 0}, + {"redir_mac", BYTE_ARRAY_T, _OFFSET(hs2Entry.redir_mac), _SIZE(hs2Entry.redir_mac), 0}, + {"tsm_req", BYTE_ARRAY_T, _OFFSET(hs2Entry.sta_mac), _SIZE(hs2Entry.sta_mac), 0}, + {"roam_enable", INT_T, _OFFSET(hs2Entry.roam_enable), _SIZE(hs2Entry.roam_enable), 1}, + {"mmpdu_limit", INT_T, _OFFSET(hs2Entry.mmpdu_limit), _SIZE(hs2Entry.mmpdu_limit), 600}, + {"ICMPv4ECHO", INT_T, _OFFSET(hs2Entry.ICMPv4ECHO), _SIZE(hs2Entry.ICMPv4ECHO), 2}, +#ifdef HS2_DEBUGMSG + {"HS2_debug_info", INT_T, ((int)(long *)&(_HS2_debug_info)), sizeof(_HS2_debug_info), 1}, + {"HS2_debug_err", INT_T, ((int)(long *)&(_HS2_debug_err)), sizeof(_HS2_debug_err), 1}, + {"HS2_debug_trace", INT_T, ((int)(long *)&(_HS2_debug_trace)), sizeof(_HS2_debug_trace), 0}, + {"HS2_debug_warn", INT_T, ((int)(long *)&(_HS2_debug_warn)), sizeof(_HS2_debug_warn), 0}, +#endif +#endif //HS2_SUPPORT + +#if defined(SWITCH_CHAN) && defined(UNIVERSAL_REPEATER) + {"switch_chan", SWITCH_CHAN_T, _OFFSET(dot11RFEntry.dot11channel), _SIZE(dot11RFEntry.dot11channel), 0}, +#endif + +#ifdef _DEBUG_RTL8192CD_ + // debug flag + {"debug_err", DEBUG_T, 1, sizeof(rtl8192cd_debug_err), 0}, + {"debug_info", DEBUG_T, 2, sizeof(rtl8192cd_debug_info), 0}, + {"debug_trace", DEBUG_T, 3, sizeof(rtl8192cd_debug_trace), 0}, + {"debug_warn", DEBUG_T, 4, sizeof(rtl8192cd_debug_warn), 0}, +#endif + + // for RF debug + {"ofdm_1ss_oneAnt", RFFT_T, _OFFSET_RFFT(ofdm_1ss_oneAnt), _SIZE_RFFT(ofdm_1ss_oneAnt), 0},// 1ss and ofdm rate using one ant + {"pathB_1T", RFFT_T, _OFFSET_RFFT(pathB_1T), _SIZE_RFFT(pathB_1T), 0},// using pathB as 1T2R/1T1R tx path + {"rssi_dump", RFFT_T, _OFFSET_RFFT(rssi_dump), _SIZE_RFFT(rssi_dump), 0}, + {"rxfifoO", RFFT_T, _OFFSET_RFFT(rxfifoO), _SIZE_RFFT(rxfifoO), 0}, + {"raGoDownUpper", RFFT_T, _OFFSET_RFFT(raGoDownUpper), _SIZE_RFFT(raGoDownUpper), 50}, + {"raGoDown20MLower",RFFT_T, _OFFSET_RFFT(raGoDown20MLower), _SIZE_RFFT(raGoDown20MLower), 18}, + {"raGoDown40MLower",RFFT_T, _OFFSET_RFFT(raGoDown40MLower), _SIZE_RFFT(raGoDown40MLower), 15}, + {"raGoUpUpper", RFFT_T, _OFFSET_RFFT(raGoUpUpper), _SIZE_RFFT(raGoUpUpper), 55}, + {"raGoUp20MLower", RFFT_T, _OFFSET_RFFT(raGoUp20MLower), _SIZE_RFFT(raGoUp20MLower), 23}, + {"raGoUp40MLower", RFFT_T, _OFFSET_RFFT(raGoUp40MLower), _SIZE_RFFT(raGoUp40MLower), 20}, + {"dig_enable", RFFT_T, _OFFSET_RFFT(dig_enable), _SIZE_RFFT(dig_enable), 1}, + {"adaptivity_enable", RFFT_T, _OFFSET_RFFT(adaptivity_enable), _SIZE_RFFT(adaptivity_enable), 0}, + {"nbi_filter_enable", RFFT_T, _OFFSET_RFFT(nbi_filter_enable), _SIZE_RFFT(nbi_filter_enable), 1}, + {"dig_cov_enable", RFFT_T, _OFFSET_RFFT(dig_cov_enable), _SIZE_RFFT(dig_cov_enable), 0}, + {"adap_debug", RFFT_T, _OFFSET_RFFT(adap_debug), _SIZE_RFFT(adap_debug), 0}, +#ifdef INTERFERENCE_CONTROL + {"digGoLowerLevel", RFFT_T, _OFFSET_RFFT(digGoLowerLevel), _SIZE_RFFT(digGoLowerLevel), 30}, + {"digGoUpperLevel", RFFT_T, _OFFSET_RFFT(digGoUpperLevel), _SIZE_RFFT(digGoUpperLevel), 35}, +#else + {"digGoLowerLevel", RFFT_T, _OFFSET_RFFT(digGoLowerLevel), _SIZE_RFFT(digGoLowerLevel), 35}, + {"digGoUpperLevel", RFFT_T, _OFFSET_RFFT(digGoUpperLevel), _SIZE_RFFT(digGoUpperLevel), 40}, +#endif + {"dcThUpper", RFFT_T, _OFFSET_RFFT(dcThUpper), _SIZE_RFFT(dcThUpper), 30}, + {"dcThLower", RFFT_T, _OFFSET_RFFT(dcThLower), _SIZE_RFFT(dcThLower), 25}, + {"rssiTx20MUpper", RFFT_T, _OFFSET_RFFT(rssiTx20MUpper), _SIZE_RFFT(rssiTx20MUpper), 20}, + {"rssiTx20MLower", RFFT_T, _OFFSET_RFFT(rssiTx20MLower), _SIZE_RFFT(rssiTx20MLower), 15}, + {"rssi_expire_to", RFFT_T, _OFFSET_RFFT(rssi_expire_to), _SIZE_RFFT(rssi_expire_to), 60}, + {"rts_init_rate", RFFT_T, _OFFSET_RFFT(rts_init_rate), _SIZE_RFFT(rts_init_rate), 0}, + {"auto_rts_rate", RFFT_T, _OFFSET_RFFT(auto_rts_rate), _SIZE_RFFT(auto_rts_rate), 1}, + + {"cck_pwr_max", RFFT_T, _OFFSET_RFFT(cck_pwr_max), _SIZE_RFFT(cck_pwr_max), 0}, + {"cck_tx_pathB", RFFT_T, _OFFSET_RFFT(cck_tx_pathB), _SIZE_RFFT(cck_tx_pathB), 0}, + + {"tx_pwr_ctrl", RFFT_T, _OFFSET_RFFT(tx_pwr_ctrl), _SIZE_RFFT(tx_pwr_ctrl), 1}, + + // 11n ap AES debug + {"aes_check_th", RFFT_T, _OFFSET_RFFT(aes_check_th), _SIZE_RFFT(aes_check_th), 2}, + + // Tx power tracking + {"tpt_period", RFFT_T, _OFFSET_RFFT(tpt_period), _SIZE_RFFT(tpt_period), 30}, + + // TXOP enlarge + {"txop_enlarge_upper", RFFT_T, _OFFSET_RFFT(txop_enlarge_upper), _SIZE_RFFT(txop_enlarge_upper), 20}, + {"txop_enlarge_lower", RFFT_T, _OFFSET_RFFT(txop_enlarge_lower), _SIZE_RFFT(txop_enlarge_lower), 15}, + +#ifdef LOW_TP_TXOP + {"low_tp_txop", RFFT_T, _OFFSET_RFFT(low_tp_txop), _SIZE_RFFT(low_tp_txop), 1}, + {"low_tp_txop_thd_n", RFFT_T, _OFFSET_RFFT(low_tp_txop_thd_n), _SIZE_RFFT(low_tp_txop_thd_n), 22}, + {"low_tp_txop_thd_g", RFFT_T, _OFFSET_RFFT(low_tp_txop_thd_g), _SIZE_RFFT(low_tp_txop_thd_g), 17}, + {"low_tp_txop_thd_low", RFFT_T, _OFFSET_RFFT(low_tp_txop_thd_low), _SIZE_RFFT(low_tp_txop_thd_low), 0}, + {"low_tp_txop_delay", RFFT_T, _OFFSET_RFFT(low_tp_txop_delay), _SIZE_RFFT(low_tp_txop_delay), 1}, + {"cwmax_enhance_thd", RFFT_T, _OFFSET_RFFT(cwmax_enhance_thd), _SIZE_RFFT(cwmax_enhance_thd), 2000}, +#endif + + // 2.3G support + {"frq_2_3G", RFFT_T, _OFFSET_RFFT(use_frq_2_3G), _SIZE_RFFT(use_frq_2_3G), 0}, + + // for mp test +#ifdef MP_TEST + {"mp_specific", RFFT_T, _OFFSET_RFFT(mp_specific), _SIZE_RFFT(mp_specific), 0}, +#endif + +#ifdef IGMP_FILTER_CMO + {"igmp_deny", RFFT_T, _OFFSET_RFFT(igmp_deny), _SIZE_RFFT(igmp_deny), 0}, +#endif + //Support IP multicast->unicast +#ifdef SUPPORT_TX_MCAST2UNI + {"mc2u_disable", RFFT_T, _OFFSET_RFFT(mc2u_disable), _SIZE_RFFT(mc2u_disable), 0}, +#ifdef CONFIG_RTL8672 + {"mc2u_drop_unknown", RFFT_T, _OFFSET_RFFT(mc2u_drop_unknown), _SIZE_RFFT(mc2u_drop_unknown), 1}, +#else + {"mc2u_drop_unknown", RFFT_T, _OFFSET_RFFT(mc2u_drop_unknown), _SIZE_RFFT(mc2u_drop_unknown), 0}, +#endif + {"mc2u_flood_ctrl", RFFT_T, _OFFSET_RFFT(mc2u_flood_ctrl), _SIZE_RFFT(mc2u_flood_ctrl), 0}, + {"mc2u_flood_mac_num", RFFT_T, _OFFSET_RFFT(mc2u_flood_mac_num), _SIZE_RFFT(mc2u_flood_mac_num), 0}, + {"mc2u_flood_mac", RFFT_ACL_T, _OFFSET_RFFT(mc2u_flood_mac), _SIZE_RFFT(mc2u_flood_mac), 0}, +#endif + +#ifdef HIGH_POWER_EXT_PA + {"use_ext_pa", RFFT_T, _OFFSET_RFFT(use_ext_pa), _SIZE_RFFT(use_ext_pa), 0}, + {"hp_ofdm_max", RFFT_T, _OFFSET_RFFT(hp_ofdm_pwr_max), _SIZE_RFFT(hp_ofdm_pwr_max), 63}, + {"hp_cck_max", RFFT_T, _OFFSET_RFFT(hp_cck_pwr_max), _SIZE_RFFT(hp_cck_pwr_max), 63}, +#endif + +#if defined(CONFIG_RTL_NOISE_CONTROL) || defined(CONFIG_RTL_NOISE_CONTROL_92C) + {"dnc_enable", RFFT_T, _OFFSET_RFFT(dnc_enable), _SIZE_RFFT(dnc_enable), 1}, +#endif + +#if defined(WIFI_11N_2040_COEXIST_EXT) + {"bws_thd", RFFT_T, _OFFSET_RFFT(bws_Thd), _SIZE_RFFT(bws_Thd), 1000}, + {"bws_enable", RFFT_T, _OFFSET_RFFT(bws_enable), _SIZE_RFFT(bws_enable), 1}, +#endif +#ifdef HIGH_POWER_EXT_LNA + {"use_ext_lna", RFFT_T, _OFFSET_RFFT(use_ext_lna), _SIZE_RFFT(use_ext_lna), 0}, + {"ext_lna_gain", RFFT_T, _OFFSET_RFFT(ext_lna_gain), _SIZE_RFFT(ext_lna_gain), 0}, +#endif + {"ndsi_support", RFFT_T, _OFFSET_RFFT(NDSi_support), _SIZE_RFFT(NDSi_support), 0}, + {"TH_L2H_ini", RFFT_T, _OFFSET_RFFT(TH_L2H_ini_backup), _SIZE_RFFT(TH_L2H_ini_backup), 0xf3},// 0xf3 + {"TH_HL_diff", RFFT_T, _OFFSET_RFFT(TH_EDCCA_HL_diff), _SIZE_RFFT(TH_EDCCA_HL_diff), 7},//Adaptivity() + {"dcbackoff", RFFT_T, _OFFSET_RFFT(dcbackoff), _SIZE_RFFT(dcbackoff), 2},//Adaptivity() + +#ifdef EN_EFUSE + {"use_efuse", INT_T, _OFFSET(efuseEntry.enable_efuse), _SIZE(efuseEntry.enable_efuse), 1}, +#endif + +#ifdef RF_MIMO_SWITCH + {"rf_mode", RFFT_T, _OFFSET_RFFT(rf_mode), _SIZE_RFFT(rf_mode), 2}, +#endif +#ifdef PCIE_POWER_SAVING + {"ps", RFFT_T, _OFFSET_RFFT(power_save), _SIZE_RFFT(power_save), (/*L2_en|*/ L1_en|_1x1_en|offload_en|stop_dma_en)}, +#if defined(RTL8676_WAKE_GPIO) && defined(WIFI_SIMPLE_CONFIG) + {"wps_led_active", RFFT_T, _OFFSET_RFFT(wps_led_active), _SIZE_RFFT(wps_led_active), 0}, +#endif +#endif + + +#ifdef SW_ANT_SWITCH + {"antSw_enable", RFFT_T, _OFFSET_RFFT(antSw_enable), _SIZE_RFFT(antSw_enable), 1}, +// {"antSw_dump", RFFT_T, _OFFSET_RFFT(antSw_dump), _SIZE_RFFT(antSw_dump), 0}, +#endif +#ifdef HW_ANT_SWITCH + {"antHw_enable", RFFT_T, _OFFSET_RFFT(antHw_enable), _SIZE_RFFT(antHw_enable), 1}, +#endif +#if defined(HW_ANT_SWITCH) || defined(SW_ANT_SWITCH) + {"antdump", RFFT_T, _OFFSET_RFFT(ant_dump), _SIZE_RFFT(ant_dump), 0}, + {"antSw_select", RFFT_T, _OFFSET_RFFT(antSw_select), _SIZE_RFFT(antSw_select), 1}, +#endif +#ifdef ADD_TX_POWER_BY_CMD + {"txPowerPlus_cck_1", RFFT_T, _OFFSET_RFFT(txPowerPlus_cck_1), _SIZE_RFFT(txPowerPlus_cck_1), 0x7f}, + {"txPowerPlus_cck_2", RFFT_T, _OFFSET_RFFT(txPowerPlus_cck_2), _SIZE_RFFT(txPowerPlus_cck_2), 0x7f}, + {"txPowerPlus_cck_5", RFFT_T, _OFFSET_RFFT(txPowerPlus_cck_5), _SIZE_RFFT(txPowerPlus_cck_5), 0x7f}, + {"txPowerPlus_cck_11", RFFT_T, _OFFSET_RFFT(txPowerPlus_cck_11), _SIZE_RFFT(txPowerPlus_cck_11), 0x7f}, + {"txPowerPlus_ofdm_6", RFFT_T, _OFFSET_RFFT(txPowerPlus_ofdm_6), _SIZE_RFFT(txPowerPlus_ofdm_6), 0x7f}, + {"txPowerPlus_ofdm_9", RFFT_T, _OFFSET_RFFT(txPowerPlus_ofdm_9), _SIZE_RFFT(txPowerPlus_ofdm_9), 0x7f}, + {"txPowerPlus_ofdm_12", RFFT_T, _OFFSET_RFFT(txPowerPlus_ofdm_12), _SIZE_RFFT(txPowerPlus_ofdm_12), 0x7f}, + {"txPowerPlus_ofdm_18", RFFT_T, _OFFSET_RFFT(txPowerPlus_ofdm_18), _SIZE_RFFT(txPowerPlus_ofdm_18), 0x7f}, + {"txPowerPlus_ofdm_24", RFFT_T, _OFFSET_RFFT(txPowerPlus_ofdm_24), _SIZE_RFFT(txPowerPlus_ofdm_24), 0x7f}, + {"txPowerPlus_ofdm_36", RFFT_T, _OFFSET_RFFT(txPowerPlus_ofdm_36), _SIZE_RFFT(txPowerPlus_ofdm_36), 0x7f}, + {"txPowerPlus_ofdm_48", RFFT_T, _OFFSET_RFFT(txPowerPlus_ofdm_48), _SIZE_RFFT(txPowerPlus_ofdm_48), 0x7f}, + {"txPowerPlus_ofdm_54", RFFT_T, _OFFSET_RFFT(txPowerPlus_ofdm_54), _SIZE_RFFT(txPowerPlus_ofdm_54), 0x7f}, + {"txPowerPlus_mcs_0", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_0), _SIZE_RFFT(txPowerPlus_mcs_0), 0x7f}, + {"txPowerPlus_mcs_1", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_1), _SIZE_RFFT(txPowerPlus_mcs_1), 0x7f}, + {"txPowerPlus_mcs_2", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_2), _SIZE_RFFT(txPowerPlus_mcs_2), 0x7f}, + {"txPowerPlus_mcs_3", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_3), _SIZE_RFFT(txPowerPlus_mcs_3), 0x7f}, + {"txPowerPlus_mcs_4", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_4), _SIZE_RFFT(txPowerPlus_mcs_4), 0x7f}, + {"txPowerPlus_mcs_5", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_5), _SIZE_RFFT(txPowerPlus_mcs_5), 0x7f}, + {"txPowerPlus_mcs_6", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_6), _SIZE_RFFT(txPowerPlus_mcs_6), 0x7f}, + {"txPowerPlus_mcs_7", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_7), _SIZE_RFFT(txPowerPlus_mcs_7), 0x7f}, + {"txPowerPlus_mcs_8", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_8), _SIZE_RFFT(txPowerPlus_mcs_8), 0x7f}, + {"txPowerPlus_mcs_9", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_9), _SIZE_RFFT(txPowerPlus_mcs_9), 0x7f}, + {"txPowerPlus_mcs_10", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_10), _SIZE_RFFT(txPowerPlus_mcs_10), 0x7f}, + {"txPowerPlus_mcs_11", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_11), _SIZE_RFFT(txPowerPlus_mcs_11), 0x7f}, + {"txPowerPlus_mcs_12", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_12), _SIZE_RFFT(txPowerPlus_mcs_12), 0x7f}, + {"txPowerPlus_mcs_13", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_13), _SIZE_RFFT(txPowerPlus_mcs_13), 0x7f}, + {"txPowerPlus_mcs_14", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_14), _SIZE_RFFT(txPowerPlus_mcs_14), 0x7f}, + {"txPowerPlus_mcs_15", RFFT_T, _OFFSET_RFFT(txPowerPlus_mcs_15), _SIZE_RFFT(txPowerPlus_mcs_15), 0x7f}, +#endif + + {"rootFwBeacon", RFFT_T, _OFFSET_RFFT(rootFwBeacon), _SIZE_RFFT(rootFwBeacon), 1}, + {"ledBlinkingFreq", RFFT_T, _OFFSET_RFFT(ledBlinkingFreq), _SIZE_RFFT(ledBlinkingFreq), 1}, + + {"diffAmpduSz", RFFT_T, _OFFSET_RFFT(diffAmpduSz), _SIZE_RFFT(diffAmpduSz), 1}, + {"1rcca", RFFT_T, _OFFSET_RFFT(one_path_cca), _SIZE_RFFT(one_path_cca), 0}, +#ifdef CONFIG_1RCCA_RF_POWER_SAVING + {"1rcca_ps", RFFT_T, _OFFSET_RFFT(_1rcca_ps), _SIZE_RFFT(_1rcca_ps), 2}, + {"1rcca_ps_rssi_thd", RFFT_T, _OFFSET_RFFT(_1rcca_ps_rssi_thd), _SIZE_RFFT(_1rcca_ps_rssi_thd), 30}, +#endif + +#if defined(CONFIG_RTL_COMAPI_CFGFILE) || defined(SDIO_2_PORT) + {"hwaddr", BYTE_ARRAY_T, _OFFSET(dot11OperationEntry.hwaddr), _SIZE(dot11OperationEntry.hwaddr), 0}, +#endif +#ifdef CONFIG_IEEE80211W_CMD + {"pmf_sta_mac", BYTE_ARRAY_T, _OFFSET(dot11StationConfigEntry.deauth_mac), _SIZE(dot11StationConfigEntry.deauth_mac), 0}, +#ifdef CONFIG_IEEE80211W_CLI + {"pmf_sa_mac", BYTE_ARRAY_T, _OFFSET(dot11StationConfigEntry.sa_req_mac), _SIZE(dot11StationConfigEntry.sa_req_mac), 0}, + {"pmf_cli_test", BYTE_T, _OFFSET(dot11StationConfigEntry.pmf_cli_test), _SIZE(dot11StationConfigEntry.pmf_cli_test), 0}, +#endif + {"pmftest", BYTE_T, _OFFSET(dot11StationConfigEntry.pmftest), _SIZE(dot11StationConfigEntry.pmftest), 0}, + {"enableSHA256", BYTE_T, _OFFSET(dot1180211AuthEntry.dot11EnableSHA256), _SIZE(dot1180211AuthEntry.dot11EnableSHA256), 0}, + {"dot11IEEE80211W", BYTE_T, _OFFSET(dot1180211AuthEntry.dot11IEEE80211W), _SIZE(dot1180211AuthEntry.dot11IEEE80211W), 0}, +#endif +#ifdef CONFIG_RTL_COMAPI_CFGFILE + {"ssid2scan", SSID2SCAN_STRING_T, _OFFSET(dot11StationConfigEntry.dot11SSIDtoScan), _SIZE(dot11StationConfigEntry.dot11SSIDtoScan), 0}, +#ifdef CONFIG_RTK_MESH + {"meshSilence", BYTE_T, _OFFSET(dot1180211sInfo.meshSilence), _SIZE(dot1180211sInfo.meshSilence), 0}, +#endif +#endif + +#ifdef DFS + {"dfsdbgmode", RFFT_T, _OFFSET_RFFT(dfsdbgmode), _SIZE_RFFT(dfsdbgmode), 0}, + {"force_TP_mode", RFFT_T, _OFFSET_RFFT(dfs_force_TP_mode), _SIZE_RFFT(dfs_force_TP_mode), 0}, + {"dfsdelayiqk", RFFT_T, _OFFSET_RFFT(dfsdelayiqk), _SIZE_RFFT(dfsdelayiqk), 1}, + {"dfs_next_ch", RFFT_T, _OFFSET_RFFT(dfs_next_ch), _SIZE_RFFT(dfs_next_ch), 0}, + {"det_off", RFFT_T, _OFFSET_RFFT(dfs_det_off), _SIZE_RFFT(dfs_det_off), 0}, + #if defined(CONFIG_WLAN_HAL_8814AE) + {"radar_diff_on", RFFT_T, _OFFSET_RFFT(dfs_radar_diff_on), _SIZE_RFFT(dfs_radar_diff_on), 0}, + {"radar_diff_print", RFFT_T, _OFFSET_RFFT(dfs_radar_diff_print), _SIZE_RFFT(dfs_radar_diff_print), 0}, + {"print_hist_report", RFFT_T, _OFFSET_RFFT(dfs_print_hist_report), _SIZE_RFFT(dfs_print_hist_report), 0}, + #endif + {"det_reset", RFFT_T, _OFFSET_RFFT(dfs_det_reset), _SIZE_RFFT(dfs_det_reset), 0}, + {"fa_lower", RFFT_T, _OFFSET_RFFT(dfs_fa_cnt_lower), _SIZE_RFFT(dfs_fa_cnt_lower), 25}, + {"fa_mid", RFFT_T, _OFFSET_RFFT(dfs_fa_cnt_mid), _SIZE_RFFT(dfs_fa_cnt_mid), 35}, + {"fa_upper", RFFT_T, _OFFSET_RFFT(dfs_fa_cnt_upper), _SIZE_RFFT(dfs_fa_cnt_upper), 50}, + {"fa_hist", RFFT_T, _OFFSET_RFFT(dfs_fa_hist), _SIZE_RFFT(dfs_fa_hist), 50}, + {"fa_inc_ratio", RFFT_T, _OFFSET_RFFT(dfs_fa_cnt_inc_ratio), _SIZE_RFFT(dfs_fa_cnt_inc_ratio), 2}, + {"crc32_lower", RFFT_T, _OFFSET_RFFT(dfs_crc32_cnt_lower), _SIZE_RFFT(dfs_crc32_cnt_lower), 10}, + {"ratio_th", RFFT_T, _OFFSET_RFFT(dfs_fa_ratio_th), _SIZE_RFFT(dfs_fa_ratio_th), 15}, + {"det_period", RFFT_T, _OFFSET_RFFT(dfs_det_period), _SIZE_RFFT(dfs_det_period), 20}, + {"det_period_jp_w53", RFFT_T, _OFFSET_RFFT(dfs_det_period_jp_w53), _SIZE_RFFT(dfs_det_period_jp_w53), 15}, + {"det_print", RFFT_T, _OFFSET_RFFT(dfs_det_print), _SIZE_RFFT(dfs_det_print), 0}, + {"det_print1", RFFT_T, _OFFSET_RFFT(dfs_det_print1), _SIZE_RFFT(dfs_det_print1), 1}, + {"det_print2", RFFT_T, _OFFSET_RFFT(dfs_det_print2), _SIZE_RFFT(dfs_det_print2), 0}, + {"det_print3", RFFT_T, _OFFSET_RFFT(dfs_det_print3), _SIZE_RFFT(dfs_det_print3), 0}, + {"det_print4", RFFT_T, _OFFSET_RFFT(dfs_det_print4), _SIZE_RFFT(dfs_det_print4), 0}, + {"det_print_psd", RFFT_T, _OFFSET_RFFT(dfs_det_print_psd), _SIZE_RFFT(dfs_det_print_psd), 0}, + {"pulse_print", RFFT_T, _OFFSET_RFFT(dfs_pulse_print), _SIZE_RFFT(dfs_pulse_print), 0}, + {"hist_len", RFFT_T, _OFFSET_RFFT(dfs_det_hist_len), _SIZE_RFFT(dfs_det_hist_len), 5}, + {"sum_th", RFFT_T, _OFFSET_RFFT(dfs_det_sum_th), _SIZE_RFFT(dfs_det_sum_th), 2}, + {"flag_offset", RFFT_T, _OFFSET_RFFT(dfs_det_flag_offset), _SIZE_RFFT(dfs_det_flag_offset), 2}, + {"DPT_FA_TH_upper", RFFT_T, _OFFSET_RFFT(dfs_dpt_fa_th_upper), _SIZE_RFFT(dfs_dpt_fa_th_upper), 1000}, + {"DPT_FA_TH_lower", RFFT_T, _OFFSET_RFFT(dfs_dpt_fa_th_lower), _SIZE_RFFT(dfs_dpt_fa_th_lower), 80}, + {"DPT_Pulse_TH_mid", RFFT_T, _OFFSET_RFFT(dfs_dpt_pulse_th_mid), _SIZE_RFFT(dfs_dpt_pulse_th_mid), 3}, + {"DPT_Pulse_TH_lower", RFFT_T, _OFFSET_RFFT(dfs_dpt_pulse_th_lower), _SIZE_RFFT(dfs_dpt_pulse_th_lower), 1}, + {"DPT_ST_L2H_max", RFFT_T, _OFFSET_RFFT(dfs_dpt_st_l2h_max), _SIZE_RFFT(dfs_dpt_st_l2h_max), 0x4e}, + {"DPT_ST_L2H_min", RFFT_T, _OFFSET_RFFT(dfs_dpt_st_l2h_min), _SIZE_RFFT(dfs_dpt_st_l2h_min), 0x20}, + {"DPT_ST_L2H_add", RFFT_T, _OFFSET_RFFT(dfs_dpt_st_l2h_add), _SIZE_RFFT(dfs_dpt_st_l2h_add), 0}, + {"DPT_ST_L2H_idle_offset", RFFT_T, _OFFSET_RFFT(dfs_dpt_st_l2h_idle_offset), _SIZE_RFFT(dfs_dpt_st_l2h_idle_offset), 0}, + {"DPT_ini_gain_th", RFFT_T, _OFFSET_RFFT(dpt_ini_gain_th), _SIZE_RFFT(dpt_ini_gain_th), 0x30}, + {"pwdb_th", RFFT_T, _OFFSET_RFFT(dfs_pwdb_th), _SIZE_RFFT(dfs_pwdb_th), 0x08}, + {"pwdb_scalar_factor", RFFT_T, _OFFSET_RFFT(dfs_pwdb_scalar_factor), _SIZE_RFFT(dfs_pwdb_scalar_factor), 12}, + {"psd_pw_th", RFFT_T, _OFFSET_RFFT(dfs_psd_pw_th), _SIZE_RFFT(dfs_psd_pw_th), 65}, + {"dfs_psd_idle_on", RFFT_T, _OFFSET_RFFT(dfs_psd_idle_on), _SIZE_RFFT(dfs_psd_idle_on), 0}, + {"dfs_psd_TP_on", RFFT_T, _OFFSET_RFFT(dfs_psd_TP_on), _SIZE_RFFT(dfs_psd_TP_on), 0}, + {"psd_skip_lookup_table", RFFT_T, _OFFSET_RFFT(psd_skip_lookup_table), _SIZE_RFFT(psd_skip_lookup_table), 0}, + {"dfs_psd_delay", RFFT_T, _OFFSET_RFFT(dfs_psd_delay), _SIZE_RFFT(dfs_psd_delay), 30}, + {"psd_fir_decay", RFFT_T, _OFFSET_RFFT(dfs_psd_fir_decay), _SIZE_RFFT(dfs_psd_fir_decay), 23}, + {"skip_iqk", RFFT_T, _OFFSET_RFFT(dfs_skip_iqk), _SIZE_RFFT(dfs_skip_iqk), 0}, + {"scan_inband", RFFT_T, _OFFSET_RFFT(dfs_scan_inband), _SIZE_RFFT(dfs_scan_inband), 0}, + {"psd_op", RFFT_T, _OFFSET_RFFT(dfs_psd_op), _SIZE_RFFT(dfs_psd_op), 1}, + {"psd_tp_th", RFFT_T, _OFFSET_RFFT(dfs_psd_tp_th), _SIZE_RFFT(dfs_psd_tp_th), 2}, + {"pc0_th_idle_w53", RFFT_T, _OFFSET_RFFT(dfs_pc0_th_idle_w53), _SIZE_RFFT(dfs_pc0_th_idle_w53), 14}, + {"pc0_th_idle_w56", RFFT_T, _OFFSET_RFFT(dfs_pc0_th_idle_w56), _SIZE_RFFT(dfs_pc0_th_idle_w56), 6}, + {"max_sht_pusle_cnt_th",RFFT_T, _OFFSET_RFFT(dfs_max_sht_pusle_cnt_th), _SIZE_RFFT(dfs_max_sht_pusle_cnt_th), 5}, +#endif + +#ifdef SW_TX_QUEUE + {"swqh", RFFT_T, _OFFSET_RFFT(swq_en_highthd), _SIZE_RFFT(swq_en_highthd), 400}, + {"swql", RFFT_T, _OFFSET_RFFT(swq_dis_lowthd), _SIZE_RFFT(swq_dis_lowthd), 80}, + {"swqen", RFFT_T, _OFFSET_RFFT(swq_enable), _SIZE_RFFT(swq_enable), 1}, + {"swqdbg", RFFT_T, _OFFSET_RFFT(swq_dbg), _SIZE_RFFT(swq_dbg), 0}, + + {"swqaggnum", RFFT_T, _OFFSET_RFFT(swq_aggnum), _SIZE_RFFT(swq_aggnum), 8}, + + {"thd1", RFFT_T, _OFFSET_RFFT(timeout_thd), _SIZE_RFFT(timeout_thd), 60}, + {"thd2", RFFT_T, _OFFSET_RFFT(timeout_thd2), _SIZE_RFFT(timeout_thd2), 150}, + {"thd3", RFFT_T, _OFFSET_RFFT(timeout_thd3), _SIZE_RFFT(timeout_thd3), 300}, +#endif + +#ifdef A4_STA + {"a4_enable", RFFT_T, _OFFSET_RFFT(a4_enable), _SIZE_RFFT(a4_enable), 1}, +#endif + +#ifdef RTL8192D_INT_PA + {"use_intpa92d", RFFT_T, _OFFSET_RFFT(use_intpa92d), _SIZE_RFFT(use_intpa92d), 0}, +#endif +#ifdef CONFIG_WLAN_HAL_8881A + {"use_intpa8881A", RFFT_T, _OFFSET_RFFT(use_intpa8881A), _SIZE_RFFT(use_intpa8881A), 0}, +#endif + {"pwr_by_rate", RFFT_T, _OFFSET_RFFT(pwr_by_rate), _SIZE_RFFT(pwr_by_rate), 0}, +#ifdef _TRACKING_TABLE_FILE + {"pwr_track_file", RFFT_T, _OFFSET_RFFT(pwr_track_file), _SIZE_RFFT(pwr_track_file), 1}, +#endif +#ifdef CONFIG_SDIO_HCI + {"disable_pwr_by_rate", RFFT_T, _OFFSET_RFFT(disable_pwr_by_rate), _SIZE_RFFT(disable_pwr_by_rate), 1}, +#else + {"disable_pwr_by_rate", RFFT_T, _OFFSET_RFFT(disable_pwr_by_rate), _SIZE_RFFT(disable_pwr_by_rate), 0}, +#endif +#ifdef TXPWR_LMT +#ifdef CONFIG_SDIO_HCI + {"disable_txpwrlmt", RFFT_T, _OFFSET_RFFT(disable_txpwrlmt), _SIZE_RFFT(disable_txpwrlmt), 1}, +#else + {"disable_txpwrlmt", RFFT_T, _OFFSET_RFFT(disable_txpwrlmt), _SIZE_RFFT(disable_txpwrlmt), 0}, +#endif + {"disable_txpwrlmt2path", RFFT_T, _OFFSET_RFFT(disable_txpwrlmt2path), _SIZE_RFFT(disable_txpwrlmt2path), 0}, +#endif +#ifdef CONFIG_RTL_92D_DMDP + {"peerReinit", RFFT_T, _OFFSET_RFFT(peerReinit), _SIZE_RFFT(peerReinit), 0}, +#endif +#ifdef CONFIG_SDIO_TX_FILTER_BY_PRI + {"tx_filter_enable", RFFT_T, _OFFSET_RFFT(tx_filter_enable), _SIZE_RFFT(tx_filter_enable), 1}, +#endif +#ifdef WIFI_WMM + {"wifi_beq_iot", RFFT_T, _OFFSET_RFFT(wifi_beq_iot), _SIZE_RFFT(wifi_beq_iot), 0}, +#endif + {"bcast_to_dzq", RFFT_T, _OFFSET_RFFT(bcast_to_dzq), _SIZE_RFFT(bcast_to_dzq), 0}, +#ifdef TLN_STATS + {"stats_time_interval", RFFT_T, _OFFSET_RFFT(stats_time_interval), _SIZE_RFFT(stats_time_interval), 86400}, +#endif +#ifdef TX_EARLY_MODE + {"em_enable", RFFT_T, _OFFSET_RFFT(em_enable), _SIZE_RFFT(em_enable), 1}, +#endif +#ifdef CLIENT_MODE + {"sta_mode_ps", RFFT_T, _OFFSET_RFFT(sta_mode_ps), _SIZE_RFFT(sta_mode_ps), 0}, +#endif +#ifdef CONFIG_RTL_WLAN_DOS_FILTER + {"dos_block_time", RFFT_T, _OFFSET_RFFT(dos_block_time), _SIZE_RFFT(dos_block_time), 20}, +#endif + + {"intel_tp", RFFT_T, _OFFSET_RFFT(intel_rtylmt_tp_margin), _SIZE_RFFT(intel_rtylmt_tp_margin), 125*1024}, /* unit: byte */ + + {"enable_macid_sleep", RFFT_T, _OFFSET_RFFT(enable_macid_sleep), _SIZE_RFFT(enable_macid_sleep), 1}, +#ifdef CONFIG_RTL_88E_SUPPORT + {"disable_pkt_pause", RFFT_T, _OFFSET_RFFT(disable_pkt_pause), _SIZE_RFFT(disable_pkt_pause), 0}, + {"disable_pkt_nolink", RFFT_T, _OFFSET_RFFT(disable_pkt_nolink), _SIZE_RFFT(disable_pkt_nolink), 0}, + {"maxpktfail", RFFT_T, _OFFSET_RFFT(max_pkt_fail), _SIZE_RFFT(max_pkt_fail), 50}, + {"minpktfail", RFFT_T, _OFFSET_RFFT(min_pkt_fail), _SIZE_RFFT(min_pkt_fail), 30}, +#endif + {"low_tp_no_aggr", RFFT_T, _OFFSET_RFFT(low_tp_no_aggr), _SIZE_RFFT(low_tp_no_aggr), 0}, +#if defined(TX_EARLY_MODE) + {"em_que_num", RFFT_T, _OFFSET_RFFT(em_que_num), _SIZE_RFFT(em_que_num), 10}, + {"em_swq_thd_high", RFFT_T, _OFFSET_RFFT(em_swq_thd_high), _SIZE_RFFT(em_swq_thd_high), 70}, + {"em_swq_thd_low", RFFT_T, _OFFSET_RFFT(em_swq_thd_low), _SIZE_RFFT(em_swq_thd_low), 60}, +#endif +#ifdef CONFIG_TCP_ACK_TXAGG + {"tcpack_agg", RFFT_T, _OFFSET_RFFT(tcpack_agg), _SIZE_RFFT(tcpack_agg), 1}, +#ifdef CONFIG_TCP_ACK_MERGE + {"tcpack_merge", RFFT_T, _OFFSET_RFFT(tcpack_merge), _SIZE_RFFT(tcpack_merge), 0}, +#endif +#endif // CONFIG_TCP_ACK_TXAGG +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + {"low_traffic_xmit_thd", RFFT_T, _OFFSET_RFFT(low_traffic_xmit_thd), _SIZE_RFFT(low_traffic_xmit_thd), 20}, +#endif + {"low_retry_rssi_thd", RFFT_T, _OFFSET_RFFT(low_retry_rssi_thd), _SIZE_RFFT(low_retry_rssi_thd), 30}, + {"low_rate_low_retry", RFFT_T, _OFFSET_RFFT(low_rate_low_retry), _SIZE_RFFT(low_rate_low_retry), 1}, +#ifdef RSSI_MIN_ADV_SEL + {"rssi_min_advsel", RFFT_T, _OFFSET_RFFT(rssi_min_advsel), _SIZE_RFFT(rssi_min_advsel), 1}, +#endif +#ifdef BEAMFORMING_SUPPORT + {"sndperiod", RFFT_T, _OFFSET_RFFT(soundingPeriod), _SIZE_RFFT(soundingPeriod), 4000}, // 40ms + {"dumpcsi", RFFT_T, _OFFSET_RFFT(dumpcsi), _SIZE_RFFT(dumpcsi), 100}, // 100 + {"sndenable", RFFT_T, _OFFSET_RFFT(soundingEnable), _SIZE_RFFT(soundingEnable), 1}, // enable + {"ndparate", RFFT_T, _OFFSET_RFFT(ndparate), _SIZE_RFFT(ndparate), 0}, + {"ndpaaid", RFFT_T, _OFFSET_RFFT(ndpaaid), _SIZE_RFFT(ndpaaid), 0xff}, + {"applyVmatrix", RFFT_T, _OFFSET_RFFT(applyVmatrix), _SIZE_RFFT(applyVmatrix), 1}, + {"Nsnding3SS", RFFT_T, _OFFSET_RFFT(Nsnding3SS), _SIZE_RFFT(Nsnding3SS), 1}, +#endif + + +#ifdef DOT11H + {"tpc_enable", BYTE_T, _OFFSET(dot11hTPCEntry.tpc_enable), _SIZE(dot11hTPCEntry.tpc_enable), 1}, + {"tpc_tx_power", BYTE_T, _OFFSET(dot11hTPCEntry.tpc_tx_power), _SIZE(dot11hTPCEntry.tpc_tx_power), 12}, + {"tpc_link_margin", BYTE_T, _OFFSET(dot11hTPCEntry.tpc_link_margin), _SIZE(dot11hTPCEntry.tpc_link_margin), 0}, // set 0 for AP + {"lpwrc", RFFT_T, _OFFSET_RFFT(lpwrc), _SIZE_RFFT(lpwrc), 0}, + #if defined(CLIENT_MODE) || defined(CONFIG_RTK_MESH) + {"min_tx_power", BYTE_T, _OFFSET(dot11hTPCEntry.min_tx_power), _SIZE(dot11hTPCEntry.min_tx_power), 0},// for power capability ie + {"max_tx_power", BYTE_T, _OFFSET(dot11hTPCEntry.max_tx_power), _SIZE(dot11hTPCEntry.max_tx_power), 20},// for power capability ie + #endif +#endif + + {"no_rtscts", RFFT_T, _OFFSET_RFFT(no_rtscts), _SIZE_RFFT(no_rtscts), 0}, +#ifdef RTK_AC_SUPPORT +// operating mode notification + {"opm", RFFT_T, _OFFSET_RFFT(oper_mode_field), _SIZE_RFFT(oper_mode_field), 0x00}, + {"opmtest", RFFT_T, _OFFSET_RFFT(opmtest), _SIZE_RFFT(opmtest), 0x00}, +// channel switch + {"csa", RFFT_T, _OFFSET_RFFT(csa), _SIZE_RFFT(csa), 0x00}, + {"lgirate", RFFT_T, _OFFSET_RFFT(lgirate), _SIZE_RFFT(lgirate), 0xffff}, + + {"cca_rts", RFFT_T, _OFFSET_RFFT(cca_rts), _SIZE_RFFT(cca_rts), 0x00}, // 1: static, 2: dynamic +// Tx Power Diff + {"pwrdiff_20BW1S_OFDM1T_A", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_20BW1S_OFDM1T_A), _SIZE(dot11RFEntry.pwrdiff_20BW1S_OFDM1T_A), 0}, + {"pwrdiff_40BW2S_20BW2S_A", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_40BW2S_20BW2S_A), _SIZE(dot11RFEntry.pwrdiff_40BW2S_20BW2S_A), 0}, + {"pwrdiff_5G_20BW1S_OFDM1T_A", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_A), _SIZE(dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_A), 0}, + {"pwrdiff_5G_40BW2S_20BW2S_A", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_A), _SIZE(dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_A), 0}, + {"pwrdiff_5G_80BW1S_160BW1S_A", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_A), _SIZE(dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_A), 0}, + {"pwrdiff_5G_80BW2S_160BW2S_A", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_A), _SIZE(dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_A), 0}, + {"pwrdiff_20BW1S_OFDM1T_B", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_20BW1S_OFDM1T_B), _SIZE(dot11RFEntry.pwrdiff_20BW1S_OFDM1T_B), 0}, + {"pwrdiff_40BW2S_20BW2S_B", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_40BW2S_20BW2S_B), _SIZE(dot11RFEntry.pwrdiff_40BW2S_20BW2S_B), 0}, + {"pwrdiff_5G_20BW1S_OFDM1T_B", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_B), _SIZE(dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_B), 0}, + {"pwrdiff_5G_40BW2S_20BW2S_B", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_B), _SIZE(dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_B), 0}, + {"pwrdiff_5G_80BW1S_160BW1S_B", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_B), _SIZE(dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_B), 0}, + {"pwrdiff_5G_80BW2S_160BW2S_B", BYTE_ARRAY_T, _OFFSET(dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_B), _SIZE(dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_B), 0}, +#endif + {"txforce", RFFT_T, _OFFSET_RFFT(txforce), _SIZE_RFFT(txforce), 0xff}, + {"sgiforce", RFFT_T, _OFFSET_RFFT(sgiforce), _SIZE_RFFT(sgiforce), 2}, +#ifdef CONFIG_WLAN_HAL_8192EE + {"delay_8b4", RFFT_T, _OFFSET_RFFT(delay_8b4), _SIZE_RFFT(delay_8b4), 30}, + {"thrd_8b4", RFFT_T, _OFFSET_RFFT(thrd_8b4), _SIZE_RFFT(thrd_8b4), 0x16}, + {"loop_8b4", RFFT_T, _OFFSET_RFFT(loop_8b4), _SIZE_RFFT(loop_8b4), 50}, + {"disable_ACPR", RFFT_T, _OFFSET_RFFT(disable_ACPR), _SIZE_RFFT(disable_ACPR), 1}, + {"ldpc_92e", RFFT_T, _OFFSET_RFFT(ldpc_92e), _SIZE_RFFT(ldpc_92e), 0}, +#endif +#ifdef RTK_NL80211 + //mark_priv , for some parameter that not support in nl80211 + {"rtk_ac_enable", RFFT_T, _OFFSET_RFFT(rtk_uci_AcEnable), _SIZE_RFFT(rtk_uci_AcEnable), 0}, + // rtk_ac_enable = 0 or 1 + {"rtk_priv_bw", RFFT_T,_OFFSET_RFFT(rtk_uci_PrivBandwidth), _SIZE_RFFT(rtk_uci_PrivBandwidth), 0}, + // rtk_priv_bw = 5M , 10M ,80M ... +#endif +#ifdef AC2G_256QAM + {"ac2g_enable", RFFT_T, _OFFSET_RFFT(ac2g_enable), _SIZE_RFFT(ac2g_enable), 1}, + {"ac2g_phy_type", RFFT_T, _OFFSET_RFFT(ac2g_phy_type), _SIZE_RFFT(ac2g_phy_type), 0}, + {"ac2g_thd_ldpc", RFFT_T, _OFFSET_RFFT(ac2g_thd_ldpc), _SIZE_RFFT(ac2g_thd_ldpc), 35}, +#endif +#ifdef CHECK_HANGUP + {"check_hang", RFFT_T, _OFFSET_RFFT(check_hang), _SIZE_RFFT(check_hang), 0xff}, +#endif +#ifdef MCR_WIRELESS_EXTEND + {"mcr_ft", RFFT_T, _OFFSET_RFFT(mcr_ft), _SIZE_RFFT(mcr_ft), 1}, + {"disable_ldpc_thd", RFFT_T, _OFFSET_RFFT(disable_ldpc_thd), _SIZE_RFFT(disable_ldpc_thd), 60}, +#endif + {"auto_cipher", RFFT_T, _OFFSET_RFFT(auto_cipher), _SIZE_RFFT(auto_cipher), 0}, +// {"mp_dig_enable", RFFT_T, _OFFSET_RFFT(mp_dig_enable), _OFFSET_RFFT(mp_dig_enable), 0}, +#ifdef USE_OUT_SRC + {"odmrfpath", ODM_DM_1UT, _OFFSET_ODM_DM(RFPathRxEnable), _SIZE_ODM_DM(RFPathRxEnable), 0},// test for ODM DM (byte) + {"odmdebuglev", ODM_DM_4UT, _OFFSET_ODM_DM(DebugLevel), _SIZE_ODM_DM(DebugLevel), 0},// test for ODM DM (4byte) + {"odmdebugcom", ODM_DM_8UT, _OFFSET_ODM_DM(DebugComponents), _SIZE_ODM_DM(DebugComponents), 0},// test for ODM DM (long long) + {"TH_L2H_Ini", ODM_DM_1UT, _OFFSET_ODM_DM(TH_L2H_default), _SIZE_ODM_DM(TH_L2H_default), 0xf3},// for odm_Adaptivity() + {"TH_HL_Diff", ODM_DM_1UT, _OFFSET_ODM_DM(TH_EDCCA_HL_diff_default), _SIZE_ODM_DM(TH_EDCCA_HL_diff_default), 7},// for odm_Adaptivity() + {"TH_L2H_Ini_mode2", ODM_DM_1UT, _OFFSET_ODM_DM(TH_L2H_ini_mode2), _SIZE_ODM_DM(TH_L2H_ini_mode2), 20},// for odm_Adaptivity() + {"TH_HL_Diff_mode2", ODM_DM_1UT, _OFFSET_ODM_DM(TH_EDCCA_HL_diff_mode2), _SIZE_ODM_DM(TH_EDCCA_HL_diff_mode2), 8},// for odm_Adaptivity() + {"EDCCA_enable", ODM_DM_1UT, _OFFSET_ODM_DM(EDCCA_enable), _SIZE_ODM_DM(EDCCA_enable), 1},// for odm_Adaptivity() + {"DCbackoff", ODM_DM_1UT, _OFFSET_ODM_DM(DCbackoff), _SIZE_ODM_DM(DCbackoff), 2},// for odm_Adaptivity() + {"ada_IGI_upper", ODM_DM_1UT, _OFFSET_ODM_DM(Adaptivity_IGI_upper), _SIZE_ODM_DM(Adaptivity_IGI_upper), 0x0},// for odm_Adaptivity() + {"antdiv_rssi", ODM_DM_1UT, _OFFSET_ODM_DM(antdiv_rssi), _SIZE_ODM_DM(antdiv_rssi), 0},// for ODM_AntennaDiversity_92E() + {"antdiv_intvl", ODM_DM_1UT, _OFFSET_ODM_DM(antdiv_intvl), _SIZE_ODM_DM(antdiv_intvl), 0}, + {"fat_comb_a", ODM_DM_1UT, _OFFSET_ODM_DM(fat_comb_a), _SIZE_ODM_DM(fat_comb_a), 0}, + {"fat_comb_b", ODM_DM_1UT, _OFFSET_ODM_DM(fat_comb_b), _SIZE_ODM_DM(fat_comb_b), 0}, + {"antdiv_period", ODM_DM_1UT, _OFFSET_ODM_DM(antdiv_period), _SIZE_ODM_DM(antdiv_period), 0},// for ODM_AntennaDiversity() + {"antdiv_select", ODM_DM_1UT, _OFFSET_ODM_DM(antdiv_select), _SIZE_ODM_DM(antdiv_select), 0},// for ODM_AntennaDiversity() + {"bdc_holdstate", ODM_DM_1UT, _OFFSET_ODM_DM(bdc_holdstate), _SIZE_ODM_DM(bdc_holdstate), 0},// for BDC algorithm {"dm_dig_max_TH", ODM_DM_1UT, _OFFSET_ODM_DM(dm_dig_max_TH), _SIZE_ODM_DM(dm_dig_max_TH), 0}, {"dm_dig_min_TH", ODM_DM_1UT, _OFFSET_ODM_DM(dm_dig_min_TH), _SIZE_ODM_DM(dm_dig_min_TH), 0}, + {"dm_dig_max_TH", ODM_DM_1UT, _OFFSET_ODM_DM(dm_dig_max_TH), _SIZE_ODM_DM(dm_dig_max_TH), 0}, + {"dm_dig_min_TH", ODM_DM_1UT, _OFFSET_ODM_DM(dm_dig_min_TH), _SIZE_ODM_DM(dm_dig_min_TH), 0}, + {"Carrier_Sense_enable", ODM_DM_1UT, _OFFSET_ODM_DM(Carrier_Sense_enable), _SIZE_ODM_DM(Carrier_Sense_enable), 0},// for odm_Adaptivity() + {"print_agc", ODM_DM_1UT, _OFFSET_ODM_DM(print_agc), _SIZE_ODM_DM(print_agc), 0}, + {"antdiv_evm_en", ODM_DM_1UT, _OFFSET_ODM_DM(antdiv_evm_en), _SIZE_ODM_DM(antdiv_evm_en), 0}, +#endif +#ifdef CONFIG_WLAN_HAL_8881A + {"pwrtrk_TxAGC_enable", RFFT_T, _OFFSET_RFFT(pwrtrk_TxAGC_enable), _SIZE_RFFT(pwrtrk_TxAGC_enable), 1}, + {"pwrtrk_TxAGC", RFFT_T, _OFFSET_RFFT(pwrtrk_TxAGC), _SIZE_RFFT(pwrtrk_TxAGC), 0}, +#endif +#ifdef CONFIG_RTL_P2P_SUPPORT + {"p2p_type", INT_T, _OFFSET(p2p_mib.p2p_type), _SIZE(p2p_mib.p2p_type),0}, + {"p2p_state", INT_T, _OFFSET(p2p_mib.p2p_state), _SIZE(p2p_mib.p2p_state),0}, + {"p2p_on_discovery", INT_T, _OFFSET(p2p_mib.p2p_on_discovery), _SIZE(p2p_mib.p2p_type),0}, + {"p2p_intent", BYTE_T, _OFFSET(p2p_mib.p2p_intent), _SIZE(p2p_mib.p2p_intent),0}, + {"p2p_listen_channel",BYTE_T, _OFFSET(p2p_mib.p2p_listen_channel), _SIZE(p2p_mib.p2p_listen_channel),0}, + {"p2p_op_channel", BYTE_T, _OFFSET(p2p_mib.p2p_op_channel), _SIZE(p2p_mib.p2p_op_channel),0}, + {"p2p_event_indiate", BYTE_T, _OFFSET(p2p_mib.p2p_event_indiate), _SIZE(p2p_mib.p2p_event_indiate),0}, + {"p2p_device_name", STRING_T, _OFFSET(p2p_mib.p2p_device_name), _SIZE(p2p_mib.p2p_device_name),0}, + {"p2p_wsc_pin_code",STRING_T, _OFFSET(p2p_mib.p2p_wsc_pin_code), _SIZE(p2p_mib.p2p_wsc_pin_code),0}, + {"p2p_wsc_config_method",INT_T, _OFFSET(p2p_mib.p2p_wsc_config_method),_SIZE(p2p_mib.p2p_wsc_config_method),0}, +#endif + {"bcn_dont_ignore_edcca", RFFT_T, _OFFSET_RFFT(bcn_dont_ignore_edcca), _SIZE_RFFT(bcn_dont_ignore_edcca), 0}, +}; + +#ifdef _DEBUG_RTL8192CD_ +unsigned long rtl8192cd_debug_err=0xffffffff; +unsigned long rtl8192cd_debug_info=0; +unsigned long rtl8192cd_debug_trace=0; +unsigned long rtl8192cd_debug_warn=0; +#endif + +#ifdef HS2_DEBUGMSG +unsigned int _HS2_debug_info=0; /* info flag */ +unsigned int _HS2_debug_err=0; /* err flag */ +unsigned int _HS2_debug_trace=0; /* trace flag */ +unsigned int _HS2_debug_warn=0; /* warn flag */ +#endif + + +#ifdef __ECOS +static sta_info_2_web sta_info[NUM_STAT + 1]; +#endif + +void MDL_DEVINIT set_mib_default_tbl(struct rtl8192cd_priv *priv) +{ + int i; + int arg_num = sizeof(mib_table)/sizeof(struct iwpriv_arg); + + for (i=0; ipmib)+mib_table[i].offset) = (unsigned char)mib_table[i].Default; + else if (mib_table[i].type == INT_T) + memcpy(((unsigned char *)priv->pmib)+mib_table[i].offset, (unsigned char *)&mib_table[i].Default, sizeof(int)); +#if defined(CONFIG_RTK_MESH) + else if (mib_table[i].type == WORD_T) + memcpy(((unsigned char *)priv->pmib)+mib_table[i].offset, (unsigned char *)&mib_table[i].Default, sizeof(unsigned short)); +#endif //CONFIG_RTK_MESH + else if (mib_table[i].type == RFFT_T && mib_table[i].len == 1) + *(((unsigned char *)&(priv->pshare->rf_ft_var))+mib_table[i].offset) = (unsigned char)mib_table[i].Default; + else if (mib_table[i].type == RFFT_T && mib_table[i].len == 4) + memcpy(((unsigned char *)&(priv->pshare->rf_ft_var))+mib_table[i].offset, (unsigned char *)&mib_table[i].Default, sizeof(int)); +#ifdef USE_OUT_SRC + else if (mib_table[i].type == ODM_DM_1UT && mib_table[i].len == 1) + *(((unsigned char *)&(priv->pshare->_dmODM))+mib_table[i].offset) = (unsigned char)mib_table[i].Default; + else if ((mib_table[i].type == ODM_DM_4UT && mib_table[i].len == 4)) + memcpy(((unsigned char *)&(priv->pshare->_dmODM))+mib_table[i].offset, (unsigned char *)&mib_table[i].Default, sizeof(int)); +#endif + else { + // We only give default value of types of BYTE_T and INT_T here. + // Some others are gave in set_mib_default(). + } + } + } +} + + +int _convert_2_pwr_dot(char *s, int base) +{ + int k = 0, i=0; + int flag = 0; + char *data = s; + + k = 0; + + while(s[i] && (s[i] == ' ' || s[i] == '\t')) + i++; + data = &s[i]; + + if (base == 10) { + while ((*data >= '0') && (*data <= '9')) { + flag = 1; + k = 10 * k + (*data - '0'); + data++; + } + + k = k*2; + + if(*data == '.'){ + flag = 1; + data++; + + if(*data >= '5' && *data <= '9') + k++; + } + } + else + return 0; + + if (!flag) + return -1; + + return k; +} + + + +int _atoi(char *s, int base) +{ + int k = 0; + int sign = 1; + + k = 0; + if (base == 10) { + if(*s== '-') { + sign = -1; + s++; + } + while (*s != '\0' && *s >= '0' && *s <= '9') { + k = 10 * k + (*s - '0'); + s++; + } + k *= sign; + } + else { + while (*s != '\0') { + int v; + if ( *s >= '0' && *s <= '9') + v = *s - '0'; + else if ( *s >= 'a' && *s <= 'f') + v = *s - 'a' + 10; + else if ( *s >= 'A' && *s <= 'F') + v = *s - 'A' + 10; + else { + _DEBUG_ERR("error hex format!\n"); +#if 1//defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) //TXPWR_LMT_8812 TXPWR_LMT_88E + return k; +#else + return 0; +#endif + } + k = 16 * k + v; + s++; + } + } + return k; +} + +#ifdef USE_OUT_SRC +unsigned long long _atoi_u8(char *s, int base) +{ + unsigned long long k = 0; + int sign = 1; + k = 0; + if (base == 10) { + if(*s== '-') { + sign = -1; + s++; + } + while (*s != '\0' && *s >= '0' && *s <= '9') { + k = 10 * k + (*s - '0'); + s++; + } + k *= sign; + } + else { + while (*s != '\0') { + int v; + if ( *s >= '0' && *s <= '9') + v = *s - '0'; + else if ( *s >= 'a' && *s <= 'f') + v = *s - 'a' + 10; + else if ( *s >= 'A' && *s <= 'F') + v = *s - 'A' + 10; + else { + _DEBUG_ERR("error hex format!\n"); + return 0; + } + k = 16 * k + v; + s++; + } + } + return k; +} +#endif +static struct iwpriv_arg *get_tbl_entry(char *pstr) +{ + int i=0; + int arg_num = sizeof(mib_table)/sizeof(struct iwpriv_arg); + volatile char name[128]; + + while (*pstr && *pstr != '=') + name[i++] = *pstr++; + name[i] = '\0'; + + for (i=0; i 0) { + memcpy(tmpbuf, src, 2); + tmpbuf[2]='\0'; + *dst++ = (unsigned char)_atoi(tmpbuf, 16); + len-=2; + src+=2; + num++; + } + return num; +} + + +char *get_arg(char *src, char *val) +{ + int len=0; + + while (*src && *src!=',') { + *val++ = *src++; + len++; + } + if (len == 0) + return NULL; + + *val = '\0'; + + if (*src==',') + src++; + + return src; +} + + +#ifdef SUPPORT_MULTI_PROFILE +static int add_ap_profile(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char tmpbuf[100], *ptr; + struct ap_profile profile; + + if (priv->pmib->ap_profile.profile_num >= PROFILE_NUM) { + panic_printk("Can't add new one because profile table is full!\n"); + return -1; + } + + if (data == NULL) { + panic_printk("invalid ap_profile_add value [%s] !\n", data); + return -1; + } + ptr = get_arg((char *)data, tmpbuf); + if (ptr == NULL || strlen(tmpbuf) == 0) { + panic_printk("SSID must be set!\n"); + return -1; + } + strcpy(profile.ssid, tmpbuf); + + ptr = get_arg(ptr, tmpbuf); + if (ptr == NULL) { + panic_printk("encryption must be set!\n"); + return -1; + } + profile.encryption = _atoi(tmpbuf, 10); + if (profile.encryption > 4) { + panic_printk("Invalid encryption value!\n"); + return -1; + } + + ptr = get_arg(ptr, tmpbuf); + if (ptr == NULL) { + panic_printk("auth_type must be set!\n"); + return -1; + } + profile.auth_type = _atoi(tmpbuf, 10); + if (profile.auth_type == 0) + goto copy_profile; + + if (profile.encryption == 1 || profile.encryption == 2) { + ptr = get_arg(ptr, tmpbuf); + if (ptr == NULL) { + panic_printk("default wep tx key must be set!\n"); + return -1; + } + profile.wep_default_key = _atoi(tmpbuf, 10); + + ptr = get_arg(ptr, tmpbuf); + if (ptr == NULL) { + panic_printk("wep key1 must be set!\n"); + return -1; + } + if (profile.encryption == 1 && strlen(tmpbuf) != 10) { + panic_printk("Invalid wep64 key1 value!\n"); + return -1; + } + if (profile.encryption == 2 && strlen(tmpbuf) != 26) { + panic_printk("Invalid wep128 key1 value!\n"); + return -1; + } + get_array_val(profile.wep_key1, tmpbuf, strlen(tmpbuf)); + + ptr = get_arg(ptr, tmpbuf); + if (ptr == NULL) { + panic_printk("wep key2 must be set!\n"); + return -1; + } + if (profile.encryption == 1 && strlen(tmpbuf) != 10) { + panic_printk("Invalid wep64 key2 value!\n"); + return -1; + } + if (profile.encryption == 2 && strlen(tmpbuf) != 26) { + panic_printk("Invalid wep128 key2 value!\n"); + return -1; + } + get_array_val(profile.wep_key2, tmpbuf, strlen(tmpbuf)); + + ptr = get_arg(ptr, tmpbuf); + if (ptr == NULL) { + panic_printk("wep key3 must be set!\n"); + return -1; + } + if (profile.encryption == 1 && strlen(tmpbuf) != 10) { + panic_printk("Invalid wep64 key3 value!\n"); + return -1; + } + if (profile.encryption == 2 && strlen(tmpbuf) != 26) { + panic_printk("Invalid wep128 key3 value!\n"); + return -1; + } + get_array_val(profile.wep_key3, tmpbuf, strlen(tmpbuf)); + + ptr = get_arg(ptr, tmpbuf); + if (ptr == NULL) { + panic_printk("wep key4 must be set!\n"); + return -1; + } + if (profile.encryption == 1 && strlen(tmpbuf) != 10) { + panic_printk("Invalid wep64 key4 value!\n"); + return -1; + } + if (profile.encryption == 2 && strlen(tmpbuf) != 26) { + panic_printk("Invalid wep128 key4 value!\n"); + return -1; + } + get_array_val(profile.wep_key4, tmpbuf, strlen(tmpbuf)); + } + else { + ptr = get_arg(ptr, tmpbuf); + if (ptr == NULL) { + panic_printk("wpa cipher must be set!\n"); + return -1; + } + profile.wpa_cipher = _atoi(tmpbuf, 10); + + ptr = get_arg(ptr, tmpbuf); + if (ptr == NULL || strlen(tmpbuf) == 0 || strlen(tmpbuf) < 8 || strlen(tmpbuf) > 64) { + panic_printk("Invalid wpa psk!\n"); + return -1; + } + strcpy(profile.wpa_psk, tmpbuf); + +#ifdef CONFIG_IEEE80211W_CLI + if((priv->wpa_global_info->rsnie_cap & BIT(6)) && (priv->wpa_global_info->rsnie_cap & BIT(7))){ + PMFDEBUG("AP PMF capability = Required\n"); + profile.bss_PMF = MGMT_FRAME_PROTECTION_REQUIRED ; + } + else if(priv->wpa_global_info->rsnie_cap & BIT(7)){ + PMFDEBUG("AP PMF capability = MFPC\n"); + profile.bss_PMF = MGMT_FRAME_PROTECTION_OPTIONAL ; + } + else{ + PMFDEBUG("AP PMF capability = None\n"); + profile.bss_PMF = NO_MGMT_FRAME_PROTECTION ; + } +#endif + } + +copy_profile: + memset(&priv->pmib->ap_profile.profile[priv->pmib->ap_profile.profile_num], '\0', sizeof(profile)); + memcpy(&priv->pmib->ap_profile.profile[priv->pmib->ap_profile.profile_num], &profile, sizeof(profile)); + priv->pmib->ap_profile.profile_num++; + return 0; +} +#endif // SUPPORT_MULTI_PROFILE + +#if defined(SWITCH_CHAN) && defined(UNIVERSAL_REPEATER) +/* switch channel + * + * iwpriv wlan0 set_mib switch_chan=1,N //switch channel to N + * iwpriv wlan0 set_mib switch_chan=0 //switch channel back to root channel + */ +static int switch_chan(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char tmpbuf[100], *ptr; + int mode, chan, i; + + if (data == NULL) { + panic_printk("invalid switch_chan value [%s] !\n", data); + return -1; + } + if (!IS_ROOT_INTERFACE(priv)) { + panic_printk("Must issue command in root interface !\n"); + return -1; + } + if (!(OPMODE & WIFI_AP_STATE)) { + panic_printk("root interface must be AP !\n"); + return -1; + } + if (!IS_DRV_OPEN(GET_VXD_PRIV(priv))) { + panic_printk("vxd interface did not be started yet !\n"); + return -1; + } + ptr = get_arg((char *)data, tmpbuf); + if (ptr == NULL) { + panic_printk("argument error, mode must be set !\n"); + return -1; + } + mode =_atoi(tmpbuf, 10); + + if (mode) { // switch to vxd chan + if (!priv->pmib->dot11RFEntry.dot11channel) { + panic_printk("channel is not stable in root interface !\n"); + return -1; + } + ptr = get_arg((char *)ptr, tmpbuf); + if (ptr == NULL) { + panic_printk("argument error, channel number must be set !\n"); + return -1; + } + chan =_atoi(tmpbuf, 10); + for (i=0; iavailable_chnl_num; i++) { + if (chan == priv->available_chnl[i]) + break; + } + if (i == priv->available_chnl_num) { + panic_printk("invalid chan [%d] !\n", chan); + return -1; + } + + priv->chan_backup = priv->pmib->dot11RFEntry.dot11channel; + priv->bw_backup = priv->pshare->CurrentChannelBW; + priv->offset_backup = priv->pshare->offset_2nd_chan; + priv->func_backup = priv->pmib->miscEntry.func_off; + + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + priv->pshare->offset_2nd_chan = 0; + priv->pmib->dot11RFEntry.dot11channel = chan; + priv->pmib->miscEntry.func_off = 1; + } + else { + priv->pmib->dot11RFEntry.dot11channel = priv->chan_backup; + priv->pshare->CurrentChannelBW = priv->bw_backup; + priv->pshare->offset_2nd_chan = priv->offset_backup; + priv->pmib->miscEntry.func_off = priv->func_backup; + } + + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + PHY_IQCalibrate(priv); +#endif + + return 0; +} +#endif // SUPPORT_MULTI_PROFILE + + +#if (!defined(CONFIG_RTL_COMAPI_CFGFILE) && !defined(CONFIG_RTL_COMAPI_WLTOOLS) && !defined(INCLUDE_WPS)) +static +#endif +int set_mib(struct rtl8192cd_priv *priv, unsigned char *data) +{ + struct iwpriv_arg *entry; + int int_val, int_idx, len, *int_ptr; + int is_hex_type=0; + unsigned char byte_val; +#ifdef USE_OUT_SRC + unsigned short short_val; + unsigned long long longlong_val; +#endif + char *arg_val, tmpbuf[100]; +#ifdef CONFIG_RTK_MESH + unsigned short word; +#endif + DEBUG_TRACE; + + DEBUG_INFO("set_mib %s\n", data); + + entry = get_tbl_entry((char *)data); + if (entry == NULL) { + DEBUG_ERR("invalid mib name [%s] !\n", data); + return -1; + } + + // search value + arg_val = (char *)data; + while (*arg_val && *arg_val != '='){ + arg_val++; + } + + if (!*arg_val) { + DEBUG_ERR("mib value empty [%s] !\n", data); + return -1; + } + + + //printk("[%s %d] %c \n",__FUNCTION__,__LINE__ , *arg_val); + arg_val++; + + // skip space + while (*arg_val && *arg_val == 0x7f) + arg_val++; + + if(*arg_val=='0' && (*(arg_val+1)== 'x' || *(arg_val+1)== 'X')){ + is_hex_type=1; + arg_val+=2; + printk("[%s %d]hex format\n",__FUNCTION__,__LINE__); + } + + + switch (entry->type) { + case BYTE_T: + byte_val = (unsigned char)_atoi(arg_val, 10); + memcpy(((unsigned char *)priv->pmib)+entry->offset, &byte_val, 1); + break; +#ifdef CONFIG_RTK_MESH + case WORD_T: + word = (unsigned short)_atoi(arg_val, 10); + memcpy(((unsigned char *)priv->pmib)+entry->offset, &word, 2); + break; +#endif + case INT_T: + if(is_hex_type) + int_val = _atoi(arg_val, 16); + else + int_val = _atoi(arg_val, 10); + +#ifdef WIFI_SIMPLE_CONFIG + if (strcmp(entry->name, "wsc_enable") == 0) { + if (int_val == 4) { // disable hidden AP + if (HIDDEN_AP && priv->pbeacon_ssid) { + memcpy(priv->pbeacon_ssid+2, SSID, SSID_LEN); + priv->hidden_ap_mib_backup = HIDDEN_AP; + HIDDEN_AP = 0; + } + break; + } + if (int_val == 5) { // restore hidden AP + if (priv->pbeacon_ssid && !HIDDEN_AP && priv->hidden_ap_mib_backup) { + memset(priv->pbeacon_ssid+2, '\0', SSID_LEN); + HIDDEN_AP = priv->hidden_ap_mib_backup; + } + break; + } +#ifdef CLIENT_MODE + if ((priv->pmib->wscEntry.wsc_enable == 1) && (int_val == 0)) { + /*handle for WPS client mode fail or timeout*/ + + if (priv->recover_join_req) { + priv->recover_join_req = 0; + priv->pmib->wscEntry.wsc_enable = 0; + + memcpy(&priv->pmib->dot11Bss, &priv->dot11Bss_original, sizeof(struct bss_desc)); + + SSID_LEN = priv->orig_SSID_LEN ; + memset(SSID,'\0',sizeof(SSID)); + memcpy(SSID , priv->orig_SSID , SSID_LEN); + + SSID2SCAN_LEN = priv->orig_SSID_LEN; + memset(SSID2SCAN,'\0',sizeof(SSID2SCAN)); + memcpy(SSID2SCAN ,priv->orig_SSID , SSID2SCAN_LEN); + //memset(BSSID, 0, MACADDRLEN); + if (netif_running(priv->dev)) + { + SMP_UNLOCK(flags); + rtl8192cd_close(priv->dev); + rtl8192cd_open(priv->dev); + SMP_LOCK(flags); + } + break; + } + } + else if ((priv->pmib->wscEntry.wsc_enable == 6) && (int_val == 0)) { + /*handle for WPS client mode success;(don't do wlan driver close open)*/ + + priv->pmib->wscEntry.wsc_enable = 0; + + } + else if ((priv->pmib->wscEntry.wsc_enable == 0) && (int_val == 1)){ + /*before start of client WPS backup some info for later restroe*/ + + memcpy(&priv->dot11Bss_original, &priv->pmib->dot11Bss, sizeof(struct bss_desc)); + memset(priv->orig_SSID,'\0',sizeof(priv->orig_SSID)); + memcpy(priv->orig_SSID , SSID , SSID_LEN); + priv->orig_SSID_LEN = SSID_LEN; + /*fixed for IOT issue */ + if((OPMODE&(WIFI_STATION_STATE | WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)) + ==(WIFI_STATION_STATE | WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)) + { + /*if client mode is associated set recover_join_req; + then when wsc immediately be cancelled client will recover orig assoc*/ + priv->recover_join_req = 1; + + issue_disassoc(priv, BSSID, _RSON_DEAUTH_STA_LEAVING_); + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)); + } + + + + } + +#endif + } +#endif + + memcpy(((unsigned char *)priv->pmib)+entry->offset, (unsigned char *)&int_val, sizeof(int)); + +#ifdef CONFIG_POWER_SAVE + if (strcmp(entry->name, "ps_level") == 0) + { + if (int_val < 0 || int_val > 2) { + DEBUG_ERR("invalid INT_T mib index [%s, %d] !\n", entry->name, int_val); + return -1; + } + if (IS_ROOT_INTERFACE(priv)) { + if (int_val == 0) + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_USER); + else if (int_val == 2) + ap_offload_activate(priv, OFFLOAD_PROHIBIT_USER); + } + } + else if (!strcmp(entry->name, "ps_sleep_time")) + { + if (int_val < 0 || int_val > 100) { + DEBUG_ERR("invalid INT_T mib index [%s, %d] !\n", entry->name, int_val); + return -1; + } + if (IS_ROOT_INTERFACE(priv) && IS_DRV_OPEN(priv)) { + if ((RTW_STS_SUSPEND == priv->pshare->pwr_state) + || (priv->pshare->offload_function_ctrl > RTW_PM_PREPROCESS) + ) + { + ap_offload_exit(GET_ROOT(priv)); + rtw_lock_suspend_timeout(priv, 2000); + } + } + } +#endif + break; + + case SSID_STRING_T: + if (strlen(arg_val) > entry->len) + arg_val[entry->len] = '\0'; + memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID)); + memcpy(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, arg_val, strlen(arg_val)); + priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = strlen(arg_val); + if ((SSID_LEN == 3) && + ((SSID[0] == 'A') || (SSID[0] == 'a')) && + ((SSID[1] == 'N') || (SSID[1] == 'n')) && + ((SSID[2] == 'Y') || (SSID[2] == 'y'))) { + SSID2SCAN_LEN = 0; + memset(SSID2SCAN, 0, 32); + } + else { + SSID2SCAN_LEN = SSID_LEN; + memcpy(SSID2SCAN, SSID, SSID_LEN); + } + break; + + case BYTE_ARRAY_T: + len = strlen(arg_val); + if (len/2 > entry->len) { + DEBUG_ERR("invalid len of BYTE_ARRAY_T mib [%s] !\n", entry->name); + return -1; + } + if (len%2) { + DEBUG_ERR("invalid len of BYTE_ARRAY_T mib [%s] !\n", entry->name); + return -1; + } + get_array_val(((unsigned char *)priv->pmib)+entry->offset, arg_val, strlen(arg_val)); + break; + + case ACL_T: + case ACL_INT_T: + arg_val = get_arg(arg_val, tmpbuf); + if (arg_val == NULL) { + DEBUG_ERR("invalid ACL_T addr [%s] !\n", entry->name); + return -1; + } + if (entry->type == ACL_T && strlen(tmpbuf)!=12) { + DEBUG_ERR("invalid len of ACL_T mib [%s] !\n", entry->name); + return -1; + } + int_ptr = (int *)(((unsigned char *)priv->pmib)+entry->offset+entry->len); + int_idx = *int_ptr; + if (entry->type == ACL_T) { + if (int_idx < (entry->len/6)) + get_array_val(((unsigned char *)priv->pmib)+entry->offset+int_idx*6, tmpbuf, 12); + else { + DEBUG_ERR("reach the max capacity of ACL_T mib [%s] !\n", entry->name); + return -1; + } + } else { + if (int_idx < (entry->len/10)) { + get_array_val(((unsigned char *)priv->pmib)+entry->offset+int_idx*(6+4), tmpbuf, 12); + if (strlen(arg_val) > 0) { + int_val = _atoi(arg_val, 10); + memcpy(((unsigned char *)priv->pmib)+entry->offset+int_idx*(6+4)+6, &int_val, 4); + } + } else { + DEBUG_ERR("reach the max capacity of ACL_INT_T mib [%s] !\n", entry->name); + return -1; + } + } + *int_ptr = *int_ptr + 1; + break; + + case IDX_BYTE_ARRAY_T: + arg_val = get_arg(arg_val, tmpbuf); + if (arg_val == NULL) { + DEBUG_ERR("invalid BYTE_ARRAY mib [%s] !\n", entry->name); + return -1; + } + int_idx = _atoi(tmpbuf, 10); + if (int_idx+1 > entry->len) { + DEBUG_ERR("invalid BYTE_ARRAY mib index [%s, %d] !\n", entry->name, int_idx); + return -1; + } + arg_val = get_arg(arg_val, tmpbuf); + if (arg_val == NULL) { + DEBUG_ERR("invalid BYTE_ARRAY mib [%s] !\n", entry->name); + return -1; + } + byte_val = (unsigned char)_atoi(tmpbuf, 10); + memcpy(((unsigned char *)priv->pmib)+entry->offset+int_idx, (unsigned char *)&byte_val, sizeof(byte_val)); + break; + + case MULTI_BYTE_T: + int_idx=0; + while (1) { + arg_val = get_arg(arg_val, tmpbuf); + if (arg_val == NULL) + break; + if (int_idx+1 > entry->len) { + DEBUG_ERR("invalid MULTI_BYTE_T mib index [%s, %d] !\n", entry->name, int_idx); + return -1; + } + byte_val = (unsigned char)_atoi(tmpbuf, 16); + memcpy(((unsigned char *)priv->pmib)+entry->offset+int_idx++, (unsigned char *)&byte_val, sizeof(byte_val)); + } + // copy length to next parameter + memcpy( ((unsigned char *)priv->pmib)+entry->offset+entry->len, (unsigned char *)&int_idx, sizeof(int)); + break; + +#ifdef _DEBUG_RTL8192CD_ + case DEBUG_T: + int_val = _atoi(arg_val, 16); + if (entry->offset==1) + rtl8192cd_debug_err = int_val; + else if (entry->offset==2) + rtl8192cd_debug_info = int_val; + else if (entry->offset==3) + rtl8192cd_debug_trace = int_val; + else if (entry->offset==4) + rtl8192cd_debug_warn = int_val; + else { + DEBUG_ERR("invalid debug index\n"); + } + break; +#endif // _DEBUG_RTL8192CD_ + + case DEF_SSID_STRING_T: + if (strlen(arg_val) > entry->len) + arg_val[entry->len] = '\0'; + memset(priv->pmib->dot11StationConfigEntry.dot11DefaultSSID, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11DefaultSSID)); + memcpy(priv->pmib->dot11StationConfigEntry.dot11DefaultSSID, arg_val, strlen(arg_val)); + priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen = strlen(arg_val); + break; +#ifdef CONFIG_RTL_COMAPI_CFGFILE + case SSID2SCAN_STRING_T: + if (strlen(arg_val) > entry->len) + arg_val[entry->len] = '\0'; + memset(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan)); + memcpy(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan, arg_val, strlen(arg_val)); + priv->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen = strlen(arg_val); + break; +#endif + + case STRING_T: + if (strlen(arg_val) >= entry->len) + arg_val[entry->len-1] = '\0'; + strcpy((char *)(((unsigned char *)priv->pmib)+entry->offset), arg_val); + break; + + case RFFT_T: + if (entry->len == 1) { + byte_val = _atoi(arg_val, 10); + memcpy(((unsigned char *)&priv->pshare->rf_ft_var)+entry->offset, (unsigned char *)&byte_val, entry->len); +#ifdef DFS + if ((strcmp(entry->name, "dfsdbgmode") == 0) && (byte_val)) { + if (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) { + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, 0x90c, bMaskDWord, 0x83321333); + PHY_SetBBReg(priv, 0xe10, bMaskDWord, 0x30303030); + PHY_SetBBReg(priv, 0x83c, bMaskDWord, 0x30303030); + } + else if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A)) + PHY_SetBBReg(priv, 0x80c, BIT(28), 1); + } + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PHY_SetBBReg(priv, 0xc7c, BIT(28), 0); // ynlin dbg + PHY_SetBBReg(priv, 0xcdc, BIT(8)|BIT(9), 1); + } + } + else if ((strcmp(entry->name, "det_reset") == 0) && (byte_val)) { + priv->pmib->dot11DFSEntry.DFS_detected = 0; + priv->FA_count_pre = 0; + priv->VHT_CRC_ok_cnt_pre = 0; + priv->HT_CRC_ok_cnt_pre = 0; + priv->LEG_CRC_ok_cnt_pre = 0; + priv->mask_idx = 0; + priv->mask_hist_checked = 0; + memset(priv->radar_det_mask_hist, 0, sizeof(priv->radar_det_mask_hist)); + memset(priv->pulse_flag_hist, 0, sizeof(priv->pulse_flag_hist)); + } +#endif + } else if (entry->len == 4) { + int_val = _atoi(arg_val, 10); + memcpy(((unsigned char *)&priv->pshare->rf_ft_var)+entry->offset, (unsigned char *)&int_val, entry->len); + } +#ifdef RTK_NL80211//mark_priv + else + { + if (strlen(arg_val) > entry->len) + arg_val[entry->len] = '\0'; + strcpy(((char *)&priv->pshare->rf_ft_var)+entry->offset ,arg_val); + } +#endif + break; + + case RFFT_ACL_T: + arg_val = get_arg(arg_val, tmpbuf); + if (arg_val == NULL) { + DEBUG_ERR("invalid RFFT_ACL_T addr [%s] !\n", entry->name); + return -1; + } + if (strlen(tmpbuf)!=12) { + DEBUG_ERR("invalid len of RFFT_ACL_T mib [%s] !\n", entry->name); + return -1; + } + + int_ptr = (int *)(((unsigned char *)&priv->pshare->rf_ft_var)+entry->offset+entry->len); + int_idx = *int_ptr; + get_array_val(((unsigned char *)&priv->pshare->rf_ft_var)+entry->offset+int_idx*6, tmpbuf, 12); + *int_ptr = *int_ptr + 1; + break; + + case VARLEN_BYTE_T: + len = strlen(arg_val); + if (len/2 > entry->len) { + DEBUG_ERR("invalid len of VARLEN_BYTE_T mib [%s] !\n", entry->name); + return -1; + } + if (len%2) { + DEBUG_ERR("invalid len of VARLEN_BYTE_T mib [%s] !\n", entry->name); + return -1; + } + memset(((unsigned char *)priv->pmib)+entry->offset, 0, entry->len); + len = get_array_val(((unsigned char *)priv->pmib)+entry->offset, arg_val, strlen(arg_val)); + *(unsigned int *)(((unsigned char *)priv->pmib)+entry->offset+entry->len) = len; + break; + +#ifdef WIFI_SIMPLE_CONFIG + case PIN_IND_T: + if (strlen(arg_val) > entry->len) { + +#ifdef INCLUDE_WPS + //include-wps case + //upnp will direct function call to wps_pin(arg_val); + //printk("set_mib:PIN=%s\n",arg_val); + wps_pin(arg_val); +#else + DOT11_WSC_PIN_IND wsc_ind; + + wsc_ind.EventId = DOT11_EVENT_WSC_PIN_IND; + wsc_ind.IsMoreEvent = 0; + strcpy((char *)wsc_ind.code, arg_val); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, -1); +#endif + } + break; +/* WPS2DOTX */ + /* support Assigned MAC Addr,Assigned SSID,dymanic change STA's PIN code, 2011-0505 */ + case WSC_SELF_PIN_IND_T: + if (strlen(arg_val) > entry->len) { + DOT11_WSC_PIN_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_SET_MY_PIN; + wsc_ind.IsMoreEvent = 0; + strcpy((char *)wsc_ind.code, arg_val); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, -1); + } + break; + case WSC_SEPC_SSID_CONN_IND_T: + if (strlen(arg_val) > entry->len) { + DOT11_WSC_PIN_IND wsc_ind; + + wsc_ind.EventId = DOT11_EVENT_WSC_SPEC_SSID; + wsc_ind.IsMoreEvent = 0; + strcpy((char *)wsc_ind.code, arg_val); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, -1); + } + break; + case WSC_SEPC_MAC_CONN_IND_T: + if (strlen(arg_val) > entry->len) { + DOT11_WSC_PIN_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_SPEC_MAC_IND; + wsc_ind.IsMoreEvent = 0; + strcpy((char *)wsc_ind.code, arg_val); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, -1); + } + break; + /* support Assigned MAC Addr,Assigned SSID,dymanic change STA's PIN code, 2011-0505 */ +/* WPS2DOTX */ +#ifdef INCLUDE_WPS +#ifndef CONFIG_MSC + case WSC_IND_T: + /*event notify user space upnp ,call by wps "*/ + if (strcmp(entry->name, "wps_get_config") == 0) { + printk("sme rx wps_get_config cmd\n"); + DOT11_WSC_PIN_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_GETCONF_IND; + wsc_ind.IsMoreEvent = 0; + strcpy(wsc_ind.code,arg_val); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, -1); + } + else if (strcmp(entry->name, "wsc_soap_action") == 0) { + DOT11_WSC_SOAP soap; + struct iw_point wrq; + + wrq.pointer = (caddr_t)&soap; + wrq.length = sizeof(DOT11_WSC_SOAP); + + soap.EventId = DOT11_EVENT_WSC_SOAP; + soap.IsMoreEvent = FALSE; + strcpy(soap.action, arg_val); + printk("ioctl soap name:%s\n",arg_val); + //rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); + } + + else if (strcmp(entry->name, "wsc_event_callback") == 0) { + DOT11_WSC_PIN_IND wsc_ind; + + wsc_ind.EventId = DOT11_EVENT_WSC_GETCONF_IND; + wsc_ind.IsMoreEvent = 0; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, -1); + + } + else if (strcmp(entry->name, "wps_led_control") == 0) { /*event to upnp*/ + + DOT11_WPS_LEDCRTL wsc_ind; + short flag = 0; + + wsc_ind.EventId = DOT11_EVENT_WSC_LEDCONTROL_IND; + + if(strcmp("WSC_START",arg_val) == 0) + flag = -1; + else if(strcmp("WSC_END",arg_val) == 0) + flag = -2; + else if(strcmp("PBC_OVERLAPPED",arg_val) == 0) + flag = -3; + else if(strcmp("WSC_ERROR",arg_val) == 0) + flag = -4; + else if(strcmp("WSC_SUCCESS",arg_val) == 0) + flag = -5; + else if(strcmp("WSC_NOP",arg_val) == 0) + flag = -6; + else + flag = -7; + + wsc_ind.flag = flag; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WPS_LEDCRTL)); + event_indicate(priv, NULL, -1); + + } + else if (strcmp(entry->name, "wps_debug") == 0) { /*event to wps*/ + priv->pshare->WSC_CONT_S.debug = _atoi(arg_val,10); + } + else if (strcmp(entry->name, "wps_reinit") == 0) { /*event to wps*/ + printk("WPS module reinit from set_mib\n"); + priv->pshare->WSC_CONT_S.wait_reinit = 1 ; + wps_init(priv); + } + break; + + // from wps call event to user space upnp + case FLASH_RESTORE_T: + if (strlen(arg_val) > entry->len) { + DOT11_WSC_RESTORE2FLASH_IND restore2flash; + memset(&restore2flash , 0 ,sizeof(struct _DOT11_WSC_RESTORE2FLASH_IND)); + restore2flash.EventId = DOT11_EVENT_WSC_PUTCONF_IND; + + strcpy(restore2flash.flashcmd[0], arg_val); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&restore2flash, + sizeof(DOT11_WSC_RESTORE2FLASH_IND)); + event_indicate(priv, NULL, -1); + } + break; + +#endif // end of CONFIG_MSC +#endif // end of INCLUDE_WPS +#ifdef CONFIG_RTL_COMAPI_CFGFILE + case WSC_START_IND_T: + if( strlen(arg_val) > 0 ) { + DOT11_WSC_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_START_IND; + wsc_ind.IsMoreEvent = 0; + //wsc_ind.value = arg_val; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_IND)); + event_indicate(priv, NULL, -1); + } + break; + //EV_MODE, EV_STATUS, EV_MEHOD, EV_STEP, EV_OOB + case WSC_MODE_IND_T: + if( strlen(arg_val) > 0 ) { + DOT11_WSC_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_MODE_IND; + wsc_ind.IsMoreEvent = 0; + wsc_ind.value = _atoi(arg_val,10); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_IND)); + event_indicate(priv, NULL, -1); + } + break; + case WSC_STATUS_IND_T: + if( strlen(arg_val) > 0 ) { + DOT11_WSC_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_STATUS_IND; + wsc_ind.IsMoreEvent = 0; + wsc_ind.value = _atoi(arg_val,10); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_IND)); + event_indicate(priv, NULL, -1); + } + break; + case WSC_METHOD_IND_T: + if( strlen(arg_val) > 0 ) { + DOT11_WSC_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_METHOD_IND; + wsc_ind.IsMoreEvent = 0; + wsc_ind.value = _atoi(arg_val,10); + if( wsc_ind.value > 3 || wsc_ind.value ==0 ) + wsc_ind.value = 1; //default set to pin method + printk("iwpriv set method = %d\n",wsc_ind.value); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_IND)); + event_indicate(priv, NULL, -1); + } + break; + case WSC_STEP_IND_T: + if( strlen(arg_val) > 0 ) { + DOT11_WSC_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_STEP_IND; + wsc_ind.IsMoreEvent = 0; + //wsc_ind.value = arg_val; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_IND)); + event_indicate(priv, NULL, -1); + } + break; + case WSC_OOB_IND_T: + if( strlen(arg_val) > 0 ) { + DOT11_WSC_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_OOB_IND; + wsc_ind.IsMoreEvent = 0; + //wsc_ind.value = arg_val; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_IND)); + event_indicate(priv, NULL, -1); + } + break; +#endif //ifdef CONFIG_RTL_COMAPI_CFGFILE +#endif + +#ifdef CONFIG_RTL_WAPI_SUPPORT + case INT_ARRAY_T: + int_idx=0; + while (1) { + arg_val = get_arg(arg_val, tmpbuf); + if (arg_val == NULL) + break; + if (int_idx+1 > (entry->len)/sizeof(int)) { + DEBUG_ERR("invalid MULTI_BYTE_T mib index [%s, %d] !\n", entry->name, int_idx); + return -1; + } + int_val = _atoi(tmpbuf, 16); + memcpy(((unsigned char *)priv->pmib)+entry->offset+int_idx++, (void *)&int_val, sizeof(int_val)); + } + break; + case WAPI_KEY_T: + { + char tmppasswd[100]={0}; + wapiMibPSK *wapipsk=NULL; + int_idx=0; + + /*Get Password*/ + arg_val = get_arg(arg_val, tmpbuf); + if (arg_val == NULL) + break; + memcpy(tmppasswd, tmpbuf, strlen(tmpbuf)); + + /*Get Password length*/ + arg_val=get_arg(arg_val, tmpbuf); + int_val = _atoi(tmpbuf, 16); + + wapipsk=(wapiMibPSK *)((unsigned char *)(priv->pmib)+entry->offset); + + /*Hex or passthru*/ + if((0==(strlen(tmppasswd) % 2)) && (int_val < strlen(tmppasswd)) && + (int_val == (strlen(tmppasswd)/2))) + { + /*Hex mode*/ + rtl_string_to_hex(tmppasswd,wapipsk->octet,strlen(tmppasswd)); + } + else + { + strncpy(wapipsk->octet,tmppasswd,strlen(tmppasswd)); + } + wapipsk->len = int_val; + break; + } +#endif + +#ifdef SUPPORT_MULTI_PROFILE + case AP_PROFILE_T: + add_ap_profile(priv, arg_val); + break; +#endif + +#if defined(SWITCH_CHAN) && defined(UNIVERSAL_REPEATER) + case SWITCH_CHAN_T: + switch_chan(priv, arg_val); + break; +#endif + +#ifdef USE_OUT_SRC + case ODM_DM_1UT: + byte_val = _atoi(arg_val, 16); + memcpy(((unsigned char *)&priv->pshare->_dmODM)+entry->offset, (unsigned char *)&byte_val, entry->len); + ODEBUG("set odm,val=0x%x\n",byte_val); + break; + case ODM_DM_2UT: + short_val = _atoi(arg_val, 16); + memcpy(((unsigned char *)&priv->pshare->_dmODM)+entry->offset, (unsigned char *)&short_val, entry->len); + ODEBUG("set odm,val=0x%02x\n",short_val); + break; + case ODM_DM_4UT: + int_val = _atoi(arg_val, 16); + memcpy(((unsigned char *)&priv->pshare->_dmODM)+entry->offset, (unsigned char *)&int_val, entry->len); + ODEBUG("set odm,val=0x%04x\n",int_val); + break; + case ODM_DM_8UT: + longlong_val = _atoi_u8(arg_val, 16); + memcpy(((unsigned char *)&priv->pshare->_dmODM)+entry->offset, (unsigned char *)&longlong_val, entry->len); + ODEBUG("set odm, val=0x%llx\n",longlong_val); + break; +#endif + default: + DEBUG_ERR("invalid mib type!\n"); + break; + } + + return 0; +} +#ifndef INCLUDE_WPS +static +#endif +int get_mib(struct rtl8192cd_priv *priv, unsigned char *data) +{ + struct iwpriv_arg *entry; + int i, len, *int_ptr, copy_len; + char tmpbuf[40]; + + DEBUG_TRACE; + + DEBUG_INFO("get_mib %s\n", data); + + entry = get_tbl_entry((char *)data); + if (entry == NULL) { + DEBUG_ERR("invalid mib name [%s] !\n", data); + return -1; + } + copy_len = entry->len; + + switch (entry->type) { + case BYTE_T: + memcpy(data, ((unsigned char *)priv->pmib)+entry->offset, 1); + PRINT_INFO("byte data: %d\n", *data); + break; +#ifdef CONFIG_RTK_MESH + case WORD_T: + memcpy(data, ((unsigned char *)priv->pmib)+entry->offset, 2); + PRINT_INFO("word data: %d\n", *data); + break; +#endif + case INT_T: + memcpy(data, ((unsigned char *)priv->pmib)+entry->offset, sizeof(int)); + PRINT_INFO("int data: %d\n", *((int *)data)); + break; + + case SSID_STRING_T: + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen); + tmpbuf[priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen] = '\0'; + strcpy((char *)data, tmpbuf); + PRINT_INFO("ssid: %s\n", tmpbuf); + break; + + case BYTE_ARRAY_T: + memcpy(data, ((unsigned char *)priv->pmib)+entry->offset, entry->len); + PRINT_INFO("data (hex): "); + for (i=0; ilen; i++) + PRINT_INFO("%02x", *((unsigned char *)((unsigned char *)priv->pmib)+entry->offset+i)); + PRINT_INFO("\n"); + break; + + case ACL_T: + int_ptr = (int *)(((unsigned char *)priv->pmib)+entry->offset+entry->len); + PRINT_INFO("ACL table (%d):\n", *int_ptr); + copy_len = 0; + for (i=0; i<*int_ptr; i++) { + memcpy(data, ((unsigned char *)priv->pmib)+entry->offset+i*6, 6); + PRINT_INFO("mac-addr: %02x-%02x-%02x-%02x-%02x-%02x\n", + data[0],data[1],data[2],data[3],data[4],data[5]); + data += 6; + copy_len += 6; + } + DEBUG_INFO("\n"); + break; + + case IDX_BYTE_ARRAY_T: + memcpy(data, ((unsigned char *)priv->pmib)+entry->offset, entry->len); + PRINT_INFO("data (dec): "); + for (i=0; ilen; i++) + PRINT_INFO("%d ", *((unsigned char *)((unsigned char *)priv->pmib)+entry->offset+i)); + PRINT_INFO("\n"); + break; + + case MULTI_BYTE_T: + memcpy(&len, ((unsigned char *)priv->pmib)+entry->offset+entry->len, sizeof(int)); + memcpy(data, ((unsigned char *)priv->pmib)+entry->offset, len); + PRINT_INFO("data (hex): "); + for (i=0; ipmib)+entry->offset+i)); + PRINT_INFO("\n"); + break; + +#ifdef _DEBUG_RTL8192CD_ + case DEBUG_T: + if (entry->offset==1) + memcpy(data, (unsigned char *)&rtl8192cd_debug_err, sizeof(rtl8192cd_debug_err)); + else if (entry->offset==2) + memcpy(data, (unsigned char *)&rtl8192cd_debug_info, sizeof(rtl8192cd_debug_info)); + else if (entry->offset==3) + memcpy(data, (unsigned char *)&rtl8192cd_debug_trace, sizeof(rtl8192cd_debug_trace)); + else if (entry->offset==4) + memcpy(data, (unsigned char *)&rtl8192cd_debug_warn, sizeof(rtl8192cd_debug_warn)); + else { + DEBUG_ERR("invalid debug index\n"); + } + PRINT_INFO("debug flag(hex): %08lx\n", *((unsigned long *)data)); + break; +#endif // _DEBUG_RTL8192CD_ + + case DEF_SSID_STRING_T: + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.dot11DefaultSSID, priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen); + tmpbuf[priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen] = '\0'; + strcpy((char *)data, tmpbuf); + PRINT_INFO("defssid: %s\n", tmpbuf); + break; + + case STRING_T: + strcpy((char *)data, (char *)(((unsigned char *)priv->pmib)+entry->offset)); + PRINT_INFO("string data: %s\n", data); + break; + + case RFFT_T: + memcpy(data, ((unsigned char *)&priv->pshare->rf_ft_var)+entry->offset, sizeof(int)); + PRINT_INFO("int data: %d\n", *((int *)data)); + break; + case RFFT_ACL_T: + int_ptr = (int *)(((unsigned char *)&priv->pshare->rf_ft_var)+entry->offset+entry->len); + copy_len = 0; + for (i=0; i<*int_ptr; i++) + { + memcpy(data, ((unsigned char *)&priv->pshare->rf_ft_var)+entry->offset+i*6, 6); + PRINT_INFO("mac-addr: %02x-%02x-%02x-%02x-%02x-%02x\n", + data[0],data[1],data[2],data[3],data[4],data[5]); + data += 6; + copy_len += 6; + } + DEBUG_INFO("\n"); + break; + + case VARLEN_BYTE_T: + copy_len = *(unsigned int *)(((unsigned char *)priv->pmib)+entry->offset+entry->len); + memcpy(data, ((unsigned char *)priv->pmib)+entry->offset, copy_len); + PRINT_INFO("data (hex): "); + for (i=0; ipmib)+entry->offset+i)); + PRINT_INFO("\n"); + break; + +#ifdef USE_OUT_SRC + case ODM_DM_1UT: + memcpy(data, ((unsigned char *)&priv->pshare->_dmODM)+entry->offset, sizeof(unsigned char)); + ODEBUG("odm byte val=0x:%x\n", *((unsigned char *)data)); + break; + case ODM_DM_2UT: + memcpy(data, ((unsigned char *)&priv->pshare->_dmODM)+entry->offset, sizeof(unsigned short)); + ODEBUG("odm short val=0x:%02x\n", *((unsigned short *)data)); + break; + case ODM_DM_4UT: + memcpy(data, ((unsigned char *)&priv->pshare->_dmODM)+entry->offset, sizeof(unsigned int)); + ODEBUG("odm long val=0x:%04x\n", *((int *)data)); + break; + case ODM_DM_8UT: + memcpy(data, ((unsigned char *)&priv->pshare->_dmODM)+entry->offset, sizeof(unsigned long long)); + ODEBUG("odm long long val=0x:%llx\n", *((unsigned long long *)data)); + break; +#endif + default: + DEBUG_ERR("invalid mib type!\n"); + return 0; + } + + return copy_len; +} + + +#ifdef _IOCTL_DEBUG_CMD_ +/* + * Write register, command: "iwpriv wlanX write_reg,type,offset,value" + * where: type may be: "b" - byte, "w" - word, "dw" - "dw" (based on wlan register offset) + * "_b" - byte, "_w" - word, "_dw" - "dw" (based on register offset 0) + * offset and value should be input in hex + */ +static int write_reg(struct rtl8192cd_priv *priv, unsigned char *data) +{ + volatile char name[100]; + int i=0, op=0, offset; + unsigned long ioaddr, val; +#ifdef CONFIG_SDIO_HCI + int type = 0; +#endif + + DEBUG_TRACE; + + // get access type + while (*data && *data != ',') + name[i++] = *data++; + name[i] = '\0'; + +#ifdef CONFIG_SDIO_HCI + if (!strcmp((char *)name, "sdio")) { + data++; + i = 0; + while (*data && *data != ',') + name[i++] = *data++; + name[i] = '\0'; + type= 1; + } +#endif + + if (!strcmp((char *)name, "b")) + op = 1; + else if (!strcmp((char *)name, "w")) + op = 2; + else if (!strcmp((char *)name, "dw")) + op = 3; + else if (!strcmp((char *)name, "_b")) + op = 0x81; + else if (!strcmp((char *)name, "_w")) + op = 0x82; + else if (!strcmp((char *)name, "_dw")) + op = 0x83; + + if (op == 0 || !*data++) { + DEBUG_ERR("invalid type!\n"); + return -1; + } + + if ( !(op&0x80)) // wlan register + ioaddr = priv->pshare->ioaddr; + else + ioaddr = 0; + + // get offset and value + i=0; + while (*data && *data != ',') + name[i++] = *data++; + name[i] = '\0'; + if (!*data++) { + DEBUG_ERR("invalid offset!\n"); + return -1; + } + offset = _atoi((char *)name, 16); + val = (unsigned long)_atoi((char *)data, 16); + + DEBUG_INFO("write reg in %s: addr=%08x, val=0x%x\n", + (op == 1 ? "byte" : (op == 2 ? "word" : "dword")), + offset, (int)val); + + switch (op&0x7f) { + case 1: +#ifdef CONFIG_SDIO_HCI + if (type) { + unsigned char b_val = (unsigned char)val; + sdio_local_write(priv, offset, 1, &b_val); + } else +#endif + RTL_W8(offset, ((unsigned char)val)); + break; + case 2: +#ifdef CONFIG_SDIO_HCI + if (type) { + unsigned short w_val = (unsigned short)val; + w_val = cpu_to_le16(w_val); + sdio_local_write(priv, offset, 2, (u8*)&w_val); + } else +#endif + RTL_W16(offset, ((unsigned short)val)); + break; + case 3: +#ifdef CONFIG_SDIO_HCI + if (type) { + val = cpu_to_le32(val); + sdio_local_write(priv, offset, 4, (u8*)&val); + } else +#endif + RTL_W32(offset, ((unsigned long)val)); + break; + } + return 0; +} + + +/* + * Read register, command: "iwpriv wlanX read_reg,type,offset" + * where: type may be: "b" - byte, "w" - word, "dw" - "dw" (based on wlan register offset) + * "_b" - byte, "_w" - word, "_dw" - "dw" (based on register offset 0) + * offset should be input in hex + */ +static int read_reg(struct rtl8192cd_priv *priv, unsigned char *data) +{ + volatile char name[100]; + int i=0, op=0, offset, len=0; + unsigned long ioaddr, dw_val; + unsigned char *org_ptr=data, b_val; + unsigned short w_val; +#ifdef CONFIG_SDIO_HCI + int type = 0; +#endif + + DEBUG_TRACE; + + // get access type + while (*data && *data != ',') + name[i++] = *data++; + name[i] = '\0'; + +#ifdef CONFIG_SDIO_HCI + if (!strcmp((char *)name, "sdio")) { + data++; + i = 0; + while (*data && *data != ',') + name[i++] = *data++; + name[i] = '\0'; + type= 1; + } +#endif + + if (!strcmp((char *)name, "b")) + op = 1; + else if (!strcmp((char *)name, "w")) + op = 2; + else if (!strcmp((char *)name, "dw")) + op = 3; + else if (!strcmp((char *)name, "_b")) + op = 0x81; + else if (!strcmp((char *)name, "_w")) + op = 0x82; + else if (!strcmp((char *)name, "_dw")) + op = 0x83; + + if (op == 0 || !*data++) { + DEBUG_ERR("invalid type!\n"); + return -1; + } + + if ( !(op&0x80)) // wlan register + ioaddr = priv->pshare->ioaddr; + else + ioaddr = 0; + + // get offset + offset = _atoi((char *)data, 16); + + switch (op&0x7f) { + case 1: +#ifdef CONFIG_SDIO_HCI + if (type) { + sdio_local_read(priv, offset, 1, &b_val); + } + else +#endif + { + b_val = (unsigned char)RTL_R8(offset); + } + panic_printk("\nread byte reg %x=0x%02x\n", offset, b_val); + len = 1; + memcpy(org_ptr, &b_val, len); + break; + case 2: +#ifdef CONFIG_SDIO_HCI + if (type) { + sdio_local_read(priv, offset, 2, (u8 *)&w_val); + w_val = le16_to_cpu(w_val); + } + else +#endif + { + w_val = (unsigned short)RTL_R16(offset); + } + panic_printk("\nread word reg %x=0x%04x\n", offset, w_val); + len = 2; +#ifdef _LITTLE_ENDIAN_ + // To fit PSD tool endian requirement + w_val = ___constant_swab16(w_val); +#endif + memcpy(org_ptr, (char *)&w_val, len); + break; + case 3: +#ifdef CONFIG_SDIO_HCI + if (type) { + sdio_local_read(priv, offset, 4, (u8 *)&dw_val); + dw_val = le32_to_cpu(dw_val); + } + else +#endif + { + dw_val = (unsigned long)RTL_R32(offset); + } + panic_printk("\nread dword reg %x=0x%08lx\n", offset, dw_val); + len = 4; +#ifdef _LITTLE_ENDIAN_ + // To fit PSD tool endian requirement + dw_val = ___constant_swab32(dw_val); +#endif + memcpy(org_ptr, (char *)&dw_val, len); + break; + } + + return len; +} + + +/* + * Write memory, command: "iwpriv wlanX write_mem,type,start,len,value" + * where: type may be: "b" - byte, "w" - word, "dw" - "dw" + * start, len and value should be input in hex + */ +static int write_mem(struct rtl8192cd_priv *priv, unsigned char *data) +{ + volatile char tmpbuf[100]; + int i=0, size=0, len; + unsigned long val, start; + + DEBUG_TRACE; + + // get access type + while (*data && *data != ',') + tmpbuf[i++] = *data++; + tmpbuf[i] = '\0'; + + if (!strcmp((char *)tmpbuf, "b")) + size = 1; + else if (!strcmp((char *)tmpbuf, "w")) + size = 2; + else if (!strcmp((char *)tmpbuf, "dw")) + size = 4; + + if (size == 0 || !*data++) { + DEBUG_ERR("invalid command!\n"); + return -1; + } + + // get start, len, and value + i=0; + while (*data && *data != ',') + tmpbuf[i++] = *data++; + tmpbuf[i] = '\0'; + if (i==0 || !*data++) { + DEBUG_ERR("invalid start!\n"); + return -1; + } + start = (unsigned long)_atoi((char *)tmpbuf, 16); + + i=0; + while (*data && *data != ',') + tmpbuf[i++] = *data++; + tmpbuf[i] = '\0'; + if (i==0 || !*data++) { + DEBUG_ERR("invalid len!\n"); + return -1; + } + len = _atoi((char *)tmpbuf, 16); + val = (unsigned long)_atoi((char *)data, 16); + + DEBUG_INFO("write memory: start=%08lx, len=%x, data=0x%x (%s)\n", + start, len, (int)val, + (size == 1 ? "byte" : (size == 2 ? "word" : "dword"))); + + for (i=0; i0) && ((i%16)==0)) + strcat(tmp1, "\n"); + } + else if (size == 2) { + sprintf(tmp2, "%04x ", w_val); + if ((i>0) && ((i%8)==0)) + strcat(tmp1, "\n"); + } + else if (size == 4) { + sprintf(tmp2, "%08lx ", dw_val); + if ((i>0) && ((i%8)==0)) + strcat(tmp1, "\n"); + } + strcat(tmp1, tmp2); + } + strcat(tmp1, "\n"); + + panic_printk("\n%s", tmp1); +//#endif // _DEBUG_RTL8192CD_ +#endif // !define CONFIG_RTL8186_TR + if (size*len > 128) + copy_len = 128; + else + copy_len = size*len; + memcpy(org_ptr, (char *)start, copy_len); + + kfree(tmp1); + return copy_len; +} + + +static int write_bb_reg(struct rtl8192cd_priv *priv, unsigned char *data) +{ + return 0; +} + + +static int read_bb_reg(struct rtl8192cd_priv *priv, unsigned char *data) +{ + return 0; +} + + +static int write_rf_reg(struct rtl8192cd_priv *priv, unsigned char *data) +{ + volatile char tmpbuf[32]; + unsigned int path, offset, val, val_read; + int i; + + DEBUG_TRACE; + + if (strlen((char *)data) != 0) { + i = 0; + while (*data && *data != ',') + tmpbuf[i++] = *data++; + tmpbuf[i] = '\0'; + if (i==0 || !*data++) { + DEBUG_ERR("invalid path!\n"); + return -1; + } + path = _atoi((char *)tmpbuf, 16); + + i = 0; + while (*data && *data != ',') + tmpbuf[i++] = *data++; + tmpbuf[i] = '\0'; + if (i==0 || !*data++) { + DEBUG_ERR("invalid offset!\n"); + return -1; + } + offset = _atoi((char *)tmpbuf, 16); + + val = (unsigned long)_atoi((char *)data, 16); + + PHY_SetRFReg(priv, path, offset, bMask20Bits, val); + val_read = PHY_QueryRFReg(priv, path, offset, bMask20Bits, 1); + printk("write RF %d offset 0x%02x val [0x%05x], read back [0x%05x]\n", + path, offset, val&0xfffff, val_read&0xfffff); + } + + return 0; +} + + +static int read_rf_reg(struct rtl8192cd_priv *priv, unsigned char *data) +{ + volatile char tmpbuf[32]; + unsigned char *arg = data; + unsigned int path, offset, val; + int i; + + DEBUG_TRACE; + + if (strlen((char *)arg) != 0) { + i = 0; + while (*arg && *arg != ',') + tmpbuf[i++] = *arg++; + tmpbuf[i] = '\0'; + if (i==0 || !*arg++) { + DEBUG_ERR("invalid path!\n"); + return -1; + } + path = _atoi((char *)tmpbuf, 16); + + offset = (unsigned char)_atoi((char *)arg, 16); + val = PHY_QueryRFReg(priv, path, offset, bMask20Bits, 1); + panic_printk("\nread RF %d reg %02x=0x%08x\n", path, offset, val); +#ifdef _LITTLE_ENDIAN_ + // To fit PSD tool endian requirement + val = ___constant_swab32(val); +#endif + memcpy(data, (char *)&val, 4); + return 4; + } + return 1; +} + + +#ifdef CONFIG_RTL8186_KB +int get_guestmac(struct rtl8192cd_priv *priv, GUESTMAC_T *macdata) +{ + int i=0; + + for (i=0; iguestMac[i].valid) + { + memcpy(macdata->macaddr, priv->guestMac[i].macaddr, 6); + macdata->valid = priv->guestMac[i].valid; + } + else + break; + macdata++; + } + return sizeof(GUESTMAC_T)*i; +} + + +int set_guestmacvalid(struct rtl8192cd_priv *priv, char *buf) +{ + int i=0; + + for (i=0; iguestMac[i].valid) + { + continue; + } + memcpy(priv->guestMac[i].macaddr, buf, 6); + priv->guestMac[i].valid = 1; + return 0; + } + /*No slot avaible*/ + return -1; +} + + +int set_guestmacinvalid(struct rtl8192cd_priv *priv, char *buf) +{ + int i=0; + + for (i=0; iguestMac[i].valid && !memcmp(priv->guestMac[i].macaddr, buf, 6)) + { + priv->guestMac[i].valid = 0; + return 0; + } + } + /*No such slot*/ + return -1; +} +#endif // CONFIG_RTL8186_KB + +#ifdef MULTI_MAC_CLONE +int get_mclone_addr(struct rtl8192cd_priv *priv, char *buf) +{ + int idx=0; + unsigned char *mac; + unsigned char tmpbuf[10]={0}; + + get_arg(buf, tmpbuf); + idx = _atoi(tmpbuf, 10); + if (idx > MAX_MAC_CLONE_NUM || idx < 0) + return -1; + + mac = (unsigned char *)&priv->pshare->mclone_sta_fixed_addr[idx]; + sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + return (strlen(buf)+1); +} + +int set_mclone_addr(struct rtl8192cd_priv *priv, char *buf) +{ + int idx=0, i; + char *mac; + unsigned char tmpbuf[10]={0}; + unsigned long *mac4; + + mac = get_arg(buf, tmpbuf); + idx = _atoi(tmpbuf, 10); + if (idx >= MAX_MAC_CLONE_NUM || idx < 0) + return -1; + + if (idx==0) { + get_array_val(tmpbuf, mac, 12); + for (i=0; ipshare->mclone_sta_fixed_addr[i].clone_addr), tmpbuf, 6); + mac4 = (unsigned long *)&priv->pshare->mclone_sta_fixed_addr[i].clone_addr[2]; + #ifdef __ECOS + *mac4 = (*mac4)+i; //temporary modified for ecos compile error. + #else + *mac4 = be32_to_cpu(cpu_to_be32(*mac4)+i); + #endif + } + } + else { + get_array_val((priv->pshare->mclone_sta_fixed_addr[idx].clone_addr), mac, 12); + } + + return 0; +} + +int __del_mclone_addr(struct rtl8192cd_priv *priv, unsigned char *tmpAddr) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + int idx=-1; + int tmpActive = ACTIVE_ID; + struct stat_info *pstat=NULL; + struct rtl8192cd_priv *tmpPriv; + + idx = mclone_find_address(priv, tmpAddr, NULL, MAC_CLONE_SA_FIND); + ACTIVE_ID = idx; + + if (idx > 0){ + tmpPriv = priv->pshare->mclone_sta[idx-1].priv; + + SAVE_INT_AND_CLI(flags); + pstat = get_stainfo(tmpPriv, (GET_MIB(tmpPriv))->dot11StationConfigEntry.dot11Bssid); + if (pstat) { + printk("Remove mclone[%d]: %02x%02x%02x%02x%02x%02x\n", idx-1, tmpAddr[0], tmpAddr[1], tmpAddr[2], tmpAddr[3], tmpAddr[4], tmpAddr[5]); + if (tmpPriv->pshare->mclone_sta[idx-1].opmode & WIFI_ASOC_STATE) + issue_deauth(tmpPriv, (GET_MIB(tmpPriv))->dot11StationConfigEntry.dot11Bssid, _RSON_DEAUTH_STA_LEAVING_); + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(tmpPriv)) + GET_HAL_INTERFACE(tmpPriv)->McloneStopMBSSIDHandler(tmpPriv, (idx-1)); + else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + mclone_stop_mbssid(tmpPriv, (idx-1));//mclone_stop_mbssid need to modify + clear_Multi_Mac_Clone(tmpPriv, idx-1); + + if (pstat->expire_to > 0) + { + cnt_assoc_num(tmpPriv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(tmpPriv, pstat, DECREASE); + } + free_stainfo(tmpPriv, pstat); + } + + RESTORE_INT(flags); + } + else if (idx == 0) { + SAVE_INT_AND_CLI(flags); + pstat = get_stainfo(priv, (GET_MIB(priv))->dot11StationConfigEntry.dot11Bssid); + if (pstat) { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + } + free_stainfo(priv, pstat); + } + RESTORE_INT(flags); + } + else { + //printk("Could not find the MAC %02x%02x%02x%02x%02x%02x\n", tmpAddr[0], tmpAddr[1], tmpAddr[2], tmpAddr[3], tmpAddr[4], tmpAddr[5]); + } + + ACTIVE_ID = tmpActive; + return idx; +} + +int del_mclone_addr(struct rtl8192cd_priv *priv, char *buf) +{ + unsigned char tmpAddr[6]; + + printk("buf:%s\n", (buf ? buf : "none")); + + get_array_val(tmpAddr, buf, 12); + + __del_mclone_addr(priv, tmpAddr); + + return 0; +} +#endif // MULTI_MAC_CLONE + +#ifdef _DEBUG_RTL8192CD_ + +//_TXPWR_REDEFINE + +#define POWER_MIN_CHECK(a,b) (((a) > (b)) ? (b) : (a)) +#ifndef POWER_RANGE_CHECK +#define POWER_RANGE_CHECK(val) (((val) > 0x3f)? 0x3f : ((val < 0) ? 0 : val)) +#endif +#define COUNT_SIGN_OFFSET(val, oft) (((oft & 0x08) == 0x08)? (val - (0x10 - oft)) : (val + oft)) + +#define ASSIGN_TX_POWER_OFFSET(offset, setting) { \ + if (setting != 0x7f) \ + offset = setting; \ +} + +#ifndef TXPWR_LMT +static int ch2idx(int ch) +{ + int val=-1; + // |1~14|36, 38, 40, ..., 64|100, 102, ..., 140|149, 151, ..., 165| + if (ch<=14) + val = ch-1; + else if (ch<=64) + val = ((ch-36)>>1)+14; + else if (ch<=140) + val = ((ch-100)>>1)+29; + else if (ch<=165) + val = ((ch-149)>>1)+50; + + return val; +} +#endif + + +#ifdef ADD_TX_POWER_BY_CMD +static void check_txpwr_by_cmd(struct rtl8192cd_priv *priv, + char *MCSTxAgcOffset_A, char *MCSTxAgcOffset_B, + char *OFDMTxAgcOffset_A, char *OFDMTxAgcOffset_B, + char *CCKTxAgc_A, char *CCKTxAgc_B) +{ +// char is_by_cmd = 0; + + if( (priv->pshare->rf_ft_var.txPowerPlus_cck_11 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_cck_5 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_cck_2 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_cck_1 != 0x7f)) + { + ASSIGN_TX_POWER_OFFSET(CCKTxAgc_A[0], priv->pshare->rf_ft_var.txPowerPlus_cck_11); + ASSIGN_TX_POWER_OFFSET(CCKTxAgc_A[1], priv->pshare->rf_ft_var.txPowerPlus_cck_5); + ASSIGN_TX_POWER_OFFSET(CCKTxAgc_A[2], priv->pshare->rf_ft_var.txPowerPlus_cck_2); + ASSIGN_TX_POWER_OFFSET(CCKTxAgc_A[3], priv->pshare->rf_ft_var.txPowerPlus_cck_1); + ASSIGN_TX_POWER_OFFSET(CCKTxAgc_B[0], priv->pshare->rf_ft_var.txPowerPlus_cck_11); + ASSIGN_TX_POWER_OFFSET(CCKTxAgc_B[1], priv->pshare->rf_ft_var.txPowerPlus_cck_5); + ASSIGN_TX_POWER_OFFSET(CCKTxAgc_B[2], priv->pshare->rf_ft_var.txPowerPlus_cck_2); + ASSIGN_TX_POWER_OFFSET(CCKTxAgc_B[3], priv->pshare->rf_ft_var.txPowerPlus_cck_1); + + printk("TXPWR_BY_CMD: CCK = %02x %02x %02x %02x \n", + priv->pshare->rf_ft_var.txPowerPlus_cck_11, + priv->pshare->rf_ft_var.txPowerPlus_cck_5, + priv->pshare->rf_ft_var.txPowerPlus_cck_2, + priv->pshare->rf_ft_var.txPowerPlus_cck_1); + } + + + if( (priv->pshare->rf_ft_var.txPowerPlus_ofdm_18 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_ofdm_12!= 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_ofdm_9 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_ofdm_6 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_ofdm_54 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_ofdm_48 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_ofdm_36 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_ofdm_24 != 0x7f)) + { + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_A[0], priv->pshare->rf_ft_var.txPowerPlus_ofdm_18); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_A[1], priv->pshare->rf_ft_var.txPowerPlus_ofdm_12); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_A[2], priv->pshare->rf_ft_var.txPowerPlus_ofdm_9); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_A[3], priv->pshare->rf_ft_var.txPowerPlus_ofdm_6); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_B[0], priv->pshare->rf_ft_var.txPowerPlus_ofdm_18); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_B[1], priv->pshare->rf_ft_var.txPowerPlus_ofdm_12); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_B[2], priv->pshare->rf_ft_var.txPowerPlus_ofdm_9); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_B[3], priv->pshare->rf_ft_var.txPowerPlus_ofdm_6); + + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_A[4], priv->pshare->rf_ft_var.txPowerPlus_ofdm_54); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_A[5], priv->pshare->rf_ft_var.txPowerPlus_ofdm_48); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_A[6], priv->pshare->rf_ft_var.txPowerPlus_ofdm_36); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_A[7], priv->pshare->rf_ft_var.txPowerPlus_ofdm_24); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_B[4], priv->pshare->rf_ft_var.txPowerPlus_ofdm_54); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_B[5], priv->pshare->rf_ft_var.txPowerPlus_ofdm_48); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_B[6], priv->pshare->rf_ft_var.txPowerPlus_ofdm_36); + ASSIGN_TX_POWER_OFFSET(OFDMTxAgcOffset_B[7], priv->pshare->rf_ft_var.txPowerPlus_ofdm_24); + + printk("TXPWR_BY_CMD: OFDM = %02x %02x %02x %02x %02x %02x %02x %02x \n", + priv->pshare->rf_ft_var.txPowerPlus_ofdm_18, + priv->pshare->rf_ft_var.txPowerPlus_ofdm_12, + priv->pshare->rf_ft_var.txPowerPlus_ofdm_9, + priv->pshare->rf_ft_var.txPowerPlus_ofdm_6, + priv->pshare->rf_ft_var.txPowerPlus_ofdm_54, + priv->pshare->rf_ft_var.txPowerPlus_ofdm_48, + priv->pshare->rf_ft_var.txPowerPlus_ofdm_36, + priv->pshare->rf_ft_var.txPowerPlus_ofdm_24); + } + + + if( (priv->pshare->rf_ft_var.txPowerPlus_mcs_3 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_2 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_1 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_0 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_7 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_6 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_5 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_4 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_11 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_10 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_9 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_8 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_15 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_14 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_13 != 0x7f) + || (priv->pshare->rf_ft_var.txPowerPlus_mcs_12 != 0x7f)) + { + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[0], priv->pshare->rf_ft_var.txPowerPlus_mcs_3); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[1], priv->pshare->rf_ft_var.txPowerPlus_mcs_2); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[2], priv->pshare->rf_ft_var.txPowerPlus_mcs_1); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[3], priv->pshare->rf_ft_var.txPowerPlus_mcs_0); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[0], priv->pshare->rf_ft_var.txPowerPlus_mcs_3); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[1], priv->pshare->rf_ft_var.txPowerPlus_mcs_2); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[2], priv->pshare->rf_ft_var.txPowerPlus_mcs_1); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[3], priv->pshare->rf_ft_var.txPowerPlus_mcs_0); + + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[4], priv->pshare->rf_ft_var.txPowerPlus_mcs_7); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[5], priv->pshare->rf_ft_var.txPowerPlus_mcs_6); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[6], priv->pshare->rf_ft_var.txPowerPlus_mcs_5); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[7], priv->pshare->rf_ft_var.txPowerPlus_mcs_4); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[4], priv->pshare->rf_ft_var.txPowerPlus_mcs_7); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[5], priv->pshare->rf_ft_var.txPowerPlus_mcs_6); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[6], priv->pshare->rf_ft_var.txPowerPlus_mcs_5); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[7], priv->pshare->rf_ft_var.txPowerPlus_mcs_4); + + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[8], priv->pshare->rf_ft_var.txPowerPlus_mcs_11); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[9], priv->pshare->rf_ft_var.txPowerPlus_mcs_10); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[10], priv->pshare->rf_ft_var.txPowerPlus_mcs_9); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[11], priv->pshare->rf_ft_var.txPowerPlus_mcs_8); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[8], priv->pshare->rf_ft_var.txPowerPlus_mcs_11); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[9], priv->pshare->rf_ft_var.txPowerPlus_mcs_10); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[10], priv->pshare->rf_ft_var.txPowerPlus_mcs_9); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[11], priv->pshare->rf_ft_var.txPowerPlus_mcs_8); + + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[12], priv->pshare->rf_ft_var.txPowerPlus_mcs_15); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[13], priv->pshare->rf_ft_var.txPowerPlus_mcs_14); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[14], priv->pshare->rf_ft_var.txPowerPlus_mcs_13); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_A[15], priv->pshare->rf_ft_var.txPowerPlus_mcs_12); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[12], priv->pshare->rf_ft_var.txPowerPlus_mcs_15); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[13], priv->pshare->rf_ft_var.txPowerPlus_mcs_14); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[14], priv->pshare->rf_ft_var.txPowerPlus_mcs_13); + ASSIGN_TX_POWER_OFFSET(MCSTxAgcOffset_B[15], priv->pshare->rf_ft_var.txPowerPlus_mcs_12); + + printk("TXPWR_BY_CMD: OFDM = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x \n", + priv->pshare->rf_ft_var.txPowerPlus_mcs_3, + priv->pshare->rf_ft_var.txPowerPlus_mcs_2, + priv->pshare->rf_ft_var.txPowerPlus_mcs_1, + priv->pshare->rf_ft_var.txPowerPlus_mcs_0, + priv->pshare->rf_ft_var.txPowerPlus_mcs_7, + priv->pshare->rf_ft_var.txPowerPlus_mcs_6, + priv->pshare->rf_ft_var.txPowerPlus_mcs_5, + priv->pshare->rf_ft_var.txPowerPlus_mcs_4, + priv->pshare->rf_ft_var.txPowerPlus_mcs_11, + priv->pshare->rf_ft_var.txPowerPlus_mcs_10, + priv->pshare->rf_ft_var.txPowerPlus_mcs_9, + priv->pshare->rf_ft_var.txPowerPlus_mcs_8, + priv->pshare->rf_ft_var.txPowerPlus_mcs_15, + priv->pshare->rf_ft_var.txPowerPlus_mcs_14, + priv->pshare->rf_ft_var.txPowerPlus_mcs_13, + priv->pshare->rf_ft_var.txPowerPlus_mcs_12); + } + +} +#endif + + +static void dump_cck(struct rtl8192cd_priv *priv, + unsigned char pwrlevelCCK_A, unsigned char pwrlevelCCK_B, + char *CCKTxAgc_A, char *CCKTxAgc_B + ) +{ + char byte, byte1, byte2, byte3; + + if (priv->pshare->rf_ft_var.cck_pwr_max) + { + printk("Use cck_pwr_max = %d\n", priv->pshare->rf_ft_var.cck_pwr_max); + + byte = POWER_RANGE_CHECK(priv->pshare->rf_ft_var.cck_pwr_max); + printk("A_CCK1_Mcs32(0xe08): 0x----%02x--\n", byte); + printk("B_CCK5_1_Mcs32(0x838): 0x%02x%02x%02x--\n", byte, byte, byte); + printk("A_CCK11_2_B_CCK11(0x86c): 0x%02x%02x%02x%02x\n", byte, byte, byte, byte); + + return; + } + + if (pwrlevelCCK_A == 0) { // use default value +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) + byte = HP_CCK_POWER_DEFAULT; + else +#endif + byte = 0x24; + + printk("Use default cck value = %d\n", byte); + + pwrlevelCCK_A = pwrlevelCCK_B = byte; + byte = 0; + ASSIGN_TX_POWER_OFFSET(byte, priv->pshare->rf_ft_var.txPowerPlus_cck_1); + byte = POWER_RANGE_CHECK(pwrlevelCCK_A + byte); + printk("A_CCK1_Mcs32(0xe08): 0x----%02x--\n", byte); + + byte = byte1 = byte2 = 0; + ASSIGN_TX_POWER_OFFSET(byte, priv->pshare->rf_ft_var.txPowerPlus_cck_1); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_cck_2); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_cck_5); + byte = POWER_RANGE_CHECK(pwrlevelCCK_B + byte); + byte1 = POWER_RANGE_CHECK(pwrlevelCCK_B + byte1); + byte2 = POWER_RANGE_CHECK(pwrlevelCCK_B + byte2); + printk("B_CCK5_1_Mcs32(0x838): 0x%02x%02x%02x--\n", byte2, byte1, byte); + + byte = byte1 = byte2 = 0; + ASSIGN_TX_POWER_OFFSET(byte, priv->pshare->rf_ft_var.txPowerPlus_cck_2); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_cck_5); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_cck_11); + byte = POWER_RANGE_CHECK(pwrlevelCCK_A + byte); + byte1 = POWER_RANGE_CHECK(pwrlevelCCK_A + byte1); + byte2 = POWER_RANGE_CHECK(pwrlevelCCK_A + byte2); + printk("A_CCK11_2_B_CCK11(0x86c): 0x%02x%02x%02x%02x\n", byte2, byte1, byte, byte2); + + return; // use default + } + + byte = POWER_RANGE_CHECK(pwrlevelCCK_A + CCKTxAgc_A[3]); + printk("A_CCK1_Mcs32(0xe08): 0x----%02x--\n", byte); + + byte = POWER_RANGE_CHECK(pwrlevelCCK_B + CCKTxAgc_B[1]); + byte1 = POWER_RANGE_CHECK(pwrlevelCCK_B + CCKTxAgc_B[2]); + byte2 = POWER_RANGE_CHECK(pwrlevelCCK_B + CCKTxAgc_B[3]); + printk("B_CCK5_1_Mcs32(0x838): 0x%02x%02x%02x--\n", byte, byte1, byte2); + + byte = POWER_RANGE_CHECK(pwrlevelCCK_A + CCKTxAgc_A[0]); + byte1 = POWER_RANGE_CHECK(pwrlevelCCK_A + CCKTxAgc_A[1]); + byte2 = POWER_RANGE_CHECK(pwrlevelCCK_A + CCKTxAgc_A[2]); + byte3 = POWER_RANGE_CHECK(pwrlevelCCK_B + CCKTxAgc_B[0]); + printk("A_CCK11_2_B_CCK11(0x86c): 0x%02x%02x%02x%02x\n", byte, byte1, byte2, byte3); + + return; + +} + + +static void dump_ofdm_mcs0(struct rtl8192cd_priv *priv, int defValue, + unsigned char pwrlevelHT40_1S_A, unsigned char pwrlevelHT40_1S_B, + unsigned char pwrdiffHT40_2S, unsigned char pwrdiffHT20, unsigned char pwrdiffOFDM, + unsigned char pwrlevelHT40_1S_A_6dB, unsigned char pwrlevelHT40_1S_B_6dB, + unsigned char pwrdiffHT40_2S_6dB, unsigned char pwrdiffHT20_6dB, + char *MCSTxAgcOffset_A, char *MCSTxAgcOffset_B, char *OFDMTxAgcOffset_A, char *OFDMTxAgcOffset_B, + int phyBandSelect + ) +{ + + s1Byte base, byte0, byte1, byte2, byte3; + unsigned char offset; + +#ifdef USB_POWER_SUPPORT + s1Byte base_6dBm; + unsigned char offset_6dBm; +#endif + + if (pwrlevelHT40_1S_A == 0) + { + +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) + defValue = HP_OFDM_POWER_DEFAULT ; +#endif + printk("pwrlevelHT40_1S_A = 0, Use Default Value = %d\n", defValue); + + base = defValue; + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_ofdm_18); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_ofdm_12); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_ofdm_9); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_ofdm_6); + + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + + printk("A_Rate18_06(0xe00): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + printk("B_Rate18_06(0x830): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_ofdm_54); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_ofdm_48); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_ofdm_36); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_ofdm_24); + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + printk("A_Rate54_24(0xe04): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + printk("B_Rate54_24(0x834): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_mcs_3); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_mcs_2); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_mcs_1); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_mcs_0); + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + printk("A_Mcs03_Mcs00(0xe10): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + printk("B_Mcs03_Mcs00(0x83c): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_mcs_7); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_mcs_6); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_mcs_5); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_mcs_4); + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + printk("A_Mcs07_Mcs04(0xe14): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + printk("B_Mcs07_Mcs04(0x848): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + +//_TXPWR_REDEFINE +#ifdef USB_POWER_SUPPORT + byte0 = byte1 = byte2 = byte3 = -USB_HT_2S_DIFF; +#else + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_mcs_11); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_mcs_10); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_mcs_9); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_mcs_8); +#endif + + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + printk("A_Mcs11_Mcs08(0xe18): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); + printk("B_Mcs11_Mcs08(0x84c): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); + +//_TXPWR_REDEFINE +#ifdef USB_POWER_SUPPORT + byte0 = byte1 = byte2 = byte3 = -USB_HT_2S_DIFF; +#else + byte0 = byte1 = byte2 = byte3 = 0; + ASSIGN_TX_POWER_OFFSET(byte0, priv->pshare->rf_ft_var.txPowerPlus_mcs_15); + ASSIGN_TX_POWER_OFFSET(byte1, priv->pshare->rf_ft_var.txPowerPlus_mcs_14); + ASSIGN_TX_POWER_OFFSET(byte2, priv->pshare->rf_ft_var.txPowerPlus_mcs_13); + ASSIGN_TX_POWER_OFFSET(byte3, priv->pshare->rf_ft_var.txPowerPlus_mcs_12); +#endif + + byte0 = POWER_RANGE_CHECK(base + byte0); + byte1 = POWER_RANGE_CHECK(base + byte1); + byte2 = POWER_RANGE_CHECK(base + byte2); + byte3 = POWER_RANGE_CHECK(base + byte3); + printk("A_Mcs15_Mcs12(0xe1c): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); + printk("B_Mcs15_Mcs12(0x868): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); + + return; // use default + } + else + { + //===PATH A=== + //OFDM + base = pwrlevelHT40_1S_A; + offset = (pwrdiffOFDM & 0x0f); + +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) + //_TXPWR_REDEFINE?? + if (priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset = ((pwrdiffOFDM & 0xf0) >> 4); + } +#endif + base = COUNT_SIGN_OFFSET(base, offset); + + byte0 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_A[0]); + byte1 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_A[1]); + byte2 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_A[2]); + byte3 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_A[3]); + printk("A_Rate18_06(0xe00): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + + byte0 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_A[4]); + byte1 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_A[5]); + byte2 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_A[6]); + byte3 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_A[7]); + printk("A_Rate54_24(0xe04): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + //MCS 0 - 7 + base = pwrlevelHT40_1S_A; + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + offset = (pwrdiffHT20 & 0x0f); +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) + //_TXPWR_REDEFINE?? + if (priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset = ((pwrdiffHT20 & 0xf0) >> 4); + } +#endif + base = COUNT_SIGN_OFFSET(base, offset); + } + + byte0 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_A[0]); + byte1 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_A[1]); + byte2 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_A[2]); + byte3 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_A[3]); + printk("A_Mcs03_Mcs00(0xe10): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + byte0 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_A[4]); + byte1 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_A[5]); + byte2 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_A[6]); + byte3 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_A[7]); + printk("A_Mcs07_Mcs04(0xe14): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + offset = (pwrdiffHT40_2S & 0x0f); +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) + //_TXPWR_REDEFINE?? + if (priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset = ((pwrdiffHT40_2S & 0xf0) >> 4); + } +#endif + base = COUNT_SIGN_OFFSET(base, offset); + + //MCS 8 -12 +#ifdef USB_POWER_SUPPORT + + base_6dBm = pwrlevelHT40_1S_A_6dB; + + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + { + offset_6dBm = (pwrdiffHT20_6dB & 0x0f); + +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) + if (priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset_6dBm = ((pwrdiffHT20_6dB & 0xf0) >> 4); + } +#endif + base_6dBm = COUNT_SIGN_OFFSET(base_6dBm, offset_6dBm); + } + + offset_6dBm = (pwrdiffHT40_2S_6dB & 0x0f); + +#if defined(CONFIG_RTL_92D_SUPPORT)&& defined(CONFIG_RTL_92D_DMDP) + if (priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + offset_6dBm = ((pwrdiffHT40_2S_6dB & 0xf0) >> 4); + } +#endif + + base_6dBm = COUNT_SIGN_OFFSET(base_6dBm, offset_6dBm); + + if ((pwrlevelHT40_1S_A_6dB!= 0) && (pwrlevelHT40_1S_A_6dB!= pwrlevelHT40_1S_A)) + byte0 = byte1 = byte2 = byte3 = base_6dBm; + else if((base - USB_HT_2S_DIFF) > 0) + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(base - USB_HT_2S_DIFF); + else + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(defValue - USB_HT_2S_DIFF); + + printk("A_Mcs11_Mcs08(0xe18): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + if ((pwrlevelHT40_1S_A_6dB != 0) && (pwrlevelHT40_1S_A_6dB != pwrlevelHT40_1S_A)) + byte0 = byte1 = byte2 = byte3 = base_6dBm; + else if((base - USB_HT_2S_DIFF) > 0) + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(base - USB_HT_2S_DIFF); + else + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(defValue - USB_HT_2S_DIFF); + + printk("A_Mcs15_Mcs12(0xe1c): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + +#else + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[8]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[9]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[10]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[11]); + printk("A_Mcs11_Mcs08(0xe18): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[12]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[13]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[14]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_A[15]); + printk("A_Mcs15_Mcs12(0xe1c): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); +#endif + //===PATH B=== + if (pwrlevelHT40_1S_B == 0) + pwrlevelHT40_1S_B = defValue; + + //OFDM + base = pwrlevelHT40_1S_B; + offset = ((pwrdiffOFDM & 0xf0) >> 4); + base = COUNT_SIGN_OFFSET(base, offset); + + byte0 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_B[0]); + byte1 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_B[1]); + byte2 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_B[2]); + byte3 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_B[3]); + printk("B_Rate18_06(0x830): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + + byte0 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_B[4]); + byte1 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_B[5]); + byte2 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_B[6]); + byte3 = POWER_RANGE_CHECK(base + OFDMTxAgcOffset_B[7]); + printk("B_Rate54_24(0x834): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + //MCS 0 - 7 + base = pwrlevelHT40_1S_B; + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + offset = ((pwrdiffHT20 & 0xf0) >> 4); + base = COUNT_SIGN_OFFSET(base, offset); + } + + byte0 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_B[0]); + byte1 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_B[1]); + byte2 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_B[2]); + byte3 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_B[3]); + printk("B_Mcs03_Mcs00(0x83c): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + byte0 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_B[4]); + byte1 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_B[5]); + byte2 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_B[6]); + byte3 = POWER_RANGE_CHECK(base + MCSTxAgcOffset_B[7]); + printk("B_Mcs07_Mcs04(0x848): 0x%02x%02x%02x%02x\n", byte0, byte1, byte2, byte3); + + offset = ((pwrdiffHT40_2S & 0xf0) >> 4); + base = COUNT_SIGN_OFFSET(base, offset); + + //MCS 8 -12 +#ifdef USB_POWER_SUPPORT + + base_6dBm = pwrlevelHT40_1S_B_6dB; + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + offset_6dBm = ((pwrdiffHT20_6dB & 0xf0) >> 4); + base_6dBm = COUNT_SIGN_OFFSET(base_6dBm, offset_6dBm); + } + + offset_6dBm = ((pwrdiffHT40_2S_6dB& 0xf0) >> 4); + base_6dBm = COUNT_SIGN_OFFSET(base_6dBm, offset_6dBm); + + if ((pwrlevelHT40_1S_B_6dB!= 0) && (pwrlevelHT40_1S_B_6dB!= pwrlevelHT40_1S_B)) + byte0 = byte1 = byte2 = byte3 = base_6dBm; + else if((base - USB_HT_2S_DIFF) > 0) + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(base - USB_HT_2S_DIFF); + else + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(defValue - USB_HT_2S_DIFF); + + printk("B_Mcs11_Mcs08(0x84c): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); + + if ((pwrlevelHT40_1S_B_6dB != 0) && (pwrlevelHT40_1S_B_6dB != pwrlevelHT40_1S_B)) + byte0 = byte1 = byte2 = byte3 = base_6dBm; + else if((base - USB_HT_2S_DIFF) > 0) + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(base - USB_HT_2S_DIFF); + else + byte0 = byte1 = byte2 = byte3 = POWER_RANGE_CHECK(defValue - USB_HT_2S_DIFF); + + printk("B_Mcs15_Mcs12(0x868): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); + +#else + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[8]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[9]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[10]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[11]); + printk("B_Mcs11_Mcs08(0x84c): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); + + byte0 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[12]); + byte1 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[13]); + byte2 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[14]); + byte3 = POWER_RANGE_CHECK(base + priv->pshare->phw->MCSTxAgcOffset_B[15]); + printk("B_Mcs15_Mcs12(0x868): 0x%02x%02x%02x%02x\n",byte0, byte1, byte2, byte3); + + return; +#endif + } + +} + +static void txpwr_dump(struct rtl8192cd_priv *priv, int start, int end) +{ + + int channel = 0; + int tmp = 0; + int defValue = 0x28; + unsigned int phyBandSelect; + + char pwrlevelCCK_A = 0; + char pwrlevelCCK_B = 0; + + unsigned char pwrlevelHT40_1S_A = 0; + unsigned char pwrlevelHT40_1S_B = 0; + unsigned char pwrdiffHT40_2S = 0; + unsigned char pwrdiffHT20 = 0; + unsigned char pwrdiffOFDM = 0; + +#if 1 // USB_POWER_SUPPORT + unsigned char pwrlevelHT40_1S_A_6dB = 0; + unsigned char pwrlevelHT40_1S_B_6dB = 0; + unsigned char pwrdiffHT40_2S_6dB = 0; + unsigned char pwrdiffHT20_6dB = 0; +#endif + + int pg_tbl_idx = 0; + int PHYREG_PG = 4; + char MCSTxAgcOffset_A[16]; + char MCSTxAgcOffset_B[16]; + char OFDMTxAgcOffset_A[8]; + char OFDMTxAgcOffset_B[8]; + + //_TXPWR_REDEFINE ?? int or char ?? + char CCKTxAgc_A[4]; + char CCKTxAgc_B[4]; + +#ifdef TXPWR_LMT + unsigned int tgpwr_CCK = 0; + unsigned int tgpwr_OFDM = 0; + unsigned int txpwr_lmt_CCK = 0; + unsigned int txpwr_lmt_OFDM = 0; + + unsigned int tgpwr_HT1S = 0; + unsigned int tgpwr_HT2S = 0; + unsigned int txpwr_lmt_HT1S = 0; + unsigned int txpwr_lmt_HT2S = 0; + + int i; + int max_idx; +#endif + + if(end <= 14) + phyBandSelect = PHY_BAND_2G; + else + phyBandSelect = PHY_BAND_5G; + + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) { +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) + if (phyBandSelect & PHY_BAND_5G) + defValue=0x28; + else + defValue=0x2d; +#else + if (phyBandSelect & PHY_BAND_5G) + defValue=0x26; + else + defValue=0x30; +#endif + } +#endif + + + if(start > end) + { + printk("Error! start = %d < end = %d\n", start, end); + } + else if (end <= 14) + { + for(channel = start; channel <= end; channel++ ) //_TXPWR_REDEFINE ?? DO NOT PRINT TOO MUCH + { + + printk("\n[CHANNEL%03d]", channel); + printk("\n"); + + //===GET FROM FLASH=== + + pwrlevelCCK_A = priv->pmib->dot11RFEntry.pwrlevelCCK_A[channel-1]; + pwrlevelCCK_B = priv->pmib->dot11RFEntry.pwrlevelCCK_B[channel-1]; + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[channel-1]; + pwrlevelHT40_1S_B = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[channel-1]; + pwrdiffHT40_2S = priv->pmib->dot11RFEntry.pwrdiffHT40_2S[channel-1]; + pwrdiffHT20 = priv->pmib->dot11RFEntry.pwrdiffHT20[channel-1]; + pwrdiffOFDM = priv->pmib->dot11RFEntry.pwrdiffOFDM[channel-1]; + +#ifdef USB_POWER_SUPPORT + printk(">>FLASH - 13dBm<<\n"); +#endif + printk("pwrlevelCCK_A = %d, pwrlevelCCK_B = %d\n", pwrlevelCCK_A, pwrlevelCCK_B); + printk("pwrlevelHT40_1S_A = %d, pwrlevelHT40_1S_B = %d\n", pwrlevelHT40_1S_A, pwrlevelHT40_1S_B); + printk("pwrdiffHT40_2S = %d(0x%02x), pwrdiffHT20 = %d(0x%02x), pwrdiffOFDM = %d(0x%02x)\n", + pwrdiffHT40_2S, pwrdiffHT40_2S, + pwrdiffHT20, pwrdiffHT20, + pwrdiffOFDM, pwrdiffOFDM); + +#ifdef USB_POWER_SUPPORT + printk(">>FLASH - 6dBm<<\n"); + pwrlevelHT40_1S_A_6dB = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[channel-1]; + pwrlevelHT40_1S_B_6dB = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel-1]; + pwrdiffHT40_2S_6dB = priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[channel-1]; + pwrdiffHT20_6dB = priv->pmib->dot11RFEntry.pwrdiff5GHT20[channel-1]; + + printk("pwrlevelHT40_1S_A = %d, pwrlevelHT40_1S_B = %d\n", pwrlevelHT40_1S_A_6dB, pwrlevelHT40_1S_B_6dB); + printk("pwrdiffHT40_2S = %d(0x%02x), pwrdiffHT20 = %d(0x%02x)\n", + pwrdiffHT40_2S_6dB, pwrdiffHT40_2S_6dB, + pwrdiffHT20_6dB, pwrdiffHT20_6dB); +#endif + + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_92D_DMDP) + if (GET_CHIP_VER(priv)==VERSION_8192D) { + if (priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) { + printk("92D-DMDP WLAN1 , Set pwrlevelCCK_A = pwrlevelCCK_B\n"); + if (phyBandSelect & PHY_BAND_2G) + pwrlevelCCK_A = priv->pmib->dot11RFEntry.pwrlevelCCK_B[channel-1]; + } + } +#endif + + +#ifdef CONFIG_RTL_92D_DMDP//_Eric ?? Get chip ?? + if (priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) + { + printk("92D-DMDP WLAN1, Set pwrlevelHT40_1S_A = pwrlevelHT40_1S_B\n"); + if (phyBandSelect & PHY_BAND_5G) + { + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel-1]; + } + else + { + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[channel-1]; + } +#ifdef USB_POWER_SUPPORT + if (phyBandSelect & PHY_BAND_5G) + { + pwrlevelHT40_1S_A_6dB= priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel]; + } + else + { + pwrlevelHT40_1S_A_6dB= priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel-1]; + } +#endif + } +#endif + + + //===POWER BY RATE=== + printk(">>Power By Rate Table<<\n"); + pg_tbl_idx = 0; + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (priv->pshare->is_40m_bw == 0) { + if (channel<=3) + pg_tbl_idx = BGN_20_CH1_3; + else if (channel<=9) + pg_tbl_idx = BGN_20_CH4_9; + else + pg_tbl_idx = BGN_20_CH10_14; + } else { + if (channel<=3) + pg_tbl_idx = BGN_40_CH1_3; + else if (channel<=9) + pg_tbl_idx = BGN_40_CH4_9; + else + pg_tbl_idx = BGN_40_CH10_14; + } + } +#ifdef MP_TEST + //In Noraml Driver mode, and if mib 'pwr_by_rate' = 0 >> Use default power by rate table + if( (priv->pshare->rf_ft_var.mp_specific == 0) && (priv->pshare->rf_ft_var.pwr_by_rate == 0) ) + pg_tbl_idx = BGN_2040_ALL; +#endif +#endif + + printk("pg_tbl_idx = %d\n", pg_tbl_idx); + + Read_PG_File(priv, PHYREG_PG, pg_tbl_idx, + MCSTxAgcOffset_A, MCSTxAgcOffset_B, + OFDMTxAgcOffset_A, OFDMTxAgcOffset_B, + CCKTxAgc_A, CCKTxAgc_B); + + printk("MCSTxAgcOffset_A - "); + for(tmp = 0; tmp <16; tmp ++) + printk("%02x ", MCSTxAgcOffset_A[tmp]); + printk("\n"); + + printk("MCSTxAgcOffset_B - "); + for(tmp = 0; tmp <16; tmp ++) + printk("%02x ", MCSTxAgcOffset_B[tmp]); + printk("\n"); + + printk("OFDMTxAgcOffset_A - "); + for(tmp = 0; tmp <8; tmp ++) + printk("%02x ", OFDMTxAgcOffset_A[tmp]); + printk("\n"); + + printk("OFDMTxAgcOffset_B - "); + for(tmp = 0; tmp <8; tmp ++) + printk("%02x ", OFDMTxAgcOffset_B[tmp]); + printk("\n"); + + printk("CCKTxAgc_A - "); + for(tmp = 0; tmp <4; tmp ++) + printk("%02x ", CCKTxAgc_A[tmp]); + printk("\n"); + + printk("CCKTxAgc_B - "); + for(tmp = 0; tmp <4; tmp ++) + printk("%02x ", CCKTxAgc_B[tmp]); + printk("\n"); + +#ifdef ADD_TX_POWER_BY_CMD + check_txpwr_by_cmd(priv, MCSTxAgcOffset_A, MCSTxAgcOffset_B, + OFDMTxAgcOffset_A, OFDMTxAgcOffset_B, CCKTxAgc_A, CCKTxAgc_B); +#endif + + + //===Count FLASH + POWER BY RATE=== + + printk(">>Tx Power - Power By Rate<<\n"); + + dump_cck(priv, pwrlevelCCK_A, pwrlevelCCK_B, CCKTxAgc_A, CCKTxAgc_B); + + dump_ofdm_mcs0(priv, defValue, pwrlevelHT40_1S_A, pwrlevelHT40_1S_B, + pwrdiffHT40_2S, pwrdiffHT20, pwrdiffOFDM, + pwrlevelHT40_1S_A_6dB, pwrlevelHT40_1S_B_6dB, + pwrdiffHT40_2S_6dB, pwrdiffHT20_6dB, + MCSTxAgcOffset_A, MCSTxAgcOffset_B, OFDMTxAgcOffset_A, OFDMTxAgcOffset_B,phyBandSelect); + + +#ifdef TXPWR_LMT + //===BAND EDGE LIMIT=== + if (priv->pshare->rf_ft_var.disable_txpwrlmt) + continue; + + printk(">>Band Edge Limit Table<<\n"); + tmp = ch2idx(channel); + + txpwr_lmt_CCK = priv->pshare->ch_pwr_lmtCCK[tmp]; + txpwr_lmt_OFDM = priv->pshare->ch_pwr_lmtOFDM[tmp]; + tgpwr_CCK = priv->pshare->ch_tgpwr_CCK[tmp]; + tgpwr_OFDM = priv->pshare->ch_tgpwr_OFDM[tmp]; + + printk("txpwr_lmt_CCK = %d tgpwr_CCK = %d\n", txpwr_lmt_CCK, tgpwr_CCK); + printk("txpwr_lmt_OFDM = %d tgpwr_OFDM = %d\n", txpwr_lmt_OFDM, tgpwr_OFDM); + + if (priv->pshare->is_40m_bw == 0) + { + txpwr_lmt_HT1S = priv->pshare->ch_pwr_lmtHT20_1S[tmp]; + txpwr_lmt_HT2S = priv->pshare->ch_pwr_lmtHT20_2S[tmp]; + tgpwr_HT1S = priv->pshare->ch_tgpwr_HT20_1S[tmp]; + tgpwr_HT2S = priv->pshare->ch_tgpwr_HT20_2S[tmp]; + + printk("txpwr_lmt_HT1S_20M = %d tgpwr_HT1S_20M = %d\n", txpwr_lmt_HT1S, tgpwr_HT1S); + printk("txpwr_lmt_HT2S_20M = %d tgpwr_HT2S_20M = %d\n", txpwr_lmt_HT2S, tgpwr_HT2S); + } + else + { + txpwr_lmt_HT1S = priv->pshare->ch_pwr_lmtHT40_1S[tmp]; + txpwr_lmt_HT2S = priv->pshare->ch_pwr_lmtHT40_2S[tmp]; + tgpwr_HT1S = priv->pshare->ch_tgpwr_HT40_1S[tmp]; + tgpwr_HT2S = priv->pshare->ch_tgpwr_HT40_2S[tmp]; + + printk("txpwr_lmt_HT1S_40M = %d tgpwr_HT1S_40M = %d\n", txpwr_lmt_HT1S, tgpwr_HT1S); + printk("txpwr_lmt_HT2S_40M = %d tgpwr_HT2S_40M = %d\n", txpwr_lmt_HT2S, tgpwr_HT2S); + } + + //===Count FLASH + min{POWER BY RATE, LIMIT}=== + if((txpwr_lmt_CCK == 0) && (txpwr_lmt_OFDM == 0) + && (txpwr_lmt_HT1S == 0) && (txpwr_lmt_HT1S == 0)) + { + printk("No Band Edge Limit for this channel=%d\n", channel); + continue; + } + + if (txpwr_lmt_CCK || tgpwr_CCK){ + max_idx=255; + }else{ + max_idx = (txpwr_lmt_CCK - tgpwr_CCK); + } + + for (i=0; i<=3; i++) { + CCKTxAgc_A[i] = POWER_MIN_CHECK(CCKTxAgc_A[i], max_idx); + CCKTxAgc_B[i] = POWER_MIN_CHECK(CCKTxAgc_B[i], max_idx); + } + + dump_cck(priv, pwrlevelCCK_A, pwrlevelCCK_B, CCKTxAgc_A, CCKTxAgc_B); + + if (!txpwr_lmt_OFDM || !tgpwr_OFDM){ + max_idx=255; + }else{ + max_idx = (txpwr_lmt_OFDM - tgpwr_OFDM); + } + + for (i=0; i<=7; i++) { + OFDMTxAgcOffset_A[i] = POWER_MIN_CHECK(OFDMTxAgcOffset_A[i], max_idx); + OFDMTxAgcOffset_B[i] = POWER_MIN_CHECK(OFDMTxAgcOffset_B[i], max_idx); + } + + if (!txpwr_lmt_HT1S || !tgpwr_HT1S){ + max_idx = 255; + }else{ + max_idx = (txpwr_lmt_HT1S - tgpwr_HT1S); + } + + for (i=0; i<=7; i++) { + MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(MCSTxAgcOffset_A[i], max_idx); + MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(MCSTxAgcOffset_B[i], max_idx); + } + + if (!txpwr_lmt_HT2S || !tgpwr_HT2S){ + max_idx = 255; + }else{ + max_idx = (txpwr_lmt_HT2S - tgpwr_HT2S); + } + + for (i=8; i<=15; i++) { + MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(MCSTxAgcOffset_A[i], max_idx); + MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(MCSTxAgcOffset_B[i], max_idx); + } + + dump_ofdm_mcs0(priv, defValue, pwrlevelHT40_1S_A, pwrlevelHT40_1S_B, + pwrdiffHT40_2S, pwrdiffHT20, pwrdiffOFDM, + pwrlevelHT40_1S_A_6dB, pwrlevelHT40_1S_B_6dB, + pwrdiffHT40_2S_6dB, pwrdiffHT20_6dB, + MCSTxAgcOffset_A, MCSTxAgcOffset_B, OFDMTxAgcOffset_A, OFDMTxAgcOffset_B,phyBandSelect); +#endif + + } + } + else if (end <= 199) + { + for(channel = start; channel <= end; channel+=2 ) + { + int ori_channel = channel; + + printk("\n[CHANNEL%03d]", channel); + printk("\n"); + + //TXPWR_REDEFINE + //FLASH GROUP [36-99] [100-148] [149-165] + //Special Cases: [34-2, 34, 34+2, 36-2, 165+2]:No DATA , [149-2]:FLASH DATA OF Channel-146-6dBm + //Use Flash data of channel 36 & 140 & 165 for these special cases. + if((channel > 30) && (channel < 36)) + channel = 36; + else if (channel == (149-2)) + channel = 140; + else if(channel > 165) + channel = 165; + + //===GET FROM FLASH=== +#ifdef RTK_5G_SUPPORT + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[channel-1]; + pwrlevelHT40_1S_B = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel-1]; + pwrdiffHT40_2S = priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[channel-1]; + pwrdiffHT20 = priv->pmib->dot11RFEntry.pwrdiff5GHT20[channel-1]; + pwrdiffOFDM = priv->pmib->dot11RFEntry.pwrdiff5GOFDM[channel-1]; +#endif + +#ifdef USB_POWER_SUPPORT + printk(">>Flash - 13dBm<<\n"); +#endif + + printk("pwrlevelHT40_1S_A = %d, pwrlevelHT40_1S_B = %d\n", pwrlevelHT40_1S_A, pwrlevelHT40_1S_B); + printk("pwrdiffHT40_2S = %d(0x%02x), pwrdiffHT20 = %d(0x%02x), pwrdiffOFDM = %d(0x%02x)\n", + pwrdiffHT40_2S, pwrdiffHT40_2S, + pwrdiffHT20, pwrdiffHT20, + pwrdiffOFDM, pwrdiffOFDM); + +#ifdef USB_POWER_SUPPORT + printk(">>Flash - 6dBm<<\n"); + pwrlevelHT40_1S_A_6dB = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[channel]; + pwrlevelHT40_1S_B_6dB = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel]; + pwrdiffHT40_2S_6dB = priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S[channel]; + pwrdiffHT20_6dB = priv->pmib->dot11RFEntry.pwrdiff5GHT20[channel]; + + printk("pwrlevelHT40_1S_A = %d, pwrlevelHT40_1S_B = %d\n", pwrlevelHT40_1S_A_6dB, pwrlevelHT40_1S_B_6dB); + printk("pwrdiffHT40_2S = %d(0x%02x), pwrdiffHT20 = %d(0x%02x)\n", + pwrdiffHT40_2S_6dB, pwrdiffHT40_2S_6dB, + pwrdiffHT20_6dB, pwrdiffHT20_6dB); +#endif + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) + { + printk("92D-DMDP WLAN1, Set pwrlevelHT40_1S_A = pwrlevelHT40_1S_B\n"); + if (phyBandSelect & PHY_BAND_5G) + { + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel-1]; + } + else + { + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[channel-1]; + } +#ifdef USB_POWER_SUPPORT + if (phyBandSelect & PHY_BAND_5G) + { + pwrlevelHT40_1S_A_6dB= priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel]; + } + else + { + pwrlevelHT40_1S_A_6dB= priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel-1]; + } +#endif + } +#endif + + channel = ori_channel; + + + //===POWER BY RATE=== + printk(">>Power By Rate Table<<\n"); + + pg_tbl_idx = 0; + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (priv->pshare->is_40m_bw == 0) { + if (channel<=99) + pg_tbl_idx = AN_20_CH_36_64; + else if (channel<=148) + pg_tbl_idx = AN_20_CH_100_140; + else + pg_tbl_idx = AN_20_CH_149_165; + } else { + if (channel<=99) + pg_tbl_idx = AN_40_CH_36_64; + else if (channel<=148) + pg_tbl_idx = AN_40_CH_100_140; + else + pg_tbl_idx = AN_40_CH_149_165; + } + } +#ifdef MP_TEST + //In Noraml Driver mode, and if mib 'pwr_by_rate' = 0 >> Use default power by rate table + if( (priv->pshare->rf_ft_var.mp_specific == 0) && (priv->pshare->rf_ft_var.pwr_by_rate == 0) ) + pg_tbl_idx = BGN_2040_ALL; +#endif +#endif + + printk("pg_tbl_idx = %d\n", pg_tbl_idx); + + Read_PG_File(priv, PHYREG_PG, pg_tbl_idx, + MCSTxAgcOffset_A, MCSTxAgcOffset_B, + OFDMTxAgcOffset_A, OFDMTxAgcOffset_B, + CCKTxAgc_A, CCKTxAgc_B); + + printk("MCSTxAgcOffset_A - "); + for(tmp = 0; tmp <16; tmp ++) + printk("%02x ", MCSTxAgcOffset_A[tmp]); + printk("\n"); + + printk("MCSTxAgcOffset_B - "); + for(tmp = 0; tmp <16; tmp ++) + printk("%02x ", MCSTxAgcOffset_B[tmp]); + printk("\n"); + + printk("OFDMTxAgcOffset_A - "); + for(tmp = 0; tmp <8; tmp ++) + printk("%02x ", OFDMTxAgcOffset_A[tmp]); + printk("\n"); + + printk("OFDMTxAgcOffset_B - "); + for(tmp = 0; tmp <8; tmp ++) + printk("%02x ", OFDMTxAgcOffset_B[tmp]); + printk("\n"); + + printk("CCKTxAgc_A - "); + for(tmp = 0; tmp <4; tmp ++) + printk("%02x ", CCKTxAgc_A[tmp]); + printk("\n"); + + printk("CCKTxAgc_B - "); + for(tmp = 0; tmp <4; tmp ++) + printk("%02x ", CCKTxAgc_B[tmp]); + printk("\n"); + +#ifdef ADD_TX_POWER_BY_CMD + check_txpwr_by_cmd(priv, MCSTxAgcOffset_A, MCSTxAgcOffset_B, + OFDMTxAgcOffset_A, OFDMTxAgcOffset_B, CCKTxAgc_A, CCKTxAgc_B); +#endif + + //===Count FLASH + POWER BY RATE=== + + printk(">>Tx Power - Power By Rate<<\n"); + + dump_ofdm_mcs0(priv, defValue, pwrlevelHT40_1S_A, pwrlevelHT40_1S_B, + pwrdiffHT40_2S, pwrdiffHT20, pwrdiffOFDM, + pwrlevelHT40_1S_A_6dB, pwrlevelHT40_1S_B_6dB, + pwrdiffHT40_2S_6dB, pwrdiffHT20_6dB, + MCSTxAgcOffset_A, MCSTxAgcOffset_B, OFDMTxAgcOffset_A, OFDMTxAgcOffset_B, phyBandSelect); + + +#ifdef TXPWR_LMT + //===BAND EDGE LIMIT=== + if (priv->pshare->rf_ft_var.disable_txpwrlmt) + continue; + + printk(">>Band Edge Limit Table<<\n"); + + tmp = ch2idx(channel); + + txpwr_lmt_CCK = priv->pshare->ch_pwr_lmtCCK[tmp]; + txpwr_lmt_OFDM = priv->pshare->ch_pwr_lmtOFDM[tmp]; + tgpwr_CCK = priv->pshare->ch_tgpwr_CCK[tmp]; + tgpwr_OFDM = priv->pshare->ch_tgpwr_OFDM[tmp]; + + printk("txpwr_lmt_CCK = %d tgpwr_CCK = %d\n", txpwr_lmt_CCK, tgpwr_CCK); + printk("txpwr_lmt_OFDM = %d tgpwr_OFDM = %d\n", txpwr_lmt_OFDM, tgpwr_OFDM); + + if (priv->pshare->is_40m_bw == 0) + { + txpwr_lmt_HT1S = priv->pshare->ch_pwr_lmtHT20_1S[tmp]; + txpwr_lmt_HT2S = priv->pshare->ch_pwr_lmtHT20_2S[tmp]; + tgpwr_HT1S = priv->pshare->ch_tgpwr_HT20_1S[tmp]; + tgpwr_HT2S = priv->pshare->ch_tgpwr_HT20_2S[tmp]; + + printk("txpwr_lmt_HT1S_20M = %d tgpwr_HT1S_20M = %d\n", txpwr_lmt_HT1S, tgpwr_HT1S); + printk("txpwr_lmt_HT2S_20M = %d tgpwr_HT2S_20M = %d\n", txpwr_lmt_HT2S, tgpwr_HT2S); + } + else + { + txpwr_lmt_HT1S = priv->pshare->ch_pwr_lmtHT40_1S[tmp]; + txpwr_lmt_HT2S = priv->pshare->ch_pwr_lmtHT40_2S[tmp]; + tgpwr_HT1S = priv->pshare->ch_tgpwr_HT40_1S[tmp]; + tgpwr_HT2S = priv->pshare->ch_tgpwr_HT40_2S[tmp]; + + printk("txpwr_lmt_HT1S_40M = %d tgpwr_HT1S_40M = %d\n", txpwr_lmt_HT1S, tgpwr_HT1S); + printk("txpwr_lmt_HT2S_40M = %d tgpwr_HT2S_40M = %d\n", txpwr_lmt_HT2S, tgpwr_HT2S); + } + + //===Count FLASH + min{POWER BY RATE, LIMIT}=== + if((txpwr_lmt_OFDM == 0) && (txpwr_lmt_HT1S == 0) && (txpwr_lmt_HT1S == 0)) + { + printk("No Band Edge Limit for this channel=%d\n", channel); + continue; + } + + if (!txpwr_lmt_OFDM || !tgpwr_OFDM){ + max_idx=255; + }else{ + max_idx = (txpwr_lmt_OFDM - tgpwr_OFDM); + } + + for (i=0; i<=7; i++) { + OFDMTxAgcOffset_A[i] = POWER_MIN_CHECK(OFDMTxAgcOffset_A[i], max_idx); + OFDMTxAgcOffset_B[i] = POWER_MIN_CHECK(OFDMTxAgcOffset_B[i], max_idx); + } + + if (!txpwr_lmt_HT1S || !tgpwr_HT1S){ + max_idx = 255; + }else{ + max_idx = (txpwr_lmt_HT1S - tgpwr_HT1S); + } + + for (i=0; i<=7; i++) { + MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(MCSTxAgcOffset_A[i], max_idx); + MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(MCSTxAgcOffset_B[i], max_idx); + } + + if (!txpwr_lmt_HT2S || !tgpwr_HT2S){ + max_idx = 255; + }else{ + max_idx = (txpwr_lmt_HT2S - tgpwr_HT2S); + } + + for (i=8; i<=15; i++) { + MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(MCSTxAgcOffset_A[i], max_idx); + MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(MCSTxAgcOffset_B[i], max_idx); + } + + dump_ofdm_mcs0(priv, defValue, pwrlevelHT40_1S_A, pwrlevelHT40_1S_B, + pwrdiffHT40_2S, pwrdiffHT20, pwrdiffOFDM, + pwrlevelHT40_1S_A_6dB, pwrlevelHT40_1S_B_6dB, + pwrdiffHT40_2S_6dB, pwrdiffHT20_6dB, + MCSTxAgcOffset_A, MCSTxAgcOffset_B, OFDMTxAgcOffset_A, OFDMTxAgcOffset_B, phyBandSelect); + +#endif + + } + } + +} + +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) +void reg_dump_8812(struct rtl8192cd_priv *priv) +{ + panic_printk("Initial Gain, Sensitivity:\n"); + panic_printk(" 0xC50: 0x%02x\n", RTL_R8(0xc50)); + panic_printk(" 0xE50: 0x%02x\n", RTL_R8(0xe50)); + panic_printk(" 0xC30: 0x%02x\n", RTL_R8(0xc30)); + panic_printk(" 0xC87: 0x%02x\n", RTL_R8(0xc87)); + panic_printk(" 0xA0A: 0x%02x\n", RTL_R8(0xa0a)); + + panic_printk("EDCA para:\n"); + panic_printk(" VO(0x%03x): 0x%08x\n", EDCA_VO_PARA, RTL_R32(EDCA_VO_PARA)); + panic_printk(" VI(0x%03x): 0x%08x\n", EDCA_VI_PARA, RTL_R32(EDCA_VI_PARA)); + panic_printk(" BE(0x%03x): 0x%08x\n", EDCA_BE_PARA, RTL_R32(EDCA_BE_PARA)); + panic_printk(" BK(0x%03x): 0x%08x\n", EDCA_BK_PARA, RTL_R32(EDCA_BK_PARA)); + + panic_printk("Tx power:\n"); + panic_printk(" A_CCK11_CCK1(0x%03x): 0x%08x\n", rTxAGC_A_CCK11_CCK1_JAguar, RTL_R32(rTxAGC_A_CCK11_CCK1_JAguar)); + panic_printk(" A_Rate18_06(0x%03x): 0x%08x\n", rTxAGC_A_Ofdm18_Ofdm6_JAguar, RTL_R32(rTxAGC_A_Ofdm18_Ofdm6_JAguar)); + panic_printk(" A_Rate54_24(0x%03x): 0x%08x\n", rTxAGC_A_Ofdm54_Ofdm24_JAguar, RTL_R32(rTxAGC_A_Ofdm54_Ofdm24_JAguar)); + panic_printk(" A_Mcs03_Mcs00(0x%03x): 0x%08x\n", rTxAGC_A_MCS3_MCS0_JAguar, RTL_R32(rTxAGC_A_MCS3_MCS0_JAguar)); + panic_printk(" A_Mcs07_Mcs04(0x%03x): 0x%08x\n", rTxAGC_A_MCS7_MCS4_JAguar, RTL_R32(rTxAGC_A_MCS7_MCS4_JAguar)); + panic_printk(" A_Mcs11_Mcs08(0x%03x): 0x%08x\n", rTxAGC_A_MCS11_MCS8_JAguar, RTL_R32(rTxAGC_A_MCS11_MCS8_JAguar)); + panic_printk(" A_Mcs15_Mcs12(0x%03x): 0x%08x\n", rTxAGC_A_MCS15_MCS12_JAguar, RTL_R32(rTxAGC_A_MCS15_MCS12_JAguar)); + panic_printk(" A_Nss13_Nss10(0x%03x): 0x%08x\n", rTxAGC_A_Nss1Index3_Nss1Index0_JAguar, RTL_R32(rTxAGC_A_Nss1Index3_Nss1Index0_JAguar)); + panic_printk(" A_Nss17_Nss14(0x%03x): 0x%08x\n", rTxAGC_A_Nss1Index7_Nss1Index4_JAguar, RTL_R32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar)); + panic_printk(" A_Nss21_Nss18(0x%03x): 0x%08x\n", rTxAGC_A_Nss2Index1_Nss1Index8_JAguar, RTL_R32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar)); + panic_printk(" A_Nss25_Nss22(0x%03x): 0x%08x\n", rTxAGC_A_Nss2Index5_Nss2Index2_JAguar, RTL_R32(rTxAGC_A_Nss2Index5_Nss2Index2_JAguar)); + panic_printk(" A_Nss29_Nss26(0x%03x): 0x%08x\n", rTxAGC_A_Nss2Index9_Nss2Index6_JAguar, RTL_R32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar)); + panic_printk(" B_CCK11_CCK1(0x%03x): 0x%08x\n", rTxAGC_B_CCK11_CCK1_JAguar, RTL_R32(rTxAGC_B_CCK11_CCK1_JAguar)); + panic_printk(" B_Rate18_06(0x%03x): 0x%08x\n", rTxAGC_B_Ofdm18_Ofdm6_JAguar, RTL_R32(rTxAGC_B_Ofdm18_Ofdm6_JAguar)); + panic_printk(" B_Rate54_24(0x%03x): 0x%08x\n", rTxAGC_B_Ofdm54_Ofdm24_JAguar, RTL_R32(rTxAGC_B_Ofdm54_Ofdm24_JAguar)); + panic_printk(" B_Mcs03_Mcs00(0x%03x): 0x%08x\n", rTxAGC_B_MCS3_MCS0_JAguar, RTL_R32(rTxAGC_B_MCS3_MCS0_JAguar)); + panic_printk(" B_Mcs07_Mcs04(0x%03x): 0x%08x\n", rTxAGC_B_MCS7_MCS4_JAguar, RTL_R32(rTxAGC_B_MCS7_MCS4_JAguar)); + panic_printk(" B_Mcs11_Mcs08(0x%03x): 0x%08x\n", rTxAGC_B_MCS11_MCS8_JAguar, RTL_R32(rTxAGC_B_MCS11_MCS8_JAguar)); + panic_printk(" B_Mcs15_Mcs12(0x%03x): 0x%08x\n", rTxAGC_B_MCS15_MCS12_JAguar, RTL_R32(rTxAGC_B_MCS15_MCS12_JAguar)); + panic_printk(" B_Nss13_Nss10(0x%03x): 0x%08x\n", rTxAGC_B_Nss1Index3_Nss1Index0_JAguar, RTL_R32(rTxAGC_B_Nss1Index3_Nss1Index0_JAguar)); + panic_printk(" B_Nss17_Nss14(0x%03x): 0x%08x\n", rTxAGC_B_Nss1Index7_Nss1Index4_JAguar, RTL_R32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar)); + panic_printk(" B_Nss21_Nss18(0x%03x): 0x%08x\n", rTxAGC_B_Nss2Index1_Nss1Index8_JAguar, RTL_R32(rTxAGC_B_Nss2Index1_Nss1Index8_JAguar)); + panic_printk(" B_Nss25_Nss22(0x%03x): 0x%08x\n", rTxAGC_B_Nss2Index5_Nss2Index2_JAguar, RTL_R32(rTxAGC_B_Nss2Index5_Nss2Index2_JAguar)); + panic_printk(" B_Nss29_Nss26(0x%03x): 0x%08x\n", rTxAGC_B_Nss2Index9_Nss2Index6_JAguar, RTL_R32(rTxAGC_B_Nss2Index9_Nss2Index6_JAguar)); + return; +} +#endif + +static void reg_dump(struct rtl8192cd_priv *priv, char *str) +{ + int i, j, len; + unsigned char tmpbuf[100]; + +#ifdef CONFIG_SDIO_HCI + if (strcmp(str, "sdio_local") == 0) { + dump_sdio_local_reg(priv); + return; + } + if (strcmp(str, "sdio_cccr") == 0) { + dump_sdio_cccr(priv); + return; + } +#endif + +//_TXPWR_REDEFINE +//_TXPWR_REDEFINE ?? Dump Too much will cause hang up ?? + panic_printk("[Channel-%03d]", priv->pmib->dot11RFEntry.dot11channel); + + if (priv->pshare->CurrentChannelBW == 0) + { + panic_printk(" - 20M BW"); + } + else + { + if (priv->pshare->CurrentChannelBW == 1) + panic_printk(" - 40M BW "); + else + panic_printk(" - 80M BW "); + + if (priv->pshare->offset_2nd_chan == 1) + panic_printk("BELOW"); + else if (priv->pshare->offset_2nd_chan == 2) + panic_printk("ABOVE"); + else if (priv->pshare->offset_2nd_chan == 0) + panic_printk("DONT CARE"); + } + + panic_printk("\n"); + +#ifdef _DEBUG_RTL8192CD_ + + if (strcmp(str, "tx") == 0) + { + printk("\n==2G L 1-3==\n"); + txpwr_dump(priv, 1, 1); + printk("\n==2G M 4-9==\n"); + txpwr_dump(priv, 4, 4); + printk("\n==2G H 10-14==\n"); + txpwr_dump(priv, 10, 10); + + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) { + printk("\n==5G G1_L 36-45==\n"); + txpwr_dump(priv, 36, 36); + printk("\n==5G G1_M 46-55==\n"); + txpwr_dump(priv, 46, 46); + printk("\n==5G G1_H 56-99==\n"); + txpwr_dump(priv, 56, 56); + printk("\n==5G G2_L 100-113==\n"); + txpwr_dump(priv, 100, 100); + printk("\n==5G G2_M 114-127==\n"); + txpwr_dump(priv, 114, 114); + printk("\n==5G G2_H 128-148==\n"); + txpwr_dump(priv, 128, 128); + printk("\n==5G G3_L 149-154==\n"); + txpwr_dump(priv, 149, 149); + printk("\n==5G G3_M 155-160==\n"); + txpwr_dump(priv, 155, 155); + printk("\n==5G G3_H 161-165==\n"); + txpwr_dump(priv, 161, 161); + } +#endif + + return; + } + + + if (strcmp(str, "tx-2g") == 0) + { + printk("\n==2G L LIST==\n"); + txpwr_dump(priv, 1, 3); + printk("\n==2G M LIST==\n"); + txpwr_dump(priv, 4, 9); + printk("\n==2G H LIST==\n"); + txpwr_dump(priv, 10, 14); + + return; + } + + if (strcmp(str, "tx-5gl") == 0) + { +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) { + printk("\n==5G G1_L LIST==\n"); + txpwr_dump(priv, 36, 45); + printk("\n==5G G1_M LIST==\n"); + txpwr_dump(priv, 46, 55); + printk("\n==5G G1_H LIST==\n"); + txpwr_dump(priv, 56, 66); //99 > 66, Because dump too much will cause reboot + } else +#endif + { + printk("NOT 92D, NOT support 5G\n"); + } + + return; + } + + if (strcmp(str, "tx-5gm") == 0) + { +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) { + printk("\n==5G G2_L LIST==\n"); + txpwr_dump(priv, 100, 113); + printk("\n==5G G2_M LIST==\n"); + txpwr_dump(priv, 114, 127); + printk("\n==5G G2_H LIST==\n"); + txpwr_dump(priv, 128, 148); + } else +#endif + { + printk("NOT 92D, NOT support 5G\n"); + } + + return; + } + + if (strcmp(str, "tx-5gh") == 0) + { + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) { + printk("\n==5G G3_L LIST==\n"); + txpwr_dump(priv, 149, 154); + printk("\n==5G G3_M LIST==\n"); + txpwr_dump(priv, 155, 160); + printk("\n==5G G3_H LIST==\n"); + txpwr_dump(priv, 161, 165); + } else +#endif + { + printk("NOT 92D, NOT support 5G\n"); + } + + return; + } +#endif + + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (strcmp(str, "check") == 0) + { + return; + } + +#endif + + if (strcmp(str, "all") != 0) { + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + reg_dump_8812(priv); + return; + } +#endif + panic_printk("Initial Gain, Sensitivity:\n"); + panic_printk(" 0xC50: 0x%02x\n", RTL_R8(0xc50)); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + panic_printk(" 0xC58: 0x%02x\n", RTL_R8(0xc58)); +#endif + panic_printk(" 0xC30: 0x%02x\n", RTL_R8(0xc30)); + panic_printk(" 0xC87: 0x%02x\n", RTL_R8(0xc87)); + panic_printk(" 0xA0A: 0x%02x\n", RTL_R8(0xa0a)); + panic_printk("EDCA para:\n"); + panic_printk(" VO(0x%03x): 0x%08x\n", EDCA_VO_PARA, RTL_R32(EDCA_VO_PARA)); + panic_printk(" VI(0x%03x): 0x%08x\n", EDCA_VI_PARA, RTL_R32(EDCA_VI_PARA)); + panic_printk(" BE(0x%03x): 0x%08x\n", EDCA_BE_PARA, RTL_R32(EDCA_BE_PARA)); + panic_printk(" BK(0x%03x): 0x%08x\n", EDCA_BK_PARA, RTL_R32(EDCA_BK_PARA)); + panic_printk("Tx power:\n"); + panic_printk(" A_CCK1_Mcs32(0x%03x): 0x%08x\n", rTxAGC_A_CCK1_Mcs32, RTL_R32(rTxAGC_A_CCK1_Mcs32)); + panic_printk(" B_CCK5_1_Mcs32(0x%03x): 0x%08x\n", rTxAGC_B_CCK5_1_Mcs32, RTL_R32(rTxAGC_B_CCK5_1_Mcs32)); + panic_printk(" A_CCK11_2_B_CCK11(0x%03x): 0x%08x\n", rTxAGC_A_CCK11_2_B_CCK11, RTL_R32(rTxAGC_A_CCK11_2_B_CCK11)); + panic_printk(" A_Rate18_06(0x%03x): 0x%08x\n", rTxAGC_A_Rate18_06, RTL_R32(rTxAGC_A_Rate18_06)); + panic_printk(" A_Rate54_24(0x%03x): 0x%08x\n", rTxAGC_A_Rate54_24, RTL_R32(rTxAGC_A_Rate54_24)); + panic_printk(" A_Mcs03_Mcs00(0x%03x): 0x%08x\n", rTxAGC_A_Mcs03_Mcs00, RTL_R32(rTxAGC_A_Mcs03_Mcs00)); + panic_printk(" A_Mcs07_Mcs04(0x%03x): 0x%08x\n", rTxAGC_A_Mcs07_Mcs04, RTL_R32(rTxAGC_A_Mcs07_Mcs04)); + panic_printk(" A_Mcs11_Mcs08(0x%03x): 0x%08x\n", rTxAGC_A_Mcs11_Mcs08, RTL_R32(rTxAGC_A_Mcs11_Mcs08)); + panic_printk(" A_Mcs15_Mcs12(0x%03x): 0x%08x\n", rTxAGC_A_Mcs15_Mcs12, RTL_R32(rTxAGC_A_Mcs15_Mcs12)); + panic_printk(" B_Rate18_06(0x%03x): 0x%08x\n", rTxAGC_B_Rate18_06, RTL_R32(rTxAGC_B_Rate18_06)); + panic_printk(" B_Rate54_24(0x%03x): 0x%08x\n", rTxAGC_B_Rate54_24, RTL_R32(rTxAGC_B_Rate54_24)); + panic_printk(" B_Mcs03_Mcs00(0x%03x): 0x%08x\n", rTxAGC_B_Mcs03_Mcs00, RTL_R32(rTxAGC_B_Mcs03_Mcs00)); + panic_printk(" B_Mcs07_Mcs04(0x%03x): 0x%08x\n", rTxAGC_B_Mcs07_Mcs04, RTL_R32(rTxAGC_B_Mcs07_Mcs04)); + panic_printk(" B_Mcs11_Mcs08(0x%03x): 0x%08x\n", rTxAGC_B_Mcs11_Mcs08, RTL_R32(rTxAGC_B_Mcs11_Mcs08)); + panic_printk(" B_Mcs15_Mcs12(0x%03x): 0x%08x\n", rTxAGC_B_Mcs15_Mcs12, RTL_R32(rTxAGC_B_Mcs15_Mcs12)); + return; + } + + panic_printk("\nMAC Registers:\n"); + for (i=0; i<0x1000; i+=0x10) { + len = sprintf((char *)tmpbuf, "%03X\t", i); + for (j=i; jpshare->phw->NumTotalRFPath; i++) { + for (j = 0; j <= rf_reg_offset; j++) { + len += sprintf((char *)(tmpbuf+len), "%d%02x %05x", + i, j, PHY_QueryRFReg(priv, i, j, bMask20Bits, 1)); + + if (j && !((j+1)%4)) { + panic_printk("%s\n", (char *)tmpbuf); + len = 0; + } else + len += sprintf((char *)(tmpbuf+len), " "); + } + panic_printk("%s\n", (len) ? (char *)tmpbuf : ""); + } + } +} +#endif // _IOCTL_DEBUG_CMD_ + + +/* + * data: byte 0 ~ byte 11 is mac addr + * if byte 12 & 13 is "no", will NOT send disasoc request + * else will send disasoc request + */ +int del_sta(struct rtl8192cd_priv *priv, unsigned char *data) +{ + struct stat_info *pstat; + unsigned char macaddr[MACADDRLEN], tmpbuf[3]; +#ifndef SMP_SYNC + unsigned long flags; +#endif + DOT11_DISASSOCIATION_IND Disassociation_Ind; + int i, send_disasoc=1; + + if (!netif_running(priv->dev)) + return 0; + + for(i=0; istate & WIFI_WDS) { + DEBUG_INFO("%02X%02X%02X%02X%02X%02X is an WDS peer, dismissed\n", + macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]); + + return 0; + } +#endif + + return del_station(priv, pstat, send_disasoc); +} + + +static int write_eeprom(struct rtl8192cd_priv *priv, unsigned char *data) +{ + return -1; +} + + +static int read_eeprom(struct rtl8192cd_priv *priv, unsigned char *data) +{ + return -1; +} + + +static void get_sta_info(struct rtl8192cd_priv *priv, sta_info_2_web *pInfo, int size +#ifdef RTK_WOW + ,unsigned int wakeup_on_wlan +#endif + ) +{ + struct list_head *phead, *plist; + struct stat_info *pstat; + struct net_device *dev = priv->dev; + int i; + + memset((char *)pInfo, '\0', sizeof(sta_info_2_web)*size); + + phead = &priv->asoc_list; + if (!netif_running(dev) || list_empty(phead)) + return; + + plist = phead; + while (((plist = asoc_list_get_next(priv, plist)) != phead) && (size > 0)) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + + if ((pstat->state & WIFI_ASOC_STATE) && + ((pstat->expire_to > 0) +#ifdef RTK_WOW + || wakeup_on_wlan +#endif + ) +#ifdef CONFIG_RTK_MESH + && (!(GET_MIB(priv)->dot1180211sInfo.mesh_enable) || isSTA(pstat)) // STA ONLY +#endif +#ifdef RTK_WOW + && (!wakeup_on_wlan || pstat->is_rtk_wow_sta) +#endif +#ifdef WDS + && !(pstat->state & WIFI_WDS) +#endif + ) { + pInfo->aid = pstat->aid; + memcpy(pInfo->addr, pstat->hwaddr, 6); + pInfo->tx_packets = pstat->tx_pkts; + pInfo->rx_packets = pstat->rx_pkts; + pInfo->expired_time = pstat->expire_to * 100; /*1s to 10ms unit*/ + pInfo->flags = STA_INFO_FLAG_ASOC; + if (!list_empty(&pstat->sleep_list)) + pInfo->flags |= STA_INFO_FLAG_ASLEEP; + pInfo->TxOperaRate = pstat->current_tx_rate; + pInfo->RxOperaRate = pstat->rx_rate; +#ifdef TLN_STATS + pInfo->enc_type = pstat->dot11KeyMapping.dot11Privacy; + + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) { + if (pstat->wpa_sta_info->RSNEnabled & PSK_WPA2) + pInfo->auth_type = STATS_PSK_WPA2; + else + pInfo->auth_type = STATS_PSK_WPA; + } else if (IEEE8021X_FUN && ((pstat->dot11KeyMapping.dot11Privacy != _WEP_40_PRIVACY_) && + (pstat->dot11KeyMapping.dot11Privacy != _WEP_104_PRIVACY_))) { + if (pstat->enterpise_wpa_info == STATS_ETP_WPA2) + pInfo->auth_type = STATS_ETP_WPA2; + else + pInfo->auth_type = STATS_ETP_WPA; + } else { + if (pstat->AuthAlgrthm) + pInfo->auth_type = STATS_AUTH_SHARE; + else + pInfo->auth_type = STATS_AUTH_OPEN; + } +#endif + pInfo->rssi = pstat->rssi; + pInfo->link_time = pstat->link_time; + pInfo->tx_fail = pstat->tx_fail; + pInfo->tx_bytes = pstat->tx_bytes; + pInfo->rx_bytes = pstat->rx_bytes; + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + pInfo->network = WIRELESS_11A; + else if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + if (!isErpSta(pstat)) + pInfo->network = WIRELESS_11B; + else { + pInfo->network = WIRELESS_11G; + for (i=0; inetwork |= WIRELESS_11B; + break; + } + } + } + } + else // 11B only + pInfo->network = WIRELESS_11B; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + if (pstat->ht_cap_len) { + pInfo->network |= WIRELESS_11N; + if (pstat->ht_current_tx_info & TX_USE_40M_MODE) + pInfo->ht_info |= TX_USE_40M_MODE; + if (pstat->ht_current_tx_info & TX_USE_SHORT_GI) + pInfo->ht_info |= TX_USE_SHORT_GI; + } + } + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) + { +#ifdef CONFIG_RTL_8812_SUPPORT + if(pstat ->vht_cap_len) { + if(pstat->tx_bw == HT_CHANNEL_WIDTH_80) + pInfo->ht_info |= TX_USE_80M_MODE; + if (pstat->ht_current_tx_info & TX_USE_40M_MODE) + pInfo->ht_info |= TX_USE_40M_MODE; + if (pstat->ht_current_tx_info & TX_USE_SHORT_GI) + pInfo->ht_info |= TX_USE_SHORT_GI; + + pInfo->acTxOperaRate = query_vht_rate(pstat); + pInfo->network |= WIRELESS_11AC; + } +#endif + } + pInfo++; + size--; + } + } +} + +#ifdef _SINUX_ +/* + * return 1: if mac is wlan client MAC, 0: if not. + */ +int rtl8192cd_check_wlan_mac(char *wlan_ifname, unsigned char *mac) +{ + struct net_device *net_dev; + struct rtl8192cd_priv *priv; + + struct list_head *phead, *plist; + struct stat_info *pstat; + int ret = 0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + if (mac == NULL) + return 0; + + net_dev = dev_get_by_name(wlan_ifname); + if (net_dev == NULL) + { + printk("rtl8192cd_check_wlan_mac(): can not get dev %s\n", wlan_ifname); + return 0; + } + priv = (struct rtl8192cd_priv *)net_dev -> priv; + + phead = &priv->asoc_list; + if (!netif_running(net_dev) || list_empty(phead)){ + dev_put(net_dev); + return 0; + } + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + if ((pstat->state & WIFI_ASOC_STATE) && (pstat->expire_to > 0) +#ifdef WDS + && !(pstat->state & WIFI_WDS) +#endif + ) { + if (memcmp(mac, pstat->hwaddr,6) == 0) { + ret = 1; + break; + } + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + + dev_put(net_dev); + + return ret; +} + +typedef struct tag_ASSOCIATE_TABLE{ + char mac[6]; + /* err: 0: no error 1: error */ + char err; +}ASSOCIATE_TABLE, *PASSOCIATE_TABLE; + +int rtl8192cd_getMacTable(char *wlan_ifname, ASSOCIATE_TABLE *mac_table, int table_num) +{ + struct net_device *net_dev; + struct rtl8192cd_priv *priv; + + struct list_head *phead, *plist; + struct stat_info *pstat; + int ret = 0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + + net_dev = dev_get_by_name(wlan_ifname); + if (net_dev == NULL) + { + printk("rtl8192cd_check_wlan_mac(): can not get dev %s\n", wlan_ifname); + return -1; + } + priv = (struct rtl8192cd_priv *)net_dev -> priv; + + + phead = &priv->asoc_list; + if (!netif_running(net_dev) || list_empty(phead)) + { + dev_put(net_dev); + return -1; + } + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead && table_num > 0 ) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + if ((pstat->state & WIFI_ASOC_STATE) && (pstat->expire_to > 0) +#ifdef WDS + && !(pstat->state & WIFI_WDS) +#endif + ) { + memcpy(mac_table->mac, pstat->hwaddr, 6); + mac_table ++; + table_num --; + ret ++; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + + dev_put(net_dev); + + return ret; +} + +#endif + +static void get_bss_info(struct rtl8192cd_priv *priv, bss_info_2_web *pBss) +{ + struct net_device *dev = priv->dev; +#ifdef CLIENT_MODE + struct stat_info *pstat; +#endif + + memset(pBss, '\0', sizeof(bss_info_2_web)); + + if (!netif_running(dev)) { + pBss->state = STATE_DISABLED; + return; + } + + if (priv->pmib->miscEntry.func_off) { + pBss->state = STATE_DISABLED; + return; + } + + if (OPMODE & WIFI_AP_STATE) + pBss->state = STATE_STARTED; +#ifdef CLIENT_MODE + else { + switch (JOIN_RES) { + case STATE_Sta_No_Bss: + pBss->state = STATE_SCANNING; + break; + case STATE_Sta_Bss: + if (IEEE8021X_FUN) { + pstat = get_stainfo(priv, BSSID); + if (pstat == NULL) + return; + if (pstat->ieee8021x_ctrlport) + pBss->state = STATE_CONNECTED; + else + pBss->state = STATE_WAITFORKEY; + } + else + pBss->state = STATE_CONNECTED; + break; + case STATE_Sta_Ibss_Active: + pBss->state = STATE_CONNECTED; + break; + case STATE_Sta_Ibss_Idle: + pBss->state = STATE_STARTED; + break; + default: + pBss->state = STATE_SCANNING; + break; + } + } +#endif + + if (priv->pmib->dot11StationConfigEntry.autoRate) + pBss->txRate = find_rate(priv, NULL, 1, 0); + else + pBss->txRate = get_rate_from_bit_value(priv->pmib->dot11StationConfigEntry.fixedTxRate); + memcpy(pBss->ssid, SSID, SSID_LEN); + pBss->ssid[SSID_LEN] = '\0'; + if (OPMODE & WIFI_SITE_MONITOR) + pBss->channel = priv->site_survey->ss_channel; + else + pBss->channel = priv->pmib->dot11RFEntry.dot11channel; + + if (pBss->state == STATE_STARTED || pBss->state == STATE_CONNECTED) { +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv) && (OPMODE & WIFI_AP_STATE)) + if (IS_DRV_OPEN(priv)) + memcpy(pBss->bssid, priv->pmib->dot11Bss.bssid, MACADDRLEN); + else + memset(pBss->bssid, '\0', MACADDRLEN); + else +#endif + memcpy(pBss->bssid, BSSID, MACADDRLEN); +#ifdef CLIENT_MODE + if (JOIN_RES == STATE_Sta_Bss) { + pstat = get_stainfo(priv, BSSID); + if (pstat) { + pBss->rssi = pstat->rssi; + pBss->sq = pstat->sq; + } + } +#endif + } + else { + memset(pBss->bssid, '\0', MACADDRLEN); + if (pBss->state == STATE_DISABLED) + pBss->channel = 0; + } +} + + +#ifdef WDS +static int get_wds_info(struct rtl8192cd_priv *priv, web_wds_info *pWds) +{ + int i, j=0; + struct stat_info *pstat; + + memset(pWds, '\0', NUM_WDS*sizeof(web_wds_info)); + + for (j=0, i=0; ipmib->dot11WdsInfo.wdsNum; i++) { + if (!netif_running(priv->wds_dev[i])) + continue; + + memcpy(pWds[j].addr, priv->pmib->dot11WdsInfo.entry[i].macAddr, 6); + + pstat = get_stainfo(priv, pWds[j].addr); + if(NULL == pstat) + continue; + + pWds[j].state = STATE_WDS_ACTIVE; + pWds[j].tx_packets = pstat->tx_pkts; + pWds[j].rx_packets = pstat->rx_pkts; + pWds[j].tx_errors = pstat->tx_fail; + pWds[j].TxOperaRate = pstat->current_tx_rate; + j++; + } + + return (sizeof(web_wds_info)*j); +} +#endif // WDS + + +static int set_sta_txrate(struct rtl8192cd_priv *priv, struct _wlan_sta_rateset *rate_set) +{ + struct stat_info *pstat; + + if (!netif_running(priv->dev)) + return 0; + + pstat = get_stainfo(priv, rate_set->mac); + if (pstat == NULL) + return 0; + if (!(pstat->state & WIFI_ASOC_STATE)) + return 0; + if (priv->pmib->dot11StationConfigEntry.autoRate) { + DEBUG_INFO("Auto rate turned on. Can't set rate\n"); + return 0; + } + + pstat->current_tx_rate = rate_set->txrate; + return 1; +} + + +#ifdef MICERR_TEST +static int issue_mic_err_pkt(struct rtl8192cd_priv *priv, unsigned char *cli_mac) +{ + struct sk_buff *skb; + struct wlan_ethhdr_t *pethhdr; + + skb = dev_alloc_skb(64); + if (skb != NULL) { + skb->dev = priv->dev; + pethhdr = (struct wlan_ethhdr_t *)(skb->data); + if (!(OPMODE & WIFI_STATION_STATE)) { + unsigned char null_mac[]={0,0,0,0,0,0}; + if (!memcmp(cli_mac, null_mac, MACADDRLEN)) { + printk("Usage: iwpriv wlanx mic_error [cli_mac_addr]\n"); + return 0; + } + printk("%s() Send MIC error packet to %02X:%02X:%02X:%02X:%02X:%02X\n",__func__,cli_mac[0],cli_mac[1],cli_mac[2],cli_mac[3],cli_mac[4],cli_mac[5]); + memcpy(pethhdr->daddr, cli_mac, MACADDRLEN); + } else { + printk("Send MIC error packet to AP...\n"); + memcpy(pethhdr->daddr, BSSID, MACADDRLEN); + } + memcpy(pethhdr->saddr, GET_MY_HWADDR, MACADDRLEN); + pethhdr->type = 0x888e; + + memset(skb->data+WLAN_ETHHDR_LEN, 0xa5, 32); + skb_put(skb, WLAN_ETHHDR_LEN+32); + + priv->micerr_flag = 1; + if (rtl8192cd_start_xmit(skb, priv->dev)) + rtl_kfree_skb(priv, skb, _SKB_TX_); + } else { + printk("Can't allocate sk_buff\n"); + } + return 0; +} + + +static int issue_mic_rpt_pkt(struct rtl8192cd_priv *priv, unsigned char *data) +{ + struct sk_buff *skb; + struct wlan_ethhdr_t *pethhdr; + int format; + unsigned char pattern[] = {0x01, 0x03, 0x00, 0x5f, 0xfe, 0x0d, 0x00, 0x00}; + + if (!(OPMODE & WIFI_STATION_STATE)) { + printk("Fail: not in client mode\n"); + return 0; + } + + if (!strcmp(data, "xp")) + format = 1; + else if (!strcmp(data, "funk")) + format = 2; + else { + printk("Usage: iwpriv wlanx mic_report {xp | funk}\n"); + return 0; + } + + printk("Send MIC report (%s format) to AP...\n", (format==1)? "XP":"Funk"); + skb = dev_alloc_skb(64); + if (skb != NULL) + { + skb->dev = priv->dev; + pethhdr = (struct wlan_ethhdr_t *)(skb->data); + memcpy(pethhdr->daddr, BSSID, MACADDRLEN); + memcpy(pethhdr->saddr, GET_MY_HWADDR, MACADDRLEN); + pethhdr->type = 0x888e; + + if (format == 2) + pattern[5] = 0x0f; + memcpy(skb->data+WLAN_ETHHDR_LEN, pattern, sizeof(pattern)); + skb_put(skb, WLAN_ETHHDR_LEN+sizeof(pattern)); + + if (rtl8192cd_start_xmit(skb, priv->dev)) + rtl_kfree_skb(priv, skb, _SKB_TX_); + } + else + { + printk("Can't allocate sk_buff\n"); + } + return 0; +} +#endif // MICERR_TEST + + +#if defined(D_ACL) || defined(MICERR_TEST) //mesh related + +static int iwpriv_atoi(struct rtl8192cd_priv *priv, unsigned char *data, unsigned char *buf, int len) +{ + unsigned char tmpbuf[20] = {'\0'}; + unsigned char ascii_addr[12] = {'\0'}; + unsigned char hex_addr[6] = {'\0'}; + int i=0; + + if( (len - 1) == MACADDRLEN ){ //user send 6 byte mac address + if(ioctl_copy_from_user(buf, (void *)data, len)) + return -1; + return 0; + } + else if( (len - 1) == MACADDRLEN*2 ){ //user send 12 byte mac string + if(ioctl_copy_from_user(tmpbuf, (void *)data, len)) + return -1; + + strcpy(ascii_addr, tmpbuf); + strcpy(buf+MACADDRLEN,tmpbuf); + + for(i = 0; i < MACADDRLEN*2; i++){ + if( '0' <= ascii_addr[i] && ascii_addr[i] <= '9') + ascii_addr[i] -= 48; + else if( 'A' <= ascii_addr[i] && ascii_addr[i] <= 'F' ) + ascii_addr[i] -= 55; + else if( 'a' <= ascii_addr[i] && ascii_addr[i] <= 'f' ) + ascii_addr[i] -= 87; + printk("%d", ascii_addr[i]); + } + + for(i = 0; i < MACADDRLEN*2; i+=2) + hex_addr[i>>1] = (ascii_addr[i] << 4) | (ascii_addr[i+1]); + + memcpy(buf,hex_addr,MACADDRLEN); + _DEBUG_INFO("in iwpriv_atoi function\n"); + return 0; + } + else{ + _DEBUG_ERR("Wrong input format\n"); + return -1; + } + +} +#endif + +static int acl_add_cmd(struct rtl8192cd_priv *priv, unsigned char *data, int len) +{ + struct list_head *phead, *plist, *pnewlist; + struct wlan_acl_node *paclnode; + unsigned char macaddr[6]; + int ret = 0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + +#ifdef D_ACL //tsananiu (mesh related) + unsigned char tmpbuf[20] = {'\0'}; + unsigned char tmp_add[12] = {'\0'}; + int i; + if(ioctl_copy_from_user(tmpbuf, (void *)data, len)) + return -1; + + if( (len - 1) == 6 ){ //user send 6 byte mac address + for(i = 0; i < 6; i++) + macaddr[i] = tmpbuf[i]; + } + else if( (len - 1) == 12 ){ //user send 12 byte mac string + + strcpy(tmp_add, tmpbuf); + + for(i = 0; i < 12; i++){ + if( '0' <= tmp_add[i] && tmp_add[i] <= '9') + tmp_add[i] -= 48; + else if( 'A' <= tmp_add[i] && tmp_add[i] <= 'F' ) + tmp_add[i] -= 55; + else if( 'a' <= tmp_add[i] && tmp_add[i] <= 'f' ) + tmp_add[i] -= 87; + printk("%d", tmp_add[i]); + } + + for(i = 0; i < 12; i+=2){ + macaddr[i>>1] = (tmp_add[i] << 4) | (tmp_add[i+1]); + } + } + + else{ + printk("Wrong input format\n"); + } + DEBUG_INFO("in add function\n"); + len = 6; +#else + if (ioctl_copy_from_user((void *)macaddr, (void *)data, 6)) + return -1; +#endif//tsananiu// + + // first of all, check if this address has been in acl_list; + phead = &priv->wlan_acl_list; + + if (phead->next == NULL) { + panic_printk("[WARN] Interface not initialized yet!\n"); + return -1; + } + + DEBUG_INFO("Adding %02X:%02X:%02X:%02X:%02X:%02X to acl_table\n", + macaddr[0],macaddr[1],macaddr[2], + macaddr[3],macaddr[4],macaddr[5]); + + SMP_LOCK_ACL(flags); + + plist = phead->next; + + while(plist != phead) + { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + + if (!(memcmp((void *)macaddr, paclnode->addr, 6))) + { + DEBUG_INFO("mac-addr %02X%02X%02X%02X%02X%02X has been in acl_list\n", + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); + ret = 0; + goto exit; + } + } + + if (list_empty(&priv->wlan_aclpolllist)) + { + DEBUG_INFO("acl_poll is full!\n"); + ret = -1; + goto exit; + } + + pnewlist = (priv->wlan_aclpolllist.next); + list_del_init(pnewlist); + + paclnode = list_entry(pnewlist, struct wlan_acl_node, list); + + memcpy((void *)paclnode->addr, macaddr, 6); + + if (len == 6) + paclnode->mode = (unsigned char)priv->pmib->dot11StationConfigEntry.dot11AclMode; + else + paclnode->mode = data[6]; + + list_add_tail(pnewlist, phead); + +exit: + SMP_UNLOCK_ACL(flags); + + return ret; +} + + +static int acl_remove_cmd(struct rtl8192cd_priv *priv, unsigned char *data, int len) +{ + struct list_head *phead, *plist; + struct wlan_acl_node *paclnode; + unsigned char macaddr[6]; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + if (data) { +#ifdef D_ACL //tsananiu (mesh related) + int i; + unsigned char tmpbuf[20] = {'\0'}; + unsigned char tmp_add[12] = {'\0'}; + + if(ioctl_copy_from_user(tmpbuf, (void *)data, len)) + return -1; + + if( (len - 1) == 6 ){ //user send 6 byte mac address + for(i = 0; i < 6; i++) + macaddr[i] = tmpbuf[i]; + } + else if( (len - 1) == 12 ){ //user send 12 byte mac string + + strcpy(tmp_add, tmpbuf); + + for(i = 0; i < 12; i++){ + if( '0' <= tmp_add[i] && tmp_add[i] <= '9') + tmp_add[i] -= 48; + else if( 'A' <= tmp_add[i] && tmp_add[i] <= 'F' ) + tmp_add[i] -= 55; + else if( 'a' <= tmp_add[i] && tmp_add[i] <= 'f' ) + tmp_add[i] -= 87; + DEBUG_INFO("%d", tmp_add[i]); + } + + for(i = 0; i < 12; i+=2){ + macaddr[i>>1] = (tmp_add[i] << 4) | (tmp_add[i+1]); + } + } + else{ + DEBUG_ERR("Wrong input format\n"); + return -1; + } + DEBUG_INFO("in remove function\n"); + DEBUG_INFO("%02X:%02X:%02X:%02X:%02X:%02X\n", + macaddr[0],macaddr[1],macaddr[2], + macaddr[3],macaddr[4],macaddr[5]); + //len = 6; +#else + if (ioctl_copy_from_user((void *)macaddr, (void *)data, 6)) + return -1; + + DEBUG_INFO("Delete %X:%X:%X:%X:%X:%X to acl_table\n", + macaddr[0],macaddr[1],macaddr[2], + macaddr[3],macaddr[4],macaddr[5]); +#endif//tsananiu// + } + + phead = &priv->wlan_acl_list; + + if (phead->next == NULL) { + panic_printk("[WARN] Interface not initialized yet!\n"); + return -1; + } + + if (list_empty(phead)) // nothing to remove + return 0; + + SMP_LOCK_ACL(flags); + + plist = phead->next; + + while(plist != phead) + { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + + if (!(memcmp((void *)macaddr, paclnode->addr, 6))) + { + list_del_init(&paclnode->list); + list_add_tail(&paclnode->list, &priv->wlan_aclpolllist); + goto exit; + } + } + + if (data) { + DEBUG_INFO("Delete %02X:%02X:%02X:%02X:%02X:%02X is not in acl_table\n", + macaddr[0],macaddr[1],macaddr[2], + macaddr[3],macaddr[4],macaddr[5]); + } +exit: + SMP_UNLOCK_ACL(flags); + + return 0; +} + + +static int acl_query_cmd(struct rtl8192cd_priv *priv, unsigned char *data, u16 length) +{ + struct list_head *phead, *plist; + struct wlan_acl_node *paclnode; + unsigned char *tmp_buf; + int len = 0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + phead = &priv->wlan_acl_list; + + if (list_empty(phead) || !IS_DRV_OPEN(priv)) // nothing to remove + return 0; + + tmp_buf = (unsigned char *)kmalloc(length, GFP_KERNEL); + if (NULL == tmp_buf) + return -1; + + SMP_LOCK_ACL(flags); + + plist = phead->next; + + while (plist != phead) { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + + if ((len + MACADDRLEN) > length) + break; + + memcpy(&tmp_buf[len], paclnode->addr, MACADDRLEN); + len += MACADDRLEN; + } + + SMP_UNLOCK_ACL(flags); + + if (len) { + if (ioctl_copy_to_user((void *)data, tmp_buf, len)) { + len = -1; + } + } + kfree(tmp_buf); + + return len; +} + + +static int acl_clear_cmd(struct rtl8192cd_priv *priv) +{ + struct list_head *phead, *plist; + struct wlan_acl_node *paclnode; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + phead = &priv->wlan_acl_list; + + if (phead->next == NULL) { + panic_printk("[WARN] Interface not initialized yet!\n"); + return -1; + } + + if (list_empty(phead)) // nothing to remove + return 0; + + SMP_LOCK_ACL(flags); + + plist = phead->next; + + while(plist != phead) + { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + list_del_init(&paclnode->list); + list_add_tail(&paclnode->list, &priv->wlan_aclpolllist); + } + + SMP_UNLOCK_ACL(flags); + + return 0; +} + + +#if defined(CONFIG_RTK_MESH) && defined(_MESH_ACL_ENABLE_) +// Copy from acl_add_cmd +static int mesh_acl_add_cmd(struct rtl8192cd_priv *priv, unsigned char *data, int len) +{ + struct list_head *phead, *plist, *pnewlist; + struct wlan_acl_node *paclnode; + unsigned char macaddr[MACADDRLEN]; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + if (ioctl_copy_from_user((void *)macaddr, (void *)data, MACADDRLEN)) + return -1; + + // first of all, check if this address has been in acl_list; + phead = &priv->mesh_acl_list; + + DEBUG_INFO("Adding %X:%X:%X:%X:%X:%X to mesh_acl_table\n", + macaddr[0],macaddr[1],macaddr[2], + macaddr[3],macaddr[4],macaddr[5]); + + SMP_LOCK_MESH_ACL(flags); + + plist = phead->next; + while(plist != phead) + { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + + if (!(memcmp((void *)macaddr, paclnode->addr, MACADDRLEN))) + { + DEBUG_INFO("mac-addr %02X%02X%02X%02X%02X%02X has been in mesh_acl_list\n", + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); + goto exit; + } + } + + if (list_empty(&priv->mesh_aclpolllist)) + { + DEBUG_INFO("mesh_acl_poll is full!\n"); + goto exit; + } + + pnewlist = (priv->mesh_aclpolllist.next); + list_del_init(pnewlist); + + paclnode = list_entry(pnewlist, struct wlan_acl_node, list); + + memcpy((void *)paclnode->addr, macaddr, MACADDRLEN); + + if (len == 6) + paclnode->mode = (unsigned char)priv->pmib->dot1180211sInfo.mesh_acl_mode; + else + paclnode->mode = data[6]; + + list_add_tail(pnewlist, phead); + +exit: + SMP_UNLOCK_MESH_ACL(flags); + + return 0; +} + + +// Copy from acl_remove_cmd +static int mesh_acl_remove_cmd(struct rtl8192cd_priv *priv, unsigned char *data, int len) +{ + struct list_head *phead, *plist; + struct wlan_acl_node *paclnode; + unsigned char macaddr[MACADDRLEN]; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + if (data) { + if (ioctl_copy_from_user((void *)macaddr, (void *)data, 6)) + return -1; + + DEBUG_INFO("Delete %X:%X:%X:%X:%X:%X to mesh_acl_table\n", + macaddr[0],macaddr[1],macaddr[2], + macaddr[3],macaddr[4],macaddr[5]); + } + + phead = &priv->mesh_acl_list; + + if (list_empty(phead)) // nothing to remove + return 0; + + SMP_LOCK_MESH_ACL(flags); + + plist = phead->next; + while(plist != phead) + { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + + if (!(memcmp((void *)macaddr, paclnode->addr, MACADDRLEN))) + { + list_del_init(&paclnode->list); + list_add_tail(&paclnode->list, &priv->mesh_aclpolllist); + goto exit; + } + } + + if (data) { + DEBUG_INFO("Delete %X:%X:%X:%X:%X:%X is not in mesh_acl_table\n", + macaddr[0],macaddr[1],macaddr[2], + macaddr[3],macaddr[4],macaddr[5]); + } +exit: + SMP_UNLOCK_MESH_ACL(flags); + + return 0; +} + + +// Copy from acl_query_cmd +static int mesh_acl_query_cmd(struct rtl8192cd_priv *priv, unsigned char *data, u16 length) +{ + struct list_head *phead, *plist; + struct wlan_acl_node *paclnode; + unsigned char *tmp_buf; + int len = 0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + phead = &priv->mesh_acl_list; + + if (list_empty(phead)) // nothing to remove + return 0; + + tmp_buf = (unsigned char *)kmalloc(length, GFP_KERNEL); + if (NULL == tmp_buf) + return -1; + + SMP_LOCK_MESH_ACL(flags); + + plist = phead->next; + while (plist != phead) { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + + if ((len + MACADDRLEN) > length) + break; + + memcpy(&tmp_buf[len], paclnode->addr, MACADDRLEN); + len += MACADDRLEN; + } + + SMP_UNLOCK_MESH_ACL(flags); + + if (len) { + if (ioctl_copy_to_user((void *)data, tmp_buf, len)) { + len = -1; + } + } + kfree(tmp_buf); + + return len; +} +#endif // CONFIG_RTK_MESH && _MESH_ACL_ENABLE_ + + +static void get_misc_data(struct rtl8192cd_priv *priv, struct _misc_data_ *pdata) +{ + memset(pdata, '\0', sizeof(struct _misc_data_)); + + pdata->mimo_tr_hw_support = GET_HW(priv)->MIMO_TR_hw_support; + + // get number of tx path + if (get_rf_mimo_mode(priv) == MIMO_1T2R) + pdata->mimo_tr_used = 1; + else if (get_rf_mimo_mode(priv) == MIMO_1T1R) + pdata->mimo_tr_used = 1; + else if (get_rf_mimo_mode(priv) == MIMO_2T2R) + pdata->mimo_tr_used = 2; + else if (get_rf_mimo_mode(priv) == MIMO_3T3R) + pdata->mimo_tr_used = 3; + else if (get_rf_mimo_mode(priv) == MIMO_4T4R) + pdata->mimo_tr_used = 4; + else // MIMO_2T4R + pdata->mimo_tr_used = 2; + + return; +} + + +#ifdef AUTO_TEST_SUPPORT +static void rtl8192cd_SSReq_AutoTest(struct rtl8192cd_priv *priv) +{ + INT8 ret = 0; + //int i1; + //static int timerbeinit = 0; +#if defined(MBSSID) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + if (IS_VAP_INTERFACE(priv)) + return; +#endif + + #ifdef CONFIG_RTK_MESH + if((priv->auto_channel &0x30) && timer_pending(&priv->ss_timer)) + ret = -2; + else + #endif + if (!netif_running(priv->dev) || priv->ss_req_ongoing) + ret = -1; + else + ret = 0; + + if (!ret) // now, let's start site survey + { + priv->ss_ssidlen = 0; + DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=0\n", (char *)__FUNCTION__); + priv->ss_req_ongoing = 1; + start_clnt_ss(priv); + }else{ + return ; + } +} + + +#ifdef CLIENT_MODE + +#if defined(WIFI_WPAS) || defined(RTK_NL80211) +int check_bss_encrypt(struct rtl8192cd_priv *priv) +#else +static int check_bss_encrypt(struct rtl8192cd_priv *priv) +#endif +{ + +#if defined(CONFIG_RTL_WAPI_SUPPORT) + // WAPI + if (priv->pmib->wapiInfo.wapiType!=wapiDisable + || priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_WAPI_SMS4_) + { + if ((priv->pmib->dot11Bss.capability & BIT(4)) == 0) + return FAIL; + else if (priv->pmib->dot11Bss.t_stamp[0] != SECURITY_INFO_WAPI) + return FAIL; + else + return SUCCESS; + } else +#endif + // no encryption + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == 0) + { + if (priv->pmib->dot11Bss.capability & BIT(4)) + return FAIL; + else + return SUCCESS; + } + // legacy encryption + else if (!IEEE8021X_FUN && + ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_))) + { + if ((priv->pmib->dot11Bss.capability & BIT(4)) == 0) + return FAIL; + else if (priv->pmib->dot11Bss.t_stamp[0] != 0) + return FAIL; + else + return SUCCESS; + } + // WPA/WPA2 + else + { + if ((priv->pmib->dot11Bss.capability & BIT(4)) == 0) + return FAIL; + else if (priv->pmib->dot11Bss.t_stamp[0] == 0) + return FAIL; + else if ((priv->pmib->dot11RsnIE.rsnie[0] == _RSN_IE_1_) && + ((priv->pmib->dot11Bss.t_stamp[0] & 0x0000ffff) == 0)) + return FAIL; + else if ((priv->pmib->dot11RsnIE.rsnie[0] == _RSN_IE_2_) && + ((priv->pmib->dot11Bss.t_stamp[0] & 0xffff0000) == 0)) + return FAIL; + else + return SUCCESS; + } +} + + +static int rtl8192cd_join_AutoTest(struct rtl8192cd_priv *priv, unsigned char *data) +{ + INT8 ret = 0; + + char tmpbuf[33]; + char SSID123[34]; + int ix = 0; + int found = 0 ; + + + if (!netif_running(priv->dev)) + ret = 2; + else if (priv->ss_req_ongoing) + ret = 1; + else + ret = 0; + + if (ioctl_copy_from_user((void *)SSID123, (void *)data, 33) ){ + panic_printk("copy SSID fail!!\n"); + return -1; + } + + for(ix = 0 ; ix < priv->site_survey->count_backup ; ix++){ + if(!strcmp(priv->site_survey->bss_backup[ix].ssid , SSID123 )){ + found = 1; + break; + } + } + + if(found == 0){ + ret = 3; + panic_printk("SSID not found!!\n"); + }else{ + memcpy((void *)&(priv->pmib->dot11Bss) , + (void *)&priv->site_survey->bss_backup[ix] , sizeof(struct bss_desc)); + } + + + + + if (!ret) // now, let's start site survey and join + { + + +#ifdef WIFI_SIMPLE_CONFIG + if (priv->pmib->wscEntry.wsc_enable && (priv->pmib->dot11Bss.bsstype&WIFI_WPS)) { + priv->pmib->dot11Bss.bsstype &= ~WIFI_WPS; + priv->wps_issue_join_req = 1; + } + else +#endif + { + if (check_bss_encrypt(priv) == FAIL) { + DEBUG_INFO("Encryption mismatch!\n"); + ret = 2; + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + else + return 0; + } + } + + if ((priv->pmib->dot11Bss.ssidlen == 0) || (priv->pmib->dot11Bss.ssid[0] == '\0')) { + DEBUG_INFO("Join to a hidden AP!\n"); + ret = 2; + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + else + return 0; + } + +#ifdef UNIVERSAL_REPEATER + disable_vxd_ap(GET_VXD_PRIV(priv)); +#endif + + memcpy(tmpbuf, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + tmpbuf[priv->pmib->dot11Bss.ssidlen] = '\0'; + DEBUG_INFO("going to join bss: %s\n", tmpbuf); + + panic_printk("going to join bss: %s\n", tmpbuf); + + memcpy(SSID2SCAN, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + SSID2SCAN_LEN = priv->pmib->dot11Bss.ssidlen; + + SSID_LEN = SSID2SCAN_LEN; + memcpy(SSID, SSID2SCAN, SSID_LEN); + memset(BSSID, 0, MACADDRLEN); + +// button 2009.05.21 +// derive PSK with slelected SSID +#ifdef INCLUDE_WPA_PSK + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) + derivePSK(priv); +#endif + JOIN_REQ_ONGOING_VAL(1); + AUTH_MODE_RETRY_VAL(0); + start_clnt_join(priv); + } + + return 0; +} +#endif +#endif + +#ifdef CONFIG_8814_AP_MAC_VERI + +typedef enum _AP_MAC_VERI_8814_ +{ + RetryLimitForEachMACID = 0x0, + LowestRetryRateInTXDESC, + ReleaseOnePKtbyMACIDeep, + AppendMACHeaderForRXpacket, + HWAutoAppendMACID, + HWSupportPowerStatedetect, +}AP_MAC_VERI_8814,*PAP_MAC_VERI_8814; + +EXTERN void rtl88XX_tx_dsr(unsigned long task_priv); + +#ifdef CONFIG_8814_AP_MAC_VERI + +void RX_MAC_Verify_8814(struct rtl8192cd_priv *priv,unsigned char * pframe,struct rx_frinfo *pfrinfo) +{ + PRX_DESC_88XX prx_desc; + int i; + unsigned char macid; + unsigned char pattern[5] = {0x55,0x55,0x55,0x55,0x55}; + unsigned char pwrBit; + unsigned char payLoadMACid; + + prx_desc = (PRX_DESC_88XX)(pframe-sizeof(RX_DESC_88XX)); + + if(!memcmp((pframe+pfrinfo->hdr_len),&pattern,5)) + { + + // printk("pfrinfo->macid = %x \n",pfrinfo->macid); + // Verify MACID + + payLoadMACid = *(pframe+pfrinfo->hdr_len+6); + #ifdef HW_FILL_MACID + if(pfrinfo->macid == payLoadMACid) + { + printk("macID %x match \n",pfrinfo->macid); + } + else + { + printk("macID mismatch HW = %x SW = %x \n",pfrinfo->macid,payLoadMACid); + + for(i=0 ; ihdr_len ;i++ ) + { + printk("%02X ",*(pframe+i)); + + if((i%16)==15) + { + printk("\n"); + } + } + printk("\n\n"); + } + #endif //HW_FILL_MACID + + #ifdef HW_DETEC_POWER_STATE + // Verify PowerBit + pwrBit = GetPwrMgt(pframe); + static u4Byte seq = 0; + static u4Byte carrier = 0; + + + if(pfrinfo->macid != 0x7F) { + //if(priv->testResult == true) + { + if(priv->pwrState[pfrinfo->macid]!= pwrBit) { + priv->pwrStateCnt[pfrinfo->macid]++; + + RTL_W16(0x1a2,RTL_R16(0x1a2)+1); + RTL_W16(0x1a6,priv->pwrStateCnt[pfrinfo->macid]); + RTL_W8(0x1a5,pwrBit); + + if(GetSequence(pframe)== 0xfff) + { + priv->sw_Carrier++; + carrier++; + } + + printk("[%s][%d]power state change at MACID:%x, Seq:%x, Cur Pwr:%x Cnt = %x HW pwr =%x HW seq=%x carrier =%x \n" + ,__FUNCTION__,__LINE__,pfrinfo->macid,GetSequence(pframe),pwrBit,priv->pwrStateCnt[pfrinfo->macid],RTL_R8(0x1140),priv->hw_seq[0],carrier); + + // comapre HW&SW pwrBit,seq,Cnt + if(pwrBit!= priv->pshare->HWPwroldState[pfrinfo->macid]) + { + + printk("MACID%x PwrStatus error SW=%x HW=%x \n",pfrinfo->macid,pwrBit,priv->pshare->HWPwroldState[pfrinfo->macid]); + priv->testResult = false; + } + + if(priv->pwrStateCnt[pfrinfo->macid]!= priv->pwrStateHWCnt[pfrinfo->macid]) + { + + printk("MACID%x PwrStatus CNT error SW=%x HW=%x \n", + pfrinfo->macid,priv->pwrStateCnt[pfrinfo->macid],priv->pwrStateHWCnt[pfrinfo->macid]); + priv->testResult = false; + } + + if(GetSequence(pframe)!= priv->hw_seq[pfrinfo->macid]) + { + printk("MACID%x Sequence error SW=%x HW=%x sw_Carrier =%x hw_Carrier =%x \n", + pfrinfo->macid,GetSequence(pframe),priv->hw_seq[0],priv->sw_Carrier,priv->hw_Carrier); + priv->testResult = false; + } + + if(priv->test_seq_MACID == pfrinfo->macid) + { +// if(GetSequence(pframe) < priv->hw_seq[pfrinfo->macid]) + if(GetSequence(pframe)!= priv->hw_seq[pfrinfo->macid]) + { + printk("MACID%x Sequence error SW=%x HW=%x \n", + pfrinfo->macid,GetSequence(pframe),priv->hw_seq[pfrinfo->macid]); + priv->testResult = false; + } + else + { + printk("MACID%x Sequence pass \n",pfrinfo->macid); + } + } + + priv->test_seq_MACID = pfrinfo->macid+1; + + if(priv->test_seq_MACID == 127) + priv->test_seq_MACID = 0; + + RTL_W8(0x1150,priv->test_seq_MACID); + printk("MACID%x PASS CNT = %x \n",pfrinfo->macid,priv->pwrStateCnt[pfrinfo->macid]); + } + else + { + printk("MACID%x No change \n",pfrinfo->macid); + } + } + priv->pwrState[pfrinfo->macid] = pwrBit; + // compare seq number + }else { + printk("[%x][%d]MacId can't Read \n",__FUNCTION__,__LINE__); + } + + #endif // #ifdef HW_DETEC_POWER_STATE + + } +} + +#endif // #ifdef CONFIG_8814_AP_MAC_VERI + + +static void issue_Test_NullData(struct rtl8192cd_priv *priv,unsigned char macID,unsigned char type) +{ + struct wifi_mib *pmib; +// unsigned char hwaddr[6] = {0x22,0x22,0x33,0x44,0x55,0x66}; + unsigned char hwaddr[6] = {0x00,0x11,0x11,0x11,0x11,0x11}; + unsigned char pattern[5] = {0x55,0x55,0x55,0x55,0x55}; + unsigned char *pbuf; + unsigned char i; + unsigned char pattern_len = 10; + DECLARE_TXINSN(txinsn); + + pmib = GET_MIB(priv); + txinsn.retry = pmib->dot11OperationEntry.dot11ShortRetryLimit; + //hwaddr = pmib->dot11OperationEntry.hwaddr; + + //printk("issue_Test_NullData type = %x \n",type); + + txinsn.q_num = type; + // if txinsn.q_num = MGNT_QUEUE, test data retry + // else test RTS retry + + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.fixed_rate = 1; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + { + printk("txinsn.phdr NULL \n"); + goto send_fail; + } + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (txinsn.pframe == NULL) + { + printk("txinsn.pframe NULL \n"); + goto send_fail; + } + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + SetFrameSubType(txinsn.phdr, WIFI_DATA); + SetToDs(txinsn.phdr); + //SetMData(txinsn.phdr); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + txinsn.hdr_len = 0; // hdr_len add in check_desc + + memcpy(pbuf,pattern,5); + for(i=5 ;i < pattern_len ;i++) + { + pbuf[i] = macID; + + } + txinsn.fr_len = pattern_len; + priv->macID_temp = macID; + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + { + printk("MACID = %x tx ok \n",macID); + return; + } + else + { + printk("MACID = %x tx fail \n",macID); + } + +send_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); +} + +int APmacTestFunction_8814(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned char *val[10]; + int i=0, op=0, offset; + char *delim = ","; + unsigned char input; + + + + if (strlen(data) == 0) { + printk("RetryLimitForEachMACID 0x1 downlaod Rsvd page\n"); + printk("LowestRetryRateInTXDESC 0x2: AP offload enable \n"); + + return 0; + } + + for(i=0;i<10;i++) + { + val[i] = kmalloc(10,GFP_ATOMIC); + } + + if(val[0] = strtok(data,delim)) + { + i= 1; + while(val[i]= strtok(NULL,delim)) + { + i++; + } + } + + int mode = 0; + unsigned char RetryLimitNum = 0; + unsigned char lowestRetry = 0; + unsigned char Enable = 0; + unsigned char macIDNum = 0; + unsigned char lowestRate =0; + unsigned char macID; + unsigned char type; + unsigned char tempEn; + + // mode2 + unsigned char option; + unsigned int reg_addr; + unsigned char releaseBit; + + + RTL_W32(0x80, RTL_R32(0x80)|BIT15); + mode = _atoi(val[0],16); + + switch(mode) + { + case RetryLimitForEachMACID: + //RetryLimitTestCmd iwpriv wlan0 apTest 0,enableBit,RetryLimitNum,macIDNum,type + // example iwpriv wlan0 apTest 1,32 + // Test For 128 MACID + + if((!val[1])||(!val[2])||(!val[3])||(!val[4])) { + printk("%s %d CMD : iwpriv wlan0 apTest 0,enableBit,RetryLimitNum,macIDNum,type\n",__FUNCTION__,__LINE__); + return; + } + + // enable=0, in TXDESC + // enable=1, in SRAM + // enable=2, TXESC and SRAM all disable + Enable = _atoi(val[1],10); + RetryLimitNum = _atoi(val[2],10); + macIDNum = _atoi(val[3],10); + type = _atoi(val[4],10); + + // set Rpt buffer + for(macID = 0; macID < macIDNum; macID++) { + + if(Enable==1) { + // set RTY_LMT_EN in SRAM + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LMT_EN, &Enable); + priv->lowestRate_TXDESCen = 0; + } + else if(Enable ==0){ + // default retry = 10 in TXDESC + priv->lowestRate_TXDESCen = 1; + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LOW_RATE_EN, &Enable); + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LMT_EN, &Enable); + } + else if(Enable ==2) { + // retry limit by register + tempEn = 0; + priv->lowestRate_TXDESCen = 0; + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LMT_EN, &tempEn); + } + + // set RetryLimitNum in SRAM + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_DATA_RT_LMT, &RetryLimitNum); + + // TX pkt + issue_Test_NullData(priv,macID,type); + rtl8192cd_tx_dsr((unsigned long)priv); + delay_ms(1*RetryLimitNum); + } + + break; + case LowestRetryRateInTXDESC: + //LowestRetryRateInTXDESC iwpriv wlan0 apTest 1,TXDESC/RPTBuffer,LowestRTYRate,macIDNum,type + // example iwpriv wlan0 apTest 1,0,4,128 (apTest LowestRetryRateInTXDESC/TXDESC/OFDM 12M/ 128 macIDs) + // Test For 128 MACID + + if((!val[1])||(!val[2])||(!val[3])||(!val[4])) { + printk("%s %d CMD : iwpriv wlan0 apTest 1,TXDESC/RPTBuffer,LowestRTYRate,macIDNum,type\n",__FUNCTION__,__LINE__); + return; + } + + Enable = _atoi(val[1],10); + lowestRate = _atoi(val[2],10); + macIDNum = _atoi(val[3],10); + type = _atoi(val[4],10); + + // set Rpt buffer + for(macID = 0; macID < macIDNum; macID++) { + if(Enable==1) { + priv->lowestRate_TXDESCen = 0; + // set lowest rate in SRAM + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LOW_RATE_EN, &Enable); + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LMT_EN, &Enable); + RetryLimitNum = 15; + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_DATA_RT_LMT, &RetryLimitNum); + }else if(Enable==0) { + priv->lowestRate_TXDESCen = 1; + priv->lowestRate = lowestRate; + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LMT_EN, &Enable); + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LOW_RATE_EN, &Enable); + // set lowest rate in TXDESC + }else if(Enable ==2) { + // retry limit by register + tempEn = 0; + priv->lowestRate_TXDESCen = 0; + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LMT_EN, &tempEn); + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTY_LOW_RATE_EN, &tempEn); + } + + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_RTS_RTY_LOW_RATE, &lowestRate); + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_DATA_RTY_LOW_RATE, &lowestRate); + + // TX pkt + issue_Test_NullData(priv,macID,type); + rtl8192cd_tx_dsr((unsigned long)priv); + delay_ms(1*RetryLimitNum); + } + break; + case ReleaseOnePKtbyMACIDeep: + //ReleaseOnePKtbyMACIDeep iwpriv wlan0 apTest 2,Option,MPDU/AMPDU,macIDNum + // example iwpriv wlan0 apTest 2,0,4,128 (apTest LowestRetryRateInTXDESC/TXDESC/OFDM 12M/ 128 macIDs) + // Test For 128 MACID + + if((!val[1])||(!val[2])||(!val[3])) { + printk("%s %d CMD : iwpriv wlan0 apTest 2,Option,MPDU/AMPDU,macIDNum\n",__FUNCTION__,__LINE__); + return; + } + + option = _atoi(val[1],10); + macID = _atoi(val[2],10); + type = _atoi(val[3],10); + reg_addr = 0x1434 + (macID >>5)*4; + releaseBit = macID%32; + switch(option) + { + case 1: + // 1.) MACID Sleep disable, + // 2.) MACID release bit set1, do nothing + for(macID = 0;macID < 128; macID++) + { + reg_addr = 0x1434 + (macID >>5)*4; + releaseBit = macID%32; + + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); + + delay_us(1000); + if(RTL_R32(reg_addr)&BIT(releaseBit)) + { + printk("Test1 fail at MACID:%x\n",macID); + } + } + printk("Test1 finish \n"); + break; + case 2: + for(macID = 0;macID < 128; macID++) + { + // 1.) MACID sleep enable (pause) + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv,1,macID); + // 2.) TX one packet (download) + issue_Test_NullData(priv,macID,0); + // 3.) MACID release one (release) + reg_addr = 0x1434 + (macID >>5)*4; + releaseBit = macID%32; + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); + + // polling 0 (TX done), or fail + + delay_ms(100); + if(RTL_R32(reg_addr)&BIT(releaseBit)) + { + printk("First TX done fail at MACID:%x\n",macID); + } + + + rtl8192cd_tx_dsr((unsigned long)priv); + } + break; + + case 3: + + for(macID = 0;macID < 128; macID++) + { + // 1.) MACID sleep enable (pause) + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv,1,macID); + + reg_addr = 0x1434 + (macID >>5)*4; + releaseBit = macID%32; + + // 2.) MACID release one (release) + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); + + // polling 1 (TX done), or fail + delay_ms(100); + if(!(RTL_R32(reg_addr)&BIT(releaseBit))) + { + printk("TX queue fail at MACID:%x\n",macID); + } + + // 5.) TX one packet (download) + issue_Test_NullData(priv,macID,0); + + delay_ms(50); + // polling 0 (TX done), or fail + if(RTL_R32(reg_addr)&BIT(releaseBit)) + { + printk("Last TX done fail at MACID:%x\n",macID); + } + + rtl8192cd_tx_dsr((unsigned long)priv); + } + break; + case 4: + // TXDESC set 1 + for(macID = 0;macID < 128; macID++) + { + reg_addr = 0x1434 + (macID >>5)*4; + releaseBit = macID%32; + priv->lowestRate_TXDESCen = 1; // TXDESC moredata = 1; + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv,1,macID); + issue_Test_NullData(priv,macID,2); + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 1 + while(RTL_R32(reg_addr)&BIT(releaseBit)) + { + delay_ms(5); + } + issue_Test_NullData(priv,macID,1); + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 1 + + while(RTL_R32(reg_addr)&BIT(releaseBit)) + { + delay_ms(5); + } + + issue_Test_NullData(priv,macID,2); + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 1 + + while(RTL_R32(reg_addr)&BIT(releaseBit)) + { + delay_ms(5); + } + rtl8192cd_tx_dsr((unsigned long)priv); + delay_ms(50); + } + break; + case 5: + // No TXDESC, + // 2.) MACID release one (release) + for(macID = 0;macID < 128; macID++) + { + reg_addr = 0x1434 + (macID >>5)*4; + releaseBit = macID%32; + priv->lowestRate_TXDESCen = 0; // TXDESC moredata = 0; + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv,1,macID); + issue_Test_NullData(priv,macID,1); + issue_Test_NullData(priv,macID,2); + issue_Test_NullData(priv,macID,3); + + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 1 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 1 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 0 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + + issue_Test_NullData(priv,macID,2); + issue_Test_NullData(priv,macID,2); + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 1 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + + issue_Test_NullData(priv,macID,2); + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 1 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 0 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); + rtl8192cd_tx_dsr((unsigned long)priv); + issue_Test_NullData(priv,macID,2); // moreData = 0 + + rtl8192cd_tx_dsr((unsigned long)priv); + delay_ms(50); + } + break; + case 6: + // disable HW_auto_fill_moreData + RTL_W8(0x454,RTL_R8(0x454)&~(BIT2)); + for(macID = 0;macID < 128; macID++) + { + reg_addr = 0x1434 + (macID >>5)*4; + releaseBit = macID%32; + priv->lowestRate_TXDESCen = 0; // TXDESC moredata = 0; + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv,1,macID); + issue_Test_NullData(priv,macID,1); + issue_Test_NullData(priv,macID,2); + issue_Test_NullData(priv,macID,3); + + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 0 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 0 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 0 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + + issue_Test_NullData(priv,macID,2); + issue_Test_NullData(priv,macID,2); + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 0 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + + issue_Test_NullData(priv,macID,2); + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 0 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); // moreData = 0 + while(RTL_R32(reg_addr)&BIT(releaseBit)){delay_ms(5); } + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); + rtl8192cd_tx_dsr((unsigned long)priv); + issue_Test_NullData(priv,macID,2); // moreData = 0 + + rtl8192cd_tx_dsr((unsigned long)priv); + delay_ms(50); + } + break; + case 7: + // pause + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv,1,macID); + break; + case 8: + // download packet + // 5.) TX one packet (download) + issue_Test_NullData(priv,macID,type); + break; + case 9: + // release packet + // 2.) MACID release one (release) + RTL_W32(reg_addr, RTL_R32(reg_addr) | BIT(releaseBit)); + break; + case 10: + // Set AMPDU + tempEn = 1; + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_PKT_TX_ONE_SEL, &tempEn); + break; + default: + printk("%s %d Unkonw option =%x\n",__FUNCTION__,__LINE__,option); + break; + } + + printk("%s %d ReleaseOnePKtbyMACIDeep Test\n",__FUNCTION__,__LINE__); + break; + case AppendMACHeaderForRXpacket: + printk("%s %d AppendMACHeaderForRXpacket Test \n",__FUNCTION__,__LINE__); + break; + case HWAutoAppendMACID: + //HWAutoAppendMACID iwpriv wlan0 apTest 4,macID, + // example iwpriv wlan0 apTest 4,1 + // Test For 128 MACID + + if((!val[1])) { + printk("%s %d CMD : iwpriv wlan0 apTest 1,TXDESC/RPTBuffer,LowestRTYRate,macIDNum,type\n",__FUNCTION__,__LINE__); + return; + } + + macIDNum = _atoi(val[1],10); + RTL_W32(0x6bc, 0x03000000); // set CRC5 buffer addr + // fill mac address + unsigned char hwaddr[6] = {0x00,0x11,0x11,0x11,0x11,0x11}; + unsigned int test; + for(macID = 0;macID < macIDNum;macID++) + { + hwaddr[5]= 0x11 + macID; + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_MAC_ADDRESS, &hwaddr); + GET_HAL_INTERFACE(priv)->SetCRC5ToRPTBufferHandler(priv,CRC5(hwaddr,6), macID,1); + } + + priv->testResult = false; + priv->RXMACIDTestEn = true; + + printk("%s %d HWAutoAppendMACID Test \n",__FUNCTION__,__LINE__); + break; + case HWSupportPowerStatedetect: + if((!val[1])) { + printk("%s %d CMD : iwpriv wlan0 apTest 5,macID\n",__FUNCTION__,__LINE__); + return; + } + + RTL_W32(0x6bc, 0x03000000); // set CRC5 buffer addr + RTL_W32(0x7D4, RTL_R32(0x7D4)|BIT17); // set ps detect enable + priv->test_seq_MACID = 0; + RTL_W32(0x1150,0x0); // set ps seq debug port + priv->testResult = true; + // macIDNum = _atoi(val[1],10); + // RTL_W8(0x1150,macIDNum); + + // priv->test_seq_MACID = macIDNum; + printk("%s %d HWSupportPowerStatedetect Test \n",__FUNCTION__,__LINE__); + break; + case 0xdd: // for verify FAST EDCA + { + /* + * iwpriv wlan0 apTest dd,macID,type,cnt + * iwpriv wlan0 apTest dd,1,2,3 + BK_QUEUE = 1, + BE_QUEUE = 2, + VI_QUEUE = 3, + VO_QUEUE = 4, + */ + unsigned char macID; + unsigned int type; + unsigned int cnt; + unsigned int i; + + if((!val[1])||(!val[2])||(!val[3])) { + printk("%s(%d): CMD: iwpriv wlan0 apTest dd,macID,type,cnt \n", __FUNCTION__, __LINE__); + return; + } + + macID = _atoi(val[1], 10); + type = _atoi(val[2], 10); + cnt = _atoi(val[3], 10); + + for (i = 0; i < cnt; i++) { + issue_Test_NullData(priv, macID, type); + if (i != 0 && i%8 == 0) { + rtl8192cd_tx_dsr((unsigned long)priv); + } + } + rtl8192cd_tx_dsr((unsigned long)priv); + } + break; + case 0xde: + { + /* tx pkt buf 0x18780000 + 0x1b000 = 0x1879B000 */ + /* (0x400[10:0] * 0x80 + 0x18780000)[23:12] */ + /* iwpriv wlan0 apTest de,400,32 */ + /* check 0x41A first */ + unsigned int reg1 = 0; + unsigned int base_reg = 0x8000; + unsigned int value32 = 0, valueA = 0, valueB = 0; + unsigned int num = 0; + unsigned int cur_reg; + + if((!val[1])||(!val[2])) { + printk("%s(%d): CMD: iwpriv wlan0 apTest de,REG_QX_INFO,cnt \n", __FUNCTION__, __LINE__); + return; + } + + reg1 = _atoi(val[1], 16); // ex: 400 + num = _atoi(val[2], 16); + + value32 = RTL_R32(reg1) & 0x7FF; // [10:0] + value32 = value32 * 0x80; + value32 = value32 + 0x18780000; + + valueA = (value32 >> 12) & 0xFFF; + valueB = value32 & 0xFFF; + base_reg = base_reg + valueB; + + printk("0x140: 0x%X\n", valueA); + RTL_W8(0x106, 0x69); + RTL_W32(0x140, valueA); + + printk("print reg:0x%X, num(dw):0x%x \n", base_reg, num); + + for (i = 0; i < num; i++) { + cur_reg = base_reg + 0x4 * i; + value32 = RTL_R32(cur_reg); +#if 0 + printk("%s(%d): cur_reg:%04X, value32:%08X \n", __FUNCTION__, __LINE__, cur_reg, value32); +#else + printk("%08X ", value32); + if (i % 4 == 3) { + printk("\n"); + } +#endif + } + printk("\n"); + } + break; + case 0xEE: + RTL_W8(0x106,0x69); + RTL_W32(0x140,0x780); + + // clear MACID + for(i=0;i<0xFFF;i++) { + RTL_W8(0x8000+i,0); + } + printk("Reset TXPKTBuffer !!! \n"); + return; + case 0xFF: + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, macID, TXRPT_VAR_ALL, NULL); + + for(i=0;i<128;i++) { + priv->pwrState[i] = 0; + priv->pwrHWState[i] = 0; + priv->pwroldHWState[i] = 0; + priv->pwrStateCnt[i] = 0; + priv->pwrStateHWCnt[i] = 0; + priv->hw_seq[i] = 0; + } + + priv->testResult = true; + RTL_W32(0x1140,0x0); + RTL_W32(0x1144,0x0); + RTL_W32(0x1148,0x0); + printk("Reset RPTBuffer !!! \n"); + return; + break; + + default: + printk("%s %d Unkonw operation ! mode=%x\n",__FUNCTION__,__LINE__,mode); + break; + } + } + + + + +#endif //#ifdef CONFIG_8814_AP_MAC_VERI + + +#ifndef CONFIG_RTL_COMAPI_WLTOOLS +static +#endif +int rtl8192cd_ss_req(struct rtl8192cd_priv *priv, unsigned char *data, int len) +{ + INT8 ret = 0; +#ifdef CONFIG_RTK_MESH + // by GANTOE for manual site survey 2008/12/25 + // inserted by Joule for simple channel unification protocol 2009/01/06 + if((priv->auto_channel &0x30) && timer_pending(&priv->ss_timer)) + ret = -2; + else +#endif + if (!netif_running(priv->dev) || priv->ss_req_ongoing) + ret = -1; +#if defined( WIFI_SIMPLE_CONFIG ) && defined(UNIVERSAL_REPEATER) + else if(priv->wsc_ss_delay > 0){ + STADEBUG("reject by wsc_ss_delay\n"); + ret = -3; + } +#endif +#ifdef SMART_REPEATER_MODE + else if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && GET_VXD_PRIV(priv)->ss_req_ongoing) { + STADEBUG("VXD is scanning. Don't site-survey\n"); + ret = -4; + } +#endif +#ifdef CONFIG_RTL_SIMPLE_CONFIG_USE_WPS_BUTTON + else if((priv->simple_config_status>=2) && (priv->pmib->wscEntry.wsc_enable)) + { + STADEBUG("it is get simple profile now, don't switch channel from ioctl\n"); + ret = -5; + } +#endif + else{ + ret = 0; + } + + + if (!ret) // now, let's start site survey + { + priv->ss_ssidlen = 0; + DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=0\n", (char *)__FUNCTION__); + + if (len == 2){ + STADEBUG("Req from WSC\n"); + priv->ss_req_ongoing = SSFROM_WSC; // WiFi-Simple-Config scan-req + #if defined( WIFI_SIMPLE_CONFIG ) && defined(UNIVERSAL_REPEATER) + if(IS_VXD_INTERFACE(priv)){ + if(get_ss_level(priv)==0){ //exist some STA connected to root or VAP + priv->wsc_ss_delay = 5; // SCAN interval , unit is second + } + } + #endif + }else + + { + STADEBUG("req_from_Web\n"); + priv->ss_req_ongoing = 1; //SS req by Web + } + + start_clnt_ss(priv); + } + + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + + return 0; +} + +static int rtl8192cd_autochannel_sel(struct rtl8192cd_priv *priv) +{ + INT8 ret = 0; + + if (!netif_running(priv->dev) || priv->ss_req_ongoing) + ret = -1; + else + ret = 0; + + /* get available channels before ACS */ + get_available_channel(priv); + + if (!ret) // now, let's start site survey + { + priv->ss_ssidlen = 0; + DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=0\n", (char *)__FUNCTION__); + priv->ss_req_ongoing = 1; + priv->auto_channel = 1; + start_clnt_ss(priv); + } + return ret; +} + +static void rtl8192cd_del_all_sta(struct rtl8192cd_priv *priv) +{ + if (OPMODE & WIFI_AP_STATE) { + int i; + for(i = 0; i < NUM_STAT; i++) + { + + if (priv->pshare->aidarray[i] && (priv->pshare->aidarray[i]->used == TRUE) +#ifdef WDS + + && !(priv->pshare->aidarray[i]->station.state & WIFI_WDS) +#endif + ) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (priv != priv->pshare->aidarray[i]->priv) + continue; +#endif + issue_deauth(priv, priv->pshare->aidarray[i]->station.hwaddr, _RSON_DEAUTH_STA_LEAVING_); + } + } + delay_ms(10); + } +} + +static int rtl8192cd_get_ss_status(struct rtl8192cd_priv *priv, unsigned char *data) +{ + UINT8 flags; + INT8 ret = 0; + + if (ioctl_copy_from_user((void *)&flags, (void *)(data), 1)) + return -1; + + if (!netif_running(priv->dev) || priv->ss_req_ongoing) + { + ret = -1; + if (ioctl_copy_to_user((void *)(data), (void *)&ret, 1)) + return -1; + } + else if (flags == 1) + { + ret = priv->site_survey->count_backup; + if (ioctl_copy_to_user((void *)(data), (void *)&ret, 1)) + return -1; + } + else if (flags == 0) + { + ret = priv->site_survey->count_backup; + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + // now we should report data base. + if (ioctl_copy_to_user((void *)(data+4), priv->site_survey->bss_backup, + sizeof(struct bss_desc)*priv->site_survey->count_backup)) + return -1; + } + +#ifdef WIFI_SIMPLE_CONFIG + else if (flags == 2) { // get simple-config scan result, append WSC IE + ret = priv->site_survey->count_backup; + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + // now we should report data base. + if (ioctl_copy_to_user((void *)(data+4), priv->site_survey->wscie_backup, + sizeof(struct wps_ie_info2)*priv->site_survey->count_backup)) + return -1; + } +#endif + + return 0; +} +#ifdef P2P_SUPPORT + +int p2p_get_p2pconnect_state(struct rtl8192cd_priv *priv, unsigned char *data) +{ + struct p2p_state_event p2p_state_event_t; + memset(&p2p_state_event_t , 0 ,sizeof(struct p2p_state_event)); + + if(priv->p2pPtr==NULL) + return -1; + + p2p_state_event_t.p2p_status = P2P_STATE; + + if(P2P_STATE == P2P_S_CLIENT_CONNECTED_DHCPC){ + + P2P_DEBUG("Wlan driver report client is connected\n"); + P2P_DEBUG("Indicate web server to start udhcpc \n\n"); + + P2P_STATE = P2P_S_CLIENT_CONNECTED_DHCPC_done ; // after web rdy get this state ; change it + + }else if(P2P_STATE == P2P_S_preGO2GO_DHCPD){ + + P2P_DEBUG("now is GO mode\n"); + P2P_DEBUG("Indicate web server to start udhcpd ...\n\n"); + P2P_STATE = P2P_S_preGO2GO_DHCPD_done ; // after web rdy get this state ; change it + + }else if(P2P_STATE == P2P_S_back2dev){ + // indicate web server to reset to p2p device mode + P2P_DEBUG("reinit by web server\n"); + P2P_STATE = P2P_S_IDLE; + + } + + if (ioctl_copy_to_user((void *)(data), (void *)&p2p_state_event_t, sizeof(struct p2p_state_event))) + return -1; + + return 0; + +} + +int p2p_get_event_state(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int MethodCase=0; + struct p2p_state_event p2p_state_event_t; + memset(&p2p_state_event_t , 0 ,sizeof(struct p2p_state_event)); + + if(priv->p2pPtr==NULL) + return -1; + + if(P2P_STATE>=P2P_S_PROVI_TX_REQ && P2P_STATE<=P2P_S_NEGO_WAIT_CONF ) + p2p_state_event_t.p2p_status = 4; + else if(P2P_STATE ==P2P_S_CLIENT_CONNECTED_DHCPC || P2P_STATE ==P2P_S_CLIENT_CONNECTED_DHCPC_done) + p2p_state_event_t.p2p_status = 5; + else if(P2P_STATE == P2P_S_preGO2GO_DHCPD || P2P_STATE ==P2P_S_preGO2GO_DHCPD_done) + p2p_state_event_t.p2p_status = 6; + else if(P2P_STATE == P2P_S_back2dev ) + p2p_state_event_t.p2p_status = 7; + else + p2p_state_event_t.p2p_status = P2P_STATE; + + + p2p_state_event_t.p2p_role = P2PMODE; + + if(P2P_EVENT_INDICATE){ + + p2p_state_event_t.p2p_event = P2P_EVENT_INDICATE; + + if(P2P_EVENT_INDICATE == P2P_EVENT_RX_PROVI_REQ) + { + MethodCase = priv->p2pPtr->wsc_method_from_target_dev; + + switch(MethodCase){ + case CONFIG_METHOD_PIN: + case CONFIG_METHOD_DISPLAY: + p2p_state_event_t.p2p_wsc_method = CONFIG_METHOD_DISPLAY; + break; + case CONFIG_METHOD_PBC: + p2p_state_event_t.p2p_wsc_method = CONFIG_METHOD_PBC; + break; + case CONFIG_METHOD_KEYPAD: + p2p_state_event_t.p2p_wsc_method = CONFIG_METHOD_KEYPAD; + break; + } + + } + P2P_EVENT_INDICATE = 0 ; + } + + if (ioctl_copy_to_user((void *)(data), (void *)&p2p_state_event_t, sizeof(struct p2p_state_event))) + return -1; + + return 0; +} + + +int p2p_wps_indicate_state(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + unsigned char flags; + + + printk("(%s %d)\n\n\n",__FUNCTION__,__LINE__); + + + if (ioctl_copy_from_user((void *)&flags, (void *)(data), 1)){ + return -1; + } + + P2P_DEBUG("Report from wscd , WPS is %s\n\n\n", (flags==1?"success":"fail")); + + if(flags == GO_WPS_SUCCESS){ + if(P2PMODE == P2P_PRE_GO) + { + P2P_DEBUG("pre-GO mdoe ;rx Report from wscd ; WPS is done \n\n"); + // mode change + P2PMODE = P2P_TMP_GO ; + + // state change + P2P_STATE = P2P_S_preGO2GO_DHCPD; + + /*build beacon P2P IE ; + when from (Pre go) switch to GO only need change beacon P2P IE*/ + if(P2PMODE == P2P_TMP_GO || P2PMODE == P2P_PRE_GO ) + priv->p2pPtr->p2p_beacon_ie_len = + p2p_build_beacon_ie(priv,priv->p2pPtr->p2p_beacon_ie); + + }else if(P2PMODE == P2P_PRE_CLIENT){ + P2P_DEBUG("Pre-Client mdoe ;Report from wscd ; WPS is done \n\n"); + P2PMODE = P2P_CLIENT ; + } + } + return 0; + +} + +int rtl8192cd_p2p_ss_req(struct rtl8192cd_priv *priv, unsigned char *data, int len) +{ + INT8 ret = 0; + if (!netif_running(priv->dev) || P2P_DISCOVERY ) + ret = -1; + else + ret = 0; + + if (!ret) // now, let's start site survey + { + printk("\n\n trigger P2P_discovery from UI\n"); + + P2P_DISCOVERY = 1; + priv->site_survey->count = 0; + P2P_scan(priv,NULL); + } + + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + + return 0; +} + + + +static int rtl8192cd_p2p_get_ss_status(struct rtl8192cd_priv *priv, unsigned char *data) +{ + UINT8 flags; + INT8 ret = 0; + //int idx ; + if (ioctl_copy_from_user((void *)&flags, (void *)(data), 1)) + return -1; + + if (!netif_running(priv->dev) || P2P_DISCOVERY) + { + ret = -1; + if (ioctl_copy_to_user((void *)(data), (void *)&ret, 1)) + return -1; + } + else if (flags == 1) + { + ret = priv->site_survey->count_backup; + if (ioctl_copy_to_user((void *)(data), (void *)&ret, 1)) + return -1; + } + else if (flags == 0) + { + ret = priv->site_survey->count_backup; + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + // now we should report data base. + + if (ioctl_copy_to_user((void *)(data+4), priv->site_survey->bss_backup, + sizeof(struct bss_desc)*priv->site_survey->count_backup)) + return -1; + } + + + return 0; +} + + +#endif + +#ifdef CLIENT_MODE +static int rtl8192cd_join(struct rtl8192cd_priv *priv, unsigned char *data) +{ + INT8 ret = 0; + char tmpbuf[33]; + + if (!netif_running(priv->dev)) + ret = 2; + else if (priv->ss_req_ongoing) + ret = 1; + else + ret = 0; + + if (!ret) // now, let's start site survey and join + { + if (ioctl_copy_from_user((void *)&(priv->pmib->dot11Bss), (void *)data, sizeof(struct bss_desc))) + return -1; + +#ifdef WIFI_SIMPLE_CONFIG + if (priv->pmib->wscEntry.wsc_enable && (priv->pmib->dot11Bss.bsstype&WIFI_WPS)) { + priv->pmib->dot11Bss.bsstype &= ~WIFI_WPS; + priv->wps_issue_join_req = 1; + } + else +#endif + { + if (check_bss_encrypt(priv) == FAIL) { + DEBUG_INFO("Encryption mismatch!\n"); + ret = 2; + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + else + return 0; + } + } + + if ((priv->pmib->dot11Bss.ssidlen == 0) || (priv->pmib->dot11Bss.ssid[0] == '\0')) { + DEBUG_INFO("Join to a hidden AP!\n"); + ret = 2; + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + else + return 0; + } + +#ifdef UNIVERSAL_REPEATER + disable_vxd_ap(GET_VXD_PRIV(priv)); +#endif + + memcpy(tmpbuf, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + tmpbuf[priv->pmib->dot11Bss.ssidlen] = '\0'; + DEBUG_INFO("going to join bss: %s\n", tmpbuf); + + memcpy(SSID2SCAN, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + SSID2SCAN_LEN = priv->pmib->dot11Bss.ssidlen; + + SSID_LEN = SSID2SCAN_LEN; + memcpy(SSID, SSID2SCAN, SSID_LEN); + memset(BSSID, 0, MACADDRLEN); + +// button 2009.05.21 +// derive PSK with slelected SSID +#ifdef INCLUDE_WPA_PSK + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) + derivePSK(priv); +#endif + + syncMulticastCipher(priv, &priv->pmib->dot11Bss); + + JOIN_REQ_ONGOING_VAL(1); + AUTH_MODE_RETRY_VAL(0); + start_clnt_join(priv); + } + + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + return 0; +} + +#ifdef CONFIG_RTK_MESH +// ==== inserted by GANTOE for site survey 2008/12/25 ==== +// This function might be modifed when the mesh peerlink precedure has been completed +static int rtl8192cd_join_mesh (struct rtl8192cd_priv *priv, unsigned char* meshid, int meshid_len, int channel, int offset, int reset) +{ + int i, ret = -1; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + if(reset == 0) { + for(i = 0; i < priv->site_survey->count; i++) + { + if(!memcmp(meshid, priv->site_survey->bss[i].meshid, meshid_len) && priv->site_survey->bss[i].channel == channel) + break; + } + } + + + if(reset || i < priv->site_survey->count) { + priv->pshare->offset_2nd_chan = reset? priv->pmib->dot11nConfigEntry.dot11n2ndChOffset : offset; + priv->pmib->dot11RFEntry.dot11channel = channel; + SwChnl(priv, channel, priv->pshare->offset_2nd_chan); // in this version, automatically establishing link + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + memcpy(GET_MIB(priv)->dot1180211sInfo.mesh_id, meshid, meshid_len); + GET_MIB(priv)->dot1180211sInfo.mesh_id[meshid_len]=0; + update_beacon(priv); + ret = 0; + } + + RESTORE_INT(flags); + return ret; +} + +// This function might be removed when the mesh peerlink precedure has been completed +static int rtl8192cd_check_mesh_link (struct rtl8192cd_priv *priv, unsigned char* macaddr) +{ + int ret = -1; + unsigned long flags; + struct stat_info *pstat; + struct list_head *phead, *plist, *pprevlist; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK_MESH_MP_HDR(flags); + + phead= &priv->mesh_mp_hdr; + plist = phead->next; + pprevlist = phead; + + while(plist != phead) + { + pstat = list_entry(plist, struct stat_info, mesh_mp_ptr); + if(!memcmp(pstat->hwaddr, macaddr, 6)) + { + ret = 0; + break; + } + plist = plist->next; + pprevlist = plist->prev; + } + + SMP_UNLOCK_MESH_MP_HDR(flags); + RESTORE_INT(flags); + return ret; +} +#endif + +static int rtl8192cd_join_status(struct rtl8192cd_priv *priv, unsigned char *data) +{ + INT8 ret = 0; + + if (!netif_running(priv->dev) || JOIN_REQ_ONGOING) + ret = -1; // pending + else + ret = JOIN_RES; + + if (ioctl_copy_to_user((void *)data, (void *)&ret, 1)) + return -1; + + return 0; +} +#endif // CLIENT_MODE + +#ifdef SUPPORT_TX_MCAST2UNI +#ifndef CONFIG_MSC +static +#endif +void AddDelMCASTGroup2STA(struct rtl8192cd_priv *priv, unsigned char *mac2addr, int add) +{ + int i, free=-1, found=0; + struct stat_info *pstat; + struct list_head *phead, *plist; +#ifdef CONFIG_RTK_MESH + struct proxy_table_entry* pProxyEntry; + struct path_sel_entry *pEntry; +#endif +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + phead = &priv->asoc_list; + if (NULL == phead->next) + return; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + // Search from SA stat list. If found check if mc entry is existed in table + if (((OPMODE & WIFI_AP_STATE) && !memcmp(pstat->hwaddr, mac2addr+6 , 6)) +#ifdef CLIENT_MODE + || !(OPMODE & WIFI_AP_STATE) +#endif + ) { + +#ifdef WDS + if ((OPMODE & WIFI_AP_STATE) && (pstat->state & WIFI_WDS)) + continue; // Do not need to mc2uni coNversion in WDS +#endif + found = 1; + break; + } + + } + + +#ifdef CONFIG_RTK_MESH + /*if we can not find the sta in asoc_list, search mesh proxy table to see if it is proxied by remote mesh node*/ + if(found == 0 && priv->pmib->dot1180211sInfo.mesh_enable && priv->pmib->dot1180211sInfo.mesh_igmp_enable) { + pProxyEntry = (struct proxy_table_entry*) HASH_SEARCH(priv->proxy_table, mac2addr+6); + if(pProxyEntry) { + pEntry = (struct path_sel_entry *)HASH_SEARCH( priv->pathsel_table, pProxyEntry->owner); + if(pEntry) { + pstat = get_stainfo(pEntry->priv, pEntry->nexthopMAC); + if(pstat) + found = 1; + } + } + } +#endif + + + if(found) { + found = 0; + for (i=0; iipmc[i].used && !memcmp(pstat->ipmc[i].mcmac, mac2addr, 6)) { + found = 1; + break; + } + if (free == -1 && !pstat->ipmc[i].used) + free = i; + } + + if (found) { + if (!add) { // delete entry + pstat->ipmc[i].used = 0; + pstat->ipmc_num--; + } + } + else { // not found + if (!add) { + if (priv->dev) + printk("%s: Delete MC entry not found!\n", priv->dev->name); + } + else { // add entry + if (free == -1) { // no free entry + if (priv->dev) + printk("%s: MC entry full!\n", priv->dev->name); + } + else { + memcpy(pstat->ipmc[free].mcmac, mac2addr, 6); + pstat->ipmc[free].used = 1; + pstat->ipmc_num++; + } + } + } + } + + SMP_UNLOCK_ASOC_LIST(flags); +} + +int ioctl_AddDelMCASTGroup2STA(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct wifi_mib *pmib = priv->pmib; + + int ret, i; + if (!priv->pshare->rf_ft_var.mc2u_disable) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + struct net_device *dev_vap; + struct rtl8192cd_priv *priv_vap; + + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) + { + for (i=0; ipvap_priv[i])) { +// rtl8192cd_ioctl(priv->pvap_priv[i]->dev, ifr, cmd); + dev_vap = priv->pvap_priv[i]->dev; + priv_vap = priv->pvap_priv[i]; + if (netif_running(dev_vap)) { + if ((((GET_MIB(priv_vap))->dot11OperationEntry.opmode) & WIFI_AP_STATE) +#ifdef CLIENT_MODE + || ((((GET_MIB(priv_vap))->dot11OperationEntry.opmode) & (WIFI_STATION_STATE|WIFI_ASOC_STATE))==(WIFI_STATION_STATE|WIFI_ASOC_STATE)) +#endif + ) + AddDelMCASTGroup2STA(priv_vap,(unsigned char *)ifr, (cmd == SIOCGIMCAST_ADD) ? 1 : 0); + } + } + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) { + dev_vap = (GET_VXD_PRIV(priv))->dev; + priv_vap = GET_DEV_PRIV(dev_vap); + +// rtl8192cd_ioctl((GET_VXD_PRIV(priv))->dev, ifr, cmd); + if (netif_running(dev_vap)) { + if ((((GET_MIB(priv_vap))->dot11OperationEntry.opmode) & WIFI_AP_STATE) +#ifdef CLIENT_MODE + || ((((GET_MIB(priv_vap))->dot11OperationEntry.opmode) & (WIFI_STATION_STATE|WIFI_ASOC_STATE))==(WIFI_STATION_STATE|WIFI_ASOC_STATE)) +#endif + ) + AddDelMCASTGroup2STA(priv_vap,(unsigned char *)ifr, (cmd == SIOCGIMCAST_ADD) ? 1 : 0); + } + } +#endif + } + if (netif_running(priv->dev)) { + DEBUG_INFO("%s: %s MCAST Group mac %02x%02x%02x%02x%02x%02x\n", priv->dev->name, + ((cmd == SIOCGIMCAST_ADD) ? "Add" : "Del"), + ((unsigned char *)ifr)[0],((unsigned char *)ifr)[1], + ((unsigned char *)ifr)[2],((unsigned char *)ifr)[3],((unsigned char *)ifr)[4],((unsigned char *)ifr)[5]); + DEBUG_INFO("STA mac %02x%02x%02x%02x%02x%02x\n", ((unsigned char *)ifr)[6],((unsigned char *)ifr)[7], + ((unsigned char *)ifr)[8],((unsigned char *)ifr)[9],((unsigned char *)ifr)[10],((unsigned char *)ifr)[11]); + + if ((OPMODE & WIFI_AP_STATE) +#ifdef CLIENT_MODE + || ((OPMODE & (WIFI_STATION_STATE|WIFI_ASOC_STATE))==(WIFI_STATION_STATE|WIFI_ASOC_STATE)) +#endif + ) + AddDelMCASTGroup2STA(priv,(unsigned char *)ifr, (cmd == SIOCGIMCAST_ADD) ? 1 : 0); + } + } + ret = 0; + return ret; +} + +#endif // SUPPORT_TX_MCAST2UNI + + +#ifdef DRVMAC_LB +void drvmac_loopback(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + unsigned char *da = priv->pmib->miscEntry.lb_da; + + // prepare station info + if (memcmp(da, "\x0\x0\x0\x0\x0\x0", 6) && !IS_MCAST(da)) + { + pstat = get_stainfo(priv, da); + if (pstat == NULL) + { + pstat = alloc_stainfo(priv, da, -1); + pstat->state = WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE; + memcpy(pstat->bssrateset, AP_BSSRATE, AP_BSSRATE_LEN); + pstat->bssratelen = AP_BSSRATE_LEN; + pstat->expire_to = 30000; + asoc_list_add(priv, pstat); + cnt_assoc_num(priv, pstat, INCREASE, (char *)__FUNCTION__); + if (QOS_ENABLE) + pstat->QosEnabled = 1; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + pstat->ht_cap_len = priv->ht_cap_len; + memcpy(&pstat->ht_cap_buf, &priv->ht_cap_buf, priv->ht_cap_len); + } + pstat->current_tx_rate = find_rate(priv, pstat, 1, 0); + update_fwtbl_asoclst(priv, pstat); +// add_update_RATid(priv, pstat); + } + } + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_MAC_LOOPBACK_ENABLE, NULL); + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + // accept all packets + // RTL_W32(_RCR_, RTL_R32(_RCR_) | _AAP_); + RTL_W32(RCR, RTL_R32(RCR) | RCR_AAP); + + + // enable MAC loopback + // RTL_W32(_CPURST_, RTL_R32(_CPURST_) | BIT(16) | BIT(17)); + RTL_W32(CR, RTL_R32(CR) | (LB_MAC_DLY&LBMODE_Mask)<= 64) { + sprintf((char *)data, "[FAIL] Adjust value too large\n"); + return strlen((char *)data)+1; + } + + for (index=0; index<8; index++) + { + if ((index == 2) || (index == 3)) + continue; + + readVal = PHY_QueryBBReg(priv, rTxAGC_A_Rate18_06+index*4, 0x7f7f7f7f); + byte0 = (readVal & 0xff000000) >> 24; + byte1 = (readVal & 0x00ff0000) >> 16; + byte2 = (readVal & 0x0000ff00) >> 8; + byte3 = (readVal & 0x000000ff); + + if (minus_sign) { + if (byte0 >= adj_value) + byte0 -= adj_value; + else + byte0 = 0; + if (byte1 >= adj_value) + byte1 -= adj_value; + else + byte1 = 0; + if (byte2 >= adj_value) + byte2 -= adj_value; + else + byte2 = 0; + if (byte3 >= adj_value) + byte3 -= adj_value; + else + byte3 = 0; + } + else { + byte0 += adj_value; + byte1 += adj_value; + byte2 += adj_value; + byte3 += adj_value; + } + + // Max power index = 0x3F Range = 0-0x3F + if (byte0 > RF6052_MAX_TX_PWR) + byte0 = RF6052_MAX_TX_PWR; + if (byte1 > RF6052_MAX_TX_PWR) + byte1 = RF6052_MAX_TX_PWR; + if (byte2 > RF6052_MAX_TX_PWR) + byte2 = RF6052_MAX_TX_PWR; + if (byte3 > RF6052_MAX_TX_PWR) + byte3 = RF6052_MAX_TX_PWR; + + writeVal = (byte0<<24) | (byte1<<16) |(byte2<<8) | byte3; + PHY_SetBBReg(priv, rTxAGC_A_Rate18_06+index*4, 0x7f7f7f7f, writeVal); + } + + byte0 = PHY_QueryBBReg(priv, rTxAGC_A_CCK1_Mcs32, bTxAGCRateCCK); + if (minus_sign) + byte0 -= adj_value; + else + byte0 += adj_value; + if (byte0 > RF6052_MAX_TX_PWR) + byte0 = RF6052_MAX_TX_PWR; + PHY_SetBBReg(priv, rTxAGC_A_CCK1_Mcs32, bTxAGCRateCCK, byte0); + + sprintf((char *)data, "[SUCCESS] %s %d level RF power\n", minus_sign?"Subtract":"Add", adj_value); + return strlen((char *)data)+1; +} + + +#ifdef DFS +void reset_nop_channel(struct rtl8192cd_priv *priv) +{ + if (timer_pending(&priv->ch52_timer)) { + del_timer_sync(&priv->ch52_timer); + rtl8192cd_ch52_timer(priv); + } + + if (timer_pending(&priv->ch56_timer)) { + del_timer_sync(&priv->ch56_timer); + rtl8192cd_ch56_timer(priv); + } + + if (timer_pending(&priv->ch60_timer)) { + del_timer_sync(&priv->ch60_timer); + rtl8192cd_ch60_timer(priv); + } + + if (timer_pending(&priv->ch64_timer)) { + del_timer_sync(&priv->ch64_timer); + rtl8192cd_ch64_timer(priv); + } + + if (timer_pending(&priv->ch100_timer)) { + del_timer_sync(&priv->ch100_timer); + rtl8192cd_ch100_timer(priv); + } + + if (timer_pending(&priv->ch104_timer)) { + del_timer_sync(&priv->ch104_timer); + rtl8192cd_ch104_timer(priv); + } + + if (timer_pending(&priv->ch108_timer)) { + del_timer_sync(&priv->ch108_timer); + rtl8192cd_ch108_timer(priv); + } + + if (timer_pending(&priv->ch112_timer)) { + del_timer_sync(&priv->ch112_timer); + rtl8192cd_ch112_timer(priv); + } + + if (timer_pending(&priv->ch116_timer)) { + del_timer_sync(&priv->ch116_timer); + rtl8192cd_ch116_timer(priv); + } + + if (timer_pending(&priv->ch120_timer)) { + del_timer_sync(&priv->ch120_timer); + rtl8192cd_ch120_timer(priv); + } + + if (timer_pending(&priv->ch124_timer)) { + del_timer_sync(&priv->ch124_timer); + rtl8192cd_ch124_timer(priv); + } + + if (timer_pending(&priv->ch128_timer)) { + del_timer_sync(&priv->ch128_timer); + rtl8192cd_ch128_timer(priv); + } + + if (timer_pending(&priv->ch132_timer)) { + del_timer_sync(&priv->ch132_timer); + rtl8192cd_ch132_timer(priv); + } + + if (timer_pending(&priv->ch136_timer)) { + del_timer_sync(&priv->ch136_timer); + rtl8192cd_ch136_timer(priv); + } + + if (timer_pending(&priv->ch140_timer)) { + del_timer_sync(&priv->ch140_timer); + rtl8192cd_ch140_timer(priv); + } + + if (timer_pending(&priv->ch144_timer)) { + del_timer_sync(&priv->ch144_timer); + rtl8192cd_ch144_timer(priv); + } +} +#endif + + +extern void clear_shortcut_cache(void); + +#ifdef WIFI_HAPD + +int rtl8192cd_net80211_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct wifi_mib *pmib = priv->pmib; + unsigned long flags; + struct iwreq *wrq = (struct iwreq *) ifr; + unsigned char *tmpbuf, *tmp1; + UINT16 sta_num; + int i = 0, ret = 0, sizeof_tmpbuf; + static unsigned char tmpbuf1[1024]; + + DEBUG_TRACE; + + sizeof_tmpbuf = sizeof(tmpbuf1); + tmpbuf = tmpbuf1; + memset(tmpbuf, '\0', sizeof_tmpbuf); + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + + //printk("rtl8192cd_net80211_ioctl, name = %s, cmd =0x%x\n", wrq->ifr_name, cmd); + + switch ( cmd ) + { + + case IEEE80211_IOCTL_SETPARAM: + ret = rtl_net80211_setparam(dev, NULL, &wrq->u, NULL); + break; + case IEEE80211_IOCTL_GETPARAM: + break; + case IEEE80211_IOCTL_SETMODE: + break; + case IEEE80211_IOCTL_GETMODE: + break; + case IEEE80211_IOCTL_SETWMMPARAMS: + break; + case IEEE80211_IOCTL_GETWMMPARAMS: + break; + case IEEE80211_IOCTL_SETCHANLIST: + break; + case IEEE80211_IOCTL_GETCHANLIST: + break; + case IEEE80211_IOCTL_CHANSWITCH: + break; + case IEEE80211_IOCTL_GET_APPIEBUF: + ret = rtl_net80211_getwpaie(dev, NULL, &wrq->u, NULL); + break; + case IEEE80211_IOCTL_SET_APPIEBUF: + ret = rtl_net80211_setappiebuf(dev, NULL, &wrq->u, NULL); + break; + case IEEE80211_IOCTL_FILTERFRAME: + break; + case IEEE80211_IOCTL_GETCHANINFO: + break; + case IEEE80211_IOCTL_SETOPTIE: +#ifdef WIFI_WPAS + ret = rtl_net80211_setoptie(dev, NULL, &wrq->u, NULL); +#endif + break; + case IEEE80211_IOCTL_GETOPTIE: + break; + case IEEE80211_IOCTL_SETMLME: + ret = rtl_net80211_setmlme(dev, NULL, &wrq->u, NULL); + break; + case IEEE80211_IOCTL_SETKEY: + ret = rtl_net80211_setkey(dev, NULL, &wrq->u, NULL); + break; + case IEEE80211_IOCTL_DELKEY: + ret = rtl_net80211_delkey(dev, NULL, &wrq->u, NULL); + break; + case IEEE80211_IOCTL_ADDMAC: + break; + case IEEE80211_IOCTL_DELMAC: + break; +#if ((defined(WIFI_HAPD) || defined(RTK_NL80211)) && defined(WDS)) && !defined(HAPD_DRV_PSK_WPS) + case IEEE80211_IOCTL_WDSADDMAC: + ret = rtl_net80211_wdsaddmac(dev, NULL, &wrq->u, NULL); + break; + case IEEE80211_IOCTL_WDSDELMAC: + ret = rtl_net80211_wdsdelmac(dev, NULL, &wrq->u, NULL); + break; +#endif + case IEEE80211_IOCTL_KICKMAC: + break; + +#ifdef WIFI_WPAS + case WPAS_IOCTL_CUSTOM: //_Eric ?? No need to define ?? + { + unsigned char *is_hapd = (unsigned char *)(wrq->u.data.pointer); + + if(*is_hapd == 0) + ret = rtl_wpas_custom(dev, NULL, &wrq->u, NULL); + else + ret = rtl_hapd_config(dev, NULL, &wrq->u, NULL); + } + + break; +#else + case HAPD_IOCTL_SETCONFIG: + ret = rtl_hapd_config(dev, NULL, &wrq->u, NULL); + break; +#endif + + default: + break; + + } + + RESTORE_INT(flags); + SMP_UNLOCK(flags); + + return ret; + +} +#endif + +#if defined(RTK_AC_SUPPORT) || defined(HS2_SUPPORT) || defined(CONFIG_IEEE80211W)//for 11ac logo +void reset_default_sigma(struct rtl8192cd_priv *priv) +{ +#ifdef RTK_AC_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + printk("reset_default_sigma for VHT5G (11AC, 80M) +++\n"); + else + { + printk("2.4G, No need to reset_default_sigma\n"); + return; + } + + //No Need to reset ssid, channel, band, rts , frag, security, edcu + + //priv->pmib->dot11RFEntry.dot11channel + //priv->pmib->dot11StationConfigEntry.dot11DesiredSSID + //priv->pmib->dot11OperationEntry.dot11FragmentationThreshold + priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod = 100; + priv->pmib->dot11nConfigEntry.dot11nUse40M = 2; + //priv->pmib->dot11OperationEntry.dot11RTSThreshold + //priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = 1; + //priv->pmib->dot11OperationEntry.opmode + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M = 1; + priv->pmib->dot11nConfigEntry.dot11nAMPDU = 1; + priv->pmib->dot11nConfigEntry.dot11nAMSDU = 1; + priv->pmib->dot11nConfigEntry.dot11nAddBAreject = 0; + //priv->pmib->dot11RFEntry.phyBandSelect + priv->pmib->dot11BssType.net_work_type = (WIRELESS_11A |WIRELESS_11N |WIRELESS_11AC); + priv->pmib->dot11StationConfigEntry.legacySTADeny = 0; + //priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm + //priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest + priv->pmib->dot11QosEntry.dot11QosEnable = 1; + priv->pmib->dot11RFEntry.MIMO_TR_mode = MIMO_2T2R; + priv->pmib->dot11acConfigEntry.dot11SupportedVHT = 0xfffa; + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap = 0xfffff; + priv->pshare->rf_ft_var.cca_rts = 0; + priv->pmib->dot11StationConfigEntry.autoRate = 1; + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + priv->pshare->rf_ft_var.txforce = 0xff; + priv->pshare->rf_ft_var.sgiforce = 2; + priv->pmib->dot11nConfigEntry.dot11nTxNoAck = 0; +#ifdef RTL_MANUAL_EDCA + priv->pmib->dot11QosEntry.ManualEDCA = 0; +#endif + priv->pmib->dot11nConfigEntry.dot11nLgyEncRstrct=15; + priv->pshare->rf_ft_var.opmtest = 0; + priv->pmib->dot11RFEntry.txbf = 1; + priv->pmib->dot11nConfigEntry.dot11nLDPC = 1; + priv->pmib->dot11nConfigEntry.dot11nSTBC = 1; + //priv->pmib->dot11RFEntry.txldpc =0; + //priv->pmib->dot11RFEntry.rxldpc =0; + priv->pshare->rf_ft_var.lgirate = 0xffff; + priv->pshare->rf_ft_var.lpwrc = 20; + priv->pshare->rf_ft_var.no_rtscts = 0; + priv->pmib->dot11StationConfigEntry.dot11RegDomain = DOMAIN_TEST; + priv->pshare->rf_ft_var.sigma_mode = AC_SIGMA_APUT; +#ifdef BEAMFORMING_SUPPORT + priv->pshare->rf_ft_var.ndparate = 0x2c; +#endif +#endif + +#ifdef HS2_SUPPORT +/* Hotsport 2.0 Release 1 */ + priv->pmib->dot11OperationEntry.block_relay = 0; + priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G; + priv->pmib->dot11RFEntry.dot11channel = 6; +#endif +} +#endif + +#if defined(RTK_AC_SUPPORT) +void reset_default_sigma_testbed(struct rtl8192cd_priv *priv) +{ + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + printk("reset_default_sigma_testbed for VHT5G (11AC, 80M) +++\n"); + else + { + printk("2.4G, No need to reset_default_sigma_testbed\n"); + return; + } + + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = 0; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = 0; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M = 0; + priv->pmib->dot11acConfigEntry.dot11SupportedVHT = 0xfff0; + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap = 0x3fcff; + priv->pmib->dot11RFEntry.txbf = 0; + priv->pmib->dot11nConfigEntry.dot11nSTBC = 0; + //priv->pmib->dot11nConfigEntry.dot11nAMSDU = 0; + priv->pmib->dot11nConfigEntry.dot11nLDPC = 0; + priv->pshare->rf_ft_var.sigma_mode = AC_SIGMA_APTB; +} + +#endif + +#if defined(SMP_SYNC) && defined(__KERNEL__) && defined(CONFIG_PCI_HCI) +unsigned long _ioctl_copy_from_user (struct rtl8192cd_priv *priv, void * to, const void * from, unsigned long n) +{ + unsigned long ret; + + SMP_UNLOCK(priv->pshare->irq_save); + RESTORE_INT(priv->pshare->irq_save); + ret = copy_from_user(to, from, n); + SAVE_INT_AND_CLI(priv->pshare->irq_save); + SMP_LOCK(priv->pshare->irq_save); + + return ret; +} + +unsigned long _ioctl_copy_to_user (struct rtl8192cd_priv *priv, void * to, const void * from, unsigned long n) +{ + unsigned long ret; + + SMP_UNLOCK(priv->pshare->irq_save); + RESTORE_INT(priv->pshare->irq_save); + ret = copy_to_user(to, from, n); + SAVE_INT_AND_CLI(priv->pshare->irq_save); + SMP_LOCK(priv->pshare->irq_save); + + return ret; +} +#endif + +int rtl8192cd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct wifi_mib *pmib = priv->pmib; + unsigned long flags; + struct iwreq *wrq = (struct iwreq *) ifr; + unsigned char *tmpbuf, *tmp1; + UINT16 sta_num; + int i = 0, ret = -1, sizeof_tmpbuf; +#ifdef CONFIG_RTL8672 + // MBSSID Port Mapping + int ifgrp_member_tmp; +#endif + static unsigned char tmpbuf1[1024]; +#ifdef RTK_WOW + unsigned int wakeup_on_wlan = 0; +#endif +#ifdef D_ACL + struct stat_info *pstat; +#endif + +#ifdef CONFIG_RTK_MESH + unsigned char strPID[10]; + int len; + static UINT8 QueueData[MAXDATALEN2]; + int QueueDataLen; + // UINT8 val8; + + // int j; + #define DATAQUEUE_EMPTY "Queue is empty" +#endif + + DEBUG_TRACE; + + +#ifdef WIFI_HAPD + if((IEEE80211_IOCTL_SETPARAM <= cmd) && (cmd <= IEEE80211_IOCTL_KICKMAC)) + return rtl8192cd_net80211_ioctl(dev, ifr, cmd); + + if(cmd == HAPD_IOCTL_SETCONFIG) + return rtl8192cd_net80211_ioctl(dev, ifr, cmd); +#endif + + sizeof_tmpbuf = sizeof(tmpbuf1); + tmpbuf = tmpbuf1; + memset(tmpbuf, '\0', sizeof_tmpbuf); + +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); + SMP_LOCK(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + +#ifdef MULTI_MAC_CLONE + ACTIVE_ID = 0; +#endif + + switch ( cmd ) + { + + case SIOCGIWNAME: + strcpy(wrq->u.name, "IEEE 802.11-DS"); + ret = 0; + break; +#ifdef CONFIG_RTL_COMAPI_WLTOOLS + case SIOCGIFHWADDR: + +#ifdef WIFI_HAPD //_Eric ?? + memcpy(ifr->ifr_hwaddr.sa_data, pmib->dot11OperationEntry.hwaddr, MACADDRLEN); +#endif + + memcpy(wrq->u.name, pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + ret = 0; + break; + case SIOCSIWFREQ: //set channel/frequency (Hz) + { + ret = rtl_siwfreq(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCGIWFREQ: // get channel/frequency (Hz) + { + ret = rtl_giwfreq(dev, NULL, &wrq->u, NULL); + break; + } +#ifdef WIFI_WPAS + case SIOCSIWMODE: //set operation mode + { + ret = rtl_siwmode(dev, NULL, &wrq->u, NULL); + break; + } +#endif + case SIOCGIWMODE: //get operation mode + { + ret = rtl_giwmode(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCSIWAP: //set access point MAC addresses + { + struct sockaddr *ap_addr=&wrq->u.ap_addr; + ret = rtl_siwap(dev, NULL, &wrq->u, ap_addr->sa_data); + break; + } + case SIOCGIWAP: //get access point MAC addresses + { + struct sockaddr *ap_addr=&wrq->u.ap_addr; + ret = rtl_giwap(dev, NULL, &wrq->u, ap_addr->sa_data); + break; + } + case SIOCGIWESSID: //Get ESSID + { + struct iw_point *essid=&wrq->u.essid; + ret = rtl_giwessid(dev, NULL, &wrq->u, essid->pointer); + break; + } + case SIOCSIWESSID: //Set ESSID + { + struct iw_point *essid=&wrq->u.essid; + ret = rtl_siwessid(dev, NULL, &wrq->u, essid->pointer); + break; + } + case SIOCGIWRATE: //get default bit rate (bps) + ret = rtl_giwrate(dev, NULL, &wrq->u, NULL); + break; + case SIOCSIWRATE: //set default bit rate (bps) + ret = rtl_siwrate(dev, NULL, &wrq->u, NULL); + break; + case SIOCGIWRANGE: //Range of Parameters + { + ret = rtl_giwrange(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCSIWSCAN: + { + ret = rtl_siwscan(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCGIWSCAN: + { + ret = rtl_giwscan(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCGIWRTS: // get RTS/CTS threshold (bytes) + { + ret = rtl_giwrts(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCSIWRTS: //set RTS/CTS threshold (bytes) + { + ret = rtl_siwrts(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCGIWFRAG: //get fragmentation thr (bytes) + { + ret = rtl_giwfrag(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCSIWFRAG: //set fragmentation thr (bytes) + { + ret = rtl_siwfrag(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCSIWRETRY: //set retry limit + { + ret = rtl_siwretry(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCGIWRETRY: //get retry limit + { + ret = rtl_giwretry(dev, NULL, &wrq->u, NULL); + break; + } + case SIOCSIWENCODE: //get encoding token & mode + { + struct iw_point *erq=&wrq->u.encoding; + if(erq) + ret = rtl_siwencode(dev, NULL, &wrq->u, erq->pointer); + break; + } + case SIOCGIWENCODE: //get encoding token & mode + { + struct iw_point *erq=&wrq->u.encoding; + if(erq) + ret = rtl_giwencode(dev, NULL, &wrq->u, erq->pointer); + break; + } + case SIOCGIWPOWER: + { + ret = rtl_giwpower(dev, NULL, &wrq->u, NULL); + break; + } +#endif + + case SIOCMIBINIT: //-- copy kernel data to user data --// + if (wrq->u.data.length != sizeof(struct wifi_mib)) { + panic_printk("IOCTL: mib size mismatch!\n"); + ret = -1; + break; + } + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, (void *)pmib, wrq->u.data.length) == 0) + ret = 0; + break; + + case SIOCMIBSYNC: //-- sync user data to kernel data --// + if (wrq->u.data.length != sizeof(struct wifi_mib)) { + panic_printk("IOCTL: mib size mismatch!\n"); + ret = -1; + break; + } + if (ioctl_copy_from_user((void *)pmib, (void *)wrq->u.data.pointer, wrq->u.data.length) == 0) + ret = 0; + break; + + case SIOCGIWPRIV: //-- get private ioctls for iwpriv --// + if (wrq->u.data.pointer) { +#ifdef __KERNEL__ +#ifdef __LINUX_2_6__ + ret = access_ok(VERIFY_WRITE, (const void *)wrq->u.data.pointer, sizeof(privtab)); + if (!ret) { + ret = -EFAULT; + DEBUG_ERR("user space valid check error!\n"); + break; + } +#else + ret = verify_area(VERIFY_WRITE, (const void *)wrq->u.data.pointer, sizeof(privtab)); + if (ret) { + DEBUG_ERR("verify_area() error!\n"); + break; + } +#endif +#else + ret = 0; +#endif +#ifdef CONFIG_RTL8672 + wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, privtab, sizeof(privtab))) + ret = -EFAULT; +#else + if ((sizeof(privtab) / sizeof(privtab[0])) <= wrq->u.data.length) + { + wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]); + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, privtab, sizeof(privtab))) + ret = -EFAULT; + }else{ + ret = -E2BIG; + } +#endif + } + break; + + +#ifdef D_ACL //tsananiu ; mesh related + case RTL8192CD_IOCTL_ADD_ACL_TABLE: + if ((ret = iwpriv_atoi(priv,(unsigned char *)(wrq->u.data.pointer),tmpbuf,wrq->u.data.length)) ) + { + DEBUG_ERR("Trasnslate MAC address from user space error\n"); + break; + } + ret = acl_add_cmd(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + if (ret >= 0) { + pstat = get_stainfo(priv, tmpbuf); + + if (priv->pmib->dot11StationConfigEntry.dot11AclMode == ACL_deny) { + if (NULL != pstat) { +#ifdef CONFIG_RTK_MESH + if (!isSTA(pstat)) { + DEBUG_INFO("I am a mesh node\n"); + issue_disassoc_MP(priv, pstat, 0, 0); + } else +#endif + { //if station + del_sta(priv, (unsigned char *)(wrq->u.data.pointer)); + } + } + } + } + break; + + case RTL8192CD_IOCTL_REMOVE_ACL_TABLE: + if ((ret = iwpriv_atoi(priv,(unsigned char *)(wrq->u.data.pointer),tmpbuf,wrq->u.data.length)) ) + { + DEBUG_ERR("Trasnslate MAC address from user space error\n"); + break; + } + ret = acl_remove_cmd(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + if (ret >= 0) { + pstat = get_stainfo(priv, tmpbuf); + + if (priv->pmib->dot11StationConfigEntry.dot11AclMode == ACL_allow) { + if (NULL != pstat) { +#ifdef CONFIG_RTK_MESH + if (!isSTA(pstat)) { + DEBUG_INFO("I am a mesh node\n"); + issue_disassoc_MP(priv, pstat, 0, 0); + } else +#endif + { //if station + del_sta(priv, (unsigned char *)(wrq->u.data.pointer)); + } + } + } + } + break; + + case RTL8192CD_IOCTL_GET_ACL_TABLE: + ret = acl_query_cmd(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + if (ret >= 0) { + wrq->u.data.length = ret; + ret = 0; + } + + break; + + case RTL8192CD_IOCTL_CLEAR_ACL_TABLE: + ret = acl_clear_cmd(priv); + break; + +#endif//tsananiu// + + case RTL8192CD_IOCTL_SET_MIB: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + ret = set_mib(priv, tmpbuf); + break; + + case RTL8192CD_IOCTL_GET_MIB: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = get_mib(priv, tmpbuf); + if (i >= 0) { + if ((i > 0) && ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; + +#ifdef _IOCTL_DEBUG_CMD_ + case RTL8192CD_IOCTL_WRITE_REG: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + ret = write_reg(priv, tmpbuf); + break; + + case RTL8192CD_IOCTL_READ_REG: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = read_reg(priv, tmpbuf); + if (i >= 0) { + if ((i > 0) && ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; + + case RTL8192CD_IOCTL_WRITE_MEM: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + ret = write_mem(priv, tmpbuf); + break; + + case RTL8192CD_IOCTL_READ_MEM: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = read_mem(priv, tmpbuf); + if (i >= 0) { + if ((i > 0) && ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; + + case RTL8192CD_IOCTL_WRITE_BB_REG: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + ret = write_bb_reg(priv, tmpbuf); + break; + + case RTL8192CD_IOCTL_READ_BB_REG: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = read_bb_reg(priv, tmpbuf); + if (i >= 0) { + if ((i > 0) && ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; + + case RTL8192CD_IOCTL_WRITE_RF_REG: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + ret = write_rf_reg(priv, tmpbuf); + break; + + case RTL8192CD_IOCTL_READ_RF_REG: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = read_rf_reg(priv, tmpbuf); + if (i >= 0) { + if ((i > 0) && ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; +#endif // _IOCTL_DEBUG_CMD_ + + + case RTL8192CD_IOCTL_DEL_STA: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + ret = del_sta(priv, tmpbuf); + break; + + + case RTL8192CD_IOCTL_WRITE_EEPROM: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + ret = write_eeprom(priv, tmpbuf); + break; + + case RTL8192CD_IOCTL_READ_EEPROM: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = read_eeprom(priv, tmpbuf); + if (i >= 0) { + if ((i > 0) && ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; + +#ifdef RTK_WOW + case SIOCGRTKWOWSTAINFO: //-- get station info for Realtek proprietary wake up on wlan mode--// + wakeup_on_wlan = 1; +#endif + case SIOCGIWRTLSTAINFO: //-- get station table information --// + sizeof_tmpbuf = sizeof(sta_info_2_web) * (NUM_STAT + 1); // for the max of all sta info +#ifdef __ECOS + tmp1 = (unsigned char *)sta_info; +#else + tmp1 = (unsigned char *)kmalloc(sizeof_tmpbuf, GFP_KERNEL); + if (!tmp1) { + printk("Unable to allocate temp buffer for ioctl (SIOCGIWRTLSTAINFO)!\n"); + return -1; + } + memset(tmp1, '\0', sizeof(sta_info_2_web)); +#endif + if (ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, 1)) + break; + if ((tmpbuf[0] == 0) || (tmpbuf[0] > NUM_STAT)) + sta_num = NUM_STAT; + else + sta_num = tmpbuf[0]; +#ifdef RTK_WOW + get_sta_info(priv, (sta_info_2_web *)(tmp1 + sizeof(sta_info_2_web)), sta_num, wakeup_on_wlan); +#else + get_sta_info(priv, (sta_info_2_web *)(tmp1 + sizeof(sta_info_2_web)), sta_num); +#endif + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmp1, sizeof(sta_info_2_web)*(sta_num+1))) + break; + wrq->u.data.length = sizeof(sta_info_2_web)*(sta_num+1); + ret = 0; + +#ifndef __ECOS + kfree(tmp1); +#endif + break; + + case SIOCGIWRTLSTANUM: //-- get the number of stations in table --// +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv) && (OPMODE & WIFI_AP_STATE) && + !IS_DRV_OPEN(priv)) + sta_num = 0; + else +#endif + //sta_num = get_assoc_sta_num(priv); // this will count expired sta + sta_num = priv->assoc_num; + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, &sta_num, sizeof(sta_num))) + break; + wrq->u.data.length = sizeof(sta_num); + ret = 0; + break; + + case SIOCGIWRTLDRVVERSION: + tmpbuf[0] = DRV_VERSION_H; + tmpbuf[1] = DRV_VERSION_L; + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, 2)) + break; + wrq->u.data.length = 2; + ret = 0; + break; + + case SIOCGIWRTLGETBSSINFO: //-- get BSS info --// + get_bss_info(priv, (bss_info_2_web *)tmpbuf); + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, sizeof(bss_info_2_web))) + break; + wrq->u.data.length = sizeof(bss_info_2_web); + ret = 0; + break; + +#if defined(CONFIG_RTL8186_KB_N)//To get auth result + case SIOCGIWRTLAUTH: + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, &authRes, sizeof(authRes))) + break; + wrq->u.data.length = sizeof(authRes); + ret = 0; + authRes = 0;//To init authRes + break; +#endif + +#ifdef WDS + case SIOCGIWRTLGETWDSINFO: //-- get WDS table information --// + ret = get_wds_info(priv, (web_wds_info *)tmpbuf); + if ((ret > 0) && ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, ret)) + break; + wrq->u.data.length = ret; +#ifdef __ECOS + ret = 0; +#endif + break; +#endif + + case SIOCSIWRTLSTATXRATE: //-- set station tx rate --// + if (wrq->u.data.length != sizeof(struct _wlan_sta_rateset) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, sizeof(struct _wlan_sta_rateset))) + break; + ret = set_sta_txrate(priv, (struct _wlan_sta_rateset *)tmpbuf); + break; + + +#ifdef MICERR_TEST + case SIOCSIWRTLMICERROR: + ret = iwpriv_atoi(priv,(unsigned char *)(wrq->u.data.pointer),tmpbuf,wrq->u.data.length); + ret = issue_mic_err_pkt(priv, tmpbuf); + break; +#ifdef CLIENT_MODE + case SIOCSIWRTLMICREPORT: + { + struct sta_info *pstat; + if ((pstat = get_stainfo(priv, BSSID)) != NULL) + ClientSendEAPOL(priv, pstat, 0); + } + ret = 0; + break; +#endif +#endif + + + case SIOCSACLADD: + ret = acl_add_cmd(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + break; + + case SIOCSACLDEL: + ret = acl_remove_cmd(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + break; + + case SIOCSACLQUERY: + ret = acl_query_cmd(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + if (ret >= 0) { + wrq->u.data.length = ret; + ret = 0; + } + break; + +#if defined(CONFIG_RTK_MESH) && defined(_MESH_ACL_ENABLE_) + case SIOCSMESHACLADD: + ret = mesh_acl_add_cmd(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + break; + + case SIOCSMESHACLDEL: + ret = mesh_acl_remove_cmd(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + break; + + case SIOCSMESHACLQUERY: + ret = mesh_acl_query_cmd(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + if (ret >= 0) { + wrq->u.data.length = ret; + ret = 0; + } + break; +#endif + + case SIOCGMISCDATA: + get_misc_data(priv, (struct _misc_data_ *)tmpbuf); + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, sizeof(struct _misc_data_))) + break; + wrq->u.data.length = sizeof(struct _misc_data_); + ret = 0; + break; + + + case RTL8192CD_IOCTL_USER_DAEMON_REQUEST: +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); +#endif + +#ifdef SMP_SYNC + SMP_UNLOCK(priv->pshare->irq_save); +#endif + ret = rtl8192cd_ioctl_priv_daemonreq(dev, &wrq->u.data); +#ifdef SMP_SYNC + SMP_LOCK(priv->pshare->irq_save); +#endif + break; + + +#ifdef USE_PID_NOTIFY + case SIOCSIWRTLSETPID: + priv->pshare->wlanapp_pid = -1; + if (wrq->u.data.length != sizeof(pid_t) || + ioctl_copy_from_user(&priv->pshare->wlanapp_pid, (void *)wrq->u.data.pointer, sizeof(pid_t))) { + //break; + } else { + ret = 0; + } + + #if defined(LINUX_2_6_27_) + if (priv->pshare->wlanapp_pid != -1) + { + rcu_read_lock(); + _wlanapp_pid = get_pid(find_vpid(priv->pshare->wlanapp_pid)); + rcu_read_unlock(); + } + #endif + break; +#endif + +#ifdef CONFIG_RTL_WAPI_SUPPORT + case SIOCSIWRTLSETWAPIPID: + priv->pshare->wlanwapi_pid= -1; + if (wrq->u.data.length != sizeof(pid_t) || + ioctl_copy_from_user(&priv->pshare->wlanwapi_pid, (void *)wrq->u.data.pointer, sizeof(pid_t))) { + //break; + } else { + ret = 0; + } + + #if defined(LINUX_2_6_27_) + if (priv->pshare->wlanwapi_pid != -1) + { + rcu_read_lock(); + _wlanwapi_pid = get_pid(find_vpid(priv->pshare->wlanwapi_pid)); + rcu_read_unlock(); + } + #endif + break; +#endif + case RTL8192CD_IOCTL_SHOWSC: + { + + #if defined(RTL_CACHED_BR_STA) && defined(BR_SHORTCUT) + extern struct brsc_cache_t brsc_cache_arr[MAX_BRSC_NUM]; + int idx2; + unsigned char* cached_br_sta_mac; + int index = priv->dev->name[4] - '0'; + panic_printk("Bridge shortcut info.:\n"); + for(idx2=0;idx2name); + } else { + panic_printk("cached_br_sta_dev is not valid entry\n"); + } + } + #endif + #if defined(RTL_MESH_TXCACHE) + extern unsigned char cached_mesh_mac[2][MACADDRLEN]; + extern struct net_device *cached_mesh_dev[2]; + if(cached_mesh_dev[index]) { + panic_printk(" Source\t:%02x-%02x-%02x-%02x-%02x-%02x\n", + cached_mesh_mac[index][0],cached_mesh_mac[index][1],cached_mesh_mac[index][2], + cached_mesh_mac[index][3],cached_mesh_mac[index][4],cached_mesh_mac[index][5]); + panic_printk(" Interface\t:%s\n",cached_mesh_dev[index]->name); + } else { + panic_printk("cached_mesh_dev[%d] is not valid entry\n",index); + } + + panic_printk("Mesh TX shortcut info:\n"); + panic_printk(" Dirty : %d\n",priv->mesh_txcache.dirty); + panic_printk(" Destination\t:%02x-%02x-%02x-%02x-%02x-%02x\n", + priv->mesh_txcache.ether_da[0],priv->mesh_txcache.ether_da[1],priv->mesh_txcache.ether_da[2], + priv->mesh_txcache.ether_da[3],priv->mesh_txcache.ether_da[4],priv->mesh_txcache.ether_da[5]); + panic_printk(" Source\t:%02x-%02x-%02x-%02x-%02x-%02x\n", + priv->mesh_txcache.ether_sa[0],priv->mesh_txcache.ether_sa[1],priv->mesh_txcache.ether_sa[2], + priv->mesh_txcache.ether_sa[3],priv->mesh_txcache.ether_sa[4],priv->mesh_txcache.ether_sa[5]); + panic_printk(" Mesh Next-hop\t:%02x-%02x-%02x-%02x-%02x-%02x\n", + priv->mesh_txcache.txcfg.nhop_11s[0],priv->mesh_txcache.txcfg.nhop_11s[1],priv->mesh_txcache.txcfg.nhop_11s[2], + priv->mesh_txcache.txcfg.nhop_11s[3],priv->mesh_txcache.txcfg.nhop_11s[4],priv->mesh_txcache.txcfg.nhop_11s[5]); + #endif + ret = 0; + } + break; + + + +#ifdef CONFIG_RTK_MESH + case RTL8192CD_IOCTL_STATIC_ROUTE: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + if( memcmp(tmpbuf, "del", 3)==0 ) + { + mac12_to_6(tmpbuf+4, tmpbuf+0x100); + ret = remove_path_entry(priv, tmpbuf+0x100); + } + else if((memcmp(tmpbuf, "add", 3)==0) && (wrq->u.data.length>28) ) + { + struct path_sel_entry Entry; + memset((void*)&Entry, 0, sizeof(struct path_sel_entry)); + mac12_to_6(tmpbuf+4, Entry.destMAC); + mac12_to_6(tmpbuf+4+13, Entry.nexthopMAC); + Entry.flag=1; + ret = pathsel_table_entry_insert_tail( priv, &Entry); + }else + ret =0; + break; +#if defined(RTK_MESH_MANUALMETRIC) + case RTL8192CD_IOCTL_MANUAL_METRIC: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + + ret = set_metric_manually(priv,tmpbuf); + break; +#endif + case SIOCJOINMESH: + { + struct + { + unsigned char *meshid; + int meshid_len, channel, offset, reset; + }mesh_identifier; + if(wrq->u.data.length > 0) + { + memcpy(&mesh_identifier, wrq->u.data.pointer, wrq->u.data.length); + ret = rtl8192cd_join_mesh(priv, mesh_identifier.meshid, mesh_identifier.meshid_len, mesh_identifier.channel, mesh_identifier.offset, mesh_identifier.reset); + } + else + ret = -1; + } + break; + case SIOCCHECKMESHLINK: // This case might be removed when the mesh peerlink precedure has been completed + { + if(wrq->u.data.length == 6) + ret = rtl8192cd_check_mesh_link(priv, wrq->u.data.pointer); + else + ret = -1; + } + break; +// ==== GANTOE ==== +#endif + case SIOCGIWRTLSCANREQ: //-- Issue SS request --// + +#if defined(CONFIG_RTL_SIMPLE_CONFIG_USE_WPS_BUTTON) + if(priv->simple_config_status >= 2) + { + break; + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv) && !priv->pmib->wscEntry.wsc_enable) { + DEBUG_ERR("can't do site-survey for vxd!\n"); + break; + } +#endif +#ifdef MBSSID + if ( + GET_ROOT(priv)->pmib->miscEntry.vap_enable && + IS_VAP_INTERFACE(priv) && !priv->pmib->wscEntry.wsc_enable) { + DEBUG_ERR("can't do site-survey for vap!\n"); + break; + } +#endif + +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); +#endif + ret = rtl8192cd_ss_req(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + break; + + case SIOCGIWRTLGETBSSDB: //-- Get SS Status --// +#if defined(CONFIG_RTL_SIMPLE_CONFIG_USE_WPS_BUTTON) + if(priv->simple_config_status >= 2) + { + break; + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv) && !priv->pmib->wscEntry.wsc_enable) { + DEBUG_ERR("can't get site-survey status for vxd!\n"); + break; + } +#endif +#ifdef MBSSID + if ( + GET_ROOT(priv)->pmib->miscEntry.vap_enable && + IS_VAP_INTERFACE(priv) && !priv->pmib->wscEntry.wsc_enable) { + DEBUG_ERR("can't get site-survey status for vap!\n"); + break; + } +#endif + ret = rtl8192cd_get_ss_status(priv, (unsigned char *)(wrq->u.data.pointer)); + break; + +/*--------------P2P related ioctl----------------------------------start*/ +#ifdef P2P_SUPPORT + /*P2P UI request do p2p discovery */ + case SIOCP2PSCANREQ: + if(!(OPMODE&WIFI_P2P_SUPPORT)) + return -1; + + if((P2PMODE != P2P_DEVICE) && (P2PMODE != P2P_CLIENT)) + return -1; + + +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); +#endif + ret = rtl8192cd_p2p_ss_req(priv, (unsigned char *)(wrq->u.data.pointer), wrq->u.data.length); + break; + /*P2P UI get P2P SS Status and Result*/ + case SIOCP2PGETRESULT: + + if(!(OPMODE&WIFI_P2P_SUPPORT)) + return -1; + if((P2PMODE != P2P_DEVICE) && (P2PMODE != P2P_CLIENT)) + return -1; + +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + DEBUG_ERR("can't get site-survey status for vxd!\n"); + break; + } +#endif +#ifdef MBSSID + if ( + GET_ROOT(priv)->pmib->miscEntry.vap_enable && + IS_VAP_INTERFACE(priv)) { + DEBUG_ERR("can't get site-survey status for vap!\n"); + break; + } +#endif + ret = rtl8192cd_p2p_get_ss_status(priv, (unsigned char *)(wrq->u.data.pointer)); + break; + + //-- issue provision discovery request , need device address from P2P UI --// + case SIOCP2PPROVREQ: + + #ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); + #endif + ret = req_p2p_provision_req(priv, (unsigned char *)(wrq->u.data.pointer)); + break; + + /*P2P UI confirm wsc method,pincode,Target device to wlan driver, + if we active send provision req before ,then will send nego req here */ + case SIOCP2WSCMETHODCONF: + + #ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); + #endif + ret = req_p2p_wsc_confirm(priv, (unsigned char *)(wrq->u.data.pointer)); + break; + + //-- report event and state to P2P UI--// + case SIOCP2PPGETEVNIND: + ret = p2p_get_event_state(priv, (unsigned char *)(wrq->u.data.pointer)); + break; + + //-- wscd(GO mode) report WPS success or fail --// + case SIOCP2P_WSC_REPORT_STATE: + ret = p2p_wps_indicate_state(priv, (unsigned char *)(wrq->u.data.pointer)); + break; + + /*Report 1.p2p client connect state to web server ; for process start udhcpc + 2.p2p pre-GO change to GO (WPS is done and success) indicate web server need start udhcpd*/ + case SIOCP2P_REPORT_CLIENT_STATE: + ret = p2p_get_p2pconnect_state(priv, (unsigned char *)(wrq->u.data.pointer)); + break; + +#endif // end of P2P_SUPPORT +/*--------------P2P related ioctl----------------------------------end*/ + +#ifdef AUTO_TEST_SUPPORT + case SIOCSSREQ: + rtl8192cd_SSReq_AutoTest(priv); + ret = 0; + break; + + case SIOCJOINREQ: +#ifdef CLIENT_MODE + ret = rtl8192cd_join_AutoTest(priv , (unsigned char *)(wrq->u.data.pointer)); +#endif + break; + +#endif + +#ifdef CLIENT_MODE + case SIOCGIWRTLJOINREQ: //-- Issue Join Request --// + ret = rtl8192cd_join(priv, (unsigned char *)(wrq->u.data.pointer)); + break; + + case SIOCGIWRTLJOINREQSTATUS: //-- Get Join Status --// + ret = rtl8192cd_join_status(priv, (unsigned char *)(wrq->u.data.pointer)); + break; +#endif + + +#ifdef RTK_WOW + case SIOCGRTKWOW: //-- issue Realtek proprietary wake up on wlan mode --// + ret = 5; + do { + issue_rtk_wow(priv, (unsigned char *)(wrq->u.data.pointer)); + } while(--ret > 0); + break; +#endif + + case SIOCSRFPWRADJ: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = dynamic_RF_pwr_adj(priv, tmpbuf); + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; + +#ifdef MCR_WIRELESS_EXTEND +#ifdef CONFIG_WLAN_HAL_8814AE + case SIORXANTSELECT: + { + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + if (Switch_Antenna_8814(priv, tmpbuf)) + GDEBUG("- Usage : # iwpriv wlan0 set_ant_rx ss=x,path=y\n"); + ret = 0; + break; + } +#endif +#endif +#ifdef MP_TEST + case MP_START_TEST: +#ifdef NOT_RTK_BSP + RESTORE_INT(priv->pshare->irq_save); + SMP_UNLOCK(priv->pshare->irq_save); +#else + RESTORE_INT(flags); + SMP_UNLOCK(flags); +#endif + mp_start_test(priv); +#ifdef NOT_RTK_BSP + SAVE_INT_AND_CLI(priv->pshare->irq_save); + SMP_LOCK(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); +#endif + ret = 0; + break; + + case MP_STOP_TEST: +#ifdef NOT_RTK_BSP + RESTORE_INT(priv->pshare->irq_save); + SMP_UNLOCK(priv->pshare->irq_save); +#else + RESTORE_INT(flags); + SMP_UNLOCK(flags); +#endif + mp_stop_test(priv); +#ifdef NOT_RTK_BSP + SAVE_INT_AND_CLI(priv->pshare->irq_save); + SMP_LOCK(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); +#endif + ret = 0; + break; + +#ifdef SDIO_AP_OFFLOAD + case SIOCSTOPPS: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + + set_ap_ps_mode(priv, tmpbuf); + // assign_MIMO_TR_Mode(priv, tmpbuf); + wrq->u.data.length = 0; + ret = 0; + break; +#endif + + case MP_SET_RATE: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + mp_set_datarate(priv, tmpbuf); + ret = 0; + break; + + case MP_SET_CHANNEL: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + mp_set_channel(priv, tmpbuf); + ret = 0; + break; + + case MP_SET_BANDWIDTH: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + mp_set_bandwidth(priv, tmpbuf); + ret = 0; + break; + + case MP_SET_TXPOWER: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + mp_set_tx_power(priv, tmpbuf); + ret = 0; + break; + + case MP_CONTIOUS_TX: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); + SMP_UNLOCK(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + mp_ctx(priv, tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); + SMP_LOCK(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); +#endif + ret = 0; + break; + + case MP_ARX: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = mp_arx(priv, tmpbuf); + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; + + case MP_SET_BSSID: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + mp_set_bssid(priv, tmpbuf); + ret = 0; + break; + + case MP_ANTENNA_TX: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + mp_set_ant_tx(priv, tmpbuf); + ret = 0; + break; + + case MP_ANTENNA_RX: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + mp_set_ant_rx(priv, tmpbuf); + ret = 0; + break; + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + case MP_SET_BAND: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + mp_set_phyBand(priv, tmpbuf); + ret = 0; + break; +#endif + + case MP_RESET_STATS: + mp_reset_stats(priv); + ret = 0; + break; + + case MP_SET_PHYPARA: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + mp_set_phypara(priv, tmpbuf); + ret = 0; + break; + +#ifdef B2B_TEST + case MP_TX_PACKET: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + i = mp_tx(priv, tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; + +#if 0 + case MP_RX_PACKET: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifndef __LINUX_2_6__ + RESTORE_INT(flags); +#endif + mp_rx(priv, tmpbuf); +#ifndef __LINUX_2_6__ + SAVE_INT_AND_CLI(flags); +#endif + ret = 0; + break; +#endif + + case MP_BRX_PACKET: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + i = mp_brx(priv, tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; +#endif // B2B_TEST + + case MP_QUERY_STATS: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = mp_query_stats(priv, tmpbuf); + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; + + case MP_TXPWR_TRACK: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + mp_txpower_tracking(priv, tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + ret = 0; + break; + + case MP_QUERY_TSSI: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + i = mp_query_tssi(priv, tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; + + case MP_QUERY_THER: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + i = mp_query_ther(priv, tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; + #ifdef MP_PSD_SUPPORT + case MP_QUERY_PSD: + if (ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + i = mp_query_psd(priv, tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + if (i > 0 ) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i )) + break; + wrq->u.data.length = i; + ret = 0; + //printk("The address of DA is 0x%p\n",(void *)wrq->u.data.pointer); + } + break; + #endif + case MP_GET_TXPOWER: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + i = mp_get_txpwr(priv, tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; + +#if defined(CONFIG_RTL_8812_SUPPORT) + case MP_DIG: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + mp_dig(priv, tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + ret = 0; + break; +#endif +#endif // MP_TEST + +#if (defined(SW_ANT_SWITCH) || defined(HW_ANT_SWITCH)) + case SIOCANTSELECT: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#if (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + if (GET_CHIP_VER(priv) <= VERSION_8192D) { + diversity_antenna_select(priv, tmpbuf); + } else +#endif + { +#ifdef USE_OUT_SRC + priv->pshare->_dmODM.antdiv_select = _atoi(tmpbuf, 10); + panic_printk("SIOCANTSELECT --> antdiv_select=%d\n", priv->pshare->_dmODM.antdiv_select); + ODM_AntDiv(ODMPTR); +#endif + } + ret = 0; + break; +#endif + + case SIOCGIWRTLREGDUMP: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + reg_dump(priv, (char *)tmpbuf); +#ifdef SMP_SYNC + SAVE_INT_AND_CLI(priv->pshare->irq_save); +#else + SAVE_INT_AND_CLI(flags); +#endif + ret = 0; + break; + +#ifdef BR_SHORTCUT + case SIOCLEARBRSC: + clear_shortcut_cache(); + ret = 0; + break; + + case SIOCLONEEARBRSC: + { + int idx; + unsigned char macaddr[MACADDRLEN]; + unsigned char tmpbuf2[4]; + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + + for(idx=0; idxu.data.pointer, wrq->u.data.length)) + break; + + rtl8192cd_del_all_sta(priv); + rtl8192cd_autochannel_sel(priv); + + wrq->u.data.length = 0; + ret = 0; + break; + + case SIOCANTSTS: + i = sprintf(tmpbuf, "%x:%x", priv->pshare->mp_antenna_tx, priv->pshare->mp_antenna_rx); + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + + wrq->u.data.length = i; + ret = 0; + break; + +#if defined(PCIE_POWER_SAVING) || defined(RF_MIMO_SWITCH) || defined(RF_MIMO_PS) + case SIOCEPDN: +#ifdef PCIE_POWER_SAVING +#ifdef PCIE_POWER_SAVING_DEBUG + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = PCIE_PowerDown(priv, tmpbuf); + + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; +#else + priv->pshare->rf_ft_var.power_save &=0xf0; + PCIeWakeUp(priv, (POWER_DOWN_T0)); +#endif +#else + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + assign_MIMO_TR_Mode(priv, tmpbuf); + wrq->u.data.length = 0; +#endif + ret = 0; + break; +#endif +#ifdef EN_EFUSE + case SIOCEFUSE_GET: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = efuse_get(priv, tmpbuf); + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; + + case SIOCEFUSE_SET: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = efuse_set(priv, tmpbuf); + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; + + case SIOCEFUSE_SYNC: + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = efuse_sync(priv, tmpbuf); + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; + +#endif + + +#ifdef P2P_SUPPORT + case SIOCP2PCMD: + + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + + //printk("ioctl-->process_p2p_cmd\n"); + + i = process_p2p_cmd(priv, tmpbuf); + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; + +#endif + +#if defined(MBSSID) || defined(UNIVERSAL_REPEATER) + case SIOCSICOPYMIB: + { + unsigned char hwaddr[MACADDRLEN]; + int func_off = priv->pmib->miscEntry.func_off; + memcpy(hwaddr, GET_MY_HWADDR, MACADDRLEN); + + memcpy(priv->pmib, GET_ROOT(priv)->pmib, sizeof(struct wifi_mib)); + + priv->pmib->miscEntry.func_off = func_off; + memcpy(GET_MY_HWADDR, hwaddr, MACADDRLEN); +#ifdef WIFI_WPAS_CLI + priv->pmib->wscEntry.wsc_enable = 0; + priv->pmib->wscEntry.beacon_ielen = 0; + priv->pmib->wscEntry.probe_rsp_ielen = 0; + priv->pmib->wscEntry.probe_req_ielen = 0; + priv->pmib->wscEntry.assoc_ielen = 0; +#endif + ret = 0; + break; + } +#endif + +#ifdef CONFIG_RTL8186_KB + case SIOCGIREADGUESTMAC: + i = get_guestmac(priv, (GUESTMAC_T *)tmpbuf); + if (i >= 0) { + if ((i > 0) && ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; + + case SIOCSIWRTGUESTMAC: + if (ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + set_guestmacvalid(priv, tmpbuf); + ret = 0; + break; +#endif + +#ifdef MULTI_MAC_CLONE + case SIOCGIMCLONE: + if (ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = get_mclone_addr(priv, tmpbuf); + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + ret = 0; + break; + + case SIOCSIMCLONE: + if (ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + set_mclone_addr(priv, tmpbuf); + ret = 0; + break; + + case SIOCSIMCLONE_DEL: + if (ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + del_mclone_addr(priv, tmpbuf); + ret = 0; + break; + + case SIOCSIMCLONE_DEL2: + if( ( ((GET_MIB(priv))->dot11OperationEntry.opmode & (WIFI_STATION_STATE|WIFI_ASOC_STATE))==(WIFI_STATION_STATE|WIFI_ASOC_STATE) )&& MCLONE_NUM ){ + __del_mclone_addr(priv, (unsigned char *)ifr); + } + ret = 0; + break; +#endif + +#ifdef SUPPORT_SNMP_MIB + case SIOCGSNMPMIB: + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + + if (mib_get(priv, tmpbuf, tmpbuf, &i)) { + if ((i > 0) && ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + wrq->u.data.length = i; + ret = 0; + } + break; +#endif + +#ifdef SUPPORT_TX_MCAST2UNI + case SIOCGIMCAST_ADD: + case SIOCGIMCAST_DEL: + ret = ioctl_AddDelMCASTGroup2STA(dev, ifr, cmd); + break; +#endif // SUPPORT_TX_MCAST2UNI +#ifdef CONFIG_RTK_MESH + case SIOCQPATHTABLE: + { + unsigned char destaddr[MACADDRLEN] = {0}; + + ioctl_copy_from_user(destaddr, (void *)(wrq->u.data.pointer), MACADDRLEN); + //MESH_DEBUG_MSG("kernel destaddr = %s\n",destaddr); + struct path_sel_entry *pEntry = pathsel_query_table( priv, destaddr); // modified by chuangch 2007.09.14 + ret = -1; + if(pEntry!= (struct path_sel_entry *)-1) + { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, (void *)pEntry, (int)&((struct path_sel_entry*)0)->start) == 0) + { + ret = 0; + wrq->u.data.length = sizeof(struct path_sel_entry); + } + } + break; + } + + case SIOCUPATHTABLE: + { + struct path_sel_entry Entry; + ioctl_copy_from_user((struct path_sel_entry *)&Entry, (void *)(wrq->u.data.pointer), (int)&((struct path_sel_entry*)0)->start); + ret = pathsel_modify_table_entry(priv, &Entry); // chuangch 2007.09.14 + break; + } + case SIOCAPATHTABLE: + { + struct path_sel_entry Entry, *pEntry; + memset((void*)&Entry, 0, sizeof(Entry)); + ioctl_copy_from_user((struct path_sel_entry *)&Entry, (void *)(wrq->u.data.pointer), (int)&((struct path_sel_entry*)0)->start); + ret = 0; + pEntry = pathsel_query_table( priv, Entry.destMAC ); + + if( pEntry == (struct path_sel_entry *)-1 || pEntry->flag==0) + { + /*prevent update path relative to any invalid neighbor*/ + if(get_stainfo(priv, Entry.nexthopMAC)) { + Entry.priv = priv; + } + #if !defined(CONFIG_RTL_MESH_CROSSBAND) + else if(priv->mesh_priv_sc && get_stainfo(priv->mesh_priv_sc, Entry.nexthopMAC)) { + Entry.priv = priv->mesh_priv_sc; + } + #endif + else { + return -1; + } + + + Entry.update_time = xtime; // chuangch 2007.09.19 + #ifdef MESH_ROUTE_MAINTENANCE + Entry.routeMaintain = xtime; // chuangch 10.19 + #endif + ret = pathsel_table_entry_insert_tail( priv, &Entry); //chuangch 2007.09.14 + + MESH_DEBUG_MSG("create path to:%02X:%02X:%02X:%02X:%02X:%02X, Nexthop=%02X:%02X:%02X:%02X:%02X:%02X, Hop count=%d\n", + Entry.destMAC[0], Entry.destMAC[1], Entry.destMAC[2], Entry.destMAC[3], Entry.destMAC[4], Entry.destMAC[5], + Entry.nexthopMAC[0], Entry.nexthopMAC[1], Entry.nexthopMAC[2], Entry.nexthopMAC[3], Entry.nexthopMAC[4], Entry.nexthopMAC[5], + Entry.hopcount); + } + + break; + } + + //modify by Jason 2007.11.26 + case REMOVE_PATH_ENTRY: + { + unsigned char invalid_node_addr[MACADDRLEN] = {0}; + struct path_sel_entry *pEntry; + + if ( ioctl_copy_from_user((void *)invalid_node_addr, (void *)(wrq->u.data.pointer), MACADDRLEN) ) { + ret = -1; + break; + } + + MESH_DEBUG_MSG("REMOVE_PATH_ENTRY\n"); + MESH_DEBUG_MSG("invalid_node_addr =%2X-%2X-%2X-%2X-%2X-%2X-\n",invalid_node_addr[0],invalid_node_addr[1],invalid_node_addr[2],invalid_node_addr[3],invalid_node_addr[4],invalid_node_addr[5]); + + pEntry = pathsel_query_table( priv, invalid_node_addr ); + if(pEntry != (struct path_sel_entry *)-1 && pEntry->flag==0) + { +#ifdef __LINUX_2_6__ +/*by qjj_qin and hf_shi*/ +#else + SAVE_INT_AND_CLI(flags); +#endif + ret = remove_path_entry(priv,invalid_node_addr); +#ifdef __LINUX_2_6__ +/*by qjj_qin and hf_shi*/ +#else + RESTORE_INT(flags); +#endif + } + break; + } + + case GET_STA_LIST: + { + struct stat_info *pstat; + + struct proxy_table_entry *pEntry=NULL; + static unsigned char node[MACADDRLEN] = {0}; + + if ( ioctl_copy_from_user((void *)node, (void *)(wrq->u.data.pointer), MACADDRLEN) ) { + ret = -1; + break; + } + + #if 0 //do not use station info + // my station + pstat = get_stainfo(priv, node); + + if(pstat != 0) + { + if(isSTA(pstat) && (pstat->state & WIFI_ASOC_STATE)) { + ret = 0; + break; + } + else // a neighbor + goto ret_nothing; + } + #endif + + pEntry = HASH_SEARCH(priv->proxy_table,node); + + // my proxied entry + if(pEntry && (memcmp(GET_MY_HWADDR, pEntry->owner, MACADDRLEN)==0)) + { + ret = 0; + break; + } + +ret_nothing: + // if not my station or not my proxied entry, then just fill garbage(0x0b) and return normally + memset(node, 0x0b, sizeof(node)); + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, (void *)node, MACADDRLEN) != 0) + { + ret = -1; + break; + } + ret = 0; + break; + } + + case SET_PORTAL_POOL: + { + if ( ioctl_copy_from_user( (priv->pann_mpp_tb->pann_mpp_pool), (void *)(wrq->u.data.pointer), sizeof(struct pann_mpp_tb_entry) * MAX_MPP_NUM ) ) { + ret = -1; + break; + } + ret = 0; + break; + } + + case SIOC_NOTIFY_PATH_CREATE: + { + unsigned char destaddr[MACADDRLEN] = {0}; + + if ( ioctl_copy_from_user((void *)destaddr, (void *)(wrq->u.data.pointer), MACADDRLEN) ) { + ret = -1; + break; + } + notify_path_found(destaddr,priv); + // MESH_DEBUG_MSG("destaddr =%2X-%2X-%2X-%2X-%2X-%2X-\n",destaddr[0],destaddr[1],destaddr[2],destaddr[3],destaddr[4],destaddr[5]); + ret = 0; + break; + } + + case SIOC_UPDATE_ROOT_INFO: + { + if ( ioctl_copy_from_user((void *)priv->root_mac, (void *)(wrq->u.data.pointer), MACADDRLEN) ) { + ret = -1; + break; + } + ret = 0; +#if 0 + LOG_MESH_MSG("Root MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", + priv->root_mac[0],priv->root_mac[1],priv->root_mac[2],priv->root_mac[3],priv->root_mac[4],priv->root_mac[5]); +#endif + break; + } + + case SIOC_GET_ROUTING_INFO: + { + unsigned char buffer[128] = {0}; + buffer[0] = (unsigned short)(priv->pmib->dot1180211sInfo.mesh_root_enable); + buffer[1] = (unsigned short)(priv->pmib->dot1180211sInfo.mesh_portal_enable); +#ifdef _11s_TEST_MODE_ + buffer[2] = (unsigned short)(priv->pmib->dot1180211sInfo.mesh_reserved1); +#endif + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, (void *)buffer, 128) == 0) + ret = 0; + else + ret = -1; + + break; + } + +case SIOC_SET_ROUTING_INFO: + { + unsigned char buffer[128] = {0}; + + if ( !wrq->u.data.pointer ){ + ret = -1; + break; + } + + if (ioctl_copy_from_user((void *)buffer, (void *)wrq->u.data.pointer, 128) == 0) + ret = 0; + else + ret = -1; + + priv->pmib->dot1180211sInfo.mesh_root_enable = buffer[0]; + priv->pmib->dot1180211sInfo.mesh_portal_enable = buffer[1]; + break; + } + + +#ifdef _11s_TEST_MODE_ + case SAVE_RECEIBVER_PID: + { + if ( !wrq->u.data.pointer ){ + ret = -1; + break; + } + + len = wrq->u.data.length; + memset(strPID, 0, sizeof(strPID)); + ioctl_copy_from_user(strPID, (void *)wrq->u.data.pointer, len); + + pid_receiver = 0; + for(i = 0; i < len; i++) //char -> int + { + pid_receiver = pid_receiver * 10 + (strPID[i] - 48); + } + ret = 0; + break; + } + + case DEQUEUE_RECEIBVER_IOCTL: + { + if((ret = DOT11_DeQueue2((unsigned long)priv, priv->receiver_queue, QueueData, &QueueDataLen)) != 0) { + ioctl_copy_to_user((void *)(wrq->u.data.pointer), DATAQUEUE_EMPTY, sizeof(DATAQUEUE_EMPTY)); + wrq->u.data.length = sizeof(DATAQUEUE_EMPTY); + } else { + ioctl_copy_to_user((void *)wrq->u.data.pointer, (void *)QueueData, QueueDataLen); + wrq->u.data.length = QueueDataLen; + } + break; + } +#endif + + case SAVEPID_IOCTL: + { + if ( !wrq->u.data.pointer ){ + ret = -1; + break; + } + + len = wrq->u.data.length; + memset(strPID, 0, sizeof(strPID)); + ioctl_copy_from_user(strPID, (void *)wrq->u.data.pointer, len); + + priv->pid_pathsel = 0; + for(i = 0; i < len; i++) //char -> int + { + priv->pid_pathsel = priv->pid_pathsel * 10 + (strPID[i] - 48); + } + + ret = 0; + break; + } + + case DEQUEUEDATA_IOCTL: + { + if((ret = DOT11_DeQueue2((unsigned long)priv, priv->pathsel_queue, QueueData, &QueueDataLen)) != 0) { + ioctl_copy_to_user((void *)(wrq->u.data.pointer), DATAQUEUE_EMPTY, sizeof(DATAQUEUE_EMPTY)); + wrq->u.data.length = sizeof(DATAQUEUE_EMPTY); + } else { + ioctl_copy_to_user((void *)wrq->u.data.pointer, (void *)QueueData, QueueDataLen); + wrq->u.data.length = QueueDataLen; + } + + break; + } +#endif // CONFIG_RTK_MESH + +#ifdef CONFIG_RTL_COMAPI_CFGFILE + case SIOCCOMAPIFILE: + { + ret = CfgFileProc(dev); + break; + } +#endif + + case SIOC92DAUTOCH: + { + if (!(OPMODE & WIFI_AP_STATE)){ + DEBUG_ERR("can't do auto-channel select for non-AP mode!\n"); + break; + } +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + DEBUG_ERR("can't do auto-channel select for vxd!\n"); + break; + } +#endif +#ifdef MBSSID + if ( + GET_ROOT(priv)->pmib->miscEntry.vap_enable && + IS_VAP_INTERFACE(priv)) { + DEBUG_ERR("can't do auto-channel select for vap!\n"); + break; + } +#endif + +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); +#endif + ret = rtl8192cd_autochannel_sel(priv); + break; + } + +#if defined(CONFIG_OFFLOAD_FUNCTION) || defined(SDIO_AP_OFFLOAD) + case SIOOFFLOADTEST: + { + if(ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + i = offloadTestFunction(priv, tmpbuf); + + if (i > 0) { + if (ioctl_copy_to_user((void *)wrq->u.data.pointer, tmpbuf, i)) + break; + } + wrq->u.data.length = i; + + ret = 0; + break; + } +#endif // CONFIG_OFFLOAD_FUNCTION || SDIO_AP_OFFLOAD + + +#ifdef CONFIG_8814_AP_MAC_VERI + case SIO_8814_AP_MAC_VERI: + { + if(copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + APmacTestFunction_8814(priv, tmpbuf); + + ret = 0; + break; + } +#endif //#ifdef CONFIG_8814_AP_MAC_VERI + +#ifdef CONFIG_RTL_92D_SUPPORT + case SIOC92DIQK: + { + PHY_IQCalibrate(priv); + ret = 0; + break; + } + +#ifdef EN_EFUSE + case SIOC92DSBANDADDR: + { + unsigned int phyband; + u8 efuse_MAC=0; + if (wrq->u.data.pointer) { + if ((wrq->u.data.length > sizeof_tmpbuf) || + ioctl_copy_from_user(tmpbuf, (void *)wrq->u.data.pointer, wrq->u.data.length)) + break; + + phyband = _atoi(tmpbuf, 16); + printk("get phyband = %d \n",phyband); + if (phyband==2) + efuse_MAC = EEPROM_MAC0_MACADDRESS; + else + efuse_MAC = EEPROM_MAC1_MACADDRESS; + + if (/*priv->AutoloadFailFlag==FALSE &&*/ priv->pmib->efuseEntry.enable_efuse==1) { +#ifdef __KERNEL__ + struct sockaddr addr; +#endif + unsigned char *hwinfo = &(priv->EfuseMap[EFUSE_INIT_MAP][0]); + unsigned char *mac = hwinfo + efuse_MAC; + unsigned char zero[] = {0, 0, 0, 0, 0, 0}; + /* printk("wlan%d EFUSE MAC [%02x:%02x:%02x:%02x:%02x:%02x]\n", priv->pshare->wlandev_idx, + *mac, *(mac+1), *(mac+2), *(mac+3), *(mac+4), *(mac+5)); */ + if(memcmp(mac, zero, MACADDRLEN) && !IS_MCAST(mac)) { +#ifdef __KERNEL__ + memcpy(addr.sa_data, mac, MACADDRLEN); + rtl8192cd_set_hwaddr(priv->dev, (void *)&addr); +#else + rtl8192cd_set_hwaddr(priv->dev, (void *)mac); +#endif + } + } + + ret = 0; + } else { + ret = -1; + } + break; + } +#endif // EN_EFUSE + +#ifdef NON_INTR_ANTDIV + case SIOC92DATNDIV: + { + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY){ + extern u32 if_priv[]; + unsigned long temp_18[2], temp_28[2], temp_0b[2]; + int i, ch[2]; + + // Backup RF 18, 28, 0B + for (i=0;i<2;i++) { + temp_18[i] = DMDP_PHY_QueryRFReg(i, RF92CD_PATH_A, 0x18, bMask20Bits, 1); + ch[i] = temp_18[i] & 0xff; + temp_28[i] = DMDP_PHY_QueryRFReg(i, RF92CD_PATH_A, 0x28, bMask20Bits, 1); + temp_0b[i] = DMDP_PHY_QueryRFReg(i, RF92CD_PATH_A, 0x0b, bMask20Bits, 1); + printk("RF[%d] 18=0x%05x 28=0x%05x 0B=0x%05x\n",i, temp_18[i], temp_28[i], temp_0b[i]); + } + + + PHY_SetBBReg(priv, 0xb30, BIT(27), 1); + + // Restore RF 18, 28, 0B + for (i=0;i<2;i++) { + DMDP_PHY_SetRFReg(i, RF92CD_PATH_A, 0x18, bMask20Bits, temp_18[i]); + //DMDP_PHY_SetRFReg(i, RF92CD_PATH_A, 0x28, BIT(7)|BIT(6), (temp_28[i]&(BIT(7)|BIT(6)))>>6); + DMDP_PHY_SetRFReg(i, RF92CD_PATH_A, 0x0b, bMask20Bits, temp_0b[i]); + } + for (i=0;i<2;i++) + SetIMR_n((struct rtl8192cd_priv *)if_priv[i], ch[i]); + for (i=0;i<2;i++) + PHY_IQCalibrate((struct rtl8192cd_priv *)if_priv[i]); + + printk("Non-interrupt antenna switched!\n"); + ret = 0; + }else { + printk("NOT DMDP, cannot support antenna switch\n"); + ret = -1; + } + break; + } +#endif // EN_EFUSE +#ifdef DPK_92D + case SIOC92DDPK: + { + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_5G){ + if (priv->pshare->rf_ft_var.dpk_on){ + int ch = PHY_QueryRFReg(priv,RF92CD_PATH_A,0x18,0xff,1); + unsigned int curMaxRFPath, eRFPath; + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + curMaxRFPath = RF92CD_PATH_B; + else + curMaxRFPath = RF92CD_PATH_MAX; + + for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++){ + if (eRFPath == RF92CD_PATH_A) + PHY_SetBBReg(priv, 0xb68, bMaskDWord, 0x28080000); + else + PHY_SetBBReg(priv, 0xb6c, bMaskDWord, 0x28080000); + + if (ch<=64){ + PHY_SetRFReg(priv,eRFPath,0x03,bMask20Bits,0x94a12); + delay_us(10); + PHY_SetRFReg(priv,eRFPath,0x04,bMask20Bits,0x94a12); + PHY_SetRFReg(priv,eRFPath,0x0e,bMask20Bits,0x94a12); + }else if (ch<=140){ + PHY_SetRFReg(priv,eRFPath,0x03,bMask20Bits,0x94a52); + delay_us(10); + PHY_SetRFReg(priv,eRFPath,0x04,bMask20Bits,0x94a52); + PHY_SetRFReg(priv,eRFPath,0x0e,bMask20Bits,0x94a52); + }else{ + PHY_SetRFReg(priv,eRFPath,0x03,bMask20Bits,0x94a12); + delay_us(10); + PHY_SetRFReg(priv,eRFPath,0x04,bMask20Bits,0x94a12); + PHY_SetRFReg(priv,eRFPath,0x0e,bMask20Bits,0x94a12); + } + + PHY_SetRFReg(priv,eRFPath,0x16,bMask20Bits,0xe1874); + PHY_SetRFReg(priv,eRFPath,0x16,bMask20Bits,0xa1874); + PHY_SetRFReg(priv,eRFPath,0x16,bMask20Bits,0x61874); + PHY_SetRFReg(priv,eRFPath,0x16,bMask20Bits,0x21874); + + } + priv->pshare->rf_ft_var.dpk_on = 0; + panic_printk("DPK OFF!\n"); + }else{ + priv->pshare->rf_ft_var.dpk_on = 1; + panic_printk("DPK ON!\n"); + PHY_DPCalibrate(priv); + } + ret = 0; + }else { + panic_printk("NO DPK for 2G!\n"); + ret = -1; + } + break; + } +#endif +#endif // CONFIG_RTL_92D_SUPPORT +#if defined(RTK_AC_SUPPORT) || defined(HS2_SUPPORT) || defined(CONFIG_IEEE80211W)//for 11ac logo, hs2.0 release 1 logo + case SIOC8812SIGMA: + { + panic_printk("Reset Default for SIGMA!!\n"); + reset_default_sigma(priv); + ret=0; + break; + } +#endif + +#if defined(RTK_AC_SUPPORT) + case SIOC8812SIGMATB: + { + panic_printk("Reset Default for SIGMA TestBed!!\n"); + reset_default_sigma(priv); + reset_default_sigma_testbed(priv); + ret=0; + break; + } +#endif + + case SIOCTXPWRAPPLY: + SetTxPowerLevel(priv); + ret = 0; + break; + +#ifdef DFS + case SIOCRESETNOPCHANNEL: + reset_nop_channel(priv); + ret = 0; + break; +#endif + } + +#ifdef SMP_SYNC + RESTORE_INT(priv->pshare->irq_save); + SMP_UNLOCK(priv->pshare->irq_save); +#else + RESTORE_INT(flags); +#endif + + return ret; +} + + +void delay_us(unsigned int t) +{ +#ifdef __LINUX_2_6__ +#if defined(CONFIG_RTL8672) || defined(NOT_RTK_BSP) + udelay(t); +#else + __udelay(t); +#endif +#else + __udelay(t, __udelay_val); +#endif +} + +#ifdef CONFIG_RTL_ALP +#define STATUS_FILE "/var/run/sitesurvey.xml" +#include +int rtl8192cd_ss_req_toXML(struct rtl8192cd_priv *priv) +{ + INT8 ret = 0; +#ifdef CONFIG_RTK_MESH + // by GANTOE for manual site survey 2008/12/25 + // inserted by Joule for simple channel unification protocol 2009/01/06 + if((priv->auto_channel &0x30) && timer_pending(&priv->ss_timer)) + ret = -2; + else +#endif + { + if (!netif_running(priv->dev) || priv->ss_req_ongoing) + ret = -1; + else + ret = 0; + } + if (!ret) // now, let's start site survey + { + priv->ss_ssidlen = 0; + DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=0\n", (char *)__FUNCTION__); + priv->ss_req_ongoing = 1; + start_clnt_ss(priv); + } + return 0; +} + +extern int encode_ssid_str(const char *source,char *dest); +typedef enum { BAND_11B=1, BAND_11G=2, BAND_11BG=3, BAND_11A=4, BAND_11N=8, BAND_5G_11AN=12 } BAND_TYPE_T; +int rtl8192cd_get_ss_status_toXML(struct rtl8192cd_priv *priv, int *data) +{ + INT8 ret = 0; + FILE *fptr; + int cnt; + struct bss_desc bss; + char tmp1Buf[20], tmp2Buf[20]; + char wpa_tkip_aes[20],wpa2_tkip_aes[20]; + char decode_ssid[200]; + + if (!netif_running(priv->dev) || priv->ss_req_ongoing) + { + diag_printf("%s: netif is not running or sitesurvey ongoing\n", __func__); + ret = -1; + } + else + { + fptr=fopen(STATUS_FILE,"w+"); + if (fptr==NULL){ + diag_printf("%s: Fail to create %s\n", __FUNCTION__, STATUS_FILE); + return -1; + } + + fprintf(fptr,""); + fprintf(fptr,"%d",priv->site_survey->count_backup); + + if (priv->site_survey->count_backup){ + for (cnt=0; cntsite_survey->count_backup; cnt++){ + bss = priv->site_survey->bss_backup[cnt]; + + memset(decode_ssid,0x00,sizeof(decode_ssid)); + encode_ssid_str(bss.ssid,decode_ssid); + + fprintf(fptr, "%s", decode_ssid); + fprintf(fptr, "%02x:%02x:%02x:%02x:%02x:%02x", + bss.bssid[0], bss.bssid[1], bss.bssid[2], + bss.bssid[3],bss.bssid[4], bss.bssid[5]); + memset(wpa_tkip_aes,0x00,sizeof(wpa_tkip_aes)); + memset(wpa2_tkip_aes,0x00,sizeof(wpa2_tkip_aes)); + if ((bss.capability & 0x10/*cPrivacy*/) == 0) { + /* No Encryption */ + sprintf(tmp2Buf, "OPEN"); + } else { + if (bss.t_stamp[0] == 0) { + /* WEP */ + sprintf(tmp2Buf, "WEP"); + } else { + int wpa_exist = 0, idx = 0; + if (bss.t_stamp[0] & 0x0000ffff) { + /* WPA */ + idx = sprintf(tmp2Buf, "WPA"); + if (((bss.t_stamp[0] & 0x0000f000) >> 12) == 0x4) { + /* WPA-PSK*/ + idx += sprintf(tmp2Buf+idx, "-PSK"); + } + wpa_exist = 1; + + if (((bss.t_stamp[0] & 0x00000f00) >> 8) == 0x5) { + /* Auto Cipher*/ + sprintf(wpa_tkip_aes,"%s","aes+tkip"); + } else if (((bss.t_stamp[0] & 0x00000f00) >> 8) == 0x4) { + /* AES */ + sprintf(wpa_tkip_aes,"%s","aes"); + } else if (((bss.t_stamp[0] & 0x00000f00) >> 8) == 0x1) { + /* TKIP */ + sprintf(wpa_tkip_aes,"%s","tkip"); + } + } + if (bss.t_stamp[0] & 0xffff0000) { + if (wpa_exist) + idx += sprintf(tmp2Buf+idx, "/"); + /* WPA2*/ + idx += sprintf(tmp2Buf+idx, "WPA2"); + if (((bss.t_stamp[0] & 0xf0000000) >> 28) == 0x4){ + /*WPA2-PSK*/ + idx += sprintf(tmp2Buf+idx, "-PSK"); + } + + if (((bss.t_stamp[0] & 0x0f000000) >> 24) == 0x5) { + /* Auto Cipher*/ + sprintf(wpa2_tkip_aes,"%s","aes+tkip"); + } else if (((bss.t_stamp[0] & 0x0f000000) >> 24) == 0x4) { + /* AES */ + sprintf(wpa2_tkip_aes,"%s","aes"); + } else if (((bss.t_stamp[0] & 0x0f000000) >> 24) == 0x1) { + /* TKIP */ + sprintf(wpa2_tkip_aes,"%s","tkip"); + } + } + } + } + fprintf(fptr, "%s", tmp2Buf); + if ((strlen(wpa_tkip_aes)!=0)&&(strlen(wpa2_tkip_aes)!=0)) + fprintf(fptr, "%s/%s", wpa_tkip_aes, wpa2_tkip_aes); + else if (strlen(wpa_tkip_aes)!=0) + fprintf(fptr, "%s", wpa_tkip_aes); + else if (strlen(wpa2_tkip_aes)!=0) + fprintf(fptr, "%s", wpa2_tkip_aes); + else + fprintf(fptr, "%s", ""); + if (bss.network==BAND_11B) + strcpy(tmp1Buf, " (B)"); + else if (bss.network==BAND_11G) + strcpy(tmp1Buf, " (G)"); + else if (bss.network==(BAND_11G|BAND_11B)) + strcpy(tmp1Buf, " (B+G)"); + else if (bss.network==(BAND_11N)) + strcpy(tmp1Buf, " (N)"); + else if (bss.network==(BAND_11G|BAND_11N)) + strcpy(tmp1Buf, " (G+N)"); + else if (bss.network==(BAND_11G|BAND_11B | BAND_11N)) + strcpy(tmp1Buf, " (B+G+N)"); + else if(bss.network== BAND_11A) + strcpy(tmp1Buf, " (A)"); + else + strcpy(tmp1Buf, " ---"); + fprintf(fptr, "%d", bss.channel); + fprintf(fptr, "%s", tmp1Buf); + fprintf(fptr, "%d", bss.rssi); + } + }; + fprintf(fptr,""); + } + + return 0; +} +#endif + +void delay_ms(unsigned int t) +{ +#if defined(CONFIG_USB_HCI) || defined(CONFIG_DIO_HCI) + // use msleep instead of mdelay to improve CPU loading when in process context + if (!in_atomic() && !irqs_disabled() && t >= (MSEC_PER_SEC / HZ)) + msleep(t); + else +#endif + mdelay(t); +} + +#ifdef _SINUX_ +enum iwpriv_type { + IW_NA, + IW_RD, + IW_WR, + IW_DP +}; + +typedef int cmd_rw_handler(struct rtl8192cd_priv *, unsigned char *); +typedef void cmd_dump_handler(struct rtl8192cd_priv *, unsigned char *); + +struct cmd_map_stru { + char *cmd_str; + void *cmd_handler; + int type; +}; + +static struct cmd_map_stru iwpriv_cmds[] = { + {"set_mib", set_mib, IW_WR}, + {"get_mib", get_mib, IW_RD}, + {"write_mem", write_mem, IW_WR}, + {"read_mem", read_mem, IW_RD}, + {"read_reg", read_reg, IW_RD}, + {"write_reg", write_reg, IW_WR}, + {"read_rf", read_rf_reg, IW_RD}, + {"write_rf", write_rf_reg, IW_WR}, + {"reg_dump", reg_dump, IW_DP}, + {NULL, NULL, IW_NA} +}; + + +int rtl8192cd_iwpriv_cmd_process(unsigned char *ifname, unsigned char *data) +{ + static unsigned char buf[1024]={0}; + struct cmd_map_stru * p_cmd; + unsigned char *para; + int ret; + struct net_device *net_dev; + struct rtl8192cd_priv *priv; + cmd_rw_handler *cmd_rw; + cmd_dump_handler *cmd_dump; + + + struct cmd_map_stru * cmds = iwpriv_cmds; + int i = 0 ; + + printk("\n"); + printk("rtl8192cd_iwpriv_cmd_process: cmd=%s\n", data); + + while (cmds[i].cmd_str != NULL ) { + if ( memcmp(data, cmds[i].cmd_str, strlen(cmds[i].cmd_str)) == 0 ) + break; + else + i++; + } + + if (cmds[i].cmd_str == NULL || cmds[i].cmd_handler == NULL) { + printk(" wireless ioctl command '%s' invalid !\n", data); + return -1; + } + + // get priv + net_dev = dev_get_by_name(ifname); + if (net_dev == NULL) + { + printk("rtl8192cd_iwpriv_cmd_process: can not get dev %s\n", data); + return -ENETDOWN; + } + priv = (struct rtl8192cd_priv *)net_dev -> priv; + + // put command parameter into buf + para = data + strlen(cmds[i].cmd_str); + para += strspn(para, " \t"); + + strncpy(buf, para, 1024); + buf[1023] = '\0'; + + // run command + printk("wireless ioctl: cmd=%s, para=%s\n", cmds[i].cmd_str, buf); + + if (cmds[i].type == IW_DP) { // dump command + cmd_dump = (cmd_dump_handler *)cmds[i].cmd_handler; + cmd_dump(priv, buf); + dev_put(net_dev); + return 0; + } + else { // read/write command + cmd_rw = (cmd_rw_handler *)cmds[i].cmd_handler; + ret = cmd_rw(priv, buf); + dev_put(net_dev); + if (ret < 0) { + printk("run fail!\n"); + return ret; + } + } + + printk("run successful !\n"); + + if (cmds[i].type == IW_RD) { + buf[ret] = '\0'; // add '\0' end for string + printk(" result length: %d\n", ret); + printk(" result text : %s\n", buf); + for (i=0; i priv; + + retlen = get_mib(priv, data); + + dev_put(net_dev); + + if (retlen > 0) + return retlen; + else + return -1; +} + + +int sos_ioctl_priv_set( + char *netName, + char *name, + void *value) +{ + int ret = 0; +#ifndef SMP_SYNC + unsigned long flags; +#endif + struct net_device *net_dev; + struct rtl8192cd_priv *priv; + int sizeof_tmpbuf; + static unsigned char tmpbuf[1024]; + + char *this_char = name; + char *this_value = (char *)value; + + sizeof_tmpbuf = sizeof(tmpbuf); + memset(tmpbuf, '\0', sizeof_tmpbuf); + + net_dev = dev_get_by_name(netName); + + if (net_dev == NULL) + { + printk("sos_ioctl_priv_set: %scan not get dev\n", netName); + return -ENETDOWN; + } + + priv = (struct rtl8192cd_priv *)net_dev->priv; + + SAVE_INT_AND_CLI(flags); + + memcpy(tmpbuf, this_char, strlen(this_char)); + ret = set_mib(priv, tmpbuf); + dev_put(net_dev); + if (ret == 0) + strcpy(this_value, tmpbuf); + + printk("sos_ioctl_priv_set: set_mib return %d\n", ret); + + RESTORE_INT(flags); + + return ret; +} + +struct wifi_mib * get_wlandev_mib(struct net_device *dev) +{ + struct rtl8192cd_priv * priv; + + if (dev == NULL) + return NULL; + + priv = (struct rtl8192cd_priv *) (dev -> priv); + + return priv -> pmib; +} + +struct spinlock_t * get_wlandev_lock (struct net_device *dev) +{ + struct rtl8192cd_priv * priv; + + if (dev == NULL) + return NULL; + + priv = (struct rtl8192cd_priv *) (dev -> priv); + + return & (priv -> pshare -> lock); + +} + +#if 0 +/* rtl8192cd_getMacTable return mac num, if fail return -1 */ +int rtl8192cd_get_staInfo(char *wlan_ifname, sta_info_2_web **ppsta_info, int *sta_len) +{ + struct net_device *net_dev; + struct rtl8192cd_priv *priv; + int sizeof_tmpbuf; + unsigned char *tmp1; + sta_info_2_web *psta_info; + int i,j=0; + + net_dev = dev_get_by_name(wlan_ifname); + + if (net_dev == NULL) + { + printk("rtl8192cd_get_staInfo(): can not get dev %s\n", wlan_ifname); + return -1; + } + + priv = (struct rtl8192cd_priv *)net_dev -> priv; + + dev_put(net_dev); + + + sizeof_tmpbuf = sizeof(sta_info_2_web) * (NUM_STAT + 1); // for the max of all sta info + tmp1 = (unsigned char *)kmalloc(sizeof_tmpbuf, GFP_ATOMIC); + + if (!tmp1) { + printk("Unable to allocate temp buffer for rtl8192cd_get_staInfo()!\n"); + return -1; + } + memset(tmp1, '\0', sizeof(sta_info_2_web)); + + get_sta_info(priv, (sta_info_2_web *)(tmp1 + sizeof(sta_info_2_web)), NUM_STAT); + +/* + for (i=0,j=0; i< maxLen; i++) { + psta_info = (sta_info_2_web *)(tmp1 + sizeof(sta_info_2_web)*(i+1)); + if (memcmp(psta_info->addr, "\x0\x0\x0\x0\x0\x0", 6)!=0) { + memcpy(macTable+j*6, psta_info->addr, 6); + j++; + } + } +*/ + *ppsta_info = tmp1; + *sta_len = NUM_STAT+1; + + return 0; +} + + +void rtl8192cd_put_staInfo(sta_info_2_web *psta_info) +{ + if (psta_info != NULL) + kfree(psta_info); + + return; +} + +#endif + +int rtl8192cd_getAutoChannel(char *wlan_ifname, int *channel) +{ + struct net_device *net_dev; + struct rtl8192cd_priv *priv; + unsigned int ret; + + net_dev = dev_get_by_name(wlan_ifname); + + if (net_dev == NULL) + { + printk("sos_ioctl_priv_stat: can not get dev %s\n", wlan_ifname); + return -1; + } + + priv = (struct rtl8192cd_priv *)net_dev -> priv; + + *channel = priv->pmib->dot11RFEntry.dot11channel; + + ret=priv->pmib->dot11nConfigEntry.dot11n2ndChOffset; + + dev_put(net_dev); + + return ret; +} + +int rtl8192cd_get_sta_num(char *wlan_ifname) +{ + struct net_device *net_dev=NULL; + struct rtl8192cd_priv *priv=NULL; + int number=0; + + net_dev = dev_get_by_name(wlan_ifname); + if (net_dev ) + { + priv = (struct rtl8192cd_priv *)net_dev -> priv; + number = priv->assoc_num; + dev_put(net_dev); + } + + return number; +} + +#ifdef _SINUX_ +/* Dynamic adjust RF power + * + * para values is char array, length must be 28. + * + */ +int rtl8192cd_adjust_rf_power(struct net_device *wdev, char *values) +{ + struct rtl8192cd_priv *priv = wdev->priv; + struct rf_finetune_var * pvar = &(priv->pshare->rf_ft_var); + + pvar->txPowerPlus_cck_1 = values[0]; + pvar->txPowerPlus_cck_2 = values[1]; + pvar->txPowerPlus_cck_5 = values[2]; + pvar->txPowerPlus_cck_11 = values[3]; + pvar->txPowerPlus_ofdm_6 = values[4]; + pvar->txPowerPlus_ofdm_9 = values[5]; + pvar->txPowerPlus_ofdm_12 = values[6]; + pvar->txPowerPlus_ofdm_18 = values[7]; + pvar->txPowerPlus_ofdm_24 = values[8]; + pvar->txPowerPlus_ofdm_36 = values[9]; + pvar->txPowerPlus_ofdm_48 = values[10]; + pvar->txPowerPlus_ofdm_54 = values[11]; + pvar->txPowerPlus_mcs_0 = values[12]; + pvar->txPowerPlus_mcs_1 = values[13]; + pvar->txPowerPlus_mcs_2 = values[14]; + pvar->txPowerPlus_mcs_3 = values[15]; + pvar->txPowerPlus_mcs_4 = values[16]; + pvar->txPowerPlus_mcs_5 = values[17]; + pvar->txPowerPlus_mcs_6 = values[18]; + pvar->txPowerPlus_mcs_7 = values[19]; + pvar->txPowerPlus_mcs_8 = values[20]; + pvar->txPowerPlus_mcs_9 = values[21]; + pvar->txPowerPlus_mcs_10 = values[22]; + pvar->txPowerPlus_mcs_11 = values[23]; + pvar->txPowerPlus_mcs_12 = values[24]; + pvar->txPowerPlus_mcs_13 = values[25]; + pvar->txPowerPlus_mcs_14 = values[26]; + pvar->txPowerPlus_mcs_15 = values[27]; + + return 0; +} + +EXPORT_SYMBOL(rtl8192cd_adjust_rf_power); +#endif + +EXPORT_SYMBOL(AddDelMCASTGroup2STA); +EXPORT_SYMBOL(rtl8192cd_get_sta_num); +EXPORT_SYMBOL(get_wlandev_lock); +EXPORT_SYMBOL(get_wlandev_mib); +EXPORT_SYMBOL(sos_ioctl_priv_set); +EXPORT_SYMBOL(sos_ioctl_priv_get); +EXPORT_SYMBOL(rtl8192cd_getMacTable); +EXPORT_SYMBOL(rtl8192cd_check_wlan_mac); +EXPORT_SYMBOL(rtl8192cd_getAutoChannel); +EXPORT_SYMBOL(rtl8192cd_iwpriv_cmd_process); + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_led.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_led.c new file mode 100755 index 000000000..2eac0f5f7 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_led.c @@ -0,0 +1,646 @@ +/* + * Handling routines for LED lightening functions + * + * $Id: 8192cd_led.c,v 1.1 2012/05/04 12:49:07 jimmylin Exp $ + * + * Copyright (c) 2012 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_LED_C_ + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + + +// for SW LED ---------------------------------------------------- +#ifdef RTL8190_SWGPIO_LED +static void set_swGpio_LED(struct rtl8192cd_priv *priv, unsigned int ledNum, int flag) +{ + unsigned int ledItem; /* parameter to decode GPIO item */ + + if (ledNum >= SWLED_GPIORT_CNT) + return; + + ledItem = SWLED_GPIORT_ITEM(LED_ROUTE, ledNum); + + if (ledItem & SWLED_GPIORT_ENABLEMSK) + { + /* get the corresponding information (GPIO number/Active high or low) of LED */ + int gpio; + int activeMode; /* !=0 : Active High, ==0 : Active Low */ + + gpio = ledItem & SWLED_GPIORT_RTBITMSK; + activeMode = ledItem & SWLED_GPIORT_HLMSK; + + if (flag) { /* Turn ON LED */ + if (activeMode) /* Active High */ + RTL_W8(0x90, RTL_R8(0x90) | BIT(gpio)); + else /* Active Low */ + RTL_W8(0x90, RTL_R8(0x90) &~ BIT(gpio)); + } + else { /* Turn OFF LED */ + if (activeMode) /* Active High */ + RTL_W8(0x90, RTL_R8(0x90) &~ BIT(gpio)); + else /* Active Low */ + RTL_W8(0x90, RTL_R8(0x90) | BIT(gpio)); + } + } +} +#endif // RTL8190_SWGPIO_LED + + +static void set_sw_LED0(struct rtl8192cd_priv *priv, int flag) +{ +#ifdef RTL8190_SWGPIO_LED + if (LED_ROUTE) + set_swGpio_LED(priv, 0, flag); +#elif defined(CONFIG_RTL8672) || defined(NOT_RTK_BSP) + if (flag) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfffffff0) | LED0SV); + else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0xfffffff0); +#else + if ((GET_CHIP_VER(priv) == VERSION_8188E)||(GET_CHIP_VER(priv) == VERSION_8192E)) { +#ifdef RTLWIFINIC_GPIO_CONTROL + if (flag) + RTLWIFINIC_GPIO_write(5, 0); + else + RTLWIFINIC_GPIO_write(5, 1); +#endif + } + else if ((GET_CHIP_VER(priv) == VERSION_8812E)) { + if (flag) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfffff0ff) | LED1SV); + else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0xfffff0ff); + } + else if (GET_CHIP_VER(priv) == VERSION_8881A) { + if (flag) + writel(readl(IO_TYPE_CAST(0xb800350c)) | BIT(24), IO_TYPE_CAST(0xb800350c)); + else + writel(readl(IO_TYPE_CAST(0xb800350c)) & ~BIT(24), IO_TYPE_CAST(0xb800350c)); + } + else { + if (flag) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfffffff0) | LED0SV); + else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0xfffffff0); + } +#endif +} + + +static void set_sw_LED1(struct rtl8192cd_priv *priv, int flag) +{ +#ifdef RTL8190_SWGPIO_LED + if (LED_ROUTE) + set_swGpio_LED(priv, 1, flag); +#elif defined(CONFIG_RTL8672) || defined(NOT_RTK_BSP) + if (flag) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfffff0ff) | LED1SV); + else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0xfffff0ff); +#else + if ((GET_CHIP_VER(priv) == VERSION_8188E)||(GET_CHIP_VER(priv) == VERSION_8192E)) { +#ifdef RTLWIFINIC_GPIO_CONTROL + if (flag) + RTLWIFINIC_GPIO_write(5, 0); + else + RTLWIFINIC_GPIO_write(5, 1); +#endif + } +#if defined(CONFIG_RTL_92D_SUPPORT) + else if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (flag) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfffff0ff) | LED1SV_92D); + else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0xfffff0ff); + } +#endif + else if (GET_CHIP_VER(priv) == VERSION_8192C){ + if (flag) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfffff0ff) | LED1SV); + else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0xfffff0ff); + } +#endif +} + + +static void set_sw_LED2(struct rtl8192cd_priv *priv, int flag) +{ +#ifdef RTL8190_SWGPIO_LED + if (LED_ROUTE) + set_swGpio_LED(priv, 2, flag); +#elif defined(CONFIG_RTL8672) || defined(NOT_RTK_BSP) + if (flag) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfff0ffff) | LED2SV); + else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0xfff0ffff); +#else + + if ((GET_CHIP_VER(priv) == VERSION_8188E)||(GET_CHIP_VER(priv) == VERSION_8192E)) { +#ifdef RTLWIFINIC_GPIO_CONTROL + if (flag) + RTLWIFINIC_GPIO_write(5, 0); + else + RTLWIFINIC_GPIO_write(5, 1); +#endif + } +#if defined(CONFIG_RTL_92D_SUPPORT) + else if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (flag) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfff0ffff) | LED2SV_92D); + else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0xfff0ffff); + } +#endif + else if (GET_CHIP_VER(priv) == VERSION_8192C){ + if (flag) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG) & 0xfff0ffff) | LED2SV); + else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) & 0xfff0ffff); + } +#endif +} + +static void LED_Interval_timeout(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + int led_on_time= LED_ON_TIME; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state != L1) && (priv->pwr_state != L2)) +#endif + { + if (!priv->pshare->set_led_in_progress) { +#if defined(CONFIG_RTL8672) || defined(NOT_RTK_BSP) +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + set_sw_LED2(priv, priv->pshare->LED_Toggle); + else +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + set_sw_LED0(priv, priv->pshare->LED_Toggle); + else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + set_sw_LED1(priv, priv->pshare->LED_Toggle); + else +#endif +#endif // CONFIG_RTL8672 || NOT_RTK_BSP + if ((LED_TYPE == LEDTYPE_SW_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LINKTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_ENABLETXRXDATA) || + ((LED_TYPE == LEDTYPE_SW_ADATA_GDATA) && (priv->pshare->curr_band == BAND_5G)) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ENABLETXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ASOCTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA_92D) || + (LED_TYPE == LEDTYPE_SW_LED1_GPIO9_LINKTXRX_92D) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX_92D)) + { + if ((LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ENABLETXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ASOCTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA_92D) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX_92D)) + set_sw_LED2(priv, priv->pshare->LED_Toggle); + else if (LED_TYPE == LEDTYPE_SW_LED1_GPIO9_LINKTXRX_92D) + set_sw_LED1(priv, priv->pshare->LED_Toggle); + else + set_sw_LED0(priv, priv->pshare->LED_Toggle); + } else { + set_sw_LED1(priv, priv->pshare->LED_Toggle); + } + } + } + + if( (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ASOCTXRXDATA) && + (!(OPMODE & WIFI_ASOC_STATE))) //client not assco , mark_led + { + led_on_time = LED_NOBLINK_TIME; + } + + if ( priv->pshare->LED_Toggle == priv->pshare->LED_ToggleStart) { + mod_timer(&priv->pshare->LED_Timer, jiffies + priv->pshare->LED_Interval); + } else { + if (LED_TYPE == LEDTYPE_SW_CUSTOM1) + mod_timer(&priv->pshare->LED_Timer, jiffies + priv->pshare->LED_Interval); + else + mod_timer(&priv->pshare->LED_Timer, jiffies + led_on_time); + } + + priv->pshare->LED_Toggle = (priv->pshare->LED_Toggle + 1) % 2; +} + + +void enable_sw_LED(struct rtl8192cd_priv *priv, int init) +{ +#if (defined(HW_ANT_SWITCH) || defined(SW_ANT_SWITCH))&&( defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + int b23 = RTL_R32(LEDCFG) & BIT(23); +#endif + + if (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ASOCTXRXDATA) + if (!(OPMODE & WIFI_STATION_STATE)) // if it is not Client mode , then run orignal 12 type + LED_TYPE = LEDTYPE_SW_LED2_GPIO8_ENABLETXRXDATA ; + + // configure mac to use SW LED +#if defined(CONFIG_RTL8672) || defined(NOT_RTK_BSP) +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG)&0xFF00FFFF) | LED2EN | LED2SV); + else +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG)&0xFFFFFF00) | LED0SV); + else +#endif +#else // !CONFIG_RTL8672 && !NOT_RTK_BSP + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) //mark_ecos + if ((GET_CHIP_VER(priv) == VERSION_8188E)||(GET_CHIP_VER(priv) == VERSION_8192E)) + { +#ifdef RTLWIFINIC_GPIO_CONTROL + RTLWIFINIC_GPIO_config(5, 0x10); +#endif + } + else +#endif +#endif // CONFIG_RTL8672 || NOT_RTK_BSP + if (GET_CHIP_VER(priv) == VERSION_8812E) + RTL_W32(LEDCFG, BIT(13) | LED1SV); + else +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv) == VERSION_8881A) { + writel(readl(IO_TYPE_CAST(0xb8000044)) | BIT(15) | BIT(16), IO_TYPE_CAST(0xb8000044)); + writel(readl(IO_TYPE_CAST(0xb8003500)) & ~BIT(24), IO_TYPE_CAST(0xb8003500)); + writel(readl(IO_TYPE_CAST(0xb8003508)) | BIT(24), IO_TYPE_CAST(0xb8003508)); + writel(readl(IO_TYPE_CAST(0xb800350c)) | BIT(24), IO_TYPE_CAST(0xb800350c)); + } else +#endif + { + if (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG)&0xFF00FFFF) | LED2EN | LED2SV); + else if (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG)&0xFF00FFFF) | LED2EN | LED2SV); +#ifdef CONFIG_RTL_92D_SUPPORT + else if ((LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX_92D) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA_92D)) + RTL_W32(LEDCFG,(RTL_R32(LEDCFG)&0xFF00FFFF)| LED2DIS_92D | LED2SV_92D); + else if (LED_TYPE == LEDTYPE_SW_LED1_GPIO9_LINKTXRX_92D) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG)&0xFFFF00FF)|LED1DIS_92D | LED1SV_92D); +#endif + else if ((LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ENABLETXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ASOCTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRXDATA)) + RTL_W32(LEDCFG, (RTL_R32(LEDCFG)&0xFF00FFFF) | GP8_LED | LED2EN | LED2SV); + else + RTL_W32(LEDCFG, LED2SV | LED1SV | LED0SV); + } + + priv->pshare->LED_Interval = LED_INTERVAL_TIME; + priv->pshare->LED_Toggle = 0; + priv->pshare->LED_ToggleStart = LED_OFF; + priv->pshare->LED_tx_cnt_log = 0; + priv->pshare->LED_rx_cnt_log = 0; + priv->pshare->LED_tx_cnt = 0; + priv->pshare->LED_rx_cnt = 0; + + if ((LED_TYPE == LEDTYPE_SW_ENABLE_TXRXDATA) || + (LED_TYPE == LEDTYPE_SW_ENABLETXRXDATA)) { + set_sw_LED0(priv, LED_ON); + set_sw_LED1(priv, LED_OFF); + + if (LED_TYPE == LEDTYPE_SW_ENABLETXRXDATA) + priv->pshare->LED_ToggleStart = LED_ON; + } else if ((LED_TYPE == LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_ENABLETXRXDATA_92D)) { + set_sw_LED2(priv, LED_ON); + priv->pshare->LED_ToggleStart = LED_ON; + } else if (LED_TYPE == LEDTYPE_SW_ADATA_GDATA) { + priv->pshare->LED_ToggleStart = LED_ON; + if (priv->pshare->curr_band == BAND_5G) { + set_sw_LED0(priv, LED_ON); + set_sw_LED1(priv, LED_OFF); + } + else { // 11G + set_sw_LED0(priv, LED_OFF); + set_sw_LED1(priv, LED_ON); + } + } + else if (LED_TYPE == LEDTYPE_SW_ENABLETXRXDATA_1) { + set_sw_LED0(priv, LED_OFF); + set_sw_LED1(priv, LED_ON); + priv->pshare->LED_ToggleStart = LED_ON; + } + else if ((LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ENABLETXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ASOCTXRXDATA) ) { + set_sw_LED2(priv, LED_ON); + priv->pshare->LED_ToggleStart = LED_ON; + } + else if ((LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRXDATA)) { + set_sw_LED2(priv, LED_OFF); + } + else { + set_sw_LED0(priv, LED_OFF); + set_sw_LED1(priv, LED_OFF); + set_sw_LED2(priv, LED_OFF); + } + +#if (defined(HW_ANT_SWITCH) || defined(SW_ANT_SWITCH))&&( defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + RTL_W32(LEDCFG, b23 | RTL_R32(LEDCFG)); +#endif + + if (init) { + init_timer(&priv->pshare->LED_Timer); +#if defined(CONFIG_PCI_HCI) + priv->pshare->LED_Timer.data = (unsigned long) priv; + priv->pshare->LED_Timer.function = &LED_Interval_timeout; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + priv->pshare->LED_Timer.data = (unsigned long) &priv->pshare->LED_Timer_event; + priv->pshare->LED_Timer.function = timer_event_timer_fn; + INIT_TIMER_EVENT_ENTRY(&priv->pshare->LED_Timer_event, + LED_Interval_timeout, (unsigned long)priv); +#endif + + mod_timer(&priv->pshare->LED_Timer, jiffies + priv->pshare->LED_Interval); + } +} + + +void disable_sw_LED(struct rtl8192cd_priv *priv) +{ + if (timer_pending(&priv->pshare->LED_Timer)) + del_timer_sync(&priv->pshare->LED_Timer); + + if ((LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ENABLETXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ASOCTXRXDATA)) { + set_sw_LED2(priv, LED_OFF); + } else { + set_sw_LED0(priv, LED_OFF); + set_sw_LED1(priv, LED_OFF); + set_sw_LED2(priv, LED_OFF); + } +} + + +void calculate_sw_LED_interval(struct rtl8192cd_priv *priv) +{ + unsigned int delta = 0; + int i, scale_num=0; + + if (priv->pshare->set_led_in_progress) + return; + + if( (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_ASOCTXRXDATA) && + (!(OPMODE & WIFI_ASOC_STATE))) //client not assco , mark_led + { + priv->pshare->LED_Interval = LED_NOBLINK_TIME; // force one second + priv->pshare->LED_tx_cnt_log = priv->pshare->LED_tx_cnt; // sync tx/rx cnt + priv->pshare->LED_rx_cnt_log = priv->pshare->LED_rx_cnt; + return ; + } + + // calculate counter delta + delta += UINT32_DIFF(priv->pshare->LED_tx_cnt, priv->pshare->LED_tx_cnt_log); + delta += UINT32_DIFF(priv->pshare->LED_rx_cnt, priv->pshare->LED_rx_cnt_log); + priv->pshare->LED_tx_cnt_log = priv->pshare->LED_tx_cnt; + priv->pshare->LED_rx_cnt_log = priv->pshare->LED_rx_cnt; + + // update interval according to delta + if (delta == 0) { + if (LED_TYPE == LEDTYPE_SW_CUSTOM1) { + if (priv->pshare->LED_Interval != RTL_SECONDS_TO_JIFFIES(1)) { + priv->pshare->LED_Interval = RTL_SECONDS_TO_JIFFIES(1); + mod_timer(&priv->pshare->LED_Timer, jiffies + priv->pshare->LED_Interval); + } + } else { + if (priv->pshare->LED_Interval == LED_NOBLINK_TIME) + mod_timer(&priv->pshare->LED_Timer, jiffies + priv->pshare->LED_Interval); + else { + priv->pshare->LED_Interval = LED_NOBLINK_TIME; + if (LED_TYPE == LEDTYPE_SW_ENABLETXRXDATA) + priv->pshare->LED_Toggle = LED_ON; + } + } + } else { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) || + (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A)) + scale_num = LED_MAX_PACKET_CNT_AG / LED_MAX_SCALE; + else + scale_num = LED_MAX_PACKET_CNT_B / LED_MAX_SCALE; + + if ((LED_TYPE == LEDTYPE_SW_LINK_TXRX) || + (LED_TYPE == LEDTYPE_SW_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED1_GPIO9_LINKTXRX_92D) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX_92D) || + (LED_TYPE == LEDTYPE_SW_CUSTOM1)) + scale_num = scale_num*2; + + for (i=1; i<=LED_MAX_SCALE; i++) { + if (delta < i*scale_num) + break; + } + + if (priv->pshare->rf_ft_var.ledBlinkingFreq > 1) { + i = i*priv->pshare->rf_ft_var.ledBlinkingFreq; + if (i > LED_MAX_SCALE) + i = LED_MAX_SCALE; + } + + priv->pshare->LED_Interval = ((LED_MAX_SCALE-i+1)*LED_INTERVAL_TIME)/LED_MAX_SCALE; + + if (priv->pshare->LED_Interval < LED_ON_TIME) + priv->pshare->LED_Interval = LED_ON_TIME; + } + + if ((LED_TYPE == LEDTYPE_SW_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LINKTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRXDATA) || + (LED_TYPE == LEDTYPE_SW_LED1_GPIO9_LINKTXRX_92D) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX_92D)) { + if (priv->link_status) + priv->pshare->LED_ToggleStart = LED_ON; + else + priv->pshare->LED_ToggleStart = LED_OFF; + } else { + if (priv->pshare->set_led_in_progress) + return; + + if ((LED_TYPE == LEDTYPE_SW_LINK_TXRX) || + (LED_TYPE == LEDTYPE_SW_LINK_TXRXDATA)) { + if (priv->link_status) + set_sw_LED0(priv, LED_ON); + else + set_sw_LED0(priv, LED_OFF); + } else if (LED_TYPE == LEDTYPE_SW_ADATA_GDATA) { + if (priv->pshare->curr_band == BAND_5G) { + set_sw_LED0(priv, LED_ON); + set_sw_LED1(priv, LED_OFF); + } else { // 11A + set_sw_LED0(priv, LED_OFF); + set_sw_LED1(priv, LED_ON); + } + } + } +} + +#if 0 + +void set_wireless_LED_steady_on(int led_num, struct net_device *dev) +{ + struct rtl8192cd_priv *priv; + + if (led_num != LED_0 && led_num != LED_1 && led_num != LED_2) + return; + +#ifdef NETDEV_NO_PRIV + if (dev == NULL || netdev_priv(dev) == NULL) + return; + + priv = ((struct rtl8192cd_priv *)netdev_priv(dev))->wlan_priv; +#else + if (dev == NULL || dev->priv == NULL) + return; + + priv = (struct rtl8192cd_priv *)dev->priv; +#endif + + + if (priv->pshare == NULL) + return; + + priv->pshare->set_led_in_progress = 1; + + if ((LED_TYPE >= LEDTYPE_HW_TX_RX) && (LED_TYPE <= LEDTYPE_HW_LINKACT_INFRA)) { + enable_sw_LED(priv, 0); + } + else if ((LED_TYPE >= LEDTYPE_SW_LINK_TXRX) && (LED_TYPE < LEDTYPE_SW_MAX)) { + if (timer_pending(&priv->pshare->LED_Timer)) + del_timer_sync(&priv->pshare->LED_Timer); + } + + if (led_num == LED_0) + set_sw_LED0(priv, LED_ON); + else if (led_num == LED_1) + set_sw_LED1(priv, LED_ON); + else + set_sw_LED2(priv, LED_ON); +} + + +void recover_wireless_LED(struct net_device *dev) +{ + struct rtl8192cd_priv *priv; + +#ifdef NETDEV_NO_PRIV + if (dev == NULL || netdev_priv(dev) == NULL) + return; + + priv = ((struct rtl8192cd_priv *)netdev_priv(dev))->wlan_priv; +#else + if (dev == NULL || dev->priv == NULL) + return; + + priv = (struct rtl8192cd_priv *)dev->priv; +#endif + + if (!priv->pshare->set_led_in_progress) + return; + + // for HW/SW LED + if ((LED_TYPE >= LEDTYPE_HW_TX_RX) && (LED_TYPE <= LEDTYPE_HW_LINKACT_INFRA)) { + set_sw_LED0(priv, LED_OFF); + set_sw_LED1(priv, LED_OFF); + set_sw_LED2(priv, LED_OFF); + enable_hw_LED(priv, LED_TYPE); + } + else if ((LED_TYPE >= LEDTYPE_SW_LINK_TXRX) && (LED_TYPE < LEDTYPE_SW_MAX)) { + enable_sw_LED(priv, 0); + mod_timer(&priv->pshare->LED_Timer, jiffies + priv->pshare->LED_Interval); + } + + priv->pshare->set_led_in_progress = 0; +} +#endif + + +void control_wireless_led(struct rtl8192cd_priv *priv, int enable) +{ + if (enable == 0) { + priv->pshare->set_led_in_progress = 1; + set_sw_LED0(priv, LED_OFF); + set_sw_LED1(priv, LED_OFF); + set_sw_LED2(priv, LED_OFF); + } + else if (enable == 1) { + priv->pshare->set_led_in_progress = 1; + set_sw_LED0(priv, LED_ON); + set_sw_LED1(priv, LED_ON); + set_sw_LED2(priv, LED_ON); + } + else if (enable == 2) { + set_sw_LED0(priv, priv->pshare->LED_ToggleStart); + set_sw_LED1(priv, priv->pshare->LED_ToggleStart); + set_sw_LED2(priv, priv->pshare->LED_ToggleStart); + priv->pshare->set_led_in_progress = 0; + } +} + + +#ifdef CONFIG_RTL_ULINKER +static struct rtl8192cd_priv *root_priv = NULL; + +void enable_sys_LED(struct rtl8192cd_priv *priv) +{ +#ifdef RTLWIFINIC_GPIO_CONTROL + RTLWIFINIC_GPIO_config(4, 0x10); +#endif + root_priv = priv; +} + + +void renable_sw_LED(void) +{ + struct rtl8192cd_priv *priv = root_priv; + + if ((LED_TYPE >= LEDTYPE_SW_LINK_TXRX) && (LED_TYPE < LEDTYPE_SW_MAX)) { + priv->pshare->set_led_in_progress = 1; + disable_sw_LED(priv); + priv->pshare->set_led_in_progress = 0; + enable_sw_LED(priv, 1); + } +} + +#endif /* #ifdef CONFIG_RTL_ULINKER */ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_log.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_log.h new file mode 100755 index 000000000..9ce5a1d9c --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_log.h @@ -0,0 +1,45 @@ + +#ifndef 8192CD_LOG_H +#define 8192CD_LOG_H + +#if defined(CONFIG_RTL_LOG_DEBUG) + + #if defined(LOG_ERROR) + #undef LOG_ERROR + #define LOG_ERROR(fmt, args...) do{ \ + if(RTL_LogTypeMask.ERROR&&RTL_LogModuleMask.WIRELESS&&LOG_LIMIT)scrlog_printk("WLS-ERROR:"fmt, ## args); \ + }while(0) + #endif + + #if defined(LOG_MEM_ERROR) + #undef LOG_MEM_ERROR + #define LOG_MEM_ERROR(fmt, args...) do{ \ + if(RTL_LogTypeMask.ERROR&&RTL_LogErrorMask.MEM&&RTL_LogModuleMask.WIRELESS&&LOG_LIMIT)scrlog_printk("WLS-MEM-ERROR:"fmt, ## args); \ + }while(0) + #endif + + #if defined(LOG_SKB_ERROR) + #undef LOG_SKB_ERROR + #define LOG_SKB_ERROR(fmt, args...) do{ \ + if(RTL_LogTypeMask.ERROR&&RTL_LogErrorMask.SKB&&RTL_LogModuleMask.WIRELESS&&LOG_LIMIT)scrlog_printk("WLS-SKB-ERROR:"fmt, ## args); \ + }while(0) + #endif + + #if defined(LOG_WARN) + #undef LOG_WARN + #define LOG_WARN(fmt, args...) do{ \ + if(RTL_LogTypeMask.WARN&&RTL_LogModuleMask.WIRELESS&&LOG_LIMIT)scrlog_printk("WLS-WARN:"fmt, ## args); \ + }while(0) + #endif + + #if defined(LOG_INFO) + #undef LOG_INFO + #define LOG_INFO(fmt, args...) do{ \ + if(RTL_LogTypeMask.INFO&&RTL_LogModuleMask.WIRELESS&&LOG_LIMIT)scrlog_printk("WLS-INFO:"fmt, ## args); \ + }while(0) + #endif + +#endif + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_mib.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_mib.c new file mode 100755 index 000000000..adf10f8e5 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_mib.c @@ -0,0 +1,555 @@ +/* + * SNMP MIB module + * + * $Id: 8192cd_mib.c,v 1.1 2009/11/06 12:26:48 victoryman Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define _8192CD_MIB_C_ + +#ifdef __KERNEL__ +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#ifdef SUPPORT_SNMP_MIB + +#ifdef __KERNEL__ +#include "./ieee802_mib.h" +#elif defined(__ECOS) +#include +#endif +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" +#include "./8192cd_mib.h" + +extern int _convert_2_pwr_dot(char *s, int base); +extern int _atoi(char *s, int base); + +struct mib_val dot11_mib_table[]={ + //dot11StationConfigTable + { {1, 1, 1, 1, 1, -1}, "dot11StationID", MIB_TYPE_PRIV, PRIV_OFFSET(dot11OperationEntry.hwaddr), PRIV_SIZE(dot11OperationEntry.hwaddr)}, + { {1, 1, 1, 2, 1, -1}, "dot11MediumOccupancyLimit ", MIB_TYPE_VAL, 100, 1}, + { {1, 1, 1, 3, 1, -1}, "dot11CFPollable", MIB_TYPE_VAL, 0, 1}, + { {1, 1, 1, 4, 1, -1}, "dot11CFPPeriod", MIB_TYPE_VAL, 0, 1}, + { {1, 1, 1, 5, 1, -1}, "dot11CFPMaxDuration", MIB_TYPE_VAL, 0, 1}, + { {1, 1, 1, 6, 1, -1}, "dot11AuthenticationResponseTimeOut", MIB_TYPE_VAL, REAUTH_TO*10, 4}, + { {1, 1, 1, 7, 1, -1}, "dot11PrivacyOptionImplemented", MIB_TYPE_VAL, 1, 1}, + { {1, 1, 1, 8, 1, -1}, "dot11PowerManagementMode", MIB_TYPE_VAL, 1, 1}, + { {1, 1, 1, 9, 1, -1}, "dot11DesiredSSID", MIB_TYPE_PRIV, PRIV_OFFSET(dot11StationConfigEntry.dot11DesiredSSID), 0}, + { {1, 1, 1, 10, 1, -1}, "dot11DesiredBSSType", MIB_TYPE_SNMP, SNMP_OFFSET(dot11DesiredBSSType), SNMP_SIZE(dot11DesiredBSSType)}, + { {1, 1, 1, 11, 1, -1}, "dot11OperationalRateSet", MIB_TYPE_SNMP1, SNMP_OFFSET(dot11OperationalRateSet), SNMP_OFFSET(dot11SupportedDataRatesNum)}, + { {1, 1, 1, 12, 1, -1}, "dot11BeaconPeriod", MIB_TYPE_PRIV, PRIV_OFFSET(dot11StationConfigEntry.dot11BeaconPeriod), PRIV_SIZE(dot11StationConfigEntry.dot11BeaconPeriod)}, + { {1, 1, 1, 13, 1, -1}, "dot11DTIMPeriod", MIB_TYPE_PRIV, PRIV_OFFSET(dot11StationConfigEntry.dot11DTIMPeriod), PRIV_SIZE(dot11StationConfigEntry.dot11DTIMPeriod)}, + { {1, 1, 1, 14, 1, -1}, "dot11AssociationResponseTimeOut", MIB_TYPE_VAL, REASSOC_TO*10, 4}, + { {1, 1, 1, 15, 1, -1}, "dot11DisassociateReason", MIB_TYPE_SNMP, SNMP_OFFSET(dot11DisassociateReason), SNMP_SIZE(dot11DisassociateReason)}, + { {1, 1, 1, 16, 1, -1}, "dot11DisassociateStation", MIB_TYPE_SNMP, SNMP_OFFSET(dot11DisassociateStation), SNMP_SIZE(dot11DisassociateStation)}, + { {1, 1, 1, 17, 1, -1}, "dot11DeauthenticateReason", MIB_TYPE_SNMP, SNMP_OFFSET(dot11DeauthenticateReason), SNMP_SIZE(dot11DeauthenticateReason)}, + { {1, 1, 1, 18, 1, -1}, "dot11DeauthenticateStation", MIB_TYPE_SNMP, SNMP_OFFSET(dot11DeauthenticateStation), SNMP_SIZE(dot11DeauthenticateStation)}, + { {1, 1, 1, 19, 1, -1}, "dot11AuthenticateFailStatus", MIB_TYPE_SNMP, SNMP_OFFSET(dot11AuthenticateFailStatus), SNMP_SIZE(dot11AuthenticateFailStatus)}, + { {1, 1, 1, 20, 1, -1}, "dot11AuthenticateFailStation", MIB_TYPE_SNMP, SNMP_OFFSET(dot11AuthenticateFailStation), SNMP_SIZE(dot11AuthenticateFailStation)}, + { {1, 1, 1, 24, 1, -1}, "dot11RegDomain", MIB_TYPE_PRIV, PRIV_OFFSET(dot11StationConfigEntry.dot11RegDomain), PRIV_SIZE(dot11StationConfigEntry.dot11RegDomain)}, + { {1, 1, 1, 25, 1, -1}, "dot11DataRate", MIB_TYPE_SNMP, SNMP_OFFSET(dot11DataRate), SNMP_SIZE(dot11DataRate)}, + { {1, 1, 1, 26, 1, -1}, "dot11ProtectionDisabled", MIB_TYPE_PRIV, PRIV_OFFSET(dot11StationConfigEntry.protectionDisabled), PRIV_SIZE(dot11StationConfigEntry.protectionDisabled)}, + { {1, 1, 1, 27, 1, -1}, "dot11nSTBC", MIB_TYPE_PRIV, PRIV_OFFSET(dot11nConfigEntry.dot11nSTBC), PRIV_SIZE(dot11nConfigEntry.dot11nSTBC)}, + { {1, 1, 1, 28, 1, -1}, "dot11nCoexist", MIB_TYPE_PRIV, PRIV_OFFSET(dot11nConfigEntry.dot11nCoexist), PRIV_SIZE(dot11nConfigEntry.dot11nCoexist)}, + { {1, 1, 1, 29, 1, -1}, "dot11nUse40M", MIB_TYPE_PRIV, PRIV_OFFSET(dot11nConfigEntry.dot11nUse40M), PRIV_SIZE(dot11nConfigEntry.dot11nUse40M)}, + { {1, 1, 1, 30, 1, -1}, "dot11n2ndChOffset", MIB_TYPE_PRIV, PRIV_OFFSET(dot11nConfigEntry.dot11n2ndChOffset), PRIV_SIZE(dot11nConfigEntry.dot11n2ndChOffset)}, + { {1, 1, 1, 31, 1, -1}, "dot11nShortGIfor20M", MIB_TYPE_PRIV, PRIV_OFFSET(dot11nConfigEntry.dot11nShortGIfor20M), PRIV_SIZE(dot11nConfigEntry.dot11nShortGIfor20M)}, + { {1, 1, 1, 32, 1, -1}, "dot11nShortGIfor40M", MIB_TYPE_PRIV, PRIV_OFFSET(dot11nConfigEntry.dot11nShortGIfor40M), PRIV_SIZE(dot11nConfigEntry.dot11nShortGIfor40M)}, + { {1, 1, 1, 33, 1, -1}, "dot11nAMPDU", MIB_TYPE_PRIV, PRIV_OFFSET(dot11nConfigEntry.dot11nAMPDU), PRIV_SIZE(dot11nConfigEntry.dot11nAMPDU)}, + { {1, 1, 1, 34, 1, -1}, "dot11nAMSDU", MIB_TYPE_PRIV, PRIV_OFFSET(dot11nConfigEntry.dot11nAMSDU), PRIV_SIZE(dot11nConfigEntry.dot11nAMSDU)}, + { {1, 1, 1, 35, 1, -1}, "dot11nLDPC", MIB_TYPE_PRIV, PRIV_OFFSET(dot11nConfigEntry.dot11nLDPC), PRIV_SIZE(dot11nConfigEntry.dot11nLDPC)}, + //dot11AuthenticationAlgorithmsTable + { {1, 2, 1, 1, 1, -1}, "dot11AuthenticationAlgorithmsIndex", MIB_TYPE_VAL, 1, 1}, + { {1, 2, 1, 2, 1, -1}, "dot11AuthenticationAlgorithm", MIB_TYPE_VAL, 1, 1}, + { {1, 2, 1, 3, 1, -1}, "dot11AuthenticationAlgorithmsEnable", MIB_TYPE_SNMP, SNMP_OFFSET(dot11AuthenticationAlgorithmsEnableOpen), SNMP_SIZE(dot11AuthenticationAlgorithmsEnableOpen)}, + { {1, 2, 1, 1, 2, -1}, "dot11AuthenticationAlgorithmsIndex", MIB_TYPE_VAL, 2, 1}, + { {1, 2, 1, 2, 2, -1}, "dot11AuthenticationAlgorithm", MIB_TYPE_VAL, 2, 1}, + { {1, 2, 1, 3, 2, -1}, "dot11AuthenticationAlgorithmsEnable", MIB_TYPE_SNMP, SNMP_OFFSET(dot11AuthenticationAlgorithmsEnableShared), SNMP_SIZE(dot11AuthenticationAlgorithmsEnableShared)}, + + //dot11WEPDefaultKeysTable + { {1, 3, 1, 1, 1, -1}, "dot11WEPDefaultKeyIndex", MIB_TYPE_VAL, 1, 1}, + { {1, 3, 1, 2, 1, -1}, "dot11WEPDefaultKeyValue", MIB_TYPE_SNMP1, SNMP_OFFSET(dot11WEPDefaultKey1), SNMP_SIZE(dot11WEPDefaultKeyLen)}, + { {1, 3, 1, 1, 2, -1}, "dot11WEPDefaultKeyIndex", MIB_TYPE_VAL, 2, 1}, + { {1, 3, 1, 2, 2, -1}, "dot11WEPDefaultKeyValue", MIB_TYPE_SNMP1, SNMP_OFFSET(dot11WEPDefaultKey2), SNMP_SIZE(dot11WEPDefaultKeyLen)}, + { {1, 3, 1, 1, 3, -1}, "dot11WEPDefaultKeyIndex", MIB_TYPE_VAL, 3, 1}, + { {1, 3, 1, 2, 3, -1}, "dot11WEPDefaultKeyValue", MIB_TYPE_SNMP1, SNMP_OFFSET(dot11WEPDefaultKey3), SNMP_SIZE(dot11WEPDefaultKeyLen)}, + { {1, 3, 1, 1, 4, -1}, "dot11WEPDefaultKeyIndex", MIB_TYPE_VAL, 4, 1}, + { {1, 3, 1, 2, 4, -1}, "dot11WEPDefaultKeyValue", MIB_TYPE_SNMP1, SNMP_OFFSET(dot11WEPDefaultKey4), SNMP_SIZE(dot11WEPDefaultKeyLen)}, + + //dot11WEPKeyMappingsTable + { {1, 4, 1, 1, 1, -1}, "dot11WEPKeyMappingIndex", MIB_TYPE_VAL, 1, 1}, + { {1, 4, 1, 2, 1, -1}, "dot11WEPKeyMappingAddress", 0}, + { {1, 4, 1, 3, 1, -1}, "dot11WEPKeyMappingWEPOn", 0}, + { {1, 4, 1, 4, 1, -1}, "dot11WEPKeyMappingValue", 0}, + { {1, 4, 1, 5, 1, -1}, "dot11WEPKeyMappingStatus", 0}, + + //dot11PrivacyTable + { {1, 5, 1, 1, 1, -1}, "dot11PrivacyInvoked", MIB_TYPE_SNMP, SNMP_OFFSET(dot11PrivacyInvoked), SNMP_SIZE(dot11PrivacyInvoked)}, + { {1, 5, 1, 2, 1, -1}, "dot11WEPDefaultKeyID", MIB_TYPE_PRIV, PRIV_OFFSET(dot1180211AuthEntry.dot11PrivacyKeyIndex), PRIV_SIZE(dot1180211AuthEntry.dot11PrivacyKeyIndex)}, + { {1, 5, 1, 3, 1, -1}, "dot11WEPKeyMappingLength", MIB_TYPE_VAL, 10, 1}, + { {1, 5, 1, 4, 1, -1}, "dot11ExcludeUnencrypted", MIB_TYPE_SNMP, SNMP_OFFSET(dot11PrivacyInvoked), SNMP_SIZE(dot11PrivacyInvoked)}, + { {1, 5, 1, 5, 1, -1}, "dot11WEPICVErrorCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11WEPICVErrorCount), SNMP_SIZE(dot11WEPICVErrorCount)}, + { {1, 5, 1, 6, 1, -1}, "dot11WEPExcludedCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11WEPExcludedCount), SNMP_SIZE(dot11WEPExcludedCount)}, + + { {1, 8, 1, 1, 1, -1}, "dot11WPAKeyIndex", MIB_TYPE_VAL, 1, 1}, + { {1, 8, 1, 2, 1, -1}, "dot11WPAKeyFormat", MIB_TYPE_VAL, 1, 1}, + { {1, 8, 1, 3, 1, -1}, "dot11WPAKeyValue", MIB_TYPE_VAL, 1, 1}, + { {1, 9, 1, 1, 1, -1}, "dot11WPA2KeyIndex", MIB_TYPE_VAL, 1, 1}, + { {1, 9, 1, 2, 1, -1}, "dot11WPA2KeyFormat", MIB_TYPE_VAL, 1, 1}, + { {1, 9, 1, 3, 1, -1}, "dot11WPA2KeyValue", MIB_TYPE_VAL, 1, 1}, + { {1, 10, 1, 1, 1, -1}, "dot11RadiusServerIPAddress", MIB_TYPE_VAL, 1, 1}, + { {1, 10, 1, 2, 1, -1}, "dot11RadiusServerPort", MIB_TYPE_VAL, 1, 1}, + { {1, 10, 1, 3, 1, -1}, "dot11RadiusServerPassword", MIB_TYPE_VAL, 1, 1}, + { {1, 10, 1, 4, 1, -1}, "dot11RadiusServerEnable", MIB_TYPE_VAL, 1, 1}, + //dot11OperationTable + { {2, 1, 1, 1, 1, -1}, "dot11MACAddress", MIB_TYPE_PRIV, PRIV_OFFSET(dot11OperationEntry.hwaddr), PRIV_SIZE(dot11OperationEntry.hwaddr)}, + { {2, 1, 1, 2, 1, -1}, "dot11RTSThreshold", MIB_TYPE_PRIV, PRIV_OFFSET(dot11OperationEntry.dot11RTSThreshold), PRIV_SIZE(dot11OperationEntry.dot11RTSThreshold)}, + { {2, 1, 1, 3, 1, -1}, "dot11ShortRetryLimit", MIB_TYPE_PRIV, PRIV_OFFSET(dot11OperationEntry.dot11ShortRetryLimit), PRIV_SIZE(dot11OperationEntry.dot11ShortRetryLimit)}, + { {2, 1, 1, 4, 1, -1}, "dot11LongRetryLimit", MIB_TYPE_PRIV, PRIV_OFFSET(dot11OperationEntry.dot11LongRetryLimit), PRIV_SIZE(dot11OperationEntry.dot11LongRetryLimit)}, + { {2, 1, 1, 5, 1, -1}, "dot11FragmentationThreshold", MIB_TYPE_PRIV, PRIV_OFFSET(dot11OperationEntry.dot11FragmentationThreshold), PRIV_SIZE(dot11OperationEntry.dot11FragmentationThreshold)}, + { {2, 1, 1, 6, 1, -1}, "dot11MaxTransmitMSDULifetime", MIB_TYPE_VAL, 512, 1}, + { {2, 1, 1, 7, 1, -1}, "dot11MaxReceiveLifetime", MIB_TYPE_VAL, FRAG_TO*10, 4}, + { {2, 1, 1, 8, 1, -1}, "dot11ManufacturerID", MIB_TYPE_VAL, (int)"Realtek", 0}, + { {2, 1, 1, 9, 1, -1}, "dot11ProductID", MIB_TYPE_VAL, (int)"RTL8185/RTL8186", 0}, + { {2, 1, 1, 10, 1, -1}, "dot11IappEnable", MIB_TYPE_PRIV,PRIV_OFFSET(dot11OperationEntry.iapp_enable), PRIV_SIZE(dot11OperationEntry.iapp_enable)}, + { {2, 1, 1, 11, 1, -1}, "dot11BlockRelay", MIB_TYPE_PRIV,PRIV_OFFSET(dot11OperationEntry.block_relay), PRIV_SIZE(dot11OperationEntry.block_relay)}, + { {2, 1, 1, 12, 1, -1}, "dot11WIFISpecific", MIB_TYPE_PRIV,PRIV_OFFSET(dot11OperationEntry.wifi_specific), PRIV_SIZE(dot11OperationEntry.wifi_specific)}, + { {2, 1, 1, 13, 1, -1}, "dot11QosEnable", MIB_TYPE_PRIV,PRIV_OFFSET(dot11QosEntry.dot11QosEnable), PRIV_SIZE(dot11QosEntry.dot11QosEnable)}, + { {2, 1, 1, 14, 1, -1}, "dot11NetworkType", MIB_TYPE_PRIV,PRIV_OFFSET(dot11BssType.net_work_type), PRIV_SIZE(dot11BssType.net_work_type)}, + { {2, 1, 1, 15, 1, -1}, "dot11LedType", MIB_TYPE_PRIV,PRIV_OFFSET(dot11OperationEntry.ledtype), PRIV_SIZE(dot11OperationEntry.ledtype)}, + { {2, 1, 1, 16, 1, -1}, "dot11OperationMode", MIB_TYPE_PRIV,PRIV_OFFSET(dot11OperationEntry.opmode), PRIV_SIZE(dot11OperationEntry.opmode)}, + { {2, 1, 1, 17, 1, -1}, "dot11BroadCastSSID", MIB_TYPE_PRIV,PRIV_OFFSET(miscEntry.show_hidden_bss), PRIV_SIZE(miscEntry.show_hidden_bss)}, + { {2, 1, 1, 18, 1, -1}, "dot11GuestAccess", MIB_TYPE_PRIV,PRIV_OFFSET(dot11OperationEntry.guest_access), PRIV_SIZE(dot11OperationEntry.guest_access)}, + + //dot11CountersTable + { {2, 2, 1, 1, 1, -1}, "dot11TransmittedFragmentCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11TransmittedFragmentCount), SNMP_SIZE(dot11TransmittedFragmentCount)}, + { {2, 2, 1, 2, 1, -1}, "dot11MulticastTransmittedFrameCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11MulticastTransmittedFrameCount), SNMP_SIZE(dot11MulticastTransmittedFrameCount)}, + { {2, 2, 1, 3, 1, -1}, "dot11FailedCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11FailedCount), SNMP_SIZE(dot11FailedCount)}, + { {2, 2, 1, 4, 1, -1}, "dot11RetryCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11RetryCount), SNMP_SIZE(dot11RetryCount)}, + { {2, 2, 1, 5, 1, -1}, "dot11MultipleRetryCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11MultipleRetryCount), SNMP_SIZE(dot11MultipleRetryCount)}, + { {2, 2, 1, 6, 1, -1}, "dot11FrameDuplicateCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11FrameDuplicateCount), SNMP_SIZE(dot11FrameDuplicateCount)}, + { {2, 2, 1, 7, 1, -1}, "dot11RTSSuccessCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11RTSSuccessCount), SNMP_SIZE(dot11RTSSuccessCount)}, + { {2, 2, 1, 8, 1, -1}, "dot11RTSFailureCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11RTSFailureCount), SNMP_SIZE(dot11RTSFailureCount)}, + { {2, 2, 1, 9, 1, -1}, "dot11ACKFailureCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11ACKFailureCount), SNMP_SIZE(dot11ACKFailureCount)}, + { {2, 2, 1, 10, 1, -1}, "dot11ReceivedFragmentCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11ReceivedFragmentCount), SNMP_SIZE(dot11ReceivedFragmentCount)}, + { {2, 2, 1, 11, 1, -1}, "dot11MulticastReceivedFrameCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11MulticastReceivedFrameCount), SNMP_SIZE(dot11MulticastReceivedFrameCount)}, + { {2, 2, 1, 12, 1, -1}, "dot11FCSErrorCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11FCSErrorCount), SNMP_SIZE(dot11FCSErrorCount)}, + { {2, 2, 1, 13, 1, -1}, "dot11TransmittedFrameCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11TransmittedFrameCount), SNMP_SIZE(dot11TransmittedFrameCount)}, + { {2, 2, 1, 14, 1, -1}, "dot11WEPUndecryptableCount", MIB_TYPE_SNMP, SNMP_OFFSET(dot11WEPUndecryptableCount), SNMP_SIZE(dot11WEPUndecryptableCount)}, + + //dot11GroupAddressesTable + { {2, 3, 1, 1, 1, -1}, "dot11GroupAddressesIndex", MIB_TYPE_VAL, 1, 1}, + { {2, 3, 1, 2, 1, -1}, "dot11Address", 0}, + { {2, 3, 1, 3, 1, -1}, "dot11GroupAddressesStatus", 0}, + + { {3, 1, 1, 0, -1}, "dot11ResourceTypeIDName", MIB_TYPE_VAL, (int)"8185", 0}, + + //dot11ResourceInfoTable + { {3, 1, 2, 1, 1, 1, -1}, "dot11manufacturerOUI", MIB_TYPE_VAL, (int)"\x00\xE0\x4C", 3}, + { {3, 1, 2, 1, 2, 1, -1}, "dot11manufacturerName", MIB_TYPE_VAL, (int)"Realtek", 0}, + { {3, 1, 2, 1, 3, 1, -1}, "dot11manufacturerProductName", MIB_TYPE_VAL, (int)"Wireless 802.11 b/g", 0}, + { {3, 1, 2, 1, 4, 1, -1}, "dot11manufacturerProductVersion", MIB_TYPE_VAL, (int)"v1.00", 0}, + + //dot11PhyOperationTable + { {4, 1, 1, 1, 1, -1}, "dot11PHYType", MIB_TYPE_VAL, 2, 1}, + { {4, 1, 1, 2, 1, -1}, "dot11CurrentRegDomain", MIB_TYPE_SNMP, SNMP_OFFSET(dot11CurrentRegDomain), SNMP_SIZE(dot11CurrentRegDomain)}, + { {4, 1, 1, 3, 1, -1}, "dot11TempType", MIB_TYPE_VAL, 1, 1}, + { {4, 1, 1, 4, 1, -1}, "dot11ShortPreamble",MIB_TYPE_PRIV, PRIV_OFFSET(dot11RFEntry.shortpreamble), PRIV_SIZE(dot11RFEntry.shortpreamble)}, + { {4, 1, 1, 5, 1, -1}, "dot11PhyBandSelect",MIB_TYPE_PRIV, PRIV_OFFSET(dot11RFEntry.phyBandSelect), PRIV_SIZE(dot11RFEntry.phyBandSelect)}, + { {4, 1, 1, 6, 1, -1}, "dot11TrSwitch",MIB_TYPE_PRIV, PRIV_OFFSET(dot11RFEntry.trswitch), PRIV_SIZE(dot11RFEntry.trswitch)}, + { {4, 1, 1, 7, 1, -1}, "dot11PowerScale", MIB_TYPE_SNMP, SNMP_OFFSET(dot11PowerScale), SNMP_SIZE(dot11PowerScale)}, + + //dot11PhyAntennaTable + { {4, 2, 1, 1, 1, -1}, "dot11CurrentTxAntenna", MIB_TYPE_SNMP, SNMP_OFFSET(dot11CurrentTxAntenna), SNMP_SIZE(dot11CurrentTxAntenna)}, + { {4, 2, 1, 2, 1, -1}, "dot11DiversitySupport", MIB_TYPE_VAL, 2, 1}, + { {4, 2, 1, 3, 1, -1}, "dot11CurrentRxAntenna", MIB_TYPE_SNMP, SNMP_OFFSET(dot11CurrentTxAntenna), SNMP_SIZE(dot11CurrentTxAntenna)}, + + //dot11PhyTxPowerTable + { {4, 3, 1, 1, 1, -1}, "dot11NumberSupportedPowerLevels", MIB_TYPE_VAL, 4, 1}, + { {4, 3, 1, 2, 1, -1}, "dot11TxPowerLevel1", MIB_TYPE_VAL, 25, 1}, + { {4, 3, 1, 3, 1, -1}, "dot11TxPowerLevel2", MIB_TYPE_VAL, 12, 1}, + { {4, 3, 1, 4, 1, -1}, "dot11TxPowerLevel3", MIB_TYPE_VAL, 6, 1}, + { {4, 3, 1, 5, 1, -1}, "dot11TxPowerLevel4", MIB_TYPE_VAL, 3, 1}, + { {4, 3, 1, 6, 1, -1}, "dot11TxPowerLevel5", MIB_TYPE_VAL, 0, 1}, + { {4, 3, 1, 7, 1, -1}, "dot11TxPowerLevel6", MIB_TYPE_VAL, 0, 1}, + { {4, 3, 1, 8, 1, -1}, "dot11TxPowerLevel7", MIB_TYPE_VAL, 0, 1}, + { {4, 3, 1, 9, 1, -1}, "dot11TxPowerLevel8", MIB_TYPE_VAL, 0, 1}, + { {4, 3, 1, 10, 1, -1}, "dot11CurrentTxPowerLevel", 0}, // NCTU + + //dot11PhyDSSSTable + { {4, 5, 1, 1, 1, -1}, "dot11CurrentChannel", MIB_TYPE_PRIV, PRIV_OFFSET(dot11RFEntry.dot11channel), PRIV_SIZE(dot11RFEntry.dot11channel)}, + { {4, 5, 1, 2, 1, -1}, "dot11CCAModeSupported", MIB_TYPE_VAL, 4, 1}, + { {4, 5, 1, 3, 1, -1}, "dot11CurrentCCAMode", MIB_TYPE_VAL, 4, 1}, + { {4, 5, 1, 4, 1, -1}, "dot11EDThreshold", MIB_TYPE_VAL, 0, 1}, + + //dot11RegDomainsSupportedTable + { {4, 7, 1, 1, 1, -1}, "dot11RegDomainsSupportIndex", MIB_TYPE_VAL, 1, 1}, + { {4, 7, 1, 2, 1, -1}, "dot11RegDomainsSupportValue", MIB_TYPE_VAL, 16, 1}, + { {4, 7, 1, 1, 2, -1}, "dot11RegDomainsSupportIndex", MIB_TYPE_VAL, 2, 1}, + { {4, 7, 1, 2, 2, -1}, "dot11RegDomainsSupportValue", MIB_TYPE_VAL, 32, 1}, + { {4, 7, 1, 1, 3, -1}, "dot11RegDomainsSupportIndex", MIB_TYPE_VAL, 3, 1}, + { {4, 7, 1, 2, 3, -1}, "dot11RegDomainsSupportValue", MIB_TYPE_VAL, 48, 1}, + { {4, 7, 1, 1, 4, -1}, "dot11RegDomainsSupportIndex", MIB_TYPE_VAL, 4, 1}, + { {4, 7, 1, 2, 4, -1}, "dot11RegDomainsSupportValue", MIB_TYPE_VAL, 49, 1}, + { {4, 7, 1, 1, 5, -1}, "dot11RegDomainsSupportIndex", MIB_TYPE_VAL, 5, 1}, + { {4, 7, 1, 2, 5, -1}, "dot11RegDomainsSupportValue", MIB_TYPE_VAL, 50, 1}, + { {4, 7, 1, 1, 6, -1}, "dot11RegDomainsSupportIndex", MIB_TYPE_VAL, 6, 1}, + { {4, 7, 1, 2, 6, -1}, "dot11RegDomainsSupportValue", MIB_TYPE_VAL, 64, 1}, + + //dot11AntennasListTable + { {4, 8, 1, 1, 1, -1}, "dot11AntennaListIndex", MIB_TYPE_VAL, 1, 1}, + { {4, 8, 1, 2, 1, -1}, "dot11SupportedTxAntenna", MIB_TYPE_VAL, 1, 1}, + { {4, 8, 1, 3, 1, -1}, "dot11SupportedRxAntenna", MIB_TYPE_VAL, 1, 1}, + { {4, 8, 1, 4, 1, -1}, "dot11DiversitySelectionRx", MIB_TYPE_VAL, 1, 1}, + + //dot11SupportedDataRatesTxTable + { {4, 9, 1, 1, 1, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 1, 1}, + { {4, 9, 1, 2, 1, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[0]), 4}, + { {4, 9, 1, 1, 2, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 2, 1}, + { {4, 9, 1, 2, 2, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[1]), 4}, + { {4, 9, 1, 1, 3, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 3, 1}, + { {4, 9, 1, 2, 3, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[2]), 4}, + { {4, 9, 1, 1, 4, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 4, 1}, + { {4, 9, 1, 2, 4, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[3]), 4}, + { {4, 9, 1, 1, 5, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 5, 1}, + { {4, 9, 1, 2, 5, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[4]), 4}, + { {4, 9, 1, 1, 6, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 6, 1}, + { {4, 9, 1, 2, 6, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[5]), 4}, + { {4, 9, 1, 1, 7, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 7, 1}, + { {4, 9, 1, 2, 7, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[6]), 4}, + { {4, 9, 1, 1, 8, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 8, 1}, + { {4, 9, 1, 2, 8, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[7]), 4}, + { {4, 9, 1, 1, 9, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 9, 1}, + { {4, 9, 1, 2, 9, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[8]), 4}, + { {4, 9, 1, 1, 10, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 10, 1}, + { {4, 9, 1, 2, 10, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[9]), 4}, + { {4, 9, 1, 1, 11, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 11, 1}, + { {4, 9, 1, 2, 11, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[10]), 4}, + { {4, 9, 1, 1, 12, -1}, "dot11SupportedDataRatesTxIndex", MIB_TYPE_VAL, 12, 1}, + { {4, 9, 1, 2, 12, -1}, "dot11SupportedDataRatesTxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[11]), 4}, + + //dot11SupportedDataRatesRxTable + { {4, 10, 1, 1, 1, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 1, 1}, + { {4, 10, 1, 2, 1, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[0]), 4}, + { {4, 10, 1, 1, 2, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 2, 1}, + { {4, 10, 1, 2, 2, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[1]), 4}, + { {4, 10, 1, 1, 3, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 3, 1}, + { {4, 10, 1, 2, 3, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[2]), 4}, + { {4, 10, 1, 1, 4, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 4, 1}, + { {4, 10, 1, 2, 4, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[3]), 4}, + { {4, 10, 1, 1, 5, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 5, 1}, + { {4, 10, 1, 2, 5, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[4]), 4}, + { {4, 10, 1, 1, 6, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 6, 1}, + { {4, 10, 1, 2, 6, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[5]), 4}, + { {4, 10, 1, 1, 7, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 7, 1}, + { {4, 10, 1, 2, 7, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[6]), 4}, + { {4, 10, 1, 1, 8, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 8, 1}, + { {4, 10, 1, 2, 8, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[7]), 4}, + { {4, 10, 1, 1, 9, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 9, 1}, + { {4, 10, 1, 2, 9, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[8]), 4}, + { {4, 10, 1, 1, 10, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 10, 1}, + { {4, 10, 1, 2, 10, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[9]), 4}, + { {4, 10, 1, 1, 11, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 11, 1}, + { {4, 10, 1, 2, 11, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[10]), 4}, + { {4, 10, 1, 1, 12, -1}, "dot11SupportedDataRatesRxIndex", MIB_TYPE_VAL, 12, 1}, + { {4, 10, 1, 2, 12, -1}, "dot11SupportedDataRatesRxValue", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesSet[11]), 4}, + + // Number of table entry, Realtek proprietary + { {6, 1, -1}, "dot11StationConfigEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 2, -1}, "dot11AuthenticationAlgorithmsEntryNum", MIB_TYPE_VAL, 2, 1}, + { {6, 3, -1}, "dot11WEPDefaultKeysEntryNum", MIB_TYPE_VAL, 4, 1}, + { {6, 4, -1}, "dot11WEPKeyMappingsEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 5, -1}, "dot11PrivacyEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 6, -1}, "dot11OperationEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 7, -1}, "dot11CountersEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 8, -1}, "dot11GroupAddressesEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 9, -1}, "dot11ResourceInfoTableNum", MIB_TYPE_VAL, 1, 1}, + { {6, 10, -1}, "dot11PhyOperationEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 11, -1}, "dot11PhyAntennaEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 12, -1}, "dot11PhyTxPowerEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 13, -1}, "dot11PhyDSSSEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 14, -1}, "dot11RegDomainsSupportEntryNum", MIB_TYPE_VAL, 6, 1}, + { {6, 15, -1}, "dot11AntennasListEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 16, -1}, "dot11AntennasListEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 17, -1}, "dot11SupportedDataRatesTxEntryNum", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesNum), SNMP_SIZE(dot11SupportedDataRatesNum)}, + { {6, 18, -1}, "dot11SupportedDataRatesRxEntryNum", MIB_TYPE_SNMP, SNMP_OFFSET(dot11SupportedDataRatesNum), SNMP_SIZE(dot11SupportedDataRatesNum)}, + { {6, 19, -1}, "dot11MultiDomainCapabilityEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 20, -1}, "dot11WPAKeysEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 21, -1}, "dot11WPA2KeysEntryNum", MIB_TYPE_VAL, 1, 1}, + { {6, 22, -1}, "dot11RadiusServerNum", MIB_TYPE_VAL, 1, 1}, + + { {-1}, NULL, 0} +}; + + +static int add_mib_entry(struct rtl8192cd_priv *priv, struct mib_val *ent) +{ + int i=0; + struct mib_entry **mib=&priv->snmp_mib.mib_tree, *pre_mib=NULL; + + while(1) { + if (ent->oid[i] == -1) + break; + if (*mib == NULL) { + if (priv->snmp_mib.tree_used_index == MAX_MIB_TREE_NUM) { + printk("Exceed max mib tree number\n"); + return -1; + } + *mib = &priv->snmp_mib.mib_list[priv->snmp_mib.tree_used_index++]; + } + + if ((*mib)->id == -1 || ent->oid[i] == (*mib)->id) { + if ((*mib)->id == -1) + (*mib)->id = ent->oid[i]; + i++; + pre_mib = *mib; + mib = &((*mib)->next_level); + } + else + mib = &((*mib)->next_node); + } + + if (pre_mib == NULL) { + printk("build mib tree error, no parent mib found!\n"); + return -1; + } + if (pre_mib->val) { + printk("build mib tree error, mib value has been assigned!\n"); + return -1; + } + pre_mib->val = ent; + return 0; +} + +static void name2oid(char *name, int *oid) +{ + int i=0; + char *src=name, *ptr; + while (*src) { + ptr = strstr(src, "."); + if (ptr) + *ptr = '\0'; + oid[i++] = _atoi(src, 10); + + if (ptr==NULL) + break; + src = ++ptr; + } + oid[i] = -1; +} + +static struct mib_val *search_mib(struct rtl8192cd_priv *priv, char *id) +{ + int i=0; + struct mib_entry *mib=priv->snmp_mib.mib_tree, *pre_mib=NULL; + int oid[100]; + + name2oid(id, oid); + + while (oid[i] != -1) { + if (mib == NULL || mib->id == -1) + return NULL; + if (mib->id == oid[i]) { + pre_mib = mib; + mib = mib->next_level; + i++; + } + else { + pre_mib = NULL; + mib = mib->next_node; + } + } + + if (pre_mib && pre_mib->val) + return pre_mib->val; + else + return NULL; +} + +static void build_tree(struct rtl8192cd_priv *priv) +{ + int i=0; + struct mib_val *tbl = dot11_mib_table; + + for (i=0; isnmp_mib.mib_list[i].id = -1; + + i=0; + while (tbl[i].name) { + if (add_mib_entry(priv, &tbl[i]) < 0) { + printk("Add mib entry failed [%s]!\n", tbl[i].name); + return; + } + i++; + } + +// printk("used mib num = %d\n", priv->snmp_mib.tree_used_index); + +} + +int mib_get(struct rtl8192cd_priv *priv, char *oid, unsigned char *data, int *pLen) +{ + int iVal; + unsigned char bVal, *pVal, *pVal_type=data++; + struct mib_val *mib; + + mib = search_mib(priv, oid); + if (mib == NULL) { + printk("search mib failed [oid=%s]!\n", oid); + return 0; + } + + *pVal_type = VAL_OCTET; + + switch (mib->type) { + case MIB_TYPE_PRIV: + if (mib->size) + *pLen = mib->size; + else { + *pLen = strlen(((unsigned char *)priv->pmib)+mib->offset)+1; + *pVal_type = VAL_STR; + } + memcpy(data, ((unsigned char *)priv->pmib)+mib->offset, *pLen); + break; + + case MIB_TYPE_SNMP: + case MIB_TYPE_SNMP1: + if (mib->type == MIB_TYPE_SNMP1) { + bVal = *(((unsigned char *)&priv->snmp_mib)+mib->size); + *pLen = (int)bVal; + } + else if (mib->size > 0) + *pLen = mib->size; + else if (mib->size == 0) { + *pLen = strlen(((unsigned char *)&priv->snmp_mib)+mib->offset) + 1; + *pVal_type = VAL_STR; + } + memcpy(data, ((unsigned char *)&priv->snmp_mib)+mib->offset, *pLen); + break; + + case MIB_TYPE_VAL: + if (mib->size == 0) { + pVal = (unsigned char *)mib->offset; + *pLen = strlen(pVal) + 1; + memcpy(data, pVal, *pLen); + *pVal_type = VAL_STR; + } else if (mib->size == 1) { + bVal = (unsigned char)mib->offset; + pVal = &bVal; + *pLen = sizeof(bVal); + } + else { + iVal = mib->offset; + pVal = (unsigned char *)&iVal; + *pLen = sizeof(iVal); + } + memcpy(data, pVal, *pLen); + break; + + default: +// printk("Invalid mib type [%d, %s]\n", mib->type, mib->name); + *pVal_type = VAL_NULL; + *pLen = 0; + break; + } + +#if 0 + { + int i; + printk("name=%s, val_type=%d, len=%d", mib->name, *pVal_type, *pLen); + if (*pVal_type == VAL_STR) + printk(", val=%s\n", data); + else { + printk(", val="); + for (i=0; i<*pLen; i++) { + printk("%02x ", data[i]); + } + printk("\n"); + } + } +#endif + *pLen += 1; + return 1; +} + +// build tree and mapping mib value from priv to dot11 +void mib_init(struct rtl8192cd_priv *priv) +{ + int val; + + memset(&priv->snmp_mib, '\0', sizeof(struct mib_snmp)); + build_tree(priv); + + if ((OPMODE & WIFI_AP_STATE) || (OPMODE & WIFI_STATION_STATE)) + SNMP_MIB_ASSIGN(dot11DesiredBSSType, 1); // infra + else + SNMP_MIB_ASSIGN(dot11DesiredBSSType, 2); // ad-hoc + + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm > 0) + SNMP_MIB_ASSIGN(dot11PrivacyInvoked, 1); + + if (priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm == 1) // shared key + SNMP_MIB_ASSIGN(dot11AuthenticationAlgorithmsEnableShared, 1); + else + SNMP_MIB_ASSIGN(dot11AuthenticationAlgorithmsEnableOpen, 1); + + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) { + SNMP_MIB_COPY(dot11WEPDefaultKey1, &priv->pmib->dot11DefaultKeysTable.keytype[0].skey[0], 5); + SNMP_MIB_COPY(dot11WEPDefaultKey2, &priv->pmib->dot11DefaultKeysTable.keytype[1].skey[0], 5); + SNMP_MIB_COPY(dot11WEPDefaultKey3, &priv->pmib->dot11DefaultKeysTable.keytype[2].skey[0], 5); + SNMP_MIB_COPY(dot11WEPDefaultKey4, &priv->pmib->dot11DefaultKeysTable.keytype[3].skey[0], 5); + SNMP_MIB_ASSIGN(dot11WEPDefaultKeyLen, 5); + } + else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) { + SNMP_MIB_COPY(dot11WEPDefaultKey1, &priv->pmib->dot11DefaultKeysTable.keytype[0].skey[0], 13); + SNMP_MIB_COPY(dot11WEPDefaultKey2, &priv->pmib->dot11DefaultKeysTable.keytype[1].skey[0], 13); + SNMP_MIB_COPY(dot11WEPDefaultKey3, &priv->pmib->dot11DefaultKeysTable.keytype[2].skey[0], 13); + SNMP_MIB_COPY(dot11WEPDefaultKey4, &priv->pmib->dot11DefaultKeysTable.keytype[3].skey[0], 13); + SNMP_MIB_ASSIGN(dot11WEPDefaultKeyLen, 13); + } + get_oper_rate(priv); + + switch(priv->pmib->dot11StationConfigEntry.dot11RegDomain) { + case DOMAIN_FCC: + val = 16; + break; + case DOMAIN_IC: + val = 32; + break; + case DOMAIN_ETSI: + val = 48; + break; + case DOMAIN_SPAIN: + val = 49; + break; + case DOMAIN_FRANCE: + val = 50; + break; + case DOMAIN_MKK: + case DOMAIN_MKK1: + case DOMAIN_MKK2: + case DOMAIN_MKK3: + val = 64; + break; + default: + printk("Invalid dot11RegDomain [%d]!\n", priv->pmib->dot11StationConfigEntry.dot11RegDomain); + val = 16; + break; + } + SNMP_MIB_ASSIGN(dot11CurrentRegDomain, val); + SNMP_MIB_ASSIGN(dot11CurrentTxAntenna, priv->pmib->dot11RFEntry.defaultAntennaB+1); +} +#endif // SUPPORT_SNMP_MIB + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_mib.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_mib.h new file mode 100755 index 000000000..2b6c1726c --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_mib.h @@ -0,0 +1,87 @@ +/* + * Header files of SNMP MIB module + * + * $Id: 8192cd_mib.h,v 1.1 2009/11/06 12:26:48 victoryman Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_MIB_H_ +#define _8192CD_MIB_H_ + +#define MAX_MIB_TREE_NUM 580 +#define MAX_OID_LEVEL 10 + +#define PRIV_OFFSET(field) ((int)(long *)&(((struct wifi_mib *)0)->field)) +#define PRIV_SIZE(field) sizeof(((struct wifi_mib *)0)->field) +#define SNMP_OFFSET(field) ((int)(long *)&(((struct mib_snmp *)0)->field)) +#define SNMP_SIZE(field) sizeof(((struct mib_snmp *)0)->field) + +enum { MIB_TYPE_VAL=1, MIB_TYPE_PRIV, MIB_TYPE_SNMP, MIB_TYPE_SNMP1 }; +enum { VAL_OCTET, VAL_STR, VAL_NULL }; + +struct mib_entry { + int id; + struct mib_entry *next_level; + struct mib_entry *next_node; + struct mib_val *val; +}; + +struct mib_val { + int oid[MAX_OID_LEVEL]; + char *name; + int type; + int offset; + int size; +}; + +struct mib_snmp { + unsigned char dot11AuthenticationAlgorithmsEnableOpen; + unsigned char dot11AuthenticationAlgorithmsEnableShared; + unsigned char dot11WEPDefaultKey1[13]; + unsigned char dot11WEPDefaultKey2[13]; + unsigned char dot11WEPDefaultKey3[13]; + unsigned char dot11WEPDefaultKey4[13]; + unsigned char dot11WEPDefaultKeyLen; + unsigned char dot11SupportedDataRatesNum; + unsigned int dot11SupportedDataRatesSet[12]; + unsigned char dot11OperationalRateSet[12]; + int dot11DesiredBSSType; + int dot11DisassociateReason; + unsigned char dot11DisassociateStation[6]; + int dot11DeauthenticateReason; + unsigned char dot11DeauthenticateStation[6]; + int dot11AuthenticateFailStatus; + unsigned char dot11AuthenticateFailStation[6]; + int dot11PrivacyInvoked; + int dot11WEPICVErrorCount; + int dot11WEPExcludedCount; + int dot11TransmittedFragmentCount; + int dot11MulticastTransmittedFrameCount; + int dot11FailedCount; + int dot11RetryCount; + int dot11MultipleRetryCount; + int dot11FrameDuplicateCount; + int dot11RTSSuccessCount; + int dot11RTSFailureCount; + int dot11ACKFailureCount; + int dot11ReceivedFragmentCount; + int dot11MulticastReceivedFrameCount; + int dot11FCSErrorCount; + int dot11TransmittedFrameCount; + int dot11WEPUndecryptableCount; + int dot11CurrentRegDomain; + int dot11CurrentTxAntenna; + int dot11DataRate; + int dot11PowerScale; + + struct mib_entry mib_list[MAX_MIB_TREE_NUM]; + int tree_used_index; + struct mib_entry *mib_tree; +}; +#endif // _8192CD_MIB_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_mp.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_mp.c new file mode 100755 index 000000000..4bc828308 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_mp.c @@ -0,0 +1,5473 @@ +/* + * MP routines + * + * $Id: 8192cd_mp.c,v 1.25.2.8 2010/11/24 12:17:18 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_MP_C_ + +#ifdef __KERNEL__ +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#ifndef __KERNEL__ +#ifdef __ECOS +#include +#include +#else +#include "./sys-support.h" +#endif +#endif + +#include "./8192cd_headers.h" +#include "./8192cd_tx.h" +#include "./8192cd_debug.h" + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +#include +#endif + +//#include "./WlanHAL/RTL88XX/HalPrecomp.h" +#ifdef CONFIG_WLAN_HAL +#include "./WlanHAL/HalPrecompInc.h" +#endif + +#ifdef MP_TEST + +#ifdef _MP_TELNET_SUPPORT_ +extern void mp_pty_write_monitor(int en); +extern int mp_pty_is_hit(void); +extern int mp_pty_write(const unsigned char *buf, int count); +int mp_printk(const char *fmt, ...) +{ + va_list args; + int r; + int mp_printed_len; + static char mp_printk_buf[1024]; + + va_start(args, fmt); + r = vprintk(fmt, args); + va_end(args); + + va_start(args, fmt); + mp_printed_len = vscnprintf(mp_printk_buf, sizeof(mp_printk_buf), fmt, args); + va_end(args); + mp_pty_write( mp_printk_buf, mp_printed_len ); + + return r; +} +#define printk mp_printk +#else +#if defined(CONFIG_PANIC_PRINTK) +#define printk panic_printk +#endif +#endif //_MP_TELNET_SUPPORT_ + +#ifdef _LITTLE_ENDIAN_ +typedef struct _R_ANTENNA_SELECT_OFDM { + unsigned int r_tx_antenna:4; + unsigned int r_ant_l:4; + unsigned int r_ant_non_ht:4; + unsigned int r_ant_ht1:4; + unsigned int r_ant_ht2:4; + unsigned int r_ant_ht_s1:4; + unsigned int r_ant_non_ht_s1:4; + unsigned int OFDM_TXSC:2; + unsigned int Reserved:2; +} R_ANTENNA_SELECT_OFDM; + +typedef struct _R_ANTENNA_SELECT_CCK { + unsigned char r_cckrx_enable_2:2; + unsigned char r_cckrx_enable:2; + unsigned char r_ccktx_enable:4; +} R_ANTENNA_SELECT_CCK; + +#else // _BIG_ENDIAN_ + +typedef struct _R_ANTENNA_SELECT_OFDM { + unsigned int Reserved:2; + unsigned int OFDM_TXSC:2; + unsigned int r_ant_non_ht_s1:4; + unsigned int r_ant_ht_s1:4; + unsigned int r_ant_ht2:4; + unsigned int r_ant_ht1:4; + unsigned int r_ant_non_ht:4; + unsigned int r_ant_l:4; + unsigned int r_tx_antenna:4; +} R_ANTENNA_SELECT_OFDM; + +typedef struct _R_ANTENNA_SELECT_CCK { + unsigned char r_ccktx_enable:4; + unsigned char r_cckrx_enable:2; + unsigned char r_cckrx_enable_2:2; +} R_ANTENNA_SELECT_CCK; +#endif + + +extern int PHYCheckIsLegalRfPath8192cPci(struct rtl8192cd_priv *priv, unsigned int eRFPath); +static void mp_chk_sw_ant(struct rtl8192cd_priv *priv); +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) +static void mp_chk_sw_ant_AC(struct rtl8192cd_priv *priv); +#endif + + +extern unsigned int TxPwrTrk_OFDM_SwingTbl[TxPwrTrk_OFDM_SwingTbl_Len]; +extern unsigned char TxPwrTrk_CCK_SwingTbl[TxPwrTrk_CCK_SwingTbl_Len][8]; +extern unsigned char TxPwrTrk_CCK_SwingTbl_CH14[TxPwrTrk_CCK_SwingTbl_Len][8]; + + +#ifdef CONFIG_RTL8671 +#define _GIMR_ 0xb9c03010 +#define _UART_RBR_ 0xb9c00000 +#define _UART_LSR_ 0xb9c00014 +#endif + +#ifdef USE_RTL8186_SDK +#ifdef CONFIG_RTL8672 + #ifdef USE_RLX_BSP + #include + #ifdef CONFIG_RTL_8196C + #undef CONFIG_RTL_8196C + #endif + #ifdef CONFIG_RTL8196C_REVISION_B + #undef CONFIG_RTL8196C_REVISION_B + #endif + #else + #include + #endif +#else +#if defined(__LINUX_2_6__) +#ifdef NOT_RTK_BSP +#include +#else +#if defined(CONFIG_OPENWRT_SDK) && !defined(CONFIG_ARCH_CPU_RLX) +#include +#else +#include +#endif //CONFIG_OPENWRT_SDK +#endif +#else +#ifndef __ECOS + #include +#endif +#endif +#endif + +#ifdef CONFIG_RTL8672 +#ifdef USE_RLX_BSP +#if defined(CONFIG_RTL8686) || defined(CONFIG_RTL8685) + #ifndef CONFIG_ARCH_LUNA_SLAVE + #define _GIMR_ BSP_GIMR1_0 + #else + #define _GIMR_ BSP_GIMR0_1 + #endif + #else + #define _GIMR_ BSP_GIMR + #endif +#else + #define _GIMR_ GIMR +#endif +#define _ICU_UART_MSK_ _UART_IE +#define _UART_RBR_ _UART_RBR +#define _UART_LSR_ _UART_LSR +#else +#if defined(__LINUX_2_6__) || defined(__ECOS) +#ifdef CONFIG_RTL_8198B +#define _GIMR_ BSP_GIMR0_0 +#else +#define _GIMR_ BSP_GIMR +#endif +#ifdef CONFIG_RTL_8198C +#define _ICU_UART0_MSK_ BSP_UART0_IER +#else +#define _ICU_UART0_MSK_ BSP_UART0_IE +#endif +#define _UART0_RBR_ BSP_UART0_RBR +#define _UART0_LSR_ BSP_UART0_LSR +#else +#define _GIMR_ GIMR +#define _ICU_UART0_MSK_ UART0_IE +#define _UART0_RBR_ UART0_RBR +#define _UART0_LSR_ UART0_LSR +#endif +#endif +#endif + +#ifdef B2B_TEST +#define MP_PACKET_HEADER ("wlan-tx-test") +#define MP_PACKET_HEADER_LEN 12 +#endif + + +#ifdef CONFIG_RTL8671 +#define RTL_UART_W16(reg, val16) writew ((val16), (unsigned int)((reg))) +#define RTL_UART_R16(reg) readw ((unsigned int)((reg))) +#define RTL_UART_R32(reg) readl ((unsigned int)((reg))) + +#define DISABLE_UART0_INT() \ + do { \ + RTL_UART_W16(_GIMR_, RTL_UART_R16(_GIMR_) & ~_ICU_UART0_MSK_); \ + RTL_UART_R32(_UART_RBR_); \ + RTL_UART_R32(_UART_RBR_); \ + } while (0) + +#define RESTORE_UART0_INT() \ + do { \ + RTL_UART_W16(_GIMR_, RTL_UART_R16(_GIMR_) | _ICU_UART0_MSK_); \ + } while (0) + +static inline int IS_KEYBRD_HIT(void) +{ + if (RTL_UART_R32(_UART_LSR_) & 0x01000000) { // data ready + RTL_UART_R32(_UART_RBR_); // clear rx FIFO + return 1; + } + return 0; +} +#endif // CONFIG_RTL8671 + +#ifndef CONFIG_RTL_92C_SUPPORT +#define VERSION_8188C 0x1000 +#define VERSION_8192C 0x1001 +#endif +#ifndef CONFIG_RTL_92D_SUPPORT +#define VERSION_8192D 0x1002 +#endif + +#define CHECKICIS92C() ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)) +#define CHECKICIS92D() (GET_CHIP_VER(priv)==VERSION_8192D) +#define CHECKICIS8812() (GET_CHIP_VER(priv)==VERSION_8812E) +#define CHECKICIS8881A() (GET_CHIP_VER(priv)==VERSION_8881A) + + + +#ifdef USE_RTL8186_SDK +#ifdef __LINUX_2_6__ +#define RTL_UART_R8(reg) readb((unsigned char *)reg) +#define RTL_UART_R32(reg) readl((unsigned char *)reg) +#define RTL_UART_W8(reg, val) writeb(val, (unsigned char *)reg) +#define RTL_UART_W32(reg, val) writel(val, (unsigned char *)reg) +#else +#define RTL_UART_R8(reg) readb((unsigned int)reg) +#define RTL_UART_R32(reg) readl((unsigned int)reg) +#define RTL_UART_W8(reg, val) writeb(val, (unsigned int)reg) +#define RTL_UART_W32(reg, val) writel(val, (unsigned int)reg) +#endif +#ifdef CONFIG_RTL8672 +#define DISABLE_UART0_INT() \ + do { \ + RTL_UART_W32(_GIMR_, RTL_UART_R32(_GIMR_) & ~_ICU_UART_MSK_); \ + RTL_UART_R8(_UART_RBR_); \ + RTL_UART_R8(_UART_RBR_); \ + } while (0) + +#define RESTORE_UART0_INT() \ + do { \ + RTL_UART_W32(_GIMR_, RTL_UART_R32(_GIMR_) | _ICU_UART_MSK_); \ + } while (0) + +static inline int IS_KEYBRD_HIT(void) +{ + if (RTL_UART_R8(_UART_LSR_) & 1) { // data ready + RTL_UART_R8(_UART_RBR_); // clear rx FIFO + return 1; + } + return 0; +} +#else +#define DISABLE_UART0_INT() \ + do { \ + RTL_UART_W32(_GIMR_, RTL_UART_R32(_GIMR_) & ~_ICU_UART0_MSK_); \ + RTL_UART_R8(_UART0_RBR_); \ + RTL_UART_R8(_UART0_RBR_); \ + } while (0) + +#define RESTORE_UART0_INT() \ + do { \ + RTL_UART_W32(_GIMR_, RTL_UART_R32(_GIMR_) | _ICU_UART0_MSK_); \ + } while (0) + +static inline int IS_KEYBRD_HIT(void) +{ + if (RTL_UART_R8(_UART0_LSR_) & 1) { // data ready + RTL_UART_R8(_UART0_RBR_); // clear rx FIFO + return 1; + } + return 0; +} + +#endif +#endif // USE_RTL8186_SDK + +unsigned char * get_bssid_mp(unsigned char *pframe) +{ + unsigned char *bssid; + unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); + + switch (to_fr_ds) { + case 0x00: // ToDs=0, FromDs=0 + bssid = GetAddr3Ptr(pframe); + break; + case 0x01: // ToDs=0, FromDs=1 + bssid = GetAddr2Ptr(pframe); + break; + case 0x02: // ToDs=1, FromDs=0 + bssid = GetAddr1Ptr(pframe); + break; + default: // ToDs=1, FromDs=1 + bssid = GetAddr2Ptr(pframe); + break; + } + + return bssid; +} + + +static __inline__ int isLegalRate(unsigned int rate) +{ + unsigned int res = 0; + + switch(rate) + { + case _1M_RATE_: + case _2M_RATE_: + case _5M_RATE_: + case _6M_RATE_: + case _9M_RATE_: + case _11M_RATE_: + case _12M_RATE_: + case _18M_RATE_: + case _24M_RATE_: + case _36M_RATE_: + case _48M_RATE_: + case _54M_RATE_: + res = 1; + break; + case _MCS0_RATE_: + case _MCS1_RATE_: + case _MCS2_RATE_: + case _MCS3_RATE_: + case _MCS4_RATE_: + case _MCS5_RATE_: + case _MCS6_RATE_: + case _MCS7_RATE_: + case _MCS8_RATE_: + case _MCS9_RATE_: + case _MCS10_RATE_: + case _MCS11_RATE_: + case _MCS12_RATE_: + case _MCS13_RATE_: + case _MCS14_RATE_: + case _MCS15_RATE_: + res = 1; + break; +#ifdef RTK_AC_SUPPORT //vht rate + case _NSS1_MCS0_RATE_: + case _NSS1_MCS1_RATE_: + case _NSS1_MCS2_RATE_: + case _NSS1_MCS3_RATE_: + case _NSS1_MCS4_RATE_: + case _NSS1_MCS5_RATE_: + case _NSS1_MCS6_RATE_: + case _NSS1_MCS7_RATE_: + case _NSS1_MCS8_RATE_: + case _NSS1_MCS9_RATE_: + case _NSS2_MCS0_RATE_: + case _NSS2_MCS1_RATE_: + case _NSS2_MCS2_RATE_: + case _NSS2_MCS3_RATE_: + case _NSS2_MCS4_RATE_: + case _NSS2_MCS5_RATE_: + case _NSS2_MCS6_RATE_: + case _NSS2_MCS7_RATE_: + case _NSS2_MCS8_RATE_: + case _NSS2_MCS9_RATE_: + case _NSS3_MCS0_RATE_: + case _NSS3_MCS1_RATE_: + case _NSS3_MCS2_RATE_: + case _NSS3_MCS3_RATE_: + case _NSS3_MCS4_RATE_: + case _NSS3_MCS5_RATE_: + case _NSS3_MCS6_RATE_: + case _NSS3_MCS7_RATE_: + case _NSS3_MCS8_RATE_: + case _NSS3_MCS9_RATE_: + case _NSS4_MCS0_RATE_: + case _NSS4_MCS1_RATE_: + case _NSS4_MCS2_RATE_: + case _NSS4_MCS3_RATE_: + case _NSS4_MCS4_RATE_: + case _NSS4_MCS5_RATE_: + case _NSS4_MCS6_RATE_: + case _NSS4_MCS7_RATE_: + case _NSS4_MCS8_RATE_: + case _NSS4_MCS9_RATE_: + res = 1; + break; +#endif + default: + res = 0; + break; + } + + return res; +} + +#ifdef MP_PSD_SUPPORT +int GetPSDData(struct rtl8192cd_priv *priv,unsigned int point) +{ + int psd_val; +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if((GET_CHIP_VER(priv)== VERSION_8812E) || (GET_CHIP_VER(priv)== VERSION_8881A)) { + psd_val = RTL_R32(0x910); + psd_val &= 0xFFBFFC00; + psd_val |= point; + + RTL_W32(0x910, psd_val); + delay_ms(2); + psd_val |= 0x00400000; + + RTL_W32(0x910, psd_val); + delay_ms(2); + psd_val = RTL_R32(0xF44); + + psd_val &= 0x0000FFFF; + } else +#endif + { + psd_val = RTL_R32(0x808); + psd_val &= 0xFFBFFC00; + psd_val |= point; + + RTL_W32(0x808, psd_val); + delay_ms(2); + psd_val |= 0x00400000; + + RTL_W32(0x808, psd_val); + delay_ms(2); + psd_val = RTL_R32(0x8B4); + + psd_val &= 0x0000FFFF; + } + return psd_val; +} +#endif +#if 0 +static void mp_RL5975e_Txsetting(struct rtl8192cd_priv *priv) +{ + RF92CD_RADIO_PATH_E eRFPath; + unsigned int rfReg0x14, rfReg0x15, rfReg0x2c; + + // reg0x14 + rfReg0x14 = 0x5ab; + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + { + //channel = 1, 11, in 20MHz mode, set RF-reg[0x14] = 0x59b + if(priv->pshare->working_channel == 1 || priv->pshare->working_channel == 11) + { + if(!is_CCK_rate(priv->pshare->mp_datarate)) //OFDM, MCS rates + rfReg0x14 = 0x59b; + } + } + else + { + //channel = 3, 9, in 40MHz mode, set RF-reg[0x14] = 0x59b + if(priv->pshare->working_channel == 3 || priv->pshare->working_channel == 9) + rfReg0x14 = 0x59b; + } + for (eRFPath = RF92CD_PATH_A; eRFPathpshare->phw->NumTotalRFPath; eRFPath++) + { + if (!PHYCheckIsLegalRfPath8192cPci(priv, eRFPath)) + continue; +/* + if (get_rf_mimo_mode(priv) == MIMO_1T2R) { + if ((eRFPath == RF92CD_PATH_A) || (eRFPath == RF92CD_PATH_B)) + continue; + } + else if (get_rf_mimo_mode(priv) == MIMO_2T2R) { + if ((eRFPath == RF92CD_PATH_B) || (eRFPath == RF90_PATH_D)) + continue; + } +*/ + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, 0x14, bMask20Bits, rfReg0x14); + delay_us(100); + } + + // reg0x15 + rfReg0x15 = 0xf80; + if(priv->pshare->mp_datarate == 4) + { + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + rfReg0x15 = 0xfc0; + } + for (eRFPath = RF92CD_PATH_A; eRFPathpshare->phw->NumTotalRFPath; eRFPath++) + { + if (!PHYCheckIsLegalRfPath8192cPci(priv, eRFPath)) + continue; +/* + if (get_rf_mimo_mode(priv) == MIMO_1T2R) { + if ((eRFPath == RF92CD_PATH_A) || (eRFPath == RF92CD_PATH_B)) + continue; + } + else if (get_rf_mimo_mode(priv) == MIMO_2T2R) { + if ((eRFPath == RF92CD_PATH_B) || (eRFPath == RF90_PATH_D)) + continue; + } +*/ + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, 0x15, bMask20Bits, rfReg0x15); + delay_us(100); + } + + //reg0x2c + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + { + rfReg0x2c = 0x3d7; + if(is_CCK_rate(priv->pshare->mp_datarate)) //CCK rate + { + if(priv->pshare->working_channel == 1 || priv->pshare->working_channel == 11) + rfReg0x2c = 0x3f7; + } + } + else + { + rfReg0x2c = 0x3ff; + } + for (eRFPath = RF92CD_PATH_A; eRFPathpshare->phw->NumTotalRFPath; eRFPath++) + { + if (!PHYCheckIsLegalRfPath8192cPci(priv, eRFPath)) + continue; +/* + if (get_rf_mimo_mode(priv) == MIMO_1T2R) { + if ((eRFPath == RF92CD_PATH_A) || (eRFPath == RF92CD_PATH_B)) + continue; + } + else if (get_rf_mimo_mode(priv) == MIMO_2T2R) { + if ((eRFPath == RF92CD_PATH_B) || (eRFPath == RF90_PATH_D)) + continue; + } +*/ + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, 0x2c, bMask20Bits, rfReg0x2c); + delay_us(100); + } + + if (priv->pshare->rf_ft_var.use_frq_2_3G) + PHY_SetRFReg(priv, RF90_PATH_C, 0x2c, 0x60, 0); +} + + +static void mp_RF_RxLPFsetting(struct rtl8192cd_priv *priv) +{ + unsigned int rfBand_A=0, rfBand_B=0, rfBand_C=0, rfBand_D=0; + + //================================================== + //because the EVM issue, CCK ACPR spec, asked by bryant. + //when BAND_20MHZ_MODE, should overwrite CCK Rx path RF, let the bandwidth + //from 10M->8M, we should overwrite the following values to the cck rx rf. + //RF_Reg[0xb]:bit[11:8] = 0x4, otherwise RF_Reg[0xb]:bit[11:8] = 0x0 + switch(priv->pshare->mp_antenna_rx) + { + case ANTENNA_A: + case ANTENNA_AC: + case ANTENNA_ABCD: + rfBand_A = 0x500; //for TxEVM, CCK ACPR + break; + case ANTENNA_B: + case ANTENNA_BD: + rfBand_B = 0x500; //for TxEVM, CCK ACPR + break; + case ANTENNA_C: + case ANTENNA_CD: + rfBand_C = 0x500; //for TxEVM, CCK ACPR + break; + case ANTENNA_D: + rfBand_D = 0x500; //for TxEVM, CCK ACPR + break; + } + + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + { + if(!rfBand_A) + rfBand_A = 0x100; + if(!rfBand_B) + rfBand_B = 0x100; + if(!rfBand_C) + rfBand_C = 0x100; + if(!rfBand_D) + rfBand_D = 0x100; + } + else + { + rfBand_A = 0x300; + rfBand_B = 0x300; + rfBand_C = 0x300; + rfBand_D = 0x300; + } + + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x0b, bMask20Bits, rfBand_A); + delay_us(100); + PHY_SetRFReg(priv, RF92CD_PATH_B, 0x0b, bMask20Bits, rfBand_B); + delay_us(100); +/* + PHY_SetRFReg(priv, RF90_PATH_C, 0x0b, bMask20Bits, rfBand_C); + delay_us(100); + PHY_SetRFReg(priv, RF90_PATH_D, 0x0b, bMask20Bits, rfBand_D); + delay_us(100); +*/ +} +#endif + + +static void mp_8192CD_tx_setting(struct rtl8192cd_priv *priv) +{ + unsigned int odd_pwr = 0; +// extern int get_CCK_swing_index(struct rtl8192cd_priv*); +//#ifndef CONFIG_RTL_92D_SUPPORT +#if 1//!defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN_D) + extern void set_CCK_swing_index(struct rtl8192cd_priv*, short ); +#endif + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if (is_CCK_rate(priv->pshare->mp_datarate) + && ( +#ifdef CONFIG_RTL_92C_SUPPORT + (!IS_TEST_CHIP(priv) && (GET_CHIP_VER(priv) == VERSION_8192C)) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + )) { + if (RTL_R8(0xa07) & 0x80) { + if (priv->pshare->mp_txpwr_patha % 2) + odd_pwr++; + } else { + if (priv->pshare->mp_txpwr_pathb % 2) + odd_pwr++; + } + + if(CHECKICIS92C()||(CHECKICIS92D()&&(RTL_R8(0xa07) & 0x40))) { + switch((odd_pwr<<1)| priv->pshare->mp_cck_txpwr_odd) { + case 1: + set_CCK_swing_index(priv, get_CCK_swing_index(priv)+1); + break; + case 2: + set_CCK_swing_index(priv, get_CCK_swing_index(priv)-1); + break; + default: + break; + }; + } + priv->pshare->mp_cck_txpwr_odd = odd_pwr; + } +#endif +} + + +static void mpt_StartCckContTx(struct rtl8192cd_priv *priv) +{ + unsigned int cckrate; + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if(CHECKICIS8812() || CHECKICIS8881A()) { + // 1. if CCK block on? + if(!PHY_QueryBBReg(priv, 0x808, BIT(28))) + PHY_SetBBReg(priv, 0x808, BIT(28), bEnable);//set CCK block on + + //Turn Off All Test Mode + PHY_SetBBReg(priv, 0x914, BIT(16), bDisable); + PHY_SetBBReg(priv, 0x914, BIT(17), bDisable); + PHY_SetBBReg(priv, 0x914, BIT(18), bDisable); + } + else +#endif + { + // 1. if CCK block on? + if (!PHY_QueryBBReg(priv, rFPGA0_RFMOD, bCCKEn)) + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, bEnable);//set CCK block on + + //Turn Off All Test Mode + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMContinueTx, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + } + //Set CCK Tx Test Rate + switch (priv->pshare->mp_datarate) + { + case 2: + cckrate = 0; + break; + case 4: + cckrate = 1; + break; + case 11: + cckrate = 2; + break; + case 22: + cckrate = 3; + break; + default: + cckrate = 0; + break; + } + PHY_SetBBReg(priv, rCCK0_System, bCCKTxRate, cckrate); + + PHY_SetBBReg(priv, rCCK0_System, bCCKBBMode, 0x2); //transmit mode + PHY_SetBBReg(priv, rCCK0_System, bCCKScramble, 0x1); //turn on scramble setting + +#if 1//def CONFIG_RTL8672 + // Commented out for background mode, sync with SD7, 2010-07-08 by Annie --- + // We will set 0x820 and 0x828 under Tx mode in mp_ctx(), 2010-09-17 by Family. + // PHY_SetBBReg(priv, 0x820, 0x400, 0x1); + // PHY_SetBBReg(priv, 0x828, 0x400, 0x1); + //--- +#else //CONFIG_RTL8672 + PHY_SetBBReg(priv, 0x820, 0x400, 0x1); + PHY_SetBBReg(priv, 0x828, 0x400, 0x1); +#endif //CONFIG_RTL8672 + +} + + +static void mpt_StopCckCoNtTx(struct rtl8192cd_priv *priv) +{ + PHY_SetBBReg(priv, rCCK0_System, bCCKBBMode, 0x0); //normal mode + PHY_SetBBReg(priv, rCCK0_System, bCCKScramble, 0x1); //turn on scramble setting + + PHY_SetBBReg(priv, 0x820, 0x400, 0x0); + PHY_SetBBReg(priv, 0x828, 0x400, 0x0); +} + + +static void mpt_StartOfdmContTx(struct rtl8192cd_priv *priv) +{ +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + unsigned int go=0; +#endif + + // 1. if OFDM block on? +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if(CHECKICIS8812() || CHECKICIS8881A()) { + if(!PHY_QueryBBReg(priv, 0x808, BIT(29))) + PHY_SetBBReg(priv, 0x808, BIT(29), bEnable);//set CCK block on + } else +#endif + { + if (!PHY_QueryBBReg(priv, rFPGA0_RFMOD, bOFDMEn)) + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn, bEnable);//set OFDM block on + } + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS92D() || CHECKICIS8812() || CHECKICIS8881A()) + { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) + go=1; + else + go=0; + } + else + go=1; + + if(go==1) +#endif + { + // 2. set CCK test mode off, set to CCK normal mode + PHY_SetBBReg(priv, rCCK0_System, bCCKBBMode, bDisable); + + // 3. turn on scramble setting + PHY_SetBBReg(priv, rCCK0_System, bCCKScramble, bEnable); + } + + // 4. Turn On Continue Tx and turn off the other test modes. +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if(CHECKICIS8812() || CHECKICIS8881A()) { + PHY_SetBBReg(priv, 0x914, BIT(16), bEnable); + PHY_SetBBReg(priv, 0x914, BIT(17), bDisable); + PHY_SetBBReg(priv, 0x914, BIT(18), bDisable); + } + else +#endif + { + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMContinueTx, bEnable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + } + +#if 1//def CONFIG_RTL8672 + // Commented out for background mode, sync with SD7, 2010-07-08 by Annie --- + // We will set 0x820 and 0x828 under Tx mode in mp_ctx(), 2010-09-17 by Family. + // PHY_SetBBReg(priv, 0x820, 0x400, 0x1); + // PHY_SetBBReg(priv, 0x828, 0x400, 0x1); + //--- +#else //CONFIG_RTL8672 + PHY_SetBBReg(priv, 0x820, 0x400, 0x1); + PHY_SetBBReg(priv, 0x828, 0x400, 0x1); +#endif //CONFIG_RTL8672 + +} + + +static void mpt_StopOfdmContTx(struct rtl8192cd_priv *priv) +{ +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if(CHECKICIS8812() || CHECKICIS8881A()) { + PHY_SetBBReg(priv, 0x914, BIT(16), bDisable); + PHY_SetBBReg(priv, 0x914, BIT(17), bDisable); + PHY_SetBBReg(priv, 0x914, BIT(18), bDisable); + } + else +#endif + { + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMContinueTx, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + } + + //Delay 10 ms + delay_ms(10); + + PHY_SetBBReg(priv, 0x820, 0x400, 0x0); + PHY_SetBBReg(priv, 0x828, 0x400, 0x0); +} + + +static void mpt_ProSetCarrierSupp(struct rtl8192cd_priv *priv, int enable) +{ + if (enable) + { // Start Carrier Suppression. +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if(CHECKICIS8812() || CHECKICIS8881A()) { + // 1. if CCK block on? + if(!PHY_QueryBBReg(priv, 0x808, BIT(28))) + PHY_SetBBReg(priv, 0x808, BIT(28), bEnable);//set CCK block on + + //Turn Off All Test Mode + PHY_SetBBReg(priv, 0x914, BIT(16), bDisable); + PHY_SetBBReg(priv, 0x914, BIT(17), bDisable); + PHY_SetBBReg(priv, 0x914, BIT(18), bDisable); + } + else +#endif + { + // 1. if CCK block on? + if(!PHY_QueryBBReg(priv, rFPGA0_RFMOD, bCCKEn)) + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, bEnable);//set CCK block on + + //Turn Off All Test Mode + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMContinueTx, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + } + PHY_SetBBReg(priv, rCCK0_System, bCCKBBMode, 0x2); //transmit mode + PHY_SetBBReg(priv, rCCK0_System, bCCKScramble, 0x0); //turn off scramble setting + //Set CCK Tx Test Rate + //PHY_SetBBReg(pAdapter, rCCK0_System, bCCKTxRate, pMgntInfo->ForcedDataRate); + PHY_SetBBReg(priv, rCCK0_System, bCCKTxRate, 0x0); //Set FTxRate to 1Mbps + } + else + { // Stop Carrier Suppression. + PHY_SetBBReg(priv, rCCK0_System, bCCKBBMode, 0x0); //normal mode + PHY_SetBBReg(priv, rCCK0_System, bCCKScramble, 0x1); //turn on scramble setting + + //BB Reset +/* + PHY_SetBBReg(priv, rPMAC_Reset, bBBResetB, 0x0); + PHY_SetBBReg(priv, rPMAC_Reset, bBBResetB, 0x1); +*/ + } +} + + +/* + * start mp testing. stop beacon and change to mp mode + */ +void mp_start_test(struct rtl8192cd_priv *priv) +{ + + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return; + } + + if (OPMODE & WIFI_MP_STATE) + { + printk("\nFail: already in MP mode\n"); + return; + } + +#ifdef MP_SWITCH_LNA + priv->pshare->rx_packet_ss_a = 0; + priv->pshare->rx_packet_ss_b = 0; +#endif + +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + printk("\nFail: only root interface supports MP mode\n"); + return; + } + else if (IS_ROOT_INTERFACE(priv) && IS_DRV_OPEN(GET_VXD_PRIV(priv))) + rtl8192cd_close(GET_VXD_PRIV(priv)->dev); +#endif + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable && + IS_VAP_INTERFACE(priv)) { + printk("\nFail: only root interface supports MP mode\n"); + return; + } else if (IS_ROOT_INTERFACE(priv)) { + int i; + if (priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + rtl8192cd_close(priv->pvap_priv[i]->dev); + } + } + } +#endif + +#ifdef AUTO_CHANNEL_TIMEOUT + priv->pshare->autoch_timeout_count = 0; +#endif + + // initialize rate to 54M (or 1M ?) + priv->pshare->mp_datarate = _54M_RATE_; + + // initialize antenna + priv->pshare->mp_antenna_tx = ANTENNA_A; + priv->pshare->mp_antenna_rx = ANTENNA_A; +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812()||CHECKICIS8881A()) + mp_chk_sw_ant_AC(priv); + else +#endif + mp_chk_sw_ant(priv); + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812() || CHECKICIS8881A()) { + //Do Nothing + } + else +#endif + if ((get_rf_mimo_mode(priv) == MIMO_2T2R) && priv->pmib->dot11RFEntry.txbf) { + // Tx Path Selection by ctrl_reg in MP mode + PHY_SetBBReg(priv, 0x90C, BIT(30), 0); + } + + // initialize swing index +#if 1 + { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) + priv->pshare->mp_cck_swing_idx = 14; + else +#endif + priv->pshare->mp_cck_swing_idx = 20; + } else +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) + priv->pshare->mp_cck_swing_idx = 30; + else +#endif + priv->pshare->mp_cck_swing_idx = 20; + } else +#endif + { + priv->pshare->mp_cck_swing_idx = 12; + } + } + //printk("==> mp_ofdm_swing_idx=%d\n", priv->pshare->mp_ofdm_swing_idx); + //printk("==> mp_cck_swing_idx=%d\n", priv->pshare->mp_cck_swing_idx); + } +#endif + // change mode to mp mode + OPMODE_VAL(OPMODE | WIFI_MP_STATE); + + // disable beacon + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT)); + RTL_W8(TXPAUSE, STOP_BCN); + + priv->pmib->dot11StationConfigEntry.autoRate = 0; + priv->pmib->dot11StationConfigEntry.protectionDisabled = 1; + priv->pmib->dot11ErpInfo.ctsToSelf = 0; + priv->pmib->dot11ErpInfo.protection = 0; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 0; + OPMODE_VAL(OPMODE & ~WIFI_STATION_STATE); + OPMODE_VAL(OPMODE | WIFI_AP_STATE); + + // stop site survey + if (timer_pending(&priv->ss_timer)) + del_timer_sync(&priv->ss_timer); + + // stop receiving packets +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + RTL_W32(RCR, RTL_R32(RCR) & ~(RCR_APWRMGT | RCR_AMF | RCR_ADF |RCR_ACRC32 |RCR_AB | RCR_AM | RCR_APM | RCR_AAP)); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + RTL_W32(RCR, RTL_R32(RCR) & ~(RCR_AB | RCR_AM | RCR_APM | RCR_AAP)); + // Global setting for MP no ack CCK + RTL_W8(0x700, 0xe0); + + // stop dynamic mechanism +// if ((get_rf_mimo_mode(priv) == MIMO_2T4R) && (priv->pmib->dot11BssType.net_work_type != WIRELESS_11B)) +// rx_path_by_rssi(priv, NULL, FALSE); +// tx_power_control(priv, NULL, FALSE); + + // DIG off and set initial gain + priv->pshare->rf_ft_var.dig_enable = 0; + set_DIG_state(priv, 0); + delay_ms(1); + +#if defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + RTL_W8(0xc50, 0x1c); + RTL_W8(0xc58, 0x1c); + } else { + RTL_W8(0xc50, 0x20); + RTL_W8(0xc58, 0x20); + } + } else +#endif +#if defined(CONFIG_RTL_92C_SUPPORT) + if ((GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C)) { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + RTL_W8(0xc50, 0x2e); + if (get_rf_mimo_mode(priv) == MIMO_2T2R) + RTL_W8(0xc58, 0x2e); + } else +#endif +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + RTL_W8(0xc50, 0x2a); + if (get_rf_mimo_mode(priv) == MIMO_2T2R) + RTL_W8(0xc58, 0x2a); + } else +#endif + { + RTL_W8(0xc50, 0x20); + if (get_rf_mimo_mode(priv) == MIMO_2T2R) + RTL_W8(0xc58, 0x20); + } + } else +#endif + { +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(HIGH_POWER_EXT_LNA) + if (GET_CHIP_VER(priv) == VERSION_8188E && priv->pshare->rf_ft_var.use_ext_lna) { + RTL_W8(0xc50, 0x1c); + }else +#endif + RTL_W8(0xc50, 0x20); + if (get_rf_mimo_mode(priv) == MIMO_2T2R) { +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv)==VERSION_8812E) + RTL_W8(0xe50, 0x20); + else +#endif + RTL_W8(0xc58, 0x20); + } + } + + RTL_W8(0xa0a, 0x83); + + priv->pshare->rf_ft_var.tpt_period=2; + priv->pshare->mp_rssi_weight = 5; + priv->pshare->mp_FA_cnt = 0; + priv->pshare->mp_CCA_cnt = 0; + + mp_8192CD_tx_setting(priv); + +#if 0//def CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + if (priv->pshare->PLL_reset_ok == false) + Check_92E_Spur_Valid(priv, true); + } +#endif + +#ifdef GREEN_HILL + printk("Enter testing mode\n"); +#else + printk("\nUsage:\n"); + printk(" iwpriv wlanx mp_stop\n"); + printk(" iwpriv wlanx mp_rate {2-108,128-143,144-163}\n"); +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + printk(" iwpriv wlanx mp_channel 1\n"); + printk(" - if bg band, use channel 1-14 only\n"); + printk(" - if a band, 20M mode use channel 36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,149,153,157,161,165 only\n"); + printk(" - if a band, 40M mode use channel 38,42,46,50,54,58,62,102,106,110,114,118,122,126,130,134,138,151,152,155,159,160,163 only\n"); +#else + printk(" iwpriv wlanx mp_channel {1-14}\n"); +#endif + printk(" iwpriv wlanx mp_bandwidth [40M={0|1|2},shortGI={0|1}]\n"); + printk(" - default: BW=0, shortGI=0\n"); + printk(" iwpriv wlanx mp_txpower [patha=x,pathb=y]\n"); + printk(" - if no parameters, driver will set tx power according to flash setting.\n"); + printk(" iwpriv wlanx mp_phypara xcap=x\n"); + printk(" iwpriv wlanx mp_bssid 001122334455\n"); + printk(" iwpriv wlanx mp_ant_tx {a,b,ab}\n"); + printk(" iwpriv wlanx mp_ant_rx {a,b,ab}\n"); + printk(" iwpriv wlanx mp_arx {start,stop,filter_SA, filter_DA, filter_BSSID}\n"); + printk(" iwpriv wlanx mp_ctx [time=t,count=n,background,stop,pkt,cs,stone,scr]\n"); + printk(" - if \"time\" is set, tx in t sec. if \"count\" is set, tx with n packet.\n"); + printk(" - if \"background\", it will tx continuously until \"stop\" is issued.\n"); + printk(" - if \"pkt\", send cck packet in packet mode (not h/w).\n"); + printk(" - if \"cs\", send cck packet with carrier suppression.\n"); + printk(" - if \"stone\", send packet in single-tone.\n"); + printk(" - default: tx infinitely (no background).\n"); + printk(" iwpriv wlanx mp_query {rssi,weight=x}\n"); +#ifdef MP_PSD_SUPPORT + printk(" iwpriv wlanx mp_psd\n"); +#endif + printk(" iwpriv wlanx mp_ther\n"); +#if defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + printk(" iwpriv wlanx mp_pwrtrk [ther={7-63}, stop]\n"); +#else + printk(" iwpriv wlanx mp_pwrtrk [ther={7-29}, stop]\n"); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + printk(" iwpriv wlanx mp_phyband {a, bg}\n"); +#endif + printk(" iwpriv wlanx mp_reset_stats\n"); + printk(" - to reset tx and rx count\n"); + printk(" iwpriv wlanx mp_get_pwr\n"); +#if defined(CONFIG_RTL_8812_SUPPORT) + printk(" iwpriv wlanx mp_dig on,off\n"); +#endif +#ifdef B2B_TEST + printk(" iwpriv wlanx mp_tx [da=xxxxxx,time=n,count=n,len=n,retry=n,err=n]\n"); + printk(" - if \"time\" is set, tx in t sec. if \"count\" is set, tx with n packet.\n"); + printk(" - if \"time=-1\", tx infinitely.\n"); + printk(" - If \"err=1\", display statistics when tx err.\n"); + printk(" - default: da=ffffffffffff, time=0, count=1000, len=1500,\n"); + printk(" retry=6(mac retry limit), err=1.\n"); +#if 0 + printk(" iwpriv wlanx mp_rx [ra=xxxxxx,quiet=t,interval=n]\n"); + printk(" - ra: rx mac. defulat is burn-in mac\n"); + printk(" - quiet_time: quit rx if no rx packet during quiet_time. default is 5s\n"); + printk(" - interval: report rx statistics periodically in sec.\n"); + printk(" default is 0 (no report).\n"); +#endif + printk(" iwpriv wlanx mp_brx {start[,ra=xxxxxx],stop}\n"); + printk(" - start: start rx immediately.\n"); + printk(" - ra: rx mac. defulat is burn-in mac.\n"); + printk(" - stop: stop rx immediately.\n"); +#endif// B2B_TEST +#endif // GREEN_HILL + + if (!priv->pshare->rf_ft_var.mp_specific) + printk("!!! Warning: Please set MIB mp_specific first\n"); + +} + + +/* + * stop mp testing. recover system to previous status. + */ +void mp_stop_test(struct rtl8192cd_priv *priv) +{ + int i; + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return; + } + +#if 1//def CONFIG_RTL8672 + // make sure mp_ctx action stop, otherwise it will cause memory leak(skb_pool_ptr) for linux SDK + // ,or crash dump for OSK because free skb_pool using rtl_kfree_skb() + if (OPMODE & WIFI_MP_CTX_BACKGROUND) { + mp_ctx(priv, "stop"); + } +#endif + + // enable beacon + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & ~STOP_BCN); + OPMODE_VAL(OPMODE & ~WIFI_MP_STATE); + + priv->pshare->ThermalValue = 0; + + printk("Please restart the interface\n"); +} + + +/* + * set data rate + */ +void mp_set_datarate(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned char rate, rate_org; + char tmpbuf[32]; +#if 0 + RF92CD_RADIO_PATH_E eRFPath; +#endif + + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) + { + printk("Fail: not in MP mode\n"); + return; + } + if (OPMODE & WIFI_MP_CTX_BACKGROUND) + { + printk("Fail: In MP background mode, please stop and retry it again\n"); + return; + } + + rate = _atoi((char *)data, 10); +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if(CHECKICIS92D() || CHECKICIS8812() || CHECKICIS8881A()) { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + if (is_CCK_rate(rate)) { + printk("(%d/2) Mbps data rate is not supported in A band\n", rate); + return; + } + } + } +#endif + + /* Translate old rate coding to new rate coding. 8814 doesn't have to translate + becuase it uses mp_version so that MP tool gives new rate coding */ + if(GET_CHIP_VER(priv) != VERSION_8814A){ + if( rate >= 144 && rate <= 144 + 19){// For VHT NSS1 MCS0 to NSS2 MCS 9 + printk("Translate old rate coding (%d) to new one (%d)\n", rate, rate - 144 + VHT_RATE_ID); + rate = rate - 144 + VHT_RATE_ID; // Change base from 144 to _NSS1_MCS0_RATE_ (160) + } + else if( rate > 144 + 19){ + printk("[Error] Rate %d is for VHT NSS3. Cannot be transfered to new rate coding!\n", rate); + } + } + + if(!isLegalRate(rate)) + { + printk("(%d/2) Mbps data rate may not be supported\n", rate); + return; + } + + rate_org = priv->pshare->mp_datarate; + priv->pshare->mp_datarate = rate; +#if 0 + for (eRFPath = RF92CD_PATH_A; eRFPathpshare->phw->NumTotalRFPath; eRFPath++) { + if (!PHYCheckIsLegalRfPath8192cPci(priv, eRFPath)) + continue; + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_RTL_88E_SUPPORT) + if (CHECKICIS8812() || CHECKICIS8881A() || (GET_CHIP_VER(priv) == VERSION_8188E)) + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, rRfChannel, (BIT(10) | BIT(11)), 3); + else +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if(CHECKICIS92D()){ + priv->pshare->RegRF18[eRFPath] &= (~BIT(11)); + priv->pshare->RegRF18[eRFPath] |= BIT(10); + } else +#endif + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, rRfChannel, (BIT(10) | BIT(11)), 0x01); + } else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) { +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812() || CHECKICIS8881A()) + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, rRfChannel, (BIT(10) | BIT(11)), 1); + else +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if(CHECKICIS92D()){ + priv->pshare->RegRF18[eRFPath] &= (~BIT(11)); + priv->pshare->RegRF18[eRFPath] &= (~BIT(10)); + } else +#endif + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, rRfChannel, (BIT(11)), 0x00); + } else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_80) { +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812() || CHECKICIS8881A()) + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, rRfChannel, (BIT(10) | BIT(11)), 0); +#endif + } +#ifdef CONFIG_RTL_92D_SUPPORT + if(CHECKICIS92D()){ + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)eRFPath, rRfChannel, bMask20Bits, priv->pshare->RegRF18[eRFPath]); + } +#endif + delay_us(100); + } +#endif +/* + if(CHECKICIS92C()) { + if (is_CCK_rate(priv->pshare->mp_datarate)) { + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x0f400); + } else { + if(IS_UMC_A_CUT_88C(priv) || GET_CHIP_VER(priv) == VERSION_8192C ) + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x4f000); + else + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x4f200); + } + } +*/ + mp_8192CD_tx_setting(priv); + + if (rate <= 108) + sprintf(tmpbuf, "Set data rate to %d Mbps\n", rate/2); + else if (rate >= HT_RATE_ID && rate < VHT_RATE_ID) + sprintf(tmpbuf, "Set data rate to MCS%d\n", (rate-HT_RATE_ID)); + else + sprintf(tmpbuf, "Set data rate to NSSS%d MCS%d\n", (rate - VHT_RATE_ID)/10 + 1, (rate - VHT_RATE_ID)%10); + printk(tmpbuf); +} + + +/* + * set channel + */ +void mp_set_channel(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned char channel, channel_org; + char tmpbuf[48]; + unsigned int eRFPath; + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) + { + printk("Fail: not in MP mode\n"); + return; + } + + channel = (unsigned char)_atoi((char *)data, 10); + priv->pshare->working_channel = channel; + + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) + { + if (priv->pshare->is_40m_bw && + ((channel < 3) || (channel > 12))) { + sprintf(tmpbuf, "channel %d is invalid\n", channel); + printk(tmpbuf); + return; + } + } + +#if defined(CONFIG_RTL_8812_SUPPORT) + if(GET_CHIP_VER(priv)==VERSION_8812E) + { + UpdateBBRFVal8812(priv, channel); + for(eRFPath = RF92CD_PATH_A ; eRFPath < RF92CD_PATH_MAX ; eRFPath++) { + PHY_SetRFReg(priv, eRFPath, rRfChannel, 0xff, channel); + } + PHY_SetOFDMTxPower_8812(priv, channel); + + if (priv->pshare->curr_band == BAND_2G) + PHY_SetCCKTxPower_8812(priv, channel); + + PHY_IQCalibrate(priv); //FOR_8812_IQK + + return; + } +#endif + +// TODO: 8814AE BB/RF + +#if defined(CONFIG_WLAN_HAL_8881A) + if(GET_CHIP_VER(priv)==VERSION_8881A) + { + GET_HAL_INTERFACE(priv)->PHYUpdateBBRFValHandler(priv, channel,priv->pshare->offset_2nd_chan); + for(eRFPath = RF92CD_PATH_A ; eRFPath < RF92CD_PATH_MAX ; eRFPath++) { + PHY_SetRFReg(priv, eRFPath, rRfChannel, 0xff, channel); + } + GET_HAL_INTERFACE(priv)->PHYSetOFDMTxPowerHandler(priv, channel); + + if (priv->pshare->curr_band == BAND_2G) + GET_HAL_INTERFACE(priv)->PHYSetCCKTxPowerHandler(priv, channel); + + PHY_IQCalibrate(priv); + + if (get_bonding_type_8881A() == BOND_8881AN) + { + unsigned int ch_band = PHY_QueryRFReg(priv, RF_PATH_A, 0x18, BIT(17)|BIT(18), 1); + if (ch_band == 0) + PHY_SetRFReg(priv, RF_PATH_A, 0x63, bMaskDWord, 0x114eb); + else if (ch_band == 1) + PHY_SetRFReg(priv, RF_PATH_A, 0x63, bMaskDWord, 0x116e7); + else if (ch_band = 2) + PHY_SetRFReg(priv, RF_PATH_A, 0x63, bMaskDWord, 0x11aeb); + } + return; + } + +#endif //#if defined(CONFIG_WLAN_HAL_8881A) + + + channel_org = priv->pmib->dot11RFEntry.dot11channel; + priv->pmib->dot11RFEntry.dot11channel = channel; + + if (priv->pshare->rf_ft_var.use_frq_2_3G) + channel += 14; + + { + unsigned int val_read; + unsigned int val= channel; + + val_read = PHY_QueryRFReg(priv, 0, 0x18, bMask20Bits, 1); + if(CHECKICIS92D()) + val_read &= 0xffffff00; + else + val_read &= 0xfffffff0; + + for(eRFPath = RF92CD_PATH_A; eRFPath < RF92CD_PATH_MAX; eRFPath++) { +#ifdef CONFIG_RTL_92D_SUPPORT + if(CHECKICIS92D()) { + priv->pshare->RegRF18[eRFPath] = (val_read | val); + + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + /* + * Set Bit18 when channel >= 100, for 5G only + */ + if (val >= 100) + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(18), 1); + priv->pshare->RegRF18[eRFPath] |= BIT(18); + else + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(18), 0); + priv->pshare->RegRF18[eRFPath] &= (~BIT(18)); + + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(16), 1); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(8), 1); + priv->pshare->RegRF18[eRFPath] |= BIT(16); + priv->pshare->RegRF18[eRFPath] |= BIT(8); + // CLOAD for RF paht_A/B (MP-chip) + if (val < 149) + PHY_SetRFReg(priv, eRFPath, 0xB, BIT(16)|BIT(15)|BIT(14), 0x7); + else + PHY_SetRFReg(priv, eRFPath, 0xB, BIT(16)|BIT(15)|BIT(14), 0x2); + } else { + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(16), 0); + //PHY_SetRFReg(priv, eRFPath, rRfChannel, BIT(8), 0); + priv->pshare->RegRF18[eRFPath] &= (~BIT(16)); + priv->pshare->RegRF18[eRFPath] &= (~BIT(8)); + + // CLOAD for RF paht_A/B (MP-chip) + PHY_SetRFReg(priv, eRFPath, 0xB, BIT(16)|BIT(15)|BIT(14), 0x7); + } + PHY_SetRFReg(priv, eRFPath, 0x18, bMask20Bits, priv->pshare->RegRF18[eRFPath]); + }else +#endif + { + PHY_SetRFReg(priv, eRFPath, 0x18, bMask20Bits, val_read | val); + } + } + + channel = val; + } + + +#ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8188E){ + unsigned int val_read; + val_read = PHY_QueryRFReg(priv, 0, 0x18, bMask20Bits, 1); + + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + val_read |= BIT(10); + val_read &= (~BIT(11)); + } + else + { + val_read |= BIT(10); + val_read |= BIT(11); + } + + PHY_SetRFReg(priv, 0, 0x18, bMask20Bits, val_read); + } +#endif + + + +#ifdef CONFIG_RTL_92D_SUPPORT + if(CHECKICIS92D()) + { + reload_txpwr_pg(priv); + +#ifdef USB_POWER_SUPPORT +//_TXPWR_REDEFINE + { + int i; + for (i=8; i<=15; i++){ + priv->pshare->phw->OFDMTxAgcOffset_A[i] = 0; + priv->pshare->phw->OFDMTxAgcOffset_B[i] = 0; + } + + } +#endif + + SetSYN_para(priv,channel); +#ifdef SW_LCK_92D + phy_ReloadLCKSetting(priv); +#endif + SetIMR_n(priv, channel); + + Update92DRFbyChannel(priv, channel); + + PHY_IQCalibrate(priv); +#ifdef DPK_92D + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_5G && priv->pshare->rf_ft_var.dpk_on) + PHY_DPCalibrate(priv); +#endif + } +#endif + +//#ifndef CONFIG_RTL_92D_SUPPORT + if(CHECKICIS92C()) { + if (priv->pshare->rf_ft_var.use_frq_2_3G) + channel -= 14; + } +//#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + if (channel == 13) { + PHY_SetBBReg(priv, 0xd18, BIT(27), 1); + PHY_SetBBReg(priv, 0xd2C, BIT(28), 1); + PHY_SetBBReg(priv, 0xd40, BIT(26), 1); + } else { + PHY_SetBBReg(priv, 0xd18, BIT(27), 0); + PHY_SetBBReg(priv, 0xd2C, BIT(28), 0); + PHY_SetBBReg(priv, 0xd40, BIT(26), 0); + } + } +#endif + + priv->pshare->working_channel = channel; + + //CCK Shaping Filter + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G +#ifdef HIGH_POWER_EXT_LNA + && !(GET_CHIP_VER(priv) == VERSION_8188E && priv->pshare->rf_ft_var.use_ext_lna) +#endif + ) + set_CCK_swing_index(priv, priv->pshare->mp_cck_swing_idx); + +// mp_8192CD_tx_setting(priv); + +#ifdef CONFIG_RTL_92C_SUPPORT + if(IS_UMC_B_CUT_88C(priv)) { + if(channel==6) + RTL_W8(0xc50, 0x22); + else + RTL_W8(0xc50, 0x20); + } +#endif + +#if 0//def TXPWR_LMT + if (!priv->pshare->rf_ft_var.disable_txpwrlmt){ + int i; + int max_idx; + + find_pwr_limit(priv); + + if (!priv->pshare->txpwr_lmt_OFDM || !priv->pshare->tgpwr_OFDM){ + DEBUG_INFO("No limit for OFDM TxPower\n"); + max_idx=255; + }else{ + // maximum additional power index + max_idx = (priv->pshare->txpwr_lmt_OFDM - priv->pshare->tgpwr_OFDM); + } + + for (i=0; i<=7; i++) { + priv->pshare->phw->OFDMTxAgcOffset_A[i] = POWER_MIN_CHECK(priv->pshare->phw->OFDMTxAgcOffset_A[i], max_idx); + priv->pshare->phw->OFDMTxAgcOffset_B[i] = POWER_MIN_CHECK(priv->pshare->phw->OFDMTxAgcOffset_B[i], max_idx); + //printk("priv->pshare->phw->OFDMTxAgcOffset_A[%d]=%x\n",i, priv->pshare->phw->OFDMTxAgcOffset_A[i]); + //printk("priv->pshare->phw->OFDMTxAgcOffset_B[%d]=%x\n",i, priv->pshare->phw->OFDMTxAgcOffset_B[i]); + } + + + if (!priv->pshare->txpwr_lmt_HT1S || !priv->pshare->tgpwr_HT1S){ + DEBUG_INFO("No limit for HT1S TxPower\n"); + max_idx=255; + }else{ + // maximum additional power index + max_idx = (priv->pshare->txpwr_lmt_HT1S - priv->pshare->tgpwr_HT1S); + } + + for (i=0; i<=7; i++) { + priv->pshare->phw->MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_A[i], max_idx); + priv->pshare->phw->MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_B[i], max_idx); + //printk("priv->pshare->phw->MCSTxAgcOffset_A[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_A[i]); + //printk("priv->pshare->phw->MCSTxAgcOffset_B[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_B[i]); + } + + if (!priv->pshare->txpwr_lmt_HT2S || !priv->pshare->tgpwr_HT2S){ + DEBUG_INFO("No limit for HT2S TxPower\n"); + max_idx=255; + }else{ + // maximum additional power index + max_idx = (priv->pshare->txpwr_lmt_HT2S - priv->pshare->tgpwr_HT2S); + } + + for (i=8; i<=15; i++) { + priv->pshare->phw->MCSTxAgcOffset_A[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_A[i], max_idx); + priv->pshare->phw->MCSTxAgcOffset_B[i] = POWER_MIN_CHECK(priv->pshare->phw->MCSTxAgcOffset_B[i], max_idx); + //printk("priv->pshare->phw->MCSTxAgcOffset_A[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_A[i]); + //printk("priv->pshare->phw->MCSTxAgcOffset_B[%d]=%x\n",i, priv->pshare->phw->MCSTxAgcOffset_B[i]); + } + + if (!priv->pshare->txpwr_lmt_CCK || !priv->pshare->tgpwr_CCK){ + DEBUG_INFO("No limit for CCK TxPower\n"); + max_idx=255; + }else{ + // maximum additional power index + max_idx = (priv->pshare->txpwr_lmt_CCK - priv->pshare->tgpwr_CCK); + } + + for (i=0; i<=3; i++) { + priv->pshare->phw->CCKTxAgc_A[i] = POWER_MIN_CHECK(priv->pshare->phw->CCKTxAgc_A[i], max_idx); + priv->pshare->phw->CCKTxAgc_B[i] = POWER_MIN_CHECK(priv->pshare->phw->CCKTxAgc_B[i], max_idx); + //printk("priv->pshare->phw->CCKTxAgc_A[%d]=%x\n",i, priv->pshare->phw->CCKTxAgc_A[i]); + //printk("priv->pshare->phw->CCKTxAgc_B[%d]=%x\n",i, priv->pshare->phw->CCKTxAgc_B[i]); + } + } +#endif + + sprintf(tmpbuf, "Change channel %d to channel %d\n", channel_org, channel); + printk(tmpbuf); +} + + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + +void mp_set_tx_power_8812(struct rtl8192cd_priv *priv, char pwrA, char pwrB) +{ + int base_A,base_B/*, byte0, byte1, byte2, byte3*/; + //unsigned int writeVal = 0; + +#if 1 + base_A = (pwrA << 24) | (pwrA << 16) | (pwrA << 8) | (pwrA); + base_B = (pwrB << 24) | (pwrB << 16) | (pwrB << 8) | (pwrB); + + RTL_W32(rTxAGC_A_Ofdm18_Ofdm6_JAguar, base_A); + RTL_W32(rTxAGC_A_Ofdm54_Ofdm24_JAguar, base_A); + RTL_W32(rTxAGC_A_MCS3_MCS0_JAguar, base_A); + RTL_W32(rTxAGC_A_MCS7_MCS4_JAguar, base_A); + RTL_W32(rTxAGC_A_MCS11_MCS8_JAguar, base_A); + RTL_W32(rTxAGC_A_MCS15_MCS12_JAguar, base_A); + RTL_W32(rTxAGC_A_Nss1Index3_Nss1Index0_JAguar, base_A); + RTL_W32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar, base_A); + RTL_W32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar, base_A); + RTL_W32(rTxAGC_A_Nss2Index5_Nss2Index2_JAguar, base_A); + RTL_W32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar, base_A); + + RTL_W32(rTxAGC_B_Ofdm18_Ofdm6_JAguar, base_B); + RTL_W32(rTxAGC_B_Ofdm54_Ofdm24_JAguar, base_B); + RTL_W32(rTxAGC_B_MCS3_MCS0_JAguar, base_B); + RTL_W32(rTxAGC_B_MCS7_MCS4_JAguar, base_B); + RTL_W32(rTxAGC_B_MCS11_MCS8_JAguar, base_B); + RTL_W32(rTxAGC_B_MCS15_MCS12_JAguar, base_B); + RTL_W32(rTxAGC_B_Nss1Index3_Nss1Index0_JAguar, base_B); + RTL_W32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar, base_B); + RTL_W32(rTxAGC_B_Nss2Index1_Nss1Index8_JAguar, base_B); + RTL_W32(rTxAGC_B_Nss2Index5_Nss2Index2_JAguar, base_B); + RTL_W32(rTxAGC_B_Nss2Index9_Nss2Index6_JAguar, base_B); + + RTL_W32(rTxAGC_A_CCK11_CCK1_JAguar, base_A); + RTL_W32(rTxAGC_B_CCK11_CCK1_JAguar, base_B); +#else + base_A = pwrA; + base_B = pwrB; + + //3 ====================== PATH A ====================== + //4 OFDM + byte0 = byte1 = byte2 = byte3 = 0; + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->OFDMTxAgcOffset_A[3]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->OFDMTxAgcOffset_A[2]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->OFDMTxAgcOffset_A[1]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->OFDMTxAgcOffset_A[0]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_Ofdm18_Ofdm6_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->OFDMTxAgcOffset_A[7]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->OFDMTxAgcOffset_A[6]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->OFDMTxAgcOffset_A[5]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->OFDMTxAgcOffset_A[4]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_Ofdm54_Ofdm24_JAguar, writeVal); + + //4 MCS + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[3]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[2]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[1]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[0]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_MCS3_MCS0_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[7]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[6]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[5]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[4]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_MCS7_MCS4_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[11]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[10]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[9]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[8]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_MCS11_MCS8_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[15]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[14]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[13]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->MCSTxAgcOffset_A[12]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_MCS15_MCS12_JAguar, writeVal); + + //4 VHT + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[3]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[2]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[1]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[0]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_Nss1Index3_Nss1Index0_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[7]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[6]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[5]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[4]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[11]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[10]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[9]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[8]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[15]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[14]); + byte2 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[13]); + byte3 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[12]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_Nss2Index5_Nss2Index2_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[19]); + byte1 = POWER_RANGE_CHECK(base_A + priv->pshare->phw->VHTTxAgcOffset_A[18]); + byte2 = POWER_RANGE_CHECK(base_A - priv->pshare->phw->VHTTxAgcOffset_A[17]); + byte3 = POWER_RANGE_CHECK(base_A - priv->pshare->phw->VHTTxAgcOffset_A[16]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar, writeVal); + + //3 ====================== PATH B ====================== + //4 OFDM + byte0 = byte1 = byte2 = byte3 = 0; + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->OFDMTxAgcOffset_B[3]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->OFDMTxAgcOffset_B[2]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->OFDMTxAgcOffset_B[1]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->OFDMTxAgcOffset_B[0]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_Ofdm18_Ofdm6_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->OFDMTxAgcOffset_B[7]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->OFDMTxAgcOffset_B[6]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->OFDMTxAgcOffset_B[5]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->OFDMTxAgcOffset_B[4]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_Ofdm54_Ofdm24_JAguar, writeVal); + + //4 MCS + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[3]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[2]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[1]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[0]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_MCS3_MCS0_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[7]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[6]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[5]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[4]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_MCS7_MCS4_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[11]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[10]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[9]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[8]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_MCS11_MCS8_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[15]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[14]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[13]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->MCSTxAgcOffset_B[12]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_MCS15_MCS12_JAguar, writeVal); + + //4 VHT + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[3]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[2]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[1]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[0]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_Nss1Index3_Nss1Index0_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[7]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[6]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[5]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[4]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_B - priv->pshare->phw->VHTTxAgcOffset_B[11]); + byte1 = POWER_RANGE_CHECK(base_B - priv->pshare->phw->VHTTxAgcOffset_B[10]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[9]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[8]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_Nss2Index1_Nss1Index8_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[15]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[14]); + byte2 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[13]); + byte3 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[12]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_Nss2Index5_Nss2Index2_JAguar, writeVal); + + byte0 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[19]); + byte1 = POWER_RANGE_CHECK(base_B + priv->pshare->phw->VHTTxAgcOffset_B[18]); + byte2 = POWER_RANGE_CHECK(base_B - priv->pshare->phw->VHTTxAgcOffset_B[17]); + byte3 = POWER_RANGE_CHECK(base_B - priv->pshare->phw->VHTTxAgcOffset_B[16]); + writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) | byte0; + RTL_W32(rTxAGC_B_Nss2Index9_Nss2Index6_JAguar, writeVal); +#endif +} + +#endif + +/* + * set tx power + */ +void mp_set_tx_power(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned int channel = priv->pmib->dot11RFEntry.dot11channel; + char *val, tmpbuf[64]; + unsigned int writeVal; + char baseA,baseB, byte[4]; + int i; + + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) + { + printk("Fail: not in MP mode\n"); + return; + } + + if (strlen(data) == 0) { + priv->pshare->mp_txpwr_patha = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[channel-1]; + priv->pshare->mp_txpwr_pathb = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[channel-1]; + } else { + val = get_value_by_token((char *)data, "patha="); + if (val) { + priv->pshare->mp_txpwr_patha = _atoi(val, 10); + } + + val = get_value_by_token((char *)data, "pathb="); + if (val) { + priv->pshare->mp_txpwr_pathb = _atoi(val, 10); + } + } +/* +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + if(priv->pshare->mp_txpwr_patha > HP_OFDM_POWER_MAX) + priv->pshare->mp_txpwr_patha = HP_OFDM_POWER_MAX; + if(priv->pshare->mp_txpwr_pathb > HP_OFDM_POWER_MAX) + priv->pshare->mp_txpwr_pathb = HP_OFDM_POWER_MAX; + + sprintf(tmpbuf, "Set OFDM power level path_A:%d path_B:%d\n", + priv->pshare->mp_txpwr_patha, priv->pshare->mp_txpwr_pathb); + printk(tmpbuf); + + } +#endif +*/ + +#if defined(CALIBRATE_BY_ODM) && defined(CONFIG_RTL_88E_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + PHY_RF6052SetCCKTxPower(priv, *(ODMPTR->pChannel)); + PHY_RF6052SetOFDMTxPower(priv, *(ODMPTR->pChannel)); + } else +#endif + { + baseA = priv->pshare->mp_txpwr_patha; + baseB = priv->pshare->mp_txpwr_pathb; + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if((GET_CHIP_VER(priv)==VERSION_8812E) || (GET_CHIP_VER(priv)==VERSION_8881A)) + { + panic_printk("Set 8812 power level path_A:%d path_B:%d\n", priv->pshare->mp_txpwr_patha, priv->pshare->mp_txpwr_pathb); + mp_set_tx_power_8812(priv, baseA, baseB); + return; + } +#endif + + + /**************path-A**************/ + // 18M ~ 6M + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseA + priv->pshare->phw->OFDMTxAgcOffset_A[i]); + else + byte[i] = baseA; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_A_Rate18_06, writeVal); + + // 54M ~ 24M + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseA + priv->pshare->phw->OFDMTxAgcOffset_A[i+4]); + else + byte[i] = baseA; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_A_Rate54_24, writeVal); + + // MCS3 ~ MCS0 + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseA + priv->pshare->phw->MCSTxAgcOffset_A[i]); + else + byte[i] = baseA; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_A_Mcs03_Mcs00, writeVal); + + // MCS7 ~ MCS4 + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseA + priv->pshare->phw->MCSTxAgcOffset_A[i+4]); + else + byte[i] = baseA; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_A_Mcs07_Mcs04, writeVal); + + // MCS11 ~ MCS8 + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + { + //_TXPWR_REDEFINE ?? #if 0 in FOX + byte[i] = POWER_RANGE_CHECK(baseA + priv->pshare->phw->MCSTxAgcOffset_A[i+8]); + } + else + byte[i] = baseA; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_A_Mcs11_Mcs08, writeVal); + + // MCS15 ~ MCS12 + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + { + //_TXPWR_REDEFINE ?? #if 0 in FOX + byte[i] = POWER_RANGE_CHECK(baseA + priv->pshare->phw->MCSTxAgcOffset_A[i+12]); + } + else + byte[i] = baseA; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_A_Mcs15_Mcs12, writeVal); + + + /**************path-B**************/ + // 18M ~ 6M + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseB + priv->pshare->phw->OFDMTxAgcOffset_B[i]); + else + byte[i] = baseB; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_B_Rate18_06, writeVal); + + + // 54M ~ 24M + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseB + priv->pshare->phw->OFDMTxAgcOffset_B[i+4]); + else + byte[i] = baseB; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_B_Rate54_24, writeVal); + + // MCS3 ~ MCS0 + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseB + priv->pshare->phw->MCSTxAgcOffset_B[i]); + else + byte[i] = baseB; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_B_Mcs03_Mcs00, writeVal); + + // MCS7 ~ MCS4 + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseB + priv->pshare->phw->MCSTxAgcOffset_B[i+4]); + else + byte[i] = baseB; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_B_Mcs07_Mcs04, writeVal); + + // MCS11 ~ MCS8 + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + { + //_TXPWR_REDEFINE ?? #if 0 in FOX + byte[i] = POWER_RANGE_CHECK(baseB + priv->pshare->phw->MCSTxAgcOffset_B[i+8]); + } + else + byte[i] = baseB; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_B_Mcs11_Mcs08, writeVal); + + // MCS15 ~ MCS12 + for (i=0; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + { + //_TXPWR_REDEFINE ?? #if 0 in FOX + byte[i] = POWER_RANGE_CHECK(baseB + priv->pshare->phw->MCSTxAgcOffset_B[i+12]); + } + else + byte[i] = baseB; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_OFDM_POWER_MAX); + } +#endif + writeVal = (byte[0]<<24) | (byte[1]<<16) |(byte[2]<<8) | byte[3]; + RTL_W32(rTxAGC_B_Mcs15_Mcs12, writeVal); + +/* +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + if(priv->pshare->mp_txpwr_patha > HP_CCK_POWER_MAX) + priv->pshare->mp_txpwr_patha = HP_CCK_POWER_MAX; + if(priv->pshare->mp_txpwr_pathb > HP_CCK_POWER_MAX) + priv->pshare->mp_txpwr_pathb = HP_CCK_POWER_MAX; + + sprintf(tmpbuf, "Set CCK power level path_A:%d path_B:%d\n", + priv->pshare->mp_txpwr_patha, priv->pshare->mp_txpwr_pathb); + printk(tmpbuf); + } +#endif +*/ + + // CCK-A 1M + if (priv->pshare->rf_ft_var.pwr_by_rate) + writeVal = POWER_RANGE_CHECK(baseA + priv->pshare->phw->CCKTxAgc_A[3]); + else + writeVal = baseA; +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + writeVal = POWER_MIN_CHECK(writeVal, HP_CCK_POWER_MAX); + } +#endif + PHY_SetBBReg(priv, rTxAGC_A_CCK1_Mcs32, 0x0000ff00, writeVal); + + // CCK-B 11M ~ 2M + for (i=1; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseB + priv->pshare->phw->CCKTxAgc_B[i]); + else + byte[i] = baseB; + } +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=1; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_CCK_POWER_MAX); + } +#endif + writeVal = (byte[1]<<16) |(byte[2]<<8) | byte[3]; + PHY_SetBBReg(priv, rTxAGC_B_CCK5_1_Mcs32, 0xffffff00, writeVal); + + // CCK-A 11M ~ 2M CCK-B 11M + for (i=1; i<4; i++) { + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[i] = POWER_RANGE_CHECK(baseA + priv->pshare->phw->CCKTxAgc_A[i-1]); + else + byte[i] = baseA; + } + if (priv->pshare->rf_ft_var.pwr_by_rate) + byte[0] = POWER_RANGE_CHECK(baseB + priv->pshare->phw->CCKTxAgc_B[0]); + else + byte[0] = baseB; +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + for (i=0; i<4; i++) + byte[i] = POWER_MIN_CHECK(byte[i], HP_CCK_POWER_MAX); + } +#endif + writeVal = (byte[1]<<24) | (byte[2]<<16) |(byte[3]<<8) | byte[0]; + PHY_SetBBReg(priv, rTxAGC_A_CCK11_2_B_CCK11, 0xffffffff, writeVal); + +} + mp_8192CD_tx_setting(priv); + +#ifdef HIGH_POWER_EXT_PA + if (!priv->pshare->rf_ft_var.use_ext_pa) +#endif + { + sprintf(tmpbuf, "Set power level path_A:%d path_B:%d\n", + priv->pshare->mp_txpwr_patha, priv->pshare->mp_txpwr_pathb); + printk(tmpbuf); + } + +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef DPK_92D + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) ) { + + unsigned int tmp_txpwr_dpk_0 = 0, tmp_txpwr_dpk_1 = 0; + + tmp_txpwr_dpk_0 += (priv->pshare->TxPowerLevelDPK[0]); + tmp_txpwr_dpk_0 += (priv->pshare->TxPowerLevelDPK[0]<<8); + tmp_txpwr_dpk_0 += (priv->pshare->TxPowerLevelDPK[0]<<16); + tmp_txpwr_dpk_0 += (priv->pshare->TxPowerLevelDPK[0]<<24); + + tmp_txpwr_dpk_1 += (priv->pshare->TxPowerLevelDPK[1]); + tmp_txpwr_dpk_1 += (priv->pshare->TxPowerLevelDPK[1]<<8); + tmp_txpwr_dpk_1 += (priv->pshare->TxPowerLevelDPK[1]<<16); + tmp_txpwr_dpk_1 += (priv->pshare->TxPowerLevelDPK[1]<<24); + + priv->pshare->phw->power_backup[0x00] = RTL_R32(rTxAGC_A_Rate18_06); + priv->pshare->phw->power_backup[0x01] = RTL_R32(rTxAGC_A_Rate54_24); + priv->pshare->phw->power_backup[0x02] = RTL_R32(rTxAGC_B_Rate18_06); + priv->pshare->phw->power_backup[0x03] = RTL_R32(rTxAGC_B_Rate54_24); + priv->pshare->phw->power_backup[0x04] = RTL_R32(rTxAGC_A_Mcs03_Mcs00); + priv->pshare->phw->power_backup[0x05] = RTL_R32(rTxAGC_A_Mcs07_Mcs04); + priv->pshare->phw->power_backup[0x06] = RTL_R32(rTxAGC_A_Mcs11_Mcs08); + priv->pshare->phw->power_backup[0x07] = RTL_R32(rTxAGC_A_Mcs15_Mcs12); + priv->pshare->phw->power_backup[0x08] = RTL_R32(rTxAGC_B_Mcs03_Mcs00); + priv->pshare->phw->power_backup[0x09] = RTL_R32(rTxAGC_B_Mcs07_Mcs04); + priv->pshare->phw->power_backup[0x0a] = RTL_R32(rTxAGC_B_Mcs11_Mcs08); + priv->pshare->phw->power_backup[0x0b] = RTL_R32(rTxAGC_B_Mcs15_Mcs12); + + RTL_W32(rTxAGC_A_Rate18_06, priv->pshare->phw->power_backup[0x00] +tmp_txpwr_dpk_0); + RTL_W32(rTxAGC_A_Rate54_24, priv->pshare->phw->power_backup[0x01] +tmp_txpwr_dpk_0); + RTL_W32(rTxAGC_B_Rate18_06, priv->pshare->phw->power_backup[0x02] +tmp_txpwr_dpk_1); + RTL_W32(rTxAGC_B_Rate54_24, priv->pshare->phw->power_backup[0x03] +tmp_txpwr_dpk_1); + RTL_W32(rTxAGC_A_Mcs03_Mcs00, priv->pshare->phw->power_backup[0x04] +tmp_txpwr_dpk_0); + RTL_W32(rTxAGC_A_Mcs07_Mcs04, priv->pshare->phw->power_backup[0x05] +tmp_txpwr_dpk_0); + RTL_W32(rTxAGC_A_Mcs11_Mcs08, priv->pshare->phw->power_backup[0x06] +tmp_txpwr_dpk_0); + RTL_W32(rTxAGC_A_Mcs15_Mcs12, priv->pshare->phw->power_backup[0x07] +tmp_txpwr_dpk_0); + RTL_W32(rTxAGC_B_Mcs03_Mcs00, priv->pshare->phw->power_backup[0x08] +tmp_txpwr_dpk_1); + RTL_W32(rTxAGC_B_Mcs07_Mcs04, priv->pshare->phw->power_backup[0x09] +tmp_txpwr_dpk_1); + RTL_W32(rTxAGC_B_Mcs11_Mcs08, priv->pshare->phw->power_backup[0x0a] +tmp_txpwr_dpk_1); + RTL_W32(rTxAGC_B_Mcs15_Mcs12, priv->pshare->phw->power_backup[0x0b] +tmp_txpwr_dpk_1); + } +#endif +#endif +} + + +/* + * continuous tx + * command: "iwpriv wlanx mp_ctx [time=t,count=n,background,stop,pkt,cs,stone,scr]" + * if "time" is set, tx in t sec. if "count" is set, tx with n packet + * if "background", it will tx continuously until "stop" is issue + * if "pkt", send cck packets with packet mode (not hardware) + * if "cs", send cck packet with carrier suppression + * if "stone", send packet in single-tone + * default: tx infinitely (no background) + */ +void mp_ctx(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned int orgTCR = RTL_R32(TCR); + unsigned char pbuf[6]={0xff,0xff,0xff,0xff,0xff,0xff}; + int payloadlen=1500, time=-1; + struct sk_buff *skb; + struct wlan_ethhdr_t *pethhdr; + int len, i=0, q_num; + unsigned char pattern; + char *val; + unsigned long end_time=0; + unsigned long flags=0; + unsigned long flags2=0; + int tx_from_isr=0, background=0; +#ifdef CONFIG_PCI_HCI + struct rtl8192cd_hw *phw = GET_HW(priv); + volatile unsigned int head, tail; +#endif + RF92CD_RADIO_PATH_E eRFPath; + +#ifdef CONFIG_RTL_92D_SUPPORT + unsigned int temp_860=0, temp_864=0, temp_870=0; +#endif +/* +// We need to turn off ADC before entering CTX mode + RTL_W32(0xe70, (RTL_R32(0xe70) & 0xFE1FFFFF ) ); + delay_us(100); +*/ + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) + { + printk("Fail: not in MP mode\n"); + return; + } + + // get count + val = get_value_by_token((char *)data, "count="); + if (val) { + priv->pshare->mp_ctx_count = _atoi(val, 10); + if (priv->pshare->mp_ctx_count) + time = 0; + } + + // get time + val = get_value_by_token((char *)data, "time="); + if (val) { + if (!memcmp(val, "-1", 2)) + time = -1; + else + time = RTL_SECONDS_TO_JIFFIES(_atoi(val, 10)); + if (time > 0) + end_time = jiffies + time; + } + + // get payload len + val = get_value_by_token((char *)data, "len="); + if (val) { + priv->pshare->mp_pkt_len = _atoi(val, 10); + if (priv->pshare->mp_pkt_len < 20) { + printk("len should be greater than 20!\n"); + return; + } + } + + // get background + val = get_value_by_token((char *)data, "background"); + if (val) + background = 1; + + // get carrier suppression mode + val = get_value_by_token((char *)data, "cs"); + if (val) { + if (!is_CCK_rate(priv->pshare->mp_datarate)) { + printk("Specify carrier suppression but not CCK rate!\n"); + return; + } + else + OPMODE_VAL(OPMODE | WIFI_MP_CTX_CCK_CS); + } + + // get single-tone + val = get_value_by_token((char *)data, "stone"); + if (val) + OPMODE_VAL(OPMODE | WIFI_MP_CTX_ST); + + // get single-carrier + val = get_value_by_token((char *)data, "scr"); + if (val) { + if (is_CCK_rate(priv->pshare->mp_datarate)) { + printk("Specify single carrier but CCK rate!\n"); + return; + } + else + OPMODE_VAL(WIFI_MP_CTX_SCR); + } + + // get stop + val = get_value_by_token((char *)data, "stop"); + if (val) { + + if (!(OPMODE & WIFI_MP_CTX_BACKGROUND)) { + printk("Error! Continuous-Tx is not on-going.\n"); + return; + } + goto stop_tx; + } + + + // get tx-isr flag, which is set in ISR when Tx ok + val = get_value_by_token((char *)data, "tx-isr"); + if (val) { + if (OPMODE & WIFI_MP_CTX_BACKGROUND) { + + if (((OPMODE & WIFI_MP_CTX_ST) || !(OPMODE & (WIFI_MP_CTX_PACKET|WIFI_MP_CTX_CCK_CS))) + && (priv->net_stats.tx_packets > 0)) + return; + + SMP_LOCK(flags); + tx_from_isr = 1; + time = -1; + } +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + else { + // avoid race condition between background and stop, which will cuase infinite loop + return; + } +#endif + } + + if (priv->pshare->mp_pkt_len) + payloadlen = priv->pshare->mp_pkt_len; + else + payloadlen = 1500; + + if (!tx_from_isr && (OPMODE & WIFI_MP_CTX_BACKGROUND)) { + printk("Continuous-Tx is on going. You can't issue any tx command except 'stop'.\n"); + return; + } + // get packet mode + val = get_value_by_token((char *)data, "pkt"); + if (val) + OPMODE_VAL(OPMODE | WIFI_MP_CTX_PACKET); + + if (background) { + priv->pshare->skb_pool_ptr = kmalloc(sizeof(struct sk_buff)*NUM_MP_SKB, GFP_KERNEL); + if (priv->pshare->skb_pool_ptr == NULL) { + printk("Allocate skb fail!\n"); + return; + } + memset(priv->pshare->skb_pool_ptr, 0, sizeof(struct sk_buff)*NUM_MP_SKB); + for (i=0; ipshare->skb_pool[i] = (struct sk_buff *)(priv->pshare->skb_pool_ptr + i * sizeof(struct sk_buff)); + priv->pshare->skb_pool[i]->head = kmalloc(RX_BUF_LEN, GFP_KERNEL); + if (priv->pshare->skb_pool[i]->head == NULL) { + for (i=0; ipshare->skb_pool[i]->head) + kfree(priv->pshare->skb_pool[i]->head); + else + break; + } + kfree(priv->pshare->skb_pool_ptr); + printk("Allocate skb fail!\n"); + return; + } + else { + priv->pshare->skb_pool[i]->data = priv->pshare->skb_pool[i]->head; + priv->pshare->skb_pool[i]->tail = priv->pshare->skb_pool[i]->data; + priv->pshare->skb_pool[i]->end = priv->pshare->skb_pool[i]->head + RX_BUF_LEN; + priv->pshare->skb_pool[i]->len = 0; + } + } + priv->pshare->skb_head = 0; + priv->pshare->skb_tail = 0; + + /*disable interrupt and change OPMODE here to avoid re-enter*/ + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + +#if defined(CONFIG_PCI_HCI) + head = get_txhead(phw, BE_QUEUE); + tail = get_txtail(phw, BE_QUEUE); + + while (head != tail) { + DEBUG_INFO("BEQ head/tail=%d/%d\n", head, tail); + rtl8192cd_tx_dsr((unsigned long)priv); + delay_us(50); + tail = get_txtail(phw, BE_QUEUE); + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + i = 0; + while ((NR_XMITFRAME != priv->pshare->free_xmit_queue.qlen) + || (NR_XMITBUFF != priv->pshare->free_xmitbuf_queue.qlen)) { + msleep(50); + i++; + if (i > 200) { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + printk("[break] some normal SKB still exist!!\n"); + return; + } + } +#endif + + OPMODE_VAL(OPMODE | WIFI_MP_CTX_BACKGROUND); + time = -1; // set as infinite + } + + len = payloadlen + WLAN_ETHHDR_LEN; + pattern = 0xAB; + q_num = BE_QUEUE; + + if (!tx_from_isr) { +#ifdef GREEN_HILL + printk("Start continuous TX"); +#else + if (time < 0) // infinite + printk("Start continuous DA=%02x%02x%02x%02x%02x%02x len=%d infinite=yes", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], payloadlen); + else if (time > 0) // by time + printk("Start continuous DA=%02x%02x%02x%02x%02x%02x len=%d time=%ds", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], + payloadlen, time/HZ); + else // by count + printk("Start TX DA=%02x%02x%02x%02x%02x%02x len=%d count=%d", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], + payloadlen, priv->pshare->mp_ctx_count); + +#if defined(USE_RTL8186_SDK) + if (!background) { + printk(", press any key to escape.\n"); + } else +#endif + printk(".\n"); +#endif // GREEN_HILL + + if (OPMODE & WIFI_MP_CTX_PACKET) { + RTL_W16(TX_PTCL_CTRL, RTL_R16(TX_PTCL_CTRL) & ~DIS_CW); + RTL_W32(EDCA_BE_PARA, (RTL_R32(EDCA_BE_PARA) & 0xffffff00) | (10 + 2 * 20)); + } else { + RTL_W16(TX_PTCL_CTRL, RTL_R16(TX_PTCL_CTRL) | DIS_CW); + RTL_W32(EDCA_BE_PARA, (RTL_R32(EDCA_BE_PARA) & 0xffffff00) | 0x01); + + if (is_CCK_rate(priv->pshare->mp_datarate)) { + if (OPMODE & WIFI_MP_CTX_CCK_CS) + mpt_ProSetCarrierSupp(priv, TRUE); + else + mpt_StartCckContTx(priv); + } else { + if (!((OPMODE & WIFI_MP_CTX_ST) && (OPMODE & WIFI_MP_CTX_SCR))) + mpt_StartOfdmContTx(priv); + OPMODE_VAL(OPMODE | WIFI_MP_CTX_OFDM_HW); + } + } +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + RTL_W32(RCR, RTL_R32(RCR) & ~(RCR_APWRMGT | RCR_AMF | RCR_ADF |RCR_ACRC32 |RCR_AB | RCR_AM | RCR_APM | RCR_AAP)); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + RTL_W32(RCR, RTL_R32(RCR) & ~(RCR_AB | RCR_AM | RCR_APM | RCR_AAP)); + + +#if defined(USE_RTL8186_SDK) + if (!background) { + DISABLE_UART0_INT(); +#ifdef _MP_TELNET_SUPPORT_ + mp_pty_write_monitor(1); +#endif //_MP_TELNET_SUPPORT_ + } +#endif + + memset(&priv->net_stats, 0, sizeof(struct net_device_stats)); + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (background) { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + notify_mp_ctx_background(priv); + return; + } +#endif + + + if (is_CCK_rate(priv->pshare->mp_datarate)) { + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x0f400); + } else { +#ifdef CONFIG_RTL_92C_SUPPORT + if( IS_UMC_A_CUT_88C(priv) || GET_CHIP_VER(priv) == VERSION_8192C) { + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x4f000); + } else +#endif + { +#ifdef CONFIG_RTL_92C_SUPPORT + if( (IS_UMC_B_CUT_88C(priv) || GET_CHIP_VER(priv) == VERSION_8192C) + && ((priv->pmib->dot11RFEntry.dot11channel == 4)||(priv->pmib->dot11RFEntry.dot11channel == 12))) + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x4f000); + else +#endif + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x4f200); + } + } + + i = 0; + while (1) + { + +#if defined(USE_RTL8186_SDK) +#ifdef _MP_TELNET_SUPPORT_ + if (!in_atomic() && !tx_from_isr && !background) + schedule(); + if (!tx_from_isr && !background && (IS_KEYBRD_HIT()||mp_pty_is_hit())) + break; +#else + if (!tx_from_isr && !background && IS_KEYBRD_HIT()) + break; +#endif //_MP_TELNET_SUPPORT_ +#endif + + if (time) { + if (time != -1) { + if (jiffies > end_time) + break; + } + else { + if ((priv->pshare->mp_ctx_count > 0) && (priv->pshare->mp_ctx_pkt >= priv->pshare->mp_ctx_count)) { + if (background) { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + } else if (tx_from_isr) { + SMP_UNLOCK(flags); + } + delay_ms(10); + return; + } + } + } + else { + if (i >= priv->pshare->mp_ctx_count) + break; + } + i++; + priv->pshare->mp_ctx_pkt++; + +if ((OPMODE & WIFI_MP_CTX_ST) && + (i == 1)) { + i++; + + { + switch (priv->pshare->mp_antenna_tx) { + case ANTENNA_B: + eRFPath = RF92CD_PATH_B; + break; + case ANTENNA_A: + default: + eRFPath = RF92CD_PATH_A; + break; + } + } + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812() || CHECKICIS8881A()) { + PHY_SetBBReg(priv, rFPGA0_RFMOD, BIT(28), 0x0); + PHY_SetBBReg(priv, rFPGA0_RFMOD, BIT(29), 0x0); + + //4 load LO + PHY_SetRFReg(priv, eRFPath, LNA_Low_Gain_3, BIT(1), 1); + + //4 rf tx mode +#ifdef HIGH_POWER_EXT_PA + if(priv->pshare->rf_ft_var.use_ext_pa) + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, 0x20000); //From suggestion of BS (RF Team) + else +#endif + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, 0x20010); + delay_us(100); + + if (eRFPath == RF92CD_PATH_A) { + //4 3 wire off + PHY_SetBBReg(priv, 0xc00, BIT(1)|BIT(0), 0); + + //4 RFE software pull low + priv->pshare->RegCB0 = RTL_R32(0xcb0); + RTL_W32(0xcb0, 0x77777777); + + //4 trsw, pape pull high + PHY_SetBBReg(priv, 0xcb4, BIT(21), 1); +#if defined(CONFIG_RTL_8812_SUPPORT) + PHY_SetBBReg(priv, 0xcb4, BIT(24), 1); +#elif defined(CONFIG_WLAN_HAL_8881A) + PHY_SetBBReg(priv, 0xcb4, BIT(23), 1); +#endif + } else { + //4 3 wire off + PHY_SetBBReg(priv, 0xe00, BIT(1)|BIT(0), 0); + + //4 RFE software pull low + priv->pshare->RegEB0 = RTL_R32(0xeb0); + RTL_W32(0xeb0, 0x77777777); + + //4 trsw, pape pull high + PHY_SetBBReg(priv, 0xeb4, BIT(21), 1); +#if defined(CONFIG_RTL_8812_SUPPORT) + PHY_SetBBReg(priv, 0xeb4, BIT(24), 1); +#elif defined(CONFIG_WLAN_HAL_8881A) + PHY_SetBBReg(priv, 0xeb4, BIT(23), 1); +#endif + } + } else +#endif + { + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + PHY_SetRFReg(priv, eRFPath, LNA_Low_Gain_3, BIT(1) ,0x1); + } +#ifdef HIGH_POWER_EXT_PA + if(priv->pshare->rf_ft_var.use_ext_pa){ + PHY_SetBBReg(priv, 0x4c, BIT(23), 0x1); + PHY_SetBBReg(priv, 0x4c, BIT(24), 0x1); + PHY_SetBBReg(priv, 0x4c, BIT(25), 0x1); + PHY_SetBBReg(priv, 0x4c, BIT(26), 0x1); + PHY_SetBBReg(priv, 0x4c, BIT(27), 0x1); + + PHY_SetBBReg(priv, 0x64, BIT(2), 0X1); + PHY_SetBBReg(priv, 0x64, BIT(3), 0X1); + PHY_SetBBReg(priv, 0x64, BIT(4), 0X1); + PHY_SetBBReg(priv, 0x64, BIT(8), 0X1); + } +#endif +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E +#ifdef HIGH_POWER_EXT_PA + && !priv->pshare->rf_ft_var.use_ext_pa +#endif + ){ + PHY_SetRFReg(priv, eRFPath, LNA_Low_Gain_3, BIT(1) ,0x1); + } +#endif + // Start Single Tone. + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, 0x0); + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn, 0x0); + +#ifdef CONFIG_RTL_92D_SUPPORT // single tone + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_5G){ + temp_860 = PHY_QueryBBReg(priv, 0x860, bMaskDWord); + temp_864 = PHY_QueryBBReg(priv, 0x864, bMaskDWord); + temp_870 = PHY_QueryBBReg(priv, 0x870, bMaskDWord); + + if (eRFPath == RF92CD_PATH_A){ + PHY_SetBBReg(priv, 0x860, BIT(11), 0x1); + PHY_SetBBReg(priv, 0x870, BIT(11), 0x1); + PHY_SetBBReg(priv, 0x870, BIT(6)|BIT(5), 0x3); + } else { + PHY_SetBBReg(priv, 0x864, BIT(11), 0x1); + PHY_SetBBReg(priv, 0x870, BIT(27), 0x1); + PHY_SetBBReg(priv, 0x870, BIT(22)|BIT(21), 0x3); + } + PHY_SetRFReg(priv, eRFPath, 0x41, BIT(19), 1); + } else +#endif + { + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x21, bMask20Bits, 0xd4000); + } + delay_us(100); +#ifdef HIGH_POWER_EXT_PA + if(priv->pshare->rf_ft_var.use_ext_pa) + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, 0x20000); //From suggestion of BS (RF Team) + else +#endif + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, 0x20010); + + delay_us(100); + +#ifdef HIGH_POWER_EXT_PA + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)){ + if(priv->pshare->rf_ft_var.use_ext_pa) { + PHY_SetBBReg(priv, 0x860, BIT(10), 0x1); + PHY_SetBBReg(priv, 0x864, BIT(10), 0x1); + PHY_SetBBReg(priv, 0x870, BIT(10), 0x1); + PHY_SetBBReg(priv, 0x870, BIT(26), 0x1); + } + } +#endif + } + } + + if ((OPMODE & WIFI_MP_CTX_SCR) && + (i == 1)) { + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812() || CHECKICIS8881A()) { + // 1. if OFDM block on? + if(!PHY_QueryBBReg(priv, 0x808, BIT(29))) + PHY_SetBBReg(priv, 0x808, BIT(29), bEnable);//set CCK block on + + // 2. set CCK test mode off, set to CCK normal mode + PHY_SetBBReg(priv, rCCK0_System, bCCKBBMode, bDisable); + + // 3. turn on scramble setting + PHY_SetBBReg(priv, rCCK0_System, bCCKScramble, bEnable); + + // 4. Turn On Continue Tx and turn off the other test modes. + PHY_SetBBReg(priv, rSingleTone_ContTx_Jaguar, BIT(16) | BIT(17) | BIT(18), 0x2); + } else +#endif + { + // 1. if OFDM block on? + if (!PHY_QueryBBReg(priv, rFPGA0_RFMOD, bOFDMEn)) + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn, bEnable);//set OFDM block on + + // 2. set CCK test mode off, set to CCK normal mode + PHY_SetBBReg(priv, rCCK0_System, bCCKBBMode, bDisable); + + // 3. turn on scramble setting + PHY_SetBBReg(priv, rCCK0_System, bCCKScramble, bEnable); + + // 4. Turn On Continue Tx and turn off the other test modes. + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMContinueTx, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleCarrier, bEnable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleTone, bEnable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMDisPwsavTx, bEnable); + + PHY_SetBBReg(priv, rOFDM1_TRxMesaure1, 0xfff, 0x404); + } + } + + if ((OPMODE & WIFI_MP_CTX_OFDM_HW) && (i > 1)) { + if (background) { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return; + } else if (tx_from_isr) { + priv->net_stats.tx_packets = 1; + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_BACKGROUND_PENDING); + SMP_UNLOCK(flags); + return; + } else { + continue; + } + } + + if (background || tx_from_isr) { + if (CIRC_SPACE(priv->pshare->skb_head, priv->pshare->skb_tail, NUM_MP_SKB) > 1) { + skb = priv->pshare->skb_pool[priv->pshare->skb_head]; + priv->pshare->skb_head = (priv->pshare->skb_head + 1) & (NUM_MP_SKB - 1); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + // avoid race condition between background and stop + if ((OPMODE & WIFI_MP_CTX_BACKGROUND_STOPPING) || !(OPMODE & WIFI_MP_CTX_BACKGROUND)) { + priv->pshare->skb_head = (priv->pshare->skb_head + NUM_MP_SKB - 1) & (NUM_MP_SKB - 1); + SMP_UNLOCK(flags); + return; + } +#endif + } else { + OPMODE_VAL(OPMODE | WIFI_MP_CTX_BACKGROUND_PENDING); + priv->pshare->mp_ctx_pkt--; + if (background) + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return; + } + } else { + skb = dev_alloc_skb(len); + } + + if (skb != NULL) { + DECLARE_TXINSN(txinsn); + + skb->dev = priv->dev; + skb_put(skb, len); + + pethhdr = (struct wlan_ethhdr_t *)(skb->data); + memcpy((void *)pethhdr->daddr, pbuf, MACADDRLEN); + memcpy((void *)pethhdr->saddr, BSSID, MACADDRLEN); + pethhdr->type = htons(payloadlen); + + memset(skb->data+WLAN_ETHHDR_LEN, pattern, payloadlen); + + txinsn.q_num = q_num; //using low queue for data queue + txinsn.fr_type = _SKB_FRAME_TYPE_; + txinsn.pframe = skb; + skb->cb[1] = 0; + +#ifdef MCAST2UI_REFINE + memcpy(&skb->cb[10], skb->data, 6); +#endif +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + + txinsn.tx_rate = txinsn.lowest_tx_rate = priv->pshare->mp_datarate; + txinsn.fixed_rate = 1; + txinsn.retry = 0; + txinsn.phdr = get_wlanllchdr_from_poll(priv); + if (NULL == txinsn.phdr) + goto congestion_handle; + + memset((void *)txinsn.phdr, 0, sizeof(struct wlanllc_hdr)); + SetFrDs(txinsn.phdr); + SetFrameType(txinsn.phdr, WIFI_DATA); + + if(rtl8192cd_firetx(priv, &txinsn) == CONGESTED) { +congestion_handle: + //printk("Congested\n"); + i--; + priv->pshare->mp_ctx_pkt--; + if (txinsn.phdr) + release_wlanllchdr_to_poll(priv, txinsn.phdr); + + if (background || tx_from_isr) { + skb->tail = skb->data = skb->head; + skb->len = 0; + priv->pshare->skb_head = (priv->pshare->skb_head + NUM_MP_SKB - 1) & (NUM_MP_SKB - 1); + } else if (skb) { + rtl_kfree_skb(priv, skb, _SKB_TX_); + } + + if (tx_from_isr) { +#ifdef CONFIG_PCI_HCI + head = get_txhead(phw, BE_QUEUE); + tail = get_txtail(phw, BE_QUEUE); + if (head == tail) // if Q empty,invoke 1s-timer to send + OPMODE_VAL(OPMODE | (WIFI_MP_CTX_BACKGROUND | WIFI_MP_CTX_BACKGROUND_PENDING)); +#endif // CONFIG_PCI_HCI + SMP_UNLOCK(flags); + return; + } else { +#ifdef CONFIG_PCI_HCI + SAVE_INT_AND_CLI(flags2); +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + RESTORE_INT(flags2); +#endif // CONFIG_PCI_HCI + } + } + else if ((1 == priv->net_stats.tx_packets) && + ((OPMODE & (WIFI_MP_CTX_PACKET| WIFI_MP_CTX_BACKGROUND| WIFI_MP_CTX_ST| + WIFI_MP_CTX_CCK_CS))==WIFI_MP_CTX_BACKGROUND) ) + { + #define CHECK_TX_MODE_CNT 40 + int check_cnt; + + // must sure RF is in TX mode before enabling TXAGC function. + if ( priv->pshare->mp_antenna_tx & ANTENNA_A ) { + check_cnt = 0; + while ( (PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x00, 0x70000, 1) != 0x02) && (check_cnt < CHECK_TX_MODE_CNT) ) { + delay_ms(1); ++check_cnt; + } + printk("RF(A) # of check tx mode = %d (%d)\n", check_cnt, tx_from_isr); + PHY_SetBBReg(priv, 0x820, 0x400, 0x1); + } + + if ( priv->pshare->mp_antenna_tx & ANTENNA_B ) { + check_cnt = 0; + while ( (PHY_QueryRFReg(priv, RF92CD_PATH_B, 0x00, 0x70000, 1) != 0x02) && (check_cnt < CHECK_TX_MODE_CNT) ) { + delay_ms(1); ++check_cnt; + } + printk("RF(B) # of check tx mode = %d\n", check_cnt); + PHY_SetBBReg(priv, 0x828, 0x400, 0x1); + } + + if ( background ) { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + } else if (tx_from_isr) { + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_BACKGROUND_PENDING); + SMP_UNLOCK(flags); + } + return; + + #undef CHECK_TX_MODE_CNT + } + } + else + { + i--; + priv->pshare->mp_ctx_pkt--; + + //printk("Can't allocate sk_buff\n"); + if (tx_from_isr) { +#ifdef CONFIG_PCI_HCI + head = get_txhead(phw, BE_QUEUE); + tail = get_txtail(phw, BE_QUEUE); + if (head == tail) // if Q empty,invoke 1s-timer to send + OPMODE_VAL(OPMODE | (WIFI_MP_CTX_BACKGROUND | WIFI_MP_CTX_BACKGROUND_PENDING)); +#endif // CONFIG_PCI_HCI + SMP_UNLOCK(flags); + return; + } + delay_ms(1); +#ifdef CONFIG_PCI_HCI + SAVE_INT_AND_CLI(flags2); +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + RESTORE_INT(flags2); +#endif // CONFIG_PCI_HCI + } + + if ((background || tx_from_isr) && (i == CURRENT_NUM_TX_DESC/4)) { + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_BACKGROUND_PENDING); + if (background) + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return; + } + } + +#if defined(USE_RTL8186_SDK) + if (!tx_from_isr && !background) { + RESTORE_UART0_INT(); +#ifdef _MP_TELNET_SUPPORT_ + mp_pty_write_monitor(0); +#endif //_MP_TELNET_SUPPORT_ + } +#endif + +stop_tx: + + RTL_W32(TCR, orgTCR); +/* +// turn on ADC + RTL_W32(0xe70, (RTL_R32(0xe70) | 0x01e00000) ); + delay_us(100); +*/ + + priv->pshare->mp_ctx_count = 0; + priv->pshare->mp_ctx_pkt = 0; + + if (OPMODE & WIFI_MP_CTX_PACKET) { + if (!(OPMODE & WIFI_MP_CTX_BACKGROUND)) + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_PACKET); + } else { + if (is_CCK_rate(priv->pshare->mp_datarate)) { + if (OPMODE & WIFI_MP_CTX_CCK_CS) { + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_CCK_CS); + mpt_ProSetCarrierSupp(priv, FALSE); + } else { + mpt_StopCckCoNtTx(priv); + } + } else { + mpt_StopOfdmContTx(priv); + if (OPMODE & WIFI_MP_CTX_OFDM_HW) + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_OFDM_HW); + if (OPMODE & WIFI_MP_CTX_ST) { + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_ST); + + if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R)) { + // eRFPath = RF90_PATH_C; + eRFPath = RF92CD_PATH_A; + } else if (get_rf_mimo_mode(priv) == MIMO_2T2R) { + switch (priv->pshare->mp_antenna_tx) { + case ANTENNA_B: + eRFPath = RF92CD_PATH_B; + break; + case ANTENNA_A: + default: + eRFPath = RF92CD_PATH_A; + break; + } + } + // Stop Single Tone. +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812() || CHECKICIS8881A()) { + PHY_SetBBReg(priv, 0x808, BIT(28), 0x1); + PHY_SetBBReg(priv, 0x808, BIT(29), 0x1); + + PHY_SetRFReg(priv, eRFPath, LNA_Low_Gain_3, BIT(1), 0); + delay_us(100); + PHY_SetRFReg(priv, eRFPath, 0x00, bRFRegOffsetMask, 0x30000); // PAD all on. + delay_us(100); + + if (eRFPath == RF92CD_PATH_A) { + PHY_SetBBReg(priv, 0xc00, BIT(1)|BIT(0), 0x3); + RTL_W32(0xcb0, priv->pshare->RegCB0); + PHY_SetBBReg(priv, 0xcb4, BIT(21), 0); +#if defined(CONFIG_RTL_8812_SUPPORT) + PHY_SetBBReg(priv, 0xcb4, BIT(24), 0); +#elif defined(CONFIG_WLAN_HAL_8881A) + PHY_SetBBReg(priv, 0xcb4, BIT(23), 0); +#endif + } else { + PHY_SetBBReg(priv, 0xe00, BIT(1)|BIT(0), 0x3); + RTL_W32(0xeb0, priv->pshare->RegEB0); + PHY_SetBBReg(priv, 0xeb4, BIT(21), 0); +#if defined(CONFIG_RTL_8812_SUPPORT) + PHY_SetBBReg(priv, 0xeb4, BIT(24), 0); +#elif defined(CONFIG_WLAN_HAL_8881A) + PHY_SetBBReg(priv, 0xeb4, BIT(23), 0); +#endif + } + } else +#endif + { +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv)==VERSION_8192E) { + PHY_SetRFReg(priv, eRFPath, LNA_Low_Gain_3, BIT(1), 0); + } +#ifdef HIGH_POWER_EXT_PA + if(priv->pshare->rf_ft_var.use_ext_pa){ + PHY_SetBBReg(priv, 0x4c, BIT(23), 0x0); + PHY_SetBBReg(priv, 0x4c, BIT(24), 0x0); + PHY_SetBBReg(priv, 0x4c, BIT(25), 0x0); + PHY_SetBBReg(priv, 0x4c, BIT(26), 0x0); + PHY_SetBBReg(priv, 0x4c, BIT(27), 0x0); + + PHY_SetBBReg(priv, 0x64, BIT(2), 0X0); + PHY_SetBBReg(priv, 0x64, BIT(3), 0X0); + PHY_SetBBReg(priv, 0x64, BIT(4), 0X0); + PHY_SetBBReg(priv, 0x64, BIT(8), 0X0); + } +#endif +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E +#ifdef HIGH_POWER_EXT_PA + && !priv->pshare->rf_ft_var.use_ext_pa +#endif + ){ + PHY_SetRFReg(priv, eRFPath, LNA_Low_Gain_3, BIT(1) ,0x0); + } +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT // single tone + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_5G){ + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn, 0x1); + PHY_SetBBReg(priv, 0x860, bMaskDWord, temp_860); + PHY_SetBBReg(priv, 0x864, bMaskDWord, temp_864); + PHY_SetBBReg(priv, 0x870, bMaskDWord, temp_870); + PHY_SetRFReg(priv, eRFPath, 0x41, BIT(19), 0); + } else +#endif + { + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, 0x1); + PHY_SetBBReg(priv, rFPGA0_RFMOD, bOFDMEn, 0x1); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x21, bMask20Bits, 0x54000); + } + delay_us(100); + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, 0x30000); // PAD all on. + delay_us(100); + +#ifdef HIGH_POWER_EXT_PA + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)){ + if(priv->pshare->rf_ft_var.use_ext_pa) { + PHY_SetBBReg(priv, 0x870, BIT(10), 0x0); + PHY_SetBBReg(priv, 0x870, BIT(26), 0x0); + } + } +#endif + } + } + + if (OPMODE & WIFI_MP_CTX_SCR) { + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_SCR); + + //Turn off all test modes. +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812() || CHECKICIS8881A()) { + PHY_SetBBReg(priv, 0x914, BIT(16), bDisable); // continue tx + PHY_SetBBReg(priv, 0x914, BIT(17), bDisable); // single carrier tx + PHY_SetBBReg(priv, 0x914, BIT(18), bDisable); // single tone tx + PHY_SetBBReg(priv, 0x914, 0xffff, 0); + } else +#endif + { + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMContinueTx, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + PHY_SetBBReg(priv, rOFDM1_LSTF, bOFDMDisPwsavTx, bDisable); + + PHY_SetBBReg(priv, rOFDM1_TRxMesaure1, 0xfff, 0); + } + //Delay 10 ms + delay_ms(10); + //BB Reset +/* + PHY_SetBBReg(priv, rPMAC_Reset, bBBResetB, 0x0); + PHY_SetBBReg(priv, rPMAC_Reset, bBBResetB, 0x1); +*/ + } + } + + PHY_SetBBReg(priv, rFPGA0_XA_HSSIParameter1, bContTxHSSI, 0); + } + + if (OPMODE & WIFI_MP_CTX_BACKGROUND) { + + printk("Stop continuous TX\n"); + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + OPMODE_VAL(OPMODE | WIFI_MP_CTX_BACKGROUND_STOPPING); + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_BACKGROUND_PENDING); + RESTORE_INT(flags); + SMP_UNLOCK(flags); + +#if defined(CONFIG_PCI_HCI) + while (priv->pshare->skb_head != priv->pshare->skb_tail) { + DEBUG_INFO("[%s %d] skb_head/skb_tail=%d/%d, head/tail=%d/%d\n", + __FUNCTION__, __LINE__, priv->pshare->skb_head, priv->pshare->skb_tail, + get_txhead(phw, BE_QUEUE), get_txtail(phw, BE_QUEUE)); + + rtl8192cd_tx_dsr((unsigned long)priv); + delay_us(50); + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + while (priv->pshare->skb_head != priv->pshare->skb_tail) { + DEBUG_INFO("[%s %d] skb_head/skb_tail=%d/%d\n", + __FUNCTION__, __LINE__, priv->pshare->skb_head, priv->pshare->skb_tail); + msleep(50); + } +#endif + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + OPMODE_VAL(OPMODE & ~(WIFI_MP_CTX_BACKGROUND | WIFI_MP_CTX_BACKGROUND_PENDING | WIFI_MP_CTX_PACKET | + WIFI_MP_CTX_ST | WIFI_MP_CTX_SCR | WIFI_MP_CTX_CCK_CS |WIFI_MP_CTX_OFDM_HW | + WIFI_MP_CTX_BACKGROUND_STOPPING)); + RESTORE_INT(flags); + SMP_UNLOCK(flags); + + for (i=0; ipshare->skb_pool[i]->head); + kfree(priv->pshare->skb_pool_ptr); + } +} + + +int mp_query_stats(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char *val; + + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return 0; + } + + if (!(OPMODE & WIFI_MP_STATE)) + { + printk("Fail: not in MP mode\n"); + return 0; + } + + val = get_value_by_token((char *)data, "weight="); + if (val) { + priv->pshare->mp_rssi_weight = _atoi(val, 10); + if ((priv->pshare->mp_rssi_weight < 0) || (priv->pshare->mp_rssi_weight > 100)) { + printk("Waring! rssi_weight should be 0~100\n"); + priv->pshare->mp_rssi_weight = 5; + } + } + + val = get_value_by_token((char *)data, "rssi"); + if (val) { +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if (IS_OUTSRC_CHIP(priv)) +#endif + { + odm_FalseAlarmCounterStatistics(ODMPTR); + priv->pshare->mp_FA_cnt = ODMPTR->FalseAlmCnt.Cnt_all; + priv->pshare->mp_CCA_cnt = ODMPTR->FalseAlmCnt.Cnt_CCA_all; + } +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if (!IS_OUTSRC_CHIP(priv)) +#endif + { + FA_statistic(priv); + priv->pshare->mp_FA_cnt = priv->pshare->FA_total_cnt; + priv->pshare->mp_CCA_cnt = priv->pshare->CCA_total_cnt; + } +#endif + sprintf(data, "%d%% rx %s%d (ss %d %d )(FA %d)(CCA %d)\n", + priv->pshare->mp_rssi, + ((priv->pshare->mp_rx_rate&0x80) && (priv->pshare->mp_rx_rate< 0x90))? "MCS" : "", + ((priv->pshare->mp_rx_rate&0x80)? priv->pshare->mp_rx_rate&0x7f : priv->pshare->mp_rx_rate/2), + priv->pshare->mp_rf_info.mimorssi[0], priv->pshare->mp_rf_info.mimorssi[1], + priv->pshare->mp_FA_cnt, + priv->pshare->mp_CCA_cnt); + return strlen(data)+1; + } + + + sprintf(data, "Tx OK:%d, Tx Fail:%d, Rx OK:%lu, CRC error:%lu", + (int)(priv->net_stats.tx_packets-priv->net_stats.tx_errors), + (int)priv->net_stats.tx_errors, + priv->net_stats.rx_packets, priv->net_stats.rx_crc_errors); + return strlen(data)+1; +} + + +void mp_txpower_tracking(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char *val; + unsigned int target_ther = 0; + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return; + } + + val = get_value_by_token((char *)data, "stop"); + if (val) { + if (priv->pshare->mp_txpwr_tracking==FALSE) + return; + priv->pshare->mp_txpwr_tracking = FALSE; + printk("mp tx power tracking stop\n"); + return; + } + + val = get_value_by_token((char *)data, "ther="); + if (val) + target_ther = _atoi(val, 10); + else if (priv->pmib->dot11RFEntry.ther) + target_ther = priv->pmib->dot11RFEntry.ther; + target_ther &= 0xff; + + if (!target_ther) { + printk("Fail: tx power tracking has no target thermal value\n"); + return; + } + + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8192C || GET_CHIP_VER(priv) == VERSION_8188C || GET_CHIP_VER(priv) == VERSION_8192D) { + if ((target_ther < 0x07) || (target_ther > 0x1d)) { + DEBUG_ERR("TPT: unreasonable target ther %d, disable tpt\n", target_ther); + target_ther = 0; + } + } else +#endif + { + if ((target_ther < 0x07) || (target_ther > 0x32)) { + DEBUG_ERR("TPT: unreasonable target ther %d, disable tpt\n", target_ther); + target_ther = 0; + } + } + + if(priv->pmib->dot11RFEntry.ther && priv->pshare->ThermalValue) + priv->pshare->ThermalValue += (target_ther - priv->pmib->dot11RFEntry.ther ); + + priv->pmib->dot11RFEntry.ther = target_ther; + + priv->pshare->mp_txpwr_tracking = TRUE; + printk("mp tx power tracking start, target value=%d\n", target_ther); +} + + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) +void mp_dig(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char *val; + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return; + } + + if ((GET_CHIP_VER(priv) != VERSION_8192D) && (GET_CHIP_VER(priv) != VERSION_8812E)) { + printk("Fail: %s() only support 92D/8812 !\n", __FUNCTION__); + return; + } + + + val = get_value_by_token((char *)data, "on"); + if (val) { + if (priv->pshare->mp_dig_on +#ifdef CONFIG_RTL_92D_SUPPORT + || (GET_CHIP_VER(priv)==VERSION_8192D && timer_pending(&priv->pshare->MP_DIGTimer)) +#endif + ) + return; + + priv->pshare->mp_dig_on = 1; + + priv->pshare->mp_dig_reg_backup = RTL_R8(0xc50); + printk("mp dig on! backup IG: 0x%x\n", priv->pshare->mp_dig_reg_backup); + +#ifdef USE_OUT_SRC + ODM_MPT_DIG(ODMPTR); +#else + MP_DIG_process(priv); +#endif + } + + val = get_value_by_token((char *)data, "off"); + if (val) { + if (priv->pshare->mp_dig_on==0) + return; + + priv->pshare->mp_dig_on = 0; +#ifdef USE_OUT_SRC + ODM_CancelTimer(ODMPTR, &ODMPTR->MPT_DIGTimer); +#else +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef __ECOS + del_timer_sync(&priv->pshare->MP_DIGTimer); +#else + del_timer(&priv->pshare->MP_DIGTimer); +#endif +#endif +#endif + if (GET_CHIP_VER(priv) == VERSION_8812E) { + RTL_W8(0xc50, priv->pshare->mp_dig_reg_backup); + RTL_W8(0xe50, priv->pshare->mp_dig_reg_backup); + } else if (GET_CHIP_VER(priv) == VERSION_8192D) { + RTL_W8(0xc50, priv->pshare->mp_dig_reg_backup); + RTL_W8(0xc58, priv->pshare->mp_dig_reg_backup); + } + + printk("mp dig off\n"); + return; + } +} + +#endif + +int mp_query_tssi(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned int i=0, j=0, val32, tssi, tssi_total=0, tssi_reg, reg_backup; + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return 0; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return 0; + } + + if (priv->pshare->mp_txpwr_tracking) { + priv->pshare->mp_txpwr_tracking = FALSE; + sprintf(data, "8651"); + return strlen(data)+1; + } + + if (is_CCK_rate(priv->pshare->mp_datarate)) { + reg_backup = RTL_R32(rFPGA0_AnalogParameter4); + RTL_W32(rFPGA0_AnalogParameter4, (reg_backup & 0xfffff0ff)); + + while (i < 5) { + j++; + delay_ms(10); + val32 = PHY_QueryBBReg(priv, rCCK0_TRSSIReport, bMaskByte0); + tssi = val32 & 0x7f; + if (tssi > 10) { + tssi_total += tssi; + i++; + } + if (j > 20) + break; + } + + RTL_W32(rFPGA0_AnalogParameter4, reg_backup); + + if (i > 0) + tssi = tssi_total / i; + else + tssi = 0; + } else { +// if (priv->pshare->mp_antenna_tx == ANTENNA_A) + tssi_reg = rFPGA0_XAB_RFInterfaceRB; +// else +// tssi_reg = rFPGA0_XCD_RFInterfaceRB; + + reg_backup = PHY_QueryBBReg(priv, rOFDM0_TRxPathEnable, 0x0000000f); + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, 0x0000000f, 0x0000000f); + + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(25), 1); + + while (i < 5) { + delay_ms(5); + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(25), 0); + val32 = PHY_QueryBBReg(priv, tssi_reg, bMaskDWord); + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(25), 1); + tssi = ((val32 & 0x04000000) >> 20) | + ((val32 & 0x00600000) >> 17) | + ((val32 & 0x00000c00) >> 8) | + ((val32 & 0x00000060) >> 5); + if (tssi) { + tssi_total += tssi; + i++; + } + } + + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, 0x0000000f, reg_backup); + + tssi = tssi_total / 5; + } + + sprintf(data, "%d", tssi); + return strlen(data)+1; +} + + +int mp_query_ther(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned int ther=0; + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return 0; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return 0; + } + + // enable power and trigger +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if ((GET_CHIP_VER(priv)==VERSION_8812E) || (GET_CHIP_VER(priv)==VERSION_8881A)) + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x42, BIT(17), 0x1); + else +#endif +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv)==VERSION_8188E) || (GET_CHIP_VER(priv)==VERSION_8192E)) + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x42, (BIT(17) | BIT(16)), 0x03); + else +#endif + if (CHECKICIS92D()) + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_T_METER_92D, bMask20Bits, 0x30000); + else + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x24, bMask20Bits, 0x60); + + // delay for 1 second + delay_ms(1000); + + // query rf reg 0x24[4:0], for thermal meter value +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if ((GET_CHIP_VER(priv)==VERSION_8812E) || (GET_CHIP_VER(priv)==VERSION_8881A)) + ther = PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x42, 0xfc00, 1); + else +#endif +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv)==VERSION_8188E) || (GET_CHIP_VER(priv)==VERSION_8192E)) + ther = PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x42, 0xfc00, 1); + else +#endif + if (CHECKICIS92D()) + ther = PHY_QueryRFReg(priv, RF92CD_PATH_A, RF_T_METER_92D, 0xf800, 1); + else + ther = PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x24, bMask20Bits, 1) & 0x01f; + + + sprintf(data, "%d", ther); + return strlen(data)+1; +} + +#ifdef MP_PSD_SUPPORT +int mp_query_psd(struct rtl8192cd_priv *priv, unsigned char * data) +{ + char *val; + unsigned int i, psd_pts=0, psd_start=0, psd_stop=0; + int psd_data=0; +#ifdef __ECOS + char tmp[16]; +#endif + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return 0; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return 0; + } + + if (strlen(data) == 0) { //default value + psd_pts = 128; + psd_start = 64; + psd_stop = 128; + + } + else + { + val = get_value_by_token((char *)data, "pts="); + if (val) { + psd_pts = _atoi(val,10); + }else { + psd_pts = 128; + } + + val = get_value_by_token((char *)data, "start="); + if (val) { + psd_start=_atoi(val,10); + }else { + psd_start = 64; + } + + val = get_value_by_token((char *)data, "stop="); + if (val) { + psd_stop=_atoi(val,10); + }else { + psd_stop = psd_pts; + } + } + + data[0] = '\0'; + + i = psd_start; + while( i < psd_stop) { + + if( i>= psd_pts) { + psd_data = GetPSDData(priv,(i-psd_pts)); + } + else { + psd_data = GetPSDData(priv,i); + } +#ifdef __ECOS + sprintf(tmp, "%x ", psd_data); + strcat(data, tmp); +#else + sprintf(data, "%s%x ",data, psd_data); +#endif + i++; + } + + panic_printk("\"read psd = %s\"\n", data); + panic_printk("Length is %d\n",strlen(data)); +#ifndef __ECOS + printk("read psd = %s\n", data); + printk("Length is %d\n",strlen(data)); +#endif + delay_ms(500); + + return strlen(data)+1; +} +#endif + +int mp_get_txpwr(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned int pwrA=0,pwrB=0; + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return 0; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return 0; + } + + switch (priv->pshare->mp_datarate){ + case 2: + pwrA = PHY_QueryBBReg(priv, 0xe08, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0x838, bMaskByte1); + break; + case 4: + pwrA = PHY_QueryBBReg(priv, 0x86c, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0x838, bMaskByte2); + break; + case 11: + pwrA = PHY_QueryBBReg(priv, 0x86c, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0x838, bMaskByte3); + break; + case 22: + pwrA = PHY_QueryBBReg(priv, 0x86c, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0x86c, bMaskByte0); + break; + case 12: + pwrA = PHY_QueryBBReg(priv, 0xe00, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0x830, bMaskByte0); + break; + case 18: + pwrA = PHY_QueryBBReg(priv, 0xe00, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0x830, bMaskByte1); + break; + case 24: + pwrA = PHY_QueryBBReg(priv, 0xe00, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0x830, bMaskByte2); + break; + case 36: + pwrA = PHY_QueryBBReg(priv, 0xe00, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0x830, bMaskByte3); + break; + case 48: + pwrA = PHY_QueryBBReg(priv, 0xe04, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0x834, bMaskByte0); + break; + case 72: + pwrA = PHY_QueryBBReg(priv, 0xe04, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0x834, bMaskByte1); + break; + case 96: + pwrA = PHY_QueryBBReg(priv, 0xe04, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0x834, bMaskByte2); + break; + case 108: + pwrA = PHY_QueryBBReg(priv, 0xe04, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0x834, bMaskByte3); + break; + case 128: + pwrA = PHY_QueryBBReg(priv, 0xe10, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0x83c, bMaskByte0); + break; + case 129: + pwrA = PHY_QueryBBReg(priv, 0xe10, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0x83c, bMaskByte1); + break; + case 130: + pwrA = PHY_QueryBBReg(priv, 0xe10, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0x83c, bMaskByte2); + break; + case 131: + pwrA = PHY_QueryBBReg(priv, 0xe10, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0x83c, bMaskByte3); + break; + case 132: + pwrA = PHY_QueryBBReg(priv, 0xe14, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0x848, bMaskByte0); + break; + case 133: + pwrA = PHY_QueryBBReg(priv, 0xe14, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0x848, bMaskByte1); + break; + case 134: + pwrA = PHY_QueryBBReg(priv, 0xe14, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0x848, bMaskByte2); + break; + case 135: + pwrA = PHY_QueryBBReg(priv, 0xe14, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0x848, bMaskByte3); + break; + case 136: + pwrA = PHY_QueryBBReg(priv, 0xe18, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0x84c, bMaskByte0); + break; + case 137: + pwrA = PHY_QueryBBReg(priv, 0xe18, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0x84c, bMaskByte1); + break; + case 138: + pwrA = PHY_QueryBBReg(priv, 0xe18, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0x84c, bMaskByte2); + break; + case 139: + pwrA = PHY_QueryBBReg(priv, 0xe18, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0x84c, bMaskByte3); + break; + case 140: + pwrA = PHY_QueryBBReg(priv, 0xe1c, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0x868, bMaskByte0); + break; + case 141: + pwrA = PHY_QueryBBReg(priv, 0xe1c, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0x868, bMaskByte1); + break; + case 142: + pwrA = PHY_QueryBBReg(priv, 0xe1c, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0x868, bMaskByte2); + break; + case 143: + pwrA = PHY_QueryBBReg(priv, 0xe1c, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0x868, bMaskByte3); + break; +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + case 144: + pwrA = PHY_QueryBBReg(priv, 0xc3c, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0xe3c, bMaskByte0); + break; + case 145: + pwrA = PHY_QueryBBReg(priv, 0xc3c, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0xe3c, bMaskByte1); + break; + case 146: + pwrA = PHY_QueryBBReg(priv, 0xc3c, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0xe3c, bMaskByte2); + break; + case 147: + pwrA = PHY_QueryBBReg(priv, 0xc3c, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0xe3c, bMaskByte3); + break; + case 148: + pwrA = PHY_QueryBBReg(priv, 0xc40, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0xe40, bMaskByte0); + break; + case 149: + pwrA = PHY_QueryBBReg(priv, 0xc40, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0xe40, bMaskByte1); + break; + case 150: + pwrA = PHY_QueryBBReg(priv, 0xc40, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0xe40, bMaskByte2); + break; + case 151: + pwrA = PHY_QueryBBReg(priv, 0xc40, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0xe40, bMaskByte3); + break; + case 152: + pwrA = PHY_QueryBBReg(priv, 0xc44, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0xe44, bMaskByte0); + break; + case 153: + pwrA = PHY_QueryBBReg(priv, 0xc44, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0xe44, bMaskByte1); + break; + case 154: + pwrA = PHY_QueryBBReg(priv, 0xc44, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0xe44, bMaskByte2); + break; + case 155: + pwrA = PHY_QueryBBReg(priv, 0xc44, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0xe44, bMaskByte3); + break; + case 156: + pwrA = PHY_QueryBBReg(priv, 0xc48, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0xe48, bMaskByte0); + break; + case 157: + pwrA = PHY_QueryBBReg(priv, 0xc48, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0xe48, bMaskByte1); + break; + case 158: + pwrA = PHY_QueryBBReg(priv, 0xc48, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0xe48, bMaskByte2); + break; + case 159: + pwrA = PHY_QueryBBReg(priv, 0xc48, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0xe48, bMaskByte3); + break; + case 160: + pwrA = PHY_QueryBBReg(priv, 0xc4c, bMaskByte0); + pwrB = PHY_QueryBBReg(priv, 0xe4c, bMaskByte0); + break; + case 161: + pwrA = PHY_QueryBBReg(priv, 0xc4c, bMaskByte1); + pwrB = PHY_QueryBBReg(priv, 0xe4c, bMaskByte1); + break; + case 162: + pwrA = PHY_QueryBBReg(priv, 0xc4c, bMaskByte2); + pwrB = PHY_QueryBBReg(priv, 0xe4c, bMaskByte2); + break; + case 163: + pwrA = PHY_QueryBBReg(priv, 0xc4c, bMaskByte3); + pwrB = PHY_QueryBBReg(priv, 0xe4c, bMaskByte3); + break; +#endif + } + + sprintf(data, "%d %d", pwrA, pwrB); + return strlen(data)+1; +} + + +#ifdef B2B_TEST +/* Do checksum and verification for configuration data */ +static unsigned char byte_checksum(unsigned char *data, int len) +{ + int i; + unsigned char sum=0; + + for (i=0; istate = WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE; + memcpy(pstat->bssrateset, AP_BSSRATE, AP_BSSRATE_LEN); + pstat->bssratelen = AP_BSSRATE_LEN; + pstat->expire_to = 30000; + asoc_list_add(priv, pstat); + cnt_assoc_num(priv, pstat, INCREASE, (char *)__FUNCTION__); + if (QOS_ENABLE) + pstat->QosEnabled = 1; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + pstat->ht_cap_len = priv->ht_cap_len; + memcpy(&pstat->ht_cap_buf, &priv->ht_cap_buf, priv->ht_cap_len); + } + pstat->current_tx_rate = priv->pshare->mp_datarate; + update_fwtbl_asoclst(priv, pstat); +// add_update_RATid(priv, pstat); + } + } +} + + +/* + * tx pakcet. + * command: "iwpriv wlanx mp_tx,da=xxx,time=n,count=n,len=n,retry=n,tofr=n,wait=n,delay=n,err=n" + * default: da=ffffffffffff, time=0,count=1000, len=1500, retry=6, tofr=0, wait=0, delay=0(ms), err=1 + * note: if time is set, it will take time (in sec) rather count. + * if "time=-1", tx will continue tx until ESC. If "err=1", display statistics when tx err. + */ +int mp_tx(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned int orgTCR = RTL_R32(TCR); + unsigned char increaseIFS=0; // set to 1 to increase the inter frame spacing while in PER test + unsigned char pbuf[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int count=1000, payloadlen=1500, retry=6, tofr=0, wait=0, delay=0, time=0; + int err=1; + struct sk_buff *skb; + struct wlan_ethhdr_t *pethhdr; + int len, i, q_num, ret, resent; + unsigned char pattern=0xab; + char *val; + struct rtl8192cd_hw *phw = GET_HW(priv); + static int last_tx_err; + unsigned long end_time=0; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return 0; + } + + if (!(OPMODE & WIFI_MP_STATE)) + { + printk("Fail: not in MP mode\n"); + return 0; + } + + // get da + val = get_value_by_token((char *)data, "da="); + if (val) { + ret = get_array_val(pbuf, val, 12); + if (ret != 6) { + printk("Error da format\n"); + return 0; + } + } + + // get time + val = get_value_by_token((char *)data, "time="); + if (val) { + if (!memcmp(val, "-1", 2)) + time = -1; + else { + time = _atoi(val, 10); + time = time*HZ; // in 10ms + } + } + + // get count + val = get_value_by_token((char *)data, "count="); + if (val) { + count = _atoi(val, 10); + } + + // get payload len + val = get_value_by_token((char *)data, "len="); + if (val) { + payloadlen = _atoi(val, 10); + if (payloadlen < 20) { + printk("len should be greater than 20!\n"); + return 0; + } + } + + // get retry number + val = get_value_by_token((char *)data, "retry="); + if (val) { + retry = _atoi(val, 10); + } + + // get tofr + val = get_value_by_token((char *)data, "tofr="); + if (val) { + tofr = _atoi(val, 10); + } + + // get wait + val = get_value_by_token((char *)data, "wait="); + if (val) { + wait = _atoi(val, 10); + } + + // get err + val = get_value_by_token((char *)data, "err="); + if (val) { + err = _atoi(val, 10); + } + + len = payloadlen + WLAN_ETHHDR_LEN; + q_num = BE_QUEUE; + + if (time) + printk("Start TX DA=%02x%02x%02x%02x%02x%02x len=%d tofr=%d retry=%d wait=%s time=%ds", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], + payloadlen, tofr, retry, (wait ? "yes" : "no"), ((time > 0) ? time/100 : -1)); + else + printk("Start TX DA=%02x%02x%02x%02x%02x%02x count=%d len=%d tofr=%d retry=%d wait=%s", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], + count, payloadlen, tofr, retry, (wait ? "yes" : "no")); + +#if defined(USE_RTL8186_SDK) + printk(", press any key to escape.\n"); +#else + printk("\n"); +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + priv->pshare->InterruptMask |= HIMR_88E_BEDOK; + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask); + } else +#endif + { + RTL_W32(HIMR, RTL_R32(HIMR) | HIMR_BEDOK); + } +#endif // CONFIG_PCI_HCI + +// RTL_W32(_RCR_, _NO_ERLYRX_); + RTL_W32(RCR, RTL_R32(RCR) & ~(RCR_AB | RCR_AM | RCR_APM | RCR_AAP)); + + if (increaseIFS) { +// RTL_W32(_TCR_, RTL_R32(_TCR_) | _DISCW_); + RTL_W16(TX_PTCL_CTRL, RTL_R16(TX_PTCL_CTRL) | DIS_CW); + } + + memset(&priv->net_stats, 0, sizeof(struct net_device_stats)); + priv->ext_stats.tx_retrys=0; + last_tx_err = 0; + + if (time > 0) { + end_time = jiffies + time; + } + + i = 0; + resent = 0; + +#if defined(USE_RTL8186_SDK) + DISABLE_UART0_INT(); +#endif + + mp_init_sta(priv, &pbuf[0]); + + while (1) + { +#if defined(USE_RTL8186_SDK) + if ( IS_KEYBRD_HIT()) + break; +#endif + + if (time) { + if (time != -1) { + if (jiffies > end_time) + break; + } + } + else { + if (!resent && i >= count) + break; + } + if (!resent) + i++; + + skb = dev_alloc_skb(len); + + if (skb != NULL) + { + DECLARE_TXINSN(txinsn); + + skb->dev = priv->dev; + skb_put(skb, len); + + pethhdr = (struct wlan_ethhdr_t *)(skb->data); + memcpy((void *)pethhdr->daddr, pbuf, MACADDRLEN); + memcpy((void *)pethhdr->saddr, BSSID, MACADDRLEN); + pethhdr->type = htons(payloadlen); + + // construct tx patten + memset(skb->data+WLAN_ETHHDR_LEN, pattern, payloadlen); + + memcpy(skb->data+WLAN_ETHHDR_LEN, MP_PACKET_HEADER, MP_PACKET_HEADER_LEN); // header + memcpy(skb->data+WLAN_ETHHDR_LEN+12, &i, 4); // packet sequence + skb->data[len-1] = byte_checksum(skb->data+WLAN_ETHHDR_LEN, payloadlen-1); // checksum + + txinsn.q_num = q_num; //using low queue for data queue + txinsn.fr_type = _SKB_FRAME_TYPE_; + txinsn.pframe = skb; + txinsn.tx_rate = txinsn.lowest_tx_rate = priv->pshare->mp_datarate; + txinsn.fixed_rate = 1; + txinsn.retry = retry; + txinsn.phdr = get_wlanllchdr_from_poll(priv); +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + if (NULL == txinsn.phdr) + goto congestion_handle; + skb->cb[1] = 0; + +#ifdef MCAST2UI_REFINE + memcpy(&skb->cb[10], skb->data, 6); +#endif + + memset((void *)txinsn.phdr, 0, sizeof(struct wlanllc_hdr)); + + if (tofr & 2) + SetToDs(txinsn.phdr); + if (tofr & 1) + SetFrDs(txinsn.phdr); + + SetFrameType(txinsn.phdr, WIFI_DATA); + + if (wait) { + while (1) { + volatile unsigned int head, tail; + head = get_txhead(phw, BE_QUEUE); + tail = get_txtail(phw, BE_QUEUE); + if (head == tail) + break; + delay_ms(1); + } + } + + if(rtl8192cd_firetx(priv, &txinsn) == CONGESTED) + { +congestion_handle: + if (txinsn.phdr) + release_wlanllchdr_to_poll(priv, txinsn.phdr); + if (skb) + rtl_kfree_skb(priv, skb, _SKB_TX_); + + //printk("CONGESTED : busy waiting...\n"); + delay_ms(1); + resent = 1; + +#ifdef CONFIG_PCI_HCI + SAVE_INT_AND_CLI(flags); +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + RESTORE_INT(flags); +#endif // CONFIG_PCI_HCI + } + else { +#ifdef CONFIG_PCI_HCI + SAVE_INT_AND_CLI(flags); +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + RESTORE_INT(flags); +#endif // CONFIG_PCI_HCI + + if (err && ((int)priv->net_stats.tx_errors) != last_tx_err) { // err happen + printk("\tout=%d\tfail=%d\n", (int)priv->net_stats.tx_packets, + (int)priv->net_stats.tx_errors); + last_tx_err = (int)priv->net_stats.tx_errors; + } + else { + if ( (i%10000) == 0 ) + printk("Tx status: ok=%d\tfail=%d\tretry=%ld\n", (int)(priv->net_stats.tx_packets-priv->net_stats.tx_errors), + (int)priv->net_stats.tx_errors, priv->ext_stats.tx_retrys); + } + resent = 0; + } + if (delay) + delay_ms(delay); + } + else + { + printk("Can't allocate sk_buff\n"); + delay_ms(1); + resent = 1; + +#ifdef CONFIG_PCI_HCI + SAVE_INT_AND_CLI(flags); +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + RESTORE_INT(flags); +#endif // CONFIG_PCI_HCI + } + } + +#if defined(USE_RTL8186_SDK) + RESTORE_UART0_INT(); +#endif + +#ifdef CONFIG_PCI_HCI + // wait till all tx is done + printk("\nwaiting tx is finished..."); + i = 0; + while (1) { + volatile unsigned int head, tail; + head = get_txhead(phw, BE_QUEUE); + tail = get_txtail(phw, BE_QUEUE); + if (head == tail) + break; + + SAVE_INT_AND_CLI(flags); +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + RESTORE_INT(flags); + + delay_ms(1); + + if (i++ >10000) + break; + } + printk("done.\n"); +#endif // CONFIG_PCI_HCI + + RTL_W32(TCR, orgTCR); + + sprintf(data, "Tx result: ok=%d,fail=%d", (int)(priv->net_stats.tx_packets-priv->net_stats.tx_errors), + (int)priv->net_stats.tx_errors); + return strlen(data)+1; +} + + +/* + * validate rx packet. rx packet format: + * |wlan-header(24 byte)|MP_PACKET_HEADER (12 byte)|sequence(4 bytes)|....|checksum(1 byte)| + * + */ +void mp_validate_rx_packet(struct rtl8192cd_priv *priv, unsigned char *data, int len) +{ + int tofr = get_tofr_ds(data); + unsigned int type=GetFrameType(data); + int header_size = 24; + unsigned long sequence; + unsigned short fr_seq; + + if (!priv->pshare->mp_rx_waiting) + return; + + if (type != WIFI_DATA) + return; + + fr_seq = GetTupleCache(data); + if (GetRetry(data) && fr_seq == priv->pshare->mp_cached_seq) { + priv->pshare->mp_rx_dup++; + return; + } + + if (tofr == 3) + header_size = 30; + + if (len < (header_size+20) ) + return; + + // see if test header matched + if (memcmp(&data[header_size], MP_PACKET_HEADER, MP_PACKET_HEADER_LEN)) + return; + + priv->pshare->mp_cached_seq = fr_seq; + + memcpy(&sequence, &data[header_size+MP_PACKET_HEADER_LEN], 4); + + if (!is_byte_checksum_ok(&data[header_size], len-header_size)) { +#if 0 + printk("mp_rx: checksum error!\n"); +#endif + printk("mp_brx: checksum error!\n"); + } + else { + if (sequence <= priv->pshare->mp_rx_sequence) { +#if 0 + printk("mp_rx: invalid sequece (%ld) <= current (%ld)!\n", + sequence, priv->pshare->mp_rx_sequence); +#endif + printk("mp_brx: invalid sequece (%ld) <= current (%ld)!\n", + sequence, priv->pshare->mp_rx_sequence); + } + else { + if (sequence > (priv->pshare->mp_rx_sequence+1)) + priv->pshare->mp_rx_lost_packet += (sequence-priv->pshare->mp_rx_sequence-1); + priv->pshare->mp_rx_sequence = sequence; + priv->pshare->mp_rx_ok++; + } + } +} + + +#if 0 +/* + * Rx test packet. + * command: "iwpriv wlanx mp_rx [ra=xxxxxx,quiet=t,interval=n]" + * - ra: rx mac. defulat is burn-in mac + * - quiet_time: quit rx if no rx packet during quiet_time. default is 5s + * - interval: report rx statistics periodically in sec. default is 0 (no report) + */ +static void mp_rx(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char *val; + unsigned char pbuf[6]; + int quiet_time=5, interval_time=0, quiet_period=0, interval_period=0, ret; + unsigned int o_rx_ok, o_rx_lost_packet, mac_changed=0; + unsigned long reg, counter=0; + + if (!(OPMODE & WIFI_MP_STATE)) + { + printk("Fail: not in MP mode\n"); + return; + } + + // get ra + val = get_value_by_token((char *)data, "ra="); + if (val) { + ret =0; + if (strlen(val) >=12) + ret = get_array_val(pbuf, val, 12); + if (ret != 6) { + printk("Error mac format\n"); + return; + } + printk("set ra to %02X:%02X:%02X:%02X:%02X:%02X\n", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5]); + + memcpy(®, pbuf, 4); + RTL_W32(_IDR0_, (cpu_to_le32(reg))); + + memcpy(®, pbuf+4, 4); + RTL_W32(_IDR0_ + 4, (cpu_to_le32(reg))); + mac_changed = 1; + } + + // get quiet time + val = get_value_by_token((char *)data, "quiet="); + if (val) + quiet_time = _atoi(val, 10); + + // get interval time + val = get_value_by_token((char *)data, "interval="); + if (val) + interval_time = _atoi(val, 10); + + RTL_W32(_RCR_, _ENMARP_ | _APWRMGT_ | _AMF_ | _ADF_ | _NO_ERLYRX_ | + _RX_DMA64_ | _ACRC32_ | _AB_ | _AM_ | _APM_ | _AAP_); + + priv->pshare->mp_cached_seq = 0; + priv->pshare->mp_rx_ok = 0; + priv->pshare->mp_rx_sequence = 0; + priv->pshare->mp_rx_lost_packet = 0; + priv->pshare->mp_rx_dup = 0; + + printk("Waiting for rx packet, quit if no packet in %d sec", quiet_time); + +#if (defined(CONFIG_RTL_EB8186) && defined(__KERNEL__)) || defined(CONFIG_RTL865X) + printk(", or press any key to escape.\n"); + DISABLE_UART0_INT(); +#else + printk(".\n"); +#endif + + priv->pshare->mp_rx_waiting = 1; + + while (1) { + // save old counter + o_rx_ok = priv->pshare->mp_rx_ok; + o_rx_lost_packet = priv->pshare->mp_rx_lost_packet; + +#if (defined(CONFIG_RTL_EB8186) && defined(__KERNEL__)) || defined(CONFIG_RTL865X) + if ( IS_KEYBRD_HIT()) + break; +#endif + + delay_ms(1000); + + if (interval_time && ++interval_period == interval_time) { + printk("\tok=%ld\tlost=%ld\n", priv->pshare->mp_rx_ok, priv->pshare->mp_rx_lost_packet); + interval_period=0; + } + else { + if ((priv->pshare->mp_rx_ok-counter) > 10000) { + printk("Rx status: ok=%ld\tlost=%ld, duplicate=%ld\n", priv->pshare->mp_rx_ok, priv->pshare->mp_rx_lost_packet, priv->pshare->mp_rx_dup); + counter += 10000; + } + } + + if (o_rx_ok == priv->pshare->mp_rx_ok && o_rx_lost_packet == priv->pshare->mp_rx_lost_packet) + quiet_period++; + else + quiet_period = 0; + + if (quiet_period >= quiet_time) + break; + } + +// printk("\nRx result: ok=%ld\tlost=%ld, duplicate=%ld\n\n", priv->pshare->mp_rx_ok, priv->pshare->mp_rx_lost_packet, priv->mp_rx_dup); + printk("\nRx reseult: ok=%ld\tlost=%ld\n\n", priv->pshare->mp_rx_ok, priv->pshare->mp_rx_lost_packet); + + priv->pshare->mp_rx_waiting = 0; + + if (mac_changed) { + memcpy(pbuf, priv->pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + + memcpy(®, pbuf, 4); + RTL_W32(_IDR0_, (cpu_to_le32(reg))); + + memcpy(®, pbuf+4, 4); + RTL_W32(_IDR0_ + 4, (cpu_to_le32(reg))); + } + +#if (defined(CONFIG_RTL_EB8186) && defined(__KERNEL__)) || defined(CONFIG_RTL865X) + RESTORE_UART0_INT(); +#endif + +} +#endif + + +/* + * Rx test packet. + * command: "iwpriv wlanx mp_brx start[,ra=xxxxxx]" + * - ra: rx mac. defulat is burn-in mac + * command: "iwpriv wlanx mp_brx stop" + * - stop rx immediately + */ +int mp_brx(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char *val; + unsigned char pbuf[6]; + int ret; + unsigned long reg; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return 0; + } + + if (!(OPMODE & WIFI_MP_STATE)) + { + printk("Fail: not in MP mode\n"); + return 0; + } + + SAVE_INT_AND_CLI(flags); + + if (!strcmp(data, "stop")) + goto stop_brx; + + // get start + val = get_value_by_token((char *)data, "start"); + if (val) { + // get ra if it exists + val = get_value_by_token((char *)data, "ra="); + if (val) { + ret =0; + if (strlen(val) >=12) + ret = get_array_val(pbuf, val, 12); + if (ret != 6) { + printk("Error mac format\n"); + RESTORE_INT(flags); + return 0; + } + printk("set ra to %02X:%02X:%02X:%02X:%02X:%02X\n", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5]); + + memcpy(®, pbuf, 4); + RTL_W32(MACID, (cpu_to_le32(reg))); + + memcpy(®, pbuf+4, 4); + RTL_W32(MACID + 4, (cpu_to_le32(reg))); + priv->pshare->mp_mac_changed = 1; + } + } + else { + RESTORE_INT(flags); + return 0; + } + + priv->pshare->mp_cached_seq = 0; + priv->pshare->mp_rx_ok = 0; + priv->pshare->mp_rx_sequence = 0; + priv->pshare->mp_rx_lost_packet = 0; + priv->pshare->mp_rx_dup = 0; + priv->pshare->mp_rx_waiting = 1; + + // record the start time of MP throughput test + priv->pshare->txrx_start_time = jiffies; + + OPMODE_VAL(OPMODE | WIFI_MP_RX); +// RTL_W32(RCR, _ENMARP_ | _APWRMGT_ | _AMF_ | _ADF_ | _NO_ERLYRX_ | +// _RX_DMA64_ | _ACRC32_ | _AB_ | _AM_ | _APM_); + RTL_W32(RCR, RCR_HTC_LOC_CTRL | RCR_AMF | RCR_ADF | RCR_ACRC32 | RCR_APWRMGT | RCR_AB | RCR_AM | RCR_APM); + + memset(&priv->net_stats, 0, sizeof(struct net_device_stats)); + memset(&priv->ext_stats, 0, sizeof(struct extra_stats)); + + RESTORE_INT(flags); + return 0; + +stop_brx: + OPMODE_VAL(OPMODE & ~WIFI_MP_RX); + +// RTL_W32(RCR, _ENMARP_ | _NO_ERLYRX_ | _RX_DMA64_); + RTL_W32(RCR, RCR_HTC_LOC_CTRL); + priv->pshare->mp_rx_waiting = 0; + + //record the elapsed time of MP throughput test + priv->pshare->txrx_elapsed_time = jiffies - priv->pshare->txrx_start_time; + + if (priv->pshare->mp_mac_changed) { + memcpy(pbuf, priv->pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + + memcpy(®, pbuf, 4); + RTL_W32(MACID, (cpu_to_le32(reg))); + + memcpy(®, pbuf+4, 4); + RTL_W32(MACID + 4, (cpu_to_le32(reg))); + } + priv->pshare->mp_mac_changed = 0; + + RESTORE_INT(flags); + + sprintf(data, "Rx reseult: ok=%ld,lost=%ld,elapsed time=%ld", + priv->pshare->mp_rx_ok, priv->pshare->mp_rx_lost_packet, priv->pshare->txrx_elapsed_time); + return strlen(data)+1; +} +#endif // B2B_TEST + + +void mp_set_bandwidth(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char *val; + int bw=0, shortGI=0; +// unsigned int regval, i, val32; +// unsigned char *CCK_SwingEntry; + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return; + } + + // get 20M~40M , 40M=0(20M), 1(40M) or 2(80M) + val = get_value_by_token((char *)data, "40M="); + if (val) { + bw = _atoi(val, 10); + } + + // get shortGI=1 or 0. + val = get_value_by_token((char *)data, "shortGI="); + if (val) { + shortGI = _atoi(val, 10); + } + + // modify short GI + if(shortGI) { + priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = 1; + } else { + priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M = 0; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = 0; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = 0; + } + + // modify BW + if (bw == 0) { + priv->pshare->is_40m_bw = 0; + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_DONTCARE; + priv->pmib->dot11nConfigEntry.dot11nUse40M=0; + } + else if (bw == 1) { + priv->pshare->is_40m_bw = 1; + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20_40; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + priv->pmib->dot11nConfigEntry.dot11nUse40M=1; + } + else if (bw == 2) { + priv->pshare->is_40m_bw = 2; + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_80; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + priv->pmib->dot11nConfigEntry.dot11nUse40M=2; + } + + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + +// mp_8192CD_tx_setting(priv); + return; // end here +} + + +/* + * auto-rx + * accept CRC32 error pkt + * accept destination address pkt + * drop tx pkt (implemented in other functions) + */ +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +int mp_arx(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char *val; + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return 0; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return 0; + } + if (OPMODE & WIFI_MP_CTX_BACKGROUND) { + printk("Fail: In MP background mode, please stop and retry it again\n"); + return 0; + } + + if (!strcmp(data, "start")) { + OPMODE_VAL(OPMODE | WIFI_MP_RX); + +#if 0//defined(CONFIG_RTL_92D_SUPPORT) + priv->pshare->mp_dig_on = 1; + mod_timer(&priv->pshare->MP_DIGTimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(700)); +#endif +#ifdef MP_SWITCH_LNA + priv->pshare->rx_packet_ss_a = 0; + priv->pshare->rx_packet_ss_b = 0; + PHY_SetBBReg(priv, 0xd00, BIT(27)|BIT(26), 0x3); + RTL_W32(RCR, RCR_APWRMGT | RCR_AMF | RCR_ADF |RCR_ACRC32 |RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_APP_PHYSTS); +#else + RTL_W32(RCR, RCR_APWRMGT | RCR_AMF | RCR_ADF |RCR_ACRC32 |RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_APP_PHYSTS); +#endif + if (priv->pshare->rf_ft_var.use_frq_2_3G) + PHY_SetBBReg(priv, rCCK0_System, bCCKEqualizer, 0x0); + + memset(&priv->net_stats, 0, sizeof(struct net_device_stats)); + memset(&priv->ext_stats, 0, sizeof(struct extra_stats)); + +#ifdef CONFIG_RTL_92C_SUPPORT + if( IS_UMC_B_CUT_88C(priv) ) + PHY_SetRFReg(priv, 0, 0x26, bMask20Bits, 0x4f200); +#endif + } else if (!strcmp(data, "stop")) { + OPMODE_VAL(OPMODE & ~WIFI_MP_RX); + /* priv->pshare->mp_dig_on = 0; */ +#if defined(CONFIG_RTL_92D_SUPPORT) + if (timer_pending(&priv->pshare->MP_DIGTimer)) { +#ifdef __ECOS + del_timer_sync(&priv->pshare->MP_DIGTimer); +#else + del_timer(&priv->pshare->MP_DIGTimer); +#endif + } +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + RTL_W32(RCR, RTL_R32(RCR) & ~(RCR_APWRMGT | RCR_AMF | RCR_ADF |RCR_ACRC32 |RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_APP_PHYSTS)); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + RTL_W32(RCR, RTL_R32(RCR) & ~(RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_APP_PHYSTS)); + + + if (priv->pshare->rf_ft_var.use_frq_2_3G) + PHY_SetBBReg(priv, rCCK0_System, bCCKEqualizer, 0x1); + +//clear filter: + if((priv->pshare->mp_filter_flag) || (OPMODE & WIFI_MP_ARX_FILTER)) { + OPMODE_VAL(OPMODE & ~WIFI_MP_ARX_FILTER); + priv->pshare->mp_filter_flag=0; + memset(priv->pshare->mp_filter_DA,0,6); + memset(priv->pshare->mp_filter_SA,0,6); + memset(priv->pshare->mp_filter_BSSID,0,6); + } + + sprintf(data, "Received packet OK:%lu CRC error:%lu\n", priv->net_stats.rx_packets, priv->net_stats.rx_crc_errors); + return strlen(data)+1; + } else if (!memcmp(data, "filter_SA",9)) { + OPMODE_VAL(OPMODE | WIFI_MP_ARX_FILTER); + memset(priv->pshare->mp_filter_SA,'\0',6); + + priv->pshare->mp_filter_flag |=0x1; + val = get_value_by_token((char *)data, "filter_SA="); + val[2]='\0'; + priv->pshare->mp_filter_SA[0]=_atoi(val,16); + val[5]='\0'; + priv->pshare->mp_filter_SA[1]=_atoi(val+3,16); + val[8]='\0'; + priv->pshare->mp_filter_SA[2]=_atoi(val+6,16); + val[11]='\0'; + priv->pshare->mp_filter_SA[3]=_atoi(val+9,16); + val[14]='\0'; + priv->pshare->mp_filter_SA[4]=_atoi(val+12,16); + val[17]='\0'; + priv->pshare->mp_filter_SA[5]=_atoi(val+15,16); + sprintf(data,"flag: %x\nSA: %02x:%02x:%02x:%02x:%02x:%02x\n",priv->pshare->mp_filter_flag, + priv->pshare->mp_filter_SA[0], + priv->pshare->mp_filter_SA[1], + priv->pshare->mp_filter_SA[2], + priv->pshare->mp_filter_SA[3], + priv->pshare->mp_filter_SA[4], + priv->pshare->mp_filter_SA[5]); + return strlen(data)+1; + + } else if (!memcmp(data, "filter_DA",9)) { + OPMODE_VAL(OPMODE | WIFI_MP_ARX_FILTER); + priv->pshare->mp_filter_flag |=0x2; + memset(priv->pshare->mp_filter_DA,'\0',6); + + val = get_value_by_token((char *)data, "filter_DA="); + val[2]='\0'; + priv->pshare->mp_filter_DA[0]=_atoi(val,16); + val[5]='\0'; + priv->pshare->mp_filter_DA[1]=_atoi(val+3,16); + val[8]='\0'; + priv->pshare->mp_filter_DA[2]=_atoi(val+6,16); + val[11]='\0'; + priv->pshare->mp_filter_DA[3]=_atoi(val+9,16); + val[14]='\0'; + priv->pshare->mp_filter_DA[4]=_atoi(val+12,16); + val[17]='\0'; + priv->pshare->mp_filter_DA[5]=_atoi(val+15,16); + sprintf(data,"flag: %x\nDA: %02x:%02x:%02x:%02x:%02x:%02x\n",priv->pshare->mp_filter_flag, + priv->pshare->mp_filter_DA[0], + priv->pshare->mp_filter_DA[1], + priv->pshare->mp_filter_DA[2], + priv->pshare->mp_filter_DA[3], + priv->pshare->mp_filter_DA[4], + priv->pshare->mp_filter_DA[5]); + return strlen(data)+1; + } else if (!memcmp(data, "filter_BSSID",12)) { + OPMODE_VAL(OPMODE | WIFI_MP_ARX_FILTER); + priv->pshare->mp_filter_flag |=0x4; + memset(priv->pshare->mp_filter_BSSID,'\0',6); + + val = get_value_by_token((char *)data, "filter_BSSID="); + val[2]='\0'; + priv->pshare->mp_filter_BSSID[0]=_atoi(val,16); + val[5]='\0'; + priv->pshare->mp_filter_BSSID[1]=_atoi(val+3,16); + val[8]='\0'; + priv->pshare->mp_filter_BSSID[2]=_atoi(val+6,16); + val[11]='\0'; + priv->pshare->mp_filter_BSSID[3]=_atoi(val+9,16); + val[14]='\0'; + priv->pshare->mp_filter_BSSID[4]=_atoi(val+12,16); + val[17]='\0'; + priv->pshare->mp_filter_BSSID[5]=_atoi(val+15,16); + sprintf(data,"flag: %x\nBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",priv->pshare->mp_filter_flag, + priv->pshare->mp_filter_BSSID[0], + priv->pshare->mp_filter_BSSID[1], + priv->pshare->mp_filter_BSSID[2], + priv->pshare->mp_filter_BSSID[3], + priv->pshare->mp_filter_BSSID[4], + priv->pshare->mp_filter_BSSID[5]); + return strlen(data)+1; + } else if( (!memcmp(data, "filter_clean",12)) || (!memcmp(data, "filter_init",11))) { + OPMODE_VAL(OPMODE & (~WIFI_MP_ARX_FILTER)); + priv->pshare->mp_filter_flag=0; + memset(priv->pshare->mp_filter_SA,'\0',6); + memset(priv->pshare->mp_filter_DA,'\0',6); + memset(priv->pshare->mp_filter_BSSID,'\0',6); + sprintf(data,"reset arx filter table\n"); + return strlen(data)+1; + } else if (!memcmp(data, "filter_print",12)) { + sprintf(data,"flag: %x\nSA: %02x:%02x:%02x:%02x:%02x:%02x\nDA: %02x:%02x:%02x:%02x:%02x:%02x\nBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",priv->pshare->mp_filter_flag, + priv->pshare->mp_filter_SA[0], + priv->pshare->mp_filter_SA[1], + priv->pshare->mp_filter_SA[2], + priv->pshare->mp_filter_SA[3], + priv->pshare->mp_filter_SA[4], + priv->pshare->mp_filter_SA[5], + priv->pshare->mp_filter_DA[0], + priv->pshare->mp_filter_DA[1], + priv->pshare->mp_filter_DA[2], + priv->pshare->mp_filter_DA[3], + priv->pshare->mp_filter_DA[4], + priv->pshare->mp_filter_DA[5], + priv->pshare->mp_filter_BSSID[0], + priv->pshare->mp_filter_BSSID[1], + priv->pshare->mp_filter_BSSID[2], + priv->pshare->mp_filter_BSSID[3], + priv->pshare->mp_filter_BSSID[4], + priv->pshare->mp_filter_BSSID[5]); + + return strlen(data)+1; + } + + return 0; +} + + +/* + * set bssid + */ +void mp_set_bssid(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned char pbuf[6]; + int ret; + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return; + } + + ret = get_array_val(pbuf, (char *)data, strlen(data)); + + if (ret != 6) { + printk("Error bssid format\n"); + return; + } else { + printk("set bssid to %02X:%02X:%02X:%02X:%02X:%02X\n", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5]); + } + + memcpy(BSSID, pbuf, MACADDRLEN); +} + + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) +static void mp_chk_sw_ant_AC(struct rtl8192cd_priv *priv) +{ + //int tx_ant_sel_val=0, rx_ant_sel_val=0; + + /* + * Tx setting + */ + switch(priv->pshare->mp_antenna_tx) + { + case ANTENNA_A: + PHY_SetBBReg(priv, 0x80c, 0xffff, 0x1111); + break; + case ANTENNA_B: + PHY_SetBBReg(priv, 0x80c, 0xffff, 0x2222); + break; + case ANTENNA_AB: + PHY_SetBBReg(priv, 0x80c, 0xffff, 0x3333); + break; + default: + break; + } + + switch(priv->pshare->mp_antenna_rx) + { + case ANTENNA_A: + PHY_SetBBReg(priv, 0x808, 0xff, 0x11); + PHY_SetBBReg(priv, 0xa04, 0xc000000, 0x0); //0xa07[3:2] + + // Reg0x00[19:16] RFMODE, 1:Idle, 3:Rx + PHY_SetRFReg(priv, 0, 0x00, 0xf0000, 3); + PHY_SetRFReg(priv, 1, 0x00, 0xf0000, 1); + break; + case ANTENNA_B: + PHY_SetBBReg(priv, 0x808, 0xff, 0x22); + PHY_SetBBReg(priv, 0xa04, 0xc000000, 0x1); + PHY_SetRFReg(priv, 0, 0x00, 0xf0000, 1); + PHY_SetRFReg(priv, 1, 0x00, 0xf0000, 3); + break; + case ANTENNA_AB: // For 8192S and 8192E/U... + PHY_SetBBReg(priv, 0x808, 0xff, 0x33); + PHY_SetBBReg(priv, 0xa04, 0xc000000, 0x0); + PHY_SetRFReg(priv, 0, 0x00, 0xf0000, 3); + PHY_SetRFReg(priv, 1, 0x00, 0xf0000, 3); + break; + } +} +#endif + + +static void mp_chk_sw_ant(struct rtl8192cd_priv *priv) +{ + R_ANTENNA_SELECT_OFDM *p_ofdm_tx; /* OFDM Tx register */ + R_ANTENNA_SELECT_CCK *p_cck_txrx; + unsigned char r_rx_antenna_ofdm=0, r_ant_select_cck_val=0; + unsigned char chgTx=0, chgRx=0; + unsigned int r_ant_sel_cck_val=0, r_ant_select_ofdm_val=0, r_ofdm_tx_en_val=0; + + p_ofdm_tx = (R_ANTENNA_SELECT_OFDM *)&r_ant_select_ofdm_val; + p_cck_txrx = (R_ANTENNA_SELECT_CCK *)&r_ant_select_cck_val; + + p_ofdm_tx->r_ant_ht1 = 0x1; + p_ofdm_tx->r_ant_non_ht = 0x3; + p_ofdm_tx->r_ant_ht2 = 0x2; + + // ­ì¦]¬OTx 3-wire enable»ÝÀHTx Ant path¥´¶}¤~·|¶}±Ò¡A + // ©Ò¥H»Ý¦b³]BB 0x824»P0x82C®É¡A¦P®É±NBB 0x804[3:0]³]¬°3(¦P®É¥´¶}Ant. A and B)¡C + // ­n¬Ù¹qªº±¡ªp¤U¡AA Tx®É 0x90C=0x11111111¡AB Tx®É 0x90C=0x22222222¡AAB¦P®É¶}´Nºû«ù­ì¨Ó³]©w0x3321333 + + + switch(priv->pshare->mp_antenna_tx) + { + case ANTENNA_A: + p_ofdm_tx->r_tx_antenna = 0x1; + r_ofdm_tx_en_val = 0x1; + p_ofdm_tx->r_ant_l = 0x1; + p_ofdm_tx->r_ant_ht_s1 = 0x1; + p_ofdm_tx->r_ant_non_ht_s1 = 0x1; + p_cck_txrx->r_ccktx_enable = 0x8; + chgTx = 1; + PHY_SetBBReg(priv, rFPGA0_XA_HSSIParameter2, 0xe, 2); + PHY_SetBBReg(priv, rFPGA0_XB_HSSIParameter2, 0xe, 1); + r_ofdm_tx_en_val = 0x3; + // Power save + r_ant_select_ofdm_val = 0x11111111; + +#ifdef HIGH_POWER_EXT_PA + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)){ + if(priv->pshare->rf_ft_var.use_ext_pa) { + PHY_SetBBReg(priv, 0x870, BIT(26), 1); + PHY_SetBBReg(priv, 0x870, BIT(10), 0); + } + } +#endif + break; + case ANTENNA_B: + p_ofdm_tx->r_tx_antenna = 0x2; + r_ofdm_tx_en_val = 0x2; + p_ofdm_tx->r_ant_l = 0x2; + p_ofdm_tx->r_ant_ht_s1 = 0x2; + p_ofdm_tx->r_ant_non_ht_s1 = 0x2; + p_cck_txrx->r_ccktx_enable = 0x4; + chgTx = 1; + PHY_SetBBReg(priv, rFPGA0_XA_HSSIParameter2, 0xe, 1); + PHY_SetBBReg(priv, rFPGA0_XB_HSSIParameter2, 0xe, 2); + r_ofdm_tx_en_val = 0x3; + // Power save + r_ant_select_ofdm_val = 0x22222222; + +#ifdef HIGH_POWER_EXT_PA + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)){ + if (priv->pshare->rf_ft_var.use_ext_pa) { + PHY_SetBBReg(priv, 0x870, BIT(26), 0); + PHY_SetBBReg(priv, 0x870, BIT(10), 1); + } + } +#endif + break; + case ANTENNA_AB: + p_ofdm_tx->r_tx_antenna = 0x3; + r_ofdm_tx_en_val = 0x3; + p_ofdm_tx->r_ant_l = 0x3; + p_ofdm_tx->r_ant_ht_s1 = 0x3; + p_ofdm_tx->r_ant_non_ht_s1 = 0x3; + p_cck_txrx->r_ccktx_enable = 0xC; + chgTx = 1; + PHY_SetBBReg(priv, rFPGA0_XA_HSSIParameter2, 0xe, 2); + PHY_SetBBReg(priv, rFPGA0_XB_HSSIParameter2, 0xe, 2); + // Disable Power save + r_ant_select_ofdm_val = 0x3321333; + +#ifdef HIGH_POWER_EXT_PA + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)){ + if (priv->pshare->rf_ft_var.use_ext_pa) { + PHY_SetBBReg(priv, 0x870, BIT(26), 0); + PHY_SetBBReg(priv, 0x870, BIT(10), 0); + } + } +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + { + if(priv->pmib->dot11RFEntry.tx2path) + { + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_WE_LUT, 0x80000,0x1); // RF Mode table write enable + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_WE_LUT, 0x80000,0x1); // RF Mode table write enable + + // Paath_A + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_RCK_OS, 0xfffff,0x18000); // Select RX mode 0x30=0x18000 + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_TXPA_G1, 0xfffff,0x0000f); // Set Table data + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_TXPA_G2, 0xfffff,0x77fc2); // Enable TXIQGEN in RX mode + // Path_B + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_RCK_OS, 0xfffff,0x18000); // Select RX mode + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_TXPA_G1, 0xfffff,0x0000f); // Set Table data + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_TXPA_G2, 0xfffff,0x77fc2); // Enable TXIQGEN in RX mode + + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_WE_LUT, 0x80000,0x0); // RF Mode table write disable + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_WE_LUT, 0x80000,0x0); // RF Mode table write disable + RTL_W8(0xA2F, 0x10); + } + } +#endif + + break; + default: + break; + } + + // + // r_rx_antenna_ofdm, bit0=A, bit1=B, bit2=C, bit3=D + // r_cckrx_enable : CCK default, 0=A, 1=B, 2=C, 3=D + // r_cckrx_enable_2 : CCK option, 0=A, 1=B, 2=C, 3=D + // + switch(priv->pshare->mp_antenna_rx) + { + case ANTENNA_A: + r_rx_antenna_ofdm = 0x11; // A + p_cck_txrx->r_cckrx_enable = 0x0; // default: A + p_cck_txrx->r_cckrx_enable_2= 0x0; // option: A + chgRx = 1; + PHY_SetRFReg(priv, 0, 7, 0x3, 0x0); + break; + case ANTENNA_B: + r_rx_antenna_ofdm = 0x22; // B + p_cck_txrx->r_cckrx_enable = 0x1; // default: B + p_cck_txrx->r_cckrx_enable_2= 0x1; // option: B + chgRx = 1; + PHY_SetRFReg(priv, 0, 7, 0x3, 0x1); + break; + case ANTENNA_AB: // For 8192S and 8192E/U... + r_rx_antenna_ofdm = 0x33; // AB + p_cck_txrx->r_cckrx_enable = 0x0; // default:A + p_cck_txrx->r_cckrx_enable_2= 0x1; // option:B + chgRx = 1; + break; + } + + if(chgTx && chgRx) { + r_ant_sel_cck_val = r_ant_select_cck_val;//(r_ant_select_cck_val<<24); + PHY_SetBBReg(priv, rFPGA1_TxInfo, 0x0fffffff, r_ant_select_ofdm_val); //OFDM Tx + PHY_SetBBReg(priv, rFPGA0_TxInfo, 0x0000000f, r_ofdm_tx_en_val); //OFDM Tx + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, 0x000000ff, r_rx_antenna_ofdm); //OFDM Rx + PHY_SetBBReg(priv, rOFDM1_TRxPathEnable, 0x0000000f, r_rx_antenna_ofdm); //OFDM Rx + PHY_SetBBReg(priv, rCCK0_AFESetting, bMaskByte3, r_ant_sel_cck_val); //CCK TxRx + } + +#ifdef CONFIG_WLAN_HAL_8192EE // 1R CCA + if (GET_CHIP_VER(priv) == VERSION_8192E) { + switch(priv->pshare->mp_antenna_rx) + { + case ANTENNA_A: + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, bMaskByte0, 0x11); + break; + + case ANTENNA_B: + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, bMaskByte0, 0x22); + break; + + case ANTENNA_AB: + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, bMaskByte0, 0x33); + break; + } + } +#endif +} + + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +void mp_set_ant_tx(struct rtl8192cd_priv *priv, unsigned char *data) +{ + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return; + } + + if (!strcmp(data, "a")) { + priv->pshare->mp_antenna_tx = ANTENNA_A; + priv->pshare->mp_antenna_rx = ANTENNA_A; + } else if (!strcmp(data, "b")) { + priv->pshare->mp_antenna_tx = ANTENNA_B; + priv->pshare->mp_antenna_rx = ANTENNA_B; + } else if (!strcmp(data, "c")) { + priv->pshare->mp_antenna_tx = ANTENNA_C; + priv->pshare->mp_antenna_rx = ANTENNA_C; + } else if (!strcmp(data, "d")) { + priv->pshare->mp_antenna_tx = ANTENNA_D; + priv->pshare->mp_antenna_rx = ANTENNA_D; + } else if (!strcmp(data, "ab")) { + priv->pshare->mp_antenna_tx = ANTENNA_AB; + priv->pshare->mp_antenna_rx = ANTENNA_AB; + } else if (!strcmp(data, "abc")) { + priv->pshare->mp_antenna_tx = ANTENNA_ABC; + priv->pshare->mp_antenna_rx = ANTENNA_ABC; + } else if (!strcmp(data, "abcd")) { + priv->pshare->mp_antenna_tx = ANTENNA_ABCD; + priv->pshare->mp_antenna_rx = ANTENNA_ABCD; + } else { + printk("Usage: mp_ant_tx {a,b,ab}\n"); + return; + } +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812() || CHECKICIS8881A()) + mp_chk_sw_ant_AC(priv); + else +#endif + mp_chk_sw_ant(priv); + mp_8192CD_tx_setting(priv); + + printk("switch Tx antenna to %s\n", data); +} + + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +void mp_set_ant_rx(struct rtl8192cd_priv *priv, unsigned char *data) +{ + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return; + } + + if (!strcmp(data, "a")) { + priv->pshare->mp_antenna_rx = ANTENNA_A; + } else if (!strcmp(data, "b")) { + priv->pshare->mp_antenna_rx = ANTENNA_B; + } else if (!strcmp(data, "c")) { + priv->pshare->mp_antenna_rx = ANTENNA_C; + } else if (!strcmp(data, "d")) { + priv->pshare->mp_antenna_rx = ANTENNA_D; + } else if (!strcmp(data, "ab")) { + priv->pshare->mp_antenna_rx = ANTENNA_AB; + } else if (!strcmp(data, "abc")) { + priv->pshare->mp_antenna_rx = ANTENNA_ABC; + } else if (!strcmp(data, "abcd")) { + priv->pshare->mp_antenna_rx = ANTENNA_ABCD; + } else { + printk("Usage: mp_ant_rx {a,b,ab}\n"); + return; + } + +#ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8188E){/* 88E MP Rx refine */ + RTL_W8(0xc50,0x1f); + RTL_W8(0xc50,0x20); + } +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if (CHECKICIS8812() || CHECKICIS8881A()) + mp_chk_sw_ant_AC(priv); + else +#endif + mp_chk_sw_ant(priv); + printk("switch Rx antenna to %s\n", data); +} + + +void mp_set_phypara(struct rtl8192cd_priv *priv, unsigned char *data) +{ + char *val; + int xcap=-32, sign; + + if (!netif_running(priv->dev)) + { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) + { + printk("Fail: not in MP mode\n"); + return; + } + +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192C || GET_CHIP_VER(priv) == VERSION_8188C) { + printk("Fail: xcap is not support for 92C!\n"); + return; + } +#endif + + // get CrystalCap value + val = get_value_by_token((char *)data, "xcap="); + if (val) { + if (*val == '-') { + sign = 1; + val++; + } + else + sign = 0; + + xcap = _atoi(val, 10); + if (sign) + xcap = 0 - xcap; + } + + // set CrystalCap value + if(GET_CHIP_VER(priv) == VERSION_8192D){ + if (xcap != -32) { + /* + PHY_SetBBReg(priv, rFPGA0_AnalogParameter1, bXtalCap01, (xcap & 0x00000003)); + PHY_SetBBReg(priv, rFPGA0_AnalogParameter2, bXtalCap23, ((xcap & 0x0000000c) >> 2)); + */ + PHY_SetBBReg(priv, 0x24, 0xF0, xcap & 0x0F); + PHY_SetBBReg(priv, 0x28, 0xF0000000, ((xcap & 0xF0) >> 4)); + } + } +#ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8188E){ + if(xcap > 0 && xcap < 0x3F) { + PHY_SetBBReg(priv, 0x24, BIT(11)|BIT(12)|BIT(13)|BIT(14)|BIT(15)|BIT(16), xcap & 0x3F); + PHY_SetBBReg(priv, 0x24, BIT(17)|BIT(18)|BIT(19)|BIT(20)|BIT(21)|BIT(22), xcap & 0x3F); + } + } +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + if(xcap > 0 && xcap < 0x3F) { + PHY_SetBBReg(priv, 0x2c, 0x01f80000, xcap & 0x3F); // 0x2c[24:19] + PHY_SetBBReg(priv, 0x2c, 0x7e000000, xcap & 0x3F); // 0x2c[30:25] + } + } +#endif +#if defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_WLAN_HAL_8881A) + if ((GET_CHIP_VER(priv)== VERSION_8192E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + if (xcap > 0 && xcap < 0x3F) { + PHY_SetBBReg(priv, 0x2c, BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17), xcap & 0x3F); + PHY_SetBBReg(priv, 0x2c, BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23), xcap & 0x3F); + } + } +#endif + + + printk("Set xcap=%d\n", xcap); +} + +// TODO: 8814AE BB/RF +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) +void mp_set_phyBand(struct rtl8192cd_priv *priv, unsigned char *data) +{ +#if defined(CONFIG_RTL_92D_SUPPORT) + unsigned int eRFPath, curMaxRFPath=((priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY)?RF92CD_PATH_MAX : RF92CD_PATH_B); +#endif + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return; + } + + if (!strcmp(data, "a")) { + if (!(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) { + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; + } else { + printk("Fail: It is already set as A band\n"); + return; + } + } else if (!strcmp(data, "bg")) { + if (!(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G)) { + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; + } else { + printk("Fail: It is already set as BG band\n"); + return; + } + } else { + printk("Usage: mp_phyband {a, bg}\n"); + return; + } + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if((GET_CHIP_VER(priv)==VERSION_8812E) || (GET_CHIP_VER(priv)==VERSION_8881A)) + { + /* + * Stop RX/Tx + */ + PHY_SetBBReg(priv, 0x808, 0xff, 0x00); + PHY_SetBBReg(priv, 0xa04, 0xc000000, 0x0); + + /* BB & RF Config */ + PHY_SetBBReg(priv, 0x808, BIT(28) | BIT(29), 0); + PHY_ConfigBBWithParaFile(priv, AGCTAB); + PHY_SetBBReg(priv, 0x808, BIT(28) | BIT(29), 3); + +#if defined(CONFIG_WLAN_HAL_8881A) + if (GET_CHIP_VER(priv) == VERSION_8881A) { + GET_HAL_INTERFACE(priv)->PHYUpdateBBRFValHandler(priv, + priv->pmib->dot11RFEntry.dot11channel,priv->pshare->offset_2nd_chan); + } +#endif //#if defined(CONFIG_WLAN_HAL_8881A) + +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8812E) + UpdateBBRFVal8812(priv, priv->pmib->dot11RFEntry.dot11channel); +#endif //#if defined(CONFIG_RTL_8812_SUPPORT) + + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + RTL_W16(RRSR, 0x150); + else + RTL_W16(RRSR, 0x15D); + + /* + * Recovery RX/Tx + */ + PHY_SetBBReg(priv, 0x808, 0xff, 0x33); + PHY_SetBBReg(priv, 0xa04, 0xc000000, 0x0); + + /* + * IQK + */ + //PHY_IQCalibrate(priv); +#if 0 + /* + * Set Rx AGC + */ + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + RTL_W8(0xc50, 0x1c); + RTL_W8(0xe50, 0x1c); + } else { + RTL_W8(0xc50, 0x20); + RTL_W8(0xe50, 0x20); + } +#endif + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + printk("Set band as A band\n"); + else + printk("Set band as BG band\n"); + return; + } +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv)==VERSION_8192D) { + /* + * Stop RX/Tx + */ + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, bMaskByte0, 0x00); + PHY_SetBBReg(priv, rOFDM1_TRxPathEnable, bDWord, 0x0); + + /* + * Reconfig BB/RF according to wireless mode + */ + /* mac config */ + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) + RTL_W8(BWOPMODE, (RTL_R8(BWOPMODE) & ~BW_OPMODE_5G)); + else /* if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) */ + RTL_W8(BWOPMODE, RTL_R8(BWOPMODE) | BW_OPMODE_5G); + + /* BB & RF Config */ + PHY_SetBBReg(priv, rFPGA0_RFMOD, BIT(25) | BIT(24), 0); + PHY_ConfigBBWithParaFile(priv, AGCTAB); + PHY_SetBBReg(priv, rFPGA0_RFMOD, BIT(25) | BIT(24), 3); + + for(eRFPath = RF92CD_PATH_A; eRFPath pshare->RegRF18[eRFPath] = PHY_QueryRFReg(priv, eRFPath, 0x18, bMask20Bits, 1); + priv->pshare->RegRF28[eRFPath] = PHY_QueryRFReg(priv, eRFPath, 0x28, bMask20Bits, 1); + } + + UpdateBBRFVal8192DE(priv); + + // 2010/09/30 protect cck + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + RTL_W16(RRSR, 0x150); + } else{ + RTL_W16(RRSR, 0x15D); + } + + /* + * Recovery RX/Tx + */ + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, bMaskByte0, 0x33); + PHY_SetBBReg(priv, rOFDM1_TRxPathEnable, bDWord, 0x3); + + /* + * IQK + */ + PHY_IQCalibrate(priv); + /* + * Set Rx AGC + */ + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + RTL_W8(0xc50, 0x1c); + RTL_W8(0xc58, 0x1c); + } else { + RTL_W8(0xc50, 0x20); + RTL_W8(0xc58, 0x20); + } + + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + printk("Set band as A band\n"); + else + printk("Set band as BG band\n"); + } +#endif + +} +#endif + + +void mp_reset_stats(struct rtl8192cd_priv *priv) +{ + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return; + } + + if (!(OPMODE & WIFI_MP_STATE)) { + printk("Fail: not in MP mode\n"); + return; + } + + memset(&priv->net_stats, 0, sizeof(struct net_device_stats)); + memset(&priv->ext_stats, 0, sizeof(struct extra_stats)); +} +#endif // MP_TEST + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_net80211.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_net80211.c new file mode 100755 index 000000000..91cd0cbfc --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_net80211.c @@ -0,0 +1,2024 @@ +/* + * API-compatible handling routines + * + * + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#if defined(WIFI_HAPD) || defined(RTK_NL80211) + +#ifdef __LINUX_2_6__ +#include +#include +#endif + +#include "./8192cd_debug.h" +#include "./8192cd_headers.h" + +#include +#include +#include +#include "net80211/ieee80211.h" +#include "net80211/ieee80211_crypto.h" +#include "net80211/ieee80211_ioctl.h" + +#include "./8192cd_net80211.h" + + +//#define HAPD_DEBUG + +void void_printk(const char *fmt, ...) +{ + ; +} + +#ifdef HAPD_DEBUG +#define HAPD_MSG printk +#else +#define HAPD_MSG void_printk +#endif + + + +const char* ether_sprintf(const u_int8_t *mac) +{ + static char etherbuf[18]; /* XXX */ + snprintf(etherbuf, sizeof(etherbuf), "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return etherbuf; +} + +static __inline__ void set_ttkeylen(struct Dot11EncryptKey *pEncryptKey, UINT8 len) +{ + pEncryptKey->dot11TTKeyLen = len; +} + + +static __inline__ void set_tmickeylen(struct Dot11EncryptKey *pEncryptKey, UINT8 len) +{ + pEncryptKey->dot11TMicKeyLen = len; +} + +static __inline__ void set_tkip_key_for_wpas(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) +{ + memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); + + memcpy(pEncryptKey->dot11TMicKey2.skey, src + 16, pEncryptKey->dot11TMicKeyLen); + memcpy(pEncryptKey->dot11TMicKey1.skey, src + 24, pEncryptKey->dot11TMicKeyLen); + + memcpy(src + 16, pEncryptKey->dot11TMicKey2.skey, pEncryptKey->dot11TMicKeyLen); + memcpy(src + 24, pEncryptKey->dot11TMicKey1.skey, pEncryptKey->dot11TMicKeyLen); + + pEncryptKey->dot11TXPN48.val48 = 0; +} + +static __inline__ void set_tkip_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) +{ + memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); + + memcpy(pEncryptKey->dot11TMicKey1.skey, src + 16, pEncryptKey->dot11TMicKeyLen); + + memcpy(pEncryptKey->dot11TMicKey2.skey, src + 24, pEncryptKey->dot11TMicKeyLen); + + pEncryptKey->dot11TXPN48.val48 = 0; +} + + +static __inline__ void set_aes_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) +{ + memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); + + memcpy(pEncryptKey->dot11TMicKey1.skey, src, pEncryptKey->dot11TMicKeyLen); +} + + +static __inline__ void set_wep40_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) +{ + memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); +} + + +static __inline__ void set_wep104_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) +{ + memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); +} + + +static int HAPD_Process_Set_Port(struct net_device *dev, unsigned char *MACAddr, int PortStatus) +{ + struct stat_info *pstat; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct wifi_mib *pmib = priv->pmib; + + HAPD_MSG("HAPD_Process_Set_Port +++ sta: %02X%02X%02X%02X%02X%02X Status %X\n", + MACAddr[0],MACAddr[1],MACAddr[2], + MACAddr[3],MACAddr[4],MACAddr[5], + PortStatus); + + // if driver is not opened, return immediately, david + if (!netif_running(priv->dev)) + return (-1); + + pstat = get_stainfo(priv, MACAddr); + + if ((pstat == NULL) || (!(pstat->state & WIFI_ASOC_STATE))) + return (-1); + + if (PortStatus) + pstat->ieee8021x_ctrlport = PortStatus; + else + pstat->ieee8021x_ctrlport = pmib->dot118021xAuthEntry.dot118021xDefaultPort; + + HAPD_MSG("HAPD_Process_Set_Port ---\n"); + + return 0; +} + +#if defined(WIFI_WPAS) || ( defined(RTK_NL80211) && defined(CLIENT_MODE)) +int rtl_wpas_join(struct rtl8192cd_priv *priv, int bss_num) +{ + char tmpbuf[33]; + + if (!netif_running(priv->dev)) { + printk("WiFi driver is NOT open!!\n"); + return -1; + } else if (priv->ss_req_ongoing) { + printk("Site Survey is not finished yet!!\n"); + return -1; + } + +#if defined(RTK_NL80211) + memcpy((void *)&(priv->pmib->dot11Bss) , + (void *)&priv->site_survey->bss_target[bss_num] , sizeof(struct bss_desc)); +#else + memcpy((void *)&(priv->pmib->dot11Bss) , + (void *)&priv->site_survey->bss_backup[bss_num] , sizeof(struct bss_desc)); +#endif + + memcpy((void *)&(priv->pmib->dot11Bss) , + (void *)&priv->site_survey->bss_backup[bss_num] , sizeof(struct bss_desc)); + +#ifdef WIFI_SIMPLE_CONFIG + //_Eric if (priv->pmib->wscEntry.wsc_enable && (priv->pmib->dot11Bss.bsstype&WIFI_WPS)) + if (priv->pmib->wscEntry.wsc_enable) + { + //priv->pmib->dot11Bss.bsstype &= ~WIFI_WPS; + priv->wps_issue_join_req = 1; + } + else +#endif + { + if (check_bss_encrypt(priv) == FAIL) + { + printk("Encryption mismatch!\n"); + return -1; + } + } + + if ((priv->pmib->dot11Bss.ssidlen == 0) || (priv->pmib->dot11Bss.ssid[0] == '\0')) + { + printk("Error !! Join to a hidden AP!\n"); + return -1; + } + +#ifdef UNIVERSAL_REPEATER + disable_vxd_ap(GET_VXD_PRIV(priv)); +#endif + + memcpy(tmpbuf, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + tmpbuf[priv->pmib->dot11Bss.ssidlen] = '\0'; + + NDEBUG3(" going to join bss: [%s] [channel=%d]\n", tmpbuf, priv->pmib->dot11Bss.channel); + + memcpy(SSID2SCAN, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + SSID2SCAN_LEN = priv->pmib->dot11Bss.ssidlen; + + SSID_LEN = SSID2SCAN_LEN; + memcpy(SSID, SSID2SCAN, SSID_LEN); + memset(BSSID, 0, MACADDRLEN); + +#ifdef INCLUDE_WPA_PSK //_Eric ?? + //if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) + //derivePSK(priv); +#endif + priv->join_req_ongoing = 1; + priv->authModeRetry = 0; + + //mod_timer(&priv->WPAS_timer, jiffies + 300); + +#ifdef RTK_NL80211 + if(priv->pmib->dot11Bss.channel >=36) + { + if(GET_CHIP_VER(priv)==VERSION_8812E || GET_CHIP_VER(priv)==VERSION_8881A) + priv->pmib->dot11BssType.net_work_type = WIRELESS_11A|WIRELESS_11N|WIRELESS_11AC; + else + priv->pmib->dot11BssType.net_work_type = WIRELESS_11A|WIRELESS_11N; + } + else + { + #ifdef P2P_SUPPORT + if(rtk_p2p_is_enabled(priv)) + priv->pmib->dot11BssType.net_work_type = WIRELESS_11G|WIRELESS_11N; // p2p mode no included 11B + else + #endif + priv->pmib->dot11BssType.net_work_type = WIRELESS_11B|WIRELESS_11G|WIRELESS_11N; + + } +#endif + + priv->pmib->dot11nConfigEntry.dot11nAMPDU = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = 1; + +#if defined(CONFIG_PCI_HCI) + start_clnt_join(priv); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + // avoid IQK handling race condition between start_clnt_auth and TXPowerTracking + // so we indicate WPAS_JOIN event to cmd_thread to do start_clnt_join() + notify_wpas_join(priv); +#endif + + return 0; +} + +#endif + + +void rtl_net80311_authmode(struct net_device *dev, int authtype, int encmode, + int pskenable, int dot11802_1x) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + HAPD_MSG("rtl_net80311_authmode +++\n"); + HAPD_MSG("authtype=%d, encmode=%d, pskenable=%d, dot11802_1x=%d \n", authtype, encmode, pskenable, dot11802_1x); + + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = authtype; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = encmode; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = pskenable; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = dot11802_1x; +} + +int rtl_net80211_setparam(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + int *i = (int *) extra; + int param = wrqu->mode; /* parameter id is 1st */ + int value = 0; /* NB: most values are TYPE_INT */ + int ret = 0; + + int authtype = priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm; + int encmode = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + int pskenable = priv->pmib->dot1180211AuthEntry.dot11EnablePSK; + int dot11802_1x = priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm; + + memcpy(&value, wrqu->name+sizeof(value), sizeof(value)); + + HAPD_MSG("rtl_net80211_setparam +++\n"); + HAPD_MSG("rtl8192cd_net80211_ioctl, param = %d, value =%d\n", param, value); + + + switch (param) { + case IEEE80211_PARAM_TURBO: /* turbo mode */ + break; + case IEEE80211_PARAM_MODE: /* phy mode (11a, 11b, etc.) */ + break; + case IEEE80211_PARAM_AUTHMODE: /* authentication mode */ + switch (value) { + case IEEE80211_AUTH_NONE: + {//Disable + authtype = 0; + encmode = 0; + pskenable = 0; + dot11802_1x = 0; + rtl_net80311_authmode(dev, authtype, encmode, pskenable, dot11802_1x); + break; + } + case IEEE80211_AUTH_OPEN: + {//WEP Open + authtype = 0; + //WEP encmode depends on key length + //encmode = 1; + pskenable = 0; + dot11802_1x = 0; + rtl_net80311_authmode(dev, authtype, encmode, pskenable, dot11802_1x); + break; + } + case IEEE80211_AUTH_SHARED: + {//WEP Shared + authtype = 1; + //WEP encmode depends on key length + //encmode = 1; + pskenable = 0; + dot11802_1x = 0; + rtl_net80311_authmode(dev, authtype, encmode, pskenable, dot11802_1x); + break; + } + case IEEE80211_AUTH_AUTO: + {//WEP Auto + authtype = 2; + //WEP encmode depends on key length + //encmode = 1; + pskenable = 0; + dot11802_1x = 0; + rtl_net80311_authmode(dev, authtype, encmode, pskenable, dot11802_1x); + break; + } + case IEEE80211_AUTH_WPA: + {//WPA-PSK-AES + //_Eric ?? if there is no valid passphrase ?? + authtype = 2; + encmode = 2; + //_Eric pskmode (WPA 0,1,2) will be set by IEEE80211_PARAM_WPA + //pskenable = 1; + dot11802_1x = 1; + rtl_net80311_authmode(dev, authtype, encmode, pskenable, dot11802_1x); + break; + } + case IEEE80211_AUTH_8021X: + { + //8021x encmode depends on key length + if((encmode == _WEP_40_PRIVACY_) || (encmode == _WEP_104_PRIVACY_)) + authtype = 2; + else + authtype = 0; + + pskenable = 0; + dot11802_1x = 1; + rtl_net80311_authmode(dev, authtype, encmode, pskenable, dot11802_1x); + break; + } + default: + return -EINVAL; + } + case IEEE80211_PARAM_PROTMODE: /* 802.11g protection */ + break; + case IEEE80211_PARAM_MCASTCIPHER: /* multicast/default cipher */ + break; + case IEEE80211_PARAM_MCASTKEYLEN: /* multicast key length */ + break; + case IEEE80211_PARAM_UCASTCIPHERS: /* unicast cipher suites */ + /* 1. Only support AES & TKIP for WPA1&WPA2 + 2. Set both wpa_cipher and wpa2_cipher, because IEEE80211_PARAM_WPA will clear unused cipher mode */ + HAPD_MSG("IEEE80211_PARAM_UCASTCIPHERS\n"); + + if(value & (1<pmib->dot11BssType.net_work_type & WIRELESS_11N)) || (OPMODE & WIFI_STATION_STATE)) + { + priv->pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(1); + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher |= BIT(1); + } + else + return -EINVAL; + } + else + { + priv->pmib->dot1180211AuthEntry.dot11WPACipher &= ~(BIT(1)); + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher &= ~(BIT(1)); + } + + + if(value & (1<pmib->dot1180211AuthEntry.dot11WPACipher |= BIT(3); + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher |= BIT(3); + } + else + { + priv->pmib->dot1180211AuthEntry.dot11WPACipher &= ~(BIT(3)); + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher &= ~(BIT(3)); + } + + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1; + + return 0; //_Eric if value > BIT(8) ? + + case IEEE80211_PARAM_UCASTCIPHER: /* unicast cipher */ + break; + case IEEE80211_PARAM_UCASTKEYLEN: /* unicast key length */ + if(value == 5) + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_40_PRIVACY_; + else if(value == 13) + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_104_PRIVACY_; + else + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + break; + case IEEE80211_PARAM_WPA: /* WPA mode (0,1,2) */ + HAPD_MSG("IEEE80211_PARAM_WPA\n"); + if((value & BIT(0)) && (value & BIT(1))) + return 0; + else if((value & BIT(0))) + {//only WPA1, so clear mib of wpa2_cipher & wpa2_psk + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK &= ~(BIT(1)); + return 0; + } + else if((value & BIT(1))) + {//only WPA2, so clear mib of wpa_cipher & wps2_psk + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK &= ~(BIT(0)); + return 0; + } + + case IEEE80211_PARAM_ROAMING: /* roaming mode */ +#ifdef WIFI_WPAS + if(value == IEEE80211_ROAMING_DEVICE) + priv->pmib->dot11StationConfigEntry.fastRoaming = 1; + else if(value == IEEE80211_ROAMING_MANUAL) + priv->pmib->dot11StationConfigEntry.fastRoaming = 0; + else + return -EINVAL; +#endif + break; + case IEEE80211_PARAM_PRIVACY: /* privacy invoked */ + ret =0; //It seems useless, just return status OK for hostapd. + break; + case IEEE80211_PARAM_COUNTERMEASURES: /* WPA/TKIP countermeasures */ + //_Eric ?? realtek do not have to support ?? + break; + case IEEE80211_PARAM_DROPUNENCRYPTED: /* discard unencrypted frames */ + break; + case IEEE80211_PARAM_DRIVER_CAPS: /* driver capabilities */ + break; + case IEEE80211_PARAM_MACCMD: /* MAC ACL operation */ + break; + case IEEE80211_PARAM_WMM: /* WMM mode (on, off) */ + break; + case IEEE80211_PARAM_HIDESSID: /* hide SSID mode (on, off) */ + break; + case IEEE80211_PARAM_APBRIDGE: /* AP inter-sta bridging */ + break; + case IEEE80211_PARAM_KEYMGTALGS: /* key management algorithms */ + HAPD_MSG("IEEE80211_PARAM_KEYMGTALGS\n"); + if((0<=value) && (value<=3)) + { + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = value; + break; + } + else + return -EINVAL; + case IEEE80211_PARAM_RSNCAPS: /* RSN capabilities */ + break; + case IEEE80211_PARAM_INACT: /* station inactivity timeout */ + break; + case IEEE80211_PARAM_INACT_AUTH: /* station auth inact timeout */ + break; + case IEEE80211_PARAM_INACT_INIT: /* station init inact timeout */ + break; + case IEEE80211_PARAM_ABOLT: /* Atheros Adv. Capabilities */ + break; + case IEEE80211_PARAM_DTIM_PERIOD: /* DTIM period (beacons) */ + break; + case IEEE80211_PARAM_BEACON_INTERVAL: /* beacon interval (ms) */ + break; + case IEEE80211_PARAM_DOTH: /* 11.h is on/off */ + break; + case IEEE80211_PARAM_PWRTARGET: /* Current Channel Pwr Constraint */ + break; + case IEEE80211_PARAM_GENREASSOC: /* Generate a reassociation request */ + break; + case IEEE80211_PARAM_COMPRESSION: /* compression */ + break; + case IEEE80211_PARAM_FF: /* fast frames support */ + break; + case IEEE80211_PARAM_XR: /* XR support */ + break; + case IEEE80211_PARAM_BURST: /* burst mode */ + break; + case IEEE80211_PARAM_PUREG: /* pure 11g (no 11b stations) */ + break; + case IEEE80211_PARAM_AR: /* AR support */ + break; + case IEEE80211_PARAM_WDS: /* Enable 4 address processing */ + break; + case IEEE80211_PARAM_BGSCAN: /* bg scanning (on, off) */ + break; + case IEEE80211_PARAM_BGSCAN_IDLE: /* bg scan idle threshold */ + break; + case IEEE80211_PARAM_BGSCAN_INTERVAL: /* bg scan interval */ + break; + case IEEE80211_PARAM_MCAST_RATE: /* Multicast Tx Rate */ + break; + case IEEE80211_PARAM_COVERAGE_CLASS: /* coverage class */ + break; + case IEEE80211_PARAM_COUNTRY_IE: /* enable country IE */ + break; + case IEEE80211_PARAM_SCANVALID: /* scan cache valid threshold */ + break; + case IEEE80211_PARAM_ROAM_RSSI_11A: /* rssi threshold in 11a */ + break; + case IEEE80211_PARAM_ROAM_RSSI_11B: /* rssi threshold in 11b */ + break; + case IEEE80211_PARAM_ROAM_RSSI_11G: /* rssi threshold in 11g */ + break; + case IEEE80211_PARAM_ROAM_RATE_11A: /* tx rate threshold in 11a */ + break; + case IEEE80211_PARAM_ROAM_RATE_11B: /* tx rate threshold in 11b */ + break; + case IEEE80211_PARAM_ROAM_RATE_11G: /* tx rate threshold in 11g */ + break; + case IEEE80211_PARAM_UAPSDINFO: /* value for qos info field */ + break; + case IEEE80211_PARAM_SLEEP: /* force sleep/wake */ + break; + case IEEE80211_PARAM_QOSNULL: /* force sleep/wake */ + break; + case IEEE80211_PARAM_PSPOLL: /* force ps-poll generation (sta only) */ + break; + case IEEE80211_PARAM_EOSPDROP: /* force uapsd EOSP drop (ap only) */ + break; + case IEEE80211_PARAM_MARKDFS: /* mark a dfs interference channel when found */ + break; + case IEEE80211_PARAM_REGCLASS: /* enable regclass ids in country IE */ + break; + case IEEE80211_PARAM_DROPUNENC_EAPOL: /* drop unencrypted eapol frames */ + break; + case IEEE80211_PARAM_SHPREAMBLE: /* Short Preamble */ + break; + + } + + HAPD_MSG("rtl_net80211_setparam ---\n"); + return ret; + +} + +/* +Management frame type to which application IE is added +enum { + IEEE80211_APPIE_FRAME_BEACON = 0, + IEEE80211_APPIE_FRAME_PROBE_REQ = 1, + IEEE80211_APPIE_FRAME_PROBE_RESP = 2, + IEEE80211_APPIE_FRAME_ASSOC_REQ = 3, + IEEE80211_APPIE_FRAME_ASSOC_RESP = 4, + IEEE80211_APPIE_NUM_OF_FRAME = 5 +}; +*/ + +int rtl_net80211_setappiebuf(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct ieee80211req_getset_appiebuf * ie = (struct ieee80211req_getset_appiebuf *)wrqu->data.pointer; + int ret = 0; + + HAPD_MSG("rtl_net80211_setappiebuf +++\n"); + HAPD_MSG("frametype =%d, iebuflen=%d \n", ie->app_frmtype, ie->app_buflen); + + //_Eric ???? hostapd has no interface to set wsc_enable. + + if((ie->app_buflen == 0) && (ie->app_frmtype != IEEE80211_APPIE_FRAME_ASSOC_RESP)) + priv->pmib->wscEntry.wsc_enable = 0; + else if(ie->app_buflen <= 256) + priv->pmib->wscEntry.wsc_enable = 2; //Work as AP + else + return -EINVAL; + + if (ie->app_frmtype == IEEE80211_APPIE_FRAME_BEACON) { + HAPD_MSG("WSC: set beacon IE\n"); + priv->pmib->wscEntry.beacon_ielen = ie->app_buflen; + memcpy((void *)priv->pmib->wscEntry.beacon_ie, ie->app_buf, ie->app_buflen); + } + else if (ie->app_frmtype == IEEE80211_APPIE_FRAME_PROBE_RESP) { + HAPD_MSG("WSC: set probe response IE\n"); + priv->pmib->wscEntry.probe_rsp_ielen = ie->app_buflen; + memcpy((void *)priv->pmib->wscEntry.probe_rsp_ie, ie->app_buf, ie->app_buflen); + } + else if (ie->app_frmtype == IEEE80211_APPIE_FRAME_ASSOC_RESP) { + HAPD_MSG("WSC: set association response IE\n"); + priv->pmib->wscEntry.assoc_ielen = ie->app_buflen; + memcpy((void *)priv->pmib->wscEntry.assoc_ie, ie->app_buf, ie->app_buflen); + } +#ifdef WIFI_WPAS + else if (ie->app_frmtype == IEEE80211_APPIE_FRAME_PROBE_REQ) { + HAPD_MSG("WSC: set probe request IE\n"); + priv->pmib->wscEntry.probe_req_ielen = ie->app_buflen; + memcpy((void *)priv->pmib->wscEntry.probe_req_ie, ie->app_buf, ie->app_buflen); + } +#endif + else + return -EINVAL; + + + HAPD_MSG("rtl_net80211_setappiebuf ---\n"); + return ret; + +} + + +#ifdef WIFI_WPAS + +int rtl_net80211_setoptie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + WPAS_ASSOCIATION_INFO Assoc_Info; + +//Check if WPS IE + UINT8 WSC_IE_OUI[4] = {0x00, 0x50, 0xf2, 0x04}; + int x; + unsigned char *ie = (unsigned char *)wrqu->data.pointer; + + if( ie[0] == _WPS_IE_) + if (!memcmp(ie+2, WSC_IE_OUI, 4)) + { + priv->pmib->wscEntry.assoc_ielen = wrqu->data.length; + memcpy((void *)priv->pmib->wscEntry.assoc_ie, wrqu->data.pointer, wrqu->data.length); + priv->pmib->wscEntry.wsc_enable = 1; + + return 0; + } + + priv->pmib->wscEntry.wsc_enable = 0; + + memset(priv->pmib->dot11RsnIE.rsnie, 0x0, 128); + memcpy(priv->pmib->dot11RsnIE.rsnie, wrqu->data.pointer, wrqu->data.length); + priv->pmib->dot11RsnIE.rsnielen = wrqu->data.length; + + memset((void *)&Assoc_Info, 0, sizeof(struct _WPAS_ASSOCIATION_INFO)); + Assoc_Info.ReqIELen = priv->pmib->dot11RsnIE.rsnie[1]+ 2; + memcpy(Assoc_Info.ReqIE, priv->pmib->dot11RsnIE.rsnie, Assoc_Info.ReqIELen); + //event_indicate_wpas(priv, NULL, WPAS_ASSOC_INFO, (UINT8 *)&Assoc_Info); + + return 0; + +} + +#endif + +int rtl_net80211_setmlme(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)wrqu->data.pointer; + struct stat_info *pstat = get_stainfo(priv, mlme->im_macaddr); + + int ret = 0; + + HAPD_MSG("rtl_net80211_setmlme +++\n"); + HAPD_MSG("auth_state =%d, mac = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n" + , mlme->im_op, mlme->im_macaddr[0], mlme->im_macaddr[1], mlme->im_macaddr[2], + mlme->im_macaddr[3], mlme->im_macaddr[4], mlme->im_macaddr[5]); + + //_Eric ???? + + if(mlme->im_op == IEEE80211_MLME_AUTHORIZE) + { + if (pstat == NULL){ + pstat = alloc_stainfo(priv, mlme->im_macaddr, -1); + if (pstat == NULL) { + printk("Exceed the upper limit of supported clients...\n"); + return -1; + } + pstat->state |= (WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE); + pstat->expire_to = priv->assoc_to; + asoc_list_add(priv, pstat); + } + + HAPD_Process_Set_Port(dev, mlme->im_macaddr ,DOT11_PortStatus_Authorized); + + } + else if(mlme->im_op == IEEE80211_MLME_UNAUTHORIZE) + { + if (pstat == NULL) + return -EINVAL; + + //pstat->state |= WIFI_AUTH_NULL; + + HAPD_Process_Set_Port(dev, mlme->im_macaddr ,DOT11_PortStatus_Authorized); + + } + else if(mlme->im_op == IEEE80211_MLME_DISASSOC) + { + if (pstat == NULL) + return -EINVAL; + +#ifdef WIFI_WPAS + + if(OPMODE & WIFI_STATION_STATE) + { + HAPD_MSG("An AP is disconnected by WPAS \n"); + issue_disassoc(priv, mlme->im_macaddr, _RSON_UNSPECIFIED_); + + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + } + + free_stainfo(priv, pstat); + memset(&priv->pmib->dot11Bss, 0, sizeof(struct bss_desc)); + memset(priv->pmib->dot11StationConfigEntry.dot11Bssid, 0, MACADDRLEN); + memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID)); + priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = 0; + memset(priv->pmib->dot11StationConfigEntry.dot11DefaultSSID, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID)); + priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen = 0; + memset(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan, 0, sizeof(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan)); + priv->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen = 0; + memset(priv->pmib->dot11StationConfigEntry.dot11DesiredBssid, 0, 6); + + priv->wpas_manual_assoc = 1; //_Eric ?? when to let driver auto-connect ?? + + priv->join_res = STATE_Sta_No_Bss; + //pstat->state &= (~WIFI_ASOC_STATE); + return ret; + } + +#endif + + if (asoc_list_del(priv, pstat)) + { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + } + } + + // Need change state back to autehnticated + release_stainfo(priv, pstat); + init_stainfo(priv, pstat); + pstat->state |= WIFI_AUTH_SUCCESS; + pstat->expire_to = priv->assoc_to; + auth_list_add(priv, pstat); + } + else if(mlme->im_op == IEEE80211_MLME_DEAUTH) + { + unsigned char MULTICAST_ADD[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + + if(!memcmp(mlme->im_macaddr, MULTICAST_ADD, 6)) //_Eric ??How to free all stainfo?? + return 0; + + if (pstat == NULL) + return -EINVAL; + + if (asoc_list_del(priv, pstat)) + { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + } + } + + release_stainfo(priv, pstat); + + } +#ifdef WIFI_WPAS + else if(mlme->im_op == IEEE80211_MLME_ASSOC) + { + int ix = 0, found = 0; + + if((OPMODE & WIFI_STATION_STATE) == 0) + { + HAPD_MSG("NOT in Client Mode, can NOT Associate !!!\n"); + return -1; + } + + for(ix = 0 ; ix < priv->site_survey->count_backup ; ix++) //_Eric ?? will bss_backup be cleaned?? -> Not found in codes + { + if(!memcmp(priv->site_survey->bss_backup[ix].bssid , mlme->im_macaddr, 6)) + { + found = 1; + break; + } + } + + if(found == 0) + { + printk("BSSID NOT Found !!\n"); + return -EINVAL; + } + else + ret = rtl_wpas_join(priv, ix); + + if(ret != 0) + printk("rtl_wpas_join Failed !!\n"); + + } +#endif + else + { + HAPD_MSG("unknown auth_state !!!\n"); + return -EINVAL; + } + + HAPD_MSG("rtl_net80211_setmlme ---\n"); + return ret; +} + + +int rtl_net80211_setkey(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct ieee80211req_key *wk = (struct ieee80211req_key *)wrqu->data.pointer; + struct wifi_mib *pmib = priv->pmib; + struct Dot11EncryptKey *pEncryptKey = NULL; + struct stat_info *pstat = NULL; + unsigned char MULTICAST_ADD[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; +#ifdef WIFI_WPAS + unsigned char GROUP_ADD[6]={0x0,0x0,0x0,0x0,0x0,0x0}; +#endif + int cipher =0; + int retVal = 0; + int group_key = 0; + DOT11_KEY_TYPE keyType = DOT11_KeyType_Pairwise; + + HAPD_MSG("rtl_net80211_setkey +++\n"); + + + HAPD_MSG("keyid = %d, mac = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n" + , wk->ik_keyix, wk->ik_macaddr[0], wk->ik_macaddr[1], wk->ik_macaddr[2], + wk->ik_macaddr[3], wk->ik_macaddr[4], wk->ik_macaddr[5]); + HAPD_MSG("type = 0x%x, flags = 0x%x, keylen = 0x%x \n" + , wk->ik_type, wk->ik_flags, wk->ik_keylen); + + + //check if the interface is down + if (!netif_running(priv->dev)) + { + if(wk->ik_type == IEEE80211_CIPHER_WEP) + { + HAPD_MSG("set WEP Key in driver DOWN\n"); + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[wk->ik_keyix].skey[0], wk->ik_keydata, wk->ik_keylen); + return 0; + } + + HAPD_MSG("\nFail: interface not opened\n"); + return 0; + } + + if(!memcmp(wk->ik_macaddr, MULTICAST_ADD, 6)) + group_key = 1; + +#ifdef WIFI_WPAS //_Eric ?? if oxff not group addr in wpas ?? + if(OPMODE & WIFI_STATION_STATE) + if(!memcmp(wk->ik_macaddr, GROUP_ADD, 6)) + group_key = 1; +#endif + + if (group_key) + keyType = DOT11_KeyType_Group; + + if (wk->ik_type == IEEE80211_CIPHER_WEP) + { + +#ifdef WIFI_WPAS + if(OPMODE & WIFI_STATION_STATE) + { + if(priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm == 0) + { + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[wk->ik_keyix].skey[0], wk->ik_keydata, wk->ik_keylen); + return 0; + } + } +#endif +#ifdef RTK_NL80211 + HAPD_MSG("set WEP Key for NL80211\n"); + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[wk->ik_keyix].skey[0], wk->ik_keydata, wk->ik_keylen); +#endif + if(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) + cipher = (DOT11_ENC_WEP40); + else if(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) + cipher = (DOT11_ENC_WEP104); + else + return -EINVAL; + } + else if (wk->ik_type == IEEE80211_CIPHER_TKIP) + { + cipher = (DOT11_ENC_TKIP); + } + else if(wk->ik_type == IEEE80211_CIPHER_AES_CCM) + { + cipher = (DOT11_ENC_CCMP); + } +#ifdef CONFIG_IEEE80211W + else if (wk->ik_type == IEEE80211_CIPHER_AES_CMAC) + { + cipher = DOT11_ENC_BIP; + keyType = DOT11_KeyType_IGTK; + } +#endif + else + { + HAPD_MSG("unknown encAlg !!!\n"); + return -EINVAL; + } + + //_Eric ?? if call DOT11_Process_Set_Key + //CamAddOneEntry(priv, wk->ik_macaddr, wk->ik_keyix, cipher, 0, wk->ik_keydata); + + if (keyType == DOT11_KeyType_Group) + { + int set_gkey_to_cam = 0; + HAPD_MSG("set group key !!\n"); + +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) + set_gkey_to_cam = 0; + else { + if (IS_ROOT_INTERFACE(priv)) { + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + set_gkey_to_cam = 0; + } + } +#endif + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + // No matter root or vap, don't set key to cam if vap is enabled. + set_gkey_to_cam = 0; + } +#endif + +#ifdef CONFIG_RTK_MESH + //modify by Joule for SECURITY + if (dev == priv->mesh_dev) + { + pmib->dot11sKeysTable.dot11Privacy = cipher; + pEncryptKey = &pmib->dot11sKeysTable.dot11EncryptKey; + pmib->dot11sKeysTable.keyid = (UINT)wk->ik_keyix; + } + else +#endif + { + pmib->dot11GroupKeysTable.dot11Privacy = cipher; + pEncryptKey = &pmib->dot11GroupKeysTable.dot11EncryptKey; + pmib->dot11GroupKeysTable.keyid = (UINT)wk->ik_keyix; + } + + switch(cipher) + { + case DOT11_ENC_TKIP: + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 8); +#ifdef RTK_NL80211 + if(OPMODE & WIFI_STATION_STATE) + set_tkip_key_for_wpas(pEncryptKey, wk->ik_keydata); + else +#endif + set_tkip_key(pEncryptKey, wk->ik_keydata); + + HAPD_MSG("going to set TKIP group key! id %X\n", (UINT)wk->ik_keyix); + if (!SWCRYPTO) { + if (set_gkey_to_cam) + { + retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, wk->ik_keyix, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, MULTICAST_ADD, wk->ik_keyix, DOT11_ENC_TKIP<<2, 0, wk->ik_keydata); + if (retVal) { + priv->pshare->CamEntryOccupied++; + pmib->dot11GroupKeysTable.keyInCam = TRUE; + } + } + } + break; + + case DOT11_ENC_WEP40: + set_ttkeylen(pEncryptKey, 5); + set_tmickeylen(pEncryptKey, 0); + set_wep40_key(pEncryptKey, wk->ik_keydata); + + HAPD_MSG("going to set WEP40 group key!\n"); + if (!SWCRYPTO) { + if (set_gkey_to_cam) + { + retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, wk->ik_keyix, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, MULTICAST_ADD, wk->ik_keyix, DOT11_ENC_WEP40<<2, 0, wk->ik_keydata); + if (retVal) { + priv->pshare->CamEntryOccupied++; + pmib->dot11GroupKeysTable.keyInCam = TRUE; + } + } + } + break; + + case DOT11_ENC_WEP104: + set_ttkeylen(pEncryptKey, 13); + set_tmickeylen(pEncryptKey, 0); + set_wep104_key(pEncryptKey, wk->ik_keydata); + + HAPD_MSG("going to set WEP104 group key!\n"); + if (!SWCRYPTO) { + if (set_gkey_to_cam) + { + retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, wk->ik_keyix, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, MULTICAST_ADD, wk->ik_keyix, DOT11_ENC_WEP104<<2, 0, wk->ik_keydata); + if (retVal) { + priv->pshare->CamEntryOccupied++; + pmib->dot11GroupKeysTable.keyInCam = TRUE; + } + } + } + break; + + case DOT11_ENC_CCMP: + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 16); + set_aes_key(pEncryptKey, wk->ik_keydata); + + HAPD_MSG("going to set CCMP-AES group key!\n"); +#ifdef CONFIG_RTK_MESH + if (dev == priv->mesh_dev) + pmib->dot11sKeysTable.keyInCam = TRUE; // keyInCam means key in driver + else +#endif + if (!SWCRYPTO) { + if (set_gkey_to_cam) + { + retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, wk->ik_keyix, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, MULTICAST_ADD, wk->ik_keyix, DOT11_ENC_CCMP<<2, 0, wk->ik_keydata); + if (retVal) { + priv->pshare->CamEntryOccupied++; + pmib->dot11GroupKeysTable.keyInCam = TRUE; + } + } + } + break; + + case DOT11_ENC_NONE: + default: + HAPD_MSG("No group encryption key is set!\n"); + set_ttkeylen(pEncryptKey, 0); + set_tmickeylen(pEncryptKey, 0); + break; + } + } + else if (keyType == DOT11_KeyType_Pairwise) + { + pstat = get_stainfo(priv, wk->ik_macaddr); + if (pstat == NULL) { + DEBUG_ERR("Set key failed, invalid mac address: %02x%02x%02x%02x%02x%02x\n", + wk->ik_macaddr[0], wk->ik_macaddr[1], wk->ik_macaddr[2], wk->ik_macaddr[3], + wk->ik_macaddr[4], wk->ik_macaddr[5]); + return (-1); + } + + pstat->dot11KeyMapping.dot11Privacy = cipher; + pEncryptKey = &pstat->dot11KeyMapping.dot11EncryptKey; + pstat->keyid = wk->ik_keyix; + +#if defined(__DRAYTEK_OS__) && defined(WDS) + if (pstat->state & WIFI_WDS) + priv->pmib->dot11WdsInfo.wdsPrivacy = cipher; +#endif + +#ifdef RTK_NL80211 //eric-ath + //printk(" +++ pstat->state=0x%x wps_join=%d \n", pstat->state, (pstat->state & WIFI_WPS_JOIN)); + + if(OPMODE & WIFI_STATION_STATE) + { + if(pstat->state & WIFI_WPS_JOIN) + { + //printk("REMOVE WIFI_WPS_JOIN State !!\n"); + pstat->state &= (~(WIFI_WPS_JOIN)); + } + } +#endif + + switch(cipher) + { + case DOT11_ENC_TKIP: + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 8); + +#ifdef RTK_NL80211 + if(OPMODE & WIFI_STATION_STATE) + set_tkip_key_for_wpas(pEncryptKey, wk->ik_keydata); + else +#endif + set_tkip_key(pEncryptKey, wk->ik_keydata); + + HAPD_MSG("going to set TKIP Unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", + wk->ik_macaddr[0], wk->ik_macaddr[1], wk->ik_macaddr[2], + wk->ik_macaddr[3], wk->ik_macaddr[4], wk->ik_macaddr[5], pstat->keyid); + if (!SWCRYPTO) { + retVal = CamDeleteOneEntry(priv, wk->ik_macaddr, wk->ik_keyix, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, wk->ik_macaddr, wk->ik_keyix, DOT11_ENC_TKIP<<2, 0, wk->ik_keydata); + if (retVal) { + priv->pshare->CamEntryOccupied++; + if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; + } + else { + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + break; + + case DOT11_ENC_WEP40: + set_ttkeylen(pEncryptKey, 5); + set_tmickeylen(pEncryptKey, 0); + set_wep40_key(pEncryptKey, wk->ik_keydata); + + HAPD_MSG("going to set WEP40 unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", + wk->ik_macaddr[0], wk->ik_macaddr[1], wk->ik_macaddr[2], + wk->ik_macaddr[3], wk->ik_macaddr[4], wk->ik_macaddr[5], pstat->keyid); + if (!SWCRYPTO) { + retVal = CamDeleteOneEntry(priv, wk->ik_macaddr, wk->ik_keyix, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, wk->ik_macaddr, wk->ik_keyix, DOT11_ENC_WEP40<<2, 0, wk->ik_keydata); + if (retVal) { + priv->pshare->CamEntryOccupied++; + if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; + } + else { + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + break; + + case DOT11_ENC_WEP104: + set_ttkeylen(pEncryptKey, 13); + set_tmickeylen(pEncryptKey, 0); + set_wep104_key(pEncryptKey, wk->ik_keydata); + + HAPD_MSG("going to set WEP104 unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", + wk->ik_macaddr[0], wk->ik_macaddr[1], wk->ik_macaddr[2], + wk->ik_macaddr[3], wk->ik_macaddr[4], wk->ik_macaddr[5], pstat->keyid); + if (!SWCRYPTO) { + retVal = CamDeleteOneEntry(priv, wk->ik_macaddr, wk->ik_keyix, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, wk->ik_macaddr, wk->ik_keyix, DOT11_ENC_WEP104<<2, 0, wk->ik_keydata); + if (retVal) { + priv->pshare->CamEntryOccupied++; + if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; + } + else { + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + break; + + case DOT11_ENC_CCMP: + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 16); + set_aes_key(pEncryptKey, wk->ik_keydata); + + HAPD_MSG("going to set CCMP-AES unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", + wk->ik_macaddr[0], wk->ik_macaddr[1], wk->ik_macaddr[2], + wk->ik_macaddr[3], wk->ik_macaddr[4], wk->ik_macaddr[5], pstat->keyid); + if (!SWCRYPTO) { + retVal = CamDeleteOneEntry(priv, wk->ik_macaddr, wk->ik_keyix, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, wk->ik_macaddr, wk->ik_keyix, DOT11_ENC_CCMP<<2, 0, wk->ik_keydata); + if (retVal) { + HAPD_MSG("CamAddOneEntry of CCMP OK\n"); + priv->pshare->CamEntryOccupied++; + if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; + assign_aggre_mthod(priv, pstat); + } + else { + HAPD_MSG("CamAddOneEntry of CCMP FAIL\n"); + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + break; + + case DOT11_ENC_NONE: + default: + DEBUG_ERR("No pairewise encryption key is set!\n"); + set_ttkeylen(pEncryptKey, 0); + set_tmickeylen(pEncryptKey, 0); + break; + } + } +#ifdef CONFIG_IEEE80211W + else if (keyType == DOT11_KeyType_IGTK) + { + HAPD_MSG("going to set BIP group key!\n"); + pmib->dot11IGTKTable.dot11Privacy = cipher; + pEncryptKey = &pmib->dot11IGTKTable.dot11EncryptKey; + pmib->dot11IGTKTable.keyid = wk->ik_keyix; + + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 16); + set_aes_key(pEncryptKey, wk->ik_keydata); + } +#endif + else + { + HAPD_MSG("keyType(%d) not support\n", keyType); + } + + HAPD_MSG("rtl_net80211_setkey ---\n"); + + return 0; +} + +int rtl_net80211_delkey(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + +#ifdef RTK_NL80211 + struct ieee80211req_del_key *wk = (struct ieee80211req_del_key *)wrqu->data.pointer; +#else + struct ieee80211req_del_key *wk = (struct ieee80211req_del_key *)wrqu->name; +#endif + struct stat_info *pstat = NULL; + struct wifi_mib *pmib = priv->pmib; + + unsigned char MULTICAST_ADD[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int ret = 0; + + //check if the interface is down + if (!netif_running(priv->dev)) + { + HAPD_MSG("\nFail: interface not opened\n"); + return 0; + } + + HAPD_MSG("rtl_net80211_delkey +++ \n"); + HAPD_MSG("keyid = %d, mac = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n" + , wk->idk_keyix, wk->idk_macaddr[0], wk->idk_macaddr[1], wk->idk_macaddr[2], + wk->idk_macaddr[3], wk->idk_macaddr[4], wk->idk_macaddr[5]); + + if(!memcmp(wk->idk_macaddr, "\x00\x00\x00\x00\x00\x00", 6)) + { + HAPD_MSG("reset ALL key !!!!!\n"); + CamResetAllEntry(priv); + } + + if (!memcmp(wk->idk_macaddr, MULTICAST_ADD, 6)) + { + pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen = 0; + pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKeyLen = 0; + + HAPD_MSG("Delete Group Key\n"); + if (CamDeleteOneEntry(priv, MULTICAST_ADD, 1, 0)) + priv->pshare->CamEntryOccupied--; + #if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + if (CamDeleteOneEntry(priv, MULTICAST_ADD, 1, 0)) + priv->pshare->CamEntryOccupied--; + #endif + + } + else + { + pstat = get_stainfo(priv, (UINT8 *)wk->idk_macaddr); + if (pstat == NULL) + return (-1); + + pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen = 0; + pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKeyLen = 0; + + HAPD_MSG("Delete Unicast Key\n"); + if (pstat->dot11KeyMapping.keyInCam == TRUE) { + if (CamDeleteOneEntry(priv, (unsigned char *)wk->idk_macaddr, 0, 0)) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + #if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + if (CamDeleteOneEntry(priv, (unsigned char *)wk->idk_macaddr, 0, 0)) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + #endif + } + } + + HAPD_MSG("rtl_net80211_delkey --- \n"); + + return ret; + + +} + +int rtl_net80211_getwpaie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct ieee80211req_wpaie *ie = (struct ieee80211req_wpaie *)wrqu->data.pointer; + struct stat_info *pstat = get_stainfo(priv, ie->wpa_macaddr); + int ret = 0; + HAPD_MSG("rtl_net80211_getwpaie +++ \n"); + HAPD_MSG("mac = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", + ie->wpa_macaddr[0], ie->wpa_macaddr[1], ie->wpa_macaddr[2], + ie->wpa_macaddr[3], ie->wpa_macaddr[4], ie->wpa_macaddr[5]); + + if(pstat == NULL) + return -EINVAL; + +#ifndef HAPD_DRV_PSK_WPS + HAPD_MSG("RSNEnabled = %d\n" + "wpa_ie = 0x%02x 0x%02x 0x%02x \n" + "wps_ie = 0x%02x 0x%02x 0x%02x \n" + ,pstat->wpa_sta_info->RSNEnabled, + pstat->wpa_ie[0], pstat->wpa_ie[1], pstat->wpa_ie[2], + pstat->wps_ie[0], pstat->wps_ie[1], pstat->wps_ie[2] + ); +#else + HAPD_MSG("RSNEnabled = %d\n" + "wpa_ie = 0x%02x 0x%02x 0x%02x \n" + ,pstat->wpa_sta_info->RSNEnabled, + pstat->wpa_ie[0], pstat->wpa_ie[1], pstat->wpa_ie[2] + ); +#endif + + if(pstat->wpa_sta_info->RSNEnabled & BIT(0)) + memcpy(ie->wpa_ie, pstat->wpa_ie, pstat->wpa_ie[1]+2); + else if(pstat->wpa_sta_info->RSNEnabled & BIT(1)) + memcpy(ie->rsn_ie, pstat->wpa_ie, pstat->wpa_ie[1]+2); + +#ifndef HAPD_DRV_PSK_WPS + if((priv->pmib->wscEntry.wsc_enable & 2) && (pstat->wps_ie[1])) + memcpy(ie->wps_ie, pstat->wps_ie, pstat->wps_ie[1]+2); +#endif + + HAPD_MSG("rtl_net80211_getwpaie --- \n"); + return ret; + +} + + +#if ((defined(WIFI_HAPD) || defined(RTK_NL80211)) && defined(WDS)) && !defined(HAPD_DRV_PSK_WPS) +int rtl_net80211_wdsaddmac(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct rtk_wds_config *wds = (struct hapd_wds_info *)wrqu->data.pointer; + int ret = 0; + int num = 0; + + HAPD_MSG("rtl_net80211_wdsaddmac +++ \n"); + + if(wds->wdsEnabled == 0) + goto bad; + if(wds->wdsNum > NUM_WDS) + goto bad; + if( (wds->wdsPrivacy != _NO_PRIVACY_) && (wds->wdsPrivacy != _WEP_40_PRIVACY_) && + (wds->wdsPrivacy != _TKIP_PRIVACY_) && (wds->wdsPrivacy != _CCMP_PRIVACY_) && + (wds->wdsPrivacy != _WEP_104_PRIVACY_)) + goto bad; + + if((wds->wdsPrivacy == _WEP_40_PRIVACY_) && (wds->wdsWepKeyLen != 5)) + goto bad; + if((wds->wdsPrivacy == _WEP_104_PRIVACY_) && (wds->wdsWepKeyLen != 13)) + goto bad; + + priv->pmib->dot11WdsInfo.wdsEnabled = 1; + priv->pmib->dot11WdsInfo.wdsNum = wds->wdsNum; + + for(num=0 ; num < wds->wdsNum; num++) + memcpy(priv->pmib->dot11WdsInfo.entry[num].macAddr, wds->macAddr[num], MACADDRLEN); + + priv->pmib->dot11WdsInfo.wdsPrivacy = wds->wdsPrivacy; + + if((wds->wdsPrivacy == _WEP_40_PRIVACY_)||(wds->wdsPrivacy == _WEP_104_PRIVACY_)) + memcpy(priv->pmib->dot11WdsInfo.wdsWepKey, wds->wdsWepKey, wds->wdsWepKeyLen); + else if((wds->wdsPrivacy == _TKIP_PRIVACY_)||(wds->wdsPrivacy == _CCMP_PRIVACY_)) + hapd_set_wdskey(dev, wds->wdsPskPassPhrase, wds->ssid, wds->wdsNum); + + + HAPD_MSG("rtl_net80211_wdsaddmac --- \n"); + return 0; + +bad: + priv->pmib->dot11WdsInfo.wdsEnabled = 0; + return -EINVAL; + + +} + +int rtl_net80211_wdsdelmac(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct rtk_wds_config *wds = (struct rtk_wds_config *)wrqu->data.pointer; + HAPD_MSG("rtl_net80211_wdsdelmac +++ \n"); + + priv->pmib->dot11WdsInfo.wdsEnabled = 0; + priv->pmib->dot11WdsInfo.wdsNum = 0; + + HAPD_MSG("rtl_net80211_wdsdelmac --- \n"); + return 0; +} +#endif + + +int rtl_hapd_config(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct rtk_hapd_config *config = (struct rtk_hapd_config *)wrqu->data.pointer; + int size = 0; + + HAPD_MSG("rtl_hapd_config +++\n"); + + priv->pmib->dot11BssType.net_work_type = config->band; + priv->pmib->dot11RFEntry.dot11channel = config->channel; + priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod = config->bcnint; + priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod = config->dtimperiod; + + if(config->stanum <= NUM_STAT) + priv->pmib->dot11StationConfigEntry.supportedStaNum = config->stanum; + else + { + HAPD_MSG("Invalid Station Number!!!\n"); + return -1; + } + + priv->pmib->dot11OperationEntry.dot11RTSThreshold = config->rtsthres; + priv->pmib->dot11OperationEntry.dot11FragmentationThreshold = config->fragthres; + priv->pmib->dot11StationConfigEntry.dot11SupportedRates = config->oprates; + priv->pmib->dot11StationConfigEntry.dot11BasicRates = config->basicrates; + priv->pmib->dot11RFEntry.shortpreamble = config->preamble; + priv->pmib->dot11StationConfigEntry.dot11AclMode = config->aclmode; + priv->pmib->dot11StationConfigEntry.dot11AclNum = config->aclnum; + + size = sizeof(priv->pmib->dot11StationConfigEntry.dot11AclAddr); + memcpy(priv->pmib->dot11StationConfigEntry.dot11AclAddr, config->acladdr, size); + + priv->pmib->dot11OperationEntry.hiddenAP = config->hiddenAP; +#ifdef WIFI_WMM + priv->pmib->dot11QosEntry.dot11QosEnable = config->qos_enable; +#endif + priv->pmib->dot11OperationEntry.expiretime = config->expired_time * 100; // 10ms unit vs 1s unit + priv->pmib->dot11OperationEntry.block_relay = config->block_relay; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = config->shortGI20M; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = config->shortGI40M; + + +//Above are for Hostapd owned configurations +//===================================================== +//Below are for RTK private configurations + + size = sizeof(priv->pmib->dot11RFEntry.pwrlevelCCK_A); + memcpy(priv->pmib->dot11RFEntry.pwrlevelCCK_A, config->pwrlevelCCK_A, size); + + size = sizeof(priv->pmib->dot11RFEntry.pwrlevelCCK_B); + memcpy(priv->pmib->dot11RFEntry.pwrlevelCCK_B, config->pwrlevelCCK_B, size); + + size = sizeof(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A); + memcpy(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A, config->pwrlevelHT40_1S_A, size); + + size = sizeof(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B); + memcpy(priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B, config->pwrlevelHT40_1S_A, size); + + size = sizeof(priv->pmib->dot11RFEntry.pwrdiffHT40_2S); + memcpy(priv->pmib->dot11RFEntry.pwrdiffHT40_2S, config->pwrdiffHT40_2S, size); + + size = sizeof(priv->pmib->dot11RFEntry.pwrdiffHT20); + memcpy(priv->pmib->dot11RFEntry.pwrdiffHT20, config->pwrdiffHT20, size); + + size = sizeof(priv->pmib->dot11RFEntry.pwrdiffOFDM); + memcpy(priv->pmib->dot11RFEntry.pwrdiffOFDM, config->pwrdiffOFDM, size); + + priv->pmib->dot11RFEntry.ther = config->ther; + +#ifdef CONFIG_RTL_92D_SUPPORT + priv->pmib->dot11RFEntry.phyBandSelect = config->phyBandSelect; +#endif + + priv->pmib->dot11StationConfigEntry.dot11swcrypto = config->swcrypto; + priv->pmib->dot11StationConfigEntry.dot11RegDomain = config->regdomain; + priv->pmib->dot11StationConfigEntry.autoRate = config->autorate; + priv->pmib->dot11StationConfigEntry.fixedTxRate = config->fixrate; + priv->pmib->dot11StationConfigEntry.protectionDisabled = config->disable_protection; + priv->pmib->dot11StationConfigEntry.olbcDetectDisabled = config->disable_olbc; + priv->pmib->dot11StationConfigEntry.legacySTADeny = config->deny_legacy; + priv->pmib->dot11OperationEntry.opmode = config->opmode; + priv->pmib->dot11nConfigEntry.dot11nUse40M = config->use40M; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = config->_2ndchoffset; + priv->pmib->dot11nConfigEntry.dot11nAMPDU = config->ampdu; + priv->pmib->dot11OperationEntry.guest_access = config->guest_access; + + priv->pmib->dot11RFEntry.macPhyMode = config->macPhyMode; + +#ifdef WIFI_11N_2040_COEXIST + priv->pmib->dot11nConfigEntry.dot11nCoexist = config->coexist; +#endif + +#ifdef MBSSID + priv->pmib->miscEntry.vap_enable = config->vap_enable; +#endif + + priv->pshare->rf_ft_var.rssi_dump = config->rssi_dump; + +#ifdef MP_TEST + priv->pshare->rf_ft_var.mp_specific = config->mp_specific; +#endif + +#ifdef HIGH_POWER_EXT_PA + priv->pshare->rf_ft_var.use_ext_pa = config->use_ext_pa; +#endif + + HAPD_MSG("rtl_hapd_config ---\n"); + return 0; +} + + + +#ifdef WIFI_WPAS + +int rtl_wpas_config_2G(struct rtl8192cd_priv *priv) +{ + HAPD_MSG("wpas config wlan 2.4G\n"); + + priv->pmib->dot11BssType.net_work_type = 1 + 2 + 8; + priv->pmib->dot11RFEntry.dot11channel = 11; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = 1; + priv->pmib->dot11StationConfigEntry.autoRate = 1; + priv->pmib->dot11nConfigEntry.dot11nUse40M = 1; + priv->pmib->dot11nConfigEntry.dot11nAMPDU = 1; + //priv->pmib->dot11RFEntry.macPhyMode = DUALMAC_DUALPHY; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW; + priv->pmib->dot11StationConfigEntry.dot11SupportedRates = 0xfff; + priv->pmib->dot11StationConfigEntry.dot11BasicRates = 0xf; + priv->pmib->dot11OperationEntry.wifi_specific = 2; //_Eric ?? + + priv->pmib->dot11OperationEntry.dot11FragmentationThreshold = 2346; + +#ifdef CONFIG_RTL_92D_SUPPORT + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; +#endif + +#ifdef WIFI_WMM + priv->pmib->dot11QosEntry.dot11QosEnable = 1; +#endif + +} + +int rtl_wpas_config_5G(struct rtl8192cd_priv *priv) +{ + printk("wpas config wlan 5G\n"); + + priv->pmib->dot11BssType.net_work_type = 4 + 8; + priv->pmib->dot11RFEntry.dot11channel = 44; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M = 1; + priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M = 1; + priv->pmib->dot11StationConfigEntry.autoRate = 1; + priv->pmib->dot11nConfigEntry.dot11nUse40M = 1; + priv->pmib->dot11nConfigEntry.dot11nAMPDU = 1; + //priv->pmib->dot11RFEntry.macPhyMode = DUALMAC_DUALPHY; //_Eric ?? How to judge ?? + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE; + priv->pmib->dot11StationConfigEntry.dot11SupportedRates = 0xff0; + priv->pmib->dot11StationConfigEntry.dot11BasicRates = 0xff0; + priv->pmib->dot11OperationEntry.wifi_specific = 2; + + priv->pmib->dot11OperationEntry.dot11FragmentationThreshold = 2346; + +#ifdef CONFIG_RTL_92D_SUPPORT + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; +#endif + +#ifdef WIFI_WMM + priv->pmib->dot11QosEntry.dot11QosEnable = 1; +#endif + +} + + +int rtl_wpas_config(struct rtl8192cd_priv *priv, unsigned char bandmode, unsigned char phymode) +{ + HAPD_MSG("wpas config interface: %s\n", priv->dev->name); + + priv->pmib->dot11OperationEntry.opmode = WIFI_STATION_STATE; + + if(bandmode == SINGLEMAC_SINGLEPHY) + { + priv->pmib->dot11RFEntry.macPhyMode = SINGLEMAC_SINGLEPHY; + + if(phymode == PHY_BAND_5G) + rtl_wpas_config_5G(priv); + else if(phymode == PHY_BAND_2G) + rtl_wpas_config_2G(priv); + else + return -1; + + } +#if defined(CUSTOMIZE_WLAN_IF_NAME) + else if(!strcmp(priv->dev->name, ROOT_IFNAME_5G)) +#else + else if(!strcmp(priv->dev->name, "wlan0")) +#endif + { + priv->pmib->dot11RFEntry.macPhyMode = DUALMAC_DUALPHY; + rtl_wpas_config_5G(priv); + } +#if defined(CUSTOMIZE_WLAN_IF_NAME) + else if(!strcmp(priv->dev->name, ROOT_IFNAME_2G)) +#else + else if(!strcmp(priv->dev->name, "wlan1")) +#endif + { + priv->pmib->dot11RFEntry.macPhyMode = DUALMAC_DUALPHY; + rtl_wpas_config_2G(priv); + } + else + return -1; + + return 0; + + +} + + +int rtl_wpas_custom(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct rtk_wpas_config *config = (struct rtk_wpas_config *)wrqu->data.pointer; + + int ret = 0; + + switch (config->type) { + case WPAS_CONFIG_MIB: + HAPD_MSG("bandmode %d phymode %d \n", config->bandmode, config->phymode); + if((config->bandmode == SINGLEMAC_SINGLEPHY) || (config->bandmode == DUALMAC_DUALPHY)) + ret = rtl_wpas_config(priv, config->bandmode, config->phymode); + else + return -EINVAL; + break; + case WPAS_CONFIG_WEPKEY: + HAPD_MSG("WPAS_CONFIG_WEPKEY !!! \n"); + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[config->wep_keyidx].skey[0], config->wep_key, config->wep_keylen); + break; + + } + + return ret; + +} +#endif + +static void Construct_RSNIE(struct rtl8192cd_priv *priv, unsigned char *pucOut, int *usOutLen) +{ + DOT11_RSN_IE_HEADER dot11RSNIEHeader = { 0 }; + DOT11_RSN_IE_SUITE dot11RSNGroupSuite; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNPairwiseSuite = NULL; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNAuthSuite = NULL; + unsigned short usSuitCount; + unsigned long ulIELength = 0; + unsigned long ulIndex = 0; + unsigned long ulPairwiseLength = 0; + unsigned long ulAuthLength = 0; + unsigned char *pucBlob; + DOT11_RSN_IE_COUNT_SUITE countSuite, authCountSuite; +#ifdef RTL_WPA2 + DOT11_RSN_CAPABILITY dot11RSNCapability = { 0 }; + unsigned long uCipherAlgo = 0; + int bCipherAlgoEnabled = FALSE; + unsigned long uAuthAlgo = 0; + int bAuthAlgoEnabled = FALSE; + unsigned long ulRSNCapabilityLength = 0; +#endif + + *usOutLen = 0; + if ( priv->pmib->dot1180211AuthEntry.dot11WPACipher != 0 ) { + // + // Construct Information Header + // + dot11RSNIEHeader.ElementID = RSN_ELEMENT_ID; + dot11RSNIEHeader.OUI[0] = 0x00; + dot11RSNIEHeader.OUI[1] = 0x50; + dot11RSNIEHeader.OUI[2] = 0xf2; + dot11RSNIEHeader.OUI[3] = 0x01; + dot11RSNIEHeader.Version = cpu_to_le16(RSN_VER1); + ulIELength += sizeof(DOT11_RSN_IE_HEADER); + + // Construct Cipher Suite: + // - Multicast Suite: + memset(&dot11RSNGroupSuite, 0, sizeof dot11RSNGroupSuite); + dot11RSNGroupSuite.OUI[0] = 0x00; + dot11RSNGroupSuite.OUI[1] = 0x50; + dot11RSNGroupSuite.OUI[2] = 0xF2; + dot11RSNGroupSuite.Type = priv->wpa_global_info->MulticastCipher; + ulIELength += sizeof(DOT11_RSN_IE_SUITE); + + // - UnicastSuite + pDot11RSNPairwiseSuite = &countSuite; + memset(pDot11RSNPairwiseSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + +#ifdef RTK_NL80211 + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipher; ulIndex++) + { + int i = ulIndexwpa_global_info->NumOfUnicastCipher - ulIndex - 1; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipher[i]; + usSuitCount++; + } +#else + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipher; ulIndex++) + { + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipher[ulIndex]; + usSuitCount++; + } +#endif + + pDot11RSNPairwiseSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulPairwiseLength = sizeof(pDot11RSNPairwiseSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulPairwiseLength; + + // + // Construction of Auth Algo List + // + pDot11RSNAuthSuite = &authCountSuite; + memset(pDot11RSNAuthSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_RSN; + usSuitCount++; + + pDot11RSNAuthSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulAuthLength = sizeof(pDot11RSNAuthSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulAuthLength; + + pucBlob = pucOut; + pucBlob += sizeof(DOT11_RSN_IE_HEADER); + memcpy(pucBlob, &dot11RSNGroupSuite, sizeof(DOT11_RSN_IE_SUITE)); + pucBlob += sizeof(DOT11_RSN_IE_SUITE); + memcpy(pucBlob, pDot11RSNPairwiseSuite, ulPairwiseLength); + pucBlob += ulPairwiseLength; + memcpy(pucBlob, pDot11RSNAuthSuite, ulAuthLength); + pucBlob += ulAuthLength; + + *usOutLen = (int)ulIELength; + pucBlob = pucOut; + dot11RSNIEHeader.Length = (unsigned char)ulIELength - 2; //This -2 is to minus elementID and Length in OUI header + memcpy(pucBlob, &dot11RSNIEHeader, sizeof(DOT11_RSN_IE_HEADER)); + } + +#ifdef RTL_WPA2 + if ( priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher != 0 ) { + DOT11_WPA2_IE_HEADER dot11WPA2IEHeader = { 0 }; + ulIELength = 0; + ulIndex = 0; + ulPairwiseLength = 0; + uCipherAlgo = 0; + bCipherAlgoEnabled = FALSE; + ulAuthLength = 0; + uAuthAlgo = 0; + bAuthAlgoEnabled = FALSE; + ulRSNCapabilityLength = 0; + + // + // Construct Information Header + // + dot11WPA2IEHeader.ElementID = WPA2_ELEMENT_ID; + dot11WPA2IEHeader.Version = cpu_to_le16(RSN_VER1); + ulIELength += sizeof(DOT11_WPA2_IE_HEADER); + + // Construct Cipher Suite: + // - Multicast Suite: + // + memset(&dot11RSNGroupSuite, 0, sizeof(dot11RSNGroupSuite)); + dot11RSNGroupSuite.OUI[0] = 0x00; + dot11RSNGroupSuite.OUI[1] = 0x0F; + dot11RSNGroupSuite.OUI[2] = 0xAC; + dot11RSNGroupSuite.Type = priv->wpa_global_info->MulticastCipher;; + ulIELength += sizeof(DOT11_RSN_IE_SUITE); + + // - UnicastSuite + pDot11RSNPairwiseSuite = &countSuite; + memset(pDot11RSNPairwiseSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + +#ifdef RTK_NL80211 + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipherWPA2; ulIndex++) + { + int i = priv->wpa_global_info->NumOfUnicastCipherWPA2 - ulIndex - 1; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipherWPA2[i]; + usSuitCount++; + } +#else + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipherWPA2; ulIndex++) + { + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipherWPA2[ulIndex]; + usSuitCount++; + } +#endif + + pDot11RSNPairwiseSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulPairwiseLength = sizeof(pDot11RSNPairwiseSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulPairwiseLength; + + // + // Construction of Auth Algo List + // + pDot11RSNAuthSuite = &authCountSuite; + memset(pDot11RSNAuthSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_RSN; + usSuitCount++; + + pDot11RSNAuthSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulAuthLength = sizeof(pDot11RSNAuthSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulAuthLength; + + //--------------------------------------------------------------------------------------------- + // Do not encapsulate capability field to solve TI WPA issue + //--------------------------------------------------------------------------------------------- + + dot11RSNCapability.field.PreAuthentication = 0; + + ulRSNCapabilityLength = sizeof(DOT11_RSN_CAPABILITY); + ulIELength += ulRSNCapabilityLength; + +#if (defined(WIFI_HAPD) & defined(WIFI_WMM)) || (defined(RTK_NL80211) & defined(WIFI_WMM)) //eric-eap + if(QOS_ENABLE){ + /* 4 PTKSA replay counters when using WMM consistent with hostapd code*/ + dot11RSNCapability.field.PtksaReplayCounter = 3; + } +#endif + + pucBlob = pucOut + *usOutLen; + pucBlob += sizeof(DOT11_WPA2_IE_HEADER); + memcpy(pucBlob, &dot11RSNGroupSuite, sizeof(DOT11_RSN_IE_SUITE)); + pucBlob += sizeof(DOT11_RSN_IE_SUITE); + memcpy(pucBlob, pDot11RSNPairwiseSuite, ulPairwiseLength); + pucBlob += ulPairwiseLength; + memcpy(pucBlob, pDot11RSNAuthSuite, ulAuthLength); + pucBlob += ulAuthLength; + memcpy(pucBlob, &dot11RSNCapability, ulRSNCapabilityLength); + + pucBlob = pucOut + *usOutLen; + dot11WPA2IEHeader.Length = (unsigned char)ulIELength - 2; //This -2 is to minus elementID and Length in OUI header + memcpy(pucBlob, &dot11WPA2IEHeader, sizeof(DOT11_WPA2_IE_HEADER)); + *usOutLen = *usOutLen + (int)ulIELength; + } +#endif // RTL_WPA2 + +} + + +static void ToDrv_SetRSNIE(struct rtl8192cd_priv *priv) +{ + struct iw_point wrq; + DOT11_SET_RSNIE Set_Rsnie; + + + debug_out("RSN: Set RSNIE", priv->wpa_global_info->AuthInfoElement.Octet, + priv->wpa_global_info->AuthInfoElement.Length); + + + wrq.pointer = (caddr_t)&Set_Rsnie; + wrq.length = sizeof(DOT11_SET_RSNIE); + Set_Rsnie.EventId = DOT11_EVENT_SET_RSNIE; + Set_Rsnie.IsMoreEvent = FALSE; + Set_Rsnie.Flag = DOT11_Ioctl_Set; + Set_Rsnie.RSNIELen = priv->wpa_global_info->AuthInfoElement.Length; + memcpy(&Set_Rsnie.RSNIE, + priv->wpa_global_info->AuthInfoElement.Octet, + priv->wpa_global_info->AuthInfoElement.Length); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + + +void rsn_init(struct rtl8192cd_priv *priv) +{ + WPA_GLOBAL_INFO *pGblInfo=priv->wpa_global_info; + int i, j, low_cipher=0; + + DEBUG_TRACE; + + HAPD_MSG("rsn_init\n"); + + memset((char *)pGblInfo, '\0', sizeof(WPA_GLOBAL_INFO)); + + if (priv->pmib->dot1180211AuthEntry.dot11WPACipher) { + for (i=0, j=0; i<_WEP_104_PRIVACY_; i++) { + if (priv->pmib->dot1180211AuthEntry.dot11WPACipher & (1<UnicastCipher[j] = i+1; + if (low_cipher == 0) + low_cipher = pGblInfo->UnicastCipher[j]; + else { + if (low_cipher == _WEP_104_PRIVACY_ && + pGblInfo->UnicastCipher[j] == _WEP_40_PRIVACY_) + low_cipher = pGblInfo->UnicastCipher[j]; + else if (low_cipher == _TKIP_PRIVACY_ && + (pGblInfo->UnicastCipher[j] == _WEP_40_PRIVACY_ || + pGblInfo->UnicastCipher[j] == _WEP_104_PRIVACY_)) + low_cipher = pGblInfo->UnicastCipher[j]; + else if (low_cipher == _CCMP_PRIVACY_) + low_cipher = pGblInfo->UnicastCipher[j]; + } + if (++j >= MAX_UNICAST_CIPHER) + break; + } + } + pGblInfo->NumOfUnicastCipher = j; + } + +#ifdef RTL_WPA2 + if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher) { + for (i=0, j=0; i<_WEP_104_PRIVACY_; i++) { + if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher & (1<UnicastCipherWPA2[j] = i+1; + if (low_cipher == 0) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + else { + if (low_cipher == _WEP_104_PRIVACY_ && + pGblInfo->UnicastCipherWPA2[j] == _WEP_40_PRIVACY_) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + else if (low_cipher == _TKIP_PRIVACY_ && + (pGblInfo->UnicastCipherWPA2[j] == _WEP_40_PRIVACY_ || + pGblInfo->UnicastCipherWPA2[j] == _WEP_104_PRIVACY_)) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + else if (low_cipher == _CCMP_PRIVACY_) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + } + if (++j >= MAX_UNICAST_CIPHER) + break; + } + } + pGblInfo->NumOfUnicastCipherWPA2= j; + } +#endif + + pGblInfo->MulticastCipher = low_cipher; + + HAPD_MSG("RSN: WPA unicast cipher= "); + for (i=0; iNumOfUnicastCipher; i++) + HAPD_MSG("%x ", pGblInfo->UnicastCipher[i]); + HAPD_MSG("\n"); + +#ifdef RTL_WPA2 + HAPD_MSG("RSN: WPA2 unicast cipher= "); + for (i=0; iNumOfUnicastCipherWPA2; i++) + HAPD_MSG("%x ", pGblInfo->UnicastCipherWPA2[i]); + HAPD_MSG("\n"); +#endif + + HAPD_MSG("RSN: multicast cipher= %x\n", pGblInfo->MulticastCipher); + + + pGblInfo->AuthInfoElement.Octet = pGblInfo->AuthInfoBuf; + + Construct_RSNIE(priv, pGblInfo->AuthInfoElement.Octet, + &pGblInfo->AuthInfoElement.Length); + + ToDrv_SetRSNIE(priv); +} + +#endif //WIFI_HAPD diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_net80211.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_net80211.h new file mode 100755 index 000000000..b2899c982 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_net80211.h @@ -0,0 +1,43 @@ +/* + * Header file for Net80211-compatible handling routines + * + * + * + * Copyright (c) 2010 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + + +#ifndef _8192CD_NET80211_H_ +#define _8192CD_NET80211_H_ + +#include + + +#define MAX_CONFIG_FILE_SIZE (20*1024) // for 8192, added to 20k +#define MAX_PARAM_BUF_SIZE (1024) // for 8192, added to 20k + +#ifdef RTK_NL80211 +#define RTK_CIPHER_PTK 1 +#define RTK_CIPHER_GTK 2 +#define RTK_CIPHER_IGTK 4 +#endif + + int rtl_net80211_setparam(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + int rtl_net80211_setappiebuf(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + int rtl_net80211_setmlme(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + int rtl_net80211_setkey(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + int rtl_net80211_delkey(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + int rtl_net80211_wdsaddmac(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + int rtl_net80211_wdsdelmac(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + int rtl_net80211_getwpaie(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + int rtl_hapd_config(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); + void rsn_init(struct rtl8192cd_priv *priv); +#if defined(RTK_NL80211) + int rtl_wpas_join(struct rtl8192cd_priv *priv, int bss_num); +#endif + +#endif diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_osdep.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_osdep.c new file mode 100755 index 000000000..f07a6e9ce --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_osdep.c @@ -0,0 +1,13374 @@ +/* + * Routines to handle OS dependent jobs and interfaces + * + * $Id: 8192cd_osdep.c,v 1.61.2.28 2011/01/11 13:48:37 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_OSDEP_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#ifdef __DRAYTEK_OS__ +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#ifdef _BROADLIGHT_FASTPATH_ +int (*send_packet_to_upper_layer)(struct sk_buff *skb) = netif_rx ; +#endif +#ifdef __KERNEL__ +#ifdef __LINUX_2_6__ +#include +#include +#include +#endif + +#ifdef CONFIG_RTL_PROC_NEW +#include +#endif + +#if defined(RTK_BR_EXT) || defined(BR_SHORTCUT) +#ifdef __LINUX_2_6__ +#include +#else +#include +#endif +#endif +#elif defined(__ECOS) +#include +#include +#include +#include +#include +#ifdef CONFIG_RTL_REPORT_LINK_STATUS +#include +#endif +#ifdef CONFIG_SDIO_HCI +#include +#endif +#else +#include "./sys-support.h" +#endif + +#include "./8192cd.h" +#include "./8192cd_hw.h" +#include "./8192cd_headers.h" +#include "./8192cd_rx.h" +#include "./8192cd_debug.h" + +#ifdef RTL8192CD_VARIABLE_USED_DMEM +#include "./8192cd_dmem.h" +#endif +#ifdef CONFIG_RTL_VLAN_8021Q +#include +extern int linux_vlan_enable; +#endif + +#ifdef CONFIG_RTL_92D_DMDP +u32 if_priv[NUM_WLAN_IFACE]; +#ifdef NOT_RTK_BSP +static int rtl8192D_idx=0; +#endif +#endif + +#ifdef CONFIG_RTK_MESH +#include "../mesh_ext/mesh_route.h" // Note : Not include in #ifdef CONFIG_RTK_MESH, Because use in wlan_device[] +#include "../mesh_ext/mesh_util.h" +#endif // CONFIG_RTK_MESH + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +#include +#endif + +#ifndef CONFIG_RTK_MESH //move below from mesh_route.h ; plus 0119 +#define MESH_SHIFT 0 +#define MESH_NUM_CFG 0 +#else +#define MESH_SHIFT 8 // ACCESS_MASK uses 2 bits, WDS_MASK use 4 bits +#define MESH_MASK 0x3 +#define MESH_NUM_CFG NUM_MESH +#endif + + +#if defined(CONFIG_RTL_8198) +#define CONFIG_RTL8198_REVISION_B 1 +//#define CONFIG_PHY_EAT_40MHZ 1 +#endif +#ifdef CONFIG_RTL8672 + #ifdef USE_RLX_BSP + #include + #include + + #ifdef CONFIG_RTL_8196C + #undef CONFIG_RTL_8196C + #endif + #ifdef CONFIG_RTL8196C_REVISION_B + #undef CONFIG_RTL8196C_REVISION_B + #endif + #else + #include + #include "../../../arch/mips/realtek/rtl8672/gpio.h" + #endif +#else + #if !defined(CONFIG_NET_PCI) && defined(CONFIG_RTL8196B) + #include + #endif + + #if !defined(CONFIG_NET_PCI) && defined(CONFIG_RTL8196C) + #ifdef __KERNEL__ + #include + #endif + #endif +#endif + +#if defined(CONFIG_RTL_819X) && defined(__LINUX_2_6__) +#if !defined(USE_RLX_BSP) +#ifndef __ECOS +#include +#endif +#else +#if defined(CONFIG_OPENWRT_SDK) && !defined(CONFIG_ARCH_CPU_RLX) +#include +#else +#include +#endif //CONFIG_OPENWRT_SDK +#endif +#endif + +#if defined(CONFIG_RTL_WAPI_SUPPORT) +#include "wapiCrypto.h" +#endif +#ifdef CONFIG_RTL_CUSTOM_PASSTHRU //mark_test +#ifdef __KERNEL__ +#include +#endif +#endif +#if defined(CONFIG_WIRELESS_LAN_MODULE) && !defined(NOT_RTK_BSP) +extern int (*wirelessnet_hook)(void); +#ifdef BR_SHORTCUT +extern struct net_device* (*wirelessnet_hook_shortcut)(unsigned char *da); +#endif +#ifdef PERF_DUMP +extern int rtl8651_romeperfEnterPoint(unsigned int index); +extern int rtl8651_romeperfExitPoint(unsigned int index); +extern int (*Fn_rtl8651_romeperfEnterPoint)(unsigned int index); +extern int (*Fn_rtl8651_romeperfExitPoint)(unsigned int index); +#endif +#ifdef CONFIG_RTL8190_PRIV_SKB +extern int (*wirelessnet_hook_is_priv_buf)(void); +extern void (*wirelessnet_hook_free_priv_buf)(unsigned char *head); +#endif +#endif // CONFIG_WIRELESS_LAN_MODULE + +#if defined(WIFI_HAPD) || defined (RTK_NL80211) +#include "8192cd_net80211.h" +#endif + +#ifdef RTK_NL80211 +#include "8192cd_cfg80211.h" +#endif + +#ifdef BR_SHORTCUT +#ifdef CLIENT_MODE +extern unsigned char cached_sta_mac[MAX_REPEATER_SC_NUM][MACADDRLEN]; +extern struct net_device *cached_sta_dev[MAX_REPEATER_SC_NUM]; +#endif + +#ifdef RTL_CACHED_BR_STA +extern struct brsc_cache_t brsc_cache_arr[MAX_BRSC_NUM]; +#endif +#endif // BR_SHORTCUT + +#if defined(CONFIG_LUNA_DUAL_LINUX) && (defined(CONFIG_USE_PCIE_SLOT_1) && !defined(CONFIG_ARCH_LUNA_SLAVE)) + #ifdef CONFIG_RTL8672 + #define SLOT1_IRQ BSP_PCIE2_IRQ + #else + #define SLOT1_IRQ BSP_PCIE1_IRQ + #endif +#endif + +// TODO: Filen, move to BSP Setting +#ifdef CONFIG_WLAN_HAL_8881A //CONFIG_SOC_RTL8881A +/* + * Wlan LBus Address + */ + +#define BSP_WLAN_BASE_ADDR 0xB8640000 +#define BSP_WLAN_CONF_ADDR NULL +#endif //CONFIG_SOC_RTL8881A + +#ifdef CONFIG_PCI_HCI +struct _device_info_ wlan_device[] = +{ +#if (defined(CONFIG_RTL8686) || defined(CONFIG_RTL8685)) +#if defined(CONFIG_USE_PCIE_SLOT_0) && defined(CONFIG_USE_PCIE_SLOT_1) +#if (defined(CONFIG_RTL_5G_SLOT_0) && defined(CONFIG_WLAN0_5G_WLAN1_2G)) || \ + (defined(CONFIG_RTL_5G_SLOT_1) && defined(CONFIG_WLAN0_2G_WLAN1_5G)) + //5G in wlan0/slot0, 2G in wlan1/slot1 or 5G in wlan1/slot1, 2G in wlan0/slot0 + {(MESH_NUM_CFG<dev->name); + if (dev) { + printk("[%s] close %s ...\n", __func__, wlan_device[0].priv->dev->name); + rtnl_lock(); + dev_close(dev); + rtnl_unlock(); + + dev_put(dev); + } + } + return 0; +} + +static struct notifier_block rtw_reboot_notifier = { + .notifier_call = rtw_shutdown, +}; +#endif + +#ifndef __ECOS +static int wlan_index=0; +int drv_registered = FALSE; +#endif + +#if defined(CONFIG_RTK_MESH) +static struct rtl8192cd_priv *tmp_priv = NULL; +#endif + +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE +static struct rtl8192cd_hw hw_info[NUM_WLAN_IFACE]; +static struct priv_shared_info shared_info[NUM_WLAN_IFACE]; +static struct wlan_hdr_poll hdr_pool[NUM_WLAN_IFACE]; +static struct wlanllc_hdr_poll llc_pool[NUM_WLAN_IFACE]; +static struct wlanbuf_poll buf_pool[NUM_WLAN_IFACE]; +static struct wlanicv_poll icv_pool[NUM_WLAN_IFACE]; +static struct wlanmic_poll mic_pool[NUM_WLAN_IFACE]; +static unsigned char desc_buf[NUM_WLAN_IFACE][DESC_DMA_PAGE_SIZE]; +static int wlandev_idx = 0; + +#else +static struct rtl8192cd_hw hw_info; +static struct priv_shared_info shared_info; +static struct wlan_hdr_poll hdr_pool; +static struct wlanllc_hdr_poll llc_pool; +static struct wlanbuf_poll buf_pool; +static struct wlanicv_poll icv_pool; +static struct wlanmic_poll mic_pool; +static unsigned char desc_buf[DESC_DMA_PAGE_SIZE]; +#endif +#endif + +// init and remove char device +#ifdef CONFIG_WIRELESS_LAN_MODULE +extern int rtl8192cd_chr_init(void); +extern void rtl8192cd_chr_exit(void); +#else +int rtl8192cd_chr_init(void); +void rtl8192cd_chr_exit(void); +#endif +struct rtl8192cd_priv *rtl8192cd_chr_reg(unsigned int minor, struct rtl8192cd_chr_priv *priv); +void rtl8192cd_chr_unreg(unsigned int minor); +int rtl8192cd_fileopen(const char *filename, int flags, int mode); + +void force_stop_wlan_hw(void); + + +#if defined(_INCLUDE_PROC_FS_) && defined(PERF_DUMP) +#include "romeperf.h" +static int read_perf_dump(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)dev->priv; +#ifndef SMP_SYNC + unsigned long x; +#endif + + SAVE_INT_AND_CLI(x); + + rtl8651_romeperfDump(ROMEPERF_INDEX_MIN, ROMEPERF_INDEX_MAX); + + RESTORE_INT(x); + return count; +} + + +static int flush_perf_dump(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)dev->priv; +#ifndef SMP_SYNC + unsigned long x; +#endif + + SAVE_INT_AND_CLI(x); + + rtl8651_romeperfReset(); + + RESTORE_INT(x); + return count; +} +#endif // _INCLUDE_PROC_FS_ && PERF_DUMP + +#ifdef MULTI_MAC_CLONE +void init_Multi_Mac_Clone(struct rtl8192cd_priv *priv) +{ + int i=0; + if (priv==NULL || priv->pshare==NULL){ + printk("init mclone_sta_fixed_addr failed, because the interface is not ready\n"); + return; + } + + for (i=0; ipshare->mclone_sta[i].opmode = WIFI_STATION_STATE; + priv->pshare->mclone_sta[i].usedStaAddrId = 0xff; + memcpy(priv->pshare->mclone_sta[i].sa_addr, NULL_MAC_ADDR, ETH_ALEN); + memcpy(priv->pshare->mclone_sta[i].hwaddr, NULL_MAC_ADDR, ETH_ALEN); + priv->pshare->mclone_sta[i].isTimerInit = 0; + priv->pshare->mclone_sta[i].aid = -1; + priv->pshare->mclone_sta[i].priv = NULL; + } + + STADEBUG("init mclone_sta_fixed_addr\n"); +#if 0 //sd9 case + /*first copy from default clone address then increase from the last byte*/ + if (!memcmp(priv->pshare->mclone_sta_fixed_addr[0].clone_addr, NULL_MAC_ADDR, MACADDRLEN)) { +// memcpy(priv->pshare->mclone_sta_fixed_addr[0].clone_addr, MCLONE_STA_ADDR_DEFAULT, MACADDRLEN); + memcpy(priv->pshare->mclone_sta_fixed_addr[0].clone_addr, priv->pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + priv->pshare->mclone_sta_fixed_addr[0].clone_addr[5] &= 0xf0; + priv->pshare->mclone_sta_fixed_addr[0].clone_addr[5] += 0x20; + STADEBUG("use defualt MAC\n"); + } else { + priv->pshare->mclone_sta_fixed_addr[0].clone_addr[5] &= 0xf0;//max is 16 clone sta. + priv->pshare->mclone_sta_fixed_addr[0].clone_addr[0] &= 0xfe;//should not mcast addr. + } + + priv->pshare->mclone_sta_fixed_addr[0].used = 0; + for (i=1; ipshare->mclone_sta_fixed_addr[i].clone_addr, NULL_MAC_ADDR, MACADDRLEN)) { + memcpy(priv->pshare->mclone_sta_fixed_addr[i].clone_addr, priv->pshare->mclone_sta_fixed_addr[0].clone_addr, MACADDRLEN); + priv->pshare->mclone_sta_fixed_addr[i].clone_addr[5] += i; + } + priv->pshare->mclone_sta_fixed_addr[i].used = 0; + } +#else + /*first copy from interface's HWADDR then increase from 3th Byte*/ + if (!memcmp(priv->pshare->mclone_sta_fixed_addr[0].clone_addr, NULL_MAC_ADDR, MACADDRLEN)) { + memcpy(priv->pshare->mclone_sta_fixed_addr[0].clone_addr, priv->pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + priv->pshare->mclone_sta_fixed_addr[0].clone_addr[2]=0; + STADEBUG("use defualt MAC\n"); + } else { + priv->pshare->mclone_sta_fixed_addr[0].clone_addr[5] &= 0xf0;//max is 16 clone sta. + priv->pshare->mclone_sta_fixed_addr[0].clone_addr[0] &= 0xfe;//should not mcast addr. + } + + priv->pshare->mclone_sta_fixed_addr[0].used = 0; + for (i=1; ipshare->mclone_sta_fixed_addr[i].clone_addr, priv->pshare->mclone_sta_fixed_addr[0].clone_addr, MACADDRLEN); + priv->pshare->mclone_sta_fixed_addr[i].clone_addr[2] += i; + priv->pshare->mclone_sta_fixed_addr[i].used = 0; + } +#endif +} + +void clear_Multi_Mac_Clone(struct rtl8192cd_priv *priv, int idx) +{ + int i, id; + if (idx==-1){//clear all and re-init all + printk("clear all mclone_sta_fixed_addr\n"); + id = ACTIVE_ID; + for (i=0; ipshare->mclone_sta[idx].usedStaAddrId != 0xff){ + priv->pshare->mclone_sta_fixed_addr[priv->pshare->mclone_sta[idx].usedStaAddrId].used = 0; + priv->pshare->mclone_sta[idx].usedStaAddrId = 0xff; + } + + priv->pshare->mclone_sta[idx].opmode = WIFI_STATION_STATE; + memcpy(priv->pshare->mclone_sta[idx].sa_addr, NULL_MAC_ADDR, ETH_ALEN); + memcpy(priv->pshare->mclone_sta[idx].hwaddr, NULL_MAC_ADDR, ETH_ALEN); + if (PENDING_REAUTH_TIMER) DELETE_REAUTH_TIMER; + if (PENDING_REASSOC_TIMER) DELETE_REASSOC_TIMER; + priv->pshare->mclone_sta[idx].aid = -1; + priv->pshare->mclone_sta[idx].priv = NULL; + MCLONE_NUM--; + + return; +} +#endif + +#ifdef CONFIG_PCI_HCI +static void rtl8192cd_bcnProc(struct rtl8192cd_priv *priv, unsigned int bcnInt, + unsigned int bcnOk, unsigned int bcnErr, unsigned int status +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + , unsigned int status_ext +#endif + ) +{ +#ifdef MBSSID + int i; +#endif +#ifdef UNIVERSAL_REPEATER + struct rtl8192cd_priv *priv_root=NULL; +#endif + + /* ================================================================ + Process Beacon OK/ERROR interrupt + ================================================================ */ + if ( bcnOk || bcnErr) + { + +#ifdef UNIVERSAL_REPEATER + if ((OPMODE & WIFI_STATION_STATE) && GET_VXD_PRIV(priv) && + (GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED)) { + priv_root = priv; + priv = GET_VXD_PRIV(priv); + } +#endif + + // + // Statistics and LED counting + // + if (bcnOk) { + // for SW LED + if (priv->pshare->LED_cnt_mgn_pkt) + priv->pshare->LED_tx_cnt++; +#ifdef MBSSID + if (priv->pshare->bcnDOk_priv) + priv->pshare->bcnDOk_priv->ext_stats.beacon_ok++; +#else + priv->ext_stats.beacon_ok++; +#endif + SNMP_MIB_INC(dot11TransmittedFragmentCount, 1); + + // disable high queue limitation + if ((OPMODE & WIFI_AP_STATE) && (priv->pshare->bcnDOk_priv)) { + if (*((unsigned char *)priv->pshare->bcnDOk_priv->beaconbuf + priv->pshare->bcnDOk_priv->timoffset + 4) & 0x01) { + RTL_W16(RD_CTRL, RTL_R16(RD_CTRL) | HIQ_NO_LMT_EN); + } + } + + } else if (bcnErr) { +#ifdef MBSSID + if (priv->pshare->bcnDOk_priv) + priv->pshare->bcnDOk_priv->ext_stats.beacon_er++; +#else + priv->ext_stats.beacon_er++; +#endif + } + +#ifdef UNIVERSAL_REPEATER + if (priv_root != NULL) + priv = priv_root; +#endif + } + + +#ifdef PCIE_POWER_SAVING + if ((OPMODE & WIFI_AP_STATE) && (status & HIMR_BCNDOK0)) { + if ((priv->offload_ctrl & 1) && (priv->offload_ctrl >> 7) && priv->pshare->rf_ft_var.power_save) { + priv->offload_ctrl &= (~1); + update_beacon(priv); + delay_us(100); + RTL_W16(CR , RTL_R16(CR) & ~ENSWBCN); + return; + } + } +#endif + + + /* ================================================================ + Process Beacon interrupt + ================================================================ */ + // + // Update beacon content + // + if (bcnInt) { + unsigned char val8; + if ( +#ifdef CONFIG_RTL_88E_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8188E)?(status & HIMR_88E_BcnInt): +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8812E)?(status & HIMR_92E_BcnInt): +#endif + (status & HIMR_BCNDMA0)) { +#ifdef UNIVERSAL_REPEATER + if ((OPMODE & WIFI_STATION_STATE) && GET_VXD_PRIV(priv) && + (GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED)) { + if (GET_VXD_PRIV(priv)->timoffset) { + update_beacon(GET_VXD_PRIV(priv)); + } + } else +#endif + { + if (priv->timoffset) { + update_beacon(priv); + } + } + } +#ifdef MBSSID + else { + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]->vap_init_seq > 0) && IS_DRV_OPEN(priv->pvap_priv[i]) + && ( +#ifdef CONFIG_RTL_88E_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8188E)?(status_ext & (HIMRE_88E_BCNDMAINT1 << + (priv->pvap_priv[i]->vap_init_seq-1))): +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8812E)?(status_ext & (HIMRE_92E_BCNDMAINT1 << + (priv->pvap_priv[i]->vap_init_seq-1))): +#endif + (status & (HIMR_BCNDMA1 << (priv->pvap_priv[i]->vap_init_seq-1))))) { + if (priv->pvap_priv[i]->timoffset) { + update_beacon(priv->pvap_priv[i]); + } + } + } + } + } +#endif + + // + // Polling highQ as there is multicast waiting for tx... + // +#ifdef UNIVERSAL_REPEATER + if ((OPMODE & WIFI_STATION_STATE) && GET_VXD_PRIV(priv) && + (GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED)) { + priv_root = priv; + priv = GET_VXD_PRIV(priv); + } +#endif + + if ((OPMODE & WIFI_AP_STATE)) { + if ( +#ifdef CONFIG_RTL_88E_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8188E)?(status & HIMR_88E_BcnInt): +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8812E)?(status & HIMR_92E_BcnInt): +#endif + + (status & HIMR_BCNDMA0)) { + val8 = *((unsigned char *)priv->beaconbuf + priv->timoffset + 4); + if (val8 & 0x01) { + if(RTL_R8(BCN_CTRL) & DIS_ATIM) + RTL_W8(BCN_CTRL, (RTL_R8(BCN_CTRL) & (~DIS_ATIM))); +#ifdef __ECOS + priv->pshare->has_triggered_process_mcast_dzqueue = 1; + priv->pshare->call_dsr = 1; +#else + process_mcast_dzqueue(priv); + priv->pkt_in_dtimQ = 0; +#endif + } else { + if(!(RTL_R8(BCN_CTRL) & DIS_ATIM)) + RTL_W8(BCN_CTRL, (RTL_R8(BCN_CTRL) | DIS_ATIM)); + } +//#ifdef MBSSID + priv->pshare->bcnDOk_priv = priv; +//#endif + } +#ifdef MBSSID + else if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]->vap_init_seq > 0) && IS_DRV_OPEN(priv->pvap_priv[i]) + && ( +#ifdef CONFIG_RTL_88E_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8188E)?(status_ext & (HIMRE_88E_BCNDMAINT1 << + (priv->pvap_priv[i]->vap_init_seq-1))): +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8812E)?(status_ext & (IMR_BCNDMAINT1_8812 << + (priv->pvap_priv[i]->vap_init_seq-1))): +#endif + (status & (HIMR_BCNDMA1 << (priv->pvap_priv[i]->vap_init_seq-1))))) { + val8 = *((unsigned char *)priv->pvap_priv[i]->beaconbuf + priv->pvap_priv[i]->timoffset + 4); + if (val8 & 0x01) { + if(RTL_R8(BCN_CTRL) & DIS_ATIM) + RTL_W8(BCN_CTRL, (RTL_R8(BCN_CTRL) & (~DIS_ATIM))); +#ifdef __ECOS + priv->pshare->has_triggered_vap_process_mcast_dzqueue[i] = 1; + priv->pshare->call_dsr = 1; +#else + process_mcast_dzqueue(priv->pvap_priv[i]); + priv->pvap_priv[i]->pkt_in_dtimQ = 0; +#endif + } else { + if(!(RTL_R8(BCN_CTRL) & DIS_ATIM)) + RTL_W8(BCN_CTRL, (RTL_R8(BCN_CTRL) | DIS_ATIM)); + } + + priv->pshare->bcnDOk_priv = priv->pvap_priv[i]; + } + } + } +#endif + + } + +// if (priv->pshare->pkt_in_hiQ) { + if (priv->pshare->bcnDOk_priv && priv->pshare->bcnDOk_priv->pkt_in_hiQ) { + int pre_head = get_txhead(priv->pshare->phw, MCAST_QNUM); + do { + txdesc_rollback(&pre_head); + } while (((get_txdesc_info(priv->pshare->pdesc_info, MCAST_QNUM) + pre_head)->type != _PRE_ALLOCLLCHDR_) && + (get_desc((get_txdesc(priv->pshare->phw, MCAST_QNUM) + pre_head)->Dword0) & TX_OWN)); + + if (get_desc((get_txdesc(priv->pshare->phw, MCAST_QNUM) + pre_head)->Dword0) & TX_OWN) { + unsigned short *phdr = (unsigned short *)((get_txdesc_info(priv->pshare->pdesc_info, MCAST_QNUM) + pre_head)->pframe); +#ifdef __MIPSEB__ + phdr = (unsigned short *)KSEG1ADDR(phdr); +#endif + ClearMData(phdr); + } + tx_poll(priv, MCAST_QNUM); +// priv->pshare->pkt_in_hiQ = 0; + } + + +#ifdef UNIVERSAL_REPEATER + if (priv_root != NULL) + priv = priv_root; +#endif + + } + + +#ifdef CLIENT_MODE + // + // Ad-hoc beacon status + // + if (OPMODE & WIFI_ADHOC_STATE) { + if (bcnOk) + priv->ibss_tx_beacon = TRUE; + if (bcnErr) + priv->ibss_tx_beacon = FALSE; + } +#endif +} +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_WLAN_HAL + +#if CFG_HAL_MEASURE_BEACON +static VOID +CalcBeaconVariation( + struct rtl8192cd_priv *priv +) +{ + u4Byte tsfVal,tsf,beaconVarationTime,i; + static u4Byte maxVal[8]= {0}; + tsf = RTL_R32(REG_TSFTR); + tsf = tsf - RTL_R8(0x556)*1024*(priv->vap_init_seq); + + if(priv->vap_init_seq ==2) + { + beaconVarationTime = (tsf%102400); + if(beaconVarationTime > maxVal[priv->vap_init_seq]) + { + maxVal[priv->vap_init_seq] = beaconVarationTime; + if(priv->vap_init_seq == 0 ) { +// printk("Root maxVal = %d \n", maxVal[0]); + } else { +// printk("VAP[%d] maxVal = %d \n",priv->vap_init_seq,maxVal[priv->vap_init_seq]); + } + } + + //RTL_W32(0x1b8,beaconVarationTime); +// printk("VAP[%d] beaconVarationTime = %d TSF =%d\n",priv->vap_init_seq,beaconVarationTime,tsf); + } +} + +#endif // #if CFG_HAL_MEASURE_BEACON +#endif //#ifdef CONFIG_WLAN_HAL + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL +static void +rtl88XX_bcnProc( + struct rtl8192cd_priv *priv, + unsigned int bcnInt, + unsigned int bcnOk, + unsigned int bcnErr +) +{ +#ifdef MBSSID + int i; +#endif + + /* ================================================================ + Process Beacon OK/ERROR interrupt + ================================================================ */ + if ( bcnOk || bcnErr) + { + // clear OWN bit after beacon ok interrupt, include root & VAPs + if (priv->pshare->bcnDOk_priv) { + GET_HAL_INTERFACE(priv)->SetBeaconDownloadHandler(priv->pshare->bcnDOk_priv, HW_VAR_BEACON_DISABLE_DOWNLOAD); + } +#ifdef BEAMFORMING_SUPPORT + priv->pshare->soundingLock=0; +#endif + +#ifdef UNIVERSAL_REPEATER + struct rtl8192cd_priv *priv_root=NULL; + if ((OPMODE & WIFI_STATION_STATE) && GET_VXD_PRIV(priv) && + (GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED)) { + priv_root = priv; + priv = GET_VXD_PRIV(priv); + } +#endif + + // + // Statistics and LED counting + // + if (bcnOk) { + // for SW LED + if (priv->pshare->LED_cnt_mgn_pkt) + priv->pshare->LED_tx_cnt++; +#ifdef MBSSID + if (priv->pshare->bcnDOk_priv) + { + priv->pshare->bcnDOk_priv->ext_stats.beacon_ok++; +#if CFG_HAL_MEASURE_BEACON + CalcBeaconVariation(priv->pshare->bcnDOk_priv); +#endif //#if CFG_HAL_MEASURE_BEACON + } +#else + priv->ext_stats.beacon_ok++; +#if CFG_HAL_MEASURE_BEACON + CalcBeaconVariation(priv); +#endif //#if CFG_HAL_MEASURE_BEACON + +#endif + SNMP_MIB_INC(dot11TransmittedFragmentCount, 1); + + // disable high queue limitation + if ((OPMODE & WIFI_AP_STATE) && (priv->pshare->bcnDOk_priv)) { + if (*((unsigned char *)priv->pshare->bcnDOk_priv->beaconbuf + priv->pshare->bcnDOk_priv->timoffset + 4) & 0x01) { + RTL_W16(RD_CTRL, RTL_R16(RD_CTRL) | HIQ_NO_LMT_EN); + } + } + + } else if (bcnErr) { +#ifdef MBSSID + if (priv->pshare->bcnDOk_priv) + priv->pshare->bcnDOk_priv->ext_stats.beacon_er++; +#else + priv->ext_stats.beacon_er++; +#endif + } + +#ifdef UNIVERSAL_REPEATER + if (priv_root != NULL) + priv = priv_root; +#endif + } + + +#ifdef PCIE_POWER_SAVING +// TODO: we should modify code below + if ((OPMODE & WIFI_AP_STATE) && (status & HIMR_BCNDOK0)) { + if ((priv->offload_ctrl & 1) && (priv->offload_ctrl >> 7) && priv->pshare->rf_ft_var.power_save) { + priv->offload_ctrl &= (~1); + update_beacon(priv); + delay_us(100); + RTL_W16(CR , RTL_R16(CR) & ~ENSWBCN); + return; + } + } +#endif + + + /* ================================================================ + Process Beacon interrupt + ================================================================ */ + // + // Update beacon content + // + if (bcnInt) { + + unsigned char val8; +#ifdef BEAMFORMING_SUPPORT + priv->pshare->soundingLock=1; +#endif + + if ( _TRUE == GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_BcnInt) ) { + GET_HAL_INTERFACE(priv)->SetBeaconDownloadHandler(priv, HW_VAR_BEACON_DISABLE_DOWNLOAD); + +#ifdef UNIVERSAL_REPEATER + if ((OPMODE & WIFI_STATION_STATE) && GET_VXD_PRIV(priv) && + (GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED)) { + if (GET_VXD_PRIV(priv)->timoffset) { + update_beacon(GET_VXD_PRIV(priv)); + } + } else +#endif + { + if (priv->timoffset) { + update_beacon(priv); + } + } + } +#ifdef MBSSID + else { + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]->vap_init_seq > 0) && IS_DRV_OPEN(priv->pvap_priv[i]) + && (_TRUE == GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_BcnInt1 + (priv->pvap_priv[i]->vap_init_seq-1)))) + { + GET_HAL_INTERFACE(priv)->SetBeaconDownloadHandler(priv->pvap_priv[i], HW_VAR_BEACON_DISABLE_DOWNLOAD); + if (priv->pvap_priv[i]->timoffset) { + update_beacon(priv->pvap_priv[i]); + } + } + } + } + } +#endif + + // + // Polling highQ as there is multicast waiting for tx... + // +#ifdef UNIVERSAL_REPEATER + struct rtl8192cd_priv *priv_root=NULL; + if ((OPMODE & WIFI_STATION_STATE) && GET_VXD_PRIV(priv) && + (GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED)) { + priv_root = priv; + priv = GET_VXD_PRIV(priv); + } +#endif + + if ((OPMODE & WIFI_AP_STATE)) { + if ( _TRUE == GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_BcnInt) ) { + // TODO: modify code below + val8 = *((unsigned char *)priv->beaconbuf + priv->timoffset + 4); + if (val8 & 0x01) { +#ifdef __ECOS //mark_ecos + priv->pshare->has_triggered_process_mcast_dzqueue = 1; + priv->pshare->call_dsr = 1; +#else + process_mcast_dzqueue(priv); + priv->pkt_in_dtimQ = 0; +#endif + } +//#ifdef MBSSID + priv->pshare->bcnDOk_priv = priv; +//#endif + } +#ifdef MBSSID + else if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]->vap_init_seq > 0) && IS_DRV_OPEN(priv->pvap_priv[i]) + && (_TRUE == GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_BcnInt1 + (priv->pvap_priv[i]->vap_init_seq-1)))){ + val8 = *((unsigned char *)priv->pvap_priv[i]->beaconbuf + priv->pvap_priv[i]->timoffset + 4); + // TODO: modify code below + if (val8 & 0x01) { +#ifdef __ECOS + priv->pshare->has_triggered_vap_process_mcast_dzqueue[i] = 1; + priv->pshare->call_dsr = 1; +#else + process_mcast_dzqueue(priv->pvap_priv[i]); + priv->pvap_priv[i]->pkt_in_dtimQ = 0; +#endif + } + priv->pshare->bcnDOk_priv = priv->pvap_priv[i]; + } + } + } +#endif + + } + +#ifdef UNIVERSAL_REPEATER + if (priv_root != NULL) + priv = priv_root; +#endif + + } + + +#ifdef CLIENT_MODE + // + // Ad-hoc beacon status + // + if (OPMODE & WIFI_ADHOC_STATE) { + if (bcnOk) + priv->ibss_tx_beacon = TRUE; + if (bcnErr) + priv->ibss_tx_beacon = FALSE; + } +#endif +} + +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +static __inline__ +VOID +InterruptRxHandle( + struct rtl8192cd_priv *priv, BOOLEAN caseRxRDU +) +{ +#if defined(__KERNEL__) || defined(__ECOS) +#if defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX) +#if defined(RX_TASKLET) + if (!priv->pshare->has_triggered_rx_tasklet) { + priv->pshare->has_triggered_rx_tasklet = 1; + GET_HAL_INTERFACE(priv)->DisableRxRelatedInterruptHandler(priv); +#ifdef __ECOS + priv->pshare->call_dsr = 1; +#else + tasklet_hi_schedule(&priv->pshare->rx_tasklet); +#endif + } +#else + rtl8192cd_rx_isr(priv); +#endif + +#else // !(defined RTL8190_ISR_RX && RTL8190_DIRECT_RX) + if (caseRxRDU) { + rtl8192cd_rx_isr(priv); + if (priv->pshare->rxInt_useTsklt) + tasklet_hi_schedule(&priv->pshare->rx_tasklet); + else + rtl8192cd_rx_dsr((unsigned long)priv); + } + else { + if (priv->pshare->rxInt_useTsklt) + tasklet_hi_schedule(&priv->pshare->rx_tasklet); + else + rtl8192cd_rx_dsr((unsigned long)priv); + } +#endif +#else // !__KERNEL__ + rtl8192cd_rx_dsr((unsigned long)priv); +#endif +} + +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +static __inline__ +VOID +InterruptTxHandle( + struct rtl8192cd_priv *priv +) +{ + struct rtl8192cd_hw *phw; + + phw = GET_HW(priv); + +#ifdef MP_TEST +#if defined(SMP_SYNC) || defined(__ECOS) + if (OPMODE & WIFI_MP_STATE){ + if (!priv->pshare->has_triggered_tx_tasklet) { +#ifdef __KERNEL__ + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; +#elif defined(__ECOS) + priv->pshare->has_triggered_tx_tasklet = 1; + priv->pshare->call_dsr = 1; +#endif + } + } +#else + if (OPMODE & WIFI_MP_STATE) + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + else +#endif + + if (GET_HAL_INTERFACE(priv)->QueryTxConditionMatchHandler(priv)) { +#if defined(__KERNEL__) || defined(__ECOS) + if (!priv->pshare->has_triggered_tx_tasklet) { +#ifdef __ECOS + priv->pshare->call_dsr = 1; +#else + tasklet_schedule(&priv->pshare->tx_tasklet); +#endif + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif +#endif + } +} + + +static __inline__ VOID +InterruptPSTimer2Handle( + struct rtl8192cd_priv *priv +) +{ +#if defined (SUPPORT_TX_AMSDU) + unsigned long current_value, timeout; +#endif + +#if 0 // TODO: Modify Code below +#ifdef SUPPORT_TX_AMSDU + RTL_W32(IMR, RTL_R32(IMR) & ~IMR_TIMEOUT2); + + current_value = RTL_R32(TSFR) ; + timeout = RTL_R32(TIMER1); + if (TSF_LESS(current_value, timeout)) + setup_timer2(priv, timeout); + else + amsdu_timeout(priv, current_value); +#endif + +#ifdef P2P_SUPPORT + if( OPMODE&WIFI_P2P_SUPPORT && (P2PMODE==P2P_CLIENT)) { + RTL_W32(HIMR, RTL_R32(HIMR) & ~HIMR_TIMEOUT2); + p2p_noa_timer(priv); + } +#endif +#endif +} + + +#if 1 //Filen_Test +#define PRINT_DATA(_TitleString, _HexData, _HexDataLen) \ +{ \ + char *szTitle = _TitleString; \ + pu1Byte pbtHexData = _HexData; \ + u4Byte u4bHexDataLen = _HexDataLen; \ + u4Byte __i; \ + DbgPrint("%s", szTitle); \ + for (__i=0;__iInterruptRecognizedHandler(priv, NULL, 0)) { +#ifndef NOT_RTK_BSP + // don't print for non-RTK platforms, interrupt line may be shared among devices + printk("NULL Wlan Interrupt !?\n"); +#endif + return SUCCESS; + } + + //Break Condition, satisfy one of condtion below: + // 1.) retry cnt until our setting value + // 2.) No interupt pending + //while(1) +int_retry_process: + { + //4 Initialize + caseBcnInt = FALSE; + caseBcnStatusOK = FALSE; + caseBcnStatusER = FALSE; + caseBcnDMAER = FALSE; + + caseRxRDU = FALSE; + caseRxOK = FALSE; + caseRxFOVW = FALSE; + +#if defined(SUPPORT_TX_AMSDU) || defined(P2P_SUPPORT) + caseTimer2 = FALSE; +#endif + + //4 Check interrupt handler + // 1.) Beacon + caseBcnInt = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_BcnInt_MBSSID); + caseBcnStatusOK = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_TBDOK); + caseBcnStatusER = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_TBDER); + caseBcnDMAER = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_BCNDERR0); + + if(TRUE == caseBcnDMAER) + { + priv->ext_stats.beacon_dma_err++; + } + + if (TRUE == caseBcnInt || TRUE == caseBcnStatusOK || TRUE == caseBcnStatusER) { + rtl88XX_bcnProc(priv, caseBcnInt, caseBcnStatusOK, caseBcnStatusER); + } + +#ifdef TXREPORT + caseC2HIsr = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_C2HCMD); + if (TRUE == caseC2HIsr) { +#ifdef __ECOS + priv->pshare->has_triggered_C2H_isr = 1; + priv->pshare->call_dsr = 1; +#else + //C2H_isr_88XX(priv); + GET_HAL_INTERFACE(priv)->C2HHandler(priv); +#endif + } +#endif + + // 2.) Rx + caseRxRDU = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_RDU); + if (TRUE == caseRxRDU) { + caseRxRDUCnt++; //filen: temp + priv->ext_stats.rx_rdu++; + priv->pshare->skip_mic_chk = SKIP_MIC_NUM; + } + + caseRxOK = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_RX_OK); + if (TRUE == caseRxOK) { + caseRxOKCnt++; //filen: temp + } + + caseRxFOVW = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_RXFOVW); + if (TRUE == caseRxFOVW) { + priv->ext_stats.rx_fifoO++; + priv->pshare->skip_mic_chk = SKIP_MIC_NUM; + } + +#if 1 + // 5.) check PS INT +#if defined(HW_DETEC_POWER_STATE) + if (GET_CHIP_VER(priv)==VERSION_8814A) { + casePwrInt0 = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_PwrInt0); + casePwrInt1 = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_PwrInt1); + casePwrInt2 = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_PwrInt2); + casePwrInt3 = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_PwrInt3); + casePwrInt4 = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_PwrInt4); + int i; + + //printk("casePwrInt0 = %x pwr = %x \n",casePwrInt0,RTL_R32(0x1140)); + + + if (TRUE == casePwrInt0 || TRUE == casePwrInt1 || TRUE == casePwrInt2 || TRUE == casePwrInt3 || TRUE == casePwrInt4) { +#ifdef HW_DETEC_POWER_STATE + if(TRUE == casePwrInt0) + { + detect_hw_pwr_state(priv,0); + } + + if(TRUE == casePwrInt1) + { + detect_hw_pwr_state(priv,1); + } + + if(TRUE == casePwrInt2) + { + detect_hw_pwr_state(priv,2); + } + + if(TRUE == casePwrInt3) + { + detect_hw_pwr_state(priv,3); + } +#endif //#ifdef HW_DETEC_POWER_STATE +#ifdef CONFIG_8814_AP_MAC_VERI + static u4Byte seq = 0; + static u4Byte carrier = 0; + RTL_W16(0x1a0,RTL_R16(0x1a0)+1); + RTL_W8(0x1a4,RTL_R8(0x1140)); + + // check 0~31 which sta ps change + + + if(priv->hw_seq[0] > RTL_R16(0x1152)) + { + priv->hw_Carrier++; + printk("hw_Carrier = %x, seq =%x \n",priv->hw_Carrier,RTL_R16(0x1152)); + carrier++; + } + + priv->hw_seq[0] = RTL_R16(0x1152); + + + printk("[%s][%d] MACID%x Seq=%x Pwr = %x, carrier =%x \n", + __FUNCTION__,__LINE__,RTL_R8(0x1150),RTL_R16(0x1152),RTL_R32(0x1140),carrier); + + RTL_W32(0x10b8, 0); + + for(i=0;i<128;i++) + { + priv->pwrHWState[i] = (RTL_R32(0x1140+(i>>5)*4) & BIT(i%32)? 1:0); + + if(priv->pwrHWState[i]!= priv->pwroldHWState[i]) + { + priv->pwrStateHWCnt[i]++; + priv->hw_seq[i] = RTL_R16(0x1152); + + // if(priv->testResult == true) + { + printk("[%s][%d] MACID%x HW PS0=%x Seq=%x Cnt=%x\n", + __FUNCTION__,__LINE__,i,priv->pwrHWState[i],priv->hw_seq[i],priv->pwrStateHWCnt[i]); + } + } + + priv->pwroldHWState[i] = priv->pwrHWState[i]; + } + RTL_W32(0x10b8, BIT(4)); + +#endif //#ifdef CONFIG_8814_AP_MAC_VERI + } + } +#endif //defined(CONFIG_WLAN_HAL_8814AE) +#endif + + if (TRUE == caseRxRDU || TRUE == caseRxOK || TRUE == caseRxFOVW) { + InterruptRxHandle(priv, caseRxRDU); + } + + // 3.) Tx + InterruptTxHandle(priv); + + // 4.) check DMA error + caseTxFOVW = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_TXFOVW); + caseTxErr = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_TXERR); + caseRxErr = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_RXERR); + + if (TRUE == caseTxFOVW || TRUE == caseTxErr) { + // check Tx DMA error + u4Byte TxDMAStatus = 0; + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_NUM_TXDMA_STATUS, (pu1Byte)&TxDMAStatus); + + if(TxDMAStatus) + { + printk("TXDMA Error TxDMAStatus =%x\n",TxDMAStatus); + priv->pshare->tx_dma_status |= TxDMAStatus; + priv->pshare->tx_dma_err++; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_NUM_TXDMA_STATUS, (pu1Byte)&TxDMAStatus); +#ifdef CHECK_LX_DMA_ERROR + check_hangup(priv); +#endif + } + } + + if (TRUE == caseRxFOVW || TRUE == caseRxErr) { + // check Rx DMA error + u1Byte RxDMAStatus = 0; + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_NUM_RXDMA_STATUS, (pu1Byte)&RxDMAStatus); + + if(RxDMAStatus) + { + printk("RXDMA Error RxDMAStatus =%x\n",RxDMAStatus); + priv->pshare->rx_dma_status |= RxDMAStatus; + priv->pshare->rx_dma_err++; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_NUM_RXDMA_STATUS, (pu1Byte)&RxDMAStatus); +#ifdef CHECK_LX_DMA_ERROR + check_hangup(priv); +#endif + } + } + + // 4.) TX_AMSDU & P2P +#if 0 // TODO: Check Code +#if defined(SUPPORT_TX_AMSDU) || defined(P2P_SUPPORT) + caseTimer2 = GET_HAL_INTERFACE(priv)->GetInterruptHandler(priv, HAL_INT_TYPE_PSTIMEOUT2); + if ( TRUE == caseTimer2 ) { + InterruptPSTimer2Handle(priv); + } +#endif +#endif + +#if 0 + //4 Check Break Condition + if(_FALSE == GET_HAL_INTERFACE(priv)->InterruptRecognizedHandler(priv, NULL, 0)) { + break; + } + else { + retry_cnt++; + + if ( retry_cnt >= RTL_WLAN_INT_RETRY_CNT_MAX ) { + break; + } + else { + watchdog_kick(); + } + } +#endif + if ((retry_cnt++) <= RTL_WLAN_INT_RETRY_CNT_MAX ) { + if (GET_HAL_INTERFACE(priv)->InterruptRecognizedHandler(priv, NULL, 0)) { + PHAL_DATA_TYPE pHalData = _GET_HAL_DATA(priv); + if ((pHalData->IntArray_bak[0] != pHalData->IntArray[0]) || (pHalData->IntArray_bak[1] != pHalData->IntArray[1])) + goto int_retry_process; + } + } + } + return SUCCESS; +} +#endif //CONFIG_WLAN_HAL + +void check_dma_error(struct rtl8192cd_priv *priv, unsigned int status, unsigned int status_ext) +{ + unsigned char reg_rxdma; + unsigned int reg_txdma; + int clear_isr=0, check_tx_dma=0, check_rx_dma=0; + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if ((status_ext & HIMRE_88E_RXFOVW) | (status_ext & HIMRE_88E_RXERR)) + check_rx_dma++; + if ((status_ext & HIMRE_88E_TXFOVW) | (status_ext & HIMRE_88E_TXERR)) + check_tx_dma++; + } else +#endif + { + if ((status & HIMR_RXFOVW) | (status_ext & HIMRE_RXERR)) + check_rx_dma++; + + if ((status & HIMR_TXFOVW) | (status_ext & HIMRE_TXERR)) + check_tx_dma++; + } + + if (check_rx_dma) { + reg_rxdma = RTL_R8(RXDMA_STATUS); + if (reg_rxdma) { + RTL_W8(RXDMA_STATUS, reg_rxdma); + printk("RXDMA_STATUS %02x\n", reg_rxdma); + priv->pshare->rx_dma_err++; + priv->pshare->rx_dma_status |= reg_rxdma; + clear_isr = 1; + } + } + + if (check_tx_dma) { + reg_txdma = RTL_R32(TXDMA_STATUS); + if (reg_txdma) { + RTL_W32(TXDMA_STATUS, reg_txdma); + printk("TXDMA_STATUS %08x\n", reg_txdma); + priv->pshare->tx_dma_err++; + priv->pshare->tx_dma_status |= reg_txdma; + clear_isr = 1; + } + } + + if (clear_isr) { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + RTL_W32(REG_88E_HISR, status); + RTL_W32(REG_88E_HISRE, status_ext); + } else +#endif + { + RTL_W32(HISR, status); + RTL_W32(HISRE, status_ext); + } + } +} + + +#define RTL_WLAN_INT_RETRY_MAX (2) + +#if(CONFIG_WLAN_NOT_HAL_EXIST) +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +__inline__ static int __rtl8192cd_interrupt(void *dev_instance) +{ + struct net_device *dev; + struct rtl8192cd_priv *priv; + struct rtl8192cd_hw *phw; + + unsigned int status, status_ext, retry_cnt; + unsigned int status_bak, status_ext_bak; + unsigned int caseBcnInt, caseBcnStatusOK, caseBcnStatusER, caseBcnDmaOK=0; + unsigned int caseRxStatus, caseRxRDU; + + #if defined(SUPPORT_TX_AMSDU) || defined(P2P_SUPPORT) + unsigned int caseTimer2; + #endif +#if defined (SUPPORT_TX_AMSDU) + unsigned long current_value, timeout; +#endif + + dev = (struct net_device *)dev_instance; + priv = GET_DEV_PRIV(dev); + +#if defined(CONFIG_RTL_92D_DMDP) && !defined(NOT_RTK_BSP) + if (GET_CHIP_VER(priv)==VERSION_8192D) { + #if (RTL_USED_PCIE_SLOT==1) + if (!((REG32(0xb8b21004)& 0x01) && (priv->pshare->wlandev_idx ==0)) && + !((REG32(0xb8b21004)& 0x02) && (priv->pshare->wlandev_idx ==1))) { + //printk("INT=[%02x] WLAN(%d)\n",(REG32(0xb8b21004)& 0x0f),(priv->pshare->wlandev_idx)); + goto int_exit; + } + #else + if (!((REG32(0xb8b01004)& 0x01) && (priv->pshare->wlandev_idx ==0)) && + !((REG32(0xb8b01004)& 0x02) && (priv->pshare->wlandev_idx ==1))) { + //printk("INT=[%02x] WLAN(%d)\n",(REG32(0xb8b21004)& 0x0f),(priv->pshare->wlandev_idx)); + goto int_exit; + } + #endif + } +#endif + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) { +#ifdef CONFIG_RTL_92D_DMDP + REG32(0xb8003000) = REG32(0xb8003000)|BIT(22); +#endif + goto int_exit; + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + status = RTL_R32(REG_88E_HISR); + RTL_W32(REG_88E_HISR, status); + if (status & HIMR_88E_HISR1_IND_INT) { + status_ext = RTL_R32(REG_88E_HISRE); + RTL_W32(REG_88E_HISRE, status_ext); + } else { + status_ext = 0; + } + } else +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8812E) { + status = RTL_R32(REG_HISR0_8812); + RTL_W32(REG_HISR0_8812, status); + + status_ext = RTL_R32(REG_HISR1_8812); + RTL_W32(REG_HISR1_8812, status_ext); + } else +#endif +#if defined(CONFIG_WLAN_HAL_8192EE) + if (GET_CHIP_VER(priv)==VERSION_8192E) { + status = RTL_R32(REG_92E_HISR); + RTL_W32(REG_92E_HISR, status); + + status_ext = RTL_R32(REG_92E_HISRE); + RTL_W32(REG_92E_HISRE, status_ext); + } else +#endif + { + status = RTL_R32(HISR); + RTL_W32(HISR, status); + status_ext = RTL_R32(HISRE); + RTL_W32(HISRE, status_ext); + } + if (status == 0 && status_ext == 0) { + goto int_exit; + } + + retry_cnt = 0; +retry_process: + + caseBcnInt = caseBcnStatusOK = caseBcnStatusER = caseBcnDmaOK = 0; + caseRxStatus = caseRxRDU = 0; + + #if defined(SUPPORT_TX_AMSDU) || defined(P2P_SUPPORT) + caseTimer2 = 0; + #endif + +#if defined(TXREPORT) +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if (CHIP_VER_92X_SERIES(priv)) { + if(status_ext & BIT(9)) +#ifdef __ECOS + priv->pshare->has_triggered_C2H_isr = 1; + priv->pshare->call_dsr = 1; +#else + C2H_isr(priv); +#endif + + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)==VERSION_8812E){ +// if(status & HIMR_92E_C2HCMD){ +// C2H_isr_8812(priv); +// } +#ifdef BEAMFORMING_SUPPORT + if(status & IMR_GTINT3_8812) + Beamforming_TimerCallback(priv); +#endif + } +#endif +#endif + + + if(GET_CHIP_VER(priv)!= VERSION_8812E) + { + check_dma_error(priv, status, status_ext); + } + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if ((status & HIMR_88E_BcnInt) || (status_ext & (HIMRE_88E_BCNDMAINT1 | HIMRE_88E_BCNDMAINT2 + | HIMRE_88E_BCNDMAINT3 | HIMRE_88E_BCNDMAINT4 | HIMRE_88E_BCNDMAINT5 + | HIMRE_88E_BCNDMAINT6 | HIMRE_88E_BCNDMAINT7))) { + caseBcnInt = 1; + } + + if (status & HIMR_88E_TBDOK) + caseBcnStatusOK = 1; + + if (status & HIMR_88E_TBDER) + caseBcnStatusER = 1; + + if (status & (HIMR_88E_ROK | HIMR_88E_RDU)) { + caseRxStatus = 1; + + if (status & HIMR_88E_RDU) { + priv->ext_stats.rx_rdu++; + caseRxRDU = 1; + priv->pshare->skip_mic_chk = SKIP_MIC_NUM; + } + } + + if (status_ext & HIMRE_88E_RXFOVW) { + priv->ext_stats.rx_fifoO++; + priv->pshare->skip_mic_chk = SKIP_MIC_NUM; + } + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8812E) { + + if ((status & HIMR_92E_BcnInt) || (status_ext & (HIMRE_92E_BCNDMAINT1 | HIMRE_92E_BCNDMAINT2 + | HIMRE_92E_BCNDMAINT3 | HIMRE_92E_BCNDMAINT4 | HIMRE_92E_BCNDMAINT5 + | HIMRE_92E_BCNDMAINT6 | HIMRE_92E_BCNDMAINT7))) { + caseBcnInt = 1; + } + + if (status & HIMR_92E_TBDOK) + caseBcnStatusOK = 1; + + if (status & HIMR_92E_TBDER) + caseBcnStatusER = 1; + + if (status & (HIMR_92E_ROK | HIMR_92E_RDU)) { + caseRxStatus = 1; + + if (status & HIMR_92E_RDU) { + priv->ext_stats.rx_rdu++; + caseRxRDU = 1; + priv->pshare->skip_mic_chk = SKIP_MIC_NUM; + } + } + + if (status_ext & HIMRE_92E_RXFOVW) { + priv->ext_stats.rx_fifoO++; + priv->pshare->skip_mic_chk = SKIP_MIC_NUM; + } + } else +#endif + { + if (status & (HIMR_BCNDMA0 | HIMR_BCNDMA1 | HIMR_BCNDMA2 | HIMR_BCNDMA3 | HIMR_BCNDMA4 | HIMR_BCNDMA5 | HIMR_BCNDMA6 | HIMR_BCNDMA7)) + caseBcnInt = 1; + if (status & (HIMR_BCNDOK0 | HIMR_BCNDOK1 | HIMR_BCNDOK2 | HIMR_BCNDOK3 | HIMR_BCNDOK4 | HIMR_BCNDOK5 | HIMR_BCNDOK6 | HIMR_BCNDOK7)) + caseBcnDmaOK = 1; + + if (status & HIMR_TXBCNOK) + caseBcnStatusOK = 1; + + if (status & HIMR_TXBCNERR) + caseBcnStatusER = 1; + + if (status & (HIMR_ROK | HIMR_RDU)) + caseRxStatus = 1; + + if (status & HIMR_RDU) { + priv->ext_stats.rx_rdu++; + caseRxRDU = 1; + priv->pshare->skip_mic_chk = SKIP_MIC_NUM; + } + + if (status & HIMR_RXFOVW) { + priv->ext_stats.rx_fifoO++; + priv->pshare->skip_mic_chk = SKIP_MIC_NUM; + } + } + + #if defined(SUPPORT_TX_AMSDU) || defined(P2P_SUPPORT) + +#ifdef CONFIG_RTL_8812_SUPPORT + if ( (GET_CHIP_VER(priv)== VERSION_8812E)) { + if (status & IMR_TIMER2_8812) + caseTimer2 = 1; + } else +#endif + { + if (status & HIMR_TIMEOUT2) + caseTimer2 = 1; + } + #endif + + if (caseBcnInt || caseBcnStatusOK || caseBcnStatusER || caseBcnDmaOK){ + rtl8192cd_bcnProc(priv, caseBcnInt, caseBcnStatusOK, caseBcnStatusER, status +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + , status_ext +#endif + ); + } + + // + // Rx interrupt + // + if (caseRxStatus) + { + // stop RX first +#if defined(__KERNEL__) || defined(__ECOS) +#if defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX) +#if defined(RX_TASKLET) + if (!priv->pshare->has_triggered_rx_tasklet) { + priv->pshare->has_triggered_rx_tasklet = 1; +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask & ~HIMR_88E_ROK); + RTL_W32(REG_88E_HIMRE, priv->pshare->InterruptMaskExt & ~HIMRE_88E_RXFOVW); + } else +#endif + { + //RTL_W32(HIMR, priv->pshare->InterruptMask & ~(HIMR_RXFOVW | HIMR_RDU | HIMR_ROK)); + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + RTL_W32(REG_HIMR0_8812, priv->pshare->InterruptMask & ~(HIMR_92E_ROK )); + RTL_W32(REG_HIMR1_8812, priv->pshare->InterruptMaskExt & ~( HIMRE_92E_RXFOVW)); + } + else +#endif + RTL_W32(HIMR, priv->pshare->InterruptMask & ~(HIMR_RXFOVW | HIMR_ROK)); + } +#ifdef __ECOS + priv->pshare->call_dsr = 1; +#else + tasklet_hi_schedule(&priv->pshare->rx_tasklet); +#endif + } +#else + rtl8192cd_rx_isr(priv); +#endif + +#else // !(defined RTL8190_ISR_RX && RTL8190_DIRECT_RX) + if (caseRxRDU) { + rtl8192cd_rx_isr(priv); + tasklet_hi_schedule(&priv->pshare->rx_tasklet); + } + else { + if (priv->pshare->rxInt_useTsklt) + tasklet_hi_schedule(&priv->pshare->rx_tasklet); + else + rtl8192cd_rx_dsr((unsigned long)priv); + } +#endif +#else // !__KERNEL__ + rtl8192cd_rx_dsr((unsigned long)priv); +#endif + } + + // + // Tx interrupt + // + phw = GET_HW(priv); +#ifdef MP_TEST +#if defined(SMP_SYNC) || defined(__ECOS) + if (OPMODE & WIFI_MP_STATE){ + if (!priv->pshare->has_triggered_tx_tasklet) { +#ifdef __KERNEL__ + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; +#elif defined(__ECOS) + priv->pshare->has_triggered_tx_tasklet = 1; + priv->pshare->call_dsr = 1; +#endif + } + } +#else + if (OPMODE & WIFI_MP_STATE) + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + else +#endif + if ((CIRC_CNT_RTK(phw->txhead0, phw->txtail0, CURRENT_NUM_TX_DESC) > 10) || + (CIRC_CNT_RTK(phw->txhead1, phw->txtail1, CURRENT_NUM_TX_DESC) > 10) || + (CIRC_CNT_RTK(phw->txhead2, phw->txtail2, CURRENT_NUM_TX_DESC) > 10) || + (CIRC_CNT_RTK(phw->txhead3, phw->txtail3, CURRENT_NUM_TX_DESC) > 10) || + (CIRC_CNT_RTK(phw->txhead4, phw->txtail4, CURRENT_NUM_TX_DESC) > 10) || + (CIRC_CNT_RTK(phw->txhead5, phw->txtail5, CURRENT_NUM_TX_DESC) > 10) + ) { +#if defined(__KERNEL__) || defined(__ECOS) + if (!priv->pshare->has_triggered_tx_tasklet) { +#ifdef __ECOS + priv->pshare->call_dsr = 1; +#else + tasklet_schedule(&priv->pshare->tx_tasklet); +#endif + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif +#endif + } + +#ifdef SUPPORT_TX_AMSDU + if (caseTimer2) { + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + RTL_W32(REG_HIMR0_8812, RTL_R32(REG_HIMR0_8812) & ~ IMR_TIMER2_8812 ); + else +#endif + RTL_W32(HIMR, RTL_R32(HIMR) & ~HIMR_TIMEOUT2); + + current_value = RTL_R32(TSFTR) ; + timeout = RTL_R32(TIMER1); + if (TSF_LESS(current_value, timeout)) + setup_timer2(priv, timeout); + else + amsdu_timeout(priv, current_value); + } +#endif + + +#ifdef P2P_SUPPORT + if( OPMODE&WIFI_P2P_SUPPORT && (P2PMODE==P2P_CLIENT)) { + if (caseTimer2) { + RTL_W32(HIMR, RTL_R32(HIMR) & ~HIMR_TIMEOUT2); + p2p_noa_timer(priv); + } + } +#endif + + if ((retry_cnt++)pshare->call_dsr); +#else + return SUCCESS; +#endif +} +#else +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +__inline__ static int __rtl8192cd_interrupt(void *dev_instance) +{ + return 0; +} +#endif//CONFIG_WLAN_NOT_HAL_EXIST + + +#ifdef __ECOS +__MIPS16 +__IRAM_IN_865X +int rtl8192cd_interrupt(struct net_device *dev_instance) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)dev_instance->priv; + priv->pshare->call_dsr = 0; +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + __rtl_wlan_interrupt((void *)dev_instance); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + __rtl8192cd_interrupt(dev_instance); + return (priv->pshare->call_dsr); +} +#else +#ifdef __LINUX_2_6__ +__MIPS16 +__IRAM_IN_865X +irqreturn_t rtl8192cd_interrupt(int irq, void *dev_instance) +{ +#ifdef CONFIG_WLAN_HAL + struct net_device *dev = (struct net_device *)dev_instance; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + if (IS_HAL_CHIP(priv)) + __rtl_wlan_interrupt(dev_instance); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + __rtl8192cd_interrupt(dev_instance); + return IRQ_HANDLED; +} +#else +__MIPS16 +__IRAM_IN_865X +void rtl8192cd_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ +#ifdef CONFIG_WLAN_HAL + struct net_device *dev = (struct net_device *)dev_instance; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + if (IS_HAL_CHIP(priv)) + __rtl_wlan_interrupt(dev_instance); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + __rtl8192cd_interrupt(dev_instance); + + return; +} +#endif +#endif /* ! __ECOS */ +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_NETDEV_MULTI_TX_QUEUE) || defined(CONFIG_SDIO_TX_FILTER_BY_PRI) +const u16 rtw_1d_to_queue[8] = { + _NETDEV_TX_QUEUE_BE, /* 0 */ + _NETDEV_TX_QUEUE_BK, /* 1 */ + _NETDEV_TX_QUEUE_BK, /* 2 */ + _NETDEV_TX_QUEUE_BE, /* 3 */ + _NETDEV_TX_QUEUE_VI, /* 4 */ + _NETDEV_TX_QUEUE_VI, /* 5 */ + _NETDEV_TX_QUEUE_VO, /* 6 */ + _NETDEV_TX_QUEUE_VO /* 7 */ +}; + +#if defined(__KERNEL__) +/* Given a data frame determine the 802.1p/1d tag to use. */ +unsigned int rtw_classify8021d(struct sk_buff *skb) +{ + struct iphdr *iph; + unsigned int dscp; + + /* skb->priority values from 256->263 are magic values to + * directly indicate a specific 802.1d priority. This is used + * to allow 802.1d priority to be passed directly in from VLAN + * tags, etc. + */ + if (skb->priority >= 256 && skb->priority <= 263) + return skb->priority - 256; + + switch (skb->protocol) { + case htons(ETH_P_IP): + // msg from user space. In this case, skb_network_header(skb) is available, but skb_mac_header(skb) is NULL. + iph = ip_hdr(skb); + if (NULL == iph) { + // msg through acceleration layer. In this case, skb_network_header(skb) is NULL, but skb_mac_header(skb) is available. + iph = (struct iphdr*)(skb_mac_header(skb) + ETH_HLEN); + } + dscp = iph->tos & 0xfc; + break; + default: + return 0; + } + + return dscp >> 5; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)) +u16 rtl8192cd_select_queue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)) +u16 rtl8192cd_select_queue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv) +#else +u16 rtl8192cd_select_queue(struct net_device *dev, struct sk_buff *skb) +#endif +{ + skb->priority = rtw_classify8021d(skb); + + return rtw_1d_to_queue[skb->priority]; +} +#elif defined(__ECOS) +/* Given a data frame determine the 802.1p/1d tag to use. */ +unsigned int rtw_classify8021d(struct sk_buff *skb) +{ + unsigned int dscp; + struct ip *ip; + struct ether_header *eh = SKB_MAC_HEADER(skb); + + /* skb->priority values from 256->263 are magic values to + * directly indicate a specific 802.1d priority. This is used + * to allow 802.1d priority to be passed directly in from VLAN + * tags, etc. + */ + if (eh->ether_type == htons(ETH_P_IP)) { + ip = (struct ip *)((char *)eh + sizeof(struct ether_header)); //fixme for TX_SCATTER + dscp = ip->ip_tos & 0xfc; + return dscp >> 5; + } + return 0; +} + +u16 rtl8192cd_select_queue(struct net_device *dev, struct sk_buff *skb) +{ + unsigned int priority; + + priority = rtw_classify8021d(skb); + return rtw_1d_to_queue[priority]; +} +#endif +#endif // CONFIG_NETDEV_MULTI_TX_QUEUE + +#ifdef __KERNEL__ +static void rtl8192cd_set_rx_mode(struct net_device *dev) +{ + +} +#endif /* __KERNEL__ */ + + +static struct net_device_stats *rtl8192cd_get_stats(struct net_device *dev) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + +#ifdef WDS + int idx; + struct stat_info *pstat; +#endif + + if(!priv) + priv = ((struct rtl8192cd_priv *)netdev_priv(dev)); + + SMP_LOCK(flags); + +#ifdef WDS + if (dev->base_addr == 0) { + idx = getWdsIdxByDev(priv, dev); + if (idx < 0) { + memset(&priv->wds_stats[NUM_WDS-1], 0, sizeof(struct net_device_stats)); + SMP_UNLOCK(flags); + return &priv->wds_stats[NUM_WDS-1]; + } + + if (netif_running(dev) && IS_DRV_OPEN(priv)) { + pstat = get_stainfo(priv, priv->pmib->dot11WdsInfo.entry[idx].macAddr); + if (pstat == NULL) { + DEBUG_ERR("%s: get_stainfo() wds fail!\n", (char *)__FUNCTION__); + memset(&priv->wds_stats[idx], 0, sizeof(struct net_device_stats)); + } + else { + priv->wds_stats[idx].tx_packets = pstat->tx_pkts; + priv->wds_stats[idx].tx_errors = pstat->tx_fail; + priv->wds_stats[idx].tx_bytes = pstat->tx_bytes; + priv->wds_stats[idx].rx_packets = pstat->rx_pkts; + priv->wds_stats[idx].rx_bytes = pstat->rx_bytes; + } + } + SMP_UNLOCK(flags); + return &priv->wds_stats[idx]; + } +#endif + +#ifdef CONFIG_RTK_MESH + + if (dev->base_addr == 1) { + if(priv->mesh_dev != dev) + { + SMP_UNLOCK(flags); + return NULL; + } + + SMP_UNLOCK(flags); + return &priv->mesh_stats; + } +#endif // CONFIG_RTK_MESH + + SMP_UNLOCK(flags); + return &(priv->net_stats); +} + +#if defined(CONFIG_WLAN_HAL) && defined(CONFIG_PCI_HCI) +static void +rtl88xx_init_swtxdec( + struct rtl8192cd_priv *priv +) +{ + struct rtl8192cd_hw *phw=NULL; + struct tx_desc_info *tx_info; + u4Byte max_qnum = HIGH_QUEUE7; + u4Byte QueueIdx; + u4Byte i; + + phw = GET_HW(priv); + + for (QueueIdx=0; QueueIdx<=max_qnum; QueueIdx++) { + tx_info = get_txdesc_info(&phw->tx_info, QueueIdx); + tx_info->type = _RESERVED_FRAME_TYPE_; + + for (i=0; i<(TXBD_ELE_NUM-2);i++) { + tx_info->buf_type[i] = _RESERVED_FRAME_TYPE_; + } + } +} +#endif // CONFIG_WLAN_HAL && CONFIG_PCI_HCI + +static int rtl8192cd_init_sw(struct rtl8192cd_priv *priv) +{ + // All the index/counters should be reset to zero... + struct rtl8192cd_hw *phw=NULL; + unsigned long offset; + unsigned int i; + struct wlan_hdr_poll *pwlan_hdr_poll; + struct wlanllc_hdr_poll *pwlanllc_hdr_poll; + struct wlanbuf_poll *pwlanbuf_poll; + struct wlanicv_poll *pwlanicv_poll; + struct wlanmic_poll *pwlanmic_poll; + struct wlan_acl_poll *pwlan_acl_poll; +#ifdef _MESH_ACL_ENABLE_ + struct mesh_acl_poll *pmesh_acl_poll; +#endif +#ifdef CONFIG_PCI_HCI + unsigned long ring_virt_addr; + unsigned long ring_dma_addr; + unsigned int ring_buf_len; +#ifndef PRIV_STA_BUF + unsigned long alloc_dma_buf; +#endif + struct sk_buff *pskb; + unsigned char *page_ptr; +#ifndef USE_RTL8186_SDK + unsigned long tx_dma_start; + struct tx_desc *tx_desc_ptr; +#endif +#endif // CONFIG_PCI_HCI + unsigned char MIMO_TR_hw_support; + unsigned int NumTotalRFPath; +#if defined(CLIENT_MODE) && defined(CHECK_HANGUP) + unsigned char *pbackup=NULL; + unsigned long backup_len=0; +#endif +#ifdef _11s_TEST_MODE_ + struct Galileo_poll *pgalileo_poll; +#endif + +#ifdef RTK_AC_SUPPORT //for 11ac logo + if(priv->pshare->rf_ft_var.no_rtscts) + { + printk("\n NO CTS & RTS !! \n\n"); + if(GET_CHIP_VER(priv) == VERSION_8812E) + { + priv->pshare->rf_ft_var.cca_rts = 0; + priv->pmib->dot11StationConfigEntry.protectionDisabled = 1; + } + } +#endif + +#ifdef BEAMFORMING_SUPPORT +#ifdef UNIVERSAL_REPEATER + if(priv->pmib->dot11RFEntry.txbf && IS_VXD_INTERFACE(priv)) + { + if(GET_ROOT(priv)->pmib->miscEntry.func_off && GET_ROOT(priv)->pmib->miscEntry.vap_enable==0) + printk("Use VXD as pure client mode, OK to use TXBF\n"); + else + { + priv->pmib->dot11RFEntry.txbf = 0; + printk("Use VXD for repeater mode, Disable TXBF\n"); + } + } +#endif +#endif + +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + priv->simple_config_could_fix = 0; + priv->pmib->dot11StationConfigEntry.sc_fix_channel = 0; +#endif + +#if defined(DFS) && !defined(RTK_NL80211) + /* + * For JAPAN : prevent switching to channels 52, 56, 60, and 64 in adhoc mode + */ + if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) || + (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK3)) && + (OPMODE & WIFI_ADHOC_STATE)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { + /* block channels 52~64 and place them in NOP_chnl */ + if (!timer_pending(&priv->ch52_timer)) + InsertChannel(priv->NOP_chnl, &priv->NOP_chnl_num, 52); + if (!timer_pending(&priv->ch56_timer)) + InsertChannel(priv->NOP_chnl, &priv->NOP_chnl_num, 56); + if (!timer_pending(&priv->ch60_timer)) + InsertChannel(priv->NOP_chnl, &priv->NOP_chnl_num, 60); + if (!timer_pending(&priv->ch64_timer)) + InsertChannel(priv->NOP_chnl, &priv->NOP_chnl_num, 64); + } + + /* if users select an illegal channel, the driver will switch to channel 36~48 */ + if ((priv->pmib->dot11RFEntry.dot11channel >= 52) && (priv->pmib->dot11RFEntry.dot11channel <= 64)) { + PRINT_INFO("Channel %d is illegal in ad-hoc mode in Japan!\n", priv->pmib->dot11RFEntry.dot11channel); + priv->pmib->dot11RFEntry.dot11channel = DFS_SelectChannel(priv); + PRINT_INFO("Swiching to channel %d!\n", priv->pmib->dot11RFEntry.dot11channel); + } + } + + /* if users select a blocked channel, the driver will switch to unblocked channel */ + if (!priv->pmib->dot11DFSEntry.disable_DFS && + ((timer_pending(&priv->ch52_timer) && (priv->pmib->dot11RFEntry.dot11channel == 52)) || + (timer_pending(&priv->ch56_timer) && (priv->pmib->dot11RFEntry.dot11channel == 56)) || + (timer_pending(&priv->ch60_timer) && (priv->pmib->dot11RFEntry.dot11channel == 60)) || + (timer_pending(&priv->ch64_timer) && (priv->pmib->dot11RFEntry.dot11channel == 64)) || + (timer_pending(&priv->ch100_timer) && (priv->pmib->dot11RFEntry.dot11channel == 100)) || + (timer_pending(&priv->ch104_timer) && (priv->pmib->dot11RFEntry.dot11channel == 104)) || + (timer_pending(&priv->ch108_timer) && (priv->pmib->dot11RFEntry.dot11channel == 108)) || + (timer_pending(&priv->ch112_timer) && (priv->pmib->dot11RFEntry.dot11channel == 112)) || + (timer_pending(&priv->ch116_timer) && (priv->pmib->dot11RFEntry.dot11channel == 116)) || + (timer_pending(&priv->ch120_timer) && (priv->pmib->dot11RFEntry.dot11channel == 120)) || + (timer_pending(&priv->ch124_timer) && (priv->pmib->dot11RFEntry.dot11channel == 124)) || + (timer_pending(&priv->ch128_timer) && (priv->pmib->dot11RFEntry.dot11channel == 128)) || + (timer_pending(&priv->ch132_timer) && (priv->pmib->dot11RFEntry.dot11channel == 132)) || + (timer_pending(&priv->ch136_timer) && (priv->pmib->dot11RFEntry.dot11channel == 136)) || + (timer_pending(&priv->ch140_timer) && (priv->pmib->dot11RFEntry.dot11channel == 140)) || + (timer_pending(&priv->ch144_timer) && (priv->pmib->dot11RFEntry.dot11channel == 144)))) { + PRINT_INFO("Channel %d is still in none occupancy period!\n", priv->pmib->dot11RFEntry.dot11channel); + priv->pmib->dot11RFEntry.dot11channel = DFS_SelectChannel(priv); + PRINT_INFO("Swiching to channel %d!\n", priv->pmib->dot11RFEntry.dot11channel); + } + + /* disable all of the transmissions during channel availability check */ +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + priv->pmib->dot11DFSEntry.disable_tx = 0; + if (!priv->pmib->dot11DFSEntry.disable_DFS && + (((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)) || + ((priv->pmib->dot11RFEntry.dot11channel >= 100) && + (priv->pmib->dot11RFEntry.dot11channel <= 140)) || + ((priv->pmib->dot11RFEntry.dot11channel == 0) && + (priv->pmib->dot11RFEntry.band5GSelected & PHY_BAND_5G_1) == 0)) && + (OPMODE & WIFI_AP_STATE)) + priv->pmib->dot11DFSEntry.disable_tx = 1; + } +#endif + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_set(&priv->rtl_tx_skb_cnt, 0); + rtl_atomic_set(&priv->rtl_rx_skb_cnt, 0); +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef __KERNEL__ +#ifdef DFS + /* will not initialize the tasklet if the driver is rebooting due to the detection of radar */ + if (!priv->pmib->dot11DFSEntry.DFS_detected) +#endif + { +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif + { +#ifdef SMART_REPEATER_MODE + if (!priv->pshare->switch_chan_rp) +#endif + { +#ifdef CONFIG_RTL_SIMPLE_CONFIG + if(!priv->pmib->dot11StationConfigEntry.sc_enabled || ((priv->simple_config_status==0) && (IS_ROOT_INTERFACE(priv) +#ifdef UNIVERSAL_REPEATER +&& (GET_VXD_PRIV(priv)->simple_config_status==0) +#endif +))) +#endif + { +#ifdef PCIE_POWER_SAVING + tasklet_init(&priv->pshare->ps_tasklet, PCIe_power_save_tasklet, (unsigned long)priv); +#endif +#ifdef CONFIG_PCI_HCI +#if !(defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX)) + tasklet_init(&priv->pshare->rx_tasklet, rtl8192cd_rx_dsr, (unsigned long)priv); +#else +#ifdef RX_TASKLET + tasklet_init(&priv->pshare->rx_tasklet, rtl8192cd_rx_tkl_isr, (unsigned long)priv); +#endif +#endif + tasklet_init(&priv->pshare->tx_tasklet, rtl8192cd_tx_dsr, (unsigned long)priv); + tasklet_init(&priv->pshare->oneSec_tasklet, rtl8192cd_expire_timer, (unsigned long)priv); +#endif // CONFIG_PCI_HCI + } + } + } + } +#endif // __KERNEL__ + +#ifdef DFS + if (priv->pmib->dot11DFSEntry.DFS_detected) + priv->pmib->dot11DFSEntry.DFS_detected = 0; +#endif + + phw = GET_HW(priv); + + // save descriptor virtual address before reset, david +#ifdef CONFIG_PCI_HCI + ring_virt_addr = phw->ring_virt_addr; + ring_dma_addr = phw->ring_dma_addr; + ring_buf_len = phw->ring_buf_len; +#ifndef PRIV_STA_BUF + alloc_dma_buf = phw->alloc_dma_buf; +#endif +#endif // CONFIG_PCI_HCI + // save RF related settings before reset + MIMO_TR_hw_support = phw->MIMO_TR_hw_support; + NumTotalRFPath = phw->NumTotalRFPath; + + memset((void *)phw, 0, sizeof(struct rtl8192cd_hw)); +#ifdef CONFIG_PCI_HCI + phw->ring_virt_addr = ring_virt_addr; + phw->ring_buf_len = ring_buf_len; +#ifndef PRIV_STA_BUF + phw->alloc_dma_buf = alloc_dma_buf; +#endif + +#ifdef CONFIG_NET_PCI + if (IS_PCIBIOS_TYPE) + phw->ring_dma_addr = ring_dma_addr; +#endif +#endif // CONFIG_PCI_HCI + phw->MIMO_TR_hw_support = MIMO_TR_hw_support; + phw->NumTotalRFPath = NumTotalRFPath; + +#if defined(DUALBAND_ONLY) && defined(CONFIG_RTL8190_PRIV_SKB) + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + split_pool(priv); + else + merge_pool(priv); +#endif + } + +#if defined(CLIENT_MODE) && defined(CHECK_HANGUP) && defined(RTK_BR_EXT) + if (priv->reset_hangup && + (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE))) { + backup_len = ((unsigned long)&((struct rtl8192cd_priv *)0)->br_ip) - + ((unsigned long)&((struct rtl8192cd_priv *)0)->join_res)+4; + pbackup = kmalloc(backup_len, GFP_ATOMIC); + if (pbackup) + memcpy(pbackup, &priv->join_res, backup_len); + } +#endif + + offset = (unsigned long)(&((struct rtl8192cd_priv *)0)->net_stats); + // zero all data members below (including) stats + memset((void *)((unsigned long)priv + offset), 0, sizeof(struct rtl8192cd_priv)-offset); + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) + priv->site_survey->count=0; +#endif + +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif + { +#ifdef SMART_REPEATER_MODE + if (!priv->pshare->switch_chan_rp) +#endif + { + + priv->up_time = 0; + } + } + +#if defined(CLIENT_MODE) && defined(CHECK_HANGUP) + if (priv->reset_hangup && pbackup) { + memcpy(&priv->join_res, pbackup, backup_len); + kfree(pbackup); + } +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + // zero all data members below (including) LED_Timer of share_info + offset = (unsigned long)(&((struct priv_shared_info*)0)->LED_Timer); + memset((void *)((unsigned long)priv->pshare+ offset), 0, sizeof(struct priv_shared_info)-offset); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + // re-initialize timer_evt_queue to make sure timer_evt_queue is empty before cmd_thread activate + _rtw_init_listhead(&priv->pshare->timer_evt_queue.queue); + priv->pshare->timer_evt_queue.qlen = 0; + // re-initialize beacon_timer + _rtw_init_listhead(&priv->pshare->beacon_timer_event.list); +#endif + +#ifdef CONFIG_USB_HCI +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif +#ifdef SMART_REPEATER_MODE + if (!priv->pshare->switch_chan_rp) +#endif + { + init_completion(&priv->pshare->cmd_thread_done); + priv->pshare->cmd_thread = kthread_run(rtw_cmd_thread, priv, "rtw_cmd/%s", priv->dev->name); + if (IS_ERR(priv->pshare->cmd_thread)) { + priv->pshare->cmd_thread = NULL; + printk("[%s] create cmd_thread fail\n", __FUNCTION__); + return 1; + } + } +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI + init_completion(&priv->pshare->xmit_thread_done); +#ifdef __ECOS + priv->pshare->xmit_thread = create_rtw_xmit_thread(priv); + if (*priv->pshare->xmit_thread == 0) { + priv->pshare->xmit_thread = NULL; + printk("[%s] create xmit_thread fail\n", __FUNCTION__); + return 1; + } +#else + priv->pshare->xmit_thread = kthread_run(rtw_xmit_thread, priv, "rtw_xmit/%s", priv->dev->name); + if (IS_ERR(priv->pshare->xmit_thread)) { + priv->pshare->xmit_thread = NULL; + printk("[%s] create xmit_thread fail\n", __FUNCTION__); + return 1; + } +#endif + +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif +#ifdef SMART_REPEATER_MODE + if (!priv->pshare->switch_chan_rp) +#endif + { + init_completion(&priv->pshare->cmd_thread_done); +#ifdef __ECOS + priv->pshare->cmd_thread = create_rtw_cmd_thread(priv); + if (*priv->pshare->cmd_thread == 0) { + priv->pshare->cmd_thread = NULL; + printk("[%s] create cmd_thread fail\n", __FUNCTION__); + return 1; + } +#else + priv->pshare->cmd_thread = kthread_run(rtw_cmd_thread, priv, "rtw_cmd/%s", priv->dev->name); + if (IS_ERR(priv->pshare->cmd_thread)) { + priv->pshare->cmd_thread = NULL; + printk("[%s] create cmd_thread fail\n", __FUNCTION__); + return 1; + } +#endif + } +#endif // CONFIG_SDIO_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + mod_timer(&priv->pshare->xmit_check_timer, jiffies + RTL_SECONDS_TO_JIFFIES(1)); +#endif + +#ifdef CONFIG_RTK_MESH + memset((void *)&priv->pshare->meshare, 0, sizeof(struct MESH_Share)); + get_random_bytes((void *)&priv->pshare->meshare.seq, sizeof(priv->pshare->meshare.seq)); +#if (MESH_DBG_LV & MESH_DBG_COMPLEX) + init_timer(&priv->pshare->meshare.mesh_test_sme_timer); + priv->pshare->meshare.mesh_test_sme_timer.data = (unsigned long) priv; + priv->pshare->meshare.mesh_test_sme_timer.function = mesh_test_sme_timer; + mod_timer(&priv->pshare->meshare.mesh_test_sme_timer, jiffies + RTL_SECONDS_TO_JIFFIES(2)); +#endif // (MESH_DBG_LV & MESH_DBG_COMPLEX) + +#if (MESH_DBG_LV & MESH_DBG_TEST) + init_timer(&priv->pshare->meshare.mesh_test_sme_timer2); + priv->pshare->meshare.mesh_test_sme_timer2.data = (unsigned long) priv; + priv->pshare->meshare.mesh_test_sme_timer2.function = mesh_test_sme_timer2; + mod_timer(&priv->pshare->meshare.mesh_test_sme_timer2, jiffies + RTL_SECONDS_TO_JIFFIES(50)); +#endif // (MESH_DBG_LV & MESH_DBG_TEST) + +#endif // CONFIG_RTK_MESH + + pwlan_hdr_poll = priv->pshare->pwlan_hdr_poll; + pwlanllc_hdr_poll = priv->pshare->pwlanllc_hdr_poll; + pwlanbuf_poll = priv->pshare->pwlanbuf_poll; + pwlanicv_poll = priv->pshare->pwlanicv_poll; + pwlanmic_poll = priv->pshare->pwlanmic_poll; + +#ifdef _11s_TEST_MODE_ + pgalileo_poll = priv->pshare->galileo_poll; + pgalileo_poll->count = AODV_RREQ_TABLE_SIZE; +#endif + pwlan_hdr_poll->count = PRE_ALLOCATED_HDR; + pwlanllc_hdr_poll->count = PRE_ALLOCATED_HDR; + pwlanbuf_poll->count = PRE_ALLOCATED_MMPDU; + pwlanicv_poll->count = PRE_ALLOCATED_HDR; + pwlanmic_poll->count = PRE_ALLOCATED_HDR; + + // initialize all the hdr/buf node, and list to the poll_list + INIT_LIST_HEAD(&priv->pshare->wlan_hdrlist); + INIT_LIST_HEAD(&priv->pshare->wlanllc_hdrlist); + INIT_LIST_HEAD(&priv->pshare->wlanbuf_list); + INIT_LIST_HEAD(&priv->pshare->wlanicv_list); + INIT_LIST_HEAD(&priv->pshare->wlanmic_list); + +#ifdef _11s_TEST_MODE_ //Galileo + + memset(priv->rvTestPacket, 0, 3000); + + INIT_LIST_HEAD(&priv->pshare->galileo_list); + INIT_LIST_HEAD(&priv->mtb_list); + + for(i=0; i< AODV_RREQ_TABLE_SIZE; i++) + { + INIT_LIST_HEAD(&(pgalileo_poll->node[i].list)); + list_add_tail(&(pgalileo_poll->node[i].list), &priv->pshare->galileo_list); + init_timer(&pgalileo_poll->node[i].data.expire_timer); + pgalileo_poll->node[i].data.priv = priv; + pgalileo_poll->node[i].data.expire_timer.function = galileo_timer; + } +#endif + + for(i=0; i< PRE_ALLOCATED_HDR; i++) + { + INIT_LIST_HEAD(&(pwlan_hdr_poll->hdrnode[i].list)); + list_add_tail(&(pwlan_hdr_poll->hdrnode[i].list), &priv->pshare->wlan_hdrlist); + + INIT_LIST_HEAD(&(pwlanllc_hdr_poll->hdrnode[i].list)); + list_add_tail( &(pwlanllc_hdr_poll->hdrnode[i].list), &priv->pshare->wlanllc_hdrlist); + + INIT_LIST_HEAD(&(pwlanicv_poll->hdrnode[i].list)); + list_add_tail( &(pwlanicv_poll->hdrnode[i].list), &priv->pshare->wlanicv_list); + + INIT_LIST_HEAD(&(pwlanmic_poll->hdrnode[i].list)); + list_add_tail( &(pwlanmic_poll->hdrnode[i].list), &priv->pshare->wlanmic_list); + } + + for(i=0; i< PRE_ALLOCATED_MMPDU; i++) + { + INIT_LIST_HEAD(&(pwlanbuf_poll->hdrnode[i].list)); + list_add_tail( &(pwlanbuf_poll->hdrnode[i].list), &priv->pshare->wlanbuf_list); + } + + DEBUG_INFO("hdrlist=%lx, llc_hdrlist=%lx, buf_list=%lx, icv_list=%lx, mic_list=%lx\n", + (unsigned long)&priv->pshare->wlan_hdrlist, (unsigned long)&priv->pshare->wlanllc_hdrlist, + (unsigned long)&priv->pshare->wlanbuf_list, (unsigned long)&priv->pshare->wlanicv_list, + (unsigned long)&priv->pshare->wlanmic_list); + +#ifdef CONFIG_PCI_HCI + page_ptr = (unsigned char *)phw->ring_virt_addr; + memset(page_ptr, 0, phw->ring_buf_len); // this is vital! + + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + phw->ring_dma_addr = 0; + phw->rx_ring_addr = 0; + phw->tx_ring0_addr = 0; + phw->tx_ring1_addr = 0; + phw->tx_ring2_addr = 0; + phw->tx_ring3_addr = 0; + phw->tx_ring4_addr = 0; + phw->tx_ring5_addr = 0; + phw->tx_ringB_addr = 0; + + memset(&phw->tx_desc0_dma_addr, 0, sizeof(unsigned long) * NUM_TX_DESC); + memset(&phw->tx_desc1_dma_addr, 0, sizeof(unsigned long) * NUM_TX_DESC); + memset(&phw->tx_desc2_dma_addr, 0, sizeof(unsigned long) * NUM_TX_DESC); + memset(&phw->tx_desc3_dma_addr, 0, sizeof(unsigned long) * NUM_TX_DESC); + memset(&phw->tx_desc4_dma_addr, 0, sizeof(unsigned long) * NUM_TX_DESC); + memset(&phw->tx_desc5_dma_addr, 0, sizeof(unsigned long) * NUM_TX_DESC); + memset(&phw->tx_descB_dma_addr, 0, sizeof(unsigned long) * NUM_TX_DESC); + memset(&phw->rx_descL_dma_addr, 0, sizeof(unsigned long) * NUM_RX_DESC); + + phw->rx_descL = NULL; + phw->tx_desc0 = NULL; + phw->tx_desc1 = NULL; + phw->tx_desc2 = NULL; + phw->tx_desc3 = NULL; + phw->tx_desc4 = NULL; + phw->tx_desc5 = NULL; + phw->tx_descB = NULL; + + memset(&phw->rx_descL_dma_addr, 0, sizeof(unsigned long) * NUM_RX_DESC) ; + + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#ifdef CONFIG_NET_PCI + if (!IS_PCIBIOS_TYPE) +#endif + phw->ring_dma_addr = virt_to_bus(page_ptr)+CONFIG_LUNA_SLAVE_PHYMEM_OFFSET; + + phw->rx_ring_addr = phw->ring_dma_addr; + phw->tx_ring0_addr = phw->ring_dma_addr + NUM_RX_DESC * sizeof(struct rx_desc); + phw->tx_ring1_addr = phw->tx_ring0_addr + NUM_TX_DESC * sizeof(struct tx_desc); + phw->tx_ring2_addr = phw->tx_ring1_addr + NUM_TX_DESC * sizeof(struct tx_desc); + phw->tx_ring3_addr = phw->tx_ring2_addr + NUM_TX_DESC * sizeof(struct tx_desc); + phw->tx_ring4_addr = phw->tx_ring3_addr + NUM_TX_DESC * sizeof(struct tx_desc); + phw->tx_ring5_addr = phw->tx_ring4_addr + NUM_TX_DESC * sizeof(struct tx_desc); + phw->tx_ringB_addr = phw->tx_ring5_addr + NUM_TX_DESC * sizeof(struct tx_desc); + + phw->rx_descL = (struct rx_desc *)page_ptr; + phw->tx_desc0 = (struct tx_desc *)(page_ptr + NUM_RX_DESC * sizeof(struct rx_desc)); + phw->tx_desc1 = (struct tx_desc *)((unsigned long)phw->tx_desc0 + NUM_TX_DESC * sizeof(struct tx_desc)); + phw->tx_desc2 = (struct tx_desc *)((unsigned long)phw->tx_desc1 + NUM_TX_DESC * sizeof(struct tx_desc)); + phw->tx_desc3 = (struct tx_desc *)((unsigned long)phw->tx_desc2 + NUM_TX_DESC * sizeof(struct tx_desc)); + phw->tx_desc4 = (struct tx_desc *)((unsigned long)phw->tx_desc3 + NUM_TX_DESC * sizeof(struct tx_desc)); + phw->tx_desc5 = (struct tx_desc *)((unsigned long)phw->tx_desc4 + NUM_TX_DESC * sizeof(struct tx_desc)); + phw->tx_descB = (struct tx_desc *)((unsigned long)phw->tx_desc5 + NUM_TX_DESC * sizeof(struct tx_desc)); + + /* To set the DMA address for both RX/TX ring */ + { +#ifndef USE_RTL8186_SDK + int txDescRingIdx; + + struct tx_desc *tx_desc_array[] = { + phw->tx_desc0, + phw->tx_desc1, + phw->tx_desc2, + phw->tx_desc3, + phw->tx_desc4, + phw->tx_desc5, + phw->tx_descB, + 0 + }; +#ifdef CONFIG_NET_PCI + unsigned long *tx_desc_dma_array[] = { + (unsigned long*)(phw->tx_desc0_dma_addr), + (unsigned long*)(phw->tx_desc1_dma_addr), + (unsigned long*)(phw->tx_desc2_dma_addr), + (unsigned long*)(phw->tx_desc3_dma_addr), + (unsigned long*)(phw->tx_desc4_dma_addr), + (unsigned long*)(phw->tx_desc5_dma_addr), + (unsigned long*)(phw->tx_descB_dma_addr), + (unsigned long*)0 + }; +#endif +#endif // !USE_RTL8186_SDK + + /* RX RING */ +#if defined(NOT_RTK_BSP) + for (i=0; irx_descL_dma_addr[i] = phw->rx_ring_addr + i*(sizeof(struct rx_desc)); + } +#else + for (i=0; irx_descL_dma_addr[i] = get_physical_addr(priv, (void *)(&phw->rx_descL[i]), + sizeof(struct rx_desc), PCI_DMA_TODEVICE); + } +#endif + +#ifndef USE_RTL8186_SDK + +#if defined(NOT_RTK_BSP) + tx_dma_start = phw->ring_dma_addr + NUM_RX_DESC * sizeof(struct rx_desc); +#endif + + /* TX RING */ + txDescRingIdx = 0; + + while (tx_desc_array[txDescRingIdx] != 0) { +#ifdef CONFIG_NET_PCI + unsigned long *tx_desc_dma_ptr = tx_desc_dma_array[txDescRingIdx]; +#endif + tx_desc_ptr = tx_desc_array[txDescRingIdx]; + +#if defined(NOT_RTK_BSP) + for (i=0; irx_descL, (unsigned long)phw->tx_desc0, (unsigned long)phw->tx_desc1, (unsigned long)phw->tx_desc2, + (unsigned long)phw->tx_desc3, (unsigned long)phw->tx_desc4, (unsigned long)phw->tx_desc5, (unsigned long)phw->tx_descB); + } +#endif // CONFIG_PCI_HCI + +#if !(defined(__ECOS) && defined(CONFIG_SDIO_HCI)) +#ifdef RTK_QUE + rtk_queue_init(&priv->pshare->skb_queue); +#else + skb_queue_head_init(&priv->pshare->skb_queue); +#endif +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + // this three functions must be called in this seqence...it cannot be moved arbitrarily + //GET_HAL_INTERFACE(priv)->InitHCIDMAMemHandler(priv); + // RX_BUF_LEN must include RX_DESC and Payload + GET_HAL_INTERFACE(priv)->PrepareRXBDHandler(priv, RX_BUF_LEN, init_rxdesc_88XX); + GET_HAL_INTERFACE(priv)->PrepareTXBDHandler(priv); + + //Filen, init SW TXDESC Type + //To avoid recycle error + rtl88xx_init_swtxdec(priv); + +// TODO: check the following compile flag...ex: USE_TXQUEUE... + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + // Now for Rx desc... + for(i=0; itx_desc0, phw->tx_ring0_addr, i); + init_txdesc(priv, phw->tx_desc1, phw->tx_ring1_addr, i); + init_txdesc(priv, phw->tx_desc2, phw->tx_ring2_addr, i); + init_txdesc(priv, phw->tx_desc3, phw->tx_ring3_addr, i); + init_txdesc(priv, phw->tx_desc4, phw->tx_ring4_addr, i); + init_txdesc(priv, phw->tx_desc5, phw->tx_ring5_addr, i); + } + +#ifdef MBSSID + for(i=0; i<(RTL8192CD_NUM_VWLAN+1); i++) { + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + if (i == RTL8192CD_NUM_VWLAN) + (phw->tx_descB + i)->Dword10 = set_desc(phw->tx_ringB_addr); + //(phw->tx_descB + i)->NextTxDescAddress = set_desc(phw->tx_ringB_addr); + else + (phw->tx_descB + i)->Dword10 = set_desc(phw->tx_ringB_addr + (i+1) * sizeof(struct tx_desc)); + //(phw->tx_descB + i)->NextTxDescAddress = set_desc(phw->tx_ringB_addr + (i+1) * sizeof(struct tx_desc)); + } + } +#endif + + //Family add: must re-initialize use_txdesc_cnt after realloc txdesc +#ifdef RESERVE_TXDESC_FOR_EACH_IF + for(i=0; i<=HIGH_QUEUE; ++i) { + priv->use_txdesc_cnt[i] = 0; + } + +#ifdef USE_TXQUEUE + for(i=0; i<=HIGH_QUEUE; i++) { + priv->use_txq_cnt[i] = 0; + } +#endif + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable){ + int j; + for (i=0; ipvap_priv[i]->use_txdesc_cnt[j] = 0; + } +#ifdef USE_TXQUEUE + for (j=0; j<=HIGH_QUEUE; j++) { + priv->pvap_priv[i]->use_txq_cnt[j] = 0; + } +#endif + } + } +#endif // #ifdef MBSSID +#ifdef UNIVERSAL_REPEATER + if (GET_VXD_PRIV(priv)) { + for(i=0; i<=HIGH_QUEUE; ++i) { + GET_VXD_PRIV(priv)->use_txdesc_cnt[i] = 0; + } +#ifdef USE_TXQUEUE + for(i=0; i<=HIGH_QUEUE; ++i) { + GET_VXD_PRIV(priv)->use_txq_cnt[i] = 0; + } +#endif + } +#endif // UNIVERSAL_REPEATER +#endif // RESERVE_TXDESC_FOR_EACH_IF + + } +#endif // CONFIG_PCI_HCI + + priv->pshare->amsdu_timer_head = priv->pshare->amsdu_timer_tail = 0; + +#ifdef RX_BUFFER_GATHER + INIT_LIST_HEAD(&priv->pshare->gather_list); +#endif + +#ifdef USE_TXQUEUE + if (init_txq_pool(&priv->pshare->txq_pool, &priv->pshare->txq_pool_addr)) { + printk("Can not init tx queue pool.\n"); + return 1; + } + for (i=0; i<7; i++) + init_txq_head(&(priv->pshare->txq_list[i])); + priv->pshare->txq_isr = 0; + priv->pshare->txq_stop = 0; + priv->pshare->txq_check = 0; +#endif + + +#if (defined(CONFIG_SLOT_0_ANT_SWITCH)|| defined(CONFIG_SLOT_1_ANT_SWITCH)||defined(CONFIG_RTL_8881A_ANT_SWITCH)) + if(!CHIP_VER_92X_SERIES(priv)) + priv->pshare->rf_ft_var.antHw_enable=0; +#endif + + +#ifdef TX_EARLY_MODE + //if ((GET_CHIP_VER(priv) == VERSION_8192C || GET_CHIP_VER(priv) == VERSION_8188C) + // && GET_TX_EARLY_MODE) + if ((GET_CHIP_VER(priv) != VERSION_8188E) && GET_TX_EARLY_MODE) + GET_TX_EARLY_MODE = 0; +#endif + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if(GET_CHIP_VER(priv) == VERSION_8192C || GET_CHIP_VER(priv) == VERSION_8192D || GET_CHIP_VER(priv) == VERSION_8188C) { + priv->pshare->fw_support_sta_num = RTL8192CD_NUM_STAT - 1; // One for MAGANEMENT_AID + priv->pshare->total_cam_entry = 32; + } + else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + priv->pshare->fw_support_sta_num = RTL8188E_NUM_STAT - 1; // One for MAGANEMENT_AID + priv->pshare->total_cam_entry = 64; + } + else +#endif + { + priv->pshare->fw_support_sta_num = FW_NUM_STAT - 1; // One for MAGANEMENT_AID + priv->pshare->total_cam_entry = 64; + } + priv->pshare->fw_free_space = priv->pshare->fw_support_sta_num; + if(NUM_STAT > priv->pshare->fw_support_sta_num) { + priv->pshare->fw_free_space--; + } + + } + + // + //hw features support examinations for root, vxd, and vap interfaces + // + + // Only 2.4G need to care about 20/40 coexist + if ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A)) + priv->pmib->dot11nConfigEntry.dot11nCoexist = 0; + + if ((priv->pmib->dot11RFEntry.tx2path || priv->pmib->dot11RFEntry.bcn2path) && ((get_rf_mimo_mode(priv) == MIMO_1T1R) || + ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific))) { + DEBUG_INFO("Disable tx2path due to 1T1R or MP mode.\n"); + priv->pmib->dot11RFEntry.tx2path = 0; + priv->pmib->dot11RFEntry.bcn2path= 0; + } + + if (priv->pmib->dot11RFEntry.tx2path) { + if(CHIP_VER_92X_SERIES(priv)){ + if (priv->pmib->dot11RFEntry.txbf) { + priv->pmib->dot11RFEntry.tx2path = 0; + DEBUG_INFO("Disable tx2path due to txbf\n"); + } + } + } + //bcn2path only 92C & 92E support + if(priv->pmib->dot11RFEntry.bcn2path && !(GET_CHIP_VER(priv)==VERSION_8192C || GET_CHIP_VER(priv)==VERSION_8192E)) + priv->pmib->dot11RFEntry.bcn2path = 0; + + //when bcn2path is enable, it should always transmit beacon with two path, close power saving rf_mode + if(priv->pmib->dot11RFEntry.bcn2path && get_rf_mimo_mode(priv) == MIMO_2T2R){ + priv->pmib->dot11RFEntry.tx2path = 0; + DEBUG_INFO("Disable tx2path due to bcn2path\n"); +#ifdef RF_MIMO_SWITCH + priv->pshare->rf_ft_var.rf_mode = 2; + DEBUG_INFO("Disable rf_mode due to bcn2path\n"); +#endif + } + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8812E && (RTL8192CD_NUM_VWLAN >5)) { + priv->pmib->dot11RFEntry.txbf =0; + } +#endif + if ((GET_CHIP_VER(priv) != VERSION_8812E) && (GET_CHIP_VER(priv) != VERSION_8192E)) { + if (priv->pmib->dot11RFEntry.txbf) { + if (priv->pmib->dot11nConfigEntry.dot11nSTBC) { + priv->pmib->dot11nConfigEntry.dot11nSTBC = 0; + DEBUG_INFO("Disable stbc due to txbf\n"); + } + } + } + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + priv->pmib->dot11nConfigEntry.dot11nLDPC = priv->pshare->rf_ft_var.ldpc_92e; +#endif + + if(GET_CHIP_VER(priv) < VERSION_8812E) { + priv->pmib->dot11nConfigEntry.dot11nLDPC = 0; + DEBUG_INFO("Disable LDPC due to old chip\n"); + } +#ifdef CONFIG_RTL_8812_SUPPORT + if( IS_B_CUT_8812(priv)) + { + printk("8812 B CUT, Disable LDPC\n"); + priv->pmib->dot11nConfigEntry.dot11nLDPC = 0; + } +#endif + +#if defined(RTK_NL80211) && defined(RTK_NL80211_HS_CLI) + init_timer(&priv->nl_ctx.remain_on_ch_timer); + priv->nl_ctx.remain_on_ch_timer.data = (unsigned long) priv; + priv->nl_ctx.remain_on_ch_timer.function = realtek_cfg80211_RemainOnChExpire; +#ifndef NOT_RTK_BSP + init_timer(&priv->nl_ctx.scan_deny_timer); + priv->nl_ctx.scan_deny_timer.data = (unsigned long) priv; + priv->nl_ctx.scan_deny_timer.function = rtk_p2p_scan_deny_expire; +#endif +#endif + +#if 0 +// disable txbf when antenna diversity is enabled + if(GET_CHIP_VER(priv) == VERSION_8192E) { +#if (defined(CONFIG_SLOT_0_ANT_SWITCH) && defined(CONFIG_SLOT_0_8192EE)) || (defined(CONFIG_SLOT_1_ANT_SWITCH) && defined(CONFIG_SLOT_1_8192EE)) + priv->pmib->dot11RFEntry.txbf = 0; +#endif + } + if(GET_CHIP_VER(priv) == VERSION_8812E) { +#if (defined(CONFIG_SLOT_0_ANT_SWITCH) && defined(CONFIG_SLOT_0_8812)) || (defined(CONFIG_SLOT_1_ANT_SWITCH) && defined(CONFIG_SLOT_1_8812)) + priv->pmib->dot11RFEntry.txbf = 0; +#endif + } +#endif + + INIT_LIST_HEAD(&priv->wlan_acl_list); + INIT_LIST_HEAD(&priv->wlan_aclpolllist); + + pwlan_acl_poll = priv->pwlan_acl_poll; + for(i=0; i< NUM_ACL; i++) + { + INIT_LIST_HEAD(&(pwlan_acl_poll->aclnode[i].list)); + list_add_tail(&(pwlan_acl_poll->aclnode[i].list), &priv->wlan_aclpolllist); + } + + // copy acl from mib to link list + for (i=0; ipmib->dot11StationConfigEntry.dot11AclNum; i++) + { + struct list_head *pnewlist; + struct wlan_acl_node *paclnode; + + pnewlist = priv->wlan_aclpolllist.next; + list_del_init(pnewlist); + + paclnode = list_entry(pnewlist, struct wlan_acl_node, list); + memcpy((void *)paclnode->addr, priv->pmib->dot11StationConfigEntry.dot11AclAddr[i], 6); + paclnode->mode = (unsigned char)priv->pmib->dot11StationConfigEntry.dot11AclMode; + + list_add_tail(pnewlist, &priv->wlan_acl_list); + } + + for(i=0; istat_hash[i])); + +#ifdef CONFIG_RTK_MESH + /* + * CAUTION !! These statement meshX(virtual interface) ONLY, Maybe modify.... + */ +#ifdef _MESH_ACL_ENABLE_ // copy acl from mib to link list (below code copy above ACL code) + INIT_LIST_HEAD(&priv->mesh_acl_list); + INIT_LIST_HEAD(&priv->mesh_aclpolllist); +#if defined(SMP_SYNC) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + spin_lock_init(&(priv->mesh_acl_list_lock)); +#endif + + priv->meshAclCacheMode = 0; /*clear mesh acl cache*/ + pmesh_acl_poll = priv->pmesh_acl_poll; + for(i=0; i< NUM_MESH_ACL; i++) + { + INIT_LIST_HEAD(&(pmesh_acl_poll->meshaclnode[i].list)); + list_add_tail(&(pmesh_acl_poll->meshaclnode[i].list), &priv->mesh_aclpolllist); + } + + for (i=0; ipmib->dot1180211sInfo.mesh_acl_num; i++) + { + struct list_head *pnewlist; + struct wlan_acl_node *paclnode; + + pnewlist = priv->mesh_aclpolllist.next; + list_del_init(pnewlist); + + paclnode = list_entry(pnewlist, struct wlan_acl_node, list); + memcpy((void *)paclnode->addr, priv->pmib->dot1180211sInfo.mesh_acl_addr[i], MACADDRLEN); + paclnode->mode = (unsigned char)priv->pmib->dot1180211sInfo.mesh_acl_mode; + + list_add_tail(pnewlist, &priv->mesh_acl_list); + } +#endif + +#ifdef MESH_BOOTSEQ_AUTH + INIT_LIST_HEAD(&(priv->mesh_auth_hdr)); +#endif + + INIT_LIST_HEAD(&(priv->mesh_unEstablish_hdr)); + INIT_LIST_HEAD(&(priv->mesh_mp_hdr)); +#if defined(SMP_SYNC) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + spin_lock_init(&(priv->mesh_mp_hdr_lock)); +#endif + + priv->mesh_profile[0].used = FALSE; // Configure by WEB in the future, Maybe delete, Preservation before delete +#endif + + INIT_LIST_HEAD(&(priv->asoc_list)); + INIT_LIST_HEAD(&(priv->auth_list)); + INIT_LIST_HEAD(&(priv->sleep_list)); + INIT_LIST_HEAD(&(priv->defrag_list)); + INIT_LIST_HEAD(&(priv->wakeup_list)); + INIT_LIST_HEAD(&(priv->rx_datalist)); + INIT_LIST_HEAD(&(priv->rx_mgtlist)); + INIT_LIST_HEAD(&(priv->rx_ctrllist)); +#ifdef CONFIG_PCI_HCI + INIT_LIST_HEAD(&(priv->addRAtid_list)); // to avoid add RAtid fail + INIT_LIST_HEAD(&(priv->addrssi_list)); +#endif + +#ifdef SMP_SYNC +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef __ECOS + _rtw_mutex_init(&(priv->hash_list_lock)); + _rtw_mutex_init(&(priv->auth_list_lock)); + _rtw_mutex_init(&(priv->sleep_list_lock)); + _rtw_mutex_init(&(priv->wakeup_list_lock)); +#else + spin_lock_init(&(priv->hash_list_lock)); + spin_lock_init(&(priv->auth_list_lock)); + spin_lock_init(&(priv->sleep_list_lock)); + spin_lock_init(&(priv->wakeup_list_lock)); +#endif +#elif defined(CONFIG_PCI_HCI) + spin_lock_init(&(priv->hash_list_lock)); +#endif + spin_lock_init(&(priv->rx_datalist_lock)); + spin_lock_init(&(priv->rx_mgtlist_lock)); + spin_lock_init(&(priv->rx_ctrllist_lock)); +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + _rtw_mutex_init(&(priv->rc_packet_q_lock)); +#else + spin_lock_init(&(priv->rc_packet_q_lock)); + spin_lock_init(&(priv->psk_gkrekey_lock)); + spin_lock_init(&(priv->psk_resend_lock)); +#endif +#endif + spin_lock_init(&priv->defrag_lock); + +#ifdef A4_STA + INIT_LIST_HEAD(&(priv->a4_sta_list)); +#endif + +#ifdef WIFI_SIMPLE_CONFIG + INIT_LIST_HEAD(&priv->wsc_disconn_list); + spin_lock_init(&priv->wsc_disconn_list_lock); +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + _init_txservq(&priv->tx_mc_queue, BE_QUEUE); + _init_txservq(&priv->tx_mgnt_queue, MGNT_QUEUE); +#endif + +#ifdef CHECK_BEACON_HANGUP + if (priv->reset_hangup) + priv->pshare->beacon_wait_cnt = 1; + else + priv->pshare->beacon_wait_cnt = 2; +#endif + +#ifdef CHECK_HANGUP + if (priv->reset_hangup) { + get_available_channel(priv); + validate_oper_rate(priv); + get_oper_rate(priv); + DOT11_InitQueue(priv->pevent_queue); +#if defined(TXREPORT) + priv->pshare->sta_query_idx=-1; + priv->pmib->staDetectInfo.txRprDetectPeriod = 1; +#endif + return 0; + } +#endif + +#ifdef CONFIG_RTL_8812AR_VN_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { // 8812AR-VN can not support AC mode + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) + priv->pmib->dot11BssType.net_work_type &= ~WIRELESS_11AC; + } +#endif + + // construct operation and basic rates set + { + // validate region domain + if ((priv->pmib->dot11StationConfigEntry.dot11RegDomain < DOMAIN_FCC) || + (priv->pmib->dot11StationConfigEntry.dot11RegDomain >= DOMAIN_MAX)) { + PRINT_INFO("invalid region domain, use default value [DOMAIN_FCC]!\n"); + priv->pmib->dot11StationConfigEntry.dot11RegDomain = DOMAIN_FCC; + } + + // validate band + if (priv->pmib->dot11BssType.net_work_type == 0) { + PRINT_INFO("operation band is not set, use G+B as default!\n"); + priv->pmib->dot11BssType.net_work_type = WIRELESS_11B | WIRELESS_11G; + } + if ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11B | WIRELESS_11G))) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { + priv->pmib->dot11BssType.net_work_type &= (WIRELESS_11B | WIRELESS_11G); + PRINT_INFO("operation band not appropriate, use G/B as default!\n"); + } + } + + if (should_forbid_Nmode(priv)) { +#ifdef SUPPORT_MULTI_PROFILE + if (!((OPMODE & WIFI_STATION_STATE) && + priv->pmib->ap_profile.enable_profile && priv->pmib->ap_profile.profile_num > 0)) +#endif + priv->pmib->dot11BssType.net_work_type &= ~(WIRELESS_11N|WIRELESS_11AC); + + // validate band + // for the N mode only + Security = WEP combination, the work_type will become 0 + if (priv->pmib->dot11BssType.net_work_type == 0) { + PRINT_INFO("operation band is not set, use G+B as default!\n"); + priv->pmib->dot11BssType.net_work_type = WIRELESS_11B | WIRELESS_11G; + } + } + + // validate channel number + if (get_available_channel(priv) == FAIL) { + PRINT_INFO("can't get operation channels, abort!\n"); + return 1; + } + +#if defined(RTK_NL80211) && !defined(NON_NL80211_AP) //brian, do not propietary ACS while open with dot11channel=0 + if(!priv->pmib->dot11RFEntry.dot11channel) + priv->pmib->dot11RFEntry.dot11channel = priv->available_chnl[0]; +#endif + + if (priv->pmib->dot11RFEntry.dot11channel != 0) { +#ifdef DFS + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80 && + (priv->pmib->dot11RFEntry.band5GSelected == PHY_BAND_5G_3 || + priv->pmib->dot11RFEntry.band5GSelected == 7)) + { + if(!is80MChannel(priv->available_chnl,priv->available_chnl_num,priv->pmib->dot11RFEntry.dot11channel)) + //priv->pmib->dot11RFEntry.dot11channel = priv->available_chnl[0]; + priv->pmib->dot11RFEntry.dot11channel = DFS_SelectChannel(priv); + if(!is80MChannel(priv->available_chnl,priv->available_chnl_num,priv->pmib->dot11RFEntry.dot11channel)) { + if(is40MChannel(priv->available_chnl,priv->available_chnl_num,priv->pmib->dot11RFEntry.dot11channel)) + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20_40; + else + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20; + } + } + else +#endif + { + for (i=0; iavailable_chnl_num; i++) + if (priv->pmib->dot11RFEntry.dot11channel == priv->available_chnl[i]) + break; + if (i == priv->available_chnl_num) { + priv->pmib->dot11RFEntry.dot11channel = priv->available_chnl[0]; + + PRINT_INFO("invalid channel number, use default value [%d]!\n", + priv->pmib->dot11RFEntry.dot11channel); + } + + // Check whether dot11channel is legal when dot11Use40M = 1 or 2 is set. + if(priv->pmib->dot11RFEntry.dot11channel > 14) { + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80) { + if(!is80MChannel(priv->available_chnl,priv->available_chnl_num,priv->pmib->dot11RFEntry.dot11channel)) { + if(is40MChannel(priv->available_chnl,priv->available_chnl_num,priv->pmib->dot11RFEntry.dot11channel)) + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20_40; + else + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20; + } + } + else if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20_40) { + if(!is40MChannel(priv->available_chnl,priv->available_chnl_num,priv->pmib->dot11RFEntry.dot11channel)) + priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20; + } + } + priv->auto_channel = 0; + priv->auto_channel_backup = priv->auto_channel; + } + +#ifdef SIMPLE_CH_UNI_PROTOCOL + SET_PSEUDO_RANDOM_NUMBER(priv->mesh_ChannelPrecedence); +#endif + } + else { +#ifdef SIMPLE_CH_UNI_PROTOCOL + if(GET_MIB(priv)->dot1180211sInfo.mesh_enable) { + priv->auto_channel = 16; + priv->auto_channel_backup = priv->auto_channel; + priv->pmib->dot11RFEntry.dot11channel = priv->available_chnl[0]; + priv->mesh_ChannelPrecedence = 0; + } + else +#endif + { +#ifdef DFS + if ((OPMODE & WIFI_AP_STATE) && !priv->pmib->dot11DFSEntry.disable_DFS && (priv->pshare->dfsSwitchChannel != 0)) { + priv->pmib->dot11RFEntry.dot11channel = priv->pshare->dfsSwitchChannel; + priv->pshare->dfsSwitchChannel = 0; + priv->auto_channel = 0; + priv->auto_channel_backup = 1; + } + else +#endif + { + if (OPMODE & WIFI_AP_STATE) + priv->auto_channel = 1; + else + priv->auto_channel = 2; + priv->pmib->dot11RFEntry.dot11channel = priv->available_chnl[0]; + priv->auto_channel_backup = priv->auto_channel; + } + } + } + //priv->auto_channel_backup = priv->auto_channel; + + if (priv->pmib->dot11RFEntry.dot11channel <= 14) + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; + else + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; + + // validate hi and low channel + if (priv->pmib->dot11RFEntry.dot11ch_low != 0) { + for (i=0; iavailable_chnl_num; i++) + if (priv->pmib->dot11RFEntry.dot11ch_low == priv->available_chnl[i]) + break; + if (i == priv->available_chnl_num) { + priv->pmib->dot11RFEntry.dot11ch_low = priv->available_chnl[0]; + + PRINT_INFO("invalid low channel number, use default value [%d]!\n", + priv->pmib->dot11RFEntry.dot11ch_low); + } + } + if (priv->pmib->dot11RFEntry.dot11ch_hi != 0) { + for (i=0; iavailable_chnl_num; i++) + if (priv->pmib->dot11RFEntry.dot11ch_hi == priv->available_chnl[i]) + break; + if (i == priv->available_chnl_num) { + priv->pmib->dot11RFEntry.dot11ch_hi = priv->available_chnl[priv->available_chnl_num-1]; + + PRINT_INFO("invalid hi channel number, use default value [%d]!\n", + priv->pmib->dot11RFEntry.dot11ch_hi); + } + } + +// Mark the code to auto disable N mode in WEP encrypt +#if 0 + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_)) + priv->pmib->dot11BssType.net_work_type &= ~WIRELESS_11N; +#endif +//------------------------------ david+2008-01-11 + + // support cck only in channel 14 + if ((priv->pmib->dot11RFEntry.disable_ch14_ofdm) && + (priv->pmib->dot11RFEntry.dot11channel == 14)) { + priv->pmib->dot11BssType.net_work_type = WIRELESS_11B; + PRINT_INFO("support cck only in channel 14!\n"); + } + + // validate and get support and basic rates + validate_oper_rate(priv); + get_oper_rate(priv); + + if ((priv->pmib->dot11nConfigEntry.dot11nUse40M == 2) && + (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC))) { + PRINT_INFO("enable 80M but not in AC mode! back to 40M\n"); + priv->pmib->dot11nConfigEntry.dot11nUse40M = 1; + } + + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == 1 && + (!(priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N | WIRELESS_11AC)))) { + PRINT_INFO("enable 40M but not in N | AC mode! back to 20M\n"); + priv->pmib->dot11nConfigEntry.dot11nUse40M = 0; + } + + // check deny band + if ((priv->pmib->dot11BssType.net_work_type & (~priv->pmib->dot11StationConfigEntry.legacySTADeny)) == 0) { + PRINT_INFO("legacySTADeny %d not suitable! set to 0\n", priv->pmib->dot11StationConfigEntry.legacySTADeny); + priv->pmib->dot11StationConfigEntry.legacySTADeny = 0; + } + } + + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11N)) { + if (AMSDU_ENABLE) + AMSDU_ENABLE = 0; + if (AMPDU_ENABLE) + AMPDU_ENABLE = 0; +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == 4) + priv->pshare->is_40m_bw = 4; + else if(priv->pmib->dot11nConfigEntry.dot11nUse40M == 5) + priv->pshare->is_40m_bw = 5; + else + priv->pshare->is_40m_bw = 0; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_DONTCARE; + } + } + else { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + priv->pshare->is_40m_bw = priv->pmib->dot11nConfigEntry.dot11nUse40M; + if (priv->pshare->is_40m_bw == 0|| priv->pshare->is_40m_bw == 4 || priv->pshare->is_40m_bw ==5) + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_DONTCARE; + else { +#if defined(RTK_5G_SUPPORT) + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + if((priv->pmib->dot11RFEntry.dot11channel>144) ? ((priv->pmib->dot11RFEntry.dot11channel-1)%8) : (priv->pmib->dot11RFEntry.dot11channel%8)) { + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + } else { + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + } + } + else +#endif + { + if ((priv->pmib->dot11RFEntry.dot11channel < 5) && + (priv->pmib->dot11nConfigEntry.dot11n2ndChOffset == HT_2NDCH_OFFSET_BELOW)) + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + else if ((priv->pmib->dot11RFEntry.dot11channel > 9) && + (priv->pmib->dot11nConfigEntry.dot11n2ndChOffset == HT_2NDCH_OFFSET_ABOVE)) + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + else + priv->pshare->offset_2nd_chan = priv->pmib->dot11nConfigEntry.dot11n2ndChOffset; + } + } + } + + // force wmm enabled if n mode + // so hostapd should always set wmm_enabled=1 if n mode. +#ifndef RTK_NL80211 + QOS_ENABLE = 1; +#endif + } + + // set wep key length + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen = 8; + else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen = 16; + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + init_crc32_table(); // for sw encryption + } + +#ifdef WIFI_WMM + if (QOS_ENABLE) { + if ((OPMODE & WIFI_AP_STATE) +#ifdef CLIENT_MODE + || (OPMODE & WIFI_ADHOC_STATE) +#endif + ) { + GET_EDCA_PARA_UPDATE = 0; +/* + //BK + GET_STA_AC_BK_PARA.AIFSN = 7; + GET_STA_AC_BK_PARA.TXOPlimit = 0; + GET_STA_AC_BK_PARA.ACM = 0; + GET_STA_AC_BK_PARA.ECWmin = 4; + GET_STA_AC_BK_PARA.ECWmax = 10; + //BE + GET_STA_AC_BE_PARA.AIFSN = 3; + GET_STA_AC_BE_PARA.TXOPlimit = 0; + GET_STA_AC_BE_PARA.ACM = 0; + GET_STA_AC_BE_PARA.ECWmin = 4; + GET_STA_AC_BE_PARA.ECWmax = 10; + //VI + GET_STA_AC_VI_PARA.AIFSN = 2; + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) || + (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A)) + GET_STA_AC_VI_PARA.TXOPlimit = 94; // 3.008ms + else + GET_STA_AC_VI_PARA.TXOPlimit = 188; // 6.016ms + GET_STA_AC_VI_PARA.ACM = 0; + GET_STA_AC_VI_PARA.ECWmin = 3; + GET_STA_AC_VI_PARA.ECWmax = 4; + //VO + GET_STA_AC_VO_PARA.AIFSN = 2; + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) || + (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A)) + GET_STA_AC_VO_PARA.TXOPlimit = 47; // 1.504ms + else + GET_STA_AC_VO_PARA.TXOPlimit = 102; // 3.264ms + GET_STA_AC_VO_PARA.ACM = 0; + GET_STA_AC_VO_PARA.ECWmin = 2; + GET_STA_AC_VO_PARA.ECWmax = 3; +*/ + default_WMM_para(priv); + + //init WMM Para ie in beacon + init_WMM_Para_Element(priv, priv->pmib->dot11QosEntry.WMM_PARA_IE); + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) { + init_WMM_Para_Element(priv, priv->pmib->dot11QosEntry.WMM_IE); // WMM STA + } +#endif + + if (AMSDU_ENABLE || AMPDU_ENABLE) { + if (priv->pmib->dot11nConfigEntry.dot11nTxNoAck) { + priv->pmib->dot11nConfigEntry.dot11nTxNoAck = 0; + PRINT_INFO("Tx No Ack is off because aggregation is enabled.\n"); + } + } + } +#endif + + i = priv->pmib->dot11ErpInfo.ctsToSelf; + memset(&priv->pmib->dot11ErpInfo, '\0', sizeof(struct erp_mib)); // reset ERP mib + priv->pmib->dot11ErpInfo.ctsToSelf = i; + + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G|WIRELESS_11A)) + priv->pmib->dot11ErpInfo.shortSlot = 1; + else + priv->pmib->dot11ErpInfo.shortSlot = 0; + + if (OPMODE & WIFI_AP_STATE) { + memcpy(priv->pmib->dot11StationConfigEntry.dot11Bssid, + priv->pmib->dot11OperationEntry.hwaddr, 6); + //priv->oper_band = priv->pmib->dot11BssType.net_work_type; +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + if (!priv->pshare->ra40MLowerMinus && (priv->pshare->rf_ft_var.raGoUp40MLower > 5) && + (priv->pshare->rf_ft_var.raGoDown40MLower > 5)) { + priv->pshare->rf_ft_var.raGoUp40MLower-=5; + priv->pshare->rf_ft_var.raGoDown40MLower-=5; + priv->pshare->ra40MLowerMinus++; + } +#if 0//def HIGH_POWER_EXT_PA + if (!priv->pshare->raThdHP_Minus) { + + if( priv->pshare->rf_ft_var.use_ext_pa ) { + if(priv->pshare->rf_ft_var.raGoDownUpper > RSSI_DIFF_PA) { + priv->pshare->rf_ft_var.raGoDownUpper -= RSSI_DIFF_PA; + priv->pshare->rf_ft_var.raGoUpUpper -= RSSI_DIFF_PA; + } + if(priv->pshare->rf_ft_var.raGoDown20MLower > RSSI_DIFF_PA) { + priv->pshare->rf_ft_var.raGoDown20MLower -= RSSI_DIFF_PA; + priv->pshare->rf_ft_var.raGoUp20MLower -= RSSI_DIFF_PA; + } + if(priv->pshare->rf_ft_var.raGoDown40MLower > RSSI_DIFF_PA) { + priv->pshare->rf_ft_var.raGoDown40MLower -= RSSI_DIFF_PA; + priv->pshare->rf_ft_var.raGoUp40MLower -= RSSI_DIFF_PA; + } + if( priv->pshare->rf_ft_var.txop_enlarge_lower > RSSI_DIFF_PA) { + priv->pshare->rf_ft_var.txop_enlarge_upper -= RSSI_DIFF_PA; + priv->pshare->rf_ft_var.txop_enlarge_lower -= RSSI_DIFF_PA; + } + } + ++priv->pshare->raThdHP_Minus; + } +#endif + } + } +#ifdef CLIENT_MODE + else { + if (priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen == 0) { + priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen = 11; + memcpy(priv->pmib->dot11StationConfigEntry.dot11DefaultSSID, "defaultSSID", 11); + } + memset(priv->pmib->dot11StationConfigEntry.dot11Bssid, 0, 6); + JOIN_RES_VAL(STATE_Sta_No_Bss); + +// Add mac clone address manually ---------- +#ifdef RTK_BR_EXT + if (priv->pmib->ethBrExtInfo.macclone_enable == 2) { + extern void mac_clone(struct rtl8192cd_priv *priv, unsigned char *addr); + mac_clone(priv, priv->pmib->ethBrExtInfo.nat25_dmzMac); + priv->macclone_completed = 1; + } +#endif +//------------------------- david+2007-5-31 + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + if (priv->pshare->ra40MLowerMinus) { + priv->pshare->rf_ft_var.raGoUp40MLower+=5; + priv->pshare->rf_ft_var.raGoDown40MLower+=5; + priv->pshare->ra40MLowerMinus = 0; + } + } +#ifdef MULTI_MAC_CLONE + if ((priv->pshare->mclone_ok == 0) && (OPMODE & WIFI_STATION_STATE)) + { + init_Multi_Mac_Clone(priv); + priv->pshare->mclone_ok = 1; + } + //priv->pshare->root_repeater = NULL; +#endif + } +#endif + + // initialize event queue + DOT11_InitQueue(priv->pevent_queue); +#ifdef CONFIG_RTL_WAPI_SUPPORT + DOT11_InitQueue(priv->wapiEvent_queue); +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)&&priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]->wapiEvent_queue); + } +#endif + +#endif + +#ifdef CONFIG_RTK_MESH + if(GET_MIB(priv)->dot1180211sInfo.mesh_enable == 1) // plus add 0217, not mesh mode should not do below function + { + DOT11_InitQueue2(priv->pathsel_queue, MAXQUEUESIZE2, MAXDATALEN2); +#ifdef _11s_TEST_MODE_ + DOT11_InitQueue2(priv->receiver_queue, MAXQUEUESIZE2, MAXDATALEN2); +#endif + priv->pmib->dot11sKeysTable.keyid = 0; + priv->pmib->dot11sKeysTable.keyInCam = TRUE; + memset(&priv->pmib->dot11sKeysTable.dot11EncryptKey, 0, sizeof(struct Dot11EncryptKey)); + } +#endif + +#ifdef __DRAYTEK_OS__ + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _TKIP_PRIVACY_ && + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _CCMP_PRIVACY_ && + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_WPA_MIXED_PRIVACY_) { +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv)) +#endif + { + priv->pmib->dot11RsnIE.rsnielen = 0; // reset RSN IE length + memset(&priv->pmib->dot11GroupKeysTable, '\0', sizeof(struct Dot11KeyMappingsEntry)); // reset group key +#ifdef UNIVERSAL_REPEATER + if (GET_VXD_PRIV(priv)) + GET_VXD_PRIV(priv)->pmib->dot11RsnIE.rsnielen = 0; +#endif + } + } +#endif + + i = RC_ENTRY_NUM; + for (;;) { + if (priv->pmib->reorderCtrlEntry.ReorderCtrlWinSz >= i) { + priv->pmib->reorderCtrlEntry.ReorderCtrlWinSz = i; + break; + } + else if (i > 8) + i = i / 2; + else { + priv->pmib->reorderCtrlEntry.ReorderCtrlWinSz = 8; + break; + } + } + + // Realtek proprietary IE + memcpy(&(priv->pshare->rtk_ie_buf[0]), Realtek_OUI, 3); + priv->pshare->rtk_ie_buf[3] = 2; +#ifdef CONFIG_WLAN_HAL_8814AE + if (GET_CHIP_VER(priv) == VERSION_8814A) { + priv->pshare->rtk_ie_buf[4] = 2; + priv->pshare->rtk_ie_buf[5] = 0; +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) + priv->pshare->rtk_ie_buf[5] |= RTK_CAP_IE_AP_CLIENT; +#endif + priv->pshare->rtk_ie_buf[6] = 0; + priv->pshare->rtk_ie_len = 7; + } + else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + priv->pshare->rtk_ie_buf[4] = 2; + priv->pshare->rtk_ie_buf[5] = 0; + priv->pshare->rtk_ie_buf[5] |= RTK_CAP_IE_WLAN_88C92C | RTK_CAP_IE_WLAN_8192SE; +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) + priv->pshare->rtk_ie_buf[5] |= RTK_CAP_IE_AP_CLIENT; +#endif + priv->pshare->rtk_ie_buf[6] = 0; + if (IS_B_CUT_8812(priv)) + priv->pshare->rtk_ie_buf[6] |= RTK_CAP_IE_8812_BCUT; + else + priv->pshare->rtk_ie_buf[6] |= RTK_CAP_IE_8812_CCUT; + priv->pshare->rtk_ie_len = 7; + } + else +#endif + { + priv->pshare->rtk_ie_buf[4] = 1; + priv->pshare->rtk_ie_buf[5] = 0; + priv->pshare->rtk_ie_buf[5] |= RTK_CAP_IE_WLAN_88C92C | RTK_CAP_IE_WLAN_8192SE; +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) + priv->pshare->rtk_ie_buf[5] |= RTK_CAP_IE_AP_CLIENT; +#endif + priv->pshare->rtk_ie_len = 6; + } + +#if defined(WIFI_HAPD) || defined (RTK_NL80211)//OPENWRT_RADIUS + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK == 0) + && (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm) + && (priv->pmib->dot1180211AuthEntry.dot11WPACipher || priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher)) + rsn_init(priv); +#endif + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) { +#if defined(INCLUDE_WPA_PSK) + psk_init(priv); +#elif defined(WIFI_HAPD) || defined(RTK_NL80211) + nl80211_psk_init(priv); +#endif + } else { +#if !defined(RTK_NL80211) || defined(NON_NL80211_AP) //make OpenWrt support VAP+RADIUS +#ifdef MBSSID + if(IS_VAP_INTERFACE(priv) && (!priv->pmib->dot11OperationEntry.keep_rsnie)) + priv->pmib->dot11RsnIE.rsnielen = 0; // reset RSN IE length +#endif +#endif + } + +#ifdef WDS +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef LAZY_WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE) { + priv->pmib->dot11WdsInfo.wdsNum = 0; + memset(priv->pmib->dot11WdsInfo.entry, '\0', sizeof(struct wdsEntry)*NUM_WDS); + } +#endif + if ((priv->pmib->dot11WdsInfo.wdsEnabled) && (priv->pmib->dot11WdsInfo.wdsNum > 0) && + ((priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_) || + (priv->pmib->dot11WdsInfo.wdsPrivacy == _CCMP_PRIVACY_))) + wds_psk_init(priv); + } +#endif +#endif + +#if 0//def WIFI_WPAS + { + WPAS_ASSOCIATION_INFO Assoc_Info; + memset((void *)&Assoc_Info, 0, sizeof(struct _WPAS_ASSOCIATION_INFO)); + Assoc_Info.ReqIELen = priv->pmib->dot11RsnIE.rsnie[1]+ 2; + memcpy(Assoc_Info.ReqIE, priv->pmib->dot11RsnIE.rsnie, Assoc_Info.ReqIELen); + + //event_indicate_wpas(priv, NULL, WPAS_ASSOC_INFO, (UINT8 *)&Assoc_Info); + } +#endif + + +#ifdef GBWC + priv->GBWC_tx_queue.head = 0; + priv->GBWC_tx_queue.tail = 0; + priv->GBWC_rx_queue.head = 0; + priv->GBWC_rx_queue.tail = 0; + priv->GBWC_tx_count = 0; + priv->GBWC_rx_count = 0; + priv->GBWC_consuming_Q = 0; +#endif + + priv->release_mcast = 0; + +#ifdef USB_PKT_RATE_CTRL_SUPPORT //mark_test + priv->change_toggle = 0; + priv->pre_pkt_cnt = 0; + priv->pkt_nsec_diff = 0; + priv->poll_usb_cnt = 0; + priv->auto_rate_mask = 0; +#endif + + +#ifdef CONFIG_RTK_VLAN_SUPPORT + if (priv->pmib->vlan.global_vlan) + priv->pmib->dot11OperationEntry.disable_brsc = 1; +#endif + +#if defined(CONFIG_RTL_819X_ECOS)&&defined(CONFIG_RTL_VLAN_SUPPORT)&&defined(CONFIG_RTL_819X_SWCORE) + if (rtl_vlan_support_enable) + priv->pmib->dot11OperationEntry.disable_brsc = 1; +#endif + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType!=wapiDisable) + { + /* set NMK */ + GenerateRandomData(priv->wapiNMK, WAPI_KEY_LEN); + priv->wapiMCastKeyId = 0; + priv->wapiMCastKeyUpdate = 0; + priv->wapiWaiTxSeq = 0; + wapiInit(priv); + } + +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)&&priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]->pmib->wapiInfo.wapiType!=wapiDisable) { + /* set NMK */ + GenerateRandomData(priv->pvap_priv[i]->wapiNMK, WAPI_KEY_LEN); + priv->pvap_priv[i]->wapiMCastKeyId = 0; + priv->pvap_priv[i]->wapiMCastKeyUpdate = 0; + priv->wapiWaiTxSeq = 0; + wapiInit(priv->pvap_priv[i]); + } + } +#endif +#endif + +#ifdef MBSSID + // if vap enabled, set beacon int to 100 at minimun when guest ssid num <= 4 + // if vap enabled, set beacon int to 200 at minimun when guest ssid num > 4 + { + int ssid_num = 1, minbcn_period; + priv->bcn_period_bak = priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod; + + if ((OPMODE & WIFI_AP_STATE) && GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + for (i=0; ipvap_priv[i] && IS_DRV_OPEN(GET_ROOT(priv)->pvap_priv[i])) + { + ssid_num++; + } + } + +#if defined(CONFIG_PCI_HCI) + if (ssid_num >= 5) +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (ssid_num >= 4) +#endif + minbcn_period = 200; + else + minbcn_period = 100; + + // if vap enabled, set beacon int to 100 at minimun + if (priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod < minbcn_period) + priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod = minbcn_period; + + for (i=0; ipvap_priv[i]) + { + GET_ROOT(priv)->pvap_priv[i]->pmib->dot11StationConfigEntry.dot11BeaconPeriod = priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod; + GET_ROOT(priv)->pvap_priv[i]->update_bcn_period = 1; + } + } + + GET_ROOT(priv)->pmib->dot11StationConfigEntry.dot11BeaconPeriod = priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod; + GET_ROOT(priv)->update_bcn_period = 1; + } + } +#endif + +#ifdef DOT11H + if ( priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) { + priv->pmib->dot11hTPCEntry.tpc_enable = 0; /*2G do not have tpc, disable it*/ + } +#endif + +#ifdef DOT11D + if ( priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) { + COUNTRY_CODE_ENABLED = 0; /*disable 11d in 2G*/ + } +#endif + +#if defined(DOT11D) || defined(DOT11H) + check_country_channel_table(priv); +#endif + +#ifdef RTL_MANUAL_EDCA + for (i=0; i<8; i++) { + if ((priv->pmib->dot11QosEntry.TID_mapping[i] < 1) || (priv->pmib->dot11QosEntry.TID_mapping[i] > 4)) + priv->pmib->dot11QosEntry.TID_mapping[i] = 2; + } +#endif + +#if defined(TXREPORT) + priv->pshare->sta_query_idx=-1; + // Init StaDetectInfo to detect disappearing STA. Added by Annie, 2010-08-10. + priv->pmib->staDetectInfo.txRprDetectPeriod = 1; +#endif + +#ifdef INCLUDE_WPS +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + wps_init(priv); +#endif + +#ifdef CONFIG_USB_HCI +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { // The QUEUE-to-OUT Endpoint mapping must match _InitQueuePriority() settings + _MappingOutEP(priv, priv->pshare->RtNumOutPipes, IS_TEST_CHIP(priv)); + } +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI +#ifdef CONFIG_RTL_88E_SUPPORT +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + rtl8188es_interface_configure(priv); + } +#endif +#endif // CONFIG_SDIO_HCI + +#ifdef P2P_SUPPORT + if(OPMODE & WIFI_P2P_SUPPORT ){ + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G){ + panic_printk("no Support P2P under 5G mode\n"); + }else{ + p2p_init(priv); + P2P_DEBUG("%s under P2P mode now\n",priv->dev->name); + } + } +#endif + +#ifdef CONFIG_POWER_SAVE + if (IS_ROOT_INTERFACE(priv)) { + rtw_ap_ps_init(priv); + } +#endif + +#ifdef CONFIG_RTK_MESH + if (IS_ROOT_INTERFACE(priv)) { + init_mesh(priv); + } +#endif + +#ifdef TLN_STATS + if (priv->pshare->rf_ft_var.stats_time_interval) + priv->stats_time_countdown = priv->pshare->rf_ft_var.stats_time_interval; +#endif + +#if defined (SUPPORT_TX_MCAST2UNI) + /*ipv4 mdns*/ + priv->pshare->rf_ft_var.mc2u_flood_mac[0].macAddr[0]=0x01; + priv->pshare->rf_ft_var.mc2u_flood_mac[0].macAddr[1]=0x00; + priv->pshare->rf_ft_var.mc2u_flood_mac[0].macAddr[2]=0x5e; + priv->pshare->rf_ft_var.mc2u_flood_mac[0].macAddr[3]=0x00; + priv->pshare->rf_ft_var.mc2u_flood_mac[0].macAddr[4]=0x00; + priv->pshare->rf_ft_var.mc2u_flood_mac[0].macAddr[5]=0xfb; + + /*ipv4 upnp&m-search*/ + priv->pshare->rf_ft_var.mc2u_flood_mac[1].macAddr[0]=0x01; + priv->pshare->rf_ft_var.mc2u_flood_mac[1].macAddr[1]=0x00; + priv->pshare->rf_ft_var.mc2u_flood_mac[1].macAddr[2]=0x5e; + priv->pshare->rf_ft_var.mc2u_flood_mac[1].macAddr[3]=0x7f; + priv->pshare->rf_ft_var.mc2u_flood_mac[1].macAddr[4]=0xff; + priv->pshare->rf_ft_var.mc2u_flood_mac[1].macAddr[5]=0xfa; + + /*ipv6 mdns*/ + priv->pshare->rf_ft_var.mc2u_flood_mac[2].macAddr[0]=0x33; + priv->pshare->rf_ft_var.mc2u_flood_mac[2].macAddr[1]=0x33; + priv->pshare->rf_ft_var.mc2u_flood_mac[2].macAddr[2]=0x00; + priv->pshare->rf_ft_var.mc2u_flood_mac[2].macAddr[3]=0x00; + priv->pshare->rf_ft_var.mc2u_flood_mac[2].macAddr[4]=0x00; + priv->pshare->rf_ft_var.mc2u_flood_mac[2].macAddr[5]=0xfb; + + /*ipv6 upnp&m-search*/ + priv->pshare->rf_ft_var.mc2u_flood_mac[3].macAddr[0]=0x33; + priv->pshare->rf_ft_var.mc2u_flood_mac[3].macAddr[1]=0x33; + priv->pshare->rf_ft_var.mc2u_flood_mac[3].macAddr[2]=0x7f; + priv->pshare->rf_ft_var.mc2u_flood_mac[3].macAddr[3]=0xff; + priv->pshare->rf_ft_var.mc2u_flood_mac[3].macAddr[4]=0xff; + priv->pshare->rf_ft_var.mc2u_flood_mac[3].macAddr[5]=0xfa; + + priv->pshare->rf_ft_var.mc2u_flood_mac_num=4; +#endif + +#ifdef _TRACKING_TABLE_FILE + if (GET_CHIP_VER(priv) == VERSION_8812E) + priv->pshare->rf_ft_var.pwr_track_file = 1; +#endif +#ifdef CONFIG_IEEE80211W + if(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _NO_PRIVACY_ + || priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) { + priv->pmib->dot1180211AuthEntry.dot11IEEE80211W = 0; + priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = 0; + } +#endif + + return 0; +} + + +static int rtl8192cd_stop_sw(struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_hw *phw; + unsigned long flags; + int i; + struct list_head *phead, *plist; + struct wlan_acl_node *paclnode; +#ifdef CONFIG_WLAN_HAL + int halQnum; + PHCI_TX_DMA_MANAGER_88XX ptx_dma; +#endif // CONFIG_WLAN_HAL + + // we hope all this can be done in critical section + SMP_LOCK(flags); + SAVE_INT_AND_CLI(flags); + + if(OPMODE&WIFI_STATION_STATE){ + priv->site_survey->count = 0; + priv->site_survey->count_target=0; + } + +#ifdef INCLUDE_WPS + priv->pshare->WSC_CONT_S.wait_reinit = 1 ; +#endif + + SMP_UNLOCK(flags); + if (timer_pending(&priv->frag_to_filter)) + { + del_timer_sync(&priv->frag_to_filter); + } + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (timer_pending(&priv->pshare->xmit_check_timer)) + del_timer_sync(&priv->pshare->xmit_check_timer); +#endif +#ifdef CONFIG_USB_HCI +#if defined(CONFIG_RTL_92C_SUPPORT) || (!defined(CONFIG_SUPPORT_USB_INT) || !defined(CONFIG_INTERRUPT_BASED_TXBCN)) + if (timer_pending(&priv->pshare->beacon_timer)) + del_timer_sync(&priv->pshare->beacon_timer); +#endif +#endif // CONFIG_USB_HCI +#ifdef CONFIG_SDIO_HCI + if (timer_pending(&priv->pshare->beacon_timer)) + del_timer_sync(&priv->pshare->beacon_timer); +#endif + if (timer_pending(&priv->expire_timer)) + del_timer_sync(&priv->expire_timer); +#ifdef SW_ANT_SWITCH + if (timer_pending(&priv->pshare->swAntennaSwitchTimer)) + del_timer_sync(&priv->pshare->swAntennaSwitchTimer); +#endif + if (timer_pending(&priv->pshare->rc_sys_timer)) + del_timer_sync(&priv->pshare->rc_sys_timer); +#if 0 + if (timer_pending(&priv->pshare->phw->tpt_timer)) + del_timer_sync(&priv->pshare->phw->tpt_timer); +#endif + +#ifdef USE_OUT_SRC +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif +#ifdef SMART_REPEATER_MODE + if (!priv->pshare->switch_chan_rp) +#endif + ODM_StopAllThreads(ODMPTR); + #ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) + #endif + ODM_CancelAllTimers(ODMPTR); +#else + #ifdef TPT_THREAD + kTPT_task_stop(priv); + #endif +#endif // USE_OUT_SRC + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType!=wapiDisable +#ifdef CHECK_HANGUP + &&(!priv->reset_hangup) +#endif +#ifdef SMART_REPEATER_MODE + &&(!priv->pshare->switch_chan_rp) +#endif + ) + { + wapiExit(priv); + } + + +#ifdef MBSSID + if( priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]; + if (vap_priv && vap_priv->pmib->wapiInfo.wapiType!=wapiDisable +#ifdef CHECK_HANGUP + &&(!vap_priv->reset_hangup) +#endif + ) { + wapiExit(vap_priv); + } + } + } +#endif +#endif // CONFIG_RTL_WAPI_SUPPORT + +#if defined(PCIE_POWER_SAVING) || defined(RF_MIMO_SWITCH) + if (timer_pending(&priv->ps_timer)) + del_timer_sync(&priv->ps_timer); +#endif + +#ifdef SDIO_AP_OFFLOAD + if (timer_pending(&priv->pshare->ps_timer)) + del_timer_sync(&priv->pshare->ps_timer); +#endif + +#ifdef BEAMFORMING_SUPPORT + if (timer_pending(&priv->txbf_timer)) + del_timer_sync(&priv->txbf_timer); + if (timer_pending(&priv->txbf_swtimer)) + del_timer_sync(&priv->txbf_swtimer); +#endif + +#ifdef CONFIG_RTK_MESH + /* + * CAUTION !! These statement meshX(virtual interface) ONLY, Maybe modify.... + */ + if (timer_pending(&priv->mesh_peer_link_timer)) + del_timer_sync(&priv->mesh_peer_link_timer); + +#ifdef MESH_BOOTSEQ_AUTH + if (timer_pending(&priv->mesh_auth_timer)) + del_timer_sync(&priv->mesh_auth_timer); +#endif +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(DPK_92D) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + if (timer_pending(&priv->pshare->DPKTimer)) + del_timer_sync(&priv->pshare->DPKTimer); + } +#endif + + } + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) // wrt-adhoc +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)){ + //printk("Try delete ibss beacon timer!! \n"); + if (timer_pending(&priv->pshare->vxd_ibss_beacon)) + del_timer_sync(&priv->pshare->vxd_ibss_beacon); + } +#endif +#endif + + if (timer_pending(&priv->ss_timer)) + del_timer_sync(&priv->ss_timer); + if (timer_pending(&priv->MIC_check_timer)) + del_timer_sync(&priv->MIC_check_timer); + if (timer_pending(&priv->assoc_reject_timer)) + del_timer_sync(&priv->assoc_reject_timer); +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + #ifdef CONFIG_PCI_HCI + // to avoid add RAtid fail + if (timer_pending(&priv->add_RATid_timer)) + del_timer_sync(&priv->add_RATid_timer); + if (timer_pending(&priv->add_rssi_timer)) + del_timer_sync(&priv->add_rssi_timer); + #endif +#endif +#ifdef CONFIG_PCI_HCI + if (timer_pending(&priv->add_ps_timer)) + del_timer_sync(&priv->add_ps_timer); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + if (timer_pending(&priv->dnc_timer)) + del_timer_sync(&priv->dnc_timer); + } +#endif + +#ifdef CLIENT_MODE + if (timer_pending(&priv->reauth_timer)) + del_timer_sync(&priv->reauth_timer); + if (timer_pending(&priv->reassoc_timer)) + del_timer_sync(&priv->reassoc_timer); + if (timer_pending(&priv->idle_timer)) + del_timer_sync(&priv->idle_timer); +#endif + +SMP_LOCK(flags); + +#ifdef GBWC + if (timer_pending(&priv->GBWC_timer)) + del_timer_sync(&priv->GBWC_timer); + while (CIRC_CNT(priv->GBWC_tx_queue.head, priv->GBWC_tx_queue.tail, NUM_TXPKT_QUEUE)) + { + struct sk_buff *pskb = priv->GBWC_tx_queue.pSkb[priv->GBWC_tx_queue.tail]; + rtl_kfree_skb(priv, pskb, _SKB_TX_); + priv->GBWC_tx_queue.tail++; + priv->GBWC_tx_queue.tail = priv->GBWC_tx_queue.tail & (NUM_TXPKT_QUEUE - 1); + } + while (CIRC_CNT(priv->GBWC_rx_queue.head, priv->GBWC_rx_queue.tail, NUM_TXPKT_QUEUE)) + { + struct sk_buff *pskb = priv->GBWC_rx_queue.pSkb[priv->GBWC_rx_queue.tail]; + rtl_kfree_skb(priv, pskb, _SKB_RX_); + priv->GBWC_rx_queue.tail++; + priv->GBWC_rx_queue.tail = priv->GBWC_rx_queue.tail & (NUM_TXPKT_QUEUE - 1); + } +#endif + +#ifdef INCLUDE_WPA_PSK + if (timer_pending(&priv->wpa_global_info->GKRekeyTimer)) + del_timer_sync(&priv->wpa_global_info->GKRekeyTimer); +#endif + +#ifdef USE_TXQUEUE + for (i=0; i<7; i++) { + struct txq_node *pnode, *phead, *pnext; + + phead = (struct txq_node *)&(priv->pshare->txq_list[i].list); + pnode = phead->list.next; + pnext = pnode; + while (pnext != phead) + { + pnode = pnext; + pnext = pnext->list.next; + if (pnode->skb && pnode->dev && pnode->dev->priv == priv) { + unlink_txq(&(priv->pshare->txq_list[i]), pnode); + rtl_kfree_skb(priv, pnode->skb, _SKB_TX_); + pnode->skb = pnode->dev = NULL; + list_add_tail(&pnode->list, &priv->pshare->txq_pool); + } + } + } + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) +#if defined(RESERVE_TXDESC_FOR_EACH_IF) + for (i=0; i<7; i++) { + priv->use_txq_cnt[i] = 0; + } +#endif + + if (IS_ROOT_INTERFACE(priv)) +#endif + { + free_txq_pool(&priv->pshare->txq_pool,priv->pshare->txq_pool_addr); + } +#endif + +#ifdef BEAMFORMING_SUPPORT + Beamforming_Release(priv); +#endif + + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef DFS + SMP_UNLOCK(flags); + if (timer_pending(&priv->DFS_TXPAUSE_timer)) + del_timer_sync(&priv->DFS_TXPAUSE_timer); + + if (timer_pending(&priv->DFS_timer)) + del_timer_sync(&priv->DFS_timer); + + if (timer_pending(&priv->ch_avail_chk_timer)) + del_timer_sync(&priv->ch_avail_chk_timer); + + if (timer_pending(&priv->dfs_chk_timer)) + del_timer_sync(&priv->dfs_chk_timer); + + if (timer_pending(&priv->dfs_det_chk_timer)) + del_timer_sync(&priv->dfs_det_chk_timer); + + /* + * when we disable the DFS function dynamically, we also remove the channel + * from NOP_chnl while the driver is rebooting + */ + if (timer_pending(&priv->ch52_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch52_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 52); + } + + if (timer_pending(&priv->ch56_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch56_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 56); + } + + if (timer_pending(&priv->ch60_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch60_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 60); + } + + if (timer_pending(&priv->ch64_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch64_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 64); + } + + if (timer_pending(&priv->ch100_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch100_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 100); + } + + if (timer_pending(&priv->ch104_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch104_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 104); + } + + if (timer_pending(&priv->ch108_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch108_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 108); + } + + if (timer_pending(&priv->ch112_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch112_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 112); + } + + if (timer_pending(&priv->ch116_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch116_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 116); + } + + if (timer_pending(&priv->ch120_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch120_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 120); + } + + if (timer_pending(&priv->ch124_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch124_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 124); + } + + if (timer_pending(&priv->ch128_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch128_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 128); + } + + if (timer_pending(&priv->ch132_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch128_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 128); + } + + if (timer_pending(&priv->ch136_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch136_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 136); + } + + if (timer_pending(&priv->ch140_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch140_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 140); + } + + if (timer_pending(&priv->ch144_timer) && + (priv->pmib->dot11DFSEntry.disable_DFS)) { + del_timer_sync(&priv->ch144_timer); + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 144); + } + SMP_LOCK(flags); + + /* + * For JAPAN in adhoc mode + */ + if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK) || + (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_MKK3)) && + (OPMODE & WIFI_ADHOC_STATE)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { + if (!timer_pending(&priv->ch52_timer)) + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 52); + if (!timer_pending(&priv->ch56_timer)) + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 56); + if (!timer_pending(&priv->ch60_timer)) + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 60); + if (!timer_pending(&priv->ch64_timer)) + RemoveChannel(priv, priv->NOP_chnl, &priv->NOP_chnl_num, 64); + } + } +#endif // DFS + + // for SW LED + if ((LED_TYPE >= LEDTYPE_SW_LINK_TXRX) && (LED_TYPE < LEDTYPE_SW_MAX)) + disable_sw_LED(priv); + +#if 0 //kill tasklets before stop hw +#ifdef __KERNEL__ +#ifdef DFS + /* prevent killing tasklet issue in interrupt */ + if (!priv->pmib->dot11DFSEntry.DFS_detected) +#endif + { +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif + { +#ifdef P2P_SUPPORT + if((OPMODE&WIFI_P2P_SUPPORT)) + { + + }else +#endif + { +#ifdef SMART_REPEATER_MODE + if (!priv->pshare->switch_chan_rp) +#endif + { +#ifdef CONFIG_RTL_SIMPLE_CONFIG + if(!priv->pmib->dot11StationConfigEntry.sc_enabled && ((priv->simple_config_status==0) && (IS_ROOT_INTERFACE(priv) +#ifdef UNIVERSAL_REPEATER +&& (GET_VXD_PRIV(priv)->simple_config_status == 0) +#endif +))) +#endif + { +#if defined(CONFIG_PCI_HCI) + RESTORE_INT(flags); + SMP_UNLOCK(flags); + tasklet_kill(&priv->pshare->rx_tasklet); + tasklet_kill(&priv->pshare->tx_tasklet); + tasklet_kill(&priv->pshare->oneSec_tasklet); + SMP_LOCK(flags); + SAVE_INT_AND_CLI(flags); +#elif defined(__KERNEL__) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + tasklet_kill(&priv->recvpriv.recv_tasklet); + tasklet_kill(&priv->pshare->xmit_tasklet); +#endif + } + } + } + + } + } +#endif // __KERNEL__ +#endif //kill tasklets before stop hw + + phw = GET_HW(priv); + +#ifdef DELAY_REFILL_RX_BUF + priv->pshare->phw->cur_rx_refill = priv->pshare->phw->cur_rx = 0; // avoid refill to rx ring +#if defined(CONFIG_WLAN_HAL) + if (IS_HAL_CHIP(priv)) { + PHCI_RX_DMA_MANAGER_88XX prx_dma = (PHCI_RX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PRxDMA88XX); + PHCI_RX_DMA_QUEUE_STRUCT_88XX cur_q = &(prx_dma->rx_queue[0]); + cur_q->host_idx = cur_q->cur_host_idx = 0; + cur_q->rxbd_ok_cnt = 0; + } +#endif +#endif + +#ifdef CONFIG_PCI_HCI + for (i=0; irx_infoL[i].pbuf != NULL) { +#ifdef CONFIG_NET_PCI + // if pci bios, then pci_unmap_single and dev_kfree_skb + if (IS_PCIBIOS_TYPE) + pci_unmap_single(priv->pshare->pdev, phw->rx_infoL[i].paddr, (RX_BUF_LEN - sizeof(struct rx_frinfo)), PCI_DMA_FROMDEVICE); +#endif + rtl_kfree_skb(priv, (struct sk_buff*)(phw->rx_infoL[i].pbuf), _SKB_RX_); + } + } + + // free the skb buffer in Low and Hi queue + DEBUG_INFO("free tx Q0 head %d tail %d\n", phw->txhead0, phw->txtail0); + DEBUG_INFO("free tx Q1 head %d tail %d\n", phw->txhead1, phw->txtail1); + DEBUG_INFO("free tx Q2 head %d tail %d\n", phw->txhead2, phw->txtail2); + DEBUG_INFO("free tx Q3 head %d tail %d\n", phw->txhead3, phw->txtail3); + DEBUG_INFO("free tx Q4 head %d tail %d\n", phw->txhead4, phw->txtail4); + DEBUG_INFO("free tx Q5 head %d tail %d\n", phw->txhead5, phw->txtail5); + + for (i=0; ipmib->miscEntry.vap_enable) + max_qnum = HIGH_QUEUE7; +#endif + + for (j=0; j<=max_qnum; j++) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + halQnum = GET_HAL_INTERFACE(priv)->MappingTxQueueHandler(priv, j); + ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + #if 0 + head = GET_HAL_INTERFACE(priv)->GetTxQueueHWIdxHandler(priv, j); + #else + head = ptx_dma->tx_queue[halQnum].host_idx; + #endif + tail = ptx_dma->tx_queue[halQnum].hw_idx; + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + head = get_txhead(phw, j); + tail = get_txtail(phw, j); + } +// if (i = head) + if( (tail <= head) ? (i = head) :(i = head)) + continue; + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if (j >= TXDESC_HIGH_QUEUE_NUM) { + if(i>=NUM_TX_DESC_HQ) + continue; + } + } +#endif + + + tx_info = get_txdesc_info(priv->pshare->pdesc_info, j); + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (tx_info[i].priv) + tx_info[i].priv->use_txdesc_cnt[j]--; +#endif + +#if defined(CONFIG_WLAN_HAL) + if (IS_HAL_CHIP(priv)) { + if (tx_info[i].buf_pframe[0] && (tx_info[i].buf_type[0] == _SKB_FRAME_TYPE_)) { // should be buf_paddr +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if (IS_PCIBIOS_TYPE && (tx_info[i].buf_len[0]!=0 && tx_info[i].buf_paddr[0]!=0)) + pci_unmap_single(priv->pshare->pdev, tx_info[i].buf_paddr[0],(tx_info[i].buf_len[0])&0xffff, PCI_DMA_TODEVICE); +#endif +#ifdef MP_TEST + if ((OPMODE & (WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND))==(WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND)) { + priv->pshare->skb_tail = (priv->pshare->skb_tail + 1) & (NUM_MP_SKB - 1); + } + else +#endif + { + rtl_kfree_skb(priv, tx_info[i].buf_pframe[0], _SKB_TX_); + DEBUG_INFO("free skb in queue %d\n", j); + } + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif // defined(CONFIG_WLAN_HAL) + {//not HAL + if (tx_info[i].pframe && (tx_info[i].type == _SKB_FRAME_TYPE_)) { +#ifdef CONFIG_NET_PCI + if (IS_PCIBIOS_TYPE) + pci_unmap_single(priv->pshare->pdev, tx_info[i].paddr, (tx_info[i].len), PCI_DMA_TODEVICE); +#endif + +#if 1//def CONFIG_RTL8672 +#ifdef MP_TEST + if ((OPMODE & (WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND))==(WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND)) { + priv->pshare->skb_tail = (priv->pshare->skb_tail + 1) & (NUM_MP_SKB - 1); + } + else +#endif + { + rtl_kfree_skb(priv, tx_info[i].pframe, _SKB_TX_); + DEBUG_INFO("free skb in queue %d\n", j); + } +#else //CONFIG_RTL8672 + rtl_kfree_skb(priv, tx_info[i].pframe, _SKB_TX_); + DEBUG_INFO("free skb in queue %d\n", j); +#endif //CONFIG_RTL8672 + } + } + } + } // TX descriptor Free + + +#if 1//def CONFIG_RTL8672 +#ifdef MP_TEST + if ((OPMODE & (WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND))==(WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND)) { + DEBUG_INFO("[%s %d] skb_head/skb_tail=%d/%d\n", + __FUNCTION__, __LINE__, priv->pshare->skb_head, priv->pshare->skb_tail); + + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_BACKGROUND); + + for (i=0; ipshare->skb_pool[i]->head); + kfree(priv->pshare->skb_pool_ptr); + } +#endif +#endif + + // unmap beacon buffer +#if defined(CONFIG_NET_PCI) +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if (IS_PCIBIOS_TYPE) { + PHCI_TX_DMA_MANAGER_88XX ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + u32 halQNum = GET_HAL_INTERFACE(priv)->MappingTxQueueHandler(priv, BEACON_QUEUE); + PHCI_TX_DMA_QUEUE_STRUCT_88XX cur_q = &(ptx_dma->tx_queue[halQNum]); + PTX_BUFFER_DESCRIPTOR cur_txbd = cur_q->pTXBD_head; + + #ifdef NOT_RTK_BSP + if (cur_txbd->TXBD_ELE[1].Dword1 != 0) + #endif + pci_unmap_single(priv->pshare->pdev, get_desc(cur_txbd->TXBD_ELE[1].Dword1), 128*sizeof(unsigned int), PCI_DMA_TODEVICE); + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + // Not HAL + if (IS_PCIBIOS_TYPE) { +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) { + #ifdef NOT_RTK_BSP + if (phw->tx_descB->Dword10 != 0) + #endif + pci_unmap_single(priv->pshare->pdev, get_desc(phw->tx_descB->Dword10), + 128*sizeof(unsigned int), PCI_DMA_TODEVICE); + } else +#endif + { + #ifdef NOT_RTK_BSP + if (phw->tx_descB->Dword8 != 0) + #endif + pci_unmap_single(priv->pshare->pdev, get_desc(phw->tx_descB->Dword8), 128*sizeof(unsigned int), PCI_DMA_TODEVICE); + } + } + } +#endif // defined(CONFIG_NET_PCI) +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef MP_TEST + if ((OPMODE & (WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND))==(WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND)) { + DEBUG_INFO("[%s %d] skb_head/skb_tail=%d/%d\n", + __FUNCTION__, __LINE__, priv->pshare->skb_head, priv->pshare->skb_tail); + + OPMODE_VAL(OPMODE & ~WIFI_MP_CTX_BACKGROUND); + + for (i=0; ipshare->skb_pool[i]->head); + kfree(priv->pshare->skb_pool_ptr); + } +#endif + rtw_flush_recvbuf_pending_queue(priv); +#ifdef CONFIG_SDIO_HCI + rtw_flush_xmit_pending_queue(priv); +#endif +#endif + +#ifdef RX_BUFFER_GATHER + flush_rx_list(priv); +#endif + } // if (IS_ROOT_INTERFACE(priv)) + + priv->pmib->dot11StationConfigEntry.dot11AclNum=0; + phead = &priv->wlan_acl_list; + if (!list_empty(phead)) { + plist = phead->next; + while(plist != phead) { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + memcpy((void *)priv->pmib->dot11StationConfigEntry.dot11AclAddr[priv->pmib->dot11StationConfigEntry.dot11AclNum], (void *)paclnode->addr, MACADDRLEN); + priv->pmib->dot11StationConfigEntry.dot11AclNum++; + }; + } + + for (i=0; ipshare->aidarray[i]) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (priv != priv->pshare->aidarray[i]->priv) + continue; + else +#endif + { + if (priv->pshare->aidarray[i]->used == TRUE) { + if (priv->pshare->aidarray[i]->station.expire_to > 0) + { + cnt_assoc_num(priv, &(priv->pshare->aidarray[i]->station), DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, &(priv->pshare->aidarray[i]->station), DECREASE); + } + if (free_stainfo(priv, &(priv->pshare->aidarray[i]->station)) == FAIL) + DEBUG_ERR("free station %d fails\n", i); + } + + +#ifdef CONFIG_PCI_HCI +#if defined(WIFI_WMM) && defined(WMM_APSD) +#ifdef PRIV_STA_BUF + free_sta_que(priv, priv->pshare->aidarray[i]->station.VO_dz_queue); + free_sta_que(priv, priv->pshare->aidarray[i]->station.VI_dz_queue); + free_sta_que(priv, priv->pshare->aidarray[i]->station.BE_dz_queue); + free_sta_que(priv, priv->pshare->aidarray[i]->station.BK_dz_queue); + +#else + kfree(priv->pshare->aidarray[i]->station.VO_dz_queue); + kfree(priv->pshare->aidarray[i]->station.VI_dz_queue); + kfree(priv->pshare->aidarray[i]->station.BE_dz_queue); + kfree(priv->pshare->aidarray[i]->station.BK_dz_queue); +#endif +#endif + +#if defined(WIFI_WMM) +#ifdef PRIV_STA_BUF + free_sta_mgt_que(priv, priv->pshare->aidarray[i]->station.MGT_dz_queue); +#else + kfree(priv->pshare->aidarray[i]->station.MGT_dz_queue); +#endif +#endif +#endif // CONFIG_PCI_HCI + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) +#ifdef PRIV_STA_BUF + free_wpa_buf(priv, priv->pshare->aidarray[i]->station.wpa_sta_info); +#else + kfree(priv->pshare->aidarray[i]->station.wpa_sta_info); +#endif +#endif +#ifdef RTL8192CD_VARIABLE_USED_DMEM + { + unsigned int index = (unsigned int)i; + rtl8192cd_dmem_free(AID_OBJ, &index); + } +#else +#ifdef PRIV_STA_BUF + free_sta_obj(priv, priv->pshare->aidarray[i]); +#else + kfree(priv->pshare->aidarray[i]); +#endif +#endif + priv->pshare->aidarray[i] = NULL; + } + } + } + +#ifdef CONFIG_USB_HCI + rtw_flush_rx_mgt_queue(priv); +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + rtw_flush_h2c_cmd_queue(priv, NULL); +#endif + rtw_flush_cmd_queue(priv, NULL); +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI + rtw_flush_rx_mgt_queue(priv); + rtw_flush_cmd_queue(priv, NULL); +#endif + +#ifndef __DRAYTEK_OS__ +#if !defined(RTK_NL80211) || defined(NON_NL80211_AP) //wrt-wps + // reset rsnie and group key from open to here, david +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef WIFI_SIMPLE_CONFIG + if (!priv->pmib->dot11OperationEntry.keep_rsnie) { + priv->pmib->wscEntry.beacon_ielen = 0; + priv->pmib->wscEntry.probe_rsp_ielen = 0; + priv->pmib->wscEntry.probe_req_ielen = 0; + priv->pmib->wscEntry.assoc_ielen = 0; + } + +// if (!(OPMODE & WIFI_AP_STATE)) +// priv->pmib->dot11OperationEntry.keep_rsnie = 1; +#endif + } +#endif + + if (!priv->pmib->dot11OperationEntry.keep_rsnie) { + priv->pmib->dot11RsnIE.rsnielen = 0; // reset RSN IE length + memset(&priv->pmib->dot11GroupKeysTable, '\0', sizeof(struct Dot11KeyMappingsEntry)); // reset group key +#ifdef UNIVERSAL_REPEATER + if (GET_VXD_PRIV(priv)) + GET_VXD_PRIV(priv)->pmib->dot11RsnIE.rsnielen = 0; +#endif + priv->auto_channel_backup = 0; + } + else { + // When wlan scheduling and auto-chan case, it will disable/enable + // wlan interface directly w/o re-set mib. Therefore, we need use + // "keep_rsnie" flag to keep auto-chan value + + if ( +#ifdef CHECK_HANGUP + !priv->reset_hangup && +#endif +#ifdef SMART_REPEATER_MODE + !priv->pshare->switch_chan_rp && +#endif + priv->auto_channel_backup) + priv->pmib->dot11RFEntry.dot11channel = 0; + } +#endif + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + if (IS_VAP_INTERFACE(priv) && !priv->pmib->dot11OperationEntry.keep_rsnie) { + priv->pmib->dot11RsnIE.rsnielen = 0; // reset RSN IE length + memset(&priv->pmib->dot11GroupKeysTable, '\0', sizeof(struct Dot11KeyMappingsEntry)); // reset group key + } + } + + // mark by Pedro: because priv->bcn_period_bak is zero currently. +#if !defined(RTK_NL80211) || defined(NON_NL80211_AP) +#ifdef CONFIG_WLAN_HAL + if (!IS_HAL_CHIP(priv)) +#endif + priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod = priv->bcn_period_bak; +#endif +#endif + +#ifdef RTK_BR_EXT + if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) { +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif + nat25_db_cleanup(priv); + } +#endif + +#ifdef A4_STA + if (OPMODE & WIFI_AP_STATE) { +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif + a4_sta_cleanup(priv); + } +#endif + +#ifdef CONFIG_PCI_HCI + { + int hd, tl; + struct sk_buff *pskb; + + hd = priv->dz_queue.head; + tl = priv->dz_queue.tail; + while (CIRC_CNT(hd, tl, NUM_TXPKT_QUEUE)) + { + pskb = priv->dz_queue.pSkb[tl]; + rtl_kfree_skb(priv, pskb, _SKB_TX_); + tl++; + tl = tl & (NUM_TXPKT_QUEUE - 1); + } + priv->dz_queue.head = 0; + priv->dz_queue.tail = 0; + } +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI + // release tx_mc_queue + rtw_txservq_flush(priv, &priv->tx_mc_queue); + _rtw_spinlock_free(&priv->tx_mc_queue.xframe_queue.lock); + + // release tx_mgnt_queue + rtw_txservq_flush(priv, &priv->tx_mgnt_queue); + _rtw_spinlock_free(&priv->tx_mgnt_queue.xframe_queue.lock); +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI + // release tx_mc_queue + rtw_txservq_flush(priv, &priv->tx_mc_queue); + _rtw_spinlock_free(&priv->tx_mc_queue.xframe_queue.lock); + + // release tx_mgnt_queue + rtw_txservq_flush(priv, &priv->tx_mgnt_queue); + _rtw_spinlock_free(&priv->tx_mgnt_queue.xframe_queue.lock); + +#ifdef CONFIG_POWER_SAVE + if(IS_ROOT_INTERFACE(priv)) + rtw_ap_ps_deinit(priv); +#endif + +#endif // CONFIG_SDIO_HCI + +#if !(defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX)) + flush_rx_queue(priv); +#endif + +RESTORE_INT(flags); + SMP_UNLOCK(flags); + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + _rtw_mutex_free(&(priv->hash_list_lock)); + _rtw_mutex_free(&(priv->auth_list_lock)); + _rtw_mutex_free(&(priv->sleep_list_lock)); + _rtw_mutex_free(&(priv->wakeup_list_lock)); + _rtw_mutex_free(&(priv->rc_packet_q_lock)); +#endif + +#ifdef WIFI_SIMPLE_CONFIG + wsc_disconn_list_flush(priv); +#endif + + return 0; +} + + +#ifdef RTK_NL80211 +#ifdef UNIVERSAL_REPEATER +static void rtl8192cd_init_vxd_mib(struct rtl8192cd_priv *priv) +{ + // copy mib_rf from root interface + memcpy(&priv->pmib->dot11RFEntry, &GET_ROOT(priv)->pmib->dot11RFEntry, sizeof(struct Dot11RFEntry)); +} +#endif +#endif + +#ifdef MBSSID +static void rtl8192cd_init_vap_mib(struct rtl8192cd_priv *priv) +{ +#if 0 + unsigned char tmpbuf[36], hwaddr[6]; + int len; + //unsigned int AclMode; + //unsigned char AclAddr[NUM_ACL][MACADDRLEN]; + //unsigned int AclNum; + struct Dot1180211AuthEntry dot1180211AuthEntry; + struct Dot118021xAuthEntry dot118021xAuthEntry; + struct Dot11DefaultKeysTable dot11DefaultKeysTable; + struct Dot11RsnIE dot11RsnIE; + + // backup mib that can differ from root interface + memcpy(hwaddr, GET_MY_HWADDR, 6); + len = SSID_LEN; + memcpy(tmpbuf, SSID, len); + //AclMode = priv->pmib->dot11StationConfigEntry.dot11AclMode; + //memcpy(AclAddr, priv->pmib->dot11StationConfigEntry.dot11AclAddr, sizeof(AclAddr)); + //AclNum = priv->pmib->dot11StationConfigEntry.dot11AclNum; + memcpy(&dot1180211AuthEntry, &priv->pmib->dot1180211AuthEntry, sizeof(struct Dot1180211AuthEntry)); + memcpy(&dot118021xAuthEntry, &priv->pmib->dot118021xAuthEntry, sizeof(struct Dot118021xAuthEntry)); + memcpy(&dot11DefaultKeysTable, &priv->pmib->dot11DefaultKeysTable, sizeof(struct Dot11DefaultKeysTable)); + memcpy(&dot11RsnIE, &priv->pmib->dot11RsnIE, sizeof(struct Dot11RsnIE)); + + // copy mib from root interface + memcpy(priv->pmib, GET_ROOT_PRIV(priv)->pmib, sizeof(struct wifi_mib)); + + // restore the different part + memcpy(GET_MY_HWADDR, hwaddr, 6); + SSID_LEN = len; + memcpy(SSID, tmpbuf, len); + SSID2SCAN_LEN = len; + memcpy(SSID2SCAN, SSID, len); + //priv->pmib->dot11StationConfigEntry.dot11AclMode = AclMode; + //memcpy(priv->pmib->dot11StationConfigEntry.dot11AclAddr, AclAddr, sizeof(AclAddr)); + //priv->pmib->dot11StationConfigEntry.dot11AclNum = AclNum; + memcpy(&priv->pmib->dot1180211AuthEntry, &dot1180211AuthEntry, sizeof(struct Dot1180211AuthEntry)); + memcpy(&priv->pmib->dot118021xAuthEntry, &dot118021xAuthEntry, sizeof(struct Dot118021xAuthEntry)); + memcpy(&priv->pmib->dot11DefaultKeysTable, &dot11DefaultKeysTable, sizeof(struct Dot11DefaultKeysTable)); + memcpy(&priv->pmib->dot11RsnIE, &dot11RsnIE, sizeof(struct Dot11RsnIE)); +#endif + unsigned int preamble; + +#ifdef NOT_RTK_BSP + // reserve the state of preamble + preamble = priv->pmib->dot11RFEntry.shortpreamble; +#endif + // copy mib_rf from root interface + memcpy(&priv->pmib->dot11RFEntry, &GET_ROOT(priv)->pmib->dot11RFEntry, sizeof(struct Dot11RFEntry)); +#ifdef NOT_RTK_BSP + priv->pmib->dot11RFEntry.shortpreamble = preamble; +#endif + + // special mib that need to set +#ifdef WIFI_WMM + //QOS_ENABLE = 0; +#ifdef WMM_APSD + APSD_ENABLE = 0; +#endif +#endif + +#ifdef WDS + // always disable wds in vap + priv->pmib->dot11WdsInfo.wdsEnabled = 0; + priv->pmib->dot11WdsInfo.wdsPure = 0; +#endif +#ifdef CONFIG_RTK_MESH + // in current release, mesh can be only run upon wlan0, so we disable the following flag in vap + priv->pmib->dot1180211sInfo.mesh_enable = 0; +#endif +} + +#if defined(CONFIG_PCI_HCI) || defined(__ECOS) +#if(CONFIG_WLAN_NOT_HAL_EXIST==1) + +#if defined(CONFIG_RTL_8812_SUPPORT) //eric_8812 ?? +static void rtl8192cd_set_DTIM(struct rtl8192cd_priv *priv) +{ +// printk("init swq=%d\n", priv->vap_init_seq); + if(GET_CHIP_VER(priv)==VERSION_8192E|| GET_CHIP_VER(priv)==VERSION_8812E) + { + switch (priv->vap_init_seq) + { + case 1: + RTL_W16(REG_92E_ATIMWND1, 0x03); //0x3C); + RTL_W8(REG_92E_DTIM_COUNT_VAP1, priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod); + break; + case 2: + RTL_W8(REG_92E_ATIMWND2, 0x3C); + RTL_W8(REG_92E_DTIM_COUNT_VAP2, priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod); + break; + case 3: + RTL_W8(REG_92E_ATIMWND3, 0x3C); + RTL_W8(REG_92E_DTIM_COUNT_VAP3, priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod); + break; + case 4: + RTL_W8(REG_92E_ATIMWND4, 0x3C); + RTL_W8(REG_92E_DTIM_COUNT_VAP4, priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod); + break; + case 5: + RTL_W8(REG_92E_ATIMWND5, 0x3C); + RTL_W8(REG_92E_DTIM_COUNT_VAP5, priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod); + break; + case 6: + RTL_W8(REG_92E_ATIMWND6, 0x3C); + RTL_W8(REG_92E_DTIM_COUNT_VAP6, priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod); + break; + case 7: + RTL_W8(REG_92E_ATIMWND7, 0x3C); + RTL_W8(REG_92E_DTIM_COUNT_VAP7, priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod); + break; + } + } +} +#endif + +static void rtl8192cd_init_mbssid(struct rtl8192cd_priv *priv) +{ + int i, j; + unsigned int camData[2]; + unsigned char *macAddr = GET_MY_HWADDR; + + if (IS_ROOT_INTERFACE(priv)) + { + //camData[0] = 0x00800000 | (macAddr[5] << 8) | macAddr[4]; + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | MBIDCAM_VALID | (macAddr[5] << 8) | macAddr[4]; + camData[1] = (macAddr[3] << 24) | (macAddr[2] << 16) | (macAddr[1] << 8) | macAddr[0]; +// for (j=0; j<2; j++) { + for (j=1; j>=0; j--) { + //RTL_W32((_MBIDCAMCONTENT_+4)-4*j, camData[j]); + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + } + //RTL_W8(_MBIDCAMCFG_, BIT(7) | BIT(6)); + + // clear the rest area of CAM + //camData[0] = 0; + camData[1] = 0; + for (i=1; i<8; i++) { + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | (i&MBIDCAM_ADDR_Mask)<=0; j--) { + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + } +// RTL_W8(_MBIDCAMCFG_, BIT(7) | BIT(6) | (unsigned char)i); + } + + // set MBIDCTRL & MBID_BCN_SPACE by cmd +// set_fw_reg(priv, 0xf1000101, 0, 0); + RTL_W32(MBSSID_BCN_SPACE, + (priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod & BCN_SPACE2_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod & BCN_SPACE1_Mask)<vap_init_seq = (RTL_R8(_MBIDCTRL_) & (BIT(4) | BIT(5) | BIT(6))) >> 4; +// priv->vap_init_seq++; +// set_fw_reg(priv, 0xf1000001 | ((priv->vap_init_seq + 1)&0xffff)<<8, 0, 0); + + priv->vap_init_seq = RTL_R8(MBID_NUM) & MBID_BCN_NUM_Mask; + priv->vap_init_seq++; + +#if defined(CONFIG_RTL_8812_SUPPORT) //eric_8812 ?? + rtl8192cd_set_DTIM(priv); +#endif + + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | MBIDCAM_VALID | + (priv->vap_init_seq&MBIDCAM_ADDR_Mask)<=0; j--) { + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + } +// RTL_W8(_MBIDCAMCFG_, BIT(7) | BIT(6) | ((unsigned char)priv->vap_init_seq & 0x1f)); +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + unsigned int vap_bcn_offset = (priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod- + ((priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod/(priv->vap_init_seq+1))*priv->vap_init_seq)-1) + & BCN_SPACE2_Mask; + + if (vap_bcn_offset > 200) + vap_bcn_offset = 200; + RTL_W32(MBSSID_BCN_SPACE, (vap_bcn_offset & BCN_SPACE2_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod & BCN_SPACE1_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod- + ((priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod/(priv->vap_init_seq+1))*priv->vap_init_seq)-1) + & BCN_SPACE2_Mask; + + if (vap_bcn_offset > 200) + vap_bcn_offset = 200; + RTL_W32(MBSSID_BCN_SPACE, (vap_bcn_offset & BCN_SPACE2_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod & BCN_SPACE1_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod- + ((priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod/(priv->vap_init_seq+1))*priv->vap_init_seq)) + & BCN_SPACE2_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod/(priv->vap_init_seq+1)) & BCN_SPACE1_Mask) + <vap_init_seq & MBID_BCN_NUM_Mask)); + else +#endif + RTL_W8(MBID_NUM, priv->vap_init_seq & MBID_BCN_NUM_Mask); + + RTL_W32(RCR, RTL_R32(RCR) & ~RCR_MBID_EN); + RTL_W32(RCR, RTL_R32(RCR) | RCR_MBID_EN); // MBSSID enable + } +} + +static void rtl8192cd_stop_mbssid(struct rtl8192cd_priv *priv) +{ + int i, j; + unsigned int camData[2]; + camData[1] = 0; + + if (IS_ROOT_INTERFACE(priv)) + { + // clear the rest area of CAM + for (i=0; i<8; i++) { + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | (i&MBIDCAM_ADDR_Mask)<=0; j--) { + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + } +// RTL_W8(_MBIDCAMCFG_, BIT(7) | BIT(6) | (unsigned char)i); + } + +// set_fw_reg(priv, 0xf1000001, 0, 0); + RTL_W32(RCR, RTL_R32(RCR) & ~RCR_MBID_EN); // MBSSID disable + RTL_W32(MBSSID_BCN_SPACE, + (priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod & BCN_SPACE1_Mask)<vap_init_seq >= 0)) + { + struct rtl8192cd_priv *tmpPriv; + unsigned char *macAddr; +// set_fw_reg(priv, 0xf1000001 | (((RTL_R8(_MBIDCTRL_) & (BIT(4) | BIT(5) | BIT(6))) >> 4)&0xffff)<<8, 0, 0); + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | + (priv->vap_init_seq&MBIDCAM_ADDR_Mask)<=0; j--) { + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + } +// RTL_W8(_MBIDCAMCFG_, BIT(7) | BIT(6) | ((unsigned char)priv->vap_init_seq & 0x1f)); + + for (i=0; ipvap_priv[i]; + if ((tmpPriv) && (tmpPriv->vap_init_seq > priv->vap_init_seq)) { + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | + (tmpPriv->vap_init_seq&MBIDCAM_ADDR_Mask)<=0; j--) { + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + } + } + } + + for (i=0; ipvap_priv[i]; + if ((tmpPriv) && (tmpPriv->vap_init_seq > priv->vap_init_seq)) { + struct rtl8192cd_hw *phw=GET_HW(tmpPriv); + struct tx_desc *pdesc; + extern void fill_bcn_desc(struct rtl8192cd_priv *priv, struct tx_desc *pdesc, void *dat_content, unsigned short txLength, char forceUpdate); + + macAddr = ((GET_MIB(tmpPriv))->dot11OperationEntry.hwaddr); + tmpPriv->vap_init_seq -= 1; + + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | MBIDCAM_VALID | + (tmpPriv->vap_init_seq&MBIDCAM_ADDR_Mask)<=0; j--) { + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + } + + pdesc = phw->tx_descB + tmpPriv->vap_init_seq; + fill_bcn_desc(tmpPriv, pdesc, (void*)tmpPriv->beaconbuf, tmpPriv->tx_beacon_len, 1); +#if defined(CONFIG_RTL_8812_SUPPORT) //eric_8812 ?? + rtl8192cd_set_DTIM(tmpPriv); +#endif + } + } + + if (RTL_R8(MBID_NUM) & MBID_BCN_NUM_Mask) { +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) //eric_8812 ?? + if ((GET_CHIP_VER(priv)==VERSION_8812E) || (GET_CHIP_VER(priv)==VERSION_8188E)) + RTL_W8(MBID_NUM, ((RTL_R8(MBID_NUM) & MBID_BCN_NUM_Mask)-1) & MBID_BCN_NUM_Mask); + else +#endif + RTL_W8(MBID_NUM, (RTL_R8(MBID_NUM)-1) & MBID_BCN_NUM_Mask); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + unsigned int vap_bcn_offset = (priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod- + ((priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod/(RTL_R8(MBID_NUM)+1)) + *RTL_R8(MBID_NUM))-1) & BCN_SPACE2_Mask; + + if (vap_bcn_offset > 200) + vap_bcn_offset = 200; + RTL_W32(MBSSID_BCN_SPACE, (vap_bcn_offset & BCN_SPACE2_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod & BCN_SPACE1_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod- + ((priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod/((RTL_R8(MBID_NUM) & MBID_BCN_NUM_Mask)+1))*(RTL_R8(MBID_NUM)&MBID_BCN_NUM_Mask))) + & BCN_SPACE2_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod) & BCN_SPACE1_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod- + ((priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod/(RTL_R8(MBID_NUM)+1))*RTL_R8(MBID_NUM))) + & BCN_SPACE2_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod/(RTL_R8(MBID_NUM)+1)) & BCN_SPACE1_Mask) + <vap_init_seq = -1; + } +} + +void rtl8192cd_set_mbssid(struct rtl8192cd_priv *priv, unsigned char *macAddr, unsigned char index) +{ + int i, j; + unsigned int camData[2]; + + if (index > 2) + return; + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | MBIDCAM_VALID | + ((7-index)&MBIDCAM_ADDR_Mask)<=0; j--) + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); +} + +void rtl8192cd_clear_mbssid(struct rtl8192cd_priv *priv, unsigned char index) +{ + int i, j; + unsigned int camData[2]; + + if (index > 1) + return; + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | MBIDCAM_VALID | ((7-index)&MBIDCAM_ADDR_Mask)<=0; j--) + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); +} +#else // !CONFIG_WLAN_NOT_HAL_EXIST +static void rtl8192cd_init_mbssid(struct rtl8192cd_priv *priv) +{ + return; +} +void rtl8192cd_set_mbssid(struct rtl8192cd_priv *priv, unsigned char *macAddr, unsigned char index) +{ + return; +} +void rtl8192cd_clear_mbssid(struct rtl8192cd_priv *priv, unsigned char index) +{ + return; +} + +static void rtl8192cd_stop_mbssid(struct rtl8192cd_priv *priv) +{ +} +#endif // CONFIG_WLAN_NOT_HAL_EXIST +#endif // CONFIG_PCI_HCI || __ECOS + +#ifdef MULTI_MAC_CLONE + void mclone_set_mbssid(struct rtl8192cd_priv *priv, unsigned char *macAddr) +{ + int i, j; + unsigned int camData[2]; + + // for debug + panic_printk("%s, %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, + macAddr[0],macAddr[1],macAddr[2],macAddr[3],macAddr[4],macAddr[5]); + + //wlan0 + if (!memcmp(macAddr, (GET_MIB(priv))->dot11OperationEntry.hwaddr, ETH_ALEN)) { + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | MBIDCAM_VALID | (macAddr[5] << 8) | macAddr[4]; + camData[1] = (macAddr[3] << 24) | (macAddr[2] << 16) | (macAddr[1] << 8) | macAddr[0]; + for (j=1; j>=0; j--) + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + + // clear the rest area of CAM + camData[1] = 0; + for (i=1; i<8; i++) { + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | (i&MBIDCAM_ADDR_Mask)<=0; j--) + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + } + + // set MBIDCTRL & MBID_BCN_SPACE by cmd + RTL_W32(MBSSID_BCN_SPACE, + (priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod & BCN_SPACE2_Mask)<pmib->dot11StationConfigEntry.dot11BeaconPeriod & BCN_SPACE1_Mask)<pshare->mclone_init_seq = RTL_R8(MBID_NUM) & MBID_BCN_NUM_Mask; + priv->pshare->mclone_init_seq++; + + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | MBIDCAM_VALID | + (priv->pshare->mclone_init_seq&MBIDCAM_ADDR_Mask)<=0; j--) + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + + RTL_W32(MBSSID_BCN_SPACE, + (priv->beacon_period & BCN_SPACE2_Mask)<pshare->mclone_init_seq & MBID_BCN_NUM_Mask); //MBID_NUM: 0x552[2:0] + + RTL_W32(RCR, RTL_R32(RCR) & ~RCR_MBID_EN); + RTL_W32(RCR, RTL_R32(RCR) | RCR_MBID_EN); // MBSSID enable + } +} + + +void mclone_stop_mbssid(struct rtl8192cd_priv *priv, int entIdx) +{ + int i, j, k; + unsigned int camData[2]; + camData[1] = 0; + + if (MCLONE_NUM <= 0) + return; + + // clear the rest area of CAM + for (i=0; i<8; i++) { + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | (i&MBIDCAM_ADDR_Mask)<=0; j--) + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + } + RTL_W32(RCR, RTL_R32(RCR) & ~RCR_MBID_EN); // MBSSID disable + RTL_W32(MBSSID_BCN_SPACE, + (priv->beacon_period& BCN_SPACE1_Mask)< 0 && priv->pshare->mclone_init_seq >= 0) + { + for (k=0; kpshare->mclone_init_seq--) + { + camData[0] = MBIDCAM_POLL | MBIDWRITE_EN | + (priv->pshare->mclone_init_seq & MBIDCAM_ADDR_Mask) <=0; j--) + RTL_W32((MBIDCAMCFG+4)-4*j, camData[j]); + + if (RTL_R8(MBID_NUM) & MBID_BCN_NUM_Mask) + { + RTL_W8(MBID_NUM, (RTL_R8(MBID_NUM)-1) & MBID_BCN_NUM_Mask); + RTL_W32(MBSSID_BCN_SPACE, (priv->beacon_period& BCN_SPACE1_Mask)<pshare->mclone_init_seq = -1; + } +} +#endif /* MULTI_MAC_CLONE */ +#endif + + +#ifdef WDS +#ifdef LAZY_WDS +void delete_wds_entry(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int i; + + for (i=0; ipmib->dot11WdsInfo.entry[i].macAddr, pstat->hwaddr, MACADDRLEN)) { + memcpy(priv->pmib->dot11WdsInfo.entry[i].macAddr, + NULL_MAC_ADDR, MACADDRLEN); + free_stainfo(priv, pstat); + priv->pmib->dot11WdsInfo.wdsNum--; + break; + } + } +} +#endif + +struct stat_info *add_wds_entry(struct rtl8192cd_priv *priv, int idx, unsigned char *mac) +{ + struct stat_info *pstat; + DOT11_SET_KEY Set_Key; +#ifdef LAZY_WDS + int i; + + if (mac != NULL) { + for (i=0; ipmib->dot11WdsInfo.entry[i].macAddr, + NULL_MAC_ADDR, MACADDRLEN)) { + memcpy( priv->pmib->dot11WdsInfo.entry[i].macAddr, mac, MACADDRLEN); + idx = i; + priv->pmib->dot11WdsInfo.wdsNum++; + break; + } + } + if (i == NUM_WDS) { + DEBUG_ERR("WDS table is full!!!\n"); + return NULL; + } + } +#endif + + pstat = alloc_stainfo(priv, priv->pmib->dot11WdsInfo.entry[idx].macAddr, -1); + if (pstat == NULL) { + DEBUG_ERR("alloc_stainfo() fail!\n"); + return NULL; + } + + + + // use self supported rate for wds + memcpy(pstat->bssrateset, AP_BSSRATE, AP_BSSRATE_LEN); + pstat->bssratelen = AP_BSSRATE_LEN; + pstat->state = WIFI_WDS; + + pstat->wds_probe_done=0; + pstat->state &= ~WIFI_WDS_RX_BEACON; + + //WDEBUG("priv->pmib->dot11WdsInfo.entry[%d].txRate=%04x\n\n",idx , priv->pmib->dot11WdsInfo.entry[idx].txRate); + + if ( priv->pmib->dot11WdsInfo.entry[idx].txRate & BIT31 ) { + //WDEBUG("under AC data rate\n"); + } else { + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11N)) + priv->pmib->dot11WdsInfo.entry[idx].txRate &= 0x0000fff; // mask HT rates + + if (!(priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G | WIRELESS_11A))) + priv->pmib->dot11WdsInfo.entry[idx].txRate &= 0xffff00f; // mask OFDM rates + + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11B)) + priv->pmib->dot11WdsInfo.entry[idx].txRate &= 0xffffff0; // mask CCK rates + } + + //WDEBUG("priv->pmib->dot11WdsInfo.entry[%d].txRate=%04x\n\n", idx , priv->pmib->dot11WdsInfo.entry[idx].txRate); + +#ifdef LAZY_WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE) + pstat->state |= WIFI_WDS_LAZY; + + if ((priv->pmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE) && + (priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_ || + priv->pmib->dot11WdsInfo.wdsPrivacy == _CCMP_PRIVACY_)) + wds_psk_set(priv, idx, NULL); +#endif + + if (priv->pmib->dot11WdsInfo.wdsPrivacy == _WEP_40_PRIVACY_ || + priv->pmib->dot11WdsInfo.wdsPrivacy == _WEP_104_PRIVACY_ ) { +#ifndef CONFIG_RTL8186_KB + memcpy(Set_Key.MACAddr, priv->pmib->dot11WdsInfo.entry[idx].macAddr, 6); + Set_Key.KeyType = DOT11_KeyType_Pairwise; + Set_Key.EncType = priv->pmib->dot11WdsInfo.wdsPrivacy; + Set_Key.KeyIndex = priv->pmib->dot11WdsInfo.wdsKeyId; + DOT11_Process_Set_Key(priv->dev, NULL, &Set_Key, priv->pmib->dot11WdsInfo.wdsWepKey); +#endif + } + else if ((priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_ || + priv->pmib->dot11WdsInfo.wdsPrivacy == _CCMP_PRIVACY_) && + (priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx]&0x80000000) ) { + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] &= ~0x80000000; + memcpy(Set_Key.MACAddr, priv->pmib->dot11WdsInfo.entry[idx].macAddr, 6); + Set_Key.KeyType = DOT11_KeyType_Pairwise; + Set_Key.EncType = priv->pmib->dot11WdsInfo.wdsPrivacy; + Set_Key.KeyIndex = priv->pmib->dot11WdsInfo.wdsKeyId; + DOT11_Process_Set_Key(priv->dev, NULL, &Set_Key, priv->pmib->dot11WdsInfo.wdsMapingKey[idx]); + } + +#if defined(CONFIG_PCI_HCI) +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + update_STA_RATid(priv, pstat); +#endif + pstat->wds_idx = idx; + assign_tx_rate(priv, pstat, NULL); + assign_aggre_mthod(priv, pstat); + assign_aggre_size(priv, pstat); + + asoc_list_add(priv, pstat); + + return pstat; +} + +static void create_wds_tbl(struct rtl8192cd_priv *priv) +{ + int i; + struct stat_info *pstat; + +#ifdef FAST_RECOVERY + if (priv->reset_hangup) + return; +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (!IS_ROOT_INTERFACE(priv)) + return; +#endif + + if (priv->pmib->dot11WdsInfo.wdsEnabled) { + for (i=0; ipmib->dot11WdsInfo.wdsNum; i++) { + pstat = add_wds_entry(priv, i, NULL); + if (pstat == NULL) + break; + } + } +} +#endif // WDS + + +void validate_fixed_tx_rate(struct rtl8192cd_priv *priv) +{ + if (!priv->pmib->dot11StationConfigEntry.autoRate) { + + if(priv->pmib->dot11StationConfigEntry.fixedTxRate & BIT(31)) //ac rates, vht 1ss, 2ss, 3ss... + { + unsigned char vht_mcs = 0; + + if(!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC)) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + + vht_mcs = (priv->pmib->dot11StationConfigEntry.fixedTxRate & 0xff); + + if((get_rf_mimo_mode(priv) == MIMO_1T1R) && (vht_mcs >= 10)) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + else if((get_rf_mimo_mode(priv) == MIMO_2T2R) && (vht_mcs >= 20)) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + else if((get_rf_mimo_mode(priv) == MIMO_3T3R) && (vht_mcs >= 30)) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + } + else if((priv->pmib->dot11StationConfigEntry.fixedTxRate & BIT(28)) + || (priv->pmib->dot11StationConfigEntry.fixedTxRate & 0x0ffff000)) //n rates. mcs0 - mcs 31 + { + + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11N)) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + + if((get_rf_mimo_mode(priv) == MIMO_1T1R)||(get_rf_mimo_mode(priv) == MIMO_1T2R)) + { + if(priv->pmib->dot11StationConfigEntry.fixedTxRate & BIT(28)) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + if(priv->pmib->dot11StationConfigEntry.fixedTxRate & 0x0ff00000) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + } + else if(get_rf_mimo_mode(priv) == MIMO_2T2R) + { + if(priv->pmib->dot11StationConfigEntry.fixedTxRate & BIT(28)) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + } + else if(get_rf_mimo_mode(priv) == MIMO_3T3R) + { + if(priv->pmib->dot11StationConfigEntry.fixedTxRate & BIT(28)) + { + if((priv->pmib->dot11StationConfigEntry.fixedTxRate&0xff) > 8) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + } + } + } + else if(priv->pmib->dot11StationConfigEntry.fixedTxRate & 0x00000ff0) // a, g rates, ofdm + { + if(!(priv->pmib->dot11BssType.net_work_type & (WIRELESS_11A | WIRELESS_11G))) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + } + else //b rates, cck + { + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11B)) + priv->pmib->dot11StationConfigEntry.fixedTxRate = 0; + } + + if (priv->pmib->dot11StationConfigEntry.fixedTxRate==0) { + priv->pmib->dot11StationConfigEntry.autoRate=1; + panic_printk("invalid fixed tx rate, use auto rate!\n"); + } + else + priv->pshare->current_tx_rate = get_rate_from_bit_value(priv->pmib->dot11StationConfigEntry.fixedTxRate); + + } + + if (priv->pmib->dot11StationConfigEntry.autoRate) + priv->pshare->current_tx_rate = find_rate(priv, NULL, 0, 1); +} + + +#ifdef RESERVE_TXDESC_FOR_EACH_IF +void recalc_txdesc_limit(struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_priv *root_priv = NULL; + int i, num, total_if = 0; + + if (IS_ROOT_INTERFACE(priv)) + root_priv = priv; + else + root_priv = GET_ROOT(priv); + + if (IS_DRV_OPEN(root_priv)) + total_if++; + +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(root_priv->pvxd_priv)) + total_if++; +#endif + +#ifdef MBSSID + for (i=0; ipvap_priv[i])) + total_if++; + } +#endif + + if (total_if <= 1) { + root_priv->pshare->num_txdesc_cnt = CURRENT_NUM_TX_DESC - 2; // 2 for space... + root_priv->pshare->num_txdesc_upper_limit = CURRENT_NUM_TX_DESC - 2; + root_priv->pshare->num_txdesc_lower_limit = 0; +#ifdef USE_TXQUEUE + root_priv->pshare->num_txq_cnt = TXQUEUE_SIZE; + root_priv->pshare->num_txq_upper_limit = TXQUEUE_SIZE; + root_priv->pshare->num_txq_lower_limit = 0; +#endif + return; + } + + num = (CURRENT_NUM_TX_DESC * IF_TXDESC_UPPER_LIMIT) / 100; + root_priv->pshare->num_txdesc_upper_limit = num; + + num = ((CURRENT_NUM_TX_DESC - 2) - num) / (total_if - 1); + root_priv->pshare->num_txdesc_lower_limit = num; + + num = root_priv->pshare->num_txdesc_upper_limit + + root_priv->pshare->num_txdesc_lower_limit * (total_if - 1); + root_priv->pshare->num_txdesc_cnt = num; + +#ifdef USE_TXQUEUE + num = (TXQUEUE_SIZE * IF_TXQ_UPPER_LIMIT) / 100; + root_priv->pshare->num_txq_upper_limit = num; + + num = (TXQUEUE_SIZE - num) / (total_if - 1); + root_priv->pshare->num_txq_lower_limit = num; + + num = root_priv->pshare->num_txq_upper_limit + + root_priv->pshare->num_txq_lower_limit * (total_if - 1); + root_priv->pshare->num_txq_cnt = num; +#endif +} +#endif + +#ifdef CONFIG_WLAN_HAL_8881A +// Branch 3.4 has no sys_bonding_type() +int get_bonding_type_8881A() +{ + int type = -1; + type = REG32(0xb800000c); + switch(type) + { + case 0: + type = BOND_8881AB; + break; + case 1: + type = BOND_8881AQ; + break; + case 3: + type = BOND_8881AL; + break; + case 9: + type = BOND_8881AN; + break; + case 10: + type = BOND_8881AM; + break; + case 13: + type = BOND_8881AM; + break; + default: + break; + } + return type; +} +#endif + +#if defined(CONFIG_RTL_8196E) +#if 1 +int get_96e_bonding_type() +{ +#define BOND_ID_MASK (0xF) +#define BOND_OPTION (SYSTEM_BASE+0x000C) + + return REG32(BOND_OPTION) & BOND_ID_MASK;; +} + +#else +#if defined(__ECOS) //mark_ecos +extern int bonding_type; //from switch +int sys_bonding_type(void) +{ + return bonding_type; +} +#else +extern int sys_bonding_type(void); //from rtl_gpio.c +#endif +#endif + +#define BOND_8196ES (0xD) +void rtl_8196es_gpio_init(void) +{ + //printk("rtl_8196es_gpio_init\n"); + // 8196ES GPIO + // WAKE# --> GPIOB5 , in (not yet , FIXME ) + // 8188ER GPIO definition , Out = 0x10 In= 0x01 + // WPS button --> GPIO7 ,In +#ifdef RTLWIFINIC_GPIO_CONTROL + RTLWIFINIC_GPIO_config(7, 0x01); + + // WPS LED / Reset LED --> GPIO4 ,out + RTLWIFINIC_GPIO_config(4, 0x10); + + // Reset button --> GPIO0 , in + RTLWIFINIC_GPIO_config(0, 0x01); +#endif +} +#endif + +#ifdef SDIO_AP_OFFLOAD +int is_ps_cond_match(struct rtl8192cd_priv *priv) +{ + if (0 == priv->pshare->total_assoc_num) + return 1; + else + return 0; +} + +void rtw_flush_all_tx_mgt_queue(struct rtl8192cd_priv *priv) +{ + rtw_txservq_flush(priv, &priv->tx_mgnt_queue); +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) { + struct rtl8192cd_priv *priv_vxd = GET_VXD_PRIV(priv); + rtw_txservq_flush(priv_vxd, &priv_vxd->tx_mgnt_queue); + } +#endif +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + int i; + for (i = 0; i < RTL8192CD_NUM_VWLAN; i++) { + struct rtl8192cd_priv *priv_vap = priv->pvap_priv[i]; + if (IS_DRV_OPEN(priv_vap)) { + rtw_txservq_flush(priv_vap, &priv_vap->tx_mgnt_queue); + } + } + } +#endif // MBSSID +} + +#ifndef CONFIG_POWER_SAVE +#define ACT_STS(x, y) ((x<<4)|y ) + +void sdio_power_save_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + unsigned char act = priv->pshare->ps_ctrl; + unsigned char sts = priv->pshare->pwr_state; + + if (priv->pshare->offload_prohibited) + goto out1; + + printk("acli: get %d %d %d\n", priv->pshare->total_assoc_num, act, sts); + + switch ( ACT_STS(act, sts) ) + { + case ACT_STS(RTW_ACT_IDLE, RTW_STS_NORMAL): + if ( is_ps_cond_match(priv)) { + /* send offload command */ + priv->pshare->offload_function_ctrl = RTW_PM_PREPROCESS; + priv->pshare->pwr_state = RTW_STS_SUSPEND; + + printk("starting offload \n"); + // Flush all tx_mgnt_queues and pending_xmitbuf_queue + // This purpose is to stop submitting any packet in AP offload (PS) state + rtw_flush_all_tx_mgt_queue(priv); + rtw_flush_xmit_pending_queue(priv); + } + break; + + case ACT_STS(RTW_ACT_ASSOC, RTW_STS_SUSPEND): + //GET_ROOT(priv)->offload_function_ctrl = RTW_PM_AWAKE; + priv->pshare->pwr_state = RTW_STS_NORMAL; + mod_timer(&priv->pshare->ps_timer, jiffies + POWER_DOWN_T0 + POWER_DOWN_T0); + goto out; + break; + + case ACT_STS(RTW_ACT_SETREP, RTW_STS_NORMAL): + priv->pshare->pwr_state = RTW_STS_REP; + goto out; + break; + + case ACT_STS(RTW_ACT_SETREP, RTW_STS_SUSPEND): + //GET_ROOT(priv)->offload_function_ctrl = RTW_PM_AWAKE; + //cmd_set_ap_offload(priv, 0); + priv->pshare->pwr_state = RTW_STS_REP; + goto out; + break; + + default: + break; + } +out1: + mod_timer(&priv->pshare->ps_timer, jiffies + POWER_DOWN_T0); + +out: + priv->pshare->ps_ctrl = RTW_ACT_IDLE; + return; +} +#endif // !CONFIG_POWER_SAVE +#endif // SDIO_AP_OFFLOAD + + +#ifdef RTK_NL80211 +int is_iface_ready_nl80211(struct net_device *dev, struct rtl8192cd_priv *priv) +{ + + if (priv->drv_state & DRV_STATE_OPEN) + { + DEBUG_INFO(" [%s] DO NOT double OPEN !!\n", dev->name); + return 0; + } + else + { + DEBUG_INFO("+++ OPEN[%s] for priv = %p (root=%d vxd=%d vap=%d) +++ \n\n", + dev->name, + priv, IS_ROOT_INTERFACE(priv), IS_VXD_INTERFACE(priv), IS_VAP_INTERFACE(priv)); + //printk("rtk->num_vap = %d rtk->num_vxd = %d \n", priv->rtk->num_vap, priv->rtk->num_vxd); + } + +#ifndef NOT_RTK_BSP + if(!IS_ROOT_INTERFACE(priv)) + { + if(!IS_DRV_OPEN(GET_ROOT(priv))) + { + DEBUG_INFO("Root interface NOT OPEN yet !!\n"); + return 0; + } + + if(IS_VXD_INTERFACE(priv) && (priv->rtk->num_vxd < 1)) + { + DEBUG_INFO("VXD if already deleted or NOT added !!\n"); + return 0; + } + + if(IS_VAP_INTERFACE(priv) && (priv->rtk->num_vap < 1)) + { + if(!is_WRT_scan_iface(dev->name)) //eric-vap + { + DEBUG_INFO("VAP already deleted or NOT added !!\n"); + return 0; + } + } + } +#endif + + if(is_WRT_scan_iface(dev->name)) + { + DEBUG_INFO("No need to call open for scan iface !!\n"); + return 0; + } + + return 1; + +} + +void prepare_iface_nl80211(struct net_device *dev, struct rtl8192cd_priv *priv) +{ + + if(priv->dev->priv_flags & IFF_DONT_BRIDGE) + { + //printk("Unable to be bridged !! Unlock for this iface !!\n"); + priv->dev->priv_flags &= ~(IFF_DONT_BRIDGE); + } + + check_5M10M_config(priv); + +#if 0 +defined(CONFIG_RTL_8881A_SELECTIVE) && !defined(CONFIG_RTL_8196E) && !defined(CONFIG_RTL_8196D) + { + if(strcmp(dev->name, "wlan0")==0) //wlan0 always be 5G, for 5G site survey issue + { + if((priv->pmib->dot11BssType.net_work_type & (WIRELESS_11B|WIRELESS_11G)) || + (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G)) + { + DEBUG_INFO("Correct Wlan0 as 5G Band !!\n"); + priv->pmib->dot11BssType.net_work_type = WIRELESS_11A|WIRELESS_11N; + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; + } + + } + } +#endif + + if(IS_VAP_INTERFACE(priv)) + { + //panic_printk("\n FORCE ROOT VAP_ENABLE=1 (VAP OPENED)!! \n\n"); + GET_ROOT(priv)->pmib->miscEntry.vap_enable = 1; + } + + //Clear scan_req from NL80211 + priv->scan_req = NULL; + + /* Because end of realtek_start_ap will perform close-open to initialize, + previos configured bandwidth will lost if always setup with N bandwidth. + */ + if(!priv->rtk->keep_legacy) { + //always enable N bandwidth to make client mode support WMM + priv->pmib->dot11BssType.net_work_type |= WIRELESS_11N; + } else { + priv->rtk->keep_legacy = 0; + } +} +#endif //RTK_NL80211 + + +int rtl8192cd_open(struct net_device *dev) +{ + struct rtl8192cd_priv *priv; // recuresively used, can't be static + int rc; +#ifdef CONFIG_WLAN_HAL + unsigned int errorFlag; +#endif + + int i; + + unsigned long x = 0; +#ifdef CHECK_HANGUP + int is_reset; +#endif + int init_hw_cnt = 0; + + DBFENTER; + + priv = GET_DEV_PRIV(dev); + + STADEBUG("===>\n"); + + if (NULL == wlan_device[0].priv) + return -ENODEV; + +#ifdef RTK_NL80211 + if(!is_iface_ready_nl80211(dev, priv)) + return 0; + + prepare_iface_nl80211(dev, priv); +#endif + +#ifdef AC2G_256QAM + if( (is_ac2g(priv)) && (GET_CHIP_VER(priv)==VERSION_8812E) ) + { + if(priv->pshare->rf_ft_var.ac2g_phy_type == 0) + { + printk("8812 2G support AC mode, PCIE_ALNA!!\n"); +#ifdef HIGH_POWER_EXT_PA + priv->pshare->rf_ft_var.use_ext_pa = 0; +#endif +#ifdef HIGH_POWER_EXT_LNA + priv->pshare->rf_ft_var.use_ext_lna = 1; +#endif + } + else + { + printk("8812 2G support AC mode, PCIE_APA_ALNA!!\n"); +#ifdef HIGH_POWER_EXT_PA + priv->pshare->rf_ft_var.use_ext_pa = 1; +#endif +#ifdef HIGH_POWER_EXT_LNA + priv->pshare->rf_ft_var.use_ext_lna = 1; +#endif + } + } +#endif + + #if defined(CONFIG_RTL_CUSTOM_PASSTHRU) + /*to open custom pass through pseudo device*/ + if(dev==wlan_device[passThruWanIdx].priv->pWlanDev) + { + /*root device is opened*/ + if(priv->drv_state&DRV_STATE_OPEN) + { + netif_start_queue(dev); + return 0; + } + + } + #endif + +#ifdef CONFIG_WLAN_HAL_8881A + if(GET_CHIP_VER(priv)==VERSION_8881A) { + //Enable MAC_System(BIT(0)), MAC_Lextra_Bus(BIT(1)) + REG32(0xB80000DC)= 0x03; + } +#endif //CONFIG_WLAN_HAL_8881A + +#if 0 +//#ifdef PCIE_POWER_SAVING + if (((REG32(CLK_MANAGE) & BIT(11)) == 0) +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + && IS_ROOT_INTERFACE(priv) +#endif + ) { + extern void setBaseAddressRegister(void); + REG32(CLK_MANAGE) |= BIT(11); + delay_ms(10); + PCIE_reset_procedure(0, 0, 1, priv->pshare->ioaddr); + setBaseAddressRegister(); + } +#endif + +// for Virtual interface... +#ifdef USE_OUT_SRC + if((GET_CHIP_VER(priv)== VERSION_8812E) || (GET_CHIP_VER(priv)== VERSION_8188E) || (IS_HAL_CHIP(priv))) + { + priv->pshare->use_outsrc = 1; +// printk("use out source!!\n"); + } + else + { + priv->pshare->use_outsrc = 0; +// printk("NOT use out source!!\n"); + } +#endif + +#ifdef CHECK_HANGUP + is_reset = priv->reset_hangup; +#endif + +// init mib from cfg file, we only need to load cfg file once - chris 2010/02 +#ifdef CONFIG_RTL_COMAPI_CFGFILE +#ifdef WDS + if (dev->base_addr) //root +#endif + { + //printk(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>dev %s set_default\n", dev->name); + //memset(priv->pmib, 0, sizeof(struct wifi_mib)); + //set_mib_default(priv); + + CfgFileProc(dev); + } +#endif + +// register iw_handler - chris 2010/02 +#if defined(CONFIG_RTL_COMAPI_WLTOOLS) || defined(WIFI_WPAS) +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) + OPMODE |= WIFI_STATION_STATE; +#endif + dev->wireless_handlers = (struct iw_handler_def *) &rtl8192cd_iw_handler_def; +#endif + + memcpy((void *)dev->dev_addr, priv->pmib->dot11OperationEntry.hwaddr, 6); + +#ifdef WDS + if (dev->base_addr == 0) + { +#ifdef BR_SHORTCUT + extern struct net_device *cached_wds_dev; + cached_wds_dev = NULL; +#endif + + netif_start_queue(dev); + return 0; + } +#endif + +#ifdef CONFIG_RTK_MESH + + if (dev->base_addr == 1) { + if(priv->mesh_priv_sc) {/*dual band*/ + /* reallocate private to mesh dev*/ + if(priv->dev->name[4] == '0' && (!IS_DRV_OPEN(priv) || GET_MIB(priv)->dot1180211sInfo.mesh_enable == 0)) { + priv = dev->priv = priv->mesh_priv_sc; + memcpy((void *)dev->dev_addr, priv->pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + } + else if(priv->dev->name[4] == '1' && (IS_DRV_OPEN(priv->mesh_priv_sc) && GET_MIB(priv->mesh_priv_sc)->dot1180211sInfo.mesh_enable)) { + priv = dev->priv = priv->mesh_priv_sc; + memcpy((void *)dev->dev_addr, priv->pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + } + + + #if !defined(CONFIG_RTL_MESH_CROSSBAND) + priv->mesh_priv_sc->mesh_priv_first = priv; + priv->mesh_priv_first = priv; + #endif + } + +#if defined(RTK_MESH_AODV_STANDALONE_TIMER) + init_timer(&priv->mesh_expire_timer); + priv->mesh_expire_timer.expires = jiffies+MESH_AODV_EXPIRE_TO; + priv->mesh_expire_timer.data = (unsigned long) priv; + priv->mesh_expire_timer.function = mesh_standalone_timer_expire; + add_timer(&priv->mesh_expire_timer); + + + #if defined(CONFIG_RTL_MESH_CROSSBAND) + if(GET_MIB(priv->mesh_priv_sc)->dot1180211sInfo.mesh_enable) { + init_timer(&priv->mesh_priv_sc->mesh_expire_timer); + priv->mesh_priv_sc->mesh_expire_timer.expires = jiffies+MESH_AODV_EXPIRE_TO; + priv->mesh_priv_sc->mesh_expire_timer.data = (unsigned long) priv->mesh_priv_sc; + priv->mesh_priv_sc->mesh_expire_timer.function = mesh_standalone_timer_expire; + add_timer(&priv->mesh_priv_sc->mesh_expire_timer); + } + #endif +#endif + netif_start_queue(dev); + return 0; + } +#endif // CONFIG_RTK_MESH + +#ifdef PCIE_POWER_SAVING + if((priv->pwr_state == L1) || (priv->pwr_state == L2)) { + PCIeWakeUp(priv, (POWER_DOWN_T0<<3)); + } +#endif +#ifdef SDIO_AP_OFFLOAD +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (!IS_ROOT_INTERFACE(priv)) { + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_DEV_OPS); + } +#endif +#endif + + // stop h/w in the very beginning +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef CONFIG_USB_HCI + priv->pshare->bDriverStopped = FALSE; + priv->pshare->bSurpriseRemoved = FALSE; + priv->pshare->bReadPortCancel = FALSE; + priv->pshare->bWritePortCancel = FALSE; + priv->pshare->cmd_wake = 0; + for (i = 0; i < BITS_TO_LONGS(MAX_RTW_CMD_CODE); ++i) + priv->pshare->pending_cmd[i] = 0; +#endif + +#ifdef CONFIG_SDIO_HCI +#ifdef SDIO_AP_OFFLOAD + priv->pshare->offload_function_ctrl = RTW_PM_AWAKE; + priv->pshare->ps_ctrl = RTW_ACT_IDLE; + priv->pshare->pwr_state = RTW_STS_NORMAL; + priv->pshare->offload_prohibited &= (OFFLOAD_PROHIBIT_USER|OFFLOAD_PROHIBIT_HANGUP); +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) + priv->pshare->offload_prohibited |= OFFLOAD_PROHIBIT_MP; +#endif + INIT_WORK(&priv->ap_cmd_queue, handle_ap_cmd); +#endif + priv->pshare->bDriverStopped = FALSE; + priv->pshare->bSurpriseRemoved = FALSE; + priv->pshare->xmit_wake = 0; + priv->pshare->cmd_wake = 0; + for (i = 0; i < BITS_TO_LONGS(MAX_RTW_CMD_CODE); ++i) + priv->pshare->pending_cmd[i] = 0; + priv->pshare->pHalData->SdioTxIntStatus = 0; // Polling mode + priv->pshare->pHalData->SdioRxFIFOCnt = 0; +#ifdef CONFIG_SDIO_TX_INTERRUPT + priv->pshare->freepage_updated = 0; +#endif +#endif // CONFIG_SDIO_HCI +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + priv->pshare->need_sched_xmit = 0; + priv->pshare->low_traffic_xmit = BIT(MGNT_QUEUE) | BIT(HIGH_QUEUE); +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + BOOLEAN bVal; + + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_MAC_IO_ENABLE, (pu1Byte)&bVal); + if ( bVal ) { + if (RT_STATUS_SUCCESS != GET_HAL_INTERFACE(priv)->StopHWHandler(priv)) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_CLOSE_STOP_HW; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + panic_printk("StopHW Failed\n"); + } + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + {//not HAL + if ( check_MAC_IO_Enable(priv) ) + rtl8192cd_stop_hw(priv); + } + + } + +#ifdef UNIVERSAL_REPEATER + // If vxd interface, see if some mandatory mib is set. If ok, backup these + // mib, and copy all mib from root interface. Then, restore the backup mib + // to current. + + if (IS_VXD_INTERFACE(priv)) { + DEBUG_INFO("Open request from vxd\n"); + if (!IS_DRV_OPEN(GET_ROOT(priv))) { + printk("Open vxd error! Root interface should be opened in advanced.\n"); +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_DEV_OPS); +#endif + return 0; + } + +#ifdef PCIE_POWER_SAVING + if((GET_ROOT(priv)->pwr_state == L1) || (GET_ROOT(priv)->pwr_state == L2)) { + PCIeWakeUp(GET_ROOT(priv), (POWER_DOWN_T0<<3)); + } +#endif + + if (!(priv->drv_state & DRV_STATE_VXD_INIT)) { +// Mark following code. MIB copy will be executed through ioctl ------------- +#if 0 + unsigned char tmpbuf[36]; + int len, encyption, is_1x, mac_clone, nat25; + struct Dot11RsnIE rsnie; + + len = SSID_LEN; + memcpy(tmpbuf, SSID, len); + encyption = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + is_1x = IEEE8021X_FUN; + mac_clone = priv->pmib->ethBrExtInfo.macclone_enable; + nat25 = priv->pmib->ethBrExtInfo.nat25_disable; + memcpy((char *)&rsnie, (char *)&priv->pmib->dot11RsnIE, sizeof(rsnie)); + + memcpy(priv->pmib, GET_ROOT_PRIV(priv)->pmib, sizeof(struct wifi_mib)); + + SSID_LEN = len; + memcpy(SSID, tmpbuf, len); + SSID2SCAN_LEN = len; + memcpy(SSID2SCAN, SSID, len); + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = encyption; + IEEE8021X_FUN = is_1x; + priv->pmib->ethBrExtInfo.macclone_enable = mac_clone; + priv->pmib->ethBrExtInfo.nat25_disable = nat25; + memcpy((char *)&priv->pmib->dot11RsnIE, (char *)&rsnie, sizeof(rsnie)); +#ifdef WDS + // always disable wds in vxd + priv->pmib->dot11WdsInfo.wdsEnabled = 0; + priv->pmib->dot11WdsInfo.wdsPure = 0; +#endif + + // if root interface is AP mode, set infra-client in vxd + // if root interfeace is a infra-client, set AP in vxd + if (OPMODE & WIFI_AP_STATE) { + OPMODE = WIFI_STATION_STATE; +#if defined(WIFI_WMM) && defined(WMM_APSD) + APSD_ENABLE = 0; +#endif + DEBUG_INFO("Set vxd as an infra-client\n"); + } + else if (OPMODE & WIFI_STATION_STATE) { + OPMODE = WIFI_AP_STATE; + priv->auto_channel = 0; + DEBUG_INFO("Set vxd as an AP\n"); + } + else { + DEBUG_ERR("Invalid opmode for vxd!\n"); + return 0; + } +#endif +//---------------------------------------------------------- david+2008-03-17 + + // correct RSN IE will be set later for WPA/WPA2 +#ifdef CHECK_HANGUP + if (!is_reset) +#endif +#ifdef SMART_REPEATER_MODE + if (!priv->pmib->dot11OperationEntry.keep_rsnie) +#endif + memset(&priv->pmib->dot11RsnIE, 0, sizeof(struct Dot11RsnIE)); + +#ifdef WDS + // always disable wds in vxd + priv->pmib->dot11WdsInfo.wdsEnabled = 0; + priv->pmib->dot11WdsInfo.wdsPure = 0; +#endif + + // Sync regdomain from root AP, ensure connectivity + priv->pmib->dot11StationConfigEntry.dot11RegDomain = GET_ROOT(priv)->pmib->dot11StationConfigEntry.dot11RegDomain; + +#ifdef CONFIG_RTK_MESH + // always disable mesh in vxd (for dev) + GET_MIB(priv)->dot1180211sInfo.mesh_enable = 0; +#endif // CONFIG_RTK_MESH + priv->drv_state |= DRV_STATE_VXD_INIT; // indicate the mib of vxd driver has been initialized + } +#ifdef SDIO_AP_OFFLOAD + priv->pshare->ps_ctrl = RTW_ACT_SETREP; +#endif + } +#endif // UNIVERSAL_REPEATER + +#ifdef CHECK_HANGUP + if (!is_reset) +#endif + { +#ifdef P2P_SUPPORT + int p2p_support_mode=0; + if (OPMODE & WIFI_P2P_SUPPORT) + p2p_support_mode=1; +#endif + if (OPMODE & WIFI_AP_STATE) { + OPMODE_VAL(WIFI_AP_STATE); + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) { + OPMODE_VAL(WIFI_STATION_STATE); + } else if (OPMODE & WIFI_ADHOC_STATE) { + OPMODE_VAL(WIFI_ADHOC_STATE); +#if defined(WIFI_WMM) && defined(WMM_APSD) + APSD_ENABLE = 0; +#endif + } +#endif + else { + printk("Undefined state... using AP mode as default\n"); + OPMODE_VAL(WIFI_AP_STATE); + } + +#ifdef P2P_SUPPORT + if(p2p_support_mode) + OPMODE_VAL(OPMODE | WIFI_P2P_SUPPORT); +#endif + } + +#if defined(UNIVERSAL_REPEATER) && defined(CLIENT_MODE) + if (IS_VXD_INTERFACE(priv) && + ((GET_MIB(GET_ROOT(priv)))->dot11OperationEntry.opmode & WIFI_STATION_STATE)) { + if (!chklink_wkstaQ(GET_ROOT(priv))) { + printk("Root interface does not link yet!\n"); +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_DEV_OPS); +#endif + return 0; + } + } +#endif + +#ifdef WIFI_WMM +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pmib->dot11OperationEntry.wifi_specific) + priv->pshare->rf_ft_var.wifi_beq_iot = 1; +#endif +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv) == VERSION_8812E) + if (priv->pmib->dot11OperationEntry.wifi_specific) + priv->pshare->rf_ft_var.wifi_beq_iot = 1; +#endif +#endif + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + if (IS_VAP_INTERFACE(priv)) { + if (!IS_DRV_OPEN(GET_ROOT(priv))) { + printk("Open vap error! Root interface should be opened in advanced.\n"); +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_DEV_OPS); +#endif + return -1; + } + + if ((GET_ROOT(priv)->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) == 0) { + printk("Fail to open VAP under non-AP mode!\n"); +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_DEV_OPS); +#endif + return -1; + } + else { +#ifdef CONFIG_RTL8672 + do { + if (GET_ROOT(priv)->pmib->dot11OperationEntry.opmode & WIFI_WAIT_FOR_CHANNEL_SELECT) { + DEBUG_INFO("wait for root interface ss_timer!!\n"); + delay_ms(1); + } + else { + DEBUG_INFO("channel=%x\n", GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel); + break; + } + }while(1); +#endif + rtl8192cd_init_vap_mib(priv); + } + } + } +#endif + +#ifdef RTK_NL80211 +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) + rtl8192cd_init_vxd_mib(priv); +#endif +#endif + +// check phyband and channel match or not +#ifdef MP_TEST + if(priv->pshare->rf_ft_var.mp_specific) //For MP nfjrom to open WLAN0 successfully + { + if ((priv->pmib->dot11RFEntry.dot11channel <= 14) && (priv->pmib->dot11RFEntry.phyBandSelect != PHY_BAND_2G)) + { + priv->pmib->dot11BssType.net_work_type = WIRELESS_11A | WIRELESS_11N; + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; + priv->pmib->dot11RFEntry.dot11channel = 36; + } + else if((priv->pmib->dot11RFEntry.dot11channel > 14) && (priv->pmib->dot11RFEntry.phyBandSelect != PHY_BAND_5G)) + { + priv->pmib->dot11BssType.net_work_type = WIRELESS_11B | WIRELESS_11G | WIRELESS_11N; + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; + priv->pmib->dot11RFEntry.dot11channel = 1; + } + + if((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)) + { + priv->pmib->dot11BssType.net_work_type = WIRELESS_11B | WIRELESS_11G | WIRELESS_11N; + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; + priv->pmib->dot11RFEntry.dot11channel = 1; + } + + // TODO: Should we add some code here?? By Filen + } +#endif + +#ifdef RTK_AC_SUPPORT //for 11ac logo + if(AC_SIGMA_MODE != AC_SIGMA_NONE) + { + priv->pmib->dot11StationConfigEntry.dot11RegDomain = DOMAIN_TEST; + printk("Enable all channels, domain = %d\n", priv->pmib->dot11StationConfigEntry.dot11RegDomain); + } +#endif + +#if defined(BR_SHORTCUT) +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if(IS_ROOT_INTERFACE(priv)) +#endif + clear_shortcut_cache(); +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + priv->pshare->current_num_tx_desc = NUM_TX_DESC; + +#if defined (CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_92D_DMDP) + if ((GET_CHIP_VER(priv) == VERSION_8192D) && + (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY)) + priv->pshare->current_num_tx_desc = (NUM_TX_DESC>MAX_NUM_TX_DESC_DMDP)? + (MAX_NUM_TX_DESC_DMDP):(NUM_TX_DESC); +#endif + } + + rc = rtl8192cd_init_sw(priv); + if (rc) { + printk("ERROR : rtl8192cd_init_sw failure\n"); + goto free_res; + } + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196C_EC) + if (!priv->auto_channel) { + LOG_START_MSG(); + } +#endif +//#ifdef CONFIG_RTL865X_AC +#if defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) + if (!priv->auto_channel) { + LOG_START_MSG(); + } +#endif + + validate_fixed_tx_rate(priv); + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef CONFIG_SDIO_HCI + if ((rc = sdio_alloc_irq(priv)) != 0) { + goto free_res; + } +#ifdef CONFIG_POWER_SAVE + rc = init_wifi_wakeup_gpio(dev, priv); + if (rc < 0) + goto free_res; +#endif +#endif // CONFIG_SDIO_HCI + +#ifdef CONFIG_PCI_HCI +#ifdef __KERNEL__ +#ifdef CHECK_HANGUP + if (!is_reset) +#endif + { +#if !defined(CONFIG_RTL8671) + #if defined(__LINUX_2_6__) + #if defined(CONFIG_RTL_92D_DMDP) || defined(NOT_RTK_BSP) + rc = request_irq(dev->irq, rtl8192cd_interrupt, IRQF_SHARED|IRQF_DISABLED, dev->name, dev); + #else + rc = request_irq(dev->irq, rtl8192cd_interrupt, IRQF_DISABLED, dev->name, dev); + #endif + #else + rc = request_irq(dev->irq, rtl8192cd_interrupt, SA_SHIRQ, dev->name, dev); + #endif +#else + rc = request_irq(dev->irq, rtl8192cd_interrupt, SA_INTERRUPT, dev->name, dev); +#endif + +#if defined(PCIE_POWER_SAVING) && defined(GPIO_WAKEPIN) + rc |= request_irq_for_wakeup_pin(dev); +#endif + + if (rc) { + DEBUG_ERR("some issue in request_irq, rc=%d\n", rc); + } + } +#endif +#endif // CONFIG_PCI_HCI + + //SAVE_INT_AND_CLI(x); + SMP_LOCK(x); + + watchdog_stop(priv); + +#ifdef EN_EFUSE + { + int i, readEfuse=0; +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + int idx= 0; + if (GET_CHIP_VER(priv) == VERSION_8192D || GET_CHIP_VER(priv) == VERSION_8812E) { + for (i=0 ; i < MAX_5G_CHANNEL_NUM ; i++) { + if (priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[i]) + idx++; + } + + if (!idx) + readEfuse = 1; + } + else +#endif + { + for(i=0;ipmib->dot11RFEntry.pwrlevelCCK_A[i]==0 + || priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[i] ==0) { + readEfuse = 1; + break; + } + } + } + if(readEfuse) + ReadTxPowerInfoFromHWPG(priv); + + if(priv->pmib->dot11RFEntry.ther==0) { + ReadThermalMeterFromEfuse(priv); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + ReadCrystalCalibrationFromEfuse(priv); + ReadDeltaValFromEfuse(priv); + ReadTRSWPAPEFromEfuse(priv); + } +#endif +#ifdef CONFIG_SDIO_HCI +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) + ReadCrystalCalibrationFromEfuse(priv); +#endif +#endif + } +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv)==VERSION_8812E) + ReadTxBBSwingFromEfuse(priv); +#endif + } +#endif + +do_hw_init: + + +#if defined(CONFIG_AUTO_PCIE_PHY_SCAN) +#ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv)==VERSION_8188E) + { + #if defined(CONFIG_RTL_8881A) + if ((REG32(0xb8000008) & 0x1000000) != 0x1000000) { + RTL_W8(0x2c, ((RTL_R8(0x2c) & 0xf0) | 0x1)); + printk("\n\n 8881A+88E 25M TEST 0x11=0x5b, 0x2c[0:3]=0x1 \n\n"); + } else { + printk("\n\n 8881A+88E 40M TEST 0x11=0x5b \n\n"); + } + #elif defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL_819XD) + if ((REG32(0xb8000008)&0x2000000)==0x2000000) //40MHz + { + printk("\n\n 88E 40M TEST 0x11=0x5b \n\n"); + + //RTL_W8(0x11, 0x5b); + //RTL_W8(0x2c, ((RTL_R8(0x2c) & 0xf0) | 0x1)); + } + else //25MHz + { + printk("\n\n 88E 25M TEST 0x11=0x5b, 0x2c[0:3]=0x1 \n\n"); + + //RTL_W8(0x11, 0x5b); + RTL_W8(0x2c, ((RTL_R8(0x2c) & 0xf0) | 0x1)); + } + #endif + } +#endif +#endif +#if !defined(CONFIG_AUTO_PCIE_PHY_SCAN) && !defined(CONFIG_PHY_EAT_40MHZ) && (defined(CONFIG_RTL_8197DL) || defined(CONFIG_RTL8672)) +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + //25MHz + //printk("\n\n 88E 25M TEST 0x11=0x5b, 0x2c[0:3]=0x1 \n\n"); + printk("\n\n 88E 25M, 0x2c[0:3]=0x1 \n\n"); + + //RTL_W8(0x11, 0x5b); + RTL_W8(0x2c, ((RTL_R8(0x2c) & 0xf0) | 0x1)); + } +#endif +#endif + + rc = rtl8192cd_init_hw_PCI(priv); + //delay_ms(200); // TODO: need refinement, for 98 watchdog time out + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (priv->pshare->bSurpriseRemoved) { + rc = 1; + goto free_res; + } +#endif + + // write IDR0, IDR4 here + { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_ETHER_ADDR, (pu1Byte)dev->dev_addr); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + unsigned long reg = 0; + reg = *(unsigned long *)(dev->dev_addr); + // RTL_W32(IDR0, (cpu_to_le32(reg))); + RTL_W32(MACID, (cpu_to_le32(reg))); + reg = *(unsigned short *)((unsigned long)dev->dev_addr + 4); + // RTL_W32(IDR4, (cpu_to_le32(reg))); + RTL_W16(MACID+4, (cpu_to_le16(reg))); + #ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + RTL_W32(MACID1 , RTL_R32(MACID)); + RTL_W16(MACID1+4, RTL_R16(MACID+4)); + } + #endif + } + } + + if (rc && ++init_hw_cnt < 5) { +#ifndef NOT_RTK_BSP + if (GET_CHIP_VER(priv)==VERSION_8192D) { + watchdog_kick(); + } +#endif + goto do_hw_init; + } + + //if (GET_CHIP_VER(priv)==VERSION_8192D) { + watchdog_resume(priv); + //} + + //RESTORE_INT(x); + SMP_UNLOCK(x); + + if (rc) { + DEBUG_ERR("init hw failed!\n"); +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D){ + RTL_W8(RSV_MAC0_CTRL, RTL_R8(RSV_MAC0_CTRL)&(~MAC0_EN)); + RTL_W8(RSV_MAC1_CTRL, RTL_R8(RSV_MAC1_CTRL)&(~MAC1_EN)); + } +#endif //CONFIG_RTL_92D_SUPPORT + force_stop_wlan_hw(); +#ifndef NOT_RTK_BSP +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)!=VERSION_8192D) /* do not trigger wtdog if 92D open fail */ +#endif + { +#ifdef LINUX_2_6_20_ + local_irq_disable(); +#else + cli(); +#endif +#ifdef CONFIG_RTL_8198B + REG32(BSP_WDTCTRLR) = BSP_WDT_ENABLE; +#else + *(volatile unsigned long *)(0xB800311c) = 0; /* enable watchdog reset now */ +#endif + for(;;) + ; + } +#endif // !NOT_RTK_BSP + goto free_res; + } +#ifdef CONFIG_WLAN_HAL_8814AE // temp add in 8813 FPGA by Eric + else + { + #ifdef DRVMAC_LB + if(GET_CHIP_VER(priv)==VERSION_8814A) { + // disable early mode, multi-tag + RTL_W32(0x3fc, ((RTL_R32(0x3fc)&0xFFFF0FFF) & (~BIT6))&(~BIT5) ); + } + #endif + #if 0 //def RTL8814_FPGA_TEMP + if(GET_CHIP_VER(priv)==VERSION_8814A) { + + // Open BB RF + //RTL_W8(0x2, RTL_R8(0x2)|BIT0|BIT1); + + // ACK RATE SETTING + //RTL_W8(0x6de, RTL_R8(0x6de)|BIT7); + + //===============Disable New Early Mode================ + + // disable new early mode, and AMPDU burst mode + //RTL_W32(0x4bc, ((RTL_R32(0x4bc)&0xFFFFFFF0)&(~BIT7))); + + // disable early mode, multi-tag + RTL_W32(0x3fc, ((RTL_R32(0x3fc)&0xFFFF0FFF) & (~BIT6))&(~BIT5) ); + + // BIT_UDF_THSD[8]=1,enable underflow recovery;r_UDF_THSD[8]=0,disable underflow recovery; + // BIT_UDF_THSD[6:0]: when mac_wrptr - PHY_rdptr is less than this value, set underflow; + //RTL_W8(0x632, 0); + + // Disable Rx BA or ACK + //RTL_W8(0x7A3,RTL_R8(0x7A3)& (~BIT0)); + + // enable Rx data/management/control packet + //RTL_W32(0x6a0,0xffffffff); + //RTL_W32(0x6a4,0xffffffff); + + //RTL_W8(0x60C,0x20); + + // Enable MAC security engine 0x100 bit9, sync with RS driver 2013/07/11 + //RTL_W8(0x101,RTL_R8(0x101)|BIT1); + + // REG_TRXFF_BNDY 0x114 bit shift error, sync with RS driver 2013/07/11 + // set RX boundary 24K + //RTL_W32(0x114, (RTL_R32(0x114)&0xFC0000FF)|(0x5fff)<<8); + // set RXFIFO overflow Thre. + //RTL_W32(0x114, (RTL_R32(0x114)&0x3FFFFFF)|(0xf)<<28); + + // disable PTCL will write BCN TRXRPT when BCNOK/BCNERR INT. + //RTL_W8(0x420, RTL_R8(0x420)&(~BIT2)); + //RTL_W8(0x421, RTL_R8(0x421)&(~BIT5)); + + // REG_AMPDU_MAX_LENGTH 256K + //RTL_W32(0x458,0x3FFFF); + + // RESERVED + //RTL_W32(0x460,0x3FFFF); + + // REG_SW_AMPDU_BURST_MODE_CTRL + //RTL_W8(0x4BC, RTL_R8(0x4BC)| 0x3F); + + // Enable single sub-frame APMDU. + //RTL_W8(0x4C7, RTL_R8(0x4C7)|BIT7); + + // REG_PROT_MODE_CTRL ????? + //RTL_W32(0x4c8,0x003F0800); + + // RESERVED + //RTL_W8(0x4E3, RTL_R8(0x4e3)& (~BIT5)); + + // REG_SIFS, sync with 8814 NIC driver + //RTL_W32(0x514,0x0E100E10); + + // If txd fifo underflow when txtype is cmpba, reset mactx state machine ,bit14 + // If txd fifo underflow, reset mactx state machine , bit 13 + // Phytxend_ps comes but mactx still active, reset mactx state machine ,bit12 + //RTL_W32(0x604,RTL_R32(0x604)& (~(BIT12|BIT13|BIT14))); + + // REG_MAC_SPEC_SIFS (Specification SIFS Register) sync error setting with RS driver + //RTL_W16(0x63a,0x0e10); + + // REG_UDF_THSD + //RTL_W32(0x630,RTL_R32(0x630)|BIT19); + + // REG_RESP_SIFS_CCK (Response SIFS for CCK Register) + // REG_RESP_SIFS_OFDM (Response SIFS for OFDM Register) + //RTL_W32(0x63C, 0x0E0E1010); + + // temp add init CPU fw initialize ready, set by CPU + // RTL_W32(0x80,RTL_R32(0x80)|BIT15); + + // set CRC5 buffer addr + //RTL_W32(0x6bc, 0x03000000); // set CRC5 buffer addr + + // set + //RTL_W32(0x7d4,RTL_R32(0x7D4)|BIT17); // set CRC5 buffer addr + } + #endif //#ifdef RTL8814_FPGA_TEMP + } +#endif //CONFIG_WLAN_HAL_8814AE + } +#if 0 // defined(UNIVERSAL_REPEATER) || defined(MBSSID) + else { + if (get_rf_mimo_mode(priv) == MIMO_1T1R) + GET_MIB(priv)->dot11nConfigEntry.dot11nSupportedMCS &= 0x00ff; + } +#endif + +#ifdef SDIO_2_PORT + if (IS_VXD_INTERFACE(priv)) { + unsigned int reg; + + reg = *(unsigned int *)(dev->dev_addr); + RTL_W32(MACID1, (cpu_to_le32(reg))); + reg = *(unsigned short *)((unsigned long)dev->dev_addr + 4); + RTL_W16(MACID1+4, (cpu_to_le16(reg))); +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + rtl8192cd_set_mbidcam(priv, GET_MY_HWADDR, 7); +#endif + } +#endif + +#ifdef HW_FILL_MACID + if(GET_CHIP_VER(priv)==VERSION_8814A) { + GET_HAL_INTERFACE(priv)->InitMACIDSearchHandler(priv); + } +#endif //#ifdef HW_FILL_MACID + + + +#ifdef MBSSID + if ((OPMODE & WIFI_AP_STATE) && (GET_ROOT(priv)->pmib->miscEntry.vap_enable)) { + + if (IS_ROOT_INTERFACE(priv)) + { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + RTL_W32(TBTT_PROHIBIT, 0x40004); + else +#endif + if(priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod <= 40) + RTL_W32(TBTT_PROHIBIT, 0x1df04); + else + RTL_W32(TBTT_PROHIBIT, 0x40004); + + } + else if(IS_VAP_INTERFACE(priv)) + { + RTL_W32(TBTT_PROHIBIT, 0x1df04); //vap interfacef really opened, set TBTT for MBSSID function + } + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->InitMBSSIDHandler(priv); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + rtl8192cd_init_mbssid(priv); + + if (IS_VAP_INTERFACE(priv)) { +#ifdef CONFIG_PCI_HCI + // set BcnDmaInt & BcnOk of different VAP in IMR +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->InitVAPIMRHandler(priv, priv->vap_init_seq); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + priv->pshare->InterruptMaskExt |= (HIMRE_88E_BCNDMAINT1 << (priv->vap_init_seq-1)); + RTL_W32(REG_88E_HIMRE, priv->pshare->InterruptMaskExt); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E){ + priv->pshare->InterruptMaskExt |= (HIMRE_92E_BCNDMAINT1 << (priv->vap_init_seq-1)); + RTL_W32(REG_HIMR1_8812, priv->pshare->InterruptMaskExt); + } else +#endif + { + priv->pshare->InterruptMask |= (HIMR_BCNDMA1 << (priv->vap_init_seq-1)); + RTL_W32(HIMR, priv->pshare->InterruptMask); + } + } +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI +#ifdef CONFIG_RTL_88E_SUPPORT +#if defined(CONFIG_SUPPORT_USB_INT) && defined(CONFIG_INTERRUPT_BASED_TXBCN) + priv->pshare->InterruptMaskExt |= (HIMRE_88E_BCNDMAINT1 << (priv->vap_init_seq-1)); + RTL_W32(REG_88E_HIMRE, priv->pshare->InterruptMaskExt); +#endif +#endif // CONFIG_RTL_88E_SUPPORT +#endif // CONFIG_USB_HCI + + if (GET_ROOT(priv)->auto_channel == 0) { + priv->pmib->dot11RFEntry.dot11channel = GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel; + priv->ht_cap_len = 0; // re-construct HT IE + + init_beacon(priv); + } + } + +#if defined(RTK_NL80211) && defined(CONFIG_PCI_HCI) + if(IS_ROOT_INTERFACE(priv)) + { + //for performance + //panic_printk("\n FORCE ROOT VAP_ENABLE=0 !! \n\n"); + priv->pmib->miscEntry.vap_enable = 0; + } +#endif + } + else if (IS_VAP_INTERFACE(priv) && (OPMODE & WIFI_STATION_STATE)) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->InitMBIDCAMHandler(priv); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + ; //ToDo + } +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if(IS_ROOT_INTERFACE(priv)) +#endif //defined(UNIVERSAL_REPEATER) || defined(MBSSID) + { +#if defined(CONFIG_WLAN_HAL) && defined(CONFIG_PCI_HCI) + if (IS_HAL_CHIP(priv)) { + u1Byte HIQ_En=0; + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HIQ_En); + HIQ_En = HIQ_En | BIT0; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HIQ_En); + } +#endif + } + + +// new added to reset keep_rsnie flag + if (priv->pmib->dot11OperationEntry.keep_rsnie) + priv->pmib->dot11OperationEntry.keep_rsnie = 0; +//------------------- david+2006-06-30 + +priv->drv_state |= DRV_STATE_OPEN; // set driver as has been opened, david + + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { +#ifdef CONFIG_PCI_HCI + GET_HAL_INTERFACE(priv)->EnableIMRHandler(priv); +#endif + } +#endif + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + recalc_txdesc_limit(priv); +#endif + + //memcpy((void *)dev->dev_addr, priv->pmib->dot11OperationEntry.hwaddr, 6); + + // below is for site_survey timer + init_timer(&priv->ss_timer); +#if defined(CONFIG_PCI_HCI) + priv->ss_timer.data = (unsigned long) priv; + priv->ss_timer.function = rtl8192cd_ss_timer; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + priv->ss_timer.data = (unsigned long) &priv->ss_timer_event; + priv->ss_timer.function = timer_event_timer_fn; + INIT_TIMER_EVENT_ENTRY(&priv->ss_timer_event,rtl8192cd_ss_timer, (unsigned long)priv); +#endif + + +#ifdef P2P_SUPPORT + init_timer(&priv->p2p_listen_timer_t); + init_timer(&priv->p2p_search_timer_t); + priv->p2p_search_timer_t.data = (unsigned long) priv; + priv->p2p_search_timer_t.function = p2p_search_timer; + priv->p2p_listen_timer_t.data = (unsigned long) priv; + priv->p2p_listen_timer_t.function = P2P_listen_timer; +#endif +#ifdef CONFIG_RTL_COMAPI_WLTOOLS + init_waitqueue_head(&priv->ss_wait); +#endif + +#ifdef CLIENT_MODE + init_timer(&priv->reauth_timer); +#if defined(CONFIG_PCI_HCI) + priv->reauth_timer.data = (unsigned long) priv; + priv->reauth_timer.function = rtl8192cd_reauth_timer; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + priv->reauth_timer.data = (unsigned long) &priv->reauth_timer_event; + priv->reauth_timer.function = timer_event_timer_fn; + INIT_TIMER_EVENT_ENTRY(&priv->reauth_timer_event, rtl8192cd_reauth_timer, (unsigned long)priv); +#endif + + init_timer(&priv->reassoc_timer); +#if defined(CONFIG_PCI_HCI) + priv->reassoc_timer.data = (unsigned long) priv; + priv->reassoc_timer.function = rtl8192cd_reassoc_timer; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + priv->reassoc_timer.data = (unsigned long) &priv->reassoc_timer_event; + priv->reassoc_timer.function = timer_event_timer_fn; + INIT_TIMER_EVENT_ENTRY(&priv->reassoc_timer_event, rtl8192cd_reassoc_timer, (unsigned long)priv); +#endif + + init_timer(&priv->idle_timer); +#if defined(CONFIG_PCI_HCI) + priv->idle_timer.data = (unsigned long) priv; + priv->idle_timer.function = rtl8192cd_idle_timer; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + priv->idle_timer.data = (unsigned long) &priv->idle_timer_event; + priv->idle_timer.function = timer_event_timer_fn; + INIT_TIMER_EVENT_ENTRY(&priv->idle_timer_event, rtl8192cd_idle_timer, (unsigned long)priv); +#endif +#ifdef DFS + init_timer(&priv->dfs_cntdwn_timer); + priv->dfs_cntdwn_timer.data = (unsigned long) priv; + priv->dfs_cntdwn_timer.function = rtl8192cd_dfs_cntdwn_timer; +#endif +#endif + +#ifdef MULTI_MAC_CLONE + for (i=0; ipshare->mclone_sta[i].isTimerInit == 0) {// if it is used, do not re-init + priv->pshare->mclone_sta[i].timer_data.priv = GET_ROOT(priv); + priv->pshare->mclone_sta[i].timer_data.active_id = i+1; + + init_timer(&priv->pshare->mclone_sta[i].reauth_timer); + priv->pshare->mclone_sta[i].reauth_timer.data = (unsigned long)&priv->pshare->mclone_sta[i].timer_data; + priv->pshare->mclone_sta[i].reauth_timer.function = rtl8192cd_mclone_reauth_timer; + + init_timer(&priv->pshare->mclone_sta[i].reassoc_timer); + priv->pshare->mclone_sta[i].reassoc_timer.data = (unsigned long)&priv->pshare->mclone_sta[i].timer_data; + priv->pshare->mclone_sta[i].reassoc_timer.function = rtl8192cd_mclone_reassoc_timer; + priv->pshare->mclone_sta[i].isTimerInit = 1; + } + } +#endif + + priv->frag_to = 0; + + init_timer(&priv->frag_to_filter); + priv->frag_to_filter.data = (unsigned long) priv; + priv->frag_to_filter.function = rtl8192cd_frag_timer; + + mod_timer(&priv->frag_to_filter, jiffies + FRAG_TO); + + priv->auth_to = AUTH_TO / HZ; + priv->assoc_to = ASSOC_TO / HZ; +#ifdef MULTI_MAC_CLONE + priv->repeater_to = REPEATER_TO / HZ; +#endif + +#ifdef PCIE_POWER_SAVING_DEBUG + priv->expire_to = 60; +#else + priv->expire_to = (EXPIRETIME > 100)? (EXPIRETIME / 100) : 86400; /*10ms to 1s*/ +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#if defined(DETECT_STA_EXISTANCE) && (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + priv->pshare->bRLShortened = FALSE; +#endif + +#if defined(PCIE_POWER_SAVING) || defined(RF_MIMO_SWITCH) + init_timer(&priv->ps_timer); + priv->ps_timer.data = (unsigned long) priv; +#if defined(PCIE_POWER_SAVING) + priv->ps_timer.function = PCIe_power_save_timer; +#else + priv->ps_timer.function = RF_MIMO_check_timer; +#endif + + mod_timer(&priv->ps_timer, jiffies + POWER_DOWN_T0); +// priv->ps_ctrl = 0x11; +#endif + +#ifdef SDIO_AP_OFFLOAD + init_timer(&priv->pshare->ps_timer); + priv->pshare->ps_timer.data = (unsigned long) priv; + priv->pshare->ps_timer.function = sdio_power_save_timer; +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + mod_timer(&priv->pshare->ps_timer, jiffies + POWER_DOWN_T0); +#endif + + init_timer(&priv->expire_timer); + priv->expire_timer.data = (unsigned long) priv; +#if defined(CONFIG_PCI_HCI) + priv->expire_timer.function = rtl8192cd_1sec_timer; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + priv->expire_timer.function = pre_rtl8192cd_1sec_timer; + INIT_TIMER_EVENT_ENTRY(&priv->expire_timer_event, rtl8192cd_1sec_timer, (unsigned long)priv); +#endif +#ifdef SW_ANT_SWITCH + init_timer(&priv->pshare->swAntennaSwitchTimer); + priv->pshare->swAntennaSwitchTimer.data = (unsigned long) priv; + priv->pshare->swAntennaSwitchTimer.function = dm_SW_AntennaSwitchCallback; +#endif +#ifdef BEAMFORMING_SUPPORT + Beamforming_Init(priv); +#endif + + mod_timer(&priv->expire_timer, jiffies + EXPIRE_TO); + + init_timer(&priv->pshare->rc_sys_timer); + priv->pshare->rc_sys_timer.data = (unsigned long) priv; + priv->pshare->rc_sys_timer.function = reorder_ctrl_timeout; + + priv->pshare->rc_timer_tick = priv->pmib->reorderCtrlEntry.ReorderCtrlTimeout / RTL_JIFFIES_TO_MICROSECOND; + if (priv->pshare->rc_timer_tick == 0) + priv->pshare->rc_timer_tick = 1; + +#ifndef USE_OUT_SRC + #ifdef TPT_THREAD + kTPT_task_init(priv); + #endif +#endif + +#if 0 + init_timer(&priv->pshare->phw->tpt_timer); + priv->pshare->phw->tpt_timer.data = (unsigned long)priv; + priv->pshare->phw->tpt_timer.function = rtl8192cd_tpt_timer; +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(DPK_92D) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + init_timer(&priv->pshare->DPKTimer); + priv->pshare->DPKTimer.data = (unsigned long) priv; + priv->pshare->DPKTimer.function = rtl8192cd_DPK_timer; + } +#endif + + } + +#ifdef AUTO_CHANNEL_TIMEOUT + if (IS_ROOT_INTERFACE(priv) && priv->pmib->miscEntry.autoch_timeout) { + priv->pshare->autoch_timeout_count = 0; + } +#endif + + // for MIC check + init_timer(&priv->MIC_check_timer); + priv->MIC_check_timer.data = (unsigned long) priv; + priv->MIC_check_timer.function = DOT11_Process_MIC_Timerup; + init_timer(&priv->assoc_reject_timer); + priv->assoc_reject_timer.data = (unsigned long) priv; + priv->assoc_reject_timer.function = DOT11_Process_Reject_Assoc_Timerup; + + priv->MIC_timer_on = FALSE; + priv->assoc_reject_on = FALSE; + +#ifdef GBWC + init_timer(&priv->GBWC_timer); + priv->GBWC_timer.data = (unsigned long) priv; + priv->GBWC_timer.function = rtl8192cd_GBWC_timer; + + if (priv->pmib->gbwcEntry.GBWCMode != GBWC_MODE_DISABLE) + mod_timer(&priv->GBWC_timer, jiffies + GBWC_TO); +#endif + +#ifdef CONFIG_PCI_HCI + // to avoid add RAtid fail +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + init_timer(&priv->add_RATid_timer); + priv->add_RATid_timer.data = (unsigned long) priv; + priv->add_RATid_timer.function = add_RATid_timer; + + init_timer(&priv->add_rssi_timer); + priv->add_rssi_timer.data = (unsigned long) priv; + priv->add_rssi_timer.function = add_rssi_timer; +#endif + init_timer(&priv->add_ps_timer); + priv->add_ps_timer.data = (unsigned long) priv; + priv->add_ps_timer.function = add_ps_timer; +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + init_timer(&priv->dnc_timer); + priv->dnc_timer.data = (unsigned long) priv; + priv->dnc_timer.function = dnc_timer; + } +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) + init_timer(&priv->pshare->MP_DIGTimer); + priv->pshare->MP_DIGTimer.data = (unsigned long) priv; + priv->pshare->MP_DIGTimer.function = MP_DIG_process; +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + // for HW/SW LED + if ((LED_TYPE >= LEDTYPE_HW_TX_RX) && (LED_TYPE <= LEDTYPE_HW_LINKACT_INFRA)) + enable_hw_LED(priv, LED_TYPE); + else if ((LED_TYPE >= LEDTYPE_SW_LINK_TXRX) && (LED_TYPE < LEDTYPE_SW_MAX)) { + if (LED_TYPE == LEDTYPE_SW_RESERVED) + LED_TYPE = LEDTYPE_SW_LED2_GPIO10_LINKTXRX_92D; + + if ((LED_TYPE == LEDTYPE_SW_LINK_TXRX) || + (LED_TYPE <= LEDTYPE_SW_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO8_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX) || + (LED_TYPE == LEDTYPE_SW_LED1_GPIO9_LINKTXRX_92D) || + (LED_TYPE == LEDTYPE_SW_LED2_GPIO10_LINKTXRX_92D)) + priv->pshare->LED_cnt_mgn_pkt = 1; + + enable_sw_LED(priv, 1); + } + +#ifdef CONFIG_RTL_ULINKER + { + extern void enable_sys_LED(struct rtl8192cd_priv *priv); + enable_sys_LED(priv); + } +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { +#ifdef SW_ANT_SWITCH + dm_SW_AntennaSwitchInit(priv); // SW Ant Switch use LED pin to control TRX Antenna +#endif +#if defined(HW_ANT_SWITCH)&&( defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + dm_HW_AntennaSwitchInit(priv); +#endif + } +#endif + +#if defined(DFS) && !defined(RTK_NL80211) + if (!priv->pmib->dot11DFSEntry.disable_DFS && + (OPMODE & WIFI_AP_STATE) && + (((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)) || + ((priv->pmib->dot11RFEntry.dot11channel >= 100) && + (priv->pmib->dot11RFEntry.dot11channel <= 140)))) { + + init_timer(&priv->ch_avail_chk_timer); + priv->ch_avail_chk_timer.data = (unsigned long) priv; + priv->ch_avail_chk_timer.function = rtl8192cd_ch_avail_chk_timer; + + if ((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) && + ((priv->pmib->dot11RFEntry.dot11channel >= 120) && + (priv->pmib->dot11RFEntry.dot11channel <= 132))) + mod_timer(&priv->ch_avail_chk_timer, jiffies + CH_AVAIL_CHK_TO_CE); + else + mod_timer(&priv->ch_avail_chk_timer, jiffies + CH_AVAIL_CHK_TO); + + init_timer(&priv->DFS_timer); + priv->DFS_timer.data = (unsigned long) priv; + priv->DFS_timer.function = rtl8192cd_DFS_timer; + + init_timer(&priv->DFS_TXPAUSE_timer); + priv->DFS_TXPAUSE_timer.data = (unsigned long) priv; + priv->DFS_TXPAUSE_timer.function = rtl8192cd_DFS_TXPAUSE_timer; + + /* DFS activated after 5 sec; prevent switching channel due to DFS false alarm */ + mod_timer(&priv->DFS_timer, jiffies + RTL_SECONDS_TO_JIFFIES(5)); + + init_timer(&priv->dfs_det_chk_timer); + priv->dfs_det_chk_timer.data = (unsigned long) priv; + priv->dfs_det_chk_timer.function = rtl8192cd_dfs_det_chk_timer; + + mod_timer(&priv->dfs_det_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pshare->rf_ft_var.dfs_det_period*10)); + + DFS_SetReg(priv); + + if (!priv->pmib->dot11DFSEntry.CAC_enable) { + del_timer_sync(&priv->ch_avail_chk_timer); + mod_timer(&priv->ch_avail_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(200)); + } + }else if(priv->pmib->dot11DFSEntry.disable_tx) + /* Recovery DFS disable_tx if there is no need to do DFS */ + priv->pmib->dot11DFSEntry.disable_tx = 0; +#endif + +#ifdef SUPPORT_SNMP_MIB + mib_init(priv); +#endif +#if defined(CONFIG_RTL_8196E) + if(get_96e_bonding_type() == BOND_8196ES ) + rtl_8196es_gpio_init(); +#endif +// priv->pshare->current_rsp_rate = 0; + } + + +#if defined(BR_SHORTCUT) && defined(RTL_CACHED_BR_STA) + { + memset(brsc_cache_arr,0,sizeof(struct brsc_cache_t)*MAX_BRSC_NUM); + } +#endif + + //if (OPMODE & WIFI_AP_STATE) //in case of station mode, queue will start only after assoc. +#if defined(CONFIG_PCI_HCI) || !defined(CONFIG_NETDEV_MULTI_TX_QUEUE) + netif_start_queue(dev); // start queue always +#else + netif_tx_start_all_queues(dev); +#endif + +#ifdef WDS + create_wds_tbl(priv); +#endif + +#ifdef CHECK_HANGUP + if (priv->reset_hangup) + priv->reset_hangup = 0; +#endif + +#if defined(INCLUDE_WPA_PSK) && defined(CLIENT_MODE) + if (OPMODE & WIFI_ADHOC_STATE) + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) + ToDrv_SetGTK(priv); +#endif + +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) +#endif + if ((OPMODE & WIFI_AP_STATE) && priv->auto_channel) { + if (((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _TKIP_PRIVACY_) && + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _CCMP_PRIVACY_) && + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_WPA_MIXED_PRIVACY_)) || + (priv->pmib->dot11RsnIE.rsnielen > 0)) { + priv->ss_ssidlen = 0; + DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=0\n", (char *)__FUNCTION__); +#ifdef CONFIG_RTL8672 + OPMODE_VAL(OPMODE | WIFI_WAIT_FOR_CHANNEL_SELECT); +#endif + start_clnt_ss(priv); + } + } + +#ifdef CLIENT_MODE + if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) { + struct net_bridge_port *br_port; + +#ifdef RTK_BR_EXT +#ifdef __ECOS + memcpy(priv->br_mac, GET_MY_HWADDR, MACADDRLEN); +#else + br_port = GET_BR_PORT(priv->dev); + + if (br_port) { +#ifdef __LINUX_2_6__ + memcpy(priv->br_mac, br_port->br->dev->dev_addr, MACADDRLEN); +#else + memcpy(priv->br_mac, priv->dev->br_port->br->dev.dev_addr, MACADDRLEN); +#endif + } +#endif +#endif +#ifdef MBSSID + if (IS_VAP_INTERFACE(priv)) { + if(OPMODE == WIFI_STATION_STATE) { + if(priv->vap_id==1){ + STADEBUG("open ,start ss_timer\n"); + mod_timer(&priv->ss_timer, jiffies + RTL_SECONDS_TO_JIFFIES(5)); + }else if(priv->vap_id==2){ + STADEBUG("open ,start ss_timer\n"); + mod_timer(&priv->ss_timer, jiffies + RTL_SECONDS_TO_JIFFIES(15)); + } + } + }else +#endif +#if defined(SMART_REPEATER_MODE) && !defined(RTK_NL80211) +// if (IS_VXD_INTERFACE(priv) && !GET_ROOT_PRIV(priv)->pmib->miscEntry.func_off) + if (IS_VXD_INTERFACE(priv)) + { + if (OPMODE == WIFI_STATION_STATE) { + #if 0 //def DFS + if (GET_ROOT(priv)->pmib->dot11DFSEntry.CAC_enable && (timer_pending(&GET_ROOT(priv)->ch_avail_chk_timer) || + ((GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel == 0) && + (GET_ROOT(priv)->pmib->dot11RFEntry.band5GSelected & PHY_BAND_5G_1) == 0))) { + if ((GET_ROOT(priv)->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) && + ((GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel >= 120) && + (GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel <= 132))) + #if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(priv->pmib->dot11StationConfigEntry.sc_enabled && priv->simple_config_status>0) + { + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(1500)); + } + else + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(5000) + CH_AVAIL_CHK_TO_CE); +#else + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(5000) + CH_AVAIL_CHK_TO_CE); +#endif + else + #if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(priv->pmib->dot11StationConfigEntry.sc_enabled && priv->simple_config_status>0) + { + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(1500)); + } + else + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(5000) + CH_AVAIL_CHK_TO); +#else + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(5000) + CH_AVAIL_CHK_TO); +#endif + } + else +#endif + { +#ifdef CONFIG_RTK_MESH + if(netif_running(GET_ROOT(priv)->dev) && + GET_ROOT(priv)->pmib->dot1180211sInfo.mesh_enable && GET_ROOT(priv)->auto_channel) + { /*if mesh is doing auto channel scanning, delay 15 sec*/ + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(15000)); + } + else +#endif + { + #if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(priv->pmib->dot11StationConfigEntry.sc_enabled && priv->simple_config_status>0) + { + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(1500)); + } + else + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(5000)); +#else + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(5000)); +#endif + } + } + } + } else +#endif + { + /*pure client mode*/ + if (!IEEE8021X_FUN || (IEEE8021X_FUN && (priv->pmib->dot11RsnIE.rsnielen > 0))) { +#ifdef CHECK_HANGUP + if (!is_reset || JOIN_RES == STATE_Sta_No_Bss || + JOIN_RES == STATE_Sta_Roaming_Scan || JOIN_RES == 0) +#endif + { +#ifdef CHECK_HANGUP + if (is_reset) + OPMODE_VAL(OPMODE & ~WIFI_SITE_MONITOR); +#endif + +#if !defined(WIFI_WPAS_CLI) && !defined(RTK_NL80211) + start_clnt_lookup(priv, RESCAN); +#endif + } + } + } + } +#endif + + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) && defined(UNIVERSAL_REPEATER) // wrt-adhoc + if (IS_VXD_INTERFACE(priv) && (OPMODE & WIFI_ADHOC_STATE)) + { +#ifdef __ECOS + init_timer(&priv->pshare->vxd_ibss_beacon, (unsigned long)priv, issue_beacon_ibss_vxd); +#else + init_timer(&priv->pshare->vxd_ibss_beacon); + priv->pshare->vxd_ibss_beacon.data = (unsigned long) priv; + priv->pshare->vxd_ibss_beacon.function = issue_beacon_ibss_vxd; +#endif + //mod_timer(&priv->pshare->vxd_ibss_beacon, jiffies + RTL_MILISECONDS_TO_JIFFIES(5000)); + } +#endif + +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv) && +#ifdef __ECOS + GET_VXD_PRIV(priv) && +#endif + netif_running(GET_VXD_PRIV(priv)->dev)) { + SAVE_INT_AND_CLI(x); + rtl8192cd_open(GET_VXD_PRIV(priv)->dev); + RESTORE_INT(x); + } + if (IS_VXD_INTERFACE(priv) && + (GET_ROOT(priv)->pmib->dot11OperationEntry.opmode&WIFI_STATION_STATE) && + (GET_ROOT(priv)->pmib->dot11OperationEntry.opmode&WIFI_ASOC_STATE) && +#ifdef RTK_BR_EXT + !(GET_ROOT(priv)->pmib->ethBrExtInfo.macclone_enable && !priv->macclone_completed) && +#endif + !(priv->drv_state & DRV_STATE_VXD_AP_STARTED) ) + enable_vxd_ap(priv); +#endif + +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) { +#if !defined(RTK_NL80211) || defined(NON_NL80211_AP) + if (priv->pmib->miscEntry.vap_enable) +#endif + { + for (i=0; ipvap_priv[i]->dev)) + rtl8192cd_open(priv->pvap_priv[i]->dev); + } + } + } +#endif + +#ifdef PCIE_POWER_SAVING +#ifdef CHECK_HANGUP + if(!is_reset) +#endif +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) || defined(CONFIG_RTL8672) + if (1) +#else + if (REG32(REVR) == RTL8196C_REVISION_B) +#endif + init_pcie_power_saving(priv); + else + priv->pshare->rf_ft_var.power_save = 0; + } +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { + Check_92E_Spur_Valid(priv, false); + } +#endif + } +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef CONFIG_USB_HCI + rtl8192cu_inirp_init(priv); +#endif + +#ifdef CONFIG_SDIO_HCI +#ifdef EN_EFUSE + rtw_bb_rf_gain_offset(priv); +#endif + EnableSdioInterrupt(priv); +#endif + } + +#if 0 //defined(MULTI_MAC_CLONE) + if (netif_running(GET_ROOT(priv)->pvxd_priv->dev) && (GET_ROOT(priv)->pvxd_priv->drv_state&DRV_STATE_VXD_INIT)) { + priv->pshare->root_repeater = GET_ROOT(priv)->pvxd_priv; + } + else { + for (i=0; ipvap_priv[i]!=NULL && + (GET_ROOT(priv)->pvap_priv[i]->pmib->dot11OperationEntry.opmode&WIFI_STATION_STATE) && + netif_running(GET_ROOT(priv)->pvap_priv[i]->dev)) { + priv->pshare->root_repeater = GET_ROOT(priv)->pvap_priv[i]; + break; + } + priv->pshare->root_repeater = NULL; + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if(!strcmp(priv->dev->name,"wlan0") || !strcmp(priv->dev->name,"wlan0-va1") || !strcmp(priv->dev->name,"wlan0-vxd")){ + priv->reperater_idx=1; + #if defined(BR_SHORTCUT) && defined(CLIENT_MODE) + if (OPMODE & WIFI_STATION_STATE) { + cached_sta_dev[0] = NULL; + } + #endif + }else if(!strcmp(priv->dev->name,"wlan0-va0") || !strcmp(priv->dev->name,"wlan0-va2")){ + priv->reperater_idx=2; + #if defined(BR_SHORTCUT) && defined(CLIENT_MODE) + if (OPMODE & WIFI_STATION_STATE) { + cached_sta_dev[1] = NULL; + } + #endif + } +#endif + +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + rtk_sc_init(priv); +#endif +#ifdef SDIO_AP_OFFLOAD +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (!IS_ROOT_INTERFACE(priv)) { + ap_offload_activate(priv, OFFLOAD_PROHIBIT_DEV_OPS); + } else +#endif + { +#ifdef USE_WAKELOCK_MECHANISM + rtw_lock_suspend_timeout(priv, 2000); +#endif + } +#endif // SDIO_AP_OFFLOAD + + DBFEXIT; + + return 0; + +free_res: + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + rtw_dev_unload(priv); + + if (timer_pending(&priv->pshare->xmit_check_timer)) + del_timer_sync(&priv->pshare->xmit_check_timer); +#endif +#ifdef CONFIG_USB_HCI +#if defined(CONFIG_RTL_92C_SUPPORT) || (!defined(CONFIG_SUPPORT_USB_INT) || !defined(CONFIG_INTERRUPT_BASED_TXBCN)) + if (timer_pending(&priv->pshare->beacon_timer)) + del_timer_sync(&priv->pshare->beacon_timer); +#endif +#endif // CONFIG_USB_HCI +#ifdef CONFIG_SDIO_HCI + if (timer_pending(&priv->pshare->beacon_timer)) + del_timer_sync(&priv->pshare->beacon_timer); +#endif +#ifdef USE_OUT_SRC + ODM_StopAllThreads(ODMPTR); +#endif + } + +#ifdef SDIO_AP_OFFLOAD +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (!IS_ROOT_INTERFACE(priv)) { + ap_offload_activate(priv, OFFLOAD_PROHIBIT_DEV_OPS); + } else +#endif + { + // Notice. disable "unlock suspend" to avoid card missing issue in Sequans platform +#ifdef USE_WAKELOCK_MECHANISM + rtw_unlock_suspend(priv); +#endif + } +#endif // SDIO_AP_OFFLOAD + + return rc; +} + + +int rtl8192cd_set_hwaddr(struct net_device *dev, void *addr) +{ + unsigned long flags = 0; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + unsigned int reg; + unsigned char *p; +#ifdef WDS + int i; +#endif +#ifdef CONFIG_WLAN_HAL + BOOLEAN bVal; +#endif //CONFIG_WLAN_HAL + + +#ifdef __KERNEL__ + p = ((struct sockaddr *)addr)->sa_data; +#else + p = (unsigned char *)addr; +#endif + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + +#ifdef MULTI_MAC_CLONE + ACTIVE_ID = 0; +#endif + + memcpy(priv->dev->dev_addr, p, 6); + memcpy(GET_MY_HWADDR, p, 6); +#if defined(RTK_NL80211) + //brian, for setup MAC address from calibration at flash only during system initialization +#ifdef NON_NL80211_AP + if(IS_VXD_INTERFACE(priv) && !IS_DRV_OPEN(priv)) +#else + if(IS_ROOT_INTERFACE(priv) && !IS_DRV_OPEN(priv)) +#endif + { + memcpy(priv->rtk->root_mac, p, MACADDRLEN); + memcpy(priv->rtk->wiphy->perm_addr, p, MACADDRLEN); + } +#endif +#ifndef __ECOS + memset(dev->broadcast, 0xff, ETH_ALEN); +#endif +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + if (IS_VAP_INTERFACE(priv)) { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return 0; + } + } +#endif + +#ifdef WDS + for (i=0; iwds_dev[i]) + memcpy(priv->wds_dev[i]->dev_addr, p, 6); +#endif +#ifdef CONFIG_RTK_MESH + if(NUM_MESH>0) + if (priv->mesh_dev) + memcpy(priv->mesh_dev->dev_addr, p, 6); +#endif + +#ifdef SDIO_AP_OFFLOAD + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_DEV_OPS); +#endif + +#ifdef UNIVERSAL_REPEATER +#ifdef SDIO_2_PORT + if (IS_VXD_INTERFACE(priv)) { + reg = *(unsigned int *)(dev->dev_addr); + RTL_W32(MACID1, (cpu_to_le32(reg))); + reg = *(unsigned short *)((unsigned long)dev->dev_addr + 4); + RTL_W16(MACID1+4, (cpu_to_le16(reg))); + + goto out; + } +#else // !SDIO_2_PORT + if (IS_ROOT_INTERFACE(priv)) { + if (GET_VXD_PRIV(priv)) { + memcpy(GET_VXD_PRIV(priv)->dev->dev_addr, p, 6); + memcpy(GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.hwaddr, p, 6); + } + } + else if (IS_VXD_INTERFACE(priv)) { + memcpy(GET_ROOT(priv)->dev->dev_addr, p, 6); + memcpy(GET_ROOT(priv)->pmib->dot11OperationEntry.hwaddr, p, 6); + } +#endif // SDIO_2_PORT +#endif // UNIVERSAL_REPEATER + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_MAC_IO_ENABLE, (pu1Byte)&bVal); + if ( bVal ) { + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_ETHER_ADDR, (pu1Byte)p); + } + else { +// printk("%s(%d): Can't write MACID register\n", __FUNCTION__, __LINE__); + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + if (check_MAC_IO_Enable(priv)) { + reg = *(unsigned int *)(dev->dev_addr); + RTL_W32(MACID, (cpu_to_le32(reg))); + reg = *(unsigned short *)((unsigned long)dev->dev_addr + 4); + RTL_W16(MACID+4, (cpu_to_le16(reg))); + #ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + RTL_W32(MACID1 , RTL_R32(MACID)); + RTL_W16(MACID1+4, RTL_R16(MACID+4)); + } + #endif + } + } +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + if (OPMODE & WIFI_AP_STATE) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if ( bVal ) + GET_HAL_INTERFACE(priv)->InitMBSSIDHandler(priv); + } + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + rtl8192cd_init_mbssid(priv); + + } + else if (IS_VAP_INTERFACE(priv) && (OPMODE & WIFI_STATION_STATE)) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if ( bVal ) + GET_HAL_INTERFACE(priv)->InitMBIDCAMHandler(priv); + } + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + ; //ToDo + } + } +#endif + +out: + RESTORE_INT(flags); + SMP_UNLOCK(flags); + +#ifndef WIFI_WPAS_CLI +#ifdef CLIENT_MODE + if (!(OPMODE & WIFI_AP_STATE) && netif_running(priv->dev)) { + int link_status = chklink_wkstaQ(priv); + if (link_status) { +#ifdef MULTI_MAC_CLONE + OPMODE_VAL(WIFI_STATION_STATE); + JOIN_RES_VAL(STATE_Sta_No_Bss); + start_clnt_auth(priv); +#else + start_clnt_join(priv); +#endif + } + } +#endif +#endif + +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_DEV_OPS); +#endif + + return 0; +} + + +int rtl8192cd_close(struct net_device *dev) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); +#ifdef UNIVERSAL_REPEATER + struct rtl8192cd_priv *priv_vxd; +#endif +#ifdef CONFIG_WLAN_HAL + unsigned int errorFlag=0; +#endif + unsigned long flags=0; + + int i; + +#ifdef RTK_NL80211 +#if defined(MBSSID) || defined(UNIVERSAL_REPEATER) + #if 0 //prevent drop vxd, vap connection + if(IS_ROOT_INTERFACE(priv)) + close_vxd_vap(priv); + #endif + + if(is_WRT_scan_iface(dev->name)) + { + printk("No need to call close for scan iface !!\n"); + return 0; + } +#endif + +#ifdef DFS + if (priv->wdev.cac_started) + event_indicate_cfg80211(priv, NULL, CFG80211_RADAR_CAC_ABORTED, NULL); +#endif + + if (priv->scan_req +#ifdef USE_OUT_SRC + || (priv->pshare->bScanInProcess == TRUE) +#endif + ) + { + event_indicate_cfg80211(priv, NULL, CFG80211_SCAN_ABORTED, NULL); + } +#endif + + STADEBUG("===>\n"); + SMP_LOCK(flags); + DBFENTER; + +#if defined(WDS) || defined(CONFIG_RTK_MESH) + if(dev->base_addr != 0 && dev->base_addr != 1) +#endif + { + if (!(priv->drv_state & DRV_STATE_OPEN)) + { + DBFEXIT; + SMP_UNLOCK(flags); + return 0; + } + } + + SAVE_INT_AND_CLI(flags); + +#ifdef MULTI_MAC_CLONE + ACTIVE_ID = 0; +#endif + +#if defined(WDS) || defined(CONFIG_RTK_MESH) + if(dev->base_addr != 0 && dev->base_addr != 1) +#endif + priv->drv_state &= ~DRV_STATE_OPEN; // set driver as has been closed, david + +#if defined(PCIE_POWER_SAVING) || defined(RF_MIMO_SWITCH) + if (timer_pending(&priv->ps_timer)) { + SMP_UNLOCK(flags); + del_timer_sync(&priv->ps_timer); + SMP_LOCK(flags); + } +#endif +#ifdef PCIE_POWER_SAVING + if((priv->pwr_state == L1) || (priv->pwr_state == L2)) { + PCIeWakeUp(priv, (POWER_DOWN_T0<<3)); + } +#endif + +#ifdef SDIO_AP_OFFLOAD +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (!IS_ROOT_INTERFACE(priv)) { + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_DEV_OPS); + } else +#endif +#ifdef WDS + if (dev->base_addr) +#endif + { +#ifdef CONFIG_POWER_SAVE + rtw_lock_suspend(priv); +#endif + del_timer_sync(&priv->pshare->ps_timer); + + if (RTW_STS_SUSPEND == priv->pshare->pwr_state) + ap_offload_exit(priv); + } +#endif // SDIO_AP_OFFLOAD + +#ifdef RTK_NL80211//survey_dump + /* + priv->rtk->tx_time = 0; + priv->rtk->rx_time = 0; + priv->rtk->chbusytime = 0; + */ + memset(priv->rtk->survey_info, 0x0, ARRAY_SIZE(realtek_5ghz_a_channels)); + memset(priv->rtk->psd_fft_info, 0x0, sizeof(priv->rtk->psd_fft_info)); +#endif + +#ifdef HS2_SUPPORT +/* Hotspot 2.0 Release 1 */ + if (timer_pending(&priv->cu_cntdwn_timer)) { + SMP_UNLOCK(flags); + del_timer_sync(&priv->cu_cntdwn_timer); + SMP_LOCK(flags); + } + //clean hs2 relative ie + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.hs2_ielen) + { + priv->pmib->hs2Entry.hs2_ielen = 0; + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.interworking_ielen) + { + priv->pmib->hs2Entry.interworking_ielen = 0; + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.advt_proto_ielen) + { + priv->pmib->hs2Entry.advt_proto_ielen = 0; + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.roam_ielen) + { + priv->pmib->hs2Entry.roam_ielen = 0; + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.timeadvt_ielen) + { + priv->pmib->hs2Entry.timeadvt_ielen = 0; + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.timezone_ielen) + { + priv->pmib->hs2Entry.timezone_ielen = 0; + } +#endif + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + recalc_txdesc_limit(priv); +#endif + +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv)) { + priv_vxd = GET_VXD_PRIV(priv); + + // if vxd interface is opened, close it first + if (IS_DRV_OPEN(priv_vxd)) { + SMP_UNLOCK(flags); + rtl8192cd_close(priv_vxd->dev); + SMP_LOCK(flags); + } + } + else { +#ifdef MBSSID +/* + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) +*/ + if (priv->vap_id < 0) +#endif + { + disable_vxd_ap(priv); +#ifdef SDIO_2_PORT + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT1)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT1)); +#endif + } + } +#endif + +#if defined(CONFIG_PCI_HCI) || !defined(CONFIG_NETDEV_MULTI_TX_QUEUE) + netif_stop_queue(dev); +#else + netif_tx_stop_all_queues(dev); +#endif + +#ifdef WDS + if (dev->base_addr == 0) + { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + DBFEXIT; + return 0; + } +#endif + +#ifdef CONFIG_RTK_MESH + if (dev->base_addr == 1) + { + #if defined(RTK_MESH_AODV_STANDALONE_TIMER) + if (timer_pending(&priv->mesh_expire_timer)) + del_timer_sync(&priv->mesh_expire_timer); + #endif + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return 0; + } +#endif // CONFIG_RTK_MESH + +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif + { + if (OPMODE & WIFI_AP_STATE) { + int i; + for(i=0; ipshare->aidarray[i] && (priv->pshare->aidarray[i]->used == TRUE) +#ifdef WDS + && !(priv->pshare->aidarray[i]->station.state & WIFI_WDS) +#endif + ) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (priv != priv->pshare->aidarray[i]->priv) + continue; +#endif + issue_deauth(priv, priv->pshare->aidarray[i]->station.hwaddr, _RSON_DEAUTH_STA_LEAVING_); + } + } + + delay_ms(10); + } +#ifdef CLIENT_MODE /* WPS2DOTX */ + else if ((OPMODE & WIFI_STATION_STATE) == WIFI_STATION_STATE){ + if ((OPMODE & (WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE))==(WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE)){ + //issue_disassoc(priv,BSSID,_RSON_DEAUTH_STA_LEAVING_); + //OS_DEBUG("issue_deauth to AP\n"); + //printMac(BSSID); + issue_deauth(priv,BSSID,_RSON_DEAUTH_STA_LEAVING_); + delay_ms(50);//make sure before issue_disassoc then TX be close + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE)); + } + +#ifdef MULTI_MAC_CLONE + if (MCLONE_NUM > 0) { + for (i=0; ipshare->mclone_sta[i].priv==priv) { + printk("[%s] mclone_sta[%d]\n", __func__, i); + if ((OPMODE & (WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE))==(WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE)) { + issue_deauth(priv, BSSID, _RSON_DEAUTH_STA_LEAVING_); + delay_ms(50);//make sure before issue_disassoc then TX be close + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS|WIFI_ASOC_STATE)); + } + + #ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->McloneStopMBSSIDHandler(priv, i); + else + #endif + mclone_stop_mbssid(priv, i); + clear_Multi_Mac_Clone(priv, i); + priv->pshare->mclone_sta[i].isTimerInit = 0; + } + } + ACTIVE_ID = 0; + + if (MCLONE_NUM == 0) + priv->pshare->mclone_ok = 0; + } else { + priv->pshare->mclone_ok = 0; + } + + + #if 0 + if (netif_running(GET_ROOT(priv)->pvxd_priv->dev) && (GET_ROOT(priv)->pvxd_priv->drv_state&DRV_STATE_VXD_INIT)) { + priv->pshare->root_repeater = GET_ROOT(priv)->pvxd_priv; + } + else { + for (i=0; ipvap_priv[i]!=NULL && + (GET_ROOT(priv)->pvap_priv[i]->pmib->dot11OperationEntry.opmode&WIFI_STATION_STATE) && + netif_running(GET_ROOT(priv)->pvap_priv[i]->dev)) { + priv->pshare->root_repeater = GET_ROOT(priv)->pvap_priv[i]; + break; + } + priv->pshare->root_repeater = NULL; + } + } + #endif +#endif + } +#endif /* WPS2DOTX */ + } + +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) { + if (priv->pmib->miscEntry.vap_enable) { + SMP_UNLOCK(flags); + for (i=0; ipvap_priv[i])) + rtl8192cd_close(priv->pvap_priv[i]->dev); + } + SMP_LOCK(flags); + } + } + + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { +#ifdef SDIO_2_PORT + if (IS_VXD_INTERFACE(priv)) + rtl8192cd_clear_mbidcam(priv, 7); +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->StopMBSSIDHandler(priv); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + rtl8192cd_stop_mbssid(priv); + + } +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#if !(defined(__ECOS) && defined(CONFIG_SDIO_HCI)) +#ifdef RTK_QUE + free_rtk_queue(priv, &priv->pshare->skb_queue); +#else + free_skb_queue(priv, &priv->pshare->skb_queue); +#endif +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + rtw_dev_unload(priv); +#endif + +#if 1 //kill tasklets before stop hw +#ifdef __KERNEL__ +#ifdef DFS + /* prevent killing tasklet issue in interrupt */ + if (!priv->pmib->dot11DFSEntry.DFS_detected) +#endif + { +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif + { +#ifdef P2P_SUPPORT + if((OPMODE&WIFI_P2P_SUPPORT)) + { + + }else +#endif + { +#ifdef SMART_REPEATER_MODE + if (!priv->pshare->switch_chan_rp) +#endif + { +#ifdef CONFIG_RTL_SIMPLE_CONFIG + if(!priv->pmib->dot11StationConfigEntry.sc_enabled && ((priv->simple_config_status==0) && (IS_ROOT_INTERFACE(priv) +#ifdef UNIVERSAL_REPEATER + && (GET_VXD_PRIV(priv)->simple_config_status == 0) +#endif +))) +#endif + { +#if defined(CONFIG_PCI_HCI) + RESTORE_INT(flags); + SMP_UNLOCK(flags); + tasklet_kill(&priv->pshare->rx_tasklet); + tasklet_kill(&priv->pshare->tx_tasklet); + tasklet_kill(&priv->pshare->oneSec_tasklet); + SMP_LOCK(flags); + SAVE_INT_AND_CLI(flags); +#elif defined(__KERNEL__) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + tasklet_kill(&priv->recvpriv.recv_tasklet); + tasklet_kill(&priv->pshare->xmit_tasklet); +#endif + } + } + } + + } + } +#endif // __KERNEL__ +#endif //kill tasklets before stop hw + + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + + //Check Error Flag + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + if (errorFlag != 0x0) { + panic_printk("Error Flag: 0x%x\n", errorFlag); + } + + if (RT_STATUS_SUCCESS == GET_HAL_INTERFACE(priv)->StopHWHandler(priv)) { + printk("StopHW Succeed\n"); + } + else { + #if 0 //Filen, we can't dump event after StopHW. except dump register is at PON section + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_CLOSE_STOP_HW; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + #endif + panic_printk("StopHW Failed\n"); + } + } + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + rtl8192cd_stop_hw(priv); + } + +#ifdef __KERNEL__ +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif + { + SMP_UNLOCK(flags); + free_irq(dev->irq, dev); + SMP_LOCK(flags); +#ifdef PCIE_POWER_SAVING +#ifdef GPIO_WAKEPIN +#ifdef RTL8676_WAKE_GPIO + { + int gpio_num, irq_num; + + get_wifi_wake_pin(&gpio_num); + irq_num = gpioGetBspIRQNum(gpio_num); + REG32(BSP_GIMR) &= ~ BIT(irq_num); + + free_irq(irq_num, dev); + gpioClearISR(gpio_num); // clear GPIO interrupt status + } + #else + +#if defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) + REG32(0xb8003000) &= ~ BIT(16); // GIMR +#else + if (REG32(REVR) == RTL8196C_REVISION_B) + REG32(0xb8003000) &= ~ BIT(9); // GIMR +#endif +#if defined(__LINUX_2_6__) + free_irq(BSP_GPIO_ABCD_IRQ, dev); +#else + free_irq(1, dev); +#endif + +#endif +#endif +#endif + + } +#endif +#endif // CONFIG_PCI_HCI + + +#ifdef UNIVERSAL_REPEATER + if (GET_VXD_PRIV(priv)) + GET_VXD_PRIV(priv)->drv_state &= ~DRV_STATE_VXD_INIT; +#endif + } +#ifdef SDIO_AP_OFFLOAD + if ( IS_ROOT_INTERFACE(priv)) { +#ifdef PLATFORM_ARM_BALONG + free_irq(dev->irq, priv); + //gpio_free(rtk_wifi_wake_i); +#endif +#ifdef CONFIG_POWER_SAVE + free_wifi_wakeup_gpio(dev, priv); +#endif + } +#endif + RESTORE_INT(flags); + SMP_UNLOCK(flags); + rtl8192cd_stop_sw(priv); + SMP_LOCK(flags); + SAVE_INT_AND_CLI(flags); + +#ifdef CONFIG_WLAN_HAL_8881A + if (IS_ROOT_INTERFACE(priv) && (GET_CHIP_VER(priv)==VERSION_8881A)) { + //Disable MAC_System(BIT(0)), MAC_Lextra_Bus(BIT(1)) + REG32(0xB80000DC)= 0x00; + } +#endif //#ifdef CONFIG_WLAN_HAL_8881A + +#ifdef ENABLE_RTL_SKB_STATS + DEBUG_INFO("skb_tx_cnt =%d\n", rtl_atomic_read(&priv->rtl_tx_skb_cnt)); + DEBUG_INFO("skb_rx_cnt =%d\n", rtl_atomic_read(&priv->rtl_rx_skb_cnt)); +#endif + +#if defined(CONFIG_RTL_92D_DMDP) && defined(CHECK_HANGUP) +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) +#endif + if ((GET_CHIP_VER(priv) == VERSION_8192D) + && (priv->pshare->rf_ft_var.peerReinit) + && (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY)) + reset_dmdp_peer(priv); +#endif + + RESTORE_INT(flags); + SMP_UNLOCK(flags); + +#if 0//def CONFIG_WLAN_HAL +#if defined( MBSSID) || defined(UNIVERSAL_REPEATER) + if (IS_ROOT_INTERFACE(priv)) +#endif + if (IS_HAL_CHIP(priv)){ + GET_HAL_INTERFACE(priv)->StopSWHandler(priv); + } +#endif //CONFIG_WLAN_HAL + +#if 0 +//#ifdef PCIE_POWER_SAVING + if(!IS_UMC_A_CUT_88C(priv)) +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + HostPCIe_Close(); +#endif + +#ifdef SDIO_AP_OFFLOAD +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (!IS_ROOT_INTERFACE(priv)) + ap_offload_activate(priv, OFFLOAD_PROHIBIT_DEV_OPS); + else +#endif + { +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif + { +#ifdef USE_WAKELOCK_MECHANISM + rtw_unlock_suspend(priv); +#endif + } + } +#endif // SDIO_AP_OFFLOAD + + DBFEXIT; + return 0; +} + + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +static void MDL_DEVINIT set_mib_default(struct rtl8192cd_priv *priv) +{ + unsigned char *p; +#ifdef __KERNEL__ + struct sockaddr addr; + p = addr.sa_data; +#else + unsigned char tmpbuf[10]; + p = (unsigned char *)tmpbuf; +#endif + + priv->pmib->mib_version = MIB_VERSION; + set_mib_default_tbl(priv); + + // others that are not types of byte and int + strcpy((char *)priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, "RTL8186-default"); + priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = strlen("RTL8186-default"); + memcpy(p, "\x00\xe0\x4c\x81\x86\x86", MACADDRLEN); + +#if defined(DOT11D) || defined(DOT11H) + // set countryCode for 11d and 11h + strcpy(priv->pmib->dot11dCountry.dot11CountryString, "US"); +#endif + +#ifdef __KERNEL__ + rtl8192cd_set_hwaddr(priv->dev, (void *)&addr); +#else + rtl8192cd_set_hwaddr(priv->dev, (void *)p); +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef DFS + init_timer(&priv->ch52_timer); + priv->ch52_timer.data = (unsigned long) priv; + priv->ch52_timer.function = rtl8192cd_ch52_timer; + + init_timer(&priv->ch56_timer); + priv->ch56_timer.data = (unsigned long) priv; + priv->ch56_timer.function = rtl8192cd_ch56_timer; + + init_timer(&priv->ch60_timer); + priv->ch60_timer.data = (unsigned long) priv; + priv->ch60_timer.function = rtl8192cd_ch60_timer; + + init_timer(&priv->ch64_timer); + priv->ch64_timer.data = (unsigned long) priv; + priv->ch64_timer.function = rtl8192cd_ch64_timer; + + init_timer(&priv->ch100_timer); + priv->ch100_timer.data = (unsigned long) priv; + priv->ch100_timer.function = rtl8192cd_ch100_timer; + + init_timer(&priv->ch104_timer); + priv->ch104_timer.data = (unsigned long) priv; + priv->ch104_timer.function = rtl8192cd_ch104_timer; + + init_timer(&priv->ch108_timer); + priv->ch108_timer.data = (unsigned long) priv; + priv->ch108_timer.function = rtl8192cd_ch108_timer; + + init_timer(&priv->ch112_timer); + priv->ch112_timer.data = (unsigned long) priv; + priv->ch112_timer.function = rtl8192cd_ch112_timer; + + init_timer(&priv->ch116_timer); + priv->ch116_timer.data = (unsigned long) priv; + priv->ch116_timer.function = rtl8192cd_ch116_timer; + + init_timer(&priv->ch120_timer); + priv->ch120_timer.data = (unsigned long) priv; + priv->ch120_timer.function = rtl8192cd_ch120_timer; + + init_timer(&priv->ch124_timer); + priv->ch124_timer.data = (unsigned long) priv; + priv->ch124_timer.function = rtl8192cd_ch124_timer; + + init_timer(&priv->ch128_timer); + priv->ch128_timer.data = (unsigned long) priv; + priv->ch128_timer.function = rtl8192cd_ch128_timer; + + init_timer(&priv->ch132_timer); + priv->ch132_timer.data = (unsigned long) priv; + priv->ch132_timer.function = rtl8192cd_ch132_timer; + + init_timer(&priv->ch136_timer); + priv->ch136_timer.data = (unsigned long) priv; + priv->ch136_timer.function = rtl8192cd_ch136_timer; + + init_timer(&priv->ch140_timer); + priv->ch140_timer.data = (unsigned long) priv; + priv->ch140_timer.function = rtl8192cd_ch140_timer; + + init_timer(&priv->ch144_timer); + priv->ch144_timer.data = (unsigned long) priv; + priv->ch144_timer.function = rtl8192cd_ch144_timer; +#endif + + if (((priv->pshare->type>>TYPE_SHIFT) & TYPE_MASK) == TYPE_EMBEDDED) { + // not implement yet + } else { +#ifdef IO_MAPPING + priv->pshare->io_mapping = 1; +#endif + } +#ifdef CONFIG_POWER_SAVE + if (priv->pmib->dot11OperationEntry.ps_level == 0) + priv->pshare->offload_prohibited |= OFFLOAD_PROHIBIT_USER; +#endif + } + +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pshare->version_id == VERSION_8192D) { +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) + priv->pshare->rf_ft_var.use_ext_lna = 0; +#endif + } +#endif + +#ifdef HIGH_POWER_EXT_PA + +#if defined(CONFIG_USE_PCIE_SLOT_1) && defined(CONFIG_USE_PCIE_SLOT_0) +//========================= +//SLOT0=5G, wlan0=pcie0, wlan1=pcie1 +#ifdef CONFIG_RTL_5G_SLOT_0 +#ifdef CONFIG_SLOT_0_EXT_PA + if(priv->pshare->wlandev_idx == 0) + priv->pshare->rf_ft_var.use_ext_pa = 1; +#endif +#ifdef CONFIG_SLOT_1_EXT_PA + if(priv->pshare->wlandev_idx == 1) + priv->pshare->rf_ft_var.use_ext_pa = 1; +#endif +#endif +//========================= +//SLOT0=5G, wlan0=pcie1, wlan1=pcie0 +#ifdef CONFIG_RTL_5G_SLOT_1 +#ifdef CONFIG_SLOT_0_EXT_PA + if(priv->pshare->wlandev_idx == 1) + priv->pshare->rf_ft_var.use_ext_pa = 1; +#endif +#ifdef CONFIG_SLOT_1_EXT_PA + if(priv->pshare->wlandev_idx == 0) + priv->pshare->rf_ft_var.use_ext_pa = 1; +#endif +#endif +//========================= +//No 5G interface, wlan0=pcie0, wlan1=pcie1 +#if !defined(CONFIG_RTL_5G_SLOT_0) && !defined(CONFIG_RTL_5G_SLOT_1) +#ifdef CONFIG_SLOT_0_EXT_PA + if(priv->pshare->wlandev_idx == 0) + priv->pshare->rf_ft_var.use_ext_pa = 1; +#endif +#ifdef CONFIG_SLOT_1_EXT_PA + if(priv->pshare->wlandev_idx == 1) + priv->pshare->rf_ft_var.use_ext_pa = 1; +#endif +#endif +//========================== +//Only ONE SLOT, always enable HIGH Power +#else //CONFIG_USE_PCIE_SLOT_1 + priv->pshare->rf_ft_var.use_ext_pa = 1; +#endif //CONFIG_USE_PCIE_SLOT_1 +//=========================== + if ((GET_CHIP_VER(priv) == VERSION_8881A) && priv->pshare->rf_ft_var.use_ext_pa) + priv->pshare->rf_ft_var.use_ext_pa = 0; + +#endif //HIGH_POWER_EXT_PA + +#ifdef HIGH_POWER_EXT_LNA +#if defined(CONFIG_USE_PCIE_SLOT_1) && defined(CONFIG_USE_PCIE_SLOT_0) + +//========================= +//SLOT0=5G, wlan0=pcie0, wlan1=pcie1 +#ifdef CONFIG_RTL_5G_SLOT_0 +#ifdef CONFIG_SLOT_0_EXT_LNA + if(priv->pshare->wlandev_idx == 0) + priv->pshare->rf_ft_var.use_ext_lna = 1; +#endif +#ifdef CONFIG_SLOT_1_EXT_LNA + if(priv->pshare->wlandev_idx == 1) + priv->pshare->rf_ft_var.use_ext_lna = 1; +#endif +#endif +//========================= +//SLOT0=5G, wlan0=pcie1, wlan1=pcie0 +#ifdef CONFIG_RTL_5G_SLOT_1 +#ifdef CONFIG_SLOT_0_EXT_LNA + if(priv->pshare->wlandev_idx == 1) + priv->pshare->rf_ft_var.use_ext_lna = 1; +#endif +#ifdef CONFIG_SLOT_1_EXT_LNA + if(priv->pshare->wlandev_idx == 0) + priv->pshare->rf_ft_var.use_ext_lna = 1; +#endif +#endif +//========================= +//No 5G interface, wlan0=pcie0, wlan1=pcie1 +#if !defined(CONFIG_RTL_5G_SLOT_0) && !defined(CONFIG_RTL_5G_SLOT_1) +#ifdef CONFIG_SLOT_0_EXT_LNA + if(priv->pshare->wlandev_idx == 0) + priv->pshare->rf_ft_var.use_ext_lna = 1; +#endif +#ifdef CONFIG_SLOT_1_EXT_LNA + if(priv->pshare->wlandev_idx == 1) + priv->pshare->rf_ft_var.use_ext_lna = 1; +#endif +#endif +//========================== +//Only ONE SLOT, always enable HIGH Power +#else //CONFIG_USE_PCIE_SLOT_1 + priv->pshare->rf_ft_var.use_ext_lna = 1; +#endif //CONFIG_USE_PCIE_SLOT_1 +//=========================== + if ((GET_CHIP_VER(priv) == VERSION_8881A) && priv->pshare->rf_ft_var.use_ext_lna) + priv->pshare->rf_ft_var.use_ext_lna = 0; +#endif //HIGH_POWER_EXT_LNA + +#if defined(CONFIG_RTL_8812_SUPPORT) && defined(HIGH_POWER_EXT_PA) + if (GET_CHIP_VER(priv) == VERSION_8812E && priv->pshare->rf_ft_var.use_ext_pa) { +#ifdef CONFIG_PA_RFMD_4501 + priv->pmib->dot11RFEntry.pa_type = PA_RFMD_4501; +#elif defined(CONFIG_PA_SKYWORKS_5023) + priv->pmib->dot11RFEntry.pa_type = PA_SKYWORKS_5023; +#elif defined(CONFIG_PA_SKYWORKS_85712_HP) + priv->pmib->dot11RFEntry.pa_type = PA_SKYWORKS_85712_HP; +#else + priv->pmib->dot11RFEntry.pa_type = PA_SKYWORKS_5022; +#endif + } +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) && defined(CONFIG_PA_RTC5634) + if (GET_CHIP_VER(priv) == VERSION_8812E) { + //panic_printk("Set PA_RTC5634\n"); + priv->pmib->dot11RFEntry.pa_type = PA_RTC5634; + } +#endif +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv) == VERSION_8881A) { +#if defined(CONFIG_8881A_INT_PA) || defined(CONFIG_8881A_RTC5634) + priv->pmib->dot11RFEntry.pa_type = PA_INTERNAL; +#else + priv->pmib->dot11RFEntry.pa_type = 0; +#endif + +#if defined(CONFIG_8881A_INT_PA) + panic_printk("\n**********************************\n"); + panic_printk("\n** NOTE!! RTL8881A INTERNAL PA! **\n"); + panic_printk("\n**********************************\n"); +#ifdef CONFIG_8881A_INT_PA_RTC5634 + priv->pshare->rf_ft_var.use_intpa8881A= 2; +#else + priv->pshare->rf_ft_var.use_intpa8881A= 1; +#endif +#else + priv->pshare->rf_ft_var.use_intpa8881A= 0; +#endif + } +#endif + +#if defined(CONFIG_WLAN_HAL_8814AE) + if (GET_CHIP_VER(priv) == VERSION_8814A){ +#if defined(CONFIG_USE_PCIE_SLOT_1) && defined(CONFIG_USE_PCIE_SLOT_0) +//========================= +//SLOT0=5G, wlan0=pcie0, wlan1=pcie1 +#ifdef CONFIG_RTL_5G_SLOT_0 + if(priv->pshare->wlandev_idx == (0^WLANIDX)) + { +#ifdef CONFIG_SLOT_0_RFE_TYPE_2 + priv->pmib->dot11RFEntry.rfe_type = 2; +#elif defined(CONFIG_SLOT_0_RFE_TYPE_3) + priv->pmib->dot11RFEntry.rfe_type = 3; +#elif defined(CONFIG_SLOT_0_RFE_TYPE_4) + priv->pmib->dot11RFEntry.rfe_type = 4; +#elif defined(CONFIG_SLOT_0_RFE_TYPE_5) + priv->pmib->dot11RFEntry.rfe_type = 5; +#else + priv->pmib->dot11RFEntry.rfe_type = 0; +#endif + } + if(priv->pshare->wlandev_idx == (1^WLANIDX)) + { +#ifdef CONFIG_SLOT_1_RFE_TYPE_2 + priv->pmib->dot11RFEntry.rfe_type = 2; +#elif defined(CONFIG_SLOT_1_RFE_TYPE_3) + priv->pmib->dot11RFEntry.rfe_type = 3; +#elif defined(CONFIG_SLOT_1_RFE_TYPE_4) + priv->pmib->dot11RFEntry.rfe_type = 4; +#elif defined(CONFIG_SLOT_1_RFE_TYPE_5) + priv->pmib->dot11RFEntry.rfe_type = 5; +#else + priv->pmib->dot11RFEntry.rfe_type = 0; +#endif + } +#endif +//========================= +//SLOT1=5G, wlan0=pcie1, wlan1=pcie0 +#ifdef CONFIG_RTL_5G_SLOT_1 + if(priv->pshare->wlandev_idx == (1^WLANIDX)) + { +#ifdef CONFIG_SLOT_0_RFE_TYPE_2 + priv->pmib->dot11RFEntry.rfe_type = 2; +#elif defined(CONFIG_SLOT_0_RFE_TYPE_3) + priv->pmib->dot11RFEntry.rfe_type = 3; +#elif defined(CONFIG_SLOT_0_RFE_TYPE_4) + priv->pmib->dot11RFEntry.rfe_type = 4; +#elif defined(CONFIG_SLOT_0_RFE_TYPE_5) + priv->pmib->dot11RFEntry.rfe_type = 5; +#else + priv->pmib->dot11RFEntry.rfe_type = 0; +#endif + } + if(priv->pshare->wlandev_idx == (0^WLANIDX)) + { +#ifdef CONFIG_SLOT_1_RFE_TYPE_2 + priv->pmib->dot11RFEntry.rfe_type = 2; +#elif defined(CONFIG_SLOT_1_RFE_TYPE_3) + priv->pmib->dot11RFEntry.rfe_type = 3; +#elif defined(CONFIG_SLOT_1_RFE_TYPE_4) + priv->pmib->dot11RFEntry.rfe_type = 4; +#elif defined(CONFIG_SLOT_1_RFE_TYPE_5) + priv->pmib->dot11RFEntry.rfe_type = 5; +#else + priv->pmib->dot11RFEntry.rfe_type = 0; +#endif + } +#endif +//========================== +//Only ONE SLOT, always enable HIGH Power +#else //defined(CONFIG_USE_PCIE_SLOT_1) && defined(CONFIG_USE_PCIE_SLOT_0) +#ifdef CONFIG_SLOT_0_RFE_TYPE_2 + priv->pmib->dot11RFEntry.rfe_type = 2; +#elif defined(CONFIG_SLOT_0_RFE_TYPE_3) + priv->pmib->dot11RFEntry.rfe_type = 3; +#elif defined(CONFIG_SLOT_0_RFE_TYPE_4) + priv->pmib->dot11RFEntry.rfe_type = 4; +#elif defined(CONFIG_SLOT_0_RFE_TYPE_5) + priv->pmib->dot11RFEntry.rfe_type = 5; +#else + priv->pmib->dot11RFEntry.rfe_type = 0; +#endif +#endif //defined(CONFIG_USE_PCIE_SLOT_1) && defined(CONFIG_USE_PCIE_SLOT_0) + } +#endif //CONFIG_WLAN_HAL_8814AE +} + + +#ifdef CONFIG_WLAN_HAL +BOOLEAN +Wlan_HAL_Link( + struct rtl8192cd_priv *priv +) +{ + BOOLEAN status = TRUE; + BOOLEAN bVal; + unsigned int errorFlag; + + if (RT_STATUS_SUCCESS == HalAssociateNic(priv, TRUE)) { + printk("HalAssociateNic OK \n"); + + } else { + printk("HalAssociateNic Failed \n"); + status = FALSE; + } + + GET_HW(priv)->MIMO_TR_hw_support = GET_HAL_INTERFACE(priv)->GetChipIDMIMOHandler(priv); + + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_MAC_IO_ENABLE, (pu1Byte)&bVal); + if ( bVal || (RTL_R8(SYS_FUNC_EN+1) & BIT2)) { + + // If the watchdog reboot the system without stop the DMA HW, it may got DMA hang + // Do reset to recovery this case + GET_HAL_INTERFACE(priv)->ResetHWForSurpriseHandler(priv); + + if (RT_STATUS_SUCCESS == GET_HAL_INTERFACE(priv)->StopHWHandler(priv)) { + printk("StopHW Succeed\n"); + } else { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_CLOSE_STOP_HW; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + panic_printk("StopHW Failed\n"); + status = FALSE; + } + } else { + //printk("Can't write MACID register\n"); + } + + return status; +} +#endif // CONFIG_WLAN_HAL + +static struct ss_res* alloc_site_survey_res(gfp_t flags) +{ + struct ss_res *res; + + res = (struct ss_res *)rtw_vmalloc(sizeof(struct ss_res)); + if (NULL == res) return NULL; + + memset(res, 0, sizeof(struct ss_res)); + +#ifdef WIFI_SIMPLE_CONFIG + res->wscie = (struct wps_ie_info *)rtw_vmalloc(sizeof(struct wps_ie_info)*MAX_BSS_NUM); + if (NULL == res->wscie) + goto exit_fail; + + res->wscie_backup = (struct wps_ie_info2 *)rtw_vmalloc(sizeof(struct wps_ie_info2)*MAX_BSS_NUM); + if (NULL == res->wscie_backup) + goto exit_fail; +#endif + + return res; + +#ifdef WIFI_SIMPLE_CONFIG +exit_fail: + +// if (res->wscie_backup) +// rtw_vmfree(res->wscie_backup, sizeof(struct wps_ie_info2)*MAX_BSS_NUM); + if (res->wscie) + rtw_vmfree(res->wscie, sizeof(struct wps_ie_info)*MAX_BSS_NUM); + rtw_vmfree(res, sizeof(struct ss_res)); + + return NULL; +#endif +} + +static void free_site_survey_res(struct ss_res *res) +{ +#ifdef WIFI_SIMPLE_CONFIG + rtw_vmfree(res->wscie_backup, sizeof(struct wps_ie_info2)*MAX_BSS_NUM); + rtw_vmfree(res->wscie, sizeof(struct wps_ie_info)*MAX_BSS_NUM); +#endif + rtw_vmfree(res, sizeof(struct ss_res)); +} + + +#if defined(__LINUX_2_6__) && !defined(CONFIG_COMPAT_NET_DEV_OPS) +static const struct net_device_ops rtl8192cd_netdev_ops = { + .ndo_open = rtl8192cd_open, + .ndo_stop = rtl8192cd_close, + .ndo_set_mac_address = rtl8192cd_set_hwaddr, +#if LINUX_VERSION_CODE=KERNEL_VERSION(3,0,0) && LINUX_VERSION_CODE=KERNEL_VERSION(3,0,0) && LINUX_VERSION_CODE>INSIDE rtl8192cd_init_one <<=====\n"); + +#ifdef RTK_NL80211 + if(vap_idx < 0) + { + if(wdev->priv == NULL) + { + printk("init for root device\n"); + rtk = realtek_cfg80211_create(); + } + else // mark_rpt + { + rtk = wdev->priv->rtk ; // find the root rtk + printk("init for vxd device\n"); + } + } + else + { + printk("init for virtual device\n"); + + if (wdev->priv != NULL) + { + rtk = wdev->priv->rtk ; // find the root rtk + } + else + { + printk("can't find the root if for this virtual interface \n"); + return -ENODEV; + } +#if 0 //wrt-vap + if(rtk->ndev_name[rtk->num_vif][0]==0) + { + printk("virtual interface shall be created by cfg80211\n"); + return NULL; + } +#endif + } + + printk("sizeof(struct rtl8192cd_priv) = %d \n", sizeof(struct rtl8192cd_priv)); + +#endif + +#if defined(CONFIG_PCI_HCI) || !defined(CONFIG_NETDEV_MULTI_TX_QUEUE) + dev = alloc_etherdev(sizeof(struct rtl8192cd_priv)); +#else + dev = alloc_etherdev_mq(sizeof(struct rtl8192cd_priv), _NETDEV_TX_QUEUE_ALL); +#endif + if (!dev) { + printk(KERN_ERR "alloc_etherdev() error!\n"); +#ifdef __KERNEL__ + return -ENOMEM; +#else + return NULL; +#endif + } + +#ifdef __ECOS + tmp_dev = dev; +#endif + // now, allocating memory for pmib +#ifdef RTL8192CD_VARIABLE_USED_DMEM + pmib = (struct wifi_mib *)rtl8192cd_dmem_alloc(PMIB, NULL); +#else + pmib = (struct wifi_mib *)kmalloc((sizeof(struct wifi_mib)), GFP_ATOMIC); +#endif + if (!pmib) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for wifi_mib (size %d)\n", sizeof(struct wifi_mib)); + goto err_out_free; + } + memset(pmib, 0, sizeof(struct wifi_mib)); + + pevent_queue = (DOT11_QUEUE *)kmalloc((sizeof(DOT11_QUEUE)), GFP_ATOMIC); + if (!pevent_queue) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for DOT11_QUEUE (size %d)\n", sizeof(DOT11_QUEUE)); + goto err_out_free; + } + memset((void *)pevent_queue, 0, sizeof(DOT11_QUEUE)); +#ifdef CONFIG_RTL_WAPI_SUPPORT + wapiEvent_queue = (DOT11_QUEUE *)kmalloc((sizeof(DOT11_QUEUE)), GFP_ATOMIC); + if (!wapiEvent_queue) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for DOT11_QUEUE (size %d)\n", sizeof(DOT11_QUEUE)); + goto err_out_free; + } + memset((void *)wapiEvent_queue, 0, sizeof(DOT11_QUEUE)); + #if 0 //def MBSSID + wapiVapEvent_queue = (DOT11_QUEUE *)kmalloc((sizeof(DOT11_QUEUE)*RTL8192CD_NUM_VWLAN), GFP_ATOMIC); + if (!wapiVapEvent_queue) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for DOT11_QUEUE (size %d)\n", sizeof(DOT11_QUEUE)*RTL8192CD_NUM_VWLAN); + goto err_out_free; + } + memset((void *)wapiVapEvent_queue, 0, sizeof(DOT11_QUEUE)*RTL8192CD_NUM_VWLAN); + #endif +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (wdev->priv == NULL) // root interface +#endif + { +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE + phw = &hw_info[wlandev_idx]; +#else + phw = &hw_info; +#endif +#else + phw = (struct rtl8192cd_hw *)kmalloc((sizeof(struct rtl8192cd_hw)), GFP_ATOMIC); + if (!phw) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for rtl8192cd_hw (size %d)\n", sizeof(struct rtl8192cd_hw)); + goto err_out_free; + } +#endif + memset((void *)phw, 0, sizeof(struct rtl8192cd_hw)); +#ifdef CONFIG_PCI_HCI + ptxdesc = &phw->tx_info; +#endif + +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE + pshare = &shared_info[wlandev_idx]; +#else + pshare = &shared_info; +#endif +#else + pshare = (struct priv_shared_info *)kmalloc(sizeof(struct priv_shared_info), GFP_ATOMIC); + if (!pshare) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for priv_shared_info (size %d)\n", sizeof(struct priv_shared_info)); + goto err_out_free; + } +#endif + memset((void *)pshare, 0, sizeof(struct priv_shared_info)); + +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE + pwlan_hdr_poll = &hdr_pool[wlandev_idx]; +#else + pwlan_hdr_poll = &hdr_pool; +#endif +#else + pwlan_hdr_poll = (struct wlan_hdr_poll *) + kmalloc((sizeof(struct wlan_hdr_poll)), GFP_ATOMIC); + if (!pwlan_hdr_poll) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for wlan_hdr_poll (size %d)\n", sizeof(struct wlan_hdr_poll)); + goto err_out_free; + } +#endif + +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE + pwlanllc_hdr_poll = &llc_pool[wlandev_idx]; +#else + pwlanllc_hdr_poll = &llc_pool; +#endif +#else + pwlanllc_hdr_poll = (struct wlanllc_hdr_poll *) + kmalloc((sizeof(struct wlanllc_hdr_poll)), GFP_ATOMIC); + if (!pwlanllc_hdr_poll) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for wlanllc_hdr_poll (size %d)\n", sizeof(struct wlanllc_hdr_poll)); + goto err_out_free; + } +#endif + +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE + pwlanbuf_poll = &buf_pool[wlandev_idx]; +#else + pwlanbuf_poll = &buf_pool; +#endif +#else + pwlanbuf_poll = (struct wlanbuf_poll *) + kmalloc((sizeof(struct wlanbuf_poll)), GFP_ATOMIC); + if (!pwlanbuf_poll) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for wlanbuf_poll (size %d)\n", sizeof(struct wlanbuf_poll)); + goto err_out_free; + } +#endif + +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE + pwlanicv_poll = &icv_pool[wlandev_idx]; +#else + pwlanicv_poll = &icv_pool; +#endif +#else + pwlanicv_poll = (struct wlanicv_poll *) + kmalloc((sizeof(struct wlanicv_poll)), GFP_ATOMIC); + if (!pwlanicv_poll) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for wlanicv_poll (size %d)\n", sizeof(struct wlanicv_poll)); + goto err_out_free; + } +#endif + +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE + pwlanmic_poll = &mic_pool[wlandev_idx]; + wlandev_idx++; +#else + pwlanmic_poll = &mic_pool; +#endif +#else + pwlanmic_poll = (struct wlanmic_poll *) + kmalloc((sizeof(struct wlanmic_poll)), GFP_ATOMIC); + if (!pwlanmic_poll) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for wlanmic_poll (size %d)\n", sizeof(struct wlanmic_poll)); + goto err_out_free; + } +#endif + } + + pwlan_acl_poll = (struct wlan_acl_poll *) + kmalloc((sizeof(struct wlan_acl_poll)), GFP_ATOMIC); + if (!pwlan_acl_poll) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for wlan_acl_poll (size %d)\n", sizeof(struct wlan_acl_poll)); + goto err_out_free; + } + +#if defined(CONFIG_RTK_MESH) && defined(_MESH_ACL_ENABLE_) // below code copy above ACL code + pmesh_acl_poll = (struct mesh_acl_poll *) + kmalloc((sizeof(struct mesh_acl_poll)), GFP_ATOMIC); + if (!pmesh_acl_poll) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for Mesh wlan_acl_poll (size %d)\n", sizeof(struct mesh_acl_poll)); + goto err_out_free; + } +#endif + + Eap_packet = (DOT11_EAP_PACKET *) + kmalloc((sizeof(DOT11_EAP_PACKET)), GFP_ATOMIC); + if (!Eap_packet) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for Eap_packet (size %d)\n", sizeof(DOT11_EAP_PACKET)); + goto err_out_free; + } + memset((void *)Eap_packet, 0, sizeof(DOT11_EAP_PACKET)); + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + wpa_global_info = (WPA_GLOBAL_INFO *) + kmalloc((sizeof(WPA_GLOBAL_INFO)), GFP_ATOMIC); + if (!wpa_global_info) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for wpa_global_info (size %d)\n", sizeof(WPA_GLOBAL_INFO)); + goto err_out_free; + } + memset((void *)wpa_global_info, 0, sizeof(WPA_GLOBAL_INFO)); +#endif + +#if (defined(UNIVERSAL_REPEATER) || defined(MBSSID)) && !defined(MULTI_MAC_CLONE) + if ((NULL == wdev->priv) || (vap_idx < 0)) +#endif + { + site_survey = alloc_site_survey_res(GFP_ATOMIC); + if (!site_survey) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for site_survey (size %d)\n", sizeof(struct ss_res)); + goto err_out_free; + } + } + +#ifndef __DRAYTEK_OS__ +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (wdev->priv) { +#ifdef UNIVERSAL_REPEATER + if (vap_idx < 0) + { +#if defined(CONFIG_OPENWRT_SDK) + sprintf(dev->name, "%s-%d", wdev->priv->dev->name, RTL8192CD_NUM_VWLAN); +#else + sprintf(dev->name, "%s-vxd", wdev->priv->dev->name); +#endif + } +#endif +#ifdef MBSSID + if (vap_idx >= 0) + { +#if defined(RTK_NL80211) && defined(CONFIG_OPENWRT_SDK) + if(vap_idx == 0) + sprintf(dev->name, "tmp.%s", wdev->priv->dev->name); + else + sprintf(dev->name, "%s-%d", wdev->priv->dev->name, vap_idx); +#elif defined(CONFIG_RTL8672) || defined(__OSK__) + sprintf(dev->name, "%s-vap%d", wdev->priv->dev->name, vap_idx); +#else + sprintf(dev->name, "%s-va%d", wdev->priv->dev->name, vap_idx); +#endif + } +#endif + } + else +#endif + { + strcpy(dev->name, "wlan%d"); + } +#endif + +#ifdef CONFIG_RTL_VLAN_8021Q + if(strcmp(dev->name,"wlan0-va0")==0) + dev->vlan_member_map=WLAN0_VA0_MASK_BIT; + else if(strcmp(dev->name,"wlan0-va1")==0) + dev->vlan_member_map=WLAN0_VA1_MASK_BIT; + else if(strcmp(dev->name,"wlan0-va2")==0) + dev->vlan_member_map=WLAN0_VA2_MASK_BIT; + else if(strcmp(dev->name,"wlan0-va3")==0) + dev->vlan_member_map=WLAN0_VA3_MASK_BIT; + else if(strcmp(dev->name,"wlan1-va0")==0) + dev->vlan_member_map=WLAN1_VA0_MASK_BIT; + else if(strcmp(dev->name,"wlan1-va1")==0) + dev->vlan_member_map=WLAN1_VA1_MASK_BIT; + else if(strcmp(dev->name,"wlan1-va2")==0) + dev->vlan_member_map=WLAN1_VA2_MASK_BIT; + else if(strcmp(dev->name,"wlan1-va3")==0) + dev->vlan_member_map=WLAN1_VA3_MASK_BIT; + else if(strcmp(dev->name,"wlan0-vxd")==0) + dev->vlan_member_map=WLAN0_VXD_MASK_BIT; + else if(strcmp(dev->name,"wlan1-vxd")==0) + dev->vlan_member_map=WLAN1_VXD_MASK_BIT; +#endif + +#ifdef LINUX_2_6_24_ + /*SET_MODULE_OWNER is obsolete from 2.6.24*/ +#else + SET_MODULE_OWNER(dev); +#endif + +#ifdef NETDEV_NO_PRIV + priv = (struct rtl8192cd_priv *)netdev_priv(dev); + priv->wlan_priv = priv; +#else + priv = dev->priv; +#endif + + priv->pmib = pmib; +#if 0/*defined(CONFIG_RTL_WAPI_SUPPORT)*/ + /* only for test */ + priv->pmib->wapiInfo.wapiType = wapiDisable; + priv->pmib->wapiInfo.wapiUpdateMCastKeyType = wapi_disable_update; + priv->pmib->wapiInfo.wapiUpdateUCastKeyTimeout = WAPI_KEY_UPDATE_PERIOD; + priv->pmib->wapiInfo.wapiUpdateUCastKeyPktNum = WAPI_KEY_UPDATE_PKTCNT; +#endif + priv->pevent_queue = pevent_queue; +#ifdef CONFIG_RTL_WAPI_SUPPORT + priv->wapiEvent_queue= wapiEvent_queue; +#endif + priv->pwlan_acl_poll = pwlan_acl_poll; + priv->Eap_packet = Eap_packet; +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + priv->wpa_global_info = wpa_global_info; +#endif + priv->site_survey = site_survey; +#ifdef MBSSID + priv->vap_id = -1; +#endif +#if defined(CONFIG_RTK_MESH) && defined(_MESH_ACL_ENABLE_) // below code copy above ACL code + priv->pmesh_acl_poll = pmesh_acl_poll; +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (wdev->priv) { + priv->pshare = wdev->priv->pshare; + priv->proot_priv = wdev->priv; +#ifdef UNIVERSAL_REPEATER + if (vap_idx < 0) // create for vxd + GET_VXD_PRIV(wdev->priv) = priv; +#endif +#ifdef MBSSID + if (vap_idx >= 0) { // create for vap + GET_ROOT(priv)->pvap_priv[vap_idx] = priv; + priv->vap_id = vap_idx; + priv->vap_init_seq = -1; + + #if 0 /*defined(CONFIG_RTL_WAPI_SUPPORT)*/ + priv->pmib->wapiInfo.wapiType = wapiDisable; + priv->pmib->wapiInfo.wapiUpdateMCastKeyType = wapi_disable_update; + priv->pmib->wapiInfo.wapiUpdateUCastKeyTimeout = WAPI_KEY_UPDATE_PERIOD; + priv->pmib->wapiInfo.wapiUpdateUCastKeyPktNum = WAPI_KEY_UPDATE_PKTCNT; + priv->wapiEvent_queue= &wapiVapEvent_queue[vap_idx]; + printk("dev[%s]:wapiType[%d] UCastKeyType[%d] psk[%s] len[%d]\n", + priv->dev->name, priv->pmib->wapiInfo.wapiType, + priv->pmib->wapiInfo.wapiUpdateMCastKeyType, + priv->pmib->wapiInfo.wapiPsk.octet, + priv->pmib->wapiInfo.wapiPsk.len); + #endif + } +#endif +#ifdef CONFIG_WLAN_HAL + priv->HalFunc = GET_ROOT(priv)->HalFunc; + priv->HalData = GET_ROOT(priv)->HalData; +#endif + } + else +#endif + { + priv->pshare = pshare; // david + priv->pshare->phw = phw; +#ifdef CONCURRENT_MODE + priv->pshare->wlandev_idx = wlan_index; +#endif +#ifdef CONFIG_PCI_HCI + priv->pshare->pdesc_info = ptxdesc; +#endif + priv->pshare->pwlan_hdr_poll = pwlan_hdr_poll; + priv->pshare->pwlanllc_hdr_poll = pwlanllc_hdr_poll; + priv->pshare->pwlanbuf_poll = pwlanbuf_poll; + priv->pshare->pwlanicv_poll = pwlanicv_poll; + priv->pshare->pwlanmic_poll = pwlanmic_poll; + wdev->priv = priv; +#ifdef __KERNEL__ + spin_lock_init(&priv->pshare->lock); +#endif + +#ifdef CONFIG_RTK_MESH + spin_lock_init(&priv->pshare->lock_queue); + spin_lock_init(&priv->pshare->lock_Rreq); +#endif + +#ifdef SMP_SYNC + spin_lock_init(&priv->pshare->lock_xmit); + spin_lock_init(&priv->pshare->lock_skb); +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + _rtw_mutex_init(&(priv->pshare->lock_buf)); +#else + spin_lock_init(&priv->pshare->lock_buf); +#endif + spin_lock_init(&priv->pshare->lock_recv); + priv->pshare->lock_owner=-1; + priv->pshare->lock_recv_owner=-1; + priv->pshare->lock_xmit_owner=-1; +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + priv->pshare->nr_bcn = 1; + priv->pshare->bcn_priv[0] = priv; +#ifdef MBSSID + _rtw_mutex_init(&priv->pshare->mbssid_lock); +#endif +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_NET_PCI + if (((wdev->type >> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS) + priv->pshare->pdev = pdev; +#endif +#endif // CONFIG_PCI_HCI + + priv->pshare->type = wdev->type; +#ifdef USE_RTL8186_SDK +#if defined(CONFIG_RTL8196B) || defined(CONFIG_RTL_819X) + priv->pshare->have_hw_mic = 1; +#else + priv->pshare->have_hw_mic = 0; +#endif +#else + priv->pshare->have_hw_mic = 0; +#endif +// priv->pshare->is_giga_exist = is_giga_board(); +#ifdef MULTI_MAC_CLONE + priv->pshare->mclone_init_seq = -1; +#endif + } + + priv->dev = dev; + +#ifndef __DRAYTEK_OS__ +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (!IS_ROOT_INTERFACE(priv)) { // is a vxd or vap + dev->base_addr = GET_ROOT(priv)->dev->base_addr; + goto register_driver; + } +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_NET_PCI + if (((wdev->type >> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS) + { + rc = pci_enable_device(pdev); + if (rc) + goto err_out_free2; +#ifndef USE_IO_OPS + rc = pci_request_regions(pdev, DRV_NAME); +#endif + if (rc) + goto err_out_disable; + + if (pdev->irq < 2) { + rc = -EIO; +#ifdef __LINUX_2_6__ + printk(KERN_ERR "invalid irq (%d) for pci dev\n", pdev->irq); +#else + printk(KERN_ERR "invalid irq (%d) for pci dev %s\n", pdev->irq, pdev->slot_name); +#endif + goto err_out_res; + } +#ifdef USE_IO_OPS + { + resource_size_t pio_start; + unsigned long pio_len, pio_flags; + + pio_start = pci_resource_start(pdev, 0); + pio_len = (unsigned long)pci_resource_len(pdev, 0); + pio_flags = (unsigned long)pci_resource_flags(pdev, 0); +// pio_start = pci_resource_start(pdev, 2); +// pio_len = (unsigned long)pci_resource_len(pdev, 2); +// pio_flags = (unsigned long)pci_resource_flags(pdev, 2); + + + if (!(pio_flags & IORESOURCE_IO)) { + rc = -EIO; +#ifdef __LINUX_2_6__ + printk(KERN_ERR "pci: region #0 not a PIO resource, aborting\n"); +#else + printk(KERN_ERR "%s: region #0 not a PIO resource, aborting\n", pdev->slot_name); +#endif + goto err_out_res; + } + + if (!request_region(pio_start, pio_len, DRV_NAME)) { + rc = -EIO; + printk(KERN_ERR "request_region failed!\n"); + goto err_out_res; + } + + if (pio_len < RTL8192CD_REGS_SIZE) { + rc = -EIO; +#ifdef __LINUX_2_6__ + printk(KERN_ERR "PIO resource (%lx) too small on pci dev\n", pio_len); +#else + printk(KERN_ERR "PIO resource (%lx) too small on pci dev %s\n", pio_len, pdev->slot_name); +#endif + goto err_out_res; + } + + dev->base_addr = pio_start; + priv->pshare->ioaddr = pio_start; // device I/O address + } +#else +#ifdef IO_MAPPING + pciaddr = pci_resource_start(pdev, 0); +// pciaddr = pci_resource_start(pdev, 2); +#else +// pciaddr = pci_resource_start(pdev, 1); + pciaddr = pci_resource_start(pdev, 2); +#endif + if (!pciaddr) { + rc = -EIO; +#ifdef __LINUX_2_6__ + printk(KERN_ERR "no MMIO resource for pci dev"); +#else + printk(KERN_ERR "no MMIO resource for pci dev %s\n", pdev->slot_name); +#endif + goto err_out_res; + } + +// if ((pmem_len = pci_resource_len(pdev, 1)) < RTL8192CD_REGS_SIZE) { + if ((pmem_len = pci_resource_len(pdev, 2)) < RTL8192CD_REGS_SIZE) { + rc = -EIO; +#ifdef __LINUX_2_6__ + printk(KERN_ERR "MMIO resource () too small on pci dev\n"); +#else + printk(KERN_ERR "MMIO resource (%lx) too small on pci dev %s\n", (unsigned long)pmem_len, pdev->slot_name); +#endif + goto err_out_res; + } + + regs = ioremap_nocache(pciaddr, pmem_len); + if (!regs) { + rc = -EIO; +#ifdef __LINUX_2_6__ + printk(KERN_ERR "Cannot map PCI MMIO () on pci dev \n"); +#else + printk(KERN_ERR "Cannot map PCI MMIO (%lx@%lx) on pci dev %s\n", (unsigned long)pmem_len, (long)pciaddr, pdev->slot_name); +#endif + goto err_out_res; + } + + dev->base_addr = (unsigned long)regs; + priv->pshare->ioaddr = (unsigned long)regs; + //check_chipID_MIMO(priv); +#endif // USE_IO_OPS +#if !defined(NOT_RTK_BSP) +#ifdef CONFIG_RTL_92D_SUPPORT + { + u32 vendor_deivce_id, config_base; + + vendor_deivce_id = dev->base_addr; + if(dev->base_addr==0xba000000) + { + vendor_deivce_id= *((volatile unsigned long *)(0xb8b30000)); + } + else if(dev->base_addr==0xb9000000) + { + vendor_deivce_id= *((volatile unsigned long *)(0xb8b10000)); + } + printk(" vendor_deivce_id=%x\n", vendor_deivce_id); + if (vendor_deivce_id == ((unsigned long)((0x8193<<16)|PCI_VENDOR_ID_REALTEK))) + priv->pshare->version_id = VERSION_8192D; + else + priv->pshare->version_id =0x1234; + } +#endif +#else/*NOT_RTK_BSP*/ + + { + struct pci_dev *pdev = priv->pshare->pdev; + u16 vendor_id,device_id; + pci_read_config_word( pdev , PCI_VENDOR_ID , &vendor_id); + pci_read_config_word( pdev , PCI_DEVICE_ID , &device_id); + + printk("vendor_id=0x%04X, device_id=0x%04X\n", vendor_id, device_id); +#ifdef CONFIG_RTL_92D_SUPPORT + if( (vendor_id==0x10ec) && (device_id==0x8193) ) + { + printk("version_id=VERSION_8192D\n"); + priv->pshare->version_id = VERSION_8192D; + #ifdef CONFIG_RTL_92D_DMDP + priv->pshare->wlandev_idx = rtl8192D_idx;/*timmy_modify*/ + if( rtl8192D_idx == 0 ) + { + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; + priv->pmib->dot11BssType.net_work_type = WIRELESS_11A | WIRELESS_11N ; + } + else + { + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; + priv->pmib->dot11BssType.net_work_type = WIRELESS_11B | WIRELESS_11G; + } + rtl8192D_idx++; + printk("macPhyMode=DUALMAC_DUALPHY MIMO_1T1R\n"); + priv->pmib->dot11RFEntry.macPhyMode = DUALMAC_DUALPHY;/*timmy_dbg*/ + priv->pshare->phw->MIMO_TR_hw_support = MIMO_1T1R; + #else + printk("macPhyMode=DUALMAC_DUALPHY MIMO_2T2R\n"); + priv->pmib->dot11RFEntry.macPhyMode = SINGLEMAC_SINGLEPHY;/*timmy_dbg*/ + priv->pshare->phw->MIMO_TR_hw_support = MIMO_2T2R; + #endif + } else +#endif // CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_8812_SUPPORT + if( (vendor_id==0x10ec) && (device_id==0x8812) ) + { + printk("version_id=VERSION_8812E found\n"); + priv->pshare->version_id = VERSION_8812E; + priv->pmib->dot11RFEntry.macPhyMode = SINGLEMAC_SINGLEPHY; + priv->pshare->phw->MIMO_TR_hw_support = MIMO_2T2R; + } else +#endif // CONFIG_RTL_8812_SUPPORT +#ifdef CONFIG_WLAN_HAL_8192EE + if( (vendor_id==0x10ec) && (device_id==0x8170 || device_id==0x818b) ) + { + printk("version_id=VERSION_8192E found\n"); + priv->pshare->version_id = VERSION_8192E; + priv->pmib->dot11RFEntry.macPhyMode = SINGLEMAC_SINGLEPHY; + priv->pshare->phw->MIMO_TR_hw_support = MIMO_2T2R; + Wlan_HAL_Link(priv); + } else +#endif // CONFIG_WLAN_HAL_8192EE +#ifdef CONFIG_WLAN_HAL_8814AE + if( (vendor_id==0x10ec) && (device_id==0x8813) ) + { + printk("version_id=VERSION_8814AE found\n"); + priv->pshare->version_id = VERSION_8814A; + priv->pmib->dot11RFEntry.macPhyMode = SINGLEMAC_SINGLEPHY; + // TODO: Filen, temporarily use 2T2R + // 8814 merge issue +#if 0 + // 8814 merge issue (Disable?) + //Disable Multi-tag + RTL_W8(REG_HCI_MIX_CFG, RTL_R8(REG_HCI_MIX_CFG) & ~BIT6 ); +#endif + Wlan_HAL_Link(priv); + } else +#endif // CONFIG_WLAN_HAL_8814AE +#ifdef CONFIG_RTL_88E_SUPPORT + if ((vendor_id == 0x10ec) && (device_id == 0x8179)) + { + printk("version_id=VERSION_8188E\n"); + priv->pshare->version_id = VERSION_8188E; + priv->pshare->phw->MIMO_TR_hw_support = MIMO_1T1R; + } else +#endif + { + printk(KERN_ERR "%s(%d): can't recognize wifi chip(vendor_id=0x%04x, device_id=0x%04x)!!\n", + __func__, __LINE__, vendor_id, device_id); + rc = -ENODEV; + goto err_out_res; + } + } +#endif /*NOT_RTK_BSP*/ + check_chipID_MIMO(priv); + } + else +#endif // CONFIG_NET_PCI + { + regs = (void *)wdev->base_addr; + dev->base_addr = (unsigned long)wdev->base_addr; + priv->pshare->ioaddr = (unsigned long)regs; + + if (((priv->pshare->type>>TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_DIRECT) + { + int i ; +#ifdef CONFIG_RTL_92D_SUPPORT + unsigned long config_base, base_addr; + config_base = wdev->conf_addr; + base_addr = wdev->base_addr; +#endif + + _DEBUG_INFO("INIT PCI config space directly\n"); + +#if 0 //defined(CONFIG_RTL_8812_SUPPORT) && (RTL_USED_PCIE_SLOT==1) + wdev->conf_addr = BSP_PCIE1_D_CFG0; +#endif + + +#if !defined(CONFIG_NET_PCI) && (defined(CONFIG_RTL8196B) || defined(CONFIG_RTL_819X) || defined(CONFIG_RTL_8196E)) + #if defined(CONFIG_RTL8196C) || defined(CONFIG_RTL_8196C) || defined(CONFIG_RTL_819X) || defined(CONFIG_RTL_8196E) + +#if 0 //defined(CONFIG_RTL_8812_SUPPORT) && (RTL_USED_PCIE_SLOT==1) + if(1) +#else + if (BSP_PCIE0_D_CFG0 == wdev->conf_addr) + + { +#ifdef CONFIG_RTL_8198B //mark_apo + PCIE_reset_procedure(1, 0, 1, BSP_PCIE1_D_CFG0); +#endif + if ((PCIE_reset_procedure(0, 0, 1, wdev->conf_addr))== FAIL) + { + rc = -ENODEV; + goto err_out_free2; + } + } + else if (BSP_PCIE1_D_CFG0 == wdev->conf_addr) +#endif + { + if ((PCIE_reset_procedure(1, 0, 1, wdev->conf_addr))== FAIL) + { + rc = -ENODEV; + goto err_out_free2; + } + } + else + { + rc = -ENODEV; + goto err_out_free2; + } + #else + if (rtl8196b_pci_reset(wdev->conf_addr) == FAIL) { + rc = -ENODEV; + goto err_out_free2; + } + #endif + //REG32(0xb8000040)=0xf; // port 5 support !!!!! +#endif +#ifdef __ECOS + /* Fix the issue to use memory under 1M */ + REG32(0xb8b00000+0x1c)=(2<<4) | (0<<12); // [7:4]=base [15:12]=limit + REG32(0xb8b00000+0x20)=(2<<4) | (0<<20); // [7:4]=base [15:12]=limit + REG32(0xb8b00000+0x24)=(2<<4) | (0<<20); // [7:4]=base [15:12]=limit +#endif + + { + u32 vendor_deivce_id, config_base; + config_base = wdev->conf_addr; + vendor_deivce_id = *((volatile unsigned long *)(config_base+0)); + printk("config_base=%x, vendor_deivce_id=%x\n", config_base, vendor_deivce_id); + if ( +#if defined(CONFIG_RTL_92D_SUPPORT) + (vendor_deivce_id != ((unsigned long)((0x8193<<16)|PCI_VENDOR_ID_REALTEK))) && +#endif + (vendor_deivce_id != ((unsigned long)((0x8191<<16)|PCI_VENDOR_ID_REALTEK))) && + (vendor_deivce_id != ((unsigned long)((0x8171<<16)|PCI_VENDOR_ID_REALTEK))) && + (vendor_deivce_id != ((unsigned long)((0x8178<<16)|PCI_VENDOR_ID_REALTEK))) && + (vendor_deivce_id != ((unsigned long)((0x8174<<16)|PCI_VENDOR_ID_REALTEK))) && + (vendor_deivce_id != ((unsigned long)((0x8176<<16)|PCI_VENDOR_ID_REALTEK))) +#ifdef CONFIG_RTL_88E_SUPPORT + && (vendor_deivce_id != ((unsigned long)((0x8179<<16)|PCI_VENDOR_ID_REALTEK))) +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + && (vendor_deivce_id != ((unsigned long)((0x8812<<16)|PCI_VENDOR_ID_REALTEK))) +#endif +#if defined(CONFIG_WLAN_HAL_8192EE) + && (vendor_deivce_id != ((unsigned long)((0x8170<<16)|PCI_VENDOR_ID_REALTEK))) + && (vendor_deivce_id != ((unsigned long)((0x818b<<16)|PCI_VENDOR_ID_REALTEK))) +#endif +#if defined(CONFIG_WLAN_HAL_8814AE) + && (vendor_deivce_id != ((unsigned long)((0x8813<<16)|PCI_VENDOR_ID_REALTEK))) +#endif + ) { + _DEBUG_ERR("vendor_deivce_id=%x not match\n", vendor_deivce_id); + rc = -EIO; + goto err_out_free2; + } + +#if defined (CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_WLAN_HAL_8814AE) +#ifdef CONFIG_RTL_92D_SUPPORT + if (vendor_deivce_id == ((unsigned long)((0x8193<<16)|PCI_VENDOR_ID_REALTEK))) + priv->pshare->version_id = VERSION_8192D; + else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (vendor_deivce_id == ((unsigned long)((0x8179<<16)|PCI_VENDOR_ID_REALTEK))) { +// printk("\n found 8188E !!! \n"); + priv->pshare->version_id = VERSION_8188E; + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (vendor_deivce_id == ((unsigned long)((0x8812<<16)|PCI_VENDOR_ID_REALTEK))) + { + printk("\n found 8812 !!! \n"); + priv->pshare->version_id = VERSION_8812E; + } + else +#endif +#if defined(CONFIG_WLAN_HAL_8192EE) + if (vendor_deivce_id == ((unsigned long)((0x8170<<16)|PCI_VENDOR_ID_REALTEK)) + || vendor_deivce_id == ((unsigned long)((0x818b<<16)|PCI_VENDOR_ID_REALTEK))) { + priv->pshare->version_id = VERSION_8192E; +// panic_printk("\n found 8192E !!! \n"); + } + else +#endif +#if defined(CONFIG_WLAN_HAL_8814AE) + if (vendor_deivce_id == ((unsigned long)((0x8813<<16)|PCI_VENDOR_ID_REALTEK))) { + priv->pshare->version_id = VERSION_8814A; + panic_printk("\n found 8814A !!! \n"); + } + else +#endif + + { + priv->pshare->version_id = 0; + } +#endif + } + + *((volatile unsigned long *)PCI_CONFIG_BASE1) = virt_to_bus((void *)dev->base_addr); + //DEBUG_INFO("...config_base1 = 0x%08lx\n", *((volatile unsigned long *)PCI_CONFIG_BASE1)); + for(i=0; i<1000000; i++); + *((volatile unsigned char *)PCI_CONFIG_COMMAND) = 0x07; + //DEBUG_INFO("...command = 0x%08lx\n", *((volatile unsigned long *)PCI_CONFIG_COMMAND)); + for(i=0; i<1000000; i++); + *((volatile unsigned short *)PCI_CONFIG_LATENCY) = 0x2000; + for(i=0; i<1000000; i++); + //DEBUG_INFO("...latency = 0x%08lx\n", *((volatile unsigned long *)PCI_CONFIG_LATENCY)); + +#ifndef NOT_RTK_BSP +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_WLAN_HAL_8814AE) + if ((GET_CHIP_VER(priv)!=VERSION_8188E) && (GET_CHIP_VER(priv)!=VERSION_8192E) && (GET_CHIP_VER(priv)!=VERSION_8812E) && (GET_CHIP_VER(priv)!=VERSION_8814A)) +#endif + { +#if defined(CONFIG_RTL8196C_REVISION_B) || defined(CONFIG_RTL_8196C) +#if defined(CONFIG_NET_PCI) +#define REVR 0xB8000000 +#define RTL8196C_REVISION_A 0x80000001 +#define RTL8196C_REVISION_B 0x80000002 +#endif + if (REG32(REVR) == RTL8196C_REVISION_B) { + REG32(0xb8b01000)=0x0f0f0f01; //Enhance for RTL8192c signal + for(i=0; i<1000000; i++); + i=REG32(0xb8b01000); + REG32(0xb9000354)=0xc940; //Card PCIE PHY initial parameter for rtl8196c revision B + REG32(0xb9000358)=0x24; + for(i=0; i<1000000; i++); + REG32(0xb9000354)=0x4270; + REG32(0xb9000358)=0x25; + for(i=0; i<1000000; i++); + REG32(0xb9000354)=0x019E; //Card PCIE PHY initial parameter for rtl8196c revision B + REG32(0xb9000358)=0x23; + } +#endif +#if defined(CONFIG_RTL8198_REVISION_B) || defined(CONFIG_RTL_8198) || defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E) +#if !defined(CONFIG_RTL_92D_SUPPORT) +#if defined(CONFIG_NET_PCI) +#define BSP_REVR 0xB8000000 +#define BSP_RTL8198_REVISION_A 0xC0000000 +#define BSP_RTL8198_REVISION_B 0xC0000001 +#endif +#if !defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN) + +#if defined(CONFIG_RTL_8196E) + if ((REG32(BSP_REVR) & 0xFFFFF000) == BSP_RTL8196E) +#else + if ((REG32(BSP_REVR) >= BSP_RTL8198_REVISION_B) || ((REG32(BSP_REVR) & 0xFFFFF000) == BSP_RTL8197D)) +#endif + { + if (priv->pshare->version_id!= VERSION_8192D) { + REG32(dev->base_addr+0x354)=0xc940; //Card PCIE PHY initial parameter for rtl8196c revision B + REG32(dev->base_addr+0x358)=0x24; + for(i=0; i<1000000; i++); + REG32(dev->base_addr+0x354)=0x4270; + REG32(dev->base_addr+0x358)=0x25; + for(i=0; i<1000000; i++); + REG32(dev->base_addr+0x354)=0x019E; //Card PCIE PHY initial parameter for rtl8196c revision B + REG32(dev->base_addr+0x358)=0x23; + } + } +#endif +#endif +#endif + } + #if defined(CONFIG_RTL_88E_SUPPORT) + else + { + REG32(dev->base_addr+0x354)=0x4104; //Card PCIE PHY initial parameter for rtl8196c revision B + for(i=0; i<1000000; i++); + REG32(dev->base_addr+0x358)=0x24; + } + #endif +#ifdef CONFIG_RTL_8198B + REG32(BSP_WDTCNTRR) |= BSP_WDT_KICK; +#else + #ifndef CONFIG_ARCH_LUNA_SLAVE + REG32(0xB800311C) |= 1 << 23; +#endif +#endif +#endif // !NOT_RTK_BSP +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv)==VERSION_8192E) { + if (RT_STATUS_SUCCESS == HalAssociateNic(priv, TRUE)) { + printk("HalAssociateNic OK \n"); +#ifndef NOT_RTK_BSP + if (PHY_QueryBBReg(priv,0xf0,BIT(23)) == 0) { + //printk("\n found 8192E MP chip!!! 0xf0=0x%x\n", RTL_R32(0xf0)); +#ifdef CONFIG_RTL_8198C + REG32(0xb8b10078)= 0x00100010; // burst size +#else + if (((RTL_R32(0xf0) >> 12 ) & 0xf) == 0){ + + unsigned int tmp_reg = REG32(0xb8b10078); + + printk("\n8192E MP chip A-cut!!! 0xb8b10078=0x%x\n", tmp_reg ); + if (((tmp_reg & 0xf000) >> 12) != 2) { + tmp_reg &= 0xffff0fff; + tmp_reg |= 0x2000; + + printk("==> 0xb8b10078=0x%x\n", tmp_reg); + RTL_W32(0x3e8, tmp_reg); + RTL_W32(0x3f0, 0x1f078); + } + } +#endif + } +#endif + check_chipID_MIMO(priv); + + } + else { + printk("HalAssociateNic Failed \n"); + } + + GET_HW(priv)->MIMO_TR_hw_support = GET_HAL_INTERFACE(priv)->GetChipIDMIMOHandler(priv); + + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_MAC_IO_ENABLE, (pu1Byte)&bVal); + if ( bVal ) +// if (bVal || (RTL_R8(SYS_FUNC_EN+1) & BIT2)) // if MCU is on + { + // If the watchdog reboot the system without stop the DMA HW, it may got DMA hang + // Do reset to recovery this case + RTL_W8(0x1c, RTL_R8(0x1c)& ~BIT(1)); + RTL_W8(0xcc, RTL_R8(0xcc) | 0x04); // UnMask Write Access for PMC FSM, we are going to write PCIe MAC enable bit + RTL_W8(CR,0); // disable MAC totally + RTL_W8(SYS_FUNC_EN+1, RTL_R8(SYS_FUNC_EN+1) & 0xfe); // PCIe MAC disable + RTL_W8(SYS_FUNC_EN+1, RTL_R8(SYS_FUNC_EN+1) |1); // PCIe MAC enable + RTL_W8(0xcc, RTL_R8(0xcc) & 0xfb); // Mask Write Access for PMC FSM + + if (RT_STATUS_SUCCESS == GET_HAL_INTERFACE(priv)->StopHWHandler(priv)) { + printk("StopHW Succeed\n"); + } + else { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_CLOSE_STOP_HW; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + panic_printk("StopHW Failed\n"); + } + } + else { + //printk("Can't write MACID register\n"); + } + } else +#endif +#ifdef CONFIG_WLAN_HAL_8814AE + if (GET_CHIP_VER(priv)==VERSION_8814A) { + Wlan_HAL_Link(priv); + } + else +#endif + + { + check_chipID_MIMO(priv); + //Exception Case + if ( check_MAC_IO_Enable(priv) ) { +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + if((GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) || (GET_CHIP_VER(priv)==VERSION_8192D) || (GET_CHIP_VER(priv)==VERSION_8812E)) { + RTL_W8(0x1c, RTL_R8(0x1c)& ~BIT(1)); + RTL_W8(CR,0); + RTL_W8(SYS_FUNC_EN+1, RTL_R8(SYS_FUNC_EN+1) & 0xfe); + RTL_W8(SYS_FUNC_EN+1, RTL_R8(SYS_FUNC_EN+1) |1); + } +#endif + rtl8192cd_stop_hw(priv); + } + } + } + else if (TYPE_EMBEDDED == ((priv->pshare->type>>TYPE_SHIFT) & TYPE_MASK) ) { + printk("TYPE_EMBEDDED\n"); + priv->pshare->version_id = VERSION_8881A; +//#ifdef CONFIG_SOC_RTL8881A +#if !defined(NOT_RTK_BSP) + // TODO: Filen_debug, code below is temporary + //Reset Letrx Bus and WL MAC + #if 0 //96D + //REG32(0xB8000010)|= 0x00008000; + #else //8881A + REG32(0xB8000010)|= 0x00003800; + //Enable MAC_System(BIT(0)), MAC_Lextra_Bus(BIT(1)) + REG32(0xB80000DC)= 0x03; + #endif +#endif //CONFIG_SOC_RTL8881A + +#ifdef CONFIG_WLAN_HAL + if (RT_STATUS_SUCCESS == HalAssociateNic(priv, TRUE)) { + printk("HalAssociateNic OK \n"); + } + else { + printk("HalAssociateNic Failed \n"); + } + + GET_HW(priv)->MIMO_TR_hw_support = GET_HAL_INTERFACE(priv)->GetChipIDMIMOHandler(priv); + + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_MAC_IO_ENABLE, (pu1Byte)&bVal); + if ( bVal ) { + if (RT_STATUS_SUCCESS == GET_HAL_INTERFACE(priv)->StopHWHandler(priv)) { + printk("StopHW Succeed\n"); + } + else { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_CLOSE_STOP_HW; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + panic_printk("StopHW Failed\n"); + } + } + else { + //printk("Can't write MACID register\n"); + } + check_chipID_MIMO(priv); +#endif //CONFIG_WLAN_HAL + } + } +/* ==========>> maybe later +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + rtl8192cd_ePhyInit(priv); +*/ + +#ifdef CONFIG_NET_PCI + if (((wdev->type >> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS) { + dev->irq = pdev->irq; + pci_set_drvdata(pdev, dev); + } + else +#endif + { + dev->irq = wdev->irq; + } +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI + dev->base_addr = (unsigned long)wdev->base_addr; + usb_set_intfdata(pusb_intf, dev); + + priv->pshare->pusbintf = pusb_intf; + priv->pshare->pusbdev = interface_to_usbdev(pusb_intf); + priv->pshare->bDriverStopped = TRUE; + +#ifdef CONFIG_RTL_92C_SUPPORT + priv->pshare->bCardDisableWOHSM = FALSE; + priv->pshare->BoardType = BOARD_USB_DONGLE; +#endif + + if (usb_dvobj_init(priv) != SUCCESS) { + rc = -ENOMEM; + goto err_out_free2; + } + + if (rtw_init_drv_sw(priv) != SUCCESS) { + usb_dvobj_deinit(priv); + rc = -ENOMEM; + goto err_out_free2; + } +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI + dev->base_addr = (unsigned long)wdev->base_addr; +#ifdef __ECOS + psdio_func->dev.driver_data = (void *)dev; //for nova +//diag_printf("###%s %d func=%p driver_data=%p dev=%p###\n",__FUNCTION__,__LINE__, psdio_func, psdio_func->dev.driver_data, dev); +#else + sdio_set_drvdata(psdio_func, dev); +#endif + priv->pshare->psdio_func = psdio_func; + priv->pshare->bDriverStopped = TRUE; + + if ((rc = sdio_dvobj_init(priv)) != 0) { + goto err_out_free2; + } + + if (rtw_init_drv_sw(priv) != SUCCESS) { + sdio_dvobj_deinit(priv); + rc = -ENOMEM; + goto err_out_free2; + } + + DisableSdioInterrupt(priv); +#endif // CONFIG_SDIO_HCI + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) +register_driver: +#endif + +#if !defined(__LINUX_2_6__) || defined(CONFIG_COMPAT_NET_DEV_OPS) + dev->open = rtl8192cd_open; + dev->stop = rtl8192cd_close; +#ifdef __KERNEL__ + dev->set_multicast_list = rtl8192cd_set_rx_mode; +#endif + dev->hard_start_xmit = rtl8192cd_start_xmit; + dev->get_stats = rtl8192cd_get_stats; + dev->do_ioctl = rtl8192cd_ioctl; +#ifdef __KERNEL__ + dev->set_mac_address = rtl8192cd_set_hwaddr; +#endif +#ifdef CONFIG_NETDEV_MULTI_TX_QUEUE + dev->select_queue = rtl8192cd_select_queue; +#endif +#else + dev->netdev_ops = &rtl8192cd_netdev_ops; +#endif + +#ifdef CONFIG_RTL8672 + dev->priv_flags = IFF_DOMAIN_WLAN; +#endif + +#ifdef __ECOS +#ifdef CONFIG_SDIO_HCI + dev->isr = NULL; +#else + dev->isr = rtl8192cd_interrupt; +#endif + dev->dsr= interrupt_dsr; + dev->can_xmit = can_xmit; +#endif + +#ifdef __KERNEL__ + +#if defined(NOT_RTK_BSP) && defined(RTK_NL80211) + priv->rtk = rtk; + if(vap_idx < 0) { + if (IS_ROOT_INTERFACE(priv)) { +#ifdef NON_NL80211_AP + rc = register_netdev(dev); +#else + realtek_cfg80211_init(rtk,priv); + realtek_interface_add(priv, rtk, rtk->root_ifname, NL80211_IFTYPE_AP, 0, 0); +#endif + } +#ifdef UNIVERSAL_REPEATER + else { +#ifdef NON_NL80211_WPAS + rc = register_netdev(dev); +#else + #ifdef NON_NL80211_AP + printk("cfg init vxd %x\n", priv->rtk); + realtek_cfg80211_init(rtk, priv); + #endif + realtek_interface_add(priv, rtk, dev->name, NL80211_IFTYPE_STATION, 0, 0); +#endif + } +#endif + } else { +#ifdef NON_NL80211_AP + rc = register_netdev(dev); +#else + realtek_interface_add(priv, rtk, dev->name, NL80211_IFTYPE_AP, 0, 0); +#endif + } +#elif defined(RTK_NL80211) + priv->rtk = rtk; + if(vap_idx < 0) { + if (IS_ROOT_INTERFACE(priv)) //wrt-vxd + { + realtek_cfg80211_init(rtk,priv); + realtek_interface_add(priv, rtk, rtk->root_ifname, NL80211_IFTYPE_STATION, 0, 0); + } +#ifdef UNIVERSAL_REPEATER //wrt-vxd + else + { + priv->dev = dev; + memcpy(dev->dev_addr, GET_ROOT(priv)->pmib->dot11Bss.bssid, 6); + dev->dev_addr[4] = dev->dev_addr[4] + 1; + memcpy(GET_MY_HWADDR, dev->dev_addr, 6); + realtek_interface_add(priv, rtk, dev->name, NL80211_IFTYPE_STATION, 0, 0); + } +#endif + } + else + { + priv->dev = dev; + memcpy(dev->dev_addr, GET_ROOT(priv)->pmib->dot11Bss.bssid, 6); + dev->dev_addr[5] = dev->dev_addr[5] + vap_idx + 1; + memcpy(GET_MY_HWADDR, dev->dev_addr, 6); + realtek_interface_add(priv, rtk, dev->name, NL80211_IFTYPE_AP, 0, 0); + } + printk("%s %d\n", __FUNCTION__, __LINE__); +#else + rc = register_netdev(dev); +#endif + + if (rc) + goto err_out_iomap; +#endif + +#if defined(CONFIG_RG_WLAN_HWNAT_ACCELERATION) && !defined(CONFIG_ARCH_LUNA_SLAVE) + if(dev->name[strlen(dev->name)-2]=='p') //dev->name="wlanX-vapX" + { + switch(dev->name[strlen(dev->name)-1]) + { + case '0': + //printk("#### vap0=%x ####\n",(u32)dev); + wlan_vap_netdev[0]=dev; + break; + case '1': + //printk("#### vap1=%x ####\n",(u32)dev); + wlan_vap_netdev[1]=dev; + break; + case '2': + //printk("#### vap2=%x ####\n",(u32)dev); + wlan_vap_netdev[2]=dev; + break; + case '3': + //printk("#### vap3=%x ####\n",(u32)dev); + wlan_vap_netdev[3]=dev; + break; + } + } + else if(dev->name[strlen(dev->name)-2]=='n') //dev->name="wlanX" + { + printk("#### root=%x ####\n",(u32)dev); + wlan_root_netdev=dev; + } +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) // is root interface +#endif + DEBUG_INFO("Init %s, base_addr=%08lx, irq=%d\n", + dev->name, (unsigned long)dev->base_addr, dev->irq); + +#else // __DRAYTEK_OS__ + regs = (void *)wdev->base_addr; + dev->base_addr = (unsigned long)wdev->base_addr; + priv->pshare->ioaddr = (unsigned long)regs; + +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv)) // is root interface +#endif + DEBUG_INFO("Init %s, base_addr=%08lx\n", + dev->name, (unsigned long)dev->base_addr); + +#endif // __DRAYTEK_OS__ + + +#ifdef CONFIG_PCI_HCI +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) // is root interface +#endif + { +#ifdef CONFIG_NET_PCI + +#if defined(CONFIG_RTL8196C_REVISION_B) || defined(CONFIG_RTL_8196C) + #if defined(CONFIG_NET_PCI) + #define REVR 0xB8000000 + #define RTL8196C_REVISION_A 0x80000001 + #define RTL8196C_REVISION_B 0x80000002 + #endif + if (REG32(REVR) == RTL8196C_REVISION_B) { + REG32(0xb9000354)=0xc940; //Card PCIE PHY initial parameter for rtl8196c revision B + REG32(0xb9000358)=0x24; + for(i=0; i<1000000; i++); + REG32(0xb9000354)=0x4270; + REG32(0xb9000358)=0x25; + for(i=0; i<1000000; i++); + REG32(0xb9000354)=0x019E; //Card PCIE PHY initial parameter for rtl8196c revision B + REG32(0xb9000358)=0x23; + } +#endif + if (((wdev->type >> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS) { + if (cache_size != SMP_CACHE_BYTES) { + panic_printk("%s: PCI cache line size set incorrectly (%i bytes) by BIOS/FW, ", dev->name, cache_size); + if (cache_size > SMP_CACHE_BYTES) { + DEBUG_INFO("expecting %i\n", SMP_CACHE_BYTES); + } else { + DEBUG_INFO("correcting to %i\n", SMP_CACHE_BYTES); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, SMP_CACHE_BYTES >> 2); + } + } + + /* enable busmastering and memory-write-invalidate */ + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + if (!(pci_command & PCI_COMMAND_INVALIDATE)) { + pci_command |= PCI_COMMAND_INVALIDATE; + pci_write_config_word(pdev, PCI_COMMAND, pci_command); + } + pci_set_master(pdev); + } +#endif + } +#endif // CONFIG_PCI_HCI + +#ifdef __ECOS +#ifdef RTLWIFINIC_GPIO_CONTROL +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) //mark_ecos +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) // is root interface +#endif + RTLWIFINIC_GPIO_init_priv(priv); +#endif +#endif +#else // !__ECOS +#ifdef _INCLUDE_PROC_FS_ +#ifdef __KERNEL__ + rtl8192cd_proc_init(dev); +#ifdef PERF_DUMP + { + #include + + struct proc_dir_entry *res; + res = create_proc_entry("perf_dump", 0, NULL); + if (res) { + res->read_proc = read_perf_dump; + res->write_proc = flush_perf_dump; + res->data = (void *)dev; + } + } +#endif +#endif +#endif +#endif + +#ifdef CONFIG_RTL_VLAN_8021Q + if(strcmp(dev->name,"wlan0")==0) + dev->vlan_member_map=WLAN0_MASK_BIT; + else if(strcmp(dev->name,"wlan1")==0) + dev->vlan_member_map=WLAN1_MASK_BIT; +#endif + + // set some default value of mib + set_mib_default(priv); + +#if defined(RTK_NL80211) && defined(UNIVERSAL_REPEATER) + if(IS_VXD_INTERFACE(priv)) + { + OPMODE = WIFI_STATION_STATE; + } +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) // is root interface +#endif + { +#ifndef __DRAYTEK_OS__ +#ifdef WDS + wds_num = (priv->pshare->type>>WDS_SHIFT) & WDS_MASK; + strcpy(baseDevName, dev->name); + + for (i=0; iopen = rtl8192cd_open; + dev->stop = rtl8192cd_close; + dev->hard_start_xmit = rtl8192cd_start_xmit; + dev->get_stats = rtl8192cd_get_stats; +#ifdef __KERNEL__ + dev->set_mac_address = rtl8192cd_set_hwaddr; +#endif +#else + dev->netdev_ops = &rtl8192cd_netdev_ops; +#endif + +#ifdef CONFIG_RTL8672 + dev->priv_flags = IFF_DOMAIN_WLAN; +#endif + +#ifdef __ECOS + //dev->isr = rtl8192cd_interrupt; + //dev->dsr= interrupt_dsr; + dev->can_xmit = can_xmit; +#endif + + priv->wds_dev[i] = dev; + strcpy(dev->name, baseDevName); + strcat(dev->name, "-wds%d"); + +#ifdef NETDEV_NO_PRIV + priv_wds = (struct rtl8192cd_wds_priv*)netdev_priv(dev); + priv_wds->wlan_priv = priv; +#else + dev->priv = priv; +#endif +#ifdef __KERNEL__ + rc = register_netdev(dev); + if (rc) { + printk(KERN_ERR "register_netdev() wds error!\n"); + goto err_out_dev; + } +#endif + +#if defined(CONFIG_RG_WLAN_HWNAT_ACCELERATION) && !defined(CONFIG_ARCH_LUNA_SLAVE) + if(dev->name[strlen(dev->name)-2]=='s') //dev->name="wlanX-wdsX" + { + int idx=dev->name[strlen(dev->name)-1]-'0'; + if((idx>=0)&&(idx<=7)) + { + wlan_wds_netdev[idx]=dev; + } + } +#endif + + + } +#endif // WDS + +#ifdef CONFIG_RTK_MESH + mesh_num = (priv->pshare->type>>MESH_SHIFT) & MESH_MASK; + +#ifndef WDS + strcpy(baseDevName, dev->name); +#endif + if(mesh_num>0) {/*the first wlan interface with mesh enabled*/ + if(tmp_priv == NULL) + { + GET_MIB(priv)->dot1180211sInfo.mesh_enable = 1; + dev = alloc_etherdev(0); // mesh allocate ethernet device BUT don't have priv memory (Because share root priv) + if (!dev) { + printk(KERN_ERR "alloc_etherdev() mesh error!\n"); + rc = -ENOMEM; + goto err_out_dev; + } + dev->base_addr = 1; +#if !defined(__LINUX_2_6__) || defined(CONFIG_COMPAT_NET_DEV_OPS) + dev->open = rtl8192cd_open; + dev->stop = rtl8192cd_close; + dev->hard_start_xmit = mesh_start_xmit; + dev->get_stats = rtl8192cd_get_stats; + dev->set_mac_address = rtl8192cd_set_hwaddr; + dev->do_ioctl = rtl8192cd_ioctl; +#else + dev->netdev_ops = &mesh_netdev_ops; +#endif + +#ifdef CONFIG_RTL8672 + dev->priv_flags = IFF_DOMAIN_WLAN; +#endif + + priv->mesh_dev = dev; // NO priv zone dev + strcpy(dev->name, "wlan-msh"); + + dev->priv = priv; // mesh priv pointer to root's priv + rc = register_netdev(dev); + + if (rc) { + printk(KERN_ERR "register_netdev() mesh error!\n"); + goto err_out_dev; + } + } + + if(tmp_priv == NULL) { + tmp_priv = priv; + } + else { + priv->mesh_dev = tmp_priv->mesh_dev; + tmp_priv->mesh_priv_sc = priv; + priv->mesh_priv_sc = tmp_priv; + } + priv->mesh_priv_first = priv; + } // end of if(mesh_num>0) + + priv->RreqEnd = 0; + priv->RreqBegin = 0; + + pann_mpp_tb = (struct mpp_tb*)kmalloc(sizeof(struct mpp_tb), GFP_ATOMIC); + if(!pann_mpp_tb) + { + rc = -ENOMEM; + printk("allocate pann_mpp_tb error!!\n"); + goto err_out_dev; + } + init_mpp_pool(pann_mpp_tb); + proxy_table = (struct hash_table*)kmalloc(sizeof(struct hash_table), GFP_ATOMIC); + if(!proxy_table) + { + rc = -ENOMEM; + printk("allocate proxy_table error!!\n"); + goto err_out_dev; + } + memset((void*)proxy_table, 0, sizeof(struct hash_table)); + +#ifdef PU_STANDARD + //pepsi + proxyupdate_table = (struct hash_table*)kmalloc(sizeof(struct hash_table), GFP_ATOMIC); + if(!proxyupdate_table) + { + rc = -ENOMEM; + printk("allocate proxyupdate_table error!!\n"); + goto err_out_dev; + } + memset((void*)proxyupdate_table, 0, sizeof(struct hash_table)); +#endif + + pathsel_queue = (DOT11_QUEUE2 *)kmalloc((sizeof(DOT11_QUEUE2)), GFP_ATOMIC); + if (!pathsel_queue) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for PATHSELECTION_QUEUE (size %d)\n", sizeof(DOT11_QUEUE)); + goto err_out_dev; + } + memset((void *)pathsel_queue, 0, sizeof (DOT11_QUEUE2)); +#ifdef _11s_TEST_MODE_ + receiver_queue = (DOT11_QUEUE2 *)kmalloc((sizeof(DOT11_QUEUE2)), GFP_ATOMIC); + if (!receiver_queue) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for receiver_queue (size %d)\n", sizeof(DOT11_QUEUE)); + goto err_out_dev; + } + memset((void *)receiver_queue, 0, sizeof (DOT11_QUEUE2)); + pgalileo_poll = (struct Galileo_poll *) kmalloc((sizeof( struct Galileo_poll)), GFP_ATOMIC); + if (!pgalileo_poll) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for pgalileo_poll (size %d)\n", sizeof(struct Galileo_poll)); + goto err_out_dev; + } +#endif + pathsel_table = (struct hash_table*)kmalloc(sizeof(struct hash_table), GFP_ATOMIC); + if(!pathsel_table) + { + rc = -ENOMEM; + printk("allocate pathsel_table error!!\n"); + goto err_out_dev; + } + memset((void*)pathsel_table, 0, sizeof(struct hash_table)); + + mesh_rreq_retry_queue = (struct hash_table*)kmalloc(sizeof(struct hash_table), GFP_ATOMIC); + if(!mesh_rreq_retry_queue) + { + rc = -ENOMEM; + printk("allocate mesh_rreq_retry_queue error!!\n"); + goto err_out_dev; + } + memset((void*)mesh_rreq_retry_queue, 0, sizeof(struct hash_table)); + + rc = init_hash_table(proxy_table, PROXY_TABLE_SIZE, MACADDRLEN, sizeof(struct proxy_table_entry), crc_hashing, search_default, insert_default, delete_default,traverse_default); + if(rc == HASH_TABLE_FAILED) + { + printk("init_hash_table \"proxy_table\" error!!\n"); + } + +#ifdef PU_STANDARD + //pepsi + rc = init_hash_table(proxyupdate_table, 8, sizeof(UINT8), sizeof(struct proxyupdate_table_entry), PU_hashing, search_default, insert_default, delete_default,traverse_default); + if(rc == HASH_TABLE_FAILED) + { + printk("init_hash_table \"proxyupdate_table\" error!!\n"); + } +#endif + rc = init_hash_table(pathsel_table, 8, MACADDRLEN, sizeof(struct path_sel_entry), crc_hashing, search_default, insert_default, delete_default,traverse_default); + if(rc == HASH_TABLE_FAILED) + { + printk("init_hash_table \"pathsel_table\" error!!\n"); + } + + rc = init_hash_table(mesh_rreq_retry_queue, DATA_SKB_BUFFER_SIZE, MACADDRLEN, sizeof(struct mesh_rreq_retry_entry), crc_hashing, search_default, insert_default, delete_default,traverse_default); + if(rc == HASH_TABLE_FAILED) + { + printk("init_hash_table \"mesh_rreq_retry_queue\" error!!\n"); + } + + for(i = 0; i < (1 << mesh_rreq_retry_queue->table_size_power); i++) + { + (((struct mesh_rreq_retry_entry*)(mesh_rreq_retry_queue->entry_array[i].data))->ptr) = (struct pkt_queue*)kmalloc(sizeof(struct pkt_queue), GFP_ATOMIC); + if (!(((struct mesh_rreq_retry_entry*)(mesh_rreq_retry_queue->entry_array[i].data))->ptr)) { + rc = -ENOMEM; + printk(KERN_ERR "Can't kmalloc for mesh_rreq_retry_entry (size %d)\n", sizeof(struct pkt_queue)); + goto err_out_dev; + } + memset((void *)((((struct mesh_rreq_retry_entry*)(mesh_rreq_retry_queue->entry_array[i].data))->ptr)), 0, sizeof (struct pkt_queue)); + } + +#ifdef PU_STANDARD + priv->proxyupdate_table = proxyupdate_table; +#endif +#ifdef _11s_TEST_MODE_ + priv->receiver_queue = receiver_queue; + priv->pshare->galileo_poll = pgalileo_poll ; +#endif + priv->proxy_table = proxy_table; + priv->pathsel_queue = pathsel_queue; + priv->pann_mpp_tb = pann_mpp_tb; + priv->pathsel_table = pathsel_table; + priv->mesh_rreq_retry_queue = mesh_rreq_retry_queue; + //========================================================= +#endif // CONFIG_RTK_MESH + + +#endif // __DRAYTEK_OS__ + + + //3 Require Descriptor Memory + //Method: + // 1.) Static Memory + // 2.) Allocate memory from OS +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { +#ifdef CONFIG_NET_PCI + if (!IS_PCIBIOS_TYPE) +#endif + { +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE + _GET_HAL_DATA(priv)->desc_dma_buf = desc_buf[priv->pshare->wlandev_idx]; + _GET_HAL_DATA(priv)->desc_dma_buf_len = DESC_DMA_PAGE_SIZE; +#else + _GET_HAL_DATA(priv)->desc_dma_buf = desc_buf; + _GET_HAL_DATA(priv)->desc_dma_buf_len = DESC_DMA_PAGE_SIZE; +#endif //CONCURRENT_MODE +#else + #ifdef __DRAYTEK_OS__ + page_ptr = rtl8185_malloc(DESC_DMA_PAGE_SIZE, 1); // allocate non-cache buffer + #else + page_ptr = kmalloc(DESC_DMA_PAGE_SIZE, GFP_KERNEL); + #endif + + _GET_HAL_DATA(priv)->desc_dma_buf = page_ptr; + + if (page_ptr == NULL) { + rc = -ENOMEM; + panic_printk(KERN_ERR "can't allocate descriptior page, abort!\n"); + _GET_HAL_DATA(priv)->desc_dma_buf_len = 0; + goto err_out_dev; + } else { + _GET_HAL_DATA(priv)->desc_dma_buf_len = DESC_DMA_PAGE_SIZE; + } +#endif //PRIV_STA_BUF + } + if (GET_HAL_INTERFACE(priv)->InitHCIDMAMemHandler(priv) == RT_STATUS_FAILURE){ + GET_HAL_INTERFACE(priv)->StopSWHandler(priv); + rc = -ENOMEM; + printk(KERN_ERR "can't allocate descriptior page, abort!\n"); +#ifndef PRIV_STA_BUF + if (page_ptr != NULL){ + kfree(page_ptr); + _GET_HAL_DATA(priv)->desc_dma_buf_len = 0; + _GET_HAL_DATA(priv)->desc_dma_buf = NULL; + } +#endif + goto err_out_dev; + } + } else +#endif // CONFIG_WLAN_HAL + { +#ifdef PRIV_STA_BUF +#ifdef CONCURRENT_MODE + page_ptr = (unsigned char *) + (((unsigned long)&desc_buf[priv->pshare->wlandev_idx]) + (PAGE_SIZE - (((unsigned long)&desc_buf[priv->pshare->wlandev_idx]) & (PAGE_SIZE-1)))); + phw->ring_buf_len = ((unsigned long)&desc_buf[priv->pshare->wlandev_idx]) + (sizeof(desc_buf)/NUM_WLAN_IFACE) - ((unsigned long)page_ptr); + phw->ring_dma_addr = virt_to_bus(page_ptr); + page_ptr = (unsigned char *)KSEG1ADDR(page_ptr); +#else + page_ptr = (unsigned char *) + (((unsigned long)desc_buf) + (PAGE_SIZE - (((unsigned long)desc_buf) & (PAGE_SIZE-1)))); + phw->ring_buf_len = (unsigned long)desc_buf + sizeof(desc_buf) - (unsigned long)page_ptr; + phw->ring_dma_addr = virt_to_bus(page_ptr); + page_ptr = (unsigned char *)KSEG1ADDR(page_ptr); +#endif +#else +#ifdef CONFIG_NET_PCI + if (IS_PCIBIOS_TYPE) { + dma_addr_t addr; + // Avoid the combination of (64-bit dma_addr_t + big endian) to get invalid phw->ring_dma_addr + page_ptr = pci_alloc_consistent(priv->pshare->pdev, DESC_DMA_PAGE_SIZE, &addr); + phw->ring_dma_addr = addr; + } else +#endif + { +#ifdef __DRAYTEK_OS__ + page_ptr = rtl8185_malloc(DESC_DMA_PAGE_SIZE, 1); // allocate non-cache buffer +#else + page_ptr = kmalloc(DESC_DMA_PAGE_SIZE, GFP_KERNEL); +#endif + } + + if (page_ptr == NULL) { + rc = -ENOMEM; + panic_printk(KERN_ERR "can't allocate descriptior page, abort!\n"); + goto err_out_dev; + } + + phw->alloc_dma_buf = (unsigned long)page_ptr; +#if defined(NOT_RTK_BSP) + page_align_phy = (PAGE_SIZE - (((unsigned long)page_ptr) & (PAGE_SIZE-1))); +#endif + page_ptr = (unsigned char *) + (((unsigned long)page_ptr) + (PAGE_SIZE - (((unsigned long)page_ptr) & (PAGE_SIZE-1)))); + phw->ring_buf_len = phw->alloc_dma_buf + DESC_DMA_PAGE_SIZE - ((unsigned long)page_ptr); +#if defined(NOT_RTK_BSP) + phw->ring_dma_addr = phw->ring_dma_addr + page_align_phy; +#else + phw->ring_dma_addr = virt_to_bus(page_ptr)+CONFIG_LUNA_SLAVE_PHYMEM_OFFSET; +#endif + +#ifdef __MIPSEB__ + page_ptr = (unsigned char *)KSEG1ADDR(page_ptr); +#endif +#endif + + DEBUG_INFO("page_ptr=%lx, size=%ld\n", (unsigned long)page_ptr, (unsigned long)DESC_DMA_PAGE_SIZE); + phw->ring_virt_addr = (unsigned long)page_ptr; + } +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_RTL8190_PRIV_SKB + init_priv_skb_buf(priv); +#endif + +#ifdef PRIV_STA_BUF + init_priv_sta_buf(priv); +#endif + +#ifdef CONFIG_RTL_92D_DMDP + if_priv[priv->pshare->wlandev_idx] = (u32)priv; +#endif + +#ifdef RX_LOOP_LIMIT + if (GET_CHIP_VER(priv) == VERSION_8812E) + priv->pmib->dot11StationConfigEntry.limit_rxloop = 150; +#endif + } + + INIT_LIST_HEAD(&priv->asoc_list); // init assoc_list first because webs may get sta_num even it is not open, + INIT_LIST_HEAD(&priv->wlan_acl_list); + /* The following locks are used in proc file, so init just now and don't init in open */ +#ifdef SMP_SYNC +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef __ECOS + _rtw_mutex_init(&(priv->asoc_list_lock)); +#else + spin_lock_init(&(priv->asoc_list_lock)); +#endif +#endif + spin_lock_init(&(priv->wlan_acl_list_lock)); +#endif + // and it will cause exception if it is not init, david+2008-03-05 +#ifdef EN_EFUSE + rc = ReadAdapterInfo8192CE(priv); + if (rc) + goto err_out_dev; +#endif + printk("=====>>EXIT rtl8192cd_init_one <<=====\n"); + +#if defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) + if(priv && RTL_R32(GPIO_PIN_CTRL)) + { +// printk("<%s>LZQ: GPIO_PIN_CTRL[0x%x] \n",__FUNCTION__, GPIO_PIN_CTRL); +// printk("<%s>LZQ: before read tmpReg[0x%x] \n",__FUNCTION__, RTL_R32(GPIO_PIN_CTRL)); + RTL_W32(GPIO_PIN_CTRL,RTL_R32(GPIO_PIN_CTRL)&(0x0)); + printk("<%s>LZQ: after read tmpReg[0x%x] \n",__FUNCTION__, RTL_R32(GPIO_PIN_CTRL)); + } +#endif + +#ifdef __KERNEL__ + return 0; +#else + //return (void *)dev; + return (void *)tmp_dev; +#endif + +err_out_dev: + + dev = priv->dev; +#ifdef _INCLUDE_PROC_FS_ + rtl8192cd_proc_remove(dev); +#endif +#ifdef __KERNEL__ +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) // is root interface +#endif + { +#ifdef EN_EFUSE + for (i = 0; i < 2; i++) + if (priv->EfuseMap[i]) + kfree(priv->EfuseMap[i]); + if (priv->EfuseCmd) + kfree(priv->EfuseCmd); +#endif + +#ifndef __DRAYTEK_OS__ +#ifdef WDS + wds_num = (priv->pshare->type>>WDS_SHIFT) & WDS_MASK; + for (i=0; iwds_dev[i]) { + unregister_netdev(priv->wds_dev[i]); +#ifdef __LINUX_2_6__ + free_netdev(priv->wds_dev[i]); +#else + kfree(priv->wds_dev[i]); +#endif + } + } +#endif // WDS + +#ifdef CONFIG_RTK_MESH + mesh_num = (priv->pshare->type>>MESH_SHIFT) & MESH_MASK; + if(mesh_num>0) { + if (priv->mesh_dev) { + unregister_netdev(priv->mesh_dev); +#ifdef __LINUX_2_6__ + free_netdev(priv->mesh_dev); +#else + kfree(priv->mesh_dev); +#endif + } + } +#endif // CONFIG_RTK_MESH +#endif // !__DRAYTEK_OS__ + } + + unregister_netdev(dev); + +err_out_iomap: +#endif // __KERNEL__ + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_NET_PCI + if (((wdev->type >> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS) { +#ifndef USE_IO_OPS + iounmap(regs); +#endif + } + +err_out_res: + + if (((wdev->type >> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS) { +#ifdef USE_IO_OPS + release_region(dev->base_addr, pci_resource_len(pdev, 0)); +//// release_region(dev->base_addr, pci_resource_len(pdev, 2)); +#else + pci_release_regions(pdev); +#endif + } + +err_out_disable: + + if (((wdev->type >> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS) + pci_disable_device(pdev); +#endif // CONFIG_NET_PCI +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI + rtw_free_drv_sw(priv); + usb_dvobj_deinit(priv); +#endif + +#ifdef CONFIG_SDIO_HCI + rtw_free_drv_sw(priv); + sdio_dvobj_deinit(priv); +#endif + +err_out_free2: + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + HalDisAssociateNic(priv, TRUE); + } +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (!IS_ROOT_INTERFACE(priv)) { // is a vxd or vap +#ifdef UNIVERSAL_REPEATER + if (vap_idx < 0) // create for vxd + GET_VXD_PRIV(wdev->priv) = NULL; +#endif +#ifdef MBSSID + if (vap_idx >= 0) // create for vap + GET_ROOT(priv)->pvap_priv[vap_idx] = NULL; +#endif + } else +#endif + wdev->priv = NULL; + +err_out_free: + + if (pmib){ +#ifdef RTL8192CD_VARIABLE_USED_DMEM + rtl8192cd_dmem_free(PMIB, pmib); +#else + kfree(pmib); +#endif + } + +#ifdef CONFIG_RTK_MESH + if(proxy_table) + { + remove_hash_table(proxy_table); + kfree(proxy_table); + } + if(mesh_rreq_retry_queue) + { + for (i=0; i< (1 << mesh_rreq_retry_queue->table_size_power); i++) + { + if(((struct mesh_rreq_retry_entry*)(mesh_rreq_retry_queue->entry_array[i].data))->ptr) + { + kfree(((struct mesh_rreq_retry_entry*)(mesh_rreq_retry_queue->entry_array[i].data))->ptr); + } + } + remove_hash_table(mesh_rreq_retry_queue); + kfree(mesh_rreq_retry_queue); + } + + // add by chuangch 2007.09.13 + if(pathsel_table) + { + remove_hash_table(pathsel_table); + kfree(pathsel_table); + } + + if(pann_mpp_tb) + kfree(pann_mpp_tb); + +#ifdef PU_STANDARD + if (proxyupdate_table) { + remove_hash_table(proxyupdate_table); + kfree(proxyupdate_table); + } +#endif + if (pathsel_queue) + kfree(pathsel_queue); +#ifdef _11s_TEST_MODE_ + if (receiver_queue) + kfree(receiver_queue); + if (pgalileo_poll) + kfree(pgalileo_poll); +#endif +#endif // CONFIG_RTK_MESH + + if (pevent_queue) + kfree(pevent_queue); +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (wapiEvent_queue) + kfree(wapiEvent_queue); + #if 0 //defined(MBSSID) + if (wapiVapEvent_queue) + kfree(wapiVapEvent_queue); + #endif +#endif + +#ifndef PRIV_STA_BUF + if (phw) + kfree(phw); + if (pshare) // david + kfree(pshare); + if (pwlan_hdr_poll) + kfree(pwlan_hdr_poll); + if (pwlanllc_hdr_poll) + kfree(pwlanllc_hdr_poll); + if (pwlanbuf_poll) + kfree(pwlanbuf_poll); + if (pwlanicv_poll) + kfree(pwlanicv_poll); + if (pwlanmic_poll) + kfree(pwlanmic_poll); +#endif + if (pwlan_acl_poll) + kfree(pwlan_acl_poll); + +#if defined(CONFIG_RTK_MESH) && defined(_MESH_ACL_ENABLE_) // below code copy above ACL code + if (pmesh_acl_poll) + kfree(pmesh_acl_poll); +#endif + + if (Eap_packet) + kfree(Eap_packet); +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + if (wpa_global_info) + kfree(wpa_global_info); +#endif + if (site_survey) + free_site_survey_res(site_survey); + +#ifdef __LINUX_2_6__ + free_netdev(dev); +#else + kfree(dev); +#endif + + printk("=====>>EXIT rtl8192cd_init_one2(%d) <<=====\n", rc); + +#ifdef __KERNEL__ + return rc; +#else + return NULL; +#endif +} + +#ifdef RTK_NL80211 +void rtl8192cd_init_one_cfg80211(struct rtknl *rtk) +{ + int wlan_index=0; + + printk("roo_ifname = %s, rtk->num_vif=%d \n", rtk->root_ifname, rtk->num_vif); + + if(!strcmp(rtk->root_ifname, "wlan1")) //if it is second wlan phy + wlan_index =1; + + rtl8192cd_init_one(NULL, NULL, &wlan_device[wlan_index], rtk->num_vif); + +} +#endif + +void rtl8192cd_deinit_one(struct rtl8192cd_priv *priv) +{ + struct net_device *dev; +#if defined(WDS) || defined(MBSSID) || defined(CONFIG_RTK_MESH) || defined(EN_EFUSE) + int i; +#endif +#if defined(WDS) || defined(CONFIG_RTK_MESH) + int num; +#endif +#ifdef UNIVERSAL_REPEATER + struct rtl8192cd_priv *vxd_priv = NULL; +#endif +#ifdef MBSSID + struct rtl8192cd_priv *vap_priv = NULL; +#endif + +#ifdef RTK_NL80211 + struct rtknl *rtk = NULL; +#endif + + if (NULL == priv) { + printk("%s: priv should NOT be a NULL pointer!\n", __func__); + return; + } else { + printk("=====>> INSIDE %s <<=====\n", __func__); + } + +#ifdef RTK_NL80211 + rtk = priv->rtk; +#endif + +#ifdef WDS + num = (priv->pshare->type >> WDS_SHIFT) & WDS_MASK; + for (i = 0; i < num; i++) { + unregister_netdev(priv->wds_dev[i]); +#ifndef NETDEV_NO_PRIV + priv->wds_dev[i]->priv = NULL; +#endif +#ifdef __LINUX_2_6__ + free_netdev(priv->wds_dev[i]); +#else + kfree(priv->wds_dev[i]); +#endif + } +#endif // WDS + +#ifdef CONFIG_RTK_MESH + num = (priv->pshare->type >> MESH_SHIFT) & MESH_MASK; + if (num > 0) { // mesh_num is always 0 or 1 + unregister_netdev(priv->mesh_dev); + priv->mesh_dev->priv = NULL; // mesh priv pointer to root's priv +#ifdef __LINUX_2_6__ + free_netdev(priv->mesh_dev); +#else + kfree(priv->mesh_dev); +#endif + } +#endif // CONFIG_RTK_MESH + +#ifdef UNIVERSAL_REPEATER + vxd_priv = priv->pvxd_priv; + if (vxd_priv) { +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + realtek_interface_del(vxd_priv, rtk, vxd_priv->dev); +#else + unregister_netdev(vxd_priv->dev); +#endif + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + _rtw_mutex_free(&(priv->asoc_list_lock)); +#endif +#ifdef _INCLUDE_PROC_FS_ + rtl8192cd_proc_remove(vxd_priv->dev); +#endif +#ifdef RTL8192CD_VARIABLE_USED_DMEM + rtl8192cd_dmem_free(PMIB, vxd_priv->pmib); +#else + kfree(vxd_priv->pmib); +#endif + kfree(vxd_priv->pevent_queue); +#ifdef CONFIG_RTL_WAPI_SUPPORT + kfree(vxd_priv->wapiEvent_queue); +#endif + kfree(vxd_priv->pwlan_acl_poll); + kfree(vxd_priv->Eap_packet); +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + kfree(vxd_priv->wpa_global_info); +#endif + free_site_survey_res(vxd_priv->site_survey); +#if defined(CONFIG_RTK_MESH) && defined(_MESH_ACL_ENABLE_) + kfree(vxd_priv->pmesh_acl_poll); +#endif +#ifdef __LINUX_2_6__ + free_netdev(vxd_priv->dev); +#else + kfree(vxd_priv->dev); +#endif + priv->pvxd_priv = NULL; + } +#endif // UNIVERSAL_REPEATER + +#ifdef MBSSID + for (i = 0; i < RTL8192CD_NUM_VWLAN; i++) { + vap_priv = priv->pvap_priv[i]; + if (vap_priv) { +#if defined(RTK_NL80211) && !defined(NON_NL80211_AP) + realtek_interface_del(vap_priv, rtk, vap_priv->dev); +#else + unregister_netdev(vap_priv->dev); +#endif +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + _rtw_mutex_free(&(priv->asoc_list_lock)); +#endif +#ifdef _INCLUDE_PROC_FS_ + rtl8192cd_proc_remove(vap_priv->dev); +#endif +#ifdef RTL8192CD_VARIABLE_USED_DMEM + rtl8192cd_dmem_free(PMIB, vap_priv->pmib); +#else + kfree(vap_priv->pmib); +#endif + kfree(vap_priv->pevent_queue); +#ifdef CONFIG_RTL_WAPI_SUPPORT + kfree(vap_priv->wapiEvent_queue); +#endif + kfree(vap_priv->pwlan_acl_poll); + kfree(vap_priv->Eap_packet); +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + kfree(vap_priv->wpa_global_info); +#endif +#ifdef MULTI_MAC_CLONE + free_site_survey_res(vap_priv->site_survey); +#endif +#if defined(CONFIG_RTK_MESH) && defined(_MESH_ACL_ENABLE_) + kfree(vap_priv->pmesh_acl_poll); +#endif +#ifdef __LINUX_2_6__ + free_netdev(vap_priv->dev); +#else + kfree(vap_priv->dev); +#endif + priv->pvap_priv[i] = NULL; + } + } +#endif // MBSSID + + // root interface clean +#ifdef CONFIG_RTL_CUSTOM_PASSTHRU + if (priv->pWlanDev) { + unregister_netdev(priv->pWlanDev); +#ifdef __LINUX_2_6__ + free_netdev(priv->pWlanDev); +#else + kfree(priv->pWlanDev); +#endif + priv->pWlanDev = NULL; + } +#endif + dev = priv->dev; + +#ifdef RTK_NL80211 +#ifndef NON_NL80211_AP + realtek_interface_del(priv, rtk, dev); +#endif + realtek_cfg80211_deinit(priv, rtk); + realtek_cfg80211_destroy(rtk); +#else + unregister_netdev(dev); +#endif +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + _rtw_mutex_free(&(priv->asoc_list_lock)); +#endif +#ifdef _INCLUDE_PROC_FS_ + rtl8192cd_proc_remove(dev); +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_NET_PCI +#ifdef USE_IO_OPS + release_region(dev->base_addr, pci_resource_len(priv->pshare->pdev, 0)); +#else + iounmap((void *)dev->base_addr); + pci_release_regions(priv->pshare->pdev); +#endif + pci_disable_device(priv->pshare->pdev); +#endif // CONFIG_NET_PCI + +#ifndef PRIV_STA_BUF +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { +#ifdef CONFIG_NET_PCI + if (!IS_PCIBIOS_TYPE) +#endif + { + if (_GET_HAL_DATA(priv)->desc_dma_buf) { + kfree(_GET_HAL_DATA(priv)->desc_dma_buf); + _GET_HAL_DATA(priv)->desc_dma_buf = NULL; + } + } + GET_HAL_INTERFACE(priv)->StopSWHandler(priv); + } else +#endif // CONFIG_WLAN_HAL + { +#ifdef CONFIG_NET_PCI + if (IS_PCIBIOS_TYPE) { + unsigned long page_align_phy = (PAGE_SIZE - (((unsigned long)priv->pshare->phw->alloc_dma_buf) & (PAGE_SIZE-1))); + pci_free_consistent(priv->pshare->pdev, DESC_DMA_PAGE_SIZE, (void*)priv->pshare->phw->alloc_dma_buf, + (dma_addr_t)(priv->pshare->phw->ring_dma_addr-page_align_phy)); + } else +#endif + kfree((void *)priv->pshare->phw->alloc_dma_buf); + } +#endif // !PRIV_STA_BUF +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI + rtw_free_drv_sw(priv); + usb_dvobj_deinit(priv); +#endif +#ifdef CONFIG_SDIO_HCI + rtw_free_drv_sw(priv); + sdio_dvobj_deinit(priv); +#endif + +#ifdef MBSSID +#if defined(__KERNEL__) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)) + _rtw_mutex_free(&priv->pshare->mbssid_lock); +#endif +#endif // MBSSID + +#ifdef RTL8192CD_VARIABLE_USED_DMEM + rtl8192cd_dmem_free(PMIB, priv->pmib); +#else + kfree(priv->pmib); +#endif + kfree(priv->pevent_queue); +#ifdef CONFIG_RTL_WAPI_SUPPORT + kfree(priv->wapiEvent_queue); +#endif + kfree(priv->pwlan_acl_poll); + kfree(priv->Eap_packet); +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + kfree(priv->wpa_global_info); +#endif + free_site_survey_res(priv->site_survey); + +#ifdef P2P_SUPPORT + if(priv->p2pPtr) + kfree(priv->p2pPtr); +#endif + +#ifdef CONFIG_RTK_MESH + remove_hash_table(priv->proxy_table); + kfree(priv->proxy_table); + + remove_hash_table(priv->pathsel_table); + kfree(priv->pathsel_table); + + for (i = 0; i < (1 << priv->mesh_rreq_retry_queue->table_size_power); i++) { + if (((struct mesh_rreq_retry_entry*)(priv->mesh_rreq_retry_queue->entry_array[i].data))->ptr) + kfree(((struct mesh_rreq_retry_entry*)(priv->mesh_rreq_retry_queue->entry_array[i].data))->ptr); + } + remove_hash_table(priv->mesh_rreq_retry_queue); + kfree(priv->mesh_rreq_retry_queue); +#ifdef PU_STANDARD + remove_hash_table(priv->proxyupdate_table); + kfree(priv->proxyupdate_table); +#endif + kfree(priv->pann_mpp_tb); + kfree(priv->pathsel_queue); + +#ifdef _11s_TEST_MODE_ + kfree(priv->receiver_queue); + + for (i = 0; i < AODV_RREQ_TABLE_SIZE; i++) + del_timer(&priv->pshare->galileo_poll->node[i].data.expire_timer); + + kfree(priv->pshare->galileo_poll); +#endif +#ifdef _MESH_ACL_ENABLE_ + kfree(priv->pmesh_acl_poll); +#endif +#endif // CONFIG_RTK_MESH + +#ifndef PRIV_STA_BUF + kfree(priv->pshare->pwlan_hdr_poll); + kfree(priv->pshare->pwlanllc_hdr_poll); + kfree(priv->pshare->pwlanbuf_poll); + kfree(priv->pshare->pwlanicv_poll); + kfree(priv->pshare->pwlanmic_poll); + kfree(priv->pshare->phw); + kfree(priv->pshare); // david +#endif + +#ifdef EN_EFUSE + for( i = 0 ; i < 2 ; i++ ) + kfree(priv->EfuseMap[i]); + kfree(priv->EfuseCmd); +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + HalDisAssociateNic(priv, TRUE); + } +#endif + +#ifdef __LINUX_2_6__ + free_netdev(dev); +#else + kfree(dev); +#endif + printk("=====>> EXIT %s <<=====\n", __func__); +} + + +#if 0//def CONFIG_RTL_STP +extern int rtl865x_wlanIF_Init(struct net_device *dev); +static int rtl_pseudo_dev_set_hwaddr(struct net_device *dev, void *addr) +{ + unsigned long flags; + int i; + unsigned char *p; + + p = ((struct sockaddr *)addr)->sa_data; + local_irq_save(flags); + for (i = 0; idev_addr[i] = p[i]; + } + local_irq_restore(flags); + return SUCCESS; +} + +#if defined(__LINUX_2_6__) && !defined(CONFIG_COMPAT_NET_DEV_OPS) +static const struct net_device_ops rtl8192cd_rtl_pseudodev_ops = { + .ndo_open = rtl8192cd_open, + .ndo_stop = rtl8192cd_close, + .ndo_set_mac_address = rtl_pseudo_dev_set_hwaddr, + .ndo_get_stats = rtl8192cd_get_stats, + .ndo_do_ioctl = rtl8192cd_ioctl, + .ndo_start_xmit = rtl8192cd_start_xmit, +}; +#endif + +void rtl_pseudo_dev_init(void* priv) +{ + struct net_device *dev; + +/* printk("[%s][%d] priv of %s\n", __FUNCTION__, __LINE__, ((struct rtl8192cd_priv*)priv)->dev->name);*/ + dev = alloc_etherdev(0); + if (dev == NULL) { + printk("alloc_etherdev() pseudo port5 error!\n"); + return; + } + +#if !defined(__LINUX_2_6__) || defined(CONFIG_COMPAT_NET_DEV_OPS) + dev->open = rtl8192cd_open; + dev->stop = rtl8192cd_close; + dev->hard_start_xmit = rtl8192cd_start_xmit; + dev->get_stats = rtl8192cd_get_stats; + dev->do_ioctl = rtl8192cd_ioctl; + dev->set_mac_address = rtl_pseudo_dev_set_hwaddr; +#else + dev->netdev_ops = &rtl8192cd_rtl_pseudodev_ops; +#endif + dev->priv = priv; + strcpy(dev->name, "port5"); + memcpy((char*)dev->dev_addr,"\x00\xe0\x4c\x81\x86\x86", MACADDRLEN); + if (register_netdev(dev)) { + printk(KERN_ERR "register_netdev() wds error!\n"); + } + rtl865x_wlanIF_Init(dev); +} +#endif + +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU) +__DRAM_IN_865X int passThruStatusWlan; +int passThruWanIdx; +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *resPassThruWlan=NULL; +static char passThru_flag_wlan[10]; +#endif + +static int rtl_passthru_pseudo_dev_set_hwaddr(struct net_device *dev, void *addr) +{ + unsigned long flags; + int i; + unsigned char *p; + + p = ((struct sockaddr *)addr)->sa_data; + local_irq_save(flags); + for (i = 0; idev_addr[i] = p[i]; + } + local_irq_restore(flags); + return SUCCESS; +} + +#if defined(__LINUX_2_6__) && !defined(CONFIG_COMPAT_NET_DEV_OPS) +static const struct net_device_ops rtl8192cd_pseudodev_ops = { + .ndo_open = rtl8192cd_open, + .ndo_stop = rtl8192cd_close, + .ndo_set_mac_address = rtl_passthru_pseudo_dev_set_hwaddr, +#if LINUX_VERSION_CODE=KERNEL_VERSION(3,0,0) && LINUX_VERSION_CODEpWlanDev) { + diag_printf("pwlan0 exist already!\n"); + return; + } +#endif + + dev = alloc_etherdev(sizeof(struct rtl8192cd_priv)); + if (dev == NULL) { + panic_printk("alloc_etherdev() pseudo pwlan0 error!\n"); + return; + } + +#if !defined(__LINUX_2_6__) || defined(CONFIG_COMPAT_NET_DEV_OPS) + dev->open = rtl8192cd_open; + dev->stop = rtl8192cd_close; +#ifdef __KERNEL__ + dev->set_multicast_list = rtl8192cd_set_rx_mode; +#endif + dev->hard_start_xmit = rtl8192cd_start_xmit; + dev->get_stats = rtl8192cd_get_stats; + dev->do_ioctl = rtl8192cd_ioctl; +#ifndef __ECOS + dev->set_mac_address = rtl_passthru_pseudo_dev_set_hwaddr; +#endif +#else + dev->netdev_ops = &rtl8192cd_pseudodev_ops; +#endif + +#ifdef __ECOS + dev->isr = __rtl8192cd_interrupt; + dev->dsr= interrupt_dsr; + dev->can_xmit = can_xmit; +#endif + +#ifdef NETDEV_NO_PRIV + ((struct rtl8192cd_priv *)netdev_priv(dev))->wlan_priv = priv; +#else + dev->priv = priv; +#endif + +#ifdef __ECOS + strcpy(dev->name, "pwlan0"); +#else + strcpy(dev->name, "pwlan%d"); +#endif + memcpy((char*)dev->dev_addr,"\x00\xe0\x4c\x81\x96\x96", MACADDRLEN); + +#ifdef __KERNEL__ + if (register_netdev(dev)) { + printk(KERN_ERR "register_netdev() pwlan0 error!\n"); + } +#endif + + ((struct rtl8192cd_priv *)priv)->pWlanDev=dev; //pWlanDev point to the virtual pwlan0 + +#ifdef __ECOS + diag_printf("[%s] added...\n", dev->name); +#endif +} + + +static unsigned long atoi_dec(char *s) +{ + unsigned long k = 0; + + k = 0; + while (*s != '\0' && *s >= '0' && *s <= '9') { + k = 10 * k + (*s - '0'); + s++; + } + return k; +} + +#ifdef CONFIG_PROC_FS +#ifdef CONFIG_RTL_PROC_NEW +static int wlan_custom_Passthru_read_proc(struct seq_file *s, void *data) +{ + seq_printf(s, "%s\n", passThru_flag_wlan); + return 0; +} +#else +static int wlan_custom_Passthru_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + len = sprintf(page, "%s\n", passThru_flag_wlan); + if (len <= off+count) + *eof = 1; + + *start = page + off; + len -= off; + + if (len>count) + len = count; + + if (len<0) len = 0; + + return len; +} +#endif +static int wlan_custom_Passthru_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int flag /*,i*/; + + if (buffer && !copy_from_user(&passThru_flag_wlan, buffer, count)) + { + flag=(int)atoi_dec(passThru_flag_wlan); + + passThruStatusWlan=flag; + + return count; + } + return -EFAULT; +} + +#ifdef CONFIG_RTL_PROC_NEW +int wlan_custom_Passthru_single_open(struct inode *inode, struct file *file) +{ + return(single_open(file, wlan_custom_Passthru_read_proc,NULL)); +} +static ssize_t wlan_custom_Passthru_single_write(struct file * file, const char __user * userbuf, + size_t count, loff_t * off) +{ + return wlan_custom_Passthru_write_proc(file, userbuf,count, off); +} + +struct file_operations wlan_custom_Passthru_proc_fops = { + .open = wlan_custom_Passthru_single_open, + .write = wlan_custom_Passthru_single_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +#endif //CONFIG_PROC_FS + +int rtl_wlan_customPassthru_init(void) +{ + int wlan_idx; + + for(wlan_idx=0;wlan_idxread_proc = wlan_custom_Passthru_read_proc; + resPassThruWlan->write_proc = wlan_custom_Passthru_write_proc; + } +#endif +#endif + + rtl_passthru_pseudo_dev_init(wlan_device[passThruWanIdx].priv); + + return 0; +} + +void __exit rtl_wlan_customPassthru_exit(void) +{ +#ifdef CONFIG_PROC_FS + if (resPassThruWlan) { + remove_proc_entry("custom_Passthru_wlan", resPassThruWlan); + resPassThruWlan = NULL; + } +#endif +} +#endif + + + +#if defined(__DRAYTEK_OS__) && defined(WDS) +int rtl8192cd_add_wds(struct net_device *dev, struct net_device *wds_dev, unsigned char *addr) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)dev->priv; + int wds_num=priv->pmib->dot11WdsInfo.wdsNum; + + priv->pmib->dot11WdsInfo.dev[wds_num] = wds_dev; + memcpy(priv->pmib->dot11WdsInfo.entry[wds_num].macAddr, addr, 6); + wds_dev->priv = priv; + wds_dev->base_addr = 0; + priv->pmib->dot11WdsInfo.wdsNum++; + + if (!priv->pmib->dot11WdsInfo.wdsEnabled) + priv->pmib->dot11WdsInfo.wdsEnabled = 1; + + if (netif_running(priv->dev)) + create_wds_tbl(priv); + + DEBUG_INFO("\r\nAdd WDS: %02x%02x %02x%02x%02x%02x\n", + addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]); +} +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_NET_PCI +static int MDL_DEVINIT rtl8192cd_init_pci(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int ret; +#ifdef MBSSID + int i; +#endif + +#ifdef RTL8192CD_VARIABLE_USED_DMEM + /* For D-MEM allocation system's initialization : It would before ALL processes */ + rtl8192cd_dmem_init(); +#endif + +#ifdef NOT_RTK_BSP + if (wlan_index >= ARRAY_SIZE(wlan_device)) { + printk("PCI device %d can't be supported\n", wlan_index); + return -1; + } +#endif + ret = rtl8192cd_init_one(pdev, ent, &wlan_device[wlan_index], -1); + if (ret) + goto error; + +#ifdef UNIVERSAL_REPEATER + ret = rtl8192cd_init_one(pdev, ent, &wlan_device[wlan_index], -1); + if (ret) + goto error; +#endif + +#ifdef MBSSID + for (i = 0; i < RTL8192CD_NUM_VWLAN; i++) { + ret = rtl8192cd_init_one(pdev, ent, &wlan_device[wlan_index], i); + if (ret) + goto error; + } +#endif + + wlan_index++; + + return 0; + +error: + if (NULL != wlan_device[wlan_index].priv) { + rtl8192cd_deinit_one(wlan_device[wlan_index].priv); + wlan_device[wlan_index].priv = NULL; + } + + return ret; +} + + +static void MDL_DEVEXIT rtk_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + if (!dev) + BUG(); + + pci_set_drvdata(pdev, NULL); + + wlan_index--; + +#if defined(RTK_NL80211) + wlan_index = 0; +#endif + + if (NULL != wlan_device[wlan_index].priv) { + rtl8192cd_deinit_one(wlan_device[wlan_index].priv); + wlan_device[wlan_index].priv = NULL; + } +} + + +static struct pci_device_id MDL_DEVINITDATA rtl8192cd_pci_tbl[] = +{ +/* + { PCI_VENDOR_ID_REALTEK, 0x8190, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +*/ +#ifdef CONFIG_RTL_92D_SUPPORT + { PCI_VENDOR_ID_REALTEK, 0x8193, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif + { PCI_VENDOR_ID_REALTEK, 0x8191, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + { PCI_VENDOR_ID_REALTEK, 0x8171, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + { PCI_VENDOR_ID_REALTEK, 0x8178, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + { PCI_VENDOR_ID_REALTEK, 0x8176, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + { PCI_VENDOR_ID_REALTEK, 0x8174, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + +#ifdef CONFIG_RTL_88E_SUPPORT + { PCI_VENDOR_ID_REALTEK, 0x8179, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif +#if defined(CONFIG_WLAN_HAL_8192EE) + { PCI_VENDOR_ID_REALTEK, 0x8170, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_REALTEK, 0x818b,//0x817b + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif +#if defined(CONFIG_WLAN_HAL_8814AE) +{ PCI_VENDOR_ID_REALTEK, 0x8813, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif +#ifdef CONFIG_RTL_8812_SUPPORT //eric_8812 ?? + { PCI_VENDOR_ID_REALTEK, 0x8812, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif + { }, +}; + + +MODULE_DEVICE_TABLE(pci, rtl8192cd_pci_tbl); + +static struct pci_driver rtl8192cd_driver = { + name: DRV_NAME, + id_table: rtl8192cd_pci_tbl, + probe: rtl8192cd_init_pci, +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)) + remove: __devexit_p(rtk_remove_one), +#else + remove: rtk_remove_one, +#endif +}; +#endif // CONFIG_NET_PCI +#endif // CONFIG_PCI_HCI + + +#ifdef CONFIG_WIRELESS_LAN_MODULE +int GetCpuCanSuspend(void) +{ + extern int gCpuCanSuspend; + return gCpuCanSuspend; +} +#endif + + +#if defined(CONFIG_RTL8196B) +//System identification for CHIP +#define CHIP_OEM_ID 0xb8000000 +#define DDR_SELECT 0xb8000008 +#define C_CUT 2 +#define DDR_BOOT 2 +int no_ddr_patch; +#endif + +#if defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) +unsigned int get_8192cd_gpio0_7(void) +{ + int i; + struct rtl8192cd_priv *priv; + struct net_device *dev; + unsigned int reg = 0; + dev = NULL; + for (i=0; (idev)) + { + priv = wlan_device[i].priv; + reg = RTL_R32(GPIO_PIN_CTRL); + printk("<%s>LZQ: read 8192cd gpio reg [0x%x]!\n", __FUNCTION__, reg); + return reg; + } + } + printk("<%s>LZQ: read 8192cd gpio reg ERROR!\n", __FUNCTION__); + return 0; +} +#endif + +#ifndef __ECOS +int MDL_INIT __rtl8192cd_init(unsigned long base_addr) +{ + int rc; +#ifdef MBSSID + int i; +#endif + +#if defined(CONFIG_RTL8196B) + //System identification for CHIP + no_ddr_patch = !((REG32(CHIP_OEM_ID)> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS), + wlan_device[wlan_index].type, wlan_device[wlan_index].base_addr,wlan_device[wlan_index].conf_addr, wlan_device[wlan_index].irq); + + if (((wlan_device[wlan_index].type >> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS) { + if (FALSE == drv_registered) { + drv_registered = TRUE; +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_NET_PCI +#ifdef LINUX_2_6_20_ + rc = pci_register_driver(&rtl8192cd_driver); + if (rc) { + printk("pci_register_driver() fail!(%d)\n", rc); + } +#else + pci_module_init(&rtl8192cd_driver); +#endif +#endif +#endif // CONFIG_PCI_HCI +#ifdef CONFIG_USB_HCI + rc = usb_register(&rtl8192cd_usb_driver); + if (rc) { + printk("usb_register() fail!(%d)\n", rc); + } +#endif // CONFIG_USB_HCI +#ifdef CONFIG_SDIO_HCI + rc = sdio_register_driver(&rtl8192cd_sdio_driver); + if (rc) { + printk("sdio_register_driver() fail!(%d)\n", rc); + } +#endif // CONFIG_SDIO_HCI + } + } + else { +#ifdef __DRAYTEK_OS__ + wlan_device[wlan_index].base_addr = base_addr; + wlan_device[wlan_index].type = (TYPE_PCI_DIRECT<dev); + rtl8192cd_close(priv->dev); + + RESTORE_INT(flags); + } + } + } +#endif + } + +#if defined(__DRAYTEK_OS__) + if (rc != 0) + return rc; +#endif +#ifndef __KERNEL__ + wlan_index++; +#endif + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + register_reboot_notifier(&rtw_reboot_notifier); +#endif + +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU) + rtl_wlan_customPassthru_init(); +#endif + +#if 0 +//#ifdef PCIE_POWER_SAVING + HostPCIe_Close(); +#endif + + +#if 0//def CONFIG_RTL_STP + rtl_pseudo_dev_init(wlan_device[0].priv); +#endif + +#ifdef _USE_DRAM_ + { + extern unsigned char *en_cipherstream; + extern unsigned char *tx_cipherstream; + extern char *rc4sbox, *rc4kbox; + extern unsigned char *pTkip_Sbox_Lower, *pTkip_Sbox_Upper; + extern unsigned char Tkip_Sbox_Lower[256], Tkip_Sbox_Upper[256]; + +#ifdef CONFIG_RTL8671 + extern void r3k_enable_DRAM(void); //6/7/04' hrchen, for 8671 DRAM init + r3k_enable_DRAM(); //6/7/04' hrchen, for 8671 DRAM init +#endif + + en_cipherstream = (unsigned char *)(DRAM_START_ADDR); + tx_cipherstream = en_cipherstream; + + rc4sbox = (char *)(DRAM_START_ADDR + 2048); + rc4kbox = (char *)(DRAM_START_ADDR + 2048 + 256); + pTkip_Sbox_Lower = (unsigned char *)(DRAM_START_ADDR + 2048 + 256*2); + pTkip_Sbox_Upper = (unsigned char *)(DRAM_START_ADDR + 2048 + 256*3); + + memcpy(pTkip_Sbox_Lower, Tkip_Sbox_Lower, 256); + memcpy(pTkip_Sbox_Upper, Tkip_Sbox_Upper, 256); + } +#endif + +#ifdef __KERNEL__ +#if defined(EAP_BY_QUEUE) && defined(USE_CHAR_DEV) +// for module, 2005-12-26 ----------- + rtl8192cd_chr_reg_hook = rtl8192cd_chr_reg; + rtl8192cd_chr_unreg_hook = rtl8192cd_chr_unreg; +//------------------------------------ + rtl8192cd_chr_init(); +#endif +#endif + +#ifdef CONFIG_RTL8671 + //turn off AP LED + { + unsigned char wlanreg = *(volatile unsigned char *)0xbd30005e; + *(volatile unsigned char *)0xbd30005e = (wlanreg | ((1<<5))); + } +#endif + +#ifdef PERF_DUMP + rtl8651_romeperfInit(); +#endif + +#ifdef USB_PKT_RATE_CTRL_SUPPORT + register_usb_hook = (register_usb_pkt_cnt_fn)(register_usb_pkt_cnt_f); +#endif + + return 0; +} +#endif + + +#ifdef __DRAYTEK_OS__ +int rtl8192cd_init(unsigned long base_addr) +{ + return __rtl8192cd_init(base_addr); +} +#elif !defined(__ECOS) +int MDL_INIT rtl8192cd_init(void) +{ +#if defined(CONFIG_RTL_ULINKER_WLAN_DELAY_INIT) + static char initated = 0; + if (initated == 0) + initated = 1; + else + return 0; +#endif + +#ifdef CONFIG_RTL8671 + gpioConfig(10,2); + gpioClear(10); + delay_ms(10); + gpioSet(10); +#endif + + return __rtl8192cd_init(0); +} +#endif + + +#ifndef __ECOS +#ifdef __KERNEL__ +#if !defined(CONFIG_RTL_ULINKER_WLAN_DELAY_INIT) +static +#endif +void MDL_EXIT rtl8192cd_exit (void) +{ +#if defined(CONFIG_PCI_HCI) && !defined(CONFIG_NET_PCI) + int idx; +#endif + +#if defined(CONFIG_WIRELESS_LAN_MODULE) && !defined(NOT_RTK_BSP) + wirelessnet_hook = NULL; +#ifdef BR_SHORTCUT + wirelessnet_hook_shortcut = NULL; +#endif +#ifdef PERF_DUMP + Fn_rtl8651_romeperfEnterPoint = NULL; + Fn_rtl8651_romeperfExitPoint = NULL; + #endif +#ifdef CONFIG_RTL8190_PRIV_SKB + wirelessnet_hook_is_priv_buf = NULL; + wirelessnet_hook_free_priv_buf = NULL; +#endif +#endif // CONFIG_WIRELESS_LAN_MODULE && !NOT_RTK_BSP + +#if defined(EAP_BY_QUEUE) && defined(USE_CHAR_DEV) +// for module, 2005-12-26 ------------ + extern struct rtl8192cd_priv* (*rtl8192cd_chr_reg_hook)(unsigned int minor, struct rtl8192cd_chr_priv *priv); + extern void (*rtl8192cd_chr_unreg_hook)(unsigned int minor); +//------------------------------------ +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + unregister_reboot_notifier(&rtw_reboot_notifier); +#endif + + drv_registered = FALSE; + +#ifdef CONFIG_PCI_HCI +#ifndef CONFIG_NET_PCI + for (idx = 0; idx < ARRAY_SIZE(wlan_device) ; idx++) { + if (NULL == wlan_device[idx].priv) + continue; + rtl8192cd_deinit_one(wlan_device[idx].priv); + wlan_device[idx].priv = NULL; + } +#else + pci_unregister_driver(&rtl8192cd_driver); +#endif +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI + usb_deregister(&rtl8192cd_usb_driver); +#endif + +#ifdef CONFIG_SDIO_HCI + sdio_unregister_driver(&rtl8192cd_sdio_driver); +#endif + +#ifdef CONFIG_WLAN_HAL + ResetHALIndex(); +#endif + +#ifdef CONFIG_POWER_SAVE + rtw_suspend_lock_deinit(); +#endif + +#if defined(EAP_BY_QUEUE) && defined(USE_CHAR_DEV) +// for module, 2005-12-26 ------------ + rtl8192cd_chr_reg_hook = NULL; + rtl8192cd_chr_unreg_hook = NULL; +//------------------------------------ + + rtl8192cd_chr_exit(); +#endif +} +#else // not __KERNEL__ +void MDL_EXIT rtl8192cd_exit(void *data) +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = dev->priv; + int idx, i; + + for (idx=0; idx> WDS_SHIFT) & WDS_MASK; + for (i=0; ipmib->dot11WdsInfo.dev[i]->priv = NULL; + unregister_netdev(wlan_device[idx].priv->pmib->dot11WdsInfo.dev[i]); + kfree(wlan_device[idx].priv->pmib->dot11WdsInfo.dev[i]); + } + } +#endif + + unregister_netdev(dev); + + kfree(priv->pmib); + +#ifdef CONFIG_RTK_MESH + + if(priv->proxy_table) + { + remove_hash_table(priv->proxy_table); + kfree(priv->proxy_table); + } + if(priv->mesh_rreq_retry_queue) + { + for (i = 0; i < (1 << priv->mesh_rreq_retry_queue->table_size_power); i++) { + if(((struct mesh_rreq_retry_entry*)(priv->mesh_rreq_retry_queue->entry_array[i].data))->ptr) + kfree(((struct mesh_rreq_retry_entry*)(priv->mesh_rreq_retry_queue->entry_array[i].data))->ptr); + } + remove_hash_table(priv->mesh_rreq_retry_queue); + kfree(priv->mesh_rreq_retry_queue); + } + + // add by chuangch 2007.09.13 + if(priv->pathsel_table) + { + remove_hash_table(priv->pathsel_table); + kfree(priv->pathsel_table); + } + + if(priv->pann_mpp_tb) + kfree(priv->pann_mpp_tb); + + kfree(priv->pathsel_queue); +#ifdef _11s_TEST_MODE_ + kfree(priv->receiver_queue); + for(i=0; i< AODV_RREQ_TABLE_SIZE; i++) + del_timer(&priv->pshare->galileo_poll->node[i].data.expire_timer); + + kfree(priv->pshare->galileo_poll); +#endif + +#ifdef _MESH_ACL_ENABLE_ + kfree(priv->pmesh_acl_poll); +#endif +#endif // CONFIG_RTK_MESH + + kfree(priv->pevent_queue); +#ifdef CONFIG_RTL_WAPI_SUPPORT +// kfree(vxd_priv->wapiEvent_queue); + kfree(priv->wapiEvent_queue); + #ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)&&priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]->wapiEvent_queue); + } + #endif +#endif +#ifndef PRIV_STA_BUF + kfree((void *)priv->pshare->phw->alloc_dma_buf); + kfree(priv->pshare->phw); + kfree(priv->pshare->pwlan_hdr_poll); + kfree(priv->pshare->pwlanllc_hdr_poll); + kfree(priv->pshare->pwlanbuf_poll); + kfree(priv->pshare->pwlanicv_poll); + kfree(priv->pshare->pwlanmic_poll); +#endif + kfree(priv->pwlan_acl_poll); + kfree(priv->Eap_packet); +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + kfree(priv->wpa_global_info); +#endif + free_site_survey_res(priv->site_survey); +#ifndef PRIV_STA_BUF + kfree(priv->pshare); // david +#endif + kfree(dev); + +#ifdef EN_EFUSE + for( i = 0 ; i < 2 ; i++ ) + kfree(priv->EfuseMap[i]); + kfree(priv->EfuseCmd); +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + HalDisAssociateNic(priv, TRUE); + DecreaseHALIndex(); + } +#endif //CONFIG_WLAN_HAL + + wlan_device[idx].priv = NULL; + + wlan_index--; +} +#endif +#endif // !__EOCS + + +#ifdef __KERNEL__ +#ifdef USE_CHAR_DEV +struct rtl8192cd_priv *rtl8192cd_chr_reg(unsigned int minor, struct rtl8192cd_chr_priv *priv) +{ + if (wlan_device[minor].priv) + wlan_device[minor].priv->pshare->chr_priv = priv; + return wlan_device[minor].priv; +} + + +void rtl8192cd_chr_unreg(unsigned int minor) +{ + if (wlan_device[minor].priv) + wlan_device[minor].priv->pshare->chr_priv = NULL; +} +#endif + + +#ifdef RTL_WPA2_PREAUTH +void wpa2_kill_fasync(void) +{ + int wlan_index = 0; + struct _device_info_ *wdev = &wlan_device[wlan_index]; + struct rtl8192cd_priv *priv = wdev->priv; + event_indicate(priv, NULL, -1); +} + + +void wpa2_preauth_packet(struct sk_buff *pskb) +{ + // ****** NOTICE ********** + int wlan_index = 0; + struct _device_info_ *wdev = &wlan_device[wlan_index]; + // ****** NOTICE ********** + + struct rtl8192cd_priv *priv = wdev->priv; + + unsigned char szEAPOL[] = {0x02, 0x01, 0x00, 0x00}; + DOT11_EAPOL_START Eapol_Start; + + if (priv == NULL) { + PRINT_INFO("%s: priv == NULL\n", (char *)__FUNCTION__); + return; + } + +#ifndef WITHOUT_ENQUEUE + if (!memcmp(pskb->data, szEAPOL, sizeof(szEAPOL))) + { + Eapol_Start.EventId = DOT11_EVENT_EAPOLSTART_PREAUTH; + Eapol_Start.IsMoreEvent = FALSE; + memcpy(&Eapol_Start.MACAddr, SKB_MAC_HEADER(pskb) + MACADDRLEN, MACADDRLEN); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&Eapol_Start, sizeof(DOT11_EAPOL_START)); + } + else + { + unsigned short pkt_len; + + pkt_len = WLAN_ETHHDR_LEN + pskb->len; + priv->Eap_packet->EventId = DOT11_EVENT_EAP_PACKET_PREAUTH; + priv->Eap_packet->IsMoreEvent = FALSE; + memcpy(&(priv->Eap_packet->packet_len), &pkt_len, sizeof(unsigned short)); + memcpy(&(priv->Eap_packet->packet[0]), SKB_MAC_HEADER(pskb), WLAN_ETHHDR_LEN); + memcpy(&(priv->Eap_packet->packet[WLAN_ETHHDR_LEN]), pskb->data, pskb->len); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)priv->Eap_packet, sizeof(DOT11_EAP_PACKET)); + } +#endif // WITHOUT_ENQUEUE + + event_indicate(priv, NULL, -1); + + // let dsr to free this skb +} +#endif // RTL_WPA2_PREAUTH +#endif // __KERNEL__ + +#if defined(CONFIG_RTL_ETH_PRIV_SKB_DEBUG) +__MIPS16 __IRAM_FWD extern int is_rtl865x_eth_priv_buf(unsigned char *head); +extern void dump_sta_dz_queue_num(struct rtl8192cd_priv *priv, struct stat_info *pstat); + +int dump_wlan_dz_queue_num(const char *name) +{ + int i,j,txCnt=0; + //int queueCnt,idx; + struct rtl8192cd_priv *priv; + //struct tx_desc_info *pdescinfoH,*pdescinfo; + //struct tx_desc *pdescH, *pdesc; + //struct sk_buff *skb = NULL; + //struct rtl8192cd_hw *phw; + int hd, tl; + + for (j=0; (jdev) && strcmp(wlan_device[j].priv->dev->name,name)==0) + { + priv = wlan_device[j].priv; + if (OPMODE & WIFI_AP_STATE) + { + hd = priv->dz_queue.head; + tl = priv->dz_queue.tail; + printk("priv->dz_queue:%d\n",CIRC_CNT(hd, tl, NUM_TXPKT_QUEUE)); + + for (i=0; ipshare->aidarray[i]) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (priv != priv->pshare->aidarray[i]->priv) + continue; + else +#endif + { + if (priv->pshare->aidarray[i]->used == TRUE) + { + dump_sta_dz_queue_num(priv, &(priv->pshare->aidarray[i]->station)); + } + + } + } + } + } + } + } + + return txCnt; +} +int get_nic_buf_in_wireless_tx(const char *name) +{ + int i,txCnt; + int queueCnt,idx; + struct rtl8192cd_priv *priv; + struct tx_desc_info *pdescinfoH,*pdescinfo; + struct tx_desc *pdescH, *pdesc; + struct sk_buff *skb = NULL; + struct rtl8192cd_hw *phw; + + txCnt = 0; + for (i=0; (idev) && strcmp(wlan_device[i].priv->dev->name,name)==0) + { + priv = wlan_device[i].priv; + if (OPMODE & WIFI_AP_STATE) + { + for(queueCnt = 0; queueCnt <= HIGH_QUEUE;queueCnt++) + { + phw=GET_HW(priv); + pdescH = get_txdesc(phw, queueCnt); + pdescinfoH = get_txdesc_info(priv->pshare->pdesc_info,queueCnt); + for(idx = 0; idx < CURRENT_NUM_TX_DESC; idx++) + { + pdesc = pdescH + idx; + pdescinfo = pdescinfoH + idx; + //if (!pdesc || (get_desc(pdesc->Dword0) & TX_OWN)) + //continue; + if(pdescinfo->type == _SKB_FRAME_TYPE_ || pdescinfo->type == _RESERVED_FRAME_TYPE_) + skb = (struct sk_buff *)(pdescinfo->pframe); + else + continue; + + if(skb && is_rtl865x_eth_priv_buf(skb->head)) + txCnt++; + } + } + + //counted = 1; + } + } + } + + return txCnt; +} +#endif + + +#if defined(CONFIG_RTK_VLAN_SUPPORT) && defined(CONFIG_RTK_VLAN_FOR_CABLE_MODEM) +struct net_device* get_dev_by_vid(int vid) +{ + int i; + struct rtl8192cd_priv *priv; + + for (i=0; (idev)) + { + priv = wlan_device[i].priv; + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->miscEntry.vap_enable) { + int j; + for (j=0; jpvap_priv[j])) { + if(priv->pvap_priv[j]->pmib->vlan.vlan_enable && priv->pvap_priv[j]->pmib->vlan.vlan_id == vid) + return priv->pvap_priv[j]->dev; + } + } + } + } + } + + return NULL; +} +#endif + +#ifdef BR_SHORTCUT +#ifdef RTL_CACHED_BR_STA +struct brsc_cache_t* get_free_brsc_cache(void){ + int idx; + int idxofoldest=0; + + /*find free cache*/ + for(idx=0;idxcached_br_sta_mac, da, MACADDRLEN); + tmpcache->cached_br_sta_dev = dev; + tmpcache->occupy = 1; + tmpcache->timestamp = jiffies; + } +}; + +void release_brsc_cache(unsigned char* da) +{ + int idx = query_brsc_cache(da); + if(idx>=0) { + memset(&brsc_cache_arr[idx],0,sizeof(struct brsc_cache_t)); + } +}; +#endif // RTL_CACHED_BR_STA + +//#ifndef NOT_RTK_BSP +__MIPS16 +__IRAM_IN_865X +struct net_device *get_shortcut_dev(unsigned char *da) +{ + int i; +#ifdef MBSSID + int j; +#endif + struct rtl8192cd_priv *priv; +#ifdef UNIVERSAL_REPEATER + struct rtl8192cd_priv *vxd_priv; +#endif + struct stat_info *pstat; + struct net_device *dev; + struct net_bridge_port *br_port=NULL; + +#if defined(BR_SHORTCUT) + #ifdef CONFIG_RTK_MESH //11 mesh no support shortcut now + { + extern unsigned char cached_mesh_mac[2][MACADDRLEN]; + extern struct net_device *cached_mesh_dev[2]; + + if (cached_mesh_dev[0] && !memcmp(da, cached_mesh_mac[0], MACADDRLEN)) { + return cached_mesh_dev[0]; + } + } + #endif + + #ifdef WDS + { + extern unsigned char cached_wds_mac[MACADDRLEN]; + extern struct net_device *cached_wds_dev; + if (cached_wds_dev && !memcmp(da, cached_wds_mac, MACADDRLEN)) + return cached_wds_dev; + } + #endif + + #ifdef RTL_CACHED_BR_STA + for(i=0;idev)) { + priv = wlan_device[i].priv; + + #ifdef CLIENT_MODE + if(priv->reperater_idx==1){ + if (cached_sta_dev[0] && !memcmp(da, cached_sta_mac[0], MACADDRLEN)){ + //STADEBUG("\n"); + return cached_sta_dev[0]; + } + }else if((priv->reperater_idx==2)){ + if (cached_sta_dev[1] && !memcmp(da, cached_sta_mac[1], MACADDRLEN)){ + //STADEBUG("\n"); + return cached_sta_dev[1]; + } + } + #endif + +#if !defined( _SINUX_ ) && defined(__KERNEL__) + // if sinux, no linux bridge, so should don't depend on br_port if use br_shortcut (John Qian 2010/6/24) + br_port = GET_BR_PORT(priv->dev); +#endif + if (IS_DRV_OPEN(priv) + //2010-5-10 +#if !defined( _SINUX_ ) && defined(__KERNEL__) + && (br_port) + && !(br_port->br->stp_enabled) +#endif + ) { + if (!priv->pmib->dot11OperationEntry.disable_brsc) { + pstat = get_stainfo(priv, da); + if (pstat && (pstat->tx_pkts > 1) && pstat->expire_to) { /* Make sure it must have some packets go theough bridge module before shortcut */ + #ifdef WDS + if (!(pstat->state & WIFI_WDS)) // if WDS peer + #endif + { + #ifdef CONFIG_RTK_MESH + if( isMeshPoint(pstat)) + {dev = priv->mesh_dev;} + else + #endif + {dev = priv->dev;} + + + //STADEBUG(" 1. got![%02X%02X%02X:%02X%02X%02X]\n",da[0],da[1],da[2],da[3],da[4],da[5]); + break; + } + } + } + #ifdef MBSSID + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->miscEntry.vap_enable) { + for (j=0; jpvap_priv[j]->assoc_num > 0) && IS_DRV_OPEN(priv->pvap_priv[j]) && + !(priv->pvap_priv[j]->pmib->dot11OperationEntry.disable_brsc)) { + pstat = get_stainfo(priv->pvap_priv[j], da); + if (pstat && (pstat->tx_pkts > 1) && pstat->expire_to) { + //STADEBUG(" 2.vap%d ,got![%02X%02X%02X:%02X%02X%02X]\n",j,da[0],da[1],da[2],da[3],da[4],da[5]); + dev = priv->pvap_priv[j]->dev; + break; + } + } + } + } + #endif + #ifdef UNIVERSAL_REPEATER + vxd_priv = GET_VXD_PRIV(priv); + if((OPMODE & WIFI_STATION_STATE) && (vxd_priv->assoc_num > 0) && IS_DRV_OPEN(vxd_priv) && + !vxd_priv->pmib->dot11OperationEntry.disable_brsc) { + pstat = get_stainfo(vxd_priv, da); + if (pstat && (pstat->tx_pkts > 1) && pstat->expire_to) { + dev = vxd_priv->dev; + break; + } + } + #endif + } + } + } + +#ifdef RTL_CACHED_BR_STA + if (dev!=NULL) { + add_to_brsc_cache(dev,da); + } +#endif + + return dev; +} +//#endif // !NOT_RTK_BSP + +void clear_shortcut_cache(void) +{ +#ifdef CONFIG_RTK_MESH + { + extern struct net_device *cached_mesh_dev[2]; + extern unsigned char cached_mesh_mac[2][MACADDRLEN]; + cached_mesh_dev[0]= NULL; + memset(cached_mesh_mac[0],0,MACADDRLEN); + cached_mesh_dev[1]= NULL; + memset(cached_mesh_mac[1],0,MACADDRLEN); + } +#endif + +#ifdef WDS + { + extern struct net_device *cached_wds_dev; + extern unsigned char cached_wds_mac[MACADDRLEN]; + cached_wds_dev= NULL; + memset(cached_wds_mac,0,MACADDRLEN); + } +#endif + +#ifdef CLIENT_MODE + { + cached_sta_dev[0] = NULL; + cached_sta_dev[1] = NULL; + memset(cached_sta_mac[0],0,MACADDRLEN); + memset(cached_sta_mac[1],0,MACADDRLEN); + } +#endif + +#ifdef RTL_CACHED_BR_STA + memset(brsc_cache_arr,0,sizeof(struct brsc_cache_t)*MAX_BRSC_NUM); +#endif + +#if defined(CONFIG_RTL_819X) && (defined(__LINUX_2_6__) || defined(__ECOS)) + { + extern unsigned char cached_eth_addr[MACADDRLEN]; + extern struct net_device *cached_dev; + cached_dev = NULL; + memset(cached_eth_addr,0,MACADDRLEN); + } +#endif + +#ifndef NOT_RTK_BSP + { + extern unsigned char cached_eth_addr2[MACADDRLEN]; + extern struct net_device *cached_dev2; + cached_dev2 = NULL; + memset(cached_eth_addr2,0,MACADDRLEN); + } + { + extern unsigned char cached_eth_addr3[MACADDRLEN]; + extern struct net_device *cached_dev3; + cached_dev3 = NULL; + memset(cached_eth_addr3,0,MACADDRLEN); + } + { + extern unsigned char cached_eth_addr4[MACADDRLEN]; + extern struct net_device *cached_dev4; + cached_dev4 = NULL; + memset(cached_eth_addr4,0,MACADDRLEN); + } +#endif // !NOT_RTK_BSP +#ifdef CONFIG_RTL8672 +#ifndef CONFIG_ARCH_LUNA_SLAVE + { + extern void clear_cached_eth_mac_addr(void); + clear_cached_eth_mac_addr(); + } +#endif +#endif +} +#endif // BR_SHORTCUT + + +void update_fwtbl_asoclst(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned char tmpbuf[16]; + int i; + +#if defined(__KERNEL__) && !defined(NOT_RTK_BSP) + struct sk_buff *skb = NULL; + struct wlan_ethhdr_t *e_hdr; + unsigned char xid_cmd[] = {0, 0, 0xaf, 0x81, 1, 2}; + + // update forwarding table of bridge module + if (GET_BR_PORT(priv->dev)) { + skb = dev_alloc_skb(64); + if (skb != NULL) { + skb->dev = priv->dev; + skb_put(skb, 60); + e_hdr = (struct wlan_ethhdr_t *)skb->data; + memset(e_hdr, 0, 64); + memcpy(e_hdr->daddr, priv->dev->dev_addr, MACADDRLEN); + memcpy(e_hdr->saddr, pstat->hwaddr, MACADDRLEN); + e_hdr->type = 8; + memcpy(&skb->data[14], xid_cmd, sizeof(xid_cmd)); + skb->protocol = eth_type_trans(skb, priv->dev); + #if defined(__LINUX_2_6__) && defined(RX_TASKLET)&& !defined(CONFIG_RTL8672) && !defined(__LINUX_3_10__) + netif_receive_skb(skb); + #else + netif_rx(skb); + #endif + } + } +#endif + + // update association lists of the other WLAN interfaces + for (i=0; ipmib->dot11OperationEntry.opmode & WIFI_AP_STATE) { + sprintf((char *)tmpbuf, "%02x%02x%02x%02x%02x%02x", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + del_sta(wlan_device[i].priv, tmpbuf); + } + } + } + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]; + if (IS_DRV_OPEN(priv_vap) && (priv_vap != priv) && (priv->vap_init_seq >= 0)) { + if (priv_vap->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) { + sprintf((char *)tmpbuf, "%02x%02x%02x%02x%02x%02x", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + del_sta(priv_vap, tmpbuf); + } + } + } + } +#endif + +#ifdef __ECOS +#ifdef CONFIG_RTL_819X_SWCORE + { + /* 02-17-2012: move the called function "update_hw_l2table" from Bridge module to here to avoid hacking the Linux kernel or the other kernel */ + extern void update_hw_l2table(const char *srcName,const unsigned char *addr); + update_hw_l2table("wlan", (const unsigned char *)pstat->hwaddr); /* RTL_WLAN_NAME */ + } +#endif +#else +#if defined(CONFIG_RTL_819X) && !defined(CONFIG_RTL8196C_KLD) +#ifndef CONFIG_RTL_8198B + { + /* 02-17-2012: move the called function "update_hw_l2table" from Bridge module to here to avoid hacking the Linux kernel or the other kernel */ + extern void update_hw_l2table(const char *srcName,const unsigned char *addr); + update_hw_l2table("wlan", (const unsigned char *)pstat->hwaddr); /* RTL_WLAN_NAME */ + } +#endif +#endif +#endif +} +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + int get_wlan_if_type(struct rtl8192cd_priv *priv) + { + int i,find = 0,if_idx = -1;; + struct rtl8192cd_priv *root_priv; + root_priv = GET_ROOT(priv); + if(root_priv == NULL) + return if_idx; + for (i=0; i<(sizeof(wlan_device)/sizeof(struct _device_info_)); i++) + { + if (wlan_device[i].priv && netif_running(wlan_device[i].priv->dev) + && wlan_device[i].priv == root_priv) + { + find = 1; + break; + } + } + if(!find) + return if_idx; + if(i == 0){ +#ifdef UNIVERSAL_REPEATER + if(IS_VXD_INTERFACE(priv)) + if_idx = WLAN0_VXD_PORT; + else +#endif + if_idx = WLAN0_PORT; + } + else if(i == 1){ +#ifdef UNIVERSAL_REPEATER + if(IS_VXD_INTERFACE(priv)) + if_idx = WLAN1_VXD_PORT; + else +#endif + if_idx = WLAN1_PORT; + } + return if_idx; + } + +#endif + + +// quick fix for warn reboot fail issue +#ifndef CONFIG_RTL_8198B +#define CLK_MANAGE 0xb8000010 +#endif +void force_stop_wlan_hw(void) +{ + int i=0; +#ifdef CONFIG_WLAN_HAL + unsigned int errorFlag; +#endif +// int temp; + +#if defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN) || defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN_D) || defined(CONFIG_RTL_92D_DMDP) + for (i=0; iGetHwRegHandler(priv, HW_VAR_MAC_IO_ENABLE, (pu1Byte)&bVal); + if ( bVal ) { + if (RT_STATUS_SUCCESS == GET_HAL_INTERFACE(priv)->StopHWHandler(priv)) { + printk("StopHW Succeed\n"); + } + else { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + errorFlag |= DRV_ER_CLOSE_STOP_HW; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_DRV_DBG, (pu1Byte)&errorFlag); + panic_printk("StopHW Failed\n"); + } + } + else { +// printk("(%d), Can't write MACID register\n", __LINE__); + } + } else +#endif + { + if ( check_MAC_IO_Enable(priv) ) { + rtl8192cd_stop_hw(priv); + } + } + } + } +} + +#ifdef TPT_THREAD +int kTPT_thread(void *p) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)p; + //printk("kTPT_thread start!\n"); + + do { + msleep_interruptible(1000); + if (!IS_DRV_OPEN(priv)) + continue; + +#ifdef CHECK_HANGUP + if (!priv->reset_hangup) +#endif +#ifdef SMART_REPEATER_MODE + if (!priv->pshare->switch_chan_rp) +#endif + if(rtl_atomic_read(&priv->pshare->do_tpt)) { + ODM_TXPowerTrackingCheck(ODMPTR); + rtl_atomic_set(&priv->pshare->do_tpt, 0); + } + + } while (!kthread_should_stop() ); + + //printk("kTPT_thread exiting\n"); + return 0; +} + +int kTPT_task_init(struct rtl8192cd_priv *priv) +{ + unsigned char thread_name[10] = {0}; + + sprintf( thread_name, "kTPTd" ); + + rtl_atomic_set(&priv->pshare->do_tpt, 0); + if (NULL == priv->pshare->tpt_task) { + priv->pshare->tpt_task = kthread_run(kTPT_thread, (void *)priv, thread_name); + if (IS_ERR(priv->pshare->tpt_task)) { + printk("%s Thread create failed!\n", thread_name); + priv->pshare->tpt_task = NULL; + return -1; + } + } + + //printk("%s Thread create successfully!\n", thread_name ); + return 0; +} + +void kTPT_task_stop(struct rtl8192cd_priv *priv) +{ + if (priv->pshare->tpt_task) + { + kthread_stop(priv->pshare->tpt_task); + priv->pshare->tpt_task = NULL; + } + rtl_atomic_set(&priv->pshare->do_tpt, 0); +} +#endif /* TPT_THREAD */ + +#ifdef _BROADLIGHT_FASTPATH_ +void replace_upper_layer_packet_destination( void * xi_destination_ptr ) +{ + printk(KERN_INFO"start fastpath\n"); + send_packet_to_upper_layer = xi_destination_ptr ; +} +EXPORT_SYMBOL(replace_upper_layer_packet_destination) ; +#endif + +#ifdef __ECOS +struct rtl8192cd_priv *wlan_search_priv(char *name) +{ + int i; +#ifdef MBSSID + int j; +#endif + + for (i=0; idev->name, name)) + return wlan_device[i].priv; +#ifdef MBSSID + for (j=0; jpvap_priv[j] && + !strcmp(wlan_device[i].priv->pvap_priv[j]->dev->name, name)) + return wlan_device[i].priv->pvap_priv[j]; + } +#endif + +#ifdef UNIVERSAL_REPEATER + if (wlan_device[i].priv->pvxd_priv && + !strcmp(wlan_device[i].priv->pvxd_priv->dev->name, name)) + return wlan_device[i].priv->pvxd_priv; +#endif + } + return NULL; +} + +void wlan_dev_kfree_skb_any(struct sk_buff *skb) +{ +#ifdef RTLPKG_DEVS_ETH_RLTK_819X_WLAN_WLAN1 + if (skb->key && skb->dev) { + if (((Rltk819x_t *)(skb->dev->info))->device_num & 0xffff0000) + kfree_skb_chk_key(skb, wlan_device[1].priv->dev); + else + kfree_skb_chk_key(skb, wlan_device[0].priv->dev); + } + else { + kfree_skb_chk_key(skb, wlan_device[0].priv->dev); + } +#else + kfree_skb_chk_key(skb, wlan_device[0].priv->dev); +#endif +} +#endif + +#ifdef __KERNEL__ +#if defined(CONFIG_WIRELESS_LAN_MODULE) +MODULE_LICENSE("GPL"); +#endif +#if defined(CONFIG_RTL_ULINKER_WLAN_DELAY_INIT) + /* don't init wlan while kernel startup */ +#else +module_init(rtl8192cd_init); +module_exit(rtl8192cd_exit); +#endif /* #if defined(CONFIG_RTL_ULINKER_WLAN_DELAY_INIT) */ +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_p2p.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_p2p.c new file mode 100755 index 000000000..ae855bb01 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_p2p.c @@ -0,0 +1,5914 @@ +/* + * P2P support ; WIFI-DRIECT + * + * $Id: 8192cd_p2p.c,$ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_P2P_C_ + +#ifdef CONFIG_RTL_P2P_SUPPORT +#ifdef __KERNEL__ +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_hw.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" +//#include "./8192cd_util.h" +#include "./8192cd_p2p.h" + +extern UINT8 WSC_IE_OUI[]; + +typedef int p2pcmd_func_t(struct rtl8192cd_priv *priv, char *data); + +struct p2p_cmd_list { + char cmd[32]; + p2pcmd_func_t* p2p_cmd_func; +}; + +char* WSC_STR_PBC="PBC"; // 0x80 +char* WSC_STR_KEYIN="keyin"; //0x100 +char* WSC_STR_DISPLAY="display pin"; // 0x8 + + +/*--------------debug---------------------*/ + + +/*---------------function declare start------------------ */ +char* p2p_find_cmd(char *, char *); +char* p2p_get_token(char *, char *); +unsigned char* p2p_search_tag(unsigned char *, int ,unsigned char , int *); +unsigned char* p2p_check_tag(unsigned char *, int , unsigned char , int *); + + +int P2P_scan(struct rtl8192cd_priv *priv, unsigned char *data); +int P2P_search(struct rtl8192cd_priv *priv, unsigned char *data); +int P2P_listen(struct rtl8192cd_priv* priv,unsigned char* data); +void p2p_show_ss_res(struct rtl8192cd_priv *priv); +int P2P_show_status(struct rtl8192cd_priv *priv, unsigned char *data); + +int p2pcmd_enable(struct rtl8192cd_priv *, unsigned char *); +int p2pcmd_discovery(struct rtl8192cd_priv *priv, unsigned char *data); +int p2pcmd_find(struct rtl8192cd_priv *priv, unsigned char *data); +int p2pcmd_set(struct rtl8192cd_priv *priv, unsigned char *data); +int p2pcmd_set_listen_channel(struct rtl8192cd_priv *priv, unsigned char *data); + +int p2pcmd_force_GO(struct rtl8192cd_priv *priv, unsigned char *data); +int p2pcmd_backtoDev(struct rtl8192cd_priv *priv, unsigned char *data); +int p2p_as_GO(struct rtl8192cd_priv *priv, int GOtype); +int p2p_as_preClient(struct rtl8192cd_priv *priv , int peers_opchannel); + + + +int wsc_build_probe_rsp_ie(struct rtl8192cd_priv *priv , + unsigned char *data , unsigned short DEVICE_PASSWORD_ID); + +int p2p_build_probe_req_ie(struct rtl8192cd_priv *priv, unsigned char *data); + + + +void indicate_wscd(struct rtl8192cd_priv *priv , unsigned char mode , + unsigned char *PSK ,struct p2p_device_peer *current_nego_peer); + +void p2p_on_provision_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); +int p2p_issue_provision_rsp(struct rtl8192cd_priv *priv, unsigned char *da); + +int p2p_issue_provision_req(struct rtl8192cd_priv *priv ); +void p2p_on_provision_rsp(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); + +void p2p_on_GO_nego_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); + +int p2p_issue_GO_nego_rsp(struct rtl8192cd_priv *priv, + struct p2p_device_peer *current_nego_peer); +void p2p_on_GO_nego_conf(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); +int p2p_issue_GO_nego_req(struct rtl8192cd_priv *priv); + +void p2p_on_GO_nego_rsp(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo); +int p2p_issue_GO_nego_conf(struct rtl8192cd_priv *priv, + struct p2p_device_peer *current_nego_peer); + + + +/*---------------function declare end-------------------- */ + +/*---------------local var declare start------------------ */ + +unsigned char P2P_WILDCARD_SSID[8]="DIRECT-"; + +unsigned char WFA_OUI[WFA_OUI_LEN] = {0x50, 0x6F, 0x9A}; +unsigned char WFA_OUI_PLUS_TYPE[WFA_OUI_PLUS_TYPE_LEN] = {0x50, 0x6F, 0x9A , 0x9}; + +unsigned char WILDCARD_ADDR[MAC_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + +/*---------------local var declare end------------------ */ + + +#define BAND_CONTROL 0 // no meaning + + +/*make sure i am under 2G band when p2p listen mode */ +void stay_on_2G(struct rtl8192cd_priv *priv) +{ + //unsigned long flags ; + if (priv->pmib->dot11RFEntry.phyBandSelect != PHY_BAND_2G) + { + P2P_DEBUG(" Switch to 2G Band\n"); + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0xf); + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; + priv->pmib->dot11BssType.net_work_type = (WIRELESS_11B|WIRELESS_11G|WIRELESS_11N); + // 2013 +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + UpdateBBRFVal8812(priv,1); + }else +#endif + { + #ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + UpdateBBRFVal8192DE(priv); + } + #endif + } + // 2013 + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0); + + //RESTORE_INT(flags); + // SMP_UNLOCK(flags); + + } + + return; + +} + + +void stay_on_5G(struct rtl8192cd_priv *priv) +{ + //unsigned long flags ; + if (priv->pmib->dot11RFEntry.phyBandSelect != PHY_BAND_5G) + { + P2P_DEBUG(" Switch to 5G Band\n"); + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + // stop BB + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0xf); + + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; + priv->pmib->dot11BssType.net_work_type = (WIRELESS_11A|WIRELESS_11N); + // 2013 +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + UpdateBBRFVal8812(priv,44); + }else +#endif + { + #ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + UpdateBBRFVal8192DE(priv); + } + #endif + } + // 2013 + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0); + + //RESTORE_INT(flags); + // SMP_UNLOCK(flags); + } + return; +} + + + + + + + +#define UTILITY_FUNCTIONS 0 // no meaning + + +/*-------------------------------- +*--------------------------------- +* +* utility unctions area +* +*--------------------------------- +---------------------------------*/ + +void generate_random_xy(unsigned char *data,int len) +{ + char *String09azAZ="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + unsigned char byteList[30]; + int idx; + if(len>30) + return; + + get_random_bytes((void *)&byteList, len); + for(idx=0;idxp2pPtr->my_channel_list,0,sizeof(struct p2p_channels)); + + memcpy(priv->p2pPtr->my_channel_list.country ,"XX" ,2); + priv->p2pPtr->my_channel_list.country[2] = 0x04; + + priv->p2pPtr->my_channel_list.reg_class_mun=3; + + priv->p2pPtr->my_channel_list.reg_class[0].reg_class = 81; + priv->p2pPtr->my_channel_list.reg_class[0].channel_mun=11; + for(idx=0;idx<11;idx++) + priv->p2pPtr->my_channel_list.reg_class[0].channel[idx]= idx+1; + + priv->p2pPtr->my_channel_list.reg_class[1].reg_class = 115; + priv->p2pPtr->my_channel_list.reg_class[1].channel_mun=4; + for(idx=0;idx<4;idx++) + priv->p2pPtr->my_channel_list.reg_class[1].channel[idx]= 36 + idx*4; + + priv->p2pPtr->my_channel_list.reg_class[2].reg_class = 124; + priv->p2pPtr->my_channel_list.reg_class[2].channel_mun = 5; + for(idx=0;idx<5;idx++) + priv->p2pPtr->my_channel_list.reg_class[2].channel[idx]= 149 + idx*4; + + priv->p2pPtr->my_channel_list.Id11_len = 3+(2+11)+(2+4)+(2+5); + //P2P_DEBUG("channel list len=%d\n",priv->p2pPtr->my_channel_list.Id11_len); +} + +void generate_GO_ssid(struct rtl8192cd_priv *priv) + +{ + + unsigned char tmpstr[24]; + + generate_random_xy(tmpstr,2); + + memcpy(priv->p2pPtr->ssid_random ,tmpstr ,2); + + memcpy(priv->p2pPtr->my_GO_ssid,P2P_WILDCARD_SSID,P2P_WILDCARD_SSID_LEN); + + memcpy(&priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN] ,priv->p2pPtr->ssid_random,2); + + memcpy(&priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN+2] ,"-RTK",4); + + priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN+2+4]='\0'; + + +#if 0 // add postfix ssid after - + priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN+2]='-'; + convert_bin_to_str(GET_MY_HWADDR, 6, tmpstr); + memcpy(priv->p2pPtr->my_GO_ssid+P2P_WILDCARD_SSID_LEN+2+1 ,tmpstr,12); + priv->p2pPtr->my_GO_ssid[P2P_WILDCARD_SSID_LEN+2+1+12]='\0'; +#else + + priv->p2pPtr->my_GO_ssid_len = strlen(priv->p2pPtr->my_GO_ssid); +#endif + P2P_DEBUG("GO SSID=%s\n",priv->p2pPtr->my_GO_ssid); + +} + + + +void generate_GO_PSK(struct rtl8192cd_priv *priv) + +{ + unsigned char tmpstr[65]; + generate_random_xy(tmpstr,8); + memcpy(priv->p2pPtr->go_PSK ,tmpstr ,8); + priv->p2pPtr->go_PSK[8]='\0'; + P2P_DEBUG("GO PSK=%s\n",priv->p2pPtr->go_PSK); +} + + +/* + * find a token in a string. If succes, return pointer of token next. If fail, return null + */ +char* p2p_find_cmd(char *data, char *token) +{ + int idx=0, src_len=strlen(data), token_len=strlen(token); + + while (src_len >= token_len) { + if (!memcmp(&data[idx], token, token_len)){ + if(data[idx+token_len]==',' || data[idx+token_len]=='=' || data[idx+token_len]==' ') + return (&data[idx+token_len+1]); + else + return (&data[idx+token_len]); + } + src_len--; + idx++; + } + return NULL; +} + +//p2p_get_token + + +char *get_config_token(char *data, char *token) +{ + char *ptr=data; + int len=0, idx=0; + + while (*ptr && *ptr != '\n' ) { + if (*ptr == '=') { + if (len <= 1) + return NULL; + memcpy(token, data, len); + + /* delete ending space */ + for (idx=len-1; idx>=0; idx--) { + if (token[idx] != ' ') + break; + } + token[idx+1] = '\0'; + + return ptr+1; + } + len++; + ptr++; + } + return NULL; +} + + +int get_config_value(char *data, char *value) +{ + char *ptr=data; + int len=0, idx, i; + + while (*ptr && *ptr != '\n' && *ptr != '\r') { + len++; + ptr++; + } + + /* delete leading space */ + idx = 0; + while (len-idx > 0) { + if (data[idx] != ' ') + break; + idx++; + } + len -= idx; + + /* delete bracing '"' */ + if (data[idx] == '"') { + for (i=idx+len-1; i>idx; i--) { + if (data[i] == '"') { + idx++; + len = i - idx; + } + break; + } + } + + if (len > 0) { + memcpy(value, &data[idx], len); + value[len] = '\0'; + } + return len; +} + +static int is_zero_ether_addr(const unsigned char *a) +{ + return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]); +} + +int is_zero_pin_code(const unsigned char *a) +{ + return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]| a[6]| a[7]); +} +void p2p_debug_out(unsigned char *label, unsigned char *data, int data_length) +{ + int i,j; + int num_blocks; + int block_remainder; + + num_blocks = data_length >> 4; + block_remainder = data_length & 15; + + if (label) + printk("%s\n", label); + + if (data==NULL || data_length==0) + return; + + for (i=0; i 0) { + printk("\t"); + for (j=0; jchannels_list.reg_class[reg_class].channel[idx]=pData[2+idx]; + //P2P_DEBUG(" channel:%d \n",pData[2+idx]); + } + len -= (2+channels); + pData += (2+channels); + reg_class++; + } + + +} + +void parse_device_info(unsigned char* pData , int tag_len , + struct device_info_s* dev_info_ptr ) +{ + int TagLenChk=tag_len; + int idx = 0; + unsigned char NoSD=0; + unsigned short WSC_T; + unsigned short WSC_L; + unsigned char DeviceName[33]; + + /*device address */ + //P2P_DEBUG("P2P Device Address:"); + //MAC_PRINT(pData); + if(dev_info_ptr){ + memcpy(dev_info_ptr->dev_address,pData,6 ); + } + + pData += 6; + TagLenChk -= 6; + + /*config method */ + //P2P_DEBUG(" Config method:0x%02X\n",*(unsigned short*)pData); + if(dev_info_ptr){ + dev_info_ptr->config_method = *(unsigned short*)pData; + } + + + pData += 2; + TagLenChk -= 2; + + + /*Primary Device Type */ + if(dev_info_ptr){ + memcpy(dev_info_ptr->pri_dev_type , pData , 8); + } + + pData += 8; + TagLenChk -= 8; + + /*Number of Second Device Type */ + + NoSD = pData[0]; + pData += 1; + TagLenChk -= 1; + + if(dev_info_ptr) + dev_info_ptr->sdv_mun = NoSD; + + /* N * Second Device Type */ + if(NoSD){ + for( idx=0 ; idx < NoSD ; idx++){ + if(idx < MAX_SEC_DEV_TYPE){ // now we just keep 2 set , take care + if(dev_info_ptr) + memcpy(&dev_info_ptr->sec_dev_type[idx] ,pData,8); + } + pData += 8; + TagLenChk -= 8; + } + } + + /* Device Name (WSC TLV(2+2+N))*/ + + WSC_T = *((unsigned short *)pData); // Tag + + pData+=2; + + WSC_L = *((unsigned short *)pData); // LEN + + if(WSC_T != 0x1011){ + P2P_PRINT("chk!! should be 0x1011\n"); + } + + pData+=2; + strncpy(DeviceName,pData,WSC_L); + DeviceName[WSC_L]='\0'; + + //P2P_DEBUG("Device name:%s\n",DeviceName); + + if(dev_info_ptr){ + strcpy(dev_info_ptr->devname ,DeviceName); + } + + + + TagLenChk -= (4+WSC_L); + if(TagLenChk){ + P2P_PRINT("chk!! TagLenChk(%d) should be 0\n",TagLenChk); + P2P_PRINT("tag_len=%d\n",tag_len); + } + + +} + + +void parse_group_info(unsigned char* pData , int tag_len) +{ + int TagLenChk=tag_len; + int EachClientInfoLen=0; + int idx = 0; + unsigned char NoSD=0; + unsigned short WSC_T; + unsigned short WSC_L; + unsigned char DeviceName[33]; + + /* process sum of all p2p clients*/ + while(TagLenChk){ + + /*length of bellowing fields */ + EachClientInfoLen = pData[0]; + pData += 1; + + TagLenChk -= EachClientInfoLen; + + /*device address */ + P2P_PRINT(" Device Addr:"); + MAC_PRINT(pData); + + + pData +=6; + EachClientInfoLen -= 6; + + /*interface address */ + P2P_PRINT(" interface Addr:"); + MAC_PRINT(pData); + + pData +=6; + EachClientInfoLen -= 6; + + /*config method */ + P2P_PRINT("Config method:0x%02X\n",*(unsigned int*)pData); + pData +=2; + EachClientInfoLen -= 2; + + + /*Primary Device Type */ + P2P_PRINT(" Primary Device Type:category_id=0x%x, oui=%02x%02x%02x%02x, sub_category_id=0x%x\n", + le16_to_cpu(*((unsigned short *)pData)), pData[2],pData[3],pData[4],pData[5], + le16_to_cpu(*((unsigned short *)&pData[6]))); + + pData +=8; + EachClientInfoLen -= 8; + + + /*Number of Second Device Type */ + + NoSD = pData[0]; + pData +=1; + EachClientInfoLen -= 1; + + /* N * Second Device Type */ + if(NoSD){ + for( ; idx < NoSD ; idx++){ + P2P_PRINT(" Second Device Type:category_id=0x%x, oui=%02x%02x%02x%02x, sub_category_id=0x%x\n", + le16_to_cpu(*((unsigned short *)pData)), pData[2],pData[3],pData[4],pData[5], + le16_to_cpu(*((unsigned short *)&pData[6]))); + + pData +=8; + EachClientInfoLen -= 8; + } + } + + /* Device Name (WSC TLV(2+2+N))*/ + + WSC_T = *((unsigned short *)pData); + if(WSC_T != 0x1011){ + P2P_PRINT("chk!! should be 0x1011\n"); + } + + + pData+=2; + WSC_L = *((unsigned short *)pData); + P2P_PRINT("device name len=%d\n",WSC_L); + + + pData+=2; + strncpy(DeviceName,pData,WSC_L); + DeviceName[WSC_L]='\0'; + + + + pData += WSC_L; + EachClientInfoLen -= (4+WSC_L); + + if(EachClientInfoLen){ + P2P_PRINT("chk!! EachClientInfoLen should be 0 now\n"); + } + + } + + + +} + + +void parse_group_id(unsigned char* pData , int tag_len , + struct p2p_device_peer *current_nego_peer) +{ + /*ID 15*/ + unsigned char StrSSID[33]; + + if(current_nego_peer){ + memcpy(current_nego_peer->group_bssid , pData ,6); + P2P_PRINT("GO's bssid=[%02x%02x%02x:%02x%02x%02x]\n", + pData[0],pData[1],pData[2],pData[3],pData[4],pData[5]); + } + + pData += 6; + tag_len -= 6 ; + + /*p2p Device Address */ + strncpy(StrSSID,pData,tag_len); + StrSSID[tag_len]='\0'; + + if(current_nego_peer){ + strcpy(current_nego_peer->group_ssid , StrSSID); + current_nego_peer->group_ssid_len = strlen(current_nego_peer->group_ssid); + } + +} + + +void parse_p2p_interface(unsigned char* pData , int tag_len) +{ + + int idx = 0; + int AddrCnt = 0; + + /*p2p Device Address */ + P2P_PRINT(" P2P DevAddr:"); + MAC_PRINT(pData); + + + pData += 6 ; + tag_len -= 6 ; + + + /*p2p interface addr count*/ + AddrCnt = pData[0]; + + /* p2p_inter_addr_cnt * inter_addr */ + if(AddrCnt){ + for( ; idx < AddrCnt ; idx++){ + + P2P_PRINT(" P2P ifAddr:"); + MAC_PRINT(pData); + + pData += 6 ; + tag_len -= 6 ; + } + } + + if(tag_len){ + P2P_PRINT("chk!! tag_len should be 0 now\n"); + } + + +} + + +void parse_p2p_Capability(void) +{ + + P2P_PRINT("0... .... Reserved\n"); + P2P_PRINT(".0.. .....Reserved\n"); + P2P_PRINT("..1. .... Device Supports P2P Invitation Procedure\n"); + P2P_PRINT("...0 .... Device Limit, able to participate in additional P2P Groups\n"); + P2P_PRINT(".... 0... Infrastructure manamgement NOT upported\n"); + P2P_PRINT(".... .0.. Concurrent operation NOT supported\n"); + P2P_PRINT(".... ..0. Client discoverability NOT supported\n"); + P2P_PRINT(".... ...1 Service discovery supported\n\n"); + + P2P_PRINT("0... .... Reserved\n"); + P2P_PRINT(".0.. .... Not operating as GO in the Provisioning phase\n"); + P2P_PRINT("..0. .... Persistent reconnect NOT supported\n"); + P2P_PRINT("...0 .... Cross connection NOT supported\n"); + P2P_PRINT(".... 0... Intra-BSS distribution NOT supported\n"); + P2P_PRINT(".... .0.. The GO is able to add additional Clients\n"); + P2P_PRINT(".... ..0. Persistent P2P Group supported\n"); + P2P_PRINT(".... ...0 NOT acting as GO\n"); + +} + + +void p2p_cancel_noa(struct rtl8192cd_priv *priv) +{ + if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NONE) + return; + + cancel_timer2(priv); + P2P_DEBUG("Stop all NoA action!\n"); + if (priv->p2pPtr->noa_list_t.p2p_txpause_flag) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + } + + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_NONE; +} + + +void p2p_noa_timer(struct rtl8192cd_priv *priv) +{ + unsigned int cur_tsf, pre_tbtt, offset; + //P2P_DEBUG("\n"); + if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_OPPPS) { + if (priv->p2pPtr->noa_list_t.p2p_txpause_flag) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + + cur_tsf = RTL_R32(TSFTR); + pre_tbtt = (cur_tsf / (priv->beacon_period * 1024)) * (priv->beacon_period * 1024); + offset = ((priv->p2pPtr->noa_list_t.CTWindow_OppPs & 0x7f) - 1) * 1024; + setup_timer2(priv, pre_tbtt + offset); + } + else { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | 0x1f); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 1; + + cur_tsf = RTL_R32(TSFTR); + pre_tbtt = (cur_tsf / (priv->beacon_period * 1024)) * (priv->beacon_period * 1024); + setup_timer2(priv, pre_tbtt + (priv->beacon_period * 1024)); + } + } + else if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NP_NOA) { + if (priv->p2pPtr->noa_list_t.p2p_txpause_flag) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_NONE; + } + } + else if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_CONT_NOA) { + if (priv->p2pPtr->noa_list_t.p2p_txpause_flag) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + offset = priv->p2pPtr->noa_list_t.noa_counter * priv->p2pPtr->noa_list_t.noa_descs.interval; + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime + offset); + } + else { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | 0x1f); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 1; + offset = priv->p2pPtr->noa_list_t.noa_counter * priv->p2pPtr->noa_list_t.noa_descs.interval + + priv->p2pPtr->noa_list_t.noa_descs.duration; + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime + offset); + priv->p2pPtr->noa_list_t.noa_counter++; + } + } + else { // priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NOA + } +} + + +void p2p_process_noa(struct rtl8192cd_priv *priv) +{ + unsigned int cur_tsf, pre_tbtt, offset; + + if ((priv->p2pPtr->noa_list_t.CTWindow_OppPs & 0x80) && ((priv->p2pPtr->noa_list_t.CTWindow_OppPs & 0x7f) != 0)) + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_OPPPS; + else if (priv->p2pPtr->noa_list_t.noa_descs.count == 1) + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_NP_NOA; + else if (priv->p2pPtr->noa_list_t.noa_descs.count == 255) + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_CONT_NOA; + else if (priv->p2pPtr->noa_list_t.noa_descs.count != 0) + priv->p2pPtr->noa_list_t.go_ps_type = P2P_GO_PS_NOA; + else { + P2P_DEBUG("No NoA parameters!\n\n"); + return; + } + P2P_DEBUG("Start GO PS type of %d\n\n", priv->p2pPtr->noa_list_t.go_ps_type); + + if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_OPPPS) { + cur_tsf = RTL_R32(TSFTR); + pre_tbtt = (cur_tsf / (priv->beacon_period * 1024)) * (priv->beacon_period * 1024); + offset = ((priv->p2pPtr->noa_list_t.CTWindow_OppPs & 0x7f) - 1) * 1024; + setup_timer2(priv, pre_tbtt + offset); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 0; + } + else if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NP_NOA) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | 0x1f); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 1; + + cur_tsf = RTL_R32(TSFTR); + if (TSF_LESS(cur_tsf, priv->p2pPtr->noa_list_t.noa_descs.starttime)) + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime + + priv->p2pPtr->noa_list_t.noa_descs.duration); + else + setup_timer2(priv, cur_tsf + priv->p2pPtr->noa_list_t.noa_descs.duration); + } + else if (priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_CONT_NOA) { + cur_tsf = RTL_R32(TSFTR); + if (TSF_LESS(cur_tsf, priv->p2pPtr->noa_list_t.noa_descs.starttime)) { + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime); + priv->p2pPtr->noa_list_t.noa_counter = 0; + } + else { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | 0x1f); + priv->p2pPtr->noa_list_t.p2p_txpause_flag = 1; + setup_timer2(priv, priv->p2pPtr->noa_list_t.noa_descs.starttime + + priv->p2pPtr->noa_list_t.noa_descs.duration); + priv->p2pPtr->noa_list_t.noa_counter = 1; + } + } + else { // priv->p2pPtr->noa_list_t.go_ps_type == P2P_GO_PS_NOA + } +} + + +void parse_p2p_NOA(struct rtl8192cd_priv *priv, unsigned char* pData, int tag_len, int seq) +{ + unsigned int noa_num, u32; + //unsigned int cur_tsf, offset; + + if (pData[0] != priv->p2pPtr->noa_list_t.index) { + p2p_cancel_noa(priv); + priv->p2pPtr->noa_list_t.index = pData[0]; + priv->p2pPtr->noa_list_t.CTWindow_OppPs = pData[1]; + + memset(&priv->p2pPtr->noa_list_t.noa_descs, 0, sizeof(struct noa_desc)); + noa_num = (tag_len - 2) / 13; + if (noa_num) { + priv->p2pPtr->noa_list_t.noa_descs.count = *(pData + 2); + memcpy(&u32, (pData + 2) + 1, 4); + priv->p2pPtr->noa_list_t.noa_descs.duration = le32_to_cpu(u32); + memcpy(&u32, (pData + 2) + 5, 4); + priv->p2pPtr->noa_list_t.noa_descs.interval = le32_to_cpu(u32); + memcpy(&u32, (pData + 2) + 9, 4); + priv->p2pPtr->noa_list_t.noa_descs.starttime = le32_to_cpu(u32); + } + + P2P_DEBUG("Update NoA (seq %d): index %d, OppPs 0x%02x, NoA count %d, duration %d, interval %d, start 0x%08x\n", + seq, + priv->p2pPtr->noa_list_t.index, + priv->p2pPtr->noa_list_t.CTWindow_OppPs, + priv->p2pPtr->noa_list_t.noa_descs.count, + priv->p2pPtr->noa_list_t.noa_descs.duration, + priv->p2pPtr->noa_list_t.noa_descs.interval, + priv->p2pPtr->noa_list_t.noa_descs.starttime); + + p2p_process_noa(priv); + } +} + + +#define P2P_TAG_SEARCH 0 // no meaning + + +/*P2P TLV format: T(1B)L(2B)V(var)*/ +unsigned char* p2p_search_tag(unsigned char *data_be_search, + int data_len,unsigned char tag, int *out_len) +{ + unsigned char id; + unsigned short tag_len; + int size; + + while (data_len > 0) { + memcpy(&id, data_be_search, 1); + memcpy(&tag_len, data_be_search+1, 2); + tag_len = le16_to_cpu(tag_len); + + if (id == tag) { + if (data_len >= (1+2+ tag_len)) { + + *out_len = (int)tag_len; + return (&data_be_search[3]); + } + else { + P2P_PRINT("Found tag [0x%x], but invalid length!\n", tag); + P2P_PRINT("data_len=%d , 1+2+tag_len(%d)\n", data_len , tag_len); + break; + } + } + size = 1+2 + tag_len; + data_be_search += size; + data_len -= size; + } + + return NULL; +} + + + +unsigned char *p2p_check_tag(unsigned char *TLV_data, int TLV_len, unsigned char tag, int *o_len) +{ + unsigned char *pData; + int tag_len; +#ifdef P2P_DEBUGMSG + unsigned char tmpstr[50]; + unsigned char tmpstr2[50]; + unsigned short tmp_u16_1; + unsigned short tmp_u16_2; +#endif + + + + pData = p2p_search_tag(TLV_data, TLV_len,tag, &tag_len); + + if (pData == NULL) { + + return NULL; + }else{ + P2P_PRINT("tag(%d) :", tag); + } + +#ifdef P2P_DEBUGMSG + switch(tag){ + + case TAG_STATUE : + P2P_PRINT(" Status:%d\n",pData[0]); + break; + case TAG_MINOR_RES_CODE : + P2P_PRINT(" Minor reason code: %d\n",pData[0]); + break; + case TAG_P2P_CAPABILITY : + ShowValByBinary(pData[0] , tmpstr , 8); + ShowValByBinary(pData[1] , tmpstr2 , 8); + P2P_PRINT(" p2p Capability: (%s %s)\n",tmpstr,tmpstr2); + parse_p2p_Capability(); + break; + case TAG_DEVICE_ID : + P2P_PRINT(" Device ID: %02x%02x%02x:%02x%02x%02x\n", + pData[0],pData[1],pData[2],pData[3],pData[4],pData[5]); + break; + case TAG_GROUP_OWNER_INTENT : + P2P_PRINT(" Owner Intent: %d , Tie=%d\n",pData[0]>>1 , pData[0]&0x1); + break; + case TAG_CONFIG_TIMEOUT : + P2P_PRINT(" Config Timeout: = (%d,%d)\n",pData[0],pData[1]); + break; + case TAG_LISTEN_CHANNEL : + P2P_PRINT(" Listen Channel: (country code),%d,%d \n",pData[3],pData[4]); + break; + case TAG_P2P_GROUP_BSSID : + P2P_PRINT(" p2p Group BSSID:%02x%02x%02x:%02x%02x%02x\n", + pData[0],pData[1],pData[2],pData[3],pData[4],pData[5]); + break; + case TAG_EXT_LISTEN_TIMING : + tmp_u16_1 = *(unsigned short*)pData; + tmp_u16_2 = *(unsigned short*)(pData+2); + P2P_PRINT(" Extended Listen Timing: (%d ,%d)\n",tmp_u16_1,tmp_u16_2); + break; + case TAG_INTEN_P2P_INTERFACE_ADDR : + P2P_PRINT(" INTENED P2P INTERFACE ADDR=%02x%02x%02x:%02x%02x%02x\n", + pData[0],pData[1],pData[2],pData[3],pData[4],pData[5]); + break; + case TAG_P2P_MANAGEABILITY : + ShowValByBinary(pData[0] , tmpstr , 8); + P2P_PRINT(" P2P Manageability =%s\n",tmpstr); + break; + case TAG_CHANNEL_LIST : + + P2P_PRINT(" Channel List\n"); + parse_channel_list(pData , tag_len ,NULL); + break; + + case TAG_NOTICE_OF_ABSENCE : + //TODO ; more detail + P2P_PRINT(" Notice of Absence\n"); + break; + case TAG_P2P_DEVICE_INFO : + + P2P_PRINT(" P2P Device Info \n"); + parse_device_info(pData,tag_len,NULL); + break; + + case TAG_P2P_GROUP_INFO : + + P2P_PRINT(" p2p Group Info \n"); + parse_group_info(pData,tag_len); + break; + + case TAG_P2P_GROUP_ID : + + P2P_PRINT(" p2p Group ID\n"); + parse_group_id(pData,tag_len,NULL); + break; + + case TAG_P2P_INTERFACE : + + P2P_PRINT(" P2P INTERFACE \n"); + parse_p2p_interface(pData,tag_len); + break; + + case TAG_OPERATION_CHANNEL : + strncpy(tmpstr , pData , 3); + P2P_PRINT(" Operation Channel ,country code=%s operation class=%d ,channel number=%d \n", + tmpstr , pData[3],pData[4]); + break; + case TAG_INVITATION_FLAGS : + ShowValByBinary(pData[0] , tmpstr , 8) ; + P2P_PRINT(" Invitation Flags=%s\n",tmpstr); + break; + default: + P2P_PRINT("Unknow TAG ID \n"); + break; + } + +#endif + *o_len = tag_len; + return pData; +} + + +#define GET_INFO 0 // no meaning +int p2p_get_role(struct rtl8192cd_priv *priv, + unsigned char *p2p_ie,int p2pIElen ) +{ + unsigned char* p2p_capa; + int tag_len = 0; + + p2p_capa = p2p_search_tag(p2p_ie , p2pIElen , TAG_P2P_CAPABILITY , &tag_len); + + + if(p2p_capa[1] & BIT(0)) + return R_P2P_GO; // GO + else + return R_P2P_DEVICE; // device + +} +void p2p_get_device_info(struct rtl8192cd_priv *priv, + unsigned char *p2p_ie ,int p2pIElen ,struct device_info_s* dev_info_ptr) +{ + unsigned char* p2p_sub_ie; + int tag_len = 0; + + p2p_sub_ie = p2p_search_tag(p2p_ie , p2pIElen , TAG_P2P_DEVICE_INFO , &tag_len); + if(p2p_sub_ie){ + parse_device_info(p2p_sub_ie,tag_len, dev_info_ptr); + }else{ + P2P_DEBUG("can't found DEVICE_INFO\n\n"); + } + +} + +int p2p_get_GO_p2p_info(struct rtl8192cd_priv *priv, + unsigned char *p2p_ie ,int p2pIElen ,struct device_info_s* dev_info_ptr) +{ + unsigned char* p2p_sub_ie=NULL; + int tag_len = 0; + + /*ID3*/ + p2p_sub_ie = p2p_search_tag(p2p_ie , p2pIElen , TAG_DEVICE_ID , &tag_len); + if(p2p_sub_ie ){ + memcpy(dev_info_ptr->dev_address , p2p_sub_ie , 6); + //MAC_PRINT(dev_info_ptr->dev_address); + return SUCCESS; + }else{ + return FAIL; + } +} + +void p2p_get_GO_wsc_info(struct rtl8192cd_priv *priv, + unsigned char *wsc_ie ,int wscIElen ,struct device_info_s *dev_info_ptr) +{ + unsigned char* p2p_sub_ie=NULL; + int tag_len = 0; + + + p2p_sub_ie = search_wsc_tag(wsc_ie, TAG_CONFIG_METHODS, wscIElen, &tag_len); + if(p2p_sub_ie){ + dev_info_ptr->config_method = *(unsigned short *)p2p_sub_ie ; + //P2P_DEBUG("wsc method = %02x\n",dev_info_ptr->config_method); + } + + p2p_sub_ie = search_wsc_tag(wsc_ie, TAG_DEVICE_NAME, wscIElen, &tag_len); + if(p2p_sub_ie){ + memcpy(dev_info_ptr->devname , p2p_sub_ie ,tag_len) ; + dev_info_ptr->devname[tag_len]='\0'; + //P2P_DEBUG("device name = %s\n",dev_info_ptr->devicename); + } + + + +} + + + +#define ADD_P2P_ATTRIBUTE 0 // no meaning + + +unsigned char *wsc_add_tlv(unsigned char *data, unsigned short id, int len, void *val) +{ + unsigned short size = htons(len); + unsigned short tag = htons(id); + + memcpy(data, &tag, 2); + memcpy(data+2, &size, 2); + memcpy(data+4, val, len); + + return (data+4+len); +} + + + +void add_primarydevtype(struct rtl8192cd_priv *priv ,unsigned char * AttrPtr) +{ + + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short shortVal = 0; + + if(OPMODE & WIFI_AP_STATE) + shortVal = P2P_device_category_id_AP; + else + shortVal = P2P_device_category_id_STA; + + memcpy(thisAttrPrt, &shortVal, 2); + + memcpy(thisAttrPrt+2, WSC_IE_OUI, 4); + + shortVal = P2P_device_sub_category_id; + + memcpy(thisAttrPrt+6, &shortVal, 2); + + +} + +unsigned char* add_Attr_status(struct rtl8192cd_priv *priv ,unsigned char * AttrPtr + , unsigned char *p2pIELen ,unsigned char status ) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 1 ; + + thisAttrPrt[0] = TAG_STATUE; + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + thisAttrPrt[3] = status; + + *p2pIELen += (1+3); + thisAttrPrt += (1+3); + + return thisAttrPrt; +} + + +unsigned char* add_Attr_minor_reason(struct rtl8192cd_priv *priv + ,unsigned char * AttrPtr , unsigned char *p2pIELen ,unsigned char reason ) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 1 ; + thisAttrPrt[0] = TAG_MINOR_RES_CODE; + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + thisAttrPrt[3] = reason; + *p2pIELen += (1+3); + thisAttrPrt += (1+3); + return thisAttrPrt; +} + +unsigned char* add_Attr_capability( + struct rtl8192cd_priv *priv ,unsigned char * AttrPtr , + unsigned char *p2pIELen ,struct p2p_device_peer *current_nego_peer) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned char deviceCap = 0; + unsigned char groupCap = 0; + unsigned short attrlen = 2 ; + + /* set devce cap*/ + if(P2PMODE == P2P_TMP_GO || P2PMODE == P2P_CLIENT) + { + deviceCap |= CLIENT_DISCOVERY; + } + + + + /* set group cap*/ + /* i am prepare as GO*/ + if(current_nego_peer && current_nego_peer->role == R_P2P_CLIENT){ + groupCap |= GCAP_IBSS_DIST ; + } + + if(P2PMODE ==P2P_TMP_GO) + { + groupCap |= GCAP_GO; + groupCap |= GCAP_IBSS_DIST ; + } + + + /*when i am pre-go , indicate that it's wps ongoing*/ + if(P2PMODE == P2P_PRE_GO ){ + groupCap |= GCAP_GO_FORMATION; + } + + if(priv->p2pPtr->persistent_go) + groupCap |= GCAP_PRESISTENT_GO; + + if(priv->p2pPtr->p2p_go_limit) + groupCap |= GCAP_GROUP_LIMIT; + + + + thisAttrPrt[0] = TAG_P2P_CAPABILITY; + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + thisAttrPrt[3] = deviceCap; + thisAttrPrt[4] = groupCap; + + *p2pIELen += (2+3); + thisAttrPrt += (2+3); + + + + return thisAttrPrt; + +} + + + + +/* SPEC 1.1 page 83*/ +unsigned char* add_Attr_device_id( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=6; + + thisAttrPrt[0] = TAG_DEVICE_ID; + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + memcpy(thisAttrPrt+3 , GET_MY_HWADDR , 6); + + + *p2pIELen+= (6+3); + thisAttrPrt += (6+3); + + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 84*/ +unsigned char* add_Attr_GO_intent(struct rtl8192cd_priv *priv ,unsigned char * AttrPtr + , unsigned char *p2pIELen , int tieBreak) +{ + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 1 ; + unsigned char intent = 0; + + thisAttrPrt[0] = TAG_GROUP_OWNER_INTENT; + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + intent = priv->pmib->p2p_mib.p2p_intent<<1; + + if(tieBreak) + intent |= 0x1; + + thisAttrPrt[3] = intent; + + *p2pIELen+= (1+3); + thisAttrPrt += (1+3); + + return thisAttrPrt; +} + +/* SPEC 1.1 page 84*/ +unsigned char* add_Attr_configration_timeout( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , + unsigned char *p2pIELen , int MyRole) +{ + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 2 ; + unsigned short attrlen2 = 2 ; + + + thisAttrPrt[0] = TAG_CONFIG_TIMEOUT; + + attrlen2 = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen2 ,2); + + + if(MyRole==R_P2P_GO){ + thisAttrPrt[3] = 0xff; + thisAttrPrt[4] = 0; + }else{ + thisAttrPrt[3] = 0; + thisAttrPrt[4] = 0xff; + } + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + + +/* SPEC 1.1 page 85*/ +unsigned char* add_Attr_listenChannel( + struct rtl8192cd_priv *priv , unsigned char * AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=5; + + thisAttrPrt[0] = TAG_LISTEN_CHANNEL; // ID6 + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + memcpy(thisAttrPrt + 3, priv->p2pPtr->my_channel_list.country,3); + + thisAttrPrt[6] = 0x51; + thisAttrPrt[7] = priv->pmib->p2p_mib.p2p_listen_channel; + + *p2pIELen+= (5+3); + thisAttrPrt += (5+3); + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 85;include in invitation req,no support now*/ +unsigned char* add_Attr_group_bssid( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + //unsigned short attrlen = 0 ; + P2P_DEBUG("TODO\n"); + + return thisAttrPrt; + +} + +/* SPEC 1.1 page 86*/ +unsigned char* add_Attr_extended_listen_timing( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen, + unsigned short period ,unsigned short interval ) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 4; + unsigned short attrlen2 ; + + thisAttrPrt[0] = TAG_EXT_LISTEN_TIMING; // ID8 + + + attrlen2 = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen2 ,2); + + attrlen2 = cpu_to_le16(period); + memcpy(thisAttrPrt+3 , (void *)&attrlen2 ,2); + + attrlen2 = cpu_to_le16(interval); + memcpy(thisAttrPrt+5 , (void *)&attrlen2 ,2); + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 87*/ +unsigned char* add_Attr_intended_interface( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=6; + thisAttrPrt[0] = TAG_INTEN_P2P_INTERFACE_ADDR; // ID 9 + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + memcpy(thisAttrPrt+3 , GET_MY_HWADDR , 6); + + + *p2pIELen+= (6+3); + thisAttrPrt += (6+3); + + return thisAttrPrt; + +} + +/* SPEC 1.1 page 87*/ +unsigned char* add_Attr_manageability( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + +/* + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 0 ; + P2P_DEBUG("TODO\n"); + + return thisAttrPrt; +*/ + return NULL; +} + + +/* SPEC 1.1 page 88 ; ID 11 */ +unsigned char* add_Attr_channel_list( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=0; + unsigned short attrlen2=0; + int idx = 0; + + thisAttrPrt[0] = TAG_CHANNEL_LIST; // ID 11 + + attrlen2 = priv->p2pPtr->my_channel_list.Id11_len; + attrlen= priv->p2pPtr->my_channel_list.Id11_len; + // P2P_DEBUG("channel list len=%d\n",priv->p2pPtr->my_channel_list.Id11_len); + attrlen2 = cpu_to_le16(attrlen2); + memcpy(&thisAttrPrt[1] , (void *)&attrlen2 ,2); // attri len + + memcpy(&thisAttrPrt[3] , priv->p2pPtr->my_channel_list.country , 3); //country code + + + + thisAttrPrt[6] = priv->p2pPtr->my_channel_list.reg_class[0].reg_class; + thisAttrPrt[7] = priv->p2pPtr->my_channel_list.reg_class[0].channel_mun; + for(idx=0;idx<11;idx++) + thisAttrPrt[8+idx] =priv->p2pPtr->my_channel_list.reg_class[0].channel[idx]; + + thisAttrPrt[19] = priv->p2pPtr->my_channel_list.reg_class[1].reg_class; + thisAttrPrt[20] = priv->p2pPtr->my_channel_list.reg_class[1].channel_mun; + for(idx=0;idx<4;idx++) + thisAttrPrt[21+idx] =priv->p2pPtr->my_channel_list.reg_class[1].channel[idx]; + + thisAttrPrt[25] = priv->p2pPtr->my_channel_list.reg_class[2].reg_class; + thisAttrPrt[26] = priv->p2pPtr->my_channel_list.reg_class[2].channel_mun; + for(idx=0;idx<5;idx++) + thisAttrPrt[27+idx] =priv->p2pPtr->my_channel_list.reg_class[2].channel[idx]; + + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + return thisAttrPrt; +} + + +/* SPEC 1.1 page 89*/ +unsigned char* add_Attr_notice_of_absence( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 2; + unsigned short attrlen2 = 0; + + thisAttrPrt[0] = TAG_NOTICE_OF_ABSENCE; // ID 9 + + attrlen2 = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen2 ,2); + + thisAttrPrt[3] = 0; // index + thisAttrPrt[4] = 0; // no oppPS , no CTWindow + + + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 85*/ +unsigned char* add_Attr_device_info( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + struct wifi_mib *pmib=priv->pmib; + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen = 0 ; + unsigned short lentmp = 0 ; + //unsigned short u16_tmp = 0 ; + + thisAttrPrt[0] = TAG_P2P_DEVICE_INFO; + + /*fill attr len later*/ + thisAttrPrt+=3 ; // id(1) + len(2) + + /*P2P device address*/ + memcpy(thisAttrPrt , pmib->dot11OperationEntry.hwaddr , 6); + thisAttrPrt+=6 ; + attrlen+=6 ; + + /*config method*/ + memcpy(thisAttrPrt , (void *)&pmib->p2p_mib.p2p_wsc_config_method , 2); + thisAttrPrt+=2 ; + attrlen+=2 ; + + add_primarydevtype(priv,thisAttrPrt); + thisAttrPrt+=8 ; + attrlen+=8 ; + + /* number of second dev type*/ + thisAttrPrt[0]=0; + thisAttrPrt+=1 ; + attrlen+=1 ; + + + /* add Device name ; WSC TLV (2+2+N)*/ + lentmp = strlen( pmib->p2p_mib.p2p_device_name ); + thisAttrPrt = wsc_add_tlv(thisAttrPrt, TAG_DEVICE_NAME, + lentmp, pmib->p2p_mib.p2p_device_name); + attrlen+= (lentmp + 4); + + + /*Attribute len */ + lentmp = cpu_to_le16(attrlen); + memcpy(AttrPtr+1 ,(void *)&lentmp ,2); + + *p2pIELen += (attrlen+3); + //p2p_debug_out("device info content", AttrPtr, attrlen); + return thisAttrPrt; + +} + + + +/* SPEC 1.1 page 93*/ +unsigned char* add_Attr_group_info( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + + unsigned char* tmpPtr = NULL; + int per_desc_len = 0; + int idx ; + unsigned short attrlen = 0 ; + unsigned short attrlen2 = 0 ; + int tmplen = 0 ; + + P2P_DEBUG("\n"); + thisAttrPrt[0] = TAG_P2P_GROUP_INFO; + + thisAttrPrt +=3; + + for(idx=0 ; idx < MAX_P2P_CLIENT_MUN; idx++){ + if(priv->p2pPtr->assocPeers[idx].inuse){ + + per_desc_len=0; + tmpPtr = thisAttrPrt; // keep len addr + thisAttrPrt +=1; // skip len + + memcpy(thisAttrPrt,priv->p2pPtr->assocPeers[idx].devInfo.dev_address,6); + thisAttrPrt +=6; + per_desc_len +=6; + + memcpy(thisAttrPrt,priv->p2pPtr->assocPeers[idx].if_addr,6); + thisAttrPrt +=6; + per_desc_len +=6; + + thisAttrPrt[0]=priv->p2pPtr->assocPeers[idx].dev_cap ; // len ==1 + thisAttrPrt +=1; + per_desc_len +=1; + + memcpy(thisAttrPrt,&priv->p2pPtr->assocPeers[idx].devInfo.config_method,2); + thisAttrPrt +=2; + per_desc_len +=2; + + memcpy(thisAttrPrt,priv->p2pPtr->assocPeers[idx].devInfo.pri_dev_type,8); + thisAttrPrt +=8; + per_desc_len +=8; + + thisAttrPrt[0] = 0 ; // second dev type count == 0 + thisAttrPrt +=1; + per_desc_len +=1; + + + /*device name ; WSC TLV (2+2+N)*/ + tmplen = strlen(priv->p2pPtr->assocPeers[idx].devInfo.devname); + thisAttrPrt = wsc_add_tlv(thisAttrPrt, TAG_DEVICE_NAME, + tmplen, priv->p2pPtr->assocPeers[idx].devInfo.devname); + + per_desc_len += (2+2+tmplen); + + + tmpPtr[0] = per_desc_len; + attrlen += per_desc_len ; + + } + } + + + + attrlen2 = attrlen; + attrlen2 = cpu_to_le16(attrlen2); + memcpy(&AttrPtr[1] , (void *)&attrlen2 ,2); + + + *p2pIELen += (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + +/* SPEC 1.1 page 94*/ +unsigned char* add_Attr_group_id( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + + unsigned short attrlen = 0 ; + unsigned short attrlen2 = 0 ; + + thisAttrPrt[0] = TAG_P2P_GROUP_ID; + + + memcpy(&thisAttrPrt[3] , GET_MY_HWADDR , 6); + attrlen+=6; + + memcpy(&thisAttrPrt[9] , priv->p2pPtr->my_GO_ssid, priv->p2pPtr->my_GO_ssid_len); + attrlen += priv->p2pPtr->my_GO_ssid_len; + + attrlen2 = attrlen; + attrlen2 = cpu_to_le16(attrlen2); + memcpy(&thisAttrPrt[1] , (void *)&attrlen2 ,2); + + + *p2pIELen += (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + + +/* SPEC 1.1 page 94*/ +unsigned char* add_Attr_Target_group_id( struct rtl8192cd_priv *priv , + unsigned char* AttrPtr , unsigned char *p2pIELen , + unsigned char* tarssid , unsigned char* tardevaddr) +{ + + unsigned char* thisAttrPrt = AttrPtr; + + unsigned short attrlen = 0 ; + unsigned short attrlen2 = 0 ; + + thisAttrPrt[0] = TAG_P2P_GROUP_ID; + + + memcpy(&thisAttrPrt[3] , tardevaddr, 6); + attrlen+=6; + + memcpy(&thisAttrPrt[9] , tarssid, strlen(tarssid)); + attrlen += strlen(tarssid) ; + + attrlen2 = attrlen; + attrlen2 = cpu_to_le16(attrlen2); + memcpy(&thisAttrPrt[1] , (void *)&attrlen2 ,2); + + + *p2pIELen += (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + +/* SPEC 1.1 page 95*/ +unsigned char* add_Attr_operation_channel( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=5; + + thisAttrPrt[0] = TAG_OPERATION_CHANNEL; + + attrlen = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen ,2); + + + memcpy(thisAttrPrt + 3, priv->p2pPtr->my_channel_list.country,3); + + + if(priv->pmib->p2p_mib.p2p_op_channel>=1 && priv->pmib->p2p_mib.p2p_op_channel<=14) + thisAttrPrt[6] = 81; + else if(priv->pmib->p2p_mib.p2p_op_channel>=36 && priv->pmib->p2p_mib.p2p_op_channel<=48) + thisAttrPrt[6] = 115; + else if(priv->pmib->p2p_mib.p2p_op_channel>=149 && priv->pmib->p2p_mib.p2p_op_channel<=165) + thisAttrPrt[6] = 124; + + thisAttrPrt[7] = priv->pmib->p2p_mib.p2p_op_channel; + + *p2pIELen+= (5+3); + thisAttrPrt += (5+3); + + return thisAttrPrt; + +} + +/* SPEC 1.1 page 96*/ +unsigned char* add_Attr_invitation_flag( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + P2P_DEBUG("TODO\n"); + return NULL; +} + + +/* SPEC 1.1 page 94*/ +unsigned char* add_Attr_interface( + struct rtl8192cd_priv *priv , unsigned char* AttrPtr , unsigned char *p2pIELen) +{ + + + unsigned char* thisAttrPrt = AttrPtr; + unsigned short attrlen=0; + unsigned short attrlen2=0; + thisAttrPrt[0] = TAG_P2P_INTERFACE; + + attrlen2 = cpu_to_le16(attrlen); + memcpy(thisAttrPrt+1 , (void *)&attrlen2 ,2); + + + *p2pIELen+= (attrlen+3); + thisAttrPrt += (attrlen+3); + + return thisAttrPrt; + +} + + +#define BUILD_IE 0 // no meaning + + +int wsc_build_probe_rsp_ie(struct rtl8192cd_priv *priv , + unsigned char *data , unsigned short DEVICE_PASSWORD_ID) +{ + + + + unsigned char *pMsg; + unsigned char byteVal; + unsigned short shortVal; + unsigned char tmpbuf2[100]; + int len5; + + /*Element ID*/ + data[0] = WSC_IE_ID; + + /*OUI*/ + memcpy(&data[2], WSC_IE_OUI, 4); + pMsg = &data[2+4]; + + /*Version*/ + byteVal = WSC_VER; + pMsg = wsc_add_tlv(pMsg, TAG_VERSION, 1, (void *)&byteVal); + + + /*config state*/ + //fixed to AP mode + byteVal = 2; //configured + + pMsg = wsc_add_tlv(pMsg, TAG_SIMPLE_CONFIG_STATE, 1, (void *)&byteVal); + + // fixed to AP mode + byteVal = RSP_TYPE_AP; + pMsg = wsc_add_tlv(pMsg, TAG_RESPONSE_TYPE2, 1, (void *)&byteVal); + + /*UUID-E*/ + //pMsg = wsc_add_tlv(pMsg, TAG_UUID_E, UUID_LEN, (void *)priv->p2pPtr->uuid); + //pMsg = wsc_add_tlv(pMsg, TAG_MANUFACTURER, strlen(priv->p2pPtr->manufacturer), priv->p2pPtr->manufacturer); + //pMsg = wsc_add_tlv(pMsg, TAG_MODEL_NAME, strlen(priv->p2pPtr->model_name), priv->p2pPtr->model_name); + //pMsg = wsc_add_tlv(pMsg, TAG_MODEL_NUMBER, strlen(priv->p2pPtr->model_num), priv->p2pPtr->model_num); + //pMsg = wsc_add_tlv(pMsg, TAG_SERIAL_NUM, strlen(priv->p2pPtr->serial_num), priv->p2pPtr->serial_num); + + + /*----TAG_PRIMARY_DEVICE_TYPE -----start*/ + + if(OPMODE & WIFI_AP_STATE) + shortVal = P2P_device_category_id_AP; + else + shortVal = P2P_device_category_id_STA; + + memcpy(tmpbuf2, &shortVal, 2); + + memcpy(&tmpbuf2[2], WSC_IE_OUI, 4); + + shortVal = P2P_device_sub_category_id; + memcpy(&tmpbuf2[6], &shortVal, 2); + pMsg = wsc_add_tlv(pMsg, TAG_PRIMARY_DEVICE_TYPE, 8, (void *)tmpbuf2); + + /*----TAG_PRIMARY_DEVICE_TYPE -----end*/ + + /*device name */ + pMsg = wsc_add_tlv(pMsg, TAG_DEVICE_NAME, + strlen(priv->pmib->p2p_mib.p2p_device_name), priv->pmib->p2p_mib.p2p_device_name); + + /*config method*/ + pMsg = wsc_add_tlv(pMsg, TAG_CONFIG_METHODS, 2, (void *)&priv->pmib->p2p_mib.p2p_wsc_config_method); + + shortVal = DEVICE_PASSWORD_ID; + pMsg = wsc_add_tlv(pMsg, TAG_DEVICE_PASSWORD_ID, 2, &shortVal); + + /*Element Length*/ + len5 = (int)(((unsigned long)pMsg)-((unsigned long)data)) -2; + data[1] = (unsigned char)len5; + + return (len5+2); +} + + + +// (TLV , T(1),L(1)) +int p2p_build_probe_rsp_ie(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + + + thisAttrPrt[0]=_P2P_IE_; + + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen ,NULL); + + /*extended listen timing (OPTIONAL)*/ + + /*notice of absence ;shell only tx by GO*/ + + + /*ID13*/ + thisAttrPrt = add_Attr_device_info(priv, thisAttrPrt ,&p2pIELen); + + /*ID14 ,only include by GO*/ + if(P2PMODE == P2P_TMP_GO){ + thisAttrPrt = add_Attr_group_info(priv, thisAttrPrt ,&p2pIELen); + } + + + data[1]=p2pIELen; + + //p2p_debug_out("probe_rsp", data, p2pIELen+2); + + return p2pIELen+2; + +} + + +int p2p_build_probe_req_ie(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + unsigned char p2pIELen=0; + unsigned char* thisAttrPrt = data; + + thisAttrPrt[0]=_P2P_IE_; + + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen += 4; + thisAttrPrt += 4; + + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen ,NULL); + + /*ID3 ; for search spec address */ + if(!is_zero_ether_addr(priv->p2pPtr->spec_find_dev_addr)) + thisAttrPrt = add_Attr_device_info(priv, thisAttrPrt ,&p2pIELen); + + + /*ID6*/ + thisAttrPrt = add_Attr_listenChannel( priv, thisAttrPrt, &p2pIELen); + + + /*extended listen timing ;(OPTIONAL) no support now*/ + + + /*ID17 ; only include by GO*/ + if(P2PMODE ==P2P_TMP_GO){ + thisAttrPrt = add_Attr_operation_channel( priv, thisAttrPrt, &p2pIELen); + } + + + data[1]= p2pIELen; + + //p2p_debug_out("probe_req", data, p2pIELen+2); + + return p2pIELen+2; + +} + + + + + +int p2p_build_beacon_ie(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + + //P2P_DEBUG("\n"); + thisAttrPrt[0]=_P2P_IE_; + + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen ,NULL); + + /*ID3*/ + thisAttrPrt = add_Attr_device_id(priv, thisAttrPrt ,&p2pIELen); + + data[1]=p2pIELen; + + //p2p_debug_out("beacon p2p IE", data, p2pIELen+2); + + return p2pIELen+2; + +} + +int p2p_build_assocReq_ie(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + + P2P_DEBUG("\n"); + thisAttrPrt[0]=_P2P_IE_; + + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /* ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen ,NULL); + + /* ID13 */ + thisAttrPrt = add_Attr_device_info(priv, thisAttrPrt ,&p2pIELen); + + data[1]=p2pIELen; + + p2p_debug_out("assoc p2p IE", data, p2pIELen+2); + + return p2pIELen+2; + +} + + +int p2p_build_assocRsp_ie(struct rtl8192cd_priv *priv, unsigned char *data + ,unsigned char status) +{ + + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + + //P2P_DEBUG("\n"); + thisAttrPrt[0]=_P2P_IE_; + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + /*ID0*/ + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,status); + + data[1]=p2pIELen; + + p2p_debug_out("AssocRsp p2p IE", data, p2pIELen+2); + + return p2pIELen+2; + +} + + +int p2p_build_deassoc_ie(struct rtl8192cd_priv *priv, + unsigned char *data ,unsigned char reason) +{ + unsigned char p2pIELen = 0; + unsigned char* thisAttrPrt = data; + P2P_DEBUG("\n"); + thisAttrPrt[0]=_P2P_IE_; + thisAttrPrt+=2; + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + /*ID1*/ + thisAttrPrt = add_Attr_minor_reason( priv, thisAttrPrt, &p2pIELen ,reason); + + data[1]=p2pIELen; + //p2p_debug_out("disassoc p2p IE", data, p2pIELen+2); + return p2pIELen+2; + +} + + +#define HANDLE_P2P_ACTION_FRAME 0 // no meaning + +#define GO_mdoe_handle_P2P_action_frame 0 // no meaning + + +int p2p_issue_GO_discovery_req( + struct rtl8192cd_priv *priv , + unsigned char *da) +{ + + unsigned char *pbuf = NULL; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_GO_dis_req_fail1; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_GO_dis_req_fail1; + + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + pbuf[0] = _VENDOR_ACTION_ID_; + memcpy(&pbuf[1],WFA_OUI_PLUS_TYPE,4); + pbuf[5] = P2P_GO_DISCOVERY; + + txinsn.fr_len += 6; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_PRINT("\n"); + P2P_DEBUG("TX GO discovery Req success!!\n"); + MAC_PRINT(da); + + /*only expect will rx ack, that is all*/ + return SUCCESS; + } + +issue_GO_dis_req_fail1: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; + + +} + + + + +/* page 68 */ +int p2p_issue_presence_rsp(struct rtl8192cd_priv *priv , unsigned char *da) +{ + + unsigned char *pbuf; + unsigned char *thisAttrPrt; + unsigned char p2pIELen = 0; + unsigned char *P2PIEstart=NULL; + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_presenceRsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_presenceRsp_fail; + + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + pbuf[0] = _VENDOR_ACTION_ID_; + memcpy(&pbuf[1],WFA_OUI_PLUS_TYPE,4); + pbuf[5] = P2P_PRESENCE_RSP; + pbuf[6] = priv->p2pPtr->presence_rx_dialog_token; + + + + /*P2P ID*/ + thisAttrPrt = pbuf + _P2P_ACTION_IE_OFFSET_; + p2pIELen = 0; + P2PIEstart = thisAttrPrt; + + thisAttrPrt[0] = P2P_IE_ID; + thisAttrPrt+=2; // ID + LEN + + /*P2P OUI+TYPE*/ + memcpy(thisAttrPrt, WFA_OUI_PLUS_TYPE, 4); + thisAttrPrt+=4; // OUI LEN + p2pIELen +=4; + + /*ID0*/ + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,P2P_SC_SUCCESS); + + + /*ID12*/ + thisAttrPrt = add_Attr_notice_of_absence(priv , thisAttrPrt, &p2pIELen ); + + P2PIEstart[1] = p2pIELen; + + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_PRINT("\n"); + P2P_DEBUG("TX Presence Rsp OK\n"); + MAC_PRINT(da); + return SUCCESS; + } + +issue_presenceRsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; + + +} + + +/* page 68 */ +void p2p_on_presence_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + + int tmplen=0; + unsigned char* tmpPtr=NULL; + + int foundP2PIE = 0; + unsigned char *P2PIEPtr = NULL ; + int P2PIElen=0; + unsigned char *p2p_sub_ie=NULL; + + P2P_DEBUG("\n"); + priv->p2pPtr->presence_rx_dialog_token = pframe[6] ; + + //========================================================================== + /*get P2P IE*/ + tmpPtr = pframe + _P2P_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + tmpPtr = get_ie(tmpPtr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_ACTION_IE_OFFSET_ - tmplen); + + if(tmpPtr!=NULL){ + if (!memcmp(tmpPtr+2, WFA_OUI_PLUS_TYPE, 4)) { + P2PIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + P2PIEPtr = tmpPtr+6 ; + foundP2PIE = 1; + break; + } + }else{ + break ; + } + tmpPtr = tmpPtr + tmplen +2 ; + } + + if(foundP2PIE){ + p2p_sub_ie = p2p_search_tag(P2PIEPtr, P2PIElen, TAG_NOTICE_OF_ABSENCE, &tmplen); + if (p2p_sub_ie) { + //parse_p2p_NOA(priv, p2p_sub_ie, tmplen, GetSequence(pframe)); + // we don't support PS under GO now , do nothing + } + else { + P2P_DEBUG("can't found NOA IE\n"); + } + + }else{ + P2P_DEBUG("can't found P2P IE\n"); + } + //========================================================================= + //========================================================================== + p2p_issue_presence_rsp(priv,pfrinfo->sa); + + +} + + +// page 109 +int P2P_on_action(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + + unsigned char *pframe=NULL; + pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; //start of action frame content + P2P_DEBUG("RX ,action frame"); + switch(pframe[5]){ + + case P2P_NOA: + P2P_PRINT("\n"); + P2P_DEBUG("RX P2P NOA\n"); + if(P2PMODE == P2P_CLIENT){ + + }else{ + P2P_DEBUG("but no under client mode\n"); + } + break; + case P2P_PRESENCE_REQ: + P2P_PRINT("\n"); + P2P_DEBUG("RX P2P Presence Req\n"); + if(P2PMODE == P2P_TMP_GO){ + p2p_on_presence_req(priv,pfrinfo); + }else{ + P2P_DEBUG("but no under GO mode\n"); + } + break; + case P2P_PRESENCE_RSP: + P2P_PRINT("\n"); + P2P_DEBUG("RX P2P Presence Rsp\n"); + if(P2PMODE == P2P_CLIENT){ + + }else{ + P2P_DEBUG("but no under client mode\n"); + } + break; + + case P2P_GO_DISCOVERY: + P2P_PRINT("\n"); + P2P_DEBUG("RX P2P GO DISCOVERY,just ack\n"); + break; + default: + P2P_DEBUG("!!! Unknow type p2p action \n"); + break; + } + return 0; +} + + +#define HANDLE_P2P_PUBLIC_ACTION_FRAME 0 // no meaning + + +int p2p_issue_device_discovery_rsp( + struct rtl8192cd_priv *priv , + unsigned char *da , unsigned char status) +{ + + unsigned char *pbuf = NULL; + unsigned char *IEStart=NULL; + unsigned char *thisAttrPrt=NULL; + unsigned char p2pIELen = 0; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_dev_dis_rsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_dev_dis_rsp_fail; + + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_DEV_DISC_RESP; + pbuf[7] = priv->p2pPtr->dev_dis_req_dialog_token ; + + thisAttrPrt = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; + IEStart = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; //anchor + + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,status); + IEStart[1] = p2pIELen; + + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + P2P_PRINT("\n"); + P2P_DEBUG("TX Device Discovery Rsp success!!\n"); + MAC_PRINT(da); + return SUCCESS; + } + +issue_dev_dis_rsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; + + +} + + +void p2p_on_device_discovery_req( + struct rtl8192cd_priv *priv , + struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + unsigned char *IEptr = NULL; + int tmplen = 0; + int foundP2PIE=0; + int p2pIElen = 0 ; + unsigned char *p2pIEPtr = NULL; + int idx; + struct p2p_device_peer *current_nego_peer=NULL; + + priv->p2pPtr->dev_dis_req_dialog_token = pframe[7]; + + + /*-----------------------------get P2P IE(start)------------------------------*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + p2pIEPtr = IEptr+6 ; + foundP2PIE = 1; + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + if(foundP2PIE){ + + /*only GO need process P2P IE in provision req*/ + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset((void *)current_nego_peer , 0 ,sizeof(struct p2p_device_peer)); + + // ID15 + IEptr = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_P2P_GROUP_ID , &tmplen); + if(IEptr){ + parse_group_id(IEptr , tmplen ,current_nego_peer); + } + + if(memcmp(current_nego_peer->group_bssid , GET_MY_HWADDR ,6)){ + P2P_DEBUG("bssid no match!!\n"); + return; + } + + // ID3 + IEptr = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_DEVICE_ID , &tmplen); + if(IEptr){ + for(idx=0;idxp2pPtr->assocPeers[idx].devInfo.dev_address,IEptr,6)){ + // some p2p device (no need assoc) search client that assoc with me + if(priv->p2pPtr->assocPeers[idx].dev_cap & CLIENT_DISCOVERY){ + + p2p_issue_GO_discovery_req(priv,IEptr); + // we assume client will ack me + p2p_issue_device_discovery_rsp(priv,pfrinfo->sa,P2P_SC_SUCCESS); + return ; + } + } + } + } + + } + /*-----------------------------get P2P IE(end)------------------------------*/ + p2p_issue_device_discovery_rsp(priv,pfrinfo->sa,P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE); + return ; + +} + + + +void p2p_on_device_discovery_rsp( + struct rtl8192cd_priv *priv , + struct rx_frinfo *pfrinfo) +{ + // TODO ? + return; +} + +int P2P_on_public_action(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + + if(memcmp(pfrinfo->da , GET_MY_HWADDR , 6)){ + return 0; + } + + if(pframe[6] ==P2P_GO_NEG_REQ || pframe[6] ==P2P_GO_NEG_RESP || pframe[6] ==P2P_GO_NEG_CONF){ + + // let the case on going + if(memcpy(priv->p2pPtr->ongoing_nego_peer.dev_addr,pfrinfo->sa , 6)){ + if(P2PMODE != P2P_DEVICE){ + P2P_DEBUG("GO / client don't process GO nego frames\n"); + MAC_PRINT(pfrinfo->sa); + return 0; + } + } + } + if(pframe[6] == P2P_PROV_DISC_REQ || pframe[6] == P2P_PROV_DISC_RSP){ + if(P2PMODE == P2P_CLIENT){ + P2P_DEBUG("client don't process provision req\n"); + return 0; + } + } + + + + switch(pframe[6]){ + + case P2P_GO_NEG_REQ: + P2P_PRINT("\n\n"); + P2P_DEBUG("RX GO Nogotiation Req\n"); + p2p_on_GO_nego_req(priv,pfrinfo); + break; + case P2P_GO_NEG_RESP: + P2P_PRINT("\n\n"); + P2P_DEBUG("RX GO Nogotiation Rsp\n"); + p2p_on_GO_nego_rsp(priv,pfrinfo); + break; + case P2P_GO_NEG_CONF: + P2P_PRINT("\n\n"); + P2P_DEBUG("RX GO Nogotiation Confirmation\n"); + p2p_on_GO_nego_conf(priv,pfrinfo); + break; + + case P2P_INVITATION_REQ: + P2P_DEBUG("P2P invitation Req\n"); + + break; + case P2P_INVITATION_RESP: + P2P_DEBUG("P2P invitation Rsp\n"); + + break; + + case P2P_DEV_DISC_REQ: + P2P_PRINT("\n\n"); + P2P_DEBUG("Rx Device Discoverability Req\n"); + + if(P2PMODE == P2P_TMP_GO) // process only under GO mode + p2p_on_device_discovery_req(priv,pfrinfo); + + break; + + case P2P_DEV_DISC_RESP: + + P2P_DEBUG("RX, Device Discoverability Rsp\n"); + if(P2PMODE == P2P_CLIENT) // process only under client mode + p2p_on_device_discovery_rsp(priv,pfrinfo); + + break; + + case P2P_PROV_DISC_REQ: + P2P_PRINT("\n"); + P2P_DEBUG("RX Provision-Discovery Req\n"); + p2p_on_provision_req(priv,pfrinfo); + break; + case P2P_PROV_DISC_RSP: + P2P_PRINT("\n"); + P2P_DEBUG("Rx Provision-Discovery Rsp\n"); + p2p_on_provision_rsp(priv,pfrinfo); + + break; + default: + P2P_DEBUG("!!! Unknow type p2p public action \n"); + break; + } + + return 0; + +} + + +void P2P_1sec_timer(struct rtl8192cd_priv *priv) +{ + //static int p2p_1sec_count = 0; + + if(P2PMODE == P2P_DEVICE){ + + if(priv->p2pPtr->wait2listenState){ + priv->p2pPtr->wait2listenState -- ; + P2P_DEBUG("befor listen(%d)\n",priv->p2pPtr->wait2listenState); + if(priv->p2pPtr->wait2listenState == 0){ + P2P_DEBUG("enter listen\n"); + P2P_listen(priv,NULL); + } + } + + + + /*handle active send provision discovery req*/ + if(priv->p2pPtr->provision_req_timeout){ + priv->p2pPtr->provision_req_timeout--; + + if ((P2P_STATE == P2P_S_PROVI_WAIT_RSP) + && priv->p2pPtr->provision_req_timeout + && (priv->p2pPtr->provision_req_timeout%2 == 0)) + { + p2p_issue_provision_req(priv); + + }else + if((P2P_STATE == P2P_S_PROVI_WAIT_RSP) + && priv->p2pPtr->provision_req_timeout==0){ + + /*timeout ; back to listen mode*/ + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + + } + + /*handle active send provision discovery req*/ + if(priv->p2pPtr->go_nego_on_going_timeout>0){ + priv->p2pPtr->go_nego_on_going_timeout --; + + if(priv->p2pPtr->go_nego_on_going_timeout==0){ + priv->p2pPtr->go_nego_on_going = 0; + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + + if(P2P_STATE == P2P_S_NEGO_WAIT_RSP && priv->p2pPtr->go_nego_on_going){ + if(priv->p2pPtr->go_nego_on_going_timeout%2 == 0){ + p2p_issue_GO_nego_req(priv); + } + } + + } + + /*handle passive rx nego req flow*/ + if(P2P_STATE == P2P_S_NEGO_WAIT_CONF ){ + if(priv->p2pPtr->wait_nego_conf_timeout > 0 ){ + priv->p2pPtr->wait_nego_conf_timeout -- ; + if(priv->p2pPtr->wait_nego_conf_timeout == 0){ + + if(priv->p2pPtr->go_nego_on_going){ + P2P_DEBUG("unlock go_nego_ongoing\n\n"); + priv->p2pPtr->go_nego_on_going = 0; + } + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + } + } + + + } + else if(P2PMODE == P2P_PRE_CLIENT){ + if(priv->p2pPtr->pre_client_timeout >= 0 ){ + + priv->p2pPtr->pre_client_timeout -=1; + + if(priv->p2pPtr->pre_client_timeout == 0){ + P2P_DEBUG(" WPS process exceed %d seconds,back to device mode\n",WSC_MODE_WAIT_TIME); + P2P_STATE = P2P_S_back2dev ; + //p2pcmd_backtoDev(priv,NULL); will bring some error + } + } + } + else if(P2PMODE == P2P_PRE_GO){ + if(priv->p2pPtr->pre_go_timeout >= 0 ){ + priv->p2pPtr->pre_go_timeout -= 1; + if(priv->p2pPtr->pre_go_timeout == 0){ + P2P_DEBUG(" WPS process exceed %d seconds,back to device mode\n",WSC_MODE_WAIT_TIME); + P2P_STATE = P2P_S_back2dev ; + //p2pcmd_backtoDev(priv,NULL); + } + } + } + /* + else if(P2PMODE == P2P_TMP_GO){ + p2p_1sec_count++; + + if(p2p_1sec_count%10 == 0) // 10 seconds check once + P2P_chk_assoc_client(priv); + } + */ + + + return ; +} + + + +#define Active_TX_provision_req 0 // no meaning + +/*P2P discovery related functions*/ +int req_p2p_provision_req(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + struct provision_comm *provision_comm_ptr = (struct provision_comm *)data; + int idx; + int found; + + P2P_DEBUG("trigger from UI ; wsc method=%02x \n",provision_comm_ptr->wsc_config_method); + P2P_DEBUG("target addr=%02x%02x%02x:%02x%02x%02x\n",provision_comm_ptr->dev_address[0] + ,provision_comm_ptr->dev_address[1],provision_comm_ptr->dev_address[2],provision_comm_ptr->dev_address[3] + ,provision_comm_ptr->dev_address[4],provision_comm_ptr->dev_address[5]); + P2P_DEBUG("target channel=%d \n",provision_comm_ptr->channel); + + + priv->p2pPtr->requestor = 1; // add 0615 ;for iam dev ;target is GO + + memcpy(priv->p2pPtr->target_device_addr,provision_comm_ptr->dev_address,6); + priv->p2pPtr->target_device_channel = provision_comm_ptr->channel; + P2P_DEBUG("\n Target dev on channel(%d) \n\n",priv->p2pPtr->target_device_channel); + + /*config method ; reference page38*/ + if(provision_comm_ptr->wsc_config_method == CONFIG_METHOD_PBC){ + + priv->p2pPtr->wsc_method_to_target_dev = CONFIG_METHOD_PBC ; + priv->p2pPtr->dev_passwd_to_tar_dev = PASS_ID_PB; /*for nego req use*/ + + }else if(provision_comm_ptr->wsc_config_method == CONFIG_METHOD_PIN + || provision_comm_ptr->wsc_config_method == CONFIG_METHOD_DISPLAY){ + + priv->p2pPtr->wsc_method_to_target_dev = CONFIG_METHOD_KEYPAD ; + priv->p2pPtr->dev_passwd_to_tar_dev = PASS_ID_REG; /*for nego req use*/ + + }else if(provision_comm_ptr->wsc_config_method == CONFIG_METHOD_KEYPAD){ + + priv->p2pPtr->wsc_method_to_target_dev = CONFIG_METHOD_DISPLAY ; + priv->p2pPtr->dev_passwd_to_tar_dev = PASS_ID_USER; /*for nego req use*/ + + } + + + found = 0; + for(idx=0;idx < priv->site_survey->count_backup; idx++){ + if(!memcmp(priv->site_survey->bss_backup[idx].p2paddress ,priv->p2pPtr->target_device_addr ,6)) + { + priv->p2pPtr->target_device_role = priv->site_survey->bss_backup[idx].p2prole ; + strcpy(priv->p2pPtr->target_device_ssid,priv->site_survey->bss_backup[idx].ssid); + found = 1; + } + } + + if(found==0){ + P2P_DEBUG("can't chk dev's role\n"); + return 0; + }else{ + P2P_DEBUG("Target role = %s \n",(priv->p2pPtr->target_device_role==R_P2P_GO?"GO":"dev")); + + } + + // 0329 + if(P2PMODE == P2P_CLIENT || P2PMODE == P2P_TMP_GO){ + P2P_DEBUG("client/GO don't send provision req\n"); + return 0; + } + + /*stay at target dev's channel and wait for provision Rsp*/ + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->p2pPtr->target_device_channel, priv->pshare->offset_2nd_chan); + P2P_DEBUG("Target device is at channel:%d\n",priv->p2pPtr->target_device_channel); + + + /*issue privision req*/ + if(p2p_issue_provision_req(priv)==SUCCESS){ //success + priv->p2pPtr->provision_req_timeout = 10; // per 2second ; total 5times (include first time) + }else{ + P2P_DEBUG("issue_provision_req fail\n"); + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + + return 0; +} + + + +int p2p_issue_provision_req(struct rtl8192cd_priv *priv ) +{ + + unsigned char *pbuf; + unsigned char randomX=0; + + unsigned char *IEStart; + unsigned char *thisAttrPrt; + unsigned char byteVal; + unsigned short shortVal; + unsigned char p2pIELen = 0; + unsigned char *P2PIEstart=NULL; + P2P_DEBUG("\n"); + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_provosionreq_fail1; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_provosionreq_fail1; + + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_PROV_DISC_REQ; + + get_random_bytes(&randomX , 1); + + priv->p2pPtr->provision_tx_dialog_token = randomX; + + + + pbuf[7] = priv->p2pPtr->provision_tx_dialog_token; + + /*below start is WSC IE content*/ + + /*Element ID*/ + thisAttrPrt = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; + IEStart = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; //anchor + + + thisAttrPrt[0] = WSC_IE_ID; + thisAttrPrt+=2; // ID + LEN + //thisAttrPrt[1] = WSC IE length; + + /*OUI*/ + memcpy(thisAttrPrt, WSC_IE_OUI, 4); + thisAttrPrt += 4; // OUI LEN + + /*Version*/ + byteVal = WSC_VER; + thisAttrPrt = wsc_add_tlv(thisAttrPrt, TAG_VERSION, 1, (void *)&byteVal); + + shortVal = priv->p2pPtr->wsc_method_to_target_dev ; + thisAttrPrt = wsc_add_tlv(thisAttrPrt, TAG_CONFIG_METHODS, 2, (void *)&shortVal); + /*Element Length*/ + IEStart[1] = (int)(((unsigned long)thisAttrPrt)-((unsigned long)IEStart)) - 2; + + /*end of WSC IE content*/ + + if(priv->p2pPtr->target_device_role == R_P2P_GO){ + p2pIELen = 0; + P2PIEstart = thisAttrPrt; + thisAttrPrt[0] = P2P_IE_ID; + thisAttrPrt+=2; // ID + LEN + + /*P2P OUI+TYPE*/ + memcpy(thisAttrPrt, WFA_OUI_PLUS_TYPE, 4); + thisAttrPrt+=4; // OUI LEN + p2pIELen +=4; + + /*p2p device id ; ID2 */ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen,NULL); + + /*p2p group id ; ID13 */ + thisAttrPrt = add_Attr_device_info( priv, thisAttrPrt, &p2pIELen); + + /*p2p group id ; ID15 */ + thisAttrPrt = add_Attr_Target_group_id( priv, thisAttrPrt, + &p2pIELen,priv->p2pPtr->target_device_ssid,priv->p2pPtr->target_device_addr); + + P2PIEstart[1] = p2pIELen; + } + + + + + + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), priv->p2pPtr->target_device_addr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_PRINT("\n\n"); + P2P_DEBUG("TX Provision_Req OK (My method=%02x)\n",shortVal); + MAC_PRINT(priv->p2pPtr->target_device_addr); + + + P2P_STATE = P2P_S_PROVI_WAIT_RSP; + return SUCCESS; + } + +issue_provosionreq_fail1: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; + + +} + + + +void p2p_on_provision_rsp(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + + int tmplen=0; + int foundWSCIE = 0; + unsigned short wscMethod=0; + + unsigned char* tmpPtr=NULL; + unsigned char *wscIEPtr = NULL ; + int wscIElen=0; + + P2P_DEBUG("RX, Provison Rsp\n"); + + if(pframe[7] != priv->p2pPtr->provision_tx_dialog_token ) + P2P_DEBUG("provision_req dialog_token=%d , no match\n",priv->p2pPtr->provision_rx_dialog_token); + + //========================================================================== + //========================================================================== + /*get WSC IE*/ + tmpPtr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + tmpPtr = get_ie(tmpPtr, _WPS_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(tmpPtr!=NULL){ + if (!memcmp(tmpPtr+2, WSC_IE_OUI, 4)) { + wscIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + wscIEPtr = tmpPtr+6 ; + foundWSCIE = 1; + break; + } + }else{ + break ; + } + tmpPtr = tmpPtr + tmplen +2 ; + } + + if(foundWSCIE){ + tmpPtr = search_wsc_tag(wscIEPtr, TAG_CONFIG_METHODS, wscIElen, &tmplen); + if(tmpPtr){ + wscMethod = *(unsigned short*)tmpPtr; + if(wscMethod == priv->p2pPtr->wsc_method_to_target_dev){ + priv->p2pPtr->wsc_method_match = 1; + P2P_DEBUG("wsc method=%02x match!!!\n",wscMethod); + }else{ + P2P_DEBUG("wsc method=%02x no match!!!\n\n\n",wscMethod); + priv->p2pPtr->wsc_method_match = 0; + } + } + }else{ + P2P_DEBUG("\n\n no include TAG_CONFIG_METHODS\n\n"); + } + //========================================================================= + //========================================================================== + + priv->p2pPtr->provision_req_timeout = 0; + + // go back listen state + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + + +} + +#define PASSIVE_RX_provision_req 6768 // no meaning + +void p2p_on_provision_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + int tmplen=0; + unsigned short wscMethod=0; + unsigned char* IEptr=NULL; + unsigned char *p2pIEPtr = NULL; + int p2pIElen=0; + int foundP2PIE = 0; + + unsigned char *wscIE=NULL ; // for ReAssembly + int wscIElen=0; + int foundWSCIE = 0; + + /*when i am GO will use it*/ + struct p2p_device_peer *current_nego_peer=NULL; + unsigned char *ptrtmp=NULL; + int tag_len; + +#ifdef P2P_DEBUGMSG + char *StrTmp; +#endif + priv->p2pPtr->provision_rx_dialog_token = pframe[7]; + //P2P_DEBUG("RX, Provision req\n"); + + + /*-----------------------------get WSC IE------------------------------*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _WPS_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WSC_IE_OUI, 4)) { + wscIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + wscIE = IEptr+6 ; + foundWSCIE = 1; + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + if(foundWSCIE){ + IEptr = search_wsc_tag(wscIE, TAG_CONFIG_METHODS, wscIElen, (int *)&tmplen); + wscMethod = *(unsigned short*)IEptr; + if(wscMethod){ + priv->p2pPtr->wsc_method_from_target_dev = wscMethod; + #ifdef P2P_DEBUGMSG + if(wscMethod==CONFIG_METHOD_KEYPAD) + StrTmp=WSC_STR_KEYIN; + else if(wscMethod==CONFIG_METHOD_PBC) + StrTmp=WSC_STR_PBC; + else if(wscMethod==CONFIG_METHOD_DISPLAY) + StrTmp=WSC_STR_DISPLAY; + + P2P_DEBUG("WSC Method:%02x[peers Req:%s]\n",wscMethod ,StrTmp ); + + if(wscMethod==0x100){ + P2P_DEBUG("\n\n keyin peers PIN code ex: iwpriv wlan0 p2pcmd keypad=%02X%02X%02X%02X%02X%02X,PIN\n\n", + pfrinfo->sa[0],pfrinfo->sa[1],pfrinfo->sa[2],pfrinfo->sa[3],pfrinfo->sa[4],pfrinfo->sa[5]); + } + #endif + } + } + /*-----------------------------get WSC IE------------------------------*/ + + + /*-----------------------------get P2P IE(start)------------------------------*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + p2pIEPtr = IEptr+6 ; + foundP2PIE = 1; + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + if(foundP2PIE){ + + /*only GO need process P2P IE in provision req*/ + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset((void *)current_nego_peer , 0 ,sizeof(struct p2p_device_peer)); + + /*ID2*/ + ptrtmp = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_P2P_CAPABILITY , &tag_len); + if(ptrtmp){ + current_nego_peer->dev_capab = ptrtmp[0]; + current_nego_peer->group_capab= ptrtmp[1]; + } + + if(ptrtmp[1] & BIT(0)){ + priv->p2pPtr->target_device_role = R_P2P_GO; + P2P_DEBUG("\n target dev should't GO role ,chk!!!\n"); + }else{ + priv->p2pPtr->target_device_role = R_P2P_DEVICE; + } + + if(P2PMODE == P2P_TMP_GO){ + /*ID13*/ + ptrtmp = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_P2P_DEVICE_INFO , &tag_len); + if(ptrtmp){ + parse_device_info(ptrtmp , tag_len ,¤t_nego_peer->peer_device_info); + } + + /*ID15*/ + ptrtmp = p2p_search_tag(p2pIEPtr, p2pIElen, TAG_P2P_GROUP_ID , &tag_len); + if(ptrtmp){ + parse_group_id(ptrtmp , tag_len ,current_nego_peer); + } + + } + } + /*-----------------------------get P2P IE(end)------------------------------*/ + + + /*for indicate UI that have provision Req*/ + P2P_EVENT_INDICATE = P2P_EVENT_RX_PROVI_REQ ; + + + + P2P_DEBUG("\n"); + p2p_issue_provision_rsp(priv , pfrinfo->sa); + P2P_DEBUG("\n"); + + if(wscMethod){ + priv->p2pPtr->wsc_method_from_target_dev = wscMethod; + #ifdef P2P_DEBUGMSG + if(wscMethod==CONFIG_METHOD_KEYPAD) + StrTmp=WSC_STR_KEYIN; + else if(wscMethod==CONFIG_METHOD_PBC) + StrTmp=WSC_STR_PBC; + else if(wscMethod==CONFIG_METHOD_DISPLAY) + StrTmp=WSC_STR_DISPLAY; + + P2P_DEBUG("WSC Method:%02x[peers Req:%s]\n",wscMethod ,StrTmp ); + + if(wscMethod==CONFIG_METHOD_KEYPAD){ + P2P_DEBUG("\n keyin peers PIN: iwpriv wlan0 p2pcmd keypad=%02X%02X%02X%02X%02X%02X,PIN\n\n", + pfrinfo->sa[0],pfrinfo->sa[1],pfrinfo->sa[2],pfrinfo->sa[3],pfrinfo->sa[4],pfrinfo->sa[5]); + } + #endif + + /*trigger wscd when i'm GO ; target is dev ; aother way is from web page ; 2013-0828*/ + if((P2PMODE == P2P_TMP_GO) && priv->p2pPtr->target_device_role == R_P2P_DEVICE ){ + struct p2p_device_peer wsc_peer_t; + P2P_DEBUG("Target is device ; i'm GO \n"); + /*target is device and i am GO , wsc method and pin etc is rdy ,*/ + memset(&wsc_peer_t , 0 , sizeof(struct p2p_device_peer)); + if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_KEYPAD){ + + /*target will display ; use Target's PIN*/ + P2P_DEBUG("use Tar's PIN\n"); + wsc_peer_t.device_pass_id = PASS_ID_REG; + + }else if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_PIN || + priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_DISPLAY){ + /*target will keyin pin ; use My PIN */ + P2P_DEBUG("use My PIN\n"); + wsc_peer_t.device_pass_id = PASS_ID_USER; + }else if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_PBC){ + /*PBC*/ + P2P_DEBUG("use PBC\n"); + wsc_peer_t.device_pass_id = PASS_ID_PB; + }else{ + P2P_DEBUG("unknow type !!!\n\n"); + } + /*indicate wscd satrt WPS procotol*/ + P2P_DEBUG("trigger AP mode wscd\n"); + indicate_wscd(priv, P2P_TMP_GO , priv->p2pPtr->go_PSK , &wsc_peer_t); + } + + } + + priv->p2pPtr->requestor = 0; // add 0615 ;for i am GO ;target is dev + +} + + + +int p2p_issue_provision_rsp(struct rtl8192cd_priv *priv, unsigned char *da) +{ + + + unsigned char *pbuf; + + unsigned char *wscStart; + unsigned char *wscPtr; + unsigned char byteVal; + unsigned short shortVal; + DECLARE_TXINSN(txinsn); + + //P2P_PRINT("\n\n"); + //P2P_DEBUG("TX Provision RSP \n\n"); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_provosionrsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_provosionrsp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + //P2P_DEBUG("\n"); + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_PROV_DISC_RSP; + pbuf[7] = priv->p2pPtr->provision_rx_dialog_token; + + + + /*below start is WSC IE content*/ + + /*Element ID*/ + wscPtr = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; + wscStart = pbuf + _P2P_PUBLIC_ACTION_IE_OFFSET_; //anchor + + + wscPtr[0] = WSC_IE_ID; + + wscPtr+=2; // ID + LEN + + + /*OUI*/ + memcpy(wscPtr, WSC_IE_OUI, 4); + wscPtr+=4; // OUI LEN + + /*Version*/ + byteVal = WSC_VER; + wscPtr = wsc_add_tlv(wscPtr, TAG_VERSION, 1, (void *)&byteVal); + + + /*config method*/ + shortVal = priv->p2pPtr->wsc_method_from_target_dev; + wscPtr = wsc_add_tlv(wscPtr, TAG_CONFIG_METHODS, 2, (void *)&shortVal); + //P2P_DEBUG("wsc method=%02x\n",priv->p2pPtr->wsc_method_from_target_dev); + + /*Element Length*/ + wscStart[1] = (int)(((unsigned long)wscPtr)-((unsigned long)wscStart)) - 2; + + txinsn.fr_len += ((int)(((unsigned long)wscPtr)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + //P2P_DEBUG("\n"); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + P2P_DEBUG("TX provison rsp ,OK!\n"); + return SUCCESS; + } + +issue_provosionrsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; +} + +#define ACTIVE_TX_GO_NEGO_REQ 0 // no meaning + + +/* plus remember to move ; + call in from web*/ +int req_p2p_wsc_confirm(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + struct __p2p_wsc_confirm *wsc_confirm_ptr = (struct __p2p_wsc_confirm *)data; + + struct p2p_device_peer wsc_peer_t; + + + // for debug + P2P_DEBUG("pincode=[%s]\n",wsc_confirm_ptr->pincode); + P2P_DEBUG("wscMethod=[%02x], from ",wsc_confirm_ptr->wsc_config_method); + MAC_PRINT(wsc_confirm_ptr->dev_address); + // for debug + + /*get PIN code*/ + strcpy(priv->p2pPtr->target_dev_pin_code,wsc_confirm_ptr->pincode); + + if(priv->p2pPtr->wsc_method_match==0){ +#if 0 //2013-0716 marked ; default pbc be allowed + P2P_DEBUG("Passive mode,Confirm wsc method\n"); + if(wsc_confirm_ptr->wsc_config_method == CONFIG_METHOD_PBC){ + P2P_DEBUG("PBC,Confirm!!\n"); + priv->p2pPtr->passivemode_pbc_trigger_flag = 1; + } +#endif + } + + + + if(priv->p2pPtr->target_device_role == R_P2P_DEVICE && P2PMODE==P2P_DEVICE){ + /* 1)target is dev and i am dev & 2) i issue this nego req*/ + + P2P_DEBUG("\n Target is dev ; i am dev \n"); + /*Use priv->p2pPtr->wsc_method_match for identify + i am active send nego req or not */ + + if(priv->p2pPtr->wsc_method_match==0){ + P2P_DEBUG("Passive mode,Confirm wsc method\n"); + return 0; + }else{ + P2P_DEBUG("Ative mode,Prepare send Go Nego Req!!\n"); + priv->p2pPtr->wsc_method_match=0; + } + + if(memcmp(priv->p2pPtr->target_device_addr ,wsc_confirm_ptr->dev_address ,6 )){ + P2P_DEBUG("dev addr no match, chk!!!!\n\n\n"); + return 0; + } + if(is_zero_ether_addr(wsc_confirm_ptr->dev_address )){ + P2P_DEBUG("dev addr is zero !!!\n\n\n"); + return 0; + } + + /* switch channel to target dev's channel first */ + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->p2pPtr->target_device_channel, priv->pshare->offset_2nd_chan); + + //P2P_DEBUG("Rx wsc confirm ; start Tx nego Req\n"); + if(p2p_issue_GO_nego_req(priv)==SUCCESS){ + priv->p2pPtr->go_nego_on_going = 1; // and P2P_STATE = P2P_S_NEGO_WAIT_RSP; + priv->p2pPtr->go_nego_on_going_timeout = 10 ; + + } + + } + else if(priv->p2pPtr->target_device_role == R_P2P_DEVICE && P2PMODE==P2P_TMP_GO){ + + P2P_DEBUG("\n\ntarget is device and i am GO \n"); + /*target is device and i am GO , wsc method and pin etc is rdy ,*/ + memset(&wsc_peer_t , 0 , sizeof(struct p2p_device_peer)); + + if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_KEYPAD){ + + /*target will display ; use Target's PIN*/ + wsc_peer_t.device_pass_id = PASS_ID_REG; + + }else if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_PIN || + priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_DISPLAY){ + + /*target will keyin pin ; use My PIN */ + wsc_peer_t.device_pass_id = PASS_ID_USER; + + }else if(priv->p2pPtr->wsc_method_from_target_dev==CONFIG_METHOD_PBC){ + + /*PBC*/ + wsc_peer_t.device_pass_id = PASS_ID_PB; + + + }else{ + P2P_DEBUG("unknow type !!!\n\n"); + } + + + + /*indicate wscd satrt WPS procotol*/ + indicate_wscd(priv, P2P_TMP_GO , priv->p2pPtr->go_PSK , &wsc_peer_t); + + + } + else if(priv->p2pPtr->target_device_role == R_P2P_GO && P2PMODE == P2P_DEVICE){ + + /*target is GO and i am device*/ + + P2P_DEBUG("\n\ntarget is GO and i am device \n"); + P2P_DEBUG("\n change to Pre-client and start WPS ,\n"); + p2p_as_preClient(priv,priv->p2pPtr->target_device_channel); + + memset(&wsc_peer_t , 0 , sizeof(struct p2p_device_peer)); + if(priv->p2pPtr->wsc_method_to_target_dev == CONFIG_METHOD_KEYPAD){ + /*tell target to keyin ; use My PIN */ + wsc_peer_t.device_pass_id = PASS_ID_USER; + + }else if(priv->p2pPtr->wsc_method_to_target_dev==CONFIG_METHOD_PIN || + priv->p2pPtr->wsc_method_to_target_dev==CONFIG_METHOD_DISPLAY){ + + /*tell target to display ; use Target PIN */ + wsc_peer_t.device_pass_id = PASS_ID_REG; + + + }else if(priv->p2pPtr->wsc_method_to_target_dev==CONFIG_METHOD_PBC){ + /* PBC */ + wsc_peer_t.device_pass_id = PASS_ID_PB; + + }else{ + P2P_DEBUG("unknow type !!!\n\n"); + } + + /* indicate wscd change mode and start WPS under client mode */ + indicate_wscd(priv, P2P_PRE_CLIENT , NULL, &wsc_peer_t); + priv->p2pPtr->pre_client_timeout = WSC_MODE_WAIT_TIME ; + + + } + else{ + P2P_DEBUG("unknow type chk!!!\n\n"); + } + + return 0; +} + +int p2p_issue_GO_nego_req(struct rtl8192cd_priv *priv) +{ + + + unsigned char *pbuf; + unsigned char *thisAttrPrt=NULL; + unsigned char p2pIELen = 0; + + unsigned char *tmpPtr=NULL; + unsigned short shortVal; + unsigned char StrTmp2[40]; + unsigned char My_tie_break; + unsigned char randomX; + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_nego_req_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_nego_req_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_GO_NEG_REQ; + + get_random_bytes(&randomX , 1); + priv->p2pPtr->go_nego_tx_dialog_token = randomX; + pbuf[7] = randomX; + + /* ===== WSC IE content =========*/ + shortVal = priv->p2pPtr->dev_passwd_to_tar_dev; + + if(priv->p2pPtr->dev_passwd_to_tar_dev == PASS_ID_REG){ + P2P_DEBUG("use My PIN \n"); + strcpy(StrTmp2,"PASS_ID_REG"); + }else if(priv->p2pPtr->dev_passwd_to_tar_dev == PASS_ID_USER){ + P2P_DEBUG("use Target's PIN \n"); + strcpy(StrTmp2,"PASS_ID_USER"); + }else if(priv->p2pPtr->dev_passwd_to_tar_dev == PASS_ID_PB){ + strcpy(StrTmp2,"PASS_ID_PB"); + }else{ + P2P_DEBUG("unknow type !!!\n\n"); + } + + + priv->p2pPtr->wsc_ie_req_mun = wsc_build_probe_rsp_ie(priv, priv->p2pPtr->wsc_ie_req ,shortVal); + + memcpy(&pbuf[8] , priv->p2pPtr->wsc_ie_req , priv->p2pPtr->wsc_ie_req_mun); + //p2p_debug_out("GO Nego Req ; WSC IE", priv->p2pPtr->wsc_ie_req ,priv->p2pPtr->wsc_ie_req_mun); + /* ===== WSC IE content =========*/ + + /* ===== P2P IE content =========*/ + thisAttrPrt = pbuf + 8 + priv->p2pPtr->wsc_ie_req_mun ; + tmpPtr = pbuf + 8 + priv->p2pPtr->wsc_ie_req_mun ; + thisAttrPrt[0]=_P2P_IE_; + + /*fill p2p ie total length later(size == 2bytes)*/ + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /*id2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen,NULL); + + + get_random_bytes(&My_tie_break , 1); + My_tie_break %= 2; + P2P_DEBUG("(Nego req)Method type:%s,tie_break=%d\n",StrTmp2,My_tie_break); + /* id4*/ + thisAttrPrt = add_Attr_GO_intent( priv, thisAttrPrt, &p2pIELen ,My_tie_break); + + /* id5*/ + thisAttrPrt = add_Attr_configration_timeout( priv, thisAttrPrt, &p2pIELen ,1); + + /* id6*/ + thisAttrPrt = add_Attr_listenChannel( priv, thisAttrPrt, &p2pIELen ); + + /* id8*/ + thisAttrPrt = add_Attr_extended_listen_timing( priv, thisAttrPrt, &p2pIELen ,65535,65535); + + + /* id9*/ + thisAttrPrt = add_Attr_intended_interface( priv, thisAttrPrt, &p2pIELen); + + /* id11*/ + thisAttrPrt = add_Attr_channel_list( priv, thisAttrPrt, &p2pIELen); + + /* id13 */ + thisAttrPrt = add_Attr_device_info( priv, thisAttrPrt, &p2pIELen); + + + /* id17*/ + thisAttrPrt = add_Attr_operation_channel( priv, thisAttrPrt, &p2pIELen); + + + + tmpPtr[1]=p2pIELen; + + //p2p_debug_out("GO Nego Req ; P2P IE", tmpPtr,p2pIELen ); + + + /* ===== total LEN =========*/ + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), priv->p2pPtr->target_device_addr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_PRINT("\n"); + P2P_DEBUG(" Tx GO nego Req OK\n\n"); + P2P_STATE = P2P_S_NEGO_WAIT_RSP; + return SUCCESS; + } + +issue_nego_req_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; + +} + + + + + + +void p2p_on_GO_nego_rsp(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + unsigned char *ptrtmp = NULL; + unsigned char* IEptr=NULL; + int tmplen=0; + unsigned char *p2pIE; + int p2pIElen=0; + int foundP2PIE = 0; + + unsigned char *wscIE; + int wscIElen=0; + int foundWSCIE = 0; + int tag_len; + struct p2p_device_peer *current_nego_peer=NULL; + + P2P_DEBUG("RX, GO nego Rsp\n"); + + if(priv->p2pPtr->go_nego_on_going && P2P_STATE == P2P_S_NEGO_WAIT_RSP){ + + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset(current_nego_peer , 0 , sizeof(struct p2p_device_peer)); + + + }else{ + if(P2P_STATE != P2P_S_NEGO_WAIT_RSP) + P2P_DEBUG("rx nego rsp ; but not at P2P_S_NEGO_WAIT_RSP\n"); + return ; + } + + current_nego_peer->dialog_token = pframe[7]; + if(pframe[7] != priv->p2pPtr->go_nego_tx_dialog_token){ + P2P_DEBUG("go_nego_tx_dialog_token no match!!\n\n\n"); + } + + memcpy(current_nego_peer->dev_addr,pfrinfo->sa,6); + //========================================================================== + /*get WSC IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _WPS_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WSC_IE_OUI, 4)) { + wscIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + wscIE = IEptr+6 ; + foundWSCIE = 1; + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + //========================================================================== + if(foundWSCIE){ + ptrtmp = search_wsc_tag(wscIE, TAG_DEVICE_PASSWORD_ID, wscIElen, &tag_len); + if(ptrtmp){ + current_nego_peer->device_pass_id = *(unsigned short *)ptrtmp; + } + }else{ + current_nego_peer->status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; + P2P_DEBUG("\n\n no include DEVICE PASS ID\n\n"); + } + //========================================================================== + + //========================================================================== + /*get P2P IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + for(;;){ + + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + p2pIE = IEptr+6 ; + foundP2PIE = 1; + //p2p_debug_out("P2P IE", p2pIE, p2pIElen); + break; + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + if(foundP2PIE){ + + // ID0 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_STATUE , &tag_len); + if(ptrtmp){ + current_nego_peer->status = ptrtmp[0]; + if(current_nego_peer->status){ + P2P_DEBUG(" nego fail!! report from target ; status = ( %d ) \n",current_nego_peer->status); + + P2P_STATE = P2P_S_LISTEN; + return; + } + + } + + // ID2 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_CAPABILITY , &tag_len); + if(ptrtmp){ + current_nego_peer->dev_capab = ptrtmp[0]; + current_nego_peer->group_capab= ptrtmp[1]; + } + + // ID4 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_GROUP_OWNER_INTENT , &tag_len); + if(ptrtmp){ + current_nego_peer->intent_value = ptrtmp[0]>>1; + current_nego_peer->TieBreak = ptrtmp[0]&0x01; + //P2P_DEBUG("Intent T(%d),M(%d) \n", + // current_nego_peer->intent_value,priv->pmib->p2p_mib.p2p_intent); + } + + // ID5 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_CONFIG_TIMEOUT , &tag_len); + if(ptrtmp){ + current_nego_peer->go_config_timeout = ptrtmp[0]; + current_nego_peer->client_config_timeout = ptrtmp[1]; + } + + + + // ID9 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_INTEN_P2P_INTERFACE_ADDR , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->p2p_interface_address , ptrtmp ,6); + } + + // ID11 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_CHANNEL_LIST , &tag_len); + if(ptrtmp){ + parse_channel_list(ptrtmp , tag_len ,current_nego_peer); + } + + // ID13 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_DEVICE_INFO , &tag_len); + if(ptrtmp){ + parse_device_info(ptrtmp , tag_len ,¤t_nego_peer->peer_device_info); + } + + // ID15 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_GROUP_ID , &tag_len); + if(ptrtmp){ + //P2P_DEBUG("TAG_P2P_GROUP_ID; len = %d \n",tag_len); + parse_group_id(ptrtmp , tag_len ,current_nego_peer); + } + + // ID17 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_OPERATION_CHANNEL , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->op_country , ptrtmp ,3); + current_nego_peer->op_country[3]='\0'; + current_nego_peer->op_class = ptrtmp[3]; + current_nego_peer->op_channel = ptrtmp[4]; + } + + } + + /*determine who is GO/Client by intent value*/ + if((priv->pmib->p2p_mib.p2p_intent==15) + && current_nego_peer->intent_value ==15){ + current_nego_peer->status = P2P_SC_FAIL_BOTH_GO_INTENT_15; + } + if(priv->pmib->p2p_mib.p2p_intent > current_nego_peer->intent_value){ + current_nego_peer->role = R_P2P_CLIENT; + }else if((priv->pmib->p2p_mib.p2p_intent == current_nego_peer->intent_value)){ + + if(current_nego_peer->TieBreak){ + current_nego_peer->role = R_P2P_GO; + }else{ + current_nego_peer->role = R_P2P_CLIENT; + } + }else if(priv->pmib->p2p_mib.p2p_intent < current_nego_peer->intent_value){ + + current_nego_peer->role = R_P2P_GO; + } + + p2p_issue_GO_nego_conf(priv,current_nego_peer); + +} + + +int p2p_issue_GO_nego_conf(struct rtl8192cd_priv *priv, + struct p2p_device_peer *current_nego_peer) +{ + unsigned char *pbuf; + unsigned char *thisAttrPrt=NULL; + unsigned char p2pIELen = 0; + unsigned char *tmpPtr=NULL; + DECLARE_TXINSN(txinsn); + + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_nego_conf_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_nego_conf_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_GO_NEG_CONF; + pbuf[7] = current_nego_peer->dialog_token; + + /* ===== no need include WSC IE content =========*/ + + + /* ===== P2P IE content =========*/ + thisAttrPrt = pbuf + 8 + priv->p2pPtr->wsc_ie_rsp_mun ; + tmpPtr = pbuf + 8 + priv->p2pPtr->wsc_ie_rsp_mun ; + thisAttrPrt[0]=_P2P_IE_; + + /*fill p2p ie total length later(size == 2bytes)*/ + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + /*ID0*/ + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,current_nego_peer->status); + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen,current_nego_peer); + + /* ID17*/ + if(current_nego_peer->role == R_P2P_CLIENT) // i am GO + thisAttrPrt = add_Attr_operation_channel( priv, thisAttrPrt, &p2pIELen); + + /* ID11*/ + thisAttrPrt = add_Attr_channel_list( priv, thisAttrPrt, &p2pIELen); + + /*ID15*/ + if(current_nego_peer->role == R_P2P_CLIENT) // i am GO + thisAttrPrt = add_Attr_group_id( priv, thisAttrPrt, &p2pIELen); + + + tmpPtr[1]=p2pIELen; + + //p2p_debug_out("p2p IE (nego Rsp)", tmpPtr,p2pIELen ); + + + /* ===== total LEN =========*/ + //txinsn.fr_len += priv->p2pPtr->wsc_ie_tmp_mun; + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), current_nego_peer->dev_addr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + P2P_DEBUG(" TX GO nego Conf ,OK!\n"); + + if(priv->p2pPtr->go_nego_on_going){ + priv->p2pPtr->go_nego_on_going = 0; + } + + priv->p2pPtr->requestor = 1; + if(current_nego_peer->role == R_P2P_CLIENT){ + + /*target dev will as client ; i will work as pre-GO*/ + P2P_DEBUG(" As Pre-GO role for %d seconds\n\n",WSC_MODE_WAIT_TIME); + p2p_as_GO(priv,P2P_PRE_GO); + + /*indicate wscd change mode ; and satrt WPS procotol*/ + indicate_wscd(priv, P2P_PRE_GO , priv->p2pPtr->go_PSK , current_nego_peer); + priv->p2pPtr->pre_go_timeout = WSC_MODE_WAIT_TIME ; + + } + else if(current_nego_peer->role == R_P2P_GO){ + + P2P_DEBUG(" As Pre-client role for %d seconds\n\n",WSC_MODE_WAIT_TIME); + p2p_as_preClient(priv , current_nego_peer->op_channel); + + /*indicate wscd change mode ; and satrt WPS procotol*/ + indicate_wscd(priv, P2P_PRE_CLIENT , NULL, current_nego_peer); + priv->p2pPtr->pre_client_timeout = WSC_MODE_WAIT_TIME ; + } + else{ + P2P_DEBUG("unknow type chk!!\n"); + } + + return SUCCESS ; + } + + + + +issue_nego_conf_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; +} + + +#define PASSIVE_RX_GO_NEGO_REQ 0 // no meaning + + + + +void p2p_on_GO_nego_req(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + unsigned char *ptrtmp = NULL; + unsigned char* IEptr=NULL; + int tmplen=0; + + unsigned char p2pIE[256]; + int p2pIElen=0; + int foundP2PIE = 0; + + //unsigned char wscIE[256]; + //int wscIElen=0; + int foundWSCIE = 0; + int tag_len; + struct p2p_device_peer *current_nego_peer=NULL; + + + //P2P_DEBUG("\n\n"); + //P2P_STATE = P2P_S_NEGO_RX_REQ ; + + if(priv->p2pPtr->go_nego_on_going){ + if(!memcmp(pfrinfo->sa , priv->p2pPtr->ongoing_nego_peer.dev_addr,6)){ + + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset(current_nego_peer , 0 , sizeof(struct p2p_device_peer)); + + }else{ + current_nego_peer = &priv->p2pPtr->others_nego_tar_device ; + current_nego_peer->status = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; + } + + }else{ + priv->p2pPtr->go_nego_on_going = 1; + priv->p2pPtr->go_nego_on_going_timeout = 15; + //P2P_DEBUG("GO_nego with\n"); + //MAC_PRINT(pfrinfo->sa); + + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + memset(current_nego_peer , 0 , sizeof(struct p2p_device_peer)); + } + + current_nego_peer->dialog_token = pframe[7]; + memcpy(current_nego_peer->dev_addr,pfrinfo->sa,6); + //========================================================================== + /*get WSC IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + + for(;;) + { + IEptr = get_ie(IEptr, _WPS_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WSC_IE_OUI, 4)) { + //wscIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + //memcpy(wscIE, IEptr+6, wscIElen); + foundWSCIE = 1; + break; + //p2p_debug_out("WSC IE", wscIE, wscIElen); + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + //========================================================================== + if(foundWSCIE){ + ptrtmp = search_wsc_tag(IEptr+6, TAG_DEVICE_PASSWORD_ID, tmplen-4, &tag_len); + if(ptrtmp){ + current_nego_peer->device_pass_id = *(unsigned short *)ptrtmp; + P2P_DEBUG("peer's device_pass_id= [%02X] \n",current_nego_peer->device_pass_id ); + + } + }else{ + current_nego_peer->status = P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD; + + } + //========================================================================== + + //========================================================================== + /*get P2P IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + for(;;){ + + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + memcpy(p2pIE, IEptr+6, p2pIElen); + foundP2PIE = 1; + break; + //p2p_debug_out("P2P IE", p2pIE, p2pIElen); + + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + if(foundP2PIE){ + + // ID2 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_CAPABILITY , &tag_len); + if(ptrtmp){ + current_nego_peer->dev_capab = ptrtmp[0]; + current_nego_peer->group_capab= ptrtmp[1]; + } + + // ID4 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_GROUP_OWNER_INTENT , &tag_len); + if(ptrtmp){ + current_nego_peer->intent_value = ptrtmp[0]>>1; + current_nego_peer->TieBreak = ptrtmp[0]&0x01; + P2P_DEBUG("Intent T(%d),M(%d),Tie break=%d \n", + current_nego_peer->intent_value, + priv->pmib->p2p_mib.p2p_intent, + current_nego_peer->TieBreak); + + } + + // ID6 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_LISTEN_CHANNEL , &tag_len); + if(ptrtmp){ + + current_nego_peer->operating_class = ptrtmp[3]; + current_nego_peer->listen_channle = ptrtmp[4]; + } + + // ID9 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_INTEN_P2P_INTERFACE_ADDR , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->p2p_interface_address , ptrtmp ,6); + } + + // ID11 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_CHANNEL_LIST , &tag_len); + if(ptrtmp){ + parse_channel_list(ptrtmp , tag_len ,current_nego_peer); + } + + // ID13 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_DEVICE_INFO , &tag_len); + if(ptrtmp){ + parse_device_info(ptrtmp , tag_len ,&(current_nego_peer->peer_device_info)); + } + + // ID17 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_OPERATION_CHANNEL , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->op_country , ptrtmp ,3); + current_nego_peer->op_country[3]='\0'; + current_nego_peer->op_class = ptrtmp[3]; + current_nego_peer->op_channel = ptrtmp[4]; + } + + } + + p2p_issue_GO_nego_rsp(priv,current_nego_peer); + +} + +int p2p_issue_GO_nego_rsp(struct rtl8192cd_priv *priv, + struct p2p_device_peer *current_nego_peer) +{ + + + unsigned char *pbuf; + unsigned char *thisAttrPrt=NULL; + unsigned char p2pIELen = 0; + unsigned char *tmpPtr=NULL; + unsigned short shortVal=0; + int MyRole=0; // GO:1 client:2 + int My_tie_break=0; + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = _6M_RATE_; + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_nego_rsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_nego_rsp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + + + pbuf[0] = CATEGORY_P2P_PUBLIC_ACTION; + pbuf[1] = ACTIONY_P2P_PUBLIC_ACTION; + memcpy(&pbuf[2],WFA_OUI_PLUS_TYPE,4); + pbuf[6] = P2P_GO_NEG_RESP; + pbuf[7] = current_nego_peer->dialog_token; + + /* ===== WSC IE content =========*/ + + if(current_nego_peer->device_pass_id == PASS_ID_USER){ + //P2P_DEBUG("use My PIN \n"); + shortVal = PASS_ID_REG; + }else if(current_nego_peer->device_pass_id == PASS_ID_REG){ + //P2P_DEBUG("use Target's PIN \n"); + shortVal = PASS_ID_USER; + }else if(current_nego_peer->device_pass_id == PASS_ID_PB){ + + shortVal = PASS_ID_PB; + }else{ + P2P_DEBUG("unknow type\n"); + } + + priv->p2pPtr->wsc_ie_rsp_mun = wsc_build_probe_rsp_ie(priv, priv->p2pPtr->wsc_ie_rsp ,shortVal); + + memcpy(&pbuf[8] , priv->p2pPtr->wsc_ie_rsp , priv->p2pPtr->wsc_ie_rsp_mun); + + //p2p_debug_out("wsc ie at nego rsp", priv->p2pPtr->wsc_ie_tmp,priv->p2pPtr->wsc_ie_tmp_mun); + /* ===== WSC IE content =========*/ + + + /*determine who is GO/Client by intent value---start*/ + + + if((priv->pmib->p2p_mib.p2p_intent==15) + && current_nego_peer->intent_value ==15){ + current_nego_peer->status = P2P_SC_FAIL_BOTH_GO_INTENT_15; + } + if(priv->pmib->p2p_mib.p2p_intent > current_nego_peer->intent_value){ + MyRole = R_P2P_GO; + current_nego_peer->role = R_P2P_CLIENT; + }else if((priv->pmib->p2p_mib.p2p_intent == current_nego_peer->intent_value)){ + + if(current_nego_peer->TieBreak){ + MyRole = R_P2P_CLIENT; + My_tie_break=0; + current_nego_peer->role = R_P2P_GO; + }else{ + MyRole = R_P2P_GO; + My_tie_break=1; + current_nego_peer->role = R_P2P_CLIENT; + } + }else if(priv->pmib->p2p_mib.p2p_intent < current_nego_peer->intent_value){ + MyRole = R_P2P_CLIENT; + current_nego_peer->role = R_P2P_GO; + } + + /*determine who is GO/Client by intent value---end */ + + + + /* ===== P2P IE content =========*/ + thisAttrPrt = pbuf + 8 + priv->p2pPtr->wsc_ie_rsp_mun ; + tmpPtr = pbuf + 8 + priv->p2pPtr->wsc_ie_rsp_mun ; + thisAttrPrt[0]=_P2P_IE_; + + /*fill p2p ie total length later(size == 2bytes)*/ + thisAttrPrt+=2; + + memcpy(thisAttrPrt , WFA_OUI_PLUS_TYPE ,4); + p2pIELen+=4; + thisAttrPrt+=4; + + + /*ID0*/ + if(current_nego_peer->device_pass_id == PASS_ID_REG){ /*use Target's PIN code*/ + if(is_zero_pin_code(priv->p2pPtr->target_dev_pin_code)){ + P2P_DEBUG("PIN not ready yet\n"); + current_nego_peer->status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; + } + }else + if(current_nego_peer->device_pass_id == PASS_ID_PB){ /*Target will use PBC*/ + + /* + if(priv->p2pPtr->passivemode_pbc_trigger_flag == 0){ + P2P_DEBUG("PBC not allow yet\n"); + current_nego_peer->status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; + } + */ + P2P_DEBUG("default allow PBC \n"); + /*else{ + // clean PBC flag + P2P_DEBUG("clean PBC flag\n"); + priv->p2pPtr->passivemode_pbc_trigger_flag = 0; + } + */ + } + + + thisAttrPrt = add_Attr_status(priv , thisAttrPrt, &p2pIELen ,current_nego_peer->status); + + + /*ID2*/ + thisAttrPrt = add_Attr_capability( priv, thisAttrPrt, &p2pIELen,current_nego_peer); + + + /* ID4*/ + thisAttrPrt = add_Attr_GO_intent( priv, thisAttrPrt, &p2pIELen ,My_tie_break); + + /* ID5*/ + thisAttrPrt = add_Attr_configration_timeout( priv, thisAttrPrt, &p2pIELen ,MyRole); + + /* ID17*/ + if(MyRole == R_P2P_GO) + thisAttrPrt = add_Attr_operation_channel( priv, thisAttrPrt, &p2pIELen); + + /* ID9*/ + thisAttrPrt = add_Attr_intended_interface( priv, thisAttrPrt, &p2pIELen); + + /* ID11*/ + thisAttrPrt = add_Attr_channel_list( priv, thisAttrPrt, &p2pIELen); + + /* ID13*/ + thisAttrPrt = add_Attr_device_info( priv, thisAttrPrt, &p2pIELen); + + /* ID15*/ + if(MyRole == R_P2P_GO) + thisAttrPrt = add_Attr_group_id( priv, thisAttrPrt, &p2pIELen); + + + tmpPtr[1]=p2pIELen; + + //p2p_debug_out("p2p IE (nego Rsp)", tmpPtr,p2pIELen ); + + + /* ===== total LEN =========*/ + txinsn.fr_len += ((int)(((unsigned long)thisAttrPrt)-((unsigned long)pbuf))); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), current_nego_peer->dev_addr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ + + // send rsp ok ;wait conf + P2P_STATE = P2P_S_NEGO_WAIT_CONF ; + priv->p2pPtr->wait_nego_conf_timeout = 2; + + P2P_DEBUG("TX GO nego Rsp success\n"); + if(current_nego_peer->status!=P2P_SC_SUCCESS){ + + P2P_DEBUG("Intent T(%d),M(%d)\n", + current_nego_peer->intent_value , priv->pmib->p2p_mib.p2p_intent); + + //P2P_DEBUG("My Role:%s\n",(MyRole==R_P2P_GO?"GO":"Client")); + + if(priv->p2pPtr->go_nego_on_going){ + P2P_DEBUG("status = %d\n",current_nego_peer->status); + P2P_DEBUG("unlock go_nego_ongoing\n\n"); + priv->p2pPtr->go_nego_on_going = 0; + } + + } + + return SUCCESS; + } + else{ + P2P_DEBUG("tx nego rsp fail\n"); + } + +issue_nego_rsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; +} + +void p2p_on_GO_nego_conf(struct rtl8192cd_priv *priv ,struct rx_frinfo *pfrinfo) +{ + /*start of action frame content*/ + unsigned char *pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; + int tmplen=0; + unsigned char *ptrtmp = NULL; + unsigned char* IEptr=NULL; + unsigned char p2pIE[256]; + int p2pIElen=0; + int foundP2PIE = 0; + int tag_len; + + struct p2p_device_peer *current_nego_peer=NULL; + + P2P_DEBUG("RX , GO_nego_conf\n\n"); + + if(priv->p2pPtr->go_nego_on_going){ + current_nego_peer = &priv->p2pPtr->ongoing_nego_peer ; + }else{ + P2P_DEBUG("no GO nego on going , drop confirm\n\n"); + return ; + } + + if(P2P_STATE != P2P_S_NEGO_WAIT_CONF){ + P2P_DEBUG("rx conf but state is wrong!!\n"); + return ; + }else{ + P2P_STATE = P2P_S_LISTEN; + } + + if(current_nego_peer == NULL){ + P2P_DEBUG("\n"); + return ; + } + + /* check dialog_token */ + if(current_nego_peer->dialog_token != pframe[7]){ + P2P_DEBUG("dialog_token no match!!!\n\n"); + return ; + } + + //========================================================================== + /*get P2P IE*/ + IEptr = pframe + _P2P_PUBLIC_ACTION_IE_OFFSET_; + tmplen = 0; + for(;;){ + + IEptr = get_ie(IEptr, _P2P_IE_, &tmplen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _P2P_PUBLIC_ACTION_IE_OFFSET_ - tmplen); + + if(IEptr!=NULL){ + if (!memcmp(IEptr+2, WFA_OUI_PLUS_TYPE, 4)) { + + p2pIElen = tmplen-4 ; //skip WSC_IE_OUI(len==4) + memcpy(p2pIE, IEptr+6, p2pIElen); + foundP2PIE = 1; + //p2p_debug_out("P2P IE", p2pIE, p2pIElen); + break; + + } + }else{ + break ; + } + IEptr = IEptr + tmplen +2 ; + } + + //========================================================================== + if(foundP2PIE){ + + // ID0 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_STATUE , &tag_len); + if(ptrtmp){ + current_nego_peer->status = ptrtmp[0]; + if(current_nego_peer->status){ + P2P_DEBUG("nego fail!! report from target ; status = ( %d ) \n\n", + current_nego_peer->status); + return; + } + + } + + // ID2 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_CAPABILITY , &tag_len); + if(ptrtmp){ + current_nego_peer->dev_capab = ptrtmp[0]; + current_nego_peer->group_capab= ptrtmp[1]; + } + + // ID17 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_OPERATION_CHANNEL , &tag_len); + if(ptrtmp){ + memcpy(current_nego_peer->op_country , ptrtmp ,3); + current_nego_peer->op_country[3]='\0'; + current_nego_peer->op_class = ptrtmp[3]; + current_nego_peer->op_channel = ptrtmp[4]; + } + + // ID11 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_CHANNEL_LIST , &tag_len); + if(ptrtmp){ + parse_channel_list(ptrtmp , tag_len ,current_nego_peer); + } + + // ID15 + ptrtmp = p2p_search_tag(p2pIE, p2pIElen, TAG_P2P_GROUP_ID , &tag_len); + if(ptrtmp){ + //P2P_DEBUG("TAG_P2P_GROUP_ID; len = %d \n",tag_len); + parse_group_id(ptrtmp , tag_len ,current_nego_peer); + } + + + } + + + priv->p2pPtr->requestor = 0; + + // nego success + if(current_nego_peer->status == P2P_SC_SUCCESS) + { + + if(current_nego_peer->role == R_P2P_CLIENT){ + + /*target dev will as client ; i will work as pre-GO*/ + P2P_DEBUG(" As Pre-GO role for %d seconds\n\n",WSC_MODE_WAIT_TIME); + p2p_as_GO(priv,P2P_PRE_GO); + + // indicate wscd change mode ; and satrt WPS procotol + indicate_wscd(priv, P2P_PRE_GO , priv->p2pPtr->go_PSK , current_nego_peer); + priv->p2pPtr->pre_go_timeout = WSC_MODE_WAIT_TIME ; + + } + else if(current_nego_peer->role == R_P2P_GO){ + /*i will work as pre-client*/ + P2P_DEBUG(" As Pre-client role for %d seconds\n\n",WSC_MODE_WAIT_TIME); + p2p_as_preClient(priv ,current_nego_peer->op_channel); + + // indicate wscd change mode and start WPS + + /*start to wsc under enrollee mode*/ + indicate_wscd(priv, P2P_PRE_CLIENT , NULL, current_nego_peer); + priv->p2pPtr->pre_client_timeout = WSC_MODE_WAIT_TIME ; + } + else{ + P2P_DEBUG("unknow type chk!!\n"); + } + + } + + if(priv->p2pPtr->go_nego_on_going){ + + P2P_DEBUG("unlock go_nego_on_going (Rx nego conf) \n\n\n"); + priv->p2pPtr->go_nego_on_going = 0; + //priv->p2pPtr->go_nego_on_going_timeout = 0; // 2011-0615 add + + } + //========================================================================== + return ; + +} + + +#define EVENT_TO_WSCD 6768 // no meaning + +void stop_wscd(struct rtl8192cd_priv *priv ,unsigned char *data) +{ + + DOT11_WSC_PIN_IND wsc_ind; + + if( priv->p2pPtr->wps_is_ongoing != 1) + return; + + wsc_ind.EventId = DOT11_EVENT_WSC_STOP; + wsc_ind.IsMoreEvent = 0; + + P2P_DEBUG("\n"); + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, + (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, 0); + priv->p2pPtr->wps_is_ongoing = 0; +} +#if 0 // 8812 test +void wps_client_set_spec_bssid(struct rtl8192cd_priv *priv,unsigned char* macaddr) +{ + DOT11_WSC_PIN_IND wsc_ind; + if(!memcpy(macaddr,"\x0\x0\x0\x0\x0\x0",6)){ + P2P_DEBUG("mac addr = NULL\n"); + return; + } + P2P_DEBUG("\n"); + + wsc_ind.EventId = DOT11_EVENT_WSC_SPEC_MAC_IND; + wsc_ind.IsMoreEvent = 0; + memcpy(wsc_ind.code, macaddr , 6); + wsc_ind.code[6]='\0'; + + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, -1); + + +} +#endif +void indicate_wscd(struct rtl8192cd_priv *priv , unsigned char mode , + unsigned char *PSK ,struct p2p_device_peer *nego_peer_xx) +{ + + + struct _DOT11_P2P_INDICATE_WSC p2p_2_wsc_event_t; + memset(&p2p_2_wsc_event_t , 0 ,sizeof(struct _DOT11_P2P_INDICATE_WSC)); + + p2p_2_wsc_event_t.EventId = DOT11_EVENT_WSC_SWITCH_MODE; // 100 + p2p_2_wsc_event_t.IsMoreEvent = 0; + + p2p_2_wsc_event_t.modeSwitch = mode; + + P2P_DEBUG(" switch wps mode to %d\n",p2p_2_wsc_event_t.modeSwitch); + +#if 0 // 8812 connect test + if(mode==2){ /*wscd client mode ; we assign target AP's mac addr*/ + P2P_DEBUG("call wps_client_set_spec_bssid\n"); + wps_client_set_spec_bssid(priv,nego_peer_xx->group_bssid); + } +#endif + + + if(PSK){ + strcpy(p2p_2_wsc_event_t.network_key , PSK); + P2P_DEBUG(" psk=%s\n",p2p_2_wsc_event_t.network_key); + }else{ + p2p_2_wsc_event_t.network_key[0]='\0'; + } + + // gossid is use under i am go + strcpy(p2p_2_wsc_event_t.gossid, priv->p2pPtr->my_GO_ssid); + //P2P_DEBUG("gossid=%s\n",p2p_2_wsc_event_t.gossid); + + + /* If p2p_2_wsc_event_t.trigger_method no assigned , + wscd only change mode , will not trigger WPS protocol*/ + if(nego_peer_xx){ + + if(nego_peer_xx->device_pass_id == PASS_ID_USER){ + + // use My PIN + P2P_DEBUG(" use My PIN\n"); + p2p_2_wsc_event_t.whosPINuse = USE_MY_PIN ; + p2p_2_wsc_event_t.trigger_method = P2P_PIN_METHOD; + priv->p2pPtr->wps_is_ongoing = 1; + + }else if(nego_peer_xx->device_pass_id == PASS_ID_REG){ + + // use Target's PIN + P2P_DEBUG(" use Target's PIN=%s\n",priv->p2pPtr->target_dev_pin_code); + p2p_2_wsc_event_t.whosPINuse = USE_TARGET_PIN; + p2p_2_wsc_event_t.trigger_method = P2P_PIN_METHOD; + strcpy(p2p_2_wsc_event_t.PINCode, priv->p2pPtr->target_dev_pin_code); + priv->p2pPtr->wps_is_ongoing = 1; + + }else if(nego_peer_xx->device_pass_id == PASS_ID_PB){ + + P2P_DEBUG(" use PBC\n"); + p2p_2_wsc_event_t.trigger_method = P2P_PBC_METHOD; + priv->p2pPtr->wps_is_ongoing = 1; + + if( priv->p2pPtr->passivemode_pbc_trigger_flag ) + P2P_DEBUG("clean PBC flag\n"); + priv->p2pPtr->passivemode_pbc_trigger_flag = 0; + + }else{ + P2P_DEBUG(" unknow type chk!!\n"); + } + + } + + if(priv->p2pPtr->requestor){ + P2P_DEBUG(" i am requestor\n"); + p2p_2_wsc_event_t.requestor = 1; + }else{ + P2P_DEBUG(" i am not requestor\n"); + } + + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, + (UINT8 *)&p2p_2_wsc_event_t, sizeof(struct _DOT11_P2P_INDICATE_WSC)); + + event_indicate(priv, NULL, 0); + +} + + +#define GROUP_SESSION_HANDLE 6768 // no meaning + + + + + +void P2P_chk_assoc_client(struct rtl8192cd_priv *priv) +{ + + int idx = 0; + int found = 0; + int needrebuild = 0; + struct list_head *phead, *plist; + struct stat_info *pstat; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + P2P_DEBUG("\n"); + + if( priv->assoc_num == 0){ + for(idx=0;idxp2pPtr->assocPeers[idx].inuse){ + + memset(priv->p2pPtr->assocPeers, 0 ,sizeof(struct assoc_peer)*MAX_P2P_CLIENT_MUN); + + priv->p2pPtr->p2p_probe_rsp_ie_len = + p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + + return; + } + } + } + + phead = &priv->asoc_list; + if (!netif_running(priv->dev) || list_empty(phead)) { + return; + } + + for(idx=0;idxp2pPtr->assocPeers[idx].inuse){ + + found = 0; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if(!memcmp(pstat->hwaddr ,priv->p2pPtr->assocPeers[idx].if_addr ,6)) { + found = 1; + break; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + + if(found==0){ + priv->p2pPtr->assocPeers[idx].inuse = 0; + needrebuild = 1; + } + + } + } + + /*rebuild GO's probe_rsp content ,build Probe_Rsp P2P IE info */ + if(needrebuild){ + priv->p2pPtr->p2p_probe_rsp_ie_len = + p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + } + + return; + +} + +void P2P_client_on_beacon(struct rtl8192cd_priv *priv, + unsigned char *IEaddr, unsigned int IElen, int seq) +{ + unsigned char* p2p_sub_ie=NULL; + int tag_len = 0; + + + // ID 12 + p2p_sub_ie = p2p_search_tag(IEaddr, IElen, TAG_NOTICE_OF_ABSENCE, &tag_len); + if (p2p_sub_ie) { + //P2P_DEBUG("\n"); + parse_p2p_NOA(priv, p2p_sub_ie, tag_len, seq); + } + else { + //P2P_DEBUG("No TAG_NOTICE_OF_ABSENCE in beacon\n"); + p2p_cancel_noa(priv); + } + return; +} + + + +int P2P_filter_manage_ap(struct rtl8192cd_priv *priv, + unsigned char *IEaddr, unsigned int IElen ) +{ + unsigned char* p2p_sub_ie=NULL; + int tag_len = 0; + // ID10 + p2p_sub_ie = p2p_search_tag(IEaddr , IElen , TAG_P2P_MANAGEABILITY , &tag_len); + + if(p2p_sub_ie){ + P2P_DEBUG("\n"); + if(p2p_sub_ie[0] & BIT(0)) + return 1; + else + return 0; + } + + return 0; + +} + + +void P2P_on_assoc_req(struct rtl8192cd_priv *priv, + unsigned char *IEaddr, unsigned int IElen , unsigned char *sa) +{ + unsigned char* p2p_sub_ie; + int tag_len = 0; + int idx = 0; + int found = 0; + + P2P_DEBUG("RX , Assoc req\n"); + + for(idx=0;idxp2pPtr->assocPeers[idx].inuse){ + if(!memcmp(priv->p2pPtr->assocPeers[idx].if_addr,sa,6)){ + found = 1; + break; + } + } + if(priv->p2pPtr->assocPeers[idx].inuse == 0){ + priv->p2pPtr->assocPeers[idx].inuse = 1; + found = 1; + break; + } + } + + if(found==0){ + // second changes + P2P_chk_assoc_client(priv); + + for(idx=0;idxp2pPtr->assocPeers[idx].inuse == 0){ + priv->p2pPtr->assocPeers[idx].inuse = 1; + found = 1; + break; + } + } + if(found==0){ + P2P_DEBUG("assoc peer full!!,chk!!\n\n\n"); + return; + } + } + + // ID 2 + p2p_sub_ie = p2p_search_tag(IEaddr , IElen , TAG_P2P_CAPABILITY , &tag_len); + if(p2p_sub_ie){ + priv->p2pPtr->assocPeers[idx].dev_cap = p2p_sub_ie[0]; + priv->p2pPtr->assocPeers[idx].group_cap = p2p_sub_ie[1]; + }else{ + + P2P_DEBUG("can't search TAG_P2P_CAPABILITY\n\n"); + return; + } + + + // ID 13 + p2p_sub_ie = p2p_search_tag(IEaddr , IElen , TAG_P2P_DEVICE_INFO , &tag_len); + if(p2p_sub_ie){ + parse_device_info(p2p_sub_ie,tag_len, &(priv->p2pPtr->assocPeers[idx].devInfo)); + }else{ + P2P_DEBUG("can't search TAG_P2P_DEVICE_INFO\n\n"); + return; + } + + memcpy(priv->p2pPtr->assocPeers[idx].if_addr ,sa, 6); + + /*rebuild GO's probe_rsp content ,build Probe_Rsp P2P IE info */ + priv->p2pPtr->p2p_probe_rsp_ie_len = p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + + return; + +} + + + +void P2P_on_assoc_rsp(struct rtl8192cd_priv *priv,unsigned char *sa) +{ + P2P_DEBUG("RX,Assoc Rsp\n"); + memset(priv->p2pPtr->assocPeers,0,sizeof(struct assoc_peer)*MAX_P2P_CLIENT_MUN); + priv->p2pPtr->assocPeers[0].inuse = 1; + memcpy(priv->p2pPtr->assocPeers[0].if_addr,sa,6); + return; + +} + + +void P2P_on_probe_req( + struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, + unsigned char *IEaddr, unsigned int IElen ) +{ + + unsigned char *pframe= get_pframe(pfrinfo); + unsigned char* pData=NULL; + int tag_len ; + + //P2P_PRINT("p2p probe_req from:"); + //MAC_PRINT(GetAddr2Ptr(pframe)); + + /* DA is broadcast addr or my p2p device addr + (default use MY-HW-ADDR as p2p device addrree)*/ + if( memcmp(GetAddr1Ptr(pframe), "\xff\xff\xff\xff\xff\xff", 6) + && memcmp(GetAddr1Ptr(pframe), GET_MY_HWADDR, 6)) + { + P2P_DEBUG("DA mismatch!\n"); + return; + } + + /*chk BSSID(ADDR3) is broadcast MacAddr */ + if( memcmp(GetAddr3Ptr(pframe), "\xff\xff\xff\xff\xff\xff", 6) ){ + P2P_DEBUG("A3 mismatch!\n"); + return; + } + + /*ID3*/ + pData = p2p_search_tag(IEaddr , IElen , TAG_DEVICE_ID , &tag_len); + if(pData){ + if( memcmp(pData , GET_MY_HWADDR , 6)){ + /*this p2p IE include spec device addr for search , and target is not me*/ + return; + } + } + + #if 0 + /*get WSC IE --start*/ + ptmp = pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_; lentmp = 0; + for (;;) + { + ptmp = get_ie(ptmp, _WPS_IE_, &lentmp, (int)(pfrinfo->pktlen - (ptmp - pframe))); + if (ptmp != NULL) { + if (!memcmp(ptmp+2, WSC_IE_OUI, 4)) { + wsc_ie_found = 1; + break; + } + } + else + break; + + ptmp = ptmp + lentmp + 2; + } + if(wsc_ie_found){ + + /*find TAG_PRIMARY_DEVICE_TYPE*/ + pData = search_wsc_tag(ptmp+6, TAG_PRIMARY_DEVICE_TYPE, lentmp-4, &tag_len); + if (pData == NULL) { + P2P_DEBUG("Can't find TAG_PRIMARY_DEVICE_TYPE\n"); + } + } + /*get WSC IE --end*/ + #endif + + if(P2PMODE ==P2P_TMP_GO){ + priv->p2pPtr->probe_rps_to_p2p_dev = 1; + //P2P_DEBUG("GO Rsp"); + //MAC_PRINT(GetAddr2Ptr(pframe)); + issue_probersp(priv, GetAddr2Ptr(pframe), SSID, SSID_LEN, FALSE,FALSE); + }else{ + issue_probersp(priv, GetAddr2Ptr(pframe), P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN, FALSE,FALSE); + } + +} + + +void p2p_client_remove(struct rtl8192cd_priv *priv , struct stat_info *pstat ) +{ + + int idx=0; + if(P2PMODE!=P2P_TMP_GO){ + return; + } + P2P_DEBUG("\n"); + + for(idx=0;idxp2pPtr->assocPeers[idx].inuse){ + if(!memcmp(priv->p2pPtr->assocPeers[idx].if_addr,pstat->hwaddr,6)){ + priv->p2pPtr->assocPeers[idx].inuse=0; + priv->p2pPtr->p2p_probe_rsp_ie_len = + p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + + break; + } + } + } + + return; +} + +#define SEPARATE4 0 // no meaning + +void p2p_init(struct rtl8192cd_priv *priv ) +{ + if(priv->p2pPtr == NULL){ + P2P_DEBUG("first init kmalloc for p2p interface!\n"); + priv->p2pPtr = (struct p2p_context*)kmalloc(sizeof(struct p2p_context),GFP_ATOMIC); + if(priv->p2pPtr == NULL){ + P2P_DEBUG("\n\n!!!! chk here!!!\n\n\n\n\n"); + }else{ + memset(priv->p2pPtr,0,sizeof(struct p2p_context)); + } + }else{ + if(P2PMODE == P2P_CLIENT){ + /*the parameter need reset when interface do open and close*/ + P2P_DEBUG("reset clientmode_try_connect\n"); + priv->p2pPtr->clientmode_try_connect=0; + } + } + + P2P_DEBUG("P2P_MODE=[%d]\n",P2PMODE); + P2P_DEBUG("dot11channel=[%d]\n",priv->pmib->dot11RFEntry.dot11channel); + + + /*setting channel;bandwidth ;ch2ndoffset*/ + if(P2PMODE == P2P_DEVICE){ + priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_listen_channel; + priv->pmib->dot11nConfigEntry.dot11nUse40M = 0; // 20Mbandwidth + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = 0; // don't care + }else + + if(P2PMODE == P2P_PRE_GO){ + /*temporal AP use 20M bandwitdh*/ + priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_op_channel; + priv->pmib->dot11nConfigEntry.dot11nUse40M = 0; // 20Mbandwidth + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = 0; // don't care + }else + if(P2PMODE == P2P_TMP_GO){ + #if 0 // use default + priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_op_channel; + priv->pmib->dot11nConfigEntry.dot11nUse40M = 1; // 40M bandwidth + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = get_ava_2ndchoff(priv,priv->pmib->dot11RFEntry.dot11channel,priv->pmib->dot11nConfigEntry.dot11nUse40M); + #endif + } + /*setting channel;bandwidth ;ch2ndoffset*/ + + if(priv->p2pPtr->rdyinit){ + + }else + { + /* do only once ,first one*/ + + /*generate my GO profile*/ + if( memcmp(SSID,"DIRECT-",7) || (SSID_LEN < 9) || (P2PMODE != P2P_TMP_GO)){ + generate_GO_ssid(priv); + strcpy(SSID,priv->p2pPtr->my_GO_ssid); //use passPhease from flash mib + }else{ + P2P_DEBUG("use mib value as GO ssid\n"); + strcpy(priv->p2pPtr->my_GO_ssid,SSID); + priv->p2pPtr->my_GO_ssid_len=SSID_LEN; + } + P2P_DEBUG("my_GO_ssid=[%s]\n",priv->p2pPtr->my_GO_ssid); + P2P_DEBUG("SSID=[%s]\n",SSID); + + + if(strlen(priv->pmib->dot1180211AuthEntry.dot11PassPhrase)<8){ + generate_GO_PSK(priv); + strcpy(priv->pmib->dot1180211AuthEntry.dot11PassPhrase,priv->p2pPtr->go_PSK); //use passPhease from flash mib + }else{ + // use the value from flash mib + strcpy(priv->p2pPtr->go_PSK,priv->pmib->dot1180211AuthEntry.dot11PassPhrase); //use passPhease from flash mib + } + P2P_DEBUG("dot11PassPhrase=[%s]\n",priv->pmib->dot1180211AuthEntry.dot11PassPhrase); + P2P_DEBUG("go_PSK=[%s]\n",priv->p2pPtr->go_PSK); + + + /*1004 test use channel from flash mib or autochannel*/ + priv->pmib->p2p_mib.p2p_op_channel = priv->pmib->dot11RFEntry.dot11channel ; + P2P_DEBUG("p2p_op_channel=[%d] copy from dot11channel\n",priv->pmib->p2p_mib.p2p_op_channel); + + /*channel list*/ + init_channel_list(priv); + /*back up orig 40M/20M and 2ndchoffset*/ + priv->p2pPtr->backup_orig_use40M = priv->pmib->dot11nConfigEntry.dot11nUse40M; + priv->p2pPtr->backup_orig_2ndchoffset = priv->pmib->dot11nConfigEntry.dot11n2ndChOffset; + P2P_DEBUG("dot11nUse40M=[%d]\n",priv->pmib->dot11nConfigEntry.dot11nUse40M); + P2P_DEBUG("dot11n2ndChOffset=[%d]\n",priv->pmib->dot11nConfigEntry.dot11n2ndChOffset); + + + priv->p2pPtr->rdyinit=1; + + + } + + if(P2PMODE == P2P_TMP_GO){ + /*it will trigger application to start DHCPD !!*/ + P2P_STATE = P2P_S_preGO2GO_DHCPD; + P2P_DEBUG("to start DhcpD\n"); + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 8; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA2 ; // support WPA+WPA2 + + } + + + + + + /*build beacon P2P IE */ + if(P2PMODE == P2P_TMP_GO || P2PMODE == P2P_PRE_GO ){ + memset(priv->p2pPtr->assocPeers,0,sizeof(struct assoc_peer)*MAX_P2P_CLIENT_MUN); + } + + /*build Probe_Rsp P2P IE info */ + priv->p2pPtr->p2p_probe_rsp_ie_len = + p2p_build_probe_rsp_ie(priv,priv->p2pPtr->p2p_probe_rsp_ie); + + + /*build Probe_Req P2P IE info */ + priv->p2pPtr->p2p_probe_req_ie_len = + p2p_build_probe_req_ie(priv,priv->p2pPtr->p2p_probe_req_ie); + + + + /*build wsc IE info ;only use under P2P device mode ; under GO(AP) mode it should be + fill by wscd , so take care!!*/ + if(P2PMODE == P2P_DEVICE){ + priv->pmib->wscEntry.probe_rsp_ielen = + wsc_build_probe_rsp_ie(priv, priv->pmib->wscEntry.probe_rsp_ie , PASS_ID_REG); + } + + /*build assocReq P2P IE */ + priv->p2pPtr->p2p_assocReq_ie_len + = p2p_build_assocReq_ie(priv,priv->p2pPtr->p2p_assocReq_ie); + + /*build disAssoc P2P IE */ + priv->p2pPtr->p2p_disass_ie_len + = p2p_build_deassoc_ie(priv,priv->p2pPtr->p2p_disass_ie , minor_case1); + + + + /*build beacon P2P IE */ + if(P2PMODE == P2P_TMP_GO || P2PMODE == P2P_PRE_GO ){ + + priv->p2pPtr->p2p_beacon_ie_len = + p2p_build_beacon_ie(priv,priv->p2pPtr->p2p_beacon_ie); + + priv->p2pPtr->p2p_assoc_RspIe_len = + p2p_build_assocRsp_ie(priv,priv->p2pPtr->p2p_assoc_RspIe,P2P_SC_SUCCESS); + + } + + + + + + P2P_show_status(priv,NULL); + if(P2PMODE == P2P_DEVICE){ + priv->p2pPtr->wait2listenState = 2; // enter listen mode by 1sec timer + } + +} + + + +int p2pcmd_enable(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + if(P2PMODE == P2P_DEVICE){ + P2P_DEBUG("->\n"); + P2P_listen(priv,NULL); + } + return 0; +} + +int P2P_listen(struct rtl8192cd_priv* priv,unsigned char* data) +{ + + /*check if listen channel is in social channel*/ + if(priv->pmib->p2p_mib.p2p_listen_channel !=1 + && priv->pmib->p2p_mib.p2p_listen_channel!=6 + && priv->pmib->p2p_mib.p2p_listen_channel!=11) + { + P2P_DEBUG("invaild listen chn(%d) ; set chn to default =6\n",priv->pmib->p2p_mib.p2p_listen_channel); + priv->pmib->p2p_mib.p2p_listen_channel = 6; + } + + P2P_DEBUG("listen;on chn(%d)\n",priv->pmib->p2p_mib.p2p_listen_channel); + stay_on_2G(priv); + + P2P_STATE = P2P_S_LISTEN; + + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + + SwChnl(priv, priv->pmib->p2p_mib.p2p_listen_channel, priv->pshare->offset_2nd_chan); + + /* 2013-0723 8812 test */ + //priv->pshare->working_channel = priv->pmib->p2p_mib.p2p_listen_channel; + //PHY_IQCalibrate(priv); + /* 2013-0723 8812 test */ + + // process receive probe_req frame + + // for assigned how long i will stay in listen state + if(P2P_DISCOVERY){ + unsigned char randomX=0; + get_random_bytes(&randomX , 1); + randomX%=3; + randomX+=1; // 1<= randomX <=3 + if (timer_pending(&priv->p2p_listen_timer_t)) + del_timer_sync(&priv->p2p_listen_timer_t); + + mod_timer(&priv->p2p_listen_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(randomX*100));/* call P2P_listen_timer() */ + } + + return 0; +} + +void P2P_listen_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + // now is on discovery procedure ; go to next state + if(P2P_DISCOVERY && (P2P_STATE == P2P_S_LISTEN)){ + P2P_DISCOVERY +=1 ; + P2P_PRINT("\n"); + P2P_DEBUG("find phase(%d)\n",P2P_DISCOVERY-1); + P2P_search(priv,NULL); + } + + return ; +} + +/*P2P discovery related functions*/ + +void p2p_search_timer(unsigned long task_priv){ + + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + + + //P2P_DEBUG("\n"); + if (priv->ss_req_ongoing || (OPMODE&WIFI_SITE_MONITOR)) + { + if (timer_pending(&priv->p2p_search_timer_t)) + del_timer_sync(&priv->p2p_search_timer_t); + + /*site survey is going... waitting 3 times passive scna time */ + // 2013 + P2P_PRINT("wait...\n"); + mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(300)); + }else{ + + int idx ; + + /*restore below two parameter*/ + if(priv->back_available_chnl_num){ + + for(idx=0;idxavailable_chnl[idx]=priv->back_available_chnl[idx]; + + priv->available_chnl_num = priv->back_available_chnl_num; + priv->back_available_chnl_num = 0 ; + + } + + + // now is on discovery procedure ; (SCAN) is done go to next state (Listen) + if(P2P_DISCOVERY && (P2P_STATE == P2P_S_SCAN)){ + //P2P_DEBUG("dev into listen mode\n"); + P2P_listen(priv,NULL); + return; + } + + // now is on discovery procedure ; (SEARCH) is done go to next state (Listen) + if(P2P_DISCOVERY && (P2P_STATE == P2P_S_SEARCH)){ + + //P2P_DEBUG("find phase(%d)\n",P2P_DISCOVERY-1) ; + + if(P2P_DISCOVERY == 4) { + + P2P_DISCOVERY = 0; + + p2p_show_ss_res(priv); + + P2P_DEBUG("P2P_discovery done\n"); + if(P2PMODE==P2P_CLIENT){ + P2P_PRINT("client connected mode\n"); + P2P_STATE = P2P_S_CLIENT_CONNECTED_DHCPC_done; + }else{ + //P2P_DEBUG("dev into listen mode\n"); + P2P_listen(priv,NULL); + } + + }else{ + //P2P_DEBUG("dev into listen mode\n"); + P2P_listen(priv,NULL); + } + } + + if((P2P_STATE == P2P_S_SEARCH) || (P2P_STATE == P2P_S_SCAN)){ + //P2P_DEBUG("dev into listen mode\n"); + P2P_listen(priv,NULL); + } + + } + +} + +int P2P_scan(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + P2P_STATE = P2P_S_SCAN; + priv->ss_ssidlen = 0; + + P2P_DEBUG("Site Servey...\n"); + priv->ss_req_ongoing = 1; // set this parameter then SS will do 2 runs or 3 runs + start_clnt_ss(priv); + + + if (timer_pending(&priv->p2p_search_timer_t)) + del_timer_sync(&priv->p2p_search_timer_t); + + // if 2G only ch number =11 ; SS_COUNT=ss runs ; stay time = 50ms ; detal time=20ms + // 2013 + mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(2000)); /* call p2p_search_timer() */ + + // if 2G + 5G + //mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(1200)); /* call p2p_search_timer() */ + + /* + start_clnt_ss will call rtl8192cd_ss_timer to complete site survey + p2p_search_timer will wait rtl8192cd_ss_timer complete site survey then on go + */ + + return 0; +} + + +int P2P_search(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + + int idx=0; + + P2P_STATE = P2P_S_SEARCH; + + /*copy below two parameter*/ + for(idx=0;idxback_available_chnl[idx]=priv->available_chnl[idx]; + + priv->back_available_chnl_num = priv->available_chnl_num; + + /*copy below two parameter-end*/ + priv->available_chnl[0]=1; + priv->available_chnl[1]=6; + priv->available_chnl[2]=11; + priv->available_chnl_num=3; + + priv->ss_ssidlen = 0; + P2P_DEBUG("p2p search ...\n"); + // priv->ss_req_ongoing = 1; + //priv->ss_req_ongoing = 1; //this parameter will let SS do 2 runs or 3 runs ; 2013-0619 + start_clnt_ss(priv); + + + if (timer_pending(&priv->p2p_search_timer_t)) + del_timer_sync(&priv->p2p_search_timer_t); + // 2013 + mod_timer(&priv->p2p_search_timer_t, jiffies + RTL_MILISECONDS_TO_JIFFIES(P2P_SEARCH_TIME_V*3 + 800 )); /* call p2p_search_timer() */ + + + return 0; +} + + + + +int P2P_show_status(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int idx=0; + if(!(OPMODE&WIFI_P2P_SUPPORT)) + PDEBUG("No under P2P mode\n"); + + P2P_DEBUG("OPMODE: %02x\n",OPMODE); + P2P_DEBUG("P2PMODE: "); + switch(P2PMODE) + { + case P2P_DEVICE: + PDEBUG("P2P_DEVICE\n"); + break; + case P2P_PRE_CLIENT: + P2P_DEBUG("P2P_PRE_CLIENT\n"); + break; + + case P2P_CLIENT: + P2P_DEBUG("P2P_CLIENT\n"); + break; + + case P2P_PRE_GO: + P2P_DEBUG("P2P_PRE_GO\n"); + break; + + case P2P_TMP_GO: + P2P_DEBUG("P2P_TMP_GO\n"); + break; + default: + P2P_DEBUG("unknow type\n"); + + } + + P2P_DEBUG("P2P Status(%d): ",P2P_STATE); + switch(P2P_STATE) + { + case P2P_S_IDLE: + PDEBUG("IDLE\n"); + break; + case P2P_S_SCAN: + PDEBUG("SCAN\n"); + break; + + case P2P_S_LISTEN: + PDEBUG("LISTEN\n"); + break; + + case P2P_S_SEARCH: + PDEBUG("SEARCH\n"); + break; + + case P2P_S_PROVI_TX_REQ: + case P2P_S_PROVI_WAIT_RSP: + case P2P_S_PROVI_RX_RSP: + PDEBUG("Provision procedure active\n"); + break; + case P2P_S_PROVI_RX_REQ: + case P2P_S_PROVI_TX_RSP: + PDEBUG("Provision procedure passive\n"); + break; + case P2P_S_NEGO_TX_REQ: + case P2P_S_NEGO_WAIT_RSP: + case P2P_S_NEGO_TX_CONF: + PDEBUG("GO nego procedure active\n"); + break; + case P2P_S_NEGO_RX_REQ: + case P2P_S_NEGO_TX_RSP: + case P2P_S_NEGO_WAIT_CONF: + PDEBUG("GO nego procedure passive\n"); + break; + case P2P_S_CLIENT_CONNECTED_DHCPC: + PDEBUG("P2P client connected\n"); + break; + case P2P_S_CLIENT_CONNECTED_DHCPC_done: + PDEBUG("P2P client connected\n"); + break; + + case P2P_S_preGO2GO_DHCPD: + case P2P_S_preGO2GO_DHCPD_done: + PDEBUG("P2P GO\n"); + break; + + default: + PDEBUG("unknow type\n"); + + } + + + P2P_DEBUG("p2p listen channel=\"%d\"\n",priv->pmib->p2p_mib.p2p_listen_channel); + P2P_DEBUG("p2p operation channel=\"%d\"\n",priv->pmib->p2p_mib.p2p_op_channel); + P2P_DEBUG("p2p intent value=\"%d\"\n",priv->pmib->p2p_mib.p2p_intent); + P2P_DEBUG("p2p device name=\"%s\"\n",priv->pmib->p2p_mib.p2p_device_name); + P2P_DEBUG("p2p pin code=\"%s\"\n",priv->pmib->p2p_mib.p2p_wsc_pin_code); + + P2P_DEBUG("GO info\n"); + P2P_DEBUG("GO SSID=%s\n",priv->p2pPtr->my_GO_ssid); + P2P_DEBUG("GO PSK=%s\n",priv->p2pPtr->go_PSK); + + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G){ + P2P_DEBUG("under PHY_BAND_2G\n"); + } + else if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G){ + P2P_DEBUG("under PHY_BAND_5G\n"); + } + + if(P2PMODE == P2P_TMP_GO){ + if(priv->p2pPtr->p2p_probe_rsp_ie_len) + debug_out("go rsp IE",priv->p2pPtr->p2p_probe_rsp_ie ,priv->p2pPtr->p2p_probe_rsp_ie_len); + + + for(idx=0;idxp2pPtr->assocPeers[idx].inuse){ + P2P_DEBUG("%d) P2P client assoc2me:",idx); + MAC_PRINT(priv->p2pPtr->assocPeers[idx].if_addr); + } + } + + } + + return 0; +} + + + +/* display the result of p2p discovery*/ +void p2p_show_ss_res(struct rtl8192cd_priv *priv) +{ + unsigned char* addrptr; + int idx =0; + //wait SiteSurvey completed + + P2P_PRINT("\n\n"); + P2P_DEBUG("result count=%d\n",priv->site_survey->count_backup); + + if(priv->ss_req_ongoing) { + P2P_PRINT("ss_req_ongoing\n"); + }else{ + + P2P_PRINT("index:"); + P2P_PRINT("address: "); + P2P_PRINT("role: "); + P2P_PRINT("channel:"); + P2P_PRINT("wsc method:"); + P2P_PRINT("name: "); + P2P_PRINT("ssid(only go):\n"); + for(idx=0;idx < priv->site_survey->count_backup; idx++){ + + //if(strlen(priv->site_survey->bss_backup[idx].p2pdevname)==0) + // continue; + + P2P_PRINT("%d ",idx); + addrptr = priv->site_survey->bss_backup[idx].p2paddress; + P2P_PRINT(";%02x%02x%02x:%02x%02x%02x ",addrptr[0],addrptr[1],addrptr[2], + addrptr[3],addrptr[4],addrptr[5]); + + if(priv->site_survey->bss_backup[idx].p2prole == R_P2P_GO){ + P2P_PRINT(";GO "); + }else if(priv->site_survey->bss_backup[idx].p2prole == R_P2P_DEVICE){ + P2P_PRINT(";DEVICE "); + } + + P2P_PRINT(";%d ",priv->site_survey->bss_backup[idx].channel); + P2P_PRINT(";%02x ",priv->site_survey->bss_backup[idx].p2pwscconfig); + P2P_PRINT("; %s ",priv->site_survey->bss_backup[idx].p2pdevname); + + if(priv->site_survey->bss_backup[idx].p2prole == R_P2P_GO){ + P2P_PRINT(";%s ",priv->site_survey->bss_backup[idx].ssid); + } + P2P_PRINT("\n"); + + } + P2P_PRINT("\n\n"); + } + +} + + + +int P2P_show_command(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + + P2P_PRINT("1)iwpriv wlan0 p2pcmd dwellch,6\n"); + P2P_PRINT("2)iwpriv wlan0 p2pcmd intent,6\n"); + P2P_PRINT("3)iwpriv wlan0 p2pcmd opch,6\n"); + P2P_PRINT("4)iwpriv wlan0 p2pcmd devname,rtl8196c-dev\n"); + P2P_PRINT("1~4) need :iwpriv wlan0 p2pcmd apply\n"); + + P2P_PRINT("6)iwpriv wlan0 p2pcmd scan\n"); + P2P_PRINT("7)iwpriv wlan0 p2pcmd search\n"); + P2P_PRINT("8)iwpriv wlan0 p2pcmd listen\n"); + P2P_PRINT("9)iwpriv wlan0 p2pcmd find\n"); + P2P_PRINT("10)iwpriv wlan0 p2pcmd discovery\n"); + P2P_PRINT("\n"); + P2P_PRINT("11)iwpriv wlan0 p2pcmd asgo\n"); + P2P_PRINT("12)iwpriv wlan0 p2pcmd bakdev\n"); + P2P_PRINT("\n"); + P2P_PRINT("13)iwpriv wlan0 p2pcmd status\n"); + + return 0; +} + + + +int p2pcmd_find(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + P2P_PRINT("start P2P find phase\n"); + P2P_DISCOVERY = 1; + priv->site_survey->count = 0; + priv->site_survey->count_backup = 0; + P2P_DEBUG("\n"); + P2P_listen(priv,NULL); + return 0; + +} +int p2pcmd_discovery(struct rtl8192cd_priv *priv, unsigned char *data) +{ + /* + discovery = scan(similar site servey) + find + find = (search+listen)*3 + search = ch1,ch6,ch11(120ms) + listen = stay at listen channel(1 or 6 or 11) ; stay time = 100ms*(random(1~3)) + */ + + P2P_PRINT("\n"); + P2P_DEBUG("Start P2P_discovery.....\n"); + P2P_DISCOVERY = 1; + priv->site_survey->count = 0; + priv->site_survey->count_backup = 0; + P2P_scan(priv,NULL); + + return 0; +} + +#define P2P_MODE_SWITCH 0 // no meaning + +int p2p_as_preClient(struct rtl8192cd_priv *priv , int peers_opchannel) +{ + + // unsigned long flags; + // P2P_DEBUG("\n"); + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + + priv->pmib->dot11RFEntry.dot11channel = peers_opchannel; + priv->pshare->working_channel = peers_opchannel; + + //PHY_IQCalibrate(priv);// 8812 test + + rtl8192cd_close(priv->dev); + OPMODE_VAL(WIFI_P2P_SUPPORT | WIFI_STATION_STATE); + P2PMODE = P2P_PRE_CLIENT; + P2P_STATE = P2P_S_IDLE; + + /* clear SSID */ + memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, '\0' , 32); + priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = 0; + + /*clear security */ + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 0; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0 ; // support WPA+WPA2 + + /* clear PSK */ + memset(priv->pmib->dot1180211AuthEntry.dot11PassPhrase,0 ,65); + + // site suvery all + priv->ss_ssidlen=0; + priv->ss_ssid[0]='\0'; + + /* set band */ + if(priv->pmib->dot11RFEntry.dot11channel <= 11) + priv->pmib->dot11BssType.net_work_type=8+2; // G+N + else + priv->pmib->dot11BssType.net_work_type=8+4; // A+N + + rtl8192cd_open(priv->dev); + + + //RESTORE_INT(flags); + //SMP_UNLOCK(flags); + + return 0; +} + +int p2p_as_GO(struct rtl8192cd_priv *priv, int GOtype){ + + //unsigned long flags; + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + + rtl8192cd_close(priv->dev); + OPMODE_VAL(WIFI_P2P_SUPPORT | WIFI_AP_STATE); + + if(GOtype == P2P_PRE_GO) + P2PMODE = P2P_PRE_GO; + else if(GOtype == P2P_TMP_GO) + P2PMODE = P2P_TMP_GO; + + P2P_DEBUG("MY GO SSID:%s\n",priv->p2pPtr->my_GO_ssid); + P2P_DEBUG("MY PSK:%s\n",priv->p2pPtr->go_PSK); + /* set SSID */ + priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = priv->p2pPtr->my_GO_ssid_len; + memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, 0, 32); + memcpy(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, + priv->p2pPtr->my_GO_ssid, priv->p2pPtr->my_GO_ssid_len); + + + + /* set channel */ + //stay_on_2G(priv); + + priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_op_channel; + if(GOtype == P2P_PRE_GO){ + /*temporal AP use 20M bandwitdh*/ + priv->pmib->dot11nConfigEntry.dot11nUse40M = 0; // 20Mbandwidth + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = 0; // don't care + }else if(GOtype == P2P_TMP_GO){ + /*when dev mode we use 20m as default; + when back to GO mode use system default value about 20/40 and 2nd ch offset*/ + priv->pmib->dot11nConfigEntry.dot11nUse40M = priv->p2pPtr->backup_orig_use40M; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = priv->p2pPtr->backup_orig_2ndchoffset; + + } + + /* set band */ + if(priv->pmib->p2p_mib.p2p_op_channel<=11) + priv->pmib->dot11BssType.net_work_type=8+2; // G+N + else + priv->pmib->dot11BssType.net_work_type=8+4; // A+N + + /*set security ;WPA2+AES*/ + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 8; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA2 ; // support WPA+WPA2 + + /* PSK */ + strcpy(priv->pmib->dot1180211AuthEntry.dot11PassPhrase, priv->p2pPtr->go_PSK); + + rtl8192cd_open(priv->dev); + + /*state change and indicate web server start udhcpd ; only under GO mode; pre GO don't*/ + if(GOtype == P2P_TMP_GO){ + /*it will trigger application to start DHCPD !!*/ + P2P_STATE = P2P_S_preGO2GO_DHCPD; + } + + //RESTORE_INT(flags); + //SMP_UNLOCK(flags); + return 0; +} + +int p2pcmd_force_GO(struct rtl8192cd_priv *priv, unsigned char *data) +{ + p2p_as_GO(priv,P2P_TMP_GO); + // switch wscd mode to AP ;only change mode wps not start yet + indicate_wscd(priv, P2P_TMP_GO ,NULL , NULL); + return 0 ; +} + +int p2pcmd_backtoDev(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + P2P_DEBUG("\nReset to p2p device \n\n\n"); +#if 0 + if(P2PMODE == P2P_CLIENT){ + if(priv->p2pPtr->assocPeers[0].inuse + && !is_zero_ether_addr(priv->p2pPtr->assocPeers[0].if_addr)){ + P2P_DEBUG("\n issue disassoc to :"); + MAC_PRINT(priv->p2pPtr->assocPeers[0].if_addr); + issue_disassoc(priv, priv->p2pPtr->assocPeers[0].if_addr , _RSON_UNSPECIFIED_ ); + } + } +#endif + + //SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + + // stop wscd + stop_wscd(priv,NULL); + + // change back to enrollee mode + indicate_wscd(priv, P2P_PRE_CLIENT ,NULL , NULL); + + rtl8192cd_close(priv->dev); + + OPMODE_VAL(WIFI_P2P_SUPPORT | WIFI_STATION_STATE); + P2PMODE = P2P_DEVICE; + P2P_STATE = P2P_S_IDLE; + + + /* set SSID */ +// priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen = 0; +// memset(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, 0, 32); + memset(SSID, 0, 32); + SSID_LEN = 0; + + memset(SSID2SCAN, 0, 32); + SSID2SCAN_LEN = 0; + + + /* set channel */ + priv->pmib->dot11RFEntry.dot11channel = priv->pmib->p2p_mib.p2p_listen_channel; + priv->pmib->dot11nConfigEntry.dot11nUse40M = 0; // 20Mbandwidth + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = 0; // don't care + + /* set band */ + priv->pmib->dot11BssType.net_work_type=8+2; //G+N + + /*set security ;WPA2+AES*/ + + //priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = _NO_PRIVACY_; + //priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + memset(&priv->pmib->dot1180211AuthEntry , 0 , sizeof(struct Dot1180211AuthEntry)); + + //priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + //priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 8; + + /* PSK */ + //memset(priv->pmib->dot1180211AuthEntry.dot11PassPhrase,0 ,65); + + + /*clean beacon P2P IE */ + priv->p2pPtr->p2p_beacon_ie_len = 0; + + /*make sure i am under 2G band*/ + stay_on_2G(priv); + + + + rtl8192cd_open(priv->dev); + + //RESTORE_INT(flags); + //SMP_UNLOCK(flags); + + //P2P_listen(priv, NULL); //0408 1sec timer will do it + + //============== + return 0; + +} + + +#define P2P_CONFIGURABILE_PARAMTER 0 // no meaning + +int p2pcmd_set_listen_channel(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int dwekk_chn=_atoi(data , 10); + + if(dwekk_chn !=1 && dwekk_chn!=6 && dwekk_chn!=11){ + P2P_DEBUG("invaild chn(%d) ; set chn to default =6\n",dwekk_chn); + priv->pmib->p2p_mib.p2p_listen_channel = 6 ; + }else{ + priv->pmib->p2p_mib.p2p_listen_channel = dwekk_chn ; + P2P_DEBUG("set listen ch[%d] OK!!\n", priv->pmib->p2p_mib.p2p_listen_channel); + } + return 0; + +} + +int p2pcmd_set_intent_value(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int intentVal = _atoi(data , 10); + if(intentVal>15 ||intentVal<0 ){ + P2P_DEBUG("invaild intent value\n"); + }else{ + priv->pmib->p2p_mib.p2p_intent = intentVal ; + P2P_DEBUG("set intentVal[%d] OK!!\n",priv->pmib->p2p_mib.p2p_intent); + } + return 0; +} + + +int p2pcmd_set_op_channel(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int opchannel = _atoi(data , 10); + priv->pmib->p2p_mib.p2p_op_channel = opchannel ; + P2P_DEBUG("set op-ch[%d] OK!!\n",priv->pmib->p2p_mib.p2p_op_channel); + return 0; +} + + +int p2pcmd_set_devicename(struct rtl8192cd_priv *priv, unsigned char *data) +{ + unsigned char devname[33]; + devname[32]='\0'; + strcpy(devname, data); + P2P_DEBUG("set dev name[%s]\n",devname); + strcpy(priv->pmib->p2p_mib.p2p_device_name ,devname ); + return 0; + +} + +int p2pcmd_set_pincode(struct rtl8192cd_priv *priv, char *data) +{ + //unsigned char macNpin[32]; + char *delim=","; + char *strP; + unsigned char TargetMac[6]; + unsigned char TargetPin[8]; + + //strcpy(macNpin, data); + P2P_DEBUG("cmd=[%s]\n",data); + + strP=strtok(data,delim); // first get macaddress + if(strP){ + P2P_DEBUG("mac=[%s]\n",strP); + rtl_string_to_hex(strP ,TargetMac , strlen(strP)); + memcpy(priv->p2pPtr->target_device_addr , TargetPin , 6); + } + + strP=strtok(NULL,delim); // fsecond get PIN code + if(strP){ + P2P_DEBUG("set PIN=[%s]\n",strP); + //string_to_hex(strP ,TargetPin , strlen(strP)); + strcpy(priv->p2pPtr->target_dev_pin_code , strP); + } + + return 0; + +} + + +int p2pcmd_set_p2pstatus(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int status = _atoi(data , 10); + priv->pmib->p2p_mib.p2p_state = status ; + P2P_DEBUG("set p2p_state to[%d] OK!!\n",status); + return 0; + + +} + +int p2pcmd_apply(struct rtl8192cd_priv *priv, unsigned char *data) +{ + p2p_init(priv); + return 0; +} + + +#define P2P_COMMAND_LIST 0 // no meaning + + +struct p2p_cmd_list p2p_cmd_tbl_lev1[] = { + + {"dwellch",p2pcmd_set_listen_channel}, // setting listen channel, should be 1,6,11 + {"intent",p2pcmd_set_intent_value}, // setting intent value + {"opch",p2pcmd_set_op_channel}, // setting operation channel + {"devname",p2pcmd_set_devicename}, // setting device name + {"keypad",p2pcmd_set_pincode}, // setting device name + {"setp2pstatus",p2pcmd_set_p2pstatus}, // setting P2P_STATE + {"asgo",p2pcmd_force_GO}, // force to GO role + {"bakdev",p2pcmd_backtoDev}, // force to device mode + {"apply",p2pcmd_apply}, + {"enable",p2pcmd_enable}, + {"scan",P2P_scan}, + {"listen",P2P_listen}, + {"search",P2P_search}, + {"discovery",p2pcmd_discovery}, + {"find",p2pcmd_find}, + {"status",P2P_show_status}, + {"help",P2P_show_command} + +}; + +int p2pcmdCnt = sizeof(p2p_cmd_tbl_lev1) / sizeof(struct p2p_cmd_list); +int process_p2p_cmd(struct rtl8192cd_priv *priv, unsigned char *data) +{ + + char *val=NULL; + int ix; + int res=0; + int found=0; + + if( !(OPMODE&WIFI_P2P_SUPPORT )){ + P2P_DEBUG("interface no support P2P now!!!\n"); + return 0; + } + + for(ix=0; ix +#include +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#ifdef __KERNEL__ +#include "./ieee802_mib.h" +#elif defined(__ECOS) +#include +#include +#endif +#ifdef RTK_NL80211 +#include "./8192cd_cfg80211.h" +#endif +#include "./8192cd_headers.h" +#if defined(CONFIG_WLAN_HAL) +#include "./WlanHAL/HalHeader/HalComReg.h" +#endif +#ifdef CONFIG_RTK_MESH +#include "../mesh_ext/mesh_route.h" +#include "../mesh_ext/mesh_util.h" +#endif // CONFIG_RTK_MESH +#if defined(_INCLUDE_PROC_FS_) || defined(__ECOS) +#ifdef __KERNEL__ +#include +#endif + +/* + * Note : These define someone copy to ./mesh_ext/mesh_proc.c !! +*/ +#ifdef __ECOS +typedef void pr_fun(char *fmt, ...); +extern pr_fun *ecos_pr_fun; + +#define PRINT_ONE(val, format, line_end) { \ + ecos_pr_fun(format, val); \ + if (line_end) \ + ecos_pr_fun("\n"); \ +} + +#define PRINT_ARRAY(val, format, len, line_end) { \ + int index; \ + for (index=0; index64) +#define PRINT_BITMAP_ARG(name, para) { \ + PRINT_ONE(name, "%s: ", 0); \ + PRINT_ONE(para._staMap_, "0x%08x", 1); \ + PRINT_ONE(name, "%s ext 1: ", 0); \ + PRINT_ONE(para._staMap_ext_1, "0x%08x", 1); \ + PRINT_ONE(name, "%s ext 2: ", 0); \ + PRINT_ONE(para._staMap_ext_2, "0x%08x", 1); \ + PRINT_ONE(name, "%s ext 3: ", 0); \ + PRINT_ONE(para._staMap_ext_3, "0x%08x", 1); \ +} + +#elif (NUM_STAT >32) +#define PRINT_BITMAP_ARG(name, para) { \ + PRINT_ONE(name, "%s: ", 0); \ + PRINT_ONE(para._staMap_, "0x%08x", 1); \ + PRINT_ONE(name, "%s ext 1: ", 0); \ + PRINT_ONE(para._staMap_ext_1, "0x%08x", 1); \ +} +#else +#define PRINT_BITMAP_ARG(name, para) { \ + PRINT_ONE(name, "%s: ", 0); \ + PRINT_ONE(para._staMap_, "0x%08x", 1); \ +} +#endif + +#if defined(__ECOS) || defined(CONFIG_RTL_PROC_NEW) +#define CHECK_LEN do {} while(0) +#else +#define CHECK_LEN { \ + len += size; \ + pos = begin + len; \ + if (pos < offset) { \ + len = 0; \ + begin = pos; \ + } else { \ + if (len == size) { \ + len -= (offset-begin); \ + memcpy(buf, &buf[offset-begin], len); \ + begin = offset; \ + } \ + if (len > length) \ + goto _ret; \ + } \ +} +#endif + +#ifdef CONFIG_RTL_PROC_NEW +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19) +static inline struct inode *file_inode(struct file *f) +{ + return f->f_path.dentry->d_inode; +} +#else // <= Linux 2.6.19 +static inline struct inode *file_inode(struct file *f) +{ + return f->f_dentry->d_inode; +} +#endif +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) +void *PDE_DATA(const struct inode *inode) +{ + return PDE(inode)->data; +} +#endif + +#define RTK_DECLARE_READ_PROC_FOPS(read_proc) \ + int read_proc##_open(struct inode *inode, struct file *file) \ + { \ + return(single_open(file, read_proc, PDE_DATA(file_inode(file)))); \ + } \ + struct file_operations read_proc##_fops = { \ + .open = read_proc##_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + } + +#define RTK_DECLARE_WRITE_PROC_FOPS(write_proc) \ + static ssize_t write_proc##_write(struct file * file, const char __user * userbuf, \ + size_t count, loff_t * off) \ + { \ + return write_proc(file, userbuf,count, PDE_DATA(file_inode(file))); \ + } \ + struct file_operations write_proc##_fops = { \ + .write = write_proc##_write, \ + } + + +#define RTK_DECLARE_READ_WRITE_PROC_FOPS(read_proc,write_proc) \ + static ssize_t read_proc##_write(struct file * file, const char __user * userbuf, \ + size_t count, loff_t * off) \ + { \ + return write_proc(file, userbuf,count, PDE_DATA(file_inode(file))); \ + } \ + int read_proc##_open(struct inode *inode, struct file *file) \ + { \ + return(single_open(file, read_proc, PDE_DATA(file_inode(file)))); \ + } \ + struct file_operations read_proc##_fops = { \ + .open = read_proc##_open, \ + .read = seq_read, \ + .write = read_proc##_write, \ + .llseek = seq_lseek, \ + .release = single_release, \ + } + + +#define RTK_CREATE_PROC_ENTRY(name) \ + proc_create_data(name, 0644, rtl8192cd_proc_root, &rtl8192cd_proc_##name##_fops, NULL); + +#define RTK_CREATE_PROC_READ_ENTRY(p, name, func) \ +{ \ + p = proc_create_data(name, 0644, rtl8192cd_proc_root, &func##_fops, (void *)dev); \ +} + +#define RTK_CREATE_PROC_READ_WRITE_ENTRY(p, name, func, write_func) \ +{ \ + proc_create_data(name, 0644, rtl8192cd_proc_root, &func##_fops, (void *)dev); \ +} + +#define RTK_CREATE_PROC_WRITE_ENTRY(p, name, write_func) \ +{ \ + proc_create_data(name, 0644, rtl8192cd_proc_root, &write_func##_fops, (void *)dev); \ +} + + + +#else +#define RTK_CREATE_PROC_ENTRY(name) \ + if ( create_proc_entry (name, 0644, rtl8192cd_proc_root, \ + rtl8192cd_proc_##name, (void *)dev) == NULL ) { \ + printk("create proc %s failed!\n", name); \ + return; \ + } + +#define RTK_CREATE_PROC_READ_ENTRY(p, name, func) \ + if ( (p = create_proc_read_entry (name, 0644, rtl8192cd_proc_root, \ + func, (void *)dev)) == NULL ) { \ + printk("create proc %s failed!\n", name); \ + return; \ + } +#define RTK_CREATE_PROC_READ_WRITE_ENTRY(p, name, func, write_func) \ +{\ + if ( (p = create_proc_read_entry (name, 0644, rtl8192cd_proc_root, \ + func, (void *)dev)) == NULL ) { \ + printk("create proc %s failed!\n", name); \ + return; \ + } \ + p->write_proc = write_func;\ +} +#define RTK_CREATE_PROC_WRITE_ENTRY(p, name, write_func) \ +{ \ + if ( (p = create_proc_entry(name, 0644, rtl8192cd_proc_root)) == NULL ) { \ + printk("create proc %s failed!\n", name); \ + return; \ + } \ + p->write_proc = write_func; \ + p->data = (void *)dev; \ +} + +#endif + + + +#ifdef __ECOS +const char* MCS_DATA_RATEStr[2][2][24] = +#else +const unsigned char* MCS_DATA_RATEStr[2][2][24] = +#endif +{ + {{"6.5", "13", "19.5", "26", "39", "52", "58.5", "65", + "13", "26", "39" ,"52", "78", "104", "117", "130", + "19.5", "39", "58.5", "78" ,"117", "156", "175.5", "195"}, // Long GI, 20MHz + + {"7.2", "14.4", "21.7", "28.9", "43.3", "57.8", "65", "72.2", + "14.4", "28.9", "43.3", "57.8", "86.7", "115.6", "130", "144.5", + "21.7", "43.3", "65", "86.7", "130", "173.3", "195", "216.7"} }, // Short GI, 20MHz + + {{"13.5", "27", "40.5", "54", "81", "108", "121.5", "135", + "27", "54", "81", "108", "162", "216", "243", "270", + "40.5", "81", "121.5", "162", "243", "324", "364.5", "405"}, // Long GI, 40MHz + + {"15", "30", "45", "60", "90", "120", "135", "150", + "30", "60", "90", "120", "180", "240", "270", "300", + "45", "90", "135", "180", "270", "360", "405", "450"} } // Short GI, 40MHz +}; + + +#ifdef RTK_AC_SUPPORT + +extern const u2Byte VHT_MCS_DATA_RATE[3][2][30]; +int query_vht_rate(struct stat_info *pstat) +{ + int txrate = pstat->current_tx_rate; + if(is_MCS_rate(txrate)) { + unsigned char sg = (pstat->ht_current_tx_info & TX_USE_SHORT_GI) ? 1 : 0; + if(is_VHT_rate(txrate)) { + txrate = VHT_MCS_DATA_RATE[MIN_NUM(pstat->tx_bw, 2)][sg][(txrate - VHT_RATE_ID)]; + } else { + char index = txrate & 0xf; + txrate= VHT_MCS_DATA_RATE[MIN_NUM(pstat->tx_bw, 1)][sg][(index <8) ? index :(index+2)]; + } + } + return (txrate>>1); +} + +int query_vht_rx_rate(struct stat_info *pstat) +{ + int rxrate = pstat->rx_rate; + if(is_MCS_rate(rxrate)) { + unsigned char sg = (pstat->rx_splcp) ? 1 : 0; + if(is_VHT_rate(rxrate)) { + rxrate = VHT_MCS_DATA_RATE[MIN_NUM(pstat->rx_bw, 2)][sg][(rxrate - VHT_RATE_ID)]; + } else { + char index = rxrate & 0xf; + rxrate= VHT_MCS_DATA_RATE[MIN_NUM(pstat->rx_bw, 1)][sg][(index <8) ? index :(index+2)]; + } + } + return (rxrate>>1); +} + +#endif + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_staconfig(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_staconfig(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + int pos = 0, i; +#ifdef __ECOS + char tmpbuf[100]; +#else + unsigned char tmpbuf[100]; +#endif + + PRINT_ONE(" Dot11StationConfigEntry...", "%s", 1); + PRINT_ARRAY_ARG(" dot11Bssid: ", + priv->pmib->dot11StationConfigEntry.dot11Bssid, "%02x", 6); + + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen); + tmpbuf[priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen] = '\0'; + PRINT_ONE(" dot11DesiredSSID:(Len ", "%s", 0); + PRINT_ONE(priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen, "%d) ", 0); + PRINT_ONE(tmpbuf, "%s", 1); + + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.dot11DefaultSSID, priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen); + tmpbuf[priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen] = '\0'; + PRINT_ONE(" dot11DefaultSSID:(Len ", "%s", 0); + PRINT_ONE(priv->pmib->dot11StationConfigEntry.dot11DefaultSSIDLen, "%d) ", 0); + PRINT_ONE(tmpbuf, "%s", 1); + + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan, priv->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen); + tmpbuf[priv->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen] = '\0'; + PRINT_ONE(" dot11SSIDtoScan:(Len ", "%s", 0); + PRINT_ONE(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen, "%d) ", 0); + PRINT_ONE(tmpbuf, "%s", 1); + + PRINT_ARRAY_ARG(" dot11DesiredBssid: ", + priv->pmib->dot11StationConfigEntry.dot11DesiredBssid, "%02x", 6); + PRINT_ARRAY_ARG(" dot11OperationalRateSet: ", + priv->pmib->dot11StationConfigEntry.dot11OperationalRateSet, "%02x", + priv->pmib->dot11StationConfigEntry.dot11OperationalRateSetLen); + PRINT_SINGL_ARG(" dot11OperationalRateSetLen: ", + priv->pmib->dot11StationConfigEntry.dot11OperationalRateSetLen, "%d"); + PRINT_SINGL_ARG(" dot11BeaconPeriod: ", + priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod, "%d"); + PRINT_SINGL_ARG(" dot11DTIMPeriod: ", + priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod, "%d"); + PRINT_SINGL_ARG(" dot11swcrypto: ", + priv->pmib->dot11StationConfigEntry.dot11swcrypto, "%d"); + PRINT_SINGL_ARG(" dot11AclMode: ", + priv->pmib->dot11StationConfigEntry.dot11AclMode, "%d"); + PRINT_SINGL_ARG(" dot11AclNum: ", + priv->pmib->dot11StationConfigEntry.dot11AclNum, "%d"); + + for (i=0; ipmib->dot11StationConfigEntry.dot11AclNum; i++) { + sprintf(tmpbuf, " dot11AclAddr[%d]: ", i); + PRINT_ARRAY_ARG(tmpbuf, priv->pmib->dot11StationConfigEntry.dot11AclAddr[i], "%02x", 6); + } +#ifdef D_ACL + if(priv->pmib->dot11StationConfigEntry.dot11AclMode) { + struct list_head *phead, *plist; + struct wlan_acl_node *paclnode; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + phead = &priv->wlan_acl_list; + + SMP_LOCK_ACL(flags); + + plist = phead->next; + if (plist != phead) { + PRINT_ONE(" Access control list...", "%s", 1); + do { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + PRINT_ONE(" hwaddr: ", "%s", 0); + PRINT_ARRAY( paclnode->addr, "%02x", MACADDRLEN, 0); + PRINT_ONE((paclnode->mode== ACL_allow)?"allow":((paclnode->mode== ACL_deny)?"deny":"invalid"), "(%s)", 1); + } while (plist != phead); + } + + SMP_UNLOCK_ACL(flags); + } +#endif + + PRINT_SINGL_ARG(" dot11SupportedRates: ", + priv->pmib->dot11StationConfigEntry.dot11SupportedRates, "0x%x"); + PRINT_SINGL_ARG(" dot11BasicRates: ", + priv->pmib->dot11StationConfigEntry.dot11BasicRates, "0x%x"); + PRINT_SINGL_ARG(" dot11RegDomain: ", + priv->pmib->dot11StationConfigEntry.dot11RegDomain, "%d"); + PRINT_SINGL_ARG(" autoRate: ", + priv->pmib->dot11StationConfigEntry.autoRate, "%d"); + PRINT_SINGL_ARG(" fixedTxRate: ", + priv->pmib->dot11StationConfigEntry.fixedTxRate, "0x%x"); +#ifdef RTK_AC_SUPPORT //vht rate + PRINT_SINGL_ARG(" dot11Supported VHT Rates: ", + priv->pmib->dot11acConfigEntry.dot11SupportedVHT, "%x"); + PRINT_SINGL_ARG(" dot11 VHT tx rate map: ", + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap, "%x"); +#endif + PRINT_SINGL_ARG(" swTkipMic: ", + priv->pmib->dot11StationConfigEntry.swTkipMic, "%d"); + PRINT_SINGL_ARG(" protectionDisabled: ", + priv->pmib->dot11StationConfigEntry.protectionDisabled, "%d"); + PRINT_SINGL_ARG(" olbcDetectDisabled: ", + priv->pmib->dot11StationConfigEntry.olbcDetectDisabled, "%d"); + PRINT_SINGL_ARG(" nmlscDetectDisabled: ", + priv->pmib->dot11StationConfigEntry.nmlscDetectDisabled, "%d"); + PRINT_SINGL_ARG(" legacySTADeny: ", + priv->pmib->dot11StationConfigEntry.legacySTADeny, "%d"); +#ifdef CLIENT_MODE + PRINT_SINGL_ARG(" fastRoaming: ", + priv->pmib->dot11StationConfigEntry.fastRoaming, "%d"); +#endif + PRINT_SINGL_ARG(" lowestMlcstRate: ", + priv->pmib->dot11StationConfigEntry.lowestMlcstRate, "%d"); + PRINT_SINGL_ARG(" supportedStaNum: ", + priv->pmib->dot11StationConfigEntry.supportedStaNum, "%d"); +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.sc_device_name, strlen(priv->pmib->dot11StationConfigEntry.sc_device_name)); + tmpbuf[strlen(priv->pmib->dot11StationConfigEntry.sc_device_name)] = '\0'; + PRINT_ONE(" scDeviceName: ", "%s", 0); + PRINT_ONE(tmpbuf, "%s", 1); + + PRINT_SINGL_ARG(" scDeviceType: ", + priv->pmib->dot11StationConfigEntry.sc_device_type, "%d"); + + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen); + tmpbuf[priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen] = '\0'; + PRINT_ONE(" scSSID: ", "%s", 0); + PRINT_ONE(tmpbuf, "%s", 1); + + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.sc_passwd, strlen(priv->pmib->dot11StationConfigEntry.sc_passwd)); + tmpbuf[strlen(priv->pmib->dot11StationConfigEntry.sc_passwd)] = '\0'; + PRINT_ONE(" scPassword: ", "%s", 0); + PRINT_ONE(tmpbuf, "%s", 1); + + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.sc_pin, strlen(priv->pmib->dot11StationConfigEntry.sc_pin)); + tmpbuf[strlen(priv->pmib->dot11StationConfigEntry.sc_pin)] = '\0'; + PRINT_ONE(" scPin: ", "%s", 0); + PRINT_ONE(tmpbuf, "%s", 1); + + memcpy(tmpbuf, priv->pmib->dot11StationConfigEntry.sc_default_pin, strlen(priv->pmib->dot11StationConfigEntry.sc_default_pin)); + tmpbuf[strlen(priv->pmib->dot11StationConfigEntry.sc_default_pin)] = '\0'; + PRINT_ONE(" scDefaultPin: ", "%s", 0); + PRINT_ONE(tmpbuf, "%s", 1); + + PRINT_SINGL_ARG(" scSyncVxdToRoot: ", + priv->pmib->dot11StationConfigEntry.sc_sync_vxd_to_root, "%d"); + PRINT_SINGL_ARG(" scControlIP: ", + priv->pmib->dot11StationConfigEntry.sc_control_ip, "%x"); + + PRINT_SINGL_ARG(" scStatus: ", + priv->pmib->dot11StationConfigEntry.sc_status, "%d"); +#endif + + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_auth(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_auth(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" Dot1180211AuthEntry...", "%s", 1); + PRINT_SINGL_ARG(" dot11AuthAlgrthm: ", + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm, "%d"); + PRINT_SINGL_ARG(" dot11PrivacyAlgrthm: ", + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm, "%d"); + PRINT_SINGL_ARG(" dot11PrivacyKeyIndex: ", + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex, "%d"); + PRINT_SINGL_ARG(" dot11PrivacyKeyLen: ", + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyLen, "%d"); +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + PRINT_SINGL_ARG(" dot11EnablePSK: ", + priv->pmib->dot1180211AuthEntry.dot11EnablePSK, "%d"); + PRINT_SINGL_ARG(" dot11WPACipher: ", + priv->pmib->dot1180211AuthEntry.dot11WPACipher, "%d"); +#ifdef RTL_WPA2 + PRINT_SINGL_ARG(" dot11WPA2Cipher: ", + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher, "%d"); +#endif +#ifdef CONFIG_IEEE80211W + PRINT_SINGL_ARG(" dot11IEEE80211W: ", + priv->pmib->dot1180211AuthEntry.dot11IEEE80211W, "%d"); + PRINT_SINGL_ARG(" dot11EnableSHA256: ", + priv->pmib->dot1180211AuthEntry.dot11EnableSHA256, "%d"); +#endif + PRINT_SINGL_ARG(" dot11PassPhrase: ", + priv->pmib->dot1180211AuthEntry.dot11PassPhrase, "%s"); + PRINT_SINGL_ARG(" dot11PassPhraseGuest: ", + priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest, "%s"); + PRINT_SINGL_ARG(" dot11GKRekeyTime: ", + priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime, "%ld"); + PRINT_SINGL_ARG(" dot11UKRekeyTime: ", + priv->pmib->dot1180211AuthEntry.dot11UKRekeyTime, "%ld"); +#endif + +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + PRINT_SINGL_ARG(" 4-way status: ", + priv->dot114WayStatus, "%d"); + } +#endif + + PRINT_ONE(" Dot118021xAuthEntry...", "%s", 1); + PRINT_SINGL_ARG(" dot118021xAlgrthm: ", + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm, "%d"); + PRINT_SINGL_ARG(" dot118021xDefaultPort: ", + priv->pmib->dot118021xAuthEntry.dot118021xDefaultPort, "%d"); + PRINT_SINGL_ARG(" dot118021xcontrolport: ", + priv->pmib->dot118021xAuthEntry.dot118021xcontrolport, "%d"); + PRINT_ONE(" RADIUS Accounting...", "%s", 1); + PRINT_SINGL_ARG(" Enabled: ",priv->pmib->dot118021xAuthEntry.acct_enabled, "%d"); + PRINT_SINGL_ARG(" Idle period to leave STA: ",priv->pmib->dot118021xAuthEntry.acct_timeout_period, "%lu min(s)"); + PRINT_SINGL_ARG(" Idle throughput to leave STA: ", priv->pmib->dot118021xAuthEntry.acct_timeout_throughput, "%d Kbpm"); + + PRINT_ONE(" Dot11RsnIE...", "%s", 1); + PRINT_ARRAY_ARG(" rsnie: ", + priv->pmib->dot11RsnIE.rsnie, "%02x", priv->pmib->dot11RsnIE.rsnielen); + PRINT_SINGL_ARG(" rsnielen: ", priv->pmib->dot11RsnIE.rsnielen, "%d"); + +#ifdef CONFIG_RTL_WAPI_SUPPORT + PRINT_ONE(" Dot1180211WAPIEntry...", "%s", 1); + PRINT_SINGL_ARG(" dot11EnableWAPI: ", + priv->pmib->wapiInfo.wapiType, "%d"); +#ifdef WAPI_SUPPORT_MULTI_ENCRYPT + PRINT_SINGL_ARG(" dot11wapiUCastEncodeType: ", + priv->pmib->wapiInfo.wapiUCastEncodeType, "%d"); + PRINT_SINGL_ARG(" dot11wapiMCastEncodeType: ", + priv->pmib->wapiInfo.wapiMCastEncodeType, "%d"); +#endif + PRINT_ARRAY_ARG(" dot11wapiPsk: ", + priv->pmib->wapiInfo.wapiPsk.octet, "%02x", WAPI_PSK_LEN); + PRINT_SINGL_ARG(" dot11wapiwapiPsklen: ", + priv->pmib->wapiInfo.wapiPsk.len, "%d"); + PRINT_SINGL_ARG(" dot11wapiUpdateUCastKeyType: ", + priv->pmib->wapiInfo.wapiUpdateUCastKeyType, "%u"); + PRINT_SINGL_ARG(" dot11wapiUpdateUCastKeyTimeout: ", + (unsigned int)priv->pmib->wapiInfo.wapiUpdateUCastKeyTimeout, "%u"); + PRINT_SINGL_ARG(" dot11wapiUpdateUCastKeyPktNum: ", + (unsigned int)priv->pmib->wapiInfo.wapiUpdateUCastKeyPktNum, "%u"); + PRINT_SINGL_ARG(" dot11wapiUpdateMCastKeyType: ", + priv->pmib->wapiInfo.wapiUpdateMCastKeyType, "%u"); + PRINT_SINGL_ARG(" dot11wapiUpdateMCastKeyTimeout: ", + (unsigned int)priv->pmib->wapiInfo.wapiUpdateMCastKeyTimeout, "%u"); + PRINT_SINGL_ARG(" dot11wapiUpdateMCastKeyPktNum: ", + (unsigned int)priv->pmib->wapiInfo.wapiUpdateMCastKeyPktNum, "%u"); + PRINT_ARRAY_ARG(" dot11wapiTimeout: ", + priv->pmib->wapiInfo.wapiTimeout, "%08x", wapiTimeoutTotalNum); +#endif + + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_dkeytbl(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_dkeytbl(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" Dot11DefaultKeysTable...", "%s", 1); + PRINT_ARRAY_ARG(" keytype[0].skey: ", + priv->pmib->dot11DefaultKeysTable.keytype[0].skey, "%02x", 16); + PRINT_ARRAY_ARG(" keytype[1].skey: ", + priv->pmib->dot11DefaultKeysTable.keytype[1].skey, "%02x", 16); + PRINT_ARRAY_ARG(" keytype[2].skey: ", + priv->pmib->dot11DefaultKeysTable.keytype[2].skey, "%02x", 16); + PRINT_ARRAY_ARG(" keytype[3].skey: ", + priv->pmib->dot11DefaultKeysTable.keytype[3].skey, "%02x", 16); + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_gkeytbl(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_gkeytbl(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + unsigned char *ptr; + + PRINT_ONE(" Dot11GroupKeysTable...", "%s", 1); +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType!=wapiDisable) + { + PRINT_SINGL_ARG(" dot11Privacy: ", + priv->pmib->wapiInfo.wapiType, "%d"); + PRINT_SINGL_ARG(" WAPI Multicast Encrypt Algorithm: ", + priv->pmib->wapiInfo.wapiMCastEncodeType, "%d"); + PRINT_SINGL_ARG(" keyInCam: ", (priv->pmib->dot11GroupKeysTable.keyInCam? "yes" : "no"), "%s"); + PRINT_SINGL_ARG(" WAPI Multicast Data KeyLen: ", + WAPI_KEY_LEN, "%d"); + PRINT_SINGL_ARG(" WAPI Multicast Mic KeyLen: ", + WAPI_KEY_LEN, "%d"); + PRINT_SINGL_ARG(" WAPI Multicast Key Index: ", + priv->wapiMCastKeyId, "%d"); + PRINT_ARRAY_ARG(" WAPI Multicast Data Key: ", + priv->wapiMCastKey[priv->wapiMCastKeyId].dataKey, "%02x", WAPI_KEY_LEN); + PRINT_ARRAY_ARG(" WAPI Multicast Mic Key: ", + priv->wapiMCastKey[priv->wapiMCastKeyId].micKey, "%02x", WAPI_KEY_LEN); + } + else +#endif + { + PRINT_SINGL_ARG(" dot11Privacy: ", + priv->pmib->dot11GroupKeysTable.dot11Privacy, "%d"); + PRINT_SINGL_ARG(" keyInCam: ", (priv->pmib->dot11GroupKeysTable.keyInCam? "yes" : "no"), "%s"); + PRINT_SINGL_ARG(" dot11EncryptKey.dot11TTKeyLen: ", + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen, "%d"); + PRINT_SINGL_ARG(" dot11EncryptKey.dot11TMicKeyLen: ", + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKeyLen, "%d"); + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11TTKey.skey: ", + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey, "%02x", 16); + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11TMicKey1.skey: ", + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKey1.skey, "%02x", 16); + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11TMicKey2.skey: ", + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKey2.skey, "%02x", 16); + ptr = (unsigned char *)&priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48.val48; + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11TXPN48.val48: ", ptr, "%02x", 8); + ptr = (unsigned char *)&priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11RXPN48.val48; + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11RXPN48.val48: ", ptr, "%02x", 8); + } + + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_operation(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_operation(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + char tmpbuf[20]; + int idx = 0; + + PRINT_ONE(" Dot11OperationEntry...", "%s", 1); + PRINT_ARRAY_ARG(" hwaddr: ", priv->pmib->dot11OperationEntry.hwaddr, "%02x", 6); + PRINT_SINGL_ARG(" opmode: ", priv->pmib->dot11OperationEntry.opmode, "0x%x"); +#ifdef MBSSID + PRINT_SINGL_ARG(" vap_init_seq: ", priv->vap_init_seq, "0x%x"); +#endif + PRINT_SINGL_ARG(" hiddenAP: ", priv->pmib->dot11OperationEntry.hiddenAP, "%d"); + PRINT_SINGL_ARG(" dot11RTSThreshold: ", priv->pmib->dot11OperationEntry.dot11RTSThreshold, "%d"); + PRINT_SINGL_ARG(" dot11FragmentationThreshold: ", priv->pmib->dot11OperationEntry.dot11FragmentationThreshold, "%d"); + PRINT_SINGL_ARG(" dot11ShortRetryLimit: ", priv->pmib->dot11OperationEntry.dot11ShortRetryLimit, "%d"); + PRINT_SINGL_ARG(" dot11LongRetryLimit: ", priv->pmib->dot11OperationEntry.dot11LongRetryLimit, "%d"); + PRINT_SINGL_ARG(" expiretime: ", priv->pmib->dot11OperationEntry.expiretime, "%d"); + PRINT_SINGL_ARG(" led_type: ", priv->pmib->dot11OperationEntry.ledtype, "%d"); +#ifdef RTL8190_SWGPIO_LED + PRINT_SINGL_ARG(" led_route: ", priv->pmib->dot11OperationEntry.ledroute, "0x%x"); +#endif + PRINT_SINGL_ARG(" iapp_enable: ", priv->pmib->dot11OperationEntry.iapp_enable, "%d"); + PRINT_SINGL_ARG(" block_relay: ", priv->pmib->dot11OperationEntry.block_relay, "%d"); + PRINT_SINGL_ARG(" deny_any: ", priv->pmib->dot11OperationEntry.deny_any, "%d"); + PRINT_SINGL_ARG(" crc_log: ", priv->pmib->dot11OperationEntry.crc_log, "%d"); + PRINT_SINGL_ARG(" wifi_specific: ", priv->pmib->dot11OperationEntry.wifi_specific, "%d"); +#ifdef WIFI_WMM + PRINT_SINGL_ARG(" qos_enable: ", priv->pmib->dot11QosEntry.dot11QosEnable, "%d"); +#ifdef WMM_APSD + PRINT_SINGL_ARG(" apsd_enable: ", priv->pmib->dot11QosEntry.dot11QosAPSD, "%d"); +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_STATION_STATE) && QOS_ENABLE && APSD_ENABLE) { + PRINT_SINGL_ARG(" uapsd_assoc: ", priv->uapsd_assoc, "%d"); + PRINT_SINGL_ARG(" UAPSD_AC_VO: ", priv->pmib->dot11QosEntry.UAPSD_AC_VO, "%d"); + PRINT_SINGL_ARG(" UAPSD_AC_VI: ", priv->pmib->dot11QosEntry.UAPSD_AC_VI, "%d"); + PRINT_SINGL_ARG(" UAPSD_AC_BE: ", priv->pmib->dot11QosEntry.UAPSD_AC_BE, "%d"); + PRINT_SINGL_ARG(" UAPSD_AC_BK: ", priv->pmib->dot11QosEntry.UAPSD_AC_BK, "%d"); + } +#endif +#endif +#endif + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + tmpbuf[idx++] = 'A'; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11B) + tmpbuf[idx++] = 'B'; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) + tmpbuf[idx++] = 'G'; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + tmpbuf[idx++] = 'N'; +#ifdef RTK_AC_SUPPORT + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + tmpbuf[idx++] = 'A'; + tmpbuf[idx++] = 'C'; + } +#endif + + tmpbuf[idx] = '\0'; + PRINT_SINGL_ARG(" net_work_type: ", tmpbuf, "%s"); + +#ifdef TX_SHORTCUT + PRINT_SINGL_ARG(" disable_txsc: ", priv->pmib->dot11OperationEntry.disable_txsc, "%d"); +#endif + +#ifdef RX_SHORTCUT + PRINT_SINGL_ARG(" disable_rxsc: ", priv->pmib->dot11OperationEntry.disable_rxsc, "%d"); +#endif + +#ifdef BR_SHORTCUT + PRINT_SINGL_ARG(" disable_brsc: ", priv->pmib->dot11OperationEntry.disable_brsc, "%d"); +#endif + + PRINT_SINGL_ARG(" guest_access: ", priv->pmib->dot11OperationEntry.guest_access, "%d"); + PRINT_SINGL_ARG(" tdls_prohibited: ", priv->pmib->dot11OperationEntry.tdls_prohibited, "%d"); + PRINT_SINGL_ARG(" tdls_cs_prohibited: ", priv->pmib->dot11OperationEntry.tdls_cs_prohibited, "%d"); + return pos; +} + + +#ifdef DFS +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_DFS(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_DFS(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" Dot11DFSEntry...", "%s", 1); + + PRINT_SINGL_ARG(" DFS version: ", get_DFS_version(), "%s"); + PRINT_SINGL_ARG(" disable_DFS: ", priv->pmib->dot11DFSEntry.disable_DFS, "%d"); + PRINT_SINGL_ARG(" DFS_timeout: ", priv->pmib->dot11DFSEntry.DFS_timeout, "%d"); + PRINT_SINGL_ARG(" DFS_detected: ", priv->pmib->dot11DFSEntry.DFS_detected, "%d"); + PRINT_SINGL_ARG(" NOP_timeout: ", priv->pmib->dot11DFSEntry.NOP_timeout, "%d"); + PRINT_SINGL_ARG(" DFS_TXPAUSE_timeout: ", priv->pmib->dot11DFSEntry.DFS_TXPAUSE_timeout, "%d"); + PRINT_SINGL_ARG(" disable_tx: ", priv->pmib->dot11DFSEntry.disable_tx, "%d"); + PRINT_SINGL_ARG(" CAC_enable: ", priv->pmib->dot11DFSEntry.CAC_enable, "%d"); + + return pos; +} +#endif + + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) //FOR_8812_MP +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_rf_ac(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_rf_ac(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" Dot11ACEntry...", "%s", 1); + + PRINT_ARRAY_ARG(" pwrdiff_5G_20BW1S_OFDM1T_A: ", priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_A, "%02x", MAX_5G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff_5G_40BW2S_20BW2S_A: ", priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_A, "%02x", MAX_5G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff_5G_80BW1S_160BW1S_A: ", priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_A, "%02x", MAX_5G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff_5G_80BW2S_160BW2S_A: ", priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_A, "%02x", MAX_5G_CHANNEL_NUM); + + PRINT_ARRAY_ARG(" pwrdiff_5G_20BW1S_OFDM1T_B: ", priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_B, "%02x", MAX_5G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff_5G_40BW2S_20BW2S_B: ", priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_B, "%02x", MAX_5G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff_5G_80BW1S_160BW1S_B: ", priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_B, "%02x", MAX_5G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff_5G_80BW2S_160BW2S_B: ", priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_B, "%02x", MAX_5G_CHANNEL_NUM); + + + PRINT_ARRAY_ARG(" pwrdiff_20BW1S_OFDM1T_A: ", priv->pmib->dot11RFEntry.pwrdiff_20BW1S_OFDM1T_A, "%02x", MAX_2G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff_40BW2S_20BW2S_A: ", priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_A, "%02x", MAX_2G_CHANNEL_NUM); + + PRINT_ARRAY_ARG(" pwrdiff_20BW1S_OFDM1T_B: ", priv->pmib->dot11RFEntry.pwrdiff_20BW1S_OFDM1T_B, "%02x", MAX_2G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff_40BW2S_20BW2S_B: ", priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_B, "%02x", MAX_2G_CHANNEL_NUM); + + return pos; +} +#endif + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_rf(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_rf(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; +#ifdef __ECOS + char tmpbuf[16]; +#else + unsigned char tmpbuf[16]; +#endif + + PRINT_ONE(" Dot11RFEntry...", "%s", 1); + PRINT_SINGL_ARG(" dot11channel: ", priv->pmib->dot11RFEntry.dot11channel, "%d"); + PRINT_SINGL_ARG(" dot11ch_low: ", priv->pmib->dot11RFEntry.dot11ch_low, "%d"); + PRINT_SINGL_ARG(" dot11ch_hi: ", priv->pmib->dot11RFEntry.dot11ch_hi, "%d"); + + + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) //FOR_8812_MP +// if ((GET_CHIP_VER(priv)==VERSION_8192D) && (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) { + if ((GET_CHIP_VER(priv)==VERSION_8192D)||(GET_CHIP_VER(priv)==VERSION_8812E)||(GET_CHIP_VER(priv)==VERSION_8881A)){ + PRINT_ARRAY_ARG(" pwrlevel5GHT40_1S_A: ", priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A, "%02x", MAX_5G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrlevel5GHT40_1S_B: ", priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B, "%02x", MAX_5G_CHANNEL_NUM); + if(GET_CHIP_VER(priv)!=VERSION_8812E) { + PRINT_ARRAY_ARG(" pwrdiff5GHT40_2S: ", priv->pmib->dot11RFEntry.pwrdiff5GHT40_2S, "%02x", MAX_5G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff5GHT20: ", priv->pmib->dot11RFEntry.pwrdiff5GHT20, "%02x", MAX_5G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiff5GOFDM: ", priv->pmib->dot11RFEntry.pwrdiff5GOFDM, "%02x", MAX_5G_CHANNEL_NUM); + } + } + //} else +#endif + { + PRINT_ARRAY_ARG(" pwrlevelCCK_A: ", priv->pmib->dot11RFEntry.pwrlevelCCK_A, "%02x", MAX_2G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrlevelCCK_B: ", priv->pmib->dot11RFEntry.pwrlevelCCK_B, "%02x", MAX_2G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrlevelHT40_1S_A: ", priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A, "%02x", MAX_2G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrlevelHT40_1S_B: ", priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B, "%02x", MAX_2G_CHANNEL_NUM); + if(GET_CHIP_VER(priv)!=VERSION_8812E) { + PRINT_ARRAY_ARG(" pwrdiffHT40_2S: ", priv->pmib->dot11RFEntry.pwrdiffHT40_2S, "%02x", MAX_2G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiffHT20: ", priv->pmib->dot11RFEntry.pwrdiffHT20, "%02x", MAX_2G_CHANNEL_NUM); + PRINT_ARRAY_ARG(" pwrdiffOFDM: ", priv->pmib->dot11RFEntry.pwrdiffOFDM, "%02x", MAX_2G_CHANNEL_NUM); + } + } + +#if 0 + PRINT_ONE(" ", "%s", 1); + PRINT_ARRAY_ARG(" CCKTxAgc_A : ", (priv->pshare->phw->CCKTxAgc_A), "%d ", 4); + PRINT_ARRAY_ARG(" OFDMTxAgcOffset_A : ", (priv->pshare->phw->OFDMTxAgcOffset_A), "%d ", 8); + PRINT_ARRAY_ARG(" MCSTxAgcOffset_A : ", (priv->pshare->phw->MCSTxAgcOffset_A), "%d ", 16); + PRINT_ARRAY_ARG(" VHTTxAgcOffset_A : ", (priv->pshare->phw->VHTTxAgcOffset_A), "%d ", 20); + + PRINT_ARRAY_ARG(" CCKTxAgc_B : ", (priv->pshare->phw->CCKTxAgc_B), "%d ", 4); + PRINT_ARRAY_ARG(" OFDMTxAgcOffset_B : ", (priv->pshare->phw->OFDMTxAgcOffset_B), "%d ", 8); + PRINT_ARRAY_ARG(" MCSTxAgcOffset_B : ", (priv->pshare->phw->MCSTxAgcOffset_B), "%d ", 16); + PRINT_ARRAY_ARG(" VHTTxAgcOffset_B : ", (priv->pshare->phw->VHTTxAgcOffset_B), "%d ", 20); +#endif + +#ifdef RTK_NL80211 + PRINT_SINGL_ARG(" TxPowerRate : ", (priv->rtk->pwr_rate), "%d(percent)"); +#endif + +#ifdef TXPWR_LMT + PRINT_SINGL_ARG(" disable_txpwrlmt : ", (priv->pshare->rf_ft_var.disable_txpwrlmt), "%d"); + PRINT_SINGL_ARG(" txpwr_lmt_CCK : ", (priv->pshare->txpwr_lmt_CCK), "%d"); + PRINT_SINGL_ARG(" txpwr_lmt_OFDM : ", (priv->pshare->txpwr_lmt_OFDM), "%d"); + PRINT_SINGL_ARG(" txpwr_lmt_HT1S : ", (priv->pshare->txpwr_lmt_HT1S), "%d"); + PRINT_SINGL_ARG(" txpwr_lmt_HT2S : ", (priv->pshare->txpwr_lmt_HT2S), "%d"); +#ifdef TXPWR_LMT_NEWFILE + if((GET_CHIP_VER(priv)== VERSION_8812E) || + (GET_CHIP_VER(priv)== VERSION_8188E) || + (GET_CHIP_VER(priv)== VERSION_8192E) || + (GET_CHIP_VER(priv)== VERSION_8881A)){ +#if defined(TXPWR_LMT_8812) || defined(TXPWR_LMT_8881A) + PRINT_SINGL_ARG(" txpwr_lmt_VHT1S : ", (priv->pshare->txpwr_lmt_VHT1S), "%d"); + PRINT_SINGL_ARG(" txpwr_lmt_VHT2S : ", (priv->pshare->txpwr_lmt_VHT2S), "%d"); +#endif + PRINT_ARRAY_ARG(" tgpwr_CCK_new : ", (priv->pshare->tgpwr_CCK_new), "%d ", 2); + PRINT_ARRAY_ARG(" tgpwr_OFDM_new : ", (priv->pshare->tgpwr_OFDM_new), "%d ", 2); + PRINT_ARRAY_ARG(" tgpwr_HT1S_new : ", (priv->pshare->tgpwr_HT1S_new), "%d ", 2); + PRINT_ARRAY_ARG(" tgpwr_HT2S_new : ", (priv->pshare->tgpwr_HT2S_new), "%d ", 2); +#if defined(TXPWR_LMT_8812) || defined(TXPWR_LMT_8881A) + PRINT_ARRAY_ARG(" tgpwr_VHT1S_new : ", (priv->pshare->tgpwr_VHT1S_new), "%d ", 2); + PRINT_ARRAY_ARG(" tgpwr_VHT2S_new : ", (priv->pshare->tgpwr_VHT2S_new), "%d ", 2); +#endif + } else +#endif + { + PRINT_SINGL_ARG(" target_CCK : ", (priv->pshare->tgpwr_CCK), "%d"); + PRINT_SINGL_ARG(" target_OFDM : ", (priv->pshare->tgpwr_OFDM), "%d"); + PRINT_SINGL_ARG(" target_HT1S : ", (priv->pshare->tgpwr_HT1S), "%d"); + PRINT_SINGL_ARG(" target_HT2S : ", (priv->pshare->tgpwr_HT2S), "%d"); + } +#endif +#ifdef POWER_PERCENT_ADJUSTMENT + PRINT_SINGL_ARG(" power_percent: ", priv->pmib->dot11RFEntry.power_percent, "%d"); +#endif + PRINT_SINGL_ARG(" shortpreamble: ", priv->pmib->dot11RFEntry.shortpreamble, "%d"); + PRINT_SINGL_ARG(" trswitch: ", priv->pmib->dot11RFEntry.trswitch, "%d"); + PRINT_SINGL_ARG(" disable_ch14_ofdm: ", priv->pmib->dot11RFEntry.disable_ch14_ofdm, "%d"); + PRINT_SINGL_ARG(" xcap: ", priv->pmib->dot11RFEntry.xcap, "%d"); + PRINT_SINGL_ARG(" tssi1: ", priv->pmib->dot11RFEntry.tssi1, "%d"); + PRINT_SINGL_ARG(" tssi2: ", priv->pmib->dot11RFEntry.tssi2, "%d"); + PRINT_SINGL_ARG(" ther: ", priv->pmib->dot11RFEntry.ther, "%d"); + + switch (priv->pshare->phw->MIMO_TR_hw_support) { + case MIMO_1T2R: + sprintf(tmpbuf, "1T2R"); + break; + case MIMO_1T1R: + sprintf(tmpbuf, "1T1R"); + break; + case MIMO_2T2R: + sprintf(tmpbuf, "2T2R"); + break; + case MIMO_3T3R: + sprintf(tmpbuf, "3T3R"); + break; + case MIMO_4T4R: + sprintf(tmpbuf, "4T4R"); + break; + default: + sprintf(tmpbuf, "2T4R"); + break; + } + PRINT_SINGL_ARG(" MIMO_TR_hw_support: ", tmpbuf, "%s"); + + switch (priv->pmib->dot11RFEntry.MIMO_TR_mode) { + case MIMO_1T2R: + sprintf(tmpbuf, "1T2R"); + break; + case MIMO_1T1R: + sprintf(tmpbuf, "1T1R"); + break; + case MIMO_2T2R: + sprintf(tmpbuf, "2T2R"); + break; + case MIMO_3T3R: + sprintf(tmpbuf, "3T3R"); + break; + case MIMO_4T4R: + sprintf(tmpbuf, "4T4R"); + break; + default: + sprintf(tmpbuf, "2T4R"); + break; + } + PRINT_SINGL_ARG(" MIMO_TR_mode: ", tmpbuf, "%s"); + +#ifdef RF_MIMO_SWITCH + PRINT_SINGL_ARG(" RF status: ", priv->pshare->rf_status, "%d"); +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + PRINT_SINGL_ARG(" phyBandSelect: ", priv->pmib->dot11RFEntry.phyBandSelect, "%d"); + + switch (priv->pmib->dot11RFEntry.macPhyMode) { + case SINGLEMAC_SINGLEPHY: + sprintf(tmpbuf, "SMSP"); + break; + case DUALMAC_SINGLEPHY: + sprintf(tmpbuf, "DMSP"); + break; + case DUALMAC_DUALPHY: + sprintf(tmpbuf, "DMDP"); + break; + default: + sprintf(tmpbuf, "unknown"); + break; + } + PRINT_SINGL_ARG(" macPhyMode: ", tmpbuf, "%s"); + } +#endif + +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188C) { + if(IS_UMC_B_CUT_88C(priv)) + sprintf(tmpbuf, "RTL6195B"); + else if(IS_88RE(priv)) + sprintf(tmpbuf, "RTL8188R"); + else + sprintf(tmpbuf, "RTL8188C"); + } else if (GET_CHIP_VER(priv) == VERSION_8192C){ + sprintf(tmpbuf, "RTL8192C"); + } + + if ((GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C)) { + if (IS_TEST_CHIP(priv)) + strcat(tmpbuf, "t"); + else + strcat(tmpbuf, "n"); + } +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + sprintf(tmpbuf, "RTL8192D"); +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + sprintf(tmpbuf, "RTL8188E"); +#ifdef SUPPORT_RTL8188E_TC + if (IS_TEST_CHIP(priv)) + strcat(tmpbuf, "t"); +#endif + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { +#ifdef CONFIG_RTL_8812AR_VN_SUPPORT + sprintf(tmpbuf, "RTL8812AR-VN"); +#else + sprintf(tmpbuf, "RTL8812"); +#endif + if (IS_TEST_CHIP(priv)) + strcat(tmpbuf, "t"); + else if (IS_C_CUT_8812(priv)) + strcat(tmpbuf, "c"); + } +#endif +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv) == VERSION_8881A) { + sprintf(tmpbuf, "RTL8881A"); + + if (get_bonding_type_8881A() == BOND_8881AB) + strcat(tmpbuf, "B"); + else if (get_bonding_type_8881A() == BOND_8881AM) + strcat(tmpbuf, "M"); + else if (get_bonding_type_8881A() == BOND_8881AQ) + strcat(tmpbuf, "Q"); + else if (get_bonding_type_8881A() == BOND_8881AN) + strcat(tmpbuf, "N"); + } +#endif +#if defined(CONFIG_WLAN_HAL_8192EE) + if (GET_CHIP_VER(priv) == VERSION_8192E) { + if (_GET_HAL_DATA(priv)->bTestChip) + { + sprintf(tmpbuf, "RTL8192Et"); + } else { + sprintf(tmpbuf, "RTL8192En"); + } + + if(_GET_HAL_DATA(priv)->cutVersion == ODM_CUT_A) + strcat(tmpbuf, "A"); + else if(_GET_HAL_DATA(priv)->cutVersion == ODM_CUT_B) + strcat(tmpbuf, "B"); + else if(_GET_HAL_DATA(priv)->cutVersion == ODM_CUT_C) + strcat(tmpbuf, "C"); + else if(_GET_HAL_DATA(priv)->cutVersion == ODM_CUT_D) + strcat(tmpbuf, "D"); + else + strcat(tmpbuf, "O");//others + } +#endif +#if defined(CONFIG_WLAN_HAL_8814AE) + if (GET_CHIP_VER(priv) == VERSION_8814A) + sprintf(tmpbuf, "RTL8814A"); +#endif + + if(IS_UMC_A_CUT(priv)) + strcat(tmpbuf, "u"); + + PRINT_SINGL_ARG(" chipVersion: ", tmpbuf, "%s"); + +#ifdef EN_EFUSE + if(priv->pmib->efuseEntry.enable_efuse) { + int k; + PRINT_SINGL_ARG(" autoload fail: ", priv->AutoloadFailFlag, "%d"); + PRINT_SINGL_ARG(" efuse used bytes: ", priv->EfuseUsedBytes, "%d"); + + PRINT_ONE("efuse init map...", "%s", 1); + for(k=0; kEfuseMapLen; k+=16) + PRINT_ARRAY_ARG(" ", (priv->EfuseMap[EFUSE_INIT_MAP]+k), "%02x", 16); + PRINT_ONE("efuse modify map...", "%s", 1); + for(k=0; kEfuseMapLen; k+=16) + PRINT_ARRAY_ARG(" ", (priv->EfuseMap[EFUSE_MODIFY_MAP]+k), "%02x", 16); + } +#endif +#if defined (HW_ANT_SWITCH) && !defined(CONFIG_RTL_92C_SUPPORT) && !defined(CONFIG_RTL_92D_SUPPORT) + PRINT_SINGL_ARG(" Antdiv_Type : ", ((priv->pshare->_dmODM.AntDivType==CGCS_RX_HW_ANTDIV) ? "RX_ANTDIV" : ((priv->pshare->_dmODM.AntDivType==CG_TRX_HW_ANTDIV)?"TRX_ANTDIV":"NONE")), "%s"); + PRINT_SINGL_ARG(" Antdiv switch : ", ((priv->pshare->_dmODM.antdiv_select==0) ? "Auto" : ((priv->pshare->_dmODM.antdiv_select==1)?"A1":"A2")), "%s"); +#endif + +#ifdef SW_ANT_SWITCH + PRINT_SINGL_ARG(" SW Ant switch enable: ", (SW_DIV_ENABLE ? "enable" : "disable"), "%s"); + PRINT_SINGL_ARG(" SW Diversity Antenna : ", priv->pshare->DM_SWAT_Table.CurAntenna, "%d"); +#endif + +#if defined (HW_ANT_SWITCH) &&( defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + PRINT_SINGL_ARG(" HW Ant switch enable: ", (HW_DIV_ENABLE ? "enable" : "disable"), "%s"); + PRINT_SINGL_ARG(" RxIdle Antenna : ", (priv->pshare->rf_ft_var.CurAntenna==0 ? 2 : 1), "%d"); +#endif + + PRINT_SINGL_ARG(" tx2path: ", priv->pmib->dot11RFEntry.tx2path, "%d"); + PRINT_SINGL_ARG(" txbf: ", priv->pmib->dot11RFEntry.txbf, "%d"); + +#ifdef RTL8192D_INT_PA + PRINT_SINGL_ARG(" use_intpa92d: ", priv->pshare->rf_ft_var.use_intpa92d, "%d"); +#endif +#if defined(CONFIG_SDIO_HCI) && defined(HIGH_POWER_EXT_LNA) +#ifdef HIGH_POWER_EXT_PA + PRINT_SINGL_ARG(" FEM LNA type: ", EXT_LNA_TYPE, "%d"); +#else + PRINT_SINGL_ARG(" ext.LNA type: ", EXT_LNA_TYPE, "%d"); +#endif +#else + PRINT_SINGL_ARG(" pa_type: ", priv->pmib->dot11RFEntry.pa_type, "%d"); +#endif + PRINT_SINGL_ARG(" acs_type: ", priv->pmib->dot11RFEntry.acs_type, "%d"); +#if defined(CONFIG_WLAN_HAL_8814AE) + PRINT_SINGL_ARG(" rfe_type: ", priv->pmib->dot11RFEntry.rfe_type, "%u"); +#endif + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_bssdesc(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_bssdesc(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + unsigned char tmpbuf[33]; + + PRINT_ONE(" bss_desc...", "%s", 1); + PRINT_ARRAY_ARG(" bssid: ", priv->pmib->dot11Bss.bssid, "%02x", MACADDRLEN); + + memcpy(tmpbuf, priv->pmib->dot11Bss.ssid, priv->pmib->dot11Bss.ssidlen); + tmpbuf[priv->pmib->dot11Bss.ssidlen] = '\0'; + PRINT_SINGL_ARG(" ssid: ", tmpbuf, "%s"); + + PRINT_SINGL_ARG(" ssidlen: ", priv->pmib->dot11Bss.ssidlen, "%d"); + PRINT_SINGL_ARG(" bsstype: ", priv->pmib->dot11Bss.bsstype, "%x"); + PRINT_SINGL_ARG(" beacon_prd: ", priv->pmib->dot11Bss.beacon_prd, "%d"); + PRINT_SINGL_ARG(" dtim_prd: ", priv->pmib->dot11Bss.dtim_prd, "%d"); +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) + PRINT_SINGL_ARG(" client mode aid: ", _AID, "%d"); +#endif + PRINT_ARRAY_ARG(" t_stamp(hex): ", priv->pmib->dot11Bss.t_stamp, "%08x", 2); + PRINT_SINGL_ARG(" ibss_par.atim_win: ", priv->pmib->dot11Bss.ibss_par.atim_win, "%d"); + PRINT_SINGL_ARG(" capability(hex): ", priv->pmib->dot11Bss.capability, "%02x"); + PRINT_SINGL_ARG(" channel: ", priv->pmib->dot11Bss.channel, "%d"); + PRINT_SINGL_ARG(" basicrate(hex): ", priv->pmib->dot11Bss.basicrate, "%x"); + PRINT_SINGL_ARG(" supportrate(hex): ", priv->pmib->dot11Bss.supportrate, "%x"); + PRINT_ARRAY_ARG(" bdsa: ", priv->pmib->dot11Bss.bdsa, "%02x", MACADDRLEN); + PRINT_SINGL_ARG(" rssi: ", priv->pmib->dot11Bss.rssi, "%d"); + PRINT_SINGL_ARG(" sq: ", priv->pmib->dot11Bss.sq, "%d"); + + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_erp(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_erp(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" ERP info...", "%s", 1); + PRINT_SINGL_ARG(" protection: ", priv->pmib->dot11ErpInfo.protection, "%d"); + PRINT_SINGL_ARG(" nonErpStaNum: ", priv->pmib->dot11ErpInfo.nonErpStaNum, "%d"); + PRINT_SINGL_ARG(" olbcDetected: ", priv->pmib->dot11ErpInfo.olbcDetected, "%d"); + PRINT_SINGL_ARG(" olbcExpired: ", priv->pmib->dot11ErpInfo.olbcExpired, "%d"); + PRINT_SINGL_ARG(" shortSlot: ", priv->pmib->dot11ErpInfo.shortSlot, "%d"); + PRINT_SINGL_ARG(" ctsToSelf: ", priv->pmib->dot11ErpInfo.ctsToSelf, "%d"); + PRINT_SINGL_ARG(" longPreambleStaNum: ", priv->pmib->dot11ErpInfo.longPreambleStaNum, "%d"); + + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_cam_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_cam_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0, i; + unsigned char TempOutputMac[6]; + unsigned char TempOutputKey[16]; + unsigned short TempOutputCfg=0; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return 0; + + PRINT_ONE(" CAM info...", "%s", 1); + PRINT_ONE(" CAM occupied: ", "%s", 0); + PRINT_ONE(priv->pshare->CamEntryOccupied, "%d", 1); + for (i=0; i < priv->pshare->total_cam_entry; i++) + { + PRINT_ONE(" Entry", "%s", 0); + PRINT_ONE(i, " %2d:", 0); + CAM_read_entry(priv,i,TempOutputMac,TempOutputKey,&TempOutputCfg); + PRINT_ARRAY_ARG(" MAC addr: ", TempOutputMac, "%02x", 6); + PRINT_SINGL_ARG(" Config: ", TempOutputCfg, "%x"); + PRINT_ARRAY_ARG(" Key: ", TempOutputKey, "%02x", 16); + } + + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_probe_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_probe_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + int pos = 0, i; + + PRINT_ONE(" Probe request info...", "%s", 1); + PRINT_ONE(" Entry occupied:", "%s", 0); + PRINT_ONE(priv->pshare->ProbeReqEntryOccupied, "%d", 1); + + for (i=0; ipshare->ProbeReqEntryOccupied; i++) + { + PRINT_ONE(" Entry", "%s", 0); + PRINT_ONE(priv->probe_sta[i].Entry, " %2d:", 1); + PRINT_ARRAY_ARG(" MAC addr: ", priv->probe_sta[i].addr, "%02x", MACADDRLEN); + PRINT_SINGL_ARG(" Signal strength: ",100-priv->probe_sta[i].rssi, "-%2d dB"); + } + for (i=0; iprobe_sta[i].used = 0; + priv->pshare->ProbeReqEntryOccupied = 0; + } + return pos; +} + +#ifdef HS2_SUPPORT +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_hs2(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_hs2(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0, i; + + PRINT_ONE(" HS2 info...", "%s", 1); + PRINT_SINGL_ARG(" hs_enable: ", priv->pmib->hs2Entry.hs_enable, "%d"); + + PRINT_ARRAY_ARG(" hs2_ie: ", + priv->pmib->hs2Entry.hs2_ie, "%02x", priv->pmib->hs2Entry.hs2_ielen); + PRINT_SINGL_ARG(" hs2_ielen: ", priv->pmib->hs2Entry.hs2_ielen, "%d"); + + PRINT_SINGL_ARG(" proxy arp: ", priv->proxy_arp, "%d"); + PRINT_SINGL_ARG(" dgaf_disable: ",priv->dgaf_disable, "%d"); + + PRINT_ARRAY_ARG(" interworking_ie: ", + priv->pmib->hs2Entry.interworking_ie, "%02x", priv->pmib->hs2Entry.interworking_ielen); + PRINT_SINGL_ARG(" interworking_ielen: ", priv->pmib->hs2Entry.interworking_ielen, "%d"); + + + PRINT_ARRAY_ARG(" advt_proto_ie: ", + priv->pmib->hs2Entry.advt_proto_ie, "%02x", priv->pmib->hs2Entry.advt_proto_ielen); + PRINT_SINGL_ARG(" advt_proto_ielen: ", priv->pmib->hs2Entry.advt_proto_ielen, "%d"); + + PRINT_ARRAY_ARG(" roam_ie: ", + priv->pmib->hs2Entry.roam_ie, "%02x", priv->pmib->hs2Entry.roam_ielen); + PRINT_SINGL_ARG(" roam_ielen: ", priv->pmib->hs2Entry.roam_ielen, "%d"); + + PRINT_ARRAY_ARG(" timeadvt_ie: ", + priv->pmib->hs2Entry.timeadvt_ie, "%02x", priv->pmib->hs2Entry.timeadvt_ielen); + PRINT_SINGL_ARG(" timeadvt_ielen: ", priv->pmib->hs2Entry.timeadvt_ielen, "%d"); + + PRINT_ARRAY_ARG(" timezone_ie: ", + priv->pmib->hs2Entry.timezone_ie, "%02x", priv->pmib->hs2Entry.timezone_ielen); + PRINT_SINGL_ARG(" timezone_ielen: ", priv->pmib->hs2Entry.timezone_ielen, "%d"); + + PRINT_ARRAY_ARG(" bssload_ie: ", + priv->pmib->hs2Entry.bssload_ie, "%02x", 5); + + return pos; +} +#endif // HS2_SUPPORT + +#ifdef MULTI_MAC_CLONE +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mbidcam_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mbidcam_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0, i; + unsigned int CAM[2]; + unsigned char mac[6]; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return 0; + + PRINT_ONE(" MBIDCAM info...", "%s", 1); + PRINT_ONE(" REG MBCAM_NUM: ", "%s", 0); + PRINT_ONE((RTL_R8(REG_MBID_NUM) & 0x7), "%d", 1); + for (i=0; i<20; i++) { + RTL_W32(REG_MBIDCAMCFG_2, 0x80000000|i<<24); + CAM[0] = RTL_R32(REG_MBIDCAMCFG_1); + CAM[1] = RTL_R32(REG_MBIDCAMCFG_2); + PRINT_ONE(" Entry", "%s", 0); + PRINT_ONE(i, " %2d:", 0); + PRINT_ONE(" MAC addr: ", "%s", 0); + mac[0] = CAM[0] & 0x000000ff; + mac[1] = CAM[0]>>8 & 0x000000ff; + mac[2] = CAM[0]>>16 & 0x000000ff; + mac[3] = CAM[0]>>24 & 0x000000ff; + mac[4] = CAM[1] & 0x000000ff; + mac[5] = CAM[1]>>8 & 0x000000ff; + PRINT_ARRAY_ARG("", mac, "%02x", 6); + } + + return pos; +} +#endif + +#ifdef WDS +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_wds(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_wds(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0, i; +#ifdef __ECOS + char tmpbuf[100]; +#else + unsigned char tmpbuf[100]; +#endif + + PRINT_ONE(" WDS info...", "%s", 1); + PRINT_SINGL_ARG(" wdsEnabled: ", priv->pmib->dot11WdsInfo.wdsEnabled, "%d"); + PRINT_SINGL_ARG(" wdsPure: ", priv->pmib->dot11WdsInfo.wdsPure, "%d"); + PRINT_SINGL_ARG(" wdsPriority: ", priv->pmib->dot11WdsInfo.wdsPriority, "%d"); + PRINT_SINGL_ARG(" wdsNum: ", priv->pmib->dot11WdsInfo.wdsNum, "%d"); + for (i=0; ipmib->dot11WdsInfo.wdsNum; i++) { + sprintf(tmpbuf, " wdsMacAddr[%d]: ", i); + PRINT_ARRAY_ARG(tmpbuf, priv->pmib->dot11WdsInfo.entry[i].macAddr, "%02x", 6); + PRINT_SINGL_ARG(" wdsTxRate: ", priv->pmib->dot11WdsInfo.entry[i].txRate, "0x%x"); + } + PRINT_SINGL_ARG(" wdsPrivacy: ", priv->pmib->dot11WdsInfo.wdsPrivacy, "%d"); + PRINT_ARRAY_ARG(" wdsWepKey: ", + priv->pmib->dot11WdsInfo.wdsWepKey, "%02x", 16); +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + PRINT_SINGL_ARG(" wds_passphrase: ", + priv->pmib->dot11WdsInfo.wdsPskPassPhrase, "%s"); +#endif + + return pos; +} +#endif // WDS + + +#ifdef RTK_BR_EXT +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_brext(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_brext(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" BR Ext info...", "%s", 1); + PRINT_SINGL_ARG(" nat25_disable: ", priv->pmib->ethBrExtInfo.nat25_disable, "%d"); + PRINT_SINGL_ARG(" macclone_enable: ", priv->pmib->ethBrExtInfo.macclone_enable, "%d"); + PRINT_SINGL_ARG(" dhcp_bcst_disable: ", priv->pmib->ethBrExtInfo.dhcp_bcst_disable, "%d"); + PRINT_SINGL_ARG(" addPPPoETag: ", priv->pmib->ethBrExtInfo.addPPPoETag, "%d"); + PRINT_SINGL_ARG(" nat25sc_disable: ", priv->pmib->ethBrExtInfo.nat25sc_disable, "%d"); + PRINT_ARRAY_ARG(" ukpro_mac: ", priv->ukpro_mac, "%02x", MACADDRLEN); + + return pos; +} +#endif + +#ifdef MULTI_MAC_CLONE +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mstainfo(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mstainfo(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos=0, i; + + PRINT_ONE(" MAC Clone info...", "%s", 1); + PRINT_SINGL_ARG(" MAX_MAC_CLONE_NUM: ", MAX_MAC_CLONE_NUM, "%d"); + PRINT_SINGL_ARG(" MCLONE_NUM: ", priv->pshare->mclone_num, "%d"); + PRINT_SINGL_ARG(" mclone_ok: ", priv->pshare->mclone_ok, "%d"); + + PRINT_ONE("", "%s", 1); + PRINT_ONE(" Multi-STA info...", "%s", 1); + PRINT_ONE(" op aid ID Tuse hwaddr sa_addr intf", "%s", 1); + for (i=0; ipshare->mclone_sta[i].opmode, " %-4x", 0); + PRINT_ONE(priv->pshare->mclone_sta[i].aid, " %-4x", 0); + PRINT_ONE(priv->pshare->mclone_sta[i].usedStaAddrId, " %-2x", 0); + PRINT_ONE(priv->pshare->mclone_sta[i].isTimerInit, " %-4d", 0); + PRINT_ONE(" ", "%s", 0); + PRINT_ARRAY(priv->pshare->mclone_sta[i].hwaddr, "%02x", 6, 0); + PRINT_ONE(" ", "%s", 0); + PRINT_ARRAY(priv->pshare->mclone_sta[i].sa_addr, "%02x", 6, 0); + if (priv->pshare->mclone_sta[i].priv==NULL) { + PRINT_ONE("n/a", " %s", 1); + } + else { + PRINT_ONE(priv->pshare->mclone_sta[i].priv->dev->name, " %s", 1); + } + } + + PRINT_ONE("", "%s", 1); + PRINT_ONE(" Multi-STA Address Pool", "%s", 1); + for (i=0; ipshare->mclone_sta_fixed_addr[i].clone_addr, "%02x", 6); + } + + return pos; +} +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_txdesc_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_txdesc_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct rtl8192cd_hw *phw; + unsigned long *txdescptr; + unsigned int q_num = priv->txdesc_num; + + int i, len = 0; +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + off_t begin = 0; + off_t pos = 0; + int size; +#endif + + phw = GET_HW(priv); +#ifdef __ECOS + ecos_pr_fun(" Tx queue %d descriptor ..........\n", q_num); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, " Tx queue %d descriptor ..........\n", q_num); +#else + size = sprintf(buf, " Tx queue %d descriptor ..........\n", q_num); + CHECK_LEN; +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->DumpTxBDescTestHandler(priv, +#ifdef CONFIG_RTL_PROC_NEW + s, +#endif + q_num); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + if (get_txdesc(phw, q_num)) { +#ifdef __ECOS + ecos_pr_fun(" tx_desc%d/physical: 0x%.8lx/0x%.8lx\n", q_num, (unsigned long)get_txdesc(phw, q_num), + *(unsigned long *)(((unsigned long)&phw->tx_ring0_addr)+sizeof(unsigned long)*q_num)); + ecos_pr_fun(" head/tail: %3d/%-3d DW0 DW1 DW2 DW3 DW4 DW5\n", + get_txhead(phw, q_num), get_txtail(phw, q_num)); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, " tx_desc%d/physical: 0x%.8lx/0x%.8lx\n", q_num, (unsigned long)get_txdesc(phw, q_num), + *(unsigned long *)(((unsigned long)&phw->tx_ring0_addr)+sizeof(unsigned long)*q_num)); + seq_printf(s, " head/tail: %3d/%-3d DW0 DW1 DW2 DW3 DW4 DW5\n", + get_txhead(phw, q_num), get_txtail(phw, q_num)); +#else + size = sprintf(buf+len, " tx_desc%d/physical: 0x%.8lx/0x%.8lx\n", q_num, (unsigned long)get_txdesc(phw, q_num), + *(unsigned long *)(((unsigned long)&phw->tx_ring0_addr)+sizeof(unsigned long)*q_num)); + CHECK_LEN; + size = sprintf(buf+len, " head/tail: %3d/%-3d DW0 DW1 DW2 DW3 DW4 DW5\n", + get_txhead(phw, q_num), get_txtail(phw, q_num)); + CHECK_LEN; +#endif + for (i=0; i length) + len = length; /* Ending slop */ +#endif + return len; +} + + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +#ifdef __ECOS +void rtl8192cd_proc_txdesc_idx_write(int txdesc_num, void *data) +#else +static int rtl8192cd_proc_txdesc_idx_write(struct file *file, const char *buffer, + unsigned long count, void *data) +#endif +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); +#ifdef __KERNEL__ + char tmp[32]; +#endif + +#ifdef __ECOS + priv->txdesc_num = txdesc_num; + if (priv->txdesc_num > 5) { + ecos_pr_fun("Invalid tx desc number!\n"); + priv->txdesc_num = 0; + } + else + ecos_pr_fun("Ready to dump tx desc %d\n", priv->txdesc_num); +#else + if (count < 2) + return -EFAULT; + + if (buffer && !copy_from_user(tmp, buffer, 32)) { + int num = sscanf(tmp, "%d", &priv->txdesc_num); + + if (num != 1) + panic_printk("Invalid tx desc number!\n"); + else if (priv->txdesc_num > 5) { + panic_printk("Invalid tx desc number!\n"); + priv->txdesc_num = 0; + } + else + panic_printk("Ready to dump tx desc %d\n", priv->txdesc_num); + } + return count; +#endif +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_rxdesc_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_rxdesc_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct rtl8192cd_hw *phw; + unsigned long *rxdescptr; + + int i, len = 0; +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + off_t begin = 0; + off_t pos = 0; + int size; +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + DumpRxBDesc88XX(priv, +#ifdef CONFIG_RTL_PROC_NEW + s, +#endif + 0); + return 0; + } else +#endif + { + phw = GET_HW(priv); +#ifdef __ECOS + ecos_pr_fun(" Rx queue descriptor ..........\n"); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, " Rx queue descriptor ..........\n"); +#else + size = sprintf(buf+len, " Rx queue descriptor ..........\n"); + CHECK_LEN; +#endif + if(phw->rx_descL){ +#ifdef __ECOS + ecos_pr_fun(" rx_descL/physical: 0x%.8lx/0x%.8lx\n", (unsigned long)phw->rx_descL, phw->rx_ring_addr); + #ifdef DELAY_REFILL_RX_BUF + ecos_pr_fun(" cur_rx/cur_rx_refill: %d/%d\n", phw->cur_rx, phw->cur_rx_refill); + #else + ecos_pr_fun(" cur_rx: %d\n", phw->cur_rx); + #endif +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, " rx_descL/physical: 0x%.8lx/0x%.8lx\n", (unsigned long)phw->rx_descL, phw->rx_ring_addr); + #ifdef DELAY_REFILL_RX_BUF + seq_printf(s, " cur_rx/cur_rx_refill: %d/%d\n", phw->cur_rx, phw->cur_rx_refill); + #else + seq_printf(s, " cur_rx: %d\n", phw->cur_rx); + #endif +#else + size = sprintf(buf+len, " rx_descL/physical: 0x%.8lx/0x%.8lx\n", (unsigned long)phw->rx_descL, phw->rx_ring_addr); + CHECK_LEN; + #ifdef DELAY_REFILL_RX_BUF + size = sprintf(buf+len, " cur_rx/cur_rx_refill: %d/%d\n", phw->cur_rx, phw->cur_rx_refill); + #else + size = sprintf(buf+len, " cur_rx: %d\n", phw->cur_rx); + #endif + CHECK_LEN; +#endif + for(i=0; irx_descL+i); +#ifdef __ECOS + ecos_pr_fun(" rxdesc[%02d]: 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", i, + (UINT)get_desc(rxdescptr[0]), (UINT)get_desc(rxdescptr[1]), + (UINT)get_desc(rxdescptr[2]), (UINT)get_desc(rxdescptr[3]), + (UINT)get_desc(rxdescptr[4]), (UINT)get_desc(rxdescptr[5]), + (UINT)get_desc(rxdescptr[6]), (UINT)get_desc(rxdescptr[7])); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, " rxdesc[%02d]: 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", i, + (UINT)get_desc(rxdescptr[0]), (UINT)get_desc(rxdescptr[1]), + (UINT)get_desc(rxdescptr[2]), (UINT)get_desc(rxdescptr[3]), + (UINT)get_desc(rxdescptr[4]), (UINT)get_desc(rxdescptr[5]), + (UINT)get_desc(rxdescptr[6]), (UINT)get_desc(rxdescptr[7])); +#else + size = sprintf(buf+len, " rxdesc[%02d]: 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", i, + (UINT)get_desc(rxdescptr[0]), (UINT)get_desc(rxdescptr[1]), + (UINT)get_desc(rxdescptr[2]), (UINT)get_desc(rxdescptr[3]), + (UINT)get_desc(rxdescptr[4]), (UINT)get_desc(rxdescptr[5]), + (UINT)get_desc(rxdescptr[6]), (UINT)get_desc(rxdescptr[7])); + CHECK_LEN; +#endif + } + } + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *eof = 1; + +_ret: + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ +#endif + return len; +} +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_desc_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_desc_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct rtl8192cd_hw *phw = GET_HW(priv); + int pos = 0; + + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + + PHCI_RX_DMA_MANAGER_88XX prx_dma = (PHCI_RX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PRxDMA88XX); + PHCI_TX_DMA_MANAGER_88XX ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + PHCI_RX_DMA_QUEUE_STRUCT_88XX rx_q = &(prx_dma->rx_queue[0]); + PHCI_TX_DMA_QUEUE_STRUCT_88XX tx_q = &(ptx_dma->tx_queue[MGNT_QUEUE]); + + PRINT_ONE(" descriptor info...", "%s", 1); + PRINT_ONE(" RX queue:", "%s", 1); + PRINT_ONE(" RDSAR: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(RX_DESA), "0x%.8x", 0); + + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)rx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)rx_q->host_idx, "%d", 1); + + PRINT_ONE(" queue 0:", "%s", 1); + PRINT_ONE(" TMGDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_MGQ_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[BK_QUEUE]); + PRINT_ONE(" queue 1:", "%s", 1); + PRINT_ONE(" TBKDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_BKQ_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[BE_QUEUE]); + PRINT_ONE(" queue 2:", "%s", 1); + PRINT_ONE(" TBEDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_BEQ_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[VI_QUEUE]); + PRINT_ONE(" queue 3:", "%s", 1); + PRINT_ONE(" TVIDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_VIQ_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[VO_QUEUE]); + PRINT_ONE(" queue 4:", "%s", 1); + PRINT_ONE(" TVODA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_VOQ_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[HIGH_QUEUE]); + PRINT_ONE(" queue 5:", "%s", 1); + PRINT_ONE(" TH0DA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_HI0Q_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[HIGH_QUEUE1]); + PRINT_ONE(" queue 6:", "%s", 1); + PRINT_ONE(" TH1DA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_HI1Q_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[HIGH_QUEUE2]); + PRINT_ONE(" queue 7:", "%s", 1); + PRINT_ONE(" TH2DA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_HI2Q_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[HIGH_QUEUE3]); + PRINT_ONE(" queue 8:", "%s", 1); + PRINT_ONE(" TH3DA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_HI3Q_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[HIGH_QUEUE4]); + PRINT_ONE(" queue 9:", "%s", 1); + PRINT_ONE(" TH4DA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_HI4Q_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[HIGH_QUEUE5]); + PRINT_ONE(" queue 10:", "%s", 1); + PRINT_ONE(" TH5DA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_HI5Q_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[HIGH_QUEUE6]); + PRINT_ONE(" queue 11:", "%s", 1); + PRINT_ONE(" TH6DA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_HI6Q_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + tx_q = &(ptx_dma->tx_queue[HIGH_QUEUE7]); + PRINT_ONE(" queue 12:", "%s", 1); + PRINT_ONE(" TH7DA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(REG_HI7Q_TXBD_DESA), "0x%.8x", 0); + PRINT_ONE(" hwIdx/hostIdx: ", "%s", 0); + PRINT_ONE((UINT)tx_q->hw_idx, "%d/", 0); + PRINT_ONE((UINT)tx_q->host_idx, "%d", 1); + + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + PRINT_ONE(" descriptor info...", "%s", 1); + PRINT_ONE(" RX queue:", "%s", 1); + PRINT_ONE(" rx_descL/physical: ", "%s", 0); + PRINT_ONE((unsigned long)phw->rx_descL, "0x%.8lx/", 0); + PRINT_ONE(phw->rx_ring_addr, "0x%.8lx", 1); + PRINT_ONE(" RDSAR: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(RX_DESA), "0x%.8x", 0); + +#ifdef DELAY_REFILL_RX_BUF + PRINT_ONE(" cur_rx/cur_rx_refill: ", "%s", 0); + PRINT_ONE((UINT)phw->cur_rx, "%d/", 0); + PRINT_ONE((UINT)phw->cur_rx_refill, "%d", 1); +#else + PRINT_ONE(" cur_rx: ", "%s", 0); + PRINT_ONE((UINT)phw->cur_rx, "%d", 1); +#endif + + PRINT_ONE(" queue 0:", "%s", 1); + PRINT_ONE(" tx_desc0/physical: ", "%s", 0); + PRINT_ONE((unsigned long)phw->tx_desc0, "0x%.8lx/", 0); + PRINT_ONE(phw->tx_ring0_addr, "0x%.8lx", 1); + PRINT_ONE(" TMGDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(MGQ_DESA), "0x%.8x", 0); + PRINT_ONE(" head/tail: ", "%s", 0); + PRINT_ONE((UINT)phw->txhead0, "%d/", 0); + PRINT_ONE((UINT)phw->txtail0, "%d", 1); + + PRINT_ONE(" queue 1:", "%s", 1); + PRINT_ONE(" tx_desc1/physical: ", "%s", 0); + PRINT_ONE((unsigned long)phw->tx_desc1, "0x%.8lx/", 0); + PRINT_ONE(phw->tx_ring1_addr, "0x%.8lx", 1); + PRINT_ONE(" TBKDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(BKQ_DESA), "0x%.8x", 0); + PRINT_ONE(" head/tail: ", "%s", 0); + PRINT_ONE((UINT)phw->txhead1, "%d/", 0); + PRINT_ONE((UINT)phw->txtail1, "%d", 1); + + PRINT_ONE(" queue 2:", "%s", 1); + PRINT_ONE(" tx_desc2/physical: ", "%s", 0); + PRINT_ONE((unsigned long)phw->tx_desc2, "0x%.8lx/", 0); + PRINT_ONE(phw->tx_ring2_addr, "0x%.8lx", 1); + PRINT_ONE(" TBEDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(BEQ_DESA), "0x%.8x", 0); + PRINT_ONE(" head/tail: ", "%s", 0); + PRINT_ONE((UINT)phw->txhead2, "%d/", 0); + PRINT_ONE((UINT)phw->txtail2, "%d", 1); + + PRINT_ONE(" queue 3:", "%s", 1); + PRINT_ONE(" tx_desc3/physical: ", "%s", 0); + PRINT_ONE((unsigned long)phw->tx_desc3, "0x%.8lx/", 0); + PRINT_ONE(phw->tx_ring3_addr, "0x%.8lx", 1); + PRINT_ONE(" TLPDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(VIQ_DESA), "0x%.8x", 0); + PRINT_ONE(" head/tail: ", "%s", 0); + PRINT_ONE((UINT)phw->txhead3, "%d/", 0); + PRINT_ONE((UINT)phw->txtail3, "%d", 1); + + PRINT_ONE(" queue 4:", "%s", 1); + PRINT_ONE(" tx_desc4/physical: ", "%s", 0); + PRINT_ONE((unsigned long)phw->tx_desc4, "0x%.8lx/", 0); + PRINT_ONE(phw->tx_ring4_addr, "0x%.8lx", 1); + PRINT_ONE(" TNPDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(VOQ_DESA), "0x%.8x", 0); + PRINT_ONE(" head/tail: ", "%s", 0); + PRINT_ONE((UINT)phw->txhead4, "%d/", 0); + PRINT_ONE((UINT)phw->txtail4, "%d", 1); + + PRINT_ONE(" queue 5:", "%s", 1); + PRINT_ONE(" tx_desc5/physical: ", "%s", 0); + PRINT_ONE((unsigned long)phw->tx_desc5, "0x%.8lx/", 0); + PRINT_ONE(phw->tx_ring5_addr, "0x%.8lx", 1); + PRINT_ONE(" THPDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(HQ_DESA), "0x%.8x", 0); + PRINT_ONE(" head/tail: ", "%s", 0); + PRINT_ONE((UINT)phw->txhead5, "%d/", 0); + PRINT_ONE((UINT)phw->txtail5, "%d", 1); + } +#if 0 + PRINT_ONE(" RX cmd queue:", "%s", 1); + PRINT_ONE(" rxcmd_desc/physical: ", "%s", 0); + PRINT_ONE((UINT)phw->rxcmd_desc, "0x%.8x/", 0); + PRINT_ONE((UINT)phw->rxcmd_ring_addr, "0x%.8x", 1); + PRINT_ONE(" RCDSA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(_RCDSA_), "0x%.8x", 0); + PRINT_ONE(" cur_rx: ", "%s", 0); + PRINT_ONE((UINT)phw->cur_rxcmd, "%d", 1); + + PRINT_ONE(" TX cmd queue:", "%s", 1); + PRINT_ONE(" txcmd_desc/physical: ", "%s", 0); + PRINT_ONE((UINT)phw->txcmd_desc, "0x%.8x/", 0); + PRINT_ONE((UINT)phw->txcmd_ring_addr, "0x%.8x", 1); + PRINT_ONE(" TCDA: ", "%s", 0); + PRINT_ONE((UINT)RTL_R32(_TCDA_), "0x%.8x", 0); + PRINT_ONE(" head/tail: ", "%s", 0); + PRINT_ONE((UINT)phw->txcmdhead, "%d/", 0); + PRINT_ONE((UINT)phw->txcmdtail, "%d", 1); +#endif + return pos; +} +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI +void usb_cancel_pending_urb(struct rtl8192cd_priv *priv, int q_num) +{ + _queue *urb_queue; + _list *phead, *plist; + _irqL irqL; + + struct xmit_buf *pxmitbuf; + struct urb *purb; + int retval; + + printk("[%s] q_num=%d\n", __FUNCTION__, q_num); + + urb_queue = &priv->pshare->tx_urb_waiting_queue[q_num]; + phead = get_list_head(urb_queue); + plist = NULL; + + _enter_critical(&urb_queue->lock, &irqL); + + plist = get_next(phead); + + while (rtw_end_of_queue_search(phead, plist) == FALSE) { + pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, tx_urb_list); + plist = get_next(plist); + + purb = pxmitbuf->pxmit_urb; + retval = usb_unlink_urb(purb); + if (-EINPROGRESS == retval) { + printk("usb_unlink_urb() succeed.\n"); + } else { + printk("usb_unlink_urb() fail!(retval=%d, usb->status=%d\n", + retval , purb->status); + } + } + + _exit_critical(&urb_queue->lock, &irqL); +} + +#define UNLINK_URB_BASE 10 +#define CLEAR_ENDPOINT_HALT_BASE 20 +static int rtl8192cd_proc_txurb_info_idx_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + char tmp[32]; + int num, cmd_no, retval; + + if (count < 2) + return -EFAULT; + + if (count > sizeof(tmp)) + return -EINVAL; + + if (buffer && !copy_from_user(tmp, buffer, count)) { + tmp[count-1] = '\0'; + num = sscanf(tmp, "%d", &cmd_no); + + if (num != 1) { + panic_printk("Invalid tx desc number!\n"); + } else if ((cmd_no >= 0) && (cmd_no < MAX_HW_TX_QUEUE)) { + priv->txdesc_num = cmd_no; + panic_printk("Ready to dump tx desc %d\n", priv->txdesc_num); + } else if ((cmd_no >= UNLINK_URB_BASE) && (cmd_no < (UNLINK_URB_BASE+MAX_HW_TX_QUEUE))) { + usb_cancel_pending_urb(priv, cmd_no-UNLINK_URB_BASE); + } else if ((cmd_no >= CLEAR_ENDPOINT_HALT_BASE) && (cmd_no < (CLEAR_ENDPOINT_HALT_BASE+MAX_HW_TX_QUEUE))) { + retval = usb_clear_halt(priv->pshare->pusbdev, ffaddr2pipehdl(priv, cmd_no-CLEAR_ENDPOINT_HALT_BASE)); + if (0 == retval) { + printk("usb_clear_halt() succeed for queue %d.\n", cmd_no-CLEAR_ENDPOINT_HALT_BASE); + } else { + printk("usb_clear_halt() fail!(retval=%d)\n", retval); + } + } else { + panic_printk("Invalid tx desc number!(%d)\n", cmd_no); + } + } + return count; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_txurb_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_txurb_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + unsigned int q_num = priv->txdesc_num; + + _queue *urb_queue; + _list *phead, *plist; + _irqL irqL; + + struct xmit_buf *pxmitbuf; + struct urb *purb; + struct tx_desc_info *pdescinfo; + struct tx_desc *pdesc; + int index = 0; + + int retval; + u16 status; + + int len = 0; +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + off_t begin = 0; + off_t pos = 0; + int size; +#endif + int i; + + retval = usb_get_status(priv->pshare->pusbdev, USB_RECIP_ENDPOINT, + GET_HAL_INTF_DATA(priv)->Queue2EPNum[q_num], &status); + if (retval == 2) { + printk("usb_get_status()=0x%02X for queue %d\n", status, q_num); + } + + urb_queue = &priv->pshare->tx_urb_waiting_queue[q_num]; + phead = get_list_head(urb_queue); + + _enter_critical(&urb_queue->lock, &irqL); + + plist = get_next(phead); + + while (rtw_end_of_queue_search(phead, plist) == FALSE) { + pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, tx_urb_list); + plist = get_next(plist); + + purb = pxmitbuf->pxmit_urb; + pdescinfo = pxmitbuf->txdesc_info; + +#if defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, "[urb%d] status=%d, transfer_flags=0x%X\n", index++, purb->status, purb->transfer_flags); + seq_printf(s, " [xmitbuf] q_num=%d, head=%p, data=%p, tail=%p, end=%p\n", + pxmitbuf->q_num, pxmitbuf->pkt_head, pxmitbuf->pkt_data, pxmitbuf->pkt_tail, pxmitbuf->pkt_end); +#else + size = sprintf(buf+len, "[urb%d] status=%d, transfer_flags=0x%X\n", index++, purb->status, purb->transfer_flags); + CHECK_LEN; + + size = sprintf(buf+len, " [xmitbuf] q_num=%d, head=%p, data=%p, tail=%p, end=%p\n", + pxmitbuf->q_num, pxmitbuf->pkt_head, pxmitbuf->pkt_data, pxmitbuf->pkt_tail, pxmitbuf->pkt_end); + CHECK_LEN; +#endif + + for (i = 0; i < pxmitbuf->agg_num; ++i) { + pdesc = (struct tx_desc *)pdescinfo[i].buf_ptr; +#if defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, " [pkt%02d] buf_prt=%p, buf_len=%d\n", i, pdescinfo[i].buf_ptr, pdescinfo[i].buf_len); + seq_printf(s, " txdesc: %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + (u32)get_desc(pdesc->Dword0), (u32)get_desc(pdesc->Dword1), + (u32)get_desc(pdesc->Dword2), (u32)get_desc(pdesc->Dword3), + (u32)get_desc(pdesc->Dword4), (u32)get_desc(pdesc->Dword5), + (u32)get_desc(pdesc->Dword6), (u32)get_desc(pdesc->Dword7)); +#else + size = sprintf(buf+len, " [pkt%02d] buf_prt=%p, buf_len=%d\n", i, pdescinfo[i].buf_ptr, pdescinfo[i].buf_len); + CHECK_LEN; + size = sprintf(buf+len, " txdesc: %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + (u32)get_desc(pdesc->Dword0), (u32)get_desc(pdesc->Dword1), + (u32)get_desc(pdesc->Dword2), (u32)get_desc(pdesc->Dword3), + (u32)get_desc(pdesc->Dword4), (u32)get_desc(pdesc->Dword5), + (u32)get_desc(pdesc->Dword6), (u32)get_desc(pdesc->Dword7)); + CHECK_LEN; +#endif + } + } + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *eof = 1; +#endif + +_ret: + _exit_critical(&urb_queue->lock, &irqL); + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ +#endif + return len; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_que_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_que_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; +#ifdef MBSSID + int i; + struct rtl8192cd_priv *priv_vap; +#endif + + PRINT_ONE(" free_xmit_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->free_xmit_queue.qlen, "%3d", 0); + PRINT_ONE(NR_XMITFRAME, "/%d", 0); + PRINT_ONE(priv->pshare->nr_out_of_xmitframe, " (fail:%d)", 1); + PRINT_ONE(" free_xmitbuf_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->free_xmitbuf_queue.qlen, "%2d", 0); + PRINT_ONE(NR_XMITBUFF, "/%d", 1); + PRINT_ONE(" free_xmit_extbuf_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->free_xmit_extbuf_queue.qlen, "%2d", 0); + PRINT_ONE(NR_XMIT_EXTBUFF, "/%d", 1); + PRINT_ONE(" free_urg_xmitbuf_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->free_urg_xmitbuf_queue.qlen, "%2d", 0); + PRINT_ONE(NR_URG_XMITBUFF, "/%d", 1); + PRINT_ONE(" use_hw_queue_bitmap: ", "%s", 0); + PRINT_ONE(priv->pshare->use_hw_queue_bitmap, "%08lX", 1); + PRINT_ONE(" stop_netif_tx_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->stop_netif_tx_queue, "%d", 0); + PRINT_ONE(priv->pshare->nr_stop_netif_tx_queue, " (%d)", 1); + PRINT_ONE(" tx_mc_queue:", "%s", 1); + PRINT_ONE(" q_num: ", "%s", 0); + PRINT_ONE(priv->tx_mc_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv->tx_mc_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv->tx_mc_queue), "%d", 1); +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + for (i = 0; i < RTL8192CD_NUM_VWLAN; i++) { + priv_vap = priv->pvap_priv[i]; + if (IS_DRV_OPEN(priv_vap)) { + PRINT_ONE(priv_vap->vap_id, " [va%d]q_num: ", 0); + PRINT_ONE(priv_vap->tx_mc_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv_vap->tx_mc_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv_vap->tx_mc_queue), "%d", 1); + } + } + } +#endif // MBSSID + PRINT_ONE(" tx_mgnt_queue:", "%s", 1); + PRINT_ONE(" q_num: ", "%s", 0); + PRINT_ONE(priv->tx_mgnt_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv->tx_mgnt_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv->tx_mgnt_queue), "%d", 1); +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + for (i = 0; i < RTL8192CD_NUM_VWLAN; i++) { + priv_vap = priv->pvap_priv[i]; + if (IS_DRV_OPEN(priv_vap)) { + PRINT_ONE(priv_vap->vap_id, " [va%d]q_num: ", 0); + PRINT_ONE(priv_vap->tx_mgnt_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv_vap->tx_mgnt_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv_vap->tx_mgnt_queue), "%d", 1); + } + } + } +#endif // MBSSID + PRINT_ONE(" pspoll_sta_queue:", "%s", 1); + PRINT_ONE(" q_num: ", "%s", 0); + PRINT_ONE(priv->pshare->pspoll_sta_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv->pshare->pspoll_sta_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv->pshare->pspoll_sta_queue), "%d", 1); + PRINT_ONE(" tx_urgent_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_urgent_queue.qlen, "%d", 1); + PRINT_ONE(" tx_pending_sta_queue:", "%s", 1); + PRINT_ONE(" MGQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[MGNT_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" BKQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[BK_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" BEQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[BE_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" VIQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[VI_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" VOQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[VO_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" HIQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[HIGH_QUEUE].qlen, "%-4d", 1); + PRINT_ONE(" tx_urb_waiting_queue:", "%s", 1); + PRINT_ONE(" MGQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_urb_waiting_queue[MGNT_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" BKQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_urb_waiting_queue[BK_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" BEQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_urb_waiting_queue[BE_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" VIQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_urb_waiting_queue[VI_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" VOQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_urb_waiting_queue[VO_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" HIQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_urb_waiting_queue[HIGH_QUEUE].qlen, "%-4d", 1); + + PRINT_ONE(" free_recv_queue: ", "%s", 0); + PRINT_ONE(priv->recvpriv.free_recv_queue.qlen, "%d", 0); + PRINT_ONE(NR_RECVFRAME, "/%d", 0); + PRINT_ONE(priv->recvpriv.nr_out_of_recvframe, " (fail:%d)", 1); + PRINT_ONE(" free_recv_buf_queue_cnt: ", "%s", 0); + PRINT_ONE(priv->recvpriv.free_recv_buf_queue_cnt, "%d", 0); + PRINT_ONE(NR_RECVBUFF, "/%d", 1); + + PRINT_ONE(" rx_pending_cnt: ", "%s", 0); + PRINT_ONE(priv->recvpriv.rx_pending_cnt-1, "%d", 1); + +#ifdef CONFIG_PREALLOC_RECV_SKB + PRINT_ONE(" free_recv_skb_queue: ", "%s", 0); + PRINT_ONE(skb_queue_len(&priv->recvpriv.free_recv_skb_queue), "%d", 0); + PRINT_ONE(NR_PREALLOC_RECV_SKB, "/%d", 1); +#endif + +#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX + PRINT_ONE(" recv_buf_pending_queue: ", "%s", 0); + PRINT_ONE(priv->recvpriv.recv_buf_pending_queue.qlen, "%d", 1); +#else + PRINT_ONE(" rx_skb_queue: ", "%s", 0); + PRINT_ONE(skb_queue_len(&priv->recvpriv.rx_skb_queue), "%d", 1); +#endif + + PRINT_ONE(" wake_event: ", "%s", 0); + PRINT_ONE(priv->pshare->cmd_wake, "%08lX", 1); + PRINT_ONE(" cmd_queue: ", "%s", 1); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(priv->pshare->cmd_queue.qlen, "%-4d", 0); + PRINT_ONE(" miss: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_cmd_miss, "%-4u", 0); + PRINT_ONE(" done: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_cmd, "%u", 1); + + PRINT_ONE(" rx_mgt_queue: ", "%s", 1); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(priv->pshare->rx_mgt_queue.qlen, "%-4d", 0); + PRINT_ONE(" miss: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_rx_mgt_cmd_miss, "%-4u", 0); + PRINT_ONE(" done: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_rx_mgt_cmd, "%u", 1); + + PRINT_ONE(" timer_evt_queue: ", "%s", 1); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(priv->pshare->timer_evt_queue.qlen, "%-4d", 0); + PRINT_ONE(" miss: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_timer_evt_miss, "%-4u", 0); + PRINT_ONE(" done: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_timer_evt, "%u", 1); + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + PRINT_ONE(" h2c_cmd_queue: ", "%s", 1); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(priv->pshare->h2c_cmd_queue.qlen, "%-4d", 0); + PRINT_ONE(" miss: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_h2c_cmd_miss, "%-4u", 0); + PRINT_ONE(" done: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_h2c_cmd, "%u", 1); +#endif +#ifdef CMD_THREAD_FUNC_DEBUG + PRINT_ONE(" cur_cmd_func: ", "%s", 0); + PRINT_ONE(priv->pshare->cur_cmd_func, "%p", 1); +#endif + + return pos; +} +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_que_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_que_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; +#ifdef MBSSID + int i; + struct rtl8192cd_priv *priv_vap; +#endif +#ifdef __ECOS + Rltk819x_t *info = dev->info; +#endif + + PRINT_ONE(" free_xmit_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->free_xmit_queue.qlen, "%3d", 0); + PRINT_ONE(NR_XMITFRAME, "/%d", 0); +#ifdef CONFIG_SDIO_TX_FILTER_BY_PRI + PRINT_ONE(priv->pshare->nr_out_of_xmitframe, " (fail:%d)", 0); + PRINT_ONE(priv->pshare->nr_tx_filter_vo, "(%d", 0); + PRINT_ONE(priv->pshare->nr_tx_filter_vi, "/%d", 0); + PRINT_ONE(priv->pshare->nr_tx_filter_be, "/%d", 0); + PRINT_ONE(priv->pshare->nr_tx_filter_bk, "/%d)", 1); +#else + PRINT_ONE(priv->pshare->nr_out_of_xmitframe, " (fail:%d)", 1); +#endif + PRINT_ONE(" free_xmitbuf_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->free_xmitbuf_queue.qlen, "%2d", 0); +#ifdef __ECOS + PRINT_ONE(NR_XMITBUFF, "/%d", 0); + PRINT_ONE(priv->pshare->nr_out_of_xmitbuf, " (fail:%d)", 1); +#else + PRINT_ONE(NR_XMITBUFF, "/%d", 1); +#endif + PRINT_ONE(" free_xmit_extbuf_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->free_xmit_extbuf_queue.qlen, "%2d", 0); +#ifdef __ECOS + PRINT_ONE(NR_XMIT_EXTBUFF, "/%d", 0); + PRINT_ONE(priv->pshare->nr_out_of_xmit_extbuf, " (fail:%d)", 1); +#else + PRINT_ONE(NR_XMIT_EXTBUFF, "/%d", 1); +#endif + PRINT_ONE(" free_urg_xmitbuf_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->free_urg_xmitbuf_queue.qlen, "%2d", 0); + PRINT_ONE(NR_URG_XMITBUFF, "/%d", 1); + PRINT_ONE(" use_hw_queue_bitmap: ", "%s", 0); + PRINT_ONE(priv->pshare->use_hw_queue_bitmap, "%08lX", 1); + PRINT_ONE(" stop_netif_tx_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->stop_netif_tx_queue, "%d", 0); + PRINT_ONE(priv->pshare->nr_stop_netif_tx_queue, " (%d)", 1); + PRINT_ONE(" tx_mc_queue:", "%s", 1); + PRINT_ONE(" q_num: ", "%s", 0); + PRINT_ONE(priv->tx_mc_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv->tx_mc_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv->tx_mc_queue), "%d", 1); +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + for (i = 0; i < RTL8192CD_NUM_VWLAN; i++) { + priv_vap = priv->pvap_priv[i]; + if (IS_DRV_OPEN(priv_vap)) { + PRINT_ONE(priv_vap->vap_id, " [va%d]q_num: ", 0); + PRINT_ONE(priv_vap->tx_mc_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv_vap->tx_mc_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv_vap->tx_mc_queue), "%d", 1); + } + } + } +#endif // MBSSID + PRINT_ONE(" tx_mgnt_queue:", "%s", 1); + PRINT_ONE(" q_num: ", "%s", 0); + PRINT_ONE(priv->tx_mgnt_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv->tx_mgnt_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv->tx_mgnt_queue), "%d", 1); +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) { + struct rtl8192cd_priv *priv_vxd = GET_VXD_PRIV(priv); + PRINT_ONE(priv_vxd->tx_mgnt_queue.q_num, " [vxd]q_num: %d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv_vxd->tx_mgnt_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv_vxd->tx_mgnt_queue), "%d", 1); + } +#endif // UNIVERSAL_REPEATER +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + for (i = 0; i < RTL8192CD_NUM_VWLAN; i++) { + priv_vap = priv->pvap_priv[i]; + if (IS_DRV_OPEN(priv_vap)) { + PRINT_ONE(priv_vap->vap_id, " [va%d]q_num: ", 0); + PRINT_ONE(priv_vap->tx_mgnt_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv_vap->tx_mgnt_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv_vap->tx_mgnt_queue), "%d", 1); + } + } + } +#endif // MBSSID + PRINT_ONE(" pspoll_sta_queue:", "%s", 1); + PRINT_ONE(" q_num: ", "%s", 0); + PRINT_ONE(priv->pshare->pspoll_sta_queue.q_num, "%d", 0); + PRINT_ONE(" tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&priv->pshare->pspoll_sta_queue.tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&priv->pshare->pspoll_sta_queue), "%d", 1); + PRINT_ONE(" tx_urgent_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_urgent_queue.qlen, "%d", 1); + PRINT_ONE(" tx_pending_sta_queue:", "%s", 1); + PRINT_ONE(" MGQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[MGNT_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" BKQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[BK_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" BEQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[BE_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" VIQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[VI_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" VOQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[VO_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" HIQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_pending_sta_queue[HIGH_QUEUE].qlen, "%-4d", 1); + PRINT_ONE(" pending_xmitbuf_queue: ", "%s", 0); + PRINT_ONE(priv->pshare->pending_xmitbuf_queue.qlen, "%d", 1); + PRINT_ONE(" MGQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_xmitbuf_waiting_queue[MGNT_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" BKQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_xmitbuf_waiting_queue[BK_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" BEQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_xmitbuf_waiting_queue[BE_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" VIQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_xmitbuf_waiting_queue[VI_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" VOQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_xmitbuf_waiting_queue[VO_QUEUE].qlen, "%-4d", 0); + PRINT_ONE(" HIQ: ", "%s", 0); + PRINT_ONE(priv->pshare->tx_xmitbuf_waiting_queue[HIGH_QUEUE].qlen, "%-4d", 1); +#ifdef CONFIG_SDIO_TX_INTERRUPT + { + u8 *free_tx_page = GET_HAL_INTF_DATA(priv)->SdioTxFIFOFreePage; + PRINT_ONE(" TxFIFOFreePage:", "%s", 1); + PRINT_ONE(" HIQ: ", "%s", 0); + PRINT_ONE(free_tx_page[HI_QUEUE_IDX], "%-4d", 0); + PRINT_ONE(" MIQ: ", "%s", 0); + PRINT_ONE(free_tx_page[MID_QUEUE_IDX], "%-4d", 0); + PRINT_ONE(" LOQ: ", "%s", 0); + PRINT_ONE(free_tx_page[LOW_QUEUE_IDX], "%-4d", 0); +#ifdef CONFIG_WLAN_HAL_8192EE + PRINT_ONE(" EXQ: ", "%s", 0); + PRINT_ONE(free_tx_page[EXTRA_QUEUE_IDX], "%-4d", 0); +#endif + PRINT_ONE(" PUBQ: ", "%s", 0); + PRINT_ONE(free_tx_page[PUBLIC_QUEUE_IDX], "%-4d", 1); + } +#endif // CONFIG_SDIO_TX_INTERRUPT + +#ifdef CONFIG_WLAN_HAL_8192EE + { + u16 oqtFreeSpace; + u8 *pFreeSpace; + + oqtFreeSpace = SdioLocalCmd52Read2Byte(priv, SDIO_REG_OQT_FREE_SPACE); +#ifdef _BIG_ENDIAN_ + oqtFreeSpace = cpu_to_le16(oqtFreeSpace); +#endif + pFreeSpace = (u8*) &oqtFreeSpace; + + PRINT_ONE(" OQT free space: [AC] ", "%s", 0); + PRINT_ONE(GET_HAL_INTF_DATA(priv)->SdioTxOQTFreeSpace[TXOQT_TYPE_AC], "%2d", 0); + PRINT_ONE(pFreeSpace[TXOQT_TYPE_AC], "/%2d", 0); + PRINT_ONE(" [NOAC] ", "%s", 0); + PRINT_ONE(GET_HAL_INTF_DATA(priv)->SdioTxOQTFreeSpace[TXOQT_TYPE_NOAC], "%2d", 0); + PRINT_ONE(pFreeSpace[TXOQT_TYPE_NOAC], "/%2d", 0); + PRINT_ONE(priv->pshare->nr_out_of_txoqt_space, " (wait:%d)", 1); + } +#else + PRINT_ONE(" OQT free space: ", "%s", 0); + PRINT_ONE(GET_HAL_INTF_DATA(priv)->SdioTxOQTFreeSpace, "%2d", 0); + PRINT_ONE(SdioLocalCmd52Read1Byte(priv, SDIO_REG_OQT_FREE_SPACE), "/%d", 0); + PRINT_ONE(priv->pshare->nr_out_of_txoqt_space, " (wait:%d)", 1); +#endif + + PRINT_ONE(" free_recv_queue: ", "%s", 0); + PRINT_ONE(priv->recvpriv.free_recv_queue.qlen, "%d", 0); + PRINT_ONE(NR_RECVFRAME, "/%d", 0); + PRINT_ONE(priv->recvpriv.nr_out_of_recvframe, " (fail:%d)", 1); + PRINT_ONE(" free_recv_buf_queue: ", "%s", 0); + PRINT_ONE(priv->recvpriv.free_recv_buf_queue.qlen, "%d", 0); + PRINT_ONE(NR_RECVBUFF, "/%d", 0); + PRINT_ONE(priv->recvpriv.nr_out_of_recvbuf, " (fail:%d", 0); + PRINT_ONE(priv->recvpriv.nr_out_of_recvbuf_mem, "/%d)", 1); + + PRINT_ONE(" recv_buf_pending_queue: ", "%s", 0); + PRINT_ONE(priv->recvpriv.recv_buf_pending_queue.qlen, "%d", 1); + + PRINT_ONE(" wake_event: ", "%s", 0); + PRINT_ONE(priv->pshare->xmit_wake | priv->pshare->cmd_wake, "%08lX", 1); + PRINT_ONE(" cmd_queue: ", "%s", 1); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(priv->pshare->cmd_queue.qlen, "%-4d", 0); + PRINT_ONE(" miss: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_cmd_miss, "%-4u", 0); + PRINT_ONE(" done: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_cmd, "%u", 1); + + PRINT_ONE(" rx_mgt_queue: ", "%s", 1); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(priv->pshare->rx_mgt_queue.qlen, "%-4d", 0); + PRINT_ONE(" miss: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_rx_mgt_cmd_miss, "%-4u", 0); + PRINT_ONE(" done: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_rx_mgt_cmd, "%u", 1); + + PRINT_ONE(" timer_evt_queue: ", "%s", 1); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(priv->pshare->timer_evt_queue.qlen, "%-4d", 0); + PRINT_ONE(" miss: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_timer_evt_miss, "%-4u", 0); + PRINT_ONE(" done: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_timer_evt, "%u", 1); +#ifdef __ECOS + PRINT_ONE(" iot_mode_enable:", "%s", 0); + PRINT_ONE(priv->pshare->iot_mode_enable, "%d", 1); + PRINT_ONE(" iot_mode_VO_exist:", "%s", 0); + PRINT_ONE(priv->pshare->iot_mode_VO_exist, "%d", 1); + PRINT_ONE(" iot_mode_VI_exist:", "%s", 0); + PRINT_ONE(priv->pshare->iot_mode_VI_exist, "%d", 1); + PRINT_ONE(" iot_mode_BE_exist:", "%s", 0); + PRINT_ONE(priv->pshare->iot_mode_BE_exist, "%d", 1); + PRINT_ONE(" iot_mode_BK_exist:", "%s", 0); + PRINT_ONE(priv->pshare->iot_mode_BK_exist, "%d", 1); +#ifdef TX_PKT_FREE_QUEUE + PRINT_SINGL_ARG(" skb_txdone_queue: ", info->skb_txdone_queue.qlen, "%d"); + PRINT_SINGL_ARG(" txdone_queue: ", info->txdone_queue.qlen, "%d"); + dump_free_txdone_queue(); +#endif +#endif + + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_sdio_dbginfo(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_sdio_dbginfo(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" pending_cmd: ", "%s", 0); + PRINT_ONE(priv->pshare->pending_cmd[0], "%08lX", 1); + PRINT_ONE(" sdio interrupt: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_interrupt, "%d", 1); + PRINT_ONE(" xmit_thread_run: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_xmit_thread_run, "%d", 1); + PRINT_ONE(" SdioTxIntStatus: ", "%s", 0); + PRINT_ONE(GET_HAL_INTF_DATA(priv)->SdioTxIntStatus, "%lu", 1); + PRINT_ONE(" need_sched_xmit: ", "%s", 0); + PRINT_ONE(priv->pshare->need_sched_xmit, "%08lX", 1); + PRINT_ONE(" low_traffic_xmit/_thd: ", "%s", 0); + PRINT_ONE(priv->pshare->low_traffic_xmit, "%08lX", 0); + PRINT_ONE(priv->pshare->rf_ft_var.low_traffic_xmit_thd, " /%d", 1); + PRINT_ONE(" xmitbuf_agg_num: ", "%s", 0); + PRINT_ONE(priv->pshare->xmitbuf_agg_num, "%d", 1); + PRINT_ONE(" xmitbuf_handled_in_thread/in_irq: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_xmitbuf_handled_in_thread, "%5d", 0); + PRINT_ONE(priv->pshare->nr_xmitbuf_handled_in_irq, "/%5d", 1); +#ifdef SDIO_STATISTICS + { + int i; + PRINT_ONE(" write port count/time", "%s", 1); + for (i = 0; i < MAX_XMITBUF_PKT; ++i) { + if (priv->pshare->writeport_avg_count[i]) { + PRINT_ONE(i+1, " [%2d]", 0); +#ifdef SDIO_STATISTICS_TIME + PRINT_ONE(priv->pshare->writeport_avg_count[i], "%4d", 0); + PRINT_ONE(priv->pshare->writeport_avg_time[i], "/%4luus", 1); +#else + PRINT_ONE(priv->pshare->writeport_avg_count[i], "%4d", 1); +#endif + } + } + } +#endif // SDIO_STATISTICS + + PRINT_ONE(" recvbuf_handled_in_irq: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_recvbuf_handled_in_irq, "%d", 1); + PRINT_ONE(" recvbuf_handled_in_tasklet: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_recvbuf_handled_in_tasklet, "%d", 1); + PRINT_ONE(" recvframe_in_recvbuf: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_recvframe_in_recvbuf, "%d", 1); +#ifdef CONFIG_1RCCA_RF_POWER_SAVING + PRINT_ONE(" 1rcca_ps_active: ", "%s", 0); + PRINT_ONE(priv->pshare->_1rcca_ps_active, "%d", 1); +#endif +#ifdef SDIO_AP_OFFLOAD + PRINT_ONE(" pwr_state/offload_ctrl: ", "%s", 0); + PRINT_ONE(priv->pshare->pwr_state, "%d", 0); + PRINT_ONE(priv->pshare->offload_function_ctrl, "/%d", 1); + PRINT_ONE(" offload_prohibited: ", "%s", 0); + PRINT_ONE(priv->pshare->offload_prohibited, "%lX", 1); + PRINT_ONE(" update_bcn_fail: ", "%s", 0); + PRINT_ONE(priv->pshare->nr_update_bcn_fail, "%d", 1); +#ifdef CONFIG_POWER_SAVE + PRINT_ONE(" ps_level: ", "%s", 0); + PRINT_ONE(priv->pmib->dot11OperationEntry.ps_level, "%d", 1); + PRINT_ONE(" ps_32k_en: ", "%s", 0); + PRINT_ONE(priv->pshare->ap_ps_handle.en_32k, "%d", 0); + PRINT_ONE(priv->pmib->dot11OperationEntry.ps_32k_en, "/%d", 0); + PRINT_ONE(priv->pshare->nr_leave_32k_fail, " (fail:%d)", 1); + PRINT_SINGL_ARG(" ps_timeout: ", priv->pmib->dot11OperationEntry.ps_timeout, "%d"); + PRINT_SINGL_ARG(" sleep_time: ", priv->pshare->ap_ps_handle.sleep_time, "%d"); +#endif +#endif +#ifdef CMD_THREAD_FUNC_DEBUG + PRINT_ONE(" cur_cmd_func: ", "%s", 0); + PRINT_ONE(priv->pshare->cur_cmd_func, "%p", 1); +#endif + + return pos; +} +#endif // CONFIG_SDIO_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef CONFIG_RTL_PROC_NEW +static int dump_one_sta_queinfo(struct seq_file *s, int num, struct stat_info *pstat) +#else +static int dump_one_sta_queinfo(int num, struct stat_info *pstat, char *buf, char **start, + off_t offset, int length, int *eof, void *data) +#endif +{ + int pos = 0; + + PRINT_ONE(num, " %d: stat_queinfo ", 0); + PRINT_ONE(pstat->aid, "[aid:%d]", 1); + PRINT_ONE(" pspoll_list: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->pspoll_list), "%d", 1); + PRINT_ONE(" tx_queue:", "%s", 1); + if (tx_servq_len(&pstat->tx_queue[MGNT_QUEUE])) { + PRINT_ONE(" [MGQ] tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->tx_queue[MGNT_QUEUE].tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&pstat->tx_queue[MGNT_QUEUE]), "%d", 1); + } + if (tx_servq_len(&pstat->tx_queue[BK_QUEUE])) { + PRINT_ONE(" [BKQ] tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->tx_queue[BK_QUEUE].tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&pstat->tx_queue[BK_QUEUE]), "%d", 1); + } + if (tx_servq_len(&pstat->tx_queue[BE_QUEUE])) { + PRINT_ONE(" [BEQ] tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->tx_queue[BE_QUEUE].tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&pstat->tx_queue[BE_QUEUE]), "%d", 1); + } + if (tx_servq_len(&pstat->tx_queue[VI_QUEUE])) { + PRINT_ONE(" [VIQ] tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->tx_queue[VI_QUEUE].tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&pstat->tx_queue[VI_QUEUE]), "%d", 1); + } + if (tx_servq_len(&pstat->tx_queue[VO_QUEUE])) { + PRINT_ONE(" [VOQ] tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->tx_queue[VO_QUEUE].tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(tx_servq_len(&pstat->tx_queue[VO_QUEUE]), "%d", 1); + } +#ifdef CONFIG_TCP_ACK_TXAGG + PRINT_ONE(" tcpack_queue:", "%s", 1); + if (pstat->tcpack_queue[BK_QUEUE].xframe_queue.qlen) { + PRINT_ONE(" [BKQ] tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->tcpack_queue[BK_QUEUE].tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(pstat->tcpack_queue[BK_QUEUE].xframe_queue.qlen, "%d", 1); + } + if (pstat->tcpack_queue[BE_QUEUE].xframe_queue.qlen) { + PRINT_ONE(" [BEQ] tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->tcpack_queue[BE_QUEUE].tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(pstat->tcpack_queue[BE_QUEUE].xframe_queue.qlen, "%d", 1); + } + if (pstat->tcpack_queue[VI_QUEUE].xframe_queue.qlen) { + PRINT_ONE(" [VIQ] tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->tcpack_queue[VI_QUEUE].tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(pstat->tcpack_queue[VI_QUEUE].xframe_queue.qlen, "%d", 1); + } + if (pstat->tcpack_queue[VO_QUEUE].xframe_queue.qlen) { + PRINT_ONE(" [VOQ] tx_pending: ", "%s", 0); + PRINT_ONE(!rtw_is_list_empty(&pstat->tcpack_queue[VO_QUEUE].tx_pending), "%d", 0); + PRINT_ONE(" qlen: ", "%s", 0); + PRINT_ONE(pstat->tcpack_queue[VO_QUEUE].xframe_queue.qlen, "%d", 1); + } +#endif // CONFIG_TCP_ACK_TXAGG + + PRINT_ONE("", "%s", 1); + + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_sta_queinfo(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_sta_queinfo(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int len = 0; +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + off_t begin = 0; + off_t pos = 0; + int size; +#endif + int num=1; + struct list_head *phead, *plist; + struct stat_info *pstat; + unsigned long flags=0; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK_ASOC_LIST(flags); + +#ifdef __ECOS + ecos_pr_fun("-- STA que info table --\n"); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, "-- STA que info table --\n"); +#else + size = sprintf(buf, "-- STA que info table --\n"); +#endif + CHECK_LEN; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + goto _ret; + + phead = &priv->asoc_list; + plist = phead->next; + + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + +#ifdef CONFIG_RTL_PROC_NEW + dump_one_sta_queinfo(s, num++, pstat); +#else + size = dump_one_sta_queinfo(num++, pstat, buf+len, start, offset, length, + eof, data); +#endif + CHECK_LEN; + } + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *eof = 1; +#endif + +_ret: + SMP_UNLOCK_ASOC_LIST(flags); + RESTORE_INT(flags); + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ +#endif + return len; +} +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_buf_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_buf_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" buf info...", "%s", 1); + PRINT_ONE(" hdr poll:", "%s", 1); + PRINT_ONE(" head: ", "%s", 0); + PRINT_ONE((unsigned long)&priv->pshare->wlan_hdrlist, "0x%.8lx", 0); + PRINT_ONE(" count: ", "%s", 0); + PRINT_ONE(priv->pshare->pwlan_hdr_poll->count, "%d", 1); + + PRINT_ONE(" hdrllc poll:", "%s", 1); + PRINT_ONE(" head: ", "%s", 0); + PRINT_ONE((unsigned long)&priv->pshare->wlanllc_hdrlist, "0x%.8lx", 0); + PRINT_ONE(" count: ", "%s", 0); + PRINT_ONE(priv->pshare->pwlanllc_hdr_poll->count, "%d", 1); + + PRINT_ONE(" mgmtbuf poll:", "%s", 1); + PRINT_ONE(" head: ", "%s", 0); + PRINT_ONE((unsigned long)&priv->pshare->wlanbuf_list, "0x%.8lx", 0); + PRINT_ONE(" count: ", "%s", 0); + PRINT_ONE(priv->pshare->pwlanbuf_poll->count, "%d", 1); + + PRINT_ONE(" icv poll:", "%s", 1); + PRINT_ONE(" head: ", "%s", 0); + PRINT_ONE((unsigned long)&priv->pshare->wlanicv_list, "0x%.8lx", 0); + PRINT_ONE(" count: ", "%s", 0); + PRINT_ONE(priv->pshare->pwlanicv_poll->count, "%d", 1); + + PRINT_ONE(" mic poll:", "%s", 1); + PRINT_ONE(" head: ", "%s", 0); + PRINT_ONE((unsigned long)&priv->pshare->wlanmic_list, "0x%.8lx", 0); + PRINT_ONE(" count: ", "%s", 0); + PRINT_ONE(priv->pshare->pwlanmic_poll->count, "%d", 1); + + return pos; +} + + +#ifdef ENABLE_RTL_SKB_STATS +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_skb_info(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_skb_info(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" skb counter...", "%s", 1); + PRINT_SINGL_ARG(" skb_tx_cnt: ", rtl_atomic_read(&priv->rtl_tx_skb_cnt) , "%d"); + PRINT_SINGL_ARG(" skb_rx_cnt: ", rtl_atomic_read(&priv->rtl_rx_skb_cnt) , "%d"); + + return pos; +} +#endif + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_11n(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_11n(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" dot11nConfigEntry...", "%s", 1); + + PRINT_SINGL_ARG(" supportedmcs: ", get_supported_mcs(priv), "%08x"); + PRINT_SINGL_ARG(" basicmcs: ", priv->pmib->dot11nConfigEntry.dot11nBasicMCS, "%08x"); + PRINT_SINGL_ARG(" use40M: ", priv->pmib->dot11nConfigEntry.dot11nUse40M, "%d"); + PRINT_SINGL_ARG(" currBW: ", (!priv->pshare->is_40m_bw) ? 20 :(priv->pshare->is_40m_bw*40), "%dM"); + + PRINT_ONE(" 2ndchoffset: ", "%s", 0); + switch (priv->pshare->offset_2nd_chan) { + case HT_2NDCH_OFFSET_BELOW: + PRINT_ONE("below", "%s", 1); + break; + case HT_2NDCH_OFFSET_ABOVE: + PRINT_ONE("above", "%s", 1); + break; + default: + PRINT_ONE("dontcare", "%s", 1); + break; + } + + PRINT_SINGL_ARG(" shortGI20M: ", priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M, "%d"); + PRINT_SINGL_ARG(" shortGI40M: ", priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M, "%d"); + PRINT_SINGL_ARG(" shortGI80M: ", priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M, "%d"); + PRINT_SINGL_ARG(" stbc: ", priv->pmib->dot11nConfigEntry.dot11nSTBC, "%d"); + PRINT_SINGL_ARG(" ldpc: ", priv->pmib->dot11nConfigEntry.dot11nLDPC, "%d"); + PRINT_SINGL_ARG(" ampdu: ", priv->pmib->dot11nConfigEntry.dot11nAMPDU, "%d"); + PRINT_SINGL_ARG(" amsdu: ", priv->pmib->dot11nConfigEntry.dot11nAMSDU, "%d"); + PRINT_SINGL_ARG(" ampduSndSz: ", priv->pmib->dot11nConfigEntry.dot11nAMPDUSendSz, "%d"); + PRINT_SINGL_ARG(" amsduMax: ", priv->pmib->dot11nConfigEntry.dot11nAMSDURecvMax, "%d"); + PRINT_SINGL_ARG(" amsduTimeout: ", priv->pmib->dot11nConfigEntry.dot11nAMSDUSendTimeout, "%d"); + PRINT_SINGL_ARG(" amsduNum: ", priv->pmib->dot11nConfigEntry.dot11nAMSDUSendNum, "%d"); + PRINT_SINGL_ARG(" lgyEncRstrct: ", priv->pmib->dot11nConfigEntry.dot11nLgyEncRstrct, "%d"); +#ifdef WIFI_11N_2040_COEXIST + PRINT_SINGL_ARG(" coexist: ", priv->pmib->dot11nConfigEntry.dot11nCoexist, "%d"); + if (priv->pmib->dot11nConfigEntry.dot11nCoexist) { +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) + PRINT_SINGL_ARG(" coexist_connection: ", priv->coexist_connection, "%d"); + + if ((OPMODE & WIFI_AP_STATE) || + ((OPMODE & WIFI_STATION_STATE) && priv->coexist_connection)) +#endif + PRINT_SINGL_ARG(" bg_ap_timeout: ", priv->bg_ap_timeout, "%d"); +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_STATION_STATE) && priv->coexist_connection) { + if (priv->bg_ap_timeout) + PRINT_ARRAY_ARG(" bg_ap_timeout_ch: ", priv->bg_ap_timeout_ch, "%d ", 14); + + PRINT_SINGL_ARG(" intolerant_timeout: ", priv->intolerant_timeout, "%d"); + } else +#endif + if (OPMODE & WIFI_AP_STATE) { + PRINT_BITMAP_ARG(" force_20_sta", priv->force_20_sta); + PRINT_BITMAP_ARG(" switch_20_sta", priv->switch_20_sta); + PRINT_SINGL_ARG(" bg_ap_rssi_chk_th: ", priv->pmib->dot11nConfigEntry.dot11nBGAPRssiChkTh, "%d"); + } + } +#endif + + PRINT_SINGL_ARG(" txnoack: ", priv->pmib->dot11nConfigEntry.dot11nTxNoAck, "%d"); + + if (priv->ht_cap_len) { + unsigned char *pbuf = (unsigned char *)&priv->ht_cap_buf; + PRINT_ARRAY_ARG(" ht_cap: ", pbuf, "%02x", priv->ht_cap_len); + } + else { + PRINT_ONE(" ht_cap: none", "%s", 1); + } + if (priv->ht_ie_len) { + unsigned char *pbuf = (unsigned char *)&priv->ht_ie_buf; + PRINT_ARRAY_ARG(" ht_ie: ", pbuf, "%02x", priv->ht_ie_len); + } + else { + PRINT_ONE(" ht_ie: none", "%s", 1); + } + + PRINT_SINGL_ARG(" legacy_obss_to: ", priv->ht_legacy_obss_to, "%d"); + PRINT_SINGL_ARG(" nomember_legacy_sta_to: ", priv->ht_nomember_legacy_sta_to, "%d"); + PRINT_SINGL_ARG(" legacy_sta_num: ", priv->ht_legacy_sta_num, "%d"); + PRINT_SINGL_ARG(" 11nProtection: ", priv->ht_protection, "%d"); +// PRINT_BITMAP_ARG(" has_2r_sta", priv->pshare->has_2r_sta); + + return pos; +} + + +#ifdef CONFIG_RTL_92C_SUPPORT //#ifndef CONFIG_RTL_92D_SUPPORT +#ifndef __ECOS +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_phypara_file_read(struct seq_file *s, void *data) +{ + return 0; +} +#else +static int rtl8192cd_proc_phypara_file_read(char *buf, char **start, off_t offset, + int length, int *eof, void *data) + +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int len=0; + + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)) { + if (priv->phypara_file_end <= (priv->phypara_file_start + offset + length)) { + *eof = 1; + len = priv->phypara_file_end - priv->phypara_file_start - offset; + } + else + len = length; + + memcpy(buf, &priv->phypara_file_start[offset], len); + *start = buf; + } + return len; +} +#endif + + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +static int rtl8192cd_proc_phypara_file_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + char tmp[64]; + + if (count < 2) + return -EFAULT; + + if (count > sizeof(tmp)) + return -EINVAL; + + if (buffer && !copy_from_user(tmp, buffer, count)) { + tmp[count-1] = '\0'; + + +#ifdef TESTCHIP_SUPPORT + if (!strcmp(tmp, "AGC_TAB.txt")) { + priv->phypara_file_start = data_AGC_TAB_start; + priv->phypara_file_end = data_AGC_TAB_end; + } + else if (!strcmp(tmp, "PHY_REG_1T.txt")) { + priv->phypara_file_start = data_PHY_REG_1T_start; + priv->phypara_file_end = data_PHY_REG_1T_end; + } + else if (!strcmp(tmp, "PHY_REG_2T.txt")) { + priv->phypara_file_start = data_PHY_REG_2T_start; + priv->phypara_file_end = data_PHY_REG_2T_end; + } + else if (!strcmp(tmp, "radio_a_1T.txt")) { + priv->phypara_file_start = data_radio_a_1T_start; + priv->phypara_file_end = data_radio_a_1T_end; + } + else if (!strcmp(tmp, "radio_a_2T.txt")) { + priv->phypara_file_start = data_radio_a_2T_start; + priv->phypara_file_end = data_radio_a_2T_end; + } + else if (!strcmp(tmp, "radio_b_2T.txt")) { + priv->phypara_file_start = data_radio_b_2T_start; + priv->phypara_file_end = data_radio_b_2T_end; + } + else +#endif + + if (!strcmp(tmp, "AGC_TAB_n.txt")) { + priv->phypara_file_start = data_AGC_TAB_n_92C_start; + priv->phypara_file_end = data_AGC_TAB_n_92C_end; + } + else if (!strcmp(tmp, "PHY_REG_1T_n.txt")) { + priv->phypara_file_start = data_PHY_REG_1T_n_start; + priv->phypara_file_end = data_PHY_REG_1T_n_end; + } + else if (!strcmp(tmp, "PHY_REG_2T_n.txt")) { + priv->phypara_file_start = data_PHY_REG_2T_n_start; + priv->phypara_file_end = data_PHY_REG_2T_n_end; + } + else if (!strcmp(tmp, "radio_a_2T_n.txt")) { + priv->phypara_file_start = data_radio_a_2T_n_start; + priv->phypara_file_end = data_radio_a_2T_n_end; + } + else if (!strcmp(tmp, "radio_b_2T_n.txt")) { + priv->phypara_file_start = data_radio_b_2T_n_start; + priv->phypara_file_end = data_radio_b_2T_n_end; + } + else if (!strcmp(tmp, "radio_a_1T_n.txt")) { + priv->phypara_file_start = data_radio_a_1T_n_start; + priv->phypara_file_end = data_radio_a_1T_n_end; + } + else if (!strcmp(tmp, "PHY_REG_PG.txt")) { + priv->phypara_file_start = data_PHY_REG_PG_92C_start; + priv->phypara_file_end = data_PHY_REG_PG_92C_end; + } + else if (!strcmp(tmp, "MACPHY_REG_92C.txt")) { + priv->phypara_file_start = data_MACPHY_REG_92C_start;//data_MACPHY_REG_92C_start + priv->phypara_file_end = data_MACPHY_REG_92C_end; + } + else if (!strcmp(tmp, "PHY_REG_MP_n.txt")) { + priv->phypara_file_start = data_PHY_REG_MP_n_92C_start; + priv->phypara_file_end = data_PHY_REG_MP_n_92C_end; + } +#ifdef HIGH_POWER_EXT_PA + else if (!strcmp(tmp, "AGC_TAB_n_hp.txt")) { + priv->phypara_file_start = data_AGC_TAB_n_hp_start; + priv->phypara_file_end = data_AGC_TAB_n_hp_end; + } + + else if (!strcmp(tmp, "PHY_REG_2T_n_hp.txt")) { + priv->phypara_file_start = data_PHY_REG_2T_n_hp_start; + priv->phypara_file_end = data_PHY_REG_2T_n_hp_end; + } +#endif +#ifdef HIGH_POWER_EXT_PA + else if (!strcmp(tmp, "radio_a_2T_n_lna.txt")) { + priv->phypara_file_start = data_radio_a_2T_n_lna_start; + priv->phypara_file_end = data_radio_a_2T_n_lna_end; + } + else if (!strcmp(tmp, "radio_b_2T_n_lna.txt")) { + priv->phypara_file_start = data_radio_b_2T_n_lna_start; + priv->phypara_file_end = data_radio_b_2T_n_lna_end; + } +#endif +#ifdef HIGH_POWER_EXT_PA + else if (!strcmp(tmp, "radio_a_2T_n_hp.txt")) { + priv->phypara_file_start = data_radio_a_2T_n_hp_start; + priv->phypara_file_end = data_radio_a_2T_n_hp_end; + } + else if (!strcmp(tmp, "radio_b_2T_n_hp.txt")) { + priv->phypara_file_start = data_radio_b_2T_n_hp_start; + priv->phypara_file_end = data_radio_b_2T_n_hp_end; + } + else if (!strcmp(tmp, "PHY_REG_PG_hp.txt")) { + priv->phypara_file_start = data_PHY_REG_PG_hp_start; + priv->phypara_file_end = data_PHY_REG_PG_hp_end; + } +#endif + else { + panic_printk("No file of \"%s\"\n", tmp); + panic_printk("PHY parameter file name list:\n" +#ifdef TESTCHIP_SUPPORT + "\tAGC_TAB.txt\n" + "\tPHY_REG_1T.txt\n" + "\tPHY_REG_2T.txt\n" + "\tradio_a_1T.txt\n" + "\tradio_a_2T.txt\n" + "\tradio_b_2T.txt\n" +#endif + "\tAGC_TAB_n_92C.txt\n" + "\tPHY_REG_1T_n.txt\n" + "\tPHY_REG_2T_n.txt\n" + "\tradio_a_2T_n.txt\n" + "\tradio_b_2T_n.txt\n" + "\tradio_a_1T_n.txt\n" + "\tPHY_REG_PG.txt\n" + "\tMACPHY_REG_92C.txt\n" + "\tPHY_REG_MP_n.txt\n" + "\tAGC_TAB_n_hp.txt\n" + "\tPHY_REG_2T_n_hp.txt\n" + "\tradio_a_2T_n_lna.txt\n" + "\tradio_b_2T_n_lna.txt\n" +#ifdef HIGH_POWER_EXT_PA + "\tradio_a_2T_n_hp.txt\n" + "\tradio_b_2T_n_hp.txt\n" + "\tPHY_REG_PG_hp.txt\n" +#endif + ); + return count; + } + } + + panic_printk("Ready to dump \"%s\"\n", tmp); + return count; +} +#endif +#endif + + +#ifdef AUTO_TEST_SUPPORT +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_SSR_read(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_SSR_read(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int len = 0; + off_t begin = 0; + off_t pos = 0, base; + int size; + + int i1; + unsigned char tmp[6]; + + //wait SiteSurvey completed + if(priv->ss_req_ongoing) { + PRINT_ONE("waitting", "%s", 1); + len = pos; + }else{ + PRINT_ONE(" SiteSurvey result : ", "%s", 1); + PRINT_ONE(" ====================", "%s", 1); + if(priv->site_survey->count_backup==0){ + PRINT_ONE("none", "%s", 1); + len = pos; + }else{ + len = pos; + + for(i1=0; i1site_survey->count_backup ;i1++){ + base = pos; + memcpy(tmp,priv->site_survey->bss_backup[i1].bssid,MACADDRLEN); + /* + panic_printk("Mac=%02X%02X%02X:%02X%02X%02X ;Channel=%02d ;SSID:%s \n", + tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5] + ,priv->site_survey->bss_backup[i1].channel + ,priv->site_survey->bss_backup[i1].ssid + ); + */ + PRINT_ARRAY_ARG(" HwAddr: ", tmp, "%02x", MACADDRLEN); + PRINT_SINGL_ARG(" Channel: ", priv->site_survey->bss_backup[i1].channel, "%d"); + PRINT_SINGL_ARG(" SSID: ", priv->site_survey->bss_backup[i1].ssid, "%s"); + PRINT_SINGL_ARG(" Type: ", ((priv->site_survey->bss_backup[i1].bsstype == 16) ? "AP" : "Ad-Hoc"), "%s"); + //PRINT_SINGL_ARG(" Type: ", priv->site_survey->bss_backup[i1].bsstype, "%d"); + PRINT_ONE(" ====================", "%s", 1); + + size = pos - base; + CHECK_LEN; + pos = len; + } + } + } +#ifdef CONFIG_RTL_PROC_NEW + return 0; +#else + *eof = 1; + +_ret: + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ + + return len; +#endif +} +#endif +#ifdef CLIENT_MODE +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_up_read(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_up_read(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int len = 0; +#ifdef __ECOS + ecos_pr_fun("%d\n",priv->up_flag); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, "%d\n",priv->up_flag); +#else + len=sprintf(buf,"%d",priv->up_flag); +#endif + return len; +} + +#ifdef __ECOS +void rtl8192cd_proc_up_write(char *tmp, void *data) +#else +static int rtl8192cd_proc_up_write(struct file *file, const char *buffer, + unsigned long count, void *data) +#endif +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); +#ifdef __KERNEL__ + char tmp[4]; +#endif + +#ifdef __ECOS + if(0 == (tmp[0]-'0')) + priv->up_flag = 0; +#else + if (buffer && !copy_from_user(tmp, buffer, 4)) { + if(0 == (tmp[0]-'0')) + priv->up_flag = 0; + } + return count; +#endif +} +#endif + +#ifdef CONFIG_RTL_WLAN_STATUS +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_up_event_read(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_up_event_read(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + int len = 0; + +#ifdef __ECOS + ecos_pr_fun("%d\n",priv->wlan_status_flag); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, "%d\n",priv->wlan_status_flag); +#else + len=sprintf(buf,"%d", priv->wlan_status_flag); +#endif + return len; +} + +#ifdef __ECOS +static int rtl8192cd_proc_up_event_write(char *tmp, void *data) +#else +static int rtl8192cd_proc_up_event_write(struct file *file, const char *buffer, + unsigned long count, void *data) +#endif +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); +#ifdef __KERNEL__ + char tmp[4]; +#endif + +#ifdef __ECOS + priv->wlan_status_flag = (tmp[0]-'0'); + return 0; +#else + if (buffer && !copy_from_user(tmp, buffer, 4)) { + priv->wlan_status_flag=tmp[0]-'0'; + } + return count; +#endif +} +#endif + +#ifdef CONFIG_RTK_VLAN_SUPPORT +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_vlan_read(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_vlan_read(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + PRINT_ONE(" vlan setting...", "%s", 1); + PRINT_SINGL_ARG(" global_vlan: ", priv->pmib->vlan.global_vlan, "%d"); + PRINT_SINGL_ARG(" is_lan: ", priv->pmib->vlan.is_lan, "%d"); + PRINT_SINGL_ARG(" vlan_enable: ", priv->pmib->vlan.vlan_enable, "%d"); + PRINT_SINGL_ARG(" vlan_tag: ", priv->pmib->vlan.vlan_tag, "%d"); + PRINT_SINGL_ARG(" vlan_id: ", priv->pmib->vlan.vlan_id, "%d"); + PRINT_SINGL_ARG(" vlan_pri: ", priv->pmib->vlan.vlan_pri, "%d"); + PRINT_SINGL_ARG(" vlan_cfi: ", priv->pmib->vlan.vlan_cfi, "%d"); +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + PRINT_SINGL_ARG(" vlan_forwarding_rule: ", priv->pmib->vlan.forwarding_rule, "%d"); +#endif + + return pos; +} + + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +static int rtl8192cd_proc_vlan_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + #ifdef CONFIG_RTL_PROC_NEW + struct net_device *dev = PDE_DATA(file_inode(file)); + #else + struct net_device *dev = (struct net_device *)data; + #endif + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + char tmp[128]; + + if (count < 2) + return -EFAULT; + if (buffer && !copy_from_user(tmp, buffer, 128)) { +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + int num = sscanf(tmp, "%d %d %d %d %d %d %d %d", +#else + int num = sscanf(tmp, "%d %d %d %d %d %d %d", +#endif + &priv->pmib->vlan.global_vlan, &priv->pmib->vlan.is_lan, + &priv->pmib->vlan.vlan_enable, &priv->pmib->vlan.vlan_tag, + &priv->pmib->vlan.vlan_id, &priv->pmib->vlan.vlan_pri, + &priv->pmib->vlan.vlan_cfi +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + , &priv->pmib->vlan.forwarding_rule +#endif + ); + +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + if (num != 8) +#else + if (num != 7) +#endif + { + panic_printk("invalid vlan parameter!\n"); + } + } + +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + rtl_add_vlan_info((struct vlan_info *)&priv->pmib->vlan, dev); +#endif + + return count; +} +#endif // CONFIG_RTK_VLAN_SUPPORT + + +#ifdef SUPPORT_MULTI_PROFILE +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_ap_profile(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_ap_profile(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + int pos = 0, i; + unsigned char tmpbuf[100]; + + PRINT_ONE(" Client Profile...", "%s", 1); + PRINT_SINGL_ARG(" enable_profile: ", priv->pmib->ap_profile.enable_profile, "%d"); + PRINT_SINGL_ARG(" profile_num: ", priv->pmib->ap_profile.profile_num, "%d"); + PRINT_SINGL_ARG(" in_use_profile: ", ((priv->profile_idx == 0) ? (priv->pmib->ap_profile.profile_num-1) : (priv->profile_idx-1)), "%d"); + + for (i=0; ipmib->ap_profile.profile_num && ipmib->ap_profile.profile[i].ssid, "%s"); + PRINT_SINGL_ARG(" encryption: ", priv->pmib->ap_profile.profile[i].encryption, "%d"); + PRINT_SINGL_ARG(" auth_type: ", priv->pmib->ap_profile.profile[i].auth_type, "%d"); + if (priv->pmib->ap_profile.profile[i].encryption == 1 || priv->pmib->ap_profile.profile[i].encryption == 2) { + PRINT_SINGL_ARG(" wep_default_key: ", priv->pmib->ap_profile.profile[i].wep_default_key, "%d"); + if (priv->pmib->ap_profile.profile[i].encryption == 1) { + PRINT_ARRAY_ARG(" wep_key1: ", priv->pmib->ap_profile.profile[i].wep_key1, "%02x", 5); + PRINT_ARRAY_ARG(" wep_key2: ", priv->pmib->ap_profile.profile[i].wep_key2, "%02x", 5); + PRINT_ARRAY_ARG(" wep_key3: ", priv->pmib->ap_profile.profile[i].wep_key3, "%02x", 5); + PRINT_ARRAY_ARG(" wep_key4: ", priv->pmib->ap_profile.profile[i].wep_key4, "%02x", 5); + } + else { + PRINT_ARRAY_ARG(" wep_key1: ", priv->pmib->ap_profile.profile[i].wep_key1, "%02x", 13); + PRINT_ARRAY_ARG(" wep_key2: ", priv->pmib->ap_profile.profile[i].wep_key2, "%02x", 13); + PRINT_ARRAY_ARG(" wep_key3: ", priv->pmib->ap_profile.profile[i].wep_key3, "%02x", 13); + PRINT_ARRAY_ARG(" wep_key4: ", priv->pmib->ap_profile.profile[i].wep_key4, "%02x", 13); + } + } + else if (priv->pmib->ap_profile.profile[i].encryption == 3 || priv->pmib->ap_profile.profile[i].encryption == 4) { + PRINT_SINGL_ARG(" wpa_cipher: ", priv->pmib->ap_profile.profile[i].wpa_cipher, "%d"); + PRINT_SINGL_ARG(" wpa_psk: ", priv->pmib->ap_profile.profile[i].wpa_psk, "%s"); +#ifdef CONFIG_IEEE80211W_CLI + PRINT_SINGL_ARG(" bss_PMF: ", priv->pmib->ap_profile.profile[i].bss_PMF, "%d"); +#endif + } + } + return pos; +} +#endif // SUPPORT_MULTI_PROFILE + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_misc(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_misc(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + int pos = 0; + + PRINT_ONE(" miscEntry...", "%s", 1); + + PRINT_SINGL_ARG(" show_hidden_bss: ", priv->pmib->miscEntry.show_hidden_bss, "%d"); + PRINT_SINGL_ARG(" ack_timeout: ", (unsigned char)priv->pmib->miscEntry.ack_timeout, "%d"); + PRINT_ARRAY_ARG(" private_ie: ", priv->pmib->miscEntry.private_ie, "%02x", priv->pmib->miscEntry.private_ie_len); + PRINT_SINGL_ARG(" rxInt: ", priv->pmib->miscEntry.rxInt_thrd, "%d"); +#ifdef DRVMAC_LB + PRINT_SINGL_ARG(" dmlb: ", priv->pmib->miscEntry.drvmac_lb, "%d"); + PRINT_ARRAY_ARG(" lb_da: ", priv->pmib->miscEntry.lb_da, "%02x", MACADDRLEN); + PRINT_SINGL_ARG(" lb_tps: ", priv->pmib->miscEntry.lb_tps, "%d"); +#endif + PRINT_SINGL_ARG(" groupID: ", priv->pmib->miscEntry.groupID, "%d"); + PRINT_SINGL_ARG(" rc_enable: ", priv->pmib->reorderCtrlEntry.ReorderCtrlEnable, "%d"); + PRINT_SINGL_ARG(" rc_winsz: ", priv->pmib->reorderCtrlEntry.ReorderCtrlWinSz, "%d"); + PRINT_SINGL_ARG(" rc_timeout: ", priv->pmib->reorderCtrlEntry.ReorderCtrlTimeout, "%d"); + PRINT_SINGL_ARG(" vap_enable: ", priv->pmib->miscEntry.vap_enable, "%d"); +#ifdef RESERVE_TXDESC_FOR_EACH_IF + PRINT_SINGL_ARG(" rsv_txdesc: ", GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc, "%d"); +#endif +#ifdef USE_TXQUEUE + PRINT_SINGL_ARG(" use_txq: ", GET_ROOT(priv)->pmib->miscEntry.use_txq, "%d"); +#endif + PRINT_SINGL_ARG(" func_off: ", priv->pmib->miscEntry.func_off, "%d"); + +#ifdef AUTO_CHANNEL_TIMEOUT + PRINT_SINGL_ARG(" autoch_timeout: ", priv->pmib->miscEntry.autoch_timeout, "%d"); +#endif + +#ifdef TX_EARLY_MODE + PRINT_SINGL_ARG(" em_waitq_on: ", GET_ROOT(priv)->pshare->em_waitq_on, "%d"); +#endif +#ifdef SUPPORT_MONITOR + PRINT_SINGL_ARG(" chan_switch_time: ", priv->pmib->miscEntry.chan_switch_time, "%d"); +#endif +#if defined(WIFI_11N_2040_COEXIST_EXT) + PRINT_BITMAP_ARG(" 40M map", priv->pshare->_40m_staMap); +#endif +#ifdef CONFIG_WLAN_HAL + PRINT_SINGL_ARG(" RxTag mismatch: ", priv->pshare->RxTagMismatchCount, "%d"); + PRINT_SINGL_ARG(" H2C full ctr: ", priv->pshare->h2c_box_full, "%d"); +#endif + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + PRINT_SINGL_ARG(" False alarm: ", ODMPTR->FalseAlmCnt.Cnt_all, "%d"); + PRINT_SINGL_ARG(" CCA: ", ODMPTR->FalseAlmCnt.Cnt_CCA_all, "%d"); + } +#endif +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + PRINT_SINGL_ARG(" False alarm: ", priv->pshare->FA_total_cnt, "%d"); + PRINT_SINGL_ARG(" CCA: ", priv->pshare->CCA_total_cnt, "%d"); + } +#endif + + + return pos; +} + + +#ifdef WIFI_SIMPLE_CONFIG +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_wsc(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_wsc(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" wscEntry...", "%s", 1); + PRINT_SINGL_ARG(" wsc_enable: ", priv->pmib->wscEntry.wsc_enable, "%d"); + PRINT_ARRAY_ARG(" beacon_ie: ", + priv->pmib->wscEntry.beacon_ie, "%02x", priv->pmib->wscEntry.beacon_ielen); + PRINT_SINGL_ARG(" beacon_ielen: ", priv->pmib->wscEntry.beacon_ielen, "%d"); + PRINT_ARRAY_ARG(" probe_rsp_ie: ", + priv->pmib->wscEntry.probe_rsp_ie, "%02x", priv->pmib->wscEntry.probe_rsp_ielen); + PRINT_SINGL_ARG(" probe_rsp_ielen: ", priv->pmib->wscEntry.probe_rsp_ielen, "%d"); + PRINT_ARRAY_ARG(" probe_req_ie: ", + priv->pmib->wscEntry.probe_req_ie, "%02x", priv->pmib->wscEntry.probe_req_ielen); + PRINT_SINGL_ARG(" probe_req_ielen: ", priv->pmib->wscEntry.probe_req_ielen, "%d"); + PRINT_ARRAY_ARG(" assoc_ie: ", + priv->pmib->wscEntry.assoc_ie, "%02x", priv->pmib->wscEntry.assoc_ielen); + PRINT_SINGL_ARG(" assoc_ielen: ", priv->pmib->wscEntry.assoc_ielen, "%d"); + + return pos; +} +#endif + +#ifdef WLANHAL_MACDM + +#if 1 +#define MACDM_MAX_PROC_ARG_NUM 7 +int rtl8192cd_proc_macdm_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + char tmp[60], command[8], action[10]; + unsigned int num; + unsigned int mode_sel, state_sel, rssi_idx, threshold, state_idx, reg_idx, reg_offset, reg_value; + PHAL_DATA_TYPE pHalData = _GET_HAL_DATA(priv); + + if (buffer && !copy_from_user(tmp, buffer, 32)) { + num = sscanf(tmp, "%s %s", command, action); + + if (num == 0) { + panic_printk("argument num: 0 (invalid)\n"); + return num; + } + else if (num > MACDM_MAX_PROC_ARG_NUM) { + panic_printk("argument num: %d (invalid)\n", num); + return num; + } + } + + panic_printk("Command: [%s], action: [%s]\n", command, action); + + if (!memcmp(command, "config", 6)) { + if (!memcmp(action, "mode", 4)) { + num = sscanf(tmp, "%s %s %u", command, action, &mode_sel); + + pHalData->MACDM_Mode_Sel = mode_sel; + + if (num != 3) { + panic_printk("argument num:%d (invalid, should be 3)\n", num); + } + } + else if (!memcmp(action, "thrs", 4)) { + num = sscanf(tmp, "%s %s %u %u %u", command, action, &state_sel, &rssi_idx, &threshold); + + pHalData->MACDM_stateThrs[state_sel][rssi_idx] = threshold; + + if (num != 5) { + panic_printk("argument num:%d (invalid, should be 5)\n", num); + } + } + else if (!memcmp(action, "table", 5)) { + num = sscanf(tmp, "%s %s %u %u %u %x %x", command, action, &state_idx, &rssi_idx, ®_idx, ®_offset, ®_value); + + pHalData->MACDM_Table[state_idx][rssi_idx][reg_idx].offset = reg_offset; + pHalData->MACDM_Table[state_idx][rssi_idx][reg_idx].value = reg_value; + + if (num != MACDM_MAX_PROC_ARG_NUM) { + panic_printk("argument num:%d (invalid, should be %d)\n", num, MACDM_MAX_PROC_ARG_NUM); + } + } + else if (!memcmp(action, "help", 4)) { + panic_printk("Command example:\n"); + panic_printk(" config mode [mode_sel(0~3)]\n"); + panic_printk(" config thrs [state_sel(0~3)] [rssi_idx(0~2)] [threshold(dec)]\n"); + panic_printk(" config table [state_idx(0~2)] [rssi_idx(0~2)] [reg_idx(0~29)] [reg_offset(hex)] [reg_value(hex)]\n"); + } + else { + panic_printk("action code: %s (invalid, should be mode/thrs/table/help)\n", action); + } + } + else { + panic_printk("Command not supported!, please type 'config help'\n"); + } + + return count; +} +#endif + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_macdm(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_macdm(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + PHAL_DATA_TYPE pHalData = _GET_HAL_DATA(priv); + unsigned int stateThrs_idx, state_idx, rssi_idx, reg_idx; + + + PRINT_ONE(" MACDM...", "%s", 1); + PRINT_SINGL_ARG(" MACDM_Mode: ", pHalData->MACDM_Mode_Sel, "%d"); + PRINT_SINGL_ARG(" MACDM_state: ", pHalData->MACDM_State, "%d"); + + //Threshold + for (stateThrs_idx=0; stateThrs_idxMACDM_stateThrs[stateThrs_idx][rssi_idx], "0x%x", 1); + } + } + + //Table + for (state_idx=0; state_idxMACDM_Table[state_idx][rssi_idx][reg_idx].offset == 0xffff) { + break; + } + + PRINT_ONE(pHalData->MACDM_Table[state_idx][rssi_idx][reg_idx].offset, "Reg: 0x%x, ", 0); + PRINT_ONE(pHalData->MACDM_Table[state_idx][rssi_idx][reg_idx].value, "Value: 0x%x", 1); + } + } + } + + return pos; +} +#endif //WLANHAL_MACDM +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_all(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_all(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int len = 0; +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + off_t begin = 0; + off_t pos = 0; +#endif + int size; + +#ifdef __ECOS + ecos_pr_fun(" Make info: v%d.%d (%s)\n", DRV_VERSION_H, DRV_VERSION_L, DRV_RELDATE); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, " Make info: v%d.%d (%s)\n", DRV_VERSION_H, DRV_VERSION_L, DRV_RELDATE); +#else + size = sprintf(buf, " Make info: v%d.%d (%s)\n", DRV_VERSION_H, DRV_VERSION_L, DRV_RELDATE); + CHECK_LEN; +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#if !(defined(__KERNEL__) && (defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI))) + if (GET_CHIP_VER(priv) != VERSION_8188E) +#endif +#endif + { +#ifdef __ECOS + ecos_pr_fun(" RTL8192 firmware version: %d.%d, built time: %02x-%02x %02x:%02x\n", priv->pshare->fw_version, + priv->pshare->fw_sub_version, priv->pshare->fw_date_month, priv->pshare->fw_date_day, + priv->pshare->fw_date_hour, priv->pshare->fw_date_minute); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, " RTL8192 firmware version: %d.%d, built time: %02x-%02x %02x:%02x\n", priv->pshare->fw_version, + priv->pshare->fw_sub_version, priv->pshare->fw_date_month, priv->pshare->fw_date_day, + priv->pshare->fw_date_hour, priv->pshare->fw_date_minute); +#else + size = sprintf(buf+len, " RTL8192 firmware version: %d.%d, built time: %02x-%02x %02x:%02x\n", priv->pshare->fw_version, + priv->pshare->fw_sub_version, priv->pshare->fw_date_month, priv->pshare->fw_date_day, + priv->pshare->fw_date_hour, priv->pshare->fw_date_minute); + CHECK_LEN; +#endif + } + +#ifdef CONFIG_RTL_PROC_NEW + rtl8192cd_proc_mib_rf(s, data); + rtl8192cd_proc_mib_operation(s, data); + rtl8192cd_proc_mib_staconfig(s, data); + rtl8192cd_proc_mib_dkeytbl(s, data); + rtl8192cd_proc_mib_auth(s, data); + rtl8192cd_proc_mib_gkeytbl(s, data); + rtl8192cd_proc_mib_bssdesc(s, data); + rtl8192cd_proc_mib_erp(s, data); + rtl8192cd_proc_mib_misc(s, data); +#ifdef WIFI_SIMPLE_CONFIG + rtl8192cd_proc_mib_wsc(s, data); +#endif + rtl8192cd_proc_probe_info(s, data); + +#ifdef HS2_SUPPORT + rtl8192cd_proc_mib_hs2(s, data); +#endif + +#ifdef WDS + rtl8192cd_proc_mib_wds(s, data); +#endif + +#ifdef RTK_BR_EXT + rtl8192cd_proc_mib_brext(s, data); +#endif + +#ifdef DFS + rtl8192cd_proc_mib_DFS(s, data); +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + rtl8192cd_proc_mib_rf_ac(s, data); +#endif + + size = rtl8192cd_proc_mib_11n(s, data); + +#ifdef CONFIG_RTK_VLAN_SUPPORT + rtl8192cd_proc_vlan_read(s, data); +#endif + +#ifdef SUPPORT_MULTI_PROFILE + rtl8192cd_proc_mib_ap_profile(s, data); +#endif +#else // !CONFIG_RTL_PROC_NEW + size = rtl8192cd_proc_mib_rf(buf+len, start, offset, length, eof, data); + CHECK_LEN; + + size = rtl8192cd_proc_mib_operation(buf+len, start, offset, length, eof, data); + CHECK_LEN; + + size = rtl8192cd_proc_mib_staconfig(buf+len, start, offset, length, eof, data); + CHECK_LEN; + + size = rtl8192cd_proc_mib_dkeytbl(buf+len, start, offset, length, eof, data); + CHECK_LEN; + + size = rtl8192cd_proc_mib_auth(buf+len, start, offset, length, eof, data); + CHECK_LEN; + + size = rtl8192cd_proc_mib_gkeytbl(buf+len, start, offset, length, eof, data); + CHECK_LEN; + + size = rtl8192cd_proc_mib_bssdesc(buf+len, start, offset, length, eof, data); + CHECK_LEN; + + size = rtl8192cd_proc_mib_erp(buf+len, start, offset, length, eof, data); + CHECK_LEN; + + size = rtl8192cd_proc_mib_misc(buf+len, start, offset, length, eof, data); + CHECK_LEN; +#ifdef WIFI_SIMPLE_CONFIG + size = rtl8192cd_proc_mib_wsc(buf+len, start, offset, length, eof, data); + CHECK_LEN; +#endif + size = rtl8192cd_proc_probe_info(buf+len, start, offset, length, eof, data); + CHECK_LEN; + +#ifdef HS2_SUPPORT + size = rtl8192cd_proc_mib_hs2(buf+len, start, offset, length, eof, data); + CHECK_LEN; +#endif +#ifdef WDS + size = rtl8192cd_proc_mib_wds(buf+len, start, offset, length, eof, data); + CHECK_LEN; +#endif + +#ifdef RTK_BR_EXT + size = rtl8192cd_proc_mib_brext(buf+len, start, offset, length, eof, data); + CHECK_LEN; +#endif + +#ifdef DFS + size = rtl8192cd_proc_mib_DFS(buf+len, start, offset, length, eof, data); + CHECK_LEN; +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if(len) + goto _ret; + size = rtl8192cd_proc_mib_rf_ac(buf+len, start, offset, length, eof, data); + CHECK_LEN; +#endif + + size = rtl8192cd_proc_mib_11n(buf+len, start, offset, length, eof, data); + CHECK_LEN; + +#ifdef CONFIG_RTK_VLAN_SUPPORT + size = rtl8192cd_proc_vlan_read(buf+len, start, offset, length, eof, data); + CHECK_LEN; +#endif + +#ifdef SUPPORT_MULTI_PROFILE + size = rtl8192cd_proc_mib_ap_profile(buf+len, start, offset, length, eof, data); + CHECK_LEN; +#endif +#endif // CONFIG_RTL_PROC_NEW + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *eof = 1; + +_ret: + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ +#endif + return len; +} + +#if defined(__ECOS) || defined(CONFIG_RTL_PROC_NEW) +#define CHECK_LEN_B do {} while(0) +#else +#define MAX_CHAR_IN_A_LINE 80 +// macro "CHECK_LEN_B" is used in dump_one_stainfo() only +#define CHECK_LEN_B { \ + if (pos > (remained_len - MAX_CHAR_IN_A_LINE)) {\ + return pos; \ + } \ +} +#endif + +//static int dump_one_stainfo(int num, struct stat_info *pstat, char *buf, char **start, +// off_t offset, int length, int *eof, void *data) +#ifdef CONFIG_RTL_PROC_NEW +static int dump_one_stainfo(struct seq_file *s, int num, struct rtl8192cd_priv *priv, struct stat_info *pstat, int *rc) +#else +static int dump_one_stainfo(int num, struct rtl8192cd_priv *priv, struct stat_info *pstat, char *buf, + off_t offset, int length, int remained_len, int *rc) +#endif +{ + int pos = 0, idx = 0; + unsigned int m, n; + char tmp[32]; + //unsigned short rate; + unsigned char tmpbuf[16]; + unsigned char *rate; + unsigned char current_rate; + + PRINT_ONE(num, " %d: stat_info...", 1); + CHECK_LEN_B; + PRINT_SINGL_ARG(" state: ", pstat->state, "%x"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" AuthAlgrthm: ", pstat->AuthAlgrthm, "%d"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" ieee8021x_ctrlport: ", pstat->ieee8021x_ctrlport, "%d"); + CHECK_LEN_B; +#ifdef CONFIG_IEEE80211W +#ifdef CONFIG_IEEE80211W_CLI + PRINT_SINGL_ARG(" bss support PMF : ", priv->support_pmf, "%d"); + CHECK_LEN_B; +#endif + PRINT_SINGL_ARG(" isPMF: ", pstat->isPMF, "%d"); + CHECK_LEN_B; +#endif + PRINT_ARRAY_ARG(" hwaddr: ", pstat->hwaddr, "%02x", MACADDRLEN); + CHECK_LEN_B; + PRINT_ARRAY_ARG(" bssrateset: ", pstat->bssrateset, "%02x", pstat->bssratelen); + CHECK_LEN_B; + PRINT_SINGL_ARG(" aid: ", pstat->aid, "%d"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" tx_bytes: ", pstat->tx_bytes, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" rx_bytes: ", pstat->rx_bytes, "%u"); + CHECK_LEN_B; +#ifdef RADIUS_ACCOUNTING + PRINT_SINGL_ARG(" tx_bytes per minute: ", pstat->tx_bytes_1m, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" rx_bytes per minute: ", pstat->rx_bytes_1m, "%u"); + CHECK_LEN_B; +#endif + PRINT_SINGL_ARG(" tx_pkts: ", pstat->tx_pkts, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" rx_pkts: ", pstat->rx_pkts, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" tx_fail: ", pstat->tx_fail, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" tx_avarage: ", pstat->tx_avarage, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" rx_avarage: ", pstat->rx_avarage, "%u"); + CHECK_LEN_B; +#ifdef CONFIG_PCI_HCI + PRINT_SINGL_ARG(" dz_queue_len: ", skb_queue_len(&pstat->dz_queue), "%u"); + CHECK_LEN_B; +#endif +#ifdef SW_TX_QUEUE + //for debug +#if 0 + PRINT_SINGL_ARG(" tx_av: ", pstat->tx_avarage, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" tx_agn: ", pstat->aggn_cnt, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" tx_be_tout: ", pstat->be_timeout_cnt, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" tx_bk_tout: ", pstat->bk_timeout_cnt, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" tx_vi_tout: ", pstat->vi_timeout_cnt, "%u"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" tx_vo_tout: ", pstat->vo_timeout_cnt, "%u"); + CHECK_LEN_B; +#endif +#endif + PRINT_ONE(" rssi: ", "%s", 0); + PRINT_ONE(pstat->rssi, "%u", 0); + PRINT_ONE(pstat->rf_info.mimorssi[0], " (%u", 0); + PRINT_ONE(pstat->rf_info.mimorssi[1], " %u", 0); + PRINT_ONE(")", "%s", 1); + CHECK_LEN_B; + +#ifdef WDS + if (pstat->state & WIFI_WDS +#ifdef LAZY_WDS + && !(pstat->state & WIFI_WDS_LAZY) +#endif + ) { + PRINT_SINGL_ARG(" idle_time: ", pstat->idle_time, "%d"); + CHECK_LEN_B; + } + else +#endif + { + PRINT_SINGL_ARG(" expired_time: ", pstat->expire_to, "%d"); + CHECK_LEN_B; + } + + PRINT_SINGL_ARG(" sleep: ", (!list_empty(&pstat->sleep_list) ? "yes" : "no"), "%s"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" sta_in_firmware_mem: ",(pstat->sta_in_firmware == -1 ? "removed" : ((pstat->sta_in_firmware) == 0 ? "no":"yes")), "%s" ); + CHECK_LEN_B; + PRINT_SINGL_ARG(" remapped_aid: ", pstat->remapped_aid, "%d"); + CHECK_LEN_B; + + // avoid current_tx_rate change during the following process to cause out of range in MCS_DATA_RATEStr + current_rate = pstat->current_tx_rate; +#ifdef RTK_AC_SUPPORT //vht rate , todo, dump vht rates in Mbps + if(current_rate >= VHT_RATE_ID){ + int rate = query_vht_rate(pstat); + PRINT_ONE(" current_tx_rate: VHT NSS", "%s", 0); + PRINT_ONE(((current_rate - VHT_RATE_ID)/10)+1, "%d", 0); + PRINT_ONE("-MCS", "%s", 0); + PRINT_ONE((current_rate - VHT_RATE_ID)%10, "%d", 0); + PRINT_ONE(rate, " %d", 1); + CHECK_LEN_B; + } + else +#endif + if (is_MCS_rate(current_rate)) { + PRINT_ONE(" current_tx_rate: MCS", "%s", 0); + PRINT_ONE((current_rate - HT_RATE_ID), "%d", 0); + rate = (unsigned char *)MCS_DATA_RATEStr[(pstat->ht_current_tx_info&BIT(0))?1:0][(pstat->ht_current_tx_info&BIT(1))?1:0][(current_rate - HT_RATE_ID)]; + PRINT_ONE(rate, " %s", 1); + CHECK_LEN_B; + } + else + { + PRINT_SINGL_ARG(" current_tx_rate: ", current_rate/2, "%d"); + CHECK_LEN_B; + } + + // avoid rx_rate change during the following process to cause out of range in MCS_DATA_RATEStr + current_rate = pstat->rx_rate; +#ifdef RTK_AC_SUPPORT //vht rate , todo, dump vht rates in Mbps + if(current_rate >= VHT_RATE_ID){ + int rate = query_vht_rx_rate(pstat); + PRINT_ONE(" rx_rate: VHT NSS", "%s", 0); + PRINT_ONE(((current_rate - VHT_RATE_ID)/10)+1, "%d", 0); + PRINT_ONE("-MCS", "%s", 0); + PRINT_ONE((current_rate - VHT_RATE_ID)%10, "%d", 0); + PRINT_ONE(rate, " %d", 1); + CHECK_LEN_B; + } + else +#endif + if (is_MCS_rate(current_rate)) { + PRINT_ONE(" current_rx_rate: MCS", "%s", 0); + PRINT_ONE((current_rate - HT_RATE_ID), "%d", 0); + rate = (unsigned char *)MCS_DATA_RATEStr[pstat->rx_bw&0x01][pstat->rx_splcp&0x01][(current_rate - HT_RATE_ID)]; + PRINT_ONE(rate, " %s", 1); + CHECK_LEN_B; + } + else + { + PRINT_SINGL_ARG(" current_rx_rate: ", current_rate/2, "%d"); + CHECK_LEN_B; + } + +//8812_client tx_bw rx_bw ?? + PRINT_SINGL_ARG(" rx_bw: ", (0x1<<(pstat->rx_bw))*20, "%dM"); + CHECK_LEN_B; + + PRINT_SINGL_ARG(" tx_bw: ", (pstat->tx_bw ? (pstat->tx_bw*40) : 20), "%dM"); + //PRINT_SINGL_ARG(" tx_bw: ", (0x1<<(pstat->tx_bw))*20, "%dM"); + CHECK_LEN_B; + +#ifdef RTK_AC_SUPPORT + PRINT_SINGL_ARG(" nss: ", (pstat->nss), "%d"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" support_mcs: ", cpu_to_le32(pstat->vht_cap_buf.vht_support_mcs[0]), "%x"); + CHECK_LEN_B; +#endif + + PRINT_SINGL_ARG(" hp_level: ", pstat->hp_level, "%d"); + CHECK_LEN_B; + +#ifdef WIFI_WMM + PRINT_SINGL_ARG(" QoS Enable: ", pstat->QosEnabled, "%d"); + CHECK_LEN_B; +#ifdef WMM_APSD + PRINT_SINGL_ARG(" APSD bitmap: ", pstat->apsd_bitmap, "0x%01x"); + CHECK_LEN_B; +#endif +#endif + + PRINT_SINGL_ARG(" tx_ra_bitmap: ", pstat->tx_ra_bitmap, "0x%08x"); + + if (pstat->is_realtek_sta) + sprintf((char *)tmpbuf, "Realtek"); + + else if (pstat->IOTPeer==HT_IOT_PEER_BROADCOM) + sprintf((char *)tmpbuf, "Broadcom"); + else if (pstat->IOTPeer==HT_IOT_PEER_MARVELL) + sprintf((char *)tmpbuf, "Marvell"); + else if (pstat->IOTPeer==HT_IOT_PEER_INTEL) + sprintf((char *)tmpbuf, "Intel"); + else if (pstat->IOTPeer==HT_IOT_PEER_RALINK) + sprintf((char *)tmpbuf, "Ralink"); + else if (pstat->IOTPeer==HT_IOT_PEER_HTC) + sprintf((char *)tmpbuf, "HTC"); + else + + sprintf((char *)tmpbuf, "--"); + PRINT_SINGL_ARG(" Chip Vendor: ", tmpbuf, "%s"); + CHECK_LEN_B; +#ifdef RTK_WOW + if (pstat->is_realtek_sta) { + PRINT_SINGL_ARG(" is_rtk_wow_sta: ", (pstat->is_rtk_wow_sta? "yes":"no"), "%s"); + CHECK_LEN_B; + } +#endif + + m = pstat->link_time / 86400; + n = pstat->link_time % 86400; + if (m) idx += sprintf(tmp, "%d day ", m); + m = n / 3600; + n = n % 3600; + if (m) idx += sprintf(tmp+idx, "%d hr ", m); + m = n / 60; + n = n % 60; + if (m) idx += sprintf(tmp+idx, "%d min ", m); + idx += sprintf(tmp+idx, "%d sec ", n); + PRINT_SINGL_ARG(" link_time: ", tmp, "%s"); + CHECK_LEN_B; + + if (pstat->private_ie_len) { + PRINT_ARRAY_ARG(" private_ie: ", pstat->private_ie, "%02x", pstat->private_ie_len); + CHECK_LEN_B; + } + if (pstat->ht_cap_len) { + unsigned char *pbuf = (unsigned char *)&pstat->ht_cap_buf; + PRINT_ARRAY_ARG(" ht_cap: ", pbuf, "%02x", pstat->ht_cap_len); + CHECK_LEN_B; + + PRINT_ONE(" 11n MIMO ps: ", "%s", 0); + if (!(pstat->MIMO_ps)) { + PRINT_ONE("no limit", "%s", 1); + } + else { + PRINT_ONE(((pstat->MIMO_ps&BIT(0))?"static":"dynamic"), "%s", 1); + } + CHECK_LEN_B; + + PRINT_SINGL_ARG(" Is_8K_AMSDU: ", pstat->is_8k_amsdu, "%d"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" amsdu_level: ", pstat->amsdu_level, "%d"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" diffAmpduSz: 0x", pstat->diffAmpduSz, "%x"); + CHECK_LEN_B; + + switch (pstat->aggre_mthd) { + case AGGRE_MTHD_MPDU: + sprintf(tmp, "AMPDU"); + break; + case AGGRE_MTHD_MSDU: + sprintf(tmp, "AMSDU"); + break; + case AGGRE_MTHD_MPDU_AMSDU: + sprintf(tmp, "AMPDU_AMSDU"); + break; + default: + sprintf(tmp, "None"); + break; + } + PRINT_SINGL_ARG(" aggre mthd: ", tmp, "%s"); + CHECK_LEN_B; + +#ifdef BEAMFORMING_SUPPORT + PRINT_SINGL_ARG(" ht beamformee: ", (cpu_to_le32(pstat->ht_cap_buf.txbf_cap) & 0x8)?"Y":"N", "%s"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" ht beamformer: ", (cpu_to_le32(pstat->ht_cap_buf.txbf_cap) & 0x10)?"Y":"N", "%s"); + CHECK_LEN_B; +#endif + +#ifdef _DEBUG_RTL8192CD_ + PRINT_ONE(" ch_width: ", "%s", 0); + PRINT_ONE((pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))?"40M":"20M", "%s", 1); + CHECK_LEN_B; + PRINT_ONE(" ampdu_mf: ", "%s", 0); + PRINT_ONE(pstat->ht_cap_buf.ampdu_para & 0x03, "%d", 1); + CHECK_LEN_B; + PRINT_ONE(" ampdu_amd: ", "%s", 0); + PRINT_ONE((pstat->ht_cap_buf.ampdu_para & _HTCAP_AMPDU_SPC_MASK_) >> _HTCAP_AMPDU_SPC_SHIFT_, "%d", 1); + CHECK_LEN_B; +#endif + } + else { + PRINT_ONE(" ht_cap: none", "%s", 1); + CHECK_LEN_B; + } + + +//AC capability +#ifdef RTK_AC_SUPPORT + if (pstat->vht_cap_len) { + unsigned char *pbuf = (unsigned char *)&pstat->vht_cap_buf; + PRINT_ARRAY_ARG(" vht_cap_ie: ", pbuf, "%02x", pstat->vht_cap_len); + CHECK_LEN_B; + +#ifdef BEAMFORMING_SUPPORT + PRINT_SINGL_ARG(" vht beamformee: ", (cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & BIT(SU_BFEE_S))?"Y":"N", "%s"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" vht beamformer: ", (cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & BIT(SU_BFER_S))?"Y":"N", "%s"); + CHECK_LEN_B; +#endif + + } + else { + PRINT_ONE(" vht_cap_ie: none", "%s", 1); + CHECK_LEN_B; + } + + if (pstat->vht_oper_len) { + unsigned char *pbuf = (unsigned char *)&pstat->vht_oper_buf; + PRINT_ARRAY_ARG(" vht_oper_ie: ", pbuf, "%02x", pstat->vht_oper_len); + CHECK_LEN_B; + } + else { + PRINT_ONE(" vht_oper_ie: none", "%s", 1); + CHECK_LEN_B; + } +#endif + +#ifdef BEAMFORMING_SUPPORT + if (priv->pmib->dot11RFEntry.txbf == 1) { + u1Byte Idx = 0; + PRT_BEAMFORMING_ENTRY pEntry; + pEntry = Beamforming_GetEntryByMacId(priv, pstat->aid, &Idx); + PRINT_SINGL_ARG(" Activate Tx beamforming : ", (pEntry ? "Y" : "N"),"%s"); + } +#endif + +#ifdef SUPPORT_TX_MCAST2UNI + PRINT_SINGL_ARG(" ipmc_num: ", pstat->ipmc_num, "%d"); + CHECK_LEN_B; + for (idx=0; idxipmc[idx].used) { + PRINT_ARRAY_ARG(" mcmac: ", pstat->ipmc[idx].mcmac, "%02x", MACADDRLEN); + CHECK_LEN_B; + } + } +#endif + + +#if defined(CONFIG_WLAN_HAL) + if(IS_HAL_CHIP(priv)) { + // below is add by SD1 Eric 2013/5/6 + // For 92E,8881 MACID Sleep and MACID drop status in driver and SRAM status + + PRINT_SINGL_ARG(" bSleep: ", pstat->txpause_flag,"%02x"); + PRINT_SINGL_ARG(" bDrop: ", pstat->bDrop, "%02x"); + +#ifdef CONFIG_PCI_HCI + u1Byte bDrop = 0; // txrpt need allocate 16byte + if(RT_STATUS_FAILURE == GET_HAL_INTERFACE(priv)->GetTxRPTHandler(priv, pstat->aid,TXRPT_VAR_PKT_DROP,&bDrop)) + { + PRINT_SINGL_ARG(" FW bDrop: ", 0xff,"%02x"); + } + else + { + PRINT_SINGL_ARG(" FW bDrop: ", bDrop,"%02x"); + } +#endif + } +#endif //defined(CONFIG_WLAN_HAL) + + +#ifdef CLIENT_MODE + if (pstat->ht_ie_len) { + unsigned char *pbuf = (unsigned char *)&pstat->ht_ie_buf; + PRINT_ARRAY_ARG(" ht_ie: ", pbuf, "%02x", pstat->ht_ie_len); + CHECK_LEN_B; + } + else { + PRINT_ONE(" ht_ie: none", "%s", 1); + CHECK_LEN_B; + } + +#ifdef HS2_SUPPORT +/* Hotspot 2.0 Release 1 */ + PRINT_ARRAY_ARG(" sta ip:", pstat->sta_ip, "%d.", 4); + CHECK_LEN_B; + PRINT_SINGL_ARG(" sta v6 ip[0]:", pstat->sta_v6ip.s6_addr32[0], "%08x"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" sta v6 ip[1]:", pstat->sta_v6ip.s6_addr32[1], "%08x"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" sta v6 ip[2]:", pstat->sta_v6ip.s6_addr32[2], "%08x"); + CHECK_LEN_B; + PRINT_SINGL_ARG(" sta v6 ip[3]:", pstat->sta_v6ip.s6_addr32[3], "%08x"); + CHECK_LEN_B; +#endif + +#endif + +#ifdef MULTI_MAC_CLONE + if (OPMODE & WIFI_STATION_STATE) { + PRINT_ARRAY_ARG(" sa_addr: ", pstat->sa_addr, "%02x", MACADDRLEN); + CHECK_LEN_B; + PRINT_SINGL_ARG(" mclone_id: ", pstat->mclone_id, "%d"); + CHECK_LEN_B; + } +#endif + + if (pstat->WirelessMode & WIRELESS_MODE_AC_5G) + sprintf(tmpbuf, "AC"); + else if (pstat->WirelessMode & WIRELESS_MODE_N_5G) + sprintf(tmpbuf, "AN"); + else if (pstat->WirelessMode & WIRELESS_MODE_N_24G) + sprintf(tmpbuf, "BGN"); + else if (pstat->WirelessMode & WIRELESS_MODE_G) + sprintf(tmpbuf, "BG"); + else if (pstat->WirelessMode & WIRELESS_MODE_A) + sprintf(tmpbuf, "A"); + else if (pstat->WirelessMode & WIRELESS_MODE_B) + sprintf(tmpbuf, "B"); + else + sprintf(tmpbuf, "--"); + PRINT_SINGL_ARG(" wireless mode: ", tmpbuf, "%s"); + CHECK_LEN_B; + + PRINT_ONE("", "%s", 1); + + *rc = 1; //finished, assign okay to return code. + return pos; +} + +#ifdef __KERNEL__ +static int read_sta_info_down; +#endif +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_stainfo(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_stainfo(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int len = 0, rc=1; +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + off_t begin = 0; + off_t pos = 0; +#endif + int size, num=1; + struct list_head *phead, *plist; + struct stat_info *pstat; + unsigned long flags=0; + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + if (offset == 0) // first calling, reset read_sta_info_down variable + read_sta_info_down = 0; + + // first, kernel call me with length=3072; second, kernel call me with length=1024, + // third, , kernel call me with length < 1024, I just return 0 when length < 1024 to avoid wasting time. + if (length < 1024) { + return 0; + } + + // do not waste time again + // I sent *eof=1 last time, I do not know why the kernel will call me again. + if (read_sta_info_down) { + *eof = 1; + return 0; + } +#endif + + SAVE_INT_AND_CLI(flags); + SMP_LOCK_ASOC_LIST(flags); + + // !!! it REALLY waste the cpu time ==> it will do from beginning when kernel call rtl8192cd_proc_stainfo() function again and again. +#ifdef __ECOS + ecos_pr_fun("-- STA info table -- (active: %d)\n", priv->assoc_num); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, "-- STA info table -- (active: %d)\n", priv->assoc_num); +#else + size = sprintf(buf, "-- STA info table -- (active: %d)\n", priv->assoc_num); + CHECK_LEN; +#endif + + phead = &priv->asoc_list; + if (!(priv->drv_state & DRV_STATE_OPEN) || list_empty(phead)) { +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *eof = 1; +#endif + goto _ret; + } + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + // (length - len) : the remained length can be used. + if ((length - len) < MAX_CHAR_IN_A_LINE) + goto _ret; + + rc = 0; // return code, assume error by default +#endif + //size = dump_one_stainfo(num++, pstat, buf+len, start, offset, length, eof, data); +#ifdef CONFIG_RTL_PROC_NEW + dump_one_stainfo(s, num++, priv, pstat, &rc); +#else + size = dump_one_stainfo(num++, priv, pstat, buf+len, offset, length, (length - len), &rc); +#endif + CHECK_LEN; + +#ifdef CONFIG_RTK_MESH + if (rc == 0) + break; + + // 3 line for Throughput statistics (sounder) + size = dump_mesh_one_mpflow_sta(num, pstat, buf+len, start, offset, length, + eof, data); + CHECK_LEN; +#endif + + plist = plist->next; + } + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + if (rc == 1) { // return code is okay. if return code is 0, it means the dump_one_stainfo() is not finished. + read_sta_info_down = 1; + *eof = 1; + } +#endif + +_ret: + SMP_UNLOCK_ASOC_LIST(flags); + RESTORE_INT(flags); + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ +#endif + + return len; +} + + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +#ifdef CONFIG_RTL_PROC_NEW +static int dump_one_sta_keyinfo(struct seq_file *s, int num, struct stat_info *pstat) +#else +static int dump_one_sta_keyinfo(int num, struct stat_info *pstat, char *buf, char **start, + off_t offset, int length, int *eof, void *data) +#endif +{ + int pos = 0; + unsigned char *ptr; + + PRINT_ONE(num, " %d: stat_keyinfo...", 1); + PRINT_ARRAY_ARG(" hwaddr: ", pstat->hwaddr, "%02x", MACADDRLEN); + PRINT_SINGL_ARG(" keyInCam: ", (pstat->dot11KeyMapping.keyInCam? "yes" : "no"), "%s"); + PRINT_SINGL_ARG(" dot11Privacy: ", + pstat->dot11KeyMapping.dot11Privacy, "%d"); + PRINT_SINGL_ARG(" dot11EncryptKey.dot11TTKeyLen: ", + pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen, "%d"); + PRINT_SINGL_ARG(" dot11EncryptKey.dot11TMicKeyLen: ", + pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKeyLen, "%d"); + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11TTKey.skey: ", + pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKey.skey, "%02x", 16); + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11TMicKey1.skey: ", + pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKey1.skey, "%02x", 16); + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11TMicKey2.skey: ", + pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKey2.skey, "%02x", 16); + ptr = (unsigned char *)&pstat->dot11KeyMapping.dot11EncryptKey.dot11TXPN48.val48; + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11TXPN48.val48: ", ptr, "%02x", 8); + ptr = (unsigned char *)&pstat->dot11KeyMapping.dot11EncryptKey.dot11RXPN48.val48; + PRINT_ARRAY_ARG(" dot11EncryptKey.dot11RXPN48.val48: ", ptr, "%02x", 8); + + PRINT_ONE("", "%s", 1); + + return pos; +} + + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_sta_keyinfo(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_sta_keyinfo(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int len = 0; +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + off_t begin = 0; + off_t pos = 0; +#endif + int size, num=1; + struct list_head *phead, *plist; + struct stat_info *pstat; + unsigned long flags=0; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK_ASOC_LIST(flags); + +#ifdef __ECOS + ecos_pr_fun("-- STA key info table --\n"); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, "-- STA key info table --\n"); +#else + strcpy(buf, "-- STA key info table --\n"); + size = strlen(buf); + CHECK_LEN; +#endif + + phead = &priv->asoc_list; + if (!(priv->drv_state & DRV_STATE_OPEN) || list_empty(phead)) + goto _ret; + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; +#ifdef CONFIG_RTL_PROC_NEW + dump_one_sta_keyinfo(s, num++, pstat); +#else + size = dump_one_sta_keyinfo(num++, pstat, buf+len, start, offset, length, + eof, data); +#endif + CHECK_LEN; + } +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *eof = 1; +#endif + +_ret: + SMP_UNLOCK_ASOC_LIST(flags); + RESTORE_INT(flags); + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ +#endif + + return len; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int dump_one_sta_dbginfo(struct seq_file *s, int num, struct stat_info *pstat) +#else +static int dump_one_sta_dbginfo(int num, struct stat_info *pstat, char *buf, char **start, + off_t offset, int length, int *eof, void *data) +#endif +{ + int pos = 0; + + PRINT_ARRAY_ARG(" hwaddr: ", pstat->hwaddr, "%02x", MACADDRLEN); +#ifdef TX_SHORTCUT + PRINT_SINGL_ARG(" tx_sc_pkts_lv1: ", pstat->tx_sc_pkts_lv1, "%d"); + PRINT_SINGL_ARG(" tx_sc_pkts_lv2: ", pstat->tx_sc_pkts_lv2, "%d"); + PRINT_SINGL_ARG(" tx_sc_pkts_slow: ", pstat->tx_sc_pkts_slow, "%u"); + PRINT_SINGL_ARG(" rx_sc_pkts: ", pstat->rx_sc_pkts, "%d"); + PRINT_SINGL_ARG(" rx_sc_pkts_slow: ", pstat->rx_sc_pkts_slow, "%u"); +#endif + +#ifdef CONFIG_PCI_HCI + PRINT_SINGL_ARG(" dz_queue_len: ", skb_queue_len(&pstat->dz_queue), "%u"); +#endif + PRINT_SINGL_ARG(" hp_level: ", pstat->hp_level, "%d"); + +#ifdef _DEBUG_RTL8192CD_ + PRINT_ONE(" ch_width: ", "%s", 0); + PRINT_ONE((pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))?"40M":"20M", "%s", 1); + PRINT_ONE(" ampdu_mf: ", "%s", 0); + PRINT_ONE(pstat->ht_cap_buf.ampdu_para & 0x03, "%d", 1); + PRINT_ONE(" ampdu_amd: ", "%s", 0); + PRINT_ONE((pstat->ht_cap_buf.ampdu_para & _HTCAP_AMPDU_SPC_MASK_) >> _HTCAP_AMPDU_SPC_SHIFT_, "%d", 1); +#endif + +#if defined(HW_ANT_SWITCH)&&( defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + PRINT_SINGL_ARG(" Ant 1 packet count: ", pstat->hwRxAntSel[1], "%u"); + PRINT_SINGL_ARG(" Ant 2 packet count: ", pstat->hwRxAntSel[0], "%u"); + PRINT_SINGL_ARG(" Antenna select : ", (pstat->CurAntenna==0 ? 2 : 1), "%u"); +#endif + +#ifdef _DEBUG_RTL8192CD_ + PRINT_SINGL_ARG(" amsdu err: ", pstat->rx_amsdu_err, "%u"); + PRINT_SINGL_ARG(" amsdu 1pkt: ", pstat->rx_amsdu_1pkt, "%u"); + PRINT_SINGL_ARG(" amsdu 2pkt: ", pstat->rx_amsdu_2pkt, "%u"); + PRINT_SINGL_ARG(" amsdu 3pkt: ", pstat->rx_amsdu_3pkt, "%u"); + PRINT_SINGL_ARG(" amsdu 4pkt: ", pstat->rx_amsdu_4pkt, "%u"); + PRINT_SINGL_ARG(" amsdu 5pkt: ", pstat->rx_amsdu_5pkt, "%u"); + PRINT_SINGL_ARG(" amsdu gt 5pkt: ", pstat->rx_amsdu_gt5pkt, "%u"); + + PRINT_SINGL_ARG(" rc drop1: ", pstat->rx_rc_drop1, "%u"); + PRINT_SINGL_ARG(" rc passup2: ", pstat->rx_rc_passup2, "%u"); + PRINT_SINGL_ARG(" rc drop3: ", pstat->rx_rc_drop3, "%u"); + PRINT_SINGL_ARG(" rc reorder3: ", pstat->rx_rc_reorder3, "%u"); + PRINT_SINGL_ARG(" rc passup3: ", pstat->rx_rc_passup3, "%u"); + PRINT_SINGL_ARG(" rc drop4: ", pstat->rx_rc_drop4, "%u"); + PRINT_SINGL_ARG(" rc reorder4: ", pstat->rx_rc_reorder4, "%u"); + PRINT_SINGL_ARG(" rc passup4: ", pstat->rx_rc_passup4, "%u"); + PRINT_SINGL_ARG(" rc passupi: ", pstat->rx_rc_passupi, "%u"); +#endif +#ifdef DETECT_STA_EXISTANCE + PRINT_SINGL_ARG(" sta leave: ", pstat->leave, "%u"); +#endif +#ifdef SW_TX_QUEUE + PRINT_SINGL_ARG(" bk aggnum: ", pstat->swq.q_aggnum[BK_QUEUE], "%d"); + PRINT_SINGL_ARG(" be aggnum: ", pstat->swq.q_aggnum[BE_QUEUE], "%d"); + PRINT_SINGL_ARG(" be qlen: ", skb_queue_len(&pstat->swq.be_queue), "%d"); + PRINT_SINGL_ARG(" vi aggnum: ", pstat->swq.q_aggnum[VI_QUEUE], "%d"); + PRINT_SINGL_ARG(" vo aggnum: ", pstat->swq.q_aggnum[VO_QUEUE], "%d"); + PRINT_SINGL_ARG(" bk backtime: ", pstat->swq.q_aggnumIncSlow[BK_QUEUE], "%d"); + PRINT_SINGL_ARG(" be backtime: ", pstat->swq.q_aggnumIncSlow[BE_QUEUE], "%d"); + PRINT_SINGL_ARG(" vi backtime: ", pstat->swq.q_aggnumIncSlow[VI_QUEUE], "%d"); + PRINT_SINGL_ARG(" vo backtime: ", pstat->swq.q_aggnumIncSlow[VO_QUEUE], "%d"); +#endif + +#ifdef BEAMFORMING_SUPPORT + PRINT_SINGL_ARG(" bf score: ", pstat->bf_score, "%u"); +#endif + + PRINT_ONE("", "%s", 1); + + return pos; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_sta_dbginfo(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_sta_dbginfo(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int len = 0; +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + off_t begin = 0; + off_t pos = 0; +#endif + int size, num=1; + struct list_head *phead, *plist; + struct stat_info *pstat; + unsigned long flags=0; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK_ASOC_LIST(flags); + +#ifdef __ECOS + ecos_pr_fun("-- STA dbg info table --\n"); +#elif defined(CONFIG_RTL_PROC_NEW) + seq_printf(s, "-- STA dbg info table --\n"); +#else + strcpy(buf, "-- STA dbg info table --\n"); + size = strlen(buf); + CHECK_LEN; +#endif + + phead = &priv->asoc_list; + if (!(priv->drv_state & DRV_STATE_OPEN) || list_empty(phead)) + goto _ret; + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; +#ifdef CONFIG_RTL_PROC_NEW + dump_one_sta_dbginfo(s, num++, pstat); +#else + size = dump_one_sta_dbginfo(num++, pstat, buf+len, start, offset, length, + eof, data); +#endif + CHECK_LEN; + } +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *eof = 1; +#endif + +_ret: + SMP_UNLOCK_ASOC_LIST(flags); + RESTORE_INT(flags); + +#if defined(__KERNEL__) && !defined(CONFIG_RTL_PROC_NEW) + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ +#endif + + return len; +} + + +#ifdef PCIE_POWER_SAVING +char pwr_state_str[][20] = {"L0", "L1", "L2", "ASPM_L0s_L1" }; +#endif + +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_stats(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_stats(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0, idx = 0; + unsigned int m, n, print=0; + char tmp[32]; + unsigned char *rate; + unsigned char current_rate; +#ifndef SMP_SYNC + unsigned long flags=0; +#endif +#ifdef CONFIG_PCI_HCI +#if defined(__ECOS) && defined(TX_PKT_FREE_QUEUE) + Rltk819x_t *info = dev->info; +#endif +#endif + + SAVE_INT_AND_CLI(flags); + + PRINT_ONE(" Statistics...", "%s", 1); + + m = priv->up_time / 86400; + n = priv->up_time % 86400; + if (m) { + idx += sprintf(tmp, "%d day ", m); + print = 1; + } + m = n / 3600; + n = n % 3600; + if (m || print) { + idx += sprintf(tmp+idx, "%d hr ", m); + print = 1; + } + m = n / 60; + n = n % 60; + if (m || print) { + idx += sprintf(tmp+idx, "%d min ", m); + print = 1; + } + idx += sprintf(tmp+idx, "%d sec ", n); + PRINT_SINGL_ARG(" up_time: ", tmp, "%s"); +#if 0//def RTK_NL80211//survey_dump //eric-sync ?? + PRINT_SINGL_ARG(" chbusytime: ", priv->rtk->chbusytime, "%lu"); + PRINT_SINGL_ARG(" tx_time: ", priv->rtk->tx_time, "%lu"); + PRINT_SINGL_ARG(" rx_time: ", priv->rtk->rx_time, "%lu"); +#endif + PRINT_SINGL_ARG(" tx_packets: ", priv->net_stats.tx_packets, "%lu"); + PRINT_SINGL_ARG(" tx_bytes: ", priv->net_stats.tx_bytes, "%lu"); + PRINT_SINGL_ARG(" tx_retrys: ", priv->ext_stats.tx_retrys, "%lu"); + PRINT_SINGL_ARG(" tx_fails: ", priv->net_stats.tx_errors, "%lu"); + PRINT_SINGL_ARG(" tx_drops: ", priv->ext_stats.tx_drops, "%lu"); + PRINT_SINGL_ARG(" tx_dma_err: ", priv->pshare->tx_dma_err, "%lu"); + PRINT_SINGL_ARG(" rx_dma_err: ", priv->pshare->rx_dma_err, "%lu"); + PRINT_SINGL_ARG(" tx_dma_status: ", priv->pshare->tx_dma_status, "%lu"); + PRINT_SINGL_ARG(" rx_dma_status: ", priv->pshare->rx_dma_status, "%lu"); + + PRINT_SINGL_ARG(" rx_packets: ", priv->net_stats.rx_packets, "%lu"); + PRINT_SINGL_ARG(" rx_bytes: ", priv->net_stats.rx_bytes, "%lu"); + PRINT_SINGL_ARG(" rx_retrys: ", priv->ext_stats.rx_retrys, "%lu"); + PRINT_SINGL_ARG(" rx_crc_errors: ", priv->net_stats.rx_crc_errors, "%lu"); + PRINT_SINGL_ARG(" rx_errors: ", priv->net_stats.rx_errors, "%lu"); + PRINT_SINGL_ARG(" rx_data_drops: ", priv->ext_stats.rx_data_drops, "%lu"); + PRINT_SINGL_ARG(" rx_decache: ", priv->ext_stats.rx_decache, "%lu"); + PRINT_SINGL_ARG(" rx_fifoO: ", priv->ext_stats.rx_fifoO, "%lu"); + PRINT_SINGL_ARG(" rx_rdu: ", priv->ext_stats.rx_rdu, "%lu"); + PRINT_SINGL_ARG(" rx_reuse: ", priv->ext_stats.rx_reuse, "%lu"); + PRINT_SINGL_ARG(" beacon_ok: ", priv->ext_stats.beacon_ok, "%lu"); + PRINT_SINGL_ARG(" beacon_er: ", priv->ext_stats.beacon_er, "%lu"); + PRINT_SINGL_ARG(" beacon_dma_err:", priv->ext_stats.beacon_dma_err, "%lu"); + + PRINT_SINGL_ARG(" freeskb_err: ", priv->ext_stats.freeskb_err, "%lu"); +#ifdef CONFIG_PCI_HCI + PRINT_SINGL_ARG(" dz_queue_len: ", CIRC_CNT(priv->dz_queue.head, priv->dz_queue.tail, NUM_TXPKT_QUEUE), "%d"); +#endif + +#ifdef CHECK_HANGUP +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef CHECK_TX_HANGUP + PRINT_SINGL_ARG(" check_cnt_tx: ", priv->check_cnt_tx, "%d"); +#endif +#ifdef CHECK_FW_ERROR + PRINT_SINGL_ARG(" check_cnt_fw: ", priv->check_cnt_fw, "%d"); +#endif +#if defined(CHECK_RX_HANGUP) || defined(CHECK_RX_DMA_ERROR) + PRINT_SINGL_ARG(" check_cnt_rx: ", priv->check_cnt_rx, "%d"); +#endif +#ifdef CHECK_BEACON_HANGUP + PRINT_SINGL_ARG(" check_cnt_bcn: ", priv->check_cnt_bcn, "%d"); +#endif +#ifdef CHECK_AFTER_RESET + PRINT_SINGL_ARG(" check_cnt_rst: ", priv->check_cnt_rst, "%d"); +#endif + } +#endif + + + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ +#ifdef _DEBUG_RTL8192CD_ + PRINT_SINGL_ARG(" Reg 0xc50: ", RTL_R8(0xc50), "0x%02x"); + PRINT_SINGL_ARG(" Reg 0xc58: ", RTL_R8(0xc58), "0x%02x"); + PRINT_SINGL_ARG(" cck_FA_cnt: ", priv->pshare->cck_FA_cnt, "%d"); + PRINT_SINGL_ARG(" ofdm_FA_cnt1: ", priv->pshare->ofdm_FA_cnt1, "%d"); + PRINT_SINGL_ARG(" ofdm_FA_cnt2: ", priv->pshare->ofdm_FA_cnt2, "%d"); + PRINT_SINGL_ARG(" ofdm_FA_cnt3: ", priv->pshare->ofdm_FA_cnt3, "%d"); + PRINT_SINGL_ARG(" ofdm_FA_cnt4: ", priv->pshare->ofdm_FA_cnt4, "%d"); + PRINT_SINGL_ARG(" FA_total_cnt: ", priv->pshare->FA_total_cnt, "%d"); + //PRINT_SINGL_ARG(" f90[31:16]: ", priv->pshare->F90_cnt, "%d"); + PRINT_SINGL_ARG(" f94[31:16]: ", priv->pshare->F94_cnt, "%d"); + PRINT_SINGL_ARG(" f94OK[15:0]: ", priv->pshare->F94_cntOK, "%d"); + PRINT_SINGL_ARG(" 664[19:0]: ", priv->pshare->Reg664_cnt, "%d"); + PRINT_SINGL_ARG(" 664OK[19:0]: ", priv->pshare->Reg664_cntOK, "%d"); +#endif + PRINT_SINGL_ARG(" DNC_on: ", priv->pshare->DNC_on, "%d"); + PRINT_SINGL_ARG(" tp_avg_pre: ", priv->ext_stats.tp_average_pre, "%lu"); + } +#endif + +#if defined(CONFIG_RTL_92C_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL_92C) + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)){ + PRINT_SINGL_ARG(" FA_total_cnt: ", priv->pshare->FA_total_cnt, "%d"); + PRINT_SINGL_ARG(" DNC_on: ", (priv->pshare->DNC_on ? 1 : 0), "%d"); + PRINT_SINGL_ARG(" tp_avg_pre: ", priv->ext_stats.tp_average_pre, "%lu"); + } +#endif + + PRINT_SINGL_ARG(" reused_skb: ", priv->ext_stats.reused_skb, "%lu"); + +#ifdef CONFIG_RTL8190_PRIV_SKB + { + #ifdef CONCURRENT_MODE + extern int skb_free_num[]; + PRINT_SINGL_ARG(" skb_free_num: ", skb_free_num[priv->pshare->wlandev_idx]+priv->pshare->skb_queue.qlen, "%d"); + #else + extern int skb_free_num; + PRINT_SINGL_ARG(" skb_free_num: ", skb_free_num+priv->pshare->skb_queue.qlen, "%d"); + #endif + } +#else +#if !(defined(__ECOS) && defined(CONFIG_SDIO_HCI)) + PRINT_SINGL_ARG(" skb_free_num: ", priv->pshare->skb_queue.qlen, "%d"); +#endif +#endif +#ifdef CONFIG_PCI_HCI +#if defined(__ECOS) && defined(TX_PKT_FREE_QUEUE) + PRINT_SINGL_ARG(" tx_queue: ", info->tx_queue.qlen, "%d"); +#endif +#endif + PRINT_SINGL_ARG(" tx_avarage: ", priv->ext_stats.tx_avarage, "%lu"); + PRINT_SINGL_ARG(" rx_avarage: ", priv->ext_stats.rx_avarage, "%lu"); + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + PRINT_SINGL_ARG(" tx_peak: ", priv->ext_stats.tx_peak, "%lu"); + PRINT_SINGL_ARG(" rx_peak: ", priv->ext_stats.rx_peak, "%lu"); +#endif + + // avoid current_tx_rate change during the following process to cause out of range in MCS_DATA_RATEStr + current_rate = priv->pshare->current_tx_rate; +#ifdef RTK_AC_SUPPORT //vht rate , todo, dump vht rates in Mbps + if(current_rate >= VHT_RATE_ID){ + int tx_rate = VHT_MCS_DATA_RATE[priv->pshare->is_40m_bw][(priv->pshare->ht_current_tx_info&BIT(1))?1:0][(current_rate - VHT_RATE_ID)]; + tx_rate = tx_rate >> 1; + PRINT_ONE(" cur_tx_rate: VHT NSS", "%s", 0); + PRINT_ONE(((current_rate - VHT_RATE_ID)/10)+1, "%d", 0); + PRINT_ONE("-MCS", "%s", 0); + PRINT_ONE((current_rate - VHT_RATE_ID)%10, "%d", 0); + PRINT_ONE(tx_rate, " %d", 1); + } + else +#endif + if (is_MCS_rate(current_rate)) { + PRINT_ONE(" cur_tx_rate: MCS", "%s", 0); + PRINT_ONE((current_rate - HT_RATE_ID), "%d", 0); + rate = (unsigned char *)MCS_DATA_RATEStr[(priv->pshare->ht_current_tx_info&BIT(0))?1:0][(priv->pshare->ht_current_tx_info&BIT(1))?1:0][(current_rate - HT_RATE_ID)]; + PRINT_ONE(rate, " %s", 1); + } + else + { + PRINT_SINGL_ARG(" cur_tx_rate: ", current_rate/2, "%d"); + } +#ifdef PCIE_POWER_SAVING + PRINT_SINGL_ARG(" pcie pwr state: ", pwr_state_str[priv->pwr_state], "%s"); +#endif + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) { + PRINT_SINGL_ARG(" bkq_used_desc: ", (UINT)priv->use_txdesc_cnt[BK_QUEUE], "%d"); + PRINT_SINGL_ARG(" beq_used_desc: ", (UINT)priv->use_txdesc_cnt[BE_QUEUE], "%d"); + PRINT_SINGL_ARG(" viq_used_desc: ", (UINT)priv->use_txdesc_cnt[VI_QUEUE], "%d"); + PRINT_SINGL_ARG(" voq_used_desc: ", (UINT)priv->use_txdesc_cnt[VO_QUEUE], "%d"); + } +#endif + +#ifdef HS2_SUPPORT +/* Hotspot 2.0 Release 1 */ + PRINT_SINGL_ARG(" proxy arp: ", priv->proxy_arp, "%d"); + PRINT_SINGL_ARG(" dgaf_disable: ",priv->dgaf_disable, "%d"); + PRINT_SINGL_ARG(" IWLen: ",priv->pmib->hs2Entry.interworking_ielen, "%d"); +#endif + +#ifdef USE_TXQUEUE + if (GET_ROOT(priv)->pmib->miscEntry.use_txq) { + PRINT_SINGL_ARG(" txq_bk_num: ", (UINT)txq_len(&priv->pshare->txq_list[BK_QUEUE]), "%d"); + PRINT_SINGL_ARG(" txq_be_num: ", (UINT)txq_len(&priv->pshare->txq_list[BE_QUEUE]), "%d"); + PRINT_SINGL_ARG(" txq_vi_num: ", (UINT)txq_len(&priv->pshare->txq_list[VI_QUEUE]), "%d"); + PRINT_SINGL_ARG(" txq_vo_num: ", (UINT)txq_len(&priv->pshare->txq_list[VO_QUEUE]), "%d"); + } +#endif +#ifdef SW_TX_QUEUE + PRINT_SINGL_ARG(" swq enable: ", priv->swq_en, "%d"); +#endif + +#ifdef CONFIG_WLAN_HAL + PRINT_SINGL_ARG(" use hal: ", priv->pshare->use_hal, "%d"); +#endif +#ifdef USE_OUT_SRC + PRINT_SINGL_ARG(" use outsrc: ", priv->pshare->use_outsrc, "%d"); +#endif + +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + PRINT_SINGL_ARG(" tx_cnt_nosc: ", priv->ext_stats.tx_cnt_nosc, "%lu"); + PRINT_SINGL_ARG(" tx_cnt_sc1: ", priv->ext_stats.tx_cnt_sc1, "%lu"); + PRINT_SINGL_ARG(" tx_cnt_sc2: ", priv->ext_stats.tx_cnt_sc2, "%lu"); + PRINT_SINGL_ARG(" rx_cnt_nosc: ", priv->ext_stats.rx_cnt_nosc, "%lu"); + PRINT_SINGL_ARG(" rx_cnt_sc: ", priv->ext_stats.rx_cnt_sc, "%lu"); + PRINT_SINGL_ARG(" br_cnt_nosc: ", priv->ext_stats.br_cnt_nosc, "%lu"); + PRINT_SINGL_ARG(" br_cnt_sc: ", priv->ext_stats.br_cnt_sc, "%lu"); +#endif + + if(RTL_R8(0x1f)==0){ + PRINT_SINGL_ARG(" rf_lock: ", "true", "%s"); + }else{ + PRINT_SINGL_ARG(" rf_lock: ", "false", "%s"); + } + PRINT_SINGL_ARG(" IQK total count: ", priv->pshare->IQK_total_cnt, "%d"); + PRINT_SINGL_ARG(" IQK fail count: ", priv->pshare->IQK_fail_cnt, "%d"); + + if(ODMPTR->ConfigBBRF) + PRINT_SINGL_ARG(" Phy para Version: ", priv->pshare->PhyVersion, "%d"); + + PRINT_SINGL_ARG(" adaptivity_enable: ", priv->pshare->rf_ft_var.adaptivity_enable, "%d"); + if (priv->pshare->rf_ft_var.adaptivity_enable) + { + int adaptivity_status; + adaptivity_status = check_adaptivity_test(priv); + PRINT_SINGL_ARG(" adaptivity_status: ", adaptivity_status, "%d"); + PRINT_SINGL_ARG(" bcn_dont_ignore_edcca: ", priv->pshare->rf_ft_var.bcn_dont_ignore_edcca, "%d"); + } + + RESTORE_INT(flags); + + return pos; +} + +#ifdef __ECOS +void rtl8192cd_proc_stats_clear(void *data) +#else +static int rtl8192cd_proc_stats_clear(struct file *file, const char *buffer, + unsigned long count, void *data) +#endif +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + memset(&priv->net_stats, 0, sizeof(struct net_device_stats)); + memset(&priv->ext_stats, 0, sizeof(struct extra_stats)); +#ifdef CONFIG_RTK_MESH + memset(&priv->mesh_stats, 0, sizeof(struct net_device_stats)); +#endif +#ifdef _11s_TEST_MODE_ + memset(priv->rvTestPacket, 0, 3000); +#endif +#ifdef __KERNEL__ + return count; +#endif +} + + +#ifdef RF_FINETUNE +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_rfft(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_rfft(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; +#ifdef SUPPORT_TX_MCAST2UNI + int i; + int tmpbuf[64]; +#endif + + PRINT_ONE(" RF fine tune variables...", "%s", 1); + + PRINT_SINGL_ARG(" rssi: ", priv->pshare->rf_ft_var.rssi_dump, "%d"); + PRINT_SINGL_ARG(" rxfifoO: ", priv->pshare->rf_ft_var.rxfifoO, "%x"); + PRINT_SINGL_ARG(" raGoDownUpper: ", priv->pshare->rf_ft_var.raGoDownUpper, "%d"); + PRINT_SINGL_ARG(" raGoDown20MLower: ", priv->pshare->rf_ft_var.raGoDown20MLower, "%d"); + PRINT_SINGL_ARG(" raGoDown40MLower: ", priv->pshare->rf_ft_var.raGoDown40MLower, "%d"); + PRINT_SINGL_ARG(" raGoUpUpper: ", priv->pshare->rf_ft_var.raGoUpUpper, "%d"); + PRINT_SINGL_ARG(" raGoUp20MLower: ", priv->pshare->rf_ft_var.raGoUp20MLower, "%d"); + PRINT_SINGL_ARG(" raGoUp40MLower: ", priv->pshare->rf_ft_var.raGoUp40MLower, "%d"); + PRINT_SINGL_ARG(" dig_enable: ", priv->pshare->rf_ft_var.dig_enable, "%d"); + PRINT_SINGL_ARG(" digGoLowerLevel: ", priv->pshare->rf_ft_var.digGoLowerLevel, "%d"); + PRINT_SINGL_ARG(" digGoUpperLevel: ", priv->pshare->rf_ft_var.digGoUpperLevel, "%d"); + PRINT_SINGL_ARG(" rssiTx20MUpper: ", priv->pshare->rf_ft_var.rssiTx20MUpper, "%d"); + PRINT_SINGL_ARG(" rssiTx20MLower: ", priv->pshare->rf_ft_var.rssiTx20MLower, "%d"); + PRINT_SINGL_ARG(" rssi_expire_to: ", priv->pshare->rf_ft_var.rssi_expire_to, "%d"); + + PRINT_SINGL_ARG(" cck_pwr_max: ", priv->pshare->rf_ft_var.cck_pwr_max, "%d"); + PRINT_SINGL_ARG(" cck_tx_pathB: ", priv->pshare->rf_ft_var.cck_tx_pathB, "%d"); + + PRINT_SINGL_ARG(" tx_pwr_ctrl: ", priv->pshare->rf_ft_var.tx_pwr_ctrl, "%d"); + + // 11n ap AES debug + PRINT_SINGL_ARG(" aes_check_th: ", priv->pshare->rf_ft_var.aes_check_th, "%d KB"); + + // Tx power tracking + PRINT_SINGL_ARG(" tpt_period: ", priv->pshare->rf_ft_var.tpt_period, "%d"); + + // TXOP enlarge + PRINT_SINGL_ARG(" txop_enlarge_upper: ", priv->pshare->rf_ft_var.txop_enlarge_upper, "%d"); + PRINT_SINGL_ARG(" txop_enlarge_lower: ", priv->pshare->rf_ft_var.txop_enlarge_lower, "%d"); + + // 2.3G support + PRINT_SINGL_ARG(" frq_2_3G: ", priv->pshare->rf_ft_var.use_frq_2_3G, "%d"); + + //Support IP multicast->unicast +#ifdef SUPPORT_TX_MCAST2UNI + PRINT_SINGL_ARG(" mc2u_disable: ", priv->pshare->rf_ft_var.mc2u_disable, "%d"); + PRINT_SINGL_ARG(" mc2u_drop_unknown: ", priv->pshare->rf_ft_var.mc2u_drop_unknown, "%d"); + PRINT_SINGL_ARG(" mc2u_flood_ctrl: ", priv->pshare->rf_ft_var.mc2u_flood_ctrl, "%d"); + if(priv->pshare->rf_ft_var.mc2u_flood_ctrl) + { + PRINT_SINGL_ARG(" mc2u_flood_mac_num: ", priv->pshare->rf_ft_var.mc2u_flood_mac_num, "%d"); + for (i=0; i< priv->pshare->rf_ft_var.mc2u_flood_mac_num; i++) { + sprintf(tmpbuf, " mc2u_flood_mac[%d]: ", i); + PRINT_ARRAY_ARG(tmpbuf, priv->pshare->rf_ft_var.mc2u_flood_mac[i].macAddr, "%02x", 6); + } + } +#endif + +#ifdef HIGH_POWER_EXT_PA + PRINT_SINGL_ARG(" use_ext_pa: ", priv->pshare->rf_ft_var.use_ext_pa, "%d"); +#endif +#ifdef HIGH_POWER_EXT_LNA + PRINT_SINGL_ARG(" use_ext_lna: ", priv->pshare->rf_ft_var.use_ext_lna, "%d"); +#endif + PRINT_SINGL_ARG(" NDSi_support: ", priv->pshare->rf_ft_var.NDSi_support, "%d"); + PRINT_SINGL_ARG(" EDCCA threshold: ", priv->pshare->rf_ft_var.edcca_thd, "%d"); + PRINT_SINGL_ARG(" 1rcca: ", priv->pshare->rf_ft_var.one_path_cca, "%d"); + + return pos; +} +#endif + + +#ifdef GBWC +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_gbwc(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_gbwc(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0, i; + + PRINT_ONE(" miscGBWC...", "%s", 1); + + PRINT_SINGL_ARG(" GBWCMode: ", priv->pmib->gbwcEntry.GBWCMode, "%d"); + PRINT_SINGL_ARG(" GBWCThrd_tx: ", priv->pmib->gbwcEntry.GBWCThrd_tx, "%d kbps"); + PRINT_SINGL_ARG(" GBWCThrd_rx: ", priv->pmib->gbwcEntry.GBWCThrd_rx, "%d kbps"); + PRINT_ONE(" Address List:", "%s", 1); + for (i=0; ipmib->gbwcEntry.GBWCNum; i++) { + PRINT_ARRAY_ARG(" ", priv->pmib->gbwcEntry.GBWCAddr[i], "%02x", MACADDRLEN); + } + + return pos; +} +#endif + + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +#ifdef __ECOS +void rtl8192cd_proc_led(int flag, void *data) +#else +static int rtl8192cd_proc_led(struct file *file, const char *buffer, + unsigned long count, void *data) +#endif +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); +#ifdef __KERNEL__ + char tmpbuf[100]; + int flag; +#endif + +#ifdef __ECOS + if (flag == 0) // disable + control_wireless_led(priv, 0); + else if (flag == 1) // enable + control_wireless_led(priv, 1); + else if (flag == 2) // restore + control_wireless_led(priv, 2); + else + ecos_pr_fun("flag [%d] not supported!\n", flag); +#else + if (buffer && !copy_from_user(tmpbuf, buffer, count)) { + sscanf(tmpbuf, "%d", &flag); + if (flag == 0) // disable + control_wireless_led(priv, 0); + else if (flag == 1) // enable + control_wireless_led(priv, 1); + else if (flag == 2) // restore + control_wireless_led(priv, 2); + else + printk("flag [%d] not supported!\n", flag); + } + return count; +#endif +} + + +#ifdef RTL_MANUAL_EDCA +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_mib_edca(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_mib_edca(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + char *queue[] = {"", "BK", "BE", "VI", "VO"}; + + PRINT_SINGL_ARG(" Manually config EDCA : ", priv->pmib->dot11QosEntry.ManualEDCA, "%d"); + PRINT_ONE(" EDCA for AP...", "%s", 1); + PRINT_SINGL_ARG(" [BE]slot number (AIFS): ", priv->pmib->dot11QosEntry.AP_manualEDCA[BE].AIFSN, "%d"); + PRINT_SINGL_ARG(" Maximal contention window period: ", priv->pmib->dot11QosEntry.AP_manualEDCA[BE].ECWmax, "%d"); + PRINT_SINGL_ARG(" Minimal contention window period: ", priv->pmib->dot11QosEntry.AP_manualEDCA[BE].ECWmin, "%d"); + PRINT_SINGL_ARG(" TXOP limit: ", priv->pmib->dot11QosEntry.AP_manualEDCA[BE].TXOPlimit, "%d"); + PRINT_SINGL_ARG(" [BK]slot number (AIFS): ", priv->pmib->dot11QosEntry.AP_manualEDCA[BK].AIFSN, "%d"); + PRINT_SINGL_ARG(" Maximal contention window period: ", priv->pmib->dot11QosEntry.AP_manualEDCA[BK].ECWmax, "%d"); + PRINT_SINGL_ARG(" Minimal contention window period: ", priv->pmib->dot11QosEntry.AP_manualEDCA[BK].ECWmin, "%d"); + PRINT_SINGL_ARG(" TXOP limit: ", priv->pmib->dot11QosEntry.AP_manualEDCA[BK].TXOPlimit, "%d"); + PRINT_SINGL_ARG(" [VI]slot number (AIFS)= ", priv->pmib->dot11QosEntry.AP_manualEDCA[VI].AIFSN, "%d"); + PRINT_SINGL_ARG(" Maximal contention window period: ", priv->pmib->dot11QosEntry.AP_manualEDCA[VI].ECWmax, "%d"); + PRINT_SINGL_ARG(" Minimal contention window period: ", priv->pmib->dot11QosEntry.AP_manualEDCA[VI].ECWmin, "%d"); + PRINT_SINGL_ARG(" TXOP limit: ", priv->pmib->dot11QosEntry.AP_manualEDCA[VI].TXOPlimit, "%d"); + PRINT_SINGL_ARG(" [VO]slot number (AIFS): ", priv->pmib->dot11QosEntry.AP_manualEDCA[VO].AIFSN, "%d"); + PRINT_SINGL_ARG(" Maximal contention window period: ", priv->pmib->dot11QosEntry.AP_manualEDCA[VO].ECWmax, "%d"); + PRINT_SINGL_ARG(" Minimal contention window period: ", priv->pmib->dot11QosEntry.AP_manualEDCA[VO].ECWmin, "%d"); + PRINT_SINGL_ARG(" TXOP limit: ", priv->pmib->dot11QosEntry.AP_manualEDCA[VO].TXOPlimit, "%d"); + PRINT_ONE(" EDCA for Wireless client...", "%s", 1); + PRINT_SINGL_ARG(" [BE]ACM: ", priv->pmib->dot11QosEntry.STA_manualEDCA[BE].ACM, "%d"); + PRINT_SINGL_ARG(" slot number (AIFS): ", priv->pmib->dot11QosEntry.STA_manualEDCA[BE].AIFSN, "%d"); + PRINT_SINGL_ARG(" Maximal contention window period: ", priv->pmib->dot11QosEntry.STA_manualEDCA[BE].ECWmax, "%d"); + PRINT_SINGL_ARG(" Minimal contention window period: ", priv->pmib->dot11QosEntry.STA_manualEDCA[BE].ECWmin, "%d"); + PRINT_SINGL_ARG(" TXOP limit: ", priv->pmib->dot11QosEntry.STA_manualEDCA[BE].TXOPlimit, "%d"); + PRINT_SINGL_ARG(" [BK]ACM:", priv->pmib->dot11QosEntry.STA_manualEDCA[BK].ACM, "%d"); + PRINT_SINGL_ARG(" slot number (AIFS): ", priv->pmib->dot11QosEntry.STA_manualEDCA[BK].AIFSN, "%d"); + PRINT_SINGL_ARG(" Maximal contention window period: ", priv->pmib->dot11QosEntry.STA_manualEDCA[BK].ECWmax, "%d"); + PRINT_SINGL_ARG(" Minimal contention window period: ", priv->pmib->dot11QosEntry.STA_manualEDCA[BK].ECWmin, "%d"); + PRINT_SINGL_ARG(" TXOP limit: ", priv->pmib->dot11QosEntry.STA_manualEDCA[BK].TXOPlimit, "%d"); + PRINT_SINGL_ARG(" [VI]ACM: ", priv->pmib->dot11QosEntry.STA_manualEDCA[VI].ACM, "%d"); + PRINT_SINGL_ARG(" slot number (AIFS): ", priv->pmib->dot11QosEntry.STA_manualEDCA[VI].AIFSN, "%d"); + PRINT_SINGL_ARG(" Maximal contention window period: ", priv->pmib->dot11QosEntry.STA_manualEDCA[VI].ECWmax, "%d"); + PRINT_SINGL_ARG(" Minimal contention window period: ", priv->pmib->dot11QosEntry.STA_manualEDCA[VI].ECWmin, "%d"); + PRINT_SINGL_ARG(" TXOP limit:", priv->pmib->dot11QosEntry.STA_manualEDCA[VI].TXOPlimit, "%d"); + PRINT_SINGL_ARG(" [VO]ACM: ", priv->pmib->dot11QosEntry.STA_manualEDCA[VO].ACM, "%d"); + PRINT_SINGL_ARG(" slot number (AIFS): ", priv->pmib->dot11QosEntry.STA_manualEDCA[VO].AIFSN, "%d"); + PRINT_SINGL_ARG(" Maximal contention window period: ", priv->pmib->dot11QosEntry.STA_manualEDCA[VO].ECWmax, "%d"); + PRINT_SINGL_ARG(" Minimal contention window period: ", priv->pmib->dot11QosEntry.STA_manualEDCA[VO].ECWmin, "%d"); + PRINT_SINGL_ARG(" TXOP limit: ", priv->pmib->dot11QosEntry.STA_manualEDCA[VO].TXOPlimit, "%d"); + + PRINT_SINGL_ARG(" TID0 mapping: ", queue[priv->pmib->dot11QosEntry.TID_mapping[0]], "%s"); + PRINT_SINGL_ARG(" TID1 mapping: ", queue[priv->pmib->dot11QosEntry.TID_mapping[1]], "%s"); + PRINT_SINGL_ARG(" TID2 mapping: ", queue[priv->pmib->dot11QosEntry.TID_mapping[2]], "%s"); + PRINT_SINGL_ARG(" TID3 mapping: ", queue[priv->pmib->dot11QosEntry.TID_mapping[3]], "%s"); + PRINT_SINGL_ARG(" TID4 mapping: ", queue[priv->pmib->dot11QosEntry.TID_mapping[4]], "%s"); + PRINT_SINGL_ARG(" TID5 mapping: ", queue[priv->pmib->dot11QosEntry.TID_mapping[5]], "%s"); + PRINT_SINGL_ARG(" TID6 mapping: ", queue[priv->pmib->dot11QosEntry.TID_mapping[6]], "%s"); + PRINT_SINGL_ARG(" TID7 mapping: ", queue[priv->pmib->dot11QosEntry.TID_mapping[7]], "%s"); + + return pos; +} +#endif //RTL_MANUAL_EDCA + + +#ifdef TLN_STATS +#ifdef CONFIG_RTL_PROC_NEW +static int proc_wifi_conn_stats(struct seq_file *s, void *data) +#else +static int proc_wifi_conn_stats(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" Wifi Connection Stats...", "%s", 1); + + PRINT_SINGL_ARG(" Time Interval: ", priv->pshare->rf_ft_var.stats_time_interval, "%d"); + PRINT_SINGL_ARG(" Connected Clients: ", priv->wifi_stats.connected_sta, "%d"); + PRINT_SINGL_ARG(" MAX Clients: ", priv->wifi_stats.max_sta, "%d"); + PRINT_SINGL_ARG(" MAX Clients Timestamp: ", priv->wifi_stats.max_sta_timestamp, "%d"); + PRINT_SINGL_ARG(" Rejected clients: ", priv->wifi_stats.rejected_sta, "%d"); + + return pos; +} + + +static int proc_wifi_conn_stats_clear(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + memset(&priv->wifi_stats, 0, sizeof(struct tln_wifi_stats)); + return count; +} + +#ifdef CONFIG_RTL_PROC_NEW +static int proc_ext_wifi_conn_stats(struct seq_file *s, void *data) +#else +static int proc_ext_wifi_conn_stats(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + + PRINT_ONE(" Extended WiFi Connection Stats...", "%s", 1); + + PRINT_ONE(" Reject Reason/Status: Reject Count", "%s", 1); + PRINT_ONE(" =====================================================", "%s", 1); + PRINT_SINGL_ARG(" Unspecified reason: ", priv->ext_wifi_stats.rson_UNSPECIFIED_1, "%d"); + PRINT_SINGL_ARG(" Previous auth no longer valid: ", priv->ext_wifi_stats.rson_AUTH_INVALID_2, "%d"); + PRINT_SINGL_ARG(" Deauth because of leaving (or has left): ", priv->ext_wifi_stats.rson_DEAUTH_STA_LEAVING_3, "%d"); + PRINT_SINGL_ARG(" Disassoc due to inactivity: ", priv->ext_wifi_stats.rson_INACTIVITY_4, "%d"); + PRINT_SINGL_ARG(" Disassoc because AP cannot handle: ", priv->ext_wifi_stats.rson_RESOURCE_INSUFFICIENT_5, "%d"); + PRINT_SINGL_ARG(" Class 2 frame from non-auth STA: ", priv->ext_wifi_stats.rson_UNAUTH_CLS2FRAME_6, "%d"); + PRINT_SINGL_ARG(" Class 3 frame from non-assoc STA: ", priv->ext_wifi_stats.rson_UNAUTH_CLS3FRAME_7, "%d"); + PRINT_SINGL_ARG(" Disassoc because leaving (or has left): ", priv->ext_wifi_stats.rson_DISASSOC_STA_LEAVING_8, "%d"); + PRINT_SINGL_ARG(" STA request (re)assoc did not auth: ", priv->ext_wifi_stats.rson_ASSOC_BEFORE_AUTH_9, "%d"); + PRINT_SINGL_ARG(" Invalid IE: ", priv->ext_wifi_stats.rson_INVALID_IE_13, "%d"); + PRINT_SINGL_ARG(" MIC failure: ", priv->ext_wifi_stats.rson_MIC_FAILURE_14, "%d"); + PRINT_SINGL_ARG(" 4-Way Handshake timeout: ", priv->ext_wifi_stats.rson_4WAY_TIMEOUT_15, "%d"); + PRINT_SINGL_ARG(" Group Key Handshake timeout: ", priv->ext_wifi_stats.rson_GROUP_KEY_TIMEOUT_16, "%d"); + PRINT_SINGL_ARG(" IE in 4-Way Handshake different: ", priv->ext_wifi_stats.rson_DIFF_IE_17, "%d"); + PRINT_SINGL_ARG(" Invalid group cipher: ", priv->ext_wifi_stats.rson_MCAST_CIPHER_INVALID_18, "%d"); + PRINT_SINGL_ARG(" Invalid pairwise cipher: ", priv->ext_wifi_stats.rson_UCAST_CIPHER_INVALID_19, "%d"); + PRINT_SINGL_ARG(" Invalid AKMP: ", priv->ext_wifi_stats.rson_AKMP_INVALID_20, "%d"); + PRINT_SINGL_ARG(" Unsupported RSNIE version: ", priv->ext_wifi_stats.rson_UNSUPPORT_RSNIE_VER_21, "%d"); + PRINT_SINGL_ARG(" Invalid RSNIE capabilities: ", priv->ext_wifi_stats.rson_RSNIE_CAP_INVALID_22, "%d"); + PRINT_SINGL_ARG(" IEEE 802.1X auth failed: ", priv->ext_wifi_stats.rson_802_1X_AUTH_FAIL_23, "%d"); + PRINT_SINGL_ARG(" Reason out of scope of the device: ", priv->ext_wifi_stats.rson_OUT_OF_SCOPE, "%d"); + + PRINT_SINGL_ARG(" Unspecified failure: ", priv->ext_wifi_stats.status_FAILURE_1, "%d"); + PRINT_SINGL_ARG(" Cannot support all capabilities: ", priv->ext_wifi_stats.status_CAP_FAIL_10, "%d"); + PRINT_SINGL_ARG(" Reassoc denied due to cannot confirm assoc exists: ", priv->ext_wifi_stats.status_NO_ASSOC_11, "%d"); + PRINT_SINGL_ARG(" Assoc denied due to reason beyond: ", priv->ext_wifi_stats.status_OTHER_12, "%d"); + PRINT_SINGL_ARG(" Not support specified auth alg: ", priv->ext_wifi_stats.status_NOT_SUPPORT_ALG_13, "%d"); + PRINT_SINGL_ARG(" Auth seq out of expected: ", priv->ext_wifi_stats.status_OUT_OF_AUTH_SEQ_14, "%d"); + PRINT_SINGL_ARG(" Challenge failure: ", priv->ext_wifi_stats.status_CHALLENGE_FAIL_15, "%d"); + PRINT_SINGL_ARG(" Auth timeout: ", priv->ext_wifi_stats.status_AUTH_TIMEOUT_16, "%d"); + PRINT_SINGL_ARG(" Denied because AP cannot handle: ", priv->ext_wifi_stats.status_RESOURCE_INSUFFICIENT_17, "%d"); + PRINT_SINGL_ARG(" Denied because STA not support all rates: ", priv->ext_wifi_stats.status_RATE_FAIL_18, "%d"); + PRINT_SINGL_ARG(" Status out of scope of the device: ", priv->ext_wifi_stats.status_OUT_OF_SCOPE, "%d"); + + return pos; +} + + +static int proc_ext_wifi_conn_stats_clear(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + memset(&priv->ext_wifi_stats, 0, sizeof(struct tln_ext_wifi_stats)); + return count; +} +#endif + + +#if defined(RTLWIFINIC_GPIO_CONTROL) +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_gpio_ctrl_read(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_gpio_ctrl_read(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int pos = 0; + int i; + char tmp[16]; + + for (i=0; i<12; i++) { + if (priv->pshare->phw->GPIO_dir[i] == 0x01) { + sprintf(tmp, "GPIO%d %d", i, RTLWIFINIC_GPIO_read(i)); + PRINT_ONE(tmp, "%s", 1); + } + } + + return pos; +} + +#ifdef __ECOS +int rtl8192cd_proc_gpio_ctrl_write(char *command, int gpio_num, char *action, void *data) +#else +static int rtl8192cd_proc_gpio_ctrl_write(struct file *file, const char *buffer, + unsigned long count, void *data) +#endif +{ + struct net_device *dev = (struct net_device *)data; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); +#ifdef __ECOS + int direction, value, count=0; +#else + char tmp[32], command[8], action[4]; + unsigned int num, gpio_num, direction, value; +#endif + +#ifdef __ECOS + ecos_pr_fun("Command: [%s] gpio: [%d] action: [%s]\n", command, gpio_num, action); +#else + if (buffer && !copy_from_user(tmp, buffer, 32)) { + num = sscanf(tmp, "%s %d %s", command, &gpio_num, action); + + if (num != 3) { + panic_printk("Invalid gpio parameter! Failed!\n"); + return num; + } + } + panic_printk("Command: [%s] gpio: [%d] action: [%s]\n", command, gpio_num, action); +#endif + + if (!memcmp(command, "config", 6)) { + if (!memcmp(action, "r", 1)) + direction = 0x01; + else if (!memcmp(action, "w", 1)) + direction = 0x10; + else { +#ifdef __ECOS + ecos_pr_fun("Action not supported!\n"); +#else + panic_printk("Action not supported!\n"); +#endif + return count; + } + + if ((gpio_num >= 0) && (gpio_num <= 11)) + priv->pshare->phw->GPIO_dir[gpio_num] = direction; + else { +#ifdef __ECOS + ecos_pr_fun("GPIO pin not supported!\n"); +#else + panic_printk("GPIO pin not supported!\n"); +#endif + return count; + } + + RTLWIFINIC_GPIO_config(gpio_num, direction); + } + else if (!memcmp(command, "set", 3)) { + if (!memcmp(action, "0", 1)) + value = 0; + else if (!memcmp(action, "1", 1)) + value = 1; + else { +#ifdef __ECOS + ecos_pr_fun("Action not supported!\n"); +#else + panic_printk("Action not supported!\n"); +#endif + return count; + } + + if (((gpio_num >= 0) && (gpio_num <= 11)) && (priv->pshare->phw->GPIO_dir[gpio_num] == 0x10)) + RTLWIFINIC_GPIO_write(gpio_num, value); + else { +#ifdef __ECOS + ecos_pr_fun("GPIO pin not supported!\n"); +#else + panic_printk("GPIO pin not supported!\n"); +#endif + return count; + } + } + else { +#ifdef __ECOS + ecos_pr_fun("Command not supported!\n"); +#else + panic_printk("Command not supported!\n"); +#endif + } + + return count; +} +#endif + +#ifdef RTK_NL80211//openwrt_psd +#ifdef CONFIG_RTL_PROC_NEW +static int rtl8192cd_proc_psd_scan_read(struct seq_file *s, void *data) +#else +static int rtl8192cd_proc_psd_scan_read(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + + struct net_device *dev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + int pos=0; + int i, idx=0; + char tmp[200]; + int freq=0, p=0, dBm=0; + + memset(tmp, 0x0, sizeof(tmp)); + + idx += sprintf(tmp+idx, "CH %d ", priv->rtk->psd_fft_info[0]); + idx += sprintf(tmp+idx, "BW %dM ", priv->rtk->psd_fft_info[1]); + idx += sprintf(tmp+idx, "PTS %d ", priv->rtk->psd_fft_info[2]); + PRINT_SINGL_ARG("PSD SCAN: ", tmp, "%s"); + + idx=0; + memset(tmp, 0x0, sizeof(tmp)); + if(priv->rtk->psd_fft_info[0]<14) + freq = 2412+5*(priv->rtk->psd_fft_info[0]-1); + else + freq = 5180+5*(priv->rtk->psd_fft_info[0]-36); + + idx += sprintf(tmp+idx, "centeral %dMHz", freq); + idx += sprintf(tmp+idx, " from %dMHz to", (freq-20)); + idx += sprintf(tmp+idx, " %dMHz (per unit is 1.25MHz)", (freq+20)); + PRINT_SINGL_ARG("Channel Frequency: ", tmp, "%s"); + + idx=0; + memset(tmp, 0x0, sizeof(tmp)); + + //fix bandwidth=40 psd_pts=128 +#if 1 + for(i=0;i<(128/4);i++) + { + p = priv->rtk->psd_fft_info[16+i*4+0]+priv->rtk->psd_fft_info[16+i*4+1]+ + priv->rtk->psd_fft_info[16+i*4+2]+priv->rtk->psd_fft_info[16+i*4+3]; + + idx += sprintf(tmp+idx, "%4x ", p); + + if((i+1)%4 == 0) + { + PRINT_ONE(tmp, "%s", 1); + memset(tmp, 0x0, sizeof(tmp)); + idx=0; + } + } +#else + int size=priv->rtk->psd_fft_info[2]+16; + for (i=16; irtk->psd_fft_info[i]); + if((i+1)%16 == 0) + { + PRINT_ONE(tmp, "%s", 1); + memset(tmp, 0x0, 64); + idx=0; + } + } +#endif + return pos; +} + + +static int rtl8192cd_proc_psd_scan_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + +#ifdef CONFIG_RTL_PROC_NEW + struct net_device *dev = PDE_DATA(file_inode(file)); +#else + struct net_device *dev = (struct net_device *)data; +#endif + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + char tmp[32]; + unsigned int num, chnl, bw=40, pts=128;//fix bandwidth=40 scan_pts=128 + + if (buffer && !copy_from_user(tmp, buffer, 32)) { + //num = sscanf(tmp, "%d", &chnl, &bw, &pts); + num = sscanf(tmp, "%d", &chnl); + if (num != 1) { + panic_printk("Invalid psd scan parameter! Failed!\n"); + return count; + } + } + panic_printk("Channel: [%d] Bandwidth: [%d] PSD_PTS: [%d]\n", chnl, bw, pts); + + priv->rtk->psd_chnl = chnl; + priv->rtk->psd_bw = bw; + priv->rtk->psd_pts= pts; + + return count; +} +#endif + +#ifdef USE_OUT_SRC +static char *phydm_msg = NULL; +#define PHYDM_MSG_LEN 80*24 + +#ifdef CONFIG_RTL_PROC_NEW +static int proc_get_phydm_cmd(struct seq_file *s, void *v) +#else +static int proc_get_phydm_cmd(char *buf, char **start, off_t offset, + int length, int *eof, void *data) +#endif +{ + int len = 0; + off_t begin = 0; + off_t pos = 0; + struct net_device *netdev = PROC_GET_DEV(); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(netdev); + int size = 0; + char* token; +#ifdef CONFIG_RTL_PROC_NEW + +#else + if(offset != 0) + return offset; //to prevent this function is called over once +#endif + + if (GET_CHIP_VER(priv) < VERSION_8188E) { + panic_printk("RTL8192C and RTL8192D don't support this cmd\n"); + return -EFAULT; + } + + //allocate memory to phydm_msg + if (NULL == phydm_msg) { + phydm_msg = rtw_zmalloc(PHYDM_MSG_LEN); + if (NULL == phydm_msg) { + + return -EFAULT; + } + phydm_cmd(ODMPTR, NULL, 0, 0, phydm_msg, PHYDM_MSG_LEN); + } + + PRINT_ONE(phydm_msg, "%s", 1); //print phydm_smg to buf for proc file + size = pos; // size is for the length check macro CHECK_LEN + CHECK_LEN; //if phydm_msg is larger than length, it must be written in proc file several times + rtw_mfree(phydm_msg, PHYDM_MSG_LEN); //free memory + phydm_msg = NULL; + +#ifdef CONFIG_RTL_PROC_NEW + return 0; +#else +#ifdef __KERNEL__ + *eof = 1; +_ret: + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ +#endif + return len; +#endif + +} + +static int proc_set_phydm_cmd(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + +#ifdef CONFIG_RTL_PROC_NEW + struct net_device *dev = PDE_DATA(file_inode(file)); +#else + struct net_device *dev = (struct net_device *)data; +#endif + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + char tmp[64] = {0}; + int pos = 0; + + if (GET_CHIP_VER(priv) < VERSION_8188E) { + panic_printk("RTL8192C and RTL8192D don't support this cmd\n"); + return -EFAULT; + } + + if (count < 1) + return -EFAULT; + + if (count > sizeof(tmp)) + return -EFAULT; + + if (buffer && !copy_from_user(tmp, buffer, 64)) { //read cmd from proc file + if (NULL == phydm_msg) { + phydm_msg = rtw_zmalloc(PHYDM_MSG_LEN); + if (NULL == phydm_msg) + return -ENOMEM; + } + else { + memset(phydm_msg, 0, PHYDM_MSG_LEN); + } + phydm_cmd(ODMPTR, tmp, count, 1, phydm_msg, PHYDM_MSG_LEN); + if (strlen(phydm_msg) == 0) { + rtw_mfree(phydm_msg, PHYDM_MSG_LEN); + phydm_msg = NULL; + } + } + return count; +} +#endif + +#ifdef CONFIG_RTL_PROC_NEW + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_all); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_rf); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_operation); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_staconfig); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_dkeytbl); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_auth); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_gkeytbl); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_bssdesc); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_stainfo); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_sta_keyinfo); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_sta_queinfo); +#endif + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_sta_dbginfo); + RTK_DECLARE_READ_WRITE_PROC_FOPS(rtl8192cd_proc_stats, rtl8192cd_proc_stats_clear); + + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_erp); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_probe_info); + +#ifdef HS2_SUPPORT + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_hs2); +#endif +#ifdef WDS + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_wds); +#endif + +#ifdef RTK_BR_EXT + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_brext); +#endif + +#ifdef DFS + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_DFS); +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_rf_ac); +#endif + + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_misc); + +#ifdef WIFI_SIMPLE_CONFIG + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_wsc); +#endif + +#ifdef GBWC + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_gbwc); +#endif + + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_11n); + +#ifdef RTL_MANUAL_EDCA + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_edca); +#endif +#ifdef CONFIG_RTK_VLAN_SUPPORT + RTK_DECLARE_READ_WRITE_PROC_FOPS(rtl8192cd_proc_vlan_read, rtl8192cd_proc_vlan_write); +#endif +#ifdef SUPPORT_MULTI_PROFILE + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mib_ap_profile); +#endif + +#ifdef CONFIG_PCI_HCI + RTK_DECLARE_READ_WRITE_PROC_FOPS(rtl8192cd_proc_txdesc_info, rtl8192cd_proc_txdesc_idx_write); +#endif +#ifdef CLIENT_MODE + RTK_DECLARE_READ_WRITE_PROC_FOPS(rtl8192cd_proc_up_read, rtl8192cd_proc_up_write); +#endif + +#if defined(CONFIG_PCI_HCI) + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_rxdesc_info); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_desc_info); +#endif +#ifdef CONFIG_USB_HCI + RTK_DECLARE_READ_WRITE_PROC_FOPS(rtl8192cd_proc_txurb_info, rtl8192cd_proc_txurb_info_idx_write); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_que_info); +#endif +#ifdef CONFIG_SDIO_HCI + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_que_info); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_sdio_dbginfo); +#endif + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_buf_info); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_cam_info); +#ifdef MULTI_MAC_CLONE + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mbidcam_info); + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_mstainfo); +#endif +#ifdef ENABLE_RTL_SKB_STATS + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_skb_info); +#endif +#ifdef RF_FINETUNE + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_rfft); +#endif + RTK_DECLARE_WRITE_PROC_FOPS(rtl8192cd_proc_led); +#ifdef AUTO_TEST_SUPPORT + RTK_DECLARE_READ_PROC_FOPS(rtl8192cd_proc_SSR_read); +#endif +#if defined(RTLWIFINIC_GPIO_CONTROL) + RTK_DECLARE_READ_WRITE_PROC_FOPS(rtl8192cd_proc_gpio_ctrl_read, rtl8192cd_proc_gpio_ctrl_write); +#endif +#ifdef CONFIG_RTL_WLAN_STATUS + RTK_DECLARE_READ_WRITE_PROC_FOPS(rtl8192cd_proc_up_event_read, rtl8192cd_proc_up_event_write); +#endif + +#ifdef CONFIG_RTK_MESH +#ifdef MESH_BOOTSEQ_AUTH + RTK_DECLARE_READ_PROC_FOPS(mesh_auth_mpinfo); +#endif + RTK_DECLARE_READ_PROC_FOPS(mesh_unEstablish_mpinfo); + RTK_DECLARE_READ_PROC_FOPS(mesh_assoc_mpinfo); + RTK_DECLARE_READ_PROC_FOPS(mesh_stats); + + // 6 line for Throughput statistics (sounder) + RTK_DECLARE_READ_WRITE_PROC_FOPS(mesh_proc_flow_stats,mesh_proc_flow_stats_write); + + RTK_DECLARE_READ_PROC_FOPS(mesh_pathsel_routetable_info); + RTK_DECLARE_READ_PROC_FOPS(mesh_proxy_table_info); + RTK_DECLARE_READ_PROC_FOPS(mesh_portal_table_info); + RTK_DECLARE_READ_PROC_FOPS(mesh_root_info); + +#ifdef MESH_USE_METRICOP + // change metric method + RTK_DECLARE_READ_WRITE_PROC_FOPS(mesh_metric_r, mesh_metric_w); +#endif + +#if DBG_NCTU_MESH + RTK_DECLARE_READ_PROC_FOPS(mesh_showAllSkbs); + RTK_DECLARE_WRITE_PROC_FOPS(mesh_setDebugLevel); +#endif +#ifdef _MESH_DEBUG_ + RTK_DECLARE_READ_PROC_FOPS(mesh_proc_clear_table); + RTK_DECLARE_READ_PROC_FOPS(mesh_proc_issueAuthReq); +#ifdef MESH_BOOTSEQ_AUTH + RTK_DECLARE_READ_PROC_FOPS(mesh_proc_issueAuthRsp); + RTK_DECLARE_READ_PROC_FOPS(mesh_proc_issueDeAuth); +#endif + RTK_DECLARE_READ_PROC_FOPS(mesh_proc_openConnect); + RTK_DECLARE_READ_PROC_FOPS(mesh_proc_issueOpen); + RTK_DECLARE_READ_PROC_FOPS(mesh_proc_issueConfirm); + RTK_DECLARE_READ_PROC_FOPS(mesh_proc_issueClose); + RTK_DECLARE_READ_PROC_FOPS(mesh_proc_closeConnect); + RTK_DECLARE_WRITE_PROC_FOPS(mesh_setMACAddr); + +#if (MESH_DBG_LV & MESH_DBG_COMPLEX) + RTK_DECLARE_READ_WRITE_PROC_FOPS(mesh_test_sme_proc_read, mesh_test_sme_proc_write); +#endif // (MESH_DBG_LV & MESH_DBG_COMPLEX) +#endif // _MESH_DEBUG_ +#endif // CONFIG_RTK_MESH + +#ifdef RTK_NL80211 + RTK_DECLARE_READ_WRITE_PROC_FOPS(rtl8192cd_proc_psd_scan_read, rtl8192cd_proc_psd_scan_write); +#endif +#ifdef USE_OUT_SRC + RTK_DECLARE_READ_WRITE_PROC_FOPS( proc_get_phydm_cmd, proc_set_phydm_cmd); +#endif +#endif // CONFIG_RTL_PROC_NEW + +#ifdef __KERNEL__ +void MDL_DEVINIT rtl8192cd_proc_init(struct net_device *dev) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct proc_dir_entry *rtl8192cd_proc_root = NULL ; + struct proc_dir_entry *p; + + rtl8192cd_proc_root = proc_mkdir(dev->name, NULL); + priv->proc_root = rtl8192cd_proc_root ; + if (rtl8192cd_proc_root == NULL) { + printk("create proc root failed!\n"); + return; + } + + //panic_printk("\n\n\ndev=%x\n\n\n",dev); + RTK_CREATE_PROC_READ_ENTRY(p, "mib_all", rtl8192cd_proc_mib_all); + +#ifdef CONFIG_ARCH_LUNA_SLAVE + RTK_CREATE_PROC_READ_ENTRY(p, "mib_rf", rtl8192cd_proc_mib_rf); + p->size = 0x1000; + RTK_CREATE_PROC_READ_ENTRY(p, "mib_operation", rtl8192cd_proc_mib_operation); + p->size = 0x1000; + RTK_CREATE_PROC_READ_ENTRY(p, "mib_staconfig", rtl8192cd_proc_mib_staconfig); + p->size = 0x1000; + RTK_CREATE_PROC_READ_ENTRY(p, "mib_dkeytbl", rtl8192cd_proc_mib_dkeytbl); + p->size = 0x1000; + RTK_CREATE_PROC_READ_ENTRY(p, "mib_auth", rtl8192cd_proc_mib_auth); + p->size = 0x1000; + RTK_CREATE_PROC_READ_ENTRY(p, "mib_gkeytbl", rtl8192cd_proc_mib_gkeytbl); + p->size = 0x1000; + RTK_CREATE_PROC_READ_ENTRY(p, "mib_bssdesc", rtl8192cd_proc_mib_bssdesc); + p->size = 0x1000; + RTK_CREATE_PROC_READ_ENTRY(p, "sta_info", rtl8192cd_proc_stainfo); + p->size = 0x3000; + RTK_CREATE_PROC_READ_ENTRY(p, "sta_keyinfo", rtl8192cd_proc_sta_keyinfo); + p->size = 0x1000; + RTK_CREATE_PROC_READ_ENTRY(p, "sta_dbginfo", rtl8192cd_proc_sta_dbginfo); + p->size = 0x3000; + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "stats", rtl8192cd_proc_stats, rtl8192cd_proc_stats_clear); + p->size = 0x1000; + RTK_CREATE_PROC_READ_ENTRY(p, "mib_erp", rtl8192cd_proc_mib_erp); + p->size = 0x1000; + +#ifdef WDS + RTK_CREATE_PROC_READ_ENTRY(p, "mib_wds", rtl8192cd_proc_mib_wds); + p->size = 0x1000; +#endif + +#ifdef RTK_BR_EXT + RTK_CREATE_PROC_READ_ENTRY(p, "mib_brext", rtl8192cd_proc_mib_brext); + p->size = 0x1000; +#endif + +#ifdef DFS + RTK_CREATE_PROC_READ_ENTRY(p, "mib_dfs", rtl8192cd_proc_mib_DFS); + p->size = 0x1000; +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + RTK_CREATE_PROC_READ_ENTRY(p, "mib_rf_ac", rtl8192cd_proc_mib_rf_ac); + p->size = 0x1000; +#endif + RTK_CREATE_PROC_READ_ENTRY(p, "mib_misc", rtl8192cd_proc_mib_misc); + p->size = 0x1000; +#ifdef WIFI_SIMPLE_CONFIG + RTK_CREATE_PROC_READ_ENTRY(p, "mib_wsc", rtl8192cd_proc_mib_wsc); + p->size = 0x1000; +#endif + +#ifdef GBWC + RTK_CREATE_PROC_READ_ENTRY(p, "mib_gbwc", rtl8192cd_proc_mib_gbwc); + p->size = 0x1000; +#endif + + RTK_CREATE_PROC_READ_ENTRY(p, "mib_11n", rtl8192cd_proc_mib_11n); + p->size = 0x1000; + +#else//CONFIG_ARCH_LUNA_SLAVE + + RTK_CREATE_PROC_READ_ENTRY(p, "mib_rf", rtl8192cd_proc_mib_rf); + RTK_CREATE_PROC_READ_ENTRY(p, "mib_operation", rtl8192cd_proc_mib_operation); + RTK_CREATE_PROC_READ_ENTRY(p, "mib_staconfig", rtl8192cd_proc_mib_staconfig); + RTK_CREATE_PROC_READ_ENTRY(p, "mib_dkeytbl", rtl8192cd_proc_mib_dkeytbl); + RTK_CREATE_PROC_READ_ENTRY(p, "mib_auth", rtl8192cd_proc_mib_auth); + RTK_CREATE_PROC_READ_ENTRY(p, "mib_gkeytbl", rtl8192cd_proc_mib_gkeytbl); + RTK_CREATE_PROC_READ_ENTRY(p, "mib_bssdesc", rtl8192cd_proc_mib_bssdesc); + RTK_CREATE_PROC_READ_ENTRY(p, "sta_info", rtl8192cd_proc_stainfo); + RTK_CREATE_PROC_READ_ENTRY(p, "sta_keyinfo", rtl8192cd_proc_sta_keyinfo); + + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + RTK_CREATE_PROC_READ_ENTRY(p, "sta_queinfo", rtl8192cd_proc_sta_queinfo); +#endif + RTK_CREATE_PROC_READ_ENTRY(p, "sta_dbginfo", rtl8192cd_proc_sta_dbginfo); + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "stats", rtl8192cd_proc_stats, rtl8192cd_proc_stats_clear); + RTK_CREATE_PROC_READ_ENTRY(p, "mib_erp", rtl8192cd_proc_mib_erp); + + RTK_CREATE_PROC_READ_ENTRY(p, "probe_info", rtl8192cd_proc_probe_info); +#ifdef HS2_SUPPORT + RTK_CREATE_PROC_READ_ENTRY(p, "mib_hs2", rtl8192cd_proc_mib_hs2); +#endif +#ifdef WDS + RTK_CREATE_PROC_READ_ENTRY(p, "mib_wds", rtl8192cd_proc_mib_wds); +#endif + +#ifdef RTK_BR_EXT + RTK_CREATE_PROC_READ_ENTRY(p, "mib_brext", rtl8192cd_proc_mib_brext); +#endif + +#ifdef DFS + RTK_CREATE_PROC_READ_ENTRY(p, "mib_dfs", rtl8192cd_proc_mib_DFS); +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + RTK_CREATE_PROC_READ_ENTRY(p, "mib_rf_ac", rtl8192cd_proc_mib_rf_ac); +#endif + + RTK_CREATE_PROC_READ_ENTRY(p, "mib_misc", rtl8192cd_proc_mib_misc); + +#ifdef WIFI_SIMPLE_CONFIG + RTK_CREATE_PROC_READ_ENTRY(p, "mib_wsc", rtl8192cd_proc_mib_wsc); +#endif + +#ifdef GBWC + RTK_CREATE_PROC_READ_ENTRY(p, "mib_gbwc", rtl8192cd_proc_mib_gbwc); +#endif + + RTK_CREATE_PROC_READ_ENTRY(p, "mib_11n", rtl8192cd_proc_mib_11n); +#endif//CONFIG_ARCH_LUNA_SLAVE + +#ifdef RTL_MANUAL_EDCA + RTK_CREATE_PROC_READ_ENTRY(p, "mib_EDCA", rtl8192cd_proc_mib_edca); +#endif + +#ifdef CONFIG_RTK_VLAN_SUPPORT + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "mib_vlan", rtl8192cd_proc_vlan_read, rtl8192cd_proc_vlan_write); +#endif + +#ifdef TLN_STATS + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "wifi_conn_stats", proc_wifi_conn_stats, proc_wifi_conn_stats_clear); + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "ext_wifi_conn_stats", proc_ext_wifi_conn_stats, proc_ext_wifi_conn_stats_clear); +#endif + +#ifdef CONFIG_ARCH_LUNA_SLAVE +#ifdef SUPPORT_MULTI_PROFILE + RTK_CREATE_PROC_READ_ENTRY(p, "mib_ap_profile", rtl8192cd_proc_mib_ap_profile); +#ifdef CONFIG_ARCH_LUNA_SLAVE + p->size = 0x1000; +#endif +#endif +#else +#ifdef SUPPORT_MULTI_PROFILE + RTK_CREATE_PROC_READ_ENTRY(p, "mib_ap_profile", rtl8192cd_proc_mib_ap_profile); +#endif +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) // is root interface +#endif + { +#ifdef CONFIG_PCI_HCI + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "txdesc", rtl8192cd_proc_txdesc_info, rtl8192cd_proc_txdesc_idx_write); +#endif // CONFIG_PCI_HCI + +#ifdef CLIENT_MODE + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "up_flag", rtl8192cd_proc_up_read, rtl8192cd_proc_up_write); +#endif + +#if defined(CONFIG_PCI_HCI) + RTK_CREATE_PROC_READ_ENTRY(p, "rxdesc", rtl8192cd_proc_rxdesc_info); + RTK_CREATE_PROC_READ_ENTRY(p, "desc_info", rtl8192cd_proc_desc_info); +#elif defined(CONFIG_USB_HCI) + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "txurb", rtl8192cd_proc_txurb_info, rtl8192cd_proc_txurb_info_idx_write); + RTK_CREATE_PROC_READ_ENTRY(p, "que_info", rtl8192cd_proc_que_info); +#elif defined(CONFIG_SDIO_HCI) + RTK_CREATE_PROC_READ_ENTRY(p, "que_info", rtl8192cd_proc_que_info); + RTK_CREATE_PROC_READ_ENTRY(p, "sdio_dbginfo", rtl8192cd_proc_sdio_dbginfo); +#endif + RTK_CREATE_PROC_READ_ENTRY(p, "buf_info", rtl8192cd_proc_buf_info); + RTK_CREATE_PROC_READ_ENTRY(p, "cam_info", rtl8192cd_proc_cam_info); +#ifdef MULTI_MAC_CLONE + RTK_CREATE_PROC_READ_ENTRY(p, "mbidcam_info", rtl8192cd_proc_mbidcam_info); + RTK_CREATE_PROC_READ_ENTRY(p, "msta_info", rtl8192cd_proc_mstainfo); +#endif + +#ifdef ENABLE_RTL_SKB_STATS + RTK_CREATE_PROC_READ_ENTRY(p, "skb_info", rtl8192cd_proc_skb_info); +#endif + +#ifdef RF_FINETUNE + RTK_CREATE_PROC_READ_ENTRY(p, "rf_finetune", rtl8192cd_proc_rfft); +#endif + +#ifdef CONFIG_RTL_92C_SUPPORT +#ifndef CONFIG_RTL_PROC_NEW + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "phypara_file", rtl8192cd_proc_phypara_file_read, rtl8192cd_proc_phypara_file_write); + } +#endif +#endif // CONFIG_RTL_92C_SUPPORT + + RTK_CREATE_PROC_WRITE_ENTRY(p, "led", rtl8192cd_proc_led); + +#ifdef AUTO_TEST_SUPPORT + RTK_CREATE_PROC_READ_ENTRY(p, "SS_Result", rtl8192cd_proc_SSR_read); +#endif + +#if defined(RTLWIFINIC_GPIO_CONTROL) + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "gpio_ctrl", rtl8192cd_proc_gpio_ctrl_read, rtl8192cd_proc_gpio_ctrl_write); + #ifdef CONFIG_ARCH_LUNA_SLAVE + p->size = 0x10; + #endif + RTLWIFINIC_GPIO_init_priv(priv); +#endif + } + +#ifdef WLANHAL_MACDM + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "macdm", rtl8192cd_proc_macdm, rtl8192cd_proc_macdm_write); +#endif //WLANHAL_MACDM + +#ifdef CONFIG_RTL_WLAN_STATUS + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "up_event", rtl8192cd_proc_up_event_read, rtl8192cd_proc_up_event_write); +#endif + +#ifdef CONFIG_RTK_MESH +#ifdef MESH_BOOTSEQ_AUTH + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_auth_mpinfo", mesh_auth_mpinfo); +#endif + + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_unestablish_mpinfo", mesh_unEstablish_mpinfo); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_assoc_mpinfo", mesh_assoc_mpinfo); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_stats", mesh_stats); + + // 6 line for Throughput statistics (sounder) + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "flow_stats", mesh_proc_flow_stats, mesh_proc_flow_stats_write); + + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_pathsel_routetable", mesh_pathsel_routetable_info); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_proxy_table", mesh_proxy_table_info); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_portal_table", mesh_portal_table_info); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_root_info", mesh_root_info); + +#ifdef MESH_USE_METRICOP + { // change metric method + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "mesh_metric", mesh_metric_r, mesh_metric_w); + } +#endif + +#if DBG_NCTU_MESH + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_skb", mesh_showAllSkbs); + RTK_CREATE_PROC_WRITE_ENTRY(p, "mesh_dbg", mesh_setDebugLevel); +#endif +#ifdef _MESH_DEBUG_ + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_clearalltable", mesh_proc_clear_table); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_issueauthreq", mesh_proc_issueAuthReq); + +#ifdef MESH_BOOTSEQ_AUTH + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_issueauthrsp", mesh_proc_issueAuthRsp); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_issuedeauth", mesh_proc_issueDeAuth); +#endif + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_openconnect", mesh_proc_openConnect); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_issueopen", mesh_proc_issueOpen); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_issueconfirm", mesh_proc_issueConfirm); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_issueclose", mesh_proc_issueClose); + RTK_CREATE_PROC_READ_ENTRY(p, "mesh_closeconnect", mesh_proc_closeConnect); + RTK_CREATE_PROC_WRITE_ENTRY(p, "mesh_setmacaddr", mesh_setMACAddr); + + +#if (MESH_DBG_LV & MESH_DBG_COMPLEX) + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, MESH_PROC_SME_TEST_FILENAME, mesh_test_sme_proc_read, mesh_test_sme_proc_write); + + /*{ + struct proc_dir_entry *proc_file; + + proc_file = create_proc_entry(MESH_PROC_FILENAME, 0644, rtl8192cd_proc_root); + if(proc_file == NULL) { + printk("can't create proc: %s\r\n", MESH_PROC_FILENAME); + return; + } + proc_file->read_proc = mesh_proc_read; + proc_file->write_proc = mesh_proc_write; + }*/ +#endif // (MESH_DBG_LV & MESH_DBG_COMPLEX) +#endif // _MESH_DEBUG_ +#endif // CONFIG_RTK_MESH + + +#ifdef RTK_NL80211 + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "psd_scan", rtl8192cd_proc_psd_scan_read, rtl8192cd_proc_psd_scan_write); +#endif +#ifdef USE_OUT_SRC + RTK_CREATE_PROC_READ_WRITE_ENTRY(p, "cmd", proc_get_phydm_cmd, proc_set_phydm_cmd); +#endif +} + + +void /*__devexit*/MDL_EXIT rtl8192cd_proc_remove (struct net_device *dev) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct proc_dir_entry *rtl8192cd_proc_root = priv->proc_root; + + if (rtl8192cd_proc_root != NULL) { + remove_proc_entry( "mib_all", rtl8192cd_proc_root ); + remove_proc_entry( "mib_rf", rtl8192cd_proc_root ); + remove_proc_entry( "mib_operation", rtl8192cd_proc_root ); + remove_proc_entry( "mib_staconfig", rtl8192cd_proc_root ); + remove_proc_entry( "mib_dkeytbl", rtl8192cd_proc_root ); + remove_proc_entry( "mib_auth", rtl8192cd_proc_root ); + remove_proc_entry( "mib_gkeytbl", rtl8192cd_proc_root ); + remove_proc_entry( "mib_bssdesc", rtl8192cd_proc_root ); + remove_proc_entry( "sta_info", rtl8192cd_proc_root ); + remove_proc_entry( "sta_keyinfo", rtl8192cd_proc_root ); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + remove_proc_entry( "sta_queinfo", rtl8192cd_proc_root ); +#endif + remove_proc_entry( "sta_dbginfo", rtl8192cd_proc_root ); + remove_proc_entry( "stats", rtl8192cd_proc_root ); + remove_proc_entry( "mib_erp", rtl8192cd_proc_root ); + remove_proc_entry( "probe_info", rtl8192cd_proc_root ); + +#ifdef WDS + remove_proc_entry( "mib_wds", rtl8192cd_proc_root ); +#endif + +#ifdef RTK_BR_EXT + remove_proc_entry( "mib_brext", rtl8192cd_proc_root ); +#endif + + +#ifdef DFS + remove_proc_entry( "mib_dfs", rtl8192cd_proc_root ); +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + remove_proc_entry( "mib_rf_ac", rtl8192cd_proc_root ); +#endif + + remove_proc_entry( "mib_misc", rtl8192cd_proc_root ); + +#ifdef WIFI_SIMPLE_CONFIG + remove_proc_entry( "mib_wsc", rtl8192cd_proc_root ); +#endif + + +#ifdef GBWC + remove_proc_entry( "mib_gbwc", rtl8192cd_proc_root ); +#endif + + remove_proc_entry( "mib_11n", rtl8192cd_proc_root ); + +#ifdef RTL_MANUAL_EDCA + remove_proc_entry( "mib_EDCA", rtl8192cd_proc_root ); +#endif +#ifdef CONFIG_RTK_VLAN_SUPPORT + remove_proc_entry( "mib_vlan", rtl8192cd_proc_root ); +#endif + +#ifdef TLN_STATS + remove_proc_entry( "wifi_conn_stats", rtl8192cd_proc_root ); + remove_proc_entry( "ext_wifi_conn_stats", rtl8192cd_proc_root ); +#endif + +#ifdef SUPPORT_MULTI_PROFILE + remove_proc_entry( "mib_ap_profile", rtl8192cd_proc_root ); +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) // is root interface +#endif + { +#if defined(CONFIG_PCI_HCI) + remove_proc_entry( "txdesc", rtl8192cd_proc_root ); + remove_proc_entry( "rxdesc", rtl8192cd_proc_root ); + remove_proc_entry( "desc_info", rtl8192cd_proc_root ); +#elif defined(CONFIG_USB_HCI) + remove_proc_entry( "txurb", rtl8192cd_proc_root ); + remove_proc_entry( "que_info", rtl8192cd_proc_root ); +#elif defined(CONFIG_SDIO_HCI) + remove_proc_entry( "que_info", rtl8192cd_proc_root ); + remove_proc_entry( "sdio_dbginfo", rtl8192cd_proc_root ); +#endif + remove_proc_entry( "buf_info", rtl8192cd_proc_root ); + remove_proc_entry( "cam_info", rtl8192cd_proc_root ); +#ifdef MULTI_MAC_CLONE + remove_proc_entry( "mbidcam_info", rtl8192cd_proc_root ); + remove_proc_entry( "msta_info", rtl8192cd_proc_root ); +#endif +#ifdef ENABLE_RTL_SKB_STATS + remove_proc_entry( "skb_info", rtl8192cd_proc_root ); +#endif +#ifdef RF_FINETUNE + remove_proc_entry( "rf_finetune", rtl8192cd_proc_root ); +#endif +#ifdef CLIENT_MODE + remove_proc_entry( "up_flag", rtl8192cd_proc_root ); +#endif +#ifdef CONFIG_RTL_92C_SUPPORT +#ifndef CONFIG_RTL_PROC_NEW + if ((GET_CHIP_VER(priv) == VERSION_8192C) || (GET_CHIP_VER(priv) == VERSION_8188C)) { + remove_proc_entry( "phypara_file", rtl8192cd_proc_root ); + } +#endif +#endif + remove_proc_entry( "led", rtl8192cd_proc_root ); + +#ifdef AUTO_TEST_SUPPORT + remove_proc_entry( "SS_Result", rtl8192cd_proc_root ); +#endif +#ifdef RTLWIFINIC_GPIO_CONTROL + remove_proc_entry( "gpio_ctrl", rtl8192cd_proc_root ); +#endif + } + +#ifdef CONFIG_RTL_WLAN_STATUS + remove_proc_entry( "up_event", rtl8192cd_proc_root ); +#endif + +#ifdef CONFIG_RTK_MESH +#ifdef MESH_BOOTSEQ_AUTH + remove_proc_entry( "mesh_auth_mpinfo", rtl8192cd_proc_root ); +#endif + remove_proc_entry( "mesh_unestablish_mpinfo", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_assoc_mpinfo", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_stats", rtl8192cd_proc_root ); + remove_proc_entry( "flow_stats", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_pathsel_routetable", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_proxy_table", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_root_info", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_vlan_info", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_portal_table", rtl8192cd_proc_root ); + +#ifdef MESH_USE_METRICOP // remove proc file + remove_proc_entry( "mesh_metric", rtl8192cd_proc_root ); +#endif + +#if DBG_NCTU_MESH + remove_proc_entry( "mesh_skb", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_dbg", rtl8192cd_proc_root ); +#endif +#ifdef _MESH_DEBUG_ + remove_proc_entry( "mesh_clearalltable", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_setmacaddr", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_issueauthreq", rtl8192cd_proc_root ); +#ifdef MESH_BOOTSEQ_AUTH + remove_proc_entry( "mesh_issueauthrsp", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_issuedeauth", rtl8192cd_proc_root ); +#endif + remove_proc_entry( "mesh_openconnect", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_issueopen", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_issueconfirm", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_issueclose", rtl8192cd_proc_root ); + remove_proc_entry( "mesh_closeconnect", rtl8192cd_proc_root ); +#if (MESH_DBG_LV & MESH_DBG_COMPLEX) + remove_proc_entry( MESH_PROC_SME_TEST_FILENAME, rtl8192cd_proc_root ); +#endif +#endif // _MESH_DEBUG_ +#endif // CONFIG_RTK_MESH + +#ifdef RTK_NL80211 + remove_proc_entry( "psd_scan", rtl8192cd_proc_root ); +#endif +#ifdef USE_OUT_SRC + remove_proc_entry( "cmd", rtl8192cd_proc_root ); +#endif + + remove_proc_entry( dev->name, NULL ); + rtl8192cd_proc_root = NULL; + } +} + +#endif + +#if defined(_SINUX_) || !defined(__KERNEL__) + +struct _proc_table_ +{ + char *cmd; + int (*func)(char *buf, char **start, off_t offset, + int length, int *eof, void *data); +}; + +static struct _proc_table_ proc_table[] = +{ + {"mib_all", rtl8192cd_proc_mib_all}, + {"mib_rf", rtl8192cd_proc_mib_rf}, + {"mib_operation", rtl8192cd_proc_mib_operation}, + {"mib_staconfig", rtl8192cd_proc_mib_staconfig}, + {"mib_dkeytbl", rtl8192cd_proc_mib_dkeytbl}, + {"mib_auth", rtl8192cd_proc_mib_auth}, + {"mib_gkeytbl", rtl8192cd_proc_mib_gkeytbl}, + {"mib_bssdesc", rtl8192cd_proc_mib_bssdesc}, + {"sta_info", rtl8192cd_proc_stainfo}, + {"sta_keyinfo", rtl8192cd_proc_sta_keyinfo}, + {"probe_info", rtl8192cd_proc_probe_info}, +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + {"sta_queinfo", rtl8192cd_proc_sta_queinfo}, +#endif + {"sta_dbginfo", rtl8192cd_proc_sta_dbginfo}, +#if defined(CONFIG_PCI_HCI) + {"txdesc", rtl8192cd_proc_txdesc_info}, + {"rxdesc", rtl8192cd_proc_rxdesc_info}, + {"desc_info", rtl8192cd_proc_desc_info}, +#elif defined(CONFIG_SDIO_HCI) + {"que_info", rtl8192cd_proc_que_info}, +#endif + {"buf_info", rtl8192cd_proc_buf_info}, + {"stats", rtl8192cd_proc_stats}, + {"mib_erp", rtl8192cd_proc_mib_erp}, + {"cam_info", rtl8192cd_proc_cam_info}, +#ifdef MULTI_MAC_CLONE + {"mbidcam_info", rtl8192cd_proc_mbidcam_info}, + {"msta_info", rtl8192cd_proc_mstainfo}, +#endif +#ifdef HS2_SUPPORT + {"mib_hs2", rtl8192cd_proc_mib_hs2}, +#endif +#ifdef WDS + {"mib_wds", rtl8192cd_proc_mib_wds}, +#endif +#ifdef RTK_BR_EXT + {"mib_brext", rtl8192cd_proc_mib_brext}, +#endif +#ifdef ENABLE_RTL_SKB_STATS + {"skb_info", rtl8192cd_proc_skb_info}, +#endif +#ifdef DFS + {"mib_dfs", rtl8192cd_proc_mib_DFS}, +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + {"mib_rf_ac", rtl8192cd_proc_mib_rf_ac}, +#endif + {"mib_misc", rtl8192cd_proc_mib_misc}, +#ifdef WIFI_SIMPLE_CONFIG + {"mib_wsc", rtl8192cd_proc_mib_wsc}, +#endif +#ifdef GBWC + {"mib_gbwc", rtl8192cd_proc_mib_gbwc}, +#endif + {"mib_11n", rtl8192cd_proc_mib_11n}, +#ifdef RTL_MANUAL_EDCA + {"mib_EDCA", rtl8192cd_proc_mib_edca}, +#endif +#ifdef CLIENT_MODE + {"up_flag", rtl8192cd_proc_up_read}, +#endif +#if defined(RTLWIFINIC_GPIO_CONTROL) + {"gpio_ctrl", rtl8192cd_proc_gpio_ctrl_read}, +#endif +#ifdef TLN_STATS + {"wifi_conn_stats", proc_wifi_conn_stats}, + {"ext_wifi_conn_stats", proc_ext_wifi_conn_stats}, +#endif + +#ifdef AUTO_TEST_SUPPORT + {"SS_Result", rtl8192cd_proc_SSR_read}, +#endif + +#ifdef _MESH_DEBUG_ // 802.11s output debug information + {"mesh_unestablish_mpinfo", mesh_unEstablish_mpinfo}, + {"mesh_assoc_mpinfo", mesh_assoc_mpinfo}, + {"mesh_stats", mesh_stats} +#endif // _MESH_DEBUG_ +#ifdef USE_OUT_SRC + {"cmd", proc_get_phydm_cmd} +#endif +}; + +#define NUM_CMD_TABLE_ENTRY (sizeof(proc_table) / sizeof(struct _proc_table_)) + +#ifdef __ECOS +void rtl8192cd_proc_help(char *name) +{ + int i; + + for (i=0; i +#include +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#if (defined(INCLUDE_WPA_PSK) && !defined(WIFI_HAPD) && !defined(RTK_NL80211)) || defined(HAPD_DRV_PSK_WPS) || defined(NON_NL80211_AP) + +#include "./8192cd.h" +#include "./wifi.h" +#include "./8192cd_util.h" +#include "./8192cd_headers.h" +#include "./8192cd_security.h" +#ifdef __KERNEL__ +#include "./ieee802_mib.h" +#elif defined(__ECOS) +#include +#endif +#include "./8192cd_debug.h" +#include "./8192cd_psk.h" +#include "./1x_rc4.h" + +#if !defined(__KERNEL__) && !defined(__ECOS) +#include "./sys-support.h" +#endif + +//#define DEBUG_PSK + +#define ETHER_ADDRLEN 6 +#define PMK_EXPANSION_CONST "Pairwise key expansion" +#define PMK_EXPANSION_CONST_SIZE 22 +#ifdef RTL_WPA2 +#define PMKID_NAME_CONST "PMK Name" +#define PMKID_NAME_CONST_SIZE 8 +#endif /* RTL_WPA2 */ +#define GMK_EXPANSION_CONST "Group key expansion" +#define GMK_EXPANSION_CONST_SIZE 19 +#define RANDOM_EXPANSION_CONST "Init Counter" +#define RANDOM_EXPANSION_CONST_SIZE 12 +#define PTK_LEN_CCMP 48 + +#define IGMK_EXPANSION_CONST "IGTK key expansion" +#define IGMK_EXPANSION_CONST_SIZE 18 + +/* + 2008-12-16, For Corega CG-WLCB54GL 54Mbps NIC interoperability issue. + The behavior of this NIC when it connect to the other AP with WPA/TKIP is: + AP <----------------------> STA + .................... + ------------> Assoc Rsp (ok) + ------------> EAPOL-key (4-way msg 1) + <------------ unknown TKIP encryption data + ------------> EAPOL-key (4-way msg 1) + <------------ unknown TKIP encryption data + ..................... + <------------ disassoc (code=8, STA is leaving) when the 5 seconds timer timeout counting from Assoc_Rsp is got. + .................... + ------------> Assoc Rsp (ok) + <-----------> EAPOL-key (4-way handshake success) + + If MAX_RESEND_NUM=3, our AP will send disassoc (code=15, 4-way timeout) to STA before STA sending disassoc to AP. + And this NIC will always can not connect to our AP. + set MAX_RESEND_NUM=5 can fix this issue. + */ +//#define MAX_RESEND_NUM 3 +#define MAX_RESEND_NUM 5 +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) +#define MAX_RESEND_NUM_STA 3 +#endif + +#define RESEND_TIME RTL_SECONDS_TO_JIFFIES(1) // in 10ms + +#ifdef CLIENT_MODE + #define WAIT_EAP_TIME RTL_SECONDS_TO_JIFFIES(5) +#endif + +#define LargeIntegerOverflow(x) (x.field.HighPart == 0xffffffff) && \ + (x.field.LowPart == 0xffffffff) +#define LargeIntegerZero(x) memset(&x.charData, 0, 8); + +#define Octet16IntegerOverflow(x) LargeIntegerOverflow(x.field.HighPart) && \ + LargeIntegerOverflow(x.field.LowPart) +#define Octet16IntegerZero(x) memset(&x.charData, 0, 16); + +#define SetNonce(ocDst, oc32Counter) SetEAPOL_KEYIV(ocDst, oc32Counter) + + +#if defined(CONFIG_RTL8186_KB_N) +int authRes = 0;//0: success; 1: fail +#endif + +extern void hmac_sha( + unsigned char* k, /* secret key */ + int lk, /* length of the key in bytes */ + unsigned char* d, /* data */ + int ld, /* length of data in bytes */ + unsigned char* out, /* output buffer, at least "t" bytes */ + int t + ); + +extern void hmac_sha1(unsigned char *text, int text_len, unsigned char *key, + int key_len, unsigned char *digest); + +extern void hmac_md5(unsigned char *text, int text_len, unsigned char *key, + int key_len, void * digest); + +#ifdef RTL_WPA2 +extern void AES_WRAP(unsigned char *plain, int plain_len, + unsigned char *iv, int iv_len, + unsigned char *kek, int kek_len, + unsigned char *cipher, unsigned short *cipher_len); +#ifdef CLIENT_MODE +extern void AES_UnWRAP(unsigned char *cipher, int cipher_len, unsigned char *kek, + int kek_len, unsigned char *plain, int plain_len); +#endif +#endif + +static void UpdateGK(struct rtl8192cd_priv *priv); +static void SendEAPOL(struct rtl8192cd_priv *priv, struct stat_info *pstat, int resend); +static void ResendTimeout(unsigned long task_psta); + + +#ifdef DEBUG_PSK +static char *ID2STR(int id) +{ + switch(id) { + case DOT11_EVENT_ASSOCIATION_IND: + return("DOT11_EVENT_ASSOCIATION_IND"); + case DOT11_EVENT_REASSOCIATION_IND: + return ("DOT11_EVENT_REASSOCIATION_IND"); + + case DOT11_EVENT_DISASSOCIATION_IND: + return ("DOT11_EVENT_DISASSOCIATION_IND"); + + case DOT11_EVENT_EAP_PACKET: + return ("DOT11_EVENT_EAP_PACKET"); + + case DOT11_EVENT_MIC_FAILURE: + return ("DOT11_EVENT_MIC_FAILURE"); + default: + return ("Not support event"); + + } +} + +static char *STATE2RXMSG(struct stat_info *pstat) +{ + if (Message_KeyType(pstat->wpa_sta_info->EapolKeyMsgRecvd) == type_Pairwise) { + if (pstat->wpa_sta_info->state == PSK_STATE_PTKSTART) + return ("4-2"); + else if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITNEGOTIATING) { + if (Message_KeyDataLength(pstat->wpa_sta_info->EapolKeyMsgRecvd) != 0) + return ("4-2 (duplicated)"); + else + return ("4-4"); + } else if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITDONE) + return ("4-4 (duplicated)"); + else + return ("invalid state"); + + } else + return ("2-2"); + +} +#endif // DEBUG_PSK + +static OCTET_STRING SubStr(OCTET_STRING f, unsigned short s, unsigned short l) +{ + OCTET_STRING res; + + res.Length = l; + res.Octet = f.Octet+s; + return res; +} + +static void i_P_SHA1( + unsigned char* key, // pointer to authentication key + int key_len, // length of authentication key + unsigned char* text, // pointer to data stream + int text_len, // length of data stream + unsigned char* digest, // caller digest to be filled in + int digest_len // in byte + ) +{ + int i; + int offset=0; + int step=20; + int IterationNum=(digest_len+step-1)/step; + + for (i = 0; i < IterationNum; i++) { + text[text_len]=(unsigned char)i; + hmac_sha(key,key_len,text,text_len+1,digest+offset,step); + offset+=step; + } +} + +static void i_PRF( + unsigned char* secret, + int secret_len, + unsigned char* prefix, + int prefix_len, + unsigned char* random, + int random_len, + unsigned char* digest, // caller digest to be filled in + int digest_len // in byte + ) +{ + unsigned char data[1000]; + memcpy(data,prefix,prefix_len); + data[prefix_len++]=0; + memcpy(data+prefix_len,random,random_len); + i_P_SHA1(secret,secret_len,data,prefix_len+random_len,digest,digest_len); +} + + +/* + * F(P, S, c, i) = U1 xor U2 xor ... Uc + * U1 = PRF(P, S || Int(i)) + * U2 = PRF(P, U1) + * Uc = PRF(P, Uc-1) + */ + +static void F( + char *password, + int passwordlength, + unsigned char *ssid, + int ssidlength, + int iterations, + int count, + unsigned char *output) +{ + unsigned char digest[36], digest1[A_SHA_DIGEST_LEN]; + int i, j; + + /* U1 = PRF(P, S || int(i)) */ + memcpy(digest, ssid, ssidlength); + digest[ssidlength] = (unsigned char)((count>>24) & 0xff); + digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff); + digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff); + digest[ssidlength+3] = (unsigned char)(count & 0xff); + hmac_sha1(digest, ssidlength + 4, + (unsigned char*) password, (int)strlen(password), + digest1); + + /* + hmac_sha1((unsigned char*) password, passwordlength, + digest, ssidlength+4, digest1); + */ + + /* output = U1 */ + memcpy(output, digest1, A_SHA_DIGEST_LEN); + + for (i = 1; i < iterations; i++) { + /* Un = PRF(P, Un-1) */ + hmac_sha1(digest1, A_SHA_DIGEST_LEN, (unsigned char*) password, + (int)strlen(password), digest); + //hmac_sha1((unsigned char*) password, passwordlength,digest1, A_SHA_DIGEST_LEN, digest); + memcpy(digest1, digest, A_SHA_DIGEST_LEN); + + /* output = output xor Un */ + for (j = 0; j < A_SHA_DIGEST_LEN; j++) { + output[j] ^= digest[j]; + } + } +} + +/* + * password - ascii string up to 63 characters in length + * ssid - octet string up to 32 octets + * ssidlength - length of ssid in octets + * output must be 40 octets in length and outputs 256 bits of key + */ +static int PasswordHash ( + char *password, + unsigned char *ssid, + short ssidlength, + unsigned char *output) +{ + int passwordlength = strlen(password); +// int ssidlength = strlen(ssid); + + if ((passwordlength > 63) || (ssidlength > 32)) + return 0; + + F(password, passwordlength, ssid, ssidlength, 4096, 1, output); + F(password, passwordlength, ssid, ssidlength, 4096, 2, &output[A_SHA_DIGEST_LEN]); + return 1; +} + +static void Message_ReplayCounter_OC2LI(OCTET_STRING f, LARGE_INTEGER * li) +{ + li->field.HighPart = ((unsigned int)(*(f.Octet + ReplayCounterPos + 3))) + + ((unsigned int)(*(f.Octet + ReplayCounterPos+ 2)) <<8 ) + + ((unsigned int)(*(f.Octet + ReplayCounterPos + 1)) << 16) + + ((unsigned int)(*(f.Octet + ReplayCounterPos + 0)) <<24); + li->field.LowPart = ((unsigned int)(*(f.Octet + ReplayCounterPos + 7))) + + ((unsigned int)(*(f.Octet + ReplayCounterPos + 6)) <<8 ) + + ((unsigned int)(*(f.Octet + ReplayCounterPos + 5)) << 16) + + ((unsigned int)(*(f.Octet + ReplayCounterPos + 4)) <<24); +} + +#if 1 +/*----------------------------------------------------------------------------------------------- + f is EAPOL-KEY message +------------------------------------------------------------------------------------------------*/ +static int Message_EqualReplayCounter(LARGE_INTEGER li1, OCTET_STRING f) +{ + LARGE_INTEGER li2; + Message_ReplayCounter_OC2LI(f, &li2); + if(li1.field.HighPart == li2.field.HighPart && li1.field.LowPart == li2.field.LowPart) + return 1; + else + return 0; +} +#endif + +#ifdef CLIENT_MODE +/*------------------------------------------------------------------------------------------- + li1 is recorded replay counter on STA + f is the replay counter from EAPOL-KEY message +---------------------------------------------------------------------------------------------*/ +static int Message_SmallerEqualReplayCounter(LARGE_INTEGER li1, OCTET_STRING f) +{ + LARGE_INTEGER li2; + Message_ReplayCounter_OC2LI(f, &li2); + if(li2.field.HighPart > li1.field.HighPart) + return 0; + else if(li2.field.HighPart < li1.field.HighPart) + return 1; + else if(li2.field.LowPart > li1.field.LowPart) + return 0; + else if(li2.field.LowPart <= li1.field.LowPart) + return 1; + else + return 0; +} +#endif + +/*--------------------------------------------------------------------------------------------- + li1 is recorded replay counter on STA + f is the replay counter from EAPOL-KEY message +-----------------------------------------------------------------------------------------------*/ +static int Message_LargerReplayCounter(LARGE_INTEGER li1, OCTET_STRING f) +{ + LARGE_INTEGER li2; + Message_ReplayCounter_OC2LI(f, &li2); + + if(li2.field.HighPart > li1.field.HighPart) + return 1; + else if(li2.field.LowPart > li1.field.LowPart) + return 1; + else + return 0; +} + +static void Message_setReplayCounter(OCTET_STRING f, unsigned int h, unsigned int l) +{ + LARGE_INTEGER *li = (LARGE_INTEGER *)(f.Octet + ReplayCounterPos); + li->charData[0] = (unsigned char)(h >> 24) & 0xff; + li->charData[1] = (unsigned char)(h >> 16) & 0xff; + li->charData[2] = (unsigned char)(h >> 8) & 0xff; + li->charData[3] = (unsigned char)(h >> 0) & 0xff; + li->charData[4] = (unsigned char)(l >> 24) & 0xff; + li->charData[5] = (unsigned char)(l >> 16) & 0xff; + li->charData[6] = (unsigned char)(l >> 8) & 0xff; + li->charData[7] = (unsigned char)(l >> 0) & 0xff; +} + +void ConstructIE(struct rtl8192cd_priv *priv, unsigned char *pucOut, int *usOutLen) +{ + DOT11_RSN_IE_HEADER dot11RSNIEHeader = { 0 }; + DOT11_RSN_IE_SUITE dot11RSNGroupSuite; +#ifdef CONFIG_IEEE80211W + DOT11_RSN_IE_SUITE dot11RSNIGTKSuite; +#endif + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNPairwiseSuite = NULL; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNAuthSuite = NULL; + unsigned short usSuitCount; + unsigned int ulIELength = 0; + unsigned int ulIndex = 0; + unsigned int ulPairwiseLength = 0; + unsigned int ulAuthLength = 0; + unsigned char *pucBlob; + DOT11_RSN_IE_COUNT_SUITE countSuite, authCountSuite; +#ifdef RTL_WPA2 + DOT11_RSN_CAPABILITY dot11RSNCapability = { 0 }; + unsigned int uCipherAlgo = 0; + int bCipherAlgoEnabled = FALSE; + unsigned int uAuthAlgo = 0; + int bAuthAlgoEnabled = FALSE; + unsigned int ulRSNCapabilityLength = 0; +#endif + + *usOutLen = 0; + if ( priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) { + // + // Construct Information Header + // + dot11RSNIEHeader.ElementID = RSN_ELEMENT_ID; + dot11RSNIEHeader.OUI[0] = 0x00; + dot11RSNIEHeader.OUI[1] = 0x50; + dot11RSNIEHeader.OUI[2] = 0xf2; + dot11RSNIEHeader.OUI[3] = 0x01; + dot11RSNIEHeader.Version = cpu_to_le16(RSN_VER1); + ulIELength += sizeof(DOT11_RSN_IE_HEADER); + + // Construct Cipher Suite: + // - Multicast Suite: + memset(&dot11RSNGroupSuite, 0, sizeof dot11RSNGroupSuite); + dot11RSNGroupSuite.OUI[0] = 0x00; + dot11RSNGroupSuite.OUI[1] = 0x50; + dot11RSNGroupSuite.OUI[2] = 0xF2; + dot11RSNGroupSuite.Type = priv->wpa_global_info->MulticastCipher; + //printk("[WPA] MulticastSuite = %d, ", dot11RSNGroupSuite.Type); + ulIELength += sizeof(DOT11_RSN_IE_SUITE); + + // - UnicastSuite + pDot11RSNPairwiseSuite = &countSuite; + memset(pDot11RSNPairwiseSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipher; ulIndex++) + { + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipher[ulIndex]; + usSuitCount++; + } + + pDot11RSNPairwiseSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulPairwiseLength = sizeof(pDot11RSNPairwiseSuite->SuiteCount) + usSuitCount * sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulPairwiseLength; + + // + // Construction of Auth Algo List + // + pDot11RSNAuthSuite = &authCountSuite; + memset(pDot11RSNAuthSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK; + usSuitCount++; + + pDot11RSNAuthSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulAuthLength = sizeof(pDot11RSNAuthSuite->SuiteCount) + usSuitCount * sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulAuthLength; + + //--------------------------------------------------------------------------------------------- + // Do not encapsulate capability field to solve TI WPA issue + //--------------------------------------------------------------------------------------------- + /* + dot11RSNCapability.field.PreAuthentication = 0;//auth->RSNVariable.isSupportPreAuthentication + dot11RSNCapability.field.PairwiseAsDefaultKey = auth->RSNVariable.isSupportPairwiseAsDefaultKey; + switch(auth->RSNVariable.NumOfRxTSC) + { + case 1: + dot11RSNCapability.field.NumOfReplayCounter = 0; + break; + case 2: + dot11RSNCapability.field.NumOfReplayCounter = 1; + break; + case 4: + dot11RSNCapability.field.NumOfReplayCounter = 2; + break; + case 16: + dot11RSNCapability.field.NumOfReplayCounter = 3; + break; + default: + dot11RSNCapability.field.NumOfReplayCounter = 0; + } + + ulRSNCapabilityLength = sizeof(DOT11_RSN_CAPABILITY); + ulIELength += ulRSNCapabilityLength; + */ + + pucBlob = pucOut; + pucBlob += sizeof(DOT11_RSN_IE_HEADER); + memcpy(pucBlob, &dot11RSNGroupSuite, sizeof(DOT11_RSN_IE_SUITE)); + pucBlob += sizeof(DOT11_RSN_IE_SUITE); + memcpy(pucBlob, pDot11RSNPairwiseSuite, ulPairwiseLength); + pucBlob += ulPairwiseLength; + memcpy(pucBlob, pDot11RSNAuthSuite, ulAuthLength); + pucBlob += ulAuthLength; + + *usOutLen = (int)ulIELength; + pucBlob = pucOut; + dot11RSNIEHeader.Length = (unsigned char)ulIELength - 2; //This -2 is to minus elementID and Length in OUI header + memcpy(pucBlob, &dot11RSNIEHeader, sizeof(DOT11_RSN_IE_HEADER)); + } + +#ifdef RTL_WPA2 + if ( priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2) { + DOT11_WPA2_IE_HEADER dot11WPA2IEHeader = { 0 }; + ulIELength = 0; + ulIndex = 0; + ulPairwiseLength = 0; + uCipherAlgo = 0; + bCipherAlgoEnabled = FALSE; + ulAuthLength = 0; + uAuthAlgo = 0; + bAuthAlgoEnabled = FALSE; + ulRSNCapabilityLength = 0; + + // + // Construct Information Header + // + dot11WPA2IEHeader.ElementID = WPA2_ELEMENT_ID; + dot11WPA2IEHeader.Version = cpu_to_le16(RSN_VER1); + ulIELength += sizeof(DOT11_WPA2_IE_HEADER); + + // Construct Cipher Suite: + // - Multicast Suite: + // + memset(&dot11RSNGroupSuite, 0, sizeof(dot11RSNGroupSuite)); + dot11RSNGroupSuite.OUI[0] = 0x00; + dot11RSNGroupSuite.OUI[1] = 0x0F; + dot11RSNGroupSuite.OUI[2] = 0xAC; + dot11RSNGroupSuite.Type = priv->wpa_global_info->MulticastCipher; + //printk("[WPA2] MulticastSuite = %d, ", dot11RSNGroupSuite.Type); + ulIELength += sizeof(DOT11_RSN_IE_SUITE); + + // - UnicastSuite + pDot11RSNPairwiseSuite = &countSuite; + memset(pDot11RSNPairwiseSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipherWPA2; ulIndex++) { + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipherWPA2[ulIndex]; + usSuitCount++; + } + + pDot11RSNPairwiseSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulPairwiseLength = sizeof(pDot11RSNPairwiseSuite->SuiteCount) + usSuitCount * sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulPairwiseLength; + + // + // Construction of Auth Algo List + // + pDot11RSNAuthSuite = &authCountSuite; + memset(pDot11RSNAuthSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + + if (OPMODE & WIFI_AP_STATE) + { +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK_SHA256; + else +#endif + { + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK; + } + usSuitCount++; + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_OPTIONAL + && priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 == 1) { + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK_SHA256; + usSuitCount++; + } +#endif + } else { +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != 0 + && priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 == 1) + { + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK_SHA256; + } + else +#endif + { + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK; + } + usSuitCount++; + } + + pDot11RSNAuthSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulAuthLength = sizeof(pDot11RSNAuthSuite->SuiteCount) + usSuitCount * sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulAuthLength; + + //--------------------------------------------------------------------------------------------- + // Do not encapsulate capability field to solve TI WPA issue + //--------------------------------------------------------------------------------------------- + +//#ifdef RTL_WPA2 +#if 1 + dot11RSNCapability.field.PreAuthentication = 0; +#else + dot11RSNCapability.field.PairwiseAsDefaultKey = auth->RSNVariable.isSupportPairwiseAsDefaultKey; + switch (auth->RSNVariable.NumOfRxTSC) { + case 1: + dot11RSNCapability.field.NumOfReplayCounter = 0; + break; + case 2: + dot11RSNCapability.field.NumOfReplayCounter = 1; + break; + case 4: + dot11RSNCapability.field.NumOfReplayCounter = 2; + break; + case 16: + dot11RSNCapability.field.NumOfReplayCounter = 3; + break; + default: + dot11RSNCapability.field.NumOfReplayCounter = 0; + } +#endif + +#ifdef CONFIG_IEEE80211W + //Protected Managemenet Protection Capability (PMF) + //printk("ConstructIE, dot11IEEE80211W=%d\n", priv->pmib->dot1180211AuthEntry.dot11IEEE80211W); + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION) { + dot11RSNCapability.field.MFPC = 0; + dot11RSNCapability.field.MFPR = 0; + } else if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_OPTIONAL) + dot11RSNCapability.field.MFPC = 1; // MFPC + else if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + dot11RSNCapability.field.MFPR = 1; // MFPR + dot11RSNCapability.field.MFPC = 1; // MFPC + } +#endif + + ulRSNCapabilityLength = sizeof(DOT11_RSN_CAPABILITY); + ulIELength += ulRSNCapabilityLength; + +#ifdef CONFIG_IEEE80211W + // Construct Cipher Suite: + // - IGTK Suite: + // + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W && priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 == TRUE) { + memset(&dot11RSNIGTKSuite, 0, sizeof(dot11RSNIGTKSuite)); + dot11RSNIGTKSuite.OUI[0] = 0x00; + dot11RSNIGTKSuite.OUI[1] = 0x0F; + dot11RSNIGTKSuite.OUI[2] = 0xAC; + + dot11RSNIGTKSuite.Type = DOT11_ENC_BIP; + ulIELength += sizeof(dot11RSNIGTKSuite) + 2; + } +#endif // CONFIG_IEEE80211W + + pucBlob = pucOut + *usOutLen; + pucBlob += sizeof(DOT11_WPA2_IE_HEADER); + memcpy(pucBlob, &dot11RSNGroupSuite, sizeof(DOT11_RSN_IE_SUITE)); + pucBlob += sizeof(DOT11_RSN_IE_SUITE); + memcpy(pucBlob, pDot11RSNPairwiseSuite, ulPairwiseLength); + pucBlob += ulPairwiseLength; + memcpy(pucBlob, pDot11RSNAuthSuite, ulAuthLength); + pucBlob += ulAuthLength; + memcpy(pucBlob, &dot11RSNCapability, ulRSNCapabilityLength); + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != NO_MGMT_FRAME_PROTECTION) { + pucBlob += ulRSNCapabilityLength + 2; // add PMDID Count (2bytes) + memcpy(pucBlob, &dot11RSNIGTKSuite, sizeof(DOT11_RSN_IE_SUITE)); + } +#endif // CONFIG_IEEE80211W + + pucBlob = pucOut + *usOutLen; + dot11WPA2IEHeader.Length = (unsigned char)ulIELength - 2; //This -2 is to minus elementID and Length in OUI header + memcpy(pucBlob, &dot11WPA2IEHeader, sizeof(DOT11_WPA2_IE_HEADER)); + *usOutLen = *usOutLen + (int)ulIELength; + } +#endif // RTL_WPA2 + +} + +static void INCLargeInteger(LARGE_INTEGER * x) +{ + if (x->field.LowPart == 0xffffffff) { + if (x->field.HighPart == 0xffffffff) { + x->field.HighPart = 0; + x->field.LowPart = 0; + } else { + x->field.HighPart++; + x->field.LowPart = 0; + } + } else + x->field.LowPart++; +} + +static void INCOctet16_INTEGER(OCTET16_INTEGER * x) +{ + if (LargeIntegerOverflow(x->field.LowPart)){ + if (LargeIntegerOverflow(x->field.HighPart)) { + LargeIntegerZero(x->field.HighPart); + LargeIntegerZero(x->field.LowPart); + } else { + INCLargeInteger(&x->field.HighPart); + LargeIntegerZero(x->field.LowPart); + } + } else + INCLargeInteger(&x->field.LowPart); + +} + +static OCTET32_INTEGER *INCOctet32_INTEGER(OCTET32_INTEGER * x) +{ + if (Octet16IntegerOverflow(x->field.LowPart)) { + if (Octet16IntegerOverflow(x->field.HighPart)) { + Octet16IntegerZero(x->field.HighPart); + Octet16IntegerZero(x->field.LowPart); + } else { + INCOctet16_INTEGER(&x->field.HighPart); + Octet16IntegerZero( x->field.LowPart); + } + } else + INCOctet16_INTEGER(&x->field.LowPart); + return x; +} + +static void SetEAPOL_KEYIV(OCTET_STRING ocDst, OCTET32_INTEGER oc32Counter) +{ + unsigned char *ptr = ocDst.Octet; + unsigned int ulTmp; + + ulTmp = cpu_to_le32(oc32Counter.field.HighPart.field.HighPart.field.HighPart); + memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp)); + ptr+=4; + + ulTmp = cpu_to_le32(oc32Counter.field.HighPart.field.HighPart.field.LowPart); + memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp)); + ptr+=4; + + ulTmp = cpu_to_le32(oc32Counter.field.HighPart.field.LowPart.field.HighPart); + memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp)); + ptr+=4; + + ulTmp = cpu_to_le32(oc32Counter.field.HighPart.field.LowPart.field.LowPart); + memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp)); + + if (ocDst.Length == 16) // for AES + return; + + ptr+=4; + + ulTmp = cpu_to_le32(oc32Counter.field.LowPart.field.HighPart.field.HighPart); + memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp)); + ptr+=4; + + ulTmp = cpu_to_le32(oc32Counter.field.LowPart.field.HighPart.field.LowPart); + memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp)); + ptr+=4; + + ulTmp = cpu_to_le32(oc32Counter.field.LowPart.field.LowPart.field.HighPart); + memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp)); + ptr+=4; + + ulTmp = cpu_to_le32(oc32Counter.field.LowPart.field.LowPart.field.LowPart); + memcpy(ptr, (char *)&ulTmp, sizeof(ulTmp)); +} + +static void EncGTK(struct rtl8192cd_priv *priv, struct stat_info *pstat, + unsigned char *kek, int keklen, unsigned char *key, + int keylen, unsigned char *out, unsigned short *outlen) +{ + + unsigned char tmp1[257], tmp2[257]; + RC4_KEY *rc4key; +#ifdef RTL_WPA2 + unsigned char default_key_iv[] = { 0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6 }; +#endif + OCTET_STRING EAPOLMsgSend; + lib1x_eapol_key *eapolkey; + + rc4key = (RC4_KEY *)kmalloc(sizeof(RC4_KEY), GFP_ATOMIC); + if (rc4key == NULL) + return; + + EAPOLMsgSend.Octet = pstat->wpa_sta_info->EAPOLMsgSend.Octet; + eapolkey = (lib1x_eapol_key *)(EAPOLMsgSend.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN); + +// should refer tx packet, david+2006-04-06 +// if (Message_KeyDescVer(pstat->wpa_sta_info->EapolKeyMsgRecvd) == key_desc_ver1) { + if (Message_KeyDescVer(pstat->wpa_sta_info->EapolKeyMsgSend) == key_desc_ver1) { + + memcpy(tmp1, eapolkey->key_iv, KEY_IV_LEN); + memcpy(tmp1 + KEY_IV_LEN, kek, keklen); + + RC4_set_key(rc4key, KEY_IV_LEN + keklen, tmp1); + + //first 256 bytes are discarded + RC4(rc4key, 256, (unsigned char *)tmp1, (unsigned char *)tmp2); + RC4(rc4key, keylen, (unsigned char *)key, out); + *outlen = keylen; + } +#ifdef RTL_WPA2 + else + //according to p75 of 11i/D3.0, the IV should be put in the least significant octecs of + //KeyIV field which shall be padded with 0, so eapolkey->key_iv + 8 + AES_WRAP(key, keylen, default_key_iv, 8, kek, keklen, out, outlen); +#endif + kfree(rc4key); +} + +static int CheckMIC(OCTET_STRING EAPOLMsgRecvd, unsigned char *key, int keylen) +{ + int retVal = 0; + OCTET_STRING EapolKeyMsgRecvd; + unsigned char ucAlgo; + OCTET_STRING tmp; //copy of overall 802.1x message + unsigned char tmpbuf[512]; + struct lib1x_eapol *tmpeapol; + lib1x_eapol_key *tmpeapolkey; + unsigned char sha1digest[20]; + + EapolKeyMsgRecvd.Octet = EAPOLMsgRecvd.Octet + + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN; + EapolKeyMsgRecvd.Length = EAPOLMsgRecvd.Length - + (ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN); + ucAlgo = Message_KeyDescVer(EapolKeyMsgRecvd); + + tmp.Length = EAPOLMsgRecvd.Length; + tmp.Octet = tmpbuf; + memcpy(tmp.Octet, EAPOLMsgRecvd.Octet, EAPOLMsgRecvd.Length); + tmpeapol = (struct lib1x_eapol *)(tmp.Octet + ETHER_HDRLEN); + tmpeapolkey = (lib1x_eapol_key *)(tmp.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN); + memset(tmpeapolkey->key_mic, 0, KEY_MIC_LEN); + + if (ucAlgo == key_desc_ver1) { + hmac_md5((unsigned char*)tmpeapol, LIB1X_EAPOL_HDRLEN + ntohs(tmpeapol->packet_body_length) , + key, keylen, tmpeapolkey->key_mic); +#if 0 + lib1x_hexdump2(MESS_DBG_KEY_MANAGE, "CheckMIC", EapolKeyMsgRecvd.Octet + + KeyMICPos, KEY_MIC_LEN, "Original"); + lib1x_hexdump2(MESS_DBG_KEY_MANAGE, "CheckMIC", tmpeapolkey->key_mic, + KEY_MIC_LEN, "Calculated"); +#endif + if (!memcmp(tmpeapolkey->key_mic, EapolKeyMsgRecvd.Octet + KeyMICPos, KEY_MIC_LEN)) + retVal = 1; + } else if (ucAlgo == key_desc_ver2) { + hmac_sha1((unsigned char*)tmpeapol, LIB1X_EAPOL_HDRLEN + ntohs(tmpeapol->packet_body_length) , + key, keylen, sha1digest); + if (!memcmp(sha1digest, EapolKeyMsgRecvd.Octet + KeyMICPos, KEY_MIC_LEN)) + retVal = 1; + } +#ifdef CONFIG_IEEE80211W + else if (ucAlgo == key_desc_ver3 +#ifdef HS2_SUPPORT // OSEN + || ucAlgo == 0 +#endif + ) + { + + omac1_aes_128(key, (unsigned char*)tmpeapol, LIB1X_EAPOL_HDRLEN + ntohs(tmpeapol->packet_body_length), tmpeapolkey->key_mic); + + if (!memcmp(tmpeapolkey->key_mic, EapolKeyMsgRecvd.Octet + KeyMICPos, KEY_MIC_LEN)) + retVal = 1; + } +#endif + return retVal; +} + +static void CalcMIC(OCTET_STRING EAPOLMsgSend, int algo, unsigned char *key, int keylen) +{ + struct lib1x_eapol *eapol = (struct lib1x_eapol *)(EAPOLMsgSend.Octet+ETHER_HDRLEN); + lib1x_eapol_key *eapolkey = (lib1x_eapol_key *)(EAPOLMsgSend.Octet+ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN); + unsigned char sha1digest[20]; + + memset(eapolkey->key_mic, 0, KEY_MIC_LEN); + + if (algo == key_desc_ver1) + hmac_md5((unsigned char*)eapol, EAPOLMsgSend.Length - ETHER_HDRLEN , + key, keylen, eapolkey->key_mic); + else if (algo == key_desc_ver2) { + hmac_sha1((unsigned char*)eapol, EAPOLMsgSend.Length - ETHER_HDRLEN , + key, keylen, sha1digest); + memcpy(eapolkey->key_mic, sha1digest, KEY_MIC_LEN); + } +#ifdef CONFIG_IEEE80211W + else if (algo == key_desc_ver3) { + omac1_aes_128(key, (unsigned char*)eapol, EAPOLMsgSend.Length - ETHER_HDRLEN, eapolkey->key_mic); + } +#endif +} + +/* GTK-PRF-X + X = 256 in TKIP + X = 128 in CCMP, WRAP, and WEP +*/ +static void CalcGTK(unsigned char *addr, unsigned char *nonce, + unsigned char *keyin, int keyinlen, + unsigned char *keyout, int keyoutlen, unsigned char *label) +{ + unsigned char data[ETHER_ADDRLEN + KEY_NONCE_LEN], tmp[64]; + + memcpy(data, addr, ETHER_ADDRLEN); + memcpy(data + ETHER_ADDRLEN, nonce, KEY_NONCE_LEN); +#ifdef CONFIG_IEEE80211W + sha256_prf(keyin, keyinlen, label, data, sizeof(data), tmp, keyoutlen); +#else + i_PRF(keyin, keyinlen, label, + GMK_EXPANSION_CONST_SIZE, data, sizeof(data), + tmp, keyoutlen); +#endif + memcpy(keyout, tmp, keyoutlen); +} + +static int MIN(unsigned char *ucStr1, unsigned char *ucStr2, unsigned int ulLen) +{ + int i; + for (i=0 ; i (unsigned char)ucStr2[i]) + return 1; + else if(i == ulLen - 1) + return 0; + else + continue; + } + return 0; +} + +static void CalcPTK(unsigned char *addr1, unsigned char *addr2, + unsigned char *nonce1, unsigned char *nonce2, + unsigned char * keyin, int keyinlen, + unsigned char *keyout, int keyoutlen +#ifdef CONFIG_IEEE80211W + ,int use_sha256 +#endif + ) +{ + unsigned char data[2*ETHER_ADDRLEN+ 2*KEY_NONCE_LEN], tmpPTK[128]; +#ifdef CONFIG_IEEE80211W + unsigned char keydata[32]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20 }; + unsigned char plainData[10]="abc"; + unsigned char **ptr; + unsigned char encryptedData[32]; +#endif + + if (MIN(addr1, addr2, ETHER_ADDRLEN) <= 0) { + memcpy(data, addr1, ETHER_ADDRLEN); + memcpy(data + ETHER_ADDRLEN, addr2, ETHER_ADDRLEN); + } else { + memcpy(data, addr2, ETHER_ADDRLEN); + memcpy(data + ETHER_ADDRLEN, addr1, ETHER_ADDRLEN); + } + if (MIN(nonce1, nonce2, KEY_NONCE_LEN) <= 0) { + memcpy(data + 2*ETHER_ADDRLEN, nonce1, KEY_NONCE_LEN); + memcpy(data + 2*ETHER_ADDRLEN + KEY_NONCE_LEN, nonce2, KEY_NONCE_LEN); + } else { + memcpy(data + 2*ETHER_ADDRLEN, nonce2, KEY_NONCE_LEN); + memcpy(data + 2*ETHER_ADDRLEN + KEY_NONCE_LEN, nonce1, KEY_NONCE_LEN); + } +#ifdef CONFIG_IEEE80211W + if (use_sha256) { + //PMFDEBUG("sha256_prf\n"); + sha256_prf(keyin, keyinlen, (unsigned char*)PMK_EXPANSION_CONST, data, sizeof(data), + tmpPTK, keyoutlen); + } else +#endif + { + + i_PRF(keyin, keyinlen, (unsigned char*)PMK_EXPANSION_CONST, + PMK_EXPANSION_CONST_SIZE, data, sizeof(data), + tmpPTK, PTK_LEN_TKIP); + } + memcpy(keyout, tmpPTK, keyoutlen); +} + +#ifdef CLIENT_MODE +/* + decrypt WPA2 Message 3's Key Data +*/ +// Use RC4 or AES to decode the keydata by checking desc-ver, david-2006-01-06 +//int DecWPA2KeyData(u_char *key, int keylen, u_char *kek, int keklen, u_char *kout) +int DecWPA2KeyData(WPA_STA_INFO* pStaInfo, unsigned char *key, int keylen, unsigned char *kek, int keklen, unsigned char *kout, int kout_len) +{ + int retVal = 0; + unsigned char default_key_iv[] = { 0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6,0xA6 }; + unsigned char tmp2[257]; + +// Use RC4 or AES to decode the keydata by checking desc-ver, david-2006-01-06 + unsigned char tmp1[257]; + RC4_KEY *rc4key; + + lib1x_eapol_key *eapolkey = (lib1x_eapol_key *)(pStaInfo->EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN); + + rc4key = (RC4_KEY *)kmalloc(sizeof(RC4_KEY), GFP_ATOMIC); + if (rc4key == NULL) + return 0; + + if (Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd) == key_desc_ver1) { + memcpy(tmp1, eapolkey->key_iv, KEY_IV_LEN); + if (keklen > sizeof(tmp1) - KEY_IV_LEN) { + printk("%s Error: keylen exceeds!\n", __func__); + return 0; + } + memcpy(tmp1+KEY_IV_LEN, kek, keklen); + RC4_set_key(rc4key, KEY_IV_LEN + keklen, tmp1); + + //first 256 bits is discard + RC4(rc4key, 256, (unsigned char*)tmp1, (unsigned char*)tmp2); + + //RC4(rc4key, keylen, eapol_key->key_data, global->skm_sm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)]); + RC4(rc4key, keylen, pStaInfo->EapolKeyMsgRecvd.Octet + KeyDataPos, (unsigned char*)tmp2); + + if (keylen > kout_len) { + printk("%s Error: keylen exceeds!\n", __func__); + return 0; + } + memcpy(kout, tmp2, keylen); + //memcpy(&global->supp_kmsm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)], tmp2, keylen); + retVal = 1; + } else { +//-------------------------------------------------------- + AES_UnWRAP(key, keylen, kek, keklen, tmp2, sizeof(tmp2)); + if(memcmp(tmp2, default_key_iv, 8)) + retVal = 0; + else { + if (keylen > kout_len) { + printk("%s Error: keylen exceeds!\n", __func__); + return 0; + } + memcpy(kout, tmp2+8, keylen); + retVal = 1; + } + } + kfree(rc4key); + return retVal; +} + +int DecGTK(OCTET_STRING EAPOLMsgRecvd, unsigned char *kek, int keklen, int keylen, unsigned char *kout, int kout_len) +{ + int retVal = 0; + unsigned char tmp1[257], tmp2[257]; + RC4_KEY *rc4key; + lib1x_eapol_key * eapol_key = (lib1x_eapol_key *)(EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN); + OCTET_STRING EapolKeyMsgRecvd; + + rc4key = (RC4_KEY *)kmalloc(sizeof(RC4_KEY), GFP_ATOMIC); + if (rc4key == NULL) + return 0; + + EapolKeyMsgRecvd.Octet = EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN; + EapolKeyMsgRecvd.Length = EAPOLMsgRecvd.Length - (ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN); + + if (Message_KeyDescVer(EapolKeyMsgRecvd) == key_desc_ver1) { + memcpy(tmp1, eapol_key->key_iv, KEY_IV_LEN); + if (keklen > sizeof(tmp1) - KEY_IV_LEN) { + printk("%s Error: keylen exceeds!\n", __func__); + return 0; + } + memcpy(tmp1 + KEY_IV_LEN, kek, keklen); + RC4_set_key(rc4key, KEY_IV_LEN + keklen, tmp1); + //first 256 bits is discard + RC4(rc4key, 256, (unsigned char*)tmp1, (unsigned char*)tmp2); + //RC4(rc4key, keylen, eapol_key->key_data, global->skm_sm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)]); + RC4(rc4key, keylen, EapolKeyMsgRecvd.Octet + KeyDataPos, (unsigned char*)tmp2); + if (keylen > kout_len) { + printk("%s Error: keylen exceeds!\n", __func__); + return 0; + } + memcpy(kout, tmp2, keylen); + //memcpy(&global->supp_kmsm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)], tmp2, keylen); + retVal = 1; + } else if (Message_KeyDescVer(EapolKeyMsgRecvd) == key_desc_ver2 +#ifdef CONFIG_IEEE80211W_CLI + || Message_KeyDescVer(EapolKeyMsgRecvd) == key_desc_ver3 +#endif + ) { + // kenny: should use default IV 0xA6A6A6A6A6A6A6A6 + unsigned char default_key_iv[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; +// david, get key len from eapol packet +// AES_UnWRAP(EapolKeyMsgRecvd.Octet + KeyDataPos, keylen + 8, kek, keklen, tmp2); + + keylen = Message_KeyDataLength(EapolKeyMsgRecvd); + AES_UnWRAP(EapolKeyMsgRecvd.Octet + KeyDataPos, keylen, kek, keklen, tmp2, sizeof(tmp2)); +//------------------------- 2005-08-01 + + //if(memcmp(tmp2, eapol_key->key_iv + 8, 8)) + if (memcmp(tmp2, default_key_iv, 8)) + retVal = 0; + else { + //memcpy(kout, tmp2, keylen); + //memcpy(global->supp_kmsm->GTK[Message_KeyIndex(global->EapolKeyMsgRecvd)], tmp2 + 8, keylen - 8); + if (keylen > kout_len) { + printk("%s Error: keylen exceeds!\n", __func__); + return 0; + } + memcpy(kout, tmp2+8, keylen); + retVal = 1; + } + } + kfree(rc4key); + return retVal; +} +#endif /* CLIENT_MODE */ + +static int parseIE(struct rtl8192cd_priv *priv, WPA_STA_INFO *pInfo, + unsigned char *pucIE, unsigned int ulIELength) +{ + unsigned short usSuitCount; + DOT11_RSN_IE_HEADER *pDot11RSNIEHeader; + DOT11_RSN_IE_SUITE *pDot11RSNIESuite; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite; + + DOT11_RSN_CAPABILITY * pDot11RSNCapability = NULL; + DEBUG_TRACE; + + if (ulIELength < sizeof(DOT11_RSN_IE_HEADER)) { + DEBUG_WARN("parseIE err 1!\n"); + return ERROR_INVALID_RSNIE; + } + + pDot11RSNIEHeader = (DOT11_RSN_IE_HEADER *)pucIE; + if (le16_to_cpu(pDot11RSNIEHeader->Version) != RSN_VER1) { + DEBUG_WARN("parseIE err 2!\n"); + return ERROR_UNSUPPORTED_RSNEVERSION; + } + + if (pDot11RSNIEHeader->ElementID != RSN_ELEMENT_ID || + pDot11RSNIEHeader->Length != ulIELength -2 || + pDot11RSNIEHeader->OUI[0] != 0x00 || pDot11RSNIEHeader->OUI[1] != 0x50 || + pDot11RSNIEHeader->OUI[2] != 0xf2 || pDot11RSNIEHeader->OUI[3] != 0x01 ) { + DEBUG_WARN("parseIE err 3!\n"); + return ERROR_INVALID_RSNIE; + } + + pInfo->RSNEnabled= PSK_WPA; // wpa + ulIELength -= sizeof(DOT11_RSN_IE_HEADER); + pucIE += sizeof(DOT11_RSN_IE_HEADER); + + //---------------------------------------------------------------------------------- + // Multicast Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIESuite = (DOT11_RSN_IE_SUITE *)pucIE; + if (pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x50 || + pDot11RSNIESuite->OUI[2] != 0xF2) { + DEBUG_WARN("parseIE err 4!\n"); + return ERROR_INVALID_RSNIE; + } + + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) { + DEBUG_WARN("parseIE err 5!\n"); + return ERROR_INVALID_MULTICASTCIPHER; + } + + if (pDot11RSNIESuite->Type != priv->wpa_global_info->MulticastCipher) { + DEBUG_WARN("parseIE err 6!\n"); + return ERROR_INVALID_MULTICASTCIPHER; + } + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (pDot11RSNIESuite->Type != DOT11_ENC_CCMP) { + PMFDEBUG("Invalid WPA group cipher %d\n", pDot11RSNIESuite->Type); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } +#endif + + ulIELength -= sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(DOT11_RSN_IE_SUITE); + + //---------------------------------------------------------------------------------- + // Pairwise Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x50 || + pDot11RSNIESuite->OUI[2] != 0xF2) { + DEBUG_WARN("parseIE err 7!\n"); + return ERROR_INVALID_RSNIE; + } + + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) { + DEBUG_WARN("parseIE err 8!\n"); + return ERROR_INVALID_UNICASTCIPHER; + } + + if ((pDot11RSNIESuite->Type < DOT11_ENC_WEP40) + || (!(BIT(pDot11RSNIESuite->Type - 1) & priv->pmib->dot1180211AuthEntry.dot11WPACipher))) { + DEBUG_WARN("parseIE err 9!\n"); + return ERROR_INVALID_UNICASTCIPHER; + } + + pInfo->UnicastCipher = pDot11RSNIESuite->Type; + +#ifdef DEBUG_PSK + printk("PSK: ParseIE -> WPA UnicastCipher=%x\n", pInfo->UnicastCipher); +#endif + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (pInfo->UnicastCipher == DOT11_ENC_TKIP) { + PMFDEBUG("Management frame protection cannot use TKIP\n"); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } +#endif + ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + + //---------------------------------------------------------------------------------- + // Authentication suite + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x50 || + pDot11RSNIESuite->OUI[2] != 0xF2 ) { + DEBUG_WARN("parseIE err 10!\n"); + return ERROR_INVALID_RSNIE; + } + + if( pDot11RSNIESuite->Type < DOT11_AuthKeyType_RSN || + pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK) { + DEBUG_WARN("parseIE err 11!\n"); + return ERROR_INVALID_AUTHKEYMANAGE; + } + + if(pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK) { + DEBUG_WARN("parseIE err 12!\n"); + return ERROR_INVALID_AUTHKEYMANAGE; + } + + pInfo->AuthKeyMethod = pDot11RSNIESuite->Type; + ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + + // RSN Capability + if (ulIELength < sizeof(DOT11_RSN_CAPABILITY)) + return 0; + +//#ifndef RTL_WPA2 +#if 0 + //---------------------------------------------------------------------------------- + // Capability field + //---------------------------------------------------------------------------------- + pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE; + pInfo->isSuppSupportPreAuthentication = pDot11RSNCapability->field.PreAuthentication; + pInfo->isSuppSupportPairwiseAsDefaultKey = pDot11RSNCapability->field.PairwiseAsDefaultKey; + + switch (pDot11RSNCapability->field.NumOfReplayCounter) { + case 0: + pInfo->NumOfRxTSC = 1; + break; + case 1: + pInfo->NumOfRxTSC = 2; + break; + case 2: + pInfo->NumOfRxTSC = 4; + break; + case 3: + pInfo->NumOfRxTSC = 16; + break; + default: + pInfo->NumOfRxTSC = 1; + } +#endif /* RTL_WPA2 */ + +#ifdef CONFIG_IEEE80211W + pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE; + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (!pDot11RSNCapability->field.MFPC) { + PMFDEBUG("Management frame protection Required, but client did not enable it\n"); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } + + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION || + !(pDot11RSNCapability->field.MFPC)) + pInfo->mgmt_frame_prot = 0; + else + pInfo->mgmt_frame_prot = 1; + + PMFDEBUG("mgmt_frame_prot=%d\n", pInfo->mgmt_frame_prot); +#endif // CONFIG_IEEE80211W + + return 0; +} + +#ifdef RTL_WPA2 +static int parseIEWPA2(struct rtl8192cd_priv *priv, WPA_STA_INFO *pInfo, + unsigned char *pucIE, unsigned int ulIELength) +{ + unsigned short usSuitCount; + DOT11_WPA2_IE_HEADER *pDot11WPA2IEHeader = NULL; + DOT11_RSN_IE_SUITE *pDot11RSNIESuite = NULL; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite = NULL; + DOT11_RSN_CAPABILITY *pDot11RSNCapability = NULL; + + DEBUG_TRACE; + + if (ulIELength < sizeof(DOT11_WPA2_IE_HEADER)) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 1!\n"); + return ERROR_INVALID_RSNIE; + } + + pDot11WPA2IEHeader = (DOT11_WPA2_IE_HEADER *)pucIE; + if (le16_to_cpu(pDot11WPA2IEHeader->Version) != RSN_VER1) { + DEBUG_WARN("ERROR_UNSUPPORTED_RSNEVERSION, err 2!\n"); + return ERROR_UNSUPPORTED_RSNEVERSION; + } + + if (pDot11WPA2IEHeader->ElementID != WPA2_ELEMENT_ID || + pDot11WPA2IEHeader->Length != ulIELength -2 ) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 3!\n"); + return ERROR_INVALID_RSNIE; + } + + pInfo->RSNEnabled= PSK_WPA2; + pInfo->PMKCached= FALSE; + + ulIELength -= sizeof(DOT11_WPA2_IE_HEADER); + pucIE += sizeof(DOT11_WPA2_IE_HEADER); + + //---------------------------------------------------------------------------------- + // Multicast Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIESuite = (DOT11_RSN_IE_SUITE *)pucIE; + if (pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 4!\n"); + return ERROR_INVALID_RSNIE; + } + +#ifdef CONFIG_IEEE80211W + if (pDot11RSNIESuite->Type > DOT11_ENC_BIP) { +#else + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) { +#endif + DEBUG_WARN("ERROR_INVALID_MULTICASTCIPHER, err 5!\n"); + return ERROR_INVALID_MULTICASTCIPHER; + } + + if (pDot11RSNIESuite->Type != priv->wpa_global_info->MulticastCipher) { + DEBUG_WARN("ERROR_INVALID_MULTICASTCIPHER, err 6!\n"); + return ERROR_INVALID_MULTICASTCIPHER; + } +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (pDot11RSNIESuite->Type != DOT11_ENC_CCMP) { + DEBUG_WARN("Invalid WPA group cipher %d\n", pDot11RSNIESuite->Type); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } +#endif + + ulIELength -= sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(DOT11_RSN_IE_SUITE); + + //---------------------------------------------------------------------------------- + // Pairwise Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 7!\n"); + return ERROR_INVALID_RSNIE; + } + + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) { + DEBUG_WARN("ERROR_INVALID_UNICASTCIPHER, err 8!\n"); + return ERROR_INVALID_UNICASTCIPHER; + } + + if ((pDot11RSNIESuite->Type < DOT11_ENC_WEP40) + || (!(BIT(pDot11RSNIESuite->Type - 1) & priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher))) { + DEBUG_WARN("ERROR_INVALID_UNICASTCIPHER, err 9!\n"); + return ERROR_INVALID_UNICASTCIPHER; + } + + pInfo->UnicastCipher = pDot11RSNIESuite->Type; +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (pInfo->UnicastCipher == DOT11_ENC_TKIP) { + DEBUG_WARN("Management frame protection cannot use TKIP\n"); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } +#endif + + ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + +#ifdef DEBUG_PSK + printk("PSK: ParseIE -> WPA2 UnicastCipher=%x\n", pInfo->UnicastCipher); +#endif + + //---------------------------------------------------------------------------------- + // Authentication suite + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC ) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 10!\n"); + return ERROR_INVALID_RSNIE; + } + + if (pDot11RSNIESuite->Type < DOT11_AuthKeyType_RSN || +#ifdef CONFIG_IEEE80211W + pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK_SHA256 +#else + pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK +#endif + ) { + DEBUG_WARN("ERROR_INVALID_AUTHKEYMANAGE, err 11!\n"); + return ERROR_INVALID_AUTHKEYMANAGE; + } + + if (pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK +#ifdef CONFIG_IEEE80211W + && pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK_SHA256 +#endif + ) { + DEBUG_WARN("ERROR_INVALID_AUTHKEYMANAGE, err 12!\n"); + return ERROR_INVALID_AUTHKEYMANAGE; + } + + pInfo->AuthKeyMethod = pDot11RSNIESuite->Type; + ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + + // RSN Capability + if (ulIELength < sizeof(DOT11_RSN_CAPABILITY)) { + pInfo->NumOfRxTSC = 2; + return 0; + } + + //---------------------------------------------------------------------------------- + // Capability field + //---------------------------------------------------------------------------------- + pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE; +#if 0 + global->RSNVariable.isSuppSupportPreAuthentication = pDot11RSNCapability->field.PreAuthentication; +//#ifdef RTL_WPA2_PREAUTH // kenny temp + //wpa2_hexdump("WPA2 IE Capability", pucIE, 2); + //global->RSNVariable.isSuppSupportPreAuthentication = (pDot11RSNCapability->charData[0] & 0x01)?TRUE:FALSE; +#endif + +#if 1 + pInfo->NumOfRxTSC = 1; +#else + global->RSNVariable.isSuppSupportPairwiseAsDefaultKey = pDot11RSNCapability->field.PairwiseAsDefaultKey; + switch (pDot11RSNCapability->field.NumOfReplayCounter) { + case 0: + global->RSNVariable.NumOfRxTSC = 1; + break; + case 1: + global->RSNVariable.NumOfRxTSC = 2; + break; + case 2: + global->RSNVariable.NumOfRxTSC = 4; + break; + case 3: + global->RSNVariable.NumOfRxTSC = 16; + break; + default: + global->RSNVariable.NumOfRxTSC = 1; + } +#endif + //pucIE += 2; + +#ifdef CONFIG_IEEE80211W + pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE; + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (!pDot11RSNCapability->field.MFPC) { + printk("Management frame protection Required, but client did not enable it\n"); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } + + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION || + !(pDot11RSNCapability->field.MFPC)) + pInfo->mgmt_frame_prot = 0; + else + pInfo->mgmt_frame_prot = 1; + + PMFDEBUG("mgmt_frame_prot=%d\n", pInfo->mgmt_frame_prot); +#endif // CONFIG_IEEE80211W + + pucIE += 2; + ulIELength -= 2; + // PMKID + if ((ulIELength < 2 + PMKID_LEN)) + return 0; + + //---------------------------------------------------------------------------------- + // PMKID Count field + //---------------------------------------------------------------------------------- + usSuitCount = le16_to_cpu(*((unsigned short *)pucIE)); + + //printf("PMKID Count = %d\n",usSuitCount); + pucIE += 2; + ulIELength -= 2; +/* + if ( usSuitCount > 0) { + struct _WPA2_PMKSA_Node* pmksa_node; + int i; + for (i=0; i < usSuitCount; i++) { + pmksa_node = find_pmksa(pucIE+(PMKID_LEN*i)); + if ( pmksa_node != NULL) { + //wpa2_hexdump("Cached PMKID found", pmksa_node->pmksa.pmkid, PMKID_LEN); + global->RSNVariable.PMKCached = TRUE; + global->RSNVariable.cached_pmk_node = pmksa_node; + break; + } + } + + } +*/ + +#ifdef CONFIG_IEEE80211W + pucIE += PMKID_LEN * usSuitCount; + printk("usSuitCount=%d, ulIELength=%d\n", usSuitCount, ulIELength); + ulIELength -= PMKID_LEN * usSuitCount; + //---------------------------------------------------------------------------------- + // Group Management Cipher field (IGTK) + //---------------------------------------------------------------------------------- + if ((ulIELength < sizeof(DOT11_RSN_IE_SUITE))) { + return 0; + } + + pDot11RSNIESuite = (DOT11_RSN_IE_SUITE*)pucIE; + + if (pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC) { + printk("RSNIE Suite OUI = %02x:%02x:%02x\n", pDot11RSNIESuite->OUI[0], pDot11RSNIESuite->OUI[1], pDot11RSNIESuite->OUI[2]); + return ERROR_INVALID_RSNIE; + } + if (pDot11RSNIESuite->Type != DOT11_ENC_BIP) { + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } +#endif // CONFIG_IEEE80211W + + return 0; +} +#endif // RTL_WPA2 + +static void GenNonce(unsigned char *nonce, unsigned char *addr) +{ + unsigned char secret[256], random[256], result[256]; + + get_random_bytes(random, 256); + memset(secret, 0, sizeof(secret)); + + i_PRF(secret, sizeof(secret), (unsigned char*)RANDOM_EXPANSION_CONST, RANDOM_EXPANSION_CONST_SIZE, + random, sizeof(random), result, KEY_NONCE_LEN); + + memcpy(nonce, result, KEY_NONCE_LEN); +} + +static void IntegrityFailure(struct rtl8192cd_priv *priv) +{ + priv->wpa_global_info->IntegrityFailed = FALSE; + + if (priv->wpa_global_info->GKeyFailure) { + priv->wpa_global_info->GTKRekey = TRUE; + priv->wpa_global_info->GKeyFailure = FALSE; + } + + //waitupto60; + INCOctet32_INTEGER(&priv->wpa_global_info->Counter); +// SetNonce(global->akm_sm->ANonce, global->auth->Counter); + + INCOctet32_INTEGER(&priv->wpa_global_info->Counter); +// SetNonce(global->akm_sm->ANonce, global->auth->Counter); +} + +static void ToDrv_RspAssoc(struct rtl8192cd_priv *priv, int id, unsigned char *mac, int status) +{ + DOT11_ASSOCIATIIN_RSP Association_Rsp; + struct iw_point wrq; + + DEBUG_TRACE; + +#ifdef DEBUG_PSK + printk("PSK: Issue assoc-rsp [%x], mac:%02x:%02x:%02x:%02x:%02x:%02x\n", + status, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +#endif + + wrq.pointer = (caddr_t)&Association_Rsp; + wrq.length = sizeof(DOT11_ASSOCIATIIN_RSP); + + if (id == DOT11_EVENT_ASSOCIATION_IND) + Association_Rsp.EventId = DOT11_EVENT_ASSOCIATION_RSP; + else + Association_Rsp.EventId = DOT11_EVENT_REASSOCIATION_RSP; + + Association_Rsp.IsMoreEvent = FALSE; + Association_Rsp.Status = status; + memcpy(Association_Rsp.MACAddr, mac, 6); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + + +static void ToDrv_RemovePTK(struct rtl8192cd_priv *priv, unsigned char *mac, int type) +{ + struct iw_point wrq; + DOT11_DELETE_KEY Delete_Key; + +#ifdef DEBUG_PSK + printk("PSK: Remove PTK, mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +#endif + + wrq.pointer = (caddr_t)&Delete_Key; + wrq.length = sizeof(DOT11_DELETE_KEY); + + Delete_Key.EventId = DOT11_EVENT_DELETE_KEY; + Delete_Key.IsMoreEvent = FALSE; + Delete_Key.KeyType = type; + memcpy(&Delete_Key.MACAddr, mac, 6); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +#ifdef CONFIG_IEEE80211W +static void ToDrv_SetPMF(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int retVal = 0; + struct iw_point wrq; + DOT11_SET_11W_Flags flags; + + PMFDEBUG("Drv:setPMF=%d\n", pstat->wpa_sta_info->mgmt_frame_prot); + flags.EventId = DOT11_EVENT_SET_PMF; + flags.IsMoreEvent = FALSE; + flags.isPMF = pstat->wpa_sta_info->mgmt_frame_prot; + + memcpy(flags.macAddr, pstat->hwaddr, 6); + + wrq.pointer = &flags; + wrq.length = sizeof(flags); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +static void ToDrv_SetIGTK(struct rtl8192cd_priv *priv) +{ + int retVal = 0; + u_long ulKeyLength = 0; + struct iw_point wrq; + DOT11_SET_KEY Set_Key; + u_char szBradcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + /* + u_char szDefaultKey[16] = {0x11, 0x11,0x11, 0x11,0x11, 0x11,0x11, 0x11, + 0x11, 0x11,0x11, 0x11,0x11, 0x11,0x11, 0x11}; + */ + PMFDEBUG("\n"); + wrq.pointer = &Set_Key; + + Set_Key.EventId = DOT11_EVENT_SET_KEY; + Set_Key.IsMoreEvent = FALSE; + Set_Key.KeyIndex = priv->wpa_global_info->GN_igtk; + Set_Key.KeyType = DOT11_KeyType_IGTK; + memcpy(&Set_Key.MACAddr, szBradcast, 6); + + Set_Key.EncType = DOT11_ENC_BIP; + //sc_yang + memset(Set_Key.KeyMaterial, 0, 64); + + // Set IGTK + memcpy(Set_Key.KeyMaterial , + priv->wpa_global_info->IGTK[priv->wpa_global_info->GN_igtk - 4] , + 16); + + + wrq.length = sizeof(DOT11_SET_KEY) - 1 + 16; + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); + +} +#endif // CONFIG_IEEE80211W + +static void ToDrv_SetPTK(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned long ulKeyLength = 0; + unsigned char *pucKeyMaterial = 0; + struct iw_point wrq; + DOT11_SET_KEY Set_Key; + +#ifdef DEBUG_PSK + printk("PSK: Set PTK, mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); +#endif + + wrq.pointer = (caddr_t)&Set_Key; + Set_Key.EventId = DOT11_EVENT_SET_KEY; + Set_Key.IsMoreEvent = FALSE; + Set_Key.KeyIndex = 0; + Set_Key.KeyType = DOT11_KeyType_Pairwise; + +#ifdef MULTI_MAC_CLONE + if ((OPMODE & WIFI_STATION_STATE) && priv->pmib->ethBrExtInfo.macclone_enable) + memcpy(&Set_Key.MACAddr, pstat->sa_addr, 6); + else +#endif + memcpy(&Set_Key.MACAddr, pstat->hwaddr, 6); + + switch (pstat->wpa_sta_info->UnicastCipher) { + case DOT11_ENC_TKIP: + ulKeyLength = PTK_LEN_TKIP - (PTK_LEN_EAPOLMIC + PTK_LEN_EAPOLENC); + break; + + // Kenny + case DOT11_ENC_CCMP: + ulKeyLength = PTK_LEN_CCMP - (PTK_LEN_EAPOLMIC + PTK_LEN_EAPOLENC); + break; + } + pucKeyMaterial = pstat->wpa_sta_info->PTK + (PTK_LEN_EAPOLMIC + PTK_LEN_EAPOLENC); + + //sc_yang + memset(Set_Key.KeyMaterial,0, 64); + memcpy(Set_Key.KeyMaterial, pucKeyMaterial, ulKeyLength); + Set_Key.EncType = pstat->wpa_sta_info->UnicastCipher; + Set_Key.KeyLen = ulKeyLength; + wrq.length = sizeof(DOT11_SET_KEY) - 1 + ulKeyLength; + +#ifdef DEBUG_PSK + debug_out(NULL, Set_Key.KeyMaterial, ulKeyLength); +#endif + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +void ToDrv_SetGTK(struct rtl8192cd_priv *priv) +{ + unsigned long ulKeyLength = 0; + //unsigned long ulKeyIndex = 0; + struct iw_point wrq; + DOT11_SET_KEY Set_Key; + unsigned char szBradcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + memset(&Set_Key, 0, sizeof(DOT11_SET_KEY)); + +#ifdef DEBUG_PSK + printk("PSK: Set GTK\n"); +#endif + + wrq.pointer = (caddr_t)&Set_Key; + wrq.length = sizeof(DOT11_SET_KEY); + + Set_Key.EventId = DOT11_EVENT_SET_KEY; + Set_Key.IsMoreEvent = FALSE; + + Set_Key.KeyType = DOT11_KeyType_Group; + memcpy(&Set_Key.MACAddr, szBradcast, 6); + + Set_Key.EncType = priv->wpa_global_info->MulticastCipher; + //sc_yang + memset(Set_Key.KeyMaterial,0, 64); + ulKeyLength = 32; +#ifdef CLIENT_MODE + if (OPMODE & WIFI_ADHOC_STATE) { + memcpy(Set_Key.KeyMaterial, priv->wpa_global_info->PSK, ulKeyLength); + Set_Key.KeyIndex = 0; + } else +#endif + { + //ulKeyIndex = priv->wpa_global_info->GN; +#ifdef CONFIG_IEEE80211W + if (priv->wpa_global_info->MulticastCipher == DOT11_ENC_BIP) { + memcpy(Set_Key.KeyMaterial, + priv->wpa_global_info->IGTK[priv->wpa_global_info->GN_igtk], + ulKeyLength); + Set_Key.KeyIndex = priv->wpa_global_info->GN_igtk; + + } else +#endif + { + memcpy(Set_Key.KeyMaterial, + priv->wpa_global_info->GTK[priv->wpa_global_info->GN], + ulKeyLength); + Set_Key.KeyIndex = priv->wpa_global_info->GN; + } + } + + wrq.length = sizeof(DOT11_SET_KEY) - 1 + ulKeyLength; + wrq.length = sizeof(DOT11_SET_KEY) - 1 + ulKeyLength; + +#ifdef DEBUG_PSK + debug_out(NULL, Set_Key.KeyMaterial, ulKeyLength); +#endif + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + + + +static void ToDrv_SetPort(struct rtl8192cd_priv *priv, struct stat_info *pstat, int status) +{ + struct iw_point wrq; + DOT11_SET_PORT Set_Port; + +#ifdef DEBUG_PSK + printk("PSK: Set PORT [%x], mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + status, pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); +#endif + + wrq.pointer = (caddr_t)&Set_Port; + wrq.length = sizeof(DOT11_SET_PORT); + Set_Port.EventId = DOT11_EVENT_SET_PORT; + Set_Port.PortStatus = status; + memcpy(&Set_Port.MACAddr, pstat->hwaddr, 6); + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +static void ToDrv_SetIE(struct rtl8192cd_priv *priv) +{ + struct iw_point wrq; + DOT11_SET_RSNIE Set_Rsnie; + +#ifdef DEBUG_PSK + debug_out("PSK: Set RSNIE", priv->wpa_global_info->AuthInfoElement.Octet, + priv->wpa_global_info->AuthInfoElement.Length); +#endif + + wrq.pointer = (caddr_t)&Set_Rsnie; + wrq.length = sizeof(DOT11_SET_RSNIE); + Set_Rsnie.EventId = DOT11_EVENT_SET_RSNIE; + Set_Rsnie.IsMoreEvent = FALSE; + Set_Rsnie.Flag = DOT11_Ioctl_Set; + Set_Rsnie.RSNIELen = priv->wpa_global_info->AuthInfoElement.Length; + memcpy(&Set_Rsnie.RSNIE, + priv->wpa_global_info->AuthInfoElement.Octet, + priv->wpa_global_info->AuthInfoElement.Length); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +static void ToDrv_DisconnectSTA(struct rtl8192cd_priv *priv, struct stat_info *pstat, int reason) +{ + struct iw_point wrq; + DOT11_DISCONNECT_REQ Disconnect_Req; + +#ifdef DEBUG_PSK + printk("PSK: disconnect sta, mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); +#endif + + wrq.pointer = (caddr_t)&Disconnect_Req; + wrq.length = sizeof(DOT11_DISCONNECT_REQ); + + Disconnect_Req.EventId = DOT11_EVENT_DISCONNECT_REQ; + Disconnect_Req.IsMoreEvent = FALSE; + Disconnect_Req.Reason = (unsigned short)reason; + memcpy(Disconnect_Req.MACAddr, pstat->hwaddr, 6); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +}; + +static void ToDrv_IndicateMICFail(struct rtl8192cd_priv *priv, unsigned char *mac) +{ + struct iw_point wrq; + DOT11_MIC_FAILURE MIC_Failure; + + wrq.pointer = (caddr_t)&MIC_Failure; + wrq.length = sizeof(DOT11_INIT_QUEUE); + + MIC_Failure.EventId = DOT11_EVENT_MIC_FAILURE; + memcpy(MIC_Failure.MACAddr, mac, 6); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +static void reset_sta_info(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + WPA_STA_INFO *pInfo = pstat->wpa_sta_info; + + unsigned long flags; + + SAVE_INT_AND_CLI(flags); + + SMP_LOCK_PSK_RESEND(flags); + if (timer_pending(&pInfo->resendTimer)){ + del_timer(&pInfo->resendTimer); + } + SMP_UNLOCK_PSK_RESEND(flags); + + if (OPMODE & WIFI_AP_STATE) { + ToDrv_RemovePTK(priv, pstat->hwaddr, DOT11_KeyType_Pairwise); + ToDrv_SetPort(priv, pstat, DOT11_PortStatus_Unauthorized); + } + + memset((char *)pInfo, '\0', sizeof(WPA_STA_INFO)); + + pInfo->ANonce.Octet = pInfo->AnonceBuf; + pInfo->ANonce.Length = KEY_NONCE_LEN; + + pInfo->SNonce.Octet = pInfo->SnonceBuf; + pInfo->SNonce.Length = KEY_NONCE_LEN; + + pInfo->EAPOLMsgSend.Octet = pInfo->eapSendBuf; + pInfo->EapolKeyMsgSend.Octet = pInfo->EAPOLMsgSend.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN; + + pInfo->EAPOLMsgRecvd.Octet = pInfo->eapRecvdBuf; + pInfo->EapolKeyMsgRecvd.Octet = pInfo->EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN; + + init_timer(&pInfo->resendTimer); + pInfo->resendTimer.data = (unsigned long)pstat; + pInfo->resendTimer.function = ResendTimeout; + + pInfo->priv = priv; + + if (OPMODE & WIFI_AP_STATE) { + pInfo->state = PSK_STATE_IDLE; + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) { + memcpy(pInfo->PMK, priv->wpa_global_info->PSK, PMK_LEN); + + pInfo->clientHndshkProcessing = FALSE; + pInfo->clientHndshkDone = FALSE; + + pInfo->CurrentReplayCounter.field.HighPart = 0xffffffff; + pInfo->CurrentReplayCounter.field.LowPart = 0xffffffff; + } +#endif + + RESTORE_INT(flags); +} + + +static void ResendTimeout(unsigned long task_psta) +{ + struct stat_info *pstat = (struct stat_info *)task_psta; + struct rtl8192cd_priv *priv = pstat->wpa_sta_info->priv; +#ifdef SMP_SYNC + unsigned long flags; +#endif + + DEBUG_TRACE; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (pstat == NULL) + return; + + SMP_LOCK_PSK_RESEND(flags); +#ifdef CLIENT_MODE +#ifdef MULTI_MAC_CLONE + ACTIVE_ID = pstat->mclone_id; +#endif + if ((OPMODE & WIFI_STATION_STATE) && !pstat->wpa_sta_info->clientHndshkProcessing) { + DEBUG_ERR("Wait EAP timeout, disconnect AP!\n"); + priv->dot114WayStatus = _RSON_4WAY_HNDSHK_TIMEOUT_; + ToDrv_DisconnectSTA(priv, pstat, expire); + SMP_UNLOCK_PSK_RESEND(flags); + return; + } +#endif + + if (++pstat->wpa_sta_info->resendCnt > MAX_RESEND_NUM) + { + +// When the case of group rekey timeout, update GTK to driver when it is +// the last one node + if (OPMODE & WIFI_AP_STATE) { + if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITDONE && + pstat->wpa_sta_info->gstate == PSK_GSTATE_REKEYNEGOTIATING) { + if (priv->wpa_global_info->GKeyDoneStations > 0) + priv->wpa_global_info->GKeyDoneStations--; + + if (priv->wpa_global_info->GKeyDoneStations==0 && !priv->wpa_global_info->GkeyReady) { + ToDrv_SetGTK(priv); +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != NO_MGMT_FRAME_PROTECTION) + ToDrv_SetIGTK(priv); +#endif + priv->wpa_global_info->GkeyReady = TRUE; + priv->wpa_global_info->GResetCounter = TRUE; + + // start groupkey rekey timer + if (priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime) + mod_timer(&priv->wpa_global_info->GKRekeyTimer, jiffies + RTL_SECONDS_TO_JIFFIES(priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime)); + + // if only one sta and group key rekey fail, don't disconnect the sta + if (get_assoc_sta_num(priv, 0) == 1) { +#ifdef DEBUG_PSK + printk("!!!!DO NOT disconnect STA under 1 client case!!!\n"); +#endif + SMP_UNLOCK_PSK_RESEND(flags); + return; + } + + } + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) { + priv->dot114WayStatus = _RSON_4WAY_HNDSHK_TIMEOUT_; + } +#endif +//--------------------------------------------------------- david+2006-04-06 + + ToDrv_DisconnectSTA(priv, pstat, RSN_4_way_handshake_timeout); +// need not reset because ToDrv_DisconnectSTA() will take care of it, david+2006-04-06 +// reset_sta_info(priv, pstat); + +#ifdef DEBUG_PSK + printk("PSK: Exceed max retry, disconnect sta\n"); +#endif +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) && defined(CLIENT_MODE) + if (OPMODE & WIFI_STATION_STATE) { + if (priv->link_status_cb_func) + priv->link_status_cb_func("wlan0", WIFI_LINK_STATUS_HANDSHAKE_TIMEOUT); + } +#endif + } else { + if (OPMODE & WIFI_AP_STATE) + SendEAPOL(priv, pstat, 1); +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + ClientSendEAPOL(priv, pstat, 0); +#endif + } + + SMP_UNLOCK_PSK_RESEND(flags); +} + + +static void GKRekeyTimeout(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned long flags = 0; +#ifdef SMP_SYNC + unsigned long flags2; +#endif + + DEBUG_TRACE; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + SAVE_INT_AND_CLI(flags); +// SMP_LOCK(flags); + + SMP_LOCK_PSK_GKREKEY(flags2); + priv->wpa_global_info->GTKRekey = TRUE; + SMP_UNLOCK_PSK_GKREKEY(flags2); + UpdateGK(priv); + + RESTORE_INT(flags); +// SMP_UNLOCK(flags); +} + +static void SendEAPOL(struct rtl8192cd_priv *priv, struct stat_info *pstat, int resend) +{ + OCTET_STRING IV, RSC, KeyID, MIC, KeyData, EAPOLMsgSend, EapolKeyMsgSend; + unsigned char IV_buff[KEY_IV_LEN], RSC_buff[KEY_RSC_LEN]; + unsigned char ID_buff[KEY_ID_LEN], MIC_buff[KEY_MIC_LEN], KEY_buff[INFO_ELEMENT_SIZE]; + unsigned short tmpKeyData_Length; + unsigned char KeyDescriptorVer=key_desc_ver1; + int IfCalcMIC = 0; + struct wlan_ethhdr_t *eth_hdr; + struct lib1x_eapol *eapol; + struct sk_buff *pskb; + lib1x_eapol_key *eapol_key; + WPA_STA_INFO *pStaInfo; + WPA_GLOBAL_INFO *pGblInfo; + + DEBUG_TRACE; + + if (priv == NULL || pstat == NULL) + return; + + pStaInfo = pstat->wpa_sta_info; + pGblInfo = priv->wpa_global_info; + + if (pStaInfo->state == PSK_STATE_IDLE) + return; + + memset(&EapolKeyMsgSend, 0, sizeof(EapolKeyMsgSend)); + EAPOLMsgSend.Octet = pStaInfo->EAPOLMsgSend.Octet; + EapolKeyMsgSend.Octet = EAPOLMsgSend.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN; + pStaInfo->EapolKeyMsgSend.Octet = EapolKeyMsgSend.Octet; + eapol_key = (lib1x_eapol_key *)EapolKeyMsgSend.Octet; + +#ifdef CONFIG_IEEE80211W + if (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK_SHA256) + KeyDescriptorVer = key_desc_ver3; + else +#endif + if ((pGblInfo->MulticastCipher == _CCMP_PRIVACY_) || (pStaInfo->UnicastCipher == _CCMP_PRIVACY_)) + KeyDescriptorVer = key_desc_ver2; + + if (resend) { + EAPOLMsgSend.Length = pStaInfo->EAPOLMsgSend.Length; + EapolKeyMsgSend.Length = pStaInfo->EapolKeyMsgSend.Length; + Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->CurrentReplayCounter.field.HighPart, pStaInfo->CurrentReplayCounter.field.LowPart); + INCLargeInteger(&pStaInfo->CurrentReplayCounter); + IfCalcMIC = TRUE; + goto send_packet; + } + + IV.Octet = IV_buff; + IV.Length = KEY_IV_LEN; + RSC.Octet = RSC_buff; + RSC.Length = KEY_RSC_LEN; + KeyID.Octet = ID_buff; + KeyID.Length = KEY_ID_LEN; + MIC.Octet = MIC_buff; + MIC.Length = KEY_MIC_LEN; + KeyData.Octet = KEY_buff; + KeyData.Length = 0; + + switch(pStaInfo->state) { + case PSK_STATE_PTKSTART: + //send 1st message of 4-way handshake + DEBUG_INFO("4-1\n"); + PSKDEBUG("4-1\n"); + memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN); + +#ifdef RTL_WPA2 + if (pStaInfo->RSNEnabled & PSK_WPA2) + Message_setDescType(EapolKeyMsgSend, desc_type_WPA2); + else +#endif + Message_setDescType(EapolKeyMsgSend, desc_type_RSN); + + Message_setKeyDescVer(EapolKeyMsgSend, KeyDescriptorVer); + Message_setKeyType(EapolKeyMsgSend, type_Pairwise); + Message_setKeyIndex(EapolKeyMsgSend, 0); + Message_setInstall(EapolKeyMsgSend, 0); + Message_setKeyAck(EapolKeyMsgSend, 1); + Message_setKeyMIC(EapolKeyMsgSend, 0); + Message_setSecure(EapolKeyMsgSend, 0); + Message_setError(EapolKeyMsgSend, 0); + Message_setRequest(EapolKeyMsgSend, 0); + Message_setReserved(EapolKeyMsgSend, 0); + Message_setKeyLength(EapolKeyMsgSend, (pStaInfo->UnicastCipher == DOT11_ENC_TKIP) ? 32:16); +// Message_setKeyLength(EapolKeyMsgSend, 32); + + // make 4-1's ReplyCounter increased + Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->CurrentReplayCounter.field.HighPart, pStaInfo->CurrentReplayCounter.field.LowPart); + memcpy(&pStaInfo->ReplayCounterStarted, &pStaInfo->CurrentReplayCounter, sizeof(LARGE_INTEGER)); // save started reply counter, david+1-12-2007 + + INCLargeInteger(&pStaInfo->CurrentReplayCounter); + + INCOctet32_INTEGER(&pGblInfo->Counter); +//#ifndef RTL_WPA2_PREAUTH + // ANonce is only updated in lib1x_init_authenticator() + // or after 4-way handshake + // To avoid different ANonce values among multiple issued 4-1 messages because of multiple association requests + // Different ANonce values among multiple 4-1 messages induce 4-2 MIC failure. + SetNonce(pStaInfo->ANonce, pGblInfo->Counter); +//#endif + Message_setKeyNonce(EapolKeyMsgSend, pStaInfo->ANonce); + + memset(IV.Octet, 0, IV.Length); + Message_setKeyIV(EapolKeyMsgSend, IV); + memset(RSC.Octet, 0, RSC.Length); + Message_setKeyRSC(EapolKeyMsgSend, RSC); + memset(KeyID.Octet, 0, KeyID.Length); + Message_setKeyID(EapolKeyMsgSend, KeyID); + +// enable it to interoper with Intel 11n Centrino, david+2007-11-19 +#if 1 + // otherwise PMK cache + if ((pStaInfo->RSNEnabled & PSK_WPA2) && (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK || pStaInfo->PMKCached) ) { + static char PMKID_KDE_TYPE[] = { 0xDD, 0x14, 0x00, 0x0F, 0xAC, 0x04 }; + Message_setKeyDataLength(EapolKeyMsgSend, 22); + memcpy(EapolKeyMsgSend.Octet + KeyDataPos, + PMKID_KDE_TYPE, sizeof(PMKID_KDE_TYPE)); +// memcpy(EapolKeyMsgSend.Octet+KeyDataPos+sizeof(PMKID_KDE_TYPE), +// global->akm_sm->PMKID, PMKID_LEN); + } else +#endif + Message_setKeyDataLength(EapolKeyMsgSend, 0); + + memset(MIC.Octet, 0, MIC.Length); + Message_setMIC(EapolKeyMsgSend, MIC); + +#ifdef RTL_WPA2 + if (pStaInfo->RSNEnabled & PSK_WPA2) + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + Message_KeyDataLength(EapolKeyMsgSend); + else +#endif + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN; + EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length; + break; + + case PSK_STATE_PTKINITNEGOTIATING: + + //Construct Message3 + DEBUG_INFO("4-3\n"); + PSKDEBUG("4-3\n"); + memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN); + +#ifdef RTL_WPA2 + if (pStaInfo->RSNEnabled & PSK_WPA2) + Message_setDescType(EapolKeyMsgSend, desc_type_WPA2); + else +#endif + Message_setDescType(EapolKeyMsgSend, desc_type_RSN); + + Message_setKeyDescVer(EapolKeyMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyType(EapolKeyMsgSend, Message_KeyType(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyIndex(EapolKeyMsgSend, Message_KeyIndex(pStaInfo->EapolKeyMsgRecvd)); + + //Message_setInstall(global->EapolKeyMsgSend, global->RSNVariable.isSuppSupportUnicastCipher ? 1:0); + Message_setInstall(EapolKeyMsgSend, 1); + Message_setKeyAck(EapolKeyMsgSend, 1); + Message_setKeyMIC(EapolKeyMsgSend, 1); + //?? + // Message_setSecure(pStaInfo->EapolKeyMsgSend, pStaInfo->RSNVariable.isSuppSupportMulticastCipher ? 0:1); + Message_setSecure(EapolKeyMsgSend, 0); + //?? + Message_setError(EapolKeyMsgSend, 0); + Message_setRequest(EapolKeyMsgSend, 0); + Message_setReserved(EapolKeyMsgSend, 0); + Message_setKeyLength(EapolKeyMsgSend, (pStaInfo->UnicastCipher == DOT11_ENC_TKIP) ? 32:16); + Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->CurrentReplayCounter.field.HighPart, pStaInfo->CurrentReplayCounter.field.LowPart); + Message_setKeyNonce(EapolKeyMsgSend, pStaInfo->ANonce); + memset(IV.Octet, 0, IV.Length); + Message_setKeyIV(EapolKeyMsgSend, IV); + +#ifdef RTL_WPA2 + if (pStaInfo->RSNEnabled & PSK_WPA2) { + unsigned char key_data[128]; + unsigned char *key_data_pos = key_data; + int i; + int mcastcipher = (pGblInfo->MulticastCipher == DOT11_ENC_TKIP)?32:16; + unsigned char GTK_KDE_TYPE[] = {0xDD, 0x16, 0x00, 0x0F, 0xAC, 0x01, 0x01, 0x00 }; +#ifdef CONFIG_IEEE80211W + unsigned char IGTK_KDE_TYPE[] = {0xDD, 0x1C, 0x00, 0x0F, 0xAC, 0x09}; +#endif + + EapolKeyMsgSend.Octet[1] = 0x13; +//??? + if (KeyDescriptorVer == key_desc_ver2 +#ifdef CONFIG_IEEE80211W + || KeyDescriptorVer == key_desc_ver3 +#endif + ) { + INCOctet32_INTEGER(&pGblInfo->Counter); + SetEAPOL_KEYIV(IV, pGblInfo->Counter); + //memset(IV.Octet, 0x0, IV.Length); + Message_setKeyIV(EapolKeyMsgSend, IV); + } + // RSN IE + if (pGblInfo->AuthInfoElement.Octet[0] == WPA2_ELEMENT_ID) { + int len = (unsigned char)pGblInfo->AuthInfoElement.Octet[1] + 2; + if ((len+sizeof(GTK_KDE_TYPE)+mcastcipher) > sizeof(key_data)) { + DEBUG_ERR("invalid IE length!\n"); + return; + } + memcpy(key_data_pos, pGblInfo->AuthInfoElement.Octet, len); + key_data_pos += len; + } else { + //find WPA2_ELEMENT_ID 0x30 + int len = (unsigned char)pGblInfo->AuthInfoElement.Octet[1] + 2; + //printf("%s: global->auth->RSNVariable.AuthInfoElement.Octet[%d] = %02X\n", (char *)__FUNCTION__, len, global->auth->RSNVariable.AuthInfoElement.Octet[len]); + if (pGblInfo->AuthInfoElement.Octet[len] == WPA2_ELEMENT_ID) { + int len2 = (unsigned char)pGblInfo->AuthInfoElement.Octet[len+1] + 2; + if ((len2+sizeof(GTK_KDE_TYPE)+mcastcipher) > sizeof(key_data)) { + DEBUG_ERR("invalid IE length!\n"); + return; + } + memcpy(key_data_pos, pGblInfo->AuthInfoElement.Octet+len, len2); + key_data_pos += len2; + } else { + DEBUG_ERR("%d ERROR!\n", __LINE__); + } + } + + memcpy(key_data_pos, GTK_KDE_TYPE, sizeof(GTK_KDE_TYPE)); + key_data_pos[1] = 6 + mcastcipher; + key_data_pos += sizeof(GTK_KDE_TYPE); + + + // FIX GROUPKEY ALL ZERO +// david+2006-04-04, fix the issue of re-generating group key +// pGblInfo->GInitAKeys = TRUE; + UpdateGK(priv); + memcpy(key_data_pos, pGblInfo->GTK[pGblInfo->GN], mcastcipher); + + key_data_pos += mcastcipher; + + //================================================= + // IGTK KDE +#ifdef CONFIG_IEEE80211W + PMFDEBUG("mgmt_frame_prot=[%d]\n", pstat->wpa_sta_info->mgmt_frame_prot); + if (pstat->wpa_sta_info->mgmt_frame_prot) { + //PMFDEBUG("SendEAPOL,PATH5\n"); + memcpy(key_data_pos, IGTK_KDE_TYPE, sizeof(IGTK_KDE_TYPE)); + key_data_pos += sizeof(IGTK_KDE_TYPE); + // Key ID + *(key_data_pos) = (unsigned char)priv->wpa_global_info->GN_igtk; + *(key_data_pos + 1) = 0; + key_data_pos += 2; + // IPN + *(key_data_pos++) = priv->wpa_global_info->IGTK_PN._byte_.TSC0; + *(key_data_pos++) = priv->wpa_global_info->IGTK_PN._byte_.TSC1; + *(key_data_pos++) = priv->wpa_global_info->IGTK_PN._byte_.TSC2; + *(key_data_pos++) = priv->wpa_global_info->IGTK_PN._byte_.TSC3; + *(key_data_pos++) = priv->wpa_global_info->IGTK_PN._byte_.TSC4; + *(key_data_pos++) = priv->wpa_global_info->IGTK_PN._byte_.TSC5; + + memcpy(key_data_pos, priv->wpa_global_info->IGTK[priv->wpa_global_info->GN_igtk - 4], 16); + + PMFDEBUG("IGTK="); + for (i = 0; i < 16; i++) + PMFDEBUG("%x", priv->wpa_global_info->IGTK[priv->wpa_global_info->GN_igtk - 4][i]); + PMFDEBUG("\n"); + key_data_pos += 16; + } +#endif + i = (key_data_pos - key_data) % 8; + if ( i != 0 ) { + *key_data_pos = 0xdd; + key_data_pos++; + for (i=i+1; i<8; i++) { + *key_data_pos = 0x0; + key_data_pos++; + } + + } + EncGTK(priv, pstat, + pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC, + key_data, + (key_data_pos - key_data), + KeyData.Octet, &tmpKeyData_Length); + KeyData.Length = (int)tmpKeyData_Length; + Message_setKeyData(EapolKeyMsgSend, KeyData); + Message_setKeyDataLength(EapolKeyMsgSend, KeyData.Length); + + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + KeyData.Length; + RSC.Octet[0] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC0; + RSC.Octet[1] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC1; + RSC.Octet[2] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC2; + RSC.Octet[3] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC3; + RSC.Octet[4] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC4; + RSC.Octet[5] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC5; + RSC.Octet[6] = 0; + RSC.Octet[7] = 0; + Message_setKeyRSC(EapolKeyMsgSend, RSC); + } else +#endif // RTL_WPA2 + { + // WPA + memset(RSC.Octet, 0, RSC.Length); + Message_setKeyRSC(EapolKeyMsgSend, RSC); + memset(KeyID.Octet, 0, KeyID.Length); + Message_setKeyID(EapolKeyMsgSend, KeyID); + //lib1x_hexdump2(MESS_DBG_KEY_MANAGE, "lib1x_akmsm_ProcessEAPOL_proc", global->auth->RSNVariable.AuthInfoElement.Octet, global->auth->RSNVariable.AuthInfoElement.Length,"Append Authenticator Information Element"); + + { + //WPA 0xDD + //printf("%s: global->auth->RSNVariable.AuthInfoElement.Octet[0] = %02X\n", (char *)__FUNCTION__, global->auth->RSNVariable.AuthInfoElement.Octet[0]); + + int len = (unsigned char)pGblInfo->AuthInfoElement.Octet[1] + 2; + len = (lenAuthInfoElement.Octet[0] == RSN_ELEMENT_ID) { + memcpy(KeyData.Octet, pGblInfo->AuthInfoElement.Octet, len); + KeyData.Length = len; + } else { + // impossible case?? + int len2 = (unsigned char)pGblInfo->AuthInfoElement.Octet[len+1] + 2; + len2 = (len2AuthInfoElement.Octet+len, len2); + KeyData.Length = len2; + } + } + Message_setKeyDataLength(EapolKeyMsgSend, KeyData.Length); + Message_setKeyData(EapolKeyMsgSend, KeyData); + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + KeyData.Length; + } + + INCLargeInteger(&pStaInfo->CurrentReplayCounter); + +#if 0 + memset(RSC.Octet, 0, RSC.Length); + Message_setKeyRSC(EapolKeyMsgSend, RSC); + memset(KeyID.Octet, 0, KeyID.Length); + Message_setKeyID(EapolKeyMsgSend, KeyID); + //lib1x_hexdump2(MESS_DBG_KEY_MANAGE, "lib1x_akmsm_ProcessEAPOL_proc", global->auth->RSNVariable.AuthInfoElement.Octet, global->auth->RSNVariable.AuthInfoElement.Length,"Append Authenticator Information Element"); + Message_setKeyDataLength(EapolKeyMsgSend, pGblInfo->AuthInfoElement.Length); + Message_setKeyData(EapolKeyMsgSend, pGblInfo->AuthInfoElement); + //Message_setKeyDataLength(global->EapolKeyMsgSend, global->akm_sm->AuthInfoElement.Length); + //Message_setKeyData(global->EapolKeyMsgSend, global->akm_sm->AuthInfoElement); + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + pGblInfo->AuthInfoElement.Length; +#endif /* RTL_WPA2 */ + + EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length; + IfCalcMIC = TRUE; + break; + + case PSK_STATE_PTKINITDONE: + //send 1st message of 2-way handshake + DEBUG_INFO("2-1\n"); + PSKDEBUG("2-1\n"); + memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN); + +#ifdef RTL_WPA2 + if (pStaInfo->RSNEnabled & PSK_WPA2) + Message_setDescType(EapolKeyMsgSend, desc_type_WPA2); + else +#endif + Message_setDescType(EapolKeyMsgSend, desc_type_RSN); + + Message_setKeyDescVer(EapolKeyMsgSend, KeyDescriptorVer); + Message_setKeyType(EapolKeyMsgSend, type_Group); + Message_setKeyIndex(EapolKeyMsgSend, 1); + Message_setInstall(EapolKeyMsgSend, 1); + Message_setKeyAck(EapolKeyMsgSend, 1); + Message_setKeyMIC(EapolKeyMsgSend, 1); + Message_setSecure(EapolKeyMsgSend, 1); + Message_setError(EapolKeyMsgSend, 0); + Message_setRequest(EapolKeyMsgSend, 0); + Message_setReserved(EapolKeyMsgSend, 0); + + EapolKeyMsgSend.Octet[1] = 0x03; + if (KeyDescriptorVer == key_desc_ver1 ) + EapolKeyMsgSend.Octet[2] = 0x91; + else if (KeyDescriptorVer == key_desc_ver2) + EapolKeyMsgSend.Octet[2] = 0x92; + else + EapolKeyMsgSend.Octet[2] = 0x93; + + Message_setKeyLength(EapolKeyMsgSend, (pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16); + Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->CurrentReplayCounter.field.HighPart, pStaInfo->CurrentReplayCounter.field.LowPart); + INCLargeInteger(&pStaInfo->CurrentReplayCounter); + // kenny: n+2 + INCLargeInteger(&pStaInfo->CurrentReplayCounter); + SetNonce(pGblInfo->GNonce, pGblInfo->Counter); + Message_setKeyNonce(EapolKeyMsgSend, pGblInfo->GNonce); + memset(IV.Octet, 0, IV.Length); + Message_setKeyIV(EapolKeyMsgSend, IV); + + RSC.Octet[0] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC0; + RSC.Octet[1] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC1; + RSC.Octet[2] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC2; + RSC.Octet[3] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC3; + RSC.Octet[4] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC4; + RSC.Octet[5] = priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC5; + RSC.Octet[6] = 0; + RSC.Octet[7] = 0; + Message_setKeyRSC(EapolKeyMsgSend, RSC); + + memset(KeyID.Octet, 0, KeyID.Length); + Message_setKeyID(EapolKeyMsgSend, KeyID); + +#ifdef RTL_WPA2 + if (pStaInfo->RSNEnabled & PSK_WPA2) { + char key_data[128]; + char *key_data_pos = key_data; + static char GTK_KDE_TYPE[] = { 0xDD, 0x16, 0x00, 0x0F, 0xAC, 0x01, 0x01, 0x00 }; + memcpy(key_data_pos, GTK_KDE_TYPE, sizeof(GTK_KDE_TYPE)); + +//fix the bug of using default KDE length ----------- + key_data_pos[1] = (unsigned char)(6+((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16)); +//------------------------------ david+2006-04-04 + + key_data_pos += sizeof(GTK_KDE_TYPE); + + EapolKeyMsgSend.Octet[1] = 0x13; +// fill key-data length after encrypt -------------------- +#if 0 + if (KeyDescriptorVer == key_desc_ver1) { +// david+2006-01-06, fix the bug of using 0 as group key id +// EapolKeyMsgSend.Octet[2] = 0x81; + Message_setKeyDescVer(EapolKeyMsgSend, key_desc_ver1); + Message_setKeyDataLength(EapolKeyMsgSend, + (sizeof(GTK_KDE_TYPE) + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16))); + } else if (KeyDescriptorVer == key_desc_ver2) { +// david+2006-01-06, fix the bug of using 0 as group key id +// EapolKeyMsgSend.Octet[2] = 0x82; + Message_setKeyDescVer(EapolKeyMsgSend, key_desc_ver2); + Message_setKeyDataLength(EapolKeyMsgSend, + (sizeof(GTK_KDE_TYPE) + (8 + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16)))); + } +#endif +//------------------------------------- david+2006-04-04 + + memcpy(key_data_pos, pGblInfo->GTK[pGblInfo->GN], (pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16); + EncGTK(priv, pstat, pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC, + (unsigned char *)key_data, + sizeof(GTK_KDE_TYPE) + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16), + KeyData.Octet, &tmpKeyData_Length); + } else +#endif // RTL_WPA2 + { +// fill key-data length after encrypt --------------------- +#if 0 + if (KeyDescriptorVer == key_desc_ver1) + Message_setKeyDataLength(EapolKeyMsgSend, + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16)); + else + Message_setKeyDataLength(EapolKeyMsgSend, + (8 + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16) )); +#endif +//------------------------------------- david+2006-04-04 + EncGTK(priv, pstat, pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC, + pGblInfo->GTK[pGblInfo->GN], + (pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16, + KeyData.Octet, &tmpKeyData_Length); + } + + KeyData.Length = (int)tmpKeyData_Length; + Message_setKeyData(EapolKeyMsgSend, KeyData); + +//set keyData length after encrypt ------------------ + Message_setKeyDataLength(EapolKeyMsgSend, KeyData.Length); +//------------------------------- david+2006-04-04 + +/* Kenny + global->EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + + ((global->RSNVariable.MulticastCipher == DOT11_ENC_TKIP) ? 32:16); +*/ + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + KeyData.Length; + EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length; + IfCalcMIC = TRUE; + break; + default: + DEBUG_ERR("Invalid wpa state [%x]\n", pStaInfo->state); + return; + }//switch + + pStaInfo->EAPOLMsgSend.Length = EAPOLMsgSend.Length; + pStaInfo->EapolKeyMsgSend.Length = EapolKeyMsgSend.Length; + +send_packet: + eth_hdr = (struct wlan_ethhdr_t *)pStaInfo->EAPOLMsgSend.Octet; + memcpy(eth_hdr->daddr, pstat->hwaddr, 6); + memcpy(eth_hdr->saddr, GET_MY_HWADDR, 6); + eth_hdr->type = htons(LIB1X_ETHER_EAPOL_TYPE); + + eapol = (struct lib1x_eapol *)(EAPOLMsgSend.Octet + ETHER_HDRLEN); + eapol->protocol_version = LIB1X_EAPOL_VER; + eapol->packet_type = LIB1X_EAPOL_KEY; + eapol->packet_body_length = htons(EapolKeyMsgSend.Length); + + if (IfCalcMIC) + CalcMIC(EAPOLMsgSend, KeyDescriptorVer, pStaInfo->PTK, PTK_LEN_EAPOLMIC); + + pskb = rtl_dev_alloc_skb(priv, MAX_EAPOLMSG_LEN, _SKB_TX_, 1); + if (pskb == NULL) { + DEBUG_ERR("Allocate EAP skb failed!\n"); + return; + } + memcpy(pskb->data, (char *)eth_hdr, EAPOLMsgSend.Length); + skb_put(pskb, EAPOLMsgSend.Length); + +#ifdef DEBUG_PSK + { + unsigned char *msg; + if (pStaInfo->state == PSK_STATE_PTKSTART) + msg = "4-1"; + else if (pStaInfo->state == PSK_STATE_PTKINITNEGOTIATING) + msg = "4-3"; + else + msg = "2-1"; + + printk("PSK: Send a EAPOL %s, len=%x\n", msg, pskb->len); + debug_out(NULL, pskb->data, pskb->len); + } +#endif +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + +// pskb->cb[0] = 7; // use highest priority to xmit + if (rtl8192cd_start_xmit(pskb, priv->dev)) + rtl_kfree_skb(priv, pskb, _SKB_TX_); + + mod_timer(&pstat->wpa_sta_info->resendTimer, jiffies + RESEND_TIME); +} + + +#ifdef __ECOS +int ecos_send_wlan(struct net_device *dev, unsigned char *data, int size) +{ + struct rtl8192cd_priv *priv; + struct sk_buff *pskb; + + priv = dev->priv; + pskb = rtl_dev_alloc_skb(priv, size, _SKB_TX_, 1); + if (pskb == NULL) { + DEBUG_ERR("wps: allocate EAP skb failed!\n"); + return -1; + } + memcpy(pskb->data, data, size); + skb_put(pskb, size); + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + + //pskb->cb[0] = 7; // use highest priority to xmit + if (rtl8192cd_start_xmit(pskb, priv->dev)){ + DEBUG_ERR("tx from wps\n"); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + return 0; +} +#endif + + +#ifdef CLIENT_MODE +void ClientSendEAPOL(struct rtl8192cd_priv *priv, struct stat_info *pstat, int resend) +{ + OCTET_STRING IV, RSC, KeyID, MIC, KeyData, EAPOLMsgSend, EapolKeyMsgSend, Nonce; + unsigned char IV_buff[KEY_IV_LEN], RSC_buff[KEY_RSC_LEN]; + unsigned char ID_buff[KEY_ID_LEN], MIC_buff[KEY_MIC_LEN], KEY_buff[INFO_ELEMENT_SIZE], Nonce_buff[KEY_NONCE_LEN]; + struct wlan_ethhdr_t *eth_hdr; + struct lib1x_eapol *eapol; + struct sk_buff *pskb; + lib1x_eapol_key *eapol_key; + WPA_STA_INFO *pStaInfo; + WPA_GLOBAL_INFO *pGblInfo; + unsigned char KeyDescriptorVer = key_desc_ver1; + int send_report = 0; + + DEBUG_TRACE; + + if (priv == NULL || pstat == NULL) + return; + + pStaInfo = pstat->wpa_sta_info; + pGblInfo = priv->wpa_global_info; + + EAPOLMsgSend.Octet = pStaInfo->EAPOLMsgSend.Octet; + EapolKeyMsgSend.Octet = EAPOLMsgSend.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN; + pStaInfo->EapolKeyMsgSend.Octet = EapolKeyMsgSend.Octet; + eapol_key = (lib1x_eapol_key *)EapolKeyMsgSend.Octet; + + if (resend) { + EAPOLMsgSend.Length = pStaInfo->EAPOLMsgSend.Length; + EapolKeyMsgSend.Length = pStaInfo->EapolKeyMsgSend.Length; + if ( (pStaInfo->EAPOLMsgSend.Length==0) || (pStaInfo->EapolKeyMsgSend.Length==0) ) { + DEBUG_ERR("(%s):The length of EAPOLMsg or EapolKeyMsg is error! EAPOLMsg:%d, EapolKeyMsg:%d\n", __FUNCTION__, pStaInfo->EAPOLMsgSend.Length, pStaInfo->EapolKeyMsgSend.Length); + return; + } + //---goto send_packet + } else { + IV.Octet = IV_buff; + IV.Length = KEY_IV_LEN; + RSC.Octet = RSC_buff; + RSC.Length = KEY_RSC_LEN; + KeyID.Octet = ID_buff; + KeyID.Length = KEY_ID_LEN; + MIC.Octet = MIC_buff; + MIC.Length = KEY_MIC_LEN; + KeyData.Octet = KEY_buff; + KeyData.Length = 0; + + Nonce.Octet = Nonce_buff; + Nonce.Length = KEY_NONCE_LEN; + + if (!pStaInfo->clientHndshkDone) { + if (pStaInfo->clientHndshkProcessing < fourWaystep3) { + //send 2nd message of 4-way handshake + DEBUG_INFO("client mode 4-2\n"); + PSKDEBUG("client mode 4-2\n"); + + pStaInfo->clientHndshkProcessing = fourWaystep2; + + memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN); + + Message_setDescType(EapolKeyMsgSend, Message_DescType(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyDescVer(EapolKeyMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyType(EapolKeyMsgSend, Message_KeyType(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyIndex(EapolKeyMsgSend, 0); + Message_setInstall(EapolKeyMsgSend, Message_KeyIndex(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyAck(EapolKeyMsgSend, 0); + Message_setKeyMIC(EapolKeyMsgSend, 1); + Message_setSecure(EapolKeyMsgSend, Message_Secure(pStaInfo->EapolKeyMsgRecvd)); + Message_setError(EapolKeyMsgSend, Message_Error(pStaInfo->EapolKeyMsgRecvd)); + Message_setRequest(EapolKeyMsgSend, Message_Request(pStaInfo->EapolKeyMsgRecvd)); + Message_setReserved(EapolKeyMsgSend, 0); + + Message_setKeyLength(EapolKeyMsgSend, Message_KeyLength(pStaInfo->EapolKeyMsgRecvd)); + Message_CopyReplayCounter(EapolKeyMsgSend, pStaInfo->EapolKeyMsgRecvd); + + Message_setKeyNonce(EapolKeyMsgSend, pStaInfo->SNonce); + memset(IV.Octet, 0, IV.Length); + Message_setKeyIV(EapolKeyMsgSend, IV); + memset(RSC.Octet, 0, RSC.Length); + Message_setKeyRSC(EapolKeyMsgSend, RSC); + memset(KeyID.Octet, 0, KeyID.Length); + Message_setKeyID(EapolKeyMsgSend, KeyID); + + Message_setKeyDataLength(EapolKeyMsgSend, pGblInfo->AuthInfoElement.Length); + Message_setKeyData(EapolKeyMsgSend, pGblInfo->AuthInfoElement); + + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN + pGblInfo->AuthInfoElement.Length; + EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length; + + } else { + //Construct Message4 + DEBUG_INFO("client mode 4-4\n"); + PSKDEBUG("client mode 4-4\n"); + + pStaInfo->clientHndshkDone++; + pStaInfo->clientHndshkProcessing=fourWaystep4; + priv->dot114WayStatus = 0; + + memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN); + + Message_setDescType(EapolKeyMsgSend, Message_DescType(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyDescVer(EapolKeyMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyType(EapolKeyMsgSend, Message_KeyType(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyIndex(EapolKeyMsgSend, 0); + Message_setInstall(EapolKeyMsgSend, 0); + Message_setKeyAck(EapolKeyMsgSend, 0); + Message_setKeyMIC(EapolKeyMsgSend, 1); + Message_setSecure(EapolKeyMsgSend, Message_Secure(pStaInfo->EapolKeyMsgRecvd)); + Message_setError(EapolKeyMsgSend, 0); + Message_setRequest(EapolKeyMsgSend, 0); + Message_setReserved(EapolKeyMsgSend, 0); + Message_setKeyLength(EapolKeyMsgSend, Message_KeyLength(pStaInfo->EapolKeyMsgRecvd)); + Message_CopyReplayCounter(EapolKeyMsgSend, pStaInfo->EapolKeyMsgRecvd); + memset(IV.Octet, 0, IV.Length); + Message_setKeyIV(EapolKeyMsgSend, IV); + memset(RSC.Octet, 0, RSC.Length); + Message_setKeyRSC(EapolKeyMsgSend, RSC); + memset(KeyID.Octet, 0, KeyID.Length); + Message_setKeyID(EapolKeyMsgSend, KeyID); + Message_setKeyDataLength(EapolKeyMsgSend, 0); + + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN; + EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length; + + LOG_MSG( "Open and authenticated\n"); + + pStaInfo->clientMICReportReplayCounter.field.HighPart = 0; + pStaInfo->clientMICReportReplayCounter.field.LowPart = 0; +// printk("client mode 4-Way Message 4-4 done\n"); + } + } else { + if (pStaInfo->clientGkeyUpdate) { + //send 2nd message of 2-way handshake + DEBUG_INFO("client mode 2-2\n"); + PSKDEBUG("client mode 2-2\n"); + memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN); + + Message_setDescType(EapolKeyMsgSend, Message_DescType(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyDescVer(EapolKeyMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyType(EapolKeyMsgSend, Message_KeyType(pStaInfo->EapolKeyMsgRecvd)); + Message_setKeyIndex(EapolKeyMsgSend, pGblInfo->GN); + Message_setInstall(EapolKeyMsgSend, 0); + Message_setKeyAck(EapolKeyMsgSend, 0); + Message_setKeyMIC(EapolKeyMsgSend, 1); + Message_setSecure(EapolKeyMsgSend, 1); + Message_setError(EapolKeyMsgSend, 0); + Message_setRequest(EapolKeyMsgSend, 0); + Message_setReserved(EapolKeyMsgSend, 0); + + Message_setKeyLength(EapolKeyMsgSend, Message_KeyLength(pStaInfo->EapolKeyMsgRecvd)); + Message_CopyReplayCounter(EapolKeyMsgSend, pStaInfo->EapolKeyMsgRecvd); + memset(Nonce.Octet, 0, KEY_NONCE_LEN); + Message_setKeyNonce(EapolKeyMsgSend, Nonce); + memset(IV.Octet, 0, IV.Length); + Message_setKeyIV(EapolKeyMsgSend, IV); + memset(RSC.Octet, 0, RSC.Length); + Message_setKeyRSC(EapolKeyMsgSend, RSC); + memset(KeyID.Octet, 0, KeyID.Length); + Message_setKeyID(EapolKeyMsgSend, KeyID); + Message_setKeyDataLength(EapolKeyMsgSend, 0); + + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN; + EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length; + + // printk("client mode Group Message 2-2 done\n"); + pStaInfo->clientGkeyUpdate = 0; + } else { + DEBUG_INFO("Send MIC Failure Report\n"); + PSKDEBUG("Send MIC Failure Report\n"); + memset(EapolKeyMsgSend.Octet, 0, MAX_EAPOLKEYMSG_LEN); +#ifdef RTL_WPA2 + if (pStaInfo->RSNEnabled & PSK_WPA2) + Message_setDescType(EapolKeyMsgSend, desc_type_WPA2); + else +#endif + Message_setDescType(EapolKeyMsgSend, desc_type_RSN); + +#ifdef CONFIG_IEEE80211W_CLI + if (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK_SHA256) + KeyDescriptorVer = key_desc_ver3; + else +#endif + if ((pGblInfo->MulticastCipher == _CCMP_PRIVACY_) || (pStaInfo->UnicastCipher == _CCMP_PRIVACY_)) + KeyDescriptorVer = key_desc_ver2; + Message_setKeyDescVer(EapolKeyMsgSend, KeyDescriptorVer); + Message_setKeyType(EapolKeyMsgSend, 0); + Message_setKeyIndex(EapolKeyMsgSend, 0); + Message_setInstall(EapolKeyMsgSend, 0); + Message_setKeyAck(EapolKeyMsgSend, 0); + Message_setKeyMIC(EapolKeyMsgSend, 1); + Message_setSecure(EapolKeyMsgSend, 1); + Message_setError(EapolKeyMsgSend, 1); + Message_setRequest(EapolKeyMsgSend, 1); + Message_setReserved(EapolKeyMsgSend, 0); + Message_setKeyLength(EapolKeyMsgSend, 0); + + Message_setReplayCounter(EapolKeyMsgSend, pStaInfo->clientMICReportReplayCounter.field.HighPart, pStaInfo->clientMICReportReplayCounter.field.LowPart); + INCLargeInteger(&pStaInfo->clientMICReportReplayCounter); + + memset(Nonce.Octet, 0, KEY_NONCE_LEN); + Message_setKeyNonce(EapolKeyMsgSend, Nonce); + memset(IV.Octet, 0, IV.Length); + Message_setKeyIV(EapolKeyMsgSend, IV); + memset(RSC.Octet, 0, RSC.Length); + Message_setKeyRSC(EapolKeyMsgSend, RSC); + memset(KeyID.Octet, 0, KeyID.Length); + Message_setKeyID(EapolKeyMsgSend, KeyID); + Message_setKeyDataLength(EapolKeyMsgSend, 0); + + EapolKeyMsgSend.Length = EAPOLMSG_HDRLEN; + EAPOLMsgSend.Length = ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EapolKeyMsgSend.Length; + send_report = 1; + } + } + pStaInfo->EAPOLMsgSend.Length = EAPOLMsgSend.Length; + pStaInfo->EapolKeyMsgSend.Length = EapolKeyMsgSend.Length; + } + + //for record EAPOLMSG length + pStaInfo->EAPOLMsgSend.Length = EAPOLMsgSend.Length; + pStaInfo->EapolKeyMsgSend.Length = EapolKeyMsgSend.Length; + //send_packet-------------------------------------------------------------- + + eth_hdr = (struct wlan_ethhdr_t *)EAPOLMsgSend.Octet; + memcpy(eth_hdr->daddr, pstat->hwaddr, 6); + memcpy(eth_hdr->saddr, GET_MY_HWADDR, 6); + eth_hdr->type = htons(LIB1X_ETHER_EAPOL_TYPE); + + eapol = (struct lib1x_eapol *)(EAPOLMsgSend.Octet + ETHER_HDRLEN); + eapol->protocol_version = LIB1X_EAPOL_VER; + eapol->packet_type = LIB1X_EAPOL_KEY; + eapol->packet_body_length = htons(EapolKeyMsgSend.Length); + + if (!resend) { + if (send_report) + CalcMIC(EAPOLMsgSend, KeyDescriptorVer, pStaInfo->PTK, PTK_LEN_EAPOLMIC); + else + CalcMIC(EAPOLMsgSend, Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd), pStaInfo->PTK, PTK_LEN_EAPOLMIC); + } + + pskb = rtl_dev_alloc_skb(priv, MAX_EAPOLMSG_LEN, _SKB_TX_, 1); + + if (pskb == NULL) { + DEBUG_ERR("Allocate EAP skb failed!\n"); + printk("Allocate EAP skb failed!\n"); + return; + } + + memcpy(pskb->data, (char *)eth_hdr, EAPOLMsgSend.Length); + skb_put(pskb, EAPOLMsgSend.Length); + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + + if (rtl8192cd_start_xmit(pskb, priv->dev)) + rtl_kfree_skb(priv, pskb, _SKB_TX_); + + if (!pStaInfo->clientHndshkDone) // only 4-2 need to check the time + mod_timer(&pStaInfo->resendTimer, jiffies + RESEND_TIME); + + //--------------------------------------------------------------send_packet +} +#endif // CLIENT_MODE + +static void AuthenticationRequest(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + static unsigned int RC_toggle = 0; + + DEBUG_TRACE; + + // For some STA that can only process if Replay Counter is not 0 + if ((++RC_toggle)%2) + INCLargeInteger(&pstat->wpa_sta_info->CurrentReplayCounter); + + INCOctet32_INTEGER(&priv->wpa_global_info->Counter); + SetNonce(pstat->wpa_sta_info->ANonce, priv->wpa_global_info->Counter); + + memcpy(pstat->wpa_sta_info->PMK, priv->wpa_global_info->PSK, PMK_LEN); + +//#ifdef RTL_WPA2 +#if 0 + CalcPMKID( akm_sm->PMKID, + akm_sm->PMK, // PMK + global->theAuthenticator->global->TxRx->oursupp_addr, // AA + global->theAuthenticator->supp_addr); // SPA +#endif + pstat->wpa_sta_info->state = PSK_STATE_PTKSTART; + pstat->wpa_sta_info->resendCnt = 0; + + //send 1st message + SendEAPOL(priv, pstat, 0); +} + +//------------------------------------------------------------- +// Start 2-way handshake after receiving 4th message +//------------------------------------------------------------- +static void UpdateGK(struct rtl8192cd_priv *priv) +{ + WPA_GLOBAL_INFO *pGblInfo=priv->wpa_global_info; + struct stat_info *pstat; + int i; +#ifdef SMP_SYNC + unsigned long flags=0; +#endif + + SMP_LOCK_PSK_GKREKEY(flags); + //------------------------------------------------------------ + // Execute Global Group key state machine + //------------------------------------------------------------ + if (pGblInfo->GTKAuthenticator && (pGblInfo->GTKRekey || pGblInfo->GInitAKeys)) { + pGblInfo->GTKRekey = FALSE; + pGblInfo->GInitAKeys = FALSE; // david+2006-04-04, fix the issue of re-generating group key + + INCOctet32_INTEGER(&pGblInfo->Counter); + + // kenny:??? GNonce should be a random number ??? + SetNonce(pGblInfo->GNonce , pGblInfo->Counter); + CalcGTK(GET_MY_HWADDR, pGblInfo->GNonce.Octet, + pGblInfo->GMK, GMK_LEN, pGblInfo->GTK[pGblInfo->GN], GTK_LEN, GMK_EXPANSION_CONST); + +#ifdef DEBUG_PSK + debug_out("PSK: Generated GTK=", pGblInfo->GTK[pGblInfo->GN], GTK_LEN); +#endif + + pGblInfo->GUpdateStationKeys = TRUE; + pGblInfo->GkeyReady = FALSE; + + if (timer_pending(&pGblInfo->GKRekeyTimer)) + del_timer_sync(&pGblInfo->GKRekeyTimer); + + //---- In the case of updating GK to all STAs, only the STA that has finished + //---- 4-way handshake is needed to be sent with 2-way handshake + //gkm_sm->GKeyDoneStations = auth->NumOfSupplicant; + pGblInfo->GKeyDoneStations = 0; + + for (i=0; ipshare->aidarray[i] && (priv->pshare->aidarray[i]->used == TRUE)) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (priv != priv->pshare->aidarray[i]->priv) + continue; +#endif + + if ((priv->pshare->aidarray[i]->station.state & WIFI_ASOC_STATE) && + (priv->pshare->aidarray[i]->station.wpa_sta_info->state == PSK_STATE_PTKINITDONE)) + pGblInfo->GKeyDoneStations++; + } + } + } + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != NO_MGMT_FRAME_PROTECTION) { + int ii; + PMFDEBUG("Calculate IGTK\n"); + + CalcGTK(GET_MY_HWADDR, pGblInfo->GNonce.Octet, + pGblInfo->GMK, GMK_LEN, pGblInfo->IGTK[pGblInfo->GN_igtk - 4], IGTK_LEN, (u_char*)IGMK_EXPANSION_CONST); + PMFDEBUG("IGTK[%d]\n", pGblInfo->GN_igtk - 4); + for (ii = 0; ii < IGTK_LEN; ii++) { + PMFDEBUG("%02x ", pGblInfo->IGTK[pGblInfo->GN_igtk - 4][ii]); + } + PMFDEBUG("\n"); + } +#endif // CONFIG_IEEE80211W + + //------------------------------------------------------------ + // Execute Group key state machine of each STA + //------------------------------------------------------------ + for (i=0; ipshare->aidarray[i] == NULL) + continue; + pstat = &priv->pshare->aidarray[i]->station; + if ((priv->pshare->aidarray[i]->used != TRUE) ||!(pstat->state & WIFI_ASOC_STATE)) + continue; + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (priv != priv->pshare->aidarray[i]->priv) + continue; +#endif + + //---- Group key handshake to only one supplicant ---- + if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITDONE && + (pGblInfo->GkeyReady && pstat->wpa_sta_info->PInitAKeys)) { + pstat->wpa_sta_info->PInitAKeys = FALSE; + pstat->wpa_sta_info->gstate = PSK_GSTATE_REKEYNEGOTIATING; // set proper gstat, david+2006-04-06 + pstat->wpa_sta_info->resendCnt = 0; + SendEAPOL(priv, pstat, 0); + } + //---- Updata group key to all supplicant---- + else if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITDONE && //Done 4-way handshake + (pGblInfo->GUpdateStationKeys || //When new key is generated + pstat->wpa_sta_info->gstate == PSK_GSTATE_REKEYNEGOTIATING)) { //1st message is not yet sent + pstat->wpa_sta_info->PInitAKeys = FALSE; + pstat->wpa_sta_info->gstate = PSK_GSTATE_REKEYNEGOTIATING; // set proper gstat, david+2006-04-06 + pstat->wpa_sta_info->resendCnt = 0; + SendEAPOL(priv, pstat, 0); + } + } + pGblInfo->GUpdateStationKeys = FALSE; + + SMP_UNLOCK_PSK_GKREKEY(flags); +}; + +static void EAPOLKeyRecvd(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + WPA_GLOBAL_INFO *pGblInfo = priv->wpa_global_info; + WPA_STA_INFO *pStaInfo = pstat->wpa_sta_info; + LARGE_INTEGER recievedRC; + struct lib1x_eapol *eapol; + OCTET_STRING tmpSNonce; +#ifdef SMP_SYNC + unsigned long flags=0; +#endif + + DEBUG_TRACE; + + eapol = ( struct lib1x_eapol * ) ( pstat->wpa_sta_info->EAPOLMsgRecvd.Octet + ETHER_HDRLEN ); + if (eapol->packet_type != LIB1X_EAPOL_KEY) { +#ifdef DEBUG_PSK + printk("Not Eapol-key pkt (type %d), drop\n", eapol->packet_type); +#endif + return; + } + + pStaInfo->EapolKeyMsgRecvd.Octet = pStaInfo->EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN; + +#ifdef DEBUG_PSK + printk("PSK: Rx a EAPOL %s, len=%x\n", STATE2RXMSG(pstat), pStaInfo->EAPOLMsgRecvd.Length); + debug_out(NULL, pstat->wpa_sta_info->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Length); +#endif + + //----IEEE 802.11-03/156r2. MIC report : (1)MIC bit (2)error bit (3) request bit + //----Check if it is MIC failure report. If it is, indicate to driver + if (Message_KeyMIC(pStaInfo->EapolKeyMsgRecvd) && Message_Error(pStaInfo->EapolKeyMsgRecvd) + && Message_Request(pStaInfo->EapolKeyMsgRecvd)) { +#ifdef DEBUG_PSK + printk("PSK: Rx MIC errir report from client\n"); +#endif + ToDrv_IndicateMICFail(priv, pstat->hwaddr); + return; + } + + if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Pairwise) { + switch(pStaInfo->state) { + case PSK_STATE_PTKSTART: + //---- Receive 2nd message and send third + DEBUG_INFO("4-2\n"); + PSKDEBUG("4-2\n"); + + //check replay counter + Message_ReplayCounter_OC2LI(pStaInfo->EapolKeyMsgRecvd, &recievedRC); + INCLargeInteger(&recievedRC); + if ( !(pStaInfo->CurrentReplayCounter.field.HighPart == recievedRC.field.HighPart + && pStaInfo->CurrentReplayCounter.field.LowPart == recievedRC.field.LowPart)) { + DEBUG_ERR("4-2: ERROR_NONEEQUL_REPLAYCOUNTER\n"); + break; + } + +check_msg2: + //pStaInfo->SNonce = Message_KeyNonce(pStaInfo->EapolKeyMsgRecvd); + tmpSNonce = Message_KeyNonce(pStaInfo->EapolKeyMsgRecvd); + memcpy(pStaInfo->SNonce.Octet, tmpSNonce.Octet, KEY_NONCE_LEN); + pStaInfo->SNonce.Length = tmpSNonce.Length; + CalcPTK(pStaInfo->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Octet + 6, + pStaInfo->ANonce.Octet, pStaInfo->SNonce.Octet, + pStaInfo->PMK, PMK_LEN, + pStaInfo->PTK, (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK_SHA256) ? 48 : PTK_LEN_TKIP +#ifdef CONFIG_IEEE80211W + , (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK_SHA256) +#endif + ); + +#ifdef DEBUG_PSK + debug_out("PSK: Generated PTK=", pStaInfo->PTK, PTK_LEN_TKIP); +#endif + + if (!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) { + if (priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest[0]) { + CalcPTK(pStaInfo->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Octet + 6, + pStaInfo->ANonce.Octet, pStaInfo->SNonce.Octet, + pGblInfo->PSKGuest, PMK_LEN, + pStaInfo->PTK, (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK_SHA256) ? 48 : PTK_LEN_TKIP +#ifdef CONFIG_IEEE80211W + , (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK_SHA256) +#endif + ); + if (CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) { + pStaInfo->isGuest = 1; + goto cont_msg; + } + } + + DEBUG_ERR("4-2: ERROR_MIC_FAIL\n"); +#if 0 + if (global->RSNVariable.PMKCached ) { + printf("\n%s:%d del_pmksa due to 4-2 ERROR_MIC_FAIL\n", (char *)__FUNCTION__, __LINE__); + global->RSNVariable.PMKCached = FALSE; + del_pmksa_by_spa(global->theAuthenticator->supp_addr); + } +#endif + + LOG_MSG("Authentication failled! (4-2: MIC error)\n"); + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Authentication failed;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +#elif defined(CONFIG_RTL8196B_TLD) + LOG_MSG_DEL("[WLAN access rejected: incorrect security] from MAC address: %02x:%02x:%02x:%02x:%02x:%02x,\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +#elif defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->sta_status_cb_func) + priv->sta_status_cb_func("wlan0", pstat->hwaddr, WIFI_STA_STATUS_AUTH_FAIL); +#endif + /* Fix, to prevent prompt "Connection Timeout" when MacBook connect with incorrect PSK + ToDrv_DisconnectSTA(priv, pstat, RSN_MIC_failure); + pStaInfo->state = PSK_STATE_IDLE; + */ + break; + } +cont_msg: + pStaInfo->resendCnt = 0; + /* Fix, to prevent display connection timeout when MacBook connect with incorrect PSK. + Relocate cancel timer here to make 4-1 retried while 4-2 MIC error, then MacBook will prompt "Incorrect Password" */ + // delete resend timer + SMP_LOCK_PSK_RESEND(flags); + if (timer_pending(&pStaInfo->resendTimer)){ + del_timer(&pStaInfo->resendTimer); + } + SMP_UNLOCK_PSK_RESEND(flags); + pStaInfo->state = PSK_STATE_PTKINITNEGOTIATING; + SendEAPOL(priv, pstat, 0); // send msg 3 + break; + + case PSK_STATE_PTKINITNEGOTIATING: + //---- Receive 4th message ---- + DEBUG_INFO("4-4\n"); + PSKDEBUG("4-4\n"); + + // test 2nd or 4th message +// check replay counter to determine if msg 2 or 4 received -------------- +// if ( Message_KeyDataLength(pStaInfo->EapolKeyMsgRecvd) != 0) { + if (Message_EqualReplayCounter(pStaInfo->ReplayCounterStarted, pStaInfo->EapolKeyMsgRecvd)) { +//---------------------------------------------------- david+1-12-2007 + + DEBUG_INFO("4-2 in akmsm_PTKINITNEGOTIATING: resend 4-3\n"); + PSKDEBUG("4-2 in akmsm_PTKINITNEGOTIATING: resend 4-3\n"); + +#if 0 // Don't check replay counter during dup 4-2 +#ifdef RTL_WPA2 + Message_ReplayCounter_OC2LI(global->EapolKeyMsgRecvd, &recievedRC); + INCLargeInteger(&recievedRC); + if ( !(global->akm_sm->CurrentReplayCounter.field.HighPart == recievedRC.field.HighPart + && global->akm_sm->CurrentReplayCounter.field.LowPart == recievedRC.field.LowPart)) +#else + if(!Message_EqualReplayCounter(global->akm_sm->CurrentReplayCounter, global->EapolKeyMsgRecvd)) +#endif + { +#ifdef FOURWAY_DEBUG + printf("4-2: ERROR_NONEEQUL_REPLAYCOUNTER\n"); + printf("global->akm_sm->CurrentReplayCounter.field.LowPart = %d\n", global->akm_sm->CurrentReplayCounter.field.LowPart); + printf("recievedRC.field.LowPart = %d\n", recievedRC.field.LowPart); +#endif + retVal = ERROR_NONEEQUL_REPLAYCOUNTER;k + }else +#endif // Don't check replay counter during dup 4-2 +//#ifndef RTL_WPA2 +#if 0 + // kenny: already increase CurrentReplayCounter after 4-1. Do it at the end of 4-2 + INCLargeInteger(&global->akm_sm->CurrentReplayCounter); +#endif + + goto check_msg2; + } + + if (!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) { // errror + DEBUG_ERR("4-4: RSN_MIC_failure\n"); +#if 0 + if (global->RSNVariable.PMKCached ) { + printf("\n%s:%d del_pmksa due to 4-4 RSN_MIC_failure\n", (char *)__FUNCTION__, __LINE__); + global->RSNVariable.PMKCached = FALSE; + del_pmksa_by_spa(global->theAuthenticator->supp_addr); + } +#endif + LOG_MSG("Authentication failled! (4-4: MIC error)\n"); + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Authentication failed;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +#elif defined(CONFIG_RTL8196B_TLD) + LOG_MSG_DEL("[WLAN access rejected: incorrect security] from MAC address: %02x:%02x:%02x:%02x:%02x:%02x,\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +#elif defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->sta_status_cb_func) + priv->sta_status_cb_func("wlan0", pstat->hwaddr, WIFI_STA_STATUS_AUTH_FAIL); +#endif + /* Refine, retry 4-3 instead dropping connect directly + ToDrv_DisconnectSTA(priv, pstat, RSN_MIC_failure); + pStaInfo->state = PSK_STATE_IDLE; + */ + break; + } + pStaInfo->resendCnt = 0; + /* Refine, relocate cancel timer here to make 4-3 retried while 4-4 MIC error */ + // delete resend timer + SMP_LOCK_PSK_RESEND(flags); + if (timer_pending(&pStaInfo->resendTimer)){ + del_timer(&pStaInfo->resendTimer); + } + SMP_UNLOCK_PSK_RESEND(flags); + LOG_MSG("Open and authenticated\n"); + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Authentication Success;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +#elif defined(CONFIG_RTL8196B_TLD) + if (!list_empty(&priv->wlan_acl_list)) { + LOG_MSG_DEL("[WLAN access allowed] from MAC: %02x:%02x:%02x:%02x:%02x:%02x,\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); + } +#endif + +//#ifdef RTL_WPA2_PREAUTH +#if 0 + // update ANonce for next 4-way handshake + SetNonce(akm_sm->ANonce, global->auth->Counter); +#endif + + //MLME-SETKEYS.request + INCLargeInteger(&pStaInfo->CurrentReplayCounter); + // kenny: n+2 + INCLargeInteger(&pStaInfo->CurrentReplayCounter); + + ToDrv_SetPTK(priv, pstat); + if (pStaInfo->isGuest) + ToDrv_SetPort(priv, pstat, DOT11_PortStatus_Guest); + else + ToDrv_SetPort(priv, pstat, DOT11_PortStatus_Authorized); + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->sta_status_cb_func) + priv->sta_status_cb_func("wlan0", pstat->hwaddr, WIFI_STA_STATUS_PORT_AUTHORIZED); +#endif + +// david+2006-04-04, fix the issue of re-generating group key, and need not +// update group key in WPA2 +// pGblInfo->GInitAKeys = TRUE; +#ifdef RTL_WPA2 + if (!(pStaInfo->RSNEnabled & PSK_WPA2)) +#endif + pStaInfo->PInitAKeys = TRUE; + pStaInfo->state = PSK_STATE_PTKINITDONE; + pStaInfo->gstate = PSK_GSTATE_REKEYNEGOTIATING; + + //lib1x_akmsm_UpdateGK_proc() calls lib1x_akmsm_SendEAPOL_proc for 2-way + //if group key sent is needed, send msg 1 of 2-way handshake +#ifdef RTL_WPA2 + if (pStaInfo->RSNEnabled & PSK_WPA2) { + //------------------------------------------------------ + // Only when the group state machine is in the state of + // (1) The first STA Connected, + // (2) UPDATE GK to all station + // does the GKeyDoneStations needed to be decreased + //------------------------------------------------------ + + if(pGblInfo->GKeyDoneStations > 0) + pGblInfo->GKeyDoneStations--; + + //Avaya akm_sm->TimeoutCtr = 0; + //To Do : set port secure to driver +// global->portSecure = TRUE; + //akm_sm->state = akmsm_PTKINITDONE; + + pStaInfo->gstate = PSK_GSTATE_REKEYESTABLISHED; + + if (pGblInfo->GKeyDoneStations==0 && !pGblInfo->GkeyReady) { + ToDrv_SetGTK(priv); +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != NO_MGMT_FRAME_PROTECTION) + ToDrv_SetIGTK(priv); +#endif + pGblInfo->GkeyReady = TRUE; + pGblInfo->GResetCounter = TRUE; + + // start groupkey rekey timer + if (priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime) + mod_timer(&pGblInfo->GKRekeyTimer, jiffies + RTL_SECONDS_TO_JIFFIES(priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime)); + } +#if 0 + if (global->RSNVariable.PMKCached) { + global->RSNVariable.PMKCached = FALSE; // reset + } +#endif +#ifdef CONFIG_IEEE80211W + ToDrv_SetPMF(priv, pstat); +#endif + + DEBUG_INFO("\nWPA2: 4-way handshake done\n"); + PSKDEBUG("WPA2: 4-way handshake done\n"); + //Wifi Logo FFD fragment attack, clear fragment list after 4-way handshake. + free_sta_frag_list(priv, pstat); + } +#endif // RTL_WPA2 + + // start unicast key rekey timer + if (priv->pmib->dot1180211AuthEntry.dot11UKRekeyTime) + pstat->uk_timeout = priv->pmib->dot1180211AuthEntry.dot11UKRekeyTime; + + if (!Message_Secure(pStaInfo->EapolKeyMsgRecvd)) + UpdateGK(priv); // send 2-1 + break; + + case PSK_STATE_PTKINITDONE: + // delete resend timer + SMP_LOCK_PSK_RESEND(flags); + if (timer_pending(&pStaInfo->resendTimer)){ + del_timer(&pStaInfo->resendTimer); + } + SMP_UNLOCK_PSK_RESEND(flags); + +#if 0 + //receive message [with request bit set] + if(Message_Request(global->EapolKeyMsgRecvd)) + //supp request to initiate 4-way handshake + { + + } +#endif + + //------------------------------------------------ + // Supplicant request to init 4 or 2 way handshake + //------------------------------------------------ + if (Message_Request(pStaInfo->EapolKeyMsgRecvd)) { + pStaInfo->state = PSK_STATE_PTKSTART; + if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Pairwise) { + if (Message_Error(pStaInfo->EapolKeyMsgRecvd)) + IntegrityFailure(priv); + else { + if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Group) { + if (Message_Error(pStaInfo->EapolKeyMsgRecvd)) { + //auth change group key, initilate 4-way handshake with supp and execute + //the Group key handshake to all Supplicants + pGblInfo->GKeyFailure = TRUE; + IntegrityFailure(priv); + } + } + } + //---- Start 4-way handshake ---- + pStaInfo->resendCnt = 0; + SendEAPOL(priv, pstat, 0); + } +//#ifdef RTL_WPA2_PREAUTH +// printf("kenny: %s() in akmsm_PTKINITDONE state. Call lib1x_akmsm_UpdateGK_proc()\n", (char *)__FUNCTION__); +//#endif + //---- Execute Group Key state machine for each STA ---- + UpdateGK(priv); + } else { + } + + break; + default: + break; + + }//switch + + } else if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Group) { + + // delete resend timer + SMP_LOCK_PSK_RESEND(flags); + if (timer_pending(&pStaInfo->resendTimer)){ + del_timer(&pStaInfo->resendTimer); + } + SMP_UNLOCK_PSK_RESEND(flags); + + //---- Receive 2nd message of 2-way handshake ---- + DEBUG_INFO("2-2\n"); + PSKDEBUG("2-2\n"); + if (!Message_Request(pStaInfo->EapolKeyMsgRecvd)) {//2nd message of 2-way handshake + //verify that replay counter maches one it has used in the Group Key handshake + if (Message_LargerReplayCounter(pStaInfo->CurrentReplayCounter, pStaInfo->EapolKeyMsgRecvd)) { + DEBUG_ERR("ERROR_LARGER_REPLAYCOUNTER\n"); + return; + } + if (!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) { + DEBUG_ERR("ERROR_MIC_FAIL\n"); + + LOG_MSG("2-way handshake failled! (2-2: MIC error)\n"); + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Authentication failed;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +#elif defined(CONFIG_RTL8196B_TLD) + LOG_MSG_DEL("[WLAN access rejected: incorrect security] from MAC address: %02x:%02x:%02x:%02x:%02x:%02x,\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +#elif defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->sta_status_cb_func) + priv->sta_status_cb_func("wlan0", pstat->hwaddr, WIFI_STA_STATUS_AUTH_FAIL); +#endif + + ToDrv_DisconnectSTA(priv, pstat, RSN_MIC_failure); + pStaInfo->state = PSK_STATE_IDLE; + return; + } + } else //if(!Message_Request(global->EapolKeyMsgRecvd)) + //supp request to change group key + { + } + + //------------------------------------------------------ + // Only when the group state machine is in the state of + // (1) The first STA Connected, + // (2) UPDATE GK to all station + // does the GKeyDoneStations needed to be decreased + //------------------------------------------------------ + + if (pGblInfo->GKeyDoneStations > 0) + pGblInfo->GKeyDoneStations--; + + //Avaya akm_sm->TimeoutCtr = 0; + //To Do : set port secure to driver + pStaInfo->gstate = PSK_GSTATE_REKEYESTABLISHED; + + if (pGblInfo->GKeyDoneStations == 0 && !pGblInfo->GkeyReady) { + ToDrv_SetGTK(priv); + DEBUG_INFO("2-way Handshake is finished\n"); + PSKDEBUG("2-way Handshake is finished\n"); + pGblInfo->GkeyReady = TRUE; + pGblInfo->GResetCounter = TRUE; + + // start groupkey rekey timer + if (priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime) + mod_timer(&pGblInfo->GKRekeyTimer, jiffies + RTL_SECONDS_TO_JIFFIES(priv->pmib->dot1180211AuthEntry.dot11GKRekeyTime)); + } else { + DEBUG_INFO(" Receive bad group key handshake"); + PSKDEBUG(" Receive bad group key handshake"); + } + } +} + +#ifdef CLIENT_MODE +static void ClientEAPOLKeyRecvd(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + WPA_GLOBAL_INFO *pGblInfo = priv->wpa_global_info; + WPA_STA_INFO *pStaInfo = pstat->wpa_sta_info; + LARGE_INTEGER recievedRC; + struct lib1x_eapol *eapol; + int toSetKey = 0, error_code=0; + OCTET_STRING tmpANonce; +#ifdef SMP_SYNC + unsigned long flags=0; +#endif + + eapol = ( struct lib1x_eapol * ) ( pstat->wpa_sta_info->EAPOLMsgRecvd.Octet + ETHER_HDRLEN ); + if (eapol->packet_type != LIB1X_EAPOL_KEY) { +#ifdef DEBUG_PSK + printk("Not Eapol-key pkt (type %d), drop\n", eapol->packet_type); +#endif + return; + } + + pStaInfo->EapolKeyMsgRecvd.Octet = pStaInfo->EAPOLMsgRecvd.Octet + ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN; + +#ifdef DEBUG_PSK + debug_out(NULL, pStaInfo->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Length); +#endif + + if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Pairwise) { + + if (Message_KeyMIC(pStaInfo->EapolKeyMsgRecvd) == FALSE) { + //---- Receive 1st message and send 2nd + DEBUG_INFO("client mode 4-1\n"); + PSKDEBUG("client mode 4-1\n"); + + SMP_LOCK_PSK_RESEND(flags); + if (timer_pending(&pStaInfo->resendTimer)){ + del_timer(&pStaInfo->resendTimer); + } + SMP_UNLOCK_PSK_RESEND(flags); + + if (pStaInfo->clientHndshkDone && pStaInfo->clientHndshkProcessing == fourWaystep4) { + DEBUG_INFO("AP trigger pairwise rekey\n"); + PSKDEBUG("AP trigger pairwise rekey\n"); + + //reset the client info------------------------------------------------------- + pStaInfo->CurrentReplayCounter.field.HighPart = 0xffffffff; + pStaInfo->CurrentReplayCounter.field.LowPart = 0xffffffff; + + pStaInfo->clientHndshkProcessing = FALSE; + pStaInfo->clientHndshkDone = FALSE; + + pGblInfo->GkeyReady = FALSE; + + //-------------------------------------------------------reset the client info + } + + //check replay counter + if(!Message_DefaultReplayCounter(pStaInfo->CurrentReplayCounter) && + Message_SmallerEqualReplayCounter(pStaInfo->CurrentReplayCounter, pStaInfo->EapolKeyMsgRecvd) ) { + DEBUG_ERR("client mode 4-1: ERROR_NONEEQUL_REPLAYCOUNTER\n"); + error_code=_RSON_UNSPECIFIED_; + goto error_reconn; + } + + + //set wpa_sta_info parameter---------------------------------------------------- + pstat->wpa_sta_info->RSNEnabled = priv->pmib->dot1180211AuthEntry.dot11EnablePSK; + if (pstat->wpa_sta_info->RSNEnabled == 1) { + if (priv->pmib->dot1180211AuthEntry.dot11WPACipher == 2) + pstat->wpa_sta_info->UnicastCipher = 0x2; + else if (priv->pmib->dot1180211AuthEntry.dot11WPACipher == 8) + pstat->wpa_sta_info->UnicastCipher = 0x4; + else + printk("unicastcipher in wpa = nothing\n"); + } else if (pstat->wpa_sta_info->RSNEnabled == 2) { + if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher == 2) + pstat->wpa_sta_info->UnicastCipher = 0x2; + else if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher == 8) + pstat->wpa_sta_info->UnicastCipher = 0x4; + else + printk("unicastcipher in wpa = nothing\n"); + } + +#ifdef CONFIG_IEEE80211W_CLI + if (Message_KeyDescVer(pStaInfo->EapolKeyMsgRecvd) == key_desc_ver3) + pStaInfo->AuthKeyMethod = DOT11_AuthKeyType_PSK_SHA256; +#endif + + //----------------------------------------------------set wpa_sta_info parameter + + INCOctet32_INTEGER(&pGblInfo->Counter); + SetNonce(pStaInfo->SNonce, pGblInfo->Counter); + + //pStaInfo->ANonce = Message_KeyNonce(pStaInfo->EapolKeyMsgRecvd); + tmpANonce = Message_KeyNonce(pStaInfo->EapolKeyMsgRecvd); + memcpy(pStaInfo->ANonce.Octet, tmpANonce.Octet, KEY_NONCE_LEN); + pStaInfo->ANonce.Length = tmpANonce.Length; + CalcPTK(pStaInfo->EAPOLMsgRecvd.Octet, pStaInfo->EAPOLMsgRecvd.Octet + 6, + pStaInfo->ANonce.Octet, pStaInfo->SNonce.Octet, + pStaInfo->PMK, PMK_LEN, pStaInfo->PTK, + (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK_SHA256) ? 48 : PTK_LEN_TKIP +#ifdef CONFIG_IEEE80211W + , (pStaInfo->AuthKeyMethod == DOT11_AuthKeyType_PSK_SHA256) +#endif + ); + +#ifdef DEBUG_PSK + debug_out("PSK: Generated PTK=", pStaInfo->PTK, PTK_LEN_TKIP); +#endif + /* Refine, make 4-2 only be sent 5 times + to prevent MAYBE some AP keep sending out 4-1 because of incorrect PSK */ + pStaInfo->clientHndshkProcessing = fourWaystep1; + ResendTimeout((unsigned long)pstat); + //ClientSendEAPOL(priv, pstat, 0); // send msg 2 + } else { + //---- Receive 3rd message ---- + DEBUG_INFO("client mode 4-3\n"); + PSKDEBUG("client mode 4-3\n"); + + if (!pStaInfo->clientHndshkProcessing) { + DEBUG_ERR("client mode 4-3: ERROR_MSG_1_ABSENT\n"); + error_code=_RSON_UNSPECIFIED_; + goto error_reconn; + } + + pStaInfo->resendCnt = 0; + pStaInfo->clientHndshkProcessing=fourWaystep3; + + // delete resend timer + SMP_LOCK_PSK_RESEND(flags); + if (timer_pending(&pStaInfo->resendTimer)){ + del_timer(&pStaInfo->resendTimer); + } + SMP_UNLOCK_PSK_RESEND(flags); + + Message_ReplayCounter_OC2LI(pStaInfo->EapolKeyMsgRecvd, &recievedRC); + if(!Message_DefaultReplayCounter(pStaInfo->CurrentReplayCounter) && + Message_SmallerEqualReplayCounter(pStaInfo->CurrentReplayCounter, pStaInfo->EapolKeyMsgRecvd) ) { + DEBUG_ERR("client mode 4-3: ERROR_NONEEQUL_REPLAYCOUNTER\n"); + error_code=_RSON_UNSPECIFIED_; + goto error_reconn; + } else if (!Message_EqualKeyNonce(pStaInfo->EapolKeyMsgRecvd, pStaInfo->ANonce)) { + DEBUG_ERR("client mode 4-3: ANonce not equal\n"); + error_code=_RSON_UNSPECIFIED_; + goto error_reconn; + } else if (!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) { + DEBUG_ERR("client mode 4-3: PTK MIC ERROR\n"); + LOG_MSG("Authentication failled! (4-3: MIC error)\n"); +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->link_status_cb_func) + priv->link_status_cb_func("wlan0", WIFI_LINK_STATUS_AUTH_FAIL); +#endif + error_code=_RSON_MIC_FAILURE_; + goto error_reconn; + } + + pStaInfo->CurrentReplayCounter.field.HighPart = recievedRC.field.HighPart; + pStaInfo->CurrentReplayCounter.field.LowPart = recievedRC.field.LowPart; + + if ((pStaInfo->RSNEnabled & PSK_WPA2) && (Message_DescType(pStaInfo->EapolKeyMsgRecvd) == desc_type_WPA2)) { + unsigned char decrypted_data[128]; + unsigned char GTK_KDE_OUI[] = { 0x00, 0x0F, 0xAC, 0x01 }; + unsigned char WPA_IE_OUI[] = { 0x00, 0x50, 0xF2, 0x01 }; + unsigned char *pGTK_KDE; + unsigned char *pKeyData; + unsigned short keyDataLength; + + keyDataLength = Message_KeyDataLength(pStaInfo->EapolKeyMsgRecvd); + pKeyData = pStaInfo->EapolKeyMsgRecvd.Octet + KeyDataPos; + + if(!DecWPA2KeyData(pStaInfo, pKeyData, keyDataLength, pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC + , decrypted_data, sizeof(decrypted_data))) + { + DEBUG_ERR("client mode 4-3: ERROR_AESKEYWRAP_MIC_FAIL\n"); + LOG_MSG("Authentication failled! (4-3: ERROR_AESKEYWRAP_MIC_FAIL)\n"); +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->link_status_cb_func) + priv->link_status_cb_func("wlan0", WIFI_LINK_STATUS_AUTH_FAIL); +#endif + error_code=_RSON_MIC_FAILURE_; + goto error_reconn; + } + + //wpa2_hexdump("4-3 KeyData (Decrypted)",decrypted_data,keyDataLength); + if ( decrypted_data[0] == WPA2_ELEMENT_ID) { + pGTK_KDE = &decrypted_data[2] + (unsigned char)decrypted_data[1]; + if ( *pGTK_KDE == WPA2_ELEMENT_ID ) { + // The second optional RSNIE is present + DEBUG_ERR("client mode 4-3: The second optional RSNIE is present! Cannot handle it yet!\n"); + error_code=_RSON_INVALID_IE_; + goto error_reconn; + } else if ( *pGTK_KDE == WPA_ELEMENT_ID ) { + // if contain RSN IE, skip it + if (!memcmp((pGTK_KDE+2), WPA_IE_OUI, sizeof(WPA_IE_OUI))) + pGTK_KDE += (unsigned char)*(pGTK_KDE+1) + 2; + + if (!memcmp((pGTK_KDE + 2), GTK_KDE_OUI, sizeof(GTK_KDE_OUI))) { + // GTK Key Data Encapsulation Format + unsigned char gtk_len = (unsigned char)*(pGTK_KDE+1) - 6; + unsigned char keyID = (unsigned char)*(pGTK_KDE+6) & 0x03; + pGblInfo->GN = keyID; + if (gtk_len > GTK_LEN) { + DEBUG_ERR("client mode 4-3: GTK length (%d) exceeds!\n", gtk_len); + return; + } + memcpy(pGblInfo->GTK[keyID], (pGTK_KDE+8), gtk_len); + toSetKey = 1; + pGblInfo->GkeyReady = TRUE; +#ifdef CONFIG_IEEE80211W_CLI + if (priv->support_pmf) { + unsigned char IGTK_KDE_TYPE[] = {0xDD, 0x1C, 0x00, 0x0F, 0xAC, 0x09}; + + if (!memcmp((pGTK_KDE+8+gtk_len), IGTK_KDE_TYPE, sizeof(IGTK_KDE_TYPE))) { + #define IGTK_HEADER_LEN 8 + PMFDEBUG("IGTK KDE Exists \n"); + memcpy(priv->pmib->dot11IGTKTable.dot11EncryptKey.dot11TTKey.skey, + (pGTK_KDE+8+gtk_len+sizeof(IGTK_KDE_TYPE)+IGTK_HEADER_LEN), IGTK_LEN); +#ifdef CONFIG_IEEE80211W_CLI_DEBUG + panic_printk("IGTK="); + int idx; + for (idx=0;idxpmib->dot11IGTKTable.dot11EncryptKey.dot11TTKey.skey[idx]); + panic_printk("\n"); +#endif + } else + PMFDEBUG("IGTK KDE Not Exists \n"); + } +#endif + } + } + + //check AP's RSNIE and set Group Key Chiper + if (decrypted_data[7] == _TKIP_PRIVACY_) + pGblInfo->MulticastCipher = _TKIP_PRIVACY_ ; + else if (decrypted_data[7] == _CCMP_PRIVACY_) + pGblInfo->MulticastCipher = _CCMP_PRIVACY_ ; + } + } else if ((pStaInfo->RSNEnabled & PSK_WPA) && (Message_DescType(pStaInfo->EapolKeyMsgRecvd) == desc_type_RSN)) { + unsigned char WPAkeyData[255]; + unsigned short DataLength; + memset(WPAkeyData, 0, 255); + DataLength = Message_KeyDataLength(pStaInfo->EapolKeyMsgRecvd); + memcpy(WPAkeyData, pStaInfo->EapolKeyMsgRecvd.Octet+KeyDataPos, 255); + + //check AP's RSNIE and set Group Key Chiper + if (WPAkeyData[11] == _TKIP_PRIVACY_) + pGblInfo->MulticastCipher = _TKIP_PRIVACY_ ; + else if (WPAkeyData[11] == _CCMP_PRIVACY_) + pGblInfo->MulticastCipher = _CCMP_PRIVACY_ ; + } + + /* Refine, make 4-4 only be sent 5 times + to prevent MAYBE some AP keep sending out 4-3 because of incorrect PSK */ + ResendTimeout((unsigned long)pstat); + //ClientSendEAPOL(priv, pstat, 0); // send msg 4 + + if (toSetKey) { + ToDrv_SetGTK(priv); + toSetKey = 0; + } + ToDrv_SetPTK(priv, pstat); + ToDrv_SetPort(priv, pstat, DOT11_PortStatus_Authorized); +#ifdef CONFIG_IEEE80211W_CLI + if (priv->support_pmf) + pstat->wpa_sta_info->mgmt_frame_prot = 1; + else + pstat->wpa_sta_info->mgmt_frame_prot = 0; + + ToDrv_SetPMF(priv,pstat); +#endif + //Wifi Logo FFD fragment attack, clear fragment list after 4-way handshake. + free_sta_frag_list(priv, pstat); + } + } else if (Message_KeyType(pStaInfo->EapolKeyMsgRecvd) == type_Group) { + + unsigned char decrypted_data[128]; + unsigned char GTK_KDE_OUI[] = { 0x00, 0x0F, 0xAC, 0x01 }; + unsigned char *pGTK_KDE; + unsigned char keyID; + + //---- Receive 1st message of 2-way handshake ---- + DEBUG_INFO("client mode receive 2-1\n"); + PSKDEBUG("client mode receive 2-1\n"); + + pStaInfo->resendCnt = 0; + + Message_ReplayCounter_OC2LI(pStaInfo->EapolKeyMsgRecvd, &recievedRC); + + if (Message_SmallerEqualReplayCounter(pStaInfo->CurrentReplayCounter, pStaInfo->EapolKeyMsgRecvd) ) { + DEBUG_ERR("client mode 2-1: ERROR_NONEEQUL_REPLAYCOUNTER\n"); + error_code=_RSON_UNSPECIFIED_; + goto error_reconn; + } else if (!CheckMIC(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK, PTK_LEN_EAPOLMIC)) { + DEBUG_ERR("client mode 2-1: ERROR_MIC_FAIL\n"); + LOG_MSG("Authentication failled! (4-2: MIC error)\n"); +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->link_status_cb_func) + priv->link_status_cb_func("wlan0", WIFI_LINK_STATUS_AUTH_FAIL); +#endif +#if defined(CONFIG_RTL8186_KB_N) + authRes = 1;//Auth failed +#endif + error_code=_RSON_MIC_FAILURE_; + goto error_reconn; + } else if (!DecGTK(pStaInfo->EAPOLMsgRecvd, pStaInfo->PTK + PTK_LEN_EAPOLMIC, PTK_LEN_EAPOLENC, + ((pGblInfo->MulticastCipher == DOT11_ENC_TKIP) ? 32:16), + pGblInfo->GTK[Message_KeyIndex(pStaInfo->EapolKeyMsgRecvd)], GTK_LEN)) { + DEBUG_ERR("client mode 2-1: ERROR_AESKEYWRAP_MIC_FAIL\n"); + error_code=_RSON_MIC_FAILURE_; + goto error_reconn; + } + + keyID = Message_KeyIndex(pStaInfo->EapolKeyMsgRecvd); + if ((pStaInfo->RSNEnabled & PSK_WPA2) && (Message_DescType(pStaInfo->EapolKeyMsgRecvd) == desc_type_WPA2)) { + unsigned char KDE_OUI[] = {0x00, 0x0F, 0xAC}; + unsigned short key_data_len = Message_KeyDataLength(pStaInfo->EapolKeyMsgRecvd); + struct KDE *pkde; + unsigned char *pgtk_kde; + + if (key_data_len > sizeof(decrypted_data)) { + DEBUG_ERR("client mode 2-1: keyID length (%d) exceeds!\n", key_data_len); + return; + } + memcpy(decrypted_data, pGblInfo->GTK[keyID], key_data_len); + pkde = (struct KDE *)decrypted_data; + pgtk_kde = (unsigned char *)pkde + sizeof(struct KDE); + + while (key_data_len > 0) { + if (pkde->type != WPA_ELEMENT_ID) { + error_code = _RSON_INVALID_IE_; + goto error_reconn; + } + + if (pkde->length == 0) { + break; + } else if (!memcmp(pkde->oui, KDE_OUI, sizeof(KDE_OUI))) { + unsigned char gtk_len; + + if (pkde->data_type == GTK_KDE) { + unsigned char key_id = pgtk_kde[0] & 0x03; + gtk_len = pkde->length - 6; + pGblInfo->GN = key_id; + if (gtk_len > GTK_LEN) { + DEBUG_ERR("client mode 2-1 GTK_KDE: GTK length (%d) exceeds!\n", gtk_len); + return; + } + memcpy(pGblInfo->GTK[key_id], (pgtk_kde + 2), gtk_len); + } +#ifdef CONFIG_IEEE80211W_CLI + else if (pkde->data_type == IGTK_KDE) { + unsigned short key_id = le16_to_cpu(*(unsigned short *)pgtk_kde); + gtk_len = pkde->length - 12; + + pGblInfo->GN_igtk = key_id; + if (gtk_len > IGTK_LEN) { + DEBUG_ERR("client mode 2-1 IGTK_KDE: GTK length (%d) exceeds!\n", gtk_len); + return; + } + memcpy(pGblInfo->IGTK[key_id-4], (pgtk_kde + 8), gtk_len); // should be shift 4?? + memcpy(priv->pmib->dot11IGTKTable.dot11EncryptKey.dot11TTKey.skey, (pgtk_kde + 8), gtk_len); + } +#endif + else { + DEBUG_INFO("data_type=%d don't process\n", pkde->data_type); + } + + key_data_len -= (2 + pkde->length); + pkde = (unsigned char *)pkde + (2 + pkde->length); + pgtk_kde = (unsigned char *)pkde + sizeof(struct KDE); + + } else { + error_code = _RSON_INVALID_IE_; + goto error_reconn; + } + } + } else { + pGblInfo->GN = keyID; + } + //MLME_SETKEYS.request() to set Group Key; + pGblInfo->GkeyReady = TRUE; + + pStaInfo->CurrentReplayCounter.field.HighPart = recievedRC.field.HighPart; + pStaInfo->CurrentReplayCounter.field.LowPart = recievedRC.field.LowPart; + pStaInfo->clientGkeyUpdate = 1; + + ToDrv_SetGTK(priv); + ClientSendEAPOL(priv, pstat, 0); // send msg 2-1 + } else { + printk("Client EAPOL Key Receive ERROR!!\n"); + error_code = _RSON_UNSPECIFIED_; + } + +error_reconn: + if(error_code) { + unsigned int opmode = OPMODE; + if(ACTIVE_ID == 0) { + priv->dot114WayStatus = error_code; + } + issue_deauth(priv,BSSID,error_code); + free_stainfo(priv, pstat); + opmode &= ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE); + OPMODE_VAL(opmode); + JOIN_RES_VAL(STATE_Sta_No_Bss); + start_clnt_lookup(priv, RESCAN); + } +} +#endif // CLIENT_MODE + + +void derivePSK(struct rtl8192cd_priv *priv) +{ + WPA_GLOBAL_INFO *pGblInfo=priv->wpa_global_info; + //unsigned long x; + //SAVE_INT_AND_CLI(x); + + if (strlen((char *)priv->pmib->dot1180211AuthEntry.dot11PassPhrase) == 64) // hex + get_array_val(pGblInfo->PSK, (char *)priv->pmib->dot1180211AuthEntry.dot11PassPhrase, 64); + else + PasswordHash((char *)priv->pmib->dot1180211AuthEntry.dot11PassPhrase, SSID, SSID_LEN, + pGblInfo->PSK); + + if (priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest[0]) { + if (strlen((char *)priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest) == 64) + get_array_val(pGblInfo->PSKGuest, (char *)priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest, 64); + else + PasswordHash((char *)priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest, SSID, SSID_LEN, + pGblInfo->PSKGuest); + } + + //RESTORE_INT(x); +} + +void psk_init(struct rtl8192cd_priv *priv) +{ + WPA_GLOBAL_INFO *pGblInfo=priv->wpa_global_info; + int i, j, low_cipher=0; + + DEBUG_TRACE; + + memset((char *)pGblInfo, '\0', sizeof(WPA_GLOBAL_INFO)); + + //---- Counter is initialized whenever boot time ---- + GenNonce(pGblInfo->Counter.charData, (unsigned char*)"addr"); + + if (OPMODE & WIFI_AP_STATE) { + //---- Initialize Goup Key state machine ---- + pGblInfo->GNonce.Octet = pGblInfo->GNonceBuf; + pGblInfo->GNonce.Length = KEY_NONCE_LEN; + pGblInfo->GTKAuthenticator = TRUE; + pGblInfo->GN = 1; + pGblInfo->GM = 2; +#ifdef CONFIG_IEEE80211W + pGblInfo->GN_igtk = 4; + pGblInfo->GM_igtk = 5; +#endif /* CONFIG_IEEE80211W */ + pGblInfo->GInitAKeys = TRUE; // david+2006-04-04, fix the issue of re-generating group key + + init_timer(&pGblInfo->GKRekeyTimer); + pGblInfo->GKRekeyTimer.data = (unsigned long)priv; + pGblInfo->GKRekeyTimer.function = GKRekeyTimeout; + } +#if 0 + if (strlen(priv->pmib->dot1180211AuthEntry.dot11PassPhrase) == 64) // hex + get_array_val(pGblInfo->PSK, priv->pmib->dot1180211AuthEntry.dot11PassPhrase, 64); + else + PasswordHash(priv->pmib->dot1180211AuthEntry.dot11PassPhrase, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, + pGblInfo->PSK); + + if (priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest[0]) { + if (strlen(priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest) == 64) + get_array_val(pGblInfo->PSKGuest, priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest, 64); + else + PasswordHash(priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, + pGblInfo->PSKGuest); + } +#else + derivePSK(priv); +#endif +#ifdef DEBUG_PSK + debug_out("PSK: PMK=", pGblInfo->PSK, PMK_LEN); + if (priv->pmib->dot1180211AuthEntry.dot11PassPhraseGuest[0]) + debug_out("PSK-Guest: PMK=", pGblInfo->PSKGuest, PMK_LEN); +#endif + + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) && + !priv->pmib->dot1180211AuthEntry.dot11WPACipher) { + DEBUG_ERR("psk_init failed, WPA cipher did not set!\n"); + return; + } + +#ifdef RTL_WPA2 + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2) && + !priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher) { + DEBUG_ERR("psk_init failed, WPA2 cipher did not set!\n"); + return; + } +#endif + + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2) && + !(priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA)) { + if (priv->pmib->dot1180211AuthEntry.dot11WPACipher) + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0; + } + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) && + !(priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2)) { + if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher) + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + } + + if (priv->pmib->dot1180211AuthEntry.dot11WPACipher) { + for (i=0, j=0; i<_WEP_104_PRIVACY_; i++) { + if (priv->pmib->dot1180211AuthEntry.dot11WPACipher & (1<UnicastCipher[j] = i+1; + if (low_cipher == 0) + low_cipher = pGblInfo->UnicastCipher[j]; + else { + if (low_cipher == _WEP_104_PRIVACY_ && + pGblInfo->UnicastCipher[j] == _WEP_40_PRIVACY_) + low_cipher = pGblInfo->UnicastCipher[j]; + else if (low_cipher == _TKIP_PRIVACY_ && + (pGblInfo->UnicastCipher[j] == _WEP_40_PRIVACY_ || + pGblInfo->UnicastCipher[j] == _WEP_104_PRIVACY_)) + low_cipher = pGblInfo->UnicastCipher[j]; + else if (low_cipher == _CCMP_PRIVACY_) + low_cipher = pGblInfo->UnicastCipher[j]; + } + if (++j >= MAX_UNICAST_CIPHER) + break; + } + } + pGblInfo->NumOfUnicastCipher = j; + } + +#ifdef CLIENT_MODE + if((OPMODE & WIFI_ADHOC_STATE)&&(priv->pmib->dot1180211AuthEntry.dot11EnablePSK & 2)) // if WPA2 + low_cipher = 0; +#endif + +#ifdef RTL_WPA2 + if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher) { + for (i=0, j=0; i<_WEP_104_PRIVACY_; i++) { + if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher & (1<UnicastCipherWPA2[j] = i+1; + if (low_cipher == 0) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + else { + if (low_cipher == _WEP_104_PRIVACY_ && + pGblInfo->UnicastCipherWPA2[j] == _WEP_40_PRIVACY_) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + else if (low_cipher == _TKIP_PRIVACY_ && + (pGblInfo->UnicastCipherWPA2[j] == _WEP_40_PRIVACY_ || + pGblInfo->UnicastCipherWPA2[j] == _WEP_104_PRIVACY_)) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + else if (low_cipher == _CCMP_PRIVACY_) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + } + if (++j >= MAX_UNICAST_CIPHER) + break; + } + } + pGblInfo->NumOfUnicastCipherWPA2= j; + } +#endif + + pGblInfo->MulticastCipher = low_cipher; + +#ifdef DEBUG_PSK + printk("PSK: WPA unicast cipher= "); + for (i=0; iNumOfUnicastCipher; i++) + printk("%x ", pGblInfo->UnicastCipher[i]); + printk("\n"); + +#ifdef RTL_WPA2 + printk("PSK: WPA2 unicast cipher= "); + for (i=0; iNumOfUnicastCipherWPA2; i++) + printk("%x ", pGblInfo->UnicastCipherWPA2[i]); + printk("\n"); +#endif + + printk("PSK: multicast cipher= %x\n", pGblInfo->MulticastCipher); +#endif + + pGblInfo->AuthInfoElement.Octet = pGblInfo->AuthInfoBuf; + + ConstructIE(priv, pGblInfo->AuthInfoElement.Octet, + &pGblInfo->AuthInfoElement.Length); + + ToDrv_SetIE(priv); +} + +#if defined(WDS) && defined(INCLUDE_WPA_PSK) +void wds_psk_set(struct rtl8192cd_priv *priv, int idx, unsigned char *key) +{ + unsigned char pchar[40]; + + if (key == NULL) { + if (strlen((char *)priv->pmib->dot11WdsInfo.wdsPskPassPhrase) == 64) // hex + get_array_val(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], (char *)priv->pmib->dot11WdsInfo.wdsPskPassPhrase, 64); + else { + memset(pchar, 0, sizeof(unsigned char)*40); + PasswordHash((char *)priv->pmib->dot11WdsInfo.wdsPskPassPhrase,(unsigned char *)"REALTEK", strlen("REALTEK"), pchar); + memcpy(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], pchar, sizeof(unsigned char)*32); + } + } else + memcpy(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], key, sizeof(unsigned char)*32); + + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] = 32; + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] |= 0x80000000; //set bit to protect the key +} + + +void wds_psk_init(struct rtl8192cd_priv *priv) +{ + unsigned char *key; + int i; + + if ( !(OPMODE & WIFI_AP_STATE)) + return; + + for (i = 0; i < priv->pmib->dot11WdsInfo.wdsNum; i++) { + if (i==0) + key = NULL; + else + key = priv->pmib->dot11WdsInfo.wdsMapingKey[0]; + + wds_psk_set(priv, i, key); + } +} +#endif + +#ifdef CONFIG_IEEE80211W +void ToDrv_SA_QUERY_RSP(struct rtl8192cd_priv *priv, const u8 *sa, const u8 *trans_id) +{ + struct iw_point wrq; + DOT11_SA_QUERY_RSP resp; + + + wrq.pointer = &resp; + wrq.length = sizeof(resp); + + resp.EventId = DOT11_EVENT_SA_QUERY_RSP; + resp.IsMoreEvent = FALSE; + memcpy(resp.MACAddr, sa, 6); + memcpy(resp.trans_id, trans_id, 2); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +void ieee802_11_sa_query_action(struct rtl8192cd_priv *priv, unsigned char *sa, unsigned char *pframe, int len) +{ + unsigned char Category_field = pframe[0]; + unsigned char Action_field = pframe[1]; + unsigned char trans_id[2]; + struct stat_info *pstat; + + memcpy(trans_id, pframe + 2, 2); + + if (Action_field == _SA_QUERY_REQ_ACTION_ID_) { + printk("IEEE 802.11: Received SA Query Request from %02x:%02x:%02x:%02x:%02x:%02x\n" + , sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); + printk("IEEE 802.11: SA Query Transaction ID %d\n", trans_id); + + pstat = get_stainfo(priv, sa); + if (pstat == NULL || pstat->wpa_sta_info->state != PSK_STATE_PTKINITDONE) { + printk("IEEE 802.11: Ignore SA Query Request from unassociated STA %02x:%02x:%02x:%02x:%02x:%02x\n" + , sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); + return; + } + + printk("IEEE 802.11: Sending SA Query Response to %02x:%02x:%02x:%02x:%02x:%02x\n" + , sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); + ToDrv_SA_QUERY_RSP(priv, sa, trans_id); + return; + } + + if (Action_field != _SA_QUERY_RSP_ACTION_ID_) { + printk("IEEE 802.11: Unexpected SA Query Action %d\n", Action_field); + return; + } +} +#endif // CONFIG_IEEE80211W + +int psk_indicate_evt(struct rtl8192cd_priv *priv, int id, unsigned char *mac, unsigned char *msg, int len) +{ + struct stat_info *pstat; + static unsigned char tmpbuf[1024]; + int ret; +#ifdef RTL_WPA2 + int isWPA2=0; +#endif + + if (!priv->pmib->dot1180211AuthEntry.dot11EnablePSK || + !((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_))) + return -1; + +#ifdef DEBUG_PSK + printk("PSK: Got evt:%s[%x], sta: %02x:%02x:%02x:%02x:%02x:%02x, msg_len=%x\n", + ID2STR(id), id, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], len); +#endif + + pstat = get_stainfo(priv, mac); +// button 2009.05.21 +#if 0 + if (pstat == NULL) +#else + if (pstat == NULL && id!=DOT11_EVENT_WPA_MULTICAST_CIPHER && id!=DOT11_EVENT_WPA2_MULTICAST_CIPHER) +#endif + { + DEBUG_ERR("Invalid mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return -1; + } + + switch (id) { + case DOT11_EVENT_ASSOCIATION_IND: + case DOT11_EVENT_REASSOCIATION_IND: + reset_sta_info(priv, pstat); + + if (OPMODE & WIFI_AP_STATE) { + // check RSNIE + if (len > 2 && msg != NULL) { +#ifdef DEBUG_PSK + debug_out("PSK: Rx Assoc-ind, RSNIE", msg, len); +#endif + +#ifdef RTL_WPA2 + memcpy(tmpbuf, msg, len); + len -= 2; +#else + tmpbuf[0] = RSN_ELEMENT_ID; + tmpbuf[1] = len; + memcpy(tmpbuf+2, msg, len); +#endif + +#ifdef RTL_WPA2 + isWPA2 = (tmpbuf[0] == WPA2_ELEMENT_ID) ? 1 : 0; + if (isWPA2) + ret = parseIEWPA2(priv, pstat->wpa_sta_info, tmpbuf, len+2); + else +#endif + ret = parseIE(priv, pstat->wpa_sta_info, tmpbuf, len+2); + if (ret != 0) { + DEBUG_ERR("parse IE error [%x]!\n", ret); + } + + // issue assoc-rsp successfully + ToDrv_RspAssoc(priv, id, mac, -ret); + + if (ret == 0) { +#ifdef EVENT_LOG + char *pmsg; + switch (pstat->wpa_sta_info->UnicastCipher) { + case DOT11_ENC_NONE: pmsg = "none"; break; + case DOT11_ENC_WEP40: pmsg = "WEP40"; break; + case DOT11_ENC_TKIP: pmsg = "TKIP"; break; + case DOT11_ENC_WRAP: pmsg = "AES"; break; + case DOT11_ENC_CCMP: pmsg = "AES"; break; + case DOT11_ENC_WEP104: pmsg = "WEP104"; break; + default: pmsg = "invalid algorithm"; break; + } +#ifdef RTL_WPA2 + LOG_MSG("%s-%s PSK authentication in progress...\n", (isWPA2 ? "WPA2" : "WPA"), pmsg); +#else + LOG_MSG("%s-WPA PSK authentication in progress...\n", pmsg); +#endif +#endif + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Authenticating......;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +#endif + AuthenticationRequest(priv, pstat); // send 4-1 + } + } else { // RNSIE is null + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) + ToDrv_RspAssoc(priv, id, mac, -ERROR_INVALID_RSNIE); + } + } +#ifdef CLIENT_MODE + else + mod_timer(&pstat->wpa_sta_info->resendTimer, jiffies + WAIT_EAP_TIME); +#endif + break; + + case DOT11_EVENT_DISASSOCIATION_IND: + reset_sta_info(priv, pstat); + break; + +#ifdef CONFIG_IEEE80211W + case DOT11_EVENT_SA_QUERY: + ieee802_11_sa_query_action(priv, mac, msg, len); + break; +#endif + + case DOT11_EVENT_EAP_PACKET: + if (OPMODE & WIFI_AP_STATE) { + if (pstat->wpa_sta_info->state == PSK_STATE_IDLE) { + DEBUG_ERR("Rx EAPOL packet but did not get Assoc-Ind yet!\n"); + break; + } + } + + if (len > MAX_EAPOLMSG_LEN) { + DEBUG_ERR("Rx EAPOL packet which length is too long [%x]!\n", len); + break; + } + +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_STATION_STATE) && + !(pstat->wpa_sta_info->clientHndshkProcessing||pstat->wpa_sta_info->clientHndshkDone)) { +#ifdef EVENT_LOG + char *pmsg; + switch (pstat->wpa_sta_info->UnicastCipher) { + case DOT11_ENC_NONE: pmsg = "none"; break; + case DOT11_ENC_WEP40: pmsg = "WEP40"; break; + case DOT11_ENC_TKIP: pmsg = "TKIP"; break; + case DOT11_ENC_WRAP: pmsg = "AES"; break; + case DOT11_ENC_CCMP: pmsg = "AES"; break; + case DOT11_ENC_WEP104: pmsg = "WEP104"; break; + default: pmsg = "invalid algorithm"; break; + } + LOG_MSG("%s-%s PSK authentication in progress...\n", (isWPA2 ? "WPA2" : "WPA"), pmsg); +#endif + reset_sta_info(priv, pstat); + }else if(OPMODE & WIFI_ADHOC_STATE){ + DEBUG_ERR("Rx EAPOL packet but not support 4 way handshark yet on Ad-hoc mode, block it!\n"); + break; + } +#endif + memcpy(pstat->wpa_sta_info->EAPOLMsgRecvd.Octet, msg, len); + pstat->wpa_sta_info->EAPOLMsgRecvd.Length = len; + if (OPMODE & WIFI_AP_STATE) + EAPOLKeyRecvd(priv, pstat); +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + ClientEAPOLKeyRecvd(priv, pstat); +#endif + break; + + case DOT11_EVENT_MIC_FAILURE: +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) + ClientSendEAPOL(priv, pstat, 0); +#endif + break; + +// button 2009.05.21 + case DOT11_EVENT_WPA_MULTICAST_CIPHER: + case DOT11_EVENT_WPA2_MULTICAST_CIPHER: +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + priv->wpa_global_info->MulticastCipher = *msg; + ConstructIE(priv, priv->wpa_global_info->AuthInfoElement.Octet, + &priv->wpa_global_info->AuthInfoElement.Length); + memcpy((void *)priv->pmib->dot11RsnIE.rsnie, priv->wpa_global_info->AuthInfoElement.Octet + , priv->wpa_global_info->AuthInfoElement.Length); + DEBUG_WARN("####### MulticastCipher=%d\n", priv->wpa_global_info->MulticastCipher); + } +#endif + break; + } + + return 0; +} + +void UKRekeyTimeout(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + AuthenticationRequest(priv, pstat); +} + + + +#ifdef CONFIG_RTK_MESH +void dot11s_mp_set_key(DRV_PRIV *priv, unsigned char *mac) +{ + DOT11_SET_KEY Set_Key; + struct Dot11EncryptKey *pEncryptKey = &(priv->pmib->dot11sKeysTable.dot11EncryptKey); + unsigned char key[40]; + + if(pEncryptKey->dot11TTKeyLen == 0) { + if (strlen((char *)priv->pmib->dot1180211sInfo.dot11PassPhrase) == 64) {// hex + get_array_val(key, (char *)priv->pmib->dot1180211sInfo.dot11PassPhrase, 64); + } else { + PasswordHash(priv->pmib->dot1180211sInfo.dot11PassPhrase, + priv->pmib->dot1180211sInfo.mesh_id, + strlen(priv->pmib->dot1180211sInfo.mesh_id), + key); + } + pEncryptKey->dot11TTKeyLen = 16; + memcpy(pEncryptKey->dot11TTKey.skey, key, pEncryptKey->dot11TTKeyLen); + } + + memset(key, 0, sizeof(key)); + memcpy(key, pEncryptKey->dot11TTKey.skey, pEncryptKey->dot11TTKeyLen); + memcpy(Set_Key.MACAddr, mac, MACADDRLEN); + Set_Key.KeyType = DOT11_KeyType_Pairwise; + Set_Key.EncType = DOT11_ENC_CCMP; + Set_Key.KeyIndex = priv->pmib->dot11sKeysTable.keyid; + DOT11_Process_Set_Key(priv->dev, NULL, &Set_Key, key); +} + +#endif + + + +#ifdef SUPPORT_CLIENT_MIXED_SECURITY +void choose_cipher(struct rtl8192cd_priv *priv, struct bss_desc *bss_target) +{ + unsigned int t_stamp; + int len; + int dot11EnablePSK = 0; + int dot11WPACipher = 0; + int dot11WPA2Cipher = 0; + unsigned char dot11PrivacyAlgrthm = _NO_PRIVACY_; + + t_stamp = bss_target->t_stamp[0]; + + if ( bss_target->capability & BIT4 ) { /*Privacy bit*/ + // fetch WPA2 + if ( (t_stamp & BIT18) || (t_stamp & BIT20) ) { + dot11EnablePSK |= PSK_WPA2; + // pairwise cipher + if ( t_stamp & BIT24 ) + dot11WPA2Cipher |= BIT1; + if ( t_stamp & BIT26 ) + dot11WPA2Cipher |= BIT3; + } + + // fetch WPA + if ( (t_stamp & BIT2) || (t_stamp & BIT4) ) { + dot11EnablePSK |= PSK_WPA; + // unicast cipher + if ( t_stamp & BIT8 ) + dot11WPACipher |= BIT1; + if ( t_stamp & BIT10 ) + dot11WPACipher |= BIT3; + } + } + + DEBUG_INFO("\ndot11EnablePSK: %d %d\n", priv->pmib->dot1180211AuthEntry.dot11EnablePSK, dot11EnablePSK); + DEBUG_INFO("dot11WPACipher: %d %d\n", priv->pmib->dot1180211AuthEntry.dot11WPACipher, dot11WPACipher); + DEBUG_INFO("dot11WPA2Cipher: %d %d\n", priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher, dot11WPA2Cipher); + + if (priv->pshare->rf_ft_var.auto_cipher) { + // privacy enable and not exist WPA & WPA2 ie -> WEP encryption + if ( dot11EnablePSK == 0 ) { + len = strlen(priv->pmib->dot11DefaultKeysTable.keytype[0].skey); + if ( len == 5 ) + dot11PrivacyAlgrthm = _WEP_40_PRIVACY_; + else if (len == 13 ) + dot11PrivacyAlgrthm = _WEP_104_PRIVACY_; + } else { // WPA or WPA2 encryption + // Select the most higher security (AES > WPA2 > OTHER) + if ( (dot11WPACipher & BIT3) || + (dot11WPA2Cipher & BIT3) ) { + if (dot11WPA2Cipher & BIT3 ) { + dot11EnablePSK = PSK_WPA2; + dot11WPACipher = 0; + dot11WPA2Cipher = BIT3; + + } else { + dot11EnablePSK = PSK_WPA; + dot11WPACipher = BIT3; + dot11WPA2Cipher = 0; + } + + dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + } else { + if ( dot11EnablePSK & PSK_WPA2 ) { + dot11EnablePSK = PSK_WPA2; + dot11WPACipher = 0; + dot11WPA2Cipher = BIT1; + } else { + dot11EnablePSK = PSK_WPA; + dot11WPACipher = BIT1; + dot11WPA2Cipher = 0; + } + + dot11PrivacyAlgrthm = _TKIP_PRIVACY_; + } + } + } + else { + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & dot11EnablePSK) + && ((priv->pmib->dot1180211AuthEntry.dot11WPACipher & dot11WPACipher) + || (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher & dot11WPA2Cipher)) + ) { + + if ((priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher & dot11WPA2Cipher) & BIT3) { + DEBUG_INFO("\nWPA2-AES\n"); + dot11EnablePSK = PSK_WPA2; + dot11WPACipher = 0; + dot11WPA2Cipher = BIT3; + dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + } else if ((priv->pmib->dot1180211AuthEntry.dot11WPACipher & dot11WPACipher) & BIT3) { + DEBUG_INFO("\nWPA-AES\n"); + dot11EnablePSK = PSK_WPA; + dot11WPACipher = BIT3; + dot11WPA2Cipher = 0; + dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + } else if ((priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher & dot11WPA2Cipher) & BIT1) { + DEBUG_INFO("\nWPA2-TKIP\n"); + dot11EnablePSK = PSK_WPA2; + dot11WPACipher = 0; + dot11WPA2Cipher = BIT1; + dot11PrivacyAlgrthm = _TKIP_PRIVACY_; + } else if ((priv->pmib->dot1180211AuthEntry.dot11WPACipher & dot11WPACipher) & BIT1) { + DEBUG_INFO("\nWPA-TKIP\n"); + dot11EnablePSK = PSK_WPA; + dot11WPACipher = BIT1; + dot11WPA2Cipher = 0; + dot11PrivacyAlgrthm = _TKIP_PRIVACY_; + } else { + DEBUG_INFO("No match wpa cipher!!!\n"); + return; + } + } else { + DEBUG_INFO("Not wpa enable!!!\n"); + return; + } + } + + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = dot11EnablePSK; + priv->pmib->dot1180211AuthEntry.dot11WPACipher = dot11WPACipher; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = dot11WPA2Cipher; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = dot11PrivacyAlgrthm; + + DEBUG_INFO("choose_cipher: psk_enable %d wpa_cipher %d wpa2_cipher %d\n\n", + priv->pmib->dot1180211AuthEntry.dot11EnablePSK, + priv->pmib->dot1180211AuthEntry.dot11WPACipher, + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher); + + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) { + psk_init(priv); + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1; + } else { + priv->pmib->dot11RsnIE.rsnielen = 0; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + } + + if (should_forbid_Nmode(priv)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { +#ifdef SUPPORT_MULTI_PROFILE + if (!priv->mask_n_band) + priv->mask_n_band = (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N | WIRELESS_11AC)); +#endif + priv->pmib->dot11BssType.net_work_type &= ~(WIRELESS_11N | WIRELESS_11AC); + } + } +#ifdef SUPPORT_MULTI_PROFILE + else { + if (priv->mask_n_band) { + priv->pmib->dot11BssType.net_work_type |= priv->mask_n_band; + priv->mask_n_band = 0; + } + } +#endif +} +#endif + +#endif // INCLUDE_WPA_PSK + + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_psk.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_psk.h new file mode 100755 index 000000000..65adf03ed --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_psk.h @@ -0,0 +1,408 @@ +/* + * Header files of WPA PSK module + * + * $Id: 8192cd_psk.h,v 1.1 2009/11/06 12:26:48 victoryman Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_PSK_H_ +#define _8192CD_PSK_H_ + +#define GMK_LEN 32 +#define GTK_LEN 32 +#define PMK_LEN 32 +#define PTK_LEN 32 +#ifdef CONFIG_IEEE80211W +#define IGTK_LEN 16 +#endif /* CONFIG_IEEE80211W */ +#define KEY_NONCE_LEN 32 +#define NumGroupKey 4 +#define KEY_RC_LEN 8 +#define KEY_NONCE_LEN 32 +#define KEY_IV_LEN 16 +#define KEY_RSC_LEN 8 +#define KEY_ID_LEN 8 +#define KEY_MIC_LEN 16 +#define KEY_MATERIAL_LEN 2 +#define PTK_LEN_EAPOLMIC 16 +#define PTK_LEN_EAPOLENC 16 +#define PTK_LEN_TKIP 64 +#define PMKID_LEN 16 +#define LIB1X_ETHER_EAPOL_TYPE 0x888E + +#define DescTypePos 0 +#define KeyInfoPos 1 +#define KeyLenPos 3 +#define ReplayCounterPos 5 +#define KeyNoncePos 13 +#define KeyIVPos 45 +#define KeyRSCPos 61 +#define KeyIDPos 69 +#define KeyMICPos 77 +#define KeyDataLenPos 93 +#define KeyDataPos 95 +#define LIB1X_EAPOL_VER 1 //00000001B +#define LIB1X_EAPOL_LOGOFF 2 //0000 0010B +#define LIB1X_EAPOL_EAPPKT 0 //0000 0000B +#define LIB1X_EAPOL_START 1 //0000 0001B +#define LIB1X_EAPOL_KEY 3 //0000 0011B +#define LIB1X_EAPOL_ENCASFALERT 4 //0000 0100B +#ifdef CONFIG_IEEE80211W_CLI +#define KeyAKMPos 16 +#define KEY_AKM_LEN 4 +#endif + +#define RANDOM_EXPANSION_CONST "Init Counter" +#define RANDOM_EXPANSION_CONST_SIZE 12 +#define A_SHA_DIGEST_LEN 20 +#define ETHER_HDRLEN 14 +#define LIB1X_EAPOL_HDRLEN 4 +#define INFO_ELEMENT_SIZE 128 +#define MAX_EAPOLMSG_LEN 512 +#define MAX_EAPOLKEYMSG_LEN (MAX_EAPOLMSG_LEN-(ETHER_HDRLEN+LIB1X_EAPOL_HDRLEN)) +#define EAPOLMSG_HDRLEN 95 //EAPOL-key payload length without KeyData +#define MAX_UNICAST_CIPHER 2 +#define WPA_ELEMENT_ID 0xDD +#define WPA2_ELEMENT_ID 0x30 + +typedef enum { desc_type_WPA2 = 2, desc_type_RSN = 254 } DescTypeRSN; +typedef enum { type_Group = 0, type_Pairwise = 1 } KeyType; +typedef enum { key_desc_ver1 = 1, key_desc_ver2 = 2, key_desc_ver3 = 3 } KeyDescVer; +enum { PSK_WPA=1, PSK_WPA2=2}; + +#ifdef TLN_STATS +enum { STATS_AUTH_OPEN=0, STATS_AUTH_SHARE=1, + STATS_PSK_WPA=2, STATS_PSK_WPA2=3, + STATS_ETP_WPA=4, STATS_ETP_WPA2=5 + }; +#endif + +enum { + PSK_STATE_IDLE, + PSK_STATE_PTKSTART, + PSK_STATE_PTKINITNEGOTIATING, + PSK_STATE_PTKINITDONE, +}; + +enum { + PSK_GSTATE_REKEYNEGOTIATING, + PSK_GSTATE_REKEYESTABLISHED, + PSK_GSTATE_KEYERROR, +}; + +#ifdef CONFIG_IEEE80211W +enum mfp_options { + NO_MGMT_FRAME_PROTECTION = 0, + MGMT_FRAME_PROTECTION_OPTIONAL = 1, + MGMT_FRAME_PROTECTION_REQUIRED = 2 +}; +#endif + +/* + * Reason code for Disconnect + */ +typedef enum _ReasonCode{ + unspec_reason = 0x01, + auth_not_valid = 0x02, + deauth_lv_ss = 0x03, + inactivity = 0x04, + ap_overload = 0x05, + class2_err = 0x06, + class3_err = 0x07, + disas_lv_ss = 0x08, + asoc_not_auth = 0x09, + RSN_invalid_info_element = 13, + RSN_MIC_failure = 14, + RSN_4_way_handshake_timeout = 15, + RSN_diff_info_element = 17, + RSN_multicast_cipher_not_valid = 18, + RSN_unicast_cipher_not_valid = 19, + RSN_AKMP_not_valid = 20, + RSN_unsupported_RSNE_version = 21, + RSN_invalid_RSNE_capabilities = 22, + RSN_ieee_802dot1x_failed = 23, + //belowing are Realtek definition + RSN_PMK_not_avaliable = 24, + expire = 30, + session_timeout = 31, + acct_idle_timeout = 32, + acct_user_request = 33 +}ReasonCode; + + +typedef struct _OCTET_STRING { + unsigned char *Octet; + int Length; +} OCTET_STRING, *POCTET_STRING; + +typedef union _LARGE_INTEGER { + unsigned char charData[8]; + struct { + unsigned int HighPart; + unsigned int LowPart; + } field; +} LARGE_INTEGER, *PLARGE_INTEGER; + +typedef union _OCTET16_INTEGER { + unsigned char charData[16]; + struct { + LARGE_INTEGER HighPart; + LARGE_INTEGER LowPart; + } field; +} OCTET16_INTEGER; + +typedef union _OCTET32_INTEGER { + unsigned char charData[32]; + struct { + OCTET16_INTEGER HighPart; + OCTET16_INTEGER LowPart; + } field; +} OCTET32_INTEGER; + +typedef struct _DOT11_WPA2_IE_HEADER { + unsigned char ElementID; + unsigned char Length; + unsigned short Version; +} DOT11_WPA2_IE_HEADER; + +#if (defined(WIFI_HAPD) && !defined(HAPD_DRV_PSK_WPS)) || (defined(RTK_NL80211) && !defined(NON_NL80211_AP) && !defined(NON_NL80211_WPAS)) +// group key info +typedef struct _wpa_global_info { + OCTET_STRING AuthInfoElement; + unsigned char AuthInfoBuf[INFO_ELEMENT_SIZE]; + unsigned char MulticastCipher; + int NumOfUnicastCipher; + unsigned char UnicastCipher[MAX_UNICAST_CIPHER]; +#ifdef RTL_WPA2 + int NumOfUnicastCipherWPA2; + unsigned char UnicastCipherWPA2[MAX_UNICAST_CIPHER]; +#endif +#ifdef CONFIG_IEEE80211W_CLI + unsigned short rsnie_cap; +#endif +} WPA_GLOBAL_INFO; + +#else + +// group key info +typedef struct _wpa_global_info { + OCTET32_INTEGER Counter; + unsigned char PSK[A_SHA_DIGEST_LEN*2]; + unsigned char PSKGuest[A_SHA_DIGEST_LEN*2]; + int GTKAuthenticator; + int GKeyDoneStations; + int GInitAKeys; + int GUpdateStationKeys; + int GkeyReady; + OCTET_STRING AuthInfoElement; + unsigned char AuthInfoBuf[INFO_ELEMENT_SIZE]; + unsigned char MulticastCipher; + int NumOfUnicastCipher; + unsigned char UnicastCipher[MAX_UNICAST_CIPHER]; +#ifdef RTL_WPA2 + int NumOfUnicastCipherWPA2; + unsigned char UnicastCipherWPA2[MAX_UNICAST_CIPHER]; +#endif + OCTET_STRING GNonce; + unsigned char GNonceBuf[KEY_NONCE_LEN]; + unsigned char GTK[NumGroupKey][GTK_LEN]; + unsigned char GMK[GMK_LEN]; + int GN; + int GM; +#ifdef CONFIG_IEEE80211W +#ifdef CONFIG_IEEE80211W_CLI + unsigned short rsnie_cap; +#endif + unsigned char IGTK[2][IGTK_LEN]; + int GN_igtk; + int GM_igtk; + union PN48 IGTK_PN; +#endif + int GRekeyCounts; + int GResetCounter; + + int IntegrityFailed; + int GTKRekey; + int GKeyFailure; + struct timer_list GKRekeyTimer; +} WPA_GLOBAL_INFO; +#endif + +#if (defined(WIFI_HAPD) && !defined(HAPD_DRV_PSK_WPS)) || (defined(RTK_NL80211) && !defined(NON_NL80211_AP) && !defined(NON_NL80211_WPAS)) +// wpa sta info +typedef struct _wpa_sta_info { + int state; + int RSNEnabled; // bit0-WPA, bit1-WPA2 + unsigned char UnicastCipher; + struct rtl8192cd_priv *priv; +#ifdef CONFIG_IEEE80211W + BOOLEAN mgmt_frame_prot; +#endif +} WPA_STA_INFO; + +#else + +// wpa sta info +typedef struct _wpa_sta_info { + int state; + int gstate; + int RSNEnabled; // bit0-WPA, bit1-WPA2 + int PMKCached; + int PInitAKeys; + unsigned char UnicastCipher; + unsigned char NumOfRxTSC; + unsigned char AuthKeyMethod; +#ifdef CONFIG_IEEE80211W + enum mfp_options ieee80211w; /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ + unsigned int assoc_sa_query_max_timeout; /* dot11AssociationSAQueryRetryTimeout (in TUs) */ + int assoc_sa_query_retry_timeout; +#endif /* CONFIG_IEEE80211W */ + int isSuppSupportPreAuthentication; + int isSuppSupportPairwiseAsDefaultKey; + LARGE_INTEGER CurrentReplayCounter; + LARGE_INTEGER ReplayCounterStarted; // david+1-12-2007 + OCTET_STRING ANonce; + OCTET_STRING SNonce; + unsigned char AnonceBuf[KEY_NONCE_LEN]; + unsigned char SnonceBuf[KEY_NONCE_LEN]; + unsigned char PMK[PMK_LEN]; + unsigned char PTK[PTK_LEN_TKIP]; + OCTET_STRING EAPOLMsgRecvd; + OCTET_STRING EAPOLMsgSend; + OCTET_STRING EapolKeyMsgRecvd; + OCTET_STRING EapolKeyMsgSend; + unsigned char eapSendBuf[MAX_EAPOLMSG_LEN]; + unsigned char eapRecvdBuf[MAX_EAPOLMSG_LEN]; + struct timer_list resendTimer; + struct rtl8192cd_priv *priv; + int resendCnt; + int isGuest; + int clientHndshkProcessing; + int clientHndshkDone; + int clientGkeyUpdate; + LARGE_INTEGER clientMICReportReplayCounter; +#ifdef CONFIG_IEEE80211W + BOOLEAN mgmt_frame_prot; +#endif +} WPA_STA_INFO; +#endif + +#if defined(PACK_STRUCTURE) || defined(__ECOS) +#pragma pack(1) +#endif + +__PACK typedef struct _LIB1X_EAPOL_KEY +{ + unsigned char key_desc_ver; + unsigned char key_info[2]; + unsigned char key_len[2]; + unsigned char key_replay_counter[KEY_RC_LEN]; + unsigned char key_nounce[KEY_NONCE_LEN]; + unsigned char key_iv[KEY_IV_LEN]; + unsigned char key_rsc[KEY_RSC_LEN]; + unsigned char key_id[KEY_ID_LEN]; + unsigned char key_mic[KEY_MIC_LEN]; + unsigned char key_data_len[KEY_MATERIAL_LEN]; + unsigned char *key_data; +}__WLAN_ATTRIB_PACK__ lib1x_eapol_key; + + +__PACK struct lib1x_eapol +{ + unsigned char protocol_version; + unsigned char packet_type; // This makes it odd in number ! + unsigned short packet_body_length; +}__WLAN_ATTRIB_PACK__; + +#if defined(PACK_STRUCTURE) || defined(__ECOS) +#pragma pack() +#endif + +#define SetSubStr(f,a,l) memcpy(f.Octet+l,a.Octet,a.Length) +#define GetKeyInfo0(f, mask) ((f.Octet[KeyInfoPos + 1] & mask) ? 1 :0) +#define SetKeyInfo0(f,mask,b) (f.Octet[KeyInfoPos + 1] = (f.Octet[KeyInfoPos + 1] & ~mask) | ( b?mask:0x0) ) +#define GetKeyInfo1(f, mask) ((f.Octet[KeyInfoPos] & mask) ? 1 :0) +#define SetKeyInfo1(f,mask,b) (f.Octet[KeyInfoPos] = (f.Octet[KeyInfoPos] & ~mask) | ( b?mask:0x0) ) + +// EAPOLKey +#define Message_DescType(f) (f.Octet[DescTypePos]) +#define Message_setDescType(f, type) (f.Octet[DescTypePos] = type) +// Key Information Filed +#define Message_KeyDescVer(f) (f.Octet[KeyInfoPos+1] & 0x07)//(f.Octet[KeyInfoPos+1] & 0x01) | (f.Octet[KeyInfoPos+1] & 0x02) <<1 | (f.Octet[KeyInfoPos+1] & 0x04) <<2 +#define Message_setKeyDescVer(f, v) (f.Octet[KeyInfoPos+1] &= 0xf8) , f.Octet[KeyInfoPos+1] |= (v & 0x07)//(f.Octet[KeyInfoPos+1] |= ((v&0x01)<<7 | (v&0x02)<<6 | (v&0x04)<<5) ) +#define Message_KeyType(f) GetKeyInfo0(f,0x08) +#define Message_setKeyType(f, b) SetKeyInfo0(f,0x08,b) +#define Message_KeyIndex(f) ((f.Octet[KeyInfoPos+1] & 0x30) >> 4) & 0x03//(f.Octet[KeyInfoPos+1] & 0x20) | (f.Octet[KeyInfoPos+1] & 0x10) <<1 +#define Message_setKeyIndex(f, v) (f.Octet[KeyInfoPos+1] &= 0xcf), f.Octet[KeyInfoPos+1] |= ((v<<4) & 0x07)//(f.Octet[KeyInfoPos+1] |= ( (v&0x01)<<5 | (v&0x02)<<4) ) +#define Message_Install(f) GetKeyInfo0(f,0x40) +#define Message_setInstall(f, b) SetKeyInfo0(f,0x40,b) +#define Message_KeyAck(f) GetKeyInfo0(f,0x80) +#define Message_setKeyAck(f, b) SetKeyInfo0(f,0x80,b) + +#define Message_KeyMIC(f) GetKeyInfo1(f,0x01) +#define Message_setKeyMIC(f, b) SetKeyInfo1(f,0x01,b) +#define Message_Secure(f) GetKeyInfo1(f,0x02) +#define Message_setSecure(f, b) SetKeyInfo1(f,0x02,b) +#define Message_Error(f) GetKeyInfo1(f,0x04) +#define Message_setError(f, b) SetKeyInfo1(f,0x04,b) +#define Message_Request(f) GetKeyInfo1(f,0x08) +#define Message_setRequest(f, b) SetKeyInfo1(f,0x08,b) +#define Message_Reserved(f) (f.Octet[KeyInfoPos] & 0xf0) +#define Message_setReserved(f, v) (f.Octet[KeyInfoPos] |= (v<<4&0xff)) +#define Message_KeyLength(f) ((unsigned short)(f.Octet[KeyLenPos] <<8) + (unsigned short)(f.Octet[KeyLenPos+1])) +#define Message_setKeyLength(f, v) (f.Octet[KeyLenPos] = (v&0xff00) >>8 , f.Octet[KeyLenPos+1] = (v&0x00ff)) + +#define Message_KeyNonce(f) SubStr(f,KeyNoncePos,KEY_NONCE_LEN) +#define Message_setKeyNonce(f, v) SetSubStr(f, v, KeyNoncePos) +#define Message_EqualKeyNonce(f1, f2) (memcmp(f1.Octet + KeyNoncePos, f2.Octet, KEY_NONCE_LEN)? 0:1) +#define Message_KeyIV(f) Substr(f, KeyIVPos, KEY_IV_LEN) +#define Message_setKeyIV(f, v) SetSubStr(f, v, KeyIVPos) +#define Message_KeyRSC(f) Substr(f, KeyRSCPos, KEY_RSC_LEN) +#define Message_setKeyRSC(f, v) SetSubStr(f, v, KeyRSCPos) +#define Message_KeyID(f) Substr(f, KeyIDPos, KEY_ID_LEN) +#define Message_setKeyID(f, v) SetSubStr(f, v, KeyIDPos) +#define Message_MIC(f) SubStr(f, KeyMICPos, KEY_MIC_LEN) +#define Message_setMIC(f, v) SetSubStr(f, v, KeyMICPos) +#define Message_clearMIC(f) memset(f.Octet+KeyMICPos, 0, KEY_MIC_LEN) +#define Message_KeyDataLength(f) ((unsigned short)(f.Octet[KeyDataLenPos] <<8) + (unsigned short)(f.Octet[KeyDataLenPos+1])) +#define Message_setKeyDataLength(f, v) (f.Octet[KeyDataLenPos] = (v&0xff00) >>8 , f.Octet[KeyDataLenPos+1] = (v&0x00ff)) +#define Message_KeyData(f, l) SubStr(f, KeyDataPos, l) +#define Message_setKeyData(f, v) SetSubStr(f, v, KeyDataPos); +#define Message_EqualRSNIE(f1 , f2, l) (memcmp(f1.Octet, f2.Octet, l) ? 0:1) +#define Message_ReturnKeyDataLength(f) f.Length - (ETHER_HDRLEN + LIB1X_EAPOL_HDRLEN + EAPOLMSG_HDRLEN) + +#define Message_CopyReplayCounter(f1, f2) memcpy(f1.Octet + ReplayCounterPos, f2.Octet + ReplayCounterPos, KEY_RC_LEN) +#define Message_DefaultReplayCounter(li) ((li.field.HighPart == 0xffffffff) && (li.field.LowPart == 0xffffffff) ) ?1:0 +#ifdef CONFIG_IEEE80211W_CLI +#define Message_setSha256AKM(f, v) SetSubStr(f, v, KeyAKMPos) +#endif + +#if defined(CONFIG_RTL8186_KB_N) +extern int authRes;//0: success; 1: fail +#endif + +struct KDE { + unsigned char type; + unsigned char length; + unsigned char oui[3]; + unsigned char data_type; +}; + +enum KDE_DATA_TYPE { + GTK_KDE = 1, + MAV_ADDRESS_KDE = 3, + PMKID_KDE = 4, + SMK_KDE = 5, + NONCE_KDE = 6, + LIFETIME_KDE = 7, + ERROR_KDE = 8, + IGTK_KDE = 9, +}; + +#endif // _8192CD_PSK_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_psk_hapd.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_psk_hapd.c new file mode 100755 index 000000000..ec1686975 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_psk_hapd.c @@ -0,0 +1,1513 @@ +/* + * WPA PSK handling routines + * + * $Id: 8192cd_psk.c,v 1.6 2010/03/10 03:24:40 keith_huang Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_PSK_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#if (defined(WIFI_HAPD) && !defined(HAPD_DRV_PSK_WPS)) || defined(RTK_NL80211) + +#include "./8192cd.h" +#include "./wifi.h" +#include "./8192cd_util.h" +#include "./8192cd_headers.h" +#include "./8192cd_security.h" +#include "./ieee802_mib.h" +#include "./8192cd_debug.h" +#include "./8192cd_psk.h" +#include "./1x_rc4.h" + +#ifndef __KERNEL__ +#include "./sys-support.h" +#endif + +//#define DEBUG_PSK + +#define ETHER_ADDRLEN 6 +#define PMK_EXPANSION_CONST "Pairwise key expansion" +#define PMK_EXPANSION_CONST_SIZE 22 +#ifdef RTL_WPA2 +#define PMKID_NAME_CONST "PMK Name" +#define PMKID_NAME_CONST_SIZE 8 +#endif /* RTL_WPA2 */ +#define GMK_EXPANSION_CONST "Group key expansion" +#define GMK_EXPANSION_CONST_SIZE 19 +#define RANDOM_EXPANSION_CONST "Init Counter" +#define RANDOM_EXPANSION_CONST_SIZE 12 +#define PTK_LEN_CCMP 48 + +/* + 2008-12-16, For Corega CG-WLCB54GL 54Mbps NIC interoperability issue. + The behavior of this NIC when it connect to the other AP with WPA/TKIP is: + AP <----------------------> STA + .................... + ------------> Assoc Rsp (ok) + ------------> EAPOL-key (4-way msg 1) + <------------ unknown TKIP encryption data + ------------> EAPOL-key (4-way msg 1) + <------------ unknown TKIP encryption data + ..................... + <------------ disassoc (code=8, STA is leaving) when the 5 seconds timer timeout counting from Assoc_Rsp is got. + .................... + ------------> Assoc Rsp (ok) + <-----------> EAPOL-key (4-way handshake success) + + If MAX_RESEND_NUM=3, our AP will send disassoc (code=15, 4-way timeout) to STA before STA sending disassoc to AP. + And this NIC will always can not connect to our AP. + set MAX_RESEND_NUM=5 can fix this issue. + */ +//#define MAX_RESEND_NUM 3 +#define MAX_RESEND_NUM 5 + +#define RESEND_TIME RTL_SECONDS_TO_JIFFIES(1)// in 10ms + +#define LargeIntegerOverflow(x) (x.field.HighPart == 0xffffffff) && \ + (x.field.LowPart == 0xffffffff) +#define LargeIntegerZero(x) memset(&x.charData, 0, 8); + +#define Octet16IntegerOverflow(x) LargeIntegerOverflow(x.field.HighPart) && \ + LargeIntegerOverflow(x.field.LowPart) +#define Octet16IntegerZero(x) memset(&x.charData, 0, 16); + +#if defined(CONFIG_RTL8186_KB_N) +int authRes = 0;//0: success; 1: fail +#endif + +extern void hmac_sha( + unsigned char* k, /* secret key */ + int lk, /* length of the key in bytes */ + unsigned char* d, /* data */ + int ld, /* length of data in bytes */ + unsigned char* out, /* output buffer, at least "t" bytes */ + int t + ); + +extern void hmac_sha1(unsigned char *text, int text_len, unsigned char *key, + int key_len, unsigned char *digest); + +extern void hmac_md5(unsigned char *text, int text_len, unsigned char *key, + int key_len, void * digest); + +#ifdef RTL_WPA2 +extern void AES_WRAP(unsigned char *plain, int plain_len, + unsigned char *iv, int iv_len, + unsigned char *kek, int kek_len, + unsigned char *cipher, unsigned short *cipher_len); +#endif + + +#ifdef DEBUG_PSK +static char *ID2STR(int id) +{ + switch(id) { + case DOT11_EVENT_ASSOCIATION_IND: + return("DOT11_EVENT_ASSOCIATION_IND"); + case DOT11_EVENT_REASSOCIATION_IND: + return ("DOT11_EVENT_REASSOCIATION_IND"); + + case DOT11_EVENT_DISASSOCIATION_IND: + return ("DOT11_EVENT_DISASSOCIATION_IND"); + + case DOT11_EVENT_EAP_PACKET: + return ("DOT11_EVENT_EAP_PACKET"); + + case DOT11_EVENT_MIC_FAILURE: + return ("DOT11_EVENT_MIC_FAILURE"); + default: + return ("Not support event"); + + } +} + +#endif // DEBUG_PSK + +static OCTET_STRING SubStr(OCTET_STRING f, unsigned short s, unsigned short l) +{ + OCTET_STRING res; + + res.Length = l; + res.Octet = f.Octet+s; + return res; +} + +static void i_P_SHA1( + unsigned char* key, // pointer to authentication key + int key_len, // length of authentication key + unsigned char* text, // pointer to data stream + int text_len, // length of data stream + unsigned char* digest, // caller digest to be filled in + int digest_len // in byte + ) +{ + int i; + int offset=0; + int step=20; + int IterationNum=(digest_len+step-1)/step; + + for(i=0;i>24) & 0xff); + digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff); + digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff); + digest[ssidlength+3] = (unsigned char)(count & 0xff); + hmac_sha1(digest, ssidlength + 4, + (unsigned char*) password, (int)strlen(password), + digest1); + + /* + hmac_sha1((unsigned char*) password, passwordlength, + digest, ssidlength+4, digest1); + */ + + /* output = U1 */ + memcpy(output, digest1, A_SHA_DIGEST_LEN); + + for (i = 1; i < iterations; i++) { + /* Un = PRF(P, Un-1) */ + hmac_sha1(digest1, A_SHA_DIGEST_LEN, (unsigned char*) password, + (int)strlen(password), digest); + //hmac_sha1((unsigned char*) password, passwordlength,digest1, A_SHA_DIGEST_LEN, digest); + memcpy(digest1, digest, A_SHA_DIGEST_LEN); + + /* output = output xor Un */ + for (j = 0; j < A_SHA_DIGEST_LEN; j++) { + output[j] ^= digest[j]; + } + } +} + +/* + * password - ascii string up to 63 characters in length + * ssid - octet string up to 32 octets + * ssidlength - length of ssid in octets + * output must be 40 octets in length and outputs 256 bits of key + */ +static int PasswordHash ( + char *password, + unsigned char *ssid, + short ssidlength, + unsigned char *output) +{ + int passwordlength = strlen(password); +// int ssidlength = strlen(ssid); + + if ((passwordlength > 63) || (ssidlength > 32)) + return 0; + + F(password, passwordlength, ssid, ssidlength, 4096, 1, output); + F(password, passwordlength, ssid, ssidlength, 4096, 2, &output[A_SHA_DIGEST_LEN]); + return 1; +} + +void nl80211_ConstructIE(struct rtl8192cd_priv *priv, unsigned char *pucOut, int *usOutLen) +{ + DOT11_RSN_IE_HEADER dot11RSNIEHeader = { 0 }; + DOT11_RSN_IE_SUITE dot11RSNGroupSuite; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNPairwiseSuite = NULL; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNAuthSuite = NULL; +#ifdef CONFIG_IEEE80211W + DOT11_RSN_IE_SUITE dot11RSNIGTKSuite; +#endif + unsigned short usSuitCount; + unsigned long ulIELength = 0; + unsigned long ulIndex = 0; + unsigned long ulPairwiseLength = 0; + unsigned long ulAuthLength = 0; + unsigned char *pucBlob; + DOT11_RSN_IE_COUNT_SUITE countSuite, authCountSuite; +#ifdef RTL_WPA2 + DOT11_RSN_CAPABILITY dot11RSNCapability = { 0 }; + unsigned long uCipherAlgo = 0; + int bCipherAlgoEnabled = FALSE; + unsigned long uAuthAlgo = 0; + int bAuthAlgoEnabled = FALSE; + unsigned long ulRSNCapabilityLength = 0; +#endif + + *usOutLen = 0; + if ( priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) { + // + // Construct Information Header + // + dot11RSNIEHeader.ElementID = RSN_ELEMENT_ID; + dot11RSNIEHeader.OUI[0] = 0x00; + dot11RSNIEHeader.OUI[1] = 0x50; + dot11RSNIEHeader.OUI[2] = 0xf2; + dot11RSNIEHeader.OUI[3] = 0x01; + dot11RSNIEHeader.Version = cpu_to_le16(RSN_VER1); + ulIELength += sizeof(DOT11_RSN_IE_HEADER); + + // Construct Cipher Suite: + // - Multicast Suite: + memset(&dot11RSNGroupSuite, 0, sizeof dot11RSNGroupSuite); + dot11RSNGroupSuite.OUI[0] = 0x00; + dot11RSNGroupSuite.OUI[1] = 0x50; + dot11RSNGroupSuite.OUI[2] = 0xF2; + dot11RSNGroupSuite.Type = priv->wpa_global_info->MulticastCipher; + ulIELength += sizeof(DOT11_RSN_IE_SUITE); + + // - UnicastSuite + pDot11RSNPairwiseSuite = &countSuite; + memset(pDot11RSNPairwiseSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + +#ifdef RTK_NL80211 + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipher; ulIndex++) + { + int i = ulIndexwpa_global_info->NumOfUnicastCipher - ulIndex - 1; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipher[i]; + usSuitCount++; + } +#else + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipher; ulIndex++) + { + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipher[ulIndex]; + usSuitCount++; + } +#endif + pDot11RSNPairwiseSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulPairwiseLength = sizeof(pDot11RSNPairwiseSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulPairwiseLength; + + // + // Construction of Auth Algo List + // + pDot11RSNAuthSuite = &authCountSuite; + memset(pDot11RSNAuthSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x50; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xF2; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK; + usSuitCount++; + + pDot11RSNAuthSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulAuthLength = sizeof(pDot11RSNAuthSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulAuthLength; + + //--------------------------------------------------------------------------------------------- + // Do not encapsulate capability field to solve TI WPA issue + //--------------------------------------------------------------------------------------------- + /* + dot11RSNCapability.field.PreAuthentication = 0;//auth->RSNVariable.isSupportPreAuthentication + dot11RSNCapability.field.PairwiseAsDefaultKey = auth->RSNVariable.isSupportPairwiseAsDefaultKey; + switch(auth->RSNVariable.NumOfRxTSC) + { + case 1: + dot11RSNCapability.field.NumOfReplayCounter = 0; + break; + case 2: + dot11RSNCapability.field.NumOfReplayCounter = 1; + break; + case 4: + dot11RSNCapability.field.NumOfReplayCounter = 2; + break; + case 16: + dot11RSNCapability.field.NumOfReplayCounter = 3; + break; + default: + dot11RSNCapability.field.NumOfReplayCounter = 0; + } + + ulRSNCapabilityLength = sizeof(DOT11_RSN_CAPABILITY); + ulIELength += ulRSNCapabilityLength; + */ + + pucBlob = pucOut; + pucBlob += sizeof(DOT11_RSN_IE_HEADER); + memcpy(pucBlob, &dot11RSNGroupSuite, sizeof(DOT11_RSN_IE_SUITE)); + pucBlob += sizeof(DOT11_RSN_IE_SUITE); + memcpy(pucBlob, pDot11RSNPairwiseSuite, ulPairwiseLength); + pucBlob += ulPairwiseLength; + memcpy(pucBlob, pDot11RSNAuthSuite, ulAuthLength); + pucBlob += ulAuthLength; + + *usOutLen = (int)ulIELength; + pucBlob = pucOut; + dot11RSNIEHeader.Length = (unsigned char)ulIELength - 2; //This -2 is to minus elementID and Length in OUI header + memcpy(pucBlob, &dot11RSNIEHeader, sizeof(DOT11_RSN_IE_HEADER)); + } + +#ifdef RTL_WPA2 + if ( priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2 ) { + DOT11_WPA2_IE_HEADER dot11WPA2IEHeader = { 0 }; + ulIELength = 0; + ulIndex = 0; + ulPairwiseLength = 0; + uCipherAlgo = 0; + bCipherAlgoEnabled = FALSE; + ulAuthLength = 0; + uAuthAlgo = 0; + bAuthAlgoEnabled = FALSE; + ulRSNCapabilityLength = 0; + + // + // Construct Information Header + // + dot11WPA2IEHeader.ElementID = WPA2_ELEMENT_ID; + dot11WPA2IEHeader.Version = cpu_to_le16(RSN_VER1); + ulIELength += sizeof(DOT11_WPA2_IE_HEADER); + + // Construct Cipher Suite: + // - Multicast Suite: + // + memset(&dot11RSNGroupSuite, 0, sizeof(dot11RSNGroupSuite)); + dot11RSNGroupSuite.OUI[0] = 0x00; + dot11RSNGroupSuite.OUI[1] = 0x0F; + dot11RSNGroupSuite.OUI[2] = 0xAC; + dot11RSNGroupSuite.Type = priv->wpa_global_info->MulticastCipher;; + ulIELength += sizeof(DOT11_RSN_IE_SUITE); + + // - UnicastSuite + pDot11RSNPairwiseSuite = &countSuite; + memset(pDot11RSNPairwiseSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; +#ifdef RTK_NL80211 + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipherWPA2; ulIndex++) + { + int i = priv->wpa_global_info->NumOfUnicastCipherWPA2 - ulIndex - 1; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipherWPA2[i]; + usSuitCount++; + } +#else + for (ulIndex=0; ulIndexwpa_global_info->NumOfUnicastCipherWPA2; ulIndex++) + { + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + pDot11RSNPairwiseSuite->dot11RSNIESuite[usSuitCount].Type = priv->wpa_global_info->UnicastCipherWPA2[ulIndex]; + usSuitCount++; + } +#endif + pDot11RSNPairwiseSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulPairwiseLength = sizeof(pDot11RSNPairwiseSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulPairwiseLength; + + // + // Construction of Auth Algo List + // + pDot11RSNAuthSuite = &authCountSuite; + memset(pDot11RSNAuthSuite, 0, sizeof(DOT11_RSN_IE_COUNT_SUITE)); + usSuitCount = 0; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + if (OPMODE & WIFI_AP_STATE) + { +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK_SHA256; + else +#endif + { + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK; + } + usSuitCount++; + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_OPTIONAL + && priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 == 1) { + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[0] = 0x00; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[1] = 0x0F; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].OUI[2] = 0xAC; + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK_SHA256; + usSuitCount++; + } +#endif + } else { +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != 0 + && priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 == 1) + { + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK_SHA256; + } + else +#endif + { + pDot11RSNAuthSuite->dot11RSNIESuite[usSuitCount].Type = DOT11_AuthKeyType_PSK; + } + usSuitCount++; + } + + pDot11RSNAuthSuite->SuiteCount = cpu_to_le16(usSuitCount); + ulAuthLength = sizeof(pDot11RSNAuthSuite->SuiteCount) + usSuitCount*sizeof(DOT11_RSN_IE_SUITE); + ulIELength += ulAuthLength; + + //--------------------------------------------------------------------------------------------- + // Do not encapsulate capability field to solve TI WPA issue + //--------------------------------------------------------------------------------------------- + +//#ifdef RTL_WPA2 +#if 1 + dot11RSNCapability.field.PreAuthentication = 0; +#else + dot11RSNCapability.field.PairwiseAsDefaultKey = auth->RSNVariable.isSupportPairwiseAsDefaultKey; + switch(auth->RSNVariable.NumOfRxTSC) + { + case 1: + dot11RSNCapability.field.NumOfReplayCounter = 0; + break; + case 2: + dot11RSNCapability.field.NumOfReplayCounter = 1; + break; + case 4: + dot11RSNCapability.field.NumOfReplayCounter = 2; + break; + case 16: + dot11RSNCapability.field.NumOfReplayCounter = 3; + break; + default: + dot11RSNCapability.field.NumOfReplayCounter = 0; + } +#endif + +#if (defined(WIFI_HAPD) & defined(WIFI_WMM)) || (defined(RTK_NL80211) & defined(WIFI_WMM)) //eric-wds + if(QOS_ENABLE){ + /* 4 PTKSA replay counters when using WMM consistent with hostapd code*/ + dot11RSNCapability.field.PtksaReplayCounter = 3; + } +#endif + +#ifdef CONFIG_IEEE80211W + //Protected Managemenet Protection Capability (PMF) + //printk("ConstructIE, dot11IEEE80211W=%d\n", priv->pmib->dot1180211AuthEntry.dot11IEEE80211W); + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION) { + dot11RSNCapability.field.MFPC = 0; + dot11RSNCapability.field.MFPR = 0; + } else if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_OPTIONAL) + dot11RSNCapability.field.MFPC = 1; // MFPC + else if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + dot11RSNCapability.field.MFPR = 1; // MFPR + dot11RSNCapability.field.MFPC = 1; // MFPC + } +#endif + + ulRSNCapabilityLength = sizeof(DOT11_RSN_CAPABILITY); + ulIELength += ulRSNCapabilityLength; + +#ifdef CONFIG_IEEE80211W + // Construct Cipher Suite: + // - IGTK Suite: + // + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W /*&& priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 == TRUE*/) { + memset(&dot11RSNIGTKSuite, 0, sizeof(dot11RSNIGTKSuite)); + dot11RSNIGTKSuite.OUI[0] = 0x00; + dot11RSNIGTKSuite.OUI[1] = 0x0F; + dot11RSNIGTKSuite.OUI[2] = 0xAC; + + dot11RSNIGTKSuite.Type = DOT11_ENC_BIP; + ulIELength += sizeof(dot11RSNIGTKSuite) + 2; + } +#endif // CONFIG_IEEE80211W + + + pucBlob = pucOut + *usOutLen; + pucBlob += sizeof(DOT11_WPA2_IE_HEADER); + memcpy(pucBlob, &dot11RSNGroupSuite, sizeof(DOT11_RSN_IE_SUITE)); + pucBlob += sizeof(DOT11_RSN_IE_SUITE); + memcpy(pucBlob, pDot11RSNPairwiseSuite, ulPairwiseLength); + pucBlob += ulPairwiseLength; + memcpy(pucBlob, pDot11RSNAuthSuite, ulAuthLength); + pucBlob += ulAuthLength; + memcpy(pucBlob, &dot11RSNCapability, ulRSNCapabilityLength); + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W != NO_MGMT_FRAME_PROTECTION) { + pucBlob += ulRSNCapabilityLength + 2; // add PMKID Count (2bytes) + memcpy(pucBlob, &dot11RSNIGTKSuite, sizeof(DOT11_RSN_IE_SUITE)); + } +#endif // CONFIG_IEEE80211W + + pucBlob = pucOut + *usOutLen; + dot11WPA2IEHeader.Length = (unsigned char)ulIELength - 2; //This -2 is to minus elementID and Length in OUI header + memcpy(pucBlob, &dot11WPA2IEHeader, sizeof(DOT11_WPA2_IE_HEADER)); + *usOutLen = *usOutLen + (int)ulIELength; + } +#endif // RTL_WPA2 + +} + +static int MIN(unsigned char *ucStr1, unsigned char *ucStr2, unsigned long ulLen) +{ + int i; + for (i=0 ; i (unsigned char)ucStr2[i]) + return 1; + else if(i == ulLen - 1) + return 0; + else + continue; + } + return 0; +} + +static int parseIE(struct rtl8192cd_priv *priv, WPA_STA_INFO *pInfo, + unsigned char *pucIE, unsigned long ulIELength) +{ + unsigned short usSuitCount; + DOT11_RSN_IE_HEADER *pDot11RSNIEHeader; + DOT11_RSN_IE_SUITE *pDot11RSNIESuite; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite; + + DOT11_RSN_CAPABILITY * pDot11RSNCapability = NULL; + DEBUG_TRACE; + + if (ulIELength < sizeof(DOT11_RSN_IE_HEADER)) { + DEBUG_WARN("parseIE err 1!\n"); + return ERROR_INVALID_RSNIE; + } + + pDot11RSNIEHeader = (DOT11_RSN_IE_HEADER *)pucIE; + if (le16_to_cpu(pDot11RSNIEHeader->Version) != RSN_VER1) { + DEBUG_WARN("parseIE err 2!\n"); + return ERROR_UNSUPPORTED_RSNEVERSION; + } + + if (pDot11RSNIEHeader->ElementID != RSN_ELEMENT_ID || + pDot11RSNIEHeader->Length != ulIELength -2 || + pDot11RSNIEHeader->OUI[0] != 0x00 || pDot11RSNIEHeader->OUI[1] != 0x50 || + pDot11RSNIEHeader->OUI[2] != 0xf2 || pDot11RSNIEHeader->OUI[3] != 0x01 ) { + DEBUG_WARN("parseIE err 3!\n"); + return ERROR_INVALID_RSNIE; + } + + pInfo->RSNEnabled= PSK_WPA; // wpa + ulIELength -= sizeof(DOT11_RSN_IE_HEADER); + pucIE += sizeof(DOT11_RSN_IE_HEADER); + + //---------------------------------------------------------------------------------- + // Multicast Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIESuite = (DOT11_RSN_IE_SUITE *)pucIE; + if (pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x50 || + pDot11RSNIESuite->OUI[2] != 0xF2) { + DEBUG_WARN("parseIE err 4!\n"); + return ERROR_INVALID_RSNIE; + } + + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) { + DEBUG_WARN("parseIE err 5!\n"); + return ERROR_INVALID_MULTICASTCIPHER; + } + + if (pDot11RSNIESuite->Type != priv->wpa_global_info->MulticastCipher) { + DEBUG_WARN("parseIE err 6!\n"); + return ERROR_INVALID_MULTICASTCIPHER; + } + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (pDot11RSNIESuite->Type != DOT11_ENC_CCMP) { + PMFDEBUG("Invalid WPA group cipher %d\n", pDot11RSNIESuite->Type); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } +#endif + + ulIELength -= sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(DOT11_RSN_IE_SUITE); + + //---------------------------------------------------------------------------------- + // Pairwise Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x50 || + pDot11RSNIESuite->OUI[2] != 0xF2) { + DEBUG_WARN("parseIE err 7!\n"); + return ERROR_INVALID_RSNIE; + } + + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) { + DEBUG_WARN("parseIE err 8!\n"); + return ERROR_INVALID_UNICASTCIPHER; + } + + if ((pDot11RSNIESuite->Type < DOT11_ENC_WEP40) + || (!(BIT(pDot11RSNIESuite->Type - 1) & priv->pmib->dot1180211AuthEntry.dot11WPACipher))) { + DEBUG_WARN("parseIE err 9!\n"); + return ERROR_INVALID_UNICASTCIPHER; + } + + pInfo->UnicastCipher = pDot11RSNIESuite->Type; + +#ifdef DEBUG_PSK + printk("PSK: ParseIE -> WPA UnicastCipher=%x\n", pInfo->UnicastCipher); +#endif + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (pInfo->UnicastCipher == DOT11_ENC_TKIP) { + PMFDEBUG("Management frame protection cannot use TKIP\n"); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } +#endif + + ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + + //---------------------------------------------------------------------------------- + // Authentication suite + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x50 || + pDot11RSNIESuite->OUI[2] != 0xF2 ) { + DEBUG_WARN("parseIE err 10!\n"); + return ERROR_INVALID_RSNIE; + } + + if( pDot11RSNIESuite->Type < DOT11_AuthKeyType_RSN || + pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK) { + DEBUG_WARN("parseIE err 11!\n"); + return ERROR_INVALID_AUTHKEYMANAGE; + } + + if(pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK) { + DEBUG_WARN("parseIE err 12!\n"); + return ERROR_INVALID_AUTHKEYMANAGE; + } + + //pInfo->AuthKeyMethod = pDot11RSNIESuite->Type; + ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + + // RSN Capability + if (ulIELength < sizeof(DOT11_RSN_CAPABILITY)) + return 0; + +//#ifndef RTL_WPA2 +#if 0 + //---------------------------------------------------------------------------------- + // Capability field + //---------------------------------------------------------------------------------- + pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE; + pInfo->isSuppSupportPreAuthentication = pDot11RSNCapability->field.PreAuthentication; + pInfo->isSuppSupportPairwiseAsDefaultKey = pDot11RSNCapability->field.PairwiseAsDefaultKey; + + switch (pDot11RSNCapability->field.NumOfReplayCounter) { + case 0: + pInfo->NumOfRxTSC = 1; + break; + case 1: + pInfo->NumOfRxTSC = 2; + break; + case 2: + pInfo->NumOfRxTSC = 4; + break; + case 3: + pInfo->NumOfRxTSC = 16; + break; + default: + pInfo->NumOfRxTSC = 1; + } +#endif /* RTL_WPA2 */ + +#ifdef CONFIG_IEEE80211W + pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE; + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (!pDot11RSNCapability->field.MFPC) { + PMFDEBUG("Management frame protection Required, but client did not enable it\n"); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } + + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION || + !(pDot11RSNCapability->field.MFPC)) + pInfo->mgmt_frame_prot = 0; + else + pInfo->mgmt_frame_prot = 1; + + PMFDEBUG("mgmt_frame_prot=%d\n", pInfo->mgmt_frame_prot); + +#endif // CONFIG_IEEE80211W + + return 0; +} + +#ifdef RTL_WPA2 +static int parseIEWPA2(struct rtl8192cd_priv *priv, WPA_STA_INFO *pInfo, + unsigned char *pucIE, unsigned long ulIELength) +{ + unsigned short usSuitCount; + DOT11_WPA2_IE_HEADER *pDot11WPA2IEHeader = NULL; + DOT11_RSN_IE_SUITE *pDot11RSNIESuite = NULL; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite = NULL; + DOT11_RSN_CAPABILITY *pDot11RSNCapability = NULL; + + DEBUG_TRACE; + + if (ulIELength < sizeof(DOT11_WPA2_IE_HEADER)) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 1!\n"); + return ERROR_INVALID_RSNIE; + } + + pDot11WPA2IEHeader = (DOT11_WPA2_IE_HEADER *)pucIE; + if (le16_to_cpu(pDot11WPA2IEHeader->Version) != RSN_VER1) { + DEBUG_WARN("ERROR_UNSUPPORTED_RSNEVERSION, err 2!\n"); + return ERROR_UNSUPPORTED_RSNEVERSION; + } + + if (pDot11WPA2IEHeader->ElementID != WPA2_ELEMENT_ID || + pDot11WPA2IEHeader->Length != ulIELength -2 ) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 3!\n"); + return ERROR_INVALID_RSNIE; + } + + pInfo->RSNEnabled= PSK_WPA2; + //pInfo->PMKCached= FALSE; + + ulIELength -= sizeof(DOT11_WPA2_IE_HEADER); + pucIE += sizeof(DOT11_WPA2_IE_HEADER); + + //---------------------------------------------------------------------------------- + // Multicast Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIESuite = (DOT11_RSN_IE_SUITE *)pucIE; + if (pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 4!\n"); + return ERROR_INVALID_RSNIE; + } + +#ifdef CONFIG_IEEE80211W + if (pDot11RSNIESuite->Type > DOT11_ENC_BIP) +#else + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) +#endif + { + DEBUG_WARN("ERROR_INVALID_MULTICASTCIPHER, err 5!\n"); + return ERROR_INVALID_MULTICASTCIPHER; + } + + if (pDot11RSNIESuite->Type != priv->wpa_global_info->MulticastCipher) { + DEBUG_WARN("ERROR_INVALID_MULTICASTCIPHER, err 6!\n"); + return ERROR_INVALID_MULTICASTCIPHER; + } + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (pDot11RSNIESuite->Type != DOT11_ENC_CCMP) { + DEBUG_WARN("Invalid WPA group cipher %d\n", pDot11RSNIESuite->Type); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } +#endif + + ulIELength -= sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(DOT11_RSN_IE_SUITE); + + //---------------------------------------------------------------------------------- + // Pairwise Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 7!\n"); + return ERROR_INVALID_RSNIE; + } + + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) { + DEBUG_WARN("ERROR_INVALID_UNICASTCIPHER, err 8!\n"); + return ERROR_INVALID_UNICASTCIPHER; + } + + if ((pDot11RSNIESuite->Type < DOT11_ENC_WEP40) + || (!(BIT(pDot11RSNIESuite->Type - 1) & priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher))) { + DEBUG_WARN("ERROR_INVALID_UNICASTCIPHER, err 9!\n"); + return ERROR_INVALID_UNICASTCIPHER; + } + + pInfo->UnicastCipher = pDot11RSNIESuite->Type; + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (pInfo->UnicastCipher == DOT11_ENC_TKIP) { + DEBUG_WARN("Management frame protection cannot use TKIP\n"); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } +#endif + + ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + +#ifdef DEBUG_PSK + printk("PSK: ParseIE -> WPA2 UnicastCipher=%x\n", pInfo->UnicastCipher); +#endif + + //---------------------------------------------------------------------------------- + // Authentication suite + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) + return 0; + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + usSuitCount = le16_to_cpu(pDot11RSNIECountSuite->SuiteCount); + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC ) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 10!\n"); + return ERROR_INVALID_RSNIE; + } + + if ((pDot11RSNIESuite->Type < DOT11_AuthKeyType_RSN) || +#ifdef CONFIG_IEEE80211W + (pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK_SHA256) +#else + (pDot11RSNIESuite->Type > DOT11_AuthKeyType_PSK) +#endif + ) { + DEBUG_WARN("ERROR_INVALID_AUTHKEYMANAGE, err 11!\n"); + return ERROR_INVALID_AUTHKEYMANAGE; + } + + if((pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK) +#ifdef CONFIG_IEEE80211W + && pDot11RSNIESuite->Type != DOT11_AuthKeyType_PSK_SHA256 +#endif + ) { + DEBUG_WARN("ERROR_INVALID_AUTHKEYMANAGE, err 12!\n"); + return ERROR_INVALID_AUTHKEYMANAGE; + } + + //pInfo->AuthKeyMethod = pDot11RSNIESuite->Type; + ulIELength -= sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(pDot11RSNIECountSuite->SuiteCount) + sizeof(DOT11_RSN_IE_SUITE); + + // RSN Capability + if (ulIELength < sizeof(DOT11_RSN_CAPABILITY)) { + //pInfo->NumOfRxTSC = 2; + return 0; + } + + //---------------------------------------------------------------------------------- + // Capability field + //---------------------------------------------------------------------------------- + pDot11RSNCapability = (DOT11_RSN_CAPABILITY * )pucIE; +#if 0 + global->RSNVariable.isSuppSupportPreAuthentication = pDot11RSNCapability->field.PreAuthentication; +//#ifdef RTL_WPA2_PREAUTH // kenny temp + //wpa2_hexdump("WPA2 IE Capability", pucIE, 2); + //global->RSNVariable.isSuppSupportPreAuthentication = (pDot11RSNCapability->charData[0] & 0x01)?TRUE:FALSE; +#endif + +#if 1 + //pInfo->NumOfRxTSC = 1; +#else + global->RSNVariable.isSuppSupportPairwiseAsDefaultKey = pDot11RSNCapability->field.PairwiseAsDefaultKey; + switch (pDot11RSNCapability->field.NumOfReplayCounter) { + case 0: + global->RSNVariable.NumOfRxTSC = 1; + break; + case 1: + global->RSNVariable.NumOfRxTSC = 2; + break; + case 2: + global->RSNVariable.NumOfRxTSC = 4; + break; + case 3: + global->RSNVariable.NumOfRxTSC = 16; + break; + default: + global->RSNVariable.NumOfRxTSC = 1; + } +#endif + +#ifdef CONFIG_IEEE80211W + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + if (!pDot11RSNCapability->field.MFPC) { + printk("Management frame protection Required, but client did not enable it\n"); + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } + } + + if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION || + !(pDot11RSNCapability->field.MFPC)) + pInfo->mgmt_frame_prot = 0; + else + pInfo->mgmt_frame_prot = 1; + + PMFDEBUG("mgmt_frame_prot=%d\n", pInfo->mgmt_frame_prot); + +#endif // CONFIG_IEEE80211W + + pucIE += sizeof(DOT11_RSN_CAPABILITY); + ulIELength -= sizeof(DOT11_RSN_CAPABILITY); + + // PMKID + if ((ulIELength < 2 + PMKID_LEN)) + return 0; + + //---------------------------------------------------------------------------------- + // PMKID Count field + //---------------------------------------------------------------------------------- + usSuitCount = le16_to_cpu(*((unsigned short *)pucIE)); + + //printf("PMKID Count = %d\n",usSuitCount); + pucIE += 2; + ulIELength -= 2; +/* + if ( usSuitCount > 0) { + struct _WPA2_PMKSA_Node* pmksa_node; + int i; + for (i=0; i < usSuitCount; i++) { + pmksa_node = find_pmksa(pucIE+(PMKID_LEN*i)); + if ( pmksa_node != NULL) { + //wpa2_hexdump("Cached PMKID found", pmksa_node->pmksa.pmkid, PMKID_LEN); + global->RSNVariable.PMKCached = TRUE; + global->RSNVariable.cached_pmk_node = pmksa_node; + break; + } + } + + } +*/ + +#ifdef CONFIG_IEEE80211W + pucIE += PMKID_LEN * usSuitCount; + printk("usSuitCount=%d, ulIELength=%d\n", usSuitCount, ulIELength); + ulIELength -= PMKID_LEN * usSuitCount; + //---------------------------------------------------------------------------------- + // Group Management Cipher field (IGTK) + //---------------------------------------------------------------------------------- + if ((ulIELength < sizeof(DOT11_RSN_IE_SUITE))) { + return 0; + } + + pDot11RSNIESuite = (DOT11_RSN_IE_SUITE*)pucIE; + + if (pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC) { + printk("RSNIE Suite OUI = %02x:%02x:%02x\n", pDot11RSNIESuite->OUI[0], pDot11RSNIESuite->OUI[1], pDot11RSNIESuite->OUI[2]); + return ERROR_INVALID_RSNIE; + } + if (pDot11RSNIESuite->Type != DOT11_ENC_BIP) { + return ERROR_MGMT_FRAME_PROTECTION_VIOLATION; + } +#endif // CONFIG_IEEE80211W + + return 0; +} +#endif // RTL_WPA2 + +static void ToDrv_RspAssoc(struct rtl8192cd_priv *priv, int id, unsigned char *mac, int status) +{ + DOT11_ASSOCIATIIN_RSP Association_Rsp; + struct iw_point wrq; + + DEBUG_TRACE; + +#ifdef DEBUG_PSK + printk("PSK: Issue assoc-rsp [%x], mac:%02x:%02x:%02x:%02x:%02x:%02x\n", + status, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +#endif + + wrq.pointer = (caddr_t)&Association_Rsp; + wrq.length = sizeof(DOT11_ASSOCIATIIN_RSP); + + if (id == DOT11_EVENT_ASSOCIATION_IND) + Association_Rsp.EventId = DOT11_EVENT_ASSOCIATION_RSP; + else + Association_Rsp.EventId = DOT11_EVENT_REASSOCIATION_RSP; + + Association_Rsp.IsMoreEvent = FALSE; + Association_Rsp.Status = status; + memcpy(Association_Rsp.MACAddr, mac, 6); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + + +static void ToDrv_RemovePTK(struct rtl8192cd_priv *priv, unsigned char *mac, int type) +{ + struct iw_point wrq; + DOT11_DELETE_KEY Delete_Key; + +#ifdef DEBUG_PSK + printk("PSK: Remove PTK, mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +#endif + + wrq.pointer = (caddr_t)&Delete_Key; + wrq.length = sizeof(DOT11_DELETE_KEY); + + Delete_Key.EventId = DOT11_EVENT_DELETE_KEY; + Delete_Key.IsMoreEvent = FALSE; + Delete_Key.KeyType = type; + memcpy(&Delete_Key.MACAddr, mac, 6); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +static void ToDrv_SetPort(struct rtl8192cd_priv *priv, struct stat_info *pstat, int status) +{ + struct iw_point wrq; + DOT11_SET_PORT Set_Port; + +#ifdef DEBUG_PSK + printk("PSK: Set PORT [%x], mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + status, pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); +#endif + + wrq.pointer = (caddr_t)&Set_Port; + wrq.length = sizeof(DOT11_SET_PORT); + Set_Port.EventId = DOT11_EVENT_SET_PORT; + Set_Port.PortStatus = status; + memcpy(&Set_Port.MACAddr, pstat->hwaddr, 6); + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +static void ToDrv_SetIE(struct rtl8192cd_priv *priv) +{ + struct iw_point wrq; + DOT11_SET_RSNIE Set_Rsnie; + +#ifdef DEBUG_PSK + debug_out("PSK: Set RSNIE", priv->wpa_global_info->AuthInfoElement.Octet, + priv->wpa_global_info->AuthInfoElement.Length); +#endif + + wrq.pointer = (caddr_t)&Set_Rsnie; + wrq.length = sizeof(DOT11_SET_RSNIE); + Set_Rsnie.EventId = DOT11_EVENT_SET_RSNIE; + Set_Rsnie.IsMoreEvent = FALSE; + Set_Rsnie.Flag = DOT11_Ioctl_Set; + Set_Rsnie.RSNIELen = priv->wpa_global_info->AuthInfoElement.Length; + memcpy(&Set_Rsnie.RSNIE, + priv->wpa_global_info->AuthInfoElement.Octet, + priv->wpa_global_info->AuthInfoElement.Length); + + rtl8192cd_ioctl_priv_daemonreq(priv->dev, &wrq); +} + +static void reset_sta_info(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + WPA_STA_INFO *pInfo = pstat->wpa_sta_info; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + if (OPMODE & WIFI_AP_STATE) + { + ToDrv_RemovePTK(priv, pstat->hwaddr, DOT11_KeyType_Pairwise); + ToDrv_SetPort(priv, pstat, DOT11_PortStatus_Unauthorized); + } + + memset((char *)pInfo, '\0', sizeof(WPA_STA_INFO)); + + pInfo->priv = priv; + + if (OPMODE & WIFI_AP_STATE) + { + pInfo->state = PSK_STATE_IDLE; + } + + RESTORE_INT(flags); +} + +void nl80211_psk_init(struct rtl8192cd_priv *priv) +{ + WPA_GLOBAL_INFO *pGblInfo=priv->wpa_global_info; + int i, j, low_cipher=0; + + DEBUG_TRACE; + + memset((char *)pGblInfo, '\0', sizeof(WPA_GLOBAL_INFO)); + + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) && + !priv->pmib->dot1180211AuthEntry.dot11WPACipher) { + DEBUG_ERR("psk_init failed, WPA cipher did not set!\n"); + return; + } + +#ifdef RTL_WPA2 + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2) && + !priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher) { + DEBUG_ERR("psk_init failed, WPA2 cipher did not set!\n"); + return; + } +#endif + + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2) && + !(priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA)) { + if (priv->pmib->dot1180211AuthEntry.dot11WPACipher) + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 0; + } + if ((priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA) && + !(priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2)) { + if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher) + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 0; + } + + if (priv->pmib->dot1180211AuthEntry.dot11WPACipher) { + for (i=0, j=0; i<_WEP_104_PRIVACY_; i++) { + if (priv->pmib->dot1180211AuthEntry.dot11WPACipher & (1<UnicastCipher[j] = i+1; + if (low_cipher == 0) + low_cipher = pGblInfo->UnicastCipher[j]; + else { + if (low_cipher == _WEP_104_PRIVACY_ && + pGblInfo->UnicastCipher[j] == _WEP_40_PRIVACY_) + low_cipher = pGblInfo->UnicastCipher[j]; + else if (low_cipher == _TKIP_PRIVACY_ && + (pGblInfo->UnicastCipher[j] == _WEP_40_PRIVACY_ || + pGblInfo->UnicastCipher[j] == _WEP_104_PRIVACY_)) + low_cipher = pGblInfo->UnicastCipher[j]; + else if (low_cipher == _CCMP_PRIVACY_) + low_cipher = pGblInfo->UnicastCipher[j]; + } + if (++j >= MAX_UNICAST_CIPHER) + break; + } + } + pGblInfo->NumOfUnicastCipher = j; + } + +#ifdef RTL_WPA2 + if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher) { + for (i=0, j=0; i<_WEP_104_PRIVACY_; i++) { + if (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher & (1<UnicastCipherWPA2[j] = i+1; + if (low_cipher == 0) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + else { + if (low_cipher == _WEP_104_PRIVACY_ && + pGblInfo->UnicastCipherWPA2[j] == _WEP_40_PRIVACY_) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + else if (low_cipher == _TKIP_PRIVACY_ && + (pGblInfo->UnicastCipherWPA2[j] == _WEP_40_PRIVACY_ || + pGblInfo->UnicastCipherWPA2[j] == _WEP_104_PRIVACY_)) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + else if (low_cipher == _CCMP_PRIVACY_) + low_cipher = pGblInfo->UnicastCipherWPA2[j]; + } + if (++j >= MAX_UNICAST_CIPHER) + break; + } + } + pGblInfo->NumOfUnicastCipherWPA2= j; + } +#endif + + pGblInfo->MulticastCipher = low_cipher; + +#ifdef DEBUG_PSK + printk("PSK: WPA unicast cipher= "); + for (i=0; iNumOfUnicastCipher; i++) + printk("%x ", pGblInfo->UnicastCipher[i]); + printk("\n"); + +#ifdef RTL_WPA2 + printk("PSK: WPA2 unicast cipher= "); + for (i=0; iNumOfUnicastCipherWPA2; i++) + printk("%x ", pGblInfo->UnicastCipherWPA2[i]); + printk("\n"); +#endif + + printk("PSK: multicast cipher= %x\n", pGblInfo->MulticastCipher); +#endif + + pGblInfo->AuthInfoElement.Octet = pGblInfo->AuthInfoBuf; + + nl80211_ConstructIE(priv, pGblInfo->AuthInfoElement.Octet, + &pGblInfo->AuthInfoElement.Length); + + ToDrv_SetIE(priv); +} + +#if (defined(WIFI_HAPD) || defined(RTK_NL80211)) && defined(WDS) +void wds_psk_set(struct rtl8192cd_priv *priv, int idx, unsigned char *key) +{ +#if !defined(WIFI_HAPD) // && !defined(RTK_NL80211) + unsigned char pchar[40]; + + if (key == NULL) { + if (strlen(priv->pmib->dot11WdsInfo.wdsPskPassPhrase) == 64) // hex + get_array_val(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], priv->pmib->dot11WdsInfo.wdsPskPassPhrase, 64); + else { + memset(pchar, 0, sizeof(unsigned char)*40); + PasswordHash(priv->pmib->dot11WdsInfo.wdsPskPassPhrase,"REALTEK", strlen("REALTEK"), pchar); + memcpy(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], pchar, sizeof(unsigned char)*32); + } + } + else + memcpy(priv->pmib->dot11WdsInfo.wdsMapingKey[idx], key, sizeof(unsigned char)*32); + + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] = 32; + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] |= 0x80000000; //set bit to protect the key +#endif +} + +void wds_psk_init(struct rtl8192cd_priv *priv) +{ + unsigned char *key; + int i; + + if ( !(OPMODE & WIFI_AP_STATE)) + return; + + for (i = 0; i < priv->pmib->dot11WdsInfo.wdsNum; i++) { + if (i==0) + key = NULL; + else + key = priv->pmib->dot11WdsInfo.wdsMapingKey[0]; + + wds_psk_set(priv, i, key); + } +} +void hapd_set_wdskey(struct net_device *dev, char *wdsPskPassPhrase, char *ssid, int wds_num) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + int idx = 0; + unsigned char pchar[40]; + + memcpy(priv->pmib->dot11WdsInfo.wdsPskPassPhrase, wdsPskPassPhrase, strlen(wdsPskPassPhrase)); + priv->pmib->dot11WdsInfo.wdsPskPassPhrase[strlen(wdsPskPassPhrase)] = '\0'; + + memset(pchar, 0, sizeof(unsigned char)*40); + PasswordHash(wdsPskPassPhrase, ssid, strlen(ssid), pchar); + + for(idx =0; idxpmib->dot11WdsInfo.wdsMapingKey[idx], pchar, sizeof(unsigned char)*32); + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] = 32; + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[idx] |= 0x80000000; //set bit to protect the key + } + +} +#endif + +int nl80211_psk_indicate_evt(struct rtl8192cd_priv *priv, int id, unsigned char *mac, unsigned char *msg, int len) +{ + struct stat_info *pstat; + unsigned char tmpbuf[1024]; + int ret; +#ifdef RTL_WPA2 + int isWPA2=0; +#endif + + if (!priv->pmib->dot1180211AuthEntry.dot11EnablePSK || + !((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_))) + return -1; + +#ifdef DEBUG_PSK + printk("PSK: Got evt:%s[%x], sta: %02x:%02x:%02x:%02x:%02x:%02x, msg_len=%x\n", + ID2STR(id), id, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], len); +#endif + + pstat = get_stainfo(priv, mac); + // button 2009.05.21 +#if 0 + if (pstat == NULL) +#else + if (pstat == NULL && id!=DOT11_EVENT_WPA_MULTICAST_CIPHER && id!=DOT11_EVENT_WPA2_MULTICAST_CIPHER) +#endif + { + DEBUG_ERR("Invalid mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return -1; + } + + switch (id) { + case DOT11_EVENT_ASSOCIATION_IND: + case DOT11_EVENT_REASSOCIATION_IND: + + reset_sta_info(priv, pstat); + + if (OPMODE & WIFI_AP_STATE) { + // check RSNIE + if (len > 2 && msg != NULL) { +#ifdef DEBUG_PSK + debug_out("PSK: Rx Assoc-ind, RSNIE", msg, len); +#endif + +#ifdef RTL_WPA2 + memcpy(tmpbuf, msg, len); + len -= 2; +#else + tmpbuf[0] = RSN_ELEMENT_ID; + tmpbuf[1] = len; + memcpy(tmpbuf+2, msg, len); +#endif + +#ifdef RTL_WPA2 + isWPA2 = (tmpbuf[0] == WPA2_ELEMENT_ID) ? 1 : 0; + if (isWPA2) + ret = parseIEWPA2(priv, pstat->wpa_sta_info, tmpbuf, len+2); + else +#endif + ret = parseIE(priv, pstat->wpa_sta_info, tmpbuf, len+2); + if (ret != 0) { + DEBUG_ERR("parse IE error [%x]!\n", ret); + } + + // issue assoc-rsp successfully + ToDrv_RspAssoc(priv, id, mac, -ret); + + if (ret == 0) { +#ifdef EVENT_LOG + char *pmsg; + switch (pstat->wpa_sta_info->UnicastCipher) { + case DOT11_ENC_NONE: pmsg = "none"; break; + case DOT11_ENC_WEP40: pmsg = "WEP40"; break; + case DOT11_ENC_TKIP: pmsg = "TKIP"; break; + case DOT11_ENC_WRAP: pmsg = "AES"; break; + case DOT11_ENC_CCMP: pmsg = "AES"; break; + case DOT11_ENC_WEP104: pmsg = "WEP104"; break; + default: pmsg = "invalid algorithm"; break; + } +#ifdef RTL_WPA2 + LOG_MSG("%s-%s PSK authentication in progress...\n", (isWPA2 ? "WPA2" : "WPA"), pmsg); +#else + LOG_MSG("%s-WPA PSK authentication in progress...\n", pmsg); +#endif +#endif + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Authenticating......;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +#endif + } + } + else { // RNSIE is null + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) + ToDrv_RspAssoc(priv, id, mac, -ERROR_INVALID_RSNIE); + } + } + break; + + case DOT11_EVENT_DISASSOCIATION_IND: + reset_sta_info(priv, pstat); + break; + + case DOT11_EVENT_MIC_FAILURE: + // do nothing + break; + + } + + return 0; +} + +#endif + + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_pwrctrl.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_pwrctrl.c new file mode 100755 index 000000000..2a1148bb4 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_pwrctrl.c @@ -0,0 +1,769 @@ + +#ifdef CONFIG_POWER_SAVE +#define _8192CD_PWRCTRL_C_ + +#include +#include +#ifdef CONFIG_WAKELOCK +#include +#endif + +#include "8192cd_headers.h" +#include "8192cd_debug.h" +#include "8192cd_pwrctrl.h" +#ifdef PLATFORM_ARM_BALONG +#include +#endif + +#ifdef USE_WAKELOCK_MECHANISM +static struct wakeup_source *ws_wifi; +#endif + +u16 temp_608; + +int rtw_sdio_prepare(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct net_device *netdev = sdio_get_drvdata(func); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(netdev); + struct priv_shared_info *pshare = priv->pshare; + + if (!IS_DRV_OPEN(priv)) { + DEBUG_INFO("[%s] driver closed, return.\n", __FUNCTION__); + return 0; + } + + // check tx pending queue is empty. + if (pshare->pending_xmitbuf_queue.qlen) { + DEBUG_INFO("[%s] tx pending queue not empty.\n", __FUNCTION__); + rtw_lock_suspend_timeout(priv, 2*priv->pmib->dot11OperationEntry.ps_timeout); + return -1; + } + + if (GET_HAL_INTF_DATA(priv)->SdioTxIntStatus) { + DEBUG_INFO("[%s] SdioTxIntStatus is not idle.\n", __FUNCTION__); + rtw_lock_suspend_timeout(priv, 2*priv->pmib->dot11OperationEntry.ps_timeout); + return -1; + } + + RTL_W8(0x286, RTL_R8(0x286)|BIT2); + + if (RTL_R8(0x286) & BIT1) { + DEBUG_INFO("[%s] rx dma is idle.\n", __FUNCTION__); + } else { + DEBUG_INFO("[%s] rx dma is not idle.\n", __FUNCTION__); + } + + pshare->ps_xfer_seq = pshare->xfer_seq; + + return 0; +} + +void rtw_sdio_complete(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct net_device *netdev = sdio_get_drvdata(func); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(netdev); + + if (!IS_DRV_OPEN(priv)) { + DEBUG_INFO("[%s] driver closed, return.\n", __FUNCTION__); + return; + } + + RTL_W8(0x286 , (RTL_R8(0x286) & (~BIT2))); +} + +int rtw_sdio_suspend(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct net_device *netdev = sdio_get_drvdata(func); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(netdev); + struct priv_shared_info *pshare = priv->pshare; + struct ap_pwrctrl_priv *ps_handle = &pshare->ap_ps_handle; + + unsigned char loc_bcn[3] = {0}; + unsigned char loc_probe[3] = {0}; + unsigned int i, hidden, wait_cnt = 0; + u1Byte IsLinked = 0; + int err = -1; + _irqL irqL; + + if (!IS_DRV_OPEN(priv)) { + DEBUG_INFO("[%s] driver closed, return.\n", __FUNCTION__); +#ifdef USE_WAKELOCK_MECHANISM + mmc_pm_flag_t pm_flag = 0; + pm_flag = sdio_get_host_pm_caps(func); + + pm_flag |= MMC_PM_KEEP_POWER; + sdio_set_host_pm_flags(func, pm_flag); + DEBUG_INFO("[%s] driver closed, but need keep wifi power.\n", __FUNCTION__); +#endif + return 0; + } + + if (pshare->offload_prohibited) { + DEBUG_ERR("[%s] power save disabled ,return\n", __FUNCTION__); + pshare->offload_function_ctrl = RTW_PM_AWAKE; +#ifdef USE_WAKELOCK_MECHANISM + rtw_lock_suspend(priv); + RTL_W8(0x286 , (RTL_R8(0x286) & (~BIT2))); +#endif + return -1; + } + + _enter_critical_mutex(&pshare->apps_lock, &irqL); + + if (RTW_PM_SUSPEND == pshare->offload_function_ctrl) { + _exit_critical_mutex(&pshare->apps_lock, &irqL); + return 0; + } + + DEBUG_INFO("%s ===>\n", __FUNCTION__); + + DEBUG_INFO("[%s,%d] name = %s\n", __FUNCTION__, __LINE__, priv->dev->name); + DEBUG_INFO("[%s,%d] ps_level = %d\n", __FUNCTION__, __LINE__, priv->pmib->dot11OperationEntry.ps_level); + DEBUG_INFO("[%s,%d] ps_timeout = %d\n", __FUNCTION__, __LINE__, priv->pmib->dot11OperationEntry.ps_timeout); + + DEBUG_INFO("[%s] total_assoc_num=%d\n", __FUNCTION__, pshare->total_assoc_num); + + temp_608 = RTL_R16(0x608); + RTL_W16(0x608, ((temp_608|BIT7)&0xfcff)); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (pshare->total_assoc_num) + RTL8188E_SuspendTxReport(priv); +#endif + + if (timer_pending(&pshare->beacon_timer)) + del_timer_sync(&pshare->beacon_timer); + if (timer_pending(&pshare->ps_timer)) + del_timer_sync(&pshare->ps_timer); + if (timer_pending(&pshare->xmit_check_timer)) + del_timer_sync(&pshare->xmit_check_timer); + + pshare->ps_timer_expires = 0; + + /* start beacon offload */ +#ifdef USE_WAKELOCK_MECHANISM + if (pshare->offload_function_ctrl == RTW_PM_AWAKE) + { + pshare->offload_function_ctrl = RTW_PM_PREPROCESS; + pshare->ps_ctrl = RTW_ACT_POWERDOWN; + update_beacon(pshare->bcn_priv[0]); + pshare->ps_ctrl = RTW_ACT_POWERON; + } +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) + loc_bcn[0] = TX_TOTAL_PAGE_NUMBER_88E + 1; + loc_probe[0] = loc_bcn[0] + pshare->ap_offload_res[0].probe_offset; +#elif defined(CONFIG_WLAN_HAL_8192EE) + loc_bcn[0] = 0xf6; + loc_probe[0] = loc_bcn[0] + pshare->ap_offload_res[0].probe_offset; +#endif + + hidden = 0; + if (pshare->bcn_priv[0]->pmib->dot11OperationEntry.hiddenAP) + hidden |= BIT0; + +#ifdef MBSSID + for (i = 1; i < pshare->nr_bcn; i++) { + loc_bcn[i] = loc_bcn[0] + pshare->ap_offload_res[i].beacon_offset; + loc_probe[i] = loc_bcn[0] + pshare->ap_offload_res[i].probe_offset; + + if (pshare->bcn_priv[i]->pmib->dot11OperationEntry.hiddenAP) + hidden |= BIT(i); + } + + DEBUG_INFO("clif loc: bcn[0]=%x probe[0]=%x bcn[1]=%x probe[1]=%x, hidden=%x\n", + loc_bcn[0], loc_probe[0], loc_bcn[1], loc_probe[1], hidden); +#else + DEBUG_INFO("clif loc: bcn[0]=%x probe[0]=%x, hidden=%x\n", + loc_bcn[0], loc_probe[0], hidden); +#endif + + DEBUG_INFO("[%s] total tx bcn inrerface : %d\n", __FUNCTION__, pshare->nr_bcn); + +#ifdef PLATFORM_ARM_BALONG + if (pshare->wake_irq > 0) + enable_irq_wake(pshare->wake_irq); +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + RTL_W8(0x1c , (RTL_R8(0x1c) & (~(BIT1|BIT0)))); +#endif + //stop rx + RTL_W8(0x286, RTL_R8(0x286)|BIT2); + //polling rx dma idle + while (!(RTL_R8(0x286) & BIT1)) { + if (++wait_cnt > 100 || pshare->ps_ctrl == RTW_ACT_POWERON) + { + DEBUG_INFO("[%s] rx dma is not idle.\n", __FUNCTION__); + goto fail; + } + msleep(1); + } + DEBUG_INFO("[%s] rx dma is idle.\n", __FUNCTION__); + + DisableSdioInterrupt( priv); + ClearSdioInterrupt(priv); + + ps_handle->suspend_processing = 1; + + if (pshare->total_assoc_num > 0) + IsLinked = 1; + + DEBUG_INFO("[%s,%d] IsLinked = %x, hidAP = %x\n", __FUNCTION__, __LINE__, IsLinked, hidden); + DEBUG_INFO("[%s,%d] offload duration = %d us\n", __FUNCTION__, __LINE__, OFFLOAD_DURATION); + DEBUG_INFO("[%s,%d] Repeat trigger duration = %d %s\n", __FUNCTION__, __LINE__, + REPEAT_TRIGGER_DURATION * ((REPEAT_TRIGGER_UNIT==TRIGGER_TIME_2SEC)?2:8), + (REPEAT_TRIGGER_UNIT==TRIGGER_TIME_2SEC)?"sec":"msec"); + + RTL_W8(0x1c7, 0x0); //check send pulse or not. + + pshare->pwr_state = RTW_STS_SUSPEND; + pshare->offload_function_ctrl = RTW_PM_SUSPEND; + pshare->ap_ps_handle.en_32k = (priv->pmib->dot11OperationEntry.ps_32k_en ? 1:0); + + rtw_ap_start_fw_ps(priv, pshare->ap_ps_handle.en_32k, 1); + delay_us(10); +#if defined(CONFIG_RTL_88E_SUPPORT) + set_wakeup_pin(priv, PULSE_DURATION, 1, 1, 1, 7); + delay_us(10); + //set_repeat_wake_pulse(priv, 1, REPEAT_TRIGGER_UNIT, REPEAT_TRIGGER_DURATION); + //delay_us(10); + set_bcn_resv_page(priv, loc_bcn[0], loc_bcn[1], loc_bcn[2]); + delay_us(10); + set_probe_res_resv_page(priv, loc_probe[0], loc_probe[1], loc_probe[2]); + delay_us(10); + + set_ap_offload(priv, 0, hidden, 1, IsLinked); +#elif defined(CONFIG_WLAN_HAL_8192EE) + GET_HAL_INTERFACE(priv)->SetAPOffloadHandler(priv, 1, IsLinked, + pshare->nr_bcn, hidden, 0, loc_bcn, loc_probe); +#endif + delay_us(10); + ps_handle->h2c_done = 1; + + wait_cnt = 0; + // check firmware is receive H2C command for AP offload + while (!(RTL_R8(0x130)&BIT3)) + { + if (++wait_cnt > 20) { + DEBUG_ERR("[%s] firmware no receive H2C command or already leave AP offload mode! \n", __FUNCTION__); + goto fail; + } + delay_ms(1); + } + + if (pshare->ap_ps_handle.en_32k) + set_ap_32k(priv, 1); + +#ifdef USE_WAKELOCK_MECHANISM + mmc_pm_flag_t pm_flag = 0; + pm_flag = sdio_get_host_pm_caps(func); + + if (!(pm_flag & MMC_PM_KEEP_POWER)) { + DEBUG_ERR("%s: cannot remain alive while host is suspended\n", sdio_func_id(func)); + err = -ENOSYS; + goto fail; + } + + DEBUG_INFO("cmd: suspend with MMC_PM_KEEP_POWER\n"); + pm_flag |= MMC_PM_KEEP_POWER; + sdio_set_host_pm_flags(func, pm_flag); +#endif + + if (pshare->ps_xfer_seq != pshare->xfer_seq) { + DEBUG_INFO("[%s] Detect traffic.\n", __FUNCTION__); + goto fail; + } + +#ifdef PLATFORM_ARM_BALONG + extern int BSP_PWRCTRL_WIFI_LowPowerEnter(void); + BSP_PWRCTRL_WIFI_LowPowerEnter(); +#endif + + DEBUG_INFO("<=== %s\n", __FUNCTION__); + _exit_critical_mutex(&pshare->apps_lock, &irqL); + + return 0; + +fail: + pshare->offload_function_ctrl = RTW_PM_SUSPEND; + __rtw_sdio_resume(priv); + _exit_critical_mutex(&pshare->apps_lock, &irqL); + + return err; +} + +int __rtw_sdio_resume(struct rtl8192cd_priv *priv) +{ + struct priv_shared_info *pshare = priv->pshare; + struct ap_pwrctrl_priv *ps_handle = &pshare->ap_ps_handle; + int i, wait_cnt = 0; + + // Don't do AP offload exit when not in AP offload state. otherwise it may cause TXDMA error. + if (RTW_PM_SUSPEND != pshare->offload_function_ctrl) + return 0; + + DEBUG_INFO("%s ===>\n", __FUNCTION__); + + if (priv->pmib->dot11OperationEntry.ps_level < 2 && pshare->total_assoc_num > 0) + { + DEBUG_ERR("[%s] current power save not match linked ps!\n", __FUNCTION__); + } + +#ifdef PLATFORM_ARM_BALONG + if (pshare->wake_irq > 0) + disable_irq_wake(pshare->wake_irq); +#endif + + // Don't do H2C commands to exit AP offload during error recovery when H2C command which enable AP offload is not done. + // Otherwise it will cause TXDMA error 0x14. + if (ps_handle->h2c_done) { + ps_handle->h2c_done = 0; + if (pshare->ap_ps_handle.en_32k) { + set_ap_32k(priv, 0); + delay_ms(1); + } +#if defined(CONFIG_RTL_88E_SUPPORT) + set_ap_offload(priv, 0, 0, 0, 0); +#elif defined(CONFIG_WLAN_HAL_8192EE) + GET_HAL_INTERFACE(priv)->SetAPOffloadHandler(priv, 0, 0, 0, 0, 0, 0, 0); +#endif + delay_ms(1); + rtw_ap_stop_fw_ps(priv); + +#ifdef CONFIG_RTL_88E_SUPPORT + RTL_W8(REG_MBID_NUM, RTL_R8(REG_MBID_NUM)& (~BIT(3))); +#endif + + // check firmware is leave AP offload mode + while ((RTL_R8(0x130)&BIT3)) + { + if (++wait_cnt > 20) { + DEBUG_ERR("[%s] firmware no leave AP offload mode! \n", __FUNCTION__); + break; + } + delay_ms(1); + } + } + + RTL_W8(0x286 , (RTL_R8(0x286) & (~BIT2))); + for (i=0; i<10; i++) + { + if(RTL_R8(0x286)&BIT2) + { + DEBUG_ERR("[%s] resume 0x286 clear BIT2 fail\n", __FUNCTION__); + RTL_W8(0x286 , (RTL_R8(0x286) & (~BIT2))); + delay_ms(1); + } + else + break; + } + + ps_handle->suspend_processing = 0; + RTL_W16(0x608,temp_608); +#ifdef CONFIG_RTL_88E_SUPPORT + if (pshare->total_assoc_num) + RTL8188E_ResumeTxReport(priv); +#endif + + // Update current Tx FIFO page & Tx OQT space + WARN_ON(GET_HAL_INTF_DATA(priv)->SdioTxIntStatus); + sdio_query_txbuf_status(priv); + sdio_query_txoqt_status(priv); + + pshare->offload_function_ctrl = RTW_PM_AWAKE; + pshare->pwr_state = RTW_STS_NORMAL; + pshare->ps_ctrl = RTW_ACT_IDLE; + + if (priv->drv_state & DRV_STATE_OPEN) { + rtw_offload_reinit_timer(priv); + rtw_lock_suspend_timeout(priv, 2*priv->pmib->dot11OperationEntry.ps_timeout); + } + // Interrupt enable must be last step of the resume to avoid interfering with resume process. + EnableSdioInterrupt(priv); + + DEBUG_INFO("<=== %s\n", __FUNCTION__); + + return 0; +} + +int rtw_sdio_resume(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct net_device *netdev = sdio_get_drvdata(func); + struct rtl8192cd_priv *priv; + int err = 0; + _irqL irqL; + + if (NULL == netdev) + return 0; + + priv = GET_DEV_PRIV(netdev); + + if (!IS_DRV_OPEN(priv)) { + DEBUG_INFO("[%s] driver closed, return.\n", __FUNCTION__); + return 0; + } + + _enter_critical_mutex(&priv->pshare->apps_lock, &irqL); + + err = __rtw_sdio_resume(priv); + + _exit_critical_mutex(&priv->pshare->apps_lock, &irqL); + + return err; +} +/********************************************************/ + +#ifdef PLATFORM_ARM_BALONG +#include + +enum { + GPIO_NORMAL=0, + GPIO_INTERRUPT=0, +}; + +#define GPIO_MAXIMUM (12) +#define GPIO_MAX_PINS (8) + +#define BALONG_GPIO_0(_nr) (_nr) +#define BALONG_GPIO_1(_nr) (BALONG_GPIO_0(GPIO_MAX_PINS - 1) + (_nr) + 1 ) +#define BALONG_GPIO_2(_nr) (BALONG_GPIO_1(GPIO_MAX_PINS - 1) + (_nr) + 1 ) +#define BALONG_GPIO_3(_nr) (BALONG_GPIO_2(GPIO_MAX_PINS - 1) + (_nr) + 1 ) +#define BALONG_GPIO_4(_nr) (BALONG_GPIO_3(GPIO_MAX_PINS - 1) + (_nr) + 1 ) +#define BALONG_GPIO_5(_nr) (BALONG_GPIO_4(GPIO_MAX_PINS - 1) + (_nr) + 1 ) +#define BALONG_GPIO_6(_nr) (BALONG_GPIO_5(GPIO_MAX_PINS - 1) + (_nr) + 1 ) +#define BALONG_GPIO_7(_nr) (BALONG_GPIO_6(GPIO_MAX_PINS - 1) + (_nr) + 1 ) + +#define INT_GPIO_GP5 117 + +#define BALONG_GPIO_WIFI_WAKEUP_CHIP 5 + +//#define BALONG_GPIO_WIFI_WAKEUP_PIN 4 +#define BALONG_GPIO_WIFI_WAKEUP_PIN 0 +#define BALONG_GPIO_WIFI_WAKEUP BALONG_GPIO_5(BALONG_GPIO_WIFI_WAKEUP_PIN) + +#define BALONG_GPIO_WIFI_PWR_PIN 2 +#define BALONG_GPIO_WIFI_PWR BALONG_GPIO_5(BALONG_GPIO_WIFI_PWR_PIN) + +/*defined in drivers/mmc/host/hisdio_sys_ctrl.h */ +#define BALONG_GPIO_WIFI_RESET_PIN 6 +#define BALONG_GPIO_WIFI_RESET BALONG_GPIO_5(BALONG_GPIO_WIFI_RESET_PIN) + +extern int gpio_int_mask_set(unsigned int gpio); +extern int gpio_int_state_clear(unsigned int gpio); +extern int gpio_set_function(unsigned int gpio, unsigned function); +extern int gpio_int_trigger_set(unsigned int gpio, unsigned int trigger); +extern int gpio_int_unmask_set(unsigned int gpio); +extern int gpio_int_state_get(unsigned int gpio, unsigned *state); +extern int gpio_direction_input(unsigned int gpio); +extern int gpio_request(unsigned int gpio, const char *lebel); +extern void gpio_free(unsigned int gpio); +extern int gpio_direction_output(unsigned int gpio, int value); + +extern void balong_wifi_vote(int element); +extern void balong_wifi_devote(int element); + +#ifdef __LINUX_2_6__ +irqreturn_t balong_gpio_wakeup_isr(int irq, void *dev_instance) +#else +void balong_gpio_wakeup_isr(int irq, void *dev_instance, struct pt_regs *regs) +#endif +{ + struct net_device *dev = NULL; + struct rtl8192cd_priv *priv = NULL; + unsigned int ucData; + + priv =(struct rtl8192cd_priv *) dev_instance; + gpio_int_state_get(BALONG_GPIO_WIFI_WAKEUP, (unsigned int*)&ucData); + printk("acli: get intr %d\n", ucData); + if ( !ucData ) + return IRQ_NONE; + + gpio_int_state_clear(BALONG_GPIO_WIFI_WAKEUP); + + if ( priv->pshare->pwr_state == RTW_STS_SUSPEND ) { + DEBUG_INFO("[%s,%d] RTW_STS_SUSPEND\n", __FUNCTION__, __LINE__); + priv->pshare->pwr_state = RTW_STS_NORMAL; + priv->pshare->ps_ctrl = RTW_ACT_IDLE; + + schedule_work(&priv->ap_cmd_queue); + } + + return IRQ_HANDLED; +} + +int set_balong_wakeup_pin(struct net_device *dev, struct rtl8192cd_priv *priv) +{ + int rc; + int gpio_num =7; + + RTL_W32(GPIO_PIN_CTRL, RTL_R32(GPIO_PIN_CTRL) & ~BIT(gpio_num+8)); + + msleep(10); + + gpio_int_mask_set(BALONG_GPIO_WIFI_WAKEUP); + gpio_int_state_clear(BALONG_GPIO_WIFI_WAKEUP); + // gpio_set_function(BALONG_GPIO_WIFI_WAKEUP); + + gpio_set_function(BALONG_GPIO_WIFI_WAKEUP, GPIO_INTERRUPT); + gpio_int_trigger_set(BALONG_GPIO_WIFI_WAKEUP, IRQ_TYPE_EDGE_RISING); + + gpio_int_state_clear(BALONG_GPIO_WIFI_WAKEUP); + gpio_int_unmask_set(BALONG_GPIO_WIFI_WAKEUP); + + dev->irq = INT_GPIO_GP5; + priv->pshare->wake_irq = dev->irq; + rc = request_irq(dev->irq, balong_gpio_wakeup_isr, IRQF_SHARED, dev->name, priv); + if ( rc ) + { + printk("some issue in wake-up irq, rx=%d\n", rc); + return -1; + } + + gpio_int_state_clear(BALONG_GPIO_WIFI_WAKEUP); + gpio_int_unmask_set(BALONG_GPIO_WIFI_WAKEUP); + + return 0; +} +#endif // PLATFORM_ARM_BALONG + +/********************************************************/ +int init_wifi_wakeup_gpio(struct net_device *dev, struct rtl8192cd_priv *priv) +{ + int err = 0; + DEBUG_INFO("[%s] ENTRY \n", __FUNCTION__); +#ifdef PLATFORM_ARM_BALONG + err = set_balong_wakeup_pin(dev, priv); +#endif + return err; +} + +void free_wifi_wakeup_gpio(struct net_device *dev, struct rtl8192cd_priv *priv) +{ + DEBUG_INFO("[%s] ENTRY \n", __FUNCTION__); +#ifdef PLATFORM_ARM_BALONG + gpio_free(BALONG_GPIO_WIFI_WAKEUP_PIN); +#endif +} + + +#define RTW_SUSPEND_LOCK_NAME "rtw_wifi" + +#ifdef USE_WAKELOCK_MECHANISM +#ifdef CONFIG_WAKELOCK +static struct wake_lock rtw_suspend_lock; +#endif +#endif + +void rtw_suspend_lock_init(void) +{ + PRINT_INFO("[%s] ENTRY \n", __FUNCTION__); + +#ifdef USE_WAKELOCK_MECHANISM +#ifdef CONFIG_WAKELOCK + wake_lock_init(&rtw_suspend_lock, WAKE_LOCK_SUSPEND, RTW_SUSPEND_LOCK_NAME); +#elif defined(CONFIG_PM_WAKELOCKS) + ws_wifi = wakeup_source_register("rtl8192 wake"); +#endif +#endif +} + +void rtw_suspend_lock_deinit(void) +{ + PRINT_INFO("[%s] ENTRY \n", __FUNCTION__); + +#ifdef USE_WAKELOCK_MECHANISM +#ifdef CONFIG_WAKELOCK + wake_lock_destroy(&rtw_suspend_lock); +#elif defined(CONFIG_PM_WAKELOCKS) + wakeup_source_unregister(ws_wifi); +#endif +#endif +} + +void rtw_lock_suspend(struct rtl8192cd_priv *priv) +{ + PRINT_INFO("[%s] ENTRY \n", __FUNCTION__); + +#ifdef USE_WAKELOCK_MECHANISM +#ifdef CONFIG_WAKELOCK + wake_lock(&rtw_suspend_lock); +#elif defined(CONFIG_PM_WAKELOCKS) + __pm_stay_awake(ws_wifi); +#endif +#endif +} + +void rtw_unlock_suspend(struct rtl8192cd_priv *priv) +{ + PRINT_INFO("[%s] ENTRY \n", __FUNCTION__); + +#ifdef USE_WAKELOCK_MECHANISM +#ifdef CONFIG_WAKELOCK + wake_unlock(&rtw_suspend_lock); +#elif defined(CONFIG_PM_WAKELOCKS) + __pm_relax(ws_wifi); +#endif +#endif +} + +void rtw_lock_suspend_timeout(struct rtl8192cd_priv *priv, unsigned int timeout) +{ + unsigned long expires; + _irqL irqL; + + if (priv->pshare->offload_prohibited) + return; + + if (!IS_DRV_OPEN(GET_ROOT(priv))) + return; + + PRINT_INFO("[%s] ENTRY TO %d\n" , __FUNCTION__, timeout); + +#ifdef USE_WAKELOCK_MECHANISM +#ifdef CONFIG_WAKELOCK + wake_lock_timeout(&rtw_suspend_lock, timeout); +#elif defined(CONFIG_PM_WAKELOCKS) + __pm_wakeup_event(ws_wifi, timeout); +#endif + timeout = timeout + 1000; +#endif + + _enter_critical(&priv->pshare->offload_lock, &irqL); + + if (!timeout) { + del_timer(&priv->pshare->ps_timer); + priv->pshare->ps_timer_expires = 0; + goto unlock; + } + + expires = jiffies + RTL_MILISECONDS_TO_JIFFIES(timeout); + + if (!priv->pshare->ps_timer_expires || time_after(expires, priv->pshare->ps_timer_expires)) { + mod_timer(&priv->pshare->ps_timer, expires); + priv->pshare->ps_timer_expires = expires; + } + +unlock: + _exit_critical(&priv->pshare->offload_lock, &irqL); +} + +int rtw_ap_ps_xmit_monitor(struct rtl8192cd_priv *priv) +{ + if (0 == priv->assoc_num) { + //printk("[%s,%d] Detects have traffic and no STA link, drop the packet.\n", __FUNCTION__, __LINE__); + return 1; + } + + priv->pshare->xfer_seq++; + + if (RTW_PM_SUSPEND == priv->pshare->offload_function_ctrl) { + if (RTW_STS_SUSPEND == priv->pshare->pwr_state) { + //printk("[%s,%d] Detects have traffic sent to STA.\n", __FUNCTION__, __LINE__); + priv->pshare->pwr_state = RTW_STS_NORMAL; + priv->pshare->ps_ctrl = RTW_ACT_IDLE; + schedule_work(&GET_ROOT(priv)->ap_cmd_queue); + } + //printk("[%s,%d] Entry queue.\n", __FUNCTION__, __LINE__); + } else { + rtw_lock_suspend_timeout(priv, 2*GET_ROOT(priv)->pmib->dot11OperationEntry.ps_timeout); + } + + return 0; +} + +void rtw_ap_ps_recv_monitor(struct rtl8192cd_priv *priv) +{ + rtw_lock_suspend_timeout(priv, 2*GET_ROOT(priv)->pmib->dot11OperationEntry.ps_timeout); +} + + +void rtw_ap_ps_init(struct rtl8192cd_priv *priv) +{ + DEBUG_INFO("[%s] ENTRY \n", __FUNCTION__); + + priv->pshare->ap_ps_handle.h2c_done = 0; + priv->pshare->ap_ps_handle.sleep_time = 0; + priv->pshare->ap_ps_handle.suspend_processing = 0; +} + +void rtw_ap_ps_deinit(struct rtl8192cd_priv *priv) +{ + DEBUG_INFO("[%s] ENTRY \n", __FUNCTION__); +} + +void rtw_ap_stop_fw_ps(struct rtl8192cd_priv *priv) +{ + DEBUG_INFO("[%s] ENTRY \n", __FUNCTION__); +#if defined(CONFIG_RTL_88E_SUPPORT) + set_softap_ps(priv, 0, 0, 0, 0); +#elif defined(CONFIG_WLAN_HAL_8192EE) + /* Set H2C Cmd to FW To leave PS */ + GET_HAL_INTERFACE(priv)->SetSAPPsHandler(priv, 0, 0, 0, 0); //zyj test +#endif +} + +void rtw_ap_start_fw_ps(struct rtl8192cd_priv *priv, u4Byte en_32k, u4Byte reason) +{ + u1Byte sleep_time; + u1Byte beaconInterval = priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod; + int ps_sleep_time = priv->pmib->dot11OperationEntry.ps_sleep_time; + + DEBUG_INFO("[%s] ENTRY \n", __FUNCTION__); + + /* Set H2C Cmd to FW To enter PS */ + switch (priv->pshare->nr_bcn) { + case 2: + sleep_time = 20;//35 + break; + case 3: + sleep_time = 20; + break; + default: + sleep_time = 20; + break; + } + + if (ps_sleep_time != 0) + sleep_time = ps_sleep_time; + + priv->pshare->ap_ps_handle.sleep_time = sleep_time; + sleep_time = (sleep_time * beaconInterval) / 100; + + DEBUG_INFO("[%s] sleep_time = %d\n", __FUNCTION__, sleep_time); + +#if defined(CONFIG_RTL_88E_SUPPORT) + set_softap_ps(priv, 1, en_32k, 1, sleep_time); +#elif defined(CONFIG_WLAN_HAL_8192EE) + GET_HAL_INTERFACE(priv)->SetSAPPsHandler(priv, 1, en_32k, 1, sleep_time); +#endif +} + +void sdio_power_save_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + struct priv_shared_info *pshare = priv->pshare; + + if (pshare->offload_prohibited) + return; + + if (pshare->pending_xmitbuf_queue.qlen || (pshare->nr_bcn > 3)) { + rtw_lock_suspend_timeout(priv, 2*priv->pmib->dot11OperationEntry.ps_timeout); + return; + } + + DEBUG_INFO("[%s] ENTRY \n", __FUNCTION__); + + if (RTW_PM_AWAKE == pshare->offload_function_ctrl) { + pshare->offload_function_ctrl = RTW_PM_PREPROCESS; + pshare->ps_xfer_seq = pshare->xfer_seq; + } +} + +#endif // CONFIG_POWER_SAVE + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_pwrctrl.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_pwrctrl.h new file mode 100755 index 000000000..0db359176 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_pwrctrl.h @@ -0,0 +1,48 @@ + +#ifdef CONFIG_POWER_SAVE + +#include "8192cd.h" +#define EXTERN extern + +EXTERN int rtw_sdio_prepare(struct device *dev); +EXTERN void rtw_sdio_complete(struct device *dev); +EXTERN int rtw_sdio_suspend(struct device *dev); +EXTERN int __rtw_sdio_resume(struct rtl8192cd_priv *priv); +EXTERN int rtw_sdio_resume(struct device *dev); + +EXTERN int init_wifi_wakeup_gpio(struct net_device *dev, struct rtl8192cd_priv *priv); +EXTERN void free_wifi_wakeup_gpio(struct net_device *dev, struct rtl8192cd_priv *priv); + +EXTERN void rtw_ap_stop_fw_ps(struct rtl8192cd_priv *priv); +EXTERN void rtw_ap_start_fw_ps(struct rtl8192cd_priv *priv, u4Byte en_32k, u4Byte reason); +#ifdef CONFIG_RTL_88E_SUPPORT +EXTERN void set_ap_offload(struct rtl8192cd_priv *priv, unsigned int deny_ap, unsigned int hid_ap, int enable, unsigned int linked); +EXTERN void set_repeat_wake_pulse(struct rtl8192cd_priv *priv, unsigned char en, unsigned char triggerTime, unsigned char duration); +EXTERN void set_bcn_resv_page(struct rtl8192cd_priv *priv, unsigned int rootap, unsigned int vap1, unsigned int vap2); +EXTERN void set_probe_res_resv_page(struct rtl8192cd_priv *priv, unsigned int rootap, unsigned int vap1, unsigned int vap2); +EXTERN void set_wakeup_pin(struct rtl8192cd_priv *priv, unsigned char duration, unsigned char en, unsigned char pull_high, unsigned char pulse, unsigned char pin); +EXTERN void set_softap_ps(struct rtl8192cd_priv *priv, u8 enable, u8 en_32K, u8 lps, u8 duration); +#endif +EXTERN void rtw_suspend_lock_init(void); +EXTERN void rtw_suspend_lock_deinit(void); +EXTERN void rtw_lock_suspend(struct rtl8192cd_priv *priv); +EXTERN void rtw_unlock_suspend(struct rtl8192cd_priv *priv); +EXTERN void rtw_lock_suspend_timeout(struct rtl8192cd_priv *priv, unsigned int timeout); +//EXTERN void rtw_ap_set_wake_lock(struct rtl8192cd_priv *priv, u1Byte level, u4Byte time_ms); +EXTERN int rtw_ap_ps_xmit_monitor(struct rtl8192cd_priv *priv); +EXTERN void rtw_ap_ps_recv_monitor(struct rtl8192cd_priv *priv); +EXTERN void rtw_ap_ps_init(struct rtl8192cd_priv *priv); +EXTERN void rtw_ap_ps_deinit(struct rtl8192cd_priv *priv); + +EXTERN void ClearSdioInterrupt(struct rtl8192cd_priv *priv); +EXTERN void set_ap_32k(struct rtl8192cd_priv *priv, BOOLEAN bRpwmCfg); + +EXTERN void rtw_flush_xmit_pending_queue(struct rtl8192cd_priv *priv); +EXTERN void rtw_flush_all_tx_mgt_queue(struct rtl8192cd_priv *priv); + +EXTERN void sdio_power_save_timer(unsigned long task_priv); + +#undef EXTERN + +#endif // CONFIG_POWER_SAVE + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_rx.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_rx.c new file mode 100755 index 000000000..2147e36a3 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_rx.c @@ -0,0 +1,10233 @@ +/* + * RX handle routines + * + * $Id: 8192cd_rx.c,v 1.27.2.31 2010/12/31 08:37:43 davidhsu Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_RX_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include + + +#elif defined(__ECOS) +#include +#include +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_hw.h" +#include "./8192cd_headers.h" +#include "./8192cd_rx.h" +#include "./8192cd_debug.h" + +#ifdef __LINUX_2_6__ +#ifdef CONFIG_RTL8672 +#include "./romeperf.h" +#else +#if !defined(NOT_RTK_BSP) +#ifdef CONFIG_OPENWRT_SDK +#include "./rtl_types.h" //mark_wrt +#else +#include +#endif +#endif +#endif +#endif + +#ifdef _BROADLIGHT_FASTPATH_ +extern int (*send_packet_to_upper_layer)(struct sk_buff *skb); +#endif + +#ifdef PREVENT_ARP_SPOOFING +#include +#include +static int check_arp_spoofing(struct rtl8192cd_priv *priv, struct sk_buff *pskb); +#endif + + +#ifdef CONFIG_RTK_MESH +#include "../mesh_ext/mesh_route.h" +#endif +#if defined(CONFIG_RTL_WAPI_SUPPORT) +#include "wapiCrypto.h" +#endif +#if defined(CONFIG_RTL_FASTBRIDGE) +#include +#endif + +#ifdef CONFIG_RTL867X_VLAN_MAPPING +#include "../../re_vlan.h" +#endif +#ifdef CONFIG_RTL_VLAN_8021Q +#include +#endif + +#ifdef PERF_DUMP +#include "romeperf.h" +#endif + +#ifdef __ECOS +#define uint32 unsigned int +#define uint16 unsigned short +#define int16 short +#endif + +#ifdef BR_SHORTCUT +#ifdef WDS +__DRAM_IN_865X unsigned char cached_wds_mac[MACADDRLEN]; +__DRAM_IN_865X struct net_device *cached_wds_dev = NULL; +#endif +#ifdef CONFIG_RTK_MESH +__DRAM_IN_865X unsigned char cached_mesh_mac[2][MACADDRLEN]; +__DRAM_IN_865X struct net_device *cached_mesh_dev[2] = {NULL,NULL}; +#endif +#ifdef CLIENT_MODE +__DRAM_IN_865X unsigned char cached_sta_mac[MAX_REPEATER_SC_NUM][MACADDRLEN]; +__DRAM_IN_865X struct net_device *cached_sta_dev[MAX_REPEATER_SC_NUM] = {NULL,NULL}; +#endif + +#ifdef RTL_CACHED_BR_STA +//__DRAM_IN_865X unsigned char cached_br_sta_mac[MACADDRLEN]; +//__DRAM_IN_865X struct net_device *cached_br_sta_dev = NULL; +__DRAM_IN_865X struct brsc_cache_t brsc_cache_arr[MAX_BRSC_NUM]; +#endif +#endif // BR_SHORTCUT + +//for 8671 IGMP snooping +#ifdef CONFIG_RTL8672 +#define wlan_igmp_tag 0x1f +extern int enable_IGMP_SNP; +#ifdef CONFIG_EXT_SWITCH +extern void check_IGMP_snoop_rx(struct sk_buff *skb, int tag); +#endif +#endif + +#if 0//def CONFIG_RTL_STP +unsigned char STPmac[6] = { 1, 0x80, 0xc2, 0,0,0}; +static struct net_device* wlan_pseudo_dev; +#define WLAN_INTERFACE_NAME "wlan0" +#endif + +#if defined(__LINUX_2_6__) && defined(CONFIG_RTK_VLAN_SUPPORT) +extern int rtk_vlan_support_enable; +#endif +#ifdef CONFIG_RTL_VLAN_8021Q +extern int linux_vlan_enable; +extern linux_vlan_ctl_t *vlan_ctl_p; +#endif + +#if defined(CONFIG_RTL_EAP_RELAY) || defined(CONFIG_RTK_INBAND_HOST_HACK) +extern unsigned char inband_Hostmac[]; //it's from br.c +#endif + +#if defined(__ECOS) +extern unsigned char freebsd_Hostmac[]; +#endif + +/* ======================== RX procedure declarations ======================== */ +static void rtl8192cd_rx_ctrlframe(struct rtl8192cd_priv *priv, + struct list_head *list, struct rx_frinfo *inputPfrinfo); +#ifndef CONFIG_RTK_MESH +static +#endif +__MIPS16 +__IRAM_IN_865X + void rtl8192cd_rx_dataframe(struct rtl8192cd_priv *priv, + struct list_head *list, struct rx_frinfo *inputPfrinfo); + + +static int auth_filter(struct rtl8192cd_priv *priv, struct stat_info *pstat, + struct rx_frinfo *pfrinfo); +static void ctrl_handler(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); + +static void process_amsdu(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct rx_frinfo *pfrinfo); + + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +static unsigned char QueryRxPwrPercentage(signed char AntPower) +{ + if ((AntPower <= -100) || (AntPower >= 20)) + return 0; + else if (AntPower >= 0) + return 100; + else + return (100+AntPower); +} +#endif + +int SignalScaleMapping(int CurrSig) +{ + int RetSig; + + // Step 1. Scale mapping. + if(CurrSig >= 61 && CurrSig <= 100) + { + RetSig = 90 + ((CurrSig - 60) / 4); + } + else if(CurrSig >= 41 && CurrSig <= 60) + { + RetSig = 78 + ((CurrSig - 40) / 2); + } + else if(CurrSig >= 31 && CurrSig <= 40) + { + RetSig = 66 + (CurrSig - 30); + } + else if(CurrSig >= 21 && CurrSig <= 30) + { + RetSig = 54 + (CurrSig - 20); + } + else if(CurrSig >= 5 && CurrSig <= 20) + { + RetSig = 42 + (((CurrSig - 5) * 2) / 3); + } + else if(CurrSig == 4) + { + RetSig = 36; + } + else if(CurrSig == 3) + { + RetSig = 27; + } + else if(CurrSig == 2) + { + RetSig = 18; + } + else if(CurrSig == 1) + { + RetSig = 9; + } + else + { + RetSig = CurrSig; + } + + return RetSig; +} + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +static unsigned char EVMdbToPercentage(signed char Value) +{ + signed char ret_val; + + ret_val = Value; + + if (ret_val >= 0) + ret_val = 0; + if (ret_val <= -33) + ret_val = -33; + ret_val = 0 - ret_val; + ret_val*=3; + if (ret_val == 99) + ret_val = 100; + return(ret_val); +} +#endif + + +#ifdef MP_SWITCH_LNA + +#define ss_threshold_H 0x28 +#define ss_threshold_L 0x17 + +static __inline__ void dynamic_switch_lna(struct rtl8192cd_priv *priv) +{ + + unsigned int tmp_b30 = PHY_QueryBBReg(priv, 0xb30, bMaskDWord); + + + unsigned int tmp_dd0 = PHY_QueryBBReg(priv, 0xdd0, bMaskDWord); + unsigned int tmp_dd0_a = (tmp_dd0 & 0x3f); + unsigned int tmp_dd0_b = ((tmp_dd0 & 0x3f00) >> 8); + + //======= PATH A ============ + + if((tmp_dd0_a >= ss_threshold_H) && (!(tmp_b30 & BIT(21)))) + { + if(priv->pshare->rx_packet_ss_a >= 10) + priv->pshare->rx_packet_ss_a = 0; + + priv->pshare->rx_packet_ss_a = (priv->pshare->rx_packet_ss_a+1); + + if(priv->pshare->rx_packet_ss_a > 3) + priv->pshare->rx_packet_ss_a = 3; + + if( priv->pshare->rx_packet_ss_a == 3) + { + tmp_b30 = (tmp_b30 | BIT(21)) ; + PHY_SetBBReg(priv, 0xb30, bMaskDWord, tmp_b30 ); + printk("!!!! UP 3 PACKETS !!!! PATH A dd0[0x%x] > 0x%x, Change b30 = 0x%x!!!!\n\n", + tmp_dd0_a , ss_threshold_H, tmp_b30 ); + } + + } + else if((tmp_dd0_a <= ss_threshold_L) && (tmp_b30 & BIT(21))) + { + if(priv->pshare->rx_packet_ss_a < 10) + priv->pshare->rx_packet_ss_a = 10; + + priv->pshare->rx_packet_ss_a = (priv->pshare->rx_packet_ss_a+1) ; + + if(priv->pshare->rx_packet_ss_a > 13) + priv->pshare->rx_packet_ss_a = 13; + + if(priv->pshare->rx_packet_ss_a == 13) + { + tmp_b30 = (tmp_b30 & ~(BIT(21))) ; + PHY_SetBBReg(priv, 0xb30, bMaskDWord, tmp_b30 ); + printk("!!!! UP 3 PACKETS !!!! PATH A dd0[0x%x] < 0x%x, Change b30 = 0x%x!!!!\n\n", + tmp_dd0_a , ss_threshold_L, tmp_b30 ); + + } + } + + //======= PATH B ============ + + if((tmp_dd0_b >= ss_threshold_H) && (!(tmp_b30 & BIT(23)))) + { + if(priv->pshare->rx_packet_ss_b >= 10) + priv->pshare->rx_packet_ss_b = 0; + + priv->pshare->rx_packet_ss_b = (priv->pshare->rx_packet_ss_b+1); + + if(priv->pshare->rx_packet_ss_b > 3) + priv->pshare->rx_packet_ss_b = 3; + + if( priv->pshare->rx_packet_ss_b == 3) + { + tmp_b30 = (tmp_b30 | BIT(23)) ; + PHY_SetBBReg(priv, 0xb30, bMaskDWord, tmp_b30 ); + printk("!!!! UP 3 PACKETS !!!! PATH B dd0[0x%x] > 0x%x, Change b30 = 0x%x!!!!\n\n", + tmp_dd0_b , ss_threshold_H, tmp_b30 ); + } + + } + else if((tmp_dd0_b <= ss_threshold_L) && (tmp_b30 & BIT(23))) + { + if(priv->pshare->rx_packet_ss_b < 10) + priv->pshare->rx_packet_ss_b = 10; + + priv->pshare->rx_packet_ss_b = (priv->pshare->rx_packet_ss_b+1) ; + + if(priv->pshare->rx_packet_ss_b > 13) + priv->pshare->rx_packet_ss_b = 13; + + if(priv->pshare->rx_packet_ss_b == 13) + { + tmp_b30 = (tmp_b30 & ~(BIT(23))) ; + PHY_SetBBReg(priv, 0xb30, bMaskDWord, tmp_b30 ); + printk("!!!! UP 3 PACKETS !!!! PATH B dd0[0x%x] < 0x%x, Change b30 = 0x%x!!!!\n\n", + tmp_dd0_b , ss_threshold_L, tmp_b30 ); + } + } + +} +#endif + + +#ifdef USE_OUT_SRC +/*static*/ __inline__ void translate_rssi_sq_outsrc(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, char rate) +{ + PODM_PHY_INFO_T pPhyInfo= (PODM_PHY_INFO_T) &(pfrinfo->rssi); + ODM_PACKET_INFO_T pktinfo; +#if defined(CONFIG_PCI_HCI) + unsigned char *frame = get_pframe(pfrinfo) + (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + unsigned char *frame = get_pframe(pfrinfo); +#endif + struct stat_info *pstat = get_stainfo(priv, GetAddr2Ptr(frame)); + +#ifdef HW_FILL_MACID //eric-8814 + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + //printk("%s %d HW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } +#endif + + pktinfo.DataRate = rate; + pktinfo.bPacketToSelf = 1; + pktinfo.bPacketMatchBSSID =1; + pktinfo.StationID = (pstat ? pstat->aid : 0); + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + unsigned short *t = (unsigned short *)(get_pframe(pfrinfo)+2); + *t = le16_to_cpu(*t); + } +#endif + + ODM_PhyStatusQuery(ODMPTR, pPhyInfo, (u1Byte *)pfrinfo->driver_info, &pktinfo); + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + if ((GET_CHIP_VER(priv) == VERSION_8812E && !IS_C_CUT_8812(priv)) + || (GET_CHIP_VER(priv) == VERSION_8881A) + || (GET_CHIP_VER(priv) == VERSION_8814A) + ) { + PPHY_STATUS_RPT_8812_T pPhyStaRpt = (PPHY_STATUS_RPT_8812_T)pfrinfo->driver_info; + pfrinfo->rx_bw = pPhyStaRpt->r_RFMOD; + } +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + PPHY_STATUS_RPT_8192CD_T pPhyStaRpt = (PPHY_STATUS_RPT_8192CD_T)pfrinfo->driver_info; + pfrinfo->rx_bw = (pPhyStaRpt->rxsc == 3) ? 1 : 0; + } +#endif + + +} +#ifdef CONFIG_PCI_HCI +static +#endif +__inline__ void translate_CRC32_outsrc(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, BOOLEAN CRC32,u2Byte PKT_LEN) +{ + //unsigned char *frame = get_pframe(pfrinfo) + (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + //struct stat_info *pstat = get_stainfo(priv, GetAddr2Ptr(frame)); + //u1Byte StationID; + + //StationID = (pstat ? pstat->aid : 0); //MAC ID + + //if(StationID!=0) +#ifdef CONFIG_HW_ANTENNA_DIVERSITY + u4Byte weighting; + + if(PKT_LEN>1538 || PKT_LEN<30) + { + return; + } + else + { + if(CRC32==CRC32_FAIL) + { + weighting=0; + } + else if(CRC32==CRC32_OK) + { + if(PKT_LEN>1000) + weighting=10; + else if(PKT_LEN>500) + weighting=5; + else if(PKT_LEN>100) + weighting=3; + else + weighting=1; + } + } + + odm_AntselStatistics(ODMPTR, 1, 1 , weighting , CRC32_METHOD); + +#endif + +} + + +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +/*static*/ __inline__ void translate_rssi_sq(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + typedef signed char s1Byte; + typedef unsigned char u1Byte; + typedef int s4Byte; + typedef unsigned int u4Byte; + + PHY_STS_OFDM_8192CD_T *pOfdm_buf; + PHY_STS_CCK_8192CD_T *pCck_buf; + u1Byte *prxpkt; + u1Byte i, Max_spatial_stream, tmp_rxsnr, tmp_rxevm; //, tmp_rxrssi; + s1Byte rx_pwr[4], rx_pwr_all=0; + s1Byte rx_snrX, rx_evmX; //, rx_rssiX; + u1Byte EVM, PWDB_ALL; + u4Byte RSSI; + u1Byte isCCKrate=0; +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + u1Byte report; +#endif +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) + unsigned int ofdm_max_rssi=0, ofdm_min_rssi=0xff; +#endif + + /* 2007/07/04 MH For OFDM RSSI. For high power or not. */ + //static u1Byte check_reg824 = 0; + //static u4Byte reg824_bit9 = 0; + + isCCKrate = is_CCK_rate(pfrinfo->rx_rate); + +#ifdef CONFIG_PCI_HCI + /*2007.08.30 requested by SD3 Jerry */ + if (priv->pshare->phw->check_reg824 == 0) { + priv->pshare->phw->reg824_bit9 = PHY_QueryBBReg(priv, rFPGA0_XA_HSSIParameter2, 0x200); + priv->pshare->phw->check_reg824 = 1; + } +#endif + + prxpkt = (u1Byte *)pfrinfo->driver_info; + + /* Initial the cck and ofdm buffer pointer */ + pCck_buf = (PHY_STS_CCK_8192CD_T *)prxpkt; + pOfdm_buf = (PHY_STS_OFDM_8192CD_T *)prxpkt; + + memset(&pfrinfo->rf_info, 0, sizeof(struct rf_misc_info)); + pfrinfo->rf_info.mimosq[0] = -1; + pfrinfo->rf_info.mimosq[1] = -1; + + if (isCCKrate) { +/* + // + // (1)Hardware does not provide RSSI for CCK + // + if ((get_rf_mimo_mode(priv) == MIMO_2T4R) && (priv->pshare->rf_ft_var.cck_sel_ver == 2)) { + for (i=RF92CD_PATH_A; iadc_pwdb_X[i]; + rx_rssiX = (s1Byte)(tmp_rxrssi); + rx_rssiX /= 2; + pfrinfo->cck_mimorssi[i] = rx_rssiX; + } + } +*/ + // + // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) + // +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8192D) +#endif + ) { + if (!priv->pshare->phw->reg824_bit9) { + report = pCck_buf->cck_agc_rpt & 0xc0; + report = report>>6; + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)) { + switch (report) { + case 0x3: + rx_pwr_all = -46 - (pCck_buf->cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -26 - (pCck_buf->cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -12 - (pCck_buf->cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 16 - (pCck_buf->cck_agc_rpt & 0x3e); + break; + } + } else +#endif + { + switch (report) { + //Fixed by Wish and BB Cherry 2013.12.04 + case 0x3: + rx_pwr_all = -46 - (pCck_buf->cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -26 - (pCck_buf->cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -12 - (pCck_buf->cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 16 - (pCck_buf->cck_agc_rpt & 0x3e); + break; + } + } + } else { + report = pCck_buf->cck_agc_rpt & 0x60; + report = report>>5; + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)) { + switch (report) { + case 0x3: + rx_pwr_all = -46 - ((pCck_buf->cck_agc_rpt & 0x1f)<<1) ; + break; + case 0x2: + rx_pwr_all = -26 - ((pCck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x1: + rx_pwr_all = -12 - ((pCck_buf->cck_agc_rpt & 0x1f)<<1) ; + break; + case 0x0: + rx_pwr_all = 16 - ((pCck_buf->cck_agc_rpt & 0x1f)<<1) ; + break; + } + } else +#endif + { + switch (report) { + //Fixed by Wish and BB Cherry 2013.12.04 + case 0x3: + rx_pwr_all = -46 - ((pCck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x2: + rx_pwr_all = -26 - ((pCck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x1: + rx_pwr_all = -12 - ((pCck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x0: + rx_pwr_all = 16 - ((pCck_buf->cck_agc_rpt & 0x1f)<<1); + break; + } + } + } + PWDB_ALL = QueryRxPwrPercentage(rx_pwr_all); + +#ifdef CONFIG_RTL_92C_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)) { +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) { + if (!(pCck_buf->cck_agc_rpt>>7)) + PWDB_ALL = (PWDB_ALL>94)?100:(PWDB_ALL + 6); + else + PWDB_ALL = (PWDB_ALL<16)?0:(PWDB_ALL -16); + + /* CCK Modification */ + if (PWDB_ALL > 25 && PWDB_ALL <= 60) + PWDB_ALL += 6; + /* + else if (PWDB_ALL <= 25) + PWDB_ALL += 8; + */ + } else +#endif + { + if (PWDB_ALL > 99) + PWDB_ALL -= 8; + else if (PWDB_ALL > 50 && PWDB_ALL <= 68) + PWDB_ALL += 4; + } + + pfrinfo->rssi = PWDB_ALL; +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna) + pfrinfo->rssi+=10; +#endif + } else +#endif + { + pfrinfo->rssi = PWDB_ALL; + pfrinfo->rssi+=3; + } + + if (pfrinfo->rssi > 100) + pfrinfo->rssi = 100; + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + unsigned int LNA_idx = ((pCck_buf->cck_agc_rpt & 0xE0) >>5); + unsigned int VGA_idx = (pCck_buf->cck_agc_rpt & 0x1F); + switch(LNA_idx) { + case 7: + if(VGA_idx <= 27) + rx_pwr_all = -100 + 2*(27-VGA_idx); //VGA_idx = 27~2 + else + rx_pwr_all = -100; + break; + case 6: + rx_pwr_all = -48 + 2*(2-VGA_idx); //VGA_idx = 2~0 + break; + case 5: + rx_pwr_all = -42 + 2*(7-VGA_idx); //VGA_idx = 7~5 + break; + case 4: + rx_pwr_all = -36 + 2*(7-VGA_idx); //VGA_idx = 7~4 + break; + case 3: + //rx_pwr_all = -28 + 2*(7-VGA_idx); //VGA_idx = 7~0 + rx_pwr_all = -24 + 2*(7-VGA_idx); //VGA_idx = 7~0 + break; + case 2: + if(priv->pshare->phw->reg824_bit9) + rx_pwr_all = -12 + 2*(5-VGA_idx); //VGA_idx = 5~0 + else + rx_pwr_all = -6+ 2*(5-VGA_idx); + break; + case 1: + rx_pwr_all = 8-2*VGA_idx; + break; + case 0: + rx_pwr_all = 14-2*VGA_idx; + break; + default: + printk("%s %d, CCK Exception default\n", __FUNCTION__, __LINE__); + break; + } + rx_pwr_all += 6; + PWDB_ALL = QueryRxPwrPercentage(rx_pwr_all); + + if(!priv->pshare->phw->reg824_bit9) { + if(PWDB_ALL >= 80) + PWDB_ALL = ((PWDB_ALL-80)<<1)+((PWDB_ALL-80)>>1)+80; + else if((PWDB_ALL <= 78) && (PWDB_ALL >= 20)) + PWDB_ALL += 3; + if(PWDB_ALL>100) + PWDB_ALL = 100; + } + + pfrinfo->rssi = PWDB_ALL; + } +#endif + + // + // (3) Get Signal Quality (EVM) + // + // if(bPacketMatchBSSID) + { + u1Byte SQ; + + if (pfrinfo->rssi > 40) { + SQ = 100; + } else { + SQ = pCck_buf->SQ_rpt; + + if (pCck_buf->SQ_rpt > 64) + SQ = 0; + else if (pCck_buf->SQ_rpt < 20) + SQ = 100; + else + SQ = ((64-SQ) * 100) / 44; + } + pfrinfo->sq = SQ; + pfrinfo->rf_info.mimosq[0] = SQ; + } + } else { + // + // (1)Get RSSI for HT rate + // + for (i=RF92CD_PATH_A; itrsw_gain_X[i]&0x3F)*2) - 110; + else +#endif + rx_pwr[i] = ((pOfdm_buf->trsw_gain_X[i]&0x3F)*2) - 106; + + //Get Rx snr value in DB + if (priv->pshare->rf_ft_var.rssi_dump) { + tmp_rxsnr = pOfdm_buf->rxsnr_X[i]; + rx_snrX = (s1Byte)(tmp_rxsnr); + rx_snrX >>= 1; + pfrinfo->rf_info.RxSNRdB[i] = (s4Byte)rx_snrX; + } + + /* Translate DBM to percentage. */ + RSSI = QueryRxPwrPercentage(rx_pwr[i]); + //total_rssi += RSSI; + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) + if (( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8188E) +#endif + ) +#ifdef HIGH_POWER_EXT_LNA + && (priv->pshare->rf_ft_var.use_ext_lna) +#endif + ) { + if ((pOfdm_buf->trsw_gain_X[i]>>7) == 1) + RSSI = (RSSI>94)?100:(RSSI + 6); + else + RSSI = (RSSI<16)?0:(RSSI -16); + + if (RSSI <= 34 && RSSI >= 4) + RSSI -= 4; + } +#endif + + /* Record Signal Strength for next packet */ + //if(bPacketMatchBSSID) + { + pfrinfo->rf_info.mimorssi[i] = (u1Byte)RSSI; + } + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8188E) +#endif + ) { + if (RSSI > ofdm_max_rssi) + ofdm_max_rssi = RSSI; + if (RSSI < ofdm_min_rssi) + ofdm_min_rssi = RSSI; + } +#endif + } + + // + // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) + // +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C) +#endif +#ifdef CONFIG_RTL_88E_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv) == VERSION_8188E) +#endif + ) { + if ((ofdm_max_rssi - ofdm_min_rssi) < 3) + PWDB_ALL = ofdm_max_rssi; + else if ((ofdm_max_rssi - ofdm_min_rssi) < 6) + PWDB_ALL = ofdm_max_rssi - 1; + else if ((ofdm_max_rssi - ofdm_min_rssi) < 10) + PWDB_ALL = ofdm_max_rssi - 2; + else + PWDB_ALL = ofdm_max_rssi - 3; + } else +#endif + { + rx_pwr_all = (((pOfdm_buf->pwdb_all ) >> 1 )& 0x7f) -106; + PWDB_ALL = QueryRxPwrPercentage(rx_pwr_all); + } + + pfrinfo->rssi = PWDB_ALL; + + // + // (3)EVM of HT rate + // + //eric_8814 ?? 3 spatial stream ?? + if ((pfrinfo->rx_rate >= _MCS8_RATE_) && (pfrinfo->rx_rate <= _MCS15_RATE_)) + Max_spatial_stream = 2; //both spatial stream make sense + else + Max_spatial_stream = 1; //only spatial stream 1 makes sense + + for (i=0; irxevm_X[i]; + rx_evmX = (s1Byte)(tmp_rxevm); + + // Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment + // fill most significant bit to "zero" when doing shifting operation which may change a negative + // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. + rx_evmX /= 2; //dbm + + EVM = EVMdbToPercentage(rx_evmX); + + //if(bPacketMatchBSSID) + { + if (i==0) // Fill value in RFD, Get the first spatial stream only + { + pfrinfo->sq = (u1Byte)(EVM & 0xff); + } + pfrinfo->rf_info.mimosq[i] = (u1Byte)(EVM & 0xff); + } + } + } +} +#endif + + +#if 0//def CONFIG_RTL_STP +int rtl865x_wlanIF_Init(struct net_device *dev) +{ + if (dev == NULL) + return FALSE; + else + { + wlan_pseudo_dev = dev; + printk("init wlan pseudo dev =====> %s\n", wlan_pseudo_dev->name); + } + return TRUE; +} +#endif + + +#ifdef SUPPORT_RX_UNI2MCAST +static unsigned int check_mcastL2L3Diff(struct sk_buff *skb) +{ + unsigned int DaIpAddr; + struct iphdr* iph = SKB_IP_HEADER(skb); + +#ifdef _LITTLE_ENDIAN_ + DaIpAddr = ntohl(iph->daddr); +#else + DaIpAddr = iph->daddr; +#endif + //printk("ip:%d, %d ,%d ,%d\n",(DaIpAddr>>24) ,(DaIpAddr<<8)>>24,(DaIpAddr<<16)>>24,(DaIpAddr<<24)>>24); + + if (((DaIpAddr & 0xFF000000) >= 0xE0000000) && ((DaIpAddr & 0xFF000000) <= 0xEF000000)) { + if (!IP_MCAST_MAC(SKB_MAC_HEADER(skb))) + return DaIpAddr; + } + return 0; +} + + +static void ConvertMCastIPtoMMac(unsigned int group, unsigned char *gmac) +{ + unsigned int u32tmp, tmp; + static int i; + + u32tmp = group & 0x007FFFFF; + gmac[0] = 0x01; + gmac[1] = 0x00; + gmac[2] = 0x5e; + + for (i=5; i>=3; i--) { + tmp = u32tmp & 0xFF; + gmac[i] = tmp; + u32tmp >>= 8; + } +} + + +static void CheckUDPandU2M(struct sk_buff *pskb) +{ + int MultiIP; + + MultiIP = check_mcastL2L3Diff(pskb); + if (MultiIP) { + unsigned char mactmp[6]; + ConvertMCastIPtoMMac(MultiIP, mactmp); + //printk("%02x%02x%02x:%02x%02x%02x\n", mactmp[0],mactmp[1],mactmp[2], + // mactmp[3],mactmp[4],mactmp[5]); + memcpy(SKB_MAC_HEADER(pskb), mactmp, 6); +#if defined(__LINUX_2_6__) + /*added by qinjunjie,warning:should not remove next line*/ + pskb->pkt_type = PACKET_MULTICAST; +#endif + } +} + +static void CheckV6UDPandU2M(struct sk_buff *pskb) +{ +#ifdef __ECOS + struct ip6_hdr *iph = (struct ip6_hdr *)(pskb->data + ETH_HLEN); + unsigned char *DDA=pskb->data; +#else + struct ipv6hdr *iph; + unsigned char *DDA; + + iph = (struct ipv6hdr *)SKB_IP_HEADER(pskb); + DDA = (unsigned char *)SKB_MAC_HEADER(pskb); +#endif + + /*ip(v6) format is multicast ip*/ +#ifdef __ECOS + if (iph->ip6_dst.s6_addr[0] == 0xff){ +#else + if (iph->daddr.s6_addr[0] == 0xff){ +#endif + + /*mac is not ipv6 multicase mac*/ + if(!ICMPV6_MCAST_MAC(DDA) ){ + /*change mac (DA) to (ipv6 multicase mac) format by (ipv6 multicast ip)*/ + DDA[0] = 0x33; + DDA[1] = 0x33; + #ifdef __ECOS + memcpy(DDA+2, &iph->ip6_dst.s6_addr[12], 4); + #else + memcpy(DDA+2, &iph->daddr.s6_addr[12], 4); + #endif + } + } +} +#endif + + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) +/* 88C, 92C, and 92D need to check privacy algorithm and accept icv error packet when using CCMP, + because hw may report wrong icv status when using CCMP privacy*/ +static __inline__ unsigned int check_icverr_drop(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) {/*return 0: accept packet, 1: drop packet*/ + unsigned int privacy; + struct stat_info *pstat; + if((GET_CHIP_VER(priv)== VERSION_8192C) || (GET_CHIP_VER(priv)== VERSION_8192D) || (GET_CHIP_VER(priv)== VERSION_8188C)){ + privacy = 0; + pstat = NULL; +#if defined(WDS) || defined(CONFIG_RTK_MESH) || defined(A4_STA) + if (get_tofr_ds((unsigned char *)get_pframe(pfrinfo)) == 3) { + pstat = get_stainfo(priv, (unsigned char *)GetAddr2Ptr((unsigned char *)get_pframe(pfrinfo))); + } else +#endif + { + pstat = get_stainfo(priv, (unsigned char *)get_sa((unsigned char *)get_pframe(pfrinfo))); + } + + if (pstat) { + if (OPMODE & WIFI_AP_STATE) { +#if defined(WDS) || defined(CONFIG_RTK_MESH) + if (get_tofr_ds((unsigned char *)get_pframe(pfrinfo)) == 3){ +#if defined(CONFIG_RTK_MESH) + if(priv->pmib->dot1180211sInfo.mesh_enable) { + privacy = (IS_MCAST(GetAddr1Ptr((unsigned char *)get_pframe(pfrinfo)))) ? _NO_PRIVACY_ : priv->pmib->dot11sKeysTable.dot11Privacy; + } else +#endif + {privacy = priv->pmib->dot11WdsInfo.wdsPrivacy;} + } + else +#endif /* defined(WDS) || defined(CONFIG_RTK_MESH) */ + {privacy = get_sta_encrypt_algthm(priv, pstat);} + } +#if defined(CLIENT_MODE) + else { + privacy = get_sta_encrypt_algthm(priv, pstat); + } +#endif + + if (privacy == _CCMP_PRIVACY_) + return 0; /* do not drop this packet*/ + } + } + return 1;/* drop this packet*/ +} +#endif + +#ifdef A4_STA +static void add_a4_client(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + struct list_head *phead, *plist; + struct stat_info *sta; + + if (!netif_running(priv->dev)) + return; + + phead = &priv->a4_sta_list; + plist = phead->next; + + while (plist != phead) { + sta = list_entry(plist, struct stat_info, a4_sta_list); + if (!memcmp(sta->hwaddr, pstat->hwaddr, WLAN_ADDR_LEN)) { + ASSERT(pstat == sta); + break; + } + plist = plist->next; + } + + if (plist == phead) + list_add_tail(&pstat->a4_sta_list, &priv->a4_sta_list); + + pstat->state |= WIFI_A4_STA; +} +#endif + +#ifdef BR_SHORTCUT +#ifdef CONFIG_RTL8672 +extern struct net_device *get_eth_cached_dev(unsigned char *da); +#else +#ifdef CONFIG_RTL_819X +__inline__ struct net_device *get_eth_cached_dev(unsigned char *da) +{ + extern unsigned char cached_eth_addr[MACADDRLEN]; + extern struct net_device *cached_dev; + +#ifndef NOT_RTK_BSP + extern unsigned char cached_eth_addr2[MACADDRLEN]; + extern struct net_device *cached_dev2; + + extern unsigned char cached_eth_addr3[MACADDRLEN]; + extern struct net_device *cached_dev3; + + extern unsigned char cached_eth_addr4[MACADDRLEN]; + extern struct net_device *cached_dev4; +#endif // !NOT_RTK_BSP + if (cached_dev && !memcmp(da, cached_eth_addr, MACADDRLEN)) + return cached_dev; +#ifndef NOT_RTK_BSP + else if (cached_dev2 && !memcmp(da, cached_eth_addr2, MACADDRLEN)) + return cached_dev2; + else if (cached_dev3 && !memcmp(da, cached_eth_addr3, MACADDRLEN)) + return cached_dev3; + else if (cached_dev4 && !memcmp(da, cached_eth_addr4, MACADDRLEN)) + return cached_dev4; +#endif // !NOT_RTK_BSP + else + return NULL; +} +#endif +#endif +#endif + +#if ((defined(CONFIG_RTK_VLAN_SUPPORT) && defined(CONFIG_RTK_VLAN_FOR_CABLE_MODEM)) || defined(MCAST2UI_REFINE)) +extern struct net_device* re865x_get_netdev_by_name(const char* name); +#endif + +#ifdef _SINUX_ +extern int g_sc_enable_brsc; +#endif + +#ifdef _FULLY_WIFI_IGMP_SNOOPING_SUPPORT_ +#include +static void ___ConvertMulticatIPtoMacAddr(__u32 group, unsigned char *gmac) +{ + __u32 u32tmp, tmp; + int i; + + u32tmp = group & 0x007FFFFF; + gmac[0]=0x01; gmac[1]=0x00; gmac[2]=0x5e; + for (i=5; i>=3; i--) { + tmp=u32tmp&0xFF; + gmac[i]=tmp; + u32tmp >>= 8; + } +} + +static char __igmp3_report_simple_check(struct sk_buff *skb, unsigned char *gmac, struct igmphdr *igmph) +{ + struct igmpv3_report *igmpv3; + struct igmpv3_grec *igmpv3grec; + unsigned int IGMP_Group;// add for fit igmp v3 + __u16 rec_id =0; + int srcnum=0; + int op = 0; + + igmpv3 = (struct igmpv3_report *)igmph; + igmpv3grec = &igmpv3->grec[0]; + + while( rec_id < ntohs(igmpv3->ngrec) ) + { + IGMP_Group = be32_to_cpu(igmpv3grec->grec_mca); + srcnum = ntohs(igmpv3grec->grec_nsrcs); + + /*check if it's protocol reserved group */ + if(IN_MULTICAST(IGMP_Group)) + { + ___ConvertMulticatIPtoMacAddr(IGMP_Group, gmac); + switch( igmpv3grec->grec_type ) + { + case IGMPV3_MODE_IS_INCLUDE: + case IGMPV3_CHANGE_TO_INCLUDE: + if (srcnum == 0){ + op = 0x8B81; // SIOCGIMCAST_DEL; + } else { + op =0x8B80; // SIOCGIMCAST_ADD; + } + break; + case IGMPV3_MODE_IS_EXCLUDE: + case IGMPV3_CHANGE_TO_EXCLUDE: + case IGMPV3_ALLOW_NEW_SOURCES: + op =0x8B80; // SIOCGIMCAST_ADD; + break; + case IGMPV3_BLOCK_OLD_SOURCES: + op = 0x8B81; // SIOCGIMCAST_DEL; + break; + default: + //printk("%s> Not support Group Record Types [%x]\n", __FUNCTION__, igmpv3grec->grec_type ); + break; + } + } /*else { + printk("%s> Mcast err addr, group:%s, rec_id:%d, srcnum:%d\n", __FUNCTION__, inet_ntoa(IGMP_Group), rec_id, srcnum); + }*/ + + if (op != 0) { + memcpy(gmac+6, SKB_MAC_HEADER(skb)+6, 6); + ioctl_AddDelMCASTGroup2STA(skb->dev, (struct ifreq*)gmac, op); + op =0; + } + + rec_id++; + igmpv3grec = (struct igmpv3_grec *)( (char*)igmpv3grec + sizeof( struct igmpv3_grec ) + (igmpv3grec->grec_auxwords+srcnum)*sizeof( __u32 ) ); + } + + return 3; +} + +static char ___igmp_type_check(struct sk_buff *skb, unsigned char *gmac) +{ + struct iphdr *iph; + __u8 hdrlen; + struct igmphdr *igmph; + unsigned int IGMP_Group;// add for fit igmp v3 + + /* check IP header information */ + iph = SKB_IP_HEADER(skb); + hdrlen = iph->ihl << 2; + if ((iph->version != 4) && (hdrlen < 20)) + return -1; + + if (ip_fast_csum((u8 *)iph, iph->ihl) != 0) + return -2; + + { /* check the length */ + __u32 len = ntohs(iph->tot_len); + if (skb->len < len || len < hdrlen) + return -3; + } + + /* parsing the igmp packet */ + igmph = (struct igmphdr *)((u8*)iph+hdrlen); + + /*IGMP-V3 type Report*/ + if(igmph->type == IGMPV3_HOST_MEMBERSHIP_REPORT) + { + return __igmp3_report_simple_check(skb, gmac, igmph); + + }else{ //4 V2 or V1 + IGMP_Group = be32_to_cpu(igmph->group); + } + + /*check if it's protocol reserved group */ + if(!IN_MULTICAST(IGMP_Group)) + { + return -4; + } + + ___ConvertMulticatIPtoMacAddr(IGMP_Group, gmac); + + if ((igmph->type==IGMP_HOST_MEMBERSHIP_REPORT) || + (igmph->type==IGMPV2_HOST_MEMBERSHIP_REPORT)) + { + return 1; /* report and add it */ + } + else if (igmph->type==IGMP_HOST_LEAVE_MESSAGE) + { + return 2; /* leave and delete it */ + } + + return -5; +} + +static void rtl_igmp_notify(struct sk_buff *skb, void *igmp_header) +{ + int op; + char type; + //struct igmphdr *ih = (struct igmphdr *)igmp_header; + unsigned char StaMacAndGroup[20]; + + type = ___igmp_type_check(skb,StaMacAndGroup); + + switch (type) { + case 1: + op = 0x8B80; // SIOCGIMCAST_ADD; + break; + case 2: + op = 0x8B81; // SIOCGIMCAST_DEL; + break; + case 3://igmpv3 report + return; + default: + printk("IGMP Error type=%d\n",type); + return; + + } + memcpy(StaMacAndGroup+6, SKB_MAC_HEADER(skb)+6, 6); + ioctl_AddDelMCASTGroup2STA(skb->dev, (struct ifreq*)StaMacAndGroup, op); +} + +static void check_igmp_snooping_pkt( struct sk_buff *pskb ) +{ + unsigned char *dest = eth_hdr(pskb)->h_dest; + struct iphdr *iph; + int vlanTag = 0; + + if (IS_MCAST(dest)) + { + if (unlikely((*(unsigned short *)(SKB_MAC_HEADER(pskb) + ETH_ALEN * 2) == __constant_htons(ETH_P_8021Q)))) + vlanTag = 4; + if (unlikely((*(unsigned short *)(SKB_MAC_HEADER(pskb) + ETH_ALEN * 2 + vlanTag) == __constant_htons(ETH_P_IP)))) + { + iph = SKB_IP_HEADER(pskb); + if (vlanTag) + iph = (struct iphdr *)((unsigned char*)iph + vlanTag); +#if defined(LINUX_2_6_22_) + skb_set_network_header(pskb, ETH_HLEN+vlanTag); +#else + pskb->nh.raw = (unsigned char *)iph; +#endif + if (unlikely(iph->protocol == IPPROTO_IGMP)) + { + //printk("dest=%02x-%02x-%02x-%02x-%02x-%02x\n",dest[0],dest[1],dest[2],dest[3],dest[4],dest[5]); +#if defined(LINUX_2_6_22_) + pskb->transport_header = pskb->network_header + (iph->ihl * 4); + rtl_igmp_notify(pskb, skb_transport_header(pskb)); +#else + pskb->h.raw = pskb->nh.raw + (iph->ihl * 4); + rtl_igmp_notify(pskb, pskb->h.raw); +#endif + } + } + } +} + + +#endif //_FULLY_WIFI_IGMP_SNOOPING_SUPPORT_ + +#ifdef _FULLY_WIFI_MLD_SNOOPING_SUPPORT_ +#define IPV6_ROUTER_ALTER_OPTION 0x05020000 +#define HOP_BY_HOP_OPTIONS_HEADER 0 +#define ROUTING_HEADER 43 +#define FRAGMENT_HEADER 44 +#define DESTINATION_OPTION_HEADER 60 + +#define ICMP_PROTOCOL 58 + +#define MLD_QUERY 130 +#define MLDV1_REPORT 131 +#define MLDV1_DONE 132 +#define MLDV2_REPORT 143 + +#define MLD2_CHANGE_TO_INCLUDE 3 +#define MLD2_CHANGE_TO_EXCLUDE 4 + +/*Convert MultiCatst IPV6_Addr to MAC_Addr*/ +static void ___ConvertMulticatIPv6toMacAddr(unsigned char* icmpv6_McastAddr, unsigned char *gmac) +{ + /*ICMPv6 valid addr 2^32 -1*/ + gmac[0] = 0x33; + gmac[1] = 0x33; + gmac[2] = icmpv6_McastAddr[12]; + gmac[3] = icmpv6_McastAddr[13]; + gmac[4] = icmpv6_McastAddr[14]; + gmac[5] = icmpv6_McastAddr[15]; +} + +static char ___mld_type_check(struct sk_buff *skb, unsigned char *gmac) +{ + unsigned char *ptr; +#ifdef __ECOS + struct ip6_hdr *ipv6h; +#else + struct ipv6hdr *ipv6h; +#endif + + unsigned char *startPtr = NULL; + unsigned char *lastPtr = NULL; + unsigned char nextHeader = 0; + unsigned short extensionHdrLen = 0; + +#if defined(LINUX_2_6_22_) + ptr = (unsigned char *)skb_network_header(skb); +#else + ptr = (unsigned char *)skb->nh.raw; +#endif + +#ifdef __ECOS + ipv6h = (struct ip6_hdr *)ptr; + if (ipv6h->ip6_vfc != IPV6_VERSION) +#else + ipv6h = (struct ipv6hdr *)ptr; + if (ipv6h->version != 6) +#endif + { + return -1; + } + + startPtr = (unsigned char *)ptr; +#ifdef __ECOS + lastPtr = startPtr + sizeof(struct ip6_hdr) + ntohs(ipv6h->ip6_plen); + nextHeader = ipv6h->ip6_nxt; + ptr = startPtr + sizeof(struct ip6_hdr); +#else + lastPtr = startPtr + sizeof(struct ipv6hdr) + ntohs(ipv6h->payload_len); + nextHeader = ipv6h->nexthdr; + ptr = startPtr + sizeof(struct ipv6hdr); +#endif + + while (ptr < lastPtr) + { + switch (nextHeader) + { + //printk("nextHeader : %d\n", nextHeader); + + case HOP_BY_HOP_OPTIONS_HEADER: + /*parse hop-by-hop option*/ + nextHeader = ptr[0]; + extensionHdrLen = ((u16)(ptr[1]) + 1) * 8; + ptr = ptr + extensionHdrLen; + break; + + case ROUTING_HEADER: + nextHeader = ptr[0]; + extensionHdrLen = ((u16)(ptr[1]) + 1) * 8; + ptr = ptr + extensionHdrLen; + break; + + case FRAGMENT_HEADER: + nextHeader = ptr[0]; + ptr = ptr + 8; + break; + + case DESTINATION_OPTION_HEADER: + nextHeader = ptr[0]; + extensionHdrLen = ((u16)(ptr[1]) + 1) * 8; + ptr = ptr + extensionHdrLen; + break; + + case ICMP_PROTOCOL: + if (ptr[0] == MLDV2_REPORT) { + //printk("MLDV2_REPORT\n"); + ___ConvertMulticatIPv6toMacAddr(ptr + 12, gmac); + + if (ptr[8] == MLD2_CHANGE_TO_EXCLUDE) + { + //printk("MLD2_CHANGE_TO_EXCLUDE\n"); + return 1; /* report and add it */ + } + + if (ptr[8] == MLD2_CHANGE_TO_INCLUDE) + { + //printk("MLD2_CHANGE_TO_INCLUDE\n"); + return 2; /* leave and delete it */ + } + } else if (ptr[0] == MLDV1_REPORT) { + //printk("MLDV1_REPORT\n"); + ___ConvertMulticatIPv6toMacAddr(ptr + 8, gmac); + return 1; /* report and add it */ + } else if (ptr[0] == MLDV1_DONE) { + //printk("MLDV1_DONE\n"); + ___ConvertMulticatIPv6toMacAddr(ptr + 8, gmac); + return 2; /* leave and delete it */ + } + + return -2; + break; + + default: + return -3; + } + } + + return -4; +} + +static void rtl_mld_notify(struct sk_buff *skb) +{ + int op; + char type; + unsigned char StaMacAndGroup[20]; + + type = ___mld_type_check(skb, StaMacAndGroup); + //printk("MLD type = %d\n", type); + + switch (type) { + case 1: + op = 0x8B80; // SIOCGIMCAST_ADD; + break; + case 2: + op = 0x8B81; // SIOCGIMCAST_DEL; + break; + default: + //printk("MLD Error type = %d\n", type); + return; + } + + memcpy(StaMacAndGroup + 6, SKB_MAC_HEADER(skb) + 6, 6); + ioctl_AddDelMCASTGroup2STA(skb->dev, (struct ifreq*)StaMacAndGroup, op); + //printk("StaMacAndGroup[0] = %02x-%02x-%02x-%02x-%02x-%02x\n", StaMacAndGroup[0], StaMacAndGroup[1], StaMacAndGroup[2], StaMacAndGroup[3], StaMacAndGroup[4], StaMacAndGroup[5]); + //printk("StaMacAndGroup[6] = %02x-%02x-%02x-%02x-%02x-%02x\n", StaMacAndGroup[0+6], StaMacAndGroup[1+6], StaMacAndGroup[2+6], StaMacAndGroup[3+6], StaMacAndGroup[4+6], StaMacAndGroup[5+6]); +} + +static void check_mld_snooping_pkt(struct sk_buff *pskb) +{ + unsigned char *dest = eth_hdr(pskb)->h_dest; + struct iphdr *iph; + int vlanTag = 0; + + if (IPV6_MCAST_MAC(dest)) + { + if (unlikely((*(unsigned short *)(SKB_MAC_HEADER(pskb) + ETH_ALEN * 2) == __constant_htons(ETH_P_8021Q)))) + vlanTag = 4; + + if (unlikely((*(unsigned short *)(SKB_MAC_HEADER(pskb) + ETH_ALEN * 2 + vlanTag) == __constant_htons(ETH_P_IPV6)))) + { + iph = SKB_IP_HEADER(pskb); + if (vlanTag) + iph = (struct iphdr *)((unsigned char*)iph + vlanTag); + +#if defined(LINUX_2_6_22_) + skb_set_network_header(pskb, ETH_HLEN+vlanTag); +#else + pskb->nh.raw = (unsigned char *)iph; +#endif + //printk("dest = %02x-%02x-%02x-%02x-%02x-%02x\n", dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]); + rtl_mld_notify(pskb); + } + } +} +#endif //_FULLY_WIFI_MLD_SNOOPING_SUPPORT_ + +#if defined(BR_SHORTCUT) + +int rtl_IsMcastIP(struct sk_buff *pskb) +{ + int ret=0; + unsigned short L3_protocol; + L3_protocol = *(unsigned short *)(pskb->data+ETH_ALEN*2); + + if( L3_protocol == __constant_htons(0x0800) ) + { + unsigned int DaIpAddr; + struct iphdr* iph = (struct iphdr *)(pskb->data + ETH_HLEN); + + DaIpAddr = iph->daddr; + //panic_printk("[%s]:[%d],pskb:%x.\n",__FUNCTION__,__LINE__,DaIpAddr); + + if((DaIpAddr & 0xF0000000) == 0xE0000000) + { + ret=1; + } + } + else if(L3_protocol == __constant_htons(0x86dd)) + { + #ifdef __ECOS + struct ip6_hdr *iph; + iph = (struct ip6_hdr *)(pskb->data + ETH_HLEN); + #else + struct ipv6hdr *iph; + iph = (struct ipv6hdr *)(pskb->data + ETH_HLEN); + #endif + /*ip(v6) format is multicast ip*/ + #ifdef __ECOS + if (iph->ip6_dst.s6_addr[0] == 0xff) + #else + if (iph->daddr.s6_addr[0] == 0xff) + #endif + { + ret=1; + } + } + + //panic_printk("[%s]:[%d],ret:%x,pskb:%x-%x-%x-%x-%x-%x.\n",__FUNCTION__,__LINE__,ret,pskb->data[0],pskb->data[1],pskb->data[2],pskb->data[3],pskb->data[4],pskb->data[5]); + return ret; +} +#endif +#ifdef CONFIG_RTL_8196E +__MIPS16 +#endif +__IRAM_IN_865X +void rtl_netif_rx(struct rtl8192cd_priv *priv, struct sk_buff *pskb, struct stat_info *pstat) +{ +#ifdef CLIENT_MODE +#ifdef SUPPORT_RX_UNI2MCAST + unsigned short L3_protocol; + unsigned char *DA_START; +#endif +#ifdef VIDEO_STREAMING_REFINE + // for video streaming refine + extern struct net_device *is_eth_streaming_only(struct sk_buff *skb); + struct net_device *dev; +#endif +#endif + struct vlan_info *vlan=NULL; +#ifdef CONFIG_RTL_VLAN_8021Q + int index; +#endif + + struct net_bridge_port *br_port=NULL; + + static unsigned char* cached_sta_macPtr=NULL; + static struct net_device *cached_sta_devPtr=NULL; + +#ifdef __KERNEL__ + br_port = GET_BR_PORT(priv->dev); +#endif +#ifdef CONFIG_POWER_SAVE + rtw_ap_ps_recv_monitor(priv); +#endif + +#ifdef PREVENT_BROADCAST_STORM + if ((OPMODE & WIFI_AP_STATE) && ((unsigned char)pskb->data[0] == 0xff) && pstat) { + if (pstat->rx_pkts_bc > BROADCAST_STORM_THRESHOLD) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Broadcast storm happened!\n"); + rtl_kfree_skb(priv, pskb, _SKB_RX_); + return; + } + } +#endif + +#ifdef CONFIG_RTK_VLAN_WAN_TAG + extern int rtl865x_same_root(struct net_device *dev1,struct net_device *dev2); +#endif + +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU) +#ifdef __ECOS + if (SUCCESS==rtl_isWlanPassthruFrame(pskb->data)) +#else + if (SUCCESS==rtl_isPassthruFrame(pskb->data)) +#endif + { +#ifdef CLIENT_MODE + if(priv &&((GET_MIB(priv))->dot11OperationEntry.opmode)& WIFI_STATION_STATE) + { + #if defined(CONFIG_RTL_92D_SUPPORT)||defined (CONFIG_RTL_8881A) + unsigned int wispWlanIndex=(passThruStatusWlan&WISP_WLAN_IDX_MASK)>>WISP_WLAN_IDX_RIGHT_SHIFT; + if( + #ifdef SMART_REPEATER_MODE + (priv==(GET_VXD_PRIV((wlan_device[wispWlanIndex].priv))))|| + #endif + (priv == wlan_device[wispWlanIndex].priv)) + { + pskb->dev = wlan_device[passThruWanIdx].priv->pWlanDev; + } + #else + pskb->dev = wlan_device[passThruWanIdx].priv->pWlanDev; + #endif + + } +#endif + } +#endif + +#ifdef GBWC + if (priv->pmib->gbwcEntry.GBWCMode && pstat) { + if (((priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_MAC_INNER) && (pstat->GBWC_in_group)) || + ((priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_MAC_OUTTER) && !(pstat->GBWC_in_group)) || + (priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_IF_RX) || + (priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_IF_TRX)) { + if ((priv->GBWC_rx_count + pskb->len) > ((priv->pmib->gbwcEntry.GBWCThrd_rx * 1024 / 8) / (100 / GBWC_TO))) { + // over the bandwidth + if (priv->GBWC_consuming_Q) { + // in rtl8192cd_GBWC_timer context + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: BWC bandwidth over!\n"); + rtl_kfree_skb(priv, pskb, _SKB_RX_); + } + else { + // normal Rx path + int ret = enque(priv, &(priv->GBWC_rx_queue.head), &(priv->GBWC_rx_queue.tail), + (unsigned long)(priv->GBWC_rx_queue.pSkb), NUM_TXPKT_QUEUE, (void *)pskb); + if (ret == FALSE) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: BWC rx queue full!\n"); + rtl_kfree_skb(priv, pskb, _SKB_RX_); + } + else + *(unsigned int *)&(pskb->cb[4]) = (unsigned int)pstat; // backup pstat pointer + } + return; + } + else { + // not over the bandwidth + if (CIRC_CNT(priv->GBWC_rx_queue.head, priv->GBWC_rx_queue.tail, NUM_TXPKT_QUEUE) && + !priv->GBWC_consuming_Q) { + // there are already packets in queue, put in queue too for order + int ret = enque(priv, &(priv->GBWC_rx_queue.head), &(priv->GBWC_rx_queue.tail), + (unsigned long)(priv->GBWC_rx_queue.pSkb), NUM_TXPKT_QUEUE, (void *)pskb); + if (ret == FALSE) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: BWC rx queue full!\n"); + rtl_kfree_skb(priv, pskb, _SKB_RX_); + } + else + *(unsigned int *)&(pskb->cb[4]) = (unsigned int)pstat; // backup pstat pointer + return; + } + else { + // can pass up directly + priv->GBWC_rx_count += pskb->len; + } + } + } + } +#endif + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif + +#if defined(MULTI_MAC_CLONE) && !defined(__ECOS) + if ((OPMODE & WIFI_AP_STATE) && pskb->dev && (pskb->dev->base_addr != 0)) { + *(unsigned int *)&(pskb->cb[40]) = 0x86518192; // means from wlan interface + } +#endif + +#ifdef HS2_SUPPORT +/* Hotspot 2.0 Release 1 */ + if ((priv->proxy_arp) && (IS_MCAST(pskb->data)) && pstat) + { + if (ICMPV6_MCAST_SOLI_MAC(pskb->data)) + stav6ip_snooping_bynsolic(pskb, pstat); + //else if (ICMPV6_MCAST_MAC(pskb->data)) + // stav6ip_snooping_bynadvert(pskb, pstat); + else + staip_snooping_byarp(pskb, pstat); + } +#endif + +#ifdef UNIVERSAL_REPEATER + if((OPMODE & WIFI_STATION_STATE) + #ifdef __KERNEL__ + && (br_port) + #endif + ) { + unsigned char *brmac; + + brmac = priv->br_mac; + if(isDHCPpkt(pskb) && memcmp(pskb->data+MACADDRLEN,brmac,MACADDRLEN)) { + DEBUG_INFO("%s %d invoke snoop_STA_IP\n",__func__,__LINE__); + snoop_STA_IP(pskb, priv); + } + } +#endif + +#ifdef _11s_TEST_MODE_ + mesh_debug_rx1(priv, pskb); +#endif + +#if 0//def CONFIG_RTL_STP + if (((unsigned char)pskb->data[12]) < 0x06) + { + if (!memcmp(pskb->data, STPmac, 5) && !(((unsigned char )pskb->data[5])& 0xF0)) + { + if (memcmp(pskb->dev->name, WLAN_INTERFACE_NAME, sizeof(WLAN_INTERFACE_NAME)) == 0) + { + if (wlan_pseudo_dev != NULL) + pskb->dev = wlan_pseudo_dev; + pskb->protocol = eth_type_trans(pskb, priv->dev); + #if defined(_BROADLIGHT_FASTPATH_) + send_packet_to_upper_layer(pskb); + #elif defined(__LINUX_2_6__) && defined(RX_TASKLET) && !defined(CONFIG_RTL8672) && !defined(NOT_RTK_BSP) && !defined(__LINUX_3_10__) + netif_receive_skb(pskb); + #else + netif_rx(pskb); + #endif + } + } + } + else +#endif + { +#ifdef CONFIG_RTK_VLAN_SUPPORT +#if defined(CONFIG_RTK_MESH) + if(pskb->dev == priv->mesh_dev) { + vlan = (struct vlan_info *)&priv->mesh_vlan; + } else +#endif + { + vlan = (struct vlan_info *)&priv->pmib->vlan; + } + + if (rtk_vlan_support_enable && vlan->global_vlan) { +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + if (rx_vlan_process(priv->dev, vlan, pskb, NULL)){ +#else + if (rx_vlan_process(priv->dev, vlan, pskb)){ +#endif + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: by vlan!\n"); + dev_kfree_skb_any(pskb); + return; + } + +#if defined(CONFIG_RTK_VLAN_FOR_CABLE_MODEM) + if(rtk_vlan_support_enable == 2 && pskb->tag.f.tpid == htons(ETH_P_8021Q)) + { + struct net_device *toDev; + + toDev = re865x_get_netdev_by_name("eth1"); + + //printk("===%s(%d),vid(%d),from(%s),todev(%s),skb->tag.vid(%d)\n",__FUNCTION__,__LINE__,pskb->tag.f.pci & 0xfff, pskb->dev->name, + //toDev?toDev->name:NULL,pskb->tag.f.pci & 0xfff); + + if(toDev) + { + pskb->dev = toDev; + toDev->netdev_ops->ndo_start_xmit(pskb,toDev); + return; + } + + } +#endif + } +#endif + +#if defined(CONFIG_RTL_819X_ECOS)&&defined(CONFIG_RTL_VLAN_SUPPORT)&&defined(CONFIG_RTL_819X_SWCORE) + if (rtl_vlan_support_enable) { + #ifdef CONFIG_RTL_BRIDGE_VLAN_SUPPORT + if (rtl_vlanIngressProcess(pskb, priv->dev->name, NULL) < 0){ + #else + if (rtl_vlanIngressProcess(pskb, priv->dev->name) < 0){ + #endif + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: by vlan!\n"); + dev_kfree_skb_any(pskb); + return; + } + } +#endif //CONFIG_RTL_VLAN_SUPPORT + +#ifdef CONFIG_RTL_VLAN_8021Q +#if 0 + if(linux_vlan_enable){ + /*add vlan tag if pkt is untagged*/ + if(*((uint16*)(pskb->data+(ETH_ALEN<<1))) != __constant_htons(ETH_P_8021Q)){ + /*mapping dev to pvid array's index*/ + index = priv->dev->vlan_member_map; + if(index>=WLAN0_MASK_BIT && index<=WLAN1_VXD_MASK_BIT){ + if(vlan_ctl_p->pvid[index]){ + memmove(pskb->data-VLAN_HLEN, pskb->data, ETH_ALEN<<1); + skb_push(pskb,VLAN_HLEN); + *((uint16*)(pskb->data+(ETH_ALEN<<1))) = __constant_htons(ETH_P_8021Q); + *((uint16*)(pskb->data+(ETH_ALEN<<1)+2)) = vlan_ctl_p->pvid[index]; + } + } + } + } +#endif +#endif + +#if defined(BR_SHORTCUT) +if(rtl_IsMcastIP(pskb)==0) +{ +#ifdef CONFIG_RTL_VLAN_8021Q + if(!linux_vlan_enable) +#endif + /*if lltd, don't go shortcut*/ + if(*(unsigned short *)(pskb->data+ETH_ALEN*2) != htons(0x88d9)) + { + struct net_device *cached_dev=NULL; + +#ifdef CONFIG_RTK_MESH + + if (pskb->dev && (pskb->dev == priv->mesh_dev)) + { + int index = 0; + #ifdef CONFIG_RTL_MESH_CROSSBAND + index = priv->dev->name[4] - '0'; + #endif + + proxy_table_chkcln(priv, pskb); + memcpy(cached_mesh_mac[index], &pskb->data[6], 6); + cached_mesh_dev[index] = pskb->dev; + } +#endif + +#ifdef WDS + if (pskb->dev && pskb->dev->base_addr==0) { + if(priv->pmib->dot11WdsInfo.wdsNum>1) + cached_wds_dev = NULL; + else + { + memcpy(cached_wds_mac, &pskb->data[6], 6); + cached_wds_dev = pskb->dev; + } + } +#endif + +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_STATION_STATE) && pskb->dev) { + + + if(priv->reperater_idx==1){ + memcpy(cached_sta_mac[0], &pskb->data[6], 6); + cached_sta_dev[0] = pskb->dev; + }else if((priv->reperater_idx==2)){ + memcpy(cached_sta_mac[1], &pskb->data[6], 6); + cached_sta_dev[1] = pskb->dev; + } + + if (!(pskb->data[0] & 0x01) && + !priv->pmib->dot11OperationEntry.disable_brsc && + #ifdef __KERNEL__ + (br_port) && + #endif + ((cached_dev=get_shortcut_dev(pskb->data)) !=NULL) + && netif_running(cached_dev) + ) + { + + pskb->dev = cached_dev; + #if !defined(__LINUX_2_6__) || defined(CONFIG_COMPAT_NET_DEV_OPS) + cached_dev->hard_start_xmit(pskb, cached_dev); + #else + cached_dev->netdev_ops->ndo_start_xmit(pskb,cached_dev); + #endif + return; + + } + } + /*AP mode side -> Client mode side*/ + if ((OPMODE & WIFI_AP_STATE) && pskb->dev) { + if (!(pskb->data[0] & 0x01) && !priv->pmib->dot11OperationEntry.disable_brsc && priv->reperater_idx + #ifdef __KERNEL__ + && (br_port) + #endif + ) + { + + + if(priv->reperater_idx==1){ + cached_sta_macPtr = cached_sta_mac[0]; + cached_sta_devPtr = cached_sta_dev[0]; + }else if(priv->reperater_idx==2){ + cached_sta_macPtr = cached_sta_mac[1]; + cached_sta_devPtr = cached_sta_dev[1]; + } + + if( cached_sta_devPtr && netif_running(cached_sta_devPtr) && (!memcmp(cached_sta_macPtr,pskb->data,6))){ + pskb->dev = cached_sta_devPtr; + + #if !defined(__LINUX_2_6__) || defined(CONFIG_COMPAT_NET_DEV_OPS) + cached_sta_devPtr->hard_start_xmit(pskb, cached_sta_devPtr); + #else + cached_sta_devPtr->netdev_ops->ndo_start_xmit(pskb,cached_sta_devPtr); + #endif + return; + } + } + } +#endif +#ifdef AP_2_AP_BRSC + // AP mode -> AP mode + if ((OPMODE & WIFI_AP_STATE) && pskb->dev) { + if (!(pskb->data[0] & 0x01) && + !priv->pmib->dot11OperationEntry.disable_brsc && +#ifdef __KERNEL__ + (br_port) && +#endif + ((cached_dev=get_shortcut_dev(pskb->data)) !=NULL) + && netif_running(cached_dev)){ + pskb->dev = cached_dev; +#if !defined(__LINUX_2_6__) || defined(CONFIG_COMPAT_NET_DEV_OPS) + cached_dev->hard_start_xmit(pskb, cached_dev); +#else + cached_dev->netdev_ops->ndo_start_xmit(pskb,cached_dev); +#endif + return; + } + } +#endif // AP_2_AP_BRSC + +#ifdef WDS + if (pskb->dev && (pskb->dev->base_addr || priv->pmib->dot11WdsInfo.wdsNum<2)) +#endif + if (!(pskb->data[0] & 0x01) && + !priv->pmib->dot11OperationEntry.disable_brsc && +#if defined(CONFIG_DOMAIN_NAME_QUERY_SUPPORT) || defined(CONFIG_RTL_ULINKER) + (pskb->data[37] != 68) && /*port 68 is dhcp dest port. In order to hack dns ip, so dhcp packa can't enter bridge short cut.*/ +#endif +#if defined(CONFIG_RTL_DNS_TRAP) + !(*(unsigned short *)(pskb->data+ETH_ALEN*2)==htons(0x0800) && + *(unsigned char *)(pskb->data+0x17) == 17 && + (*(unsigned short *)(pskb->data+0x24) == htons(53))) && +#endif +#ifdef __KERNEL__ +#ifndef _SINUX_ // if sinux, no linux bridge, so should don't depend on br_port if use br_shortcut (John Qian 2010/6/24) + (br_port) && +#else + (g_sc_enable_brsc) && +#endif +#endif +#ifdef CONFIG_RTL_819X + #if defined(CONFIG_RTL_ULINKER_BRSC) + (((cached_dev=brsc_get_cached_dev(0, pskb->data))!=NULL) || ((cached_dev = get_eth_cached_dev(pskb->data)) != NULL)) + #else + ((cached_dev = get_eth_cached_dev(pskb->data)) != NULL) + #endif +#else + cached_dev +#endif +#ifdef CONFIG_RTK_VLAN_WAN_TAG + && rtl865x_same_root(pskb->dev,cached_dev) +#endif + && netif_running(cached_dev) +#if defined(CONFIG_RTK_GUEST_ZONE) && defined(__KERNEL__) + && (cached_dev->br_port->zone_type == br_port->zone_type) +#endif + ) + { + + #if defined(CONFIG_RTL_ULINKER_BRSC) + if (cached_usb.dev && cached_dev == cached_usb.dev) { + BRSC_COUNTER_UPDATE(tx_wlan_sc); + BDBG_BRSC("BRSC: get shortcut dev[%s]\n", cached_usb.dev->name); + + if (pskb->dev) + brsc_cache_dev(1, pskb->dev, pskb->data+ETH_ALEN); + } + #endif + +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.br_cnt_sc++; +#endif + pskb->dev = cached_dev; +#ifdef TX_SCATTER + pskb->list_num = 0; +#endif +#if !defined(__LINUX_2_6__) || defined(CONFIG_COMPAT_NET_DEV_OPS) + cached_dev->hard_start_xmit(pskb, cached_dev); + #else + cached_dev->netdev_ops->ndo_start_xmit(pskb,cached_dev); + #endif + return; + } + } +} +#endif // BR_SHORTCUT + #if defined(CONFIG_RTL_FASTBRIDGE) + if (br_port) { + if (RTL_FB_RETURN_SUCCESS==rtl_fb_process_in_nic(pskb, pskb->dev)) + return; + } + #endif + +#ifdef MBSSID + if ((OPMODE & WIFI_AP_STATE) && pskb->dev && (pskb->dev->base_addr != 0)) { + *(unsigned int *)&(pskb->cb[20]) = 0x86518190; // means from wlan interface + *(unsigned int *)&(pskb->cb[24]) = priv->pmib->miscEntry.groupID; // remember group ID + } +#endif + +#ifdef CONFIG_RTL867X_VLAN_MAPPING + if (re_vlan_loaded()) { + re_vlan_untag(pskb); + } +#endif + +#ifdef __KERNEL__ + if (pskb->dev) +#ifdef __LINUX_2_6__ + pskb->protocol = eth_type_trans(pskb, pskb->dev); + else +#endif + pskb->protocol = eth_type_trans(pskb, priv->dev); +#endif + +#ifdef _FULLY_WIFI_IGMP_SNOOPING_SUPPORT_ + check_igmp_snooping_pkt(pskb); +#endif //_FULLY_WIFI_IGMP_SNOOPING_SUPPORT_ + +#ifdef _FULLY_WIFI_MLD_SNOOPING_SUPPORT_ + check_mld_snooping_pkt(pskb); +#endif //_FULLY_WIFI_MLD_SNOOPING_SUPPORT_ + +#ifdef CONFIG_RTL8672 + if(enable_IGMP_SNP) { +#ifdef CONFIG_EXT_SWITCH + check_IGMP_snoop_rx(pskb, wlan_igmp_tag); +#endif + } + pskb->switch_port = priv->dev->name; + pskb->from_dev = priv->dev; +#endif + +#ifdef HS2_SUPPORT +/* Hotspot 2.0 Release 1 */ + if (pskb->protocol == __constant_htons(ETHER_TDLS)) + { + priv->ext_stats.rx_data_drops++; + HS2_DEBUG_INFO("RX DROP: TDLS!\n"); + dev_kfree_skb_any(pskb); + + return; + } +#endif + +#ifdef SUPPORT_RX_UNI2MCAST + /* under sta mode for check UDP type packet that L3 IP is multicast but L2 mac is not */ + if (((OPMODE & WIFI_STATION_STATE) == WIFI_STATION_STATE) +#ifdef MULTI_MAC_CLONE + && !GET_MIB(priv)->ethBrExtInfo.macclone_enable +#endif + ) + { + L3_protocol = *(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN * 2); + DA_START = SKB_MAC_HEADER(pskb); + + if( L3_protocol == __constant_htons(0x0800) ) + //&&(*(unsigned char *)(SKB_MAC_HEADER(pskb) + 23)) == 0x11) { /*added by qinjunjie,warning:unicast to multicast conversion should not only limited to udp*/ + { + CheckUDPandU2M(pskb); + }else if(L3_protocol == __constant_htons(0x86dd) && + *(unsigned char *)(SKB_MAC_HEADER(pskb) + 20) == 0x11 ) + { + CheckV6UDPandU2M(pskb); + } + } + +#ifdef BR_SHORTCUT +#ifdef VIDEO_STREAMING_REFINE + // for video streaming refine + if ((OPMODE & WIFI_STATION_STATE) && + (*((unsigned char *)SKB_MAC_HEADER(pskb))) & 0x01) && + !priv->pmib->dot11OperationEntry.disable_brsc && + (br_port) && + ((dev = is_eth_streaming_only(pskb)) != NULL)) { + skb_push(pskb, 14); +#if !defined(__LINUX_2_6__) || defined(CONFIG_COMPAT_NET_DEV_OPS) + dev->hard_start_xmit(pskb, dev); +#else + dev->netdev_ops->ndo_start_xmit(pskb, dev); +#endif + return; + } +#endif // VIDEO_STREAMING_REFINE +#endif // BR_SHORTCUT +#endif // SUPPORT_RX_UNI2MCAST + +#ifdef CONFIG_RTL_NETSNIPER_SUPPORT + pskb->wanorlan = rtl_check_wanorlan(pskb->dev->name); /* wan:1 lan:2 default:0 */ +#endif + +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.br_cnt_nosc++; +#endif + #if defined(_BROADLIGHT_FASTPATH_) + send_packet_to_upper_layer(pskb); + #elif defined(__LINUX_2_6__) && defined(RX_TASKLET) && !defined(CONFIG_RTL8672)&& !defined(NOT_RTK_BSP)&& !defined(__LINUX_3_10__) + netif_receive_skb(pskb); + #else +#if defined(CONFIG_RG_WLAN_HWNAT_ACCELERATION) && !defined(CONFIG_ARCH_LUNA_SLAVE) +{ + enum { + RE8670_RX_STOP=0, + RE8670_RX_CONTINUE, + RE8670_RX_STOP_SKBNOFREE, + RE8670_RX_END + }; + int ret; + pskb->data-=14; + pskb->len+=14; + //printk("[%s]\n",pskb->dev->name); + ret=fwdEngine_rx_skb(NULL,pskb,NULL); + if(ret==RE8670_RX_CONTINUE) + { + pskb->data+=14; + pskb->len-=14; + //printk("WLAN0 rx, fwdEngine is handled, trap to netif_rx\n"); + netif_rx(pskb); + } + else if(ret==RE8670_RX_STOP) + { + kfree_skb(pskb); + } +} +#else + netif_rx(pskb); +#endif + +#endif + } +} + + +#ifdef GBWC +static int GBWC_forward_check(struct rtl8192cd_priv *priv, struct sk_buff *pskb, struct stat_info *pstat) +{ + if (priv->pmib->gbwcEntry.GBWCMode && pstat) { + if (((priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_MAC_INNER) && (pstat->GBWC_in_group)) || + ((priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_MAC_OUTTER) && !(pstat->GBWC_in_group)) || + (priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_IF_RX) || + (priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_IF_TRX)) { + if ((priv->GBWC_rx_count + pskb->len) > ((priv->pmib->gbwcEntry.GBWCThrd_rx * 1024 / 8) / (100 / GBWC_TO))) { + // over the bandwidth + int ret = enque(priv, &(priv->GBWC_tx_queue.head), &(priv->GBWC_tx_queue.tail), + (unsigned long)(priv->GBWC_tx_queue.pSkb), NUM_TXPKT_QUEUE, (void *)pskb); + if (ret == FALSE) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: BWC tx queue full!\n"); + dev_kfree_skb_any(pskb); + } + else { +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + } + return 1; + } + else { + // not over the bandwidth + if (CIRC_CNT(priv->GBWC_tx_queue.head, priv->GBWC_tx_queue.tail, NUM_TXPKT_QUEUE)) { + // there are already packets in queue, put in queue too for order + int ret = enque(priv, &(priv->GBWC_tx_queue.head), &(priv->GBWC_tx_queue.tail), + (unsigned long)(priv->GBWC_tx_queue.pSkb), NUM_TXPKT_QUEUE, (void *)pskb); + if (ret == FALSE) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: BWC tx queue full!\n"); + dev_kfree_skb_any(pskb); + } + else { +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + } + return 1; + } + else { + // can forward directly + priv->GBWC_rx_count += pskb->len; + } + } + } + } + + return 0; +} +#endif + + +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +static void reorder_ctrl_pktout(struct rtl8192cd_priv *priv, struct sk_buff *pskb, struct stat_info *pstat) +{ + struct stat_info *dst_pstat = (struct stat_info*)(*(unsigned int *)&(pskb->cb[4])); + + if (dst_pstat == 0) + rtl_netif_rx(priv, pskb, pstat); + else + { +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif +#ifdef TX_SCATTER + pskb->list_num = 0; +#endif +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + if(pskb->cb[3] == RELAY_11S) { + struct tx_insn txcfg; + txcfg.priv = pskb->dev->priv; + txcfg.is_11s = RELAY_11S; + pskb->dev = priv->mesh_dev; + __rtl8192cd_start_xmit_out(pskb, dst_pstat, &txcfg); + } + else if(pskb->cb[3] == XMIT_11S) { + DECLARE_TXINSN(txcfg); + if(dot11s_datapath_decision(pskb, &txcfg, 1) != 0) { + dst_pstat = get_stainfo(txcfg.priv, txcfg.nhop_11s); + pskb->dev = priv->mesh_dev; + __rtl8192cd_start_xmit_out(pskb, dst_pstat, &txcfg); + } + } + else +#endif + if (rtl8192cd_start_xmit(pskb, priv->dev)) + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } +} + + +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +static void reorder_ctrl_consumeQ(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char tid, int seg) +{ + int win_start, win_size; + struct reorder_ctrl_entry *rc_entry; + + rc_entry = &pstat->rc_entry[tid]; + win_start = rc_entry->win_start; + win_size = priv->pmib->reorderCtrlEntry.ReorderCtrlWinSz; + + while (SN_LESS(win_start, rc_entry->last_seq) || (win_start == rc_entry->last_seq)) { + if (rc_entry->packet_q[win_start & (win_size - 1)]) { + reorder_ctrl_pktout(priv, rc_entry->packet_q[win_start & (win_size - 1)], pstat); + rc_entry->packet_q[win_start & (win_size - 1)] = NULL; +#ifdef _DEBUG_RTL8192CD_ + if (seg == 0) + pstat->rx_rc_passupi++; + else if (seg == 2) + pstat->rx_rc_passup2++; + else if (seg == 3) + pstat->rx_rc_passup3++; + else if (seg == 4) + pstat->rx_rc_passup4++; +#endif + } + win_start = SN_NEXT(win_start); + } + rc_entry->start_rcv = FALSE; +} + + +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +static int reorder_ctrl_timer_add(struct rtl8192cd_priv *priv, struct stat_info *pstat, int tid, int from_timeout) +{ + unsigned int now, timeout, new_timer=0; + int setup_timer; + int current_idx, next_idx; + int sys_tick; + + if (!from_timeout) { + while (CIRC_CNT(priv->pshare->rc_timer_head, priv->pshare->rc_timer_tail, RC_TIMER_NUM)) { + if (priv->pshare->rc_timer[priv->pshare->rc_timer_tail].pstat == NULL) { + priv->pshare->rc_timer_tail = (priv->pshare->rc_timer_tail + 1) & (RC_TIMER_NUM - 1); + } + else + break; + } + + if (CIRC_CNT(priv->pshare->rc_timer_head, priv->pshare->rc_timer_tail, RC_TIMER_NUM)) { + timeout = priv->pshare->rc_timer[priv->pshare->rc_timer_tail].timeout; + if (TSF_LESS(timeout, jiffies) || (timeout == jiffies)) { + if (timer_pending(&priv->pshare->rc_sys_timer)) + del_timer(&priv->pshare->rc_sys_timer); +#ifdef SMP_SYNC + spin_unlock(&priv->rc_packet_q_lock); +#endif + reorder_ctrl_timeout((unsigned long)priv); +#ifdef SMP_SYNC + spin_lock(&priv->rc_packet_q_lock); +#endif + } + } + } + + current_idx = priv->pshare->rc_timer_head; + + while (CIRC_CNT(current_idx, priv->pshare->rc_timer_tail, RC_TIMER_NUM)) { + if (priv->pshare->rc_timer[priv->pshare->rc_timer_tail].pstat == NULL) { + priv->pshare->rc_timer_tail = (priv->pshare->rc_timer_tail + 1) & (RC_TIMER_NUM - 1); + new_timer = 1; + } + else + break; + } + + if (CIRC_CNT(current_idx, priv->pshare->rc_timer_tail, RC_TIMER_NUM) == 0) { + if (timer_pending(&priv->pshare->rc_sys_timer)) + del_timer(&priv->pshare->rc_sys_timer); + setup_timer = 1; + } + else if (CIRC_SPACE(current_idx, priv->pshare->rc_timer_tail, RC_TIMER_NUM) == 0) { + DEBUG_ERR("%s: %s, RC timer overflow!\n", priv->dev->name, __FUNCTION__ ); + return -1; + } + else { // some items in timer queue + setup_timer = 0; + if (new_timer) + new_timer = priv->pshare->rc_timer[priv->pshare->rc_timer_tail].timeout; + } + + next_idx = (current_idx + 1) & (RC_TIMER_NUM - 1); + + priv->pshare->rc_timer[current_idx].priv = priv; + priv->pshare->rc_timer[current_idx].pstat = pstat; + priv->pshare->rc_timer[current_idx].tid = (unsigned char)tid; + priv->pshare->rc_timer_head = next_idx; + + now = jiffies; + timeout = now + priv->pshare->rc_timer_tick; + priv->pshare->rc_timer[current_idx].timeout = timeout; + sys_tick = priv->pshare->rc_timer_tick; + + if (!from_timeout) { + if (setup_timer) { + mod_timer(&priv->pshare->rc_sys_timer, jiffies + sys_tick); + } + else if (new_timer) { + if (TSF_LESS(new_timer, now)) { + mod_timer(&priv->pshare->rc_sys_timer, jiffies + sys_tick); + } + else { + sys_tick = TSF_DIFF(new_timer, now); + if (sys_tick < 1) + sys_tick = 1; + mod_timer(&priv->pshare->rc_sys_timer, jiffies + sys_tick); + } + } + } + + return current_idx; +} + + +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +void reorder_ctrl_timeout(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned int timeout, current_time; + struct reorder_ctrl_entry *rc_entry=NULL; + struct rtl8192cd_priv *priv_this=NULL; + struct stat_info *pstat; + int win_start=0, win_size, win_end, head, tid=0, sys_tick; + unsigned long flags; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) + return ; +#endif + + SAVE_INT_AND_CLI(flags); + SMP_LOCK_REORDER_CTRL(flags); + + current_time = jiffies; + + head = priv->pshare->rc_timer_head; + win_size = priv->pmib->reorderCtrlEntry.ReorderCtrlWinSz; + + while (CIRC_CNT(head, priv->pshare->rc_timer_tail, RC_TIMER_NUM)) + { + pstat = priv->pshare->rc_timer[priv->pshare->rc_timer_tail].pstat; + if (pstat) { + timeout = priv->pshare->rc_timer[priv->pshare->rc_timer_tail].timeout; + if (TSF_LESS(timeout, current_time) || (TSF_DIFF(timeout, current_time) <= RTL_MILISECONDS_TO_JIFFIES(10))) { + priv_this = priv->pshare->rc_timer[priv->pshare->rc_timer_tail].priv; + tid = priv->pshare->rc_timer[priv->pshare->rc_timer_tail].tid; + rc_entry = &pstat->rc_entry[tid]; + win_start = rc_entry->win_start; + win_end = (win_start + win_size) & 0xfff; + priv->pshare->rc_timer[priv->pshare->rc_timer_tail].pstat = NULL; + } + else { + sys_tick = TSF_DIFF(timeout, current_time); + if (sys_tick < 1) + sys_tick = 1; + mod_timer(&priv->pshare->rc_sys_timer, jiffies + sys_tick); + + if (TSF_LESS(timeout, current_time)) + DEBUG_ERR("Setup RC timer %d too late (now %d)\n", timeout, current_time); + + RESTORE_INT(flags); + SMP_UNLOCK_REORDER_CTRL(flags); + return; + } + } + + priv->pshare->rc_timer_tail = (priv->pshare->rc_timer_tail + 1) & (RC_TIMER_NUM - 1); + + if (pstat) { + while (!(rc_entry->packet_q[win_start & (win_size - 1)])) + win_start = SN_NEXT(win_start); + + while (rc_entry->packet_q[win_start & (win_size - 1)]) { + reorder_ctrl_pktout(priv_this, rc_entry->packet_q[win_start & (win_size - 1)], pstat); + rc_entry->packet_q[win_start & (win_size - 1)] = NULL; +#ifdef _DEBUG_RTL8192CD_ + pstat->rx_rc_passupi++; +#endif + win_start = SN_NEXT(win_start); + } + + rc_entry->win_start = win_start; + + if (SN_LESS(win_start, rc_entry->last_seq) || (win_start == rc_entry->last_seq)) { + rc_entry->rc_timer_id = reorder_ctrl_timer_add(priv_this, pstat, tid, 1) + 1; + if (rc_entry->rc_timer_id == 0) + reorder_ctrl_consumeQ(priv_this, pstat, tid, 0); + } + else { + rc_entry->start_rcv = FALSE; + rc_entry->rc_timer_id = 0; + } + } + } + + if (CIRC_CNT(priv->pshare->rc_timer_head, priv->pshare->rc_timer_tail, RC_TIMER_NUM)) { + sys_tick = (priv->pshare->rc_timer[priv->pshare->rc_timer_tail].timeout - current_time); + if (sys_tick < 1) + sys_tick = 1; + mod_timer(&priv->pshare->rc_sys_timer, jiffies + sys_tick); + + if (TSF_LESS(priv->pshare->rc_timer[priv->pshare->rc_timer_tail].timeout, current_time)) + DEBUG_ERR("Setup RC timer %d too late (now %d)\n", priv->pshare->rc_timer[priv->pshare->rc_timer_tail].timeout, current_time); + } + RESTORE_INT(flags); + SMP_UNLOCK_REORDER_CTRL(flags); +} + + +/* ==================================================================================== + segment 1 2 3 4 + -----------------+--------------------------------+------------------------- + win_start win_end + +--------------------------------+ + win_size + + segment 1: drop this packet + segment 2: indicate this packet, then indicate the following packets until a hole + segment 3: queue this packet in corrosponding position + segment 4: indicate queued packets until SN_DIFF(seq, win_start)seq; + tid = pfrinfo->tid; + rc_entry = &pstat->rc_entry[tid]; + win_start = rc_entry->win_start; + win_size = priv->pmib->reorderCtrlEntry.ReorderCtrlWinSz; + win_end = (win_start + win_size) & 0xfff; + + if (!pfrinfo->paggr && (rc_entry->start_rcv == FALSE)) + { + SMP_UNLOCK_REORDER_CTRL(flags); + return TRUE; + } + + if (rc_entry->start_rcv == FALSE) + { + rc_entry->start_rcv = TRUE; + rc_entry->win_start = SN_NEXT(seq); + rc_entry->last_seq = seq; + SMP_UNLOCK_REORDER_CTRL(flags); + return TRUE; + } + else + { + segment = check_win_seqment(win_start, win_end, seq); + if (segment == 1) { + SMP_UNLOCK_REORDER_CTRL(flags); +#ifdef _DEBUG_RTL8192CD_ + pstat->rx_rc_drop1++; +#endif + //priv->ext_stats.rx_data_drops++; + //DEBUG_ERR("RX DROP: skb behind the window\n"); + //rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + //return FALSE; + return TRUE; + } + else if (segment == 2) { + reorder_ctrl_pktout(priv, pfrinfo->pskb, pstat); + win_start = SN_NEXT(win_start); + while (rc_entry->packet_q[win_start & (win_size - 1)]) { + reorder_ctrl_pktout(priv, rc_entry->packet_q[win_start & (win_size - 1)], pstat); + rc_entry->packet_q[win_start & (win_size - 1)] = NULL; + win_start = SN_NEXT(win_start); +#ifdef _DEBUG_RTL8192CD_ + pstat->rx_rc_passup2++; +#endif + } + rc_entry->win_start = win_start; + if (SN_LESS(rc_entry->last_seq, seq)) + rc_entry->last_seq = seq; + + if (rc_entry->rc_timer_id) + priv->pshare->rc_timer[rc_entry->rc_timer_id - 1].pstat = NULL; + if (SN_LESS(rc_entry->last_seq, win_start)) + rc_entry->rc_timer_id = 0; + else { + rc_entry->rc_timer_id = reorder_ctrl_timer_add(priv, pstat, tid, 0) + 1; + if (rc_entry->rc_timer_id == 0) + reorder_ctrl_consumeQ(priv, pstat, tid, 2); + } + SMP_UNLOCK_REORDER_CTRL(flags); + return FALSE; + } + else if (segment == 3) { + index = seq & (win_size - 1); + if (rc_entry->packet_q[index]) { + SMP_UNLOCK_REORDER_CTRL(flags); +#ifdef _DEBUG_RTL8192CD_ + pstat->rx_rc_drop3++; +#endif + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: skb already in rc queue\n"); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + return FALSE; + } + else { + rc_entry->packet_q[index] = pfrinfo->pskb; +#ifdef _DEBUG_RTL8192CD_ + pstat->rx_rc_reorder3++; +#endif + } + if (SN_LESS(rc_entry->last_seq, seq)) + rc_entry->last_seq = seq; + if (rc_entry->rc_timer_id == 0) { + rc_entry->rc_timer_id = reorder_ctrl_timer_add(priv, pstat, tid, 0) + 1; + if (rc_entry->rc_timer_id == 0) + reorder_ctrl_consumeQ(priv, pstat, tid, 3); + } + SMP_UNLOCK_REORDER_CTRL(flags); + return FALSE; + } + else { // (segment == 4) + while ((SN_DIFF(seq, win_start) >= win_size) || (rc_entry->packet_q[win_start & (win_size - 1)])) { + if (rc_entry->packet_q[win_start & (win_size - 1)]) { + reorder_ctrl_pktout(priv, rc_entry->packet_q[win_start & (win_size - 1)], pstat); + rc_entry->packet_q[win_start & (win_size - 1)] = NULL; +#ifdef _DEBUG_RTL8192CD_ + pstat->rx_rc_passup4++; +#endif + } + win_start = SN_NEXT(win_start); + } + rc_entry->win_start = win_start; + + index = seq & (win_size - 1); + if (rc_entry->packet_q[index]) { +#ifdef _DEBUG_RTL8192CD_ + pstat->rx_rc_drop4++; +#endif + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: skb already in rc queue\n"); + rtl_kfree_skb(priv, rc_entry->packet_q[index], _SKB_RX_); + } + + rc_entry->packet_q[index] = pfrinfo->pskb; +#ifdef _DEBUG_RTL8192CD_ + pstat->rx_rc_reorder4++; +#endif + rc_entry->last_seq = seq; + if (rc_entry->rc_timer_id) + priv->pshare->rc_timer[rc_entry->rc_timer_id - 1].pstat = NULL; + rc_entry->rc_timer_id = reorder_ctrl_timer_add(priv, pstat, tid, 0) + 1; + if (rc_entry->rc_timer_id == 0) + reorder_ctrl_consumeQ(priv, pstat, tid, 4); + SMP_UNLOCK_REORDER_CTRL(flags); + return FALSE; + } + } +} + + +#ifdef RX_SHORTCUT +/*--------------------------------------------------------------- + return value: + TRUE: MIC ok + FALSE: MIC error +----------------------------------------------------------------*/ +static int wait_mic_done_and_compare(unsigned char *org_mic, unsigned char *tkipmic) +{ +#ifdef NOT_RTK_BSP + return TRUE; +#else + register unsigned long int l,r; + int delay = 20; + + while ((*(volatile unsigned int *)GDMAISR & GDMA_COMPIP) == 0) { + delay_us(delay); + delay = delay / 2; + } + + l = *(volatile unsigned int *)GDMAICVL; + r = *(volatile unsigned int *)GDMAICVR; + + tkipmic[0] = (unsigned char)(l & 0xff); + tkipmic[1] = (unsigned char)((l >> 8) & 0xff); + tkipmic[2] = (unsigned char)((l >> 16) & 0xff); + tkipmic[3] = (unsigned char)((l >> 24) & 0xff); + tkipmic[4] = (unsigned char)(r & 0xff); + tkipmic[5] = (unsigned char)((r >> 8) & 0xff); + tkipmic[6] = (unsigned char)((r >> 16) & 0xff); + tkipmic[7] = (unsigned char)((r >> 24) & 0xff); + + return (memcmp(org_mic, tkipmic, 8) ? FALSE : TRUE); +#endif // NOT_RTK_BSP +} + + +__MIPS16 +__IRAM_IN_865X +int get_rx_sc_index(struct stat_info *pstat, unsigned char *pframe) +{ + struct rx_sc_entry *prxsc_entry; + int i; + + prxsc_entry = pstat->rx_sc_ent; + + for (i=0; i= 0) + return i; + + prxsc_entry = pstat->rx_sc_ent; + + for (i=0; irx_sc_replace_idx; + pstat->rx_sc_replace_idx = (++pstat->rx_sc_replace_idx) % RX_SC_ENTRY_NUM; + return i; +} +inline unsigned char sta_packet_number_check(struct rtl8192cd_priv *priv, union PN48 *last_RxPN, unsigned char *pframe, unsigned int hdr_len) +{ + int ret = SUCCESS; + union PN48 rxPN; + + if(!GetPrivacy(pframe)) { + return FAIL; + } + + rxPN.val48 = 0; + rxPN._byte_.TSC0 = pframe[hdr_len]; + rxPN._byte_.TSC1 = pframe[hdr_len+1]; + rxPN._byte_.TSC2 = pframe[hdr_len+4]; + rxPN._byte_.TSC3 = pframe[hdr_len+5]; + rxPN._byte_.TSC4 = pframe[hdr_len+6]; + rxPN._byte_.TSC5 = pframe[hdr_len+7]; + + if((last_RxPN->val48 + 1) != rxPN.val48) { + ret = FAIL; + } else { + last_RxPN->val48 = rxPN.val48; + } + + return ret; +} + +#ifndef RTK_NL80211 +const unsigned char rfc1042_header[WLAN_LLC_HEADER_SIZE]={0xaa,0xaa,0x03,00,00,00}; +#else +//For OpenWRT, rfc1042_header is defined at compat-wireless/net/wireless/util.c +extern const unsigned char rfc1042_header[]; +#endif +/*--------------------------------------------------------------- + return value: + 0: shortcut ok, rx data has passup + 1: discard this packet + -1: can't do shortcut, data path should be continued + ---------------------------------------------------------------*/ +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +int rx_shortcut(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ +// unsigned long flags=0; + struct stat_info *pstat, *dst_pstat; + int privacy, tkip_mic_ret=0; + int payload_length, offset, pos=0, do_rc=0, idx; + struct wlan_ethhdr_t *e_hdr; + unsigned char rxmic[8], tkipmic[8]; + struct sk_buff skb_copy; + unsigned char wlanhdr_copy[sizeof(struct wlanllc_hdr)]; + unsigned char *pframe = get_pframe(pfrinfo); + unsigned char da[MACADDRLEN]; + unsigned short tpcache=0; + +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + struct path_sel_entry *pEntry = NULL; + struct MESH_HDR *meshHdrPt; + unsigned char meshDest[MACADDRLEN]; +#endif + struct rx_sc_entry *prxsc_entry = NULL; + unsigned char is_qos_datafrm=0; + +#ifdef HW_FILL_MACID //eric-8814 + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + if(!pstat) + pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + } + else +#endif + pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + + is_qos_datafrm = is_qos_data(pframe); + + +#if defined(CONFIG_RTK_MESH) && !defined(RX_RL_SHORTCUT) + + // RTK mesh doesn't support shortcut now -- chris 071909. + if (GET_MIB(priv)->dot1180211sInfo.mesh_enable) + goto shouldnot_rxsc; +#endif + +#if 0 // already flush cache in rtl8192cd_rx_isr() +#ifndef RTL8190_CACHABLE_CLUSTER +#ifdef __MIPSEB__ + pframe = (UINT8 *)((unsigned long)pframe | 0x20000000); +#endif +#endif +#endif + + if (priv->pmib->dot11OperationEntry.guest_access +#ifdef CONFIG_RTL8186_KB + ||(pstat && pstat->ieee8021x_ctrlport == DOT11_PortStatus_Guest) +#endif + ) + goto shouldnot_rxsc; + + if (pstat && ((idx = get_rx_sc_index(pstat, pframe)) >= 0)) + prxsc_entry = &pstat->rx_sc_ent[idx]; + + if ((NULL != prxsc_entry) && + prxsc_entry->rx_payload_offset && + (GetFragNum(pframe) == 0) && (GetMFrag(pframe) == 0)) + { + privacy = GetPrivacy(pframe); + memcpy(da, pfrinfo->da, MACADDRLEN); + + tpcache = GetTupleCache(pframe); +#ifdef CLIENT_MODE + if (IS_MCAST(da)) + { + if (tpcache == pstat->tpcache_mcast) + { + priv->ext_stats.rx_decache++; + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + SNMP_MIB_INC(dot11FrameDuplicateCount, 1); + return 0; + } + } + else +#endif + if (is_qos_datafrm) { + pos = GetSequence(pframe) & (TUPLE_WINDOW - 1); + if (tpcache == pstat->tpcache[pfrinfo->tid][pos]) { + priv->ext_stats.rx_decache++; + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + SNMP_MIB_INC(dot11FrameDuplicateCount, 1); + return 0; + } + } + else { + if (GetRetry(pframe)) { + if (tpcache == pstat->tpcache_mgt) { + priv->ext_stats.rx_decache++; + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + SNMP_MIB_INC(dot11FrameDuplicateCount, 1); + return 0; + } + } + } + + // check wlan header + if (pstat->rx_privacy == privacy) + { + +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + if (pfrinfo->is_11s) { + if(mesh_shortcut_update(priv, pfrinfo, pstat, idx, &pEntry, &meshHdrPt) != 0) { + goto shouldnot_rxsc; + } + + if(pEntry == NULL) { + memcpy(meshDest, meshHdrPt->DestMACAddr, MACADDRLEN);/*backup mesh addr5 */ + } + pfrinfo->pskb->dev = priv->mesh_dev; + } + else + +#endif //CONFIG_RTK_MESH + +#ifdef WDS + if (pfrinfo->to_fr_ds == 3 +#ifdef CONFIG_RTK_MESH + && priv->pmib->dot11WdsInfo.wdsEnabled +#endif + ) { + if (memcmp(GetAddr4Ptr(pframe), prxsc_entry->rx_wlanhdr.addr4, 6)) + goto shouldnot_rxsc; + pfrinfo->pskb->dev = getWdsDevByAddr(priv, GetAddr2Ptr(pframe)); + } + else +#endif + +#ifdef A4_STA + if (pfrinfo->to_fr_ds == 3 && (pstat->state & WIFI_A4_STA)) { + if (memcmp(GetAddr4Ptr(pframe), prxsc_entry->rx_wlanhdr.addr4, 6)) + goto shouldnot_rxsc; + a4_sta_add(priv, pstat, GetAddr4Ptr(pframe)); + } +#endif + pfrinfo->pskb->dev = priv->dev; + + offset = prxsc_entry->rx_payload_offset + sizeof(rfc1042_header); + +/* + printk("pstat->rx_payload_offset = %02x, 0xaa, cmp = %d \n",pframe[prxsc_entry->rx_payload_offset], + memcmp(&pframe[prxsc_entry->rx_payload_offset], rfc1042_header, 6)); + printk("pstat->rx_ethhdr.type = %02x, pframe[offset] = %02x, cmp= %d \n", prxsc_entry->rx_ethhdr.type, pframe[offset], + memcmp(&prxsc_entry->rx_ethhdr.type,&pframe[offset], 2)); +*/ + // check snap header + if (memcmp(&pframe[prxsc_entry->rx_payload_offset], rfc1042_header, 6) || + memcmp(&prxsc_entry->rx_ethhdr.type,&pframe[offset], 2)) + goto shouldnot_rxsc; + + payload_length = pfrinfo->pktlen - offset - prxsc_entry->rx_trim_pad - 2; + if (payload_length < WLAN_ETHHDR_LEN) + goto shouldnot_rxsc; + + if (privacy) + { + +#ifdef WDS + if (pfrinfo->to_fr_ds == 3 +#ifdef CONFIG_RTK_MESH + && priv->pmib->dot11WdsInfo.wdsEnabled +#endif + ) + privacy = priv->pmib->dot11WdsInfo.wdsPrivacy; + + else +#endif + privacy = get_sta_encrypt_algthm(priv, pstat); + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (privacy==_WAPI_SMS4_) + { + /* Decryption */ + if (SecSWSMS4Decryption(priv, pstat, pfrinfo) == FAIL) + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: WAPI decrpt error!\n"); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + return 1; + } + pframe = get_pframe(pfrinfo); + } + else +#endif + { + if (privacy == _TKIP_PRIVACY_) + { + memcpy((void *)rxmic, (void *)(pframe + pfrinfo->pktlen - 8 - 4), 8); // 8 michael, 4 icv + //SAVE_INT_AND_CLI(flags); + tkip_mic_ret = tkip_rx_mic(priv, pframe, pfrinfo->da, pfrinfo->sa, + pfrinfo->tid, pframe + pfrinfo->hdr_len + 8, + pfrinfo->pktlen - pfrinfo->hdr_len - 8 - 8 - 4, tkipmic, 1); // 8 IV, 8 Mic, 4 ICV + if (tkip_mic_ret) { // MIC completed + //RESTORE_INT(flags); + if (memcmp(rxmic, tkipmic, 8)) { + goto shouldnot_rxsc; + } + } + else { + memcpy(&skb_copy, pfrinfo->pskb, sizeof(skb_copy)); + memcpy(wlanhdr_copy, pframe, sizeof(wlanhdr_copy)); + } + } + } + } + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + priv->pmib->reorderCtrlEntry.ReorderCtrlEnable) { + if (!IS_MCAST(GetAddr1Ptr(pframe))) + do_rc = 1; + } + + rx_sum_up(NULL, pstat, pfrinfo->pktlen, 0); + pstat->rx_sc_pkts++; + + priv->pshare->NumRxBytesUnicast += pfrinfo->pktlen; + + update_sta_rssi(priv, pstat, pfrinfo); + +#ifdef DETECT_STA_EXISTANCE +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if (pstat->leave!= 0) + RTL8188E_MACID_NOLINK(priv, 0, REMAP_AID(pstat)); + } +#endif + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if (pstat->leave!= 0) + { +#if defined(CONFIG_PCI_HCI) + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); + pstat->bDrop = 0; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_update_sta_msr(priv, pstat, INCREASE); +#endif + } + pstat->rx_last_good_time = priv->up_time; + } +#endif //#ifdef CONFIG_WLAN_HAL + + pstat->leave = 0; +#endif + + //printk("RXSC\n"); + +#ifdef SUPPORT_SNMP_MIB + if (IS_MCAST(da)) + SNMP_MIB_INC(dot11MulticastReceivedFrameCount, 1); +#endif + + /* chop 802.11 header from skb. */ + //skb_put(pfrinfo->pskb, pfrinfo->pktlen); // pskb->tail will be wrong + pfrinfo->pskb->tail = pfrinfo->pskb->data + pfrinfo->pktlen; + pfrinfo->pskb->len = pfrinfo->pktlen; + + skb_pull(pfrinfo->pskb, offset+2); + +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + + if (pfrinfo->is_11s && pEntry == NULL) { + skb_pull(pfrinfo->pskb, 16); //because we guarantee only 6 address frame enters shortcut + payload_length -= 16; + } +#endif + + e_hdr = (struct wlan_ethhdr_t *)skb_push(pfrinfo->pskb, WLAN_ETHHDR_LEN); + memcpy((unsigned char *)e_hdr, (unsigned char *)&prxsc_entry->rx_ethhdr, sizeof(struct wlan_ethhdr_t)); + /* chop off the 802.11 CRC */ + + skb_trim(pfrinfo->pskb, payload_length + WLAN_ETHHDR_LEN); + + + //printk("RXSC skb_pull offset+2 = %d\n", offset+2); + //printk("RXSC pstat->rx_ethhdr dest= %02x\n", e_hdr->daddr[5]); + //printk("RXSC pstat->rx_ethhdr src = %02x\n", e_hdr->saddr[5]); + + if ((privacy == _TKIP_PRIVACY_) && (tkip_mic_ret == FALSE)) { + if (wait_mic_done_and_compare(rxmic, tkipmic) == FALSE) { +// RESTORE_INT(flags); + memcpy(pfrinfo->pskb, &skb_copy, sizeof(skb_copy)); + memcpy(pframe, wlanhdr_copy, sizeof(wlanhdr_copy)); + goto shouldnot_rxsc; + } +// RESTORE_INT(flags); + } + +#ifdef CLIENT_MODE + if (IS_MCAST(da)) + pstat->tpcache_mcast = tpcache; + else +#endif + if (is_qos_datafrm) + pstat->tpcache[pfrinfo->tid][pos] = tpcache; + else + pstat->tpcache_mgt = tpcache; + + if (OPMODE & WIFI_AP_STATE) + { + +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + pfrinfo->pskb->cb[3] = 0; + if (pfrinfo->is_11s ) {/* from wlan0-msh0*/ + if(pEntry) {/* to wlan0-msh0*/ + meshHdrPt->TTL--; + if(1 > meshHdrPt->TTL) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: TTL=0\n"); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + return 0; + } + dst_pstat = get_stainfo(pEntry->priv, pEntry->nexthopMAC); + if(dst_pstat) { + if (do_rc) { + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = dst_pstat; + pfrinfo->pskb->cb[3] = RELAY_11S; + pfrinfo->pskb->dev = pEntry->priv->dev; /*temprarily save the priv to nexthop*/ + if (reorder_ctrl_check(priv, pstat, pfrinfo) == FALSE) { + do_rc = 0; + } + } else { + do_rc = 1; + } + + + if(do_rc) { + struct tx_insn txcfg; + txcfg.priv = pEntry->priv; + txcfg.is_11s = RELAY_11S; + pfrinfo->pskb->dev = priv->mesh_dev; +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + __rtl8192cd_start_xmit_out(pfrinfo->pskb, dst_pstat, &txcfg); + } + return 0; + } + } + else { /*to wlan0 or eth0*/ + dst_pstat = get_stainfo(priv, meshDest);/*mesh addr5*/ + } + } + else { /*from wlan0*/ + dst_pstat = get_stainfo(priv, da); + if(dst_pstat == NULL) { + int index = 0; + #ifdef CONFIG_RTL_MESH_CROSSBAND + index = (priv->dev->name[4] == '0')?1:0; + #endif + if(cached_mesh_dev[index] && !memcmp(da, cached_mesh_mac[index], MACADDRLEN)) {/*to wlan0-msh0*/ + #ifdef CONFIG_RTL_MESH_CROSSBAND + pfrinfo->pskb->dev = priv->mesh_priv_sc->dev; + #else + pfrinfo->pskb->dev = priv->mesh_priv_first->dev; + #endif + + if (do_rc) { + pfrinfo->pskb->cb[4] = 1; + pfrinfo->pskb->cb[3] = XMIT_11S; + if (reorder_ctrl_check(priv, pstat, pfrinfo) == FALSE) { + do_rc = 0; + } + } + else + do_rc = 1; + + if(do_rc) { + DECLARE_TXINSN(txcfg); + if(dot11s_datapath_decision(pfrinfo->pskb, &txcfg, 1) != 0) { + dst_pstat = get_stainfo(txcfg.priv, txcfg.nhop_11s); + pfrinfo->pskb->dev = priv->mesh_dev; +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + __rtl8192cd_start_xmit_out(pfrinfo->pskb, dst_pstat, &txcfg); + } + } + return 0; + } + } + } +#else + dst_pstat = get_stainfo(priv, da); +#endif + + + +#ifdef A4_STA + if (priv->pshare->rf_ft_var.a4_enable && (dst_pstat == NULL)) + dst_pstat = a4_sta_lookup(priv, da); +#endif + + + +#if defined(WDS) + if ((pfrinfo->to_fr_ds==3 +#ifdef CONFIG_RTK_MESH + && priv->pmib->dot11WdsInfo.wdsEnabled +#endif + ) || + (dst_pstat == NULL) || !(dst_pstat->state & WIFI_ASOC_STATE)) +#else + if ((dst_pstat == NULL) || (!(dst_pstat->state & WIFI_ASOC_STATE))) +#endif + { + if (do_rc) { + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = 0; + if (reorder_ctrl_check(priv, pstat, pfrinfo)) { + rtl_netif_rx(priv, pfrinfo->pskb, pstat); + } + } + else + rtl_netif_rx(priv, pfrinfo->pskb, pstat); + } +#ifdef HS2_SUPPORT + /* Hotspot 2.0 Release 1 */ + else if (priv->pmib->dot11OperationEntry.block_relay == 3) { // with l2_inspect + unsigned short protocol; + + HS2_DEBUG_INFO("%s block_relay=3\n"); + if(IS_ICMPV4_PROTO(pfrinfo->pskb->data)) { + if(IS_ICMPV4_ECHO_TYPE(pfrinfo->pskb->data)) { + if(priv->pmib->hs2Entry.ICMPv4ECHO == 2) { + memcpy(&pfrinfo->pskb->data[0], priv->pmib->hs2Entry.redir_mac, 6); + HS2_DEBUG_INFO("redirect ICMPv4 Packet to connected portal\n"); + rtl_netif_rx(priv, pfrinfo->pskb, pstat); + } else if(priv->pmib->hs2Entry.ICMPv4ECHO == 0) { + HS2_DEBUG_INFO("Drop ICMPv4 Packet\n"); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + } + /* + else if(priv->pmib->hs2Entry.ICMPv4ECHO == 1) { + panic_printk("Allow ICMPv4 Echo Requests\n"); + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = (unsigned int)dst_pstat; // backup pstat pointer + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + if (rtl8192cd_start_xmit(pfrinfo->pskb, isMeshPoint(dst_pstat)? priv->mesh_dev: priv->dev)) +#else + if (rtl8192cd_start_xmit(pfrinfo->pskb, priv->dev)) +#endif + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_TX_); + } + */ + return 1; + } else { + //free + } + } else { + //free + } + } +#endif + else + { + if (priv->pmib->dot11OperationEntry.block_relay == 1) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Relay unicast packet is blocked in shortcut!\n"); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + return 1; + } + else if (priv->pmib->dot11OperationEntry.block_relay == 2) { + DEBUG_INFO("Relay unicast packet is blocked! Indicate to bridge in shortcut\n"); + rtl_netif_rx(priv, pfrinfo->pskb, pstat); + } + else { +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif +#ifdef GBWC + if (GBWC_forward_check(priv, pfrinfo->pskb, pstat)) { + // packet is queued, nothing to do + } + else +#endif + if (do_rc) { +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_rx_skb_cnt); +#endif + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = (unsigned int)dst_pstat; // backup pstat pointer + if (reorder_ctrl_check(priv, pstat, pfrinfo)) { +#ifdef TX_SCATTER + pfrinfo->pskb->list_num = 0; +#endif +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif + if (rtl8192cd_start_xmit(pfrinfo->pskb, priv->dev)) + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_TX_); + } + } + else { +#ifdef TX_SCATTER + pfrinfo->pskb->list_num = 0; +#endif + + if (rtl8192cd_start_xmit(pfrinfo->pskb, priv->dev)) + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_TX_); + } + } + } + return 0; + } +#ifdef CLIENT_MODE + else if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) { + priv->rxDataNumInPeriod++; + if (IS_MCAST(pfrinfo->pskb->data)) { + priv->rxMlcstDataNumInPeriod++; + } else if ((OPMODE & WIFI_STATION_STATE) && (priv->ps_state)) { + if ((GetFrameSubType(pframe) == WIFI_DATA) +#ifdef WIFI_WMM + ||(QOS_ENABLE && pstat->QosEnabled && (GetFrameSubType(pframe) == WIFI_QOS_DATA)) +#endif + ) { + if (GetMData(pframe)) { +#if defined(WIFI_WMM) && defined(WMM_APSD) + if (QOS_ENABLE && APSD_ENABLE && priv->uapsd_assoc) { + if (!((priv->pmib->dot11QosEntry.UAPSD_AC_BE && ((pfrinfo->tid == 0) || (pfrinfo->tid == 3))) || + (priv->pmib->dot11QosEntry.UAPSD_AC_BK && ((pfrinfo->tid == 1) || (pfrinfo->tid == 2))) || + (priv->pmib->dot11QosEntry.UAPSD_AC_VI && ((pfrinfo->tid == 4) || (pfrinfo->tid == 5))) || + (priv->pmib->dot11QosEntry.UAPSD_AC_VO && ((pfrinfo->tid == 6) || (pfrinfo->tid == 7))))) + issue_PsPoll(priv); + } else +#endif + { + issue_PsPoll(priv); + } + } + } + } + +#ifdef RTK_BR_EXT + if (!priv->pmib->ethBrExtInfo.nat25sc_disable && + !(pfrinfo->pskb->data[0] & 1) && + *((unsigned short *)(pfrinfo->pskb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_IP) && + !memcmp(priv->scdb_ip, pfrinfo->pskb->data+ETH_HLEN+16, 4)) { + memcpy(pfrinfo->pskb->data, priv->scdb_mac, ETH_ALEN); +#ifdef MULTI_MAC_CLONE + mclone_dhcp_caddr(priv, pfrinfo->pskb); +#endif + } + else + if(nat25_handle_frame(priv, pfrinfo->pskb) == -1) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: nat25_handle_frame fail in shortcut!\n"); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + return 1; + } +#endif + if (do_rc) { + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = 0; + if (reorder_ctrl_check(priv, pstat, pfrinfo)) + rtl_netif_rx(priv, pfrinfo->pskb, pstat); + } + else + rtl_netif_rx(priv, pfrinfo->pskb, pstat); + return 0; + } +#endif + else + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Non supported mode in process_datafrme in shortcut\n"); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + return 1; + } + } + } + +shouldnot_rxsc: + + if (pstat) + pstat->rx_sc_pkts_slow++; + return -1; +} +#endif // RX_SHORTCUT + + +#ifdef DRVMAC_LB +void lb_convert(struct rtl8192cd_priv *priv, unsigned char *pframe) +{ + unsigned char *addr1, *addr2, *addr3; + + if (get_tofr_ds(pframe) == 0x01) + { + SetToDs(pframe); + ClearFrDs(pframe); + addr1 = GetAddr1Ptr(pframe); + addr2 = GetAddr2Ptr(pframe); + addr3 = GetAddr3Ptr(pframe); + if (addr1[0] & 0x01) { + memcpy(addr3, addr1, 6); + memcpy(addr1, addr2, 6); + memcpy(addr2, priv->pmib->miscEntry.lb_da, 6); + } + else { + memcpy(addr1, addr2, 6); + memcpy(addr2, priv->pmib->miscEntry.lb_da, 6); + } + } +} +#endif + + +/* + Strip from "validate_mpdu()" + + 0: no reuse, allocate new skb due to the current is queued. + 1: reuse! due to error pkt or short pkt. +*/ +static int rtl8192cd_rx_procCtrlPkt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo +#ifdef MBSSID + ,int vap_idx +#endif + ) +{ + unsigned char *pframe = get_pframe(pfrinfo); + struct stat_info *pstat = NULL; + +#if defined(SMP_SYNC) + unsigned long x; +#endif + if (((GetFrameSubType(pframe)) != WIFI_PSPOLL) || + (pfrinfo->to_fr_ds != 0x00)) + return 1; + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable && (vap_idx >= 0)) + { + priv = priv->pvap_priv[vap_idx]; + if (!(OPMODE & WIFI_AP_STATE)) + return 1; + } + else +#endif + { + if (!(OPMODE & WIFI_AP_STATE)) { +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + priv = GET_VXD_PRIV(priv); + else + return 1; +#else + return 1; +#endif + } + } + + if (!IS_BSSID(priv, GetAddr1Ptr(pframe))) + return 1; + + +#ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + //printk("%s %d HW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } +#endif + if(!pstat) + { + pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + //printk("%s %d SW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + + // check power save state + + if (pstat != NULL) + { + #ifdef HW_DETEC_POWER_STATE + if (GET_CHIP_VER(priv) == VERSION_8814A) { + // 8813 power state control only by HW, not by SW. + // Only if HW detect macid not ready, SW patch this packet + if(pfrinfo->macid == HW_MACID_SEARCH_NOT_READY) + { + printk("%s %d HW_MACID_SEARCH_NOT_READY",__FUNCTION__,__LINE__); + if(priv->pshare->HWPwrStateUpdate[pstat->aid]==false) + { + printk("%s %d HW not update By SW Aid = %x \n",__FUNCTION__,__LINE__,pstat->aid); + pwr_state(priv, pfrinfo); + } + } + else if(pfrinfo->macid > HW_MACID_SEARCH_SUPPORT_NUM) + { + pwr_state(priv, pfrinfo); + } + } else + #endif // #ifdef HW_DETEC_POWER_STATE + { + pwr_state(priv, pfrinfo); + } + } else + return 1; + +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_ctrlframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_CTRL(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_ctrllist)); + SMP_UNLOCK_RX_CTRL(x); +#endif + return 0; +} + + +static int rtl8192cd_rx_procNullPkt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo +#ifdef MBSSID + ,int vap_idx +#endif + ) +{ + unsigned char *sa = pfrinfo->sa; + struct stat_info *pstat = NULL; + unsigned char *pframe = get_pframe(pfrinfo); +#ifdef SMP_SYNC + unsigned long x; +#endif + +#ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + //printk("%s %d HW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } +#endif + + if(!pstat) + { + pstat = get_stainfo(priv, sa); + //printk("%s %d SW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + +#ifdef UNIVERSAL_REPEATER + if ((pstat == NULL) && IS_DRV_OPEN(GET_VXD_PRIV(priv))) { + +#ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + //printk("%s %d HW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } +#endif + if(!pstat) + { + pstat = get_stainfo(GET_VXD_PRIV(priv), sa); + //printk("%s %d SW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + + if (pstat) + priv = GET_VXD_PRIV(priv); + } +#endif + +#ifdef MBSSID + if ((pstat == NULL) + && GET_ROOT(priv)->pmib->miscEntry.vap_enable + && (vap_idx >= 0)) { + +#ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + //printk("%s %d HW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } +#endif + if(!pstat) + { + pstat = get_stainfo(priv->pvap_priv[vap_idx], sa); + //printk("%s %d SW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + + if (pstat) + priv = priv->pvap_priv[vap_idx]; + } +#endif + + if (pstat && (pstat->state & WIFI_ASOC_STATE) + && (!(OPMODE & WIFI_AP_STATE) || IS_BSSID(priv, GetAddr1Ptr(pframe)))) { +#ifdef DRVMAC_LB + rx_sum_up(priv, pstat, pfrinfo->pktlen, 0); +#else + rx_sum_up(NULL, pstat, pfrinfo->pktlen, 0); +#endif + update_sta_rssi(priv, pstat, pfrinfo); + +#ifdef DETECT_STA_EXISTANCE +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if (pstat->leave!= 0) + RTL8188E_MACID_NOLINK(priv, 0, REMAP_AID(pstat)); + } +#endif +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if (pstat->leave!= 0) + { +#if defined(CONFIG_PCI_HCI) + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); + pstat->bDrop = 0; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_update_sta_msr(priv, pstat, INCREASE); +#endif + } + pstat->rx_last_good_time = priv->up_time; + } +#endif //#ifdef CONFIG_WLAN_HAL + + pstat->leave = 0; +#endif + + // check power save state +#ifndef DRVMAC_LB + if (OPMODE & WIFI_AP_STATE) { +#ifdef HW_DETEC_POWER_STATE + if (GET_CHIP_VER(priv) == VERSION_8814A) { + // 8813 power state control only by HW, not by SW. + // Only if HW detect macid not ready, SW patch this packet + if(pfrinfo->macid == HW_MACID_SEARCH_NOT_READY) + { + printk("%s %d HW_MACID_SEARCH_NOT_READY",__FUNCTION__,__LINE__); + if(priv->pshare->HWPwrStateUpdate[pstat->aid]==false) + { + printk("%s %d HW not update By SW Aid = %x \n",__FUNCTION__,__LINE__,pstat->aid); + pwr_state(priv, pfrinfo); + } + } + else if(pfrinfo->macid > HW_MACID_SEARCH_SUPPORT_NUM) + { + pwr_state(priv, pfrinfo); + } + } + else +#endif // #ifdef HW_DETEC_POWER_STATE + { + pwr_state(priv, pfrinfo); + } + } +#endif + } + +#ifdef MULTI_MAC_CLONE + int idx = mclone_find_address(priv, pfrinfo->sa, NULL, MAC_CLONE_SA_FIND); + if (idx >= 0) + { + struct rtl8192cd_priv *priv_backup; + struct stat_info *pstat_backup; + priv_backup = priv; + pstat_backup = pstat; + priv = priv->pshare->mclone_sta[idx-1].priv; + pstat = get_stainfo(priv, BSSID); + if (pstat) + { + ACTIVE_ID = idx; + issue_NullData(priv, pstat->hwaddr); + } + priv = priv_backup; + pstat = pstat_backup; + } +#endif + +#if defined(WIFI_WMM) && defined(WMM_APSD) + if ((QOS_ENABLE) +#ifndef DRVMAC_LB + && (APSD_ENABLE) +#endif + && (OPMODE & WIFI_AP_STATE) && pstat +#ifndef DRVMAC_LB + && (pstat->state & WIFI_SLEEP_STATE) +#endif + && (pstat->QosEnabled) +#ifndef DRVMAC_LB + && (pstat->apsd_bitmap & 0x0f) +#endif + && ((GetFrameSubType(pframe)) == (WIFI_DATA_NULL | BIT(7)))) { + unsigned char *bssid = GetAddr1Ptr(pframe); + if (IS_BSSID(priv, bssid)) + { +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_datalist)); + SMP_UNLOCK_RX_DATA(x); +#endif + return 0; + } + } +#endif + + /* special case for mobile wifi. the mobile insleep will send + null data to AP after AP's reboot. if not deauthed, the client will not reconnect */ + if (pstat == NULL) { + if (OPMODE & WIFI_AP_STATE) + issue_deauth(priv,GetAddr2Ptr(pframe), _RSON_UNSPECIFIED_); + return 1; + } + + // for AR5007 IOT ISSUE + if ((!GetPwrMgt(pframe)) && (GetTupleCache(pframe) == 0) // because this is special case for AR5007, so use GetTupleCache with Seq-Num and Frag-Num, GetSequenceis also ok + && (OPMODE & WIFI_AP_STATE) && (IS_BSSID(priv, GetAddr1Ptr(pframe))) + && (((GetFrameSubType(pframe)) == WIFI_DATA_NULL) +#ifdef WIFI_WMM + || ((QOS_ENABLE) && ((GetFrameSubType(pframe)) == (WIFI_DATA_NULL | BIT(7)))) +#endif + ) + ) { +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_datalist)); + SMP_UNLOCK_RX_DATA(x); +#endif + DEBUG_INFO("special Null Data in%d \n", pfrinfo->tid); + return 0; + } + + return 1; +} + + +// for AR5007 IOT ISSUE +static void rtl8192cd_rx_handle_Spec_Null_Data(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *sa; + struct stat_info *pstat = NULL; + unsigned char *pframe = get_pframe(pfrinfo); +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + sa = pfrinfo->sa; + + #ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + //printk("%s %d HW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + #endif + + if(!pstat) + { + pstat = get_stainfo(priv, sa); + //printk("%s %d SW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + + if (pstat==NULL) { + goto out; + } + + pframe = get_pframe(pfrinfo); + if ((!GetPwrMgt(pframe)) && (GetTupleCache(pframe) == 0) // because this is special case for AR5007, so use GetTupleCache with Seq-Num and Frag-Num, GetSequenceis also ok + && (OPMODE & WIFI_AP_STATE) && (IS_BSSID(priv, GetAddr1Ptr(pframe)))) + { + int i,j; + + DEBUG_INFO("tpcache should be reset: %d\n", pfrinfo->tid); + for (i=0; i<8; i++) + for (j=0; jtpcache[i][j] = 0xffff; + } +out: + RESTORE_INT(flags); +} + + +#ifdef RTK_NL80211 // wrt-adhoc +#ifdef UNIVERSAL_REPEATER +unsigned char is_vxd_bssid(struct rtl8192cd_priv *priv, unsigned char *bssid) +{ + struct rtl8192cd_priv * priv_root = NULL; + struct rtl8192cd_priv * priv_vxd = NULL; + unsigned char ret = 0; + + if(!IS_VXD_INTERFACE(priv)) + { + priv_root = GET_ROOT(priv); + priv_vxd = GET_VXD_PRIV(priv_root); + } + + if((netif_running(priv_vxd->dev)) && + (priv_vxd->pmib->dot11OperationEntry.opmode & WIFI_ADHOC_STATE)) + { + if(!memcmp(bssid, priv_vxd->pmib->dot11StationConfigEntry.dot11Bssid, 6)) + ret = 1; + } + + return ret; + +} +#endif +#endif + +/* + Check the "to_fr_ds" field: + + FromDS = 0 + ToDS = 0 +*/ +static int rtl8192cd_rx_dispatch_mgmt_adhoc(struct rtl8192cd_priv **priv_p, struct rx_frinfo *pfrinfo +#ifdef MBSSID + ,int vap_idx +#endif + ) +{ + int reuse = 1; + struct rtl8192cd_priv *priv = *priv_p; + unsigned int opmode = OPMODE; + unsigned char *pframe = get_pframe(pfrinfo); + int retry=GetRetry(pframe);/*in case of skb has been freed*/ + unsigned int frtype = GetFrameType(pframe); + unsigned char *da = pfrinfo->da; + unsigned char *bssid = GetAddr3Ptr(pframe); + unsigned short frame_type = GetFrameSubType(pframe); +#ifdef MBSSID + int i; +#endif + +#if defined(SMP_SYNC) + unsigned long x; +#endif + if ((GetMFrag(pframe)) && (frtype == WIFI_MGT_TYPE)) + goto out; + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + // If mgt packet & (beacon or prob-rsp), put in root interface Q + // then it will be handled by root & virtual interface + // If mgt packet & (prob-req), put in AP interface Q + // If mgt packet & (others), check BSSID (addr3) for matched interface + + if (frtype == WIFI_MGT_TYPE) { + int vxd_interface_ready=1, vap_interface_ready=0; + +#ifdef UNIVERSAL_REPEATER + if (!IS_DRV_OPEN(GET_VXD_PRIV(priv)) || + ((opmode & WIFI_STATION_STATE) && !(GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED))) + vxd_interface_ready = 0; +#endif + +#ifdef MBSSID +// if (opmode & WIFI_AP_STATE) { + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + vap_interface_ready = 1; + } + } +// } +#endif + + if (!vxd_interface_ready && !vap_interface_ready) + goto put_in_que; + +#if 0 + if (frame_type == WIFI_BEACON || frame_type == WIFI_PROBERSP) { + pfrinfo->is_br_mgnt = 1; + goto put_in_que; + } +#endif + + if (frame_type == WIFI_PROBEREQ) { +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + if (vap_interface_ready) { + pfrinfo->is_br_mgnt = 1; + goto put_in_que; + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (opmode & WIFI_STATION_STATE) { + if (!vxd_interface_ready) goto out; + priv = GET_VXD_PRIV(priv); + opmode = OPMODE; + goto put_in_que; + } +#endif + } + else { // not (Beacon, Probe-rsp, probe-rsp) +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + if (vap_idx >= 0) { + if (frame_type == WIFI_BEACON && priv->ss_req_ongoing) + { + pfrinfo->is_br_mgnt = 1; + goto put_in_que;//goto root interface + } + + priv = priv->pvap_priv[vap_idx]; + opmode = OPMODE; + goto put_in_que; + } + } +#endif + if (OPMODE & WIFI_AP_STATE) { + if (frame_type == WIFI_BEACON || frame_type == WIFI_PROBERSP) { + pfrinfo->is_br_mgnt = 1; + goto put_in_que; + } + } + +#ifdef UNIVERSAL_REPEATER + if (vxd_interface_ready && !memcmp(GET_VXD_PRIV(priv)->pmib->dot11Bss.bssid, bssid, MACADDRLEN)) { + priv = GET_VXD_PRIV(priv); + opmode = OPMODE; + } +#endif + } + } + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) // wrt-adhoc +#ifdef UNIVERSAL_REPEATER + if (frtype != WIFI_MGT_TYPE) + if (memcmp(bssid, "\x0\x0\x0\x0\x0\x0", MACADDRLEN) && + is_vxd_bssid(priv, bssid)) + { + unsigned char *sa = pfrinfo->sa; + + priv = GET_VXD_PRIV(priv); +#if 0 + printk(" VXD_ADHOC Rx data packets !! \n"); + dump_mac_rx(da); + dump_mac_rx(sa); +#endif + +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_datalist)); + SMP_UNLOCK_RX_DATA(x); +#endif + reuse = 0; + + goto out; + } +#endif +#endif + +put_in_que: +#endif // UNIVERSAL_REPEATER || MBSSID + + if (opmode & WIFI_AP_STATE) + { + if (IS_MCAST(da)) + { + // For AP mode, if DA == MCAST, then BSSID should be also MCAST + if (IS_MCAST(bssid)) + reuse = 0; + + // support 11A + else if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G|WIRELESS_11A)) + reuse = 0; + +#ifdef WDS + else if (priv->pmib->dot11WdsInfo.wdsEnabled) + reuse = 0; +#endif + +#ifdef CONFIG_RTK_MESH + else if (GET_MIB(priv)->dot1180211sInfo.mesh_enable) + reuse = 0; +#endif + + else if (opmode & WIFI_SITE_MONITOR) + reuse = 0; + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + else if (pfrinfo->is_br_mgnt && reuse) + reuse = 0; +#endif + + else + {} + } + else + { + /* + * For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID + * Action frame is an exception (for bcm iot), do not check bssid + */ + if (IS_BSSID(priv, da) && ((IS_BSSID(priv, bssid) || (frame_type == WIFI_WMM_ACTION)) +#ifdef CONFIG_RTK_MESH + || (GET_MIB(priv)->dot1180211sInfo.mesh_enable + && (!memcmp(bssid, pfrinfo->sa, MACADDRLEN)) /*mesh's management frame: A3 = A2 = TA*/ + && (frtype == WIFI_MGT_TYPE)) +#endif + )) { + + + reuse = 0; +} + else if (opmode & WIFI_SITE_MONITOR) + reuse = 0; + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + else if (pfrinfo->is_br_mgnt && reuse) + reuse = 0; +#endif +#ifdef WDS + else if (priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum) + reuse = 0; +#endif + + else + {} + } + + if (!reuse) { + if (frtype == WIFI_MGT_TYPE) + { +#ifdef RTL8190_DIRECT_RX + #if defined(CONFIG_PCI_HCI) + rtl8192cd_rx_mgntframe(priv, NULL, pfrinfo); + #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_recv_mgnt_frame(priv, pfrinfo); + #endif +#else + SMP_LOCK_RX_MGT(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_mgtlist)); + SMP_UNLOCK_RX_MGT(x); +#endif + } + else + reuse = 1; + } + } +#ifdef CLIENT_MODE + else if (opmode & WIFI_STATION_STATE) + { + // For Station mode, sa and bssid should always be BSSID, and DA is my mac-address + // in case of to_fr_ds = 0x00, then it must be mgt frame type + +#ifdef MULTI_MAC_CLONE + if (IS_MCAST(da) || mclone_find_address(priv, da, pfrinfo->pskb, MAC_CLONE_DA_FIND) >= 0) +#else + unsigned char *myhwaddr = priv->pmib->dot11OperationEntry.hwaddr; + if (IS_MCAST(da) || !memcmp(da, myhwaddr, MACADDRLEN)) +#endif + reuse = 0; + + if (!reuse) { + if (frtype == WIFI_MGT_TYPE) + { +#ifdef RTL8190_DIRECT_RX + #if defined(CONFIG_PCI_HCI) + rtl8192cd_rx_mgntframe(priv, NULL, pfrinfo); + #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_recv_mgnt_frame(priv, pfrinfo); + #endif +#else + SMP_LOCK_RX_MGT(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_mgtlist)); + SMP_UNLOCK_RX_MGT(x); +#endif + } + else + reuse = 1; + } + } + else if (opmode & WIFI_ADHOC_STATE) + { + unsigned char *myhwaddr = priv->pmib->dot11OperationEntry.hwaddr; + if (IS_MCAST(da) || !memcmp(da, myhwaddr, MACADDRLEN)) + { + if (frtype == WIFI_MGT_TYPE) + { +#ifdef RTL8190_DIRECT_RX + #if defined(CONFIG_PCI_HCI) + rtl8192cd_rx_mgntframe(priv, NULL, pfrinfo); + #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_recv_mgnt_frame(priv, pfrinfo); + #endif +#else + SMP_LOCK_RX_MGT(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_mgtlist)); + SMP_UNLOCK_RX_MGT(x); +#endif + reuse = 0; + } + else + { // data frames + if (memcmp(bssid, "\x0\x0\x0\x0\x0\x0", MACADDRLEN) && + memcmp(BSSID, "\x0\x0\x0\x0\x0\x0", MACADDRLEN) && + !memcmp(bssid, BSSID, MACADDRLEN)) + { +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_datalist)); + SMP_UNLOCK_RX_DATA(x); +#endif + reuse = 0; + } + } + } + } +#endif // CLIENT_MODE + else + reuse = 1; + +out: + + /* update priv's point */ + *priv_p = priv; + rx_sum_up(priv, NULL, pfrinfo->pktlen, retry); + return reuse; +} + + +/* + Check the "to_fr_ds" field: + + FromDS != 0 + ToDS = 0 +*/ +#if defined(CLIENT_MODE) || defined(CONFIG_RTK_MESH) +static int rtl8192cd_rx_dispatch_fromDs(struct rtl8192cd_priv **priv_p, struct rx_frinfo *pfrinfo +#ifdef MBSSID + ,int vap_idx +#endif +) +{ + int reuse = 1; + struct rtl8192cd_priv *priv = *priv_p; + unsigned int opmode = OPMODE; + unsigned char *pframe = get_pframe(pfrinfo); + int retry=GetRetry(pframe);/*in case of skb has been freed*/ + unsigned int frtype = GetFrameType(pframe); + unsigned char *da = pfrinfo->da; +#ifdef MULTI_MAC_CLONE + unsigned char *myhwaddr = GET_MY_HWADDR; +#else + unsigned char *myhwaddr = priv->pmib->dot11OperationEntry.hwaddr; +#endif + unsigned char *bssid = GetAddr2Ptr(pframe); +#if defined(SMP_SYNC) + unsigned long x; +#endif + + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable && (vap_idx >= 0)) + { + priv = priv->pvap_priv[vap_idx]; + opmode = OPMODE; + myhwaddr = GET_MY_HWADDR; + } +#endif +#ifdef CLIENT_MODE //(add for Mesh) + if (frtype == WIFI_MGT_TYPE) + goto out; + + if ((opmode & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == + (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + { + // For Station mode, + // da should be for me, bssid should be BSSID + if (IS_BSSID(priv, bssid)) { + if (IS_MCAST(da) || !memcmp(da, myhwaddr, MACADDRLEN)) + { +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_datalist)); + SMP_UNLOCK_RX_DATA(x); +#endif + reuse = 0; + } + } + } +#ifdef UNIVERSAL_REPEATER + else if ((opmode & WIFI_AP_STATE) && IS_DRV_OPEN(GET_VXD_PRIV(priv))) + { +#ifdef SDIO_2_PORT + myhwaddr = GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.hwaddr; +#endif + if (IS_BSSID(GET_VXD_PRIV(priv), bssid)) { + if (IS_MCAST(da) || !memcmp(da, myhwaddr, MACADDRLEN)) + { + priv = GET_VXD_PRIV(priv); +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&(pfrinfo->rx_list), &priv->rx_datalist); + SMP_UNLOCK_RX_DATA(x); +#endif + reuse = 0; + } + } + } +#endif + else + reuse = 1; + +#endif // CLIENT_MODE (add for Mesh) +out: + + /* update priv's point */ + *priv_p = priv; + rx_sum_up(priv, NULL, pfrinfo->pktlen, retry); + return reuse; +} +#endif // defined(CLIENT_MODE) || defined(CONFIG_RTK_MESH) + + +/* + Check the "to_fr_ds" field: + + FromDS = 0 + ToDS != 0 +*/ +static inline int rtl8192cd_rx_dispatch_toDs(struct rtl8192cd_priv **priv_p, struct rx_frinfo *pfrinfo +#ifdef MBSSID + ,int vap_idx +#endif + ) +{ + int reuse = 1; + struct rtl8192cd_priv *priv = *priv_p; + unsigned int opmode = OPMODE; + unsigned char *pframe = get_pframe(pfrinfo); + int retry=GetRetry(pframe); /*in case of skb has been freed*/ + unsigned int frtype = GetFrameType(pframe); + unsigned char *bssid = GetAddr1Ptr(pframe); + +#if defined(SMP_SYNC) + unsigned long x; +#endif +#ifdef CONFIG_RTK_MESH + if (GET_MIB(priv)->dot1180211sInfo.mesh_enable == 1) { // For MBSSID enable and STA connect to Virtual-AP can't use problem. + struct stat_info *pstat = get_stainfo(priv, pfrinfo->sa); + + if ((pstat == NULL) || isPossibleNeighbor(pstat)) + goto out; + } +#endif // CONFIG_RTK_MESH + + + if (frtype == WIFI_MGT_TYPE) + goto out; + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable && (vap_idx >= 0)) + { + priv = priv->pvap_priv[vap_idx]; + opmode = OPMODE; + } +#endif + + if (opmode & WIFI_AP_STATE) + { +#if 0 +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable && (vap_idx >= 0)) + { + priv = priv->pvap_priv[vap_idx]; +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_datalist)); + SMP_UNLOCK_RX_DATA(x); +#endif + reuse = 0; + } + else +#endif +#endif + // For AP mode, the data frame should have bssid==BSSID. (sa state checked laterly) + if (IS_BSSID(priv, bssid)) + { + // we only receive mgt frame when we are in SITE_MONITOR or link_loss + // please consider the case: re-auth and re-assoc +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&(pfrinfo->rx_list), &(priv->rx_datalist)); + SMP_UNLOCK_RX_DATA(x); +#endif + reuse = 0; + } + } +#ifdef UNIVERSAL_REPEATER + else if (IS_ROOT_INTERFACE(priv) && (opmode & WIFI_STATION_STATE) && IS_DRV_OPEN(GET_VXD_PRIV(priv)) + && (GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED)) { + if (IS_BSSID(GET_VXD_PRIV(priv), bssid)) + { + priv = GET_VXD_PRIV(priv); +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&(pfrinfo->rx_list), &priv->rx_datalist); + SMP_UNLOCK_RX_DATA(x); +#endif + reuse = 0; + } + } +#endif + else + reuse = 1; + +out: + + /* update priv's point */ + *priv_p = priv; + rx_sum_up(priv, NULL, pfrinfo->pktlen,retry); + return reuse; +} + + +/* + Check the "to_fr_ds" field: + + FromDS != 0 + ToDS != 0 + NOTE: The functuion duplicate to rtl8190_rx_dispatch_mesh (mesh_rx.c) +*/ +#ifdef WDS +static int rtl8192cd_rx_dispatch_wds(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + int reuse = 1; + unsigned char *pframe = get_pframe(pfrinfo); + unsigned int frtype = GetFrameType(pframe); + struct net_device *dev; + int fragnum; +#if defined(SMP_SYNC) + unsigned long x; +#endif + + rx_sum_up(priv, NULL, pfrinfo->pktlen, GetRetry(pframe)); + + if (memcmp(GET_MY_HWADDR, GetAddr1Ptr(pframe), MACADDRLEN)) { + DEBUG_INFO("Rx a WDS packet but which addr1 is not matched own, drop it!\n"); + goto out; + } + + if (!priv->pmib->dot11WdsInfo.wdsEnabled) { + DEBUG_ERR("Rx a WDS packet but WDS is not enabled in local mib, drop it!\n"); + goto out; + } + dev = getWdsDevByAddr(priv, GetAddr2Ptr(pframe)); + if (dev==NULL) { +#ifdef LAZY_WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE) { + if (add_wds_entry(priv, 0, GetAddr2Ptr(pframe))) { + dev = getWdsDevByAddr(priv, GetAddr2Ptr(pframe)); + if (dev == NULL) { + DEBUG_ERR("Rx a WDS packet but which TA is not valid, drop it!\n"); + goto out; + } + LOG_MSG("Add a wds entry - %02X:%02X:%02X:%02X:%02X:%02X\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), *(GetAddr2Ptr(pframe)+3), + *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); + } + else { + DEBUG_ERR("Rx a WDS packet but wds table is full, drop it!\n"); + goto out; + } + } + else +#endif + { + DEBUG_ERR("Rx a WDS packet but which TA is not valid, drop it!\n"); + goto out; + } + } + if (!netif_running(dev)) { + DEBUG_ERR("Rx a WDS packet but which interface is not up, drop it!\n"); + goto out; + } + fragnum = GetFragNum(pframe); + if (GetMFrag(pframe) || fragnum) { + DEBUG_ERR("Rx a fragment WDS packet, drop it!\n"); + goto out; + } + if (frtype != WIFI_DATA_TYPE) { + DEBUG_ERR("Rx a WDS packet but which type is not DATA, drop it!\n"); + goto out; + } +#ifdef __LINUX_2_6__ + pfrinfo->pskb->dev=dev; +#endif + +#ifdef RTL8190_DIRECT_RX + rtl8192cd_rx_dataframe(priv, NULL, pfrinfo); +#else + SMP_LOCK_RX_DATA(x); + list_add_tail(&pfrinfo->rx_list, &priv->rx_datalist); + SMP_UNLOCK_RX_DATA(x); +#endif + reuse = 0; + goto out; + +out: + + return reuse; +} +#endif // WDS + +#ifdef SUPPORT_MONITOR +static void rtl_ieee80211_add_rx_packet_header(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, unsigned int frtype,unsigned int subfrtype) +{ + unsigned char *pframe = get_pframe(pfrinfo); //skb data + struct rtl_wifi_header *rthdr; + struct sk_buff* pskb = pfrinfo->pskb; + unsigned char channel = 0; + unsigned char *p = NULL; + static const size_t len = PAGE_SIZE; + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if(GetFrameSubType(pframe)==WIFI_BEACON) + { + if (p != NULL) + channel = *(p+2); + else + channel = priv->pmib->dot11RFEntry.dot11channel; + } + else + channel = priv->chan_num+1; + + rthdr = (void *)skb_push(pskb, sizeof(*rthdr)); + if(!rthdr) + { + panic_printk("(%s)line=%d,!!! failed to allocate memory !!!\n", __FUNCTION__, __LINE__); + ASSERT(rthdr); + } + memset(rthdr, 0, sizeof(*rthdr)); + + rthdr->rt_frame_type = frtype; + rthdr->rt_sub_frame_type = subfrtype; + rthdr->rt_rssi = pfrinfo->rssi; + rthdr->rt_noise = 10; + memcpy((rthdr->rt_addr1),GetAddr1Ptr(pframe), MACADDRLEN); + memcpy((rthdr->rt_addr2),GetAddr2Ptr(pframe), MACADDRLEN); + rthdr->rt_rate= pfrinfo->rx_rate; + rthdr->rt_channel_num = channel; +} +#endif + + + +/*--------------------------------------------------------------- + return value: + 0: no reuse, allocate new skb due to the current is queued. + 1: reuse! due to error pkt or short pkt. +----------------------------------------------------------------*/ +__MIPS16 +__IRAM_IN_865X +int validate_mpdu(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *sa, *da, *myhwaddr, *pframe; + unsigned int frtype; + + + int reuse = 1; +#ifdef MBSSID + unsigned int opmode = OPMODE; + int i, vap_idx=-1; +#endif + +#if defined(__LINUX_2_6__) || defined(__ECOS) + if(pfrinfo == NULL || pfrinfo->pskb==NULL || pfrinfo->pskb->data == NULL) + return 1; +#endif + + pframe = get_pframe(pfrinfo); + +#if 1 //Filen_Debug + if ((unsigned long)pframe & BIT0) { + panic_printk("Error: pframe(0x%lx), pfrinfo->pskb(0x%lx), pfrinfo(0x%lx)\n", (unsigned long)pframe, (unsigned long)pfrinfo->pskb, (unsigned long)pfrinfo); + panic_printk("Error: rxbuf_shift(0x%x), driver_info_size(0x%x)\n", pfrinfo->rxbuf_shift, pfrinfo->driver_info_size); + return 1; + } +#endif + +#if 0 // already flush cache in rtl8192cd_rx_isr() +#ifndef RTL8190_CACHABLE_CLUSTER +#ifdef __MIPSEB__ + pframe = (UINT8 *)((unsigned long)pframe | 0x20000000); +#endif +#endif +#endif + +#ifdef DRVMAC_LB + if (priv->pmib->miscEntry.drvmac_lb) + lb_convert(priv, pframe); +#endif + + pfrinfo->hdr_len = get_hdrlen(priv, pframe); + if (pfrinfo->hdr_len == 0) // unallowed packet type + { +// printk("pfrinfo->hdr_len == 0\n"); + return 1; + } + +#ifdef CONFIG_8814_AP_MAC_VERI + RX_MAC_Verify_8814(priv,pframe,pfrinfo); +#endif //#ifdef CONFIG_8814_AP_MAC_VERI + + frtype = GetFrameType(pframe); + pfrinfo->to_fr_ds = get_tofr_ds(pframe); + pfrinfo->da = da = get_da(pframe); + pfrinfo->sa = sa = get_sa(pframe); + pfrinfo->seq = GetSequence(pframe); + +#ifdef SUPPORT_MONITOR + if(priv->is_monitor_mode == TRUE) + { + unsigned int sub_frame_type = GetFrameSubType(pframe); + if((frtype == WIFI_MGT_TYPE) || (frtype == WIFI_DATA_TYPE)) + { + struct sk_buff* pskb = pfrinfo->pskb; + rtl_ieee80211_add_rx_packet_header(priv, pfrinfo, frtype,sub_frame_type); + pskb->dev = priv->dev; + skb_reset_mac_header(pskb); + pskb->ip_summed = CHECKSUM_UNNECESSARY; + pskb->pkt_type = PACKET_OTHERHOST; + pskb->protocol = htons(ETH_P_802_2); + netif_receive_skb(pskb); + reuse = 0; + return reuse; + } + else + { + reuse = 1; + return reuse; + } + } +#endif + +#ifdef CONFIG_RTK_MESH + pfrinfo->is_11s = 0; + + // WIFI_11S_MESH_ACTION use QoS bit, but it's not a QoS data (8186 compatible) + if (is_qos_data(pframe) && GetFrameSubType(pframe)!=WIFI_11S_MESH_ACTION) { +#else + if (is_qos_data(pframe)) { +#endif + pfrinfo->tid = GetTid(pframe) & 0x07; // we only process TC of 0~7 + } + else { + pfrinfo->tid = 0; + } +#ifdef MULTI_MAC_CLONE + if (MCLONE_NUM > 0 && !IS_MCAST(GetAddr1Ptr(pframe))) { + int id; + id = mclone_find_address(priv, GetAddr1Ptr(pframe), pfrinfo->pskb, MAC_CLONE_DA_FIND); + if (id > 0) + ACTIVE_ID = id; + else + ACTIVE_ID = 0; + } else + ACTIVE_ID = 0; + myhwaddr = GET_MY_HWADDR; +#else + myhwaddr = priv->pmib->dot11OperationEntry.hwaddr; +#endif + +#ifdef PCIE_POWER_SAVING + if (!memcmp(myhwaddr, GetAddr1Ptr(pframe), MACADDRLEN)) + mod_timer(&priv->ps_timer, jiffies + POWER_DOWN_T0); +#endif + + // filter packets that SA is myself +#ifdef MULTI_MAC_CLONE + if ((OPMODE & WIFI_STATION_STATE) && IS_MCAST(GetAddr1Ptr(pframe)) && + priv->pmib->ethBrExtInfo.macclone_enable && (mclone_find_address(priv, sa, NULL, MAC_CLONE_NOCARE_FIND) >= 0)) { + return 1; + } + else if ((OPMODE & WIFI_AP_STATE) && IS_MCAST(GetAddr1Ptr(pframe)) && + /*priv->pmib->ethBrExtInfo.macclone_enable &&*/ (mclone_find_address(priv, sa, NULL, MAC_CLONE_MSA_FIND) >= 0)) { + return 1; + } + else +#endif + if ((!memcmp(myhwaddr, sa, MACADDRLEN) && (0==priv->pmib->miscEntry.func_off)) +#ifdef CONFIG_RTK_MESH + // for e.g., MPP1 - THIS_DEVICE - ROOT ; + // THIS_DEVICE use ROOT first, and then ROOT dispatch the packet to MPP1 + && (priv->pmib->dot1180211sInfo.mesh_enable ? ((pfrinfo->to_fr_ds != 0x03) && GetFrameSubType(pframe) != WIFI_11S_MESH) : TRUE) +#endif + ) + return 1; + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + { + if ( (((pfrinfo->to_fr_ds == 0x00) || (pfrinfo->to_fr_ds == 0x02)) && !memcmp(priv->pvap_priv[i]->pmib->dot11OperationEntry.hwaddr, GetAddr1Ptr(pframe), MACADDRLEN)) + || (((pfrinfo->to_fr_ds == 0x00) || (pfrinfo->to_fr_ds == 0x01)) && !memcmp(priv->pvap_priv[i]->pmib->dot11StationConfigEntry.dot11Bssid, GetAddr2Ptr(pframe), MACADDRLEN)) ) { + vap_idx = i; + if ((priv->pvap_priv[i]->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) && (pfrinfo->to_fr_ds == 0x01) && !memcmp(priv->pvap_priv[i]->pmib->dot11OperationEntry.hwaddr, sa, MACADDRLEN)) + return 1; + break; + } + } + } + } +#endif + +#if 0 + // check power save state + if ((opmode & WIFI_AP_STATE) +#ifdef UNIVERSAL_REPEATER + || ((opmode & WIFI_STATION_STATE) && IS_DRV_OPEN(GET_VXD_PRIV(priv))) +#endif + ) + { + bssid = GetAddr1Ptr(pframe); + +#ifdef MBSSID + if (vap_idx >= 0) { + if (IS_BSSID(priv->pvap_priv[vap_idx], bssid)) + pwr_state(priv->pvap_priv[vap_idx], pfrinfo); + } + else +#endif +#ifdef UNIVERSAL_REPEATER + if (opmode & WIFI_AP_STATE) { + if (IS_BSSID(priv, bssid)) + pwr_state(priv, pfrinfo); + } + else { + if (IS_BSSID(GET_VXD_PRIV(priv), bssid)) + pwr_state(GET_VXD_PRIV(priv), pfrinfo); + } +#else + if (IS_BSSID(priv, bssid)) + pwr_state(priv, pfrinfo); +#endif + } +#endif + + // if receiving control frames, we just handle PS-Poll only + if (frtype == WIFI_CTRL_TYPE) + { + return rtl8192cd_rx_procCtrlPkt(priv, pfrinfo +#ifdef MBSSID + ,vap_idx +#endif + ); + } + + // for ap, we have handled; for station/ad-hoc, we reject null_data frame + if (((GetFrameSubType(pframe)) == WIFI_DATA_NULL) || + (((GetFrameSubType(pframe)) == WIFI_DATA) && pfrinfo->pktlen <= 24) +#ifdef WIFI_WMM + ||((QOS_ENABLE) && ((GetFrameSubType(pframe)) == (WIFI_DATA_NULL | BIT(7)))) +#endif + ) + { + return rtl8192cd_rx_procNullPkt(priv, pfrinfo +#ifdef MBSSID + ,vap_idx +#endif + ); + } + + // david, move rx statistics from rtl8192cd_rx_isr() to here because repeater issue + //qinjunjie:move rx_sum_up to rtl8192cd_rx_dispatch_mgmt_adhoc/rtl8192cd_rx_dispatch_fromDs/rtl8192cd_rx_dispatch_toDs/rtl8192cd_rx_dispatch_wds + // rx_sum_up(priv, NULL, pfrinfo->pktlen, GetRetry(pframe)); + + // enqueue data frames and management frames +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if((priv->pmib->dot11StationConfigEntry.sc_enabled == 1) && (priv->simple_config_status !=0)) + { + rtk_sc_start_parse_packet(priv, pfrinfo); + } +#ifdef UNIVERSAL_REPEATER + if((GET_VXD_PRIV(priv)->pmib->dot11StationConfigEntry.sc_enabled == 1) && (GET_VXD_PRIV(priv)->simple_config_status !=0)) + { + rtk_sc_start_parse_packet(GET_VXD_PRIV(priv), pfrinfo); + } +#endif +#endif + + switch (pfrinfo->to_fr_ds) + { + case 0x00: // ToDs=0, FromDs=0 + reuse = rtl8192cd_rx_dispatch_mgmt_adhoc(&priv, pfrinfo +#ifdef MBSSID + ,vap_idx +#endif + ); + break; + + case 0x01: // ToDs=0, FromDs=1 +#if defined(CLIENT_MODE) || defined(CONFIG_RTK_MESH) + reuse = rtl8192cd_rx_dispatch_fromDs(&priv, pfrinfo +#ifdef MBSSID + ,vap_idx +#endif + ); +#endif + break; + + case 0x02: // ToDs=1, FromDs=0 + reuse = rtl8192cd_rx_dispatch_toDs(&priv, pfrinfo +#ifdef MBSSID + ,vap_idx +#endif + ); + break; + + case 0x03: // ToDs=1, FromDs=1 +#ifdef CONFIG_RTK_MESH + if( 1 == GET_MIB(priv)->dot1180211sInfo.mesh_enable) + { + reuse = rx_dispatch_mesh(priv, pfrinfo); + break; + } +#endif + +#ifdef A4_STA + if (priv->pshare->rf_ft_var.a4_enable) { + + reuse = rtl8192cd_rx_dispatch_toDs(&priv, pfrinfo +#ifdef MBSSID + ,vap_idx +#endif + ); + break; + } +#endif + +#ifdef WDS + reuse = rtl8192cd_rx_dispatch_wds(priv, pfrinfo); +#endif + break; + } + + return reuse; +} + + +void rx_pkt_exception(struct rtl8192cd_priv *priv, unsigned int cmd) +{ + struct net_device_stats *pnet_stats = &(priv->net_stats); + + if (cmd & RX_CRC32) + { + pnet_stats->rx_crc_errors++; + pnet_stats->rx_errors++; + SNMP_MIB_INC(dot11FCSErrorCount, 1); +#ifdef _11s_TEST_MODE_ + mesh_debug_rx2(priv, cmd); +#endif + } + else if (cmd & RX_ICVERR) + { + pnet_stats->rx_errors++; + SNMP_MIB_ASSIGN(dot11WEPICVErrorCount, 1); + } + else + { + } +} + +#ifdef CONFIG_WLAN_HAL +__IRAM_IN_865X +static void +rx_pkt_exception_88XX( + struct rtl8192cd_priv *priv, + BOOLEAN bRX_CRC32, + BOOLEAN bRX_ICVERR +) +{ + struct net_device_stats *pnet_stats = &(priv->net_stats); + + priv->ext_stats.rx_reuse++; + //printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + + if ( bRX_CRC32 ) + { + pnet_stats->rx_crc_errors++; + pnet_stats->rx_errors++; + SNMP_MIB_INC(dot11FCSErrorCount, 1); + +#if 0 //Filen: mesh_debug_rx2() can't be found ??? +#ifdef _11s_TEST_MODE_ + mesh_debug_rx2(priv, cmd); +#endif +#endif + } + else if ( bRX_ICVERR ) + { + pnet_stats->rx_errors++; + SNMP_MIB_ASSIGN(dot11WEPICVErrorCount, 1); + } + else + { + } +} +#endif //CONFIG_WLAN_HAL + +#ifdef CONFIG_PCI_HCI +#if defined(RX_TASKLET) || defined(__ECOS) +__IRAM_IN_865X +void rtl8192cd_rx_tkl_isr(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv; +#if defined(__LINUX_2_6__) || defined(__ECOS) + unsigned long flags = 0; +#endif +#if defined(SMP_SYNC) + unsigned long x = 0; +#endif + + priv = (struct rtl8192cd_priv *)task_priv; + +// printk("=====>> INSIDE rtl8192cd_rx_tkl_isr <<=====\n"); + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) { + priv->pshare->has_triggered_rx_tasklet = 0; + return; + } +#endif + +#if defined(__LINUX_2_6__) || defined(__ECOS) + SMP_LOCK(x); + //RTL_W32(HIMR, 0); +#else + SAVE_INT_AND_CLI(x); + SMP_LOCK(x); + +#ifdef DELAY_REFILL_RX_BUF + priv->pshare->has_triggered_rx_tasklet = 2; // indicate as ISR in service +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask); + RTL_W32(REG_88E_HIMRE, priv->pshare->InterruptMaskExt); + } else +#endif + { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->EnableRxRelatedInterruptHandler(priv); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + //RTL_W32(HIMR, RTL_R32(HIMR) | (HIMR_RXFOVW| HIMR_RDU | HIMR_ROK)); +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + RTL_W32(REG_92E_HIMR, RTL_R32(REG_92E_HIMR) | HIMR_ROK); + RTL_W32(REG_92E_HIMRE, RTL_R32(REG_92E_HIMRE) | HIMRE_92E_RXFOVW); + } + else +#endif + { + RTL_W32(HIMR, RTL_R32(HIMR) | (HIMR_RXFOVW | HIMR_ROK)); + } + } + } +#endif + +//#ifdef DELAY_REFILL_RX_BUF +// priv->pshare->has_triggered_rx_tasklet = 2; // indicate as ISR in service +//#endif + + rtl8192cd_rx_isr(priv); + +#if defined(__LINUX_2_6__) || defined(__ECOS) + + SAVE_INT_AND_CLI(flags); + //Filen: "has_triggered_rx_tasklet" & "HIMR Enable" should be atomic + // To avoid that "RX interrupt" is gone + priv->pshare->has_triggered_rx_tasklet = 0; + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask); + RTL_W32(REG_88E_HIMRE, priv->pshare->InterruptMaskExt); + } else +#endif + { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->EnableRxRelatedInterruptHandler(priv); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + RTL_W32(REG_92E_HIMR, priv->pshare->InterruptMask); + RTL_W32(REG_92E_HIMRE, priv->pshare->InterruptMaskExt); + } + else +#endif + { + RTL_W32(HIMR, priv->pshare->InterruptMask); + } + } + } + + RESTORE_INT(flags); + SMP_UNLOCK(x); +#else + + priv->pshare->has_triggered_rx_tasklet = 0; + + RESTORE_INT(x); + SMP_UNLOCK(x); +#endif +} +#endif +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_WLAN_HAL +#ifdef DELAY_REFILL_RX_BUF +#ifndef __LINUX_2_6__ +__MIPS16 +#endif +__IRAM_IN_865X +int refill_rx_ring_88XX( + struct rtl8192cd_priv *priv, + struct sk_buff *skb, + unsigned char *data, + unsigned int q_num, + PHCI_RX_DMA_QUEUE_STRUCT_88XX cur_q +) +{ + + /* return 0 means can't refill (because interface be closed or not opened yet) to rx ring but relesae to skb_poll*/ + if (!(priv->drv_state & DRV_STATE_OPEN)){ + return 0; + } + struct rtl8192cd_hw *phw=GET_HW(priv); + struct sk_buff *new_skb; +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + unsigned long x; +#endif + extern struct sk_buff *dev_alloc_8190_skb(unsigned char *data, int size); +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + SAVE_INT_AND_CLI(x); + SMP_LOCK_SKB(x); +#endif + if (skb || (priv->pshare->has_triggered_rx_tasklet != 2 && + (((cur_q->host_idx + cur_q->rxbd_ok_cnt)%cur_q->total_rxbd_num) != cur_q->cur_host_idx) ) ) { + + if (skb) { + new_skb = skb; + } else { +#ifdef CONFIG_RTL8190_PRIV_SKB + new_skb = dev_alloc_8190_skb(data, RX_BUF_LEN); +#else + new_skb = dev_alloc_skb(RX_BUF_LEN); +#endif + if (new_skb == NULL) { + DEBUG_ERR("out of skb struct!\n"); +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); +#endif + return 0; + } + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_rx_skb_cnt); +#endif + } + + { + GET_HAL_INTERFACE(priv)->UpdateRXBDInfoHandler(priv, q_num, + (cur_q->host_idx+cur_q->rxbd_ok_cnt)%cur_q->total_rxbd_num, new_skb, init_rxdesc_88XX, _FALSE); + + cur_q->rxbd_ok_cnt++; + } + + +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); +#endif + return 1; + } + else { +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); +#endif + return 0; + } +} +#endif +#endif // CONFIG_WLAN_HAL + +#ifdef DELAY_REFILL_RX_BUF +#if (!defined(CONFIG_WLAN_HAL) || CONFIG_WLAN_NOT_HAL_EXIST) +#ifndef __LINUX_2_6__ +__MIPS16 +#endif +#ifndef __ECOS +__IRAM_IN_865X +#endif +int refill_rx_ring(struct rtl8192cd_priv *priv, struct sk_buff *skb, unsigned char *data) +{ + struct rtl8192cd_hw *phw=GET_HW(priv); + struct sk_buff *new_skb; +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + unsigned long x; +#endif + extern struct sk_buff *dev_alloc_8190_skb(unsigned char *data, int size); +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + SAVE_INT_AND_CLI(x); + SMP_LOCK_SKB(x); +#endif + if (skb || + //(priv->pshare->has_triggered_rx_tasklet != 2 && phw->cur_rx_refill != phw->cur_rx)) { + phw->cur_rx_refill != phw->cur_rx) { + if (skb) + new_skb = skb; + else { +#ifdef CONFIG_RTL8190_PRIV_SKB + new_skb = dev_alloc_8190_skb(data, RX_BUF_LEN); +#else + new_skb = dev_alloc_skb(RX_BUF_LEN); +#endif + if (new_skb == NULL) { + DEBUG_ERR("out of skb struct!\n"); +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); +#endif + return 0; + } + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_rx_skb_cnt); +#endif + } + + init_rxdesc(new_skb, phw->cur_rx_refill, priv); + //phw->cur_rx_refill = (phw->cur_rx_refill + 1) % NUM_RX_DESC; + phw->cur_rx_refill = ((phw->cur_rx_refill+1)==NUM_RX_DESC)?0:phw->cur_rx_refill+1; +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + RTL_W32(REG_88E_HISR, HIMR_88E_RDU); + RTL_W32(REG_88E_HISRE, HIMRE_88E_RXFOVW); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT //8812_client + if (GET_CHIP_VER(priv)==VERSION_8812E) { + RTL_W32(REG_HISR0_8812, BIT(1)); + RTL_W32(REG_HISR1_8812, BIT(8)); + } else +#endif + { + RTL_W32(HISR,(HIMR_RXFOVW | HIMR_RDU)); + } +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); +#endif + return 1; + } + else { +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(RX_TASKLET) + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); +#endif + return 0; + } +} +#else +int refill_rx_ring(struct rtl8192cd_priv *priv, struct sk_buff *skb, unsigned char *data) +{ + return 0; +} +#endif // !CONFIG_WLAN_HAL || CONFIG_WLAN_NOT_HAL_EXIST +#endif // DELAY_REFILL_RX_BUF + +#ifdef RX_BUFFER_GATHER +void flush_rx_list(struct rtl8192cd_priv *priv) +{ + struct rx_frinfo *pfrinfo; + struct list_head *phead, *plist; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + phead = &priv->pshare->gather_list; + plist = phead->next; + + while (plist != phead) { + pfrinfo = list_entry(plist, struct rx_frinfo, rx_list); + plist = plist->next; + if (pfrinfo->pskb) + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + } + INIT_LIST_HEAD(&priv->pshare->gather_list); + + RESTORE_INT(flags); +} + +static int search_first_segment(struct rtl8192cd_priv *priv, struct rx_frinfo **found) +{ + struct rx_frinfo *pfrinfo, *first = NULL; + struct list_head *phead, *plist; + int len = 0, look_for = GATHER_FIRST, ok = 0; +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned char *pframe; + u8 qosControl[4]; + + SAVE_INT_AND_CLI(flags); + + phead = &priv->pshare->gather_list; + plist = phead->next; + + while (phead && plist != phead) { + pfrinfo = list_entry(plist, struct rx_frinfo, rx_list); + plist = plist->next; + + if (pfrinfo->gather_flag & look_for) { + len += pfrinfo->pktlen; + if (pfrinfo->gather_flag & GATHER_FIRST) { + first = pfrinfo; + list_del_init(&pfrinfo->rx_list); + + if (pfrinfo->pskb) { + pframe = get_pframe(pfrinfo); + memcpy(qosControl, GetQosControl(pframe), 2); + if (!is_qos_data(pframe) || !(qosControl[0] & BIT(7))) { /* not AMSDU */ + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + pfrinfo->pskb = NULL; + } else { + look_for = GATHER_MIDDLE | GATHER_LAST; + } + } + } + else if (pfrinfo->gather_flag & GATHER_LAST) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + first->gather_len = len - _CRCLNG_; + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + first->gather_len = len; + } + *found = first; + ok = 1; + break; + } + } + else { + list_del_init(&pfrinfo->rx_list); + if (pfrinfo->pskb) + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + } + } + + if (first && !ok) { + if (first->pskb) + rtl_kfree_skb(priv, first->pskb, _SKB_RX_); + } + + RESTORE_INT(flags); + return ok; +} + +#endif /* RX_BUFFER_GATHER */ + +#ifdef CONFIG_PCI_HCI + +#if (defined(__ECOS) ||defined(__LINUX_2_6__)) && defined(RX_TASKLET) +#define RTL_WLAN_RX_ATOMIC_PROTECT_ENTER do {SAVE_INT_AND_CLI(x);} while(0) +#define RTL_WLAN_RX_ATOMIC_PROTECT_EXIT do {RESTORE_INT(x);} while(0) +#else +#define RTL_WLAN_RX_ATOMIC_PROTECT_ENTER +#define RTL_WLAN_RX_ATOMIC_PROTECT_EXIT +#endif + + +#ifdef CONFIG_WLAN_HAL + +BOOLEAN +CheckRxPktLenReuse( + struct rtl8192cd_priv *priv, + struct rx_frinfo *pfrinfo, + PRX_DESC_STATUS_88XX prx_desc_status +) +{ + // TODO: 0x2d00 is 11520, but MAX AMSDU is 11454 (0x2CBE) + //3 Check Upper bound length + // 1.) Check older than 11AC + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC)) { + if (pfrinfo->pktlen > 0x2000) { + return TRUE; + } + } + + // 2.) Check 11AC + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + if (pfrinfo->pktlen > 0x2d00) { + return TRUE; + } + } + + //3 Check Low bound length + if (prx_desc_status->C2HPkt) { + // TODO: check if there is low bound length for C2H packet length + } + else { + // Normal RX packet + if (pfrinfo->pktlen < 16) { + +#if defined(RX_BUFFER_GATHER) + if (pfrinfo->gather_flag != GATHER_LAST) { + return TRUE; + } +#else + return TRUE; +#endif //defined(RX_BUFFER_GATHER) + } + } + + return FALSE; +} + +__MIPS16 +__IRAM_IN_865X +void +validate_C2HPkt( + struct rtl8192cd_priv *priv, + struct rx_frinfo *pfrinfo +) +{ +#ifdef CONFIG_WLAN_HAL_8881A + if ((GET_CHIP_VER(priv) == VERSION_8881A)) { + C2HPacketHandler_8881A(priv, get_pframe(pfrinfo), pfrinfo->pktlen); // no CRC in C2H_PACKET + } + else +#endif + GET_HAL_INTERFACE(priv)->C2HPacketHandler(priv,get_pframe(pfrinfo), pfrinfo->pktlen); // no CRC in C2H_PACKET + // TODO: Parsing C2H Packet +} + +#define CFG_UPDATE_RX_SWBD_IDX_EARLY 1 + +#ifdef CONFIG_RTK_VOIP_QOS +extern int ( *check_voip_channel_loading )( void ); +#endif +#if !defined(__LINUX_2_6__) && !defined(__ECOS) +__MIPS16 +#endif +__IRAM_IN_865X +void rtl88XX_rx_isr(struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_hw *phw; + struct sk_buff *pskb, *new_skb; + struct rx_frinfo *pfrinfo; + unsigned int reuse; +#if defined(DELAY_REFILL_RX_BUF) + unsigned int cmp_flags; +#endif +#if (defined(__ECOS) || defined(__LINUX_2_6__)) && defined(RX_TASKLET) + unsigned long x; +#if defined(SMP_SYNC) + unsigned long y = 0; +#endif +#endif +#if defined(DELAY_REFILL_RX_BUF) + int refill; +#else + u2Byte rxbdOkCnt = 0; +#endif +#if defined(MP_TEST) + unsigned char *sa,*da,*bssid; + char *pframe; + unsigned int find_flag; +#endif +#if defined(CONFIG_RTL8190_PRIV_SKB) +#ifdef CONCURRENT_MODE + extern int skb_free_num[]; +#else + extern int skb_free_num; +#endif +#endif +#if defined(RX_BUFFER_GATHER) + int pfrinfo_update; +#endif + unsigned int q_num; + PHCI_RX_DMA_MANAGER_88XX prx_dma; + PHCI_RX_DMA_QUEUE_STRUCT_88XX cur_q; + RX_DESC_STATUS_88XX rx_desc_status; + +#if 1//(defined (CONFIG_RTK_VOIP_QOS) && !defined (CONFIG_RTK_VOIP_ETHERNET_DSP_IS_HOST)) || defined (CHK_RX_ISR_TAKES_TOO_LONG) + unsigned long start_time = jiffies; + int n = 0; +#endif + int update = 0; + u4Byte skb_shift_size = 0; + u4Byte skb_used_size; + +#ifdef RX_LOOP_LIMIT + unsigned int loop_cnt = 0; +#endif + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + SMP_LOCK_RECV(y); + + phw = GET_HW(priv); + + RTL_WLAN_RX_ATOMIC_PROTECT_ENTER; + + // Currently, only one queue for rx... + q_num = 0; + prx_dma = (PHCI_RX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PRxDMA88XX); + cur_q = &(prx_dma->rx_queue[q_num]); + + GET_HAL_INTERFACE(priv)->UpdateRXBDHWIdxHandler(priv, q_num); + + while (cur_q->cur_host_idx != cur_q->hw_idx) + { + if ( (n++ > (NUM_RX_DESC *2/3)) || ((jiffies - start_time) >= RTL_MILISECONDS_TO_JIFFIES(1000) )) + { + break; + } +#if 0 //def __ECOS + if ((n++ > 100) || ((jiffies - start_time) >= 1)) + { + break; + } +#endif +#ifdef RX_LOOP_LIMIT + if ((priv->pmib->dot11StationConfigEntry.limit_rxloop > 0) && + (loop_cnt++ > priv->pmib->dot11StationConfigEntry.limit_rxloop)) + break; +#endif +#if defined (CONFIG_RTK_VOIP_QOS) && !defined (CONFIG_RTK_VOIP_ETHERNET_DSP_IS_HOST) + if ( (n++ > 100 || (jiffies - start_time) >= 1 )&& (check_voip_channel_loading && (check_voip_channel_loading() > 0)) ) + { + break; + } +#endif +#if defined (CHK_RX_ISR_TAKES_TOO_LONG) + /* for small packet RX test(ex. VeryWave UDP small pkt size RX test), there may comes too many packets from the air and + cause our RX ISR while(1) loop run too long and then cause the system watch dog timer timeout. + So we break the while loop when it takes to long */ + if ( (n++ > 1000) || ((jiffies - start_time) >= RTL_MILISECONDS_TO_JIFFIES(1000) )) + { + break; + } +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + if(((priv->pshare->RxTagPollingCount >20)) ) + break; + } +#endif + +#if defined(DELAY_REFILL_RX_BUF) + refill = 1; +#endif // DELAY_REFILL_RX_BUF + +#if defined(RX_BUFFER_GATHER) + pfrinfo_update = 0; +#endif + + pskb = (struct sk_buff *)(phw->rx_infoL[cur_q->cur_host_idx].pbuf); + pfrinfo = get_pfrinfo(pskb); + reuse = 1; + skb_shift_size = 0; + + if ( RT_STATUS_SUCCESS != GET_HAL_INTERFACE(priv)->QueryRxDescHandler(priv, q_num, pskb->data, &rx_desc_status) ) { +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if (IS_PCIBIOS_TYPE) { + pci_unmap_single(priv->pshare->pdev, phw->rx_infoL[cur_q->cur_host_idx].paddr, (RX_BUF_LEN - sizeof(struct rx_frinfo)), PCI_DMA_FROMDEVICE); + } +#endif + pfrinfo = NULL; + priv->ext_stats.rx_reuse++; +#ifdef __ECOS + panic_printk("QueryRxDesc:%s(%d), reuse1(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); +#else + printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); +#endif + goto rx_reuse; + } + +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if (IS_PCIBIOS_TYPE) { + pci_unmap_single(priv->pshare->pdev, phw->rx_infoL[cur_q->cur_host_idx].paddr, rx_desc_status.PKT_LEN, PCI_DMA_FROMDEVICE); + } +#endif + + #ifdef CONFIG_WLAN_HAL_8192EE + //translate_CRC32_outsrc(priv, pfrinfo, rx_desc_status.CRC32); + if(!rx_desc_status.C2HPkt) + { + translate_CRC32_outsrc(priv, pfrinfo, rx_desc_status.CRC32,rx_desc_status.PKT_LEN); + } + #endif + + if (rx_desc_status.CRC32) { + rx_pkt_exception_88XX(priv, rx_desc_status.CRC32, rx_desc_status.ICVERR); + goto rx_reuse; + } + +#if !defined(RX_BUFFER_GATHER) + else if (!(rx_desc_status.FS == 0x01 && rx_desc_status.LS == 0x01)) { + // h/w use more than 1 rx descriptor to receive a packet + // that means this packet is too large + // drop such kind of packet + priv->ext_stats.rx_reuse++; + printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + goto rx_reuse; + } +#endif // !defined(RX_BUFFER_GATHER) + else if (!IS_DRV_OPEN(priv)) { + priv->ext_stats.rx_reuse++; + printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + goto rx_reuse; + } + else { + pfrinfo->pskb = pskb; + if(rx_desc_status.C2HPkt) + pfrinfo->pktlen = rx_desc_status.PKT_LEN;// If is C2H packet, there is no CRC length Kevin for txbf + else + pfrinfo->pktlen = rx_desc_status.PKT_LEN - _CRCLNG_; + +#if defined(RX_BUFFER_GATHER) + if (!(rx_desc_status.FS == 0x01 && rx_desc_status.LS == 0x01)) { + if (rx_desc_status.FS == 0x01 && priv->pshare->gather_state == GATHER_STATE_NO) { + priv->pshare->gather_state = GATHER_STATE_FIRST; + pfrinfo->pktlen = rx_desc_status.RXBuffSize - SIZE_RXDESC_88XX - rx_desc_status.DRV_INFO_SIZE - rx_desc_status.SHIFT; + priv->pshare->gather_len = pfrinfo->pktlen; + priv->pshare->pkt_total_len = rx_desc_status.PKT_LEN; + pfrinfo->gather_flag = GATHER_FIRST; + } else if ((rx_desc_status.FS == 0x00 && rx_desc_status.LS == 0x00) && + (priv->pshare->gather_state == GATHER_STATE_FIRST || priv->pshare->gather_state == GATHER_STATE_MIDDLE)) { + priv->pshare->gather_state = GATHER_STATE_MIDDLE; + pfrinfo->pktlen = rx_desc_status.RXBuffSize; + priv->pshare->gather_len += rx_desc_status.RXBuffSize; + pfrinfo->gather_flag = GATHER_MIDDLE; + } else if (rx_desc_status.LS == 0x01 && + (priv->pshare->gather_state == GATHER_STATE_FIRST || priv->pshare->gather_state == GATHER_STATE_MIDDLE)) { + priv->pshare->gather_state = GATHER_STATE_LAST; + pfrinfo->pktlen = priv->pshare->pkt_total_len - priv->pshare->gather_len; + pfrinfo->gather_flag = GATHER_LAST; + } else { + if (priv->pshare->gather_state != GATHER_STATE_NO) { + flush_rx_list(priv); + priv->pshare->gather_state = GATHER_STATE_NO; + } + + priv->ext_stats.rx_reuse++; + //printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + goto rx_reuse; + } + + } + else { + if (priv->pshare->gather_state != GATHER_STATE_NO) { + DEBUG_ERR("Rx pkt not in valid gather state [%x]!\n", priv->pshare->gather_state); + flush_rx_list(priv); + priv->pshare->gather_state = GATHER_STATE_NO; + } + } + + if (pfrinfo->gather_flag && pfrinfo->gather_flag != GATHER_FIRST) { + pfrinfo->driver_info_size = 0; + pfrinfo->rxbuf_shift = 0; + } + else +#endif /* RX_BUFFER_GATHER */ + { + pfrinfo->driver_info_size = rx_desc_status.DRV_INFO_SIZE; + pfrinfo->rxbuf_shift = rx_desc_status.SHIFT; + } + + pfrinfo->sw_dec = rx_desc_status.SWDEC; + + if (CheckRxPktLenReuse(priv, pfrinfo, &rx_desc_status)) { + printk("pktlen out of range, pfrinfo->pktlen=0x%x, goto rx_reuse\n", pfrinfo->pktlen); + priv->ext_stats.rx_reuse++; + printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + goto rx_reuse; + } + +#if defined(CONFIG_RTL865X_CMO) + if (pfrinfo->pskb == NULL) { + pfrinfo->pskb = pskb; + priv->ext_stats.rx_reuse++; + printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + goto rx_reuse; + } +#endif + +#if defined(RX_BUFFER_GATHER) + if (priv->pshare->gather_state != GATHER_STATE_MIDDLE && priv->pshare->gather_state != GATHER_STATE_LAST) +#endif + { + //3 Shift SKB pointer before we use skb->data + skb_reserve(pskb, sizeof(RX_DESC_88XX)); + skb_shift_size += sizeof(RX_DESC_88XX); + } + + //3 1.) Check if C2H packet is received + if (rx_desc_status.C2HPkt) { + //printk("rcv c2h pkt\n"); + //priv->ext_stats.rx_reuse++; + //printk("%s(%d), C2H reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + validate_C2HPkt(priv, pfrinfo); +#if 0//def CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + C2HPacketHandler_92E(priv, get_pframe(pfrinfo), pfrinfo->pktlen); // no CRC in C2H_PACKET + } +#endif + pskb->data -= skb_shift_size; // skb_shift_size == sizeof(RX_DESC_88XX) + pskb->tail -= skb_shift_size; // skb_shift_size == sizeof(RX_DESC_88XX) + goto rx_reuse; + } + +#if defined(RX_BUFFER_GATHER) + if (TRUE == rx_desc_status.PHYST && ((priv->pshare->gather_state == GATHER_STATE_FIRST) || (priv->pshare->gather_state == GATHER_STATE_NO))) +#else + if (TRUE == rx_desc_status.PHYST) +#endif + { + pfrinfo->driver_info = (struct RxFWInfo *)(get_pframe(pfrinfo)); + } + else { + //printk("%s(%d): driver_info pointer error\n", __FUNCTION__, __LINE__); + } + + pfrinfo->physt = rx_desc_status.PHYST; + pfrinfo->paggr = rx_desc_status.PAGGR; + pfrinfo->faggr = 0; + pfrinfo->rx_splcp = 0; +#ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pfrinfo->macid = rx_desc_status.rxMACID; + } +#endif //HW_FILL_MACID + pfrinfo->rx_bw = 0; + + if(priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + if (rx_desc_status.RX_RATE < 12) { + pfrinfo->rx_rate = dot11_rate_table[rx_desc_status.RX_RATE]; + } else if(rx_desc_status.RX_RATE < 44) { + pfrinfo->rx_rate = HT_RATE_ID + (rx_desc_status.RX_RATE - 12); + } else{ + pfrinfo->rx_rate = VHT_RATE_ID + (rx_desc_status.RX_RATE - 44); + } + } else if (rx_desc_status.RX_RATE < 12) { + pfrinfo->rx_rate = dot11_rate_table[rx_desc_status.RX_RATE]; + } else { + pfrinfo->rx_rate = HT_RATE_ID + (rx_desc_status.RX_RATE - 12); + } + + if (!pfrinfo->physt) { + pfrinfo->rssi = 0; + } else { +#if defined(RX_BUFFER_GATHER) + if (pfrinfo->driver_info_size > 0) +#endif + { + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + translate_rssi_sq_outsrc(priv, pfrinfo, rx_desc_status.RX_RATE); + } +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + translate_rssi_sq(priv, pfrinfo); + } +#endif + + } + } + +#if defined(CONFIG_RTL8190_PRIV_SKB) + { +#if defined(DELAY_REFILL_RX_BUF) + // Use REFILL_THRESHOLD-2 because we should keep at least 2 skb to trigger movement of host_idx + cmp_flags = (CIRC_CNT_RTK(cur_q->cur_host_idx, + (cur_q->host_idx+cur_q->rxbd_ok_cnt)%cur_q->total_rxbd_num, NUM_RX_DESC) >= REFILL_THRESHOLD-2); + + if (cmp_flags) { + DEBUG_WARN("out of skb_buff\n"); + priv->ext_stats.rx_reuse++; + DEBUG_WARN("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + priv->ext_stats.reused_skb++; + pskb->data -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + pskb->tail -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + goto rx_reuse; + } + new_skb = NULL; +#else + new_skb = rtl_dev_alloc_skb(priv, RX_BUF_LEN, _SKB_RX_, 0); + if (new_skb == NULL) { + DEBUG_WARN("out of skb_buff\n"); + priv->ext_stats.rx_reuse++; + //printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + priv->ext_stats.reused_skb++; + pskb->data -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + pskb->tail -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + goto rx_reuse; + } +#endif + } +#else /* defined(CONFIG_RTL8190_PRIV_SKB) */ + +#if defined(DELAY_REFILL_RX_BUF) + // TODO: REFILL_THRESHOLD or REFILL_THRESHOLD-1? + cmp_flags = (CIRC_CNT_RTK(cur_q->cur_host_idx, + (cur_q->host_idx+cur_q->rxbd_ok_cnt)%cur_q->total_rxbd_num, NUM_RX_DESC) > REFILL_THRESHOLD); + + if (cmp_flags) { + DEBUG_WARN("out of skb_buff\n"); + priv->ext_stats.rx_reuse++; + printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + priv->ext_stats.reused_skb++; + pskb->data -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + pskb->tail -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + goto rx_reuse; + } + new_skb = NULL; +#else + + // allocate new one in advance + new_skb = rtl_dev_alloc_skb(priv, RX_BUF_LEN, _SKB_RX_, 0); + if (new_skb == NULL) { + DEBUG_WARN("out of skb_buff\n"); + priv->ext_stats.rx_reuse++; + printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + priv->ext_stats.reused_skb++; + pskb->data -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + pskb->tail -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + goto rx_reuse; + } +#endif +#endif + + /*----------------------------------------------------- + validate_mpdu will check if we still can reuse the skb + ------------------------------------------------------*/ +#if defined(CONFIG_RTL_QOS_PATCH) || defined(CONFIG_RTK_VOIP_QOS) || defined(CONFIG_RTK_VLAN_WAN_TAG_SUPPORT) + pskb->srcPhyPort = QOS_PATCH_RX_FROM_WIRELESS; +#endif + +#if defined(MP_TEST) + if (OPMODE & WIFI_MP_STATE) { + skb_reserve(pskb, (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size)); + skb_shift_size += (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + reuse = 1; + find_flag=1; + //------------------------------------------------------------------------------------------- + if((OPMODE & WIFI_MP_ARX_FILTER ) && (OPMODE & WIFI_MP_RX ) ) + { + pframe = get_pframe(pfrinfo); + sa = get_sa(pframe); + da = get_da(pframe); + bssid =get_bssid_mp(pframe); + if(priv->pshare->mp_filter_flag & 0x1) + { + //sa = get_sa(pframe); + if(memcmp(priv->pshare->mp_filter_SA,sa,MACADDRLEN)) + { + find_flag=0; + } + } + if(find_flag) + { + if(priv->pshare->mp_filter_flag & 0x2) + { + //da = get_da(pframe); + if(memcmp(priv->pshare->mp_filter_DA,da,MACADDRLEN)) + { + find_flag=0; + } + } + } + if(find_flag) + { + if(priv->pshare->mp_filter_flag & 0x4) + { + //bssid =get_bssid_mp(pframe); + if(memcmp(priv->pshare->mp_filter_BSSID,bssid,MACADDRLEN)) + { + find_flag=0; + } + } + } + #if 0 + if(find_flag) + { + printk("flag: %x\nSA: %02x:%02x:%02x:%02x:%02x:%02x\nDA: %02x:%02x:%02x:%02x:%02x:%02x\nBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",priv->pshare->mp_filter_flag, + sa[0], sa[1], sa[2], sa[3], sa[4], sa[5], + da[0], da[1], da[2], da[3], da[4], da[5], + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + } + #endif + } + //------------------------------------------------------------------------------------------- + if(find_flag) + { + #if defined(B2B_TEST) + mp_validate_rx_packet(priv, pskb->data, pfrinfo->pktlen); + #endif + rx_sum_up(priv, NULL, pfrinfo->pktlen, GetRetry(get_pframe(pfrinfo))); + //if (priv->pshare->rf_ft_var.rssi_dump) + update_sta_rssi(priv, NULL, pfrinfo); + } + + pskb->data -= skb_shift_size; // skb_shift_size is (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size + sizeof(RX_DESC_88XX)) + pskb->tail -= skb_shift_size; // skb_shift_size is (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size + sizeof(RX_DESC_88XX)) + } + else +#endif // defined(MP_TEST) + { + + // 64 is the value in init_rxdesc_88XX: *pBufLen = RX_BUF_LEN - sizeof(struct rx_frinfo) - 64; + // Actually, the precise value is the offset, but the value is 64 in old version code (rtl8192cd). +#if defined(RX_BUFFER_GATHER) + if (rx_desc_status.FS == 0x01 && rx_desc_status.LS == 0x01) { + skb_used_size = 64 + sizeof(struct rx_frinfo) + SIZE_RXDESC_88XX + + pfrinfo->driver_info_size + pfrinfo->rxbuf_shift + pfrinfo->pktlen + _CRCLNG_; + } else if (rx_desc_status.FS == 0x01 && rx_desc_status.LS == 0x0) { + skb_used_size = 64 + sizeof(struct rx_frinfo) + SIZE_RXDESC_88XX + + pfrinfo->driver_info_size + pfrinfo->rxbuf_shift + pfrinfo->pktlen; + } else { // (FS,LS) = (0,0) or (0,1) + skb_used_size = 64 + sizeof(struct rx_frinfo) + + pfrinfo->driver_info_size + pfrinfo->rxbuf_shift + pfrinfo->pktlen; + } +#else + skb_used_size = 64 + sizeof(struct rx_frinfo) + SIZE_RXDESC_88XX + + pfrinfo->driver_info_size + pfrinfo->rxbuf_shift + pfrinfo->pktlen + _CRCLNG_; +#endif + + if (skb_used_size <= RX_BUF_LEN) { + skb_reserve(pskb, (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size)); + skb_shift_size += (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + + if (rx_desc_status.ICVERR) { + rx_pkt_exception_88XX(priv, rx_desc_status.CRC32, rx_desc_status.ICVERR); + pskb->data -= skb_shift_size; // skb_shift_size is (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size + sizeof(RX_DESC_88XX)) + pskb->tail -= skb_shift_size; // skb_shift_size is (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size + sizeof(RX_DESC_88XX)) +#if !defined(DELAY_REFILL_RX_BUF) || !defined(CONFIG_RTL8190_PRIV_SKB) //we create this, but we do not free it! + if (new_skb != NULL) + rtl_kfree_skb(priv, new_skb, _SKB_RX_); +#endif + priv->ext_stats.rx_reuse++; + printk("%s(%d), reuse(0x%x)\n", __FUNCTION__, __LINE__, (unsigned int)priv->ext_stats.rx_reuse); + goto rx_reuse; + } + + SNMP_MIB_INC(dot11ReceivedFragmentCount, 1); + + #if defined(SW_ANT_SWITCH) + if(priv->pshare->rf_ft_var.antSw_enable) { + dm_SWAW_RSSI_Check(priv, pfrinfo); + } + #endif + +#if defined(RX_BUFFER_GATHER) + if (priv->pshare->gather_state != GATHER_STATE_NO) { + list_add_tail(&pfrinfo->rx_list, &priv->pshare->gather_list); + + if (priv->pshare->gather_state == GATHER_STATE_LAST) { + if (!search_first_segment(priv, &pfrinfo)) { + reuse = 0; + } else { + pskb = pfrinfo->pskb; + pfrinfo_update = 1; + } + priv->pshare->gather_state = GATHER_STATE_NO; + } else { + reuse = 0; + } + } + if (priv->pshare->gather_state == GATHER_STATE_NO && reuse) +#endif + { +#ifdef BEAMFORMING_SUPPORT + unsigned char *pframe = get_pframe(pfrinfo); + unsigned int frtype = GetFrameSubType(pframe); + if( frtype== Type_Action_No_Ack || frtype == Type_NDPA ) { + if( frtype== Type_Action_No_Ack) { + priv->pshare->rf_ft_var.csi_counter++; + priv->pshare->rf_ft_var.csi_counter %= priv->pshare->rf_ft_var.dumpcsi; + if( priv->pshare->rf_ft_var.dumpcsi && + priv->pshare->rf_ft_var.csi_counter==1) + { + if ((pfrinfo->physt)&& (pfrinfo->driver_info_size > 0)) { + } + } + } + else /*if(frtype == Type_NDPA) */{ + } + reuse = 1; + }else +#endif + reuse = validate_mpdu(priv, pfrinfo); + } + + if (reuse) { + pskb->data -= skb_shift_size; // skb_shift_size is (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size + sizeof(RX_DESC_88XX)) + pskb->tail -= skb_shift_size; // skb_shift_size is (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size + sizeof(RX_DESC_88XX)) + +#ifdef RX_BUFFER_GATHER + if (pfrinfo->gather_flag & GATHER_FIRST){ + //flush_rx_list(priv); + rtl_kfree_skb(priv, pskb, _SKB_RX_); + reuse = 0; + // printk("%s(%d), Gather-First packet error, free skb\n", __FUNCTION__, __LINE__); + DEBUG_WARN("Gather-First packet error, free skb\n"); + } +#endif + } + else { + //free skb by upper layer, i.e., validate_mpdu + //So, we don't need to control skb data/tail pointer + } + } + else { + pskb->data -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + pskb->tail -= skb_shift_size; // skb_shift_size is sizeof(RX_DESC_88XX) + } + } + } /* if (cmd&XXXX) */ + + if (!reuse) { + phw->rx_infoL[cur_q->cur_host_idx].pbuf = NULL; + +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if (IS_PCIBIOS_TYPE) { +// pci_unmap_single(priv->pshare->pdev, phw->rx_infoL[cur_q->cur_host_idx].paddr, (RX_BUF_LEN - sizeof(struct rx_frinfo)), PCI_DMA_FROMDEVICE); + } +#endif + +#if defined(DELAY_REFILL_RX_BUF) +#if defined(CONFIG_RTL8190_PRIV_SKB) +#ifdef CONCURRENT_MODE + if (skb_free_num[priv->pshare->wlandev_idx] == 0 && priv->pshare->skb_queue.qlen == 0) +#else + if (skb_free_num == 0 && priv->pshare->skb_queue.qlen == 0) +#endif + { + refill = 0; + goto rx_done; + } +#endif + new_skb = rtl_dev_alloc_skb(priv, RX_BUF_LEN, _SKB_RX_, 0); + ASSERT(new_skb); + if(new_skb == NULL) { + printk("not enough memory...\n"); + refill = 0; + goto rx_done; + } + +#endif + pskb = new_skb; + +#if defined(DELAY_REFILL_RX_BUF) + GET_HAL_INTERFACE(priv)->UpdateRXBDInfoHandler(priv, q_num, + (cur_q->host_idx+cur_q->rxbd_ok_cnt)%cur_q->total_rxbd_num, (pu1Byte)pskb, init_rxdesc_88XX, _FALSE); +#else + GET_HAL_INTERFACE(priv)->UpdateRXBDInfoHandler(priv, q_num, cur_q->cur_host_idx, (pu1Byte)pskb, init_rxdesc_88XX, _FALSE); +#endif + goto rx_done; + + } /* if (!reuse) */ +#if !defined(DELAY_REFILL_RX_BUF) + else { + rtl_kfree_skb(priv, new_skb, _SKB_RX_); + } +#endif + +rx_reuse: + #if 0 //Filen: for debug + { + static unsigned int rx_reuse_cnt = 0; + + rx_reuse_cnt++; + printk("%s(%d): reuse(0x%x), rx_reuse_cnt(0x%x), pkt_len: 0x%x\n", + __FUNCTION__, __LINE__, reuse, rx_reuse_cnt, rx_desc_status.PKT_LEN); + } + #endif + +#if defined(DELAY_REFILL_RX_BUF) +#if defined(RX_BUFFER_GATHER) + cmp_flags = (cur_q->cur_host_idx != (cur_q->host_idx+cur_q->rxbd_ok_cnt)%cur_q->total_rxbd_num) || pfrinfo_update; +#else + cmp_flags = (cur_q->cur_host_idx != (cur_q->host_idx+cur_q->rxbd_ok_cnt)%cur_q->total_rxbd_num); +#endif // RX_BUFFER_GATHER + + if (cmp_flags) + { + phw->rx_infoL[cur_q->cur_host_idx].pbuf = NULL; + pskb->data = pskb->head; + pskb->tail = pskb->head; + // TODO: why skb_reserve 128 + #ifdef __ECOS + skb_reserve(pskb, 32); + #else + skb_reserve(pskb, 128); + #endif +#if defined(CONFIG_RTL8196_RTL8366) + skb_reserve(pskb, 8); +#endif +#if defined(CONFIG_RTK_VOIP_VLAN_ID) + skb_reserve(pskb, 4); +#endif + refill_rx_ring_88XX(priv, pskb, NULL, q_num, cur_q); + refill = 0; + } else +#endif /* defined(DELAY_REFILL_RX_BUF) */ + { + u4Byte offset; +#if defined(RX_BUFFER_GATHER) + if (pfrinfo != NULL) { + pfrinfo->gather_flag = 0; + } +#endif + offset = GetOffsetStartToRXDESC(priv, pskb); +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) +// phw->rx_infoL[cur_q->cur_host_idx].paddr = get_physical_addr(priv, pskb->data, (RX_BUF_LEN - sizeof(struct rx_frinfo) - offset), PCI_DMA_FROMDEVICE); + + pskb->data -= (sizeof(struct rx_frinfo) + offset); + pskb->tail -= (sizeof(struct rx_frinfo) + offset); + + GET_HAL_INTERFACE(priv)->UpdateRXBDInfoHandler(priv, q_num, cur_q->cur_host_idx, (pu1Byte)pskb, init_rxdesc_88XX, _FALSE); + // Remove it because pci_map_single() in get_physical_addr() already performed memory sync. + //rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(phw->rx_infoL[cur_q->cur_host_idx].paddr), + // RX_BUF_LEN - sizeof(struct rx_frinfo) - offset, + // PCI_DMA_FROMDEVICE); +#else +#ifdef TRXBD_CACHABLE_REGION + memset(phw->rx_infoL[cur_q->cur_host_idx].paddr, 0, RX_BUF_LEN - sizeof(struct rx_frinfo) - offset); + _dma_cache_wback((unsigned long)(bus_to_virt(phw->rx_infoL[cur_q->cur_host_idx].paddr)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), + RX_BUF_LEN - sizeof(struct rx_frinfo) - offset); + +// _dma_cache_inv((unsigned long)(bus_to_virt(phw->rx_infoL[cur_q->cur_host_idx].paddr)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), +// RX_BUF_LEN - sizeof(struct rx_frinfo) - offset); +#else + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(phw->rx_infoL[cur_q->cur_host_idx].paddr), + RX_BUF_LEN - sizeof(struct rx_frinfo) - offset, + PCI_DMA_FROMDEVICE); +#endif + +#endif + + } + +rx_done: + + cur_q->cur_host_idx = (cur_q->cur_host_idx+1) % cur_q->total_rxbd_num; + +#if CFG_UPDATE_RX_SWBD_IDX_EARLY + update = 0; + if(cur_q->cur_host_idx == cur_q->hw_idx) { + GET_HAL_INTERFACE(priv)->UpdateRXBDHWIdxHandler(priv, q_num); + update = 1; + } +#endif + +#if defined(DELAY_REFILL_RX_BUF) + if (refill) { + cur_q->rxbd_ok_cnt++; + } +#else + rxbdOkCnt++; +#endif // DELAY_REFILL_RX_BUF + +#if CFG_UPDATE_RX_SWBD_IDX_EARLY + if (update) { +#if defined(DELAY_REFILL_RX_BUF) + GET_HAL_INTERFACE(priv)->UpdateRXBDHostIdxHandler(priv, q_num, cur_q->rxbd_ok_cnt); + cur_q->rxbd_ok_cnt = 0; +#else + GET_HAL_INTERFACE(priv)->UpdateRXBDHostIdxHandler(priv, q_num, rxbdOkCnt); + rxbdOkCnt = 0; +#endif + } +#endif //CFG_UPDATE_RX_SWBD_IDX_EARLY + } /* while(1) */ + +//#if !CFG_UPDATE_RX_SWBD_IDX_EARLY +#if defined(DELAY_REFILL_RX_BUF) + GET_HAL_INTERFACE(priv)->UpdateRXBDHostIdxHandler(priv, q_num, cur_q->rxbd_ok_cnt); + cur_q->rxbd_ok_cnt = 0; +#else + GET_HAL_INTERFACE(priv)->UpdateRXBDHostIdxHandler(priv, q_num, rxbdOkCnt); +#endif +//#endif //!CFG_UPDATE_RX_SWBD_IDX_EARLY + + RTL_WLAN_RX_ATOMIC_PROTECT_EXIT; + + SMP_UNLOCK_RECV(y); + + if (!IS_DRV_OPEN(priv)) + return; + +#if defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX) + if (OPMODE & WIFI_AP_STATE) { + if (!list_empty(&priv->wakeup_list)) + process_dzqueue(priv); + +#if defined(MBSSID) + if (priv->pmib->miscEntry.vap_enable) { + int i; + struct rtl8192cd_priv *priv_vap; + + for (i=0; ipvap_priv[i])) { + priv_vap = priv->pvap_priv[i]; + if (!list_empty(&priv_vap->wakeup_list)) + process_dzqueue(priv_vap); + } + } + } +#endif + } +#ifdef UNIVERSAL_REPEATER + else { + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + if (!list_empty(&GET_VXD_PRIV(priv)->wakeup_list)) + process_dzqueue(GET_VXD_PRIV(priv)); + } +#endif +#endif /* defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX) */ + + if(priv->pshare->skip_mic_chk) + --priv->pshare->skip_mic_chk; +} +#endif // CONFIG_WLAN_HAL + +#ifdef CONFIG_RTK_VOIP_QOS +extern int ( *check_voip_channel_loading )( void ); +#endif +#ifndef __ECOS +#ifndef __LINUX_2_6__ +__MIPS16 +#endif +#endif +__IRAM_IN_865X +void rtl8192cd_rx_isr(struct rtl8192cd_priv *priv) +{ + struct rx_desc *pdesc, *prxdesc; + struct rtl8192cd_hw *phw; + struct sk_buff *pskb, *new_skb; + struct rx_frinfo *pfrinfo; + unsigned int tail; + unsigned int cmd, reuse; +#ifdef DELAY_REFILL_RX_BUF + unsigned int cmp_flags; +#endif + unsigned int rtl8192cd_ICV; +#if (defined(__ECOS) ||defined(__LINUX_2_6__)) && defined(RX_TASKLET) + unsigned long x; +#if defined(SMP_SYNC) + unsigned long y = 0; +#endif +#endif +#if defined(DELAY_REFILL_RX_BUF) + int refill; +#endif +#if defined(MP_TEST) + unsigned char *sa,*da,*bssid; + char *pframe; + unsigned int find_flag; +#endif +#if defined(CONFIG_RTL8190_PRIV_SKB) +#ifdef CONCURRENT_MODE + extern int skb_free_num[]; +#else + extern int skb_free_num; +#endif +#endif +#if defined(RX_BUFFER_GATHER) + int pfrinfo_update; +#endif + +#if /*defined(__ECOS) ||*/ (defined (CONFIG_RTK_VOIP_QOS) && !defined (CONFIG_RTK_VOIP_ETHERNET_DSP_IS_HOST)) + unsigned long start_time = jiffies; + int n = 0; +#endif +#ifdef RX_LOOP_LIMIT + unsigned int loop_cnt = 0; +#endif + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { + rtl88XX_rx_isr(priv); + return; + }else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + { + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + SMP_LOCK_RECV(y); + + phw = GET_HW(priv); + tail = phw->cur_rx; + +#if defined(RTL8190_CACHABLE_DESC) + prxdesc = (struct rx_desc *)(phw->rx_descL); + rtl_cache_sync_wback(priv, (unsigned long)prxdesc, sizeof(struct rx_desc), PCI_DMA_FROMDEVICE); +#else +#if defined(__MIPSEB__) + prxdesc = (struct rx_desc *)((unsigned long)(phw->rx_descL) | 0x20000000); +#else + prxdesc = (struct rx_desc *)(phw->rx_descL); +#endif +#endif /* RTL8190_CACHABLE_DESC */ + + while (1) + { +#if 0 //def __ECOS + if ((n++ > 100) || ((jiffies - start_time) >= 1)) + { + break; + } +#endif + +#ifdef RX_LOOP_LIMIT + if ((priv->pmib->dot11StationConfigEntry.limit_rxloop > 0) && + (loop_cnt++ > priv->pmib->dot11StationConfigEntry.limit_rxloop)) + break; +#endif + +#if defined (CONFIG_RTK_VOIP_QOS) && !defined (CONFIG_RTK_VOIP_ETHERNET_DSP_IS_HOST) + if ( (n++ > 100 || (jiffies - start_time) >= 1 )&& (check_voip_channel_loading && (check_voip_channel_loading() > 0)) ) + { + break; + } +#endif +#if defined(DELAY_REFILL_RX_BUF) + refill = 1; + + /* + if (((tail+1) % NUM_RX_DESC) == phw->cur_rx_refill) { + break; + }*/ + RTL_WLAN_RX_ATOMIC_PROTECT_ENTER; + cmp_flags = ( ((tail+1)==NUM_RX_DESC?0:tail+1) == phw->cur_rx_refill ); + RTL_WLAN_RX_ATOMIC_PROTECT_EXIT; + + if (cmp_flags) { + break; + } +#endif + +#if defined(RX_BUFFER_GATHER) + pfrinfo_update = 0; +#endif + + pdesc = prxdesc + tail; + cmd = get_desc(pdesc->Dword0); + reuse = 1; + + if (cmd & RX_OWN) + break; + #if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if (IS_PCIBIOS_TYPE) { + pci_unmap_single(priv->pshare->pdev, phw->rx_infoL[tail].paddr, (cmd & RX_PktLenMask), PCI_DMA_FROMDEVICE); + } + #endif + + pskb = (struct sk_buff *)(phw->rx_infoL[tail].pbuf); + pfrinfo = get_pfrinfo(pskb); + +#ifdef MP_SWITCH_LNA + if((GET_CHIP_VER(priv) == VERSION_8192D) && priv->pshare->rf_ft_var.mp_specific) + dynamic_switch_lna(priv); +#endif + + if (cmd & RX_CRC32) { + /*printk("CRC32 happens~!!\n");*/ + rx_pkt_exception(priv, cmd); + goto rx_reuse; + } +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + else if ((GET_CHIP_VER(priv)==VERSION_8188E) && + (((get_desc(pdesc->Dword3) >> RXdesc_88E_RptSelSHIFT) & RXdesc_88E_RptSelMask) == 2)) { + pfrinfo->pktlen = (cmd & RX_PktLenMask); + if (get_desc(pdesc->Dword4) || get_desc(pdesc->Dword5)) +#ifdef RATEADAPTIVE_BY_ODM + ODM_RA_TxRPT2Handle_8188E(ODMPTR, pskb->data, pfrinfo->pktlen, get_desc(pdesc->Dword4), get_desc(pdesc->Dword5)); +#else + RTL8188E_TxReportHandler(priv, pskb, get_desc(pdesc->Dword4), get_desc(pdesc->Dword5), pdesc); +#endif + goto rx_reuse; + } else if ((GET_CHIP_VER(priv)==VERSION_8188E) && + ((get_desc(pdesc->Dword3) >> RXdesc_88E_RptSelSHIFT) & RXdesc_88E_RptSelMask)) { + printk("%s %d, Rx report select mismatch, val:%d\n", __FUNCTION__, __LINE__, + ((get_desc(pdesc->Dword3) >> RXdesc_88E_RptSelSHIFT) & RXdesc_88E_RptSelMask)); + goto rx_reuse; + } +#endif +#if !defined(RX_BUFFER_GATHER) + else if ((cmd & (RX_FirstSeg | RX_LastSeg)) != (RX_FirstSeg | RX_LastSeg)) { + // h/w use more than 1 rx descriptor to receive a packet + // that means this packet is too large + // drop such kind of packet + goto rx_reuse; + } +#endif + else if (!IS_DRV_OPEN(priv)) { + goto rx_reuse; + } else { + pfrinfo->pskb = pskb; + pfrinfo->pktlen = (cmd & RX_PktLenMask) - _CRCLNG_; + +#if defined(RX_BUFFER_GATHER) + if ((cmd & (RX_FirstSeg | RX_LastSeg)) != (RX_FirstSeg | RX_LastSeg)) { + if ((cmd & RX_FirstSeg) && priv->pshare->gather_state == GATHER_STATE_NO) { + priv->pshare->gather_state = GATHER_STATE_FIRST; + priv->pshare->gather_len = pfrinfo->pktlen; + pfrinfo->gather_flag = GATHER_FIRST; + } else if (!(cmd & (RX_FirstSeg | RX_LastSeg)) && + (priv->pshare->gather_state == GATHER_STATE_FIRST || priv->pshare->gather_state == GATHER_STATE_MIDDLE)) { + priv->pshare->gather_state = GATHER_STATE_MIDDLE; + priv->pshare->gather_len += pfrinfo->pktlen; + pfrinfo->gather_flag = GATHER_MIDDLE; + } else if ((cmd & RX_LastSeg) && + (priv->pshare->gather_state == GATHER_STATE_FIRST || priv->pshare->gather_state == GATHER_STATE_MIDDLE)) { + priv->pshare->gather_state = GATHER_STATE_LAST; + pfrinfo->pktlen -= priv->pshare->gather_len; + pfrinfo->gather_flag = GATHER_LAST; + } else { + if (priv->pshare->gather_state != GATHER_STATE_NO) { + DEBUG_ERR("Rx pkt not in sequence [%x, %x]!\n", (cmd & (RX_FirstSeg | RX_LastSeg)), priv->pshare->gather_state); + flush_rx_list(priv); + priv->pshare->gather_state = GATHER_STATE_NO; + } + goto rx_reuse; + } + } else { + if (priv->pshare->gather_state != GATHER_STATE_NO) { + DEBUG_ERR("Rx pkt not in valid gather state [%x]!\n", priv->pshare->gather_state); + flush_rx_list(priv); + priv->pshare->gather_state = GATHER_STATE_NO; + } + } + if (pfrinfo->gather_flag && pfrinfo->gather_flag != GATHER_FIRST) { + pfrinfo->driver_info_size = 0; + pfrinfo->rxbuf_shift = 0; + } + else +#endif /* RX_BUFFER_GATHER */ + { + pfrinfo->driver_info_size = ((cmd >> RX_DrvInfoSizeSHIFT) & RX_DrvInfoSizeMask)<<3; + pfrinfo->rxbuf_shift = (cmd & (RX_ShiftMask << RX_ShiftSHIFT)) >> RX_ShiftSHIFT; + } + +#if defined(RX_BUFFER_GATHER) + if (pfrinfo->gather_flag) { + pfrinfo->pktlen -= (pfrinfo->driver_info_size - 4); + priv->pshare->gather_len -= (pfrinfo->driver_info_size - 4); + } +#endif + pfrinfo->sw_dec = (cmd & RX_SwDec) >> 27; + pfrinfo->pktlen -= pfrinfo->rxbuf_shift; +#ifdef CONFIG_RTL_8812_SUPPORT + if ( ((GET_CHIP_VER(priv)!= VERSION_8812E) && (pfrinfo->pktlen > 0x2000)) + || ((GET_CHIP_VER(priv)== VERSION_8812E) && (pfrinfo->pktlen > 0x2d00)) + || (pfrinfo->pktlen < 16)) { +#else + if ((pfrinfo->pktlen > 0x2000) || (pfrinfo->pktlen < 16)) { +#endif +#if defined(RX_BUFFER_GATHER) + if (!(pfrinfo->gather_flag && (pfrinfo->pktlen < 16))) +#endif + { + DEBUG_INFO("pfrinfo->pktlen=%d, goto rx_reuse\n",pfrinfo->pktlen); + if( get_desc(pdesc->Dword2) & BIT(28)) { +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + C2HPacketHandler_8812(priv, get_pframe(pfrinfo), pfrinfo->pktlen+4); // no CRC in C2H_PACKET +#endif + } + goto rx_reuse; + } + } + +//#ifdef PCIE_POWER_SAVING_DEBUG +#if 0 + if(priv->firstPkt) { + unsigned char *pp= pdesc ; + printk("rx isr, first pkt: len=%d\n[", pfrinfo->pktlen); + // printHex(pp, sizeof(struct rx_frinfo)); + // printk("------------------\n"); + printHex(pskb->data+32,pfrinfo->pktlen); + priv->firstPkt=0; + printk("]\n\n"); + } +#endif + +#if defined(CONFIG_RTL865X_CMO) + if (pfrinfo->pskb == NULL) { + panic_printk(" rtl8192cd_rx_isr(): pfrinfo->pskb = NULL.\n"); + pfrinfo->pskb = pskb; + goto rx_reuse; + } +#endif + + pfrinfo->driver_info = (struct RxFWInfo *)(get_pframe(pfrinfo)); + pfrinfo->physt = (get_desc(pdesc->Dword0) & RX_PHYST)? 1:0; +#if defined(CONFIG_RTL_8812_SUPPORT) //eric_8812 ?? + if (GET_CHIP_VER(priv)==VERSION_8812E) + { + pfrinfo->paggr = (get_desc(pdesc->Dword1) & RXdesc_92E_PAGGR)? 1:0; + pfrinfo->faggr = 0; + if (IS_C_CUT_8812(priv)) { + pfrinfo->rx_bw = (get_desc(pdesc->Dword4)>>4)&0x3; + pfrinfo->rx_splcp = (get_desc(pdesc->Dword4))&0x01; + } else { + pfrinfo->rx_bw = 0; + pfrinfo->rx_splcp = 0; + } + } + else +#endif + { + pfrinfo->faggr = (get_desc(pdesc->Dword1) & RX_FAGGR)? 1:0; + pfrinfo->paggr = (get_desc(pdesc->Dword1) & RX_PAGGR)? 1:0; + pfrinfo->rx_bw = (get_desc(pdesc->Dword3) & RX_BW)? 1:0; + pfrinfo->rx_splcp = (get_desc(pdesc->Dword3) & RX_SPLCP)? 1:0; + } + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + { + unsigned int rxdesc_rate = (get_desc(pdesc->Dword3)& 0x7f); + if (rxdesc_rate < 12) { + pfrinfo->rx_rate = dot11_rate_table[rxdesc_rate]; + } else if(rxdesc_rate < 44) { + pfrinfo->rx_rate = HT_RATE_ID +(rxdesc_rate - 12); + } else{ + pfrinfo->rx_rate = VHT_RATE_ID +(rxdesc_rate - 44); + } + } + else +#endif + if ((get_desc(pdesc->Dword3)&RX_RxMcsMask) < 12) { + pfrinfo->rx_rate = dot11_rate_table[(get_desc(pdesc->Dword3)&RX_RxMcsMask)]; + } else { + pfrinfo->rx_rate = HT_RATE_ID + ((get_desc(pdesc->Dword3)&RX_RxMcsMask)-12); + } + + if (!pfrinfo->physt) { + pfrinfo->rssi = 0; + } else { +#if defined(RX_BUFFER_GATHER) + if (pfrinfo->driver_info_size > 0) +#endif + { +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + translate_rssi_sq_outsrc(priv, pfrinfo, (get_desc(pdesc->Dword3)&RX_RxMcsMask)); + } +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + translate_rssi_sq(priv, pfrinfo); + } +#endif + } + } + +#if defined(CONFIG_RTL8190_PRIV_SKB) + { +#if defined(DELAY_REFILL_RX_BUF) + RTL_WLAN_RX_ATOMIC_PROTECT_ENTER; + cmp_flags = (CIRC_CNT_RTK(tail, phw->cur_rx_refill, NUM_RX_DESC) > REFILL_THRESHOLD); + RTL_WLAN_RX_ATOMIC_PROTECT_EXIT; + if (cmp_flags) { + DEBUG_WARN("out of skb_buff\n"); + priv->ext_stats.reused_skb++; + goto rx_reuse; + } + new_skb = NULL; +#else +// if (skb_free_num== 0 && priv->pshare->skb_queue.qlen == 0) { + new_skb = rtl_dev_alloc_skb(priv, RX_BUF_LEN, _SKB_RX_, 0); + if (new_skb == NULL) { + DEBUG_WARN("out of skb_buff\n"); + priv->ext_stats.reused_skb++; + goto rx_reuse; + } +#endif + } +#else /* defined(CONFIG_RTL8190_PRIV_SKB) */ +#if defined(DELAY_REFILL_RX_BUF) + RTL_WLAN_RX_ATOMIC_PROTECT_ENTER; + cmp_flags = (CIRC_CNT_RTK(tail, phw->cur_rx_refill, NUM_RX_DESC) > REFILL_THRESHOLD); + RTL_WLAN_RX_ATOMIC_PROTECT_EXIT; + if (cmp_flags) { + DEBUG_WARN("out of skb_buff\n"); + priv->ext_stats.reused_skb++; + goto rx_reuse; + } + new_skb = NULL; +#else + // allocate new one in advance + new_skb = rtl_dev_alloc_skb(priv, RX_BUF_LEN, _SKB_RX_, 0); + if (new_skb == NULL) { + DEBUG_WARN("out of skb_buff\n"); + priv->ext_stats.reused_skb++; + goto rx_reuse; + } +#endif +#endif + + /*----------------------------------------------------- + validate_mpdu will check if we still can reuse the skb + ------------------------------------------------------*/ +#if defined(CONFIG_RTL_QOS_PATCH) || defined(CONFIG_RTK_VOIP_QOS) || defined(CONFIG_RTK_VLAN_WAN_TAG_SUPPORT) + pskb->srcPhyPort = QOS_PATCH_RX_FROM_WIRELESS; +#endif + +#if defined(MP_TEST) + if (OPMODE & WIFI_MP_STATE) { + skb_reserve(pskb, (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size)); + reuse = 1; + find_flag=1; + //------------------------------------------------------------------------------------------- + if((OPMODE & WIFI_MP_ARX_FILTER ) && (OPMODE & WIFI_MP_RX ) ) + { + pframe = get_pframe(pfrinfo); + sa = get_sa(pframe); + da = get_da(pframe); + bssid =get_bssid_mp(pframe); + if(priv->pshare->mp_filter_flag & 0x1) + { + //sa = get_sa(pframe); + if(memcmp(priv->pshare->mp_filter_SA,sa,MACADDRLEN)) + { + find_flag=0; + } + } + if(find_flag) + { + if(priv->pshare->mp_filter_flag & 0x2) + { + //da = get_da(pframe); + if(memcmp(priv->pshare->mp_filter_DA,da,MACADDRLEN)) + { + find_flag=0; + } + } + } + if(find_flag) + { + if(priv->pshare->mp_filter_flag & 0x4) + { + //bssid =get_bssid_mp(pframe); + if(memcmp(priv->pshare->mp_filter_BSSID,bssid,MACADDRLEN)) + { + find_flag=0; + } + } + } +#if 0 + if(find_flag) + { + printk("flag: %x\nSA: %02x:%02x:%02x:%02x:%02x:%02x\nDA: %02x:%02x:%02x:%02x:%02x:%02x\nBSSID: %02x:%02x:%02x:%02x:%02x:%02x\n",priv->pshare->mp_filter_flag, + sa[0], + sa[1], + sa[2], + sa[3], + sa[4], + sa[5], + da[0], + da[1], + da[2], + da[3], + da[4], + da[5], + bssid[0], + bssid[1], + bssid[2], + bssid[3], + bssid[4], + bssid[5]); + } +#endif + } + //------------------------------------------------------------------------------------------- + if(find_flag) + { +#if defined(B2B_TEST) + mp_validate_rx_packet(priv, pskb->data, pfrinfo->pktlen); +#endif + rx_sum_up(priv, NULL, pfrinfo->pktlen, GetRetry(get_pframe(pfrinfo))); + if (priv->pshare->rf_ft_var.rssi_dump) + update_sta_rssi(priv, NULL, pfrinfo); + } + pskb->data -= (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + pskb->tail -= (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + } + else +#endif // defined(MP_TEST) + { +#if defined(RX_BUFFER_GATHER) + #define RTL_WLAN_DRV_RX_GATHER_GAP_THRESHOLD 32 +#else + #define RTL_WLAN_DRV_RX_GATHER_GAP_THRESHOLD 64 +#endif + + if (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size + pfrinfo->pktlen + _CRCLNG_ <= (RX_BUF_LEN- sizeof(struct rx_frinfo)-RTL_WLAN_DRV_RX_GATHER_GAP_THRESHOLD) ) { + skb_reserve(pskb, (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size)); + if (cmd & RX_ICVERR) { + rtl8192cd_ICV = 1; +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + /* 88C, 92C, and 92D need to check privacy algorithm and accept icv error packet when using CCMP, + because hw may report wrong icv status when using CCMP privacy + */ + rtl8192cd_ICV = check_icverr_drop(priv, pfrinfo); +#endif + + if (rtl8192cd_ICV) { + rx_pkt_exception(priv, cmd); + pskb->data -= (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + pskb->tail -= (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); +#if !defined(DELAY_REFILL_RX_BUF) || !defined(CONFIG_RTL8190_PRIV_SKB) //we create this, but we do not free it! + if (new_skb != NULL) + rtl_kfree_skb(priv, new_skb, _SKB_RX_); +#endif + goto rx_reuse; + } + + } + +// printk("pkt in\n"); + SNMP_MIB_INC(dot11ReceivedFragmentCount, 1); + +#if defined(SW_ANT_SWITCH) + if(priv->pshare->rf_ft_var.antSw_enable) { + dm_SWAW_RSSI_Check(priv, pfrinfo); + } +#endif + +#if defined(RX_BUFFER_GATHER) + if (priv->pshare->gather_state != GATHER_STATE_NO) { + list_add_tail(&pfrinfo->rx_list, &priv->pshare->gather_list); + + if (priv->pshare->gather_state == GATHER_STATE_LAST) { + if (!search_first_segment(priv, &pfrinfo)) + reuse = 0; + else { + pskb = pfrinfo->pskb; + pfrinfo_update = 1; + } + priv->pshare->gather_state = GATHER_STATE_NO; + } else { + reuse = 0; + } + } + if (priv->pshare->gather_state == GATHER_STATE_NO && reuse) +#endif + { +#ifdef BEAMFORMING_SUPPORT + unsigned char *pframe = get_pframe(pfrinfo); + unsigned int frtype = GetFrameSubType(pframe); + if( frtype== Type_Action_No_Ack || frtype == Type_NDPA ) { + if( frtype== Type_Action_No_Ack) { + priv->pshare->rf_ft_var.csi_counter++; + if(priv->pshare->rf_ft_var.dumpcsi) + priv->pshare->rf_ft_var.csi_counter %= priv->pshare->rf_ft_var.dumpcsi; + if( priv->pshare->rf_ft_var.dumpcsi && + priv->pshare->rf_ft_var.csi_counter==1) + { +#if 0 + panic_printk("Action_no_Ack: %x %x %x %x\n", + get_desc(pdesc->Dword0), + get_desc(pdesc->Dword1), + get_desc(pdesc->Dword2), + get_desc(pdesc->Dword3) ); + if ((pfrinfo->physt)&& (pfrinfo->driver_info_size > 0)) { + unsigned char *p = pfrinfo->driver_info; + } +#endif + } + } + else if(frtype == Type_NDPA) { +#if 0 + panic_printk("Type_NDPA: %x %x %x %x\n", + get_desc(pdesc->Dword0), + get_desc(pdesc->Dword1), + get_desc(pdesc->Dword2), + get_desc(pdesc->Dword3) + ); +#endif + Beamforming_GetNDPAFrame(priv, pframe); +#if 0 + if ((pfrinfo->physt)&& (pfrinfo->driver_info_size > 0)) { + panic_printk("pRtRfdStatus:(%d)\n", pfrinfo->driver_info_size); + printHex(pfrinfo->driver_info, pfrinfo->driver_info_size); + panic_printk("\n"); + } +#endif + } + reuse = 1; + }else +#endif + reuse = validate_mpdu(priv, pfrinfo); + } + + if (reuse) { + pskb->data -= (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + pskb->tail -= (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + +#ifdef RX_BUFFER_GATHER + if (pfrinfo->gather_flag & GATHER_FIRST){ + //flush_rx_list(priv); + rtl_kfree_skb(priv, pskb, _SKB_RX_); + reuse = 0; + DEBUG_WARN("Gather-First packet error, free skb\n"); + } +#endif + } + } + #undef RTL_WLAN_DRV_RX_GATHER_GAP_THRESHOLD + } + } /* if (cmd&XXXX) */ + + if (!reuse) { + phw->rx_infoL[tail].pbuf = NULL; // clear pointer for not being accidently freed + +#if 0 + // allocate new one + pskb = rtl_dev_alloc_skb(priv, RX_BUF_LEN, _SKB_RX_); + + if (pskb == (struct sk_buff *)NULL) + { + DEBUG_WARN("out of skb_buff\n"); + list_del(&pfrinfo->rx_list); + pskb = (struct sk_buff *)(phw->rx_infoL[tail].pbuf); + pskb->data -= (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + pskb->tail -= (pfrinfo->rxbuf_shift + pfrinfo->driver_info_size); + goto rx_reuse; + } +#endif + +#if defined(DELAY_REFILL_RX_BUF) +#if defined(CONFIG_RTL8190_PRIV_SKB) +#ifdef CONCURRENT_MODE + if (skb_free_num[priv->pshare->wlandev_idx] == 0 && priv->pshare->skb_queue.qlen == 0) +#else + if (skb_free_num == 0 && priv->pshare->skb_queue.qlen == 0) +#endif + { + refill = 0; + goto rx_done; + } +#endif + new_skb = rtl_dev_alloc_skb(priv, RX_BUF_LEN, _SKB_RX_, 0); + ASSERT(new_skb); + if(new_skb == NULL) { + printk("not enough memory...\n"); + refill = 0; + goto rx_done; + } +#endif + pskb = new_skb; + + +#if defined(DELAY_REFILL_RX_BUF) + RTL_WLAN_RX_ATOMIC_PROTECT_ENTER; + init_rxdesc(pskb, phw->cur_rx_refill, priv); + RTL_WLAN_RX_ATOMIC_PROTECT_EXIT; +#else + init_rxdesc(pskb, tail, priv); +#endif + + goto rx_done; + } /* if (!reuse) */ +#if !defined(DELAY_REFILL_RX_BUF) + else { + rtl_kfree_skb(priv, new_skb, _SKB_RX_); + } +#endif + +rx_reuse: +#if defined(DELAY_REFILL_RX_BUF) + RTL_WLAN_RX_ATOMIC_PROTECT_ENTER; +#if defined(RX_BUFFER_GATHER) + cmp_flags = (tail != phw->cur_rx_refill) || (pfrinfo_update); +#else + cmp_flags = (tail != phw->cur_rx_refill); +#endif + RTL_WLAN_RX_ATOMIC_PROTECT_EXIT; + + if (cmp_flags) + { + phw->rx_infoL[tail].pbuf = NULL; // clear pointer for not being accidently freed + pskb->data = pskb->head; + pskb->tail = pskb->head; + skb_reserve(pskb, NET_SKB_PAD); +#if defined(CONFIG_RTL8196_RTL8366) + skb_reserve(pskb, 8); +#endif +#if defined(CONFIG_RTK_VOIP_VLAN_ID) + skb_reserve(pskb, 4); +#endif + refill_rx_ring(priv, pskb, NULL); + refill = 0; + } else +#endif /* defined(DELAY_REFILL_RX_BUF) */ + { +#if defined(RX_BUFFER_GATHER) + pfrinfo->gather_flag = 0; +#endif + SMP_LOCK_SKB(x); +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if (IS_PCIBIOS_TYPE) { + phw->rx_infoL[tail].paddr = get_physical_addr(priv, pskb->data, (RX_BUF_LEN - sizeof(struct rx_frinfo)), PCI_DMA_FROMDEVICE); + } +#endif + pdesc->Dword6 = set_desc(phw->rx_infoL[tail].paddr); +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + // Remove it because pci_map_single() in get_physical_addr() already performed memory sync. + //rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(phw->rx_infoL[tail].paddr), RX_BUF_LEN - sizeof(struct rx_frinfo)-64, PCI_DMA_FROMDEVICE); +#else + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(phw->rx_infoL[tail].paddr-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), RX_BUF_LEN - sizeof(struct rx_frinfo)-64, PCI_DMA_FROMDEVICE); +#endif + pdesc->Dword0 = set_desc((tail == (NUM_RX_DESC - 1)? RX_EOR : 0) | RX_OWN | (RX_BUF_LEN - sizeof(struct rx_frinfo)-64)); + SMP_UNLOCK_SKB(x); + } + +rx_done: + RTL_WLAN_RX_ATOMIC_PROTECT_ENTER; + //tail = (tail + 1) % NUM_RX_DESC; + tail = ( ((tail+1)==NUM_RX_DESC)?0:tail+1); + phw->cur_rx = tail; + +#if defined(DELAY_REFILL_RX_BUF) + if (refill) { + //phw->cur_rx_refill = (phw->cur_rx_refill + 1) % NUM_RX_DESC; + phw->cur_rx_refill = ( ((phw->cur_rx_refill+1)==NUM_RX_DESC)?0:phw->cur_rx_refill+1); + } +#endif + RTL_WLAN_RX_ATOMIC_PROTECT_EXIT; + } /* while(1) */ + SMP_UNLOCK_RECV(y); + + if (!IS_DRV_OPEN(priv)) + return; + +#if defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX) + if (OPMODE & WIFI_AP_STATE) { + if (!list_empty(&priv->wakeup_list)) + process_dzqueue(priv); + +#if defined(MBSSID) + if (priv->pmib->miscEntry.vap_enable) { + int i; + struct rtl8192cd_priv *priv_vap; + + for (i=0; ipvap_priv[i])) { + priv_vap = priv->pvap_priv[i]; + if (!list_empty(&priv_vap->wakeup_list)) + process_dzqueue(priv_vap); + } + } + } +#endif + } +#ifdef UNIVERSAL_REPEATER + else { + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + if (!list_empty(&GET_VXD_PRIV(priv)->wakeup_list)) + process_dzqueue(GET_VXD_PRIV(priv)); + } +#endif +#endif /* defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX) */ + + if(priv->pshare->skip_mic_chk) + --priv->pshare->skip_mic_chk; +} +} + +#undef RTL_WLAN_RX_ATOMIC_PROTECT_ENTER +#undef RTL_WLAN_RX_ATOMIC_PROTECT_EXIT + +#endif // CONFIG_PCI_HCI + +// The purpose of reassemble is to assemble the frag into a complete one. +static struct rx_frinfo *reassemble(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + struct list_head *phead, *plist; + unsigned short seq=0; + unsigned char tofr_ds=0; + unsigned int iv, icv, mic, privacy=0, offset; + struct sk_buff *pskb; + struct rx_frinfo *pfrinfo, *pfirstfrinfo=NULL; + unsigned char *pframe=NULL, *pfirstframe=NULL, tail[16]; //4, 12, and 8 for WEP/TKIP/AES + unsigned long flags; + int i; + union PN48 last_PN; + + struct list_head frag_list; + + INIT_LIST_HEAD(&frag_list); + + DEFRAG_LOCK(flags); + list_del_init(&pstat->defrag_list); + list_splice_init(&pstat->frag_list, &frag_list); + pstat->frag_count = 0; + DEFRAG_UNLOCK(flags); + + phead = &frag_list; + + // checking all the seq should be the same, and the frg should monotically increase + for(i=0, plist=phead->next; plist!=phead; plist=plist->next, i++) + { + pfrinfo = list_entry(plist, struct rx_frinfo, mpdu_list); + pframe = get_pframe(pfrinfo); + + if ((GetFragNum(pframe)) != i) + { + DEBUG_ERR("RX DROP: FragNum did not match, FragNum=%d, GetFragNum(pframe)=%d\n", + i, GetFragNum(pframe)); + goto unchainned_all; + } + + if (i == 0) + { + seq = GetSequence(pframe); + privacy = GetPrivacy(pframe); + tofr_ds = pfrinfo->to_fr_ds; + if (get_sta_encrypt_algthm(priv, pstat) == _CCMP_PRIVACY_) + { + last_PN.val48 = 0; + last_PN._byte_.TSC0 = pframe[pfrinfo->hdr_len]; + last_PN._byte_.TSC1 = pframe[pfrinfo->hdr_len+1]; + last_PN._byte_.TSC2 = pframe[pfrinfo->hdr_len+4]; + last_PN._byte_.TSC3 = pframe[pfrinfo->hdr_len+5]; + last_PN._byte_.TSC4 = pframe[pfrinfo->hdr_len+6]; + last_PN._byte_.TSC5 = pframe[pfrinfo->hdr_len+7]; + } + } + else + { + if (get_sta_encrypt_algthm(priv, pstat) == _CCMP_PRIVACY_ && + sta_packet_number_check(priv, &last_PN, pframe, pfrinfo->hdr_len) != SUCCESS) + { + DEBUG_ERR("RX DROP: Non-consecutive Packet Number\n"); + goto unchainned_all; + } + + if (GetSequence(pframe) != seq) + { + DEBUG_ERR("RX DROP: Seq is not correct, seq=%d, GetSequence(pframe)=%d\n", + seq, GetSequence(pframe)); + goto unchainned_all; + } + + if (GetPrivacy(pframe) != privacy) + { + DEBUG_ERR("RX DROP: Privacy is not correct, privacy=%d, GetPrivacy(pframe)=%d\n", + privacy, GetPrivacy(pframe)); + goto unchainned_all; + } + + if (pfrinfo->to_fr_ds != tofr_ds) + { + DEBUG_ERR("RX DROP: to_fr_ds did not match, tofr_ds=%d, pfrinfo->to_fr_ds=%d\n", + tofr_ds, pfrinfo->to_fr_ds); + goto unchainned_all; + } + } + } + + privacy = get_privacy(priv, pstat, &iv, &icv, &mic); + + offset = iv; + offset += get_hdrlen(priv, pframe); + + // below we are going to re-assemble the whole pkts... + for(i=0, plist=phead->next; plist!=phead; plist=plist->next, i++) + { + pfrinfo = list_entry(plist, struct rx_frinfo, mpdu_list); + + if (pfrinfo->pktlen <= (offset + icv + mic)) + { + DEBUG_ERR("RX DROP: Frame length bad (%d)\n", pfrinfo->pktlen); + pfirstfrinfo = NULL; + goto unchainned_all; + } + + if (i == 0) + { + pfirstfrinfo = pfrinfo; + pfirstframe = get_pframe(pfrinfo); + pfirstframe += pfrinfo->pktlen - (icv + mic); + + if (icv + mic) + { + memcpy((void *)tail, (void *)(pfirstframe), (icv + mic)); + pfirstfrinfo->pktlen -= (icv + mic); + } + continue; + } + + // check if too many frags... + pfirstfrinfo->pktlen += (pfrinfo->pktlen - offset - icv - mic); +#if defined(CONFIG_PCI_HCI) + if (pfirstfrinfo->pktlen >= (RX_BUF_LEN - offset - icv - mic - 200)) +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if ((pfirstframe + (pfrinfo->pktlen - offset)) >= + ((unsigned char *)((unsigned long)(pfirstfrinfo->pskb->end)))) +#endif + { + DEBUG_ERR("RX DROP: over rx buf size after reassemble...\n"); + pfirstfrinfo = NULL; + goto unchainned_all; + } + + // here we should check if all these frags exceeds the buf size + memcpy(pfirstframe, get_pframe(pfrinfo) + offset, pfrinfo->pktlen - offset - icv - mic); + pfirstframe += (pfrinfo->pktlen - offset - icv - mic); + } + + if (icv + mic) + { + memcpy((void *)pfirstframe, (void *)tail, (icv + mic)); + pfirstfrinfo->pktlen += (icv + mic); + } + + // take the first frame out of fragment list + plist = phead->next; + list_del_init(plist); + +unchainned_all: // dequeue all the queued-up frag, free skb, and init_list_head again... + + while (!list_empty(phead)) { + plist = phead->next; + list_del(plist); + + pfrinfo = list_entry(plist, struct rx_frinfo, mpdu_list); + pskb = get_pskb(pfrinfo); + rtl_kfree_skb(priv, pskb, _SKB_RX_IRQ_); + + if (pfirstfrinfo == NULL) + priv->ext_stats.rx_data_drops++; + } + + return pfirstfrinfo; +} + + +/*---------------------------------------------------------------------------------------- + So far, only data pkt will be defragmented. +-----------------------------------------------------------------------------------------*/ +static struct rx_frinfo *defrag_frame_main(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *da, *sa; + struct stat_info *pstat=NULL; + unsigned int res, hdr_len, len; + int status, privacy=0, pos; + unsigned long flags; + unsigned char tkipmic[8], rxmic[8]; + unsigned char *pframe; + unsigned char hw_didnt_decrypt=0; + + pframe = get_pframe(pfrinfo); + hdr_len = pfrinfo->hdr_len; + da = pfrinfo->da; + sa = pfrinfo->sa; + len = pfrinfo->pktlen; + + /*---------first of all check if sa is assocated---------*/ + if (OPMODE & WIFI_AP_STATE) { +#if defined(CONFIG_RTK_MESH) || defined(WDS) + // for 802.11s case, pstat will not be NULL, because we have check it in validate-mpdu + if (pfrinfo->to_fr_ds == 3) { + pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + if (pstat == NULL){ + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX Drop: WDS rx data with pstat == NULL\n"); + goto free_skb_in_defrag; + } else { + goto check_privacy; + } + } + else +#endif + { +#ifdef A4_STA + if (pfrinfo->to_fr_ds == 3 && priv->pshare->rf_ft_var.a4_enable) { + pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + if (pstat && !(pstat->state & WIFI_A4_STA)) + add_a4_client(priv, pstat); + + a4_sta_add(priv, pstat, sa); + } + else +#endif + + #ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + // printk("%s %d HW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + #endif + + //if(!pstat) + { + pstat = get_stainfo(priv, sa); + // printk("%s %d SW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) { + unsigned char *bssid = GetAddr2Ptr(pframe); + pstat = get_stainfo(priv, bssid); + } + else // Ad-hoc + pstat = get_stainfo(priv, sa); +#endif + + if (pstat == NULL) + { + status = _RSON_CLS2_; + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: class 2 error!\n"); + goto data_defrag_error; + } + else if (!(pstat->state & WIFI_ASOC_STATE)) + { + status = _RSON_CLS3_; + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: class 3 error!\n"); + goto data_defrag_error; + } + else {} + + /*-------------------get privacy-------------------*/ +#if defined(CONFIG_RTK_MESH) || defined(WDS) +check_privacy: +#endif + + if (OPMODE & WIFI_AP_STATE) { +#ifdef CONFIG_RTK_MESH + //modify by Joule for SECURITY + if(pfrinfo->is_11s) + privacy = IS_MCAST(da) ? _NO_PRIVACY_ : get_sta_encrypt_algthm(priv, pstat); + else +#endif +#ifdef WDS + if (pfrinfo->to_fr_ds == 3) + privacy = priv->pmib->dot11WdsInfo.wdsPrivacy; + else +#endif + privacy = get_sta_encrypt_algthm(priv, pstat); + } +#ifdef CLIENT_MODE + else { + if (IS_MCAST(da)) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (!IS_ROOT_INTERFACE(priv) && !IEEE8021X_FUN && + ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_))){ + privacy = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + }else +#endif +#if defined(CONFIG_RTL_WAPI_SUPPORT) + if (pstat&&pstat->wapiInfo&&pstat->wapiInfo->wapiType!=wapiDisable){ + privacy = _WAPI_SMS4_; + }else +#endif + { + // iv, icv and mic are not be used below. Don't care them! + privacy = priv->pmib->dot11GroupKeysTable.dot11Privacy; + } + } + else + { + privacy = get_sta_encrypt_algthm(priv, pstat); + } + } + + if (IS_MCAST(da)) + { + if (GetTupleCache(pframe) == pstat->tpcache_mcast) + { + priv->ext_stats.rx_decache++; + SNMP_MIB_INC(dot11FrameDuplicateCount, 1); + goto free_skb_in_defrag; + } + else + pstat->tpcache_mcast = GetTupleCache(pframe); + } + else +#endif + /*-------------------check retry-------------------*/ + if (is_qos_data(pframe)) { + pos = GetSequence(pframe) & (TUPLE_WINDOW - 1); + if (IS_MCAST(da)) { + // ignore check of multicast packet to workaround Veriware test. + } + else if (GetTupleCache(pframe) == pstat->tpcache[pfrinfo->tid][pos]) { + priv->ext_stats.rx_decache++; + SNMP_MIB_INC(dot11FrameDuplicateCount, 1); + goto free_skb_in_defrag; + } + else + pstat->tpcache[pfrinfo->tid][pos] = GetTupleCache(pframe); + } + else { + if (GetRetry(pframe)) { + if (GetTupleCache(pframe) == pstat->tpcache_mgt) { + priv->ext_stats.rx_decache++; + SNMP_MIB_INC(dot11FrameDuplicateCount, 1); + goto free_skb_in_defrag; + } + } + pstat->tpcache_mgt = GetTupleCache(pframe); + } + + /*-------------------------------------------------------*/ + /*-----------insert MPDU-based decrypt below-------------*/ + /*-------------------------------------------------------*/ + +#ifdef SUPPORT_SNMP_MIB + if (GetPrivacy(pframe) && privacy == _NO_PRIVACY_) + SNMP_MIB_INC(dot11WEPUndecryptableCount, 1); + + if (!GetPrivacy(pframe) && privacy != _NO_PRIVACY_) + SNMP_MIB_INC(dot11WEPExcludedCount, 1); +#endif + +#if defined(CONFIG_RTL_WAPI_SUPPORT) + if (privacy==_WAPI_SMS4_) + { + //WAPI authentication packet is not encryption, but privacy==_WAPI_SMS4_. This can avoid WAPI authentication packet is droped!!! + } + else +#endif + if (!GetPrivacy(pframe) && privacy != _NO_PRIVACY_) + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Recv unencrypted packet!\n"); + goto free_skb_in_defrag; + } + +#ifdef CONFIG_IEEE80211W + if (GetPrivacy(pframe) && !UseSwCrypto(priv, pstat, IS_MCAST(GetAddr1Ptr(pframe)), 0) && pfrinfo->sw_dec) +#else + if (GetPrivacy(pframe) && !UseSwCrypto(priv, pstat, IS_MCAST(GetAddr1Ptr(pframe))) && pfrinfo->sw_dec) +#endif + { + printk( "Rx packet, hardware did not decrypt\n" ); + hw_didnt_decrypt = 1; + } + + // check whether WEP bit is set in mac header and sw encryption +#ifdef CONFIG_IEEE80211W + if (GetPrivacy(pframe) && (UseSwCrypto(priv, pstat, IS_MCAST(GetAddr1Ptr(pframe)), 0) || hw_didnt_decrypt)) // 0: PMF +#else + if (GetPrivacy(pframe) && (UseSwCrypto(priv, pstat, IS_MCAST(GetAddr1Ptr(pframe))) || hw_didnt_decrypt)) +#endif + { +#if defined(CONFIG_RTL_WAPI_SUPPORT) + if (privacy==_WAPI_SMS4_) + { + /* Decryption */ +// SAVE_INT_AND_CLI(flags); + res = SecSWSMS4Decryption(priv, pstat, pfrinfo); +// RESTORE_INT(flags); + if (res == FAIL) + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: WAPI decrpt error!\n"); + goto free_skb_in_defrag; + } + pframe = get_pframe(pfrinfo); + } else +#endif + if (privacy == _TKIP_PRIVACY_) + { + res = tkip_decrypt(priv, pfrinfo, pfrinfo->pktlen); + if (res == FAIL) + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Tkip decrpt error!\n"); + goto free_skb_in_defrag; + } + } + else if (privacy == _CCMP_PRIVACY_) + { + res = aesccmp_decrypt(priv, pfrinfo +#ifdef CONFIG_IEEE80211W + , 0 +#endif + ); + if (res == FAIL) + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: AES decrpt error!\n"); + goto free_skb_in_defrag; + } + } + else if (privacy == _WEP_40_PRIVACY_ || privacy == _WEP_104_PRIVACY_) + { + res = wep_decrypt(priv, pfrinfo, pfrinfo->pktlen, privacy, 0); + if (res == FAIL) + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: WEP decrpt error!\n"); + goto free_skb_in_defrag; + } + } + else + { + DEBUG_ERR("RX DROP: encrypted packet but no key in sta or wrong enc type!\n"); + goto free_skb_in_defrag; + } + + } + /*----------------End of MPDU-based decrypt--------------*/ + + if (GetMFrag(pframe)) + { + if (pstat->frag_count > MAX_FRAG_COUNT) + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: station has received too many frags!\n"); + goto free_skb_in_defrag; + } + + DEFRAG_LOCK(flags); + + if (pstat->frag_count == 0) // the first frag... + pstat->frag_to = priv->frag_to; + + if (list_empty(&pstat->defrag_list)) + list_add_tail(&pstat->defrag_list, &priv->defrag_list); + + list_add_tail(&pfrinfo->mpdu_list, &pstat->frag_list); + pstat->frag_count++; + + DEFRAG_UNLOCK(flags); + + return (struct rx_frinfo *)NULL; + } + else + { + if(GetFragNum(pframe)) + { + DEFRAG_LOCK(flags); + list_add_tail(&pfrinfo->mpdu_list, &pstat->frag_list); + DEFRAG_UNLOCK(flags); + + pfrinfo = reassemble(priv, pstat); + if (pfrinfo == NULL) + return (struct rx_frinfo *)NULL; + } + } + + /*-----discard non-authorized packet before MIC check----*/ + if (OPMODE & WIFI_AP_STATE) { +#if defined(CONFIG_RTK_MESH) || defined(WDS) + if (pfrinfo->to_fr_ds != 3) +#endif + if (auth_filter(priv, pstat, pfrinfo) == FAIL) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: due to auth_filter fails\n"); + goto free_skb_in_defrag; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) { + if (auth_filter(priv, pstat, pfrinfo) == FAIL) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: due to auth_filter fails\n"); + goto free_skb_in_defrag; + } + } +#endif + + /*------------------------------------------------------------------------*/ + //insert MSDU-based digest here! + /*------------------------------------------------------------------------*/ + if (GetPrivacy(pframe) && (privacy == _TKIP_PRIVACY_)) + { + pframe = get_pframe(pfrinfo); + len = pfrinfo->pktlen; + + //truncate Michael... + memcpy((void *)rxmic, (void *)(pframe + len - 8 - 4), 8); // 8 michael, 4 icv + SAVE_INT_AND_CLI(flags); + tkip_rx_mic(priv, pframe, da, sa, + pfrinfo->tid, pframe + hdr_len + 8, + len - hdr_len - 8 - 8 - 4, tkipmic, 0); // 8 IV, 8 Mic, 4 ICV + RESTORE_INT(flags); + + if(memcmp(rxmic, tkipmic, 8)) + { + priv->ext_stats.rx_data_drops++; +#ifdef _SINUX_ + printk("RX DROP: MIC error! Indicate to protection mechanism\n"); + mic_error_report(0); +#else + DEBUG_ERR("RX DROP: MIC error! Indicate to protection mechanism\n"); +#endif + if (OPMODE & WIFI_AP_STATE) { +#ifdef RTL_WPA2 +#ifdef _SINUX_ + printk("%s: DOT11_Indicate_MIC_Failure %02X:%02X:%02X:%02X:%02X:%02X \n", (char *)__FUNCTION__,pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); +#else + PRINT_INFO("%s: DOT11_Indicate_MIC_Failure %02X:%02X:%02X:%02X:%02X:%02X \n", (char *)__FUNCTION__,pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); +#endif + +#endif +#ifdef WDS + if ((pfrinfo->to_fr_ds == 3) && + pstat && (pstat->state & WIFI_WDS)) + goto free_skb_in_defrag; +#endif + DOT11_Indicate_MIC_Failure(priv->dev, pstat); + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + DOT11_Indicate_MIC_Failure_Clnt(priv, sa); +#endif + goto free_skb_in_defrag; + } + } + + return pfrinfo; + +data_defrag_error: + + if (OPMODE & WIFI_AP_STATE){ + issue_deauth(priv,sa,status); + if (pstat != NULL){ +#if defined(CONFIG_PCI_HCI) + free_stainfo(priv, pstat); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_del_sta(priv, pstat); +#endif + } + } +#ifdef CLIENT_MODE + else { + if (pstat == NULL) { + DEBUG_ERR("rx data with pstat == NULL\n"); + } + else if (!(pstat->state & WIFI_ASOC_STATE)) { + DEBUG_ERR("rx data with pstat not associated\n"); + } + } +#endif + +free_skb_in_defrag: + + rtl_kfree_skb(priv, get_pskb(pfrinfo), _SKB_RX_); + + return (struct rx_frinfo *)NULL; +} + + +static struct rx_frinfo *defrag_frame(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + struct sk_buff *pskb = get_pskb(pfrinfo); + struct rx_frinfo *prx_frinfo = NULL; + unsigned int encrypt; + unsigned char *pframe; + + // rx a encrypt packet but encryption is not enabled in local mib, discard it + pframe = get_pframe(pfrinfo); + encrypt = GetPrivacy(pframe); + +//modify by Joule for SECURITY +// here maybe need do some tune; plus +#ifdef CONFIG_RTK_MESH /*-------*/ + if (encrypt && ( + (pfrinfo->to_fr_ds==3 && ( +#ifdef WDS + GET_MIB(priv)->dot1180211sInfo.mesh_enable ==0 ? + priv->pmib->dot11WdsInfo.wdsPrivacy==_NO_PRIVACY_ : +#endif + priv->pmib->dot11sKeysTable.dot11Privacy ==_NO_PRIVACY_ )) || + (pfrinfo->to_fr_ds!=3 && priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_NO_PRIVACY_ +#if defined(CONFIG_RTL_WAPI_SUPPORT) + && priv->pmib->wapiInfo.wapiType==wapiDisable +#endif + ))) +#else /*-------*/ +// origin +#ifdef WDS + if (encrypt && ( + (pfrinfo->to_fr_ds==3 && priv->pmib->dot11WdsInfo.wdsPrivacy==_NO_PRIVACY_) || + (pfrinfo->to_fr_ds!=3 && priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_NO_PRIVACY_)) +#if defined(CONFIG_RTL_WAPI_SUPPORT) + && priv->pmib->wapiInfo.wapiType==wapiDisable +#endif + ) +#else + if (encrypt && priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _NO_PRIVACY_ +#if defined(CONFIG_RTL_WAPI_SUPPORT) + && priv->pmib->wapiInfo.wapiType==wapiDisable +#endif + ) +#endif +#endif/*-------*/ + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Discard a encrypted packet!\n"); + rtl_kfree_skb(priv, pskb, _SKB_RX_); + return (struct rx_frinfo *)NULL; + } + +#ifdef CONFIG_RTK_MESH + if (pfrinfo->to_fr_ds==3 && !encrypt && ( +#ifdef WDS + GET_MIB(priv)->dot1180211sInfo.mesh_enable ==0 ? + priv->pmib->dot11WdsInfo.wdsPrivacy!=_NO_PRIVACY_ : +#endif + (priv->pmib->dot11sKeysTable.dot11Privacy != _NO_PRIVACY_ && !IS_MCAST(pfrinfo->da)))) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Discard a un-encrypted WDS/MESH packet!\n"); + rtl_kfree_skb(priv, pskb, _SKB_RX_); + SNMP_MIB_INC(dot11WEPExcludedCount, 1); + return (struct rx_frinfo *)NULL; + } +#else +//origin +#ifdef WDS + if (pfrinfo->to_fr_ds==3 && !encrypt && priv->pmib->dot11WdsInfo.wdsPrivacy!=_NO_PRIVACY_) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Discard a un-encrypted WDS packet!\n"); + rtl_kfree_skb(priv, pskb, _SKB_RX_); + SNMP_MIB_INC(dot11WEPExcludedCount, 1); + return (struct rx_frinfo *)NULL; + } +#endif +#endif + prx_frinfo = defrag_frame_main(priv, pfrinfo); + + return prx_frinfo; +} + + +static int auth_filter(struct rtl8192cd_priv *priv, struct stat_info *pstat, + struct rx_frinfo *pfrinfo) +{ + unsigned int hdr_len; + unsigned char *pframe, *pbuf; + unsigned short proto; + +// hdr_len = pfrinfo->hdr_len; +// pframe = get_pframe(pfrinfo); +// pbuf = pframe + hdr_len + sizeof(struct wlan_llc_t) + 3; +// proto = *(unsigned short *)pbuf; + + if(IEEE8021X_FUN) { + if (pstat) { + if (pstat->ieee8021x_ctrlport) // controlled port is enable... + return SUCCESS; + else { + //only 802.1x frame can pass... + hdr_len = pfrinfo->hdr_len; + pframe = get_pframe(pfrinfo); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (GetPrivacy(pframe)) + pbuf = pframe + hdr_len + sizeof(struct wlan_llc_t) + 3 + 8; // 8 bytes IV + else +#endif + pbuf = pframe + hdr_len + sizeof(struct wlan_llc_t) + 3; + + proto = *(unsigned short *)pbuf; + if (proto == __constant_htons(0x888e)) + return SUCCESS; + else { + return FAIL; + } + } + } + else { + DEBUG_ERR("pstat == NULL in auth_filter\n"); + return FAIL; + } + } + + return SUCCESS; +} + + +#if defined(WIFI_WMM) && defined(WMM_APSD) +void SendQosNullData(struct rtl8192cd_priv *priv, unsigned char *da) +{ + struct wifi_mib *pmib; + unsigned char *hwaddr; + unsigned char tempQosControl[2]; + DECLARE_TXINSN(txinsn); + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + pmib = GET_MIB(priv); + + hwaddr = pmib->dot11OperationEntry.hwaddr; + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.fr_type = _PRE_ALLOCHDR_; + txinsn.phdr = get_wlanhdr_from_poll(priv); + txinsn.pframe = NULL; + + if (txinsn.phdr == NULL) + goto send_qos_null_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + SetFrameSubType(txinsn.phdr, BIT(7) | WIFI_DATA_NULL); + SetFrDs(txinsn.phdr); + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + txinsn.hdr_len = WLAN_HDR_A3_QOS_LEN; + + memset(tempQosControl, 0, 2); + tempQosControl[0] = 0x07; //set priority to VO + tempQosControl[0] |= BIT(4); //set EOSP + memcpy((void *)GetQosControl((txinsn.phdr)), tempQosControl, 2); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +send_qos_null_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); +} + +#ifdef CONFIG_PCI_HCI +static void process_APSD_dz_queue(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned short tid) +{ + unsigned int deque_level = 1; // deque pkts level, VO = 4, VI = 3, BE = 2, BK = 1 + struct sk_buff *pskb = NULL; + DECLARE_TXINSN(txinsn); + + if ((((tid == 7) || (tid == 6)) && !(pstat->apsd_bitmap & 0x01)) + || (((tid == 5) || (tid == 4)) && !(pstat->apsd_bitmap & 0x02)) + || (((tid == 3) || (tid == 0)) && !(pstat->apsd_bitmap & 0x08)) + || (((tid == 2) || (tid == 1)) && !(pstat->apsd_bitmap & 0x04))) { + DEBUG_INFO("RcvQosNull legacy ps tid=%d", tid); + return; + } + + if (pstat->apsd_pkt_buffering == 0) + goto sendQosNull; + + if ((pstat->apsd_bitmap & 0x01) && (!isFFempty(pstat->VO_dz_queue->head, pstat->VO_dz_queue->tail))) + deque_level = 4; + else if ((pstat->apsd_bitmap & 0x02) && (!isFFempty(pstat->VI_dz_queue->head, pstat->VI_dz_queue->tail))) + deque_level = 3; + else if ((pstat->apsd_bitmap & 0x08) && (!isFFempty(pstat->BE_dz_queue->head, pstat->BE_dz_queue->tail))) + deque_level = 2; + else if ((!(pstat->apsd_bitmap & 0x04)) || (isFFempty(pstat->BK_dz_queue->head, pstat->BK_dz_queue->tail))) { + //send QoS Null packet +sendQosNull: + SendQosNullData(priv, pstat->hwaddr); + DEBUG_INFO("sendQosNull tid=%d\n", tid); + return; + } + + while(1) { + if (deque_level == 4) { + pskb = (struct sk_buff *)deque(priv, &(pstat->VO_dz_queue->head), &(pstat->VO_dz_queue->tail), + (unsigned long)(pstat->VO_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE); + if (pskb == NULL) { + if ((pstat->apsd_bitmap & 0x02) && (!isFFempty(pstat->VI_dz_queue->head, pstat->VI_dz_queue->tail))) + deque_level--; + else if ((pstat->apsd_bitmap & 0x08) && (!isFFempty(pstat->BE_dz_queue->head, pstat->BE_dz_queue->tail))) + deque_level = 2; + else if ((pstat->apsd_bitmap & 0x04) && (!isFFempty(pstat->BK_dz_queue->head, pstat->BK_dz_queue->tail))) + deque_level = 1; + else + deque_level = 0; + } + else { + DEBUG_INFO("deque VO pkt\n"); + } + } + else if (deque_level == 3) { + pskb = (struct sk_buff *)deque(priv, &(pstat->VI_dz_queue->head), &(pstat->VI_dz_queue->tail), + (unsigned long)(pstat->VI_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE); + if (pskb == NULL) { + if ((pstat->apsd_bitmap & 0x08) && (!isFFempty(pstat->BE_dz_queue->head, pstat->BE_dz_queue->tail))) + deque_level--; + else if ((pstat->apsd_bitmap & 0x04) && (!isFFempty(pstat->BK_dz_queue->head, pstat->BK_dz_queue->tail))) + deque_level = 1; + else + deque_level = 0; + } + else { + DEBUG_INFO("deque VI pkt\n"); + } + } + else if (deque_level == 2) { + pskb = (struct sk_buff *)deque(priv, &(pstat->BE_dz_queue->head), &(pstat->BE_dz_queue->tail), + (unsigned long)(pstat->BE_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE); + if (pskb == NULL) { + if ((pstat->apsd_bitmap & 0x04) && (!isFFempty(pstat->BK_dz_queue->head, pstat->BK_dz_queue->tail))) + deque_level--; + else + deque_level = 0; + } + else { + DEBUG_INFO("deque BE pkt\n"); + } + } + else if (deque_level == 1) { + pskb = (struct sk_buff *)deque(priv, &(pstat->BK_dz_queue->head), &(pstat->BK_dz_queue->tail), + (unsigned long)(pstat->BK_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE); + if(pskb) + DEBUG_INFO("deque BK pkt\n"); + } + + if (pskb) { + txinsn.q_num = BE_QUEUE; + txinsn.fr_type = _SKB_FRAME_TYPE_; + txinsn.pframe = pskb; + txinsn.phdr = (UINT8 *)get_wlanllchdr_from_poll(priv); + pskb->cb[1] = 0; + + if (pskb->len > priv->pmib->dot11OperationEntry.dot11RTSThreshold) + txinsn.retry = priv->pmib->dot11OperationEntry.dot11LongRetryLimit; + else + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + if (txinsn.phdr == NULL) { + DEBUG_ERR("Can't alloc wlan header!\n"); + goto xmit_skb_fail; + } + + memset((void *)txinsn.phdr, 0, sizeof(struct wlanllc_hdr)); + + SetFrDs(txinsn.phdr); + SetFrameSubType(txinsn.phdr, WIFI_QOS_DATA); + if (((deque_level == 4) && (!isFFempty(pstat->VO_dz_queue->head, pstat->VO_dz_queue->tail)) && (pstat->apsd_bitmap & 0x01)) || + ((deque_level >= 3) && (!isFFempty(pstat->VI_dz_queue->head, pstat->VI_dz_queue->tail)) && (pstat->apsd_bitmap & 0x02)) || + ((deque_level >= 2) && (!isFFempty(pstat->BE_dz_queue->head, pstat->BE_dz_queue->tail)) && (pstat->apsd_bitmap & 0x08)) || + ((deque_level >= 1) && (!isFFempty(pstat->BK_dz_queue->head, pstat->BK_dz_queue->tail)) && (pstat->apsd_bitmap & 0x04))) + SetMData(txinsn.phdr); + + if (rtl8192cd_wlantx(priv, &txinsn) == CONGESTED) { + +xmit_skb_fail: + priv->ext_stats.tx_drops++; + DEBUG_WARN("TX DROP: Congested!\n"); + if (txinsn.phdr) + release_wlanllchdr_to_poll(priv, txinsn.phdr); + if (pskb) + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + } + else if (deque_level <= 1) { + if ((pstat->apsd_pkt_buffering) && + (isFFempty(pstat->VO_dz_queue->head, pstat->VO_dz_queue->tail)) && + (isFFempty(pstat->VI_dz_queue->head, pstat->VI_dz_queue->tail)) && + (isFFempty(pstat->BE_dz_queue->head, pstat->BE_dz_queue->tail)) && + (isFFempty(pstat->BK_dz_queue->head, pstat->BK_dz_queue->tail))) + pstat->apsd_pkt_buffering = 0; + break; + } + } +} +#endif // CONFIG_PCI_HCI + + +static void process_qos_null(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *pframe; + struct stat_info *pstat = NULL; + + pframe = get_pframe(pfrinfo); + +#ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + //printk("%s %d HW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } +#endif + + if(!pstat) + { + pstat = get_stainfo(priv, get_sa(pframe)); + //printk("%s %d SW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + + if ((!(OPMODE & WIFI_AP_STATE)) || (pstat == NULL)) { + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + return; + } + + if (pstat->apsd_bitmap & 0x0f) + process_APSD_dz_queue(priv, pstat, pfrinfo->tid); + + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); +} +#endif + + +#if defined(DRVMAC_LB) && defined(WIFI_WMM) +static void process_lb_qos_null(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ +// unsigned char *pframe; +// unsigned int aid; +// struct stat_info *pstat = NULL; + +// pframe = get_pframe(pfrinfo); +// aid = GetAid(pframe); +// pstat = get_aidinfo(priv, aid); + +// if ((!(OPMODE & WIFI_AP_STATE)) || (pstat == NULL) || (memcmp(pstat->hwaddr, get_sa(pframe), MACADDRLEN))) { +// rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); +// return; +// } +// process_APSD_dz_queue(priv, pstat, pfrinfo->tid); + +#if 0 + if (pfrinfo->pskb && pfrinfo->pskb->data) { + unsigned int *p_skb_int = (unsigned int *)pfrinfo->pskb->data; + printk("LB RX FRAME =====>>\n"); + printk("0x%08x 0x%08x 0x%08x 0x%08x\n", *p_skb_int, *(p_skb_int+1), *(p_skb_int+2), *(p_skb_int+3)); + printk("0x%08x 0x%08x 0x%08x 0x%08x\n", *(p_skb_int+4), *(p_skb_int+5), *(p_skb_int+6), *(p_skb_int+7)); + printk("LB RX FRAME <<=====\n"); + } +#endif + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); +} + + +static void process_lb_qos(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ +// unsigned char *pframe; +// unsigned int aid; +// struct stat_info *pstat = NULL; + +// pframe = get_pframe(pfrinfo); +// aid = GetAid(pframe); +// pstat = get_aidinfo(priv, aid); + +// if ((!(OPMODE & WIFI_AP_STATE)) || (pstat == NULL) || (memcmp(pstat->hwaddr, get_sa(pframe), MACADDRLEN))) { +// rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); +// return; +// } +// process_APSD_dz_queue(priv, pstat, pfrinfo->tid); + +#if 1 + if (pfrinfo->pskb && pfrinfo->pskb->data) { + unsigned char *p_skb_int = (unsigned char *)pfrinfo->pskb->data; + unsigned int payload_length = 0, i = 0, mismatch = 0; + unsigned char matching = 0; + + if (pfrinfo->pktlen && pfrinfo->hdr_len && pfrinfo->pktlen > pfrinfo->hdr_len) { + payload_length = pfrinfo->pktlen - pfrinfo->hdr_len; + if (payload_length >= 2048) + printk("LB Qos RX, payload max hit!\n"); +// if (payload_length > 32) +// payload_length = 32; + } + else { + if (!pfrinfo->pktlen) + printk("LB Qos RX, zero pktlen!!!\n"); + else if (!pfrinfo->hdr_len) + printk("LB Qos RX, zero hdr_len!!!\n"); + else if (pfrinfo->pktlen < pfrinfo->hdr_len) + printk("LB Qos RX, pktlen < hdr_len!!!\n"); + else + printk("LB Qos RX, empty payload.\n"); + goto out; + } + + p_skb_int += pfrinfo->hdr_len; + +// printk("LB RX >> "); +// for (i = 0; i < payload_length; i++) { +// if (i>0 && !(i%4)) +// printk(" "); +// if (!(i%4)) +// printk("0x"); +// printk("%02x", *(p_skb_int+i)); +// } +// printk(" <<\n"); + + for (i = 0; i < payload_length; i++) { + if (priv->pmib->miscEntry.lb_mlmp == 1) { + matching = 0; + if (memcmp((p_skb_int+i), &matching, 1)) { + mismatch++; + break; + } + } + else if (priv->pmib->miscEntry.lb_mlmp == 2) { + matching = 0xff; + if (memcmp((p_skb_int+i), &matching, 1)) { + mismatch++; + break; + } + } + else if ((priv->pmib->miscEntry.lb_mlmp == 3) || (priv->pmib->miscEntry.lb_mlmp == 4)) { + matching = i%0x100; + if (memcmp((p_skb_int+i), &matching, 1)) { + mismatch++; + break; + } + } + else { + printk("LB Qos RX, wrong mlmp setting!\n"); + goto out; + } + } + + if (mismatch) { + printk("LB Qos RX, rx pattern mismatch!!\n"); + priv->pmib->miscEntry.drvmac_lb = 0; // stop the test + } + } +#endif + +out: + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); +} +#endif + + +#ifdef CONFIG_RTL8186_KB +int rtl8192cd_guestmac_valid(struct rtl8192cd_priv *priv, char *macaddr) +{ + int i=0; + + for (i=0; iguestMac[i].valid && !memcmp(priv->guestMac[i].macaddr, macaddr, 6)) + return 1; + } + return 0; +} +#endif +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(CONFIG_RTL_IGMP_SNOOPING) + /*added by qinjunjie,to avoid igmpv1/v2 report suppress*/ +int rtl8192cd_isIgmpV1V2Report(unsigned char *macFrame) +{ + unsigned char *ptr; +#ifdef __ECOS + struct ip *iph=NULL; +#else + struct iphdr *iph=NULL; +#endif + unsigned int payloadLen; + + if((macFrame[0]!=0x01) || (macFrame[1]!=0x00) || (macFrame[2]!=0x5e)) + { + return FALSE; + } + + ptr=macFrame+12; + if(*(int16 *)(ptr)==(int16)htons(0x8100)) + { + ptr=ptr+4; + } + + /*it's not ipv4 packet*/ + if(*(int16 *)(ptr)!=(int16)htons(0x0800)) + { + return FALSE; + } + ptr=(ptr+2); +#ifdef __ECOS + iph=(struct ip *)ptr; + if(iph->ip_p!=0x02) +#else + iph=(struct iphdr *)ptr; + if(iph->protocol!=0x02) +#endif + { + return FALSE; + } + +#ifdef __ECOS + payloadLen=(iph->ip_len-((iph->ip_hl&0x0f)<<2)); +#else + payloadLen=(iph->tot_len-((iph->ihl&0x0f)<<2)); +#endif + if(payloadLen>8) + { + return FALSE; + } + +#ifdef __ECOS + ptr=ptr+(((unsigned int)iph->ip_hl)<<2); +#else + ptr=ptr+(((unsigned int)iph->ihl)<<2); +#endif + if((*ptr==0x11) ||(*ptr==0x16)) + { + return TRUE; + } + return FALSE; + +} +#if defined (CONFIG_RTL_MLD_SNOOPING) +#define IPV6_ROUTER_ALTER_OPTION 0x05020000 +#define HOP_BY_HOP_OPTIONS_HEADER 0 +#define ROUTING_HEADER 43 +#define FRAGMENT_HEADER 44 +#define DESTINATION_OPTION_HEADER 60 + +#define ICMP_PROTOCOL 58 + +#define MLD_QUERY 130 +#define MLDV1_REPORT 131 +#define MLDV1_DONE 132 +#define MLDV2_REPORT 143 + +int rtl8192cd_isMldV1Report(unsigned char *macFrame) +{ + unsigned char *ptr; +#ifdef __ECOS + struct ip6_hdr* ipv6h; +#else + struct ipv6hdr* ipv6h; +#endif + unsigned char *startPtr=NULL; + unsigned char *lastPtr=NULL; + unsigned char nextHeader=0; + unsigned short extensionHdrLen=0; + + unsigned char optionDataLen=0; + unsigned char optionType=0; + unsigned int ipv6RAO=0; + + if((macFrame[0]!=0x33) || (macFrame[1]!=0x33) ) + { + return FALSE; + } + + if(macFrame[2]==0xff) + { + return FALSE; + } + + ptr=macFrame+12; + if(*(int16 *)(ptr)==(int16)htons(0x8100)) + { + ptr=ptr+4; + } + + /*it's not ipv6 packet*/ + if(*(int16 *)(ptr)!=(int16)htons(0x86dd)) + { + return FALSE; + } + + ptr=(ptr+2); + +#ifdef __ECOS + ipv6h= (struct ip6_hdr *) ptr; + if(ipv6h->ip6_vfc!=IPV6_VERSION) +#else + ipv6h= (struct ipv6hdr *) ptr; + if(ipv6h->version!=6) +#endif + { + return FALSE; + } + + startPtr= (unsigned char *)ptr; +#ifdef __ECOS + lastPtr=startPtr+sizeof(struct ip6_hdr)+(ipv6h->ip6_plen); + nextHeader= ipv6h ->ip6_nxt; + ptr=startPtr+sizeof(struct ip6_hdr); +#else + lastPtr=startPtr+sizeof(struct ipv6hdr)+(ipv6h->payload_len); + nextHeader= ipv6h ->nexthdr; + ptr=startPtr+sizeof(struct ipv6hdr); +#endif + + while(ptrdev); + if (!br_port) + return 0; + + protocol = *((unsigned short *)(pskb->data + 2 * ETH_ALEN)); + if (protocol == __constant_htons(ETH_P_ARP)) { + arp = (struct arphdr *)(pskb->data + ETH_HLEN); + if (arp->ar_pro == __constant_htons(ETH_P_IP)) { + arp_ptr = (unsigned char *)(arp + 1); + arp_ptr += arp->ar_hln; + + ipaddr = inet_select_addr(br_port->br->dev, 0, RT_SCOPE_LINK); + if (!memcmp(&ipaddr, arp_ptr, arp->ar_pln)) + return -1; + } + } + + return 0; +} +#endif + +static int process_datafrme(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *pframe, da[MACADDRLEN]; + unsigned int privacy; + unsigned int res; + struct stat_info *pstat = NULL, *dst_pstat = NULL; + struct sk_buff *pskb = NULL, *pnewskb = NULL; + unsigned char qosControl[2]; + int dontBcast2otherSta = 0, do_rc = 0; + struct net_bridge_port *br_port=NULL; +#ifdef RX_SHORTCUT + int i; +#endif + + pframe = get_pframe(pfrinfo); + + pskb = get_pskb(pfrinfo); + //skb_put(pskb, pfrinfo->pktlen); // pskb->tail will be wrong + pskb->tail = pskb->data + pfrinfo->pktlen; + pskb->len = pfrinfo->pktlen; + pskb->dev = priv->dev; + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + priv->pmib->reorderCtrlEntry.ReorderCtrlEnable) { + if (!IS_MCAST(GetAddr1Ptr(pframe))) + do_rc = 1; + } + + if (OPMODE & WIFI_AP_STATE) + { + memcpy(da, pfrinfo->da, MACADDRLEN); + +#ifdef CONFIG_RTK_MESH + if (pfrinfo->is_11s) + { + pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + rx_sum_up(NULL, pstat, pfrinfo->pktlen, 0); + priv->pshare->NumRxBytesUnicast += pfrinfo->pktlen; + update_sta_rssi(priv, pstat, pfrinfo); + return process_11s_datafrme(priv,pfrinfo, pstat); + } + else +#endif +#ifdef WDS + if (pfrinfo->to_fr_ds == 3) { + pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + pskb->dev = getWdsDevByAddr(priv, GetAddr2Ptr(pframe)); + } + else +#endif + { +#ifdef A4_STA + if (pfrinfo->to_fr_ds == 3 && priv->pshare->rf_ft_var.a4_enable) + pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + else +#endif + { + #ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + pstat = get_HW_mapping_sta(priv,pfrinfo->macid); + // printk("%s %d HW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + #endif + + //if(!pstat) + { + pstat = get_stainfo(priv, pfrinfo->sa); + // printk("%s %d SW MACID = %x pstat = %x \n",__FUNCTION__,__LINE__,pfrinfo->macid,pstat); + } + } + } + +#if defined(CONFIG_RTL_WAPI_SUPPORT) +#if defined(CONFIG_PCI_HCI) + if (wapiHandleRecvPacket(pfrinfo, pstat)==SUCCESS) + { + return SUCCESS; + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (pstat->wapiInfo && (wapiDisable != pstat->wapiInfo->wapiType)) + { + int waiOffset; + if ((SecIsWAIPacket(pskb, &waiOffset) == SUCCESS) || + (pstat->wapiInfo->wapiState != ST_WAPI_AE_MSKA_ESTABLISH)) + { + notify_recv_wai_frame(priv, pfrinfo); + return SUCCESS; + } + } +#endif +#endif // CONFIG_RTL_WAPI_SUPPORT + + // log rx statistics... +#ifdef WDS + if (pfrinfo->to_fr_ds == 3) { + privacy = priv->pmib->dot11WdsInfo.wdsPrivacy; + } + else +#endif + { + privacy = get_sta_encrypt_algthm(priv, pstat); + } + rx_sum_up(NULL, pstat, pfrinfo->pktlen, 0); + priv->pshare->NumRxBytesUnicast += pfrinfo->pktlen; + update_sta_rssi(priv, pstat, pfrinfo); + +#ifdef DETECT_STA_EXISTANCE +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if (pstat->leave!= 0) + RTL8188E_MACID_NOLINK(priv, 0, REMAP_AID(pstat)); + } +#endif +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if (pstat->leave!= 0) + { +#if defined(CONFIG_PCI_HCI) + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); + pstat->bDrop = 0; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_update_sta_msr(priv, pstat, INCREASE); +#endif + } + pstat->rx_last_good_time = priv->up_time; + } +#endif //#ifdef CONFIG_WLAN_HAL + + pstat->leave = 0; +#endif + +#ifdef SUPPORT_SNMP_MIB + if (IS_MCAST(da)) + SNMP_MIB_INC(dot11MulticastReceivedFrameCount, 1); +#endif + +#if defined(WIFI_WMM) && defined(WMM_APSD) + if( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (QOS_ENABLE) && (APSD_ENABLE) && (pstat->QosEnabled) && (pstat->apsd_bitmap & 0x0f) && + ((pstat->state & (WIFI_ASOC_STATE|WIFI_SLEEP_STATE)) == (WIFI_ASOC_STATE|WIFI_SLEEP_STATE)) && + (GetFrameSubType(get_pframe(pfrinfo)) == (WIFI_QOS_DATA))) { + process_APSD_dz_queue(priv, pstat, pfrinfo->tid); + } +#endif + + // Process A-MSDU + if (is_qos_data(pframe)) { + memcpy(qosControl, GetQosControl(pframe), 2); + if (qosControl[0] & BIT(7)) // A-MSDU present + { + + if (!pstat->is_realtek_sta && (pstat->IOTPeer!=HT_IOT_PEER_RALINK) && (pstat->IOTPeer!=HT_IOT_PEER_MARVELL)) { + pstat->IOTPeer=HT_IOT_PEER_MARVELL; + if (priv->pshare->is_40m_bw){ + setSTABitMap(&priv->pshare->marvellMapBit, pstat->aid); + } + } + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if((GET_CHIP_VER(priv)== VERSION_8812E) || (GET_CHIP_VER(priv)== VERSION_8881A)) { + //Do Nothing + } + else +#endif + if (priv->pshare->is_40m_bw && (pstat->IOTPeer==HT_IOT_PEER_MARVELL) && (priv->pshare->Reg_RRSR_2 == 0) && (priv->pshare->Reg_81b == 0)){ +#if defined(CONFIG_PCI_HCI) + priv->pshare->Reg_RRSR_2 = RTL_R8(RRSR+2); + priv->pshare->Reg_81b = RTL_R8(0x81b); + RTL_W8(RRSR+2, priv->pshare->Reg_RRSR_2 | 0x60); + RTL_W8(0x81b, priv->pshare->Reg_81b | 0x0E); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_40M_RRSR_SC_change(priv); +#endif + } + + process_amsdu(priv, pstat, pfrinfo); + return SUCCESS; + } +#ifdef RX_BUFFER_GATHER + else if (!list_empty(&priv->pshare->gather_list)) + flush_rx_list(priv); +#endif + } + +#ifdef PREVENT_BROADCAST_STORM +// if (get_free_memory() < FREE_MEM_LOWER_BOUND) { + if (da[0] == 0xff) { + pstat->rx_pkts_bc++; + #if 0 + if (pstat->rx_pkts_bc > BROADCAST_STORM_THRESHOLD) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Broadcast storm happened!\n"); + return FAIL; + } + #endif + } +#endif + + // AP always receive unicast frame only +#ifdef WDS + if (pfrinfo->to_fr_ds!=3 && IS_MCAST(da)) +#else + if (IS_MCAST(da)) +#endif + { +#ifdef DRVMAC_LB + if (priv->pmib->miscEntry.drvmac_lb) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: drop br/ml packet in loop-back mode!\n"); + return FAIL; + } +#endif + +#if 0 //def PREVENT_BROADCAST_STORM +// if (get_free_memory() < FREE_MEM_LOWER_BOUND) { + if (da[0] == 0xff) { + pstat->rx_pkts_bc++; + if (pstat->rx_pkts_bc > BROADCAST_STORM_THRESHOLD) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Broadcast storm happened!\n"); + return FAIL; + } + } +#endif + + // This is a legal frame, convert it to skb + res = skb_p80211_to_ether(priv->dev, privacy, pfrinfo); + if (res == FAIL) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: skb_p80211_to_ether fail!\n"); + return FAIL; + } + +#ifdef PREVENT_ARP_SPOOFING + if (check_arp_spoofing(priv, pskb)) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Detected ARP spoofing!\n"); + return FAIL; + } +#endif + +#ifdef SUPPORT_TX_MCAST2UNI + if(IP_MCAST_MAC(pskb->data) && IS_IGMP_PROTO(pskb->data)) + { + dontBcast2otherSta=1; + } +#endif +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(CONFIG_RTL_IGMP_SNOOPING) + /*added by qinjunjie,to avoid igmpv1/v2 report suppress*/ + if(rtl8192cd_isIgmpV1V2Report(pskb->data)) + { + //printk("%s:%d,receive igmpv1/v2 report\n",__FUNCTION__,__LINE__); + goto mcast_netif_rx; + } + #if defined (CONFIG_RTL_MLD_SNOOPING) + if(rtl8192cd_isMldV1Report(pskb->data)) + { + goto mcast_netif_rx; + } + #endif +#endif + +#ifdef __KERNEL__ +#ifndef CONFIG_RTL8196C_KLD + br_port = GET_BR_PORT(priv->dev); + + // if we are STP aware, don't broadcast received BPDU + if (!(br_port && + br_port->br->stp_enabled && + !memcmp(pskb->data, "\x01\x80\xc2\x00\x00\x00", 6))) +#endif +#endif + { + if (!priv->pmib->dot11OperationEntry.block_relay) + { +#if defined(_SINUX_) && defined(CONFIG_RTL865X_ETH_PRIV_SKB) + extern struct sk_buff *priv_skb_copy(struct sk_buff *skb); + pnewskb = priv_skb_copy(pskb); +#else + pnewskb = skb_copy(pskb, GFP_ATOMIC); +#endif + if (pnewskb) { +#ifdef GBWC + if (GBWC_forward_check(priv, pnewskb, pstat)) { + // packet is queued, nothing to do + } + else +#endif + { +#ifdef TX_SCATTER + pnewskb->list_num = 0; +#endif + if(dontBcast2otherSta){ + dev_kfree_skb_any(pnewskb); + }else{ +#ifdef PREVENT_BROADCAST_STORM + if (da[0] == 0xff) { + if (pstat->rx_pkts_bc > BROADCAST_STORM_THRESHOLD) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Broadcast storm happened!\n"); + dev_kfree_skb_any(pnewskb); + } + else { + if (rtl8192cd_start_xmit(pnewskb, priv->dev)) + rtl_kfree_skb(priv, pnewskb, _SKB_TX_); + } + } + else +#endif + { + if (rtl8192cd_start_xmit(pnewskb, priv->dev)) + rtl_kfree_skb(priv, pnewskb, _SKB_TX_); + } + } + + } + } + } + } + +#if (defined(__LINUX_2_6__) || defined(__ECOS)) && defined(CONFIG_RTL_IGMP_SNOOPING) +mcast_netif_rx: +#endif + + if (do_rc) { + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = 0; + if (reorder_ctrl_check(priv, pstat, pfrinfo)) + rtl_netif_rx(priv, pfrinfo->pskb, pstat); + } + else + rtl_netif_rx(priv, pskb, pstat); + } + else + { + // unicast.. the status of sa has been checked in defrag_frame. + // however, we should check if the da is in the WDS to see if we should + res = skb_p80211_to_ether(pskb->dev, privacy, pfrinfo); + if (res == FAIL) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: skb_p80211_to_ether fail!\n"); + return FAIL; + } + +#ifdef PREVENT_ARP_SPOOFING + if (check_arp_spoofing(priv, pskb)) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Detected ARP spoofing!\n"); + return FAIL; + } +#endif + + dst_pstat = get_stainfo(priv, da); + +#if defined(CONFIG_RTK_MESH) + if(isMeshPoint(dst_pstat)) + dst_pstat = NULL; +#endif + +#ifdef A4_STA + if (priv->pshare->rf_ft_var.a4_enable && (dst_pstat == NULL)) + dst_pstat = a4_sta_lookup(priv, da); +#endif + +#ifdef WDS + if ((pfrinfo->to_fr_ds==3) || + (dst_pstat == NULL) || !(dst_pstat->state & WIFI_ASOC_STATE)) +#else + if ((dst_pstat == NULL) || (!(dst_pstat->state & WIFI_ASOC_STATE))) +#endif + { +#ifndef __ECOS + if (priv->pmib->dot11OperationEntry.guest_access +#ifdef CONFIG_RTL8186_KB + ||(pstat && pstat->ieee8021x_ctrlport == DOT11_PortStatus_Guest) +#endif + ) { + br_port = GET_BR_PORT(priv->dev); + + if ( + (*(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN*2) != __constant_htons(0x888e)) && + (*(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN*2) != __constant_htons(0x86dd)) +#ifndef CONFIG_RTL8196C_KLD + && br_port +#ifdef __LINUX_2_6__ + #if defined(CONFIG_RTL_EAP_RELAY) || defined(CONFIG_RTK_INBAND_HOST_HACK) + && memcmp(da, inband_Hostmac, MACADDRLEN) + #else + && memcmp(da, br_port->br->dev->dev_addr, MACADDRLEN) + #endif +#else + && memcmp(da, priv->dev->br_port->br->dev.dev_addr, MACADDRLEN) +#endif +#endif + ) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: guest access fail!\n"); + return FAIL; + } +#if !defined(NOT_RTK_BSP) && !defined(CONFIG_OPENWRT_SDK) + pskb->__unused = 0xe5; +#endif + +#ifdef CONFIG_RTL8186_KB + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == 0) + { + /* hotel style guest access */ + if (!rtl8192cd_guestmac_valid(priv, SKB_MAC_HEADER(pskb)+MACADDRLEN)) + { +#if !defined(NOT_RTK_BSP) && !defined(CONFIG_OPENWRT_SDK) + pskb->__unused = 0xd3; +#endif + } + } + else + { + /* wpa/wp2 guest access */ + /* just let __unused flag be 0xe5 */ + } +#endif + + //printk("guest packet, addr: %0x2:%02x:%02x:%02x:%02x:%02x\n",da[0],da[1],da[2],da[3],da[4],da[5]); + } +#if !defined(NOT_RTK_BSP) && !defined(CONFIG_OPENWRT_SDK) + else + pskb->__unused = 0; +#endif + +#ifdef __LINUX_2_6__ + if(pskb->dev) + pskb->protocol = eth_type_trans(pskb,pskb->dev); + else +#endif + pskb->protocol = eth_type_trans(pskb, priv->dev); + +#if defined(HS2_SUPPORT) + /* Hotspot 2.0 Release 1 */ + if(pskb->protocol == __constant_htons(ETHER_TDLS)) + { + priv->ext_stats.rx_data_drops++; + HS2_DEBUG_INFO("RX DROP: TDLS!\n"); + return FAIL; + } +#endif + +#ifdef EAPOLSTART_BY_QUEUE + if (*(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN*2) == __constant_htons(0x888e)) + { + unsigned char szEAPOL[] = {0x01, 0x01, 0x00, 0x00}; + DOT11_EAPOL_START Eapol_Start; + + if (!memcmp(pskb->data, szEAPOL, sizeof(szEAPOL))) + { + Eapol_Start.EventId = DOT11_EVENT_EAPOLSTART; + Eapol_Start.IsMoreEvent = FALSE; + memcpy(&Eapol_Start.MACAddr, SKB_MAC_HEADER(pskb) + MACADDRLEN, WLAN_ETHHDR_LEN); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&Eapol_Start, sizeof(DOT11_EAPOL_START)); + event_indicate(priv, SKB_MAC_HEADER(pskb) + MACADDRLEN, 4); + return FAIL; // let dsr free this skb + } + } +#endif +#else +#ifdef CONFIG_RTL_819X_ECOS + if (priv->pmib->dot11OperationEntry.guest_access) + { + if((*(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN*2) != __constant_htons(0x888e)) && + (*(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN*2) != __constant_htons(0x86dd)) && + memcmp(da, freebsd_Hostmac, MACADDRLEN) + ) + { + //wlan sta can't access LAN when guest access is enabled + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: guest access fail!\n"); + return FAIL; + } + else + pskb->__unused = 0xe5; + } +#endif +#endif /* __ECOS */ + +#if defined(WIFI_WPAS_CLI) || (defined(RTK_NL80211) && defined(NON_NL80211_AP)) + if (!(OPMODE & WIFI_STATION_STATE)) +#endif + { +#if (defined(EAP_BY_QUEUE) || defined(INCLUDE_WPA_PSK)) && (!defined(WIFI_HAPD) || defined(HAPD_DRV_PSK_WPS)) +#ifdef WDS + if ((pfrinfo->to_fr_ds != 3) && (*(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN*2) == __constant_htons(0x888e))) +#else + if (*(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN*2) == __constant_htons(0x888e)) +#endif + { + if (IEEE8021X_FUN +#ifdef INCLUDE_WPA_PSK + || (priv->pmib->dot1180211AuthEntry.dot11EnablePSK && + ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_))) +#endif +#ifdef WIFI_SIMPLE_CONFIG + || priv->pmib->wscEntry.wsc_enable +#endif + ) { + unsigned short pkt_len; + +#ifdef __ECOS + pkt_len = pskb->len; +#else + pkt_len = WLAN_ETHHDR_LEN + pskb->len; +#endif + priv->Eap_packet->EventId = DOT11_EVENT_EAP_PACKET; + priv->Eap_packet->IsMoreEvent = FALSE; + memcpy(&(priv->Eap_packet->packet_len), &pkt_len, sizeof(unsigned short)); +#ifdef __ECOS + memcpy(&priv->Eap_packet->packet, pskb->data, pskb->len); +#else + memcpy(&(priv->Eap_packet->packet[0]), SKB_MAC_HEADER(pskb), WLAN_ETHHDR_LEN); + memcpy(&(priv->Eap_packet->packet[WLAN_ETHHDR_LEN]), pskb->data, pskb->len); +#endif +#ifdef EAP_BY_QUEUE + +#ifdef INCLUDE_WPS + + wps_NonQueue_indicate_evt(priv , + (char *)priv->Eap_packet, sizeof(DOT11_EAP_PACKET)); +#else + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, + (unsigned char*)priv->Eap_packet,sizeof(DOT11_EAP_PACKET)); + + event_indicate(priv, NULL, -1); +#endif + +#endif +#ifdef INCLUDE_WPA_PSK +#ifdef __ECOS + psk_indicate_evt(priv, DOT11_EVENT_EAP_PACKET, (unsigned char*)&(priv->Eap_packet->packet[6]), + (unsigned char*)priv->Eap_packet->packet, pskb->len); +#else + psk_indicate_evt(priv, DOT11_EVENT_EAP_PACKET, (unsigned char*)&(priv->Eap_packet->packet[6]), + (unsigned char*)priv->Eap_packet->packet, WLAN_ETHHDR_LEN+pskb->len); +#endif +#endif + +#if !defined(WIFI_HAPD) && (!defined(RTK_NL80211) || defined(NON_NL80211_AP)) + return FAIL; // let dsr free this skb +#endif + } + } +#endif + } // WIFI_WPAS_CLI +#ifndef __ECOS + skb_push(pskb, WLAN_ETHHDR_LEN); // push back due to be pulled by eth_type_trans() +#endif + + if (do_rc) { + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = 0; + if (reorder_ctrl_check(priv, pstat, pfrinfo)) + rtl_netif_rx(priv, pfrinfo->pskb, pstat); + } + else + rtl_netif_rx(priv, pskb, pstat); + } + else + { + if (priv->pmib->dot11OperationEntry.block_relay == 1) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Relay unicast packet is blocked!\n"); +#ifdef RX_SHORTCUT + for (i=0; irx_sc_ent[i].rx_payload_offset = 0; + } +#endif + return FAIL; + } + else if (priv->pmib->dot11OperationEntry.block_relay == 2) { + DEBUG_INFO("Relay unicast packet is blocked! Indicate to bridge.\n"); + rtl_netif_rx(priv, pskb, pstat); + } +#ifdef HS2_SUPPORT + /* Hotspot 2.0 Release 1 */ + else if (priv->pmib->dot11OperationEntry.block_relay == 3) { + HS2_DEBUG_INFO("block_relay=3\n"); + + if(IS_ICMPV4_PROTO(pfrinfo->pskb->data)) { + if(IS_ICMPV4_ECHO_TYPE(pfrinfo->pskb->data)) { + if(priv->pmib->hs2Entry.ICMPv4ECHO == 2) { + memcpy(&pfrinfo->pskb->data[0], priv->pmib->hs2Entry.redir_mac, 6); + HS2_DEBUG_INFO("redirect ICMPv4 Packet to connected portal\n"); + rtl_netif_rx(priv, pskb, pstat); + } + else if(priv->pmib->hs2Entry.ICMPv4ECHO == 0) { + HS2_DEBUG_INFO("Drop ICMPv4 Packet\n"); + return FAIL; + } + /* + else if(priv->pmib->hs2Entry.ICMPv4ECHO == 1) { + panic_printk("Allow ICMPv4 Echo Requests\n"); + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = (unsigned int)dst_pstat; // backup pstat pointer + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + if (rtl8192cd_start_xmit(pfrinfo->pskb, isMeshPoint(dst_pstat)? priv->mesh_dev: priv->dev)) +#else + if (rtl8192cd_start_xmit(pfrinfo->pskb, priv->dev)) +#endif + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_TX_); + } + */ + return 1; + } + } + } +#endif + else { +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif +#ifdef GBWC + if (GBWC_forward_check(priv, pfrinfo->pskb, pstat)) { + // packet is queued, nothing to do + } + else +#endif + if (do_rc) { +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_rx_skb_cnt); +#endif + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = (unsigned int)dst_pstat; // backup pstat pointer + if (reorder_ctrl_check(priv, pstat, pfrinfo)) { +#ifdef TX_SCATTER + pskb->list_num = 0; +#endif + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif +//Joule 2009.03.10 +#ifdef CONFIG_RTK_MESH + if (rtl8192cd_start_xmit(pskb, isMeshPoint(dst_pstat) ? priv->mesh_dev: priv->dev)) +#else + if (rtl8192cd_start_xmit(pskb, priv->dev)) +#endif + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + } else { +#ifdef TX_SCATTER + pskb->list_num = 0; +#endif +#ifdef CONFIG_RTK_MESH +// mantis bug 0000081 2008.07.16 + if (rtl8192cd_start_xmit(pskb, isMeshPoint(dst_pstat) ? priv->mesh_dev: priv->dev)) +#else + if (rtl8192cd_start_xmit(pskb, priv->dev)) +#endif + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + } + } + } + } +#ifdef CLIENT_MODE + else if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) { + // I am station, and just report every frame I received to protocol statck + if (OPMODE & WIFI_STATION_STATE) + pstat = get_stainfo(priv, BSSID); + else // Ad-hoc + pstat = get_stainfo(priv, pfrinfo->sa); + + if (IS_MCAST(pfrinfo->da)) { + // iv, icv and mic are not be used below. Don't care them! + privacy = get_mcast_encrypt_algthm(priv); + } else { + privacy = get_sta_encrypt_algthm(priv, pstat); + } + + rx_sum_up(NULL, pstat, pfrinfo->pktlen, 0); + priv->pshare->NumRxBytesUnicast += pfrinfo->pktlen; + update_sta_rssi(priv, pstat, pfrinfo); + priv->rxDataNumInPeriod++; + if (IS_MCAST(pfrinfo->da)) { + priv->rxMlcstDataNumInPeriod++; +#ifdef SUPPORT_SNMP_MIB + SNMP_MIB_INC(dot11MulticastReceivedFrameCount, 1); +#endif + } else if ((OPMODE & WIFI_STATION_STATE) && (priv->ps_state)) { + if ((GetFrameSubType(get_pframe(pfrinfo)) == WIFI_DATA) +#ifdef WIFI_WMM + || (QOS_ENABLE && pstat->QosEnabled && (GetFrameSubType(get_pframe(pfrinfo)) == WIFI_QOS_DATA)) +#endif + ) { + if (GetMData(pframe)) { +#if defined(WIFI_WMM) && defined(WMM_APSD) + if (QOS_ENABLE && APSD_ENABLE && priv->uapsd_assoc) { + if (!((priv->pmib->dot11QosEntry.UAPSD_AC_BE && ((pfrinfo->tid == 0) || (pfrinfo->tid == 3))) || + (priv->pmib->dot11QosEntry.UAPSD_AC_BK && ((pfrinfo->tid == 1) || (pfrinfo->tid == 2))) || + (priv->pmib->dot11QosEntry.UAPSD_AC_VI && ((pfrinfo->tid == 4) || (pfrinfo->tid == 5))) || + (priv->pmib->dot11QosEntry.UAPSD_AC_VO && ((pfrinfo->tid == 6) || (pfrinfo->tid == 7))))) + issue_PsPoll(priv); + } else +#endif + { + issue_PsPoll(priv); + } + } + } + } + + #if defined(CONFIG_RTL_WAPI_SUPPORT) + if (privacy==_WAPI_SMS4_) { +#if defined(CONFIG_PCI_HCI) + if (wapiHandleRecvPacket(pfrinfo, pstat)==SUCCESS) + { + return SUCCESS; + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (pstat->wapiInfo && (wapiDisable != pstat->wapiInfo->wapiType)) + { + int waiOffset; + if ((SecIsWAIPacket(pskb, &waiOffset) == SUCCESS) || + (pstat->wapiInfo->wapiState != ST_WAPI_AE_MSKA_ESTABLISH)) + { + notify_recv_wai_frame(priv, pfrinfo); + return SUCCESS; + } + } +#endif + } + #endif + // Process A-MSDU + if (is_qos_data(pframe)) { + memcpy(qosControl, GetQosControl(pframe), 2); + if (qosControl[0] & BIT(7)) // A-MSDU present + { + process_amsdu(priv, pstat, pfrinfo); + return SUCCESS; + } +#ifdef RX_BUFFER_GATHER + else if (!list_empty(&priv->pshare->gather_list)) + flush_rx_list(priv); +#endif + } + + res = skb_p80211_to_ether(priv->dev, privacy, pfrinfo); + if (res == FAIL) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: skb_p80211_to_ether fail!\n"); + return FAIL; + } + +#ifdef RTK_BR_EXT + if(nat25_handle_frame(priv, pskb) == -1) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); + return FAIL; + } +#endif + +#if 0 //rtk_nl80211 (for debug) +#ifdef __ECOS + if (*(unsigned short *)(pskb->data + MACADDRLEN*2) == __constant_htons(0x888e)) +#else + if (*(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN*2) == __constant_htons(0x888e)) +#endif +{ + + printk("[%s][%d]rx eap packets len = %d!!\n\n", __FUNCTION__, __LINE__, pskb->len); +} +#endif + +#ifdef __KERNEL__ + pskb->protocol = eth_type_trans(pskb, priv->dev); +#endif + +#if defined(WIFI_WPAS_CLI) || (defined(RTK_NL80211) && defined(NON_NL80211_AP)) + if (!(OPMODE & WIFI_STATION_STATE)) +#endif + { +#if (defined(EAP_BY_QUEUE) || defined(INCLUDE_WPA_PSK)) && (!defined(WIFI_HAPD) || defined(HAPD_DRV_PSK_WPS)) + if (*(unsigned short *)(SKB_MAC_HEADER(pskb) + MACADDRLEN*2) == __constant_htons(0x888e)) + { + unsigned short pkt_len; + +#ifdef __ECOS + pkt_len = pskb->len; +#else + pkt_len = WLAN_ETHHDR_LEN + pskb->len; +#endif + priv->Eap_packet->EventId = DOT11_EVENT_EAP_PACKET; + priv->Eap_packet->IsMoreEvent = FALSE; + memcpy(&(priv->Eap_packet->packet_len), &pkt_len, sizeof(unsigned short)); +#ifdef __ECOS + memcpy(&priv->Eap_packet->packet, pskb->data, pskb->len); +#else + memcpy(&(priv->Eap_packet->packet[0]), SKB_MAC_HEADER(pskb), WLAN_ETHHDR_LEN); + memcpy(&(priv->Eap_packet->packet[WLAN_ETHHDR_LEN]), pskb->data, pskb->len); +#endif +#ifdef EAP_BY_QUEUE + +#ifdef INCLUDE_WPS + + wps_NonQueue_indicate_evt(priv , + (char *)priv->Eap_packet, sizeof(DOT11_EAP_PACKET)); +#else + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, + (unsigned char*)priv->Eap_packet, sizeof(DOT11_EAP_PACKET)); + event_indicate(priv, NULL, -1); +#endif +#endif +#ifdef INCLUDE_WPA_PSK +#ifdef __ECOS + psk_indicate_evt(priv, DOT11_EVENT_EAP_PACKET, (unsigned char*)&(priv->Eap_packet->packet[6]), + (unsigned char*)priv->Eap_packet->packet, pskb->len); +#else + psk_indicate_evt(priv, DOT11_EVENT_EAP_PACKET, (unsigned char*)&(priv->Eap_packet->packet[6]), + (unsigned char*)priv->Eap_packet->packet, WLAN_ETHHDR_LEN+pskb->len); +#endif +#endif + +#if !defined(WIFI_HAPD) && (!defined(RTK_NL80211) || defined(NON_NL80211_AP)) + return FAIL; // let dsr free this skb +#endif + } +#endif + } // WIFI_WPAS_CLI + +#ifdef __KERNEL__ + skb_push(pskb, WLAN_ETHHDR_LEN); // push back due to be pulled by eth_type_trans() +#endif + if (do_rc) { + *(unsigned int *)&(pfrinfo->pskb->cb[4]) = 0; + if (reorder_ctrl_check(priv, pstat, pfrinfo)) + rtl_netif_rx(priv, pskb, pstat); + } + else + rtl_netif_rx(priv, pskb, pstat); + } +#endif // CLIENT_MODE + else + { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Non supported mode in process_datafrme\n"); + return FAIL; + } + + return SUCCESS; +} + + +/* + Actually process RX management frame: + + Process management frame stored in "inputPfrinfo" or gotten from "list", + only one of them is used to get Frame information. + + Note that: + 1. If frame information is gotten from "list", "inputPfrinfo" MUST be NULL. + 2. If frame information is gotten from "inputPfrinfo", "list" MUST be NULL +*/ + void rtl8192cd_rx_mgntframe(struct rtl8192cd_priv *priv, struct list_head *list, + struct rx_frinfo *inputPfrinfo) +{ + struct rx_frinfo *pfrinfo = NULL; + + // for SW LED + if (priv->pshare->LED_cnt_mgn_pkt) + priv->pshare->LED_rx_cnt++; + + /* Get RX frame info */ + if (list) { + /* Indicate the frame information can be gotten from "list" */ + pfrinfo = list_entry(list, struct rx_frinfo, rx_list); + } + else { + /* Indicate the frame information is stored in "inputPfrinfo" */ + pfrinfo = inputPfrinfo; + } + + if (pfrinfo == NULL) + goto out; + + mgt_handler(priv, pfrinfo); + +out: + return; +} + + +/* + Actually process RX control frame: + + Process control frame stored in "inputPfrinfo" or gotten from "list", + only one of them is used to get Frame information. + + Note that: + 1. If frame information is gotten from "list", "inputPfrinfo" MUST be NULL. + 2. If frame information is gotten from "inputPfrinfo", "list" MUST be NULL +*/ +static void rtl8192cd_rx_ctrlframe(struct rtl8192cd_priv *priv, struct list_head *list, + struct rx_frinfo *inputPfrinfo) +{ + struct rx_frinfo *pfrinfo = NULL; + + /* Get RX frame info */ + if (list) { + /* Indicate the frame information can be gotten from "list" */ + pfrinfo = list_entry(list, struct rx_frinfo, rx_list); + } + else { + /* Indicate the frame information is stored in "inputPfrinfo " */ + pfrinfo = inputPfrinfo; + } + + if (pfrinfo == NULL) + goto out; + + ctrl_handler(priv, pfrinfo); + +out: + return; +} + + +/* + Actually process RX data frame: + + Process data frame stored in "inputPfrinfo" or gotten from "list", + only one of them is used to get Frame information. + + Note that: + 1. If frame information is gotten from "list", "inputPfrinfo" MUST be NULL. + 2. If frame information is gotten from "inputPfrinfo", "list" MUST be NULL +*/ +__MIPS16 +__IRAM_IN_865X + void rtl8192cd_rx_dataframe(struct rtl8192cd_priv *priv, struct list_head *list, + struct rx_frinfo *inputPfrinfo) +{ + struct rx_frinfo *pfrinfo = NULL; + unsigned char *pframe; + + /* ============== Do releted process for Packet RX ============== */ + // for SW LED + priv->pshare->LED_rx_cnt++; + + // for Rx dynamic tasklet + priv->pshare->rxInt_data_delta++; + + /* Get RX frame info */ + if (list) { + /* Indicate the frame information can be gotten from "list" */ + pfrinfo = list_entry(list, struct rx_frinfo, rx_list); + } + else { + /* Indicate the frame information is stored in "inputPfrinfo " */ + pfrinfo = inputPfrinfo; + } + + if (pfrinfo == NULL) { + printk("pfrinfo == NULL\n"); + goto out; + } + + pframe = get_pframe(pfrinfo); + +#ifdef WIFI_WMM + if (is_qos_data(pframe)) { + if ((OPMODE & WIFI_AP_STATE) && (QOS_ENABLE)) { + if ((pfrinfo->tid == 7) || (pfrinfo->tid == 6)) { + priv->pshare->phw->VO_pkt_count++; + } else if ((pfrinfo->tid == 5) || (pfrinfo->tid == 4)) { + priv->pshare->phw->VI_pkt_count++; + if (priv->pshare->rf_ft_var.wifi_beq_iot) + priv->pshare->phw->VI_rx_pkt_count++; + } else if ((pfrinfo->tid == 2) || (pfrinfo->tid == 1)) { + priv->pshare->phw->BK_pkt_count++; + } + } + } +#endif + + // check power save state +#ifndef DRVMAC_LB + if (OPMODE & WIFI_AP_STATE) { + if (get_stainfo(priv, GetAddr2Ptr(pframe)) != NULL) { + if (IS_BSSID(priv, GetAddr1Ptr(pframe))) { + struct stat_info *pstat = get_stainfo(priv, pfrinfo->sa); +#ifdef HW_DETEC_POWER_STATE + if (GET_CHIP_VER(priv) == VERSION_8814A) { + // 8813 power state control only by HW, not by SW. + // Only if HW detect macid not ready, SW patch this packet + if(pfrinfo->macid == HW_MACID_SEARCH_NOT_READY) + { + printk("%s %d HW_MACID_SEARCH_NOT_READY",__FUNCTION__,__LINE__); + if(priv->pshare->HWPwrStateUpdate[pstat->aid]==false) + { + printk("%s %d HW not update By SW Aid = %x \n",__FUNCTION__,__LINE__,pstat->aid); + pwr_state(priv, pfrinfo); + } + } + else if(pfrinfo->macid > HW_MACID_SEARCH_SUPPORT_NUM) + { + pwr_state(priv, pfrinfo); + } + } else +#endif // #ifdef HW_DETEC_POWER_STATE + { + if (pstat && (pstat->state & WIFI_ASOC_STATE) && + (GetPwrMgt(pframe) != ((pstat->state & WIFI_SLEEP_STATE ? 1 : 0)))) + pwr_state(priv, pfrinfo); + } + } + } + } +#endif + + /* ============== Start to process RX dataframe ============== */ +#if defined(CONFIG_RTK_VOIP_QOS)|| defined(CONFIG_RTK_VLAN_WAN_TAG_SUPPORT) +#ifdef MBSSID + if(IS_VAP_INTERFACE(priv)) + pfrinfo->pskb->srcPhyPort += (priv->vap_id+1); +#endif +#endif + +#if defined(DRVMAC_LB) && defined(WIFI_WMM) + if(priv->pmib->miscEntry.drvmac_lb /*&& priv->pmib->miscEntry.lb_tps*/) { + if ((QOS_ENABLE) && (GetFrameSubType(get_pframe(pfrinfo)) == (BIT(7)|WIFI_DATA_NULL))) + process_lb_qos_null(priv, pfrinfo); + else if ((QOS_ENABLE) && (GetFrameSubType(get_pframe(pfrinfo)) == (WIFI_QOS_DATA))) + process_lb_qos(priv, pfrinfo); + else { +#if 0 + if (!QOS_ENABLE) + printk("wifi qos not enabled, "); + printk("cannot match loopback pkt pattern!!!\n"); + if (pfrinfo->pskb && pfrinfo->pskb->data) { + unsigned int *p_skb_int = (unsigned int *)pfrinfo->pskb->data; + printk("ERROR PKT===>> 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x <<===\n", + *p_skb_int, *(p_skb_int+1), *(p_skb_int+2), *(p_skb_int+3), *(p_skb_int+4), *(p_skb_int+5), + *(p_skb_int+6), *(p_skb_int+7)); + } +#endif + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + } + goto out; + } +#endif + + if (GetFrameSubType(pframe) == (BIT(7)|WIFI_DATA_NULL)) { //Intel 6205 IOT issue + //printk("\n receive qos_null !!\n\n"); +#if defined(WIFI_WMM) && defined(WMM_APSD) + if((OPMODE & WIFI_AP_STATE) && (QOS_ENABLE)) { + rtl8192cd_rx_handle_Spec_Null_Data(priv, pfrinfo); // for AR5007 IOT ISSUE + process_qos_null(priv, pfrinfo); + } + else +#endif + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + goto out; + } + +#if 0 +#if defined(WIFI_WMM) && defined(WMM_APSD) + if( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (QOS_ENABLE) && (APSD_ENABLE) && (GetFrameSubType(get_pframe(pfrinfo)) == (BIT(7)|WIFI_DATA_NULL))) { + rtl8192cd_rx_handle_Spec_Null_Data(priv, pfrinfo); // for AR5007 IOT ISSUE + process_qos_null(priv, pfrinfo); + goto out; + } +#endif +#endif + + // for AR5007 IOT ISSUE + if ( (GetFrameSubType(pframe) == WIFI_DATA_NULL) +#ifdef WIFI_WMM + || ((QOS_ENABLE) && ((GetFrameSubType(pframe)) == (WIFI_DATA_NULL | BIT(7)))) +#endif + ){ + rtl8192cd_rx_handle_Spec_Null_Data(priv, pfrinfo); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + goto out; + } + +#ifdef RX_SHORTCUT + if (!priv->pmib->dot11OperationEntry.disable_rxsc && + !IS_MCAST(pfrinfo->da) +#if defined(WIFI_WMM) && defined(WMM_APSD) + && (!( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (APSD_ENABLE) && (GetFrameSubType(pframe) == (WIFI_QOS_DATA)) && (GetPwrMgt(pframe)))) +#endif + ) { + if (rx_shortcut(priv, pfrinfo) >= 0) { +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.rx_cnt_sc++; +#endif + goto out; + } + } +#endif + +#if 0//rtk_nl80211 (for debug) +{ + struct sk_buff *pskb = get_pskb(pfrinfo); + unsigned int encrypt; + unsigned char *pframe; + unsigned short proto; + + unsigned int hdr_len; + unsigned char *pbuf; + + // rx a encrypt packet but encryption is not enabled in local mib, discard it + hdr_len = pfrinfo->hdr_len; + pframe = get_pframe(pfrinfo); + pbuf = pframe + hdr_len + sizeof(struct wlan_llc_t) + 3; + proto = *(unsigned short *)pbuf; + + if (proto == __constant_htons(0x888e)) + printk("[rx eap] from 0x%02x 0x%02x 0x%02x\n", pfrinfo->sa[3], pfrinfo->sa[4], pfrinfo->sa[5]); +} +#endif + +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.rx_cnt_nosc++; +#endif + pfrinfo = defrag_frame(priv, pfrinfo); + + if (pfrinfo == NULL) + goto out; + + if (process_datafrme(priv, pfrinfo) == FAIL) { + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + } + +out: + return; +} + +#ifdef CONFIG_PCI_HCI +#if !(defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX)) +void process_all_queues(struct rtl8192cd_priv *priv) +{ + struct list_head *list = NULL; + +#if defined(SMP_SYNC) + unsigned long x; +#endif + // processing data frame first... + while(1) + { + SMP_LOCK_RX_DATA(x); + list = dequeue_frame(priv, &(priv->rx_datalist)); + SMP_UNLOCK_RX_DATA(x); + + if (list == NULL) + break; + + rtl8192cd_rx_dataframe(priv, list, NULL); + } + + // going to process management frame + while(1) + { + SMP_LOCK_RX_MGT(x); + list = dequeue_frame(priv, &(priv->rx_mgtlist)); + SMP_UNLOCK_RX_MGT(x); + + if (list == NULL) + break; + + rtl8192cd_rx_mgntframe(priv, list, NULL); + } + + while(1) + { + SMP_LOCK_RX_CTRL(x); + list = dequeue_frame(priv, &(priv->rx_ctrllist)); + SMP_UNLOCK_RX_CTRL(x); + + if (list == NULL) + break; + + rtl8192cd_rx_ctrlframe(priv, list, NULL); + } + + if (!list_empty(&priv->wakeup_list)) + process_dzqueue(priv); +} + +#ifdef CONFIG_WLAN_HAL +__IRAM_IN_865X +static void rtl88XX_rx_dsr(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned long mask, mask_rx; +#ifdef MBSSID + int i; +#endif + +#ifndef __ASUS_DVD__ + extern int r3k_flush_dcache_range(int, int); +#endif + +#ifdef __KERNEL__ + // disable rx interrupt in DSR + SAVE_INT_AND_CLI(flags); + GET_HAL_INTERFACE(priv)->DisableRxRelatedInterruptHandler(priv); +#endif + + rtl8192cd_rx_isr(priv); + +#ifdef __KERNEL__ + RESTORE_INT(flags); +#endif + + process_all_queues(priv); + +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + process_all_queues(GET_VXD_PRIV(priv)); +#endif + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + process_all_queues(priv->pvap_priv[i]); + } + } +#endif + +#ifdef __KERNEL__ + GET_HAL_INTERFACE(priv)->EnableRxRelatedInterruptHandler(priv); +#endif +} +#endif // CONFIG_WLAN_HAL + +__IRAM_IN_865X +void rtl8192cd_rx_dsr(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned long mask, mask_rx, mask_ext, mask_ext_rx=0; +#ifdef MBSSID + int i; +#endif + +#ifndef __ASUS_DVD__ + extern int r3k_flush_dcache_range(int, int); +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + rtl88XX_rx_dsr(task_priv); + return; + }else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + {//not HAL +#ifdef __KERNEL__ + // disable rx interrupt in DSR + SAVE_INT_AND_CLI(flags); +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if (priv->pshare->InterruptMask & HIMR_88E_ROK) + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask & ~HIMR_88E_ROK); + if (priv->pshare->InterruptMaskExt & HIMRE_88E_RXFOVW) + RTL_W32(REG_88E_HIMRE, priv->pshare->InterruptMaskExt & ~HIMRE_88E_RXFOVW); + } else +#endif + { + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + { + mask = RTL_R32(REG_92E_HIMR); + mask_rx = mask & HIMR_92E_ROK; + RTL_W32(REG_92E_HIMR, mask & ~mask_rx); + + mask_ext = RTL_R32(REG_92E_HIMRE); + mask_ext_rx = mask_ext & HIMRE_92E_RXFOVW; + RTL_W32(REG_92E_HIMRE, mask_ext & ~mask_ext_rx); + } + else +#endif + { + mask = RTL_R32(HIMR); + //mask_rx = mask & (HIMR_RXFOVW | HIMR_RDU | HIMR_ROK); + mask_rx = mask & (HIMR_RXFOVW | HIMR_ROK); + RTL_W32(HIMR, mask & ~mask_rx); + //RTL_W32(HISR, mask_rx); + } + + } +#endif + + rtl8192cd_rx_isr(priv); + +#ifdef __KERNEL__ + RESTORE_INT(flags); +#endif + + process_all_queues(priv); + +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + process_all_queues(GET_VXD_PRIV(priv)); +#endif + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + process_all_queues(priv->pvap_priv[i]); + } + } +#endif + +#ifdef __KERNEL__ +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if (priv->pshare->InterruptMask & HIMR_88E_ROK) + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask); + if (priv->pshare->InterruptMaskExt & HIMRE_88E_RXFOVW) + RTL_W32(REG_88E_HIMRE, priv->pshare->InterruptMaskExt); + } else +#endif + { +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + { + RTL_W32(REG_92E_HIMR, RTL_R32(REG_92E_HIMR) | mask_rx); + RTL_W32(REG_92E_HIMRE, RTL_R32(REG_92E_HIMRE) | mask_ext_rx); + } + else +#endif + { + mask = RTL_R32(HIMR); + RTL_W32(HIMR, mask | mask_rx); + } + + } +#endif + } +} +#endif // !(defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX)) +#endif // CONFIG_PCI_HCI + +#if !(defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX)) +void flush_rx_queue(struct rtl8192cd_priv *priv) +{ + struct list_head *list = NULL; + struct rx_frinfo *pfrinfo = NULL; + + while(1) + { + list = dequeue_frame(priv, &(priv->rx_datalist)); + + if (list == NULL) + break; + + pfrinfo = list_entry(list, struct rx_frinfo, rx_list); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + } + + while(1) + { + list = dequeue_frame(priv, &(priv->rx_mgtlist)); + + if (list == NULL) + break; + + pfrinfo = list_entry(list, struct rx_frinfo, rx_list); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + } + + while(1) + { + list = dequeue_frame(priv, &(priv->rx_ctrllist)); + + if (list == NULL) + break; + + pfrinfo = list_entry(list, struct rx_frinfo, rx_list); + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + } +} +#endif // !(defined(RTL8190_ISR_RX) && defined(RTL8190_DIRECT_RX)) + + +#if defined(CONFIG_WLAN_HAL) || defined(CONFIG_RTL_8812_SUPPORT)|| defined(CONFIG_RTL_88E_SUPPORT) +static __inline__ unsigned char parse_ps_poll(struct rtl8192cd_priv *priv, struct stat_info *pstat) { + unsigned char Q_id[8]; + unsigned char Q_pktnum[8]; + int i=0; + unsigned int packet_num=0; + unsigned char hw_queue_num = 0; +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { + hw_queue_num = 8; + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + hw_queue_num = 8; + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8188E){ + hw_queue_num = 4; + } +#endif + + if(hw_queue_num) { + if(pstat->sta_in_firmware == 1) + { + /* check how many packet in hw queue now*/ +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if(hw_queue_num == 8) { /* for 92E, 8812, & 8881A*/ + for(i=0; i<4; i++) { + Q_pktnum[i] = (RTL_R8(0x400+i*4+1) & 0x7f); // 14:8 7b + if(Q_pktnum[i]) { + Q_id[i] = (RTL_R8(0x400+i*4+3)>>1) & 0x7f; //31:25 7b + } else { + Q_id[i] = 0; + } + Q_pktnum[i+4] = (RTL_R8(0x468+i*4+1) & 0x7f); // 14:8 7b + if(Q_pktnum[i+4]) { + Q_id[i+4] = (RTL_R8(0x468+i*4+3)>>1) & 0x7f; //31:25 7b + } else { + Q_id[i+4] = 0; + } + } + } +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if(hw_queue_num == 4) { /* 88E */ + for(i=0; i<4; i++) { + Q_pktnum[i] = RTL_R8(0x400+i*4+1); + if(Q_pktnum[i]) { // 15:8 7b + Q_id[i] = (RTL_R8(0x400+i*4+3)>>2) & 0x3f; //31:26 7b + } else { + Q_id[i] = 0; + } + } + } +#endif + + for(i=0; iaid == Q_id[i]) { + packet_num += Q_pktnum[i]; + } + } + + + if(pstat->txpause_flag == 1) { + if(packet_num > 1) { + /* drop packet in hw queue for 11n logo test 4.2.47, + DO NOT change the sequence!!*/ + + /*1. drop packet command*/ + #ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, DECREASE); + #endif + + #ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + UpdateHalMSRRPT8812(priv, pstat, DECREASE); + #endif + #ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8188E) + RTL8188E_MACID_NOLINK(priv, 1, REMAP_AID(pstat)); + #endif + + /*2. wait 500 us to make sure the H2C command is sent to hw, only 92E, 8812, and 8881A needed*/ + if(hw_queue_num == 8) + delay_us(500); + + + /*3. relase tx pause*/ + #ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0 , REMAP_AID(pstat)); + #endif + #ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8812E) + RTL8812_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + #endif + #ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8188E) + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + #endif + + + + pstat->txpause_flag = 0; + + + /*4. wait 50*hwq_num us for hw to deque*/ + if(hw_queue_num == 8) + delay_us(50*packet_num); + else + delay_us(120*packet_num); /* for 88E*/ + + + /*5. cancel drop packet command*/ + #ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); + #endif + #ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + UpdateHalMSRRPT8812(priv, pstat, INCREASE); + #endif + #ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8188E) + RTL8188E_MACID_NOLINK(priv, 0, REMAP_AID(pstat)); + #endif + } + + if(pstat->txpause_flag){ + /*relase tx pause*/ + #ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0 , REMAP_AID(pstat)); + #endif + #ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8812E) + RTL8812_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + #endif + #ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8188E) + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + #endif + pstat->txpause_flag = 0; + + } + + if(packet_num == 1) { + return 1; + } + } + else { + if(packet_num > 0) + return 1; + } + + + DEBUG_WARN("%s %d OnPsPoll, set MACID 0 AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + } + else + { + DEBUG_WARN(" MACID sleep only support %d STA \n", priv->pshare->fw_support_sta_num-1); + } + } + return 0; + +} +#endif + +static void ctrl_handler(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + struct sk_buff *pskbpoll, *pskb; + unsigned char *pframe; + struct stat_info *pstat; + unsigned short aid; + +// 2009.09.08 +#ifndef SMP_SYNC + unsigned long flags; +#endif + + DECLARE_TXINSN(txinsn); + + pframe = get_pframe(pfrinfo); + pskbpoll = get_pskb(pfrinfo); + + aid = GetAid(pframe); + + pstat = get_aidinfo(priv, aid); + + if (pstat == NULL) + goto end_ctrl; + + // check if hardware address matches... + if (memcmp(pstat->hwaddr, (void *)(pframe + 10), MACADDRLEN)) + goto end_ctrl; + +#if defined(CONFIG_PCI_HCI) +#if defined(CONFIG_WLAN_HAL) || defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) + if ((GetFrameSubType(pframe)) == WIFI_PSPOLL) + { + if(parse_ps_poll(priv, pstat) == 1) + goto end_ctrl; + } +#endif + + SAVE_INT_AND_CLI(flags); + + // now dequeue from the pstat's dz_queue + pskb = __skb_dequeue(&pstat->dz_queue); + + RESTORE_INT(flags); + + + if (pskb == NULL) + goto end_ctrl; + + txinsn.q_num = BE_QUEUE; //using low queue for data queue + txinsn.fr_type = _SKB_FRAME_TYPE_; + txinsn.pframe = pskb; + txinsn.phdr = (UINT8 *)get_wlanllchdr_from_poll(priv); + pskb->cb[1] = 0; + + if (pskb->len > priv->pmib->dot11OperationEntry.dot11RTSThreshold) + txinsn.retry = priv->pmib->dot11OperationEntry.dot11LongRetryLimit; + else + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + if (txinsn.phdr == NULL) { + DEBUG_ERR("Can't alloc wlan header!\n"); + goto xmit_skb_fail; + } + + memset((void *)txinsn.phdr, 0, sizeof(struct wlanllc_hdr)); + + SetFrDs(txinsn.phdr); +#ifdef WIFI_WMM + if (pstat && (QOS_ENABLE) && (pstat->QosEnabled)) + SetFrameSubType(txinsn.phdr, WIFI_QOS_DATA); + else +#endif + SetFrameSubType(txinsn.phdr, WIFI_DATA); + + if (skb_queue_len(&pstat->dz_queue)) + SetMData(txinsn.phdr); + +#ifdef A4_STA + if ((pstat->state & WIFI_A4_STA) && IS_MCAST(pskb->data)) { + txinsn.pstat = pstat; + SetToDs(txinsn.phdr); + } +#endif + + if (rtl8192cd_wlantx(priv, &txinsn) == CONGESTED) + { + +xmit_skb_fail: + + priv->ext_stats.tx_drops++; + DEBUG_WARN("TX DROP: Congested!\n"); + if (txinsn.phdr) + release_wlanllchdr_to_poll(priv, txinsn.phdr); + if (pskb) + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + +#ifdef CONFIG_WLAN_HAL +// if ((GetFrameSubType(pframe)) == WIFI_PSPOLL) + { + if(IS_HAL_CHIP(priv)) + { +#ifdef CONFIG_WLAN_HAL_8814AE + if (GET_CHIP_VER(priv) == VERSION_8814A) { + // Release one packet + GET_HAL_INTERFACE(priv)->ReleaseOnePacketHandler(priv,REMAP_AID(pstat)); + } +#endif // #ifdef CONFIG_WLAN_HAL_8814AE + } + } +#endif +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + pstat->sleep_time = jiffies; + if (tx_servq_len(&pstat->tx_queue[BE_QUEUE])) { + rtw_pspoll_sta_enqueue(priv, pstat, ENQUEUE_TO_TAIL); + tasklet_hi_schedule(&priv->pshare->xmit_tasklet); + } +#endif + +end_ctrl: + + if (pskbpoll) { + rtl_kfree_skb(priv, pskbpoll, _SKB_RX_); + } + + return; +} + + +/* +typedef struct tx_sts_struct +{ + // DW 1 + UINT8 TxRateid; + UINT8 TxRate; +} tx_sts; + +typedef struct tag_Tx_Status_Feedback +{ + // For endian transfer --> for driver + // DW 0 + UINT16 Length; // Command packet length + UINT8 Reserve1; + UINT8 Element_ID; // Command packet type + + tx_sts Tx_Sts[NUM_STAT]; +} CMPK_TX_STATUS_T; +*/ + +#ifdef RX_BUFFER_GATHER +static struct sk_buff *get_next_skb(struct rtl8192cd_priv *priv, int remove, int *is_last) +{ + struct rx_frinfo *pfrinfo = NULL; + struct sk_buff *pskb = NULL; + struct list_head *phead, *plist; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + phead = &priv->pshare->gather_list; + plist = phead->next; + + if (plist != phead) { + pfrinfo = list_entry(plist, struct rx_frinfo, rx_list); + pskb = get_pskb(pfrinfo); + if (pskb) { + pskb->tail = pskb->data + pfrinfo->pktlen; + pskb->len = pfrinfo->pktlen; + pskb->dev = priv->dev; + if (remove) + list_del_init(plist); + } + } + + if (is_last && pskb && pfrinfo->gather_flag == GATHER_LAST) + *is_last = 1; + + RESTORE_INT(flags); + return pskb; +} + +static struct sk_buff *shift_padding_len(struct rtl8192cd_priv *priv, struct sk_buff *skb, int len, int *is_last) +{ + struct sk_buff *nskb= skb ; + + if (skb->len < len) { + if (*is_last) + return NULL; + + nskb = get_next_skb(priv, 1, is_last); + if (nskb) + skb_pull(nskb, len - skb->len); + else + DEBUG_ERR("Shift len error (%d, %d)!\n", skb->len, len); + } + else + skb_pull(nskb, len); + + return nskb; +} + +static int get_subframe_len(struct rtl8192cd_priv *priv, struct sk_buff *skb, int is_last) +{ + u8 sub_len[2]; + struct sk_buff *nskb; + int offset; + u16 u16_len; + + if (skb->len < WLAN_ETHHDR_LEN) { + if (is_last) + return 0; + + if (skb->len == WLAN_ETHHDR_LEN -1) { + sub_len[0] = skb->data[MACADDRLEN*2]; + offset = 1; + } + else + offset = WLAN_ETHHDR_LEN -2 - skb->len; + + nskb = get_next_skb(priv, 0, NULL); + if (nskb == NULL) + return -1; + + if (offset == 1) + sub_len[1] = nskb->data[0]; + else + memcpy(sub_len, nskb->data + offset, 2); + } + else + memcpy(sub_len, &skb->data[MACADDRLEN*2], 2); + + u16_len = ntohs(*((u16 *)sub_len)); + return ((int)u16_len); +} + +static struct sk_buff *get_subframe(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct sk_buff **orgskb, int len, int *is_last) +{ + struct sk_buff *nextskb=NULL, *joinskb; + int offset, copy_len; + + if (skb->len < len+WLAN_ETHHDR_LEN) { + int rest_len = len + WLAN_ETHHDR_LEN - skb->len; + + if (*is_last) + return NULL; + + joinskb = dev_alloc_skb(len + WLAN_ETHHDR_LEN); + if (joinskb == NULL) { + DEBUG_ERR("dev_alloc_skb() failed!\n"); + return NULL; + } + memcpy(joinskb->data, skb->data, skb->len); + offset = skb->len; + + do { + if (nextskb) + rtl_kfree_skb(priv, nextskb, _SKB_RX_); + + nextskb = get_next_skb(priv, 1, is_last); + if (nextskb == NULL) { + dev_kfree_skb_any(joinskb); + return NULL; + } + + if (nextskb->len < rest_len && *is_last) { + dev_kfree_skb_any(joinskb); + rtl_kfree_skb(priv, nextskb, _SKB_RX_); + return NULL; + } + if (nextskb->len < rest_len) + copy_len = nextskb->len; + else + copy_len = rest_len; + + memcpy(joinskb->data+offset, nextskb->data, copy_len); + rest_len -= copy_len; + offset += copy_len; + skb_pull(nextskb, copy_len); + }while (rest_len > 0); + rtl_kfree_skb(priv, *orgskb, _SKB_RX_); + *orgskb = nextskb; + skb = joinskb; + } + else + skb_pull(*orgskb, len+WLAN_ETHHDR_LEN); + + return skb; +} +#endif /* RX_BUFFER_GATHER */ + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +static void process_amsdu(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct rx_frinfo *pfrinfo) +{ + unsigned char *pframe, *da; + struct stat_info *dst_pstat = NULL; + struct sk_buff *pskb = NULL, *pnewskb = NULL; + unsigned char *next_head; + int rest, agg_pkt_num=0, i, privacy; + unsigned int subfr_len, padding; + const unsigned char rfc1042_ip_header[8]={0xaa,0xaa,0x03,00,00,00,0x08,0x00}; +#ifdef RX_BUFFER_GATHER + struct sk_buff *nskb; + int rx_gather = 0; + int is_last = 0; +#endif + + pframe = get_pframe(pfrinfo); + pskb = get_pskb(pfrinfo); + + rest = pfrinfo->pktlen - pfrinfo->hdr_len; + next_head = pframe + pfrinfo->hdr_len; + +#ifdef RX_BUFFER_GATHER + if (pfrinfo->gather_flag == GATHER_FIRST) { + skb_pull(pskb, pfrinfo->hdr_len); + rest = pfrinfo->gather_len - pfrinfo->hdr_len; + rx_gather = 1; + } +#endif + + if (GetPrivacy(pframe)) { +#ifdef WDS + if (pfrinfo->to_fr_ds==3) + privacy = priv->pmib->dot11WdsInfo.wdsPrivacy; + else +#endif + privacy = get_sta_encrypt_algthm(priv, pstat); + if ((privacy == _CCMP_PRIVACY_) || (privacy == _TKIP_PRIVACY_)) { + rest -= 8; + next_head += 8; +#ifdef RX_BUFFER_GATHER + pskb->data += 8; + pskb->len -= 8; +#endif + + } + else { // WEP + rest -= 4; + next_head += 4; +#ifdef RX_BUFFER_GATHER + pskb->data += 4; + pskb->len -= 4; +#endif + + } + } + //Wifi Logo FFD 4.2.1 + if (isEqualMACAddr(next_head, rfc1042_ip_header)) + { + DEBUG_ERR("RX DROP: LLC header within an A-MSDU subframe!\n"); +#ifdef RX_BUFFER_GATHER_REORDER + if(pfrinfo->gather_flag == GATHER_FIRST) + flush_rx_list_inq(priv, pfrinfo); +#endif + priv->ext_stats.rx_data_drops++; + rtl_kfree_skb(priv, pskb, _SKB_RX_); + return; + } + while (rest > WLAN_ETHHDR_LEN) { + pnewskb = skb_clone(pskb, GFP_ATOMIC); + if (pnewskb) { + pnewskb->data = next_head; +#ifdef RX_BUFFER_GATHER + if (rx_gather) { + subfr_len = get_subframe_len(priv, pnewskb, is_last); + if (subfr_len <= 0) { + DEBUG_ERR("invalid subfr_len=%d, discard AMSDU!\n", subfr_len); + dev_kfree_skb_any(pnewskb); + break; + } + nskb = get_subframe(priv, pnewskb, &pskb, subfr_len, &is_last); + if (nskb == NULL) { + DEBUG_ERR("get_subframe() failed, discard AMSDU!\n"); + dev_kfree_skb_any(pnewskb); + priv->ext_stats.rx_data_drops++; + break; + } + if (nskb != pnewskb) { + nskb->dev = pnewskb->dev; + dev_kfree_skb_any(pnewskb); + pnewskb = nskb; + } + } + else +#endif + subfr_len = (*(next_head + MACADDRLEN*2) << 8) + (*(next_head + MACADDRLEN*2 + 1)); + + pnewskb->len = WLAN_ETHHDR_LEN + subfr_len; + pnewskb->tail = pnewskb->data + pnewskb->len; +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_rx_skb_cnt); +#endif + + if(pnewskb->tail > pnewskb->end) { + rtl_kfree_skb(priv, pnewskb, _SKB_RX_); + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: sub-frame length too large!\n"); + break; + } + + if (!memcmp(rfc1042_ip_header, pnewskb->data+WLAN_ETHHDR_LEN, 8)) { + for (i=0; idata[19-i] = pnewskb->data[11-i]; + pnewskb->data += 8; + pnewskb->len -= 8; + } + else + strip_amsdu_llc(priv, pnewskb, pstat); + agg_pkt_num++; + + if (OPMODE & WIFI_AP_STATE) + { + da = pnewskb->data; + dst_pstat = get_stainfo(priv, da); + if ((dst_pstat == NULL) || (!(dst_pstat->state & WIFI_ASOC_STATE))) + rtl_netif_rx(priv, pnewskb, pstat); + else + { + if (priv->pmib->dot11OperationEntry.block_relay == 1) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: Relay unicast packet is blocked!\n"); +#ifdef RX_SHORTCUT + for (i=0; irx_sc_ent[i].rx_payload_offset = 0; + } +#endif + rtl_kfree_skb(priv, pnewskb, _SKB_RX_); + } + else if (priv->pmib->dot11OperationEntry.block_relay == 2) { + DEBUG_INFO("Relay unicast packet is blocked! Indicate to bridge.\n"); + rtl_netif_rx(priv, pnewskb, pstat); + } + else { +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif +#ifdef GBWC + if (GBWC_forward_check(priv, pnewskb, pstat)) { + // packet is queued, nothing to do + } + else +#endif + { +#ifdef TX_SCATTER + pnewskb->list_num = 0; +#endif +#ifdef CONFIG_RTK_MESH + if (rtl8192cd_start_xmit(pnewskb, isMeshPoint(dst_pstat) ? priv->mesh_dev: priv->dev)) +#else + if (rtl8192cd_start_xmit(pnewskb, priv->dev)) +#endif + rtl_kfree_skb(priv, pnewskb, _SKB_TX_); + } + } + } + } +#ifdef CLIENT_MODE + else if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) + { +#ifdef RTK_BR_EXT + if(nat25_handle_frame(priv, pnewskb) == -1) { + priv->ext_stats.rx_data_drops++; + DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); + rtl_kfree_skb(priv, pnewskb, _SKB_RX_); + } else +#endif + rtl_netif_rx(priv, pnewskb, pstat); + } +#endif + + padding = 4 - ((WLAN_ETHHDR_LEN + subfr_len) % 4); + if (padding == 4) + padding = 0; + rest -= (WLAN_ETHHDR_LEN + subfr_len + padding); + +#ifdef RX_BUFFER_GATHER + if (rx_gather) { + if ((rest <= WLAN_ETHHDR_LEN) && is_last) + break; + + nskb = shift_padding_len(priv, pskb, padding, &is_last); + if (nskb == NULL) { + DEBUG_ERR("shift AMSDU padding len error!\n"); + break; + } + if (nskb != pskb) { + rtl_kfree_skb(priv, pskb, _SKB_RX_); + pskb = nskb; + } + next_head = pskb->data; + } + else +#endif + next_head += (WLAN_ETHHDR_LEN + subfr_len + padding); + } + else { + // Can't get new skb header, drop this packet + break; + } + } + + // clear saved shortcut data +#ifdef RX_SHORTCUT + for (i=0; irx_sc_ent[i].rx_payload_offset = 0; + } +#endif + +#ifdef _DEBUG_RTL8192CD_ + switch (agg_pkt_num) { + case 0: + pstat->rx_amsdu_err++; + break; + case 1: + pstat->rx_amsdu_1pkt++; + break; + case 2: + pstat->rx_amsdu_2pkt++; + break; + case 3: + pstat->rx_amsdu_3pkt++; + break; + case 4: + pstat->rx_amsdu_4pkt++; + break; + case 5: + pstat->rx_amsdu_5pkt++; + break; + default: + pstat->rx_amsdu_gt5pkt++; + break; + } +#endif + + rtl_kfree_skb(priv, pskb, _SKB_RX_); +} + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_rx.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_rx.h new file mode 100755 index 000000000..4dec5d1a5 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_rx.h @@ -0,0 +1,289 @@ +/* + * Header files defines some RX inline routines + * + * $Id: 8192cd_rx.h,v 1.4.4.5 2010/12/10 06:11:55 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_RX_H_ +#define _8192CD_RX_H_ + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_util.h" + +#if defined(CONFIG_RG_WLAN_HWNAT_ACCELERATION) && !defined(CONFIG_ARCH_LUNA_SLAVE) +int fwdEngine_rx_skb (struct re_private *cp, struct sk_buff *skb,struct rx_info *pRxInfo); +#endif + +#define SN_NEXT(n) ((n + 1) & 0xfff) +#define SN_LESS(a, b) (((a - b) & 0x800) != 0) +#define SN_DIFF(a, b) ((a >= b)? (a - b):(0xfff - b + a + 1)) + + +#define init_frinfo(pinfo) \ + do { \ + pinfo->pskb = pskb; \ + pinfo->rssi = 0; \ + INIT_LIST_HEAD(&(pinfo->mpdu_list)); \ + INIT_LIST_HEAD(&(pinfo->rx_list)); \ + } while(0) + + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL +#define ALIGN_OFFSET_SKB_DATA 32 //It is necessary to be power of 2 +#define GetOffsetStartToRXDESC(priv, pskb) (ALIGN_OFFSET_SKB_DATA - ((((unsigned long)pskb->data) + sizeof(struct rx_frinfo)) & (ALIGN_OFFSET_SKB_DATA-1))) + + +static __inline__ +__MIPS16 +__IRAM_IN_865X +void init_rxdesc_88XX( + struct rtl8192cd_priv *priv, + struct sk_buff *pskb, + u2Byte i, + pu4Byte pBufAddr, // output + pu4Byte pBufLen // output + ) +{ + struct rtl8192cd_hw *phw; + struct rx_frinfo *pfrinfo; + u4Byte offset; + + phw = GET_HW(priv); + + offset = GetOffsetStartToRXDESC(priv, pskb); + skb_reserve(pskb, sizeof(struct rx_frinfo) + offset); + pfrinfo = get_pfrinfo(pskb); + init_frinfo(pfrinfo); + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + pfrinfo->is_br_mgnt = 0; +#endif +#ifdef RX_BUFFER_GATHER + pfrinfo->gather_flag = 0; +#endif + +#ifdef __ECOS +#ifdef DELAY_REFILL_RX_BUF + pskb->priv = priv; +#endif +#endif + + phw->rx_infoL[i].pbuf = (void *)pskb; + phw->rx_infoL[i].paddr = get_physical_addr(priv, pskb->data, (RX_BUF_LEN - sizeof(struct rx_frinfo) - offset), PCI_DMA_FROMDEVICE); + + *pBufAddr = (u4Byte)pskb->data; +#if 0 + *pBufLen = RX_BUF_LEN - sizeof(struct rx_frinfo) - offset; +#else + + //3 this buf len must be 32 byte alignment in 8881A !!!!, If not, the fs/ls mechanism will be fail + *pBufLen = RX_BUF_LEN - sizeof(struct rx_frinfo) - 64; +#ifdef CONFIG_WLAN_HAL_8881A + if(GET_CHIP_VER(priv) == VERSION_8881A) { + if ((*pBufLen & 0x1f) != 0) { + *pBufLen = (((*pBufLen) >> 5) << 5); // *pBufLen = *pBufLen / 32 * 32; + //printk("%s(%d): RX_BUF_LEN(%d) must be 32 byte alignment !!! \n", __FUNCTION__, __LINE__, *pBufLen); + } + } +#endif + +#endif + +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + // Remove it because pci_map_single() in get_physical_addr() already performed memory sync. + //rtl_cache_sync_wback(priv, bus_to_virt(phw->rx_infoL[i].paddr), RX_BUF_LEN - sizeof(struct rx_frinfo) - offset, PCI_DMA_FROMDEVICE); +#else +#ifdef TRXBD_CACHABLE_REGION + memset(phw->rx_infoL[i].paddr, 0, RX_BUF_LEN - sizeof(struct rx_frinfo) - offset); + _dma_cache_wback((unsigned long)(bus_to_virt(phw->rx_infoL[i].paddr)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), + RX_BUF_LEN - sizeof(struct rx_frinfo) - offset); + +// _dma_cache_inv((unsigned long)(bus_to_virt(phw->rx_infoL[i].paddr)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), +// RX_BUF_LEN - sizeof(struct rx_frinfo) - offset); +#else + rtl_cache_sync_wback(priv, bus_to_virt(phw->rx_infoL[i].paddr), RX_BUF_LEN - sizeof(struct rx_frinfo) - offset, PCI_DMA_FROMDEVICE); +#endif +#endif +} +#endif //CONFIG_WLAN_HAL + +static __inline__ void init_rxdesc(struct sk_buff *pskb, int i, struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_hw *phw; + struct rx_frinfo *pfrinfo; + int offset; + + phw = GET_HW(priv); + + offset = 0x20 - ((((unsigned long)pskb->data) + sizeof(struct rx_frinfo)) & 0x1f); // need 32 byte aligned + skb_reserve(pskb, sizeof(struct rx_frinfo) + offset); + pfrinfo = get_pfrinfo(pskb); + + init_frinfo(pfrinfo); +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + pfrinfo->is_br_mgnt = 0; +#endif +#ifdef RX_BUFFER_GATHER + pfrinfo->gather_flag = 0; +#endif + +#ifdef __ECOS +#ifdef DELAY_REFILL_RX_BUF + pskb->priv = priv; +#endif +#endif + + phw->rx_infoL[i].pbuf = (void *)pskb; + phw->rx_infoL[i].paddr = get_physical_addr(priv, pskb->data, (RX_BUF_LEN - sizeof(struct rx_frinfo) - 64), PCI_DMA_FROMDEVICE); + phw->rx_descL[i].Dword6 = set_desc(phw->rx_infoL[i].paddr); +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + // Remove it because pci_map_single() in get_physical_addr() already performed memory sync. + //rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(phw->rx_infoL[i].paddr), RX_BUF_LEN - sizeof(struct rx_frinfo)-64, PCI_DMA_FROMDEVICE); +#else + rtl_cache_sync_wback(priv, (unsigned long)(phw->rx_infoL[i].paddr), RX_BUF_LEN - sizeof(struct rx_frinfo)-64, PCI_DMA_FROMDEVICE); +#endif + phw->rx_descL[i].Dword0 = set_desc((i == (NUM_RX_DESC - 1)? RX_EOR : 0) | RX_OWN |((RX_BUF_LEN - sizeof(struct rx_frinfo)-64) & RX_PktLenMask)); //32 for alignment, 32 for TKIP MIC + +} +#endif // CONFIG_PCI_HCI + +static __inline__ unsigned char cal_rssi_avg_mp(struct rtl8192cd_priv *priv, unsigned int agv, unsigned int pkt_rssi) +{ + unsigned int rssi; + + rssi = ((agv * (100 - priv->pshare->mp_rssi_weight)) + (pkt_rssi*priv->pshare->mp_rssi_weight)) / 100; + if (pkt_rssi > agv) + rssi++; + + return (unsigned char)rssi; +} + +static __inline__ unsigned char cal_rssi_avg(unsigned int agv, unsigned int pkt_rssi) +{ + unsigned int rssi; + + rssi = ((agv * 19) + pkt_rssi) / 20; + if (pkt_rssi > agv) + rssi++; + + return (unsigned char)rssi; +} + + +static __inline__ void update_sta_rssi(struct rtl8192cd_priv *priv, + struct stat_info *pstat, struct rx_frinfo *pfrinfo) +{ + int i; + +#ifdef SW_ANT_SWITCH + if(priv->pshare->RSSI_test == TRUE) + return; +#endif + +#ifdef MP_TEST + if (OPMODE & WIFI_MP_STATE) { + //if (priv->pshare->rf_ft_var.rssi_dump) { + if (pfrinfo->physt && pfrinfo->rssi) { + priv->pshare->mp_rssi = cal_rssi_avg_mp(priv, priv->pshare->mp_rssi, pfrinfo->rssi); + priv->pshare->mp_sq = pfrinfo->sq; + priv->pshare->mp_rx_rate = pfrinfo->rx_rate; +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + for (i=0; i<2; i++) + priv->pshare->mp_rf_info.mimorssi[i] = cal_rssi_avg_mp(priv, priv->pshare->mp_rf_info.mimorssi[i], pfrinfo->rf_info.mimorssi[i]); + memcpy(&priv->pshare->mp_rf_info.mimosq[0], &pfrinfo->rf_info.mimosq[0], 2); + } +#endif +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + for (i=0; i<2; i++) + priv->pshare->mp_rf_info.mimorssi[i] = cal_rssi_avg_mp(priv, priv->pshare->mp_rf_info.mimorssi[i], pfrinfo->rf_info.mimorssi[i]); + memcpy(&priv->pshare->mp_rf_info.mimosq[0], &pfrinfo->rf_info.mimosq[0], sizeof(struct rf_misc_info) - 2); + } +#endif + } + return; + } +#endif + + if (pfrinfo->physt) { + if (pfrinfo->rssi) { + +#if defined(HW_ANT_SWITCH)&& (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + if (pfrinfo->driver_info_size > 0) { + unsigned char *phystatus = (unsigned char*)pfrinfo->driver_info; + int i = 1&(phystatus[27]>>7); + if (is_CCK_rate(pfrinfo->rx_rate)) + ++(pstat->cckPktCount[i]); + else + ++(pstat->hwRxAntSel[i]); + if(!pstat->AntRSSI[i]) + pstat->AntRSSI[i] = pfrinfo->rssi; + else + pstat->AntRSSI[i] = cal_rssi_avg(pstat->AntRSSI[i], pfrinfo->rssi); + + if(priv->pshare->rf_ft_var.ant_dump&1) { + panic_printk("pkt--> cck:%d, B7=%d, B6=%d, R:(%d) Len:%d\n", is_CCK_rate(pfrinfo->rx_rate), + i, (1&(phystatus[27]>>6)) + , pfrinfo->rssi, pfrinfo->pktlen); + } + + } +#endif + + pstat->rssi = cal_rssi_avg(pstat->rssi, pfrinfo->rssi); + pstat->sq = pfrinfo->sq; + pstat->rx_rate = pfrinfo->rx_rate; + pstat->rx_bw = pfrinfo->rx_bw; + pstat->rx_splcp = pfrinfo->rx_splcp; + + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + if (pfrinfo->rf_info.mimorssi[0] != 0 || pfrinfo->rf_info.mimorssi[1] != 0) + for (i=0; i<2; i++) + pstat->rf_info.mimorssi[i] = cal_rssi_avg(pstat->rf_info.mimorssi[i], pfrinfo->rf_info.mimorssi[i]); + + if (priv->pshare->rf_ft_var.rssi_dump) + memcpy(&pstat->rf_info.mimosq[0], &pfrinfo->rf_info.mimosq[0], sizeof(struct rf_misc_info) - 2); + } +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + if (pfrinfo->rf_info.mimorssi[0] != 0 || pfrinfo->rf_info.mimorssi[1] != 0) + for (i=0; i<2; i++) + pstat->rf_info.mimorssi[i] = cal_rssi_avg(pstat->rf_info.mimorssi[i], pfrinfo->rf_info.mimorssi[i]); + + if (priv->pshare->rf_ft_var.rssi_dump) + memcpy(&pstat->rf_info.mimosq[0], &pfrinfo->rf_info.mimosq[0], sizeof(struct rf_misc_info) - 2); + } +#endif + + if (pstat->highest_rx_rate < pstat->rx_rate) + pstat->highest_rx_rate = pstat->rx_rate; + } + } +} +#endif // _8192CD_RX_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_security.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_security.c new file mode 100755 index 000000000..c82514128 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_security.c @@ -0,0 +1,2268 @@ +/* + * Handle routines to communicate with AUTH daemon (802.1x authenticator) + * + * $Id: 8192cd_security.c,v 1.10.2.9 2011/01/10 08:19:42 jimmylin Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_SECURITY_C_ +#ifdef __KERNEL__ +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#if !defined(__KERNEL__) && !defined(__ECOS) +#include "./sys-support.h" +#endif + +#include "./8192cd.h" +#include "./8192cd_security.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + +#if defined(CONFIG_RTL_WAPI_SUPPORT) +#include "wapi_wai.h" +#endif + +#ifdef INCLUDE_WPS +#include "./wps/wsc.h" +#endif + +#ifdef RTK_NL80211 +#include "8192cd_cfg80211.h" +#endif + + +#define E_MSG_DOT11_2LARGE "ItemSize Too Large" +#define E_MSG_DOT11_QFULL "Event Queue Full" +#define E_MSG_DOT11_QEMPTY "Event Queue Empty" + + +void DOT11_InitQueue(DOT11_QUEUE * q) +{ + q->Head = 0; + q->Tail = 0; + q->NumItem = 0; + q->MaxItem = MAXQUEUESIZE; +} + +#ifndef WITHOUT_ENQUEUE +/*-------------------------------------------------------------------------------- + Return Value +Success : return 0; +Fail : return E_DOT11_QFULL if queue is full +return E_DOT1ZX_2LARGE if the item size is large than allocated +--------------------------------------------------------------------------------*/ +int DOT11_EnQueue(unsigned long task_priv, DOT11_QUEUE *q, unsigned char *item, int itemsize) +{ +#ifdef __KERNEL__ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; +#endif +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (itemsize > MAXDATALEN) + return E_DOT11_2LARGE; + + SAVE_INT_AND_CLI(flags); + + if (DOT11_IsFullQueue(q)) { + RESTORE_INT(flags); + return E_DOT11_QFULL; + } + + q->ItemArray[q->Tail].ItemSize = itemsize; + memset(q->ItemArray[q->Tail].Item, 0, sizeof(q->ItemArray[q->Tail].Item)); + memcpy(q->ItemArray[q->Tail].Item, item, itemsize); + q->NumItem++; + if((q->Tail+1) == MAXQUEUESIZE) + q->Tail = 0; + else + q->Tail++; + + RESTORE_INT(flags); + return 0; +} + + +int DOT11_DeQueue(unsigned long task_priv, DOT11_QUEUE *q, unsigned char *item, int *itemsize) +{ +#ifdef __KERNEL__ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; +#endif +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + if (DOT11_IsEmptyQueue(q)) { + RESTORE_INT(flags); + return E_DOT11_QEMPTY; + } + + memcpy(item, q->ItemArray[q->Head].Item, q->ItemArray[q->Head].ItemSize); + *itemsize = q->ItemArray[q->Head].ItemSize; + q->NumItem--; + if((q->Head+1) == MAXQUEUESIZE) + q->Head = 0; + else + q->Head++; + + RESTORE_INT(flags); + return 0; +} +#endif // !WITHOUT_ENQUEUE + + +#if 0 +void DOT11_PrintQueue(DOT11_QUEUE *q) +{ + int i, j, index; + + printk("\n/-------------------------------------------------\n[DOT11_PrintQueue]: MaxItem = %d, NumItem = %d, Head = %d, Tail = %d\n", q->MaxItem, q->NumItem, q->Head, q->Tail); + for(i=0; iNumItem; i++) { + index = (i + q->Head) % q->MaxItem; + printk("Queue[%d].ItemSize = %d ", index, q->ItemArray[index].ItemSize); + for(j=0; jItemArray[index].ItemSize; j++) + printk(" %x", q->ItemArray[index].Item[j]); + printk("\n"); + } + printk("------------------------------------------------/\n"); +} + + +char *DOT11_ErrMsgQueue(int err) +{ + switch(err) + { + case E_DOT11_2LARGE: + return E_MSG_DOT11_2LARGE; + case E_DOT11_QFULL: + return E_MSG_DOT11_QFULL; + case E_DOT11_QEMPTY: + return E_MSG_DOT11_QEMPTY; + default: + return "E_MSG_DOT11_QNOERR"; + } +} + + +void DOT11_Dump(char *fun, UINT8 *buf, int size, char *comment) +{ + int i; + + printk("$$ %s $$: %s", fun, comment); + if (buf != NULL) { + printk("\nMessage is %d bytes %x hex", size, size); + for (i = 0; i < size; i++) { + if (i % 16 == 0) printk("\n\t"); + printk("%2x ", *(buf+i)); + } + } + printk("\n"); +} +#endif + + +/*------------------------------------------------------------ + Set RSNIE is to set Information Element of AP + Return Value +Success : 0 +------------------------------------------------------------*/ +static int DOT11_Process_Set_RSNIE(struct net_device *dev, struct iw_point *data) +{ + struct Dot11RsnIE *pdot11RsnIE; + struct wifi_mib *pmib; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + +#ifdef HS2_SUPPORT + unsigned char rsnie_hdr_OSEN[4]={0x50, 0x6F, 0x9A, 0x12}; +#endif + DOT11_SET_RSNIE *Set_RSNIE = (DOT11_SET_RSNIE *)data->pointer; + + DEBUG_INFO("going to set rsnie\n"); + pmib = priv->pmib; + pdot11RsnIE = &pmib->dot11RsnIE; + if(Set_RSNIE->Flag == DOT11_Ioctl_Set) + { + pdot11RsnIE->rsnielen = Set_RSNIE->RSNIELen; + memcpy((void *)pdot11RsnIE->rsnie, Set_RSNIE->RSNIE, pdot11RsnIE->rsnielen); + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1; + DEBUG_INFO("DOT11_Process_Set_RSNIE rsnielen=%d\n", pdot11RsnIE->rsnielen); + + // see whether if driver is open. If not, do not enable tx/rx, david + if (!netif_running(priv->dev)) { +#ifdef __OSK__ + if (IS_VXD_INTERFACE(priv) && pdot11RsnIE->rsnielen > 0) + priv->pmib->dot11OperationEntry.keep_rsnie = 1; +#endif + return 0; + } + + // Alway enable tx/rx in rtl8190_init_hw_PCI() + //RTL_W8(_CR_, BIT(2) | BIT(3)); +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + if (!priv->pmib->dot1180211AuthEntry.dot11EnablePSK) +#endif + { + if (OPMODE & WIFI_AP_STATE) { +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) +#endif + { + if (priv->auto_channel) { + priv->ss_ssidlen = 0; + DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=0\n", (char *)__FUNCTION__); + start_clnt_ss(priv); + } + } + } +//for openwrt 8021x donot trigger site survey when rsnie init in init sw +#if defined(CLIENT_MODE) && !defined(RTK_NL80211) && !defined(WIFI_WPAS_CLI) + if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) + start_clnt_lookup(priv, RESCAN); +#endif + } + } + else if(Set_RSNIE->Flag == DOT11_Ioctl_Query) + { + } + return 0; +} + + +#if 0 +char *DOT11_Parse_RSNIE_Err(int err) +{ + switch(err) + { + case ERROR_BUFFER_TOO_SMALL: + return RSN_STRERROR_BUFFER_TOO_SMALL; + case ERROR_INVALID_PARA: + return RSN_STRERROR_INVALID_PARAMETER; + case ERROR_INVALID_RSNIE: + return RSN_STRERROR_INVALID_RSNIE; + case ERROR_INVALID_MULTICASTCIPHER: + return RSN_STRERROR_INVALID_MULTICASTCIPHER; + case ERROR_INVALID_UNICASTCIPHER: + return RSN_STRERROR_INVALID_UNICASTCIPHER; + case ERROR_INVALID_AUTHKEYMANAGE: + return RSN_STRERROR_INVALID_AUTHKEYMANAGE; + case ERROR_UNSUPPORTED_RSNEVERSION: + return RSN_STRERROR_UNSUPPORTED_RSNEVERSION; + case ERROR_INVALID_CAPABILITIES: + return RSN_STRERROR_INVALID_CAPABILITIES; + default: + return "Uknown Failure"; + } +} +#endif + + +/*------------------------------------------------- + Send association response to STA + Return Value +Success : 0 +---------------------------------------------------*/ +static int DOT11_Process_Association_Rsp(struct net_device *dev, struct iw_point *data, int frame_type) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + struct stat_info *pstat; + unsigned char *hwaddr; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + DOT11_ASSOCIATIIN_RSP *Assoc_Rsp = (DOT11_ASSOCIATIIN_RSP *)data->pointer; + + pstat = get_stainfo(priv, (UINT8 *)Assoc_Rsp->MACAddr); + + if (pstat == NULL) + return (-1); + + hwaddr = (unsigned char *)Assoc_Rsp->MACAddr; + DEBUG_INFO("802.1x issue assoc_rsp sta:%02X%02X%02X%02X%02X%02X status:%d\n", + hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5], Assoc_Rsp->Status); + + issue_asocrsp(priv, Assoc_Rsp->Status, pstat, frame_type); + + if (Assoc_Rsp->Status != 0) + { + SAVE_INT_AND_CLI(flags); + if (asoc_list_del(priv, pstat)) + { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + LOG_MSG("A STA is rejected by 802.1x daemon - %02X:%02X:%02X:%02X:%02X:%02X\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + } + } + + free_stainfo(priv, pstat); + RESTORE_INT(flags); + } + else + update_fwtbl_asoclst(priv, pstat); + + return 0; +} + + +/*------------------------------------------------- + Send Disassociation request to STA + Return Value +Success : 0 +---------------------------------------------------*/ +#ifdef CONFIG_PCI_HCI +static inline +#endif +int __DOT11_Process_Disconnect_Req(struct net_device *dev, struct iw_point *data) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + struct stat_info *pstat; + unsigned char *hwaddr; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + DOT11_DISCONNECT_REQ *Disconnect_Req = (DOT11_DISCONNECT_REQ *)data->pointer; + + pstat = get_stainfo(priv, (UINT8 *)Disconnect_Req->MACAddr); + + if (pstat == NULL) + return (-1); + + hwaddr = (unsigned char *)Disconnect_Req->MACAddr; + +#ifdef WIFI_SIMPLE_CONFIG + if (wsc_disconn_list_check(priv, hwaddr)) { + DEBUG_INFO("Ignore issue disassoc sta:%02X%02X%02X%02X%02X%02X due to STA had reconnected\n", + hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]); + return 0; + } +#endif + + DEBUG_INFO("802.1x issue disassoc sta:%02X%02X%02X%02X%02X%02X reason:%d\n", + hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5], Disconnect_Req->Reason); + +#ifdef CLIENT_MODE + if(OPMODE & WIFI_STATION_STATE){ + + if((OPMODE&( WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)) + ==( WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)) + { + issue_deauth(priv, BSSID, _RSON_DEAUTH_STA_LEAVING_); + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)); +#ifndef WIFI_WPAS_CLI +#ifdef SMART_REPEATER_MODE + if(GET_MIB(priv)->ap_profile.enable_profile && GET_MIB(priv)->ap_profile.profile_num > 0) + { + if((priv->site_survey->count_target > 0) && ((priv->join_index+1) > priv->site_survey->count_target)){ + start_clnt_lookup(priv, RESCAN); + }else{ + start_clnt_lookup(priv, DONTRESCAN); + } + } else +#endif + { + start_clnt_lookup(priv, RESCAN); + } +#endif // !WIFI_WPAS_CLI + //SME_DEBUG("!!issue disconnect at wlan!!\n"); + }else{ + return (-1); + } + + }else +#endif + { + issue_deauth(priv, pstat->hwaddr, Disconnect_Req->Reason); + } + + SAVE_INT_AND_CLI(flags); + if (asoc_list_del(priv, pstat)) + { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + LOG_MSG("A STA is rejected by 802.1x daemon - %02X:%02X:%02X:%02X:%02X:%02X\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + } + } + + free_stainfo(priv, pstat); + RESTORE_INT(flags); + + return 0; +} + +int DOT11_Process_Disconnect_Req(struct net_device *dev, struct iw_point *data) +{ +#if defined(CONFIG_PCI_HCI) + return __DOT11_Process_Disconnect_Req(dev, data); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_disconnect_sta(dev, (DOT11_DISCONNECT_REQ *)data->pointer); + return 0; +#endif +} + +/*--------------------------------------------------------------------- + Delete Group Key for AP and Pairwise Key for specific STA + Return Value +Success : 0 +-----------------------------------------------------------------------*/ +int DOT11_Process_Delete_Key(struct net_device *dev, struct iw_point *data) +{ + struct stat_info *pstat = NULL; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + DOT11_DELETE_KEY *Delete_Key = (DOT11_DELETE_KEY *)data->pointer; + struct wifi_mib *pmib = priv->pmib; + + unsigned char MULTICAST_ADD[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + + if (Delete_Key->KeyType == DOT11_KeyType_Group) + { + pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen = 0; + pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKeyLen = 0; + + DEBUG_INFO("Delete Group Key\n"); + if (CamDeleteOneEntry(priv, MULTICAST_ADD, 1, 0)) + priv->pshare->CamEntryOccupied--; +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + if (CamDeleteOneEntry(priv, MULTICAST_ADD, 1, 0)) + priv->pshare->CamEntryOccupied--; +#endif + + } + else if (Delete_Key->KeyType == DOT11_KeyType_Pairwise) + { + pstat = get_stainfo(priv, (UINT8 *)Delete_Key->MACAddr); + if (pstat == NULL) + return (-1); + + pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen = 0; + pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKeyLen = 0; + + DEBUG_INFO("Delete Unicast Key\n"); + if (pstat->dot11KeyMapping.keyInCam == TRUE) { + if (CamDeleteOneEntry(priv, (unsigned char *)Delete_Key->MACAddr, 0, 0)) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + if (CamDeleteOneEntry(priv, (unsigned char *)Delete_Key->MACAddr, 0, 0)) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } +#endif + } + } + + return 0; +} + + +static __inline__ void set_ttkeylen(struct Dot11EncryptKey *pEncryptKey, UINT8 len) +{ + pEncryptKey->dot11TTKeyLen = len; +} + + +static __inline__ void set_tmickeylen(struct Dot11EncryptKey *pEncryptKey, UINT8 len) +{ + pEncryptKey->dot11TMicKeyLen = len; +} + + +static __inline__ void set_tkip_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) +{ + memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); + + memcpy(pEncryptKey->dot11TMicKey1.skey, src + 16, pEncryptKey->dot11TMicKeyLen); + + memcpy(pEncryptKey->dot11TMicKey2.skey, src + 24, pEncryptKey->dot11TMicKeyLen); +} + + +static __inline__ void set_aes_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) +{ + memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); + + memcpy(pEncryptKey->dot11TMicKey1.skey, src, pEncryptKey->dot11TMicKeyLen); +} + + +static __inline__ void set_wep40_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) +{ + memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); +} + + +static __inline__ void set_wep104_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) +{ + memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); +} + + +static __inline__ void clean_pn(unsigned char *pn) +{ + memset(pn, 0, 6); +} + + +/*--------------------------------------------------------------------- + Set Group Key for AP and Pairwise Key for specific STA + Return Value +Success : 0 +-----------------------------------------------------------------------*/ +int DOT11_Process_Set_Key(struct net_device *dev, struct iw_point *data, + DOT11_SET_KEY *pSetKey, unsigned char *pKey) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct wifi_mib *pmib = priv->pmib; + struct Dot11EncryptKey *pEncryptKey = NULL; + struct stat_info *pstat = NULL; + DOT11_SET_KEY Set_Key; + unsigned char key_combo[32]; + unsigned char MULTICAST_ADD[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int retVal; + + if (data) { +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + memcpy((void *)&Set_Key, (void *)data->pointer, sizeof(DOT11_SET_KEY)); + memcpy((void *)key_combo, + ((DOT11_SET_KEY *)data->pointer)->KeyMaterial, 32); +#else + if (copy_from_user((void *)&Set_Key, (void *)data->pointer, sizeof(DOT11_SET_KEY))) { + DEBUG_ERR("copy_from_user error!\n"); + return -1; + } + if (copy_from_user((void *)key_combo, + ((DOT11_SET_KEY *)data->pointer)->KeyMaterial, 32)) { + DEBUG_ERR("copy_from_user error!\n"); + return -1; + } +#endif + } + else { + Set_Key = *pSetKey; + memcpy(key_combo, pKey, 32); + } + +#ifdef WDS +#ifdef LAZY_WDS + if ((priv->pmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE || + (priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum)) && +#else + if (priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum && +#endif + ((priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_) || + (priv->pmib->dot11WdsInfo.wdsPrivacy == _CCMP_PRIVACY_)) && + (Set_Key.KeyType == DOT11_KeyType_Group) && + !memcmp(Set_Key.MACAddr, NULL_MAC_ADDR, 6)) { + int i; + + for (i=0; i<32; i++) + sprintf((char *)&priv->pmib->dot11WdsInfo.wdsPskPassPhrase[i*2], "%02x", key_combo[i]); + priv->pmib->dot11WdsInfo.wdsPskPassPhrase[i*2] = '\0'; + + for (i=0; ipmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE) { + if (!memcmp(priv->pmib->dot11WdsInfo.entry[i].macAddr, + NULL_MAC_ADDR, 6)) + continue; + } + else +#endif + { + if (i+1 > pmib->dot11WdsInfo.wdsNum) + break; + } + memcpy(Set_Key.MACAddr, priv->pmib->dot11WdsInfo.entry[i].macAddr, 6); + Set_Key.KeyType = DOT11_KeyType_Pairwise; + Set_Key.EncType = priv->pmib->dot11WdsInfo.wdsPrivacy; + Set_Key.KeyIndex = 0; + DOT11_Process_Set_Key(priv->dev, NULL, &Set_Key, key_combo); + } + return 0; + } +#endif + + if(Set_Key.KeyType == DOT11_KeyType_Group) + { + int set_gkey_to_cam = 0; +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + set_gkey_to_cam = 1; +#endif + +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) + set_gkey_to_cam = 0; + else { + if (IS_ROOT_INTERFACE(priv)) { + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + set_gkey_to_cam = 0; + } + } +#endif + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + // No matter root or vap, don't set key to cam if vap is enabled. + set_gkey_to_cam = 0; + } +#endif + + pmib->dot11GroupKeysTable.dot11Privacy = Set_Key.EncType; + pEncryptKey = &pmib->dot11GroupKeysTable.dot11EncryptKey; + pmib->dot11GroupKeysTable.keyid = (UINT)Set_Key.KeyIndex; + + + switch(Set_Key.EncType) + { + case DOT11_ENC_TKIP: + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 8); + set_tkip_key(pEncryptKey, key_combo); + + DEBUG_INFO("going to set TKIP group key! id %X\n", (UINT)Set_Key.KeyIndex); + if (!SWCRYPTO) { + if (set_gkey_to_cam) + { + retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, DOT11_ENC_TKIP<<2, 0, key_combo); + if (retVal) { + priv->pshare->CamEntryOccupied++; + pmib->dot11GroupKeysTable.keyInCam = TRUE; + } + } + } + break; + + case DOT11_ENC_WEP40: + set_ttkeylen(pEncryptKey, 5); + set_tmickeylen(pEncryptKey, 0); + set_wep40_key(pEncryptKey, key_combo); + + DEBUG_INFO("going to set WEP40 group key!\n"); + if (!SWCRYPTO) { + if (set_gkey_to_cam) + { + retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, DOT11_ENC_WEP40<<2, 0, key_combo); + if (retVal) { + priv->pshare->CamEntryOccupied++; + pmib->dot11GroupKeysTable.keyInCam = TRUE; + } + } + } + break; + + case DOT11_ENC_WEP104: + set_ttkeylen(pEncryptKey, 13); + set_tmickeylen(pEncryptKey, 0); + set_wep104_key(pEncryptKey, key_combo); + + DEBUG_INFO("going to set WEP104 group key!\n"); + if (!SWCRYPTO) { + if (set_gkey_to_cam) + { + retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, DOT11_ENC_WEP104<<2, 0, key_combo); + if (retVal) { + priv->pshare->CamEntryOccupied++; + pmib->dot11GroupKeysTable.keyInCam = TRUE; + } + } + } + break; + + case DOT11_ENC_CCMP: + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 16); + set_aes_key(pEncryptKey, key_combo); + + DEBUG_INFO("going to set CCMP-AES group key!\n"); + + if (!SWCRYPTO) { + if (set_gkey_to_cam) + { + retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, DOT11_ENC_CCMP<<2, 0, key_combo); + if (retVal) { + priv->pshare->CamEntryOccupied++; + pmib->dot11GroupKeysTable.keyInCam = TRUE; + } + } + } + break; + + case DOT11_ENC_NONE: + default: + DEBUG_ERR("No group encryption key is set!\n"); + set_ttkeylen(pEncryptKey, 0); + set_tmickeylen(pEncryptKey, 0); + break; + } + } +#ifdef CONFIG_IEEE80211W + else if(Set_Key.KeyType == DOT11_KeyType_IGTK) + { + int set_gkey_to_cam = 0; + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + set_gkey_to_cam = 1; +#endif //CONFIG_RTL_88E_SUPPORT + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + // No matter root or vap, don't set key to cam if vap is enabled. + set_gkey_to_cam = 0; + } +#endif + + pmib->dot11IGTKTable.dot11Privacy = Set_Key.EncType; + pEncryptKey = &pmib->dot11IGTKTable.dot11EncryptKey; + pmib->dot11IGTKTable.keyid = (UINT)Set_Key.KeyIndex; + + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 16); + set_aes_key(pEncryptKey, key_combo); + + } +#endif // CONFIG_IEEE80211W + else if(Set_Key.KeyType == DOT11_KeyType_Pairwise) + { +#ifdef WDS + // always to store WDS key for tx-hangup re-init +#if 0 + // if driver is not opened, save the WDS key into mib. The key value will + // be updated into CAM when driver opened. david + if ( !IS_DRV_OPEN(priv)) { // not open or not in open + // if interface is not open and STA is a WDS entry, save the key + // to mib and restore it to STA table when driver is open, david + struct net_device *pNet = getWdsDevByAddr(priv, Set_Key.MACAddr); + if (pNet) { + int widx = getWdsIdxByDev(priv, pNet); + if (widx >= 0) { + if (Set_Key.EncType == _WEP_40_PRIVACY_ || + Set_Key.EncType == _WEP_104_PRIVACY_) + memcpy(pmib->dot11WdsInfo.wdsWepKey, key_combo, 32); + else { + memcpy(pmib->dot11WdsInfo.wdsMapingKey[widx], key_combo, 32); + pmib->dot11WdsInfo.wdsMappingKeyLen[widx] = 32; + } + + pmib->dot11WdsInfo.wdsKeyId = Set_Key.KeyIndex; + pmib->dot11WdsInfo.wdsPrivacy = Set_Key.EncType; + + return 0; + } + } + return -1; + } +#endif + int widx = -1; + struct net_device *pNet = getWdsDevByAddr(priv, Set_Key.MACAddr); + if (pNet) { + widx = getWdsIdxByDev(priv, pNet); + if (widx >= 0) { + if (Set_Key.EncType == _WEP_40_PRIVACY_ || + Set_Key.EncType == _WEP_104_PRIVACY_) + memcpy(pmib->dot11WdsInfo.wdsWepKey, key_combo, 32); + else { + memcpy(pmib->dot11WdsInfo.wdsMapingKey[widx], key_combo, 32); + pmib->dot11WdsInfo.wdsMappingKeyLen[widx] = 32; + } + pmib->dot11WdsInfo.wdsKeyId = Set_Key.KeyIndex; + pmib->dot11WdsInfo.wdsPrivacy = Set_Key.EncType; + } + } + if ( !IS_DRV_OPEN(priv)) { + if (widx > 0 && pmib->dot11WdsInfo.wdsMappingKeyLen[widx] > 0) + pmib->dot11WdsInfo.wdsMappingKeyLen[widx] |= 0x80000000; + return 0; + } + //----------------------------------- david+2006-06-30 +#endif // WDS + +#ifdef MULTI_MAC_CLONE + if ((OPMODE & WIFI_STATION_STATE) && priv->pmib->ethBrExtInfo.macclone_enable) { + ACTIVE_ID = mclone_find_address(priv, Set_Key.MACAddr, NULL, MAC_CLONE_NOCARE_FIND); + if (ACTIVE_ID < 0) { + DEBUG_ERR("Invalid mac address!\n"); + return 0; + } + pstat = get_stainfo(priv, priv->pmib->dot11Bss.bssid); + } + else +#endif + pstat = get_stainfo(priv, Set_Key.MACAddr); + if (pstat == NULL) { + DEBUG_ERR("Set key failed, invalid mac address: %02x%02x%02x%02x%02x%02x\n", + Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], Set_Key.MACAddr[3], + Set_Key.MACAddr[4], Set_Key.MACAddr[5]); + return (-1); + } + + pstat->dot11KeyMapping.dot11Privacy = Set_Key.EncType; + pEncryptKey = &pstat->dot11KeyMapping.dot11EncryptKey; + pstat->keyid = Set_Key.KeyIndex; + +#if defined(__DRAYTEK_OS__) && defined(WDS) + if (pstat->state & WIFI_WDS) + priv->pmib->dot11WdsInfo.wdsPrivacy = Set_Key.EncType; +#endif + + switch(Set_Key.EncType) + { + case DOT11_ENC_TKIP: + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 8); + set_tkip_key(pEncryptKey, key_combo); + + DEBUG_INFO("going to set TKIP Unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", + Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], + Set_Key.MACAddr[3], Set_Key.MACAddr[4], Set_Key.MACAddr[5], pstat->keyid); + if (!SWCRYPTO) { + retVal = CamDeleteOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, DOT11_ENC_TKIP<<2, 0, key_combo); + if (retVal) { + priv->pshare->CamEntryOccupied++; + if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; + } + else { + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + break; + + case DOT11_ENC_WEP40: + set_ttkeylen(pEncryptKey, 5); + set_tmickeylen(pEncryptKey, 0); + set_wep40_key(pEncryptKey, key_combo); + + DEBUG_INFO("going to set WEP40 unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", + Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], + Set_Key.MACAddr[3], Set_Key.MACAddr[4], Set_Key.MACAddr[5], pstat->keyid); + if (!SWCRYPTO) { + retVal = CamDeleteOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, DOT11_ENC_WEP40<<2, 0, key_combo); + if (retVal) { + priv->pshare->CamEntryOccupied++; + if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; + } + else { + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + break; + + case DOT11_ENC_WEP104: + set_ttkeylen(pEncryptKey, 13); + set_tmickeylen(pEncryptKey, 0); + set_wep104_key(pEncryptKey, key_combo); + + DEBUG_INFO("going to set WEP104 unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", + Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], + Set_Key.MACAddr[3], Set_Key.MACAddr[4], Set_Key.MACAddr[5], pstat->keyid); + if (!SWCRYPTO) { + retVal = CamDeleteOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, DOT11_ENC_WEP104<<2, 0, key_combo); + if (retVal) { + priv->pshare->CamEntryOccupied++; + if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; + } + else { + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + break; + + case DOT11_ENC_CCMP: + set_ttkeylen(pEncryptKey, 16); + set_tmickeylen(pEncryptKey, 16); + set_aes_key(pEncryptKey, key_combo); + + DEBUG_INFO("going to set CCMP-AES unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", + Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], + Set_Key.MACAddr[3], Set_Key.MACAddr[4], Set_Key.MACAddr[5], pstat->keyid); + if (!SWCRYPTO) { + retVal = CamDeleteOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; + } + retVal = CamAddOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, DOT11_ENC_CCMP<<2, 0, key_combo); + if (retVal) { + priv->pshare->CamEntryOccupied++; + if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; + assign_aggre_mthod(priv, pstat); + } + else { + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + break; + + case DOT11_ENC_NONE: + default: + DEBUG_ERR("No pairewise encryption key is set!\n"); + set_ttkeylen(pEncryptKey, 0); + set_tmickeylen(pEncryptKey, 0); + break; + } + } + + return 0; +} + + +/*--------------------------------------------------------------------- + Set Port Enable of Disable for STA + Return Value +Success : 0 +-----------------------------------------------------------------------*/ +static int DOT11_Process_Set_Port(struct net_device *dev, struct iw_point *data) +{ + struct stat_info *pstat; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct wifi_mib *pmib = priv->pmib; + DOT11_SET_PORT *Set_Port = (DOT11_SET_PORT *)data->pointer; + + DEBUG_INFO("Set_Port sta %02X%02X%02X%02X%02X%02X Status %X\n", + Set_Port->MACAddr[0],Set_Port->MACAddr[1],Set_Port->MACAddr[2], + Set_Port->MACAddr[3],Set_Port->MACAddr[4],Set_Port->MACAddr[5], + Set_Port->PortStatus); + + // if driver is not opened, return immediately, david + if (!netif_running(priv->dev)) + return (-1); + + pstat = get_stainfo(priv, Set_Port->MACAddr); + + if ((pstat == NULL) || (!(pstat->state & WIFI_ASOC_STATE))) + return (-1); + + if (Set_Port->PortStatus) + { + pstat->ieee8021x_ctrlport = Set_Port->PortStatus; +#ifdef INDICATE_LINK_CHANGE + indicate_sta_link_change(priv, pstat, INCREASE, __FUNCTION__); +#endif + } + else + pstat->ieee8021x_ctrlport = pmib->dot118021xAuthEntry.dot118021xDefaultPort; + +#ifdef P2P_SUPPORT + if((OPMODE&WIFI_P2P_SUPPORT)&&( P2PMODE ==P2P_CLIENT)){ + + /*to indicate web server that data path is connected done(can start issue udhcpc daemon)*/ + P2P_STATE = P2P_S_CLIENT_CONNECTED_DHCPC; + priv->p2pPtr->clientmode_try_connect = 0; + P2P_DEBUG("Set_Port Sta[%02X%02X%02X%02X%02X%02X],Status=%X\n\n\n", + Set_Port->MACAddr[0],Set_Port->MACAddr[1],Set_Port->MACAddr[2], + Set_Port->MACAddr[3],Set_Port->MACAddr[4],Set_Port->MACAddr[5], + Set_Port->PortStatus); + } +#endif + return 0; +} + + +static int DOT11_Process_QueryRSC(struct net_device *dev, struct iw_point *data) +{ + DOT11_GKEY_TSC *pGkey_TSC = (DOT11_GKEY_TSC *)data->pointer; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct wifi_mib *pmib = priv->pmib; + + pGkey_TSC->EventId = DOT11_EVENT_GKEY_TSC; + pGkey_TSC->IsMoreEvent = FALSE; + + // Fix bug of getting RSC for auth (should consider endian issue) + //memcpy((void *)pGkey_TSC->KeyTSC, + // (void *)&(pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48.val48), 6); + pGkey_TSC->KeyTSC[0] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC0; + pGkey_TSC->KeyTSC[1] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC1; + pGkey_TSC->KeyTSC[2] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC2; + pGkey_TSC->KeyTSC[3] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC3; + pGkey_TSC->KeyTSC[4] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC4; + pGkey_TSC->KeyTSC[5] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC5; + pGkey_TSC->KeyTSC[6] = 0x00; + pGkey_TSC->KeyTSC[7] = 0x00; + + return 0; +} + + +static int DOT11_Porcess_EAPOL_MICReport(struct net_device *dev, struct iw_point *data) +{ +#ifdef _DEBUG_RTL8192CD_ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); +#endif + struct stat_info *pstat = NULL; +#ifdef _SINUX_ + DOT11_MIC_FAILURE *MIC_Failure = (DOT11_MIC_FAILURE *)data->pointer; + + printk("MIC fail report from 802.1x daemon\n"); + printk("mac: %02x%02x%02x%02x%02x%02x\n", MIC_Failure->MACAddr[0], MIC_Failure->MACAddr[1], + MIC_Failure->MACAddr[2], MIC_Failure->MACAddr[3], MIC_Failure->MACAddr[4], MIC_Failure->MACAddr[5]); + mic_error_report(1); +#else + //DOT11_MIC_FAILURE *MIC_Failure = (DOT11_MIC_FAILURE *)data->pointer; + + DEBUG_INFO("MIC fail report from 802.1x daemon\n"); + //DEBUG_INFO("mac: %02x%02x%02x%02x%02x%02x\n", MIC_Failure->MACAddr[0], MIC_Failure->MACAddr[1], + //MIC_Failure->MACAddr[2], MIC_Failure->MACAddr[3], MIC_Failure->MACAddr[4], MIC_Failure->MACAddr[5]); +#endif +#ifdef RTL_WPA2 + PRINT_INFO("%s: DOT11_Indicate_MIC_Failure \n", (char *)__FUNCTION__); +#endif + + DOT11_Indicate_MIC_Failure(dev, pstat); + + return 0; +} + +#ifdef CONFIG_PCI_HCI +static inline +#endif +int __DOT11_Indicate_MIC_Failure(struct net_device *dev, struct stat_info *pstat) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct stat_info *pstat_del; + DOT11_MIC_FAILURE Mic_Failure; + DOT11_DISASSOCIATION_IND Disassociation_Ind; + int i; + + if (priv->pshare->skip_mic_chk || ((priv->ext_stats.tx_avarage + priv->ext_stats.rx_avarage) > (1024*1024/8))) + return 0; + + // Indicate to upper layer + if (pstat != NULL) // if pstat==NULL, it is called by upper layer + { + DEBUG_INFO("MIC error indicate to 1x in driver\n"); + //DEBUG_INFO("mac: %02x%02x%02x%02x%02x%02x\n", pstat->hwaddr[0], pstat->hwaddr[1], + //pstat->hwaddr[2], pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); + +#ifdef __DRAYTEK_OS__ + cb_tkip_micFailure(dev, pstat->hwaddr); + return 0; +#endif + +#if !defined(WITHOUT_ENQUEUE) && (!defined(RTK_NL80211) || defined(NON_NL80211_AP)) + Mic_Failure.EventId = DOT11_EVENT_MIC_FAILURE; + Mic_Failure.IsMoreEvent = 0; + memcpy(&Mic_Failure.MACAddr, pstat->hwaddr, MACADDRLEN); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Mic_Failure, sizeof(DOT11_MIC_FAILURE)); +#endif +#ifdef INCLUDE_WPA_PSK + psk_indicate_evt(priv, DOT11_EVENT_MIC_FAILURE, pstat->hwaddr, NULL, 0); +#endif + +#ifdef WIFI_HAPD + event_indicate_hapd(priv, pstat->hwaddr, HAPD_MIC_FAILURE, NULL); +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, pstat->hwaddr, 5); +#endif +#else + event_indicate(priv, pstat->hwaddr, 5); +#endif +#if 0//def WIFI_WPAS //_Eric ?? + event_indicate_wpas(priv, pstat->hwaddr, WPAS_MIC_FAILURE, NULL); +#endif + } + + if (priv->MIC_timer_on) + { + // Second time to detect MIC error in a time period + + // Stop Timer (fill a timer before than now) + if (timer_pending(&priv->MIC_check_timer)) + del_timer_sync(&priv->MIC_check_timer); + priv->MIC_timer_on = FALSE; + + // Start Timer to reject assocaiton request from STA, and reject all the packet + mod_timer(&priv->assoc_reject_timer, jiffies + REJECT_ASSOC_PERIOD); + priv->assoc_reject_on = TRUE; + for(i=0; ipshare->aidarray[i] && (priv->pshare->aidarray[i]->used == TRUE) +#ifdef WDS + && !(priv->pshare->aidarray[i]->station.state & WIFI_WDS) +#endif + ) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (priv != priv->pshare->aidarray[i]->priv) + continue; +#endif + + pstat_del = &(priv->pshare->aidarray[i]->station); + if (!list_empty(&pstat_del->asoc_list)) + { +#ifdef _SINUX_ + printk("Second time to detect MIC error in a time period so disassociate the all client\n"); + mic_error_report(2); +#endif +#ifndef WITHOUT_ENQUEUE + memcpy((void *)Disassociation_Ind.MACAddr, (void *)pstat_del->hwaddr, MACADDRLEN); + Disassociation_Ind.EventId = DOT11_EVENT_DISASSOCIATION_IND; + Disassociation_Ind.IsMoreEvent = 0; + Disassociation_Ind.Reason = _STATS_OTHER_; + Disassociation_Ind.tx_packets = pstat_del->tx_pkts; + Disassociation_Ind.rx_packets = pstat_del->rx_pkts; + Disassociation_Ind.tx_bytes = pstat_del->tx_bytes; + Disassociation_Ind.rx_bytes = pstat_del->rx_bytes; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Disassociation_Ind, + sizeof(DOT11_DISASSOCIATION_IND)); +#endif +#if defined(INCLUDE_WPA_PSK) + psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, pstat_del->hwaddr, NULL, 0); +#elif defined(WIFI_HAPD) || defined(RTK_NL80211) + nl80211_psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, pstat_del->hwaddr, NULL, 0); +#endif + +#if defined(RTK_NL80211) && !defined(NON_NL80211_AP) + event_indicate_cfg80211(priv, pstat_del->hwaddr, CFG80211_DEL_STA, NULL); +#elif defined(WIFI_HAPD) + event_indicate_hapd(priv, pstat_del->hwaddr, HAPD_EXIRED, NULL); +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, pstat_del->hwaddr, 2); +#endif +#else + event_indicate(priv, pstat_del->hwaddr, 2); +#endif + + issue_disassoc(priv, pstat_del->hwaddr, _RSON_MIC_FAILURE_); + } + free_stainfo(priv, pstat_del); + } + } + priv->assoc_num = 0; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + priv->pmib->dot11ErpInfo.nonErpStaNum = 0; + check_protection_shortslot(priv); + priv->pmib->dot11ErpInfo.longPreambleStaNum = 0; + } + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + priv->ht_legacy_sta_num = 0; + + // ToDo: Should we delete group key? +#ifdef _SINUX_ + printk("-------------------------------------------------------\n"); + printk("Second time of MIC failure in a time period \n"); + printk("-------------------------------------------------------\n"); +#else + DEBUG_INFO("-------------------------------------------------------\n"); + DEBUG_INFO("Second time of MIC failure in a time period \n"); + DEBUG_INFO("-------------------------------------------------------\n"); +#endif + } + else + { + // First time to detect MIC error, start the timer + mod_timer(&priv->MIC_check_timer, jiffies + MIC_TIMER_PERIOD); + priv->MIC_timer_on = TRUE; + + DEBUG_INFO("-------------------------------------------------------\n"); + DEBUG_INFO("First time of MIC failure in a time period, start timer\n"); + DEBUG_INFO("-------------------------------------------------------\n"); + } + + return 0; +} + +int DOT11_Indicate_MIC_Failure(struct net_device *dev, struct stat_info *pstat) +{ +#if defined(CONFIG_PCI_HCI) + return __DOT11_Indicate_MIC_Failure(dev, pstat); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_indicate_MIC_failure(dev, pstat); + return 0; +#endif +} + +void DOT11_Process_MIC_Timerup(unsigned long data) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)data; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + DEBUG_INFO("MIC Timer is up. Cancel Timer\n"); + priv->MIC_timer_on = FALSE; +} + +void DOT11_Process_Reject_Assoc_Timerup(unsigned long data) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)data; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + DEBUG_INFO("Reject Association Request Timer is up. Cancel Timer\n"); + memset(priv->assoc_reject_mac,0,MACADDRLEN); +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) + start_clnt_lookup(priv, 0); +#endif + priv->assoc_reject_on = FALSE; +} + +#ifdef CONFIG_PCI_HCI +static inline +#endif +void __DOT11_Indicate_MIC_Failure_Clnt(struct rtl8192cd_priv *priv, unsigned char *sa) +{ + DOT11_MIC_FAILURE Mic_Failure; + struct stat_info *pstat_del; + DOT11_DISASSOCIATION_IND Disassociation_Ind; +// int i; +#ifndef WITHOUT_ENQUEUE + Mic_Failure.EventId = DOT11_EVENT_MIC_FAILURE; + Mic_Failure.IsMoreEvent = 0; + memcpy(&Mic_Failure.MACAddr, sa, MACADDRLEN); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Mic_Failure, sizeof(DOT11_MIC_FAILURE)); +#endif +#if defined(INCLUDE_WPA_PSK) && !defined(NON_NL80211_AP) && !defined(WIFI_WPAS_CLI) + if (OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + psk_indicate_evt(priv, DOT11_EVENT_MIC_FAILURE, BSSID, NULL, 0); +#endif + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + event_indicate_cfg80211(priv, sa, CFG80211_MIC_FAILURE, NULL); +#elif defined(WIFI_WPAS) + event_indicate_wpas(priv, sa, WPAS_MIC_FAILURE, NULL); +#else + event_indicate(priv, sa, 5); +#endif + if (priv->MIC_timer_on) { + // Second time to detect MIC error in a time period + + // Stop Timer (fill a timer before than now) + if (timer_pending(&priv->MIC_check_timer)) + del_timer_sync(&priv->MIC_check_timer); + priv->MIC_timer_on = FALSE; + + // Start Timer to reject assocaiton request from STA, and reject all the packet + mod_timer(&priv->assoc_reject_timer, jiffies + REJECT_ASSOC_PERIOD); + priv->assoc_reject_on = TRUE; + memcpy(priv->assoc_reject_mac, BSSID, MACADDRLEN); + + pstat_del = get_stainfo(priv, BSSID); + memcpy((void *)Disassociation_Ind.MACAddr, (void *)pstat_del->hwaddr, MACADDRLEN); + DEBUG_INFO("%s() disassoc %02X:%02X:%02X:%02X:%02X:%02X\n",__func__,pstat_del->hwaddr[0],pstat_del->hwaddr[1],pstat_del->hwaddr[2],pstat_del->hwaddr[3],pstat_del->hwaddr[4],pstat_del->hwaddr[5]); + + Disassociation_Ind.EventId = DOT11_EVENT_DISASSOCIATION_IND; + Disassociation_Ind.IsMoreEvent = 0; + Disassociation_Ind.Reason = _STATS_OTHER_; + Disassociation_Ind.tx_packets = pstat_del->tx_pkts; + Disassociation_Ind.rx_packets = pstat_del->rx_pkts; + Disassociation_Ind.tx_bytes = pstat_del->tx_bytes; + Disassociation_Ind.rx_bytes = pstat_del->rx_bytes; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Disassociation_Ind, + sizeof(DOT11_DISASSOCIATION_IND)); + + /* + * To make sure the MIC Failure Report is sent before disassoc + */ + delay_ms(20); + issue_disassoc(priv, pstat_del->hwaddr, _RSON_MIC_FAILURE_); + free_stainfo(priv, pstat_del); + + priv->assoc_num = 0; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + priv->pmib->dot11ErpInfo.nonErpStaNum = 0; + check_protection_shortslot(priv); + priv->pmib->dot11ErpInfo.longPreambleStaNum = 0; + } + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + priv->ht_legacy_sta_num = 0; + + DEBUG_INFO("-------------------------------------------------------\n"); + DEBUG_INFO("Second time of MIC failure in a time period \n"); + DEBUG_INFO("-------------------------------------------------------\n"); + } else { + // First time to detect MIC error, start the timer + mod_timer(&priv->MIC_check_timer, jiffies + MIC_TIMER_PERIOD); + priv->MIC_timer_on = TRUE; + + DEBUG_INFO("-------------------------------------------------------\n"); + DEBUG_INFO("First time of MIC failure in a time period, start timer\n"); + DEBUG_INFO("-------------------------------------------------------\n"); + } +} + +void DOT11_Indicate_MIC_Failure_Clnt(struct rtl8192cd_priv *priv, unsigned char *sa) +{ +#if defined(WIFI_WPAS_CLI) + event_indicate_wpas(priv, sa, WPAS_MIC_FAILURE, NULL); +#elif defined(CONFIG_PCI_HCI) + __DOT11_Indicate_MIC_Failure_Clnt(priv, sa); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_indicate_MIC_failure_clnt(priv, sa); +#endif +} + +#ifdef RADIUS_ACCOUNTING +void DOT11_Process_Acc_SetExpiredTime(struct net_device *dev, struct iw_point *data) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + //WLAN_CTX *wCtx = (WLAN_CTX *) ( priv->pwlanCtx ); + DOT11_SET_EXPIREDTIME *Set_ExpireTime = (DOT11_SET_EXPIREDTIME *)data->pointer; + struct stat_info *pstat=NULL; + + if( Set_ExpireTime != NULL ){ + Set_ExpireTime->EventId = DOT11_EVENT_ACC_SET_EXPIREDTIME; + Set_ExpireTime->IsMoreEvent = 0; + + if( (pstat = get_stainfo(priv, Set_ExpireTime->MACAddr)) ){ + pstat->def_expired_time = Set_ExpireTime->ExpireTime; + DEBUG_INFO("%s: Set %02x:%02x:%02x:%02x:%02x:%02x def_expired_time = %ld!\n", (char *)__FUNCTION__, + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5], + Set_ExpireTime->ExpireTime); + } + else{ + DEBUG_ERR("%s: ERRO, CAN NOT GET STA INFO!\n", (char *)__FUNCTION__); + } + } + else{ + DEBUG_ERR("%s: NULL POINTER!\n", (char *)__FUNCTION__); + } +} + + +void DOT11_Process_Acc_QueryStats(struct net_device *dev, struct iw_point *data) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + //WLAN_CTX *wCtx = (WLAN_CTX *) ( priv->pwlanCtx ); + struct stat_info *pstat=NULL; + DOT11_QUERY_STATS *pStats = (DOT11_QUERY_STATS *)data->pointer; + + if( pStats != NULL ){ + pStats->EventId = DOT11_EVENT_ACC_QUERY_STATS; + pStats->IsMoreEvent = 0; + + if( (pstat = get_stainfo(priv, pStats->MACAddr)) ){ + pStats->tx_packets = pstat->tx_pkts; + pStats->rx_packets = pstat->rx_pkts; + pStats->tx_bytes = pstat->tx_bytes; + pStats->rx_bytes = pstat->rx_bytes; + + pStats->IsSuccess = TRUE; + DEBUG_INFO("%s: Get %02x:%02x:%02x:%02x:%02x:%02x stats!\n", (char *)__FUNCTION__, + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + } + else{ + pStats->IsSuccess = FALSE; + DEBUG_ERR("%s: ERROR, CAN NOT GET STA INFO!\n", (char *)__FUNCTION__); + } + } + else{ + DEBUG_ERR("%s: NULL POINTER!\n", (char *)__FUNCTION__); + } +} + + +//------------------------- +//DOT11_QUERY_STATS stats[RTL_AP_MAX_STA_NUM+1]; +//data->pointer = (unsigned char *)stats; +void DOT11_Process_Acc_QueryStats_All(struct net_device *dev, struct iw_point *data) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + struct list_head *phead=NULL, *plist=NULL; + struct stat_info *pstat=NULL; + //WLAN_CTX *wCtx = (WLAN_CTX *) ( priv->pwlanCtx ); + DOT11_QUERY_STATS *pStats = (DOT11_QUERY_STATS *)data->pointer; + //int i; + int cnt = 0; +#ifdef SMP_SYNC + unsigned long flags=0; +#endif + + if( pStats != NULL ){ + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + pStats[cnt].EventId = DOT11_EVENT_ACC_QUERY_STATS_ALL; + pStats[cnt].IsMoreEvent = 0; + memcpy( pStats[cnt].MACAddr, pstat->hwaddr, MACADDRLEN ); + pStats[cnt].tx_packets = pstat->tx_pkts; + pStats[cnt].rx_packets = pstat->rx_pkts; + pStats[cnt].tx_bytes = pstat->tx_bytes; + pStats[cnt].rx_bytes = pstat->rx_bytes; + + cnt++; + } + SMP_UNLOCK_ASOC_LIST(flags); + } + else{ + printk("%s: NULL POINTER!\n", (char *)__FUNCTION__); + } +} +#endif + + +static int DOT11_Process_STA_Query_Bssid(struct net_device *dev, struct iw_point *data) +{ + DOT11_STA_QUERY_BSSID *pQuery = (DOT11_STA_QUERY_BSSID *)data->pointer; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + pQuery->EventId = DOT11_EVENT_STA_QUERY_BSSID; + pQuery->IsMoreEvent = FALSE; + if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == + (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + { + pQuery->IsValid = TRUE; + memcpy(pQuery->Bssid, BSSID, 6); + } + else + pQuery->IsValid = FALSE; + + return 0; +} + + +static int DOT11_Process_STA_Query_Ssid(struct net_device *dev, struct iw_point *data) +{ + DOT11_STA_QUERY_SSID *pQuery = (DOT11_STA_QUERY_SSID *)data->pointer; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + pQuery->EventId = DOT11_EVENT_STA_QUERY_SSID; + pQuery->IsMoreEvent = FALSE; + if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == + (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + { + pQuery->IsValid = TRUE; + memcpy(pQuery->ssid, SSID, 32); + pQuery->ssid_len = SSID_LEN; + } + else + pQuery->IsValid = FALSE; + + return 0; +} + + +#ifdef WIFI_SIMPLE_CONFIG +static int DOT11_WSC_set_ie(struct net_device *dev, struct iw_point *data) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + DOT11_SET_RSNIE *Set_RSNIE = (DOT11_SET_RSNIE *)data->pointer; + + if (Set_RSNIE->Flag == SET_IE_FLAG_BEACON) { + DEBUG_INFO("WSC: set beacon IE\n"); + priv->pmib->wscEntry.beacon_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->wscEntry.beacon_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); +#ifdef SDIO_AP_OFFLOAD + { +#define TAG_SELECTED_REGISTRAR 0x1041 + + int attr_len; + if (search_wsc_tag(Set_RSNIE->RSNIE+6, TAG_SELECTED_REGISTRAR, + Set_RSNIE->RSNIELen-6, &attr_len)) // found + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_WPS); + else + ap_offload_activate(priv, OFFLOAD_PROHIBIT_WPS); + } +#endif // SDIO_AP_OFFLOAD + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_PROBE_RSP) { + DEBUG_INFO("WSC: set probe response IE\n"); + priv->pmib->wscEntry.probe_rsp_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->wscEntry.probe_rsp_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_PROBE_REQ) { + DEBUG_INFO("WSC: set probe request IE\n"); + priv->pmib->wscEntry.probe_req_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->wscEntry.probe_req_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_ASSOC_REQ || + Set_RSNIE->Flag == SET_IE_FLAG_ASSOC_RSP) { + DEBUG_INFO("WSC: set assoc IE\n"); + priv->pmib->wscEntry.assoc_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->wscEntry.assoc_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + } +#if 0 + else if (Set_RSNIE->Flag == 3) { + printk("WSC: set RSN IE\n"); + priv->pmib->dot11RsnIE.rsnielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->dot11RsnIE.rsnie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + } +#endif + else { + DEBUG_ERR("Invalid flag of set IE [%d]!\n", Set_RSNIE->Flag); + } + +#ifdef PCIE_POWER_SAVING + if ((Set_RSNIE->Flag == SET_IE_FLAG_BEACON) || (Set_RSNIE->Flag == SET_IE_FLAG_PROBE_RSP)) + PCIeWakeUp(priv, (POWER_DOWN_T0)); +#endif + + return 0; +} + +#ifdef INCLUDE_WPS +#ifndef CONFIG_MSC +static int dispatch_wscsoap(struct rtl8192cd_priv *priv ,pDOT11_WSC_SOAP soap) +{ + struct WSC_packet *packet=NULL; + + printk("\nWlan Driver receive SOAP request:%s\n",soap->action); + + packet = &soap->packet; + + if( strcmp(soap->action,"WFAGetDeviceInfo") ){ + packet->EventType = WSC_NOT_PROXY; + packet->EventID = WSC_GETDEVINFO; + } else if ( strcmp(soap->action,"SendMsgToSM_Dir_In") ){ + packet->EventID = WSC_SETSELECTEDREGISTRA; + } else if ( strcmp(soap->action,"SendMsgToSM_Dir_InOut") ){ + packet->EventID = WSC_M2M4M6M8; + } else if ( strcmp(soap->action,"WFAPutWLANResponse") ) { + packet->EventID = WSC_PUTWLANRESPONSE; + } +#ifdef SUPPORT_UPNP + if (PWSCUpnpCallbackEventHandler(packet) != WSC_UPNP_SUCCESS) { + DEBUG_ERR("WSCCallBack Fail!\n"); + goto error_handle; + } +#endif + return 0; + +error_handle: + return -1; +} +#endif +#endif + +#endif // WIFI_SIMPLE_CONFIG + +#ifdef USER_ADDIE +static int DOT11_USER_set_ie(struct net_device *dev, struct iw_point *data) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + DOT11_SET_USERIE *Set_USERIE = (DOT11_SET_USERIE *)data->pointer; + unsigned int i; + + if (Set_USERIE->Flag == SET_IE_FLAG_INSERT) { + DEBUG_INFO("USER: add beacon IE\n"); + for (i=0; iuser_ie_list[i].used) + break; + } + if (i == MAX_USER_IE) + return -1; + priv->user_ie_list[i].used = 1; + priv->user_ie_list[i].ie_len = Set_USERIE->USERIELen; + memcpy((void *)priv->user_ie_list[i].ie, Set_USERIE->USERIE, Set_USERIE->USERIELen); + } + else if (Set_USERIE->Flag == SET_IE_FLAG_DELETE) { + DEBUG_INFO("USER: remove beacon IE\n"); + for (i=0; iuser_ie_list[i].used && + !memcmp(priv->user_ie_list[i].ie, Set_USERIE->USERIE, Set_USERIE->USERIELen)) { + priv->user_ie_list[i].used = 0; + break; + } + } + if (i == MAX_USER_IE) + return -1; + } + else { + DEBUG_ERR("Invalid flag of set IE [%d]!\n", Set_USERIE->Flag); + } + + return 0; +} + +#endif + +#ifdef CONFIG_IEEE80211W +static int DOT11_PMF_set_ie(struct net_device *dev, struct iw_point *data) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + struct stat_info *pstat; + DOT11_SET_11W_Flags flags; + if (!memcpy((void *)(&flags),(void *)(data->pointer), data->length)) + { + PMFDEBUG("memcpy fail!, data=%x, length=%d\n", data->pointer, data->length); + return -1; + } + + pstat= get_stainfo(priv,flags.macAddr); + + if (!pstat) { + //PMFDEBUG("psta is NULL\n"); + } else { + pstat->isPMF = flags.isPMF; + PMFDEBUG("set sta[%02x%02x%02x:%02x%02x%02x]'s PMF=[%d]\n",pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5], flags.isPMF); + } + + return 0; +} +#endif + +#ifdef HS2_SUPPORT +/* Hotspot 2.0 Release 1*/ +static int DOT11_HS2_set_ie(struct net_device *dev, struct iw_point *data) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + DOT11_SET_RSNIE *Set_RSNIE = (DOT11_SET_RSNIE *)data->pointer; + HS2_DEBUG_INFO("HS2 set ie, flag=%d\n",Set_RSNIE->Flag); + if (Set_RSNIE->Flag == SET_IE_FLAG_INTERWORKING) + { + //DEBUG_INFO + HS2_DEBUG_TRACE(1, "HS2: set interworking IE,%x,%x\n",Set_RSNIE->RSNIE[0], Set_RSNIE->RSNIE[1]); + priv->pmib->hs2Entry.interworking_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->hs2Entry.interworking_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_ADVT_PROTO) + { + HS2_DEBUG_TRACE(1, "HS2: set advt proto IE\n"); + priv->pmib->hs2Entry.advt_proto_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->hs2Entry.advt_proto_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_ROAMING) + { + HS2_DEBUG_TRACE(1, "HS2: set roaming IE\n"); + priv->pmib->hs2Entry.roam_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->hs2Entry.roam_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_HS2) + { + HS2_DEBUG_TRACE(1, "HS2: set HS2 IE\n"); + priv->pmib->hs2Entry.hs2_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->hs2Entry.hs2_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + if (priv->pmib->hs2Entry.hs2_ie[4] & 0x01) + { + HS2_DEBUG_TRACE(1, "dgaf enable\n"); + priv->dgaf_disable = 1; + } + else + { + HS2_DEBUG_TRACE(1, "dgaf disable\n"); + priv->dgaf_disable = 0; + } + + //channel utilization + init_timer(&priv->cu_cntdwn_timer); + priv->cu_cntdwn_timer.data = (unsigned long) priv; + priv->cu_cntdwn_timer.function = rtl8192cd_cu_cntdwn_timer; + priv->cu_cntdwn = priv->cu_initialcnt = (priv->pmib->hs2Entry.channel_utili_beaconIntval * priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod)/CU_Intval; + start_bbp_ch_load(priv, 50000); + priv->cu_cntdwn_timer.expires = jiffies + CU_TO; + mod_timer(&priv->cu_cntdwn_timer, jiffies + CU_TO); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_TIMEADVT) + { + HS2_DEBUG_TRACE(1, "HS2: set timeadvt IE\n"); + priv->pmib->hs2Entry.timeadvt_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->hs2Entry.timeadvt_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_TIMEZONE) + { + HS2_DEBUG_TRACE(1, "HS2: set time zone IE\n"); + priv->pmib->hs2Entry.timezone_ielen = Set_RSNIE->RSNIELen; + memcpy((void *)priv->pmib->hs2Entry.timezone_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_PROXYARP) + { + priv->proxy_arp = *Set_RSNIE->RSNIE; + HS2_DEBUG_INFO("\n\n\n\nproxy arp in driver=%d\n\n\n\n\n", priv->proxy_arp); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_ICMPv4ECHO) + { + priv->pmib->hs2Entry.ICMPv4ECHO = *Set_RSNIE->RSNIE; + HS2_DEBUG_INFO("\n\n\n\nICMPv4ECHO in driver=%d\n\n\n\n\n", priv->pmib->hs2Entry.ICMPv4ECHO); + } + else if (Set_RSNIE->Flag == SET_IE_FLAG_MMPDULIMIT) { + memcpy((void *)(&priv->pmib->hs2Entry.mmpdu_limit), Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); + HS2_DEBUG_INFO("mmpdu_limit:%d\n",priv->pmib->hs2Entry.mmpdu_limit); + } + else + { + HS2_DEBUG_ERR("HS2: unknown ioctl flag\n"); + } +} +#endif + +/*----------------------------------------------------------------------------- + Most of the time, we don't have to worry about the racing condition of + "event_queue" in wlan drivers, since all the queue/dequeue are handled + in non-isr context. + However, my guess is, someone always want to port these driver to fit different + OS platform. At that time, please always keep in mind all the possilbe racing + condition... That could be big disasters... + ------------------------------------------------------------------------------*/ +#if defined(CONFIG_RTL_KERNEL_MIPS16_WLAN) && defined(CONFIG_RTL8196C) +__NOMIPS16 +#endif +int rtl8192cd_ioctl_priv_daemonreq(struct net_device *dev, struct iw_point *data) +{ + int ret; +#ifndef WITHOUT_ENQUEUE + static UINT8 QueueData[MAXDATALEN]; + int QueueDataLen; +#elif defined(CONFIG_RTL_WAPI_SUPPORT) + static UINT8 QueueData[MAXDATALEN]; + int QueueDataLen; +#endif + UINT8 val8; + DOT11_REQUEST req; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + memcpy((void *)&req, (void *)(data->pointer), sizeof(DOT11_REQUEST)); +#else + if (copy_from_user((void *)&req, (void *)(data->pointer), sizeof(DOT11_REQUEST))) { + DEBUG_ERR("copy_from_user error!\n"); + return -1; + } +#endif +#ifdef INCLUDE_WPS + DOT11_GETSET_MIB *getset_mib_t; +#endif + switch(req.EventId) + { + case DOT11_EVENT_NO_EVENT: + break; + +#ifndef WITHOUT_ENQUEUE + case DOT11_EVENT_REQUEST: + if((ret = DOT11_DeQueue((unsigned long)priv, priv->pevent_queue, QueueData, &QueueDataLen)) != 0) + { + val8 = DOT11_EVENT_NO_EVENT; + if (copy_to_user((void *)((unsigned long)(data->pointer)), &val8, 1)) { + DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + val8 = 0; + if (copy_to_user((void *)((unsigned long)(data->pointer) + 1), &val8, 1)) { + DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + data->length = sizeof(DOT11_NO_EVENT); + } + else + { + QueueData[1] = (priv->pevent_queue->NumItem != 0)? 1 : 0; + if (copy_to_user((void *)data->pointer, (void *)QueueData, QueueDataLen)) { + DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + data->length = QueueDataLen; + } + break; +#ifdef INCLUDE_WPS + case DOT11_EVENT_REQUEST_F_INCLUDE_WPS: + if((ret = DOT11_DeQueue((unsigned long)priv, priv->pevent_queue, QueueData, &QueueDataLen)) != 0) + { + val8 = DOT11_EVENT_NO_EVENT; + memcpy((void *)((unsigned long)(data->pointer)), &val8, 1); + + val8 = 0; + memcpy((void *)((unsigned long)(data->pointer) + 1), &val8, 1); + data->length = sizeof(DOT11_NO_EVENT); + } + else + { + QueueData[1] = (priv->pevent_queue->NumItem != 0)? 1 : 0; + memcpy((void *)data->pointer, (void *)QueueData, QueueDataLen); + data->length = QueueDataLen; + //DEBUG_INFO("%d de-queue ; pMsg=%s\n", __LINE__ , (char *)data->pointer); + } + break; +#endif +#endif + + case DOT11_EVENT_ASSOCIATION_RSP: + if(!DOT11_Process_Association_Rsp(dev, data, WIFI_ASSOCRSP)) + {} + break; + + case DOT11_EVENT_DISCONNECT_REQ: + if(!DOT11_Process_Disconnect_Req(dev, data)) + {} + break; + + case DOT11_EVENT_SET_802DOT11: + break; + + case DOT11_EVENT_SET_KEY: +#if defined(CONFIG_PCI_HCI) + if(!DOT11_Process_Set_Key(dev, data, NULL, NULL)) + {} +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_set_key(dev, (DOT11_SET_KEY *)data->pointer, NULL); +#endif + break; + + case DOT11_EVENT_SET_PORT: + if(!DOT11_Process_Set_Port(dev, data)) + {} + break; + + case DOT11_EVENT_DELETE_KEY: + if(!DOT11_Process_Delete_Key(dev, data)) + {} + break; + + case DOT11_EVENT_SET_RSNIE: + if(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _NO_PRIVACY_ && + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_40_PRIVACY_ && + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_104_PRIVACY_) + if(!DOT11_Process_Set_RSNIE(dev, data)) + {} + break; + + case DOT11_EVENT_GKEY_TSC: + if(!DOT11_Process_QueryRSC(dev, data)) + {} + break; + + case DOT11_EVENT_MIC_FAILURE: + if(!DOT11_Porcess_EAPOL_MICReport(dev, data)) + {} + break; + + case DOT11_EVENT_ASSOCIATION_INFO: +#if 0 + if(!DOT11_Process_Association_Info(dev, data)) + {} +#endif + DEBUG_INFO("trying to process assoc info\n"); + break; + + case DOT11_EVENT_INIT_QUEUE: + DOT11_InitQueue(priv->pevent_queue); + break; + + case DOT11_EVENT_ACC_SET_EXPIREDTIME: +#ifdef RADIUS_ACCOUNTING + DOT11_Process_Acc_SetExpiredTime(dev, data); +#endif + DEBUG_INFO("trying to Set ACC Expiredtime\n"); + break; + + case DOT11_EVENT_ACC_QUERY_STATS: +#ifdef RADIUS_ACCOUNTING + DOT11_Process_Acc_QueryStats(dev, data); +#endif + DEBUG_INFO("trying to Set ACC Expiredtime\n"); + break; + + case DOT11_EVENT_REASSOCIATION_RSP: + if(!DOT11_Process_Association_Rsp(dev, data, WIFI_REASSOCRSP)) + {} + break; + + case DOT11_EVENT_STA_QUERY_BSSID: + if(!DOT11_Process_STA_Query_Bssid(dev, data)) + {}; + break; + + case DOT11_EVENT_STA_QUERY_SSID: + if(!DOT11_Process_STA_Query_Ssid(dev, data)) + {}; + break; + +#ifdef WIFI_SIMPLE_CONFIG + case DOT11_EVENT_WSC_SET_IE: + if(!DOT11_WSC_set_ie(dev, data)) + {}; + break; + +#ifdef INCLUDE_WPS +#ifndef CONFIG_MSC + // procress ioctl request from upnp + + case DOT11_EVENT_WSC_SOAP:{ + CTX_Tp tmp = &(priv->pshare->WSC_CONT_S); + DOT11_WSC_SOAP *soap_evt; //chris 0328 + DOT11_EAP_PACKET *upnp_pkt; //chris 0328 + struct soap_t *soap_pkt; //chris 0328 + + soap_evt = (DOT11_WSC_SOAP *) kmalloc(sizeof(DOT11_WSC_SOAP), GFP_ATOMIC); + upnp_pkt = (DOT11_EAP_PACKET *) kmalloc(sizeof(DOT11_EAP_PACKET), GFP_ATOMIC); + soap_pkt = (struct soap_t *) kmalloc(sizeof(struct soap_t), GFP_ATOMIC); + + memset(soap_evt, 0, sizeof(DOT11_WSC_SOAP)); + memset(upnp_pkt, 0, sizeof(DOT11_EAP_PACKET)); + memset(soap_pkt, 0, sizeof(struct soap_t)); + + if (copy_from_user((void *)soap_evt, (void *)(data->pointer), sizeof(DOT11_WSC_SOAP))) { + //DEBUG_ERR("copy_from_user error!\n"); + printk("copy_from_user error!\n"); + kfree(soap_evt); + kfree(upnp_pkt); + kfree(soap_pkt); + return -1; + } + memcpy(soap_pkt->EventMac, soap_evt->packet.EventMac, MACLEN); + memcpy(soap_pkt->IP, soap_evt->packet.IP, IP_ADDRLEN); + memcpy(soap_pkt->packet, soap_evt->packet.buffer, soap_evt->packet.size); + soap_pkt->length = soap_evt->packet.size; + + if( soap_evt->packet.EventID == WSC_GETDEVINFO ){ + upnp_pkt->EventId = DOT11_EVENT_WSC_GETDEVINFO; + tmp->wps_profile.soap_mathods.upnpGetDeviceInfoHandler(soap_pkt); + printk("%s %d ; call upnpGetDeviceInfoHandler\n",__FUNCTION__,__LINE__); + }else if ( soap_evt->packet.EventID == WSC_M2M4M6M8 ) { + upnp_pkt->EventId = DOT11_EVENT_WSC_M2M4M6M8; + tmp->wps_profile.soap_mathods.upnpPutMessageHandler(soap_pkt); + }else if ( soap_evt->packet.EventID == WSC_SETSELECTEDREGISTRA ) { + upnp_pkt->EventId = DOT11_EVENT_WSC_PUTMESSAGE; + tmp->wps_profile.soap_mathods.upnpSelectedRegistrarHandler(soap_pkt); + }else if ( soap_evt->packet.EventID == WSC_PUTWLANRESPONSE ) { + upnp_pkt->EventId = DOT11_EVENT_WSC_PUTWLANRESPONSE; + tmp->wps_profile.soap_mathods.upnpWlanResponseHandler(soap_pkt); + } + + upnp_pkt->IsMoreEvent = FALSE; + /* + if( packet.tx_size < MAX_MSG_SIZE ){ + upnp_packet.packet_len = packet.tx_size; + memcpy(upnp_packet.packet, packet.tx_buffer, packet.tx_size); + } else { + upnp_packet.packet_len = 0; + }*/ + if( soap_pkt->length > 0 && soap_pkt->length < MAX_MSG_SIZE ){ + upnp_pkt->packet_len = soap_pkt->length; + memcpy(upnp_pkt->packet, soap_pkt->packet, soap_pkt->length); + } else { + upnp_pkt->packet_len = 0; + } + + printk("Rx ; En-Queue UPnP Packet %s %d \n",__FUNCTION__ , __LINE__); + wsc_debug_out(">>>>>>>>>>>>>upnp_packet", upnp_pkt, sizeof(DOT11_EAP_PACKET)); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)upnp_pkt, sizeof(DOT11_EAP_PACKET)); + event_indicate(priv, NULL, -1); + + kfree(soap_evt); + kfree(upnp_pkt); + kfree(soap_pkt); + + } + break; + + case DOT11_EVENT_WSC_PIN:{ + CTX_Tp tmp = &(priv->pshare->WSC_CONT_S); + DOT11_WSC_METHOD wps_pin; + if (copy_from_user((void *)&wps_pin, (void *)(data->pointer), sizeof(DOT11_WSC_PIN_IND))) { + //DEBUG_ERR("copy_from_user error!\n"); + printk("copy_from_user error!\n"); + return -1; + } + tmp->start = 3; + memcpy(tmp->peer_pin_code, wps_pin.code, PIN_LEN); + //evHandler_pin_input(wps_pin.code); + printk("PIN method invoked (from wscd)\n"); + } + break; + case DOT11_EVENT_WSC_PBC:{ + CTX_Tp tmp = &(priv->pshare->WSC_CONT_S); + tmp->start = 2; + //evHandler_pb_press(); + printk("PBC method invoked from wscd\n"); + } + break; + case DOT11_EVENT_WSC_PUTCONF:{ + DOT11_WSC_GETCONF wps_getconf; + CTX_Tp tmp = &(priv->pshare->WSC_CONT_S); + memset(&wps_getconf,0,sizeof(DOT11_WSC_GETCONF)); + WSC_CONFp wps_config = &(wps_getconf.config); + if (copy_from_user((void *)&wps_getconf, (void *)(data->pointer), sizeof(WSC_CONF))) { + DEBUG_ERR("copy_from_user error!\n"); + return -1; + } + /* + for verify ,wscd-deamon will report config-info at WSC_CONF + call to kernel-mode-wps , receive_config_setting(); + + in sercomm case , will not via here,sercomm will direct call wps_start() + */ + printk("[wlan ioctl]:receive \"DOT11_EVENT_WSC_PUTCONF\" from wscd \n"); + //receive_config_setting(priv , wps_config); + read_config_file(tmp, DEFAULT_CONFIG_FILENAME); + } + break; + case DOT11_EVENT_WSC_PROXY_ON: { + printk("[%s] switch proxy on\n",__FUNCTION__); + priv->pshare->WSC_CONT_S.TotalSubscriptions = 1; + } + break; + case DOT11_EVENT_WSC_PROXY_OFF: { + printk("[%s] switch proxy off\n",__FUNCTION__); + priv->pshare->WSC_CONT_S.TotalSubscriptions = 0; + } + break; +#endif +#endif + +#ifdef INCLUDE_WPS + case DOT11_EVENT_WSC_SET_MIB: + + getset_mib_t = (DOT11_GETSET_MIB *)data->pointer; + set_mib(dev->priv, getset_mib_t->cmd); + break; + + case DOT11_EVENT_WSC_GET_MIB: + getset_mib_t = (DOT11_GETSET_MIB*)data->pointer; + get_mib(dev->priv, getset_mib_t->cmd); + break; +#endif +#endif //WIFI_SIMPLE_CONFIG + +#ifdef CONFIG_RTL_WAPI_SUPPORT + case DOT11_EVENT_WAPI_INIT_QUEUE: + DOT11_InitQueue(priv->wapiEvent_queue); + break; + case DOT11_EVENT_WAPI_READ_QUEUE: + if((ret = DOT11_DeQueue((unsigned long)priv, priv->wapiEvent_queue, QueueData, &QueueDataLen)) != 0) + { + val8 = DOT11_EVENT_NO_EVENT; + if (copy_to_user((void *)((unsigned long)(data->pointer)), &val8, 1)) { + DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + val8 = 0; + if (copy_to_user((void *)((unsigned long)(data->pointer) + 1), &val8, 1)) { + DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + data->length = sizeof(DOT11_NO_EVENT); + } + else + { + QueueData[1] = (priv->wapiEvent_queue->NumItem != 0)? 1 : 0; + if (copy_to_user((void *)data->pointer, (void *)QueueData, QueueDataLen)) { + DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + data->length = QueueDataLen; + } + break; + case DOT11_EVENT_WAPI_WRITE_QUEUE: + { + unsigned char *kernelbuf; + kernelbuf = (unsigned char *)kmalloc(data->length,GFP_ATOMIC); + if(NULL == kernelbuf) + { + DEBUG_ERR("Memory alloc fail!\n"); + return -1; + } + if (copy_from_user((void *)kernelbuf, (void *)(data->pointer), data->length)) { + DEBUG_ERR("copy_from_user error!\n"); + kfree(kernelbuf); + return -1; + } + DOT11_Process_WAPI_Info(priv,kernelbuf,data->length); + kfree(kernelbuf); + } + break; +#endif +#ifdef HS2_SUPPORT +/* Hotsport 2.0 Release 1 */ + case DOT11_EVENT_HS2_SET_IE: + if(!DOT11_HS2_set_ie(dev, data)) {}; + break; + case DOT11_EVENT_HS2_GET_TSF: + { + unsigned long long tsf; + unsigned long tsf_sec; + tsf = RTL_R32(TSFTR+4); + tsf = (tsf<<32) + RTL_R32(TSFTR); + tsf_sec = (unsigned long)tsf/1000000; + if (copy_to_user((void *)(data->pointer), &tsf_sec, sizeof(unsigned long))) + { + HS2_DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + data->length = sizeof(unsigned long); + } + break; + case DOT11_EVENT_HS2_GAS_RSP: + issue_GASrsp(priv, data->pointer); + break; + case DOT11_EVENT_HS2_TSM_REQ: + issue_BSS_TSM_req(priv, data->pointer); + break; + case DOT11_EVENT_HS2_GET_RSN: + { + struct wifi_mib *pmib; + pmib = GET_MIB(priv); + if (pmib->dot11RsnIE.rsnielen) { + if (copy_to_user((void *)(data->pointer), pmib->dot11RsnIE.rsnie, pmib->dot11RsnIE.rsnielen)) + { + HS2_DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + data->length = pmib->dot11RsnIE.rsnielen; + } + } + break; + case DOT11_EVENT_HS2_GET_MMPDULIMIT: + { + struct wifi_mib *pmib; + pmib = GET_MIB(priv); + if (copy_to_user((void *)(data->pointer), (void *)(&pmib->hs2Entry.mmpdu_limit), sizeof(unsigned int))) + { + HS2_DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + data->length = sizeof(unsigned int); + } + break; +#endif // HS2_SUPPORT +#ifdef CONFIG_IEEE80211W + /*HS2 R2 logo test*/ + case DOT11_EVENT_INIT_PMF: + { + int i; + DOT11_INIT_11W_Flags flags; + if (copy_from_user((void *)(&flags),(void *)(data->pointer), data->length)) + { + PMFDEBUG("copy_from_user fail!\n"); + return -1; + } + + PMFDEBUG("init pmf:11W[%d],SHA256[%d]\n",flags.dot11IEEE80211W, flags.dot11EnableSHA256); + + priv->pmib->dot1180211AuthEntry.dot11IEEE80211W = flags.dot11IEEE80211W; + priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = flags.dot11EnableSHA256; + + if(priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == 0 && priv->pmib->dot1180211AuthEntry.dot11EnableSHA256) { + priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = 0; + panic_printk("disable SHA256 when PMF is disable\n"); + } + } + case DOT11_EVENT_SET_PMF: + if(!DOT11_PMF_set_ie(dev, data)) + {} + break; + case DOT11_EVENT_GET_IGTK_PN: + { + struct wifi_mib *pmib; + int i; + unsigned char *tt; + pmib = GET_MIB(priv); + +#ifdef PMF_DEBUGMSG + PMFDEBUG("get IGTK_PN:"); + tt = (unsigned char *) & pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48; + for (i=0;idot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC0 + ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC1 + ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC2 + ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC3 + ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC4 + ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC5); +#endif +#endif + + if (copy_to_user((void *)(data->pointer), (void *) (&pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48.val48), sizeof(pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48.val48))) + { + DEBUG_ERR("copy_to_user fail!\n"); + return -1; + } + data->length = sizeof(pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48.val48); + } + break; + case DOT11_EVENT_SA_QUERY_RSP: + { + DOT11_SA_QUERY_RSP resp; + if (copy_from_user((void *)(&resp),(void *)(data->pointer), data->length)) + { + DEBUG_ERR("copy_from_user fail!\n"); + return -1; + } + issue_SA_Query_Rsp(dev, resp.MACAddr, resp.trans_id); + } + break; +#endif // CONFIG_IEEE80211W +#ifdef USER_ADDIE + case DOT11_EVENT_USER_SETIE: + { + if(DOT11_USER_set_ie(dev, data) < 0) { + DEBUG_ERR("DOT11_USER_set_ie failed\n"); + return -1; + }; + } + break; +#endif + + default: + DEBUG_ERR("unknown user daemon command\n"); + break; + } // switch(req->EventId) + + return 0; +} + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_security.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_security.h new file mode 100755 index 000000000..44ddfda5f --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_security.h @@ -0,0 +1,831 @@ +/* + * Header file defines the interface with AUTH daemon (802.1x authenticator) + * + * $Id: 8192cd_security.h,v 1.3.2.1 2010/12/01 13:38:00 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_SECURITY_H_ +#define _8192CD_SECURITY_H_ + +#include "./8192cd_cfg.h" + +#ifdef INCLUDE_WPS +#include "./wps/wsc.h" +#endif + +typedef struct _DOT11_QUEUE_NODE +{ + unsigned short ItemSize; + unsigned char Item[MAXDATALEN]; +}DOT11_QUEUE_NODE; + +typedef struct _DOT11_QUEUE +{ + int Head; + int Tail; + int NumItem; + int MaxItem; + DOT11_QUEUE_NODE ItemArray[MAXQUEUESIZE]; +}DOT11_QUEUE; + +typedef unsigned char DOT11_KEY_RSC[8]; + +typedef enum{ + DOT11_KeyType_Group = 0, + DOT11_KeyType_Pairwise = 1, + DOT11_KeyType_IGTK = 2 +} DOT11_KEY_TYPE; + +typedef enum{ + DOT11_EAPOL_GROUP_INDEX = 0, + DOT11_EAPOL_PAIRWISE_INDEX = 3 +} DOT11_EAPOL_KEY_INDEX; + +typedef enum{ + DOT11_KeyUsage_ENC, + DOT11_KeyUsage_MIC +} DOT11_KEY_USAGE; + +typedef enum{ + DOT11_Role_Auth, + DOT11_Role_Supp +} DOT11_ROLE; + +typedef enum{ + DOT11_VARIABLE_MACEnable, + DOT11_VARIABLE_SystemAuthControl, + DOT11_VARIABLE_AuthControlledPortStatus, + DOT11_VARIABLE_AuthControlledPortControl, + DOT11_VARIABLE_AuthenticationType, + DOT11_VARIABLE_KeyManagement, + DOT11_VARIABLE_MulticastCipher, + DOT11_VARIABLE_UnicastCipher +} DOT11_VARIABLE_TYPE; + +typedef enum{ + DOT11_SysAuthControl_Disabled, + DOT11_SysAuthControl_Enabled +} DOT11_SYSTEM_AUTHENTICATION_CONTROL; + +typedef enum{ + DOT11_PortControl_ForceUnauthorized, + DOT11_PortControl_ForceAuthorized, + DOT11_PortControl_Auto +} DOT11_PORT_CONTROL; + +typedef enum{ + DOT11_PortStatus_Unauthorized, + DOT11_PortStatus_Authorized, + DOT11_PortStatus_Guest +}DOT11_PORT_STATUS; + +typedef enum{ + DOT11_Association_Fail, + DOT11_Association_Success +}DOT11_ASSOCIATION_RESULT; + +typedef enum{ + DOT11_AuthKeyType_RSN = 1, + DOT11_AuthKeyType_PSK = 2, + DOT11_AuthKeyType_NonRSN802dot1x = 3, + DOT11_AuthKeyType_802_1X_SHA256 = 5, //CONFIG_IEEE80211W_CLI + DOT11_AuthKeyType_PSK_SHA256 = 6 +} DOT11_AUTHKEY_TYPE; + +typedef enum{ + DOT11_AuthKeyType_RSN_MAP = 1, + DOT11_AuthKeyType_PSK_MAP = 2, + DOT11_AuthKeyType_NonRSN802dot1x_MAP = 4 +} DOT11_AUTHKEY_TYPE_MAP; + +typedef enum{ + DOT11_Ioctl_Query = 0, + DOT11_Ioctl_Set = 1 +} DOT11_Ioctl_Flag; + +typedef enum{ + DOT11_ENC_NONE = 0, + DOT11_ENC_WEP40 = 1, + DOT11_ENC_TKIP = 2, + DOT11_ENC_WRAP = 3, + DOT11_ENC_CCMP = 4, + DOT11_ENC_WEP104= 5, + DOT11_ENC_BIP = 6, + DOT11_ENC_WAPI = 6 +} DOT11_ENC_ALGO; + +typedef enum{ + DOT11_ENC_NONE_MAP = 1, + DOT11_ENC_WEP40_MAP = 2, + DOT11_ENC_TKIP_MAP = 4, + DOT11_ENC_WRAP_MAP = 8, + DOT11_ENC_CCMP_MAP = 16, + DOT11_ENC_WEP104_MAP= 32 +} DOT11_ENC_ALGO_MAP; + + +typedef enum{ + DOT11_EVENT_NO_EVENT = 1, + DOT11_EVENT_REQUEST = 2, + DOT11_EVENT_ASSOCIATION_IND = 3, + DOT11_EVENT_ASSOCIATION_RSP = 4, + DOT11_EVENT_AUTHENTICATION_IND = 5, + DOT11_EVENT_REAUTHENTICATION_IND = 6, + DOT11_EVENT_DEAUTHENTICATION_IND = 7, + DOT11_EVENT_DISASSOCIATION_IND = 8, + DOT11_EVENT_DISCONNECT_REQ = 9, + DOT11_EVENT_SET_802DOT11 = 10, + DOT11_EVENT_SET_KEY = 11, + DOT11_EVENT_SET_PORT = 12, + DOT11_EVENT_DELETE_KEY = 13, + DOT11_EVENT_SET_RSNIE = 14, + DOT11_EVENT_GKEY_TSC = 15, + DOT11_EVENT_MIC_FAILURE = 16, + DOT11_EVENT_ASSOCIATION_INFO = 17, + DOT11_EVENT_INIT_QUEUE = 18, + DOT11_EVENT_EAPOLSTART = 19, +#ifdef CONFIG_IEEE80211W + DOT11_EVENT_SA_QUERY = 20, + DOT11_EVENT_SA_QUERY_RSP = 21, +#endif + DOT11_EVENT_ACC_SET_EXPIREDTIME = 31, + DOT11_EVENT_ACC_QUERY_STATS = 32, + DOT11_EVENT_ACC_QUERY_STATS_ALL = 33, + DOT11_EVENT_REASSOCIATION_IND = 34, + DOT11_EVENT_REASSOCIATION_RSP = 35, + DOT11_EVENT_STA_QUERY_BSSID = 36, + DOT11_EVENT_STA_QUERY_SSID = 37, + DOT11_EVENT_EAP_PACKET = 41, + +#ifdef RTL_WPA2_PREAUTH + DOT11_EVENT_EAPOLSTART_PREAUTH = 45, + DOT11_EVENT_EAP_PACKET_PREAUTH = 46, +#endif + + DOT11_EVENT_WPA2_MULTICAST_CIPHER = 47, + DOT11_EVENT_WPA_MULTICAST_CIPHER = 48, + +#ifdef WIFI_SIMPLE_CONFIG + DOT11_EVENT_WSC_SET_IE = 55, + DOT11_EVENT_WSC_PROBE_REQ_IND = 56, + DOT11_EVENT_WSC_PIN_IND = 57, + DOT11_EVENT_WSC_ASSOC_REQ_IE_IND = 58, + + +#ifdef INCLUDE_WPS + + DOT11_EVENT_WSC_SET_MIB=42, + DOT11_EVENT_WSC_GET_MIB=43, + DOT11_EVENT_REQUEST_F_INCLUDE_WPS=44, + + + DOT11_EVENT_WSC_INIT_IND = 70, + DOT11_EVENT_WSC_EXIT_IND = 71, + DOT11_EVENT_WSC_TERM_IND = 72, + DOT11_EVENT_WSC_GETCONF_IND = 73, + DOT11_EVENT_WSC_PUTCONF_IND = 74, + DOT11_EVENT_WSC_LEDCONTROL_IND = 75, + DOT11_EVENT_WSC_SENDMSG_IND = 76, + DOT11_EVENT_WSC_PUTCONF = 77, + DOT11_EVENT_WSC_SOAP = 78, + DOT11_EVENT_WSC_PIN = 79, + DOT11_EVENT_WSC_PBC = 80, + DOT11_EVENT_WSC_SYS = 81, + DOT11_EVENT_WSC_PUTWLANREQUEST_IND = 82, + DOT11_EVENT_WSC_PUTPKT = 83, + DOT11_EVENT_WSC_GETDEVINFO = 84, + DOT11_EVENT_WSC_M2M4M6M8 = 85, + DOT11_EVENT_WSC_PUTWLANRESPONSE = 86, + DOT11_EVENT_WSC_PUTMESSAGE = 87, + DOT11_EVENT_WSC_PUTWLREQ_PROBEIND = 88, + DOT11_EVENT_WSC_PUTWLREQ_STATUSIND = 89, +#endif + +#ifdef P2P_SUPPORT + DOT11_EVENT_WSC_SWITCH_MODE = 100, + DOT11_EVENT_WSC_STOP = 101, +#endif + /* support Assigned MAC Addr,Assigned SSID,dymanic change STA's PIN code, 2011-0505 */ + DOT11_EVENT_WSC_SET_MY_PIN = 102, + DOT11_EVENT_WSC_SPEC_SSID = 103, + DOT11_EVENT_WSC_SPEC_MAC_IND = 104, + /* support Assigned MAC Addr,Assigned SSID,dymanic change STA's PIN code, 2011-0505 */ + +#endif +#ifdef CONFIG_RTK_MESH + DOT11_EVENT_PATHSEL_GEN_RREQ = 59, + DOT11_EVENT_PATHSEL_GEN_RERR = 60, + DOT11_EVENT_PATHSEL_RECV_RREQ = 61, + DOT11_EVENT_PATHSEL_RECV_RREP = 62, + DOT11_EVENT_PATHSEL_RECV_RERR = 63, + DOT11_EVENT_PATHSEL_RECV_PANN = 65, + DOT11_EVENT_PATHSEL_RECV_RANN = 66, +#endif // CONFIG_RTK_MESH +#ifdef CONFIG_RTL_WAPI_SUPPORT + DOT11_EVENT_WAPI_INIT_QUEUE =67, + DOT11_EVENT_WAPI_READ_QUEUE = 68, + DOT11_EVENT_WAPI_WRITE_QUEUE =69, +#endif +#if defined(CONFIG_RTL_COMAPI_CFGFILE) && defined(WIFI_SIMPLE_CONFIG) +#ifdef INCLUDE_WPS + DOT11_EVENT_WSC_START_IND = 90, + //EV_MODE, EV_STATUS, EV_MEHOD, EV_STEP, EV_OOB + DOT11_EVENT_WSC_MODE_IND = 91, + DOT11_EVENT_WSC_STATUS_IND = 92, + DOT11_EVENT_WSC_METHOD_IND = 93, + DOT11_EVENT_WSC_STEP_IND = 94, + DOT11_EVENT_WSC_OOB_IND = 95, +#else + DOT11_EVENT_WSC_START_IND = 70, + //EV_MODE, EV_STATUS, EV_MEHOD, EV_STEP, EV_OOB + DOT11_EVENT_WSC_MODE_IND = 71, + DOT11_EVENT_WSC_STATUS_IND = 72, + DOT11_EVENT_WSC_METHOD_IND = 73, + DOT11_EVENT_WSC_STEP_IND = 74, + DOT11_EVENT_WSC_OOB_IND = 75, +#endif +#endif + DOT11_EVENT_WSC_RM_PBC_STA=106, +#ifdef HS2_SUPPORT + /* Hotspot 2.0 Release 1 */ + DOT11_EVENT_GAS_INIT_REQ = 110, + DOT11_EVENT_GAS_COMEBACK_REQ = 111, + DOT11_EVENT_HS2_SET_IE = 112, + DOT11_EVENT_HS2_GAS_RSP = 113, + DOT11_EVENT_HS2_GET_TSF = 114, + DOT11_EVENT_HS2_TSM_REQ = 115, + DOT11_EVENT_HS2_GET_RSN = 116, + DOT11_EVENT_HS2_GET_MMPDULIMIT=117, +#endif +#ifdef USER_ADDIE + DOT11_EVENT_USER_SETIE = 118, +#endif +#ifdef CONFIG_IEEE80211W + DOT11_EVENT_SET_PMF = 120, + DOT11_EVENT_GET_IGTK_PN = 121, + DOT11_EVENT_INIT_PMF = 122, // HS2 R2 logo test +#endif +#ifdef INDICATE_LINK_CHANGE + DOT11_EVENT_LINK_CHANGE_IND = 123, +#endif + DOT11_EVENT_UNKNOWN = 124 +} DOT11_EVENT; + +#ifdef WIFI_SIMPLE_CONFIG +enum {SET_IE_FLAG_BEACON=1, SET_IE_FLAG_PROBE_RSP=2, SET_IE_FLAG_PROBE_REQ=3, + SET_IE_FLAG_ASSOC_RSP=4, SET_IE_FLAG_ASSOC_REQ=5}; +#endif + +#ifdef HS2_SUPPORT +/* Hotspot 2.0 Release 1 */ +enum {SET_IE_FLAG_INTERWORKING=1, SET_IE_FLAG_ADVT_PROTO=2, SET_IE_FLAG_ROAMING=3, + SET_IE_FLAG_HS2=4, SET_IE_FLAG_TIMEADVT=5, SET_IE_FLAG_TIMEZONE=6, SET_IE_FLAG_PROXYARP=7, + SET_IE_FLAG_MMPDULIMIT=10, SET_IE_FLAG_ICMPv4ECHO=11}; +#endif + +#ifdef USER_ADDIE +enum {SET_IE_FLAG_INSERT=1, SET_IE_FLAG_DELETE=2}; +#endif + +typedef struct _DOT11_GENERAL{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char *Data; +}DOT11_GENERAL; + +typedef struct _DOT11_NOEVENT{ + unsigned char EventId; + unsigned char IsMoreEvent; +}DOT11_NO_EVENT; + +typedef struct _DOT11_REQUEST{ + unsigned char EventId; +}DOT11_REQUEST; + +typedef struct _DOT11_WPA2_MULTICAST_CIPHER{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char MulticastCipher; +}DOT11_WPA2_MULTICAST_CIPHER; + +typedef struct _DOT11_WPA_MULTICAST_CIPHER{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char MulticastCipher; +}DOT11_WPA_MULTICAST_CIPHER; + +typedef struct _DOT11_ASSOCIATION_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned short RSNIELen; + char RSNIE[MAXRSNIELEN]; // include ID and Length by kenny +}DOT11_ASSOCIATION_IND; + +typedef struct _DOT11_ASSOCIATION_RSP{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned char Status; +}DOT11_ASSOCIATIIN_RSP; + +typedef struct _DOT11_REASSOCIATION_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned short RSNIELen; + char RSNIE[MAXRSNIELEN]; + char OldAPaddr[MACADDRLEN]; +}DOT11_REASSOCIATION_IND; + +typedef struct _DOT11_REASSOCIATION_RSP{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned char Status; + char CurrAPaddr[MACADDRLEN]; +}DOT11_REASSOCIATIIN_RSP; + +typedef struct _DOT11_AUTHENTICATION_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; +}DOT11_AUTHENTICATION_IND; + +typedef struct _DOT11_REAUTHENTICATION_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; +}DOT11_REAUTHENTICATION_IND; + +#ifdef WIFI_SIMPLE_CONFIG +typedef struct _DOT11_PROBE_REQUEST_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned short ProbeIELen; + char ProbeIE[PROBEIELEN]; +}DOT11_PROBE_REQUEST_IND; + +typedef struct _DOT11_WSC_ASSOC_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned short AssocIELen; + char AssocIE[PROBEIELEN]; + unsigned char wscIE_included; +}DOT11_WSC_ASSOC_IND; + +typedef struct _DOT11_GETSET_MIB { + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char cmd[50]; +}DOT11_GETSET_MIB; + +#endif + +typedef struct _DOT11_DEAUTHENTICATION_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned long tx_packets; // == transmited packets + unsigned long rx_packets; // == received packets + unsigned long tx_bytes; // == transmited bytes + unsigned long rx_bytes; // == received bytes + unsigned long Reason; +}DOT11_DEAUTHENTICATION_IND; + +typedef struct _DOT11_DISASSOCIATION_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned long tx_packets; // == transmited packets + unsigned long rx_packets; // == received packets + unsigned long tx_bytes; // == transmited bytes + unsigned long rx_bytes; // == received bytes + unsigned long Reason; +}DOT11_DISASSOCIATION_IND; + +typedef struct _DOT11_DISCONNECT_REQ{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned short Reason; + char MACAddr[MACADDRLEN]; +}DOT11_DISCONNECT_REQ; + +typedef struct _DOT11_SET_802DOT11{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char VariableType; + unsigned char VariableValue; + char MACAddr[MACADDRLEN]; +}DOT11_SET_802DOT11; + +typedef struct _DOT11_SET_KEY{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned long KeyIndex; + unsigned long KeyLen; + unsigned char KeyType; + unsigned char EncType; + unsigned char MACAddr[MACADDRLEN]; + DOT11_KEY_RSC KeyRSC; + unsigned char KeyMaterial[64]; +}DOT11_SET_KEY; + +typedef struct _DOT11_DELETE_KEY{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned char KeyType; +}DOT11_DELETE_KEY; + +typedef struct _DOT11_SET_RSNIE{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned short Flag; + unsigned short RSNIELen; + char RSNIE[MAXRSNIELEN]; + char MACAddr[MACADDRLEN]; +}DOT11_SET_RSNIE; + +typedef struct _DOT11_SET_PORT{ + unsigned char EventId; + unsigned char PortStatus; + unsigned char PortType; + unsigned char MACAddr[MACADDRLEN]; +}DOT11_SET_PORT; + +typedef struct _DOT11_GKEY_TSC{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char KeyTSC[8]; +}DOT11_GKEY_TSC; + +typedef struct _DOT11_MIC_FAILURE{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; +}DOT11_MIC_FAILURE; + +typedef struct _DOT11_STA_QUERY_BSSID{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned long IsValid; + char Bssid[MACADDRLEN]; +}DOT11_STA_QUERY_BSSID; + +typedef struct _DOT11_STA_QUERY_SSID{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned long IsValid; + char ssid[32]; + int ssid_len; +}DOT11_STA_QUERY_SSID; + +typedef struct _DOT11_EAPOL_START{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; +}DOT11_EAPOL_START; + +typedef struct _DOT11_SET_EXPIREDTIME{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char MACAddr[MACADDRLEN]; + unsigned long ExpireTime; +}DOT11_SET_EXPIREDTIME; + +typedef struct _DOT11_QUERY_STATS{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char MACAddr[MACADDRLEN]; + unsigned long IsSuccess; + unsigned long tx_packets; // == transmited packets + unsigned long rx_packets; // == received packets + unsigned long tx_bytes; // == transmited bytes + unsigned long rx_bytes; // == received bytes +}DOT11_QUERY_STATS; + +typedef struct _DOT11_EAP_PACKET{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned short packet_len; + unsigned char packet[1550]; +}DOT11_EAP_PACKET; + +#ifdef INCLUDE_WPS +#ifndef CONFIG_MSC +typedef struct _DOT11_EVENT_PACKET{ + unsigned char EventId; + unsigned char EventType; + unsigned short packet_len; + unsigned char packet[1550]; +}DOT11_EVENT_PACKET; +#endif +#endif + +typedef DOT11_ASSOCIATION_IND DOT11_AUTH_IND; + +#ifdef WIFI_SIMPLE_CONFIG +typedef struct _DOT11_WSC_PIN_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char code[256]; +} DOT11_WSC_PIN_IND; + +#ifdef CONFIG_RTL_COMAPI_CFGFILE +typedef struct _DOT11_WSC_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned int value; +} DOT11_WSC_IND; +#endif //CONFIG_RTL_COMAPI_CFGFILE +#endif + +#define DOT11_AI_REQFI_CAPABILITIES 1 +#define DOT11_AI_REQFI_LISTENINTERVAL 2 +#define DOT11_AI_REQFI_CURRENTAPADDRESS 4 + +#define DOT11_AI_RESFI_CAPABILITIES 1 +#define DOT11_AI_RESFI_STATUSCODE 2 +#define DOT11_AI_RESFI_ASSOCIATIONID 4 + +typedef struct _DOT11_ASSOCIATION_INFO +{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char SupplicantAddress[MACADDRLEN]; + UINT32 Length; + UINT16 AvailableRequestFixedIEs; + struct _DOT11_AI_REQFI { + UINT16 Capabilities; + UINT16 ListenInterval; + char CurrentAPAddress[MACADDRLEN]; + } RequestFixedIEs; + UINT32 RequestIELength; + UINT32 OffsetRequestIEs; + UINT16 AvailableResponseFixedIEs; + struct _DOT11_AI_RESFI { + UINT16 Capabilities; + UINT16 StatusCode; + UINT16 AssociationId; + } ResponseFixedIEs; + UINT32 ResponseIELength; + UINT32 OffsetResponseIEs; +} DOT11_ASSOCIATION_INFO, *PDOT11_ASSOCIATION_INFO; + +typedef struct _DOT11_INIT_QUEUE +{ + unsigned char EventId; + unsigned char IsMoreEvent; +} DOT11_INIT_QUEUE, *PDOT11_INIT_QUEUE; + +#ifdef USER_ADDIE +typedef struct _DOT11_SET_USERIE{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned short Flag; + unsigned short USERIELen; + char USERIE[256]; +}DOT11_SET_USERIE; +#endif + + +//*------The following are defined to handle the event Queue for security event--------*/ +// For Event Queue related function +void DOT11_InitQueue(DOT11_QUEUE *q); +#ifndef WITHOUT_ENQUEUE +int DOT11_EnQueue(unsigned long task_priv, DOT11_QUEUE *q, unsigned char *item, int itemsize); +int DOT11_DeQueue(unsigned long task_priv, DOT11_QUEUE *q, unsigned char *item, int *itemsize); +#endif +void DOT11_PrintQueue(DOT11_QUEUE *q); +char *DOT11_ErrMsgQueue(int err); +#define DOT11_IsEmptyQueue(q) (q->NumItem==0 ? 1:0) +#define DOT11_IsFullQueue(q) (q->NumItem==q->MaxItem? 1:0) +#define DOT11_NumItemQueue(q) q->NumItem + + +typedef enum{ + ERROR_BUFFER_TOO_SMALL = -1, + ERROR_INVALID_PARA = -2, + ERROR_INVALID_RSNIE = -13, + ERROR_INVALID_MULTICASTCIPHER = -18, + ERROR_INVALID_UNICASTCIPHER = -19, + ERROR_INVALID_AUTHKEYMANAGE = -20, + ERROR_UNSUPPORTED_RSNEVERSION = -21, + ERROR_INVALID_CAPABILITIES = -22, + ERROR_MGMT_FRAME_PROTECTION_VIOLATION = -31 +} INFO_ERROR; + +#define RSN_STRERROR_BUFFER_TOO_SMALL "Input Buffer too small" +#define RSN_STRERROR_INVALID_PARAMETER "Invalid RSNIE Parameter" +#define RSN_STRERROR_INVALID_RSNIE "Invalid RSNIE" +#define RSN_STRERROR_INVALID_MULTICASTCIPHER "Multicast Cipher is not valid" +#define RSN_STRERROR_INVALID_UNICASTCIPHER "Unicast Cipher is not valid" +#define RSN_STRERROR_INVALID_AUTHKEYMANAGE "Authentication Key Management Protocol is not valid" +#define RSN_STRERROR_UNSUPPORTED_RSNEVERSION "Unsupported RSNE version" +#define RSN_STRERROR_INVALID_CAPABILITIES "Invalid RSNE Capabilities" + +#define DOT11_s2n(s,c) (*((c))=(unsigned char)(((s)>> 8)&0xff), \ + *((c)+1)=(unsigned char)(((s) )&0xff)) + +#define DOT11_n2s(c,s) (s =((unsigned short)(*((c))))<< 8, \ + s|=((unsigned short)(*((c)+1)))) + +#define DOT11_lc2s(bc,s) (s = ((unsigned short)(*((bc)+1)))<< 8, \ + s |= ((unsigned short)(*((bc))))) + + +void DOT11_Dump(char *fun, UINT8 *buf, int size, char *comment); + +typedef enum _COUNTERMEASURE_TEST +{ + TEST_TYPE_PAIRWISE_ERROR = 0, + TEST_TYPE_GROUP_ERROR = 1, + TEST_TYPE_SEND_BAD_UNICAST_PACKET = 2, + TEST_TYPE_SEND_BAD_BROADCAST_PACKET = 3 +} COUNTERMEASURE_TEST; + +#define MIC_TIMER_PERIOD RTL_SECONDS_TO_JIFFIES(60) //unit: 10 milli-seconds +#define REJECT_ASSOC_PERIOD RTL_SECONDS_TO_JIFFIES(60) + + +//*---------- The followings are for processing of RSN Information Element------------*/ +#define RSN_ELEMENT_ID 0xDD +#define RSN_VER1 0x01 +#define DOT11_MAX_CIPHER_ALGORITHMS 0x0a +#define DOT11_GROUPFLAG 0x02 +#define DOT11_REPLAYBITSSHIFT 2 +#define DOT11_REPLAYBITS 3 +#define IsPairwiseUsingDefaultKey(Cap) ((Cap[0] & DOT11_GROUPFLAG)?TRUE:FALSE) +#define IsPreAuthentication(Cap) ((Cap[0] & 0x01)?TRUE:FALSE) +#define DOT11_GetNumOfRxTSC(Cap) (2<<((Cap[0] >> DOT11_REPLAYBITSSHIFT) & DOT11_REPLAYBITS)) + +#if defined(PACK_STRUCTURE) || defined(__ECOS) +#pragma pack(1) +#endif + +typedef struct _DOT11_RSN_IE_HEADER { + UINT8 ElementID; + UINT8 Length; + UINT8 OUI[4]; + UINT16 Version; +}DOT11_RSN_IE_HEADER; + + +typedef struct _DOT11_RSN_IE_SUITE{ + UINT8 OUI[3]; + UINT8 Type; +}DOT11_RSN_IE_SUITE; + + +typedef struct _DOT11_RSN_IE_COUNT_SUITE{ + + UINT16 SuiteCount; + DOT11_RSN_IE_SUITE dot11RSNIESuite[DOT11_MAX_CIPHER_ALGORITHMS]; +} __WLAN_ATTRIB_PACK__ DOT11_RSN_IE_COUNT_SUITE, *PDOT11_RSN_IE_COUNT_SUITE; + +typedef union _DOT11_RSN_CAPABILITY{ + + UINT16 shortData; + UINT8 charData[2]; + +#ifdef RTL_WPA2 + struct + { +#ifdef _BIG_ENDIAN_ +#ifdef CONFIG_IEEE80211W + unsigned short MFPC:1; // B7 + unsigned short MFPR:1; // B6 +#else + unsigned short Reserved1:2; // B7 B6 +#endif + unsigned short GtksaReplayCounter:2; // B5 B4 + unsigned short PtksaReplayCounter:2; // B3 B2 + unsigned short NoPairwise:1; // B1 + unsigned short PreAuthentication:1; // B0 + unsigned short Reserved2:8; +#else + unsigned short PreAuthentication:1; // B0 + unsigned short NoPairwise:1; // B1 + unsigned short PtksaReplayCounter:2; // B3 B2 + unsigned short GtksaReplayCounter:2; // B5 B4 +#ifdef CONFIG_IEEE80211W + unsigned short MFPR:1; // B6 + unsigned short MFPC:1; // B7 +#else + unsigned short Reserved1:2; // B7 B6 +#endif + unsigned short Reserved2:8; +#endif + } __WLAN_ATTRIB_PACK__ field; +#else + struct + { +#ifdef _BIG_ENDIAN_ + unsigned short PreAuthentication:1; + unsigned short PairwiseAsDefaultKey:1; + unsigned short NumOfReplayCounter:2; + unsigned short Reserved:12; +#else + unsigned short Reserved1:4; + unsigned short NumOfReplayCounter:2; + unsigned short PairwiseAsDefaultKey:1; + unsigned short PreAuthentication:1; + unsigned short Reserved2:8; +#endif + } __WLAN_ATTRIB_PACK__ field; +#endif + +} __WLAN_ATTRIB_PACK__ DOT11_RSN_CAPABILITY; + +#ifdef HS2_SUPPORT +/* Hotspot 2.0 Release 1 */ +#define MAX_GAS_CONTENTS_LEN PRE_ALLOCATED_BUFSIZE +typedef struct _DOT11_HS2_GAS_REQ{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char Dialog_token; + unsigned char MACAddr[MACADDRLEN]; + unsigned char Advt_proto; + unsigned short Reqlen; + unsigned char Req[MAX_GAS_CONTENTS_LEN]; +}DOT11_HS2_GAS_REQ; + +typedef struct _DOT11_HS2_GAS_RSP{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char Dialog_token; + unsigned char Action; + unsigned char MACAddr[MACADDRLEN]; + unsigned short StatusCode; + unsigned short Comeback_delay; + unsigned char Rsp_fragment_id; + unsigned char Advt_proto; + unsigned short Rsplen; + unsigned char Rsp[MAX_GAS_CONTENTS_LEN]; +}DOT11_HS2_GAS_RSP; + +typedef struct _DOT11_HS2_TSM_REQ{ + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char Dialog_token; + unsigned char MACAddr[MACADDRLEN]; + unsigned char Req_mode; + unsigned char Validity_intval; + unsigned short Disassoc_timer; + unsigned char term_len; + unsigned char url_len; + unsigned char list_len; + unsigned char terminal_dur[12]; + unsigned char Session_url[50]; + unsigned char Candidate_list[100]; +}DOT11_HS2_TSM_REQ; +#endif + +#ifdef CONFIG_IEEE80211W +/*HS2 R2 logo test*/ +typedef struct _DOT11_INIT_11W_Flags { + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char dot11IEEE80211W; + unsigned char dot11EnableSHA256; +}DOT11_INIT_11W_Flags; + +typedef struct _DOT11_SET_11W_Flags { + unsigned char EventId; + unsigned char IsMoreEvent; + unsigned char macAddr[MACADDRLEN]; + unsigned char isPMF; +}DOT11_SET_11W_Flags; + +typedef struct _DOT11_SA_QUERY_RSP { + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned char trans_id[2]; +}DOT11_SA_QUERY_RSP; +#endif // CONFIG_IEEE80211W + +#ifdef INDICATE_LINK_CHANGE +typedef struct _DOT11_LINK_CHANGE_IND { + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned char LinkStatus; +} DOT11_LINK_CHANGE_IND; +#endif + +#if defined(PACK_STRUCTURE) || defined(__ECOS) +#pragma pack() +#endif + +#endif // _8192CD_SECURITY_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_sme.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_sme.c new file mode 100755 index 000000000..f7f894a8a --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_sme.c @@ -0,0 +1,26471 @@ +/* + * Handling routines for 802.11 SME (Station Management Entity) + * + * $Id: 8192cd_sme.c,v 1.90.2.36 2011/01/10 07:49:07 jerryko Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_SME_C_ + +#ifdef __KERNEL__ +#ifdef __MIPSEB__ +#include +#include +#endif +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#ifdef CONFIG_RTL_REPORT_LINK_STATUS +#include +#endif +#endif +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./wifi.h" +#include "./8192cd_hw.h" +#include "./8192cd_headers.h" +#include "./8192cd_rx.h" +#include "./8192cd_debug.h" +#include "./8192cd_psk.h" +#include "./8192cd_security.h" + +#ifdef CONFIG_RTK_MESH +#include "../mesh_ext/mesh_util.h" +#include "../mesh_ext/mesh_route.h" +#ifdef MESH_USE_METRICOP +#include "mesh_ext/mesh_11kv.h" +#endif +#endif + +#ifdef CONFIG_RTL_SIMPLE_CONFIG +#include "8192cd_profile.h" +#endif +#ifdef RTK_NL80211 +#include "8192cd_cfg80211.h" +#endif + +#ifdef WIFI_SIMPLE_CONFIG +#ifdef P2P_SUPPORT +extern unsigned char WFA_OUI[]; +extern unsigned char WFA_OUI_PLUS_TYPE[]; +#define MAX_REASSEM_P2P_IE 512 + +#endif +#ifdef INCLUDE_WPS +#include "./wps/wsc.h" +#endif + +#define TAG_REQUEST_TYPE 0x103a +#define TAG_RESPONSE_TYPE 0x103b + +/*add for WPS2DOTX*/ +#define TAG_VERSION2 0x1067 +#define TAG_VENDOR_EXT 0x1049 +#define VENDOR_VERSION2 0x00 +unsigned char WSC_VENDOR_OUI[3] = {0x00, 0x37, 0x2a}; +/*add for WPS2DOTX*/ + +#define MAX_REQUEST_TYPE_NUM 0x3 +UINT8 WSC_IE_OUI[4] = {0x00, 0x50, 0xf2, 0x04}; +#endif + +#ifdef WIFI_WMM +unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; +unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; +#endif + +#ifdef CONFIG_IEEE80211W_CLI +#include "./sha256.h" +#endif + +#define INTEL_OUI_NUM 192 +unsigned char INTEL_OUI[INTEL_OUI_NUM][3] = +{{0x00, 0x02, 0xb3}, {0x00, 0x03, 0x47}, +{0x00, 0x04, 0x23}, {0x00, 0x07, 0xe9}, +{0x00, 0x0c, 0xf1}, {0x00, 0x0e, 0x0c}, +{0x00, 0x0e, 0x35}, {0x00, 0x11, 0x11}, +{0x00, 0x11, 0x75}, {0x00, 0x12, 0xf0}, +{0x00, 0x13, 0x02}, {0x00, 0x13, 0x20}, +{0x00, 0x13, 0xce}, {0x00, 0x13, 0xe8}, +{0x00, 0x15, 0x00}, {0x00, 0x15, 0x17}, +{0x00, 0x16, 0x6f}, {0x00, 0x16, 0x76}, +{0x00, 0x16, 0xea}, {0x00, 0x16, 0xeb}, +{0x00, 0x18, 0xde}, {0x00, 0x19, 0xd1}, +{0x00, 0x19, 0xd2}, {0x00, 0x1b, 0x21}, +{0x00, 0x1b, 0x77}, {0x00, 0x1c, 0xbf}, +{0x00, 0x1c, 0xc0}, {0x00, 0x1d, 0xe0}, +{0x00, 0x1d, 0xe1}, {0x00, 0x1e, 0x64}, +{0x00, 0x1e, 0x65}, {0x00, 0x1e, 0x67}, +{0x00, 0x1f, 0x3b}, {0x00, 0x1f, 0x3c}, +{0x00, 0x20, 0x7b}, {0x00, 0x21, 0x5c}, +{0x00, 0x21, 0x5d}, {0x00, 0x21, 0x6a}, +{0x00, 0x21, 0x6b}, {0x00, 0x22, 0xfa}, +{0x00, 0x22, 0xfb}, {0x00, 0x23, 0x14}, +{0x00, 0x23, 0x15}, {0x00, 0x24, 0xd6}, +{0x00, 0x24, 0xd7}, {0x00, 0x26, 0xc6}, +{0x00, 0x26, 0xc7}, {0x00, 0x27, 0x0e}, +{0x00, 0x27, 0x10}, {0x00, 0x28, 0xf8}, +{0x00, 0x50, 0xf1}, {0x00, 0x90, 0x27}, +{0x00, 0xa0, 0xc9}, {0x00, 0xaa, 0x00}, +{0x00, 0xaa, 0x01}, {0x00, 0xaa, 0x02}, +{0x00, 0xc2, 0xc6}, {0x00, 0xd0, 0xb7}, +{0x00, 0xdb, 0xdf}, {0x08, 0x11, 0x96}, +{0x08, 0xd4, 0x0c}, {0x0c, 0x8b, 0xfd}, +{0x0c, 0xd2, 0x92}, {0x10, 0x02, 0xb5}, +{0x10, 0x0b, 0xa9}, {0x10, 0x4a, 0x7d}, +{0x10, 0xf0, 0x05}, {0x18, 0x3d, 0xa2}, +{0x18, 0x5e, 0x0f}, {0x18, 0xff, 0x0f}, +{0x24, 0x77, 0x03}, {0x28, 0xb2, 0xbd}, +{0x2c, 0x6e, 0x85}, {0x30, 0x3a, 0x64}, +{0x30, 0xe3, 0x7a}, {0x34, 0x02, 0x86}, +{0x34, 0x13, 0xe8}, {0x34, 0xde, 0x1a}, +{0x34, 0xe6, 0xad}, {0x34, 0xf3, 0x9a}, +{0x3c, 0xa9, 0xf4}, {0x3c, 0xfd, 0xfe}, +{0x40, 0x25, 0xc2}, {0x44, 0x85, 0x00}, +{0x48, 0x45, 0x20}, {0x48, 0x51, 0xb7}, +{0x4c, 0x34, 0x88}, {0x4c, 0x79, 0xba}, +{0x4c, 0x80, 0x93}, {0x4c, 0xeb, 0x42}, +{0x50, 0x2d, 0xa2}, {0x58, 0x91, 0xcf}, +{0x58, 0x94, 0x6b}, {0x58, 0xa8, 0x39}, +{0x58, 0xfb, 0x84}, {0x5c, 0x51, 0x4f}, +{0x5c, 0xc5, 0xd4}, {0x5c, 0xd2, 0xe4}, +{0x5c, 0xe0, 0xc5}, {0x60, 0x36, 0xdd}, +{0x60, 0x57, 0x18}, {0x60, 0x67, 0x20}, +{0x60, 0x6c, 0x66}, {0x64, 0x80, 0x99}, +{0x64, 0xd4, 0xda}, {0x68, 0x05, 0xca}, +{0x68, 0x07, 0x15}, {0x68, 0x17, 0x29}, +{0x68, 0x5d, 0x43}, {0x6c, 0x29, 0x95}, +{0x6c, 0x88, 0x14}, {0x6c, 0xa1, 0x00}, +{0x70, 0x1c, 0xe7}, {0x74, 0xe5, 0x0b}, +{0x78, 0x0c, 0xb8}, {0x78, 0x92, 0x9c}, +{0x78, 0xff, 0x57}, {0x7c, 0x5c, 0xf8}, +{0x7c, 0x7a, 0x91}, {0x7c, 0xb0, 0xc2}, +{0x7c, 0xcc, 0xb8}, {0x80, 0x00, 0x0b}, +{0x80, 0x19, 0x34}, {0x80, 0x86, 0xf2}, +{0x80, 0x9b, 0x20}, {0x84, 0x3a, 0x4b}, +{0x84, 0x68, 0x3e}, {0x84, 0xa6, 0xc8}, +{0x84, 0xef, 0x18}, {0x88, 0x53, 0x2e}, +{0x8c, 0x70, 0x5a}, {0x8c, 0xa9, 0x82}, +{0x90, 0x2e, 0x1c}, {0x90, 0x49, 0xfa}, +{0x90, 0xe2, 0xba}, {0x94, 0x65, 0x9c}, +{0x98, 0x4f, 0xee}, {0x98, 0x54, 0x1b}, +{0x9c, 0x4e, 0x36}, {0xa0, 0x36, 0x9f}, +{0xa0, 0x88, 0x69}, {0xa0, 0x88, 0xb4}, +{0xa0, 0xa8, 0xcd}, {0xa0, 0xc5, 0x89}, +{0xa0, 0xd3, 0x7a}, {0xa4, 0x02, 0xb9}, +{0xa4, 0x34, 0xd9}, {0xa4, 0x4e, 0x31}, +{0xa4, 0xc4, 0x94}, {0xa4, 0xbf, 0x01}, +{0xac, 0x2b, 0x6e}, {0xac, 0x72, 0x89}, +{0xac, 0x7b, 0xa1}, {0xac, 0xfd, 0xce}, +{0xb4, 0x6d, 0x83}, {0xb4, 0xb6, 0x76}, +{0xb4, 0xd5, 0xbd}, {0xb8, 0x03, 0x05}, +{0xb8, 0x08, 0xcf}, {0xb8, 0x81, 0x98}, +{0xb8, 0x8a, 0x60}, {0xb8, 0xb8, 0x1e}, +{0xb8, 0xbf, 0x83}, {0xbc, 0x0f, 0x64}, +{0xbc, 0x77, 0x37}, {0xc4, 0x85, 0x08}, +{0xc4, 0xd9, 0x87}, {0xc8, 0x21, 0x58}, +{0xc8, 0x34, 0x8e}, {0xc8, 0xf7, 0x33}, +{0xcc, 0x3d, 0x82}, {0xd0, 0x57, 0x7b}, +{0xd0, 0x7e, 0x35}, {0xd8, 0xfc, 0x93}, +{0xdc, 0x53, 0x60}, {0xdc, 0xa9, 0x71}, +{0xe0, 0x94, 0x67}, {0xe0, 0x9d, 0x31}, +{0xe4, 0x02, 0x9b}, {0xe4, 0xa4, 0x71}, +{0xe4, 0xa7, 0xa0}, {0xe4, 0xb3, 0x18}, +{0xe4, 0xf8, 0x9c}, {0xe4, 0xfa, 0xfd}, +{0xe8, 0x2a, 0xea}, {0xe8, 0xb1, 0xfc}, +{0xf0, 0x42, 0x1c}, {0xf0, 0xd5, 0xbf}, +{0xf4, 0x06, 0x69}, {0xf8, 0x16, 0x54}, +{0xf8, 0x63, 0x3f}, {0xfc, 0xf8, 0xae}}; + +#define HTC_OUI_NUM 28 +unsigned char HTC_OUI[HTC_OUI_NUM][3]= { +{0x00,0x09,0x2D}, +{0x00,0x23,0x76}, +{0x00,0xEE,0xBD}, +{0x04,0xC2,0x3E}, +{0x18,0x87,0x96}, +{0x1C,0xB0,0x94}, +{0x2C,0x8A,0x72}, +{0x38,0xE7,0xD8}, +{0x40,0x4E,0x36}, +{0x50,0x2E,0x5C}, +{0x64,0xA7,0x69}, +{0x7C,0x61,0x93}, +{0x80,0x01,0x84}, +{0x80,0x7A,0xBF}, +{0x84,0x7A,0x88}, +{0x90,0x21,0x55}, +{0x90,0xE7,0xC4}, +{0x98,0x0D,0x2E}, +{0xA0,0xF4,0x50}, +{0xA8,0x26,0xD9}, +{0xAC,0x37,0x43}, +{0xB4,0xCE,0xF6}, +{0xBC,0xCF,0xCC}, +{0xD4,0x0B,0x1A}, +{0xD4,0x20,0x6D}, +{0xD8,0xB3,0x77}, +{0xE8,0x99,0xC4}, +{0xF8,0xDB,0x7F} +}; + + +#define PSP_OUI_NUM 51 +unsigned char PSP_OUI[PSP_OUI_NUM][3] = +{{0x04, 0x76, 0x6E}, +{0x00, 0x26, 0x43}, +{0x79, 0xC9, 0x74}, +{0x8C, 0x7C, 0xB5}, +{0x78, 0xDD, 0x08}, +{0x50, 0x63, 0x13}, +{0x2C, 0x81, 0x58}, +{0x66, 0x60, 0xEC}, +{0x5C, 0x6D, 0x20}, +{0x00, 0x06, 0xF5}, +{0xC0, 0x14, 0x3D}, +{0x46, 0x8F, 0x25}, +{0xD4, 0x4B, 0x5E}, +{0x00, 0xD4, 0x4B}, +{0x90, 0x34, 0xFC}, +{0x4C, 0x0F, 0x6E}, +{0xF0, 0xF0, 0x02}, +{0x00, 0x07, 0x04}, +{0x00, 0x22, 0xCF}, +{0x00, 0x06, 0xF7}, +{0x60, 0xF4, 0x94}, +{0x0C, 0xEE, 0xE6}, +{0x00, 0x1D, 0xD9}, +{0x00, 0x1C, 0x26}, +{0x00, 0x1B, 0xFB}, +{0x00, 0x19, 0x7F}, +{0x00, 0x19, 0x7E}, +{0x00, 0x19, 0x7D}, +{0x00, 0x16, 0xCF}, +{0x00, 0x16, 0xFE}, +{0x00, 0x13, 0xA8}, +{0x00, 0x16, 0xCE}, +{0x00, 0x13, 0xA9}, +{0x00, 0x14, 0xA4}, +{0x00, 0x02, 0xC7}, +{0x00, 0x19, 0x66}, +{0x00, 0x1F, 0x3A}, +{0x00, 0x24, 0x33}, +{0x00, 0x26, 0x5C}, +{0x00, 0x25, 0x56}, +{0x00, 0x24, 0x2C}, +{0x00, 0x24, 0x2B}, +{0x00, 0x23, 0x4E}, +{0x00, 0x23, 0x4D}, +{0x00, 0x23, 0x06}, +{0x00, 0x22, 0x69}, +{0x00, 0x22, 0x68}, +{0x00, 0x21, 0x4F}, +{0x00, 0x1F, 0xE2}, +{0x00, 0x1F, 0xE1}, +{0x00, 0x01, 0x4A}}; + +#define BCM_OUI_NUM 8 +unsigned char BCM_OUI[BCM_OUI_NUM][3]={ +{0x00, 0x05, 0xb5}, +{0x00, 0x0a, 0xf7}, +{0x00, 0x0d, 0xb6}, +{0x00, 0x10, 0x18}, +{0x00, 0x1b, 0xe9}, +{0x18, 0xc0, 0x86}, +{0xd4, 0x01, 0x29}, +{0xe0, 0x3e, 0x44}, +}; + +/* for RTL865x suspend mode, the CPU can be suspended initially. */ +int gCpuCanSuspend = 1; + +#ifdef RTK_NL80211 +static int rtl8192cd_query_psd_cfg80211(struct rtl8192cd_priv *priv, int chnl, int bw, int fft_pts); +#endif +static unsigned int OnAssocReq(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnProbeReq(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnProbeRsp(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnBeacon(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnDisassoc(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnAuth(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnDeAuth(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnWmmAction(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int DoReserved(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +#ifdef WDS +static void issue_probereq(struct rtl8192cd_priv * priv, unsigned char * ssid, int ssid_len, unsigned char * da); +#endif +#ifdef CLIENT_MODE +static unsigned int OnAssocRsp(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnBeaconClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnATIM(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnDisassocClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnAuthClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static unsigned int OnDeAuthClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +static void start_clnt_assoc(struct rtl8192cd_priv *priv); +static void calculate_rx_beacon(struct rtl8192cd_priv *priv); +static void updateTSF(struct rtl8192cd_priv *priv); +static void issue_PwrMgt_NullData(struct rtl8192cd_priv * priv); +static unsigned int isOurFrameBuffred(unsigned char* tim, unsigned int aid); +#ifdef WIFI_11N_2040_COEXIST +static void issue_coexist_mgt(struct rtl8192cd_priv *priv); +#endif +#endif + +/*Site Survey and sorting result by profile related*/ +static int compareTpyeByProfile(struct rtl8192cd_priv *priv , const void *entry1, const void *entry2 , int CompareType); +static int get_profile_index(struct rtl8192cd_priv *priv ,char* SSID2Search); +static void backup_wscIE(struct rtl8192cd_priv *priv); +#ifdef MBSSID +/*under multi-repeater case when some STA has connect , the other one don't connect to diff channel AP ; skip this*/ +static int multiRepeater_startlookup_chk(struct rtl8192cd_priv *priv , int db_idx); +static int multiRepeater_connection_status(struct rtl8192cd_priv *priv ); +#endif + +int check_dz_mgmt(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct tx_insn* txcfg); + +void SelectLowestInitRate(struct rtl8192cd_priv *priv); + + +#ifdef BEAMFORMING_SUPPORT +void DynamicSelect2STA(struct rtl8192cd_priv *priv); +#endif + +struct mlme_handler { + unsigned int num; + char* str; + unsigned int (*func)(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo); +}; + +#ifdef CONFIG_RTK_MESH +struct mlme_handler mlme_mp_tbl[]={ + {WIFI_ASSOCREQ, "OnAssocReq", OnAssocReq_MP}, + {WIFI_ASSOCRSP, "OnAssocRsp", OnAssocRsp_MP}, + {WIFI_REASSOCREQ, "OnReAssocReq", OnAssocReq_MP}, + {WIFI_REASSOCRSP, "OnReAssocRsp", OnAssocRsp_MP}, + {WIFI_PROBEREQ, "OnProbeReq", OnProbeReq}, + {WIFI_PROBERSP, "OnProbeRsp", OnProbeRsp}, + + /*---------------------------------------------------------- + below 2 are reserved + -----------------------------------------------------------*/ + {0, "DoReserved", DoReserved}, + {0, "DoReserved", DoReserved}, + {WIFI_BEACON, "OnBeacon", OnBeacon}, + {WIFI_ATIM, "OnATIM", DoReserved}, + {WIFI_DISASSOC, "OnDisassoc", OnDisassoc_MP}, + {WIFI_AUTH, "OnAuth", OnAuth}, + {WIFI_DEAUTH, "OnDeAuth", OnDeAuth}, + {WIFI_WMM_ACTION, "OnWmmAct", OnWmmAction} +}; +#endif // CONFIG_RTK_MESH + +struct mlme_handler mlme_ap_tbl[]={ + {WIFI_ASSOCREQ, "OnAssocReq", OnAssocReq}, + {WIFI_ASSOCRSP, "OnAssocRsp", DoReserved}, + {WIFI_REASSOCREQ, "OnReAssocReq", OnAssocReq}, + {WIFI_REASSOCRSP, "OnReAssocRsp", DoReserved}, + {WIFI_PROBEREQ, "OnProbeReq", OnProbeReq}, + {WIFI_PROBERSP, "OnProbeRsp", OnProbeRsp}, + + /*---------------------------------------------------------- + below 2 are reserved + -----------------------------------------------------------*/ + {0, "DoReserved", DoReserved}, + {0, "DoReserved", DoReserved}, + {WIFI_BEACON, "OnBeacon", OnBeacon}, + {WIFI_ATIM, "OnATIM", DoReserved}, + {WIFI_DISASSOC, "OnDisassoc", OnDisassoc}, + {WIFI_AUTH, "OnAuth", OnAuth}, + {WIFI_DEAUTH, "OnDeAuth", OnDeAuth}, + {WIFI_WMM_ACTION, "OnWmmAct", OnWmmAction} +}; +#ifdef CLIENT_MODE +struct mlme_handler mlme_station_tbl[]={ + {WIFI_ASSOCREQ, "OnAssocReq", DoReserved}, + {WIFI_ASSOCRSP, "OnAssocRsp", OnAssocRsp}, + {WIFI_REASSOCREQ, "OnReAssocReq", DoReserved}, + {WIFI_REASSOCRSP, "OnReAssocRsp", OnAssocRsp}, + {WIFI_PROBEREQ, "OnProbeReq", OnProbeReq}, + {WIFI_PROBERSP, "OnProbeRsp", OnProbeRsp}, + + /*---------------------------------------------------------- + below 2 are reserved + -----------------------------------------------------------*/ + {0, "DoReserved", DoReserved}, + {0, "DoReserved", DoReserved}, + {WIFI_BEACON, "OnBeacon", OnBeaconClnt}, + {WIFI_ATIM, "OnATIM", OnATIM}, + {WIFI_DISASSOC, "OnDisassoc", OnDisassocClnt}, + {WIFI_AUTH, "OnAuth", OnAuthClnt}, + {WIFI_DEAUTH, "OnDeAuth", OnDeAuthClnt}, + {WIFI_WMM_ACTION, "OnWmmAct", OnWmmAction} +}; +#endif + +#ifdef CONFIG_RTL_WLAN_DOS_FILTER +#define MAX_BLOCK_MAC 4 +unsigned char block_mac[MAX_BLOCK_MAC][6]; +unsigned int block_mac_idx = 0; +unsigned int block_sta_time = 0; +unsigned long block_priv; +#endif + +static int is_support_wpa_aes(struct rtl8192cd_priv *priv, unsigned char *pucIE, unsigned long ulIELength) +{ + unsigned short version, usSuitCount; + DOT11_RSN_IE_HEADER *pDot11RSNIEHeader; + DOT11_RSN_IE_SUITE *pDot11RSNIESuite; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite; + unsigned char *ptr; + + if (ulIELength < sizeof(DOT11_RSN_IE_HEADER)) { + DEBUG_WARN("parseIE err 1!\n"); + return -1; + } + + pDot11RSNIEHeader = (DOT11_RSN_IE_HEADER *)pucIE; + ptr = (unsigned char *)&pDot11RSNIEHeader->Version; + version = (ptr[1] << 8) | ptr[0]; + + if (version != RSN_VER1) { + DEBUG_WARN("parseIE err 2!\n"); + return -1; + } + + if (pDot11RSNIEHeader->ElementID != RSN_ELEMENT_ID || + pDot11RSNIEHeader->Length != ulIELength -2 || + pDot11RSNIEHeader->OUI[0] != 0x00 || pDot11RSNIEHeader->OUI[1] != 0x50 || + pDot11RSNIEHeader->OUI[2] != 0xf2 || pDot11RSNIEHeader->OUI[3] != 0x01 ) { + DEBUG_WARN("parseIE err 3!\n"); + return -1; + } + + ulIELength -= sizeof(DOT11_RSN_IE_HEADER); + pucIE += sizeof(DOT11_RSN_IE_HEADER); + + //---------------------------------------------------------------------------------- + // Multicast Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < sizeof(DOT11_RSN_IE_SUITE)) { + DEBUG_WARN("parseIE err 4!\n"); + return -1; + } + + pDot11RSNIESuite = (DOT11_RSN_IE_SUITE *)pucIE; + if (pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x50 || + pDot11RSNIESuite->OUI[2] != 0xF2) { + DEBUG_WARN("parseIE err 5!\n"); + return -1; + } + + ulIELength -= sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(DOT11_RSN_IE_SUITE); + + //---------------------------------------------------------------------------------- + // Pairwise Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) { + DEBUG_WARN("parseIE err 6!\n"); + return -1; + } + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + ptr = (unsigned char *)&pDot11RSNIECountSuite->SuiteCount; + usSuitCount = (ptr[1] << 8) | ptr[0]; + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x50 || + pDot11RSNIESuite->OUI[2] != 0xF2) { + DEBUG_WARN("parseIE err 7!\n"); + return -1; + } + + if (pDot11RSNIESuite->Type == DOT11_ENC_CCMP) + return 1; + else + return 0; +} + + +static int is_support_wpa2_aes(struct rtl8192cd_priv *priv, unsigned char *pucIE, unsigned long ulIELength) +{ + unsigned short version, usSuitCount; + DOT11_WPA2_IE_HEADER *pDot11WPA2IEHeader = NULL; + DOT11_RSN_IE_SUITE *pDot11RSNIESuite = NULL; + DOT11_RSN_IE_COUNT_SUITE *pDot11RSNIECountSuite = NULL; + unsigned char *ptr; + + if (ulIELength < sizeof(DOT11_WPA2_IE_HEADER)) { + DEBUG_WARN("ERROR_INVALID_RSNIE_LEN, err 1\n"); + return -1; + } + + pDot11WPA2IEHeader = (DOT11_WPA2_IE_HEADER *)pucIE; + ptr = (unsigned char *)&pDot11WPA2IEHeader->Version; + version = (ptr[1] << 8) | ptr[0]; + + if (version != RSN_VER1) { + DEBUG_WARN("ERROR_UNSUPPORTED_RSNEVERSION, err 2\n"); + return -1; + } + + if (pDot11WPA2IEHeader->ElementID != WPA2_ELEMENT_ID || + pDot11WPA2IEHeader->Length != ulIELength -2 ) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 3\n"); + return -1; + } + + ulIELength -= sizeof(DOT11_WPA2_IE_HEADER); + pucIE += sizeof(DOT11_WPA2_IE_HEADER); + + //---------------------------------------------------------------------------------- + // Multicast Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < sizeof(DOT11_RSN_IE_SUITE)) { + DEBUG_WARN("ERROR_INVALID_RSNIE_LEN, err 4\n"); + return -1; + } + + pDot11RSNIESuite = (DOT11_RSN_IE_SUITE *)pucIE; + if (pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 5\n"); + return -1; + } + + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) { + DEBUG_WARN("ERROR_INVALID_MULTICASTCIPHER, err 6\n"); + return -1; + } + + ulIELength -= sizeof(DOT11_RSN_IE_SUITE); + pucIE += sizeof(DOT11_RSN_IE_SUITE); + + //---------------------------------------------------------------------------------- + // Pairwise Cipher Suite processing + //---------------------------------------------------------------------------------- + if (ulIELength < 2 + sizeof(DOT11_RSN_IE_SUITE)) { + DEBUG_WARN("ERROR_INVALID_RSN_IE_SUITE_LEN, err 7\n"); + return -1; + } + + pDot11RSNIECountSuite = (PDOT11_RSN_IE_COUNT_SUITE)pucIE; + pDot11RSNIESuite = pDot11RSNIECountSuite->dot11RSNIESuite; + ptr = (unsigned char *)&pDot11RSNIECountSuite->SuiteCount; + usSuitCount = (ptr[1] << 8) | ptr[0]; + + if (usSuitCount != 1 || + pDot11RSNIESuite->OUI[0] != 0x00 || + pDot11RSNIESuite->OUI[1] != 0x0F || + pDot11RSNIESuite->OUI[2] != 0xAC) { + DEBUG_WARN("ERROR_INVALID_RSNIE, err 8\n"); + return -1; + } + + if (pDot11RSNIESuite->Type > DOT11_ENC_WEP104) { + DEBUG_WARN("ERROR_INVALID_UNICASTCIPHER, err 9\n"); + return -1; + } + + if (pDot11RSNIESuite->Type == DOT11_ENC_CCMP) + return 1; + else + return 0; +} + +static unsigned char check_probe_sta_rssi_valid(struct rtl8192cd_priv *priv,unsigned char* addr, unsigned char rssi) +{ + int i, idx=-1; + unsigned char *hwaddr; + hwaddr = addr; + for (i=0; iprobe_sta[i].addr, addr, MACADDRLEN)){ + idx = i; + break;// check if it is already in the list + } + } + if (idx < 0){ + return 1;// if probe req sta isn't in the list, allow it + } + else{ + if ( priv->probe_sta[idx].rssi && RTL_ABS(priv->probe_sta[idx].rssi,rssi) > 10) + return 0; + else + return 1; + } +} +static void add_probe_req_sta(struct rtl8192cd_priv *priv,unsigned char* addr, unsigned char rssi) +{ + int i, idx=-1, idx2 =0; + unsigned char *hwaddr; + unsigned char rssi_input; + hwaddr = addr; + + for (i=0; iprobe_sta[i].used == 0) { + if (idx < 0) + idx = i; //search for empty entry + continue; + } + if (!memcmp(priv->probe_sta[i].addr, addr, MACADDRLEN)) { + idx2 = i; + break;// check if it is already in the list + } + } + if (idx >= 0){ + rssi_input = rssi; + memcpy(priv->probe_sta[idx].addr, addr, MACADDRLEN); + priv->probe_sta[idx].used = 1; + priv->probe_sta[idx].Entry = idx;//check which entry is the probe sta recorded + priv->probe_sta[idx].rssi = rssi_input; + priv->pshare->ProbeReqEntryOccupied++; + return; + } + else if (idx2){ + rssi_input = ((priv->probe_sta[idx2].rssi * 7)+(rssi * 3)) / 10; + priv->probe_sta[idx2].rssi = rssi_input; + return; + } + else if (priv->pshare->ProbeReqEntryOccupied == MAX_PROBE_REQ_STA) {// sta list full, need to replace sta + idx = priv->pshare->ProbeReqEntryNum; + for (i=0; iprobe_sta[i].addr, addr, MACADDRLEN)) + return; // check if it is already in the list + } + memcpy(priv->probe_sta[idx].addr, addr, MACADDRLEN); + priv->probe_sta[idx].used = 1; + priv->probe_sta[idx].Entry = idx; + priv->probe_sta[idx].rssi = rssi; + priv->pshare->ProbeReqEntryNum++; + if( priv->pshare->ProbeReqEntryNum == MAX_PROBE_REQ_STA) + priv->pshare->ProbeReqEntryNum = 0; // Reset entry counter; + return; + } +} + +#ifdef WIFI_SIMPLE_CONFIG +/* WPS2DOTX */ +#ifdef __ECOS //search_VendorExt_tag() also defined in wsc/util.c. Static definition here to avoid confilct. +static +#endif +unsigned char *search_VendorExt_tag(unsigned char *data, unsigned char id, int len, int *out_len) +{ + unsigned char tag, tag_len; + int size; + + //skip WFA_VENDOR_LEN + data+=3; + len-=3; + + while (len > 0) { + memcpy(&tag, data, 1); + memcpy(&tag_len, data+1, 1); + if (id == tag) { + if (len >= (2 + tag_len)) { + *out_len = (int)tag_len; + return (&data[2]); + } + else { + _DEBUG_ERR("Found VE tag [0x%x], but invalid length!\n", id); + break; + } + } + size = 2 + tag_len; + data += size; + len -= size; + } + + return NULL; +} +/* WPS2DOTX */ + +unsigned char *search_wsc_tag(unsigned char *data, unsigned short id, int len, int *out_len) +{ + unsigned short tag, tag_len; + int size; + + while (len > 0) { + memcpy(&tag, data, 2); + memcpy(&tag_len, data+2, 2); + tag = ntohs(tag); + tag_len = ntohs(tag_len); + + if (id == tag) { + if (len >= (4 + tag_len)) { + *out_len = (int)tag_len; + return (&data[4]); + } + else { + _DEBUG_ERR("Found tag [0x%x], but invalid length!\n", id); + break; + } + } + size = 4 + tag_len; + data += size; + len -= size; + } + + return NULL; +} + + +static struct wsc_probe_request_info *search_wsc_probe_sta(struct rtl8192cd_priv *priv, unsigned char *addr) +{ + int i, idx=-1; + + for (i=0; iwsc_sta[i].used == 0) { + if (idx < 0) + idx = i; + continue; + } + if (!memcmp(priv->wsc_sta[i].addr, addr, MACADDRLEN)) + break; + } + + if ( i != MAX_WSC_PROBE_STA) + return (&priv->wsc_sta[i]); // return sta info for WSC sta + + if (idx >= 0) + return (&priv->wsc_sta[idx]); // add sta info for WSC sta + else { + // sta list full, need to replace sta + unsigned long oldest_time_stamp=jiffies; + + for (i=0; iwsc_sta[i].time_stamp < oldest_time_stamp) { + oldest_time_stamp = priv->wsc_sta[i].time_stamp; + idx = i; + } + } + memset(&priv->wsc_sta[idx], 0, sizeof(struct wsc_probe_request_info)); + + return (&priv->wsc_sta[idx]); + } +} + + +static int search_wsc_pbc_probe_sta(struct rtl8192cd_priv *priv, unsigned char *addr) +{ + int i/*, idx=-1*/; +#ifndef SMP_SYNC + unsigned long flags; +#endif + SAVE_INT_AND_CLI(flags); + + for (i=0; iwsc_sta[i].used==1 && priv->wsc_sta[i].pbcactived==1) { + + if (!memcmp(priv->wsc_sta[i].addr, addr, MACADDRLEN)){ + + priv->wsc_sta[i].used=0; + priv->wsc_sta[i].pbcactived=0; + RESTORE_INT(flags); + return 1; + } + } + } + RESTORE_INT(flags); + return 0; + +} + +#define TAG_DEVICE_PASSWORD_ID 0x1012 +#define PASS_ID_PB 0x4 +static void wsc_forward_probe_request(struct rtl8192cd_priv *priv, unsigned char *pframe, unsigned char *IEaddr, unsigned int IElen) +{ + unsigned char *p=IEaddr; + unsigned int len=IElen; + unsigned char forwarding=0; + struct wsc_probe_request_info *wsc_sta=NULL; + DOT11_PROBE_REQUEST_IND ProbeReq_Ind; +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned char *p2=IEaddr; + unsigned int len2=IElen; + unsigned short pwid=0; + + if (IEaddr == NULL || IElen == 0) + return; + if (IElen > PROBEIELEN) { + DEBUG_WARN("[%s] IElen=%d\n", __FUNCTION__, IElen); + return; + } + p = search_wsc_tag(p+2+4, TAG_REQUEST_TYPE, len-4, (int *)&len); + if (p && (*p <= MAX_REQUEST_TYPE_NUM)) { //forward WPS IE to wsc daemon + SAVE_INT_AND_CLI(flags); + wsc_sta = search_wsc_probe_sta(priv, (unsigned char *)GetAddr2Ptr(pframe)); + p2 = search_wsc_tag(p2+2+4, TAG_DEVICE_PASSWORD_ID, len2-4, (int *)&len2); + if(p2){ + memcpy(&pwid, p2, len2); + pwid = ntohs(pwid); + if(pwid==PASS_ID_PB){ + wsc_sta->pbcactived=1; + } + } + if (wsc_sta->used) { + if ((wsc_sta->ProbeIELen != IElen) || + (memcmp(wsc_sta->ProbeIE, (void *)(IEaddr), IElen) != 0) || + ((jiffies - wsc_sta->time_stamp) > RTL_SECONDS_TO_JIFFIES(3))) + { + memcpy(wsc_sta->ProbeIE, (void *)(IEaddr), IElen); + wsc_sta->ProbeIELen = IElen; + wsc_sta->time_stamp = jiffies; + forwarding = 1; + } + } + else { + memcpy(wsc_sta->addr, (void *)GetAddr2Ptr(pframe), MACADDRLEN); + memcpy(wsc_sta->ProbeIE, (void *)(IEaddr), IElen); + wsc_sta->ProbeIELen = IElen; + wsc_sta->time_stamp = jiffies; + wsc_sta->used = 1; + forwarding = 1; + } + RESTORE_INT(flags); + + if (forwarding) { + memcpy((void *)ProbeReq_Ind.MACAddr, (void *)GetAddr2Ptr(pframe), MACADDRLEN); + ProbeReq_Ind.EventId = DOT11_EVENT_WSC_PROBE_REQ_IND; + ProbeReq_Ind.IsMoreEvent = 0; + ProbeReq_Ind.ProbeIELen = IElen; + memcpy((void *)ProbeReq_Ind.ProbeIE, (void *)(IEaddr), ProbeReq_Ind.ProbeIELen); +#ifdef INCLUDE_WPS + // wps_indicate_evt(priv); + wps_NonQueue_indicate_evt(priv , + (UINT8 *)&ProbeReq_Ind,sizeof(DOT11_PROBE_REQUEST_IND)); +#else + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&ProbeReq_Ind, sizeof(DOT11_PROBE_REQUEST_IND)); +#ifdef WIFI_HAPD + event_indicate_hapd(priv, GetAddr2Ptr(pframe), HAPD_WPS_PROBEREQ, (UINT8 *)&ProbeReq_Ind); //_Eric ???? this event is not registered +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#else + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#endif + } + } +} + + +static __inline__ void wsc_probe_expire(struct rtl8192cd_priv *priv) +{ + int i; + //unsigned long flags; + + //SAVE_INT_AND_CLI(flags); + for (i=0; iwsc_sta[i].used == 0) + continue; + if ((jiffies - priv->wsc_sta[i].time_stamp) > RTL_SECONDS_TO_JIFFIES(180)) + memset(&priv->wsc_sta[i], 0, sizeof(struct wsc_probe_request_info)); + } + //RESTORE_INT(flags); +} +#endif // WIFI_SIMPLE_CONFIG + + +static __inline__ UINT8 match_supp_rate(unsigned char *pRate, int len, UINT8 rate) +{ + int idx; + for (idx=0; idxnext; + list_del(plist); + + pfrinfo = list_entry(plist, struct rx_frinfo, mpdu_list); + pskb = get_pskb(pfrinfo); + priv->ext_stats.rx_data_drops++; + rtl_kfree_skb(priv, pskb, _SKB_RX_); + } +} + + +void rtl8192cd_frag_timer(unsigned long task_priv) +{ + unsigned long flags; + struct list_head *phead, *plist; + struct stat_info *pstat; + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + struct list_head frag_list; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + INIT_LIST_HEAD(&frag_list); + + priv->frag_to ^= 0x01; + + phead = &priv->defrag_list; + + DEFRAG_LOCK(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, defrag_list); + plist = plist->next; + + if (pstat->frag_to == priv->frag_to) { + list_del_init(&pstat->defrag_list); + list_splice_init(&pstat->frag_list, &frag_list); + pstat->frag_count = 0; + } + } + + DEFRAG_UNLOCK(flags); + + unchainned_all_frag(priv, &frag_list); + + mod_timer(&priv->frag_to_filter, jiffies + FRAG_TO); +} + + +#ifdef USB_PKT_RATE_CTRL_SUPPORT +usb_pktCnt_fn get_usb_pkt_cnt_hook = NULL; +register_usb_pkt_cnt_fn register_usb_hook = NULL; + +void register_usb_pkt_cnt_f(void *usbPktFunc) +{ + get_usb_pkt_cnt_hook = (usb_pktCnt_fn)(usbPktFunc); +} + + +void usbPkt_timer_handler(struct rtl8192cd_priv *priv) +{ + unsigned int pkt_cnt, pkt_diff; + + if (!get_usb_pkt_cnt_hook) + return; + + pkt_cnt = get_usb_pkt_cnt_hook(); + pkt_diff = pkt_cnt - priv->pre_pkt_cnt; + + if (pkt_diff) { + priv->auto_rate_mask = 0x803fffff; + priv->change_toggle = ((priv->change_toggle) ? 0 : 1); + } + + priv->pre_pkt_cnt = pkt_cnt; + priv->pkt_nsec_diff += pkt_diff; + + if ((++priv->poll_usb_cnt) % 10 == 0) { + if ((priv->pkt_nsec_diff) < 10 ) { + priv->auto_rate_mask = 0; + priv->pkt_nsec_diff = 0; + } + } +} +#endif // USB_PKT_RATE_CTRL_SUPPORT + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +static void auth_expire(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + struct list_head *phead, *plist; + struct list_head local_head; +#ifdef SMP_SYNC + unsigned long flags; +#endif + + INIT_LIST_HEAD(&local_head); + + SMP_LOCK_AUTH_LIST(flags); + + phead = &priv->auth_list; + plist = phead->next; + + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, auth_list); + plist = plist->next; + +// #if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) // Skip MP node +#ifdef CONFIG_RTK_MESH // Skip MP node + if(isPossibleNeighbor(pstat)) + continue; +#endif // CONFIG_RTK_MESH + + pstat->expire_to--; + if (pstat->expire_to == 0) { + list_del(&pstat->auth_list); + list_add_tail(&pstat->auth_list, &local_head); + } + } + + phead = &local_head; + plist = phead->next; + + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, auth_list); + list_del_init(plist); + + SMP_UNLOCK_AUTH_LIST(flags); + + //below should be take care... since auth fail, just free the stat info... + DEBUG_INFO("auth expire %02X%02X%02X%02X%02X%02X\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + + free_stainfo(priv, pstat); + + SMP_LOCK_AUTH_LIST(flags); + + plist = phead->next; + } + + SMP_UNLOCK_AUTH_LIST(flags); +} +#else +static void auth_expire(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + struct list_head *phead, *plist; + //unsigned long flags; + + phead = &priv->auth_list; + plist = phead->next; + + //SAVE_INT_AND_CLI(flags); + while(plist != phead) + { + pstat = list_entry(plist, struct stat_info, auth_list); + plist = plist->next; + +// #if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) // Skip MP node +#ifdef CONFIG_RTK_MESH // Skip MP node + if(isPossibleNeighbor(pstat)) + continue; +#endif // CONFIG_RTK_MESH + + pstat->expire_to--; + if (pstat->expire_to == 0) + { + list_del_init(&pstat->auth_list); + + //below should be take care... since auth fail, just free the stat info... + DEBUG_INFO("auth expire %02X%02X%02X%02X%02X%02X\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + free_stainfo(priv, pstat); + } + } + //RESTORE_INT(flags); +} +#endif + + +#if 0 // def RTL8192SE +void reset_1r_sta_RA(struct rtl8192cd_priv *priv, unsigned int sg_rate){ + struct list_head *phead, *plist; + struct stat_info *pstat; +#ifdef SMP_SYNC + unsigned long flags=0; +#endif + + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while(plist != phead) + { + + unsigned int sta_band = 0; + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if(pstat && !pstat->ht_cap_len) + continue; + + if (pstat->tx_ra_bitmap & 0xffff000) + sta_band |= WIRELESS_11N | WIRELESS_11G | WIRELESS_11B; + else if (pstat->tx_ra_bitmap & 0xff0) + sta_band |= WIRELESS_11G |WIRELESS_11B; + else + sta_band |= WIRELESS_11B; + + if((pstat->tx_ra_bitmap & 0x0ff00000) == 0 && (pstat->tx_ra_bitmap & BIT(28))!=0 && sg_rate == 0xffff){ + pstat->tx_ra_bitmap &= ~BIT(28); // disable short GI for 1R sta + set_fw_reg(priv, (0xfd0000a2 | ((REMAP_AID(pstat) & 0x1f)<<4 | (sta_band & 0xf))<<8), pstat->tx_ra_bitmap, 1); + } + else if((pstat->tx_ra_bitmap & 0x0ff00000) == 0 && (pstat->tx_ra_bitmap & BIT(28))==0 && sg_rate == 0x7777){ + pstat->tx_ra_bitmap |= BIT(28); // enable short GI for 1R sta + set_fw_reg(priv, (0xfd0000a2 | ((REMAP_AID(pstat) & 0x1f)<<4 | (sta_band & 0xf))<<8), pstat->tx_ra_bitmap, 1); + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + + return; +} +#endif + + + +// for simplify, we consider only two stations. Otherwise we may sorting all the stations and +// hard to maintain the code. +// 0 for path A/B selection(bg only or 1ss rate), 1 for TX Diversity (ex: DIR 655 clone) +#if 0 +struct stat_info* switch_ant_enable(struct rtl8192cd_priv *priv, unsigned char flag) +{ + struct stat_info *pstat, *pstat_chosen = NULL; + struct list_head *phead, *plist; + unsigned int tp_2nd = 0, maxTP = 0; + unsigned int rssi_2ndTp = 0, rssi_maxTp = 0; + unsigned int tx_2s_avg = 0; + unsigned int rx_2s_avg = 0; + unsigned long total_sum = (priv->pshare->current_tx_bytes+priv->pshare->current_rx_bytes); + unsigned char th_rssi = 0; +#ifdef SMP_SYNC + unsigned long flags=0; +#endif + + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if((pstat->tx_avarage + pstat->rx_avarage) > maxTP){ + tp_2nd = maxTP; + rssi_2ndTp = rssi_maxTp; + + maxTP = pstat->tx_avarage + pstat->rx_avarage; + rssi_maxTp = pstat->rssi; + + pstat_chosen = pstat; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + + // for debug +// printk("maxTP: %d, second: %d\n", rssi_maxTp, rssi_2ndTp); + + if(pstat_chosen == NULL){ +// printk("ERROR! NULL pstat_chosen \n"); + return NULL; + } + + if(total_sum != 0){ + tx_2s_avg = (unsigned int)((pstat_chosen->current_tx_bytes*100) / total_sum); + rx_2s_avg = (unsigned int)((pstat_chosen->current_rx_bytes*100) / total_sum); + } + + if( priv->assoc_num > 1 && (tx_2s_avg+rx_2s_avg) < (100/priv->assoc_num)){ // this is not a burst station + pstat_chosen = NULL; +// printk("avg is: %d\n", (tx_2s_avg+rx_2s_avg)); + goto out_switch_ant_enable; + } + + if(flag == 1) + goto out_switch_ant_enable; + + if(pstat_chosen && (pstat_chosen->sta_in_firmware == 1) && + !getSTABitMap(&priv->pshare->has_2r_sta, REMAP_AID(pstat_chosen)) // 1r STA + ) + th_rssi = 40; + else + th_rssi = 63; + + if((maxTP < tp_2nd*2 && (rssi_maxTp < th_rssi || rssi_2ndTp < th_rssi))) + pstat_chosen = NULL; + else if(maxTP >= tp_2nd*2 && rssi_maxTp < th_rssi) + pstat_chosen = NULL; + +out_switch_ant_enable: + return pstat_chosen; +} +#endif + + +void dynamic_response_rate(struct rtl8192cd_priv *priv, short rssi) +{ + if(rssi<30){ + if(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G){ + if(priv->pshare->current_rsp_rate !=0x10){ + RTL_W16(RRSR,0x10); + priv->pshare->current_rsp_rate=0x10; + //SDEBUG("current_rsp_rate=%x\n" ,priv->pshare->current_rsp_rate); + } + }else if(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G){ + if(priv->pshare->current_rsp_rate!=0x1f){ + RTL_W16(RRSR,0x1f); + priv->pshare->current_rsp_rate=0x1f; + } + } + + }else if(rssi>35){ + if(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G){ + if(priv->pshare->current_rsp_rate!=0x150){ + RTL_W16(RRSR,0x150); + priv->pshare->current_rsp_rate=0x150; + //SDEBUG("current_rsp_rate=%x\n" ,priv->pshare->current_rsp_rate); + } + }else if(priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G){ + if(priv->pshare->current_rsp_rate!=0x15f){ + RTL_W16(RRSR,0x15f); + priv->pshare->current_rsp_rate=0x15f; + } + } + } +} + +#ifdef RSSI_MIN_ADV_SEL +void collect_min_rssi_data(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + struct priv_shared_info *pshare = priv->pshare; + int i; + + if (0 == pshare->rf_ft_var.rssi_min_advsel) + return; + + for (i = (int)pshare->min_rssi_data_cnt-1; i >= 0; --i) { + if (pstat->rssi < pshare->min_rssi_data[i].rssi) { + if (i != NR_RSSI_MIN_DATA-1) { + memcpy(&pshare->min_rssi_data[i+1], + &pshare->min_rssi_data[i], sizeof(struct rssi_search_entry)); + } + } else + break; + } + + if (i != NR_RSSI_MIN_DATA-1) { + ++i; + pshare->min_rssi_data[i].rssi = pstat->rssi; + pshare->min_rssi_data[i].tx_rate = pstat->current_tx_rate; + pshare->min_rssi_data[i].throughput = + (pstat->tx_avarage + pstat->rx_avarage) >> 17; + if (pshare->min_rssi_data_cnt < NR_RSSI_MIN_DATA) + pshare->min_rssi_data_cnt++; + } +} + +#define RSSI_MIN_LIMIT 15 +void select_rssi_min_from_data(struct rtl8192cd_priv *priv) +{ + struct priv_shared_info *pshare = priv->pshare; + struct rssi_search_entry *entry; + unsigned char rssi_min, rssi_max; + unsigned char loRate; + int FA_counter; + + if (pshare->min_rssi_data_cnt <= 1) { + pshare->rssi_min_prev = pshare->rssi_min; + return; + } + + entry = &pshare->min_rssi_data[0]; + loRate = ((entry->tx_rate <= _9M_RATE_) + || (_MCS0_RATE_ == entry->tx_rate) || (_MCS1_RATE_ == entry->tx_rate)); + rssi_min = entry->rssi; + + rssi_max = pshare->min_rssi_data[pshare->min_rssi_data_cnt-1].rssi; + if ((rssi_min < RSSI_MIN_LIMIT) && (rssi_max >= RSSI_MIN_LIMIT)) + rssi_min = RSSI_MIN_LIMIT; + + FA_counter = ODMPTR->FalseAlmCnt.Cnt_all; + if (loRate || (FA_counter >= 512)) { + if (FA_counter > 2500) + rssi_min = rssi_min + 8; + else + rssi_min = rssi_min + 5; + if (rssi_min > rssi_max) + rssi_min = rssi_max; + } + if (rssi_min + 2 < pshare->rssi_min_prev) + rssi_min = pshare->rssi_min_prev -2; + + pshare->rssi_min = rssi_min; + pshare->rssi_min_prev = pshare->rssi_min; +} +#endif // RSSI_MIN_ADV_SEL + +static void assoc_expire(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + struct list_head *phead, *plist; + unsigned int ok_curr, ok_pre; + unsigned int highest_tp = 0; + struct stat_info *pstat_highest=NULL; + int i,j; + phead = &priv->asoc_list; + plist = phead; + + while ((plist = asoc_list_get_next(priv, plist)) != phead) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + pstat->link_time++; + +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_STATION_STATE) && (pstat->expire_to > 0)) { + if ((priv->pshare->rf_ft_var.sta_mode_ps && !priv->ps_state) || + (!priv->pshare->rf_ft_var.sta_mode_ps && priv->ps_state)) { + if (!priv->ps_state) + priv->ps_state++; + else + priv->ps_state = 0; + + issue_PwrMgt_NullData(priv); + } +#ifdef MULTI_MAC_CLONE + else if (!memcmp(GET_MIB(priv)->dot11OperationEntry.hwaddr, pstat->sa_addr, MACADDRLEN)) // repeater send null packet + { + if (--priv->repeater_to == 0) + { + issue_NullData(priv, pstat->hwaddr); + priv->repeater_to = REPEATER_TO / HZ; + } + } +#endif + } +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + // free queued TX packets if STA keep sleeping a long time + if ((pstat->state & WIFI_SLEEP_STATE) && pstat->expire_to) { + if (time_after(jiffies, pstat->sleep_time+10*HZ)) { + free_sta_tx_skb(priv, pstat); + pstat->sleep_time = jiffies; + } + } +#endif + + // Check idle using packet transmit....nctu note it + ok_curr = pstat->tx_pkts - pstat->tx_fail; + ok_pre = pstat->tx_pkts_pre - pstat->tx_fail_pre; +#ifdef LAZY_WDS + if ((!(pstat->state & WIFI_WDS) && + (ok_curr == ok_pre) && + (pstat->rx_pkts == pstat->rx_pkts_pre)) || + ((pstat->state & WIFI_WDS_LAZY) && + ((pstat->rx_pkts == pstat->rx_pkts_pre) && !pstat->beacon_num))) +#else + if ((ok_curr == ok_pre) && + (pstat->rx_pkts == pstat->rx_pkts_pre)) +#endif + { + pstat->idle_count++; + if (pstat->expire_to > 0) + { + // free queued skb if sta is idle longer than 5 seconds + if ((priv->expire_to - pstat->expire_to) == 5){ + pstat->idle_count = 0; + free_sta_skb(priv, pstat); + for (i=0; i<8; i++) + for (j=0; jtpcache[i][j] = 0xffff; + pstat->tpcache_mgt = 0xffff; + } + + if(pstat->idle_count >= 5) { + pstat->idle_count = 0; + free_sta_tx_skb(priv, pstat); + } + + // calculate STA number + if ((pstat->expire_to == 1) +#ifdef WDS +#ifdef LAZY_WDS + && (!(pstat->state & WIFI_WDS) || (pstat->state & WIFI_WDS_LAZY)) +#else + && !(pstat->state & WIFI_WDS) +#endif +#endif + ) { + +#ifdef LAZY_WDS + if (!(pstat->state & WIFI_WDS_LAZY)) +#endif + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + } + + // CAM entry update + if (!SWCRYPTO && pstat->dot11KeyMapping.keyInCam) { + if (CamDeleteOneEntry(priv, pstat->hwaddr, 0, 0)) { + pstat->dot11KeyMapping.keyInCam = FALSE; + pstat->tmp_rmv_key = TRUE; + priv->pshare->CamEntryOccupied--; + } + #if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + if (CamDeleteOneEntry(priv, pstat->hwaddr, 0, 0)) { + pstat->dot11KeyMapping.keyInCam = FALSE; + pstat->tmp_rmv_key = TRUE; + priv->pshare->CamEntryOccupied--; + } + #endif + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + sleep_list_del(priv, pstat); +#endif + release_remapAid(priv, pstat); + + LOG_MSG("A STA is expired - %02X:%02X:%02X:%02X:%02X:%02X\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if ((OPMODE & WIFI_AP_STATE) && priv->sta_status_cb_func) + priv->sta_status_cb_func("wlan0", pstat->hwaddr, WIFI_STA_STATUS_EXPIRED); +#endif + +#ifdef LAZY_WDS + if (pstat->state & WIFI_WDS_LAZY) { + asoc_list_unref(priv, pstat); + delete_wds_entry(priv, pstat); + return; + } +#endif + } + + pstat->expire_to--; + + if (pstat->expire_to == 0) { +#if defined(BR_SHORTCUT) && defined(RTL_CACHED_BR_STA) + release_brsc_cache(pstat->hwaddr); +#endif + +#ifdef P2P_SUPPORT + if ((OPMODE & WIFI_P2P_SUPPORT) && (P2PMODE == P2P_TMP_GO)) { + if (pstat->is_p2p_client) { + P2P_DEBUG("p2p client leaved excced %d seconds\n", P2P_CLIENT_ASSOC_EXPIRE); + p2p_client_remove(priv, pstat); + } + } +#endif +#ifdef BEAMFORMING_SUPPORT + if ((priv->pmib->dot11RFEntry.txbf == 1) && (GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv) == VERSION_8192E || GET_CHIP_VER(priv) == VERSION_8814A) ) + { + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + pBeamformingInfo->CurDelBFerBFeeEntrySel = BFerBFeeEntry; + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s,\n", __FUNCTION__)); + + if(Beamforming_DeInitEntry(priv, pstat->hwaddr)) + Beamforming_Notify(priv); + } +#endif + +#ifdef MULTI_MAC_CLONE + { + struct list_head *ptmp = plist->next; + unsigned char ucChk = 0; + if (plist == plist->next){ + ucChk = 1; + } + if (OPMODE & WIFI_STATION_STATE) { + __del_mclone_addr(priv, pstat->sa_addr); + }else{ + issue_deauth(priv, pstat->hwaddr, _RSON_DEAUTH_STA_LEAVING_); + free_stainfo(priv, pstat); + } + + if (ucChk == 1){ + break; + }else{ + plist = ptmp; + continue; + } + } +#endif + } + } + else { + free_sta_tx_skb(priv, pstat); + } + } + else + { + pstat->idle_count = 0; +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + /* + * pass rssi info to f/w + */ +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if(CHIP_VER_92X_SERIES(priv)) { + if (pstat->sta_in_firmware == 1) + add_update_rssi(priv, pstat); + } +#endif + } +#endif + + if (priv->pshare->rf_ft_var.rssi_dump && !(priv->up_time % priv->pshare->rf_ft_var.rssi_dump)) { + unsigned char mimorssi[2]; +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + mimorssi[0] = pstat->rf_info.mimorssi[0]; + mimorssi[1] = pstat->rf_info.mimorssi[1]; + } +#endif +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + mimorssi[0] = pstat->rf_info.mimorssi[0]; + mimorssi[1] = pstat->rf_info.mimorssi[1]; + } +#endif + + { + unsigned int FA_total_cnt=0; + unsigned int CCA_total_cnt=0; + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + FA_total_cnt = ODMPTR->FalseAlmCnt.Cnt_all; + CCA_total_cnt = ODMPTR->FalseAlmCnt.Cnt_CCA_all; + } +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + FA_total_cnt = priv->pshare->FA_total_cnt; + CCA_total_cnt = priv->pshare->CCA_total_cnt; + } +#endif + +#if 1 //txforce + if(priv->pshare->rf_ft_var.txforce != 0xff) + { + unsigned char txforce = priv->pshare->rf_ft_var.txforce; + unsigned char dot11_rate_table[]={2,4,11,22,12,18,24,36,48,72,96,108,0}; + + panic_printk("[%d] %d%% txforce %s%s%s%s%s%d%s rx %s%s%s%s%s%d%s (ss %d %d)(FA %d)(CCA %d)(DIG 0x%x)(TP %d,%d)", + pstat->aid, pstat->rssi, + ((txforce >= 44)) ? "VHT " : "", + ((txforce >= 12) && (txforce < 44))? "MCS" : "", + ((txforce >= 44) && (txforce < 54)) ? "NSS1 " : "", + ((txforce >= 54) && (txforce < 64)) ? "NSS2 " : "", + ((txforce >= 64) && (txforce < 74)) ? "NSS3 " : "", + (txforce >= 44) ? ((txforce-44)%10):((txforce >= 12)? txforce-12: dot11_rate_table[txforce]/2), + (pstat->ht_current_tx_info&BIT(1))? "s" : " ", + ((pstat->rx_rate) >= VHT_RATE_ID)? "VHT " : "", + ((pstat->rx_rate >=_NSS1_MCS0_RATE_) && (pstat->rx_rate < _NSS2_MCS0_RATE_)) ? "NSS1 " : "", + ((pstat->rx_rate >=_NSS2_MCS0_RATE_) && (pstat->rx_rate < _NSS3_MCS0_RATE_)) ? "NSS2 " : "", + ((pstat->rx_rate >= _NSS3_MCS0_RATE_) && (pstat->rx_rate < _NSS4_MCS0_RATE_)) ? "NSS3 " : "", + ((pstat->rx_rate >= HT_RATE_ID) && (pstat->rx_rate < VHT_RATE_ID))? "MCS" : "", + ((pstat->rx_rate) >= VHT_RATE_ID) ? ((pstat->rx_rate - VHT_RATE_ID)%10) : ((pstat->rx_rate >= HT_RATE_ID)? (pstat->rx_rate - HT_RATE_ID) : pstat->rx_rate/2), + pstat->rx_splcp? "s" : " ", +#ifdef CONFIG_RTL_88E_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8188E)?0: +#endif + mimorssi[0], +#ifdef CONFIG_RTL_88E_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8188E)?0: +#endif + mimorssi[1], + FA_total_cnt, CCA_total_cnt, + RTL_R8(0xc50), + (unsigned int)(pstat->tx_avarage>>17), + (unsigned int)(pstat->rx_avarage>>17)); + } + else +#endif + panic_printk("[%d] %d%% tx %s%s%s%s%s%d%s rx %s%s%s%s%s%d%s (ss %d %d)(FA %d)(CCA %d)(DIG 0x%x)(TP %d,%d)", + pstat->aid, pstat->rssi, + ((pstat->current_tx_rate >= VHT_RATE_ID)) ? "VHT " : "", + ((pstat->current_tx_rate >= HT_RATE_ID) && (pstat->current_tx_rate < VHT_RATE_ID))? "MCS" : "", + ((pstat->current_tx_rate >=_NSS1_MCS0_RATE_) && (pstat->current_tx_rate < _NSS2_MCS0_RATE_)) ? "NSS1 " : "", + ((pstat->current_tx_rate >=_NSS2_MCS0_RATE_) && (pstat->current_tx_rate < _NSS3_MCS0_RATE_)) ? "NSS2 " : "", + ((pstat->current_tx_rate >=_NSS3_MCS0_RATE_) && (pstat->current_tx_rate < _NSS4_MCS0_RATE_)) ? "NSS3 " : "", + (pstat->current_tx_rate >= VHT_RATE_ID) ? ((pstat->current_tx_rate - VHT_RATE_ID)%10):((pstat->current_tx_rate >= HT_RATE_ID)? (pstat->current_tx_rate - HT_RATE_ID) : pstat->current_tx_rate/2), + (pstat->ht_current_tx_info&BIT(1))? "s" : " ", + ((pstat->rx_rate) >= VHT_RATE_ID)? "VHT " : "", + ((pstat->rx_rate >=_NSS1_MCS0_RATE_) && (pstat->rx_rate < _NSS2_MCS0_RATE_)) ? "NSS1 " : "", + ((pstat->rx_rate >=_NSS2_MCS0_RATE_) && (pstat->rx_rate < _NSS3_MCS0_RATE_)) ? "NSS2 " : "", + ((pstat->rx_rate >=_NSS3_MCS0_RATE_) && (pstat->rx_rate < _NSS4_MCS0_RATE_)) ? "NSS3 " : "", + ((pstat->rx_rate >= HT_RATE_ID) && (pstat->rx_rate < VHT_RATE_ID))? "MCS" : "", + ((pstat->rx_rate) >= VHT_RATE_ID) ? ((pstat->rx_rate - VHT_RATE_ID)%10) : ((pstat->rx_rate >= HT_RATE_ID)? (pstat->rx_rate-HT_RATE_ID) : pstat->rx_rate/2), + pstat->rx_splcp? "s" : " ", +#ifdef CONFIG_RTL_88E_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8188E)?0: +#endif + mimorssi[0], +#ifdef CONFIG_RTL_88E_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8188E)?0: +#endif + mimorssi[1], + FA_total_cnt, CCA_total_cnt, + RTL_R8(0xc50), + (unsigned int)(pstat->tx_avarage>>17), + (unsigned int)(pstat->rx_avarage>>17)); + } +#ifdef CONFIG_RTL8672 +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + panic_printk("(FA "); + else +#endif + panic_printk("(FA %x,%x ", RTL_R8(0xc50), RTL_R8(0xc58)); + + panic_printk("%d, %d)", +#ifdef INTERFERENCE_CONTROL + priv->pshare->ofdm_FA_total_cnt, +#else + priv->pshare->ofdm_FA_cnt1+priv->pshare->ofdm_FA_cnt2+priv->pshare->ofdm_FA_cnt3+priv->pshare->ofdm_FA_cnt4, +#endif + priv->pshare->cck_FA_cnt); +#endif + panic_printk("\n"); + } + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if ((GET_CHIP_VER(priv) == VERSION_8188E) && priv->pmib->dot11StationConfigEntry.autoRate) +#ifdef RATEADAPTIVE_BY_ODM + ODMPTR->RAInfo[pstat->aid].RssiStaRA = pstat->rssi; +#else + priv->pshare->RaInfo[pstat->aid].RssiStaRA = pstat->rssi; +#endif +#endif +#ifdef MCR_WIRELESS_EXTEND +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv) && (pstat->IOTPeer == HT_IOT_PEER_CMW)) { + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + } +#endif +#endif + + // calculate STA number + if ((pstat->expire_to == 0) +#ifdef WDS + && !(pstat->state & WIFI_WDS) +#endif + ) { + cnt_assoc_num(priv, pstat, INCREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, INCREASE); + + // CAM entry update + if (!SWCRYPTO) { + if (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm || + pstat->tmp_rmv_key == TRUE) { + unsigned int privacy = pstat->dot11KeyMapping.dot11Privacy; + + if (CamAddOneEntry(priv, pstat->hwaddr, 0, privacy<<2, 0, + pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKey.skey)) { + pstat->dot11KeyMapping.keyInCam = TRUE; + pstat->tmp_rmv_key = FALSE; + priv->pshare->CamEntryOccupied++; + assign_aggre_mthod(priv, pstat); + } + else { + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + } + + // Resume Ratid +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + if (pstat->sta_in_firmware == 1) { + RTL8188E_MACID_NOLINK(priv, 0, REMAP_AID(pstat)); + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + } else +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + UpdateHalRAMask8812(priv, pstat, 3); + else +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + else +#endif + { +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if(CHIP_VER_92X_SERIES(priv)) + add_update_RATid(priv, pstat); +#endif + } + + //pstat->dwngrade_probation_idx = pstat->upgrade_probation_idx = 0; // unused + LOG_MSG("A expired STA is resumed - %02X:%02X:%02X:%02X:%02X:%02X\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + } + +#ifdef P2P_SUPPORT + if( OPMODE&WIFI_P2P_SUPPORT && (P2PMODE==P2P_TMP_GO) ){ + if(pstat->is_p2p_client) + pstat->expire_to = P2P_CLIENT_ASSOC_EXPIRE; + + }else +#endif + { + pstat->expire_to = priv->expire_to; + } + + } + +#if defined(RTK_AC_SUPPORT) + // operating mode notification + void issue_op_mode_notify(struct rtl8192cd_priv *priv, struct stat_info *pstat, char mode); + if(priv->pshare->rf_ft_var.opmtest&2) { + issue_op_mode_notify(priv, pstat, priv->pshare->rf_ft_var.oper_mode_field); + priv->pshare->rf_ft_var.opmtest &= 1; + } +#endif + +#ifdef WDS + if (pstat->state & WIFI_WDS) { + if ((pstat->rx_pkts != pstat->rx_pkts_pre) || pstat->beacon_num) + pstat->idle_time = 0; + else + pstat->idle_time++; + + if ((priv->up_time%2) == 0) { + if ((pstat->beacon_num == 0) && (pstat->state & WIFI_WDS_RX_BEACON)) + pstat->state &= ~WIFI_WDS_RX_BEACON; + if (pstat->beacon_num) + pstat->beacon_num = 0; + } + } +#endif + // update proc bssdesc + if ((OPMODE & WIFI_STATION_STATE) && !memcmp(priv->pmib->dot11Bss.bssid, pstat->hwaddr, MACADDRLEN)) { + priv->pmib->dot11Bss.rssi = pstat->rssi; + priv->pmib->dot11Bss.sq = pstat->sq; + } + +#ifdef BEAMFORMING_SUPPORT + if ((priv->pmib->dot11RFEntry.txbfer == 1) && ((priv->up_time % 3) == 0) && + (GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv) == VERSION_8192E || GET_CHIP_VER(priv) == VERSION_8814A) ) { + pstat->bf_score = 0; + if((pstat->ht_cap_len && (cpu_to_le32(pstat->ht_cap_buf.txbf_cap)&_HTCAP_RECEIVED_NDP)) // +#ifdef RTK_AC_SUPPORT + || (pstat->vht_cap_len && (cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & (BIT(SU_BFEE_S)|BIT(SU_BFER_S)))) +#endif + ) { + if( ( pstat->rssi > 10) && + ( pstat->rx_pkts != pstat->rx_pkts_pre) && +#ifdef DETECT_STA_EXISTANCE + (!(pstat->leave)) +#endif + ){ + u1Byte Idx = 0; + PRT_BEAMFORMING_ENTRY pEntry, pBfeeEntry; + pEntry = Beamforming_GetEntryByMacId(priv, pstat->aid, &Idx); + if(pEntry == NULL) { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, Beamforming_GetFreeBFeeEntry\n", __FUNCTION__)); + pBfeeEntry = Beamforming_GetFreeBFeeEntry(priv, &Idx, pstat->hwaddr); + if(pBfeeEntry) + Beamforming_Enter(priv, pstat); + } + } + pstat->bf_score = 100 - pstat->rssi; + if(pstat->tx_byte_cnt> (1<<16)) { // 0.5M bps + pstat->bf_score += 100; + } + if((priv->pmib->dot11nConfigEntry.dot11nLDPC) && (pstat) && + ((pstat->ht_cap_len && cpu_to_le16(pstat->ht_cap_buf.ht_cap_info) & _HTCAP_SUPPORT_RX_LDPC_) +#ifdef RTK_AC_SUPPORT + || (pstat->vht_cap_len && (cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & BIT(RX_LDPC_E))) +#endif + )) + pstat->bf_score -=2; + if(priv->pmib->dot11nConfigEntry.dot11nSTBC && + ((pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_RX_STBC_CAP_)) +#ifdef RTK_AC_SUPPORT + || (pstat->vht_cap_buf.vht_cap_info & cpu_to_le32(_VHTCAP_RX_STBC_CAP_)) +#endif + )) { + pstat->bf_score -=5; + if(!(pstat->MIMO_ps & _HT_MIMO_PS_STATIC_)) { +#ifdef RTK_AC_SUPPORT + if (pstat->vht_cap_len) { + if(((le32_to_cpu(pstat->vht_cap_buf.vht_support_mcs[0]) >> 2) & 3) != 3) + pstat->bf_score -=3; + } else +#endif + { + pstat->tx_ra_bitmap = 0; + if (pstat->ht_cap_len) { + for (i=0; i<16; i++) { + if (pstat->ht_cap_buf.support_mcs[i/8] & BIT(i%8)) + pstat->tx_ra_bitmap |= BIT(i+12); + } + if(pstat->tx_ra_bitmap & 0x0ff00000) + pstat->bf_score -=3; + } + } + } + } + } + } +#endif + + pstat->tx_pkts_pre = pstat->tx_pkts; + pstat->rx_pkts_pre = pstat->rx_pkts; + pstat->tx_fail_pre = pstat->tx_fail; + + if ((priv->up_time % 3) == 0) { +#ifndef DRVMAC_LB +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) + if (is_auto_rate(priv, pstat) + || (should_restrict_Nrate(priv, pstat) && is_fixedMCSTxRate(priv, pstat))) + check_RA_by_rssi(priv, pstat); +#endif +#endif + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if(CHIP_VER_92X_SERIES(priv)) + check_txrate_by_reg(priv, pstat); +#endif + + /*Now 8812 use txreport for get txreport and inital tx rate*/ + #if 0 //defined(CONFIG_RTL_8812_SUPPORT) + if(GET_CHIP_VER(priv)==VERSION_8812E){ + check_txrate_by_reg_8812(priv, pstat); + } + #endif + + /* + * Check if station is 2T + */ + if (!pstat->is_2t_mimo_sta && (pstat->highest_rx_rate >= _MCS8_RATE_)) + pstat->is_2t_mimo_sta = TRUE; +#ifdef RTK_AC_SUPPORT + // Dynamic Enable/Disable LDPC + if((pstat->IOTPeer == HT_IOT_PEER_REALTEK_8812) && + (pstat->WirelessMode & (WIRELESS_MODE_AC_5G|WIRELESS_MODE_AC_24G)) && + ( (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_ | _HTCAP_SHORTGI_40M_)) + || ( cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & BIT(SHORT_GI80M_E)) + )){ + const char thd = 45; +#ifdef MCR_WIRELESS_EXTEND + thd = priv->pshare->rf_ft_var.disable_ldpc_thd; +#endif + if (!pstat->disable_ldpc && pstat->rssi> thd+5) + pstat->disable_ldpc=1; + else if(pstat->disable_ldpc && pstat->rssi disable_ldpc=0; + } +#endif +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST +if(!IS_OUTSRC_CHIP(priv)) +#endif +{ + + /* + * Check if station is near by to use lower tx power + */ + if((priv->pshare->FA_total_cnt > 1000) || (priv->pshare->FA_total_cnt > 300 && (RTL_R8(0xc50) & 0x7f) >= 0x32)) { + pstat->hp_level = 0; + } else { + if (priv->pshare->rf_ft_var.tx_pwr_ctrl) { + if ((pstat->hp_level == 0) && (pstat->rssi > HP_LOWER+4)){ + pstat->hp_level = 1; + }else if ((pstat->hp_level == 1) && (pstat->rssi < (HP_LOWER - 4) )){ + pstat->hp_level = 0; + } + } + } +} +#endif + } + { + const char thd = 30; + if (!pstat->no_rts && pstat->rssi>thd+5) + pstat->no_rts=1; + else if(pstat->no_rts && pstat->rssino_rts=0; + } + + if (pstat->IOTPeer == HT_IOT_PEER_INTEL) + { +#if 0//def CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) { + if ((((priv->ext_stats.tx_avarage>>17) + (priv->ext_stats.rx_avarage>>17)) > 80) && (pstat->no_rts == 1)) + pstat->no_rts = 0; + else if ((((priv->ext_stats.tx_avarage>>17) + (priv->ext_stats.rx_avarage>>17)) < 60) && (pstat->no_rts == 0)) + pstat->no_rts = 1; + } +#endif +#if 0//def CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + const char thd = 20; + if (!pstat->no_rts && pstat->rssino_rts=1; + else if(pstat->no_rts && pstat->rssi>thd+5) + pstat->no_rts=0; + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8812E) { + const char thd = 40; + if (!pstat->no_rts && (pstat->rssi < thd)) + { + pstat->no_rts=1; + //printk("Disable rts !!\n"); + } + else if(pstat->no_rts && (pstat->rssi > (thd+5))) + { + pstat->no_rts=0; + //printk("Enable rts !!\n"); + } + } +#endif + + /* Count every Intel clients with complying throughput margin */ + if ((pstat->tx_byte_cnt + pstat->rx_byte_cnt) >= priv->pshare->rf_ft_var.intel_rtylmt_tp_margin) + priv->pshare->intel_active_sta++; + } +#if 0 +//#ifdef AC2G_256QAM + { + if ( (is_ac2g(priv)) && (GET_CHIP_VER(priv)==VERSION_8812E) ) + { + if (pstat->rssi < priv->pshare->rf_ft_var.ac2g_thd_ldpc) + { + priv->pmib->dot11nConfigEntry.dot11nLDPC = 1; + } + else if(pstat->rssi > (priv->pshare->rf_ft_var.ac2g_thd_ldpc+5)) + { + priv->pmib->dot11nConfigEntry.dot11nLDPC = 0; + } + } + } +#endif + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + ChooseIotMainSTA(priv, pstat); +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + choose_IOT_main_sta(priv, pstat); +#endif + +#ifdef SW_TX_QUEUE + { + int i; + for (i=BK_QUEUE;i<=VO_QUEUE;i++) + { + int q_aggnumIncSlow = (priv->assoc_num > 1) ? (2+pstat->swq.q_aggnumIncSlow[i]) : (1+pstat->swq.q_aggnumIncSlow[i]); + //int q_aggnumIncSlow = (1+pstat->swq.q_aggnumIncSlow[i]); +#if 1//def SW_TX_QUEUE_SMALL_PACKET_CHECK + if ((priv->swq_en == 0) /*|| (((priv->ext_stats.tx_avarage>>17) + (priv->ext_stats.rx_avarage>>17)) < 20)*/) { // disable check for small udp packet(88B) test with veriwave tool +#else + if ((priv->swq_en == 0) || (((priv->ext_stats.tx_avarage>>17) + (priv->ext_stats.rx_avarage>>17)) < 20)) { +#endif + //pstat->swq.q_aggnum[i] = priv->pshare->rf_ft_var.swq_aggnum; + + pstat->swq.q_aggnumIncSlow[i] = 0; + } + else if (((priv->up_time % q_aggnumIncSlow) == 0) && ((priv->swqen_keeptime != 0) && (priv->up_time > priv->swqen_keeptime+3)) && (pstat->tx_avarage > 25000) && (pstat->ht_cap_len)) { +#ifdef SMP_SYNC + unsigned long x=0; +#endif + //SMP_LOCK(x); + adjust_swq_setting(priv, pstat, i, CHECK_INC_AGGN); + //SMP_UNLOCK(x); + } + /*clear used*/ + pstat->swq.q_used[i] = 0; + pstat->swq.q_TOCount[i] = 0; + } + } +#endif + // calculate tx/rx throughput + pstat->tx_avarage = (pstat->tx_avarage/10)*7 + (pstat->tx_byte_cnt/10)*3; + pstat->tx_byte_cnt_LowMAW = (pstat->tx_byte_cnt_LowMAW/10)*1 + (pstat->tx_byte_cnt/10)*9; + pstat->tx_byte_cnt = 0; + pstat->rx_avarage = (pstat->rx_avarage/10)*7 + (pstat->rx_byte_cnt/10)*3; + pstat->rx_byte_cnt_LowMAW = (pstat->rx_byte_cnt_LowMAW/10)*1 + (pstat->rx_byte_cnt/10)*9; + pstat->rx_byte_cnt = 0; + +#ifdef PREVENT_BROADCAST_STORM + // reset rx_pkts_bc in every one second + pstat->rx_pkts_bc = 0; +#endif + if ((pstat->tx_avarage + pstat->rx_avarage) > highest_tp) { + highest_tp = pstat->tx_avarage + pstat->rx_avarage; + pstat_highest = pstat; + } +#if defined(HW_ANT_SWITCH)&&( defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + if(HW_DIV_ENABLE) + dm_STA_Ant_Select(priv, pstat); +#endif + + /* + * Broadcom, Intel IOT, dynamic inc or dec retry count + */ + + + if ((pstat->IOTPeer == HT_IOT_PEER_BROADCOM) || (pstat->IOTPeer == HT_IOT_PEER_INTEL)) + { + if((pstat->tx_avarage + pstat->rx_avarage >= RETRY_TRSHLD_H) && (pstat->retry_inc == 0)) + { +#ifdef TX_SHORTCUT + clearTxShortCutBufSize(priv, pstat); +#endif + pstat->retry_inc = 1; + } + else if((pstat->tx_avarage + pstat->rx_avarage < RETRY_TRSHLD_L) && (pstat->retry_inc == 1)) + { +#ifdef TX_SHORTCUT + clearTxShortCutBufSize(priv, pstat); +#endif + pstat->retry_inc = 0; + } + } + + if (((int)pstat->expire_to > ((int)priv->expire_to - priv->pshare->rf_ft_var.rssi_expire_to)) +#ifdef DETECT_STA_EXISTANCE + && (!pstat->leave) +#endif + ) + { + if (pstat->rssi < priv->pshare->rssi_min) + priv->pshare->rssi_min = pstat->rssi; +#ifdef RSSI_MIN_ADV_SEL + collect_min_rssi_data(priv, pstat); +#endif + } + +#ifdef MCR_WIRELESS_EXTEND + if (pstat->IOTPeer == HT_IOT_PEER_CMW) + priv->pshare->rssi_min = pstat->rssi; +#endif + /* + * Periodically clear ADDBAreq sent indicator + */ + if ((pstat->expire_to > 0) && pstat->ht_cap_len && (pstat->aggre_mthd & AGGRE_MTHD_MPDU)) + memset(pstat->ADDBA_sent, 0, 8); + +#if defined(INCLUDE_WPA_PSK) && !defined(WIFI_HAPD) && (!defined(RTK_NL80211) || defined(NON_NL80211_AP)) //update unicast key by hostapd ! + // Update unicast key + if (priv->pmib->dot1180211AuthEntry.dot11UKRekeyTime) + { + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) { + if (pstat->uk_timeout) + pstat->uk_timeout --; + else { + if (pstat->wpa_sta_info->state == PSK_STATE_PTKINITDONE) + UKRekeyTimeout(priv, pstat); + } + } + } +#endif + + if (plist == plist->next) + break; + } + + + /*dynamic tuning response date rate*/ +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef MP_TEST + if (!((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) +#endif + { + if (priv->up_time % 2){ + if(priv->pshare->rssi_min!=0xff){ + dynamic_response_rate(priv, priv->pshare->rssi_min); + } + } + } + } + + +#if defined(HW_ANT_SWITCH)&&( defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + if(HW_DIV_ENABLE) { + dm_HW_IdleAntennaSelect(priv); + } +#endif + + /* + * Intel IOT, dynamic enhance beacon tx AGC + */ + pstat = pstat_highest; + + if (pstat && pstat->IOTPeer == HT_IOT_PEER_INTEL) + { + const char thd = 25; + if (!priv->bcnTxAGC) { + if (pstat->rssi < thd) + priv->bcnTxAGC = 2; + else if (pstat->rssi < thd+5) + priv->bcnTxAGC = 1; + } else if (priv->bcnTxAGC == 1) { + if (pstat->rssi < thd) + priv->bcnTxAGC = 2; + else if (pstat->rssi > thd+10) + priv->bcnTxAGC = 0; + } else if (priv->bcnTxAGC == 2) { + if (pstat->rssi > thd+10) + priv->bcnTxAGC = 0; + else if (pstat->rssi > thd+5) + priv->bcnTxAGC = 1; + } + } else { + if (priv->bcnTxAGC) + priv->bcnTxAGC = 0; + } +} + + +#ifdef WDS +static void wds_probe_expire(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + unsigned int i; + + if ((priv->up_time % 30) != 5) + return; + + for (i = 0; i < priv->pmib->dot11WdsInfo.wdsNum; i++) { + pstat = get_stainfo(priv, priv->pmib->dot11WdsInfo.entry[i].macAddr); + if (pstat) { + if (pstat->wds_probe_done) + continue; + issue_probereq(priv, NULL, 0, pstat->hwaddr); + } + } +} +#endif + +int check_adaptivity_test(struct rtl8192cd_priv *priv) +{ + unsigned int value32; + + if ( !priv->pshare->rf_ft_var.adaptivity_enable ) + return 0; + +#ifdef USE_OUT_SRC + if (IS_OUTSRC_CHIP(priv)) + { + if (ODMPTR->SupportICType & ODM_IC_11N_SERIES) + { + ODM_SetBBReg(ODMPTR,ODM_REG_DBG_RPT_11N, bMaskDWord, 0x208); + value32 = ODM_GetBBReg(ODMPTR, ODM_REG_RPT_11N, bMaskDWord); + } + else if (ODMPTR->SupportICType & ODM_IC_11AC_SERIES) + { + ODM_SetBBReg(ODMPTR,ODM_REG_DBG_RPT_11AC, bMaskDWord, 0x209); + value32 = ODM_GetBBReg(ODMPTR,ODM_REG_RPT_11AC, bMaskDWord); + } + + if ((value32 & BIT30) && (ODMPTR->SupportICType & (ODM_RTL8723B|ODM_RTL8188E))) + return 1; + else if(value32 & BIT29) + return 1; + else + return 0; + } + else +#endif + { + PHY_SetBBReg(priv,0x908, bMaskDWord, 0x208); + value32 = PHY_QueryBBReg(priv, 0xdf4, bMaskDWord); + + if(value32 & BIT29) + return 1; + else + return 0; + } +} + +#ifdef CHECK_HANGUP +#ifdef CONFIG_PCI_HCI +#ifdef CHECK_TX_HANGUP +static int check_tx_hangup(struct rtl8192cd_priv *priv, int q_num, int *pTail, int *pIsEmpty) +{ + struct tx_desc *pdescH, *pdesc; + volatile int head, tail; + struct rtl8192cd_hw *phw; + + phw = GET_HW(priv); + head = get_txhead(phw, q_num); + tail = get_txtail(phw, q_num); + pdescH = get_txdesc(phw, q_num); + + *pTail = tail; + + if (CIRC_CNT_RTK(head, tail, CURRENT_NUM_TX_DESC)) + { + *pIsEmpty = 0; + pdesc = pdescH + (tail); + +#ifdef __MIPSEB__ + pdesc = (struct tx_desc *)KSEG1ADDR(pdesc); +#endif + if (pdesc && ((get_desc(pdesc->Dword0)) & TX_OWN)) // pending + { + // In adaptivity test, we need avoid check tx hang + // if( check_adaptivity_test(priv) ) + // return 0; + // else + return 1; + } + } + else + *pIsEmpty = 1; + + return 0; +} +#endif + + +#ifdef CHECK_RX_HANGUP +static void check_rx_hangup_send_pkt(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + struct list_head *phead = &priv->asoc_list; + struct list_head *plist = phead; + DECLARE_TXINSN(txinsn); + + while ((plist = asoc_list_get_next(priv, plist)) != phead) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + + if (pstat->expire_to > 0) { + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + txinsn.q_num = MANAGE_QUE_NUM; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.fr_type = _PRE_ALLOCHDR_; + txinsn.phdr = get_wlanhdr_from_poll(priv); + txinsn.pframe = NULL; + + if (txinsn.phdr == NULL) + goto send_test_pkt_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + SetFrameSubType(txinsn.phdr, WIFI_DATA_NULL); + + if (OPMODE & WIFI_AP_STATE) { + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), pstat->hwaddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + } + else { + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), pstat->hwaddr, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + } + + txinsn.hdr_len = WLAN_HDR_A3_LEN; + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) { + asoc_list_unref(priv, pstat); + return; + } + +send_test_pkt_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + } + } +} + + +static void check_rx_hangup(struct rtl8192cd_priv *priv) +{ + if (priv->rx_start_monitor_running == 0) { + if (UINT32_DIFF(priv->rx_packets_pre1, priv->rx_packets_pre2) > 20) { + priv->rx_start_monitor_running = 1; + //printk("start monitoring = %d\n", priv->rx_start_monitor_running); + } + } + else if (priv->rx_start_monitor_running == 1) { + if (UINT32_DIFF(priv->net_stats.rx_packets, priv->rx_packets_pre1) == 0) + priv->rx_start_monitor_running = 2; + else if (UINT32_DIFF(priv->net_stats.rx_packets, priv->rx_packets_pre1) < 2 && + UINT32_DIFF(priv->net_stats.rx_packets, priv->rx_packets_pre1) > 0) { + priv->rx_start_monitor_running = 0; + //printk("stop monitoring = %d\n", priv->rx_start_monitor_running); + } + } + + if (priv->rx_start_monitor_running >= 2) { + //printk("\n\n%s %d start monitoring = 2 rx_packets_pre1=%lu; rx_packets_pre2=%lu; net_stats.rx_packets=%lu\n", + //__FUNCTION__, __LINE__, + //priv->rx_packets_pre1, priv->rx_packets_pre2, + //priv->net_stats.rx_packets); + priv->pshare->rx_hang_checking = 1; + priv->pshare->selected_priv = priv;; + } +} + + +static __inline__ void check_rx_hangup_record_rxpkts(struct rtl8192cd_priv *priv) +{ + priv->rx_packets_pre2 = priv->rx_packets_pre1; + priv->rx_packets_pre1 = priv->net_stats.rx_packets; +} +#endif // CHECK_RX_HANGUP + + +#ifdef CONFIG_RTL_92D_DMDP +void reset_dmdp_peer(struct rtl8192cd_priv *from) +{ + extern u32 if_priv[]; + struct rtl8192cd_priv *priv; +#ifdef FAST_RECOVERY + void *info = NULL; +#ifdef UNIVERSAL_REPEATER + void *vxd_info = NULL; +#endif +#endif + +#ifdef MBSSID + int i; + void *vap_info[RTL8192CD_NUM_VWLAN]; + memset(vap_info, 0, sizeof(vap_info)); +#endif + + if (from->pshare->wlandev_idx == 0) + priv = (struct rtl8192cd_priv *)if_priv[1]; + else + priv = (struct rtl8192cd_priv *)if_priv[0]; + + if (priv == NULL) + return; + + if (!netif_running(priv->dev)) + return; + + priv->reset_hangup = 1; +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + GET_VXD_PRIV(priv)->reset_hangup = 1; +#endif +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + priv->pvap_priv[i]->reset_hangup = 1; + } + } +#endif + +#ifdef WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled && + (priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_ || + priv->pmib->dot11WdsInfo.wdsPrivacy == _CCMP_PRIVACY_) ) { + int i; + for (i=0; ipmib->dot11WdsInfo.wdsNum; i++) + if (netif_running(priv->wds_dev[i])) + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[i]|=0x80000000; + } +#endif + +#ifdef FAST_RECOVERY + info = backup_sta(priv); +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + vap_info[i] = backup_sta(priv->pvap_priv[i]); + else + vap_info[i] = NULL; + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + vxd_info = backup_sta(GET_VXD_PRIV(priv)); +#endif +#endif // FAST_RECOVERY + + priv->pmib->dot11OperationEntry.keep_rsnie = 1; +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + priv->pvap_priv[i]->pmib->dot11OperationEntry.keep_rsnie = 1; + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.keep_rsnie = 1; +#endif + + rtl8192cd_close(priv->dev); + rtl8192cd_open(priv->dev); + +#ifdef FAST_RECOVERY + if (info) + restore_backup_sta(priv, info); + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]) && vap_info[i]) + restore_backup_sta(priv->pvap_priv[i], vap_info[i]); + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && vxd_info) + restore_backup_sta(GET_VXD_PRIV(priv), vxd_info); +#endif +#endif // FAST_RECOVERY + +#ifdef CHECK_AFTER_RESET + priv->pshare->reset_monitor_cnt_down = 3; + priv->pshare->reset_monitor_pending = 0; + priv->pshare->reset_monitor_rx_pkt_cnt = priv->net_stats.rx_packets; +#endif +} +#endif + + +int check_hangup(struct rtl8192cd_priv *priv) +{ + unsigned long flags = 0; +#ifdef CHECK_TX_HANGUP + int tail, q_num, is_empty, alive=0; +#endif + int txhangup, rxhangup, beacon_hangup, reset_fail_hangup, fw_error; +#ifdef CONFIG_WLAN_HAL + u4Byte hal_hang_state = 0; +#endif // CONFIG_WLAN_HAL + +#ifdef MBSSID + int i; +#endif +#ifdef FAST_RECOVERY + void *info = NULL; +#ifdef UNIVERSAL_REPEATER + void *vxd_info = NULL; +#endif +#endif // FAST_RECOVERY +#ifdef CHECK_RX_HANGUP + unsigned int rx_cntreg; +#endif + +#ifdef MBSSID + void *vap_info[RTL8192CD_NUM_VWLAN]; + memset(vap_info, 0, sizeof(vap_info)); +#endif + +/* +#if defined(CHECK_BEACON_HANGUP) + unsigned int BcnQ_Val = 0; +#endif +*/ + +// for debug +#if 0 + __DRAM_IN_865X static unsigned char temp_reg_C50, temp_reg_C58, + temp_reg_C60, temp_reg_C68, temp_reg_A0A; + temp_reg_C50 = 0; temp_reg_C58 = 0; temp_reg_C60 = 0; + temp_reg_C68 = 0; temp_reg_A0A = 0; +#endif +//--------------------------------------------------------- +// margin = -1; + + txhangup = rxhangup = beacon_hangup = reset_fail_hangup = fw_error =0; + + +#if defined(CONFIG_WLAN_HAL) + if (IS_HAL_CHIP(priv)) { + +#if defined(CHECK_LX_DMA_ERROR) + if(priv->pshare->rf_ft_var.check_hang & CHECK_LX_DMA_ERROR) { + hal_hang_state = GET_HAL_INTERFACE(priv)->CheckHangHandler(priv); + + switch (hal_hang_state) { + case HANG_VAR_TX_STUCK: + txhangup = 1; + break; + case HANG_VAR_RX_STUCK: + rxhangup = 1; + break; + default: // HANG_VAR_NORMAL + break; + } + } +#endif +#ifdef CHECK_FW_ERROR +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) + if (priv->pshare->rf_ft_var.check_hang & CHECK_FW_ERROR) { + int hmeter, mcutst2; + hmeter = RTL_R8(HMETFR); + mcutst2 = RTL_R16(MCUTST_II); + if( (hmeter == 0xf) && (priv->pshare->mcu_tst2 == mcutst2)) { + if (priv->pshare->mcu_pending_cnt < 15) { + priv->pshare->mcu_pending_cnt++; + } else { + fw_error =1; + } + } else { + priv->pshare->mcu_pending_cnt =0; + } + priv->pshare->mcu_tst2 = mcutst2; + } +#endif +#endif + +#ifdef CHECK_TX_HANGUP + if(priv->pshare->rf_ft_var.check_hang & CHECK_TX_HANGUP) { + if( check_adaptivity_test(priv)) { + for(q_num = 0; q_num<13; q_num++) + if( priv->pshare->Q_info[q_num].pending_tick){ + priv->pshare->Q_info[q_num].pending_tick++; + //panic_printk("%d q_num = %d,pending_tick %d\n",__LINE__,q_num,priv->pshare->Q_info[q_num].pending_tick); + } + } else { + for(q_num = 0; q_num<13; q_num++) { + PHCI_TX_DMA_MANAGER_88XX ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + PHCI_TX_DMA_QUEUE_STRUCT_88XX tx_q = &(ptx_dma->tx_queue[q_num]); + + tail = RTL_R32(tx_q->reg_rwptr_idx); + if( (0xffff & ((tail>>16)^ tail))==0) { + if(priv->pshare->Q_info[q_num].pending_tick) + alive++; + priv->pshare->Q_info[q_num].pending_tick = 0; + } else { + tail = (tail>>16) & 0xffff; + if (priv->pshare->Q_info[q_num].pending_tick && + (tail == priv->pshare->Q_info[q_num].pending_tail) && + (UINT32_DIFF(priv->up_time, priv->pshare->Q_info[q_num].pending_tick) >= PENDING_PERIOD)) { + txhangup++; + // break; + } + + if ((priv->pshare->Q_info[q_num].pending_tick == 0) || + (tail != priv->pshare->Q_info[q_num].pending_tail)) { + if (tail != priv->pshare->Q_info[q_num].pending_tail) + alive++; + priv->pshare->Q_info[q_num].pending_tick = priv->up_time; + priv->pshare->Q_info[q_num].pending_tail = tail; + } + priv->pshare->Q_info[q_num].idle_tick = 0; + // break; + } + } + if(alive) { + txhangup =0; + for(q_num = 0; q_num<13; q_num++) + priv->pshare->Q_info[q_num].pending_tick = 0; + } + } + } +#endif + + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif // CONFIG_WLAN_HAL + { +#ifdef CHECK_TX_HANGUP + // we check Q5, Q0, Q4, Q3, Q2, Q1 + if(priv->pshare->rf_ft_var.check_hang & CHECK_TX_HANGUP) { + if( check_adaptivity_test(priv)) { + for(q_num = 0; q_num<=5; q_num++){ + if( priv->pshare->Q_info[q_num].pending_tick){ + priv->pshare->Q_info[q_num].pending_tick++; + //panic_printk("%d q_num = %d,pending_tick %d\n",__LINE__,q_num,priv->pshare->Q_info[q_num].pending_tick); + } + } + } else { + for(q_num = 0; q_num<=5; q_num++) { + + if (check_tx_hangup(priv, q_num, &tail, &is_empty)) { + if (priv->pshare->Q_info[q_num].pending_tick && + (tail == priv->pshare->Q_info[q_num].pending_tail) && + (UINT32_DIFF(priv->up_time, priv->pshare->Q_info[q_num].pending_tick) >= PENDING_PERIOD)) { + // the stopping is over the period => hangup! + txhangup++; + // break; + } + + if ((priv->pshare->Q_info[q_num].pending_tick == 0) || + (tail != priv->pshare->Q_info[q_num].pending_tail)) { + if(tail != priv->pshare->Q_info[q_num].pending_tail) + alive++; + // the first time stopping or the tail moved + priv->pshare->Q_info[q_num].pending_tick = priv->up_time; + priv->pshare->Q_info[q_num].pending_tail = tail; + } + priv->pshare->Q_info[q_num].idle_tick = 0; + // break; + } + else { + if(priv->pshare->Q_info[q_num].pending_tick) + alive++; + else if (tail != priv->pshare->Q_info[q_num].pending_tail) + alive++; + priv->pshare->Q_info[q_num].pending_tail = tail; + // empty or own bit is cleared + priv->pshare->Q_info[q_num].pending_tick = 0; + if (!is_empty && + priv->pshare->Q_info[q_num].idle_tick && + (tail == priv->pshare->Q_info[q_num].pending_tail) && + (UINT32_DIFF(priv->up_time, priv->pshare->Q_info[q_num].idle_tick) >= PENDING_PERIOD)) { + // own bit is cleared, but the tail didn't move and is idle over the period => call DSR +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { +#ifdef __ECOS + priv->pshare->call_dsr = 1; +#else + tasklet_schedule(&priv->pshare->tx_tasklet); +#endif + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else +#ifdef __ECOS + priv->pshare->has_triggered_tx_tasklet = 1; + priv->pshare->call_dsr = 1; +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif +#endif + priv->pshare->Q_info[q_num].idle_tick = 0; + // break; + } + else { + if (is_empty) + priv->pshare->Q_info[q_num].idle_tick = 0; + else { + if ((priv->pshare->Q_info[q_num].idle_tick == 0) || + (tail != priv->pshare->Q_info[q_num].pending_tail)) { + // the first time idle, or the own bit is cleared and the tail moved + priv->pshare->Q_info[q_num].idle_tick = priv->up_time; + priv->pshare->Q_info[q_num].pending_tail = tail; + // break; + } + } + } + } + + } + if(alive) { + txhangup =0; + for(q_num = 0; q_num<=5; q_num++) + priv->pshare->Q_info[q_num].pending_tick = 0; + } + } + } +#endif + } + +#ifdef CHECK_RX_HANGUP + // check for rx stop + if (txhangup == 0) { + if ((priv->assoc_num > 0 +#ifdef WDS + || priv->pmib->dot11WdsInfo.wdsEnabled +#endif + ) && !priv->pshare->rx_hang_checking) + check_rx_hangup(priv); + +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && + GET_VXD_PRIV(priv)->assoc_num > 0 && + !priv->pshare->rx_hang_checking) + check_rx_hangup(GET_VXD_PRIV(priv)); +#endif +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]) && + priv->pvap_priv[i]->assoc_num > 0 && + !priv->pshare->rx_hang_checking) + check_rx_hangup(priv->pvap_priv[i]); + } + } +#endif + + if (priv->pshare->rx_hang_checking) + { + if (priv->pshare->rx_cntreg_log == 0) + priv->pshare->rx_cntreg_log = RTL_R32(_RXPKTNUM_); + else { + rx_cntreg = RTL_R32(_RXPKTNUM_); + if (priv->pshare->rx_cntreg_log == rx_cntreg) { + if (priv->pshare->rx_stop_pending_tick) { + if (UINT32_DIFF(priv->pshare->selected_priv->up_time, priv->pshare->rx_stop_pending_tick) >= (PENDING_PERIOD-1)) { + rxhangup++; + //printk("\n\n%s %d rxhangup++ rx_packets_pre1=%lu; rx_packets_pre2=%lu; net_stats.rx_packets=%lu\n", + //__FUNCTION__, __LINE__, + //priv->pshare->selected_priv->rx_packets_pre1, priv->pshare->selected_priv->rx_packets_pre2, + //priv->pshare->selected_priv->net_stats.rx_packets); + } + } + else { + priv->pshare->rx_stop_pending_tick = priv->pshare->selected_priv->up_time; + RTL_W32(_RCR_, RTL_R32(_RCR_) | _ACF_); + check_rx_hangup_send_pkt(priv->pshare->selected_priv); + //printk("\n\ncheck_rx_hangup_send_pkt!\n"); + //printk("%s %d rx_packets_pre1=%lu; rx_packets_pre2=%lu; net_stats.rx_packets=%lu\n", + //__FUNCTION__, __LINE__, + //priv->pshare->selected_priv->rx_packets_pre1, priv->pshare->selected_priv->rx_packets_pre2, + //priv->pshare->selected_priv->net_stats.rx_packets); + } + } + else { + //printk("\n\n%s %d Recovered!\n" ,__FUNCTION__, __LINE__); + priv->pshare->rx_hang_checking = 0; + priv->pshare->rx_cntreg_log = 0; + priv->pshare->selected_priv = NULL; + priv->rx_start_monitor_running = 0; +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + GET_VXD_PRIV(priv)->rx_start_monitor_running = 0; +#endif +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + priv->pvap_priv[i]->rx_start_monitor_running = 0; + } + } +#endif + + if (priv->pshare->rx_stop_pending_tick) { + priv->pshare->rx_stop_pending_tick = 0; + RTL_W32(_RCR_, RTL_R32(_RCR_) & (~_ACF_)); + } + } + } + } + + if (rxhangup == 0) { + if (priv->assoc_num > 0) + check_rx_hangup_record_rxpkts(priv); + else if (priv->rx_start_monitor_running) { + priv->rx_start_monitor_running = 0; + //printk("stop monitoring = %d\n", priv->rx_start_monitor_running); + } +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) { + if (GET_VXD_PRIV(priv)->assoc_num > 0) + check_rx_hangup_record_rxpkts(GET_VXD_PRIV(priv)); + else if (GET_VXD_PRIV(priv)->rx_start_monitor_running) { + GET_VXD_PRIV(priv)->rx_start_monitor_running = 0; + //printk("stop monitoring = %d\n", GET_VXD_PRIV(priv)->rx_start_monitor_running); + } + } +#endif +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) { + if (priv->pvap_priv[i]->assoc_num > 0) + check_rx_hangup_record_rxpkts(priv->pvap_priv[i]); + else if (priv->pvap_priv[i]->rx_start_monitor_running) { + priv->pvap_priv[i]->rx_start_monitor_running = 0; + //printk("stop monitoring = %d\n", priv->pvap_priv[i]->rx_start_monitor_running); + } + } + } + } +#endif + } + } +#endif // CHECK_RX_HANGUP + +#ifdef CHECK_RX_DMA_ERROR + if(priv->pshare->rf_ft_var.check_hang & CHECK_RX_DMA_ERROR) + if((GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) + || (GET_CHIP_VER(priv)==VERSION_8192D)|| (GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8192E)) + { + int rxffptr, rxffpkt; + + rxffptr = RTL_R16(RXFF_PTR+2); + rxffpkt = RTL_R8(RXPKT_NUM+3); + + if((rxffptr%0x80) && rxffpkt && (RTL_R8(RXPKT_NUM+2)^2)){ + if( (priv->pshare->rx_byte_cnt == priv->net_stats.rx_bytes) && + !((rxffptr ^ priv->pshare->rxff_rdptr)|(rxffpkt ^ priv->pshare->rxff_pkt))) { + if (priv->pshare->rx_dma_err_cnt < 15) { // continue for 15 seconds + priv->pshare->rx_dma_err_cnt++; + } else { + unsigned char tmp; + tmp = RTL_R8(0x1c); + + // Turn OFF BIT_WLOCK_ALL + RTL_W8(0x1c, tmp & (~(BIT(0) | BIT(1)))); + // Turn ON BIT_SYSON_DIS_PMCREG_WRMSK + RTL_W8(0xcc, RTL_R8(0xcc) | BIT(2)); + // Turn ON BIT_STOP_RXQ + RTL_W8(0x301, RTL_R8(0x301) | BIT(0)); + // Reset flow + RTL_W8(CR, 0); + RTL_W8(SYS_FUNC_EN+1, RTL_R8(SYS_FUNC_EN+1) & (~BIT(0))); + RTL_W8(SYS_FUNC_EN+1, RTL_R8(SYS_FUNC_EN+1) | BIT(0)); + // Turn OFF BIT_STOP_RXQ + RTL_W8(0x301, RTL_R8(0x301) & (~BIT(0))); + // Turn OFF BIT_SYSON_DIS_PMCREG_WRMSK + RTL_W8(0xcc, RTL_R8(0xcc) & (~BIT(2))); + // Restore BIT_WLOCK_ALL + RTL_W8(0x1c, tmp); + + rxhangup++; + } + } else { + priv->pshare->rx_dma_err_cnt = 0; + priv->pshare->rxff_rdptr = rxffptr; + priv->pshare->rxff_pkt = rxffpkt; + priv->pshare->rx_byte_cnt = priv->net_stats.rx_bytes; + } + } + } +#endif + +#ifdef CHECK_RX_TAG_ERROR +#ifdef CONFIG_WLAN_HAL_8192EE + if(priv->pshare->rf_ft_var.check_hang & CHECK_RX_TAG_ERROR) + if (GET_CHIP_VER(priv) == VERSION_8192E) { + if(((priv->pshare->RxTagPollingCount >20)) && (RTL_R32(0)!=0xffffffff) ) { + rxhangup++; +// panic_printk("%s, %d, Rx recover!!", __FUNCTION__, __LINE__); + } + } +#endif +#endif + +#ifdef CHECK_BEACON_HANGUP + if (((OPMODE & WIFI_AP_STATE) + && !(OPMODE &WIFI_SITE_MONITOR) + && priv->pBeaconCapability // beacon has init +#ifdef WDS + && !priv->pmib->dot11WdsInfo.wdsPure +#endif +#if defined(CONFIG_RTK_MESH) + && !priv->pmib->dot1180211sInfo.meshSilence +#endif + && !priv->pmib->miscEntry.func_off + ) +#ifdef UNIVERSAL_REPEATER + || ((OPMODE & WIFI_STATION_STATE) && GET_VXD_PRIV(priv) && + (GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED)) +#endif + ) { + unsigned long beacon_ok; + +#ifdef UNIVERSAL_REPEATER + if (OPMODE & WIFI_STATION_STATE){ + beacon_ok = GET_VXD_PRIV(priv)->ext_stats.beacon_ok; +/* + BcnQ_Val = GET_VXD_PRIV(priv)->ext_stats.beaconQ_sts; + GET_VXD_PRIV(priv)->ext_stats.beaconQ_sts = RTL_R32(0x120); + if(BcnQ_Val == GET_VXD_PRIV(priv)->ext_stats.beaconQ_sts) + beacon_hangup = 1; +*/ + } + else +#endif + { + beacon_ok = priv->ext_stats.beacon_ok; +/* + BcnQ_Val = priv->ext_stats.beaconQ_sts; + priv->ext_stats.beaconQ_sts = RTL_R32(0x120);// firmware beacon Q stats + if(BcnQ_Val == priv->ext_stats.beaconQ_sts) + beacon_hangup = 1; +*/ + } + + if (priv->pshare->beacon_wait_cnt == 0) { + if (priv->pshare->beacon_ok_cnt == beacon_ok) { + int threshold=1; +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) + threshold=3; +#endif + if (priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod < 650) + threshold = 0; + if (priv->pshare->beacon_pending_cnt++ >= threshold) + beacon_hangup = 1; + } + else { + priv->pshare->beacon_ok_cnt =beacon_ok; + if (priv->pshare->beacon_pending_cnt > 0) + priv->pshare->beacon_pending_cnt = 0; + } + } + else + priv->pshare->beacon_wait_cnt--; + } +#endif + +#ifdef CHECK_AFTER_RESET + if (priv->pshare->reset_monitor_cnt_down > 0) { + priv->pshare->reset_monitor_cnt_down--; + if (priv->pshare->reset_monitor_rx_pkt_cnt == priv->net_stats.rx_packets) { +// if (priv->pshare->reset_monitor_pending++ > 1) + reset_fail_hangup = 1; + } + else { + priv->pshare->reset_monitor_rx_pkt_cnt = priv->net_stats.rx_packets; + if (priv->pshare->reset_monitor_pending > 0) + priv->pshare->reset_monitor_pending = 0; + } + } +#endif + + if (txhangup || rxhangup || beacon_hangup || reset_fail_hangup || fw_error) { // hangup happen + priv->reset_hangup = 1; +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + GET_VXD_PRIV(priv)->reset_hangup = 1; +#endif +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + priv->pvap_priv[i]->reset_hangup = 1; + } + } +#endif + + if (txhangup) + priv->check_cnt_tx++; + else if (rxhangup) + priv->check_cnt_rx++; + else if (beacon_hangup) + priv->check_cnt_bcn++; + else if (reset_fail_hangup) + priv->check_cnt_rst++; + else if (fw_error) + priv->check_cnt_fw++; + +// for debug +#if 0 + if (txhangup) + printk("WA: Tx reset, up-time=%lu sec\n", priv->up_time); + else if (rxhangup) + printk("WA: Rx reset, up-time=%lu sec\n", priv->up_time); + else if (beacon_hangup) + printk("WA: Beacon reset, up-time=%lu sec\n", priv->up_time); + else if (reset_fail_hangup) + printk("WA: Reset-fail reset, up-time=%lu sec\n", priv->up_time); + else if (fw_error) + printk("WA: FW reset, up-time=%lu sec\n", priv->up_time); +#endif + +// Set flag to re-init WDS key in rtl8192cd_open() +#ifdef WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled && + (priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_ || + priv->pmib->dot11WdsInfo.wdsPrivacy == _CCMP_PRIVACY_) ) { + int i; + for (i=0; ipmib->dot11WdsInfo.wdsNum; i++) + if (netif_running(priv->wds_dev[i])) + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[i]|=0x80000000; + } +#endif +//----------------------------- david+2006-06-30 + + PRINT_INFO("Status check! Tx[%d] Rx[%d] Bcnt[%d] Rst[%d] ...\n", + priv->check_cnt_tx, priv->check_cnt_rx, priv->check_cnt_bcn, priv->check_cnt_rst); + + watchdog_stop(priv); + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + +#ifdef FAST_RECOVERY + info = backup_sta(priv); +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + vap_info[i] = backup_sta(priv->pvap_priv[i]); + else + vap_info[i] = NULL; + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + vxd_info = backup_sta(GET_VXD_PRIV(priv)); +#endif +#endif // FAST_RECOVERY + + priv->pmib->dot11OperationEntry.keep_rsnie = 1; +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + priv->pvap_priv[i]->pmib->dot11OperationEntry.keep_rsnie = 1; + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.keep_rsnie = 1; +#endif + + SMP_UNLOCK(flags); + rtl8192cd_close(priv->dev); + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + RTL_W8(0x1c, RTL_R8(0x1c) & (~(BIT(0) | BIT(1)))); + RTL_W8(SYS_FUNC_EN+1, RTL_R8(SYS_FUNC_EN+1) & (~ BIT(0))); + RTL_W8(SYS_FUNC_EN+1, RTL_R8(SYS_FUNC_EN+1) | BIT(0)); + RTL_W8(0x1c, RTL_R8(0x1c) | BIT(0) | BIT(1)); + } +#endif + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + reset_dmdp_peer(priv); +#endif + + rtl8192cd_open(priv->dev); + SMP_LOCK(flags); + +#ifdef FAST_RECOVERY + if (info) + restore_backup_sta(priv, info); + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]) && vap_info[i]) + restore_backup_sta(priv->pvap_priv[i], vap_info[i]); + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && vxd_info) + restore_backup_sta(GET_VXD_PRIV(priv), vxd_info); +#endif +#endif // FAST_RECOVERY + +#ifdef CHECK_AFTER_RESET + priv->pshare->reset_monitor_cnt_down = 3; + priv->pshare->reset_monitor_pending = 0; + priv->pshare->reset_monitor_rx_pkt_cnt = priv->net_stats.rx_packets; +#endif + + RESTORE_INT(flags); + SMP_UNLOCK(flags); + + watchdog_resume(priv); + + return 1; + } + else + return 0; +} +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +int check_hangup(struct rtl8192cd_priv *priv) +{ + unsigned long flags = 0; + int txhangup, rxhangup, fw_error; +#ifdef MBSSID + int i; +#endif +#ifdef FAST_RECOVERY + void *info = NULL; +#ifdef UNIVERSAL_REPEATER + void *vxd_info = NULL; +#endif +#endif // FAST_RECOVERY +#ifdef MBSSID + void *vap_info[RTL8192CD_NUM_VWLAN]; + memset(vap_info, 0, sizeof(vap_info)); +#endif + + txhangup = rxhangup = fw_error = 0; +#ifdef CHECK_FW_ERROR + if (priv->pshare->rf_ft_var.check_hang & CHECK_FW_ERROR) { + int mcutst, mcutst2; + mcutst = RTL_R8(MCUTST_I); + mcutst2 = RTL_R16(MCUTST_II); + if ((mcutst&BIT1) || (priv->pshare->mcu_tst2 == mcutst2)) { + if ((mcutst&BIT1) == 0 && +#ifdef SDIO_AP_OFFLOAD + priv->pshare->mcu_pending_cnt < 30 +#else + priv->pshare->mcu_pending_cnt < 15 +#endif + ) { // continue for 15 seconds + priv->pshare->mcu_pending_cnt++; + } else { + fw_error = 1; + } + } else { + priv->pshare->mcu_pending_cnt = 0; + } + priv->pshare->mcu_tst2 = mcutst2; + } +#endif + +#ifdef CHECK_TX_HANGUP + if (priv->pshare->rf_ft_var.check_hang & CHECK_TX_HANGUP) { + if (RTL_R32(TXDMA_STATUS)) { + txhangup++; + } + } +#endif + +#ifdef CHECK_RX_DMA_ERROR + if (priv->pshare->rf_ft_var.check_hang & CHECK_RX_DMA_ERROR) { + if (RTL_R32(RXDMA_STATUS) & (~BIT5)) { + rxhangup++; + } + } +#endif + + if (txhangup || rxhangup || fw_error) { // hangup happen +#ifdef SDIO_AP_OFFLOAD + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_HANGUP); +#endif + priv->reset_hangup = 1; + printk("[%s] reset_hangup = %d\n", __FUNCTION__, priv->reset_hangup); + +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + GET_VXD_PRIV(priv)->reset_hangup = 1; +#endif +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + priv->pvap_priv[i]->reset_hangup = 1; + } + } +#endif + + if (txhangup) + priv->check_cnt_tx++; + else if (rxhangup) + priv->check_cnt_rx++; + else if (fw_error) + priv->check_cnt_fw++; + +//--------------------------------------- for debug --------------------------------------- +#if 1 + if (txhangup) + printk("WA: Tx reset, up-time=%lu sec\n", priv->up_time); + else if (rxhangup) + printk("WA: Rx reset, up-time=%lu sec\n", priv->up_time); + else if (fw_error) + printk("WA: FW reset, up-time=%lu sec\n", priv->up_time); +#endif +//----------------------------------------------------------------------------------------- + +// Set flag to re-init WDS key in rtl8192cd_open() +#ifdef WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled && + (priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_ || + priv->pmib->dot11WdsInfo.wdsPrivacy == _CCMP_PRIVACY_) ) { + int i; + for (i=0; ipmib->dot11WdsInfo.wdsNum; i++) + if (netif_running(priv->wds_dev[i])) + priv->pmib->dot11WdsInfo.wdsMappingKeyLen[i]|=0x80000000; + } +#endif + + printk("Status check! Tx[%d] Rx[%d] FW[%d] ...\n", priv->check_cnt_tx, priv->check_cnt_rx, priv->check_cnt_fw); + + SMP_LOCK(flags); + +#ifdef FAST_RECOVERY + info = backup_sta(priv); +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + vap_info[i] = backup_sta(priv->pvap_priv[i]); + else + vap_info[i] = NULL; + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + vxd_info = backup_sta(GET_VXD_PRIV(priv)); +#endif +#endif // FAST_RECOVERY + + priv->pmib->dot11OperationEntry.keep_rsnie = 1; +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + priv->pvap_priv[i]->pmib->dot11OperationEntry.keep_rsnie = 1; + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.keep_rsnie = 1; +#endif + + SMP_UNLOCK(flags); + rtl8192cd_close(priv->dev); + rtl8192cd_open(priv->dev); + SMP_LOCK(flags); + +#ifdef FAST_RECOVERY + if (info) + restore_backup_sta(priv, info); + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]) && vap_info[i]) + restore_backup_sta(priv->pvap_priv[i], vap_info[i]); + } + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && vxd_info) + restore_backup_sta(GET_VXD_PRIV(priv), vxd_info); +#endif +#endif // FAST_RECOVERY + + SMP_UNLOCK(flags); +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_HANGUP); +#endif + return 1; + } + else + return 0; +} +#endif +#endif // CHECK_HANGUP + + +#ifdef CONFIG_PCI_HCI +// quick fix of tx stuck especial in client mode +void tx_stuck_fix(struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_hw *phw = GET_HW(priv); + unsigned int val32; +#ifndef SMP_SYNC + unsigned long flags; +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + return; + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + SAVE_INT_AND_CLI(flags); +// RTL_W32(0x350, RTL_R32(0x350) | BIT(26)); + val32 = RTL_R32(0x350); + if (val32 & BIT(24)) { // tx stuck + RTL_W8(0x301, RTL_R8(0x301) | BIT(0)); + delay_us(100); + rtl8192cd_rx_isr(priv); + RTL_W8(0x302, RTL_R8(0x302) | BIT(4)); + RTL_W8(0x3, RTL_R8(0x3) & (~BIT(0))); + RTL_W8(0x3, RTL_R8(0x3) | BIT(0)); +#ifdef DELAY_REFILL_RX_BUF + { + struct sk_buff *pskb; + + while (phw->cur_rx_refill != phw->cur_rx) { + pskb = rtl_dev_alloc_skb(priv, RX_BUF_LEN, _SKB_RX_, 1); + if (pskb == NULL) { + printk("[%s] can't allocate skbuff for RX!\n", __FUNCTION__); + } + init_rxdesc(pskb, phw->cur_rx_refill, priv); + + phw->cur_rx_refill = (phw->cur_rx_refill + 1) % NUM_RX_DESC; + } + } + phw->cur_rx_refill = 0; +#endif + phw->cur_rx = 0; + RTL_W32(RX_DESA, (unsigned int)phw->ring_dma_addr); + RTL_W8(0x301, RTL_R8(0x301) & (~BIT(0))); + RTL_W8(PCIE_CTRL_REG, MGQ_POLL | BEQ_POLL); + } + RESTORE_INT(flags); +} +} +#endif // CONFIG_PCI_HCI + +static struct ac_log_info *aclog_lookfor_entry(struct rtl8192cd_priv *priv, unsigned char *addr) +{ + int i, idx=-1; + + for (i=0; iacLog[i].used == 0) { + if (idx < 0) + idx = i; + continue; + } + if (!memcmp(priv->acLog[i].addr, addr, MACADDRLEN)) + break; + } + + if ( i != MAX_AC_LOG) + return (&priv->acLog[i]); + + if (idx >= 0) + return (&priv->acLog[idx]); + + return NULL; // table full +} + + +static void aclog_update_entry(struct ac_log_info *entry, unsigned char *addr) +{ + if (entry->used == 0) { + memcpy(entry->addr, addr, MACADDRLEN); + entry->used = 1; + } + entry->cur_cnt++; + entry->last_attack_time = jiffies; +} + + +static int aclog_check(struct rtl8192cd_priv *priv) +{ + int i, used=0; + + for (i=0; iacLog[i].used) { + used++; + if (priv->acLog[i].cur_cnt != priv->acLog[i].last_cnt) { +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_DROP("Unauthorized wireless PC try to connect;note:%02X:%02X:%02X:%02X:%02X:%02X;\n", + priv->acLog[i].addr[0], priv->acLog[i].addr[1], priv->acLog[i].addr[2], + priv->acLog[i].addr[3], priv->acLog[i].addr[4], priv->acLog[i].addr[5]); +#elif defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) + LOG_MSG_DROP("Unauthorized wireless PC try to connect;note:%02X:%02X:%02X:%02X:%02X:%02X;\n", + priv->acLog[i].addr[0], priv->acLog[i].addr[1], priv->acLog[i].addr[2], + priv->acLog[i].addr[3], priv->acLog[i].addr[4], priv->acLog[i].addr[5]); +#elif defined(CONFIG_RTL8196B_TLD) + LOG_MSG_DEL("[WLAN access denied] from MAC: %02x:%02x:%02x:%02x:%02x:%02x,\n", + priv->acLog[i].addr[0], priv->acLog[i].addr[1], priv->acLog[i].addr[2], + priv->acLog[i].addr[3], priv->acLog[i].addr[4], priv->acLog[i].addr[5]); +#else + LOG_MSG("A wireless client (%02X:%02X:%02X:%02X:%02X:%02X) was rejected due to access control for %d times in 5 minutes\n", + priv->acLog[i].addr[0], priv->acLog[i].addr[1], priv->acLog[i].addr[2], + priv->acLog[i].addr[3], priv->acLog[i].addr[4], priv->acLog[i].addr[5], + priv->acLog[i].cur_cnt - priv->acLog[i].last_cnt); +#endif + priv->acLog[i].last_cnt = priv->acLog[i].cur_cnt; + } + else { // no update, check expired entry + if ((jiffies - priv->acLog[i].last_attack_time) > AC_LOG_EXPIRE) { + memset(&priv->acLog[i], '\0', sizeof(struct ac_log_info)); + used--; + } + } + } + } + + return used; +} + + +#ifdef WIFI_WMM +static void get_AP_Qos_Info(struct rtl8192cd_priv *priv, unsigned char *temp) +{ + temp[0] = GET_EDCA_PARA_UPDATE; + temp[0] &= 0x0f; + if (APSD_ENABLE) + temp[0] |= BIT(7); +} + + +static void get_STA_AC_Para_Record(struct rtl8192cd_priv *priv, unsigned char *temp) +{ +//BE + temp[0] = GET_STA_AC_BE_PARA.AIFSN; + temp[0] &= 0x0f; + if (GET_STA_AC_BE_PARA.ACM) + temp[0] |= BIT(4); + temp[1] = GET_STA_AC_BE_PARA.ECWmax; + temp[1] <<= 4; + temp[1] |= GET_STA_AC_BE_PARA.ECWmin; + temp[2] = GET_STA_AC_BE_PARA.TXOPlimit % 256; + temp[3] = GET_STA_AC_BE_PARA.TXOPlimit / 256; // 2^8 = 256, for one byte's range + +//BK + temp[4] = GET_STA_AC_BK_PARA.AIFSN; + temp[4] &= 0x0f; + if (GET_STA_AC_BK_PARA.ACM) + temp[4] |= BIT(4); + temp[4] |= BIT(5); + temp[5] = GET_STA_AC_BK_PARA.ECWmax; + temp[5] <<= 4; + temp[5] |= GET_STA_AC_BK_PARA.ECWmin; + temp[6] = GET_STA_AC_BK_PARA.TXOPlimit % 256; + temp[7] = GET_STA_AC_BK_PARA.TXOPlimit / 256; + +//VI + temp[8] = GET_STA_AC_VI_PARA.AIFSN; + temp[8] &= 0x0f; + if (GET_STA_AC_VI_PARA.ACM) + temp[8] |= BIT(4); + temp[8] |= BIT(6); + temp[9] = GET_STA_AC_VI_PARA.ECWmax; + temp[9] <<= 4; + temp[9] |= GET_STA_AC_VI_PARA.ECWmin; + temp[10] = GET_STA_AC_VI_PARA.TXOPlimit % 256; + temp[11] = GET_STA_AC_VI_PARA.TXOPlimit / 256; + +//VO + temp[12] = GET_STA_AC_VO_PARA.AIFSN; + temp[12] &= 0x0f; + if (GET_STA_AC_VO_PARA.ACM) + temp[12] |= BIT(4); + temp[12] |= BIT(5)|BIT(6); + temp[13] = GET_STA_AC_VO_PARA.ECWmax; + temp[13] <<= 4; + temp[13] |= GET_STA_AC_VO_PARA.ECWmin; + temp[14] = GET_STA_AC_VO_PARA.TXOPlimit % 256; + temp[15] = GET_STA_AC_VO_PARA.TXOPlimit /256; +} + + +void init_WMM_Para_Element(struct rtl8192cd_priv *priv, unsigned char *temp) +{ + if (OPMODE & WIFI_AP_STATE) { + memcpy(temp, WMM_PARA_IE, 6); +//Qos Info field + get_AP_Qos_Info(priv, &temp[6]); +//AC Parameters + get_STA_AC_Para_Record(priv, &temp[8]); + } +#ifdef CLIENT_MODE + else if ((OPMODE & WIFI_STATION_STATE) ||(OPMODE & WIFI_ADHOC_STATE)) { // WMM STA + memcpy(temp, WMM_IE, 6); + temp[6] = 0x00; // set zero to WMM STA Qos Info field +#ifdef WMM_APSD + if ((OPMODE & WIFI_STATION_STATE) && APSD_ENABLE && priv->uapsd_assoc) { + if (priv->pmib->dot11QosEntry.UAPSD_AC_BE) + temp[6] |= BIT(3); + if (priv->pmib->dot11QosEntry.UAPSD_AC_BK) + temp[6] |= BIT(2); + if (priv->pmib->dot11QosEntry.UAPSD_AC_VI) + temp[6] |= BIT(1); + if (priv->pmib->dot11QosEntry.UAPSD_AC_VO) + temp[6] |= BIT(0); + } +#endif + } +#endif +} + +void default_WMM_para(struct rtl8192cd_priv *priv) +{ +#ifdef RTL_MANUAL_EDCA + if( priv->pmib->dot11QosEntry.ManualEDCA ) { + GET_STA_AC_BE_PARA.ACM = priv->pmib->dot11QosEntry.STA_manualEDCA[BE].ACM; + GET_STA_AC_BE_PARA.AIFSN = priv->pmib->dot11QosEntry.STA_manualEDCA[BE].AIFSN; + GET_STA_AC_BE_PARA.ECWmin = priv->pmib->dot11QosEntry.STA_manualEDCA[BE].ECWmin; + GET_STA_AC_BE_PARA.ECWmax = priv->pmib->dot11QosEntry.STA_manualEDCA[BE].ECWmax; + GET_STA_AC_BE_PARA.TXOPlimit = priv->pmib->dot11QosEntry.STA_manualEDCA[BE].TXOPlimit; + + GET_STA_AC_BK_PARA.ACM = priv->pmib->dot11QosEntry.STA_manualEDCA[BK].ACM; + GET_STA_AC_BK_PARA.AIFSN = priv->pmib->dot11QosEntry.STA_manualEDCA[BK].AIFSN; + GET_STA_AC_BK_PARA.ECWmin = priv->pmib->dot11QosEntry.STA_manualEDCA[BK].ECWmin; + GET_STA_AC_BK_PARA.ECWmax = priv->pmib->dot11QosEntry.STA_manualEDCA[BK].ECWmax; + GET_STA_AC_BK_PARA.TXOPlimit = priv->pmib->dot11QosEntry.STA_manualEDCA[BK].TXOPlimit; + + GET_STA_AC_VI_PARA.ACM = priv->pmib->dot11QosEntry.STA_manualEDCA[VI].ACM; + GET_STA_AC_VI_PARA.AIFSN = priv->pmib->dot11QosEntry.STA_manualEDCA[VI].AIFSN; + GET_STA_AC_VI_PARA.ECWmin = priv->pmib->dot11QosEntry.STA_manualEDCA[VI].ECWmin; + GET_STA_AC_VI_PARA.ECWmax = priv->pmib->dot11QosEntry.STA_manualEDCA[VI].ECWmax; + GET_STA_AC_VI_PARA.TXOPlimit = priv->pmib->dot11QosEntry.STA_manualEDCA[VI].TXOPlimit; // 6.016ms + + GET_STA_AC_VO_PARA.ACM = priv->pmib->dot11QosEntry.STA_manualEDCA[VO].ACM; + GET_STA_AC_VO_PARA.AIFSN = priv->pmib->dot11QosEntry.STA_manualEDCA[VO].AIFSN; + GET_STA_AC_VO_PARA.ECWmin = priv->pmib->dot11QosEntry.STA_manualEDCA[VO].ECWmin; + GET_STA_AC_VO_PARA.ECWmax = priv->pmib->dot11QosEntry.STA_manualEDCA[VO].ECWmax; + GET_STA_AC_VO_PARA.TXOPlimit = priv->pmib->dot11QosEntry.STA_manualEDCA[VO].TXOPlimit; // 3.264ms + } else +#endif + { + GET_STA_AC_BE_PARA.ACM = rtl_sta_EDCA[BE].ACM; + GET_STA_AC_BE_PARA.AIFSN = rtl_sta_EDCA[BE].AIFSN; + GET_STA_AC_BE_PARA.ECWmin = rtl_sta_EDCA[BE].ECWmin; + GET_STA_AC_BE_PARA.ECWmax = rtl_sta_EDCA[BE].ECWmax; + GET_STA_AC_BE_PARA.TXOPlimit = rtl_sta_EDCA[BE].TXOPlimit; + + GET_STA_AC_BK_PARA.ACM = rtl_sta_EDCA[BK].ACM; + GET_STA_AC_BK_PARA.AIFSN = rtl_sta_EDCA[BK].AIFSN; + GET_STA_AC_BK_PARA.ECWmin = rtl_sta_EDCA[BK].ECWmin; + GET_STA_AC_BK_PARA.ECWmax = rtl_sta_EDCA[BK].ECWmax; + GET_STA_AC_BK_PARA.TXOPlimit = rtl_sta_EDCA[BK].TXOPlimit; + + GET_STA_AC_VI_PARA.ACM = rtl_sta_EDCA[VI].ACM; + GET_STA_AC_VI_PARA.AIFSN = rtl_sta_EDCA[VI].AIFSN; + GET_STA_AC_VI_PARA.ECWmin = rtl_sta_EDCA[VI].ECWmin; + GET_STA_AC_VI_PARA.ECWmax = rtl_sta_EDCA[VI].ECWmax; + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G|WIRELESS_11A)) + GET_STA_AC_VI_PARA.TXOPlimit = 94; // 3.008ms GET_STA_AC_VI_PARA.TXOPlimit = rtl_sta_EDCA[VI_AG].TXOPlimit; // 3.008ms + else + GET_STA_AC_VI_PARA.TXOPlimit = 188; // 6.016ms GET_STA_AC_VI_PARA.TXOPlimit = rtl_sta_EDCA[VI].TXOPlimit; // 6.016ms + + GET_STA_AC_VO_PARA.ACM = rtl_sta_EDCA[VO].ACM; + GET_STA_AC_VO_PARA.AIFSN = rtl_sta_EDCA[VO].AIFSN; + GET_STA_AC_VO_PARA.ECWmin = rtl_sta_EDCA[VO].ECWmin; + GET_STA_AC_VO_PARA.ECWmax = rtl_sta_EDCA[VO].ECWmax; + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G|WIRELESS_11A)) + GET_STA_AC_VO_PARA.TXOPlimit = 47; // 1.504ms GET_STA_AC_VO_PARA.TXOPlimit = rtl_sta_EDCA[VO_AG].TXOPlimit; // 1.504ms + else + GET_STA_AC_VO_PARA.TXOPlimit = 102; // 3.264ms GET_STA_AC_VO_PARA.TXOPlimit = rtl_sta_EDCA[VO].TXOPlimit; // 3.264ms + } +} + + + +#ifdef CLIENT_MODE +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +static void process_WMM_para_ie(struct rtl8192cd_priv *priv, unsigned char *p) +{ + int ACI = (p[0] >> 5) & 0x03; + /*avoid unaligned load*/ + unsigned short txoplimit; + memcpy(&txoplimit,&p[2],sizeof(unsigned short)); + if ((ACI >= 0) && (ACI <= 3)) { + switch(ACI) { + case 0: + GET_STA_AC_BE_PARA.ACM = (p[0] >> 4) & 0x01; + GET_STA_AC_BE_PARA.AIFSN = p[0] & 0x0f; + GET_STA_AC_BE_PARA.ECWmin = p[1] & 0x0f; + GET_STA_AC_BE_PARA.ECWmax = p[1] >> 4; + GET_STA_AC_BE_PARA.TXOPlimit = le16_to_cpu(txoplimit); + break; + case 3: + GET_STA_AC_VO_PARA.ACM = (p[0] >> 4) & 0x01; + GET_STA_AC_VO_PARA.AIFSN = p[0] & 0x0f; + GET_STA_AC_VO_PARA.ECWmin = p[1] & 0x0f; + GET_STA_AC_VO_PARA.ECWmax = p[1] >> 4; + GET_STA_AC_VO_PARA.TXOPlimit = le16_to_cpu(txoplimit); + break; + case 2: + GET_STA_AC_VI_PARA.ACM = (p[0] >> 4) & 0x01; + GET_STA_AC_VI_PARA.AIFSN = p[0] & 0x0f; + GET_STA_AC_VI_PARA.ECWmin = p[1] & 0x0f; + GET_STA_AC_VI_PARA.ECWmax = p[1] >> 4; + GET_STA_AC_VI_PARA.TXOPlimit = le16_to_cpu(txoplimit); + break; + default: + GET_STA_AC_BK_PARA.ACM = (p[0] >> 4) & 0x01; + GET_STA_AC_BK_PARA.AIFSN = p[0] & 0x0f; + GET_STA_AC_BK_PARA.ECWmin = p[1] & 0x0f; + GET_STA_AC_BK_PARA.ECWmax = p[1] >> 4; + GET_STA_AC_BK_PARA.TXOPlimit = le16_to_cpu(txoplimit); + break; + } + } + else + printk("WMM AP EDCA Parameter IE error!\n"); +} + + +static void sta_config_EDCA_para(struct rtl8192cd_priv *priv) +{ + unsigned int slot_time = 20, ifs_time = 10; + unsigned int vo_edca = 0, vi_edca = 0, be_edca = 0, bk_edca = 0; + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N ) || + (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) + slot_time = 9; + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + ifs_time = 16; +#if 1 + if (GET_STA_AC_VO_PARA.AIFSN) { + vo_edca = (((unsigned short)(GET_STA_AC_VO_PARA.TXOPlimit)) << 16) + | (((unsigned char)(GET_STA_AC_VO_PARA.ECWmax)) << 12) + | (((unsigned char)(GET_STA_AC_VO_PARA.ECWmin)) << 8) + | (ifs_time + GET_STA_AC_VO_PARA.AIFSN * slot_time); + + RTL_W32(EDCA_VO_PARA, vo_edca); + } + + if (GET_STA_AC_VI_PARA.AIFSN) { + vi_edca = (((unsigned short)(GET_STA_AC_VI_PARA.TXOPlimit)) << 16) + | (((unsigned char)(GET_STA_AC_VI_PARA.ECWmax)) << 12) + | (((unsigned char)(GET_STA_AC_VI_PARA.ECWmin)) << 8) + | (ifs_time + GET_STA_AC_VI_PARA.AIFSN * slot_time); + + /* WiFi Client mode WMM test IOT refine */ + if (priv->pmib->dot11OperationEntry.wifi_specific && (GET_STA_AC_VI_PARA.AIFSN == 2)) + vi_edca = (vi_edca & ~0xff) | (ifs_time + (GET_STA_AC_VI_PARA.AIFSN + 1) * slot_time); + + RTL_W32(EDCA_VI_PARA, vi_edca); + } + + if (GET_STA_AC_BE_PARA.AIFSN) { + be_edca = (((unsigned short)(GET_STA_AC_BE_PARA.TXOPlimit)) << 16) + | (((unsigned char)(GET_STA_AC_BE_PARA.ECWmax)) << 12) + | (((unsigned char)(GET_STA_AC_BE_PARA.ECWmin)) << 8) + | (ifs_time + GET_STA_AC_BE_PARA.AIFSN * slot_time); + + RTL_W32(EDCA_BE_PARA, be_edca); + } + + if (GET_STA_AC_BK_PARA.AIFSN) { + bk_edca = (((unsigned short)(GET_STA_AC_BK_PARA.TXOPlimit)) << 16) + | (((unsigned char)(GET_STA_AC_BK_PARA.ECWmax)) << 12) + | (((unsigned char)(GET_STA_AC_BK_PARA.ECWmin)) << 8) + | (ifs_time + GET_STA_AC_BK_PARA.AIFSN * slot_time); + + RTL_W32(EDCA_BK_PARA, bk_edca); + } +#else + if(GET_STA_AC_VO_PARA.AIFSN > 0) { + RTL_W32(EDCA_VO_PARA, (((unsigned short)(GET_STA_AC_VO_PARA.TXOPlimit)) << 16) + | (((unsigned char)(GET_STA_AC_VO_PARA.ECWmax)) << 12) + | (((unsigned char)(GET_STA_AC_VO_PARA.ECWmin)) << 8) + | (ifs_time + GET_STA_AC_VO_PARA.AIFSN * slot_time)); + if(GET_STA_AC_VO_PARA.ACM > 0) + RTL_W8(ACMHWCTRL, RTL_R8(ACMHWCTRL)|BIT(3)); + } + + if(GET_STA_AC_VI_PARA.AIFSN > 0) { + RTL_W32(EDCA_VI_PARA, (((unsigned short)(GET_STA_AC_VI_PARA.TXOPlimit)) << 16) + | (((unsigned char)(GET_STA_AC_VI_PARA.ECWmax)) << 12) + | (((unsigned char)(GET_STA_AC_VI_PARA.ECWmin)) << 8) + | (ifs_time + GET_STA_AC_VI_PARA.AIFSN * slot_time)); + if(GET_STA_AC_VI_PARA.ACM > 0) + RTL_W8(ACMHWCTRL, RTL_R8(ACMHWCTRL)|BIT(2)); + } + + if(GET_STA_AC_BE_PARA.AIFSN > 0) { + RTL_W32(EDCA_BE_PARA, (((unsigned short)(GET_STA_AC_BE_PARA.TXOPlimit)) << 16) + | (((unsigned char)(GET_STA_AC_BE_PARA.ECWmax)) << 12) + | (((unsigned char)(GET_STA_AC_BE_PARA.ECWmin)) << 8) + | (ifs_time + GET_STA_AC_BE_PARA.AIFSN * slot_time)); + if(GET_STA_AC_BE_PARA.ACM > 0) + RTL_W8(ACMHWCTRL, RTL_R8(ACMHWCTRL)|BIT(1)); + } + + if(GET_STA_AC_BK_PARA.AIFSN > 0) { + RTL_W32(EDCA_BK_PARA, (((unsigned short)(GET_STA_AC_BK_PARA.TXOPlimit)) << 16) + | (((unsigned char)(GET_STA_AC_BK_PARA.ECWmax)) << 12) + | (((unsigned char)(GET_STA_AC_BK_PARA.ECWmin)) << 8) + | (ifs_time + GET_STA_AC_BK_PARA.AIFSN * slot_time)); + } + + if ((GET_STA_AC_VO_PARA.ACM > 0) || (GET_STA_AC_VI_PARA.ACM > 0) || (GET_STA_AC_BE_PARA.ACM > 0)) + RTL_W8(ACMHWCTRL, RTL_R8(ACMHWCTRL)|BIT(0)); +#endif + + priv->pmib->dot11QosEntry.EDCA_STA_config = 1; + priv->pshare->iot_mode_enable = 0; + if (priv->pshare->rf_ft_var.wifi_beq_iot) + priv->pshare->iot_mode_VI_exist = 0; + priv->pshare->iot_mode_VO_exist = 0; +#ifdef WMM_VIBE_PRI + priv->pshare->iot_mode_BE_exist = 0; +#endif +#ifdef WMM_BEBK_PRI + priv->pshare->iot_mode_BK_exist = 0; +#endif +#ifdef LOW_TP_TXOP + priv->pshare->BE_cwmax_enhance = 0; +#endif +} + + +static void reset_EDCA_para(struct rtl8192cd_priv *priv) +{ + memset((void *)&GET_STA_AC_VO_PARA, 0, sizeof(struct ParaRecord)); + memset((void *)&GET_STA_AC_VI_PARA, 0, sizeof(struct ParaRecord)); + memset((void *)&GET_STA_AC_BE_PARA, 0, sizeof(struct ParaRecord)); + memset((void *)&GET_STA_AC_BK_PARA, 0, sizeof(struct ParaRecord)); + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + EdcaParaInit(priv); +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + init_EDCA_para(priv, priv->pmib->dot11BssType.net_work_type); +#endif + + priv->pmib->dot11QosEntry.EDCA_STA_config = 0; +} +#endif // CLIENT_MODE +#endif // WIFI_WMM + + +// Realtek proprietary IE +static void process_rtk_ie(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + int use_long_slottime=0; + unsigned int threshold; +#ifdef SMP_SYNC + unsigned long flags=0; +#endif + + if ((priv->up_time % 3) != 0) + return; + + if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R)) + threshold = 50*1024*1024/8; + else + threshold = 100*1024*1024/8; + + if (OPMODE & WIFI_AP_STATE) + { + struct list_head *phead = &priv->asoc_list; + struct list_head *plist; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while(plist != phead) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if ((pstat->expire_to > 0) && + (/*priv->pshare->is_giga_exist ||*/ !pstat->is_2t_mimo_sta) && + ((pstat->is_realtek_sta && (pstat->IOTPeer!= HT_IOT_PEER_RTK_APCLIENT) && ((pstat->tx_avarage + pstat->rx_avarage) > threshold)) +#ifdef WDS + || ((pstat->state & WIFI_WDS) && ((pstat->tx_avarage + pstat->rx_avarage) > (threshold*2/3))) +#endif + )) { + use_long_slottime = 1; + break; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + + if (priv->pshare->use_long_slottime == 0) { + if (use_long_slottime) { + priv->pshare->use_long_slottime = 1; + set_slot_time(priv, 0); + priv->pmib->dot11ErpInfo.shortSlot = 0; + RESET_SHORTSLOT_IN_BEACON_CAP; + priv->pshare->rtk_ie_buf[5] |= RTK_CAP_IE_USE_LONG_SLOT; + } + } + else { + if (use_long_slottime == 0) { + priv->pshare->use_long_slottime = 0; + check_protection_shortslot(priv); + priv->pshare->rtk_ie_buf[5] &= (~RTK_CAP_IE_USE_LONG_SLOT); + } + } + } +} + +#ifdef RADIUS_ACCOUNTING +void indicate_sta_leaving(struct rtl8192cd_priv *priv,struct stat_info *pstat, unsigned long reason) +{ + DOT11_DISASSOCIATION_IND Disassociation_Ind; + + memcpy((void *)Disassociation_Ind.MACAddr, (void *)(pstat->hwaddr), MACADDRLEN); + Disassociation_Ind.EventId = DOT11_EVENT_DISASSOCIATION_IND; + Disassociation_Ind.IsMoreEvent = 0; + Disassociation_Ind.Reason = reason; + Disassociation_Ind.tx_packets = pstat->tx_pkts; + Disassociation_Ind.rx_packets = pstat->rx_pkts; + Disassociation_Ind.tx_bytes = pstat->tx_bytes; + Disassociation_Ind.rx_bytes = pstat->rx_bytes; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Disassociation_Ind, + sizeof(DOT11_DISASSOCIATION_IND)); + psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, pstat->hwaddr, NULL, 0); +} + +int cal_statistics_acct(struct rtl8192cd_priv *priv) +{ + unsigned long ret=0; + struct list_head *phead=NULL, *plist=NULL; + struct stat_info *pstat=NULL; +#ifdef SMP_SYNC + unsigned long flags=0; +#endif + + phead = &priv->asoc_list; + if( list_empty(phead) ) + goto acct_cal_out; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if( pstat->link_time%ACCT_TP_INT == 0 ){ + pstat->rx_bytes_1m = pstat->rx_bytes - pstat->rx_bytes_1m; + pstat->tx_bytes_1m = pstat->tx_bytes - pstat->tx_bytes_1m; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + +acct_cal_out: + return ret; +} + +int expire_sta_for_radiusacct(struct rtl8192cd_priv *priv) +{ + int ret=0; + struct list_head *phead=NULL, *plist=NULL; + struct stat_info *pstat=NULL; + + if( (ACCT_FUN_TIME == 0) && (ACCT_FUN_TP == 0)) + goto acct_expire_out; + + phead = &priv->asoc_list; + if(list_empty(phead)) + goto acct_expire_out; + + plist = phead; + + while ((plist = asoc_list_get_next(priv, plist)) != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + + if(pstat->link_time > ACCT_FUN_TIME*60 ){ +#if !defined(WITHOUT_ENQUEUE) && (defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211)) + indicate_sta_leaving(priv,pstat,_RSON_AUTH_NO_LONGER_VALID_); +#endif + issue_deauth(priv,pstat->hwaddr,_RSON_AUTH_NO_LONGER_VALID_); + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + LOG_MSG("A STA(%02X:%02X:%02X:%02X:%02X:%02X) is deleted for accounting becoz of time-out\n", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); + } + + if(pstat->tx_bytes_1m+pstat->rx_bytes_1m < ACCT_FUN_TP*(2^20) ){ +#if !defined(WITHOUT_ENQUEUE) && (defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211)) + indicate_sta_leaving(priv,pstat,_RSON_AUTH_NO_LONGER_VALID_); +#endif + issue_deauth(priv,pstat->hwaddr,_RSON_AUTH_NO_LONGER_VALID_); + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + LOG_MSG("A STA(%02X:%02X:%02X:%02X:%02X:%02X) is deleted for accounting becoz of low TP\n", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); + } + } + +acct_expire_out: + return ret; +} +#endif //#ifdef RADIUS_ACCOUNTING + + +#if defined(SMART_REPEATER_MODE) && !defined(RTK_NL80211) +static void switch_chan_to_vxd(struct rtl8192cd_priv *priv) +{ +#ifdef MBSSID + unsigned int i; +#endif + + priv->pmib->dot11RFEntry.dot11channel = priv->pshare->switch_chan_rp; + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = priv->pshare->switch_2ndchoff_rp; + GET_ROOT(priv)->pmib->dot11nConfigEntry.dot11nUse40M = priv->pshare->band_width_rp; + RTL_W8(TXPAUSE, 0xff); + + // update vxd channel and 2ndChOffset +#ifdef UNIVERSAL_REPEATER + // GET_VXD_PRIV(priv)->pmib->dot11RFEntry.dot11channel = priv->pshare->switch_chan_rp; + // GET_VXD_PRIV(priv)->pmib->dot11nConfigEntry.dot11n2ndChOffset = priv->pshare->switch_2ndchoff_rp; +#endif + + DEBUG_INFO("3. Swiching channel to %d!\n", priv->pmib->dot11RFEntry.dot11channel); + priv->pmib->dot11OperationEntry.keep_rsnie = 1; + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + priv->pvap_priv[i]->pmib->dot11OperationEntry.keep_rsnie = 1; + } + } +#endif + +#ifdef UNIVERSAL_REPEATER + if (GET_VXD_PRIV(priv)) + GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.keep_rsnie = 1; +#endif + + rtl8192cd_close(priv->dev); + rtl8192cd_open(priv->dev); + + RTL_W8(TXPAUSE, 0x00); +} +#endif + +#if defined(TXREPORT) && defined(CONFIG_WLAN_HAL) +void requestTxReport88XX(struct rtl8192cd_priv *priv) +{ + unsigned char h2cresult; + struct stat_info *sta; + unsigned char H2CCommand[2] = {0xff, 0xff}; + + if ( priv->pshare->sta_query_idx == -1) + return; + + sta = findNextSTA(priv, &priv->pshare->sta_query_idx); + if (sta) + { + H2CCommand[0] = REMAP_AID(sta); + } + else { + priv->pshare->sta_query_idx = -1; + return; + } + + sta = findNextSTA(priv, &priv->pshare->sta_query_idx); + if (sta) { + H2CCommand[1] = REMAP_AID(sta); + } else { + priv->pshare->sta_query_idx = -1; + } + + //WDEBUG("\n"); + //h2cresult = FillH2CCmd8812(priv, H2C_8812_TX_REPORT, 2 , H2CCommand); + //WDEBUG("h2cresult=%d\n",h2cresult); + GET_HAL_INTERFACE(priv)->FillH2CCmdHandler(priv, H2C_88XX_AP_REQ_TXREP, 2, H2CCommand); + +} +#endif + + +int is_intel_connected(struct rtl8192cd_priv *priv) +{ + struct list_head *phead, *plist; + struct stat_info *pstat; + unsigned char intel_connected=0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + phead = &priv->asoc_list; + + if (list_empty(phead)) { + return 0; + } + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if(pstat->IOTPeer== HT_IOT_PEER_INTEL) + { + intel_connected = 1; + break; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + + return intel_connected; +} + +#ifdef HS2_SUPPORT +#ifdef HS2_CLIENT_TEST +//issue_GASreq for client test used +int issue_GASreq(struct rtl8192cd_priv *priv, DOT11_HS2_GAS_REQ *gas_req, unsigned short qid); +int testflg=0; +#endif +#endif + +#ifdef RTK_NL80211//survey_dump +const int MCS_DATA_RATEFloat[2][2][16] = +{ + {{6.5, 13, 19.5, 26, 39, 52, 58.5, 65, 13, 26, 39, 52, 78, 104, 117, 130}, // Long GI, 20MHz + {7.2, 14.4, 21.7, 28.9, 43.3, 57.8, 65, 72.2, 14.4, 28.9, 43.3, 57.8, 86.7, 115.6, 130, 144.5}}, // Short GI, 20MHz + {{13.5, 27, 40.5, 54, 81, 108, 121.5, 135, 27, 54, 81, 108, 162, 216, 243, 270}, // Long GI, 40MHz + {15, 30, 45, 60, 90, 120, 135, 150, 30, 60, 90, 120, 180, 240, 270, 300}} // Short GI, 40MHz +}; +#endif +#ifdef RTK_NL80211 +void check_sta_throughput(struct rtl8192cd_priv *priv, unsigned int chan_idx) +{ + struct list_head *phead, *plist; + struct stat_info *pstat; + int tx_rate=0, rx_rate=0; + int tx_time=0, rx_time=0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + //check every sta throughput + phead = &priv->asoc_list; + if (list_empty(phead)) { + return; + } + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + pstat->tx_time_total=0; + pstat->rx_time_total=0; + //cal current tx rate +#ifdef RTK_AC_SUPPORT //vht rate , todo, dump vht rates in Mbps + if(pstat->current_tx_rate >= 0x90) + { + tx_rate = query_vht_rate(pstat); + rx_rate = query_vht_rate(pstat); + } + else +#endif + if (is_MCS_rate(pstat->current_tx_rate)) + { + tx_rate = MCS_DATA_RATEFloat[(pstat->ht_current_tx_info&BIT(0))?1:0][(pstat->ht_current_tx_info&BIT(1))?1:0][pstat->current_tx_rate&0xf]; + rx_rate = MCS_DATA_RATEFloat[pstat->rx_bw&0x01][pstat->rx_splcp&0x01][pstat->rx_rate&0xf]; + } + else + { + tx_rate = pstat->current_tx_rate/2; + rx_rate = pstat->rx_rate/2; + } + + //last tx/rx time + if(tx_rate != 0) + pstat->tx_time_total += (((pstat->tx_bytes - pstat->tx_byte_last)*8*1000)/(tx_rate*1024)); + if(rx_rate != 0) + pstat->rx_time_total += (((pstat->rx_bytes - pstat->rx_byte_last)*8*1000)/(rx_rate*1024)); + #if 0 + printk("tx: rate[%d] tx_byte[%d] tx_byte_last[%d]\n", + tx_rate, pstat->tx_bytes - pstat->tx_byte_last, pstat->tx_byte_last); + printk("rx: rate[%d] rx_byte[%d] rx_byte_last[%d]\n", + rx_rate, pstat->rx_bytes - pstat->rx_byte_last, pstat->rx_byte_last); + #endif + //tx/rx byte last + pstat->tx_byte_last = pstat->tx_bytes; + pstat->rx_byte_last = pstat->rx_bytes; + + //count all traffic time + tx_time += pstat->tx_time_total; + rx_time += pstat->rx_time_total; + + plist = plist->next; + } + + SMP_UNLOCK_ASOC_LIST(flags); + + priv->rtk->survey_info[chan_idx].tx_time = tx_time; + priv->rtk->survey_info[chan_idx].rx_time = rx_time; + + //printk("tx_time=%d rx_time=%d\n",priv->rtk->survey_info[chan_idx].tx_time, priv->rtk->survey_info[chan_idx].rx_time); +} + +int read_noise_report(struct rtl8192cd_priv *priv, unsigned int idx) +{ + s8 noise[RF92CD_PATH_MAX]={0}, noise_max=0, noise_tmp=0; + int ret=0, i=0, loop=0, valid_cnt[RF92CD_PATH_MAX]={0}; + + //8812 not support report noise from hardware + if(GET_CHIP_VER(priv) == VERSION_8192E) { + for(loop=0;loop<50;loop++) { + for (i=RF92CD_PATH_A; i<2; i++) { + RTL_W32(0x80c, RTL_R32(0x80c)|BIT(25)); + noise_tmp = (s8)((RTL_R32(0x8f8) & ((i==RF92CD_PATH_A)?0xff:0xff00)) >> (i*8)); + if(noise_tmp < 10 && noise_tmp >= -35) { //advised by Luke.lee + noise[i] += noise_tmp; + valid_cnt[i]++; + } + RTL_W32(0x80c, RTL_R32(0x80c)&(~BIT(25))); + udelay(5); + } + } + + for(i=RF92CD_PATH_A; i<2; i++) { + if ( valid_cnt[i] != 0 ) + noise[i] /= valid_cnt[i]; + DEBUG_INFO("%s %d ch:%d noise[%d]:%02x(HEX), %d(INT), valid:%d\n",__func__,__LINE__,priv->site_survey->ss_channel,i,noise[i],noise[i],valid_cnt[i]); + } + + for(i=RF92CD_PATH_A; i<2; i++) { + if( noise_max == 0 ) + noise_max = noise[i]; + else if (noise[i] > noise_max) + noise_max = noise[i]; + } + + noise_max -= 110; + } + +#if defined(CONFIG_WLAN_HAL_8814AE) + if(GET_CHIP_VER(priv) == VERSION_8814A) { + for(loop=0;loop<50;loop++) { + for (i=RF92CD_PATH_A; i> (i*8)); + if(noise_tmp < 10 && noise_tmp >= -35) { //advised by Luke.lee + noise[i] += noise_tmp; + valid_cnt[i]++; + } + udelay(5); + //fixme, 8814/8194's idle pwr report may not control by thisbit + //RTL_W32(0x80c, RTL_R32(0x80c)&(~BIT(25))); + } + } + + for(i=RF92CD_PATH_A; isite_survey->ss_channel,i,noise[i],noise[i],valid_cnt[i]); + } + + for(i=RF92CD_PATH_A; i noise_max) + noise_max = noise[i]; + } + + noise_max -= 110; + } +#endif + + //fixme, noise pwr should not be positive + if(noise_max >= 0) { + DEBUG_INFO("%s %d SNR is positive, force to ignorable value!\n",__func__,__LINE__); + noise_max = -128; + } + + priv->rtk->survey_info[idx].noise = noise_max; + DEBUG_INFO("%s %d channel:%d noise floor:%d\n",__func__,__LINE__,priv->rtk->survey_info[idx].channel,priv->rtk->survey_info[idx].noise); + + return ret; +} +#endif//end RTK_NL80211 + +#if defined(CLIENT_MODE) && defined(WIFI_11N_2040_COEXIST) +void start_clnt_coexist_scan(struct rtl8192cd_priv *priv) +{ + static unsigned int to_issue_coexist_mgt = 0; + int do_scan = 1; + int throughput = 0; + + if (((priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N | WIRELESS_11G)) == (WIRELESS_11N | WIRELESS_11G)) && + priv->pmib->dot11nConfigEntry.dot11nCoexist && + priv->coexist_connection && + (!(priv->up_time % 85) || to_issue_coexist_mgt)) + { + throughput = (priv->ext_stats.tx_avarage + priv->ext_stats.rx_avarage) * 8; + if (throughput > 1024) + do_scan = 0; + +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + throughput = (GET_ROOT(priv)->ext_stats.tx_avarage + GET_ROOT(priv)->ext_stats.rx_avarage) * 8; + if (throughput > 1024) + do_scan = 0; + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + int i; + for (i=0; ipvap_priv[i])) { + throughput = (GET_ROOT(priv)->pvap_priv[i]->ext_stats.tx_avarage + GET_ROOT(priv)->pvap_priv[i]->ext_stats.rx_avarage) * 8; + if (throughput > 1024) + do_scan = 0; + } + } + } +#endif + } +#endif + + if(!(priv->up_time % 85) && do_scan) { + priv->ss_ssidlen = 0; + DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=0\n", (char *)__FUNCTION__); + priv->ss_req_ongoing = 1; + start_clnt_ss(priv); + to_issue_coexist_mgt++; + } + + if (to_issue_coexist_mgt && !(OPMODE & WIFI_SITE_MONITOR) && + (priv->bg_ap_timeout || priv->intolerant_timeout)) { + issue_coexist_mgt(priv); + to_issue_coexist_mgt = 0; + } + } +} +#endif + + +#ifdef CONFIG_IEEE80211W +void issue_actionFrame(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + struct list_head *phead, *plist; +#ifdef SMP_SYNC + unsigned long local_flags = 0; +#endif + + if (priv->pmib->dot11StationConfigEntry.pmftest == 1) { // for PMF case 4.4, protect broadcast mgmt frame by BIP + PMFDEBUG("%s(%d) issue broadcast deauth\n", __FUNCTION__, __LINE__); + memcpy(priv->pmib->dot11StationConfigEntry.deauth_mac,"\xff\xff\xff\xff\xff\xff",6); + issue_deauth(priv, priv->pmib->dot11StationConfigEntry.deauth_mac, _RSON_UNSPECIFIED_); + + phead = &priv->asoc_list; + if (netif_running(priv->dev) && !list_empty(phead)) { + SMP_LOCK_ASOC_LIST(local_flags); + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + SMP_UNLOCK_ASOC_LIST(local_flags); + + PMFDEBUG("pstat=%02x%02x%02x%02x%02x%02x\n", pstat->hwaddr[0] + , pstat->hwaddr[1] + , pstat->hwaddr[2] + , pstat->hwaddr[3] + , pstat->hwaddr[4] + , pstat->hwaddr[5]); + del_station(priv,pstat, 0); + + SMP_LOCK_ASOC_LIST(local_flags); + plist = phead->next; + } + SMP_UNLOCK_ASOC_LIST(local_flags); + } + priv->pmib->dot11StationConfigEntry.pmftest = 0; + } else if (priv->pmib->dot11StationConfigEntry.pmftest == 2) { + PMFDEBUG("issue unicast deauth\n"); + pstat = get_stainfo(priv, priv->pmib->dot11StationConfigEntry.deauth_mac); + if (!pstat) { + PMFDEBUG("no associated STA (%02x%02x%02x%02x%02x%02x)\n" + ,priv->pmib->dot11StationConfigEntry.deauth_mac[0] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[1] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[2] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[3] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[4] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[5]); + } else { + issue_deauth(priv, priv->pmib->dot11StationConfigEntry.deauth_mac, _RSON_UNSPECIFIED_); + del_station(priv,pstat, 0); + } + priv->pmib->dot11StationConfigEntry.pmftest = 0; + } +#ifdef CONFIG_IEEE80211W_CLI_DEBUG + else if (priv->pmib->dot11StationConfigEntry.pmftest == 3) { // CONFIG_IEEE80211W_CLI + panic_printk("%s(%d) issue unicast disassoc\n", __FUNCTION__, __LINE__); + pstat = get_stainfo(priv, priv->pmib->dot11StationConfigEntry.deauth_mac); + if (!pstat) { + panic_printk("%s(%d) no associated STA (%02x%02x%02x%02x%02x%02x)\n", __FUNCTION__, __LINE__ + ,priv->pmib->dot11StationConfigEntry.deauth_mac[0] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[1] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[2] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[3] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[4] + ,priv->pmib->dot11StationConfigEntry.deauth_mac[5]); + } else { + issue_disassoc(priv, priv->pmib->dot11StationConfigEntry.deauth_mac, _RSON_UNSPECIFIED_); + del_station(priv,pstat, 0); + } + priv->pmib->dot11StationConfigEntry.pmftest = 0; + } else if (priv->pmib->dot11StationConfigEntry.pmftest == 4) { // CONFIG_IEEE80211W_CLI + panic_printk("%s(%d) issue SA Request\n", __FUNCTION__, __LINE__); + pstat = get_stainfo(priv, priv->pmib->dot11StationConfigEntry.sa_req_mac); + if (!pstat) { + panic_printk("%s(%d) no associated STA (%02x%02x%02x%02x%02x%02x)\n", __FUNCTION__, __LINE__ + ,priv->pmib->dot11StationConfigEntry.sa_req_mac[0] + ,priv->pmib->dot11StationConfigEntry.sa_req_mac[1] + ,priv->pmib->dot11StationConfigEntry.sa_req_mac[2] + ,priv->pmib->dot11StationConfigEntry.sa_req_mac[3] + ,priv->pmib->dot11StationConfigEntry.sa_req_mac[4] + ,priv->pmib->dot11StationConfigEntry.sa_req_mac[5]); + } else { + if (pstat->sa_query_count == 0) { + panic_printk("sa_query_end=%lu, sa_query_start=%lu\n", pstat->sa_query_end, pstat->sa_query_start); + pstat->sa_query_count++; + issue_SA_Query_Req(priv->dev,priv->pmib->dot11StationConfigEntry.sa_req_mac); + + panic_printk("%s(%d), settimer, %x\n", __FUNCTION__, __LINE__, &pstat->SA_timer); + + if (timer_pending(&pstat->SA_timer)) + del_timer(&pstat->SA_timer); + + pstat->SA_timer.data = (unsigned long) pstat; + pstat->SA_timer.function = rtl8192cd_sa_query_timer; + mod_timer(&pstat->SA_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(SA_QUERY_RETRY_TO)); + panic_printk("%s(%d), settimer end\n", __FUNCTION__, __LINE__); + } + } + priv->pmib->dot11StationConfigEntry.pmftest = 0; + } else if (priv->pmib->dot11StationConfigEntry.pmftest == 5) { // for PMF case 4.4, protect broadcast mgmt frame by BIP + panic_printk("%s(%d) issue broadcast diassoc\n", __FUNCTION__, __LINE__); // CONFIG_IEEE80211W_CLI + memcpy(priv->pmib->dot11StationConfigEntry.deauth_mac,"\xff\xff\xff\xff\xff\xff",6); + issue_disassoc(priv, priv->pmib->dot11StationConfigEntry.deauth_mac, _RSON_UNSPECIFIED_); + + phead = &priv->asoc_list; + if (netif_running(priv->dev) && !list_empty(phead)) { + SMP_LOCK_ASOC_LIST(local_flags); + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + SMP_UNLOCK_ASOC_LIST(local_flags); + + panic_printk("pstat=%02x%02x%02x%02x%02x%02x\n", pstat->hwaddr[0] + , pstat->hwaddr[1] + , pstat->hwaddr[2] + , pstat->hwaddr[3] + , pstat->hwaddr[4] + , pstat->hwaddr[5]); + del_station(priv,pstat, 0); + + SMP_LOCK_ASOC_LIST(local_flags); + plist = phead->next; + } + SMP_UNLOCK_ASOC_LIST(local_flags); + } + priv->pmib->dot11StationConfigEntry.pmftest = 0; + } +#endif +} +#endif // CONFIG_IEEE80211W + +void rtl8192cd_expire_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned long flags=0; + int somevapopened=0; +#ifdef MBSSID + int i; +#endif + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + +#ifdef MULTI_MAC_CLONE + ACTIVE_ID = 0; +#endif + + // advance driver up timer + priv->up_time++; + +#ifdef TLN_STATS + if (priv->pshare->rf_ft_var.stats_time_interval) { + if (priv->stats_time_countdown) { + priv->stats_time_countdown--; + } else { + memset(&priv->wifi_stats, 0, sizeof(struct tln_wifi_stats)); + memset(&priv->ext_wifi_stats, 0, sizeof(struct tln_ext_wifi_stats)); + + priv->stats_time_countdown = priv->pshare->rf_ft_var.stats_time_interval; + } + } +#endif + +#ifdef INCLUDE_WPS + // mount wsp wps_1sec_routine +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + +#ifndef CONFIG_MSC // for verify + if(priv->pshare->WSC_CONT_S.RdyGetConfig == 0){ + // if not get config from upnp yet ; send request + unsigned char tmp12[20]; + sprintf(tmp12 , "wps_get_config=1"); + set_mib(priv , tmp12) ; + } +#endif + if(priv->pshare->WSC_CONT_S.oneSecTimeStart){ + wps_1sec_routine(priv); + } + else{ + printk("%s %d not enter wsc 1sec \n", __FUNCTION__, __LINE__); + } + } +#endif + + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) { + SMP_UNLOCK(flags); + RESTORE_INT(flags); + return; + } +#endif + + +#ifdef CONFIG_RTK_MESH + if ((GET_MIB(priv)->dot1180211sInfo.mesh_enable == 1 ) +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) // fix: 0000107 2008/10/13 + && IS_ROOT_INTERFACE(priv) +#endif + ) { + if( priv->mesh_log ) // advance flow log timer Throughput statistics (sounder) + priv->log_time++; + + mesh_expire(priv); + } + +#ifdef _11s_TEST_MODE_ + mesh_debug_sme1(priv); +#endif + +#endif // DOT11_MESH_MODE_ + + // check auth_list + auth_expire(priv); + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + if ((priv->up_time % 2) == 0) + priv->pshare->highTP_found_pstat = NULL; + priv->pshare->rssi_min = 0xff; +#ifdef RSSI_MIN_ADV_SEL + priv->pshare->min_rssi_data_cnt = 0; +#endif +#ifdef CLIENT_MODE + if((OPMODE & WIFI_ADHOC_STATE) && (priv->prev_tsf)) { + UINT64 tsf, tsf_diff; + tsf = RTL_R32(TSFTR+4); + tsf = (tsf<<32) + RTL_R32(TSFTR); + tsf_diff = tsf - priv->prev_tsf; + priv->prev_tsf = tsf; + if( (tsf > priv->prev_tsf) && (tsf_diff > BIT(24))) { + tsf = cpu_to_le64(tsf); + memcpy(priv->rx_timestamp, (void*)(&tsf), 8); + updateTSF(priv); + } + } +#endif + } + + // check asoc_list + assoc_expire(priv); + +#if defined(DRVMAC_LB) && defined(WIFI_WMM) + if (priv->pmib->miscEntry.drvmac_lb && priv->pmib->miscEntry.lb_tps) { + unsigned int i = 0; + for (i = 0; i < priv->pmib->miscEntry.lb_tps; i++) { + if (priv->pmib->miscEntry.lb_mlmp) + SendLbQosData(priv); + else + SendLbQosNullData(priv); +// if (i > 4) +// priv->pmib->miscEntry.lb_tps = 0; + } + } +#endif + +#ifdef WIFI_SIMPLE_CONFIG + // check wsc probe request list + if (priv->pmib->wscEntry.wsc_enable & 2) // work as AP (not registrar) + wsc_probe_expire(priv); + wsc_disconn_list_expire(priv); +#endif + +#ifdef WDS + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11WdsInfo.wdsEnabled && + priv->pmib->dot11WdsInfo.wdsNum){ + wds_probe_expire(priv); + } +#endif + + // check link status and start/stop net queue + priv->link_status = chklink_wkstaQ(priv); + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + if (priv->link_status != priv->link_status_bak) { + if (priv->link_status_cb_func) + priv->link_status_cb_func("wlan0", priv->link_status); + } + } +#endif + priv->link_status_bak = priv->link_status; +#endif + +#ifdef RTK_AC_SUPPORT //for 11ac logo + // channel switch + if(priv->pshare->rf_ft_var.csa) { + int ch = priv->pshare->rf_ft_var.csa; + priv->pshare->rf_ft_var.csa = 0; + + GET_ROOT(priv)->pmib->dot11DFSEntry.DFS_detected = 1; + priv->pshare->dfsSwitchChannel = ch; + priv->pshare->dfsSwitchChCountDown = 6; + if (priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod >= priv->pshare->dfsSwitchChCountDown) + priv->pshare->dfsSwitchChCountDown = priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod+1; + } +#endif + + // for SW LED + if ((LED_TYPE >= LEDTYPE_SW_LINK_TXRX) && (LED_TYPE < LEDTYPE_SW_MAX)) + { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state != L1) && (priv->pwr_state != L2)) +#endif + calculate_sw_LED_interval(priv); + } + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)!=VERSION_8188E) +#endif + { +#ifdef CLIENT_MODE + if (((OPMODE & WIFI_AP_STATE) || + ((OPMODE & WIFI_ADHOC_STATE) && + ((JOIN_RES == STATE_Sta_Ibss_Active) || (JOIN_RES == STATE_Sta_Ibss_Idle)))) && + (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) +#else + if ((OPMODE & WIFI_AP_STATE) && + (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) +#endif + { + if (priv->pmib->dot11ErpInfo.olbcDetected) { + if (priv->pmib->dot11ErpInfo.olbcExpired > 0) + priv->pmib->dot11ErpInfo.olbcExpired--; + + if (priv->pmib->dot11ErpInfo.olbcExpired == 0) { + priv->pmib->dot11ErpInfo.olbcDetected = 0; + DEBUG_INFO("OLBC expired\n"); + check_protection_shortslot(priv); + } + } + } + } + +#ifdef TX_EARLY_MODE + priv->pshare->em_tx_byte_cnt = priv->ext_stats.tx_byte_cnt; +#endif + + // calculate tx/rx throughput + priv->ext_stats.tx_avarage = (priv->ext_stats.tx_avarage/10)*7 + (priv->ext_stats.tx_byte_cnt/10)*3; + priv->ext_stats.tx_byte_cnt = 0; + priv->ext_stats.rx_avarage = (priv->ext_stats.rx_avarage/10)*7 + (priv->ext_stats.rx_byte_cnt/10)*3; + priv->ext_stats.rx_byte_cnt = 0; + +#ifdef RTK_NL80211 +#if 0 //brian, collect channel load information during sitesurvey in stead of here to make sure freshness + //survey_dump + int val = read_bbp_ch_load(priv); + if(val != -1) + { + priv->rtk->chbusytime = (val/1000)*5; + start_bbp_ch_load(priv); + } + check_sta_throughput(priv); +#endif + //openwrt_psd + if(priv->rtk->psd_chnl != 0) + rtl8192cd_query_psd_cfg80211(priv, priv->rtk->psd_chnl, priv->rtk->psd_bw, priv->rtk->psd_pts); + priv->rtk->psd_chnl=0; + priv->rtk->psd_bw=0; + priv->rtk->psd_pts=0; +#endif + +#ifdef CONFIG_RTL8190_THROUGHPUT +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + unsigned long throughput; + + throughput = (priv->ext_stats.tx_avarage + priv->ext_stats.rx_avarage) * 8 / 1024 / 1024; /* unit: Mbps */ + if (gCpuCanSuspend) { + if (throughput > TP_HIGH_WATER_MARK) { + gCpuCanSuspend = 0; + } + } + else { + if (throughput < TP_LOW_WATER_MARK) { + gCpuCanSuspend = 1; + } + } +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) { + if( (((priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage) * 8)/1024)/1024 > 50 ) //when TH > 50Mbps + { + if(!priv->bIntMigration){ + RTL_W32(REG_INT_MIG_8812,0x30300000); + RTL_W16(REG_PCIE_MULTIFET_CTRL_8812,0xF450); + priv->bIntMigration=1; + //SDEBUG("bIntMigration=1\n"); + } + }else{ + if(priv->bIntMigration){ + RTL_W32(REG_INT_MIG_8812,0); + RTL_W16(REG_PCIE_MULTIFET_CTRL_8812,0); + priv->bIntMigration=0; + //SDEBUG("bIntMigration=0\n"); + } + } + } +#endif + } +#endif + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196C_EC) + if (priv->ext_stats.tx_avarage > priv->ext_stats.tx_peak) + priv->ext_stats.tx_peak = priv->ext_stats.tx_avarage; + + if (priv->ext_stats.rx_avarage > priv->ext_stats.rx_peak) + priv->ext_stats.rx_peak = priv->ext_stats.rx_avarage; +#endif +//#ifdef CONFIG_RTL865X_AC +#if defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) + if (priv->ext_stats.tx_avarage > priv->ext_stats.tx_peak) + priv->ext_stats.tx_peak = priv->ext_stats.tx_avarage; + + if (priv->ext_stats.rx_avarage > priv->ext_stats.rx_peak) + priv->ext_stats.rx_peak = priv->ext_stats.rx_avarage; +#endif + +#ifdef CLIENT_MODE + if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) + { + + // calculate how many beacons we received and decide if should roaming +#ifdef DFS + if (!priv->pshare->dfsSwCh_ongoing) +#endif + calculate_rx_beacon(priv); + +#ifdef RTK_BR_EXT + // expire NAT2.5 entry + nat25_db_expire(priv); + + if (priv->pppoe_connection_in_progress > 0) + priv->pppoe_connection_in_progress--; +#endif + } +#endif + +#ifdef A4_STA + if (OPMODE & WIFI_AP_STATE) + a4_sta_expire(priv); +#endif + +#ifdef MP_TEST +#ifdef CONFIG_PCI_HCI + if ((OPMODE & (WIFI_MP_CTX_BACKGROUND|WIFI_MP_CTX_BACKGROUND_PENDING)) == + (WIFI_MP_CTX_BACKGROUND|WIFI_MP_CTX_BACKGROUND_PENDING)) +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif +#endif // CONFIG_PCI_HCI + + + if (OPMODE & WIFI_MP_RX) { + if (priv->pshare->rf_ft_var.rssi_dump) { +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + panic_printk("%d%% (ss %d %d )(snr %d %d )(sq %d %d)\n", + priv->pshare->mp_rssi, + priv->pshare->mp_rf_info.mimorssi[0], priv->pshare->mp_rf_info.mimorssi[1], + priv->pshare->mp_rf_info.RxSNRdB[0], priv->pshare->mp_rf_info.RxSNRdB[1], + priv->pshare->mp_rf_info.mimosq[0], priv->pshare->mp_rf_info.mimosq[1]); + } +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + panic_printk("%d%% (ss %d %d )(snr %d %d )(sq %d %d)\n", + priv->pshare->mp_rssi, + priv->pshare->mp_rf_info.mimorssi[0], priv->pshare->mp_rf_info.mimorssi[1], + priv->pshare->mp_rf_info.RxSNRdB[0], priv->pshare->mp_rf_info.RxSNRdB[1], + priv->pshare->mp_rf_info.mimosq[0], priv->pshare->mp_rf_info.mimosq[1]); + } +#endif + } + } +#endif + + // Realtek proprietary IE +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)!=VERSION_8188E) +#endif + process_rtk_ie(priv); + + // check ACL log event + if ((OPMODE & WIFI_AP_STATE) && priv->acLogCountdown > 0) { + if (--priv->acLogCountdown == 0) + if (aclog_check(priv) > 0) // still have active entry + priv->acLogCountdown = AC_LOG_TIME; + } + +#ifdef CLIENT_MODE + if (OPMODE & WIFI_AP_STATE) +#endif + { + // 11n protection count down + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + if (priv->ht_legacy_obss_to > 0) + priv->ht_legacy_obss_to--; + if (priv->ht_nomember_legacy_sta_to > 0) + priv->ht_nomember_legacy_sta_to--; + } + } +#ifdef WIFI_11N_2040_COEXIST + if (priv->pmib->dot11nConfigEntry.dot11nCoexist && ((OPMODE & WIFI_AP_STATE) +#ifdef CLIENT_MODE + || ((OPMODE & WIFI_STATION_STATE) && priv->coexist_connection) +#endif + ) && (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G))) { + if (priv->bg_ap_timeout) { + // don't go back to 40M mode for 6300 wrong channel issue + if (orSTABitMap(&priv->pshare->intel_sta_bitmap) == 0) { + priv->bg_ap_timeout--; + if (0 == priv->bg_ap_timeout) { +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 0); +#endif + SetTxPowerLevel(priv); + } + } else { + priv->bg_ap_timeout = 60; + } +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + unsigned int i; + for (i = 0; i < 14; i++) + if (priv->bg_ap_timeout_ch[i]) + priv->bg_ap_timeout_ch[i]--; + } +#endif + } +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_STATION_STATE) && priv->intolerant_timeout) + priv->intolerant_timeout--; +#endif + } +#endif + + // Dump Rx FiFo overflow count + if (priv->pshare->rf_ft_var.rxfifoO) { + panic_printk("RxFiFo Overflow: %d\n", (unsigned int)(priv->ext_stats.rx_fifoO - priv->pshare->rxFiFoO_pre)); + priv->pshare->rxFiFoO_pre = priv->ext_stats.rx_fifoO; + } + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef WIFI_WMM + if (QOS_ENABLE) { +#ifdef CLIENT_MODE + if((OPMODE & WIFI_STATION_STATE) && (!priv->link_status) && (priv->pmib->dot11QosEntry.EDCA_STA_config)) { + reset_EDCA_para(priv); + } +#endif + } +#endif + + if (fw_was_full(priv) && priv->pshare->fw_free_space > 0) { // there are free space for STA + // do some algorithms to re-alloc STA into free space + realloc_RATid(priv); + } + +#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE) { + if (!GET_EM_SWQ_ENABLE) { + if (priv->pshare->em_tx_byte_cnt > EM_TP_UP_BOUND) + priv->pshare->reach_tx_limit_cnt++; + else + priv->pshare->reach_tx_limit_cnt = 0; + + if (priv->pshare->txop_enlarge && priv->pshare->reach_tx_limit_cnt >= WAIT_TP_TIME) { + GET_EM_SWQ_ENABLE = 1; + priv->pshare->reach_tx_limit_cnt = 0; + enable_em(priv); + } + } + else { + if (priv->pshare->em_tx_byte_cnt < EM_TP_LOW_BOUND) + priv->pshare->reach_tx_limit_cnt++; + else + priv->pshare->reach_tx_limit_cnt = 0; + + if (!priv->pshare->txop_enlarge || priv->pshare->reach_tx_limit_cnt >= WAIT_TP_TIME) { + GET_EM_SWQ_ENABLE = 0; + priv->pshare->reach_tx_limit_cnt = 0; + disable_em(priv); + } + } + } +#endif + + priv->pshare->phw->LowestInitRate = _NSS4_MCS9_RATE_; + } + +#ifdef USB_PKT_RATE_CTRL_SUPPORT + usbPkt_timer_handler(priv); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + if (CHIP_VER_92X_SERIES(priv)) + { + if (priv->pshare->rf_ft_var.auto_rts_rate) + SelectLowestInitRate(priv); + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv) && GET_VXD_PRIV(priv) && + netif_running(GET_VXD_PRIV(priv)->dev)) { + SMP_UNLOCK(flags); + rtl8192cd_expire_timer((unsigned long)GET_VXD_PRIV(priv)); + SMP_LOCK(flags); + } +#endif + + + if((GET_CHIP_VER(priv) != VERSION_8812E) && (GET_CHIP_VER(priv) != VERSION_8881A)) +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) +#endif + { + unsigned char intel_sta_connected = 0; + +#if defined(CONFIG_PCI_HCI) + if(is_intel_connected(priv)) + intel_sta_connected = 1; + +#ifdef MBSSID +// SMP_UNLOCK(flags); + if (priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) { + if(is_intel_connected(priv->pvap_priv[i])) { + intel_sta_connected = 1; + break; + } + } + } + } +// SMP_LOCK(flags); +#endif +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + intel_sta_connected = orSTABitMap(&priv->pshare->intel_sta_bitmap); +#endif + + if (!intel_sta_connected) { + unsigned int tmp_d2c = RTL_R32(0xd2c); + if((tmp_d2c & BIT(11)) == 0) + { + tmp_d2c = tmp_d2c | BIT(11); + RTL_W32(0xd2c, tmp_d2c); +#if 0 //eric-8814 ?? + tmp_d2c = RTL_R32(0xd2c); + if(tmp_d2c & BIT(11)) + printk("No Intel STA, BIT(11) of 0xd2c = %d, 0xd2c = 0x%x\n", 1, tmp_d2c); + else + printk("No Intel STA, BIT(11) of 0xd2c = %d, 0xd2c = 0x%x\n", 0, tmp_d2c); +#endif + } + } + } + +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) { + if (priv->pmib->miscEntry.vap_enable) { + SMP_UNLOCK(flags); + for (i=0; ipvap_priv[i])) { + rtl8192cd_expire_timer((unsigned long)priv->pvap_priv[i]); + + if(priv->pvap_priv[i]->pmib->miscEntry.func_off==0){ + somevapopened=1; + } + } + } + SMP_LOCK(flags); + } + } + +#endif + +#ifdef MBSSID +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if ((GET_ROOT(priv)->pmib->miscEntry.vap_enable)) { + if (priv->pmib->miscEntry.func_off) { + if (!priv->func_off_already) { + rtl8192cd_sort_mbssid_bcn(priv); + } + } else { + if (priv->func_off_already) { + rtl8192cd_sort_mbssid_bcn(priv); + } + } + } else +#endif + if (IS_ROOT_INTERFACE(priv)) +#endif + { + if (priv->pmib->miscEntry.func_off) { // func_off =1 + + if(somevapopened==0){ // not any VAP be opened and func_off not be enabled + /*minimum prohibit time[19:8] to 1*/ + RTL_W32(TBTT_PROHIBIT, (RTL_R32(TBTT_PROHIBIT)&0xfff000ff) | 0x100); + } else { + RTL_W32(TBTT_PROHIBIT, (RTL_R32(TBTT_PROHIBIT)&0xfff000ff) | 0x1df00); + } + if (!priv->func_off_already) { + RTL_W8(REG_MBSSID_CTRL, RTL_R8(REG_MBSSID_CTRL) & ~(BIT(0))); + priv->func_off_already = 1; + } + } + else { // func_off =0 + if (priv->func_off_already) { + RTL_W8(REG_MBSSID_CTRL, RTL_R8(REG_MBSSID_CTRL) | BIT(0)); + priv->func_off_already = 0; + + if(somevapopened==0) + RTL_W32(TBTT_PROHIBIT, (RTL_R32(TBTT_PROHIBIT)&0xfff000ff) | 0x40000); + else + RTL_W32(TBTT_PROHIBIT, (RTL_R32(TBTT_PROHIBIT)&0xfff000ff) | 0x1df00); + } + + } + + } +#ifdef MBSSID + else + if(IS_VAP_INTERFACE(priv)) + { + if (priv->pmib->miscEntry.func_off) { + if (!priv->func_off_already) { + RTL_W8(REG_MBSSID_CTRL, RTL_R8(REG_MBSSID_CTRL) & ~(1 << priv->vap_init_seq)); + priv->func_off_already = 1; + } + } + else { + if (priv->func_off_already) { + RTL_W8(REG_MBSSID_CTRL, RTL_R8(REG_MBSSID_CTRL) | (1 << priv->vap_init_seq)); + priv->func_off_already = 0; + } + } + } +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { +#ifdef MP_TEST + if (!((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) +#endif + { +#ifdef RSSI_MIN_ADV_SEL + select_rssi_min_from_data(priv); +#endif + +#ifdef INTERFERENCE_CONTROL + if (priv->pshare->rf_ft_var.rssi_dump && (priv->assoc_num == 0)) { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + panic_printk("(FA %x ", RTL_R8(0xc50)); + else +#endif + panic_printk("(FA %x,%x ", RTL_R8(0xc50), RTL_R8(0xc58)); + + panic_printk("%d, %d)\n", priv->pshare->ofdm_FA_total_cnt, priv->pshare->cck_FA_cnt); + } +#endif + +#ifdef BEAMFORMING_SUPPORT + if (((priv->up_time % 3) == 0) && (priv->pmib->dot11RFEntry.txbfer == 1) && + ((GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv) == VERSION_8192E) || GET_CHIP_VER(priv) == VERSION_8814A) ) + { + DynamicSelect2STA(priv); + } +#endif +#ifdef USE_OUT_SRC + if(!IS_OUTSRC_CHIP(priv)) +#endif + { + if ( ((OPMODE & WIFI_AP_STATE)?(!(priv->assoc_num)):(!(OPMODE & WIFI_ASOC_STATE))) +#ifdef UNIVERSAL_REPEATER + && !(GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.opmode & WIFI_ASOC_STATE) +#endif + ) + priv->pshare->rf_ft_var.bLinked = FALSE; + else + priv->pshare->rf_ft_var.bLinked = TRUE; + + rtl8192cd_CheckAdaptivity(priv); + } + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + int idx = 0, link=0; + struct stat_info* pEntry = findNextSTA(priv, &idx); + while(pEntry) { + if(pEntry && pEntry->expire_to) { + link=1; + break; + } + pEntry = findNextSTA(priv, &idx); + }; + ODM_CmnInfoUpdate(ODMPTR, ODM_CMNINFO_LINK, link ); + ODM_CmnInfoUpdate(ODMPTR, ODM_CMNINFO_RSSI_MIN, priv->pshare->rssi_min); +#ifdef UNIVERSAL_REPEATER + link = IS_DRV_OPEN(GET_VXD_PRIV(priv)) + && (GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.opmode & WIFI_ASOC_STATE); + ODM_CmnInfoUpdate(ODMPTR, ODM_CMNINFO_VXD_LINK, link); +#endif + if(priv->pshare->rf_ft_var.dig_enable && priv->pshare->DIG_on) + ODMPTR->DM_DigTable.bStopDIG = FALSE; + else + ODMPTR->DM_DigTable.bStopDIG = TRUE; + if(priv->pshare->rf_ft_var.adaptivity_enable) + ODM_CmnInfoUpdate(ODMPTR, ODM_CMNINFO_ABILITY, ODMPTR->SupportAbility | ODM_BB_ADAPTIVITY); + else + ODM_CmnInfoUpdate(ODMPTR, ODM_CMNINFO_ABILITY, ODMPTR->SupportAbility & (~ ODM_BB_ADAPTIVITY)); + + ODM_DMWatchdog(ODMPTR); + IotEngine(priv); + } +#endif + +#ifdef AUTO_CHANNEL_TIMEOUT + if (priv->pmib->miscEntry.autoch_timeout) { + printk("auto timeout expire\n"); + auto_channel_timeout_expire(priv); + } +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + //HAL timer callback entry point + GET_HAL_INTERFACE(priv)->Timer1SecHandler(priv); + } +#endif //CONFIG_WLAN_HAL + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST +if(!IS_OUTSRC_CHIP(priv)) +#endif +{ +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) +if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A)){ +} +else +#endif +{ + if (priv->up_time % 2) { +#ifdef CONFIG_RTL_NEW_AUTOCH + if( priv->auto_channel ==0 || priv->auto_channel ==2 ) +#endif + FA_statistic(priv); + + if ((priv->up_time > 5) && priv->pshare->rf_ft_var.dig_enable) + DIG_process(priv); + } + + + if (priv->pshare->rf_ft_var.auto_rts_rate) { + priv->pshare->phw->RTSInitRate_Candidate = + get_rate_index_from_ieee_value(find_rts_rate(priv, priv->pshare->phw->LowestInitRate, + priv->pmib->dot11ErpInfo.protection)); + + if (priv->pshare->phw->RTSInitRate_Candidate != priv->pshare->phw->RTSInitRate) { + priv->pshare->phw->RTSInitRate = priv->pshare->phw->RTSInitRate_Candidate; + RTL_W8(INIRTS_RATE_SEL, priv->pshare->phw->RTSInitRate); + } + } + +} + +#ifdef SW_ANT_SWITCH + if ((SW_DIV_ENABLE) && (priv->up_time % 4==1)) + dm_SW_AntennaSwitch(priv, SWAW_STEP_PEAK); +#endif +} +#endif + +#ifdef CONFIG_1RCCA_RF_POWER_SAVING + if (priv->pshare->rf_ft_var._1rcca_ps == 2) { + if (priv->pshare->rssi_min == 0xff) { // No Link + set_1rcca_ps(priv, 1); + } else { + if (priv->pshare->rssi_min > priv->pshare->rf_ft_var._1rcca_ps_rssi_thd) + set_1rcca_ps(priv, 1); + else + set_1rcca_ps(priv, 0); + } + } +#endif // CONFIG_1RCCA_RF_POWER_SAVING + } + + if (priv->pmib->dot11RFEntry.ther && priv->pshare->rf_ft_var.tpt_period) + TXPowerTracking(priv); + +#if defined(WIFI_11N_2040_COEXIST_EXT) + if((OPMODE & WIFI_AP_STATE)) + checkBandwidth(priv); +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST +if(!IS_OUTSRC_CHIP(priv)) +#endif +{ + +#ifdef HIGH_POWER_EXT_PA + if(CHIP_VER_92X_SERIES(priv)) { + if((priv->pshare->rf_ft_var.use_ext_pa) && (priv->pshare->rf_ft_var.tx_pwr_ctrl)) + tx_power_control(priv); + } +#endif + IOT_engine(priv); + rxBB_dm(priv); + +} +#endif + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + { + if ((priv->up_time % 3) == 1) { + if (priv->pshare->rssi_min != 0xff) { + if (priv->pshare->rf_ft_var.nbi_filter_enable) + check_NBI_by_rssi(priv, priv->pshare->rssi_min); + } + } + } +#endif + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if (CHIP_VER_92X_SERIES(priv)) { +#ifdef CONFIG_PCI_HCI + if (priv->pshare->txpause_pstat != NULL) { + if (TSF_DIFF(jiffies, priv->pshare->txpause_time) > RTL_SECONDS_TO_JIFFIES(1)) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->pshare->txpause_pstat = NULL; + } + } +#endif + } +#endif + + } + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (GET_CHIP_VER(priv) == VERSION_8812E)) { + struct list_head *plist, *phead; + struct stat_info *pstat; +#ifdef SMP_SYNC + unsigned long local_flags = 0; +#endif + phead = &priv->sleep_list; + + SMP_LOCK_SLEEP_LIST(local_flags); + + plist = phead->next; + while(plist != phead) + { + pstat = list_entry(plist, struct stat_info, sleep_list); + plist = plist->next; + + if (pstat->sta_in_firmware == 1) { + if (pstat->txpause_flag && (TSF_DIFF(jiffies, pstat->txpause_time) > RTL_SECONDS_TO_JIFFIES(1))) { +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)==VERSION_8812E) + RTL8812_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + else +#endif + { +#ifdef CONFIG_RTL_88E_SUPPORT + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); +#endif + } + pstat->txpause_time = 0; + pstat->txpause_flag = 0; + } + } + } + + SMP_UNLOCK_SLEEP_LIST(local_flags); + } else +#endif +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + struct list_head *plist, *phead; + struct stat_info *pstat; +#ifdef SMP_SYNC + unsigned long local_flags = 0; +#endif + phead = &priv->sleep_list; + + SMP_LOCK_SLEEP_LIST(local_flags); + + plist = phead->next; + while(plist != phead) + { + pstat = list_entry(plist, struct stat_info, sleep_list); + plist = plist->next; + + if (pstat->txpause_flag && (TSF_DIFF(jiffies, pstat->txpause_time) > RTL_SECONDS_TO_JIFFIES(1))) { + DEBUG_WARN("%s %d expire timeout, set MACID 0 AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + } + + SMP_UNLOCK_SLEEP_LIST(local_flags); + } else +#endif // CONFIG_WLAN_HAL + {} + + +#if defined(TXREPORT) + if ( CHIP_VER_92X_SERIES(priv) ||(GET_CHIP_VER(priv)==VERSION_8812E)) { + + + if (!IS_TEST_CHIP(priv)) + #ifdef MP_TEST + if (!((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) + #endif + #if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) + #endif + { + +#if defined(DETECT_STA_EXISTANCE) && (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + if(CHIP_VER_92X_SERIES(priv)) + LeavingSTA_RLCheck(priv); +#endif + if (!(priv->up_time%priv->pmib->staDetectInfo.txRprDetectPeriod) && (priv->pshare->sta_query_idx==-1)) { + priv->pshare->sta_query_idx = 0; +#if defined(CONFIG_RTL_8812_SUPPORT) + if((GET_CHIP_VER(priv)==VERSION_8812E)){ + requestTxReport_8812(priv); + } +#endif + if(CHIP_VER_92X_SERIES(priv)){ + requestTxReport(priv); + } + } + } + } +#endif + +#ifdef TXREPORT +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { +#ifdef MP_TEST + if (!((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) +#endif +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + if ( priv->pshare->sta_query_idx == -1) { + priv->pshare->sta_query_idx = 0; + requestTxReport88XX(priv); + } + } +#endif +#endif + +#ifdef CONFIG_IEEE80211W + issue_actionFrame(priv); +#endif + +#ifdef SW_TX_QUEUE +#ifdef HS2_SUPPORT + { + unsigned char zeromac[6]={0x00,0x00,0x00,0x00,0x00,0x00}; + + if (memcmp(priv->pmib->hs2Entry.sta_mac, zeromac, 6)) + { + DOT11_HS2_TSM_REQ tsmreq; + HS2_DEBUG_INFO("send bss tx mgmt req to STA:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", + priv->pmib->hs2Entry.sta_mac[0], priv->pmib->hs2Entry.sta_mac[1], + priv->pmib->hs2Entry.sta_mac[2], priv->pmib->hs2Entry.sta_mac[3], + priv->pmib->hs2Entry.sta_mac[4], priv->pmib->hs2Entry.sta_mac[5]); + memcpy(tsmreq.MACAddr, priv->pmib->hs2Entry.sta_mac, 6); + tsmreq.Req_mode = priv->pmib->hs2Entry.reqmode; + if (tsmreq.Req_mode & 0x08) + { + tsmreq.term_len = 12; + tsmreq.terminal_dur[0] = 4; + tsmreq.terminal_dur[1] = 10; + tsmreq.terminal_dur[10] = 0x01; + tsmreq.terminal_dur[11] = 0; + } + else + tsmreq.term_len = 0; + + tsmreq.Dialog_token = priv->pmib->hs2Entry.disassoc_timer & 0xff; + tsmreq.Disassoc_timer = priv->pmib->hs2Entry.disassoc_timer; + tsmreq.Validity_intval = priv->pmib->hs2Entry.validity_intval; + tsmreq.url_len = strlen(priv->pmib->hs2Entry.session_url); + memcpy(tsmreq.Session_url, priv->pmib->hs2Entry.session_url, tsmreq.url_len); + tsmreq.list_len = 0; + + issue_BSS_TSM_req(priv, &tsmreq); + memset(priv->pmib->hs2Entry.sta_mac, 0, 6); + } + } + +#ifdef HS2_CLIENT_TEST + //printk("swq_dbg=%d\n",priv->pshare->rf_ft_var.swq_dbg); + if (priv->pshare->rf_ft_var.swq_dbg != 0) + { + DOT11_HS2_GAS_REQ gas_req; + unsigned short query_id; + + if ((OPMODE & WIFI_ASOC_STATE) == 0) + { + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + delay_us(250); + } + + if ((priv->pshare->rf_ft_var.swq_dbg >= 30) && (priv->pshare->rf_ft_var.swq_dbg <= 39)) + { + unsigned char tmpda[]={0xff,0xff,0xff,0xff,0xff,0xff}; + issue_probereq(priv,"",0, tmpda); + goto hs_break; + } + if (priv->pshare->rf_ft_var.swq_dbg == 20) + { + unsigned char list[]={0x03,0x01,0x30,0x03,0x01,0x50}; + issue_BSS_TSM_query(priv, list, sizeof(list)); + priv->pshare->rf_ft_var.swq_dbg = 0; + goto hs_break; + } + + + + // query_id is identified by the issue_GASreq function + // refer to Table 8-184 + //capability List (Test Case 4.2 Proc. (a) in HS2.0 R2 Test Plan v.0.01) + if (priv->pshare->rf_ft_var.swq_dbg == 3) + query_id = 257; + //Roaming Consortium list (Test Case 4.4 Step2 in HS2.0 R2 Test Plan v.0.01) + else if (priv->pshare->rf_ft_var.swq_dbg == 4) + query_id = 261; + //venue name (Test Case 4.4 Step8 in HS2.0 R2 Test Plan v.0.01) + else if (priv->pshare->rf_ft_var.swq_dbg == 5) + query_id = 258; + // Network Authentication Type Information (Test Case 4.4 Step10 in HS2.0 R2 Test Plan v.0.01) + else if (priv->pshare->rf_ft_var.swq_dbg == 6) + query_id = 260; + //IP Address Type Availability Information (Test Case 4.4 Step12 in HS2.0 R2 Test Plan v.0.01) + else if (priv->pshare->rf_ft_var.swq_dbg == 7) + query_id = 262; + //combine nai_list+3gpp+domain_list (Test Case 4.4 Step4 in HS2.0 R2 Test Plan v.0.01) + else if (priv->pshare->rf_ft_var.swq_dbg == 8) + query_id = 10000; + //HS Capability list and Operator Friendly Name (Test Case 4.4 Step6 in HS2.0 R2 Test Plan v.0.01) + else if (priv->pshare->rf_ft_var.swq_dbg == 9) + query_id = 501; + //HS WAN Metrics and Connection Lists (Test Case 4.4 Step14 in HS2.0 R2 Test Plan v.0.01) + else if (priv->pshare->rf_ft_var.swq_dbg == 10) + query_id = 502; + //hs wan+hs no support type + else if (priv->pshare->rf_ft_var.swq_dbg == 18) + query_id = 505; + //hs home realm query, cnt=0 + else if (priv->pshare->rf_ft_var.swq_dbg == 19) + query_id = 506; + //hs operating class + else if (priv->pshare->rf_ft_var.swq_dbg == 21) + query_id = 507; + //hs home realm query (Test Case 4.4 Step16 in HS2.0 R2 Test Plan v.0.01) + else if (priv->pshare->rf_ft_var.swq_dbg == 11) + query_id = 503; + //hs 2 home realm query + else if (priv->pshare->rf_ft_var.swq_dbg == 17) + query_id = 504; + //advt protocol error + else if (priv->pshare->rf_ft_var.swq_dbg == 12) + query_id = 262; + // Query element (qid = roaming list) + HS2 WAN Metrics element + HS2 Operating Class Indication element + else if (priv->pshare->rf_ft_var.swq_dbg == 13) + query_id = 270; + //roaming list (qid = roaming list) + HS2 element (subtype = reserved) + HS Query List + else if (priv->pshare->rf_ft_var.swq_dbg == 14) + query_id = 271; + //nai list + else if (priv->pshare->rf_ft_var.swq_dbg == 15) + query_id = 263; + //capa+comback request + else if (priv->pshare->rf_ft_var.swq_dbg == 16) + { + query_id = 257; + testflg = 1; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 22) // for Test Case 4.3 Step 4 + query_id = 272; + else if (priv->pshare->rf_ft_var.swq_dbg == 23) // for Test Case 4.3 Step 6 + query_id = 0; + else if (priv->pshare->rf_ft_var.swq_dbg == 42) { // ICON Request + query_id = 508; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 43) { // Online Sign-Up Providers list + query_id = 509; + } + else + goto hs_break; + + gas_req.Dialog_token = 5; + issue_GASreq(priv, &gas_req, query_id); + HS2_DEBUG_INFO("send gas req\n"); + priv->pshare->rf_ft_var.swq_dbg = 0; + } +hs_break: +#endif +#endif + +#ifdef SW_TX_QUEUE_SMALL_PACKET_CHECK +// add for small udp packet(88B) test with veriwave tool (let sw tx queue start quickly after first round test) +// the interval between every round test is about 10sec +#if 1 + if ((priv->assoc_num > 1) && (AMPDU_ENABLE) && (priv->swq_txmac_chg >= priv->pshare->rf_ft_var.swq_en_highthd)) + priv->swq_boost_delay = 0; + else + priv->swq_boost_delay++; + + if (priv->swq_boost_delay >= 10) + priv->swq_boost_delay = 10; +#else + priv->swq_boost_delay = 0; +#endif +#endif + + //for debug + //if (priv->pshare->rf_ft_var.swq_dbg) + // printk("sw cnt:%d:%d,0x%x\n", priv->swq_txmac_chg,priv->swq_en, RTL_R32(EDCA_BE_PARA)); + + priv->swq_txmac_chg = 0; +#endif + +#if defined(CLIENT_MODE) && defined(WIFI_11N_2040_COEXIST) + if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + start_clnt_coexist_scan(priv); +#endif + +#ifdef RADIUS_ACCOUNTING + //brian add for accounting + if(ACCT_FUN) + { + cal_statistics_acct(priv); + expire_sta_for_radiusacct(priv); + } +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + switch(priv->pshare->intel_active_sta) { + case 0: + case 1: + priv->pshare->intel_rty_lmt = 0x30; /* 48 times */ + break; + case 2: + priv->pshare->intel_rty_lmt = 0x18; /* 24 times */ + break; + default: + priv->pshare->intel_rty_lmt = 0; /* use system default */ + break; + } + + priv->pshare->intel_active_sta = 0; + +#if defined(SMART_REPEATER_MODE) && !defined(RTK_NL80211) + if (priv->pshare->switch_chan_rp && + ((priv->pmib->dot11RFEntry.dot11channel != priv->pshare->switch_chan_rp) || + (priv->pmib->dot11nConfigEntry.dot11n2ndChOffset != priv->pshare->switch_2ndchoff_rp) || + (priv->pmib->dot11nConfigEntry.dot11nUse40M != priv->pshare->band_width_rp)) ) { + DEBUG_INFO("swtich chan=%d\n", priv->pshare->switch_chan_rp); + switch_chan_to_vxd(priv); + priv->pshare->switch_chan_rp = 0; + } +#endif + } + + /*for delay wsc client mode do Scan; special on repeater mode + if client mode do Scan too frequent and continous + will cause the client(that connected with repeater's AP interface) disconnect*/ +#if defined( WIFI_SIMPLE_CONFIG ) && defined(UNIVERSAL_REPEATER) + if(IS_VXD_INTERFACE(priv) && (OPMODE & WIFI_STATION_STATE)){ + if(priv->wsc_ss_delay){ + //STADEBUG("wsc_ss_delay remain[%d]\n",priv->wsc_ss_delay); + priv->wsc_ss_delay--; + } + } +#endif + +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(priv->pmib->dot11StationConfigEntry.sc_enabled == 1) + { + priv->simple_config_time++; + if(priv->simple_config_status == 0) + { + rtk_sc_start_simple_config(priv); + } + else if(priv->simple_config_status == 2) + { + if(priv->simple_config_time > priv->pmib->dot11StationConfigEntry.sc_get_sync_time) + { + rtk_sc_restart_simple_config(priv); + } + } + else if(priv->simple_config_status>=3 && priv->simple_config_status<=5) + { + if (OPMODE & WIFI_ASOC_STATE) + { + struct stat_info *pstat; + pstat = get_stainfo(priv, priv->pmib->dot11StationConfigEntry.dot11DesiredBssid); + if( pstat) + { + if((pstat->link_time >= priv->pmib->dot11StationConfigEntry.sc_check_link_time) || (pstat->wpa_sta_info->clientHndshkDone)) + { + priv->simple_config_status = 6; + panic_printk("connect to %s now!\n", priv->pmib->dot11StationConfigEntry.dot11DesiredSSID); + rtk_sc_stop_simple_config(priv); + } + } + } + else + { + if(priv->simple_config_time > priv->pmib->dot11StationConfigEntry.sc_connect_timeout) + { + rtk_sc_restart_simple_config(priv); + } + } + } + else if(priv->simple_config_status == 6) + { + //rtk_sc_stop_simple_config(priv); + } +#if defined(CONFIG_RTL_SIMPLE_CONFIG_USE_WPS_BUTTON) + if(priv->simple_config_status >= 2) + { + if(priv->pmib->wscEntry.wsc_enable) + priv->pmib->wscEntry.wsc_enable = 0; + } +#endif + + if(priv->pmib->dot11StationConfigEntry.sc_duration_time>0) + { + priv->pmib->dot11StationConfigEntry.sc_duration_time--; + if(priv->pmib->dot11StationConfigEntry.sc_duration_time == 0) + { + rtk_sc_stop_simple_config(priv); + } + } + } + else + { + if(priv->simple_config_status != 0) + { + priv->simple_config_status = 0; + } + } +#endif + + RESTORE_INT(flags); + SMP_UNLOCK(flags); +} + + +/* + * @brief System 1 sec timer + * + * @param task_priv: priv + * + * @retval void + */ +#if defined(CONFIG_PCI_HCI) +// #define CHECK_CRYPTO +void rtl8192cd_1sec_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; +#ifdef CHECK_CRYPTO + unsigned long flags; +#endif + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) { + goto expire_timer; + } +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL + if (!IS_HAL_CHIP(priv)) +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)!= VERSION_8812E) +#endif + if (!(priv->up_time % 5)) + tx_stuck_fix(priv); +#endif // CONFIG_PCI_HCI + +// 2009.09.08 +#ifdef CHECK_HANGUP +#ifdef MP_TEST + if (!((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) +#endif + if (check_hangup(priv)) + return; +#endif + +#ifdef CHECK_CRYPTO + // TODO: Filen, Check code below for 8881A & 92E + if(GET_CHIP_VER(priv) != VERSION_8192D) + if((RTL_R32(0x6B8) & 0x3) == 0x3) { + DEBUG_ERR("Cyrpto checked\n"); + SAVE_INT_AND_CLI(flags); + RTL_W8(0x522, 0x0F); + RTL_W8(0x6B8, 0xFF); + RTL_W8(0x101,0x0); + RTL_W8(0x21,0x35); + delay_us(250); + RTL_W8(0x101,0x02); + RTL_W8(0x522,0x0); + RESTORE_INT(flags); + } +#endif + + // for Rx dynamic tasklet +#ifdef CONFIG_RTL8672 + priv->pshare->rxInt_useTsklt = TRUE; +#else + if (priv->pshare->rxInt_data_delta > priv->pmib->miscEntry.rxInt_thrd) + priv->pshare->rxInt_useTsklt = TRUE; + else + priv->pshare->rxInt_useTsklt = FALSE; +#endif + priv->pshare->rxInt_data_delta = 0; + +#ifdef PCIE_POWER_SAVING +expire_timer: +#endif + +#ifdef __KERNEL__ + tasklet_schedule(&priv->pshare->oneSec_tasklet); +#else + rtl8192cd_expire_timer((unsigned long)priv); +#endif + +#ifdef P2P_SUPPORT + if (OPMODE & WIFI_P2P_SUPPORT) + P2P_1sec_timer(priv); +#endif + +#ifdef CONFIG_RTL_WLAN_DOS_FILTER + if ((block_sta_time > 0) && (block_priv == (unsigned long)priv)) + { + block_sta_time--; + } +#endif + + mod_timer(&priv->expire_timer, jiffies + EXPIRE_TO); +} +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef SDIO_STATISTICS +void update_sdio_statistics(struct rtl8192cd_priv *priv) +{ + struct priv_shared_info *pshare = priv->pshare; + unsigned long diff_time; + int i; + + diff_time = jiffies - pshare->statistic_update_time; + pshare->statistic_update_time = jiffies; + + for (i = 0; i < MAX_XMITBUF_PKT; ++i) { +#ifdef SDIO_STATISTICS_TIME + if (pshare->writeport_total_count[i]) + pshare->writeport_avg_time[i] = pshare->writeport_total_time[i] /pshare->writeport_total_count[i]; + else + pshare->writeport_avg_time[i] = 0; + pshare->writeport_total_time[i] = 0; +#endif + pshare->writeport_avg_count[i] = pshare->writeport_total_count[i]; + pshare->writeport_total_count[i] = 0; + } +} +#endif + +void pre_rtl8192cd_1sec_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if ((priv->pshare->bDriverStopped) || (priv->pshare->bSurpriseRemoved)) { + printk("[%s] bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", + __FUNCTION__, priv->pshare->bDriverStopped, priv->pshare->bSurpriseRemoved); + return; + } + + rtw_enqueue_timer_event(priv, &priv->expire_timer_event, ENQUEUE_TO_TAIL); + +#ifdef SDIO_STATISTICS + update_sdio_statistics(priv); +#endif +} + +#ifdef CONFIG_POWER_SAVE +void rtl8192cd_offload_expire_timer(struct rtl8192cd_priv *priv) +{ + struct list_head *phead, *plist; + struct stat_info *pstat; + unsigned long flags = 0; + int i, wakeup = 0; + + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if (pstat->expire_to > 1) + pstat->expire_to--; + else if (pstat->expire_to == 1) + wakeup = 1; + } + + SMP_UNLOCK_ASOC_LIST(flags); + + if (priv->pshare->pwr_state == RTW_STS_SUSPEND && wakeup) { + DEBUG_INFO("[%s,%d] STA expired time = 1, need resume driver to update aid map.\n", __FUNCTION__, __LINE__); + priv->pshare->pwr_state = RTW_STS_NORMAL; + priv->pshare->ps_ctrl = RTW_ACT_IDLE; + schedule_work(&GET_ROOT(priv)->ap_cmd_queue); + } + + if (IS_ROOT_INTERFACE(priv)) { +#ifdef UNIVERSAL_REPEATER + if (GET_VXD_PRIV(priv) && netif_running(GET_VXD_PRIV(priv)->dev)) { + rtl8192cd_offload_expire_timer(GET_VXD_PRIV(priv)); + } +#endif +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + rtl8192cd_offload_expire_timer(priv->pvap_priv[i]); + } + } +#endif + } +} +#endif // CONFIG_POWER_SAVE + +void rtl8192cd_1sec_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + +#ifdef SDIO_AP_OFFLOAD + if (priv->pshare->offload_function_ctrl) { +#ifdef CONFIG_POWER_SAVE + if (priv->pshare->total_assoc_num) + rtl8192cd_offload_expire_timer(priv); +#endif + goto out; + } +#endif + +#ifdef CHECK_HANGUP +#ifdef MP_TEST + if (!((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) +#endif + if (check_hangup(priv)) + return; +#endif + + rtl8192cd_expire_timer((unsigned long)priv); + +#ifdef P2P_SUPPORT + if (OPMODE & WIFI_P2P_SUPPORT) + P2P_1sec_timer(priv); +#endif + +out: + mod_timer(&priv->expire_timer, jiffies + EXPIRE_TO); +} +#endif + +#if !defined(__LINUX_2_6__) && !defined(__ECOS) +__IRAM_IN_865X +#endif +void pwr_state(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + struct stat_info *pstat; + unsigned char *sa, *pframe; + + pframe = get_pframe(pfrinfo); + sa = pfrinfo->sa; + pstat = get_stainfo(priv, sa); + + if (pstat == (struct stat_info *)NULL) + return; + + if (!(pstat->state & WIFI_ASOC_STATE)) + return; + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + local_bh_disable(); +#endif + + if (GetPwrMgt(pframe)) + { + if ((pstat->state & WIFI_SLEEP_STATE) == 0) { + pstat->state |= WIFI_SLEEP_STATE; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + pstat->sleep_time = jiffies; +#endif +#ifdef CONFIG_PCI_HCI + if(CHIP_VER_92X_SERIES(priv)) + { + if (pstat == priv->pshare->highTP_found_pstat) { + if (priv->pshare->txpause_pstat == NULL) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE)|STOP_BE|STOP_BK); + + + priv->pshare->txpause_pstat = pstat; + priv->pshare->txpause_time = jiffies; + + } + } + } +#endif // CONFIG_PCI_HCI + + if (pstat->sta_in_firmware == 1) + { + + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + DEBUG_WARN("%s %d client into ps, set MACID sleep AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + DEBUG_WARN("Pwr_state jiffies = %lu \n",jiffies); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 1, REMAP_AID(pstat)); + pstat->txpause_flag = 1; + pstat->txpause_time = jiffies; + + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8812E) { + RTL8812_MACID_PAUSE(priv, 1, REMAP_AID(pstat)); + pstat->txpause_flag = 1; + pstat->txpause_time = jiffies; + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + RTL8188E_MACID_PAUSE(priv, 1, REMAP_AID(pstat)); + pstat->txpause_flag = 1; + pstat->txpause_time = jiffies; + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_ps(priv, pstat); +#endif + } + } + } + + SAVE_INT_AND_CLI(flags); + if (wakeup_list_del(priv, pstat)) { + DEBUG_INFO("Del fr wakeup_list %02X%02X%02X%02X%02X%02X\n", sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]); + } + if (sleep_list_add(priv, pstat)) { + DEBUG_INFO("Add to sleep_list %02X%02X%02X%02X%02X%02X\n", sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]); + } + RESTORE_INT(flags); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + stop_sta_xmit(priv, pstat); +#endif + } else { + if (pstat->state & WIFI_SLEEP_STATE) { + pstat->state &= ~(WIFI_SLEEP_STATE); + +#ifdef CONFIG_PCI_HCI + if (pstat == priv->pshare->txpause_pstat) { +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E && (pstat->IOTPeer == HT_IOT_PEER_BROADCOM)) + RTL_W16(REG_RL_8812, priv->pshare->RL_setting); + else +#endif + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & 0xe0); + priv->pshare->txpause_pstat = NULL; + } +#endif // CONFIG_PCI_HCI + + if (pstat->sta_in_firmware == 1) + { + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if (pstat->txpause_flag) { + DEBUG_WARN("%s %d client leave ps, set MACID sleep AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + DEBUG_WARN("Pwr_state jiffies = %lu diff = %lu\n",jiffies,jiffies-pstat->txpause_time); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + pstat->txpause_time = 0; + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8812E) { + if (pstat->txpause_flag) { + RTL8812_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + pstat->txpause_time = 0; + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if (pstat->txpause_flag) { + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + pstat->txpause_time = 0; + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_ps(priv, pstat); +#endif + } + } + } + + SAVE_INT_AND_CLI(flags); + if (sleep_list_del(priv, pstat)) { + DEBUG_INFO("Del fr sleep_list %02X%02X%02X%02X%02X%02X\n", sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]); + } + RESTORE_INT(flags); + +#if defined(CONFIG_PCI_HCI) + if ((skb_queue_len(&pstat->dz_queue)) +#ifdef WIFI_WMM +#ifdef WMM_APSD + ||( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (QOS_ENABLE) && (APSD_ENABLE) && (pstat->QosEnabled) && (pstat->apsd_pkt_buffering) && + ((!isFFempty(pstat->VO_dz_queue->head, pstat->VO_dz_queue->tail)) || + (!isFFempty(pstat->VI_dz_queue->head, pstat->VI_dz_queue->tail)) || + (!isFFempty(pstat->BE_dz_queue->head, pstat->BE_dz_queue->tail)) || + (!isFFempty(pstat->BK_dz_queue->head, pstat->BK_dz_queue->tail)))) +#endif + || (!isFFempty(pstat->MGT_dz_queue->head, pstat->MGT_dz_queue->tail)) +#ifdef DZ_ADDBA_RSP + || pstat->dz_addba.used +#endif +#endif + ) { + SAVE_INT_AND_CLI(flags); + if (wakeup_list_add(priv, pstat)) { + DEBUG_INFO("Add to wakeup_list %02X%02X%02X%02X%02X%02X\n", sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]); + } + RESTORE_INT(flags); + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + wakeup_sta_xmit(priv, pstat); +#endif + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + local_bh_enable(); +#endif + +#if defined(CONFIG_WLAN_HAL) && defined(CONFIG_PCI_HCI) + if(IS_HAL_CHIP(priv)) + check_PS_set_HIQLMT(priv); +#endif + return; +} + +#ifdef HW_DETEC_POWER_STATE +void detect_hw_pwr_state(struct rtl8192cd_priv *priv, unsigned char macIDGroup) +{ + unsigned char i; + unsigned int pwr; + + switch(macIDGroup) + { + case 0: + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HW_PS_STATE0, (pu1Byte)&pwr); + break; + case 1: + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HW_PS_STATE1, (pu1Byte)&pwr); + break; + case 2: + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HW_PS_STATE2, (pu1Byte)&pwr); + break; + case 3: + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HW_PS_STATE3, (pu1Byte)&pwr); + break; + } + + // check PS change + for(i=0;i<32;i++) + { + // getHWPwrStateHander + priv->pshare->HWPwrState[i+(macIDGroup<<5)] = (pwr & BIT(i) ? 1:0); + + if(priv->pshare->HWPwroldState[i+(macIDGroup<<5)]!= priv->pshare->HWPwrState[i+(macIDGroup<<5)]) + { + + pwr_state_enhaced(priv,i+(macIDGroup<<5),priv->pshare->HWPwrState[i+(macIDGroup<<5)]); + +#ifdef CONFIG_8814_AP_MAC_VERI + priv->pwrStateHWCnt[i+(macIDGroup<<5)]++; + priv->hw_seq[i+(macIDGroup<<5)] = RTL_R16(0x1152); + + // if(priv->testResult == true) + { + printk("[%s][%d] MACID%x HW PS0=%x Seq=%x Cnt=%x\n", + __FUNCTION__,__LINE__,i,priv->pshare->HWPwrState[i+(macIDGroup<<5)],priv->hw_seq[i+(macIDGroup<<5)],priv->pwrStateHWCnt[i+(macIDGroup<<5)]); + } +#endif //#ifdef CONFIG_8814_AP_MAC_VERI + } + priv->pshare->HWPwroldState[i+(macIDGroup<<5)] = priv->pshare->HWPwrState[i+(macIDGroup<<5)]; + } +} + +__IRAM_IN_865X +void pwr_state_enhaced(struct rtl8192cd_priv *priv, unsigned char macID, unsigned char PwrBit) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned char i; + struct stat_info *pstat; + + if(macID > 0) + { + if((macID == 0x7E)) + { + for(i=0;i<128;i++) + { + priv->pshare->HWPwrStateUpdate[i] = false; + } + return; + } + + if((macID == 0x7F)) + { + return; + } + } + + priv->pshare->HWPwrStateUpdate[i] = true; + pstat = get_HW_mapping_sta(priv,macID); + + // get priv from aidarray + + priv = priv->pshare->aidarray[macID-1]->priv; + + if (pstat == (struct stat_info *)NULL) + { + printk("%s %d pstat NULL return\n",__FUNCTION__,__LINE__); + return; + } + + if (!(pstat->state & WIFI_ASOC_STATE)) + { + printk("%s %d pstat NULL return\n",__FUNCTION__,__LINE__); + return; + } + + if (PwrBit == 1) + { + if ((pstat->state & WIFI_SLEEP_STATE) == 0) { + pstat->state |= WIFI_SLEEP_STATE; + if (pstat->sta_in_firmware == 1) + { + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 1, REMAP_AID(pstat)); + pstat->txpause_flag = 1; + pstat->txpause_time = jiffies; + } + } + + SAVE_INT_AND_CLI(flags); + wakeup_list_del(priv, pstat); + sleep_list_add(priv, pstat); + RESTORE_INT(flags); + + } else { + if (pstat->state & WIFI_SLEEP_STATE) { + pstat->state &= ~(WIFI_SLEEP_STATE); + + if (pstat->sta_in_firmware == 1) + { + DEBUG_WARN("%s %d client leave ps, set MACID sleep AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + DEBUG_WARN("Pwr_state jiffies = %x diff = %d\n",jiffies,jiffies-pstat->txpause_time); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + pstat->txpause_time = 0; + } + } + + SAVE_INT_AND_CLI(flags); + sleep_list_del(priv, pstat); + RESTORE_INT(flags); + + if ((skb_queue_len(&pstat->dz_queue)) +#ifdef WIFI_WMM +#ifdef WMM_APSD + ||( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (QOS_ENABLE) && (APSD_ENABLE) && (pstat->QosEnabled) && (pstat->apsd_pkt_buffering) && + ((!isFFempty(pstat->VO_dz_queue->head, pstat->VO_dz_queue->tail)) || + (!isFFempty(pstat->VI_dz_queue->head, pstat->VI_dz_queue->tail)) || + (!isFFempty(pstat->BE_dz_queue->head, pstat->BE_dz_queue->tail)) || + (!isFFempty(pstat->BK_dz_queue->head, pstat->BK_dz_queue->tail)))) +#endif + || (!isFFempty(pstat->MGT_dz_queue->head, pstat->MGT_dz_queue->tail)) +#ifdef DZ_ADDBA_RSP + || pstat->dz_addba.used +#endif +#endif + ) { + SAVE_INT_AND_CLI(flags); + if (wakeup_list_add(priv, pstat)) { + //DEBUG_INFO("Add to wakeup_list %02X%02X%02X%02X%02X%02X\n", sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]); + } + RESTORE_INT(flags); + } + } + + if(IS_HAL_CHIP(priv)) + check_PS_set_HIQLMT(priv); + + return; +} +#endif //#ifdef HW_DETEC_POWER_STATE + + +#ifdef CONFIG_WLAN_HAL +void check_PS_set_HIQLMT(struct rtl8192cd_priv *priv) +{ + u1Byte HiQLMTEn; + u1Byte tmp; + + +#ifdef MBSSID + if(priv->sleep_list.next != &priv->sleep_list) // one client into PS mode + { + if (IS_ROOT_INTERFACE(priv)) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + HiQLMTEn = HiQLMTEn & (~BIT0); + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&tmp); + } + else { + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + HiQLMTEn = HiQLMTEn & ~(BIT(priv->vap_init_seq)); + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&tmp); + } + } + } + else { // all client leave PS mode + if (IS_ROOT_INTERFACE(priv)) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + HiQLMTEn = HiQLMTEn | BIT0; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&tmp); + } + else { + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + HiQLMTEn = HiQLMTEn | BIT(priv->vap_init_seq); + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&tmp); + } + } + } +#else + if(priv->sleep_list.next != &priv->sleep_list) // one client into PS mode + { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + HiQLMTEn = HiQLMTEn & (~BIT0); + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&tmp); + } + else { + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + HiQLMTEn = HiQLMTEn | BIT0; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&HiQLMTEn); + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_HIQ_NO_LMT_EN, (pu1Byte)&tmp); + } + +#endif //#ifdef MBSSID + } +#endif //CONFIG_WLAN_HAL + +#ifdef CONFIG_IEEE80211W +enum _ROBUST_FRAME_STATE_{ + NOT_ROBUST_MGMT = 0, + IS_ROBUST_MGMT = 1, + MGMT_FRAME_MIC_ERR = 2, +}; + +static int isCorrectRobustFrame(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *pframe = get_pframe(pfrinfo); + unsigned char Category_field; + struct stat_info *pstat = get_stainfo(priv, pfrinfo->sa); +#ifdef CONFIG_IEEE80211W_CLI + unsigned char *da = GetAddr1Ptr(pframe); +#endif + + if (pframe[0] == WIFI_DEAUTH || pframe[0] == WIFI_DISASSOC || pframe[0] == WIFI_WMM_ACTION) { + if (GetPrivacy(pframe) && pstat +#ifdef CONFIG_IEEE80211W_CLI + && !IS_MCAST(da) +#endif + ) { + unsigned char mic[8]; + + // Add sanity check to avoid core dump in aes_tx due to plen is extraordinary big(0xfffffffx) + if (pfrinfo->pktlen <= pfrinfo->hdr_len+16) + return MGMT_FRAME_MIC_ERR; + + memcpy(mic,pframe + pfrinfo->pktlen - 8, 8); + if (aesccmp_decrypt(priv, pfrinfo, 1) == FALSE) + return MGMT_FRAME_MIC_ERR; + + if (!aesccmp_checkmic(priv, pfrinfo, mic)) { +#ifdef PMF_DEBUGMSG + if(pframe[0] == WIFI_DEAUTH) { + PMFDEBUG("DEAUTH MIC_ERR[%s]\n", priv->dev->name); + } else if(pframe[0] == WIFI_DISASSOC) { + PMFDEBUG("DISASSOC MIC_ERR[%s]\n", priv->dev->name); + } else { + PMFDEBUG(" MIC_ERR[%s]\n", priv->dev->name); + } +#endif + return MGMT_FRAME_MIC_ERR; + } + else { + memcpy(pframe + pfrinfo->hdr_len, pframe + pfrinfo->hdr_len + 8, pfrinfo->pktlen - pfrinfo->hdr_len - 8 - 8); + pfrinfo->pktlen = pfrinfo->pktlen - 16; + } + } +#ifdef CONFIG_IEEE80211W_CLI + if ((priv->support_pmf == TRUE) && pstat) { + pstat->isPMF = TRUE; + } +#endif + } + + if (pframe[0] == WIFI_DEAUTH || pframe[0] == WIFI_DISASSOC) + { + return IS_ROBUST_MGMT; + } + //pframe += WLAN_HDR_A3_LEN; // Action Field + + if (pframe[0] == WIFI_WMM_ACTION) { + Category_field = pframe[WLAN_HDR_A3_LEN]; + } else + return NOT_ROBUST_MGMT; + + return (Category_field != 4) && (Category_field != 7) && (Category_field != 11) + && (Category_field != 15) && (Category_field != 127); +} +#endif + +#ifdef CONFIG_IEEE80211W +#ifdef CONFIG_IEEE80211W_CLI +static int isMMICExist(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *pframe = get_pframe(pfrinfo); + + if (pfrinfo->pktlen + MMIC_CRC_LEN <= MMIC_ILLEGAL_LEN) + return FALSE; + + if (pframe[BIP_HEADER_LEN] == _MMIC_IE_) { + PMFDEBUG(" MMIC IE Exists!!\n"); + if (pframe[BIP_HEADER_LEN + MMIC_TAG_IE] == _MMIC_LEN_) { +#ifdef CONFIG_IEEE80211W_CLI_DEBUG + panic_printk("MMIC IE="); + int idx; + for(idx = 0; idx < _MMIC_LEN_; idx++) + panic_printk("%02x", pframe[BIP_HEADER_LEN + MMIC_TAG_IE + MMIC_TAG_LEN + idx]); + panic_printk("\n"); +#endif + } + return TRUE; + } + else { + PMFDEBUG(" No MMIC IE Exists!!\n"); + return FALSE; + } +} + +static int CheckBIPMIC(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *pframe = get_pframe(pfrinfo); + + if (MMIE_check(priv, pfrinfo)) { + PMFDEBUG("BIP: MIC Check PASS \n"); + return TRUE; + } else { + if (pframe[0] == WIFI_DEAUTH) { + PMFDEBUG("[%s] BIP: DEAUTH MIC_ERR\n", priv->dev->name); + } else if (pframe[0] == WIFI_DISASSOC) { + PMFDEBUG("[%s] BIP: DISASSOC MIC_ERR\n", priv->dev->name); + } else { + PMFDEBUG("[%s] BIP: MIC_ERR\n", priv->dev->name); + } + + return FALSE; + } +} +#endif + +int legal_mgnt_frame(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *pframe = get_pframe(pfrinfo); + unsigned char *da = GetAddr1Ptr(pframe); + int ret = isCorrectRobustFrame(priv, pfrinfo); + + if (ret == MGMT_FRAME_MIC_ERR) { // mgmt frame with mic error + return MGNT_ERR; + } else if (ret == IS_ROBUST_MGMT) { // robust mgmt frame + if(priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == NO_MGMT_FRAME_PROTECTION) { + if (GetPrivacy(pframe)) + return MGNT_PRIVACY_ERR; + } + else if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_OPTIONAL) { + struct stat_info *pstat = get_stainfo(priv, pfrinfo->sa); + if (pstat == NULL) + return MGNT_ERR; + + if (pstat->isPMF == 0) { // MFPC=0 + if (GetPrivacy(pframe)) + return MGNT_PRIVACY_ERR; + } else { // MFPC = 1 + if (!IS_MCAST(da)) { + if(GET_UNICAST_ENCRYP_KEY == NULL) { + if ((pframe[0] == WIFI_DEAUTH || pframe[0] == WIFI_DISASSOC)) { + if (GetPrivacy(pframe)) + return MGNT_PRIVACY_ERR; + } else + return MGNT_PRIVACY_ERR; + } else { + if (!GetPrivacy(pframe)) + return MGNT_PRIVACY_ERR; + else { + ClearPrivacy(pframe); + return MGNT_LEGAL; + } + } + } // Does AP receive multicast robust frame from client? +#ifdef CONFIG_IEEE80211W_CLI + else { // MMPDU has a group RA + if (!GET_IGROUP_ENCRYP_KEY) { + if ((pframe[0] != WIFI_DEAUTH && pframe[0] != WIFI_DISASSOC)) + return MGNT_ERR; + } else { + if (!isMMICExist(priv ,pfrinfo)) + return MGNT_BCAST_PRIVACY_ERR; + else { + if(!CheckBIPMIC(priv, pfrinfo)) + return MGNT_BCAST_PRIVACY_ERR; + } + } + } +#endif + } + } + else if (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == MGMT_FRAME_PROTECTION_REQUIRED) { + struct stat_info *pstat = get_stainfo(priv, pfrinfo->sa); + if (pstat == NULL) + return MGNT_ERR; + + if (pstat->isPMF == 0) { // MFPC=0 + return MGNT_ERR; + } else { // MFPC = 1 + if (!IS_MCAST(da)) { + if (GET_UNICAST_ENCRYP_KEY == NULL) { + return MGNT_PRIVACY_ERR; + } else { + if (!GetPrivacy(pframe)) + return MGNT_PRIVACY_ERR; + else { + ClearPrivacy(pframe); + return MGNT_LEGAL; + } + } + } + } + } + + } + + return MGNT_LEGAL; +} +#endif // CONFIG_IEEE80211W + +void mgt_handler(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + struct mlme_handler *ptable; + unsigned int index; + unsigned char *pframe = get_pframe(pfrinfo); + unsigned char *sa = pfrinfo->sa; + unsigned char *da = pfrinfo->da; + struct stat_info *pstat = NULL; + unsigned short frame_type; + +#if 0 // already flush cache in rtl8192cd_rx_isr() +#ifdef __MIPSEB__ + pframe = (unsigned char*)KSEG1ADDR(pframe); +#endif +#endif + + if (OPMODE & WIFI_AP_STATE) + ptable = mlme_ap_tbl; +#ifdef CLIENT_MODE + else if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) + ptable = mlme_station_tbl; +#endif + else + { + DEBUG_ERR("Currently we do not support opmode=%d\n", OPMODE); +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv) || (pfrinfo->is_br_mgnt == 0)) +#endif + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + return; + } + + frame_type = GetFrameSubType(pframe); + index = frame_type >> 4; + if (index > 13) + { + DEBUG_ERR("Currently we do not support reserved sub-fr-type=%d\n", index); +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv) || (pfrinfo->is_br_mgnt == 0)) +#endif + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + return; + } + ptable += index; + +#ifdef CONFIG_RTK_MESH + if( is_11s_mgt_frame(ptable->num, priv, pfrinfo)) + { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + pfrinfo->is_br_mgnt = 0; +#endif + pfrinfo->is_11s = 1; + ptable = mlme_mp_tbl; + ptable += index; +#ifdef MBSSID + if(!IS_VAP_INTERFACE(priv)) +#endif + // An 11s mgt frame will have Addr3 = 00..00, it might be dispatched to vxd in validate_mpdu + // Hence, we have to "correct" it here. + priv = GET_ROOT(priv); + } +#endif // CONFIG_RTK_MESH + + pstat = get_stainfo(priv, sa); + + if ((pstat != NULL) && (WIFI_PROBEREQ != frame_type)) + { +#ifdef DETECT_STA_EXISTANCE +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if (pstat->leave!= 0) + RTL8188E_MACID_NOLINK(priv, 0, REMAP_AID(pstat)); + } +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if (pstat->leave) + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); + } +#endif + pstat->leave = 0; +#endif + } + + if (!IS_MCAST(da)) + { + //pstat = get_stainfo(priv, sa); + + // only check last cache seq number for management frame, david ------------------------- + if (pstat != NULL) { + if (GetRetry(pframe)) { + if (GetTupleCache(pframe) == pstat->tpcache_mgt) { + priv->ext_stats.rx_decache++; +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv) || (pfrinfo->is_br_mgnt == 0)) +#endif + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); + SNMP_MIB_INC(dot11FrameDuplicateCount, 1); + return; + } + else + { + pstat->tpcache_mgt = GetTupleCache(pframe); + } + } + pstat->tpcache_mgt = GetTupleCache(pframe); + } + } + + // log rx statistics... +#ifdef WDS + if (pstat && (pstat->state & WIFI_WDS) && (ptable->num == WIFI_BEACON)) { + rx_sum_up(NULL, pstat, pfrinfo->pktlen, 0); + update_sta_rssi(priv, pstat, pfrinfo); + } + else +#endif +#ifdef CONFIG_RTK_MESH + if (pstat && pfrinfo->is_11s && (ptable->num == WIFI_BEACON)) { + // count statistics for mesh points -- chris + rx_sum_up(NULL, pstat, pfrinfo->pktlen, 0); + update_sta_rssi(priv, pstat, pfrinfo); + } + else +#endif + if (pstat != NULL) + { + // If AP mode and rx is a beacon, do not count in statistics. david +#ifdef DONT_COUNT_PROBE_PACKET + if (!((OPMODE & WIFI_AP_STATE) && ((ptable->num == WIFI_BEACON)||(ptable->num == WIFI_PROBEREQ)))) +#else + if (!((OPMODE & WIFI_AP_STATE) && (ptable->num == WIFI_BEACON))) +#endif + { + rx_sum_up(NULL, pstat, pfrinfo->pktlen, 0); + update_sta_rssi(priv, pstat, pfrinfo); + } + } + + // check power save state + if ((OPMODE & WIFI_AP_STATE) && (pstat != NULL)) { + if (IS_BSSID(priv, GetAddr1Ptr(pframe))) + { + #ifdef HW_DETEC_POWER_STATE + if (GET_CHIP_VER(priv) == VERSION_8814A) { + // 8814 power state control only by HW, not by SW. + // Only if HW detect macid not ready, SW patch this packet + if(pfrinfo->macid == HW_MACID_SEARCH_NOT_READY) + { + printk("%s %d HW_MACID_SEARCH_NOT_READY",__FUNCTION__,__LINE__); + if(priv->pshare->HWPwrStateUpdate[pstat->aid]==false) + { + printk("%s %d HW not update By SW Aid = %x \n",__FUNCTION__,__LINE__,pstat->aid); + pwr_state(priv, pfrinfo); + } + } + else if(pfrinfo->macid > HW_MACID_SEARCH_SUPPORT_NUM) + { + pwr_state(priv, pfrinfo); + } + } else + #endif // #ifdef HW_DETEC_POWER_STATE + { + pwr_state(priv, pfrinfo); + } + } + } + +#ifdef MBSSID + if ( + GET_ROOT(priv)->pmib->miscEntry.vap_enable && + IS_VAP_INTERFACE(priv)) { + if (IS_MCAST(da) || !memcmp(GET_MY_HWADDR, da, MACADDRLEN)) + { +#ifdef CONFIG_POWER_SAVE + if ((ptable->num != WIFI_BEACON) && (ptable->num != WIFI_PROBEREQ) + && (ptable->num != WIFI_PROBERSP)) { + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_MGT); + ptable->func(priv, pfrinfo); + ap_offload_activate(priv, OFFLOAD_PROHIBIT_MGT); + } else +#endif + ptable->func(priv, pfrinfo); + } + } + else +#endif + { +#ifdef CONFIG_IEEE80211W + int ret = legal_mgnt_frame(priv,pfrinfo); + if (ret == MGNT_LEGAL) +#endif + { +#ifdef CONFIG_POWER_SAVE + if ((ptable->num != WIFI_BEACON) && (ptable->num != WIFI_PROBEREQ) + && (ptable->num != WIFI_PROBERSP)) { + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_MGT); + ptable->func(priv, pfrinfo); + ap_offload_activate(priv, OFFLOAD_PROHIBIT_MGT); + } else +#endif + ptable->func(priv, pfrinfo); + } +#ifdef CONFIG_IEEE80211W_CLI + else if (ret == MGNT_PRIVACY_ERR) + { + if ((pframe[0] == WIFI_DEAUTH || pframe[0] == WIFI_DISASSOC)) + { + PMFDEBUG("issue_SA_Query_Req() when Receving Unprotected action frame !\n"); + if (pstat != NULL) + issue_SA_Query_Req(priv->dev,pstat->hwaddr); + } + }else + PMFDEBUG("MGNT_ERR! ret = %d \n", ret); +#endif + } + +#ifdef MBSSID + if (IS_VAP_INTERFACE(priv)) { + if (pfrinfo->is_br_mgnt) { + rx_sum_up(priv, NULL, pfrinfo->pktlen, GetRetry(pframe)); + return; + } + } + else if (IS_ROOT_INTERFACE(priv) && pfrinfo->is_br_mgnt && (OPMODE & WIFI_AP_STATE)) { + int i; +#ifdef CONFIG_IEEE80211W + int retVal; +#endif + for (i=0; ipvap_priv[i])) && ((IS_MCAST(da)) || + (!memcmp(priv->pvap_priv[i]->pmib->dot11StationConfigEntry.dot11Bssid, da, MACADDRLEN)))) + { +#ifdef CONFIG_IEEE80211W + retVal = legal_mgnt_frame(priv->pvap_priv[i],pfrinfo); + if (retVal == MGNT_LEGAL) +#endif + { + mgt_handler(priv->pvap_priv[i], pfrinfo); + } +#ifdef CONFIG_IEEE80211W_CLI + else if (retVal == MGNT_PRIVACY_ERR) + { + if ((pframe[0] == WIFI_DEAUTH || pframe[0] == WIFI_DISASSOC)) + issue_SA_Query_Req(priv->dev,pstat->hwaddr); + } else + PMFDEBUG("(%s)line=%d MGNT_ERR! retVal = %d \n", __FUNCTION__, __LINE__, retVal); +#endif + } + } + } +#endif + +#ifdef UNIVERSAL_REPEATER + if (pfrinfo->is_br_mgnt) { + pfrinfo->is_br_mgnt = 0; + +// fix hang-up issue when root-ap (A+B) + vxd-client ------------ + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) { + if ((OPMODE & WIFI_AP_STATE) || + ((OPMODE & WIFI_STATION_STATE) && + GET_VXD_PRIV(priv) && (GET_VXD_PRIV(priv)->drv_state & DRV_STATE_VXD_AP_STARTED))) { +//--------------------------------------------david+2006-07-17 + + mgt_handler(GET_VXD_PRIV(priv), pfrinfo); + return; + } + } + } +#endif + + rtl_kfree_skb(priv, pfrinfo->pskb, _SKB_RX_); +} + + +/*---------------------------------------------------------------------------- +// the purpose of this sub-routine +Any station has changed from sleep to active state, and has data buffer should +be dequeued here! +-----------------------------------------------------------------------------*/ +#ifdef CONFIG_PCI_HCI +void process_dzqueue(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat; + struct sk_buff *pskb; + struct list_head *phead = &priv->wakeup_list; + struct list_head *plist = phead->next; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + while(plist != phead) + { + pstat = list_entry(plist, struct stat_info, wakeup_list); + plist = plist->next; + + while(1) + { +// 2009.09.08 + SAVE_INT_AND_CLI(flags); +#if defined(WIFI_WMM) && defined(WMM_APSD) + if ( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (QOS_ENABLE) && (APSD_ENABLE) && pstat && (pstat->QosEnabled) && (pstat->apsd_pkt_buffering)) { + pskb = (struct sk_buff *)deque(priv, &(pstat->VO_dz_queue->head), &(pstat->VO_dz_queue->tail), + (unsigned long)(pstat->VO_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE); + if (pskb == NULL) { + pskb = (struct sk_buff *)deque(priv, &(pstat->VI_dz_queue->head), &(pstat->VI_dz_queue->tail), + (unsigned long)(pstat->VI_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE); + if (pskb == NULL) { + pskb = (struct sk_buff *)deque(priv, &(pstat->BE_dz_queue->head), &(pstat->BE_dz_queue->tail), + (unsigned long)(pstat->BE_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE); + if (pskb == NULL) { + pskb = (struct sk_buff *)deque(priv, &(pstat->BK_dz_queue->head), &(pstat->BK_dz_queue->tail), + (unsigned long)(pstat->BK_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE); + if (pskb == NULL) { + pstat->apsd_pkt_buffering = 0; + goto legacy_ps; + } + DEBUG_INFO("release BK pkt\n"); + } else { + DEBUG_INFO("release BE pkt\n"); + } + } else { + DEBUG_INFO("release VI pkt\n"); + } + } else { + DEBUG_INFO("release VO pkt\n"); + } + } else +legacy_ps: +#endif +#if defined(WIFI_WMM) + if (!isFFempty(pstat->MGT_dz_queue->head, pstat->MGT_dz_queue->tail)){ + struct tx_insn *tx_cfg; + tx_cfg = (struct tx_insn *)deque(priv, &(pstat->MGT_dz_queue->head), &(pstat->MGT_dz_queue->tail), + (unsigned long)(pstat->MGT_dz_queue->ptx_insn), NUM_DZ_MGT_QUEUE); + if ((rtl8192cd_firetx(priv, tx_cfg)) == SUCCESS){ + DEBUG_INFO("release MGT pkt\n"); + }else{ + DEBUG_ERR("release MGT pkt failed!\n"); + if (tx_cfg->phdr) + release_wlanhdr_to_poll(priv, tx_cfg->phdr); + if (tx_cfg->pframe) + release_mgtbuf_to_poll(priv, tx_cfg->pframe); + } + kfree(tx_cfg); + RESTORE_INT(flags); + continue; + } + else +#ifdef DZ_ADDBA_RSP + if (pstat->dz_addba.used) { + issue_ADDBArsp(priv, pstat->hwaddr, pstat->dz_addba.dialog_token, + pstat->dz_addba.TID, pstat->dz_addba.status_code, pstat->dz_addba.timeout); + pstat->dz_addba.used = 0; + //printk("issue DZ addba!!!!!!!\n"); + RESTORE_INT(flags); + continue; + } + else +#endif +#endif + pskb = __skb_dequeue(&pstat->dz_queue); + +// 2009.09.08 + RESTORE_INT(flags); + + if (pskb == NULL) + break; + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + + if (rtl8192cd_start_xmit_noM2U(pskb, pskb->dev)) + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + + SAVE_INT_AND_CLI(flags); + if (wakeup_list_del(priv, pstat)) { + DEBUG_INFO("Del fr wakeup_list %02X%02X%02X%02X%02X%02X\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + } + RESTORE_INT(flags); + } +} + + +void process_mcast_dzqueue(struct rtl8192cd_priv *priv) +{ + struct sk_buff *pskb; + + priv->release_mcast = 1; + while(1) { + pskb = (struct sk_buff *)deque(priv, &(priv->dz_queue.head), &(priv->dz_queue.tail), + (unsigned long)(priv->dz_queue.pSkb), NUM_TXPKT_QUEUE); + + if (pskb == NULL) + break; + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + +// stanley: I think using pskb->dev is correct IN THE FUTURE, when mesh0 also applies dzqueue +#ifdef CONFIG_RTK_MESH + if (rtl8192cd_start_xmit(pskb, pskb->dev)) +#else + if (rtl8192cd_start_xmit(pskb, priv->dev)) +#endif + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + priv->release_mcast = 0; +} +#endif // CONFIG_PCI_HCI + + +#if 0 + int check_basic_rate(struct rtl8192cd_priv *priv, unsigned char *pRate, int pLen) +{ + int i, match, idx; + UINT8 rate; + + // david, check if is there is any basic rate existed -- + int any_one_basic_rate_found = 0; + + for (i=0; ipshare->BeamformingInfo); + PRT_BEAMFORMING_ENTRY pEntry; + if(pBeamformingInfo->BeamformeeEntry[0].bUsed && pBeamformingInfo->BeamformeeEntry[1].bUsed) { + candidate1 = psta = findNextSTA(priv, &idx); + while(psta) { + if(psta && psta->expire_to) { + if( psta->bf_score > candidate1->bf_score) + candidate1 = psta; + } + psta = findNextSTA(priv, &idx); + }; + if(candidate1 ==NULL) + return; + idx = 0; + candidate2 = psta = findNextSTA(priv, &idx); + + if(candidate2 == candidate1) // to avoid 1st STA with highest score case + candidate2 = psta = findNextSTA(priv, &idx); + + while(psta) { + if(psta && psta->expire_to) { + if( (psta->bf_score > candidate2->bf_score) && (psta != candidate1)) + candidate2 = psta; + } + psta = findNextSTA(priv, &idx); + }; + if( candidate2 == candidate1) + candidate2 = NULL; + if(candidate1) + ++candidateCtr; + if(candidate2) + ++candidateCtr; + { + for(idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) { + if( pBeamformingInfo->BeamformeeEntry[idx].bUsed) { + isCandidate = 0; + if(candidate1 && (pBeamformingInfo->BeamformeeEntry[idx].MacId == candidate1->aid)) + ++bfeCtr; + else if(candidate2 && (pBeamformingInfo->BeamformeeEntry[idx].MacId == candidate2->aid)) + ++bfeCtr; + } + } + candidateCtr -=bfeCtr; + for(idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) + { + if( pBeamformingInfo->BeamformeeEntry[idx].bUsed) { + isCandidate = 0; + if(candidate1 && (pBeamformingInfo->BeamformeeEntry[idx].MacId == candidate1->aid)) + isCandidate = 1; + if(candidate2 && (pBeamformingInfo->BeamformeeEntry[idx].MacId == candidate2->aid)) + isCandidate = 2; + if(isCandidate==0 && candidateCtr) { + + pBeamformingInfo->CurDelBFerBFeeEntrySel = BFeeEntry; + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s,\n", __FUNCTION__)); + + if(Beamforming_DeInitEntry(priv, pBeamformingInfo->BeamformeeEntry[idx].MacAddr)) + Beamforming_Notify(priv); + + --candidateCtr; + } + } + } + + if(candidate1) { + pEntry = Beamforming_GetEntryByMacId(priv, candidate1->aid, (unsigned char*)&idx); + if(pEntry == NULL) { + Beamforming_Enter(priv, candidate1); + } + } + if(candidate2) { + pEntry = Beamforming_GetEntryByMacId(priv, candidate2->aid, (unsigned char*)&idx); + if(pEntry == NULL) { + Beamforming_Enter(priv, candidate2); + } + } + } + } + +} +#endif + +// which: 0: set basic rates as mine, 1: set basic rates as peer's + void get_matched_rate(struct rtl8192cd_priv *priv, unsigned char *pRate, int *pLen, int which) +{ + int i, j, num=0; + UINT8 rate; + UINT8 found_rate[32]; + + for (i=0; ibssrateset, 0, sizeof(pstat->bssrateset)); + pstat->bssratelen=len; + memcpy(pstat->bssrateset, buf, len); +} + + +int isErpSta(struct stat_info *pstat) +{ + int i, len=pstat->bssratelen; + UINT8 *buf=pstat->bssrateset; + + for (i=0; ipmib->dot11StationConfigEntry.autoRate) + { + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + if (pstat->sta_in_firmware == 1 && (pstat->expire_to > 0)) + { + + if(pstat->current_tx_rate < priv->pshare->phw->LowestInitRate) + priv->pshare->phw->LowestInitRate = pstat->current_tx_rate; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + } + else if (priv->pmib->dot11StationConfigEntry.fixedTxRate) + priv->pshare->phw->LowestInitRate = priv->pmib->dot11StationConfigEntry.fixedTxRate; + else + priv->pshare->phw->LowestInitRate = _24M_RATE_; + +} + +/*---------------------------------------------------------------------------- +index: the information element id index, limit is the limit for search +-----------------------------------------------------------------------------*/ +/** + * @brief Get Information Element + * + * p (Find ID in limit) \n + * +--- -+------------+-----+--- \n + * | ... | element ID | len |... \n + * +--- -+------------+-----+--- \n + * + * @param pbuf frame data for search + * @param index the information element id = index (search target) + * @param limit limit for search + * + * @retval p pointer to element ID + * @retval len p(IE) len + */ + unsigned char *get_ie(unsigned char *pbuf, int index, int *len, int limit) +{ + unsigned int tmp,i; + unsigned char *p; + + if (limit < 1) + return NULL; + + p = pbuf; + i = 0; + *len = 0; + while(1) + { + if (*p == index) + { + *len = *(p + 1); + return (p); + } + else + { + tmp = *(p + 1); + p += (tmp + 2); + i += (tmp + 2); + } + if (i >= limit) + break; + } + return NULL; +} + + +#ifdef RTL_WPA2 +/*---------------------------------------------------------------------------- +index: the information element id index, limit is the limit for search +-----------------------------------------------------------------------------*/ +static unsigned char *get_rsn_ie(struct rtl8192cd_priv *priv, unsigned char *pbuf, int *len, int limit) +{ + unsigned char *p = NULL; + + if (priv->pmib->dot11RsnIE.rsnielen == 0) + return NULL; + + if ((priv->pmib->dot11RsnIE.rsnie[0] == _RSN_IE_2_) || + ((priv->pmib->dot11RsnIE.rsnielen > priv->pmib->dot11RsnIE.rsnie[1]) && + (priv->pmib->dot11RsnIE.rsnie[priv->pmib->dot11RsnIE.rsnie[1]+2] == _RSN_IE_2_))) { + p = get_ie(pbuf, _RSN_IE_2_, len, limit); + if (p != NULL) + return p; + else + return get_ie(pbuf, _RSN_IE_1_, len, limit); + } + else { + p = get_ie(pbuf, _RSN_IE_1_, len, limit); + if (p != NULL) + return p; + else + return get_ie(pbuf, _RSN_IE_2_, len, limit); + } +} +#endif + + +/** + * @brief Set Information Element + * + * Difference between set_fixed_ie, reserve 2 Byte, for Element ID & length \n + * \n + * +-------+ +------------+--------+----------------+ \n + * | pbuf. | <--- | element ID | length | source | \n + * +-------+ +------------+--------+----------------+ \n + * + * @param pbuf buffer(frame) for set + * @param index IE element ID + * @param len IE length content & set length + * @param source IE data for buffer set + * @param frlen total frame length + * + * @retval pbuf+len+2 pointer of buffer tail.(+2 because element ID and length total 2 bytes) + */ + unsigned char *set_ie(unsigned char *pbuf, int index, unsigned int len, unsigned char *source, + unsigned int *frlen) +{ + *pbuf = index; + *(pbuf + 1) = len; + if (len > 0) + memcpy((void *)(pbuf + 2), (void *)source, len); + *frlen = *frlen + (len + 2); + return (pbuf + len + 2); +} + + +static __inline__ int set_virtual_bitmap(unsigned char *pbuf, unsigned int i) +{ + unsigned int r,s,t; + + r = (i >> 3) << 3; + t = i - r; + + s = BIT(t); + + *(pbuf + (i >> 3)) |= s; + + return (i >> 3); +} + + +static __inline__ unsigned char *update_tim(struct rtl8192cd_priv *priv, + unsigned char *bcn_buf, unsigned int *frlen) +{ +#ifdef CONFIG_PCI_HCI + unsigned int pre_head; +#endif + unsigned int i, set_pvb; + unsigned char val8; + unsigned long flags; + struct list_head *plist, *phead; + struct stat_info *pstat; + unsigned char bitmap[(NUM_STAT/8)+1]; + unsigned char *pbuf= bcn_buf; + unsigned char N1, N2, bitmap_offset; + +#ifdef CONFIG_PCI_HCI +#if defined(CONFIG_WLAN_HAL) || defined(CONFIG_RTL_8812_SUPPORT)|| defined(CONFIG_RTL_88E_SUPPORT) + unsigned char Q_info[8]; + unsigned char b_calhwqnum = 0; +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) + b_calhwqnum = 8; +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + b_calhwqnum = 8; +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8188E){ + b_calhwqnum = 4; + } +#endif + + if(b_calhwqnum == 8) { + for(i=0; i<4; i++) { + if(RTL_R8(0x400+i*4+1) & 0x7f) // 14:8 7b + Q_info[i] = (RTL_R8(0x400+i*4+3)>>1) & 0x7f; //31:25 7b + else + Q_info[i] = 0; + if(RTL_R8(0x468+i*4+1) & 0x7f) // 14:8 7b + Q_info[i+4] = (RTL_R8(0x468+i*4+3)>>1) & 0x7f; //31:25 7b + else + Q_info[i+4] = 0; + } + } + else if(b_calhwqnum == 4) { + for(i=0; i<4; i++) { + if(RTL_R8(0x400+i*4+1)){ // 15:8 7b + Q_info[i] = (RTL_R8(0x400+i*4+3)>>2) & 0x3f; //31:26 7b + } + else + Q_info[i] = 0; + } + + } +#endif +#endif // CONFIG_PCI_HCI + + memset(bitmap, 0, sizeof(bitmap)); + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable && IS_VAP_INTERFACE(priv)) + priv->dtimcount = GET_ROOT(priv)->dtimcount; + else +#endif + { + if (priv->dtimcount == 0) + priv->dtimcount = (priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod - 1); + else + priv->dtimcount--; + } + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL + if (!IS_HAL_CHIP(priv)) +#endif + { +#ifdef SMP_SYNC + unsigned long flags; +#endif + //if (priv->pkt_in_dtimQ && (priv->dtimcount == 0)) + SMP_LOCK_XMIT(flags); + pre_head = get_txhead(priv->pshare->phw, MCAST_QNUM); + txdesc_rollback(&pre_head); + SMP_UNLOCK_XMIT(flags); + + if (priv->dtimcount == (priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod - 1) + &&(*((unsigned char *)priv->beaconbuf + priv->timoffset + 4) & 0x01)) { + RTL_W16(RD_CTRL, RTL_R16(RD_CTRL) & (~ HIQ_NO_LMT_EN)); + } + if(priv->dtimcount == (priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod - 1) + && !(get_desc((get_txdesc(priv->pshare->phw, MCAST_QNUM) + pre_head)->Dword0) & TX_OWN)) + priv->pkt_in_hiQ = 0; + } + + if ((priv->dtimcount == 0) && + (priv->pkt_in_dtimQ || + // (get_desc((get_txdesc(priv->pshare->phw, MCAST_QNUM) + pre_head)->Dword0) & TX_OWN))) + priv->pkt_in_hiQ)) + val8 = 0x01; + else + val8 = 0x00; +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if ((priv->dtimcount == 0) + && (((MCAST_QNUM == priv->tx_mc_queue.q_num) && (tx_servq_len(&priv->tx_mc_queue) > 0)) +#ifdef CONFIG_USB_HCI + || (priv->pshare->tx_urb_waiting_queue[MCAST_QNUM].qlen > 0) +#endif +#ifdef CONFIG_SDIO_HCI + || (priv->pshare->tx_xmitbuf_waiting_queue[MCAST_QNUM].qlen > 0) +#endif +#if defined(CONFIG_RTL_88E_SUPPORT) + || (RTL_R8(HIQ_INFO+1)) +#elif defined(CONFIG_WLAN_HAL_8192EE) + || (RTL_R8(HIQ_INFO+1) & 0x7F) +#else + || (RTL_R8(HIQ_INFO+2)) +#endif + )) + val8 = 0x01; + else + val8 = 0x00; +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#if defined(CONFIG_WLAN_HAL) && defined(CONFIG_PCI_HCI) + if (IS_HAL_CHIP(priv)) + { + u1Byte macID_list[NUM_AC_QUEUE]; + u1Byte macID_index; + memset(macID_list, 0, NUM_AC_QUEUE); + if(RT_STATUS_SUCCESS == GET_HAL_INTERFACE(priv)->GetMACIDQueueInTXPKTBUFHandler(priv,macID_list)) + { + for(macID_index=0;macID_indexdtimcount; + *(pbuf + 3) = priv->pmib->dot11StationConfigEntry.dot11DTIMPeriod; + + phead = &priv->sleep_list; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK_SLEEP_LIST(flags); + + plist = phead->next; + while(plist != phead) + { + pstat = list_entry(plist, struct stat_info, sleep_list); + plist = plist->next; + set_pvb = 0; + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + for (i = BK_QUEUE; i <= VO_QUEUE; ++i) { + if (tx_servq_len(&pstat->tx_queue[i]) > 0) { + set_pvb++; + break; + } + } + +#elif defined(CONFIG_PCI_HCI) +#if defined(WIFI_WMM) && defined(WMM_APSD) + if ((QOS_ENABLE) && (APSD_ENABLE) && (pstat) && ((pstat->apsd_bitmap & 0x0f) == 0x0f) && + ((!isFFempty(pstat->VO_dz_queue->head, pstat->VO_dz_queue->tail)) || + (!isFFempty(pstat->VI_dz_queue->head, pstat->VI_dz_queue->tail)) || + (!isFFempty(pstat->BE_dz_queue->head, pstat->BE_dz_queue->tail)) || + (!isFFempty(pstat->BK_dz_queue->head, pstat->BK_dz_queue->tail)))) { + set_pvb++; + } + else +#endif + + if (skb_queue_len(&pstat->dz_queue)) + set_pvb++; + +#if defined(CONFIG_WLAN_HAL) || defined(CONFIG_RTL_8812_SUPPORT)|| defined(CONFIG_RTL_88E_SUPPORT) + if(set_pvb == 0 && b_calhwqnum) { + for(i=0; iaid; + i = set_virtual_bitmap(bitmap, i); + } + } + + SMP_UNLOCK_SLEEP_LIST(flags); + RESTORE_INT(flags); + + N1 = 0; + for(i=0; i<(NUM_STAT/8)+1; i++) { + if(bitmap[i] != 0) { + N1 = i; + break; + } + } + N2 = N1; + for(i=(NUM_STAT/8); i>N1; i--) { + if(bitmap[i] != 0) { + N2 = i; + break; + } + } + + // N1 should be an even number + N1 = (N1 & 0x01)? (N1-1) : N1; + bitmap_offset = N1 >> 1; // == N1/2 + *(pbuf + 1) = N2 - N1 + 4; + *(frlen) = *frlen + *(pbuf + 1) + 2; + + *(pbuf + 4) = val8 | (bitmap_offset << 1); + memcpy((void *)(pbuf + 5), &bitmap[N1], (N2-N1+1)); + + return (bcn_buf + *(pbuf + 1) + 2); +} + +/** + * @brief set fixed information element + * + * set_fixed is haven't Element ID & length, Total length is frlen. \n + * len \n + * +-----------+-----------+ \n + * | pbuf | source | \n + * +-----------+-----------+ \n + * + * @param pbuf buffer(frame) for set + * @param len IE set length + * @param source IE data for buffer set + * @param frlen total frame length (Note: frlen have side effect??) + * + * @retval pbuf+len pointer of buffer tail. \n + */ + unsigned char *set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source, + unsigned int *frlen) +{ + memcpy((void *)pbuf, (void *)source, len); + *frlen = *frlen + len; + return (pbuf + len); +} + + +void construct_ht_ie(struct rtl8192cd_priv *priv, int use_40m, int offset) +{ + struct ht_cap_elmt *ht_cap; + struct ht_info_elmt *ht_ie; + int ch_offset; + + if (priv->ht_cap_len == 0) { + unsigned int sup_mcs = get_supported_mcs(priv); + // construct HT Capabilities element + priv->ht_cap_len = sizeof(struct ht_cap_elmt); + ht_cap = &priv->ht_cap_buf; + memset(ht_cap, 0, sizeof(struct ht_cap_elmt)); + if (use_40m ==1 || use_40m ==2){ + ht_cap->ht_cap_info |= cpu_to_le16(use_40m ? _HTCAP_SUPPORT_CH_WDTH_ : 0); + } + ht_cap->ht_cap_info |= cpu_to_le16(_HTCAP_SMPWR_DISABLE_); + ht_cap->ht_cap_info |= cpu_to_le16(priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M? _HTCAP_SHORTGI_20M_ : 0); + + if (use_40m == 1 || use_40m ==2 + || (priv->pmib->dot11nConfigEntry.dot11nUse40M==1) + || (priv->pmib->dot11nConfigEntry.dot11nUse40M==2)) { + ht_cap->ht_cap_info |= cpu_to_le16(priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M? _HTCAP_SHORTGI_40M_ : 0); + } + if ((get_rf_mimo_mode(priv) == MIMO_1T1R) +#ifdef CONFIG_RTL_92C_SUPPORT + || (GET_CHIP_VER(priv) == VERSION_8192C) +#endif + ) + ht_cap->ht_cap_info |= cpu_to_le16(priv->pmib->dot11nConfigEntry.dot11nSTBC? _HTCAP_RX_STBC_1S_ : 0); + else + ht_cap->ht_cap_info |= cpu_to_le16(priv->pmib->dot11nConfigEntry.dot11nSTBC? (_HTCAP_TX_STBC_ | _HTCAP_RX_STBC_1S_) : 0); + + if (can_enable_rx_ldpc(priv)) + ht_cap->ht_cap_info |= cpu_to_le16((priv->pmib->dot11nConfigEntry.dot11nLDPC&1)? (_HTCAP_SUPPORT_RX_LDPC_) : 0); + + ht_cap->ht_cap_info |= cpu_to_le16(priv->pmib->dot11nConfigEntry.dot11nAMSDURecvMax? _HTCAP_AMSDU_LEN_8K_ : 0); + ht_cap->ht_cap_info |= cpu_to_le16(_HTCAP_CCK_IN_40M_); +// 64k +#if defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv)==VERSION_8812E) { + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) + ht_cap->ampdu_para = ((_HTCAP_AMPDU_SPC_16_US_ << _HTCAP_AMPDU_SPC_SHIFT_) | _HTCAP_AMPDU_FAC_64K_); + else + ht_cap->ampdu_para = ((_HTCAP_AMPDU_SPC_8_US_ << _HTCAP_AMPDU_SPC_SHIFT_) | _HTCAP_AMPDU_FAC_64K_); + } else +#endif +#if defined(CONFIG_WLAN_HAL) + if (GET_CHIP_VER(priv)==VERSION_8192E) { + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) + ht_cap->ampdu_para = ((_HTCAP_AMPDU_SPC_16_US_ << _HTCAP_AMPDU_SPC_SHIFT_) | _HTCAP_AMPDU_FAC_64K_); + else + ht_cap->ampdu_para = ((_HTCAP_AMPDU_SPC_8_US_ << _HTCAP_AMPDU_SPC_SHIFT_) | _HTCAP_AMPDU_FAC_64K_); + } else +#endif + { + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) + ht_cap->ampdu_para = ((_HTCAP_AMPDU_SPC_16_US_ << _HTCAP_AMPDU_SPC_SHIFT_) | _HTCAP_AMPDU_FAC_32K_); + else +#ifdef RTK_AC_SUPPORT //for 11ac logo + if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8814A)) + ht_cap->ampdu_para = ((_HTCAP_AMPDU_SPC_NORES_ << _HTCAP_AMPDU_SPC_SHIFT_) | _HTCAP_AMPDU_FAC_64K_); + else +#endif + ht_cap->ampdu_para = ((_HTCAP_AMPDU_SPC_8_US_ << _HTCAP_AMPDU_SPC_SHIFT_) | _HTCAP_AMPDU_FAC_32K_); + + } + ht_cap->support_mcs[0] = (sup_mcs & 0xff); + ht_cap->support_mcs[1] = (sup_mcs & 0xff00) >> 8; + ht_cap->support_mcs[2] = (sup_mcs & 0xff0000) >> 16; + ht_cap->support_mcs[3] = (sup_mcs & 0xff000000) >> 24; + ht_cap->ht_ext_cap = 0; +#ifdef BEAMFORMING_SUPPORT + if (((GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv) == VERSION_8192E || GET_CHIP_VER(priv) == VERSION_8814A)) && + (priv->pmib->dot11RFEntry.txbf == 1)){ + if ((priv->pmib->dot11RFEntry.txbfer == 1) && (priv->pmib->dot11RFEntry.txbfee == 0)) + { + if(GET_CHIP_VER(priv) == VERSION_8814A) + ht_cap->txbf_cap = cpu_to_le32(0x18000410); + else + ht_cap->txbf_cap = cpu_to_le32(0x08000410); + } + else if ((priv->pmib->dot11RFEntry.txbfer == 0) && (priv->pmib->dot11RFEntry.txbfee == 1)) + { + if(GET_CHIP_VER(priv) == VERSION_8814A) + ht_cap->txbf_cap = cpu_to_le32(0x01810008); + else + ht_cap->txbf_cap = cpu_to_le32(0x00810008); + } + else + { + if(GET_CHIP_VER(priv) == VERSION_8814A) + ht_cap->txbf_cap = cpu_to_le32(0x19810418); + else + ht_cap->txbf_cap = cpu_to_le32(0x08810418); + } + } + else +#endif + ht_cap->txbf_cap = 0; + ht_cap->asel_cap = 0; + +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_AP_STATE) || (OPMODE & WIFI_ADHOC_STATE)) +#endif + { + // construct HT Information element + priv->ht_ie_len = sizeof(struct ht_info_elmt); + ht_ie = &priv->ht_ie_buf; + memset(ht_ie, 0, sizeof(struct ht_info_elmt)); + ht_ie->primary_ch = priv->pmib->dot11RFEntry.dot11channel; + if ((use_40m == 1) || (use_40m == 2)) { + if (offset == HT_2NDCH_OFFSET_BELOW) + ch_offset = _HTIE_2NDCH_OFFSET_BL_ | _HTIE_STA_CH_WDTH_; + else + ch_offset = _HTIE_2NDCH_OFFSET_AB_ | _HTIE_STA_CH_WDTH_; + } else { + ch_offset = _HTIE_2NDCH_OFFSET_NO_; + } + + ht_ie->info0 |= ch_offset; + ht_ie->info1 = 0; + ht_ie->info2 = 0; + ht_ie->basic_mcs[0] = (priv->pmib->dot11nConfigEntry.dot11nBasicMCS & 0xff); + ht_ie->basic_mcs[1] = (priv->pmib->dot11nConfigEntry.dot11nBasicMCS & 0xff00) >> 8; + ht_ie->basic_mcs[2] = (priv->pmib->dot11nConfigEntry.dot11nBasicMCS & 0xff0000) >> 16; + ht_ie->basic_mcs[3] = (priv->pmib->dot11nConfigEntry.dot11nBasicMCS & 0xff000000) >> 24; + } + } + else +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_AP_STATE) || (OPMODE & WIFI_ADHOC_STATE) ) +#endif + { +#ifdef WIFI_11N_2040_COEXIST + if (priv->pmib->dot11nConfigEntry.dot11nCoexist && (OPMODE & WIFI_AP_STATE)) { + ht_ie = &priv->ht_ie_buf; + ht_ie->info0 &= ~(_HTIE_2NDCH_OFFSET_BL_ | _HTIE_STA_CH_WDTH_); + if (use_40m && !(priv->bg_ap_timeout || orForce20_Switch20Map(priv)) ) { + if (offset == HT_2NDCH_OFFSET_BELOW) + ch_offset = _HTIE_2NDCH_OFFSET_BL_ | _HTIE_STA_CH_WDTH_; + else + ch_offset = _HTIE_2NDCH_OFFSET_AB_ | _HTIE_STA_CH_WDTH_; + } else { + ch_offset = _HTIE_2NDCH_OFFSET_NO_; + } + ht_ie->info0 |= ch_offset; + } +#endif + if (!priv->pmib->dot11StationConfigEntry.protectionDisabled) { + if (priv->ht_legacy_obss_to || priv->ht_legacy_sta_num) + priv->ht_protection = 1; + else + priv->ht_protection = 0;; + } + + if (priv->ht_legacy_sta_num) { + priv->ht_ie_buf.info1 |= cpu_to_le16(_HTIE_OP_MODE3_); + } else if (priv->ht_legacy_obss_to || priv->ht_nomember_legacy_sta_to) { + priv->ht_ie_buf.info1 &= cpu_to_le16(~_HTIE_OP_MODE3_); + priv->ht_ie_buf.info1 |= cpu_to_le16(_HTIE_OP_MODE1_); + } else { + priv->ht_ie_buf.info1 &= cpu_to_le16(~_HTIE_OP_MODE3_); + } + + if (priv->ht_protection) + priv->ht_ie_buf.info1 |= cpu_to_le16(_HTIE_OBSS_NHT_STA_); + else + priv->ht_ie_buf.info1 &= cpu_to_le16(~_HTIE_OBSS_NHT_STA_); + } +#if defined(UNIVERSAL_REPEATER) + if( IS_DRV_OPEN(GET_VXD_PRIV(GET_ROOT(priv)))) { + ht_cap = &priv->ht_cap_buf; + ht_cap->ht_cap_info |= cpu_to_le16( _HTCAP_SUPPORT_CH_WDTH_ | _HTCAP_SHORTGI_40M_); + } +#endif +} + + +unsigned char *construct_ht_ie_old_form(struct rtl8192cd_priv *priv, unsigned char *pbuf, unsigned int *frlen) +{ + unsigned char old_ht_ie_id[] = {0x00, 0x90, 0x4c}; + + *pbuf = _RSN_IE_1_; + *(pbuf + 1) = 3 + 1 + priv->ht_cap_len; + memcpy((pbuf + 2), old_ht_ie_id, 3); + *(pbuf + 5) = 0x33; + memcpy((pbuf + 6), (unsigned char *)&priv->ht_cap_buf, priv->ht_cap_len); + *frlen += (*(pbuf + 1) + 2); + pbuf +=(*(pbuf + 1) + 2); + + *pbuf = _RSN_IE_1_; + *(pbuf + 1) = 3 + 1 + priv->ht_ie_len; + memcpy((pbuf + 2), old_ht_ie_id, 3); + *(pbuf + 5) = 0x34; + memcpy((pbuf + 6), (unsigned char *)&priv->ht_ie_buf, priv->ht_ie_len); + *frlen += (*(pbuf + 1) + 2); + pbuf +=(*(pbuf + 1) + 2); + + return pbuf; +} + + +#ifdef WIFI_11N_2040_COEXIST +void construct_obss_scan_para_ie(struct rtl8192cd_priv *priv) +{ + struct obss_scan_para_elmt *obss_scan_para; + + if (priv->obss_scan_para_len == 0) { + priv->obss_scan_para_len = sizeof(struct obss_scan_para_elmt); + obss_scan_para = &priv->obss_scan_para_buf; + memset(obss_scan_para, 0, sizeof(struct obss_scan_para_elmt)); + + // except word2, all are default values and meaningless for ap at present + obss_scan_para->word0 = cpu_to_le16(0x14); + obss_scan_para->word1 = cpu_to_le16(0x0a); + obss_scan_para->word2 = cpu_to_le16(180); // set as 180 second for 11n test plan + obss_scan_para->word3 = cpu_to_le16(0xc8); + obss_scan_para->word4 = cpu_to_le16(0x14); + obss_scan_para->word5 = cpu_to_le16(5); + obss_scan_para->word6 = cpu_to_le16(0x19); + } +} + +int bg_ap_rssi_chk(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, int channel) +{ + int i; + int ch_begin = -1; + int ch_end = -1; + int chk_l = 0; + int chk_h = 0; + + for (i = 0; i < priv->available_chnl_num; i++) + { + if (priv->available_chnl[i] <= 14) + { + if (ch_begin == -1) + ch_begin = priv->available_chnl[i]; + + ch_end = priv->available_chnl[i]; + } + else + break; + } + + + if (priv->pmib->dot11RFEntry.dot11channel && (priv->pmib->dot11RFEntry.dot11channel <= 14)) + { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_ABOVE) + { + chk_l = priv->pmib->dot11RFEntry.dot11channel + 2 - 5; + chk_h = priv->pmib->dot11RFEntry.dot11channel + 2 + 5; + } + + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + { + chk_l = priv->pmib->dot11RFEntry.dot11channel - 2 - 5; + chk_h = priv->pmib->dot11RFEntry.dot11channel - 2 + 5; + } + + if (chk_l < ch_begin) + chk_l = ch_begin; + if (chk_h > ch_end) + chk_h = ch_end; + + if ((channel >= chk_l) && (channel <= chk_h)) + { + if (pfrinfo->rssi >= priv->pmib->dot11nConfigEntry.dot11nBGAPRssiChkTh) + return 1; + } + } + + return 0; +} +#endif + +#if 1 +//#ifdef PCIE_POWER_SAVING +void fill_bcn_desc(struct rtl8192cd_priv *priv, struct tx_desc *pdesc, void *dat_content, unsigned short txLength, char forceUpdate) +{ +#if defined(CONFIG_RTL_8812_SUPPORT) +if (GET_CHIP_VER(priv)==VERSION_8812E) +{ + memset(pdesc, 0, 40); + pdesc->Dword0 |= set_desc(TX_FirstSeg | TX_LastSeg); + pdesc->Dword0 |= set_desc(TX_BMC| (40<Dword10 = set_desc(get_physical_addr(priv, dat_content, txLength, PCI_DMA_TODEVICE)); + pdesc->Dword0 |= set_desc((unsigned short)(txLength) << TX_PktSizeSHIFT); + pdesc->Dword1 |= set_desc(0x10 << TX_QSelSHIFT); + pdesc->Dword9 |= set_desc((GetSequence(dat_content) & TXdesc_92E_TX_SeqMask) << TXdesc_92E_TX_SeqSHIFT); + pdesc->Dword3 = set_desc(TXdesc_92E_DisDataFB|TXdesc_92E_UseRate); + + if (priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_80) { + pdesc->Dword5 |= set_desc((priv->pshare->txsc_20 << TXdesc_92E_DataScSHIFT)); + } else if (priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_20_40) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + pdesc->Dword5 |= set_desc(2 << TXdesc_92E_DataScSHIFT); + else + pdesc->Dword5 |= set_desc(1 << TXdesc_92E_DataScSHIFT); + } + + priv->pshare->is_40m_bw_bak = priv->pshare->is_40m_bw; + + priv->tx_beacon_len = txLength; + + pdesc->Dword7 |= set_desc((unsigned short)(txLength) & TX_TxBufSizeMask); + pdesc->Dword9 |= set_desc((GetSequence(dat_content) & TXdesc_92E_TX_SeqMask) << TXdesc_92E_TX_SeqSHIFT); + //pdesc->Dword9 |= set_desc((priv->timoffset & TXdesc_92E_TX_GroupIEMask) | TXdesc_92E_TX_GroupIEEnable); + + pdesc->Dword4 |= set_desc(0x1f << DATA_RATE_FB_LIMIT); + pdesc->Dword4 |= set_desc(0xf << RTS_RATE_FB_LIMIT); + +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT && (P2PMODE==P2P_TMP_GO || P2PMODE==P2P_PRE_GO)){ + pdesc->Dword4 |= set_desc((4 & TXdesc_92E_RtsRateMask) << TXdesc_92E_RtsRateSHIFT); + pdesc->Dword4 |= set_desc((4 & TXdesc_92E_DataRateMask) << TXdesc_92E_DataRateSHIFT); // use 6M to beacon rate + }else +#endif + if ((priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)||(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_80)) //AC2G_256QAM + { + pdesc->Dword4 |= set_desc((4 & TXdesc_92E_RtsRateMask) << TXdesc_92E_RtsRateSHIFT); + pdesc->Dword4 |= set_desc((4 & TXdesc_92E_DataRateMask) << TXdesc_92E_DataRateSHIFT); + } + +/* + * Intel IOT, dynamic enhance beacon tx AGC +*/ + pdesc->Dword5 &= set_desc(~((TXdesc_8812_TxPwrOffetMask) << TXdesc_8812_TxPwrOffetSHIFT)); + if (priv->bcnTxAGC ==1) + pdesc->Dword5 |= set_desc((4 & TXdesc_8812_TxPwrOffetMask) << TXdesc_8812_TxPwrOffetSHIFT); + else if (priv->bcnTxAGC ==2) + pdesc->Dword5 |= set_desc((5 & TXdesc_8812_TxPwrOffetMask) << TXdesc_8812_TxPwrOffetSHIFT); + + return; //_eric_8812 ?? +} +#endif //defined(CONFIG_RTL_8812_SUPPORT) +/* + * Intel IOT, dynamic enhance beacon tx AGC + */ + if (priv->bcnTxAGC_bak != priv->bcnTxAGC || forceUpdate) + { + memset((void *)&pdesc->Dword6, 0, 4); + +#ifdef HIGH_POWER_EXT_PA + if (!priv->pshare->rf_ft_var.use_ext_pa) +#endif + if (priv->bcnTxAGC) + { + pdesc->Dword6 |= set_desc((((priv->bcnTxAGC*6) & 0xfffffffe) & TX_TxAgcAMask) << TX_TxAgcASHIFT); + pdesc->Dword6 |= set_desc((((priv->bcnTxAGC*6) & 0xfffffffe) & TX_TxAgcBMask) << TX_TxAgcBSHIFT); + } + priv->bcnTxAGC_bak = priv->bcnTxAGC; + } + + if (priv->pshare->is_40m_bw != priv->pshare->is_40m_bw_bak || forceUpdate) { + memset((void *)&pdesc->Dword4, 0, 4); + + pdesc->Dword4 = set_desc(TX_DisDataFB | TX_UseRate); + + if (priv->pshare->is_40m_bw) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + pdesc->Dword4 |= set_desc(2 << TX_DataScSHIFT); + else + pdesc->Dword4 |= set_desc(1 << TX_DataScSHIFT); + } + priv->pshare->is_40m_bw_bak = priv->pshare->is_40m_bw; + +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + pdesc->Dword4 |= set_desc((4 & TX_RtsRateMask) << TX_RtsRateSHIFT); +#endif + } + + if (txLength != priv->tx_beacon_len || forceUpdate) + { + memset(pdesc, 0, 24); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + pdesc->Dword0 |= set_desc(TX_OWN|TX_BMC|TX_FirstSeg | TX_LastSeg | ((32)<Dword7, 0, 8); + + pdesc->Dword0 |= set_desc(TX_BMC|TX_FirstSeg | TX_LastSeg | ((32)<Dword0 |= set_desc((unsigned short)(txLength) << TX_PktSizeSHIFT); + pdesc->Dword1 |= set_desc(0x10 << TX_QSelSHIFT); + + if (priv->pmib->dot11RFEntry.bcn2path){ + RTL_W32(0x80c,RTL_R32(0x80c)|BIT(31)); + pdesc->Dword2 &= set_desc(0x03ffffff); // clear related bits + pdesc->Dword2 |= set_desc(3 << TX_TxAntCckSHIFT); // Set Default CCK rate with 2T + } + pdesc->Dword3 |= set_desc((GetSequence(dat_content) & TX_SeqMask) << TX_SeqSHIFT); + pdesc->Dword4 = set_desc(TX_DisDataFB | TX_UseRate); + + if (priv->pshare->is_40m_bw) + { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + pdesc->Dword4 |= set_desc(2 << TX_DataScSHIFT); + else + pdesc->Dword4 |= set_desc(1 << TX_DataScSHIFT); + } + priv->pshare->is_40m_bw_bak = priv->pshare->is_40m_bw; + + if (priv->pmib->dot11RFEntry.txbf == 1) { + pdesc->Dword2 &= set_desc(0x03ffffff); // clear related bits + + pdesc->Dword2 |= set_desc(1 << TX_TxAntCckSHIFT); // Set Default CCK rate with 1T + pdesc->Dword2 |= set_desc(1 << TX_TxAntlSHIFT); // Set Default Legacy rate with 1T + pdesc->Dword2 |= set_desc(1 << TX_TxAntHtSHIFT); // Set Default Ht rate + } + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + pdesc->Dword4 |= set_desc((4 & TX_RtsRateMask) << TX_RtsRateSHIFT); + pdesc->Dword5 |= set_desc((4 & TX_DataRateMask) << TX_DataRateSHIFT); + } + } +#endif + + priv->tx_beacon_len = txLength; + +#ifdef CONFIG_PCI_HCI + pdesc->Dword7 |= set_desc((unsigned short)(txLength) & TX_TxBufSizeMask); + pdesc->Dword8 = set_desc(get_physical_addr(priv, dat_content, txLength, PCI_DMA_TODEVICE)); +#endif // CONFIG_PCI_HCI + } + else + { + memset((void *)&pdesc->Dword3, 0, 4); + pdesc->Dword3 |= set_desc((GetSequence(dat_content) & TX_SeqMask) << TX_SeqSHIFT); + } + +#ifdef P2P_SUPPORT // 2013 + if((GET_CHIP_VER(priv)!=VERSION_8812E)){ + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) { + if(OPMODE&WIFI_P2P_SUPPORT && (P2PMODE==P2P_TMP_GO || P2PMODE==P2P_PRE_GO)){ + pdesc->Dword5 |= set_desc((4 & TX_DataRateMask) << TX_DataRateSHIFT); // use 6M to beacon rate + } + } + } +#endif + +} +#endif + +#ifdef CONFIG_PCI_HCI +void signin_beacon_desc(struct rtl8192cd_priv *priv, unsigned int *beaconbuf, unsigned int frlen) +{ + struct rtl8192cd_hw *phw=GET_HW(priv); + struct tx_desc *pdesc; +// unsigned int next_idx = 1; + +#ifdef MBSSID + if (IS_VAP_INTERFACE(priv)) { + pdesc = phw->tx_descB + priv->vap_init_seq; +// next_idx = priv->vap_init_seq + 1; + } + else +#endif + pdesc = phw->tx_descB; + + //memset(pdesc, 0, 32); // clear all bit + +#ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS && + (timer_pending(&GET_ROOT(priv)->ch_avail_chk_timer)) && + (GET_CHIP_VER(priv) == VERSION_8192D)) { + pdesc->Dword0 &= set_desc(~(TX_OWN)); + RTL_W16(PCIE_CTRL_REG, RTL_R16(PCIE_CTRL_REG)| (BCNQSTOP)); + return; + } +#endif + + + fill_bcn_desc(priv, pdesc, (void*)beaconbuf, frlen, 0); + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(get_desc(pdesc->Dword10)), frlen, PCI_DMA_TODEVICE); + else +#endif + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(get_desc(pdesc->Dword8)), frlen, PCI_DMA_TODEVICE); + + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) + priv->use_txdesc_cnt[BEACON_QUEUE]++; +#endif + +#ifdef MBSSID +if((GET_CHIP_VER(priv)== VERSION_8188C) || (GET_CHIP_VER(priv)== VERSION_8192C) || (GET_CHIP_VER(priv)== VERSION_8192D)) +{ + unsigned int tmp_522 = RTL_R8(0x522); //TXPAUSE register + if (priv->pmib->miscEntry.func_off && IS_ROOT_INTERFACE(priv)) + RTL_W8(0x522, tmp_522 | BIT(6)); + else if(tmp_522 & BIT(6)) + RTL_W8(0x522, tmp_522 & ~BIT(6)); +} +#endif + + pdesc->Dword0 |= set_desc(TX_OWN); +} +#endif // CONFIG_PCI_HCI + + + +/** + * @brief Update beacon content + * + * IBSS parameter set (STA), TIM (AP), ERP & Ext rate not set \n \n + * +----------------------------+-----+--------------------+-----+---------------------+-----+------------+-----+ \n + * | DS parameter (init_beacon) | TIM | IBSS parameter set | ERP | EXT supported rates | RSN | Realtek IE | CRC | \n + * +----------------------------+-----+--------------------+-----+---------------------+-----+------------+-----+ \n + * \n + * set_desc() set data to hardware, 8190n_hw.h define value + */ + + +#if 1//def RTK_AC_SUPPORT //for 11ac logo +int get_center_channel(struct rtl8192cd_priv *priv, int channel, int offset, int cur) +{ + int val = channel, bw=0; + + if (cur) + bw = priv->pshare->CurrentChannelBW; + else + bw = priv->pmib->dot11nConfigEntry.dot11nUse40M; + +#ifdef RTK_AC_SUPPORT + if (bw == HT_CHANNEL_WIDTH_80) + { +#ifdef AC2G_256QAM + if(is_ac2g(priv)) + val = 7; + else +#endif + if(channel <= 48) + val = 42; + else if(channel <= 64) + val = 58; + else if(channel <= 112) + val = 106; + else if(channel <= 128) + val = 122; + else if(channel <= 144) + val = 138; + else if(channel <= 161) + val = 155; + else if(channel <= 177) + val = 171; + } else +#endif + if (bw == HT_CHANNEL_WIDTH_20_40) { + if (offset == 1) + val -= 2; + else + val += 2; + } + + //SDEBUG("channel[%d] offset[%d] bw[%d] cent[%d]\n", channel, offset, bw, val); + return val; +} + + +#endif + + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) +int is_main_AP_interface(struct rtl8192cd_priv *priv) +{ + int i; + + if (IS_ROOT_INTERFACE(priv)) { + if (priv->pmib->miscEntry.func_off == 0) + return TRUE; + else + return FALSE; + } + else { // vap interfaces + if (GET_ROOT(priv)->pmib->miscEntry.func_off == 0) + return FALSE; +#if defined(MBSSID) + else { + for (i=0; ipvap_priv[i])) { + if ((GET_ROOT(priv)->pvap_priv[i])->pmib->miscEntry.func_off == 0) { + if (priv == (GET_ROOT(priv)->pvap_priv[i])) + return TRUE; + break; + } + } + } + return FALSE; + } +#endif + } +} +#endif + + +void update_beacon(struct rtl8192cd_priv *priv) +{ +#if !defined(SMP_SYNC) && defined(CONFIG_RTL_WAPI_SUPPORT) + unsigned long flags; +#endif + + struct wifi_mib *pmib; + struct rtl8192cd_hw *phw; + unsigned int frlen; + unsigned char *pbuf; + unsigned char *pbssrate=NULL; + int bssrate_len; + unsigned int i; + +#ifdef CONFIG_RTK_MESH + UINT8 meshiearray[32]; // mesh IE buffer (Max byte is mesh_ie_MeshID) +#endif + +#ifdef AUTO_CHANNEL_TIMEOUT + if (priv->pshare->autoch_trigger_by_timeout) + return; +#endif + + pmib = GET_MIB(priv); + phw = GET_HW(priv); + +#if defined(USE_OUT_SRC) || defined(CONFIG_POWER_SAVE) + if ( TRUE == priv->pshare->bScanInProcess ) + return; +#endif + + if (priv->update_bcn_period) + { + unsigned short val16 = 0; + pbuf = (unsigned char *)priv->beaconbuf; + frlen = 0; + + pbuf += 24; + frlen += 24; + + frlen += _TIMESTAMP_; // for timestamp + pbuf += _TIMESTAMP_; + + //setup BeaconPeriod... + val16 = cpu_to_le16(pmib->dot11StationConfigEntry.dot11BeaconPeriod); + pbuf = set_fixed_ie(pbuf, _BEACON_ITERVAL_, (unsigned char *)&val16, &frlen); + priv->update_bcn_period = 0; + } + frlen = priv->timoffset; + pbuf = (unsigned char *)priv->beaconbuf + priv->timoffset; + + // setting tim field... + if (OPMODE & WIFI_AP_STATE) + pbuf = update_tim(priv, pbuf, &frlen); + + if (OPMODE & WIFI_ADHOC_STATE) { + unsigned short val16 = 0; + pbuf = set_ie(pbuf, _IBSS_PARA_IE_, 2, (unsigned char *)&val16, &frlen); + } + +#ifdef MCR_WIRELESS_EXTEND + if (!priv->pshare->cmw_link) +#endif + { +#if defined(DOT11D) || defined(DOT11H) + if(priv->countryTableIdx) { + pbuf = construct_country_ie(priv, pbuf, &frlen); + } +#endif + +#ifdef DOT11H + if(priv->pmib->dot11hTPCEntry.tpc_enable) { + pbuf = set_ie(pbuf, _PWR_CONSTRAINT_IE_, 1, &priv->pshare->rf_ft_var.lpwrc, &frlen); + pbuf = construct_TPC_report_ie(priv, pbuf, &frlen); + } +#endif + } + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + // ERP infomation + unsigned char val8 = 0; + if (priv->pmib->dot11ErpInfo.protection) + val8 |= BIT(1); + if (priv->pmib->dot11ErpInfo.nonErpStaNum) + val8 |= BIT(0); + + if (!SHORTPREAMBLE || priv->pmib->dot11ErpInfo.longPreambleStaNum) + val8 |= BIT(2); + + pbuf = set_ie(pbuf, _ERPINFO_IE_, 1, &val8, &frlen); + } + + // EXT supported rates + if (get_bssrate_set(priv, _EXT_SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len)) + pbuf = set_ie(pbuf, _EXT_SUPPORTEDRATES_IE_, bssrate_len, pbssrate, &frlen); + + + /* + 2008-12-16, For Buffalo WLI_CB_AG54L 54Mbps NIC interoperability issue. + This NIC can not connect to our AP when our AP is set to WPA/TKIP encryption. + This issue can be fixed after move "HT Capability Info" and "Additional HT Info" in front of "WPA" and "WMM". + */ + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + construct_ht_ie(priv, priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + pbuf = set_ie(pbuf, _HT_CAP_, priv->ht_cap_len, (unsigned char *)&priv->ht_cap_buf, &frlen); + pbuf = set_ie(pbuf, _HT_IE_, priv->ht_ie_len, (unsigned char *)&priv->ht_ie_buf, &frlen); + } +// beacon +#ifdef RTK_AC_SUPPORT //for 11ac logo + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + // 41 + { + char tmp[8]; + memset(tmp, 0, 8); + tmp[7] = 0x40; + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 8, tmp, &frlen); + } + // 60, 61 +#ifdef MCR_WIRELESS_EXTEND + construct_vht_ie_mcr(priv, priv->pshare->working_channel, pstat); +#else + construct_vht_ie(priv, priv->pshare->working_channel); +#endif + pbuf = set_ie(pbuf, EID_VHTCapability, priv->vht_cap_len, (unsigned char *)&priv->vht_cap_buf, &frlen); + pbuf = set_ie(pbuf, EID_VHTOperation, priv->vht_oper_len, (unsigned char *)&priv->vht_oper_buf, &frlen); + // 62 + if(priv->pshare->rf_ft_var.lpwrc) { + char tmp[4]; + tmp[1] = tmp[2] = tmp[3] = priv->pshare->rf_ft_var.lpwrc; + tmp[0] = priv->pshare->CurrentChannelBW; // 20, 40, 80 + pbuf = set_ie(pbuf, EID_VHTTxPwrEnvelope, tmp[0]+2, tmp, &frlen); + } + } +#endif + + +#ifdef CONFIG_RTK_MESH // Mesh IE + if (GET_MIB(priv)->dot1180211sInfo.mesh_enable && !GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + // OFDM Parameter Set + pbuf = set_ie(pbuf, _OFDM_PARAMETER_SET_IE_, mesh_ie_OFDM(priv, meshiearray), meshiearray, &frlen); + // Mesh ID + pbuf = set_ie(pbuf, _MESH_ID_IE_, mesh_ie_MeshID(priv, meshiearray, FALSE), meshiearray, &frlen); + + // WLAN Mesh Capability + pbuf = set_ie(pbuf, _WLAN_MESH_CAP_IE_, mesh_ie_WLANMeshCAP(priv, meshiearray), meshiearray, &frlen); + + if(priv->mesh_swchnl_channel) { /*mesh channel switch procedure is on-going*/ + pbuf = set_ie(pbuf, _MESH_CHANNEL_SWITCH_IE_, mesh_ie_MeshChannelSwitch(priv, meshiearray), meshiearray, &frlen); + pbuf = set_ie(pbuf, _CSA_IE_, mesh_ie_ChannelSwitchAnnoun(priv, meshiearray), meshiearray, &frlen); + pbuf = set_ie(pbuf, _SECONDARY_CHANNEL_OFFSET_IE_, mesh_ie_SecondaryChannelOffset(priv, meshiearray), meshiearray, &frlen); + } + } + + /* if pure Mesh Point without mesh enable, don't send beacon*/ + if ( (OPMODE & WIFI_AP_STATE) && pmib->dot1180211sInfo.meshSilence ) + return; +#endif // CONFIG_RTK_MESH + +// 63 +#if defined(DFS) || defined(RTK_AC_SUPPORT) //for 11ac logo + if (GET_ROOT(priv)->pmib->dot11DFSEntry.DFS_detected && priv->pshare->dfsSwitchChannel) { + static unsigned int set_stop_bcn = 0; + + if (priv->pshare->dfsSwitchChCountDown) { + unsigned char tmpStr[3]; + tmpStr[0] = 1; /* channel switch mode */ + tmpStr[1] = priv->pshare->dfsSwitchChannel; /* new channel number */ + tmpStr[2] = priv->pshare->dfsSwitchChCountDown; /* channel switch count */ + pbuf = set_ie(pbuf, _CSA_IE_, 3, tmpStr, &frlen); + +#if defined(RTK_AC_SUPPORT) //for 11ac logo + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + unsigned char tmp2[15]; + int len = 5; + + tmp2[0] = EID_WIDEBW_CH_SW; + tmp2[1] = 3; + tmp2[2] = (priv->pmib->dot11nConfigEntry.dot11nUse40M==2) ? 1 : 0; + tmp2[3] = get_center_channel(priv, priv->pshare->dfsSwitchChannel, priv->pshare->offset_2nd_chan, 0); + tmp2[4] = 0; + pbuf = set_ie(pbuf, EID_CH_SW_WRAPPER, len, tmp2, &frlen); + } +#endif + + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + //if (IS_ROOT_INTERFACE(priv)) + if (is_main_AP_interface(priv)) +#endif + { + priv->pshare->dfsSwitchChCountDown--; + if (set_stop_bcn) + set_stop_bcn = 0; + } + } + else { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + //if (IS_ROOT_INTERFACE(priv)) + if (is_main_AP_interface(priv)) +#endif + { +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_RTL_8881A) + if ((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A)) { + if (GET_CHIP_VER(priv) == VERSION_8881A){ + PHY_SetBBReg(priv, 0xcb0, 0x000000f0, 4); + } + SwitchChannel(GET_ROOT(priv)); + if (GET_CHIP_VER(priv) == VERSION_8881A){ + delay_us(500); + PHY_SetBBReg(priv, 0xcb0, 0x000000f0, 5); + } + } + else +#endif + { +#ifdef DFS +#ifdef __ECOS + priv->pshare->has_triggered_dfs_switch_channel = 1; + priv->pshare->call_dsr = 1; +#else + DFS_SwitchChannel(GET_ROOT(priv)); +#endif +#endif + } + } +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + else { + if (!set_stop_bcn) { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + u8 RegTXPause; + GET_HAL_INTERFACE(priv)->GetHwRegHandler(priv, HW_VAR_TXPAUSE, (pu1Byte)&RegTXPause); + RegTXPause |= TXPAUSE_BCN_QUEUE_BIT; + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_TXPAUSE, (pu1Byte)&RegTXPause); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | STOP_BCN); + } + set_stop_bcn++; + } + } +#endif + return; + } + } +#endif + +#ifdef RTK_AC_SUPPORT //for 11ac logo + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + //66 + if(priv->pshare->rf_ft_var.opmtest&1) { + pbuf = set_ie(pbuf, EID_VHTOperatingMode, 1, (unsigned char *)&(priv->pshare->rf_ft_var.oper_mode_field), &frlen); + } + } +#endif + +#ifdef WIFI_11N_2040_COEXIST + if ((OPMODE & WIFI_AP_STATE) && + (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G)) && + priv->pmib->dot11nConfigEntry.dot11nCoexist && priv->pshare->is_40m_bw) { + unsigned char temp_buf = _2040_COEXIST_SUPPORT_ ; + construct_obss_scan_para_ie(priv); + pbuf = set_ie(pbuf, _OBSS_SCAN_PARA_IE_, priv->obss_scan_para_len, + (unsigned char *)&priv->obss_scan_para_buf, &frlen); +#ifdef HS2_SUPPORT + if (priv->pmib->hs2Entry.interworking_ielen) + { + unsigned char capArray[6]; + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_ | _2040_COEXIST_SUPPORT_ | _BSS_TRANSITION_; + if (priv->proxy_arp) + buf32 |= _PROXY_ARP_; + + if ((priv->pmib->hs2Entry.timezone_ielen!=0) && (priv->pmib->hs2Entry.timeadvt_ielen)) + buf32 |= _UTC_TSF_OFFSET_; + + temp_buf32 = cpu_to_le32(buf32); + //capArray[5]=0x40; //WNM notification + capArray[4]=0x0; + memcpy(capArray,(void *)(&temp_buf32),4); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 5, capArray, &frlen); + //pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + } + else +#endif + + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 1, &temp_buf, &frlen); + } +#ifdef HS2_SUPPORT + else + { + if (priv->pmib->hs2Entry.interworking_ielen) + { + unsigned char capArray[6]; + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_ | _BSS_TRANSITION_; + if (priv->proxy_arp) + buf32 |= _PROXY_ARP_; + + if ((priv->pmib->hs2Entry.timezone_ielen!=0) && (priv->pmib->hs2Entry.timeadvt_ielen)) + buf32 |= _UTC_TSF_OFFSET_; + + temp_buf32 = cpu_to_le32(buf32); + //capArray[5]=0x40; //WNM notification + capArray[4]=0; + memcpy(capArray,(void *)(&temp_buf32),4); + + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 5, capArray, &frlen); + //pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + } + } +#endif +#endif + + if (pmib->dot11RsnIE.rsnielen) { + memcpy(pbuf, pmib->dot11RsnIE.rsnie, pmib->dot11RsnIE.rsnielen); + pbuf += pmib->dot11RsnIE.rsnielen; + frlen += pmib->dot11RsnIE.rsnielen; + } + +#ifdef WIFI_WMM + //Set WMM Parameter Element + if (QOS_ENABLE) + pbuf = set_ie(pbuf, _RSN_IE_1_, _WMM_Para_Element_Length_, GET_WMM_PARA_IE, &frlen); +#endif +#ifdef TDLS_SUPPORT + unsigned char tempbuf[6]; + if(priv->pmib->dot11OperationEntry.tdls_prohibited){ + tempbuf[4] = 0x40; // bit 38(tdls_prohibited) + } + if(priv->pmib->dot11OperationEntry.tdls_cs_prohibited){ + tempbuf[4] = 0x80; // bit 39(tdls_cs_prohibited) + } + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 5, tempbuf, &frlen); +#endif + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + /* + 2008-12-16, For Buffalo WLI_CB_AG54L 54Mbps NIC interoperability issue. + This NIC can not connect to our AP when our AP is set to WPA/TKIP encryption. + This issue can be fixed after move "HT Capability Info" and "Additional HT Info" in front of "WPA" and "WMM". + */ + //construct_ht_ie(priv, priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + //pbuf = set_ie(pbuf, _HT_CAP_, priv->ht_cap_len, (unsigned char *)&priv->ht_cap_buf, &frlen); + //pbuf = set_ie(pbuf, _HT_IE_, priv->ht_ie_len, (unsigned char *)&priv->ht_ie_buf, &frlen); + pbuf = construct_ht_ie_old_form(priv, pbuf, &frlen); + } + + // Realtek proprietary IE + if (priv->pshare->rtk_ie_len) + pbuf = set_ie(pbuf, _RSN_IE_1_, priv->pshare->rtk_ie_len, priv->pshare->rtk_ie_buf, &frlen); + + // Customer proprietary IE + if (priv->pmib->miscEntry.private_ie_len) { + memcpy(pbuf, pmib->miscEntry.private_ie, pmib->miscEntry.private_ie_len); + pbuf += pmib->miscEntry.private_ie_len; + frlen += pmib->miscEntry.private_ie_len; + } + +#ifdef USER_ADDIE +{ + int i; + for (i=0; iuser_ie_list[i].used) { + memcpy(pbuf, priv->user_ie_list[i].ie, priv->user_ie_list[i].ie_len); + pbuf += priv->user_ie_list[i].ie_len; + fr_len += priv->user_ie_list[i].ie_len; + } + } +} +#endif +#if defined(CONFIG_RTL_WAPI_SUPPORT) + if (priv->pmib->wapiInfo.wapiType!=wapiDisable) + { + SAVE_INT_AND_CLI(flags); + *priv->pBeaconCapability |= cpu_to_le16(BIT(4)); /* set privacy */ + priv->wapiCachedBuf = pbuf+2; + wapiSetIE(priv); + pbuf[0] = _EID_WAPI_; + pbuf[1] = priv->wapiCachedLen; + pbuf += priv->wapiCachedLen+2; + frlen += priv->wapiCachedLen+2; + RESTORE_INT(flags); + } +#endif + +#ifdef WIFI_SIMPLE_CONFIG +/*modify for WPS2DOTX SUPPORT*/ + if (pmib->wscEntry.wsc_enable && pmib->wscEntry.beacon_ielen + && (priv->pmib->dot11StationConfigEntry.dot11AclMode != ACL_allow + || (priv->pmib->dot11StationConfigEntry.dot11AclMode == ACL_allow && priv->pmib->dot11StationConfigEntry.dot11AclNum > 0))) + { + memcpy(pbuf, pmib->wscEntry.beacon_ie, pmib->wscEntry.beacon_ielen); + pbuf += pmib->wscEntry.beacon_ielen; + frlen += pmib->wscEntry.beacon_ielen; + } +#endif + +#ifdef HS2_SUPPORT + // support hs2 enable, p2p disable + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.hs2_ielen) + { + //unsigned char p2ptmpie[]={0x50,0x6f,0x9a,0x09,0x02,0x02,0x00,0x00,0x00}; + unsigned char p2ptmpie[]={0x50,0x6f,0x9a,0x09,0x0a,0x01,0x00,0x05}; + pbuf = set_ie(pbuf, 221, sizeof(p2ptmpie), p2ptmpie, &frlen); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.hs2_ielen) + { + pbuf = set_ie(pbuf, _HS2_IE_, priv->pmib->hs2Entry.hs2_ielen, priv->pmib->hs2Entry.hs2_ie, &frlen); + + priv->pmib->hs2Entry.bssload_ie[0] = priv->assoc_num & 0xff; + priv->pmib->hs2Entry.bssload_ie[1] = (priv->assoc_num & 0xff00) >> 8; + priv->pmib->hs2Entry.bssload_ie[2] = priv->channel_utilization; + priv->pmib->hs2Entry.bssload_ie[3] = 0; + priv->pmib->hs2Entry.bssload_ie[4] = 0; + pbuf = set_ie(pbuf, _BSS_LOAD_IE_, 5, priv->pmib->hs2Entry.bssload_ie, &frlen); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.interworking_ielen) + { + unsigned char magicmac[MACADDRLEN]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + if (!memcmp(magicmac,priv->pmib->hs2Entry.interworking_ie+3,6)) { // this case is used for HS2 testing (means MAC address of the AP) + memcpy(priv->pmib->hs2Entry.interworking_ie+3, priv->pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + pbuf = set_ie(pbuf, _INTERWORKING_IE_, priv->pmib->hs2Entry.interworking_ielen, priv->pmib->hs2Entry.interworking_ie, &frlen); + + } + else { + pbuf = set_ie(pbuf, _INTERWORKING_IE_, priv->pmib->hs2Entry.interworking_ielen, priv->pmib->hs2Entry.interworking_ie, &frlen); + } + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.advt_proto_ielen) + { + pbuf = set_ie(pbuf, _ADVT_PROTO_IE_, priv->pmib->hs2Entry.advt_proto_ielen, priv->pmib->hs2Entry.advt_proto_ie, &frlen); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.MBSSID_ielen) + { + pbuf = set_ie(pbuf, _MUL_BSSID_IE_, priv->pmib->hs2Entry.MBSSID_ielen, priv->pmib->hs2Entry.MBSSID_ie, &frlen); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.roam_ielen && priv->pmib->hs2Entry.roam_enable) + { + pbuf = set_ie(pbuf, _ROAM_IE_, priv->pmib->hs2Entry.roam_ielen, priv->pmib->hs2Entry.roam_ie, &frlen); + } + + if (priv->dtimcount == 0) + { + if (priv->timeadvt_dtimcount == 0) + { + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.timeadvt_ielen) + { + pbuf = set_ie(pbuf, _TIMEADVT_IE_, priv->pmib->hs2Entry.timeadvt_ielen, priv->pmib->hs2Entry.timeadvt_ie, &frlen); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.timezone_ielen) + { + pbuf = set_ie(pbuf, _TIMEZONE_IE_, priv->pmib->hs2Entry.timezone_ielen, priv->pmib->hs2Entry.timezone_ie, &frlen); + } + priv->timeadvt_dtimcount = priv->pmib->hs2Entry.timeadvt_DTIMIntval-1; + } + else + { + priv->timeadvt_dtimcount--; + } + } +#endif + +#ifdef P2P_SUPPORT + if ((OPMODE&WIFI_P2P_SUPPORT) && ((P2PMODE==P2P_PRE_GO)||(P2PMODE ==P2P_TMP_GO)) ) + { + if(priv->p2pPtr->p2p_beacon_ie_len){ + memcpy(pbuf, priv->p2pPtr->p2p_beacon_ie, priv->p2pPtr->p2p_beacon_ie_len); + pbuf += priv->p2pPtr->p2p_beacon_ie_len; + frlen += priv->p2pPtr->p2p_beacon_ie_len; + } + } +#endif + +#ifdef USER_ADDIE + for (i=0; iuser_ie_list[i].used) { + memcpy(pbuf, priv->user_ie_list[i].ie, priv->user_ie_list[i].ie_len); + pbuf += priv->user_ie_list[i].ie_len; + frlen += priv->user_ie_list[i].ie_len; + } + } +#endif + +/* + pdesc->Dword0 = set_desc(TX_FirstSeg| TX_LastSeg| (32)<Dword1 = set_desc(0x10 << TX_QSelSHIFT); +// pdesc->Dword4 = set_desc((0x7 << TX_RaBRSRIDSHIFT) | TX_UseRate); // need to confirm + pdesc->Dword4 = set_desc(TX_UseRate); + pdesc->Dword4 = set_desc(TX_DisDataFB); + pdesc->Dword7 = set_desc(frlen & TX_TxBufSizeMask); +*/ // by signin_beacon_desc + +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196C_EC) + priv->ext_stats.tx_byte_cnt += frlen; +#endif +//#ifdef CONFIG_RTL865X_AC +#if defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) + priv->ext_stats.tx_byte_cnt += frlen; +#endif + +#ifdef WDS + // if pure WDS bridge, don't send beacon + if ((OPMODE & WIFI_AP_STATE) && pmib->dot11WdsInfo.wdsPure) + return; +#endif + + // if schedule off, don't send beacon + if (priv->pmib->miscEntry.func_off) + { +#ifdef MBSSID + if(!((GET_CHIP_VER(priv)== VERSION_8188C) || (GET_CHIP_VER(priv)== VERSION_8192C) || (GET_CHIP_VER(priv)== VERSION_8192D))) + return; + else if(!IS_ROOT_INTERFACE(priv)) + return; +#else + return; +#endif + } + + if (!IS_DRV_OPEN(priv)) + return; + +// pdesc->Dword0 |= set_desc(TX_OWN); // by signin_beacon_desc + assign_wlanseq(phw, (unsigned char *)priv->beaconbuf, NULL ,pmib +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , 0 +#endif + ); +// pdesc->Dword3 |= set_desc((GetSequence(priv->beaconbuf) & TX_SeqMask)<< TX_SeqSHIFT); // by signin_beacon_desc +// rtl_cache_sync_wback(priv, get_desc(pdesc->Dword8), 128*sizeof(unsigned int), PCI_DMA_TODEVICE); // by signin_beacon_desc + +#ifdef CONFIG_PCI_HCI +#ifdef PCIE_POWER_SAVING + if((priv->offload_ctrl&1) && priv->pshare->rf_ft_var.power_save) { + unsigned char *prsp; + int len ; + struct tx_desc tx_desc; + len = frlen + TX_DESC_SZ; + if(len%PKT_PAGE_SZ) + len = (len+PKT_PAGE_SZ-(len%PKT_PAGE_SZ)) ; + priv->offload_ctrl = 1| (len&0x7f80); + + prsp = (unsigned char *)priv->beaconbuf + len ; + memset(prsp, 0, WLAN_HDR_A3_LEN); + len = WLAN_HDR_A3_LEN + fill_probe_rsp_content(priv, prsp, prsp+WLAN_HDR_A3_LEN, SSID, SSID_LEN, 1, 0, 0); + assign_wlanseq(phw, prsp, NULL ,pmib +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , 0 +#endif + ); + memset(&tx_desc, 0, TX_DESC_SZ); + fill_bcn_desc(priv, &tx_desc, (void*)prsp, len, 1); + tx_desc.Dword5 |= set_desc(TX_RtyLmtEn); + memcpy(prsp-TX_DESC_SZ, &tx_desc, TX_DESC_SZ ); + len += (priv->offload_ctrl&0x7f80) /*+TX_DESC_SZ*/; + signin_beacon_desc(priv, priv->beaconbuf, len); + } + else { + signin_beacon_desc(priv, priv->beaconbuf, frlen); + } + + // Now we use sw beacon, we need to poll it every time. + RTL_W8(PCIE_CTRL_REG, BCNQ_POLL); + +#else + + +#ifdef CONFIG_OFFLOAD_FUNCTION +#ifdef CONFIG_WLAN_HAL + + if((priv->offload_function_ctrl&1)) { + // this section is for AP_OFFLOAD download + unsigned char *prsp; + const unsigned char txDesSize = 40; + const unsigned int txPktSize = 256; + unsigned char pkt_offset = 0; + unsigned int dummy = 0; + unsigned int probePayloadLen = 0; + unsigned int TotalPktLen = 0; + + unsigned int len ; + len = frlen + txDesSize; // add beacon tx desc size , + // now len is represent from beacon desc + beacon payload + + dummy = GET_HAL_INTERFACE(priv)->GetRsvdPageLocHandler(priv,len,&pkt_offset); + // dummy = bcn pkt_len + dummy + + priv->offload_bcn_page = RTL_R8(0x209); + priv->offload_proc_page = RTL_R8(0x209) + pkt_offset; + + printk("priv->offload_bcn_page =%x \n",priv->offload_bcn_page); + printk("priv->offload_proc_page =%x \n",priv->offload_proc_page); + printk("dummy =%x \n",dummy); + + prsp = (unsigned char *)priv->beaconbuf + dummy ; + memset(prsp, 0, WLAN_HDR_A3_LEN); + probePayloadLen = WLAN_HDR_A3_LEN + fill_probe_rsp_content(priv, prsp, prsp+WLAN_HDR_A3_LEN, SSID, SSID_LEN, 1, 0, 0); + len = probePayloadLen; + + assign_wlanseq(phw, prsp, NULL ,pmib +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , 0 +#endif + ); + + TotalPktLen = probePayloadLen + dummy; + + GET_HAL_INTERFACE(priv)->SetRsvdPageHandler(priv,prsp,priv->beaconbuf,probePayloadLen,TotalPktLen); + + // TODO: currently, we do not implement this function, so mark it temporarily + // 8814 merge issue + //GET_HAL_INTERFACE(priv)->DownloadRsvdPageHandler(priv,priv->beaconbuf,frlen); + priv->offload_function_ctrl = 0; + } + else +#endif // #ifdef CONFIG_WLAN_HAL +#endif //#ifdef CONFIG_OFFLOAD_FUNCTION + { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->SigninBeaconTXBDHandler(priv, priv->beaconbuf, frlen); + GET_HAL_INTERFACE(priv)->SetBeaconDownloadHandler(priv, HW_VAR_BEACON_ENABLE_DOWNLOAD); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + signin_beacon_desc(priv, priv->beaconbuf, frlen); + } + + // Now we use sw beacon, we need to poll it every time. + //RTL_W8(PCIE_CTRL_REG, BCNQ_POLL); +#endif + } +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef SDIO_AP_OFFLOAD + if ((RTW_PM_PREPROCESS == priv->pshare->offload_function_ctrl) +#ifdef MBSSID + && (0 == priv->vap_init_seq) +#endif +#ifdef CONFIG_SDIO_TX_INTERRUPT + && !GET_HAL_INTF_DATA(priv)->SdioTxIntStatus +#ifdef CONFIG_SDIO_TX_IN_INTERRUPT + && !priv->pshare->xmit_thread_state +#endif +#endif + ) + { + ap_offload_process(priv, frlen); + } + else +#endif + { + signin_beacon_desc(priv, priv->beaconbuf, frlen); + } +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI +} + + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) && defined(CLIENT_MODE) // wrt-adhoc +void construct_ibss_beacon(struct rtl8192cd_priv *priv) +{ + unsigned short val16; + unsigned char val8; + struct wifi_mib *pmib; + unsigned char *bssid; + + unsigned int frlen=0; + unsigned char *pbuf=(unsigned char *)priv->beaconbuf_ibss_vxd; + unsigned char *pbssrate=NULL; + int bssrate_len; + struct FWtemplate *txfw; + struct FWtemplate Temptxfw; + + unsigned int rate; + + + pmib = GET_MIB(priv); + bssid = pmib->dot11StationConfigEntry.dot11Bssid; + + + + { + unsigned char tmpbssid[MACADDRLEN]; + + unsigned char random; + int i =0; + + memset(tmpbssid, 0, MACADDRLEN); + if (!memcmp(BSSID, tmpbssid, MACADDRLEN)) { + // generate an unique Ibss ssid +#ifdef __ECOS + { + unsigned char random_buf[4]; + get_random_bytes(random_buf, 4); + random = random_buf[3]; + } +#else + get_random_bytes(&random, 1); +#endif + tmpbssid[0] = 0x02; + for (i=1; isite_survey->count_target; i++) { + if (!memcmp(tmpbssid, priv->site_survey->bss_target[i].bssid, MACADDRLEN)) { + tmpbssid[5]++; + break; + } + } + if (i == priv->site_survey->count) + break; + } + } + } + + memset(pbuf, 0, sizeof(priv->beaconbuf_ibss_vxd)); + + txfw = &Temptxfw; + rate = find_rate(priv, NULL, 0, 1); + + if (is_MCS_rate(rate)) { + // can we use HT rates for beacon? + txfw->txRate = rate & 0x7f; + txfw->txHt = 1; + } + else { + txfw->txRate = get_rate_index_from_ieee_value((UINT8)rate); + if (priv->pshare->is_40m_bw) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + txfw->txSC = 2; + else + txfw->txSC = 1; + } + } + + SetFrameSubType(pbuf, WIFI_BEACON); + + memset((void *)GetAddr1Ptr(pbuf), 0xff, 6); + memcpy((void *)GetAddr2Ptr(pbuf), GET_MY_HWADDR, 6); + memcpy((void *)GetAddr3Ptr(pbuf), bssid, 6); // (Indeterminable set null mac (all zero)) (Refer: Draft 1.06, Page 12, 7.2.3, Line 21~30) + + pbuf += 24; + frlen += 24; + + frlen += _TIMESTAMP_; // for timestamp + pbuf += _TIMESTAMP_; + + //setup BeaconPeriod... + if(priv->beacon_period <= 0) + priv->beacon_period = pmib->dot11StationConfigEntry.dot11BeaconPeriod; + + if(priv->beacon_period) + val16 = cpu_to_le16(priv->beacon_period); + else + val16 = cpu_to_le16(100); + + pbuf = set_fixed_ie(pbuf, _BEACON_ITERVAL_, (unsigned char *)&val16, &frlen); + + val16 = cpu_to_le16(BIT(1)); //IBSS + + + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) + val16 |= cpu_to_le16(BIT(4)); + + if (SHORTPREAMBLE) + val16 |= cpu_to_le16(BIT(5)); +#ifdef RTK_AC_SUPPORT //for 11ac logo + if(priv->pshare->rf_ft_var.lpwrc) + val16 |= cpu_to_le16(BIT(8)); /* set spectrum mgt */ +#endif + + pbuf = set_fixed_ie(pbuf, _CAPABILITY_, (unsigned char *)&val16, &frlen); + priv->pBeaconCapability = (unsigned short *)(pbuf - _CAPABILITY_); + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && (priv->pmib->dot11ErpInfo.shortSlot)) + SET_SHORTSLOT_IN_BEACON_CAP; + else + RESET_SHORTSLOT_IN_BEACON_CAP; + + //set ssid... + pbuf = set_ie(pbuf, _SSID_IE_, SSID_LEN, SSID, &frlen); + + //supported rates... + get_bssrate_set(priv, _SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len); + pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_, bssrate_len, pbssrate, &frlen); + + + val16 = 0; + pbuf = set_ie(pbuf, _IBSS_PARA_IE_, 2, (unsigned char *)&val16, &frlen); + + +#if defined(DOT11D) || defined(DOT11H) + if(priv->countryTableIdx) { + pbuf = construct_country_ie(priv, pbuf, &frlen); + } +#endif + +#ifdef DOT11H + if(priv->pmib->dot11hTPCEntry.tpc_enable) { + pbuf = set_ie(pbuf, _PWR_CONSTRAINT_IE_, 1, &priv->pshare->rf_ft_var.lpwrc, &frlen); + pbuf = construct_TPC_report_ie(priv, pbuf, &frlen); + } +#endif + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + // ERP infomation + unsigned char val8 = 0; + if (priv->pmib->dot11ErpInfo.protection) + val8 |= BIT(1); + if (priv->pmib->dot11ErpInfo.nonErpStaNum) + val8 |= BIT(0); + + if (!SHORTPREAMBLE || priv->pmib->dot11ErpInfo.longPreambleStaNum) + val8 |= BIT(2); + + pbuf = set_ie(pbuf, _ERPINFO_IE_, 1, &val8, &frlen); + } + + // EXT supported rates + if (get_bssrate_set(priv, _EXT_SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len)) + pbuf = set_ie(pbuf, _EXT_SUPPORTEDRATES_IE_, bssrate_len, pbssrate, &frlen); + + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + construct_ht_ie(priv, priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + pbuf = set_ie(pbuf, _HT_CAP_, priv->ht_cap_len, (unsigned char *)&priv->ht_cap_buf, &frlen); + pbuf = set_ie(pbuf, _HT_IE_, priv->ht_ie_len, (unsigned char *)&priv->ht_ie_buf, &frlen); + } + // beacon +#ifdef RTK_AC_SUPPORT //for 11ac logo + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + // 41 + { + char tmp[8]; + memset(tmp, 0, 8); + tmp[7] = 0x40; + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 8, tmp, &frlen); + } + // 60, 61 + construct_vht_ie(priv, priv->pshare->working_channel); + pbuf = set_ie(pbuf, EID_VHTCapability, priv->vht_cap_len, (unsigned char *)&priv->vht_cap_buf, &frlen); + pbuf = set_ie(pbuf, EID_VHTOperation, priv->vht_oper_len, (unsigned char *)&priv->vht_oper_buf, &frlen); + // 62 + if(priv->pshare->rf_ft_var.lpwrc) { + char tmp[4]; + tmp[1] = tmp[2] = tmp[3] = priv->pshare->rf_ft_var.lpwrc; + tmp[0] = priv->pshare->CurrentChannelBW; // 20, 40, 80 + pbuf = set_ie(pbuf, EID_VHTTxPwrEnvelope, tmp[0]+2, tmp, &frlen); + } + } +#endif + +#ifdef RTK_AC_SUPPORT //for 11ac logo + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + //66 + if(priv->pshare->rf_ft_var.opmtest&1) { + pbuf = set_ie(pbuf, EID_VHTOperatingMode, 1, (unsigned char *)&(priv->pshare->rf_ft_var.oper_mode_field), &frlen); + } + } +#endif + + if (pmib->dot11RsnIE.rsnielen) { + memcpy(pbuf, pmib->dot11RsnIE.rsnie, pmib->dot11RsnIE.rsnielen); + pbuf += pmib->dot11RsnIE.rsnielen; + frlen += pmib->dot11RsnIE.rsnielen; + } + +#ifdef WIFI_WMM + //Set WMM Parameter Element + if (QOS_ENABLE) + pbuf = set_ie(pbuf, _RSN_IE_1_, _WMM_Para_Element_Length_, GET_WMM_PARA_IE, &frlen); +#endif + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + pbuf = construct_ht_ie_old_form(priv, pbuf, &frlen); + } + + // Realtek proprietary IE + if (priv->pshare->rtk_ie_len) + pbuf = set_ie(pbuf, _RSN_IE_1_, priv->pshare->rtk_ie_len, priv->pshare->rtk_ie_buf, &frlen); + + // Customer proprietary IE + if (priv->pmib->miscEntry.private_ie_len) { + memcpy(pbuf, pmib->miscEntry.private_ie, pmib->miscEntry.private_ie_len); + pbuf += pmib->miscEntry.private_ie_len; + frlen += pmib->miscEntry.private_ie_len; + } + + priv->beaconbuf_ibss_vxd_len = frlen; + +} + + +#ifdef __KERNEL__ +void issue_beacon_ibss_vxd(unsigned long task_priv) +#elif defined(__ECOS) +void issue_beacon_ibss_vxd(void *task_priv) +#endif +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned long flags; + DECLARE_TXINSN(txinsn); + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + + if(priv->beaconbuf_ibss_vxd_len<=0) + goto issue_beacon_ibss_done; + + if(!netif_running(priv->dev)) + goto issue_beacon_ibss_done; + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.phdr = get_wlanhdr_from_poll(priv); + txinsn.pframe = get_mgtbuf_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_beacon_ibss_fail; + + if (txinsn.pframe == NULL) + goto issue_beacon_ibss_fail; + +//fill MAC header + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + SetFrameSubType(txinsn.phdr, WIFI_BEACON); + memset((void *)GetAddr1Ptr((txinsn.phdr)), 0xff, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + +//fill Beacon frames + txinsn.fr_len = (priv->beaconbuf_ibss_vxd_len-24); + + if(txinsn.fr_len > 0) + memcpy((unsigned char *)txinsn.pframe, (((unsigned char *)priv->beaconbuf_ibss_vxd)+24) , txinsn.fr_len); + else + goto issue_beacon_ibss_fail; + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + goto issue_beacon_ibss_done; + +issue_beacon_ibss_fail: + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + +issue_beacon_ibss_done: + RESTORE_INT(flags); + SMP_UNLOCK(flags); + + mod_timer(&priv->pshare->vxd_ibss_beacon, jiffies + RTL_MILISECONDS_TO_JIFFIES(500)); + +} + + +#endif + + +/** + * @brief Initial beacon + * + * Refer wifi.h and 8190mib.h about MIB define. \n + * Refer 802.11 7,3,13 Beacon interval field \n + * - Timestamp \n - Beacon interval \n - Capability \n - SSID \n - Support rate \n - DS Parameter set \n \n + * +-------+-------+-------+ \n + * | addr1 | addr2 | addr3 | \n + * +-------+-------+-------+ \n + * + * +-----------+-----------------+------------+------+--------------+------------------+ \n + * | Timestamp | Beacon interval | Capability | SSID | Support rate | DS Parameter set | \n + * +-----------+-----------------+------------+------+--------------+------------------+ \n + * [Note] \n + * abridge FH (unused), CF (AP not support PCF), \n + * IBSS parameter set (STA), DTIM (AP), ERP ??Ext rate IE complete in Update beacon.\n + * set_desc is important. + */ + +void init_beacon(struct rtl8192cd_priv *priv) +{ + unsigned short val16; + unsigned char val8; + struct wifi_mib *pmib; + unsigned char *bssid; +// struct tx_desc *pdesc; +// struct rtl8192cd_hw *phw=GET_HW(priv); +// int next_idx = 1; + + unsigned int frlen=0; + unsigned char *pbuf=(unsigned char *)priv->beaconbuf; + unsigned char *pbssrate=NULL; + int bssrate_len; + struct FWtemplate *txfw; + struct FWtemplate Temptxfw; + + unsigned int rate; + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) //wrt-adhoc + if(IS_VXD_INTERFACE(priv) && (OPMODE & WIFI_ADHOC_STATE)) + return; +#endif + + pmib = GET_MIB(priv); + bssid = pmib->dot11StationConfigEntry.dot11Bssid; + + //memset(pbuf, 0, 128*4); + memset(pbuf, 0, sizeof(priv->beaconbuf)); + txfw = &Temptxfw; + +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + rate = _6M_RATE_; + }else +#endif + rate = find_rate(priv, NULL, 0, 1); + +#ifdef _11s_TEST_MODE_ + mesh_debug_sme2(priv, &rate); +#endif + + if (is_MCS_rate(rate)) { + // can we use HT rates for beacon? + txfw->txRate = rate - HT_RATE_ID; + txfw->txHt = 1; + } + else { + txfw->txRate = get_rate_index_from_ieee_value((UINT8)rate); + if (priv->pshare->is_40m_bw) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + txfw->txSC = 2; + else + txfw->txSC = 1; + } + } + + SetFrameSubType(pbuf, WIFI_BEACON); + + memset((void *)GetAddr1Ptr(pbuf), 0xff, 6); + memcpy((void *)GetAddr2Ptr(pbuf), GET_MY_HWADDR, 6); + memcpy((void *)GetAddr3Ptr(pbuf), bssid, 6); // (Indeterminable set null mac (all zero)) (Refer: Draft 1.06, Page 12, 7.2.3, Line 21~30) + + pbuf += 24; + frlen += 24; + + frlen += _TIMESTAMP_; // for timestamp + pbuf += _TIMESTAMP_; + + //setup BeaconPeriod... + val16 = cpu_to_le16(pmib->dot11StationConfigEntry.dot11BeaconPeriod); +#ifdef CLIENT_MODE + if (OPMODE & WIFI_ADHOC_STATE) + val16 = cpu_to_le16(priv->beacon_period); +#endif + pbuf = set_fixed_ie(pbuf, _BEACON_ITERVAL_, (unsigned char *)&val16, &frlen); + +#ifdef CONFIG_RTK_MESH + if ((1 == GET_MIB(priv)->dot1180211sInfo.mesh_enable) && (0 == GET_MIB(priv)->dot1180211sInfo.mesh_ap_enable)) // non-AP MP (MAP) only, popen:802.11s Draft 1.0 P17 7.3.1.4 : ESS & IBSS are "0" (PS:val reset here) + val16= 0; + else +#endif // CONFIG_RTK_MESH + { + if (OPMODE & WIFI_AP_STATE) + val16 = cpu_to_le16(BIT(0)); //ESS + else + val16 = cpu_to_le16(BIT(1)); //IBSS + } + + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) + val16 |= cpu_to_le16(BIT(4)); + + if (SHORTPREAMBLE) + val16 |= cpu_to_le16(BIT(5)); + +#ifdef DOT11H + if(priv->pmib->dot11hTPCEntry.tpc_enable) + val16 |= cpu_to_le16(BIT(8)); /* set spectrum mgt */ +#endif + + pbuf = set_fixed_ie(pbuf, _CAPABILITY_, (unsigned char *)&val16, &frlen); + priv->pBeaconCapability = (unsigned short *)(pbuf - _CAPABILITY_); + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && (priv->pmib->dot11ErpInfo.shortSlot)) + SET_SHORTSLOT_IN_BEACON_CAP; + else + RESET_SHORTSLOT_IN_BEACON_CAP; + + //set ssid... +#ifdef WIFI_SIMPLE_CONFIG + priv->pbeacon_ssid = pbuf; +#endif +#ifdef CONFIG_RTK_MESH + if ((1 == GET_MIB(priv)->dot1180211sInfo.mesh_enable) && (0 == GET_MIB(priv)->dot1180211sInfo.mesh_ap_enable)) // non-AP MP (MAP) only, popen:802.11s Draft 1.0, Page 11, SSID + pbuf = set_ie(pbuf, _SSID_IE_, 0, 0, &frlen); // wildcard SSID (len = 0) + else +#endif + { + if (!HIDDEN_AP) + pbuf = set_ie(pbuf, _SSID_IE_, SSID_LEN, SSID, &frlen); + else { +#ifdef CONFIG_RTL8196B_TLD + pbuf = set_ie(pbuf, _SSID_IE_, 0, NULL, &frlen); +#else + unsigned char ssidbuf[32]; + memset(ssidbuf, 0, 32); + pbuf = set_ie(pbuf, _SSID_IE_, SSID_LEN, ssidbuf, &frlen); +#endif + } + } + + //supported rates... + get_bssrate_set(priv, _SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len); + pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_, bssrate_len, pbssrate, &frlen); + + //ds parameter set... + val8 = pmib->dot11RFEntry.dot11channel; +#if defined(RTK_5G_SUPPORT) + if ( priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) +#endif + pbuf = set_ie(pbuf, _DSSET_IE_, 1, &val8, &frlen); + priv->timoffset = frlen; +// pdesc = phw->tx_descB; // by signin_beacon_desc + // clear all bit +// memset(pdesc, 0, 32); // by signin_beacon_desc + +// pdesc->Dword4 |= set_desc(0x08 << TX_RtsRateSHIFT); // by signin_beacon_desc +// pdesc->Dword8 = set_desc(get_physical_addr(priv, priv->beaconbuf, 128*sizeof(unsigned int), PCI_DMA_TODEVICE)); // by signin_beacon_desc + + // next pointer should point to a descriptor, david + //set NextDescAddress +// pdesc->Dword10 = set_desc(get_physical_addr(priv, &phw->tx_descB[next_idx], sizeof(struct tx_desc), PCI_DMA_TODEVICE)); // by signin_beacon_desc + +#ifdef CONFIG_PCI_HCI + update_beacon(priv); + + // enable tx bcn +//#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) +// if (IS_ROOT_INTERFACE(priv)) +//#endif +// RTL_W8(BCN_CTRL, EN_BCN_FUNCTION); + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->TxPollingHandler(priv, TXPOLL_BEACON_QUEUE); + } else +#endif + { + // use hw beacon +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv) != VERSION_8812E) +#endif + RTL_W8(PCIE_CTRL_REG, BCNQ_POLL); + } + +#ifndef DRVMAC_LB +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->SetHwRegHandler(priv, HW_VAR_ENABLE_BEACON_DMA, NULL); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + RTL_W16(PCIE_CTRL_REG, RTL_R16(PCIE_CTRL_REG)& (~ BCNQSTOP) ); + } +#endif +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI +#if defined(CONFIG_RTL_92C_SUPPORT) || (!defined(CONFIG_SUPPORT_USB_INT) || !defined(CONFIG_INTERRUPT_BASED_TXBCN)) + if (!timer_pending(&priv->pshare->beacon_timer)) + mod_timer(&priv->pshare->beacon_timer, jiffies); +#endif +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI + if (!timer_pending(&priv->pshare->beacon_timer)) + mod_timer(&priv->pshare->beacon_timer, jiffies + + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod)); +#endif // CONFIG_SDIO_HCI +} + + +#ifndef CONFIG_RTL_NEW_AUTOCH +static void setChannelScore(int number, unsigned int *val, int min, int max) +{ + int i=0, score; + + if (number > max) + return; + + *(val + number) += 5; + + if (number > min) { + for (i=number-1, score=4; i>=min && score; i--, score--) { + *(val + i) += score; + } + } + if (number < max) { + for (i=number+1, score=4; i<=max && score; i++, score--) { + *(val +i) += score; + } + } +} +#endif + + +#if defined(CONFIG_RTL_NEW_AUTOCH) && defined(SS_CH_LOAD_PROC) +static void record_SS_report(struct rtl8192cd_priv *priv) +{ + int i, j; + priv->ch_ss_rpt_cnt = priv->site_survey->count; + memset(priv->ch_ss_rpt, 0, (sizeof(struct ss_report)*MAX_BSS_NUM)); + + for(i=0; isite_survey->count ;i++){ + priv->ch_ss_rpt[i].channel = priv->site_survey->bss[i].channel; + priv->ch_ss_rpt[i].is40M = ((priv->site_survey->bss[i].t_stamp[1] & BIT(1)) ? 1 : 0); + priv->ch_ss_rpt[i].rssi = priv->site_survey->bss[i].rssi; + for (j=0; javailable_chnl_num; j++) { + if (priv->ch_ss_rpt[i].channel == priv->available_chnl[j]) { + priv->ch_ss_rpt[i].fa_count = priv->chnl_ss_fa_count[j]; + priv->ch_ss_rpt[i].cca_count = priv->chnl_ss_cca_count[j]; + priv->ch_ss_rpt[i].ch_load = priv->chnl_ss_load[j]; + } + } + } +} +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) +struct ap_info { + unsigned char ch; + unsigned char bw; + unsigned char rssi; +}; + +#define MASK_CH(_ch, _begin, _end) if ((_ch) >= (_begin) && (_ch) < (_end)) score[_ch] = 0xffffffff; +int find_clean_channel(struct rtl8192cd_priv *priv, unsigned int begin, unsigned int end, unsigned int *score) +{ + struct bss_desc *pBss=NULL; + int i, j, y, found; + int ap_count[MAX_2G_CHANNEL_NUM]; + struct ap_info ap_rec[MAX_BSS_NUM]; + unsigned int ap_rec_num = 0; + + memset(ap_count, 0, sizeof(ap_count)); + memset(ap_rec, 0, sizeof(ap_rec)); + + for (y=begin; ychnl_ss_fa_count[y]; +#ifdef _DEBUG_RTL8192CD_ + printk("ch %d: FA: %d\n", y+1, score[y]); +#endif + } + + for (i=0; isite_survey->count; i++) { + pBss = &priv->site_survey->bss[i]; + + ap_rec[ap_rec_num].ch = pBss->channel; + if ((pBss->t_stamp[1] & 0x6) == 0) ap_rec[ap_rec_num].bw = 0; + else if ((pBss->t_stamp[1] & 0x4) == 0) ap_rec[ap_rec_num].bw = 1; + else ap_rec[ap_rec_num].bw = 2; + ap_rec[ap_rec_num++].rssi = pBss->rssi; + + if (pBss->rssi > 15) { + for (y=begin; ychannel == priv->available_chnl[y]) { + ap_count[y]++; + if ((pBss->t_stamp[1] & 0x6) == 0) { // 20M + for (j=-2; j<=2; j++) + MASK_CH(y+j, begin, end); + } + else if ((pBss->t_stamp[1] & 0x4) == 0) { // 40M upper + for (j=-2; j<=6; j++) + MASK_CH(y+j, begin, end); + } + else { // 40M lower + for (j=-6; j<=2; j++) + MASK_CH(y+j, begin, end); + } + } + } + } + } + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + && priv->pshare->is_40m_bw) { + for (y=begin; yavailable_chnl[y] == 14) + score[y] = 0xffffffff; // mask chan14 + } + + if (priv->pmib->dot11RFEntry.disable_ch1213) { + for (y=begin; yavailable_chnl[y]; + if ((ch == 12) || (ch == 13)) + score[y] = 0xffffffff; + } + } + + if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_GLOBAL) || + (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_WORLD_WIDE)) && + (end >= 11) && (end < 14)) { + score[13] = 0xffffffff; // mask chan14 + score[12] = 0xffffffff; // mask chan13 + score[11] = 0xffffffff; // mask chan12 + } + +#ifdef _DEBUG_RTL8192CD_ + for (y=begin; yavailable_chnl[y] == ap_rec[i].ch) { + printk("%s:%d ", ap_rec[i].bw==0?"N":(ap_rec[i].bw==1?"U":"L"), ap_rec[i].rssi); + } + } + printk("\n"); + } +#endif + + for (y=begin; ypmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20_40) + i = 4; + else + i = 2; + + for (j=-i; j<=i; j++) { + if ((y+j >= begin) && (y+j < end)) { + if (score[y+j] == 0xffffffff) { + found = 0; + break; + } + } + } + + if (found) + return 1; + } + + return 0; +} +#endif + +//#define ACS_DEBUG_INFO //acs debug default off + +int selectClearChannel(struct rtl8192cd_priv *priv) +{ + static unsigned int score2G[MAX_2G_CHANNEL_NUM], score5G[MAX_5G_CHANNEL_NUM]; + unsigned int score[64], use_nhm = 0; + unsigned int minScore=0xffffffff; + unsigned int tmpScore, tmpIdx=0; + unsigned int traffic_check = 0; + unsigned int fa_count_weighting = 1; + int i, j, idx=0, idx_2G_end=-1, idx_5G_begin=-1, minChan=0; + struct bss_desc *pBss=NULL; + +#ifdef _DEBUG_RTL8192CD_ + char tmpbuf[400]; + int len=0; +#endif + + memset(score2G, '\0', sizeof(score2G)); + memset(score5G, '\0', sizeof(score5G)); + + for (i=0; iavailable_chnl_num; i++) { + if (priv->available_chnl[i] <= 14) + idx_2G_end = i; + else + break; + } + + for (i=0; iavailable_chnl_num; i++) { + if (priv->available_chnl[i] > 14) { + idx_5G_begin = i; + break; + } + } + +#ifndef CONFIG_RTL_NEW_AUTOCH + for (i=0; isite_survey->count; i++) { + pBss = &priv->site_survey->bss[i]; + for (idx=0; idxavailable_chnl_num; idx++) { + if (pBss->channel == priv->available_chnl[idx]) { + if (pBss->channel <= 14) + setChannelScore(idx, score2G, 0, MAX_2G_CHANNEL_NUM-1); + else + score5G[idx - idx_5G_begin] += 5; + break; + } + } + } +#endif + + if (idx_2G_end >= 0) + for (i=0; i<=idx_2G_end; i++) + score[i] = score2G[i]; + if (idx_5G_begin >= 0) + for (i=idx_5G_begin; iavailable_chnl_num; i++) + score[i] = score5G[i - idx_5G_begin]; + +#ifdef CONFIG_RTL_NEW_AUTOCH + { + unsigned int y, /*cca_thd=0, ch_num=0,*/ ch_begin=0, ch_end= priv->available_chnl_num; + /*unsigned int mac_rx_th=0, mac_rx_ch_count=0, fa_ch_count=0;*/ + unsigned int do_ap_check = 1, ap_ratio = 0; + + if (idx_2G_end >= 0) + ch_end = idx_2G_end+1; + if (idx_5G_begin >= 0) + ch_begin = idx_5G_begin; + +#ifdef ACS_DEBUG_INFO//for debug + printk("\n"); + for (y=ch_begin; yavailable_chnl[y], + priv->chnl_ss_mac_rx_count[y], + priv->chnl_ss_mac_rx_count_40M[y], + priv->chnl_ss_fa_count[y], + score[y]); + printk("\n"); +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv) == VERSION_8192E) + && priv->pmib->dot11RFEntry.acs_type) + { + unsigned int tmp_score[64]; + memcpy(tmp_score, score, sizeof(score)); + if (find_clean_channel(priv, ch_begin, ch_end, tmp_score)) { + //memcpy(score, tmp_score, sizeof(score)); +#ifdef _DEBUG_RTL8192CD_ + printk("!! Found clean channel, select minimum FA channel\n"); +#endif + goto USE_CLN_CH; + } +#ifdef _DEBUG_RTL8192CD_ + printk("!! Not found clean channel, use NHM algorithm\n"); +#endif + use_nhm = 1; +USE_CLN_CH: + for (y=ch_begin; ynhm_cnt[y][i]; + for (j=0; jL, score: %d\n", + y+1, priv->nhm_cnt[y][9], priv->nhm_cnt[y][8], priv->nhm_cnt[y][7], + priv->nhm_cnt[y][6], priv->nhm_cnt[y][5], priv->nhm_cnt[y][4], + priv->nhm_cnt[y][3], priv->nhm_cnt[y][2], priv->nhm_cnt[y][1], + priv->nhm_cnt[y][0], score[y]); +#endif + } + + if (!use_nhm) + memcpy(score, tmp_score, sizeof(score)); + + goto choose_ch; + } +#endif + + /* + * For each channel, weighting behind channels with MAC RX counter + * For each channel, weighting the channel with FA counter + */ + for (y=ch_begin; ychnl_ss_mac_rx_count[y]; + if (priv->chnl_ss_mac_rx_count[y] > 30) + do_ap_check = 0; + if( priv->chnl_ss_mac_rx_count[y] > MAC_RX_COUNT_THRESHOLD ) + traffic_check = 1; + +#ifdef RTK_5G_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) +#endif + { + if ((int)(y-4) >= (int)ch_begin) + score[y-4] += 2 * priv->chnl_ss_mac_rx_count[y]; + if ((int)(y-3) >= (int)ch_begin) + score[y-3] += 8 * priv->chnl_ss_mac_rx_count[y]; + if ((int)(y-2) >= (int)ch_begin) + score[y-2] += 8 * priv->chnl_ss_mac_rx_count[y]; + if ((int)(y-1) >= (int)ch_begin) + score[y-1] += 10 * priv->chnl_ss_mac_rx_count[y]; + if ((int)(y+1) < (int)ch_end) + score[y+1] += 10 * priv->chnl_ss_mac_rx_count[y]; + if ((int)(y+2) < (int)ch_end) + score[y+2] += 8 * priv->chnl_ss_mac_rx_count[y]; + if ((int)(y+3) < (int)ch_end) + score[y+3] += 8 * priv->chnl_ss_mac_rx_count[y]; + if ((int)(y+4) < (int)ch_end) + score[y+4] += 2 * priv->chnl_ss_mac_rx_count[y]; + } + + //this is for CH_LOAD caculation + if( priv->chnl_ss_cca_count[y] > priv->chnl_ss_fa_count[y]) + priv->chnl_ss_cca_count[y]-= priv->chnl_ss_fa_count[y]; + else + priv->chnl_ss_cca_count[y] = 0; + } + +#ifdef ACS_DEBUG_INFO//for debug + printk("\n"); + for (y=ch_begin; yavailable_chnl[y], score[y]); + printk("\n"); +#endif + + for (y=ch_begin; ychnl_ss_mac_rx_count_40M[y]) { + score[y] += 5 * priv->chnl_ss_mac_rx_count_40M[y]; + if (priv->chnl_ss_mac_rx_count_40M[y] > 30) + do_ap_check = 0; + if( priv->chnl_ss_mac_rx_count_40M[y] > MAC_RX_COUNT_THRESHOLD ) + traffic_check = 1; + +#ifdef RTK_5G_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) +#endif + { + if ((int)(y-6) >= (int)ch_begin) + score[y-6] += 1 * priv->chnl_ss_mac_rx_count_40M[y]; + if ((int)(y-5) >= (int)ch_begin) + score[y-5] += 4 * priv->chnl_ss_mac_rx_count_40M[y]; + if ((int)(y-4) >= (int)ch_begin) + score[y-4] += 4 * priv->chnl_ss_mac_rx_count_40M[y]; + if ((int)(y-3) >= (int)ch_begin) + score[y-3] += 5 * priv->chnl_ss_mac_rx_count_40M[y]; + if ((int)(y-2) >= (int)ch_begin) + score[y-2] += (5 * priv->chnl_ss_mac_rx_count_40M[y])/2; + if ((int)(y-1) >= (int)ch_begin) + score[y-1] += 5 * priv->chnl_ss_mac_rx_count_40M[y]; + if ((int)(y+1) < (int)ch_end) + score[y+1] += 5 * priv->chnl_ss_mac_rx_count_40M[y]; + if ((int)(y+2) < (int)ch_end) + score[y+2] += (5 * priv->chnl_ss_mac_rx_count_40M[y])/2; + if ((int)(y+3) < (int)ch_end) + score[y+3] += 5 * priv->chnl_ss_mac_rx_count_40M[y]; + if ((int)(y+4) < (int)ch_end) + score[y+4] += 4 * priv->chnl_ss_mac_rx_count_40M[y]; + if ((int)(y+5) < (int)ch_end) + score[y+5] += 4 * priv->chnl_ss_mac_rx_count_40M[y]; + if ((int)(y+6) < (int)ch_end) + score[y+6] += 1 * priv->chnl_ss_mac_rx_count_40M[y]; + } + } + } + +#ifdef ACS_DEBUG_INFO//for debug + printk("\n"); + for (y=ch_begin; yavailable_chnl[y], score[y]); + printk("\n"); + printk("4. do_ap_check=%d traffic_check=%d\n", do_ap_check, traffic_check); + printk("\n"); +#endif + + if( traffic_check == 0) + fa_count_weighting = 5; + else + fa_count_weighting = 1; + + for (y=ch_begin; ychnl_ss_fa_count[y]; + } + +#ifdef ACS_DEBUG_INFO//for debug + printk("\n"); + for (y=ch_begin; yavailable_chnl[y], score[y]); + printk("\n"); +#endif + + if (do_ap_check) { + for (i=0; isite_survey->count; i++) { + pBss = &priv->site_survey->bss[i]; + for (y=ch_begin; ychannel == priv->available_chnl[y]) { + if (pBss->channel <= 14) { +#ifdef ACS_DEBUG_INFO//for debug + printk("\n"); + printk("chnl[%d] has ap rssi=%d bw[0x%02x]\n", + pBss->channel, pBss->rssi, pBss->t_stamp[1]); + printk("\n"); +#endif + if (pBss->rssi > 60) + ap_ratio = 4; + else if (pBss->rssi > 35) + ap_ratio = 2; + else + ap_ratio = 1; + + if ((pBss->t_stamp[1] & 0x6) == 0) { + score[y] += 50 * ap_ratio; + if ((int)(y-4) >= (int)ch_begin) + score[y-4] += 10 * ap_ratio; + if ((int)(y-3) >= (int)ch_begin) + score[y-3] += 20 * ap_ratio; + if ((int)(y-2) >= (int)ch_begin) + score[y-2] += 30 * ap_ratio; + if ((int)(y-1) >= (int)ch_begin) + score[y-1] += 40 * ap_ratio; + if ((int)(y+1) < (int)ch_end) + score[y+1] += 40 * ap_ratio; + if ((int)(y+2) < (int)ch_end) + score[y+2] += 30 * ap_ratio; + if ((int)(y+3) < (int)ch_end) + score[y+3] += 20 * ap_ratio; + if ((int)(y+4) < (int)ch_end) + score[y+4] += 10 * ap_ratio; + } + else if ((pBss->t_stamp[1] & 0x4) == 0) { + score[y] += 50 * ap_ratio; + if ((int)(y-3) >= (int)ch_begin) + score[y-3] += 20 * ap_ratio; + if ((int)(y-2) >= (int)ch_begin) + score[y-2] += 30 * ap_ratio; + if ((int)(y-1) >= (int)ch_begin) + score[y-1] += 40 * ap_ratio; + if ((int)(y+1) < (int)ch_end) + score[y+1] += 50 * ap_ratio; + if ((int)(y+2) < (int)ch_end) + score[y+2] += 50 * ap_ratio; + if ((int)(y+3) < (int)ch_end) + score[y+3] += 50 * ap_ratio; + if ((int)(y+4) < (int)ch_end) + score[y+4] += 50 * ap_ratio; + if ((int)(y+5) < (int)ch_end) + score[y+5] += 40 * ap_ratio; + if ((int)(y+6) < (int)ch_end) + score[y+6] += 30 * ap_ratio; + if ((int)(y+7) < (int)ch_end) + score[y+7] += 20 * ap_ratio; + } + else { + score[y] += 50 * ap_ratio; + if ((int)(y-7) >= (int)ch_begin) + score[y-7] += 20 * ap_ratio; + if ((int)(y-6) >= (int)ch_begin) + score[y-6] += 30 * ap_ratio; + if ((int)(y-5) >= (int)ch_begin) + score[y-5] += 40 * ap_ratio; + if ((int)(y-4) >= (int)ch_begin) + score[y-4] += 50 * ap_ratio; + if ((int)(y-3) >= (int)ch_begin) + score[y-3] += 50 * ap_ratio; + if ((int)(y-2) >= (int)ch_begin) + score[y-2] += 50 * ap_ratio; + if ((int)(y-1) >= (int)ch_begin) + score[y-1] += 50 * ap_ratio; + if ((int)(y+1) < (int)ch_end) + score[y+1] += 40 * ap_ratio; + if ((int)(y+2) < (int)ch_end) + score[y+2] += 30 * ap_ratio; + if ((int)(y+3) < (int)ch_end) + score[y+3] += 20 * ap_ratio; + } + } + else { + if ((pBss->t_stamp[1] & 0x6) == 0) { + score[y] += 500; + } + else if ((pBss->t_stamp[1] & 0x4) == 0) { + score[y] += 500; + if ((int)(y+1) < (int)ch_end) + score[y+1] += 500; + } + else { + score[y] += 500; + if ((int)(y-1) >= (int)ch_begin) + score[y-1] += 500; + } + } + break; + } + } + } + } + +#ifdef ACS_DEBUG_INFO//for debug + printk("\n"); + for (y=ch_begin; yavailable_chnl[y],score[y]); + printk("\n"); +#endif + +#ifdef SS_CH_LOAD_PROC + + // caculate noise level -- suggested by wilson + for (y=ch_begin; ychnl_ss_fa_count[y]>1000) { + fa_lv = 100; + } else if (priv->chnl_ss_fa_count[y]>500) { + fa_lv = 34 * (priv->chnl_ss_fa_count[y]-500) / 500 + 66; + } else if (priv->chnl_ss_fa_count[y]>200) { + fa_lv = 33 * (priv->chnl_ss_fa_count[y] - 200) / 300 + 33; + } else if (priv->chnl_ss_fa_count[y]>100) { + fa_lv = 18 * (priv->chnl_ss_fa_count[y] - 100) / 100 + 15; + } else { + fa_lv = 15 * priv->chnl_ss_fa_count[y] / 100; + } + if (priv->chnl_ss_cca_count[y]>400) { + cca_lv = 100; + } else if (priv->chnl_ss_cca_count[y]>200) { + cca_lv = 34 * (priv->chnl_ss_cca_count[y] - 200) / 200 + 66; + } else if (priv->chnl_ss_cca_count[y]>80) { + cca_lv = 33 * (priv->chnl_ss_cca_count[y] - 80) / 120 + 33; + } else if (priv->chnl_ss_cca_count[y]>40) { + cca_lv = 18 * (priv->chnl_ss_cca_count[y] - 40) / 40 + 15; + } else { + cca_lv = 15 * priv->chnl_ss_cca_count[y] / 40; + } + + priv->chnl_ss_load[y] = (((fa_lv > cca_lv)? fa_lv : cca_lv)*75+((score[y]>100)?100:score[y])*25)/100; + + DEBUG_INFO("ch:%d f=%d (%d), c=%d (%d), fl=%d, cl=%d, sc=%d, cu=%d\n", + priv->available_chnl[y], + priv->chnl_ss_fa_count[y], fa_thd, + priv->chnl_ss_cca_count[y], cca_thd, + fa_lv, + cca_lv, + score[y], + priv->chnl_ss_load[y]); + + } +#endif + } +#endif + +choose_ch: + +#ifdef DFS + // heavy weighted DFS channel + if (idx_5G_begin >= 0){ + for (i=idx_5G_begin; iavailable_chnl_num; i++) { + if (!priv->pmib->dot11DFSEntry.disable_DFS && is_DFS_channel(priv->available_chnl[i]) + && (score[i]!= 0xffffffff)){ + score[i] += 1600; + } + } + } +#endif + + +//prevent Auto Channel selecting wrong channel in 40M mode----------------- + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + && priv->pshare->is_40m_bw) { +#if 0 + if (GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset == 1) { + //Upper Primary Channel, cannot select the two lowest channels + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + score[0] = 0xffffffff; + score[1] = 0xffffffff; + score[2] = 0xffffffff; + score[3] = 0xffffffff; + score[4] = 0xffffffff; + + score[13] = 0xffffffff; + score[12] = 0xffffffff; + score[11] = 0xffffffff; + } + +// if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { +// score[idx_5G_begin] = 0xffffffff; +// score[idx_5G_begin + 1] = 0xffffffff; +// } + } + else if (GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset == 2) { + //Lower Primary Channel, cannot select the two highest channels + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + score[0] = 0xffffffff; + score[1] = 0xffffffff; + score[2] = 0xffffffff; + + score[13] = 0xffffffff; + score[12] = 0xffffffff; + score[11] = 0xffffffff; + score[10] = 0xffffffff; + score[9] = 0xffffffff; + } + +// if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { +// score[priv->available_chnl_num - 2] = 0xffffffff; +// score[priv->available_chnl_num - 1] = 0xffffffff; +// } + } +#endif + for (i=0; i<=idx_2G_end; ++i) + if (priv->available_chnl[i] == 14) + score[i] = 0xffffffff; // mask chan14 + +#ifdef RTK_5G_SUPPORT + if (idx_5G_begin >= 0) { + for (i=idx_5G_begin; iavailable_chnl_num; i++) { + int ch = priv->available_chnl[i]; + if(ch > 144) + --ch; + if((ch%4) || ch==140 || ch == 164 ) //mask ch 140, ch 165, ch 184... + score[i] = 0xffffffff; + } + } +#endif + + + } + + if (priv->pmib->dot11RFEntry.disable_ch1213) { + for (i=0; i<=idx_2G_end; ++i) { + int ch = priv->available_chnl[i]; + if ((ch == 12) || (ch == 13)) + score[i] = 0xffffffff; + } + } + + if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_GLOBAL) || + (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_WORLD_WIDE)) && + (idx_2G_end >= 11) && (idx_2G_end < 14)) { + score[13] = 0xffffffff; // mask chan14 + score[12] = 0xffffffff; // mask chan13 + score[11] = 0xffffffff; // mask chan12 + } + +//------------------------------------------------------------------ + +#ifdef _DEBUG_RTL8192CD_ + for (i=0; iavailable_chnl_num; i++) { + len += sprintf(tmpbuf+len, "ch%d:%u ", priv->available_chnl[i], score[i]); + } + strcat(tmpbuf, "\n"); + panic_printk("%s", tmpbuf); + +#endif + + if ( (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + && (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80)) + { + for (i=0; iavailable_chnl_num; i++) { + if (is80MChannel(priv->available_chnl, priv->available_chnl_num, priv->available_chnl[i])) { + tmpScore = 0; + for (j=0; j<4; j++) { + if ((tmpScore != 0xffffffff) && (score[i+j] != 0xffffffff)) + tmpScore += score[i+j]; + else + tmpScore = 0xffffffff; + } + tmpScore = tmpScore / 4; + if (minScore > tmpScore) { + minScore = tmpScore; + + tmpScore = 0xffffffff; + for (j=0; j<4; j++) { + if (score[i+j] < tmpScore) { + tmpScore = score[i+j]; + tmpIdx = i+j; + } + } + + idx = tmpIdx; + } + i += 3; + } + } + if (minScore == 0xffffffff) { + // there is no 80M channels + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_20; + for (i=0; iavailable_chnl_num; i++) { + if (score[i] < minScore) { + minScore = score[i]; + idx = i; + } + } + } + } + else if( (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + && (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20_40)) + { + for (i=0; iavailable_chnl_num; i++) { + if(is40MChannel(priv->available_chnl,priv->available_chnl_num,priv->available_chnl[i])) { + tmpScore = 0; + for(j=0;j<2;j++) { + if ((tmpScore != 0xffffffff) && (score[i+j] != 0xffffffff)) + tmpScore += score[i+j]; + else + tmpScore = 0xffffffff; + } + tmpScore = tmpScore / 2; + if(minScore > tmpScore) { + minScore = tmpScore; + + tmpScore = 0xffffffff; + for (j=0; j<2; j++) { + if (score[i+j] < tmpScore) { + tmpScore = score[i+j]; + tmpIdx = i+j; + } + } + + idx = tmpIdx; + } + i += 1; + } + } + if (minScore == 0xffffffff) { + // there is no 40M channels + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_20; + for (i=0; iavailable_chnl_num; i++) { + if (score[i] < minScore) { + minScore = score[i]; + idx = i; + } + } + } + } + else if( (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) + && (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20_40) + && (priv->available_chnl_num >= 5) ) + { + unsigned int groupScore[14]; + + memset(groupScore, 0xff , sizeof(groupScore)); + for (i=0; iavailable_chnl_num-4; i++) { + if (score[i] != 0xffffffff && score[i+4] != 0xffffffff) { + groupScore[i] = score[i] + score[i+4]; + printk("groupScore, ch %d,%d: %d\n", i+1, i+5, groupScore[i]); + if (groupScore[i] < minScore) { +#ifdef AUTOCH_SS_SPEEDUP + if(priv->pmib->miscEntry.autoch_1611_enable) + { + if(priv->available_chnl[i]==1 || priv->available_chnl[i]==6 || priv->available_chnl[i]==11) + { + minScore = groupScore[i]; + idx = i; + } + } + else +#endif + { + minScore = groupScore[i]; + idx = i; + } + } + } + } + + if (score[idx] < score[idx+4]) { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + } else { + idx = idx + 4; + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + } + } + else + { + for (i=0; iavailable_chnl_num; i++) { + if (score[i] < minScore) { +#ifdef AUTOCH_SS_SPEEDUP + if(priv->pmib->miscEntry.autoch_1611_enable) + { + if(priv->available_chnl[i]==1 || priv->available_chnl[i]==6 || priv->available_chnl[i]==11) + { + minScore = score[i]; + idx = i; + } + } + else +#endif + { + minScore = score[i]; + idx = i; + } + } + } + } + + if (IS_A_CUT_8881A(priv) && + (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80)) { + if ((priv->available_chnl[idx] == 36) || + (priv->available_chnl[idx] == 52) || + (priv->available_chnl[idx] == 100) || + (priv->available_chnl[idx] == 116) || + (priv->available_chnl[idx] == 132) || + (priv->available_chnl[idx] == 149) || + (priv->available_chnl[idx] == 165)) + idx++; + else if ((priv->available_chnl[idx] == 48) || + (priv->available_chnl[idx] == 64) || + (priv->available_chnl[idx] == 112) || + (priv->available_chnl[idx] == 128) || + (priv->available_chnl[idx] == 144) || + (priv->available_chnl[idx] == 161) || + (priv->available_chnl[idx] == 177)) + idx--; + } + + minChan = priv->available_chnl[idx]; + + // skip channel 14 if don't support ofdm + if ((priv->pmib->dot11RFEntry.disable_ch14_ofdm) && + (minChan == 14)) { + score[idx] = 0xffffffff; + + minScore = 0xffffffff; + for (i=0; iavailable_chnl_num; i++) { + if (score[i] < minScore) { + minScore = score[i]; + idx = i; + } + } + minChan = priv->available_chnl[idx]; + } + +#if 0 + //Check if selected channel available for 80M/40M BW or NOT ? + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + { + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80) + { + if(!is80MChannel(priv->available_chnl,priv->available_chnl_num,minChan)) + { + //printk("BW=80M, selected channel = %d is unavaliable! reduce to 40M\n", minChan); + //priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20_40; + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_20_40; + } + } + + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_20_40) + { + if(!is40MChannel(priv->available_chnl,priv->available_chnl_num,minChan)) + { + //printk("BW=40M, selected channel = %d is unavaliable! reduce to 20M\n", minChan); + //priv->pmib->dot11nConfigEntry.dot11nUse40M = HT_CHANNEL_WIDTH_20; + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_20; + } + } + } +#endif + +#ifdef CONFIG_RTL_NEW_AUTOCH + RTL_W32(RXERR_RPT, RXERR_RPT_RST); +#endif + +// auto adjust contro-sideband + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + && (priv->pshare->is_40m_bw ==1 || priv->pshare->is_40m_bw ==2)) { + +#ifdef RTK_5G_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + if( (minChan>144) ? ((minChan-1)%8) : (minChan%8)) { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + } else { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + } + + } else +#endif + { +#if 0 +#ifdef CONFIG_RTL_NEW_AUTOCH + unsigned int ch_max; + + if (priv->available_chnl[idx_2G_end] >= 13) + ch_max = 13; + else + ch_max = priv->available_chnl[idx_2G_end]; + + if ((minChan >= 5) && (minChan <= (ch_max-5))) { + if (score[minChan+4] > score[minChan-4]) { /* what if some channels were cancelled? */ + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + } else { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + } + } else +#endif + { + if (minChan < 5) { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + } + else if (minChan > 7) { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + } + } +#endif + } + } +//----------------------- + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + panic_printk("Auto channel choose ch:%d\n", minChan); +#else +#ifdef _DEBUG_RTL8192CD_ + panic_printk("Auto channel choose ch:%d\n", minChan); +#endif +#endif +#ifdef ACS_DEBUG_INFO//for debug + printk("7. minChan:%d 2nd_offset:%d\n", minChan, priv->pshare->offset_2nd_chan); +#endif + + return minChan; +} + + +#ifdef CONFIG_RTL_WLAN_DOS_FILTER +int issue_disassoc_from_kernel(void *priv, unsigned char *mac) +{ + memcpy(block_mac[block_mac_idx], mac, 6); + block_mac_idx++; + block_mac_idx = block_mac_idx % MAX_BLOCK_MAC; + + if (priv != NULL) { +// issue_disassoc((struct rtl8192cd_priv *)priv, mac, _RSON_UNSPECIFIED_); + issue_deauth((struct rtl8192cd_priv *)priv, mac, _RSON_UNSPECIFIED_); + block_sta_time = ((struct rtl8192cd_priv *)priv)->pshare->rf_ft_var.dos_block_time; + block_priv = (unsigned long)priv; + } + return 0; +} +#endif + +/** + * @brief issue de-authenticaion + * + * Defragement fail will be de-authentication or STA issue deauthenticaion request + * + * +---------------+-----+----+----+-------+-----+-------------+ \n + * | Frame Control | ... | DA | SA | BSSID | ... | Reason Code | \n + * +---------------+-----+----+----+-------+-----+-------------+ \n + */ +void issue_deauth(struct rtl8192cd_priv *priv, unsigned char *da, int reason) +{ +#ifdef CONFIG_RTK_MESH + issue_deauth_MP(priv, da, reason, FALSE); +} + + +void issue_deauth_MP(struct rtl8192cd_priv *priv, unsigned char *da, int reason, UINT8 is_11s) +{ +#endif + struct wifi_mib *pmib; + unsigned char *bssid, *pbuf; + unsigned short val; + struct stat_info *pstat = get_stainfo(priv, da); + DECLARE_TXINSN(txinsn); + + if (!memcmp(da, "\x0\x0\x0\x0\x0\x0", 6)) + return; + + // check if da is legal + if (da[0] & 0x01 +#ifdef CONFIG_IEEE80211W + && memcmp(da,"\xff\xff\xff\xff\xff\xff",6) +#endif + ) { + DEBUG_WARN("Send Deauth Req to bad DA %02x%02x%02x%02x%02x%02x", da[0], da[1], da[2], da[3], da[4], da[5]); + return; + } + +#ifdef TLN_STATS + stats_conn_rson_counts(priv, reason); +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if (pstat && pstat->sta_in_firmware == 1) { + RTL8188E_MACID_NOLINK(priv, 1, REMAP_AID(pstat)); + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + } +#endif + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if(pstat && (REMAP_AID(pstat) < 128)) + { + DEBUG_WARN("%s %d issue_asocrsp, set MACID 0 AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + else + { + DEBUG_WARN(" MACID sleep only support 128 STA \n"); + } + } +#endif + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + pmib= GET_MIB(priv); + + bssid = pmib->dot11StationConfigEntry.dot11Bssid; + +#ifdef CONFIG_RTK_MESH + txinsn.is_11s = is_11s; +#endif + + txinsn.q_num = MANAGE_QUE_NUM; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.fr_type = _PRE_ALLOCMEM_; +#ifdef CONFIG_IEEE80211W + if (!memcmp(da,"\xff\xff\xff\xff\xff\xff",6)) { + txinsn.isPMF = 1; //????? + } else { + PMFDEBUG("txinsn.isPMF,pstat=%p, da=%02x%02x%02x%02x%02x%02x\n",pstat,da[0],da[1],da[2],da[3],da[4],da[5]); + + if (pstat) + txinsn.isPMF = pstat->isPMF; + else + txinsn.isPMF = 0; + } + //printk("deauth:txinsn.isPMF=%d\n",txinsn.isPMF); +#endif + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + + if (pbuf == NULL) + goto issue_deauth_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_deauth_fail; + + memset((void *)txinsn.phdr, 0, sizeof(struct wlan_hdr)); + + val = cpu_to_le16(reason); + + pbuf = set_fixed_ie(pbuf, _RSON_CODE_ , (unsigned char *)&val, &txinsn.fr_len); + +#ifdef P2P_SUPPORT + if(OPMODE&WIFI_P2P_SUPPORT && P2PMODE==P2P_CLIENT){ + if(priv->p2pPtr->p2p_disass_ie_len){ + memcpy(pbuf, priv->p2pPtr->p2p_disass_ie, priv->p2pPtr->p2p_disass_ie_len); + pbuf += priv->p2pPtr->p2p_disass_ie_len; + txinsn.fr_len += priv->p2pPtr->p2p_disass_ie_len; + } + } +#endif + + + SetFrameType((txinsn.phdr),WIFI_MGT_TYPE); + SetFrameSubType((txinsn.phdr),WIFI_DEAUTH); +#ifdef CONFIG_IEEE80211W + if (txinsn.isPMF) + *(unsigned char*)(txinsn.phdr+1) |= BIT(6); // enable privacy +#endif + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), bssid, MACADDRLEN); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + txinsn.is_urgent = 1; +#endif + + SNMP_MIB_ASSIGN(dot11DeauthenticateReason, reason); + SNMP_MIB_COPY(dot11DeauthenticateStation, da, MACADDRLEN); + +#ifdef MULTI_MAC_CLONE + if (OPMODE & WIFI_AP_STATE) { //if priv is AP, disconnect the client in multi-Sta + __del_mclone_addr(priv, da); + } +#endif + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ +#ifdef CONFIG_RTL_WLAN_STATUS + priv->wlan_status_flag=1; +#endif + return; + } + +issue_deauth_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); +} + + +void issue_disassoc(struct rtl8192cd_priv *priv, unsigned char *da, int reason) +{ + struct wifi_mib *pmib; + unsigned char *bssid, *pbuf; + unsigned short val; + struct stat_info *pstat; + DECLARE_TXINSN(txinsn); + + // check if da is legal + if (da[0] & 0x01) { + DEBUG_WARN("Send Disassoc Req to bad DA %02x%02x%02x%02x%02x%02x", da[0], da[1], da[2], da[3], da[4], da[5]); + return; + } + pstat = get_stainfo(priv, da); + +#ifdef TLN_STATS + stats_conn_rson_counts(priv, reason); +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + if (pstat && pstat->sta_in_firmware == 1) { + RTL8188E_MACID_NOLINK(priv, 1, REMAP_AID(pstat)); + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + } +#endif + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if(pstat && (REMAP_AID(pstat) < 128)) + { + DEBUG_WARN("%s %d issue disAssoc, set MACID 0 AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0 , REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + else + { + DEBUG_WARN(" MACID sleep only support 128 STA \n"); + } + } +#endif + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + pmib= GET_MIB(priv); + + bssid = pmib->dot11StationConfigEntry.dot11Bssid; + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; +#ifdef CONFIG_IEEE80211W + if (!memcmp(da,"\xff\xff\xff\xff\xff\xff",6)) { + txinsn.isPMF = 1; + } else { + if(pstat) + txinsn.isPMF = pstat->isPMF; + else + txinsn.isPMF = 0; + } + PMFDEBUG("deauth:isPMF=[%d]\n",txinsn.isPMF); +#endif + +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + + if (pbuf == NULL) + goto issue_disassoc_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_disassoc_fail; + + memset((void *)txinsn.phdr, 0, sizeof(struct wlan_hdr)); + + val = cpu_to_le16(reason); + + pbuf = set_fixed_ie(pbuf, _RSON_CODE_, (unsigned char *)&val, &txinsn.fr_len); + +#ifdef P2P_SUPPORT + if(OPMODE&WIFI_P2P_SUPPORT && P2PMODE==P2P_CLIENT){ + if(priv->p2pPtr->p2p_disass_ie_len){ + memcpy(pbuf, priv->p2pPtr->p2p_disass_ie, priv->p2pPtr->p2p_disass_ie_len); + pbuf += priv->p2pPtr->p2p_disass_ie_len; + txinsn.fr_len += priv->p2pPtr->p2p_disass_ie_len; + } + } +#endif + + SetFrameType((txinsn.phdr), WIFI_MGT_TYPE); + SetFrameSubType((txinsn.phdr), WIFI_DISASSOC); + +#ifdef CONFIG_IEEE80211W + if (txinsn.isPMF) + *(unsigned char*)(txinsn.phdr+1) |= BIT(6); // enable privacy +#endif + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), bssid, MACADDRLEN); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + txinsn.is_urgent = 1; +#endif + + SNMP_MIB_ASSIGN(dot11DisassociateReason, reason); + SNMP_MIB_COPY(dot11DisassociateStation, da, MACADDRLEN); + +#ifdef MULTI_MAC_CLONE + if (OPMODE & WIFI_AP_STATE) { //if priv is AP, disconnect the client in multi-Sta + __del_mclone_addr(priv, da); + } +#endif + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS){ +#ifdef CONFIG_RTL_WLAN_STATUS + priv->wlan_status_flag=1; +#endif + return; + } + +issue_disassoc_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); +} + + +// if pstat == NULL, indiate we are station now... +void issue_auth(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned short status) +{ + struct wifi_mib *pmib; + unsigned char *bssid, *pbuf; + unsigned short val; + int use_shared_key=0; + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + UINT8 isMeshMP = FALSE; +#endif // CONFIG_RTK_MESH + + DECLARE_TXINSN(txinsn); + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + pmib= GET_MIB(priv); + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if ((NULL != pstat) && (1 == GET_MIB(priv)->dot1180211sInfo.mesh_enable) && isPossibleNeighbor(pstat)) + isMeshMP = TRUE; + + if ((pstat) || (TRUE == isMeshMP)) +#else + if (pstat) +#endif //CONFIG_RTK_MESH + bssid = BSSID; + else + bssid = priv->pmib->dot11Bss.bssid; + +#if defined(CLIENT_MODE) && (defined(INCLUDE_WPA_PSK) || defined(RTK_NL80211)) + if (priv->assoc_reject_on && !memcmp(priv->assoc_reject_mac, bssid, MACADDRLEN)) { + DEBUG_INFO("[%s:%d] assoc_reject_on=1, "MACSTR"\n", __func__, __LINE__, MAC2STR(priv->assoc_reject_mac)); + goto issue_auth_fail; + } +#endif + + txinsn.q_num = MANAGE_QUE_NUM; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ // 2013 + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.fr_type = _PRE_ALLOCMEM_; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + + if (pbuf == NULL) + goto issue_auth_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_auth_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + // setting auth algm number + /* In AP mode, if auth is set to shared-key, use shared key + * if auth is set to auto, use shared key if client use shared + * otherwise set to open + * In client mode, if auth is set to shared-key or auto, and WEP is used, + * use shared key algorithm + */ + val = 0; + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) // skip SIMPLE_CONFIG and Auth check ,Force use open system auth. + if (FALSE == isMeshMP) +#endif + { + +#ifdef WIFI_SIMPLE_CONFIG + if (pmib->wscEntry.wsc_enable) { + if (pstat && (status == _STATS_SUCCESSFUL_) && (pstat->auth_seq == 2) && + (pstat->state & WIFI_AUTH_SUCCESS) && (pstat->AuthAlgrthm == 0)) + goto skip_security_check; + else if ((pstat == NULL) && (AUTH_SEQ == 1)) + goto skip_security_check; + } +#endif + + if (priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm > 0) { + if (pstat) { + if (priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm == 1) // shared key + val = 1; + else { // auto mode, check client algorithm + if (pstat && pstat->AuthAlgrthm) + val = 1; + } + } + else { // client mode, use shared key if WEP is enabled + if (priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm == 1) { // shared-key ONLY + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) + val = 1; + } + else { // auto-auth + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) { + if (AUTH_SEQ == 1) + AUTH_MODE_TOGGLE_VAL((AUTH_MODE_TOGGLE ? 0 : 1)); + + if (AUTH_MODE_TOGGLE) + val = 1; + } + } + } + + if (val) { + val = cpu_to_le16(val); + use_shared_key = 1; + } + } + + if (pstat && (status != _STATS_SUCCESSFUL_)) + val = cpu_to_le16(pstat->AuthAlgrthm); + } + +#ifdef WIFI_SIMPLE_CONFIG +skip_security_check: +#endif + + pbuf = set_fixed_ie(pbuf, _AUTH_ALGM_NUM_, (unsigned char *)&val, &txinsn.fr_len); + + // setting transaction sequence number... +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if ((pstat) || (TRUE == isMeshMP)) +#else + if (pstat) +#endif + val = cpu_to_le16(pstat->auth_seq); // Mesh only + else + val = cpu_to_le16(AUTH_SEQ); + + pbuf = set_fixed_ie(pbuf, _AUTH_SEQ_NUM_, (unsigned char *)&val, &txinsn.fr_len); + + // setting status code... + val = cpu_to_le16(status); + pbuf = set_fixed_ie(pbuf, _STATUS_CODE_, (unsigned char *)&val, &txinsn.fr_len); + + // then checking to see if sending challenging text... (Mesh skip this section) + if (pstat) + { + if ((pstat->auth_seq == 2) && (pstat->state & WIFI_AUTH_STATE1) && use_shared_key) + pbuf = set_ie(pbuf, _CHLGETXT_IE_, 128, pstat->chg_txt, &txinsn.fr_len); + } + else + { + if ((AUTH_SEQ == 3) && (OPMODE & WIFI_AUTH_STATE1) && use_shared_key) + { + pbuf = set_ie(pbuf, _CHLGETXT_IE_, 128, CHG_TXT, &txinsn.fr_len); + SetPrivacy(txinsn.phdr); + DEBUG_INFO("sending a privacy pkt with auth_seq=%d\n", AUTH_SEQ); + } + } + + SetFrameSubType((txinsn.phdr), WIFI_AUTH); + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if ((pstat) || (TRUE == isMeshMP)) +#else + if (pstat) // for AP mode +#endif + { + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), pstat->hwaddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), bssid, MACADDRLEN); + } + else + { + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), bssid, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + } + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if (TRUE == isMeshMP) // Though spec define management frames Address 3 is "null mac" (all zero), but avoid filter out by other MP, set "Other MP MAC") (Refer: Draft 1.06, Page 12, 7.2.3, Line 29~30 2007/08/11 by popen) + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), pstat->hwaddr, MACADDRLEN); + else +#endif + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), bssid, MACADDRLEN); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + txinsn.is_urgent = 1; +#endif + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +issue_auth_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); +} + +void issue_asocrsp(struct rtl8192cd_priv *priv, unsigned short status, struct stat_info *pstat, int pkt_type) +{ + unsigned short val; + struct wifi_mib *pmib; + unsigned char *bssid,*pbuf; + DECLARE_TXINSN(txinsn); + +#ifdef CONFIG_IEEE80211W + unsigned char iebuf[5]; + int timeout; + unsigned int temp_timeout; +#endif + +#ifdef TLN_STATS + stats_conn_status_counts(priv, status); +#endif + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + pmib= GET_MIB(priv); + + bssid = pmib->dot11StationConfigEntry.dot11Bssid; + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + update_remapAid(priv,pstat); + if (pstat->sta_in_firmware == 1) + { + RTL8188E_MACID_NOLINK(priv, (status == _STATS_SUCCESSFUL_)?0:1, REMAP_AID(pstat)); + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + } +#endif + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if(pstat && (REMAP_AID(pstat) < 128)) + { + DEBUG_WARN("%s %d issue_asocrsp, set MACID 0 AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0 ,REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + else + { + DEBUG_WARN(" MACID sleep only support 128 STA \n"); + } + } +#endif + + + + if (pbuf == NULL) + goto issue_asocrsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_asocrsp_fail; + + memset((void *)txinsn.phdr, 0, sizeof(struct wlan_hdr)); + + val = cpu_to_le16(BIT(0)); + + if (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) + val |= cpu_to_le16(BIT(4)); + + if (SHORTPREAMBLE) + val |= cpu_to_le16(BIT(5)); + + if (priv->pmib->dot11ErpInfo.shortSlot) + val |= cpu_to_le16(BIT(10)); + +#ifdef RTK_AC_SUPPORT //for 11ac logo + if(priv->pshare->rf_ft_var.lpwrc) + val |= cpu_to_le16(BIT(8)); /* set spectrum mgt */ +#endif + + pbuf = set_fixed_ie(pbuf, _CAPABILITY_, (unsigned char *)&val, &txinsn.fr_len); + + status = cpu_to_le16(status); + pbuf = set_fixed_ie(pbuf, _STATUS_CODE_, (unsigned char *)&status, &txinsn.fr_len); + + val = cpu_to_le16(pstat->aid | 0xC000); + pbuf = set_fixed_ie(pbuf, _ASOC_ID_, (unsigned char *)&val, &txinsn.fr_len); + + if (STAT_OPRATE_LEN <= 8) + pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_, STAT_OPRATE_LEN, STAT_OPRATE, &txinsn.fr_len); + else { + pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_, 8, STAT_OPRATE, &txinsn.fr_len); + pbuf = set_ie(pbuf, _EXT_SUPPORTEDRATES_IE_, STAT_OPRATE_LEN-8, STAT_OPRATE+8, &txinsn.fr_len); + } + +#ifdef CONFIG_IEEE80211W + if (status == cpu_to_le16(_STATS_ASSOC_REJ_TEMP_) && pstat->isPMF) { + iebuf[0] = ASSOC_COMEBACK_TIME; + + timeout = (int) RTL_JIFFIES_TO_MILISECONDS(pstat->sa_query_end - jiffies); + if(timeout < 0) + timeout = 0; + if(timeout < SA_QUERY_MAX_TO) + timeout++; + PMFDEBUG("ASSOC comeback time, timeout=%d\n", timeout); + temp_timeout = cpu_to_le32(timeout); + memcpy(&iebuf[1], &temp_timeout, 4); + pbuf = set_ie(pbuf, EID_TIMEOUT_INTERVAL, 5, iebuf, &txinsn.fr_len); + } +#endif + +#ifdef WIFI_WMM + //Set WMM Parameter Element + if ((QOS_ENABLE) && (pstat->QosEnabled)) + pbuf = set_ie(pbuf, _RSN_IE_1_, _WMM_Para_Element_Length_, GET_WMM_PARA_IE, &txinsn.fr_len); +#endif + +#ifdef WIFI_SIMPLE_CONFIG +/*modify for WPS2DOTX SUPPORT*/ + if (pmib->wscEntry.wsc_enable && pmib->wscEntry.assoc_ielen + && (priv->pmib->dot11StationConfigEntry.dot11AclMode != ACL_allow + || (priv->pmib->dot11StationConfigEntry.dot11AclMode == ACL_allow && priv->pmib->dot11StationConfigEntry.dot11AclNum > 0))) + { + memcpy(pbuf, pmib->wscEntry.assoc_ie, pmib->wscEntry.assoc_ielen); + pbuf += pmib->wscEntry.assoc_ielen; + txinsn.fr_len += pmib->wscEntry.assoc_ielen; + } +#endif + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && (pstat->ht_cap_len > 0)) { + if (!should_restrict_Nrate(priv, pstat)) { + pbuf = set_ie(pbuf, _HT_CAP_, priv->ht_cap_len, (unsigned char *)&priv->ht_cap_buf, &txinsn.fr_len); + pbuf = set_ie(pbuf, _HT_IE_, priv->ht_ie_len, (unsigned char *)&priv->ht_ie_buf, &txinsn.fr_len); + pbuf = construct_ht_ie_old_form(priv, pbuf, &txinsn.fr_len); + } + +#ifdef WIFI_11N_2040_COEXIST + if (priv->pmib->dot11nConfigEntry.dot11nCoexist && priv->pshare->is_40m_bw && + (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) { + unsigned char temp_buf = _2040_COEXIST_SUPPORT_ ; + construct_obss_scan_para_ie(priv); + pbuf = set_ie(pbuf, _OBSS_SCAN_PARA_IE_, priv->obss_scan_para_len, + (unsigned char *)&priv->obss_scan_para_buf, &txinsn.fr_len); + + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 1, &temp_buf, &txinsn.fr_len); + } +#endif + } + +#ifdef RTK_AC_SUPPORT //for 11ac logo + if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) && (!should_restrict_Nrate(priv, pstat))) + if((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_40_PRIVACY_) + && (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_104_PRIVACY_)) + { +// 41 + // operting mode + { + char tmp[8]; + memset(tmp, 0, 8); + tmp[7] = 0x40; + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 8, tmp, &txinsn.fr_len); + } + +//60, 61 + construct_vht_ie(priv, priv->pshare->working_channel); + pbuf = set_ie(pbuf, EID_VHTCapability, priv->vht_cap_len, (unsigned char *)&priv->vht_cap_buf, &txinsn.fr_len); + pbuf = set_ie(pbuf, EID_VHTOperation, priv->vht_oper_len, (unsigned char *)&priv->vht_oper_buf, &txinsn.fr_len); +// 66 + if(priv->pshare->rf_ft_var.opmtest&1) + pbuf = set_ie(pbuf, EID_VHTOperatingMode, 1, (unsigned char *)&(priv->pshare->rf_ft_var.oper_mode_field), &txinsn.fr_len); + + } +#endif + + // Realtek proprietary IE + if (priv->pshare->rtk_ie_len) + pbuf = set_ie(pbuf, _RSN_IE_1_, priv->pshare->rtk_ie_len, priv->pshare->rtk_ie_buf, &txinsn.fr_len); + +#ifdef P2P_SUPPORT + if(OPMODE&WIFI_P2P_SUPPORT && P2PMODE==P2P_TMP_GO){ + if(pstat->is_p2p_client){ + if(priv->p2pPtr->p2p_assoc_RspIe_len){ + memcpy(pbuf, priv->p2pPtr->p2p_assoc_RspIe , priv->p2pPtr->p2p_assoc_RspIe_len); + pbuf += priv->p2pPtr->p2p_assoc_RspIe_len; + txinsn.fr_len += priv->p2pPtr->p2p_assoc_RspIe_len; + } + } + } +#endif + + if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP)) + SetFrameSubType((txinsn.phdr), pkt_type); + else + goto issue_asocrsp_fail; + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), pstat->hwaddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), bssid, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), bssid, MACADDRLEN); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + txinsn.is_urgent = 1; +#endif + + +if((GET_CHIP_VER(priv) != VERSION_8812E) && (GET_CHIP_VER(priv) != VERSION_8881A)) +{ + unsigned int tmp_d2c = RTL_R32(0xd2c); + unsigned int val_d2c = tmp_d2c; + +#if defined(CONFIG_PCI_HCI) + if(pstat->IOTPeer== HT_IOT_PEER_INTEL) + { + tmp_d2c = (tmp_d2c & (~ BIT(11))); + } + else + { + if(is_intel_connected(priv)) + tmp_d2c = (tmp_d2c & (~ BIT(11))); + else + tmp_d2c = (tmp_d2c | BIT(11)); + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (orSTABitMap(&priv->pshare->intel_sta_bitmap)) + tmp_d2c = (tmp_d2c & (~ BIT(11))); + else + tmp_d2c = (tmp_d2c | BIT(11)); +#endif + + if (tmp_d2c ^ val_d2c) + RTL_W32(0xd2c, tmp_d2c); + +#if 1 + tmp_d2c = RTL_R32(0xd2c); + + if(tmp_d2c & BIT(11)) + printk("BIT(11) of 0xd2c = %d, 0xd2c = 0x%x\n", 1, tmp_d2c); + else + printk("BIT(11) of 0xd2c = %d, 0xd2c = 0x%x\n", 0, tmp_d2c); +#endif + +} + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) { +//#if !defined(CONFIG_RTL865X_KLD) && !defined(CONFIG_RTL8196B_KLD) +#if 0 + if(!SWCRYPTO && !IEEE8021X_FUN && + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_ || + pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_)) { + DOT11_SET_KEY Set_Key; + memcpy(Set_Key.MACAddr, pstat->hwaddr, 6); + Set_Key.KeyType = DOT11_KeyType_Pairwise; + Set_Key.EncType = pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + + Set_Key.KeyIndex = pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + DOT11_Process_Set_Key(priv->dev, NULL, &Set_Key, + pmib->dot11DefaultKeysTable.keytype[Set_Key.KeyIndex].skey); + } +#endif + return; + } + +issue_asocrsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); +} + + +int fill_probe_rsp_content(struct rtl8192cd_priv *priv, + UINT8 *phdr, UINT8 *pbuf, + UINT8 *ssid, int ssid_len, int set_privacy, UINT8 is_11s, UINT8 is_11b_only) +{ + unsigned short val; + struct wifi_mib *pmib; + unsigned char *bssid; + UINT8 val8; + unsigned char *pbssrate=NULL; + int bssrate_len, fr_len=0; +#ifdef CONFIG_RTK_MESH + UINT8 meshiearray[32]; // mesh IE buffer (Max byte is mesh_ie_MeshID) +#endif + +#if !defined(SMP_SYNC) && defined(CONFIG_RTL_WAPI_SUPPORT) + unsigned long flags; +#endif + +#ifdef P2P_SUPPORT + int need_include_p2pie = 0; +#endif + + pmib= GET_MIB(priv); + + bssid = pmib->dot11StationConfigEntry.dot11Bssid; + + pbuf += _TIMESTAMP_; + fr_len += _TIMESTAMP_; + + val = cpu_to_le16(pmib->dot11StationConfigEntry.dot11BeaconPeriod); + pbuf = set_fixed_ie(pbuf, _BEACON_ITERVAL_ , (unsigned char *)&val, (unsigned int *)&fr_len); + +#ifdef P2P_SUPPORT + if( (OPMODE & WIFI_P2P_SUPPORT) + && (P2PMODE == P2P_DEVICE) + && (P2P_STATE == P2P_S_LISTEN)) + { + val |= cpu_to_le16(BIT(0)); //set ESS to 1 + }else +#endif +#ifdef CONFIG_RTK_MESH + if ((1 == GET_MIB(priv)->dot1180211sInfo.mesh_enable) && (0 == GET_MIB(priv)->dot1180211sInfo.mesh_ap_enable)) // non-AP MP (MAP) only, popen:802.11s Draft 1.0 P17 7.3.1.4 : ESS & IBSS are "0" (PS:val Reset here.) + val = 0; + else +#endif + { + if (OPMODE & WIFI_AP_STATE) + val = cpu_to_le16(BIT(0)); //ESS + else + val = cpu_to_le16(BIT(1)); //IBSS + } + + if (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm && set_privacy) + val |= cpu_to_le16(BIT(4)); + +#if defined(CONFIG_RTL_WAPI_SUPPORT) + if (priv->pmib->wapiInfo.wapiType!=wapiDisable) + { + val |= cpu_to_le16(BIT(4)); /* set privacy */ + } +#endif + + if (SHORTPREAMBLE) + val |= cpu_to_le16(BIT(5)); + + if (priv->pmib->dot11ErpInfo.shortSlot) + val |= cpu_to_le16(BIT(10)); + +#ifdef DOT11H + if(priv->pmib->dot11hTPCEntry.tpc_enable) + val |= cpu_to_le16(BIT(8)); /* set spectrum mgt */ +#endif + + pbuf = set_fixed_ie(pbuf, _CAPABILITY_, (unsigned char *)&val, (unsigned int *)&fr_len); + + pbuf = set_ie(pbuf, _SSID_IE_, ssid_len, ssid, (unsigned int *)&fr_len); + +#ifdef P2P_SUPPORT + if(OPMODE&WIFI_P2P_SUPPORT) + get_bssrate_set(priv, _SUPPORTED_RATES_NO_CCK_, &pbssrate, &bssrate_len); + else +#endif + get_bssrate_set(priv, _SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len); + pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_, bssrate_len, pbssrate, (unsigned int *)&fr_len); + + +#ifdef P2P_SUPPORT // fill DSSET + if((OPMODE&WIFI_P2P_SUPPORT) && (P2PMODE == P2P_DEVICE)&& (P2P_STATE==P2P_S_LISTEN )){ + val8 = priv->pmib->p2p_mib.p2p_listen_channel; + }else +#endif + { + val8 = pmib->dot11RFEntry.dot11channel; + } + +#if defined(RTK_5G_SUPPORT) + if ( priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_2G) +#endif + pbuf = set_ie(pbuf, _DSSET_IE_, 1, &val8 , (unsigned int *)&fr_len); + + if (OPMODE & WIFI_ADHOC_STATE) { + unsigned short val16 = 0; + pbuf = set_ie(pbuf, _IBSS_PARA_IE_, 2, (unsigned char *)&val16, (unsigned int *)&fr_len); + } + +#if defined(DOT11D) || defined(DOT11H) + if(priv->countryTableIdx) { + pbuf = construct_country_ie(priv, pbuf, &fr_len); + } +#endif + + +#ifdef DOT11H + if(priv->pmib->dot11hTPCEntry.tpc_enable) { + pbuf = set_ie(pbuf, _PWR_CONSTRAINT_IE_, 1, &priv->pshare->rf_ft_var.lpwrc, &fr_len); + pbuf = construct_TPC_report_ie(priv, pbuf, &fr_len); + } +#endif + + + if (OPMODE & WIFI_AP_STATE) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + //ERP infomation. + val8=0; + if (priv->pmib->dot11ErpInfo.protection) + val8 |= BIT(1); + if (priv->pmib->dot11ErpInfo.nonErpStaNum) + val8 |= BIT(0); + pbuf = set_ie(pbuf, _ERPINFO_IE_ , 1 , &val8, (unsigned int *)&fr_len); + } + } + + //EXT supported rates. + if (get_bssrate_set(priv, _EXT_SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len)) + pbuf = set_ie(pbuf, _EXT_SUPPORTEDRATES_IE_ , bssrate_len , pbssrate, (unsigned int *)&fr_len); + + /* + 2008-12-16, For Buffalo WLI_CB_AG54L 54Mbps NIC interoperability issue. + This NIC can not connect to our AP when our AP is set to WPA/TKIP encryption. + This issue can be fixed after move "HT Capability Info" and "Additional HT Info" in front of "WPA" and "WMM". + */ + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && (!is_11b_only)) { + pbuf = set_ie(pbuf, _HT_CAP_, priv->ht_cap_len, (unsigned char *)&priv->ht_cap_buf, (unsigned int *)&fr_len); + pbuf = set_ie(pbuf, _HT_IE_, priv->ht_ie_len, (unsigned char *)&priv->ht_ie_buf, (unsigned int *)&fr_len); + } +// probe + +#ifdef RTK_AC_SUPPORT //for 11ac logo + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + // 41 + { + char tmp[8]; + memset(tmp, 0, 8); + tmp[7] = 0x40; + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 8, tmp, &fr_len); + } + + // 60, 61 + construct_vht_ie(priv, priv->pshare->working_channel); + pbuf = set_ie(pbuf, EID_VHTCapability, priv->vht_cap_len, (unsigned char *)&priv->vht_cap_buf, &fr_len); + pbuf = set_ie(pbuf, EID_VHTOperation, priv->vht_oper_len, (unsigned char *)&priv->vht_oper_buf, &fr_len); + + // 62 + if(priv->pshare->rf_ft_var.lpwrc) { + char tmp[4]; + tmp[1] = tmp[2] = tmp[3] = priv->pshare->rf_ft_var.lpwrc; + tmp[0] = priv->pshare->CurrentChannelBW; // 20, 40, 80 + pbuf = set_ie(pbuf, EID_VHTTxPwrEnvelope, tmp[0]+2, tmp, &fr_len); + } + + //66 + if(priv->pshare->rf_ft_var.opmtest&1) + pbuf = set_ie(pbuf, EID_VHTOperatingMode, 1, (unsigned char *)&(priv->pshare->rf_ft_var.oper_mode_field), &fr_len); + + } +#endif + +#ifdef WIFI_11N_2040_COEXIST + if ((OPMODE & WIFI_AP_STATE) && + (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G)) && + priv->pmib->dot11nConfigEntry.dot11nCoexist && priv->pshare->is_40m_bw) { + unsigned char temp_buf = _2040_COEXIST_SUPPORT_ ; + construct_obss_scan_para_ie(priv); + pbuf = set_ie(pbuf, _OBSS_SCAN_PARA_IE_, priv->obss_scan_para_len, + (unsigned char *)&priv->obss_scan_para_buf, (unsigned int *)&fr_len); +#ifdef HS2_SUPPORT + if (priv->pmib->hs2Entry.interworking_ielen) + { + unsigned char capArray[6]; + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_ | _BSS_TRANSITION_; + if (priv->proxy_arp) + buf32 |= _PROXY_ARP_; + + if ((priv->pmib->hs2Entry.timezone_ielen!=0) && (priv->pmib->hs2Entry.timeadvt_ielen)) + buf32 |= _UTC_TSF_OFFSET_; + + temp_buf32 = cpu_to_le32(buf32); + //capArray[5]=0x40; //WNM notification + capArray[4]=0x0; + memcpy(capArray,(void *)(&temp_buf32),4); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 5, capArray, &fr_len); + //pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, (unsigned int *)&fr_len); + } + else +#endif + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 1, &temp_buf, (unsigned int *)&fr_len); + } +#ifdef HS2_SUPPORT + else + { + if (priv->pmib->hs2Entry.interworking_ielen) + { + unsigned char capArray[6]; + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_ | _BSS_TRANSITION_; + + if (priv->proxy_arp) + buf32 |= _PROXY_ARP_; + + if ((priv->pmib->hs2Entry.timezone_ielen!=0) && (priv->pmib->hs2Entry.timeadvt_ielen)) + buf32 |= _UTC_TSF_OFFSET_; + + temp_buf32 = cpu_to_le32(buf32); + //capArray[5]=0x40; //WNM notification + capArray[4]=0x0; + memcpy(capArray,(void *)(&temp_buf32),4); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 5, capArray, &fr_len); + + //pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, (unsigned int *)&fr_len); + } + } +#endif +#endif + + if (pmib->dot11RsnIE.rsnielen && set_privacy + #if defined(CONFIG_RTL_WAPI_SUPPORT) + &&(pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WAPI_SMS4_) + #endif + ) + { + memcpy(pbuf, pmib->dot11RsnIE.rsnie, pmib->dot11RsnIE.rsnielen); + pbuf += pmib->dot11RsnIE.rsnielen; + fr_len += pmib->dot11RsnIE.rsnielen; + } + +#ifdef WIFI_WMM + //Set WMM Parameter Element + if (QOS_ENABLE && (is_11b_only != 0xf)) + pbuf = set_ie(pbuf, _RSN_IE_1_, _WMM_Para_Element_Length_, GET_WMM_PARA_IE, (unsigned int *)&fr_len); +#endif + + + + + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && (!is_11b_only)) { + /* + 2008-12-16, For Buffalo WLI_CB_AG54L 54Mbps NIC interoperability issue. + This NIC can not connect to our AP when our AP is set to WPA/TKIP encryption. + This issue can be fixed after move "HT Capability Info" and "Additional HT Info" in front of "WPA" and "WMM". + */ + //pbuf = set_ie(pbuf, _HT_CAP_, priv->ht_cap_len, (unsigned char *)&priv->ht_cap_buf, &txinsn.fr_len); + //pbuf = set_ie(pbuf, _HT_IE_, priv->ht_ie_len, (unsigned char *)&priv->ht_ie_buf, &txinsn.fr_len); + pbuf = construct_ht_ie_old_form(priv, pbuf, (unsigned int *)&fr_len); + } + +#ifdef CONFIG_RTK_MESH + if((TRUE == is_11s)) + { + pbuf = set_ie(pbuf, _OFDM_PARAMETER_SET_IE_, mesh_ie_OFDM(priv, meshiearray), meshiearray, &fr_len); + pbuf = set_ie(pbuf, _MESH_ID_IE_, mesh_ie_MeshID(priv, meshiearray, FALSE), meshiearray, &fr_len); + pbuf = set_ie(pbuf, _WLAN_MESH_CAP_IE_, mesh_ie_WLANMeshCAP(priv, meshiearray), meshiearray, &fr_len); + + if(priv->mesh_swchnl_channel) { /*mesh channel switch procedure is on-going*/ + pbuf = set_ie(pbuf, _MESH_CHANNEL_SWITCH_IE_, mesh_ie_MeshChannelSwitch(priv, meshiearray), meshiearray, &fr_len); + pbuf = set_ie(pbuf, _CSA_IE_, mesh_ie_ChannelSwitchAnnoun(priv, meshiearray), meshiearray, &fr_len); + pbuf = set_ie(pbuf, _SECONDARY_CHANNEL_OFFSET_IE_, mesh_ie_SecondaryChannelOffset(priv, meshiearray), meshiearray, &fr_len); + } + } +#endif + + // Realtek proprietary IE + if (priv->pshare->rtk_ie_len) + pbuf = set_ie(pbuf, _RSN_IE_1_, priv->pshare->rtk_ie_len, priv->pshare->rtk_ie_buf, (unsigned int *)&fr_len); + + // Customer proprietary IE + if (priv->pmib->miscEntry.private_ie_len) { + memcpy(pbuf, pmib->miscEntry.private_ie, pmib->miscEntry.private_ie_len); + pbuf += pmib->miscEntry.private_ie_len; + fr_len += pmib->miscEntry.private_ie_len; + } + +#ifdef HS2_SUPPORT + //if support hs2 enable, p2p disable + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.hs2_ielen) + { + //unsigned char p2ptmpie[]={0x50,0x6f,0x9a,0x09,0x02,0x02,0x00,0x00,0x00}; + unsigned char p2ptmpie[]={0x50,0x6f,0x9a,0x09,0x0a,0x01,0x00,0x01}; + pbuf = set_ie(pbuf, 221, sizeof(p2ptmpie), p2ptmpie, &fr_len); + } + //if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.hs2_ielen) + //{ + // pbuf = set_ie(pbuf, _HS2_IE_, priv->pmib->hs2Entry.hs2_ielen, priv->pmib->hs2Entry.hs2_ie, &fr_len); + //} + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.hs2_ielen) + { + pbuf = set_ie(pbuf, _HS2_IE_, priv->pmib->hs2Entry.hs2_ielen, priv->pmib->hs2Entry.hs2_ie, &fr_len); + priv->pmib->hs2Entry.bssload_ie[0] = priv->assoc_num & 0xff; + priv->pmib->hs2Entry.bssload_ie[1] = (priv->assoc_num & 0xff00) >> 8; + priv->pmib->hs2Entry.bssload_ie[2] = priv->channel_utilization; + priv->pmib->hs2Entry.bssload_ie[3] = 0; + priv->pmib->hs2Entry.bssload_ie[4] = 0; + pbuf = set_ie(pbuf, _BSS_LOAD_IE_, 5, priv->pmib->hs2Entry.bssload_ie, &fr_len); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.interworking_ielen) + { + pbuf = set_ie(pbuf, _INTERWORKING_IE_, priv->pmib->hs2Entry.interworking_ielen, priv->pmib->hs2Entry.interworking_ie, &fr_len); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.advt_proto_ielen) + { + pbuf = set_ie(pbuf, _ADVT_PROTO_IE_, priv->pmib->hs2Entry.advt_proto_ielen, priv->pmib->hs2Entry.advt_proto_ie, &fr_len); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.roam_ielen && priv->pmib->hs2Entry.roam_enable) + { + pbuf = set_ie(pbuf, _ROAM_IE_, priv->pmib->hs2Entry.roam_ielen, priv->pmib->hs2Entry.roam_ie, &fr_len); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.timeadvt_ielen) + { + pbuf = set_ie(pbuf, _TIMEADVT_IE_, priv->pmib->hs2Entry.timeadvt_ielen, priv->pmib->hs2Entry.timeadvt_ie, &fr_len); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.MBSSID_ielen) + { + pbuf = set_ie(pbuf, _MUL_BSSID_IE_, priv->pmib->hs2Entry.MBSSID_ielen, priv->pmib->hs2Entry.MBSSID_ie, &fr_len); + } + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->hs2Entry.timezone_ielen) + { + pbuf = set_ie(pbuf, _TIMEZONE_IE_, priv->pmib->hs2Entry.timezone_ielen, priv->pmib->hs2Entry.timezone_ie, &fr_len); + } +#endif + +//#ifdef RTK_AC_SUPPORT +#if 0 + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + construct_vht_ie(priv, priv->pshare->working_channel); + pbuf = set_ie(pbuf, EID_VHTCapability, priv->vht_cap_len, (unsigned char *)&priv->vht_cap_buf, &fr_len); + pbuf = set_ie(pbuf, EID_VHTOperation, priv->vht_oper_len, (unsigned char *)&priv->vht_oper_buf, &fr_len); + // operting mode + { + char tmp[8]; + memset(tmp, 0, 8); + tmp[7] = 0x40; + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 8, tmp, &fr_len); + } + if(priv->pshare->rf_ft_var.opmtest&1) + pbuf = set_ie(pbuf, EID_VHTOperatingMode, 1, (unsigned char *)&(priv->pshare->rf_ft_var.oper_mode_field), &fr_len); + } +#endif + +#ifdef P2P_SUPPORT + if( (P2PMODE == P2P_DEVICE) && (P2P_STATE == P2P_S_LISTEN)) + { + if(pmib->wscEntry.probe_rsp_ielen){ + memcpy(pbuf, pmib->wscEntry.probe_rsp_ie, pmib->wscEntry.probe_rsp_ielen); + pbuf += pmib->wscEntry.probe_rsp_ielen; + fr_len += pmib->wscEntry.probe_rsp_ielen; + } + } + else +#endif +#ifdef WIFI_SIMPLE_CONFIG + { + if (!priv->pshare->rf_ft_var.NDSi_support + && (priv->pmib->dot11StationConfigEntry.dot11AclMode != ACL_allow + || (priv->pmib->dot11StationConfigEntry.dot11AclMode == ACL_allow && priv->pmib->dot11StationConfigEntry.dot11AclNum > 0))) + { + if (pmib->wscEntry.wsc_enable && pmib->wscEntry.probe_rsp_ielen) { + memcpy(pbuf, pmib->wscEntry.probe_rsp_ie, pmib->wscEntry.probe_rsp_ielen); + pbuf += pmib->wscEntry.probe_rsp_ielen; + fr_len += pmib->wscEntry.probe_rsp_ielen; + } + } + } +#endif + +#ifdef P2P_SUPPORT + if( (OPMODE&WIFI_P2P_SUPPORT) && (P2PMODE == P2P_TMP_GO)){ + if(priv->p2pPtr->probe_rps_to_p2p_dev){ + need_include_p2pie = 1; + priv->p2pPtr->probe_rps_to_p2p_dev = 0; + } + } + + if ( ((P2PMODE == P2P_DEVICE) && (P2P_STATE == P2P_S_LISTEN)) + || need_include_p2pie ) + { + if(priv->p2pPtr->p2p_probe_rsp_ie_len){ + memcpy(pbuf, priv->p2pPtr->p2p_probe_rsp_ie, priv->p2pPtr->p2p_probe_rsp_ie_len); + pbuf += priv->p2pPtr->p2p_probe_rsp_ie_len ; + fr_len += priv->p2pPtr->p2p_probe_rsp_ie_len ; + } + } +#endif + + + + SetFrameSubType((phdr), WIFI_PROBERSP); + memcpy((void *)GetAddr2Ptr((phdr)), GET_MY_HWADDR, MACADDRLEN); + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType!=wapiDisable) + { + SAVE_INT_AND_CLI(flags); + priv->wapiCachedBuf = pbuf+2; + wapiSetIE(priv); + pbuf[0] = _EID_WAPI_; + pbuf[1] = priv->wapiCachedLen; + pbuf += priv->wapiCachedLen+2; + fr_len += priv->wapiCachedLen+2; + RESTORE_INT(flags); + } +#endif + +#ifdef P2P_SUPPORT + if( (P2PMODE == P2P_DEVICE) && (P2P_STATE == P2P_S_LISTEN)) { + memcpy((void *)GetAddr3Ptr((phdr)), GET_MY_HWADDR , MACADDRLEN); + } + else +#endif + { + memcpy((void *)GetAddr3Ptr((phdr)), bssid, MACADDRLEN); + } + + return fr_len; +} + + +/** + * @brief issue probe response + * + * - Timestamp \n - Beacon interval \n - Capability \n - SSID \n - Support rate \n - DS Parameter set \n \n + * +-------+-------+----+----+--------+ \n + * | Frame control | DA | SA | BSS ID | \n + * +-------+-------+----+----+--------+ \n + * \n + * +-----------+-----------------+------------+------+--------------+------------------+-----------+ \n + * | Timestamp | Beacon interval | Capability | SSID | Support rate | DS Parameter set | ERP info. | \n + * +-----------+-----------------+------------+------+--------------+------------------+-----------+ \n + * + * \param priv device info. + * \param da address + * \param sid SSID + * \param ssid_len SSID length + * \param set_privacy Use Robust security network + */ +//static ; extern for P2P_SUPPORT +void issue_probersp(struct rtl8192cd_priv *priv, unsigned char *da, + UINT8 *ssid, int ssid_len, int set_privacy, UINT8 is_11b_only) +{ +#ifdef CONFIG_RTK_MESH + issue_probersp_MP(priv, da, ssid, ssid_len, set_privacy, FALSE, is_11b_only); +} + + +void issue_probersp_MP(struct rtl8192cd_priv *priv, unsigned char *da, + UINT8 *ssid, int ssid_len, int set_privacy, UINT8 is_11s, UINT8 is_11b_only) +{ +// UINT8 meshiearray[32]; // mesh IE buffer (Max byte is mesh_ie_MeshID) +#endif + unsigned int z = 0; + unsigned char *hwaddr, *pbuf; + + DECLARE_TXINSN(txinsn); + +#ifdef SDIO_AP_OFFLOAD + if (priv->pshare->offload_function_ctrl) + return; +#endif + +// pmib= GET_MIB(priv); +// bssid = pmib->dot11StationConfigEntry.dot11Bssid; +#ifdef CONFIG_RTK_MESH + txinsn.is_11s = is_11s; +#endif + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + + +#ifdef P2P_SUPPORT // 2013 + /* 2013-0619 ; This means that the P2P Group Owner transmits Probe Response frames using + OFDM, including frames sent in response to Probe Requests received at 11b rates from non 11b-only devices*/ + + if(OPMODE&WIFI_P2P_SUPPORT ){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.pframe = get_mgtbuf_from_poll(priv); + + if (txinsn.pframe == NULL) + goto issue_probersp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_probersp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + for (z = 0; z < PSP_OUI_NUM; z++) { + if (is_11b_only && (da[0] == PSP_OUI[z][0]) && + (da[1] == PSP_OUI[z][1]) && + (da[2] == PSP_OUI[z][2])) { + is_11b_only = 0xf; + printMac(da); + break; + } + } + + +#ifdef HS2_SUPPORT +#ifdef HS2_CLIENT_TEST + printk("issue_Probereq_MP\n"); + if ((priv->pshare->rf_ft_var.swq_dbg == 30) || (priv->pshare->rf_ft_var.swq_dbg == 31)) + { + printk("Probe Request to SSID [Hotspot 2.0]\n"); + strcpy(ssid, "Hotspot 2.0"); + ssid[11] = '\0'; + ssid_len = strlen(ssid); + pbuf = set_ie(pbuf, _SSID_IE_, ssid_len, ssid, &txinsn.fr_len); + } + else if ((priv->pshare->rf_ft_var.swq_dbg == 32) || (priv->pshare->rf_ft_var.swq_dbg == 33) || (priv->pshare->rf_ft_var.swq_dbg == 34) || (priv->pshare->rf_ft_var.swq_dbg == 35) || (priv->pshare->rf_ft_var.swq_dbg == 36) || (priv->pshare->rf_ft_var.swq_dbg == 37) || (priv->pshare->rf_ft_var.swq_dbg == 38) || (priv->pshare->rf_ft_var.swq_dbg == 39)) + { + pbuf = set_ie(pbuf, _SSID_IE_, 0, ssid, &txinsn.fr_len); + } + else +#endif +#endif + +#ifdef CONFIG_RTK_MESH + txinsn.fr_len = fill_probe_rsp_content(priv, txinsn.phdr, txinsn.pframe, ssid, ssid_len, set_privacy, is_11s, is_11b_only); +#else + txinsn.fr_len = fill_probe_rsp_content(priv, txinsn.phdr, txinsn.pframe, ssid, ssid_len, set_privacy, 0, is_11b_only); +#endif + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +issue_probersp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); +} + + +/** + * @brief STA issue prob request + * + * +---------------+-----+------+-----------------+--------------------------+ \n + * | Frame Control | ... | SSID | Supported Rates | Extended Supported Rates | \n + * +---------------+-----+------+-----------------+--------------------------+ \n + * @param priv device + * @param ssid ssid name + * @param ssid_len ssid length + */ +static void issue_probereq(struct rtl8192cd_priv *priv, unsigned char *ssid, int ssid_len, unsigned char *da) +{ +#ifdef CONFIG_RTK_MESH + issue_probereq_MP(priv, ssid, ssid_len, da, FALSE); +} + + +void issue_probereq_MP(struct rtl8192cd_priv *priv, unsigned char *ssid, int ssid_len, unsigned char *da, int is_11s) +{ + UINT8 meshiearray[32]; // mesh IE buffer (Max byte is mesh_ie_MeshID) +#endif + + struct wifi_mib *pmib; + unsigned char *hwaddr, *pbuf; + unsigned char *pbssrate=NULL; + int bssrate_len; + DECLARE_TXINSN(txinsn); + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) + return; +#endif + + +#if 0 //def DFS +#ifdef UNIVERSAL_REPEATER + if(under_apmode_repeater(priv)) + { + unsigned int channel = priv->pmib->dot11RFEntry.dot11channel; + unsigned char issue_ok = 0; + unsigned int tmp_opmode =0; + if(is_DFS_channel(channel)) + { + if((OPMODE & WIFI_ASOC_STATE) && (OPMODE & WIFI_STATION_STATE)) + { + issue_ok = 1; + } + + if(IS_ROOT_INTERFACE(priv)) + { + tmp_opmode = GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.opmode; + + if((tmp_opmode & WIFI_ASOC_STATE) && (tmp_opmode & WIFI_STATION_STATE)) + { + issue_ok = 1; + } + } + + //printk("DFS Channel=%d, issue_probeReq=%d\n", channel, issue_ok); + + if(issue_ok == 0) + return; + } + } +#endif +#endif + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + pmib = GET_MIB(priv); + + hwaddr = pmib->dot11OperationEntry.hwaddr; +#ifdef CONFIG_RTK_MESH + txinsn.is_11s = is_11s; +#endif + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + + if (pbuf == NULL) + goto issue_probereq_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_probereq_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + pbuf = set_ie(pbuf, _SSID_IE_, ssid_len, ssid, &txinsn.fr_len); + + /*fill supported rates*/ + +#ifdef P2P_SUPPORT + if(OPMODE&WIFI_P2P_SUPPORT){ + get_bssrate_set(priv, _SUPPORTED_RATES_NO_CCK_, &pbssrate, &bssrate_len); + }else +#endif + { + get_bssrate_set(priv, _SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len); + } + + + pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_ , bssrate_len , pbssrate, &txinsn.fr_len); + + if (get_bssrate_set(priv, _EXT_SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len)) + pbuf = set_ie(pbuf, _EXT_SUPPORTEDRATES_IE_ , bssrate_len , pbssrate, &txinsn.fr_len); + + +#ifdef RTK_AC_SUPPORT // WDS-VHT support + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + //WDEBUG("construct_vht_ie\n"); + construct_vht_ie(priv, priv->pshare->working_channel); + pbuf = set_ie(pbuf, EID_VHTCapability, priv->vht_cap_len, (unsigned char *)&priv->vht_cap_buf, &txinsn.fr_len); + pbuf = set_ie(pbuf, EID_VHTOperation, priv->vht_oper_len, (unsigned char *)&priv->vht_oper_buf, &txinsn.fr_len); + } +#endif + +#ifdef P2P_SUPPORT + if (OPMODE&WIFI_P2P_SUPPORT) + { /*add wsc ie*/ + if(pmib->wscEntry.probe_req_ielen){ + memcpy(pbuf, pmib->wscEntry.probe_req_ie, pmib->wscEntry.probe_req_ielen); + pbuf += pmib->wscEntry.probe_req_ielen; + txinsn.fr_len += pmib->wscEntry.probe_req_ielen; + } + } + else +#endif +#ifdef WIFI_SIMPLE_CONFIG + { + if (pmib->wscEntry.wsc_enable && pmib->wscEntry.probe_req_ielen) { + memcpy(pbuf, pmib->wscEntry.probe_req_ie, pmib->wscEntry.probe_req_ielen); + pbuf += pmib->wscEntry.probe_req_ielen; + txinsn.fr_len += pmib->wscEntry.probe_req_ielen; + } + } +#endif + +#ifdef HS2_SUPPORT +#ifdef HS2_CLIENT_TEST + if (priv->pshare->rf_ft_var.swq_dbg == 30) + { + // HS2.0 AP does not transmit a probe response frame + // HESSID is wrong. + + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x02,0x50,0x6F,0x9A,0x00,0x00,0x01}; + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 7, tmp, &frlen); + txinsn.fr_len += frlen; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 31) + { + // HS2.0 AP does not transmit a probe response frame + // HESSID is wrong. + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x02,0x00,0x00,0x50,0x6F,0x9A,0x00,0x00,0x01}; + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 9, tmp, &frlen); + txinsn.fr_len += frlen; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 32) + { + // APUT transmits Probe Response Message + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x02,0x00,0x33,0x44,0x55,0x66,0x77}; // HESSID = redir_mac, please refer to next line + + memcpy(&tmp[1], priv->pmib->hs2Entry.redir_mac, 6); + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 7, tmp, &frlen); + txinsn.fr_len += frlen; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 33) + { + // APUT transmits Probe Response Message + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x02,0x00,0x00,0x00,0x33,0x44,0x55,0x66,0x77}; // HESSID = redir_mac, please refer to next line + + memcpy(&tmp[3], priv->pmib->hs2Entry.redir_mac, 6); + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 9, tmp, &frlen); + txinsn.fr_len += frlen; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 34) + { + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x03}; // HESSID is not present + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 1, tmp, &frlen); + txinsn.fr_len += frlen; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 35) + { + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x03,0x00,0x00}; // HESSID is not present + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 3, tmp, &frlen); + txinsn.fr_len += frlen; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 36) + { + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x02,0xff,0xff,0xff,0xff,0xff,0xff}; + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 7, tmp, &frlen); + txinsn.fr_len += frlen; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 37) + { + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x02,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff}; + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 9, tmp, &frlen); + txinsn.fr_len += frlen; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 38) + { + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x0f,0xff,0xff,0xff,0xff,0xff,0xff}; + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 7, tmp, &frlen); + txinsn.fr_len += frlen; + } + else if (priv->pshare->rf_ft_var.swq_dbg == 39) + { + unsigned int temp_buf32, buf32 = _INTERWORKING_SUPPORT_, frlen=0; + unsigned char tmp[]={0x0f,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff}; + + temp_buf32 = cpu_to_le32(buf32); + pbuf = set_ie(pbuf, _EXTENDED_CAP_IE_, 4, &temp_buf32, &frlen); + txinsn.fr_len += frlen; + + frlen = 0; + pbuf = set_ie(pbuf, _INTERWORKING_IE_, 9, tmp, &frlen); + txinsn.fr_len += frlen; + } +#endif +#endif + +#ifdef P2P_SUPPORT + if (OPMODE&WIFI_P2P_SUPPORT) + { + if(priv->p2pPtr->p2p_probe_req_ie_len){ + + memcpy(pbuf, priv->p2pPtr->p2p_probe_req_ie, + priv->p2pPtr->p2p_probe_req_ie_len); + + pbuf += priv->p2pPtr->p2p_probe_req_ie_len ; + txinsn.fr_len += priv->p2pPtr->p2p_probe_req_ie_len ; + + } + + } +#endif + + + +#ifdef CONFIG_RTK_MESH // mesh_profile Configure by WEB in the future, Maybe delete, Preservation before delete + if((TRUE == is_11s) && (1 == GET_MIB(priv)->dot1180211sInfo.mesh_enable) && (TRUE == priv->mesh_profile[0].used) + && (MESH_PEER_LINK_CAP_NUM(priv) > 0)) + { +// ==== modified by GANTOE for site survey 2008/12/25 ==== + if(priv->auto_channel == 0) + pbuf = set_ie(pbuf, _MESH_ID_IE_, 0, "", &txinsn.fr_len); + else + pbuf = set_ie(pbuf, _MESH_ID_IE_, mesh_ie_MeshID(priv, meshiearray, FALSE), meshiearray, &txinsn.fr_len); + pbuf = set_ie(pbuf, _WLAN_MESH_CAP_IE_, mesh_ie_WLANMeshCAP(priv, meshiearray), meshiearray, &txinsn.fr_len); + } +#endif + + SetFrameSubType(txinsn.phdr, WIFI_PROBEREQ); + + if (da) + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); // unicast + else + memset((void *)GetAddr1Ptr((txinsn.phdr)), 0xff, MACADDRLEN); // broadcast + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + //nctu note + // spec define ProbeREQ Address 3 is BSSID or wildcard) (Refer: Draft 1.06, Page 12, 7.2.3, Line 27~28) + memset((void *)GetAddr3Ptr((txinsn.phdr)), 0xff, MACADDRLEN); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +issue_probereq_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); +} + + +#if defined(CLIENT_MODE) && defined(WIFI_11N_2040_COEXIST) +static void issue_coexist_mgt(struct rtl8192cd_priv *priv) +{ + unsigned char *pbuf; + unsigned int len = 0, ch_len=0, i=0; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_coexist_mgt_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_coexist_mgt_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _PUBLIC_CATEGORY_ID_; + pbuf[1] = _2040_COEXIST_ACTION_ID_; + len+=2; + + pbuf[2] = _2040_BSS_COEXIST_IE_; + pbuf[3] = 1; + len+=2; + + if (priv->intolerant_timeout) + pbuf[4] = _20M_BSS_WIDTH_REQ_; + else + pbuf[4] = 0; + len+=1; + + if (priv->bg_ap_timeout) { + pbuf[5] = _2040_Intolerant_ChRpt_IE_; + pbuf[7] = 0; /*set category*/ + for (i=0; i<14; i++) { + if (priv->bg_ap_timeout_ch[i]) { + pbuf[8+ch_len] = i+1;/*set channels*/ + ch_len++; + } + } + pbuf[6] = ch_len+1; + len += (pbuf[6]+2); + } + + txinsn.fr_len = len; + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + DEBUG_INFO("Coexist-mgt sent to AP\n"); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +issue_coexist_mgt_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return; +} +#endif + + +#ifdef WIFI_WMM + +#if 0 +void issue_DELBA(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char TID, unsigned char initiator){ + unsigned char *pbuf; + unsigned short delba_para = 0; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_DELBA_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_DELBA_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _BLOCK_ACK_CATEGORY_ID_; + pbuf[1] = _DELBA_ACTION_ID_; + delba_para = initiator << 11 | TID << 12; // assign buffer size | assign TID | set Immediate Block Ack + pbuf[2] = initiator << 3 | TID << 4; + pbuf[3] = 0; + pbuf[4] = 38;//reason code + pbuf[5] = 0; + + /* set the immediate next seq number of the "TID", as Block Ack Starting Seq*/ + + txinsn.fr_len = _DELBA_Frame_Length; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), pstat->hwaddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + DEBUG_INFO("issue_DELBAreq sent to AID %d, token %d TID %d size %d seq %d\n", + pstat->aid, pstat->dialog_token, TID, max_size, pstat->AC_seq[TID]); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +issue_DELBA_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return; +} +#endif + +void issue_ADDBAreq(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char TID) +{ + unsigned char *pbuf; + unsigned short ba_para = 0; + int max_size; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + +#ifdef CONFIG_IEEE80211W + if (pstat) + txinsn.isPMF = pstat->isPMF; + else + txinsn.isPMF = 0; +#endif + +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_ADDBAreq_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_ADDBAreq_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + if (!(++pstat->dialog_token)) // dialog token set to a non-zero value + pstat->dialog_token++; + + pbuf[0] = _BLOCK_ACK_CATEGORY_ID_; + pbuf[1] = _ADDBA_Req_ACTION_ID_; + pbuf[2] = pstat->dialog_token; + + if (should_restrict_Nrate(priv, pstat)) + max_size = 1; + else { +#ifdef CONFIG_RTL8196B_GW_8M + if (pstat->IOTPeer==HT_IOT_PEER_BROADCOM) + max_size = _ADDBA_Maximum_Buffer_Size_ / 2; + else +#endif + max_size = _ADDBA_Maximum_Buffer_Size_; + } + + ba_para = (max_size<<6) | (TID<<2) | BIT(1); // assign buffer size | assign TID | set Immediate Block Ack + + if(AMSDU_ENABLE >= 2) + ba_para |= BIT(0); // AMSDU + + pbuf[3] = ba_para & 0x00ff; + pbuf[4] = (ba_para & 0xff00) >> 8; + + // set Block Ack Timeout value to zero, to disable the timeout + pbuf[5] = 0; + pbuf[6] = 0; + + // set the immediate next seq number of the "TID", as Block Ack Starting Seq + pbuf[7] = ((pstat->AC_seq[TID] & 0xfff) << 4) & 0x00ff; + pbuf[8] = (((pstat->AC_seq[TID] & 0xfff) << 4) & 0xff00) >> 8; + + txinsn.fr_len = _ADDBA_Req_Frame_Length_; + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); +#ifdef CONFIG_IEEE80211W + if (txinsn.isPMF) + *(unsigned char*)(txinsn.phdr+1) |= BIT(6); // enable privacy +#endif + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), pstat->hwaddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + DEBUG_INFO("ADDBA-req sent to AID %d, token %d TID %d size %d seq %d\n", + pstat->aid, pstat->dialog_token, TID, max_size, pstat->AC_seq[TID]); + /* + panic_printk("ADDBA-req sent to AID %d, token %d TID %d size %d seq %d\n", + pstat->aid, pstat->dialog_token, TID, max_size, pstat->AC_seq[TID]); + */ + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) { + //pstat->ADDBA_ready++; + return; + } + +issue_ADDBAreq_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return; +} + +#ifdef HS2_SUPPORT +#ifdef HS2_CLIENT_TEST + +//issue_GASreq for client test used +int issue_GASreq(struct rtl8192cd_priv *priv, DOT11_HS2_GAS_REQ *gas_req, unsigned short qid) +{ + unsigned char *pbuf; + struct stat_info *pstat; +#if defined(WIFI_WMM) + int ret; +#endif + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + if (qid != 10000) + { + if (qid < 500) + { + if (qid == 0) + gas_req->Reqlen = 0; + else if (qid == 270) + gas_req->Reqlen = 26; + else if (qid == 271) + gas_req->Reqlen = 27; + else if (qid == 272) + gas_req->Reqlen = 15; + else + gas_req->Reqlen = 6; + } + else if(qid == 501) + gas_req->Reqlen = 12; + else if(qid == 502) + gas_req->Reqlen = 12; + else if(qid == 503) + gas_req->Reqlen = 24; + else if(qid == 504) + gas_req->Reqlen = 36; + else if(qid == 505) + gas_req->Reqlen = 44; + else if(qid == 506) + gas_req->Reqlen = 11; + else if(qid == 507) + gas_req->Reqlen = 11; + else if(qid == 508) + gas_req->Reqlen = 25; + else if(qid == 509) + gas_req->Reqlen = 19; + } + else + gas_req->Reqlen = 10; + + if ((OPMODE & WIFI_ASOC_STATE) == 0) + { + //unsigned char tmpmac[]={0x00,0xe0,0x4c,0x09,0x08,0x10}; + //memcpy((GET_MIB(priv))->dot11StationConfigEntry.dot11Bssid, tmpmac, 6); + memcpy((GET_MIB(priv))->dot11StationConfigEntry.dot11Bssid, priv->pmib->hs2Entry.redir_mac, 6); + } + memcpy(gas_req->MACAddr , BSSID, 6); +// gas_req->MACAddr[1] = 0x33; +// gas_req->MACAddr[2] = 0x44; +// gas_req->MACAddr[3] = 0x55; +// gas_req->MACAddr[4] = 0x66; +// gas_req->MACAddr[5] = 0x77; + + pbuf[0] = _PUBLIC_CATEGORY_ID_; + if (qid != 0) + pbuf[1] = _GAS_INIT_REQ_ACTION_ID_; + else + pbuf[1] = _GAS_COMBACK_REQ_ACTION_ID_; + + pbuf[2] = gas_req->Dialog_token; + + if (qid != 0) + { + // refer to Fig. 8-354 in IEEE 802.11 - 2012 + pbuf[3] = 108; // element ID: 108 (Advertisement Protocol IE) + pbuf[4] = 2; // length = 0x 02 + pbuf[5] = 0x00; // Query Response Length Limit + pbuf[6] = 0; // Advertisement Protcol ID = 0x0 (ANQP) + if (priv->pshare->rf_ft_var.swq_dbg == 12) + pbuf[6] = 1; // Advertisement Protcol ID = 0x1 (MIH) + else + pbuf[6] = 0; // Advertisement Protcol ID = 0x0 (ANQP) + pbuf[7] = gas_req->Reqlen & 0x00ff; // Query Request length + pbuf[8] = (gas_req->Reqlen & 0xff00) >> 8; // Query Request length + pbuf[9] = 256 & 0x00ff; // Info ID = 256 ( Query List) + // Query Request fields + // Info ID = 256 ( Query List) + pbuf[10] = (256 & 0xff00) >> 8; + + if (qid != 10000) + { + if (qid < 500) + { + if (qid == 270) + { + pbuf[11] = 2 & 0x00ff; // length + pbuf[12] = (2 & 0xff00) >> 8; + pbuf[13] = 261 & 0x00ff; // InfoID: Roaming list + pbuf[14] = (261 & 0xff00) >> 8; // InfoID: Roaming list + pbuf[15] = 0xdd; + pbuf[16] = 0xdd; + pbuf[17] = 0x06; + pbuf[18] = 0x00; + pbuf[19] = 0x50; + pbuf[20] = 0x6f; + pbuf[21] = 0x9a; + pbuf[22] = 0x11; + pbuf[23] = 0x04; // WAN Metrics + pbuf[24] = 0x00; + pbuf[25] = 0xdd; + pbuf[26] = 0xdd; + pbuf[27] = 0x06; + pbuf[28] = 0x00; + pbuf[29] = 0x50; + pbuf[30] = 0x6f; + pbuf[31] = 0x9a; + pbuf[32] = 0x11; + pbuf[33] = 0x07; // Operating Class Indication + pbuf[34] = 0x00; + txinsn.fr_len += 35; + } + else if (qid == 271) + { + pbuf[11] = 2 & 0x00ff; + pbuf[12] = (2 & 0xff00) >> 8; + pbuf[13] = 261 & 0x00ff; // InfoID: Roaming list + pbuf[14] = (261 & 0xff00) >> 8; // InfoID: Roaming list + pbuf[15] = 0xdd; + pbuf[16] = 0xdd; + pbuf[17] = 0x06; + pbuf[18] = 0x00; + pbuf[19] = 0x50; + pbuf[20] = 0x6f; + pbuf[21] = 0x9a; + pbuf[22] = 0x0b; + pbuf[23] = 0x00; // Subtype = 0 (Reserved) + pbuf[24] = 0x00; + pbuf[25] = 0xdd; + pbuf[26] = 0xdd; + pbuf[27] = 0x07; + pbuf[28] = 0x00; + pbuf[29] = 0x50; + pbuf[30] = 0x6f; + pbuf[31] = 0x9a; + pbuf[32] = 0x11; + pbuf[33] = 0x01; // HS Query List + pbuf[34] = 0x00; + pbuf[35] = 0x07; // Query Operating Class Indication + txinsn.fr_len += 24; + } + else if (qid == 272) { + pbuf[11] = 2& 0x00ff; + pbuf[12] = (2& 0xff00) >> 8; + pbuf[13] = 261 & 0x00ff; // InfoID: Roaming list + pbuf[14] = (261 & 0xff00) >> 8; // InfoID: Roaming list + pbuf[15] = 0xdd; + pbuf[16] = 0xdd; + pbuf[17] = 0x05; + pbuf[18] = 0x00; + pbuf[19] = 0x50; + pbuf[20] = 0x6f; + pbuf[21] = 0x9a; + pbuf[22] = 0x0b; + pbuf[23] = 0x00; // Subtype = 0 (Reserved) + txinsn.fr_len += 36; + } + else + { + // ANQP Query List (Fig. 8-403 in IEEE 802.11-2012) + // length = 2 + pbuf[11] = 2 & 0x00ff; + pbuf[12] = (2 & 0xff00) >> 8; + // ANQP Query ID + pbuf[13] = qid & 0x00ff; + pbuf[14] = (qid & 0xff00) >> 8; + txinsn.fr_len += 15; + } + } + else if(qid == 501) + { + pbuf[9] = 56797 & 0x00ff; + pbuf[10] = (56797 & 0xff00) >> 8; + pbuf[11] = 0x08; + pbuf[12] = 0; + //OI + pbuf[13] =0x50; + pbuf[14] =0x6f; + pbuf[15] =0x9a; + pbuf[16] =0x11; + pbuf[17] =0x1; // HS query list + pbuf[18] =0x0; + //payload + pbuf[19] =0x2; // HS Capability List + pbuf[20] =0x3; // Operator Friendly Name + txinsn.fr_len += 21; + } + else if(qid == 502) + { + pbuf[9] = 56797 & 0x00ff; + pbuf[10] = (56797 & 0xff00) >> 8; + pbuf[11] = 0x08; + pbuf[12] = 0; + //OI + pbuf[13] =0x50; + pbuf[14] =0x6f; + pbuf[15] =0x9a; + pbuf[16] =0x11; + pbuf[17] =0x1; // HS query list + pbuf[18] =0x0; + //payload + pbuf[19] =0x4; + pbuf[20] =0x5; + txinsn.fr_len += 21; + } + else if(qid == 505) + { + pbuf[9] = 56797 & 0x00ff; + pbuf[10] = (56797 & 0xff00) >> 8; + pbuf[11] = 0x08; + pbuf[12] = 0; + pbuf[13] =0x50; + pbuf[14] =0x6f; + pbuf[15] =0x9a; + pbuf[16] =0x11; + pbuf[17] =0x1; // HS query list + pbuf[18] =0x0; + pbuf[19] =0x4; + pbuf[20] =0x5; + pbuf[21] = 56797 & 0x00ff; + pbuf[22] = (56797 & 0xff00) >> 8; + pbuf[23] = 0x06; + pbuf[24] = 0; + pbuf[25] =0x50; + pbuf[26] =0x6f; + pbuf[27] =0x9a; + pbuf[28] =0x0b; + pbuf[29] =0x0; // Reserved + pbuf[30] =0x0; + pbuf[31] = 56797 & 0x00ff; + pbuf[32] = (56797 & 0xff00) >> 8; + pbuf[33] = 21; + pbuf[34] = 0; + pbuf[35] =0x50; + pbuf[36] =0x6f; + pbuf[37] =0x9a; + pbuf[38] =0x11; + pbuf[39] =0x06; // Subtype: NAI Home Realm Query + pbuf[40] =0x0; + pbuf[41] =0x1; + pbuf[42] =0x0; + pbuf[43] =0xc; + pbuf[44] ='e'; + pbuf[45] ='x'; + pbuf[46] ='a'; + pbuf[47] ='m'; + pbuf[48] ='p'; + pbuf[49] ='l'; + pbuf[50] ='e'; + pbuf[51] ='.'; + pbuf[52] ='c'; + pbuf[53] ='o'; + pbuf[54] ='m'; + + txinsn.fr_len += 55; + + } + else if(qid == 503) + { + pbuf[9] = 56797 & 0x00ff; + pbuf[10] = (56797 & 0xff00) >> 8; + pbuf[11] = 21; + pbuf[12] = 0; + //OI + pbuf[13] =0x50; + pbuf[14] =0x6f; + pbuf[15] =0x9a; + //TYPE + pbuf[16] =0x11; + //home realm query + pbuf[17] =0x6; + pbuf[18] =0x0; + //payload + pbuf[19] =0x1; + pbuf[20] =0x0; + pbuf[21] =0xc; + pbuf[22] ='e'; + pbuf[23] ='x'; + pbuf[24] ='a'; + pbuf[25] ='m'; + pbuf[26] ='p'; + pbuf[27] ='l'; + pbuf[28] ='e'; + pbuf[29] ='.'; + pbuf[30] ='c'; + pbuf[31] ='o'; + pbuf[32] ='m'; + txinsn.fr_len += 33; + } + else if (qid == 506) + { + pbuf[9] = 56797 & 0x00ff; + pbuf[10] = (56797 & 0xff00) >> 8; + pbuf[11] = 7; + pbuf[12] = 0; + pbuf[13] =0x50; + pbuf[14] =0x6f; + pbuf[15] =0x9a; + pbuf[16] =0x11; + pbuf[17] =0x6; + pbuf[18] =0x0; + pbuf[19] =0x0; + txinsn.fr_len += 20; + } + else if (qid == 507) + { + pbuf[9] = 56797 & 0x00ff; + pbuf[10] = (56797 & 0xff00) >> 8; + pbuf[11] = 7; + pbuf[12] = 0; + pbuf[13] =0x50; + pbuf[14] =0x6f; + pbuf[15] =0x9a; + pbuf[16] =0x11; + pbuf[17] =0x1; + pbuf[18] =0x0; + pbuf[19] =0x7; + txinsn.fr_len += 20; + } + else if (qid == 504) + { + pbuf[9] = 56797 & 0x00ff; + pbuf[10] = (56797 & 0xff00) >> 8; + pbuf[11] = 32; + pbuf[12] = 0; + pbuf[13] =0x50; + pbuf[14] =0x6f; + pbuf[15] =0x9a; + pbuf[16] =0x11; + pbuf[17] =0x6; + pbuf[18] =0x0; + pbuf[19] =0x2; + pbuf[20] =0x0; + pbuf[21] =0x9; + pbuf[22] ='c'; + pbuf[23] ='i'; + pbuf[24] ='s'; + pbuf[25] ='c'; + pbuf[26] ='o'; + pbuf[27] ='.'; + pbuf[28] ='c'; + pbuf[29] ='o'; + pbuf[30] ='m'; + + pbuf[31] =0x0; + pbuf[32] =0xc; + pbuf[33] ='e'; + pbuf[34] ='x'; + pbuf[35] ='a'; + pbuf[36] ='m'; + pbuf[37] ='p'; + pbuf[38] ='l'; + pbuf[39] ='e'; + pbuf[40] ='4'; + pbuf[41] ='.'; + pbuf[42] ='c'; + pbuf[43] ='o'; + pbuf[44] ='m'; + txinsn.fr_len += 45; + } + else if (qid == 508) + { + pbuf[9] = 56797 & 0x00ff; + pbuf[10] = (56797 & 0xff00) >> 8; + pbuf[11] = 15; + pbuf[12] = 0; + pbuf[13] =0x50; + pbuf[14] =0x6f; + pbuf[15] =0x9a; + pbuf[16] =0x11; + pbuf[17] =0xa; + pbuf[18] =0x0; + pbuf[19] ='1'; + pbuf[20] ='3'; + pbuf[21] ='5'; + pbuf[22] ='7'; + pbuf[23] ='1'; + pbuf[24] ='6'; + pbuf[25] ='1'; + pbuf[26] ='4'; + pbuf[27] ='7'; + pbuf[28] ='5'; + pbuf[29] ='_'; + pbuf[30] ='w'; + pbuf[31] ='i'; + pbuf[32] ='f'; + pbuf[33] ='i'; + + txinsn.fr_len += 34; + } + else if (qid == 509) + { + + pbuf[11] = 4 & 0x00ff; // length + pbuf[12] = (4 & 0xff00) >> 8; + pbuf[13] = 260 & 0x00ff; // InfoID: Network Authentication Type + pbuf[14] = (260 & 0xff00) >> 8; // InfoID: Network Authentication Type + pbuf[15] = 263 & 0x00ff; // InfoID: NAI Realm List + pbuf[16] = (263 & 0xff00) >> 8; // InfoID: NAI Realm List + pbuf[17] = 56797 & 0x00ff; + pbuf[18] = (56797 & 0xff00) >> 8; + pbuf[19] = 0x07; + pbuf[20] = 0; + //OI + pbuf[21] =0x50; + pbuf[22] =0x6f; + pbuf[23] =0x9a; + pbuf[24] =0x11; + pbuf[25] =0x1; // HS query list + pbuf[26] =0x0; + //payload + pbuf[27] =0x8; // OSU Providers List + txinsn.fr_len += 28; + } + } + else + { + pbuf[11] = 6 & 0x00ff; + pbuf[12] = (6 & 0xff00) >> 8; + pbuf[13] = 263 & 0x00ff; + pbuf[14] = (263 & 0xff00) >> 8; + pbuf[15] = 264 & 0x00ff; + pbuf[16] = (264 & 0xff00) >> 8; + pbuf[17] = 268 & 0x00ff; + pbuf[18] = (268 & 0xff00) >> 8; + txinsn.fr_len += 19; + } + } + else + { + txinsn.fr_len += 11; + } + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), gas_req->MACAddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), gas_req->MACAddr, MACADDRLEN); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return SUCCESS; +} +#endif + +int issue_GASrsp(struct rtl8192cd_priv *priv, DOT11_HS2_GAS_RSP *gas_rsp) +{ + unsigned char *pbuf; + struct stat_info *pstat; +#if defined(WIFI_WMM) + int ret; +#endif + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_GASrsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_GASrsp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _PUBLIC_CATEGORY_ID_; + pbuf[1] = gas_rsp->Action; + pbuf[2] = gas_rsp->Dialog_token; + pbuf[3] = gas_rsp->StatusCode & 0x00ff; + pbuf[4] = (gas_rsp->StatusCode & 0xff00) >> 8; + + if (gas_rsp->Action == _GAS_INIT_RSP_ACTION_ID_) + { + pbuf[5] = gas_rsp->Comeback_delay & 0x00ff; + pbuf[6] = (gas_rsp->Comeback_delay & 0xff00) >> 8; + //advertisement protocol element + pbuf[7] = 0x6c; + pbuf[8] = 2; + pbuf[9] = 0x20; + pbuf[10] = 0;//gas_rsp->Advt_proto; + //gas rsp + pbuf[11] = gas_rsp->Rsplen & 0x00ff; + pbuf[12] = (gas_rsp->Rsplen & 0xff00) >> 8; + if (gas_rsp->Rsplen > 0) + memcpy(&pbuf[13], gas_rsp->Rsp, gas_rsp->Rsplen); + + txinsn.fr_len += 13 + gas_rsp->Rsplen; + } + else if (gas_rsp->Action == _GAS_COMBACK_RSP_ACTION_ID_) + { + pbuf[5] = gas_rsp->Rsp_fragment_id; + pbuf[6] = gas_rsp->Comeback_delay & 0x00ff; + pbuf[7] = (gas_rsp->Comeback_delay & 0xff00) >> 8; + //advertisement protocol element + pbuf[8] = 0x6c; + pbuf[9] = 2; + pbuf[10] = 0x20; + pbuf[11] = 0;//gas_rsp->Advt_proto; + //gas rsp + pbuf[12] = gas_rsp->Rsplen & 0x00ff; + pbuf[13] = (gas_rsp->Rsplen & 0xff00) >> 8; + if (gas_rsp->Rsplen > 0) + memcpy(&pbuf[14], gas_rsp->Rsp, gas_rsp->Rsplen); + + txinsn.fr_len += 14 + gas_rsp->Rsplen; + } + else + { + //unknown action + goto issue_GASrsp_fail; + } + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), gas_rsp->MACAddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + pstat = get_stainfo(priv, gas_rsp->MACAddr); + +#if defined(WIFI_WMM) + ret = check_dz_mgmt(priv, pstat, &txinsn); + + if (ret < 0) + goto issue_GASrsp_fail; + else if (ret==1) + return SUCCESS; + else +#endif + { + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return SUCCESS; + } + +issue_GASrsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; +} + +int issue_BSS_TSM_req(struct rtl8192cd_priv *priv, DOT11_HS2_TSM_REQ *tsm_req) +{ + unsigned char *pbuf; + struct stat_info *pstat; +#if defined(WIFI_WMM) + int ret; +#endif + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; +#ifdef CONFIG_IEEE80211W + struct stat_info *psta; + if (!memcmp(tsm_req->MACAddr,"\xff\xff\xff\xff\xff\xff",6)) { + txinsn.isPMF = 1; //????? + } else { + psta = get_stainfo(priv,tsm_req->MACAddr); + if (!psta) { + printk("STA does not exist\n"); + return 0; + } + if (psta) + txinsn.isPMF = psta->isPMF; + else + txinsn.isPMF = 0; + } + //printk("deauth:txinsn.isPMF=%d\n",txinsn.isPMF); +#endif + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_BSS_TxMgmt_req_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_BSS_TxMgmt_req_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _WNM_CATEGORY_ID_; + pbuf[1] = _BSS_TSMREQ_ACTION_ID_; + pbuf[2] = tsm_req->Dialog_token; //token + pbuf[3] = tsm_req->Req_mode; //request mode + pbuf[4] = tsm_req->Disassoc_timer & 0xff; //disassociation timer + pbuf[5] = (tsm_req->Disassoc_timer & 0xff00) >> 8; + pbuf[6] = tsm_req->Validity_intval; //validity interval + if (tsm_req->term_len != 0) + memcpy(&pbuf[7], tsm_req->terminal_dur, 12); + if (tsm_req->url_len != 0) + memcpy(&pbuf[7+tsm_req->term_len], tsm_req->Session_url, tsm_req->url_len); + if (tsm_req->list_len != 0) + memcpy(&pbuf[7+tsm_req->term_len+tsm_req->url_len], tsm_req->Candidate_list, tsm_req->list_len); + + txinsn.fr_len += 7+tsm_req->term_len+tsm_req->url_len+tsm_req->list_len; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); +#ifdef CONFIG_IEEE80211W + if (txinsn.isPMF) + *(unsigned char*)(txinsn.phdr+1) |= BIT(6); // enable privacy +#endif + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), tsm_req->MACAddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + pstat = get_stainfo(priv, tsm_req->MACAddr); + +#if defined(WIFI_WMM) + ret = check_dz_mgmt(priv, pstat, &txinsn); + + if (ret < 0) + goto issue_BSS_TxMgmt_req_fail; + else if (ret==1) + return SUCCESS; + else +#endif + { + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return SUCCESS; + } + +issue_BSS_TxMgmt_req_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; +} + +int issue_DLS_rsp(struct rtl8192cd_priv *priv, unsigned short status, unsigned char *da, unsigned char *dest, unsigned char *src) +{ + unsigned char *pbuf; + struct stat_info *pstat; +#if defined(WIFI_WMM) + int ret; +#endif + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_DLS_rsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_DLS_rsp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _DLS_CATEGORY_ID_; + pbuf[1] = _DLS_RSP_ACTION_ID_; + pbuf[2] = status & 0xff; + pbuf[3] = (status >> 8) & 0xff; //status code + memcpy(&pbuf[4], dest, 6); + memcpy(&pbuf[10], src, 6); + + txinsn.fr_len += 16; + + pstat = get_stainfo(priv, da); + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + +#if defined(WIFI_WMM) + ret = check_dz_mgmt(priv, pstat, &txinsn); + + if (ret < 0) + goto issue_DLS_rsp_fail; + else if (ret==1) + return SUCCESS; + else +#endif + { + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return SUCCESS; + } + +issue_DLS_rsp_fail: + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; +} + +#ifdef HS2_CLIENT_TEST +//issue_TSM Query for client test used +int issue_BSS_TSM_query(struct rtl8192cd_priv *priv, unsigned char *list, unsigned char list_len) +{ + unsigned char *pbuf; + struct stat_info *pstat; +#if defined(WIFI_WMM) + int ret; +#endif + unsigned char tmpda[]={0x00,0x33,0x44,0x055,0x66,0x77}; + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_BSS_TxMgmt_query_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_BSS_TxMgmt_query_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _WNM_CATEGORY_ID_; + pbuf[1] = _WNM_TSMQUERY_ACTION_ID_; + pbuf[2] = 20; //token + pbuf[3] = 18; //request mode + + if (list_len >0 ) + memcpy(&pbuf[4], list, list_len); + txinsn.fr_len += 4 + list_len; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + pstat = get_stainfo(priv, BSSID); + +#if defined(WIFI_WMM) + ret = check_dz_mgmt(priv, pstat, &txinsn); + + if (ret < 0) + goto issue_BSS_TxMgmt_query_fail; + else if (ret==1) + return SUCCESS; + else +#endif + { + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return SUCCESS; + } + +issue_BSS_TxMgmt_query_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; +} + +//issue_TSM response for client test used +int issue_BSS_TSM_rsp(struct rtl8192cd_priv *priv, unsigned char *token, unsigned char *list, unsigned char list_len) +{ + unsigned char *pbuf; + struct stat_info *pstat; +#if defined(WIFI_WMM) + int ret; +#endif + unsigned char tmpda[]={0x00,0x33,0x44,0x055,0x66,0x77}; + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_BSS_TxMgmt_rsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_BSS_TxMgmt_rsp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _WNM_CATEGORY_ID_; + pbuf[1] = _BSS_TSMRSP_ACTION_ID_; + pbuf[2] = *token; //token + pbuf[3] = 0; //request mode + pbuf[4] = 0; + + if (list_len != 0) + memcpy(&pbuf[5], list, list_len); + + txinsn.fr_len += 5+list_len; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + pstat = get_stainfo(priv, BSSID); + +#if defined(WIFI_WMM) + ret = check_dz_mgmt(priv, pstat, &txinsn); + + if (ret < 0) + goto issue_BSS_TxMgmt_rsp_fail; + else if (ret==1) + return SUCCESS; + else +#endif + { + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return SUCCESS; + } + +issue_BSS_TxMgmt_rsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; +} +#endif +#endif + +#if defined(WIFI_WMM) +#ifdef RTK_AC_SUPPORT //for 11ac logo + +void issue_op_mode_notify(struct rtl8192cd_priv *priv, struct stat_info *pstat, char mode) +{ + unsigned char *pbuf; + unsigned short ba_para = 0; + int max_size; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_opm_notification_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_opm_notification_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _VHT_ACTION_CATEGORY_ID_; + pbuf[1] = _VHT_ACTION_OPMNOTIF_ID_; + pbuf[2] = mode; + txinsn.fr_len = _OPMNOTIF_Frame_Length_; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), pstat->hwaddr, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) { + return; + } + +issue_opm_notification_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return; +} + +#endif + +/*------------------------------------------------------------------------------- + Check if packet should be queued +return value: +-1: fail +1: success +0: no queue +--------------------------------------------------------------------------------*/ +#if defined(CONFIG_PCI_HCI) +int check_dz_mgmt(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct tx_insn* txcfg) +{ + if (pstat && ((pstat->state & (WIFI_SLEEP_STATE | WIFI_ASOC_STATE)) == + (WIFI_SLEEP_STATE | WIFI_ASOC_STATE))){ + int ret; + struct tx_insn *ptx_insn; + ptx_insn = (struct tx_insn*)kmalloc(sizeof(struct tx_insn), GFP_ATOMIC); + + if (ptx_insn == NULL){ + printk("%s: not enough memory\n", __FUNCTION__); + return -1; + } + memcpy((void *)ptx_insn, (void *)txcfg, sizeof(struct tx_insn)); + + //printk("%s %d\n",__FUNCTION__,__LINE__); + DEBUG_INFO("h= %d t=%d\n", (pstat->MGT_dz_queue->head), (pstat->MGT_dz_queue->tail)); + ret = enque(priv, &(pstat->MGT_dz_queue->head), &(pstat->MGT_dz_queue->tail), + (unsigned long)(pstat->MGT_dz_queue->ptx_insn), NUM_DZ_MGT_QUEUE, (void *)ptx_insn); + + if (ret == FALSE) { + kfree(ptx_insn); + DEBUG_ERR("MGT_dz_queue full!\n"); + return -1; + } + + return 1; // success + }else{ + return 0; // no queue + } +} +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +static int _check_dz_mgmt(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct tx_insn* txcfg) +{ + if (pstat && ((pstat->state & (WIFI_SLEEP_STATE | WIFI_ASOC_STATE)) == + (WIFI_SLEEP_STATE | WIFI_ASOC_STATE))) + { + if (update_txinsn_stage1(priv, txcfg) == FALSE) + return -1; + + txcfg->next_txpath = TXPATH_FIRETX; + if (rtw_xmit_enqueue(priv, txcfg) == FALSE) { + return -1; + } + + return 1; // success + } + + return 0; // no queue +} + +int check_dz_mgmt(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct tx_insn* txcfg) +{ + int res; + + local_bh_disable(); + res = _check_dz_mgmt(priv, pstat, txcfg); + local_bh_enable(); + + return res; +} +#endif +#endif + +#ifdef CONFIG_IEEE80211W +void stop_sa_query(struct stat_info *pstat) +{ + PMFDEBUG("RX 11W_SA_Rsp , stop send sa query again\n"); + pstat->sa_query_count = 0; + if (timer_pending(&pstat->SA_timer)) + del_timer(&pstat->SA_timer); +} + + +int check_sa_query_timeout(struct stat_info *pstat) +{ + if (pstat->sa_query_end <= jiffies) { + PMFDEBUG("sa query time out\n"); + pstat->sa_query_timed_out = 1; + pstat->sa_query_count = 0; + if (timer_pending(&pstat->SA_timer)) + del_timer(&pstat->SA_timer); + return 1; + } + return 0; +} + +void rtl8192cd_sa_query_timer(unsigned long task_priv) +{ + struct stat_info *pstat = (struct stat_info *)task_priv; + struct rtl8192cd_priv *priv = NULL; + struct aid_obj *aidobj; + + if (!pstat) + return ; + + aidobj = container_of(pstat, struct aid_obj, station); + priv = aidobj->priv; + + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (pstat->sa_query_count > 0 && check_sa_query_timeout(pstat)) { + PMFDEBUG("check_sa_query_timeout\n"); + return; + } + if (pstat->sa_query_count < SA_QUERY_MAX_NUM) { + PMFDEBUG("re Send sa query\n"); + pstat->sa_query_count++; + issue_SA_Query_Req(priv->dev,pstat->hwaddr); + } + mod_timer(&pstat->SA_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(SA_QUERY_RETRY_TO)); +} + +int issue_SA_Query_Req(struct net_device *dev, unsigned char *da) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + + struct stat_info *pstat; + unsigned char *pbuf; + int ret; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.fixed_rate = 1; + + pstat = get_stainfo(priv, da); + + if (pstat == NULL) { + PMFDEBUG("issue_SA_Query_Req_fail\n"); + goto issue_SA_Query_Req_fail; + } + + txinsn.isPMF = pstat->isPMF; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_SA_Query_Req_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_SA_Query_Req_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _SA_QUERY_CATEGORY_ID_; + pbuf[1] = _SA_QUERY_REQ_ACTION_ID_; + + get_random_bytes(&pstat->SA_TID[pstat->sa_query_count], sizeof(unsigned short)); + + pbuf[2] = pstat->SA_TID[pstat->sa_query_count] & 0xff; + pbuf[3] = (pstat->SA_TID[pstat->sa_query_count] & 0xff00) >> 8; +#ifdef CONFIG_IEEE80211W_AP_DEBUG + panic_printk("DA[%02x%02x%02x:%02x%02x%02x] STA_TID=[%02x%02x]\n", + da[0],da[1],da[2],da[3],da[4],da[5],pbuf[2], pbuf[3]); +#endif + txinsn.fr_len = 4; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + if (txinsn.isPMF) + *(unsigned char*)(txinsn.phdr+1) |= BIT(6); // enable privacy + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + txinsn.pstat = pstat; + +#if defined(WIFI_WMM) + ret = check_dz_mgmt(priv, pstat, &txinsn); + if (ret < 0) { + PMFDEBUG("issue_SA_Query_Req_fail\n"); + goto issue_SA_Query_Req_fail; + } else if (ret==1) { + PMFDEBUG("sta go to sleep... Q it\n"); + return SUCCESS; + } + else +#endif + { + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) { + PMFDEBUG("SUCCESS!!\n"); + return SUCCESS; + } + } + +issue_SA_Query_Req_fail: + + PMFDEBUG("issue_SA_Query_Req_fail\n"); + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; +} + + +int issue_SA_Query_Rsp(struct net_device *dev, unsigned char *da, unsigned char *trans_id) +{ + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + struct stat_info *pstat; + unsigned char *pbuf; + int ret; + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.fixed_rate = 1; + + pstat = get_stainfo(priv, da); + + if (pstat == NULL) + goto issue_SA_Query_Rsp_fail; + + txinsn.isPMF = pstat->isPMF; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_SA_Query_Rsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_SA_Query_Rsp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _SA_QUERY_CATEGORY_ID_; + pbuf[1] = _SA_QUERY_RSP_ACTION_ID_; + memcpy(pbuf+2,trans_id, 2); +#ifdef CONFIG_IEEE80211W_CLI_DEBUG + panic_printk("TID= %02x%02x\n", pbuf[2], pbuf[3]); +#endif + + txinsn.fr_len = 4; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); + + if (txinsn.isPMF) + *(unsigned char*)(txinsn.phdr+1) |= BIT(6); // enable privacy + + PMFDEBUG("\n"); + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); +#ifdef CONFIG_IEEE80211W_AP_DEBUG + panic_printk("DA[%02x%02x%02x:%02x%02x%02x]\n",da[0],da[1],da[2],da[3],da[4],da[5]); +#endif + + txinsn.pstat = pstat; + +#if defined(WIFI_WMM) + ret = check_dz_mgmt(priv, pstat, &txinsn); + if (ret < 0) + goto issue_SA_Query_Rsp_fail; + else if (ret==1) { + return SUCCESS; + } + else +#endif + { + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return SUCCESS; + } + +issue_SA_Query_Rsp_fail: + PMFDEBUG("issue_SA_Query_Rsp_fail\n"); + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + + return FAIL; +} +#endif + +int issue_ADDBArsp(struct rtl8192cd_priv *priv, unsigned char *da, unsigned char dialog_token, + unsigned char TID, unsigned short status_code, unsigned short timeout) +{ + unsigned char *pbuf; + unsigned short ba_para = 0; + struct stat_info *pstat; + int max_size; +#if defined(WIFI_WMM) + int ret; +#endif + + DECLARE_TXINSN(txinsn); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto issue_ADDBArsp_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto issue_ADDBArsp_fail; + + memset((void *)(txinsn.phdr), 0, sizeof(struct wlan_hdr)); + + pbuf[0] = _BLOCK_ACK_CATEGORY_ID_; + pbuf[1] = _ADDBA_Rsp_ACTION_ID_; + pbuf[2] = dialog_token; + pbuf[3] = status_code & 0x00ff; + pbuf[4] = (status_code & 0xff00) >> 8; + + pstat = get_stainfo(priv, da); + +#ifdef CONFIG_IEEE80211W + if (pstat) + txinsn.isPMF = pstat->isPMF; + else + txinsn.isPMF = 0; + //printk("deauth:txinsn.isPMF=%d\n",txinsn.isPMF); +#endif + if (pstat && should_restrict_Nrate(priv, pstat)) + max_size = 1; + else { +#ifdef CONFIG_RTL8196B_GW_8M + if (pstat->IOTPeer==HT_IOT_PEER_BROADCOM) + max_size = _ADDBA_Maximum_Buffer_Size_ / 2; + else +#endif + max_size = _ADDBA_Maximum_Buffer_Size_; + } + + ba_para = (max_size<<6) | (TID<<2) | BIT(1); // assign buffer size | assign TID | set Immediate Block Ack + + if(AMSDU_ENABLE >= 2) + ba_para |= BIT(0); + +#ifdef RTK_AC_SUPPORT //for 11ac logo + if((AC_SIGMA_MODE == AC_SIGMA_APUT) && (AMSDU_ENABLE >= 1)) + ba_para |= BIT(0); +#endif + + pbuf[5] = ba_para & 0x00ff; + pbuf[6] = (ba_para & 0xff00) >> 8; + pbuf[7] = timeout & 0x00ff; + pbuf[8] = (timeout & 0xff00) >> 8; + + txinsn.fr_len += _ADDBA_Rsp_Frame_Length_; + + SetFrameSubType((txinsn.phdr), WIFI_WMM_ACTION); +#ifdef CONFIG_IEEE80211W + if (txinsn.isPMF) + *(unsigned char*)(txinsn.phdr+1) |= BIT(6); // enable privacy +#endif + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + + DEBUG_INFO("ADDBA-rsp sent to AID %d, token %d TID %d size %d status %d\n", + get_stainfo(priv, da)->aid, dialog_token, TID, max_size, status_code); +#if defined(WIFI_WMM) + ret = check_dz_mgmt(priv, pstat, &txinsn); + + if (ret < 0) + goto issue_ADDBArsp_fail; + else if (ret==1) + return SUCCESS; + else +#endif + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return SUCCESS; + +issue_ADDBArsp_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return FAIL; +} +#endif + + +#ifdef RTK_WOW +void issue_rtk_wow(struct rtl8192cd_priv *priv, unsigned char *da) +{ + unsigned char *pbuf; + unsigned int i; + DECLARE_TXINSN(txinsn); + + if (!(OPMODE & WIFI_AP_STATE)) { + DEBUG_WARN("rtk_wake_up pkt should be sent in AP mode!!\n"); + return; + } + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto send_rtk_wake_up_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto send_rtk_wake_up_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + SetFrameSubType(txinsn.phdr, WIFI_DATA); + SetFrDs(txinsn.phdr); + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + + // sync stream + memset((void *)pbuf, 0xff, MACADDRLEN); + pbuf += MACADDRLEN; + txinsn.fr_len += MACADDRLEN; + + for(i=0; i<16; i++) { + memcpy((void *)pbuf, da, MACADDRLEN); + pbuf += MACADDRLEN; + txinsn.fr_len += MACADDRLEN; + } + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) { + DEBUG_INFO("RTK wake up pkt sent\n"); + return; + } + else { + DEBUG_ERR("Fail to send RTK wake up pkt\n"); + } + +send_rtk_wake_up_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); +} +#endif + + +#ifdef CONFIG_RTL_92D_SUPPORT +int clnt_ss_check_band(struct rtl8192cd_priv *priv, unsigned int channel) +{ +#ifdef CLIENT_MODE + if (OPMODE & (WIFI_STATION_STATE|WIFI_ADHOC_STATE)) { + if (priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY) { + if (channel > 14 && priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G){ + //printk("change to 5G %d\n", channel); + // stop BB + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0xf); + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_5G; + priv->pshare->iqk_5g_done = 0; + //priv->pmib->dot11BssType.net_work_type = (WIRELESS_11A|WIRELESS_11N); + UpdateBBRFVal8192DE(priv); + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0); + return 1; + } + + if (channel <= 14 && priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G){ + //printk("change to 2G %d\n", channel); + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0xf); + priv->pmib->dot11RFEntry.phyBandSelect = PHY_BAND_2G; + priv->pshare->iqk_2g_done = 0; + //priv->pmib->dot11BssType.net_work_type = (WIRELESS_11B|WIRELESS_11G|WIRELESS_11N); + //PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0); + UpdateBBRFVal8192DE(priv); + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0); + return 1; + } + } + } +#endif + return 0; +} +#endif + + +/** + * @brief Process Site Survey + * + * set site survery, reauth. , reassoc, idle_timer and proces Site survey \n + * PS: ss_timer is site survey timer \n + */ +void start_clnt_ss(struct rtl8192cd_priv *priv) +{ + unsigned long flags; +#ifdef SUPPORT_MULTI_PROFILE + int j; +#endif + +#ifdef WIFI_WPAS_CLI + printk("acli: start_ss_t ss_req:%d scanning:%d is_root:%d \n", + priv->ss_req_ongoing, priv->pshare->bScanInProcess, IS_ROOT_INTERFACE(priv)); +#endif + + if (timer_pending(&priv->ss_timer)) + del_timer(&priv->ss_timer); +#ifdef CLIENT_MODE + if (PENDING_REAUTH_TIMER) + DELETE_REAUTH_TIMER; + if (PENDING_REASSOC_TIMER) + DELETE_REASSOC_TIMER; + if (timer_pending(&priv->idle_timer)) + del_timer(&priv->idle_timer); +#endif + +#ifdef RTK_NL80211 + if( priv->pshare->rtk_remain_on_channel ) { + NDEBUG3("deny scan by rtk_remain_on_channel\n"); + return; + } +#endif + +#ifdef P2P_SUPPORT + if( (OPMODE & WIFI_P2P_SUPPORT)&& (P2PMODE == P2P_DEVICE)&&(P2P_STATE == P2P_S_LISTEN)){ + P2P_DEBUG("p2p device listen mode don't SS!!\n"); + return; + } +#endif + +#ifdef SDIO_AP_OFFLOAD + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_SITE_SURVEY); +#endif + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + priv->pshare->bScanInProcess = TRUE; +#endif + + OPMODE_VAL(OPMODE & (~WIFI_SITE_MONITOR)); + + SAVE_INT_AND_CLI(flags); +#if defined(SMART_REPEATER_MODE) && !defined(RTK_NL80211) + if (priv->ss_req_ongoing == SSFROM_REPEATER_VXD){ +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(priv->pmib->dot11StationConfigEntry.sc_enabled == 0){ + if(get_ss_level(priv) > SS_LV_WSTA){ + priv->site_survey_times = SS_COUNT-2; + }else { + priv->site_survey_times = SS_COUNT-1; + } + }else{ + priv->site_survey_times = 0; + } +#else + if(get_ss_level(priv) > SS_LV_WSTA){ + priv->site_survey_times = SS_COUNT-2; + } + else{ + priv->site_survey_times = SS_COUNT-1; + } +#endif + } else +#endif + { + priv->site_survey_times = 0; //normal case ss SS_COUNT times + } + +#ifndef CONFIG_POWER_SAVE + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | STOP_BCN); //when start ss, disable beacon +#endif + priv->site_survey->ss_channel = priv->available_chnl[0]; + +#if defined(CONFIG_RTL_92D_SUPPORT) && !defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN_D) + if ((GET_CHIP_VER(priv) == VERSION_8192D) && priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY) { + clnt_ss_check_band(priv, priv->site_survey->ss_channel); + } +#endif + + //let vxd can do ss under 5G +#ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS && is_DFS_channel(priv->site_survey->ss_channel)) + priv->pmib->dot11DFSEntry.disable_tx = 1; + else + priv->pmib->dot11DFSEntry.disable_tx = 0; +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv) || + (IS_VXD_INTERFACE(priv) && !GET_ROOT(priv)->pmib->dot11DFSEntry.CAC_ss_counter )) +#endif +#endif + { + + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_10) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_10; + else if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_5; + else + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(!rtk_sc_is_channel_fixed(priv)) +#endif + { + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->site_survey->ss_channel, priv->pshare->offset_2nd_chan); + } + +#if defined(RTK_NL80211) + //by brian, trigger channel load evaluation after channel switched + start_bbp_ch_load(priv, (45*1000)/4); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) && !defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN_D) + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11RFEntry.macPhyMode == SINGLEMAC_SINGLEPHY)) + PHY_IQCalibrate(priv); +#endif + +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv) && priv->pmib->wscEntry.wsc_enable) + GET_ROOT(priv)->pmib->miscEntry.func_off = 1; +#endif + } +#ifdef DFS + if (GET_ROOT(priv)->pmib->dot11DFSEntry.CAC_ss_counter){ + GET_ROOT(priv)->pmib->dot11DFSEntry.CAC_ss_counter--; + } +#endif + + priv->site_survey->count = 0; + priv->site_survey->hidden_ap_found = 0; + memset((void *)priv->site_survey->bss, 0, sizeof(struct bss_desc)*MAX_BSS_NUM); + +#ifdef WIFI_SIMPLE_CONFIG + if (priv->ss_req_ongoing == 2) + memset((void *)priv->site_survey->wscie, 0, sizeof(struct wps_ie_info)*MAX_BSS_NUM); +#endif + +#if defined(WIFI_WPAS) || defined(RTK_NL80211) //_Eric ?? //eric-sync ?? + if (priv->ss_req_ongoing == 2) { + memset((void *)priv->site_survey->wpa_ie, 0, sizeof(struct wpa_ie_info)*MAX_BSS_NUM); + memset((void *)priv->site_survey->rsn_ie, 0, sizeof(struct rsn_ie_info)*MAX_BSS_NUM); + } +#endif + +#if defined(TESTCHIP_SUPPORT) && defined(CONFIG_RTL_92C_SUPPORT) + if(IS_TEST_CHIP(priv)) + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) | DIS_TSF_UPDATE); + else +#endif + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) | DIS_TSF_UPDATE_N); + +#if defined(CLIENT_MODE) +#if defined(TESTCHIP_SUPPORT) && defined(CONFIG_RTL_92C_SUPPORT) + if( IS_TEST_CHIP(priv) ) { + if ((OPMODE & WIFI_STATION_STATE) || (OPMODE & WIFI_ADHOC_STATE)) + RTL_W32(RCR, RTL_R32(RCR) & ~RCR_CBSSID); + } else +#endif + { + RTL_W32(RCR, RTL_R32(RCR) & ~RCR_CBSSID_ADHOC); + } +#endif + +#ifdef CONFIG_POWER_SAVE + RTL_W16(0x454 , RTL_R16(0x454) | (BIT(6)|BIT(3))); + RTL_W16(0x100 , RTL_R16(0x100) & ~BIT(8)); +#endif + DIG_for_site_survey(priv, TRUE); +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + if (priv->pshare->DNC_on){ + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); + } + } +#endif + OPMODE_VAL(OPMODE | WIFI_SITE_MONITOR); + RESTORE_INT(flags); +#ifdef CONFIG_RTL_NEW_AUTOCH + if (priv->auto_channel == 1) { + reset_FA_reg(priv); + + if (OPMODE & WIFI_AP_STATE) + RTL_W32(RXERR_RPT, RXERR_RPT_RST); + } +#endif + + + + + if( (priv->site_survey->hidden_ap_found == HIDE_AP_FOUND_DO_ACTIVE_SSAN ) || + !is_passive_channel(priv, priv->pmib->dot11StationConfigEntry.dot11RegDomain, priv->site_survey->ss_channel)) + { + + #ifdef CONFIG_RTK_MESH + // GANTOE for site survey 2008/12/25 ==== + if(GET_MIB(priv)->dot1180211sInfo.mesh_enable) + issue_probereq_MP(priv, NULL, 0, NULL, TRUE); + else + #endif + { + /*no assigned SSID*/ + if (priv->ss_ssidlen == 0){ + + #ifdef P2P_SUPPORT + if( OPMODE&WIFI_P2P_SUPPORT && + ((P2PMODE==P2P_DEVICE)||(P2PMODE==P2P_CLIENT)) ){ + //P2P_DEBUG("p2p scan (chann:%d)\n",priv->site_survey->ss_channel); + issue_probereq(priv, "DIRECT-", 7, NULL); + }else + #endif + { + //STADEBUG("issue_probereq no assigned SSID\n"); + issue_probereq(priv, NULL, 0, NULL); + } + + }else{ /*has assigned SSID*/ + #ifdef SUPPORT_MULTI_PROFILE /*per channel tx multi probe_req by profile_num*/ + if (priv->pmib->ap_profile.enable_profile && priv->pmib->ap_profile.profile_num > 0) { + for(j=0;jpmib->ap_profile.profile_num;j++) { + STADEBUG("issue_probereq,ssid[%s],ch=[%d]\n",priv->pmib->ap_profile.profile[j].ssid,priv->site_survey->ss_channel); + issue_probereq(priv, priv->pmib->ap_profile.profile[j].ssid, strlen(priv->pmib->ap_profile.profile[j].ssid), NULL); + } + } + else + #endif + { + STADEBUG("issue_probereq,ssid[%s],ch[%d]\n",priv->ss_ssid,priv->site_survey->ss_channel); + issue_probereq(priv, priv->ss_ssid, priv->ss_ssidlen, NULL); + } + + } + } + } + + +#ifdef CONFIG_RTK_MESH + //GANTOE for site survey 2008/12/25 ==== + if(priv->auto_channel & 0x30) + { + SET_PSEUDO_RANDOM_NUMBER(flags); + flags %= SS_RAND_DEFER; + } else + flags=0; +#endif + + /*how long stady on current channel -start*/ + + //if (should_passive_scan(priv))// replaced by is_passive_channel + if(is_passive_channel(priv, priv->pmib->dot11StationConfigEntry.dot11RegDomain, priv->site_survey->ss_channel)) + { + if(priv->pmib->miscEntry.passive_ss_int) { + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.passive_ss_int) + #ifdef CONFIG_RTK_MESH //GANTOE for site survey 2008/12/25 + + ( flags ) // for the deafness problem + #endif + ); + } else { + mod_timer(&priv->ss_timer, jiffies + SS_PSSV_TO + #ifdef CONFIG_RTK_MESH //GANTOE for site survey 2008/12/25 + + ( flags ) // for the deafness problem + #endif + ); + } + }else +#ifdef P2P_SUPPORT + if(OPMODE&WIFI_P2P_SUPPORT && P2P_STATE == P2P_S_SEARCH){ + /*search phase (only 1,6,11) use 120ms*/ + //P2P_DEBUG("%dms\n",P2P_SEARCH_TIME_V); + mod_timer(&priv->ss_timer, jiffies + P2P_SEARCH_TIME); + }else +#endif + { +#ifdef CONFIG_RTL_NEW_AUTOCH + if (priv->auto_channel == 1){ + mod_timer(&priv->ss_timer, jiffies + SS_AUTO_CHNL_TO +#ifdef CONFIG_RTK_MESH //GANTOE for site survey 2008/12/25 + + ( flags ) // for the deafness problem +#endif + ); + }else +#endif + { + mod_timer(&priv->ss_timer, jiffies + SS_TO + #ifdef CONFIG_RTK_MESH //GANTOE for site survey 2008/12/25 + + ( flags ) // for the deafness problem + #endif + ); + } + + } + /*how long stady on current channel -end*/ + + +} + +static void ProfileSort (struct rtl8192cd_priv *priv, int CompareType , void *base, int nel, int width) +{ + int wgap, i, j, k; + unsigned char tmp; + + if ((nel > 1) && (width > 0)) { + //assert( nel <= ((size_t)(-1)) / width ); /* check for overflow */ + wgap = 0; + do { + wgap = 3 * wgap + 1; + } while (wgap < (nel-1)/3); + + /* From the above, we know that either wgap == 1 < nel or */ + /* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap < nel. */ + + wgap *= width; /* So this can not overflow if wnel doesn't. */ + nel *= width; /* Convert nel to 'wnel' */ + do { + i = wgap; + do { + j = i; + do { + register unsigned char *a; + register unsigned char *b; + + j -= wgap; + a = (unsigned char *)(j + ((char *)base)); + b = a + wgap; + if ( compareTpyeByProfile(priv,a, b,CompareType) <= 0 ) { + break; + } + k = width; + do { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } while ( --k ); + } while (j >= wgap); + i += width; + } while (i < nel); + wgap = (wgap - width)/3; + } while (wgap); + } +} + + +static void qsort (void *base, int nel, int width, + int (*comp)(const void *, const void *)) +{ + int wgap, i, j, k; + unsigned char tmp; + + if ((nel > 1) && (width > 0)) { + //assert( nel <= ((size_t)(-1)) / width ); /* check for overflow */ + wgap = 0; + do { + wgap = 3 * wgap + 1; + } while (wgap < (nel-1)/3); + /* From the above, we know that either wgap == 1 < nel or */ + /* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap < nel. */ + wgap *= width; /* So this can not overflow if wnel doesn't. */ + nel *= width; /* Convert nel to 'wnel' */ + do { + i = wgap; + do { + j = i; + do { + register unsigned char *a; + register unsigned char *b; + + j -= wgap; + a = (unsigned char *)(j + ((char *)base)); + b = a + wgap; + if ( (*comp)(a, b) <= 0 ) { + break; + } + k = width; + do { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } while ( --k ); + } while (j >= wgap); + i += width; + } while (i < nel); + wgap = (wgap - width)/3; + } while (wgap); + } +} + + +static int get_profile_index(struct rtl8192cd_priv *priv ,char* SSID2Search) +{ + int idx=0; + int len1=0; + int len2=0; + len1 = strlen(SSID2Search); + + + for(idx=0 ; idx < priv->pmib->ap_profile.profile_num ; idx++){ + len2 = strlen(priv->pmib->ap_profile.profile[idx].ssid); + if(len1==len2){ + if(!strcmp(priv->pmib->ap_profile.profile[idx].ssid,SSID2Search)){ + return idx; + } + } + } + return -1; + +} +static int compareTpyeByProfile(struct rtl8192cd_priv *priv , const void *entry1, const void *entry2 , int CompareType) +{ + int result1=0; + int result2=0; + switch(CompareType){ + case COMPARE_BSS: + result1=get_profile_index(priv,((struct bss_desc *)entry1)->ssid); + result2=get_profile_index(priv,((struct bss_desc *)entry2)->ssid); + break; + case COMPARE_WSCIE: + result1=get_profile_index(priv,((struct wps_ie_info *)entry1)->ssid); + result2=get_profile_index(priv,((struct wps_ie_info *)entry2)->ssid); + break; +#ifdef WIFI_WPAS + case COMPARE_WPAIE: + result1=get_profile_index(priv,((struct wpa_ie_info *)entry1)->ssid); + result2=get_profile_index(priv,((struct wpa_ie_info *)entry2)->ssid); + break; + case COMPARE_RSNIE: + result1=get_profile_index(priv,((struct rsn_ie_info *)entry1)->ssid); + result2=get_profile_index(priv,((struct rsn_ie_info *)entry2)->ssid); + break; +#endif + default: + STADEBUG("unknow, check!!!\n\n"); + } + + /*result more small then list at more front*/ + if ( result1 < result2 ) + return -1; + + if ( result1 > result2 ) + return 1; + + return 0; + +} + +static int compareBSS(const void *entry1, const void *entry2) +{ + if (((struct bss_desc *)entry1)->rssi > ((struct bss_desc *)entry2)->rssi) + return -1; + + if (((struct bss_desc *)entry1)->rssi < ((struct bss_desc *)entry2)->rssi) + return 1; + + return 0; +} + + +#ifdef WIFI_SIMPLE_CONFIG +static int compareWpsIE(const void *entry1, const void *entry2) +{ + if (((struct wps_ie_info *)entry1)->rssi > ((struct wps_ie_info *)entry2)->rssi) + return -1; + + if (((struct wps_ie_info *)entry1)->rssi < ((struct wps_ie_info *)entry2)->rssi) + return 1; + + return 0; +} +#endif + +#if defined(WIFI_WPAS) || defined(RTK_NL80211) +static int compareWpaIE(const void *entry1, const void *entry2) +{ + if (((struct wpa_ie_info *)entry1)->rssi > ((struct wpa_ie_info *)entry2)->rssi) + return -1; + + if (((struct wpa_ie_info *)entry1)->rssi < ((struct wpa_ie_info *)entry2)->rssi) + return 1; + + return 0; +} + +static int compareRsnIE(const void *entry1, const void *entry2) +{ + if (((struct rsn_ie_info *)entry1)->rssi > ((struct rsn_ie_info *)entry2)->rssi) + return -1; + + if (((struct rsn_ie_info *)entry1)->rssi < ((struct rsn_ie_info *)entry2)->rssi) + return 1; + + return 0; +} +#endif + +static void debug_print_bss(struct rtl8192cd_priv *priv) +{ + STADEBUG("Got ssid count %d\n", priv->site_survey->count); +#if 0 + int i; + + panic_printk("Got ssid count %d\n", priv->site_survey->count); + panic_printk("SSID BSSID ch prd cap bsc oper ss sq bd 40m\n"); + for(i=0; isite_survey->count; i++) + { + char tmpbuf[33]; + UINT8 *mac = priv->site_survey->bss[i].bssid; + + memcpy(tmpbuf, priv->site_survey->bss[i].ssid, priv->site_survey->bss[i].ssidlen); + if (priv->site_survey->bss[i].ssidlen < 20) { + memset(tmpbuf+priv->site_survey->bss[i].ssidlen, ' ', 20-priv->site_survey->bss[i].ssidlen); + tmpbuf[20] = '\0'; + } + else + tmpbuf[priv->site_survey->bss[i].ssidlen] = '\0'; + + panic_printk("%s %02x%02x%02x%02x%02x%02x %2d %4d %04x %04x %04x %02x %02x %02x %3d\n", + tmpbuf,mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],priv->site_survey->bss[i].channel, + priv->site_survey->bss[i].beacon_prd,priv->site_survey->bss[i].capability, + (unsigned short)priv->site_survey->bss[i].basicrate, + (unsigned short)priv->site_survey->bss[i].supportrate, + priv->site_survey->bss[i].rssi,priv->site_survey->bss[i].sq, + priv->site_survey->bss[i].network, + ((priv->site_survey->bss[i].t_stamp[1] & BIT(1)) ? 1 : 0) + ); + } + panic_printk("\n\n"); +#endif +} + + +void rtl8192cd_ss_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + int idx, loop_finish=0; + int AUTOCH_SS_COUNT=SS_COUNT;//AUTOCH_SS_SPEEDUP + int i; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif +#ifdef SUPPORT_MULTI_PROFILE + int jdx; +#endif + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + +#if (defined( UNIVERSAL_REPEATER) || defined(MBSSID)) && defined(CLIENT_MODE) && !defined(WIFI_WPAS_CLI) && !defined(RTK_NL80211) + //for RTK_NL80211, let scan triggered by upper layer + if(!priv->ss_req_ongoing) { + if(!IS_ROOT_INTERFACE(priv)){ + start_repeater_ss(priv); // site survey by vxd or vap + return; + } + } +#endif + +#ifdef CONFIG_RTK_MESH + if(GET_MIB(priv)->dot1180211sInfo.mesh_enable && priv->auto_channel) { + if(priv->mesh_swchnl_channel) {/* force abort mesh auto channel procedure*/ + priv->auto_channel = 1; + goto skip_40M_ss; + } + } +#endif + +// STADEBUG("rtl8192cd_ss_timer,ss_channel=%d\n",priv->site_survey->ss_channel); + + SMP_LOCK(flags); + +#ifdef MULTI_MAC_CLONE + ACTIVE_ID = 0; +#endif + + for (idx=0; idxavailable_chnl_num; idx++) + if (priv->site_survey->ss_channel == priv->available_chnl[idx]) + break; + +#if defined(RTK_NL80211) + //by brian, collect channel statistic here, move from 8192cd_expire_timer + if (IS_CFG80211_IFACE(priv) +#if defined(NON_NL80211_WPAS) && defined(WIFI_WPAS_CLI) + && (SSFROM_WPAS != priv->ss_req_ongoing) +#endif + ) + { + priv->rtk->survey_info[idx].channel = priv->site_survey->ss_channel; + int val = read_bbp_ch_load(priv); + if(val != -1) { + priv->rtk->survey_info[idx].chbusytime = (val/1000)*5; + } else { + priv->rtk->survey_info[idx].chbusytime = 0; + NDEBUG("Invalid channel load!\n"); + } + + check_sta_throughput(priv, idx); + read_noise_report(priv, idx); + } +#endif + +#ifdef CONFIG_RTL_NEW_AUTOCH +#ifdef AUTOCH_SS_SPEEDUP + if (priv->auto_channel == 1) + if(priv->pmib->miscEntry.autoch_ss_cnt>0) + AUTOCH_SS_COUNT = priv->pmib->miscEntry.autoch_ss_cnt; +#endif + if (priv->auto_channel == 1) { + unsigned int ofdm_ok, cck_ok, ht_ok; + + if (!priv->site_survey->to_scan_40M && !priv->auto_channel_step) { +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if (IS_OUTSRC_CHIP(priv))//outsrc chip use odemFAStatistic +#endif + { + odm_FalseAlarmCounterStatistics(ODMPTR); + priv->chnl_ss_fa_count[idx] = ODMPTR->FalseAlmCnt.Cnt_all; + priv->chnl_ss_cca_count[idx] = ODMPTR->FalseAlmCnt.Cnt_CCA_all; + } +#endif // USE_OUT_SRC +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if (!IS_OUTSRC_CHIP(priv)) +#endif + { + hold_CCA_FA_counter(priv); + _FA_statistic(priv); + priv->chnl_ss_fa_count[idx] = priv->pshare->FA_total_cnt; + priv->chnl_ss_cca_count[idx] = ((RTL_R8(0xa60)<<8)|RTL_R8(0xa61)) + RTL_R16(0xda0); + + release_CCA_FA_counter(priv); + } + #endif // !USE_OUT_SRC || _OUTSRC_COEXIST + } + + RTL_W32(RXERR_RPT, 0 << RXERR_RPT_SEL_SHIFT); + ofdm_ok = RTL_R16(RXERR_RPT); + + RTL_W32(RXERR_RPT, 3 << RXERR_RPT_SEL_SHIFT); + cck_ok = RTL_R16(RXERR_RPT); + + RTL_W32(RXERR_RPT, 6 << RXERR_RPT_SEL_SHIFT); + ht_ok = RTL_R16(RXERR_RPT); + + RTL_W32(RXERR_RPT, RXERR_RPT_RST); + + if (priv->site_survey->to_scan_40M) { + unsigned int z=0, ch_begin=0, ch_end=priv->available_chnl_num, + current_ch = PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x18, 0xff, 1); + int idx_2G_end=-1; +#if defined(RTK_5G_SUPPORT) + int idx_5G_begin=-1; + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + for (z=0; zavailable_chnl_num; z++) { + if (priv->available_chnl[z] > 14) { + idx_5G_begin = z; + break; + } + } + if (idx_5G_begin >= 0) + ch_begin = idx_5G_begin; + + for (z=ch_begin; z < ch_end; z++) { + if ((priv->available_chnl[z] == (current_ch+2)) || (priv->available_chnl[z] == (current_ch-2))) { + priv->chnl_ss_mac_rx_count_40M[z] = ofdm_ok + cck_ok + ht_ok; + } + } + } else +#endif + { + for (z=0; zavailable_chnl_num; z++) { + if (priv->available_chnl[z] <= 14) + idx_2G_end = z; + else + break; + } + if (idx_2G_end >= 0) + ch_end = idx_2G_end+1; + + for (z=ch_begin; z < ch_end; z++) { + if (priv->available_chnl[z] == current_ch) { + priv->chnl_ss_mac_rx_count_40M[z] = ofdm_ok + cck_ok + ht_ok; + break; + } + } + } + } else { + priv->chnl_ss_mac_rx_count[idx] = ofdm_ok + cck_ok + ht_ok; + } + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if (!priv->site_survey->to_scan_40M) { + unsigned long val32 = 0; + if ((GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv) == VERSION_8192E) + && priv->pmib->dot11RFEntry.acs_type && priv->auto_channel_step) { + for (i=0; i<20; i++) { + mdelay(1); + if (RTL_R8(0x8b6) & BIT1) + break; + } + + if (priv->auto_channel_step == 1) { + val32 = RTL_R32(0x8dc); + priv->nhm_cnt[idx][9] = (val32 & 0x0000ff00) >> 8; + priv->nhm_cnt[idx][8] = (val32 & 0x000000ff); + val32 = RTL_R32(0x8d8); + priv->nhm_cnt[idx][7] = (val32 & 0xff000000) >> 24; + priv->nhm_cnt[idx][6] = (val32 & 0x00ff0000) >> 16; + priv->nhm_cnt[idx][5] = (val32 & 0x0000ff00) >> 8; + } else if (priv->auto_channel_step == 2) { + val32 = RTL_R32(0x8d8); + priv->nhm_cnt[idx][4] = RTL_R8(0x8dc); + priv->nhm_cnt[idx][3] = (val32 & 0xff000000) >> 24; + priv->nhm_cnt[idx][2] = (val32 & 0x00ff0000) >> 16; + priv->nhm_cnt[idx][1] = (val32 & 0x0000ff00) >> 8; + priv->nhm_cnt[idx][0] = (val32 & 0x000000ff); + } + } + } +#endif + } +#endif + + if (idx == (priv->available_chnl_num - 1) && + priv->site_survey->hidden_ap_found != HIDE_AP_FOUND) { + loop_finish = 1; + } + else { +// mark by david ------------------------ +#if 0 + if ((priv->pmib->dot11RFEntry.dot11ch_hi != 0) && + (priv->site_survey->ss_channel >= priv->pmib->dot11RFEntry.dot11ch_hi)) + loop_finish = 1; + else +#endif +//--------------------------- 2007-04-14 + if (priv->site_survey->hidden_ap_found != HIDE_AP_FOUND) { +#if defined(DFS) + if(priv->site_survey->defered_ss) { + priv->site_survey->defered_ss--; + } else +#endif + { + priv->site_survey->ss_channel = priv->available_chnl[idx+1]; +#if defined(DFS) + priv->site_survey->defered_ss = should_defer_ss(priv); +#endif + } + + priv->site_survey->hidden_ap_found = 0; + } + else{ + STADEBUG("HIDE_AP_FOUND_DO_ACTIVE_SSAN\n"); + priv->site_survey->hidden_ap_found = HIDE_AP_FOUND_DO_ACTIVE_SSAN; + } +#ifdef CONFIG_RTL_NEW_AUTOCH + if ((priv->auto_channel == 1) && priv->site_survey->to_scan_40M) { +#if defined(RTK_5G_SUPPORT) + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + unsigned int current_ch = PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x18, 0xff, 1); + + if (((priv->site_survey->ss_channel+2) == current_ch) || ((priv->site_survey->ss_channel-2) == current_ch)) { + if ((idx+2) >= (priv->available_chnl_num - 1)) + loop_finish = 1; + else + priv->site_survey->ss_channel = priv->available_chnl[idx+2]; + } + } else +#endif + { + if (priv->site_survey->ss_channel == 14) + loop_finish = 1; + } + } +#endif + } + + if (loop_finish) { + priv->site_survey_times++; +#ifdef SIMPLE_CH_UNI_PROTOCOL + if(GET_MIB(priv)->dot1180211sInfo.mesh_enable && (priv->auto_channel & 0x30) ) + { + if( priv->auto_channel == 0x10 ) + { + if( priv->site_survey_times >= _11S_SS_COUNT1 ){ + if(priv->mesh_ChannelPrecedence == 0)/*not yet select channel or recieved others channel number*/ + { + priv->pmib->dot11RFEntry.dot11channel = selectClearChannel(priv); + SET_PSEUDO_RANDOM_NUMBER(priv->mesh_ChannelPrecedence); + } + priv->auto_channel = 0x20; + } + } + else + { + if( priv->site_survey_times >= _11S_SS_COUNT1+_11S_SS_COUNT2) + priv->auto_channel = 1; + } + if(priv->auto_channel == 1) { + get_available_channel(priv); + } + else { + for(i=0; iavailable_chnl_num; i++) + { + get_random_bytes(&(idx), sizeof(idx)); + idx %= priv->available_chnl_num; + loop_finish = priv->available_chnl[idx]; + priv->available_chnl[idx] = priv->available_chnl[i]; + priv->available_chnl[i] = loop_finish; + } + } + priv->site_survey->ss_channel = priv->available_chnl[0]; + } + else +#endif + +// only do multiple scan when site-survey request, david+2006-01-25 +// if (priv->site_survey_times < SS_COUNT) + if (priv->ss_req_ongoing && priv->site_survey_times < AUTOCH_SS_COUNT) {//AUTOCH_SS_SPEEDUP +// mark by david --------------------- + #if 0 // mark by david --------------------- + // scan again + if (priv->pmib->dot11RFEntry.dot11ch_low != 0) + priv->site_survey->ss_channel = priv->pmib->dot11RFEntry.dot11ch_low; + else + #endif //------------------------ 2007-04-14 + + //if scan 40M, start channel from start_ch_40M + if(priv->site_survey->to_scan_40M && priv->site_survey->start_ch_40M!=0) + priv->site_survey->ss_channel = priv->site_survey->start_ch_40M; + else + priv->site_survey->ss_channel = priv->available_chnl[0]; + + if(priv->pmib->miscEntry.ss_loop_delay) { + //STADEBUG("loop delay for %d miliseconads\n",priv->pmib->miscEntry.ss_loop_delay); + if(timer_pending(&priv->ss_timer)) + del_timer(&priv->ss_timer); + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.ss_loop_delay)); + + if(priv->ss_req_ongoing == SSFROM_REPEATER_VXD) { + //STADEBUG("RollBack to ROOT's ch[%d] between loop\n",GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel); +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(!rtk_sc_is_channel_fixed(priv)) +#endif + { + SwBWMode(GET_ROOT(priv), GET_ROOT(priv)->pshare->CurrentChannelBW, GET_ROOT(priv)->pshare->offset_2nd_chan); + SwChnl(GET_ROOT(priv), GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel, GET_ROOT(priv)->pshare->offset_2nd_chan); + } +#if defined(DFS) + priv->pmib->dot11DFSEntry.disable_tx = 0; +#endif + } + return; + } + } +#ifdef CONFIG_RTL_NEW_AUTOCH + else if ((priv->auto_channel == 1) && !priv->site_survey->to_scan_40M) { + unsigned int z=0, ch_begin=0, ch_end=priv->available_chnl_num; + int idx_2G_end=-1; + unsigned int proc_nhm = 0; +#if defined(RTK_5G_SUPPORT) + int idx_5G_begin=-1; + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + for (z=0; zavailable_chnl_num; z++) { + if (priv->available_chnl[z] > 14) { + idx_5G_begin = z; + break; + } + } + if (idx_5G_begin < 0) + goto skip_40M_ss; + } else +#endif +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv) == VERSION_8192E) + && priv->pmib->dot11RFEntry.acs_type && !priv->auto_channel_step) { + priv->auto_channel_step = 1; + + memset(priv->nhm_cnt, 0, sizeof(priv->nhm_cnt)); + + RTL_W8(TXPAUSE, STOP_BCN); + + RTL_W8(0xc50, 0x3e); + if (get_rf_mimo_mode(priv) != MIMO_1T1R) + RTL_W8(0xc58, 0x3e); + + RTL_W16(0x896, 0x61a8); + RTL_W16(0x892, 0xffff); + RTL_W32(0x898, 0x82786e64); + RTL_W32(0x89c, 0xffffff8c); + PHY_SetBBReg(priv, 0xE28, bMaskByte0, 0xff); + PHY_SetBBReg(priv, 0x890, BIT8|BIT9|BIT10, 3); + + priv->site_survey_times = 0; + priv->site_survey->ss_channel = priv->available_chnl[0]; + proc_nhm = 1; + } + else if ((GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv) == VERSION_8192E) + && priv->pmib->dot11RFEntry.acs_type && priv->auto_channel_step == 1) { + priv->auto_channel_step = 2; + + RTL_W8(0xc50, 0x2a); + if (get_rf_mimo_mode(priv) != MIMO_1T1R) + RTL_W8(0xc58, 0x2a); + + RTL_W32(0x898, 0x5a50463c); + RTL_W32(0x89c, 0xffffff64); + + priv->site_survey_times = 0; + priv->site_survey->ss_channel = priv->available_chnl[0]; + proc_nhm = 1; + } + else +#endif + { + if (priv->auto_channel_step) { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE)&~STOP_BCN); + priv->auto_channel_step = 0; + goto skip_40M_ss; + } + + for (z=0; zavailable_chnl_num; z++) { + if (priv->available_chnl[z] < 14) + idx_2G_end = z; + else + break; + } + if (idx_2G_end >= 0) + ch_end = idx_2G_end+1; + + for (z=ch_begin; z < ch_end; z++) + if ((priv->available_chnl[z] >= 5) && (priv->available_chnl[z] < 14)) + break; + if (z == ch_end) + goto skip_40M_ss; + } + + if (!proc_nhm) { + priv->site_survey->to_scan_40M++; + priv->site_survey->ss_channel = priv->available_chnl[z]; + priv->site_survey->start_ch_40M = priv->available_chnl[z];//when scan 40M, record start ch + //priv->site_survey_times = 0;//Do not reset the ss_time because it will rescan SS_COUNT again //AUTOCH_SS_SPEEDUP + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20_40; + } + } +#endif + else { +#ifdef CONFIG_RTL_NEW_AUTOCH +skip_40M_ss: + priv->site_survey->to_scan_40M = 0; +#endif + // scan end + OPMODE_VAL(OPMODE & ~WIFI_SITE_MONITOR); + //STADEBUG("End of scan\n"); + #if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + if (priv->pshare->DNC_on){ + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07600760); + } + } + #endif + + #if defined(CONFIG_RTL_92D_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8192D) + clnt_ss_check_band(priv, priv->pmib->dot11RFEntry.dot11channel); + #endif + +#ifdef CONFIG_POWER_SAVE + RTL_W16(0x454 , RTL_R16(0x454) & ~(BIT(6)|BIT(3))); + RTL_W16(0x100 , RTL_R16(0x100) | BIT(8)); +#endif + DIG_for_site_survey(priv, FALSE); +#ifdef USE_OUT_SRC + priv->pshare->bScanInProcess = FALSE; +#endif +#if defined(TESTCHIP_SUPPORT) && defined(CONFIG_RTL_92C_SUPPORT) + if( IS_TEST_CHIP(priv) ) { + if ((OPMODE & WIFI_STATION_STATE) || (OPMODE & WIFI_ADHOC_STATE)) { +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv) && !netif_running(GET_VXD_PRIV(priv)->dev)) +#endif + RTL_W32(RCR, RTL_R32(RCR) | RCR_CBSSID); + } + } else +#endif + { + #if 0 + if (OPMODE & WIFI_STATION_STATE) { + #ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv) && !netif_running(GET_VXD_PRIV(priv)->dev)) + #endif + RTL_W32(RCR, RTL_R32(RCR) | RCR_CBSSID); + } + else + #endif +#ifdef UNIVERSAL_REPEATER +#ifdef RTK_NL80211 //wrt-adhoc + if (IS_ROOT_INTERFACE(priv) && !netif_running(GET_VXD_PRIV(priv)->dev)) +#endif + if ((IS_VXD_INTERFACE(priv)&& !timer_pending(&GET_ROOT(priv)->ss_timer)) + || (IS_ROOT_INTERFACE(priv) && !timer_pending(&GET_VXD_PRIV(priv)->ss_timer))) +#endif + { + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) & ~STOP_BCN); // Re-enable beacon + } + + if (OPMODE & WIFI_ADHOC_STATE) + RTL_W32(RCR, RTL_R32(RCR) | RCR_CBSSID_ADHOC); + + if(IS_ROOT_INTERFACE(priv) && (OPMODE & WIFI_STATION_STATE)) + RTL_W32(RCR, RTL_R32(RCR) | RCR_CBSSID_ADHOC); + } + + + + #ifdef DFS + if (!GET_ROOT(priv)->pmib->dot11DFSEntry.disable_DFS && + (timer_pending(&GET_ROOT(priv)->ch_avail_chk_timer))) + GET_ROOT(priv)->pmib->dot11DFSEntry.disable_tx = 1; + else + GET_ROOT(priv)->pmib->dot11DFSEntry.disable_tx = 0; + #endif + + if (priv->ss_req_ongoing +#if defined(DFS) && defined (UNIVERSAL_REPEATER) + && (IS_ROOT_INTERFACE(priv) || + (IS_VXD_INTERFACE(priv) && !GET_ROOT(priv)->pmib->dot11DFSEntry.CAC_ss_counter )) +#endif + ) + { + GET_ROOT(priv)->pshare->CurrentChannelBW = GET_ROOT(priv)->pshare->is_40m_bw; + STADEBUG("RollBack to ROOT's ch[%d] becoz scan done\n",GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel); +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(!rtk_sc_is_channel_fixed(priv)) +#endif + { + SwBWMode(GET_ROOT(priv), GET_ROOT(priv)->pshare->CurrentChannelBW, GET_ROOT(priv)->pshare->offset_2nd_chan); + SwChnl(GET_ROOT(priv), GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel, GET_ROOT(priv)->pshare->offset_2nd_chan); + } + #ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D + #ifdef UNIVERSAL_REPEATER + && IS_ROOT_INTERFACE(priv) + #endif + ) + PHY_IQCalibrate(priv); + #endif + } + #ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv) && priv->pmib->wscEntry.wsc_enable) + GET_ROOT(priv)->pmib->miscEntry.func_off = 0; + #endif + + + + #ifdef SUPPORT_MULTI_PROFILE + if( priv->pmib->ap_profile.sortbyprofile && priv->pmib->ap_profile.enable_profile && priv->pmib->ap_profile.profile_num > 0){ + + // sort by profile + ProfileSort(priv,COMPARE_BSS, priv->site_survey->bss, priv->site_survey->count, sizeof(struct bss_desc)); + #ifdef WIFI_SIMPLE_CONFIG + ProfileSort(priv,COMPARE_WSCIE, priv->site_survey->wscie, priv->site_survey->count, sizeof(struct wps_ie_info)); + #endif + #if defined(WIFI_WPAS) || defined(RTK_NL80211) + ProfileSort(priv,COMPARE_WPAIE, priv->site_survey->wpa_ie, priv->site_survey->count, sizeof(struct wpa_ie_info)); + ProfileSort(priv,COMPARE_RSNIE, priv->site_survey->rsn_ie, priv->site_survey->count, sizeof(struct rsn_ie_info)); + #endif + + }else + #endif + { + // sort by rssi + qsort(priv->site_survey->bss, priv->site_survey->count, sizeof(struct bss_desc), compareBSS); + #ifdef WIFI_SIMPLE_CONFIG + qsort(priv->site_survey->wscie, priv->site_survey->count, sizeof(struct wps_ie_info), compareWpsIE); + #endif + #if defined(WIFI_WPAS) || defined(RTK_NL80211) + qsort(priv->site_survey->wpa_ie, priv->site_survey->count, sizeof(struct wpa_ie_info), compareWpaIE); + qsort(priv->site_survey->rsn_ie, priv->site_survey->count, sizeof(struct rsn_ie_info), compareRsnIE); + #endif + + } + + debug_print_bss(priv); + +#ifdef RTK_NL80211 //nl_clnt + if (IS_CFG80211_IFACE(priv) +#if defined(NON_NL80211_WPAS) && defined(WIFI_WPAS_CLI) + && (SSFROM_WPAS != priv->ss_req_ongoing) +#endif + ) + { + SMP_UNLOCK(flags); + printk("[%s %d][%s]scan done fun_off=%d ss_req_ongoing=%d\n", + __FUNCTION__, __LINE__, priv->dev->name, priv->pmib->miscEntry.func_off, priv->ss_req_ongoing); + realtek_cfg80211_inform_ss_result(priv); + + //if(OPMODE & WIFI_STATION_STATE) + //if((priv->site_survey->count==0) && (priv->ss_req_ongoing==0)) + //priv->ss_req_ongoing = 1; + + //if(priv->site_survey->count) always report scan done, maight be SSID not found + event_indicate_cfg80211(priv, NULL, CFG80211_SCAN_DONE, NULL); + SMP_LOCK(flags); + } +#endif + if (priv->auto_channel == 1) { + #ifdef SIMPLE_CH_UNI_PROTOCOL + if(!GET_MIB(priv)->dot1180211sInfo.mesh_enable) + #endif + { + priv->pmib->dot11RFEntry.dot11channel = selectClearChannel(priv); + #ifdef P2P_SUPPORT + P2P_DEBUG("auto channel select to[%d],ch changed call p2p_init again\n\n",priv->pmib->dot11RFEntry.dot11channel); + priv->p2pPtr->rdyinit=0; + p2p_init(priv); + #endif + DEBUG_INFO("auto channel select ch %d\n", priv->pmib->dot11RFEntry.dot11channel); + #if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196C_EC) + LOG_START_MSG(); + #endif + #if defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) + LOG_START_MSG(); + #endif + // When adaptivity_enable=2 and ACS algo use nhm, nhm setting should be revert. +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv) == VERSION_8192E) + && priv->pmib->dot11RFEntry.acs_type && priv->pshare->rf_ft_var.adaptivity_enable == 2) + { +#ifdef USE_OUT_SRC + extern void Phydm_NHMCounterStatisticsInit(void*); + if ( IS_OUTSRC_CHIP(priv) ) + Phydm_NHMCounterStatisticsInit(ODMPTR); + else +#endif + rtl8192cd_NHMBBInit(priv); + } +#endif + } +#ifdef DFS + #if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) + #endif + { + if(!priv->pmib->dot11DFSEntry.disable_DFS + && is_DFS_channel(priv->pmib->dot11RFEntry.dot11channel) && (OPMODE & WIFI_AP_STATE)) { + if (timer_pending(&priv->DFS_timer)) + del_timer(&priv->DFS_timer); + + if (timer_pending(&priv->ch_avail_chk_timer)) + del_timer(&priv->ch_avail_chk_timer); + + if (timer_pending(&priv->dfs_det_chk_timer)) + del_timer(&priv->dfs_det_chk_timer); + + init_timer(&priv->ch_avail_chk_timer); + priv->ch_avail_chk_timer.data = (unsigned long) priv; + priv->ch_avail_chk_timer.function = rtl8192cd_ch_avail_chk_timer; + + if ((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) && + ((priv->pmib->dot11RFEntry.dot11channel >= 120) && + (priv->pmib->dot11RFEntry.dot11channel <= 132))) + mod_timer(&priv->ch_avail_chk_timer, jiffies + CH_AVAIL_CHK_TO_CE); + else + mod_timer(&priv->ch_avail_chk_timer, jiffies + CH_AVAIL_CHK_TO); + + init_timer(&priv->DFS_timer); + priv->DFS_timer.data = (unsigned long) priv; + priv->DFS_timer.function = rtl8192cd_DFS_timer; + + /* DFS activated after 5 sec; prevent switching channel due to DFS false alarm */ + mod_timer(&priv->DFS_timer, jiffies + RTL_SECONDS_TO_JIFFIES(5)); + + init_timer(&priv->dfs_det_chk_timer); + priv->dfs_det_chk_timer.data = (unsigned long) priv; + priv->dfs_det_chk_timer.function = rtl8192cd_dfs_det_chk_timer; + + mod_timer(&priv->dfs_det_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pshare->rf_ft_var.dfs_det_period*10)); + + DFS_SetReg(priv); + + if (!priv->pmib->dot11DFSEntry.CAC_enable) { + del_timer_sync(&priv->ch_avail_chk_timer); + mod_timer(&priv->ch_avail_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(200)); + } + } + + + /* disable all of the transmissions during channel availability check */ + priv->pmib->dot11DFSEntry.disable_tx = 0; + if (!priv->pmib->dot11DFSEntry.disable_DFS && + is_DFS_channel(priv->pmib->dot11RFEntry.dot11channel) && (OPMODE & WIFI_AP_STATE)){ + priv->pmib->dot11DFSEntry.disable_tx = 1; + } + } +#endif /* DFS */ + + + + if (OPMODE & WIFI_AP_STATE) + priv->auto_channel = 0; + else + priv->auto_channel = 2; + + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(!rtk_sc_is_channel_fixed(priv)) +#endif + { + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + } +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + PHY_IQCalibrate(priv); +#endif + + +#ifdef AUTO_CHANNEL_TIMEOUT + if (priv->pmib->miscEntry.autoch_timeout && priv->pshare->autoch_trigger_by_timeout) + { + // Update channel. + unsigned char *pbuf = (unsigned char *)priv->beaconbuf + priv->timoffset - 3; + if (*pbuf == _DSSET_IE_&& *(pbuf+1) == 1) { + *(pbuf + 2) = priv->pmib->dot11RFEntry.dot11channel; + } + priv->ht_cap_len = 0; +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]->pmib->dot11RFEntry.dot11channel = priv->pmib->dot11RFEntry.dot11channel; + priv->pvap_priv[i]->ht_cap_len = 0; // re-construct HT IE + + if (IS_DRV_OPEN(priv->pvap_priv[i])) { + pbuf = (unsigned char *)priv->pvap_priv[i]->beaconbuf + priv->timoffset - 3; + if (*pbuf == _DSSET_IE_&& *(pbuf+1) == 1) { + *(pbuf + 2) = priv->pmib->dot11RFEntry.dot11channel; + } + } + } + } +#endif + priv->pshare->autoch_trigger_by_timeout = 0; + printk("===> complete select channel curr = %d, 2ch = %d\n", + priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + } + else +#endif + { + priv->ht_cap_len = 0; // re-construct HT IE + init_beacon(priv); +#ifdef SIMPLE_CH_UNI_PROTOCOL + printk("scan finish, sw ch to (#%d), init beacon\n", priv->pmib->dot11RFEntry.dot11channel); +#endif +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]->pmib->dot11RFEntry.dot11channel = priv->pmib->dot11RFEntry.dot11channel; + priv->pvap_priv[i]->ht_cap_len = 0; // re-construct HT IE + + if (IS_DRV_OPEN(priv->pvap_priv[i])) + init_beacon(priv->pvap_priv[i]); + } + } +#endif + +#ifdef CLIENT_MODE +#ifdef HS2_CLIENT_TEST + JOIN_RES = STATE_Sta_Ibss_Idle; +#else + if (JOIN_RES == STATE_Sta_Ibss_Idle) { + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_ADHOC & NETYPE_Mask) << NETYPE_SHIFT)); + mod_timer(&priv->idle_timer, jiffies + RTL_SECONDS_TO_JIFFIES(5)); + } +#endif +#endif + } + + + if (priv->ss_req_ongoing) { + priv->site_survey->count_backup = priv->site_survey->count; + memcpy(priv->site_survey->bss_backup, priv->site_survey->bss, sizeof(struct bss_desc)*priv->site_survey->count); + priv->ss_req_ongoing = 0; + } + +#if defined(CONFIG_RTL_NEW_AUTOCH) && defined(SS_CH_LOAD_PROC) + record_SS_report(priv); +#endif + + } + // backup the bss database +#ifdef WIFI_WPAS_CLI + else if (SSFROM_WPAS == priv->ss_req_ongoing) { + printk("cliW: scan ind to => sp:%d ss:%d\n", + priv->pshare->bScanInProcess, priv->ss_req_ongoing); + + /* report scan list to wpa_supplicant using ap scan */ + GET_VXD_PRIV(priv)->site_survey->count_backup = priv->site_survey->count; + memcpy(GET_VXD_PRIV(priv)->site_survey->bss_backup, priv->site_survey->bss, + sizeof(struct bss_desc)*priv->site_survey->count); +#ifdef WIFI_SIMPLE_CONFIG + memcpy(GET_VXD_PRIV(priv)->site_survey->wscie, priv->site_survey->wscie, + sizeof(struct wps_ie_info)*priv->site_survey->count); +#endif + memcpy(GET_VXD_PRIV(priv)->site_survey->wpa_ie_backup, priv->site_survey->wpa_ie, + sizeof(struct wpa_ie_info)*priv->site_survey->count); + memcpy(GET_VXD_PRIV(priv)->site_survey->rsn_ie_backup, priv->site_survey->rsn_ie, + sizeof(struct rsn_ie_info)*priv->site_survey->count); + GET_VXD_PRIV(priv)->ss_req_ongoing = 0; + priv->ss_req_ongoing = 0; + printk("cliW: scan done 4 ss_req_ongoing = 0\n"); + event_indicate_wpas(GET_VXD_PRIV(priv), NULL, WPAS_SCAN_DONE, NULL); + } +#endif // WIFI_WPAS_CLI + else if (priv->ss_req_ongoing) { +#ifdef P2P_SUPPORT + if((OPMODE&WIFI_P2P_SUPPORT) + && P2P_DISCOVERY){ + //for keep priv->site_survey->count_backup when P2P discovery + } + else +#endif + { + priv->site_survey->count_backup = priv->site_survey->count; + memcpy(priv->site_survey->bss_backup, priv->site_survey->bss, sizeof(struct bss_desc)*priv->site_survey->count); + } +#ifdef WIFI_SIMPLE_CONFIG + backup_wscIE(priv); + //memcpy(priv->site_survey->wscie_backup, priv->site_survey->wscie, sizeof(struct wps_ie_info)*priv->site_survey->count); +#endif + + +#if defined(WIFI_WPAS) || defined(RTK_NL80211) //_Eric ?? sizeof(struct wpa_ie_info)*priv->site_survey->count ===> * is multiple, not pointer ~ + memcpy(priv->site_survey->wpa_ie_backup, priv->site_survey->wpa_ie, sizeof(struct wpa_ie_info)*priv->site_survey->count); + memcpy(priv->site_survey->rsn_ie_backup, priv->site_survey->rsn_ie, sizeof(struct rsn_ie_info)*priv->site_survey->count); +#endif + +#ifdef CLIENT_MODE +#if defined(RTK_NL80211) + if(priv->ss_req_ongoing != SSFROM_WSC) +#else + if(priv->ss_req_ongoing != SSFROM_WSC && priv->ss_req_ongoing != SSFROM_REPEATER_VXD) +#endif + { + if (JOIN_RES == STATE_Sta_Ibss_Idle) { + STADEBUG("start_clnt_lookup(RESCAN)\n"); + start_clnt_lookup(priv, RESCAN); + } + else if (JOIN_RES == STATE_Sta_Auth_Success){ + start_clnt_assoc(priv); + } + else if (JOIN_RES == STATE_Sta_Roaming_Scan) { + STADEBUG("start_clnt_lookup(RESCAN)\n"); + start_clnt_lookup(priv, RESCAN); + } + else if(JOIN_RES == STATE_Sta_No_Bss) { + STADEBUG("start_clnt_lookup(RESCAN)\n"); + JOIN_RES_VAL(STATE_Sta_Roaming_Scan); + start_clnt_lookup(priv, RESCAN); + } + + } +#endif + +#ifdef SMART_REPEATER_MODE + if (priv->ss_req_ongoing == SSFROM_REPEATER_VXD) { + // VXD Interface +#ifdef SUPPORT_MULTI_PROFILE + if (GET_MIB(priv)->ap_profile.enable_profile && + GET_MIB(priv)->ap_profile.profile_num > 0) { + SSID2SCAN_LEN = strlen(GET_MIB(priv)->ap_profile.profile[priv->profile_idx].ssid); + memcpy(SSID2SCAN, GET_MIB(priv)->ap_profile.profile[priv->profile_idx].ssid, SSID2SCAN_LEN); + } + else +#endif + { + SSID2SCAN_LEN = GET_MIB(priv)->dot11StationConfigEntry.dot11SSIDtoScanLen; + memcpy(SSID2SCAN, GET_MIB(priv)->dot11StationConfigEntry.dot11SSIDtoScan, SSID2SCAN_LEN); + } + priv->site_survey->count_target = priv->site_survey->count; + memcpy(priv->site_survey->bss_target, priv->site_survey->bss, sizeof(struct bss_desc)*priv->site_survey->count); + priv->join_index = -1; + priv->join_res = STATE_Sta_Min; + + start_clnt_lookup(priv, DONTRESCAN); +#if !defined(RTK_NL80211) + //STADEBUG("call set_vxd_rescan\n"); + if(priv->join_res == STATE_Sta_Min) + set_vxd_rescan(priv,RESCAN_BY_NEXTTIME); +#endif + } +#endif + + priv->ss_req_ongoing = 0; + //STADEBUG("set priv->ss_req_ongoing to 0\n\n\n"); + +#ifdef WIFI_WPAS + event_indicate_wpas(priv, NULL, WPAS_SCAN_DONE, NULL); +#endif + } +#ifdef CLIENT_MODE + else if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) { + priv->site_survey->count_target = priv->site_survey->count; + memcpy(priv->site_survey->bss_target, priv->site_survey->bss, sizeof(struct bss_desc)*priv->site_survey->count); + priv->join_index = -1; +#ifdef HS2_CLIENT_TEST +#else + if (JOIN_RES == STATE_Sta_Roaming_Scan){ + STADEBUG("start_clnt_lookup(DONTRESCAN)\n"); + start_clnt_lookup(priv, DONTRESCAN); + } + +#endif + } +#endif + else { + DEBUG_ERR("Faulty scanning\n"); + } + +#ifdef CONFIG_RTL_COMAPI_WLTOOLS + wake_up_interruptible(&priv->ss_wait); +#endif + +#ifdef CHECK_BEACON_HANGUP + priv->pshare->beacon_wait_cnt = 2; +#endif +#ifdef CONFIG_RTL8672 + OPMODE_VAL(OPMODE & (~WIFI_WAIT_FOR_CHANNEL_SELECT)); +#endif + SMP_UNLOCK(flags); +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_SITE_SURVEY); +#endif + return; + } + } + + + + /*switch channel; now, change RF channel... start*/ + + #ifdef CONFIG_RTL_92D_SUPPORT + int band_switch = 0; + #endif + + // now, change RF channel... + #ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS && is_DFS_channel(priv->site_survey->ss_channel)){ + priv->pmib->dot11DFSEntry.disable_tx = 1; + }else{ + priv->pmib->dot11DFSEntry.disable_tx = 0; + } + #endif + + #if defined(CONFIG_RTL_92D_SUPPORT) && !defined(CONFIG_RTL_DUAL_PCIESLOT_BIWLAN_D) + if ((GET_CHIP_VER(priv) == VERSION_8192D) && priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY) { + band_switch = clnt_ss_check_band(priv, priv->site_survey->ss_channel); + } + #endif + + #ifdef CONFIG_RTL_NEW_AUTOCH + if (priv->site_survey->to_scan_40M) { + #if defined(RTK_5G_SUPPORT) + if (GET_ROOT(priv)->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + if((priv->site_survey->ss_channel>144) ? ((priv->site_survey->ss_channel-1)%8) : (priv->site_survey->ss_channel%8)) { + //STADEBUG("SwChnl=%d,2ndoffsetCh=%d\n",priv->site_survey->ss_channel,HT_2NDCH_OFFSET_ABOVE); +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(!rtk_sc_is_channel_fixed(priv)) +#endif + { + SwChnl(GET_ROOT(priv), priv->site_survey->ss_channel, HT_2NDCH_OFFSET_ABOVE); + SwBWMode(GET_ROOT(priv), priv->pshare->CurrentChannelBW, HT_2NDCH_OFFSET_ABOVE); + } + } else { + //STADEBUG("SwChnl=%d,2ndoffsetCh=%d\n",priv->site_survey->ss_channel,HT_2NDCH_OFFSET_BELOW); +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(!rtk_sc_is_channel_fixed(priv)) +#endif + { + SwChnl(GET_ROOT(priv), priv->site_survey->ss_channel, HT_2NDCH_OFFSET_BELOW); + SwBWMode(GET_ROOT(priv), priv->pshare->CurrentChannelBW, HT_2NDCH_OFFSET_BELOW); + } + } + + } else + #endif + { + /* set channel >= 5 for algo requirement */ + //STADEBUG("SwChnl=%d,2ndoffsetCh=%d\n",priv->site_survey->ss_channel,HT_2NDCH_OFFSET_BELOW); +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(!rtk_sc_is_channel_fixed(priv)) +#endif + { + SwChnl(GET_ROOT(priv), priv->site_survey->ss_channel, HT_2NDCH_OFFSET_BELOW); + SwBWMode(GET_ROOT(priv), priv->pshare->CurrentChannelBW, HT_2NDCH_OFFSET_BELOW); + } + } + } + else + #endif + { + #if defined(UNIVERSAL_REPEATER) && defined(SMART_REPEATER_MODE) +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(rtk_sc_during_simple_config_scan(priv)){ + + int max_bw = HT_CHANNEL_WIDTH_20; + int sc_scan_offset = HT_2NDCH_OFFSET_DONTCARE; + + //panic_printk("%s %d (idx=%d, channel=%d)+++\n", __FUNCTION__, __LINE__, idx, priv->available_chnl[idx]); + + if(priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + max_bw = HT_CHANNEL_WIDTH_20_40; + + if(priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) + max_bw = HT_CHANNEL_WIDTH_80; + + if(max_bw != HT_CHANNEL_WIDTH_20){ + sc_scan_offset = rtk_sc_get_scan_offset(GET_ROOT(priv), priv->site_survey->ss_channel, max_bw); + } + + GET_ROOT(priv)->pshare->offset_2nd_chan = sc_scan_offset; + GET_ROOT(priv)->pshare->CurrentChannelBW = max_bw; + + priv->pshare->offset_2nd_chan = sc_scan_offset; + priv->pshare->CurrentChannelBW = max_bw; + + if(!rtk_sc_is_channel_fixed(priv)) { + SwBWMode(GET_ROOT(priv), max_bw, sc_scan_offset); + SwChnl(GET_ROOT(priv), priv->site_survey->ss_channel, sc_scan_offset); + } + + if( (priv->site_survey->ss_channel >= 5) && (priv->site_survey->ss_channel <= 9) + && (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) && (idx >= 0)) + priv->site_survey->ss_channel = priv->available_chnl[(idx)]; + + + } + else +#endif +#if defined(DFS) && defined (UNIVERSAL_REPEATER) + if(IS_ROOT_INTERFACE(priv) || + (IS_VXD_INTERFACE(priv) && !GET_ROOT(priv)->pmib->dot11DFSEntry.CAC_ss_counter)) +#endif + { + if(priv->site_survey->defered_ss) { + //STADEBUG("Rollback to AP's ch then stay %d ms\n",priv->pmib->miscEntry.ss_delay); + //STADEBUG("SwChnl[%d],2ndCh[%d]\n",GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel,GET_ROOT(priv)->pshare->offset_2nd_chan); +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(!rtk_sc_is_channel_fixed(priv)) +#endif + { + SwBWMode(GET_ROOT(priv), GET_ROOT(priv)->pshare->CurrentChannelBW, GET_ROOT(priv)->pshare->offset_2nd_chan); + SwChnl(GET_ROOT(priv), GET_ROOT(priv)->pmib->dot11RFEntry.dot11channel, GET_ROOT(priv)->pshare->offset_2nd_chan); + } + priv->pmib->dot11DFSEntry.disable_tx = 0; + + } else + #endif + { + //STADEBUG("SwChnl=%d,2ndoffsetCh=%d\n",priv->site_survey->ss_channel,priv->pshare->offset_2nd_chan); + #if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(!rtk_sc_is_channel_fixed(priv)) + #endif + SwChnl(GET_ROOT(priv), priv->site_survey->ss_channel, priv->pshare->offset_2nd_chan); + #ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D) && + (priv->pmib->dot11RFEntry.macPhyMode == SINGLEMAC_SINGLEPHY) && band_switch) + PHY_IQCalibrate(GET_ROOT(priv)); + #endif + #ifdef CONFIG_RTL_NEW_AUTOCH + if (priv->auto_channel == 1) { + reset_FA_reg(priv); + + #if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv) == VERSION_8192E) + && priv->pmib->dot11RFEntry.acs_type && priv->auto_channel_step) { + PHY_SetBBReg(priv, 0x890, BIT1, 0); + PHY_SetBBReg(priv, 0x890, BIT1, 1); + } + #endif + } + #endif + } +#if defined(UNIVERSAL_REPEATER) && defined(SMART_REPEATER_MODE) + } +#endif + } + /*switch channel-end*/ +#if defined(RTK_NL80211) + //by brian, trigger channel load evaluation after channel switched + start_bbp_ch_load(priv, (45*1000)/4); +#endif + /*TX probe_request -- start*/ + if (priv->site_survey->hidden_ap_found == HIDE_AP_FOUND_DO_ACTIVE_SSAN || + !is_passive_channel(priv , priv->pmib->dot11StationConfigEntry.dot11RegDomain, priv->site_survey->ss_channel)) + { + #ifdef SIMPLE_CH_UNI_PROTOCOL + if(GET_MIB(priv)->dot1180211sInfo.mesh_enable) + issue_probereq_MP(priv, "MESH-SCAN", 9, NULL, TRUE); + else + #endif + if (priv->ss_ssidlen == 0){ + + #ifdef P2P_SUPPORT + if( OPMODE&WIFI_P2P_SUPPORT && + ((P2PMODE==P2P_DEVICE)||(P2PMODE==P2P_CLIENT)) ){ + //P2P_DEBUG("p2p scan (chann:%d)\n",priv->site_survey->ss_channel); + issue_probereq(priv, "DIRECT-", 7, NULL); + }else + #endif + { + if (!priv->auto_channel_step) { + issue_probereq(priv, NULL, 0, NULL); + } + } + }else{ + #ifdef SUPPORT_MULTI_PROFILE /*send multi probe_req by profile_num*/ + if (priv->pmib->ap_profile.enable_profile && priv->pmib->ap_profile.profile_num > 0) { + for(jdx=0;jdxpmib->ap_profile.profile_num;jdx++) { + STADEBUG("issue_probereq[%s],ch=[%d]\n",priv->pmib->ap_profile.profile[jdx].ssid , priv->site_survey->ss_channel); + issue_probereq(priv, priv->pmib->ap_profile.profile[jdx].ssid, strlen(priv->pmib->ap_profile.profile[jdx].ssid), NULL); + } + } + else + #endif + { + STADEBUG("issue_probereq,ssid[%s],ch[%d]\n",priv->ss_ssid,priv->site_survey->ss_channel); + issue_probereq(priv, priv->ss_ssid, priv->ss_ssidlen, NULL); + } + + } + } + + /*TX probe_request -- End*/ + SMP_UNLOCK(flags); + + + /*now, scheduling next ss_timer ; the time util to next timer executed is how long DUT stady in this channel*/ + // now, start another timer again. + + if(is_passive_channel(priv , priv->pmib->dot11StationConfigEntry.dot11RegDomain, priv->site_survey->ss_channel)) + { +#if defined(UNIVERSAL_REPEATER) && defined(SMART_REPEATER_MODE) + if(priv->site_survey->defered_ss) { + if(priv->pmib->miscEntry.ss_delay) { + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.ss_delay)); + } else { + if(priv->pmib->miscEntry.passive_ss_int) { + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.passive_ss_int)); + } else { + mod_timer(&priv->ss_timer, jiffies + SS_PSSV_TO); + } + } + } + else { + if(priv->pmib->miscEntry.passive_ss_int) { + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.passive_ss_int)); + } else { + mod_timer(&priv->ss_timer, jiffies + SS_PSSV_TO); + } + } + +#else + if(priv->pmib->miscEntry.passive_ss_int) { + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.passive_ss_int)); + } else { + mod_timer(&priv->ss_timer, jiffies + SS_PSSV_TO); + } +#endif + + } + else + + { +#ifdef CONFIG_RTL_NEW_AUTOCH + if (priv->auto_channel == 1){ + #ifdef AUTOCH_SS_SPEEDUP + if(priv->pmib->miscEntry.autoch_ss_to != 0) + mod_timer(&priv->ss_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.autoch_ss_to)); + else + #endif + if (priv->auto_channel_step) + mod_timer(&priv->ss_timer, jiffies + SS_AUTO_CHNL_NHM_TO); + else + mod_timer(&priv->ss_timer, jiffies + SS_AUTO_CHNL_TO); + }else +#endif + { + #ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT && P2P_STATE == P2P_S_SEARCH){ + /*search phase (only 1,6,11) use 120ms*/ + //P2P_DEBUG("%dms\n",P2P_SEARCH_TIME_V); + mod_timer(&priv->ss_timer, jiffies + P2P_SEARCH_TIME); + }else + #endif + { + mod_timer(&priv->ss_timer, jiffies + SS_TO); + } + } + } +} + + +/** + * @brief get WPA/WPA2 information + * + * use 1 timestamp (32-bit variable) to carry WPA/WPA2 info \n + * 1st 16-bit: WPA \n + * | auth | unicast cipher | multicast cipher | \n + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 \n + * +-----+-----+----+-----+--------+------+-----+------+-------+-----+--------+------+-----+------+-------+-----+ \n + * | Rsv | PSK | 1X | Rsv | WEP104 | CCMP | Rsv | TKIP | WEP40 | Grp | WEP104 | CCMP | Rsv | TKIP | WEP40 | Grp | \n + * +-----+-----+----+-----+--------+------+-----+------+-------+-----+--------+------+-----+------+-------+-----+ \n + * 2nd 16-bit: WPA2 \n + * auth | unicast cipher | multicast cipher | \n + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 \n + * +-----+-----+----+-----+--------+------+-----+------+-------+-----+--------+------+-----+------+-------+-----+ \n + * | Rsv | PSK | 1X | Rsv | WEP104 | CCMP | Rsv | TKIP | WEP40 | Grp | WEP104 | CCMP | Rsv | TKIP | WEP40 | Grp | \n + * +-----+-----+----+-----+--------+------+-----+------+-------+-----+--------+------+-----+------+-------+-----+ \n + */ +static void get_security_info(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, int index) +{ + int i, len, result; + unsigned char *p, *pframe, *p_uni, *p_auth, val; + unsigned short num; + unsigned char OUI1[] = {0x00, 0x50, 0xf2}; + unsigned char OUI2[] = {0x00, 0x0f, 0xac}; +#if defined(CONFIG_RTL_WAPI_SUPPORT) + const unsigned char OUI3[] = {0x00, 0x14, 0x72}; +#endif +#ifdef CONFIG_IEEE80211W_CLI + unsigned short rsnie_cap; + DOT11_RSN_CAPABILITY *pDot11RSNCapability; +#endif + + //WPS2DOTX + unsigned char *awPtr = (unsigned char *)&priv->site_survey->wscie[index].data; + int foundtimes = 0; + unsigned char *ptmp = NULL; + unsigned int lentmp=0; + unsigned int totallen=0; + //WPS2DOTX + + if (index >= MAX_BSS_NUM) { + DEBUG_ERR("get_security_info Error: WSC IE index exceeds!\n"); + return; + } + + pframe = get_pframe(pfrinfo); + priv->site_survey->bss[index].t_stamp[0] = 0; + + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + len = 0; + result = 0; + do { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if ((p != NULL) && (len > 18)) + { + if (memcmp((p + 2), OUI1, 3)) + goto next_tag; + if (*(p + 5) != 0x01) + goto next_tag; + if (memcmp((p + 8), OUI1, 3)) + goto next_tag; + val = *(p + 11); + priv->site_survey->bss[index].t_stamp[0] |= BIT(val); + p_uni = p + 12; + memcpy(&num, p_uni, 2); + num = le16_to_cpu(num); + for (i=0; isite_survey->bss[index].t_stamp[0] |= (BIT(val) << 6); + } + p_auth = p_uni + 2 + 4 * num; + memcpy(&num, p_auth, 2); + num = le16_to_cpu(num); + for (i=0; isite_survey->bss[index].t_stamp[0] |= (BIT(val) << 12); + } + result = 1; + } +next_tag: + if (p != NULL) + p = p + 2 + len; + } while ((p != NULL) && (result != 1)); + + if (result != 1) + { + priv->site_survey->bss[index].t_stamp[0] = 0; + } + + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + len = 0; + result = 0; + do { + p = get_ie(p, _RSN_IE_2_, &len, + pfrinfo->pktlen - (p - pframe)); + if ((p != NULL) && (len > 12)) + { + if (memcmp((p + 4), OUI2, 3)) + goto next_id; + val = *(p + 7); + priv->site_survey->bss[index].t_stamp[0] |= (BIT(val) << 16); + p_uni = p + 8; + memcpy(&num, p_uni, 2); + num = le16_to_cpu(num); + for (i=0; isite_survey->bss[index].t_stamp[0] |= (BIT(val) << 22); + } + p_auth = p_uni + 2 + 4 * num; + memcpy(&num, p_auth, 2); + num = le16_to_cpu(num); + for (i=0; isite_survey->bss[index].t_stamp[0] |= (BIT(val) << 28); + } +#ifdef CONFIG_IEEE80211W_CLI + pDot11RSNCapability = (DOT11_RSN_CAPABILITY *)(p_auth + 2 + 4 * num); + priv->site_survey->bss[index].t_stamp[1] &= ~PMF_REQ; + + if (pDot11RSNCapability) + { + if (pDot11RSNCapability->field.MFPC && pDot11RSNCapability->field.MFPR) + priv->site_survey->bss[index].t_stamp[1] |= PMF_REQ; + else if (pDot11RSNCapability->field.MFPC) + priv->site_survey->bss[index].t_stamp[1] |= PMF_CAP; + else + priv->site_survey->bss[index].t_stamp[1] |= PMF_NONE; + } +#endif + result = 1; + } +next_id: + if (p != NULL) + p = p + 2 + len; + } while ((p != NULL) && (result != 1)); + + if (result != 1) + { + priv->site_survey->bss[index].t_stamp[0] &= 0x0000ffff; + } + +#if defined(CONFIG_RTL_WAPI_SUPPORT) + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + len = 0; + result = 0; + do { + p = get_ie(p, _EID_WAPI_, &len, + pfrinfo->pktlen - (p - pframe)); + if ((p != NULL) && (len >19)) + { + i = *((uint16*)(p+4)); + if (i != 0x0100) + goto next_id_wapi; + if (memcmp((p + 6), OUI3, 3) || *(p+9)!=2) + goto next_id_wapi; + + val = *(p + 9); + priv->site_survey->bss[index].t_stamp[0] = SECURITY_INFO_WAPI; + break; + } +next_id_wapi: + if (p != NULL) + p = p + 2 + len; + } while ((p != NULL) && (result != 1)); +#endif + +#ifdef WIFI_SIMPLE_CONFIG +/* WPS2DOTX*/ +#ifndef MULTI_MAC_CLONE +#if defined(WIFI_WPAS_CLI) + if ((OPMODE & WIFI_STATION_STATE) || (SSFROM_WPAS == priv->ss_req_ongoing)) +#elif defined(WIFI_WPAS) || defined(RTK_NL80211) + if (OPMODE & WIFI_STATION_STATE) +#else + if (priv->ss_req_ongoing == 2) // simple-config scan-req +#endif +#endif + { + + + //ptmp = pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_; + ptmp = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + + for (;;) + { + ptmp = get_ie(ptmp, _WPS_IE_, (int *)&lentmp,pfrinfo->pktlen - (ptmp - pframe)); + + if (ptmp != NULL) { + if (!memcmp(ptmp+2, WSC_IE_OUI, 4)) { + foundtimes ++; + if(foundtimes ==1){ + if (lentmp+2 > MAX_WSC_IE_LEN-totallen) { + DEBUG_ERR("get_security_info Error: wps_ie len exceeds!\n"); + return; + } + memcpy(awPtr , ptmp ,lentmp + 2); + awPtr+= (lentmp + 2); + totallen += (lentmp + 2); + }else{ + if ((lentmp < 4) || (lentmp-4 > MAX_WSC_IE_LEN-totallen)) { + DEBUG_ERR("get_security_info Error: wps_ie len error!\n"); + return; + } + memcpy(awPtr , ptmp+2+4 ,lentmp-4); + awPtr+= (lentmp-4); + totallen += (lentmp-4); + } + } + } + else{ + break; + } + + ptmp = ptmp + lentmp + 2; + } + if(foundtimes){ + priv->site_survey->wscie[index].wps_ie_len = totallen; + //debug_out("WSC_IE",priv->site_survey->ie[index].data,totallen); + + //get the first wps ie to see the + //search_wsc_tag(unsigned char *data, unsigned short id, int len, &target_len); + priv->site_survey->bss[index].t_stamp[1] |= BIT(8); // set t_stamp[1] bit 8 when AP supports WPS + } else { + awPtr[0]='\0'; + priv->site_survey->bss[index].t_stamp[1] &= ~BIT(8); // clear t_stamp[1] bit 8 when AP not supports WPS(do not have wps IE) + } + } + +#endif +/* WPS2DOTX*/ +} + +#ifdef P2P_SUPPORT +int p2p_collect_bss_info(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + + int index ; + int len; + unsigned char *pframe, *sa, channel_tmp; + int role; + int idx=0; + int exist=0; + unsigned char *ptmp=NULL; + unsigned char *SsidPtr=NULL; + int ssidlen = 0; + + /* p2p IE must support fragment and reassembly ; + this method is sample for support reassembly*/ + static unsigned char ReAssem_p2pie[MAX_REASSEM_P2P_IE]; + static unsigned char ReAssem_wscie[MAX_REASSEM_P2P_IE]; + + int IEfoundtimes = 0 ; + unsigned char *p2pIEPtr = ReAssem_p2pie ; + int p2pIElen=0; + + unsigned char *wscIEPtr = ReAssem_wscie ; + int wscIElen=0; + + struct device_info_s p2p_devic_info; + memset(&p2p_devic_info,0,sizeof(struct device_info_s)); + + pframe = get_pframe(pfrinfo); + sa = GetAddr2Ptr(pframe); + + if (priv->site_survey->count >= MAX_BSS_NUM){ + P2P_DEBUG("bss count > MAX_BSS_NUM!!!\n"); + return 0; + } + + /* chk DA is broadcast or my p2p device-addr (default use MY-HW-ADDR as p2p device addrree)*/ + if( memcmp(GetAddr1Ptr(pframe), "\xff\xff\xff\xff\xff\xff", 6) + && memcmp(GetAddr1Ptr(pframe), GET_MY_HWADDR, 6)) + { + P2P_DEBUG("DA mismatch!\n"); + return 0; + } + + + /*get SSID*/ + SsidPtr = get_ie(pframe + WLAN_HDR_A3_LEN + _PROBERSP_IE_OFFSET_, _SSID_IE_, &ssidlen, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBERSP_IE_OFFSET_); + + + /* chk ssid == wildcard SSID ("DIRECT-")*/ + if(SsidPtr + && (*(SsidPtr+2) == 'D' ) && (*(SsidPtr+3) == 'I' ) + && (*(SsidPtr+4) == 'R')&& (*(SsidPtr+5) == 'E') + && (*(SsidPtr+6) == 'C')&& (*(SsidPtr+7) == 'T') + && (*(SsidPtr+8) == '-')) + { + P2P_DEBUG("device: %02x%02x%02x:%02x%02x%02x\n" , + sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]); + + }else{ + return 0; + } + + + /*----------------------------find P2P IE -----------------------------------start*/ + + /* Get P2P IE from Probe_RSP */ + IEfoundtimes = 0; + len = 0 ; + ptmp = pframe + WLAN_HDR_A3_LEN + _PROBERSP_IE_OFFSET_ ; + + /*support ReAssemble*/ + for (;;) + { + ptmp = get_ie(ptmp, _P2P_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBERSP_IE_OFFSET_ - len); + + if (ptmp) { + if (!memcmp(ptmp+2, WFA_OUI_PLUS_TYPE, 4)) { + IEfoundtimes ++; + memcpy(p2pIEPtr , ptmp+6 ,len-4); + p2pIEPtr+= (len-4); + } + + } + else{ + break; + } + ptmp = ptmp + len + 2; + + } + + + + if(IEfoundtimes){ + if(IEfoundtimes>1){ + P2P_DEBUG("ReAssembly p2p IE\n"); + } + p2pIElen = (int)(((unsigned long)p2pIEPtr)-((unsigned long)ReAssem_p2pie)); + if(p2pIElen > MAX_REASSEM_P2P_IE){ + P2P_DEBUG("\n\n ReAssem WSC IE exceed MAX_REASSEM_P2P_IE , chk!!!\n\n"); + return 0; + } + + }else{ + return 0; + } + /*----------------------------find P2P IE -----------------------------------end*/ + + + /*----------------------------find WSC IE -----------------------------------start*/ + + /* Get WSC IE from Probe Rsp */ + IEfoundtimes = 0; + len = 0; + + ptmp = pframe + WLAN_HDR_A3_LEN + _PROBERSP_IE_OFFSET_ ; + for (;;) + { + ptmp = get_ie(ptmp, _WPS_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBERSP_IE_OFFSET_ - len); + + if (ptmp) { + if (!memcmp(ptmp+2, WSC_IE_OUI, 4)) { + + IEfoundtimes ++; + memcpy(wscIEPtr , ptmp+6 ,len-4); + wscIEPtr+= (len-4); + } + } + else{ + break; + } + ptmp = ptmp + len + 2; + + } + + if(IEfoundtimes){ + wscIElen = (int)(((unsigned long)wscIEPtr)-((unsigned long)ReAssem_wscie)); + + if(IEfoundtimes>1){ + P2P_DEBUG("ReAssembly WSC IE\n"); + } + + if(wscIElen > MAX_REASSEM_P2P_IE){ + P2P_DEBUG("\n\n ReAssem WSC IE exceed MAX_REASSEM_P2P_IE , chk!!!\n\n"); + return 0; + } + + }else{ + P2P_DEBUG("no found wsc IE \n"); + return 0 ; + } + /*----------------------------find wsc IE -----------------------------------end*/ + + + /*--- record rx form which channel from _DSSET_IE_ for later use---*/ + ptmp = get_ie(pframe + WLAN_HDR_A3_LEN + _PROBERSP_IE_OFFSET_, _DSSET_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBERSP_IE_OFFSET_); + + + if (ptmp != NULL){ + channel_tmp = *(ptmp+2); + }else{ + channel_tmp = priv->site_survey->ss_channel; + } + /*--- record rx form which channel from _DSSET_IE_ for later use---*/ + + + + /*-----chk target is GO or device-----*/ + //p2pIEPtr = ReAssem_p2pie; + role = p2p_get_role(priv,ReAssem_p2pie,p2pIElen); + + if(role == R_P2P_DEVICE){ + + p2p_get_device_info(priv,ReAssem_p2pie,p2pIElen,&p2p_devic_info); + + } + else if(role == R_P2P_GO){ + + if(p2p_get_GO_p2p_info(priv,ReAssem_p2pie,p2pIElen,&p2p_devic_info)==FAIL){ + /*no include device addr in P2P IE*/ + memcpy(p2p_devic_info.dev_address , pfrinfo->sa ,6); + } + + p2p_get_GO_wsc_info(priv,ReAssem_wscie,wscIElen,&p2p_devic_info); + } + /*-----chk target is GO or device-----*/ + + + /*---find free site_survey bss---*/ + if(priv->site_survey->count_backup==0){ + index=0; + priv->site_survey->count_backup++; + }else{ + // search if exist + for(idx=0 ; idxsite_survey->count_backup ; idx++){ + if(!memcmp(priv->site_survey->bss_backup[idx].p2paddress + ,p2p_devic_info.dev_address ,6)) + { + exist=1; + index = idx; + break; + } + } + if(exist==0){ + index = idx; + priv->site_survey->count_backup++; + } + } + + // now recored this bss info + priv->site_survey->bss_backup[index].channel = channel_tmp ; + priv->site_survey->bss_backup[index].p2prole = role; + + memcpy(priv->site_survey->bss_backup[index].p2paddress,p2p_devic_info.dev_address ,6); + //memcpy(priv->site_survey->bss_backup[index].p2pdevname , p2p_devic_info.devname ,33); + strcpy(priv->site_survey->bss_backup[index].p2pdevname , p2p_devic_info.devname); + priv->site_survey->bss_backup[index].p2pwscconfig = p2p_devic_info.config_method; + + if(role == R_P2P_GO){ + memcpy(priv->site_survey->bss_backup[index].ssid , SsidPtr+2 , ssidlen); + priv->site_survey->bss_backup[index].ssid[ssidlen]='\0'; + //P2P_DEBUG("ssid=%s\n",priv->site_survey->bss_backup[index].ssid); + } + + return SUCCESS; +} + +#endif + +#ifdef CONFIG_IEEE80211W_CLI +unsigned char SHA256_AKM_SUITE[] = {0x00, 0x0F, 0xAC, 0x06}; +unsigned char Doll1X_SHA256_AKM_SUITE[] = {0x00, 0x0F, 0xAC, 0x05}; +unsigned char Doll1X_AKM_SUITE[] = {0x00, 0x0F, 0xAC, 0x01}; + +void add_sha256_akm(struct rtl8192cd_priv *priv) +{ + WPA_GLOBAL_INFO *pGblInfo = priv->wpa_global_info; + unsigned char AKM_buff[KEY_AKM_LEN]; + + OCTET_STRING AKM; + memcpy(AKM_buff, SHA256_AKM_SUITE, KEY_AKM_LEN); + AKM.Octet = AKM_buff; + AKM.Length = KEY_AKM_LEN; + Message_setSha256AKM(pGblInfo->AuthInfoElement, AKM); +} +#endif + +/** + * @brief After site survey, collect BSS information to site_survey->bss[index] + * + * The function can find site + * Later finish site survey, call the function get BSS informat. + */ +int collect_bss_info(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + int i, index, len=0; + unsigned char *addr, *p, *pframe, *sa, channel=0; + UINT32 basicrate=0, supportrate=0, hiddenAP=0; + UINT16 val16; + struct wifi_mib *pmib; + DOT11_WPA_MULTICAST_CIPHER wpaMulticastCipher; + unsigned char OUI1[] = {0x00, 0x50, 0xf2, 0x01}; + DOT11_WPA2_MULTICAST_CIPHER wpa2MulticastCipher; + unsigned char OUI2[] = {0x00, 0x0f, 0xac}; + +#ifdef P2P_SUPPORT + static unsigned char ReAssem_p2pie[MAX_REASSEM_P2P_IE]; + int IEfoundtimes=0; + unsigned char *p2pIEPtr = ReAssem_p2pie ; + int p2pIElen=0; +#endif + +#ifdef SUPPORT_MULTI_PROFILE + int jdx=0; + int found=0; + int ssid_len=0; +#endif + + pframe = get_pframe(pfrinfo); +#ifdef CONFIG_RTK_MESH +// GANTOE for site survey 2008/12/25 ==== + if(pfrinfo->is_11s) + addr = GetAddr2Ptr(pframe); + else +#endif + addr = GetAddr3Ptr(pframe); + + sa = GetAddr2Ptr(pframe); + pmib = GET_MIB(priv); + +#ifdef WIFI_11N_2040_COEXIST + if (priv->pmib->dot11nConfigEntry.dot11nCoexist && + (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G)) && ( +#ifdef CLIENT_MODE + (OPMODE & WIFI_STATION_STATE) || +#endif + priv->pshare->is_40m_bw)) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, + &len, pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p == NULL) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) + channel = *(p+2); + if (OPMODE & WIFI_AP_STATE) { + if (channel && (channel <= 14) && (priv->pmib->dot11nConfigEntry.dot11nCoexist_ch_chk ? + (channel != priv->pmib->dot11RFEntry.dot11channel) : 1)) { + if(!priv->bg_ap_timeout) { + priv->bg_ap_timeout = 60; +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + } + priv->bg_ap_timeout = 60; + } + } +#ifdef CLIENT_MODE + else if ((OPMODE & WIFI_STATION_STATE) && priv->coexist_connection) { + if (channel && (channel <= 14)) { +#if 0 +//#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if(!priv->bg_ap_timeout) { + priv->bg_ap_timeout = 180; + update_RAMask_to_FW(priv, 1); + } +#endif + priv->bg_ap_timeout = 180; + priv->bg_ap_timeout_ch[channel-1] = 180; + channel = 0; + } + } +#endif + } +#ifdef CLIENT_MODE + else if ((OPMODE & WIFI_STATION_STATE) && priv->coexist_connection) { + /* + * check if there is any 40M intolerant field set by other 11n AP + */ + struct ht_cap_elmt *ht_cap=(struct ht_cap_elmt *)(p+2); + if (cpu_to_le16(ht_cap->ht_cap_info) & _HTCAP_40M_INTOLERANT_) + priv->intolerant_timeout = 180; + } +#endif + } +#endif + + if (priv->site_survey->count >= MAX_BSS_NUM) + return 0; + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) + channel = *(p+2); + else { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) + channel = *(p+2); + else { + if (priv->site_survey->ss_channel > 14 && !priv->site_survey->defered_ss) + channel = priv->site_survey->ss_channel; + else { + DEBUG_INFO("Beacon/Probe rsp doesn't carry channel info\n"); + return SUCCESS; + } + } + } + +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(priv->simple_config_status == 2 || priv->simple_config_status == 3) + { + if(!memcmp(priv->pmib->dot11StationConfigEntry.dot11DesiredBssid, sa, MACADDRLEN)) { + int found_target_bss = 0; + + for(i=0; isite_survey->count; i++) { + if(!memcmp(priv->pmib->dot11StationConfigEntry.dot11DesiredBssid, priv->site_survey->bss[i].bssid, MACADDRLEN)) { + found_target_bss =1; + break; + } + } + + if(!found_target_bss) + goto collect_this_bss; + } + } +#endif + + for(i=0; isite_survey->count; i++) { + if (!memcmp((void *)addr, priv->site_survey->bss[i].bssid, MACADDRLEN)) { +#if defined(CLIENT_MODE) && defined(WIFI_WMM) && defined(WMM_APSD) // WMM STA + if ((OPMODE & WIFI_STATION_STATE) && QOS_ENABLE && APSD_ENABLE + && (channel == priv->site_survey->bss[i].channel)) { // get WMM IE / WMM Parameter IE + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + for (;;) { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, WMM_PARA_IE, 6)) { + priv->site_survey->bss[i].t_stamp[1] |= BIT(0); // set t_stamp[1] bit 0 when AP supports WMM + + if (*(p+8) & BIT(7)) + priv->site_survey->bss[i].t_stamp[1] |= BIT(3); // set t_stamp[1] bit 3 when AP supports UAPSD + else + priv->site_survey->bss[i].t_stamp[1] &= ~(BIT(3)); // reset t_stamp[1] bit 3 when AP not support UAPSD + break; + } + } else { + priv->site_survey->bss[i].t_stamp[1] &= ~(BIT(0)|BIT(3)); // reset t_stamp[1] bit 0 when AP not support WMM & UAPSD + break; + } + p = p + len + 2; + } + } +#endif + + if ((unsigned char)pfrinfo->rssi > priv->site_survey->bss[i].rssi) { + priv->site_survey->bss[i].rssi = (unsigned char)pfrinfo->rssi; +#ifdef WIFI_SIMPLE_CONFIG + priv->site_survey->wscie[i].rssi = priv->site_survey->bss[i].rssi; +#endif +#if defined(WIFI_WPAS) || defined(RTK_NL80211) + priv->site_survey->wpa_ie[i].rssi = priv->site_survey->bss[i].rssi; + priv->site_survey->rsn_ie[i].rssi = priv->site_survey->bss[i].rssi; +#endif + if (channel == priv->site_survey->bss[i].channel) { + if ((unsigned char)pfrinfo->sq > priv->site_survey->bss[i].sq) + priv->site_survey->bss[i].sq = (unsigned char)pfrinfo->sq; + } else { + priv->site_survey->bss[i].channel = channel; + priv->site_survey->bss[i].sq = (unsigned char)pfrinfo->sq; + } + } + return SUCCESS; + } + } + + // checking SSID + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _SSID_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if ((p == NULL) || // NULL AP case 1 + (len == 0) || // NULL AP case 2 + (*(p+2) == '\0')) // NULL AP case 3 (like 8181/8186) + { + if (priv->ss_req_ongoing && pmib->miscEntry.show_hidden_bss) + hiddenAP = 1; + else if (priv->auto_channel == 1) + hiddenAP = 1; +#ifdef CONFIG_RTK_MESH + else if(pfrinfo->is_11s) + hiddenAP = 1; +#endif + else { +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_STATION_STATE) && + //!priv->ss_req_ongoing && //20131218 , mark it for hidden + dfs ch AP connection + // !priv->auto_channel && + is_passive_channel(priv , priv->pmib->dot11StationConfigEntry.dot11RegDomain, priv->site_survey->ss_channel)) + { + /*For eg: ch60 now and hidden_ap_found=1 ; next time ss_timer will keep at ch60=> issue probe_req; next time ss_timer change to ch64 and on going... + hidden_ap_found status machine as below + 1) 0->1,1st ch60 + next time + 2)1->2, 2nd ch 60, and don't 2->1(chk in here) else will bring loop,ch 60,60,60,60,60......util hidden AP gone + */ + if( priv->site_survey->hidden_ap_found != HIDE_AP_FOUND_DO_ACTIVE_SSAN){ + //STADEBUG("hidden_ap_found=1\n"); + priv->site_survey->hidden_ap_found = HIDE_AP_FOUND; + } + } +#endif + DEBUG_INFO("drop beacon/probersp due to null ssid\n"); + return 0; + } + } + + // if scan specific SSID + if (priv->ss_ssidlen > 0) + { + /*when multiProfile enable,we send probe_req to all dev on profiles list , so chk if ssid match with ssid on profiles list*/ +#ifdef SUPPORT_MULTI_PROFILE + if (priv->pmib->ap_profile.enable_profile && priv->pmib->ap_profile.profile_num > 0) { + found = 0; + for(jdx=0;jdxpmib->ap_profile.profile_num;jdx++) { + ssid_len = strlen(priv->pmib->ap_profile.profile[jdx].ssid); + if ((ssid_len == len) && !memcmp(priv->pmib->ap_profile.profile[jdx].ssid, p+2, len)) { + //STADEBUG("Found ssid=%s,jdx=%d\n", priv->pmib->ap_profile.profile[jdx].ssid , jdx); + found = 1; + break; + } + } + + if(found == 0) + return 0; + } + else +#endif + if ((priv->ss_ssidlen != len) || memcmp(priv->ss_ssid, p+2, len)){ + + return 0; + } + } + +#ifdef CLIENT_MODE +// mantis#2523 + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _SSID_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if ( p && (SSID_LEN == len) && !memcmp(SSID, p+2, len)) { + memcpy(priv->rx_timestamp, pframe+WLAN_HDR_A3_LEN, 8); + } +#endif + + //printk("priv->ss_ssid = %s, priv->ss_ssidlen=%d\n", priv->ss_ssid, priv->ss_ssidlen); + + // if scan specific SSID && WPA2 enabled + if (priv->ss_ssidlen > 0) { + // search WPA2 IE + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _RSN_IE_2_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + // RSN IE + // 0 1 23 4567 + // ID Len Versin GroupCipherSuite +#ifdef CONFIG_IEEE80211W_CLI + if ((2 == WPA_GET_LE16(p+14))) { //AKM num >= 2 + if (!memcmp((p+20), SHA256_AKM_SUITE, sizeof(SHA256_AKM_SUITE))) { + priv->support_sha256 = TRUE; + add_sha256_akm(priv); + } + } else if (!memcmp((p+16), SHA256_AKM_SUITE, sizeof(SHA256_AKM_SUITE))) { + priv->support_sha256 = TRUE; + add_sha256_akm(priv); + } else + priv->support_sha256 = FALSE; +#endif + + if ((len > 7) && (pmib->dot11RsnIE.rsnie[0] == _RSN_IE_2_) && + (pmib->dot11RsnIE.rsnie[7] != *(p+7)) && + !memcmp((p + 4), OUI2, 3)) { + // set WPA2 Multicast Cipher as same as AP's + //printk("WPA2 Multicast Cipher = %d\n", *(p+7)); + pmib->dot11RsnIE.rsnie[7] = *(p+7); + } +#ifndef WITHOUT_ENQUEUE + wpa2MulticastCipher.EventId = DOT11_EVENT_WPA2_MULTICAST_CIPHER; + wpa2MulticastCipher.IsMoreEvent = 0; + wpa2MulticastCipher.MulticastCipher = *(p+7); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&wpa2MulticastCipher, + sizeof(DOT11_WPA2_MULTICAST_CIPHER)); +#endif + event_indicate(priv, NULL, -1); + + } + } + + // david, reported multicast cipher suite for WPA + // if scan specific SSID && WPA2 enabled + if (priv->ss_ssidlen > 0) { + // search WPA IE, should skip that not real RSNIE (eg. Asus WL500g-Deluxe) + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + len = 0; + do { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if ((len > 11) && (pmib->dot11RsnIE.rsnie[0] == _RSN_IE_1_) && + (pmib->dot11RsnIE.rsnie[11] != *(p+11)) && + !memcmp((p + 2), OUI1, 4)) { + // set WPA Multicast Cipher as same as AP's + pmib->dot11RsnIE.rsnie[11] = *(p+11); + +#ifndef WITHOUT_ENQUEUE + wpaMulticastCipher.EventId = DOT11_EVENT_WPA_MULTICAST_CIPHER; + wpaMulticastCipher.IsMoreEvent = 0; + wpaMulticastCipher.MulticastCipher = *(p+11); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&wpaMulticastCipher, + sizeof(DOT11_WPA_MULTICAST_CIPHER)); +#endif + event_indicate(priv, NULL, -1); + } + } + if (p != NULL) + p = p + 2 + len; + } while (p != NULL); + } + + for(i=0; iavailable_chnl_num; i++) { + if (channel == priv->available_chnl[i]) + break; + } + if (i == priv->available_chnl_num) // receive the adjacent channel that is not our domain + return 0; + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + for(i=0; ipktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + for(i=0; idot11BssType.net_work_type & WIRELESS_11B)){ + if (((basicrate & 0xff0) == 0) && ((supportrate & 0xff0) == 0)){ + return 0; + } + } + + if (!(pmib->dot11BssType.net_work_type & WIRELESS_11G)){ + if (((basicrate & 0xf) == 0) && ((supportrate & 0xf) == 0)){ + return 0; + } + } + } +#ifdef P2P_SUPPORT + if((OPMODE & WIFI_P2P_SUPPORT) && ((P2PMODE == P2P_PRE_CLIENT))){ + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_ ; + + /*support ReAssemble*/ + for (;;){ + + p = get_ie(p, _P2P_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_ - len); + if (p) { + if (!memcmp(p+2, WFA_OUI_PLUS_TYPE, 4)) { + IEfoundtimes ++; + memcpy(p2pIEPtr , p+2+4 ,len-4); + p2pIEPtr+= (len-4); + } + } + else{ + break; + } + p = p + len + 2; + + } + + if(IEfoundtimes){ + if(IEfoundtimes>1){ + P2P_DEBUG("ReAssembly p2p IE\n"); + } + p2pIElen = (int)(((unsigned long)p2pIEPtr)-((unsigned long)ReAssem_p2pie)); + + if(p2pIElen > MAX_REASSEM_P2P_IE){ + P2P_DEBUG("\n\n reassemble P2P IE exceed MAX_REASSEM_P2P_IE , chk!!!\n\n"); + return 0; + }else{ + /*if target AP support management function ; skip it*/ + if(P2P_filter_manage_ap(priv , ReAssem_p2pie , p2pIElen )){ + return 0; + } + } + } + + } +#endif + + +#if defined(CONFIG_RTL_SIMPLE_CONFIG) +collect_this_bss: +#endif + /* + * okay, recording this bss... + */ + index = priv->site_survey->count; + priv->site_survey->count++; + + memcpy(priv->site_survey->bss[index].bssid, addr, MACADDRLEN); + + if (hiddenAP) { + priv->site_survey->bss[index].ssidlen = 0; + memset((void *)(priv->site_survey->bss[index].ssid),0, 32); + } + else { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _SSID_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + priv->site_survey->bss[index].ssidlen = len; + memcpy((void *)(priv->site_survey->bss[index].ssid), (void *)(p+2), len); + /*add for sorting by profile */ + #ifdef WIFI_SIMPLE_CONFIG + memcpy((void *)(priv->site_survey->wscie[index].ssid), (void *)(p+2), len); + #endif + + #if defined(WIFI_WPAS) || defined(RTK_NL80211) + memcpy((void *)(priv->site_survey->wpa_ie[index].ssid), (void *)(p+2), len); + memcpy((void *)(priv->site_survey->rsn_ie[index].ssid), (void *)(p+2), len); + #endif + + } +#ifdef CONFIG_RTK_MESH + // GANTOE for site survey 2008/12/25 ==== + //Mesh ID + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _MESH_ID_IE_, (int *)&len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if(NULL == p) + { + priv->site_survey->bss[index].meshidlen = 0; + priv->site_survey->bss[index].meshid[0] = '\0'; + } + else + { + priv->site_survey->bss[index].meshidlen = (len > MESH_ID_LEN ? MESH_ID_LEN : len); + memcpy((void *)(priv->site_survey->bss[index].meshid), (void *)(p + 2), priv->site_survey->bss[index].meshidlen); + } +#endif + + // we use t_stamp to carry other info so don't get timestamp here +#if 0 + memcpy(&val32, (pframe + WLAN_HDR_A3_LEN), 4); + priv->site_survey->bss[index].t_stamp[0] = le32_to_cpu(val32); + + memcpy(&val32, (pframe + WLAN_HDR_A3_LEN + 4), 4); + priv->site_survey->bss[index].t_stamp[1] = le32_to_cpu(val32); +#endif + +#ifdef RTK_NL80211 + unsigned long long val64; + memcpy(&val64, (pframe + WLAN_HDR_A3_LEN), 8); + priv->site_survey->bss[index].timestamp = le64_to_cpu(val64); +#endif + + memcpy(&val16, (pframe + WLAN_HDR_A3_LEN + 8 ), 2); + priv->site_survey->bss[index].beacon_prd = le16_to_cpu(val16); + + memcpy(&val16, (pframe + WLAN_HDR_A3_LEN + 8 + 2), 2); + priv->site_survey->bss[index].capability = le16_to_cpu(val16); + + if ((priv->site_survey->bss[index].capability & BIT(0)) && + !(priv->site_survey->bss[index].capability & BIT(1))) + priv->site_survey->bss[index].bsstype = WIFI_AP_STATE; + else if (!(priv->site_survey->bss[index].capability & BIT(0)) && + (priv->site_survey->bss[index].capability & BIT(1))) + priv->site_survey->bss[index].bsstype = WIFI_ADHOC_STATE; + else + priv->site_survey->bss[index].bsstype = 0; + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _TIM_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) + priv->site_survey->bss[index].dtim_prd = *(p+3); + + priv->site_survey->bss[index].channel = channel; + priv->site_survey->bss[index].basicrate = basicrate; + priv->site_survey->bss[index].supportrate = supportrate; + + memcpy(priv->site_survey->bss[index].bdsa, sa, MACADDRLEN); + + priv->site_survey->bss[index].rssi = (unsigned char)pfrinfo->rssi; + priv->site_survey->bss[index].sq = (unsigned char)pfrinfo->sq; + +#ifdef WIFI_SIMPLE_CONFIG + priv->site_survey->wscie[index].rssi = priv->site_survey->bss[index].rssi; +#endif +#if defined(WIFI_WPAS) || defined(RTK_NL80211) + priv->site_survey->wpa_ie[index].rssi = priv->site_survey->bss[index].rssi; + priv->site_survey->rsn_ie[index].rssi = priv->site_survey->bss[index].rssi; +#endif + + + if (channel >= 36) + priv->site_survey->bss[index].network |= WIRELESS_11A; + else { + if ((basicrate & 0xff0) || (supportrate & 0xff0)) + priv->site_survey->bss[index].network |= WIRELESS_11G; + if ((basicrate & 0xf) || (supportrate & 0xf)) + priv->site_survey->bss[index].network |= WIRELESS_11B; + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + struct ht_cap_elmt *ht_cap=(struct ht_cap_elmt *)(p+2); + if (cpu_to_le16(ht_cap->ht_cap_info) & _HTCAP_SUPPORT_CH_WDTH_) + priv->site_survey->bss[index].t_stamp[1] |= BIT(1); + else + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(1)); + priv->site_survey->bss[index].network |= WIRELESS_11N; +#if defined(RTK_NL80211) + memcpy(&priv->site_survey->bss[index].ht_cap, ht_cap, 26); +#endif + } else { + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(1)); + } +#ifdef RTK_AC_SUPPORT + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTCapability, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if ((p != NULL) && (len <= sizeof(struct vht_cap_elmt))) { + priv->site_survey->bss[index].network |= WIRELESS_11AC; + } + + //Check if 80M AP + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTOperation, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + priv->site_survey->bss[index].t_stamp[1] &= ~(BSS_BW_MASK << BSS_BW_SHIFT); + + if ((p != NULL) && (len <= sizeof(struct vht_oper_elmt))) { + if (p[2] == 1) { + priv->site_survey->bss[index].t_stamp[1] |= (HT_CHANNEL_WIDTH_AC_80 << BSS_BW_SHIFT); + } + } +#endif + +#if defined(RTK_NL80211) && defined(NOT_RTK_BSP) + memcpy(priv->site_survey->bss[index].all_ie, + pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + priv->site_survey->bss[index].all_ie_len = pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_; +#endif + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if (p != NULL) { + struct ht_info_elmt *ht_info=(struct ht_info_elmt *)(p+2); + if (!(ht_info->info0 & _HTIE_STA_CH_WDTH_)) + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(1)|BIT(2)); + else { + if ((ht_info->info0 & _HTIE_2NDCH_OFFSET_BL_) == _HTIE_2NDCH_OFFSET_NO_) + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(1)|BIT(2)); + else + if ((ht_info->info0 & _HTIE_2NDCH_OFFSET_BL_) == _HTIE_2NDCH_OFFSET_BL_) + priv->site_survey->bss[index].t_stamp[1] |= BIT(2); + else + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(2)); + } +#if defined(RTK_NL80211) + memcpy(&priv->site_survey->bss[index].ht_info, ht_info, 22); +#endif + } + else + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(1)|BIT(2)); + + // get WPA/WPA2 information + get_security_info(priv, pfrinfo, index); + +#ifdef WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum) { + // look for ERP rate. if no ERP rate existed, thought it is a legacy AP + unsigned char supportedRates[32]; + int supplen=0; + + struct stat_info *pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + if (pstat && (pstat->state & WIFI_WDS)) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, + _SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p) { + if (len>8) + len=8; + memcpy(&supportedRates[supplen], p+2, len); + supplen += len; + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, + _EXT_SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p) { + if (len>8) + len=8; + memcpy(&supportedRates[supplen], p+2, len); + supplen += len; + } + + get_matched_rate(priv, supportedRates, &supplen, 0); + update_support_rate(pstat, supportedRates, supplen); + if (supplen == 0) + pstat->current_tx_rate = 0; + else { + if (priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate == 0) { + pstat->current_tx_rate = find_rate(priv, pstat, 1, 0); + //pstat->upper_tx_rate = 0; // unused + } + } + + // Customer proprietary IE + if (priv->pmib->miscEntry.private_ie_len) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, + priv->pmib->miscEntry.private_ie[0], &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p) { + memcpy(pstat->private_ie, p, len + 2); + pstat->private_ie_len = len + 2; + } + } + + // Realtek proprietary IE + pstat->is_realtek_sta = FALSE; + pstat->IOTPeer = HT_IOT_PEER_UNKNOWN; + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; len = 0; + for (;;) { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, Realtek_OUI, 3) && *(p+2+3) == 2) { /*found realtek out and type == 2*/ + pstat->is_realtek_sta = TRUE; + pstat->IOTPeer = HT_IOT_PEER_REALTEK; + + if (*(p+2+3+2) & RTK_CAP_IE_AP_CLIENT) + pstat->IOTPeer = HT_IOT_PEER_RTK_APCLIENT; + + if(*(p+2+3+2) & RTK_CAP_IE_WLAN_8192SE) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_92SE; + + if (*(p+2+3+2) & RTK_CAP_IE_USE_AMPDU) + pstat->is_forced_ampdu = TRUE; + else + pstat->is_forced_ampdu = FALSE; +#ifdef RTK_WOW + if (*(p+2+3+2) & RTK_CAP_IE_USE_WOW) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_WOW; +#endif + if (*(p+2+3+2) & RTK_CAP_IE_WLAN_88C92C) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_81XX; + + if (*(p+2+3+3) & ( RTK_CAP_IE_8812_BCUT | RTK_CAP_IE_8812_CCUT)) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_8812; + break; + } + } + else + break; + + p = p + len + 2; + } + +#ifdef WIFI_WMM + if (QOS_ENABLE) { + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + for (;;) { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, WMM_PARA_IE, 6)) { + pstat->QosEnabled = 1; + break; + } + } + else { + pstat->QosEnabled = 0; + break; + } + p = p + len + 2; + } + } +#endif + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + pstat->ht_cap_len = len; + memcpy((unsigned char *)&pstat->ht_cap_buf, p+2, len); + if (cpu_to_le16(pstat->ht_cap_buf.ht_cap_info) & _HTCAP_AMSDU_LEN_8K_) { + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 7935 - sizeof(struct wlan_hdr); + } + else { + pstat->is_8k_amsdu = 0; + pstat->amsdu_level = 3839 - sizeof(struct wlan_hdr); + } + } + else + pstat->ht_cap_len = 0; + } + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)){ + pstat->tx_bw = HT_CHANNEL_WIDTH_20_40; + }else{ + pstat->tx_bw = HT_CHANNEL_WIDTH_20; + } +#ifdef RTK_AC_SUPPORT + //WDS-VHT support + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) + { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTCapability, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if ((p != NULL) && (len <= sizeof(struct vht_cap_elmt))) { + pstat->vht_cap_len = len; + memcpy((unsigned char *)&pstat->vht_cap_buf, p+2, len); + //WDEBUG("vht_cap len = %d \n",len); + //WDEBUG("vht_cap vht_cap_info:%04X \n",pstat->vht_cap_buf.vht_cap_info); + //WDEBUG("vht_cap vht_support_mcs[0]=[%04X] ; vht_support_mcs[1]=[%04X] \n", pstat->vht_cap_buf.vht_support_mcs[0],pstat->vht_cap_buf.vht_support_mcs[1]); + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTOperation, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if ((p != NULL) && (len <= sizeof(struct vht_oper_elmt))) { + pstat->vht_oper_len = len; + memcpy((unsigned char *)&pstat->vht_oper_buf, p+2, len); + //WDEBUG("vht_oper len = %d \n",len); + //WDEBUG("vht_oper: 0[%02x],1[%02x],2[%02x] \n",pstat->vht_oper_buf.vht_oper_info[0],pstat->vht_oper_buf.vht_oper_info[1],pstat->vht_oper_buf.vht_oper_info[2]); + //WDEBUG("vht_oper [%02X]\n",pstat->vht_oper_buf.vht_basic_msc); + } + + + if ((pstat->vht_cap_len)) { + switch(cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & 0x3) { + default: + case 0: + pstat->is_8k_amsdu = 0; + pstat->amsdu_level = 3895 - sizeof(struct wlan_hdr); + break; + case 1: + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 7991 - sizeof(struct wlan_hdr); + break; + case 2: + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 11454 - sizeof(struct wlan_hdr); + break; + } + + if ((priv->vht_oper_buf.vht_oper_info[0] == 1) && (pstat->vht_oper_buf.vht_oper_info[0] == 1)) { + pstat->tx_bw = HT_CHANNEL_WIDTH_80; + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_80; + //WDEBUG("pstat->tx_bw=80M\n"); + } + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTOperatingMode, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if ((p != NULL) && (len == 1)) { + // check self capability.... + if((p[2] &3) <= priv->pmib->dot11nConfigEntry.dot11nUse40M) + pstat->tx_bw = p[2] &3; + pstat->nss = ((p[2]>>4)&0x7)+1; + printk("[%s %d]receive opering mode data = %02X \n",__FUNCTION__,__LINE__ ,p[2]); + } + + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + UpdateHalRAMask8812(priv, pstat, 3); + //WDEBUG("UpdateHalRAMask8812\n"); + UpdateHalMSRRPT8812(priv, pstat, INCREASE); + //WDEBUG("UpdateHalMSRRPT8812\n"); + } +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)){ + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + } +#endif + + + } + } +#endif + +#ifdef WIFI_WMM // WMM STA + if (QOS_ENABLE) { // get WMM IE / WMM Parameter IE + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + for (;;) { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if ((!memcmp(p+2, WMM_IE, 6)) || (!memcmp(p+2, WMM_PARA_IE, 6))) { + priv->site_survey->bss[index].t_stamp[1] |= BIT(0); // set t_stamp[1] bit 0 when AP supports WMM +#if defined(CLIENT_MODE) && defined(WMM_APSD) + if ((OPMODE & WIFI_STATION_STATE) && APSD_ENABLE) { + if (!memcmp(p+2, WMM_PARA_IE, 6)) { + if (*(p+8) & BIT(7)) + priv->site_survey->bss[index].t_stamp[1] |= BIT(3); // set t_stamp[1] bit 3 when AP supports UAPSD + else + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(3)); // reset t_stamp[1] bit 3 when AP not support UAPSD + break; + } else { + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(3)); // reset t_stamp[1] bit 3 when AP not support UAPSD + } + } else +#endif + break; + } + } else { + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(0)); // reset t_stamp[1] bit 0 when AP not support WMM +#if defined(CLIENT_MODE) && defined(WMM_APSD) + if ((OPMODE & WIFI_STATION_STATE) && APSD_ENABLE) + priv->site_survey->bss[index].t_stamp[1] &= ~(BIT(3)); // reset t_stamp[1] bit 3 when AP not support UAPSD +#endif + break; + } + p = p + len + 2; + } + } +#endif + +#if defined(WIFI_WPAS) || defined(RTK_NL80211) + + priv->site_survey->rsn_ie[index].rsn_ie_len = 0; + priv->site_survey->wpa_ie[index].wpa_ie_len = 0; + + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + p = get_ie(p, _RSN_IE_2_, &len, + pfrinfo->pktlen - (p - pframe)); + if ((p != NULL) && (len > 7)) { + priv->site_survey->rsn_ie[index].rsn_ie_len = len + 2; + memcpy(priv->site_survey->rsn_ie[index].data, p, len + 2); + } + + len = 0; + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + do { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if ((p != NULL) && (len > 11) + && (!memcmp((p + 2), OUI1, 4))) { + priv->site_survey->wpa_ie[index].wpa_ie_len = len + 2; + memcpy(priv->site_survey->wpa_ie[index].data, p, len + 2); + } + if (p != NULL) + p = p + 2 + len; + } while (p != NULL); + +#endif + + +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + { + if(!memcmp(priv->pmib->dot11StationConfigEntry.dot11DesiredBssid, sa, 6)) { + int bss_bw = HT_CHANNEL_WIDTH_20_40; + int bss_offset = 0; + +#ifdef RTK_AC_SUPPORT + if(GET_CHIP_VER(priv)==VERSION_8812E || GET_CHIP_VER(priv)==VERSION_8881A){ + if((priv->site_survey->bss[index].t_stamp[1] & (BSS_BW_MASK << BSS_BW_SHIFT)) + == (HT_CHANNEL_WIDTH_80 << BSS_BW_SHIFT)) + bss_bw = HT_CHANNEL_WIDTH_80; + } +#endif + + if ((priv->site_survey->bss[index].t_stamp[1] & (BIT(1) | BIT(2))) == (BIT(1) | BIT(2))) + bss_offset = HT_2NDCH_OFFSET_BELOW; + else if ((priv->site_survey->bss[index].t_stamp[1] & (BIT(1) | BIT(2))) == BIT(1)) + bss_offset = HT_2NDCH_OFFSET_ABOVE; + else { + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_10) + bss_bw = HT_CHANNEL_WIDTH_10; + else if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5) + bss_bw = HT_CHANNEL_WIDTH_5; + else + bss_bw = HT_CHANNEL_WIDTH_20; + + bss_offset = HT_2NDCH_OFFSET_DONTCARE; + } + + + if(channel){ + + if(priv->simple_config_could_fix) + if(priv->simple_config_status == 2 || priv->simple_config_status == 3) { + + if(priv->pmib->dot11StationConfigEntry.sc_fix_channel == 0) { + if(priv->pmib->dot11StationConfigEntry.sc_debug) + panic_printk("Simple Config switch to remote AP's channel %d BW %d Offset %d\n", + channel, bss_bw, bss_offset); + + //sync channel + priv->pmib->dot11RFEntry.dot11channel = channel; + + //sync bw + priv->pmib->dot11nConfigEntry.dot11nUse40M = bss_bw; + priv->pshare->CurrentChannelBW = bss_bw; + priv->pshare->is_40m_bw = bss_bw; + + //sync offset + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = bss_offset; + priv->pshare->offset_2nd_chan = bss_offset; + + SwBWMode(priv, bss_bw, bss_offset); + SwChnl(priv, channel, bss_offset); + + rtk_sc_set_value(SC_FIX_CHANNEL, channel); + priv->pmib->dot11StationConfigEntry.sc_fix_bw = bss_bw; + priv->pmib->dot11StationConfigEntry.sc_fix_offset = bss_offset; + + } + + if(priv->simple_config_status == 3) + rtk_sc_check_security(priv, &(priv->site_survey->bss[index])); + + return SUCCESS; + } + + } + + } + + } +#endif + + + return SUCCESS; +} + + +void assign_tx_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct rx_frinfo *pfrinfo) +{ + int tx_rate=0; + UINT8 rate; + int auto_rate; + +#ifdef WDS + if (pstat->state & WIFI_WDS) { + auto_rate = (priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate==0) ? 1: 0; + tx_rate = priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate; + } + else +#endif + { + auto_rate = priv->pmib->dot11StationConfigEntry.autoRate; + tx_rate = priv->pmib->dot11StationConfigEntry.fixedTxRate; + } + + if (auto_rate || +#ifdef RTK_AC_SUPPORT + ( is_fixedVHTTxRate(priv, pstat) && !(pstat->vht_cap_len)) || +#endif + ( should_restrict_Nrate(priv, pstat) && is_fixedMCSTxRate(priv, pstat))) { +#if 0 + // if auto rate, select highest or lowest rate depending on rssi + if (pfrinfo && pfrinfo->rssi > 30) + pstat->current_tx_rate = find_rate(priv, pstat, 1, 0); + else + pstat->current_tx_rate = find_rate(priv, pstat, 0, 0); +#endif + pstat->current_tx_rate = find_rate(priv, pstat, 1, 0); + + } + else { + // see if current fixed tx rate of mib is existed in supported rates set + rate = get_rate_from_bit_value(tx_rate); + if (match_supp_rate(pstat->bssrateset, pstat->bssratelen, rate)) + tx_rate = (int)rate; + if (tx_rate == 0) // if not found, use highest supported rate for current tx rate + tx_rate = find_rate(priv, pstat, 1, 0); + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A)){ + pstat->current_tx_rate = rate; + }else +#endif + { + pstat->current_tx_rate = tx_rate; + } +// ToDo: +// fixed 2T rate, but STA is 1R... + } + + if ((pstat->MIMO_ps & _HT_MIMO_PS_STATIC_) && is_2T_rate(pstat->current_tx_rate)) { +#ifdef RTK_AC_SUPPORT + if( is_VHT_rate(pstat->current_tx_rate)){ + pstat->current_tx_rate = _NSS1_MCS9_RATE_; + }else +#endif + { + pstat->current_tx_rate = _MCS7_RATE_; // when HT MIMO Static power save is set and rate > MCS7, fix rate to MCS7 + } + } + + + if (pfrinfo) + pstat->rssi = pfrinfo->rssi; // give the initial value to pstat->rssi + + pstat->ht_current_tx_info = 0; + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len) { + if (priv->pshare->is_40m_bw && ((pstat->tx_bw == HT_CHANNEL_WIDTH_20_40)||(pstat->tx_bw == HT_CHANNEL_WIDTH_80))) { + pstat->ht_current_tx_info |= TX_USE_40M_MODE; + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_))) + pstat->ht_current_tx_info |= TX_USE_SHORT_GI; + } + else { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) + pstat->ht_current_tx_info |= TX_USE_SHORT_GI; + } + } + + if (priv->pshare->rf_ft_var.rssi_dump && pfrinfo) + { +#ifdef RTK_AC_SUPPORT + if(is_VHT_rate(pstat->current_tx_rate)) + printk("[%d] rssi=%d%% assign rate %s%d %d\n", pstat->aid, pfrinfo->rssi, + "VHT NSS", (((pstat->current_tx_rate-VHT_RATE_ID)/10)+1), ((pstat->current_tx_rate-VHT_RATE_ID)%10)); + else +#endif + printk("[%d] rssi=%d%% assign rate %s%d\n", pstat->aid, pfrinfo->rssi, + is_MCS_rate(pstat->current_tx_rate)? "MCS" : "", + is_MCS_rate(pstat->current_tx_rate)? (pstat->current_tx_rate-HT_RATE_ID) : pstat->current_tx_rate/2); + } +} + + +// Assign aggregation method automatically. +// We according to the following rule: +// 1. Rtl8190: AMPDU +// 2. Broadcom: AMSDU +// 3. Station who supports only 4K AMSDU receiving: AMPDU +// 4. Others: AMSDU +void assign_aggre_mthod(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len) { +#ifdef RTK_AC_SUPPORT //for 11ac logo + if ((AMPDU_ENABLE) && (AMSDU_ENABLE >= 2)) // + pstat->aggre_mthd = AGGRE_MTHD_MPDU_AMSDU; // AMPDU + AMSDU //5.2.81 + else +#endif + if ((AMPDU_ENABLE == 1) || (AMSDU_ENABLE == 1)) // auto assignment + pstat->aggre_mthd = AGGRE_MTHD_MPDU; + else if ((AMPDU_ENABLE >= 2) && (AMSDU_ENABLE == 0)) + pstat->aggre_mthd = AGGRE_MTHD_MPDU; + else if ((AMPDU_ENABLE == 0) && (AMSDU_ENABLE >= 2)) + pstat->aggre_mthd = AGGRE_MTHD_MSDU; //5.2.38 + else + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + else + pstat->aggre_mthd = AGGRE_MTHD_NONE; + + if (should_restrict_Nrate(priv, pstat) && (pstat->aggre_mthd != AGGRE_MTHD_NONE)) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + +// Client mode IOT issue, Button 2009.07.17 +// we won't restrict N rate with 8190 +#ifdef CLIENT_MODE + if(OPMODE & WIFI_STATION_STATE) + { + if((pstat->IOTPeer !=HT_IOT_PEER_REALTEK_92SE) && pstat->is_realtek_sta && pstat->is_legacy_encrpt) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } +#endif + + if(pstat->sta_in_firmware != 1 && priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _NO_PRIVACY_) + pstat->aggre_mthd = AGGRE_MTHD_NONE; +} + + +void assign_aggre_size(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len) { + if ((priv->pmib->dot11nConfigEntry.dot11nAMPDUSendSz == 8) || + (priv->pmib->dot11nConfigEntry.dot11nAMPDUSendSz == 16) || + (priv->pmib->dot11nConfigEntry.dot11nAMPDUSendSz == 32)) { + if (priv->pmib->dot11nConfigEntry.dot11nAMPDUSendSz == 8) + pstat->diffAmpduSz = 0x44444444; + else if (priv->pmib->dot11nConfigEntry.dot11nAMPDUSendSz == 16) + pstat->diffAmpduSz = 0x88888888; + else + pstat->diffAmpduSz = 0xffffffff; + } else { + unsigned int ampdu_para = pstat->ht_cap_buf.ampdu_para & 0x03; + pstat->diffAmpduSz = RTL_R32(AGGLEN_LMT); + if ((!ampdu_para) || (ampdu_para == 1)) { + if ((pstat->diffAmpduSz & 0xf) > 4*(ampdu_para+1)) + pstat->diffAmpduSz = (pstat->diffAmpduSz & ~0xf) | 0x4*(ampdu_para+1); + if (((pstat->diffAmpduSz & 0xf0) >> 4) > 4*(ampdu_para+1)) + pstat->diffAmpduSz = (pstat->diffAmpduSz & ~0xf0) | 0x40*(ampdu_para+1); + if (((pstat->diffAmpduSz & 0xf00) >> 8) > 4*(ampdu_para+1)) + pstat->diffAmpduSz = (pstat->diffAmpduSz & ~0xf00) | 0x400*(ampdu_para+1); + if (((pstat->diffAmpduSz & 0xf000) >> 12) > 4*(ampdu_para+1)) + pstat->diffAmpduSz = (pstat->diffAmpduSz & ~0xf000) | 0x4000*(ampdu_para+1); + if (((pstat->diffAmpduSz & 0xf0000) >> 16) > 4*(ampdu_para+1)) + pstat->diffAmpduSz = (pstat->diffAmpduSz & ~0xf0000) | 0x40000*(ampdu_para+1); + if (((pstat->diffAmpduSz & 0xf00000) >> 20) > 4*(ampdu_para+1)) + pstat->diffAmpduSz = (pstat->diffAmpduSz & ~0xf00000) | 0x400000*(ampdu_para+1); + if (((pstat->diffAmpduSz & 0xf000000) >> 24) > 4*(ampdu_para+1)) + pstat->diffAmpduSz = (pstat->diffAmpduSz & ~0xf000000) | 0x4000000*(ampdu_para+1); + if (((pstat->diffAmpduSz & 0xf0000000) >> 28) > 4*(ampdu_para+1)) + pstat->diffAmpduSz = (pstat->diffAmpduSz & ~0xf0000000) | 0x40000000*(ampdu_para+1); + } + } + DEBUG_INFO("assign aggregation size: %d\n", 8<<(pstat->ht_cap_buf.ampdu_para & 0x03)); + } +} + +#ifdef SUPPORT_MONITOR +void rtl8192cd_chan_switch_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + if(priv->is_monitor_mode==TRUE) + { + if(((priv->chan_num%priv->available_chnl_num)==0)&&(priv->chan_num>0)) + priv->chan_num = 0; + else + priv->chan_num++; + + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->available_chnl[priv->chan_num], priv->pshare->offset_2nd_chan); + mod_timer(&priv->chan_switch_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pmib->miscEntry.chan_switch_time)); + } +} +#endif + +#ifndef USE_WEP_DEFAULT_KEY +void set_keymapping_wep(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + struct wifi_mib *pmib = GET_MIB(priv); + +// if ((GET_ROOT(priv)->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) && +#ifdef MULTI_MAC_CLONE + if (!IEEE8021X_FUN && +#else + if (!SWCRYPTO && !IEEE8021X_FUN && +#endif + ((pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) || + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_))) + { + pstat->dot11KeyMapping.dot11Privacy = pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + pstat->keyid = pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + if (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) { + pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen = 5; + memcpy(pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKey.skey, + pmib->dot11DefaultKeysTable.keytype[pstat->keyid].skey, 5); + } + else { + pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen = 13; + memcpy(pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKey.skey, + pmib->dot11DefaultKeysTable.keytype[pstat->keyid].skey, 13); + } + + DEBUG_INFO("going to set %s unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_)?"WEP40":"WEP104", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5], pstat->keyid); + if (!SWCRYPTO) { + int retVal; + retVal = CamDeleteOneEntry(priv, pstat->hwaddr, pstat->keyid, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pstat->dot11KeyMapping.keyInCam = FALSE; + } +#ifdef MULTI_MAC_CLONE + if ((OPMODE & WIFI_STATION_STATE) && priv->pmib->ethBrExtInfo.macclone_enable) + retVal = CamAddOneEntry(priv, pstat->sa_addr, pstat->keyid, + pstat->dot11KeyMapping.dot11Privacy<<2, 0, pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKey.skey); + else +#endif + retVal = CamAddOneEntry(priv, pstat->hwaddr, pstat->keyid, + pstat->dot11KeyMapping.dot11Privacy<<2, 0, pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKey.skey); + if (retVal) { + priv->pshare->CamEntryOccupied++; + pstat->dot11KeyMapping.keyInCam = TRUE; + } + else { + if (pstat->aggre_mthd != AGGRE_MTHD_NONE) + pstat->aggre_mthd = AGGRE_MTHD_NONE; + } + } + } +} +#endif + + +/*----------------------------------------------------------------------------- +OnAssocReg: + --> Reply DeAuth or AssocRsp +Capability Info, Listen Interval, SSID, SupportedRates +------------------------------------------------------------------------------*/ +static unsigned int OnAssocReq(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + struct wifi_mib *pmib; + struct stat_info *pstat; + unsigned char *pframe, *p; + unsigned char rsnie_hdr[4]={0x00, 0x50, 0xf2, 0x01}; +#ifdef RTL_WPA2 + unsigned char rsnie_hdr_wpa2[2]={0x01, 0x00}; +#endif + int len; +#ifndef SMP_SYNC + unsigned long flags; +#endif + DOT11_ASSOCIATION_IND Association_Ind; + DOT11_REASSOCIATION_IND Reassociation_Ind; + unsigned char supportRate[32]; + int supportRateNum; + unsigned int status = _STATS_SUCCESSFUL_; + unsigned short frame_type, ie_offset=0, val16; + unsigned int z = 0; + +#ifdef P2P_SUPPORT + unsigned char ReAssem_p2pie[MAX_REASSEM_P2P_IE]; + int IEfoundtimes; + unsigned char *p2pIEPtr = ReAssem_p2pie ; + int p2pIElen; +#endif + pmib = GET_MIB(priv); + pframe = get_pframe(pfrinfo); + pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + + if (!(OPMODE & WIFI_AP_STATE)) + return FAIL; + +#ifdef WDS + if (pmib->dot11WdsInfo.wdsPure) + return FAIL; +#endif + + if (pmib->miscEntry.func_off) + return FAIL; + +#ifdef DFS + if (priv->pshare->rf_ft_var.dfs_det_period) + priv->det_asoc_clear = 500 / priv->pshare->rf_ft_var.dfs_det_period; + else + priv->det_asoc_clear = 50; +#endif + +#ifdef CONFIG_RTK_MESH + +// KEY_MAP_KEY_PATCH_0223 + if((pmib->dot1180211sInfo.mesh_enable && !(GET_MIB(priv)->dot1180211sInfo.mesh_ap_enable)) || pmib->dot1180211sInfo.meshSilence) +// 2008.05.16 +// ((pmib->dot11sKeysTable.dot11Privacy && pmib->dot11sKeysTable.keyInCam == FALSE ) +// ||( (OPMODE & WIFI_AP_STATE) && !(GET_MIB(priv)->dot1180211sInfo.mesh_ap_enable)))) + { + return FAIL; + } +// KEY_MAP_KEY_PATCH_0223 +// 2008.05.16 + +#endif + +#ifdef CONFIG_POWER_SAVE + priv->pshare->xfer_seq++; +#endif + + frame_type = GetFrameSubType(pframe); + if (frame_type == WIFI_ASSOCREQ) + ie_offset = _ASOCREQ_IE_OFFSET_; + else // WIFI_REASSOCREQ + ie_offset = _REASOCREQ_IE_OFFSET_; + + if (pstat == (struct stat_info *)NULL) + { + status = _RSON_CLS2_; + goto asoc_class2_error; + } + + // check if this stat has been successfully authenticated/assocated + if (!((pstat->state) & WIFI_AUTH_SUCCESS)) + { + status = _RSON_CLS2_; + goto asoc_class2_error; + } + +#ifdef NOT_RTK_BSP + if (priv->pmib->dot11StationConfigEntry.supportedStaNum) { + if (priv->assoc_num >= priv->pmib->dot11StationConfigEntry.supportedStaNum) { + DEBUG_ERR("Assoc()Exceed the upper limit of supported clients(%d)...\n",priv->pmib->dot11StationConfigEntry.supportedStaNum); + status = _STATS_UNABLE_HANDLE_STA_; + goto OnAssocReqFail; + } + } +#endif + + if (priv->assoc_reject_on) + { + status = _STATS_OTHER_; + goto OnAssocReqFail; + } +#ifdef CONFIG_IEEE80211W + if (((pstat->state) & WIFI_ASOC_STATE) && + pstat->isPMF && + !pstat->sa_query_timed_out && + pstat->sa_query_count) { + check_sa_query_timeout(pstat); + } + + if (((pstat->state) & WIFI_ASOC_STATE) && + pstat->isPMF && + !pstat->sa_query_timed_out) { + + status = _STATS_ASSOC_REJ_TEMP_; + if (pstat->sa_query_count == 0) { + pstat->sa_query_start = jiffies; + pstat->sa_query_end = jiffies + RTL_MILISECONDS_TO_JIFFIES(SA_QUERY_MAX_TO); + } + if (frame_type == WIFI_ASSOCREQ) + issue_asocrsp(priv, status, pstat, WIFI_ASSOCRSP); + else + issue_asocrsp(priv, status, pstat, WIFI_REASSOCRSP); + + if (pstat->sa_query_count == 0) { + //PMFDEBUG("sa_query_end=%lu, sa_query_start=%lu\n", pstat->sa_query_end, pstat->sa_query_start); + pstat->sa_query_count++; + issue_SA_Query_Req(priv->dev,pstat->hwaddr); + + + if (timer_pending(&pstat->SA_timer)) + del_timer(&pstat->SA_timer); + + pstat->SA_timer.data = (unsigned long) pstat; + pstat->SA_timer.function = rtl8192cd_sa_query_timer; + mod_timer(&pstat->SA_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(SA_QUERY_RETRY_TO)); + + } + return FAIL; + } + pstat->sa_query_timed_out = 0; +#endif +#ifdef CONFIG_RTL_WLAN_DOS_FILTER + if (block_sta_time) + { + int i; + for (i=0; ihwaddr, block_mac[i], 6) == 0) + { + status = _STATS_OTHER_; + goto OnAssocReqFail; + } + } + } +#endif + + /* Rate adpative algorithm */ + if (pstat->check_init_tx_rate) + pstat->check_init_tx_rate = 0; + + // now we should check all the fields... + + // checking SSID + p = get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset); + + if (p == NULL) + { + status = _STATS_FAILURE_; + goto OnAssocReqFail; + } + + if (len == 0) // broadcast ssid, however it is not allowed in assocreq + status = _STATS_FAILURE_; + else + { + // check if ssid match + if (memcmp((void *)(p+2), SSID, SSID_LEN)) + status = _STATS_FAILURE_; + + if (len != SSID_LEN) + status = _STATS_FAILURE_; + } + + // check if the supported is ok + p = get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset); + + if (len > 8) + status = _STATS_RATE_FAIL_; + else if (p == NULL) { + DEBUG_WARN("Rx a sta assoc-req which supported rate is empty!\n"); + // use our own rate set as statoin used + memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); + supportRateNum = AP_BSSRATE_LEN; + } + else { + memcpy(supportRate, p+2, len); + supportRateNum = len; + + p = get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset); + if ((p != NULL) && (len <= 8)) { + memcpy(supportRate+supportRateNum, p+2, len); + supportRateNum += len; + } + } + + + + +#ifdef __DRAYTEK_OS__ + if (status == _STATS_SUCCESSFUL_) { + status = cb_assoc_request(priv->dev, GetAddr2Ptr(pframe), pframe + WLAN_HDR_A3_LEN + _ASOCREQ_IE_OFFSET_, + pfrinfo->pktlen-WLAN_HDR_A3_LEN-_ASOCREQ_IE_OFFSET_); + if (status != _STATS_SUCCESSFUL_) { + DEBUG_ERR("\rReject association from draytek OS, status=%d!\n", status); + goto OnAssocReqFail; + } + } +#endif +#if 0 +#ifdef P2P_SUPPORT + if((OPMODE & WIFI_P2P_SUPPORT)){ + + } + else +#endif + { + if (check_basic_rate(priv, supportRate, supportRateNum) == FAIL) { // check basic rate. jimmylin 2004/12/02 + DEBUG_WARN("Rx a sta assoc-req which basic rates not match! %02X%02X%02X%02X%02X%02X\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + if (priv->pmib->dot11OperationEntry.wifi_specific) { + status = _STATS_RATE_FAIL_; + goto OnAssocReqFail; + } + } + } +#endif + get_matched_rate(priv, supportRate, &supportRateNum, 0); + update_support_rate(pstat, supportRate, supportRateNum); + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + !isErpSta(pstat) && + (priv->pmib->dot11StationConfigEntry.legacySTADeny & WIRELESS_11B)) { + status = _STATS_RATE_FAIL_; + goto OnAssocReqFail; + } + + val16 = cpu_to_le16(*(unsigned short*)((unsigned long)pframe + WLAN_HDR_A3_LEN)); + if (!(val16 & BIT(5))) // NOT use short preamble + pstat->useShortPreamble = 0; + else + pstat->useShortPreamble = 1; + + pstat->state |= WIFI_ASOC_STATE; + + if (status != _STATS_SUCCESSFUL_) + goto OnAssocReqFail; + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType!=wapiDisable) + { + SAVE_INT_AND_CLI(flags); + if (pstat->wapiInfo==NULL) + { + pstat->wapiInfo = (wapiStaInfo*)kmalloc(sizeof(wapiStaInfo), GFP_ATOMIC); + if (pstat->wapiInfo==NULL) + { + /*pstat->wapiInfo->wapiState = ST_WAPI_AE_IDLE;*/ + status = _RSON_UNABLE_HANDLE_; + RESTORE_INT(flags); + goto asoc_class2_error; + } + pstat->wapiInfo->priv = priv; + wapiStationInit(pstat); + } + + RESTORE_INT(flags); + + p = get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EID_WAPI_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset); + + if (p==NULL) + { + pstat->wapiInfo->wapiState = ST_WAPI_AE_IDLE; + status = _RSON_IE_NOT_CONSISTENT_; + goto asoc_class2_error; + } + + memcpy(pstat->wapiInfo->asueWapiIE, p, len+2); + pstat->wapiInfo->asueWapiIELength= len+2; + + /* check for KM */ + if ((status=wapiIEInfoInstall(priv, pstat))!=_STATS_SUCCESSFUL_) + { + pstat->wapiInfo->wapiState = ST_WAPI_AE_IDLE; + goto asoc_class2_error; + } + } +#endif + + // now the station is qualified to join our BSS... + #if defined(BR_SHORTCUT) && defined(RTL_CACHED_BR_STA) + release_brsc_cache(GetAddr2Ptr(pframe)); + #endif + +#ifdef WIFI_WMM + // check if there is WMM IE + if (QOS_ENABLE) { + p = pframe + WLAN_HDR_A3_LEN + ie_offset; len = 0; + for (;;) { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, WMM_IE, 6)) { + pstat->QosEnabled = 1; +#ifdef WMM_APSD + if (APSD_ENABLE) + pstat->apsd_bitmap = *(p+8) & 0x0f; // get QSTA APSD bitmap +#endif + break; + } + } + else { + pstat->QosEnabled = 0; +#ifdef WMM_APSD + pstat->apsd_bitmap = 0; +#endif + break; + } + p = p + len + 2; + } + } + else { + pstat->QosEnabled = 0; +#ifdef WMM_APSD + pstat->apsd_bitmap = 0; +#endif + } +#endif +#ifdef RTK_AC_SUPPORT + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) + { + p = get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, EID_VHTCapability, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset); + + if ((p != NULL) && (len <= sizeof(struct vht_cap_elmt))) { + pstat->vht_cap_len = len; + memcpy((unsigned char *)&pstat->vht_cap_buf, p+2, len); + /* For debugging + SDEBUG("Receive vht_cap len = %d \n",len); + if (pstat->vht_cap_buf.vht_cap_info & cpu_to_le32(_VHTCAP_RX_STBC_CAP_)) { + SDEBUG("STA support RX STBC\n"); + } + if (pstat->vht_cap_buf.vht_cap_info & cpu_to_le32(_VHTCAP_RX_LDPC_CAP_)) { + SDEBUG("STA support RX LDPC\n"); + } + */ + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, EID_VHTOperation, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset); + + if ((p != NULL) && (len <= sizeof(struct vht_oper_elmt))) { + pstat->vht_oper_len = len; + memcpy((unsigned char *)&pstat->vht_oper_buf, p+2, len); +// SDEBUG("Receive vht_oper len = %d \n",len); + } + } +#endif +// ====2011-0926 ;roll back ; ht issue +#if 1 + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _HT_CAP_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset); + if ((p != NULL) && (len <= sizeof(struct ht_cap_elmt))) { + pstat->ht_cap_len = len; + memcpy((unsigned char *)&pstat->ht_cap_buf, p+2, len); + } + else { + unsigned char old_ht_ie_id[] = {0x00, 0x90, 0x4c}; + p = pframe + WLAN_HDR_A3_LEN + ie_offset; len = 0; + for (;;) + { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, old_ht_ie_id, 3) && (*(p+5) == 0x33) && ((len - 4) <= sizeof(struct ht_cap_elmt))) { + pstat->ht_cap_len = len - 4; + memcpy((unsigned char *)&pstat->ht_cap_buf, p+6, pstat->ht_cap_len); + break; + } + } + else + break; + + p = p + len + 2; + } + } + + //AC mode only, deny N mode STA +#ifdef RTK_AC_SUPPORT + if (!pstat->vht_cap_len && (priv->pmib->dot11StationConfigEntry.legacySTADeny & (WIRELESS_11N ))) { + DEBUG_ERR("AC mode only, deny non-AC STA association!\n"); + status = _STATS_RATE_FAIL_; + goto OnAssocReqFail; + } +#endif + if (pstat->ht_cap_len) { + // below is the process to check HT MIMO power save + unsigned char mimo_ps = ((cpu_to_le16(pstat->ht_cap_buf.ht_cap_info)) >> 2)&0x0003; + pstat->MIMO_ps = 0; + if (!mimo_ps) + pstat->MIMO_ps |= _HT_MIMO_PS_STATIC_; + else if (mimo_ps == 1) + pstat->MIMO_ps |= _HT_MIMO_PS_DYNAMIC_; + if (cpu_to_le16(pstat->ht_cap_buf.ht_cap_info) & _HTCAP_AMSDU_LEN_8K_) { + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 7935 - sizeof(struct wlan_hdr); + } + else { + pstat->is_8k_amsdu = 0; + pstat->amsdu_level = 3839 - sizeof(struct wlan_hdr); + } + + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)) + pstat->tx_bw = HT_CHANNEL_WIDTH_20_40; +#ifdef RTK_AC_SUPPORT + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) && (pstat->vht_cap_len)) + { + switch(cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & 0x3) { + default: + case 0: + pstat->is_8k_amsdu = 0; + pstat->amsdu_level = 3895 - sizeof(struct wlan_hdr); + break; + case 1: + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 7991 - sizeof(struct wlan_hdr); + break; + case 2: + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 11454 - sizeof(struct wlan_hdr); + break; + } +// force 4k +// pstat->is_8k_amsdu = 0; +// pstat->amsdu_level = 3895 - sizeof(struct wlan_hdr); + } +#endif + } + else { + if(!priv->pmib->wscEntry.wsc_enable){ + if (priv->pmib->dot11StationConfigEntry.legacySTADeny & (WIRELESS_11G | WIRELESS_11A)) { + DEBUG_ERR("Deny legacy STA association!\n"); + status = _STATS_RATE_FAIL_; + goto OnAssocReqFail; + } + + } + } +#ifdef RTK_AC_SUPPORT + if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC)) { + if (pstat->vht_cap_len && (priv->vht_oper_buf.vht_oper_info[0] == 1)) + pstat->tx_bw = HT_CHANNEL_WIDTH_80; + + p = get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, EID_VHTOperatingMode, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset); + if ((p != NULL) && (len == 1)) { + // check self capability.... + if((p[2] &3) <= priv->pshare->CurrentChannelBW) + pstat->tx_bw = p[2] &3; + pstat->nss = ((p[2]>>4)&0x7)+1; + //printk("receive opering mode data = %x \n", p[2]); + } + + + } +#endif + + } +#endif +// ====2011-0926 ; ht issue + +#ifdef WIFI_WMM + if (QOS_ENABLE) { + if ((pstat->QosEnabled == 0) && pstat->ht_cap_len) { + DEBUG_INFO("STA supports HT but doesn't support WMM, force WMM supported\n"); + pstat->QosEnabled = 1; + } + } +#endif + + +#ifdef P2P_SUPPORT + if(OPMODE&WIFI_P2P_SUPPORT){ + p = pframe + WLAN_HDR_A3_LEN + ie_offset ; + for (;;) + { + p = get_ie(p, _P2P_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset - len); + if (p) { + if (!memcmp(p+2, WFA_OUI_PLUS_TYPE, 4)) { + IEfoundtimes ++; + memcpy(p2pIEPtr , p+6 ,len-4); + p2pIEPtr+= (len-4); + } + } + else{ + break; + } + p = p + len + 2; + + } + + if(IEfoundtimes){ + + if(IEfoundtimes>1){ + P2P_DEBUG("ReAssembly p2p IE\n"); + } + p2pIElen = (int)(((unsigned long)p2pIEPtr)-((unsigned long)ReAssem_p2pie)); + + if(p2pIElen > MAX_REASSEM_P2P_IE){ + P2P_DEBUG("\n\n reassemble P2P IE exceed MAX_REASSEM_P2P_IE , chk!!!\n\n"); + }else{ + /*just start record GC's info when i am Real GO*/ + if(P2PMODE == P2P_TMP_GO){ + P2P_on_assoc_req(priv,ReAssem_p2pie,p2pIElen , pfrinfo->sa); + P2P_DEBUG("GC come from:\n"); + printMac(pfrinfo->sa); + p2p_debug_out("p2pie at assoc_req: ", ReAssem_p2pie, p2pIElen); + pstat->is_p2p_client = 1; + + } + } + } + } + +#endif + + + // Realtek proprietary IE + pstat->is_realtek_sta = FALSE; + pstat->IOTPeer = HT_IOT_PEER_UNKNOWN; + p = pframe + WLAN_HDR_A3_LEN + ie_offset; len = 0; + for (;;) + { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, Realtek_OUI, 3) && *(p+2+3) == 2) { /*found realtek out and type == 2*/ + pstat->is_realtek_sta = TRUE; + pstat->IOTPeer = HT_IOT_PEER_REALTEK; + + if (*(p+2+3+2) & RTK_CAP_IE_AP_CLIENT) + pstat->IOTPeer = HT_IOT_PEER_RTK_APCLIENT; + + if(*(p+2+3+2) & RTK_CAP_IE_WLAN_8192SE) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_92SE; + + if (*(p+2+3+2) & RTK_CAP_IE_USE_AMPDU) + pstat->is_forced_ampdu = TRUE; + else + pstat->is_forced_ampdu = FALSE; +#ifdef RTK_WOW + if (*(p+2+3+2) & RTK_CAP_IE_USE_WOW) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_WOW; +#endif + if (*(p+2+3+2) & RTK_CAP_IE_WLAN_88C92C) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_81XX; + + if (*(p+2+3+3) & ( RTK_CAP_IE_8812_BCUT | RTK_CAP_IE_8812_CCUT)) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_8812; + break; + } + } + else + break; + + p = p + len + 2; + } + + // identify if this is Broadcom sta + p = pframe + WLAN_HDR_A3_LEN + ie_offset; len = 0; + + for (;;) + { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + for (z = 0; z < BCM_OUI_NUM; z++) { + if (!memcmp(p+2, BCM_OUI[z], 3)) { + pstat->IOTPeer = HT_IOT_PEER_BROADCOM; + break; + } + } + if (z < BCM_OUI_NUM) + break; + } + else + break; + + p = p + len + 2; + } + + // identify if this is ralink sta + p = pframe + WLAN_HDR_A3_LEN + ie_offset; len = 0; + +#if 0 +//#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + pstat->is_ralink_sta = FALSE; +#endif + for (;;) + { + unsigned char Ralink_OUI1[]={0x00, 0x0c, 0x43}; + + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, Ralink_OUI1, 3)) { + + pstat->IOTPeer= HT_IOT_PEER_RALINK; + + break; + } + } + else + break; + + p = p + len + 2; + } + + for (z = 0; z < HTC_OUI_NUM; z++) { + if ((pstat->hwaddr[0] == HTC_OUI[z][0]) && + (pstat->hwaddr[1] == HTC_OUI[z][1]) && + (pstat->hwaddr[2] == HTC_OUI[z][2])) { + + pstat->IOTPeer = HT_IOT_PEER_HTC; + + break; + } + } + + if (!pstat->is_realtek_sta && (pstat->IOTPeer!=HT_IOT_PEER_BROADCOM) && pstat->IOTPeer!=HT_IOT_PEER_RALINK && pstat->IOTPeer!=HT_IOT_PEER_HTC) + { + //unsigned int z = 0; + + for (z = 0; z < INTEL_OUI_NUM; z++) { + if ((pstat->hwaddr[0] == INTEL_OUI[z][0]) && + (pstat->hwaddr[1] == INTEL_OUI[z][1]) && + (pstat->hwaddr[2] == INTEL_OUI[z][2])) { + + pstat->IOTPeer = HT_IOT_PEER_INTEL; + + pstat->no_rts = 1; + break; + } + } + + } + +#ifdef MCR_WIRELESS_EXTEND + if ((GET_CHIP_VER(priv)==VERSION_8812E) || (GET_CHIP_VER(priv)==VERSION_8192E) || (GET_CHIP_VER(priv)==VERSION_8814A)) { + if (!memcmp(pstat->hwaddr, "\x00\x01\x02\x03\x04\x05", MACADDRLEN)) { + pstat->IOTPeer = HT_IOT_PEER_CMW; + priv->pshare->cmw_link = 1; + priv->pshare->rf_ft_var.tx_pwr_ctrl = 0; +#ifdef CONFIG_WLAN_HAL_8814AE + if (GET_CHIP_VER(priv)==VERSION_8814A) { +#ifdef DFS + priv->pshare->rf_ft_var.dfs_psd_idle_on= 0; +#endif + //PHY_SetBBReg(priv, 0x93c, 0xfff00000, 0x106); + PHY_SetBBReg(priv, 0x808, 0xff, 0x66); + + //PHY_SetBBReg(priv, 0x808, 0x0f00, 0x0); + + if (priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_80) { + PHY_SetBBReg(priv, 0x838, BIT0, 0x1); + if (get_rf_mimo_mode(priv) == MIMO_2T2R) { + PHY_SetBBReg(priv, 0x82C, 0x0fff0000, 0x5a9); + PHY_SetBBReg(priv, 0x838, 0x0fff0000, 0x788); + PHY_SetBBReg(priv, 0x840, 0x0000f000, 0x6); + RTL_W8(0x830,0xa); + } else { + PHY_SetBBReg(priv, 0x82C, 0x0fff0000, 0x398); + PHY_SetBBReg(priv, 0x838, 0x0fff0000, 0x777); + PHY_SetBBReg(priv, 0x840, 0x0000f000, 0x7); + RTL_W8(0x830,0x8); + } + } + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8812E) { + PHY_SetBBReg(priv, 0x878, BIT(12)|BIT(13), 0); + } else +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv)==VERSION_8192E) { + RTL_W16(RESP_SIFS_CCK, 0x0808); + RTL_W8(0xa2f, 0x0); + RTL_W8(0xa20, 0x10); + } +#endif + } + } +#endif + + SAVE_INT_AND_CLI(flags); + auth_list_del(priv, pstat); + if (asoc_list_add(priv, pstat)) + { + pstat->expire_to = priv->expire_to; + //printk("wlan%d pstat->asoc_list = %p priv->asoc_list=%p\n",priv->pshare->wlandev_idx, pstat->asoc_list, priv->asoc_list); + cnt_assoc_num(priv, pstat, INCREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, INCREASE); + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + construct_ht_ie(priv, priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + } + RESTORE_INT(flags); + + assign_tx_rate(priv, pstat, pfrinfo); + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + //panic_printk("%s %d UpdateRAMask\n", __FUNCTION__, __LINE__); + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + ODM_RAPostActionOnAssoc(ODMPTR); + pstat->ratr_idx_init = pstat->ratr_idx; + //phydm_ra_dynamic_rate_id_on_assoc(ODMPTR, pstat->WirelessMode, pstat->ratr_idx_init); + + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) { + UpdateHalRAMask8812(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } + assign_aggre_mthod(priv, pstat); + assign_aggre_size(priv, pstat); + + update_intel_sta_bitmap(priv, pstat, 0); +#if defined(WIFI_11N_2040_COEXIST_EXT) + update_40m_staMap(priv, pstat, 0); + checkBandwidth(priv); +#endif + + // Customer proprietary IE + if (priv->pmib->miscEntry.private_ie_len) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, priv->pmib->miscEntry.private_ie[0], &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - ie_offset); + if (p) { + memcpy(pstat->private_ie, p, len + 2); + pstat->private_ie_len = len + 2; + } + } + + DEBUG_INFO("%s %02X%02X%02X%02X%02X%02X\n", + (frame_type == WIFI_ASSOCREQ)? "OnAssocReq" : "OnReAssocReq", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + + /* 1. If 802.1x enabled, get RSN IE (if exists) and indicate ASSOIC_IND event + * 2. Set dot118021xAlgrthm, dot11PrivacyAlgrthm in pstat + */ + if (IEEE8021X_FUN || IAPP_ENABLE || priv->pmib->wscEntry.wsc_enable) + { + p = pframe + WLAN_HDR_A3_LEN + ie_offset; len = 0; + for(;;) + { +#ifdef RTL_WPA2 + char tmpbuf[128]; + int buf_len=0; + p = get_rsn_ie(priv, p, &len, + pfrinfo->pktlen - (p - pframe)); + + buf_len = sprintf(tmpbuf, "RSNIE len = %d, p = %s", len, (p==NULL? "NULL":"non-NULL")); + if (p != NULL) + buf_len += sprintf(tmpbuf+buf_len, ", ID = %02X\n", *(unsigned char *)p); + else + buf_len += sprintf(tmpbuf+buf_len, "\n"); + DEBUG_INFO("%s", tmpbuf); +#else + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); +#endif + + if (p == NULL) { +#if defined(WIFI_HAPD) || (defined(RTK_NL80211) && !defined(NON_NL80211_AP)) + memset(pstat->wpa_ie, 0, 256); +#endif + break; + } + +#if defined(WIFI_HAPD) || (defined(RTK_NL80211) && !defined(NON_NL80211_AP)) + if((*(unsigned char *)p == _RSN_IE_1_)&& (len >= 4)) + { + pstat->wpa_sta_info->RSNEnabled = BIT(0); + memcpy(pstat->wpa_ie, p, len+2); + } + else if((*(unsigned char *)p == _RSN_IE_2_) && (len >= 2)) + { + pstat->wpa_sta_info->RSNEnabled = BIT(1); + memcpy(pstat->wpa_ie, p, len+2); + } +#endif + +#ifdef RTL_WPA2 + if ((*(unsigned char *)p == _RSN_IE_1_) && (len >= 4) && (!memcmp((void *)(p + 2), (void *)rsnie_hdr, 4))) { +#ifdef TLN_STATS + pstat->enterpise_wpa_info = STATS_ETP_WPA; +#endif + break; +} + + if ((*(unsigned char *)p == _RSN_IE_2_) && (len >= 2) && (!memcmp((void *)(p + 2), (void *)rsnie_hdr_wpa2, 2))) { +#ifdef TLN_STATS + pstat->enterpise_wpa_info = STATS_ETP_WPA2; +#endif + break; + } +#else + if ((len >= 4) && (!memcmp((void *)(p + 2), (void *)rsnie_hdr, 4))) { +#ifdef TLN_STATS + pstat->enterpise_wpa_info = STATS_ETP_WPA; +#endif + break; + } +#endif + + p = p + len + 2; + } + +#ifdef WIFI_SIMPLE_CONFIG +/* WPS2DOTX -start*/ + if (priv->pmib->wscEntry.wsc_enable & 2) { // work as AP (not registrar) + unsigned char *ptmp; + unsigned char *TagPtr=NULL; + int IS_V2=0; + int Taglen = 0; + int Taglent2 = 0; + unsigned int lentmp = 0; + unsigned char passWscIE=0; + DOT11_WSC_ASSOC_IND wsc_Association_Ind; + + ptmp = pframe + WLAN_HDR_A3_LEN + ie_offset; + + for (;;) + { + ptmp = get_ie(ptmp, _WPS_IE_, (int *)&lentmp , pfrinfo->pktlen - (ptmp - pframe)); + if (ptmp != NULL) { + if ((!memcmp(ptmp+2, WSC_IE_OUI, 4)) && ((lentmp + 2) <= (MIN_NUM(PROBEIELEN,256)))) {//256 is size of pstat->wps_ie +#if (defined(RTK_NL80211) || defined(WIFI_HAPD)) && !defined(HAPD_DRV_PSK_WPS) + //printk("copy wps_ie \n"); + memcpy(pstat->wps_ie, ptmp, lentmp+2); +#endif + + TagPtr = search_wsc_tag(ptmp+2+4, TAG_REQUEST_TYPE, lentmp-4, &Taglen); + if (TagPtr && (*TagPtr <= MAX_REQUEST_TYPE_NUM)) { + SME_DEBUG("found WSC_IE TAG_REQUEST_TYPE=%d (from %02x%02x%02x:%02x%02x%02x)\n", + *TagPtr , pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); + passWscIE = 1; + } + + + TagPtr = search_wsc_tag(ptmp+2+4, TAG_VENDOR_EXT, lentmp-4, &Taglen); + if (TagPtr != NULL) { + if(!memcmp(TagPtr , WSC_VENDOR_OUI ,3 )){ + SME_DEBUG("Found WFA-vendor OUI!!\n"); + TagPtr = search_VendorExt_tag(TagPtr ,VENDOR_VERSION2 , Taglen , &Taglent2); + if(TagPtr){ + IS_V2 = 1; + SME_DEBUG("sme Rev version2(0x%x) ProReq\n",TagPtr[0]); + } + } + } + + + break; + } else { + if (TagPtr !=NULL){ + DEBUG_INFO("Found WSC_IE TAG_REQUEST_TYPE=%d", *TagPtr); + }else{ + DEBUG_INFO("Found WSC_IE"); + } + DEBUG_INFO(" from %02x%02x%02x:%02x%02x%02x, but the length(%d) of WSC_IE may be bigger than %d, Parse next WSC_IE\n", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], pstat->hwaddr[3], + pstat->hwaddr[4], pstat->hwaddr[5], lentmp + 2, (MIN_NUM(PROBEIELEN,256)) ); + } + } + else{ +#if (defined(RTK_NL80211) || defined(WIFI_HAPD)) && !defined(HAPD_DRV_PSK_WPS) + memset(pstat->wps_ie, 0, 256); +#endif + break; + } + + ptmp = ptmp + lentmp + 2; + } + + memset(&wsc_Association_Ind, 0, sizeof(DOT11_WSC_ASSOC_IND)); + wsc_Association_Ind.EventId = DOT11_EVENT_WSC_ASSOC_REQ_IE_IND; + memcpy((void *)wsc_Association_Ind.MACAddr, (void *)GetAddr2Ptr(pframe), MACADDRLEN); + if (passWscIE) { + wsc_Association_Ind.wscIE_included = 1; + wsc_Association_Ind.AssocIELen = lentmp + 2; + memcpy((void *)wsc_Association_Ind.AssocIE, (void *)(ptmp), wsc_Association_Ind.AssocIELen); + } + else { + /*modify for WPS2DOTX SUPPORT*/ + if(IS_V2==0) + { + /*when sta is wps1.1 case then should be run below path*/ + if (IEEE8021X_FUN && + (pstat->AuthAlgrthm == _NO_PRIVACY_) && // authentication is open + (p == NULL)) // No SSN or RSN IE + { + wsc_Association_Ind.wscIE_included = 1; //treat this case as WSC IE included + SME_DEBUG("Association : auth open & no SSN or RSN IE , for wps1.1 case\n"); + } + } + } + + /* wscIE_included : + case 1: make sure STA include WSC IE + case 2: because auth == open & no SSN or RSN IE ;so we + treat this case as WSC IE included + */ + /*modify for WPS2DOTX SUPPORT*/ + if ((wsc_Association_Ind.wscIE_included == 1) || !IEEE8021X_FUN){ +#ifdef INCLUDE_WPS + + wps_NonQueue_indicate_evt(priv , + (UINT8 *)&wsc_Association_Ind,sizeof(DOT11_WSC_ASSOC_IND)); +#else + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&wsc_Association_Ind, + sizeof(DOT11_WSC_ASSOC_IND)); +#endif + } + /*modify for WPS2DOTX SUPPORT*/ + if (wsc_Association_Ind.wscIE_included == 1) { + pstat->state |= WIFI_WPS_JOIN; + goto OnAssocReqSuccess; + } +// Brad add for DWA-652 WPS interoperability 2008/03/13-------- + if ((pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ || + pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) && + !IEEE8021X_FUN) + pstat->state |= WIFI_WPS_JOIN; +//------------------------- end + + } +/* WPS2DOTX -end*/ +#endif + +// ====2011-0926 ;roll back ; ht issue +#if 1 + if(priv->pmib->wscEntry.wsc_enable) { + if (!pstat->ht_cap_len && (priv->pmib->dot11StationConfigEntry.legacySTADeny & (WIRELESS_11G | WIRELESS_11A))) { + DEBUG_ERR("Deny legacy STA association!\n"); + status = _STATS_RATE_FAIL_; + SAVE_INT_AND_CLI(flags); + asoc_list_del(priv, pstat); + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + RESTORE_INT(flags); + goto OnAssocReqFail; + } + } +#endif +// ====2011-0926 end + + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _NO_PRIVACY_)) + { + int mask_mcs_rate = 0; + if ((pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) || + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_)) + mask_mcs_rate = 2; +#ifdef CONFIG_RTL_WAPI_SUPPORT + else if(pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WAPI_SMS4_) { + mask_mcs_rate = 0; + } +#endif + else { + if (p == NULL) + mask_mcs_rate = 1; + else { + if (*p == _RSN_IE_1_) { + if (is_support_wpa_aes(priv, p, len+2) != 1) + mask_mcs_rate = 1; + } + else if (*p == _RSN_IE_2_) { + if (is_support_wpa2_aes(priv, p, len+2) != 1) + mask_mcs_rate = 1; + } + else + mask_mcs_rate = 1; + } + } + + if (mask_mcs_rate) { + pstat->is_legacy_encrpt = mask_mcs_rate; + assign_tx_rate(priv, pstat, pfrinfo); +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + //panic_printk("%s %d UpdateRAMask\n", __FUNCTION__, __LINE__); + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + ODM_RAPostActionOnAssoc(ODMPTR); + pstat->ratr_idx_init = pstat->ratr_idx; + //phydm_ra_dynamic_rate_id_on_assoc(ODMPTR, pstat->WirelessMode, pstat->ratr_idx_init); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) { + UpdateHalRAMask8812(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } + assign_aggre_mthod(priv, pstat); + } + } + +#ifndef WITHOUT_ENQUEUE + if (frame_type == WIFI_ASSOCREQ) + { + memcpy((void *)Association_Ind.MACAddr, (void *)GetAddr2Ptr(pframe), MACADDRLEN); + Association_Ind.EventId = DOT11_EVENT_ASSOCIATION_IND; + Association_Ind.IsMoreEvent = 0; + if (p == NULL) + Association_Ind.RSNIELen = 0; + else + { + DEBUG_INFO("assoc indication rsnie len=%d\n", len); +#ifdef RTL_WPA2 + // inlcude ID and Length + Association_Ind.RSNIELen = len + 2; + memcpy((void *)Association_Ind.RSNIE, (void *)(p), Association_Ind.RSNIELen); +#else + Association_Ind.RSNIELen = len; + memcpy((void *)Association_Ind.RSNIE, (void *)(p + 2), len); +#endif + } + // indicate if 11n sta associated + Association_Ind.RSNIE[MAXRSNIELEN-1] = ((pstat->ht_cap_len==0) ? 0 : 1); + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Association_Ind, + sizeof(DOT11_ASSOCIATION_IND)); + } + else + { + memcpy((void *)Reassociation_Ind.MACAddr, (void *)GetAddr2Ptr(pframe), MACADDRLEN); + Reassociation_Ind.EventId = DOT11_EVENT_REASSOCIATION_IND; + Reassociation_Ind.IsMoreEvent = 0; + if (p == NULL) + Reassociation_Ind.RSNIELen = 0; + else + { + DEBUG_INFO("assoc indication rsnie len=%d\n", len); +#ifdef RTL_WPA2 + // inlcude ID and Length + Reassociation_Ind.RSNIELen = len + 2; + memcpy((void *)Reassociation_Ind.RSNIE, (void *)(p), Reassociation_Ind.RSNIELen); +#else + Reassociation_Ind.RSNIELen = len; + memcpy((void *)Reassociation_Ind.RSNIE, (void *)(p + 2), len); +#endif + } + memcpy((void *)Reassociation_Ind.OldAPaddr, + (void *)(pframe + WLAN_HDR_A3_LEN + _CAPABILITY_ + _LISTEN_INTERVAL_), MACADDRLEN); + + // indicate if 11n sta associated + Reassociation_Ind.RSNIE[MAXRSNIELEN-1] = ((pstat->ht_cap_len==0) ? 0 : 1); + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Reassociation_Ind, + sizeof(DOT11_REASSOCIATION_IND)); + } +#endif // WITHOUT_ENQUEUE + +#ifdef RTK_NL80211 + //printk("pstat=0x%x at %d: %02x %02x %02x\n", pstat, __LINE__, pstat->wpa_ie[0], pstat->wpa_ie[1], pstat->wpa_ie[2]); + //event_indicate_cfg80211(priv, GetAddr2Ptr(pframe), CFG80211_NEW_STA, pstat); +#endif + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + { + int id; + unsigned char *pIE; + int ie_len; + +#if !(defined(__ECOS) && defined(CONFIG_SDIO_HCI)) + LOG_MSG("A wireless client is associated - %02X:%02X:%02X:%02X:%02X:%02X\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#endif + + if (frame_type == WIFI_ASSOCREQ) + id = DOT11_EVENT_ASSOCIATION_IND; + else + id = DOT11_EVENT_REASSOCIATION_IND; + +#ifdef RTL_WPA2 + ie_len = len + 2; + pIE = p; +#else + ie_len = len; + pIE = p + 2; +#endif + +#if defined(INCLUDE_WPA_PSK) + psk_indicate_evt(priv, id, GetAddr2Ptr(pframe), pIE, ie_len); +#elif defined(WIFI_HAPD) || defined(RTK_NL80211) + nl80211_psk_indicate_evt(priv, id, GetAddr2Ptr(pframe), pIE, ie_len); +#endif + } +#endif // INCLUDE_WPA_PSK + +#if defined(RTK_NL80211) && !defined(NON_NL80211_AP) //eric-sync ?? + //printk("pstat=0x%x at %d: %02x %02x %02x\n", pstat, __LINE__, pstat->wpa_ie[0], pstat->wpa_ie[1], pstat->wpa_ie[2]); + //event_indicate_cfg80211(priv, GetAddr2Ptr(pframe), CFG80211_NEW_STA, pstat); +#else //RTK_NL80211 +#ifdef WIFI_HAPD + event_indicate_hapd(priv, GetAddr2Ptr(pframe), HAPD_REGISTERED, NULL); +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#else + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#ifdef WIFI_WPAS + //printk("_Eric WPAS_REGISTERED at %s %d \n", __FUNCTION__, __LINE__); + event_indicate_wpas(priv, GetAddr2Ptr(pframe), WPAS_REGISTERED, NULL); +#endif +#endif //RTK_NL80211 + } +#ifdef HS2_SUPPORT + calcu_sta_v6ip(pstat); +#endif + +//#ifndef INCLUDE_WPA_PSK +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196C_EC) + if (!IEEE8021X_FUN && + !(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)) + LOG_MSG_NOTICE("Wireless PC connected;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#elif defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) + if (!IEEE8021X_FUN && + !(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)) + LOG_MSG_NOTICE("Wireless PC connected;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#elif defined(CONFIG_RTL8196B_TLD) + if (!IEEE8021X_FUN && + !(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)) { + if (!list_empty(&priv->wlan_acl_list)) { + LOG_MSG_DEL("[WLAN access allowed] from MAC: %02x:%02x:%02x:%02x:%02x:%02x,\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); + } + } +#elif defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->sta_status_cb_func) + priv->sta_status_cb_func("wlan0", GetAddr2Ptr(pframe), ((frame_type == WIFI_ASSOCREQ)? WIFI_STA_STATUS_ASSOCIATED : WIFI_STA_STATUS_REASSOCIATED)); +#else + LOG_MSG("A wireless client is associated - %02X:%02X:%02X:%02X:%02X:%02X\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#endif +//#endif + +#if !defined(RTK_NL80211) || defined(NON_NL80211_AP) //OPENWRT_RADIUS + if (IEEE8021X_FUN || IAPP_ENABLE || priv->pmib->wscEntry.wsc_enable) { +#ifndef __DRAYTEK_OS__ + if (IEEE8021X_FUN && // in WPA, let user daemon check RSNIE and decide to accept or not + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)) { + +#ifdef BEAMFORMING_SUPPORT + //panic_printk("%s, %x\n", __FUNCTION__, cpu_to_le32(pstat->vht_cap_buf.vht_cap_info)); + if(GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv) == VERSION_8192E || GET_CHIP_VER(priv) == VERSION_8814A) + if((priv->pmib->dot11RFEntry.txbf == 1) && ((pstat->ht_cap_len && (pstat->ht_cap_buf.txbf_cap)) +#ifdef RTK_AC_SUPPORT + || (pstat->vht_cap_len && (cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & (BIT(SU_BFEE_S)|BIT(SU_BFER_S)))) +#endif + )){ + Beamforming_Enter(priv, pstat); + } +#endif + + return SUCCESS; + } +#endif + } +#endif + +#ifdef WIFI_SIMPLE_CONFIG +OnAssocReqSuccess: +#endif + + if (frame_type == WIFI_ASSOCREQ) + issue_asocrsp(priv, status, pstat, WIFI_ASSOCRSP); + else + issue_asocrsp(priv, status, pstat, WIFI_REASSOCRSP); + +#ifdef BEAMFORMING_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv) == VERSION_8192E || GET_CHIP_VER(priv) == VERSION_8814A) + if((priv->pmib->dot11RFEntry.txbf == 1) && + ((pstat->ht_cap_len && (pstat->ht_cap_buf.txbf_cap)) +#ifdef RTK_AC_SUPPORT + ||(pstat->vht_cap_len && (cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & (BIT(SU_BFEE_S)|BIT(SU_BFER_S)))) +#endif + )) { + Beamforming_Enter(priv, pstat); + } +#endif + +//#ifdef BR_SHORTCUT +#if 0 + clear_shortcut_cache(); +#endif + + update_fwtbl_asoclst(priv, pstat); + +/*update mesh proxy table*/ +#if defined(CONFIG_RTK_MESH) + mesh_proxy_update(priv, pframe); + + #ifdef BR_SHORTCUT + clear_shortcut_cache(); + #endif // BR_SHORTCUT +#endif +#if defined(RTK_NL80211) && !defined(NON_NL80211_AP) + //printk("pstat=%p: %02x %02x %02x\n", pstat, pstat->wpa_ie[0], pstat->wpa_ie[1], pstat->wpa_ie[2]); + event_indicate_cfg80211(priv, GetAddr2Ptr(pframe), CFG80211_NEW_STA, pstat); +#else //RTK_NL80211 + +#ifdef WIFI_HAPD + event_indicate_hapd(priv, GetAddr2Ptr(pframe), HAPD_REGISTERED, NULL); +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#else + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#ifdef WIFI_WPAS + //printk("_Eric WPAS_REGISTERED at %s %d\n", __FUNCTION__, __LINE__); + event_indicate_wpas(priv, GetAddr2Ptr(pframe), WPAS_REGISTERED, NULL); +#endif +#endif //RTK_NL80211 + +#ifndef USE_WEP_DEFAULT_KEY + set_keymapping_wep(priv, pstat); +#endif + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType==wapiTypeCert) + { + wapiAssert(pstat->wapiInfo->wapiState==ST_WAPI_AE_IDLE); + + WAPI_LOCK(&pstat->wapiInfo->lock); + pstat->wapiInfo->wapiRetry = 0; + WAPI_UNLOCK(&pstat->wapiInfo->lock); + + wapiReqActiveCA(pstat); + return SUCCESS; + } + else if (priv->pmib->wapiInfo.wapiType==wapiTypePSK) + { + wapiAssert(pstat->wapiInfo->wapiState==ST_WAPI_AE_IDLE); + + WAPI_LOCK(&pstat->wapiInfo->lock); + pstat->wapiInfo->wapiRetry = 0; + WAPI_UNLOCK(&pstat->wapiInfo->lock); + + wapiSetBK(pstat); + if (wapiSendUnicastKeyAgrementRequeset(priv, pstat)==WAPI_RETURN_SUCCESS) + return SUCCESS; + else + return FAIL; + } +#endif + + return SUCCESS; + +asoc_class2_error: + + issue_deauth(priv, (void *)GetAddr2Ptr(pframe), status); + if (pstat){ + free_stainfo(priv, pstat); + } + return FAIL; + +OnAssocReqFail: + + if (frame_type == WIFI_ASSOCREQ) + issue_asocrsp(priv, status, pstat, WIFI_ASSOCRSP); + else + issue_asocrsp(priv, status, pstat, WIFI_REASSOCRSP); + return FAIL; +} + +#ifdef P2P_SUPPORT +int is_brate(unsigned char rrate) +{ + if(rrate==0x82 || rrate==0x84 || rrate==0x8b || rrate==0x96 ) + return 1; + else + return 0; +} +#endif +static unsigned int OnProbeReq(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + struct wifi_mib *pmib; + unsigned char *pframe, *p; + unsigned char *ssidptrx=NULL; + unsigned int len; + +#ifdef P2P_SUPPORT + int idx=0; + int brateonly = 1; + static unsigned char ReAssem_p2pie[MAX_REASSEM_P2P_IE]; + + unsigned char *p2pIEPtr = ReAssem_p2pie ; + int IEfoundtimes=0; + int p2pIElen=0; +#endif + + + + unsigned char *bssid, is_11b_only=0; + +#ifdef WDS + unsigned int i; +#endif + + //WPS2DOTX support probe_req wsc ie resammbly + static unsigned char tmp_assem_wscie[512]; + unsigned char *awPtr = tmp_assem_wscie ; + unsigned int foundtimes=0; + int lenx = 0; + //WPS2DOTX +#if defined(WIFI_SIMPLE_CONFIG) || defined(P2P_SUPPORT) + unsigned char *ptmp; + unsigned int lentmp; +#endif + + bssid = BSSID; + pmib = GET_MIB(priv); + pframe = get_pframe(pfrinfo); + + if (!IS_DRV_OPEN(priv)) + return FAIL; + + if (priv->auto_channel == 1) + return FAIL; + +#ifdef P2P_SUPPORT + if((OPMODE&WIFI_P2P_SUPPORT) && + ((P2PMODE == P2P_DEVICE) && (P2P_STATE == P2P_S_LISTEN))){ + /*allow (p2p device mode && under listen state) can process probe_req frame*/ + } + else +#endif + { + if (!((OPMODE & WIFI_AP_STATE) || (OPMODE & WIFI_ADHOC_STATE)) +#ifdef MP_TEST + || priv->pshare->rf_ft_var.mp_specific +#endif + ) + return FAIL; + + } + +#ifdef WDS + if (pmib->dot11WdsInfo.wdsEnabled && pmib->dot11WdsInfo.wdsPure) { + if (pmib->dot11WdsInfo.wdsNum) { + for (i = 0; i < pmib->dot11WdsInfo.wdsNum; i++) { + if (!memcmp(pmib->dot11WdsInfo.entry[i].macAddr, (char *)GetAddr2Ptr(pframe), MACADDRLEN)) { + break; + } + } + if (i == pmib->dot11WdsInfo.wdsNum) { + return FAIL; + } + } + else{ + return FAIL; + } + } +#endif + + if (pmib->miscEntry.func_off) + return FAIL; +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_ADHOC_STATE) && + (!priv->ibss_tx_beacon || (OPMODE & WIFI_SITE_MONITOR))) + return FAIL; +#endif + +#ifdef CONFIG_RTK_MESH + if(pfrinfo->is_11s) + return OnProbeReq_MP(priv, pfrinfo); +#endif + +// PSP IOT +#if 1 + p = get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, (int *)&len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); + if (p == NULL) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); + if( (p == NULL) || ( len<=4)) + is_11b_only = 1; + } +#endif +// +#ifdef WIFI_SIMPLE_CONFIG + if (priv->pmib->wscEntry.wsc_enable & 2) { // work as AP (not registrar) + ptmp = pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_; lentmp = 0; + for (;;) + { + ptmp = get_ie(ptmp, _WPS_IE_, (int *)&lentmp, + pfrinfo->pktlen - (ptmp - pframe)); + if (ptmp != NULL) { + if (!memcmp(ptmp+2, WSC_IE_OUI, 4)) { + foundtimes ++; + if(foundtimes ==1){ + if ( (lentmp + 2 ) > PROBEIELEN) + { + DEBUG_WARN("[%s] WPS_IE length is too big =%d\n", __FUNCTION__, (lentmp+2)); + foundtimes--; + break; + } else { + memcpy(awPtr , ptmp ,lentmp + 2); + awPtr+= (lentmp + 2); + lenx += (lentmp + 2); + } + }else{ + if ( (lenx + lentmp-4 ) > PROBEIELEN) + { + DEBUG_WARN("[%s] Total length of several WPS_IE is too big =%d, do not include the last WSC IEs\n", __FUNCTION__, (lenx+lentmp-4)); + foundtimes--; + break; + } else { + memcpy(awPtr , ptmp+2+4 ,lentmp-4); + awPtr+= (lentmp-4); + lenx += (lentmp-4); + } + } + } + } + else{ + break; + } + + ptmp = ptmp + lentmp + 2; + } + if(foundtimes){ + lenx = (int)(((unsigned long)awPtr)-((unsigned long)tmp_assem_wscie)); + if(foundtimes>1){ + tmp_assem_wscie[1] = lenx-2; + //debug_out("ReAss probe_Req wsc_ie ",tmp_assem_wscie,lenx); + } + +#if defined(RTK_NL80211) && !defined(NON_NL80211_AP) + if (priv->probe_req_report) + { + rtk_cfg80211_rx_mgmt(priv, pfrinfo, priv->pmib->dot11RFEntry.dot11channel); + } + else +#endif + { + wsc_forward_probe_request(priv, pframe, tmp_assem_wscie, lenx); + } + }else{ // + if( search_wsc_pbc_probe_sta(priv, (unsigned char *)GetAddr2Ptr(pframe))==1){ + DOT11_WSC_PIN_IND wsc_ind; + wsc_ind.EventId = DOT11_EVENT_WSC_RM_PBC_STA ; + wsc_ind.IsMoreEvent = 0; + memcpy(wsc_ind.code,(unsigned char *)GetAddr2Ptr(pframe),6); + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)&wsc_ind, sizeof(DOT11_WSC_PIN_IND)); + event_indicate(priv, NULL, -1); + } + } + } +/* WPS2DOTX */ +#ifdef HS2_SUPPORT + + if (priv->pmib->hs2Entry.interworking_ielen) + { + unsigned char *ptmp; + unsigned int hs_len; + ptmp = get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _EXTENDED_CAP_IE_, (int *)&hs_len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); + + if (ptmp) + { + unsigned char tmp[12]; + + if (hs_len >= 4) + { + memcpy(tmp, ptmp+2, hs_len); + + if (tmp[3] & 0x80) //interworking capability bit + { + ptmp = get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _INTERWORKING_IE_, (int *)&hs_len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); + + if (ptmp) + { + memcpy(tmp, ptmp+2, hs_len); + //printk("Check Interworking element, hs_len=%d\n",hs_len); + //check ant match or not + if ((tmp[0] & 0x0f) != (priv->pmib->hs2Entry.interworking_ie[0] & 0x0f) && ((tmp[0] & 0x0f) != 15)) //access network type not match + { + //printk("ant (access network type) not match\n"); + goto OnProbeReqFail; + } + + hs_len -= 1; + if (hs_len > 1) + { + //printk("Case hs_len = %d\n",hs_len); + if (hs_len == 8) + { + if (memcmp(tmp+3, priv->pmib->hs2Entry.interworking_ie+3, 6) && memcmp(tmp+3, "\xff\xff\xff\xff\xff\xff", 6)) //hessid not match + { + //printk("no match hessid1, %02x%02x%02x%02x%02x%02x\n",tmp[3],tmp[4],tmp[5],tmp[6],tmp[7],tmp[8]); + goto OnProbeReqFail; + } + } + else if (hs_len == 6) + { + if (memcmp(tmp+1, priv->pmib->hs2Entry.interworking_ie+3, 6) && memcmp(tmp+1, "\xff\xff\xff\xff\xff\xff", 6)) //hessid not match + { + //printk("no match hessid2, %02x%02x%02x%02x%02x%02x\n",tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6]); + goto OnProbeReqFail; + } + } + else { + goto OnProbeReqFail; + } + } + } + else + panic_printk("enable interworking bit, but no interworking ie!!\n"); + } + } + } + } +#endif +#endif + + +#ifdef P2P_SUPPORT + if((OPMODE&WIFI_P2P_SUPPORT) + && (((P2PMODE == P2P_DEVICE) && (P2P_STATE == P2P_S_LISTEN)) || (P2PMODE == P2P_TMP_GO )) ) + { + + + /*check P2P Wildcard SSID: The SSID field ¡§DIRECT-¡¨.*/ + ssidptrx = get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); + + if (ssidptrx == NULL){ + //P2P_DEBUG("\n"); + goto OnProbeReqFail; + } + + if( len==7 && (*(ssidptrx+2) == 'D' ) && (*(ssidptrx+3) == 'I' ) + && (*(ssidptrx+4) == 'R')&& (*(ssidptrx+5) == 'E') + && (*(ssidptrx+6) == 'C')&& (*(ssidptrx+7) == 'T') + && (*(ssidptrx+8) == '-')) + { + //P2P_SME_P("chk (DIRECT-) ssid\n"); + }else{ + + if((P2PMODE == P2P_DEVICE) && (P2P_STATE == P2P_S_LISTEN)){ + /*don't response*/ + goto OnProbeReqFail; + }else if(P2PMODE == P2P_TMP_GO ){ + /*will response but enter normal case*/ + goto normal_probe_req; + } + } + + /*------chk if target include B rate only ----- + ptmp = get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_,_SUPPORTEDRATES_IE_, + (int *)&len,pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); + if(ptmp){ + for(idx=0;idxpktlen - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_ - len); + if (ptmp != NULL) { + if (!memcmp(ptmp+2, WFA_OUI_PLUS_TYPE, 4)) { + IEfoundtimes ++; + memcpy(p2pIEPtr , ptmp+6 ,len-4); + p2pIEPtr+= (len-4); + } + } + else{ + break; + } + ptmp = ptmp + len + 2; + + } + + if(IEfoundtimes){ + + if(IEfoundtimes>1){ + P2P_DEBUG("ReAssembly p2p IE\n"); + } + p2pIElen = (int)(((unsigned long)p2pIEPtr)-((unsigned long)ReAssem_p2pie)); + + if(p2pIElen > MAX_REASSEM_P2P_IE){ + P2P_DEBUG("\n\n reassemble P2P IE exceed MAX_REASSEM_P2P_IE , chk!!!\n\n"); + }else{ + P2P_on_probe_req(priv, pfrinfo, ReAssem_p2pie, p2pIElen); + return SUCCESS; + } + } + else{ + if((P2PMODE == P2P_DEVICE) && (P2P_STATE == P2P_S_LISTEN)) + goto OnProbeReqFail; + else if(P2PMODE == P2P_TMP_GO ) + goto normal_probe_req; + } + /*------chk include P2P IE ------*/ + + } + + +normal_probe_req: +#endif + ssidptrx = get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); + + if (ssidptrx == NULL) + goto OnProbeReqFail; + + if (len == 0) { + if (HIDDEN_AP) + goto OnProbeReqFail; + else + goto send_rsp; + } + + if ((len != SSID_LEN) || + memcmp((void *)(ssidptrx+2), (void *)SSID, SSID_LEN)) { + if ((len == 3) && + ((*(ssidptrx+2) == 'A') || (*(ssidptrx+2) == 'a')) && + ((*(ssidptrx+3) == 'N') || (*(ssidptrx+3) == 'n')) && + ((*(ssidptrx+4) == 'Y') || (*(ssidptrx+4) == 'y'))) { + if (pmib->dot11OperationEntry.deny_any) + goto OnProbeReqFail; + else + if (HIDDEN_AP) + goto OnProbeReqFail; + else + goto send_rsp; + } + else + goto OnProbeReqFail; + } + +send_rsp: + + #ifdef CONFIG_RTK_MESH + if(pmib->dot1180211sInfo.meshSilence) { + return FAIL; + } + else if( pmib->dot1180211sInfo.mesh_enable && !pmib->dot1180211sInfo.mesh_ap_enable) { + issue_probersp(priv, GetAddr2Ptr(pframe), NULL, 0, 1, is_11b_only); + } + else + #endif + { + if(priv->pmib->dot11StationConfigEntry.probe_info_enable){ + if (check_probe_sta_rssi_valid(priv,GetAddr2Ptr(pframe),pfrinfo->rssi)) + add_probe_req_sta(priv,GetAddr2Ptr(pframe),pfrinfo->rssi); + } + issue_probersp(priv, GetAddr2Ptr(pframe), SSID, SSID_LEN, 1, is_11b_only); + } + return SUCCESS; + +OnProbeReqFail: + + return FAIL; +} + + +static unsigned int OnProbeRsp(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ +#ifdef WDS + struct stat_info *pstat = NULL; +#endif + +#if defined(CONFIG_RTL_WAPI_SUPPORT) + uint8 *p; + int len; +#endif + +#if defined(WDS)||defined(CONFIG_RTL_WAPI_SUPPORT) + unsigned char *pframe = get_pframe(pfrinfo); +#endif +// ==== modified by GANTOE for site survey 2008/12/25 ==== + if (OPMODE & WIFI_SITE_MONITOR) + { + +#ifdef P2P_SUPPORT + if( (OPMODE&WIFI_P2P_SUPPORT) && ((P2PMODE == P2P_DEVICE) || (P2PMODE == P2P_CLIENT))) + { + p2p_collect_bss_info(priv, pfrinfo); + } + else +#endif + { + collect_bss_info(priv, pfrinfo); + } + +#if defined(CONFIG_RTL_WAPI_SUPPORT) + p = get_ie(pframe + WLAN_HDR_A3_LEN, _EID_WAPI_, + &len, pfrinfo->pktlen); + if (p) + { + memcpy(priv->aeWapiIE, p, len+2); + priv->aeWapiIELength = len+2; + } +#endif + } +#ifdef WDS + else if ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11WdsInfo.wdsEnabled && + priv->pmib->dot11WdsInfo.wdsNum) { + pstat = get_stainfo(priv, (unsigned char *)GetAddr2Ptr(pframe)); + if (pstat && (pstat->state & WIFI_WDS)) { + collect_bss_info(priv, pfrinfo); + #if 0 + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)) + pstat->tx_bw = HT_CHANNEL_WIDTH_20_40; + else + pstat->tx_bw = HT_CHANNEL_WIDTH_20; + #endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } + assign_aggre_mthod(priv, pstat); + assign_tx_rate(priv, pstat, pfrinfo); + assign_aggre_size(priv, pstat); +#ifdef TX_SHORTCUT + /*Clear WDS station tx sc info*/ + memset(pstat->tx_sc_ent, 0x0, sizeof(pstat->tx_sc_ent)); +#endif + if (!pstat->wds_probe_done){ + //WDEBUG("\n=>wds_probe_done=1\n\n"); +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)){ + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); + // Have to inform firmware that wds is connectted, so RA can operate correctly + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + UpdateHalMSRRPT8812(priv, pstat, INCREASE); + } +#endif + pstat->wds_probe_done = 1; + } + } + } +#endif +#ifdef CONFIG_RTK_MESH // ==== GANTOE ==== + if(pfrinfo->is_11s) + return OnProbeRsp_MP(priv, pfrinfo); +#endif + + return SUCCESS; +} + + +static unsigned int OnBeacon(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + int i, len; + unsigned char *p, *pframe, channel; + + if (OPMODE & WIFI_SITE_MONITOR) { + collect_bss_info(priv, pfrinfo); + return SUCCESS; + } + + pframe = get_pframe(pfrinfo); + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) + channel = *(p+2); + else + channel = priv->pmib->dot11RFEntry.dot11channel; + + // If used as AP in G mode, need monitor other 11B AP beacon to enable + // protection mechanism +#ifdef WDS + // if WDS is used, need monitor other WDS AP beacon to decide tx rate + if (priv->pmib->dot11WdsInfo.wdsEnabled || + ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G|WIRELESS_11A)) && + (channel == priv->pmib->dot11RFEntry.dot11channel))) +#else + if ((OPMODE & WIFI_AP_STATE) && + (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G|WIRELESS_11A)) && + (channel == priv->pmib->dot11RFEntry.dot11channel)) +#endif + { + // look for ERP rate. if no ERP rate existed, thought it is a legacy AP + unsigned char supportedRates[32]; + int supplen=0, legacy=1; + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, + _SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p) { + if (len>8) + len=8; + memcpy(&supportedRates[supplen], p+2, len); + supplen += len; + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, + _EXT_SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p) { + if (len>8) + len=8; + memcpy(&supportedRates[supplen], p+2, len); + supplen += len; + } + +#ifdef WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled) { + struct stat_info *pstat = get_stainfo(priv, GetAddr2Ptr(pframe)); + if (pstat && !(pstat->state & WIFI_WDS_RX_BEACON)) { + get_matched_rate(priv, supportedRates, &supplen, 0); + update_support_rate(pstat, supportedRates, supplen); + if (supplen == 0) + pstat->current_tx_rate = 0; + else { + if (priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate == 0) { + pstat->current_tx_rate = find_rate(priv, pstat, 1, 0); + //pstat->upper_tx_rate = 0; // unused + } + } + + // Customer proprietary IE + if (priv->pmib->miscEntry.private_ie_len) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, + priv->pmib->miscEntry.private_ie[0], &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p) { + memcpy(pstat->private_ie, p, len + 2); + pstat->private_ie_len = len + 2; + } + } + + // Realtek proprietary IE + pstat->is_realtek_sta = FALSE; + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; len = 0; + for (;;) + { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, Realtek_OUI, 3) && *(p+2+3) == 2) { /*found realtek out and type == 2*/ + pstat->is_realtek_sta = TRUE; + break; + } + } + else + break; + p = p + len + 2; + } + +#ifdef WIFI_WMM + if (QOS_ENABLE) { + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + for (;;) { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, WMM_PARA_IE, 6)) { + pstat->QosEnabled = 1; + break; + } + } + else { + pstat->QosEnabled = 0; + break; + } + p = p + len + 2; + } + } +#endif + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + pstat->ht_cap_len = len; + memcpy((unsigned char *)&pstat->ht_cap_buf, p+2, len); + if (cpu_to_le16(pstat->ht_cap_buf.ht_cap_info) & _HTCAP_AMSDU_LEN_8K_) { + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 7935 - sizeof(struct wlan_hdr); + } + else { + pstat->is_8k_amsdu = 0; + pstat->amsdu_level = 3839 - sizeof(struct wlan_hdr); + } + } + else + pstat->ht_cap_len = 0; + } + + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)) + pstat->tx_bw = HT_CHANNEL_WIDTH_20_40; + else + pstat->tx_bw = HT_CHANNEL_WIDTH_20; + + + /*-----------------get VHT info------------------*/ +#ifdef RTK_AC_SUPPORT //WDS-VHT support + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) + { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTCapability, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if ((p != NULL) && (len <= sizeof(struct vht_cap_elmt))) { + pstat->vht_cap_len = len; + memcpy((unsigned char *)&pstat->vht_cap_buf, p+2, len); + //WDEBUG("vht_cap len = %d \n",len); + //WDEBUG("vht_cap vht_cap_info:%04X \n",pstat->vht_cap_buf.vht_cap_info); + //WDEBUG("vht_cap vht_support_mcs[0]=[%04X] ; vht_support_mcs[1]=[%04X] \n", pstat->vht_cap_buf.vht_support_mcs[0],pstat->vht_cap_buf.vht_support_mcs[1]); + + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTOperation, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if ((p != NULL) && (len <= sizeof(struct vht_oper_elmt))) { + pstat->vht_oper_len = len; + memcpy((unsigned char *)&pstat->vht_oper_buf, p+2, len); + //WDEBUG("vht_oper len = %d \n",len); + //WDEBUG("vht_oper: 0[%02x],1[%02x],2[%02x] \n",pstat->vht_oper_buf.vht_oper_info[0],pstat->vht_oper_buf.vht_oper_info[1],pstat->vht_oper_buf.vht_oper_info[2]); + //WDEBUG("vht_oper [%02X]\n",pstat->vht_oper_buf.vht_basic_msc); + + } + + if(pstat->vht_cap_len){ + switch(cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & 0x3) { + default: + case 0: + pstat->is_8k_amsdu = 0; + pstat->amsdu_level = 3895 - sizeof(struct wlan_hdr); + break; + case 1: + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 7991 - sizeof(struct wlan_hdr); + break; + case 2: + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 11454 - sizeof(struct wlan_hdr); + break; + } + + if ((priv->vht_oper_buf.vht_oper_info[0] == 1) && (pstat->vht_oper_buf.vht_oper_info[0] == 1)) { + pstat->tx_bw = HT_CHANNEL_WIDTH_80; + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_80; + //WDEBUG("pstat->tx_bw=80M\n"); + } + + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTOperatingMode, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if ((p != NULL) && (len == 1)) { + // check self capability.... + if((p[2] &3) <= priv->pmib->dot11nConfigEntry.dot11nUse40M) + pstat->tx_bw = p[2] &3; + pstat->nss = ((p[2]>>4)&0x7)+1; + //WDEBUG("receive opering mode data = %02X\n" ,p[2]); + } + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + + //WDEBUG("UpdateHalRAMask8812 \n"); + UpdateHalRAMask8812(priv, pstat, 3); + //WDEBUG("UpdateHalMSRRPT8812 \n"); + UpdateHalMSRRPT8812(priv, pstat, INCREASE); + } +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)){ + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + } +#endif + + } +#endif + /*-----------------get VHT info------------------*/ + + assign_tx_rate(priv, pstat, pfrinfo); + assign_aggre_mthod(priv, pstat); + assign_aggre_size(priv, pstat); + pstat->state |= WIFI_WDS_RX_BEACON; + } + + if (pstat && pstat->state & WIFI_WDS) { + pstat->beacon_num++; + if (!pstat->wds_probe_done){ + pstat->wds_probe_done = 1; + collect_bss_info(priv, pfrinfo); +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)){ + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); + // Have to inform firmware that wds is connectted, so RA can operate correctly + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + UpdateHalMSRRPT8812(priv, pstat, INCREASE); + } +#endif + assign_aggre_mthod(priv, pstat); + assign_aggre_size(priv, pstat); + //WDEBUG("\n=>wds_probe_done=1\n\n"); + } + } + } +#endif + + for (i=0; ipktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p && (*(p+2) & BIT(0))) + legacy = 1; + } + + if (legacy) { + if (!priv->pmib->dot11StationConfigEntry.olbcDetectDisabled && + priv->pmib->dot11ErpInfo.olbcDetected==0) { + priv->pmib->dot11ErpInfo.olbcDetected = 1; + check_protection_shortslot(priv); + DEBUG_INFO("OLBC detected\n"); + } + if (priv->pmib->dot11ErpInfo.olbcDetected) + priv->pmib->dot11ErpInfo.olbcExpired = DEFAULT_OLBC_EXPIRE; + } + } + + if ((OPMODE & WIFI_AP_STATE) && + (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) +// && (channel == priv->pmib->dot11RFEntry.dot11channel) + ) + { + if (!priv->pmib->dot11StationConfigEntry.protectionDisabled && + !priv->pmib->dot11StationConfigEntry.olbcDetectDisabled) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, + &len, pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p == NULL) + priv->ht_legacy_obss_to = 60; + } + + if (!priv->pmib->dot11StationConfigEntry.protectionDisabled && + !priv->pmib->dot11StationConfigEntry.nmlscDetectDisabled) { + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + struct ht_info_elmt *ht_info=(struct ht_info_elmt *)(p+2); + if (len) { + unsigned int prot_mode = (cpu_to_le16(ht_info->info1) & 0x03); + if (prot_mode == _HTIE_OP_MODE3_) + priv->ht_nomember_legacy_sta_to= 60; + } + } + } + } + +#ifdef WIFI_11N_2040_COEXIST + if (priv->pmib->dot11nConfigEntry.dot11nCoexist && (OPMODE & WIFI_AP_STATE) && + (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G)) && + priv->pshare->is_40m_bw) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, + &len, pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if ((p == NULL) && bg_ap_rssi_chk(priv, pfrinfo, channel)) { + + if (channel && (priv->pmib->dot11nConfigEntry.dot11nCoexist_ch_chk ? + (channel != priv->pmib->dot11RFEntry.dot11channel) :1)) + { + if(!priv->bg_ap_timeout) { + priv->bg_ap_timeout = 60; +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + } + priv->bg_ap_timeout = 60; + } + } + } +#endif + + +#ifdef CONFIG_RTK_MESH + if(pfrinfo->is_11s) { + OnBeacon_MP(priv, pfrinfo); + } +#endif + + return SUCCESS; +} + + +static unsigned int OnDisassoc(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *pframe; + struct stat_info *pstat; + unsigned char *sa; + unsigned short reason; + DOT11_DISASSOCIATION_IND Disassociation_Ind; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + pframe = get_pframe(pfrinfo); + sa = GetAddr2Ptr(pframe); + pstat = get_stainfo(priv, sa); + + if (pstat == NULL) + return 0; + +#ifdef CONFIG_POWER_SAVE + priv->pshare->xfer_seq++; +#endif + +#ifdef CONFIG_IEEE80211W + if (pstat->isPMF) { + pstat->isPMF = 0; // transmit unprotected mgmt frame + } +#endif + +#ifdef RTK_WOW + if (pstat->is_rtk_wow_sta) + return 0; +#endif + +#ifdef P2P_SUPPORT + P2P_DEBUG(" ............on DisAssoc\n"); + MAC_PRINT(pstat->hwaddr); + if(OPMODE&WIFI_P2P_SUPPORT && (P2PMODE == P2P_TMP_GO)){ + if(pstat->is_p2p_client){ + p2p_client_remove(priv,pstat); + } + } +#endif + + reason = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN )); + DEBUG_INFO("receiving disassoc from station %02X%02X%02X%02X%02X%02X reason %d\n", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5], reason); + +#ifdef MULTI_MAC_CLONE + __del_mclone_addr(priv, pstat->hwaddr);//this function only AP in. +#endif + + SAVE_INT_AND_CLI(flags); + + if (asoc_list_del(priv, pstat)) + { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + } +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E && pstat->sta_in_firmware == 1) { + RTL8188E_MACID_NOLINK(priv, 1, REMAP_AID(pstat)); + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } +#endif + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if(pstat && (REMAP_AID(pstat) < 128)) + { + DEBUG_WARN("%s %d OnDisassoc, set MACID 0 AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0 , REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + else + { + DEBUG_WARN(" MACID sleep only support 128 STA \n"); + } + } +#endif + + } + +#ifdef CONFIG_RTL8186_KB + if (priv->pmib->dot11OperationEntry.guest_access || (pstat && pstat->ieee8021x_ctrlport == DOT11_PortStatus_Guest)) + { + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == 0) + { + /* hotel style guest access */ + set_guestmacinvalid(priv, sa); + } + } +#endif + + // Need change state back to autehnticated + if (IEEE8021X_FUN) + { +#if !defined(WITHOUT_ENQUEUE) && (!defined(RTK_NL80211) || defined(NON_NL80211_AP)) + memcpy((void *)Disassociation_Ind.MACAddr, (void *)sa, MACADDRLEN); + Disassociation_Ind.EventId = DOT11_EVENT_DISASSOCIATION_IND; + Disassociation_Ind.IsMoreEvent = 0; + Disassociation_Ind.Reason = reason; + Disassociation_Ind.tx_packets = pstat->tx_pkts; + Disassociation_Ind.rx_packets = pstat->rx_pkts; + Disassociation_Ind.tx_bytes = pstat->tx_bytes; + Disassociation_Ind.rx_bytes = pstat->rx_bytes; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Disassociation_Ind, + sizeof(DOT11_DISASSOCIATION_IND)); +#endif + } + + release_stainfo(priv, pstat); + init_stainfo(priv, pstat); + pstat->state |= WIFI_AUTH_SUCCESS; + pstat->expire_to = priv->assoc_to; + auth_list_add(priv, pstat); + + RESTORE_INT(flags); + + if (IEEE8021X_FUN) + { +#if defined(INCLUDE_WPA_PSK) + psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, sa, NULL, 0); +#elif defined(WIFI_HAPD) || defined(RTK_NL80211) + nl80211_psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, sa, NULL, 0); +#endif + } + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->sta_status_cb_func) + priv->sta_status_cb_func("wlan0", sa, WIFI_STA_STATUS_DISASSOCIATED); +#else + LOG_MSG("A wireless client is disassociated - %02X:%02X:%02X:%02X:%02X:%02X\n", + *sa, *(sa+1), *(sa+2), *(sa+3), *(sa+4), *(sa+5)); +#endif +#if defined(RTK_NL80211) && !defined(NON_NL80211_AP) + event_indicate_cfg80211(priv, sa, CFG80211_DEL_STA, NULL); +#elif defined(WIFI_HAPD) + event_indicate_hapd(priv, sa, HAPD_EXIRED, NULL); +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, sa, 2); +#endif +#else + event_indicate(priv, sa, 2); +#endif + + + return SUCCESS; +} + + +static unsigned int OnAuth(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned int privacy,seq, len; + unsigned long flags=0; + struct list_head *phead, *plist; + struct wlan_acl_node *paclnode; + unsigned int acl_mode; + + struct wifi_mib *pmib; + struct stat_info *pstat=NULL; + unsigned char *pframe, *sa, *p; + unsigned int res=FAIL; + UINT16 algorithm; + int status, alloc_pstat=0; + struct ac_log_info *log_info; + + pmib = GET_MIB(priv); + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + UINT8 isMeshMP = FALSE, prevState = MP_UNUSED; +#endif + acl_mode = priv->pmib->dot11StationConfigEntry.dot11AclMode; + pframe = get_pframe(pfrinfo); + sa = GetAddr2Ptr(pframe); + pstat = get_stainfo(priv, sa); + + if (!IS_DRV_OPEN(priv)) + return FAIL; + if (!(OPMODE & WIFI_AP_STATE)) + return FAIL; + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) // Is Mesh MP? + if ((1 == GET_MIB(priv)->dot1180211sInfo.mesh_enable) && (NULL != pstat) && isPossibleNeighbor(pstat)) { + prevState = pstat->mesh_neighbor_TBL.State; + isMeshMP = TRUE; + } +#endif +#ifdef WDS +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if ((pmib->dot11WdsInfo.wdsPure) && (isMeshMP==FALSE)) +#else + if (pmib->dot11WdsInfo.wdsPure) +#endif + return FAIL; +#endif + + if (pmib->miscEntry.func_off) + return FAIL; + +#ifdef CONFIG_POWER_SAVE + priv->pshare->xfer_seq++; +#endif + + privacy = priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm; + + seq = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + 2)); + + algorithm = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN)); + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + MESH_DEBUG_MSG("\nMesh: Auth START !! seq=%d\n", seq); + + if (FALSE == isMeshMP) +#endif + { + if (GetPrivacy(pframe)) + { + int use_keymapping=0; + status = wep_decrypt(priv, pfrinfo, pfrinfo->pktlen, + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm, use_keymapping); + + if (status == FALSE) + { + SAVE_INT_AND_CLI(flags); +#ifdef CONFIG_RTL8196B_TLD + LOG_MSG_DEL("[WLAN access rejected: incorrect security] from MAC address: %02x:%02x:%02x:%02x:%02x:%02x,\n", + sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); +#endif + + DEBUG_ERR("wep-decrypt a Auth frame error!\n"); + status = _STATS_CHALLENGE_FAIL_; + goto auth_fail; + } + + seq = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + 4 + 2)); + algorithm = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + 4)); + } +#ifdef WIFI_SIMPLE_CONFIG +#ifndef CONFIG_RTL8196B_TLD + else { + if (pmib->wscEntry.wsc_enable && (seq == 1) && (algorithm == 0)) + privacy = 0; + } +#endif +#endif + + DEBUG_INFO("auth alg=%x, seq=%X\n", algorithm, seq); + + if (privacy == 2 && + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_40_PRIVACY_ && + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_104_PRIVACY_) + privacy = 0; + + if ((algorithm > 0 && privacy == 0) || // rx a shared-key auth but shared not enabled + (algorithm == 0 && privacy == 1) ) // rx a open-system auth but shared-key is enabled + { + SAVE_INT_AND_CLI(flags); + DEBUG_ERR("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n", + algorithm, privacy, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); +#ifdef CONFIG_RTL8196B_TLD + LOG_MSG_DEL("[WLAN access rejected: incorrect security] from MAC address: %02x:%02x:%02x:%02x:%02x:%02x,\n", + sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); +#endif + status = _STATS_NO_SUPP_ALG_; + goto auth_fail; + } + +#ifdef WIFI_SIMPLE_CONFIG + wsc_disconn_list_update(priv, sa); +#endif + + // STA ACL check;nctu note + SAVE_INT_AND_CLI(flags); + SMP_LOCK_ACL(flags); + + phead = &priv->wlan_acl_list; + plist = phead->next; + //check sa + if (acl_mode == 1) // 1: positive check, only those on acl_list can be connected. + res = FAIL; + else + res = SUCCESS; + + while(plist != phead) + { + paclnode = list_entry(plist, struct wlan_acl_node, list); + plist = plist->next; + if (!memcmp((void *)sa, paclnode->addr, 6)) { + if (paclnode->mode & 2) { // deny + res = FAIL; + break; + } + else { + res = SUCCESS; + break; + } + } + } + + RESTORE_INT(flags); + SMP_UNLOCK_ACL(flags); + +#if defined(CONFIG_RTK_MESH) && defined(MESH_ESTABLISH_RSSI_THRESHOLD) + if (pfrinfo->rssi < priv->mesh_fake_mib.establish_rssi_threshold) + res = FAIL; +#endif + +#ifdef __DRAYTEK_OS__ + if (res == SUCCESS) { + if (cb_auth_request(priv->dev, sa) != 0) + res = FAIL; + } +#endif + + if (res != SUCCESS) { + DEBUG_ERR("auth abort because ACL!\n"); + + log_info = aclog_lookfor_entry(priv, sa); + if (log_info) { + aclog_update_entry(log_info, sa); + + if (log_info->cur_cnt == 1) { // first time trigger +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_DROP("Unauthorized wireless PC try to connect;note:%02x:%02x:%02x:%02x:%02x:%02x;\n", + *sa, *(sa+1), *(sa+2), *(sa+3), *(sa+4), *(sa+5)); +#elif defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) + LOG_MSG_DROP("Unauthorized wireless PC try to connect;note:%02x:%02x:%02x:%02x:%02x:%02x;\n", + *sa, *(sa+1), *(sa+2), *(sa+3), *(sa+4), *(sa+5)); +#elif defined(CONFIG_RTL8196B_TLD) + LOG_MSG_DEL("[WLAN access denied] from MAC: %02x:%02x:%02x:%02x:%02x:%02x,\n", + *sa, *(sa+1), *(sa+2), *(sa+3), *(sa+4), *(sa+5)); +#else + LOG_MSG("A wireless client was rejected due to access control - %02X:%02X:%02X:%02X:%02X:%02X\n", + *sa, *(sa+1), *(sa+2), *(sa+3), *(sa+4), *(sa+5)); +#endif + log_info->last_cnt = log_info->cur_cnt; + + if (priv->acLogCountdown == 0) + priv->acLogCountdown = AC_LOG_TIME; + } + } + return FAIL; + } + + if (priv->pmib->dot11StationConfigEntry.supportedStaNum) { + if (!pstat && priv->assoc_num >= priv->pmib->dot11StationConfigEntry.supportedStaNum) { + DEBUG_ERR("Exceed the upper limit of supported clients...\n"); + status = _STATS_UNABLE_HANDLE_STA_; + goto auth_fail; + } + } + } //if MESH is enable here is end of (FALSE == isMeshMP) + + // (below, share with Mesh) due to the free_statinfo in AUTH_TO, we should enter critical section here! + SAVE_INT_AND_CLI(flags); + + if (pstat == NULL) // STA only, other one, Don't detect peer MP myself, But peer MP detect me and send Auth request.;nctu note + { +#ifdef CONFIG_RTK_MESH + // Denied STA auth, When MP configure MAP "OFF"(beacon or ProbeREQ/RSP AP information OFF), and STA ignore these information. + if (((1 == GET_MIB(priv)->dot1180211sInfo.mesh_enable) && (0 == GET_MIB(priv)->dot1180211sInfo.mesh_ap_enable)) || + GET_MIB(priv)->dot1180211sInfo.meshSilence) { + status = _STATS_OTHER_; + goto auth_fail; + } +#endif + + // allocate a new one + DEBUG_INFO("going to alloc stainfo for sa=%02X%02X%02X%02X%02X%02X\n", sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]); + pstat = alloc_stainfo(priv, sa, -1); + + if (pstat == NULL) + { + DEBUG_ERR("Exceed the upper limit of supported clients...\n"); + status = _STATS_UNABLE_HANDLE_STA_; + goto auth_fail; + } + pstat->state = WIFI_AUTH_NULL; + pstat->auth_seq = 0; // clear in alloc_stainfo;nctu note + pstat->tpcache_mgt = GetTupleCache(pframe); + } +#ifdef CONFIG_IEEE80211W + else if (pstat->isPMF) + { + pstat->auth_seq = seq + 1; + goto auth_success; + } +#endif + else + { // close exist connection.;nctu note + if (asoc_list_del(priv, pstat)) + { +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if ((TRUE == isMeshMP) // fix: 00000053 2007/12/11 NOTE!! Best solution detail see bug report !! + && ((pstat->mesh_neighbor_TBL.State == MP_SUPERORDINATE_LINK_UP) || (pstat->mesh_neighbor_TBL.State == MP_SUBORDINATE_LINK_UP) + || (pstat->mesh_neighbor_TBL.State == MP_SUPERORDINATE_LINK_DOWN) || (pstat->mesh_neighbor_TBL.State == MP_SUBORDINATE_LINK_DOWN_E))) + { +#if 0 + LOG_MESH_MSG("OnAuth mesh_cnt_ASSOC_PeerLink_CAP(-)\n"); +#endif + mesh_cnt_ASSOC_PeerLink_CAP(priv, pstat, DECREASE); + SMP_LOCK_MESH_MP_HDR(flags); + if (!list_empty(&pstat->mesh_mp_ptr)) // add by Galileo + list_del_init(&(pstat->mesh_mp_ptr)); + SMP_UNLOCK_MESH_MP_HDR(flags); + + } +#endif + + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + } + } + if (seq==1) { +#ifdef SUPPORT_TX_MCAST2UNI + int ipmc_num; + struct ip_mcast_info ipmc[MAX_IP_MC_ENTRY]; + + ipmc_num = pstat->ipmc_num; + if (ipmc_num) + memcpy(ipmc, pstat->ipmc, MAX_IP_MC_ENTRY * sizeof(struct ip_mcast_info)); +#endif + release_stainfo(priv, pstat); + init_stainfo(priv, pstat); +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv)==VERSION_8188E) +#ifdef RATEADAPTIVE_BY_ODM + ODM_RAInfo_Init(ODMPTR, pstat->aid); +#else + RateAdaptiveInfoInit(&priv->pshare->RaInfo[pstat->aid]); +#endif +#endif + + pstat->tpcache_mgt = GetTupleCache(pframe); +#ifdef SUPPORT_TX_MCAST2UNI + if (ipmc_num) { + pstat->ipmc_num = ipmc_num; + memcpy(pstat->ipmc, ipmc, MAX_IP_MC_ENTRY * sizeof(struct ip_mcast_info)); + } +#endif + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if (TRUE == isMeshMP) { + SMP_LOCK_MESH_MP_HDR(flags); + if (!list_empty(&pstat->mesh_mp_ptr)) + list_del_init(&pstat->mesh_mp_ptr); + SMP_UNLOCK_MESH_MP_HDR(flags); + + // Avoid pstat remain in system when can't auth, Not actually use + pstat->mesh_neighbor_TBL.BSexpire_LLSAperiod = jiffies + MESH_PEER_LINK_LISTEN_TO; + pstat->mesh_neighbor_TBL.State = MP_LISTEN; + pstat->state = WIFI_AUTH_NULL; + SET_PSEUDO_RANDOM_NUMBER(pstat->mesh_neighbor_TBL.LocalLinkID); + + SMP_LOCK_MESH_MP_HDR(flags); + list_add_tail(&(pstat->mesh_mp_ptr), &(priv->mesh_auth_hdr)); + SMP_UNLOCK_MESH_MP_HDR(flags); + + if (!(timer_pending(&priv->mesh_auth_timer))) // start timer if stop + mod_timer(&priv->mesh_auth_timer, jiffies + MESH_TIMER_TO); + } +#endif + + } + } + + auth_list_add(priv, pstat); + + if (pstat->auth_seq == 0) + pstat->expire_to = priv->auth_to; + + // Authentication Sequence (STA only) +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) // Mesh can't check, Because recived seq=1 and 2 + if((FALSE == isMeshMP) && ((pstat->auth_seq + 1) != seq)) +#else + if ((pstat->auth_seq + 1) != seq) +#endif + { + DEBUG_ERR("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", + seq, pstat->auth_seq+1); + status = _STATS_OUT_OF_AUTH_SEQ_; + goto auth_fail; + } + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if (algorithm == 0 && ((FALSE == isMeshMP && (privacy == 0 || privacy == 2)) || (TRUE == isMeshMP))) // open auth (STA & mesh) +#else + if (algorithm == 0 && (privacy == 0 || privacy == 2)) // STA only open auth +#endif + { +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if ((1 == seq) || ((2 == seq) && (TRUE == isMeshMP))) +#else + if (seq == 1) +#endif + { +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if((2 == seq) && ((MP_OPEN_SENT != prevState) || + (_STATS_SUCCESSFUL_ != cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + 2 + 2))))) + return FAIL; +#endif + + pstat->state &= ~WIFI_AUTH_NULL; + pstat->state |= WIFI_AUTH_SUCCESS; + pstat->expire_to = priv->assoc_to; + pstat->AuthAlgrthm = algorithm; + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if (TRUE == isMeshMP) { // Authentication Success + + SMP_LOCK_MESH_MP_HDR(flags); + if (!list_empty(&pstat->mesh_mp_ptr)) // mesh_auth_hdr -> mesh_unEstablish_hdr + list_del_init(&(pstat->mesh_mp_ptr)); + SMP_UNLOCK_MESH_MP_HDR(flags); + + if ((1 == seq) && (MP_OPEN_SENT != prevState)) { // Passive + pstat->expire_to = priv->assoc_to; + MESH_DEBUG_MSG("Mesh: Auth Successful... seq = '%d', state = '%d', And 'PASSIVE' connect\n", seq, prevState); + pstat->mesh_neighbor_TBL.BSexpire_LLSAperiod = jiffies + MESH_PEER_LINK_LISTEN_TO; + pstat->mesh_neighbor_TBL.State = MP_LISTEN; + } else { // Active (include associated) + MESH_DEBUG_MSG("Mesh: Auth Successful... seq = '%d', state = '%d', And 'ACTIVE' connect\n", seq, prevState); + pstat->mesh_neighbor_TBL.BSexpire_LLSAperiod = jiffies + MESH_PEER_LINK_RETRY_TO; + pstat->mesh_neighbor_TBL.retry = 0; + pstat->mesh_neighbor_TBL.State = MP_OPEN_SENT; + } + + SMP_LOCK_MESH_MP_HDR(flags); + list_add_tail(&(pstat->mesh_mp_ptr), &(priv->mesh_unEstablish_hdr)); + SMP_UNLOCK_MESH_MP_HDR(flags); + + if (!(timer_pending(&priv->mesh_peer_link_timer))) // start timer if stop + mod_timer(&priv->mesh_peer_link_timer, jiffies + MESH_TIMER_TO); + + } +#endif + + } + else + { + DEBUG_ERR("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", + seq, pstat->auth_seq+1); + status = _STATS_OUT_OF_AUTH_SEQ_; + goto auth_fail; + } + } + else // shared system or auto authentication (STA only). + { +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if (TRUE == isMeshMP) { + MESH_DEBUG_MSG("Mesh: Auth rejected because You're Mesh MP, but use incorrect algorithm = %d!\n", algorithm); + status = _STATS_CHALLENGE_FAIL_; + goto auth_fail; + } +#endif + if (seq == 1) + { + //prepare for the challenging txt... + get_random_bytes((void *)pstat->chg_txt, 128); + pstat->state &= ~WIFI_AUTH_NULL; + pstat->state |= WIFI_AUTH_STATE1; + pstat->AuthAlgrthm = algorithm; + pstat->auth_seq = 2; + } + else if (seq == 3) + { + //checking for challenging txt... + p = get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); + if ((p != NULL) && !memcmp((void *)(p + 2),pstat->chg_txt, 128)) + { + pstat->state &= (~WIFI_AUTH_STATE1); + pstat->state |= WIFI_AUTH_SUCCESS; + // challenging txt is correct... + pstat->expire_to = priv->assoc_to; + } + else + { + DEBUG_ERR("auth rejected because challenge failure!\n"); + status = _STATS_CHALLENGE_FAIL_; +#ifdef CONFIG_RTL8196B_TLD + LOG_MSG_DEL("[WLAN access rejected: incorrect security] from MAC address: %02x:%02x:%02x:%02x:%02x:%02x,\n", + sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); +#endif + goto auth_fail; + } + } + else + { + DEBUG_ERR("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", + seq, pstat->auth_seq+1); + status = _STATS_OUT_OF_AUTH_SEQ_; + goto auth_fail; + } + } + + // Now, we are going to issue_auth... + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if (TRUE == isMeshMP) + pstat->auth_seq = 2; // Mesh send seq=2 (response) only + else +#endif + pstat->auth_seq = seq + 1; +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if ((FALSE == isMeshMP) || ((1 == seq) && (TRUE == isMeshMP))) +#endif + issue_auth(priv, pstat, (unsigned short)(_STATS_SUCCESSFUL_)); + + if (pstat->state & WIFI_AUTH_SUCCESS) // STA valid + pstat->auth_seq = 0; + + RESTORE_INT(flags); + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if ((TRUE == isMeshMP) && ( MP_OPEN_SENT == pstat->mesh_neighbor_TBL.State) && (2 == seq)) // Active 2==seq , auth success prevState is MP_OPEN_SENT + issue_assocreq_MP(priv, pstat); +#endif + + return SUCCESS; +auth_success: + + issue_auth(priv, pstat, (unsigned short)(_STATS_SUCCESSFUL_)); + + if (pstat->state & WIFI_AUTH_SUCCESS) // STA valid + pstat->auth_seq = 0; + + RESTORE_INT(flags); + +#if defined(CONFIG_RTK_MESH) && defined(MESH_BOOTSEQ_AUTH) + if ((TRUE == isMeshMP) && ( MP_OPEN_SENT == pstat->mesh_neighbor_TBL.State) && (2 == seq)) // Active 2==seq , auth success prevState is MP_OPEN_SENT + issue_assocreq_MP(priv, pstat); +#endif + + return SUCCESS; + +auth_fail: + + if ((OPMODE & WIFI_AP_STATE) && (pstat == NULL)) { + pstat = (struct stat_info *)kmalloc(sizeof(struct stat_info), GFP_ATOMIC); + if (pstat == NULL) { + RESTORE_INT(flags); + return FAIL; + } + + alloc_pstat = 1; + memset(pstat, 0, sizeof(struct stat_info)); + + pstat->auth_seq = 2; + memcpy(pstat->hwaddr, sa, 6); + pstat->AuthAlgrthm = algorithm; + } + else { + alloc_pstat = 0; + pstat->auth_seq = seq + 1; + } + + issue_auth(priv, pstat, (unsigned short)status); +#ifdef TLN_STATS + stats_conn_status_counts(priv, status); +#endif + + if (alloc_pstat) + kfree(pstat); + + SNMP_MIB_ASSIGN(dot11AuthenticateFailStatus, status); + SNMP_MIB_COPY(dot11AuthenticateFailStation, sa, MACADDRLEN); + + RESTORE_INT(flags); + + return FAIL; +} + + + +/** + * @brief AP recived De-Authentication + * + */ +static unsigned int OnDeAuth(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *pframe; + struct stat_info *pstat; + unsigned char *sa; + unsigned short reason; + DOT11_DISASSOCIATION_IND Disassociation_Ind; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + pframe = get_pframe(pfrinfo); + sa = GetAddr2Ptr(pframe); + pstat = get_stainfo(priv, sa); + + if (pstat == NULL) + return 0; + +#ifdef CONFIG_POWER_SAVE + priv->pshare->xfer_seq++; +#endif + +#if defined(CONFIG_IEEE80211W) || defined(RTK_NL80211_HS_CLI) + if (pstat->isPMF) { + pstat->isPMF = 0; + } +#endif +#ifdef RTK_WOW + if (pstat->is_rtk_wow_sta) + return 0; +#endif + +#ifdef P2P_SUPPORT + P2P_DEBUG("on deauth\n"); + MAC_PRINT(pstat->hwaddr); + if(OPMODE&WIFI_P2P_SUPPORT && (P2PMODE == P2P_TMP_GO)){ + if(pstat->is_p2p_client) + p2p_client_remove(priv,pstat); + } +#endif + + reason = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN )); + DEBUG_INFO("receiving deauth from station %02X%02X%02X%02X%02X%02X reason %d\n", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5], reason); + +#ifdef MULTI_MAC_CLONE + __del_mclone_addr(priv, pstat->hwaddr);//this function only AP in. +#endif + + SAVE_INT_AND_CLI(flags); + if (asoc_list_del(priv, pstat)) + { + if (pstat->expire_to > 0) + { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + +#ifdef CONFIG_RTK_MESH + if (isPossibleNeighbor(pstat)) + { +#if 0 + LOG_MESH_MSG("OnDeAuth mesh_cnt_ASSOC_PeerLink_CAP(-)\n"); +#endif + mesh_cnt_ASSOC_PeerLink_CAP(priv, pstat, DECREASE); + } +#endif + } +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E && pstat->sta_in_firmware == 1) { + RTL8188E_MACID_NOLINK(priv, 1, REMAP_AID(pstat)); + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } +#endif + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if(pstat && (REMAP_AID(pstat) < 128)) + { + DEBUG_WARN("%s %d OnDeAuth, set MACID 0 AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + else + { + DEBUG_WARN(" MACID sleep only support 128 STA \n"); + } + } +#endif + + } + RESTORE_INT(flags); + +#ifdef BEAMFORMING_SUPPORT + if (priv->pmib->dot11RFEntry.txbf == 1 && (GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv) == VERSION_8192E || GET_CHIP_VER(priv) == VERSION_8814A) ) + { + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s,\n", __FUNCTION__)); + + pBeamformingInfo->CurDelBFerBFeeEntrySel = BFerBFeeEntry; + + if(Beamforming_DeInitEntry(priv, pstat->hwaddr)) + Beamforming_Notify(priv); + } +#endif + + + free_stainfo(priv, pstat); + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->sta_status_cb_func) + priv->sta_status_cb_func("wlan0", sa, WIFI_STA_STATUS_DEAUTHENTICATED); +#else + LOG_MSG("A wireless client is deauthenticated - %02X:%02X:%02X:%02X:%02X:%02X\n", + *sa, *(sa+1), *(sa+2), *(sa+3), *(sa+4), *(sa+5)); +#endif + + if (IEEE8021X_FUN) + { +#if !defined(WITHOUT_ENQUEUE) && (!defined(RTK_NL80211) || defined(NON_NL80211_AP)) +#ifdef CONFIG_RTK_MESH + if (isSTA(pstat)) +#endif + { + memcpy((void *)Disassociation_Ind.MACAddr, (void *)sa, MACADDRLEN); + Disassociation_Ind.EventId = DOT11_EVENT_DISASSOCIATION_IND; + Disassociation_Ind.IsMoreEvent = 0; + Disassociation_Ind.Reason = reason; + Disassociation_Ind.tx_packets = pstat->tx_pkts; + Disassociation_Ind.rx_packets = pstat->rx_pkts; + Disassociation_Ind.tx_bytes = pstat->tx_bytes; + Disassociation_Ind.rx_bytes = pstat->rx_bytes; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Disassociation_Ind, + sizeof(DOT11_DISASSOCIATION_IND)); + } +#endif +#if defined(INCLUDE_WPA_PSK) + psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, sa, NULL, 0); +#elif defined(WIFI_HAPD) || defined(RTK_NL80211) + nl80211_psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, sa, NULL, 0); +#endif + } + +#if defined(RTK_NL80211) && !defined(NON_NL80211_AP) + event_indicate_cfg80211(priv, sa, CFG80211_DEL_STA, NULL); +#elif defined(WIFI_HAPD) + event_indicate_hapd(priv, sa, HAPD_EXIRED, NULL); +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, sa, 2); +#endif +#else + event_indicate(priv, sa, 2); +#endif + + return SUCCESS; +} + + +static unsigned int OnWmmAction(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ +#if defined(P2P_SUPPORT) || defined(HS2_SUPPORT) || defined(RTK_NL80211_HS_CLI) + int needRdyAssoc=1; +#endif +#ifdef CONFIG_RTK_MESH + // please add the codes to check where the action frame is rreq, rrep or rrer + // (check the action field ) + if (pfrinfo->is_11s) { + unsigned char *pframe, *pFrameBody; + unsigned char action_type = -1, category_type; + int Is_6Addr = 0; + + pframe = get_pframe(pfrinfo); // get frame data + + if (pframe!=0) { + if(is_mesh_6addr_format_without_qos(pframe)) { + pFrameBody = pframe + WLAN_HDR_A6_MESH_DATA_LEN; + Is_6Addr = 1; + } else + pFrameBody = pframe + WLAN_HDR_A4_MESH_DATA_LEN; + + //pFrameBody = GetMeshMgtPtr(pframe); + // reason = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A4_MESH_MGT_LEN )); //len define ref to wifi.h + category_type = *pFrameBody; + action_type = *(pFrameBody+1); + + + +#ifdef MESH_USE_METRICOP + if(category_type == _CATEGORY_11K_ACTION_) + { + switch(action_type) { + case ACTION_FILED_11K_LINKME_REQ: + return On11kvLinkMeasureReq(priv, pfrinfo); + case ACTION_FILED_11K_LINKME_REP: + return On11kvLinkMeasureRep(priv, pfrinfo); + } + } +#endif + + if(category_type == _MESH_CATEGORY_ID_) { + switch(action_type) { + case _MESH_LINK_REPORT_ACTION_ID_: + OnLocalLinkStateANNOU_MP(priv, pfrinfo); + break; + case _HWMP_MESH_PATHSEL_ACTION_ID_: + case _GANN_ACTION_ID_: + OnPathSelectionManagFrame(priv, pfrinfo, Is_6Addr); + break; + + default: + printk("unknow action_type in OnWmmAction\n"); + goto ACTIVE_NOT_11S; + } + + } + else if(category_type == _MULTIHOP_CATEGORY_ID_) { + switch(action_type) { +#ifdef PU_STANDARD + case _PROXY_UPDATES_ACTION_ID_: + OnProxyUpdate_MP(priv,pfrinfo); + break; + case _PROXY_UPDATES_CONFIRM_ACTION_ID_: + OnProxyUpdateConfirm_MP(priv,pfrinfo); + break; +#endif + default: + printk("unknow action_type in OnWmmAction\n"); + goto ACTIVE_NOT_11S; + } + + } + else { + goto ACTIVE_NOT_11S; + } + } + return SUCCESS; + } + +ACTIVE_NOT_11S: +#endif // CONFIG_RTK_MESH + +#ifdef WIFI_WMM + if (QOS_ENABLE +#ifdef P2P_SUPPORT + || (OPMODE&WIFI_P2P_SUPPORT) +#endif + ) { + unsigned char *sa = pfrinfo->sa; + unsigned char *da = pfrinfo->da; + struct stat_info *pstat = get_stainfo(priv, sa); + unsigned char *pframe=NULL; + unsigned char Category_field=0, Action_field=0, previous_mimo_ps=0; + unsigned char TID=0; + unsigned short blockAck_para=0, status_code=_STATS_SUCCESSFUL_, timeout=0, reason_code, max_size; +#ifdef TX_SHORTCUT + unsigned int do_tx_slowpath = 0; +#endif +#ifdef HS2_SUPPORT + DOT11_HS2_GAS_REQ gas_req, gas_req2; +#endif + + // Reply in B/G mode to fix IOT issue with D-Link DWA-642 +#if 0 + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) || + (pstat && pstat->ht_cap_len == 0)) { + DEBUG_ERR("Drop Action frame!\n"); + return SUCCESS; + } +#endif + + pframe = get_pframe(pfrinfo) + WLAN_HDR_A3_LEN; //start of action frame content + Category_field = pframe[0]; + Action_field = pframe[1]; + +#if defined(HS2_SUPPORT) || defined(RTK_NL80211_HS_CLI) + if((Category_field==_PUBLIC_CATEGORY_ID_) && ((Action_field==_GAS_INIT_REQ_ACTION_ID_) || + (Action_field==_GAS_COMBACK_REQ_ACTION_ID_) || (Action_field==_GAS_INIT_RSP_ACTION_ID_) || + (Action_field==_GAS_COMBACK_RSP_ACTION_ID_))) + { + needRdyAssoc=0; + } + if ((Category_field==_DLS_CATEGORY_ID_) && (Action_field==_DLS_REQ_ACTION_ID_)) + needRdyAssoc=0; +#endif + + +#ifdef P2P_SUPPORT + if(OPMODE&WIFI_P2P_SUPPORT){ + if( (Category_field==4 && Action_field==9) + //|| (Category_field==_VENDOR_ACTION_ID_) + ) + { + needRdyAssoc=0; + } + } +#endif + + if ((!IS_MCAST(da)) && (pstat +#if defined(P2P_SUPPORT) || defined(HS2_SUPPORT) || defined(RTK_NL80211_HS_CLI) + || needRdyAssoc==0 +#endif + )) + { + + switch (Category_field) { +#ifdef DOT11H + case _SPECTRUM_MANAGEMENT_CATEGORY_ID_: + switch (Action_field) { + case _TPC_REQEST_ACTION_ID_: + if(priv->pmib->dot11hTPCEntry.tpc_enable) + issue_TPC_report(priv, sa, pframe[2]); + break; + case _TPC_REPORT_ACTION_ID_: + break; + default: + break; + } + break; +#endif + case _BLOCK_ACK_CATEGORY_ID_: + switch (Action_field) { + case _ADDBA_Req_ACTION_ID_: + blockAck_para = pframe[3] | (pframe[4] << 8); + timeout = 0; //pframe[5] | (pframe[6] << 8); + TID = (blockAck_para>>2)&0x000f; + max_size = (blockAck_para&0xffc0)>>6; + DEBUG_INFO("ADDBA-req recv fr AID %d, token %d TID %d size %d timeout %d\n", + pstat->aid, pframe[2], TID, max_size, timeout); + if (!(blockAck_para & BIT(1)) || (pstat->ht_cap_len == 0) + || (pstat->sta_in_firmware != 1 && priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _NO_PRIVACY_) + || priv->pmib->dot11nConfigEntry.dot11nAddBAreject + ){ // 0=delayed BA, 1=immediate BA + status_code = _STATS_REQ_DECLINED_; + }else{ + pstat->ADDBA_req_num[TID] = 0; + } + +#ifdef DZ_ADDBA_RSP + if (pstat && ((pstat->state & (WIFI_SLEEP_STATE | WIFI_ASOC_STATE)) == + (WIFI_SLEEP_STATE | WIFI_ASOC_STATE))) { + pstat->dz_addba.used = 1; + pstat->dz_addba.dialog_token = pframe[2]; + pstat->dz_addba.TID = TID; + pstat->dz_addba.status_code = status_code; + pstat->dz_addba.timeout = timeout; + } + else +#endif + if (!issue_ADDBArsp(priv, sa, pframe[2], TID, status_code, timeout)) + DEBUG_ERR("issue ADDBA-rsp failed\n"); + break; + case _DELBA_ACTION_ID_: + TID = (pframe[3] & 0xf0) >> 4; + pstat->ADDBA_ready[TID] = 0; + pstat->ADDBA_req_num[TID] = 0; + pstat->ADDBA_sent[TID] = 0; + reason_code = pframe[4] | (pframe[5] << 8); + DEBUG_INFO("DELBA recv from AID %d, TID %d reason %d\n", pstat->aid, TID, reason_code); +#ifdef TX_SHORTCUT + do_tx_slowpath++; +#endif + break; + case _ADDBA_Rsp_ACTION_ID_: + blockAck_para = pframe[5] | (pframe[6] << 8); + status_code = pframe[3] | (pframe[4] << 8); + TID = (blockAck_para>>2)&0x000f; + max_size = (blockAck_para&0xffc0)>>6; + if (status_code != _STATS_SUCCESSFUL_) { + pstat->ADDBA_ready[TID] = 0; + } else { + DEBUG_INFO("%s %d increase ADDBA_ready, clear ADDBA_sent\n",__func__,__LINE__); + pstat->ADDBA_ready[TID]++; + pstat->ADDBA_sent[TID] = 0; + } + pstat->ADDBA_req_num[TID] = 0; +#ifdef TX_SHORTCUT + do_tx_slowpath++; +#endif + DEBUG_INFO("ADDBA-rsp recv fr AID %d, token %d TID %d size %d status %d\n", + pstat->aid, pframe[2], TID, max_size, status_code); + break; + default: + DEBUG_ERR("Error BA Action frame is received\n"); + goto error_frame; + break; + } + break; + +#if defined(WIFI_11N_2040_COEXIST) || defined(P2P_SUPPORT) || defined(HS2_SUPPORT) || defined(RTK_NL80211_HS_CLI) + case _PUBLIC_CATEGORY_ID_: + switch (Action_field) { +#ifdef RTK_NL80211_HS_CLI + case _GAS_INIT_RSP_ACTION_ID_: + { + printk("cliw: GAS initial RSP Action frame\n"); + rtk_cfg80211_rx_mgmt(priv, pfrinfo, priv->nl_ctx.p2p_listen_channel); + } + break; + case _GAS_COMBACK_RSP_ACTION_ID_: + { + printk("cliw: GAS cimbo RSP Action frame\n"); + rtk_cfg80211_rx_mgmt(priv, pfrinfo, priv->nl_ctx.p2p_listen_channel); + } + break; +#endif + case _2040_COEXIST_ACTION_ID_: + if (priv->pmib->dot11nConfigEntry.dot11nCoexist) { + if (!(OPMODE & WIFI_AP_STATE)) { + DEBUG_WARN("Ignored Public Action frame received since this is not an AP\n"); + break; + } + if (!priv->pshare->is_40m_bw) { + DEBUG_WARN("Ignored Public Action frame received since AP is 20m mode\n"); + break; + } + if (!(priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G))) { + DEBUG_WARN("Ignored Public Action frame received since AP is not 2.4G band\n"); + break; + } + if (pframe[2] == _2040_BSS_COEXIST_IE_) { + if (pframe[4] & (_40M_INTOLERANT_ |_20M_BSS_WIDTH_REQ_)) { + if (pframe[4] & _40M_INTOLERANT_) { + DEBUG_INFO("Public Action frame: force 20m by 40m intolerant\n"); + } else { + DEBUG_INFO("Public Action frame: force 20m by 20m bss width req\n"); + } + + setSTABitMap(&priv->switch_20_sta, pstat->aid); + + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + } else { + if ((pframe[2+pframe[3]+2]) && (pframe[2+pframe[3]+2] == _2040_Intolerant_ChRpt_IE_)) { + int ch_idx, ch_len= pframe[2+pframe[3]+2+1]-1, ch; + DEBUG_INFO("Public Action frame: force 20m by channel report\n"); + for(ch_idx=0; ch_idx < ch_len; ch_idx++) { + ch = pframe[2+pframe[3]+2+3 + ch_idx]; + if( ch && (ch<=14) && (priv->pmib->dot11nConfigEntry.dot11nCoexist_ch_chk? + (ch != priv->pmib->dot11RFEntry.dot11channel):1) ) + { + setSTABitMap(&priv->switch_20_sta, pstat->aid); + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + break; + } + } + } else { + DEBUG_INFO("Public Action frame: cancel force 20m\n"); +#if 0 + + clearSTABitMap(&priv->switch_20_sta, pstat->aid); + +#if defined(WIFI_11N_2040_COEXIST_EXT) + clearSTABitMap(&priv->pshare->_40m_staMap, pstat->aid); +#endif +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 0); +#endif +#endif + } + } + +#ifdef TX_SHORTCUT + do_tx_slowpath++; +#endif + } else { + DEBUG_ERR("Error Public Action frame received\n"); + } + } else { + DEBUG_WARN("Public Action frame received but func off\n"); + } + break; +#ifdef HS2_SUPPORT + case _GAS_INIT_REQ_ACTION_ID_: + HS2_DEBUG_INFO("Receive GAS Init REQ\n"); + if (priv->pmib->hs2Entry.interworking_ielen) + { + int tmplen = pframe[4]; + gas_req.Reqlen = (pframe[5+tmplen+1] << 8) | pframe[4+tmplen+1]; + memcpy((void *)gas_req.MACAddr, (void *)sa, MACADDRLEN); + gas_req.EventId = DOT11_EVENT_GAS_INIT_REQ; + gas_req.IsMoreEvent = 0; + gas_req.Dialog_token = pframe[2]; + gas_req.Advt_proto = pframe[4+tmplen]; + + memcpy(gas_req.Req, &pframe[5+tmplen+2], gas_req.Reqlen); //copy ANQP content + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&gas_req, + sizeof(DOT11_HS2_GAS_REQ)); + + event_indicate(priv, sa, 1); + } + + break; + case _GAS_COMBACK_REQ_ACTION_ID_: + if (priv->pmib->hs2Entry.interworking_ielen) + { + memcpy((void *)gas_req.MACAddr, (void *)sa, MACADDRLEN); + HS2_DEBUG_INFO("GAS comback REQ Action frame\n"); + gas_req.EventId = DOT11_EVENT_GAS_COMEBACK_REQ; + gas_req.Dialog_token = pframe[2]; + + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&gas_req, + sizeof(DOT11_HS2_GAS_REQ)); + + event_indicate(priv, sa, 1); + } + break; +#ifdef HS2_CLIENT_TEST + case _GAS_INIT_RSP_ACTION_ID_: + { + HS2_DEBUG_INFO("GAS initial RSP Action frame\n"); + if ((pframe[5] != 0) || (testflg == 1)) + { + memcpy((void *)gas_req.MACAddr, (void *)sa, MACADDRLEN); + gas_req.Dialog_token = pframe[2]; + issue_GASreq(priv, &gas_req, 0); + testflg = 0; + } + } + break; + case _GAS_COMBACK_RSP_ACTION_ID_: + { + HS2_DEBUG_INFO("GAS combo RSP Action frame\n"); + if ((pframe[5] & 0x80 )!= 0) + { + memcpy((void *)gas_req.MACAddr, (void *)sa, MACADDRLEN); + gas_req.Dialog_token = pframe[2]; + issue_GASreq(priv, &gas_req, 0); + } + } + break; +#endif +#endif + +#ifdef P2P_SUPPORT + case _P2P_PUBLIC_ACTION_FIELD_: + if(!memcmp(&pframe[2] , WFA_OUI_PLUS_TYPE,4)){ + P2P_on_public_action(priv,pfrinfo); + } + break; +#endif + default: + DEBUG_INFO("Public Action frame received but not support yet\n"); + goto error_frame; + break; + } + break; +#endif +#ifdef CONFIG_IEEE80211W + case _SA_QUERY_CATEGORY_ID_: + PMFDEBUG("RX _SA_QUERY_CATEGORY_ID_\n"); + if (Action_field == _SA_QUERY_REQ_ACTION_ID_) { + PMFDEBUG("RX 11W_SA_Req\n"); + issue_SA_Query_Rsp(priv->dev, sa, pframe+2); + //if (IEEE8021X_FUN && priv->pmib->dot1180211AuthEntry.dot11EnablePSK) { + // PMFDEBUG("recv SA req..2\n"); + // psk_indicate_evt(priv, DOT11_EVENT_SA_QUERY, GetAddr2Ptr(pframe), pframe, 0); + //} + } else if (Action_field == _SA_QUERY_RSP_ACTION_ID_) { + int idx; + unsigned short trans_id = (unsigned short) (pframe[3] << 8) + pframe[2]; + for (idx = 1; idx <= pstat->sa_query_count; idx++) { + if (pstat->SA_TID[idx] == trans_id) + break; + } + if (idx > pstat->sa_query_count) { // No match + PMFDEBUG("RX 11W_SA_Rsp but comeback timeout\n"); + return SUCCESS; + } + PMFDEBUG("RX 11W_SA_Rsp\n"); + stop_sa_query(pstat); + } + break; +#endif // CONFIG_IEEE80211W +#ifdef RTK_AC_SUPPORT + case _VHT_ACTION_CATEGORY_ID_: + if (Action_field == _VHT_ACTION_OPMNOTIF_ID_) { +// int nss = ((pframe[4]>>4)&0x7); + if((pframe[2] &3) <= priv->pmib->dot11nConfigEntry.dot11nUse40M) + pstat->tx_bw = pframe[2] &3; + pstat->nss = ((pframe[2]>>4)&0x7)+1; +// pstat->vht_cap_buf.vht_support_mcs[0] |= cpu_to_le32(0xffff); +// pstat->vht_cap_buf.vht_support_mcs[0] &= ~ cpu_to_le32((1<<((nss+1)<<1))-1); +// panic_printk("Action 21, operating mode:%d, %d", pstat->tx_bw, pstat->nss); +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + UpdateHalRAMask8812(priv, pstat, 3); +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)){ + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + } +#endif + + + } + break; +#endif + case _HT_CATEGORY_ID_: + if (Action_field == _HT_MIMO_PS_ACTION_ID_) { + previous_mimo_ps = pstat->MIMO_ps; + pstat->MIMO_ps = 0; + if (pframe[2] & BIT(0)) { + if (pframe[2] & BIT(1)) + pstat->MIMO_ps|=_HT_MIMO_PS_DYNAMIC_; + else + pstat->MIMO_ps|=_HT_MIMO_PS_STATIC_; + } + if ((previous_mimo_ps|pstat->MIMO_ps)&_HT_MIMO_PS_STATIC_) { + assign_tx_rate(priv, pstat, pfrinfo); +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) { + UpdateHalRAMask8812(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } + } +#ifdef TX_SHORTCUT + if ((previous_mimo_ps|pstat->MIMO_ps)&_HT_MIMO_PS_DYNAMIC_) + do_tx_slowpath++; +#endif + check_NAV_prot_len(priv, pstat, 0); + } else { + DEBUG_INFO("HT Action Frame is received but not support yet\n"); + } + break; +#ifdef HS2_SUPPORT + case _WNM_CATEGORY_ID_: + switch (Action_field) { + case _WNM_TSMQUERY_ACTION_ID_: + { + DOT11_HS2_TSM_REQ tsm_req; + int can_list = 0; + int payload = pfrinfo->pktlen - WLAN_HDR_A3_LEN; + tsm_req.Dialog_token = pframe[2]; + + HS2_DEBUG_INFO("got TSM QUERY frame\n"); + if (payload > 4) + { + if (payload-4 > 100) + { + tsm_req.list_len = 100; + tsm_req.url_len = 0; + HS2_DEBUG_ERR("payload too long!!\n"); + memcpy(tsm_req.Candidate_list, &pframe[4], 100); + can_list = 1; + } + else + { + tsm_req.list_len = payload-4; + tsm_req.url_len = 0; + memcpy(tsm_req.Candidate_list, &pframe[4], payload-4); + can_list = 1; + } + } + else + { + tsm_req.url_len = 0; + tsm_req.list_len = 0; + can_list = 0; + } + memcpy(tsm_req.MACAddr, get_pframe(pfrinfo) + WLAN_ADDR_LEN + 4, MACADDRLEN); + tsm_req.Req_mode = priv->pmib->hs2Entry.reqmode | (can_list & 0x01); + tsm_req.Disassoc_timer = priv->pmib->hs2Entry.disassoc_timer; + if (can_list != 0) + tsm_req.Validity_intval = 200; + else + tsm_req.Validity_intval = priv->pmib->hs2Entry.validity_intval; + issue_BSS_TSM_req(priv, &tsm_req); + } + break; + case _BSS_TSMRSP_ACTION_ID_: + HS2_DEBUG_INFO("got TSM RSP frame\n"); + HS2_DEBUG_INFO("token=%d\n", pframe[2]); + HS2_DEBUG_INFO("status code=%d\n", pframe[3]); + break; +#ifdef HS2_CLIENT_TEST + case _BSS_TSMREQ_ACTION_ID_: + printk("got TSM REQ frame\n"); + if (pfrinfo->pktlen - WLAN_HDR_A3_LEN > 7) + issue_BSS_TSM_rsp(priv, &pframe[2], &pframe[7], pfrinfo->pktlen - WLAN_HDR_A3_LEN-7); + else + issue_BSS_TSM_rsp(priv, &pframe[2], NULL, 0); + break; +#endif + } + break; + case _DLS_CATEGORY_ID_: + printk("dls..action=%d\n", Action_field); + switch (Action_field) { + case _DLS_REQ_ACTION_ID_: + printk("recv DLS frame\n"); + + issue_DLS_rsp(priv, 48, sa, &pframe[2], &pframe[8]); // status = 48 means that Direct link is not allowed in the BSS by policy) + break; + }; + break; +#endif // HS2_SUPPORT +#ifdef TDLS_SUPPORT + case _TDLS_CATEGORY_ID_: + printk("TDLS..action=%d, tdls_prohibited = %d\n", Action_field, priv->pmib->dot11OperationEntry.tdls_prohibited); + break; +#endif +#ifdef P2P_SUPPORT + case _VENDOR_ACTION_ID_: + if(!memcmp(&pframe[1],WFA_OUI_PLUS_TYPE,WFA_OUI_PLUS_TYPE_LEN)){ + P2P_on_action(priv,pfrinfo); + } + break; +#endif + default: + DEBUG_INFO("Action Frame is received but not support yet\n"); + break; + } +#ifdef TX_SHORTCUT + if (do_tx_slowpath) { + /* let the first tx packet go through normal path and set fw properly */ + if (!priv->pmib->dot11OperationEntry.disable_txsc) { + clearTxShortCutBufSize(priv, pstat); + } + } +#endif + } else { + if (IS_MCAST(da)) { + //DEBUG_ERR("Error Broadcast or Multicast Action Frame is received\n"); + } + else { + //DEBUG_ERR("Action Frame is received from non-associated station\n"); + } + } + } +error_frame: +#endif + return SUCCESS; +} + + +static unsigned int DoReserved(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + return SUCCESS; +} + + +#ifdef CLIENT_MODE +static void update_bss(struct Dot11StationConfigEntry *dst, struct bss_desc *src) +{ + memcpy((void *)dst->dot11Bssid, (void *)src->bssid, MACADDRLEN); + memset((void *)dst->dot11DesiredSSID, 0, sizeof(dst->dot11DesiredSSID)); + memcpy((void *)dst->dot11DesiredSSID, (void *)src->ssid, src->ssidlen); + dst->dot11DesiredSSIDLen = src->ssidlen; +} + + + +/** + * @brief Authenticat success, Join a BSS + * + * Set BSSID to hardware, Join BSS complete + */ +static void join_bss(struct rtl8192cd_priv *priv) +{ + unsigned short val16; + unsigned long val32; + + memcpy((void *)&val32, BSSID, 4); + memcpy((void *)&val16, BSSID+4, 2); + +#ifdef SDIO_2_PORT + if (IS_VXD_INTERFACE(priv)) { + RTL_W32(BSSIDR1, cpu_to_le32(val32)); + RTL_W16((BSSIDR1 + 4), cpu_to_le16(val16)); + } else +#endif + { + RTL_W32(BSSIDR, cpu_to_le32(val32)); + RTL_W16((BSSIDR + 4), cpu_to_le16(val16)); + } +} + + +/** + * @brief issue Association Request + * + * STA find compatible network, and authenticate success, use this function send association request. \n + * +---------------+----+----+-------+------------+-----------------+------+-----------------+ \n + * | Frame Control | DA | SA | BSSID | Capability | Listen Interval | SSID | Supported Rates | \n + * +---------------+----+----+-------+------------+-----------------+------+-----------------+ \n + * \n + * +--------------------+---------------------+-----------------+ \n + * | Ext. Support Rates | Realtek proprietary | RSN information | \n + * +--------------------+---------------------+-----------------+ \n + * + * PS: Reassociation Frame Body have Current AP Address field, But not implement. + */ +static unsigned int issue_assocreq(struct rtl8192cd_priv *priv) +{ + unsigned short val; + struct wifi_mib *pmib; + unsigned char *bssid, *pbuf; + unsigned char *pbssrate=NULL; + int bssrate_len; + unsigned char supportRateSet[32]; + int i, j, idx=0, supportRateSetLen=0, match=0; + unsigned int retval=0; +#ifdef WIFI_WMM + int k; +#endif +#ifdef CONFIG_RTL_WAPI_SUPPORT + unsigned long flags; +#endif +#ifdef SUPPORT_MULTI_PROFILE + int found=0; + int jdx=0; + int ssid_len=0; +#endif + + DECLARE_TXINSN(txinsn); + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + pmib= GET_MIB(priv); + + bssid = pmib->dot11Bss.bssid; + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCMEM_; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + + if (pbuf == NULL) + goto issue_assocreq_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + + if (txinsn.phdr == NULL) + goto issue_assocreq_fail; + memset((void *)txinsn.phdr, 0, sizeof(struct wlan_hdr)); + + val = cpu_to_le16(pmib->dot11Bss.capability); + + if (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) + val |= cpu_to_le16(BIT(4)); + + if (SHORTPREAMBLE) + val |= cpu_to_le16(BIT(5)); + +#ifdef DOT11H + if(priv->pmib->dot11hTPCEntry.tpc_enable) + val |= cpu_to_le16(BIT(8)); /* set spectrum mgt */ +#endif + + pbuf = set_fixed_ie(pbuf, _CAPABILITY_, (unsigned char *)&val, &txinsn.fr_len); + + val = cpu_to_le16(3); + pbuf = set_fixed_ie(pbuf, _LISTEN_INTERVAL_, (unsigned char *)&val, &txinsn.fr_len); + + pbuf = set_ie(pbuf, _SSID_IE_, pmib->dot11Bss.ssidlen, pmib->dot11Bss.ssid, &txinsn.fr_len); + + if (pmib->dot11Bss.supportrate == 0) + { + // AP don't contain rate info in beacon/probe response + // Use our rate in asoc req + get_bssrate_set(priv, _SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len); + pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_, bssrate_len, pbssrate, &txinsn.fr_len); + + //EXT supported rates. + if (get_bssrate_set(priv, _EXT_SUPPORTEDRATES_IE_, &pbssrate, &bssrate_len)) + pbuf = set_ie(pbuf, _EXT_SUPPORTEDRATES_IE_, bssrate_len, pbssrate, &txinsn.fr_len); + } + else + { + // See if there is any mutual supported rate + for (i=0; dot11_rate_table[i]; i++) { + int bit_mask = 1 << i; + if (pmib->dot11Bss.supportrate & bit_mask) { + val = dot11_rate_table[i]; + for (j=0; jdot11Bss.supportrate & bit_mask) { + val = dot11_rate_table[i]; + if (((pmib->dot11BssType.net_work_type == WIRELESS_11B) && is_CCK_rate(val)) || + (pmib->dot11BssType.net_work_type != WIRELESS_11B)) { + if (pmib->dot11Bss.basicrate & bit_mask) + val |= 0x80; + + supportRateSet[idx] = val; + supportRateSetLen++; + idx++; + } + } + } + + if (supportRateSetLen == 0) { + retval = 1; + goto issue_assocreq_fail; + } + else if (supportRateSetLen <= 8) + pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_ , supportRateSetLen , supportRateSet, &txinsn.fr_len); + else { + pbuf = set_ie(pbuf, _SUPPORTEDRATES_IE_, 8, supportRateSet, &txinsn.fr_len); + pbuf = set_ie(pbuf, _EXT_SUPPORTEDRATES_IE_, supportRateSetLen-8, &supportRateSet[8], &txinsn.fr_len); + } + } + + +#ifdef DOT11H + if(pmib->dot11hTPCEntry.tpc_enable) { + pbuf = construct_power_capability_ie(priv, pbuf, &txinsn.fr_len); + pbuf = construct_supported_channel_ie(priv, pbuf, &txinsn.fr_len); + } +#endif + /*RSN IE*/ +#ifdef WIFI_SIMPLE_CONFIG + if (!(pmib->wscEntry.wsc_enable && pmib->wscEntry.assoc_ielen)) +#endif + { +#if 0 +//#ifdef SUPPORT_MULTI_PROFILE + /*echo profile maintain self RNSIE,when issue_assoc chk and try to use itself RSNIE , + the fail case is when RTK AP use mixed mode we use wrong macst cipher type*/ + if ( priv->pmib->ap_profile.enable_profile && priv->pmib->ap_profile.profile_num > 0) { + + int RSNIE_LEN=0; + unsigned char RSNIE[128]; + for(jdx=0 ; jdxpmib->ap_profile.profile_num ; jdx++) { + ssid_len = strlen(priv->pmib->ap_profile.profile[jdx].ssid); + ///STADEBUG("be chk ssid=%s,idx=%d\n", priv->pmib->ap_profile.profile[jdx].ssid,jdx); + if((ssid_len == pmib->dot11Bss.ssidlen) && !memcmp(priv->pmib->ap_profile.profile[jdx].ssid , pmib->dot11Bss.ssid,ssid_len )) + { + ///STADEBUG("Found;my[%s],target[%s]\n", priv->pmib->ap_profile.profile[jdx].ssid,pmib->dot11Bss.ssid); + priv->profile_idx = jdx; + ///STADEBUG("call switch_profile(%d)\n",priv->profile_idx); + switch_profile(priv, priv->profile_idx); + + if(priv->pmib->ap_profile.profile[jdx].MulticastCipher){ + + priv->wpa_global_info->MulticastCipher=priv->pmib->ap_profile.profile[jdx].MulticastCipher; + ///STADEBUG("MulticastCipher=%d\n", priv->wpa_global_info->MulticastCipher); + ///STADEBUG("dot11EnablePSK=[%d]\n", priv->pmib->dot1180211AuthEntry.dot11EnablePSK); + ConstructIE(priv, RSNIE,&RSNIE_LEN); + ///STADEBUG("AuthInfoElement len=%d\n", RSNIE_LEN); + if(RSNIE_LEN){ + memcpy(pbuf, RSNIE,RSNIE_LEN); + pbuf += RSNIE_LEN; + txinsn.fr_len += RSNIE_LEN; + STADEBUG("Use profile's RSNIE[%s]\n", priv->pmib->ap_profile.profile[jdx].ssid); + } + + } + else{ + ///STADEBUG("NO RSNIE\n"); + } + break; + } + + } + + + } + else +#endif + { + //STADEBUG("normal case [ssid=%s]\n", pmib->dot11Bss.ssid); + if (pmib->dot11RsnIE.rsnielen) { + memcpy(pbuf, pmib->dot11RsnIE.rsnie, pmib->dot11RsnIE.rsnielen); + pbuf += pmib->dot11RsnIE.rsnielen; + txinsn.fr_len += pmib->dot11RsnIE.rsnielen; + } + } + } + + if ((QOS_ENABLE) || (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N)) { + int count=0; + struct bss_desc *bss=NULL; + + if (priv->site_survey->count) { + count = priv->site_survey->count; + bss = priv->site_survey->bss; + } + else if (priv->site_survey->count_backup) { + count = priv->site_survey->count_backup; + bss = priv->site_survey->bss_backup; + } + + for(k=0; kuapsd_assoc++; + else + priv->uapsd_assoc = 0; + + init_WMM_Para_Element(priv, priv->pmib->dot11QosEntry.WMM_IE); + } +#endif + pbuf = set_ie(pbuf, _RSN_IE_1_, _WMM_IE_Length_, GET_WMM_IE, &txinsn.fr_len); + } +#endif + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + (bss[k].network & WIRELESS_11N)) { + + int is_40m_bw, offset_chan; +#ifdef UNIVERSAL_REPEATER + if (!IS_ROOT_INTERFACE(priv) && !GET_ROOT(priv)->pmib->dot11nConfigEntry.dot11nUse40M) + is_40m_bw=0; + else +#endif + is_40m_bw = (bss[k].t_stamp[1] & BIT(1)) ? 1 : 0; + + if (is_40m_bw) { + if (bss[k].t_stamp[1] & BIT(2)) + offset_chan = 1; + else + offset_chan = 2; + } + else + offset_chan = 0; + + priv->ht_cap_len = 0; // re-construct HT IE + construct_ht_ie(priv, is_40m_bw, offset_chan); + pbuf = set_ie(pbuf, _HT_CAP_, priv->ht_cap_len, (unsigned char *)&priv->ht_cap_buf, &txinsn.fr_len); +#ifdef RTK_AC_SUPPORT + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + construct_vht_ie(priv, priv->pshare->working_channel); + pbuf = set_ie(pbuf, EID_VHTCapability, priv->vht_cap_len, (unsigned char *)&priv->vht_cap_buf, &txinsn.fr_len); + pbuf = set_ie(pbuf, EID_VHTOperation, priv->vht_oper_len, (unsigned char *)&priv->vht_oper_buf, &txinsn.fr_len); + } +#endif + } + + break; + } + } + } + +#ifdef WIFI_SIMPLE_CONFIG + if (pmib->wscEntry.wsc_enable && pmib->wscEntry.assoc_ielen) { + memcpy(pbuf, pmib->wscEntry.assoc_ie, pmib->wscEntry.assoc_ielen); + pbuf += pmib->wscEntry.assoc_ielen; + txinsn.fr_len += pmib->wscEntry.assoc_ielen; + } +#endif +#ifdef P2P_SUPPORT + if((OPMODE&WIFI_P2P_SUPPORT)){ + + if(priv->p2pPtr->p2p_assocReq_ie_len) { + + memcpy(pbuf, priv->p2pPtr->p2p_assocReq_ie, priv->p2pPtr->p2p_assocReq_ie_len); + + pbuf += priv->p2pPtr->p2p_assocReq_ie_len; + txinsn.fr_len += priv->p2pPtr->p2p_assocReq_ie_len; + } + + } +#endif +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType!=wapiDisable) + { + SAVE_INT_AND_CLI(flags); + priv->wapiCachedBuf = pbuf+2; + wapiSetIE(priv); + pbuf[0] = _EID_WAPI_; + pbuf[1] = priv->wapiCachedLen; + pbuf += priv->wapiCachedLen+2; + txinsn.fr_len += priv->wapiCachedLen+2; + RESTORE_INT(flags); + } +#endif + + // Realtek proprietary IE + if (priv->pshare->rtk_ie_len) + pbuf = set_ie(pbuf, _RSN_IE_1_, priv->pshare->rtk_ie_len, priv->pshare->rtk_ie_buf, &txinsn.fr_len); + + // Customer proprietary IE + if (priv->pmib->miscEntry.private_ie_len) { + memcpy(pbuf, pmib->miscEntry.private_ie, pmib->miscEntry.private_ie_len); + pbuf += pmib->miscEntry.private_ie_len; + txinsn.fr_len += pmib->miscEntry.private_ie_len; + } + + SetFrameSubType((txinsn.phdr), WIFI_ASSOCREQ); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), bssid, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), bssid, MACADDRLEN); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + txinsn.is_urgent = 1; +#endif + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + { +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) //wrt_clnt + unsigned char *assocreq_ie = txinsn.pframe + 4; //ignore fix ies + int assocreq_ie_len = (txinsn.fr_len-4); + + //printk("AssocReq Len = %d\n", assocreq_ie_len); + if(assocreq_ie_len > MAX_ASSOC_REQ_LEN) + { + printk("AssocReq Len too LONG !!\n"); + memcpy(priv->rtk->clnt_info.assoc_req, assocreq_ie, MAX_ASSOC_REQ_LEN); + priv->rtk->clnt_info.assoc_req_len = MAX_ASSOC_REQ_LEN; + } + else + { + memcpy(priv->rtk->clnt_info.assoc_req, assocreq_ie, assocreq_ie_len); + priv->rtk->clnt_info.assoc_req_len = assocreq_ie_len; + } +#endif + return retval; + } + +issue_assocreq_fail: + + DEBUG_ERR("sending assoc req fail!\n"); + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return retval; +} + +#if defined( UNIVERSAL_REPEATER) || defined(MBSSID) +void ap_sync_chan_to_bss(struct rtl8192cd_priv *priv, int bss_channel, int bss_bw, int bss_offset) +{ + int i, j; + struct rtl8192cd_priv *vap_priv; + struct stat_info * pstat; + STADEBUG("===>\n"); + for(j=0; jpshare->aidarray[j] && (priv->pshare->aidarray[j]->used == TRUE) +#ifdef WDS + && !(priv->pshare->aidarray[j]->station.state & WIFI_WDS) +#endif + ) { + if (priv != priv->pshare->aidarray[j]->priv) + continue; + + pstat = &(priv->pshare->aidarray[j]->station); +#ifdef CONFIG_RTK_MESH + if(isPossibleNeighbor(pstat)) { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + mesh_cnt_ASSOC_PeerLink_CAP(priv, pstat, DECREASE); + free_stainfo(priv, pstat); + } + else +#endif + { + issue_deauth(priv, pstat->hwaddr, _RSON_DEAUTH_STA_LEAVING_); + } + } + } + delay_ms(10); + + //sync channel + priv->pmib->dot11RFEntry.dot11channel = bss_channel; + + //sync bw + priv->pmib->dot11nConfigEntry.dot11nUse40M = bss_bw; + priv->pshare->CurrentChannelBW = bss_bw; + priv->pshare->is_40m_bw = bss_bw; + + //sync offset + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = bss_offset; + priv->pshare->offset_2nd_chan = bss_offset; + + //regen ht ie + priv->ht_cap_len = 0; + priv->ht_ie_len = 0; + + /*The beacon IE content before TIM(TLV) need call init_beacon for update ; + for example channle info(Direct Sequence Parameter Set) + else content can update by update_beacon() + */ + init_beacon(priv); + +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i]; + if (vap_priv && IS_DRV_OPEN(vap_priv)) { + for(j=0; jpshare->aidarray[j] && (priv->pshare->aidarray[j]->used == TRUE)) { + if (vap_priv != priv->pshare->aidarray[j]->priv) + continue; + issue_deauth(vap_priv, priv->pshare->aidarray[j]->station.hwaddr, _RSON_DEAUTH_STA_LEAVING_); + } + } + delay_ms(10); + + vap_priv->pmib->dot11RFEntry.dot11channel = bss_channel; //sync channel + vap_priv->pmib->dot11nConfigEntry.dot11nUse40M = bss_bw; //sync bandwidth + vap_priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = bss_offset; //sync 2nd ch offset + + vap_priv->ht_cap_len = 0; //regen ht ie + vap_priv->ht_ie_len = 0; + init_beacon(vap_priv); + } + } + } +#endif + +} +#endif + +void clnt_switch_chan_to_bss(struct rtl8192cd_priv *priv) +{ + int bss_channel, bss_bw, bss_offset = 0; + + STADEBUG("===>\n"); + //sync channel + bss_channel = priv->pmib->dot11Bss.channel; + + //sync bw & offset + bss_bw = HT_CHANNEL_WIDTH_20_40; + +#ifdef RTK_AC_SUPPORT + if(GET_CHIP_VER(priv)==VERSION_8812E || GET_CHIP_VER(priv)==VERSION_8881A){ + if((priv->pmib->dot11Bss.t_stamp[1] & (BSS_BW_MASK << BSS_BW_SHIFT)) + == (HT_CHANNEL_WIDTH_80 << BSS_BW_SHIFT)) + bss_bw = HT_CHANNEL_WIDTH_80; + } +#endif + + if ((priv->pmib->dot11Bss.t_stamp[1] & (BIT(1) | BIT(2))) == (BIT(1) | BIT(2))) + bss_offset = HT_2NDCH_OFFSET_BELOW; + else if ((priv->pmib->dot11Bss.t_stamp[1] & (BIT(1) | BIT(2))) == BIT(1)) + bss_offset = HT_2NDCH_OFFSET_ABOVE; + else { + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_10) + bss_bw = HT_CHANNEL_WIDTH_10; + else if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5) + bss_bw = HT_CHANNEL_WIDTH_5; + else + bss_bw = HT_CHANNEL_WIDTH_20; + + bss_offset = HT_2NDCH_OFFSET_DONTCARE; + } + + + //sync channel + priv->pmib->dot11RFEntry.dot11channel = bss_channel; + + //sync bw + priv->pmib->dot11nConfigEntry.dot11nUse40M = bss_bw; + priv->pshare->CurrentChannelBW = bss_bw; + priv->pshare->is_40m_bw = bss_bw; + + //sync offset + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = bss_offset; + priv->pshare->offset_2nd_chan = bss_offset; + + /*3.4.6,wlanx-vax interface also can support STA mode*/ +#if defined( UNIVERSAL_REPEATER) || defined(MBSSID) + if( !IS_ROOT_INTERFACE(priv) +#ifdef MULTI_MAC_CLONE + || (OPMODE&WIFI_STATION_STATE) +#endif + ) + { + struct rtl8192cd_priv *priv_root = GET_ROOT(priv); + #if defined(SMART_REPEATER_MODE) && !defined(RTK_NL80211) + priv->pshare->switch_chan_rp = bss_channel; + priv->pshare->band_width_rp = bss_bw; + priv->pshare->switch_2ndchoff_rp = bss_offset; +#endif + if(IS_DRV_OPEN(priv_root) || (priv_root->pmib->miscEntry.vap_enable)) + if ((priv_root->pmib->dot11RFEntry.dot11channel != bss_channel) || + (priv_root->pmib->dot11nConfigEntry.dot11nUse40M != bss_bw) || + (priv_root->pmib->dot11nConfigEntry.dot11n2ndChOffset != bss_offset) ) { + ap_sync_chan_to_bss(priv_root, bss_channel, bss_bw, bss_offset); + } +#if defined(SMART_REPEATER_MODE) && !defined(RTK_NL80211) + priv->pshare->switch_chan_rp = 0; +#endif + } +#endif + + // when STA want to connect target AP make sure TX_PAUSE don't pause packet + priv->site_survey->target_ap_found=1; + SwBWMode(priv, bss_bw, bss_offset); + SwChnl(priv, bss_channel, bss_offset); + priv->site_survey->target_ap_found=0; +} + + +/** + * @brief STA Authentication + * + * STA process Authentication Request first step. + */ +void start_clnt_auth(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if((priv->pmib->dot11StationConfigEntry.sc_enabled == 1) && (priv->simple_config_status > 2) && priv->simple_config_status != 5) + { + if(rtk_sc_is_channel_fixed(priv)) + { + return; + } + } +#endif + + + SAVE_INT_AND_CLI(flags); + + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_AUTH_STATE1 | WIFI_ASOC_STATE)); + OPMODE_VAL(OPMODE | WIFI_AUTH_NULL); + REAUTH_COUNT_VAL(0); + REASSOC_COUNT_VAL(0); + AUTH_SEQ_VAL(1); + + if (PENDING_REAUTH_TIMER) + DELETE_REAUTH_TIMER; + if (PENDING_REASSOC_TIMER) + DELETE_REASSOC_TIMER; + +#ifdef CONFIG_RTK_MESH + if(mesh_channel_switch_initiate(priv)) {/*check if we need to inform other mesh nodes first*/ + RESTORE_INT(flags); + return; + } +#endif + + +#ifdef MULTI_MAC_CLONE + if (ACTIVE_ID == 0) +#endif + { +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D) { + if(priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY) + clnt_ss_check_band(priv, priv->pmib->dot11Bss.channel); + reload_txpwr_pg(priv); + } +#endif + +#if 0 // do not switch to bw=20 when issue auth + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, 0); + + SwChnl(priv, priv->pmib->dot11Bss.channel, 0); +#else + clnt_switch_chan_to_bss(priv); // Eric +#endif + + { + unsigned int trigger_iqk = 0; +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11Bss.channel > 14)) { + priv->pshare->iqk_5g_done = 0; + trigger_iqk++; + } else +#endif + { + if (priv->pmib->dot11Bss.channel <= 14) { + priv->pshare->iqk_2g_done = 0; + trigger_iqk++; + } + } + + if (trigger_iqk) + PHY_IQCalibrate(priv); + } + } + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + if (OPMODE & WIFI_STATION_STATE) { + if ((priv->pshare->CurrentChannelBW==0 && priv->pmib->dot11RFEntry.dot11channel==13) + ||(priv->pshare->CurrentChannelBW==1 && priv->pmib->dot11RFEntry.dot11channel>=11)) + Check_92E_Spur_Valid(priv, false); + } + } +#endif + + MOD_REAUTH_TIMER(REAUTH_TO); + +#ifdef MULTI_MAC_CLONE + if ((ACTIVE_ID == 0) || ((GET_MIB(priv))->dot11OperationEntry.opmode & WIFI_ASOC_STATE)) +#endif + { + DEBUG_INFO("start sending auth req\n"); + //STADEBUG("tx auth req\n"); + issue_auth(priv, NULL, 0); + } + +#ifdef INCLUDE_WPA_PSK + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) + { + SSID_LEN = priv->pmib->dot11Bss.ssidlen; + memcpy(SSID, priv->pmib->dot11Bss.ssid, SSID_LEN); + derivePSK(priv); + } +#endif + + RESTORE_INT(flags); +} + + +/** + * @brief client (STA) association + * + * PS: clnt is client. + */ +void start_clnt_assoc(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + // now auth has succedded...let's perform assoc + SAVE_INT_AND_CLI(flags); + + OPMODE_VAL(OPMODE & (~ (WIFI_AUTH_NULL | WIFI_AUTH_STATE1 | WIFI_ASOC_STATE))); + OPMODE_VAL(OPMODE | (WIFI_AUTH_SUCCESS)); + JOIN_RES_VAL(STATE_Sta_Auth_Success); + REAUTH_COUNT_VAL(0); + REASSOC_COUNT_VAL(0); + + if (PENDING_REAUTH_TIMER) + DELETE_REAUTH_TIMER; + if (PENDING_REASSOC_TIMER) + DELETE_REASSOC_TIMER; + + DEBUG_INFO("start sending assoc req\n"); + if (issue_assocreq(priv) == 0) { + MOD_REASSOC_TIMER(REASSOC_TO); + RESTORE_INT(flags); + } + else { + RESTORE_INT(flags); +#ifdef WIFI_WPAS_CLI + event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL); +#else + STADEBUG("start_clnt_lookup(DONTRESCAN)\n"); + start_clnt_lookup(priv, DONTRESCAN); +#endif + } +} + + +void clean_for_join(struct rtl8192cd_priv *priv) +{ + int i; +#ifndef SMP_SYNC + unsigned long flags; +#endif +#ifdef P2P_SUPPORT + int p2p_support=0; +#endif + SAVE_INT_AND_CLI(flags); + + for(i=0; ipshare->aidarray[i] && (priv->pshare->aidarray[i]->used == TRUE)) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (priv != priv->pshare->aidarray[i]->priv) + continue; +#endif +#ifdef MULTI_MAC_CLONE + __del_mclone_addr(priv, priv->pshare->aidarray[i]->station.sa_addr); +#else + if (asoc_list_del(priv, &priv->pshare->aidarray[i]->station) + && priv->pshare->aidarray[i]->station.expire_to > 0) { + cnt_assoc_num(priv, &(priv->pshare->aidarray[i]->station), DECREASE, (char *)__FUNCTION__); + } + if ((free_stainfo(priv, &(priv->pshare->aidarray[i]->station))) == FALSE) + DEBUG_ERR("free station %d fails\n", i); +#endif + } + } + + priv->assoc_num = 0; + + memset(BSSID, 0, MACADDRLEN); +#ifdef P2P_SUPPORT + if(OPMODE & WIFI_P2P_SUPPORT) + p2p_support = 1; +#endif + OPMODE_VAL(OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)); + +#ifdef P2P_SUPPORT + if(p2p_support) + OPMODE_VAL(OPMODE | WIFI_P2P_SUPPORT); +#endif + + //P2P_DEBUG("\n\n\n"); + + if ((OPMODE & WIFI_STATION_STATE) && + ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_WPA_MIXED_PRIVACY_))) { + memset(&(priv->pmib->dot11GroupKeysTable), 0, sizeof(struct Dot11KeyMappingsEntry)); +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv)) +#endif + CamResetAllEntry(priv); + } + + if (IEEE8021X_FUN) + priv->pmib->dot118021xAuthEntry.dot118021xcontrolport = + priv->pmib->dot118021xAuthEntry.dot118021xDefaultPort; + else + priv->pmib->dot118021xAuthEntry.dot118021xcontrolport = 1; + + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G|WIRELESS_11A)) { + if (OPMODE & WIFI_ADHOC_STATE) { + priv->pmib->dot11ErpInfo.nonErpStaNum = 0; + check_protection_shortslot(priv); + priv->pmib->dot11ErpInfo.longPreambleStaNum = 0; + } + } + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + priv->ht_legacy_sta_num = 0; + + JOIN_RES_VAL(STATE_Sta_No_Bss); + priv->link_status = 0; + //netif_stop_queue(priv->dev); // don't start/stop queue dynamically + priv->rxBeaconNumInPeriod = 0; + memset(priv->rxBeaconCntArray, 0, sizeof(priv->rxBeaconCntArray)); + priv->rxBeaconCntArrayIdx = 0; + priv->rxBeaconCntArrayWindow = 0; + priv->rxBeaconPercentage = 0; + priv->rxDataNumInPeriod = 0; + memset(priv->rxDataCntArray, 0, sizeof(priv->rxDataCntArray)); + priv->rxMlcstDataNumInPeriod = 0; +// priv->rxDataNumInPeriod_pre = 0; +// priv->rxMlcstDataNumInPeriod_pre = 0; + RESTORE_INT(flags); +} + +unsigned int mod64(unsigned int A1, unsigned int A2, unsigned int b) +{ + unsigned int r; + r = A1%b; + r = (r<<12) | ((A2>>20)&0x0fff); + r %=b; + r = (r<<12) | ((A2>>8)&0x0fff); + r %=b; + r = (r<<8) | (A2&0xff); + r %=b; +// DEBUG_INFO("A1=%u, A2=%u, b=%u, r=%u\n", A1, A2, b, r); + return r; +} + +static void updateTSF(struct rtl8192cd_priv *priv) +{ + UINT64 tsf; + unsigned int r ; + + if (priv->beacon_period == 0) + return; + + tsf = *((UINT64*)priv->rx_timestamp); + tsf = le64_to_cpu(tsf); + if( tsf > 1024) { + r = mod64(tsf>>32, tsf&0xffffffff, priv->beacon_period*1024); + tsf = tsf -r -1024; + priv->prev_tsf = tsf; + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | BIT(6)); + +#ifdef SDIO_2_PORT + if (IS_VXD_INTERFACE(priv)) { + RTL_W8(DUAL_TSF_RST, BIT(1)); + RTL_W8(BCN_CTRL1, RTL_R8(BCN_CTRL1) & ~ (EN_BCN_FUNCTION)); + } else + +#endif + { + RTL_W8(DUAL_TSF_RST, BIT(0)); + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) & ~ (EN_BCN_FUNCTION)); + } + + RTL_W32(TSFTR, (unsigned int)(tsf&0xffffffff)); + RTL_W32(TSFTR+4, (unsigned int)(tsf>>32)); + +#ifdef SDIO_2_PORT + if (IS_VXD_INTERFACE(priv)) { + RTL_W8(BCN_CTRL1, RTL_R8(BCN_CTRL1) | DIS_ATIM); + } else +#endif + { + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) | EN_BCN_FUNCTION); + + if(OPMODE & WIFI_STATION_STATE) + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) | DIS_ATIM); + } + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) ^ BIT(6)); + } +} + + +/** + * @brief STA join BSS + * Join a BSS, In function, emit join request, Before association must be Authentication. \n + * [NOTE] TPT information element + */ +void start_clnt_join(struct rtl8192cd_priv *priv) +{ + struct wifi_mib *pmib = GET_MIB(priv); + unsigned char null_mac[]={0,0,0,0,0,0}; + unsigned char random; + int i; +#ifdef P2P_SUPPORT + int p2p_support=0; +#endif + +#ifdef DFS + if (priv->pmib->dot11DFSEntry.disable_tx) + priv->pmib->dot11DFSEntry.disable_tx = 0; +#endif + +#ifdef MULTI_MAC_CLONE + if (ACTIVE_ID) { + OPMODE_VAL(WIFI_STATION_STATE); + JOIN_RES_VAL(STATE_Sta_No_Bss); + start_clnt_auth(priv); + return; + } +#endif + +// stop ss_timer before join ------------------------ + if (timer_pending(&priv->ss_timer)) + del_timer(&priv->ss_timer); +//------------------------------- david+2007-03-10 + +#ifdef WIFI_SIMPLE_CONFIG + if (priv->pmib->wscEntry.wsc_enable == 1) { //wps client mode + if (priv->wps_issue_join_req) + priv->wps_issue_join_req = 0; + else { + priv->recover_join_req = 1; + return; + } + } +#endif + +#ifdef SDIO_AP_OFFLOAD + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_JOIN); +#endif + + // if found bss + if (memcmp(pmib->dot11Bss.bssid, null_mac, MACADDRLEN)) + { + priv->beacon_period = pmib->dot11Bss.beacon_prd; + if (pmib->dot11Bss.bsstype & WIFI_AP_STATE) + { +#ifdef WIFI_SIMPLE_CONFIG + if (priv->pmib->wscEntry.wsc_enable == 1) //wps client mode + priv->recover_join_req = 1; +#endif + clean_for_join(priv); + +#ifdef P2P_SUPPORT + if(OPMODE & WIFI_P2P_SUPPORT) + p2p_support = 1; +#endif + OPMODE_VAL(WIFI_STATION_STATE); +#ifdef P2P_SUPPORT + if(p2p_support) + OPMODE_VAL(OPMODE | WIFI_P2P_SUPPORT); +#endif + +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv)) +#endif + { + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_INFRA & NETYPE_Mask) << NETYPE_SHIFT)); + updateTSF(priv); +#if defined(TESTCHIP_SUPPORT) && defined(CONFIG_RTL_92C_SUPPORT) + if (IS_TEST_CHIP(priv)) + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) & ~(DIS_TSF_UPDATE |DIS_SUB_STATE)); + else +#endif + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) & ~(DIS_TSF_UPDATE_N | DIS_SUB_STATE_N)); + + } +#ifdef SDIO_2_PORT + if (IS_VXD_INTERFACE(priv)) { + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT1)) | ((NETYPE_INFRA & NETYPE_Mask) << NETYPE_SHIFT1)); + updateTSF(priv); + RTL_W8(BCN_CTRL1, RTL_R8(BCN_CTRL1) & ~(DIS_TSF_UPDATE_N | DIS_SUB_STATE_N)); + RTL_W32(RCR, RTL_R32(RCR) & ~RCR_CBSSID); // acli + } +#endif +#ifdef DFS +#ifdef UNIVERSAL_REPEATER + if( IS_VXD_INTERFACE(priv) && is_DFS_channel(pmib->dot11Bss.channel) + && (!GET_ROOT(priv)->pmib->dot11DFSEntry.CAC_ss_counter) + && (pmib->dot11Bss.channel != pmib->dot11RFEntry.dot11channel)) { + clnt_switch_chan_to_bss(priv); + GET_ROOT(priv)->pmib->dot11DFSEntry.disable_tx = 1; + start_clnt_lookup(priv, RESCAN); + } else +#endif +#endif + { + start_clnt_auth(priv); + } + } + else if (pmib->dot11Bss.bsstype == WIFI_ADHOC_STATE) + { + clean_for_join(priv); + OPMODE_VAL(WIFI_ADHOC_STATE); + update_bss(&pmib->dot11StationConfigEntry, &pmib->dot11Bss); + pmib->dot11RFEntry.dot11channel = pmib->dot11Bss.channel; + + if (pmib->dot11BssType.net_work_type & WIRELESS_11N) { + if (priv->pmib->dot11nConfigEntry.dot11nUse40M) { + if (pmib->dot11Bss.t_stamp[1] & BIT(1)) + priv->pshare->is_40m_bw = 1; + else + priv->pshare->is_40m_bw = 0; + + if (priv->pshare->is_40m_bw) { + if (pmib->dot11Bss.t_stamp[1] & BIT(2)) + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + else + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + } + else + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_DONTCARE; + } + else + priv->pshare->is_40m_bw = 0; + + priv->ht_cap_len = 0; + priv->ht_ie_len = 0; + + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + } +#ifdef RTK_AC_SUPPORT //ADHOC-VHT support + if (pmib->dot11BssType.net_work_type & WIRELESS_11AC) + { + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == 2) { + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_80; + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; + } + else if (priv->pmib->dot11nConfigEntry.dot11nUse40M == 1){ + if (pmib->dot11Bss.t_stamp[1] & BIT(1)) + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_20_40; + + else + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_20; + + if (priv->pshare->is_40m_bw) { + if (pmib->dot11Bss.t_stamp[1] & BIT(2)) + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + else + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + } + else + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_DONTCARE; + } + else + priv->pshare->is_40m_bw = 0; + + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_5; + else if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_10) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_10; + else + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + } + +#endif +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D)&&(priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY)) { + clnt_ss_check_band(priv, priv->pmib->dot11Bss.channel); + } +#endif + SwChnl(priv, pmib->dot11Bss.channel, priv->pshare->offset_2nd_chan); + + { + unsigned int trigger_iqk = 0; +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11Bss.channel > 14)) { + priv->pshare->iqk_5g_done = 0; + trigger_iqk++; + } else +#endif + { + if (priv->pmib->dot11Bss.channel <= 14) { + priv->pshare->iqk_2g_done = 0; + trigger_iqk++; + } + } + + if (trigger_iqk) + PHY_IQCalibrate(priv); + } + + DEBUG_INFO("Join IBSS: chan=%d, 40M=%d, offset=%d\n", pmib->dot11Bss.channel, + priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + + join_bss(priv); + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_ADHOC & NETYPE_Mask) << NETYPE_SHIFT)); + updateTSF(priv); +#if defined(TESTCHIP_SUPPORT) && defined(CONFIG_RTL_92C_SUPPORT) + if (IS_TEST_CHIP(priv)) + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) & ~(DIS_TSF_UPDATE )); + else +#endif + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) & ~(DIS_TSF_UPDATE_N)); + + JOIN_REQ_ONGOING_VAL(0); + init_beacon(priv); + JOIN_RES_VAL(STATE_Sta_Ibss_Active); + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) //wrt-adhoc + if(IS_VXD_INTERFACE(priv)) + construct_ibss_beacon(priv); +#endif + + DEBUG_INFO("Join IBSS - %02X:%02X:%02X:%02X:%02X:%02X\n", + BSSID[0], BSSID[1], BSSID[2], BSSID[3], BSSID[4], BSSID[5]); + LOG_MSG("Join IBSS - %02X:%02X:%02X:%02X:%02X:%02X\n", + BSSID[0], BSSID[1], BSSID[2], BSSID[3], BSSID[4], BSSID[5]); + } + +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_JOIN); +#endif + return; + } + + // not found + //if (OPMODE & WIFI_STATION_STATE) orig +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + if (OPMODE & WIFI_STATION_STATE) +#else + /*new ; under vxd if not found then stop ss and wait next time by timer*/ + if ((OPMODE & WIFI_STATION_STATE) && priv->ss_req_ongoing != SSFROM_REPEATER_VXD) +#endif + { + clean_for_join(priv); +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv)) +#endif + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT)); +#ifdef SDIO_2_PORT + if (IS_VXD_INTERFACE(priv)) + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT1)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT1)); +#endif + JOIN_RES_VAL(STATE_Sta_No_Bss); + JOIN_REQ_ONGOING_VAL(0); +#ifdef WIFI_WPAS_CLI + WARN_ON("pmib->dot11Bss.bssid is NULL"); +#else + STADEBUG("start_clnt_lookup(RESCAN)\n"); + start_clnt_lookup(priv, RESCAN); +#endif + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + unsigned char tmpbssid[MACADDRLEN]; + int start_period; + + memset(tmpbssid, 0, MACADDRLEN); + if (!memcmp(BSSID, tmpbssid, MACADDRLEN)) { + // generate an unique Ibss ssid +#ifdef __ECOS + { + unsigned char random_buf[4]; + get_random_bytes(random_buf, 4); + random = random_buf[3]; + } +#else + get_random_bytes(&random, 1); +#endif + tmpbssid[0] = 0x02; + for (i=1; isite_survey->count_target; i++) { + if (!memcmp(tmpbssid, priv->site_survey->bss_target[i].bssid, MACADDRLEN)) { + tmpbssid[5]++; + break; + } + } + if (i == priv->site_survey->count) + break; + } + + clean_for_join(priv); + memcpy(BSSID, tmpbssid, MACADDRLEN); + if (SSID_LEN == 0) { + SSID_LEN = pmib->dot11StationConfigEntry.dot11DefaultSSIDLen; + memcpy(SSID, pmib->dot11StationConfigEntry.dot11DefaultSSID, SSID_LEN); + } + + pmib->dot11Bss.channel = pmib->dot11RFEntry.dot11channel; + + if (pmib->dot11BssType.net_work_type & WIRELESS_11N) { + priv->pshare->is_40m_bw = priv->pmib->dot11nConfigEntry.dot11nUse40M; + if (priv->pshare->is_40m_bw) + priv->pshare->offset_2nd_chan = priv->pmib->dot11nConfigEntry.dot11n2ndChOffset; + else + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_DONTCARE; + + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_5; + else if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_10) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_10; + else + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + } +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8192D){ + if (priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY) + clnt_ss_check_band(priv, priv->pmib->dot11Bss.channel); + reload_txpwr_pg(priv); + } +#endif + + SwChnl(priv, pmib->dot11Bss.channel, priv->pshare->offset_2nd_chan); + + { + unsigned int trigger_iqk = 0; +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11Bss.channel > 14)) { + priv->pshare->iqk_5g_done = 0; + trigger_iqk++; + } else +#endif + { + if (priv->pmib->dot11Bss.channel <= 14) { + priv->pshare->iqk_2g_done = 0; + trigger_iqk++; + } + } + + if (trigger_iqk) + PHY_IQCalibrate(priv); + } + + DEBUG_INFO("Start IBSS: chan=%d, 40M=%d, offset=%d\n", pmib->dot11Bss.channel, + priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + DEBUG_INFO("Start IBSS - %02X:%02X:%02X:%02X:%02X:%02X\n", + BSSID[0], BSSID[1], BSSID[2], BSSID[3], BSSID[4], BSSID[5]); + + join_bss(priv); + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) //wrt-adhoc + if(IS_VXD_INTERFACE(priv)) + construct_ibss_beacon(priv); +#endif + + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_ADHOC & NETYPE_Mask) << NETYPE_SHIFT)); + updateTSF(priv); +#if defined(TESTCHIP_SUPPORT) && defined(CONFIG_RTL_92C_SUPPORT) + if (IS_TEST_CHIP(priv)) + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) & ~(DIS_TSF_UPDATE)); + else +#endif + RTL_W8(BCN_CTRL, RTL_R8(BCN_CTRL) & ~(DIS_TSF_UPDATE_N)); + + + priv->beacon_period = pmib->dot11StationConfigEntry.dot11BeaconPeriod; + JOIN_RES_VAL(STATE_Sta_Ibss_Idle); + JOIN_REQ_ONGOING_VAL(0); + if (priv->auto_channel) { + priv->auto_channel = 1; + priv->ss_ssidlen = 0; + DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=0\n", (char *)__FUNCTION__); + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT)); + start_clnt_ss(priv); +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_JOIN); +#endif + return; + } + else + init_beacon(priv); + + JOIN_RES_VAL(STATE_Sta_Ibss_Idle); + } + else { + pmib->dot11Bss.channel = pmib->dot11RFEntry.dot11channel; + + if (pmib->dot11BssType.net_work_type & WIRELESS_11N) { + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + } +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D)&&(priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY)) { + clnt_ss_check_band(priv, priv->pmib->dot11Bss.channel); + } +#endif + SwChnl(priv, pmib->dot11Bss.channel, priv->pshare->offset_2nd_chan); + + { + unsigned int trigger_iqk = 0; +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11Bss.channel > 14)) { + priv->pshare->iqk_5g_done = 0; + trigger_iqk++; + } else +#endif + { + if (priv->pmib->dot11Bss.channel <= 14) { + priv->pshare->iqk_2g_done = 0; + trigger_iqk++; + } + } + + if (trigger_iqk) + PHY_IQCalibrate(priv); + } + + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_ADHOC & NETYPE_Mask) << NETYPE_SHIFT)); + + DEBUG_INFO("Start IBSS: chan=%d, 40M=%d, offset=%d\n", pmib->dot11Bss.channel, + priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + DEBUG_INFO("Start IBSS - %02X:%02X:%02X:%02X:%02X:%02X\n", + BSSID[0], BSSID[1], BSSID[2], BSSID[3], BSSID[4], BSSID[5]); + JOIN_RES_VAL(STATE_Sta_Ibss_Idle); + } + + // start for more than scanning period, including random backoff + start_period = UINT32_DIFF(jiffies, priv->jiffies_pre) / HZ + 1; +#ifdef __ECOS + { + unsigned char random_buf[4]; + get_random_bytes(random_buf, 4); + random = random_buf[3]; + } +#else + get_random_bytes(&random, 1); +#endif + start_period += (random % 5); + mod_timer(&priv->idle_timer, jiffies + RTL_SECONDS_TO_JIFFIES(start_period)); + + LOG_MSG("Start IBSS - %02X:%02X:%02X:%02X:%02X:%02X\n", + BSSID[0], BSSID[1], BSSID[2], BSSID[3], BSSID[4], BSSID[5]); + } + +#ifdef SDIO_AP_OFFLOAD + ap_offload_activate(priv, OFFLOAD_PROHIBIT_JOIN); +#endif +} + + +static int check_bss_networktype(struct rtl8192cd_priv * priv, struct bss_desc *bss_target) +{ + int result; + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + (priv->pmib->dot11StationConfigEntry.legacySTADeny & WIRELESS_11G) && + !(bss_target->network & WIRELESS_11N)) + result = FAIL; + else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + (priv->pmib->dot11StationConfigEntry.legacySTADeny & WIRELESS_11B) && + (bss_target->network == WIRELESS_11B)) + result = FAIL; + else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + (priv->pmib->dot11StationConfigEntry.legacySTADeny & WIRELESS_11B) && + (bss_target->network == WIRELESS_11B)) + result = FAIL; + else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) && + (priv->pmib->dot11StationConfigEntry.legacySTADeny & WIRELESS_11N) && + !(bss_target->network & WIRELESS_11AC)) + result = FAIL; + else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) && + (priv->pmib->dot11StationConfigEntry.legacySTADeny & WIRELESS_11A) && + (bss_target->network == WIRELESS_11A)) + result = FAIL; + else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + (priv->pmib->dot11StationConfigEntry.legacySTADeny & WIRELESS_11A) && + (bss_target->network == WIRELESS_11A)) + result = FAIL; + else + result = SUCCESS; + + if (result == FAIL) { + DEBUG_ERR("Deny connect to a legacy AP!\n"); + } + + return result; +} + +#ifdef MULTI_MAC_CLONE +void mclone_start_roaming(struct rtl8192cd_priv *priv) +{ + int i; + + if (MCLONE_NUM > 0) { + for (i=0; ipshare->mclone_sta[i].priv) { + if (OPMODE & WIFI_ASOC_STATE) { + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)); + JOIN_RES_VAL(STATE_Sta_No_Bss); + start_clnt_join(priv); + } + } + } + ACTIVE_ID = 0; + } +} +#endif + + +#if 1 //def SMART_REPEATER_MODE +static int check_ap_security(struct rtl8192cd_priv *priv, struct bss_desc *bss) + +{ +#ifdef SUPPORT_MULTI_PROFILE + if (GET_MIB(priv)->ap_profile.enable_profile && + GET_MIB(priv)->ap_profile.profile_num > 0) { + + if ((GET_MIB(priv)->ap_profile.profile[priv->profile_idx].encryption==0) && (bss->capability&BIT(4))) + return 0; + else if ((GET_MIB(priv)->ap_profile.profile[priv->profile_idx].encryption == 1) || + (GET_MIB(priv)->ap_profile.profile[priv->profile_idx].encryption == 2)) { + if ((bss->capability&BIT(4))==0) + return 0; + else if (bss->t_stamp[0]!=0) + return 0; + } + else if ((GET_MIB(priv)->ap_profile.profile[priv->profile_idx].encryption == 3) || + (GET_MIB(priv)->ap_profile.profile[priv->profile_idx].encryption == 4) || + (GET_MIB(priv)->ap_profile.profile[priv->profile_idx].encryption == 6)) { + if ((bss->capability&BIT(4))==0) + return 0; + else if (bss->t_stamp[0]==0) + return 0; + } + + if (check_bss_networktype(priv, bss)) + return 1; + } + else +#endif + { + if ((GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyAlgrthm==_NO_PRIVACY_) && (bss->capability&BIT(4))) + return 0; + else if ((GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) || + (GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_)) { + if ((bss->capability&BIT(4))==0) + return 0; + else if (bss->t_stamp[0]!=0) + return 0; + } + else if ((GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) || + (GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)) { + if ((bss->capability&BIT(4))==0) + return 0; + else if (bss->t_stamp[0]==0) + return 0; + } + + if (check_bss_networktype(priv, bss)) + return 1; + } + return 0; +} +#endif + + +#ifdef SUPPORT_MULTI_PROFILE +void switch_profile(struct rtl8192cd_priv *priv, int idx) +{ + struct ap_profile *profile; + int key_len; + + if (idx > priv->pmib->ap_profile.profile_num) { + panic_printk("Invalid profile idx (%d), reset to 0.\n", idx); + idx = 0; + } + + profile = &priv->pmib->ap_profile.profile[idx]; + + SSID2SCAN_LEN = strlen(profile->ssid); + SSID_LEN = strlen(profile->ssid); + memcpy(SSID2SCAN, profile->ssid, SSID2SCAN_LEN); + memcpy(SSID, profile->ssid, SSID_LEN); + + if(OPMODE & WIFI_ADHOC_STATE) + OPMODE_VAL(WIFI_ADHOC_STATE); + else + OPMODE_VAL(WIFI_STATION_STATE); + + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _NO_PRIVACY_; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK= 0; + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = profile->auth_type; + + if (profile->encryption == 1 || profile->encryption == 2) { + if (profile->encryption == 1) { + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_40_PRIVACY_; + key_len = 5; + } + else { + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_104_PRIVACY_; + key_len = 13; + } + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[0], profile->wep_key1, key_len); + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[1], profile->wep_key2, key_len); + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[2], profile->wep_key3, key_len); + memcpy(&priv->pmib->dot11DefaultKeysTable.keytype[3], profile->wep_key4, key_len); + priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex = profile->wep_default_key; + + priv->pmib->dot11GroupKeysTable.dot11Privacy = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + memcpy(&priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey, + &priv->pmib->dot11DefaultKeysTable.keytype[0].skey[0], key_len); + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen = key_len; + priv->pmib->dot11GroupKeysTable.keyid = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + priv->pmib->dot11GroupKeysTable.keyInCam = 0; + } + else if (profile->encryption == 3 || profile->encryption == 4) { + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + if (profile->encryption == 3) { + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA; + priv->pmib->dot1180211AuthEntry.dot11WPACipher = profile->wpa_cipher; + } + else { + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA2; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = profile->wpa_cipher; + } + strcpy(priv->pmib->dot1180211AuthEntry.dot11PassPhrase, profile->wpa_psk); + } + else if (profile->encryption == 6) { +#ifdef SUPPORT_CLIENT_MIXED_SECURITY + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = 2; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 3; + priv->pmib->dot1180211AuthEntry.dot11WPACipher = 10; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 10; +#else + printk("Do not support WPA-MIXED, set to WPA2 by default!"); + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _CCMP_PRIVACY_; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = PSK_WPA2; + priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher = 8; +#endif + strcpy(priv->pmib->dot1180211AuthEntry.dot11PassPhrase, profile->wpa_psk); + } + if(priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm == 1 + && priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm!=_WEP_40_PRIVACY_ + && priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm!=_WEP_104_PRIVACY_){//radius + priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + priv->pmib->dot1180211AuthEntry.dot11EnablePSK = 0; + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = _IEEE8021X_PSK_; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm= 1; + } + else{ + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) { +#if (defined(INCLUDE_WPA_PSK) && !defined(WIFI_HAPD) && !defined(RTK_NL80211)) || defined(HAPD_DRV_PSK_WPS) + psk_init(priv); +#endif + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1; + } else { + priv->pmib->dot11RsnIE.rsnielen = 0; + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 0; + } + } + + if (should_forbid_Nmode(priv)) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + if (!priv->mask_n_band) + priv->mask_n_band = (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N | WIRELESS_11AC)); + priv->pmib->dot11BssType.net_work_type &= ~(WIRELESS_11N | WIRELESS_11AC); + } + } + else { + if (priv->mask_n_band) { + priv->pmib->dot11BssType.net_work_type |= priv->mask_n_band; + priv->mask_n_band = 0; + } + } +} +#endif /* SUPPORT_MULTI_PROFILE */ + + +unsigned int get_ava_2ndchoff(struct rtl8192cd_priv *priv, unsigned int channel, unsigned int bandwidth) +{ + + int chan_offset = 0; + + if(bandwidth == HT_CHANNEL_WIDTH_20) + return HT_2NDCH_OFFSET_DONTCARE; + + if(channel >=34){ + if((channel>144) ? ((channel-1)%8) : (channel%8)) { + chan_offset = HT_2NDCH_OFFSET_ABOVE; + } else { + chan_offset = HT_2NDCH_OFFSET_BELOW; + } + } + else + { + if(channel < 5) + chan_offset = HT_2NDCH_OFFSET_ABOVE; + else if(channel > 9) + chan_offset = HT_2NDCH_OFFSET_BELOW; + else + { + chan_offset = priv->pmib->dot11nConfigEntry.dot11n2ndChOffset; + if(chan_offset == HT_2NDCH_OFFSET_DONTCARE) + chan_offset = HT_2NDCH_OFFSET_BELOW; + } + } + + return chan_offset; + +} + + +/** + * @brief STA don't how to do + * popen:Maybe process client lookup and auth and assoc by IOCTL trigger + * + * [Important] + * Exceed Authentication times, process this function. + * @param rescan : process rescan. + */ +void start_clnt_lookup(struct rtl8192cd_priv *priv, int rescan) +{ + struct wifi_mib *pmib = GET_MIB(priv); + unsigned char null_mac[]={0,0,0,0,0,0}; + char tmpbuf[33]; + int i; +#ifdef SUPPORT_MULTI_PROFILE + int j1, j2; + int found = 0; +#endif + +#ifdef SMP_SYNC + unsigned long flags = 0; + int locked=0; + int cpuid; +#endif // SMP_SYNC + +#if defined(WIFI_WPAS_CLI) || defined(RTK_NL80211) + printk("cliW: no lookup for wpa supplicant\n"); + return; +#endif + +#ifdef P2P_SUPPORT + if((OPMODE&WIFI_P2P_SUPPORT)&&(P2PMODE == P2P_DEVICE)){ + //P2P_DEBUG("P2P_DEVICE don't lookup\n"); + return; + } +#endif + +#ifdef MULTI_MAC_CLONE + if (ACTIVE_ID) { + start_clnt_join(priv); + return; + } +#endif + +#ifdef SMART_REPEATER_MODE +#ifdef RTK_NL80211 //wrt-adhoc + if(IS_VXD_INTERFACE(priv) && (OPMODE & WIFI_ADHOC_STATE)) + printk("DO RESCAN for VXD ADHOC!! \n"); + else +#endif + //if(under_apmode_repeater(priv) && rescan) + if(!IS_ROOT_INTERFACE(priv) && rescan) + { + SDEBUG("STA(non-root)don't SS immediately wait next time by timer\n"); +#ifdef SMP_SYNC + locked = 0; + SMP_TRY_LOCK(flags,locked); +#endif + set_vxd_rescan(priv,rescan); /*when rescan==2 means Roaming or AP's CH/2ndch/BW be changed*/ +#ifdef SMP_SYNC + if(locked) + SMP_UNLOCK(flags); +#endif + return; + } +#endif + + + + //if (rescan || ((priv->site_survey->count_target > 0) && ((priv->join_index+1) >= priv->site_survey->count_target))) + if (rescan || ((priv->site_survey->count_target > 0) && ((priv->join_index+1) > priv->site_survey->count_target))) + { +#ifdef P2P_SUPPORT + if((OPMODE & WIFI_P2P_SUPPORT ) && (P2PMODE == P2P_CLIENT) ) + { + // client data can't connected yet + //if( P2P_STATE == P2P_S_IDLE) + { + priv->p2pPtr->clientmode_try_connect ++; + P2P_DEBUG("P2P_client try to connect (%d) timeout=%d seconds\n", + priv->p2pPtr->clientmode_try_connect,CLIENT_MODE_WAIT_TIME); + + if( priv->p2pPtr->clientmode_try_connect >= CLIENT_MODE_WAIT_TIME) + { + P2P_DEBUG("P2P client exceed %d seconds don't connect,backto p2p dev!\n",CLIENT_MODE_WAIT_TIME); + priv->p2pPtr->clientmode_try_connect = 0; + P2P_STATE = P2P_S_back2dev; + return; + } + } + + } +#endif + JOIN_RES_VAL(STATE_Sta_Roaming_Scan); + if (OPMODE & WIFI_SITE_MONITOR) // if scanning, scan later + return; + +#if 0 //def SUPPORT_MULTI_PROFILE + if (priv->pmib->ap_profile.enable_profile && priv->pmib->ap_profile.profile_num > 0) { + + switch_profile(priv, 0); + } +#endif + + priv->ss_ssidlen = SSID2SCAN_LEN; + memcpy(priv->ss_ssid, SSID2SCAN, SSID2SCAN_LEN); + DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=%d, rescan=%d\n", (char *)__FUNCTION__, priv->ss_ssidlen, rescan); + priv->jiffies_pre = jiffies; + +#ifdef WIFI_WPAS_CLI + event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL); +#else + if((OPMODE & WIFI_ADHOC_STATE) && rescan) + RTL_W8(TXPAUSE, RTL_R8(TXPAUSE) | STOP_BCN); //when start Ad-hoc ss, disable beacon + start_clnt_ss(priv); +#ifdef MULTI_MAC_CLONE + mclone_start_roaming(priv); +#endif +#endif + return; + } + +#ifdef SMART_REPEATER_MODE + + if (priv->ss_req_ongoing != SSFROM_REPEATER_VXD) +#endif + { + memset(&pmib->dot11Bss, 0, sizeof(struct bss_desc)); + } + + + if (SSID2SCAN_LEN > 0 +#ifdef SUPPORT_MULTI_PROFILE + || (priv->pmib->ap_profile.enable_profile && priv->pmib->ap_profile.profile_num > 0) +#endif + ) + { + for (i=priv->join_index+1; isite_survey->count_target; i++) + { + // check SSID +#ifdef SUPPORT_MULTI_PROFILE + + if (priv->pmib->ap_profile.enable_profile && priv->pmib->ap_profile.profile_num > 0) { + int pidx = priv->profile_idx; + found = 0; + for(j2=0;j2pmib->ap_profile.profile_num;j2++) + { + j1 = (pidx + j2) % priv->pmib->ap_profile.profile_num; + + if(strlen(priv->pmib->ap_profile.profile[j1].ssid)==0){ + continue; + } + SSID2SCAN_LEN = strlen(priv->pmib->ap_profile.profile[j1].ssid); + memcpy(SSID2SCAN, priv->pmib->ap_profile.profile[j1].ssid, SSID2SCAN_LEN); + SSID2SCAN[SSID2SCAN_LEN]='\0'; + + //STADEBUG("Profile.ssid=%s, target.ssid=%s,rssi=[%d]\n",priv->pmib->ap_profile.profile[j1].ssid, priv->site_survey->bss_target[i].ssid,priv->site_survey->bss_target[i].rssi); + if ((priv->site_survey->bss_target[i].ssidlen == SSID2SCAN_LEN) && + (!memcmp(SSID2SCAN, priv->site_survey->bss_target[i].ssid, SSID2SCAN_LEN)) + ) { + priv->profile_idx = j1; + //STADEBUG(" found[%s];switch_profile(%d)\n",SSID2SCAN ,priv->profile_idx); + switch_profile(priv, priv->profile_idx); + + if(check_ap_security(priv, &priv->site_survey->bss_target[i])) { + syncMulticastCipher(priv, &priv->site_survey->bss_target[i]); + found = 1; + break; + } + } + } + int idx3,tmpidx; + tmpidx = priv->profile_idx; + for(idx3=0;idx3pmib->ap_profile.profile_num;idx3++){ + tmpidx++; + tmpidx%=priv->pmib->ap_profile.profile_num; + if(strlen(priv->pmib->ap_profile.profile[tmpidx].ssid)==0){ + }else{ + priv->profile_idx=tmpidx; + break; + } + } + STADEBUG("next to search profile_idx[%d]\n",priv->profile_idx); + } + else + { + if ((priv->site_survey->bss_target[i].ssidlen == SSID2SCAN_LEN) && + (!memcmp(SSID2SCAN, priv->site_survey->bss_target[i].ssid, SSID2SCAN_LEN))) + { +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(priv->simple_config_status == 3) + { + rtk_sc_check_security(priv, &(priv->site_survey->bss_target[i])); + } +#endif + found = 1; + + } + else + found = 0; + } +#endif + +#ifdef SUPPORT_MULTI_PROFILE + if (found) +#else + if ((priv->site_survey->bss_target[i].ssidlen == SSID2SCAN_LEN) && + (!memcmp(SSID2SCAN, priv->site_survey->bss_target[i].ssid, SSID2SCAN_LEN))) +#endif + { +#ifdef SUPPORT_CLIENT_MIXED_SECURITY + choose_cipher(priv, &priv->site_survey->bss_target[i]); +#endif + syncMulticastCipher(priv, &priv->site_survey->bss_target[i]); + // check BSSID + if ( +#ifndef WIFI_WPAS + !memcmp(pmib->dot11StationConfigEntry.dot11DesiredBssid, null_mac, MACADDRLEN) || +#endif + !memcmp(priv->site_survey->bss_target[i].bssid, pmib->dot11StationConfigEntry.dot11DesiredBssid, MACADDRLEN) +#ifdef SMART_REPEATER_MODE + || (priv->ss_req_ongoing == SSFROM_REPEATER_VXD) +#endif + ) + { +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(priv->simple_config_status == 3) + { + rtk_sc_check_security(priv, &(priv->site_survey->bss_target[i])); + } +#endif + // check BSS type + if (((OPMODE & WIFI_STATION_STATE) && (priv->site_survey->bss_target[i].bsstype == WIFI_AP_STATE)) || + ((OPMODE & WIFI_ADHOC_STATE) && (priv->site_survey->bss_target[i].bsstype == WIFI_ADHOC_STATE)) +#ifdef SMART_REPEATER_MODE + || ((priv->ss_req_ongoing == SSFROM_REPEATER_VXD) && (priv->site_survey->bss_target[i].bsstype == WIFI_AP_STATE)) +#endif + ) + { + + /*check encryption ; if security setting no match with mine use next site_survey->bss_target */ + if ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_NO_PRIVACY_) && (priv->site_survey->bss_target[i].capability&BIT(4))) + continue; + else if ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_)) { + if ((priv->site_survey->bss_target[i].capability&BIT(4))==0) + continue; + else if (priv->site_survey->bss_target[i].t_stamp[0]!=0) + continue; + } + else if ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)) { + if ((priv->site_survey->bss_target[i].capability&BIT(4))==0) + continue; + else if (priv->site_survey->bss_target[i].t_stamp[0]==0) + continue; + } + if ((OPMODE & WIFI_ADHOC_STATE) && (priv->site_survey->bss_target[i].bsstype == WIFI_ADHOC_STATE)){ + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK){ + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK==1){ + if (!((priv->site_survey->bss_target[i].t_stamp[0] & (BIT(2)|BIT(4)|BIT(8)|BIT(10))))) { + continue; + } + } + else if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK==2){ + if (!((priv->site_survey->bss_target[i].t_stamp[0] & (BIT(18)|BIT(20)|BIT(24)|BIT(26))))){ + continue; + } + } + } + } + +#ifdef CONFIG_IEEE80211W_CLI + if (!priv->support_pmf + && (priv->pmib->dot1180211AuthEntry.dot11IEEE80211W==MGMT_FRAME_PROTECTION_REQUIRED) + && (priv->pmib->dot1180211AuthEntry.dot11EnablePSK & PSK_WPA2)) { + PMFDEBUG("(%s)line=%d, AP NOT SUPPORT PMF, but CLI is PMF requested\n", __FUNCTION__, __LINE__); + PMFDEBUG("(%s)line=%d, dot11IEEE80211W = %d\n", __FUNCTION__, __LINE__,priv->pmib->dot1180211AuthEntry.dot11IEEE80211W); + continue; + } +#endif + /*check encryption ; if security setting no match with mine use next site_survey->bss_target */ + { + // check network type + if (check_bss_networktype(priv, &(priv->site_survey->bss_target[i]))) + { + #ifdef MBSSID + /*under multi-repeater case when some STA has connect , the other one don't connect to diff channel AP ; skip this*/ + if(IS_VAP_INTERFACE(priv) && multiRepeater_startlookup_chk(priv,i) ){ + STADEBUG("RP1 rdy connected and RP2's target ch/2nd ch not match\n"); + continue; + } + #endif + memcpy(tmpbuf, SSID2SCAN, SSID2SCAN_LEN); + tmpbuf[SSID2SCAN_LEN] = '\0'; + DEBUG_INFO("found desired bss [%s], start to join\n", tmpbuf); + STADEBUG("(1)found desired bss [%s] start to join,\n ch=%d,2ndch=%d , i=%d\n",tmpbuf ,priv->pshare->switch_chan_rp ,priv->pshare->switch_2ndchoff_rp,i ); + + + memcpy(&pmib->dot11Bss, &(priv->site_survey->bss_target[i]), sizeof(struct bss_desc)); + break; + } + } + } + } + } + } + priv->join_index = i; + } + else + { + for (i=priv->join_index+1; isite_survey->count_target; i++) + { + // check BSSID + if (!memcmp(pmib->dot11StationConfigEntry.dot11DesiredBssid, null_mac, MACADDRLEN) || + !memcmp(priv->site_survey->bss_target[i].bssid, pmib->dot11StationConfigEntry.dot11DesiredBssid, MACADDRLEN)) + { +#ifdef SUPPORT_CLIENT_MIXED_SECURITY + choose_cipher(priv, &priv->site_survey->bss_target[i]); +#endif + syncMulticastCipher(priv, &priv->site_survey->bss_target[i]); + // check BSS type + if (((OPMODE & WIFI_STATION_STATE) && (priv->site_survey->bss_target[i].bsstype == WIFI_AP_STATE)) || + ((OPMODE & WIFI_ADHOC_STATE) && (priv->site_survey->bss_target[i].bsstype == WIFI_ADHOC_STATE))) + { + // check encryption + if (((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) && (priv->site_survey->bss_target[i].capability&BIT(4))) || + ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==0) && ((priv->site_survey->bss_target[i].capability&BIT(4))==0))) + { + if ((OPMODE & WIFI_ADHOC_STATE) && (priv->site_survey->bss_target[i].bsstype == WIFI_ADHOC_STATE)){ + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK){ + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK==1){ + if (!((priv->site_survey->bss_target[i].t_stamp[0] & (BIT(2)|BIT(4)|BIT(8)|BIT(10))))) { + continue; + } + } + else if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK==2){ + if (!((priv->site_survey->bss_target[i].t_stamp[0] & (BIT(18)|BIT(20)|BIT(24)|BIT(26))))){ + continue; + } + } + } + } + // check network type + if (check_bss_networktype(priv, &(priv->site_survey->bss_target[i]))) + { + #if 0 //def UNIVERSAL_REPEATER + // if this is vxd interface, and chan of found AP is + if ((GET_ROOT_PRIV(priv)->pmib->dot11RFEntry.dot11channel!= priv->site_survey->bss_target[i].channel)){ + SDEBUG("if this is vxd interface, and chan of found AP is different with root interface AP, skip it\n"); + continue; + } + #endif + memcpy(tmpbuf, priv->site_survey->bss_target[i].ssid, priv->site_survey->bss_target[i].ssidlen); + tmpbuf[priv->site_survey->bss_target[i].ssidlen] = '\0'; + DEBUG_INFO("found desired bss [%s], start to join\n", tmpbuf); + STADEBUG("(2)found desired bss [%s], start to join\n\n", tmpbuf); + + memcpy(&pmib->dot11Bss, &(priv->site_survey->bss_target[i]), sizeof(struct bss_desc)); +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if(priv->simple_config_status == 3) + { + rtk_sc_check_security(priv, &(priv->site_survey->bss_target[i])); + } +#endif + + break; + } + } + } + } + } + priv->join_index = i; + } + +#ifdef WIFI_WPAS + if(priv->wpas_manual_assoc == 0) +#endif + { +//#ifdef SMART_REPEATER_MODE;20130725 remove + // if (priv->ss_req_ongoing != 3) +//#endif + start_clnt_join(priv); + } + +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if((priv->simple_config_could_fix == 0) && (priv->pmib->dot11StationConfigEntry.sc_enabled == 1)) + { + priv->simple_config_could_fix = 1; + } +#endif +} + + +static void calculate_rx_beacon(struct rtl8192cd_priv *priv) +{ + int window_top; + unsigned int rx_beacon_delta, expect_num, decision_period, rx_data_delta; + + if ((((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) || + ((OPMODE & WIFI_ADHOC_STATE) && + ((JOIN_RES == STATE_Sta_Ibss_Active) || (JOIN_RES == STATE_Sta_Ibss_Idle)))) && + !priv->ss_req_ongoing) + { + if (OPMODE & WIFI_ADHOC_STATE) + decision_period = ROAMING_DECISION_PERIOD_ADHOC; + else + decision_period = ROAMING_DECISION_PERIOD_INFRA; + + priv->rxBeaconCntArray[priv->rxBeaconCntArrayIdx] = priv->rxBeaconNumInPeriod; + priv->rxDataCntArray[priv->rxBeaconCntArrayIdx] = priv->rxDataNumInPeriod; + if (priv->rxBeaconCntArrayWindow < decision_period) + priv->rxBeaconCntArrayWindow++; + else + { + window_top = priv->rxBeaconCntArrayIdx + 1; + if (window_top == decision_period) + window_top = 0; + + rx_beacon_delta = UINT32_DIFF(priv->rxBeaconCntArray[priv->rxBeaconCntArrayIdx], + priv->rxBeaconCntArray[window_top]); + + rx_data_delta = UINT32_DIFF(priv->rxDataCntArray[priv->rxBeaconCntArrayIdx], + priv->rxDataCntArray[window_top]); + + expect_num = (decision_period * 1000) / priv->beacon_period; + priv->rxBeaconPercentage = (rx_beacon_delta * 100) / expect_num; + + //DEBUG_INFO("Rx beacon percentage=%d%%, delta=%d, cnt=%d\n", priv->rxBeaconPercentage, + // rx_beacon_delta, priv->rxBeaconCntArray[priv->rxBeaconCntArrayIdx]); +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) + { + // when fast-roaming is enabled, trigger roaming while (david+2006-01-25): + // - no any beacon frame received in last one sec (under beacon interval is <= 200ms) + // - rx beacon is less than FAST_ROAMING_THRESHOLD + int offset, fast_roaming_triggered=0; +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + int if_idx = -1; +#endif + if (priv->pmib->dot11StationConfigEntry.fastRoaming) { + if (priv->beacon_period <= 200) { + if (priv->rxBeaconCntArrayIdx == 0) + offset = priv->rxBeaconNumInPeriod - priv->rxBeaconCntArray[decision_period]; + else + offset = priv->rxBeaconNumInPeriod - priv->rxBeaconCntArray[priv->rxBeaconCntArrayIdx-1]; + if (offset == 0) + fast_roaming_triggered = 1; + } + if (!fast_roaming_triggered && priv->rxBeaconPercentage < FAST_ROAMING_THRESHOLD) + fast_roaming_triggered = 1; + } + if ((priv->rxBeaconPercentage < ROAMING_THRESHOLD || fast_roaming_triggered) && !rx_data_delta) { + DEBUG_INFO("Roaming...\n"); + LOG_MSG("Roaming...\n"); +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Roaming...;note:\n"); +#endif + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)); +#ifdef UNIVERSAL_REPEATER + disable_vxd_ap(GET_VXD_PRIV(priv)); +#endif + + JOIN_RES_VAL(STATE_Sta_No_Bss); +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + if((if_idx = get_wlan_if_type(priv))>=0){ + set_if_status(if_idx,IF_DOWN); + set_if_change_status(if_idx,IF_STATUS_CHANGE); + } +#endif + +#ifdef CONFIG_POWER_SAVE + rtw_lock_suspend_timeout(priv, 3000); +#endif + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + event_indicate_cfg80211(priv, NULL, CFG80211_DISCONNECTED, NULL); +#elif defined(WIFI_WPAS_CLI) + event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL); +#else //do not auto site survey when disconnected //eric-sync ?? + STADEBUG("start_clnt_lookup(RESCAN_ROAMING)\n"); + start_clnt_lookup(priv, RESCAN_ROAMING); +#endif + #ifdef CONFIG_RTL_WLAN_STATUS + //panic_printk("%s:%d\n",__FUNCTION__,__LINE__); + priv->wlan_status_flag=1; + #endif + + } + } + else + { + if ((rx_beacon_delta == 0) && (rx_data_delta == 0)) { + if (JOIN_RES == STATE_Sta_Ibss_Active) + { + DEBUG_INFO("Searching IBSS...\n"); + LOG_MSG("Searching IBSS...\n"); + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT)); + JOIN_RES_VAL(STATE_Sta_Ibss_Idle); + start_clnt_lookup(priv, RESCAN); + } + } + } +#endif // CLIENT_MODE + } + + priv->rxBeaconCntArrayIdx++; + if (priv->rxBeaconCntArrayIdx == decision_period) + priv->rxBeaconCntArrayIdx = 0; + } +} + + +void rtl8192cd_reauth_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned long flags = 0; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + +#ifdef MULTI_MAC_CLONE + ACTIVE_ID = 0; +#endif + + REAUTH_COUNT_VAL(REAUTH_COUNT+1); + if (REAUTH_COUNT > REAUTH_LIMIT) + { + DEBUG_WARN("Client Auth time-out!\n"); + RESTORE_INT(flags); + SMP_UNLOCK(flags); +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + event_indicate_cfg80211(priv, NULL, CFG80211_DISCONNECTED, NULL); +#elif defined(WIFI_WPAS_CLI) + event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL); +#else + start_clnt_lookup(priv, DONTRESCAN); +#endif + return; + } + + if (OPMODE & WIFI_AUTH_SUCCESS) + { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return; + } + + AUTH_SEQ_VAL(1); + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_STATE1)); + OPMODE_VAL(OPMODE | WIFI_AUTH_NULL); + + DEBUG_INFO("auth timeout, sending auth req again\n"); + issue_auth(priv, NULL, 0); + + mod_timer(&priv->reauth_timer, jiffies + REAUTH_TO); + + RESTORE_INT(flags); + SMP_UNLOCK(flags); +} + + +void rtl8192cd_reassoc_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned long flags = 0; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + +#ifdef MULTI_MAC_CLONE + ACTIVE_ID = 0; +#endif + + REASSOC_COUNT_VAL(REASSOC_COUNT+1); + if (REASSOC_COUNT > REASSOC_LIMIT) + { + DEBUG_WARN("Client Assoc time-out!\n"); + RESTORE_INT(flags); + SMP_UNLOCK(flags); +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + event_indicate_cfg80211(priv, NULL, CFG80211_DISCONNECTED, NULL); +#elif defined(WIFI_WPAS_CLI) + event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL); +#else + STADEBUG("Client Assoc time-out!; start_clnt_lookup(DONTRESCAN)\n"); + start_clnt_lookup(priv, DONTRESCAN); +#endif + return; + } + + if (OPMODE & WIFI_ASOC_STATE) + { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return; + } + + DEBUG_INFO("assoc timeout, sending assoc req again\n"); + issue_assocreq(priv); + + MOD_REASSOC_TIMER(REASSOC_TO); + + RESTORE_INT(flags); + SMP_UNLOCK(flags); +} + + +void rtl8192cd_idle_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + SMP_LOCK(flags); + if (!(priv->drv_state & DRV_STATE_OPEN)) { + SMP_UNLOCK(flags); + return; + } + + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT)); + LOG_MSG("Searching IBSS...\n"); + start_clnt_lookup(priv, RESCAN); + SMP_UNLOCK(flags); +} + +#ifdef MULTI_MAC_CLONE +void rtl8192cd_mclone_reauth_timer(unsigned long data) +{ + struct mclone_timer_data *timer_data = (struct mclone_timer_data *)data; + struct rtl8192cd_priv *priv; + unsigned long active_id = timer_data->active_id; + unsigned long flags; + + ASSERT(active_id > 0 && active_id <= MAX_MAC_CLONE_NUM); + priv = timer_data->priv->pshare->mclone_sta[active_id-1].priv; + + if ((NULL == priv) || (!(priv->drv_state & DRV_STATE_OPEN))) + return; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + + if (!((GET_MIB(priv))->dot11OperationEntry.opmode & WIFI_ASOC_STATE)) { + ACTIVE_ID = active_id; + MOD_REAUTH_TIMER(REAUTH_TO); + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return; + } + + panic_printk("%s enter %s [%d]\n", priv->dev->name, __FUNCTION__, active_id-1); // for debug + + ACTIVE_ID = active_id; + + REAUTH_COUNT_VAL(REAUTH_COUNT+1); + if (REAUTH_COUNT > REAUTH_LIMIT) { + DEBUG_WARN("Client Auth time-out!\n"); + RESTORE_INT(flags); + SMP_UNLOCK(flags); + + start_clnt_auth(priv); + return; + } + + if (OPMODE & WIFI_AUTH_SUCCESS) { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return; + } + + + AUTH_SEQ_VAL(1); + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_STATE1)); + OPMODE_VAL(OPMODE | WIFI_AUTH_NULL); + + DEBUG_INFO("auth timeout, sending auth req again\n"); + + if ((GET_MIB(priv))->dot11OperationEntry.opmode & WIFI_ASOC_STATE) + issue_auth(priv, NULL, 0); + + MOD_REAUTH_TIMER(REAUTH_TO); + + RESTORE_INT(flags); + SMP_UNLOCK(flags); +} + +void rtl8192cd_mclone_reassoc_timer(unsigned long data) +{ + struct mclone_timer_data *timer_data = (struct mclone_timer_data *)data; + struct rtl8192cd_priv *priv; + unsigned long active_id = timer_data->active_id; + unsigned long flags; + + ASSERT(active_id > 0 && active_id <= MAX_MAC_CLONE_NUM); + priv = timer_data->priv->pshare->mclone_sta[active_id-1].priv; + + if ((NULL == priv) || (!(priv->drv_state & DRV_STATE_OPEN))) + return; + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + + if (!((GET_MIB(priv))->dot11OperationEntry.opmode & WIFI_ASOC_STATE)) { + ACTIVE_ID = active_id; + MOD_REASSOC_TIMER(REASSOC_TO); + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return; + } + + panic_printk("%s enter %s [%d]\n", priv->dev->name, __FUNCTION__, active_id-1); // for debug + + ACTIVE_ID = active_id; + + REASSOC_COUNT_VAL(REASSOC_COUNT+1); + if (REASSOC_COUNT > REASSOC_LIMIT) { + DEBUG_WARN("Client Assoc time-out!\n"); + RESTORE_INT(flags); + SMP_UNLOCK(flags); + + start_clnt_auth(priv); + return; + } + + if (OPMODE & WIFI_ASOC_STATE) { + RESTORE_INT(flags); + SMP_UNLOCK(flags); + return; + } + + DEBUG_INFO("assoc timeout, sending assoc req again\n"); + + if ((GET_MIB(priv))->dot11OperationEntry.opmode & WIFI_ASOC_STATE) + issue_assocreq(priv); + + MOD_REASSOC_TIMER(REASSOC_TO); + + RESTORE_INT(flags); + SMP_UNLOCK(flags); +} +#endif /* MULTI_MAC_CLONE */ + +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +static unsigned int OnAssocRsp(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + struct wifi_mib *pmib; + struct stat_info *pstat; + unsigned char *pframe, *p; + unsigned char *ptr; + DOT11_ASSOCIATION_IND Association_Ind; + unsigned char supportRate[32]; + int supportRateNum; + UINT16 val; + int len; +#ifdef P2P_SUPPORT + unsigned char ReAssem_p2pie[MAX_REASSEM_P2P_IE]; + int IEfoundtimes=0; + unsigned char *p2pIEPtr = ReAssem_p2pie ; + int p2pIElen=0; +#endif +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + int if_idx = -1; +#endif + + + + if (!(OPMODE & WIFI_STATION_STATE)) + return SUCCESS; + + if (memcmp(GET_MY_HWADDR, pfrinfo->da, MACADDRLEN)) + return SUCCESS; + + if (OPMODE & WIFI_SITE_MONITOR) + return SUCCESS; + + if (OPMODE & WIFI_ASOC_STATE) + return SUCCESS; + + pmib = GET_MIB(priv); + pframe = get_pframe(pfrinfo); + DEBUG_INFO("got assoc response (OPMODE %x seq %d)\n", OPMODE, GetSequence(pframe)); + + // checking status + val = cpu_to_le16(*(unsigned short*)((unsigned long)pframe + WLAN_HDR_A3_LEN + 2)); + + if (val) { + DEBUG_ERR("assoc reject, status: %d\n", val); + goto assoc_rejected; + } + + AID_VAL(cpu_to_le16(*(unsigned short*)((unsigned long)pframe + WLAN_HDR_A3_LEN + 4)) & 0x3fff); + + pstat = get_stainfo(priv, pfrinfo->sa); + if (pstat == NULL) { + pstat = alloc_stainfo(priv, pfrinfo->sa, -1); + if (pstat == NULL) { + DEBUG_ERR("Exceed the upper limit of supported clients...\n"); + goto assoc_rejected; + } + } + else { + SAVE_INT_AND_CLI(flags); + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + release_stainfo(priv, pstat); + init_stainfo(priv, pstat); + RESTORE_INT(flags); + } + pstat->tpcache_mgt = GetTupleCache(pframe); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + update_remapAid(priv,pstat); + if (pstat && pstat->sta_in_firmware == 1) { + RTL8188E_MACID_NOLINK(priv, 0, REMAP_AID(pstat)); + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + } +#endif + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + if(pstat && (REMAP_AID(pstat) < 128)) + { + DEBUG_WARN("%s %d OnAssocRsp, set MACID 0 AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + } + else + { + DEBUG_WARN(" MACID sleep only support 128 STA \n"); + } + } +#endif + + + // Realtek proprietary IE + pstat->is_realtek_sta = FALSE; + pstat->IOTPeer = HT_IOT_PEER_UNKNOWN; + p = pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_; len = 0; + for (;;) { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, Realtek_OUI, 3) && *(p+2+3) == 2) { /*found realtek out and type == 2*/ + pstat->is_realtek_sta = TRUE; + pstat->IOTPeer = HT_IOT_PEER_REALTEK; + + if(*(p+2+3+2) & RTK_CAP_IE_WLAN_8192SE) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_92SE; + + if(*(p+2+3+2) & RTK_CAP_IE_WLAN_88C92C) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_81XX; + + if (*(p+2+3+3) & ( RTK_CAP_IE_8812_BCUT | RTK_CAP_IE_8812_CCUT)) + pstat->IOTPeer = HT_IOT_PEER_REALTEK_8812; + break; + } + } + else + break; + p = p + len + 2; + } + + // identify if this is Broadcom sta + p = pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_; len = 0; + + for (;;) + { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + unsigned int z; + for (z = 0; z < BCM_OUI_NUM; z++) { + if (!memcmp(p+2, BCM_OUI[z], 3)) { + pstat->IOTPeer = HT_IOT_PEER_BROADCOM; + break; + } + } + if (z < BCM_OUI_NUM) + break; + } + else + break; + + p = p + len + 2; + } + + // identify if this is ralink sta + p = pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_; len = 0; + + for (;;) + { + unsigned char Ralink_OUI1[]={0x00, 0x0c, 0x43}; + + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, Ralink_OUI1, 3)) { + + pstat->IOTPeer= HT_IOT_PEER_RALINK; + + break; + } + } + else + break; + p = p + len + 2; + } + + if(!pstat->is_realtek_sta && pstat->IOTPeer != HT_IOT_PEER_BROADCOM && pstat->IOTPeer != HT_IOT_PEER_RALINK) + + { + unsigned int z = 0; + for (z = 0; z < INTEL_OUI_NUM; z++) { + if ((pstat->hwaddr[0] == INTEL_OUI[z][0]) && + (pstat->hwaddr[1] == INTEL_OUI[z][1]) && + (pstat->hwaddr[2] == INTEL_OUI[z][2])) { + + pstat->IOTPeer= HT_IOT_PEER_INTEL; + + pstat->no_rts = 1; + break; + } + } + + } + + // get rates + p = get_ie(pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_, _SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _ASOCRSP_IE_OFFSET_); + if ((p == NULL) || (len > 32)){ + free_stainfo(priv, pstat); + return FAIL; + } + memcpy(supportRate, p+2, len); + supportRateNum = len; + p = get_ie(pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _ASOCRSP_IE_OFFSET_); + if ((p != NULL) && (len <= 8)) { + memcpy(supportRate+supportRateNum, p+2, len); + supportRateNum += len; + } + + // other capabilities + memcpy(&val, (pframe + WLAN_HDR_A3_LEN), 2); + val = le16_to_cpu(val); + if (val & BIT(5)) { + // set preamble according to AP + RTL_W8(RRSR+2, RTL_R8(RRSR+2) | BIT(7)); + pstat->useShortPreamble = 1; + } + else { + // set preamble according to AP + RTL_W8(RRSR+2, RTL_R8(RRSR+2) & ~BIT(7)); + pstat->useShortPreamble = 0; + } + + if ((priv->pshare->curr_band == BAND_2G) && (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) + { + if (val & BIT(10)) { + priv->pmib->dot11ErpInfo.shortSlot = 1; + set_slot_time(priv, priv->pmib->dot11ErpInfo.shortSlot); + } + else { + priv->pmib->dot11ErpInfo.shortSlot = 0; + set_slot_time(priv, priv->pmib->dot11ErpInfo.shortSlot); + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if (p && (*(p+2) & BIT(1))) // use Protection + priv->pmib->dot11ErpInfo.protection = 1; + else + priv->pmib->dot11ErpInfo.protection = 0; + + if (p && (*(p+2) & BIT(2))) // use long preamble + priv->pmib->dot11ErpInfo.longPreambleStaNum = 1; + else + priv->pmib->dot11ErpInfo.longPreambleStaNum = 0; + } + + // set associated and add to association list + pstat->state |= (WIFI_ASOC_STATE | WIFI_AUTH_SUCCESS); + +#ifdef WIFI_WMM // WMM STA + if (QOS_ENABLE) { + int i; + p = pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_; + for (;;) { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, WMM_PARA_IE, 6)) { + pstat->QosEnabled = 1; +//capture the EDCA para + p += 10; // start of EDCA parameters + for (i = 0; i <4; i++) { + process_WMM_para_ie(priv, p); //get the info + p += 4; + } + DEBUG_INFO("BE: ACM %d, AIFSN %d, ECWmin %d, ECWmax %d, TXOP %d\n", + GET_STA_AC_BE_PARA.ACM, GET_STA_AC_BE_PARA.AIFSN, + GET_STA_AC_BE_PARA.ECWmin, GET_STA_AC_BE_PARA.ECWmax, + GET_STA_AC_BE_PARA.TXOPlimit); + DEBUG_INFO("VO: ACM %d, AIFSN %d, ECWmin %d, ECWmax %d, TXOP %d\n", + GET_STA_AC_VO_PARA.ACM, GET_STA_AC_VO_PARA.AIFSN, + GET_STA_AC_VO_PARA.ECWmin, GET_STA_AC_VO_PARA.ECWmax, + GET_STA_AC_VO_PARA.TXOPlimit); + DEBUG_INFO("VI: ACM %d, AIFSN %d, ECWmin %d, ECWmax %d, TXOP %d\n", + GET_STA_AC_VI_PARA.ACM, GET_STA_AC_VI_PARA.AIFSN, + GET_STA_AC_VI_PARA.ECWmin, GET_STA_AC_VI_PARA.ECWmax, + GET_STA_AC_VI_PARA.TXOPlimit); + DEBUG_INFO("BK: ACM %d, AIFSN %d, ECWmin %d, ECWmax %d, TXOP %d\n", + GET_STA_AC_BK_PARA.ACM, GET_STA_AC_BK_PARA.AIFSN, + GET_STA_AC_BK_PARA.ECWmin, GET_STA_AC_BK_PARA.ECWmax, + GET_STA_AC_BK_PARA.TXOPlimit); + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + SAVE_INT_AND_CLI(flags); + sta_config_EDCA_para(priv); + RESTORE_INT(flags); + } + break; + } + } + else { + pstat->QosEnabled = 0; + break; + } + p = p + len + 2; + } + } + else { + pstat->QosEnabled = 0; + } +#endif + + +#ifdef P2P_SUPPORT + if((OPMODE & WIFI_P2P_SUPPORT) && ((P2PMODE == P2P_CLIENT)||(P2PMODE == P2P_PRE_CLIENT))) + { + + + ptr = pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_ ; + /*support ReAssemble*/ + for (;;) + { + /*get P2P_IE*/ + ptr = get_ie(ptr, _P2P_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _ASOCRSP_IE_OFFSET_ - len); + + if (ptr) { + if (!memcmp(ptr+2, WFA_OUI_PLUS_TYPE, 4)) { + memcpy(p2pIEPtr , ptr+6 ,len - 4); + p2pIEPtr += (len - 4); + IEfoundtimes ++; + } + } + else{ + break; + } + ptr = ptr + len + 2; + + } + + if(IEfoundtimes){ + + if(IEfoundtimes>1){ + P2P_DEBUG("ReAssembly p2p IE\n"); + } + p2pIElen = (int)(((unsigned long)p2pIEPtr)-((unsigned long)ReAssem_p2pie)); + + if(p2pIElen > MAX_REASSEM_P2P_IE){ + P2P_DEBUG("\n\n reassemble P2P IE exceed MAX_REASSEM_P2P_IE , chk!!!\n\n"); + }else{ + P2P_on_assoc_rsp(priv,pfrinfo->sa); + pstat->is_p2p_client = 1; + } + } +} +#endif + + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && priv->ht_cap_len) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_, _HT_CAP_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _ASOCRSP_IE_OFFSET_); + if ((p != NULL) && (len <= sizeof(struct ht_cap_elmt))) { + pstat->ht_cap_len = len; + memcpy((unsigned char *)&pstat->ht_cap_buf, p+2, len); + } else { + pstat->ht_cap_len = 0; + memset((unsigned char *)&pstat->ht_cap_buf, 0, sizeof(struct ht_cap_elmt)); + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_, _HT_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _ASOCRSP_IE_OFFSET_); + if ((p != NULL) && (len <= sizeof(struct ht_info_elmt))) { + pstat->ht_ie_len = len; + memcpy((unsigned char *)&pstat->ht_ie_buf, p+2, len); + + priv->ht_protection = 0; + if (!priv->pmib->dot11StationConfigEntry.protectionDisabled && pstat->ht_ie_len) { + unsigned int prot_mode = (cpu_to_le16(pstat->ht_ie_buf.info1) & 0x03); + if (prot_mode == _HTIE_OP_MODE1_ || prot_mode == _HTIE_OP_MODE3_) + priv->ht_protection = 1; + } + } else { + pstat->ht_ie_len = 0; + } + + if (pstat->ht_cap_len) { + if (cpu_to_le16(pstat->ht_cap_buf.ht_cap_info) & _HTCAP_AMSDU_LEN_8K_) { + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 7935 - sizeof(struct wlan_hdr); + } else { + pstat->is_8k_amsdu = 0; + pstat->amsdu_level = 3839 - sizeof(struct wlan_hdr); + } + +#ifdef WIFI_11N_2040_COEXIST + priv->coexist_connection = 0; + + if (priv->pmib->dot11nConfigEntry.dot11nCoexist && + (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_, _EXTENDED_CAP_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _ASOCRSP_IE_OFFSET_); + + if (p != NULL) { + if (*(p+2) & _2040_COEXIST_SUPPORT_) + priv->coexist_connection = 1; + } + } +#endif + } + } + + +//8812_client add pstat vht ie +#ifdef RTK_AC_SUPPORT + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) + { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_, EID_VHTCapability, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _ASOCRSP_IE_OFFSET_); + + if ((p != NULL) && (len <= sizeof(struct vht_cap_elmt))) { + pstat->vht_cap_len = len; + memcpy((unsigned char *)&pstat->vht_cap_buf, p+2, len); + printk("receive vht_cap len = %d \n", len); + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_, EID_VHTOperation, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _ASOCRSP_IE_OFFSET_); + + if ((p != NULL) && (len <= sizeof(struct vht_oper_elmt))) { + pstat->vht_oper_len = len; + memcpy((unsigned char *)&pstat->vht_oper_buf, p+2, len); + printk("receive vht_oper len = %d \n", len); + } + } +#endif + +#ifdef WIFI_WMM // WMM STA + if (QOS_ENABLE) { + if ((pstat->QosEnabled == 0) && pstat->ht_cap_len) { + DEBUG_INFO("AP supports HT but doesn't support WMM, use default WMM value\n"); + pstat->QosEnabled = 1; + default_WMM_para(priv); +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + SAVE_INT_AND_CLI(flags); + sta_config_EDCA_para(priv); + RESTORE_INT(flags); + } + } + } +#endif + +//Client mode IOT issue, Button 2009.07.17 + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _NO_PRIVACY_) + #if defined(CONFIG_RTL_WAPI_SUPPORT) + &&(pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WAPI_SMS4_) + #endif + ) + { + pstat->is_legacy_encrpt = 0; + if ((pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) || + (pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_ )) + pstat->is_legacy_encrpt = 2; + else if (pmib->dot11RsnIE.rsnielen) { + if (pmib->dot11RsnIE.rsnie[0] == _RSN_IE_1_) { + if (is_support_wpa_aes(priv, pmib->dot11RsnIE.rsnie, pmib->dot11RsnIE.rsnielen) != 1) + pstat->is_legacy_encrpt = 1; + } + else { + if (is_support_wpa2_aes(priv, pmib->dot11RsnIE.rsnie, pmib->dot11RsnIE.rsnielen) != 1) + pstat->is_legacy_encrpt = 1; + } + } + } + + priv->pshare->AP_BW = -1; +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + if(GET_ROOT(priv)->pmib->dot11nConfigEntry.dot11nUse40M) { + if((pstat->ht_cap_len > 0) && (pstat->ht_ie_len > 0) && + (pstat->ht_ie_buf.info0 & _HTIE_STA_CH_WDTH_) && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))) { + priv->pshare->is_40m_bw = 1; + } + } + } +#endif + + if (pstat->ht_cap_len) { + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)) + pstat->tx_bw = HT_CHANNEL_WIDTH_20_40; + else + pstat->tx_bw = HT_CHANNEL_WIDTH_20; + } + + get_matched_rate(priv, supportRate, &supportRateNum, 1); + update_support_rate(pstat, supportRate, supportRateNum); + assign_tx_rate(priv, pstat, pfrinfo); + assign_aggre_mthod(priv, pstat); + assign_aggre_size(priv, pstat); + +#if defined(INCLUDE_WPA_PSK) && !defined(WIFI_WPAS_CLI) && (!defined(RTK_NL80211) || defined(NON_NL80211_WPAS)) + if (IEEE8021X_FUN && priv->pmib->dot1180211AuthEntry.dot11EnablePSK) { + if (psk_indicate_evt(priv, DOT11_EVENT_ASSOCIATION_IND, GetAddr2Ptr(pframe), NULL, 0) < 0){ + STADEBUG("assoc_rejected\n"); + goto assoc_rejected; + } + } +#endif + + SAVE_INT_AND_CLI(flags); + + pstat->expire_to = priv->expire_to; + asoc_list_add(priv, pstat); + cnt_assoc_num(priv, pstat, INCREASE, (char *)__FUNCTION__); + + if (!IEEE8021X_FUN && + !(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_)) { +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Connected to AP;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + if((if_idx = get_wlan_if_type(priv))>=0){ + set_if_status(if_idx,IF_UP); + set_if_change_status(if_idx,IF_STATUS_CHANGE); + } +#endif +#else + LOG_MSG("Associate to AP successfully - %02X:%02X:%02X:%02X:%02X:%02X\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + if((if_idx = get_wlan_if_type(priv))>=0){ + set_if_status(if_idx,IF_UP); + set_if_change_status(if_idx,IF_STATUS_CHANGE); + } +#endif +#endif + } + + // now we have successfully join the give bss... + if (PENDING_REAUTH_TIMER) + DELETE_REAUTH_TIMER; + if (PENDING_REASSOC_TIMER) + DELETE_REASSOC_TIMER; + + // clear cached Dev +#if defined(BR_SHORTCUT) && defined(CLIENT_MODE) + { + extern unsigned char cached_sta_mac[6]; + extern struct net_device *cached_sta_dev; + memset(cached_sta_mac, 0, MACADDRLEN); + cached_sta_dev = NULL; + } +#endif + + RESTORE_INT(flags); + + OPMODE_VAL(OPMODE | WIFI_ASOC_STATE); + update_bss(&priv->pmib->dot11StationConfigEntry, &priv->pmib->dot11Bss); + priv->pmib->dot11RFEntry.dot11channel = priv->pmib->dot11Bss.channel; + join_bss(priv); + + JOIN_RES_VAL(STATE_Sta_Bss); + JOIN_REQ_ONGOING_VAL(0); + +#ifndef WITHOUT_ENQUEUE + if (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm +#ifdef WIFI_SIMPLE_CONFIG + && !(priv->pmib->wscEntry.wsc_enable) +#endif + ) + { + memcpy((void *)Association_Ind.MACAddr, (void *)GetAddr2Ptr(pframe), MACADDRLEN); + Association_Ind.EventId = DOT11_EVENT_ASSOCIATION_IND; + Association_Ind.IsMoreEvent = 0; + Association_Ind.RSNIELen = 0; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Association_Ind, + sizeof(DOT11_ASSOCIATION_IND)); + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + //event_indicate_cfg80211(priv, GetAddr2Ptr(pframe), CFG80211_NEW_STA, NULL); +#else //RTK_NL80211 +#ifdef WIFI_HAPD + event_indicate_hapd(priv, GetAddr2Ptr(pframe), HAPD_REGISTERED, NULL); +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#else + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#endif //RTK_NL80211 + } +#endif // WITHOUT_ENQUEUE + +#ifdef WIFI_SIMPLE_CONFIG + if (priv->pmib->wscEntry.wsc_enable) { + DOT11_WSC_ASSOC_IND wsc_Association_Ind; + + memset(&wsc_Association_Ind, 0, sizeof(DOT11_WSC_ASSOC_IND)); + wsc_Association_Ind.EventId = DOT11_EVENT_WSC_ASSOC_REQ_IE_IND; + memcpy((void *)wsc_Association_Ind.MACAddr, (void *)GetAddr2Ptr(pframe), MACADDRLEN); +#ifdef INCLUDE_WPS + wps_NonQueue_indicate_evt(priv ,(UINT8 *)&wsc_Association_Ind, + sizeof(DOT11_WSC_ASSOC_IND)); +#else + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&wsc_Association_Ind, + sizeof(DOT11_WSC_ASSOC_IND)); + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + //event_indicate_cfg80211(priv, GetAddr2Ptr(pframe), CFG80211_NEW_STA, NULL); + +#else //RTK_NL80211 + +#ifdef WIFI_HAPD + event_indicate_hapd(priv, GetAddr2Ptr(pframe), HAPD_REGISTERED, NULL); +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#else + event_indicate(priv, GetAddr2Ptr(pframe), 1); +#endif +#endif //RTK_NL80211 + +#endif + pstat->state |= WIFI_WPS_JOIN; + } +#endif + +#if 0 + // Get operating bands + // | B | G | BG <= AP + // B | B | x | B + // G | x | G | G + // BG | B | G | BG + if ((priv->pshare->curr_band == WIRELESS_11A) || + (priv->pshare->curr_band == WIRELESS_11B)) + priv->oper_band = priv->pshare->curr_band; + else { // curr_band == WIRELESS_11G + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11B) || + !is_CCK_rate(pstat->bssrateset[0] & 0x7f)) + priv->oper_band = WIRELESS_11G; + else if (is_CCK_rate(pstat->bssrateset[pstat->bssratelen-1] & 0x7f)) + priv->oper_band = WIRELESS_11B; + else + priv->oper_band = WIRELESS_11B | WIRELESS_11G; + } +#endif + + DEBUG_INFO("assoc successful!\n"); + STADEBUG("Assoc successful!\n"); + +#ifdef DFS +#ifdef UNIVERSAL_REPEATER + //if(under_apmode_repeater(priv)) + { + RTL_W8(TXPAUSE, 0x0); + } +#endif +#endif + + if ((OPMODE & WIFI_STATION_STATE) +#ifdef UNIVERSAL_REPEATER + && IS_ROOT_INTERFACE(priv) +#endif + ) + priv->up_flag = 1; + +//#ifdef BR_SHORTCUT +#if 0 + clear_shortcut_cache(); +#if defined(CONFIG_RTL_FASTBRIDGE) + rtl_fb_flush(); +#endif +#endif + + +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv)) +#endif + { + if ((pstat->ht_cap_len > 0) && (pstat->ht_ie_len > 0) && + (pstat->ht_ie_buf.info0 & _HTIE_STA_CH_WDTH_) && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))) { + priv->pshare->is_40m_bw = 1; + if ((pstat->ht_ie_buf.info0 & _HTIE_2NDCH_OFFSET_BL_) == _HTIE_2NDCH_OFFSET_BL_) + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + else + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + + if (priv->pshare->is_40m_bw == 1) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_ABOVE) { + int i, channel = priv->pmib->dot11Bss.channel + 4; + for (i=0; iavailable_chnl_num; i++) { + if (channel == priv->available_chnl[i]) + break; + } + if (i == priv->available_chnl_num) { + priv->pshare->is_40m_bw = 0; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_DONTCARE; + DEBUG_INFO("AP is 40M (ch%d-ch%d) but not fit region domain, sw back to 20M\n", priv->pmib->dot11Bss.channel, channel); + } + } + } + +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D)&&(priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY)) { + clnt_ss_check_band(priv, priv->pmib->dot11Bss.channel); + } +#endif + +#ifdef RTK_AC_SUPPORT +//8812_client , check ap support 80m ?? + if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC)) { + if (pstat->vht_cap_len && (pstat->vht_oper_buf.vht_oper_info[0] == 1)) { + pstat->tx_bw = HT_CHANNEL_WIDTH_80; + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_80; + } + } + + //printk("vht_oper_info[0] = 0x%x\n", pstat->vht_oper_buf.vht_oper_info[0]); + //printk("vht_cap_len=%d, is_40m_bw=%d\n", pstat->vht_cap_len, priv->pshare->is_40m_bw); +#endif + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11Bss.channel, priv->pshare->offset_2nd_chan); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + PHY_IQCalibrate(priv); + +#ifdef DPK_92D + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_5G && priv->pshare->rf_ft_var.dpk_on) + PHY_DPCalibrate(priv); +#endif +#endif + + DEBUG_INFO("%s: set chan=%d, 40M=%d, offset_2nd_chan=%d\n", + __FUNCTION__, + priv->pmib->dot11Bss.channel, + priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + } + else { + priv->pshare->is_40m_bw = 0; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_DONTCARE; + +//_TXPWR_REDEFINE +#ifdef CONFIG_RTL_92D_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8192D)&&(priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY)) { + clnt_ss_check_band(priv, priv->pmib->dot11Bss.channel); + } +#endif + if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_5; + else if(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_10) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_10; + else + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11Bss.channel, priv->pshare->offset_2nd_chan); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D) + PHY_IQCalibrate(priv); +#endif + + } + } + +//8812_client , check ap support 80m ?? +#ifdef RTK_AC_SUPPORT + if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC)) { + if (pstat->vht_cap_len && (pstat->vht_oper_buf.vht_oper_info[0] == 1)) { + pstat->tx_bw = HT_CHANNEL_WIDTH_80; + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_80; + } + } +#endif +#ifdef BEAMFORMING_SUPPORT + + //panic_printk("%s, %x\n", __FUNCTION__, cpu_to_le32(pstat->vht_cap_buf.vht_cap_info)); + if(((GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv) == VERSION_8192E || GET_CHIP_VER(priv) == VERSION_8814A)) + && (priv->pmib->dot11RFEntry.txbf == 1)&& + ((pstat->ht_cap_len && (pstat->ht_cap_buf.txbf_cap)) +#ifdef RTK_AC_SUPPORT + || (pstat->vht_cap_len && (cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & (BIT(SU_BFEE_S)|BIT(SU_BFER_S)))) +// BeamformingControl(priv, pstat->hwaddr, pstat->aid, 0, pstat->tx_bw); +#endif + )) { + Beamforming_Enter(priv,pstat); + } +#endif + +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv)) { +#ifdef RTK_BR_EXT + if (!(priv->pmib->ethBrExtInfo.macclone_enable && !priv->macclone_completed)) +#endif + { + if ( +#ifdef __ECOS + GET_VXD_PRIV(priv) && +#endif + netif_running(GET_VXD_PRIV(priv)->dev)) + enable_vxd_ap(GET_VXD_PRIV(priv)); + } + } +#endif + +#ifndef USE_WEP_DEFAULT_KEY + set_keymapping_wep(priv, pstat); +#endif + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + UpdateHalRAMask8812(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } + +#ifdef P2P_SUPPORT // p2pcheck need check fit for all kind ic? + if ((OPMODE & WIFI_P2P_SUPPORT) && (P2PMODE == P2P_CLIENT)) + RTL_W32(RCR, RTL_R32(RCR) | RCR_CBSSID_ADHOC); +#endif + + +#ifdef WIFI_WPAS + //printk("_Eric WPAS_REGISTERED at %s %d\n", __FUNCTION__, __LINE__); + event_indicate_wpas(priv, GetAddr2Ptr(pframe), WPAS_REGISTERED, NULL); +#endif +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) +#if 1 //wrt_clnt + { + unsigned char *assocrsp_ie = pfrinfo->pskb->data + (WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_); + int assocrsp_ie_len = pfrinfo->pktlen - (WLAN_HDR_A3_LEN + _ASOCRSP_IE_OFFSET_); + + if(assocrsp_ie_len > 0) + { + //printk("AssocRsp Len = %d\n", assocrsp_ie_len); + if(assocrsp_ie_len > MAX_ASSOC_RSP_LEN) + { + printk("AssocRsp Len too LONG !!\n"); + memcpy(priv->rtk->clnt_info.assoc_rsp, assocrsp_ie, MAX_ASSOC_RSP_LEN); + priv->rtk->clnt_info.assoc_rsp_len = MAX_ASSOC_RSP_LEN; + } + else + { + memcpy(priv->rtk->clnt_info.assoc_rsp, assocrsp_ie, assocrsp_ie_len); + priv->rtk->clnt_info.assoc_rsp_len = assocrsp_ie_len; + } + + } + else + printk(" !! Error AssocRsp Len = %d\n", assocrsp_ie_len); + } +#endif + event_indicate_cfg80211(priv, GetAddr2Ptr(pframe), CFG80211_CONNECT_RESULT, NULL); +#endif + + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType==wapiTypeCert) + { + wapiAssert(pstat->wapiInfo->wapiState==ST_WAPI_AE_IDLE); + } + else if (priv->pmib->wapiInfo.wapiType==wapiTypePSK) + { + wapiAssert(pstat->wapiInfo->wapiState==ST_WAPI_AE_IDLE); + wapiSetBK(pstat); + } +#endif + + +#ifdef CLIENT_MODE + + if ((OPMODE & WIFI_STATION_STATE) && pstat->IOTPeer == HT_IOT_PEER_BROADCOM) + { + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + RTL_W8(0x51a, 0x0f); + } + } +#endif + + + return SUCCESS; + +assoc_rejected: + +#ifndef WIFI_WPAS_CLI + JOIN_RES_VAL(STATE_Sta_No_Bss); + JOIN_REQ_ONGOING_VAL(0); + + if (PENDING_REASSOC_TIMER) + DELETE_REASSOC_TIMER; + + STADEBUG("assoc_rejected ; start_clnt_lookup(DONTRESCAN)\n"); + start_clnt_lookup(priv, DONTRESCAN); + +#ifdef UNIVERSAL_REPEATER + disable_vxd_ap(GET_VXD_PRIV(priv)); +#endif +#endif // !WIFI_WPAS_CLI + + return FAIL; +} + + +/** + * @brief STA in Infra-structure mode Beacon process. + */ +static unsigned int OnBeaconClnt_Bss(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *bssid; + struct stat_info *pstat; + unsigned char *p, *pframe; + int len; + unsigned short val16; +#ifdef WIFI_11N_2040_COEXIST + unsigned int channel=0; +#endif +#ifdef WIFI_WMM + unsigned int i, vo_txop=0, vi_txop=0, be_txop=0, bk_txop=0; +#ifndef SMP_SYNC + unsigned long flags; +#endif +#endif +#ifdef P2P_SUPPORT + unsigned char *ptr; + static unsigned char ReAssem_p2pie[MAX_REASSEM_P2P_IE]; + int IEfoundtimes=0; + unsigned char *p2pIEPtr = ReAssem_p2pie ; + int p2pIElen=0; +#endif +#ifdef MULTI_MAC_CLONE + int firstSta=0; +#endif + int htcap_chwd_cur = 0; + + pframe = get_pframe(pfrinfo); + bssid = GetAddr3Ptr(pframe); + + memcpy(&val16, (pframe + WLAN_HDR_A3_LEN + 8 + 2), 2); + val16 = le16_to_cpu(val16); + if (!(val16 & BIT(0)) || (val16 & BIT(1))) + return SUCCESS; + +#ifdef WIFI_11N_2040_COEXIST + if ((!IS_BSSID(priv, bssid)) && + priv->pmib->dot11nConfigEntry.dot11nCoexist && + priv->coexist_connection && + (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G))) { + /* + * check if there is any bg AP around + */ + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, + &len, pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p == NULL) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) + channel = *(p+2); + if (channel && (channel <= 14)) { +#if 0 +//#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if(!priv->bg_ap_timeout) { + priv->bg_ap_timeout = 180; + priv->bg_ap_timeout_ch[channel-1] = 180; + update_RAMask_to_FW(priv, 1); + } +#endif + priv->bg_ap_timeout = 180; + priv->bg_ap_timeout_ch[channel-1] = 180; + channel = 0; + } + } else { + /* + * check if there is any 40M intolerant field set by other 11n AP + */ + struct ht_cap_elmt *ht_cap=(struct ht_cap_elmt *)(p+2); + if (cpu_to_le16(ht_cap->ht_cap_info) & _HTCAP_40M_INTOLERANT_) + priv->intolerant_timeout = 180; + } + } +#endif + + if (!IS_BSSID(priv, bssid)) + return SUCCESS; + + // this is our AP + pstat = get_stainfo(priv, bssid); + if (pstat == NULL) { + DEBUG_ERR("Can't find our AP\n"); + return FAIL; + } + +#ifdef RTK_5G_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + priv->rxBeaconNumInPeriod++; + } else +#endif + { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + if (priv->pmib->dot11Bss.channel == *(p+2)) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _SSID_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (!(p && (len > 0) && *(p+2) && + memcmp(priv->pmib->dot11Bss.ssid, p+2, priv->pmib->dot11Bss.ssidlen))) + priv->rxBeaconNumInPeriod++; + } + } + } + + if (priv->ps_state) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _TIM_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + if (isOurFrameBuffred(p, _AID) == TRUE) { +#if defined(WIFI_WMM) && defined(WMM_APSD) + if (QOS_ENABLE && APSD_ENABLE && priv->uapsd_assoc) { + if (!(priv->pmib->dot11QosEntry.UAPSD_AC_BE && + priv->pmib->dot11QosEntry.UAPSD_AC_BK && + priv->pmib->dot11QosEntry.UAPSD_AC_VI && + priv->pmib->dot11QosEntry.UAPSD_AC_VO)) + issue_PsPoll(priv); + } else +#endif + { + issue_PsPoll(priv); + } + } + +#ifdef MULTI_MAC_CLONE + { + int k; + if (MCLONE_NUM > 0) { + for (k=0; kuapsd_assoc) { + if (!(priv->pmib->dot11QosEntry.UAPSD_AC_BE && + priv->pmib->dot11QosEntry.UAPSD_AC_BK && + priv->pmib->dot11QosEntry.UAPSD_AC_VI && + priv->pmib->dot11QosEntry.UAPSD_AC_VO)) + issue_PsPoll(priv); + } else +#endif + issue_PsPoll(priv); + + } + ACTIVE_ID = 0; + } + } +#endif + } + } + + if (val16 & BIT(5)) + pstat->useShortPreamble = 1; + else + pstat->useShortPreamble = 0; + + if ((priv->pshare->curr_band == BAND_2G) && (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) + { + if (val16 & BIT(10)) { + if (priv->pmib->dot11ErpInfo.shortSlot == 0) { + priv->pmib->dot11ErpInfo.shortSlot = 1; + set_slot_time(priv, priv->pmib->dot11ErpInfo.shortSlot); + } + } + else { + if (priv->pmib->dot11ErpInfo.shortSlot == 1) { + priv->pmib->dot11ErpInfo.shortSlot = 0; + set_slot_time(priv, priv->pmib->dot11ErpInfo.shortSlot); + } + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if (p && (*(p+2) & BIT(1))) // use Protection + priv->pmib->dot11ErpInfo.protection = 1; + else + priv->pmib->dot11ErpInfo.protection = 0; + + if (p && (*(p+2) & BIT(2))) // use long preamble + priv->pmib->dot11ErpInfo.longPreambleStaNum = 1; + else + priv->pmib->dot11ErpInfo.longPreambleStaNum = 0; + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + struct ht_cap_elmt *ht_cap = (struct ht_cap_elmt *)(p+2); + if (OPMODE & WIFI_ASOC_STATE) { + if ((ht_cap->ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))) + htcap_chwd_cur = 1; + } + } + /* + * Update HT Operation IE of AP for protection and coexist infomation + */ +#if 0 //def MULTI_MAC_CLONE + if ((priv==priv->pshare->root_repeater) + || ((priv->pshare->root_repeater!=NULL) && !(priv->pshare->root_repeater->pmib->dot11OperationEntry.opmode&WIFI_ASOC_STATE))) +#endif + { + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + int htcap_chwd_offset = 0; + if (OPMODE & WIFI_ASOC_STATE) { + if ((p[3]& _HTIE_2NDCH_OFFSET_BL_) == _HTIE_2NDCH_OFFSET_BL_) + htcap_chwd_offset = HT_2NDCH_OFFSET_BELOW; + else if ((p[3] & _HTIE_2NDCH_OFFSET_BL_) == _HTIE_2NDCH_OFFSET_AB_) + htcap_chwd_offset = HT_2NDCH_OFFSET_ABOVE; + else + htcap_chwd_offset = 0; + if(htcap_chwd_cur ==0) + htcap_chwd_offset = 0; + + if (priv->pmib->dot11nConfigEntry.dot11n2ndChOffset != htcap_chwd_offset) { + STADEBUG("my dot11n2ndChOffset[%d],AP's offset= [%d]\n\n",priv->pmib->dot11nConfigEntry.dot11n2ndChOffset, htcap_chwd_offset); + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = htcap_chwd_offset; + #if 0 //def UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + OPMODE_VAL(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE); + JOIN_RES_VAL(STATE_Sta_No_Bss); + DEBUG_INFO("%s: AP has changed 2nd ch offset, reconnect...\n", __FUNCTION__); + return SUCCESS; + } + else + #endif + #if 0//defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) + #endif + { //either root or non-root goto reconn + DEBUG_INFO("%s: AP has changed 2nd ch offset, reconnect...\n", __FUNCTION__); +// goto ReConn; + priv->pmib->dot11Bss.t_stamp[1] &= ~(BIT(1) | BIT(2)); + if(htcap_chwd_offset == HT_2NDCH_OFFSET_BELOW) + priv->pmib->dot11Bss.t_stamp[1] |= (BIT(1) | BIT(2)); + else if(htcap_chwd_offset == HT_2NDCH_OFFSET_ABOVE) + priv->pmib->dot11Bss.t_stamp[1] |= (BIT(1)); + clnt_switch_chan_to_bss(priv); +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + } + } + } + + pstat->ht_ie_len = len; + memcpy((unsigned char *)&pstat->ht_ie_buf, p+2, len); + + priv->ht_protection = 0; + if (!priv->pmib->dot11StationConfigEntry.protectionDisabled && pstat->ht_ie_len) { + unsigned int prot_mode = (cpu_to_le16(pstat->ht_ie_buf.info1) & 0x03); + if (prot_mode == _HTIE_OP_MODE1_ || prot_mode == _HTIE_OP_MODE3_) + priv->ht_protection = 1; + } + } +#if 0 + + //if ((priv->beacon_period > 200) || ((priv->rxBeaconNumInPeriod % 3) == 0)) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + struct ht_cap_elmt *ht_cap = (struct ht_cap_elmt *)(p+2); + int htcap_chwd_cur = 0; + + if (OPMODE & WIFI_ASOC_STATE) { + if ((ht_cap->ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))) + htcap_chwd_cur = 1; + + if (priv->pshare->AP_BW < 0) + priv->pshare->AP_BW = htcap_chwd_cur; + else { + if (priv->pshare->AP_BW != htcap_chwd_cur) { + DEBUG_INFO("%s: AP has changed BW, reconnect...\n", __FUNCTION__); + goto ReConn; + } + } + } + } else { + DEBUG_INFO("%s: AP HT capability missing, reconnect...\n", __FUNCTION__); + goto ReConn; + } + //} +#endif + } + + } + + + /* + * Update TXOP from Beacon every 3 seconds + */ +#ifdef WIFI_WMM + if (QOS_ENABLE && pstat->QosEnabled && !(priv->up_time % 3) && +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + IS_ROOT_INTERFACE(priv) && +#endif + priv->pmib->dot11OperationEntry.wifi_specific) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _RSN_IE_1_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + + if (p != NULL) { + if (!memcmp(p+2, WMM_PARA_IE, 6)) { + /* save previous edca value */ + vo_txop = (unsigned short)(GET_STA_AC_VO_PARA.TXOPlimit); + vi_txop = (unsigned short)(GET_STA_AC_VI_PARA.TXOPlimit); + be_txop = (unsigned short)(GET_STA_AC_BE_PARA.TXOPlimit); + bk_txop = (unsigned short)(GET_STA_AC_BK_PARA.TXOPlimit); + + /* capture the EDCA para */ + p += 10; /* start of EDCA parameters at here*/ + for (i = 0; i <4; i++) { + process_WMM_para_ie(priv, p); /* get the info */ + p += 4; + } + + /* check whether if TXOP is different from previous settings */ + if ((vo_txop != (unsigned short)(GET_STA_AC_VO_PARA.TXOPlimit)) || + (vi_txop != (unsigned short)(GET_STA_AC_VI_PARA.TXOPlimit)) || + (be_txop != (unsigned short)(GET_STA_AC_BE_PARA.TXOPlimit)) || + (bk_txop != (unsigned short)(GET_STA_AC_BK_PARA.TXOPlimit))) { + SAVE_INT_AND_CLI(flags); + sta_config_EDCA_para(priv); + RESTORE_INT(flags); + DEBUG_INFO("Client mode EDCA updated from beacon\n"); + DEBUG_INFO("BE: ACM %d, AIFSN %d, ECWmin %d, ECWmax %d, TXOP %d\n", + GET_STA_AC_BE_PARA.ACM, GET_STA_AC_BE_PARA.AIFSN, + GET_STA_AC_BE_PARA.ECWmin, GET_STA_AC_BE_PARA.ECWmax, + GET_STA_AC_BE_PARA.TXOPlimit); + DEBUG_INFO("VO: ACM %d, AIFSN %d, ECWmin %d, ECWmax %d, TXOP %d\n", + GET_STA_AC_VO_PARA.ACM, GET_STA_AC_VO_PARA.AIFSN, + GET_STA_AC_VO_PARA.ECWmin, GET_STA_AC_VO_PARA.ECWmax, + GET_STA_AC_VO_PARA.TXOPlimit); + DEBUG_INFO("VI: ACM %d, AIFSN %d, ECWmin %d, ECWmax %d, TXOP %d\n", + GET_STA_AC_VI_PARA.ACM, GET_STA_AC_VI_PARA.AIFSN, + GET_STA_AC_VI_PARA.ECWmin, GET_STA_AC_VI_PARA.ECWmax, + GET_STA_AC_VI_PARA.TXOPlimit); + DEBUG_INFO("BK: ACM %d, AIFSN %d, ECWmin %d, ECWmax %d, TXOP %d\n", + GET_STA_AC_BK_PARA.ACM, GET_STA_AC_BK_PARA.AIFSN, + GET_STA_AC_BK_PARA.ECWmin, GET_STA_AC_BK_PARA.ECWmax, + GET_STA_AC_BK_PARA.TXOPlimit); + } + } + } + } +#endif + + // Realtek proprietary IE + pstat->is_realtek_sta = FALSE; + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; len = 0; + for (;;) + { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, Realtek_OUI, 3) && *(p+2+3) == 2) { /*found realtek out and type == 2*/ + pstat->is_realtek_sta = TRUE; + break; + } + } + else + break; + + p = p + len + 2; + } + + // Customer proprietary IE + if (priv->pmib->miscEntry.private_ie_len) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, priv->pmib->miscEntry.private_ie[0], &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p) { + memcpy(pstat->private_ie, p, len + 2); + pstat->private_ie_len = len + 2; + } + } + +#ifdef DFS + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _CSA_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p!=NULL){ + DEBUG_INFO("Associated AP notified to do DFS\n"); + if(IS_ROOT_INTERFACE(priv)) { + // channel switch mode + priv->pshare->dfsSwitchChannel = (unsigned int)*(p+3); + priv->pshare->dfsSwitchChCountDown =(unsigned int)*(p+4); + DEBUG_INFO("CSA Detected mode=%d, channel=%d, countdown=%d\n",*(p+2), priv->pshare->dfsSwitchChannel, priv->pshare->dfsSwitchChCountDown); + if (priv->pshare->dfsSwitchChCountDown <= 5) { + if (timer_pending(&priv->dfs_cntdwn_timer)) + del_timer(&priv->dfs_cntdwn_timer); + + DFS_SwChnl_clnt(priv); + priv->pshare->dfsSwCh_ongoing = 1; + mod_timer(&priv->dfs_cntdwn_timer, jiffies + RTL_SECONDS_TO_JIFFIES(2)); + } + } else { + if(!GET_ROOT(priv)->pmib->dot11DFSEntry.DFS_detected) { + GET_ROOT(priv)->pshare->dfsSwitchChannel = (unsigned int)*(p+3); + GET_ROOT(priv)->pshare->dfsSwitchChCountDown =(unsigned int)*(p+4); + GET_ROOT(priv)->pmib->dot11DFSEntry.DFS_detected = 1; + DEBUG_INFO("Asscociated AP detected CSA , channel=%d, countdown=%d\n", GET_ROOT(priv)->pshare->dfsSwitchChannel, GET_ROOT(priv)->pshare->dfsSwitchChCountDown); + } + } +} +#endif + +#ifdef P2P_SUPPORT + if ((OPMODE&WIFI_P2P_SUPPORT) && (P2PMODE == P2P_CLIENT)) { + /*just take care beacon come from my BSSID*/ + if(!memcmp(BSSID,pfrinfo->sa,6)){ + ptr = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; + len = 0; + + /*support ReAssemble*/ + for (;;) + { + /* get P2P_IE */ + ptr = get_ie(ptr, _P2P_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_ - len); + + if (ptr) { + if (!memcmp(ptr+2, WFA_OUI_PLUS_TYPE, 4)) { + + memcpy(p2pIEPtr , ptr+6 ,len - 4); + p2pIEPtr += (len - 4); + IEfoundtimes ++; + + } + } + else{ + break; + } + + ptr = ptr + len + 2; + } + + if(IEfoundtimes){ + + //if(IEfoundtimes>1) + // P2P_DEBUG("ReAssembly p2p IE\n"); + + p2pIElen = (int)(((unsigned long)p2pIEPtr)-((unsigned long)ReAssem_p2pie)); + + if(p2pIElen > MAX_REASSEM_P2P_IE){ + P2P_DEBUG("\n\n reassemble P2P IE exceed MAX_REASSEM_P2P_IE , chk!!!\n\n"); + }else{ + P2P_client_on_beacon(priv, ReAssem_p2pie , p2pIElen , GetSequence(pframe)); + } + } + + } + } +#endif + + return SUCCESS; + +#if 0 +ReConn: + + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)); +#ifdef CONFIG_RTL_WLAN_STATUS + priv->wlan_status_flag=1; +#endif +#ifdef UNIVERSAL_REPEATER + disable_vxd_ap(GET_VXD_PRIV(priv)); +#endif + JOIN_RES_VAL(STATE_Sta_No_Bss); + STADEBUG("start_clnt_lookup(RESCAN_ROAMING)\n"); + start_clnt_lookup(priv, RESCAN_ROAMING); + return SUCCESS; +#endif +} + + +/** + * @brief STA in ad hoc mode Beacon process. + */ +static unsigned int OnBeaconClnt_Ibss(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned char *bssid, *bdsa; + struct stat_info *pstat; + unsigned char *p, *pframe, channel; + int len; + unsigned char supportRate[32]; + int supportRateNum; + unsigned short val16; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + pframe = get_pframe(pfrinfo); + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if(p == NULL) + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) + channel = *(p+2); + else + channel = priv->pmib->dot11RFEntry.dot11channel; + + /* + * check if OLBC exist + */ + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + (channel == priv->pmib->dot11RFEntry.dot11channel)) + { + // look for ERP rate. if no ERP rate existed, thought it is a legacy AP + unsigned char supportedRates[32]; + int supplen=0, legacy=1, i; + + pframe = get_pframe(pfrinfo); + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p) { + if (len>8) + len=8; + memcpy(&supportedRates[supplen], p+2, len); + supplen += len; + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p) { + if (len>8) + len=8; + memcpy(&supportedRates[supplen], p+2, len); + supplen += len; + } + + for (i=0; ipktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p && (*(p+2) & BIT(0))) + legacy = 1; + } + + if (legacy) { + if (!priv->pmib->dot11StationConfigEntry.olbcDetectDisabled && + priv->pmib->dot11ErpInfo.olbcDetected==0) { + priv->pmib->dot11ErpInfo.olbcDetected = 1; + check_protection_shortslot(priv); + DEBUG_INFO("OLBC detected\n"); + } + if (priv->pmib->dot11ErpInfo.olbcDetected) + priv->pmib->dot11ErpInfo.olbcExpired = DEFAULT_OLBC_EXPIRE; + } + } + + +// mantis#2523 + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _SSID_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if ( p && (SSID_LEN == len) && !memcmp(SSID, p+2, len)) { + memcpy(priv->rx_timestamp, pframe+WLAN_HDR_A3_LEN, 8); + } + + /* + * add into sta table and calculate beacon + */ + bssid = GetAddr3Ptr(pframe); + bdsa = GetAddr2Ptr(pframe); + + if (!IS_BSSID(priv, bssid)) + return SUCCESS; + + memcpy(&val16, (pframe + WLAN_HDR_A3_LEN + 8 + 2), 2); + val16 = le16_to_cpu(val16); + if ((val16 & BIT(0)) || !(val16 & BIT(1))) + return SUCCESS; + + // this is our peers + pstat = get_stainfo(priv, bdsa); + + if (pstat == NULL) { + DEBUG_INFO("Add IBSS sta, %02x:%02x:%02x:%02x:%02x:%02x!\n", + bdsa[0],bdsa[1], bdsa[2],bdsa[3],bdsa[4],bdsa[5]); + + pstat = alloc_stainfo(priv, bdsa, -1); + if (pstat == NULL) + return SUCCESS; + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p == NULL) { + free_stainfo(priv, pstat); + return SUCCESS; + } + memcpy(supportRate, p+2, len); + supportRateNum = len; + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + memcpy(supportRate+supportRateNum, p+2, len); + supportRateNum += len; + } + +#ifdef WIFI_WMM + // check if there is WMM IE + if (QOS_ENABLE) { + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; len = 0; + for (;;) { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + if (p != NULL) { + if (!memcmp(p+2, WMM_IE, 6)) { + pstat->QosEnabled = 1; +#ifdef WMM_APSD + if (APSD_ENABLE) + pstat->apsd_bitmap = *(p+8) & 0x0f; // get QSTA APSD bitmap +#endif + break; + } + } + else { + pstat->QosEnabled = 0; +#ifdef WMM_APSD + pstat->apsd_bitmap = 0; +#endif + break; + } + p = p + len + 2; + } + } + else { + pstat->QosEnabled = 0; +#ifdef WMM_APSD + pstat->apsd_bitmap = 0; +#endif + } +#endif + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_CAP_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + unsigned char mimo_ps; + pstat->ht_cap_len = len; + memcpy((unsigned char *)&pstat->ht_cap_buf, p+2, len); + // below is the process to check HT MIMO power save + mimo_ps = ((cpu_to_le16(pstat->ht_cap_buf.ht_cap_info)) >> 2)&0x0003; + pstat->MIMO_ps = 0; + if (!mimo_ps) + pstat->MIMO_ps |= _HT_MIMO_PS_STATIC_; + else if (mimo_ps == 1) + pstat->MIMO_ps |= _HT_MIMO_PS_DYNAMIC_; + + check_NAV_prot_len(priv, pstat, 0); + + if (cpu_to_le16(pstat->ht_cap_buf.ht_cap_info) & _HTCAP_AMSDU_LEN_8K_) { + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 7935 - sizeof(struct wlan_hdr); + } else { + pstat->is_8k_amsdu = 0; + pstat->amsdu_level = 3839 - sizeof(struct wlan_hdr); + } + + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)) + pstat->tx_bw = HT_CHANNEL_WIDTH_20_40; + else + pstat->tx_bw = HT_CHANNEL_WIDTH_20; + } + else { + pstat->ht_cap_len = 0; + memset((unsigned char *)&pstat->ht_cap_buf, 0, sizeof(struct ht_cap_elmt)); + } + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + pstat->ht_ie_len = len; + memcpy((unsigned char *)&pstat->ht_ie_buf, p+2, len); + } + else + pstat->ht_ie_len = 0; + } +#ifdef RTK_AC_SUPPORT //ADHOC-VHT support + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) + { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTCapability, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if ((p != NULL) && (len <= sizeof(struct vht_cap_elmt))) { + pstat->vht_cap_len = len; + memcpy((unsigned char *)&pstat->vht_cap_buf, p+2, len); + } + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTOperation, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if ((p != NULL) && (len <= sizeof(struct vht_oper_elmt))) { + pstat->vht_oper_len = len; + memcpy((unsigned char *)&pstat->vht_oper_buf, p+2, len); + } + if(pstat->vht_cap_len){ + switch(cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & 0x3) { + default: + case 0: + pstat->is_8k_amsdu = 0; + pstat->amsdu_level = 3895 - sizeof(struct wlan_hdr); + break; + case 1: + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 7991 - sizeof(struct wlan_hdr); + break; + case 2: + pstat->is_8k_amsdu = 1; + pstat->amsdu_level = 11454 - sizeof(struct wlan_hdr); + break; + } + if ((priv->vht_oper_buf.vht_oper_info[0] == 1) && (pstat->vht_oper_buf.vht_oper_info[0] == 1)) { + pstat->tx_bw = HT_CHANNEL_WIDTH_80; + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_80; + } + } + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, EID_VHTOperatingMode, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if ((p != NULL) && (len == 1)) { + if((p[2] &3) <= priv->pmib->dot11nConfigEntry.dot11nUse40M) + pstat->tx_bw = p[2] &3; + pstat->nss = ((p[2]>>4)&0x7)+1; + } +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + UpdateHalMSRRPT8812(priv, pstat, INCREASE); + } +#endif + } +#endif + + // Realtek proprietary IE + pstat->is_realtek_sta = FALSE; + p = pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_; len = 0; + for (;;) + { + p = get_ie(p, _RSN_IE_1_, &len, + pfrinfo->pktlen - (p - pframe)); + +#ifdef WIFI_WPAS + if (p != NULL) { + if((*(unsigned char *)p == _RSN_IE_1_)&& (len >= 4)) + { + WPAS_ASSOCIATION_INFO Assoc_Info; + + memset((void *)&Assoc_Info, 0, sizeof(struct _WPAS_ASSOCIATION_INFO)); + Assoc_Info.ReqIELen = p[1]+ 2; + memcpy(Assoc_Info.ReqIE, p, Assoc_Info.ReqIELen); + event_indicate_wpas(priv, NULL, WPAS_ASSOC_INFO, (UINT8 *)&Assoc_Info); + } + } +#endif + + if (p != NULL) { + if (!memcmp(p+2, Realtek_OUI, 3) && *(p+2+3) == 2) { /*found realtek out and type == 2*/ + pstat->is_realtek_sta = TRUE; + break; + } + } + else + break; + + p = p + len + 2; + } + + if ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) ) { + DOT11_SET_KEY Set_Key; + memcpy(Set_Key.MACAddr, pstat->hwaddr, 6); + Set_Key.KeyType = DOT11_KeyType_Pairwise; + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) { + Set_Key.EncType = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + Set_Key.KeyIndex = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + DOT11_Process_Set_Key(priv->dev, NULL, &Set_Key, + priv->pmib->dot11DefaultKeysTable.keytype[Set_Key.KeyIndex].skey); + } + else { + Set_Key.EncType = (unsigned char)priv->pmib->dot11GroupKeysTable.dot11Privacy; + Set_Key.KeyIndex = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + DOT11_Process_Set_Key(priv->dev, NULL, &Set_Key, + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKey1.skey); + } + } + + get_matched_rate(priv, supportRate, &supportRateNum, 0); + update_support_rate(pstat, supportRate, supportRateNum); + + assign_tx_rate(priv, pstat, pfrinfo); + assign_aggre_mthod(priv, pstat); + assign_aggre_size(priv, pstat); + + val16 = cpu_to_le16(*(unsigned short*)((unsigned long)pframe + WLAN_HDR_A3_LEN + 8 + 2)); + if (!(val16 & BIT(5))) // NOT use short preamble + pstat->useShortPreamble = 0; + else + pstat->useShortPreamble = 1; + + pstat->state |= (WIFI_ASOC_STATE | WIFI_AUTH_SUCCESS); + + SAVE_INT_AND_CLI(flags); + pstat->expire_to = priv->expire_to; + asoc_list_add(priv, pstat); + cnt_assoc_num(priv, pstat, INCREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, INCREASE); + RESTORE_INT(flags); + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) //wrt-adhoc + event_indicate_cfg80211(priv, NULL, CFG80211_IBSS_JOINED, NULL); +#endif + + LOG_MSG("An IBSS client is detected - %02X:%02X:%02X:%02X:%02X:%02X\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + UpdateHalRAMask8812(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } + } + + if (timer_pending(&priv->idle_timer)) + del_timer(&priv->idle_timer); + + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if(p == NULL) + p = get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _HT_IE_, &len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_); + if (p != NULL) { + if (priv->pmib->dot11Bss.channel == *(p+2)) { + pstat->beacon_num++; + priv->rxBeaconNumInPeriod++; + JOIN_RES_VAL(STATE_Sta_Ibss_Active); + } + } + return SUCCESS; +} + + +/** + * @brief STA recived Beacon process + */ +static unsigned int OnBeaconClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + int ret = SUCCESS; + + // Site survey and collect information + if (OPMODE & WIFI_SITE_MONITOR) { + +#ifdef P2P_SUPPORT + if( (OPMODE&WIFI_P2P_SUPPORT) && (P2PMODE == P2P_DEVICE) ){ + p2p_collect_bss_info(priv, pfrinfo); // 20130913 p2pcheck ? + } + else +#endif + { + collect_bss_info(priv, pfrinfo); + } + return SUCCESS; + } + + // Infra client mode, check beacon info + if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == + (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + ret = OnBeaconClnt_Bss(priv, pfrinfo); +#if defined(WIFI_WMM) && defined(WMM_APSD) && !defined(WIFI_WPAS_CLI) + else if (QOS_ENABLE && APSD_ENABLE && (OPMODE & WIFI_STATION_STATE) && !(OPMODE & WIFI_ASOC_STATE)) + collect_bss_info(priv, pfrinfo); +#endif + + // Ad-hoc client mode, check peer's beacon + if ((OPMODE & WIFI_ADHOC_STATE) && + ((JOIN_RES == STATE_Sta_Ibss_Active) || (JOIN_RES == STATE_Sta_Ibss_Idle))) + ret = OnBeaconClnt_Ibss(priv, pfrinfo); + + return ret; +} + + +/** + * @brief STA recived ATIM + * + * STA only. + */ +static unsigned int OnATIM(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + return SUCCESS; +} + + +static unsigned int OnDisassocClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned long link_time=0; + struct stat_info *pstat=NULL; + unsigned char *pframe = get_pframe(pfrinfo); + unsigned char *bssid = GetAddr3Ptr(pframe); + unsigned short val16; +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + int if_idx = -1; +#endif + if (!(OPMODE & WIFI_STATION_STATE)) + return SUCCESS; + + if (memcmp(GET_MY_HWADDR, pfrinfo->da, MACADDRLEN) +#ifdef CONFIG_IEEE80211W_CLI + && !IS_BCAST2(pfrinfo->da) //BIP da: 0xFFFFFFFFFFFF +#endif + ) + return SUCCESS; + + if (!memcmp(BSSID, bssid, MACADDRLEN)) { + memcpy(&val16, (pframe + WLAN_HDR_A3_LEN), 2); + val16 = le16_to_cpu(val16); + DEBUG_INFO("recv Disassociation, reason: %d\n", val16); + if(ACTIVE_ID == 0) { + if(val16 == _RSON_MIC_FAILURE_ || val16 == _RSON_4WAY_HNDSHK_TIMEOUT_) + priv->dot114WayStatus = val16; + } +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + pstat = get_stainfo(priv, pfrinfo->da); + + if (pstat && pstat->sta_in_firmware == 1) { + RTL8188E_MACID_NOLINK(priv, 1, REMAP_AID(pstat)); + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + } + } +#endif + + pstat = get_stainfo(priv, bssid); + if (pstat == NULL) { + link_time = 0; + }else{ + link_time = pstat->link_time; + } + + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)); + JOIN_RES_VAL(STATE_Sta_No_Bss); + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + event_indicate_cfg80211(priv, NULL, CFG80211_DISCONNECTED, NULL); +#elif defined(WIFI_WPAS_CLI) + event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL); +#else // !WIFI_WPAS_CLI +#ifdef SMART_REPEATER_MODE + if(GET_MIB(priv)->ap_profile.enable_profile && GET_MIB(priv)->ap_profile.profile_num > 0) + { + if((priv->site_survey->count_target > 0) && ((priv->join_index+1) > priv->site_survey->count_target)){ + STADEBUG("start_clnt_lookup(RESCAN)\n"); + start_clnt_lookup(priv, RESCAN); + }else{ + STADEBUG("start_clnt_lookup(DONTRESCAN)\n"); + start_clnt_lookup(priv, DONTRESCAN); + } + }else +#endif +#if !defined(RTK_NL80211) + if (link_time > priv->expire_to) { // if link time exceeds timeout, site survey again + STADEBUG("start_clnt_lookup(RESCAN)\n"); + start_clnt_lookup(priv, RESCAN); + } else{ + STADEBUG("start_clnt_lookup(DONTRESCAN)\n"); + start_clnt_lookup(priv, DONTRESCAN); + } +#endif +#endif // WIFI_WPAS_CLI +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Disassociated by AP;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + if((if_idx = get_wlan_if_type(priv))>=0){ + set_if_status(if_idx,IF_DOWN); + set_if_change_status(if_idx,IF_STATUS_CHANGE); + } +#endif +#else + LOG_MSG("Disassociated by AP - %02X:%02X:%02X:%02X:%02X:%02X\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + if((if_idx = get_wlan_if_type(priv))>=0){ + set_if_status(if_idx,IF_DOWN); + set_if_change_status(if_idx,IF_STATUS_CHANGE); + } +#endif +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->link_status_cb_func) + priv->link_status_cb_func("wlan0", WIFI_LINK_STATUS_DISASSOCIATED); +#endif +#endif + +#ifdef UNIVERSAL_REPEATER + disable_vxd_ap(GET_VXD_PRIV(priv)); +#endif +#ifdef CONFIG_RTL_WLAN_STATUS + priv->wlan_status_flag=1; +#endif + } + + return SUCCESS; +} + + +/** + * @brief STA recived authentication + * AP and STA authentication each other. + */ +static unsigned int OnAuthClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + unsigned int privacy, seq, len, status, algthm, offset, go2asoc=0; +#ifndef SMP_SYNC + unsigned long flags; +#endif + struct wifi_mib *pmib; + unsigned char *pframe, *p; + + if (!(OPMODE & WIFI_STATION_STATE)) + return SUCCESS; + + if (memcmp(GET_MY_HWADDR, pfrinfo->da, MACADDRLEN)) + return SUCCESS; + + if (OPMODE & WIFI_SITE_MONITOR) + return SUCCESS; + +#if defined(CLIENT_MODE) && (defined(INCLUDE_WPA_PSK) || defined(RTK_NL80211)) + if (priv->assoc_reject_on && !memcmp(priv->assoc_reject_mac, pfrinfo->sa, MACADDRLEN)) + return SUCCESS; +#endif + + DEBUG_INFO("got auth response\n"); + pmib = GET_MIB(priv); + pframe = get_pframe(pfrinfo); + + privacy = priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm; + + if (GetPrivacy(pframe)) + offset = 4; + else + offset = 0; + + algthm = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + offset)); + seq = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + offset + 2)); + status = cpu_to_le16(*(unsigned short *)((unsigned long)pframe + WLAN_HDR_A3_LEN + offset + 4)); + + if (status != 0) + { + DEBUG_ERR("clnt auth fail, status: %d\n", status); + goto authclnt_err_end; + } + + if (seq == 2) + { +#ifdef WIFI_SIMPLE_CONFIG + if (pmib->wscEntry.wsc_enable && algthm == 0) + privacy = 0; +#endif + + if ((privacy == 1) || // legacy shared system + ((privacy == 2) && (AUTH_MODE_TOGGLE) && // auto and use shared-key currently + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_))) + { + p = get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len, + pfrinfo->pktlen - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); + + if (p == NULL) { + DEBUG_ERR("no challenge text?\n"); + goto authclnt_fail; + } + + DEBUG_INFO("auth chlgetxt len =%d\n", len); + memcpy((void *)CHG_TXT, (void *)(p+2), len); + SAVE_INT_AND_CLI(flags); + AUTH_SEQ_VAL(3); + OPMODE_VAL(OPMODE & (~ WIFI_AUTH_NULL)); + OPMODE_VAL(OPMODE | (WIFI_AUTH_STATE1)); + RESTORE_INT(flags); + issue_auth(priv, NULL, 0); + return SUCCESS; + } + else // open system + go2asoc = 1; + } + else if (seq == 4) + { + if (privacy) + go2asoc = 1; + else + { + // this is illegal + DEBUG_ERR("no privacy but auth seq=4?\n"); + goto authclnt_fail; + } + } + else + { + // this is also illegal + DEBUG_ERR("clnt auth failed due to illegal seq=%x\n", seq); + goto authclnt_fail; + } + + if (go2asoc) + { + DEBUG_INFO("auth successful!\n"); + start_clnt_assoc(priv); + return SUCCESS; + } + +authclnt_fail: + + REAUTH_COUNT_VAL(REAUTH_COUNT+1); + if (REAUTH_COUNT < REAUTH_LIMIT) + return FAIL; + +authclnt_err_end: + + if ((priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm == 2) && + ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_)) && + (AUTH_MODE_RETRY == 0)) { + // auto-auth mode, retry another auth method + AUTH_MODE_RETRY_VAL(AUTH_MODE_RETRY+1); + + start_clnt_auth(priv); + return SUCCESS; + } + else { +#ifndef WIFI_WPAS_CLI + JOIN_RES_VAL(STATE_Sta_No_Bss); + JOIN_REQ_ONGOING_VAL(0); + + if (PENDING_REAUTH_TIMER) + DELETE_REAUTH_TIMER; + + start_clnt_lookup(priv, DONTRESCAN); +#endif // !WIFI_WPAS_CLI + return FAIL; + } +} + + +/** + * @brief Client/STA De authentication + * First DeAuthClnt, Second OnDeAuthClnt + */ +static unsigned int OnDeAuthClnt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned long link_time; + unsigned char *pframe = get_pframe(pfrinfo); + unsigned char *bssid = GetAddr3Ptr(pframe); + struct stat_info *pstat; + unsigned short val16; +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + int if_idx = -1; +#endif + +#ifdef CONFIG_IEEE80211W_CLI + unsigned int status = _STATS_SUCCESSFUL_; + unsigned short frame_type; +#endif + + if (!(OPMODE & WIFI_STATION_STATE)) + return SUCCESS; + + + if (memcmp(GET_MY_HWADDR, pfrinfo->da, MACADDRLEN) +#ifdef CONFIG_IEEE80211W_CLI + && !IS_BCAST2(pfrinfo->da) //BIP da: 0xFFFFFFFFFFFF +#endif + ) + return SUCCESS; + + if (memcmp(GetAddr2Ptr(pframe), bssid, MACADDRLEN)) + return SUCCESS; + + if (!memcmp(priv->pmib->dot11Bss.bssid, bssid, MACADDRLEN)) { + memcpy(&val16, (pframe + WLAN_HDR_A3_LEN), 2); + DEBUG_INFO("recv Deauthentication, reason: %d\n", le16_to_cpu(val16)); + + pstat = get_stainfo(priv, bssid); + if (pstat == NULL) { // how come? +// Start scan again ---------------------- +// return FAIL; + link_time = 0; // get next bss info + goto do_scan; +//--------------------- david+2007-03-10 + } + +#ifdef MULTI_MAC_CLONE + if (ACTIVE_ID == 0) +#endif + { + link_time = pstat->link_time; + + SAVE_INT_AND_CLI(flags); + if (asoc_list_del(priv, pstat)) { + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E && pstat->sta_in_firmware == 1) { + RTL8188E_MACID_NOLINK(priv, 1, REMAP_AID(pstat)); + RTL8188E_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + } +#endif + } + RESTORE_INT(flags); + + free_stainfo(priv, pstat); + } +do_scan: + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)); + JOIN_RES_VAL(STATE_Sta_No_Bss); + +// Delete timer -------------------------------------- + if (PENDING_REAUTH_TIMER) + DELETE_REAUTH_TIMER; + + if (PENDING_REASSOC_TIMER) + DELETE_REASSOC_TIMER; +//---------------------------------- david+2007-03-10 + +#if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) + event_indicate_cfg80211(priv, NULL, CFG80211_DISCONNECTED, NULL); +#elif defined(WIFI_WPAS_CLI) + event_indicate_wpas(priv, NULL, WPAS_DISCON, NULL); +#else // !WIFI_WPAS_CLI +#ifdef MULTI_MAC_CLONE + if (ACTIVE_ID > 0 && priv->pshare->mclone_sta[ACTIVE_ID-1].usedStaAddrId == 0xff) { + // don't reconnect + } + else +#endif +#ifdef SMART_REPEATER_MODE + if(GET_MIB(priv)->ap_profile.enable_profile && GET_MIB(priv)->ap_profile.profile_num > 0) + { + if((priv->site_survey->count_target > 0) && ((priv->join_index+1) > priv->site_survey->count_target)){ + STADEBUG("start_clnt_lookup(RESCAN)\n"); + start_clnt_lookup(priv, RESCAN); + }else{ + STADEBUG("start_clnt_lookup(DONTRESCAN)\n"); + start_clnt_lookup(priv, DONTRESCAN); + } + }else +#endif + if (link_time > priv->expire_to) { // if link time exceeds timeout, site survey again + STADEBUG("start_clnt_lookup(RESCAN)\n"); + start_clnt_lookup(priv, RESCAN); + } else{ + STADEBUG("start_clnt_lookup(DONTRESCAN)\n"); + start_clnt_lookup(priv, DONTRESCAN); + } +#endif // WIFI_WPAS_CLI +#if defined(CONFIG_RTL8196B_TR) || defined(CONFIG_RTL865X_SC) || defined(CONFIG_RTL865X_AC) || defined(CONFIG_RTL865X_KLD) || defined(CONFIG_RTL8196B_KLD) || defined(CONFIG_RTL8196C_KLD) || defined(CONFIG_RTL8196C_EC) + LOG_MSG_NOTICE("Deauthenticated by AP;note:%02x-%02x-%02x-%02x-%02x-%02x;\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + if((if_idx = get_wlan_if_type(priv))>=0){ + set_if_status(if_idx,IF_DOWN); + set_if_change_status(if_idx,IF_STATUS_CHANGE); + } +#endif +#else + LOG_MSG("Deauthenticated by AP - %02X:%02X:%02X:%02X:%02X:%02X\n", + *GetAddr2Ptr(pframe), *(GetAddr2Ptr(pframe)+1), *(GetAddr2Ptr(pframe)+2), + *(GetAddr2Ptr(pframe+3)), *(GetAddr2Ptr(pframe)+4), *(GetAddr2Ptr(pframe)+5)); +#if defined(CONFIG_RTL_REPORT_LINK_STATUS) && defined(__ECOS) + if((if_idx = get_wlan_if_type(priv))>=0){ + set_if_status(if_idx,IF_DOWN); + set_if_change_status(if_idx,IF_STATUS_CHANGE); + } +#endif +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (priv->link_status_cb_func) + priv->link_status_cb_func("wlan0", WIFI_LINK_STATUS_DEAUTHENTICATED); +#endif +#endif + +#ifdef UNIVERSAL_REPEATER + disable_vxd_ap(GET_VXD_PRIV(priv)); +#endif +#ifdef CONFIG_RTL_WLAN_STATUS + priv->wlan_status_flag=1; +#endif + } +done: + return SUCCESS; +} + + +static void issue_PwrMgt_NullData(struct rtl8192cd_priv *priv) +{ + struct wifi_mib *pmib; + unsigned char *hwaddr; + DECLARE_TXINSN(txinsn); + + pmib = GET_MIB(priv); + txinsn.retry = pmib->dot11OperationEntry.dot11ShortRetryLimit; + hwaddr = pmib->dot11OperationEntry.hwaddr; + + txinsn.q_num = MANAGE_QUE_NUM; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.fr_type = _PRE_ALLOCHDR_; + txinsn.phdr = get_wlanhdr_from_poll(priv); + txinsn.pframe = NULL; + + if (txinsn.phdr == NULL) + goto send_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + SetFrameSubType(txinsn.phdr, WIFI_DATA_NULL); + SetToDs(txinsn.phdr); + if (priv->ps_state) + SetPwrMgt(txinsn.phdr); + else + ClearPwrMgt(txinsn.phdr); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + txinsn.hdr_len = WLAN_HDR_A3_LEN; + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +send_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); +} + + +void issue_PsPoll(struct rtl8192cd_priv *priv) +{ + struct wifi_mib *pmib; + unsigned char *hwaddr; + DECLARE_TXINSN(txinsn); + + pmib = GET_MIB(priv); + txinsn.retry = pmib->dot11OperationEntry.dot11ShortRetryLimit; + hwaddr = GET_MY_HWADDR; + + txinsn.q_num = MANAGE_QUE_NUM; +#ifdef P2P_SUPPORT // 2013 + if(OPMODE&WIFI_P2P_SUPPORT){ + txinsn.tx_rate = _6M_RATE_; + }else +#endif + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.fr_type = _PRE_ALLOCHDR_; + txinsn.phdr = get_wlanhdr_from_poll(priv); + txinsn.pframe = NULL; + + if (txinsn.phdr == NULL) + goto send_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + SetFrameSubType(txinsn.phdr, WIFI_PSPOLL); + SetPwrMgt(txinsn.phdr); + SetPsPollAid(txinsn.phdr, _AID); + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + txinsn.hdr_len = WLAN_HDR_PSPOLL; + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +send_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); +} + +#ifdef MULTI_MAC_CLONE +void issue_NullData(struct rtl8192cd_priv *priv, unsigned char *da) +{ +#ifdef WIFI_WMM + unsigned char tempQosControl[2]; +#endif + unsigned char *hwaddr; + DECLARE_TXINSN(txinsn); + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + + hwaddr = GET_MY_HWADDR; + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.phdr = get_wlanhdr_from_poll(priv); + txinsn.pframe = NULL; + + if (txinsn.phdr == NULL) + goto send_qos_null_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + SetToDs(txinsn.phdr); +#ifdef WIFI_WMM + if ((QOS_ENABLE) && (priv->pmib->dot11Bss.t_stamp[1] & BIT(0))) + { + SetFrameSubType(txinsn.phdr, BIT(7) | WIFI_DATA_NULL); + txinsn.hdr_len = WLAN_HDR_A3_QOS_LEN; + memset(tempQosControl, 0, 2); + tempQosControl[0] = 0x07; //set priority to VO + tempQosControl[0] |= BIT(4); //set EOSP + memcpy((void *)GetQosControl((txinsn.phdr)), tempQosControl, 2); + + } + else // WIFI_DATA_NULL +#endif + { + SetFrameSubType(txinsn.phdr, WIFI_DATA_NULL); + txinsn.hdr_len = WLAN_HDR_A3_LEN; + } + + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), BSSID, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), da, MACADDRLEN); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +send_qos_null_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); +} +#endif + + +static unsigned int isOurFrameBuffred(unsigned char* tim, unsigned int aid) +{ + unsigned int numSta; + + numSta = (*(tim + 4) & 0xFE) * 8; + if (!((aid < numSta) || (aid >= (numSta + (*(tim + 1)-3)*8)))) { + unsigned int offset; + unsigned int offset_byte; + unsigned int offset_bit; + unsigned char *PartialBitmap = tim + 5; + unsigned int result; + + offset = aid - numSta; + offset_byte = offset / 8; + offset_bit = offset % 8; + result = PartialBitmap[offset_byte] & (1 << offset_bit); + + return (result) ? TRUE : FALSE; + } + + return FALSE; +} +#endif // CLIENT_MODE + + +// A dedicated function to check link status +int chklink_wkstaQ(struct rtl8192cd_priv *priv) +{ + int link_status=0; + + if (OPMODE & WIFI_AP_STATE) + { + if (priv->assoc_num > 0) + link_status = 1; + else + link_status = 0; + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + if (OPMODE & WIFI_ASOC_STATE) { +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + if (IEEE8021X_FUN) { + struct stat_info *pstat; + pstat = get_stainfo(priv, BSSID); + if (pstat && pstat->ieee8021x_ctrlport) + link_status = 1; + else + link_status = 0; + } + else { + link_status = 1; + } +#else + link_status = 1; +#endif + } + else { + link_status = 0; + } + } + else if ((OPMODE & WIFI_ADHOC_STATE) && + ((JOIN_RES == STATE_Sta_Ibss_Active) || (JOIN_RES == STATE_Sta_Ibss_Idle))) + { + if (priv->rxBeaconCntArrayWindow < ROAMING_DECISION_PERIOD_ADHOC) { + if (priv->rxBeaconCntArrayWindow) { + if (priv->rxBeaconCntArray[priv->rxBeaconCntArrayIdx-1] > 0) { + link_status = 1; + } + } + } + else { + if (priv->rxBeaconPercentage) + link_status = 1; + else + link_status = 0; + } + } +#endif + else + { + link_status = 0; + } + + return link_status; +} + + +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) +void start_repeater_ss(struct rtl8192cd_priv *priv) +{ + unsigned long flags = 0; + int xtimeout = 0; //ecos have a "timeout" function. Rename the variable. + int channel_tmp1; + int i=0; +#ifdef MULTI_MAC_CLONE + struct rtl8192cd_priv *vxd_priv=priv; + struct rtl8192cd_priv *vap_priv; + int num_sta=0; + + #ifdef MBSSID + for (i=RTL8192CD_NUM_VWLAN-1; i>=0; i--) + { + vap_priv = GET_VAP_PRIV(priv, i); + if (netif_running(vap_priv->dev) && + (GET_MIB(vap_priv)->dot11OperationEntry.opmode&WIFI_STATION_STATE)) + { + num_sta++; + //if (!(GET_MIB(vap_priv)->dot11OperationEntry.opmode&WIFI_ASOC_STATE)) + // priv = vap_priv; + } + } +#endif // MBSSID + if (netif_running(vxd_priv->dev) && (vxd_priv->drv_state&DRV_STATE_VXD_INIT)) + { + num_sta++; + //if (!(GET_MIB(vxd_priv)->dot11OperationEntry.opmode&WIFI_ASOC_STATE)) + // priv = vxd_priv; + } + + if (!num_sta) + return; +#else + if(!netif_running(priv->dev)){ + return; + } + +#if defined( UNIVERSAL_REPEATER) + if(IS_VXD_INTERFACE(priv) && !(priv->drv_state & DRV_STATE_VXD_INIT) ) + { + return; + } +#endif // UNIVERSAL_REPEATER +#endif + + //STADEBUG("count_target=%d;join_index=%d ;ongoing=%d\n",priv->site_survey->count_target,priv->join_index,priv->ss_req_ongoing); + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + + if ( !(GET_MIB(priv)->dot11OperationEntry.opmode & WIFI_ASOC_STATE)) { + if (!netif_running(priv->dev) || priv->ss_req_ongoing) { + xtimeout = RTL_SECONDS_TO_JIFFIES(1); + goto out; + } + if (!netif_running(GET_ROOT(priv)->dev) || GET_ROOT(priv)->ss_req_ongoing) { + + xtimeout = RTL_SECONDS_TO_JIFFIES(1); + goto out; + } + if (GET_MIB(priv)->wscEntry.wsc_enable) { + goto out; + } + +#ifdef CONFIG_RTK_MESH + if(GET_ROOT(priv)->pmib->dot1180211sInfo.mesh_enable && timer_pending(&(GET_ROOT(priv)->ss_timer))) + { /*if mesh is doing auto channel scanning, delay 1 sec*/ + xtimeout = RTL_SECONDS_TO_JIFFIES(1); + goto out; + } +#endif +#ifdef DFS + if(timer_pending(&GET_ROOT(priv)->ch_avail_chk_timer)){ + xtimeout = RTL_SECONDS_TO_JIFFIES(3); + goto out; + } +#endif +#ifdef SUPPORT_MULTI_PROFILE + /*change because check_vxd_ap_timer hook on vxd now ; before it hook on root interface jw*/ + if (GET_MIB(priv)->ap_profile.enable_profile && GET_MIB(priv)->ap_profile.profile_num > 0) { + priv->ss_ssidlen = strlen(GET_MIB(priv)->ap_profile.profile[priv->profile_idx].ssid); + memcpy(priv->ss_ssid, GET_MIB(priv)->ap_profile.profile[priv->profile_idx].ssid, priv->ss_ssidlen); + } + else +#endif + { + priv->ss_ssidlen = GET_MIB(priv)->dot11StationConfigEntry.dot11SSIDtoScanLen; + memcpy(priv->ss_ssid, GET_MIB(priv)->dot11StationConfigEntry.dot11SSIDtoScan, priv->ss_ssidlen); + } + + + priv->pshare->switch_chan_rp = 0; + //STADEBUG(" Call start_clnt_ss\n\n"); + + #ifdef MBSSID + /*if the other STA is connected just scan the same ch with it*/ + if(IS_VAP_INTERFACE(priv)) + { + /*multiRepeater_connection_status return if other STA connected(return it's channel) or not*/ + channel_tmp1=multiRepeater_connection_status( priv ); + if(channel_tmp1==0){ + //STADEBUG("\n"); + /*restore available_chnl_num,available_chnl*/ + if(priv->MultiSTA_available_backup==1){ + //STADEBUG("\n"); + for(i=0;iMultiSTA_available_chnl_num;i++) + priv->available_chnl[i] = priv->MultiSTA_available_chnl[i]; + + priv->available_chnl_num = priv->MultiSTA_available_chnl_num; + + priv->MultiSTA_available_backup = 0; + } + + }else{ + //STADEBUG("channel_tmp1=[%d]\n",channel_tmp1); + + /*backup available_chnl_num,available_chnl*/ + if(priv->MultiSTA_available_backup==0){ + STADEBUG("\n"); + for(i=0;iavailable_chnl_num;i++) + priv->MultiSTA_available_chnl[i] = priv->available_chnl[i]; + + priv->MultiSTA_available_chnl_num=priv->available_chnl_num; + priv->MultiSTA_available_backup=1; + } + + /*only scan the channel the same with the other STA*/ + priv->available_chnl[0]=channel_tmp1; + priv->available_chnl_num=1; + } + } + /*if the other STA is connected just scan the same ch with it*/ + #endif + + #ifdef SUPPORT_MULTI_PROFILE + /* 1) AP disappear,2)AP's ch/2nd ch offset/band width be changed , under these cases do RESCAN instead of DONTRESCAN*/ + if(priv->rescantype==RESCAN_ROAMING){ + priv->ss_req_ongoing = SSFROM_REPEATER_VXD; // 3 for vxd SiteSurvey case + priv->rescantype=0; + start_clnt_ss(priv); + }else + if((priv->site_survey->count_target == 0) || + ((priv->site_survey->count_target > 0) && ((priv->join_index+1) > priv->site_survey->count_target))){ + + priv->ss_req_ongoing = SSFROM_REPEATER_VXD; // 3 for vxd SiteSurvey case + STADEBUG(" start_clnt_ss()\n"); + start_clnt_ss(priv); + }else{ + STADEBUG(" start_clnt_lookup(DONTRESCAN)\n"); + start_clnt_lookup(priv, DONTRESCAN); + } +#else + priv->ss_req_ongoing = SSFROM_REPEATER_VXD; // 3 for vxd SiteSurvey case + start_clnt_ss(priv); +#endif + xtimeout = 0; + } +#if 0 // Dont run ss_timer when vxd is associated. + else{ + + /*now vxd STA under WIFI_ASOC_STATE mode ; just hook a timer for check myself status*/ + xtimeout = CHECK_VXD_AP_TIMEOUT; + } +#endif +out: + if (xtimeout){ + //STADEBUG("timeout=%d\n",timeout); + mod_timer(&priv->ss_timer, jiffies + xtimeout); + } + RESTORE_INT(flags); + SMP_UNLOCK(flags); + +} + + + +/* + * reschedule STA( not root interface) to do Scan + * SMP_LOCK before call set_vxd_rescan() + */ +void set_vxd_rescan(struct rtl8192cd_priv *priv,int rescantype) +{ + /*rescantype:// + RESCAN_BY_NEXTTIME by get_ss_level + RESCAN_ROAMING: + because 1) AP disappear,2)AP's ch/2nd ch offset/band width be changed , under these cases do RESCAN + */ + unsigned long flags = 0; + if(IS_ROOT_INTERFACE(priv)){ + return; + } + + if( OPMODE & WIFI_ASOC_STATE){ + return; + } + +#ifdef SMP_SYNC + SMP_LOCK_ASSERT(); +#endif + + SAVE_INT_AND_CLI(flags); + //SMP_LOCK(flags); + if (timer_pending(&priv->ss_timer)) { + SMP_UNLOCK(flags); + del_timer_sync(&priv->ss_timer); + SMP_LOCK(flags); + } + + if(rescantype==RESCAN_ROAMING){ + STADEBUG("1sec\n"); + mod_timer(&priv->ss_timer, jiffies + RTL_SECONDS_TO_JIFFIES(1)); + }else{ + /* SS_LV_WSTA = 0, has STA connect to root AP/VAP + SS_LV_WOSTA = 1, no STA connect to root AP/VAP + SS_LV_ROOTFUNCOFF = 2, only root AP and it's func_off=1 */ + switch(get_ss_level(priv)) { + case SS_LV_WSTA: + /*SS_LV_WSTA = 0, has STA connect to root AP/VAP*/ + STADEBUG("60secs\n"); +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if((priv->pmib->dot11StationConfigEntry.sc_enabled == 1) && (priv->simple_config_status !=0)) + { + mod_timer(&priv->ss_timer, jiffies + priv->pmib->dot11StationConfigEntry.sc_vxd_rescan_time); + } + else + mod_timer(&priv->ss_timer, jiffies + CHECK_VXD_AP_TIMEOUT); + +#else + mod_timer(&priv->ss_timer, jiffies + CHECK_VXD_AP_TIMEOUT); +#endif + break; + case SS_LV_ROOTFUNCOFF: + STADEBUG("1sec\n"); + mod_timer(&priv->ss_timer, jiffies + RTL_SECONDS_TO_JIFFIES(1)); + break; + default: + // No STA connected to AP,and AP hasn't func_off,wait a while let DUT's AP can be connected. +#if defined(CONFIG_RTL_SIMPLE_CONFIG) + if((priv->pmib->dot11StationConfigEntry.sc_enabled == 1) && (priv->simple_config_status !=0)) + { + mod_timer(&priv->ss_timer, jiffies + priv->pmib->dot11StationConfigEntry.sc_vxd_rescan_time); + } + else + mod_timer(&priv->ss_timer, jiffies + CHECK_VXD_RUN_DELAY); + +#else + mod_timer(&priv->ss_timer, jiffies + CHECK_VXD_RUN_DELAY); +#endif + } + } + + RESTORE_INT(flags); + //SMP_UNLOCK(flags); +} + +#if 0 +void sync_channel_2ndch_bw(struct rtl8192cd_priv *priv) +{ + STADEBUG("\n"); + if(priv->pmib->dot11RFEntry.dot11channel != priv->pshare->switch_chan_rp){ + STADEBUG("ch;My[%d],RAP[%d]\n",priv->pmib->dot11RFEntry.dot11channel , priv->pshare->switch_chan_rp); + priv->pmib->dot11RFEntry.dot11channel = priv->pshare->switch_chan_rp; + } + if(priv->pmib->dot11nConfigEntry.dot11n2ndChOffset != priv->pshare->switch_2ndchoff_rp){ + STADEBUG("2nd ch;My[%d],RAP[%d]\n",priv->pmib->dot11nConfigEntry.dot11n2ndChOffset , priv->pshare->switch_2ndchoff_rp); + priv->pmib->dot11nConfigEntry.dot11n2ndChOffset = priv->pshare->switch_2ndchoff_rp; + } + if(priv->pmib->dot11nConfigEntry.dot11nUse40M != priv->pshare->band_width_rp){ + STADEBUG("\n"); + priv->pmib->dot11nConfigEntry.dot11nUse40M = priv->pshare->band_width_rp; + } +} +#endif /* SMART_REPEATER_MODE */ + +#endif /* SMART_REPEATER_MODE */ +/*for report request from wsc daemon*/ +static void backup_wscIE(struct rtl8192cd_priv *priv) +{ + int idx=0; + for(idx=0;idxsite_survey->count;idx++){ + priv->site_survey->wscie_backup[idx].rssi = priv->site_survey->wscie[idx].rssi; + memcpy(priv->site_survey->wscie_backup[idx].data , priv->site_survey->wscie[idx].data , MAX_WSC_IE_LEN); + } +} + +#ifdef MBSSID + +/*under multi-repeater case when some STA has connect , + the other STA don't connect to Remote AP that has diff channel or diff 2nd ch skip this*/ +static int multiRepeater_startlookup_chk(struct rtl8192cd_priv *priv , int db_idx) +{ + + struct rtl8192cd_priv *priv_root=NULL; + struct rtl8192cd_priv *priv_other_va=NULL; + int target_2ndch=0; + if(!IS_VAP_INTERFACE(priv)) + return 0; + if((OPMODE & WIFI_STATION_STATE)==0) + return 0; + + priv_root = GET_ROOT(priv); + + if(priv_root==NULL) + return 0; + + /*now we default use wlan0-va1 and wlan0-va2 as STA under multiRepeater mode*/ + if (priv->vap_id == 1) + priv_other_va=priv_root->pvap_priv[2]; + else if (priv->vap_id == 2) + priv_other_va=priv_root->pvap_priv[1]; + + if(priv_other_va && priv_other_va->pmib->dot11OperationEntry.opmode & WIFI_ASOC_STATE){ + + /*get target Remote AP's 2nd ch off set*/ + if ((priv->site_survey->bss_target[db_idx].t_stamp[1] & (BIT(1) | BIT(2))) == (BIT(1) | BIT(2))) + target_2ndch = HT_2NDCH_OFFSET_BELOW; + else if ((priv->site_survey->bss_target[db_idx].t_stamp[1] & (BIT(1) | BIT(2))) == BIT(1)) + target_2ndch = HT_2NDCH_OFFSET_ABOVE; + else { + target_2ndch = HT_2NDCH_OFFSET_DONTCARE; + } + + /*check ch and 2nd ch off set*/ + if( (priv_other_va->pmib->dot11RFEntry.dot11channel != priv->site_survey->bss_target[db_idx].channel)|| + ( priv_other_va->pmib->dot11nConfigEntry.dot11n2ndChOffset != target_2ndch)) + { + /* + if( priv_other_va->pmib->dot11nConfigEntry.dot11n2ndChOffset != target_2ndch){ + + STADEBUG("2nd ch no match other's[%d],target[%d]\n",priv_other_va->pmib->dot11nConfigEntry.dot11n2ndChOffset,target_2ndch); + } + */ + return 1; + } + } + else{ + return 0; + } + + STADEBUG("\n"); + return 0; + +} + +static int multiRepeater_connection_status(struct rtl8192cd_priv *priv) +{ + struct rtl8192cd_priv *priv_root=NULL; + struct rtl8192cd_priv *priv_other_va=NULL; + + if(!IS_VAP_INTERFACE(priv)) + return 0; + if((OPMODE & WIFI_STATION_STATE)==0) + return 0; + + priv_root = GET_ROOT(priv); + + if(priv_root==NULL) + return 0; + + //now we default use wlan0-va1 and wlan0-va2 as STA under multiRepeater mode + if(priv->vap_id==1){ + priv_other_va=priv_root->pvap_priv[2]; + }else if(priv->vap_id==2){ + priv_other_va=priv_root->pvap_priv[1]; + } + + if(priv_other_va && priv_other_va->pmib->dot11OperationEntry.opmode & WIFI_ASOC_STATE){ + return priv_other_va->pmib->dot11RFEntry.dot11channel; + } + else{ + return 0; + } +} +#endif + +#ifdef RTK_NL80211//openwrt_psd +extern u2Byte dB_Invert_Table[8][12]; +static u4Byte rtl8192cd_convertto_db(u4Byte Value) +{ + u1Byte i; + u1Byte j; + u4Byte dB; + + Value = Value & 0xFFFF; + + for (i=0;i<8;i++) + { + if (Value <= dB_Invert_Table[i][11]) + break; + } + + if (i >= 8) + return (96); // maximum 96 dB + + for (j=0;j<12;j++) + { + if (Value <= dB_Invert_Table[i][j]) + break; + } + dB = i*12 + j + 1; + + return (dB); +} + +static int rtl8192cd_get_psd_data(struct rtl8192cd_priv *priv, unsigned int point) +{ + u4Byte psd_val; + + //2.4G + if (GET_CHIP_VER(priv)==VERSION_8192E) + { + psd_val = RTL_R32(0x808); + + // FFT sample points will be adjusted in "acs_query_psd" + // set which fft pts we calculate + psd_val &= 0xFFFFFC00; + psd_val |= point; + RTL_W32(0x808, psd_val); + + // Reg 808[22] = 0 ( default ) + // set Reg08[22] = 1, 0->1, PSD activate + psd_val |= BIT22; + RTL_W32(0x808, psd_val); + + delay_ms(1); + psd_val &= ~(BIT22); + // set Reg08[22] = 0 + RTL_W32(0x808, psd_val); + + psd_val = RTL_R32(0x8B4); + psd_val &= 0x0000FFFF; + } + else if (GET_CHIP_VER(priv)==VERSION_8812E) + { + IN PDM_ODM_T pDM_Odm = ODMPTR; + + //Set DCO frequency index, offset=(40MHz/SamplePts)*point + ODM_SetBBReg(pDM_Odm, 0x910, 0x3FF, point); + + //Start PSD calculation, Reg808[22]=0->1 + ODM_SetBBReg(pDM_Odm, 0x910, BIT22, 1); + + //Need to wait for HW PSD report + delay_us(150); + + ODM_SetBBReg(pDM_Odm, 0x910, BIT22, 0); + + //Read PSD report, Reg8B4[15:0] + psd_val = (int)ODM_GetBBReg(pDM_Odm,0xf44, bMaskDWord) & 0x0000FFFF; + psd_val = (int)(rtl8192cd_convertto_db((u4Byte)psd_val)); + } + + return psd_val; +} + +static int rtl8192cd_query_psd_2g(struct rtl8192cd_priv *priv, unsigned int * data, int fft_pts) +{ + unsigned int regc70, regc7c, reg800, regc14, regc1c, reg522, reg88c, reg804, reg808, regc50; + int regval; + unsigned int psd_pts=0, psd_start=0, psd_stop=0, psd_data=0, i, j; + + //pre seeting for PSD start --- + regc50 = RTL_R32(0xc50); // initial gain + + //store init value + regc70 = RTL_R32(0xc70); // AGC + regc7c = RTL_R32(0xc7c); // AAGC + reg800 = RTL_R32(0x800); // CCK + regc14 = RTL_R32(0xc14); // IQ matrix A + + // 2013-07-08 Jeffery modified + regc1c = RTL_R32(0xc1c); // IQ matrix B + + reg522 = RTL_R8(0x522); // MAC queen + reg88c = RTL_R32(0x88c); // 3-wire + reg804 = RTL_R32(0x804); // PSD ant select + reg808 = RTL_R32(0x808); // PSD setting + + //CCK off + regval = RTL_R32(0x800); + regval = regval & (~BIT24);//808[24]=0 + // regval = regval & 0xFEFFFFFF;//808[24]=0 + RTL_W32(0x800, regval); + + // CCA off path A & B, set IQ matrix = 0 + RTL_W32(0xc14, 0x0); + RTL_W32(0xc1c, 0x0); + + //TX off, MAC queen + RTL_W8(0x522, 0xFF); + + //2 set IGI before 3-wire off + + // caution ! mib uses decimal value + RTL_W8(0xc50, 0x30); // default IGI = -30 dBm + // RTL_W8(0xc50, 0x32); + + //3-wire off + regval = RTL_R32(0x88c); + regval = regval | (BIT23|BIT22|BIT21|BIT20) ; + RTL_W32(0x88c, regval) ; + + //set PSD path a, b = 0, 1 + //path = 0; + regval = RTL_R32(0x804); + regval = regval & (~(BIT4|BIT5)); + // regval = regval & 0xFFFFFFCF; + RTL_W32(0x804, regval); + + + regval = RTL_R32(0x808); + + //FFT pts 128, 256, 512, 1024 = 0, 1, 2, 3 +#if 1 + if(fft_pts == 128) + regval = regval & 0xFFFF3FFF; + else if(fft_pts == 256) + regval = regval & 0xFFFF7FFF; + else if(fft_pts == 512) + regval = regval & 0xFFFFBFFF; + //else if(fft_pts == 1024) + // regval = regval & 0xFFFFFFFF; + else//default 128 + { + regval = regval & 0xFFFF3FFF; + fft_pts = 128; + } + + //set psd pts + psd_start = fft_pts/2; + psd_stop = psd_start+fft_pts; + psd_pts = fft_pts; +#else + //default set PSD pts 128 + printk("[2G] Now we only support PSD to scan 128 points, you set PSD pts:%d\n",fft_pts); + regval = regval & 0xFFFF3FFF; + psd_start = 64; + psd_stop = 192; + psd_pts = 128; +#endif + + RTL_W32(0x808, regval); + + + regval = RTL_R32(0x808); + regval = regval & ( (~BIT12)|(~BIT13) ); + RTL_W32(0x808, regval); + //pre setting for PSD end --- + + //Get PSD Data + i = psd_start; + j = 0; + while(i= psd_pts) + psd_data = rtl8192cd_get_psd_data(priv,(i-psd_pts)); + else + psd_data = rtl8192cd_get_psd_data(priv,i); + data[j] = psd_data; + i++;j++; + } + + //rollback settings start --- + RTL_W32(0xc70, regc70); + RTL_W32(0xc7c, regc7c); + RTL_W32(0x800, reg800); + RTL_W32(0xc14, regc14); + RTL_W32(0xc1c, regc1c); + RTL_W8(0x522, reg522); + RTL_W32(0x88c, reg88c); + RTL_W32(0x804, reg804); + RTL_W32(0x808, reg808); + RTL_W32(0xc50, regc50); + //rollback settings start --- + + return psd_pts; +} + +static int rtl8192cd_query_psd_5g(struct rtl8192cd_priv *priv, unsigned int * data, int fft_pts) +{ + IN PDM_ODM_T pDM_Odm = ODMPTR; + + unsigned int psd_pts=0, psd_start=0, psd_stop=0, psd_data=0, i, j; + int psd_pts_idx, initial_gain = 0x3e, initial_gain_org; + + + //pre seeting for PSD start --- + // Turn off CCK + ODM_SetBBReg(pDM_Odm, 0x808, BIT28, 0); //808[28] + + // Turn off TX + // Pause TX Queue + if (!priv->pmib->dot11DFSEntry.disable_tx) + ODM_Write1Byte(pDM_Odm, 0x522, 0xFF); //REG_TXPAUSE set 0xff + + // Turn off CCA + ODM_SetBBReg(pDM_Odm, 0x838, BIT3, 0x1); //838[3] set 1 + + // PHYTXON while loop + i = 0; + while (ODM_GetBBReg(pDM_Odm, 0xfa0, BIT18)) { + i++; + if (i > 1000000) { + panic_printk("Wait in %s() more than %d times!\n", __FUNCTION__, i); + break; + } + } + + // backup IGI_origin , set IGI = 0x3e; + pDM_Odm->bDMInitialGainEnable = FALSE; // setmib dig_enable 0; + initial_gain_org = ODM_Read1Byte(pDM_Odm, 0xc50); + ODM_Write_DIG(pDM_Odm, initial_gain); + + delay_us(100); + + // Turn off 3-wire + ODM_SetBBReg(pDM_Odm, 0xC00, BIT1|BIT0, 0x0); //c00[1:0] set 0 + + // pts value = 128=0, 256=1, 512=2, 1024=3 +#if 1 + if(fft_pts == 128) + psd_pts_idx = 0; + else if(fft_pts == 256) + psd_pts_idx = 1; + else if(fft_pts == 512) + psd_pts_idx = 2; + //else if(fft_pts == 1024) + // psd_pts_idx = 3; + else//default 128 + { + psd_pts_idx = 0; + fft_pts = 128; + } + ODM_SetBBReg(pDM_Odm, 0x910, BIT14|BIT15, psd_pts_idx); //910[15:14] set 0, 128 points + //set psd pts + psd_start = fft_pts/2; + psd_stop = psd_start+fft_pts; + psd_pts = fft_pts; +#else + printk("[5G] Now we only support PSD to scan 128 points, you set PSD pts:%d\n",fft_pts); + ODM_SetBBReg(pDM_Odm, 0x910, BIT14|BIT15, 0x0); //910[15:14] set 0, 128 points + psd_start = 64; + psd_stop = 192; + psd_pts = 128; +#endif + //pre seeting for PSD end --- + + + //Get PDS DATA + i = psd_start; + j = 0; + while(i= psd_pts) + psd_data = rtl8192cd_get_psd_data(priv,(i-psd_pts)); + else + psd_data = rtl8192cd_get_psd_data(priv,i); + data[j] = psd_data; + i++;j++; + } + + + //rollback settings start --- + // CCK on + ODM_SetBBReg(pDM_Odm, 0x808, BIT28, 1); //808[28] + + // Turn on TX + // Resume TX Queue + if (!priv->pmib->dot11DFSEntry.disable_tx) + ODM_Write1Byte(pDM_Odm, 0x522, 0x00); //REG_TXPAUSE set 0x0 + + // Turn on 3-wire + ODM_SetBBReg(pDM_Odm, 0xc00, BIT1|BIT0, 0x3); //c00[1:0] set 3 + + // Restore Current Settings + // Resume DIG + pDM_Odm->bDMInitialGainEnable = TRUE; // setmib dig_enable 1; + ODM_Write_DIG(pDM_Odm, initial_gain_org); // set IGI=IGI_origin + + //Turn on CCA + ODM_SetBBReg(pDM_Odm, 0x838, BIT3, 0); //838[3] set 0 + //rollback settings end --- + + return psd_pts; +} + +static int rtl8192cd_query_psd_cfg80211(struct rtl8192cd_priv *priv, int chnl, int bw, int fft_pts) +{ + unsigned int psd_fft_info[1024];//128, 256, 512, 1024 + unsigned int backup_chnl = priv->pmib->dot11RFEntry.dot11channel; + unsigned int backup_2ndch = priv->pshare->offset_2nd_chan; + unsigned int backup_bw = priv->pshare->CurrentChannelBW; + int i, scan_pts=0; + + if (!netif_running(priv->dev)) { + printk("\nFail: interface not opened\n"); + return -1; + } + + //check channel + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) + { + if(chnl>14 || chnl<1) + { + printk("\nFail: channel %d is not in 2.4G\n", chnl); + return -1; + } + } + else if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + { + if(chnl<14) + { + printk("\nFail: channel %d is not in 5G\n", chnl); + return -1; + } + } + + memset(psd_fft_info, 0x0, sizeof(psd_fft_info)); + + //set chnl + SwChnl(priv, chnl, HT_2NDCH_OFFSET_BELOW); + //set BW, PSD always scan 40M, is this necessary ??? + SwBWMode(priv, HT_CHANNEL_WIDTH_20_40, HT_2NDCH_OFFSET_BELOW); + + + //query psd data + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) + { + //printk("Scan 2G PSD in CH[%d] cur_CH[%d] fft_pts[%d]\n", chnl, backup_chnl,fft_pts); + scan_pts = rtl8192cd_query_psd_2g(priv, psd_fft_info, fft_pts); + } + else if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + { + //printk("Sacn 5G PSD in CH[%d] cur_CH[%d] fft_pts[%d]\n", chnl, backup_chnl, fft_pts); + scan_pts = rtl8192cd_query_psd_5g(priv, psd_fft_info, fft_pts); + } + + //rollback chnl and bw + priv->pmib->dot11RFEntry.dot11channel = backup_chnl; + priv->pshare->offset_2nd_chan = backup_2ndch; + priv->pshare->CurrentChannelBW = backup_bw; + SwChnl(priv,priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + + priv->rtk->psd_fft_info[0]=chnl; + priv->rtk->psd_fft_info[1]=40;//bw; + priv->rtk->psd_fft_info[2]=scan_pts; + memcpy(priv->rtk->psd_fft_info+16, psd_fft_info, sizeof(psd_fft_info)); + + //for debug +#if 0 + printk("\n PDS Result:\n"); + for(i=0;i<128;i++) + { + if(i%16==0) + printk("\n"); + printk("%3x ", psd_fft_info[i]); + } + printk("\n"); +#endif + + return 0; +} +#endif + +#ifdef AUTO_CHANNEL_TIMEOUT +void auto_channel_timeout_expire(struct rtl8192cd_priv *priv) +{ + int i; + + if ((OPMODE & WIFI_AP_STATE) == 0) { + printk("not as AP\n"); + return; + } + +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { + priv->pshare->autoch_timeout_count = 0; + printk("be MP\n"); + return; + } +#endif + +#if 0 + if (priv->auto_channel_backup != 1) { + priv->pshare->autoch_timeout_count = 0; + printk("backup \n"); + return; + } +#endif + + if (priv->assoc_num != 0) { + priv->pshare->autoch_timeout_count = 0; + printk("asso num\n"); + return; + } + + printk("enter auto_channel_timeout_expire\n"); + +#ifdef MBSSID + for (i=0; ipvap_priv[i])) { + if (priv->pvap_priv[i]->assoc_num != 0) { + priv->pshare->autoch_timeout_count = 0; + return; + } + } + } +#endif + +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(priv->pvxd_priv)) { + if (priv->pvxd_priv->pmib->dot11OperationEntry.opmode & WIFI_ASOC_STATE) { + priv->pshare->autoch_timeout_count = 0; + return; + } + + if (GET_VXD_PRIV(priv)->ss_req_ongoing) { + return; + } + } +#endif + + if (priv->ss_req_ongoing) { + return; + } + + priv->pshare->autoch_timeout_count++; + + printk("timeout:%d \n", priv->pshare->autoch_timeout_count) +; + if (priv->pshare->autoch_timeout_count >= priv->pmib->miscEntry.autoch_timeout) + { + priv->pshare->autoch_timeout_count = 0; + + priv->pshare->autoch_trigger_by_timeout = 1; + priv->auto_channel = 1; + priv->ss_req_ongoing = 1; + printk("===> re-select channel, current = %d, 2ch = %d\n", + priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + start_clnt_ss(priv); + } +} +#endif + + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_tkip.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_tkip.c new file mode 100755 index 000000000..e01e6737c --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_tkip.c @@ -0,0 +1,1369 @@ +/* + * Software TKIP encryption/descryption routines + * + * $Id: 8192cd_tkip.c,v 1.4.4.2 2010/09/30 05:27:28 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_TKIP_C_ + +#ifdef __KERNEL__ +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" + +#if !defined(__KERNEL__) && !defined(__ECOS) +#include "./sys-support.h" +#endif + +#include "./8192cd.h" +#ifdef __KERNEL__ +#include "./ieee802_mib.h" +#elif defined(__ECOS) +#include +#endif +#include "./8192cd_util.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + +#ifdef __LINUX_2_6__ +/*avoid mutli defined*/ +#ifdef swap +#undef swap +#endif +#endif + +#define MAX_MESSAGE_LENGTH 2048 + +#define rotr(n,x) (((x) >> ((int)(n))) | ((x) << (32 - (int)(n)))) +#define rotl(n,x) (((x) << ((int)(n))) | ((x) >> (32 - (int)(n)))) + +#define block_function(l,r) { \ + r = r ^ rotl(17,l); \ + l = (l + r); \ + r ^= ((l & 0xff00ff00) >> 8) | ((l & 0x00ff00ff) << 8); \ + l = (l + r); \ + r = r ^ rotl(3,l); \ + l = (l + r); \ + r = r ^ rotr(2,l); \ + l = (l + r); \ +} + +void debug_out(unsigned char *label, unsigned char *data, int data_length) +{ + int i,j; + int num_blocks; + int block_remainder; + + num_blocks = data_length >> 4; + block_remainder = data_length & 15; + + if (label) { + printk("%s\n", label); + } + + if (data==NULL || data_length==0) + return; + + for (i=0; i 0) + { + printk("\t"); + for (j=0; j> bits; + f = (a & c) << (32 - bits); + + g = e | f; + + return (g & 0xffffffff ); +} + + +static __inline__ unsigned long int rotl(int bits, unsigned long int a) +{ + unsigned long int c,d,e,f,g; + c = (0x0001 << (32-bits))-1; + d = ~c; + + e = (a & c) << bits; + f = (a & d) >> (32 - bits); + + g = e | f; + + return (g & 0xffffffff ); +} + + +static __inline__ unsigned long int xswap(unsigned long int in) +{ + unsigned long int a,b,c,d,out; + + a = in & 0xff; + b = (in >> 8) & 0xff; + c = (in >> 16) & 0xff; + d = (in >> 24) & 0xff; + + out = 0; + out |= c << 24; + out |= d << 16; + out |= a << 8; + out |= b; + + return out; +} + + +static __inline__ void block_function( + unsigned long int l, + unsigned long int r, + unsigned long int *l_out, + unsigned long int *r_out) +{ + r = r ^ rotl(17,l); + l = (l + r); + r = r ^ xswap(l); + l = (l + r); + r = r ^ rotl(3,l); + l = (l + r); + r = r ^ rotr(2,l); + l = (l + r); + *l_out = l; + *r_out = r; +} +#endif + + +void michael( + struct rtl8192cd_priv *priv, + unsigned char *key, + unsigned char *hdr, + unsigned char *llc, + unsigned char *message, + int message_length, + unsigned char *mic, int tx) +{ +// unsigned long int l_out, r_out; + register unsigned int l,r; + register unsigned int k0,k1; + register unsigned int m; + register unsigned char a,b,c,d; + + int num_blocks; + int block; + + num_blocks = message_length >> 2; + + k0 = key[0] + (key[1] << 8) + (key[2] << 16) + (key[3] << 24); + k1 = key[4] + (key[5] << 8) + (key[6] << 16) + (key[7] << 24); + + l = k0; + r = k1; + + //in the beginning, perform the first 16 bytes from hdr... + if (hdr) + { + for (block = 0; block < 4; block++) + { + a = hdr[block<<2]; + b = hdr[1+(block<<2)]; + c = hdr[2+(block<<2)]; + d = hdr[3+(block<<2)]; + m = a + (b << 8) + (c << 16) + (d << 24); + l = l ^ m; +#if 0 + block_function(l,r,&l_out,&r_out); + l = l_out; + r = r_out; +#endif + block_function(l,r); + } + + num_blocks -= 4; + } + + if (llc) + { + for (block = 0; block < 2; block++) + { + a = llc[block<<2]; + b = llc[1+(block<<2)]; + c = llc[2+(block<<2)]; + d = llc[3+(block<<2)]; + m = a + (b << 8) + (c << 16) + (d << 24); + l = l ^ m; +#if 0 + block_function(l,r,&l_out,&r_out); + l = l_out; + r = r_out; +#endif + block_function(l,r); + } + + num_blocks -= 2; + } + +#ifndef NOT_RTK_BSP + if ((priv->pshare->have_hw_mic) && + !(priv->pmib->dot11StationConfigEntry.swTkipMic)) + { + if (tx) + rtl_cache_sync_wback(priv, (unsigned long)message, (num_blocks*4), PCI_DMA_TODEVICE); + + *(volatile unsigned int *)GDMACNR = 0; + *(volatile unsigned int *)GDMACNR = GDMA_ENABLE; + *(volatile unsigned int *)GDMAIMR = 0; + *(volatile unsigned int *)GDMAISR = 0xffffffff; + *(volatile unsigned int *)GDMAICVL = (l); + *(volatile unsigned int *)GDMAICVR = (r); + *(volatile unsigned int *)GDMASBP0 = virt_to_bus(message)+CONFIG_LUNA_SLAVE_PHYMEM_OFFSET; + *(volatile unsigned int *)GDMASBL0 = GDMA_LDB|(num_blocks*4); + *(volatile unsigned int *)GDMADBP0 = 0; + *(volatile unsigned int *)GDMADBL0 = 0; + *(volatile unsigned int *)GDMACNR = GDMA_ENABLE|GDMA_POLL|GDMA_MIC|internalUsedGDMACNR; + } + else +#endif // NOT_RTK_BSP + { + for (block = 0; block < num_blocks; block++) + { + a = message[block<<2]; + b = message[1+(block<<2)]; + c = message[2+(block<<2)]; + d = message[3+(block<<2)]; + m = a + (b << 8) + (c << 16) + (d << 24); + l = l ^ m; +#if 0 + block_function(l,r,&l_out,&r_out); + l = l_out; + r = r_out; +#endif + block_function(l,r); + } + + mic[0] = (unsigned char)(l & 0xff); + mic[1] = (unsigned char)((l >> 8) & 0xff); + mic[2] = (unsigned char)((l >> 16) & 0xff); + mic[3] = (unsigned char)((l >> 24) & 0xff); + mic[4] = (unsigned char)(r & 0xff); + mic[5] = (unsigned char)((r >> 8) & 0xff); + mic[6] = (unsigned char)((r >> 16) & 0xff); + mic[7] = (unsigned char)((r >> 24) & 0xff); + } +} + + +/*----------------------------------------------------------------------------- + below is for key mixing function +------------------------------------------------------------------------------*/ + +/* The Sbox can be reduced to two 16 bit wide tables, each with 256 entries.*/ +/* The second table is the same as the first but with the upper and lower */ +/* bytes swapped. To allow an endian tolerant implementation, the byte */ +/* halves have been expressed independently here. */ +unsigned char Tkip_Sbox_Lower[256] = +{ + 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54, + 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A, + 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B, + 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B, + 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F, + 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F, + 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5, + 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F, + 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB, + 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97, + 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED, + 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A, + 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94, + 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3, + 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04, + 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D, + 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39, + 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95, + 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83, + 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76, + 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4, + 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B, + 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0, + 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18, + 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51, + 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85, + 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12, + 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9, + 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7, + 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A, + 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8, + 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A +}; + +unsigned char Tkip_Sbox_Upper[256] = +{ + 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91, + 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC, + 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB, + 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B, + 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83, + 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A, + 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F, + 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA, + 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B, + 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13, + 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6, + 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85, + 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11, + 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B, + 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1, + 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF, + 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E, + 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6, + 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B, + 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD, + 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8, + 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2, + 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49, + 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10, + 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97, + 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F, + 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C, + 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27, + 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33, + 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5, + 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0, + 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C +}; + +#ifdef _USE_DRAM_ +unsigned char *pTkip_Sbox_Lower, *pTkip_Sbox_Upper; +#endif + +/*****************************/ +/**** Function Prototypes ****/ +/*****************************/ + +unsigned int tkip_sbox(unsigned int index); +static __inline__ unsigned int rotr1(unsigned int a); + +/* Mixes key from TA, TK and TSC */ +// key: TTK (16 bytes), ta (transmitted address) +void mix_key( + unsigned char *key, + unsigned char *ta, + unsigned int pnl, /* Least significant 16 bits of PN */ + unsigned int pnh, /* Most significant 32 bits of PN */ + unsigned char *rc4key); + + +/************************************************************/ +/* tkip_sbox() */ +/* Returns a 16 bit value from a 64K entry table. The Table */ +/* is synthesized from two 256 entry byte wide tables. */ +/************************************************************/ +unsigned int tkip_sbox(unsigned int index) +{ + unsigned int index_low; + unsigned int index_high; + unsigned int left, right; + + index_low = (index & 255); + index_high = ((index >> 8) & 255); + +#if defined(_USE_DRAM_) + left = ((int)pTkip_Sbox_Lower[index_low]) + (((int)pTkip_Sbox_Upper[index_low]) << 8); + right = ((int)pTkip_Sbox_Upper[index_high]) + (((int)pTkip_Sbox_Lower[index_high]) << 8); +#else + left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] << 8); + right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] << 8); +#endif + + return (left ^ right); +} + + +static __inline__ unsigned int rotr1(unsigned int a) +{ + unsigned int b; + + if ((a & 0x01) == 0x01) + { + b = (a >> 1) | 0x8000; + } + else + { + b = (a >> 1) & 0x7fff; + } + b = b & 0xffff; + return b; +} + + +/****************************************************/ +/* mix_key() */ +/* Takes a key, PN and TK. Calculates an RC4 key. */ +/****************************************************/ +void mix_key( + unsigned char *key, + unsigned char *ta, + unsigned int pnl, /* Least significant 16 bits of PN */ + unsigned int pnh, /* Most significant 32 bits of PN */ + unsigned char *rc4key) +{ + unsigned int p1k[5]; + /* 16 bit numbers */ + unsigned int tsc0; + unsigned int tsc1; + unsigned int tsc2; + + unsigned int ppk0; + unsigned int ppk1; + unsigned int ppk2; + unsigned int ppk3; + unsigned int ppk4; + unsigned int ppk5; + + int i; + int j; + + tsc0 = (unsigned int)((pnh >> 16) & 0xffff); /* tsc0 is most significant */ + tsc1 = (unsigned int)(pnh & 0xffff); + tsc2 = (unsigned int)(pnl & 0xffff); /* tsc2 is least significant */ + + /* Phase 1, step 1 */ + p1k[0] = tsc1; + p1k[1] = tsc0; + p1k[2] = (unsigned int)(ta[0] + (ta[1]<< 8)); + p1k[3] = (unsigned int)(ta[2] + (ta[3]<< 8)); + p1k[4] = (unsigned int)(ta[4] + (ta[5]<< 8)); + + /* Phase 1, step 2 */ + for (i=0; i<8; i++) + { + j = (i & 1) << 1; + p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((key[1+j] << 8) + key[j])) & 0xffff )) & 0xffff; + p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((key[5+j] << 8) + key[4+j])) & 0xffff )) & 0xffff; + p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((key[9+j] << 8) + key[8+j])) & 0xffff )) & 0xffff; + p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((key[13+j]<< 8) + key[12+j])) & 0xffff )) & 0xffff; + p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((key[1+j]<< 8) + key[j]))) & 0xffff )) & 0xffff; + p1k[4] = (p1k[4] + i) & 0xffff; + } + + /* Phase 2, Step 1 */ + ppk0 = p1k[0]; + ppk1 = p1k[1]; + ppk2 = p1k[2]; + ppk3 = p1k[3]; + ppk4 = p1k[4]; + ppk5 = (p1k[4] + tsc2) & (65536-1); + + /* Phase2, Step 2 */ + ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((key[1]<<8) + key[0])) & 0xffff); + ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((key[3]<<8) + key[2])) & 0xffff); + ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((key[5]<<8) + key[4])) & 0xffff); + ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((key[7]<<8) + key[6])) & 0xffff); + ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((key[9]<<8) + key[8])) & 0xffff); + ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((key[11]<<8) + key[10])) & 0xffff); + + ppk0 = ppk0 + rotr1(ppk5 ^ ((key[13]<<8) + key[12])); + ppk1 = ppk1 + rotr1(ppk0 ^ ((key[15]<<8) + key[14])); + ppk2 = ppk2 + rotr1(ppk1); + ppk3 = ppk3 + rotr1(ppk2); + ppk4 = ppk4 + rotr1(ppk3); + ppk5 = ppk5 + rotr1(ppk4); + + /* Phase 2, Step 3 */ + rc4key[0] = (tsc2 >> 8) & 255; + rc4key[1] = (((tsc2 >> 8) & 255) | 0x20) & 0x7f; + rc4key[2] = tsc2 & 255; + rc4key[3] = ((ppk5 ^ ((key[1]<<8) + key[0])) >> 1) & 255; + + rc4key[4] = ppk0 & 255; + rc4key[5] = (ppk0 >> 8) & 255; + + rc4key[6] = ppk1 & 255; + rc4key[7] = (ppk1 >> 8) & 255; + + rc4key[8] = ppk2 & 255; + rc4key[9] = (ppk2 >> 8) & 255; + + rc4key[10] = ppk3 & 255; + rc4key[11] = (ppk3 >> 8) & 255; + + rc4key[12] = ppk4 & 255; + rc4key[13] = (ppk4 >> 8) & 255; + + rc4key[14] = ppk5 & 255; + rc4key[15] = (ppk5 >> 8) & 255; +} + + +void rc4( + unsigned char *key, + int key_length, + int cipherstream_length, + unsigned char *cipherstream); + +void rc4_encrypt( + unsigned char *key, + int key_length, + unsigned char *data, + int data_length, + unsigned char *ciphertext); + + +void xor_block(int length, unsigned char *a, unsigned char *b, unsigned char *out) +{ + int i; + for (i=0;i>1)&0x08) | ((val8>>3)&0x04) | ((val8>>5)&0x02) | ((val8>>7)&0x01) ) +#define CRC32_POLY 0x04c11db7 + +static unsigned int crc32_table[256]; + +void init_crc32_table(void) +{ + int i, j; + unsigned int c; + unsigned char *p=(unsigned char *)&c, *p1; + unsigned char k; + + c = 0x12340000; + + for (i = 0; i < 256; ++i) + { + k = REVERSE_BIT( (unsigned char)(i) ); + for (c = ((unsigned int)k) << 24, j = 8; j > 0; --j){ + c = (c & 0x80000000) ? ((c << 1) ^ CRC32_POLY) : (c << 1); + } + p1 = (unsigned char *)&crc32_table[i]; + + p1[0] = REVERSE_BIT(p[3]); + p1[1] = REVERSE_BIT(p[2]); + p1[2] = REVERSE_BIT(p[1]); + p1[3] = REVERSE_BIT(p[0]); + } +} + + +unsigned long crc32(unsigned char *buf, int len) +{ + unsigned char *p; + unsigned long crc; + + crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ + + for (p = buf; len > 0; ++p, --len) { + crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8); + } + + return ~crc; /* transmit complement, per CRC-32 spec */ +} + + +unsigned long crc32_frag(unsigned long crc, unsigned char *buf, int len) +{ + unsigned char *p; + + for (p = buf; len > 0; ++p, --len) { + crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8); + } + + return ~crc; /* transmit complement, per CRC-32 spec */ +} + +#if 0 +void appendICV(unsigned char *src, unsigned int len, unsigned char *dest) +{ + unsigned char CRC[4]; + + *((unsigned long *)CRC) = crc32(src,len); + *(unsigned char *)dest=*((unsigned char *)CRC+3); + *(unsigned char *)(dest+1)=*((unsigned char *)CRC+2); + *(unsigned char *)(dest+2)=*((unsigned char *)CRC+1); + *(unsigned char *)(dest+3)=*((unsigned char *)CRC); +} +#endif + + +void tkip_icv(unsigned char *picv, unsigned char *frag1, unsigned int frag1_len, + unsigned char *frag2,unsigned int frag2_len) +{ + unsigned int *pcrc; + unsigned int crc= 0xffffffff; + + pcrc = &crc; + if (frag1) + crc = crc32_frag(crc, frag1, frag1_len); + else + crc = ~crc; + if (frag2) + crc = crc32_frag(~crc, frag2, frag2_len); + +#if defined(_LITTLE_ENDIAN_) + *(unsigned char *)picv=*((unsigned char *)pcrc); + *(unsigned char *)(picv+1)=*((unsigned char *)pcrc+1); + *(unsigned char *)(picv+2)=*((unsigned char *)pcrc+2); + *(unsigned char *)(picv+3)=*((unsigned char *)pcrc+3); +#else + *(unsigned char *)picv=*((unsigned char *)pcrc+3); + *(unsigned char *)(picv+1)=*((unsigned char *)pcrc+2); + *(unsigned char *)(picv+2)=*((unsigned char *)pcrc+1); + *(unsigned char *)(picv+3)=*((unsigned char *)pcrc); +#endif +} + + +#ifdef _USE_DRAM_ +unsigned char *tx_cipherstream; +#else +__DRAM_IN_865X unsigned char tx_cipherstream[MAX_MESSAGE_LENGTH+1]; +#endif + +/*----------------------------------------------------------------------------- + TKIP Flow +1. Key Mixing (TTK key(128 bits), TA(48 bits), pnl(16 bits), pnh(32 bits) + ==>rc4 key +2. Using rc4 key to generate Ciphertext/Cipherstream. +3. Most of the time, we used frag1 to points to llc, frag2 to points to mpdu, + and frag3 to points to icv +------------------------------------------------------------------------------*/ +void tkip_encrypt( + struct rtl8192cd_priv *priv, unsigned char *pwlhdr, unsigned int hdrlen, + unsigned char *frag1, unsigned int frag1_len, + unsigned char *frag2, unsigned int frag2_len, + unsigned char *frag3, unsigned int frag3_len) +{ + unsigned char *ttkey = NULL; + unsigned char rc4key[16]; + union PN48 *ptsc48 = NULL; + unsigned short pnl; // 16 LSB + unsigned int pnh; // 32 MSB + unsigned int keyid = 0; + unsigned char *iv = pwlhdr + hdrlen; + struct stat_info *pstat = NULL; + unsigned char *ta = GET_MY_HWADDR; + unsigned char *ra; +#ifdef WDS + unsigned int to_fr_ds = (GetToDs(pwlhdr) << 1) | GetFrDs(pwlhdr); +#endif + + DEBUG_TRACE; + + ra = GetAddr1Ptr(pwlhdr); + pstat = get_stainfo(priv, ra); + +#ifdef WDS + if ( (to_fr_ds == 3) && pstat && (pstat->state & WIFI_WDS)) { + ttkey = GET_UNICAST_ENCRYP_KEY; + ptsc48 = GET_UNICAST_ENCRYP_PN; + keyid = pstat->keyid; + goto do_tkip_encrypt; + } +#endif + + if (OPMODE & WIFI_AP_STATE) + { + if (IS_MCAST(ra)) + { + ttkey = GET_GROUP_ENCRYP_KEY; + ptsc48 = GET_GROUP_ENCRYP_PN; + //keyid = 1; + keyid = priv->pmib->dot11GroupKeysTable.keyid;//use mib keyid + } + else + { + if (pstat == NULL) { + DEBUG_ERR("tx tkip pstat == NULL\n"); + return; + } + ttkey = GET_UNICAST_ENCRYP_KEY; + ptsc48 = GET_UNICAST_ENCRYP_PN; + keyid = 0; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + if (IS_MCAST(ra)) + { + ttkey = GET_GROUP_ENCRYP_KEY; + ptsc48 = GET_GROUP_ENCRYP_PN; + keyid = GET_ROOT(priv)->pmib->dot11GroupKeysTable.keyid; + } + else + { + if (pstat == NULL) { + DEBUG_ERR("tx tkip pstat == NULL\n"); + return; + } + ttkey = GET_UNICAST_ENCRYP_KEY; + ptsc48 = GET_UNICAST_ENCRYP_PN; + keyid = 0; + } + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + ttkey = GET_GROUP_ENCRYP_KEY; + ptsc48 = GET_GROUP_ENCRYP_PN; + keyid = 0; + } +#endif + + if ((ttkey == NULL) || (ptsc48 == NULL)) { + DEBUG_ERR("no encrypt key for TKIP due to ttkey=NULL or ptsc48=NULL\n"); + return; + } + +#ifdef WDS +do_tkip_encrypt: +#endif + pnl = get_pnl(ptsc48); + pnh = get_pnh(ptsc48); + + // below is for key mixing! + mix_key(ttkey, ta, pnl, pnh, rc4key); + + //okay, use rc4_encrypt go generate ciphertext. + rc4(rc4key, 16, (frag1_len + frag2_len + frag3_len), tx_cipherstream); + + // now, using cipherstream to xor all the plaintext! + rc4_frag_encrypt(frag1, frag1_len, frag2, frag2_len, frag3, frag3_len, tx_cipherstream); + + // Wa-oh...finally, let's fill in the IV field... + iv[0] = ptsc48->_byte_.TSC1; + iv[1] = (iv[0] | 0x20) & 0x7f; + iv[2] = ptsc48->_byte_.TSC0; + iv[3] = 0x20 | (keyid << 6); + iv[4] = ptsc48->_byte_.TSC2; + iv[5] = ptsc48->_byte_.TSC3; + iv[6] = ptsc48->_byte_.TSC4; + iv[7] = ptsc48->_byte_.TSC5; + + if (ptsc48->val48 == 0xffffffffffffULL) + ptsc48->val48 = 0; + else + ptsc48->val48++; +} + + +unsigned int tkip_decrypt(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo, unsigned int fr_len) +{ + union TSC48 tsc48; + unsigned char *da; + unsigned char *ta; + unsigned int keylen=0, hdr_len, pnh, crc; + unsigned short pnl; + unsigned char *ttkey = NULL; + unsigned char rc4key[16]; + unsigned char *pframe; + struct stat_info *pstat = NULL; + + pframe = get_pframe(pfrinfo); + da = pfrinfo->da; + hdr_len = pfrinfo->hdr_len; + + ta = GetAddr2Ptr(pframe); + pstat = get_stainfo(priv, ta); + + if (pstat) { +#ifdef WDS + if ((pfrinfo->to_fr_ds == 3) && (pstat->state & WIFI_WDS)) { + keylen = GET_UNICAST_ENCRYP_KEYLEN; + ttkey = GET_UNICAST_ENCRYP_KEY; + goto do_tkip_decrypt; + } +#endif + } + + if (OPMODE & WIFI_AP_STATE) + { + if (pstat == NULL) { + DEBUG_WARN("rx tkip pstat == NULL\n"); + return FALSE; + } + keylen = GET_UNICAST_ENCRYP_KEYLEN; + ttkey = GET_UNICAST_ENCRYP_KEY; + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + if (IS_MCAST(da)) + { + keylen = GET_GROUP_ENCRYP_KEYLEN; + ttkey = GET_GROUP_ENCRYP_KEY; + } + else + { + if (pstat == NULL) { + DEBUG_WARN("rx tkip pstat == NULL\n"); + return FALSE; + } + keylen = GET_UNICAST_ENCRYP_KEYLEN; + ttkey = GET_UNICAST_ENCRYP_KEY; + } + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + keylen = GET_GROUP_ENCRYP_KEYLEN; + ttkey = GET_GROUP_ENCRYP_KEY; + } +#endif + + if (keylen == 0) { + DEBUG_ERR("no descrypt key for TKIP due to keylen=0\n"); + return FALSE; + } +#ifdef WDS +do_tkip_decrypt: +#endif + tsc48._byte_.TSC1 = *(pframe + hdr_len + 0); + tsc48._byte_.TSC0 = *(pframe + hdr_len + 2); + tsc48._byte_.TSC2 = *(pframe + hdr_len + 4); + tsc48._byte_.TSC3 = *(pframe + hdr_len + 5); + tsc48._byte_.TSC4 = *(pframe + hdr_len + 6); + tsc48._byte_.TSC5 = *(pframe + hdr_len + 7); + pnl = get_pnl((union PN48 *)&tsc48); + pnh = get_pnh((union PN48 *)&tsc48); + + mix_key(ttkey, ta, pnl, pnh, rc4key); + + rc4_encrypt(rc4key, 16, pframe + hdr_len + 8, fr_len - hdr_len - 8, pframe + hdr_len + 8); + + // now, let's check if icv is correct! + crc = crc32(pframe + hdr_len + 8, fr_len - hdr_len - 8 - 4); + + crc = le32_to_cpu(crc); //crc is big endian located in the payload + if (memcmp((void *)&crc, (void *)(pframe + fr_len -4), 4)) + { + DEBUG_ERR("crc error!crc=%08X, vs %02X%02X%02X%02X\n", crc, + *(pframe + fr_len -4), + *(pframe + fr_len -3), + *(pframe + fr_len -2), + *(pframe + fr_len -1)); + return FALSE; + } + else + return TRUE; +} + + +void wep_encrypt(struct rtl8192cd_priv *priv, unsigned char *pwlhdr, unsigned int hdrlen, + unsigned char *frag1, unsigned int frag1_len, + unsigned char *frag2, unsigned int frag2_len, + unsigned char *frag3, unsigned int frag3_len, + int type) +{ + unsigned char *ra; + unsigned char *ttkey = NULL; + unsigned char rc4key[16]; + unsigned int keyid = 0; + unsigned char *iv = pwlhdr + hdrlen; + struct stat_info *pstat = NULL; + unsigned int *piv; + int keylen; +#ifdef WDS + unsigned int to_fr_ds = (GetToDs(pwlhdr) << 1) | GetFrDs(pwlhdr); +#endif + + DEBUG_TRACE; + + ra = GetAddr1Ptr(pwlhdr); + pstat = get_stainfo(priv, ra); + + if (pstat) { +#ifdef WDS + if ((to_fr_ds == 3) && (pstat->state & WIFI_WDS)) { +#ifdef CONFIG_RTL8186_KB + keyid = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + ttkey = priv->pmib->dot11DefaultKeysTable.keytype[keyid&3].skey; +#else + ttkey = GET_UNICAST_ENCRYP_KEY; + keyid = pstat->keyid; +#endif + goto do_encrypt; + } +#endif + } + + if (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm) // 1x enabled, get key from mapping table + { + if (OPMODE & WIFI_AP_STATE) + { + if (IS_MCAST(ra)) + { + ttkey = GET_GROUP_ENCRYP_KEY; + keyid = 0; + } + else + { + if (pstat == NULL) { + DEBUG_ERR("tx wep pstat == NULL\n"); + return; + } + ttkey = GET_UNICAST_ENCRYP_KEY; + keyid = 3; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + if (pstat == NULL) { + DEBUG_ERR("tx wep pstat == NULL\n"); + return; + } + ttkey = GET_UNICAST_ENCRYP_KEY; + keyid = 3; + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + ttkey = GET_GROUP_ENCRYP_KEY; + keyid = 0; + } +#endif + } + else + { + keyid = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + ttkey = priv->pmib->dot11DefaultKeysTable.keytype[keyid&3].skey; + } + +#ifdef WDS +do_encrypt: +#endif + + piv = (unsigned int *)GET_GROUP_ENCRYP_PN; + if (type == _WEP_40_PRIVACY_) + keylen = 8; + else + keylen = 16; + + *((unsigned int *)iv) = cpu_to_le32(((*piv) & 0x00FFFFFF) |((keyid&0x03)<<30)); + *piv = *piv + 1; + + memcpy(rc4key, iv, 3); + memcpy(&rc4key[3], ttkey, keylen-3); + +#ifdef _DEBUG_RTL8192CD_ +{ + char tmpbuf[400], tmp1[100]; + int i; + + sprintf(tmpbuf, "wep encrypt: iv=%d, keyid=%d, type=%s, key=", + (le32_to_cpup((u32 *)iv) & 0xFFFFFF), keyid, + (type==_WEP_40_PRIVACY_ ? "64b" : "128b")); + + for (i=0; ihdr_len; + memcpy(iv, pframe+hdr_len, sizeof(iv)); + + if (type == _WEP_40_PRIVACY_) + keylen = 8; + else + keylen = 16; + + pstat = get_stainfo(priv, ta); + + if (pstat) { +#ifdef WDS + if ((pfrinfo->to_fr_ds == 3) && (pstat->state & WIFI_WDS)) { + ttkey = GET_UNICAST_ENCRYP_KEY; + goto do_decrypt; + } +#endif + } + + if (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm) // 1x enabled, get key from mapping table + { + if (OPMODE & WIFI_AP_STATE) + { + if (using_keymap) { + if (pstat == NULL) { + DEBUG_ERR("rx wep pstat == NULL\n"); + return FALSE; + } + ttkey = GET_UNICAST_ENCRYP_KEY; + } + else if ((iv[3] & 0xC0) == 0) // key id=0, use group key + ttkey = GET_GROUP_ENCRYP_KEY; + else if ((iv[3] & 0xC0) == 0xC0) + { + if (pstat == NULL) { + DEBUG_ERR("rx wep pstat == NULL\n"); + return FALSE; + } + ttkey = GET_UNICAST_ENCRYP_KEY; + } + else + { + DEBUG_ERR("rx wep keyid != 0 and 3 \n"); + return FALSE; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) { + if ((iv[3] & 0xC0) == 0) // key id=0, use group key + ttkey = GET_GROUP_ENCRYP_KEY; + else if ((iv[3] & 0xC0) == 0xC0) + { + if (pstat == NULL) { + DEBUG_ERR("rx wep pstat == NULL\n"); + return FALSE; + } + ttkey = GET_UNICAST_ENCRYP_KEY; + } + else + { + DEBUG_ERR("rx wep keyid != 0 and 3 \n"); + return FALSE; + } + } + else if (OPMODE & WIFI_ADHOC_STATE) + ttkey = GET_GROUP_ENCRYP_KEY; +#endif + } + else // default key + ttkey = priv->pmib->dot11DefaultKeysTable.keytype[(iv[3]>>6) & 3].skey; + +#ifdef WDS +do_decrypt: +#endif + + memcpy(rc4key, iv, 3); + memcpy(&rc4key[3], ttkey, keylen-3); + +#ifdef _DEBUG_RTL8192CD_ +{ + char tmpbuf[400], tmp1[100]; + int i; + + sprintf(tmpbuf, "wep decript: iv=%d, keyid=%d, type=%s, key=", + (le32_to_cpup((u32 *)iv) & 0xFFFFFF), (int)((iv[3]>>6)&3), + (type==_WEP_40_PRIVACY_ ? "64b" : "128b")); + + for (i=0; istate & WIFI_WDS)) +#ifdef __DRAYTEK_OS__ + mickey = GET_UNICAST_TKIP_MIC2_KEY; +#else + mickey = GET_UNICAST_TKIP_MIC1_KEY; +#endif + else +#endif + mickey = GET_UNICAST_TKIP_MIC2_KEY; + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + if (IS_MCAST(da)) + { + keylen = GET_GROUP_MIC_KEYLEN; + mickey = GET_GROUP_TKIP_MIC1_KEY; + } + else + { + if (pstat == NULL) { + DEBUG_ERR("rx mic pstat == NULL\n"); + return FALSE; + } + + keylen = GET_UNICAST_MIC_KEYLEN; + mickey = GET_UNICAST_TKIP_MIC1_KEY; + } + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + keylen = GET_GROUP_MIC_KEYLEN; + mickey = GET_GROUP_TKIP_MIC1_KEY; + } +#endif + + if (keylen == 0) + { + DEBUG_ERR("no mic padding for TKIP due to keylen=0\n"); + return FALSE; + } + memcpy((void *)hdr, (void *)da, WLAN_ADDR_LEN); + memcpy((void *)(hdr + WLAN_ADDR_LEN), (void *)sa, WLAN_ADDR_LEN); + hdr[12] = priority; + hdr[13] = hdr[14] = hdr[15] = 0; + + pbuf[len] = 0x5a; /* Insert padding */ + pbuf[len+1] = 0x00; + pbuf[len+2] = 0x00; + pbuf[len+3] = 0x00; + pbuf[len+4] = 0x00; + pbuf[len+5] = 0x00; + pbuf[len+6] = 0x00; + pbuf[len+7] = 0x00; + + num_blocks = (16 + len + 5)/4; // 8 is for snap_llc length = 8 + if ((16 + len + 5) & (4-1)) + num_blocks++; + +#ifndef NOT_RTK_BSP + if ((priv->pshare->have_hw_mic) && + !(priv->pmib->dot11StationConfigEntry.swTkipMic)) + { + register unsigned long int l,r; + + michael(priv, mickey, hdr, pbuf, pbuf+8, (num_blocks << 2), tkipmic, 0); + + if (no_wait) + return FALSE; + + do { + delay_us(60); + } while ((*(volatile unsigned int *)GDMAISR & GDMA_COMPIP) == 0); + + l = *(volatile unsigned int *)GDMAICVL; + r = *(volatile unsigned int *)GDMAICVR; + + tkipmic[0] = (unsigned char)(l & 0xff); + tkipmic[1] = (unsigned char)((l >> 8) & 0xff); + tkipmic[2] = (unsigned char)((l >> 16) & 0xff); + tkipmic[3] = (unsigned char)((l >> 24) & 0xff); + tkipmic[4] = (unsigned char)(r & 0xff); + tkipmic[5] = (unsigned char)((r >> 8) & 0xff); + tkipmic[6] = (unsigned char)((r >> 16) & 0xff); + tkipmic[7] = (unsigned char)((r >> 24) & 0xff); + } + else +#endif // NOT_RTK_BSP + michael(priv, mickey, hdr, pbuf, pbuf+8, (num_blocks << 2), tkipmic, 0); + + return TRUE; +} + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_tx.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_tx.c new file mode 100755 index 000000000..95a935e31 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_tx.c @@ -0,0 +1,12758 @@ +/* + * TX handle routines + * + * $Id: 8192cd_tx.c,v 1.39.2.31 2011/01/19 15:20:34 victoryman Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_TX_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#ifdef __DRAYTEK_OS__ +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_hw.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + +#if !defined(__KERNEL__) && !defined(__ECOS) +#include "./sys-support.h" +#endif + +#ifdef RTL8192CD_VARIABLE_USED_DMEM +#include "./8192cd_dmem.h" +#endif + +#if defined(CONFIG_RTL_WAPI_SUPPORT) +#include "wapiCrypto.h" +#endif +#ifdef CONFIG_RTL_VLAN_8021Q +#include +#endif + +#ifdef CONFIG_RTL867X_VLAN_MAPPING +#include "../../re_vlan.h" +#endif + +#ifdef PERF_DUMP +#include "romeperf.h" +#endif + +struct rtl_arphdr +{ + //for corss platform + __be16 ar_hrd; /* format of hardware address */ + __be16 ar_pro; /* format of protocol address */ + unsigned char ar_hln; /* length of hardware address */ + unsigned char ar_pln; /* length of protocol address */ + __be16 ar_op; /* ARP opcode (command) */ +}; + +#define AMSDU_TX_DESC_TH 2 // A-MSDU tx desc threshold, A-MSDU will be + // triggered when more than this threshold packet in hw queue + +#define RET_AGGRE_BYPASS 0 +#define RET_AGGRE_ENQUE 1 +#define RET_AGGRE_DESC_FULL 2 + +#define TX_NORMAL 0 +#define TX_NO_MUL2UNI 1 +#define TX_AMPDU_BUFFER_SIG 2 +#define TX_AMPDU_BUFFER_FIRST 3 +#define TX_AMPDU_BUFFER_MID 4 +#define TX_AMPDU_BUFFER_LAST 5 + +#if 0//def CONFIG_RTL_STP +extern unsigned char STPmac[6]; +#endif + +#ifdef CONFIG_RTL_VLAN_8021Q +extern int linux_vlan_enable; +extern linux_vlan_ctl_t *vlan_ctl_p; +#endif + +#ifdef RTL_MANUAL_EDCA +unsigned int PRI_TO_QNUM(struct rtl8192cd_priv *priv, int priority) +{ + if (priv->pmib->dot11QosEntry.ManualEDCA) { + return priv->pmib->dot11QosEntry.TID_mapping[priority]; + } + else { + if ((priority == 0) || (priority == 3)) { + if (!((OPMODE & WIFI_STATION_STATE) && GET_STA_AC_BE_PARA.ACM)) + return BE_QUEUE; + else + return BK_QUEUE; + } else if ((priority == 7) || (priority == 6)) { + if (!((OPMODE & WIFI_STATION_STATE) && GET_STA_AC_VO_PARA.ACM)) { + return VO_QUEUE; + } else { + if (!GET_STA_AC_VI_PARA.ACM) + return VI_QUEUE; + else if (!GET_STA_AC_BE_PARA.ACM) + return BE_QUEUE; + else + return BK_QUEUE; + } + } else if ((priority == 5) || (priority == 4)) { + if (!((OPMODE & WIFI_STATION_STATE) && GET_STA_AC_VI_PARA.ACM)) { + return VI_QUEUE; + } else { + if (!GET_STA_AC_BE_PARA.ACM) + return BE_QUEUE; + else + return BK_QUEUE; + } + } else { + return BK_QUEUE; + } + } +} +#endif + + +#if !defined(CONFIG_RTL_8676HWNAT) && defined(CONFIG_RTL8672) && !defined(CONFIG_RTL8686) && !defined(CONFIG_RTL8685) +extern int check_IGMP_report(struct sk_buff *skb); +extern int check_wlan_mcast_tx(struct sk_buff *skb); +#endif + +#define BG_TABLE_SIZE 21 +#define MCS_40M_TABLE_SIZE 18 +#define MCS_20M_TABLE_SIZE 22 + +unsigned short BG_TABLE[2][BG_TABLE_SIZE] = {{73,68,63,57,52,47,42,37,31,30,27,25,23,22,20,18,16,14,11,9,8}, + {108,108,108,108,108,108,108,108,108,108,108,108,72,72,48,48,36,12,11,11,4}}; +unsigned short MCS_40M_TABLE[2][MCS_40M_TABLE_SIZE] = {{73,68,63,57,53,45,39,37,31,29,28,26,25,23,21,19,17,12}, + {7,7,7,7,7,7,7,7,5,4,4,4,2,2,2,0,0,0}}; +unsigned short MCS_20M_TABLE[2][MCS_20M_TABLE_SIZE]={{73,68,65,60,55,50,45,40,31,32,27,26,24,22,21,19,18,16,14,11,9,8}, + {7,7,7,7,7,7,7,7,7,6,5,5,5,4,3,3,3,2,3,1,0,0}}; + +static int tkip_mic_padding(struct rtl8192cd_priv *priv, + unsigned char *da, unsigned char *sa, unsigned char priority, + unsigned char *llc,struct sk_buff *pskb, struct tx_insn* txcfg); + +#ifdef CONFIG_PCI_HCI +static int rtl8192cd_tx_queueDsr(struct rtl8192cd_priv *priv, unsigned int txRingIdx); +static void rtl8192cd_tx_restartQueue(struct rtl8192cd_priv *priv); +#endif + +__MIPS16 +__IRAM_IN_865X +int __rtl8192cd_start_xmit(struct sk_buff*skb, struct net_device *dev, int tx_fg); + +#ifdef TX_SCATTER +extern struct sk_buff *copy_skb(struct sk_buff *skb); +#endif + + + +unsigned int get_tx_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + if (pstat->sta_in_firmware == 1) { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + if (CHIP_VER_92X_SERIES(priv) && (priv->pmib->dot11RFEntry.txbf == 1)) + check_txrate_by_reg(priv, pstat); +#endif + return pstat->current_tx_rate; + } else { + // firmware does not keep the aid ... + //use default rate instead + // eric_8814 ?? VHT rates ?? 1SS ?? 2SS ?? 3SS ?? + if (pstat->ht_cap_len) { // is N client + if (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40) {//(pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))){ //40Mhz + int i = 0; + pstat->current_tx_rate = MCS_40M_TABLE[1][MCS_40M_TABLE_SIZE-1] + HT_RATE_ID; + for (i=1; i < MCS_40M_TABLE_SIZE; i++) { + if (pstat->rssi > MCS_40M_TABLE[0][i]){ + pstat->current_tx_rate = MCS_40M_TABLE[1][i-1] + HT_RATE_ID; + break; + } + } + return pstat->current_tx_rate; + } else { // 20Mhz + int i = 0; + pstat->current_tx_rate = MCS_20M_TABLE[1][MCS_20M_TABLE_SIZE-1] + HT_RATE_ID; + for (i=1; i < MCS_20M_TABLE_SIZE; i++) { + if (pstat->rssi > MCS_20M_TABLE[0][i]){ + pstat->current_tx_rate = MCS_20M_TABLE[1][i-1] + HT_RATE_ID; + break; + } + } + return pstat->current_tx_rate; + } + return pstat->current_tx_rate; + + } +#ifdef RTK_AC_SUPPORT + else if (pstat->vht_cap_len) { // is N client + if (pstat->tx_bw == HT_CHANNEL_WIDTH_80) {//(pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))){ //40Mhz + int i = 0; + pstat->current_tx_rate = MCS_40M_TABLE[1][MCS_40M_TABLE_SIZE-1] + VHT_RATE_ID; + for (i=1; i < MCS_40M_TABLE_SIZE; i++) { + if (pstat->rssi > MCS_40M_TABLE[0][i]){ + pstat->current_tx_rate = MCS_40M_TABLE[1][i-1] + VHT_RATE_ID; + break; + } + } + return pstat->current_tx_rate; + } else { // 20Mhz + int i = 0; + pstat->current_tx_rate = MCS_20M_TABLE[1][MCS_20M_TABLE_SIZE-1] + VHT_RATE_ID; + for (i=1; i < MCS_20M_TABLE_SIZE; i++) { + if (pstat->rssi > MCS_20M_TABLE[0][i]){ + pstat->current_tx_rate = MCS_20M_TABLE[1][i-1] + VHT_RATE_ID; + break; + } + } + return pstat->current_tx_rate; + } + return pstat->current_tx_rate; + + } +#endif + else { // is BG client + int i = 0; + pstat->current_tx_rate = BG_TABLE[1][BG_TABLE_SIZE-1]; // eric_8814 ?? conflict with HT RATES ?? + for (i = 0; i < BG_TABLE_SIZE; i++) { + if (pstat->rssi > BG_TABLE[0][i]){ + pstat->current_tx_rate = BG_TABLE[1][i-1]; + break; + } + } + return pstat->current_tx_rate; + } + + } + +} + + +unsigned int get_lowest_tx_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat, + unsigned int tx_rate) +{ + unsigned int lowest_tx_rate; + + if (is_auto_rate(priv , pstat)) + { + lowest_tx_rate = find_rate(priv, pstat, 0, 0); + } + else + lowest_tx_rate = tx_rate; + + return lowest_tx_rate; +} + + +__MIPS16 +__IRAM_IN_865X +void assign_wlanseq(struct rtl8192cd_hw *phw, unsigned char *pframe, struct stat_info *pstat, struct wifi_mib *pmib +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , unsigned char is_11s +#endif + ) +{ +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + u16 seq; +#endif + +#ifdef WIFI_WMM + unsigned char qosControl[2]; + int tid; + + if (is_qos_data(pframe)) { + memcpy(qosControl, GetQosControl(pframe), 2); + tid = qosControl[0] & 0x07; + + if (pstat) { + SetSeqNum(pframe, pstat->AC_seq[tid]); + pstat->AC_seq[tid] = (pstat->AC_seq[tid] + 1) & 0xfff; + } + else { +// SetSeqNum(pframe, phw->AC_seq[tid]); +// phw->AC_seq[tid] = (phw->AC_seq[tid] + 1) & 0xfff; +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + if (is_11s) + { + SetSeqNum(pframe, phw->seq); + phw->seq = (phw->seq + 1) & 0xfff; + } + else +#endif + printk("Invalid seq num setting for Multicast or Broadcast pkt!!\n"); + } + + { + if ((tid == 7) || (tid == 6)) + phw->VO_pkt_count++; + else if ((tid == 5) || (tid == 4)) + phw->VI_pkt_count++; + else if ((tid == 2) || (tid == 1)) + phw->BK_pkt_count++; +#ifdef WMM_VIBE_PRI + else + phw->BE_pkt_count++; +#endif + } + } + else +#endif + { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + seq = atomic_inc_return(&phw->seq); + seq = seq & 0x0fff; + SetSeqNum(pframe, seq); +#elif defined(CONFIG_PCI_HCI) + SetSeqNum(pframe, phw->seq); + phw->seq = (phw->seq + 1) & 0xfff; +#endif + } +} + + +#ifdef CONFIG_RTK_MESH +static unsigned int get_skb_priority3(struct rtl8192cd_priv *priv, struct sk_buff *skb, int is_11s, struct stat_info *pstat) +#else +__MIPS16 __IRAM_IN_865X unsigned int get_skb_priority(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat) +#endif +{ + unsigned int pri=0, parsing=0; + unsigned char protocol[2]; + +#ifdef WIFI_WMM + if (QOS_ENABLE) { + parsing = 1; +#ifdef CONFIG_PCI_HCI + if(pstat && !pstat->QosEnabled) + parsing = 0; +#endif + } +#endif + + if (parsing) { +#if defined(CONFIG_RTK_VLAN_SUPPORT) ||defined(CONFIG_RTL_VLAN_SUPPORT) + if (skb->cb[0]) + pri = skb->cb[0]; + else +#endif + { + protocol[0] = skb->data[12]; + protocol[1] = skb->data[13]; + + if ((protocol[0] == 0x08) && (protocol[1] == 0x00)) + { +#ifdef CONFIG_RTK_MESH + if(is_11s & RELAY_11S) + { + pri = (skb->data[31] & 0xe0) >> 5; + } + else +#endif + { +#if defined(CONFIG_SDIO_HCI) && defined(TX_SCATTER) + pri = (get_skb_data_u8(skb, 15) & 0xe0) >> 5; +#else + pri = (skb->data[15] & 0xe0) >> 5; +#endif + } + } +#ifndef NOT_RTK_BSP + else if ((skb->cb[0]>0) && (skb->cb[0]<8)) // Ethernet driver will parse priority and put in cb[0] + pri = skb->cb[0]; +#endif + else + pri = 0; + } + +#ifdef CLIENT_MODE + if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) { + if (GET_STA_AC_VO_PARA.ACM) { + if (!GET_STA_AC_VI_PARA.ACM) + pri = 5; + else if (!GET_STA_AC_BE_PARA.ACM) + pri = 0; + else + pri = 1; + } else if (GET_STA_AC_VI_PARA.ACM) { + if (!GET_STA_AC_BE_PARA.ACM) + pri = 0; + else + pri = 1; + } else if (GET_STA_AC_BE_PARA.ACM) { + pri = 1; // DSCP_BK tag = 1; + } + } +#endif + skb->cb[1] = pri; + + return pri; + } + else { + // default is no priority + skb->cb[1] = 0; + return 0; + } +} + + +#ifdef CONFIG_RTK_MESH +#define get_skb_priority(priv, skb, pstat) get_skb_priority3(priv, skb, 0, pstat) +#endif + +#ifdef CONFIG_PCI_HCI +static int dz_queue(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct sk_buff *pskb) +{ + unsigned int ret; + + if (pstat) + { + if(0 == pstat->expire_to) + return FALSE; +#if defined(WIFI_WMM) && defined(WMM_APSD) + if ((QOS_ENABLE) && (APSD_ENABLE) && (pstat->QosEnabled) && (pstat->apsd_bitmap & 0x0f)) { + int pri = 0; + + pri = get_skb_priority(priv, pskb, pstat); + + if (((pri == 7) || (pri == 6)) && (pstat->apsd_bitmap & 0x01)) { + ret = enque(priv, &(pstat->VO_dz_queue->head), &(pstat->VO_dz_queue->tail), + (unsigned long)(pstat->VO_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE, (void *)pskb); + if (ret) + DEBUG_INFO("enque VO pkt\n"); + } + else if (((pri == 5) || (pri == 4)) && (pstat->apsd_bitmap & 0x02)) { + ret = enque(priv, &(pstat->VI_dz_queue->head), &(pstat->VI_dz_queue->tail), + (unsigned long)(pstat->VI_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE, (void *)pskb); + if (ret) + DEBUG_INFO("enque VI pkt\n"); + } + else if (((pri == 0) || (pri == 3)) && (pstat->apsd_bitmap & 0x08)) { + ret = enque(priv, &(pstat->BE_dz_queue->head), &(pstat->BE_dz_queue->tail), + (unsigned long)(pstat->BE_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE, (void *)pskb); + if (ret) + DEBUG_INFO("enque BE pkt\n"); + } + else if (pstat->apsd_bitmap & 0x04) { + ret = enque(priv, &(pstat->BK_dz_queue->head), &(pstat->BK_dz_queue->tail), + (unsigned long)(pstat->BK_dz_queue->pSkb), NUM_APSD_TXPKT_QUEUE, (void *)pskb); + if (ret) + DEBUG_INFO("enque BK pkt\n"); + } + else + goto legacy_ps; + + if (!pstat->apsd_pkt_buffering) + pstat->apsd_pkt_buffering = 1; + + if (ret == FALSE) { + DEBUG_ERR("sleep Q full for priority = %d!\n", pri); + return CONGESTED; + } + return TRUE; + } + else +legacy_ps: +#endif + if (pstat->dz_queue.qlendz_queue, pskb); + return TRUE; + } + } + else { // Multicast or Broadcast + ret = enque(priv, &(priv->dz_queue.head), &(priv->dz_queue.tail), + (unsigned long)(priv->dz_queue.pSkb), NUM_TXPKT_QUEUE, (void *)pskb); + if (ret == TRUE) { + if (!priv->pkt_in_dtimQ) + priv->pkt_in_dtimQ = 1; + return TRUE; + } + } + + return FALSE; +} +#endif // CONFIG_PCI_HCI + + +/* Function to process different situations in TX flow */ +/* ====================================================================== */ +#define TX_PROCEDURE_CTRL_STOP 0 +#define TX_PROCEDURE_CTRL_CONTINUE 1 +#define TX_PROCEDURE_CTRL_SUCCESS 2 + +#ifdef WDS +static int rtl8192cd_tx_wdsDevProc(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct net_device **dev_p, + struct net_device **wdsDev_p, struct tx_insn *txcfg) +{ + struct stat_info *pstat; + + txcfg->wdsIdx = getWdsIdxByDev(priv, *dev_p); + if (txcfg->wdsIdx < 0) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: getWdsIdxByDev() fail!\n"); + goto free_and_stop; + } + + if (!netif_running(priv->dev)) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't send WDS packet due to wlan interface is down!\n"); + goto free_and_stop; + } + pstat = get_stainfo(priv, priv->pmib->dot11WdsInfo.entry[txcfg->wdsIdx].macAddr); + if (NULL == pstat) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: %s: get_stainfo() for wds failed [%d]!\n", (char *)__FUNCTION__, txcfg->wdsIdx); + goto free_and_stop; + } + if (pstat->current_tx_rate==0) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't send packet due to tx rate is not supported in peer WDS AP!\n"); + goto free_and_stop; + } + *wdsDev_p = *dev_p; + *dev_p = priv->dev; + + /* Reply caller function : Continue process */ + return TX_PROCEDURE_CTRL_CONTINUE; + +free_and_stop: /* Free current packet and stop TX process */ + + rtl_kfree_skb(priv,skb,_SKB_TX_); + + /* Reply caller function : STOP process */ + return TX_PROCEDURE_CTRL_STOP; +} +#endif + + +#ifdef CLIENT_MODE +static int rtl8192cd_tx_clientMode(struct rtl8192cd_priv *priv, struct sk_buff **pskb) +{ + struct sk_buff *skb=*pskb; + int DontEnterNat25=0; + + { +#ifdef RTK_BR_EXT + int res, is_vlan_tag=0, i, do_nat25=1; + unsigned short vlan_hdr=0; + int lltd_flag=0; + + if (!priv->pmib->wscEntry.wsc_enable) +#ifdef MULTI_MAC_CLONE + if (mac_clone_handle_frame(priv, skb)) { + /*if STAs number exceed max macclone support number then let it run nat25 path*/ + ACTIVE_ID = 0; + //priv->ext_stats.tx_drops++; + //DEBUG_ERR("TX DROP: exceed max clone address!\n"); + //goto free_and_stop; + } +#else + mac_clone_handle_frame(priv, skb); + if(priv->pmib->ethBrExtInfo.macclone_enable && priv->macclone_completed){ + if(!memcmp(skb->data+ETH_ALEN, GET_MY_HWADDR, ETH_ALEN)) { + DontEnterNat25=1; + } + } +#endif + if ((!priv->pmib->ethBrExtInfo.nat25_disable && DontEnterNat25==0) +#ifdef MULTI_MAC_CLONE + && ((ACTIVE_ID == 0) || (ACTIVE_ID > 0 && priv->pshare->mclone_sta[ACTIVE_ID-1].usedStaAddrId != 0xff))//(ACTIVE_ID == 0)//change for wifi-sta +#endif + ) + { + if (*((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_8021Q)) { + is_vlan_tag = 1; + vlan_hdr = *((unsigned short *)(skb->data+MACADDRLEN*2+2)); + for (i=0; i<6; i++) + *((unsigned short *)(skb->data+MACADDRLEN*2+2-i*2)) = *((unsigned short *)(skb->data+MACADDRLEN*2-2-i*2)); + skb_pull(skb, 4); + } + + + if ((*((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_IP)) && !IS_MCAST(skb->data)) { + if (memcmp(priv->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN)) { + if ((priv->scdb_entry = (struct nat25_network_db_entry *)scdb_findEntry(priv, + skb->data+MACADDRLEN, skb->data+WLAN_ETHHDR_LEN+12)) != NULL) { + memcpy(priv->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN); + memcpy(priv->scdb_ip, skb->data+WLAN_ETHHDR_LEN+12, 4); + priv->scdb_entry->ageing_timer = jiffies; + do_nat25 = 0; + } + } + else { + if (priv->scdb_entry) { + priv->scdb_entry->ageing_timer = jiffies; + do_nat25 = 0; + } + else { + memset(priv->scdb_mac, 0, MACADDRLEN); + memset(priv->scdb_ip, 0, 4); + } + } + } + + if (*((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(0x88d9)) { + if(skb->data[0] & 0x1) + { + do_nat25=0; + lltd_flag=1; + } + } + + if (do_nat25) + { + if (nat25_db_handle(priv, skb, NAT25_CHECK) == 0) { + struct sk_buff *newskb; + + if (is_vlan_tag) { + skb_push(skb, 4); + for (i=0; i<6; i++) + *((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2)); + *((unsigned short *)(skb->data+MACADDRLEN*2)) = __constant_htons(ETH_P_8021Q); + *((unsigned short *)(skb->data+MACADDRLEN*2+2)) = vlan_hdr; + } + + newskb = skb_copy(skb, GFP_ATOMIC); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: skb_copy fail!\n"); + goto free_and_stop; + } + dev_kfree_skb_any(skb); + *pskb = skb = newskb; + if (is_vlan_tag) { + vlan_hdr = *((unsigned short *)(skb->data+MACADDRLEN*2+2)); + for (i=0; i<6; i++) + *((unsigned short *)(skb->data+MACADDRLEN*2+2-i*2)) = *((unsigned short *)(skb->data+MACADDRLEN*2-2-i*2)); + skb_pull(skb, 4); + } + } + + res = nat25_db_handle(priv, skb, NAT25_INSERT); + if (res < 0) { + if (res == -2) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: nat25_db_handle fail!\n"); + goto free_and_stop; + } + // we just print warning message and let it go + DEBUG_WARN("nat25_db_handle INSERT fail!\n"); + } + } + + if(lltd_flag != 1) + { + memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR, MACADDRLEN); + } + + if (is_vlan_tag) { + skb_push(skb, 4); + for (i=0; i<6; i++) + *((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2)); + *((unsigned short *)(skb->data+MACADDRLEN*2)) = __constant_htons(ETH_P_8021Q); + *((unsigned short *)(skb->data+MACADDRLEN*2+2)) = vlan_hdr; + } + } + else{ + + /*even nat25 is disabled, we still do nat25 for bridge's ip/mac*/ + if (!memcmp(skb->data+MACADDRLEN, priv->br_mac, MACADDRLEN)) { + unsigned short ethtype = *((unsigned short *)(skb->data+MACADDRLEN*2)); + i = 0; + if(ethtype == __constant_htons(ETH_P_IP)) { + i = 12; + } + else if(ethtype == __constant_htons(ETH_P_ARP)) { + i= 14; + } + + if(i) { + memcpy(priv->br_ip, skb->data+WLAN_ETHHDR_LEN+i, 4); + res = nat25_db_handle(priv, skb, NAT25_INSERT); + if (res < 0) { + if (res == -2) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: nat25_db_handle fail!\n"); + goto free_and_stop; + } + // we just print warning message and let it go + DEBUG_WARN("nat25_db_handle INSERT fail!\n"); + } + memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR, MACADDRLEN); + } + } + +#ifdef TX_SUPPORT_IPV6_MCAST2UNI + if (*((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_8021Q)) { + is_vlan_tag = 1; + } + + if(is_vlan_tag){ + if(ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A_VALN(skb->data)){ + memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR, MACADDRLEN); + } + }else + { + if(ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A(skb->data)){ + memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR, MACADDRLEN); + } + } +#endif + } + + + + // check if SA is equal to our MAC + if (memcmp(skb->data+MACADDRLEN, GET_MY_HWADDR, MACADDRLEN)) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: untransformed frame SA:%02X%02X%02X%02X%02X%02X!\n", + skb->data[6],skb->data[7],skb->data[8],skb->data[9],skb->data[10],skb->data[11]); + goto free_and_stop; + } +#endif // RTK_BR_EXT + } + + /* Reply caller function : Continue process */ + return TX_PROCEDURE_CTRL_CONTINUE; + +#ifdef RTK_BR_EXT +free_and_stop: /* Free current packet and stop TX process */ + + rtl_kfree_skb(priv, skb, _SKB_TX_); + +//stop_proc: + /* Reply caller function : STOP process */ + return TX_PROCEDURE_CTRL_STOP; +#endif + +} +#endif // CLIENT_MODE + + +#ifdef GBWC +static int rtl8192cd_tx_gbwc(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct sk_buff *skb) +{ + if (((priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_MAC_INNER) && (pstat->GBWC_in_group)) || + ((priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_MAC_OUTTER) && !(pstat->GBWC_in_group)) || + (priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_IF_TX) || + (priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_LIMIT_IF_TRX)) { + if ((priv->GBWC_tx_count + skb->len) > ((priv->pmib->gbwcEntry.GBWCThrd_tx * 1024 / 8) / (100 / GBWC_TO))) { + // over the bandwidth + if (priv->GBWC_consuming_Q) { + // in rtl8192cd_GBWC_timer context + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: BWC bandwidth over!\n"); + rtl_kfree_skb(priv, skb, _SKB_TX_); + } + else { + // normal Tx path + int ret = enque(priv, &(priv->GBWC_tx_queue.head), &(priv->GBWC_tx_queue.tail), + (unsigned long)(priv->GBWC_tx_queue.pSkb), NUM_TXPKT_QUEUE, (void *)skb); + if (ret == FALSE) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: BWC tx queue full!\n"); + rtl_kfree_skb(priv, skb, _SKB_TX_); + } + } + goto stop_proc; + } + else { + // not over the bandwidth + if (CIRC_CNT(priv->GBWC_tx_queue.head, priv->GBWC_tx_queue.tail, NUM_TXPKT_QUEUE) && + !priv->GBWC_consuming_Q) { + // there are already packets in queue, put in queue too for order + int ret = enque(priv, &(priv->GBWC_tx_queue.head), &(priv->GBWC_tx_queue.tail), + (unsigned long)(priv->GBWC_tx_queue.pSkb), NUM_TXPKT_QUEUE, (void *)skb); + if (ret == FALSE) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: BWC tx queue full!\n"); + rtl_kfree_skb(priv, skb, _SKB_TX_); + } + goto stop_proc; + } + else { + // can transmit directly + priv->GBWC_tx_count += skb->len; + } + } + } + + /* Reply caller function : Continue process */ + return TX_PROCEDURE_CTRL_CONTINUE; + +stop_proc: + /* Reply caller function : STOP process */ + return TX_PROCEDURE_CTRL_STOP; +} +#endif + + +#ifdef TX_SHORTCUT +static int rtl8192cd_tx_tkip(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info*pstat, struct tx_insn *txcfg) +{ + struct wlan_ethhdr_t *pethhdr; + struct llc_snap *pllc_snap = NULL; + unsigned char * da; + pethhdr = (struct wlan_ethhdr_t *)(skb->data - WLAN_ETHHDR_LEN); + + da = pethhdr->daddr; +#ifdef MCAST2UI_REFINE + memcpy(pethhdr->daddr, &skb->cb[10], 6); +#endif + +#ifdef A4_STA + if(pstat && (pstat->state & WIFI_A4_STA)) { + da = GetAddr3Ptr(txcfg->phdr); + } +#endif + + if(txcfg->llc) { + pllc_snap = (struct llc_snap *)((UINT8 *)(txcfg->phdr) + txcfg->hdr_len + txcfg->iv); + } + +#ifdef WIFI_WMM + if ((tkip_mic_padding(priv, da, pethhdr->saddr, ((QOS_ENABLE) && (pstat) && (pstat->QosEnabled))?skb->cb[1]:0, (UINT8 *)pllc_snap, + skb, txcfg)) == FALSE) +#else + if ((tkip_mic_padding(priv, da, pethhdr->saddr, 0, (UINT8 *)pllc_snap, + skb, txcfg)) == FALSE) +#endif + { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Tkip mic padding fail!\n"); + rtl_kfree_skb(priv, skb, _SKB_TX_); + release_wlanllchdr_to_poll(priv, txcfg->phdr); + goto stop_proc; + } + skb_put((struct sk_buff *)txcfg->pframe, 8); + txcfg->fr_len += 8; // for Michael padding. + + /* Reply caller function : Continue process */ + return TX_PROCEDURE_CTRL_CONTINUE; + +stop_proc: + /* Reply caller function : STOP process */ + return TX_PROCEDURE_CTRL_STOP; +} + + +#ifdef CONFIG_PCI_HCI +__MIPS16 +__IRAM_IN_865X +int get_tx_sc_index(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char *hdr) +{ + struct tx_sc_entry *ptxsc_entry; + int i; + + ptxsc_entry = pstat->tx_sc_ent; + + for (i=0; istate & WIFI_WDS) +#endif + ) { + if (!memcmp(hdr+6, &ptxsc_entry[i].ethhdr.saddr, sizeof(struct wlan_ethhdr_t)-6)) + return i; + } + else +#endif + { + if (!memcmp(hdr, &ptxsc_entry[i].ethhdr, sizeof(struct wlan_ethhdr_t))) + return i; + } + } + + return -1; +} + + +#ifdef CONFIG_RTL8672 +__MIPS16 +__IRAM_IN_865X +#endif +int get_tx_sc_free_entry(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned char *hdr) +{ + struct tx_sc_entry *ptxsc_entry; + int i; + + i = get_tx_sc_index(priv, pstat, hdr); + if (i >= 0) + return i; + + ptxsc_entry = pstat->tx_sc_ent; + + for (i=0; itx_sc_replace_idx; + pstat->tx_sc_replace_idx = (++pstat->tx_sc_replace_idx) % TX_SC_ENTRY_NUM; + return i; +} +#endif // CONFIG_PCI_HCI +#endif // TX_SHORTCUT + + +/* + Always STOP process after calling this Procedure. +*/ +#ifdef CONFIG_RTL_KERNEL_MIPS16_WLAN +__NOMIPS16 +#endif +static void rtl8192cd_tx_xmitSkbFail(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct net_device *dev, + struct net_device *wdsDev, struct tx_insn *txcfg) +{ +/* + * Comment-out the following lines to disable flow-control in any case to fix + * WDS interface may be blocked sometimes during root interface is up/down + * continously. + */ +#if 0 +#ifdef WDS + if (wdsDev) + netif_stop_queue(wdsDev); + else +#endif + { +#ifdef WIFI_WMM + if (!QOS_ENABLE) +#endif + netif_stop_queue(dev); + } +#endif + + priv->ext_stats.tx_drops++; + DEBUG_WARN("TX DROP: Congested!\n"); + if (txcfg->phdr) + release_wlanllchdr_to_poll(priv, txcfg->phdr); + if (skb) + rtl_kfree_skb(priv, skb, _SKB_TX_); + + return; +} + + +int rtl8192cd_tx_slowPath(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat, + struct net_device *dev, struct net_device *wdsDev, struct tx_insn *txcfg) +{ + + SMP_LOCK_XMIT(flags); +#ifdef CONFIG_RTL_WAPI_SUPPORT + if ((pstat && pstat->wapiInfo + && (pstat->wapiInfo->wapiType!=wapiDisable) + && skb->protocol != __constant_htons(ETH_P_WAPI) + && (!pstat->wapiInfo->wapiUCastTxEnable))) + { + rtl8192cd_tx_xmitSkbFail(priv, skb, dev, wdsDev, txcfg); + goto stop_proc; + } +#endif + + if (IEEE8021X_FUN && pstat && (pstat->ieee8021x_ctrlport == DOT11_PortStatus_Unauthorized) && +#ifdef WDS + (! (pstat->state & WIFI_WDS)) && +#endif +#ifdef CONFIG_RTK_MESH + (txcfg->is_11s == 0) && /* is not mesh packet*/ +#endif + (*((UINT16 *)((UINT8 *)skb->data + ETH_ALEN*2)) != htons(0x888e)) && + (!(OPMODE & WIFI_ADHOC_STATE))) + { + DEBUG_ERR("TX DROP: control port not authorized!\n"); + rtl8192cd_tx_xmitSkbFail(priv, skb, dev, wdsDev, txcfg); + goto stop_proc; + } + + // Note: Don't change txcfg->q_num for USB. If do it, you may hold two ownerships, but only release one. +#ifdef CONFIG_PCI_HCI + if (txcfg->aggre_en < FG_AGGRE_MSDU_FIRST) { + txcfg->q_num = BE_QUEUE; // using low queue for data queue + skb->cb[1] = 0; + } +#endif + txcfg->fr_type = _SKB_FRAME_TYPE_; + txcfg->pframe = skb; + + if ((txcfg->aggre_en == FG_AGGRE_MSDU_MIDDLE) || (txcfg->aggre_en == FG_AGGRE_MSDU_LAST)) + txcfg->phdr = NULL; + else + { + txcfg->phdr = (UINT8 *)get_wlanllchdr_from_poll(priv); + + if (txcfg->phdr == NULL) { + DEBUG_ERR("Can't alloc wlan header!\n"); + rtl8192cd_tx_xmitSkbFail(priv, skb, dev, wdsDev, txcfg); + goto stop_proc; + } + + if (skb->len > priv->pmib->dot11OperationEntry.dot11RTSThreshold) + txcfg->retry = priv->pmib->dot11OperationEntry.dot11LongRetryLimit; + else + txcfg->retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + +#ifdef RTK_NL80211 + if(*((UINT16 *)((UINT8 *)skb->data + ETH_ALEN*2)) == htons(0x888e)) + txcfg->retry = 0x20; +#endif + + memset((void *)txcfg->phdr, 0, sizeof(struct wlanllc_hdr)); + +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s) + { + SetFrameSubType(txcfg->phdr, WIFI_11S_MESH); + SetToDs(txcfg->phdr); + } + else +#endif +#ifdef WIFI_WMM + if ((pstat) && (QOS_ENABLE) && (pstat->QosEnabled)) + SetFrameSubType(txcfg->phdr, WIFI_QOS_DATA); + else +#endif + SetFrameType(txcfg->phdr, WIFI_DATA); + + if (OPMODE & WIFI_AP_STATE) { + SetFrDs(txcfg->phdr); +#ifdef WDS + if (wdsDev) + SetToDs(txcfg->phdr); +#endif +#ifdef A4_STA + if (pstat && (pstat->state & WIFI_A4_STA)) + SetToDs(txcfg->phdr); +#endif + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + SetToDs(txcfg->phdr); + else if (OPMODE & WIFI_ADHOC_STATE) + /* toDS=0, frDS=0 */; +#endif + else + DEBUG_WARN("non supported mode yet!\n"); + } + +#ifdef USE_TXQUEUE + if (GET_ROOT(priv)->pmib->miscEntry.use_txq && priv->pshare->iot_mode_enable) + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + txcfg->next_txpath = TXPATH_FIRETX; +#endif + + SMP_UNLOCK_XMIT(flags); +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (__rtl8192cd_firetx(priv, txcfg) == CONGESTED) +#else + if (rtl8192cd_wlantx(priv, txcfg) == CONGESTED) +#endif + { + SMP_LOCK_XMIT(flags); + rtl8192cd_tx_xmitSkbFail(priv, skb, dev, wdsDev, txcfg); + goto stop_proc; + } + SMP_LOCK_XMIT(flags); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + rtw_handle_xmit_fail(priv, txcfg); +#endif + + /* Reply caller function : process done successfully */ + SMP_UNLOCK_XMIT(flags); + return TX_PROCEDURE_CTRL_SUCCESS; + +stop_proc: + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + rtw_handle_xmit_fail(priv, txcfg); +#endif + SMP_UNLOCK_XMIT(flags); + + /* Reply caller function : STOP process */ + return TX_PROCEDURE_CTRL_STOP; +} + + +__IRAM_IN_865X +int rtl8192cd_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + int ret; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + +#ifdef CONFIG_POWER_SAVE + unsigned short protocol; +#endif +#if !defined(CONFIG_USB_HCI) && !defined(CONFIG_SDIO_HCI) + unsigned long x; +#endif + +#if (defined(RTK_NL80211) && !defined(NON_NL80211_AP)) && defined(MBSSID) + struct net_device *dev_vap = NULL; + if(ntohs(*((UINT16 *)((UINT8 *)skb->data + ETH_ALEN*2))) == 0x888e) + { + printk("[%s]Tx EAP packets, len = %d \n", dev->name, skb->len); + if(IS_ROOT_INTERFACE(priv)) + if(priv->pmib->miscEntry.vap_enable) + { + struct stat_info *pstat=NULL; + unsigned char *da; + unsigned char *sa; + + da = skb->data; + sa = skb->data+ETH_ALEN; + + //dump_mac2(da); + //dump_mac2(sa); + pstat = get_stainfo(priv, da); + + if(pstat == NULL) + { + int i; + for (i=0; ipvap_priv[i])) + { + pstat = get_stainfo(priv->pvap_priv[i], da); + if(pstat) + { + priv = priv->pvap_priv[i]; + dev_vap = priv->dev; + memcpy(sa, dev_vap->dev_addr, ETH_ALEN); + printk("Use [%s] Tx EAP packets \n", dev_vap->name); + //dump_mac2(sa); + break; + } + } + } + } + } + } +#endif + + if (!(priv->drv_state & DRV_STATE_OPEN)){ + dev_kfree_skb_any(skb); + return 0; + } + +#ifdef CONFIG_POWER_SAVE + if (rtw_ap_ps_xmit_monitor(priv)) { + dev_kfree_skb_any(skb); + return 0; + } + // defer suspend procedure when EAP packet exchange + // and avoid to do ToDrv_DisconnectSTA in suspend mode when EAP packet resend timeout due to short ps_timeout + protocol = *((u16*)(skb->data+ETH_ALEN*2)); + if ((protocol == __constant_htons(0x888e)) +#ifdef CONFIG_RTL_WAPI_SUPPORT + || (protocol == __constant_htons(ETH_P_WAPI)) +#endif + ) + rtw_lock_suspend_timeout(priv, 2000); +#endif + + SAVE_INT_AND_CLI(x); + SMP_LOCK_XMIT(x); + +#ifdef MCAST2UI_REFINE + memcpy(&skb->cb[10], skb->data, 6); +#endif + +#if (defined(RTK_NL80211) && !defined(NON_NL80211_AP)) && defined(MBSSID) + if(dev_vap) + ret = __rtl8192cd_start_xmit(skb, dev_vap, TX_NORMAL); + else +#endif + ret = __rtl8192cd_start_xmit(skb, dev, TX_NORMAL); + + RESTORE_INT(x); + SMP_UNLOCK_XMIT(x); + + return ret; +} + + +#ifdef SUPPORT_TX_MCAST2UNI + +__IRAM_IN_865X +int rtl8192cd_start_xmit_noM2U(struct sk_buff *skb, struct net_device *dev) +{ + int ret; + +#if !defined(CONFIG_USB_HCI) && !defined(CONFIG_SDIO_HCI) + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + unsigned long x; + + SAVE_INT_AND_CLI(x); + SMP_LOCK_XMIT(x); +#endif + + ret = __rtl8192cd_start_xmit(skb, dev, TX_NO_MUL2UNI); + +#if !defined(CONFIG_USB_HCI) && !defined(CONFIG_SDIO_HCI) + RESTORE_INT(x); + SMP_UNLOCK_XMIT(x); +#endif + + return ret; +} + +#endif + +#ifdef SUPPORT_TX_AMSDU +static int amsdu_xmit(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct tx_insn *txcfg, int tid, + int from_isr, struct net_device *wdsDev, struct net_device *dev) +{ + int q_num, max_size, is_first=1, total_len=0, total_num=0; + struct sk_buff *pskb; + unsigned long flags; + int *tx_head, *tx_tail, space=0; + struct rtl8192cd_hw *phw = GET_HW(priv); + + txcfg->pstat = pstat; + q_num = txcfg->q_num; + + tx_head = get_txhead_addr(phw, q_num); + tx_tail = get_txtail_addr(phw, q_num); + + max_size = pstat->amsdu_level; + + // start to transmit queued skb + SAVE_INT_AND_CLI(flags); + while (skb_queue_len(&pstat->amsdu_tx_que[tid]) > 0) { + pskb = __skb_dequeue(&pstat->amsdu_tx_que[tid]); + if (pskb == NULL) + break; + total_len += (pskb->len + sizeof(struct llc_snap) + 3); + + if (is_first) { + if (skb_queue_len(&pstat->amsdu_tx_que[tid]) > 0) { + space = CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC); + if (space < 10) { +#ifdef SMP_SYNC + if (!priv->pshare->has_triggered_tx_tasklet) { + tasklet_schedule(&priv->pshare->tx_tasklet); + priv->pshare->has_triggered_tx_tasklet = 1; + } +#else + rtl8192cd_tx_dsr((unsigned long)priv); +#endif + + space = CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC); + if (space < 10) { + // printk("Tx desc not enough for A-MSDU!\n"); + __skb_queue_head(&pstat->amsdu_tx_que[tid], pskb); + RESTORE_INT(flags); + return 0; + } + } + txcfg->aggre_en = FG_AGGRE_MSDU_FIRST; + is_first = 0; + total_num++; + } + else { + if (!from_isr) { + __skb_queue_head(&pstat->amsdu_tx_que[tid], pskb); + RESTORE_INT(flags); + return 0; + } + txcfg->aggre_en = 0; + } + } + else if ((skb_queue_len(&pstat->amsdu_tx_que[tid]) == 0) || + ((total_len + pstat->amsdu_tx_que[tid].next->len + sizeof(struct llc_snap) + 3) > max_size) || + (total_num >= (space - 4)) || // 1 for header, 1 for ICV when sw encrypt, 2 for spare + (!pstat->is_realtek_sta && (total_num >= (priv->pmib->dot11nConfigEntry.dot11nAMSDUSendNum-1)))) { + txcfg->aggre_en = FG_AGGRE_MSDU_LAST; + total_len = 0; + is_first = 1; + total_num = 0; + } + else { + txcfg->aggre_en = FG_AGGRE_MSDU_MIDDLE; + total_num++; + } + + pstat->amsdu_size[tid] -= (pskb->len + sizeof(struct llc_snap)); +#ifdef MESH_AMSDU + txcfg->llc = 0; + if( isMeshPoint(pstat)) + { + txcfg->is_11s = 8; + dev = priv->mesh_dev; + memcpy(txcfg->nhop_11s, pstat->hwaddr, MACADDRLEN); + } + else + txcfg->is_11s = 0; + +#endif + SMP_UNLOCK_XMIT(flags); + rtl8192cd_tx_slowPath(priv, pskb, pstat, dev, wdsDev, txcfg); + SMP_LOCK_XMIT(flags); + + } + RESTORE_INT(flags); + + return 1; +} + + +static int amsdu_timer_add(struct rtl8192cd_priv *priv, struct stat_info *pstat, int tid, int from_timeout) +{ + unsigned int now, timeout, new_timer=0; + int setup_timer; + int current_idx, next_idx; + + current_idx = priv->pshare->amsdu_timer_head; + + while (CIRC_CNT(current_idx, priv->pshare->amsdu_timer_tail, AMSDU_TIMER_NUM)) { + if (priv->pshare->amsdu_timer[priv->pshare->amsdu_timer_tail].pstat == NULL) { + priv->pshare->amsdu_timer_tail = (priv->pshare->amsdu_timer_tail + 1) & (AMSDU_TIMER_NUM - 1); + new_timer = 1; + } + else + break; + } + + if (CIRC_CNT(current_idx, priv->pshare->amsdu_timer_tail, AMSDU_TIMER_NUM) == 0) { + cancel_timer2(priv); + setup_timer = 1; + } + else if (CIRC_SPACE(current_idx, priv->pshare->amsdu_timer_tail, AMSDU_TIMER_NUM) == 0) { + printk("%s: %s, amsdu timer overflow!\n", priv->dev->name, __FUNCTION__ ); + return -1; + } + else { // some items in timer queue + setup_timer = 0; + if (new_timer) + new_timer = priv->pshare->amsdu_timer[priv->pshare->amsdu_timer_tail].timeout; + } + + next_idx = (current_idx + 1) & (AMSDU_TIMER_NUM - 1); + + priv->pshare->amsdu_timer[current_idx].priv = priv; + priv->pshare->amsdu_timer[current_idx].pstat = pstat; + priv->pshare->amsdu_timer[current_idx].tid = (unsigned char)tid; + priv->pshare->amsdu_timer_head = next_idx; + now = RTL_R32(TSFTR); + timeout = now + priv->pmib->dot11nConfigEntry.dot11nAMSDUSendTimeout; + priv->pshare->amsdu_timer[current_idx].timeout = timeout; + + if (!from_timeout) { + if (setup_timer) + setup_timer2(priv, timeout); + else if (new_timer) { + if (TSF_LESS(new_timer, now)) + setup_timer2(priv, timeout); + else + setup_timer2(priv, new_timer); + } + } + + return current_idx; +} + + +void amsdu_timeout(struct rtl8192cd_priv *priv, unsigned int current_time) +{ + struct tx_insn tx_insn; + struct stat_info *pstat; + struct net_device *wdsDev=NULL; + struct rtl8192cd_priv *priv_this=NULL; + int tid=0, head; + //DECLARE_TXCFG(txcfg, tx_insn); + + head = priv->pshare->amsdu_timer_head; + while (CIRC_CNT(head, priv->pshare->amsdu_timer_tail, AMSDU_TIMER_NUM)) + { + DECLARE_TXCFG(txcfg, tx_insn); // will be reused in this while loop + + pstat = priv->pshare->amsdu_timer[priv->pshare->amsdu_timer_tail].pstat; + if (pstat) { + tid = priv->pshare->amsdu_timer[priv->pshare->amsdu_timer_tail].tid; + priv_this = priv->pshare->amsdu_timer[priv->pshare->amsdu_timer_tail].priv; + priv->pshare->amsdu_timer[priv->pshare->amsdu_timer_tail].pstat = NULL; + } + + priv->pshare->amsdu_timer_tail = (priv->pshare->amsdu_timer_tail + 1) & (AMSDU_TIMER_NUM - 1); + + if (pstat) { +#ifdef WDS + wdsDev = NULL; + if (pstat->state & WIFI_WDS) { + wdsDev = getWdsDevByAddr(priv, pstat->hwaddr); + txcfg->wdsIdx = getWdsIdxByDev(priv, wdsDev); + } +#endif +#ifdef RTL_MANUAL_EDCA + txcfg->q_num = PRI_TO_QNUM(priv, tid); +#else + PRI_TO_QNUM(tid, txcfg->q_num, priv->pmib->dot11OperationEntry.wifi_specific); +#endif + + if (pstat->state & WIFI_SLEEP_STATE) + pstat->amsdu_timer_id[tid] = amsdu_timer_add(priv_this, pstat, tid, 1) + 1; + else + { + int ret; + unsigned long flags; + + SMP_LOCK_XMIT(flags); + ret = amsdu_xmit(priv_this, pstat, txcfg, tid, 1, wdsDev, priv->dev); + SMP_UNLOCK_XMIT(flags); + if (ret == 0) // not finish + pstat->amsdu_timer_id[tid] = amsdu_timer_add(priv_this, pstat, tid, 1) + 1; + else + pstat->amsdu_timer_id[tid] = 0; + } + } + } + + if (CIRC_CNT(priv->pshare->amsdu_timer_head, priv->pshare->amsdu_timer_tail, AMSDU_TIMER_NUM)) { + setup_timer2(priv, priv->pshare->amsdu_timer[priv->pshare->amsdu_timer_tail].timeout); + if (TSF_LESS(priv->pshare->amsdu_timer[priv->pshare->amsdu_timer_tail].timeout, current_time)) + printk("Setup timer2 %d too late (now %d)\n", priv->pshare->amsdu_timer[priv->pshare->amsdu_timer_tail].timeout, current_time); + } +} + + + int amsdu_check(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat, struct tx_insn *txcfg) +{ + int q_num; + unsigned int priority; + unsigned short protocol; + int *tx_head, *tx_tail, cnt, add_timer=1; + struct rtl8192cd_hw *phw; +#ifndef SMP_SYNC + unsigned long flags; +#endif + struct net_device *wdsDev=NULL; + + protocol = ntohs(*((UINT16 *)((UINT8 *)skb->data + ETH_ALEN*2))); +#ifdef CONFIG_RTL_WAPI_SUPPORT + if ((protocol == 0x888e)||(protocol == ETH_P_WAPI)) +#else + if (protocol == 0x888e) +#endif + { + return RET_AGGRE_BYPASS; + } + + if (((protocol + WLAN_ETHHDR_LEN) > WLAN_MAX_ETHFRM_LEN) && + (skb_headroom(skb) < sizeof(struct llc_snap))) { + return RET_AGGRE_BYPASS; + } +//---------------------- + +#ifdef CONFIG_RTK_MESH + priority = get_skb_priority3(priv, skb, txcfg->is_11s, pstat); +#else + priority = get_skb_priority(priv, skb, pstat); +#endif +#ifdef RTL_MANUAL_EDCA + q_num = PRI_TO_QNUM(priv, priority); +#else + PRI_TO_QNUM(priority, q_num, priv->pmib->dot11OperationEntry.wifi_specific); +#endif + + phw = GET_HW(priv); + tx_head = get_txhead_addr(phw, q_num); + tx_tail = get_txtail_addr(phw, q_num); + + cnt = CIRC_CNT_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC); + +#if 0 + if (cnt <= AMSDU_TX_DESC_TH) + return RET_AGGRE_BYPASS; +#endif + + if (cnt == (CURRENT_NUM_TX_DESC - 1)) + return RET_AGGRE_DESC_FULL; + +#ifdef MESH_AMSDU + if(txcfg->is_11s==0 && isMeshPoint(pstat)) + { + return RET_AGGRE_DESC_FULL; + } + if (txcfg->is_11s&1) + { + short j, popen = ((txcfg->mesh_header.mesh_flag &1) ? 16 : 4); + if (skb_headroom(skb) < popen || skb_cloned(skb)) { + struct sk_buff *skb2 = dev_alloc_skb(skb->len); + if (skb2 == NULL) { + printk("%s: %s, dev_alloc_skb() failed!\n", priv->mesh_dev->name, __FUNCTION__); + return RET_AGGRE_BYPASS; + } + memcpy(skb_put(skb2, skb->len), skb->data, skb->len); + dev_kfree_skb_any(skb); + skb = skb2; + txcfg->pframe = (void *)skb; + } + skb_push(skb, popen); + for(j=0; jdata[j]= skb->data[j+popen]; + memcpy(skb->data+j, &(txcfg->mesh_header), popen); + } +#endif // MESH_AMSDU + + + SAVE_INT_AND_CLI(flags); + __skb_queue_tail(&pstat->amsdu_tx_que[priority], skb); + pstat->amsdu_size[priority] += (skb->len + sizeof(struct llc_snap)); + + if ((pstat->amsdu_size[priority] >= pstat->amsdu_level) || + (!pstat->is_realtek_sta && (skb_queue_len(&pstat->amsdu_tx_que[priority]) >= priv->pmib->dot11nConfigEntry.dot11nAMSDUSendNum))) + { +#ifdef WDS + wdsDev = NULL; + if (pstat->state & WIFI_WDS) { + wdsDev = getWdsDevByAddr(priv, pstat->hwaddr); + txcfg->wdsIdx = getWdsIdxByDev(priv, wdsDev); + } +#endif + // delete timer entry + if (pstat->amsdu_timer_id[priority] > 0) { + priv->pshare->amsdu_timer[pstat->amsdu_timer_id[priority] - 1].pstat = NULL; + pstat->amsdu_timer_id[priority] = 0; + } + txcfg->q_num = q_num; + if (amsdu_xmit(priv, pstat, txcfg, priority, 0, wdsDev, priv->dev) == 0) // not finish + pstat->amsdu_timer_id[priority] = amsdu_timer_add(priv, pstat, priority, 0) + 1; + else + add_timer = 0; + } + + if (add_timer) { + if (pstat->amsdu_timer_id[priority] == 0) + pstat->amsdu_timer_id[priority] = amsdu_timer_add(priv, pstat, priority, 0) + 1; + } + + RESTORE_INT(flags); + + return RET_AGGRE_ENQUE; +} +#endif // SUPPORT_TX_AMSDU + +#ifdef SUPPORT_TX_MCAST2UNI +#ifndef CONFIG_RTK_MESH +static +#endif +int isICMPv6Mng(struct sk_buff *skb) +{ +#ifdef __ECOS + if((skb->data[12] == 0x86) &&(skb->data[13] == 0xdd)&& +#else + if((skb->protocol == __constant_htons(0x86dd)) && +#endif + ((skb->data[20] == 0x3a) || (skb->data[54] == 0x3a)) //next header is icmpv6 + //&& skb->data[54] == 0x86 //RA + /*128,129,133,.....255 SHOULD BE MANAGMENT PACKET + REF:http://en.wikipedia.org/wiki/ICMPv6 */ + ) + { + return 1; + } + else + return 0; +} + +#ifndef CONFIG_RTK_MESH +static +#endif +inline int isMDNS(unsigned char *data) +{ + if((data[3] == 0x00) && (data[4] == 0x00) && (data[5] == 0xfb) && + (((data[12] == 0x08) && (data[13] == 0x00) // IPv4 + && (data[23] == 0x11) // UDP + //&& (data[30] == 0xe0) // 224.0.0.251 + && (data[36] == 0x14) && (data[37] == 0xe9)) // port 5353 + || + ((data[12] == 0x86) && (data[13] == 0xdd) // IPv6 + && (data[20] == 0x11) // next header is UDP + && (data[56] == 0x14) && (data[57] == 0xe9)) // port 5353 + )) { + return 1; + } + + return 0; +} + +#ifdef CONFIG_PCI_HCI +static int rtl8192cd_tx_recycle(struct rtl8192cd_priv *priv, unsigned int txRingIdx, int *recycleCnt_p); +static inline void check_tx_queue(struct rtl8192cd_priv *priv) +{ + int *tx_head, *tx_tail; + struct rtl8192cd_hw *phw = GET_HW(priv); + +#ifdef CONFIG_WLAN_HAL + PHCI_TX_DMA_MANAGER_88XX ptx_dma; + if (IS_HAL_CHIP(priv)) { + ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + tx_head = get_txhead_addr(phw, BE_QUEUE);// use BE queue to send multicast + tx_tail = get_txtail_addr(phw, BE_QUEUE); + } + if ( +#ifdef CONFIG_WLAN_HAL + (IS_HAL_CHIP(priv)) ? (compareAvailableTXBD(priv, (CURRENT_NUM_TX_DESC/4), BE_QUEUE, 2)) : +#endif + (CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC) < (CURRENT_NUM_TX_DESC/4)) + ) + { + rtl8192cd_tx_queueDsr(priv, BE_QUEUE); + //int recycleCnt; + //rtl8192cd_tx_recycle(priv, BE_QUEUE, &recycleCnt); + } + + return; +} +#endif // CONFIG_PCI_HCI + + +#if defined(CONFIG_RTL865X_ETH_PRIV_SKB) || defined(CONFIG_RTL_ETH_PRIV_SKB) + extern struct sk_buff *priv_skb_copy(struct sk_buff *skb); + extern int eth_skb_free_num; +#endif +#ifdef CONFIG_RTL8196B_GW_8M +#define ETH_SKB_FREE_TH 50 +#else +#define ETH_SKB_FREE_TH 100 +#endif + +int isSpecialFloodMac(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + int i; + if(priv->pshare->rf_ft_var.mc2u_flood_ctrl==0) + { + return 0; + } + + for(i=0; i< priv->pshare->rf_ft_var.mc2u_flood_mac_num; i++) + { + if(memcmp(skb->data, priv->pshare->rf_ft_var.mc2u_flood_mac[i].macAddr,MACADDRLEN)==0) + { + return 1; + } + + } + return 0; +} + +int mlcst2unicst(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + struct stat_info *pstat, *sa_stat; + struct list_head *phead, *plist; + struct sk_buff *newskb; + unsigned char origDest[6]; + int i= 0; + int m2uCnt =0; + int fwdCnt=0; + struct stat_info *pstat_found = NULL; +#ifdef MCAST2UI_REFINE + unsigned int privacy; +#endif + +#ifdef CONFIG_MAXED_MULTICAST + int M2Uanyway=0; +#endif + +#ifdef HS2_SUPPORT + // if AP + // 1.support HS2 and + // 2.dgaf disable=0 + // it means to let icmpv6 mgmt multicast to clients + if ((priv->pmib->hs2Entry.hs2_ielen != 0) && (priv->dgaf_disable == 0)) { + if (isICMPv6Mng(skb) || IS_ICMPV6_PROTO(skb->data)) + return 0; + } +#endif + + memcpy(origDest, skb->data, 6); + + sa_stat = get_stainfo(priv, skb->data+MACADDRLEN); +#ifdef A4_STA + if (priv->pshare->rf_ft_var.a4_enable) { + if(sa_stat == NULL) { + sa_stat = a4_sta_lookup(priv, skb->data+MACADDRLEN); + } + } +#endif + + if (isMDNS(skb->data)) + { + return FALSE; + } + + // all multicast managment packet try do m2u + if( isSpecialFloodMac(priv,skb) /*|| IS_MDNSV4_MAC(skb->data)||IS_MDNSV6_MAC(skb->data)*/||IS_IGMP_PROTO(skb->data) || isICMPv6Mng(skb) || IS_ICMPV6_PROTO(skb->data)|| isMDNS(skb->data)) + { + /*added by qinjunjie,do multicast to unicast conversion, and send to every associated station */ + phead = &priv->asoc_list; + plist = phead; + while ((plist = asoc_list_get_next(priv, plist)) != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + + #ifdef CONFIG_RTK_MESH + if(isPossibleNeighbor(pstat)) { + continue; + } + #endif + + /* avoid come from STA1 and send back STA1 */ + if (sa_stat == pstat) { + continue; + } + + if(pstat->leave || pstat->expire_to==0) + continue; +#ifdef MCAST2UI_REFINE + privacy = get_sta_encrypt_algthm(priv, pstat); + if ((privacy == _NO_PRIVACY_ || (privacy == _CCMP_PRIVACY_ +#ifdef CONFIG_IEEE80211W + && !UseSwCrypto(priv, pstat, FALSE,0))) +#else + && !UseSwCrypto(priv, pstat, FALSE))) +#endif + && (newskb = skb_clone(skb, GFP_ATOMIC))) + { + memcpy(&newskb->cb[10], pstat->hwaddr, 6); + newskb->cb[2] = (char)0xff; + __rtl8192cd_start_xmit(newskb, priv->dev, TX_NO_MUL2UNI); + } + else +#endif + { + if((plist->next == phead) && !skb_cloned(skb)) { + asoc_list_unref(priv, pstat); +#ifdef MCAST2UI_REFINE + memcpy(&skb->cb[10], pstat->hwaddr, 6); +#else + memcpy(skb->data, pstat->hwaddr, 6); +#endif + skb->cb[2] = (char)0xff; // not do aggregation +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + __rtl8192cd_start_xmit(skb, priv->dev, TX_NO_MUL2UNI); + return TRUE; + } + +#if defined(CONFIG_RTL865X_ETH_PRIV_SKB) || defined(CONFIG_RTL_ETH_PRIV_SKB) + newskb = priv_skb_copy(skb); +#else + newskb = skb_copy(skb, GFP_ATOMIC); +#endif + if (newskb) { +#ifdef MCAST2UI_REFINE + memcpy(&newskb->cb[10], pstat->hwaddr, 6); +#else + memcpy(newskb->data, pstat->hwaddr, 6); +#endif + newskb->cb[2] = (char)0xff; // not do aggregation + __rtl8192cd_start_xmit(newskb, priv->dev, TX_NO_MUL2UNI); + } + else { + asoc_list_unref(priv, pstat); + + DEBUG_ERR("%s: muti2unit skb_copy() failed!\n", priv->dev->name); + priv->stop_tx_mcast2uni = 2; + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: %s: run out ether buffer!\n", __FUNCTION__); + rtl_kfree_skb(priv, skb, _SKB_TX_); + return TRUE; + } + + } + } + rtl_kfree_skb(priv, skb, _SKB_TX_); + return TRUE; + } + +//#ifdef VIDEO_STREAMING_REFINE + // for video streaming refine + phead = &priv->asoc_list; + plist = phead; + while ((plist = asoc_list_get_next(priv, plist)) != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + + #ifdef CONFIG_RTK_MESH + if(isPossibleNeighbor(pstat)) { + continue; + } + #endif + + /* avoid come from STA1 and send back STA1 */ + if (sa_stat == pstat){ + continue; + } + if(pstat->leave || pstat->expire_to==0) + continue; + for (i=0; iipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[0], origDest, 6)) { + pstat_found = pstat; + m2uCnt++; + break; + } + } + } + + if (m2uCnt == 1 && !skb_cloned(skb)) { +#ifdef MCAST2UI_REFINE + memcpy(&skb->cb[10], pstat_found->hwaddr, 6); +#else + memcpy(skb->data, pstat_found->hwaddr, 6); +#endif +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + __rtl8192cd_start_xmit(skb, priv->dev, TX_NO_MUL2UNI); + return TRUE; + } + + fwdCnt = m2uCnt; + + if(m2uCnt == 0){ + +#ifdef CONFIG_MAXED_MULTICAST + /*case: when STA <=3 do M2U anyway ; + if STA number > 3 by orig method(multicast);*/ + if(priv->assoc_num <=3){ + M2Uanyway=1; + fwdCnt = priv->assoc_num; + }else +#endif + if(!priv->pshare->rf_ft_var.mc2u_drop_unknown) + { + /*case: if M2U can't success then + forward by multicast(orig method), + defect: may affect system performance + advantage:better compatibility*/ + return FALSE; + } + else + { + + /*case: if M2U can't success then drop this packet ; + defect:maybe some management packet will lose + advantage:better performance*/ + DEBUG_WARN("TX DROP: %s %d !\n", __FUNCTION__,__LINE__); + priv->ext_stats.tx_drops++; + rtl_kfree_skb(priv, skb, _SKB_TX_); + return TRUE; + + } + } +//#endif + + + + // Do multicast to unicast conversion + phead = &priv->asoc_list; + plist = phead; + while ((plist = asoc_list_get_next(priv, plist)) != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + + #ifdef CONFIG_RTK_MESH + if(isPossibleNeighbor(pstat)) { + continue; + } + #endif + + /* avoid come from STA1 and send back STA1 */ + if (sa_stat == pstat) { + continue; + } + + if(pstat->leave || pstat->expire_to==0) + continue; + +#ifdef CONFIG_PCI_HCI + { + int *tx_head, *tx_tail, q_num; + struct rtl8192cd_hw *phw = GET_HW(priv); + q_num = BE_QUEUE; // use BE queue to send multicast +#ifdef CONFIG_WLAN_HAL + //PHCI_TX_DMA_MANAGER_88XX ptx_dma; + if (IS_HAL_CHIP(priv)) { + //ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + tx_head = get_txhead_addr(phw, q_num); + tx_tail = get_txtail_addr(phw, q_num); + } + + if (priv->stop_tx_mcast2uni) { + rtl8192cd_tx_queueDsr(priv, q_num); + + if (priv->stop_tx_mcast2uni == 1) { +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { + if(compareAvailableTXBD(priv, ((CURRENT_NUM_TX_DESC*1)/4), q_num, 1)) + priv->stop_tx_mcast2uni = 0; + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + if(CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC) > (CURRENT_NUM_TX_DESC*1)/4) + priv->stop_tx_mcast2uni = 0; + } + } + +#if defined(CONFIG_RTL865X_ETH_PRIV_SKB) || defined(CONFIG_RTL_ETH_PRIV_SKB) + else if ((priv->stop_tx_mcast2uni == 2) && (eth_skb_free_num > ETH_SKB_FREE_TH)) + { + priv->stop_tx_mcast2uni = 0; + } +#endif + else { + asoc_list_unref(priv, pstat); + + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: %s: run out ether buffer!\n", __FUNCTION__); + rtl_kfree_skb(priv, skb, _SKB_TX_); + return TRUE; + } + } else { +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { + if(compareAvailableTXBD(priv, 20, q_num, 2)) { + asoc_list_unref(priv, pstat); + #ifdef __ECOS + #else + priv->stop_tx_mcast2uni = 1; + #endif + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: %s: txdesc full!\n", __FUNCTION__); + rtl_kfree_skb(priv, skb, _SKB_TX_); + return TRUE; + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + if (CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC) < 20) { + asoc_list_unref(priv, pstat); + #ifdef __ECOS + #else + priv->stop_tx_mcast2uni = 1; + #endif + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: %s: txdesc full!\n", __FUNCTION__); + rtl_kfree_skb(priv, skb, _SKB_TX_); + return TRUE; + } + } + } + } +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_MAXED_MULTICAST + + if(M2Uanyway){ + if((fwdCnt== 1) && !skb_cloned(skb)) + { + asoc_list_unref(priv, pstat); +#ifdef MCAST2UI_REFINE + memcpy(&skb->cb[10], pstat->hwaddr, 6); +#else + memcpy(skb->data, pstat->hwaddr, 6); +#endif + skb->cb[2] = (char)0xff; // not do aggregation +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + __rtl8192cd_start_xmit(skb, priv->dev, TX_NO_MUL2UNI); + return TRUE; + } + +#if defined(CONFIG_RTL865X_ETH_PRIV_SKB) || defined(CONFIG_RTL_ETH_PRIV_SKB) + newskb = priv_skb_copy(skb); +#else + newskb = skb_copy(skb, GFP_ATOMIC); +#endif + if (newskb) { +#ifdef MCAST2UI_REFINE + memcpy(&newskb->cb[10], pstat->hwaddr, 6); +#else + memcpy(newskb->data, pstat->hwaddr, 6); +#endif + newskb->cb[2] = (char)0xff; // not do aggregation + __rtl8192cd_start_xmit(newskb, priv->dev, TX_NO_MUL2UNI); + } + else { + asoc_list_unref(priv, pstat); + + DEBUG_ERR("%s: muti2unit skb_copy() failed!\n", priv->dev->name); + #ifdef __ECOS + #else + priv->stop_tx_mcast2uni = 2; + #endif + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: %s: run out ether buffer!\n", __FUNCTION__); + rtl_kfree_skb(priv, skb, _SKB_TX_); + return TRUE; + } + fwdCnt--; + continue; + } +#endif + for (i=0; iipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[0], origDest, 6)) { + + + if((fwdCnt== 1) && !skb_cloned(skb)) + { + asoc_list_unref(priv, pstat); +#ifdef MCAST2UI_REFINE + memcpy(&skb->cb[10], pstat->hwaddr, 6); +#else + memcpy(skb->data, pstat->hwaddr, 6); +#endif + skb->cb[2] = (char)0xff; // not do aggregation +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + __rtl8192cd_start_xmit(skb, priv->dev, TX_NO_MUL2UNI); + return TRUE; + } + else { +#ifdef MCAST2UI_REFINE + privacy = get_sta_encrypt_algthm(priv, pstat); + if ((privacy == _NO_PRIVACY_ || (privacy == _CCMP_PRIVACY_ +#ifdef CONFIG_IEEE80211W + && !UseSwCrypto(priv, pstat, FALSE,0))) +#else + && !UseSwCrypto(priv, pstat, FALSE))) +#endif + && (newskb = skb_clone(skb, GFP_ATOMIC))) + { + memcpy(&newskb->cb[10], pstat->hwaddr, 6); + newskb->cb[2] = (char)0xff; + __rtl8192cd_start_xmit(newskb, priv->dev, TX_NO_MUL2UNI); + } + else +#endif + { + #if defined(CONFIG_RTL865X_ETH_PRIV_SKB) || defined(CONFIG_RTL_ETH_PRIV_SKB) + + newskb = priv_skb_copy(skb); + #else + newskb = skb_copy(skb, GFP_ATOMIC); + #endif + if (newskb) { +#ifdef MCAST2UI_REFINE + memcpy(&newskb->cb[10], pstat->hwaddr, 6); +#else + memcpy(newskb->data, pstat->hwaddr, 6); +#endif + newskb->cb[2] = (char)0xff; // not do aggregation + __rtl8192cd_start_xmit(newskb, priv->dev, TX_NO_MUL2UNI); + } + else { + asoc_list_unref(priv, pstat); + + DEBUG_ERR("%s: muti2unit skb_copy() failed!\n", priv->dev->name); + #ifdef __ECOS + #else + priv->stop_tx_mcast2uni = 2; + #endif + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: %s: run out ether buffer!\n", __FUNCTION__); + rtl_kfree_skb(priv, skb, _SKB_TX_); + return TRUE; + } + } + fwdCnt--; + break; + } + } + } + } + + /* + * Device interested in this MC IP cannot be found, drop packet. + */ + rtl_kfree_skb(priv, skb, _SKB_TX_); + return TRUE; +} + +#endif // TX_SUPPORT_MCAST2U + + +#ifdef RESERVE_TXDESC_FOR_EACH_IF +int check_txdesc_dynamic_mechanism(struct rtl8192cd_priv *priv, int q_num, int txdesc_need) +{ + struct rtl8192cd_priv *root_priv = NULL; + unsigned int lower_limit = priv->pshare->num_txdesc_lower_limit; + unsigned int avail_cnt = priv->pshare->num_txdesc_cnt; + unsigned int used = priv->use_txdesc_cnt[q_num]; + unsigned int accu = 0, i; + + if (IS_ROOT_INTERFACE(priv)) + root_priv = priv; + else + root_priv = GET_ROOT(priv); + + if (IS_ROOT_INTERFACE(priv)) { + if (IS_DRV_OPEN(priv)) + accu += used; + } else { + if (IS_DRV_OPEN(root_priv)) + accu += MAX_NUM(root_priv->use_txdesc_cnt[q_num], lower_limit); + } + +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) { + if (IS_DRV_OPEN(priv)) + accu += used; + } else { + if (IS_DRV_OPEN(root_priv->pvxd_priv)) + accu += MAX_NUM(root_priv->pvxd_priv->use_txdesc_cnt[q_num], lower_limit); + } +#endif + +#ifdef MBSSID + for (i=0; ipvap_priv[i])) { + if (root_priv->pvap_priv[i] == priv) + accu += used; + else + accu += MAX_NUM(root_priv->pvap_priv[i]->use_txdesc_cnt[q_num], lower_limit); + } + } +#endif + + if (accu + txdesc_need <= avail_cnt) + return 0; + + return -1; +} + +#ifdef USE_TXQUEUE +int check_txq_dynamic_mechanism(struct rtl8192cd_priv *priv, int q_num) +{ + struct rtl8192cd_priv *root_priv = NULL; + unsigned int lower_limit = priv->pshare->num_txq_lower_limit; + unsigned int avail_cnt = priv->pshare->num_txq_cnt; + unsigned int used = priv->use_txq_cnt[q_num]; + unsigned int accu = 0, i; + + if (IS_ROOT_INTERFACE(priv)) + root_priv = priv; + else + root_priv = GET_ROOT(priv); + + if (IS_ROOT_INTERFACE(priv)) + { + if ( IS_DRV_OPEN(priv) ) + accu += used; + } + else + { + if ( IS_DRV_OPEN(root_priv) ) + accu += MAX_NUM(root_priv->use_txq_cnt[q_num], lower_limit); + } + +#ifdef UNIVERSAL_REPEATER + if (IS_VXD_INTERFACE(priv)) + { + if ( IS_DRV_OPEN(priv) ) + accu += used; + } + else + { + if ( IS_DRV_OPEN(root_priv->pvxd_priv) ) + accu += MAX_NUM(root_priv->pvxd_priv->use_txq_cnt[q_num], lower_limit); + } +#endif + +#ifdef MBSSID + for (i=0; ipvap_priv[i]) ) + { + if (root_priv->pvap_priv[i] == priv) + accu += used; + else + accu += MAX_NUM(root_priv->pvap_priv[i]->use_txq_cnt[q_num], lower_limit); + } + } +#endif + + if (accu < avail_cnt) + return 0; + + return -1; + +} +#endif +#endif + + +#ifdef BEAMFORMING_SUPPORT +BOOLEAN +IsMgntNDPA( + pu1Byte pdu +) +{ + BOOLEAN ret = 0; + if(IsMgntActionNoAck(pdu) && GET_80211_HDR_ORDER(pdu)) + { + if(GET_HT_CTRL_NDP_ANNOUNCEMENT(pdu+sMacHdrLng) == 1) + ret = 1; + } + return ret; +} +#endif + +void RtsCheck(struct rtl8192cd_priv *priv, struct tx_insn* txcfg, + BOOLEAN *bRtsEnable, BOOLEAN *bCts2SelfEnable, BOOLEAN *bHwRts, BOOLEAN *bErpProtect, BOOLEAN *bNProtect) +{ + *bRtsEnable = FALSE; + *bCts2SelfEnable = FALSE; + *bHwRts = FALSE; + *bErpProtect = FALSE; + *bNProtect = FALSE; + + if ((txcfg->rts_thrshld <= get_mpdu_len(txcfg, txcfg->fr_len)) || + (txcfg->pstat && txcfg->pstat->is_forced_rts)) + *bRtsEnable = TRUE; + else { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + is_MCS_rate(txcfg->tx_rate) && + (priv->ht_protection /*|| txcfg->pstat->is_rtl8190_sta*/)) + { + *bNProtect = 1; + if (priv->pmib->dot11ErpInfo.protection) + *bErpProtect = 1; + if (priv->pmib->dot11ErpInfo.ctsToSelf) + *bCts2SelfEnable = TRUE; + else + *bRtsEnable = TRUE; + + } + else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + (!is_CCK_rate(txcfg->tx_rate)) && // OFDM mode + priv->pmib->dot11ErpInfo.protection) + { + *bErpProtect = 1; + if (priv->pmib->dot11ErpInfo.ctsToSelf) + *bCts2SelfEnable = TRUE; + else + *bRtsEnable = TRUE; + + } + else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + (txcfg->pstat) && (txcfg->pstat->MIMO_ps & _HT_MIMO_PS_DYNAMIC_)) + { // when HT MIMO Dynamic power save is set, RTS is needed + *bRtsEnable = TRUE; + + } else { + /* + * Auto rts mode, use rts depends on packet length and packet tx time + */ + + if (is_MCS_rate(txcfg->tx_rate) && (/*(txcfg->pstat->IOTPeer!=HT_IOT_PEER_INTEL) ||*/ !txcfg->pstat->no_rts)) + { + *bNProtect = 1; + *bHwRts = TRUE; + if (priv->pmib->dot11ErpInfo.ctsToSelf) + *bCts2SelfEnable = TRUE; + else + *bRtsEnable = TRUE; + } + } + } +} + +#ifdef RTK_AC_SUPPORT +static void RtsCheckAC(struct rtl8192cd_priv *priv, struct tx_insn* txcfg, BOOLEAN *bRtsEnable, BOOLEAN *bCts2SelfEnable, BOOLEAN *bHwRts) +{ + if((priv->pshare->rf_ft_var.cca_rts) && (txcfg->pstat->vht_cap_len > 0)) { + *bHwRts = FALSE; + *bCts2SelfEnable = FALSE; + *bRtsEnable = TRUE; + } +} +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT +static void rtl8192cd_fill_fwinfo_8812(struct rtl8192cd_priv *priv, struct tx_insn* txcfg, struct tx_desc *pdesc, unsigned int frag_idx) +{ + char n_txshort = 0, bg_txshort = 0; + //int erp_protection = 0, n_protection = 0; +// unsigned char rate; + unsigned char txRate = 0; +#ifdef DRVMAC_LB + static unsigned int rate_select = 0; +#endif + BOOLEAN bRtsEnable; + BOOLEAN bErpProtect; + BOOLEAN bNProtect; + BOOLEAN bHwRts; + BOOLEAN bCts2SelfEnable; + unsigned char RtsRate; + +#ifdef MP_TEST + if (OPMODE & WIFI_MP_STATE) { + if (is_VHT_rate(txcfg->tx_rate)) { + txRate = txcfg->tx_rate - VHT_RATE_ID; + txRate += 44; + } else if (is_MCS_rate(txcfg->tx_rate)) { // HT rates + txRate = txcfg->tx_rate - HT_RATE_ID; + txRate += 12; + } else{ + txRate = get_rate_index_from_ieee_value((UINT8)txcfg->tx_rate); + } + + if (priv->pshare->is_40m_bw == 2) { + pdesc->Dword5 |= set_desc((0 << TXdesc_92E_DataScSHIFT) | (0 << TXdesc_92E_RtsScSHIFT)); + pdesc->Dword5 |= set_desc(0x2 << TXdesc_92E_DataBwSHIFT); + + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M) + n_txshort = 1; + } else if (priv->pshare->is_40m_bw == 1) { + pdesc->Dword5 |= set_desc((0 << TXdesc_92E_DataScSHIFT) | (0 << TXdesc_92E_RtsScSHIFT)); + pdesc->Dword5 |= set_desc(0x1 << TXdesc_92E_DataBwSHIFT); + + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M) + n_txshort = 1; + } else { + pdesc->Dword5 |= set_desc((0 << TXdesc_92E_DataScSHIFT) | (0 << TXdesc_92E_RtsScSHIFT)); + pdesc->Dword5 |= set_desc(0 << TXdesc_92E_DataBwSHIFT); + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M) + n_txshort = 1; + } + + if (txcfg->retry) { + pdesc->Dword4 |= set_desc(TXdesc_92E_RtyLmtEn); + pdesc->Dword4 |= set_desc((txcfg->retry & TXdesc_92E_DataRtyLmtMask) << TXdesc_92E_DataRtyLmtSHIFT); + } + + pdesc->Dword4 |= set_desc((txRate & TXdesc_92E_DataRateMask) << TXdesc_92E_DataRateSHIFT); + + + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + pdesc->Dword4 |= set_desc((4 & TX_RtsRateMask_8812) << TX_RtsRateSHIFT_8812); + + if(n_txshort == 1) + pdesc->Dword5 |= set_desc(TXdesc_92E_DataShort); + + return; + } +#endif + + + if (is_MCS_rate(txcfg->tx_rate)) // HT rates + { + if( txcfg->tx_rate >= VHT_RATE_ID) + { + txRate = (txcfg->tx_rate - VHT_RATE_ID) + 44; + } + else + { + txRate = (txcfg->tx_rate - HT_RATE_ID) + 12; + } + + if (priv->pshare->is_40m_bw==2) + { +// get_txsc_AC(priv, priv->pmib->dot11RFEntry.dot11channel); + if(txcfg->pstat && is_VHT_rate(txcfg->tx_rate) && (txcfg->pstat->tx_bw == HT_CHANNEL_WIDTH_80 + && (is_auto_rate(priv, txcfg->pstat) || is_fixedVHTTxRate(priv, txcfg->pstat)) + ) ) + { + pdesc->Dword5 |= set_desc((0 << TXdesc_92E_DataScSHIFT) | (0 << TXdesc_92E_RtsScSHIFT)); + pdesc->Dword5 |= set_desc(0x2 << TXdesc_92E_DataBwSHIFT); + + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M && + txcfg->pstat && (txcfg->pstat->vht_cap_buf.vht_cap_info & cpu_to_le32(BIT(5)))) + n_txshort = 1; + } + else if(txcfg->pstat && is_MCS_rate(txcfg->tx_rate) && (txcfg->pstat->tx_bw >= HT_CHANNEL_WIDTH_20_40 + && (is_auto_rate(priv, txcfg->pstat) || is_fixedMCSTxRate(priv, txcfg->pstat)) + ) ) + { + pdesc->Dword5 |= set_desc((priv->pshare->txsc_40 << TXdesc_92E_DataScSHIFT) | (priv->pshare->txsc_40 << TXdesc_92E_RtsScSHIFT)); + pdesc->Dword5 |= set_desc(0x1 << TXdesc_92E_DataBwSHIFT); + + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_))) + n_txshort = 1; + } + else + { + pdesc->Dword5 |= set_desc((priv->pshare->txsc_20 << TXdesc_92E_DataScSHIFT) | (priv->pshare->txsc_20 << TXdesc_92E_RtsScSHIFT)); + + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) + n_txshort = 1; + } + } + else + if (priv->pshare->is_40m_bw) { + if (txcfg->pstat && (txcfg->pstat->tx_bw == HT_CHANNEL_WIDTH_20_40) +#ifdef WIFI_11N_2040_COEXIST + && !(priv->pmib->dot11nConfigEntry.dot11nCoexist && (((OPMODE & WIFI_AP_STATE) && + (priv->bg_ap_timeout || orForce20_Switch20Map(priv) + )) +#ifdef CLIENT_MODE + || ((OPMODE & WIFI_STATION_STATE) && priv->coexist_connection && + (txcfg->pstat->ht_ie_len) && !(txcfg->pstat->ht_ie_buf.info0 & _HTIE_STA_CH_WDTH_)) +#endif + )) +#endif + + ) { + + pdesc->Dword5 |= set_desc((1 << TXdesc_92E_DataBwSHIFT) | (3 << TXdesc_92E_DataScSHIFT)); + + { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_))) + n_txshort = 1; + } + } + else { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + pdesc->Dword5 |= set_desc((2 << TXdesc_92E_DataScSHIFT) | (2 << TXdesc_92E_RtsScSHIFT)); + else + pdesc->Dword5 |= set_desc((1 << TXdesc_92E_DataScSHIFT) | (1 << TXdesc_92E_RtsScSHIFT)); + + { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) + n_txshort = 1; + } + } + } else { + { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) + n_txshort = 1; + } + } + + + if ( + ( txcfg->pstat && + ((txcfg->pstat->aggre_mthd == AGGRE_MTHD_MPDU_AMSDU) || (txcfg->pstat->aggre_mthd == AGGRE_MTHD_MPDU)) + && txcfg->aggre_en ) || + ((txcfg->aggre_en >= FG_AGGRE_MPDU) && (txcfg->aggre_en <= FG_AGGRE_MPDU_BUFFER_LAST)) + ){ + int TID = ((struct sk_buff *)txcfg->pframe)->cb[1]; + if (txcfg->pstat->ADDBA_ready[TID] && !txcfg->pstat->low_tp_disable_ampdu) { + + + pdesc->Dword2 |= set_desc(TXdesc_92E_AggEn); + + + /* + * assign aggr size + */ + + // assign aggr density + if (txcfg->privacy) { + //8812_11n_iot, set TxAmpduDsty=7 for 20M WPA2 + if ((priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) && (!priv->pshare->is_40m_bw)) + pdesc->Dword2 |= set_desc(7 << TX_AmpduDstySHIFT); // according to DWA-160 A2 + else + pdesc->Dword2 |= set_desc(5 << TX_AmpduDstySHIFT); // according to WN111v2 + } + else { + pdesc->Dword2 |= set_desc(((txcfg->pstat->ht_cap_buf.ampdu_para & _HTCAP_AMPDU_SPC_MASK_) >> _HTCAP_AMPDU_SPC_SHIFT_) << TX_AmpduDstySHIFT); + } + } + } + + // for STBC + if (priv->pmib->dot11nConfigEntry.dot11nSTBC && txcfg->pstat ) // 2012 10 31 for test + { + if((txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_RX_STBC_CAP_)) + || (txcfg->pstat->vht_cap_buf.vht_cap_info & cpu_to_le32(_VHTCAP_RX_STBC_CAP_))){ + +#ifdef BEAMFORMING_SUPPORT + u1Byte Idx = 0; + PRT_BEAMFORMING_ENTRY pEntry; + pEntry = Beamforming_GetEntryByMacId(priv, txcfg->pstat->aid, &Idx); + if(pEntry == NULL) +#endif + pdesc->Dword5 |= set_desc(1 << TXdesc_92E_DataStbcSHIFT); + + } + + } + } + else // legacy rate + { + txRate = get_rate_index_from_ieee_value((UINT8)txcfg->tx_rate); + if (is_CCK_rate(txcfg->tx_rate) && (txcfg->tx_rate != 2)) { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + (priv->pmib->dot11ErpInfo.longPreambleStaNum > 0)) + ; // txfw->txshort = 0 + else { + if (txcfg->pstat) + bg_txshort = (priv->pmib->dot11RFEntry.shortpreamble) && + (txcfg->pstat->useShortPreamble); + else + bg_txshort = priv->pmib->dot11RFEntry.shortpreamble; + } + } + + if (priv->pshare->is_40m_bw==2) { +// get_txsc_AC(priv, priv->pmib->dot11RFEntry.dot11channel); + pdesc->Dword5 |= set_desc((priv->pshare->txsc_20 << TXdesc_92E_DataScSHIFT) | (priv->pshare->txsc_20 << TXdesc_92E_RtsScSHIFT)); + } + else + if (priv->pshare->is_40m_bw) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + pdesc->Dword5 |= set_desc((2 << TXdesc_92E_DataScSHIFT) | (2 << TXdesc_92E_RtsScSHIFT)); + else + pdesc->Dword5 |= set_desc((1 << TXdesc_92E_DataScSHIFT) | (1 << TXdesc_92E_RtsScSHIFT)); + } + + if (bg_txshort) + pdesc->Dword5 |= set_desc(TXdesc_92E_DataShort); + + } + + if(AC_SIGMA_MODE != AC_SIGMA_NONE) //for 11ac logo + if(txcfg->pstat) + { + txcfg->pstat->no_rts=0; + } + + if (txcfg->need_ack) { // unicast + if (frag_idx == 0) + RtsCheck(priv, txcfg, &bRtsEnable, &bCts2SelfEnable, &bHwRts, &bErpProtect, &bNProtect); + } + + RtsRate = find_rts_rate(priv, txcfg->tx_rate, bErpProtect); + if(bRtsEnable && CheckCts2SelfEnable(RtsRate)) + { + bRtsEnable = FALSE; + bCts2SelfEnable = TRUE; + } + + if(txcfg->pstat) //8812_11n_iot, only vht clnt support cca_rts, //for 11ac logo + RtsCheckAC(priv, txcfg, &bRtsEnable, &bCts2SelfEnable, &bHwRts); + + if(bRtsEnable) + pdesc->Dword3 |= set_desc(TX_RtsEn); + if(bCts2SelfEnable) + pdesc->Dword3 |= set_desc(TX_CTS2Self); + if(bHwRts) + pdesc->Dword3 |= set_desc(TX_HwRtsEn); + + if (bRtsEnable || bCts2SelfEnable ) { + + unsigned int rtsTxRateIdx = get_rate_index_from_ieee_value(RtsRate); + if (bErpProtect) { + unsigned char rtsShort = 0; + if (is_CCK_rate(RtsRate) && (RtsRate != 2)) { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + (priv->pmib->dot11ErpInfo.longPreambleStaNum > 0)) + rtsShort = 0; // do nothing + else { + if (txcfg->pstat) + rtsShort = (priv->pmib->dot11RFEntry.shortpreamble) && + (txcfg->pstat->useShortPreamble); + else + rtsShort = priv->pmib->dot11RFEntry.shortpreamble; + } + } + pdesc->Dword5 |= (rtsShort == 1)? set_desc(TXdesc_92E_RtsShort): 0; + + } + pdesc->Dword4 |= set_desc((rtsTxRateIdx & TXdesc_92E_RtsRateMask) << TXdesc_92E_RtsRateSHIFT); + pdesc->Dword4 |= set_desc((0xf & TXdesc_92E_RtsRateFBLmtMask) << TXdesc_92E_RtsRateFBLmtSHIFT); + + } + + + if(priv->pshare->rf_ft_var.txforce != 0xFF) + { + if(priv->pshare->rf_ft_var.sgiforce == 1) + n_txshort = 1; + else if(priv->pshare->rf_ft_var.sgiforce == 2) + n_txshort = 0; + } + + if(n_txshort == 1 && txcfg->pstat && txcfg->pstat->sta_in_firmware == 1) + pdesc->Dword5 |= set_desc(TXdesc_92E_DataShort); + + +#ifdef DRVMAC_LB + if (priv->pmib->miscEntry.drvmac_lb && (priv->pmib->miscEntry.lb_mlmp == 4)) { + txRate = rate_select; + if (rate_select++ > 0x1b) + rate_select = 0; + + pdesc->Dword3 |= set_desc(TXdesc_92E_DisDataFB|TXdesc_92E_DisRtsFB|TXdesc_92E_UseRate); + } +#endif + + + if((priv->pshare->rf_ft_var.txforce != 0xff) +#ifdef BEAMFORMING_SUPPORT + && (!txcfg->ndpa) +#endif + ) { + pdesc->Dword3 |= set_desc(TXdesc_92E_DisDataFB|TXdesc_92E_DisRtsFB|TXdesc_92E_UseRate); + pdesc->Dword4 |= set_desc((priv->pshare->rf_ft_var.txforce & TXdesc_92E_DataRateMask) << TXdesc_92E_DataRateSHIFT); + } + else + pdesc->Dword4 |= set_desc((txRate & TXdesc_92E_DataRateMask) << TXdesc_92E_DataRateSHIFT); + + +#if 1 + if (priv->pshare->rf_ft_var.rts_init_rate) { + pdesc->Dword4 &= set_desc(~(TX_RtsRateMask_8812 << TX_RtsRateSHIFT_8812)); + pdesc->Dword4 |= set_desc(((priv->pshare->rf_ft_var.rts_init_rate) & TX_RtsRateMask_8812) << TX_RtsRateSHIFT_8812); + } + if ((priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) && + (TX_RtsRateMask_8812&(get_desc(pdesc->Dword4)>>TX_RtsRateSHIFT_8812)) <4 ) + pdesc->Dword4 |= set_desc((4 & TX_RtsRateMask_8812) << TX_RtsRateSHIFT_8812); +#else + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + pdesc->Dword4 |= set_desc((4 & TX_RtsRateMask_8812) << TX_RtsRateSHIFT_8812); + +#endif + + if (txcfg->need_ack) { + // give retry limit to management frame + if (txcfg->q_num == MANAGE_QUE_NUM) { + pdesc->Dword4 |= set_desc(TXdesc_92E_RtyLmtEn); + + if (GetFrameSubType(txcfg->phdr) == WIFI_PROBERSP) { + ; // 0 no need to set + } +#ifdef WDS + else if ((GetFrameSubType(txcfg->phdr) == WIFI_PROBEREQ) && (txcfg->pstat->state & WIFI_WDS)) { + pdesc->Dword4 |= set_desc((2 & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } +#endif + else { + pdesc->Dword4 |= set_desc((6 & TXdesc_92E_DataRtyLmtMask) << TXdesc_92E_DataRtyLmtSHIFT); + } + } +#ifdef WDS + else if (txcfg->wdsIdx >= 0) { + if (txcfg->pstat->rx_avarage == 0) { + pdesc->Dword4 |= set_desc(TX_RtyLmtEn); + pdesc->Dword4 |= set_desc((3 & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } + } +#endif + + else if (is_MCS_rate(txcfg->pstat->current_tx_rate) && (txcfg->pstat->IOTPeer==HT_IOT_PEER_INTEL) && (txcfg->pstat->retry_inc) + && !(txcfg->pstat->leave) && priv->pshare->intel_rty_lmt) { + pdesc->Dword4 |= set_desc(TXdesc_92E_RtyLmtEn); + pdesc->Dword4 |= set_desc((priv->pshare->intel_rty_lmt & TXdesc_92E_DataRtyLmtMask) << TXdesc_92E_DataRtyLmtSHIFT); + } + + else if ((txcfg->pstat->IOTPeer==HT_IOT_PEER_BROADCOM) && (txcfg->pstat->retry_inc) && !(txcfg->pstat->leave)) { + pdesc->Dword4 |= set_desc(TXdesc_92E_RtyLmtEn); + pdesc->Dword4 |= set_desc((0x20 & TXdesc_92E_DataRtyLmtMask) << TXdesc_92E_DataRtyLmtSHIFT); + } + + if (priv->pshare->rf_ft_var.tx_pwr_ctrl && txcfg->pstat && (txcfg->fr_type == _SKB_FRAME_TYPE_)) { + if (txcfg->pstat->hp_level == 1) { + pdesc->Dword5 |= set_desc((2 & TXdesc_8812_TxPwrOffetMask) << TXdesc_8812_TxPwrOffetSHIFT); + } + } + +#ifdef BEAMFORMING_SUPPORT + if(txcfg->ndpa) { + unsigned char *pFrame = (unsigned char*)txcfg->phdr; + if(IsCtrlNDPA(pFrame) || IsMgntNDPA(pFrame)) { + //SET_TX_DESC_DATA_RETRY_LIMIT_8812(pDesc, 5); + //SET_TX_DESC_RETRY_LIMIT_ENABLE_8812(pDesc, 1); + pdesc->Dword4 &= set_desc(~(TXdesc_92E_DataRtyLmtMask << TXdesc_92E_DataRtyLmtSHIFT)); + pdesc->Dword4 |= set_desc(TXdesc_92E_RtyLmtEn|((0x05 & TXdesc_92E_DataRtyLmtMask) << TXdesc_92E_DataRtyLmtSHIFT)); + + if(IsMgntNDPA(pFrame)) //0xe0 + { + pdesc->Dword3 |= set_desc((1 &TXdesc_92E_NDPAMASK)<pstat->WirelessMode & WIRELESS_MODE_AC_5G) && (txcfg->pstat->IOTPeer!=HT_IOT_PEER_BROADCOM)) + pdesc->Dword3 |= set_desc((2 &TXdesc_92E_NDPAMASK)<Dword3 |= set_desc((1 &TXdesc_92E_NDPAMASK)<Dword3 |= set_desc((1 &TXdesc_92E_NDPAMASK)<Dword3)); + } + } else +#endif + + { + if((priv->pmib->dot11nConfigEntry.dot11nLDPC) && (txcfg->pstat) && (!txcfg->pstat->disable_ldpc) && + ((txcfg->pstat->ht_cap_len && cpu_to_le16(txcfg->pstat->ht_cap_buf.ht_cap_info) & _HTCAP_SUPPORT_RX_LDPC_) || + (txcfg->pstat->vht_cap_len && (cpu_to_le32(txcfg->pstat->vht_cap_buf.vht_cap_info) & BIT(RX_LDPC_E)))) + ) { + pdesc->Dword5 |= set_desc(TXdesc_92E_DataLDPC); + } + } + } +} + +#endif + +#ifdef CONFIG_WLAN_HAL +static void +rtl88XX_fill_fwinfo( + struct rtl8192cd_priv *priv, + struct tx_insn *txcfg, + unsigned int frag_idx, + PTX_DESC_DATA_88XX pdesc_data +) +{ + char n_txshort = 0, bg_txshort = 0; +// int erp_protection = 0, n_protection = 0; +// unsigned char rate; + unsigned char txRate = 0; +#ifdef DRVMAC_LB + static unsigned int rate_select = 0; +#endif +// BOOLEAN bRtsEnable; + BOOLEAN bErpProtect; + BOOLEAN bNProtect; +// BOOLEAN bHwRts; +// BOOLEAN bCts2SelfEnable; + unsigned char RtsRate; + +#ifdef MP_TEST + if (OPMODE & WIFI_MP_STATE) { + #ifdef RTK_AC_SUPPORT + if (is_VHT_rate(txcfg->tx_rate)) { + txRate = (txcfg->tx_rate - VHT_RATE_ID) + 44; + } + else + #endif + if (is_MCS_rate(txcfg->tx_rate)) { // HT rates + txRate = (txcfg->tx_rate - HT_RATE_ID) + 12; + } + else{ + txRate = get_rate_index_from_ieee_value((UINT8)txcfg->tx_rate); + } + + if (priv->pshare->is_40m_bw == 2) { + pdesc_data->dataSC = 0x0; + pdesc_data->RTSSC = 0x0; + pdesc_data->dataBW = 0x2; + + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M) + n_txshort = 1; + } + else if (priv->pshare->is_40m_bw == 1) { + pdesc_data->dataSC = 0x0; + pdesc_data->RTSSC = 0x0; + pdesc_data->dataBW = 0x1; + + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M) + n_txshort = 1; + } + else { + pdesc_data->dataSC = 0x0; + pdesc_data->RTSSC = 0x0; + pdesc_data->dataBW = 0x0; + + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M) + n_txshort = 1; + } + + if (txcfg->retry) { + pdesc_data->rtyLmtEn = TRUE; + pdesc_data->dataRtyLmt = txcfg->retry; + } + + pdesc_data->dataRate = txRate; + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + pdesc_data->RTSRate = 4; + + if(n_txshort == 1) + pdesc_data->dataShort = 1; + + return; + } +#endif + + if (is_MCS_rate(txcfg->tx_rate)) // HT rates + { +#ifdef RTK_AC_SUPPORT + if(is_VHT_rate(txcfg->tx_rate)) + { + txRate = (txcfg->tx_rate - VHT_RATE_ID) + 44; + } + else +#endif + { + txRate = (txcfg->tx_rate - HT_RATE_ID) + 12; + } + +#ifdef RTK_AC_SUPPORT + if (priv->pshare->is_40m_bw==2) + { + if(txcfg->pstat && (txcfg->pstat->tx_bw == HT_CHANNEL_WIDTH_80 + && (is_auto_rate(priv, txcfg->pstat) || is_fixedVHTTxRate(priv, txcfg->pstat)) + ) ) + { + pdesc_data->dataSC = 0; + pdesc_data->RTSSC = 0; + pdesc_data->dataBW = 2; + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M && + (txcfg->pstat->vht_cap_buf.vht_cap_info & cpu_to_le32(BIT(5)))) + n_txshort = 1; + } // TODO: Pedro, in 8812: is_MCS_rate(txcfg->tx_rate) + else if(txcfg->pstat && (txcfg->pstat->tx_bw >= HT_CHANNEL_WIDTH_20_40 + && (is_auto_rate(priv, txcfg->pstat) || is_fixedMCSTxRate(priv, txcfg->pstat)) + ) ) + { + pdesc_data->dataSC = priv->pshare->txsc_40; + pdesc_data->RTSSC = priv->pshare->txsc_40; + pdesc_data->dataBW = 1; + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M && + (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_))) + n_txshort = 1; + } + else + { + pdesc_data->dataSC = priv->pshare->txsc_20; + pdesc_data->RTSSC = priv->pshare->txsc_20; + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) + n_txshort = 1; + } + } + else +#endif + if (priv->pshare->is_40m_bw) { + if (txcfg->pstat && (txcfg->pstat->tx_bw == HT_CHANNEL_WIDTH_20_40) +#ifdef WIFI_11N_2040_COEXIST + && !(priv->pmib->dot11nConfigEntry.dot11nCoexist && (((OPMODE & WIFI_AP_STATE) && + (priv->bg_ap_timeout || orForce20_Switch20Map(priv) + )) +#ifdef CLIENT_MODE + || ((OPMODE & WIFI_STATION_STATE) && priv->coexist_connection && + (txcfg->pstat->ht_ie_len) && !(txcfg->pstat->ht_ie_buf.info0 & _HTIE_STA_CH_WDTH_)) +#endif + )) +#endif + + ) { + pdesc_data->dataBW = 1; + pdesc_data->dataSC = 3; + { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M && + (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_))) + n_txshort = 1; + } + } + else { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) { + pdesc_data->dataSC = 2; + pdesc_data->RTSSC = 2; + } else { + pdesc_data->dataSC = 1; + pdesc_data->RTSSC = 1; + } + + { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) + n_txshort = 1; + } + } + } else { + { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) + n_txshort = 1; + } + } + + + if ( + ( AMSDU_ENABLE && AMPDU_ENABLE && txcfg->aggre_en ) || + ((txcfg->aggre_en >= FG_AGGRE_MPDU) && (txcfg->aggre_en <= FG_AGGRE_MPDU_BUFFER_LAST)) + ){ + int TID = ((struct sk_buff *)txcfg->pframe)->cb[1]; + if (txcfg->pstat->ADDBA_ready[TID] && !txcfg->pstat->low_tp_disable_ampdu) { + pdesc_data->aggEn = TRUE; + + /* + * assign aggr size + */ + +#ifdef CONFIG_WLAN_HAL + // TODO: ³o¸Ì¬O«ü«DAC chip ??? + // TODO: check ¬O§_¦³¦b¨ä¥L¦ì¸m.. +#else + if(GET_CHIP_VER(priv) != VERSION_8812E) + { + if (priv->pshare->rf_ft_var.diffAmpduSz) { + pdesc->Dword6 |= set_desc((txcfg->pstat->diffAmpduSz & 0xffff) << TX_MCS1gMaxSHIFT | TX_UseMaxLen); + + if (GET_CHIP_VER(priv)!=VERSION_8812E) + pdesc->Dword7 |= set_desc(txcfg->pstat->diffAmpduSz & 0xffff0000); + } + } +#endif // CONFIG_WLAN_HAL + + // assign aggr density + if (txcfg->privacy) { +#if 1 // TODO: for test two STA TP + pdesc_data->ampduDensity = 7; +#else + pdesc_data->ampduDensity = 5; +#endif + } + else { +#if 0 // TODO: for test two STA TP + pdesc_data->ampduDensity = 5; +#else + pdesc_data->ampduDensity = ((txcfg->pstat->ht_cap_buf.ampdu_para & _HTCAP_AMPDU_SPC_MASK_) >> _HTCAP_AMPDU_SPC_SHIFT_); +#endif + } + pdesc_data->maxAggNum = ((1<<(txcfg->pstat->ht_cap_buf.ampdu_para & 0x03))*5)>>1; + } + } + + // for STBC + if (priv->pmib->dot11nConfigEntry.dot11nSTBC && (txcfg->pstat) && + ((txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_RX_STBC_CAP_)) +#ifdef RTK_AC_SUPPORT + || (txcfg->pstat->vht_cap_buf.vht_cap_info & cpu_to_le32(_VHTCAP_RX_STBC_CAP_)) +#endif + )){ +#ifdef BEAMFORMING_SUPPORT + u1Byte Idx = 0; + PRT_BEAMFORMING_ENTRY pEntry; + pEntry = Beamforming_GetEntryByMacId(priv, txcfg->pstat->aid, &Idx); + if(pEntry == NULL) +#endif + if((get_rf_mimo_mode(priv) == MIMO_2T2R) || (get_rf_mimo_mode(priv) == MIMO_3T3R)) + pdesc_data->dataStbc = 1; + } + // LDPC +#ifdef BEAMFORMING_SUPPORT + if(!txcfg->ndpa) +#endif + if((priv->pmib->dot11nConfigEntry.dot11nLDPC) && (txcfg->pstat) && (!txcfg->pstat->disable_ldpc) && + ((txcfg->pstat->ht_cap_len && cpu_to_le16(txcfg->pstat->ht_cap_buf.ht_cap_info) & _HTCAP_SUPPORT_RX_LDPC_) +#ifdef RTK_AC_SUPPORT + || (txcfg->pstat->vht_cap_len && (cpu_to_le32(txcfg->pstat->vht_cap_buf.vht_cap_info) & BIT(RX_LDPC_E))) +#endif + )) { + pdesc_data->dataLdpc = 1; + } + } + else // legacy rate + { + txRate = get_rate_index_from_ieee_value((UINT8)txcfg->tx_rate); + if (is_CCK_rate(txcfg->tx_rate) && (txcfg->tx_rate != 2)) { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + (priv->pmib->dot11ErpInfo.longPreambleStaNum > 0)) + ; // txfw->txshort = 0 + else { + if (txcfg->pstat) + bg_txshort = (priv->pmib->dot11RFEntry.shortpreamble) && + (txcfg->pstat->useShortPreamble); + else + bg_txshort = priv->pmib->dot11RFEntry.shortpreamble; + } + } + +#ifdef RTK_AC_SUPPORT + if (priv->pshare->is_40m_bw==2) { + pdesc_data->dataSC = priv->pshare->txsc_20; + pdesc_data->RTSSC = priv->pshare->txsc_20; + } + else +#endif + if (priv->pshare->is_40m_bw) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) { + pdesc_data->dataSC = 2; + pdesc_data->RTSSC = 2; + } else { + pdesc_data->dataSC = 1; + pdesc_data->RTSSC = 1; + } + } + + if (bg_txshort) { + pdesc_data->dataShort = 1; + } + + } + +#if defined(CONFIG_WLAN_HAL_8192EE) + if (GET_CHIP_VER(priv)==VERSION_8192E && priv->pmib->dot11RFEntry.bcn2path ) + pdesc_data->TXAnt = 1; // use path A for 1ss CCK rate tx +#endif + + if (txcfg->need_ack) { // unicast + if (frag_idx == 0) + RtsCheck(priv, txcfg, &pdesc_data->RTSEn, &pdesc_data->CTS2Self, &pdesc_data->HWRTSEn, &bErpProtect, &bNProtect); + } + RtsRate = find_rts_rate(priv, txcfg->tx_rate, bErpProtect); + if(pdesc_data->RTSEn && CheckCts2SelfEnable(RtsRate)) + { + pdesc_data->RTSEn = FALSE; + pdesc_data->CTS2Self = TRUE; + } + + if (pdesc_data->CTS2Self || pdesc_data->RTSEn) + { + unsigned int rtsTxRateIdx = get_rate_index_from_ieee_value(RtsRate); + if (bErpProtect) { + unsigned char rtsShort = 0; + if (is_CCK_rate(RtsRate) && (RtsRate != 2)) { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + (priv->pmib->dot11ErpInfo.longPreambleStaNum > 0)) + rtsShort = 0; // do nothing + else { + if (txcfg->pstat) + rtsShort = (priv->pmib->dot11RFEntry.shortpreamble) && + (txcfg->pstat->useShortPreamble); + else + rtsShort = priv->pmib->dot11RFEntry.shortpreamble; + } + } + pdesc_data->RTSShort = (rtsShort == 1) ? TRUE : FALSE; + } + + pdesc_data->RTSRate = rtsTxRateIdx; + pdesc_data->RTSRateFBLmt = 0xf; + + } + + if(priv->pshare->rf_ft_var.txforce != 0xFF) + { + if(priv->pshare->rf_ft_var.sgiforce == 1) + n_txshort = 1; + else if(priv->pshare->rf_ft_var.sgiforce == 2) + n_txshort = 0; + } + if(n_txshort == 1 && txcfg->pstat && txcfg->pstat->sta_in_firmware == 1) + { + pdesc_data->dataShort = 1; + } + + +#ifdef DRVMAC_LB + if (priv->pmib->miscEntry.drvmac_lb && (priv->pmib->miscEntry.lb_mlmp == 4)) { + txRate = rate_select; + if (rate_select++ > 0x1b) + rate_select = 0; + + pdesc_data->disDataFB = TRUE; + pdesc_data->disRTSFB = TRUE; + pdesc_data->useRate = TRUE; + } +#endif + + if((priv->pshare->rf_ft_var.txforce != 0xff) +#ifdef BEAMFORMING_SUPPORT + && (!txcfg->ndpa) +#endif + ){ + pdesc_data->useRate = TRUE; + pdesc_data->dataRate = priv->pshare->rf_ft_var.txforce; + } else { + pdesc_data->dataRate = txRate; + } + + +#if 1 + if (priv->pshare->rf_ft_var.rts_init_rate) { + pdesc_data->RTSRate = priv->pshare->rf_ft_var.rts_init_rate; + } + if ((priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) && + (pdesc_data->RTSRate)<4) { + pdesc_data->RTSRate = 4; + } +#else + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + pdesc->Dword4 |= set_desc((4 & TX_RtsRateMask_8812) << TX_RtsRateSHIFT_8812); + +#endif + + if (txcfg->need_ack) { + // give retry limit to management frame + if (txcfg->q_num == MANAGE_QUE_NUM) { + pdesc_data->rtyLmtEn = TRUE; + // TODO: ???? for hw tx sc... how to do + if (GetFrameSubType(txcfg->phdr) == WIFI_PROBERSP) { + ; // 0 no need to set + } +#ifdef WDS + else if ((GetFrameSubType(txcfg->phdr) == WIFI_PROBEREQ) && (txcfg->pstat->state & WIFI_WDS)) { + pdesc_data->dataRtyLmt = 2; + } +#endif + else { + pdesc_data->dataRtyLmt = 6; + } + } +#ifdef WDS + else if (txcfg->wdsIdx >= 0) { + if (txcfg->pstat->rx_avarage == 0) { + pdesc_data->rtyLmtEn = TRUE; + pdesc_data->dataRtyLmt = 3; + } + } +#endif + else if (txcfg->pstat && !txcfg->fixed_rate) + { + if (priv->pshare->rf_ft_var.low_retry_rssi_thd && txcfg->pstat->rssi + && (txcfg->pstat->rssi < priv->pshare->rf_ft_var.low_retry_rssi_thd)) { + if ((txcfg->tx_rate <= _9M_RATE_) || + ((_MCS0_RATE_ == txcfg->tx_rate) || (_MCS1_RATE_ == txcfg->tx_rate))) { + pdesc_data->rtyLmtEn = TRUE; + pdesc_data->dataRtyLmt = 0x04; + } else { + pdesc_data->rtyLmtEn = TRUE; + pdesc_data->dataRtyLmt = 0x0c; + } + } else if (priv->pshare->rf_ft_var.low_rate_low_retry + && ((txcfg->tx_rate <= _9M_RATE_) + || (_MCS0_RATE_ == txcfg->tx_rate) || (_MCS1_RATE_ == txcfg->tx_rate))) { + pdesc_data->rtyLmtEn = TRUE; + pdesc_data->dataRtyLmt = 0x08; + } else if (is_MCS_rate(txcfg->tx_rate) && (txcfg->pstat->IOTPeer==HT_IOT_PEER_INTEL) && (txcfg->pstat->retry_inc) + && !(txcfg->pstat->leave) && priv->pshare->intel_rty_lmt) { + pdesc_data->rtyLmtEn = TRUE; + pdesc_data->dataRtyLmt = priv->pshare->intel_rty_lmt; + } else if ((txcfg->pstat->IOTPeer==HT_IOT_PEER_BROADCOM) && (txcfg->pstat->retry_inc) && !(txcfg->pstat->leave)) { + pdesc_data->rtyLmtEn = TRUE; + pdesc_data->dataRtyLmt = 0x20; + } + } + + + // High power + if (priv->pshare->rf_ft_var.tx_pwr_ctrl && txcfg->pstat && (txcfg->fr_type == _SKB_FRAME_TYPE_)) { + if (txcfg->pstat->hp_level == 1) + { +#if defined(CONFIG_WLAN_HAL_8192EE) && defined(HIGH_POWER_EXT_PA) + if (GET_CHIP_VER(priv)==VERSION_8192E && priv->pshare->rf_ft_var.use_ext_pa) + pdesc_data->TXPowerOffset = 3; // -11 dB + else +#endif + pdesc_data->TXPowerOffset = 2; // -7 dB + } + } + +#ifdef BEAMFORMING_SUPPORT + if(txcfg->ndpa) { + unsigned char *pFrame = (unsigned char*)txcfg->phdr; + if(IsCtrlNDPA(pFrame) || IsMgntNDPA(pFrame)) { + pdesc_data->dataRtyLmt = 5; + pdesc_data->rtyLmtEn = TRUE; + if(IsMgntNDPA(pFrame)) //0xe0 + { + pdesc_data->ndpa = 1; + } + else // 0x54 + { + if(!IS_TEST_CHIP(priv)) + { + if ((txcfg->pstat->WirelessMode & WIRELESS_MODE_AC_5G) && (txcfg->pstat->IOTPeer!=HT_IOT_PEER_BROADCOM)) + pdesc_data->ndpa= 2; + else + pdesc_data->ndpa= 1; + + } + else + { + pdesc_data->ndpa = 1; + } + } + } +} +#endif + + } +} +#endif // CONFIG_WLAN_HAL +#if (CONFIG_WLAN_NOT_HAL_EXIST == 1) +void rtl8192cd_fill_fwinfo(struct rtl8192cd_priv *priv, struct tx_insn* txcfg, struct tx_desc *pdesc, unsigned int frag_idx) +{ + char n_txshort = 0, bg_txshort = 0; + //int erp_protection = 0, n_protection = 0; + //unsigned char rate; + unsigned char txRate = 0; +#ifdef DRVMAC_LB + static unsigned int rate_select = 0; +#endif + BOOLEAN bRtsEnable = FALSE; + BOOLEAN bErpProtect = FALSE; + BOOLEAN bNProtect = FALSE; + BOOLEAN bHwRts = FALSE; + BOOLEAN bCts2SelfEnable = FALSE; + unsigned char RtsRate; + +#ifdef MP_TEST + if (OPMODE & WIFI_MP_STATE) { + if (is_MCS_rate(txcfg->tx_rate)) { // HT rates + txRate = (txcfg->tx_rate - HT_RATE_ID) + 12; + } + else{ + txRate = get_rate_index_from_ieee_value((UINT8)txcfg->tx_rate); + } + + if (priv->pshare->CurrentChannelBW) { + pdesc->Dword4 |= set_desc(TX_DataBw | (3&TX_DataScMask) << TX_DataScSHIFT); + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40 && priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M) + n_txshort = 1; + else if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_80 && priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M) + n_txshort = 1; + } + else { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M) + n_txshort = 1; + } + + if (txcfg->retry) + pdesc->Dword5 |= set_desc((txcfg->retry & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT | TX_RtyLmtEn); + + if(n_txshort == 1) + pdesc->Dword5 |= set_desc(TX_SGI); + + pdesc->Dword5 |= set_desc((txRate & TX_DataRateMask) << TX_DataRateSHIFT); + +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + pdesc->Dword4 |= set_desc((4 & TX_RtsRateMask) << TX_RtsRateSHIFT); + //if (is_CCK_rate(txRate)) + //pdesc->Dword5 |= set_desc((4 & TX_DataRateMask) << TX_DataRateSHIFT); + } +#endif + + return; + } +#endif + + if (priv->pmib->dot11RFEntry.txbf == 1) { + pdesc->Dword2 &= set_desc(0x03ffffff); // clear related bits + pdesc->Dword2 |= set_desc(1 << TX_TxAntCckSHIFT); // Set Default CCK rate with 1T + pdesc->Dword2 |= set_desc(1 << TX_TxAntlSHIFT); // Set Default Legacy rate with 1T + pdesc->Dword2 |= set_desc(1 << TX_TxAntHtSHIFT); // Set Default Ht rate + } + if(priv->pmib->dot11RFEntry.bcn2path){ + pdesc->Dword2 &= set_desc(0x03ffffff); // clear related bits + pdesc->Dword2 |= set_desc(1 << TX_TxAntCckSHIFT); // Set Default CCK rate with 1T + } + + if (is_MCS_rate(txcfg->tx_rate)) // HT rates + { + txRate = (txcfg->tx_rate - HT_RATE_ID) + 12; + + if (priv->pmib->dot11RFEntry.txbf == 1) { + if (txRate <= 0x12) { + pdesc->Dword2 |= set_desc(3 << TX_TxAntHtSHIFT); // Set Ht rate < MCS6 with 2T + } + } + + if (priv->pshare->is_40m_bw) { + if (txcfg->pstat && (txcfg->pstat->tx_bw == HT_CHANNEL_WIDTH_20_40) +#ifdef WIFI_11N_2040_COEXIST + && !(priv->pmib->dot11nConfigEntry.dot11nCoexist && (((OPMODE & WIFI_AP_STATE) && + (priv->bg_ap_timeout || orForce20_Switch20Map(priv) + )) +#ifdef CLIENT_MODE + || ((OPMODE & WIFI_STATION_STATE) && priv->coexist_connection && + (txcfg->pstat->ht_ie_len) && !(txcfg->pstat->ht_ie_buf.info0 & _HTIE_STA_CH_WDTH_)) +#endif + )) +#endif + + ) { + pdesc->Dword4 |= set_desc(TX_DataBw | (3 << TX_DataScSHIFT)); + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if ((txcfg->fixed_rate) || (GET_CHIP_VER(priv)!=VERSION_8188E)) +#endif + { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_))) + n_txshort = 1; + } + } + else { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + pdesc->Dword4 |= set_desc((2 << TX_DataScSHIFT) | (2 << TX_RtsScSHIFT)); + else + pdesc->Dword4 |= set_desc((1 << TX_DataScSHIFT) | (1 << TX_RtsScSHIFT)); + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if ((txcfg->fixed_rate) || (GET_CHIP_VER(priv)!=VERSION_8188E)) +#endif + { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) + n_txshort = 1; + } + } + } else { +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if ((txcfg->fixed_rate) || (GET_CHIP_VER(priv)!=VERSION_8188E)) +#endif + { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) + n_txshort = 1; + } + } + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if ((GET_CHIP_VER(priv)==VERSION_8188E) && !(txcfg->fixed_rate)) { + if (txcfg->pstat->ht_current_tx_info & TX_USE_SHORT_GI) + n_txshort = 1; + } +#endif + + if ((txcfg->aggre_en >= FG_AGGRE_MPDU) && (txcfg->aggre_en <= FG_AGGRE_MPDU_BUFFER_LAST)) { + int TID = ((struct sk_buff *)txcfg->pframe)->cb[1]; + if (txcfg->pstat->ADDBA_ready[TID] && !txcfg->pstat->low_tp_disable_ampdu) { +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) + pdesc->Dword2 |= set_desc(TXdesc_88E_AggEn); + else +#endif + pdesc->Dword1 |= set_desc(TX_AggEn); + + /* + * assign aggr size + */ + if (priv->pshare->rf_ft_var.diffAmpduSz) { + pdesc->Dword6 |= set_desc((txcfg->pstat->diffAmpduSz & 0xffff) << TX_MCS1gMaxSHIFT | TX_UseMaxLen); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)!=VERSION_8188E) +#endif + pdesc->Dword7 |= set_desc(txcfg->pstat->diffAmpduSz & 0xffff0000); + } + // assign aggr density + if (txcfg->privacy) { +#ifdef CONFIG_RTL_92D_SUPPORT + if ((priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) && (!priv->pshare->is_40m_bw)) + pdesc->Dword2 |= set_desc(7 << TX_AmpduDstySHIFT); // according to DWA-160 A2 + else +#endif + pdesc->Dword2 |= set_desc(5 << TX_AmpduDstySHIFT); // according to WN111v2 + } + else { + pdesc->Dword2 |= set_desc(((txcfg->pstat->ht_cap_buf.ampdu_para & _HTCAP_AMPDU_SPC_MASK_) >> _HTCAP_AMPDU_SPC_SHIFT_) << TX_AmpduDstySHIFT); + } + } + //set Break +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) != VERSION_8188E) +#endif + { + if ((txcfg->q_num >=1 && txcfg->q_num <=4)) { + if (txcfg->pstat != priv->pshare->CurPstat[txcfg->q_num-1]) { + pdesc->Dword1 |= set_desc(TX_BK); + priv->pshare->CurPstat[txcfg->q_num-1] = txcfg->pstat; + } + } else { + pdesc->Dword1 |= set_desc(TX_BK); + } + } + } + + // for STBC +#ifdef CONFIG_RTL_92C_SUPPORT + if (GET_CHIP_VER(priv) != VERSION_8192C) +#endif + if (priv->pmib->dot11nConfigEntry.dot11nSTBC && + txcfg->pstat && (txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_RX_STBC_CAP_)) && + ((get_rf_mimo_mode(priv) == MIMO_2T2R) || (get_rf_mimo_mode(priv) == MIMO_3T3R))) + pdesc->Dword4 |= set_desc(1 << TX_DataStbcSHIFT); + } + else // legacy rate + { + txRate = get_rate_index_from_ieee_value((UINT8)txcfg->tx_rate); + if (is_CCK_rate(txcfg->tx_rate) && (txcfg->tx_rate != 2)) { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + (priv->pmib->dot11ErpInfo.longPreambleStaNum > 0)) + ; // txfw->txshort = 0 + else { + if (txcfg->pstat) + bg_txshort = (priv->pmib->dot11RFEntry.shortpreamble) && + (txcfg->pstat->useShortPreamble); + else + bg_txshort = priv->pmib->dot11RFEntry.shortpreamble; + } + } + if (priv->pshare->is_40m_bw) { + if (priv->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_BELOW) + pdesc->Dword4 |= set_desc((2 << TX_DataScSHIFT) | (2 << TX_RtsScSHIFT)); + else + pdesc->Dword4 |= set_desc((1 << TX_DataScSHIFT) | (1 << TX_RtsScSHIFT)); + } + + if (bg_txshort) + pdesc->Dword4 |= set_desc(TX_DataShort); + } + + if (txcfg->need_ack) { // unicast + if (frag_idx == 0) + RtsCheck(priv, txcfg, &bRtsEnable, &bCts2SelfEnable, &bHwRts, &bErpProtect, &bNProtect); + } + + RtsRate = find_rts_rate(priv, txcfg->tx_rate, bErpProtect); + if(bRtsEnable && CheckCts2SelfEnable(RtsRate)) + { + bRtsEnable = FALSE; + bCts2SelfEnable = TRUE; + } + +// if(bErpProtect) +// priv->pshare->phw->bErpProtection = TRUE; + + if(bRtsEnable) + pdesc->Dword4 |= set_desc(TX_RtsEn); + if(bCts2SelfEnable) + pdesc->Dword4 |= set_desc(TX_CTS2Self); + if(bHwRts) + pdesc->Dword4 |=set_desc(TX_HwRtsEn); + + if (bRtsEnable || bCts2SelfEnable) { + unsigned int rtsTxRateIdx = get_rate_index_from_ieee_value(RtsRate); + if (bErpProtect) { + unsigned char rtsShort = 0; + if (is_CCK_rate(RtsRate) && (RtsRate != 2)) { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && + (priv->pmib->dot11ErpInfo.longPreambleStaNum > 0)) + rtsShort = 0; // do nothing + else { + if (txcfg->pstat) + rtsShort = (priv->pmib->dot11RFEntry.shortpreamble) && + (txcfg->pstat->useShortPreamble); + else + rtsShort = priv->pmib->dot11RFEntry.shortpreamble; + } + } + pdesc->Dword4 |= (rtsShort == 1)? set_desc(TX_RtsShort): 0; + } + + pdesc->Dword4 |= set_desc((rtsTxRateIdx & TX_RtsRateMask) << TX_RtsRateSHIFT); + pdesc->Dword5 |= set_desc((0xf & TX_RtsRateFBLmtMask) << TX_RtsRateFBLmtSHIFT); + //8192SE Must specified BW mode while sending RTS ... + if (priv->pshare->is_40m_bw) + pdesc->Dword4 |= set_desc(TX_RtsBw); + + } + + if(priv->pshare->rf_ft_var.txforce != 0xFF) + { + if(priv->pshare->rf_ft_var.sgiforce == 1) + n_txshort = 1; + else if(priv->pshare->rf_ft_var.sgiforce == 2) + n_txshort = 0; + } + if(n_txshort == 1 && txcfg->pstat && txcfg->pstat->sta_in_firmware == 1) + pdesc->Dword5 |= set_desc(TX_SGI); + +#ifdef DRVMAC_LB + if (priv->pmib->miscEntry.drvmac_lb && (priv->pmib->miscEntry.lb_mlmp == 4)) { + txRate = rate_select; + if (rate_select++ > 0x1b) + rate_select = 0; + + pdesc->Dword4 |= set_desc(TX_UseRate); + pdesc->Dword4 |= set_desc(TX_DisDataFB); + pdesc->Dword4 |= set_desc(TX_DisRtsFB);// disable RTS fall back + } +#endif + + if(priv->pshare->rf_ft_var.txforce != 0xff) { + pdesc->Dword4 |= set_desc(TX_UseRate); + pdesc->Dword5 |= set_desc((priv->pshare->rf_ft_var.txforce & TX_DataRateMask) << TX_DataRateSHIFT); + } else { + pdesc->Dword5 |= set_desc((txRate & TX_DataRateMask) << TX_DataRateSHIFT); + } + +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + pdesc->Dword4 |= set_desc((4 & TX_RtsRateMask) << TX_RtsRateSHIFT); + //if (is_CCK_rate(txRate)) + //pdesc->Dword5 |= set_desc((4 & TX_DataRateMask) << TX_DataRateSHIFT); + } +#endif + + if (txcfg->need_ack) { + // give retry limit to management frame +#ifndef DRVMAC_LB + if (txcfg->q_num == MANAGE_QUE_NUM) { + pdesc->Dword5 |= set_desc(TX_RtyLmtEn); + if (GetFrameSubType(txcfg->phdr) == WIFI_PROBERSP) { + ; // 0 no need to set + } +#ifdef WDS + else if ((GetFrameSubType(txcfg->phdr) == WIFI_PROBEREQ) && (txcfg->pstat->state & WIFI_WDS)) { + pdesc->Dword5 |= set_desc((2 & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } +#endif + else { + pdesc->Dword5 |= set_desc((6 & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } + } +#ifdef WDS + else if (txcfg->wdsIdx >= 0) { + if (txcfg->pstat->rx_avarage == 0) { + pdesc->Dword5 |= set_desc(TX_RtyLmtEn); + pdesc->Dword5 |= set_desc((3 & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } + } +#endif +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + else if (priv->pshare->rf_ft_var.low_retry_rssi_thd && !txcfg->fixed_rate && txcfg->pstat->rssi + && (txcfg->pstat->rssi < priv->pshare->rf_ft_var.low_retry_rssi_thd)) { + if ((txcfg->tx_rate <= _9M_RATE_) || + ((_MCS0_RATE_ == txcfg->tx_rate) || (_MCS1_RATE_ == txcfg->tx_rate))) { + pdesc->Dword5 |= set_desc(TX_RtyLmtEn); + pdesc->Dword5 |= set_desc((0x04 & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } else { + pdesc->Dword5 |= set_desc(TX_RtyLmtEn); + pdesc->Dword5 |= set_desc((0x08 & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } + } else if (priv->pshare->rf_ft_var.low_rate_low_retry && !txcfg->fixed_rate + && ((txcfg->tx_rate <= _9M_RATE_) + || (_MCS0_RATE_ == txcfg->tx_rate) || (_MCS1_RATE_ == txcfg->tx_rate))) { + pdesc->Dword5 |= set_desc(TX_RtyLmtEn); + pdesc->Dword5 |= set_desc((0x08 & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } +#endif + else if (is_MCS_rate(txcfg->tx_rate) && (txcfg->pstat->IOTPeer==HT_IOT_PEER_INTEL) && (txcfg->pstat->retry_inc) + + + && !(txcfg->pstat->leave) && priv->pshare->intel_rty_lmt) { + pdesc->Dword5 |= set_desc(TX_RtyLmtEn); + pdesc->Dword5 |= set_desc((priv->pshare->intel_rty_lmt & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } + + else if ((txcfg->pstat->IOTPeer==HT_IOT_PEER_BROADCOM) && (txcfg->pstat->retry_inc) && !(txcfg->pstat->leave)) { + pdesc->Dword5 |= set_desc(TX_RtyLmtEn); + pdesc->Dword5 |= set_desc((0x20 & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } +#endif //end DRVMAC_LB + + // High power mechanism + //if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)) + + { + if (priv->pshare->rf_ft_var.tx_pwr_ctrl && txcfg->pstat && (txcfg->fr_type == _SKB_FRAME_TYPE_)) { + if ((txcfg->pstat->hp_level == 1) +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + || ((priv->pshare->DNC_on) && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G)) +#endif + ) { + int pwr = (priv->pshare->rf_ft_var.min_pwr_idex > 16) ? 16: priv->pshare->rf_ft_var.min_pwr_idex; + pwr &= 0x1e; + pdesc->Dword6 |= set_desc(((-pwr) & TX_TxAgcAMask) << TX_TxAgcASHIFT); + pdesc->Dword6 |= set_desc(((-pwr) & TX_TxAgcBMask) << TX_TxAgcBSHIFT); + } + } + } + } +} +#endif + + +#ifdef TX_EARLY_MODE +__MIPS16 +__IRAM_IN_865X +static void insert_emcontent(struct rtl8192cd_priv *priv, struct tx_insn* txcfg, unsigned char *buf) +{ + struct stat_info *pstat = txcfg->pstat; + unsigned int dw[2]; + + dw[0] = set_desc((pstat->empkt_num & 0xf) | + (((pstat->empkt_len[0]+pstat->emextra_len) << 4) & 0xfff0) | + (((pstat->empkt_len[1]+pstat->emextra_len) << 16) & 0xfff0000) | + (((pstat->empkt_len[2]+pstat->emextra_len) << 28) & 0xf0000000) + ); + dw[1] = set_desc((((pstat->empkt_len[2]+pstat->emextra_len) >> 4) & 0xff) | + (((pstat->empkt_len[3]+pstat->emextra_len) << 8) & 0xfff00) | + (((pstat->empkt_len[4]+pstat->emextra_len) << 20) & 0xfff00000) + ); + memcpy(buf, dw, 8); +} +#endif + + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL +int rtl88XX_signin_txdesc(struct rtl8192cd_priv *priv, struct tx_insn* txcfg, unsigned char convHdr) +{ + struct tx_desc_info *pswdescinfo, *pdescinfo; + unsigned int fr_len, tx_len, i, keyid; + u2Byte *tx_head; + u4Byte q_num; + unsigned char *da, *pbuf, *pwlhdr, *pmic, *picv; + struct rtl8192cd_hw *phw; +#ifdef TX_SHORTCUT + int fit_shortcut=0, idx=0; +#endif + + + PHCI_TX_DMA_MANAGER_88XX ptx_dma; + u32 halQNum; + PHCI_TX_DMA_QUEUE_STRUCT_88XX cur_q; + PTX_BUFFER_DESCRIPTOR cur_txbd; + TX_DESC_DATA_88XX desc_data; + +#ifdef CONFIG_IEEE80211W + unsigned int isBIP = 0; +#endif +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + BOOLEAN isWiFiHdr = TRUE; +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + + keyid=0; + pmic=NULL; + picv=NULL; + + if (txcfg->tx_rate == 0) { + DEBUG_ERR("tx_rate=0!\n"); + txcfg->tx_rate = find_rate(priv, NULL, 0, 1); + } + + q_num = txcfg->q_num; + + phw = GET_HW(priv); + + halQNum = GET_HAL_INTERFACE(priv)->MappingTxQueueHandler(priv, (u32)q_num); + ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + cur_q = &(ptx_dma->tx_queue[halQNum]); + cur_txbd = cur_q->pTXBD_head + cur_q->host_idx; + memset(&desc_data, 0, sizeof(TX_DESC_DATA_88XX)); + + tx_head = &(cur_q->host_idx); + + pswdescinfo = get_txdesc_info(priv->pshare->pdesc_info, q_num); + + tx_len = txcfg->fr_len; + + if (txcfg->fr_type == _SKB_FRAME_TYPE_) + pbuf = ((struct sk_buff *)txcfg->pframe)->data; + else + pbuf = (unsigned char*)txcfg->pframe; + +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + // this condition is 802.3 header + if ((GET_CHIP_VER(priv)==VERSION_8814A) && (convHdr==HW_TX_SC_HEADER_CONV)) + isWiFiHdr = FALSE; +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + + +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr) +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + { + da = get_da((unsigned char *)txcfg->phdr); + } + +#ifdef CONFIG_IEEE80211W + if(txcfg->isPMF && IS_MCAST(da)) + { + isBIP = 1; + txcfg->iv = 0; + txcfg->fr_len += 10; // 10: MMIE length + } +#endif + + // TODO: hw tx shorcut, reuse txdesc only support AES... +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr) +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + // in case of default key, then find the key id + if (GetPrivacy((txcfg->phdr))) + { +#ifdef WDS + if (txcfg->wdsIdx >= 0) { + if (txcfg->pstat) + keyid = txcfg->pstat->keyid; + else + keyid = 0; + } + else +#endif + +#ifdef __DRAYTEK_OS__ + if (!IEEE8021X_FUN) + keyid = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + else { + if (IS_MCAST(GetAddr1Ptr ((unsigned char *)txcfg->phdr)) || !txcfg->pstat) + keyid = priv->pmib->dot11GroupKeysTable.keyid; + else + keyid = txcfg->pstat->keyid; + } +#else + + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_WEP_104_PRIVACY_) { + if(IEEE8021X_FUN && txcfg->pstat) { +#ifdef A4_STA + if (IS_MCAST(da) && !(txcfg->pstat->state & WIFI_A4_STA)) +#else + if(IS_MCAST(da)) +#endif + keyid = 0; + else + keyid = txcfg->pstat->keyid; + } + else { + keyid = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + } + } +#endif + } + + + for (i=0; i < txcfg->frg_num; i++) + { + pdescinfo = pswdescinfo + *tx_head; + +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + // TODO: hw tx shortcut no support fragment ? Qos Control bit ?? + if (isWiFiHdr) +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (i != 0) + { + memset(&desc_data, 0, sizeof(TX_DESC_DATA_88XX)); + + // we have to allocate wlan_hdr + pwlhdr = (UINT8 *)get_wlanhdr_from_poll(priv); + if (pwlhdr == (UINT8 *)NULL) + { + DEBUG_ERR("System-bug... should have enough wlan_hdr\n"); + return (txcfg->frg_num - i); + } + // other MPDU will share the same seq with the first MPDU + memcpy((void *)pwlhdr, (void *)(txcfg->phdr), txcfg->hdr_len); // data pkt has 24 bytes wlan_hdr + } + else + { +#ifdef WIFI_WMM + if (txcfg->pstat /*&& (is_qos_data(txcfg->phdr))*/) { + if ((GetFrameSubType(txcfg->phdr) & (WIFI_DATA_TYPE | BIT(6) | BIT(7))) == (WIFI_DATA_TYPE | BIT(7))) { + unsigned char tempQosControl[2]; + memset(tempQosControl, 0, 2); + tempQosControl[0] = ((struct sk_buff *)txcfg->pframe)->cb[1]; +#ifdef WMM_APSD + if ( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (APSD_ENABLE) && (txcfg->pstat) && (txcfg->pstat->state & WIFI_SLEEP_STATE) && + (!GetMData(txcfg->phdr)) && + ((((tempQosControl[0] == 7) || (tempQosControl[0] == 6)) && (txcfg->pstat->apsd_bitmap & 0x01)) || + (((tempQosControl[0] == 5) || (tempQosControl[0] == 4)) && (txcfg->pstat->apsd_bitmap & 0x02)) || + (((tempQosControl[0] == 3) || (tempQosControl[0] == 0)) && (txcfg->pstat->apsd_bitmap & 0x08)) || + (((tempQosControl[0] == 2) || (tempQosControl[0] == 1)) && (txcfg->pstat->apsd_bitmap & 0x04)))) + tempQosControl[0] |= BIT(4); +#endif + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST) + tempQosControl[0] |= BIT(7); + + if (priv->pmib->dot11nConfigEntry.dot11nTxNoAck) + tempQosControl[0] |= BIT(5); + + memcpy((void *)GetQosControl((txcfg->phdr)), tempQosControl, 2); + } + } +#endif + +#ifdef BEAMFORMING_SUPPORT + if(!txcfg->ndpa) +#endif + assign_wlanseq(GET_HW(priv), txcfg->phdr, txcfg->pstat, GET_MIB(priv) +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , txcfg->is_11s +#endif + ); + pwlhdr = txcfg->phdr; + } +#ifdef BEAMFORMING_SUPPORT + if(!txcfg->ndpa) +#endif + { +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr) +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + { + SetDuration(pwlhdr, 0); + } + } + + // TODO: how to fill some field in rtl88XX_fill_fwinfo + rtl88XX_fill_fwinfo(priv, txcfg, i, &desc_data); + + +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + if (GetFrameSubType(txcfg->phdr) == WIFI_PSPOLL) + desc_data.navUseHdr = _TRUE; + + if (priv->ps_state) + SetPwrMgt(pwlhdr); + else + ClearPwrMgt(pwlhdr); + } +#endif +#ifdef BEAMFORMING_SUPPORT + if(txcfg->ndpa) + desc_data.navUseHdr = _TRUE; +#endif + +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr) +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (i != (txcfg->frg_num - 1)) + { + SetMFrag(pwlhdr); + if (i == 0) { + fr_len = (txcfg->frag_thrshld - txcfg->llc); + tx_len -= (txcfg->frag_thrshld - txcfg->llc); + } + else { + fr_len = txcfg->frag_thrshld; + tx_len -= txcfg->frag_thrshld; + } + } + else // last seg, or the only seg (frg_num == 1) + { + fr_len = tx_len; + ClearMFrag(pwlhdr); + } + +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr) +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + { + SetFragNum((pwlhdr), i); + } + + if (((i == 0) && (txcfg->fr_type == _SKB_FRAME_TYPE_)) +#ifdef BEAMFORMING_SUPPORT + || txcfg->ndpa +#endif + ) { + pdescinfo->type = _PRE_ALLOCLLCHDR_; + } + else { + pdescinfo->type = _PRE_ALLOCHDR_; + } + +#ifdef _11s_TEST_MODE_ + mesh_debug_tx9(txcfg, pdescinfo); +#endif + + if(txcfg->fr_type == _SKB_FRAME_TYPE_) + desc_data.tid = ((struct sk_buff *)txcfg->pframe)->cb[1]; + + + if (i != (txcfg->frg_num - 1)) { + desc_data.frag = _TRUE; + } + + if (txcfg->pstat) { + if (txcfg->pstat->aid != MANAGEMENT_AID) { + desc_data.rateId = txcfg->pstat->ratr_idx; + desc_data.macId = REMAP_AID(txcfg->pstat); + } +#ifdef BEAMFORMING_SUPPORT + if((priv->pmib->dot11RFEntry.txbf == 1) && + ((txcfg->pstat->ht_cap_len && (txcfg->pstat->ht_cap_buf.txbf_cap)) +#ifdef RTK_AC_SUPPORT + ||(txcfg->pstat->vht_cap_len && (cpu_to_le32(txcfg->pstat->vht_cap_buf.vht_cap_info) & BIT(SU_BFEE_S))) +#endif + )){ + desc_data.p_aid = txcfg->pstat->p_aid; + desc_data.g_id = txcfg->pstat->g_id; + } +#endif + } else { + desc_data.rateId = ARFR_BMC; +#ifdef BEAMFORMING_SUPPORT + if (priv->pmib->dot11RFEntry.txbf == 1) + desc_data.g_id = 1; +#endif + } + + desc_data.dataRateFBLmt = 0x1F; + + if (txcfg->fixed_rate) { + desc_data.disDataFB = _TRUE; + desc_data.disRTSFB = _TRUE; + desc_data.useRate = _TRUE; + } + + + if(txcfg->pstat && txcfg->pstat->sta_in_firmware != 1) + desc_data.useRate = _TRUE; + + +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr) +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (txcfg->privacy) { + desc_data.secType = txcfg->privacy; +#ifdef CONFIG_IEEE80211W + if (UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF)) +#else + if (UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) +#endif + { + desc_data.swCrypt = TRUE; + desc_data.icv = txcfg->icv; + desc_data.mic = txcfg->mic; + desc_data.iv = txcfg->iv; + } else { + // hw encrypt + desc_data.swCrypt = FALSE; + switch(txcfg->privacy) { + case _WEP_104_PRIVACY_: + case _WEP_40_PRIVACY_: + desc_data.icv = 0; + desc_data.mic = 0; + desc_data.iv = txcfg->iv; + wep_fill_iv(priv, pwlhdr, txcfg->hdr_len, keyid); + break; + + case _TKIP_PRIVACY_: + desc_data.icv = 0; + desc_data.mic = txcfg->mic; + desc_data.iv = txcfg->iv; + tkip_fill_encheader(priv, pwlhdr, txcfg->hdr_len, keyid); + break; + + #if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + case _WAPI_SMS4_: + desc_data.icv = 0; + desc_data.mic = 0; + desc_data.iv = txcfg->iv; + break; + #endif + + case _CCMP_PRIVACY_: + //michal also hardware... + desc_data.icv = 0; + desc_data.mic = 0; + desc_data.iv = txcfg->iv; + aes_fill_encheader(priv, pwlhdr, txcfg->hdr_len, keyid); + break; + + default: + DEBUG_ERR("Unknow privacy\n"); + break; + } + } + } + +#ifdef WLAN_HAL_HW_AES_IV + if ((txcfg->privacy == _CCMP_PRIVACY_) && + ( +#ifdef CONFIG_IEEE80211W + (UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF)) +#else + (UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) +#endif + == FALSE)) { + desc_data.secType = txcfg->privacy; + desc_data.swCrypt = FALSE; + desc_data.icv = 0; + desc_data.mic = 0; + desc_data.iv = 0; + desc_data.hwAESIv = TRUE; + + if (isWiFiHdr == TRUE) { + desc_data.iv = txcfg->iv; + // when desc_data.hwAESIv == TRUE, hw auto fill AES iv + // aes_fill_encheader(priv, pwlhdr, txcfg->hdr_len, keyid); + } + } +#endif // WLAN_HAL_HW_AES_IV + + // below is for sw desc info + // TODO: hw tx shortcut recycle....sw desc. +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr == FALSE) { + pdescinfo->pframe = NULL; + } else +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + { + pdescinfo->pframe = pwlhdr; + } + +#if defined(WIFI_WMM) && defined(WMM_APSD) + pdescinfo->priv = priv; + pdescinfo->pstat = txcfg->pstat; +#endif + +#ifdef TX_SHORTCUT + if (!priv->pmib->dot11OperationEntry.disable_txsc && txcfg->pstat && + (txcfg->fr_type == _SKB_FRAME_TYPE_) && + (txcfg->frg_num == 1) && + ((txcfg->privacy == 0) +#ifdef CONFIG_RTL_WAPI_SUPPORT + || (txcfg->privacy == _WAPI_SMS4_) +#endif +#ifdef CONFIG_IEEE80211W + || (!UseSwCrypto(priv, txcfg->pstat, FALSE, txcfg->isPMF)) +#else + || (!UseSwCrypto(priv, txcfg->pstat, FALSE)) +#endif + ) && + ( +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + (isWiFiHdr == FALSE) ? TRUE : +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + (!GetMData(txcfg->phdr)) + ) + ) { + +#ifdef CONFIG_RTK_MESH + if( txcfg->is_11s) { + idx = get_tx_sc_free_entry(priv, txcfg->pstat, &priv->ethhdr); + } else +#endif + { +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr == FALSE) { + idx = get_tx_sc_free_entry(priv, txcfg->pstat, pbuf); + } else +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + { + idx = get_tx_sc_free_entry(priv, txcfg->pstat, pbuf - sizeof(struct wlan_ethhdr_t)); + } + } +#ifdef CONFIG_RTK_MESH + if( txcfg->is_11s) { + memcpy((void *)&txcfg->pstat->tx_sc_ent[idx].ethhdr, &priv->ethhdr, sizeof(struct wlan_ethhdr_t)); + } else +#endif + { +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr == FALSE) + { + memcpy((void *)&txcfg->pstat->tx_sc_ent[idx].ethhdr, pbuf, sizeof(struct wlan_ethhdr_t)); + } else +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + { + memcpy((void *)&txcfg->pstat->tx_sc_ent[idx].ethhdr, pbuf - sizeof(struct wlan_ethhdr_t), sizeof(struct wlan_ethhdr_t)); + } + } + + txcfg->pstat->protection = priv->pmib->dot11ErpInfo.protection; + txcfg->pstat->ht_protection = priv->ht_protection; + txcfg->pstat->tx_sc_ent[idx].sc_keyid = keyid; + txcfg->pstat->tx_sc_ent[idx].pktpri = ((struct sk_buff *)txcfg->pframe)->cb[1]; + fit_shortcut = 1; + +#ifdef CONFIG_WLAN_HAL_8814AE + if (GET_CHIP_VER(priv)==VERSION_8814A) { +#ifdef WLAN_HAL_HW_TX_SHORTCUT_REUSE_TXDESC + desc_data.txwifiCp = TRUE; +#endif // WLAN_HAL_HW_TX_SHORTCUT_REUSE_TXDESC +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (convHdr == HW_TX_SC_BACKUP_HEADER) { + desc_data.macCp = TRUE; // backup 802.11 header info. + desc_data.smhEn = FALSE; + } else if (convHdr == HW_TX_SC_HEADER_CONV) { + desc_data.macCp = FALSE; + desc_data.smhEn = TRUE; // auto conv hdr (802.3 -> 802.11) + // TODO: consider AES for HW_TX_SHORTCUT_HDR_CONV + // Eth hdr 14 bytes => gen llc 8 bytes + // gen iv 8 bytes + // skb: ethHdr + data + // ethHdr + (iv + llc) + data + // BD[0]: txDesc, BD[1]: ethHdr, BD[2]: iv+llc, BD[3]: data + } +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + } +#endif // CONFIG_WLAN_HAL_8814AE + } + else { + if (txcfg->pstat) { + for (idx=0; idxSetShortCutTxBuffSizeHandler(priv, txcfg->pstat->tx_sc_ent[idx].hal_hw_desc, 0); + } + } + } +#endif + + // TODO: Currently, we don't care WAPI + if (txcfg->privacy) + { + if (txcfg->privacy == _WAPI_SMS4_) + { + pdescinfo->pstat = txcfg->pstat; + pdescinfo->rate = txcfg->tx_rate; + } +#ifdef CONFIG_IEEE80211W + else if (!UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF)) +#else + else if (!UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) +#endif + { + pdescinfo->pstat = txcfg->pstat; + pdescinfo->rate = txcfg->tx_rate; + } + // TODO: why swCrypto doesn't set these two swDesc ? + } + else + { + pdescinfo->pstat = txcfg->pstat; + pdescinfo->rate = txcfg->tx_rate; + } + + if (0 == txcfg->fr_len) + goto swenc_end; + + #ifdef CONFIG_RTL_WAPI_SUPPORT + //panic_printk("%s:%d privacy=%d\n", __FUNCTION__, __LINE__,txcfg->privacy); + if (txcfg->privacy == _WAPI_SMS4_) + { + //panic_printk("%s:%d\n", __FUNCTION__, __LINE__); + SecSWSMS4Encryption(priv, txcfg); + desc_data.pMic = ((struct sk_buff *)txcfg->pframe)->data+txcfg->fr_len; + } + #endif + /*** start sw encryption ***/ +#ifdef CONFIG_IEEE80211W + if (txcfg->privacy && UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE),txcfg->isPMF)) { +#else + if (txcfg->privacy && UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) { +#endif + if (txcfg->privacy == _TKIP_PRIVACY_ || + txcfg->privacy == _WEP_40_PRIVACY_ || + txcfg->privacy == _WEP_104_PRIVACY_) { + + //picvdescinfo = pswdescinfo + *tx_head; + + // append ICV first... + picv = get_icv_from_poll(priv); + if (picv == NULL) { + DEBUG_ERR("System-Buf! can't alloc picv\n"); + BUG(); + } + + pdescinfo->buf_type[1] = _PRE_ALLOCICVHDR_; + pdescinfo->buf_pframe[1] = picv; + pdescinfo->buf_len[1] = txcfg->icv; + + desc_data.pIcv = picv; + + if (i == 0) { + tkip_icv(picv, + pwlhdr + txcfg->hdr_len + txcfg->iv, txcfg->llc, + pbuf, txcfg->fr_len); + } else { + tkip_icv(picv, + NULL, 0, + pbuf, txcfg->fr_len); + } + + if ((i == 0) && (txcfg->llc != 0)) { + if (txcfg->privacy == _TKIP_PRIVACY_) { + tkip_encrypt(priv, pwlhdr, txcfg->hdr_len, + pwlhdr + txcfg->hdr_len + 8, sizeof(struct llc_snap), + pbuf, txcfg->fr_len, + picv, txcfg->icv); + } else { + wep_encrypt(priv, pwlhdr, txcfg->hdr_len, + pwlhdr + txcfg->hdr_len + 4, sizeof(struct llc_snap), + pbuf, txcfg->fr_len, + picv, txcfg->icv, + txcfg->privacy); + } + } else { // not first segment or no snap header + if (txcfg->privacy == _TKIP_PRIVACY_) { + tkip_encrypt(priv, pwlhdr, txcfg->hdr_len, + NULL, 0, + pbuf, txcfg->fr_len, + picv, txcfg->icv); + } else { + wep_encrypt(priv, pwlhdr, txcfg->hdr_len, + NULL, 0, + pbuf, txcfg->fr_len, + picv, txcfg->icv, + txcfg->privacy); + } + } + + } else if (txcfg->privacy == _CCMP_PRIVACY_) { + //pmicdescinfo = pswdescinfo + *tx_head; + + // append MIC first... + pmic = get_mic_from_poll(priv); + if (pmic == NULL) { + DEBUG_ERR("System-Buf! can't alloc pmic\n"); + BUG(); + } + + pdescinfo->buf_type[1] = _PRE_ALLOCMICHDR_; + pdescinfo->buf_pframe[1] = pmic; + pdescinfo->buf_len[1] = txcfg->mic; + + desc_data.pMic = pmic; + + // then encrypt all (including ICV) by AES + if ((i == 0)&&(txcfg->llc != 0)) { // encrypt 3 segments ==> llc, mpdu, and mic +#ifdef CONFIG_IEEE80211W + if (isBIP) { + BIP_encrypt(priv, pwlhdr, + pwlhdr + txcfg->hdr_len + 8, + pbuf, txcfg->fr_len, + pmic,txcfg->isPMF); + } + else { + aesccmp_encrypt(priv, pwlhdr, + pwlhdr + txcfg->hdr_len + 8, + pbuf, txcfg->fr_len, + pmic,txcfg->isPMF); + } +#else + aesccmp_encrypt(priv, pwlhdr, + pwlhdr + txcfg->hdr_len + 8, + pbuf, txcfg->fr_len, + pmic); +#endif + } else { // encrypt 2 segments ==> mpdu and mic +#ifdef CONFIG_IEEE80211W + if (isBIP) { + BIP_encrypt(priv, pwlhdr, + NULL, + pbuf, txcfg->fr_len, + pmic,txcfg->isPMF); + } + else { + aesccmp_encrypt(priv, pwlhdr, + NULL, + pbuf, txcfg->fr_len, + pmic,txcfg->isPMF); + } +#else + aesccmp_encrypt(priv, pwlhdr, + NULL, + pbuf, txcfg->fr_len, + pmic); +#endif + } + } + } + /*** end sw encryption ***/ +swenc_end: + + desc_data.pHdr = pwlhdr; + desc_data.hdrLen = txcfg->hdr_len; + desc_data.llcLen = (i==0 ? txcfg->llc : 0); + desc_data.frLen = fr_len; + + if (fr_len != 0) { + desc_data.pBuf = pbuf; + } + +#ifdef CONFIG_8814_AP_MAC_VERI + if (txcfg->fr_len != 0) //for mgt frame + { + if((desc_data.pBuf[0]==0x55) && (desc_data.pBuf[1]==0x55)) + { + desc_data.dataRtyLmt = 10; + desc_data.macId = priv->macID_temp; + desc_data.disDataFB = _FALSE; + desc_data.disRTSFB = _FALSE; + desc_data.useRate= _TRUE; + + desc_data.dataRate = 0x17; // HT MCS6 + desc_data.RTSRate = 0x8; + desc_data.rateId = 5; + + if(priv->lowestRate_TXDESCen) + { + desc_data.moreData = 1; + desc_data.dataRateFBLmt = priv->lowestRate; + desc_data.RTSRateFBLmt = priv->lowestRate; + desc_data.rtyLmtEn = 1; + } + else + { + desc_data.rtyLmtEn = 0; + } + + desc_data.RTSEn = TRUE; + +#ifdef VERIFY_AP_FAST_EDCA + desc_data.aggEn = 0; // no agg. + desc_data.dataRate = 4; // OFDM rate + desc_data.RTSEn = FALSE; +#endif + } + } +#endif + +#ifdef TX_SHORTCUT + if (fit_shortcut) { +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (isWiFiHdr == FALSE) { + desc_data.pHdr = txcfg->phdr; + desc_data.hdrLen = txcfg->fr_len; + desc_data.llcLen = 0; + desc_data.frLen = 0; + } +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + GET_HAL_INTERFACE(priv)->FillShortCutTxHwCtrlHandler( + priv, halQNum, (void *)&desc_data, txcfg->pstat->tx_sc_ent[idx].hal_hw_desc, 0x01); + } else +#endif + { + GET_HAL_INTERFACE(priv)->FillTxHwCtrlHandler(priv, halQNum, (void *)&desc_data); + } + + if (txcfg->fr_len != 0) { + if (i == 0) { + pdescinfo->buf_type[0] = txcfg->fr_type; + } else { + pdescinfo->buf_type[0] = _RESERVED_FRAME_TYPE_; + } + + pdescinfo->buf_pframe[0] = txcfg->pframe; + pdescinfo->buf_len[0] = txcfg->fr_len; + pdescinfo->buf_paddr[0] = get_desc(cur_txbd->TXBD_ELE[2].Dword1);//payload + } + pdescinfo->paddr = get_desc(cur_txbd->TXBD_ELE[1].Dword1);//header address + +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + // TODO: temp for swdesc...should check it.. + if (isWiFiHdr == FALSE) { + pdescinfo->type = _SKB_FRAME_TYPE_; // 802.3 header + payload + pdescinfo->pframe = txcfg->pframe; // skb + + pdescinfo->buf_type[0] = 0; + pdescinfo->buf_pframe[0] = 0; // no packet payload + } +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + +#ifdef TX_SHORTCUT + if (fit_shortcut) { + //descinfo_copy(&txcfg->pstat->tx_sc_ent[idx].swdesc1, pdescinfo); + txcfg->pstat->tx_sc_ent[idx].swdesc1.type = pdescinfo->type; + txcfg->pstat->tx_sc_ent[idx].swdesc1.len = pdescinfo->len; + txcfg->pstat->tx_sc_ent[idx].swdesc1.rate = pdescinfo->rate; + //txcfg->pstat->tx_sc_ent[idx].swdesc1.buf_type[0] = pdescinfo->buf_type[0] + } +#endif + + if (txcfg->fr_len == 0) + { +// printk("%s(%d): fr_len == 0 !!! \n", __FUNCTION__, __LINE__); + goto init_deschead; + } + + pbuf += fr_len; + + } + + +init_deschead: + + // TODO: ...pfrst_dma_desc + GET_HAL_INTERFACE(priv)->SyncSWTXBDHostIdxToHWHandler(priv, halQNum); + return 0; +} +#endif // CONFIG_WLAN_HAL + +#ifdef CONFIG_RTL_8812_SUPPORT +int rtl8192cd_signin_txdesc_8812(struct rtl8192cd_priv *priv, struct tx_insn* txcfg) +{ + struct tx_desc *phdesc, *pdesc, *pndesc, *picvdesc, *pmicdesc, *pfrstdesc; + struct tx_desc_info *pswdescinfo, *pdescinfo, *pndescinfo, *picvdescinfo, *pmicdescinfo; + unsigned int fr_len, tx_len, i, keyid; + int *tx_head, q_num; + unsigned long tmpphyaddr; + unsigned char *da, *pbuf, *pwlhdr, *pmic, *picv; + struct rtl8192cd_hw *phw; + unsigned char q_select; +#ifdef TX_SHORTCUT + int fit_shortcut=0, idx=0; +#endif + unsigned long pfrst_dma_desc=0; + unsigned long *dma_txhead; + + unsigned long flush_addr[20]; + int flush_len[20]; + int flush_num=0; +#ifdef CONFIG_IEEE80211W + unsigned int isBIP = 0; +#endif + + picvdesc=NULL; + keyid=0; + pmic=NULL; + picv=NULL; + q_select=0; + + if (txcfg->tx_rate == 0) { + DEBUG_ERR("tx_rate=0!\n"); + txcfg->tx_rate = find_rate(priv, NULL, 0, 1); + } + + q_num = txcfg->q_num; + + phw = GET_HW(priv); + + dma_txhead = get_txdma_addr(phw, q_num); + tx_head = get_txhead_addr(phw, q_num); + phdesc = get_txdesc(phw, q_num); + pswdescinfo = get_txdesc_info(priv->pshare->pdesc_info, q_num); + + da = get_da((unsigned char *)txcfg->phdr); + +#ifdef CONFIG_IEEE80211W + if (txcfg->isPMF && IS_MCAST(da)) + { + isBIP = 1; + txcfg->iv = 0; + txcfg->fr_len += 10; // 10: MMIE length + } +#endif + tx_len = txcfg->fr_len; + + if (txcfg->fr_type == _SKB_FRAME_TYPE_) + pbuf = ((struct sk_buff *)txcfg->pframe)->data; + else + pbuf = (unsigned char*)txcfg->pframe; + + + tmpphyaddr = get_physical_addr(priv, pbuf, tx_len, PCI_DMA_TODEVICE); + + // in case of default key, then find the key id + if (GetPrivacy((txcfg->phdr))) + { +#ifdef WDS + if (txcfg->wdsIdx >= 0) { + if (txcfg->pstat) + keyid = txcfg->pstat->keyid; + else + keyid = 0; + } + else +#endif + +#ifdef __DRAYTEK_OS__ + if (!IEEE8021X_FUN) + keyid = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + else { + if (IS_MCAST(GetAddr1Ptr ((unsigned char *)txcfg->phdr)) || !txcfg->pstat) + keyid = priv->pmib->dot11GroupKeysTable.keyid; + else + keyid = txcfg->pstat->keyid; + } +#else + + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_WEP_104_PRIVACY_) { + if(IEEE8021X_FUN && txcfg->pstat) { +#ifdef A4_STA + if (IS_MCAST(da) && !(txcfg->pstat->state & WIFI_A4_STA)) +#else + if(IS_MCAST(da)) +#endif + keyid = 0; + else + keyid = txcfg->pstat->keyid; + } + else + keyid = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + } +#endif + + + } + + for(i=0, pfrstdesc= phdesc + (*tx_head); i < txcfg->frg_num; i++) + { + /*------------------------------------------------------------*/ + /* fill descriptor of header + iv + llc */ + /*------------------------------------------------------------*/ + pdesc = phdesc + (*tx_head); + pdescinfo = pswdescinfo + *tx_head; + + //clear all bits + + memset(pdesc, 0, 40); + + if (i != 0) + { + // we have to allocate wlan_hdr + pwlhdr = (UINT8 *)get_wlanhdr_from_poll(priv); + if (pwlhdr == (UINT8 *)NULL) + { + DEBUG_ERR("System-bug... should have enough wlan_hdr\n"); + return (txcfg->frg_num - i); + } + // other MPDU will share the same seq with the first MPDU + memcpy((void *)pwlhdr, (void *)(txcfg->phdr), txcfg->hdr_len); // data pkt has 24 bytes wlan_hdr + pdesc->Dword9 |= set_desc((GetSequence(txcfg->phdr) & TXdesc_92E_TX_SeqMask) << TXdesc_92E_TX_SeqSHIFT); + } + else + { +#ifdef WIFI_WMM + if (txcfg->pstat && (is_qos_data(txcfg->phdr))) { + if ((GetFrameSubType(txcfg->phdr) & (WIFI_DATA_TYPE | BIT(6) | BIT(7))) == (WIFI_DATA_TYPE | BIT(7))) { + unsigned char tempQosControl[2]; + memset(tempQosControl, 0, 2); + tempQosControl[0] = ((struct sk_buff *)txcfg->pframe)->cb[1]; +#ifdef WMM_APSD + if ( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (APSD_ENABLE) && (txcfg->pstat) && (txcfg->pstat->state & WIFI_SLEEP_STATE) && + (!GetMData(txcfg->phdr)) && + ((((tempQosControl[0] == 7) || (tempQosControl[0] == 6)) && (txcfg->pstat->apsd_bitmap & 0x01)) || + (((tempQosControl[0] == 5) || (tempQosControl[0] == 4)) && (txcfg->pstat->apsd_bitmap & 0x02)) || + (((tempQosControl[0] == 3) || (tempQosControl[0] == 0)) && (txcfg->pstat->apsd_bitmap & 0x08)) || + (((tempQosControl[0] == 2) || (tempQosControl[0] == 1)) && (txcfg->pstat->apsd_bitmap & 0x04)))) + tempQosControl[0] |= BIT(4); +#endif + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST) + tempQosControl[0] |= BIT(7); + + if (priv->pmib->dot11nConfigEntry.dot11nTxNoAck) + tempQosControl[0] |= BIT(5); + + memcpy((void *)GetQosControl((txcfg->phdr)), tempQosControl, 2); + } + } +#endif + +#ifdef BEAMFORMING_SUPPORT + if(!txcfg->ndpa) +#endif + assign_wlanseq(GET_HW(priv), txcfg->phdr, txcfg->pstat, GET_MIB(priv) +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , txcfg->is_11s +#endif + ); + + pdesc->Dword9 |= set_desc((GetSequence(txcfg->phdr) & TXdesc_92E_TX_SeqMask) << TXdesc_92E_TX_SeqSHIFT); + pwlhdr = txcfg->phdr; + } +#ifdef BEAMFORMING_SUPPORT + if(!txcfg->ndpa) +#endif + SetDuration(pwlhdr, 0); + + rtl8192cd_fill_fwinfo_8812(priv, txcfg, pdesc, i); + + if (priv->pmib->dot11nConfigEntry.dot11nTxNoAck){ + pdesc->Dword0 |= set_desc(TX_BMC); + pdesc->Dword2 &= set_desc(~(TXdesc_92E_AggEn)); + } + + + //Disable all RTS/CTS //for 11ac logo + if(priv->pshare->rf_ft_var.no_rtscts) { + pdesc->Dword3 &= set_desc(~(TXdesc_92E_HwRtsEn|TXdesc_92E_RtsEn|TXdesc_92E_CTS2Self)); + } + else + { + if(txcfg->pstat) //8812_11n_iot, only vht clnt support cca_rts + if((priv->pshare->rf_ft_var.cca_rts) && (txcfg->pstat->vht_cap_len > 0)) + pdesc->Dword2 |= set_desc((priv->pshare->rf_ft_var.cca_rts & 0x03) << TX_8812_CcaRtsSHIFT); //10b: RTS support dynamic mode CCA secondary + } + + + + + pdesc->Dword0 |= set_desc(40 << TX_OffsetSHIFT); // tx_desc size + + if (IS_MCAST(GetAddr1Ptr((unsigned char *)txcfg->phdr))) + pdesc->Dword0 |= set_desc(TX_BMC); + +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + if (GetFrameSubType(txcfg->phdr) == WIFI_PSPOLL) + pdesc->Dword3 |= set_desc(TXdesc_92E_NAVUSEHDR); + + + if (priv->ps_state) + SetPwrMgt(pwlhdr); + else + ClearPwrMgt(pwlhdr); + } +#endif +#ifdef BEAMFORMING_SUPPORT + if(txcfg->ndpa) + pdesc->Dword3 |= set_desc(TXdesc_92E_NAVUSEHDR); +#endif + + if (i != (txcfg->frg_num - 1)) + { + SetMFrag(pwlhdr); + if (i == 0) { + fr_len = (txcfg->frag_thrshld - txcfg->llc); + tx_len -= (txcfg->frag_thrshld - txcfg->llc); + } + else { + fr_len = txcfg->frag_thrshld; + tx_len -= txcfg->frag_thrshld; + } + } + else // last seg, or the only seg (frg_num == 1) + { + fr_len = tx_len; + ClearMFrag(pwlhdr); + } + SetFragNum((pwlhdr), i); + + if ((i == 0) && (txcfg->fr_type == _SKB_FRAME_TYPE_)) + { + pdesc->Dword7 |= set_desc((txcfg->hdr_len + txcfg->llc) << TX_TxBufSizeSHIFT); + pdesc->Dword0 |= set_desc((fr_len + (get_desc(pdesc->Dword7) & TX_TxBufSizeMask)) << TX_PktSizeSHIFT); + pdesc->Dword0 |= set_desc(TX_FirstSeg); + pdescinfo->type = _PRE_ALLOCLLCHDR_; + } + else + { + pdesc->Dword7 |= set_desc(txcfg->hdr_len << TX_TxBufSizeSHIFT); + pdesc->Dword0 |= set_desc((fr_len + (get_desc(pdesc->Dword7) & TX_TxBufSizeMask)) << TX_PktSizeSHIFT); + pdesc->Dword0 |= set_desc(TX_FirstSeg); + +#ifdef BEAMFORMING_SUPPORT + if(txcfg->ndpa) + pdescinfo->type = _PRE_ALLOCLLCHDR_; + else +#endif + pdescinfo->type = _PRE_ALLOCHDR_; + } + +#ifdef _11s_TEST_MODE_ + mesh_debug_tx9(txcfg, pdescinfo); +#endif + + switch (q_num) { + case HIGH_QUEUE: + q_select = 0x11;// High Queue + break; + case MGNT_QUEUE: + q_select = 0x12; + break; +#if defined(DRVMAC_LB) && defined(WIFI_WMM) + case BE_QUEUE: + q_select = 0; + break; +#endif + default: + // data packet +#ifdef RTL_MANUAL_EDCA + if (priv->pmib->dot11QosEntry.ManualEDCA) { + switch (q_num) { + case VO_QUEUE: + q_select = 6; + break; + case VI_QUEUE: + q_select = 4; + break; + case BE_QUEUE: + q_select = 0; + break; + default: + q_select = 1; + break; + } + } + else +#endif + q_select = ((struct sk_buff *)txcfg->pframe)->cb[1]; + break; + } + pdesc->Dword1 |= set_desc((q_select & TX_QSelMask)<< TX_QSelSHIFT); + + if (i != (txcfg->frg_num - 1)) + pdesc->Dword2 |= set_desc(TX_MoreFrag); + +// Set RateID + if (txcfg->pstat) { + if (txcfg->pstat->aid != MANAGEMENT_AID) { + u8 ratid; + + ratid = txcfg->pstat->ratr_idx; + + pdesc->Dword1 |= set_desc((ratid & TXdesc_92E_RateIDMask) << TX_RateIDSHIFT); + + // Set MacID + pdesc->Dword1 |= set_desc(REMAP_AID(txcfg->pstat) & TXdesc_92E_MacIdMask); + +#ifdef BEAMFORMING_SUPPORT + if((priv->pmib->dot11RFEntry.txbf == 1) && + ((txcfg->pstat->ht_cap_len && (txcfg->pstat->ht_cap_buf.txbf_cap)) || + (txcfg->pstat->vht_cap_len && (cpu_to_le32(txcfg->pstat->vht_cap_buf.vht_cap_info) & BIT(SU_BFEE_S)))) + ){ + pdesc->Dword2 |= set_desc((txcfg->pstat->p_aid & TX_8812_PAIDMask) << TX_8812_PAIDSHIFT); + pdesc->Dword2 |= set_desc((txcfg->pstat->g_id & TX_8812_GIDMask) << TX_8812_GIDSHIFT); + } +#endif + } + } else { + pdesc->Dword1 |= set_desc((ARFR_BMC &TXdesc_92E_RateIDMask)<pmib->dot11RFEntry.txbf == 1) + pdesc->Dword2 |= set_desc((TX_8812_GIDMask) << TX_8812_GIDSHIFT); +#endif + + } + + pdesc->Dword4 |= set_desc((0x1f & TXdesc_92E_DataRateFBLmtMask) << TXdesc_92E_DataRateFBLmtSHIFT); + + if (txcfg->fixed_rate) { + pdesc->Dword3 |= set_desc(TXdesc_92E_DisDataFB|TXdesc_92E_DisRtsFB|TXdesc_92E_UseRate); + } + + if(txcfg->pstat && txcfg->pstat->sta_in_firmware != 1) + pdesc->Dword3 |= set_desc(TXdesc_92E_UseRate); + +#ifdef CONFIG_IEEE80211W + if (!txcfg->need_ack && txcfg->privacy && UseSwCrypto(priv, NULL, TRUE, txcfg->isPMF)) +#else + if (!txcfg->need_ack && txcfg->privacy && UseSwCrypto(priv, NULL, TRUE)) +#endif // CONFIG_IEEE80211W + pdesc->Dword1 &= set_desc( ~(TX_SecTypeMask<< TX_SecTypeSHIFT)); + + if (txcfg->privacy) { +#ifdef CONFIG_IEEE80211W + if (UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF)) { +#else + if (UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) { +#endif // CONFIG_IEEE80211W + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0)+ txcfg->icv + txcfg->mic + txcfg->iv); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7)+ txcfg->iv); + } else { + // hw encrypt + switch(txcfg->privacy) { + case _WEP_104_PRIVACY_: + case _WEP_40_PRIVACY_: + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0) + txcfg->iv); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + txcfg->iv); + wep_fill_iv(priv, pwlhdr, txcfg->hdr_len, keyid); + pdesc->Dword1 |= set_desc(0x1 << TX_SecTypeSHIFT); + break; + + case _TKIP_PRIVACY_: + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0) + txcfg->iv + txcfg->mic); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + txcfg->iv); + tkip_fill_encheader(priv, pwlhdr, txcfg->hdr_len, keyid); + pdesc->Dword1 |= set_desc(0x1 << TX_SecTypeSHIFT); + break; + #if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + case _WAPI_SMS4_: + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0) + txcfg->iv); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + txcfg->iv); + + pdesc->Dword1 |= set_desc(0x2 << TX_SecTypeSHIFT); + break; + #endif + case _CCMP_PRIVACY_: + //michal also hardware... + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0) + txcfg->iv); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + txcfg->iv); + aes_fill_encheader(priv, pwlhdr, txcfg->hdr_len, keyid); + pdesc->Dword1 |= set_desc(0x3 << TX_SecTypeSHIFT); + break; + + default: + DEBUG_ERR("Unknow privacy\n"); + break; + } + } + } + +#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE && pwlhdr && i == 0) { + pdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & 0xff00ffff) | (0x28 << TX_OffsetSHIFT)); + pdesc->Dword1 = set_desc(get_desc(pdesc->Dword1) | (1 << TX_PktOffsetSHIFT)); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + 8); + + memset(pwlhdr-8, '\0', 8); + if (txcfg->pstat && txcfg->pstat->empkt_num > 0) + insert_emcontent(priv, txcfg, pwlhdr-8); + + pdesc->Dword10 = set_desc(get_physical_addr(priv, pwlhdr-8, + get_desc(pdesc->Dword7)&TX_TxBufSizeMask, PCI_DMA_TODEVICE)); + } + else +#endif + { + pdesc->Dword10 = set_desc(get_physical_addr(priv, pwlhdr, + (get_desc(pdesc->Dword7)&TX_TxBufSizeMask), PCI_DMA_TODEVICE)); + + } + + // below is for sw desc info + pdescinfo->paddr = get_desc(pdesc->Dword10); + pdescinfo->pframe = pwlhdr; +#if defined(WIFI_WMM) && defined(WMM_APSD) + pdescinfo->priv = priv; + pdescinfo->pstat = txcfg->pstat; +#endif + +#ifdef TX_SHORTCUT + if (!priv->pmib->dot11OperationEntry.disable_txsc && txcfg->pstat && + (txcfg->fr_type == _SKB_FRAME_TYPE_) && + (txcfg->frg_num == 1) && + ((txcfg->privacy == 0) +#ifdef CONFIG_RTL_WAPI_SUPPORT + || (txcfg->privacy == _WAPI_SMS4_) +#endif +#ifdef CONFIG_IEEE80211W + || !UseSwCrypto(priv, txcfg->pstat, FALSE, txcfg->isPMF)) && +#else + || !UseSwCrypto(priv, txcfg->pstat, FALSE)) && +#endif // CONFIG_IEEE80211W + !GetMData(txcfg->phdr) ) { + +#ifdef CONFIG_RTK_MESH + if( txcfg->is_11s) { + idx = get_tx_sc_free_entry(priv, txcfg->pstat, &priv->ethhdr); + } else +#endif + idx = get_tx_sc_free_entry(priv, txcfg->pstat, pbuf - sizeof(struct wlan_ethhdr_t)); + +#ifdef CONFIG_RTK_MESH + if( txcfg->is_11s) { + memcpy((void *)&txcfg->pstat->tx_sc_ent[idx].ethhdr, &priv->ethhdr, sizeof(struct wlan_ethhdr_t)); + } else +#endif + memcpy((void *)&txcfg->pstat->tx_sc_ent[idx].ethhdr, pbuf - sizeof(struct wlan_ethhdr_t), sizeof(struct wlan_ethhdr_t)); + + memcpy(&txcfg->pstat->tx_sc_ent[idx].hwdesc1, pdesc, 40); + descinfo_copy(&txcfg->pstat->tx_sc_ent[idx].swdesc1, pdescinfo); + txcfg->pstat->protection = priv->pmib->dot11ErpInfo.protection; + txcfg->pstat->ht_protection = priv->ht_protection; + txcfg->pstat->tx_sc_ent[idx].sc_keyid = keyid; + txcfg->pstat->tx_sc_ent[idx].pktpri = ((struct sk_buff *)txcfg->pframe)->cb[1]; + fit_shortcut = 1; + } + else { + if (txcfg->pstat) { + for (idx=0; idxpstat->tx_sc_ent[idx].hwdesc1.Dword7 &= set_desc(~TX_TxBufSizeMask); + } + } +#endif + + pfrst_dma_desc = dma_txhead[*tx_head]; + + if (i != 0) { + pdesc->Dword0 |= set_desc(TX_OWN); +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + } + + flush_addr[flush_num] = (unsigned long)bus_to_virt(get_desc(pdesc->Dword10)); + flush_len[flush_num++]= (get_desc(pdesc->Dword7) & TX_TxBufSizeMask); + +/* + //printk desc content + { + unsigned int *ppdesc = (unsigned int *)pdesc; + printk("%08x %08x %08x \n", get_desc(*(ppdesc)), get_desc(*(ppdesc+1)), get_desc(*(ppdesc+2))); + printk("%08x %08x %08x \n", get_desc(*(ppdesc+3)), get_desc(*(ppdesc+4)), get_desc(*(ppdesc+5))); + printk("%08x %08x %08x \n", get_desc(*(ppdesc+6)), get_desc(*(ppdesc+7)), get_desc(*(ppdesc+8))); + printk("%08x\n", *(ppdesc+9)); + printk("===================================================\n"); + } +*/ + + txdesc_rollover(pdesc, (unsigned int *)tx_head); + + if (txcfg->fr_len == 0) + { + if (txcfg->aggre_en != FG_AGGRE_MSDU_FIRST) + pdesc->Dword0 |= set_desc(TX_LastSeg); + goto init_deschead; + } + + /*------------------------------------------------------------*/ + /* fill descriptor of frame body */ + /*------------------------------------------------------------*/ + pndesc = phdesc + *tx_head; + pndescinfo = pswdescinfo + *tx_head; + //clear all bits + + memset(pndesc, 0,40); + pndesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | (TX_OWN)); + + + +#if (defined(CONFIG_HW_ANTENNA_DIVERSITY)) + if(txcfg->pstat) + { + ODM_SetTxAntByTxInfo(priv, pdesc, txcfg->pstat->aid); //AC-series Set TX antenna + } +#endif + + + if (txcfg->privacy) + { + if (txcfg->privacy == _WAPI_SMS4_) + { + if (txcfg->aggre_en != FG_AGGRE_MSDU_FIRST) + pndesc->Dword0 |= set_desc(TX_LastSeg); + pndescinfo->pstat = txcfg->pstat; + pndescinfo->rate = txcfg->tx_rate; + } +#ifdef CONFIG_IEEE80211W + else if (!UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE),txcfg->isPMF)) +#else + else if (!UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) +#endif // CONFIG_IEEE80211W + { + if (txcfg->aggre_en != FG_AGGRE_MSDU_FIRST) + pndesc->Dword0 |= set_desc(TX_LastSeg); + pndescinfo->pstat = txcfg->pstat; + pndescinfo->rate = txcfg->tx_rate; + } + } + else + { + if (txcfg->aggre_en != FG_AGGRE_MSDU_FIRST) + pndesc->Dword0 |= set_desc(TX_LastSeg); + pndescinfo->pstat = txcfg->pstat; + pndescinfo->rate = txcfg->tx_rate; + } + +#ifdef CONFIG_RTL_WAPI_SUPPORT +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) +#ifdef CONFIG_IEEE80211W + if ((txcfg->privacy == _WAPI_SMS4_)&&(UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF))) +#else + if ((txcfg->privacy == _WAPI_SMS4_)&&(UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE)))) +#endif +#else + if (txcfg->privacy == _WAPI_SMS4_) +#endif + { + pndesc->Dword7 |= set_desc( (fr_len+SMS4_MIC_LEN) & TX_TxBufSizeMask); + } + else +#endif + pndesc->Dword7 |= set_desc(fr_len & TX_TxBufSizeMask); + + if (i == 0) + pndescinfo->type = txcfg->fr_type; + else + pndescinfo->type = _RESERVED_FRAME_TYPE_; + +#if defined(CONFIG_RTK_MESH) && defined(MESH_USE_METRICOP) + if( (txcfg->fr_type == _PRE_ALLOCMEM_) && (txcfg->is_11s & 128)) // for 11s link measurement frame + pndescinfo->type =_RESERVED_FRAME_TYPE_; +#endif + +#ifdef _11s_TEST_MODE_ + mesh_debug_tx10(txcfg, pndescinfo); +#endif + + + pndesc->Dword10 = set_desc(tmpphyaddr); //TxBufferAddr + pndescinfo->paddr = get_desc(pndesc->Dword10); + pndescinfo->pframe = txcfg->pframe; + pndescinfo->len = txcfg->fr_len; // for pci_unmap_single + pndescinfo->priv = priv; + + pbuf += fr_len; + tmpphyaddr += fr_len; + +#ifdef TX_SHORTCUT + if (fit_shortcut) { + memcpy(&txcfg->pstat->tx_sc_ent[idx].hwdesc2, pndesc, 40); + descinfo_copy(&txcfg->pstat->tx_sc_ent[idx].swdesc2, pndescinfo); + } +#endif + +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + flush_addr[flush_num]=(unsigned long)bus_to_virt(get_desc(pndesc->Dword10)); + flush_len[flush_num++] = get_desc(pndesc->Dword7) & TX_TxBufSizeMask; + + txdesc_rollover(pndesc, (unsigned int *)tx_head); + + // retrieve H/W MIC and put in payload +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (txcfg->privacy == _WAPI_SMS4_) + { + SecSWSMS4Encryption(priv, txcfg); +#if 0 + if (txcfg->mic>0) + { + pndesc->Dword7 &= set_desc(~TX_TxBufSizeMask); + pndesc->Dword7 |= set_desc((fr_len+txcfg->mic)& TX_TxBufSizeMask); + flush_len[flush_num-1]= (get_desc(pndesc->Dword7) & TX_TxBufSizeMask); + } + else + { + txcfg->mic = SMS4_MIC_LEN; + } +#endif + + } +#endif + +#ifndef NOT_RTK_BSP + if ((txcfg->privacy == _TKIP_PRIVACY_) && + (priv->pshare->have_hw_mic) && + !(priv->pmib->dot11StationConfigEntry.swTkipMic) && + (i == (txcfg->frg_num-1)) ) // last segment + { + register unsigned long int l,r; + unsigned char *mic; + volatile int i; + + while ((*(volatile unsigned int *)GDMAISR & GDMA_COMPIP) == 0) + for (i=0; i<10; i++) + ; + + l = *(volatile unsigned int *)GDMAICVL; + r = *(volatile unsigned int *)GDMAICVR; + + mic = ((struct sk_buff *)txcfg->pframe)->data + txcfg->fr_len - 8; + mic[0] = (unsigned char)(l & 0xff); + mic[1] = (unsigned char)((l >> 8) & 0xff); + mic[2] = (unsigned char)((l >> 16) & 0xff); + mic[3] = (unsigned char)((l >> 24) & 0xff); + mic[4] = (unsigned char)(r & 0xff); + mic[5] = (unsigned char)((r >> 8) & 0xff); + mic[6] = (unsigned char)((r >> 16) & 0xff); + mic[7] = (unsigned char)((r >> 24) & 0xff); + +#ifdef MICERR_TEST + if (priv->micerr_flag) { + mic[7] ^= mic[7]; + priv->micerr_flag = 0; + } +#endif + } +#endif // !NOT_RTK_BSP + + /*------------------------------------------------------------*/ + /* insert sw encrypt here! */ + /*------------------------------------------------------------*/ +#ifdef CONFIG_IEEE80211W + if (txcfg->privacy && UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF)) +#else + if (txcfg->privacy && UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) +#endif + { + if (txcfg->privacy == _TKIP_PRIVACY_ || + txcfg->privacy == _WEP_40_PRIVACY_ || + txcfg->privacy == _WEP_104_PRIVACY_) + { + picvdesc = phdesc + *tx_head; + picvdescinfo = pswdescinfo + *tx_head; + //clear all bits + memset(picvdesc, 0,32); + + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST){ + picvdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | TX_OWN); + } + else{ + picvdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | TX_OWN | TX_LastSeg); + } + + picvdesc->Dword7 |= (set_desc(txcfg->icv & TX_TxBufSizeMask)); //TxBufferSize + + // append ICV first... + picv = get_icv_from_poll(priv); + if (picv == NULL) + { + DEBUG_ERR("System-Buf! can't alloc picv\n"); + BUG(); + } + + picvdescinfo->type = _PRE_ALLOCICVHDR_; + picvdescinfo->pframe = picv; + picvdescinfo->pstat = txcfg->pstat; + picvdescinfo->rate = txcfg->tx_rate; + picvdescinfo->priv = priv; + //TxBufferAddr + + picvdesc->Dword10 = set_desc(get_physical_addr(priv, picv, txcfg->icv, PCI_DMA_TODEVICE)); + + if (i == 0) + tkip_icv(picv, + pwlhdr + txcfg->hdr_len + txcfg->iv, txcfg->llc, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask)); + else + tkip_icv(picv, + NULL, 0, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask)); + + if ((i == 0) && (txcfg->llc != 0)) { + if (txcfg->privacy == _TKIP_PRIVACY_) + tkip_encrypt(priv, pwlhdr, txcfg->hdr_len, + pwlhdr + txcfg->hdr_len + 8, sizeof(struct llc_snap), + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), picv, txcfg->icv); + else + wep_encrypt(priv, pwlhdr, txcfg->hdr_len, + pwlhdr + txcfg->hdr_len + 4, sizeof(struct llc_snap), + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), picv, txcfg->icv, + txcfg->privacy); + } + else { // not first segment or no snap header + if (txcfg->privacy == _TKIP_PRIVACY_) + tkip_encrypt(priv, pwlhdr, txcfg->hdr_len, NULL, 0, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), picv, txcfg->icv); + else + wep_encrypt(priv, pwlhdr, txcfg->hdr_len, NULL, 0, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), picv, txcfg->icv, + txcfg->privacy); + } +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + flush_addr[flush_num] = (unsigned long)bus_to_virt(get_desc(picvdesc->Dword10)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET); + flush_len[flush_num++]=(get_desc(picvdesc->Dword7) & TX_TxBufSizeMask); + + txdesc_rollover(picvdesc, (unsigned int *)tx_head); + } + + else if (txcfg->privacy == _CCMP_PRIVACY_) + { + pmicdesc = phdesc + *tx_head; + pmicdescinfo = pswdescinfo + *tx_head; + + //clear all bits + memset(pmicdesc, 0,32); + + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST) + pmicdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | TX_OWN); + else + pmicdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | TX_OWN | TX_LastSeg); + + // set TxBufferSize + pmicdesc->Dword7 = set_desc(txcfg->mic & TX_TxBufSizeMask); + + // append MIC first... + pmic = get_mic_from_poll(priv); + if (pmic == NULL) + { + DEBUG_ERR("System-Buf! can't alloc pmic\n"); + BUG(); + } + + pmicdescinfo->type = _PRE_ALLOCMICHDR_; + pmicdescinfo->pframe = pmic; + pmicdescinfo->pstat = txcfg->pstat; + pmicdescinfo->rate = txcfg->tx_rate; + pmicdescinfo->priv = priv; + // set TxBufferAddr + pmicdesc->Dword10= set_desc(get_physical_addr(priv, pmic, txcfg->mic, PCI_DMA_TODEVICE)); + + // then encrypt all (including ICV) by AES + if ((i == 0)&&(txcfg->llc != 0)) // encrypt 3 segments ==> llc, mpdu, and mic + { + +#ifdef CONFIG_IEEE80211W + if (isBIP) { + BIP_encrypt(priv, pwlhdr, pwlhdr + txcfg->hdr_len + 8, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic,txcfg->isPMF); + } + else { + aesccmp_encrypt(priv, pwlhdr, pwlhdr + txcfg->hdr_len + 8, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic,txcfg->isPMF); + } +#else + aesccmp_encrypt(priv, pwlhdr, pwlhdr + txcfg->hdr_len + 8, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic); +#endif + + } + else {// encrypt 2 segments ==> mpdu and mic +#ifdef CONFIG_IEEE80211W + if (isBIP) + { + BIP_encrypt(priv, pwlhdr, NULL, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic,txcfg->isPMF); + } + else + { + aesccmp_encrypt(priv, pwlhdr, NULL, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic,txcfg->isPMF); + } +#else // !defined(CONFIG_IEEE80211W) + aesccmp_encrypt(priv, pwlhdr, NULL, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic); +#endif // CONFIG_IEEE80211W + } +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + flush_addr[flush_num]=(unsigned long)bus_to_virt(get_desc(pmicdesc->Dword10)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET); + flush_len[flush_num++]= (get_desc(pmicdesc->Dword7) & TX_TxBufSizeMask); + + txdesc_rollover(pmicdesc, (unsigned int *)tx_head); + } + } + } + + +init_deschead: +#if 0 + switch (q_select) { + case 0: + case 3: + if (q_num != BE_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 1: + case 2: + if (q_num != BK_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 4: + case 5: + if (q_num != VI_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 6: + case 7: + if (q_num != VO_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 0x11 : + if (q_num != HIGH_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 0x12 : + if (q_num != MGNT_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + default : + printk("%s %d warning : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + } +#endif + + for (i=0; iaggre_en == FG_AGGRE_MSDU_FIRST) { + priv->amsdu_first_desc = pfrstdesc; +#ifndef USE_RTL8186_SDK + priv->amsdu_first_dma_desc = pfrst_dma_desc; +#endif + priv->amsdu_len = get_desc(pfrstdesc->Dword0) & 0xffff; // get pktSize + return 0; + } + + pfrstdesc->Dword0 |= set_desc(TX_OWN); +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(pfrst_dma_desc-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + if (q_num == HIGH_QUEUE) { +// priv->pshare->pkt_in_hiQ = 1; + priv->pkt_in_hiQ = 1; + + return 0; + } else { + tx_poll(priv, q_num); + } + + return 0; +} +#endif // CONFIG_RTL_8812_SUPPORT + +// I AM not sure that if our Buffersize and PKTSize is right, +// If there are any problem, fix this first +#if(CONFIG_WLAN_NOT_HAL_EXIST==1) +int rtl8192cd_signin_txdesc(struct rtl8192cd_priv *priv, struct tx_insn* txcfg) +{ + struct tx_desc *phdesc, *pdesc, *pndesc, *picvdesc, *pmicdesc, *pfrstdesc; + struct tx_desc_info *pswdescinfo, *pdescinfo, *pndescinfo, *picvdescinfo, *pmicdescinfo; + unsigned int fr_len, tx_len, i, keyid; + int *tx_head, q_num; + unsigned long tmpphyaddr; + unsigned char *da, *pbuf, *pwlhdr, *pmic, *picv; + struct rtl8192cd_hw *phw; + unsigned char q_select; +#ifdef TX_SHORTCUT + int fit_shortcut=0, idx=0; +#endif + unsigned long pfrst_dma_desc=0; + unsigned long *dma_txhead; + + unsigned long flush_addr[20]; + int flush_len[20]; + int flush_num=0; + +#ifdef TX_SCATTER + int actual_size = 0; + struct sk_buff *skb=NULL; +#endif +#ifdef CONFIG_IEEE80211W + unsigned int isBIP = 0; +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + return rtl8192cd_signin_txdesc_8812(priv, txcfg); + } +#endif + + picvdesc=NULL; + keyid=0; + pmic=NULL; + picv=NULL; + q_select=0; + + if (txcfg->tx_rate == 0) { + DEBUG_ERR("tx_rate=0!\n"); + txcfg->tx_rate = find_rate(priv, NULL, 0, 1); + } + + q_num = txcfg->q_num; + + phw = GET_HW(priv); + + dma_txhead = get_txdma_addr(phw, q_num); + tx_head = get_txhead_addr(phw, q_num); + phdesc = get_txdesc(phw, q_num); + pswdescinfo = get_txdesc_info(priv->pshare->pdesc_info, q_num); + + da = get_da((unsigned char *)txcfg->phdr); + +#ifdef CONFIG_IEEE80211W + if (txcfg->isPMF && IS_MCAST(da)) + { + isBIP = 1; + txcfg->iv = 0; + txcfg->fr_len += 10; // 10: MMIE length + } +#endif + tx_len = txcfg->fr_len; + + if (txcfg->fr_type == _SKB_FRAME_TYPE_) + pbuf = ((struct sk_buff *)txcfg->pframe)->data; + else + pbuf = (unsigned char*)txcfg->pframe; + +#ifdef TX_SCATTER + if (txcfg->fr_type == _SKB_FRAME_TYPE_ && + ((struct sk_buff *)txcfg->pframe)->list_num > 0) { + skb = (struct sk_buff *)txcfg->pframe; + actual_size = skb->len; + } else { + actual_size = tx_len; + } + + tmpphyaddr = get_physical_addr(priv, pbuf, actual_size, PCI_DMA_TODEVICE); +#else + tmpphyaddr = get_physical_addr(priv, pbuf, tx_len, PCI_DMA_TODEVICE); +#endif + + // in case of default key, then find the key id + if (GetPrivacy((txcfg->phdr))) + { +#ifdef WDS + if (txcfg->wdsIdx >= 0) { + if (txcfg->pstat) + keyid = txcfg->pstat->keyid; + else + keyid = 0; + } + else +#endif + +#ifdef __DRAYTEK_OS__ + if (!IEEE8021X_FUN) + keyid = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + else { + if (IS_MCAST(GetAddr1Ptr ((unsigned char *)txcfg->phdr)) || !txcfg->pstat) + keyid = priv->pmib->dot11GroupKeysTable.keyid; + else + keyid = txcfg->pstat->keyid; + } +#else + + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm==_WEP_104_PRIVACY_) { + if(IEEE8021X_FUN && txcfg->pstat) { +#ifdef A4_STA + if (IS_MCAST(da) && !(txcfg->pstat->state & WIFI_A4_STA)) +#else + if(IS_MCAST(da)) +#endif + keyid = 0; + else + keyid = txcfg->pstat->keyid; + } + else + keyid = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + } +#endif + + + } + + for(i=0, pfrstdesc= phdesc + (*tx_head); i < txcfg->frg_num; i++) + { + /*------------------------------------------------------------*/ + /* fill descriptor of header + iv + llc */ + /*------------------------------------------------------------*/ + pdesc = phdesc + (*tx_head); + pdescinfo = pswdescinfo + *tx_head; + + //clear all bits + memset(pdesc, 0, 32); + + if (i != 0) + { + // we have to allocate wlan_hdr + pwlhdr = (UINT8 *)get_wlanhdr_from_poll(priv); + if (pwlhdr == (UINT8 *)NULL) + { + DEBUG_ERR("System-bug... should have enough wlan_hdr\n"); + return (txcfg->frg_num - i); + } + // other MPDU will share the same seq with the first MPDU + memcpy((void *)pwlhdr, (void *)(txcfg->phdr), txcfg->hdr_len); // data pkt has 24 bytes wlan_hdr + pdesc->Dword3 |= set_desc((GetSequence(txcfg->phdr) & TX_SeqMask) << TX_SeqSHIFT); + } + else + { +#ifdef WIFI_WMM + if (txcfg->pstat && (is_qos_data(txcfg->phdr))) { + if ((GetFrameSubType(txcfg->phdr) & (WIFI_DATA_TYPE | BIT(6) | BIT(7))) == (WIFI_DATA_TYPE | BIT(7))) { + unsigned char tempQosControl[2]; + memset(tempQosControl, 0, 2); + tempQosControl[0] = ((struct sk_buff *)txcfg->pframe)->cb[1]; +#ifdef WMM_APSD + if ( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (APSD_ENABLE) && (txcfg->pstat) && (txcfg->pstat->state & WIFI_SLEEP_STATE) && + (!GetMData(txcfg->phdr)) && + ((((tempQosControl[0] == 7) || (tempQosControl[0] == 6)) && (txcfg->pstat->apsd_bitmap & 0x01)) || + (((tempQosControl[0] == 5) || (tempQosControl[0] == 4)) && (txcfg->pstat->apsd_bitmap & 0x02)) || + (((tempQosControl[0] == 3) || (tempQosControl[0] == 0)) && (txcfg->pstat->apsd_bitmap & 0x08)) || + (((tempQosControl[0] == 2) || (tempQosControl[0] == 1)) && (txcfg->pstat->apsd_bitmap & 0x04)))) + tempQosControl[0] |= BIT(4); +#endif + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST) + tempQosControl[0] |= BIT(7); + + if (priv->pmib->dot11nConfigEntry.dot11nTxNoAck) + tempQosControl[0] |= BIT(5); + + memcpy((void *)GetQosControl((txcfg->phdr)), tempQosControl, 2); + } + } +#endif + + assign_wlanseq(GET_HW(priv), txcfg->phdr, txcfg->pstat, GET_MIB(priv) +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , txcfg->is_11s +#endif + ); + pdesc->Dword3 |= set_desc((GetSequence(txcfg->phdr) & TX_SeqMask) << TX_SeqSHIFT); + pwlhdr = txcfg->phdr; + } + SetDuration(pwlhdr, 0); + + rtl8192cd_fill_fwinfo(priv, txcfg, pdesc, i); + +#if (defined(CONFIG_HW_ANTENNA_DIVERSITY)) + if(txcfg->pstat) + { + ODM_SetTxAntByTxInfo(priv, pdesc,txcfg->pstat->aid); //N-series Set TX antenna + } +#endif +#if defined (HW_ANT_SWITCH) && (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + pdesc->Dword2 &= set_desc(~ BIT(24)); + pdesc->Dword2 &= set_desc(~ BIT(25)); + if(!(priv->pshare->rf_ft_var.CurAntenna & 0x80) && (txcfg->pstat)) { + pdesc->Dword2 |= set_desc(((txcfg->pstat->CurAntenna^priv->pshare->rf_ft_var.CurAntenna)&1)<<24); + pdesc->Dword2 |= set_desc(((txcfg->pstat->CurAntenna^priv->pshare->rf_ft_var.CurAntenna)&1)<<25); + } +#endif + + pdesc->Dword0 |= set_desc(32 << TX_OffsetSHIFT); // tx_desc size + + if (IS_MCAST(GetAddr1Ptr((unsigned char *)txcfg->phdr))) + pdesc->Dword0 |= set_desc(TX_BMC); + +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + if (GetFrameSubType(txcfg->phdr) == WIFI_PSPOLL) + pdesc->Dword1 |= set_desc(TX_NAVUSEHDR); + + if (priv->ps_state) + SetPwrMgt(pwlhdr); + else + ClearPwrMgt(pwlhdr); + } +#endif + + if (i != (txcfg->frg_num - 1)) + { + SetMFrag(pwlhdr); + if (i == 0) { + fr_len = (txcfg->frag_thrshld - txcfg->llc); + tx_len -= (txcfg->frag_thrshld - txcfg->llc); + } + else { + fr_len = txcfg->frag_thrshld; + tx_len -= txcfg->frag_thrshld; + } + } + else // last seg, or the only seg (frg_num == 1) + { + fr_len = tx_len; + ClearMFrag(pwlhdr); + } + SetFragNum((pwlhdr), i); + + if ((i == 0) && (txcfg->fr_type == _SKB_FRAME_TYPE_)) + { + pdesc->Dword7 |= set_desc((txcfg->hdr_len + txcfg->llc) << TX_TxBufSizeSHIFT); + pdesc->Dword0 |= set_desc((fr_len + (get_desc(pdesc->Dword7) & TX_TxBufSizeMask)) << TX_PktSizeSHIFT); + pdesc->Dword0 |= set_desc(TX_FirstSeg); + pdescinfo->type = _PRE_ALLOCLLCHDR_; + } + else + { + pdesc->Dword7 |= set_desc(txcfg->hdr_len << TX_TxBufSizeSHIFT); + pdesc->Dword0 |= set_desc((fr_len + (get_desc(pdesc->Dword7) & TX_TxBufSizeMask)) << TX_PktSizeSHIFT); + pdesc->Dword0 |= set_desc(TX_FirstSeg); + pdescinfo->type = _PRE_ALLOCHDR_; + } + +#ifdef _11s_TEST_MODE_ + mesh_debug_tx9(txcfg, pdescinfo); +#endif + + switch (q_num) { + case HIGH_QUEUE: + q_select = 0x11;// High Queue + break; + case MGNT_QUEUE: + q_select = 0x12; + break; +#if defined(DRVMAC_LB) && defined(WIFI_WMM) + case BE_QUEUE: + q_select = 0; + break; +#endif + default: + // data packet +#ifdef RTL_MANUAL_EDCA + if (priv->pmib->dot11QosEntry.ManualEDCA) { + switch (q_num) { + case VO_QUEUE: + q_select = 6; + break; + case VI_QUEUE: + q_select = 4; + break; + case BE_QUEUE: + q_select = 0; + break; + default: + q_select = 1; + break; + } + } + else +#endif + q_select = ((struct sk_buff *)txcfg->pframe)->cb[1]; + break; + } + pdesc->Dword1 |= set_desc((q_select & TX_QSelMask)<< TX_QSelSHIFT); + + if (i != (txcfg->frg_num - 1)) + pdesc->Dword2 |= set_desc(TX_MoreFrag); + +// Set RateID + if (txcfg->pstat) { + if (txcfg->pstat->aid != MANAGEMENT_AID) { + u8 ratid; + +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G){ + if (txcfg->pstat->tx_ra_bitmap & 0xffff000) { + if (priv->pshare->is_40m_bw) + ratid = ARFR_2T_Band_A_40M; + else + ratid = ARFR_2T_Band_A_20M; + } else { + ratid = ARFR_G_ONLY; + } + } else +#endif + { + if (txcfg->pstat->tx_ra_bitmap & 0xff00000) { + if (priv->pshare->is_40m_bw) + ratid = ARFR_2T_40M; + else + ratid = ARFR_2T_20M; + } else if (txcfg->pstat->tx_ra_bitmap & 0xff000) { + if (priv->pshare->is_40m_bw) + ratid = ARFR_1T_40M; + else + ratid = ARFR_1T_20M; + } else if (txcfg->pstat->tx_ra_bitmap & 0xff0) { + ratid = ARFR_BG_MIX; + } else { + ratid = ARFR_B_ONLY; + } + + +#ifdef P2P_SUPPORT /*tx to GC no user B rate*/ + if(txcfg->pstat->is_p2p_client){ + switch(ratid) { + case ARFR_BG_MIX : + ratid = ARFR_G_ONLY; + break; + default: + ratid = ARFR_2T_Band_A_40M; + } + } +#endif + } + pdesc->Dword1 |= set_desc((ratid & TX_RateIDMask) << TX_RateIDSHIFT); + // Set MacID +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) + pdesc->Dword1 |= set_desc(REMAP_AID(txcfg->pstat) & TXdesc_88E_MacIdMask); + else +#endif + pdesc->Dword1 |= set_desc(REMAP_AID(txcfg->pstat) & TX_MacIdMask); + } + } else { + +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + pdesc->Dword1 |= set_desc((ARFR_Band_A_BMC &TX_RateIDMask)<Dword1 |= set_desc((ARFR_BMC &TX_RateIDMask)<Dword5 |= set_desc((0x1f & TX_DataRateFBLmtMask) << TX_DataRateFBLmtSHIFT); + if (txcfg->fixed_rate) + pdesc->Dword4 |= set_desc(TX_DisDataFB|TX_DisRtsFB|TX_UseRate); +#ifdef CONFIG_RTL_88E_SUPPORT + else if (GET_CHIP_VER(priv)==VERSION_8188E) + pdesc->Dword4 |= set_desc(TX_UseRate); +#endif + + if(txcfg->pstat && txcfg->pstat->sta_in_firmware != 1) + pdesc->Dword4 |= set_desc(TX_UseRate); + + if (!txcfg->need_ack && txcfg->privacy && +#ifdef CONFIG_IEEE80211W + UseSwCrypto(priv, NULL, TRUE, txcfg->isPMF) +#else + UseSwCrypto(priv, NULL, TRUE) +#endif + ) + pdesc->Dword1 &= set_desc( ~(TX_SecTypeMask<< TX_SecTypeSHIFT)); + + if (txcfg->privacy) { +#ifdef CONFIG_IEEE80211W + if (UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF +#else + if (UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE) +#endif + )) { + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0)+ txcfg->icv + txcfg->mic + txcfg->iv); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7)+ txcfg->iv); + } else { + // hw encrypt + switch(txcfg->privacy) { + case _WEP_104_PRIVACY_: + case _WEP_40_PRIVACY_: + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0) + txcfg->iv); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + txcfg->iv); + wep_fill_iv(priv, pwlhdr, txcfg->hdr_len, keyid); + pdesc->Dword1 |= set_desc(0x1 << TX_SecTypeSHIFT); + break; + + case _TKIP_PRIVACY_: + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0) + txcfg->iv + txcfg->mic); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + txcfg->iv); + tkip_fill_encheader(priv, pwlhdr, txcfg->hdr_len, keyid); + pdesc->Dword1 |= set_desc(0x1 << TX_SecTypeSHIFT); + break; + #if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + case _WAPI_SMS4_: + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0) + txcfg->iv); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + txcfg->iv); + + pdesc->Dword1 |= set_desc(0x2 << TX_SecTypeSHIFT); + break; + #endif + case _CCMP_PRIVACY_: + //michal also hardware... + pdesc->Dword0 = set_desc(get_desc(pdesc->Dword0) + txcfg->iv); + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + txcfg->iv); + aes_fill_encheader(priv, pwlhdr, txcfg->hdr_len, keyid); + pdesc->Dword1 |= set_desc(0x3 << TX_SecTypeSHIFT); + break; + + default: + DEBUG_ERR("Unknow privacy\n"); + break; + } + } + } + +#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE && pwlhdr && i == 0) { + pdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & 0xff00ffff) | (0x28 << TX_OffsetSHIFT)); + pdesc->Dword1 = set_desc(get_desc(pdesc->Dword1) | (1 << TX_PktOffsetSHIFT)); +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + pdesc->Dword6 &= set_desc(~ (0xf << TX_MaxAggNumSHIFT)); + pdesc->Dword6 |= set_desc(0xf << TX_MaxAggNumSHIFT); + } +#endif + pdesc->Dword7 = set_desc(get_desc(pdesc->Dword7) + 8); + + memset(pwlhdr-8, '\0', 8); + if (txcfg->pstat && txcfg->pstat->empkt_num > 0) + insert_emcontent(priv, txcfg, pwlhdr-8); + pdesc->Dword8 = set_desc(get_physical_addr(priv, pwlhdr-8, + get_desc(pdesc->Dword7)&TX_TxBufSizeMask, PCI_DMA_TODEVICE)); + } + else +#endif + { +#if defined(TX_EARLY_MODE) && defined(CONFIG_RTL_88E_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E) + pdesc->Dword6 &= set_desc(~ (0xf << TX_MaxAggNumSHIFT)); +#endif + pdesc->Dword8 = set_desc(get_physical_addr(priv, pwlhdr, + (get_desc(pdesc->Dword7)&TX_TxBufSizeMask), PCI_DMA_TODEVICE)); + } + + // below is for sw desc info + pdescinfo->paddr = get_desc(pdesc->Dword8); + pdescinfo->pframe = pwlhdr; +#if defined(WIFI_WMM) && defined(WMM_APSD) + pdescinfo->priv = priv; + pdescinfo->pstat = txcfg->pstat; +#endif + +#ifdef TX_SHORTCUT + if (!priv->pmib->dot11OperationEntry.disable_txsc && txcfg->pstat && + (txcfg->fr_type == _SKB_FRAME_TYPE_) && + (txcfg->frg_num == 1) && + ((txcfg->privacy == 0) +#ifdef CONFIG_RTL_WAPI_SUPPORT + || (txcfg->privacy == _WAPI_SMS4_) +#endif +#ifdef CONFIG_IEEE80211W + || !UseSwCrypto(priv, txcfg->pstat, FALSE,txcfg->isPMF)) && +#else + || !UseSwCrypto(priv, txcfg->pstat, FALSE)) && +#endif // CONFIG_IEEE80211W + !GetMData(txcfg->phdr) ) { + +#ifdef CONFIG_RTK_MESH + if( txcfg->is_11s) { + idx = get_tx_sc_free_entry(priv, txcfg->pstat, &priv->ethhdr); + } else +#endif + idx = get_tx_sc_free_entry(priv, txcfg->pstat, pbuf - sizeof(struct wlan_ethhdr_t)); + +#ifdef CONFIG_RTK_MESH + if( txcfg->is_11s) { + memcpy((void *)&txcfg->pstat->tx_sc_ent[idx].ethhdr, &priv->ethhdr, sizeof(struct wlan_ethhdr_t)); + } else +#endif +#ifdef TX_SCATTER + if (((struct sk_buff *)txcfg->pframe)->list_num > 0) + memcpy((void *)&txcfg->pstat->tx_sc_ent[idx].ethhdr, ((struct sk_buff *)txcfg->pframe)->list_buf[0].buf, sizeof(struct wlan_ethhdr_t)); + else +#endif + memcpy((void *)&txcfg->pstat->tx_sc_ent[idx].ethhdr, pbuf - sizeof(struct wlan_ethhdr_t), sizeof(struct wlan_ethhdr_t)); + + desc_copy(&txcfg->pstat->tx_sc_ent[idx].hwdesc1, pdesc); + descinfo_copy(&txcfg->pstat->tx_sc_ent[idx].swdesc1, pdescinfo); + txcfg->pstat->protection = priv->pmib->dot11ErpInfo.protection; + txcfg->pstat->ht_protection = priv->ht_protection; + txcfg->pstat->tx_sc_ent[idx].sc_keyid = keyid; + txcfg->pstat->tx_sc_ent[idx].pktpri = ((struct sk_buff *)txcfg->pframe)->cb[1]; + fit_shortcut = 1; + } + else { + if (txcfg->pstat) { + for (idx=0; idxpstat->tx_sc_ent[idx].hwdesc1.Dword7 &= set_desc(~TX_TxBufSizeMask); +#ifdef TX_SCATTER + txcfg->pstat->tx_sc_ent[idx].has_desc3 = 0; +#endif + } + } + } +#endif + + pfrst_dma_desc = dma_txhead[*tx_head]; + + if (i != 0) { + pdesc->Dword0 |= set_desc(TX_OWN); +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + } + + flush_addr[flush_num] = (unsigned long)bus_to_virt(get_desc(pdesc->Dword8)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET); + flush_len[flush_num++]= (get_desc(pdesc->Dword7) & TX_TxBufSizeMask); + +/* + //printk desc content + { + unsigned int *ppdesc = (unsigned int *)pdesc; + printk("%08x %08x %08x \n", get_desc(*(ppdesc)), get_desc(*(ppdesc+1)), get_desc(*(ppdesc+2))); + printk("%08x %08x %08x \n", get_desc(*(ppdesc+3)), get_desc(*(ppdesc+4)), get_desc(*(ppdesc+5))); + printk("%08x %08x %08x \n", get_desc(*(ppdesc+6)), get_desc(*(ppdesc+7)), get_desc(*(ppdesc+8))); + printk("%08x\n", *(ppdesc+9)); + printk("===================================================\n"); + } +*/ + + txdesc_rollover(pdesc, (unsigned int *)tx_head); + + if (txcfg->fr_len == 0) + { + if (txcfg->aggre_en != FG_AGGRE_MSDU_FIRST) + pdesc->Dword0 |= set_desc(TX_LastSeg); + goto init_deschead; + } + +#ifdef TX_SCATTER +fill_body: +#endif + /*------------------------------------------------------------*/ + /* fill descriptor of frame body */ + /*------------------------------------------------------------*/ + pndesc = phdesc + *tx_head; + pndescinfo = pswdescinfo + *tx_head; + //clear all bits + memset(pndesc, 0,32); + pndesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | (TX_OWN)); + + +#if defined (HW_ANT_SWITCH) && (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + pndesc->Dword2 &= set_desc(~ BIT(24)); + pndesc->Dword2 &= set_desc(~ BIT(25)); + if(!(priv->pshare->rf_ft_var.CurAntenna & 0x80) && (txcfg->pstat)) { + pndesc->Dword2 |= set_desc(((txcfg->pstat->CurAntenna^priv->pshare->rf_ft_var.CurAntenna)&1)<<24); + pndesc->Dword2 |= set_desc(((txcfg->pstat->CurAntenna^priv->pshare->rf_ft_var.CurAntenna)&1)<<25); + } +#endif + + + if (txcfg->privacy) + { + if (txcfg->privacy == _WAPI_SMS4_) + { + if (txcfg->aggre_en != FG_AGGRE_MSDU_FIRST) + pndesc->Dword0 |= set_desc(TX_LastSeg); + pndescinfo->pstat = txcfg->pstat; + pndescinfo->rate = txcfg->tx_rate; + } +#ifdef CONFIG_IEEE80211W + else if (!UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF)) +#else + else if (!UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) +#endif + { + if (txcfg->aggre_en != FG_AGGRE_MSDU_FIRST) { +#ifdef TX_SCATTER + if (!skb || (skb && ((skb->list_idx+1) == skb->list_num))) +#endif + pndesc->Dword0 |= set_desc(TX_LastSeg); + } + pndescinfo->pstat = txcfg->pstat; + pndescinfo->rate = txcfg->tx_rate; + } + } + else + { + if (txcfg->aggre_en != FG_AGGRE_MSDU_FIRST) { +#ifdef TX_SCATTER + if (!skb || (skb && ((skb->list_idx+1) == skb->list_num))) +#endif + pndesc->Dword0 |= set_desc(TX_LastSeg); + } + pndescinfo->pstat = txcfg->pstat; + pndescinfo->rate = txcfg->tx_rate; + } +#ifdef TX_SCATTER + if (skb != NULL) + fr_len = actual_size; +#endif + +#ifdef CONFIG_RTL_WAPI_SUPPORT +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) +#ifdef CONFIG_IEEE80211W + if ((txcfg->privacy == _WAPI_SMS4_)&&(UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF))) +#else + if ((txcfg->privacy == _WAPI_SMS4_)&&(UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE)))) +#endif // CONFIG_IEEE80211W +#else + if (txcfg->privacy == _WAPI_SMS4_) +#endif + { + pndesc->Dword7 |= set_desc( (fr_len+SMS4_MIC_LEN) & TX_TxBufSizeMask); + } + else +#endif + pndesc->Dword7 |= set_desc(fr_len & TX_TxBufSizeMask); + +#ifdef TX_SCATTER + if (skb && (skb->list_num > 0)) { + if (get_desc(pndesc->Dword0) & TX_LastSeg) + pndescinfo->type = txcfg->fr_type; + else + pndescinfo->type = _RESERVED_FRAME_TYPE_; + } else +#endif + { + if (i == 0) + pndescinfo->type = txcfg->fr_type; + else + pndescinfo->type = _RESERVED_FRAME_TYPE_; + } + +#if defined(CONFIG_RTK_MESH) && defined(MESH_USE_METRICOP) + if( (txcfg->fr_type == _PRE_ALLOCMEM_) && (txcfg->is_11s & 128)) // for 11s link measurement frame + pndescinfo->type =_RESERVED_FRAME_TYPE_; +#endif + +#ifdef _11s_TEST_MODE_ + mesh_debug_tx10(txcfg, pndescinfo); +#endif + + pndesc->Dword8 = set_desc(tmpphyaddr); //TxBufferAddr + pndescinfo->paddr = get_desc(pndesc->Dword8); + pndescinfo->pframe = txcfg->pframe; + pndescinfo->len = txcfg->fr_len; // for pci_unmap_single + pndescinfo->priv = priv; + + pbuf += fr_len; + tmpphyaddr += fr_len; + +#ifdef TX_SHORTCUT + if (fit_shortcut) { +#ifdef TX_SCATTER + if (txcfg->pstat->tx_sc_ent[idx].has_desc3) { + desc_copy(&txcfg->pstat->tx_sc_ent[idx].hwdesc3, pndesc); + descinfo_copy(&txcfg->pstat->tx_sc_ent[idx].swdesc3, pndescinfo); + } else +#endif + { + desc_copy(&txcfg->pstat->tx_sc_ent[idx].hwdesc2, pndesc); + descinfo_copy(&txcfg->pstat->tx_sc_ent[idx].swdesc2, pndescinfo); + } + } +#endif + +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + flush_addr[flush_num]=(unsigned long)bus_to_virt(get_desc(pndesc->Dword8)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET); + flush_len[flush_num++] = get_desc(pndesc->Dword7) & TX_TxBufSizeMask; + + txdesc_rollover(pndesc, (unsigned int *)tx_head); + + // retrieve H/W MIC and put in payload +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (txcfg->privacy == _WAPI_SMS4_) + { + SecSWSMS4Encryption(priv, txcfg); +#if 0 + if (txcfg->mic>0) + { + pndesc->Dword7 &= set_desc(~TX_TxBufSizeMask); + pndesc->Dword7 |= set_desc((fr_len+txcfg->mic)& TX_TxBufSizeMask); + flush_len[flush_num-1]= (get_desc(pndesc->Dword7) & TX_TxBufSizeMask); + } + else + { + txcfg->mic = SMS4_MIC_LEN; + } +#endif + + } +#endif + +#ifndef NOT_RTK_BSP + if ((txcfg->privacy == _TKIP_PRIVACY_) && + (priv->pshare->have_hw_mic) && + !(priv->pmib->dot11StationConfigEntry.swTkipMic) && + (i == (txcfg->frg_num-1)) ) // last segment + { + register unsigned long int l,r; + unsigned char *mic; + volatile int i; + + while ((*(volatile unsigned int *)GDMAISR & GDMA_COMPIP) == 0) + for (i=0; i<10; i++) + ; + + l = *(volatile unsigned int *)GDMAICVL; + r = *(volatile unsigned int *)GDMAICVR; + + mic = ((struct sk_buff *)txcfg->pframe)->data + txcfg->fr_len - 8; + mic[0] = (unsigned char)(l & 0xff); + mic[1] = (unsigned char)((l >> 8) & 0xff); + mic[2] = (unsigned char)((l >> 16) & 0xff); + mic[3] = (unsigned char)((l >> 24) & 0xff); + mic[4] = (unsigned char)(r & 0xff); + mic[5] = (unsigned char)((r >> 8) & 0xff); + mic[6] = (unsigned char)((r >> 16) & 0xff); + mic[7] = (unsigned char)((r >> 24) & 0xff); + +#ifdef MICERR_TEST + if (priv->micerr_flag) { + mic[7] ^= mic[7]; + priv->micerr_flag = 0; + } +#endif + } +#endif // !NOT_RTK_BSP + + /*------------------------------------------------------------*/ + /* insert sw encrypt here! */ + /*------------------------------------------------------------*/ + if (txcfg->privacy && +#ifdef CONFIG_IEEE80211W + UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF)) +#else + UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) +#endif + { + if (txcfg->privacy == _TKIP_PRIVACY_ || + txcfg->privacy == _WEP_40_PRIVACY_ || + txcfg->privacy == _WEP_104_PRIVACY_) + { + picvdesc = phdesc + *tx_head; + picvdescinfo = pswdescinfo + *tx_head; + //clear all bits + memset(picvdesc, 0,32); + + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST){ + picvdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | TX_OWN); + } + else{ + picvdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | TX_OWN | TX_LastSeg); + } + + picvdesc->Dword7 |= (set_desc(txcfg->icv & TX_TxBufSizeMask)); //TxBufferSize + + // append ICV first... + picv = get_icv_from_poll(priv); + if (picv == NULL) + { + DEBUG_ERR("System-Buf! can't alloc picv\n"); + BUG(); + } + + picvdescinfo->type = _PRE_ALLOCICVHDR_; + picvdescinfo->pframe = picv; + picvdescinfo->pstat = txcfg->pstat; + picvdescinfo->rate = txcfg->tx_rate; + picvdescinfo->priv = priv; + //TxBufferAddr + picvdesc->Dword8 = set_desc(get_physical_addr(priv, picv, txcfg->icv, PCI_DMA_TODEVICE)); + + if (i == 0) + tkip_icv(picv, + pwlhdr + txcfg->hdr_len + txcfg->iv, txcfg->llc, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask)); + else + tkip_icv(picv, + NULL, 0, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask)); + + if ((i == 0) && (txcfg->llc != 0)) { + if (txcfg->privacy == _TKIP_PRIVACY_) + tkip_encrypt(priv, pwlhdr, txcfg->hdr_len, + pwlhdr + txcfg->hdr_len + 8, sizeof(struct llc_snap), + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), picv, txcfg->icv); + else + wep_encrypt(priv, pwlhdr, txcfg->hdr_len, + pwlhdr + txcfg->hdr_len + 4, sizeof(struct llc_snap), + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), picv, txcfg->icv, + txcfg->privacy); + } + else { // not first segment or no snap header + if (txcfg->privacy == _TKIP_PRIVACY_) + tkip_encrypt(priv, pwlhdr, txcfg->hdr_len, NULL, 0, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), picv, txcfg->icv); + else + wep_encrypt(priv, pwlhdr, txcfg->hdr_len, NULL, 0, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), picv, txcfg->icv, + txcfg->privacy); + } +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + flush_addr[flush_num] = (unsigned long)bus_to_virt(get_desc(picvdesc->Dword8)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET); + flush_len[flush_num++]=(get_desc(picvdesc->Dword7) & TX_TxBufSizeMask); + + txdesc_rollover(picvdesc, (unsigned int *)tx_head); + } + + else if (txcfg->privacy == _CCMP_PRIVACY_) + { + pmicdesc = phdesc + *tx_head; + pmicdescinfo = pswdescinfo + *tx_head; + + //clear all bits + memset(pmicdesc, 0,32); + + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST) + pmicdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | TX_OWN); + else + pmicdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & (~TX_FirstSeg)) | TX_OWN | TX_LastSeg); + + // set TxBufferSize + pmicdesc->Dword7 = set_desc(txcfg->mic & TX_TxBufSizeMask); + + // append MIC first... + pmic = get_mic_from_poll(priv); + if (pmic == NULL) + { + DEBUG_ERR("System-Buf! can't alloc pmic\n"); + BUG(); + } + + pmicdescinfo->type = _PRE_ALLOCMICHDR_; + pmicdescinfo->pframe = pmic; + pmicdescinfo->pstat = txcfg->pstat; + pmicdescinfo->rate = txcfg->tx_rate; + pmicdescinfo->priv = priv; + // set TxBufferAddr + pmicdesc->Dword8= set_desc(get_physical_addr(priv, pmic, txcfg->mic, PCI_DMA_TODEVICE)); + + // then encrypt all (including ICV) by AES + if ((i == 0)&&(txcfg->llc != 0)) // encrypt 3 segments ==> llc, mpdu, and mic + { +#ifdef CONFIG_IEEE80211W + if (isBIP) + { + BIP_encrypt(priv, pwlhdr, pwlhdr + txcfg->hdr_len + 8, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic,txcfg->isPMF); + } + else { + aesccmp_encrypt(priv, pwlhdr, pwlhdr + txcfg->hdr_len + 8, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic,txcfg->isPMF); + } +#else + aesccmp_encrypt(priv, pwlhdr, pwlhdr + txcfg->hdr_len + 8, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic); +#endif + } + else { // encrypt 2 segments ==> mpdu and mic +#ifdef CONFIG_IEEE80211W + if (isBIP) + { + BIP_encrypt(priv, pwlhdr, NULL, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic,txcfg->isPMF); + } + else { + aesccmp_encrypt(priv, pwlhdr, NULL, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic,txcfg->isPMF); + } +#else // !defined(CONFIG_IEEE80211W) + aesccmp_encrypt(priv, pwlhdr, NULL, + pbuf - (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), (get_desc(pndesc->Dword7) & TX_TxBufSizeMask), pmic); +#endif // CONFIG_IEEE80211W + } +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + flush_addr[flush_num]=(unsigned long)bus_to_virt(get_desc(pmicdesc->Dword8)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET); + flush_len[flush_num++]= (get_desc(pmicdesc->Dword7) & TX_TxBufSizeMask); + + txdesc_rollover(pmicdesc, (unsigned int *)tx_head); + } + } + +#ifdef TX_SCATTER + if (skb && ++skb->list_idx < skb->list_num) { + skb_assign_buf(skb, skb->list_buf[skb->list_idx].buf, skb->list_buf[skb->list_idx].len); + skb->len = skb->list_buf[skb->list_idx].len; + pbuf = skb->data; + actual_size = skb->len; + tmpphyaddr = get_physical_addr(priv, pbuf, actual_size, PCI_DMA_TODEVICE); +#ifdef TX_SHORTCUT + if (txcfg->pstat) { + if (txcfg->pstat->tx_sc_ent[idx].has_desc3) { + fit_shortcut = 0; + txcfg->pstat->tx_sc_ent[idx].has_desc3 = 0; + for (idx=0; idxpstat->tx_sc_ent[idx].hwdesc1.Dword7 &= set_desc(~TX_TxBufSizeMask); + } else { + txcfg->pstat->tx_sc_ent[idx].has_desc3 = 1; + } + } +#endif + goto fill_body; + } +#endif + } + + +init_deschead: +#if 0 + switch (q_select) { + case 0: + case 3: + if (q_num != BE_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 1: + case 2: + if (q_num != BK_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 4: + case 5: + if (q_num != VI_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 6: + case 7: + if (q_num != VO_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 0x11 : + if (q_num != HIGH_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + case 0x12 : + if (q_num != MGNT_QUEUE) + printk("%s %d error : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + default : + printk("%s %d warning : q_select[%d], q_num[%d]\n", __FUNCTION__, __LINE__, q_select, q_num); + break; + } +#endif + + for (i=0; iaggre_en == FG_AGGRE_MSDU_FIRST) { + priv->amsdu_first_desc = pfrstdesc; +#ifndef USE_RTL8186_SDK + priv->amsdu_first_dma_desc = pfrst_dma_desc; +#endif + priv->amsdu_len = get_desc(pfrstdesc->Dword0) & 0xffff; // get pktSize + return 0; + } + + pfrstdesc->Dword0 |= set_desc(TX_OWN); +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(pfrst_dma_desc-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + if (q_num == HIGH_QUEUE) { +// priv->pshare->pkt_in_hiQ = 1; + priv->pkt_in_hiQ = 1; + + return 0; + } else { + tx_poll(priv, q_num); + } + + return 0; +} +#else +int rtl8192cd_signin_txdesc(struct rtl8192cd_priv *priv, struct tx_insn* txcfg) +{ + return 0; +} +#endif//CONFIG_WLAN_NOT_HAL_EXIST +#endif // CONFIG_PCI_HCI + + +#ifdef SUPPORT_TX_AMSDU +int rtl8192cd_signin_txdesc_amsdu(struct rtl8192cd_priv *priv, struct tx_insn* txcfg) +{ + struct tx_desc *phdesc, *pdesc, *pfrstdesc; + struct tx_desc_info *pswdescinfo, *pdescinfo; + unsigned int tx_len; + int *tx_head, q_num; + unsigned long tmpphyaddr; + unsigned char *pbuf; + struct rtl8192cd_hw *phw; + unsigned long *dma_txhead; + + q_num = txcfg->q_num; + phw = GET_HW(priv); + + dma_txhead = get_txdma_addr(phw, q_num); + tx_head = get_txhead_addr(phw, q_num); + phdesc = get_txdesc(phw, q_num); + pswdescinfo = get_txdesc_info(priv->pshare->pdesc_info, q_num); + + pbuf = ((struct sk_buff *)txcfg->pframe)->data; + tx_len = ((struct sk_buff *)txcfg->pframe)->len; + tmpphyaddr = get_physical_addr(priv, pbuf, tx_len, PCI_DMA_TODEVICE); +#ifdef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)pbuf, tx_len, PCI_DMA_TODEVICE); +#endif + + pdesc = phdesc + (*tx_head); + pdescinfo = pswdescinfo + *tx_head; + + //clear all bits +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + { + memset(pdesc, 0, 40); //clear all bits + pdesc->Dword10 = set_desc(tmpphyaddr); // TXBufferAddr + pdesc->Dword7 |= (set_desc(tx_len & TX_TxBufSizeMask)); + pdesc->Dword0 |= set_desc(40 << TX_OffsetSHIFT); // tx_desc size + } + else +#endif + { + memset(pdesc, 0, 32); + pdesc->Dword8 = set_desc(tmpphyaddr); // TXBufferAddr + pdesc->Dword7 |= (set_desc(tx_len & TX_TxBufSizeMask)); + pdesc->Dword0 |= set_desc(32 << TX_OffsetSHIFT); // tx_desc size + } + + if (txcfg->aggre_en == FG_AGGRE_MSDU_LAST){ + pdesc->Dword0 = set_desc(TX_OWN | TX_LastSeg); + } + else + pdesc->Dword0 = set_desc(TX_OWN); + +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + pdescinfo->type = _SKB_FRAME_TYPE_; + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + pdescinfo->paddr = get_desc(pdesc->Dword10); // TXBufferAddr + else +#endif + pdescinfo->paddr = get_desc(pdesc->Dword8); // TXBufferAddr + + pdescinfo->pframe = txcfg->pframe; + pdescinfo->len = txcfg->fr_len; + pdescinfo->priv = priv; + + txdesc_rollover(pdesc, (unsigned int *)tx_head); + + priv->amsdu_len += tx_len; + + if (txcfg->aggre_en == FG_AGGRE_MSDU_LAST) { + pfrstdesc = priv->amsdu_first_desc; + pfrstdesc->Dword0 = set_desc((get_desc(pfrstdesc->Dword0) &0xff0000) | priv->amsdu_len | TX_FirstSeg | TX_OWN); +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + pfrstdesc->Dword2 |= set_desc(TXdesc_92E_BK); +#endif + +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(priv->amsdu_first_dma_desc-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + tx_poll(priv, q_num); + } + + return 0; +} +#endif // SUPPORT_TX_AMSDU + + +#if 0 + +#ifdef CONFIG_PCI_HCI +//----------------------------------------------------------------------------- +// Procedure: Fill Tx Command Packet Descriptor +// +// Description: This routine fill command packet descriptor. We assum that command packet +// require only one descriptor. +// +// Arguments: This function is only for Firmware downloading in current stage +// +// Returns: +//----------------------------------------------------------------------------- +int rtl8192cd_SetupOneCmdPacket(struct rtl8192cd_priv *priv, unsigned char *dat_content, unsigned short txLength, unsigned char LastPkt) +/* + IN PADAPTER Adapter, + IN PRT_TCB pTcb, + IN u1Byte QueueIndex, + IN u2Byte index, + IN BOOLEAN bFirstSeg, + IN BOOLEAN bLastSeg, + IN pu1Byte VirtualAddress, + IN u4Byte PhyAddressLow, + IN u4Byte BufferLen, + IN BOOLEAN bSetOwnBit, + IN BOOLEAN bLastInitPacket, + IN u4Byte DescPacketType, + IN u4Byte PktLen + ) +*/ +{ + + unsigned char ih=0; + unsigned char DescNum; + unsigned short DebugTimerCount; + + struct tx_desc *pdesc; + struct tx_desc *phdesc; + volatile unsigned int *ppdesc ; //= (unsigned int *)pdesc; + int *tx_head, *tx_tail; + struct rtl8192cd_hw *phw = GET_HW(priv); + + tx_head = (int *)&phw->txcmdhead; + tx_tail = (int *)&phw->txcmdtail; + phdesc = phw->txcmd_desc; + + DebugTimerCount = 0; // initialize debug counter to exit loop + DescNum = 1; + +//TODO: Fill the dma check here + +// printk("data lens: %d\n", txLength ); + + for (ih=0; ihtxcmd_desc_dma_addr[*tx_head], 32, PCI_DMA_TODEVICE); + // For firmware downlaod we only need to set LINIP + if (LastPkt) + pdesc->Dword0 |= set_desc(TX_LINIP); + + // From Scott --> 92SE must set as 1 for firmware download HW DMA error + pdesc->Dword0 |= set_desc(TX_FirstSeg);;//bFirstSeg; + pdesc->Dword0 |= set_desc(TX_LastSeg);;//bLastSeg; + + // 92SE need not to set TX packet size when firmware download + pdesc->Dword7 |= (set_desc((unsigned short)(txLength) << TX_TxBufSizeSHIFT)); + + memcpy(priv->pshare->txcmd_buf, dat_content, txLength); + + rtl_cache_sync_wback(priv, (unsigned long)priv->pshare->txcmd_buf, txLength, PCI_DMA_TODEVICE); + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + pdesc->Dword10 = set_desc(priv->pshare->cmdbuf_phyaddr); + else +#endif + pdesc->Dword8 = set_desc(priv->pshare->cmdbuf_phyaddr); + + +// pdesc->Dword0 |= set_desc((unsigned short)(txLength) << TX_PktIDSHIFT); + pdesc->Dword0 |= set_desc((unsigned short)(txLength) << TX_PktSizeSHIFT); + //if (bSetOwnBit) + { + pdesc->Dword0 |= set_desc(TX_OWN); +// *(ppdesc) |= set_desc(BIT(31)); + } + +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(phw->txcmd_desc_dma_addr[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + *tx_head = (*tx_head + 1) & (NUM_CMD_DESC - 1); + } + + return TRUE; +} +#endif // CONFIG_PCI_HCI +#endif + +#ifdef CONFIG_RTK_MESH +#ifndef __LINUX_2_6__ +__MIPS16 +#endif +int reuse_meshhdr(struct rtl8192cd_priv *priv, struct tx_insn *txcfg) +{ + const short meshhdrlen= (txcfg->mesh_header.mesh_flag & 0x01) ? 16 : 4; + struct sk_buff *pskb = (struct sk_buff *)txcfg->pframe; + if (skb_cloned(pskb)) + { + struct sk_buff *newskb = skb_copy(pskb, GFP_ATOMIC); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + release_wlanllchdr_to_poll(priv, txcfg->phdr); + DEBUG_ERR("TX DROP: Can't copy the skb!\n"); + return 0; + } + txcfg->pframe = pskb = newskb; +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + } + memcpy(skb_push(pskb,meshhdrlen), &(txcfg->mesh_header), meshhdrlen); + txcfg->fr_len += meshhdrlen; + return 1; +} +#endif //CONFIG_RTK_MESH + + +#if defined(WIFI_WMM) && defined(DRVMAC_LB) +void SendLbQosNullData(struct rtl8192cd_priv *priv) +{ + struct wifi_mib *pmib; + unsigned char *hwaddr; + unsigned char tempQosControl[2]; + DECLARE_TXINSN(txinsn); + + + pmib = GET_MIB(priv); + hwaddr = pmib->dot11OperationEntry.hwaddr; + + if(!pmib->miscEntry.drvmac_lb) { + printk("LB mode disabled, cannot SendLbQosNullData!!!\n"); + return; + } + + if(!memcmp(pmib->miscEntry.lb_da, "\x0\x0\x0\x0\x0\x0", 6)) { + printk("LB addr is NULL, cannot SendLbQosNullData!!!\n"); + return; + } + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + txinsn.q_num = BE_QUEUE; +// txinsn.q_num = MANAGE_QUE_NUM; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; + txinsn.fr_type = _PRE_ALLOCHDR_; + txinsn.phdr = get_wlanhdr_from_poll(priv); + txinsn.pframe = NULL; + + if (txinsn.phdr == NULL) + goto send_qos_null_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + + SetFrameSubType(txinsn.phdr, BIT(7) | WIFI_DATA_NULL); + SetFrDs(txinsn.phdr); + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), pmib->miscEntry.lb_da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + txinsn.hdr_len = WLAN_HDR_A3_QOS_LEN; + + memset(tempQosControl, 0, 2); +// tempQosControl[0] = 0x07; //set priority to VO +// tempQosControl[0] |= BIT(4); //set EOSP + memcpy((void *)GetQosControl((txinsn.phdr)), tempQosControl, 2); + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +send_qos_null_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); +} + + +void SendLbQosData(struct rtl8192cd_priv *priv) +{ + struct wifi_mib *pmib; + unsigned char *hwaddr; + unsigned char tempQosControl[2]; + unsigned char *pbuf; + static unsigned int pkt_length = 1; + DECLARE_TXINSN(txinsn); + + pmib = GET_MIB(priv); + hwaddr = pmib->dot11OperationEntry.hwaddr; + + if(!pmib->miscEntry.drvmac_lb) { + printk("LB mode disabled, cannot SendLbQosData!!!\n"); + return; + } + + if(!memcmp(pmib->miscEntry.lb_da, "\x0\x0\x0\x0\x0\x0", 6)) { + printk("LB addr is NULL, cannot SendLbQosData!!!\n"); + return; + } + + txinsn.retry = priv->pmib->dot11OperationEntry.dot11ShortRetryLimit; + txinsn.q_num = BE_QUEUE; + txinsn.fr_type = _PRE_ALLOCMEM_; + txinsn.tx_rate = find_rate(priv, NULL, 0, 1); + txinsn.lowest_tx_rate = txinsn.tx_rate; + txinsn.fixed_rate = 1; +// txinsn.pframe = NULL; + + pbuf = txinsn.pframe = get_mgtbuf_from_poll(priv); + if (pbuf == NULL) + goto send_qos_fail; + + txinsn.phdr = get_wlanhdr_from_poll(priv); + if (txinsn.phdr == NULL) + goto send_qos_fail; + + memset((void *)(txinsn.phdr), 0, sizeof (struct wlan_hdr)); + memset((void *)pbuf, 0, PRE_ALLOCATED_BUFSIZE); + + SetFrameSubType(txinsn.phdr, WIFI_QOS_DATA); + SetFrDs(txinsn.phdr); + memcpy((void *)GetAddr1Ptr((txinsn.phdr)), pmib->miscEntry.lb_da, MACADDRLEN); + memcpy((void *)GetAddr2Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + memcpy((void *)GetAddr3Ptr((txinsn.phdr)), hwaddr, MACADDRLEN); + txinsn.hdr_len = WLAN_HDR_A3_QOS_LEN; + + memset(tempQosControl, 0, 2); + memcpy((void *)GetQosControl((txinsn.phdr)), tempQosControl, 2); + +// printk("--0x%02x%02x%02x%02x 0x%02x%02x%02x%02x--\n", *pbuf, *(pbuf+1), *(pbuf+2), *(pbuf+3), *(pbuf+4), *(pbuf+5), *(pbuf+6), *(pbuf+7)); + + if (pmib->miscEntry.lb_mlmp == 1) { + // all zero in payload + memset((void *)pbuf, 0x00, pkt_length); + pbuf += pkt_length; + txinsn.fr_len += pkt_length; + } + else if (pmib->miscEntry.lb_mlmp == 2) { + // all 0xff in payload + memset((void *)pbuf, 0xff, pkt_length); +// printk("~~0x%02x%02x%02x%02x 0x%02x%02x%02x%02x~~\n", *pbuf, *(pbuf+1), *(pbuf+2), *(pbuf+3), *(pbuf+4), *(pbuf+5), *(pbuf+6), *(pbuf+7)); + pbuf += pkt_length; + txinsn.fr_len += pkt_length; + } + else if ((pmib->miscEntry.lb_mlmp == 3) || (pmib->miscEntry.lb_mlmp == 4)) { + // all different value in payload, 0x00~0xff + unsigned int i = 0; +// printk("~~"); + for (i = 0; i = 600) + if (pkt_length++ >= 2048) + pkt_length = 1; + + if ((rtl8192cd_firetx(priv, &txinsn)) == SUCCESS) + return; + +send_qos_fail: + + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); +} +#endif + +#ifdef TX_EARLY_MODE +__MIPS16 +__IRAM_IN_865X +static void get_tx_early_info(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct sk_buff_head *pqueue) +{ + struct sk_buff *next_skb; + + pstat->empkt_num = 0; + memset(pstat->empkt_len, '\0', sizeof(pstat->empkt_len)); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + int tmplen = 0, extra_len = 0; + + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _CCMP_PRIVACY_) { + extra_len = 16; + } else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _TKIP_PRIVACY_) { + extra_len = 20; + } else if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_ || + priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_) { + extra_len = 8; + } + + skb_queue_walk(pqueue, next_skb) { + if ((pstat->empkt_num %2) == 0) { + pstat->empkt_len[pstat->empkt_num/2] = next_skb->len+WLAN_HDR_A3_LEN+WLAN_CRC_LEN+extra_len; + } else { + tmplen = pstat->empkt_len[(pstat->empkt_num-1)/2]; + tmplen += ((tmplen%4)?(4-tmplen%4):0)+4; + tmplen += next_skb->len+WLAN_HDR_A3_LEN+WLAN_CRC_LEN+extra_len; + pstat->empkt_len[(pstat->empkt_num-1)/2] = tmplen; + } + + pstat->empkt_num++; + if (skb_queue_is_last(pqueue, next_skb)) + break; + + if (pstat->empkt_num >= 10) + break; + } + } else +#endif + skb_queue_walk(pqueue, next_skb) { + pstat->empkt_len[pstat->empkt_num++] = next_skb->len; + + if (skb_queue_is_last(pqueue, next_skb)) + break; + + if (pstat->empkt_num >= 5) + break; + } +} +#endif + +#ifdef SW_TX_QUEUE +__MIPS16 +__IRAM_IN_865X +#if defined(CONFIG_RTK_MESH) +int __rtl8192cd_start_xmit_out(struct sk_buff *skb, struct stat_info *pstat, struct tx_insn *ptxcfg); +#else +int __rtl8192cd_start_xmit_out(struct sk_buff *skb, struct stat_info *pstat); +#endif + + +void rtl8192cd_beq_timer(unsigned long task_priv) +{ + struct stat_info *pstat = (struct stat_info *)task_priv; + struct sk_buff *skb = NULL; + struct rtl8192cd_priv *priv = NULL; + unsigned long x = 0, bdfull=0, qnum = BE_QUEUE; + struct aid_obj *aidobj; + int *tx_head=NULL, *tx_tail=NULL; + + aidobj = container_of(pstat, struct aid_obj, station); + priv = aidobj->priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) { + return; + } + + SMP_LOCK_XMIT(x); + SAVE_INT_AND_CLI(x); + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)){ + if(compareAvailableTXBD(priv, 4, qnum, 2)) + bdfull = 1; + }else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + tx_head = get_txhead_addr(GET_HW(priv), qnum); + tx_tail = get_txtail_addr(GET_HW(priv), qnum); + if((4) > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC)) + bdfull = 1; + } + + while(1) { + + if(bdfull) { + struct sk_buff_head *pqueue = &pstat->swq.be_queue; + struct timer_list *ptimer; + int aggnum=pstat->swq.q_aggnum[qnum]; + ptimer = &pstat->swq.beq_timer; + + if(skb_queue_len(pqueue) <= aggnum*2) + { + pstat->swq.q_used[qnum]=1; + if (!timer_pending(ptimer)) + { + ptimer->data = (unsigned long) pstat; + ptimer->function = rtl8192cd_beq_timer; //rtl8190_tmp_timer; + mod_timer(ptimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(30)); + } + break; + } + } + + + skb = skb_dequeue(&pstat->swq.be_queue); + + if (skb == NULL) + break; + + + + +#ifdef TX_EARLY_MODE + if (priv && GET_TX_EARLY_MODE && GET_EM_SWQ_ENABLE) + get_tx_early_info(priv, pstat, &pstat->swq.be_queue); +#endif + +#if defined(CONFIG_RTK_MESH) + __rtl8192cd_start_xmit_out(skb, pstat, NULL); +#else + __rtl8192cd_start_xmit_out(skb, pstat); +#endif + + pstat->swq.q_TOCount[BE_QUEUE]++; + } + if(skb_queue_len(&pstat->swq.be_queue) ==0) + pstat->swq.beq_empty = 0; + + RESTORE_INT(x); + SMP_UNLOCK_XMIT(x); + + if(!bdfull) { + SAVE_INT_AND_CLI(x); + SMP_LOCK(x); + adjust_swq_setting(priv, pstat, BE_QUEUE, CHECK_DEC_AGGN); + SMP_UNLOCK(x); + RESTORE_INT(x); + } +} + +void rtl8192cd_bkq_timer(unsigned long task_priv) +{ + struct stat_info *pstat = (struct stat_info *)task_priv; + struct sk_buff *skb = NULL; + struct rtl8192cd_priv *priv = NULL; + unsigned long x = 0, bdfull=0, qnum = BK_QUEUE; + struct aid_obj *aidobj; + int *tx_head=NULL, *tx_tail=NULL; + + + aidobj = container_of(pstat, struct aid_obj, station); + priv = aidobj->priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) { + return; + } + SMP_LOCK_XMIT(x); + SAVE_INT_AND_CLI(x); + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { + if(compareAvailableTXBD(priv, 4, qnum, 2)) + bdfull = 1; + }else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + tx_head = get_txhead_addr(GET_HW(priv), qnum); + tx_tail = get_txtail_addr(GET_HW(priv), qnum); + if((4) > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC)) + bdfull = 1; + } + + while(1) { + + if(bdfull) { + struct sk_buff_head *pqueue = &pstat->swq.bk_queue; + struct timer_list *ptimer; + int aggnum=pstat->swq.q_aggnum[qnum]; + ptimer = &pstat->swq.bkq_timer; + + if(skb_queue_len(pqueue) <= aggnum*2) + { + pstat->swq.q_used[qnum]=1; + if (!timer_pending(ptimer)) + { + ptimer->data = (unsigned long) pstat; + ptimer->function = rtl8192cd_bkq_timer; //rtl8190_tmp_timer; + mod_timer(ptimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(30)); + } + break; + } + } + + skb = skb_dequeue(&pstat->swq.bk_queue); + + if (skb == NULL) + break; + + +#ifdef TX_EARLY_MODE + if (priv && GET_TX_EARLY_MODE && GET_EM_SWQ_ENABLE) + get_tx_early_info(priv, pstat, &pstat->swq.bk_queue); +#endif + +#if defined(CONFIG_RTK_MESH) + __rtl8192cd_start_xmit_out(skb, pstat, NULL); +#else + __rtl8192cd_start_xmit_out(skb, pstat); +#endif + + pstat->swq.q_TOCount[BK_QUEUE]++; + } + if(skb_queue_len(&pstat->swq.bk_queue) ==0) + pstat->swq.bkq_empty = 0; + + RESTORE_INT(x); + SMP_UNLOCK_XMIT(x); + + if(!bdfull) { + SAVE_INT_AND_CLI(x); + SMP_LOCK(x); + adjust_swq_setting(priv, pstat, BK_QUEUE, CHECK_DEC_AGGN); + SMP_UNLOCK(x); + RESTORE_INT(x); + } +} + +void rtl8192cd_viq_timer(unsigned long task_priv) +{ + struct stat_info *pstat = (struct stat_info *)task_priv; + struct sk_buff *skb = NULL; + struct rtl8192cd_priv *priv = NULL; + unsigned long x = 0, bdfull=0, qnum = VI_QUEUE; + struct aid_obj *aidobj; + int *tx_head=NULL, *tx_tail=NULL; + + aidobj = container_of(pstat, struct aid_obj, station); + priv = aidobj->priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) { + return; + } + + SMP_LOCK_XMIT(x); + SAVE_INT_AND_CLI(x); + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { + if(compareAvailableTXBD(priv, 4, qnum, 2)) + bdfull = 1; + }else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + tx_head = get_txhead_addr(GET_HW(priv), qnum); + tx_tail = get_txtail_addr(GET_HW(priv), qnum); + if((4) > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC)) + bdfull = 1; + } + + + while(1) { + if(bdfull) { + struct sk_buff_head *pqueue = &pstat->swq.vi_queue; + struct timer_list *ptimer; + int aggnum=pstat->swq.q_aggnum[qnum]; + ptimer = &pstat->swq.viq_timer; + + if(skb_queue_len(pqueue) <= aggnum*2) + { + pstat->swq.q_used[qnum]=1; + if (!timer_pending(ptimer)) + { + ptimer->data = (unsigned long) pstat; + ptimer->function = rtl8192cd_viq_timer; //rtl8190_tmp_timer; + mod_timer(ptimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(30)); + } + break; + } + } + + skb = skb_dequeue(&pstat->swq.vi_queue); + + if (skb == NULL) + break; + + + +#ifdef TX_EARLY_MODE + if (priv && GET_TX_EARLY_MODE && GET_EM_SWQ_ENABLE) + get_tx_early_info(priv, pstat, &pstat->swq.vi_queue); +#endif + +#if defined(CONFIG_RTK_MESH) + __rtl8192cd_start_xmit_out(skb, pstat, NULL); +#else + __rtl8192cd_start_xmit_out(skb, pstat); +#endif + + pstat->swq.q_TOCount[VI_QUEUE]++; + } + if(skb_queue_len(&pstat->swq.vi_queue) ==0) + pstat->swq.viq_empty = 0; + + RESTORE_INT(x); + SMP_UNLOCK_XMIT(x); + + if(!bdfull) { + SAVE_INT_AND_CLI(x); + SMP_LOCK(x); + adjust_swq_setting(priv, pstat, VI_QUEUE, CHECK_DEC_AGGN); + SMP_UNLOCK(x); + RESTORE_INT(x); + } +} + +void rtl8192cd_voq_timer(unsigned long task_priv) +{ + struct stat_info *pstat = (struct stat_info *)task_priv; + struct sk_buff *skb = NULL; + struct rtl8192cd_priv *priv = NULL; + unsigned long x = 0, bdfull=0, qnum = VO_QUEUE; + struct aid_obj *aidobj; + int *tx_head=NULL, *tx_tail=NULL; + + aidobj = container_of(pstat, struct aid_obj, station); + priv = aidobj->priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) { + return; + } + SMP_LOCK_XMIT(x); + SAVE_INT_AND_CLI(x); + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { + if(compareAvailableTXBD(priv, 4, qnum, 2)) + bdfull = 1; + }else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + tx_head = get_txhead_addr(GET_HW(priv), qnum); + tx_tail = get_txtail_addr(GET_HW(priv), qnum); + if((4) > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC)) + bdfull = 1; + } + + while(1) { + + if(bdfull) { + struct sk_buff_head *pqueue = &pstat->swq.vo_queue; + struct timer_list *ptimer; + int aggnum=pstat->swq.q_aggnum[qnum]; + ptimer = &pstat->swq.voq_timer; + + if(skb_queue_len(pqueue) <= aggnum*2) + { + pstat->swq.q_used[qnum]=1; + if (!timer_pending(ptimer)) + { + ptimer->data = (unsigned long) pstat; + ptimer->function = rtl8192cd_voq_timer; //rtl8190_tmp_timer; + mod_timer(ptimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(30)); + } + break; + } + } + + skb = skb_dequeue(&pstat->swq.vo_queue); + + if (skb == NULL) + break; + + +#ifdef TX_EARLY_MODE + if (priv && GET_TX_EARLY_MODE && GET_EM_SWQ_ENABLE) + get_tx_early_info(priv, pstat, &pstat->swq.vo_queue); +#endif + +#if defined(CONFIG_RTK_MESH) + __rtl8192cd_start_xmit_out(skb, pstat, NULL); +#else + __rtl8192cd_start_xmit_out(skb, pstat); +#endif + + pstat->swq.q_TOCount[VO_QUEUE]++; + } + if(skb_queue_len(&pstat->swq.vo_queue) ==0) + pstat->swq.voq_empty = 0; + + RESTORE_INT(x); + SMP_UNLOCK_XMIT(x); + + if(!bdfull) { + SAVE_INT_AND_CLI(x); + SMP_LOCK(x); + adjust_swq_setting(priv, pstat, VO_QUEUE, CHECK_DEC_AGGN); + SMP_UNLOCK(x); + RESTORE_INT(x); + } +} + +__MIPS16 +__IRAM_IN_865X +int sw_dequeue(struct rtl8192cd_priv *priv, struct sk_buff_head *pqueue, struct timer_list *ptimer)//, int *pempty) +{ + struct stat_info *pstat = (struct stat_info *)ptimer->data; + int *tx_head=NULL, *tx_tail=NULL, bdfull=0, qnum = BE_QUEUE; + + if (timer_pending(ptimer)) + del_timer(ptimer); + + if(pqueue == &pstat->swq.bk_queue) + qnum = BK_QUEUE; + else if(pqueue == &pstat->swq.vi_queue) + qnum = VI_QUEUE; + else if(pqueue == &pstat->swq.vo_queue) + qnum = VO_QUEUE; + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { + if(compareAvailableTXBD(priv, 4, qnum, 2)) + bdfull = 1; + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + tx_head = get_txhead_addr(GET_HW(priv), qnum); + tx_tail = get_txtail_addr(GET_HW(priv), qnum); + if((4) > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC)) + bdfull = 1; + } + + while(1) + { + struct sk_buff *tmpskb; + + if(bdfull) { + break; + } + + tmpskb = skb_dequeue(pqueue); + if (tmpskb == NULL) + break; + +#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE && GET_EM_SWQ_ENABLE) + get_tx_early_info(priv, pstat, pqueue); +#endif +#if defined(CONFIG_RTK_MESH) + __rtl8192cd_start_xmit_out(tmpskb, pstat, NULL); +#else + __rtl8192cd_start_xmit_out(tmpskb, pstat); +#endif + } + return 0; +} + +__MIPS16 +__IRAM_IN_865X +int sw_enqueue(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat) +{ + int q_len, pri, q_num, tri_time, *pempty, aggnum; + struct sk_buff_head *pqueue; + struct timer_list *ptimer; + void (*timer_hook)(unsigned long task_priv); + + pri = get_skb_priority(priv, skb, pstat); +#if defined(RTL_MANUAL_EDCA) + q_num = PRI_TO_QNUM(priv, pri); +#else + PRI_TO_QNUM(pri, q_num, priv->pmib->dot11OperationEntry.wifi_specific); +#endif + switch(q_num) + { + case BK_QUEUE: + pqueue = &pstat->swq.bk_queue; + ptimer = &pstat->swq.bkq_timer; + timer_hook = rtl8192cd_bkq_timer; + pempty = &pstat->swq.bkq_empty; + pstat->swq.q_used[BK_QUEUE]=1; + aggnum=pstat->swq.q_aggnum[BK_QUEUE]; + break; + case VO_QUEUE: + pqueue = &pstat->swq.vo_queue; + ptimer = &pstat->swq.voq_timer; + timer_hook = rtl8192cd_voq_timer; + pempty = &pstat->swq.voq_empty; + pstat->swq.q_used[VO_QUEUE]=1; + aggnum=pstat->swq.q_aggnum[VO_QUEUE]; + break; + case VI_QUEUE: + pqueue = &pstat->swq.vi_queue; + ptimer = &pstat->swq.viq_timer; + timer_hook = rtl8192cd_viq_timer; + pempty = &pstat->swq.viq_empty; + pstat->swq.q_used[VI_QUEUE]=1; + aggnum=pstat->swq.q_aggnum[VI_QUEUE]; + break; + //case BE_QUEUE: + default: + pqueue = &pstat->swq.be_queue; + ptimer = &pstat->swq.beq_timer; + timer_hook = rtl8192cd_beq_timer; + pempty = &pstat->swq.beq_empty; + pstat->swq.q_used[BE_QUEUE]=1; + aggnum=pstat->swq.q_aggnum[BE_QUEUE]; + break; + } + + skb_queue_tail(pqueue, skb); + ptimer->data = (unsigned long)pstat; + + if (!pstat->ADDBA_ready[pri]) + { + sw_dequeue(priv, pqueue, ptimer); + if(skb_queue_len(pqueue) ==0) + *pempty = 0; + return 0; + } + + q_len = skb_queue_len(pqueue); +// if(priv->assoc_num == 1) +// aggnum = priv->pshare->rf_ft_var.swq_aggnum; + +#ifdef TX_EARLY_MODE + if (q_len >= (GET_EM_SWQ_ENABLE ? MAX_EM_QUE_NUM : aggnum)) { +#else + if (q_len >= aggnum) { +#endif + sw_dequeue(priv, pqueue, ptimer);//, pempty); + if(skb_queue_len(pqueue) ==0) + *pempty = 0; + return 0; + } else if (q_len == 1) { + if (!timer_pending(ptimer)) + { + if ((pstat->tx_avarage > 1875000)) //15M~ + tri_time = RTL_MILISECONDS_TO_JIFFIES(10); + else if ((pstat->tx_avarage > 500000)) //4M~15M + tri_time = RTL_MILISECONDS_TO_JIFFIES(30); + else if ((pstat->tx_avarage > 250000) && (pstat->tx_avarage <= 500000)) //2M~4M + tri_time = RTL_MILISECONDS_TO_JIFFIES(90); + else if ((pstat->tx_avarage > 100000)) //800K~2M + tri_time = RTL_MILISECONDS_TO_JIFFIES(120); + else + tri_time = RTL_MILISECONDS_TO_JIFFIES(10); + + ptimer->data = (unsigned long) pstat; + ptimer->function = timer_hook; //rtl8190_tmp_timer; + mod_timer(ptimer, jiffies + tri_time); + } + } + + *pempty = 1; + return 0; +} +#endif + +#ifdef A4_STA +static void send_br_packet(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat) +{ + struct sk_buff *newskb=NULL; + struct tx_insn tx_insn; + DECLARE_TXCFG(txcfg, tx_insn); + +#ifdef DETECT_STA_EXISTANCE + if (pstat->leave) { + priv->ext_stats.tx_drops++; + DEBUG_WARN("TX DROP: sta may leave! %02x%02x%02x%02x%02x%02x\n", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + return; + } +#endif + + if (UseSwCrypto(priv, pstat, FALSE) || + (get_sta_encrypt_algthm(priv, pstat) == _TKIP_PRIVACY_)) { + if (skb_cloned(skb)) { + newskb = skb_copy(skb, GFP_ATOMIC); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't copy the skb!\n"); + return; + } + } + } + + if (!newskb) { + newskb = skb_clone(skb, GFP_ATOMIC); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't clone the skb!\n"); + return; + } + } + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + + txcfg->pstat = pstat; + +#if defined(CONFIG_PCI_HCI) + if ((pstat->state & (WIFI_SLEEP_STATE | WIFI_ASOC_STATE)) == + (WIFI_SLEEP_STATE | WIFI_ASOC_STATE)) { + if (dz_queue(priv, pstat, newskb) == TRUE) + { + DEBUG_INFO("queue up skb due to sleep mode\n"); + } + else { + DEBUG_WARN("ucst sleep queue full!!\n"); + rtl_kfree_skb(priv, newskb, _SKB_TX_); + } + return; + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + txcfg->fr_type = _SKB_FRAME_TYPE_; + txcfg->pframe = newskb; + + if (update_txinsn_stage1(priv, txcfg) == FALSE) { + priv->ext_stats.tx_drops++; + rtl_kfree_skb(priv, newskb, _SKB_TX_); + return; + } + + txcfg->next_txpath = TXPATH_SLOW_PATH; + + xmit_preempt_disable(flags); + if ((pstat->state & (WIFI_SLEEP_STATE | WIFI_ASOC_STATE)) == + (WIFI_SLEEP_STATE | WIFI_ASOC_STATE)) { + if (dz_queue(priv, pstat, txcfg) == TRUE) + { + DEBUG_INFO("queue up skb due to sleep mode\n"); + } + else { + DEBUG_WARN("ucst sleep queue full!!\n"); + rtl_kfree_skb(priv, newskb, _SKB_TX_); + } + xmit_preempt_enable(flags); + return; + } + + if (rtw_is_tx_queue_empty(priv, txcfg) == FALSE) { + if (rtw_xmit_enqueue(priv, txcfg) == FALSE) { + rtl_kfree_skb(priv, newskb, _SKB_TX_); + } + xmit_preempt_enable(flags); + return; + } + xmit_preempt_enable(flags); +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + + SMP_UNLOCK_XMIT(flags); + rtl8192cd_tx_slowPath(priv, newskb, pstat, priv->dev, NULL, txcfg); + SMP_LOCK_XMIT(flags); +} +#endif /* A4_STA */ + +#ifdef CONFIG_PCI_HCI +#ifndef SW_TX_QUEUE +__MIPS16 +__IRAM_IN_865X +int __rtl8192cd_start_xmit_out(struct sk_buff *skb, struct stat_info *pstat); +#endif + +__MIPS16 +__IRAM_IN_865X +int __rtl8192cd_start_xmit(struct sk_buff *skb, struct net_device *dev, int tx_flag) +{ + struct rtl8192cd_priv *priv; + struct stat_info *pstat=NULL; + unsigned char *da; +#if defined(HS2_SUPPORT) + struct sk_buff *newskb = NULL; +#endif +#ifdef TX_SCATTER + struct sk_buff *newskb = NULL; +#endif + struct net_device *wdsDev = NULL; +#ifdef SW_TX_QUEUE + int q_num, *pempty; + int swq_out = 0; + struct sk_buff_head *pqueue; + struct timer_list *ptimer; +#endif +#if defined(CONFIG_RTK_VLAN_SUPPORT) + struct vlan_info *vlan=NULL; +#endif + struct tx_insn tx_insn; +#ifdef CONFIG_RTL_EAP_RELAY + int real_len; +#endif +#ifdef CONFIG_RTL_VLAN_8021Q + uint16 vid; + struct sk_buff *newskb; +#endif + int temp; +#ifdef SMP_SYNC + unsigned long flags; +#endif + + + DECLARE_TXCFG(txcfg, tx_insn); + + priv = GET_DEV_PRIV(dev); + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + + if (skb->len < 15) + { + _DEBUG_ERR("TX DROP: SKB len small:%d\n", skb->len); + goto free_and_stop; + } + + #ifdef CONFIG_RTL_NETSNIPER_SUPPORT + rtl_netsniper_check(skb, dev); + #endif + +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU) + if (dev==wlan_device[passThruWanIdx].priv->pWlanDev ||skb->dev==wlan_device[passThruWanIdx].priv->pWlanDev) + { +#ifdef __ECOS + if (SUCCESS==rtl_isWlanPassthruFrame(skb->data)) +#else + if (SUCCESS==rtl_isPassthruFrame(skb->data)) +#endif + { +#ifdef UNIVERSAL_REPEATER + if(passThruStatusWlan & 0x8) //WISP Mode Enable. default is vxd + { + // TODO: need to add 8881A?, check it + #if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT)||defined (CONFIG_RTL_8881A) + unsigned int wispWlanIndex=(passThruStatusWlan&WISP_WLAN_IDX_MASK)>>WISP_WLAN_IDX_RIGHT_SHIFT; + if ((wlan_device[wispWlanIndex].priv->drv_state & DRV_STATE_OPEN )&& + ((GET_MIB(GET_VXD_PRIV((wlan_device[wispWlanIndex].priv)))->dot11OperationEntry.opmode) & WIFI_STATION_STATE)) + { + #if 0//def NETDEV_NO_PRIV + //dev=skb->dev=((struct rtl8192cd_priv *)(((struct rtl8192cd_priv *)netdev_priv(wlan_device[wispWlanIndex].priv->pWlanDev))->wlan_priv))->pvxd_priv->dev; + dev=skb->dev=(((struct rtl8192cd_priv *)netdev_priv(wlan_device[wispWlanIndex].priv->dev))->wlan_priv)->pvxd_priv->dev; + #else + dev=skb->dev=GET_VXD_PRIV(wlan_device[wispWlanIndex].priv)->dev; + #endif + } else { + goto free_and_stop; + } + #else + #if 0//def NETDEV_NO_PRIV + //dev=skb->dev=((struct rtl8192cd_priv *)(((struct rtl8192cd_priv *)netdev_priv(wlan_device[passThruWanIdx].priv->pWlanDev))->wlan_priv))->pvxd_priv->dev; + dev=skb->dev=(((struct rtl8192cd_priv *)netdev_priv(wlan_device[wispWlanIndex].priv->dev))->wlan_priv)->pvxd_priv->dev; + #else + dev=skb->dev= GET_VXD_PRIV(wlan_device[passThruWanIdx].priv)->dev; + #endif + #endif + } else +#endif + { + // TODO: need to add 8881A?, check it + #if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT)||defined (CONFIG_RTL_8881A) + unsigned int wispWlanIndex=(passThruStatusWlan&WISP_WLAN_IDX_MASK)>>WISP_WLAN_IDX_RIGHT_SHIFT; + if ((wlan_device[wispWlanIndex].priv->drv_state & DRV_STATE_OPEN )&& + (((GET_MIB(wlan_device[wispWlanIndex].priv))->dot11OperationEntry.opmode) & WIFI_STATION_STATE)) + { + #ifdef NETDEV_NO_PRIV + dev=skb->dev=((struct rtl8192cd_priv *)netdev_priv(wlan_device[wispWlanIndex].priv->pWlanDev))->wlan_priv->dev; + #else + dev=skb->dev=wlan_device[wispWlanIndex].priv->dev; + #endif + } else { + goto free_and_stop; + } + #else + #ifdef NETDEV_NO_PRIV + dev=skb->dev=((struct rtl8192cd_priv *)netdev_priv(wlan_device[passThruWanIdx].priv->pWlanDev))->wlan_priv->dev; + #else + dev=skb->dev=((struct rtl8192cd_priv *)(wlan_device[passThruWanIdx].priv->pWlanDev->priv))->dev; + #endif + #endif + } + + SMP_UNLOCK_XMIT(flags); + + rtl8192cd_start_xmit(skb, dev); + + SMP_LOCK_XMIT(flags); + return 0; + + } else { + goto free_and_stop; + } + } +#endif /* defined(CONFIG_RTL_CUSTOM_PASSTHRU) */ + +#if 0//def CONFIG_RTL_STP + //port5: virtual device for wlan0 stp BPDU process + if(memcmp((void *)(dev->name), "port5", 5)==0) + { + if ((skb->data[0]&0x01) && !memcmp(&(skb->data[0]), STPmac, 5) && !(skb->data[5] & 0xF0)) + { + //To virtual device port5, tx bpdu. + } + else + { + //To virtual device port5, drop tx pkt becasue not bpdu! + goto free_and_stop; + } + } +#endif + +#ifdef CONFIG_RTL_EAP_RELAY +//mark_test , remove EAP padding by ethernet + if (*((UINT16 *)((UINT8 *)skb->data + ETH_ALEN*2)) == __constant_htons(0x888e)) + { + real_len = ETH_ALEN*2+2+4+ntohs(*((UINT16 *)((UINT8 *)skb->data + ETH_ALEN*2+2+2))); + skb_trim(skb,real_len); + //printk("2 wlan tx EAP ,skb->len=%d,skb->data=%d \n",skb->len,skb->data_len); + } +#endif + +//#ifdef SW_TX_QUEUE + skb->dev = dev; +//#endif + +#ifdef WDS + if (!dev->base_addr && skb_cloned(skb) + && (priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_) + ) { + struct sk_buff *mcast_skb = NULL; + mcast_skb = skb_copy(skb, GFP_ATOMIC); + if (mcast_skb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't copy the skb!\n"); + goto free_and_stop; + } + dev_kfree_skb_any(skb); + skb = mcast_skb; + } +#endif + +#ifdef IGMP_FILTER_CMO + if (priv->pshare->rf_ft_var.igmp_deny) + { + if ((OPMODE & WIFI_AP_STATE) && IS_MCAST(skb->data)) + { + if (IP_MCAST_MAC(skb->data) + #ifdef TX_SUPPORT_IPV6_MCAST2UNI + || ICMPV6_MCAST_MAC(skb->data) + #endif + ) + { + if(!IS_IGMP_PROTO(skb->data)){ + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Multicast packet filtered\n"); + goto free_and_stop; + } + } + } + } +#endif + +#ifdef HS2_SUPPORT + if (priv->proxy_arp) { + + unsigned short protocol; + + if(isDHCPpkt(skb)) { + staip_snooping_bydhcp(skb, priv); + } + + if (IS_MCAST(skb->data)) { + protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); + + //proxy arp + if (protocol == __constant_htons(ETH_P_ARP)) { + if (proxy_arp_handle(priv, skb)) { + //reply ok and return + goto stop_proc; + } + //drop packets + goto free_and_stop; + } + //icmpv6 + if (ICMPV6_MCAST_SOLI_MAC(skb->data)) { + //if (ICMPV6_MCAST_MAC(skb->data)) + if (proxy_icmpv6_ndisc(priv,skb)) { + goto stop_proc; + } + //drop packets + goto free_and_stop; + } + //drop unsolicited neighbor advertisement when proxy arp=1 + if (ICMPV6_MCAST_MAC(skb->data)) { + if (check_nei_advt(priv,skb)) { + //drop packets + goto free_and_stop; + } + } + } + } + + if(priv->dgaf_disable) + { + //dhcp m2u check + if (IS_MCAST(skb->data)) + { + if (isDHCPpkt(skb)) + { + struct list_head *phead, *plist; + + phead = &priv->asoc_list; + plist = phead->next; + while (phead && (plist != phead)) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + /* avoid come from STA1 and send back STA1 */ + if (!memcmp(pstat->hwaddr, &skb->data[6], 6)) + { + continue; + } +#if defined(CONFIG_RTL865X_ETH_PRIV_SKB) || defined(CONFIG_RTL_ETH_PRIV_SKB) + newskb = priv_skb_copy(skb); +#else + newskb = skb_copy(skb, GFP_ATOMIC); +#endif + if (newskb) + { + memcpy(newskb->data, pstat->hwaddr, 6); + newskb->cb[2] = (char)0xff; // not do aggregation + printk("send m2u\n"); + __rtl8192cd_start_xmit(newskb, priv->dev, TX_NO_MUL2UNI); + } + } + } + goto free_and_stop; + } + } +#endif + +#ifdef SUPPORT_TX_MCAST2UNI +#ifdef WDS // when interface is WDS don't enter multi2uni path + if (dev->base_addr && !priv->pmib->dot11WdsInfo.wdsPure) +#endif + if (!priv->pshare->rf_ft_var.mc2u_disable) { + if ((OPMODE & WIFI_AP_STATE) && IS_MCAST(skb->data)) + { + if ((IP_MCAST_MAC(skb->data) + #ifdef TX_SUPPORT_IPV6_MCAST2UNI + || IPV6_MCAST_MAC(skb->data) + #endif + ) && (tx_flag != TX_NO_MUL2UNI)) + { + if (mlcst2unicst(priv, skb)){ + return 0; + } + } + } + + skb->cb[2] = 0; // allow aggregation + } +#endif + +#ifdef SUPPORT_TX_MCAST2UNI + skb->cb[16] = tx_flag; +#endif + +#if !defined(CONFIG_RTL_8676HWNAT) && defined(CONFIG_RTL8672) && !defined(CONFIG_RTL8686) && !defined(CONFIG_RTL8685) + + //IGMP snooping + if (check_wlan_mcast_tx(skb)==1) { + goto free_and_stop; + } +#endif + +#ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS && + GET_ROOT(priv)->pmib->dot11DFSEntry.disable_tx + && (priv->site_survey) + && (priv->site_survey->hidden_ap_found != HIDE_AP_FOUND_DO_ACTIVE_SSAN)) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: DFS probation period\n"); + goto free_and_stop; + } +#endif + + if (!IS_DRV_OPEN(priv)) + goto free_and_stop; + +#ifdef MP_TEST + if (OPMODE & WIFI_MP_STATE) { + goto free_and_stop; + } +#endif + +#ifdef MULTI_MAC_CLONE + if (priv->pmib->ethBrExtInfo.macclone_enable) { + int id; + if (!(skb->data[ETH_ALEN] & 1) && MCLONE_NUM > 0) { + id = mclone_find_address(priv, skb->data+ETH_ALEN, skb, MAC_CLONE_SA_FIND); + if (id > 0) + ACTIVE_ID = id; + else + ACTIVE_ID = 0; + } else + ACTIVE_ID = 0; + } +#endif + +#ifdef CONFIG_RTL867X_VLAN_MAPPING + if (re_vlan_loaded()) { + struct ethhdr *eth = (struct ethhdr *)skb->data; + unsigned short vid = 0; + + if (eth->h_proto != ETH_P_PAE) { + if (re_vlan_skb_xmit(skb, &vid)) { + priv->ext_stats.tx_drops++; + return 0; + } + if (vid && re_vlan_addtag(skb, vid)) { + priv->ext_stats.tx_drops++; + return 0; + } + } + } +#endif + +#ifdef CONFIG_RTK_VLAN_SUPPORT + vlan = &priv->pmib->vlan; + + if (vlan->global_vlan && + *((UINT16 *)((UINT8 *)skb->data + ETH_ALEN*2)) != __constant_htons(0x888e)) { + int get_pri = 0; +#ifdef WIFI_WMM + if (QOS_ENABLE) { +#ifdef CLIENT_MODE + if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + pstat = get_stainfo(priv, BSSID); + else +#endif + { +#ifdef MCAST2UI_REFINE + if (pstat == NULL && !IS_MCAST(&skb->cb[10])) + pstat = get_stainfo(priv, &skb->cb[10]); +#else + if (pstat == NULL && !IS_MCAST(skb->data)) + pstat = get_stainfo(priv, skb->data); +#endif + } + + if (pstat && pstat->QosEnabled) + get_pri = 1; + } +#endif + + if (!get_pri) + skb->cb[0] = '\0'; + + if (tx_vlan_process(dev, &priv->pmib->vlan, skb, get_pri)) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: by vlan!\n"); + goto free_and_stop; + } + } + else + skb->cb[0] = '\0'; +#endif + +#if defined(CONFIG_RTL_819X_ECOS)&&defined(CONFIG_RTL_VLAN_SUPPORT)&&defined(CONFIG_RTL_819X_SWCORE) + if (rtl_vlan_support_enable && ntohs(*((UINT16 *)((UINT8 *)skb->data + ETH_ALEN*2))) != 0x888e) { + int get_pri = 0; + if (QOS_ENABLE) { +#ifdef CLIENT_MODE + if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + pstat = get_stainfo(priv, BSSID); + else +#endif + { + if (pstat == NULL && !IS_MCAST(skb->data)) + pstat = get_stainfo(priv, skb->data); + } + + if (pstat && pstat->QosEnabled) + get_pri = 1; + } + + if (!get_pri) + skb->cb[0] = '\0'; + + if (rtl_vlanEgressProcess(skb, priv->dev->name, get_pri) < 0) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: by vlan!\n"); + goto free_and_stop; + } + } + else + skb->cb[0] = '\0'; +#endif + +#ifdef CONFIG_RTL_VLAN_8021Q + /*remove vlan tag if it is not need to tagged out*/ + if(linux_vlan_enable){ + if(*((uint16*)(skb->data+(ETH_ALEN<<1))) == __constant_htons(ETH_P_8021Q)){ + vid = *((uint16*)(skb->data+(ETH_ALEN<<1)+2)); + vid = vid&0xfff; + if(!(vlan_ctl_p->group[vid].tagMemberMask&(1<vlan_member_map))){ + if (skb_cloned(skb)){ + newskb = skb_copy(skb, GFP_ATOMIC); + if (newskb == NULL) { + goto free_and_stop; + } + dev_kfree_skb_any(skb); + skb = newskb; + } + memmove(skb->data+VLAN_HLEN, skb->data, ETH_ALEN<<1); + skb_pull(skb,VLAN_HLEN); + } + } + } +#endif + +#ifdef WDS + if (dev->base_addr) { + // normal packets + if (priv->pmib->dot11WdsInfo.wdsPure) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Sent normal pkt in Pure WDS mode!\n"); + goto free_and_stop; + } + } + else { + // WDS process + if (rtl8192cd_tx_wdsDevProc(priv, skb, &dev, &wdsDev, txcfg) == TX_PROCEDURE_CTRL_STOP) { + goto stop_proc; + } + } +#endif // WDS + + if (priv->pmib->miscEntry.func_off) + goto free_and_stop; + + // drop packets if link status is null +#ifdef WDS + if (!wdsDev) +#endif + { + temp = get_assoc_sta_num(priv, 1); + if (temp == 0) { + priv->ext_stats.tx_drops++; + DEBUG_WARN("TX DROP: Non asoc tx request!\n"); + goto free_and_stop; + } + } + +#ifdef CLIENT_MODE + // nat2.5 translation, mac clone, dhcp broadcast flag add. + if (((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + || (OPMODE & WIFI_ADHOC_STATE)) { +#ifdef RTK_BR_EXT + if (!priv->pmib->ethBrExtInfo.nat25_disable && + !(skb->data[0] & 1) && +#ifdef MULTI_MAC_CLONE + (ACTIVE_ID == 0) && +#endif +#ifdef __KERNEL__ + GET_BR_PORT(priv->dev) && +#endif + memcmp(skb->data+MACADDRLEN, priv->br_mac, MACADDRLEN) && +// *((unsigned short *)(skb->data+MACADDRLEN*2)) != __constant_htons(ETH_P_8021Q) && + *((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_IP) && + !memcmp(priv->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN) && priv->scdb_entry) { + memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR, MACADDRLEN); + priv->scdb_entry->ageing_timer = jiffies; + } + else +#endif + { + if(memcmp(skb->data+ETH_ALEN, GET_MY_HWADDR, ETH_ALEN)) { // ignore tx from root br to vap(client mode) if vap is not connected to remote ap successfully + struct stat_info *pstat = get_stainfo(priv,BSSID); + if (!((NULL != pstat) && (pstat->state & (WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)) + && (((0 != pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen) && (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _NO_PRIVACY_)) + || (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _NO_PRIVACY_)))) { + goto free_and_stop; + } + } + + SMP_UNLOCK_XMIT(flags); + if (rtl8192cd_tx_clientMode(priv, &skb) == TX_PROCEDURE_CTRL_STOP) { + SMP_LOCK_XMIT(flags); + goto stop_proc; + } + SMP_LOCK_XMIT(flags); + } + +#ifdef RTK_BR_EXT //8812_client +#ifdef MULTI_MAC_CLONE + if (ACTIVE_ID >= 0) + mclone_dhcp_caddr(priv, skb); + if (ACTIVE_ID == 0) //not a mac clone sta +#endif + dhcp_flag_bcast(priv, skb); +#endif + + } +#endif // CLIENT_MODE + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + if ((OPMODE & WIFI_AP_STATE) && !wdsDev) { + if ((*(unsigned int *)&(skb->cb[20]) == 0x86518190) && // come from wlan interface + (*(unsigned int *)&(skb->cb[24]) != priv->pmib->miscEntry.groupID)) // check group ID + { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: not the same group!\n"); + goto free_and_stop; + } + } + } +#endif + +#ifdef USE_TXQUEUE + if (GET_ROOT(priv)->pmib->miscEntry.use_txq && priv->pshare->iot_mode_enable) { + int pri = 0, qnum = BE_QUEUE, qlen = 0, qidx = 0; + pri = get_skb_priority(priv, skb, NULL); +#ifdef RTL_MANUAL_EDCA + q_num = PRI_TO_QNUM(priv, pri); +#else + PRI_TO_QNUM(pri, qnum, priv->pmib->dot11OperationEntry.wifi_specific); +#endif + + if (!priv->pshare->txq_isr) + { + if (txq_len(&priv->pshare->txq_list[qnum]) > 0) + { +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) { + if (!check_txq_dynamic_mechanism(priv, qnum)) { + append_skb_to_txq_tail(&priv->pshare->txq_list[qnum], priv, skb, dev, &priv->pshare->txq_pool); + priv->use_txq_cnt[qnum]++; + priv->pshare->txq_check = 1; + goto stop_proc; + } else { + DEBUG_ERR("TX DROP: exceed the tx queue!\n"); + priv->ext_stats.tx_drops++; + goto free_and_stop; + } + } + else +#endif + { + for (qidx=0; qidx<7; qidx++) + qlen += txq_len(&priv->pshare->txq_list[qidx]); + if (qlen < TXQUEUE_SIZE) { + append_skb_to_txq_tail(&priv->pshare->txq_list[qnum], priv, skb, dev, &priv->pshare->txq_pool); + priv->pshare->txq_check = 1; + goto stop_proc; + } else { + DEBUG_ERR("TX DROP: exceed the tx queue!\n"); + priv->ext_stats.tx_drops++; + goto free_and_stop; + } + } + } + } + } +#endif + +#ifdef WDS + if (wdsDev) + da = priv->pmib->dot11WdsInfo.entry[txcfg->wdsIdx].macAddr; + else +#endif + { + +#ifdef MCAST2UI_REFINE + da = &skb->cb[10]; +#else + da = skb->data; +#endif + } + +#ifdef CLIENT_MODE + if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + pstat = get_stainfo(priv, BSSID); + else +#endif + { + pstat = get_stainfo(priv, da); +#ifdef A4_STA + if (pstat == NULL && !IS_MCAST(skb->data) && priv->pshare->rf_ft_var.a4_enable) + pstat = a4_sta_lookup(priv, da); +#endif + +#ifdef SW_TX_QUEUE + if (pstat) + swq_out = priv->swq_en | pstat->swq.beq_empty | pstat->swq.viq_empty | pstat->swq.voq_empty | pstat->swq.bkq_empty; +#endif + } +#ifdef DETECT_STA_EXISTANCE + if(pstat && pstat->leave) { + priv->ext_stats.tx_drops++; + DEBUG_WARN("TX DROP: sta may leave! %02x%02x%02x%02x%02x%02x\n", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + goto free_and_stop; + } +#endif + +#ifdef TX_SCATTER +#ifdef CONFIG_IEEE80211W + if (skb->list_num > 0 && (UseSwCrypto(priv, pstat, (pstat ? FALSE : TRUE), 0) || +#else + if (skb->list_num > 0 && (UseSwCrypto(priv, pstat, (pstat ? FALSE : TRUE)) || +#endif + (pstat && (get_sta_encrypt_algthm(priv, pstat) == _TKIP_PRIVACY_)))) { + newskb = copy_skb(skb); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't copy the skb for list buffer!\n"); + goto free_and_stop; + } + dev_kfree_skb_any(skb); + skb = newskb; + } +#endif + +#ifdef SW_TX_QUEUE + + //if ((pstat == NULL) || (pstat && (!priv->swq_en) && (!(pstat->swq.beq_empty | pstat->swq.viq_empty | pstat->swq.voq_empty | pstat->swq.bkq_empty)))) + if (swq_out == 0 +#ifdef GBWC + || priv->GBWC_consuming_Q +#endif + ) { +#ifdef CONFIG_RTK_MESH + return __rtl8192cd_start_xmit_out(skb, pstat, NULL); +#else + return __rtl8192cd_start_xmit_out(skb, pstat); +#endif + } else if (priv->swq_en) { + return sw_enqueue(priv,skb,pstat); + } else { + //if ((pstat != NULL) && (priv->pshare->rf_ft_var.swq_enable == 1) && (AMPDU_ENABLE != 0)) + //ptimer->data = (unsigned long)pstat; + for(q_num = BK_QUEUE; q_num <= VO_QUEUE; q_num++) + { + switch(q_num) + { + case BK_QUEUE: + pqueue = &pstat->swq.bk_queue; + ptimer = &pstat->swq.bkq_timer; + pempty = &pstat->swq.bkq_empty; + break; + case VO_QUEUE: + pqueue = &pstat->swq.vo_queue; + ptimer = &pstat->swq.voq_timer; + pempty = &pstat->swq.voq_empty; + break; + case VI_QUEUE: + pqueue = &pstat->swq.vi_queue; + ptimer = &pstat->swq.viq_timer; + pempty = &pstat->swq.viq_empty; + break; + //case BE_QUEUE: + default: + pqueue = &pstat->swq.be_queue; + ptimer = &pstat->swq.beq_timer; + pempty = &pstat->swq.beq_empty; + break; + } + + if (*pempty == 0) + continue; + + ptimer->data = (unsigned long)pstat; + sw_dequeue(priv, pqueue, ptimer);//, pempty, pstat); + *pempty = 0; + } + +#if defined(CONFIG_RTK_MESH) + __rtl8192cd_start_xmit_out(skb, pstat, NULL); +#else + __rtl8192cd_start_xmit_out(skb, pstat); +#endif + } + goto stop_proc; +#else +#ifdef CONFIG_RTK_MESH + return __rtl8192cd_start_xmit_out(skb, pstat, NULL); +#else + return __rtl8192cd_start_xmit_out(skb, pstat); +#endif +#endif + +free_and_stop: /* Free current packet and stop TX process */ + + rtl_kfree_skb(priv, skb, _SKB_TX_); + +stop_proc: /* Stop process and assume the TX-ed packet is already "processed" (freed or TXed) in previous code. */ + + return 0; +} + +__MIPS16 +__IRAM_IN_865X +#ifdef CONFIG_RTK_MESH +int __rtl8192cd_start_xmit_out(struct sk_buff *skb, struct stat_info *pstat, struct tx_insn *ptxcfg) //struct net_device *dev) +#else +int __rtl8192cd_start_xmit_out(struct sk_buff *skb, struct stat_info *pstat) //struct net_device *dev) +#endif +{ + struct rtl8192cd_priv *priv; + //struct stat_info *pstat=NULL; + struct net_device *dev = skb->dev; +#ifdef A4_STA + unsigned char *da; +#endif + struct sk_buff *newskb = NULL; + struct net_device *wdsDev = NULL; +#if defined(CONFIG_RTL8672) || defined(TX_SHORTCUT) + int k; +#endif +#if defined(TX_SHORTCUT) + struct tx_sc_entry *ptxsc_entry = NULL; +#endif + struct tx_insn tx_insn; + DECLARE_TXCFG(txcfg, tx_insn); + + priv = GET_DEV_PRIV(dev); + +#if defined(CONFIG_RTK_MESH) + if(dev == priv->mesh_dev) { + if(ptxcfg->is_11s == 1) { + memcpy(txcfg, ptxcfg, sizeof(*ptxcfg)); + priv = txcfg->priv; + } + else { /* if ptxcfg->is_11s is RELAY_11S */ + txcfg->is_11s = RELAY_11S; + memcpy(txcfg->nhop_11s, pstat->hwaddr, MACADDRLEN); + memcpy(&txcfg->mesh_header, skb->data + WLAN_ETHHDR_LEN, sizeof(struct lls_mesh_header)); + priv = ptxcfg->priv; + } + } +#endif + +#ifdef CONFIG_RTL8672 +#ifdef SUPPORT_TX_MCAST2UNI + if (skb->cb[16] == TX_NO_MUL2UNI) + txcfg->isMC2UC = 1; + else + txcfg->isMC2UC = 0; +#endif +#endif + +#ifdef WDS + if (dev->base_addr) { + // normal packets + if (priv->pmib->dot11WdsInfo.wdsPure) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Sent normal pkt in Pure WDS mode!\n"); + goto free_and_stop; + } + } + else { + // WDS process + if (rtl8192cd_tx_wdsDevProc(priv, skb, &dev, &wdsDev, txcfg) == TX_PROCEDURE_CTRL_STOP) { + goto stop_proc; + } + } +#endif // WDS + + { + if (skb_cloned(skb) +#ifdef MCAST2UI_REFINE + && !memcmp(skb->data, &skb->cb[10], 6) +#endif + ) + { + newskb = skb_copy(skb, GFP_ATOMIC); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't copy the skb!\n"); + goto free_and_stop; + } + dev_kfree_skb_any(skb); + skb = newskb; + } + } + +#ifdef SUPPORT_SNMP_MIB + if (IS_MCAST(skb->data)) + SNMP_MIB_INC(dot11MulticastTransmittedFrameCount, 1); +#endif + + if ((OPMODE & WIFI_AP_STATE) +#ifdef WDS + && (!wdsDev) +#endif +#ifdef CONFIG_RTK_MESH + && (dev != priv->mesh_dev) +#endif + ) { +#ifdef MCAST2UI_REFINE + if ((pstat && ((pstat->state & (WIFI_SLEEP_STATE | WIFI_ASOC_STATE)) == + (WIFI_SLEEP_STATE | WIFI_ASOC_STATE))) || + (((IS_MCAST(&skb->cb[10]) && (priv->sleep_list.next != &priv->sleep_list)) || + ((priv->pshare->rf_ft_var.bcast_to_dzq) && ((unsigned char )(skb->cb[10]) == 0xff))) && + (!priv->release_mcast))) +#else + if ((pstat && ((pstat->state & (WIFI_SLEEP_STATE | WIFI_ASOC_STATE)) == + (WIFI_SLEEP_STATE | WIFI_ASOC_STATE))) || + (((IS_MCAST(skb->data) && (priv->sleep_list.next != &priv->sleep_list)) || + (priv->pshare->rf_ft_var.bcast_to_dzq && (*(skb->data) == 0xff))) && + (!priv->release_mcast))) +#endif + { + +#ifdef _11s_TEST_MODE_ + mesh_debug_tx3(dev, priv, skb); +#endif + if (dz_queue(priv, pstat, skb) == TRUE) + { + DEBUG_INFO("queue up skb due to sleep mode\n"); + goto stop_proc; + } + else { + if (pstat) { + DEBUG_WARN("ucst sleep queue full!!\n"); + } + else { + DEBUG_WARN("mcst sleep queue full!!\n"); + } + goto free_and_stop; + } + } + } + +#ifdef GBWC + if (priv->pmib->gbwcEntry.GBWCMode && pstat) { + if (rtl8192cd_tx_gbwc(priv, pstat, skb) == TX_PROCEDURE_CTRL_STOP) { + goto stop_proc; + } + } +#endif + +#ifdef SUPPORT_TX_AMSDU + if (pstat && (pstat->aggre_mthd & AGGRE_MTHD_MSDU) && (pstat->amsdu_level > 0) +#ifdef SUPPORT_TX_MCAST2UNI + && (priv->pshare->rf_ft_var.mc2u_disable || (skb->cb[2] != (char)0xff)) +#endif + ) { + int ret = amsdu_check(priv, skb, pstat, txcfg); + + if (ret == RET_AGGRE_ENQUE) + goto stop_proc; + + if (ret == RET_AGGRE_DESC_FULL) + goto free_and_stop; + } +#endif +#ifdef MESH_AMSDU + if(dev == priv->mesh_dev) + goto just_skip; +#endif + +#ifdef SW_TX_QUEUE + +#ifdef CONFIG_RTK_MESH + if(dev != priv->mesh_dev) /*mesh do not support sw tx queue yet, skip this*/ +#endif + { + + if ((priv->assoc_num > 1) && pstat) + { +#ifdef MCAST2UI_REFINE + if (memcmp(&skb->cb[10], priv->record_mac, 6)) +#else + if (memcmp(skb->data, priv->record_mac, 6)) +#endif + { + priv->swq_txmac_chg++; +#ifdef MCAST2UI_REFINE + memcpy(priv->record_mac, &skb->cb[10], 6); +#else + memcpy(priv->record_mac, skb->data, 6); +#endif + } + else + { + int pri, q_num; + +#ifdef CONFIG_RTK_MESH + pri = get_skb_priority3(priv, skb, txcfg->is_11s, pstat); +#else + pri = get_skb_priority(priv, skb, pstat); +#endif + +#ifdef RTL_MANUAL_EDCA + q_num = PRI_TO_QNUM(priv, pri); +#else + PRI_TO_QNUM(pri, q_num, priv->pmib->dot11OperationEntry.wifi_specific); +#endif + if (priv->record_qnum != q_num) + { + priv->swq_txmac_chg++; + priv->record_qnum = q_num; + } + } + } + +#ifdef SW_TX_QUEUE_SMALL_PACKET_CHECK + // add check for small udp packet(88B) test with veriwave tool + if ((priv->swq_en == 0) && (priv->assoc_num > 1) && (AMPDU_ENABLE)) + { + int thd_value; + + if ((priv->swq_boost_delay > 0) && (priv->swq_boost_delay < 10)) + thd_value = priv->pshare->rf_ft_var.swq_en_highthd / 10; + else + thd_value = priv->pshare->rf_ft_var.swq_en_highthd; + + if (priv->swq_txmac_chg >= thd_value); + { + //printk("%s %d : thd_value %d\n", __FUNCTION__, __LINE__, thd_value); + + if (priv->pshare->txop_enlarge == 0) + priv->pshare->txop_enlarge = 2; + + priv->swq_en = 1; + priv->swqen_keeptime = priv->up_time; + + struct stat_info *pstat_swq; + struct list_head *phead, *plist; + struct stat_info *pstat_highest = NULL; + + phead = &priv->asoc_list; + plist = phead->next; + + while (plist != phead) + { + pstat_swq = list_entry(plist, struct stat_info, asoc_list); + + int i; + for (i = BK_QUEUE; i <= VO_QUEUE; i++) + { + pstat_swq->swq.q_aggnum[i] = priv->pshare->rf_ft_var.swq_aggnum; // MAX_BACKOFF_CNT; + } + + if (plist == plist->next) + break; + + plist = plist->next; + } + } + } +#endif + + } +#endif //SW_TX_QUEUE + +#ifdef TX_SHORTCUT + if (!priv->pmib->dot11OperationEntry.disable_txsc && pstat + && ((k = get_tx_sc_index(priv, pstat, skb->data)) >= 0)) + ptxsc_entry = &pstat->tx_sc_ent[k]; + + if ((NULL != ptxsc_entry) && +#ifdef NOT_RTK_BSP + // go slow path to avoid TX drop when no enough tail room to put TKIP MIC. + ((_TKIP_PRIVACY_ != ptxsc_entry->txcfg.privacy) || ((skb->tail + 8) <= skb->end)) && +#endif + ((ptxsc_entry->txcfg.privacy == 0) || +#ifdef CONFIG_RTL_WAPI_SUPPORT + (ptxsc_entry->txcfg.privacy == _WAPI_SMS4_) || +#endif +#ifdef CONFIG_IEEE80211W + !UseSwCrypto(priv, pstat, FALSE, 0) ) && +#else + !UseSwCrypto(priv, pstat, FALSE) ) && +#endif + (ptxsc_entry->txcfg.fr_len > 0) && +#ifdef CONFIG_RTK_MESH + (get_skb_priority3(priv, skb, txcfg->is_11s, pstat) == ptxsc_entry->pktpri) && +#else + (get_skb_priority(priv, skb, pstat) == ptxsc_entry->pktpri) && +#endif + (FRAGTHRSLD > 1500)) + { + int *tx_head=NULL, *tx_tail=NULL, q_num; + struct rtl8192cd_hw *phw = GET_HW(priv); +#ifdef TX_SCATTER + int reuse_txdesc = 0; +#endif +#ifdef CONFIG_WLAN_HAL + PHCI_TX_DMA_MANAGER_88XX ptx_dma; +#endif + + q_num = ptxsc_entry->txcfg.q_num; +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif // CONFIG_WLAN_HAL + {//not HAL + tx_head = get_txhead_addr(phw, q_num); + tx_tail = get_txtail_addr(phw, q_num); + } + // check if we need active tx tasklet +//#ifdef __KERNEL__ + + if( +#ifdef CONFIG_WLAN_HAL + IS_HAL_CHIP(priv) ? (compareAvailableTXBD(priv, (CURRENT_NUM_TX_DESC/2), q_num, 2)) : +#endif // CONFIG_WLAN_HAL + (CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC) < CURRENT_NUM_TX_DESC/2) + + ) + { + if (!priv->pshare->has_triggered_tx_tasklet) { +#ifdef __KERNEL__ + tasklet_schedule(&priv->pshare->tx_tasklet); +#endif + priv->pshare->has_triggered_tx_tasklet = 1; + } + } +//#endif + // Check if we need to reclaim TX-ring before processing TX + + if( +#ifdef CONFIG_WLAN_HAL + IS_HAL_CHIP(priv) ? (compareAvailableTXBD(priv, 32, q_num, 2)) : +#endif // CONFIG_WLAN_HAL + (CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC) < 10) + + ) + { + rtl8192cd_tx_queueDsr(priv, q_num); + } + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if ( GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc ) { + if( check_txdesc_dynamic_mechanism(priv, q_num, 2) ) { +#ifdef USE_TXQUEUE + if (GET_ROOT(priv)->pmib->miscEntry.use_txq && priv->pshare->iot_mode_enable) { + if (priv->pshare->txq_isr) { + append_skb_to_txq_head(&priv->pshare->txq_list[q_num], priv, skb, dev, &priv->pshare->txq_pool); + priv->pshare->txq_stop = 1; + } else { + append_skb_to_txq_tail(&priv->pshare->txq_list[q_num], priv, skb, dev, &priv->pshare->txq_pool); + } + priv->use_txq_cnt[q_num]++; + priv->pshare->txq_check = 1; + } + else +#endif + { + DEBUG_WARN("%d hw Queue desc exceed available count: used:%d\n", q_num, priv->use_txdesc_cnt[q_num]); + rtl8192cd_tx_xmitSkbFail(priv, skb, dev, wdsDev, txcfg); + } + goto stop_proc; + } + } else +#endif + { +#ifdef TX_EARLY_MODE + if( +#ifdef CONFIG_WLAN_HAL + IS_HAL_CHIP(priv) ? + ( compareAvailableTXBD(priv, ((GET_TX_EARLY_MODE && GET_EM_SWQ_ENABLE) ? 14 : 4), q_num, 2)) : +#endif // CONFIG_WLAN_HAL + (((GET_TX_EARLY_MODE && GET_EM_SWQ_ENABLE) ? 14 : 4) > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC)) + + ) +#else + if( +#ifdef CONFIG_WLAN_HAL + IS_HAL_CHIP(priv) ? (compareAvailableTXBD(priv, 4, q_num, 2)) : +#endif // CONFIG_WLAN_HAL +#ifdef TX_SCATTER + ((ptxsc_entry->has_desc3 && 6 > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC)) || + (!ptxsc_entry->has_desc3 && 4 > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC))) +#else + ((4) > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC)) //per mpdu, we need 2 desc... +#endif + ) +#endif + { + // 2 is for spare... +#ifdef USE_TXQUEUE + if (GET_ROOT(priv)->pmib->miscEntry.use_txq && priv->pshare->iot_mode_enable) { + if (priv->pshare->txq_isr) { + append_skb_to_txq_head(&priv->pshare->txq_list[q_num], priv, skb, dev, &priv->pshare->txq_pool); + priv->pshare->txq_stop = 1; + } else { + append_skb_to_txq_tail(&priv->pshare->txq_list[q_num], priv, skb, dev, &priv->pshare->txq_pool); + } + priv->pshare->txq_check = 1; + } + else +#endif + { +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) { + DEBUG_ERR("%s:%d: tx drop: %d hw Queue desc not available! head=%d, tail=%d request %d\n", __FUNCTION__, __LINE__, + q_num, ptx_dma->tx_queue[q_num].host_idx, ptx_dma->tx_queue[q_num].hw_idx,2); + } + else +#endif + DEBUG_ERR("%d hw Queue desc not available! head=%d, tail=%d request %d\n",q_num,*tx_head,*tx_tail,2); + + + rtl8192cd_tx_xmitSkbFail(priv, skb, dev, wdsDev, txcfg); + } + goto stop_proc; + } + } + +#if defined(MESH_TX_SHORTCUT) + if(txcfg->is_11s) { + if(!mesh_txsc_decision(txcfg, &ptxsc_entry->txcfg)) { /*compare addr 5 and 6*/ + goto just_skip; + } + + if(memcmp(skb->data, GetAddr3Ptr(&ptxsc_entry->wlanhdr), MACADDRLEN)) {/*compare addr 3*/ + goto just_skip; + } + + ptxsc_entry->txcfg.mesh_header.segNum = txcfg->mesh_header.segNum; + ptxsc_entry->txcfg.mesh_header.TTL = txcfg->mesh_header.TTL; + ptxsc_entry->txcfg.is_11s = txcfg->is_11s; + } +#endif + + memcpy(txcfg, &ptxsc_entry->txcfg, sizeof(struct tx_insn)); + +#ifdef CONFIG_RTL8672 +#ifdef SUPPORT_TX_MCAST2UNI + if (skb->cb[16] == TX_NO_MUL2UNI) + txcfg->isMC2UC = 1; + else + txcfg->isMC2UC = 0; +#endif +#endif + +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + if (GET_CHIP_VER(priv)==VERSION_8814A) { + txcfg->phdr = skb->data; // 802.3 hdr + //txcfg->hdr_len = WLAN_ETHHDR_LEN; + txcfg->pframe = skb; // skb->data: 802.3 hdr + payload + txcfg->fr_len = skb->len; // len(802.3 hdr + payload) + // TODO: currently , we don't care encryption.... it's only support AES in HW + } else +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + + { + txcfg->phdr = (UINT8 *)get_wlanllchdr_from_poll(priv); + if (txcfg->phdr == NULL) { + DEBUG_ERR("Can't alloc wlan header!\n"); + rtl8192cd_tx_xmitSkbFail(priv, skb, dev, wdsDev, txcfg); + goto stop_proc; + } + memcpy(txcfg->phdr, (const void *)&ptxsc_entry->wlanhdr, sizeof(struct wlanllc_hdr)); + txcfg->pframe = skb; +#ifdef WDS + /*Correct the aggre_mthd*/ + if(pstat->state & WIFI_WDS) + if(txcfg->aggre_en != pstat->aggre_mthd) { + /*Invalid the tx_sc entry*/ + ptxsc_entry->txcfg.fr_len=0; + txcfg->aggre_en = pstat->aggre_mthd; + } +#endif + +#ifdef TX_SCATTER + if (skb->list_num > 0) + txcfg->fr_len = skb->total_len - WLAN_ETHHDR_LEN; + else +#endif + txcfg->fr_len = skb->len - WLAN_ETHHDR_LEN; + skb_pull(skb, WLAN_ETHHDR_LEN); + } + +#ifdef CONFIG_RTL_WAPI_SUPPORT +#ifdef CONFIG_RTL_HW_WAPI_SUPPORT +#ifdef CONFIG_IEEE80211W + if((txcfg->privacy==_WAPI_SMS4_)&&(txcfg->llc>0)&&(UseSwCrypto(priv, pstat, FALSE, 0))) +#else + if((txcfg->privacy==_WAPI_SMS4_)&&(txcfg->llc>0)&&(UseSwCrypto(priv, pstat, FALSE))) +#endif +#else + if((txcfg->privacy==_WAPI_SMS4_)&&(txcfg->llc>0)) +#endif + { + //To restore not-encrypted llc in wlan hdr + //because llc in wlan hdr has been sms4encrypted to deliver at SecSWSMS4Encryption() + eth_2_llc(&ptxsc_entry->ethhdr, (struct llc_snap *)(txcfg->phdr+txcfg->hdr_len + txcfg->iv)); + } +#endif + + if (txcfg->privacy == _TKIP_PRIVACY_) { + if (rtl8192cd_tx_tkip(priv, skb, pstat, txcfg) == TX_PROCEDURE_CTRL_STOP) { + goto stop_proc; + } + } + +#ifdef MESH_TX_SHORTCUT + if ( (txcfg->is_11s&1) && (GetFrameSubType(txcfg->phdr) == WIFI_11S_MESH)) + if( !reuse_meshhdr(priv, txcfg) ) { + goto stop_proc; + } +#endif + + txcfg->tx_rate = get_tx_rate(priv, pstat); + txcfg->lowest_tx_rate = get_lowest_tx_rate(priv, pstat, txcfg->tx_rate); + // log tx statistics... + +#ifdef CONFIG_RTL8672 + tx_sum_up(priv, pstat, txcfg->fr_len+txcfg->hdr_len+txcfg->iv+txcfg->llc+txcfg->mic+txcfg->icv, txcfg); +#else + tx_sum_up(priv, pstat, txcfg->fr_len+txcfg->hdr_len+txcfg->iv+txcfg->llc+txcfg->mic+txcfg->icv); +#endif + SNMP_MIB_INC(dot11TransmittedFragmentCount, 1); + +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, (POWER_DOWN_T0)); +#endif + + // for SW LED + priv->pshare->LED_tx_cnt++; + + if ( +#ifdef RTK_AC_SUPPORT //for 11ac logo //FOR_VHT5G_PF + ( ((pstat->aggre_mthd == AGGRE_MTHD_MPDU_AMSDU) || (pstat->aggre_mthd == AGGRE_MTHD_MPDU)) + && txcfg->aggre_en ) || +#endif + ((txcfg->aggre_en >= FG_AGGRE_MPDU) && (txcfg->aggre_en <= FG_AGGRE_MPDU_BUFFER_LAST)) + ) { + if (!pstat->ADDBA_ready[(int)skb->cb[1]]) { + if ((pstat->ADDBA_req_num[(int)skb->cb[1]] < 5) && !pstat->ADDBA_sent[(int)skb->cb[1]]) { + pstat->ADDBA_req_num[(int)skb->cb[1]]++; + SMP_UNLOCK_XMIT(flags); + issue_ADDBAreq(priv, pstat, (int)skb->cb[1]); + SMP_LOCK_XMIT(flags); + pstat->ADDBA_sent[(int)skb->cb[1]]++; + } + } + } + +#ifdef TX_SCATTER + if (skb->list_num == 0) { + reuse_txdesc = 1; + } else { + if (ptxsc_entry->has_desc3) { + if (skb->list_num == 3 && (skb->list_buf[0].len == WLAN_ETHHDR_LEN) && + (skb->list_buf[2].len == (get_desc(ptxsc_entry->hwdesc3.Dword7)&TX_TxBufSizeMask))){ + reuse_txdesc = 1; + } + } else { + if ((skb->list_num == 1 && skb->list_buf[0].len > WLAN_ETHHDR_LEN) || + (skb->list_num == 2 && skb->list_buf[0].len == WLAN_ETHHDR_LEN)) + reuse_txdesc = 1; + } + if (skb->len == 0 && skb->list_num > 1) { + skb->list_idx++; + skb_assign_buf(skb, skb->list_buf[skb->list_idx].buf, skb->list_buf[skb->list_idx].len); + skb->len = skb->list_buf[skb->list_idx].len; + } + } +#endif + + // check if we could re-use tx descriptor + if ( +#ifdef WLAN_HAL_HW_TX_SHORTCUT_DISABLE_REUSE_TXDESC_FOR_DEBUG + // TODO: tempory False for disable reuse txdesc, only hdr conversion + FALSE && +#endif + ( +#ifdef CONFIG_WLAN_HAL + IS_HAL_CHIP(priv) ? +#ifdef WLAN_HAL_HW_TX_SHORTCUT_REUSE_TXDESC + ((GET_CHIP_VER(priv)==VERSION_8814A) ? + TRUE : + ((GET_HAL_INTERFACE(priv)->GetShortCutTxBuffSizeHandler(priv, ptxsc_entry->hal_hw_desc)) > 0) ) +#else + ((GET_HAL_INTERFACE(priv)->GetShortCutTxBuffSizeHandler(priv, ptxsc_entry->hal_hw_desc)) > 0) +#endif + : +#endif // CONFIG_WLAN_HAL + ((get_desc(ptxsc_entry->hwdesc1.Dword7)&TX_TxBufSizeMask) > 0) + + ) + && ( +#ifdef CONFIG_RTL_WAPI_SUPPORT + // Note: for sw wapi, txcfg->mic=16; for hw wapi, txcfg->mic=0. + (txcfg->privacy==_WAPI_SMS4_) ? ((skb->len+txcfg->mic)==(get_desc(ptxsc_entry->hwdesc2.Dword7)&TX_TxBufSizeMask)) : +#endif + ( +#ifdef CONFIG_WLAN_HAL + IS_HAL_CHIP(priv) ? +#ifdef WLAN_HAL_HW_TX_SHORTCUT_REUSE_TXDESC + ((GET_CHIP_VER(priv)==VERSION_8814A) ? + TRUE: + (skb->len == (GET_HAL_INTERFACE(priv)->GetShortCutTxBuffSizeHandler(priv, ptxsc_entry->hal_hw_desc))) ) +#else + (skb->len == (GET_HAL_INTERFACE(priv)->GetShortCutTxBuffSizeHandler(priv, ptxsc_entry->hal_hw_desc))) +#endif + : +#endif // CONFIG_WLAN_HAL + (skb->len == (get_desc(ptxsc_entry->hwdesc2.Dword7)&TX_TxBufSizeMask)) + ) + ) && + (txcfg->tx_rate == ptxsc_entry->txcfg.tx_rate) && + (pstat->protection == priv->pmib->dot11ErpInfo.protection) && + (pstat->ht_protection == priv->ht_protection) +#if defined(WIFI_WMM) && defined(WMM_APSD) + && (!( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (APSD_ENABLE) && (pstat->state & WIFI_SLEEP_STATE))) +#endif +#ifdef TX_SCATTER + && reuse_txdesc +#endif + ) { + + pstat->tx_sc_pkts_lv2++; + + if (txcfg->privacy) { + switch (txcfg->privacy) { + case _WEP_104_PRIVACY_: + case _WEP_40_PRIVACY_: + wep_fill_iv(priv, txcfg->phdr, txcfg->hdr_len, ptxsc_entry->sc_keyid); + break; + + case _TKIP_PRIVACY_: + tkip_fill_encheader(priv, txcfg->phdr, txcfg->hdr_len, ptxsc_entry->sc_keyid); + break; + + case _CCMP_PRIVACY_: + aes_fill_encheader(priv, txcfg->phdr, txcfg->hdr_len, ptxsc_entry->sc_keyid); + break; + } + } + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + // for TXBD mechanism, sending a packet always need one txdesc. So, txcfg->one_txdesc is useless. + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif // CONFIG_WLAN_HAL + {//not HAL + if ((skb_headroom(skb) >= (txcfg->hdr_len + txcfg->llc + txcfg->iv +#ifdef TX_EARLY_MODE + + (GET_TX_EARLY_MODE ? 8 : 0) +#endif + )) && + !skb_cloned(skb) && + (txcfg->privacy != _TKIP_PRIVACY_) && +#if defined(CONFIG_RTL_WAPI_SUPPORT) + (txcfg->privacy != _WAPI_SMS4_) && +#endif + ((((unsigned int)skb->data) % 2) == 0) + ) + { + memcpy((skb->data - (txcfg->hdr_len + txcfg->llc + txcfg->iv)), txcfg->phdr, (txcfg->hdr_len + txcfg->llc + txcfg->iv)); + release_wlanllchdr_to_poll(priv, txcfg->phdr); + txcfg->phdr = skb->data - (txcfg->hdr_len + txcfg->llc + txcfg->iv); + txcfg->one_txdesc = 1; + } + } + + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) { + int ret=0; + priv->use_txdesc_cnt[q_num] += (txcfg->one_txdesc)? 1 : 2; + + +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + ret = rtl88XX_signin_txdesc_shortcut(priv, txcfg, k); + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif // CONFIG_WLAN_HAL + ret = rtl8192cd_signin_txdesc_shortcut(priv, txcfg, k); + + if(ret) + priv->use_txdesc_cnt[q_num] -= (txcfg->one_txdesc)? 1 : 2; + } else +#endif + { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + rtl88XX_signin_txdesc_shortcut(priv, txcfg, k); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif // CONFIG_WLAN_HAL + {//not HAL + rtl8192cd_signin_txdesc_shortcut(priv, txcfg, k); + } + } +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.tx_cnt_sc2++; +#endif + goto stop_proc; + } + + pstat->tx_sc_pkts_lv1++; +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s) { + memcpy(&priv->ethhdr, &(ptxsc_entry->ethhdr), sizeof(struct wlan_ethhdr_t)); + } +#endif + + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) { + int desc_num=2; + if ( txcfg->privacy +#if defined(CONFIG_RTL_WAPI_SUPPORT) + && (_WAPI_SMS4_ != txcfg->privacy) +#endif +#ifdef CONFIG_IEEE80211W + && UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE),0) ){ +#else + && UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE)) ){ +#endif + desc_num=3; + } + priv->use_txdesc_cnt[q_num] += desc_num; + if ( rtl8192cd_signin_txdesc(priv, txcfg)) { + priv->use_txdesc_cnt[q_num] -= desc_num; + } + } else +#endif + { +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + rtl88XX_signin_txdesc(priv, txcfg, HW_TX_SC_HEADER_CONV); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + rtl8192cd_signin_txdesc(priv, txcfg); + } + } +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.tx_cnt_sc1++; +#endif + ptxsc_entry->txcfg.tx_rate = txcfg->tx_rate; + goto stop_proc; + } + if (!priv->pmib->dot11OperationEntry.disable_txsc && pstat) + pstat->tx_sc_pkts_slow++; +#endif // TX_SHORTCUT +#ifdef CONFIG_RTK_MESH +just_skip: +#endif + +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.tx_cnt_nosc++; +#endif + + /* ==================== Slow path of packet TX process ==================== */ + SMP_UNLOCK_XMIT(flags); + if (rtl8192cd_tx_slowPath(priv, skb, pstat, dev, wdsDev, txcfg) == TX_PROCEDURE_CTRL_STOP) { + SMP_LOCK_XMIT(flags); + goto stop_proc; + } + SMP_LOCK_XMIT(flags); + +#ifdef __KERNEL__ + dev->trans_start = jiffies; +#endif + +#ifdef A4_STA + if ((OPMODE & WIFI_AP_STATE) && IS_MCAST(da) && + priv->pshare->rf_ft_var.a4_enable && !list_empty(&priv->a4_sta_list)) { + struct list_head *phead, *plist; + + skb_push(skb, WLAN_ETHHDR_LEN); + + phead = &priv->a4_sta_list; + plist = phead->next; + + while (plist != phead) { + struct stat_info *dst_stat; + + pstat = list_entry(plist, struct stat_info, a4_sta_list); + ASSERT(pstat->state & WIFI_A4_STA); + + dst_stat = a4_sta_lookup(priv, skb->data+MACADDRLEN); + if (pstat != dst_stat) + send_br_packet(priv, skb, pstat); + + plist = plist->next; + } + } +#endif + + goto stop_proc; + +free_and_stop: /* Free current packet and stop TX process */ + + rtl_kfree_skb(priv, skb, _SKB_TX_); + +stop_proc: /* Stop process and assume the TX-ed packet is already "processed" (freed or TXed) in previous code. */ + + return 0; +} +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +int __rtl8192cd_start_xmit(struct sk_buff *skb, struct net_device *dev, int tx_flag) +{ + struct rtl8192cd_priv *priv; + struct stat_info *pstat=NULL; + unsigned char *da; +#if defined(HS2_SUPPORT) || !defined(CONFIG_PCI_HCI) + struct sk_buff *newskb = NULL; +#endif +#ifdef TX_SCATTER + struct sk_buff *newskb = NULL; +#endif + struct net_device *wdsDev = NULL; + struct tx_insn tx_insn; + int temp; +#ifdef SMP_SYNC + unsigned long flags; +#endif + + + DECLARE_TXCFG(txcfg, tx_insn); + + priv = GET_DEV_PRIV(dev); + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + + if (skb->len < 15) + { + _DEBUG_ERR("TX DROP: SKB len small:%d\n", skb->len); + goto free_and_stop; + } + + skb->dev = dev; + +#ifdef WDS + if (!dev->base_addr && skb_cloned(skb) + && (priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_) + ) { + struct sk_buff *mcast_skb = NULL; + mcast_skb = skb_copy(skb, GFP_ATOMIC); + if (mcast_skb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't copy the skb!\n"); + goto free_and_stop; + } + dev_kfree_skb_any(skb); + skb = mcast_skb; + } +#endif + +#ifdef HS2_SUPPORT + if (priv->proxy_arp) { + + unsigned short protocol; + + if(isDHCPpkt(skb)) { + staip_snooping_bydhcp(skb, priv); + } + + if (IS_MCAST(skb->data)) { + protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); + + //proxy arp + if (protocol == __constant_htons(ETH_P_ARP)) { + if (proxy_arp_handle(priv, skb)) { + //reply ok and return + goto stop_proc; + } + //drop packets + goto free_and_stop; + } + //icmpv6 + if (ICMPV6_MCAST_SOLI_MAC(skb->data)) { + //if (ICMPV6_MCAST_MAC(skb->data)) + if (proxy_icmpv6_ndisc(priv,skb)) { + goto stop_proc; + } + //drop packets + goto free_and_stop; + } + //drop unsolicited neighbor advertisement when proxy arp=1 + if (ICMPV6_MCAST_MAC(skb->data)) { + if (check_nei_advt(priv,skb)) { + //drop packets + goto free_and_stop; + } + } + } + } + + if(priv->dgaf_disable) + { + //dhcp m2u check + if (IS_MCAST(skb->data)) + { + if (isDHCPpkt(skb)) + { + struct list_head *phead, *plist; + + phead = &priv->asoc_list; + plist = phead->next; + while (phead && (plist != phead)) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + /* avoid come from STA1 and send back STA1 */ + if (!memcmp(pstat->hwaddr, &skb->data[6], 6)) + { + continue; + } +#if defined(CONFIG_RTL865X_ETH_PRIV_SKB) || defined(CONFIG_RTL_ETH_PRIV_SKB) + newskb = priv_skb_copy(skb); +#else + newskb = skb_copy(skb, GFP_ATOMIC); +#endif + if (newskb) + { + memcpy(newskb->data, pstat->hwaddr, 6); + newskb->cb[2] = (char)0xff; // not do aggregation + printk("send m2u\n"); + __rtl8192cd_start_xmit(newskb, priv->dev, TX_NO_MUL2UNI); + } + } + } + goto free_and_stop; + } + } +#endif + +#ifdef SUPPORT_TX_MCAST2UNI +#ifdef WDS // when interface is WDS don't enter multi2uni path + if (dev->base_addr && !priv->pmib->dot11WdsInfo.wdsPure) +#endif + if (!priv->pshare->rf_ft_var.mc2u_disable) { + if ((OPMODE & WIFI_AP_STATE) && IS_MCAST(skb->data)) + { + if ((IP_MCAST_MAC(skb->data) + #ifdef TX_SUPPORT_IPV6_MCAST2UNI + || IPV6_MCAST_MAC(skb->data) + #endif + ) && (tx_flag != TX_NO_MUL2UNI)) + { + if (mlcst2unicst(priv, skb)){ + return 0; + } + } + } + + skb->cb[2] = 0; // allow aggregation + } +#endif + +#ifdef SUPPORT_TX_MCAST2UNI + skb->cb[16] = tx_flag; +#endif + +#ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS && + GET_ROOT(priv)->pmib->dot11DFSEntry.disable_tx + && (priv->site_survey) + && (priv->site_survey->hidden_ap_found != HIDE_AP_FOUND_DO_ACTIVE_SSAN)) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: DFS probation period\n"); + goto free_and_stop; + } +#endif + + if (!IS_DRV_OPEN(priv)) + goto free_and_stop; + +#ifdef MP_TEST + if (OPMODE & WIFI_MP_STATE) { + goto free_and_stop; + } +#endif + +#ifdef MULTI_MAC_CLONE + if (priv->pmib->ethBrExtInfo.macclone_enable) { + int id; + if (!(skb->data[ETH_ALEN] & 1) && MCLONE_NUM > 0) { + id = mclone_find_address(priv, skb->data+ETH_ALEN, skb, MAC_CLONE_SA_FIND); + if (id > 0) + ACTIVE_ID = id; + else + ACTIVE_ID = 0; + } else + ACTIVE_ID = 0; + } +#endif + + // strip VLAN tag to avoid packet drop on peer which not support VLAN tag + if (*((u16*)(skb->data+(ETH_ALEN<<1))) == __constant_htons(ETH_P_8021Q)) { + if (skb_cloned(skb)) { + newskb = skb_copy(skb, GFP_ATOMIC); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't copy the skb!\n"); + goto free_and_stop; + } + dev_kfree_skb_any(skb); + skb = newskb; + } + memmove(skb->data + 4, skb->data, ETH_ALEN<<1); + skb_pull(skb, 4); + } + +#ifdef WDS + if (dev->base_addr) { + // normal packets + if (priv->pmib->dot11WdsInfo.wdsPure) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Sent normal pkt in Pure WDS mode!\n"); + goto free_and_stop; + } + } + else { + // WDS process + if (rtl8192cd_tx_wdsDevProc(priv, skb, &dev, &wdsDev, txcfg) == TX_PROCEDURE_CTRL_STOP) { + goto stop_proc; + } + } +#endif // WDS + + if (priv->pmib->miscEntry.func_off) + goto free_and_stop; + + // drop packets if link status is null +#ifdef WDS + if (!wdsDev) +#endif + { + temp = get_assoc_sta_num(priv, 1); + if (temp == 0) { + priv->ext_stats.tx_drops++; + DEBUG_WARN("TX DROP: Non asoc tx request!\n"); + goto free_and_stop; + } + } + +#ifdef CLIENT_MODE + // nat2.5 translation, mac clone, dhcp broadcast flag add. + if (((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + || (OPMODE & WIFI_ADHOC_STATE)) { +#ifdef RTK_BR_EXT + if (!priv->pmib->ethBrExtInfo.nat25_disable && + !(skb->data[0] & 1) && +#ifdef MULTI_MAC_CLONE + (ACTIVE_ID == 0) && +#endif +#ifdef __KERNEL__ + GET_BR_PORT(priv->dev) && +#endif + memcmp(skb->data+MACADDRLEN, priv->br_mac, MACADDRLEN) && +// *((unsigned short *)(skb->data+MACADDRLEN*2)) != __constant_htons(ETH_P_8021Q) && + *((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_IP) && + !memcmp(priv->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN) && priv->scdb_entry) { + memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR, MACADDRLEN); + priv->scdb_entry->ageing_timer = jiffies; + } + else +#endif + { + if(memcmp(skb->data+ETH_ALEN, GET_MY_HWADDR, ETH_ALEN)) { // ignore tx from root br to vap(client mode) if vap is not connected to remote ap successfully + struct stat_info *pstat = get_stainfo(priv,BSSID); + if (!((NULL != pstat) && (pstat->state & (WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)) + && (((0 != pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen) && (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _NO_PRIVACY_)) + || (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _NO_PRIVACY_)))) { + goto free_and_stop; + } + } + + SMP_UNLOCK_XMIT(flags); + if (rtl8192cd_tx_clientMode(priv, &skb) == TX_PROCEDURE_CTRL_STOP) { + SMP_LOCK_XMIT(flags); + goto stop_proc; + } + SMP_LOCK_XMIT(flags); + } + +#ifdef RTK_BR_EXT //8812_client +#ifdef MULTI_MAC_CLONE + if (ACTIVE_ID >= 0) + mclone_dhcp_caddr(priv, skb); + if (ACTIVE_ID == 0) //not a mac clone sta +#endif + dhcp_flag_bcast(priv, skb); +#endif + + } +#endif // CLIENT_MODE + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + if ((OPMODE & WIFI_AP_STATE) && !wdsDev) { + if ((*(unsigned int *)&(skb->cb[20]) == 0x86518190) && // come from wlan interface + (*(unsigned int *)&(skb->cb[24]) != priv->pmib->miscEntry.groupID)) // check group ID + { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: not the same group!\n"); + goto free_and_stop; + } + } + } +#endif + +#ifdef WDS + if (wdsDev) + da = priv->pmib->dot11WdsInfo.entry[txcfg->wdsIdx].macAddr; + else +#endif + { + +#ifdef MCAST2UI_REFINE + da = &skb->cb[10]; +#else + da = skb->data; +#endif + } + +#ifdef CLIENT_MODE + if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + pstat = get_stainfo(priv, BSSID); + else +#endif + { + pstat = get_stainfo(priv, da); +#ifdef A4_STA + if (pstat == NULL && !IS_MCAST(skb->data) && priv->pshare->rf_ft_var.a4_enable) + pstat = a4_sta_lookup(priv, da); +#endif + } +#ifdef DETECT_STA_EXISTANCE + if(pstat && pstat->leave) { + priv->ext_stats.tx_drops++; + DEBUG_WARN("TX DROP: sta may leave! %02x%02x%02x%02x%02x%02x\n", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + goto free_and_stop; + } +#endif + +#ifdef WIFI_SIMPLE_CONFIG + if (pstat && (*((u16*)(skb->data+ETH_ALEN*2)) == __constant_htons(0x888e)) + && (skb->data[15] == 0) && (skb->data[18] == 4)) { // EAP-Failure + wsc_disconn_list_add(priv, da); + } +#endif + +#ifdef TX_SCATTER +#ifdef CONFIG_IEEE80211W + if (skb->list_num > 0 && (UseSwCrypto(priv, pstat, (pstat ? FALSE : TRUE), 0) || +#else + if (skb->list_num > 0 && (UseSwCrypto(priv, pstat, (pstat ? FALSE : TRUE)) || +#endif + (pstat && (get_sta_encrypt_algthm(priv, pstat) == _TKIP_PRIVACY_)))) { + newskb = copy_skb(skb); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't copy the skb for list buffer!\n"); + goto free_and_stop; + } + dev_kfree_skb_any(skb); + skb = newskb; + } +#endif + + txcfg->fr_type = _SKB_FRAME_TYPE_; + txcfg->pframe = skb; + txcfg->pstat = pstat; + + if (update_txinsn_stage1(priv, txcfg) == FALSE) { + priv->ext_stats.tx_drops++; + goto free_and_stop; + } + +#if !defined(SUPPORT_TX_AMSDU) + if ((txcfg->privacy) && ( +#ifdef CONFIG_IEEE80211W + UseSwCrypto(priv, pstat, (pstat ? FALSE : TRUE), 0) // sw enc will modify content +#else + UseSwCrypto(priv, pstat, (pstat ? FALSE : TRUE)) // sw enc will modify content +#endif + || (pstat && (_TKIP_PRIVACY_ == txcfg->privacy)))) // need append MIC +#endif + { + if (skb_cloned(skb) +#ifdef MCAST2UI_REFINE + && !memcmp(skb->data, &skb->cb[10], 6) +#endif + ) + { + newskb = skb_copy(skb, GFP_ATOMIC); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Can't copy the skb!\n"); + goto free_and_stop; + } + dev_kfree_skb_any(skb); + skb = newskb; + } + } + + txcfg->pframe = skb; + txcfg->next_txpath = TXPATH_HARD_START_XMIT; + +#ifdef CONFIG_TCP_ACK_TXAGG + if (priv->pshare->rf_ft_var.tcpack_agg && pstat && (pstat->state & WIFI_ASOC_STATE)) { + if (*(u16 *)(skb->data + ETH_ALEN*2) == htons(ETH_P_IP)) { + struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); + if (6 == iph->protocol) { // IPPROTO_TCP + struct tcphdr *tcph = (struct tcphdr *)((u8*)iph + iph->ihl*4); + // only handle TCP ACK w/o TCP data packet + if (iph->ihl*4+tcph->doff*4 == ntohs(iph->tot_len)) { + int tcp_flag = tcp_flag_word(tcph) & __cpu_to_be32(0xff0000); + if (TCP_FLAG_ACK == tcp_flag) { + if (rtw_xmit_enqueue_tcpack(priv, txcfg) == FALSE) { + goto free_and_stop; + } + goto stop_proc; + } + } + } + } + } +#endif // CONFIG_TCP_ACK_TXAGG + + if (rtw_xmit_enqueue(priv, txcfg) == FALSE) { + goto free_and_stop; + } + goto stop_proc; + +free_and_stop: /* Free current packet and stop TX process */ + + rtl_kfree_skb(priv, skb, _SKB_TX_); + +stop_proc: /* Stop process and assume the TX-ed packet is already "processed" (freed or TXed) in previous code. */ + + return 0; +} + +int __rtl8192cd_usb_start_xmit(struct rtl8192cd_priv *priv, struct tx_insn* txcfg) +{ + struct net_device *dev; + struct net_device *wdsDev = NULL; + struct stat_info *pstat; + struct sk_buff *skb; +#ifdef TX_SHORTCUT + int k; + struct tx_sc_entry *ptxsc_entry = NULL; + unsigned char pktpri; +#endif +// int priority; +#if defined(CONFIG_SDIO_HCI) && defined(TX_SCATTER) + struct wlan_ethhdr_t *pethhdr=NULL; +#endif + + skb = (struct sk_buff *)txcfg->pframe; + + if (!IS_DRV_OPEN(priv)) + goto free_and_stop; + + if (priv->pmib->miscEntry.func_off) + goto free_and_stop; + + switch( rtw_xmit_decision(priv, txcfg) ) { + case XMIT_DECISION_ENQUEUE: + goto stop_proc; + case XMIT_DECISION_STOP: + priv->ext_stats.tx_drops++; + goto free_and_stop; + case XMIT_DECISION_CONTINUE: + break; + } + +#ifdef WDS + if (txcfg->wdsIdx >= 0) { + wdsDev = priv->wds_dev[txcfg->wdsIdx]; + } +#endif + + dev = priv->dev; + pstat = txcfg->pstat; + +#ifdef GBWC + if (priv->pmib->gbwcEntry.GBWCMode && pstat) { + if (rtl8192cd_tx_gbwc(priv, pstat, skb) == TX_PROCEDURE_CTRL_STOP) { + goto stop_proc; + } + } +#endif + +#ifdef SUPPORT_TX_AMSDU + if (pstat && (pstat->aggre_mthd & AGGRE_MTHD_MSDU) && (pstat->amsdu_level > 0) +#ifdef SUPPORT_TX_MCAST2UNI + && (priv->pshare->rf_ft_var.mc2u_disable || (skb->cb[2] != (char)0xff)) +#endif + ) { + int ret = amsdu_check(priv, skb, pstat, txcfg); + + if (ret == RET_AGGRE_ENQUE) + goto stop_proc; + + if (ret == RET_AGGRE_DESC_FULL) + goto free_and_stop; + } +#endif +#ifdef MESH_AMSDU + if(dev == priv->mesh_dev) + goto just_skip; +#endif + + +#ifdef TX_SHORTCUT + if (!priv->pmib->dot11OperationEntry.disable_txsc && pstat) { + pktpri = get_skb_priority(priv, skb, pstat); + if ((k = get_tx_sc_index(priv, pstat, skb->data, pktpri)) >= 0) + ptxsc_entry = &pstat->tx_sc_ent[pktpri][k]; + } + + if ((NULL != ptxsc_entry) && +#ifdef NOT_RTK_BSP + // go slow path to avoid TX drop when no enough tail room to put TKIP MIC. + ((_TKIP_PRIVACY_ != ptxsc_entry->txcfg.privacy) || ((skb->tail + 8) <= skb->end)) && +#endif + ((ptxsc_entry->txcfg.privacy == 0) || +#ifdef CONFIG_RTL_WAPI_SUPPORT + (ptxsc_entry->txcfg.privacy == _WAPI_SMS4_) || +#endif +#ifdef CONFIG_IEEE80211W + !UseSwCrypto(priv, pstat, FALSE, 0) ) && +#else + !UseSwCrypto(priv, pstat, FALSE) ) && +#endif + (ptxsc_entry->txcfg.fr_len > 0) && + (FRAGTHRSLD > 1500)) + { +#if defined(MESH_TX_SHORTCUT) + if(txcfg->is_11s) { + if(!mesh_txsc_decision(txcfg, &ptxsc_entry->txcfg)) { /*compare addr 5 and 6*/ + goto just_skip; + } + + if(memcmp(skb->data, GetAddr3Ptr(&ptxsc_entry->wlanhdr), MACADDRLEN)) {/*compare addr 3*/ + goto just_skip; + } + + ptxsc_entry->txcfg.mesh_header.segNum = txcfg->mesh_header.segNum; + ptxsc_entry->txcfg.mesh_header.TTL = txcfg->mesh_header.TTL; + ptxsc_entry->txcfg.is_11s = txcfg->is_11s; + } +#endif + + BUG_ON(txcfg->q_num != ptxsc_entry->txcfg.q_num); + memcpy(txcfg, &ptxsc_entry->txcfg, FIELD_OFFSET(struct tx_insn, pxmitframe)); + + { + txcfg->phdr = (UINT8 *)get_wlanllchdr_from_poll(priv); + if (txcfg->phdr == NULL) { + DEBUG_ERR("Can't alloc wlan header!\n"); + rtl8192cd_tx_xmitSkbFail(priv, skb, dev, wdsDev, txcfg); + goto stop_proc; + } + memcpy(txcfg->phdr, (const void *)&ptxsc_entry->wlanhdr, sizeof(struct wlanllc_hdr)); + txcfg->pframe = skb; +#ifdef WDS + /*Correct the aggre_mthd*/ + if(pstat->state & WIFI_WDS) + if(txcfg->aggre_en != pstat->aggre_mthd) { + /*Invalid the tx_sc entry*/ + ptxsc_entry->txcfg.fr_len=0; + txcfg->aggre_en = pstat->aggre_mthd; + } +#endif + + txcfg->fr_len = skb->len - WLAN_ETHHDR_LEN; +#if defined(CONFIG_SDIO_HCI) && defined(TX_SCATTER) + // in case 1st buffer len is 14, we get ether header pointer first and then ajust the skb + pethhdr = (struct wlan_ethhdr_t *)(skb->data); +#endif + skb_pull(skb, WLAN_ETHHDR_LEN); + } + +#ifdef CONFIG_RTL_WAPI_SUPPORT +#ifdef CONFIG_RTL_HW_WAPI_SUPPORT +#ifdef CONFIG_IEEE80211W + if((txcfg->privacy==_WAPI_SMS4_)&&(txcfg->llc>0)&&(UseSwCrypto(priv, pstat, FALSE, 0))) +#else + if((txcfg->privacy==_WAPI_SMS4_)&&(txcfg->llc>0)&&(UseSwCrypto(priv, pstat, FALSE))) +#endif +#else + if((txcfg->privacy==_WAPI_SMS4_)&&(txcfg->llc>0)) +#endif + { + //To restore not-encrypted llc in wlan hdr + //because llc in wlan hdr has been sms4encrypted to deliver at SecSWSMS4Encryption() + eth_2_llc(&ptxsc_entry->ethhdr, (struct llc_snap *)(txcfg->phdr+txcfg->hdr_len + txcfg->iv)); + } +#endif + + if (txcfg->privacy == _TKIP_PRIVACY_) { + if (rtl8192cd_tx_tkip(priv, skb, pstat, txcfg) == TX_PROCEDURE_CTRL_STOP) { + goto stop_proc; + } + } + +#ifdef MESH_TX_SHORTCUT + if ( (txcfg->is_11s&1) && (GetFrameSubType(txcfg->phdr) == WIFI_11S_MESH)) + if( !reuse_meshhdr(priv, txcfg) ) { + goto stop_proc; + } +#endif + if (txcfg->is_pspoll && (tx_servq_len(&pstat->tx_queue[BE_QUEUE]) > 0)) { + SetMData(txcfg->phdr); + } + +#ifdef WMM_APSD + if (pstat->apsd_trigger) { + if (((pstat->apsd_bitmap & 0x01) && tx_servq_len(&pstat->tx_queue[VO_QUEUE])) + || ((pstat->apsd_bitmap & 0x02) && tx_servq_len(&pstat->tx_queue[VI_QUEUE])) + || ((pstat->apsd_bitmap & 0x04) && tx_servq_len(&pstat->tx_queue[BK_QUEUE])) + || ((pstat->apsd_bitmap & 0x08) && tx_servq_len(&pstat->tx_queue[BE_QUEUE]))) { + SetMData(txcfg->phdr); + } else { + if ((GetFrameSubType(txcfg->phdr) & (BIT2 | BIT3 | BIT6 | BIT7)) == (WIFI_DATA_TYPE | BIT7)) { + if (pstat->state & WIFI_SLEEP_STATE) { + unsigned char *qosctrl = GetQosControl(txcfg->phdr); + qosctrl[0] |= BIT4; + } + } + pstat->apsd_trigger = 0; + pstat->apsd_pkt_buffering = 0; + } + } +#endif + + txcfg->tx_rate = get_tx_rate(priv, pstat); + txcfg->lowest_tx_rate = get_lowest_tx_rate(priv, pstat, txcfg->tx_rate); + // log tx statistics... + tx_sum_up(priv, pstat, txcfg->fr_len+txcfg->hdr_len+txcfg->iv+txcfg->llc+txcfg->mic+txcfg->icv); + + // for SW LED + priv->pshare->LED_tx_cnt++; + + if ( +#ifdef RTK_AC_SUPPORT //for 11ac logo //FOR_VHT5G_PF + ( ((pstat->aggre_mthd == AGGRE_MTHD_MPDU_AMSDU) || (pstat->aggre_mthd == AGGRE_MTHD_MPDU)) + && txcfg->aggre_en ) || +#endif + ((txcfg->aggre_en >= FG_AGGRE_MPDU) && (txcfg->aggre_en <= FG_AGGRE_MPDU_BUFFER_LAST)) + ) { + if (!pstat->ADDBA_ready[(int)skb->cb[1]]) { + if ((pstat->ADDBA_req_num[(int)skb->cb[1]] < 5) && !pstat->ADDBA_sent[(int)skb->cb[1]]) { + pstat->ADDBA_req_num[(int)skb->cb[1]]++; + SMP_UNLOCK_XMIT(flags); + issue_ADDBAreq(priv, pstat, (int)skb->cb[1]); + SMP_LOCK_XMIT(flags); + pstat->ADDBA_sent[(int)skb->cb[1]]++; + } + } + } + + // check if we could re-use tx descriptor + if ( + ((get_desc(ptxsc_entry->hwdesc1.Dword7)&TX_TxBufSizeMask) > 0) && + (skb->len == (get_desc(ptxsc_entry->hwdesc1.Dword7)&TX_TxBufSizeMask)) && + (txcfg->tx_rate == ptxsc_entry->txcfg.tx_rate) && + (pstat->protection == priv->pmib->dot11ErpInfo.protection) && + (pstat->ht_protection == priv->ht_protection) +#if defined(WIFI_WMM) && defined(WMM_APSD) + && (!( +#ifdef CLIENT_MODE + (OPMODE & WIFI_AP_STATE) && +#endif + (APSD_ENABLE) && (pstat->state & WIFI_SLEEP_STATE))) +#endif + ) { + + pstat->tx_sc_pkts_lv2++; + + if (txcfg->privacy) { + switch (txcfg->privacy) { + case _WEP_104_PRIVACY_: + case _WEP_40_PRIVACY_: + wep_fill_iv(priv, txcfg->phdr, txcfg->hdr_len, ptxsc_entry->sc_keyid); + break; + + case _TKIP_PRIVACY_: + tkip_fill_encheader(priv, txcfg->phdr, txcfg->hdr_len, ptxsc_entry->sc_keyid); + break; + + case _CCMP_PRIVACY_: + aes_fill_encheader(priv, txcfg->phdr, txcfg->hdr_len, ptxsc_entry->sc_keyid); + break; + } + } + rtl8192cd_signin_txdesc_shortcut(priv, txcfg, ptxsc_entry); +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.tx_cnt_sc2++; +#endif + goto stop_proc; + } + + pstat->tx_sc_pkts_lv1++; +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s) { + memcpy(&priv->ethhdr, &(ptxsc_entry->ethhdr), sizeof(struct wlan_ethhdr_t)); + } +#endif + + +#if defined(__ECOS) && defined(TX_SCATTER) + if (skb->key) + rtl8192cd_signin_txdesc(priv, txcfg, pethhdr); //TBD, ethhdr might be overwrite by WAPI + else + rtl8192cd_signin_txdesc(priv, txcfg, NULL); +#else + rtl8192cd_signin_txdesc(priv, txcfg, NULL); +#endif +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.tx_cnt_sc1++; +#endif + goto stop_proc; + } + if (!priv->pmib->dot11OperationEntry.disable_txsc && pstat) + pstat->tx_sc_pkts_slow++; +#endif // TX_SHORTCUT +#ifdef CONFIG_RTK_MESH +just_skip: +#endif + +#if defined(SHORTCUT_STATISTIC) //defined(__ECOS) && defined(_DEBUG_RTL8192CD_) + priv->ext_stats.tx_cnt_nosc++; +#endif + + /* ==================== Slow path of packet TX process ==================== */ + SMP_UNLOCK_XMIT(flags); + if (rtl8192cd_tx_slowPath(priv, skb, pstat, dev, wdsDev, txcfg) == TX_PROCEDURE_CTRL_STOP) { + SMP_LOCK_XMIT(flags); + goto stop_proc; + } + SMP_LOCK_XMIT(flags); + +#ifdef __KERNEL__ + dev->trans_start = jiffies; +#endif + +#ifdef A4_STA + if ((OPMODE & WIFI_AP_STATE) && IS_MCAST(da) && + priv->pshare->rf_ft_var.a4_enable && !list_empty(&priv->a4_sta_list)) { + struct list_head *phead, *plist; + + skb_push(skb, WLAN_ETHHDR_LEN); + + phead = &priv->a4_sta_list; + plist = phead->next; + + while (plist != phead) { + struct stat_info *dst_stat; + + pstat = list_entry(plist, struct stat_info, a4_sta_list); + ASSERT(pstat->state & WIFI_A4_STA); + + dst_stat = a4_sta_lookup(priv, skb->data+MACADDRLEN); + if (pstat != dst_stat) + send_br_packet(priv, skb, pstat); + + plist = plist->next; + } + } +#endif + + goto stop_proc; + +free_and_stop: /* Free current packet and stop TX process */ + + rtl_kfree_skb(priv, skb, _SKB_TX_); + +stop_proc: /* Stop process and assume the TX-ed packet is already "processed" (freed or TXed) in previous code. */ + + rtw_handle_xmit_fail(priv, txcfg); + + return 0; +} +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#ifndef CONFIG_RTK_MESH +int rtl8192cd_wlantx(struct rtl8192cd_priv *priv, struct tx_insn* txcfg) +{ + return (rtl8192cd_firetx(priv, txcfg)); +} +#endif + +#ifdef TX_SHORTCUT + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL +__MIPS16 +__IRAM_IN_865X +int rtl88XX_signin_txdesc_shortcut(struct rtl8192cd_priv *priv, struct tx_insn *txcfg, int idx) +{ + struct tx_desc_info *pswdescinfo, *pdescinfo; + struct rtl8192cd_hw *phw; + int q_num; + u2Byte *tx_head; + struct stat_info *pstat; + struct sk_buff *pskb; + + PHCI_TX_DMA_MANAGER_88XX ptx_dma; + u32 halQNum; + PHCI_TX_DMA_QUEUE_STRUCT_88XX cur_q; + PTX_BUFFER_DESCRIPTOR cur_txbd; + TX_DESC_DATA_88XX desc_data; + + pstat = txcfg->pstat; + pskb = (struct sk_buff *)txcfg->pframe; + + phw = GET_HW(priv); + q_num = txcfg->q_num; + + halQNum = GET_HAL_INTERFACE(priv)->MappingTxQueueHandler(priv, (u32)q_num); + ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + cur_q = &(ptx_dma->tx_queue[halQNum]); + cur_txbd = cur_q->pTXBD_head + cur_q->host_idx; + memset(&desc_data, 0, sizeof(TX_DESC_DATA_88XX)); + + tx_head = &(cur_q->host_idx); + + pswdescinfo = get_txdesc_info(priv->pshare->pdesc_info, q_num); + + pdescinfo = pswdescinfo + *tx_head; + + // TODO: if enable HW_SEQ , it should be disabled here... + assign_wlanseq(GET_HW(priv), txcfg->phdr, pstat, GET_MIB(priv) +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , txcfg->is_11s +#endif + ); + + if ((pstat->IOTPeer==HT_IOT_PEER_INTEL) && (pstat->retry_inc)) { + if (is_MCS_rate(pstat->current_tx_rate) && !(pstat->leave) + && priv->pshare->intel_rty_lmt) { + desc_data.rtyLmtEn = _TRUE; + desc_data.dataRtyLmt = priv->pshare->intel_rty_lmt; + } else { + desc_data.rtyLmtEn = _FALSE; + desc_data.dataRtyLmt = 1; + } + } + + + desc_data.iv = txcfg->iv; + desc_data.secType = txcfg->privacy; + + if((priv->pshare->rf_ft_var.txforce != 0xff) +#ifdef BEAMFORMING_SUPPORT + && (!txcfg->ndpa) +#endif + ){ + desc_data.dataRate = priv->pshare->rf_ft_var.txforce; + desc_data.disDataFB = _TRUE; + desc_data.disRTSFB = _TRUE; + desc_data.useRate = _TRUE; + } + +#ifdef BEAMFORMING_SUPPORT + if (priv->pmib->dot11nConfigEntry.dot11nSTBC && (txcfg->pstat) && + ((txcfg->pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_RX_STBC_CAP_)) +#ifdef RTK_AC_SUPPORT + || (txcfg->pstat->vht_cap_buf.vht_cap_info & cpu_to_le32(_VHTCAP_RX_STBC_CAP_)) +#endif + )){ + u1Byte Idx = 0; + PRT_BEAMFORMING_ENTRY pEntry; + pEntry = Beamforming_GetEntryByMacId(priv, txcfg->pstat->aid, &Idx); + if(((get_rf_mimo_mode(priv) == MIMO_2T2R) || (get_rf_mimo_mode(priv) == MIMO_3T3R)) && (pEntry == NULL)) + desc_data.dataStbc = 1; + } +#endif +#if 0 +//#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE) + pdesc->Dword8 = set_desc(get_physical_addr(priv, txcfg->phdr-8, + (get_desc(pdesc->Dword7)& TX_TxBufSizeMask), PCI_DMA_TODEVICE)); + else +#endif + +#if 0 + pdescinfo->pframe = txcfg->phdr; + //pdescinfo->buf_type[0] = txcfg->fr_type; + //pdescinfo->buf_pframe[0] = txcfg->pframe; +#if defined(WIFI_WMM) && defined(WMM_APSD) + pdescinfo->priv = priv; + pdescinfo->pstat = pstat; +#endif +#endif // 0 + +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + if (GetFrameSubType(txcfg->phdr) == WIFI_PSPOLL) { + desc_data.navUseHdr = _TRUE; + } + + if (priv->ps_state) + SetPwrMgt(txcfg->phdr); + else + ClearPwrMgt(txcfg->phdr); + } +#endif + +// if (txcfg->one_txdesc) +// goto one_txdesc; + + // TODO: have_hw_mic +//one_txdesc: + + //descinfo_copy(pdescinfo, &pstat->tx_sc_ent[idx].swdesc1); + pdescinfo->type = pstat->tx_sc_ent[idx].swdesc1.type; + pdescinfo->len = pstat->tx_sc_ent[idx].swdesc1.len; + pdescinfo->rate = pstat->tx_sc_ent[idx].swdesc1.rate; + + //??? pdescinfo->buf_type[0] = pstat->tx_sc_ent[idx].swdesc1.buf_type[0]; + pdescinfo->buf_type[0] = txcfg->fr_type; + + pdescinfo->pframe = txcfg->phdr; + //pdescinfo->buf_pframe[0] = txcfg->pframe; +#if defined(WIFI_WMM) && defined(WMM_APSD) + pdescinfo->priv = priv; + pdescinfo->pstat = pstat; +#endif + + desc_data.pHdr = txcfg->phdr; + desc_data.hdrLen = txcfg->hdr_len; + desc_data.llcLen = txcfg->llc; + desc_data.frLen = txcfg->fr_len; // pskb->len ?? + //if (pskb->len != txcfg->fr_len) { + // printk("%s(%d): pskb->len:%d, txcfg->fr_len:%d \n", __FUNCTION__, __LINE__, pskb->len, txcfg->fr_len); + //} + desc_data.pBuf = pskb->data; + +#ifdef CONFIG_WLAN_HAL_8814AE + if (GET_CHIP_VER(priv)==VERSION_8814A) { +#ifdef WLAN_HAL_HW_TX_SHORTCUT_REUSE_TXDESC + desc_data.stwEn = TRUE; + if (txcfg->pstat->aid != MANAGEMENT_AID) { + desc_data.macId = REMAP_AID(txcfg->pstat); + } +#endif // WLAN_HAL_HW_TX_SHORTCUT_REUSE_TXDESC +#ifdef WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + desc_data.smhEn = TRUE; + + desc_data.pHdr = txcfg->phdr; // 802.3 hdr len + payload len; + desc_data.hdrLen = txcfg->fr_len; // 802.3 hdr + payload + + desc_data.llcLen = 0; + + desc_data.frLen = 0; + desc_data.pBuf = 0; // useless....because frLen is zero + // TODO: recycle problem for sw desc.. +#endif // WLAN_HAL_HW_TX_SHORTCUT_HDR_CONV + } +#endif // CONFIG_WLAN_HAL_8814AE + + GET_HAL_INTERFACE(priv)->FillShortCutTxHwCtrlHandler( + priv, halQNum, (void *)&desc_data, pstat->tx_sc_ent[idx].hal_hw_desc, 0x02); + + // TODO: check the sw desc here for HW_TX_SHORTCUT + pdescinfo->paddr = get_desc(cur_txbd->TXBD_ELE[1].Dword1);//header address + pdescinfo->len = get_desc(cur_txbd->TXBD_ELE[1].Dword0) & 0xffff; + pdescinfo->buf_paddr[0] = get_desc(cur_txbd->TXBD_ELE[2].Dword1);//payload address + pdescinfo->buf_pframe[0] = pskb; + pdescinfo->buf_len[0] = txcfg->fr_len; // pskb->len; + + GET_HAL_INTERFACE(priv)->SyncSWTXBDHostIdxToHWHandler(priv, halQNum); + + return 0; +} +#endif // CONFIG_WLAN_HAL + +#ifdef CONFIG_RTL_8812_SUPPORT +__MIPS16 +__IRAM_IN_865X +int rtl8192cd_signin_txdesc_shortcut_8812(struct rtl8192cd_priv *priv, struct tx_insn *txcfg, int idx) +{ + struct tx_desc *phdesc, *pdesc, *pfrstdesc; + struct tx_desc_info *pswdescinfo, *pdescinfo; + struct rtl8192cd_hw *phw; + int *tx_head, q_num; + struct stat_info *pstat; + struct sk_buff *pskb; + unsigned long pfrst_dma_desc; + unsigned long *dma_txhead; +/* +#if defined(CONFIG_RTL_WAPI_SUPPORT) + uint8 *wapiMic2; + struct tx_desc *pmicdesc; + struct tx_desc_info *pmicdescinfo; +#endif +*/ + pstat = txcfg->pstat; + pskb = (struct sk_buff *)txcfg->pframe; + pfrst_dma_desc=0; + + phw = GET_HW(priv); + q_num = txcfg->q_num; + + dma_txhead = get_txdma_addr(phw, q_num); + tx_head = get_txhead_addr(phw, q_num); + phdesc = get_txdesc(phw, q_num); + pswdescinfo = get_txdesc_info(priv->pshare->pdesc_info, q_num); + + /*------------------------------------------------------------*/ + /* fill descriptor of header + iv + llc */ + /*------------------------------------------------------------*/ + pfrstdesc = pdesc = phdesc + *tx_head; + pdescinfo = pswdescinfo + *tx_head; + + memcpy(pdesc, &pstat->tx_sc_ent[idx].hwdesc1, 40); + + assign_wlanseq(GET_HW(priv), txcfg->phdr, pstat, GET_MIB(priv) +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , txcfg->is_11s +#endif + ); + + pdesc->Dword9 = 0; + pdesc->Dword9 |= set_desc((GetSequence(txcfg->phdr) & TXdesc_92E_TX_SeqMask) << TXdesc_92E_TX_SeqSHIFT); + + if((priv->pshare->rf_ft_var.txforce != 0xff) +#ifdef BEAMFORMING_SUPPORT + && (!txcfg->ndpa) +#endif + ){ + pdesc->Dword4 &= set_desc(~(TXdesc_92E_DataRateMask << TXdesc_92E_DataRateSHIFT)); + pdesc->Dword3 |= set_desc(TXdesc_92E_DisDataFB|TXdesc_92E_DisRtsFB|TXdesc_92E_UseRate); + pdesc->Dword4 |= set_desc((priv->pshare->rf_ft_var.txforce & TXdesc_92E_DataRateMask) << TXdesc_92E_DataRateSHIFT); + } + + + if (txcfg->one_txdesc) { +#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE) { + pdesc->Dword0 = set_desc(((get_desc(pdesc->Dword0) & 0xff00ffff) |(0x28 << TX_OffsetSHIFT)) | + TX_LastSeg | (txcfg->hdr_len + txcfg->llc + txcfg->iv + txcfg->fr_len)); + pdesc->Dword1 = set_desc(get_desc(pdesc->Dword1) | (1 << TX_PktOffsetSHIFT) ); + pdesc->Dword7 = set_desc((get_desc(pdesc->Dword7) & 0xffff0000) | + (txcfg->hdr_len + txcfg->llc + txcfg->iv + txcfg->fr_len+8)); + memset(txcfg->phdr-8, '\0', 8); + if (pstat->empkt_num > 0) + insert_emcontent(priv, txcfg, txcfg->phdr-8); + pdesc->Dword10 = set_desc(get_physical_addr(priv, txcfg->phdr-8, + (get_desc(pdesc->Dword7)&TX_TxBufSizeMask), PCI_DMA_TODEVICE)); + + } + else +#endif + { + pdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & 0xffff0000) | + TX_LastSeg | (txcfg->hdr_len + txcfg->llc + txcfg->iv + txcfg->fr_len)); + pdesc->Dword7 = set_desc((get_desc(pdesc->Dword7) & 0xffff0000) | + (txcfg->hdr_len + txcfg->llc + txcfg->iv + txcfg->fr_len)); + } + } + +#ifdef BEAMFORMING_SUPPORT + if ((priv->pmib->dot11RFEntry.txbf == 1) && (priv->pmib->dot11nConfigEntry.dot11nSTBC)) { + if ((pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_RX_STBC_CAP_)) +#ifdef RTK_AC_SUPPORT + || (txcfg->pstat->vht_cap_buf.vht_cap_info & cpu_to_le32(_VHTCAP_RX_STBC_CAP_)) +#endif + ) { + u1Byte Idx = 0; + PRT_BEAMFORMING_ENTRY pEntry; + pEntry = Beamforming_GetEntryByMacId(priv, pstat->aid, &Idx); + if(pEntry) + pdesc->Dword5 &= set_desc(~ (BIT(TXdesc_92E_DataStbcSHIFT))); + } + } +#endif +#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE) + pdesc->Dword10 = set_desc(get_physical_addr(priv, txcfg->phdr-8, + (get_desc(pdesc->Dword7)& TX_TxBufSizeMask), PCI_DMA_TODEVICE)); + else +#endif + pdesc->Dword10 = set_desc(get_physical_addr(priv, txcfg->phdr, + (get_desc(pdesc->Dword7)& TX_TxBufSizeMask), PCI_DMA_TODEVICE)); + + descinfo_copy(pdescinfo, &pstat->tx_sc_ent[idx].swdesc1); + pdescinfo->paddr = get_desc(pdesc->Dword10); // buffer addr + if (txcfg->one_txdesc) { + pdescinfo->type = _SKB_FRAME_TYPE_; + pdescinfo->pframe = pskb; + pdescinfo->priv = priv; +#if defined(WIFI_WMM) && defined(WMM_APSD) + pdescinfo->pstat = pstat; +#endif + } + else { + pdescinfo->pframe = txcfg->phdr; +#if defined(WIFI_WMM) && defined(WMM_APSD) + pdescinfo->priv = priv; + pdescinfo->pstat = pstat; +#endif + } + +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + if (GetFrameSubType(pdescinfo->pframe) == WIFI_PSPOLL) + pdesc->Dword1 |= set_desc(TX_NAVUSEHDR); + + if (priv->ps_state) + SetPwrMgt(pdescinfo->pframe); + else + ClearPwrMgt(pdescinfo->pframe); + } +#endif + + pfrst_dma_desc = dma_txhead[*tx_head]; +/* +#ifdef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, get_desc(pdesc->Dword8), (get_desc(pdesc->Dword7)&TX_TxBufferSizeMask), PCI_DMA_TODEVICE); +#endif +*/ + txdesc_rollover(pdesc, (unsigned int *)tx_head); + + if (txcfg->one_txdesc) + goto one_txdesc; + + /*------------------------------------------------------------*/ + /* fill descriptor of frame body */ + /*------------------------------------------------------------*/ + pdesc = phdesc + *tx_head; + pdescinfo = pswdescinfo + *tx_head; + memcpy(pdesc, &pstat->tx_sc_ent[idx].hwdesc2, 40); + + pdesc->Dword10 = set_desc(get_physical_addr(priv, pskb->data, + (get_desc(pdesc->Dword7)&0x0fff), PCI_DMA_TODEVICE)); + + descinfo_copy(pdescinfo, &pstat->tx_sc_ent[idx].swdesc2); + + pdescinfo->paddr = get_desc(pdesc->Dword10); + pdescinfo->pframe = pskb; + pdescinfo->priv = priv; +/* +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, dma_txhead[*tx_head], sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#else + rtl_cache_sync_wback(priv, get_desc(pdesc->Dword8), (get_desc(pdesc->Dword7)&TX_TxBufferSizeMask), PCI_DMA_TODEVICE); +#endif +*/ + +#if defined(CONFIG_RTL_WAPI_SUPPORT) + if (txcfg->privacy == _WAPI_SMS4_) + { + SecSWSMS4Encryption(priv, txcfg); + } +#endif + +#ifndef NOT_RTK_BSP + if ((txcfg->privacy == _TKIP_PRIVACY_) && + (priv->pshare->have_hw_mic) && + !(priv->pmib->dot11StationConfigEntry.swTkipMic)) + { + register unsigned long int l,r; + unsigned char *mic; + int delay = 18; + + while ((*(volatile unsigned int *)GDMAISR & GDMA_COMPIP) == 0) { + delay_us(delay); + delay = delay / 2; + } + + l = *(volatile unsigned int *)GDMAICVL; + r = *(volatile unsigned int *)GDMAICVR; + + mic = ((struct sk_buff *)txcfg->pframe)->data + txcfg->fr_len - 8; + mic[0] = (unsigned char)(l & 0xff); + mic[1] = (unsigned char)((l >> 8) & 0xff); + mic[2] = (unsigned char)((l >> 16) & 0xff); + mic[3] = (unsigned char)((l >> 24) & 0xff); + mic[4] = (unsigned char)(r & 0xff); + mic[5] = (unsigned char)((r >> 8) & 0xff); + mic[6] = (unsigned char)((r >> 16) & 0xff); + mic[7] = (unsigned char)((r >> 24) & 0xff); + +#ifdef MICERR_TEST + if (priv->micerr_flag) { + mic[7] ^= mic[7]; + priv->micerr_flag = 0; + } +#endif + } +#endif // NOT_RTK_BSP + +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(get_desc(pdesc->Dword10)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), (get_desc(pdesc->Dword7)&TX_TxBufSizeMask), PCI_DMA_TODEVICE); + + txdesc_rollover(pdesc, (unsigned int *)tx_head); + +one_txdesc: + + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(get_desc(pfrstdesc->Dword10)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), (get_desc(pfrstdesc->Dword7)&TX_TxBufSizeMask), PCI_DMA_TODEVICE); + +#ifdef SUPPORT_SNMP_MIB + if (txcfg->rts_thrshld <= get_mpdu_len(txcfg, txcfg->fr_len)) + SNMP_MIB_INC(dot11RTSSuccessCount, 1); +#endif + + pfrstdesc->Dword0 |= set_desc(TX_OWN); + +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(pfrst_dma_desc-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + if (q_num == HIGH_QUEUE) { + DEBUG_WARN("signin shortcut for DTIM pkt?\n"); + return 0; + } else { + tx_poll(priv, q_num); + } + + return 0; +} +#endif + +#if(CONFIG_WLAN_NOT_HAL_EXIST==1) +__MIPS16 +__IRAM_IN_865X +int rtl8192cd_signin_txdesc_shortcut(struct rtl8192cd_priv *priv, struct tx_insn *txcfg, int idx) +{ + struct tx_desc *phdesc, *pdesc, *pfrstdesc; + struct tx_desc_info *pswdescinfo, *pdescinfo; + struct rtl8192cd_hw *phw; + int *tx_head, q_num; + struct stat_info *pstat; + struct sk_buff *pskb; + unsigned long pfrst_dma_desc; + unsigned long *dma_txhead; +/* +#if defined(CONFIG_RTL_WAPI_SUPPORT) + uint8 *wapiMic2; + struct tx_desc *pmicdesc; + struct tx_desc_info *pmicdescinfo; +#endif +*/ +#ifdef TX_SCATTER + int go_desc3=0; +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + return rtl8192cd_signin_txdesc_shortcut_8812(priv, txcfg, idx); +#endif + + pstat = txcfg->pstat; + pskb = (struct sk_buff *)txcfg->pframe; + pfrst_dma_desc=0; + + phw = GET_HW(priv); + q_num = txcfg->q_num; + + dma_txhead = get_txdma_addr(phw, q_num); + tx_head = get_txhead_addr(phw, q_num); + phdesc = get_txdesc(phw, q_num); + pswdescinfo = get_txdesc_info(priv->pshare->pdesc_info, q_num); + + /*------------------------------------------------------------*/ + /* fill descriptor of header + iv + llc */ + /*------------------------------------------------------------*/ + pfrstdesc = pdesc = phdesc + *tx_head; + pdescinfo = pswdescinfo + *tx_head; + + desc_copy(pdesc, &pstat->tx_sc_ent[idx].hwdesc1); + assign_wlanseq(GET_HW(priv), txcfg->phdr, pstat, GET_MIB(priv) +#ifdef CONFIG_RTK_MESH // For broadcast data frame via mesh (ex:ARP requst) + , txcfg->is_11s +#endif + ); + + + pdesc->Dword3 = 0; + pdesc->Dword3 = set_desc((GetSequence(txcfg->phdr) & TX_SeqMask) << TX_SeqSHIFT); + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + if (CHIP_VER_92X_SERIES(priv)) +#endif + if (priv->pmib->dot11RFEntry.txbf == 1) { + pdesc->Dword2 &= set_desc(0x03ffffff); // clear related bits + pdesc->Dword2 |= set_desc(1 << TX_TxAntCckSHIFT); // Set Default CCK rate with 1T + pdesc->Dword2 |= set_desc(1 << TX_TxAntlSHIFT); // Set Default Legacy rate with 1T + pdesc->Dword2 |= set_desc(1 << TX_TxAntHtSHIFT); // Set Default Ht rate + + if (is_MCS_rate(txcfg->tx_rate)) { + if ((txcfg->tx_rate - HT_RATE_ID) <= 6){ + pdesc->Dword2 |= set_desc(3 << TX_TxAntHtSHIFT); // Set Ht rate < MCS6 with 2T + } + } + } + if(priv->pmib->dot11RFEntry.bcn2path){ + pdesc->Dword2 &= set_desc(0x03ffffff); // clear related bits + pdesc->Dword2 |= set_desc(1 << TX_TxAntCckSHIFT); // Set Default CCK rate with 1T + } + +// if (txcfg->pstat) +// pdesc->Dword1 |= set_desc(txcfg->pstat->aid & TX_MACIDMask); + + //set Break +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) != VERSION_8188E) +#endif + { + if ((txcfg->q_num >=1 && txcfg->q_num <=4)) { + if (pstat != priv->pshare->CurPstat[txcfg->q_num-1]) { + pdesc->Dword1 |= set_desc(TX_BK); + priv->pshare->CurPstat[txcfg->q_num-1] = pstat; + } else { + pdesc->Dword1 &= set_desc(~TX_BK); // clear it + } + } else { + pdesc->Dword1 |= set_desc(TX_BK); + } + } + + if ((pstat->IOTPeer==HT_IOT_PEER_INTEL) && (pstat->retry_inc)) { + if (is_MCS_rate(pstat->current_tx_rate) && !(pstat->leave) + && priv->pshare->intel_rty_lmt) { + pdesc->Dword5 |= set_desc(TX_RtyLmtEn); + + pdesc->Dword5 &= set_desc(~(TX_DataRtyLmtMask << TX_DataRtyLmtSHIFT)); + pdesc->Dword5 |= set_desc((priv->pshare->intel_rty_lmt & TX_DataRtyLmtMask) << TX_DataRtyLmtSHIFT); + } else { + pdesc->Dword5 &= set_desc(~TX_RtyLmtEn); + pdesc->Dword5 &= set_desc(~(TX_DataRtyLmtMask << TX_DataRtyLmtSHIFT)); + } + } + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if ((GET_CHIP_VER(priv)==VERSION_8188E) && (!txcfg->fixed_rate)) { + if (pstat->ht_current_tx_info & TX_USE_SHORT_GI) + pdesc->Dword5 |= set_desc(TX_SGI); + else + pdesc->Dword5 &= set_desc(~TX_SGI); + } +#endif + + if (txcfg->one_txdesc) { +#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE) { + pdesc->Dword0 = set_desc(((get_desc(pdesc->Dword0) & 0xff00ffff) |(0x28 << TX_OffsetSHIFT)) | + TX_LastSeg | (txcfg->hdr_len + txcfg->llc + txcfg->iv + txcfg->fr_len)); + pdesc->Dword1 = set_desc(get_desc(pdesc->Dword1) | (1 << TX_PktOffsetSHIFT) ); + pdesc->Dword7 = set_desc((get_desc(pdesc->Dword7) & 0xffff0000) | + (txcfg->hdr_len + txcfg->llc + txcfg->iv + txcfg->fr_len+8)); +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + pdesc->Dword6 &= set_desc(~ (0xf << TX_MaxAggNumSHIFT)); + pdesc->Dword6 |= set_desc(0xf << TX_MaxAggNumSHIFT); + } +#endif + memset(txcfg->phdr-8, '\0', 8); + if (pstat->empkt_num > 0) + insert_emcontent(priv, txcfg, txcfg->phdr-8); + pdesc->Dword8 = set_desc(get_physical_addr(priv, txcfg->phdr-8, + (get_desc(pdesc->Dword7)&TX_TxBufSizeMask), PCI_DMA_TODEVICE)); + + } + else +#endif + { +#if defined(TX_EARLY_MODE) && defined(CONFIG_RTL_88E_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E) + pdesc->Dword6 &= set_desc(~ (0x0f << TX_MaxAggNumSHIFT)); +#endif + pdesc->Dword0 = set_desc((get_desc(pdesc->Dword0) & 0xffff0000) | + TX_LastSeg | (txcfg->hdr_len + txcfg->llc + txcfg->iv + txcfg->fr_len)); + pdesc->Dword7 = set_desc((get_desc(pdesc->Dword7) & 0xffff0000) | + (txcfg->hdr_len + txcfg->llc + txcfg->iv + txcfg->fr_len)); + } + } + + if(priv->pshare->rf_ft_var.txforce != 0xff) { + pdesc->Dword5 &= set_desc(~(TX_DataRateMask << TX_DataRateSHIFT)); + pdesc->Dword4 |= set_desc(TX_UseRate); + pdesc->Dword5 |= set_desc((priv->pshare->rf_ft_var.txforce & TX_DataRateMask) << TX_DataRateSHIFT); + } + +#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE) + pdesc->Dword8 = set_desc(get_physical_addr(priv, txcfg->phdr-8, + (get_desc(pdesc->Dword7)& TX_TxBufSizeMask), PCI_DMA_TODEVICE)); + else +#endif + pdesc->Dword8 = set_desc(get_physical_addr(priv, txcfg->phdr, + (get_desc(pdesc->Dword7)& TX_TxBufSizeMask), PCI_DMA_TODEVICE)); + + descinfo_copy(pdescinfo, &pstat->tx_sc_ent[idx].swdesc1); + pdescinfo->paddr = get_desc(pdesc->Dword8); // buffer addr + if (txcfg->one_txdesc) { + pdescinfo->type = _SKB_FRAME_TYPE_; + pdescinfo->pframe = pskb; + pdescinfo->priv = priv; +#if defined(WIFI_WMM) && defined(WMM_APSD) + pdescinfo->pstat = pstat; +#endif + } + else { + pdescinfo->pframe = txcfg->phdr; +#if defined(WIFI_WMM) && defined(WMM_APSD) + pdescinfo->priv = priv; + pdescinfo->pstat = pstat; +#endif + } + +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + if (GetFrameSubType(pdescinfo->pframe) == WIFI_PSPOLL) + pdesc->Dword1 |= set_desc(TX_NAVUSEHDR); + + if (priv->ps_state) + SetPwrMgt(pdescinfo->pframe); + else + ClearPwrMgt(pdescinfo->pframe); + } +#endif + + pfrst_dma_desc = dma_txhead[*tx_head]; +/* +#ifdef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, get_desc(pdesc->Dword8), (get_desc(pdesc->Dword7)&TX_TxBufferSizeMask), PCI_DMA_TODEVICE); +#endif +*/ + txdesc_rollover(pdesc, (unsigned int *)tx_head); + + if (txcfg->one_txdesc) + goto one_txdesc; + + /*------------------------------------------------------------*/ + /* fill descriptor of frame body */ + /*------------------------------------------------------------*/ +#ifdef TX_SCATTER +next_desc: +#endif + pdesc = phdesc + *tx_head; + pdescinfo = pswdescinfo + *tx_head; +#ifdef TX_SCATTER + if (go_desc3) + desc_copy(pdesc, &pstat->tx_sc_ent[idx].hwdesc3); + else +#endif + desc_copy(pdesc, &pstat->tx_sc_ent[idx].hwdesc2); + +#ifdef TX_SCATTER + if (pskb->list_num > 1) { + if (go_desc3) + pdesc->Dword7 = set_desc((get_desc(pdesc->Dword7) & 0xffff0000) | + pskb->list_buf[2].len); + else + pdesc->Dword7 = set_desc((get_desc(pdesc->Dword7) & 0xffff0000) | + pskb->list_buf[1].len); + } +#endif + + pdesc->Dword8 = set_desc(get_physical_addr(priv, pskb->data, + (get_desc(pdesc->Dword7)&0x0fff), PCI_DMA_TODEVICE)); + +#ifdef TX_SCATTER + if (go_desc3) { + descinfo_copy(pdescinfo, &pstat->tx_sc_ent[idx].swdesc3); + pdescinfo->type = _RESERVED_FRAME_TYPE_; + } else +#endif + { + descinfo_copy(pdescinfo, &pstat->tx_sc_ent[idx].swdesc2); + } + + pdescinfo->paddr = get_desc(pdesc->Dword8); + pdescinfo->pframe = pskb; + pdescinfo->priv = priv; +/* +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, dma_txhead[*tx_head], sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#else + rtl_cache_sync_wback(priv, get_desc(pdesc->Dword8), (get_desc(pdesc->Dword7)&TX_TxBufferSizeMask), PCI_DMA_TODEVICE); +#endif +*/ + +#if defined(CONFIG_RTL_WAPI_SUPPORT) + if (txcfg->privacy == _WAPI_SMS4_) + { + SecSWSMS4Encryption(priv, txcfg); + } +#endif + +#ifndef NOT_RTK_BSP + if ((txcfg->privacy == _TKIP_PRIVACY_) && + (priv->pshare->have_hw_mic) && + !(priv->pmib->dot11StationConfigEntry.swTkipMic)) + { + register unsigned long int l,r; + unsigned char *mic; + int delay = 18; + + while ((*(volatile unsigned int *)GDMAISR & GDMA_COMPIP) == 0) { + delay_us(delay); + delay = delay / 2; + } + + l = *(volatile unsigned int *)GDMAICVL; + r = *(volatile unsigned int *)GDMAICVR; + + mic = ((struct sk_buff *)txcfg->pframe)->data + txcfg->fr_len - 8; + mic[0] = (unsigned char)(l & 0xff); + mic[1] = (unsigned char)((l >> 8) & 0xff); + mic[2] = (unsigned char)((l >> 16) & 0xff); + mic[3] = (unsigned char)((l >> 24) & 0xff); + mic[4] = (unsigned char)(r & 0xff); + mic[5] = (unsigned char)((r >> 8) & 0xff); + mic[6] = (unsigned char)((r >> 16) & 0xff); + mic[7] = (unsigned char)((r >> 24) & 0xff); + +#ifdef MICERR_TEST + if (priv->micerr_flag) { + mic[7] ^= mic[7]; + priv->micerr_flag = 0; + } +#endif + } +#endif // NOT_RTK_BSP + +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(dma_txhead[*tx_head]-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(get_desc(pdesc->Dword8)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), (get_desc(pdesc->Dword7)&TX_TxBufSizeMask), PCI_DMA_TODEVICE); + + txdesc_rollover(pdesc, (unsigned int *)tx_head); + +#ifdef TX_SCATTER + if (pstat->tx_sc_ent[idx].has_desc3 && go_desc3 == 0) { + go_desc3 = 1; + goto next_desc; + } +#endif +one_txdesc: + + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(get_desc(pfrstdesc->Dword8)-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), (get_desc(pfrstdesc->Dword7)&TX_TxBufSizeMask), PCI_DMA_TODEVICE); + +#ifdef SUPPORT_SNMP_MIB + if (txcfg->rts_thrshld <= get_mpdu_len(txcfg, txcfg->fr_len)) + SNMP_MIB_INC(dot11RTSSuccessCount, 1); +#endif + + pfrstdesc->Dword0 |= set_desc(TX_OWN); + +#ifndef USE_RTL8186_SDK + rtl_cache_sync_wback(priv, (unsigned long)bus_to_virt(pfrst_dma_desc-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), sizeof(struct tx_desc), PCI_DMA_TODEVICE); +#endif + + if (q_num == HIGH_QUEUE) { + DEBUG_WARN("signin shortcut for DTIM pkt?\n"); + return 0; + } else { + tx_poll(priv, q_num); + } + + return 0; +} +#else +__MIPS16 +__IRAM_IN_865X +int rtl8192cd_signin_txdesc_shortcut(struct rtl8192cd_priv *priv, struct tx_insn *txcfg, int idx) +{ + return 0; +} +#endif//CONFIG_WLAN_NOT_HAL_EXIST +#endif // CONFIG_PCI_HCI +#endif // TX_SHORTCUT + +#ifdef CONFIG_PCI_HCI +/* This sub-routine is gonna to check how many tx desc we need */ +static int check_txdesc(struct rtl8192cd_priv *priv, struct tx_insn* txcfg) +{ + struct sk_buff *pskb=NULL; + unsigned short protocol; + unsigned char *da=NULL; + struct stat_info *pstat=NULL; + int priority=0; + unsigned int is_dhcp = 0; + + if (txcfg->aggre_en == FG_AGGRE_MSDU_MIDDLE || txcfg->aggre_en == FG_AGGRE_MSDU_LAST) + return TRUE; + + txcfg->privacy = txcfg->iv = txcfg->icv = txcfg->mic = 0; + txcfg->frg_num = 0; + txcfg->need_ack = 1; + + if (txcfg->fr_type == _SKB_FRAME_TYPE_) + { + pskb = ((struct sk_buff *)txcfg->pframe); +#ifdef TX_SCATTER + if (pskb->list_num > 0) + txcfg->fr_len = pskb->total_len - WLAN_ETHHDR_LEN; + else +#endif + txcfg->fr_len = pskb->len - WLAN_ETHHDR_LEN; + +#ifdef MP_TEST + if (OPMODE & WIFI_MP_STATE) { + txcfg->hdr_len = WLAN_HDR_A3_LEN; + txcfg->frg_num = 1; + if (IS_MCAST(pskb->data)) + txcfg->need_ack = 0; + return TRUE; + } +#endif + +#ifdef WDS + if (txcfg->wdsIdx >= 0) { + txcfg->hdr_len = WLAN_HDR_A4_LEN; + pstat = get_stainfo(priv, priv->pmib->dot11WdsInfo.entry[txcfg->wdsIdx].macAddr); + if (pstat == NULL) { + DEBUG_ERR("TX DROP: %s: get_stainfo() for wds failed [%d]!\n", (char *)__FUNCTION__, txcfg->wdsIdx); + return FALSE; + } + + txcfg->privacy = priv->pmib->dot11WdsInfo.wdsPrivacy; + switch (txcfg->privacy) { + case _WEP_40_PRIVACY_: + case _WEP_104_PRIVACY_: + txcfg->iv = 4; + txcfg->icv = 4; + break; + case _TKIP_PRIVACY_: + txcfg->iv = 8; + txcfg->icv = 4; + txcfg->mic = 0; + txcfg->fr_len += 8; // for Michael padding + break; + case _CCMP_PRIVACY_: + txcfg->iv = 8; + txcfg->icv = 0; + txcfg->mic = 8; + break; + } + txcfg->frg_num = 1; + if (txcfg->aggre_en < FG_AGGRE_MSDU_FIRST) { + priority = get_skb_priority(priv, (struct sk_buff *)txcfg->pframe, pstat); +#ifdef RTL_MANUAL_EDCA + txcfg->q_num = PRI_TO_QNUM(priv, priority); +#else + PRI_TO_QNUM(priority, txcfg->q_num, priv->pmib->dot11OperationEntry.wifi_specific); +#endif + } + + txcfg->tx_rate = get_tx_rate(priv, pstat); + txcfg->lowest_tx_rate = get_lowest_tx_rate(priv, pstat, txcfg->tx_rate); + + if (priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate) + txcfg->fixed_rate = 1; + txcfg->need_ack = 1; + txcfg->pstat = pstat; +#ifdef WIFI_WMM + if ((pstat) && (QOS_ENABLE) && (pstat->QosEnabled) && (is_qos_data(txcfg->phdr))) + txcfg->hdr_len = WLAN_HDR_A4_QOS_LEN; +#endif + + if (txcfg->aggre_en == 0) { + if ((pstat->aggre_mthd == AGGRE_MTHD_MPDU) && is_MCS_rate(txcfg->tx_rate)) + txcfg->aggre_en = FG_AGGRE_MPDU; + } + + return TRUE; + } +#endif + +#ifdef WIFI_WMM + if (OPMODE & WIFI_AP_STATE) { +#ifdef MCAST2UI_REFINE + pstat = get_stainfo(priv, &pskb->cb[10]); +#else + pstat = get_stainfo(priv, pskb->data); +#endif +#ifdef A4_STA + if (pstat == NULL) { + if (txcfg->pstat && (txcfg->pstat->state & WIFI_A4_STA)) + pstat = txcfg->pstat; + else if (!IS_MCAST(pskb->data) && priv->pshare->rf_ft_var.a4_enable) + pstat = a4_sta_lookup(priv, pskb->data); + if (pstat) + da = pstat->hwaddr; + } +#endif + } + else if (OPMODE & WIFI_STATION_STATE) + pstat = get_stainfo(priv, BSSID); + else if (OPMODE & WIFI_ADHOC_STATE) + pstat = get_stainfo(priv, pskb->data); + + if ((pstat) && (QOS_ENABLE) && (pstat->QosEnabled) && (is_qos_data(txcfg->phdr))) { + txcfg->hdr_len = WLAN_HDR_A3_QOS_LEN; + } + else +#endif + { + txcfg->hdr_len = WLAN_HDR_A3_LEN; + } + +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s) + { + txcfg->hdr_len = WLAN_HDR_A4_QOS_LEN ; + da = txcfg->nhop_11s; + } + else +#endif + +#ifdef A4_STA + if (!da) +#endif +#ifdef MCAST2UI_REFINE + da = &pskb->cb[10]; +#else + da = pskb->data; +#endif + + //check if da is associated, if not, just drop and return false + if (!IS_MCAST(da) +#ifdef CLIENT_MODE + || (OPMODE & WIFI_STATION_STATE) +#endif +#ifdef A4_STA + || (pstat && (pstat->state & WIFI_A4_STA)) +#endif + ) + { +#ifdef A4_STA + if (!(pstat && (pstat->state & WIFI_A4_STA))) +#endif + { +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) + pstat = get_stainfo(priv, BSSID); + else +#endif + { + pstat = get_stainfo(priv, da); + } + } + + if ((pstat == NULL) || (!(pstat->state & WIFI_ASOC_STATE))) + { + DEBUG_ERR("TX DROP: Non asoc tx request!\n"); + return FALSE; + } +#ifdef A4_STA + if (pstat->state & WIFI_A4_STA) + txcfg->hdr_len += WLAN_ADDR_LEN; +#endif + protocol = ntohs(*((UINT16 *)((UINT8 *)pskb->data + ETH_ALEN*2))); + + if ((((protocol == 0x888E) && ((GET_UNICAST_ENCRYP_KEYLEN == 0) +#ifdef WIFI_SIMPLE_CONFIG + || (pstat->state & WIFI_WPS_JOIN) +#endif + )) +#ifdef CONFIG_RTL_WAPI_SUPPORT + || (protocol == ETH_P_WAPI) +#endif + +#ifdef BEAMFORMING_SUPPORT + || (txcfg->ndpa) +#endif + )) + txcfg->privacy = 0; + else + txcfg->privacy = get_privacy(priv, pstat, &txcfg->iv, &txcfg->icv, &txcfg->mic); + + if ((OPMODE & WIFI_AP_STATE) && !IS_MCAST(da) && pskb && (isDHCPpkt(pskb) == TRUE)) + is_dhcp++; + + if ((protocol == 0x888E) +#ifdef CONFIG_RTL_WAPI_SUPPORT + ||(protocol == ETH_P_WAPI) +#endif + || is_dhcp) { + // use basic rate to send EAP packet for sure + txcfg->tx_rate = find_rate(priv, NULL, 0, 1); + txcfg->lowest_tx_rate = txcfg->tx_rate; + txcfg->fixed_rate = 1; + } else { + txcfg->tx_rate = get_tx_rate(priv, pstat); + txcfg->lowest_tx_rate = get_lowest_tx_rate(priv, pstat, txcfg->tx_rate); + if (!is_auto_rate(priv, pstat) && + !(should_restrict_Nrate(priv, pstat) && is_fixedMCSTxRate(priv, pstat))) + { +#ifdef RTK_AC_SUPPORT + if(! is_fixedVHTTxRate(priv, pstat) || (pstat->vht_cap_len)) +#endif + { + txcfg->fixed_rate = 1; + } + } + } + + if (txcfg->aggre_en < FG_AGGRE_MSDU_FIRST) { +#ifdef CONFIG_RTK_MESH + priority = get_skb_priority3(priv, (struct sk_buff *)txcfg->pframe, txcfg->is_11s, pstat); +#else + priority = get_skb_priority(priv, (struct sk_buff *)txcfg->pframe, pstat); +#endif +#ifdef RTL_MANUAL_EDCA + txcfg->q_num = PRI_TO_QNUM(priv, priority); +#else + PRI_TO_QNUM(priority, txcfg->q_num, priv->pmib->dot11OperationEntry.wifi_specific); +#endif + } + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (protocol==ETH_P_WAPI) + { + txcfg->q_num = MGNT_QUEUE; + } +#endif + + if (txcfg->aggre_en == 0 +#ifdef SUPPORT_TX_MCAST2UNI + && (priv->pshare->rf_ft_var.mc2u_disable || (pskb->cb[2] != (char)0xff)) +#endif + ) { + if ((pstat->aggre_mthd == AGGRE_MTHD_MPDU) && + /* is_MCS_rate(txcfg->tx_rate) &&*/ (protocol != 0x888E) +#ifdef CONFIG_RTL_WAPI_SUPPORT + && (protocol != ETH_P_WAPI) +#endif + && !is_dhcp) + txcfg->aggre_en = FG_AGGRE_MPDU; + } + + if( +#ifdef RTK_AC_SUPPORT //FOR_VHT5G_PF + ( txcfg->pstat && + ((txcfg->pstat->aggre_mthd == AGGRE_MTHD_MPDU_AMSDU) || (txcfg->pstat->aggre_mthd == AGGRE_MTHD_MPDU)) + && txcfg->aggre_en ) || +#endif + (txcfg->aggre_en >= FG_AGGRE_MPDU && txcfg->aggre_en <= FG_AGGRE_MPDU_BUFFER_LAST) + ) + { + //panic_printk("%s %d pstat->ADDBA_ready[priority]=%d, priority=%d\n",__func__,__LINE__,pstat->ADDBA_ready[priority],priority); + if (!pstat->ADDBA_ready[priority]) { + if ((pstat->ADDBA_req_num[priority] < 5) && !pstat->ADDBA_sent[priority]) { + pstat->ADDBA_req_num[priority]++; + SMP_UNLOCK_XMIT(flags); + issue_ADDBAreq(priv, pstat, priority); + SMP_LOCK_XMIT(flags); + pstat->ADDBA_sent[priority]++; + } + } + } + } + else + { + // if group key not set yet, don't let unencrypted multicast go to air + if (priv->pmib->dot11GroupKeysTable.dot11Privacy) { + if (GET_GROUP_ENCRYP_KEYLEN == 0) { + DEBUG_ERR("TX DROP: group key not set yet!\n"); + return FALSE; + } + } + + txcfg->privacy = get_mcast_privacy(priv, &txcfg->iv, &txcfg->icv, &txcfg->mic); +#if defined(CONFIG_WLAN_HAL) + if (IS_HAL_CHIP(priv)) { + if (OPMODE & WIFI_AP_STATE) { +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) + txcfg->q_num = HIGH_QUEUE; + else if (priv->vap_init_seq == 1) + txcfg->q_num = HIGH_QUEUE1; + else if (priv->vap_init_seq == 2) + txcfg->q_num = HIGH_QUEUE2; + else if (priv->vap_init_seq == 3) + txcfg->q_num = HIGH_QUEUE3; + else if (priv->vap_init_seq == 4) + txcfg->q_num = HIGH_QUEUE4; + else if (priv->vap_init_seq == 5) + txcfg->q_num = HIGH_QUEUE5; + else if (priv->vap_init_seq == 6) + txcfg->q_num = HIGH_QUEUE6; + else if (priv->vap_init_seq == 7) + txcfg->q_num = HIGH_QUEUE7; +#else + txcfg->q_num = HIGH_QUEUE; +#endif + SetMData(txcfg->phdr); + } else { + // to do: sta mode? + txcfg->q_num = BE_QUEUE; + pskb->cb[1] = 0; + } + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + if ((OPMODE & WIFI_AP_STATE) && priv->pkt_in_dtimQ) { + txcfg->q_num = MCAST_QNUM; + SetMData(txcfg->phdr); + } + else { + txcfg->q_num = BE_QUEUE; + pskb->cb[1] = 0; + } + } + + if ((*da) == 0xff) // broadcast + txcfg->tx_rate = find_rate(priv, NULL, 0, 1); + else { // multicast + if (priv->pmib->dot11StationConfigEntry.lowestMlcstRate) + txcfg->tx_rate = get_rate_from_bit_value(priv->pmib->dot11StationConfigEntry.lowestMlcstRate); + else + txcfg->tx_rate = find_rate(priv, NULL, 1, 1); + } + +#ifdef _11s_TEST_MODE_ + mesh_debug_tx4(priv, txcfg); +#endif + + txcfg->lowest_tx_rate = txcfg->tx_rate; + txcfg->fixed_rate = 1; + } + } +#ifdef _11s_TEST_MODE_ /*---11s mgt frame---*/ + else if (txcfg->is_11s) + mesh_debug_tx6(priv, txcfg); +#endif + + if (!da) + { + // This is non data frame, no need to frag. +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s) + da = GetAddr1Ptr(txcfg->phdr); + else +#endif + da = get_da((unsigned char *) (txcfg->phdr)); + + txcfg->frg_num = 1; + + if (IS_MCAST(da)) + txcfg->need_ack = 0; + else + txcfg->need_ack = 1; + + if (GetPrivacy(txcfg->phdr)) + { +#ifdef CONFIG_IEEE80211W + if (txcfg->isPMF) { + txcfg->privacy = _CCMP_PRIVACY_; + txcfg->iv = 8; + txcfg->icv = 0; + txcfg->mic = 8; + } else +#endif + { + // only auth with legacy wep... + txcfg->iv = 4; + txcfg->icv = 4; + txcfg->privacy = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + } + } + +#ifdef DRVMAC_LB + if (GetFrameType(txcfg->phdr) == WIFI_MGT_TYPE) +#endif + if (txcfg->fr_len != 0) //for mgt frame + txcfg->hdr_len += WLAN_HDR_A3_LEN; + } + +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_AP_STATE) || (OPMODE & WIFI_ADHOC_STATE)) +#else + if (OPMODE & WIFI_AP_STATE) +#endif + { + if (IS_MCAST(da)) + { + txcfg->frg_num = 1; + txcfg->need_ack = 0; + txcfg->rts_thrshld = 10000; + } + else if(!(txcfg->phdr && (GetFrameType(txcfg->phdr) == WIFI_MGT_TYPE) && (GetFrameSubType((unsigned char *) (txcfg->phdr))>>4 == 5))) // exclude probe rsp + { + pstat = get_stainfo(priv, da); + txcfg->pstat = pstat; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + if ((txcfg->fr_type == _SKB_FRAME_TYPE_) || // skb frame + !memcmp(GetAddr1Ptr(txcfg->phdr), BSSID, MACADDRLEN)) { // mgt frame to AP + pstat = get_stainfo(priv, BSSID); + txcfg->pstat = pstat; + } + } +#endif + +#ifdef BEAMFORMING_SUPPORT + if((priv->pmib->dot11RFEntry.txbf == 1) && (pstat) && + ((pstat->ht_cap_len && (pstat->ht_cap_buf.txbf_cap)) +#ifdef RTK_AC_SUPPORT + ||(pstat->vht_cap_len && (cpu_to_le32(pstat->vht_cap_buf.vht_cap_info) & BIT(SU_BFEE_S))) +#endif + )) + Beamforming_GidPAid(priv, pstat); +#endif + if (txcfg->privacy == _TKIP_PRIVACY_) + txcfg->fr_len += 8; // for Michael padding. + + txcfg->frag_thrshld -= (txcfg->mic + txcfg->iv + txcfg->icv + txcfg->hdr_len); + + if (txcfg->frg_num == 0) + { + if (txcfg->aggre_en > 0) + txcfg->frg_num = 1; + else { + // how many mpdu we need... + int llc; + + if ((ntohs(*((UINT16 *)((UINT8 *)pskb->data + ETH_ALEN*2))) + WLAN_ETHHDR_LEN) > WLAN_MAX_ETHFRM_LEN) + llc = sizeof(struct llc_snap); + else + llc = 0; + + txcfg->frg_num = (txcfg->fr_len + llc) / txcfg->frag_thrshld; + if (((txcfg->fr_len + llc) % txcfg->frag_thrshld) != 0) + txcfg->frg_num += 1; + } + } + +#ifdef TX_SCATTER + if (pskb && pskb->list_num > 0 && txcfg->frg_num > 1) { + struct sk_buff *newskb = copy_skb(pskb); + if (newskb == NULL) { + DEBUG_ERR("TX DROP: Can't copy the skb for list buffer in frag!\n"); + return FALSE; + } + dev_kfree_skb_any(pskb); + txcfg->pframe = (void *)newskb; + } +#endif + + return TRUE; +} +#endif // CONFIG_PCI_HCI + +/*------------------------------------------------------------------------------- +tx flow: + Please refer to design spec for detail flow + +rtl8192cd_firetx: check if hw desc is available for tx + hdr_len, iv,icv, tx_rate info are available + +signin_txdesc: fillin the desc and txpoll is necessary +--------------------------------------------------------------------------------*/ +int __rtl8192cd_firetx(struct rtl8192cd_priv *priv, struct tx_insn* txcfg) +{ + int *tx_head=NULL, *tx_tail=NULL, q_num; + unsigned int val32=0, is_dhcp=0; + struct sk_buff *pskb=NULL; + struct llc_snap *pllc_snap; + struct wlan_ethhdr_t *pethhdr=NULL; +#ifdef SUPPORT_TX_AMSDU + struct wlan_ethhdr_t *pmsdu_hdr; + struct wlan_ethhdr_t pethhdr_data; +#endif + struct rtl8192cd_hw *phw = GET_HW(priv); +#ifdef CONFIG_WLAN_HAL +#ifndef TRXBD_CACHABLE_REGION + PHCI_TX_DMA_MANAGER_88XX ptx_dma; +#endif +#endif + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + unsigned int txdesc_need = 1, ret_txdesc = 0; +#endif + unsigned long x; + unsigned char *da; +#if defined(CONFIG_RTL_WAPI_SUPPORT) + struct wlan_ethhdr_t ethhdr; + pethhdr = ðhdr; +#endif + +#ifdef CONFIG_PCI_HCI + /*---frag_thrshld setting---plus tune---0115*/ +#ifdef WDS + if (txcfg->wdsIdx >= 0){ + txcfg->frag_thrshld = 2346; // if wds, disable fragment + }else +#endif +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s){ + txcfg->frag_thrshld = 2346; // if Mesh case, disable fragment + }else +#endif + { + txcfg->frag_thrshld = FRAGTHRSLD - _CRCLNG_; + } + /*---frag_thrshld setting---end*/ + + txcfg->rts_thrshld = RTSTHRSLD; + txcfg->frg_num = 0; + +#ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS && + GET_ROOT(priv)->pmib->dot11DFSEntry.disable_tx + && (priv->site_survey) + && (priv->site_survey->hidden_ap_found != HIDE_AP_FOUND_DO_ACTIVE_SSAN)) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: DFS probation period\n"); + + if (txcfg->fr_type == _SKB_FRAME_TYPE_) { + rtl_kfree_skb(priv, (struct sk_buff *)txcfg->pframe, _SKB_TX_); + release_wlanllchdr_to_poll(priv, txcfg->phdr); + } else if (txcfg->fr_type == _PRE_ALLOCMEM_) { + release_mgtbuf_to_poll(priv, txcfg->pframe); + release_wlanhdr_to_poll(priv, txcfg->phdr); + } else if (txcfg->fr_type == _PRE_ALLOCHDR_) { + release_wlanhdr_to_poll(priv, txcfg->phdr); + } + + return SUCCESS; + } +#endif + + if ((check_txdesc(priv, txcfg)) == FALSE) // this will only happen in errorous forwarding + { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: check_txdesc Fail \n"); + // Don't need to print "TX DROP", already print in check_txdesc() + if (txcfg->fr_type == _SKB_FRAME_TYPE_) { + rtl_kfree_skb(priv, (struct sk_buff *)txcfg->pframe, _SKB_TX_); + release_wlanllchdr_to_poll(priv, txcfg->phdr); + } + else if (txcfg->fr_type == _PRE_ALLOCMEM_) { + release_mgtbuf_to_poll(priv, txcfg->pframe); + release_wlanhdr_to_poll(priv, txcfg->phdr); + } else if (txcfg->fr_type == _PRE_ALLOCHDR_) { + release_wlanhdr_to_poll(priv, txcfg->phdr); + } + return SUCCESS; + } + + if (txcfg->aggre_en > 0) + txcfg->frag_thrshld = 2346; + + if (txcfg->aggre_en < FG_AGGRE_MSDU_FIRST) { + // now we are going to calculate how many hw desc we should have before tx... + // wlan_hdr(including iv and llc) will occupy one desc, payload will occupy one, and + // icv/mic will occupy the third desc if swcrypto is utilized. + q_num = txcfg->q_num; +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + val32 = txcfg->frg_num; + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + { + tx_head = get_txhead_addr(phw, q_num); + tx_tail = get_txtail_addr(phw, q_num); + } + + + if (txcfg->privacy) + { + if ( + #if defined(CONFIG_RTL_WAPI_SUPPORT) + (_WAPI_SMS4_ != txcfg->privacy) && + #endif +#ifdef CONFIG_IEEE80211W + UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF)) +#else + UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) +#endif + + val32 = txcfg->frg_num * 3; //extra one is for ICV padding. + else + val32 = txcfg->frg_num * 2; + } + else { + val32 = txcfg->frg_num * 2; + } + +#ifdef TX_SCATTER + if (txcfg->fr_type == _SKB_FRAME_TYPE_ && + ((struct sk_buff *)txcfg->pframe)->key > 0 && + ((struct sk_buff *)txcfg->pframe)->list_num > 1) + val32 += ((struct sk_buff *)txcfg->pframe)->list_num -1; +#endif + } + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if(GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc && txcfg->fr_type == _SKB_FRAME_TYPE_) { + if (check_txdesc_dynamic_mechanism(priv, q_num, val32)) { +#ifdef USE_TXQUEUE + if (GET_ROOT(priv)->pmib->miscEntry.use_txq && priv->pshare->iot_mode_enable) { + SMP_LOCK_XMIT(x); + if (priv->pshare->txq_isr) { + append_skb_to_txq_head(&priv->pshare->txq_list[q_num], priv, txcfg->pframe, priv->dev, &priv->pshare->txq_pool); + priv->pshare->txq_stop = 1; + } else { + append_skb_to_txq_tail(&priv->pshare->txq_list[q_num], priv, txcfg->pframe, priv->dev, &priv->pshare->txq_pool); + } + if (txcfg->phdr) + release_wlanllchdr_to_poll(priv, txcfg->phdr); + priv->use_txq_cnt[q_num]++; + priv->pshare->txq_check = 1; + SMP_UNLOCK_XMIT(x); + return SUCCESS; + } + else +#endif + { + DEBUG_WARN("%d hw Queue desc exceed available count: used:%d\n", q_num,priv->use_txdesc_cnt[q_num]); + return CONGESTED; + } + } + txdesc_need = val32; + } else +#endif + { +#ifdef CONFIG_WLAN_HAL +#ifndef TRXBD_CACHABLE_REGION + if (IS_HAL_CHIP(priv)) { + ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + } +#endif +#endif + SMP_LOCK_XMIT(x); + if ( +#ifdef CONFIG_WLAN_HAL + IS_HAL_CHIP(priv)? (compareAvailableTXBD(priv, val32+1, q_num, 2)) : +#endif + ((val32 + 2) > CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC)) //per mpdu, we need 2 desc... + ){ + // 2 is for spare... +#ifdef USE_TXQUEUE + if (txcfg->fr_type == _SKB_FRAME_TYPE_ && GET_ROOT(priv)->pmib->miscEntry.use_txq && priv->pshare->iot_mode_enable) { + if (priv->pshare->txq_isr) { + append_skb_to_txq_head(&priv->pshare->txq_list[q_num], priv, txcfg->pframe, priv->dev, &priv->pshare->txq_pool); + priv->pshare->txq_stop = 1; + } else { + append_skb_to_txq_tail(&priv->pshare->txq_list[q_num], priv, txcfg->pframe, priv->dev, &priv->pshare->txq_pool); + } + if (txcfg->phdr) + release_wlanllchdr_to_poll(priv, txcfg->phdr); + priv->pshare->txq_check = 1; + SMP_UNLOCK_XMIT(x); + return SUCCESS; + } + else +#endif + { + // Marked by SC, may cause crash. + //DEBUG_ERR("%d hw Queue desc not available! head=%d, tail=%d request %d\n",q_num,*tx_head,*tx_tail,val32); + SMP_UNLOCK_XMIT(x); + return CONGESTED; + } + } + SMP_UNLOCK_XMIT(x); + } + } else { + q_num = txcfg->q_num; + } + + // then we have to check if wlan-hdr is available for usage... + // actually, the checking can be void + + /* ---------- + Actually, I believe the check below is redundant. + Since at this moment, desc is available, hdr/icv/ + should be enough. + --------------*/ + val32 = txcfg->frg_num; + + if (val32 >= priv->pshare->pwlan_hdr_poll->count) + { + DEBUG_ERR("%d hw Queue tx without enough wlan_hdr\n", q_num); + return CONGESTED; + } +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + switch( rtw_xmit_decision(priv, txcfg) ) { + case XMIT_DECISION_ENQUEUE: + return SUCCESS; + case XMIT_DECISION_STOP: + return CONGESTED; + case XMIT_DECISION_CONTINUE: + break; + } + + if (update_txinsn_stage2(priv, txcfg) == FALSE) { + return CONGESTED; + } + + q_num = txcfg->q_num; +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + + // then we have to check if wlan_snapllc_hdrQ is enough for use + // for each msdu, we need wlan_snapllc_hdrQ for maximum + + if (txcfg->fr_type == _SKB_FRAME_TYPE_) + { + pskb = (struct sk_buff *)txcfg->pframe; + +#ifdef CONFIG_PCI_HCI + if ((OPMODE & WIFI_AP_STATE) && pskb && (isDHCPpkt(pskb) == TRUE)) + is_dhcp++; +#endif + +#ifdef SUPPORT_TX_AMSDU + // for AMSDU + if (txcfg->aggre_en >= FG_AGGRE_MSDU_FIRST) { + unsigned short usLen; + int msdu_len; + + memcpy(&pethhdr_data, pskb->data, sizeof(struct wlan_ethhdr_t)); + pethhdr = &pethhdr_data; + msdu_len = pskb->len - WLAN_ETHHDR_LEN; + if ((ntohs(pethhdr->type) + WLAN_ETHHDR_LEN) > WLAN_MAX_ETHFRM_LEN) { + if (skb_headroom(pskb) < sizeof(struct llc_snap)) { + struct sk_buff *skb2 = dev_alloc_skb(pskb->len); + if (skb2 == NULL) { + printk("%s: %s, dev_alloc_skb() failed!\n", priv->dev->name, __FUNCTION__); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + if(txcfg->aggre_en == FG_AGGRE_MSDU_FIRST) + release_wlanllchdr_to_poll(priv, txcfg->phdr); + return 0; + } + memcpy(skb_put(skb2, pskb->len), pskb->data, pskb->len); + dev_kfree_skb_any(pskb); + pskb = skb2; + txcfg->pframe = (void *)pskb; + } + skb_push(pskb, sizeof(struct llc_snap)); + } + pmsdu_hdr = (struct wlan_ethhdr_t *)pskb->data; + + memcpy(pmsdu_hdr, pethhdr, 12); + if ((ntohs(pethhdr->type) + WLAN_ETHHDR_LEN) > WLAN_MAX_ETHFRM_LEN) { + usLen = (unsigned short)(msdu_len + sizeof(struct llc_snap)); + pmsdu_hdr->type = htons(usLen); + eth_2_llc(pethhdr, (struct llc_snap *)(((unsigned long)pmsdu_hdr)+sizeof(struct wlan_ethhdr_t))); + } + else { + usLen = (unsigned short)msdu_len; + pmsdu_hdr->type = htons(usLen); + } + + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST) + eth2_2_wlanhdr(priv, pethhdr, txcfg); + + txcfg->llc = 0; + pllc_snap = NULL; + + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST || txcfg->aggre_en == FG_AGGRE_MSDU_MIDDLE) { + if ((usLen+14) % 4) + skb_put(pskb, 4-((usLen+14)%4)); + } + txcfg->fr_len = pskb->len; + } + else +#endif /* SUPPORT_TX_AMSDU */ + { // not A-MSDU +#if defined(CONFIG_SDIO_HCI) && defined(TX_SCATTER) + // in case 1st buffer len is 14, we get ether header pointer first and then ajust the skb + pethhdr = (struct wlan_ethhdr_t *)(pskb->data); + // now, we should adjust the skb ... + skb_pull(pskb, WLAN_ETHHDR_LEN); +#else + // now, we should adjust the skb ... + skb_pull(pskb, WLAN_ETHHDR_LEN); +#ifdef CONFIG_RTK_MESH + pethhdr = &priv->ethhdr; + memcpy(pethhdr, pskb->data - sizeof(struct wlan_ethhdr_t), sizeof(struct wlan_ethhdr_t)); +#else + pethhdr = (struct wlan_ethhdr_t *)(pskb->data - sizeof(struct wlan_ethhdr_t)); +#endif +#endif + pllc_snap = (struct llc_snap *)((UINT8 *)(txcfg->phdr) + txcfg->hdr_len + txcfg->iv); + + if ((ntohs(pethhdr->type) + WLAN_ETHHDR_LEN) > WLAN_MAX_ETHFRM_LEN) { + eth_2_llc(pethhdr, pllc_snap); + txcfg->llc = sizeof(struct llc_snap); + } + else + { + pllc_snap = NULL; + } + + eth2_2_wlanhdr(priv, pethhdr, txcfg); + +#ifdef CONFIG_PCI_HCI +#ifdef TX_SCATTER + if (pskb->len == 0 && pskb->list_num > 1) { + pskb->list_idx++; + skb_assign_buf(pskb, pskb->list_buf[pskb->list_idx].buf, pskb->list_buf[pskb->list_idx].len); + pskb->len = pskb->list_buf[pskb->list_idx].len; + } +#endif +#endif + +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s&1 && GetFrameSubType(txcfg->phdr) == WIFI_11S_MESH) + { + const short meshhdrlen= (txcfg->mesh_header.mesh_flag & 0x01) ? 16 : 4; + if (skb_cloned(pskb)) + { + struct sk_buff *newskb = skb_copy(pskb, GFP_ATOMIC); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + if (newskb == NULL) { + priv->ext_stats.tx_drops++; + release_wlanllchdr_to_poll(priv, txcfg->phdr); + DEBUG_ERR("TX DROP: Can't copy the skb!\n"); + return SUCCESS; + } + txcfg->pframe = pskb = newskb; +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); +#endif + } + memcpy(skb_push(pskb,meshhdrlen), &(txcfg->mesh_header), meshhdrlen); + txcfg->fr_len += meshhdrlen; + } +#endif // CONFIG_RTK_MESH + } + + // TODO: modify as when skb is not bigger enough, take ICV from local pool +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (txcfg->privacy == _WAPI_SMS4_) + { + if ((pskb->tail + SMS4_MIC_LEN) > pskb->end) + { + struct sk_buff *pnewskb; + + pnewskb = skb_copy_expand(pskb, skb_headroom(pskb), SMS4_MIC_LEN, GFP_ATOMIC); + if (NULL == pnewskb) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: an over size skb!\n"); + rtl_kfree_skb(priv, (struct sk_buff *)txcfg->pframe, _SKB_TX_); + release_wlanllchdr_to_poll(priv, txcfg->phdr); + return SUCCESS; + } + + dev_kfree_skb_any(pskb); + pskb = pnewskb; + txcfg->pframe = pskb; +#ifndef CONFIG_RTK_MESH + if (txcfg->aggre_en < FG_AGGRE_MSDU_FIRST) + pethhdr = (struct wlan_ethhdr_t *)(pskb->data - sizeof(struct wlan_ethhdr_t)); +#endif + } + memcpy(ðhdr, pethhdr, sizeof(struct wlan_ethhdr_t)); +#ifdef MCAST2UI_REFINE + memcpy(ðhdr.daddr, &pskb->cb[10], 6); +#endif + pethhdr = ðhdr; + } else +#endif + + if (txcfg->privacy == _TKIP_PRIVACY_) + { + if ((pskb->tail + 8) > pskb->end) + { +#ifndef NOT_RTK_BSP + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: an over size skb!\n"); + rtl_kfree_skb(priv, (struct sk_buff *)txcfg->pframe, _SKB_TX_); + release_wlanllchdr_to_poll(priv, txcfg->phdr); + return SUCCESS; + +#else // NOT_RTK_BSP + struct sk_buff *pnewskb; + + pnewskb = skb_copy_expand(pskb, skb_headroom(pskb), 8, GFP_ATOMIC); + if (NULL == pnewskb) { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: an over size skb!\n"); + rtl_kfree_skb(priv, (struct sk_buff *)txcfg->pframe, _SKB_TX_); + release_wlanllchdr_to_poll(priv, txcfg->phdr); + return SUCCESS; + } + + dev_kfree_skb_any(pskb); + pskb = pnewskb; + txcfg->pframe = pskb; +#ifndef CONFIG_RTK_MESH + if (txcfg->aggre_en < FG_AGGRE_MSDU_FIRST) + pethhdr = (struct wlan_ethhdr_t *)(pskb->data - sizeof(struct wlan_ethhdr_t)); +#endif +#endif + } + + da = pethhdr->daddr; +#ifdef MCAST2UI_REFINE + memcpy(pethhdr->daddr, &pskb->cb[10], 6); +#endif + +#ifdef A4_STA + if(txcfg->pstat && (txcfg->pstat->state & WIFI_A4_STA)) { + da = GetAddr3Ptr(txcfg->phdr); + } +#endif + +#ifdef WIFI_WMM + if ((tkip_mic_padding(priv, da, pethhdr->saddr, ((QOS_ENABLE) && (txcfg->pstat) && (txcfg->pstat->QosEnabled))?pskb->cb[1]:0, (UINT8 *)pllc_snap, + pskb, txcfg)) == FALSE) +#else + if ((tkip_mic_padding(priv, da, pethhdr->saddr, 0, (UINT8 *)pllc_snap, + pskb, txcfg)) == FALSE) +#endif + { + priv->ext_stats.tx_drops++; + DEBUG_ERR("TX DROP: Tkip mic padding fail!\n"); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + release_wlanllchdr_to_poll(priv, txcfg->phdr); + return SUCCESS; + } + if ((txcfg->aggre_en < FG_AGGRE_MSDU_FIRST) || (txcfg->aggre_en == FG_AGGRE_MSDU_LAST)) + skb_put((struct sk_buff *)txcfg->pframe, 8); + } + } + + if (txcfg->privacy && txcfg->aggre_en <= FG_AGGRE_MSDU_FIRST) + SetPrivacy(txcfg->phdr); + + // log tx statistics... +#ifdef CONFIG_RTL8672 + tx_sum_up(priv, txcfg->pstat, txcfg->fr_len+txcfg->hdr_len+txcfg->iv+txcfg->llc+txcfg->mic+txcfg->icv, txcfg); +#else + tx_sum_up(priv, txcfg->pstat, txcfg->fr_len+txcfg->hdr_len+txcfg->iv+txcfg->llc+txcfg->mic+txcfg->icv); +#endif + SNMP_MIB_INC(dot11TransmittedFragmentCount, 1); + + // for SW LED + if (txcfg->aggre_en > FG_AGGRE_MSDU_FIRST || GetFrameType(txcfg->phdr) == WIFI_DATA_TYPE) { + priv->pshare->LED_tx_cnt++; + } else { + if (priv->pshare->LED_cnt_mgn_pkt) + priv->pshare->LED_tx_cnt++; + } + +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, (POWER_DOWN_T0)); +#endif + + SAVE_INT_AND_CLI(x); + SMP_LOCK_XMIT(x); + +#ifdef SUPPORT_TX_AMSDU + if (txcfg->aggre_en == FG_AGGRE_MSDU_MIDDLE || txcfg->aggre_en == FG_AGGRE_MSDU_LAST) { +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) { + priv->use_txdesc_cnt[q_num] += 1; + if (rtl8192cd_signin_txdesc_amsdu(priv, txcfg)) + priv->use_txdesc_cnt[q_num] -= 1; + } else +#endif + { + rtl8192cd_signin_txdesc_amsdu(priv, txcfg); + } + } else +#endif + { +#ifdef _11s_TEST_MODE_ + signin_txdesc_galileo(priv, txcfg); +#else +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) { + priv->use_txdesc_cnt[q_num] += txdesc_need; + if ( +#ifdef CONFIG_WLAN_HAL + IS_HAL_CHIP(priv) ? ((ret_txdesc = rtl88XX_signin_txdesc(priv, txcfg)) != 0 ): +#endif + ((ret_txdesc = rtl8192cd_signin_txdesc(priv, txcfg)) != 0 ) + ){ + if (txcfg->privacy && +#if defined(CONFIG_RTL_WAPI_SUPPORT) + (_WAPI_SMS4_ != txcfg->privacy) && +#endif +#ifdef CONFIG_IEEE80211W + UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE), txcfg->isPMF)) +#else + UseSwCrypto(priv, txcfg->pstat, (txcfg->pstat ? FALSE : TRUE))) +#endif + priv->use_txdesc_cnt[q_num] -= 3 * ret_txdesc; + else + priv->use_txdesc_cnt[q_num] -= 2 * ret_txdesc; + } + } else +#endif + { +#if defined(CONFIG_PCI_HCI) +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + // TODO: these if conditions are all the same as the following code, it should be optimzed..... + if((!priv->pmib->dot11OperationEntry.disable_txsc) && + (txcfg->fr_type == _SKB_FRAME_TYPE_) && + (txcfg->pstat) && + (txcfg->frg_num == 1) && + ((txcfg->privacy == 0) +#ifdef CONFIG_IEEE80211W + || (!UseSwCrypto(priv, txcfg->pstat, FALSE, txcfg->isPMF))) && +#else + || (!UseSwCrypto(priv, txcfg->pstat, FALSE))) && +#endif + (pethhdr->type != htons(0x888e)) && + !is_dhcp && + !GetMData(txcfg->phdr) && + #ifdef MCAST2UI_REFINE + pskb && !IS_MCAST(&pskb->cb[10]) && + #else + !IS_MCAST((unsigned char *)pethhdr) && + #endif + (txcfg->aggre_en < FG_AGGRE_MSDU_FIRST) + ) { + rtl88XX_signin_txdesc(priv, txcfg, HW_TX_SC_BACKUP_HEADER); + } else { + rtl88XX_signin_txdesc(priv, txcfg, HW_TX_SC_NORMAL); + } + + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + rtl8192cd_signin_txdesc(priv, txcfg); + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + rtl8192cd_signin_txdesc(priv, txcfg, pethhdr); +#endif + } +#endif + } + + SMP_UNLOCK_XMIT(x); + RESTORE_INT(x); + +#ifdef CONFIG_PCI_HCI +#ifdef TX_SHORTCUT + if ((!priv->pmib->dot11OperationEntry.disable_txsc) && + (txcfg->fr_type == _SKB_FRAME_TYPE_) && + (txcfg->pstat) && + (txcfg->frg_num == 1) && + ((txcfg->privacy == 0) +#ifdef CONFIG_RTL_WAPI_SUPPORT + || (txcfg->privacy == _WAPI_SMS4_) +#endif +#ifdef CONFIG_IEEE80211W + || !UseSwCrypto(priv, txcfg->pstat, FALSE, txcfg->isPMF)) && +#else + || !UseSwCrypto(priv, txcfg->pstat, FALSE)) && +#endif + /*(!IEEE8021X_FUN || + (IEEE8021X_FUN && (txcfg->pstat->ieee8021x_ctrlport == 1) && + (pethhdr->type != htons(0x888e)))) && */ + (pethhdr->type != htons(0x888e)) && + !is_dhcp && +#ifdef CONFIG_RTL_WAPI_SUPPORT + (pethhdr->type != htons(ETH_P_WAPI)) && +#endif + !GetMData(txcfg->phdr) && +#ifdef A4_STA + ((txcfg->pstat && txcfg->pstat->state & WIFI_A4_STA) + ||!IS_MCAST((unsigned char *)pethhdr)) && +#else +#ifdef MCAST2UI_REFINE + ( +#ifdef WDS + (txcfg->pstat->state & WIFI_WDS)? (!IS_BCAST2((unsigned char *)pethhdr)) : +#endif + (pskb && !IS_MCAST(&pskb->cb[10])))&& +#else + ( +#ifdef WDS + (txcfg->pstat->state & WIFI_WDS)? (!IS_BCAST2((unsigned char *)pethhdr)) : +#endif + (!IS_MCAST((unsigned char *)pethhdr))) && +#endif +#endif + (txcfg->aggre_en < FG_AGGRE_MSDU_FIRST) + ) + { + int i = get_tx_sc_index(priv, txcfg->pstat, (unsigned char *)pethhdr); + if (i >= 0) { + memcpy(&txcfg->pstat->tx_sc_ent[i].txcfg, txcfg, sizeof(struct tx_insn)); + memcpy((void *)&txcfg->pstat->tx_sc_ent[i].wlanhdr, txcfg->phdr, sizeof(struct wlanllc_hdr)); + } + } + else { + if (txcfg->pstat && pethhdr) { + int i = get_tx_sc_index(priv, txcfg->pstat, (unsigned char *)pethhdr); + if (i >= 0) { + txcfg->pstat->tx_sc_ent[i].txcfg.fr_len = 0; +#ifdef TX_SCATTER + txcfg->pstat->tx_sc_ent[i].has_desc3 = 0; +#endif + } + } + } +#endif +#endif // CONFIG_PCI_HCI + + return SUCCESS; +} + +#ifdef CONFIG_PCI_HCI +int rtl8192cd_firetx(struct rtl8192cd_priv *priv, struct tx_insn* txcfg) +{ +#ifdef RX_TASKLET +#ifndef SMP_SYNC + unsigned long x; +#endif + int ret; + + SAVE_INT_AND_CLI(x); + + ret = __rtl8192cd_firetx(priv, txcfg); + + RESTORE_INT(x); + return ret; +#else + return (__rtl8192cd_firetx(priv, txcfg)); +#endif +} +#endif // CONFIG_PCI_HCI + + +#ifdef CONFIG_PCI_HCI +#ifdef CONFIG_WLAN_HAL +static int +rtl88XX_tx_recycle( + struct rtl8192cd_priv *priv, + unsigned int txRingIdx, + int *recycleCnt_p +) +{ + int cnt = 0; + struct tx_desc_info *pdescinfoH, *pdescinfo; + // TODO: int or u2Byte ? + //volatile int head, tail; + volatile u2Byte head, tail; + int needRestartQueue = 0; + int recycleCnt = 0; + unsigned int halQnum = GET_HAL_INTERFACE(priv)->MappingTxQueueHandler(priv, txRingIdx); + PHCI_TX_DMA_MANAGER_88XX ptx_dma; + + ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + head = GET_HAL_INTERFACE(priv)->GetTxQueueHWIdxHandler(priv, txRingIdx); + tail = ptx_dma->tx_queue[halQnum].hw_idx; + + pdescinfoH = get_txdesc_info(priv->pshare->pdesc_info, txRingIdx); + + while (CIRC_CNT_RTK(head, tail, ptx_dma->tx_queue[halQnum].total_txbd_num)) + { + pdescinfo = pdescinfoH + (tail); + +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if (IS_PCIBIOS_TYPE) { + if (_RESERVED_FRAME_TYPE_ != pdescinfo->type) { + pci_unmap_single(priv->pshare->pdev, pdescinfo->paddr, pdescinfo->len, PCI_DMA_TODEVICE); + } + } +#endif + + if (pdescinfo->type == _SKB_FRAME_TYPE_) + { +#ifdef MP_TEST + if (OPMODE & WIFI_MP_CTX_BACKGROUND) { + #if 0 + printk("skb_tail: 0x%x, skb_head: 0x%x\n", + priv->pshare->skb_tail, + priv->pshare->skb_head + ); + #endif + + struct sk_buff *skb = (struct sk_buff *)(pdescinfo->pframe); + skb->data = skb->head; + skb->tail = skb->data; + skb->len = 0; + priv->pshare->skb_tail = (priv->pshare->skb_tail + 1) & (NUM_MP_SKB - 1); + } + else +#endif + { +#ifdef __LINUX_2_6__ + rtl_kfree_skb(pdescinfo->priv, (struct sk_buff *)(pdescinfo->pframe), _SKB_TX_IRQ_); +#else +// for debug ------------ +// rtl_kfree_skb(pdescinfo->priv, (struct sk_buff *)(pdescinfo->pframe), _SKB_TX_IRQ_); + if (pdescinfo->pframe) { + if (((struct sk_buff *)pdescinfo->pframe)->list) { + DEBUG_ERR("Free tx skb error, skip it!\n"); + priv->ext_stats.freeskb_err++; + } + else { + rtl_kfree_skb(pdescinfo->priv, (struct sk_buff *)(pdescinfo->pframe), _SKB_TX_IRQ_); + } + } +#endif + needRestartQueue = 1; + } + } + else if (pdescinfo->type == _PRE_ALLOCMEM_) + { + release_mgtbuf_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _PRE_ALLOCHDR_) + { + release_wlanhdr_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _PRE_ALLOCLLCHDR_) + { + release_wlanllchdr_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _PRE_ALLOCICVHDR_) + { + release_icv_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _PRE_ALLOCMICHDR_) + { + release_mic_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _RESERVED_FRAME_TYPE_) + { + // the chained skb, no need to release memory + } + else + { + DEBUG_ERR("Unknown tx frame type %d\n", pdescinfo->type); + } + + //Reset to default value + pdescinfo->type = _RESERVED_FRAME_TYPE_; + // for skb buffer free + pdescinfo->pframe = NULL; + + recycleCnt++; + + for (cnt =0; cntbuf_type[cnt]) { + //use the paddr and flen of pdesc field for icv, mic case which doesn't fill the pdescinfo + pci_unmap_single(priv->pshare->pdev, + pdescinfo->buf_paddr[cnt],//payload + pdescinfo->buf_len[cnt], + PCI_DMA_TODEVICE); + } + } +#endif + //if (txRingIdx == 2) + //panic_printk("buf type[%d]=%d\n", cnt, pdescinfo->buf_type[cnt]); + + if (pdescinfo->buf_type[cnt] == _SKB_FRAME_TYPE_) + { +#ifdef MP_TEST + if (OPMODE & WIFI_MP_CTX_BACKGROUND) { + struct sk_buff *skb = (struct sk_buff *)(pdescinfo->buf_pframe[cnt]); + skb->data = skb->head; + skb->tail = skb->data; + skb->len = 0; + priv->pshare->skb_tail = (priv->pshare->skb_tail + 1) & (NUM_MP_SKB - 1); + } + else +#endif + { +#ifdef __LINUX_2_6__ + rtl_kfree_skb(pdescinfo->priv, (struct sk_buff *)(pdescinfo->buf_pframe[cnt]), _SKB_TX_IRQ_); +#else +// for debug ------------ +// rtl_kfree_skb(pdescinfo->priv, (struct sk_buff *)(pdescinfo->pframe), _SKB_TX_IRQ_); + if (pdescinfo->buf_pframe[cnt]) { + if (((struct sk_buff *)pdescinfo->buf_pframe[cnt])->list) { + DEBUG_ERR("Free tx skb error, skip it!\n"); + priv->ext_stats.freeskb_err++; + } + else + rtl_kfree_skb(pdescinfo->priv, (struct sk_buff *)(pdescinfo->buf_pframe[cnt]), _SKB_TX_IRQ_); + } +#endif + needRestartQueue = 1; + } + } + else if (pdescinfo->buf_type[cnt] == _PRE_ALLOCMEM_) + { + release_mgtbuf_to_poll(priv, (UINT8 *)(pdescinfo->buf_pframe[cnt])); + } + else if (pdescinfo->buf_type[cnt] == _PRE_ALLOCHDR_) + { + release_wlanhdr_to_poll(priv, (UINT8 *)(pdescinfo->buf_pframe[cnt])); + } + else if (pdescinfo->buf_type[cnt] == _PRE_ALLOCLLCHDR_) + { + release_wlanllchdr_to_poll(priv, (UINT8 *)(pdescinfo->buf_pframe[cnt])); + } + else if (pdescinfo->buf_type[cnt] == _PRE_ALLOCICVHDR_) + { + release_icv_to_poll(priv, (UINT8 *)(pdescinfo->buf_pframe[cnt])); + } + else if (pdescinfo->buf_type[cnt] == _PRE_ALLOCMICHDR_) + { + release_mic_to_poll(priv, (UINT8 *)(pdescinfo->buf_pframe[cnt])); + } + else if (pdescinfo->buf_type[cnt] == _RESERVED_FRAME_TYPE_) + { + // the chained skb, no need to release memory + } + else + { + DEBUG_ERR("Unknown tx frame type %d:%d\n", pdescinfo->buf_type[cnt]); + } + + //Reset to default value + pdescinfo->buf_type[cnt] = _RESERVED_FRAME_TYPE_; + // for skb buffer free + pdescinfo->buf_pframe[cnt] = NULL; + + recycleCnt ++; + } + + tail = (tail + 1) % (ptx_dma->tx_queue[halQnum].total_txbd_num); + ptx_dma->tx_queue[halQnum].avail_txbd_num++; + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + // TODO: + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) + pdescinfo->priv->use_txdesc_cnt[txRingIdx]--; +#endif + + if (head == tail) + head = GET_HAL_INTERFACE(priv)->GetTxQueueHWIdxHandler(priv, txRingIdx); + } + + + ptx_dma->tx_queue[halQnum].hw_idx = tail; + + if (recycleCnt_p) + *recycleCnt_p = recycleCnt; + + return needRestartQueue; +} +#endif + +/* + Procedure to re-cycle TXed packet in Queue index "txRingIdx" + + => Return value means if system need restart-TX-queue or not. + + 1: Need Re-start Queue + 0: Don't Need Re-start Queue +*/ + +static int rtl8192cd_tx_recycle(struct rtl8192cd_priv *priv, unsigned int txRingIdx, int *recycleCnt_p) +{ + struct tx_desc *pdescH, *pdesc; + struct tx_desc_info *pdescinfoH, *pdescinfo; + volatile int head, tail; + struct rtl8192cd_hw *phw=GET_HW(priv); + int needRestartQueue=0; + int recycleCnt=0; +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + return rtl88XX_tx_recycle(priv, txRingIdx, recycleCnt_p); + } else if (CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + {//not HAL + head = get_txhead(phw, txRingIdx); + tail = get_txtail(phw, txRingIdx); + pdescH = get_txdesc(phw, txRingIdx); + pdescinfoH = get_txdesc_info(priv->pshare->pdesc_info, txRingIdx); + + while (CIRC_CNT_RTK(head, tail, CURRENT_NUM_TX_DESC)) + { + pdesc = pdescH + (tail); + pdescinfo = pdescinfoH + (tail); + +#ifdef __MIPSEB__ + pdesc = (struct tx_desc *)KSEG1ADDR(pdesc); +#endif + + if (!pdesc || (get_desc(pdesc->Dword0) & TX_OWN)) + break; + if (pdescinfo->pframe == NULL) { + DEBUG_ERR("Free Null Buf: head=%d tail=%d recycleCnt=%d RingIdx=%d!\n", head, tail, recycleCnt, txRingIdx); + } + +#ifdef CONFIG_PCI_HCI +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if (IS_PCIBIOS_TYPE) { + //use the paddr and flen of pdesc field for icv, mic case which doesn't fill the pdescinfo +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + pci_unmap_single(priv->pshare->pdev, + get_desc(pdesc->Dword10), + (get_desc(pdesc->Dword7)&0xffff), + PCI_DMA_TODEVICE); + else +#endif + pci_unmap_single(priv->pshare->pdev, + get_desc(pdesc->Dword8), + (get_desc(pdesc->Dword7)&0xffff), + PCI_DMA_TODEVICE); + } +#endif +#endif // CONFIG_PCI_HCI + + if (pdescinfo->type == _SKB_FRAME_TYPE_) + { +#ifdef MP_TEST + if (OPMODE & WIFI_MP_CTX_BACKGROUND) { + struct sk_buff *skb = (struct sk_buff *)(pdescinfo->pframe); + skb->data = skb->head; + skb->tail = skb->data; + skb->len = 0; + priv->pshare->skb_tail = (priv->pshare->skb_tail + 1) & (NUM_MP_SKB - 1); + } + else +#endif + { +#ifdef __LINUX_2_6__ + rtl_kfree_skb(pdescinfo->priv, (struct sk_buff *)(pdescinfo->pframe), _SKB_TX_IRQ_); +#else +// for debug ------------ +// rtl_kfree_skb(pdescinfo->priv, (struct sk_buff *)(pdescinfo->pframe), _SKB_TX_IRQ_); + if (pdescinfo->pframe) { + if (((struct sk_buff *)pdescinfo->pframe)->list) { + DEBUG_ERR("Free tx skb error, skip it!\n"); + priv->ext_stats.freeskb_err++; + } + else + rtl_kfree_skb(pdescinfo->priv, (struct sk_buff *)(pdescinfo->pframe), _SKB_TX_IRQ_); + } +#endif + needRestartQueue = 1; + } + } + else if (pdescinfo->type == _PRE_ALLOCMEM_) + { + release_mgtbuf_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _PRE_ALLOCHDR_) + { + release_wlanhdr_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _PRE_ALLOCLLCHDR_) + { + release_wlanllchdr_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _PRE_ALLOCICVHDR_) + { + release_icv_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _PRE_ALLOCMICHDR_) + { + release_mic_to_poll(priv, (UINT8 *)(pdescinfo->pframe)); + } + else if (pdescinfo->type == _RESERVED_FRAME_TYPE_) + { + // the chained skb, no need to release memory + } + else + { + DEBUG_ERR("Unknown tx frame type %d\n", pdescinfo->type); + } + + // for skb buffer free + pdescinfo->type = _RESERVED_FRAME_TYPE_; + pdescinfo->pframe = NULL; + + recycleCnt ++; + + tail = (tail + 1) % CURRENT_NUM_TX_DESC; + +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) + pdescinfo->priv->use_txdesc_cnt[txRingIdx]--; +#endif + } + + *get_txtail_addr(phw, txRingIdx) = tail; + + if (recycleCnt_p) + *recycleCnt_p = recycleCnt; + + return needRestartQueue; + } //not HAL +#ifdef CONFIG_WLAN_HAL + else { + panic_printk("Shouldn't come here %s()\n", __FUNCTION__); + return 0; + } +#endif +} + + +#ifdef CONFIG_WLAN_HAL +static void rtl88XX_tx_dsr(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned int j=0; + unsigned int restart_queue=0; + struct rtl8192cd_hw *phw=GET_HW(priv); + int needRestartQueue; + int Queue_max = HIGH_QUEUE; + unsigned long flags; + + if (!phw) + return; + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) { + priv->pshare->has_triggered_tx_tasklet = 0; + return; + } +#endif + +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + Queue_max = HIGH_QUEUE7; +#endif + + + SAVE_INT_AND_CLI(flags); + SMP_LOCK_XMIT(flags); + + for(j=0; j<=Queue_max; j++) + { + needRestartQueue = rtl8192cd_tx_recycle(priv, j, NULL); + /* If anyone of queue report the TX queue need to be restart : we would set "restart_queue" to process ALL queues */ + if (needRestartQueue == 1) + restart_queue = 1; + } + + if (restart_queue) + rtl8192cd_tx_restartQueue(priv); + +#ifdef MP_TEST +#if 1//def CONFIG_RTL8672 + if ((OPMODE & (WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND|WIFI_MP_CTX_BACKGROUND_STOPPING)) + ==(WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND)) +#else //CONFIG_RTL8672 + if ((OPMODE & (WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND))==(WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND)) +#endif //CONFIG_RTL8672 + { +#ifdef CONFIG_WLAN_HAL + PHCI_TX_DMA_MANAGER_88XX ptx_dma; +#endif + + RESTORE_INT(flags); + +#ifdef CONFIG_WLAN_HAL + ptx_dma = (PHCI_TX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PTxDMA88XX); + + if (compareAvailableTXBD(priv, (CURRENT_NUM_TX_DESC/2), BE_QUEUE, 1)) { + SMP_UNLOCK_XMIT(flags); + mp_ctx(priv, (unsigned char *)"tx-isr"); + SMP_LOCK_XMIT(flags); + } +#else + int *tx_head, *tx_tail; + + tx_head = get_txhead_addr(phw, BE_QUEUE); + tx_tail = get_txtail_addr(phw, BE_QUEUE); + if (CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC) > (CURRENT_NUM_TX_DESC/2)) + { + SMP_UNLOCK_XMIT(flags); + mp_ctx(priv, (unsigned char *)"tx-isr"); + SMP_LOCK_XMIT(flags); + } +#endif //CONFIG_WLAN_HAL + + SAVE_INT_AND_CLI(flags); + } +#endif + + refill_skb_queue(priv); + +#ifdef USE_TXQUEUE + // TODO: HAL + if (GET_ROOT(priv)->pmib->miscEntry.use_txq && !priv->pshare->txq_isr && priv->pshare->txq_check) + { + int q_num, send_cnt = 0; + priv->pshare->txq_isr = 1; + + for (q_num=6; q_num>=0; q_num--) + { + priv->pshare->txq_stop = 0; + while ( txq_len(&priv->pshare->txq_list[q_num]) > 0 ) + { + struct sk_buff *tmp_skb = NULL; + struct net_device *dev = NULL; + remove_skb_from_txq(&priv->pshare->txq_list[q_num], &tmp_skb, &dev, &priv->pshare->txq_pool); + if (tmp_skb && dev) { +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) + ((struct rtl8192cd_priv*)(dev->priv))->use_txq_cnt[q_num]--; +#endif +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + __rtl8192cd_start_xmit(tmp_skb, dev, TX_NORMAL); + send_cnt++; + if (priv->pshare->txq_stop) break; + } + } + } + + priv->pshare->txq_isr = 0; + + if (send_cnt == 0) + priv->pshare->txq_check = 0; + } +#endif + + priv->pshare->has_triggered_tx_tasklet = 0; + + RESTORE_INT(flags); + SMP_UNLOCK_XMIT(flags); +} +#endif //CONFIG_WLAN_HAL + + +/*----------------------------------------------------------------------------- +Purpose of tx_dsr: + + For ALL TX queues + 1. Free Allocated Buf + 2. Update tx_tail + 3. Update tx related counters + 4. Restart tx queue if needed +------------------------------------------------------------------------------*/ +void rtl8192cd_tx_dsr(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + unsigned int j=0; + unsigned int restart_queue=0; + struct rtl8192cd_hw *phw=GET_HW(priv); + int needRestartQueue; + unsigned long flags; +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)){ + rtl88XX_tx_dsr((unsigned long)priv); + return; + }else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif //CONFIG_WLAN_HAL + {//not HAL + if (!phw) + return; + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) { + priv->pshare->has_triggered_tx_tasklet = 0; + return; + } +#endif + + SAVE_INT_AND_CLI(flags); + SMP_LOCK_XMIT(flags); + for(j=0; j<=HIGH_QUEUE; j++) + { + needRestartQueue = rtl8192cd_tx_recycle(priv, j, NULL); + /* If anyone of queue report the TX queue need to be restart : we would set "restart_queue" to process ALL queues */ + if (needRestartQueue == 1) + restart_queue = 1; + } + + if (restart_queue) + rtl8192cd_tx_restartQueue(priv); + +#ifdef MP_TEST +#if 1//def CONFIG_RTL8672 + if ((OPMODE & (WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND|WIFI_MP_CTX_BACKGROUND_STOPPING)) + ==(WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND)) +#else //CONFIG_RTL8672 + if ((OPMODE & (WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND))==(WIFI_MP_STATE|WIFI_MP_CTX_BACKGROUND)) +#endif //CONFIG_RTL8672 + { + int *tx_head, *tx_tail; + RESTORE_INT(flags); + tx_head = get_txhead_addr(phw, BE_QUEUE); + tx_tail = get_txtail_addr(phw, BE_QUEUE); + if (CIRC_SPACE_RTK(*tx_head, *tx_tail, CURRENT_NUM_TX_DESC) > (CURRENT_NUM_TX_DESC/2)) + { + SMP_UNLOCK_XMIT(flags); + mp_ctx(priv, (unsigned char *)"tx-isr"); + SMP_LOCK_XMIT(flags); + } + SAVE_INT_AND_CLI(flags); + } +#endif + + refill_skb_queue(priv); + +#ifdef USE_TXQUEUE + if (GET_ROOT(priv)->pmib->miscEntry.use_txq && !priv->pshare->txq_isr && priv->pshare->txq_check) + { + int q_num, send_cnt = 0, tx_flag = TX_NORMAL; + priv->pshare->txq_isr = 1; + + for (q_num=6; q_num>=0; q_num--) + { + priv->pshare->txq_stop = 0; + while ( txq_len(&priv->pshare->txq_list[q_num]) > 0 ) + { + struct sk_buff *tmp_skb = NULL; + struct net_device *dev = NULL; + remove_skb_from_txq(&priv->pshare->txq_list[q_num], &tmp_skb, &dev, &priv->pshare->txq_pool); + if (tmp_skb && dev) { +#ifdef RESERVE_TXDESC_FOR_EACH_IF + if (GET_ROOT(priv)->pmib->miscEntry.rsv_txdesc) + ((struct rtl8192cd_priv*)(dev->priv))->use_txq_cnt[q_num]--; +#endif +#ifdef SUPPORT_TX_MCAST2UNI + tx_flag = tmp_skb->cb[16]; +#endif +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + __rtl8192cd_start_xmit(tmp_skb, dev, tx_flag); + send_cnt++; + if (priv->pshare->txq_stop) break; + } + } + } + + priv->pshare->txq_isr = 0; + + if (send_cnt == 0) + priv->pshare->txq_check = 0; + } +#endif + + priv->pshare->has_triggered_tx_tasklet = 0; + + RESTORE_INT(flags); + SMP_UNLOCK_XMIT(flags); +} +} + + +/* + Try to do TX-DSR for only ONE TX-queue ( rtl8192cd_tx_dsr would check for ALL TX queue ) +*/ +int rtl8192cd_tx_queueDsr(struct rtl8192cd_priv *priv, unsigned int txRingIdx) +{ + int recycleCnt; +#ifndef SMP_SYNC + unsigned long flags; +#endif + SAVE_INT_AND_CLI(flags); + + if (rtl8192cd_tx_recycle(priv, txRingIdx, &recycleCnt) == 1) + rtl8192cd_tx_restartQueue(priv); + + RESTORE_INT(flags); + return recycleCnt; +} + + +/* + Procedure to restart TX Queue +*/ +void rtl8192cd_tx_restartQueue(struct rtl8192cd_priv *priv) +{ +#ifdef __KERNEL__ + priv = GET_ROOT(priv); + + if (IS_DRV_OPEN(priv) && netif_queue_stopped(priv->dev)) { + DEBUG_INFO("wake-up Root queue\n"); + netif_wake_queue(priv->dev); + } + +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && netif_queue_stopped(GET_VXD_PRIV(priv)->dev)) { + DEBUG_INFO("wake-up VXD queue\n"); + netif_wake_queue(GET_VXD_PRIV(priv)->dev); + } +#endif + +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + int bssidIdx; + for (bssidIdx=0; bssidIdxpvap_priv[bssidIdx]) && netif_queue_stopped(priv->pvap_priv[bssidIdx]->dev)) { + DEBUG_INFO("wake-up Vap%d queue\n", bssidIdx); + netif_wake_queue(priv->pvap_priv[bssidIdx]->dev); + } + } + } +#endif + +#ifdef CONFIG_RTK_MESH + if(priv->mesh_dev) { + if (netif_running(priv->mesh_dev) && + netif_queue_stopped(priv->mesh_dev) ) + { + netif_wake_queue(priv->mesh_dev); + } + } +#endif +#ifdef WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled) { + int i; + for (i=0; ipmib->dot11WdsInfo.wdsNum; i++) { + if (netif_running(priv->wds_dev[i]) && + netif_queue_stopped(priv->wds_dev[i])) { + DEBUG_INFO("wake-up wds[%d] queue\n", i); + netif_wake_queue(priv->wds_dev[i]); + } + } + } +#endif +#endif +} +#endif // CONFIG_PCI_HCI + + +static int tkip_mic_padding(struct rtl8192cd_priv *priv, + unsigned char *da, unsigned char *sa, unsigned char priority, + unsigned char *llc, struct sk_buff *pskb, struct tx_insn* txcfg) +{ + // now check what's the mic key we should apply... + + unsigned char *mickey = NULL; + unsigned int keylen = 0; + struct stat_info *pstat = NULL; + unsigned char *hdr, hdr_buf[16]; + unsigned int num_blocks; + unsigned char tkipmic[8]; + unsigned char *pbuf=pskb->data; + unsigned int len=pskb->len; + unsigned int llc_len = 0; + + // check if the mic/tkip key is valid at this moment. + + if ((pskb->tail + 8) > (pskb->end)) + { + DEBUG_ERR("pskb have no extra room for TKIP Michael padding\n"); + return FALSE; + } + +#ifdef WDS + if (txcfg->wdsIdx >= 0) { + pstat = get_stainfo(priv, priv->pmib->dot11WdsInfo.entry[txcfg->wdsIdx].macAddr); + if (pstat) { + keylen = GET_UNICAST_MIC_KEYLEN; + mickey = GET_UNICAST_TKIP_MIC1_KEY; + } + } + else +#endif + if (OPMODE & WIFI_AP_STATE) + { + +#ifdef CONFIG_RTK_MESH + + if(txcfg->is_11s) + + da = txcfg->nhop_11s; + +#endif + if (IS_MCAST(da)) + { + keylen = GET_GROUP_MIC_KEYLEN; + mickey = GET_GROUP_TKIP_MIC1_KEY; +#ifdef A4_STA + if (txcfg->pstat && (txcfg->pstat->state & WIFI_A4_STA)) { + pstat = txcfg->pstat; + keylen = GET_UNICAST_MIC_KEYLEN; + mickey = GET_UNICAST_TKIP_MIC1_KEY; + } +#endif + } + else + { + pstat = get_stainfo (priv, da); +#ifdef A4_STA + if (priv->pshare->rf_ft_var.a4_enable && (pstat == NULL)) + pstat = a4_sta_lookup(priv, da); +#endif + if (pstat == NULL) { + DEBUG_ERR("tx mic pstat == NULL\n"); + return FALSE; + } + + keylen = GET_UNICAST_MIC_KEYLEN; + mickey = GET_UNICAST_TKIP_MIC1_KEY; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + pstat = get_stainfo (priv, BSSID); + if (pstat == NULL) { + DEBUG_ERR("tx mic pstat == NULL\n"); + return FALSE; + } + + keylen = GET_UNICAST_MIC_KEYLEN; + mickey = GET_UNICAST_TKIP_MIC2_KEY; + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + keylen = GET_GROUP_MIC_KEYLEN; + mickey = GET_GROUP_TKIP_MIC1_KEY; + } +#endif + + if ((txcfg->aggre_en == FG_AGGRE_MSDU_MIDDLE) || (txcfg->aggre_en == FG_AGGRE_MSDU_LAST)) + mickey = pstat->tmp_mic_key; + + if (keylen == 0) + { + DEBUG_ERR("no mic padding for TKIP due to keylen=0\n"); + return FALSE; + } + + if (txcfg->aggre_en <= FG_AGGRE_MSDU_FIRST) { + hdr = hdr_buf; + memcpy((void *)hdr, (void *)da, WLAN_ADDR_LEN); + memcpy((void *)(hdr + WLAN_ADDR_LEN), (void *)sa, WLAN_ADDR_LEN); + hdr[12] = priority; + hdr[13] = hdr[14] = hdr[15] = 0; + } + else + hdr = NULL; + + pbuf[len] = 0x5a; /* Insert padding */ + pbuf[len+1] = 0x00; + pbuf[len+2] = 0x00; + pbuf[len+3] = 0x00; + pbuf[len+4] = 0x00; + pbuf[len+5] = 0x00; + pbuf[len+6] = 0x00; + pbuf[len+7] = 0x00; + + if (llc) + llc_len = 8; + num_blocks = (16 + llc_len + len + 5) / 4; + if ((16 + llc_len + len + 5) & (4-1)) + num_blocks++; + + if (txcfg->aggre_en >= FG_AGGRE_MSDU_FIRST) { + if (txcfg->aggre_en == FG_AGGRE_MSDU_FIRST) { + num_blocks = (16 + len) / 4; + if ((16 + len) & (4-1)) + num_blocks++; + } + else if (txcfg->aggre_en == FG_AGGRE_MSDU_MIDDLE) { + num_blocks = len / 4; + if (len & (4-1)) + num_blocks++; + } + else if (txcfg->aggre_en == FG_AGGRE_MSDU_LAST) { + num_blocks = (len + 5) / 4; + if ((len + 5) & (4-1)) + num_blocks++; + } + } + + michael(priv, mickey, hdr, llc, pbuf, (num_blocks << 2), tkipmic, 1); + + //tkip mic is MSDU-based, before filled-in descriptor, already finished. + if (!(priv->pshare->have_hw_mic) || + (priv->pmib->dot11StationConfigEntry.swTkipMic)) + { +#ifdef MICERR_TEST + if (priv->micerr_flag) { + tkipmic[7] ^= tkipmic[7]; + priv->micerr_flag = 0; + } +#endif + if ((txcfg->aggre_en == FG_AGGRE_MSDU_FIRST) || (txcfg->aggre_en == FG_AGGRE_MSDU_MIDDLE)) { + memcpy((void *)pstat->tmp_mic_key, (void *)tkipmic, 8); + } + else + memcpy((void *)(pbuf + len), (void *)tkipmic, 8); + } + + return TRUE; +} + + +void wep_fill_iv(struct rtl8192cd_priv *priv, + unsigned char *pwlhdr, unsigned int hdrlen, unsigned long keyid) +{ + unsigned char *iv = pwlhdr + hdrlen; + union PN48 *ptsc48 = NULL; + union PN48 auth_pn48; + unsigned char *da; + struct stat_info *pstat = NULL; + + memset(&auth_pn48, 0, sizeof(union PN48)); + da = get_da(pwlhdr); + +#if defined(WDS) || defined(A4_STA) + if (get_tofr_ds(pwlhdr) == 3) + da = GetAddr1Ptr(pwlhdr); +#endif + + if (OPMODE & WIFI_AP_STATE) + { + if (IS_MCAST(da)) + { + ptsc48 = GET_GROUP_ENCRYP_PN; + } + else + { + pstat = get_stainfo(priv, da); + if (NULL == pstat) { + DEBUG_ERR("no such station (da:%02x:%02x:%02x:%02x:%02x:%02x)\n", + da[0],da[1],da[2],da[3],da[4],da[5]); + return; + } + ptsc48 = GET_UNICAST_ENCRYP_PN; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + pstat = get_stainfo(priv, BSSID); + if (pstat != NULL) + ptsc48 = GET_UNICAST_ENCRYP_PN; + else + ptsc48 = &auth_pn48; + } + else if (OPMODE & WIFI_ADHOC_STATE) + ptsc48 = GET_GROUP_ENCRYP_PN; +#endif + + if (ptsc48 == NULL) + { + DEBUG_ERR("no TSC for WEP due to ptsc48=NULL\n"); + return; + } + + iv[0] = ptsc48->_byte_.TSC0; + iv[1] = ptsc48->_byte_.TSC1; + iv[2] = ptsc48->_byte_.TSC2; + iv[3] = 0x0 | (keyid << 6); + + if (ptsc48->val48 == 0xffffffffffffULL) + ptsc48->val48 = 0; + else + ptsc48->val48++; +} + + +void tkip_fill_encheader(struct rtl8192cd_priv *priv, + unsigned char *pwlhdr, unsigned int hdrlen, unsigned long keyid_out) +{ + unsigned char *iv = pwlhdr + hdrlen; + union PN48 *ptsc48 = NULL; + unsigned int keyid = 0; + unsigned char *da; + struct stat_info *pstat = NULL; + + da = get_da(pwlhdr); + + if (OPMODE & WIFI_AP_STATE) + { +#if defined(WDS) || defined(CONFIG_RTK_MESH) || defined(A4_STA) + unsigned int to_fr_ds = (GetToDs(pwlhdr) << 1) | GetFrDs(pwlhdr); + if (to_fr_ds == 3) + da = GetAddr1Ptr(pwlhdr); +#endif + + if (IS_MCAST(da)) + { + ptsc48 = GET_GROUP_ENCRYP_PN; + keyid = priv->pmib->dot11GroupKeysTable.keyid; + } + else + { + pstat = get_stainfo(priv, da); + if (NULL == pstat) { + DEBUG_ERR("no such station (da:%02x:%02x:%02x:%02x:%02x:%02x)\n", + da[0],da[1],da[2],da[3],da[4],da[5]); + return; + } + ptsc48 = GET_UNICAST_ENCRYP_PN; + keyid = 0; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + pstat = get_stainfo(priv, BSSID); + if (NULL == pstat) { + DEBUG_ERR("no such station\n"); + return; + } + ptsc48 = GET_UNICAST_ENCRYP_PN; + keyid = 0; + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + ptsc48 = GET_GROUP_ENCRYP_PN; + keyid = 0; + } +#endif + +#ifdef __DRAYTEK_OS__ + keyid = keyid_out; +#endif + + if (ptsc48 == NULL) + { + DEBUG_ERR("no TSC for TKIP due to ptsc48=NULL\n"); + return; + } + + iv[0] = ptsc48->_byte_.TSC1; + iv[1] = (iv[0] | 0x20) & 0x7f; + iv[2] = ptsc48->_byte_.TSC0; + iv[3] = 0x20 | (keyid << 6); + iv[4] = ptsc48->_byte_.TSC2; + iv[5] = ptsc48->_byte_.TSC3; + iv[6] = ptsc48->_byte_.TSC4; + iv[7] = ptsc48->_byte_.TSC5; + + if (ptsc48->val48 == 0xffffffffffffULL) + ptsc48->val48 = 0; + else + ptsc48->val48++; +} + + +__MIPS16 +#ifndef WIFI_MIN_IMEM_USAGE +__IRAM_IN_865X +#endif +void aes_fill_encheader(struct rtl8192cd_priv *priv, + unsigned char *pwlhdr, unsigned int hdrlen, unsigned long keyid) +{ + unsigned char *da; + struct stat_info *pstat = NULL; + union PN48 *pn48 = NULL; + +#ifdef __DRAYTEK_OS__ + int keyid_input = keyid; +#endif + + da = get_da(pwlhdr); + + if (OPMODE & WIFI_AP_STATE) + { +#if defined(WDS) || defined(CONFIG_RTK_MESH) || defined(A4_STA) + unsigned int to_fr_ds = (GetToDs(pwlhdr) << 1) | GetFrDs(pwlhdr); + if (to_fr_ds == 3) + da = GetAddr1Ptr(pwlhdr); +#endif + + + if (IS_MCAST(da)) + { + pn48 = GET_GROUP_ENCRYP_PN; + keyid = priv->pmib->dot11GroupKeysTable.keyid; + } + else + { + pstat = get_stainfo(priv, da); + if (NULL == pstat) { + DEBUG_ERR("no such station (da:%02x:%02x:%02x:%02x:%02x:%02x)\n", + da[0],da[1],da[2],da[3],da[4],da[5]); + return; + } + pn48 = GET_UNICAST_ENCRYP_PN; + keyid = 0; + } + } +#ifdef CLIENT_MODE + else if (OPMODE & WIFI_STATION_STATE) + { + pstat = get_stainfo(priv, BSSID); + if (NULL == pstat) { + DEBUG_ERR("no such station\n"); + return; + } + pn48 = GET_UNICAST_ENCRYP_PN; + keyid = 0; + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + pn48 = GET_GROUP_ENCRYP_PN; + keyid = 0; + } +#endif + + if (pn48 == NULL) + { + DEBUG_ERR("no TSC for AES due to pn48=NULL\n"); + return; + } + +#ifdef __DRAYTEK_OS__ + keyid = keyid_input; +#endif + + pwlhdr[hdrlen] = pn48->_byte_.TSC0; + pwlhdr[hdrlen+1] = pn48->_byte_.TSC1; + pwlhdr[hdrlen+2] = 0x00; + pwlhdr[hdrlen+3] = (0x20 | (keyid << 6)); + pwlhdr[hdrlen+4] = pn48->_byte_.TSC2; + pwlhdr[hdrlen+5] = pn48->_byte_.TSC3; + pwlhdr[hdrlen+6] = pn48->_byte_.TSC4; + pwlhdr[hdrlen+7] = pn48->_byte_.TSC5; + + if (pn48->val48 == 0xffffffffffffULL) + pn48->val48 = 0; + else + pn48->val48++; +} + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_tx.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_tx.h new file mode 100755 index 000000000..de8643ab7 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_tx.h @@ -0,0 +1,202 @@ +/* + * Header file define some tx inline functions + * + * $Id: 8192cd_tx.h,v 1.2 2010/01/29 09:39:16 jimmylin Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_TX_H_ +#define _8192CD_TX_H_ + +#ifndef WLAN_HAL_INTERNAL_USED + + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_util.h" + +#ifdef CONFIG_RTK_MESH +#define rtl8192cd_wlantx(p,t) rtl8192cd_firetx(p, t) +#endif + +enum _TX_QUEUE_ { + MGNT_QUEUE = 0, + BK_QUEUE = 1, + BE_QUEUE = 2, + VI_QUEUE = 3, + VO_QUEUE = 4, + HIGH_QUEUE = 5, +#if defined(CONFIG_PCI_HCI) +#if defined(CONFIG_WLAN_HAL) + HIGH_QUEUE1 = 6, + HIGH_QUEUE2 = 7, + HIGH_QUEUE3 = 8, + HIGH_QUEUE4 = 9, + HIGH_QUEUE5 = 10, + HIGH_QUEUE6 = 11, + HIGH_QUEUE7 = 12, + BEACON_QUEUE = 13 +#else + BEACON_QUEUE = 6, +#endif +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + BEACON_QUEUE = 6, + TXCMD_QUEUE = 7, + HW_QUEUE_ENTRY = 8 +#endif +}; + +#define MCAST_QNUM HIGH_QUEUE + +#if defined(CONFIG_NETDEV_MULTI_TX_QUEUE) || defined(CONFIG_SDIO_TX_FILTER_BY_PRI) +enum _NETDEV_TX_QUEUE_ { + _NETDEV_TX_QUEUE_VO = 0, + _NETDEV_TX_QUEUE_VI = 1, + _NETDEV_TX_QUEUE_BE = 2, + _NETDEV_TX_QUEUE_BK = 3, + _NETDEV_TX_QUEUE_ALL +}; +#endif + +#ifndef RTL_MANUAL_EDCA +#define PRI_TO_QNUM(priority, q_num, wifi_specific) { \ + if ((priority == 0) || (priority == 3)) \ + q_num = BE_QUEUE; \ + else if ((priority == 7) || (priority == 6)) \ + q_num = VO_QUEUE; \ + else if ((priority == 5) || (priority == 4)) \ + q_num = VI_QUEUE; \ + else \ + q_num = BK_QUEUE; \ +} +#endif + +static __inline__ unsigned int get_mpdu_len(struct tx_insn *txcfg, unsigned int fr_len) +{ + return (txcfg->hdr_len + txcfg->llc + txcfg->iv + txcfg->icv + txcfg->mic + _CRCLNG_ + fr_len); +} + +#ifdef CONFIG_PCI_HCI +// the purpose if actually just to link up all the desc in the same q +static __inline__ void init_txdesc(struct rtl8192cd_priv *priv, struct tx_desc *pdesc, + unsigned long ringaddr, unsigned int i) +{ +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E){ + if (i == (CURRENT_NUM_TX_DESC - 1)) + (pdesc + i)->Dword12 = set_desc(ringaddr); // NextDescAddress + else + (pdesc + i)->Dword12 = set_desc(ringaddr + (i+1) * sizeof(struct tx_desc)); // NextDescAddress + } else +#endif + { + if (i == (CURRENT_NUM_TX_DESC - 1)) + (pdesc + i)->Dword10 = set_desc(ringaddr); // NextDescAddress + else + (pdesc + i)->Dword10 = set_desc(ringaddr + (i+1) * sizeof(struct tx_desc)); // NextDescAddress + } + +} + +#define txdesc_rollover(ptxdesc, ptxhead) (*ptxhead = (*ptxhead + 1) % CURRENT_NUM_TX_DESC) + +#define txdesc_rollback(ptxhead) (*ptxhead = (*ptxhead == 0)? (CURRENT_NUM_TX_DESC - 1) : (*ptxhead - 1)) + +static __inline__ void tx_poll(struct rtl8192cd_priv *priv, int q_num) +{ + unsigned char val = 0; + +#ifdef CONFIG_RTL8671 +#ifdef CONFIG_CPU_RLX4181 + r3k_flush_dcache_range(0,0); +#endif +#endif + + switch (q_num) { + case MGNT_QUEUE: + val = MGQ_POLL; + break; + case BK_QUEUE: + val = BKQ_POLL; + break; + case BE_QUEUE: + val = BEQ_POLL; + break; + case VI_QUEUE: + val = VIQ_POLL; + break; + case VO_QUEUE: + val = VOQ_POLL; + break; + case HIGH_QUEUE: + val = HQ_POLL; + break; + default: + break; + } + RTL_W8(PCIE_CTRL_REG, val); +} +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_PCI_HCI +#define desc_copy(dst, src) memcpy(dst, src, 32) + +#define descinfo_copy(d, s) \ + do { \ + struct tx_desc_info *dst = (struct tx_desc_info *)d; \ + struct tx_desc_info *src = (struct tx_desc_info *)s; \ + dst->type = src->type; \ + dst->len = src->len; \ + dst->rate = src->rate; \ + } while (0) +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#define desc_copy(dst, src) memcpy(dst, src, TXDESC_SIZE) + +#define descinfo_copy(d, s) \ + do { \ + struct tx_desc_info *dst = (struct tx_desc_info *)d; \ + struct tx_desc_info *src = (struct tx_desc_info *)s; \ + dst->type = src->type; \ + dst->rate = src->rate; \ + } while (0) +#endif + + + +#ifdef WDS +#define DECLARE_TXINSN(A) struct tx_insn A; \ + do { \ + memset(&A, 0, sizeof(struct tx_insn)); \ + A.wdsIdx = -1; \ + } while (0) + +#define DECLARE_TXCFG(P, TEMPLATE) struct tx_insn *P = &(TEMPLATE); \ + do { \ + memset(P, 0, sizeof(struct tx_insn)); \ + P->wdsIdx = -1; \ + } while (0) + +#else +#define DECLARE_TXINSN(A) struct tx_insn A; \ + do { \ + memset(&A, 0, sizeof(struct tx_insn)); \ + } while (0) + +#define DECLARE_TXCFG(P, TEMPLATE) struct tx_insn* P = &(TEMPLATE); \ + do { \ + memset(P, 0, sizeof(struct tx_insn)); \ + } while (0) + +#endif // WDS + +#endif //#ifndef WLAN_HAL_INTERNAL_USED + +#endif // _8192CD_TX_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_util.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_util.c new file mode 100755 index 000000000..3bee723e1 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_util.c @@ -0,0 +1,10027 @@ +/* + * Utility routines + * + * $Id: 8192cd_util.c,v 1.52.2.24 2011/01/10 06:55:07 chuangsw Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _8192CD_UTILS_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_util.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + +#ifdef RTK_NL80211 +#include "8192cd_cfg80211.h" +#endif +#ifdef RTL8192CD_VARIABLE_USED_DMEM +#include "./8192cd_dmem.h" +#endif +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU) +#ifdef __KERNEL__ +#include +#endif +#endif +#if defined(CONFIG_RTL_FASTBRIDGE) +#include +#endif + +#if defined(CONFIG_RTL_SIMPLE_CONFIG) +#include +#include "./8192cd_profile.h" +extern unsigned char g_sc_ifname[32]; +#endif +#ifdef __ECOS +extern void rtl8192cd_beq_timer(void *task_priv); +extern void rtl8192cd_bkq_timer(void *task_priv); +extern void rtl8192cd_viq_timer(void *task_priv); +extern void rtl8192cd_voq_timer(void *task_priv); +#endif + +#if defined(USE_PID_NOTIFY) && defined(LINUX_2_6_27_) +struct pid *_wlanapp_pid; +struct pid *_wlanwapi_pid; +#endif + +UINT8 Realtek_OUI[]={0x00, 0xe0, 0x4c}; +UINT8 dot11_rate_table[]={2,4,11,22,12,18,24,36,48,72,96,108,0}; // last element must be zero!! + + +#define WLAN_PKT_FORMAT_ENCAPSULATED 0x01 +#define WLAN_PKT_FORMAT_CDP 0x06 +#ifndef CONFIG_RTK_MESH // mesh project moves these define to 8190n_headers.h +#define WLAN_PKT_FORMAT_SNAP_RFC1042 0x02 +#define WLAN_PKT_FORMAT_SNAP_TUNNEL 0x03 +#define WLAN_PKT_FORMAT_IPX_TYPE4 0x04 +#define WLAN_PKT_FORMAT_APPLETALK 0x05 +#define WLAN_PKT_FORMAT_OTHERS 0x07 +#endif + +#ifdef __ECOS +#ifndef VLAN_HLEN +#define VLAN_HLEN 4 +#endif +#endif + +unsigned char SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37}; +unsigned char SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3}; +unsigned char SNAP_ETH_TYPE_APPLETALK_DDP[2] = {0x80, 0x9B}; +unsigned char SNAP_HDR_APPLETALK_DDP[3] = {0x08, 0x00, 0x07}; // Datagram Delivery Protocol + +void mem_dump(unsigned char *ptitle, unsigned char *pbuf, int len) +{ + char tmpbuf[100]; + int i, n = 0; + + if (ptitle) + sprintf(tmpbuf, "%s", ptitle); + else + tmpbuf[0] = '\0'; + + for (i = 0; i < len; ++i ) { + if (!(i & 0x0f)) { + printk("%s\n", tmpbuf); + n = sprintf(tmpbuf, "%03X:\t", i); + } + n += sprintf((tmpbuf+n), " %02X", pbuf[i]); + } + printk("%s\n", tmpbuf); +} + +struct rtl_arphdr +{ + //for corss platform + __be16 ar_hrd; /* format of hardware address */ + __be16 ar_pro; /* format of protocol address */ + unsigned char ar_hln; /* length of hardware address */ + unsigned char ar_pln; /* length of protocol address */ + __be16 ar_op; /* ARP opcode (command) */ +}; + +#ifdef DBG_MEMORY_LEAK +#include +atomic_t _malloc_cnt = ATOMIC_INIT(0); +atomic_t _malloc_size = ATOMIC_INIT(0); +#endif /* DBG_MEMORY_LEAK */ + +#ifdef __KERNEL__ +inline u8* _rtw_vmalloc(u32 sz) +{ + u8 *pbuf; + + pbuf = vmalloc(sz); + +#ifdef DBG_MEMORY_LEAK + if (pbuf != NULL) { + atomic_inc(&_malloc_cnt); + atomic_add(sz, &_malloc_size); + } +#endif /* DBG_MEMORY_LEAK */ + + return pbuf; +} + +inline u8* _rtw_zvmalloc(u32 sz) +{ + u8 *pbuf; + + pbuf = _rtw_vmalloc(sz); + if (pbuf != NULL) { + memset(pbuf, 0, sz); + } + + return pbuf; +} + +inline void _rtw_vmfree(const void *pbuf, u32 sz) +{ + if (pbuf) + { + vfree(pbuf); + +#ifdef DBG_MEMORY_LEAK + atomic_dec(&_malloc_cnt); + atomic_sub(sz, &_malloc_size); +#endif /* DBG_MEMORY_LEAK */ + } +} +#endif // __KERNEL__ + +u8* _rtw_malloc(u32 sz) +{ + u8 *pbuf = NULL; + + pbuf = kmalloc(sz, /*GFP_KERNEL*/GFP_ATOMIC); + +#ifdef DBG_MEMORY_LEAK + if (pbuf != NULL) { + atomic_inc(&_malloc_cnt); + atomic_add(sz, &_malloc_size); + } +#endif /* DBG_MEMORY_LEAK */ + + return pbuf; +} + +u8* _rtw_zmalloc(u32 sz) +{ + u8 *pbuf = _rtw_malloc(sz); + + if (pbuf != NULL) { + memset(pbuf, 0, sz); + } + + return pbuf; +} + +void* rtw_malloc2d(int h, int w, int size) +{ + int j; + + void **a = (void **) rtw_zmalloc( h*sizeof(void *) + h*w*size ); + if(a == NULL) + { + return NULL; + } + + for( j=0; j= PRE_ALLOCATED_HDR) { + _DEBUG_ERR("over size free buf phead=%lX, *count=%d\n", (unsigned long)phead, *count); + return; + } +#endif + + plist = (struct list_head *)((unsigned long)pbuf - sizeof(struct list_head)); + + SMP_LOCK_BUF(flags); + + *count = *count + 1; + list_add_tail(plist, phead); + + SMP_UNLOCK_BUF(flags); +} + +#ifndef _11s_TEST_MODE_ + static +#endif +__inline__ unsigned char *get_buf_from_poll(struct rtl8192cd_priv *priv, struct list_head *phead, unsigned int *count) +{ + unsigned char *buf; + struct list_head *plist; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + if(priv) + SMP_LOCK_BUF(flags); + + if (list_empty(phead)) { + if(priv) + SMP_UNLOCK_BUF(flags); +// _DEBUG_ERR("phead=%lX buf is empty now!\n", (unsigned long)phead); + return NULL; + } + + if (*count == 0) { + if(priv) + SMP_UNLOCK_BUF(flags); + _DEBUG_ERR("phead=%lX under-run!\n", (unsigned long)phead); + return NULL; + } + + *count = *count - 1; + plist = phead->next; + list_del_init(plist); + + if(priv) + SMP_UNLOCK_BUF(flags); + + buf = (UINT8 *)((unsigned long)plist + sizeof (struct list_head)); + return buf; +} + +__inline__ unsigned int orSTABitMap(STA_BITMAP *map) +{ + return ( + map->_staMap_ +#if (NUM_STAT >32) + || map->_staMap_ext_1 +#if (NUM_STAT >64) + || map->_staMap_ext_2 || map->_staMap_ext_3 +#endif +#endif + ); +} + +__inline__ unsigned int orForce20_Switch20Map(struct rtl8192cd_priv *priv) +{ + return (orSTABitMap(&priv->force_20_sta) || orSTABitMap(&priv->switch_20_sta)); +} + +/* return 1 or 0*/ +unsigned char getSTABitMap(STA_BITMAP *map, int bitIdx) +{ + unsigned int ret = 0; + bitIdx--; + + if (bitIdx < 32) + ret = map->_staMap_ & BIT(bitIdx); +#if (NUM_STAT >32) + else if (bitIdx <= 64) + ret = map->_staMap_ext_1 & BIT(bitIdx - 32); +#if (NUM_STAT >64) + else if (bitIdx <= 96) + ret = map->_staMap_ext_2 & BIT(bitIdx - 64); + else if (bitIdx <= 128) + ret = map->_staMap_ext_3 & BIT(bitIdx -96); +#endif +#endif + + return (ret?1:0); +} + +#ifdef RTK_NL80211 +int changePreamble(struct rtl8192cd_priv *priv, int preamble) +{ + unsigned char *p = (unsigned char *)priv->beaconbuf; + unsigned short *bcn_cap = p+BEACON_MACHDR_LEN+_TIMESTAMP_+_BEACON_ITERVAL_; + + if(preamble) + *bcn_cap |= cpu_to_le16(BIT(5)); + else + *bcn_cap &= ~(cpu_to_le16(BIT(5))); + + return 0; +} + +int HideAP(struct rtl8192cd_priv *priv) +{ + unsigned char *p = (unsigned char *)priv->beaconbuf; + + memset(p + 24 + _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_ + 2, 0, SSID_LEN); + + return 0; +} + +int DehideAP(struct rtl8192cd_priv *priv) +{ + unsigned char *p = (unsigned char *)priv->beaconbuf; + + memcpy(p + 24 + _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_ + 2, SSID, SSID_LEN); + *(p + 24 + _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_ + 1) = SSID_LEN; + + return 0; +} +#endif + +void setSTABitMap(STA_BITMAP *map, int bitIdx) +{ + bitIdx--; + + if (bitIdx < 32) + map->_staMap_ |= BIT(bitIdx); +#if (NUM_STAT >32) + else if (bitIdx <= 64) + map->_staMap_ext_1 |= BIT(bitIdx - 32); +#if (NUM_STAT >64) + else if (bitIdx <= 96) + map->_staMap_ext_2 |= BIT(bitIdx - 64); + else if (bitIdx <= 128) + map->_staMap_ext_3 |= BIT(bitIdx -96); +#endif +#endif +} + +void clearSTABitMap(STA_BITMAP* map, int bitIdx) +{ + bitIdx--; + + if (bitIdx < 32) + map->_staMap_ &= ~ BIT(bitIdx); +#if (NUM_STAT >32) + else if (bitIdx < 64) + map->_staMap_ext_1 &= ~ BIT(bitIdx - 32); +#if (NUM_STAT >64) + else if (bitIdx < 96) + map->_staMap_ext_2 &= ~ BIT(bitIdx - 64); + else if (bitIdx < 128) + map->_staMap_ext_3 &= ~ BIT(bitIdx - 96); +#endif +#endif +} + +#ifdef PRIV_STA_BUF +struct priv_obj_buf { + unsigned char magic[8]; + struct list_head list; + struct aid_obj obj; +}; + +#if defined(WIFI_WMM) && defined(WMM_APSD) +struct priv_apsd_que { + unsigned char magic[8]; + struct list_head list; + struct apsd_pkt_queue que; +}; +#endif + +#if defined(WIFI_WMM) +struct priv_dz_mgt_que { + unsigned char magic[8]; + struct list_head list; + struct dz_mgmt_queue que; +}; +#endif + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) +struct priv_wpa_buf { + unsigned char magic[8]; + struct list_head list; + WPA_STA_INFO wpa; +}; +#endif + +#define MAGIC_CODE_BUF "8192" + +#define MAX_PRIV_OBJ_NUM NUM_STAT + +#ifdef CONCURRENT_MODE +static struct priv_obj_buf obj_buf[NUM_WLAN_IFACE][MAX_PRIV_OBJ_NUM]; +static struct list_head objbuf_list[NUM_WLAN_IFACE]; +static int free_obj_buf_num[NUM_WLAN_IFACE]; + + +#if defined(WIFI_WMM) && defined(WMM_APSD) + #define MAX_PRIV_QUE_NUM (MAX_PRIV_OBJ_NUM*4) + static struct priv_apsd_que que_buf[NUM_WLAN_IFACE][MAX_PRIV_QUE_NUM]; + static struct list_head quebuf_list[NUM_WLAN_IFACE]; + static int free_que_buf_num[NUM_WLAN_IFACE]; +#endif + +#if defined(WIFI_WMM) + #define MAX_MGT_QUE_NUM (MAX_PRIV_OBJ_NUM) + static struct priv_dz_mgt_que mgt_que_buf[NUM_WLAN_IFACE][MAX_MGT_QUE_NUM]; + static struct list_head mgt_quebuf_list[NUM_WLAN_IFACE]; + static int free_mgt_que_buf_num[NUM_WLAN_IFACE]; +#endif + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + #define MAX_PRIV_WPA_NUM MAX_PRIV_OBJ_NUM + static struct priv_wpa_buf wpa_buf[NUM_WLAN_IFACE][MAX_PRIV_WPA_NUM]; + static struct list_head wpabuf_list[NUM_WLAN_IFACE]; + static int free_wpa_buf_num[NUM_WLAN_IFACE]; +#endif + +#else +static struct priv_obj_buf obj_buf[MAX_PRIV_OBJ_NUM]; +static struct list_head objbuf_list; +static int free_obj_buf_num; + + +#if defined(WIFI_WMM) && defined(WMM_APSD) + #define MAX_PRIV_QUE_NUM (MAX_PRIV_OBJ_NUM*4) + static struct priv_apsd_que que_buf[MAX_PRIV_QUE_NUM]; + static struct list_head quebuf_list; + static int free_que_buf_num; +#endif + +#if defined(WIFI_WMM) + #define MAX_MGT_QUE_NUM (MAX_PRIV_OBJ_NUM) + static struct priv_dz_mgt_que mgt_que_buf[MAX_MGT_QUE_NUM]; + static struct list_head mgt_quebuf_list; + static int free_mgt_que_buf_num; +#endif + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + #define MAX_PRIV_WPA_NUM MAX_PRIV_OBJ_NUM + static struct priv_wpa_buf wpa_buf[MAX_PRIV_WPA_NUM]; + static struct list_head wpabuf_list; + static int free_wpa_buf_num; +#endif +#endif + +void init_priv_sta_buf(struct rtl8192cd_priv *priv) +{ + int i; +#ifdef CONCURRENT_MODE + int idx = priv->pshare->wlandev_idx; + memset(&obj_buf[idx], '\0', sizeof(struct priv_obj_buf)*MAX_PRIV_OBJ_NUM); + INIT_LIST_HEAD(&objbuf_list[idx]); + for (i=0; ipshare->wlandev_idx], (unsigned int *)&free_obj_buf_num[priv->pshare->wlandev_idx]); +#else + priv_obj = (struct aid_obj *)get_buf_from_poll(priv, &objbuf_list, (unsigned int *)&free_obj_buf_num); +#endif +#else +#ifdef CONCURRENT_MODE + priv_obj = (struct aid_obj *)get_buf_from_poll(NULL, &objbuf_list[priv->pshare->wlandev_idx], (unsigned int *)&free_obj_buf_num[priv->pshare->wlandev_idx]); +#else + priv_obj = (struct aid_obj *)get_buf_from_poll(NULL, &objbuf_list, (unsigned int *)&free_obj_buf_num); +#endif +#endif + + if(priv) + RESTORE_INT(flags); + +#ifdef __KERNEL__ + if (priv_obj == NULL) + return ((struct aid_obj *)kmalloc(sizeof(struct aid_obj), GFP_ATOMIC)); + else +#endif + return priv_obj; +} + +void free_sta_obj(struct rtl8192cd_priv *priv, struct aid_obj *obj) +{ + unsigned long offset = (unsigned long)(&((struct priv_obj_buf *)0)->obj); + struct priv_obj_buf *priv_obj = (struct priv_obj_buf *)(((unsigned long)obj) - offset); +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (!memcmp(priv_obj->magic, MAGIC_CODE_BUF, 4) && + ((unsigned long)&priv_obj->obj) == ((unsigned long)obj)) { + SAVE_INT_AND_CLI(flags); +#ifdef CONCURRENT_MODE + release_buf_to_poll(priv, (unsigned char *)obj, &objbuf_list[priv->pshare->wlandev_idx], (unsigned int *)&free_obj_buf_num[priv->pshare->wlandev_idx]); +#else + release_buf_to_poll(priv, (unsigned char *)obj, &objbuf_list, (unsigned int *)&free_obj_buf_num); +#endif + RESTORE_INT(flags); + } + else +#ifdef __ECOS + ASSERT(0); +#else + kfree(obj); +#endif +} + +#if defined(WIFI_WMM) && defined(WMM_APSD) +static struct apsd_pkt_queue *alloc_sta_que(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + struct apsd_pkt_queue *priv_que; + SAVE_INT_AND_CLI(flags); +#ifdef CONCURRENT_MODE + priv_que = (struct apsd_pkt_queue*)get_buf_from_poll(priv, &quebuf_list[priv->pshare->wlandev_idx], (unsigned int *)&free_que_buf_num[priv->pshare->wlandev_idx]); +#else + priv_que = (struct apsd_pkt_queue*)get_buf_from_poll(priv, &quebuf_list, (unsigned int *)&free_que_buf_num); +#endif + RESTORE_INT(flags); + +#ifdef __KERNEL__ + if (priv_que == NULL) + return ((struct apsd_pkt_queue *)kmalloc(sizeof(struct apsd_pkt_queue), GFP_ATOMIC)); + else +#endif + return priv_que; +} + +void free_sta_que(struct rtl8192cd_priv *priv, struct apsd_pkt_queue *que) +{ + unsigned long offset = (unsigned long)(&((struct priv_apsd_que *)0)->que); + struct priv_apsd_que *priv_que = (struct priv_apsd_que *)(((unsigned long)que) - offset); +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (!memcmp(priv_que->magic, MAGIC_CODE_BUF, 4) && + ((unsigned long)&priv_que->que) == ((unsigned long)que)) { + SAVE_INT_AND_CLI(flags); +#ifdef CONCURRENT_MODE + release_buf_to_poll(priv, (unsigned char *)que, &quebuf_list[priv->pshare->wlandev_idx], (unsigned int *)&free_que_buf_num[priv->pshare->wlandev_idx]); +#else + release_buf_to_poll(priv, (unsigned char *)que, &quebuf_list, (unsigned int *)&free_que_buf_num); +#endif + RESTORE_INT(flags); + } + else +#ifdef __ECOS + ASSERT(0); +#else + kfree(que); +#endif +} +#endif // defined(WIFI_WMM) && defined(WMM_APSD) + +#if defined(WIFI_WMM) +static struct dz_mgmt_queue *alloc_sta_mgt_que(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + struct dz_mgmt_queue *priv_que; + + SAVE_INT_AND_CLI(flags); +#ifdef CONCURRENT_MODE + priv_que = (struct dz_mgmt_queue*)get_buf_from_poll(priv, &mgt_quebuf_list[priv->pshare->wlandev_idx], (unsigned int *)&free_mgt_que_buf_num[priv->pshare->wlandev_idx]); +#else + priv_que = (struct dz_mgmt_queue*)get_buf_from_poll(priv, &mgt_quebuf_list, (unsigned int *)&free_mgt_que_buf_num); +#endif + RESTORE_INT(flags); + +#ifdef __KERNEL__ + if (priv_que == NULL) + return ((struct dz_mgmt_queue *)kmalloc(sizeof(struct dz_mgmt_queue), GFP_ATOMIC)); + else +#endif + return priv_que; +} + +void free_sta_mgt_que(struct rtl8192cd_priv *priv, struct dz_mgmt_queue *que) +{ + unsigned long offset = (unsigned long)(&((struct priv_dz_mgt_que *)0)->que); + struct priv_dz_mgt_que *priv_que = (struct priv_dz_mgt_que *)(((unsigned long)que) - offset); +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (!memcmp(priv_que->magic, MAGIC_CODE_BUF, 4) && + ((unsigned long)&priv_que->que) == ((unsigned long)que)) { + SAVE_INT_AND_CLI(flags); +#ifdef CONCURRENT_MODE + release_buf_to_poll(priv, (unsigned char *)que, &mgt_quebuf_list[priv->pshare->wlandev_idx], (unsigned int *)&free_mgt_que_buf_num[priv->pshare->wlandev_idx]); +#else + release_buf_to_poll(priv, (unsigned char *)que, &mgt_quebuf_list, (unsigned int *)&free_mgt_que_buf_num); +#endif + RESTORE_INT(flags); + } + else + kfree(que); +} +#endif // defined(WIFI_WMM) + + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) +static WPA_STA_INFO *alloc_wpa_buf(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + WPA_STA_INFO *priv_buf; + SAVE_INT_AND_CLI(flags); +#ifdef CONCURRENT_MODE + priv_buf = (WPA_STA_INFO *)get_buf_from_poll(priv, &wpabuf_list[priv->pshare->wlandev_idx], (unsigned int *)&free_wpa_buf_num[priv->pshare->wlandev_idx]); +#else + priv_buf = (WPA_STA_INFO *)get_buf_from_poll(priv, &wpabuf_list, (unsigned int *)&free_wpa_buf_num); +#endif + RESTORE_INT(flags); + +#ifdef __ECOS + ASSERT(priv_buf != NULL); + return priv_buf; + +#else + if (priv_buf == NULL) + return ((WPA_STA_INFO *)kmalloc(sizeof(WPA_STA_INFO), GFP_ATOMIC)); + else + return priv_buf; +#endif +} + +void free_wpa_buf(struct rtl8192cd_priv *priv, WPA_STA_INFO *buf) +{ + unsigned long offset = (unsigned long)(&((struct priv_wpa_buf *)0)->wpa); + struct priv_wpa_buf *priv_buf = (struct priv_wpa_buf *)(((unsigned long)buf) - offset); +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (!memcmp(priv_buf->magic, MAGIC_CODE_BUF, 4) && + ((unsigned long)&priv_buf->wpa) == ((unsigned long)buf)) { + SAVE_INT_AND_CLI(flags); +#ifdef CONCURRENT_MODE + release_buf_to_poll(priv, (unsigned char *)buf, &wpabuf_list[priv->pshare->wlandev_idx], (unsigned int *)&free_wpa_buf_num[priv->pshare->wlandev_idx]); +#else + release_buf_to_poll(priv, (unsigned char *)buf, &wpabuf_list, (unsigned int *)&free_wpa_buf_num); +#endif + RESTORE_INT(flags); + } + else +#ifdef __ECOS + ASSERT(0); +#else + kfree(buf); +#endif +} +#endif // INCLUDE_WPA_PSK +#endif // PRIV_STA_BUF + + +#ifdef CONFIG_RTL8190_PRIV_SKB +#ifdef CONCURRENT_MODE +static struct sk_buff *dev_alloc_skb_priv(struct rtl8192cd_priv *priv, unsigned int size); +#else +static struct sk_buff *dev_alloc_skb_priv(struct rtl8192cd_priv *priv, unsigned int size); +#endif +#endif + + +int enque(struct rtl8192cd_priv *priv, int *head, int *tail, unsigned long ffptr, int ffsize, void *elm) +{ + // critical section! +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + if (CIRC_SPACE(*head, *tail, ffsize) == 0) { + RESTORE_INT(flags); + return FALSE; + } + + *(unsigned long *)(ffptr + (*head)*(sizeof(void *))) = (unsigned long)elm; + *head = (*head + 1) & (ffsize - 1); + RESTORE_INT(flags); + return TRUE; +} + + +void* deque(struct rtl8192cd_priv *priv, int *head, int *tail, unsigned long ffptr, int ffsize) +{ + // critical section! + unsigned int i; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + void *elm; + + SAVE_INT_AND_CLI(flags); + if (CIRC_CNT(*head, *tail, ffsize) == 0) { + RESTORE_INT(flags); + return NULL; + } + + i = *tail; + *tail = (*tail + 1) & (ffsize - 1); + elm = (void*)(*(unsigned long *)(ffptr + i*(sizeof(void *)))); + RESTORE_INT(flags); + + return elm; +} + + +void initque(struct rtl8192cd_priv *priv, int *head, int *tail) +{ + // critical section! +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + *head = *tail = 0; + RESTORE_INT(flags); +} + + +int isFFempty(int head, int tail) +{ + return (head == tail); +} + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +void _init_txservq(struct tx_servq *ptxservq, int q_num) +{ + _rtw_init_listhead(&ptxservq->tx_pending); + _rtw_init_queue(&ptxservq->xframe_queue); + ptxservq->q_num = q_num; +#ifdef CONFIG_SDIO_HCI + ptxservq->ts_used = 0; +#endif +} + +#ifdef CONFIG_TCP_ACK_TXAGG +void _init_tcpack_servq(struct tcpack_servq *tcpackq, int q_num) +{ + _rtw_init_listhead(&tcpackq->tx_pending); + _rtw_init_queue(&tcpackq->xframe_queue); + tcpackq->q_num = q_num; +} +#endif +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#ifdef CONFIG_RTK_MESH +unsigned int find_rate_MP(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct ht_cap_elmt * peer_ht_cap, int peer_ht_cap_len, char *peer_rate,int peer_rate_len,int mode, int isBasicRate) +{ + unsigned int len, i, hirate, lowrate, rate_limit, OFDM_only=0; + unsigned char *rateset, *p; + + if ((get_rf_mimo_mode(priv)== MIMO_1T2R) || (get_rf_mimo_mode(priv)== MIMO_1T1R)) //eric-8814 ?? 3t3r ?? + rate_limit = 8; + else if (get_rf_mimo_mode(priv)== MIMO_2T2R) + rate_limit = 16; + else if (get_rf_mimo_mode(priv)== MIMO_3T3R) + rate_limit = 24; + else + rate_limit = 16; + + if (pstat) { + rateset = pstat->bssrateset; + len = pstat->bssratelen; + } + else { + rateset = peer_rate; + len = peer_rate_len; + } + + hirate = _1M_RATE_; + lowrate = _54M_RATE_; + if (priv->pshare->curr_band == BAND_5G) + OFDM_only = 1; + + for(i=0,p=rateset; i hirate) + if (!OFDM_only || !is_CCK_rate(*p & 0x7f)) + hirate = (*p & 0x7f); + + if ((*p & 0x7f) < lowrate) + if (!OFDM_only || !is_CCK_rate(*p & 0x7f)) + lowrate = (*p & 0x7f); + } + + if (pstat) { + if ((mode == 1) && (isBasicRate == 0) && pstat->ht_cap_len) { + for (i=0; iht_cap_buf.support_mcs[i/8] & BIT(i%8)) { + hirate = i; + hirate += HT_RATE_ID; + } + } + } + } + else { + if ((mode == 1) && (isBasicRate == 0) && priv->ht_cap_len && peer_ht_cap_len) { + for (i=0; isupport_mcs[i/8] & BIT(i%8)) { + hirate = i; + hirate += HT_RATE_ID; + } + } + } + } + + if (mode == 0) + return lowrate; + else + return hirate; +} + +#endif + + +// rateset: is the rateset for searching +// mode: 0: find the lowest rate, 1: find the highest rate +// isBasicRate: bit0-1: find from basic rate set, bit0-0: find from supported rate set. bit1-1: find CCK only +unsigned int find_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat, int mode, int isBasicRate) +{ + unsigned int len, i, hirate, lowrate, rate_limit, OFDM_only=0; + unsigned char *rateset, *p; +#ifdef CLIENT_MODE + unsigned char totalrateset[32]; +#endif + + if ((get_rf_mimo_mode(priv)== MIMO_1T2R) || (get_rf_mimo_mode(priv)== MIMO_1T1R)) //eric-8814 ?? 3t3r ?? + rate_limit = 8; + else if (get_rf_mimo_mode(priv)== MIMO_2T2R) + rate_limit = 16; + else if (get_rf_mimo_mode(priv)== MIMO_3T3R) + rate_limit = 24; + else + rate_limit = 16; + + if (pstat) { + rateset = pstat->bssrateset; + len = pstat->bssratelen; + } else { +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_STATION_STATE) && priv->pmib->dot11Bss.supportrate) { + int i=0; + len = 0; + for (i=0; dot11_rate_table[i]; i++) { + if (priv->pmib->dot11Bss.supportrate & BIT(i)) { + totalrateset[len] = dot11_rate_table[i]; + if (priv->pmib->dot11Bss.basicrate & BIT(i)) + totalrateset[len] |= 0x80; + len++; + } + } + rateset = totalrateset; + } else +#endif + { + rateset = AP_BSSRATE; + len = AP_BSSRATE_LEN; + } + } + + hirate = _1M_RATE_; + lowrate = _54M_RATE_; + if (priv->pshare->curr_band == BAND_5G +#if defined(RTK_5G_SUPPORT) + || priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G +#endif + ) + OFDM_only = 1; + + for(i=0,p=rateset; i hirate) + if (!OFDM_only || !is_CCK_rate(*p & 0x7f)) + hirate = (*p & 0x7f); + + if ((*p & 0x7f) < lowrate) + if (!OFDM_only || !is_CCK_rate(*p & 0x7f)) + lowrate = (*p & 0x7f); + } + + if (pstat) { + if ((mode == 1) && (isBasicRate == 0) && pstat->ht_cap_len && (!should_restrict_Nrate(priv, pstat))) { + for (i=0; iht_cap_buf.support_mcs[i/8] & BIT(i&0x7)) { + hirate = i; + hirate += HT_RATE_ID; + } + } + } + } + else { + if ((mode == 1) && (isBasicRate == 0) && priv->ht_cap_len) { + for (i=0; iht_cap_buf.support_mcs[i/8] & BIT(i%8)) { + hirate = i; + hirate += HT_RATE_ID; + } + } + } + } + + if (mode == 0) + return lowrate; + else + return hirate; +} + + +UINT8 get_rate_from_bit_value(int bit_val) +{ + int i; + + if (bit_val == 0) + return 0; + +#ifdef RTK_AC_SUPPORT //vht rate + if(bit_val & BIT(31)) { + i = bit_val - BIT(31); + + if(i < VHT_RATE_NUM) + return (VHT_RATE_ID + i); + else + return _NSS1_MCS0_RATE_; //unknown rate value + } +#endif + + if(bit_val & BIT(28)) { + i = bit_val - BIT(28); + + if((i+16) < HT_RATE_NUM) + return (_MCS16_RATE_ + i); + else + return _MCS0_RATE_; //unknown rate value + } + + i = 0; + while ((bit_val & BIT(i)) == 0) + i++; + + if (i < 12) + return dot11_rate_table[i]; + else if (i < 28) + return ((i - 12) + HT_RATE_ID); + + return 0; +} + + +int get_rate_index_from_ieee_value(UINT8 val) +{ + int i; + for (i=0; dot11_rate_table[i]; i++) { + if (val == dot11_rate_table[i]) { + return i; + } + } + _DEBUG_ERR("Local error, invalid input rate for get_rate_index_from_ieee_value() [%d]!!\n", val); + return 0; +} + + +int get_bit_value_from_ieee_value(UINT8 val) +{ + int i=0; + while(dot11_rate_table[i] != 0) { + if (dot11_rate_table[i] == val) + return BIT(i); + i++; + } + return 0; +} + +BOOLEAN CheckCts2SelfEnable(UINT8 rtsTxRate) +{ + return (rtsTxRate <= _11M_RATE_) ? 1 :0; +} + +UINT8 find_rts_rate(struct rtl8192cd_priv *priv, UINT8 TxRate, BOOLEAN bErpProtect) +{ + UINT8 rtsTxRate = _6M_RATE_; + + if(bErpProtect) // use CCK rate as RTS + { + rtsTxRate = _1M_RATE_; + } + else + { + switch (TxRate) + { + case _NSS2_MCS9_RATE_: + case _NSS2_MCS8_RATE_: + case _NSS2_MCS7_RATE_: + case _NSS2_MCS6_RATE_: + case _NSS2_MCS5_RATE_: + case _NSS2_MCS4_RATE_: + case _NSS2_MCS3_RATE_: + case _NSS1_MCS9_RATE_: + case _NSS1_MCS8_RATE_: + case _NSS1_MCS7_RATE_: + case _NSS1_MCS6_RATE_: + case _NSS1_MCS5_RATE_: + case _NSS1_MCS4_RATE_: + case _NSS1_MCS3_RATE_: + case _MCS15_RATE_: + case _MCS14_RATE_: + case _MCS13_RATE_: + case _MCS12_RATE_: + case _MCS11_RATE_: + case _MCS7_RATE_: + case _MCS6_RATE_: + case _MCS5_RATE_: + case _MCS4_RATE_: + case _MCS3_RATE_: + case _54M_RATE_: + case _48M_RATE_: + case _36M_RATE_: + case _24M_RATE_: + rtsTxRate = _24M_RATE_; + break; + case _NSS2_MCS2_RATE_: + case _NSS2_MCS1_RATE_: + case _NSS1_MCS2_RATE_: + case _NSS1_MCS1_RATE_: + case _MCS10_RATE_: + case _MCS9_RATE_: + case _MCS2_RATE_: + case _MCS1_RATE_: + case _18M_RATE_: + case _12M_RATE_: + rtsTxRate = _12M_RATE_; + break; + case _NSS2_MCS0_RATE_: + case _NSS1_MCS0_RATE_: + case _MCS8_RATE_: + case _MCS0_RATE_: + case _9M_RATE_: + case _6M_RATE_: + rtsTxRate = _6M_RATE_; + break; + case _11M_RATE_: + case _5M_RATE_: + case _2M_RATE_: + case _1M_RATE_: + rtsTxRate = _1M_RATE_; + break; + default: + rtsTxRate = _6M_RATE_; + break; + } + } + + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + if(rtsTxRate < _6M_RATE_) + rtsTxRate = _6M_RATE_; + } + + return rtsTxRate; +} + +void init_stainfo(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + struct wifi_mib *pmib = priv->pmib; + unsigned long offset; + int i, j; +#if !defined(SMP_SYNC) && defined(CONFIG_RTL_WAPI_SUPPORT) + unsigned long flags; +#endif + +#ifdef WDS + static unsigned char bssrateset[32]; + unsigned int bssratelen=0; + unsigned int current_tx_rate=0; +#endif + unsigned short bk_aid; + unsigned char bk_hwaddr[MACADDRLEN]; + + + // init linked list header + // BUT do NOT init hash_list + INIT_LIST_HEAD(&pstat->asoc_list); + INIT_LIST_HEAD(&pstat->auth_list); + INIT_LIST_HEAD(&pstat->sleep_list); + INIT_LIST_HEAD(&pstat->defrag_list); + INIT_LIST_HEAD(&pstat->wakeup_list); + INIT_LIST_HEAD(&pstat->frag_list); + +#ifdef CONFIG_PCI_HCI + // to avoid add RAtid fail + INIT_LIST_HEAD(&pstat->addRAtid_list); + INIT_LIST_HEAD(&pstat->addrssi_list); +#endif + +#ifdef CONFIG_RTK_MESH + INIT_LIST_HEAD(&pstat->mesh_mp_ptr); +#endif // CONFIG_RTK_MESH + +#ifdef A4_STA + INIT_LIST_HEAD(&pstat->a4_sta_list); +#endif +#if defined(CONFIG_PCI_HCI) + skb_queue_head_init(&pstat->dz_queue); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + INIT_LIST_HEAD(&pstat->pspoll_list); + + for (i = 0; i < MAX_STA_TX_SERV_QUEUE; ++i) { + _init_txservq(&pstat->tx_queue[i], i); +#ifdef CONFIG_TCP_ACK_TXAGG + _init_tcpack_servq(&pstat->tcpack_queue[i], i); +#endif + } + + pstat->pending_cmd = 0; + pstat->asoc_list_refcnt = 0; +#ifdef __ECOS + cyg_flag_init(&pstat->asoc_unref_done); +#else + init_completion(&pstat->asoc_unref_done); +#endif +#endif + +#ifdef SW_TX_QUEUE + init_timer(&pstat->swq.beq_timer); + init_timer(&pstat->swq.bkq_timer); + init_timer(&pstat->swq.viq_timer); + init_timer(&pstat->swq.voq_timer); + + skb_queue_head_init(&pstat->swq.be_queue); + skb_queue_head_init(&pstat->swq.bk_queue); + skb_queue_head_init(&pstat->swq.vi_queue); + skb_queue_head_init(&pstat->swq.vo_queue); + for(i=BK_QUEUE;iswq.q_aggnum[i] = priv->pshare->rf_ft_var.swq_aggnum; + pstat->swq.q_aggnum[i] = 2; + + } +#endif + + // we do NOT reset MAC here + +#if defined(WIFI_WMM) +#ifdef DZ_ADDBA_RSP + pstat->dz_addba.used = 0; +#endif +#endif + +#ifdef WDS + if (pstat->state & WIFI_WDS) { + bssratelen = pstat->bssratelen; + memcpy(bssrateset, pstat->bssrateset, bssratelen); + current_tx_rate = pstat->current_tx_rate; + } +#endif + + // zero out all the rest + bk_aid = pstat->aid; + memcpy(bk_hwaddr, pstat->hwaddr, MACADDRLEN); + + offset = (unsigned long)(&((struct stat_info *)0)->auth_seq); + memset((void *)((unsigned long)pstat + offset), 0, sizeof(struct stat_info)-offset); + + pstat->aid = bk_aid; + memcpy(pstat->hwaddr, bk_hwaddr, MACADDRLEN); + +#ifdef WDS + if (bssratelen) { + pstat->bssratelen = bssratelen; + memcpy(pstat->bssrateset, bssrateset, bssratelen); + pstat->current_tx_rate = current_tx_rate; + pstat->state |= WIFI_WDS; + } +#endif + + // some variables need initial value + pstat->ieee8021x_ctrlport = pmib->dot118021xAuthEntry.dot118021xDefaultPort; + pstat->expire_to = priv->expire_to; + pstat->idle_count = 0; + for (i=0; i<8; i++) + for (j=0; jtpcache[i][j] = 0xffff; + // Stanldy mesh: pstat->tpcache[i][j] = j+1 is best solution, because its a hash table, fill slot[i] with i+1 can prevent collision,fix the packet loss of first unicast + pstat->tpcache_mgt = 0xffff; +#ifdef CLIENT_MODE + pstat->tpcache_mcast = 0xffff; +#endif +#ifdef GBWC + for (i=0; ipmib->gbwcEntry.GBWCNum; i++) { + if (!memcmp(pstat->hwaddr, priv->pmib->gbwcEntry.GBWCAddr[i], MACADDRLEN)) { + pstat->GBWC_in_group = TRUE; + break; + } + } +#endif + +// button 2009.05.21 +#ifdef INCLUDE_WPA_PSK + pstat->wpa_sta_info->clientHndshkProcessing = pstat->wpa_sta_info->clientHndshkDone = FALSE; +#endif + +#ifdef CONFIG_RTK_MESH + pstat->mesh_neighbor_TBL.BSexpire_LLSAperiod = jiffies + MESH_EXPIRE_TO; +#endif //CONFIG_RTK_MESH + + memset(pstat->rc_entry, 0, sizeof(pstat->rc_entry)); + +#ifdef SUPPORT_TX_AMSDU + for (i=0; i<8; i++) + skb_queue_head_init(&pstat->amsdu_tx_que[i]); +#endif + +#if defined (HW_ANT_SWITCH) && (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) + pstat->CurAntenna = priv->pshare->rf_ft_var.CurAntenna; +#endif + +#ifdef CONFIG_IEEE80211W + init_timer(&pstat->SA_timer); + pstat->SA_timer.data = (unsigned long) pstat; + pstat->SA_timer.function = rtl8192cd_sa_query_timer; +#endif + +#ifdef CONFIG_RTL_WAPI_SUPPORT +// if (priv->pmib->wapiInfo.wapiType!=wapiDisable) + { + SAVE_INT_AND_CLI(flags); +// wapiAssert(pstat->wapiInfo!=NULL); + if (pstat->wapiInfo==NULL) + { + pstat->wapiInfo = (wapiStaInfo*)kmalloc(sizeof(wapiStaInfo), GFP_ATOMIC); + if (pstat->wapiInfo==NULL) + { + printk("Err: kmalloc wapiStaInfo fail!\n"); + } + } + if (pstat->wapiInfo!=NULL) + { + pstat->wapiInfo->priv = priv; + wapiStationInit(pstat); + pstat->wapiInfo->wapiType = priv->pmib->wapiInfo.wapiType; + } + RESTORE_INT(flags); + } +#endif + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + ODM_CmnInfoPtrArrayHook(ODMPTR , ODM_CMNINFO_STA_STATUS, pstat->aid, pstat); +#endif + +#ifdef MULTI_MAC_CLONE + if ((OPMODE & WIFI_STATION_STATE) && priv->pmib->ethBrExtInfo.macclone_enable) + { + pstat->mclone_id = ACTIVE_ID; + memcpy(pstat->sa_addr, GET_MY_HWADDR, MACADDRLEN); + } +#endif +} + +#if defined(CONFIG_RTL_ETH_PRIV_SKB_DEBUG) +void dump_sta_dz_queue_num(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#if defined(WIFI_WMM) && defined(WMM_APSD) + int hd, tl; +#endif + + // free all skb in dz_queue + + printk("---------------------------------------\n"); +#if defined(CONFIG_PCI_HCI) + printk("pstat->dz_queue:%d\n",skb_queue_len(&pstat->dz_queue)); +#endif + +#ifdef SW_TX_QUEUE + printk("swq.be_queue:%d\n",skb_queue_len(&pstat->swq.be_queue)); + printk("swq.bk_queue:%d\n",skb_queue_len(&pstat->swq.bk_queue)); + printk("swq.vi_queue:%d\n",skb_queue_len(&pstat->swq.vi_queue)); + printk("swq.vo_queue:%d\n",skb_queue_len(&pstat->swq.vo_queue)); +#endif + +#if defined(WIFI_WMM) && defined(WMM_APSD) + hd = pstat->VO_dz_queue->head; + tl = pstat->VO_dz_queue->tail; + printk("VO_dz_queue:%d\n",CIRC_CNT(hd, tl, NUM_APSD_TXPKT_QUEUE)); + hd = pstat->VI_dz_queue->head; + tl = pstat->VI_dz_queue->tail; + printk("VI_dz_queue:%d\n",CIRC_CNT(hd, tl, NUM_APSD_TXPKT_QUEUE)); + hd = pstat->BE_dz_queue->head; + tl = pstat->BE_dz_queue->tail; + printk("BE_dz_queue:%d\n",CIRC_CNT(hd, tl, NUM_APSD_TXPKT_QUEUE)); + hd = pstat->BK_dz_queue->head; + tl = pstat->BK_dz_queue->tail; + printk("BK_dz_queue:%d\n",CIRC_CNT(hd, tl, NUM_APSD_TXPKT_QUEUE)); +#endif + +#if defined(WIFI_WMM) + hd = pstat->MGT_dz_queue->head; + tl = pstat->MGT_dz_queue->tail; + printk("BK_dz_queue:%d\n",CIRC_CNT(hd, tl, NUM_DZ_MGT_QUEUE)); +#endif + + return; + +} +#endif + +#ifdef CONFIG_PCI_HCI +void free_sta_tx_skb(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef WIFI_WMM + int hd, tl; +#endif + struct sk_buff *pskb; + + // free all skb in dz_queue + while (skb_queue_len(&pstat->dz_queue)) { + pskb = skb_dequeue(&pstat->dz_queue); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + +#ifdef SW_TX_QUEUE + while (skb_queue_len(&pstat->swq.be_queue)) { + pskb = skb_dequeue(&pstat->swq.be_queue); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + while (skb_queue_len(&pstat->swq.bk_queue)) { + pskb = skb_dequeue(&pstat->swq.bk_queue); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + while (skb_queue_len(&pstat->swq.vi_queue)) { + pskb = skb_dequeue(&pstat->swq.vi_queue); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + while (skb_queue_len(&pstat->swq.vo_queue)) { + pskb = skb_dequeue(&pstat->swq.vo_queue); + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } +#endif + +#if defined(WIFI_WMM) && defined(WMM_APSD) + hd = pstat->VO_dz_queue->head; + tl = pstat->VO_dz_queue->tail; + while (CIRC_CNT(hd, tl, NUM_APSD_TXPKT_QUEUE)) { + pskb = pstat->VO_dz_queue->pSkb[tl]; + rtl_kfree_skb(priv, pskb, _SKB_TX_); + tl++; + tl = tl & (NUM_APSD_TXPKT_QUEUE - 1); + } + pstat->VO_dz_queue->head = 0; + pstat->VO_dz_queue->tail = 0; + + hd = pstat->VI_dz_queue->head; + tl = pstat->VI_dz_queue->tail; + while (CIRC_CNT(hd, tl, NUM_APSD_TXPKT_QUEUE)) { + pskb = pstat->VI_dz_queue->pSkb[tl]; + rtl_kfree_skb(priv, pskb, _SKB_TX_); + tl++; + tl = tl & (NUM_APSD_TXPKT_QUEUE - 1); + } + pstat->VI_dz_queue->head = 0; + pstat->VI_dz_queue->tail = 0; + + hd = pstat->BE_dz_queue->head; + tl = pstat->BE_dz_queue->tail; + while (CIRC_CNT(hd, tl, NUM_APSD_TXPKT_QUEUE)) { + pskb = pstat->BE_dz_queue->pSkb[tl]; + rtl_kfree_skb(priv, pskb, _SKB_TX_); + tl++; + tl = tl & (NUM_APSD_TXPKT_QUEUE - 1); + } + pstat->BE_dz_queue->head = 0; + pstat->BE_dz_queue->tail = 0; + + hd = pstat->BK_dz_queue->head; + tl = pstat->BK_dz_queue->tail; + while (CIRC_CNT(hd, tl, NUM_APSD_TXPKT_QUEUE)) { + pskb = pstat->BK_dz_queue->pSkb[tl]; + rtl_kfree_skb(priv, pskb, _SKB_TX_); + tl++; + tl = tl & (NUM_APSD_TXPKT_QUEUE - 1); + } + pstat->BK_dz_queue->head = 0; + pstat->BK_dz_queue->tail = 0; +#endif +#if defined(WIFI_WMM) + hd = pstat->MGT_dz_queue->head; + tl = pstat->MGT_dz_queue->tail; + while (CIRC_CNT(hd, tl, NUM_DZ_MGT_QUEUE)) { + struct tx_insn *ptx_insn = pstat->MGT_dz_queue->ptx_insn[tl]; + release_mgtbuf_to_poll(priv, ptx_insn->pframe); + release_wlanhdr_to_poll(priv, ptx_insn->phdr); + kfree(ptx_insn); + tl++; + tl = tl & (NUM_DZ_MGT_QUEUE - 1); + } + pstat->MGT_dz_queue->head = 0; + pstat->MGT_dz_queue->tail = 0; + + +#ifdef DZ_ADDBA_RSP + pstat->dz_addba.used = 0; +#endif +#endif +} +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +void free_sta_tx_skb(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int i; + for (i = 0; i < MAX_STA_TX_SERV_QUEUE; ++i) { +#ifdef CONFIG_TCP_ACK_TXAGG + rtw_tcpack_servq_flush(priv, &pstat->tcpack_queue[i]); +#endif + rtw_txservq_flush(priv, &pstat->tx_queue[i]); + } +} +#endif + +void free_sta_skb(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int i, j; + struct list_head frag_list; + struct sk_buff *pskb; + unsigned long flags; + + free_sta_tx_skb(priv,pstat); + + // free all skb in frag_list + INIT_LIST_HEAD(&frag_list); + + DEFRAG_LOCK(flags); + list_splice_init(&pstat->frag_list, &frag_list); + DEFRAG_UNLOCK(flags); + + unchainned_all_frag(priv, &frag_list); + + // free all skb in rc queue + SMP_LOCK_REORDER_CTRL(flags); + for (i=0; i<8; i++) { + pstat->rc_entry[i].start_rcv = FALSE; + for (j=0; jrc_entry[i].packet_q[j]) { + pskb = pstat->rc_entry[i].packet_q[j]; + rtl_kfree_skb(priv, pskb, _SKB_RX_); + pstat->rc_entry[i].packet_q[j] = NULL; + } + } + } + SMP_UNLOCK_REORDER_CTRL(flags); +} + +void free_sta_frag_list(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + struct list_head frag_list; + unsigned long flags; + + // free all skb in frag_list + INIT_LIST_HEAD(&frag_list); + + DEFRAG_LOCK(flags); + list_del_init(&pstat->defrag_list); + list_splice_init(&pstat->frag_list, &frag_list); + pstat->frag_count = 0; + DEFRAG_UNLOCK(flags); + + unchainned_all_frag(priv, &frag_list); +} + +void release_stainfo(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int i; + unsigned long flags; + + if (priv->pshare->is_40m_bw && (pstat->IOTPeer == HT_IOT_PEER_MARVELL)) + + { + clearSTABitMap(&priv->pshare->marvellMapBit, pstat->aid); + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if((GET_CHIP_VER(priv)==VERSION_8812E)||(GET_CHIP_VER(priv)==VERSION_8881A)){ + } + else +#endif + if ((orSTABitMap(&priv->pshare->marvellMapBit) == 0) && + (priv->pshare->Reg_RRSR_2 != 0) && (priv->pshare->Reg_81b != 0)) + { +#if defined(CONFIG_PCI_HCI) + RTL_W8(RRSR+2, priv->pshare->Reg_RRSR_2); + RTL_W8(0x81b, priv->pshare->Reg_81b); + priv->pshare->Reg_RRSR_2 = 0; + priv->pshare->Reg_81b = 0; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_40M_RRSR_SC_change(priv); +#endif + } + } + + update_intel_sta_bitmap(priv, pstat, 1); +#if defined(WIFI_11N_2040_COEXIST_EXT) + update_40m_staMap(priv, pstat, 1); +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + // avoid xmit_tasklet deadlock when receiving auth req under heavy TX traffic +#ifdef WDS + pstat->state &= WIFI_WDS; +#else + pstat->state = 0; +#endif +#endif + + // flush the stainfo cache + //if (!memcmp(pstat->hwaddr, priv->stainfo_cache.hwaddr, MACADDRLEN)) + // memset(&(priv->stainfo_cache), 0, sizeof(priv->stainfo_cache)); + if (pstat == priv->pstat_cache) + priv->pstat_cache = NULL; + + // delete all list + // BUT do NOT delete hash list + asoc_list_del(priv, pstat); + auth_list_del(priv, pstat); + sleep_list_del(priv, pstat); + wakeup_list_del(priv, pstat); + + DEFRAG_LOCK(flags); + if (!list_empty(&(pstat->defrag_list))) + list_del_init(&(pstat->defrag_list)); + DEFRAG_UNLOCK(flags); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + rtw_pspoll_sta_delete(priv, pstat); +#endif + +#ifdef CONFIG_PCI_HCI + // to avoid add RAtid fail + if (!list_empty(&(pstat->addRAtid_list))) + list_del_init(&(pstat->addRAtid_list)); + + if (!list_empty(&(pstat->addrssi_list))) + list_del_init(&(pstat->addrssi_list)); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + #if defined(CONFIG_USB_HCI) + rtw_flush_h2c_cmd_queue(priv, pstat); + #endif +#elif defined(CONFIG_RTL_88E_SUPPORT) + #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + rtw_flush_cmd_queue(priv, pstat); + #endif +#endif + +#ifdef SW_TX_QUEUE +#ifdef SMP_SYNC + int locked=0; + SMP_TRY_LOCK_XMIT(flags,locked); +#endif + if (timer_pending(&pstat->swq.beq_timer)) + del_timer(&pstat->swq.beq_timer); + if (timer_pending(&pstat->swq.bkq_timer)) + del_timer(&pstat->swq.bkq_timer); + if (timer_pending(&pstat->swq.viq_timer)) + del_timer(&pstat->swq.viq_timer); + if (timer_pending(&pstat->swq.voq_timer)) + del_timer(&pstat->swq.voq_timer); +#ifdef SMP_SYNC + if(locked) + SMP_UNLOCK_XMIT(flags); +#endif + +#endif + +#ifdef CONFIG_IEEE80211W + if (timer_pending(&pstat->SA_timer)) + del_timer(&pstat->SA_timer); +#endif + + // free all queued skb + free_sta_skb(priv, pstat); + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + for (i = 0; i < MAX_STA_TX_SERV_QUEUE; ++i) { + _rtw_spinlock_free(&(pstat->tx_queue[i].xframe_queue.lock)); +#ifdef CONFIG_TCP_ACK_TXAGG + _rtw_spinlock_free(&(pstat->tcpack_queue[i].xframe_queue.lock)); +#endif + } +#endif + +#ifdef CONFIG_RTK_MESH + SMP_LOCK_MESH_MP_HDR(flags); + if (!list_empty(&(pstat->mesh_mp_ptr))) + list_del_init(&(pstat->mesh_mp_ptr)); + SMP_UNLOCK_MESH_MP_HDR(flags); + + pstat->mesh_neighbor_TBL.State = MP_UNUSED; // reset state (clean is high priority) + +//yschen 2009-03-04 +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) // 1.Proxy_table in root interface NOW!! 2.Spare for Mesh work with Multiple AP (Please see Mantis 0000107 for detail) + if(IS_ROOT_INTERFACE(priv)) +#endif + { + remove_proxy_table(priv, pstat->hwaddr); + clear_route_info(priv, pstat->hwaddr); + } +#endif + +#ifdef A4_STA + if (!list_empty(&pstat->a4_sta_list)) + list_del_init(&pstat->a4_sta_list); +#endif + + // remove key in CAM + if (pstat->dot11KeyMapping.keyInCam == TRUE) { + if (GET_ROOT(priv)->drv_state & DRV_STATE_OPEN) { + if (CamDeleteOneEntry(priv, pstat->hwaddr, 0, 0)) { + pstat->dot11KeyMapping.keyInCam = FALSE; + priv->pshare->CamEntryOccupied--; + } +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + /* for wapi, one state take two cam entry */ + if (CamDeleteOneEntry(priv, pstat->hwaddr, 0, 0)) { + pstat->dot11KeyMapping.keyInCam = FALSE; + priv->pshare->CamEntryOccupied--; + } +#endif + } + } + + SMP_LOCK_REORDER_CTRL(flags); + for (i=0; ipshare->rc_timer[i].pstat == pstat) + priv->pshare->rc_timer[i].pstat = NULL; + SMP_UNLOCK_REORDER_CTRL(flags); + +#ifdef WDS + pstat->state &= WIFI_WDS; +#else + pstat->state = 0; +#endif + +#ifdef INDICATE_LINK_CHANGE + indicate_sta_link_change(priv, pstat, DECREASE, __FUNCTION__); +#endif + +#ifdef TX_SHORTCUT + memset(pstat->tx_sc_ent, 0, sizeof(pstat->tx_sc_ent)); +#endif + +#ifdef RX_SHORTCUT + for (i=0; irx_sc_ent[i].rx_payload_offset = 0; +#endif + +#ifdef INCLUDE_WPA_PSK + if (timer_pending(&pstat->wpa_sta_info->resendTimer)) { + del_timer(&pstat->wpa_sta_info->resendTimer); + } +#endif + + release_remapAid(priv, pstat); + +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + ODM_CmnInfoPtrArrayHook(ODMPTR , ODM_CMNINFO_STA_STATUS, pstat->aid, 0); +#endif +#ifdef SUPPORT_TX_AMSDU + for (i=0; i<8; i++) + free_skb_queue(priv, &pstat->amsdu_tx_que[i]); +#endif + +#ifdef BEAMFORMING_SUPPORT + if (priv->pmib->dot11RFEntry.txbf == 1 && (GET_CHIP_VER(priv) == VERSION_8812E || GET_CHIP_VER(priv) == VERSION_8192E || GET_CHIP_VER(priv) == VERSION_8814A) ) + { + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s,\n", __FUNCTION__)); + + pBeamformingInfo->CurDelBFerBFeeEntrySel = BFerBFeeEntry; + + if(Beamforming_DeInitEntry(priv, pstat->hwaddr)) + Beamforming_Notify(priv); + } +#endif +#if 1 +#if defined(BR_SHORTCUT) && defined(RTL_CACHED_BR_STA) + release_brsc_cache(pstat->hwaddr); +#endif +#if defined(CONFIG_RTL_FASTBRIDGE) + rtl_fb_del_entry(pstat->hwaddr); +#endif +#else +#ifdef BR_SHORTCUT + clear_shortcut_cache(); +#endif +#endif +#ifdef CONFIG_RTL_WAPI_SUPPORT + free_sta_wapiInfo(priv, pstat); +#endif +} + + +struct stat_info *alloc_stainfo(struct rtl8192cd_priv *priv, unsigned char *hwaddr, int id) +{ + unsigned long flags; + unsigned int i,index; + struct list_head *phead, *plist; + struct stat_info *pstat; + + SAVE_INT_AND_CLI(flags); + + if (id < 0) { // not from FAST_RECOVERY + // any free sta info? + for(i=0; ipshare->aidarray[i] && (priv->pshare->aidarray[i]->used == FALSE)) + { + priv->pshare->aidarray[i]->priv = priv; + priv->pshare->aidarray[i]->used = TRUE; + pstat = &(priv->pshare->aidarray[i]->station); + memcpy(pstat->hwaddr, hwaddr, MACADDRLEN); + init_stainfo(priv, pstat); +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef RATEADAPTIVE_BY_ODM + ODM_RAInfo_Init(ODMPTR, pstat->aid); +#else + priv->pshare->RaInfo[pstat->aid].pstat = pstat; + RateAdaptiveInfoInit(&priv->pshare->RaInfo[pstat->aid]); +#endif + } +#endif + + // insert to hash list + hash_list_add(priv, pstat); + + RESTORE_INT(flags); + return pstat; + } + } + + // allocate new sta info + for(i=0; ipshare->aidarray[i] == NULL) + break; + } + } + else + i = id; + + if (i < NUM_STAT) { +#ifdef RTL8192CD_VARIABLE_USED_DMEM + priv->pshare->aidarray[i] = (struct aid_obj *)rtl8192cd_dmem_alloc(AID_OBJ, &i); +#else +#ifdef PRIV_STA_BUF + priv->pshare->aidarray[i] = alloc_sta_obj(priv); +#else + priv->pshare->aidarray[i] = (struct aid_obj *)kmalloc(sizeof(struct aid_obj), GFP_ATOMIC); +#endif +#endif + if (priv->pshare->aidarray[i] == NULL) + goto no_free_memory; + memset(priv->pshare->aidarray[i], 0, sizeof(struct aid_obj)); + +#ifdef CONFIG_PCI_HCI +#if defined(WIFI_WMM) && defined(WMM_APSD) +#ifdef PRIV_STA_BUF + priv->pshare->aidarray[i]->station.VO_dz_queue = alloc_sta_que(priv); +#else + priv->pshare->aidarray[i]->station.VO_dz_queue = (struct apsd_pkt_queue *)kmalloc(sizeof(struct apsd_pkt_queue), GFP_ATOMIC); +#endif + if (priv->pshare->aidarray[i]->station.VO_dz_queue == NULL) + goto no_free_memory; + memset(priv->pshare->aidarray[i]->station.VO_dz_queue, 0, sizeof(struct apsd_pkt_queue)); + +#ifdef PRIV_STA_BUF + priv->pshare->aidarray[i]->station.VI_dz_queue = alloc_sta_que(priv); +#else + priv->pshare->aidarray[i]->station.VI_dz_queue = (struct apsd_pkt_queue *)kmalloc(sizeof(struct apsd_pkt_queue), GFP_ATOMIC); +#endif + if (priv->pshare->aidarray[i]->station.VI_dz_queue == NULL) + goto no_free_memory; + memset(priv->pshare->aidarray[i]->station.VI_dz_queue, 0, sizeof(struct apsd_pkt_queue)); + +#ifdef PRIV_STA_BUF + priv->pshare->aidarray[i]->station.BE_dz_queue = alloc_sta_que(priv); +#else + priv->pshare->aidarray[i]->station.BE_dz_queue = (struct apsd_pkt_queue *)kmalloc(sizeof(struct apsd_pkt_queue), GFP_ATOMIC); +#endif + if (priv->pshare->aidarray[i]->station.BE_dz_queue == NULL) + goto no_free_memory; + memset(priv->pshare->aidarray[i]->station.BE_dz_queue, 0, sizeof(struct apsd_pkt_queue)); + +#ifdef PRIV_STA_BUF + priv->pshare->aidarray[i]->station.BK_dz_queue = alloc_sta_que(priv); +#else + priv->pshare->aidarray[i]->station.BK_dz_queue = (struct apsd_pkt_queue *)kmalloc(sizeof(struct apsd_pkt_queue), GFP_ATOMIC); +#endif + if (priv->pshare->aidarray[i]->station.BK_dz_queue == NULL) + goto no_free_memory; + memset(priv->pshare->aidarray[i]->station.BK_dz_queue, 0, sizeof(struct apsd_pkt_queue)); +#endif + +#if defined(WIFI_WMM) +#ifdef PRIV_STA_BUF + priv->pshare->aidarray[i]->station.MGT_dz_queue = alloc_sta_mgt_que(priv); +#else + priv->pshare->aidarray[i]->station.MGT_dz_queue = (struct dz_mgmt_queue *)kmalloc(sizeof(struct dz_mgmt_queue), GFP_ATOMIC); +#endif + if (priv->pshare->aidarray[i]->station.MGT_dz_queue == NULL) + goto no_free_memory; + memset(priv->pshare->aidarray[i]->station.MGT_dz_queue, 0, sizeof(struct dz_mgmt_queue)); +#endif +#endif // CONFIG_PCI_HCI + +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) +#ifdef PRIV_STA_BUF + priv->pshare->aidarray[i]->station.wpa_sta_info = alloc_wpa_buf(priv); +#else + priv->pshare->aidarray[i]->station.wpa_sta_info = (WPA_STA_INFO *)kmalloc(sizeof(WPA_STA_INFO), GFP_ATOMIC); +#endif + if (priv->pshare->aidarray[i]->station.wpa_sta_info == NULL) + goto no_free_memory; + memset(priv->pshare->aidarray[i]->station.wpa_sta_info, 0, sizeof(WPA_STA_INFO)); +#endif + +#if defined(WIFI_HAPD) || defined(RTK_NL80211) + memset(priv->pshare->aidarray[i]->station.wpa_ie, 0, 256); +#ifndef HAPD_DRV_PSK_WPS + memset(priv->pshare->aidarray[i]->station.wps_ie, 0, 256); +#endif +#endif + + priv->pshare->aidarray[i]->priv = priv; + INIT_LIST_HEAD(&(priv->pshare->aidarray[i]->station.hash_list)); + priv->pshare->aidarray[i]->station.aid = i + 1; //aid 0 is reserved for AP + priv->pshare->aidarray[i]->used = TRUE; + pstat = &(priv->pshare->aidarray[i]->station); +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv)==VERSION_8188E) { + +#ifdef RATEADAPTIVE_BY_ODM + ODM_RAInfo_Init(ODMPTR, pstat->aid); +#else + priv->pshare->RaInfo[i + 1].pstat = pstat; + RateAdaptiveInfoInit(&priv->pshare->RaInfo[i + 1]); +#endif + } +#endif + + memcpy(pstat->hwaddr, hwaddr, MACADDRLEN); + init_stainfo(priv, pstat); + + // insert to hash list + hash_list_add(priv, pstat); + + RESTORE_INT(flags); + return pstat; + } + + // no more free sta info, check idle sta + for(i=0; ipshare->aidarray[i]->station); + if ((pstat->expire_to == 0) +#ifdef WDS +#ifdef LAZY_WDS + && ((pstat->state & WIFI_WDS_LAZY) || + (!(pstat->state & WIFI_WDS_LAZY) && !(pstat->state & WIFI_WDS))) +#else + && !(pstat->state & WIFI_WDS) +#endif +#endif + ) + { + release_stainfo(priv->pshare->aidarray[i]->priv, pstat); + hash_list_del(priv->pshare->aidarray[i]->priv, pstat); + + priv->pshare->aidarray[i]->used = TRUE; + priv->pshare->aidarray[i]->priv = priv; + memcpy(pstat->hwaddr, hwaddr, MACADDRLEN); + init_stainfo(priv, pstat); +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv)==VERSION_8188E) +#ifdef RATEADAPTIVE_BY_ODM + ODM_RAInfo_Init(ODMPTR, pstat->aid); +#else + RateAdaptiveInfoInit(&priv->pshare->RaInfo[pstat->aid]); +#endif +#endif + // insert to hash list + hash_list_add(priv, pstat); + + RESTORE_INT(flags); + return pstat; + } + } + + RESTORE_INT(flags); + DEBUG_ERR("AID buf is not enough\n"); + return (struct stat_info *)NULL; + +no_free_memory: + + if (priv->pshare->aidarray[i]) { +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + if (priv->pshare->aidarray[i]->station.wpa_sta_info) +#ifdef PRIV_STA_BUF + free_wpa_buf(priv, priv->pshare->aidarray[i]->station.wpa_sta_info); +#else + kfree(priv->pshare->aidarray[i]->station.wpa_sta_info); +#endif +#endif + +#ifdef CONFIG_PCI_HCI +#if defined(WIFI_WMM) && defined(WMM_APSD) +#ifdef PRIV_STA_BUF + if (priv->pshare->aidarray[i]->station.VO_dz_queue) + free_sta_que(priv, priv->pshare->aidarray[i]->station.VO_dz_queue); + if (priv->pshare->aidarray[i]->station.VI_dz_queue) + free_sta_que(priv, priv->pshare->aidarray[i]->station.VI_dz_queue); + if (priv->pshare->aidarray[i]->station.BE_dz_queue) + free_sta_que(priv, priv->pshare->aidarray[i]->station.BE_dz_queue); + if (priv->pshare->aidarray[i]->station.BK_dz_queue) + free_sta_que(priv, priv->pshare->aidarray[i]->station.BK_dz_queue); +#else + if (priv->pshare->aidarray[i]->station.VO_dz_queue) + kfree(priv->pshare->aidarray[i]->station.VO_dz_queue); + if (priv->pshare->aidarray[i]->station.VI_dz_queue) + kfree(priv->pshare->aidarray[i]->station.VI_dz_queue); + if (priv->pshare->aidarray[i]->station.BE_dz_queue) + kfree(priv->pshare->aidarray[i]->station.BE_dz_queue); + if (priv->pshare->aidarray[i]->station.BK_dz_queue) + kfree(priv->pshare->aidarray[i]->station.BK_dz_queue); +#endif +#endif + +#if defined(WIFI_WMM) +#ifdef PRIV_STA_BUF + if (priv->pshare->aidarray[i]->station.MGT_dz_queue) + free_sta_mgt_que(priv, priv->pshare->aidarray[i]->station.MGT_dz_queue); +#else + if (priv->pshare->aidarray[i]->station.MGT_dz_queue) + kfree(priv->pshare->aidarray[i]->station.MGT_dz_queue); + +#endif +#endif +#endif // CONFIG_PCI_HCI + +#ifdef RTL8192CD_VARIABLE_USED_DMEM + rtl8192cd_dmem_free(AID_OBJ, &i); +#else +#ifdef PRIV_STA_BUF + free_sta_obj(priv, priv->pshare->aidarray[i]); +#else + kfree(priv->pshare->aidarray[i]); +#endif +#endif + priv->pshare->aidarray[i] = NULL; + } + + RESTORE_INT(flags); + DEBUG_ERR("No free memory to allocate station info\n"); + return NULL; +} + + +int del_station(struct rtl8192cd_priv *priv, struct stat_info *pstat, int send_disasoc) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + DOT11_DISASSOCIATION_IND Disassociation_Ind; + + if (!netif_running(priv->dev)) + return 0; + + if (pstat == NULL) + return 0; + + if (!list_empty(&pstat->asoc_list)) + { + if (IEEE8021X_FUN) + { +#ifndef WITHOUT_ENQUEUE + memcpy((void *)Disassociation_Ind.MACAddr, (void *)pstat->hwaddr, MACADDRLEN); + Disassociation_Ind.EventId = DOT11_EVENT_DISASSOCIATION_IND; + Disassociation_Ind.IsMoreEvent = 0; + Disassociation_Ind.Reason = _STATS_OTHER_; + Disassociation_Ind.tx_packets = pstat->tx_pkts; + Disassociation_Ind.rx_packets = pstat->rx_pkts; + Disassociation_Ind.tx_bytes = pstat->tx_bytes; + Disassociation_Ind.rx_bytes = pstat->rx_bytes; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Disassociation_Ind, + sizeof(DOT11_DISASSOCIATION_IND)); +#endif +#if defined(INCLUDE_WPA_PSK) +#ifdef RTK_NL80211 + if (IS_CFG80211_IFACE(priv)) + nl80211_psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, pstat->hwaddr, NULL, 0); + else +#endif + psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, pstat->hwaddr, NULL, 0); +#elif defined(WIFI_HAPD) || defined(RTK_NL80211) + nl80211_psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, pstat->hwaddr, NULL, 0); +#endif + +#ifdef RTK_NL80211 + if (IS_CFG80211_IFACE(priv)) + event_indicate_cfg80211(priv, pstat->hwaddr, CFG80211_DEL_STA, NULL); +#endif + +#ifdef WIFI_HAPD + event_indicate_hapd(priv, pstat->hwaddr, HAPD_EXIRED, NULL); +#ifdef HAPD_DRV_PSK_WPS + event_indicate(priv, pstat->hwaddr, 2); +#endif +#else + event_indicate(priv, pstat->hwaddr, 2); +#endif + } + + if (send_disasoc) + issue_disassoc(priv, pstat->hwaddr, _RSON_UNSPECIFIED_); + + if (pstat->expire_to > 0) + { + SAVE_INT_AND_CLI(flags); + cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); + check_sta_characteristic(priv, pstat, DECREASE); + RESTORE_INT(flags); + + LOG_MSG("A STA is deleted by application program - %02X:%02X:%02X:%02X:%02X:%02X\n", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); + } + } + + free_stainfo(priv, pstat); + +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)); + start_clnt_lookup(priv, DONTRESCAN); + } +#endif + + return 1; +} + + +int free_stainfo(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned int i; + + if (pstat == (struct stat_info *)NULL) + { + DEBUG_ERR("illegal free an NULL stat obj\n"); + return FAIL; + } + + for(i=0; ipshare->aidarray[i] && +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + (priv->pshare->aidarray[i]->priv == priv) && +#endif + (priv->pshare->aidarray[i]->used == TRUE) && + (&(priv->pshare->aidarray[i]->station) == pstat)) + { + DEBUG_INFO("free station info of %02X%02X%02X%02X%02X%02X\n", + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); + + SAVE_INT_AND_CLI(flags); +#ifdef WDS +#ifdef LAZY_WDS + if (!(pstat->state & WIFI_WDS) || (pstat->state & WIFI_WDS_LAZY)) +#else + if (!(pstat->state & WIFI_WDS)) +#endif +#endif + { + priv->pshare->aidarray[i]->used = FALSE; + // remove from hash_list + hash_list_del(priv, pstat); +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) && !defined(RATEADAPTIVE_BY_ODM) + if (GET_CHIP_VER(priv)==VERSION_8188E) + priv->pshare->RaInfo[pstat->aid].pstat = NULL; +#endif + } + + release_stainfo(priv, pstat); + RESTORE_INT(flags); + return SUCCESS; + } + } + +#if defined(CONFIG_RTL_WAPI_SUPPORT) + wapiAssert(pstat->wapiInfo==NULL); +#endif + DEBUG_ERR("pstat can not be freed \n"); + return FAIL; +} + + +/* any station allocated can be searched by hash list */ +__MIPS16 +__IRAM_IN_865X +struct stat_info *get_stainfo(struct rtl8192cd_priv *priv, const unsigned char *hwaddr) +{ + struct list_head *phead, *plist; + struct stat_info *pstat; + unsigned int index; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + +#ifdef RTK_NL80211 + if(hwaddr == NULL) + return (struct stat_info *)NULL; +#endif + + //if (!memcmp(hwaddr, priv->stainfo_cache.hwaddr, MACADDRLEN) && priv->stainfo_cache.pstat) + pstat = priv->pstat_cache; + +#ifdef MULTI_MAC_CLONE + if ((priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) && MCLONE_NUM > 0) { + if (pstat && !memcmp(hwaddr, pstat->hwaddr, MACADDRLEN) && pstat->mclone_id == ACTIVE_ID) + return pstat; + } + else +#endif + { + if (pstat && !memcmp(hwaddr, pstat->hwaddr, MACADDRLEN)) + return pstat; + } + + index = wifi_mac_hash(hwaddr); + phead = &priv->stat_hash[index]; + + SMP_LOCK_HASH_LIST(flags); + + plist = phead->next; + while (plist != phead) + { + pstat = list_entry(plist, struct stat_info ,hash_list); + plist = plist->next; + + if (!(memcmp((void *)pstat->hwaddr, (void *)hwaddr, MACADDRLEN))) { // if found the matched address +#ifdef MULTI_MAC_CLONE + if (!(priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) || + ((priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) && + !priv->pmib->ethBrExtInfo.macclone_enable) || + ((priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) && + priv->pmib->ethBrExtInfo.macclone_enable & (pstat->mclone_id == ACTIVE_ID))) +#endif + { + priv->pstat_cache = pstat; + goto exit; + } + } +#ifdef CONFIG_PCI_HCI + if (plist == plist->next) + break; +#endif + } + + pstat = NULL; + +exit: + SMP_UNLOCK_HASH_LIST(flags); + + return pstat; +} + + +#ifdef HW_FILL_MACID +__MIPS16 +__IRAM_IN_865X +struct stat_info *get_HW_mapping_sta(struct rtl8192cd_priv *priv, unsigned char macID) +{ + struct aid_obj *obj; + + if(macID > 0) + { + if((macID >= 0x7E)) + return (struct stat_info *)NULL; + else + return &(priv->pshare->aidarray[macID-1]->station); + + /* + obj = priv->pshare->aidarray[macID-1]; + + if(obj->priv == priv) + return &(priv->pshare->aidarray[macID-1]->station); + else + { + printk("obj error at macID %x \n",macID); + return (struct stat_info *)NULL; + }*/ + + } +} +#endif // #ifdef HW_FILL_MACID + +/* aid is only meaningful for assocated stations... */ +struct stat_info *get_aidinfo(struct rtl8192cd_priv *priv, unsigned int aid) +{ + struct list_head *plist, *phead; + struct stat_info *pstat = NULL; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + if (aid == 0) + return (struct stat_info *)NULL; + + SMP_LOCK_ASOC_LIST(flags); + + phead = &priv->asoc_list; + plist = phead->next; + + while (plist != phead) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + if (pstat->aid == aid) + goto exit; + } + pstat = NULL; +exit: + SMP_UNLOCK_ASOC_LIST(flags); + + return pstat; +} + +#if defined(TXREPORT) +struct stat_info *get_macidinfo(struct rtl8192cd_priv *priv, unsigned int aid) +{ + struct list_head *plist, *phead; + struct stat_info *pstat = NULL; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + if (aid == 0) + return (struct stat_info *)NULL; + + SMP_LOCK_ASOC_LIST(flags); + + phead = &priv->asoc_list; + plist = phead->next; + + while (plist != phead) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + if (REMAP_AID(pstat) == aid) + goto exit; + } + pstat = NULL; +exit: + SMP_UNLOCK_ASOC_LIST(flags); + + return pstat; +} +#endif + +int IS_BSSID(struct rtl8192cd_priv *priv, unsigned char *da) +{ + unsigned char *bssid; + bssid = priv->pmib->dot11StationConfigEntry.dot11Bssid; + + if (!memcmp(da, bssid, 6)) + return TRUE; + else + return FALSE; +} + + +int IS_MCAST(unsigned char *da) +{ + if ((*da) & 0x01) + return TRUE; + else + return FALSE; +} + +int IS_BCAST2(unsigned char *da) +{ + if ((*da) == 0xff) + return TRUE; + else + return FALSE; +} + + + UINT8 oui_rfc1042[] = {0x00, 0x00, 0x00}; + UINT8 oui_8021h[] = {0x00, 0x00, 0xf8}; + UINT8 oui_cisco[] = {0x00, 0x00, 0x0c}; +int p80211_stt_findproto(UINT16 proto) +{ + /* Always return found for now. This is the behavior used by the */ + /* Zoom Win95 driver when 802.1h mode is selected */ + /* TODO: If necessary, add an actual search we'll probably + need this to match the CMAC's way of doing things. + Need to do some testing to confirm. + */ + + if (proto == 0x80f3 || /* APPLETALK */ + proto == 0x8137 ) /* DIX II IPX */ + return 1; + + return 0; +} + + +void eth_2_llc(struct wlan_ethhdr_t *pethhdr, struct llc_snap *pllc_snap) +{ + pllc_snap->llc_hdr.dsap=pllc_snap->llc_hdr.ssap=0xAA; + pllc_snap->llc_hdr.ctl=0x03; + + if (p80211_stt_findproto(ntohs(pethhdr->type))) { + memcpy((void *)pllc_snap->snap_hdr.oui, oui_8021h, WLAN_IEEE_OUI_LEN); + } + else { + memcpy((void *)pllc_snap->snap_hdr.oui, oui_rfc1042, WLAN_IEEE_OUI_LEN); + } + pllc_snap->snap_hdr.type = pethhdr->type; +} + + +void eth2_2_wlanhdr(struct rtl8192cd_priv *priv, struct wlan_ethhdr_t *pethhdr, struct tx_insn *txcfg) +{ + unsigned char *pframe = txcfg->phdr; + unsigned int to_fr_ds = get_tofr_ds(pframe); + + switch (to_fr_ds) + { + case 0x00: + memcpy(GetAddr1Ptr(pframe), (const void *)pethhdr->daddr, WLAN_ADDR_LEN); + memcpy(GetAddr2Ptr(pframe), (const void *)pethhdr->saddr, WLAN_ADDR_LEN); + memcpy(GetAddr3Ptr(pframe), BSSID, WLAN_ADDR_LEN); + break; + case 0x01: + { +#ifdef MCAST2UI_REFINE + if (txcfg->fr_type == _SKB_FRAME_TYPE_) + memcpy(GetAddr1Ptr(pframe), (const void *) &((struct sk_buff *)txcfg->pframe)->cb[10], WLAN_ADDR_LEN); + else +#endif + memcpy(GetAddr1Ptr(pframe), (const void *)pethhdr->daddr, WLAN_ADDR_LEN); + memcpy(GetAddr2Ptr(pframe), BSSID, WLAN_ADDR_LEN); + memcpy(GetAddr3Ptr(pframe), (const void *)pethhdr->saddr, WLAN_ADDR_LEN); + } + break; + case 0x02: + { + memcpy(GetAddr1Ptr(pframe), BSSID, WLAN_ADDR_LEN); + memcpy(GetAddr2Ptr(pframe), (const void *)pethhdr->saddr, WLAN_ADDR_LEN); + memcpy(GetAddr3Ptr(pframe), (const void *)pethhdr->daddr, WLAN_ADDR_LEN); + } + break; + case 0x03: +#ifdef WDS +#ifdef MP_TEST + if (OPMODE & WIFI_MP_STATE) + memcpy(GetAddr1Ptr(pframe), (const void *)pethhdr->daddr, WLAN_ADDR_LEN); + else +#endif +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s) + memcpy(GetAddr1Ptr(pframe), txcfg->nhop_11s, WLAN_ADDR_LEN); + else +#endif + memcpy(GetAddr1Ptr(pframe), priv->pmib->dot11WdsInfo.entry[txcfg->wdsIdx].macAddr, WLAN_ADDR_LEN); + +#ifdef MP_TEST + if (OPMODE & WIFI_MP_STATE) + memcpy(GetAddr2Ptr(pframe), priv->dev->dev_addr, WLAN_ADDR_LEN); + else +#endif + +#ifdef __DRAYTEK_OS__ + memcpy(GetAddr2Ptr(pframe), priv->dev->dev_addr, WLAN_ADDR_LEN); +#else +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s) + memcpy(GetAddr2Ptr(pframe), GET_MY_HWADDR, WLAN_ADDR_LEN); + else +#endif // CONFIG_RTK_MESH + memcpy(GetAddr2Ptr(pframe), priv->wds_dev[txcfg->wdsIdx]->dev_addr , WLAN_ADDR_LEN); +#endif + memcpy(GetAddr3Ptr(pframe), (const void *)pethhdr->daddr, WLAN_ADDR_LEN); + memcpy(GetAddr4Ptr(pframe), (const void *)pethhdr->saddr, WLAN_ADDR_LEN); + +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s && is_qos_data(pframe)) + memset( pframe+WLAN_HDR_A4_LEN, 0, 2); // qos +#endif // CONFIG_RTK_MESH + +#else // not WDS +#ifdef CONFIG_RTK_MESH + if(txcfg->is_11s) { + memcpy(GetAddr1Ptr(pframe), txcfg->nhop_11s, WLAN_ADDR_LEN); + memcpy(GetAddr2Ptr(pframe), GET_MY_HWADDR, WLAN_ADDR_LEN); + memcpy(GetAddr3Ptr(pframe), (const void *)pethhdr->daddr, WLAN_ADDR_LEN); + memcpy(GetAddr4Ptr(pframe), (const void *)pethhdr->saddr, WLAN_ADDR_LEN); + + //if((*pframe) & 0x80) //if qos is enable, the bit 7 of frame control will set to 1 + if(is_qos_data(pframe)) + memset(pframe+WLAN_HDR_A4_LEN, 0, 2); // qos + } else +#endif // CONFIG_RTK_MESH + +#ifdef A4_STA + if (priv->pshare->rf_ft_var.a4_enable && txcfg->pstat && + (txcfg->pstat->state & WIFI_A4_STA)) { + memcpy(GetAddr1Ptr(pframe), txcfg->pstat->hwaddr, WLAN_ADDR_LEN); + memcpy(GetAddr2Ptr(pframe), GET_MY_HWADDR, WLAN_ADDR_LEN); + memcpy(GetAddr3Ptr(pframe), (const void *)pethhdr->daddr, WLAN_ADDR_LEN); + memcpy(GetAddr4Ptr(pframe), (const void *)pethhdr->saddr, WLAN_ADDR_LEN); + } + else +#endif + { + DEBUG_ERR("no support for WDS!\n"); + memcpy(GetAddr1Ptr(pframe), (const void *)pethhdr->daddr, WLAN_ADDR_LEN); + memcpy(GetAddr2Ptr(pframe), (const void *)BSSID, WLAN_ADDR_LEN); + memcpy(GetAddr3Ptr(pframe), (const void *)pethhdr->saddr, WLAN_ADDR_LEN); + } // else of if(txcfg->is_11s) +#endif // WDS + break; + } +} + + +int skb_p80211_to_ether(struct net_device *dev, int wep_mode, struct rx_frinfo *pfrinfo) +{ + UINT to_fr_ds; + INT payload_length; + INT payload_offset, trim_pad; + UINT8 daddr[WLAN_ETHADDR_LEN]; + UINT8 saddr[WLAN_ETHADDR_LEN]; + UINT8 *pframe; +#ifdef CONFIG_RTK_MESH + INT mesh_header_len=0; +#endif + struct wlan_hdr *w_hdr; + struct wlan_ethhdr_t *e_hdr; + struct wlan_llc_t *e_llc; + struct wlan_snap_t *e_snap; + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + int wlan_pkt_format; + struct sk_buff *skb = get_pskb(pfrinfo); + +#ifdef RX_SHORTCUT + extern int get_rx_sc_free_entry(struct stat_info *pstat, unsigned char *pframe); + int privacy, idx=0; + struct rx_sc_entry *prxsc_entry = NULL; + struct wlan_hdr wlanhdr; + +#ifndef MESH_AMSDU + struct stat_info *pstat = get_stainfo(priv, GetAddr2Ptr(skb->data)); +#else + struct stat_info *pstat; + + if (pfrinfo->is_11s & 8) + pstat = NULL; + else + pstat = get_stainfo(priv, GetAddr2Ptr(skb->data)); +#endif // MESH_AMSDU +#endif // RX_SHORTCUT + + pframe = get_pframe(pfrinfo); + to_fr_ds = get_tofr_ds(pframe); +#ifndef MESH_AMSDU + payload_offset = get_hdrlen(priv, pframe); +#else + // Get_hdrlen needs to access pframe+32 + // When is_11s=8, the length of a frame might be less than 32 bytes, so we need to protect it + if( pfrinfo->is_11s &8 ) + payload_offset = 0; + else + payload_offset = get_hdrlen(priv, pframe); +#endif // MESH_AMSDU + trim_pad = 0; // _CRCLNG_ has beed subtracted in isr + w_hdr = (struct wlan_hdr *)pframe; + +#ifdef MESH_AMSDU + if( pfrinfo->is_11s &8 ) + { + struct wlan_ethhdr_t eth; + struct MESH_HDR* mhdr = (struct MESH_HDR*) (pframe+sizeof(struct wlan_ethhdr_t)); + const short mlen = (mhdr->mesh_flag &1) ? 16 : 4; + memcpy( ð, pframe, sizeof(struct wlan_ethhdr_t)); + if( mlen &16 ) + memcpy(ð, mhdr->DestMACAddr, WLAN_ETHADDR_LEN<<1 ); + memcpy(skb_pull(skb, mlen), ð, sizeof(struct wlan_ethhdr_t)); + return SUCCESS; + } +#endif + + if ( to_fr_ds == 0x00) { + memcpy(daddr, (const void *)w_hdr->addr1, WLAN_ETHADDR_LEN); + memcpy(saddr, (const void *)w_hdr->addr2, WLAN_ETHADDR_LEN); + } + else if( to_fr_ds == 0x01) { + memcpy(daddr, (const void *)w_hdr->addr1, WLAN_ETHADDR_LEN); + memcpy(saddr, (const void *)w_hdr->addr3, WLAN_ETHADDR_LEN); + } + else if( to_fr_ds == 0x02) { + memcpy(daddr, (const void *)w_hdr->addr3, WLAN_ETHADDR_LEN); + memcpy(saddr, (const void *)w_hdr->addr2, WLAN_ETHADDR_LEN); + } + else { +#ifdef CONFIG_RTK_MESH + // WIFI_11S_MESH = WIFI_QOS_DATA + if(pfrinfo->is_11s &1) { + memcpy(daddr, (const void *)pfrinfo->mesh_header.DestMACAddr, WLAN_ETHADDR_LEN); + memcpy(saddr, (const void *)pfrinfo->mesh_header.SrcMACAddr, WLAN_ETHADDR_LEN); + mesh_header_len = 16; + } + else +#endif // CONFIG_RTK_MESH + { + memcpy(daddr, (const void *)w_hdr->addr3, WLAN_ETHADDR_LEN); + memcpy(saddr, (const void *)w_hdr->addr4, WLAN_ETHADDR_LEN); + } + } + + if (GetPrivacy(pframe)) { +#ifdef CONFIG_RTL_WAPI_SUPPORT + if ((wep_mode == _WAPI_SMS4_)) { + payload_offset += (WAPI_EXT_LEN-WAPI_ALIGNMENT_OFFSET); + trim_pad += (SMS4_MIC_LEN); + } else +#endif + if (((wep_mode == _WEP_40_PRIVACY_) || (wep_mode == _WEP_104_PRIVACY_))) { + payload_offset += 4; + trim_pad += 4; + } + else if ((wep_mode == _TKIP_PRIVACY_)) { + payload_offset += 8; + trim_pad += (8 + 4); + } + else if ((wep_mode == _CCMP_PRIVACY_)) { + payload_offset += 8; + trim_pad += 8; + } + else { + DEBUG_ERR("drop pkt due to unallowed wep_mode privacy=%d\n", wep_mode); + return FAIL; + } + } + +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) + skb->len -= WAPI_ALIGNMENT_OFFSET; +#endif + + payload_length = skb->len - payload_offset - trim_pad; + +#ifdef CONFIG_RTK_MESH + payload_length -= mesh_header_len; +#endif + + if (payload_length <= 0) { + DEBUG_ERR("drop pkt due to payload_length<=0\n"); + return FAIL; + } + + e_hdr = (struct wlan_ethhdr_t *) (pframe + payload_offset); + e_llc = (struct wlan_llc_t *) (pframe + payload_offset); + e_snap = (struct wlan_snap_t *) (pframe + payload_offset + sizeof(struct wlan_llc_t)); + + if ((e_llc->dsap==0xaa) && (e_llc->ssap==0xaa) && (e_llc->ctl==0x03)) + { + if (!memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)) { + wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_RFC1042; + if(!memcmp(&e_snap->type, SNAP_ETH_TYPE_IPX, 2)) + wlan_pkt_format = WLAN_PKT_FORMAT_IPX_TYPE4; + else if(!memcmp(&e_snap->type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)) + wlan_pkt_format = WLAN_PKT_FORMAT_APPLETALK; + } + else if (!memcmp(e_snap->oui, SNAP_HDR_APPLETALK_DDP, WLAN_IEEE_OUI_LEN) && + !memcmp(&e_snap->type, SNAP_ETH_TYPE_APPLETALK_DDP, 2)) + wlan_pkt_format = WLAN_PKT_FORMAT_APPLETALK; + else if (!memcmp(e_snap->oui, oui_8021h, WLAN_IEEE_OUI_LEN)) + wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_TUNNEL; + else if (!memcmp(e_snap->oui, oui_cisco, WLAN_IEEE_OUI_LEN)) + wlan_pkt_format = WLAN_PKT_FORMAT_CDP; + else { + DEBUG_ERR("drop pkt due to invalid frame format!\n"); + return FAIL; + } + } + else if ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) && + (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0)) + wlan_pkt_format = WLAN_PKT_FORMAT_ENCAPSULATED; + else + wlan_pkt_format = WLAN_PKT_FORMAT_OTHERS; + + DEBUG_INFO("Convert 802.11 to 802.3 in format %d\n", wlan_pkt_format); + + if ((wlan_pkt_format == WLAN_PKT_FORMAT_SNAP_RFC1042) || + (wlan_pkt_format == WLAN_PKT_FORMAT_SNAP_TUNNEL) || + (wlan_pkt_format == WLAN_PKT_FORMAT_CDP)) { + /* Test for an overlength frame */ + payload_length = payload_length - sizeof(struct wlan_llc_t) - sizeof(struct wlan_snap_t); + + if ((payload_length+WLAN_ETHHDR_LEN) > WLAN_MAX_ETHFRM_LEN) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + DEBUG_WARN("SNAP frame too large (%d>%d)\n", + (payload_length+WLAN_ETHHDR_LEN), WLAN_MAX_ETHFRM_LEN); + } + +#ifdef RX_SHORTCUT + if (!priv->pmib->dot11OperationEntry.disable_rxsc && pstat) { +#ifdef CONFIG_RTK_MESH + if (pfrinfo->is_11s) + privacy = get_sta_encrypt_algthm(priv, pstat); + else +#endif // CONFIG_RTK_MESH +#ifdef WDS + if (pfrinfo->to_fr_ds == 3) + privacy = priv->pmib->dot11WdsInfo.wdsPrivacy; + else +#endif + privacy = get_sta_encrypt_algthm(priv, pstat); + if ((GetFragNum(pframe)==0) && +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + (!pfrinfo->is_11s || !IS_MCAST(pfrinfo->da)) && +#endif + ((privacy == 0) || +#ifdef CONFIG_RTL_WAPI_SUPPORT + (privacy==_WAPI_SMS4_) || +#endif +#ifdef CONFIG_IEEE80211W + (!UseSwCrypto(priv, pstat, IS_MCAST(GetAddr1Ptr(pframe)), 0)))) +#else + (!UseSwCrypto(priv, pstat, IS_MCAST(GetAddr1Ptr(pframe)))))) +#endif + { + idx = get_rx_sc_free_entry(pstat, pframe); + prxsc_entry = &pstat->rx_sc_ent[idx]; + memcpy((void *)&wlanhdr, pframe, pfrinfo->hdr_len); + } + } +#endif // RX_SHORTCUT + + + /* chop 802.11 header from skb. */ + skb_pull(skb, payload_offset); + + if ((wlan_pkt_format == WLAN_PKT_FORMAT_SNAP_RFC1042) || + (wlan_pkt_format == WLAN_PKT_FORMAT_SNAP_TUNNEL)) + { + /* chop llc header from skb. */ + skb_pull(skb, sizeof(struct wlan_llc_t)); + + /* chop snap header from skb. */ + skb_pull(skb, sizeof(struct wlan_snap_t)); + } + +#ifdef CONFIG_RTK_MESH + /* chop mesh header from skb. */ + skb_pull(skb, mesh_header_len); +#endif + + /* create 802.3 header at beginning of skb. */ + e_hdr = (struct wlan_ethhdr_t *)skb_push(skb, WLAN_ETHHDR_LEN); + if (wlan_pkt_format == WLAN_PKT_FORMAT_CDP) + e_hdr->type = payload_length; + else + e_hdr->type = e_snap->type; + memcpy((void *)e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy((void *)e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + + /* chop off the 802.11 CRC */ + skb_trim(skb, payload_length + WLAN_ETHHDR_LEN); + +#ifdef RX_SHORTCUT + if (prxsc_entry) { + if ((e_hdr->type != htons(0x888e)) && // for WIFI_SIMPLE_CONFIG +#ifdef CONFIG_RTL_WAPI_SUPPORT + (e_hdr->type != htons(ETH_P_WAPI)) && +#endif + (e_hdr->type != htons(ETH_P_ARP)) && + (wlan_pkt_format != WLAN_PKT_FORMAT_CDP)) { + memcpy((void *)&prxsc_entry->rx_wlanhdr, &wlanhdr, pfrinfo->hdr_len); + memcpy((void *)&prxsc_entry->rx_ethhdr, (const void *)e_hdr, sizeof(struct wlan_ethhdr_t)); + prxsc_entry->rx_payload_offset = payload_offset; + prxsc_entry->rx_trim_pad = trim_pad; + pstat->rx_privacy = GetPrivacy(pframe); + +#if defined(CONFIG_RTK_MESH) && defined(RX_RL_SHORTCUT) + if ( (pfrinfo->is_11s &3) && (pfrinfo->mesh_header.mesh_flag &1)) + { + memcpy((void *)&prxsc_entry->rx_wlanhdr.meshhdr.DestMACAddr, (const void *)pfrinfo->mesh_header.DestMACAddr, WLAN_ETHADDR_LEN); + memcpy((void *)&prxsc_entry->rx_wlanhdr.meshhdr.SrcMACAddr, (const void *)pfrinfo->mesh_header.SrcMACAddr, WLAN_ETHADDR_LEN); + } +#endif + } + } +#endif + } + else if ((wlan_pkt_format == WLAN_PKT_FORMAT_OTHERS) || + (wlan_pkt_format == WLAN_PKT_FORMAT_APPLETALK) || + (wlan_pkt_format == WLAN_PKT_FORMAT_IPX_TYPE4)) { + + /* Test for an overlength frame */ + if ( (payload_length + WLAN_ETHHDR_LEN) > WLAN_MAX_ETHFRM_LEN ) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + DEBUG_WARN("IPX/AppleTalk frame too large (%d>%d)\n", + (payload_length + WLAN_ETHHDR_LEN), WLAN_MAX_ETHFRM_LEN); + } + + /* chop 802.11 header from skb. */ + skb_pull(skb, payload_offset); + +#ifdef CONFIG_RTK_MESH + /* chop mesh header from skb. */ + skb_pull(skb, mesh_header_len); +#endif + + /* create 802.3 header at beginning of skb. */ + e_hdr = (struct wlan_ethhdr_t *)skb_push(skb, WLAN_ETHHDR_LEN); + memcpy((void *)e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy((void *)e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + e_hdr->type = htons(payload_length); + + /* chop off the 802.11 CRC */ + skb_trim(skb, payload_length+WLAN_ETHHDR_LEN); + } + else if (wlan_pkt_format == WLAN_PKT_FORMAT_ENCAPSULATED) { + + if ( payload_length > WLAN_MAX_ETHFRM_LEN ) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + DEBUG_WARN("Encapsulated frame too large (%d>%d)\n", + payload_length, WLAN_MAX_ETHFRM_LEN); + } + + /* Chop off the 802.11 header. */ + skb_pull(skb, payload_offset); + +#ifdef CONFIG_RTK_MESH + /* chop mesh header from skb. */ + skb_pull(skb, mesh_header_len); +#endif + + /* chop off the 802.11 CRC */ + skb_trim(skb, payload_length); + } + +#ifdef __KERNEL__ +#ifdef LINUX_2_6_22_ + skb_reset_mac_header(skb); +#else + skb->mac.raw = (unsigned char *) skb->data; /* new MAC header */ +#endif +#endif + + return SUCCESS; +} + + +int strip_amsdu_llc(struct rtl8192cd_priv *priv, struct sk_buff *skb, struct stat_info *pstat) +{ + INT payload_length; + INT payload_offset; + UINT8 daddr[WLAN_ETHADDR_LEN]; + UINT8 saddr[WLAN_ETHADDR_LEN]; + struct wlan_ethhdr_t *e_hdr; + struct wlan_llc_t *e_llc; + struct wlan_snap_t *e_snap; + int pkt_format; + + memcpy(daddr, skb->data, MACADDRLEN); + memcpy(saddr, skb->data+MACADDRLEN, MACADDRLEN); + payload_length = skb->len - WLAN_ETHHDR_LEN; + payload_offset = WLAN_ETHHDR_LEN; + + e_hdr = (struct wlan_ethhdr_t *) (skb->data + payload_offset); + e_llc = (struct wlan_llc_t *) (skb->data + payload_offset); + e_snap = (struct wlan_snap_t *) (skb->data + payload_offset + sizeof(struct wlan_llc_t)); + + if ((e_llc->dsap==0xaa) && (e_llc->ssap==0xaa) && (e_llc->ctl==0x03)) + { + if (!memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)) { + pkt_format = WLAN_PKT_FORMAT_SNAP_RFC1042; + if(!memcmp(&e_snap->type, SNAP_ETH_TYPE_IPX, 2)) + pkt_format = WLAN_PKT_FORMAT_IPX_TYPE4; + else if(!memcmp(&e_snap->type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)) + pkt_format = WLAN_PKT_FORMAT_APPLETALK; + } + else if (!memcmp(e_snap->oui, SNAP_HDR_APPLETALK_DDP, WLAN_IEEE_OUI_LEN) && + !memcmp(&e_snap->type, SNAP_ETH_TYPE_APPLETALK_DDP, 2)) + pkt_format = WLAN_PKT_FORMAT_APPLETALK; + else if (!memcmp(e_snap->oui, oui_8021h, WLAN_IEEE_OUI_LEN)) + pkt_format = WLAN_PKT_FORMAT_SNAP_TUNNEL; + else if (!memcmp(e_snap->oui, oui_cisco, WLAN_IEEE_OUI_LEN)) + pkt_format = WLAN_PKT_FORMAT_CDP; + else { + DEBUG_ERR("drop pkt due to invalid frame format!\n"); + return FAIL; + } + } + else if ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) && + (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0)) + pkt_format = WLAN_PKT_FORMAT_ENCAPSULATED; + else + pkt_format = WLAN_PKT_FORMAT_OTHERS; + + DEBUG_INFO("Convert 802.11 to 802.3 in format %d\n", pkt_format); + + if ((pkt_format == WLAN_PKT_FORMAT_SNAP_RFC1042) || + (pkt_format == WLAN_PKT_FORMAT_SNAP_TUNNEL) || + (pkt_format == WLAN_PKT_FORMAT_CDP)) { + /* Test for an overlength frame */ + payload_length = payload_length - sizeof(struct wlan_llc_t) - sizeof(struct wlan_snap_t); + + if ((payload_length+WLAN_ETHHDR_LEN) > WLAN_MAX_ETHFRM_LEN) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + DEBUG_WARN("SNAP frame too large (%d>%d)\n", + (payload_length+WLAN_ETHHDR_LEN), WLAN_MAX_ETHFRM_LEN); + } + + /* chop 802.11 header from skb. */ + skb_pull(skb, payload_offset); + + if ((pkt_format == WLAN_PKT_FORMAT_SNAP_RFC1042) || + (pkt_format == WLAN_PKT_FORMAT_SNAP_TUNNEL)) + { + /* chop llc header from skb. */ + skb_pull(skb, sizeof(struct wlan_llc_t)); + + /* chop snap header from skb. */ + skb_pull(skb, sizeof(struct wlan_snap_t)); + } + + /* create 802.3 header at beginning of skb. */ + e_hdr = (struct wlan_ethhdr_t *)skb_push(skb, WLAN_ETHHDR_LEN); + if (pkt_format == WLAN_PKT_FORMAT_CDP) + e_hdr->type = payload_length; + else + e_hdr->type = e_snap->type; + memcpy((void *)e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy((void *)e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + + /* chop off the 802.11 CRC */ + skb_trim(skb, payload_length + WLAN_ETHHDR_LEN); + } + else if ((pkt_format == WLAN_PKT_FORMAT_OTHERS) || + (pkt_format == WLAN_PKT_FORMAT_APPLETALK) || + (pkt_format == WLAN_PKT_FORMAT_IPX_TYPE4)) { + + /* Test for an overlength frame */ + if ( (payload_length + WLAN_ETHHDR_LEN) > WLAN_MAX_ETHFRM_LEN ) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + DEBUG_WARN("IPX/AppleTalk frame too large (%d>%d)\n", + (payload_length + WLAN_ETHHDR_LEN), WLAN_MAX_ETHFRM_LEN); + } + + /* chop 802.11 header from skb. */ + skb_pull(skb, payload_offset); + + /* create 802.3 header at beginning of skb. */ + e_hdr = (struct wlan_ethhdr_t *)skb_push(skb, WLAN_ETHHDR_LEN); + memcpy((void *)e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); + memcpy((void *)e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); + e_hdr->type = htons(payload_length); + + /* chop off the 802.11 CRC */ + skb_trim(skb, payload_length+WLAN_ETHHDR_LEN); + } + else if (pkt_format == WLAN_PKT_FORMAT_ENCAPSULATED) { + + if ( payload_length > WLAN_MAX_ETHFRM_LEN ) { + /* A bogus length ethfrm has been sent. */ + /* Is someone trying an oflow attack? */ + DEBUG_WARN("Encapsulated frame too large (%d>%d)\n", + payload_length, WLAN_MAX_ETHFRM_LEN); + } + + /* Chop off the 802.11 header. */ + skb_pull(skb, payload_offset); + + /* chop off the 802.11 CRC */ + skb_trim(skb, payload_length); + } + +#ifdef __KERNEL__ +#ifdef LINUX_2_6_22_ + skb_reset_mac_header(skb); +#else + skb->mac.raw = (unsigned char *) skb->data; /* new MAC header */ +#endif +#endif + + return SUCCESS; +} + + +unsigned int get_sta_encrypt_algthm(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned int privacy = 0; + +#ifdef CONFIG_RTK_MESH + if( isMeshPoint(pstat) ) + return priv->pmib->dot11sKeysTable.dot11Privacy ; +#endif + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (pstat&&pstat->wapiInfo&&pstat->wapiInfo->wapiType!=wapiDisable) + { + return _WAPI_SMS4_; + } + else +#endif + { + if (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm) { + if (pstat) + privacy = pstat->dot11KeyMapping.dot11Privacy; + else + DEBUG_ERR("pstat == NULL\n"); + } + else + { + // legacy system + privacy = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; //could be wep40 or wep104 + } + } + + return privacy; +} + + +unsigned int get_mcast_encrypt_algthm(struct rtl8192cd_priv *priv) +{ + unsigned int privacy; + +#ifdef CONFIG_RTL_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType!=wapiDisable) + { + return _WAPI_SMS4_; + } else +#endif + { + if (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm) { + // check station info + privacy = priv->pmib->dot11GroupKeysTable.dot11Privacy; + } + else { // legacy system + privacy = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm;//must be wep40 or wep104 + } + } + return privacy; +} + + +unsigned int get_privacy(struct rtl8192cd_priv *priv, struct stat_info *pstat, + unsigned int *iv, unsigned int *icv, unsigned int *mic) +{ + unsigned int privacy; + *iv = 0; + *icv = 0; + *mic = 0; + + privacy = get_sta_encrypt_algthm(priv, pstat); + + switch (privacy) + { +#ifdef CONFIG_RTL_WAPI_SUPPORT + case _WAPI_SMS4_: + *iv = WAPI_PN_LEN+2; + *icv = 0; +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) +#ifdef CONFIG_IEEE80211W + if(!(UseSwCrypto(priv, pstat, (pstat ? FALSE : TRUE), 0))) +#else + if(!(UseSwCrypto(priv, pstat, (pstat ? FALSE : TRUE)))) +#endif + *mic = 0; //HW will take care of the mic + else + *mic = SMS4_MIC_LEN; +#else + *mic = SMS4_MIC_LEN; +#endif + break; +#endif + case _NO_PRIVACY_: + *iv = 0; + *icv = 0; + *mic = 0; + break; + case _WEP_40_PRIVACY_: + case _WEP_104_PRIVACY_: + *iv = 4; + *icv = 4; + *mic = 0; + break; + case _TKIP_PRIVACY_: + *iv = 8; + *icv = 4; + *mic = 0; // mic of TKIP is msdu based + break; + case _CCMP_PRIVACY_: + *iv = 8; + *icv = 0; + *mic = 8; + break; + default: + DEBUG_WARN("un-awared encrypted type %d\n", privacy); + *iv = *icv = *mic = 0; + break; + } + + return privacy; +} + + +unsigned int get_mcast_privacy(struct rtl8192cd_priv *priv, unsigned int *iv, unsigned int *icv, + unsigned int *mic) +{ + unsigned int privacy; + *iv = 0; + *icv = 0; + *mic = 0; + + privacy = get_mcast_encrypt_algthm(priv); + + switch (privacy) + { +#ifdef CONFIG_RTL_WAPI_SUPPORT + case _WAPI_SMS4_: + *iv = WAPI_PN_LEN+2; + *icv = 0; +#if defined(CONFIG_RTL_HW_WAPI_SUPPORT) +#ifdef CONFIG_IEEE80211W + if(!(UseSwCrypto(priv, NULL, TRUE),0)) +#else + if(!(UseSwCrypto(priv, NULL, TRUE))) +#endif + *mic = 0; //HW will take care of the mic + else + *mic = SMS4_MIC_LEN; +#else + *mic = SMS4_MIC_LEN; +#endif + break; +#endif + case _NO_PRIVACY_: + *iv = 0; + *icv = 0; + *mic = 0; + break; + case _WEP_40_PRIVACY_: + case _WEP_104_PRIVACY_: + *iv = 4; + *icv = 4; + *mic = 0; + break; + case _TKIP_PRIVACY_: + *iv = 8; + *icv = 4; + *mic = 0; // mic of TKIP is msdu based + break; + case _CCMP_PRIVACY_: + *iv = 8; + *icv = 0; + *mic = 8; + break; + default: + DEBUG_WARN("un-awared encrypted type %d\n", privacy); + *iv = 0; + *icv = 0; + *mic = 0; + break; + } + + return privacy; +} + +unsigned char * get_da(unsigned char *pframe) +{ + unsigned char *da; + unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); + + switch (to_fr_ds) { + case 0x00: // ToDs=0, FromDs=0 + da = GetAddr1Ptr(pframe); + break; + case 0x01: // ToDs=0, FromDs=1 + da = GetAddr1Ptr(pframe); + break; + case 0x02: // ToDs=1, FromDs=0 + da = GetAddr3Ptr(pframe); + break; + default: // ToDs=1, FromDs=1 + da = GetAddr3Ptr(pframe); + break; + } + + return da; +} + + +unsigned char * get_sa(unsigned char *pframe) +{ + unsigned char *sa; + unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); + + switch (to_fr_ds) { + case 0x00: // ToDs=0, FromDs=0 + sa = GetAddr2Ptr(pframe); + break; + case 0x01: // ToDs=0, FromDs=1 + sa = GetAddr3Ptr(pframe); + break; + case 0x02: // ToDs=1, FromDs=0 + sa = GetAddr2Ptr(pframe); + break; + default: // ToDs=1, FromDs=1 + sa = GetAddr4Ptr(pframe); + break; + } + + return sa; +} + + +__MIPS16 +__IRAM_IN_865X +unsigned char get_hdrlen(struct rtl8192cd_priv *priv, UINT8 *pframe) +{ + if (GetFrameType(pframe) == WIFI_DATA_TYPE) + { +#ifdef CONFIG_RTK_MESH + if ((get_tofr_ds(pframe) == 0x03) && ( (GetFrameSubType(pframe) == WIFI_11S_MESH) || (GetFrameSubType(pframe) == WIFI_11S_MESH_ACTION))) + { + if(GetFrameSubType(pframe) == WIFI_11S_MESH) // DATA frame, qos might be on (TRUE on 8186) + { + return WLAN_HDR_A4_QOS_LEN; + } // WIFI_11S_MESH + else // WIFI_11S_MESH_ACTION frame, although qos flag is on, the qos field(2bytes) is not used for 8186 + { + if(is_mesh_6addr_format_without_qos(pframe)) { + return WLAN_HDR_A6_MESH_DATA_LEN; + } else { + return WLAN_HDR_A4_MESH_DATA_LEN; + } + } + } // end of get_tofr_ds == 0x03 & (MESH DATA or MESH ACTION) + else +#endif // CONFIG_RTK_MESH + if (is_qos_data(pframe)) { + if (get_tofr_ds(pframe) == 0x03) + return WLAN_HDR_A4_QOS_LEN; + else + return WLAN_HDR_A3_QOS_LEN; + } + else { + if (get_tofr_ds(pframe) == 0x03) + return WLAN_HDR_A4_LEN; + else + return WLAN_HDR_A3_LEN; + } + } + else if (GetFrameType(pframe) == WIFI_MGT_TYPE) + return WLAN_HDR_A3_LEN; + else if (GetFrameType(pframe) == WIFI_CTRL_TYPE) + { + if (GetFrameSubType(pframe) == WIFI_PSPOLL) + return 16; + else if (GetFrameSubType(pframe) == WIFI_BLOCKACK_REQ) + return 16; + else if (GetFrameSubType(pframe) == WIFI_BLOCKACK) + return 16; + else + { +#ifdef _DEBUG_RTL8192CD_ + printk("unallowed control pkt type! 0x%04X\n", GetFrameSubType(pframe)); +#endif + return 0; + } + } + else + { +#ifdef _DEBUG_RTL8192CD_ + printk("unallowed pkt type! 0x%04X\n", GetFrameType(pframe)); +#endif + return 0; + } +} + + +unsigned char *get_mgtbuf_from_poll(struct rtl8192cd_priv *priv) +{ + unsigned char *ret; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + ret = get_buf_from_poll(priv, &priv->pshare->wlanbuf_list, (unsigned int *)&priv->pshare->pwlanbuf_poll->count); + + RESTORE_INT(flags); + return ret; +} + + +void release_mgtbuf_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + release_buf_to_poll(priv, pbuf, &priv->pshare->wlanbuf_list, (unsigned int *)&priv->pshare->pwlanbuf_poll->count); + + RESTORE_INT(flags); +} + + +unsigned char *get_wlanhdr_from_poll(struct rtl8192cd_priv *priv) +{ + unsigned char *pbuf; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + pbuf = get_buf_from_poll(priv, &priv->pshare->wlan_hdrlist, (unsigned int *)&priv->pshare->pwlan_hdr_poll->count); +#ifdef TX_EARLY_MODE + pbuf += 8; +#endif + + RESTORE_INT(flags); + return pbuf; +} + + +void release_wlanhdr_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (pbuf == NULL) + { + DEBUG_ERR("Err: Free Null Buf!\n"); + return; + } + + SAVE_INT_AND_CLI(flags); + +#ifdef TX_EARLY_MODE + pbuf -= 8; +#endif + release_buf_to_poll(priv, pbuf, &priv->pshare->wlan_hdrlist, (unsigned int *)&priv->pshare->pwlan_hdr_poll->count); + + RESTORE_INT(flags); +} + + +//__MIPS16 +__IRAM_IN_865X +unsigned char *get_wlanllchdr_from_poll(struct rtl8192cd_priv *priv) +{ + unsigned char *pbuf; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + pbuf = get_buf_from_poll(priv, &priv->pshare->wlanllc_hdrlist, (unsigned int *)&priv->pshare->pwlanllc_hdr_poll->count); +#ifdef TX_EARLY_MODE + pbuf += 8; +#endif + + RESTORE_INT(flags); + return pbuf; +} + + +void release_wlanllchdr_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + +#ifdef TX_EARLY_MODE + pbuf -= 8; +#endif + release_buf_to_poll(priv, pbuf, &priv->pshare->wlanllc_hdrlist, (unsigned int *)&priv->pshare->pwlanllc_hdr_poll->count); + + RESTORE_INT(flags); +} + + +unsigned char *get_icv_from_poll(struct rtl8192cd_priv *priv) +{ + unsigned char *ret; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + ret = get_buf_from_poll(priv, &priv->pshare->wlanicv_list, (unsigned int *)&priv->pshare->pwlanicv_poll->count); + + RESTORE_INT(flags); + return ret; +} + + +void release_icv_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + release_buf_to_poll(priv, pbuf, &priv->pshare->wlanicv_list, (unsigned int *)&priv->pshare->pwlanicv_poll->count); + + RESTORE_INT(flags); +} + + +unsigned char *get_mic_from_poll(struct rtl8192cd_priv *priv) +{ + unsigned char *ret; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + ret = get_buf_from_poll(priv, &priv->pshare->wlanmic_list, (unsigned int *)&priv->pshare->pwlanmic_poll->count); + + RESTORE_INT(flags); + return ret; +} + + +void release_mic_to_poll(struct rtl8192cd_priv *priv, unsigned char *pbuf) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + release_buf_to_poll(priv, pbuf, &priv->pshare->wlanmic_list, (unsigned int *)&priv->pshare->pwlanmic_poll->count); + + RESTORE_INT(flags); +} + + +unsigned short get_pnl(union PN48 *ptsc) +{ + return (((ptsc->_byte_.TSC1) << 8) | (ptsc->_byte_.TSC0)); +} + + +unsigned int get_pnh(union PN48 *ptsc) +{ + return (((ptsc->_byte_.TSC5) << 24) | + ((ptsc->_byte_.TSC4) << 16) | + ((ptsc->_byte_.TSC3) << 8) | + (ptsc->_byte_.TSC2)); +} + + +#ifdef CONFIG_IEEE80211W +int UseSwCrypto(struct rtl8192cd_priv *priv, struct stat_info *pstat, int isMulticast, int isPMF) +#else +int UseSwCrypto(struct rtl8192cd_priv *priv, struct stat_info *pstat, int isMulticast) +#endif +{ +#ifdef CONFIG_IEEE80211W + if (isPMF) + return 1; +#endif + if (SWCRYPTO) + return 1; + else // hw crypto + { +#ifdef CONFIG_RTK_MESH + if( isMeshPoint(pstat) ) + return 0; +// return (pstat->dot11KeyMapping.keyInCam || isMulticast) ? 0 : 1; + +#endif + +#ifdef WDS + if (pstat && (pstat->state & WIFI_WDS) && !(pstat->state & WIFI_ASOC_STATE)) { +#ifndef CONFIG_RTL8186_KB + if (!pstat->dot11KeyMapping.keyInCam) + return 1; + else +#endif + return 0; + } +#endif + + if (priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm +#ifdef CONFIG_RTL_WAPI_SUPPORT + || priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WAPI_SMS4_ +#endif + ) { + if (isMulticast) { // multicast + if (!priv->pmib->dot11GroupKeysTable.keyInCam) + return 1; + else + return 0; + } + else { + if (!pstat->dot11KeyMapping.keyInCam) + return 1; + else // key is in CAM + return 0; + } + } + else { // legacy 802.11 auth (wep40 || wep104) +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) + { + if (GET_ROOT(priv)->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) { + if (isMulticast) + return 1; + else { + if (!pstat->dot11KeyMapping.keyInCam) + return 1; + else // key is in CAM + return 0; + } + } + } +#endif + +#ifdef USE_WEP_DEFAULT_KEY + if (GET_ROOT(priv)->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE) + { + if (pstat && (pstat->state & WIFI_ASOC_STATE)) + return 0; + } + + if (isMulticast && !priv->pmib->dot11GroupKeysTable.keyInCam) + return 1; +#else + if (isMulticast) { + if (!priv->pmib->dot11GroupKeysTable.keyInCam) + return 1; + } + else { + if (!pstat->dot11KeyMapping.keyInCam) + return 1; + } +#endif + return 0; + } + } + } + + +void check_protection_shortslot(struct rtl8192cd_priv *priv) +{ +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL_8881A) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A)) + return; +#endif + if (priv->pmib->dot11ErpInfo.nonErpStaNum == 0 && + priv->pmib->dot11ErpInfo.olbcDetected == 0) + { + if (priv->pmib->dot11ErpInfo.protection) { + priv->pmib->dot11ErpInfo.protection = 0; + //priv->pshare->phw->RTSInitRate_Candidate = 0x8; // 24Mbps + } + } + else + { + if (!priv->pmib->dot11StationConfigEntry.protectionDisabled && + priv->pmib->dot11ErpInfo.protection == 0) { + priv->pmib->dot11ErpInfo.protection = 1; + //priv->pshare->phw->RTSInitRate_Candidate = 0x3; // 11Mbps + } + } + + if (priv->pmib->dot11ErpInfo.nonErpStaNum == 0) + { + if (priv->pmib->dot11ErpInfo.shortSlot == 0) + { + priv->pmib->dot11ErpInfo.shortSlot = 1; +#ifdef MBSSID + if ((IS_ROOT_INTERFACE(priv)) +#ifdef UNIVERSAL_REPEATER + || (IS_VXD_INTERFACE(priv)) +#endif + ) +#endif + set_slot_time(priv, priv->pmib->dot11ErpInfo.shortSlot); + SET_SHORTSLOT_IN_BEACON_CAP; + DEBUG_INFO("set short slot time\n"); + } + } + else + { + if (priv->pmib->dot11ErpInfo.shortSlot) + { + priv->pmib->dot11ErpInfo.shortSlot = 0; +#ifdef MBSSID + if ((IS_ROOT_INTERFACE(priv)) +#ifdef UNIVERSAL_REPEATER + || (IS_VXD_INTERFACE(priv)) +#endif + ) +#endif + set_slot_time(priv, priv->pmib->dot11ErpInfo.shortSlot); + RESET_SHORTSLOT_IN_BEACON_CAP; + DEBUG_INFO("reset short slot time\n"); + } + } +} + + +void check_sta_characteristic(struct rtl8192cd_priv *priv, struct stat_info *pstat, int act) +{ + if (act == INCREASE) { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && !isErpSta(pstat)) { + priv->pmib->dot11ErpInfo.nonErpStaNum++; + check_protection_shortslot(priv); + + if (!pstat->useShortPreamble) + priv->pmib->dot11ErpInfo.longPreambleStaNum++; + } + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && (pstat->ht_cap_len == 0)) + priv->ht_legacy_sta_num++; + } + else { + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && !isErpSta(pstat)) { + priv->pmib->dot11ErpInfo.nonErpStaNum--; + check_protection_shortslot(priv); + + if (!pstat->useShortPreamble && priv->pmib->dot11ErpInfo.longPreambleStaNum > 0) + priv->pmib->dot11ErpInfo.longPreambleStaNum--; + } + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && (pstat->ht_cap_len == 0)) + priv->ht_legacy_sta_num--; + } +} + +int should_forbid_Nmode(struct rtl8192cd_priv *priv) +{ + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11N)) + return 0; + + if (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _NO_PRIVACY_) + return 0; + + if (!(priv->pmib->dot11nConfigEntry.dot11nLgyEncRstrct & BIT(3))) + return 0; + + // if pure TKIP, change N mode to G mode + if (priv->pmib->dot11nConfigEntry.dot11nLgyEncRstrct & BIT(1)) { + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK || + priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm) { + + if ((priv->pmib->dot1180211AuthEntry.dot11WPACipher == 2) && + (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher == 0)) + return 1; + else if ((priv->pmib->dot1180211AuthEntry.dot11WPACipher == 0) && + (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher == 2)) + return 1; + else if ((priv->pmib->dot1180211AuthEntry.dot11WPACipher == 2) && + (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher == 2)) + return 1; + } + } + + // if WEP, forbid N mode + if ((priv->pmib->dot11nConfigEntry.dot11nLgyEncRstrct & BIT(0)) && + ((priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_40_PRIVACY_) || + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == _WEP_104_PRIVACY_))) + return 1; + + return 0; +} + +#ifdef RTK_AC_SUPPORT //for 11ac logo +int is_mixed_mode(struct rtl8192cd_priv *priv) +{ + if((priv->pmib->dot1180211AuthEntry.dot11EnablePSK == 3) + && (priv->pmib->dot1180211AuthEntry.dot11WPACipher & BIT(1)) + && (priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher & BIT(1)) + && (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm == 2)) + { + return 1; + } + else + return 0; +} +#endif + +int should_restrict_Nrate(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + if (OPMODE & WIFI_AP_STATE) + { + if (pstat->is_legacy_encrpt == 1) { + if (priv->pmib->dot11nConfigEntry.dot11nLgyEncRstrct & BIT(1)) { + if (!pstat->is_realtek_sta || (priv->pmib->dot11nConfigEntry.dot11nLgyEncRstrct & BIT(2))) + return 1; + } + } + else if (pstat->is_legacy_encrpt == 2) { + if (priv->pmib->dot11nConfigEntry.dot11nLgyEncRstrct & BIT(0)) { + if (!pstat->is_realtek_sta || (priv->pmib->dot11nConfigEntry.dot11nLgyEncRstrct & BIT(2))) + return 1; + } + } + +#ifdef RTK_AC_SUPPORT //for 11ac logo // Cheat for mixed mode + if(AC_SIGMA_MODE != AC_SIGMA_NONE) { + if(is_mixed_mode(priv)) + return 1; + } +#endif + +#ifdef WDS + else if (pstat->state & WIFI_WDS) { + if ((priv->pmib->dot11WdsInfo.wdsPrivacy == _WEP_40_PRIVACY_) || + (priv->pmib->dot11WdsInfo.wdsPrivacy == _WEP_104_PRIVACY_) || + (priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_)) + return 1; + } +#endif + } +// Client mode IOT issue, Button 2009.07.17 +#ifdef CLIENT_MODE + else if(OPMODE & WIFI_STATION_STATE) + { + + if(!pstat->is_realtek_sta && (pstat->IOTPeer != HT_IOT_PEER_MARVELL) && pstat->is_legacy_encrpt) + + + return 1; + } +#endif + + return 0; +} + + +#ifdef WDS +int getWdsIdxByDev(struct rtl8192cd_priv *priv, struct net_device *dev) +{ + int i; + +#ifdef LAZY_WDS + int max_num; + if (priv->pmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE) + max_num = NUM_WDS; + else + max_num = priv->pmib->dot11WdsInfo.wdsNum; + + for (i=0; ipmib->dot11WdsInfo.wdsNum; i++) { +#endif + + if (dev == priv->wds_dev[i]) + return i; + } + return -1; +} + + +struct net_device *getWdsDevByAddr(struct rtl8192cd_priv *priv, unsigned char *addr) +{ + int i; + +#ifdef LAZY_WDS + int max_num; + if (priv->pmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE) + max_num = NUM_WDS; + else + max_num = priv->pmib->dot11WdsInfo.wdsNum; + + for (i=0; ipmib->dot11WdsInfo.wdsNum; i++) { +#endif + if (!memcmp(priv->pmib->dot11WdsInfo.entry[i].macAddr, addr, 6)) + return priv->wds_dev[i]; + } + return NULL; +} +#endif // WDS + + +void validate_oper_rate(struct rtl8192cd_priv *priv) +{ + unsigned int supportedRates; + unsigned int basicRates; + + if (OPMODE & WIFI_AP_STATE) + { + supportedRates = priv->pmib->dot11StationConfigEntry.dot11SupportedRates; + basicRates = priv->pmib->dot11StationConfigEntry.dot11BasicRates; + +#ifndef CONFIG_RTL8186_KB + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11B) { + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) { + // if use B only, mask G high rate + supportedRates &= 0xf; + basicRates &= 0xf; + } + } + else { + // if use A or G mode, mask B low rate + supportedRates &= 0xff0; + basicRates &= 0xff0; + } + + if (supportedRates == 0) { + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G | WIRELESS_11A)) + supportedRates = 0xff0; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11B) + supportedRates |= 0xf; + + PRINT_INFO("invalid supproted rate, use default value [%x]!\n", supportedRates); + } + + if (basicRates == 0) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + //basicRates = 0x1f0; + //11a basic rate is 6/12/24M + basicRates = 0x150; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11B) + basicRates = 0xf; + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11B)) + basicRates = 0x1f0; + } + + PRINT_INFO("invalid basic rate, use default value [%x]!\n", basicRates); + } + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11B) { + if ((basicRates & 0xf) == 0) // if no CCK rates. jimmylin 2004/12/02 + basicRates |= 0xf; + if ((supportedRates & 0xf) == 0) // if no CCK rates. jimmylin 2004/12/02 + supportedRates |= 0xf; + } + if ((supportedRates & 0xff0) == 0) { // no ERP rate existed + supportedRates |= 0xff0; + + PRINT_INFO("invalid supported rate for 11G, use default value [%x]!\n", + supportedRates); + } + } +#endif // !CONFIG_RTL8186_KB + + priv->supported_rates = supportedRates; + priv->basic_rates = basicRates; + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + if (priv->pmib->dot11nConfigEntry.dot11nSupportedMCS == 0) + priv->pmib->dot11nConfigEntry.dot11nSupportedMCS = 0xffff; + } + } +#ifdef CLIENT_MODE + else + { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11B | WIRELESS_11G)) + priv->dual_band = 1; + else + priv->dual_band = 0; + } + else + priv->dual_band = 0; + + if (priv->dual_band) { + // for 2.4G band + supportedRates = priv->pmib->dot11StationConfigEntry.dot11SupportedRates; + basicRates = priv->pmib->dot11StationConfigEntry.dot11BasicRates; + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11B) { + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) { + supportedRates &= 0xf; + basicRates &= 0xf; + } + if ((supportedRates & 0xf) == 0) + supportedRates |= 0xf; + if ((basicRates & 0xf) == 0) + basicRates |= 0xf; + } + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11B)) { + supportedRates &= 0xff0; + basicRates &= 0xff0; + } + if ((supportedRates & 0xff0) == 0) + supportedRates |= 0xff0; + if ((basicRates & 0xff0) == 0) + basicRates |= 0x1f0; + } + + priv->supported_rates = supportedRates; + priv->basic_rates = basicRates; + + // for 5G band + supportedRates = priv->pmib->dot11StationConfigEntry.dot11SupportedRates; + basicRates = priv->pmib->dot11StationConfigEntry.dot11BasicRates; + + supportedRates &= 0xff0; + basicRates &= 0xff0; + if (supportedRates == 0) + supportedRates |= 0xff0; + if (basicRates == 0) + basicRates |= 0x1f0; + + priv->supported_rates_alt = supportedRates; + priv->basic_rates_alt = basicRates; + } + else { + supportedRates = priv->pmib->dot11StationConfigEntry.dot11SupportedRates; + basicRates = priv->pmib->dot11StationConfigEntry.dot11BasicRates; + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11B) { + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11G)) { + supportedRates &= 0xf; + basicRates &= 0xf; + } + if ((supportedRates & 0xf) == 0) + supportedRates |= 0xf; + if ((basicRates & 0xf) == 0) + basicRates |= 0xf; + } + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11G | WIRELESS_11A)) { + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11B)) { + supportedRates &= 0xff0; + basicRates &= 0xff0; + } + if ((supportedRates & 0xff0) == 0) + supportedRates |= 0xff0; + if ((basicRates & 0xff0) == 0) + basicRates |= 0x1f0; + } + + priv->supported_rates = supportedRates; + priv->basic_rates = basicRates; + } + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + if (priv->pmib->dot11nConfigEntry.dot11nSupportedMCS == 0) + priv->pmib->dot11nConfigEntry.dot11nSupportedMCS = 0xffff; + } + } +#endif +#if defined(RTK_AC_SUPPORT) + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) { + + if (IS_TEST_CHIP(priv)) { + if(get_rf_mimo_mode(priv) == MIMO_1T1R) { + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap &= 0x0ff; + priv->pmib->dot11acConfigEntry.dot11SupportedVHT = 0xfffc; + } else { + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap &= 0x3fcff; + priv->pmib->dot11acConfigEntry.dot11SupportedVHT = 0xfff0; + } + } else { + if(get_rf_mimo_mode(priv) == MIMO_1T1R) { + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap &= 0x3ff; + priv->pmib->dot11acConfigEntry.dot11SupportedVHT |= 0xfffc; + + if(!priv->pmib->dot11acConfigEntry.dot11VHT_TxMap) + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap = 0x3ff; + if(priv->pmib->dot11acConfigEntry.dot11SupportedVHT == 0xffff) + priv->pmib->dot11acConfigEntry.dot11SupportedVHT = 0xfffe; + } else if (get_rf_mimo_mode(priv) == MIMO_2T2R) { //eric_8814 + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap &= 0xfffff; + priv->pmib->dot11acConfigEntry.dot11SupportedVHT |= 0xfff0; + + if(!priv->pmib->dot11acConfigEntry.dot11VHT_TxMap) + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap = 0xfffff; + if(priv->pmib->dot11acConfigEntry.dot11SupportedVHT == 0xffff) + priv->pmib->dot11acConfigEntry.dot11SupportedVHT = 0xfffa; + } else if ((get_rf_mimo_mode(priv) == MIMO_3T3R) ||(get_rf_mimo_mode(priv) == MIMO_4T4R)) { //eric_8814 + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap &= 0x3fffffff; + priv->pmib->dot11acConfigEntry.dot11SupportedVHT |= 0xffc0; + + if(!priv->pmib->dot11acConfigEntry.dot11VHT_TxMap) + priv->pmib->dot11acConfigEntry.dot11VHT_TxMap = 0x3fffffff; + if(priv->pmib->dot11acConfigEntry.dot11SupportedVHT == 0xffff) + priv->pmib->dot11acConfigEntry.dot11SupportedVHT = 0xffda; + } + } + } + +#endif +} + + +void get_oper_rate(struct rtl8192cd_priv *priv) +{ + unsigned int supportedRates=0; + unsigned int basicRates=0; + unsigned char val; + int i, idx=0; + + memset(AP_BSSRATE, 0, sizeof(AP_BSSRATE)); + AP_BSSRATE_LEN = 0; + + if (OPMODE & WIFI_AP_STATE) { + supportedRates = priv->supported_rates; + basicRates = priv->basic_rates; + } +#ifdef CLIENT_MODE + else { + if (priv->dual_band && (priv->pshare->curr_band == BAND_5G)) { + supportedRates = priv->supported_rates_alt; + basicRates = priv->basic_rates_alt; + } + else { + supportedRates = priv->supported_rates; + basicRates = priv->basic_rates; + } + } +#endif + + for (i=0; dot11_rate_table[i]; i++) { + int bit_mask = 1 << i; + if (supportedRates & bit_mask) { + val = dot11_rate_table[i]; + +#ifdef SUPPORT_SNMP_MIB + SNMP_MIB_ASSIGN(dot11SupportedDataRatesSet[i], ((unsigned int)val)); + SNMP_MIB_ASSIGN(dot11OperationalRateSet[i], ((unsigned char)val)); +#endif + + if (basicRates & bit_mask) + val |= 0x80; + + AP_BSSRATE[idx] = val; + AP_BSSRATE_LEN++; + idx++; + } + } + +#ifdef SUPPORT_SNMP_MIB + SNMP_MIB_ASSIGN(dot11SupportedDataRatesNum, ((unsigned char)AP_BSSRATE_LEN)); +#endif + +} + + +// bssrate_ie: _SUPPORTEDRATES_IE_ get supported rate set +// bssrate_ie: _EXT_SUPPORTEDRATES_IE_ get extended supported rate set +int get_bssrate_set(struct rtl8192cd_priv *priv, int bssrate_ie, unsigned char **pbssrate, int *bssrate_len) +{ + int i; + +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) +#else + if ((priv->pshare->curr_band == BAND_5G)||(priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80)) //AC2G_256QAM +#endif + { + +#ifdef P2P_SUPPORT + if(bssrate_ie == _SUPPORTED_RATES_NO_CCK_ ){ + *pbssrate = &dot11_rate_table[4]; + *bssrate_len = 8; + return TRUE; + } +#endif + + if (bssrate_ie == _SUPPORTEDRATES_IE_ ) + { + for(i=0; i 8) + *bssrate_len = 8; + else + *bssrate_len = AP_BSSRATE_LEN; + return TRUE; + } +#ifdef P2P_SUPPORT + else if( bssrate_ie == _SUPPORTED_RATES_NO_CCK_){ + *pbssrate = &dot11_rate_table[4]; + *bssrate_len = 8; + return TRUE; + } +#endif + else + { + if (AP_BSSRATE_LEN > 8) { + *pbssrate = &AP_BSSRATE[8]; + *bssrate_len = AP_BSSRATE_LEN - 8; + return TRUE; + } + else + return FALSE; + } + } +} + + +struct channel_list{ + unsigned char channel[31]; + unsigned char len; +}; +static struct channel_list reg_channel_2_4g[] = { + /* FCC */ {{1,2,3,4,5,6,7,8,9,10,11},11}, + /* IC */ {{1,2,3,4,5,6,7,8,9,10,11},11}, + /* ETSI */ {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, + /* SPAIN */ {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, + /* FRANCE */ {{10,11,12,13},4}, + /* MKK */ {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}, + /* ISRAEL */ {{3,4,5,6,7,8,9,10,11,12,13},11}, + /* MKK1 */ {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}, + /* MKK2 */ {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}, + /* MKK3 */ {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}, + /* NCC (Taiwan) */ {{1,2,3,4,5,6,7,8,9,10,11},11}, + /* RUSSIAN */ {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, + /* CN */ {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, + /* Global */ {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}, + /* World_wide */ {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, + /* Test */ {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}, + /* 5M10M */ {{},0}, + /* SG */ {{1,2,3,4,5,6,7,8,9,10,11},11}, + /* KR */ {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, +}; + +#ifdef DFS +static struct channel_list reg_channel_5g_full_band[] = { + /* FCC */ {{36,40,44,48,52,56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},20}, + /* IC */ {{36,40,44,48,52,56,60,64,149,153,157,161},12}, + /* ETSI */ {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140},19}, + /* SPAIN */ {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140},19}, + /* FRANCE */ {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140},19}, + /* MKK */ {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140},19}, + /* ISRAEL */ {{36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140},19}, + /* MKK1 */ {{34,38,42,46},4}, + /* MKK2 */ {{36,40,44,48},4}, + /* MKK3 */ {{36,40,44,48,52,56,60,64},8}, + /* NCC (Taiwan) */ {{56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},15}, + /* RUSSIAN */ {{36,40,44,48,52,56,60,64,132,136,140,149,153,157,161,165},16}, + /* CN */ {{36,40,44,48,52,56,60,64,149,153,157,161,165},13}, + /* Global */ {{36,40,44,48,52,56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},20}, + /* World_wide */ {{36,40,44,48,52,56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},20}, + /* Test */ {{36,40,44,48, 52,56,60,64, 100,104,108,112, 116,120,124,128, 132,136,140,144, 149,153,157,161, 165,169,173,177}, 28}, + /* 5M10M */ {{146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170}, 25}, + /* SG */ {{36,40,44,48,149,153,157,161,165},9}, + /* KR */ {{36,40,44,48,52,56,60,64,100,104,108,112,116,136,140,149,153,157,161,165},20}, +}; + +struct channel_list reg_channel_5g_not_dfs_band[] = { + /* FCC */ {{36,40,44,48,149,153,157,161,165},9}, + /* IC */ {{36,40,44,48,149,153,157,161},8}, + /* ETSI */ {{36,40,44,48},4}, + /* SPAIN */ {{36,40,44,48},4}, + /* FRANCE */ {{36,40,44,48},4}, + /* MKK */ {{36,40,44,48},4}, + /* ISRAEL */ {{36,40,44,48},4}, + /* MKK1 */ {{34,38,42,46},4}, + /* MKK2 */ {{36,40,44,48},4}, + /* MKK3 */ {{36,40,44,48},4}, + /* NCC (Taiwan) */ {{56,60,64,149,153,157,161,165},8}, + /* RUSSIAN */ {{36,40,44,48,149,153,157,161,165},9}, + /* CN */ {{36,40,44,48,149,153,157,161,165},9}, + /* Global */ {{36,40,44,48,149,153,157,161,165},9}, + /* World_wide */ {{36,40,44,48,149,153,157,161,165},9}, + /* Test */ {{36,40,44,48, 149,153,157,161, 165,169,173,177}, 12}, + /* 5M10M */ {{146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170}, 25}, + /* SG */ {{36,40,44,48,149,153,157,161,165},9}, + /* KR */ {{36,40,44,48,149,153,157,161,165},9}, +}; +#else + +// Exclude DFS channels +static struct channel_list reg_channel_5g_full_band[] = { + /* FCC */ {{36,40,44,48,149,153,157,161,165},9}, + /* IC */ {{36,40,44,48,149,153,157,161},8}, + /* ETSI */ {{36,40,44,48},4}, + /* SPAIN */ {{36,40,44,48},4}, + /* FRANCE */ {{36,40,44,48},4}, + /* MKK */ {{36,40,44,48},4}, + /* ISRAEL */ {{36,40,44,48},4}, + /* MKK1 */ {{34,38,42,46},4}, + /* MKK2 */ {{36,40,44,48},4}, + /* MKK3 */ {{36,40,44,48},4}, + /* NCC (Taiwan) */ {{56,60,64,149,153,157,161,165},8}, + /* RUSSIAN */ {{36,40,44,48,149,153,157,161,165},9}, + /* CN */ {{36,40,44,48,149,153,157,161,165},9}, + /* Global */ {{36,40,44,48,149,153,157,161,165},9}, + /* World_wide */ {{36,40,44,48,149,153,157,161,165},9}, + /* Test */ {{36,40,44,48, 52,56,60,64, 100,104,108,112, 116,120,124,128, 132,136,140,144, 149,153,157,161, 165,169,173,177}, 28}, + /* 5M10M */ {{146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170}, 25}, + /* SG */ {{36,40,44,48,149,153,157,161,165},9}, + /* KR */ {{36,40,44,48,149,153,157,161,165},9}, +}; +#endif + + +int is_available_channel(struct rtl8192cd_priv *priv, unsigned char channel) { + + if(priv->pmib->dot11DFSEntry.disable_DFS == 1) { + if((channel >= 52 && channel <= 140)) + return 0; + } + + if((priv->pmib->dot11RFEntry.band5GSelected & PHY_BAND_5G_1) && + (channel >= 36 && channel <= 48)) + return 1; + else if((priv->pmib->dot11RFEntry.band5GSelected & PHY_BAND_5G_2) && + (channel >= 52 && channel <= 64)) + return 1; + else if((priv->pmib->dot11RFEntry.band5GSelected & PHY_BAND_5G_3) && + (channel >= 100 && channel <= 144)) + return 1; + else if((priv->pmib->dot11RFEntry.band5GSelected & PHY_BAND_5G_4) && + (channel >= 149 && channel <= 177)) + return 1; + else if((priv->pmib->dot11RFEntry.band5GSelected & PHY_BAND_5G_4) && + (channel >= 146 && channel <= 177) && + (priv->pmib->dot11nConfigEntry.dot11nUse40M == 4 ||priv->pmib->dot11nConfigEntry.dot11nUse40M == 5)) + return 1; + else + return 0; +} + + +int is_available_NonDFS_channel(struct rtl8192cd_priv *priv, unsigned char channel) +{ + if((priv->pmib->dot11RFEntry.band5GSelected == PHY_BAND_5G_3)) + return 0; + else + return 1; +} + + +#define MAX_NUM_80M_CH 7 +unsigned int CH_80m[MAX_NUM_80M_CH]={36,52,100,116,132,149,165}; + +int is80MChannel(unsigned int chnl_list[], unsigned int chnl_num,unsigned int channel) +{ + int idx; + int chNO; + int baseCH=0; + idx = -1; + + if( (CH_80m[MAX_NUM_80M_CH-1] <= channel) && ((CH_80m[MAX_NUM_80M_CH-1]+8) >= channel)) + baseCH = CH_80m[MAX_NUM_80M_CH-1]; + else + { + for(chNO=0;chNO channel) { + baseCH = CH_80m[chNO]; + break; + } + } + } + + if(baseCH == 0) + _DEBUG_ERR("Channel is out of scope\n"); + + for(idx=0;idx= chnl_num) + return 0; + + if(chnl_list[idx+1] == baseCH + 4 && + chnl_list[idx+2] == baseCH + 8 && + chnl_list[idx+3] == baseCH + 12) + return 1; + else + return 0; +} + + +#define MAX_NUM_40M_CH 14 +unsigned int CH_40m[MAX_NUM_40M_CH]={36,44,52,60,100,108,116,124,132,140,149,157,165,173}; + +int is40MChannel(unsigned int chnl_list[], unsigned int chnl_num,unsigned int channel) +{ + int idx; + int chNO; + int baseCH=0; + idx = -1; + + if( (CH_40m[MAX_NUM_40M_CH-1] <= channel) && ((CH_40m[MAX_NUM_40M_CH-1]+4) >= channel)) + baseCH = CH_40m[MAX_NUM_40M_CH-1]; + else + { + for(chNO=0;chNO channel) { + baseCH = CH_40m[chNO]; + break; + } + } + } + + if(baseCH == 0) + _DEBUG_ERR("Channel is out of scope\n"); + + for(idx=0;idx= chnl_num) + return 0; + + if(chnl_list[idx+1] == baseCH + 4) + return 1; + else + return 0; +} + + +int find80MChannel(unsigned int chnl_list[], unsigned int chnl_num) { + int i,j; + unsigned int random; + unsigned int num; +#ifdef __ECOS + { + unsigned char random_buf[4]; + get_random_bytes(random_buf, 4); + random = random_buf[3]; + } +#else + get_random_bytes(&random, 4); +#endif + num = random % chnl_num; + for(i=num;i=chnl_num) + j=j-chnl_num; + if(is80MChannel(chnl_list,chnl_num,chnl_list[j])) + return chnl_list[j]; + } + return -1; +} + + +int find40MChannel(unsigned int chnl_list[], unsigned int chnl_num) +{ + int i,j; + unsigned int random; + unsigned int num; +#ifdef __ECOS + { + unsigned char random_buf[4]; + get_random_bytes(random_buf, 4); + random = random_buf[3]; + } +#else + get_random_bytes(&random, 4); +#endif + num = random % chnl_num; + + for(i=num;i=chnl_num) + j=j-chnl_num; + if(is40MChannel(chnl_list,chnl_num,chnl_list[j])) + return chnl_list[j]; + } + return -1; +} + + +int get_available_channel(struct rtl8192cd_priv *priv) +{ + int i, reg; + struct channel_list *ch_5g_lst=NULL; + + priv->available_chnl_num = 0; + reg = priv->pmib->dot11StationConfigEntry.dot11RegDomain; + + if ((reg < DOMAIN_FCC) || (reg >= DOMAIN_MAX)) + return FAIL; + + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11B | WIRELESS_11G) || + ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && + !(priv->pmib->dot11BssType.net_work_type & WIRELESS_11A))) { +#if 0 //def AC2G_256QAM + if(is_ac2g(priv)) //if 2.4G + 11ac mode, force available channels = 1, 5, 9, 13 + { + priv->available_chnl[0]=1; + priv->available_chnl[1]=5; + priv->available_chnl[2]=9; + priv->available_chnl[3]=13; + priv->available_chnl_num=4; + } + else +#endif + { + for (i=0; iavailable_chnl[i] = reg_channel_2_4g[reg-1].channel[i]; + priv->available_chnl_num += reg_channel_2_4g[reg-1].len; + } + } + + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { + + ch_5g_lst = reg_channel_5g_full_band; + + for (i=0; iavailable_chnl[priv->available_chnl_num++] = ch_5g_lst[reg-1].channel[i]; + } + + //for (i=0; iavailable_chnl[priv->available_chnl_num+i] = ch_5g_lst[reg-1].channel[i]; + //priv->available_chnl_num += ch_5g_lst[reg-1].len; + +#ifdef DFS + /* remove the blocked channels from available_chnl[32] */ + if (priv->NOP_chnl_num) + for (i=0; iNOP_chnl_num; i++) + RemoveChannel(priv, priv->available_chnl, &priv->available_chnl_num, priv->NOP_chnl[i]); + + priv->Not_DFS_chnl_num = 0; + for (i=0; iNot_DFS_chnl[priv->Not_DFS_chnl_num++] = reg_channel_5g_not_dfs_band[reg-1].channel[i]; + + } + + +#endif + } + +// add by david --------------------------------------------------- + if (priv->pmib->dot11RFEntry.dot11ch_low || priv->pmib->dot11RFEntry.dot11ch_hi) { + unsigned int tmpbuf[100]; + int num=0; + for (i=0; iavailable_chnl_num; i++) { + if ( (priv->pmib->dot11RFEntry.dot11ch_low && + priv->available_chnl[i] < priv->pmib->dot11RFEntry.dot11ch_low) || + (priv->pmib->dot11RFEntry.dot11ch_hi && + priv->available_chnl[i] > priv->pmib->dot11RFEntry.dot11ch_hi)) + continue; + else + tmpbuf[num++] = priv->available_chnl[i]; + } + if (num) { + memcpy(priv->available_chnl, tmpbuf, num*4); + priv->available_chnl_num = num; + } + } +//------------------------------------------------------ 2007-04-14 + + return SUCCESS; +} + + +void cnt_assoc_num(struct rtl8192cd_priv *priv, struct stat_info *pstat, int act, char *func) +{ +#ifdef CONFIG_RTL_92D_SUPPORT + int i; +#endif + +#ifdef INDICATE_LINK_CHANGE + if (!IEEE8021X_FUN && ((_NO_PRIVACY_ == priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) || + (_WEP_40_PRIVACY_ == priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm) || + (_WEP_104_PRIVACY_ == priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm))) { + indicate_sta_link_change(priv, pstat, act, func); + } +#endif + + if (act == INCREASE) { + if (priv->assoc_num <= NUM_STAT) { + priv->assoc_num++; +#ifdef TLN_STATS + if (priv->assoc_num > priv->wifi_stats.max_sta) { + priv->wifi_stats.max_sta = priv->assoc_num; + priv->wifi_stats.max_sta_timestamp = priv->up_time; + } +#endif + priv->pshare->total_assoc_num++; +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + #if defined(CONFIG_PCI_HCI) + RTL8188E_AssignTxReportMacId(priv); + if (priv->pshare->total_assoc_num == 1) + RTL8188E_ResumeTxReport(priv); + #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_tx_report_change(priv); + #endif + } +#endif +#if 0 +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + { + if (priv->assoc_num > 1) + check_DIG_by_rssi(priv, 0); // force DIG temporary off for association after the fist one + } +#endif + if (pstat->ht_cap_len) { + priv->pshare->ht_sta_num++; + if (priv->pshare->iot_mode_enable && (priv->pshare->ht_sta_num == 1) +#ifdef RTL_MANUAL_EDCA + && (priv->pmib->dot11QosEntry.ManualEDCA == 0) +#endif + ) { +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + IotEdcaSwitch(priv, priv->pshare->iot_mode_enable); +#endif +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + IOT_EDCA_switch(priv, priv->pmib->dot11BssType.net_work_type, priv->pshare->iot_mode_enable); +#endif + } + +#ifdef WIFI_11N_2040_COEXIST + if (priv->pmib->dot11nConfigEntry.dot11nCoexist && priv->pshare->is_40m_bw && + (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G))) { + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_40M_INTOLERANT_)) { + if (OPMODE & WIFI_AP_STATE) { +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + unsigned int force_20_stamap; + force_20_stamap = orSTABitMap(&priv->force_20_sta); + setSTABitMap(&priv->force_20_sta, pstat->aid); + // force all STA switch TXBW to 20M + if (0 == force_20_stamap) + update_RAMask_to_FW(priv, 1); +#else + setSTABitMap(&priv->force_20_sta, pstat->aid); +#endif +#if defined(WIFI_11N_2040_COEXIST_EXT) + clearSTABitMap(&priv->pshare->_40m_staMap, pstat->aid); + +#endif + } + } + } +#endif + + check_NAV_prot_len(priv, pstat, 0); + } +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + UpdateHalMSRRPT8812(priv, pstat, INCREASE); + RTL8812_MACID_PAUSE(priv, 0, REMAP_AID(pstat)); + } +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if(pstat->aid <128) + { + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); + GET_HAL_INTERFACE(priv)->SetMACIDSleepHandler(priv, 0, REMAP_AID(pstat)); + pstat->txpause_flag = 0; + pstat->bDrop = 0; + } + } +#endif + +#if defined(CONFIG_WLAN_HAL_8814AE) +#ifdef HW_FILL_MACID + // set Drop = 0; + if (GET_CHIP_VER(priv) == VERSION_8814A) { +// if(pstat->aid <128) +// { +// GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); +// pstat->bDrop = 0; +// } + + //Init fill mac address,Init fill CRC5 + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, REMAP_AID(pstat), TXRPT_VAR_MAC_ADDRESS, &pstat->hwaddr); + GET_HAL_INTERFACE(priv)->SetCRC5ToRPTBufferHandler(priv,CRC5(&pstat->hwaddr,6), REMAP_AID(pstat),1); + } +#endif //#ifdef HW_FILL_MACID +#endif + + + } else { + DEBUG_ERR("Association Number Error (%d)!\n", NUM_STAT); + } + } else { + if (priv->assoc_num > 0) { + priv->assoc_num--; + priv->pshare->total_assoc_num--; +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E) { + #if defined(CONFIG_PCI_HCI) + if (!priv->pshare->total_assoc_num) + RTL8188E_SuspendTxReport(priv); + else + RTL8188E_AssignTxReportMacId(priv); + #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_tx_report_change(priv); + #endif + } +#endif +#if defined(CONFIG_POWER_SAVE) + if (priv->pshare->total_assoc_num == 0 && GET_ROOT(priv)->pmib->dot11OperationEntry.ps_level == 2) + { + rtw_lock_suspend_timeout(priv, 2000); + } +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + if (0 == priv->assoc_num) { + rtw_txservq_flush(priv, &priv->tx_mc_queue); + } +#endif + +#if 0 +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (IS_ROOT_INTERFACE(priv)) +#endif + if (!priv->assoc_num) { +#ifdef INTERFERENCE_CONTROL + if (priv->pshare->rf_ft_var.nbi_filter_enable) + check_NBI_by_rssi(priv, 0xFF); // force NBI on while no station associated +#else + #if defined(CONFIG_PCI_HCI) + check_DIG_by_rssi(priv, 0); // force DIG off while no station associated + #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_check_DIG_by_rssi(priv, 0); + #endif +#endif + } +#endif + if (pstat->ht_cap_len) { + if (--priv->pshare->ht_sta_num < 0) { + printk("ht_sta_num error\n"); // this should not happen + } else { + if (priv->pshare->iot_mode_enable && !priv->pshare->ht_sta_num +#ifdef RTL_MANUAL_EDCA + && (priv->pmib->dot11QosEntry.ManualEDCA == 0) +#endif + ) { +#ifdef USE_OUT_SRC +#ifdef _OUTSRC_COEXIST + if(IS_OUTSRC_CHIP(priv)) +#endif + IotEdcaSwitch(priv, priv->pshare->iot_mode_enable); +#endif + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +#ifdef _OUTSRC_COEXIST + if(!IS_OUTSRC_CHIP(priv)) +#endif + IOT_EDCA_switch(priv, priv->pmib->dot11BssType.net_work_type, priv->pshare->iot_mode_enable); +#endif + } +#ifdef WIFI_11N_2040_COEXIST + if (priv->pmib->dot11nConfigEntry.dot11nCoexist && priv->pshare->is_40m_bw && + (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N|WIRELESS_11G))) { + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_40M_INTOLERANT_)) { + if (OPMODE & WIFI_AP_STATE) { + clearSTABitMap(&priv->force_20_sta, pstat->aid); +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 0); +#endif + SetTxPowerLevel(priv); + } + } + } +#endif + + check_NAV_prot_len(priv, pstat, 1); + } + } +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + UpdateHalMSRRPT8812(priv, pstat, DECREASE); + } +#endif +#if defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8192EE) + if ((GET_CHIP_VER(priv) == VERSION_8881A) || (GET_CHIP_VER(priv) == VERSION_8192E)) { + if(pstat->aid <127) + { + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, DECREASE); + pstat->bDrop = 1; + } + } +#endif +#if defined(CONFIG_WLAN_HAL_8814AE) +#ifdef HW_FILL_MACID + if (GET_CHIP_VER(priv) == VERSION_8814A) { + // if(pstat->aid <127) + // { + // GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, DECREASE); + // pstat->bDrop = 1; + // } + // Set hwaddr zero + u1Byte hwaddr = {0x00,0x00,0x00,0x00,0x00,0x00}; + GET_HAL_INTERFACE(priv)->SetTxRPTHandler(priv, REMAP_AID(pstat), TXRPT_VAR_MAC_ADDRESS, &hwaddr); + GET_HAL_INTERFACE(priv)->SetCRC5ToRPTBufferHandler(priv,CRC5(&hwaddr,6), REMAP_AID(pstat),0); + } +#endif //#ifdef HW_FILL_MACID +#endif + + } else { + DEBUG_ERR("Association Number Error (0)!\n"); + } + } + +#ifdef CONFIG_RTL_92D_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8192D){ + for (i=NUM_STAT-1; i>=0 ; i--){ + if (priv->pshare->aidarray[i]!=NULL){ + if (priv->pshare->aidarray[i]->used) + break; + } + } + priv->pshare->max_fw_macid = priv->pshare->aidarray[i]->station.aid+1; // fw check macid num from 1~32, so we add 1 to index. + if (priv->pshare->max_fw_macid > (NUM_STAT+1)) + priv->pshare->max_fw_macid = (NUM_STAT+1); + } +#endif + + DEBUG_INFO("assoc_num%s(%d) in %s %02X%02X%02X%02X%02X%02X\n", + act?"++":"--", + priv->assoc_num, + func, + pstat->hwaddr[0], + pstat->hwaddr[1], + pstat->hwaddr[2], + pstat->hwaddr[3], + pstat->hwaddr[4], + pstat->hwaddr[5]); +} + +#ifdef INDICATE_LINK_CHANGE +void indicate_sta_link_change(struct rtl8192cd_priv *priv, struct stat_info *pstat, int act, char *func) +{ + DOT11_LINK_CHANGE_IND LinkChange_Ind; + + if ((INCREASE == act) && !pstat->link_up) { + pstat->link_up = 1; + // do something about STA addition + } else if ((DECREASE == act) && pstat->link_up) { + pstat->link_up = 0; + // do something about STA removal + } else { + return; + } + + memcpy(LinkChange_Ind.MACAddr, pstat->hwaddr, MACADDRLEN); + LinkChange_Ind.EventId = DOT11_EVENT_LINK_CHANGE_IND; + LinkChange_Ind.IsMoreEvent = 0; + LinkChange_Ind.LinkStatus = pstat->link_up; + DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&LinkChange_Ind, + sizeof(DOT11_LINK_CHANGE_IND)); + + DEBUG_INFO("%s%s in %s %02X%02X%02X%02X%02X%02X\n", + __func__, + act ? "++" : "--", + func, + pstat->hwaddr[0], pstat->hwaddr[1], pstat->hwaddr[2], + pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); +} +#endif // INDICATE_LINK_CHANGE + + +/* + * Use this function to get the number of associated station, no matter + * it is expired or not. And don't count WDS peers in. + */ +int get_assoc_sta_num(struct rtl8192cd_priv *priv, int mode) +{ + struct list_head *phead, *plist; + struct stat_info *pstat; + int sta_num; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + sta_num = 0; + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + +#ifdef CONFIG_RTK_MESH + if(mode == 1) { + if(isPossibleNeighbor(pstat)) + continue; + } +#endif + + if ((pstat->state & WIFI_ASOC_STATE) +#ifdef NOT_RTK_BSP + && pstat->expire_to +#endif + ) + { + sta_num++; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + return sta_num; +} + + +void event_indicate(struct rtl8192cd_priv *priv, unsigned char *mac, int event) +{ +#ifdef __KERNEL__ +#ifdef USE_CHAR_DEV + if (priv->pshare->chr_priv && priv->pshare->chr_priv->asoc_fasync) + kill_fasync(&priv->pshare->chr_priv->asoc_fasync, SIGIO, POLL_IN); +#endif +#ifdef USE_PID_NOTIFY + if (priv->pshare->wlanapp_pid > 0) +#ifdef LINUX_2_6_27_ + { + kill_pid(_wlanapp_pid, SIGIO, 1); + } +#else + kill_proc(priv->pshare->wlanapp_pid, SIGIO, 1); +#endif +#endif +#endif + +#ifdef __DRAYTEK_OS__ + if (event == 2) + cb_disassoc_indicate(priv->dev, mac); +#endif + +#ifdef GREEN_HILL + extern void indicate_to_upper(int reason, unsigned char *addr); + if (event > 0) + indicate_to_upper(event, mac); +#endif + +#ifdef __ECOS +#ifdef RTLPKG_DEVS_ETH_RLTK_819X_IWCONTROL + extern cyg_flag_t iw_flag; + cyg_flag_setbits(&iw_flag, 0x1); + +#else +#ifdef RTLPKG_DEVS_ETH_RLTK_819X_WLAN_WPS + extern cyg_flag_t wsc_flag; + cyg_flag_setbits(&wsc_flag, 0x1); +#endif +#endif +#endif +} + +#ifdef WIFI_HAPD +int event_indicate_hapd(struct rtl8192cd_priv *priv, unsigned char *mac, int event, unsigned char *extra) +{ + struct net_device *dev = (struct net_device *)priv->dev; + union iwreq_data wreq; + + if(OPMODE & WIFI_AP_STATE) + { + + printk("event_indicate_hapd +++, event =0x%x\n", event); + + memset(&wreq, 0, sizeof(wreq)); + + if(event == HAPD_EXIRED) + { + memcpy(wreq.addr.sa_data, mac, 6); + wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL); + return 0; + } + else if(event == HAPD_REGISTERED) + { + memcpy(wreq.addr.sa_data, mac, 6); + wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL); + return 0; + } + else if(event == HAPD_MIC_FAILURE) + { + char buf[6]; + memcpy(buf, mac, 6); + wreq.data.flags = event; + wreq.data.length = 6; + wireless_send_event(dev, IWEVCUSTOM, &wreq, buf); + return 0; + } + else if(event == HAPD_WPS_PROBEREQ) + { + wreq.data.flags = event; + wreq.data.length = sizeof(struct _DOT11_PROBE_REQUEST_IND); + wireless_send_event(dev, IWEVGENIE, &wreq, extra); //IW_CUSTOM_MAX is 256, can NOT afford _DOT11_PROBE_REQUEST_IND + return 0; + } + else{ + //Not used yet + wreq.data.flags = event; + wireless_send_event(dev, IWEVCUSTOM, &wreq, extra); + return 0; + } + } + + return -1; +} +#endif + +#ifdef WIFI_WPAS +int event_indicate_wpas(struct rtl8192cd_priv *priv, unsigned char *mac, int event, unsigned char *extra) +{ + struct net_device *dev = (struct net_device *)priv->dev; + union iwreq_data wreq; + + if(OPMODE & WIFI_STATION_STATE) + { + printk("event_indicate_wpas +++ event = 0x%x\n", event); + + memset(&wreq, 0, sizeof(wreq)); + + if(event == WPAS_EXIRED) + { + memcpy(wreq.addr.sa_data, mac, 6); + wireless_send_event(dev, IWEVEXPIRED, &wreq, NULL); + return 0; + } + else if(event == WPAS_REGISTERED) + { + memcpy(wreq.addr.sa_data, mac, 6); + wireless_send_event(dev, SIOCGIWAP, &wreq, NULL); + return 0; + } + else if(event == WPAS_MIC_FAILURE) + { +#ifdef WIFI_WPAS_CLI + struct iw_michaelmicfailure ev; + memset(&ev, 0, sizeof(ev)); +// if (hdr->addr1[0] & 0x01) +// ev.flags |= IW_MICFAILURE_GROUP; +// else +// ev.flags |= IW_MICFAILURE_PAIRWISE; + ev.src_addr.sa_family = ARPHRD_ETHER; + memcpy(ev.src_addr.sa_data, mac, ETH_ALEN); + wreq.data.length = sizeof(ev); + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wreq, (char *)&ev); +#else + char buf[6]; + memcpy(buf, mac, 6); + wreq.data.flags = event; + wreq.data.length = 6; + wireless_send_event(dev, IWEVCUSTOM, &wreq, buf); + return 0; +#endif + } + else if(event == WPAS_ASSOC_INFO) + { + wreq.data.flags = event; + wreq.data.length = sizeof(struct _WPAS_ASSOCIATION_INFO); + wireless_send_event(dev, IWEVCUSTOM, &wreq, extra); //IW_CUSTOM_MAX is 256, can NOT afford _DOT11_PROBE_REQUEST_IND + return 0; + } + else if(event == WPAS_SCAN_DONE) + { + wireless_send_event(dev, SIOCGIWSCAN, &wreq, NULL); + return 0; + } +#ifdef WIFI_WPAS_CLI + else if (event == WPAS_DISCON) + { + wreq.ap_addr.sa_family = ARPHRD_ETHER; + memset(wreq.ap_addr.sa_data, 0, ETH_ALEN); + wireless_send_event(dev, SIOCGIWAP, &wreq, NULL); + return 0; + } +#endif + else + { + //Not used yet + wreq.data.flags = event; + wireless_send_event(dev, IWEVCUSTOM, &wreq, extra); + return 0; + } + } + + return -1; +} +#endif + + +#ifdef CONFIG_RTL_WAPI_SUPPORT +void wapi_event_indicate(struct rtl8192cd_priv *priv) +{ + #ifdef LINUX_2_6_27_ + struct pid *pid; + #endif + + if (priv->pshare->wlanwapi_pid > 0) + { +#ifdef LINUX_2_6_27_ + kill_pid(_wlanwapi_pid, SIGIO, 1); +#else + kill_proc(priv->pshare->wlanwapi_pid, SIGIO, 1); +#endif + } +} +#endif + +#ifdef USE_WEP_DEFAULT_KEY +void init_DefaultKey_Enc(struct rtl8192cd_priv *priv, unsigned char *key, int algorithm) +{ + unsigned char defaultmac[4][6]; + int i; + + memset(defaultmac, 0, sizeof(defaultmac)); + for(i=0; i<4; i++) + defaultmac[i][5] = i; + + for(i=0; i<4; i++) + { + CamDeleteOneEntry(priv, defaultmac[i], i, 1); + if (key == NULL) + CamAddOneEntry(priv, defaultmac[i], i, + (priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm)<<2, + 1, priv->pmib->dot11DefaultKeysTable.keytype[i].skey); + else + CamAddOneEntry(priv, defaultmac[i], i, + algorithm<<2, + 1, key); + } + priv->pshare->CamEntryOccupied += 4; +} +#endif + + +#ifdef UNIVERSAL_REPEATER +// +// Disable AP function in virtual interface +// +void disable_vxd_ap(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if ((priv==NULL) || !(priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE)) + return; + + if (!(priv->drv_state & DRV_STATE_VXD_AP_STARTED)) + return; + else + priv->drv_state &= ~DRV_STATE_VXD_AP_STARTED; + + DEBUG_INFO("Disable vxd AP\n"); + + if (IS_DRV_OPEN(priv)) + rtl8192cd_close(priv->dev); + + SAVE_INT_AND_CLI(flags); + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->DisableVXDAPHandler(priv); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL +#if defined(CONFIG_PCI_HCI) || (defined(CONFIG_USB_HCI) && defined(CONFIG_SUPPORT_USB_INT) && defined(CONFIG_INTERRUPT_BASED_TXBCN)) +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + priv->pshare->InterruptMask &= ~(HIMR_88E_BcnInt | HIMR_88E_TBDOK | HIMR_88E_TBDER); + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask); + } else +#endif + { + RTL_W32(HIMR, RTL_R32(HIMR) & ~(HIMR_BCNDOK0)); + } +#endif + + //RTL_W16(ATIMWND, 2); + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_NOLINK & NETYPE_Mask) << NETYPE_SHIFT)); + } + + RESTORE_INT(flags); +} + + +// +// Enable AP function in virtual interface +// +void enable_vxd_ap(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if ((priv==NULL) || !(priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) || + !(priv->drv_state & DRV_STATE_VXD_INIT)) + return; + + if (priv->drv_state & DRV_STATE_VXD_AP_STARTED) + return; + else + priv->drv_state |= DRV_STATE_VXD_AP_STARTED; + + DEBUG_INFO("Enable vxd AP\n"); + + priv->pmib->dot11RFEntry.dot11channel = GET_ROOT(priv)->pmib->dot11Bss.channel; + //priv->pmib->dot11BssType.net_work_type = GET_ROOT_PRIV(priv)->oper_band; + priv->pmib->dot11BssType.net_work_type = GET_ROOT(priv)->pmib->dot11BssType.net_work_type & + GET_ROOT(priv)->pmib->dot11Bss.network; + + if (!IS_DRV_OPEN(priv)) + rtl8192cd_open(priv->dev); + else { + //priv->oper_band = priv->pmib->dot11BssType.net_work_type; + validate_oper_rate(priv); + get_oper_rate(priv); + } + + memcpy(priv->pmib->dot11StationConfigEntry.dot11Bssid, GET_ROOT(priv)->pmib->dot11OperationEntry.hwaddr, MACADDRLEN); + memcpy(GET_MY_HWADDR, priv->pmib->dot11StationConfigEntry.dot11Bssid, MACADDRLEN); + memcpy(priv->pmib->dot11Bss.bssid, priv->pmib->dot11StationConfigEntry.dot11Bssid, MACADDRLEN); + + SAVE_INT_AND_CLI(flags); + priv->ht_cap_len = 0; + init_beacon(priv); + +#if defined(CONFIG_PCI_HCI) || (defined(CONFIG_USB_HCI) && defined(CONFIG_SUPPORT_USB_INT) && defined(CONFIG_INTERRUPT_BASED_TXBCN)) +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + priv->pshare->InterruptMask |= HIMR_88E_BcnInt | HIMR_88E_TBDOK | HIMR_88E_TBDER; + RTL_W32(REG_88E_HIMR, priv->pshare->InterruptMask); + } else +#endif + { + RTL_W32(HIMR, RTL_R32(HIMR) | HIMR_BCNDOK0); + } +#endif + + //RTL_W16(ATIMWND, 0x0030); + RTL_W32(CR, (RTL_R32(CR) & ~(NETYPE_Mask << NETYPE_SHIFT)) | ((NETYPE_AP & NETYPE_Mask) << NETYPE_SHIFT)); +#ifdef CONFIG_RTL_92C_SUPPORT + if (!IS_TEST_CHIP(priv)) +#endif + { + RTL_W8(0x422, RTL_R8(0x422) | BIT(6)); + RTL_W8(BCN_CTRL, 0); + RTL_W8(0x553, 1); + RTL_W8(BCN_CTRL, DIS_TSF_UPDATE_N| EN_BCN_FUNCTION | DIS_SUB_STATE_N | EN_TXBCN_RPT); + } + + RESTORE_INT(flags); +} +#endif // UNIVERSAL_REPEATER + + +#ifdef GBWC +void rtl8192cd_GBWC_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + struct sk_buff *pskb; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (priv->pmib->gbwcEntry.GBWCMode == GBWC_MODE_DISABLE) + return; + + priv->GBWC_consuming_Q = 1; + + // clear bandwidth control counter + priv->GBWC_tx_count = 0; + priv->GBWC_rx_count = 0; + + // consume Tx queue + while(1) + { + pskb = (struct sk_buff *)deque(priv, &(priv->GBWC_tx_queue.head), &(priv->GBWC_tx_queue.tail), + (unsigned long)(priv->GBWC_tx_queue.pSkb), NUM_TXPKT_QUEUE); + + if (pskb == NULL) + break; + +#ifdef ENABLE_RTL_SKB_STATS + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); +#endif + + if (rtl8192cd_start_xmit_noM2U(pskb, pskb->dev)) + rtl_kfree_skb(priv, pskb, _SKB_TX_); + } + + // consume Rx queue + while(1) + { + pskb = (struct sk_buff *)deque(priv, &(priv->GBWC_rx_queue.head), &(priv->GBWC_rx_queue.tail), + (unsigned long)(priv->GBWC_rx_queue.pSkb), NUM_TXPKT_QUEUE); + + if (pskb == NULL) + break; + + rtl_netif_rx(priv, pskb, (struct stat_info *)*(unsigned int *)&(pskb->cb[4])); + } + + priv->GBWC_consuming_Q = 0; + + mod_timer(&priv->GBWC_timer, jiffies + GBWC_TO); +} +#endif + + +unsigned char fw_was_full(struct rtl8192cd_priv *priv) +{ + struct list_head *phead; + struct list_head *plist; + struct stat_info *pstat; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + unsigned char is_full; + + phead = &priv->asoc_list; + if(list_empty(phead)) + return 0; + + is_full = 0; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + if( pstat->sta_in_firmware != 1) + { + is_full = 1; + goto exit; + } + } + +exit: + SMP_UNLOCK_ASOC_LIST(flags); + return is_full; +} + + +int realloc_RATid(struct rtl8192cd_priv *priv) +{ + struct list_head *phead; + struct list_head *plist; + struct stat_info *pstat =NULL, *pstat_chosen = NULL; + unsigned int max_through_put = 0; + unsigned int have_chosen = 0; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + phead = &priv->asoc_list; + if(list_empty(phead)) + return 0; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + int temp_through_put ; + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if (pstat->sta_in_firmware == 1)// STA has rate adaptive + continue; + + if (pstat->expire_to == 0) // exclude expired STA + continue; + + temp_through_put = pstat->tx_avarage + pstat->rx_avarage; + + if (temp_through_put >= max_through_put){ + pstat_chosen = pstat; + max_through_put = temp_through_put; + have_chosen = 1; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + + if (have_chosen == 0) + return 0; + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat_chosen, 3); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + UpdateHalRAMask8812(priv, pstat_chosen, 3); + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + if(CHIP_VER_92X_SERIES(priv)) + add_update_RATid(priv, pstat_chosen); +#endif + } + + return 1; +} + + +void update_remapAid(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int array_idx; + + if(pstat->sta_in_firmware == 1) + return; /*already exists, just return*/ + + if(priv->pshare->fw_free_space) { + /*find an empty slot*/ + for (array_idx = 0; array_idx < NUM_STAT; array_idx++) { + if (priv->pshare->remapped_aidarray[array_idx] == 0) + break; + } + + if (array_idx == NUM_STAT) { + /*WARNING: THIS SHOULD NOT HAPPEN*/ + printk("add AID fail!!\n"); + BUG(); + return; + } + + + pstat->remapped_aid = array_idx + 1; + priv->pshare->remapped_aidarray[array_idx] = pstat->aid; + pstat->sta_in_firmware = 1; // this value will updated in expire_timer + priv->pshare->fw_free_space --; + } + else { /* free space run out, share the same aid*/ + pstat->remapped_aid = priv->pshare->fw_support_sta_num; + pstat->sta_in_firmware = 0; + } +} + + +void release_remapAid(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int i; + if (pstat->sta_in_firmware == 1) + { + for(i = 0; i < NUM_STAT; i++) { + if(priv->pshare->remapped_aidarray[i] == pstat->aid){ + priv->pshare->remapped_aidarray[i] = 0; + break; + } + } + priv->pshare->fw_free_space ++; + pstat->remapped_aid = 0; + pstat->sta_in_firmware = -1; + DEBUG_INFO("Remove id %d from ratr\n", pstat->aid); + } +} + + +unsigned int is_h2c_buf_occupy(struct rtl8192cd_priv *priv) +{ + unsigned int occupied = 0; + + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (IS_TEST_CHIP(priv) && RTL_R8(0x1c0+priv->pshare->fw_q_fifo_count)) || +#endif + (RTL_R8(0x1cc) & BIT(priv->pshare->fw_q_fifo_count))) + occupied++; + + return occupied; +} + +#if defined(UNIVERSAL_REPEATER) +int under_apmode_repeater(struct rtl8192cd_priv *priv) +{ + int ret = 0; + + if(IS_ROOT_INTERFACE(priv)) + { + if(IS_DRV_OPEN(GET_VXD_PRIV(priv))) + { + if((priv->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) && + (GET_VXD_PRIV(priv)->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE)) + ret = 1; + } + } + else if(IS_VXD_INTERFACE(priv)) + { + if(IS_DRV_OPEN(priv)) + { + if((GET_ROOT(priv)->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) && + (priv->pmib->dot11OperationEntry.opmode & WIFI_STATION_STATE)) + ret = 1; + } + } + + return ret; +} +#endif + +short signin_h2c_cmd(struct rtl8192cd_priv *priv, unsigned int content, unsigned short ext_content) +{ + int c=0; + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) + goto SigninFAIL; +#endif + + /* + * Check if h2c cmd signin buffer is occupied, + * for Power Saving related functions only + */ + //if ((content & 0x7f) < H2C_CMD_RSSI) { + while (is_h2c_buf_occupy(priv)) { + delay_us(10); + if(++c ==30) + { + printk("signin_h2c_cmd() failed! [content = %x , ext_content = %x]\n", content, ext_content); + goto SigninFAIL; + } + } + //} + + /* + * signin reg in order to fit hw requirement + */ + if(content & BIT(7)) + RTL_W16(0x88+(priv->pshare->fw_q_fifo_count*2), ext_content); + + RTL_W32(HMEBOX_0+(priv->pshare->fw_q_fifo_count*4), content); + + //printk("(smcc) sign in h2c %x\n", HMEBOX_0+(priv->pshare->fw_q_fifo_count*4)); + +#if defined(TESTCHIP_SUPPORT) && defined(CONFIG_RTL_92C_SUPPORT) + /* + * set own bit + */ + if(IS_TEST_CHIP(priv)) + RTL_W8(0x1c0+priv->pshare->fw_q_fifo_count, 1); +#endif + + /* + * rollover ring buffer count + */ + if (++priv->pshare->fw_q_fifo_count > 3) + priv->pshare->fw_q_fifo_count = 0; + + return 0; + +SigninFAIL: + return 1; +} + + +void set_ps_cmd(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned int content = 0; + + if(! CHIP_VER_92X_SERIES(priv)) + return; + + SAVE_INT_AND_CLI(flags); + + /* + * set ps state + */ + if (pstat->state & WIFI_SLEEP_STATE) + content |= BIT(24); + + /* + * set macid + */ + content |= REMAP_AID(pstat) << 8; + + /* + * set cmd id + */ + content |= H2C_CMD_PS; + + signin_h2c_cmd(priv, content, 0); + + RESTORE_INT(flags); +} + +#ifdef TX_SHORTCUT +#if defined(CONFIG_PCI_HCI) +__inline__ void clearTxShortCutBufSize(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int i; + for (i=0; iSetShortCutTxBuffSizeHandler(priv, pstat->tx_sc_ent[i].hal_hw_desc, 0); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif // CONFIG_WLAN_HAL + {//not HAL + pstat->tx_sc_ent[i].hwdesc1.Dword7 &= set_desc(~TX_TxBufSizeMask); + } + } +} +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +__inline__ void clearTxShortCutBufSize(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int i, j; + for (i = 0; i < NR_NET80211_UP; ++i) { + for (j = 0; j < TX_SC_ENTRY_NUM; ++j) + pstat->tx_sc_ent[i][j].hwdesc1.Dword7 &= set_desc(~TX_TxBufSizeMask); + } +} +#endif +#endif // TX_SHORTCUT + + +#ifdef CONFIG_PCI_HCI +void add_ps_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + struct stat_info *pstat = NULL; + unsigned int set_timer = 0; + unsigned long flags = 0; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (timer_pending(&priv->add_ps_timer)) + del_timer_sync(&priv->add_ps_timer); + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) + return; +#endif + + if (!list_empty(&priv->addps_list)) { + pstat = list_entry(priv->addps_list.next, struct stat_info, addps_list); + if (!pstat) + return ; + + if (!is_h2c_buf_occupy(priv)) { + set_ps_cmd(priv, pstat); + if (!list_empty(&pstat->addps_list)) { + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + list_del_init(&pstat->addps_list); + RESTORE_INT(flags); + SMP_UNLOCK(flags); + } + + if (!list_empty(&priv->addps_list)) + set_timer++; + } else { + set_timer++; + } + } + + if (set_timer) + mod_timer(&priv->add_ps_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(50)); // 50 ms +} + + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) +void add_update_ps(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif +//#ifdef CONFIG_RTL_8812_SUPPORT + if(! CHIP_VER_92X_SERIES(priv)) + return; +//#endif + if (is_h2c_buf_occupy(priv)) { + if (list_empty(&pstat->addps_list)) { + SAVE_INT_AND_CLI(flags); + list_add_tail(&(pstat->addps_list), &(priv->addps_list)); + RESTORE_INT(flags); + + if (!timer_pending(&priv->add_ps_timer)) + mod_timer(&priv->add_ps_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(50)); // 50 ms + } + } else { + set_ps_cmd(priv, pstat); + } +} +#endif +#endif // CONFIG_PCI_HCI + + +void update_intel_sta_bitmap(struct rtl8192cd_priv *priv, struct stat_info *pstat, int release) +{ + if (pstat->IOTPeer != HT_IOT_PEER_INTEL) + return; + + if (release) { + clearSTABitMap(&priv->pshare->intel_sta_bitmap, pstat->aid); + } else { // join + setSTABitMap(&priv->pshare->intel_sta_bitmap, pstat->aid); + } +} + +#if defined(WIFI_11N_2040_COEXIST_EXT) + +void update_40m_staMap(struct rtl8192cd_priv *priv, struct stat_info *pstat, int release) +{ + if(pstat) { + if(release || (pstat->tx_bw == HT_CHANNEL_WIDTH_20)) + clearSTABitMap(&priv->pshare->_40m_staMap, pstat->aid); + else + setSTABitMap(&priv->pshare->_40m_staMap, pstat->aid); + + } +} + +void checkBandwidth(struct rtl8192cd_priv *priv) +{ + int i; + unsigned int _40m_stamap = orSTABitMap(&priv->pshare->_40m_staMap); + + int FA_counter = priv->pshare->FA_total_cnt; + + if(!priv->pshare->rf_ft_var.bws_enable) + return; + +#ifdef MP_TEST + if ( (OPMODE & WIFI_MP_STATE)|| priv->pshare->rf_ft_var.mp_specific) + return ; +#endif + + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + return ; + +#ifdef WDS + if (priv->pmib->dot11WdsInfo.wdsEnabled) + return; +#endif + + if (!(OPMODE & WIFI_AP_STATE)) + return; + +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) + return; +#endif + + if (timer_pending(&priv->ss_timer) || priv->ss_req_ongoing) + return; + +#if defined(USE_OUT_SRC) + if(IS_OUTSRC_CHIP(priv)) + FA_counter = ODMPTR->FalseAlmCnt.Cnt_all; +#endif + + if ((priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) && (!_40m_stamap) ) { + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_10) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_10; + else if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_5) + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_5; + else + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + } + if( priv->pmib->dot11nConfigEntry.dot11nCoexist + && !orSTABitMap(&priv->pshare->intel_sta_bitmap)) { +#if defined(CONFIG_PCI_HCI) + if((FA_counter> priv->pshare->rf_ft_var.bws_Thd)&&((RTL_R8(0xc50) & 0x7f) >= 0x32)) +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + u1Byte IGI = RTL_R8(0xc50) & 0x7f; + if (((FA_counter> priv->pshare->rf_ft_var.bws_Thd) && (IGI >= 0x32)) || (IGI >= 0x42)) +#endif + { + if(priv->pshare->is_40m_bw != HT_CHANNEL_WIDTH_20) { + priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_20; + priv->ht_cap_len = 0; // reconstruct ie + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + construct_ht_ie(priv, priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + } + } else { + if(priv->pshare->is_40m_bw != priv->pmib->dot11nConfigEntry.dot11nUse40M) { + priv->pshare->is_40m_bw = priv->pmib->dot11nConfigEntry.dot11nUse40M; + priv->ht_cap_len = 0; // reconstruct ie + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + construct_ht_ie(priv, priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + } + } + } + + if( _40m_stamap && (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) && + ((priv->pmib->dot11nConfigEntry.dot11nUse40M != HT_CHANNEL_WIDTH_20))) { + if(priv->pmib->dot11nConfigEntry.dot11nCoexist) { + priv->pshare->is_40m_bw = priv->pmib->dot11nConfigEntry.dot11nUse40M; + priv->ht_cap_len = 0; // reconstruct ie + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + construct_ht_ie(priv, priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + } + priv->pshare->CurrentChannelBW = priv->pmib->dot11nConfigEntry.dot11nUse40M; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + } +} +#endif + + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) +#ifdef CONFIG_PCI_HCI +void add_RATid_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + struct stat_info *pstat = NULL; + unsigned int set_timer = 0; + unsigned long flags = 0; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (timer_pending(&priv->add_RATid_timer)) + del_timer_sync(&priv->add_RATid_timer); + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) + return; +#endif + + if (!list_empty(&priv->addRAtid_list)) { + pstat = list_entry(priv->addRAtid_list.next, struct stat_info, addRAtid_list); + if (!pstat) + return; + + if (!is_h2c_buf_occupy(priv)) { + add_RATid(priv, pstat); + if (!list_empty(&pstat->addRAtid_list)) { + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + list_del_init(&pstat->addRAtid_list); + RESTORE_INT(flags); + SMP_UNLOCK(flags); + } + + if (!list_empty(&priv->addRAtid_list)) + set_timer++; + } else { + set_timer++; + } + } + + if (set_timer) + mod_timer(&priv->add_RATid_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(50)); // 50 ms +} + + +void add_update_RATid(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (is_h2c_buf_occupy(priv)) { + if (list_empty(&pstat->addRAtid_list)) { + SAVE_INT_AND_CLI(flags); + list_add_tail(&(pstat->addRAtid_list), &(priv->addRAtid_list)); + RESTORE_INT(flags); + + if (!timer_pending(&priv->add_RATid_timer)) + mod_timer(&priv->add_RATid_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(50)); // 50 ms + } + } else { + add_RATid(priv, pstat); + } +} +#endif // CONFIG_PCI_HCI +#endif + +#ifdef SDIO_AP_OFFLOAD +void set_ap_ps_mode(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int mode; + + if (strlen(data) == 0) + return; + + mode = _atoi(data, 16); + + if (mode == 0x00) { + ap_offload_activate(priv, OFFLOAD_PROHIBIT_USER); + } else { + ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_USER); + } +} + +void ap_offload_deactivate(struct rtl8192cd_priv *priv, int reason) +{ + _irqL irqL; + + _enter_critical(&priv->pshare->offload_lock, &irqL); + +#ifdef CONFIG_POWER_SAVE + if (!priv->pshare->offload_prohibited) { + if (IS_DRV_OPEN(GET_ROOT(priv))) { + del_timer(&priv->pshare->ps_timer); + priv->pshare->ps_timer_expires = 0; + rtw_lock_suspend(priv); + } + } +#endif + priv->pshare->offload_prohibited |= reason; + + _exit_critical(&priv->pshare->offload_lock, &irqL); + + if (IS_DRV_OPEN(GET_ROOT(priv))) { + if ((RTW_STS_SUSPEND == priv->pshare->pwr_state) +#ifdef CONFIG_POWER_SAVE + || (priv->pshare->offload_function_ctrl > RTW_PM_PREPROCESS) +#endif + ) + ap_offload_exit(GET_ROOT(priv)); + } +} + +void ap_offload_activate(struct rtl8192cd_priv *priv, int reason) +{ + _irqL irqL; + + _enter_critical(&priv->pshare->offload_lock, &irqL); + + priv->pshare->offload_prohibited &= ~reason; + + _exit_critical(&priv->pshare->offload_lock, &irqL); + + if (IS_DRV_OPEN(GET_ROOT(priv))) { +#ifdef CONFIG_POWER_SAVE + rtw_lock_suspend_timeout(priv, 2000); +#else + mod_timer(&priv->pshare->ps_timer, jiffies + POWER_DOWN_T0); +#endif + } +} +#endif // SDIO_AP_OFFLOAD + +void send_h2c_cmd_detect_wps_gpio(struct rtl8192cd_priv *priv, unsigned int gpio_num, unsigned int enable, unsigned int high_active) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned int content = 0; + + SAVE_INT_AND_CLI(flags); + + content = gpio_num << 16; + + /* + * enable firmware to detect wps gpio + */ + if (enable) + content |= BIT(8); + + /* + * rising edge trigger + */ + if (high_active) + content |= BIT(9); + + /* + * set cmd id + */ + content |= H2C_CMD_AP_WPS_CTRL; + + signin_h2c_cmd(priv, content, 0); + printk("signin ap_wps_ctrl h2c: 0x%08X\n", content); + + RESTORE_INT(flags); +} + +#ifdef RTK_QUE +void rtk_queue_init(struct ring_que *que) +{ + memset(que, '\0', sizeof(struct ring_que)); + que->qmax = MAX_PRE_ALLOC_SKB_NUM; +} + +static int rtk_queue_tail(struct rtl8192cd_priv *priv, struct ring_que *que, struct sk_buff *skb) +{ + int next; + unsigned long x; + + SAVE_INT_AND_CLI(x); + SMP_LOCK_SKB(x); + + if (que->head == que->qmax) + next = 0; + else + next = que->head + 1; + + if (que->qlen >= que->qmax || next == que->tail) { + printk("%s: ring-queue full!\n", __FUNCTION__); + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); + return 0; + } + + que->ring[que->head] = skb; + que->head = next; + que->qlen++; + + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); + return 1; +} + + +__IRAM_IN_865X +static struct sk_buff *rtk_dequeue(struct rtl8192cd_priv *priv, struct ring_que *que) +{ + struct sk_buff *skb; + unsigned long x; + + SAVE_INT_AND_CLI(x); + SMP_LOCK_SKB(x); + + if (que->qlen <= 0 || que->tail == que->head) { + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); + return NULL; + } + + skb = que->ring[que->tail]; + + if (que->tail == que->qmax) + que->tail = 0; + else + que->tail++; + + que->qlen--; + + RESTORE_INT(x); + SMP_UNLOCK_SKB(x); + return (struct sk_buff *)skb; +} + + +void free_rtk_queue(struct rtl8192cd_priv *priv, struct ring_que *skb_que) +{ + struct sk_buff *skb; + + while (skb_que->qlen > 0) { + skb = rtk_dequeue(priv, skb_que); + if (skb == NULL) + break; + dev_kfree_skb_any(skb); + } +} +#endif // RTK_QUE + +#ifdef DELAY_REFILL_RX_BUF +#ifdef CONFIG_WLAN_HAL + extern int refill_rx_ring_88XX(struct rtl8192cd_priv * priv, struct sk_buff * skb, unsigned char * data, unsigned int q_num, PHCI_RX_DMA_QUEUE_STRUCT_88XX cur_q); +#endif +extern int refill_rx_ring(struct rtl8192cd_priv *priv, struct sk_buff *skb, unsigned char *data); +#endif + +#ifdef __ECOS +#ifdef DELAY_REFILL_RX_BUF +int __MIPS16 rtk_wifi_delay_refill(struct sk_buff *pskb) +{ + struct rtl8192cd_priv *priv; + struct rtl8192cd_hw *phw; + struct sk_buff *skb=(struct sk_buff *)pskb; + int ret=0; + if(!(pskb && pskb->priv)) + return ret; + + priv=(struct rtl8192cd_priv *)pskb->priv; + phw=GET_HW(priv); + +#ifdef CONFIG_WLAN_HAL + unsigned int q_num; + PHCI_RX_DMA_MANAGER_88XX prx_dma; + PHCI_RX_DMA_QUEUE_STRUCT_88XX cur_q; +#endif // CONFIG_WLAN_HAL + +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if (!(priv->drv_state & DRV_STATE_OPEN)){ + /* return 0 means can't refill (because interface be closed or not opened yet) to rx ring but relesae to skb_poll*/ + ret=0; + }else{ + q_num = 0; + prx_dma = (PHCI_RX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PRxDMA88XX); + cur_q = &(prx_dma->rx_queue[q_num]); + ret = refill_rx_ring_88XX(priv, NULL, NULL, q_num, cur_q); + GET_HAL_INTERFACE(priv)->UpdateRXBDHostIdxHandler(priv, q_num, cur_q->rxbd_ok_cnt); + cur_q->rxbd_ok_cnt = 0; + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + { + if (phw->cur_rx_refill != phw->cur_rx) { + ret=refill_rx_ring(priv, NULL, NULL); + } + } + return ret; +} +#endif +#endif + +#if !(defined(__ECOS) && defined(CONFIG_SDIO_HCI)) +void refill_skb_queue(struct rtl8192cd_priv *priv) +{ + struct sk_buff *skb; +#ifdef DELAY_REFILL_RX_BUF + struct rtl8192cd_hw *phw=GET_HW(priv); + +#ifdef CONFIG_WLAN_HAL + unsigned int q_num; + PHCI_RX_DMA_MANAGER_88XX prx_dma; + PHCI_RX_DMA_QUEUE_STRUCT_88XX cur_q; + + if (IS_HAL_CHIP(priv)) { + q_num = 0; + prx_dma = (PHCI_RX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PRxDMA88XX); + cur_q = &(prx_dma->rx_queue[q_num]); + } +#endif // CONFIG_WLAN_HAL +#endif + +#ifdef NOT_RTK_BSP + while (skb_queue_len(&priv->pshare->skb_queue) < MAX_PRE_ALLOC_SKB_NUM) +#else + while (priv->pshare->skb_queue.qlen < MAX_PRE_ALLOC_SKB_NUM) +#endif + { + + #ifdef CONFIG_RTL8190_PRIV_SKB + skb = dev_alloc_skb_priv(priv, RX_BUF_LEN); + #else + skb = dev_alloc_skb(RX_BUF_LEN); + #endif + + if (skb == NULL) { +// DEBUG_ERR("dev_alloc_skb() failed!\n"); + return; + } +#ifdef DELAY_REFILL_RX_BUF +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if (cur_q->cur_host_idx != ((cur_q->host_idx + cur_q->rxbd_ok_cnt)%cur_q->total_rxbd_num)) { + refill_rx_ring_88XX(priv, skb, NULL, q_num, cur_q); + continue; + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif // CONFIG_WLAN_HAL + {//not HAL + if (phw->cur_rx_refill != phw->cur_rx) { + refill_rx_ring(priv, skb, NULL); + continue; + } + } +#endif + +#ifdef RTK_QUE + rtk_queue_tail(priv, &priv->pshare->skb_queue, skb); +#else +#ifdef __ECOS + skb_queue_tail(&priv->pshare->skb_queue, skb); +#else + __skb_queue_tail(&priv->pshare->skb_queue, skb); +#endif +#endif + } +#ifdef DELAY_REFILL_RX_BUF +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->UpdateRXBDHostIdxHandler(priv, q_num, cur_q->rxbd_ok_cnt); + cur_q->rxbd_ok_cnt = 0; + } +#endif // CONFIG_WLAN_HAL +#endif +} + + +__MIPS16 +__IRAM_IN_865X +struct sk_buff *alloc_skb_from_queue(struct rtl8192cd_priv *priv) +{ + struct sk_buff *skb=NULL; + +#ifdef NOT_RTK_BSP + if (skb_queue_len(&priv->pshare->skb_queue) < 2) +#else + if (priv->pshare->skb_queue.qlen == 0) +#endif + { +// struct sk_buff *skb; +#ifdef CONFIG_RTL8190_PRIV_SKB +#ifdef CONCURRENT_MODE + skb = dev_alloc_skb_priv(priv, RX_BUF_LEN); +#else + skb = dev_alloc_skb_priv(priv, RX_BUF_LEN); +#endif +#else + skb = dev_alloc_skb(RX_BUF_LEN); +#endif + if (skb == NULL) { + DEBUG_ERR("dev_alloc_skb() failed!\n"); + } + + return skb; + } +#ifdef RTK_QUE + skb = rtk_dequeue(priv, &priv->pshare->skb_queue); +#else +#ifdef __ECOS + skb = skb_dequeue(&priv->pshare->skb_queue); +#else + skb = __skb_dequeue(&priv->pshare->skb_queue); +#endif +#endif + if (skb == NULL) { + DEBUG_ERR("skb_dequeue() failed!\n"); + } + + return skb; +} + + +void free_skb_queue(struct rtl8192cd_priv *priv, struct sk_buff_head *skb_que) +{ + struct sk_buff *skb; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + while (skb_que->qlen > 0) { +// 2009.09.08 + SAVE_INT_AND_CLI(flags); + skb = __skb_dequeue(skb_que); + RESTORE_INT(flags); + if (skb == NULL) + break; + dev_kfree_skb_any(skb); + } +} +#endif // !(__ECOS && CONFIG_SDIO_HCI) + +#ifdef FAST_RECOVERY +struct backup_info { + struct aid_obj *sta[NUM_STAT]; + struct Dot11KeyMappingsEntry gkey; +#ifdef WDS + struct wds_info wds; +#endif +}; + +void *backup_sta(struct rtl8192cd_priv *priv) +{ + int i; + struct backup_info *pBackup; + + pBackup = (struct backup_info *)kmalloc((sizeof(struct backup_info)), GFP_ATOMIC); + if (pBackup == NULL) { + printk("%s: kmalloc() failed!\n", __FUNCTION__); + return NULL; + } + memset(pBackup, '\0', sizeof(struct backup_info)); + for (i=0; ipshare->aidarray[i] && priv->pshare->aidarray[i]->used) { +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if (priv != priv->pshare->aidarray[i]->priv) + continue; +#endif + pBackup->sta[i] = (struct aid_obj *)kmalloc((sizeof(struct aid_obj)), GFP_ATOMIC); + if (pBackup->sta[i] == NULL) { + printk("%s: kmalloc(sta) failed!\n", __FUNCTION__); + for (--i; i>=0; --i) { + if (pBackup->sta[i]) { +#ifdef CONFIG_RTL_WAPI_SUPPORT + free_sta_wapiInfo(priv, &pBackup->sta[i]->station); +#endif + kfree(pBackup->sta[i]); + } + } + kfree(pBackup); + return NULL; + } + memcpy(pBackup->sta[i], priv->pshare->aidarray[i], sizeof(struct aid_obj)); +#ifdef CONFIG_RTL_WAPI_SUPPORT + // prevent backup station.wapiInfo from being freed during recovery preiod + priv->pshare->aidarray[i]->station.wapiInfo = NULL; +#endif + } + } + +#ifdef WDS + memcpy(&pBackup->wds, &priv->pmib->dot11WdsInfo, sizeof(struct wds_info)); +#endif + memcpy(&pBackup->gkey, &priv->pmib->dot11GroupKeysTable, sizeof(struct Dot11KeyMappingsEntry)); + + return (void *)pBackup; +} + + +void restore_backup_sta(struct rtl8192cd_priv *priv, void *pInfo) +{ + unsigned int i, offset; + struct stat_info *pstat; + unsigned char key_combo[32]; + struct backup_info *pBackup=(struct backup_info *)pInfo; +#ifdef CONFIG_RTK_MESH + unsigned char is_11s_MP = FALSE; + unsigned long flags; +#endif + int retVal; + + for (i=0; ista[i]) { + +#ifdef CONFIG_RTK_MESH // Restore Establish MP ONLY + if ((1 == GET_MIB(priv)->dot1180211sInfo.mesh_enable) && !isSTA2(pBackup->sta[i]->station)) { + UINT8 State = pBackup->sta[i]->station.mesh_neighbor_TBL.State; + + if ((State == MP_SUPERORDINATE_LINK_UP) || (State == MP_SUBORDINATE_LINK_UP) + || (State == MP_SUPERORDINATE_LINK_DOWN) || (State == MP_SUBORDINATE_LINK_DOWN_E)) + is_11s_MP = TRUE; + else // is MP, but not establish, Give up. + { + kfree(pBackup->sta[i]); + continue; + } + } +#endif + + pstat = alloc_stainfo(priv, pBackup->sta[i]->station.hwaddr, i); + if (!pstat) { + printk("%s: alloc_stainfo() failed!\n", __FUNCTION__); + for (; ista[i]) { +#ifdef CONFIG_RTL_WAPI_SUPPORT + free_sta_wapiInfo(priv, &pBackup->sta[i]->station); +#endif + kfree(pBackup->sta[i]); + } + } + kfree(pBackup); + return; + } + +#ifdef CONFIG_RTL_WAPI_SUPPORT + // free new allocated wapiInfo before restore backup wapiInfo + if (pstat->wapiInfo) free_sta_wapiInfo(priv, pstat); +#endif + offset = (unsigned long)(&((struct stat_info *)0)->aid); + memcpy(((unsigned char *)pstat)+offset, + ((unsigned char *)&pBackup->sta[i]->station)+offset, sizeof(struct stat_info)-offset); + asoc_list_add(priv, pstat); + + if (pstat->sta_in_firmware == 1) { + priv->pshare->remapped_aidarray[pstat->remapped_aid-1] = pstat->aid; + priv->pshare->fw_free_space--; + } + +#ifdef CONFIG_RTK_MESH + if (TRUE == is_11s_MP) { + is_11s_MP = FALSE; + SMP_LOCK_MESH_MP_HDR(flags); + list_add_tail(&pstat->mesh_mp_ptr, &priv->mesh_mp_hdr); + SMP_UNLOCK_MESH_MP_HDR(flags); + mesh_cnt_ASSOC_PeerLink_CAP(priv, pstat, INCREASE); + } +#endif + +#ifdef WDS + if (!(pstat->state & WIFI_WDS)) +#endif + if (pstat->expire_to > 0) + cnt_assoc_num(priv, pstat, INCREASE, (char *)__FUNCTION__); + + if ((pstat->expire_to > 0) +#ifdef WDS + || (pstat->state & WIFI_WDS) +#endif + ) { + check_sta_characteristic(priv, pstat, INCREASE); + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) + construct_ht_ie(priv, priv->pshare->is_40m_bw, priv->pshare->offset_2nd_chan); + +#ifndef USE_WEP_DEFAULT_KEY + set_keymapping_wep(priv, pstat); +#endif + if (!SWCRYPTO && pstat->dot11KeyMapping.keyInCam == TRUE) { +#ifdef CONFIG_RTL_HW_WAPI_SUPPORT + if (pstat->wapiInfo && (pstat->wapiInfo->wapiType != wapiDisable)) { + wapiStaInfo *wapiInfo = pstat->wapiInfo; + + retVal = CamAddOneEntry(priv, + pstat->hwaddr, + wapiInfo->wapiUCastKeyId, /* keyid */ + DOT11_ENC_WAPI<<2, /* type */ + 0, /* use default key */ + wapiInfo->wapiUCastKey[wapiInfo->wapiUCastKeyId].dataKey); + if (retVal) { + priv->pshare->CamEntryOccupied++; + + retVal = CamAddOneEntry(priv, + pstat->hwaddr, + wapiInfo->wapiUCastKeyId, /* keyid */ + DOT11_ENC_WAPI<<2, /* type */ + 1, /* use default key */ + wapiInfo->wapiUCastKey[wapiInfo->wapiUCastKeyId].micKey); + if (retVal) { + //pstat->dot11KeyMapping.keyInCam = TRUE; + priv->pshare->CamEntryOccupied++; + } else { + retVal = CamDeleteOneEntry(priv, pstat->hwaddr, wapiInfo->wapiUCastKeyId, 0); + if (retVal) { + priv->pshare->CamEntryOccupied--; + pstat->dot11KeyMapping.keyInCam = FALSE; + } + } + } else { + pstat->dot11KeyMapping.keyInCam = FALSE; + } + } else +#endif // CONFIG_RTL_HW_WAPI_SUPPORT + if (pstat->dot11KeyMapping.dot11Privacy) { + memcpy(key_combo, + pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKey.skey, + pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen); + memcpy(&key_combo[pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen], + pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKey1.skey, + pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKeyLen); + +#ifdef MULTI_MAC_CLONE + if ((OPMODE & WIFI_STATION_STATE) && priv->pmib->ethBrExtInfo.macclone_enable) + retVal = CamAddOneEntry(priv, pstat->sa_addr, pstat->dot11KeyMapping.keyid, + pstat->dot11KeyMapping.dot11Privacy<<2, 0, key_combo); + else +#endif + retVal = CamAddOneEntry(priv, pstat->hwaddr, pstat->dot11KeyMapping.keyid, + pstat->dot11KeyMapping.dot11Privacy<<2, 0, key_combo); + + if (retVal) + priv->pshare->CamEntryOccupied++; + else + pstat->dot11KeyMapping.keyInCam = FALSE; + } + } + } + // to avoid add RAtid fail +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) { + UpdateHalRAMask8812(priv, pstat, 3); + } else +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } + kfree(pBackup->sta[i]); + + if (priv->pshare->is_40m_bw && (pstat->IOTPeer == HT_IOT_PEER_MARVELL)) + + { + setSTABitMap(&priv->pshare->marvellMapBit, pstat->aid); + +#if defined(CONFIG_RTL_8812_SUPPORT)||defined(CONFIG_WLAN_HAL) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(IS_HAL_CHIP(priv))){ + } + else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + if (priv->pshare->Reg_RRSR_2 == 0 && priv->pshare->Reg_81b == 0){ + priv->pshare->Reg_RRSR_2 = RTL_R8(RRSR+2); + priv->pshare->Reg_81b = RTL_R8(0x81b); + RTL_W8(RRSR+2, priv->pshare->Reg_RRSR_2 | 0x60); + RTL_W8(0x81b, priv->pshare->Reg_81b | 0x0E); + } + } + } + update_intel_sta_bitmap(priv, pstat, 0); +#if defined(WIFI_11N_2040_COEXIST_EXT) + update_40m_staMap(priv, pstat, 0); +#endif + } + } + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + memcpy(&priv->pmib->dot11GroupKeysTable, &pBackup->gkey, sizeof(struct Dot11KeyMappingsEntry)); + if (!SWCRYPTO && priv->pmib->dot11GroupKeysTable.keyInCam) { +#ifdef CONFIG_RTL_HW_WAPI_SUPPORT + if (priv->pmib->wapiInfo.wapiType != wapiDisable) + { + const uint8 CAM_CONST_BCAST[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + retVal = CamAddOneEntry(priv, + CAM_CONST_BCAST, + priv->wapiMCastKeyId<<1, /* keyid */ + DOT11_ENC_WAPI<<2, /* type */ + 0, /* use default key */ + priv->wapiMCastKey[priv->wapiMCastKeyId].dataKey); + if (retVal) { + retVal = CamAddOneEntry(priv, + CAM_CONST_BCAST, + (priv->wapiMCastKeyId<<1)+1, /* keyid */ + DOT11_ENC_WAPI<<2, /* type */ + 1, /* use default key */ + priv->wapiMCastKey[priv->wapiMCastKeyId].micKey); + if (retVal) { + priv->pshare->CamEntryOccupied++; +// priv->pmib->dot11GroupKeysTable.keyInCam = TRUE; + } else { + retVal = CamDeleteOneEntry(priv, CAM_CONST_BCAST, 1, 0); + if (retVal) + priv->pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + } else { + priv->pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + } else +#endif // CONFIG_RTL_HW_WAPI_SUPPORT + { + memcpy(key_combo, + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKey.skey, + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen); + + memcpy(&key_combo[priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen], + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKey1.skey, + priv->pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKeyLen); + + retVal = CamAddOneEntry(priv, (unsigned char *)"\xff\xff\xff\xff\xff\xff", priv->pmib->dot11GroupKeysTable.keyid, + priv->pmib->dot11GroupKeysTable.dot11Privacy<<2, 0, key_combo); + + if (retVal) + priv->pshare->CamEntryOccupied++; + else + priv->pmib->dot11GroupKeysTable.keyInCam = FALSE; + } + } + +#ifdef WDS + memcpy(&priv->pmib->dot11WdsInfo, &pBackup->wds, sizeof(struct wds_info)); +#endif + kfree(pInfo); +} +#endif // FAST_RECOVERY + +#ifdef CONFIG_RTL8190_PRIV_SKB + #if defined(CONFIG_RTL8196B_GW_8M) || defined(CONFIG_RTL8196C_AP_ROOT) || defined(CONFIG_RTL8196C_CLIENT_ONLY) || defined(CONFIG_RTL_8198_AP_ROOT) || defined(__ECOS) +#ifdef __LINUX_2_6__ + #define SKB_BUF_SIZE (MIN_RX_BUF_LEN+sizeof(struct skb_shared_info)+128+128) +#else + #define SKB_BUF_SIZE (MIN_RX_BUF_LEN+sizeof(struct skb_shared_info)+128) +#endif + #else +#ifdef __LINUX_2_6__ + #define SKB_BUF_SIZE (MIN_RX_BUF_LEN+sizeof(struct skb_shared_info)+128+128) +#else + #define SKB_BUF_SIZE (MIN_RX_BUF_LEN+sizeof(struct skb_shared_info)+128) +#endif + #endif + +#define MAGIC_CODE "8190" + +struct priv_skb_buf { + unsigned char magic[4]; + unsigned int buf_pointer; +#ifdef CONCURRENT_MODE + struct rtl8192cd_priv *root_priv; +#endif + struct list_head list; + unsigned char buf[SKB_BUF_SIZE]; +}; + + +#ifdef DUALBAND_ONLY + #define REAL_MAX_SKB (MAX_SKB_NUM/2) +#else + #define REAL_MAX_SKB (MAX_SKB_NUM) +#endif + +#ifdef CONCURRENT_MODE +static struct priv_skb_buf skb_buf[NUM_WLAN_IFACE][REAL_MAX_SKB]; +static struct list_head skbbuf_list[NUM_WLAN_IFACE]; +#ifdef CONFIG_WIRELESS_LAN_MODULE +static int skb_free_num[NUM_WLAN_IFACE] = {REAL_MAX_SKB, REAL_MAX_SKB}; +#else +int skb_free_num[NUM_WLAN_IFACE] = {REAL_MAX_SKB, REAL_MAX_SKB}; +#endif + +#else +static struct priv_skb_buf skb_buf[REAL_MAX_SKB]; +static struct list_head skbbuf_list; +static struct rtl8192cd_priv *root_priv; +#ifdef CONFIG_WIRELESS_LAN_MODULE +static int skb_free_num = REAL_MAX_SKB; +#else +int skb_free_num = REAL_MAX_SKB; +#endif +#endif + + +extern struct sk_buff *dev_alloc_8190_skb(unsigned char *data, int size); + + +void init_priv_skb_buf(struct rtl8192cd_priv *priv) +{ + + panic_printk("\n\n#######################################################\n"); + panic_printk("SKB_BUF_SIZE=%d MAX_SKB_NUM=%d\n",SKB_BUF_SIZE,MAX_SKB_NUM); + panic_printk("#######################################################\n\n"); + + + int i; +#ifdef CONCURRENT_MODE + int idx = priv->pshare->wlandev_idx; + memset(skb_buf[idx], '\0', sizeof(struct priv_skb_buf)*REAL_MAX_SKB); + + INIT_LIST_HEAD(&skbbuf_list[idx]); + + for (i=0; ipshare->wlandev_idx; + data = get_buf_from_poll(priv, &skbbuf_list[i], (unsigned int *)&skb_free_num[i]); + + RESTORE_INT(flags); + return data; +} + +#else + +static __inline__ unsigned char *get_priv_skb_buf(struct rtl8192cd_priv *priv) +{ + unsigned char *ret; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + SAVE_INT_AND_CLI(flags); + + ret = get_buf_from_poll(root_priv, &skbbuf_list, (unsigned int *)&skb_free_num); + + RESTORE_INT(flags); + return ret; +} + +#endif + +#if defined(DUALBAND_ONLY) && defined(CONFIG_RTL8190_PRIV_SKB) +extern u32 if_priv[]; +void merge_pool(struct rtl8192cd_priv *priv) +{ + unsigned char *buf; + unsigned long offset = (unsigned long)(&((struct priv_skb_buf *)0)->buf); + struct priv_skb_buf *priv_buf; + int next_idx; + int idx = priv->pshare->wlandev_idx; + + if (idx == 0) + next_idx = 1; + else + next_idx = 0; + + while (1) { + if (skb_free_num[idx] >= REAL_MAX_SKB*2) + break; + + buf = get_priv_skb_buf((struct rtl8192cd_priv *)if_priv[next_idx]); + if (buf == NULL) + break; + + priv_buf = (struct priv_skb_buf *)(((unsigned long)buf) - offset); + priv_buf->root_priv = priv; + release_buf_to_poll(priv, buf, &skbbuf_list[idx], (unsigned int *)&skb_free_num[idx]); + } +} + +void split_pool(struct rtl8192cd_priv *priv) +{ + unsigned char *buf; + unsigned long offset = (unsigned long)(&((struct priv_skb_buf *)0)->buf); + struct priv_skb_buf *priv_buf; + + int next_idx; + int idx = priv->pshare->wlandev_idx; + + if (idx == 0) + next_idx = 1; + else + next_idx = 0; + + while (1) { + if (skb_free_num[idx] <= REAL_MAX_SKB) + break; + + buf = get_priv_skb_buf(priv); + if (buf == NULL) + break; + + priv_buf = (struct priv_skb_buf *)(((unsigned long)buf) - offset); + priv_buf->root_priv = (struct rtl8192cd_priv *)if_priv[next_idx]; + release_buf_to_poll((struct rtl8192cd_priv *)if_priv[next_idx], + buf, &skbbuf_list[next_idx], (unsigned int *)&skb_free_num[next_idx]); + } +} +#endif + +__IRAM_IN_865X +#ifdef CONCURRENT_MODE +static struct sk_buff *dev_alloc_skb_priv(struct rtl8192cd_priv *priv, unsigned int size) +{ + struct sk_buff *skb; + + unsigned char *data = get_priv_skb_buf(priv); + if (data == NULL) { +// _DEBUG_ERR("wlan: priv skb buffer empty!\n"); + return NULL; + } + + skb = dev_alloc_8190_skb(data, size); + if (skb == NULL) { + free_rtl8190_priv_buf(data); + return NULL; + } + return skb; +} +#else +static struct sk_buff *dev_alloc_skb_priv(struct rtl8192cd_priv *priv, unsigned int size) +{ + struct sk_buff *skb; + + unsigned char *data = get_priv_skb_buf(priv); + if (data == NULL) { +// _DEBUG_ERR("wlan: priv skb buffer empty!\n"); + return NULL; + } + + skb = dev_alloc_8190_skb(data, size); + if (skb == NULL) { + free_rtl8190_priv_buf(data); + return NULL; + } + return skb; +} +#endif + +int is_rtl8190_priv_buf(unsigned char *head) +{ + unsigned long offset = (unsigned long)(&((struct priv_skb_buf *)0)->buf); + struct priv_skb_buf *priv_buf = (struct priv_skb_buf *)(((unsigned long)head) - offset); + + if (!memcmp(priv_buf->magic, MAGIC_CODE, 4) && + (priv_buf->buf_pointer == (unsigned int)priv_buf)) + return 1; + else + return 0; +} + +__IRAM_IN_865X +void free_rtl8190_priv_buf(unsigned char *head) +{ + +#ifdef CONCURRENT_MODE + unsigned long offset = (unsigned long)(&((struct priv_skb_buf *)0)->buf); + struct priv_skb_buf *priv_buf = (struct priv_skb_buf *)(((unsigned long)head) - offset); + struct rtl8192cd_priv *priv = priv_buf->root_priv; + int i = priv->pshare->wlandev_idx; +#ifndef SMP_SYNC + unsigned long x; +#endif +#ifdef DELAY_REFILL_RX_BUF + int ret; +#ifdef SMP_SYNC + unsigned long flags; + int locked, cpuid; +#endif +#ifdef CONFIG_WLAN_HAL + unsigned int q_num; + PHCI_RX_DMA_MANAGER_88XX prx_dma; + PHCI_RX_DMA_QUEUE_STRUCT_88XX cur_q; +#endif // CONFIG_WLAN_HAL +#ifdef SMP_SYNC + locked = 0; + SMP_TRY_LOCK_RECV(flags,locked); +#endif + SAVE_INT_AND_CLI(x); +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + if (!(priv->drv_state & DRV_STATE_OPEN)){ + /* return 0 means can't refill (because interface be closed or not opened yet) to rx ring but relesae to skb_poll*/ + ret=0; + }else{ + q_num = 0; + prx_dma = (PHCI_RX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PRxDMA88XX); + cur_q = &(prx_dma->rx_queue[q_num]); + + ret = refill_rx_ring_88XX(priv, NULL, head, q_num, cur_q); + GET_HAL_INTERFACE(priv)->UpdateRXBDHostIdxHandler(priv, q_num, cur_q->rxbd_ok_cnt); + cur_q->rxbd_ok_cnt = 0; + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + ret = refill_rx_ring(priv, NULL, head); + } + + if (ret) { +#ifdef SMP_SYNC + if(locked) + SMP_UNLOCK_RECV(flags); +#endif + RESTORE_INT(x); + return; + } + else { + release_buf_to_poll(priv, head, &skbbuf_list[i], (unsigned int *)&skb_free_num[i]); + } +#ifdef SMP_SYNC + if(locked) + SMP_UNLOCK_RECV(flags); +#endif + RESTORE_INT(x); +#else // ! DELAY_REFILL_RX_BUF + SAVE_INT_AND_CLI(x); + release_buf_to_poll(priv, head, &skbbuf_list[i], (unsigned int *)&skb_free_num[i]); + RESTORE_INT(x); +#endif + +#else // ! CONCURRENT_MODE + + unsigned long x; + struct rtl8192cd_priv *priv = root_priv; +#if 0 + if (!is_rtl8190_priv_buf(head)) { + printk("wlan: free invalid priv skb buf!\n"); + return; + } +#endif + +#ifdef DELAY_REFILL_RX_BUF +#ifdef CONFIG_WLAN_HAL + unsigned int q_num; + PHCI_RX_DMA_MANAGER_88XX prx_dma; + PHCI_RX_DMA_QUEUE_STRUCT_88XX cur_q; +#endif + int ret; + +#ifdef SMP_SYNC + unsigned long flags; + int locked, cpuid; + cpuid = smp_processor_id(); + locked = 0; + SMP_TRY_LOCK_RECV(flags,locked,cpuid); +#endif + SAVE_INT_AND_CLI(x); +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + // Currently, only one queue for rx... + if (!(priv->drv_state & DRV_STATE_OPEN)){ + /* return 0 means can't refill (because interface be closed or not opened yet) to rx ring but relesae to skb_poll*/ + ret=0; + }else{ + q_num = 0; + prx_dma = (PHCI_RX_DMA_MANAGER_88XX)(_GET_HAL_DATA(priv)->PRxDMA88XX); + cur_q = &(prx_dma->rx_queue[q_num]); + ret = refill_rx_ring_88XX(priv, NULL, head, q_num, cur_q); + GET_HAL_INTERFACE(priv)->UpdateRXBDHostIdxHandler(priv, q_num, cur_q->rxbd_ok_cnt); + cur_q->rxbd_ok_cnt = 0; + } + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + ret = refill_rx_ring(priv, NULL, head); + } + + if (ret) { +#ifdef SMP_SYNC + if(locked) + SMP_UNLOCK_RECV(flags); +#endif + RESTORE_INT(x); + return; + } else { + release_buf_to_poll(root_priv, head, &skbbuf_list, (unsigned int *)&skb_free_num); + } +#ifdef SMP_SYNC + if(locked) + SMP_UNLOCK_RECV(flags); +#endif + RESTORE_INT(x); +#else // ! DELAY_REFILL_RX_BUF + + SAVE_INT_AND_CLI(x); + release_buf_to_poll(root_priv, head, &skbbuf_list, (unsigned int *)&skb_free_num); + RESTORE_INT(x); + +#endif + +#endif +} +#endif //CONFIG_RTL8190_PRIV_SKB + + + +/* +unsigned int set_fw_reg(struct rtl8192cd_priv *priv, unsigned int cmd, unsigned int val, unsigned int with_val) +{ + static unsigned int delay_count; + + delay_count = 10; + + do { + if (!RTL_R32(0x2c0)) + break; + delay_us(5); + delay_count--; + } while (delay_count); + delay_count = 10; + + if (with_val == 1) + RTL_W32(0x2c4, val); + + RTL_W32(0x2c0, cmd); + + do { + if (!RTL_R32(0x2c0)) + break; + delay_us(5); + delay_count--; + } while (delay_count); + + return 0; +} + + +void set_fw_A2_entry(struct rtl8192cd_priv *priv, unsigned int cmd, unsigned char *addr) +{ + unsigned int delay_count = 10; + + do{ + if (!RTL_R32(0x2c0)) + break; + delay_us(5); + delay_count--; + } while (delay_count); + delay_count = 10; + + RTL_W32(0x2c4, addr[3]<<24 | addr[2]<<16 | addr[1]<<8 | addr[0]); + RTL_W32(0x2c8, addr[5]<<8 | addr[4]); + RTL_W32(0x2c0, cmd); + + do{ + if (!RTL_R32(0x2c0)) + break; + delay_us(5); + delay_count--; + } while (delay_count); +} +*/ + +//#if defined(TXREPORT) || defined(SW_ANT_SWITCH) || defined(USE_OUT_SRC) +#if 1 +struct stat_info* findNextSTA(struct rtl8192cd_priv *priv, int *idx) +{ + int i; + for(i= *idx; ipshare->aidarray[i] && priv->pshare->aidarray[i]->used == TRUE) { + *idx = (i+1); + if (priv->pshare->aidarray[i]->station.sta_in_firmware != 1) + continue; + + return &(priv->pshare->aidarray[i]->station); + } + } + return NULL; +} +#endif + +int is_DFS_channel(int channelVal) +{ + if( channelVal >= 52 && channelVal <= 140 ){ + return 1; + }else{ + return 0; + } +} + +int is_passive_channel(struct rtl8192cd_priv *priv , int domain, int chan) +{ + +#ifdef DFS + /*during DFS channel , do passive scan*/ + if( (chan >= 52 && chan <= 140) && !priv->pmib->dot11DFSEntry.disable_DFS){ + return 1; + } +#endif + #if 0/*when the mib "w52_passive_scan" enabled , do passive scan in ch W52(ch 36 40 44 48)*/ + else if(((chan >= 36) && (chan <= 48)) + && priv->pmib->dot11StationConfigEntry.w52_passive_scan ){ + return 1; + } + #endif + #if 0 + else if ((chan >= 12 && chan <= 14) && (domain == DOMAIN_GLOBAL || domain == DOMAIN_WORLD_WIDE)){ + return 1; + } + #endif + return 0; +} + +void init_STA_SWQAggNum(struct rtl8192cd_priv *priv) +{ +#ifdef SW_TX_QUEUE + struct stat_info *sta; + int i, Idx = 0; + while(1) { + sta = findNextSTA(priv, &Idx); + if(sta) { + if(sta->tx_avarage> (1<<16)) { + for(i=BK_QUEUE;iswq.q_aggnum[i] = priv->pshare->rf_ft_var.swq_aggnum>>1; + } + } + } else { + return; + } + } +#endif +} + + + +#if defined(TXREPORT) +void requestTxReport(struct rtl8192cd_priv *priv) +{ + int h2ccmd, counter=20; + struct stat_info *sta; + + if( priv->pshare->sta_query_idx == -1) + return; + + while(is_h2c_buf_occupy(priv)) { + delay_ms(2); + if(--counter==0) + break; + } + if(!counter) + return; + + h2ccmd= AP_REQ_RPT; + + sta = findNextSTA(priv, &priv->pshare->sta_query_idx); + if(sta) + h2ccmd |= (REMAP_AID(sta)<<24); + else { + priv->pshare->sta_query_idx = -1; + return; + } + sta = findNextSTA(priv, &priv->pshare->sta_query_idx); + if(sta) { + h2ccmd |= (REMAP_AID(sta)<<16); + } else { + priv->pshare->sta_query_idx = -1; + } + + signin_h2c_cmd(priv, h2ccmd , 0); + DEBUG_INFO("signin h2c:%x\n", h2ccmd); + +} + +/* +inital tx rate report from fw +--------------------------------------------------------- +0 -> cck 1 12 -> MCS0 44 -> 1NSS-MCS0 +1 -> cck 2 13 -> MCS1 45 -> 1NSS-MCS1 +2 -> cck 5.5 14 -> MCS2 46 -> 1NSS-MCS2 +3 -> cck 11 15 -> MCS3 47 -> 1NSS-MCS3 +------------ 16 -> MCS4 48 -> 1NSS-MCS4 +4 -> ofdm 6 17 -> MCS5 49 -> 1NSS-MCS5 +5 -> ofdm 9 18 -> MCS6 50 -> 1NSS-MCS6 +6 -> ofdm 12 19 -> MCS7 51 -> 1NSS-MCS7 +7 -> ofdm 18 20 -> MCS8 52 -> 1NSS-MCS8 +8 -> ofdm 24 21 -> MCS9 53 -> 1NSS-MCS9 +9 -> ofdm 36 22 -> MCS10 54 -> 2NSS-MCS0 +10 -> ofdm 48 23 -> MCS11 55 -> 2NSS-MCS1 +11 -> ofdm 54 24 -> MCS12 56 -> 2NSS-MCS2 + 25 -> MCS13 57 -> 2NSS-MCS3 + 26 -> MCS14 58 -> 2NSS-MCS4 + 27 -> MCS15 59 -> 2NSS-MCS5 + 60 -> 2NSS-MCS6 + 61 -> 2NSS-MCS7 + 62 -> 2NSS-MCS8 + 63 -> 2NSS-MCS9 +--------------------------------------------------------- +*/ +#ifdef FOR_DISPLAY_RATE +void get_inital_tx_rate2string(unsigned char txrate ){ + static unsigned char rateStr[16]; + if(txrate>=44 && txrate<=53){ + printk("VHT 1SS-MCS%d\n",txrate-44); + } + else if(txrate>=54 && txrate<=63){ + printk("VHT 2SS-MCS%d\n",txrate-54); + } + else if(txrate>=12 && txrate<=27){ + printk("MCS%d\n",txrate-12); + } + else if(txrate>=0 && txrate<=3){ + if(txrate==0) + printk("CCK-1\n"); + else if(txrate==1) + printk("CCK-2\n"); + else if(txrate==2) + printk("CCK-5.5\n"); + else if(txrate==3) + printk("CCK-11\n"); + } + else if(txrate>=4 && txrate<=11){ + if(txrate==4) + printk("OFDM-6\n"); + else if(txrate==5) + printk("OFDM-9\n"); + else if(txrate==6) + printk("OFDM-12\n"); + else if(txrate==7) + printk("OFDM-18\n"); + else if(txrate==8) + printk("OFDM-24\n"); + else if(txrate==9) + printk("OFDM-36\n"); + else if(txrate==10) + printk("OFDM-48\n"); + else if(txrate==11) + printk("OFDM-54\n"); + + } + +} + +//#define FDEBUG(fmt, args...) panic_printk("[%s %d]"fmt,__FUNCTION__,__LINE__,## args) +#endif + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + +void update_RAMask_to_FW(struct rtl8192cd_priv *priv, int forceUpdate) +{ + int idx = 0; + struct stat_info *pstat = NULL; + + if( !IS_HAL_CHIP(priv) && GET_CHIP_VER(priv)!= VERSION_8812E) + return; + + + if (!forceUpdate && !( priv->pshare->is_40m_bw +#ifdef WIFI_11N_2040_COEXIST + && !((((GET_MIB(priv))->dot11OperationEntry.opmode) & WIFI_AP_STATE) + && priv->pmib->dot11nConfigEntry.dot11nCoexist + && (priv->bg_ap_timeout || orForce20_Switch20Map(priv) + )) +#endif + )) + return; + + pstat = findNextSTA(priv, &idx); + + while(pstat) { + if(forceUpdate) { +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + UpdateHalRAMask8812(priv, pstat, 3); + else +#endif + { +#ifdef CONFIG_WLAN_HAL + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); +#endif + } + } else { + if(!pstat->tx_bw_fw && pstat->tx_bw) { +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) + UpdateHalRAMask8812(priv, pstat, 3); + else +#endif + { +#ifdef CONFIG_WLAN_HAL + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); +#endif + } + } + } + pstat = findNextSTA(priv, &idx); + + } + +} + +// TODO: Filen, check 8192E code below +void txrpt_handler_8812(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat) +{ + static unsigned char initial_rate = 0x7f; + static unsigned char legacyRA =0 ; + static unsigned int autoRate1=0; + + /*under auto rate case , pstat->current_tx_rate just for display but it'll be changed, + so, take care! if under fixed rate case don't enter below block*/ + + if(!pstat) + return; + if(pstat->sta_in_firmware == 1) + { + if( should_restrict_Nrate(priv, pstat) && is_fixedMCSTxRate(priv, pstat)){ + legacyRA = 1; + } + + autoRate1= is_auto_rate(priv, pstat); + + if( !(legacyRA || autoRate1) ) + return; + + //FDEBUG("STA[%02x%02x%02x:%02x%02x%02x]auto rate ,txfail=%d , txok=%d , rate=", + // pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5], + // report->txfail, report->txok ); + //get_inital_tx_rate2string(report->initil_tx_rate&0x3f); + + + initial_rate = report->initil_tx_rate ; + if ((initial_rate & 0x7f) == 0x7f) + return; + + if ((initial_rate&0x3f) < 12) { + pstat->current_tx_rate = dot11_rate_table[initial_rate&0x3f]; + + pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; + } else { + if((initial_rate&0x3f) >= 44){ + pstat->current_tx_rate = VHT_RATE_ID+((initial_rate&0x3f) -44); + }else{ + pstat->current_tx_rate = HT_RATE_ID+((initial_rate&0x3f) -12); + } + + if (initial_rate & BIT(7)) + pstat->ht_current_tx_info |= TX_USE_SHORT_GI; + else + pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; + } + + priv->pshare->current_tx_rate = pstat->current_tx_rate; + priv->pshare->ht_current_tx_info = pstat->ht_current_tx_info; + + } +} +#endif +#ifdef CONFIG_WLAN_HAL +void APReqTXRptHandler( + struct rtl8192cd_priv *priv, + pu1Byte pbuf +) +{ + PAPREQTXRPT pparm = (PAPREQTXRPT)pbuf; + struct tx_rpt rpt1; + unsigned char MacID = 0xff; + unsigned char idx = 0; + int j; + { + for (j = 0; j < 2; j++) { + + MacID = pparm->txrpt[j].RPT_MACID; + if (MacID == 0xff) + continue; + + rpt1.macid = MacID; + + if (rpt1.macid) { + rpt1.txok = le16_to_cpu(pparm->txrpt[j].RPT_TXOK); + rpt1.txfail = le16_to_cpu(pparm->txrpt[j].RPT_TXFAIL); + rpt1.initil_tx_rate = pparm->txrpt[j].RPT_InitialRate; + + txrpt_handler(priv, &rpt1); // add inital tx rate handle for 8812E + } + idx += 6; + } + } +} +#endif + +void _txrpt_handler(struct rtl8192cd_priv *priv, struct stat_info *pstat, struct tx_rpt *report) +{ + if ((0 == report->txok) && (0 == report->txfail)) + return; + + priv->net_stats.tx_errors += report->txfail; + pstat->tx_fail += report->txfail; + pstat->tx_pkts += report->txfail; + if (pstat->txrpt_tx_ok_chk_cnt <= 10) + pstat->tx_pkts += report->txok; + + if (pstat->txrpt_tx_bytes_pre == pstat->tx_bytes) { + if (report->txok) { + pstat->txrpt_tx_ok_chk_cnt++; + } + } else { + pstat->txrpt_tx_bytes_pre = pstat->tx_bytes; + pstat->txrpt_tx_ok_chk_cnt = 0; + } + + DEBUG_INFO("debug[%02X%02X%02X%02X%02X%02X]:id=%d,ok=%d,fail=%d\n", + pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5], + report->macid, report->txok, report->txfail); + +#ifdef DETECT_STA_EXISTANCE +#ifdef CONFIG_WLAN_HAL + if(IS_HAL_CHIP(priv)) + { + DetectSTAExistance88XX(priv, report, pstat); + } else if(CONFIG_WLAN_NOT_HAL_EXIST) +#endif + {//not HAL + // Check for STA existance; added by Annie, 2010-08-10.Not support now +#if (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)|| defined(CONFIG_RTL_8812_SUPPORT)) + if (CHIP_VER_92X_SERIES(priv) || (GET_CHIP_VER(priv)== VERSION_8812E)) + DetectSTAExistance(priv, report, pstat); +#endif +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) + RTL8188E_DetectSTAExistance(priv, report, pstat); +#endif + } +#endif // DETECT_STA_EXISTANCE + +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + if( GET_CHIP_VER(priv)== VERSION_8812E || IS_HAL_CHIP(priv)) + txrpt_handler_8812(priv, report, pstat); +#endif +} + +void txrpt_handler(struct rtl8192cd_priv *priv, struct tx_rpt *report) +{ + struct stat_info *pstat; +#ifdef MBSSID + int i; +#endif + pstat = get_macidinfo(priv, report->macid); + if(pstat) { + _txrpt_handler(priv, pstat, report); + return; + } + +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) { + pstat = get_macidinfo(GET_VXD_PRIV(priv), report->macid); + if(pstat) { + _txrpt_handler(GET_VXD_PRIV(priv), pstat, report); + return; + } + } +#endif +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) { + pstat = get_macidinfo(priv->pvap_priv[i], report->macid); + if(pstat) { + _txrpt_handler(priv->pvap_priv[i], pstat, report); + return; + } + } + } + } +#endif +} + +void C2H_isr(struct rtl8192cd_priv *priv) +{ + struct tx_rpt rpt1; + int j, tmp32, idx=0x1a2; +#ifndef SMP_SYNC + unsigned long flags; +#endif + SAVE_INT_AND_CLI(flags); + tmp32 = RTL_R16(0x1a0); + if( (tmp32&0xff)==0xc2 ) { + for(j=0; j<2; j++) { + rpt1.macid= (0x1f) & RTL_R8(idx+4); + if(rpt1.macid) { +#ifdef _BIG_ENDIAN_ + rpt1.txok = le16_to_cpu(RTL_R16(idx+2)); + rpt1.txfail = le16_to_cpu(RTL_R16(idx)); +#else + rpt1.txok = be16_to_cpu(RTL_R16(idx+2)); + rpt1.txfail = be16_to_cpu(RTL_R16(idx)); +#endif + txrpt_handler(priv, &rpt1); + } + idx+=6; + } + } + RTL_W8( 0x1af, 0); + requestTxReport(priv); + RESTORE_INT(flags); +} + + +#endif + + +static int _is_hex(char c) +{ + return (((c >= '0') && (c <= '9')) || + ((c >= 'A') && (c <= 'F')) || + ((c >= 'a') && (c <= 'f'))); +} + + +int rtl_string_to_hex(char *string, unsigned char *key, int len) +{ + char tmpBuf[4]; + int idx, ii=0; + for (idx=0; idxhwaddr[0] | 0x02; + addrp.s6_addr[9] = pstat->hwaddr[1]; + addrp.s6_addr[10] = pstat->hwaddr[2]; + addrp.s6_addr[11] = 0xff; + addrp.s6_addr[12] = 0xfe; + addrp.s6_addr[13] = pstat->hwaddr[3]; + addrp.s6_addr[14] = pstat->hwaddr[4]; + addrp.s6_addr[15] = pstat->hwaddr[5]; + + ipv6_addr_copy(&pstat->sta_v6ip, &addrp); +} + +void staip_snooping_byarp(struct sk_buff *pskb, struct stat_info *pstat) +{ + struct arphdr *arp = (struct arphdr *)(pskb->data + ETH_HLEN); + unsigned char *arp_ptr = (unsigned char *)(arp + 1); + if((arp->ar_pro == __constant_htons(ETH_P_IP)) && (arp->ar_op == htons(ARPOP_REQUEST))) { + //find sender ip + arp_ptr += arp->ar_hln; + //backup sender ip + if ((*arp_ptr == 0) && (*(arp_ptr+1) == 0) && (*(arp_ptr+2) == 0) && (*(arp_ptr+3) == 0)) + return; + else { + memcpy(pstat->sta_ip, arp_ptr, 4); + panic_printk("ARP cache ip=%d.%d.%d.%d\n", pstat->sta_ip[0],pstat->sta_ip[1],pstat->sta_ip[2],pstat->sta_ip[3]); + } + } +} + +void stav6ip_snooping_bynsolic(struct sk_buff *pskb, struct stat_info *pstat) +{ + struct ipv6hdr *hdr = (struct ipv6hdr *)(pskb->data+ETH_HLEN); + struct icmp6hdr *icmphdr; + int pkt_len, type; + if (hdr->version != 6) + return; + + if (hdr->hop_limit != 255) + return; + + pkt_len = ntohs(hdr->payload_len); + if (pkt_len>0) + { + icmphdr = (struct icmp6hdr *)(pskb->data+ETH_HLEN+sizeof(*hdr)); + type = icmphdr->icmp6_type; + if (type == NDISC_NEIGHBOUR_SOLICITATION) + { + if ((hdr->saddr.s6_addr32[0] == 0) && (hdr->saddr.s6_addr32[1] == 0) && (hdr->saddr.s6_addr32[2] == 0) && (hdr->saddr.s6_addr32[3] == 0)) { + struct in6_addr *target = (struct in6_addr *) (icmphdr + 1); + if ((target->s6_addr32[0] == 0) && (target->s6_addr32[1] == 0) && (target->s6_addr32[2] == 0) && (target->s6_addr32[3] == 0)) { + return; + } + else { + printk("rcv multicast ns duplicate addr\n"); + ipv6_addr_copy(&pstat->sta_v6ip, target); + } + } + else { + printk("rcv multicast ns\n"); + ipv6_addr_copy(&pstat->sta_v6ip, &hdr->saddr); + } + } + } +} + +#if 0 +void stav6ip_snooping_bynadvert(struct sk_buff *pskb, struct stat_info *pstat) +{ + struct ipv6hdr *hdr = (struct ipv6hdr *)(pskb->data+ETH_HLEN); + struct icmp6hdr *icmphdr; + int pkt_len, type; + if (hdr->version != 6) + return; + + if (hdr->hop_limit != 255) + return; + + pkt_len = ntohs(hdr->payload_len); + if (pkt_len>0) + { + icmphdr = (struct icmp6hdr *)(pskb->data+ETH_HLEN+sizeof(*hdr)); + type = icmphdr->icmp6_type; + if (type == NDISC_NEIGHBOUR_ADVERTISEMENT) + { + if ((hdr->saddr.s6_addr32[0] == 0) && (hdr->saddr.s6_addr32[1] == 0) && (hdr->saddr.s6_addr32[2] == 0) && (hdr->saddr.s6_addr32[3] == 0)) { + return; + } + else { + printk("rcv unsolicited neighbor advert multicast\n"); + ipv6_addr_copy(&pstat->sta_v6ip, &hdr->saddr); + } + } + } +} +#endif + +void staip_snooping_bydhcp(struct sk_buff *pskb, struct rtl8192cd_priv *priv) //struct stat_info *pstat) +{ + #define DHCP_MAGIC 0x63825363 + +struct iphdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 ihl:4, + version:4; +#elif defined (__BIG_ENDIAN_BITFIELD) + __u8 version:4, + ihl:4; +#else +#error "Please fix " +#endif + __u8 tos; + __u16 tot_len; + __u16 id; + __u16 frag_off; + __u8 ttl; + __u8 protocol; +#if 0 + __u16 check; + __u32 saddr; + __u32 daddr; +#endif +}; + +struct udphdr { + __u16 source; + __u16 dest; + __u16 len; + __u16 check; +}; + +struct dhcpMessage { + u_int8_t op; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + u_int32_t ciaddr; + u_int32_t yiaddr; + u_int32_t siaddr; + u_int32_t giaddr; + u_int8_t chaddr[16]; + u_int8_t sname[64]; + u_int8_t file[128]; + u_int32_t cookie; +#if 0 + u_int8_t options[308]; /* 312 - cookie */ +#endif +}; + + struct stat_info *pstat; + struct iphdr* iph; + struct udphdr *udph; + struct dhcpMessage *dhcph; + struct list_head *phead, *plist; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + iph = (struct iphdr *)(pskb->data + ETH_HLEN); + udph = (struct udphdr *)((unsigned int)iph + (iph->ihl << 2)); + dhcph = (struct dhcpMessage *)((unsigned int)udph + sizeof(struct udphdr)); + + phead = &priv->asoc_list; + SMP_LOCK_ASOC_LIST(flags); + plist = phead->next; + while (phead && (plist != phead)) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if (!memcmp(pstat->hwaddr, &dhcph->chaddr[0], 6)) { + if (dhcph->op == 2) //dhcp reply + { + if (dhcph->yiaddr != 0) { + memcpy(pstat->sta_ip, &dhcph->yiaddr, 4); + printk("dhcp give yip=%d.%d.%d.%d\n", pstat->sta_ip[0],pstat->sta_ip[1],pstat->sta_ip[2],pstat->sta_ip[3]); + } + } + SMP_UNLOCK_ASOC_LIST(flags); + return; + } + } + SMP_UNLOCK_ASOC_LIST(flags); +} + +extern __MIPS16 __IRAM_IN_865X int __rtl8192cd_start_xmit_out(struct sk_buff *skb, struct stat_info *pstat); + +int check_nei_advt(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data+ETH_HLEN); + struct icmp6hdr *icmpv6; + unsigned int pkt_len; + int type; + + pkt_len = ntohs(hdr->payload_len); + if (pkt_len>0) + { + icmpv6 = (struct icmp6hdr *)(skb->data+ETH_HLEN+sizeof(*hdr)); + type = icmpv6->icmp6_type; + //printk("pkt len=%d,type=%d\n", pkt_len, type); + if (type == NDISC_NEIGHBOUR_ADVERTISEMENT) + { + printk("drop nei advr\n"); + return 1; + } + else + return 0; + } + return 0; +} + +int proxy_icmpv6_ndisc(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + struct sk_buff *newskb = NULL; + struct in6_addr *addrp; + struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data+ETH_HLEN); + struct ipv6hdr *replyhdr; + struct icmp6hdr *icmpv6_nsolic; + struct icmp6hdr *icmpv6_nadvt; + struct stat_info *pstat; + struct list_head *phead, *plist; + unsigned int pkt_len; + int type; + + HS2_DEBUG_TRACE(2, "proxy_icmpv6_ndisc\n"); + if (hdr->version != 6) + return 0; + + pkt_len = ntohs(hdr->payload_len); + + if (pkt_len>0) + { + icmpv6_nsolic = (struct icmp6hdr *)(skb->data+ETH_HLEN+sizeof(*hdr)); + type = icmpv6_nsolic->icmp6_type; + //printk("pkt len=%d,type=%d\n", pkt_len, type); + if (type == NDISC_NEIGHBOUR_SOLICITATION) + { + HS2_DEBUG_TRACE(2, "NDISC_NEIGHBOUR_SOLICITATION\n"); + if (!memcmp(skb->data+ETH_ALEN, priv->pmib->dot11StationConfigEntry.dot11Bssid, ETH_ALEN)) + { + HS2_DEBUG_TRACE(2, "v6:arp req src mac=BSSID\n"); + return 0; + } + if (ipv6_addr_loopback(&hdr->daddr)) + { + HS2_DEBUG_TRACE(2, "v6:loopback\n"); + return 0; + } + + //search target ip mapping pstat mac + phead = &priv->asoc_list; + plist = phead->next; + while (phead && (plist != phead)) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + addrp = (struct in6_addr *)(icmpv6_nsolic+1); + if (ipv6_addr_equal(&pstat->sta_v6ip, addrp)) + { +#if defined(CONFIG_RTL865X_ETH_PRIV_SKB) || defined(CONFIG_RTL_ETH_PRIV_SKB) + extern struct sk_buff *priv_skb_copy(struct sk_buff *skb); + newskb = priv_skb_copy(skb); +#else + newskb = skb_copy(skb, GFP_ATOMIC); +#endif + //printk("compare ok!!\n"); + if (newskb == NULL) + { + priv->ext_stats.tx_drops++; + HS2_DEBUG_ERR("alloc icmpv6 neighbor advertisement skb null!!\n"); + rtl_kfree_skb(priv, skb, _SKB_TX_); + return 1; + } + else + { + unsigned char *opt; + int len; + //da + memcpy(newskb->data, newskb->data+ETH_ALEN, 6); + //sa + memcpy(newskb->data+ETH_ALEN, pstat->hwaddr, 6); + + replyhdr = (struct ipv6hdr *)(newskb->data+ETH_HLEN); + ipv6_addr_copy(&replyhdr->saddr, &pstat->sta_v6ip); + ipv6_addr_copy(&replyhdr->daddr, &hdr->saddr); + + icmpv6_nadvt = (struct icmp6hdr *)(newskb->data+ETH_HLEN+sizeof(*hdr)); + icmpv6_nadvt->icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; + icmpv6_nadvt->icmp6_solicited = 1; + icmpv6_nadvt->icmp6_override = 0; + + //target ip + opt = (unsigned char *)(newskb->data+ETH_HLEN+sizeof(*replyhdr)+sizeof(struct icmp6hdr)); + ipv6_addr_copy((struct in6_addr *)opt, &pstat->sta_v6ip); + opt += sizeof(struct in6_addr); + //option + opt[0] = 2; // Type: Target link-layer addr + opt[1] = 1; // Length: 1 (8 bytes) + memcpy(opt+2, pstat->hwaddr, ETH_ALEN); + icmpv6_nadvt->icmp6_cksum = 0; + len = sizeof(struct icmp6hdr)+sizeof(struct in6_addr)+8; + + icmpv6_nadvt->icmp6_cksum = csum_ipv6_magic(&replyhdr->saddr, &replyhdr->daddr, len, + IPPROTO_ICMPV6, csum_partial(icmpv6_nadvt, len, 0)); + + rtl_kfree_skb(priv, skb, _SKB_TX_); + + if (ipv6_addr_equal(&replyhdr->saddr, &replyhdr->daddr)) + { + printk("v6:tip=sip!!\n"); + dev_kfree_skb_any(newskb); + return 1; + } + + if ((pstat = get_stainfo(priv, newskb->data)) != NULL) + { + int i; + HS2_DEBUG_TRACE(2, "v6:da in wlan\n"); + newskb->cb[2] = (char)0xff; // not do aggregation + memcpy(newskb->cb+10,newskb->data,6); + HS2_DEBUG_INFO("data="); + for(i=0;idata[i]); + } + HS2_DEBUG_INFO("\n"); + //dev_kfree_skb_any(newskb); + __rtl8192cd_start_xmit(newskb, priv->dev, 1); + } + else + { + HS2_DEBUG_TRACE(2, "v6:da in lan\n"); + if (newskb->dev) +#ifdef __LINUX_2_6__ + newskb->protocol = eth_type_trans(newskb, newskb->dev); + else +#endif + newskb->protocol = eth_type_trans(newskb, priv->dev); + +#if defined(__LINUX_2_6__) && defined(RX_TASKLET) && !defined(CONFIG_RTL8672) && !defined(__LINUX_3_10__) + netif_receive_skb(newskb); +#else + netif_rx(newskb); +#endif + } + return 1; + } + } + } + } + } + return 0; +} + +int proxy_arp_handle(struct rtl8192cd_priv *priv, struct sk_buff *skb) +{ + struct sk_buff *newskb = NULL; + struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); + unsigned char *arp_ptr = (unsigned char *)(arp + 1), *psender, *ptarget, *psender_bak; + struct stat_info *pstat; + struct list_head *phead, *plist; + int k; + unsigned char *tmp = (unsigned char *)(skb->data); + + /*if((arp->ar_pro == __constant_htons(ETH_P_IP)) && (arp->ar_op == htons(ARPOP_REQUEST)||arp->ar_op == htons(ARPOP_REPLY))) + { + arp_ptr += arp->ar_hln; + psender_bak = arp_ptr; + //target ip + arp_ptr += (arp->ar_hln + arp->ar_pln); + ptarget = arp_ptr; + if (!memcmp(psender_bak,ptarget,4)) + { + printk("gratuitous ARP Request or Reply\n"); + return 0; + } + }*/ + HS2_DEBUG_TRACE(2, "Proxy ARP handle\n"); + if((arp->ar_pro == __constant_htons(ETH_P_IP)) && (arp->ar_op == htons(ARPOP_REQUEST))) + { + //{ + // int j; + // printk("orin==>"); + // for(j=0;jlen;j++) + // printk("0x%02x:",*(skb->data+j)); + // printk("\n"); + //} + //sender ip + arp_ptr += arp->ar_hln; + psender_bak = arp_ptr; + //target ip + arp_ptr += (arp->ar_hln + arp->ar_pln); + ptarget = arp_ptr; + + if (!memcmp(skb->data+ETH_ALEN, priv->pmib->dot11StationConfigEntry.dot11Bssid, ETH_ALEN)) + { + HS2_DEBUG_TRACE(1, "arp req src mac=BSSID\n"); + return 0; + } + + if (ipv4_is_loopback(ptarget) || ipv4_is_multicast(ptarget)) + { + HS2_DEBUG_TRACE(1, "loopback or muticast!!\n"); + return 0; + } + + //search target ip mapping pstat mac + phead = &priv->asoc_list; + plist = phead->next; + while (phead && (plist != phead)) + { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + HS2_DEBUG_INFO("Proxy ARP: Find Destination in Assocation List, sta_ip=%d.%d.%d.%d\n",pstat->sta_ip[0],pstat->sta_ip[1],pstat->sta_ip[2],pstat->sta_ip[3]); + if (!memcmp(pstat->sta_ip, ptarget, 4)) + { + panic_printk("Proxy ARP: Find Destination in Assocation List\n"); +#if defined(CONFIG_RTL865X_ETH_PRIV_SKB) || defined(CONFIG_RTL_ETH_PRIV_SKB) + extern struct sk_buff *priv_skb_copy(struct sk_buff *skb); + newskb = priv_skb_copy(skb); +#else + newskb = skb_copy(skb, GFP_ATOMIC); +#endif + if (newskb == NULL) + { + priv->ext_stats.tx_drops++; + HS2_DEBUG_ERR("alloc arp rsp skb null!!\n"); + rtl_kfree_skb(priv, skb, _SKB_TX_); + return 1; + } + else + { + // ====================== + // build new arp response + // ====================== + //da + memcpy(newskb->data, newskb->data+ETH_ALEN, 6); + //memcpy(newskb->data, priv->pmib->dot11StationConfigEntry.dot11Bssid, 6); + //sa + memcpy(newskb->data+ETH_ALEN, pstat->hwaddr, 6); + //memcpy(newskb->data+ETH_ALEN, priv->pmib->dot11StationConfigEntry.dot11Bssid, 6); + //arp response + arp = (struct arphdr *)(newskb->data + ETH_HLEN); + arp_ptr = (unsigned char *)(arp + 1); + arp->ar_op = htons(ARPOP_REPLY); + //sender mac and ip + memcpy(arp_ptr, pstat->hwaddr, 6); + arp_ptr += arp->ar_hln; + psender = (unsigned char *)arp_ptr; + memcpy(psender, ptarget, 4); + //printk("sender mac and ip:%02x:%02x:%02x:%02x:%02x:%02x,%d.%d.%d.%d\n",pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5],ptarget[0],ptarget[1],ptarget[2],ptarget[3]); + //target mac and ip + arp_ptr += arp->ar_pln; + memcpy(arp_ptr, newskb->data, 6); + //memcpy(newskb->data, priv->pmib->dot11StationConfigEntry.dot11Bssid, 6); + + arp_ptr += arp->ar_hln; + ptarget = arp_ptr; + memcpy((unsigned char *)ptarget, (unsigned char *)psender_bak, 4); + //printk("target mac and ip:%02x:%02x:%02x:%02x:%02x:%02x,%d.%d.%d.%d\n",newskb->data[0],newskb->data[1],newskb->data[2],newskb->data[3],newskb->data[4],newskb->data[5],ptarget[0],ptarget[1],ptarget[2],ptarget[3]); + + rtl_kfree_skb(priv, skb, _SKB_TX_); + + if (!memcmp(ptarget, psender, 4)) + { + HS2_DEBUG_TRACE(2, "target ip = sender ip!!\n"); + dev_kfree_skb_any(newskb); + return 1; + } + + if ((pstat = get_stainfo(priv, newskb->data)) != NULL) + { + //struct sk_buff_head *pqueue; + //struct timer_list *ptimer; + //void (*timer_hook)(unsigned long task_priv); + + //if (newskb->dev) +//#ifdef __LINUX_2_6__ +// newskb->protocol = eth_type_trans(newskb, newskb->dev); +// else +//#endif +// newskb->protocol = eth_type_trans(newskb, priv->dev); + +// printk("enq\n"); +// pqueue = &pstat->swq.be_queue; +// ptimer = &pstat->swq.beq_timer; +// timer_hook = rtl8192cd_beq_timer; + +// skb_queue_tail(pqueue, newskb); +// ptimer->data = (unsigned long)pstat; +// ptimer->function = timer_hook; //rtl8190_tmp_timer; +// mod_timer(ptimer, jiffies + 1); + +// SAVE_INT_AND_CLI(x); + //pstat = get_stainfo(priv, newskb->data); + HS2_DEBUG_TRACE(1, "da in wlan\n"); + //__rtl8192cd_start_xmit_out(newskb, pstat); + newskb->cb[2] = (char)0xff; // not do aggregation + memcpy(newskb->cb+10,newskb->data,6); + __rtl8192cd_start_xmit(newskb, priv->dev, 1); +// RESTORE_INT(x); + + } + else + { + HS2_DEBUG_TRACE(1, "da in lan\n"); + if (newskb->dev) +#ifdef __LINUX_2_6__ + newskb->protocol = eth_type_trans(newskb, newskb->dev); + else +#endif + newskb->protocol = eth_type_trans(newskb, priv->dev); + +#if defined(__LINUX_2_6__) && defined(RX_TASKLET) && !defined(CONFIG_RTL8672) + netif_receive_skb(newskb); +#else + netif_rx(newskb); +#endif + } + return 1; + } + } + } + } + + //drop packet + return 0; +} + +void rtl8192cd_cu_cntdwn_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + int val; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (timer_pending(&priv->cu_cntdwn_timer)) + { + del_timer_sync(&priv->cu_cntdwn_timer); + } + + if ((val = read_bbp_ch_load(priv)) == -1) + { + //printk("bbp not ready!!!\n"); + mod_timer(&priv->cu_cntdwn_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(10)); + } + else + { + priv->chbusytime += val; + priv->cu_cntdwn--; + if (priv->cu_cntdwn == 0) + { + priv->channel_utilization = (priv->chbusytime*255)/(priv->pmib->hs2Entry.channel_utili_beaconIntval * priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod * 1024); + //printk("ch=%d\n", priv->channel_utilization); + priv->chbusytime = 0; + priv->cu_cntdwn = priv->cu_initialcnt; + } + start_bbp_ch_load(priv); + mod_timer(&priv->cu_cntdwn_timer, jiffies + CU_TO); + } +} +#endif + +#ifdef USE_TXQUEUE +int init_txq_pool(struct list_head *head, unsigned char **ppool) +{ + unsigned char *ptr; + unsigned int i; + struct txq_node *pnode; + + INIT_LIST_HEAD(head); + + ptr = kmalloc(TXQUEUE_SIZE * sizeof(struct txq_node), GFP_ATOMIC); + if (!ptr) { + printk("ERRORL: %s failed\n", __FUNCTION__); + *ppool = NULL; + return -1; + } + + pnode = (struct txq_node *)ptr; + for (i=0; iext_stats.tx_drops++; + return; + } + + pnode = (struct txq_node *)pool->next; + list_del(pool->next); + pnode->skb = skb; + pnode->dev = dev; + + add_txq_head(head, pnode); +} + +void append_skb_to_txq_tail(struct txq_list_head *head, struct rtl8192cd_priv *priv, struct sk_buff *skb, struct net_device *dev, struct list_head *pool) +{ + struct txq_node *pnode = NULL; + + if (list_empty(pool)) + { + DEBUG_ERR("%s: No unused node in pool, this should not happend, fix me.\n", __FUNCTION__); + rtl_kfree_skb(priv, skb, _SKB_TX_); + DEBUG_ERR("TX DROP: exceed the tx queue!\n"); + priv->ext_stats.tx_drops++; + return; + } + + pnode = (struct txq_node *)pool->next; + list_del(pool->next); + pnode->skb = skb; + pnode->dev = dev; + + add_txq_tail(head, pnode); +} + +void remove_skb_from_txq(struct txq_list_head *head, struct sk_buff **pskb, struct net_device **pdev, struct list_head *pool) +{ + struct txq_node *pnode = NULL; + + if (is_txq_empty(head)) + { + *pskb = NULL; + *pdev = NULL; + return; + } + + pnode = deq_txq(head); + *pskb = pnode->skb; + *pdev = pnode->dev; + pnode->skb = NULL; + pnode->dev = NULL; + + list_add_tail(&pnode->list, pool); +} + +#endif + + +#ifdef TLN_STATS +void stats_conn_rson_counts(struct rtl8192cd_priv *priv, unsigned int reason) +{ + switch (reason) { + case _RSON_UNSPECIFIED_: + priv->ext_wifi_stats.rson_UNSPECIFIED_1++; + break; + case _RSON_AUTH_NO_LONGER_VALID_: + priv->ext_wifi_stats.rson_AUTH_INVALID_2++; + break; + case _RSON_DEAUTH_STA_LEAVING_: + priv->ext_wifi_stats.rson_DEAUTH_STA_LEAVING_3++; + break; + case _RSON_INACTIVITY_: + priv->ext_wifi_stats.rson_INACTIVITY_4++; + break; + case _RSON_UNABLE_HANDLE_: + priv->ext_wifi_stats.rson_RESOURCE_INSUFFICIENT_5++; + break; + case _RSON_CLS2_: + priv->ext_wifi_stats.rson_UNAUTH_CLS2FRAME_6++; + break; + case _RSON_CLS3_: + priv->ext_wifi_stats.rson_UNAUTH_CLS3FRAME_7++; + break; + case _RSON_DISAOC_STA_LEAVING_: + priv->ext_wifi_stats.rson_DISASSOC_STA_LEAVING_8++; + break; + case _RSON_ASOC_NOT_AUTH_: + priv->ext_wifi_stats.rson_ASSOC_BEFORE_AUTH_9++; + break; + case _RSON_INVALID_IE_: + priv->ext_wifi_stats.rson_INVALID_IE_13++; + break; + case _RSON_MIC_FAILURE_: + priv->ext_wifi_stats.rson_MIC_FAILURE_14++; + break; + case _RSON_4WAY_HNDSHK_TIMEOUT_: + priv->ext_wifi_stats.rson_4WAY_TIMEOUT_15++; + break; + case _RSON_GROUP_KEY_UPDATE_TIMEOUT_: + priv->ext_wifi_stats.rson_GROUP_KEY_TIMEOUT_16++; + break; + case _RSON_DIFF_IE_: + priv->ext_wifi_stats.rson_DIFF_IE_17++; + break; + case _RSON_MLTCST_CIPHER_NOT_VALID_: + priv->ext_wifi_stats.rson_MCAST_CIPHER_INVALID_18++; + break; + case _RSON_UNICST_CIPHER_NOT_VALID_: + priv->ext_wifi_stats.rson_UCAST_CIPHER_INVALID_19++; + break; + case _RSON_AKMP_NOT_VALID_: + priv->ext_wifi_stats.rson_AKMP_INVALID_20++; + break; + case _RSON_UNSUPPORT_RSNE_VER_: + priv->ext_wifi_stats.rson_UNSUPPORT_RSNIE_VER_21++; + break; + case _RSON_INVALID_RSNE_CAP_: + priv->ext_wifi_stats.rson_RSNIE_CAP_INVALID_22++; + break; + case _RSON_IEEE_802DOT1X_AUTH_FAIL_: + priv->ext_wifi_stats.rson_802_1X_AUTH_FAIL_23++; + break; + default: + priv->ext_wifi_stats.rson_OUT_OF_SCOPE++; + /*panic_printk("incorrect reason(%d) for statistics\n", reason);*/ + break; + } + + priv->wifi_stats.rejected_sta++; +} + + +void stats_conn_status_counts(struct rtl8192cd_priv *priv, unsigned int status) +{ + switch (status) { + case _STATS_SUCCESSFUL_: + priv->wifi_stats.connected_sta++; + break; + case _STATS_FAILURE_: + priv->ext_wifi_stats.status_FAILURE_1++; + break; + case _STATS_CAP_FAIL_: + priv->ext_wifi_stats.status_CAP_FAIL_10++; + break; + case _STATS_NO_ASOC_: + priv->ext_wifi_stats.status_NO_ASSOC_11++; + break; + case _STATS_OTHER_: + priv->ext_wifi_stats.status_OTHER_12++; + break; + case _STATS_NO_SUPP_ALG_: + priv->ext_wifi_stats.status_NOT_SUPPORT_ALG_13++; + break; + case _STATS_OUT_OF_AUTH_SEQ_: + priv->ext_wifi_stats.status_OUT_OF_AUTH_SEQ_14++; + break; + case _STATS_CHALLENGE_FAIL_: + priv->ext_wifi_stats.status_CHALLENGE_FAIL_15++; + break; + case _STATS_AUTH_TIMEOUT_: + priv->ext_wifi_stats.status_AUTH_TIMEOUT_16++; + break; + case _STATS_UNABLE_HANDLE_STA_: + priv->ext_wifi_stats.status_RESOURCE_INSUFFICIENT_17++; + break; + case _STATS_RATE_FAIL_: + priv->ext_wifi_stats.status_RATE_FAIL_18++; + break; + default: + priv->ext_wifi_stats.status_OUT_OF_SCOPE++; + /*panic_printk("incorrect status(%d) for statistics\n", status);*/ + break; + } + + if (status != _STATS_SUCCESSFUL_) + priv->wifi_stats.rejected_sta++; +} +#endif + + +#ifdef SW_TX_QUEUE +void adjust_swq_setting(struct rtl8192cd_priv *priv, struct stat_info *pstat, int i, int mode) +{ + int thd; + + if(pstat->swq.q_used[i]) { + if (mode == CHECK_DEC_AGGN) { + if (pstat->swq.q_aggnum[i] <= 2) + thd = priv->pshare->rf_ft_var.timeout_thd; + else if (pstat->swq.q_aggnum[i] <= 4) + thd = priv->pshare->rf_ft_var.timeout_thd2; + else + thd = priv->pshare->rf_ft_var.timeout_thd3; + + if ((pstat->swq.q_TOCount[i] >= thd)&& ((pstat->swq.q_TOCount[i] % thd) == 0)) { + --(pstat->swq.q_aggnum[i]); + if (pstat->swq.q_aggnum[i] <= 2) + pstat->swq.q_aggnum[i] = 2; + if (++pstat->swq.q_aggnumIncSlow[i] >= MAX_BACKOFF_CNT) + pstat->swq.q_aggnumIncSlow[i] = MAX_BACKOFF_CNT; + DEBUG_INFO("dec,aid:%d,cnt:%d\n", pstat->aid, pstat->swq.q_TOCount[i]); + } + } + else { + if (pstat->swq.q_aggnum[i] <= 2) + thd = priv->pshare->rf_ft_var.timeout_thd-10; + else if (pstat->swq.q_aggnum[i] <= 4) + thd = priv->pshare->rf_ft_var.timeout_thd2-30; + else + thd = priv->pshare->rf_ft_var.timeout_thd3-50; + + if(pstat->swq.q_TOCount[i]< thd) { + int step = 1; + if(pstat->swq.q_TOCount[i]< thd/5) + step = 5; + else if(pstat->swq.q_TOCount[i]< thd/3) + step = 3; + + pstat->swq.q_aggnum[i] += step; + + if (pstat->swq.q_aggnum[i] > priv->pshare->rf_ft_var.swq_aggnum) + pstat->swq.q_aggnum[i] = priv->pshare->rf_ft_var.swq_aggnum; + //panic_printk("inc,aid:%d,cnt:%d,%d\n", pstat->aid, pstat->swq.q_TOCount[i], pstat->swq.q_aggnum[BE_QUEUE]); + } + } + } +} +#endif + +#if defined(CONFIG_RTL_ULINKER) +int get_wlan_opmode(struct net_device *dev) +{ + int opmode = -1; + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)dev->priv; + + if (netif_running(dev)) { + if ((priv->pmib->dot11OperationEntry.opmode) & WIFI_AP_STATE) + opmode = 0; + else + opmode = 1; + } + + return opmode; +} +#endif + + + +#if defined(RF_MIMO_SWITCH) || defined(RF_MIMO_PS) + +void Do_BB_Reset(struct rtl8192cd_priv *priv) +{ + unsigned char tmp_reg2 = 0; + tmp_reg2 = RTL_R8(0x2); + + tmp_reg2 &= (~BIT(0)); + RTL_W8(0x2, tmp_reg2); + tmp_reg2 |= BIT(0); + RTL_W8(0x2, tmp_reg2); + +} + +void Assert_BB_Reset(struct rtl8192cd_priv *priv) +{ + unsigned char tmp_reg2 = 0; + tmp_reg2 = RTL_R8(0x2); + + tmp_reg2 &= (~BIT(0)); + RTL_W8(0x2, tmp_reg2); +} + +void Release_BB_Reset(struct rtl8192cd_priv *priv) +{ + unsigned char tmp_reg2 = 0; + tmp_reg2 = RTL_R8(0x2); + + tmp_reg2 |= BIT(0); + RTL_W8(0x2, tmp_reg2); +} + +void RF_MIMO_check_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + int i=0, assoc_num = priv->assoc_num; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if(get_rf_mimo_mode(priv) != MIMO_2T2R) + return; + + if(priv->auto_channel || timer_pending(&priv->ss_timer)) { +#ifdef CONFIG_PCI_HCI + goto end; +#else + return; +#endif + } +#ifdef MCR_WIRELESS_EXTEND + return; +#endif +#ifdef MP_TEST + if (((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) + return; +#endif + if(0 +#ifdef WDS + || (priv->pmib->dot11WdsInfo.wdsEnabled) +#endif +#ifdef UNIVERSAL_REPEATER + || (IS_DRV_OPEN(GET_VXD_PRIV(priv))) +#endif + ) { + if(MIMO_mode_switch(priv, MIMO_2T2R)) { +#if defined(WIFI_11N_2040_COEXIST_EXT) + if((priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) && (priv->pmib->dot11nConfigEntry.dot11nUse40M != HT_CHANNEL_WIDTH_20)) { + priv->pshare->CurrentChannelBW = priv->pmib->dot11nConfigEntry.dot11nUse40M; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + } +#endif + } + return; + } + + if(priv->pshare->rf_ft_var.rf_mode ==0) { +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable){ + for (i=0; ipvap_priv[i]-> assoc_num; + } +#endif + if(assoc_num) { + if(MIMO_mode_switch(priv, MIMO_2T2R)) { +#if defined(WIFI_11N_2040_COEXIST_EXT) + if((priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) && (priv->pmib->dot11nConfigEntry.dot11nUse40M != HT_CHANNEL_WIDTH_20)) { + priv->pshare->CurrentChannelBW = priv->pmib->dot11nConfigEntry.dot11nUse40M; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + } +#endif + // reset bb for 8812 to avoid rx hang + //if (GET_CHIP_VER(priv) == VERSION_8812E) + //Do_BB_Reset(priv); + } + } + else { +#if defined(WIFI_11N_2040_COEXIST_EXT) + if((priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40)|| (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_80)) { + priv->pshare->CurrentChannelBW = HT_CHANNEL_WIDTH_20; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + } +#endif + if(MIMO_mode_switch(priv, MIMO_1T1R)) { + + // reset bb for 8812 to avoid rx hang + //if (GET_CHIP_VER(priv) == VERSION_8812E) + //Do_BB_Reset(priv); + + } + } + } else if (priv->pshare->rf_ft_var.rf_mode == 2) { + if(MIMO_mode_switch(priv, MIMO_2T2R)) { +#if defined(WIFI_11N_2040_COEXIST_EXT) + if((priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) && (priv->pmib->dot11nConfigEntry.dot11nUse40M != HT_CHANNEL_WIDTH_20)) { + priv->pshare->CurrentChannelBW = priv->pmib->dot11nConfigEntry.dot11nUse40M; + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); +#if defined(CONFIG_RTL_8812_SUPPORT) || defined(CONFIG_WLAN_HAL) + update_RAMask_to_FW(priv, 1); +#endif + SetTxPowerLevel(priv); + } +#endif + } + } else if (priv->pshare->rf_ft_var.rf_mode == 1) { + MIMO_mode_switch(priv, MIMO_1T1R); + } + +#ifdef CONFIG_PCI_HCI +end: + mod_timer(&priv->ps_timer, jiffies + IDLE_T0); +#endif +} + +/* + * 92es sdio debug using GPIO 14 to trigger + */ + +int switch_gpio14_mode(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int mode = _atoi(data, 16); + + RTL_W32(0x4c, RTL_R32(0x4c) & ~BIT(22)); + RTL_W32(0x60, RTL_R32(0x60) & ~BIT(30)); + + RTL_W32(0x60, RTL_R32(0x60) | BIT(22)); + + if ( mode == 0x01 ) { + RTL_W32(0x60, RTL_R32(0x60) | BIT(14)); + printk("goip high\n"); + } else if ( mode == 0x02) { + RTL_W32(0x60, RTL_R32(0x60) & ~BIT(14)); + printk("goip low\n"); + } +} + +int assign_MIMO_TR_Mode(struct rtl8192cd_priv *priv, unsigned char *data) +{ +#define dprintf printk + int mode = _atoi(data, 16); + if (strlen(data) == 0) { + printk("tr mode.\n"); + printk("mimo 1: swith to 1T\n"); + printk("mimo 2: switch to 2T\n"); + printk("mimo 0: auto\n"); + return 0; + } + if (mode == 0x01) { + MIMO_mode_switch(priv, MIMO_1T1R); + priv->pshare->rf_ft_var.rf_mode = 1; + } else if (mode == 0x02) { + MIMO_mode_switch(priv, MIMO_2T2R); + priv->pshare->rf_ft_var.rf_mode = 2; + } else { + priv->pshare->rf_ft_var.rf_mode = 0; + } + return 0; +} +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +struct list_head* asoc_list_get_next(struct rtl8192cd_priv *priv, struct list_head *plist) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + struct list_head *phead, *plist_next; + struct stat_info *pstat; + + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist_next = plist->next; + if (plist_next != phead) { + pstat = list_entry(plist_next, struct stat_info, asoc_list); + pstat->asoc_list_refcnt++; +#ifdef __ECOS + cyg_flag_maskbits(&pstat->asoc_unref_done, ~0x1); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)) + reinit_completion(&pstat->asoc_unref_done); +#else + INIT_COMPLETION(pstat->asoc_unref_done); +#endif +#endif + } + + SMP_UNLOCK_ASOC_LIST(flags); + + if (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + asoc_list_unref(priv, pstat); + } + + return plist_next; +} + +void asoc_list_unref(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + SMP_LOCK_ASOC_LIST(flags); + + BUG_ON(0 == pstat->asoc_list_refcnt); + + pstat->asoc_list_refcnt--; + if (0 == pstat->asoc_list_refcnt) { + list_del_init(&pstat->asoc_list); +#ifdef __ECOS + cyg_flag_setbits(&pstat->asoc_unref_done, 0x1); +#else + complete(&pstat->asoc_unref_done); +#endif + } + + SMP_UNLOCK_ASOC_LIST(flags); +} + +// The function returns whether it had linked to asoc_list before removing. +int asoc_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + int ret = 0, wait = 0; + +#ifdef __KERNEL__ + might_sleep(); +#endif + + SMP_LOCK_ASOC_LIST(flags); + + if (0 != pstat->asoc_list_refcnt) { + pstat->asoc_list_refcnt--; + if (0 ==pstat->asoc_list_refcnt) { +// if (!list_empty(&pstat->asoc_list)) { + list_del_init(&pstat->asoc_list); + ret = 1; +// } + } else { + wait = 1; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + + if (wait) { +#ifdef __ECOS + cyg_flag_wait(&pstat->asoc_unref_done, 0x01, CYG_FLAG_WAITMODE_OR | CYG_FLAG_WAITMODE_CLR); +#else + wait_for_completion(&pstat->asoc_unref_done); +#endif + ret = 1; + } + + return ret; +} + +int asoc_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + int ret = 0; + + SMP_LOCK_ASOC_LIST(flags); + + if (list_empty(&pstat->asoc_list)) { + list_add_tail(&pstat->asoc_list, &priv->asoc_list); + pstat->asoc_list_refcnt = 1; + ret = 1; + } + + SMP_UNLOCK_ASOC_LIST(flags); + + return ret; +} +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#ifdef WIFI_SIMPLE_CONFIG +#define IGNORE_DISCON_TIMEOUT 3 +void wsc_disconn_list_add(struct rtl8192cd_priv *priv, unsigned char *hwaddr) +{ + struct wsc_disconn_entry *entry; + unsigned long flags; + + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + if (NULL == entry) + return; + + INIT_LIST_HEAD(&entry->list); + memcpy(entry->addr, hwaddr, MACADDRLEN); + entry->state = WSC_DISCON_STATE_RECV_EAP_FAIL; + entry->expire_to = IGNORE_DISCON_TIMEOUT; + + spin_lock_irqsave(&priv->wsc_disconn_list_lock, flags); + + list_add_tail(&entry->list, &priv->wsc_disconn_list); + + spin_unlock_irqrestore(&priv->wsc_disconn_list_lock, flags); +} + +void wsc_disconn_list_expire(struct rtl8192cd_priv *priv) +{ + struct list_head *phead, *plist; + struct wsc_disconn_entry *entry; + unsigned long flags; + + phead = &priv->wsc_disconn_list; + + if (list_empty(phead)) + return; + + spin_lock_irqsave(&priv->wsc_disconn_list_lock, flags); + + plist = phead->next; + + while (plist != phead) { + entry = list_entry(plist, struct wsc_disconn_entry, list); + plist = plist->next; + + entry->expire_to--; + if (0 == entry->expire_to) { + list_del(&entry->list); + kfree(entry); + } + } + + spin_unlock_irqrestore(&priv->wsc_disconn_list_lock, flags); +} + +void wsc_disconn_list_update(struct rtl8192cd_priv *priv, unsigned char *hwaddr) +{ + struct list_head *phead, *plist; + struct wsc_disconn_entry *entry; + unsigned long flags; + + phead = &priv->wsc_disconn_list; + + if (list_empty(phead)) + return; + + spin_lock_irqsave(&priv->wsc_disconn_list_lock, flags); + + plist = phead->next; + + while (plist != phead) { + entry = list_entry(plist, struct wsc_disconn_entry, list); + plist = plist->next; + + if (!memcmp(entry->addr, hwaddr, MACADDRLEN)) { + if (WSC_DISCON_STATE_RECV_EAP_FAIL == entry->state) + entry->state = WSC_DISCON_STATE_IGNORE; + break; + } + } + + spin_unlock_irqrestore(&priv->wsc_disconn_list_lock, flags); +} + +int wsc_disconn_list_check(struct rtl8192cd_priv *priv, unsigned char *hwaddr) +{ + struct list_head *phead, *plist; + struct wsc_disconn_entry *entry; + unsigned long flags; + int status; + + phead = &priv->wsc_disconn_list; + + if (list_empty(phead)) + return FALSE; + + spin_lock_irqsave(&priv->wsc_disconn_list_lock, flags); + + plist = phead->next; + + while (plist != phead) { + entry = list_entry(plist, struct wsc_disconn_entry, list); + plist = plist->next; + + if (!memcmp(entry->addr, hwaddr, MACADDRLEN)) { + list_del(&entry->list); + spin_unlock_irqrestore(&priv->wsc_disconn_list_lock, flags); + + status = (WSC_DISCON_STATE_IGNORE == entry->state) ? TRUE : FALSE; + kfree(entry); + return status; + } + } + + spin_unlock_irqrestore(&priv->wsc_disconn_list_lock, flags); + + return FALSE; +} + +void wsc_disconn_list_flush(struct rtl8192cd_priv *priv) +{ + struct list_head *phead, *plist; + struct wsc_disconn_entry *entry; + unsigned long flags; + + phead = &priv->wsc_disconn_list; + + if (list_empty(phead)) + return; + + spin_lock_irqsave(&priv->wsc_disconn_list_lock, flags); + + plist = phead->next; + + while (plist != phead) { + entry = list_entry(plist, struct wsc_disconn_entry, list); + plist = plist->next; + kfree(entry); + } + + spin_unlock_irqrestore(&priv->wsc_disconn_list_lock, flags); +} +#endif // WIFI_SIMPLE_CONFIG + + +//return value: Auto site-survey level +//0(SS_LV_WSTA), STA connect to root AP/VAP +//1(SS_LV_WOSTA), No STA connected to root AP/VAP +//2(SS_LV_ROOTFUNCOFF), root AP only and func_off=1 +int get_ss_level(struct rtl8192cd_priv *priv) +{ + int idx=0; + + if( GET_ROOT(priv)->pmib->miscEntry.func_off ){ + + #ifdef MBSSID + if(GET_ROOT(priv)->pmib->miscEntry.vap_enable==0) + return SS_LV_ROOTFUNCOFF; + else{ + for (idx=0; idxpvap_priv[idx])&& + (GET_ROOT(priv)->pvap_priv[idx]->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) && + (GET_ROOT(priv)->pvap_priv[idx]->assoc_num)){ + return SS_LV_WSTA; + } + } + } + #else + return SS_LV_ROOTFUNCOFF; + #endif + + } + else{ + + if((GET_ROOT(priv)->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) && GET_ROOT(priv)->assoc_num) + return SS_LV_WSTA; + + #ifdef MBSSID + if(GET_ROOT(priv)->pmib->miscEntry.vap_enable==1) { + for (idx=0; idxpvap_priv[idx])&& + (GET_ROOT(priv)->pvap_priv[idx]->pmib->dot11OperationEntry.opmode & WIFI_AP_STATE) && + (GET_ROOT(priv)->pvap_priv[idx]->assoc_num)) + { + return SS_LV_WSTA; + } + } + } + #endif + } + + //default + return SS_LV_WOSTA; + +} + +void syncMulticastCipher(struct rtl8192cd_priv *priv, struct bss_desc *bss_target) +{ + int mcipher = 1; + // set Multicast Cipher as same as AP's + if (priv->pmib->dot11RsnIE.rsnie[0] == _RSN_IE_1_) { + if(bss_target->t_stamp[0] & BIT(4)) + mcipher = 4; + else if(bss_target->t_stamp[0] & BIT(2)) + mcipher = 2; + priv->pmib->dot11RsnIE.rsnie[11] = mcipher; +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + priv->wpa_global_info->AuthInfoBuf[11] = mcipher; +#endif + } else if(priv->pmib->dot11RsnIE.rsnie[0] == _RSN_IE_2_) { + if(bss_target->t_stamp[0] & BIT(20)) + mcipher = 4; + else if(bss_target->t_stamp[0] & BIT(18)) + mcipher = 2; + priv->pmib->dot11RsnIE.rsnie[7] = mcipher; +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) + priv->wpa_global_info->AuthInfoBuf[7] = mcipher; + +#ifdef CONFIG_IEEE80211W_CLI + if ((bss_target->t_stamp[1] & PMF_REQ) == PMF_REQ) { + PMFDEBUG("AP PMF capability = Required\n"); + priv->support_pmf = TRUE; + } else if (bss_target->t_stamp[1] & PMF_CAP) { + PMFDEBUG("AP PMF capability = MFPC\n"); + priv->support_pmf = TRUE; + } else { + priv->support_pmf = FALSE; + } +#endif +#endif + } +} + +unsigned int isDHCPpkt(struct sk_buff *pskb) +{ +#define DHCP_MAGIC 0x63825363 + + struct iphdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 ihl:4, + version:4; +#elif defined (__BIG_ENDIAN_BITFIELD) + __u8 version:4, + ihl:4; +#else +#error "Please fix " +#endif + __u8 tos; + __u16 tot_len; + __u16 id; + __u16 frag_off; + __u8 ttl; + __u8 protocol; +#if 0 + __u16 check; + __u32 saddr; + __u32 daddr; +#endif + }; + + struct udphdr { + __u16 source; + __u16 dest; + __u16 len; + __u16 check; + }; + + struct dhcpMessage { + u_int8_t op; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + u_int32_t ciaddr; + u_int32_t yiaddr; + u_int32_t siaddr; + u_int32_t giaddr; + u_int8_t chaddr[16]; + u_int8_t sname[64]; + u_int8_t file[128]; + u_int32_t cookie; +#if 0 + u_int8_t options[308]; /* 312 - cookie */ +#endif + }; + + unsigned short protocol = 0; + struct iphdr* iph; + struct udphdr *udph; + struct dhcpMessage *dhcph; + + protocol = *((unsigned short *)(pskb->data + 2 * ETH_ALEN)); + + if(protocol == __constant_htons(ETH_P_IP)) { /* IP */ + iph = (struct iphdr *)(pskb->data + ETH_HLEN); + + if(iph->protocol == 17) { /* UDP */ + udph = (struct udphdr *)((unsigned long)iph + (iph->ihl << 2)); + dhcph = (struct dhcpMessage *)((unsigned long)udph + sizeof(struct udphdr)); + + if ((unsigned long)dhcph & 0x03) { //not 4-byte alignment + u_int32_t cookie; + char *pdhcphcookie; + char *pcookie = (char *)&cookie; + + pdhcphcookie = (char *)&dhcph->cookie; + pcookie[0] = pdhcphcookie[0]; + pcookie[1] = pdhcphcookie[1]; + pcookie[2] = pdhcphcookie[2]; + pcookie[3] = pdhcphcookie[3]; + if(cookie == htonl(DHCP_MAGIC)) + return TRUE; + } + else { + if(dhcph->cookie == htonl(DHCP_MAGIC)) + return TRUE; + } + } + } + + return FALSE; +} + +#ifdef UNIVERSAL_REPEATER +#if defined (__ECOS) || defined(RTK_NL80211) || (defined(CONFIG_OPENWRT_SDK) && defined(__LINUX_3_10__))//wrt-dhcp //TBD //eric-sync ?? __LINUX_3_10__ +int send_arp_response(struct rtl8192cd_priv *priv, unsigned int *dip, unsigned int *sip, unsigned char *dmac, unsigned char *smac) +{ + return -1; +} +#else +int send_arp_response(struct rtl8192cd_priv *priv, unsigned int *dip, unsigned int *sip, unsigned char *dmac, unsigned char *smac) +{ + unsigned int ret = -1; + struct sk_buff *arp_skb = NULL; + struct rtl_arphdr *arp=NULL; + unsigned char *ptr; + int hlen, tlen; + + hlen = LL_RESERVED_SPACE(priv->dev); + tlen = priv->dev->needed_tailroom; + arp_skb = __alloc_skb(arp_hdr_len(priv->dev) + hlen + tlen, GFP_ATOMIC, 0, -1); + + if (arp_skb == NULL) + goto err_out; + + skb_reserve(arp_skb, LL_RESERVED_SPACE(priv->dev)); + skb_reset_network_header(arp_skb); + arp = (struct rtl_arphdr *) skb_put(arp_skb, arp_hdr_len(priv->dev)); + arp_skb->dev = priv->dev; + arp_skb->protocol = htons(ETH_P_ARP); +#if 0 + //without consideration of VLAN +//#ifdef CONFIG_RTK_VLAN_SUPPORT + arp_skb->tag = arp_tag; +#if defined(CONFIG_RTK_VLAN_NEW_FEATURE) + arp_skb->src_info = arp_info; +#endif +#endif + if (dev_hard_header(arp_skb, priv->dev, ETH_P_ARP, dmac, smac, arp_skb->len) < 0) { + kfree_skb(arp_skb); + goto err_out; + } + // ====================== + // build new arp response + // ====================== + //arp response + ptr = (unsigned char *)(arp + 1); + arp->ar_op = htons(ARPOP_REPLY); + arp->ar_hrd = htons(priv->dev->type); + arp->ar_pro = htons(ETH_P_IP); + arp->ar_hln = priv->dev->addr_len;; + arp->ar_pln = 4; //for ipv4 + //sender mac and ip + memcpy(ptr, smac, 6); + ptr += arp->ar_hln; + memcpy(ptr, sip, 4); + //printk("sender mac and ip:%02x:%02x:%02x:%02x:%02x:%02x,%d.%d.%d.%d\n",pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5],pstat->sta_ip[0],pstat->sta_ip[1],pstat->sta_ip[2],pstat->sta_ip[3]); + //target mac and ip + ptr += arp->ar_pln; + memcpy(ptr, dmac, MACADDRLEN); + ptr += arp->ar_hln; + memcpy(ptr, dip, 4); + //printk("target mac and ip:%02x:%02x:%02x:%02x:%02x:%02x,%d.%d.%d.%d\n",newskb->data[0],newskb->data[1],newskb->data[2],newskb->data[3],newskb->data[4],newskb->data[5],ptarget[0],ptarget[1],ptarget[2],ptarget[3]); + +#ifdef MULTI_MAC_CLONE + *(unsigned int *)&(arp_skb->cb[40]) = 0x86518192; +#endif + + if(arp_skb){ + int i=0; + arp_skb->cb[2] = (char)0xff; // not do aggregation + memcpy(arp_skb->cb+10,arp_skb->data,6); + SMP_LOCK_XMIT(x); + if(__rtl8192cd_start_xmit(arp_skb, priv->dev, 1)) { + DEBUG_ERR("%s %d ARP response sent failed\n",__func__,__LINE__); + } else { + ret = 0; + DEBUG_INFO("%s %d ARP response for %02x:%02x:%02x:%02x:%02x:%02x to %s sent\n",__func__,__LINE__, + smac[0],smac[1],smac[2],smac[3],smac[4],smac[5],priv->dev->name); + for(i=0;ilen;i++){ + DEBUG_INFO("%02x",arp_skb->data[i]); + if(i/16 && ((i%16) == 0)) + DEBUG_INFO("\n"); + } + DEBUG_INFO("\n"); + } + SMP_UNLOCK_XMIT(x); + } else { + DEBUG_ERR("%s %d Alloc skb failed\n",__func__,__LINE__); + } + + return ret; + +err_out: + return ret; +} +#endif + +void snoop_STA_IP(struct sk_buff *pskb, struct rtl8192cd_priv *priv) +{ + #define DHCP_MAGIC 0x63825363 + +struct iphdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u8 ihl:4, + version:4; +#elif defined (__BIG_ENDIAN_BITFIELD) + __u8 version:4, + ihl:4; +#else +#error "Please fix " +#endif + __u8 tos; + __u16 tot_len; + __u16 id; + __u16 frag_off; + __u8 ttl; + __u8 protocol; +#if 0 + __u16 check; + __u32 saddr; + __u32 daddr; +#endif +}; + +struct udphdr { + __u16 source; + __u16 dest; + __u16 len; + __u16 check; +}; + +struct dhcpMessage { + u_int8_t op; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + u_int32_t ciaddr; + u_int32_t yiaddr; + u_int32_t siaddr; + u_int32_t giaddr; + u_int8_t chaddr[16]; + u_int8_t sname[64]; + u_int8_t file[128]; + u_int32_t cookie; +#if 0 + u_int8_t options[308]; /* 312 - cookie */ +#endif +}; + struct rtl8192cd_priv *ap_priv; + struct stat_info *pstat; + struct iphdr* iph; + struct udphdr *udph; + struct dhcpMessage *dhcph; + struct list_head *phead, *plist; + + iph = (struct iphdr *)(pskb->data + ETH_HLEN); + udph = (struct udphdr *)((unsigned int)iph + (iph->ihl << 2)); + dhcph = (struct dhcpMessage *)((unsigned int)udph + sizeof(struct udphdr)); + + if(IS_VXD_INTERFACE(priv)) { + ap_priv = GET_ROOT(priv); + } else { + DEBUG_INFO("Receive DHCP response but interface is not VXD\n"); + return ; + } + + //dhcp reply only + if(ap_priv && IS_DRV_OPEN(ap_priv) && (dhcph->op == 2)) { + unsigned char sta_ip[4]; + + memcpy(sta_ip,&dhcph->yiaddr,4); + DEBUG_INFO("[%s]External DHCP Server give IP[%d.%d.%d.%d]\n",priv->dev->name,sta_ip[0],sta_ip[1],sta_ip[2],sta_ip[3]); + if( send_arp_response(priv,&dhcph->siaddr,&dhcph->yiaddr,pskb->data+MACADDRLEN,&dhcph->chaddr[0]) ) + DEBUG_ERR("Send ARP failed\n"); + + return; + } +} +#endif //UNIVERSAL_REPEATER + +/* Do defered channel scan when, + 1.There is not any station connected to active AP interafce(Root AP/VAP) + 2.Scan is not requested by wscd + 3.Scan is not requested by Station mode without any VAP +*/ +int should_defer_ss(struct rtl8192cd_priv *priv) +{ + int ret=0; + + if(GET_ROOT(priv)->pmib->dot11OperationEntry.opmode & (WIFI_STATION_STATE|WIFI_ADHOC_STATE)) { + ret = 0; + } else { + if(get_ss_level(priv) < SS_LV_ROOTFUNCOFF) { + if((priv->site_survey->ss_channel == 100) && (priv->pmib->miscEntry.ss_delay)) { + ret=1; + DEBUG_INFO("%s Sitesurvey defered\n",priv->dev->name); + } + } + } + + if(priv->ss_req_ongoing == SSFROM_WSC) + ret = 0; + + return ret; +} + +#ifdef RTK_NL80211 +void copy_wps_ie(struct rtl8192cd_priv *priv, unsigned char *wps_ie, unsigned char mgmt_type) +{ + + /*T(1) L(1) V , wps_ie[1]==L => LEN = value of (L) + sizeof(T)+sizeof(L), cy wang note*/ + unsigned int wps_ie_len = (wps_ie[1] + 2); + + if(wps_ie_len > 256){ + NDEBUG2("WPS_IE length > 256 !! Can NOT copy !!\n"); + return; + } + + if(OPMODE & WIFI_AP_STATE) + priv->pmib->wscEntry.wsc_enable = 2; //Enable WPS for AP mode + else if(OPMODE & WIFI_STATION_STATE) + priv->pmib->wscEntry.wsc_enable = 1; + + if (mgmt_type == MGMT_BEACON) { + NDEBUG2("WSC:Set Beacon IE[%d]\n",wps_ie_len); + priv->pmib->wscEntry.beacon_ielen = wps_ie_len; + memcpy((void *)priv->pmib->wscEntry.beacon_ie, wps_ie, wps_ie_len); + } + else if (mgmt_type == MGMT_PROBERSP) { + NDEBUG2("WSC:Set Probe Rsp IE[%d]\n",wps_ie_len); + priv->pmib->wscEntry.probe_rsp_ielen = wps_ie_len; + memcpy((void *)priv->pmib->wscEntry.probe_rsp_ie, wps_ie, wps_ie_len); + } + else if (mgmt_type == MGMT_PROBEREQ) { + NDEBUG2("WSC:Set Probe Req IE[%d]\n",wps_ie_len); + priv->pmib->wscEntry.probe_req_ielen= wps_ie_len; + memcpy((void *)priv->pmib->wscEntry.probe_req_ie, wps_ie, wps_ie_len); + } + else if ((mgmt_type == MGMT_ASSOCRSP) || (mgmt_type == MGMT_ASSOCREQ)) { //wrt-wps-clnt + NDEBUG2("WSC:Set Assoc IE[%d]\n",wps_ie_len); + priv->pmib->wscEntry.assoc_ielen = wps_ie_len; + memcpy((void *)priv->pmib->wscEntry.assoc_ie, wps_ie, wps_ie_len); + } +} + +/** + * rtk_get_wps_ie - Search WPS IE from a series of IEs + * @in_ie: Address of IEs to search + * @in_len: Length limit from in_ie + * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie + * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE + * + * Returns: The address of the WPS IE found, or NULL + */ + +u8* rtk_get_wps_ie(u8 *in_ie, int in_len, u8 *wps_ie, int *wps_ielen) +{ + int cnt=0; + u8 eid=0; + u8 *wpsie_ptr=NULL; + + u8 WSC_OUI[4] = {0x00, 0x50, 0xf2, 0x04}; + + + if(wps_ielen){ + *wps_ielen = 0; + } + + if(!in_ie || in_len<=0) + return wpsie_ptr; + + while(cntdev->name); + else +#endif +#endif + strcpy(g_sc_ifname, priv->dev->name); + + rtk_sc_set_para(priv); + if(priv->pmib->dot11StationConfigEntry.sc_debug) + panic_printk("Start simple config now!\n"); + rtk_sc_clean_profile_value(); + +#if 0 //eric-sc +{ + if(priv->pmib->dot11StationConfigEntry.sc_debug) + panic_printk("\nFORCE ENABLE LDPC FOR SIMPLE CONFIG!!\n\n"); + RTL_W8(0x913, RTL_R8(0x913)|0x02); +} +#endif + priv->simple_config_could_fix = 0; + + rtk_sc_set_value(SC_FIX_CHANNEL, 0); + +#ifdef UNIVERSAL_REPEATER + if(IS_VXD_INTERFACE(priv)) + { + if(priv->simple_config_status == 0) + memcpy(priv->pmib->dot11Bss.bssid, null_mac, MACADDRLEN); + } +#endif + + if(priv->simple_config_status == 0) + priv->simple_config_status = 1; + + priv->pmib->dot11StationConfigEntry.sc_status = 1; + priv->pmib->dot11StationConfigEntry.sc_vxd_rescan_time = CHECK_VXD_SC_TIMEOUT; + + RTL_W32(RCR, RTL_R32(RCR) | RCR_AAP); //Accept Destination Address packets. + return 0; +} + +int rtk_sc_start_connect_target(struct rtl8192cd_priv *priv) +{ + int i=0; + if(priv->pmib->dot11StationConfigEntry.sc_fix_channel >= 0) + priv->pmib->dot11StationConfigEntry.sc_fix_channel = 0; + + if(priv->pmib->dot11StationConfigEntry.sc_reset_beacon_psk == 1) + { +#if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) + if (priv->pmib->dot1180211AuthEntry.dot11EnablePSK) { + watchdog_stop(priv); + psk_init(priv); + watchdog_resume(priv); + } +#endif + if( (priv->pmib->dot11StationConfigEntry.sc_sync_vxd_to_root == 1) && IS_VXD_INTERFACE(priv)) + { + watchdog_stop(GET_ROOT(priv)); + if (GET_ROOT(priv)->pmib->dot1180211AuthEntry.dot11EnablePSK) { + psk_init(GET_ROOT(priv)); + } + init_beacon(GET_ROOT(priv)); + watchdog_resume(GET_ROOT(priv)); + } + } + else + { +#ifdef UNIVERSAL_REPEATER + if(IS_VXD_INTERFACE(priv)) + { +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) + priv->pvap_priv[i]->pmib->dot11OperationEntry.keep_rsnie = 1; + } + } +#endif + } +#endif + RTL_W32(RCR, RTL_R32(RCR) & ~RCR_AAP); // Disable Accept Destination Address packets. +#ifdef CONFIG_RTL_8198C + /* rtl8192cd_ss_timer-->start_clnt_lookup-->rtk_sc_check_security-->rtk_sc_start_connect_target + * ss_timer call SMP_LOCK, so we should call unlock before close interface + */ + unsigned long flags; + SMP_UNLOCK(flags); +#endif + if(priv->pmib->dot11StationConfigEntry.sc_fix_channel > 0) + priv->pmib->dot11StationConfigEntry.sc_fix_channel = 0; + RTL_W8(TXPAUSE, 0xff); + rtl8192cd_close(priv->dev); +#ifdef UNIVERSAL_REPEATER + if( (priv->pmib->dot11StationConfigEntry.sc_sync_vxd_to_root == 1) && IS_VXD_INTERFACE(priv)) + { + GET_ROOT(priv)->pmib->dot11StationConfigEntry.sc_enabled = 0; + rtl8192cd_close(GET_ROOT(priv)->dev); + rtl8192cd_open(GET_ROOT(priv)->dev); + while(!netif_running(GET_ROOT(priv)->dev)) + delay_ms(10); + } +#endif + rtl8192cd_open(priv->dev); + RTL_W8(TXPAUSE, 0x00); +#ifdef CONFIG_RTL_8198C + SMP_LOCK(flags); +#endif + } + + rtk_sc_set_value(SC_PRIV_STATUS, 5); + rtk_sc_set_value(SC_STATUS, 5); + + return 0; +} +#ifdef UNIVERSAL_REPEATER +int rtk_sc_sync_vxd_to_root(struct rtl8192cd_priv * priv) +{ + if(IS_VXD_INTERFACE(priv)) + { + if(priv->pmib->dot11StationConfigEntry.sc_sync_vxd_to_root == 1) + { + GET_ROOT(priv)->pmib->dot1180211AuthEntry.dot11AuthAlgrthm = priv->pmib->dot1180211AuthEntry.dot11AuthAlgrthm; + GET_ROOT(priv)->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm = priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm; + GET_ROOT(priv)->pmib->dot1180211AuthEntry.dot11EnablePSK = priv->pmib->dot1180211AuthEntry.dot11EnablePSK; + GET_ROOT(priv)->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex = priv->pmib->dot1180211AuthEntry.dot11PrivacyKeyIndex; + GET_ROOT(priv)->pmib->dot118021xAuthEntry.dot118021xAlgrthm = priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm; + GET_ROOT(priv)->pmib->dot1180211AuthEntry.dot11WPA2Cipher = priv->pmib->dot1180211AuthEntry.dot11WPA2Cipher; + GET_ROOT(priv)->pmib->dot1180211AuthEntry.dot11WPACipher = priv->pmib->dot1180211AuthEntry.dot11WPACipher; + strcpy(GET_ROOT(priv)->pmib->dot1180211AuthEntry.dot11PassPhrase, priv->pmib->dot1180211AuthEntry.dot11PassPhrase); + strcpy(&(GET_ROOT(priv)->pmib->dot11DefaultKeysTable.keytype[0]), &(priv->pmib->dot11DefaultKeysTable.keytype[0])); + strcpy(GET_ROOT(priv)->pmib->dot11StationConfigEntry.dot11DesiredSSID, priv->pmib->dot11StationConfigEntry.dot11DesiredSSID); + strcpy(GET_ROOT(priv)->pmib->dot11StationConfigEntry.dot11SSIDtoScan, priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan); + GET_ROOT(priv)->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen= priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen; + GET_ROOT(priv)->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen= priv->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen; + } + } + + return 0; +} +#else +int rtk_sc_sync_vxd_to_root(struct rtl8192cd_priv * priv) +{ + return 0; +} + +#endif + +int rtk_sc_stop_simple_config(struct rtl8192cd_priv *priv) +{ + int i=0, ack_num=0; + int sc_security_type = priv->pmib->dot11StationConfigEntry.sc_security_type; + + if (OPMODE & WIFI_ASOC_STATE) + { + rtk_sc_set_value(SC_ENABLED, 0); + rtk_sc_set_value(SC_PRIV_STATUS, 0); + rtk_sc_set_value(SC_STATUS, 10+sc_security_type); + } + else + rtk_sc_set_value(SC_STATUS, -1); + + rtk_sc_set_value(SC_FIX_CHANNEL, 0); + return 0; +} + +struct net_device * rtl_get_dev_by_wlan_name(char *name) +{ +#if defined(__ECOS) + return rtl_getDevByName(name); +#else + return __dev_get_by_name(&init_net, name); +#endif +} + +int rtk_sc_set_value(unsigned int id, unsigned int value) +{ + struct net_device *dev; + dev=rtl_get_dev_by_wlan_name(g_sc_ifname); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + + switch(id) + { + case SC_ENABLED: + priv->pmib->dot11StationConfigEntry.sc_enabled = value; + break; + case SC_DURATION_TIME: + priv->pmib->dot11StationConfigEntry.sc_duration_time = value; + break; + case SC_GET_SYNC_TIME: + priv->pmib->dot11StationConfigEntry.sc_get_sync_time = value; + break; + case SC_GET_PROFILE_TIME: + priv->pmib->dot11StationConfigEntry.sc_get_profile_time = value; + break; + case SC_VXD_RESCAN_TIME: + priv->pmib->dot11StationConfigEntry.sc_vxd_rescan_time = value; + break; + case SC_PIN_ENABLED: + priv->pmib->dot11StationConfigEntry.sc_pin_enabled = value; + break; + case SC_STATUS: + priv->pmib->dot11StationConfigEntry.sc_status = value; + break; + case SC_DEBUG: + priv->pmib->dot11StationConfigEntry.sc_debug = value; + break; + case SC_CHECK_LINK_TIME: + priv->pmib->dot11StationConfigEntry.sc_check_link_time = value; + break; + case SC_SYNC_VXD_TO_ROOT: + priv->pmib->dot11StationConfigEntry.sc_sync_vxd_to_root = value; + break; + case SC_ACK_ROUND: + priv->pmib->dot11StationConfigEntry.sc_ack_round = value; + break; + case SC_CONTROL_IP: + priv->pmib->dot11StationConfigEntry.sc_control_ip = value; + break; + case SC_PRIV_STATUS: + priv->simple_config_status = value; + break; + case SC_CONFIG_TIME: + priv->simple_config_time = value; + break; + case SC_FIX_CHANNEL: + if(priv->pmib->dot11StationConfigEntry.sc_fix_channel >= 0){ + if ( (value > 0) && priv->simple_config_could_fix) + priv->pmib->dot11StationConfigEntry.sc_fix_channel = value; + else + priv->pmib->dot11StationConfigEntry.sc_fix_channel = value; + } + break; + case SC_FROM_TO_DS: + if(value == 2) + { + if(priv->pmib->dot11StationConfigEntry.sc_debug) + panic_printk("receive fromDS is 0, toDS is 1 packet\n"); + priv->pmib->dot11StationConfigEntry.sc_get_sync_time = 120; + } + else if(value == 1) + { + if(priv->pmib->dot11StationConfigEntry.sc_debug) + panic_printk("receive fromDS is 1, toDS is 0 packet\n"); + } +#if 0 + if(priv->site_survey->ss_channel > 14 && priv->pmib->dot11StationConfigEntry.sc_fix_channel>=0) + { + priv->pmib->dot11StationConfigEntry.sc_fix_channel = PHY_QueryRFReg(priv,RF92CD_PATH_A,0x18,0xff,1); + if(priv->pmib->dot11StationConfigEntry.sc_debug) + panic_printk("Simple Config 5G switch to remote AP channel(center) %d\n", priv->pmib->dot11StationConfigEntry.sc_fix_channel ); + } +#endif + break; + default: + break; + } + return 0; +} + +int rtk_sc_get_value(unsigned int id) +{ + struct net_device *dev; + int value=0; + dev=rtl_get_dev_by_wlan_name(g_sc_ifname); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + + switch(id) + { + case SC_ENABLED: + value = priv->pmib->dot11StationConfigEntry.sc_enabled; + break; + case SC_DURATION_TIME: + value = priv->pmib->dot11StationConfigEntry.sc_duration_time; + break; + case SC_GET_SYNC_TIME: + value = priv->pmib->dot11StationConfigEntry.sc_get_sync_time; + break; + case SC_GET_PROFILE_TIME: + value = priv->pmib->dot11StationConfigEntry.sc_get_profile_time; + break; + case SC_VXD_RESCAN_TIME: + value = priv->pmib->dot11StationConfigEntry.sc_vxd_rescan_time; + break; + case SC_PIN_ENABLED: + value = priv->pmib->dot11StationConfigEntry.sc_pin_enabled; + break; + case SC_STATUS: + value = priv->pmib->dot11StationConfigEntry.sc_status; + break; + case SC_DEBUG: + value = priv->pmib->dot11StationConfigEntry.sc_debug; + break; + case SC_CHECK_LINK_TIME: + value = priv->pmib->dot11StationConfigEntry.sc_check_link_time; + break; + case SC_SYNC_VXD_TO_ROOT: + value = priv->pmib->dot11StationConfigEntry.sc_sync_vxd_to_root; + break; + case SC_ACK_ROUND: + value = priv->pmib->dot11StationConfigEntry.sc_ack_round; + break; + case SC_CONTROL_IP: + value = priv->pmib->dot11StationConfigEntry.sc_control_ip; + break; + case SC_PRIV_STATUS: + value = priv->simple_config_status; + break; + case SC_CONFIG_TIME: + value = priv->simple_config_time; + break; + case SC_CHECK_LEVEL: + value = priv->pmib->dot11StationConfigEntry.sc_check_level; + break; + case SC_IGNORE_OVERLAP: + value = priv->pmib->dot11StationConfigEntry.sc_ignore_overlap; + break; + case SC_FIX_CHANNEL: + value = priv->pmib->dot11StationConfigEntry.sc_fix_channel; + default: + break; + } + return value; +} + +int rtk_sc_set_string_value(unsigned int id, unsigned char *value) +{ + struct net_device *dev; + int i=0; + dev=rtl_get_dev_by_wlan_name(g_sc_ifname); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + switch(id) + { + case SC_PIN: + strcpy(priv->pmib->dot11StationConfigEntry.sc_pin, value); + break; + case SC_DEFAULT_PIN: + strcpy(priv->pmib->dot11StationConfigEntry.sc_default_pin, value); + break; + case SC_PASSWORD: + strcpy(priv->pmib->dot11StationConfigEntry.sc_passwd, value); + break; + case SC_DEVICE_NAME: + strcpy(priv->pmib->dot11StationConfigEntry.sc_device_name, value); + break; + case SC_DEVICE_TYPE: + strcpy(priv->pmib->dot11StationConfigEntry.sc_device_type, value); + break; + case SC_SSID: + strcpy(priv->pmib->dot11StationConfigEntry.dot11DesiredSSID, value); + strcpy(priv->pmib->dot11StationConfigEntry.dot11SSIDtoScan, value); + priv->pmib->dot11StationConfigEntry.dot11DesiredSSIDLen= strlen(value); + priv->pmib->dot11StationConfigEntry.dot11SSIDtoScanLen= strlen(value); + break; + case SC_BSSID: + for(i=0; i<6; i++) + { + priv->pmib->dot11StationConfigEntry.dot11DesiredBssid[i] = value[i]; + } + break; + default: + panic_printk("RTL Simple Config don't support this mib setting now!\n"); + } + return 0; +} + +int rtk_sc_get_string_value(unsigned int id, unsigned char *value) +{ + struct net_device *dev; + dev=rtl_get_dev_by_wlan_name(g_sc_ifname); + struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); + + switch(id) + { + case SC_PIN: + strcpy(value, priv->pmib->dot11StationConfigEntry.sc_pin); + break; + case SC_DEFAULT_PIN: + strcpy(value, priv->pmib->dot11StationConfigEntry.sc_default_pin); + break; + case SC_PASSWORD: + strcpy(value, priv->pmib->dot11StationConfigEntry.sc_passwd); + break; + case SC_DEVICE_NAME: + strcpy(value, priv->pmib->dot11StationConfigEntry.sc_device_name); + break; + case SC_DEVICE_TYPE: + strcpy(value, priv->pmib->dot11StationConfigEntry.sc_device_type); + break; + default: + panic_printk("RTL Simple Config don't support this mib setting now!\n"); + break; + } + return 0; +} + +int set_wep_key(struct rtl8192cd_priv *priv, int type) +{ + int i, length; + unsigned char value; + unsigned char wep_key[26]={0}; + if(type == 0) + length=10; + else if(type == 1) + length=26; + for(i=0; ipmib->dot11StationConfigEntry.sc_passwd[i]; + if((value >=0x30) && (value <=0x39)) + value -= 0x30; + else if((value >= 'a')&&(value <= 'z')) + value -= 0x57; + else if((value >= 'A')&&(value <= 'Z')) + value -= 0x37; + value &= 0xf; + if(i%2 == 0) + wep_key[i/2] = value<<4; + else + wep_key[i/2] += value; + } + memcpy(&(GET_MIB(priv)->dot11DefaultKeysTable.keytype[0]), wep_key, length/2); +} + +int rtk_sc_check_security(struct rtl8192cd_priv * priv,struct bss_desc * bss) +{ + int length=0, i=0; + int status = rtk_sc_get_value(SC_STATUS); + length = strlen(priv->pmib->dot11StationConfigEntry.sc_passwd); + if ((bss->capability&BIT(4)) == 0) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11AuthAlgrthm = 0; + GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyAlgrthm=_NO_PRIVACY_; + GET_MIB(priv)->dot1180211AuthEntry.dot11EnablePSK = 0; + rtk_sc_set_value(SC_CHECK_LINK_TIME, 2); + GET_MIB(priv)->dot11StationConfigEntry.sc_security_type= 0; + GET_MIB(priv)->dot11RsnIE.rsnielen = 0; + GET_MIB(priv)->dot118021xAuthEntry.dot118021xAlgrthm= 0; + } + else if((bss->capability&BIT(4))) + { + if(bss->t_stamp[0] == 0) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11EnablePSK = 0; + if((length == 5) || (length == 10)) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_40_PRIVACY_; + if(length == 5) + { + memcpy(&(GET_MIB(priv)->dot11DefaultKeysTable.keytype[0]), priv->pmib->dot11StationConfigEntry.sc_passwd, 5); + priv->pmib->dot11StationConfigEntry.sc_security_type= 1; + } + else if(length == 10) + { + set_wep_key(priv, 0); + priv->pmib->dot11StationConfigEntry.sc_security_type= 2; + } + GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyKeyIndex = 0; + } + else if((length == 13) || (length == 26)) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyAlgrthm = _WEP_104_PRIVACY_; + if(length == 13) + { + memcpy(&(GET_MIB(priv)->dot11DefaultKeysTable.keytype[0]), priv->pmib->dot11StationConfigEntry.sc_passwd, 13); + priv->pmib->dot11StationConfigEntry.sc_security_type= 3; + } + else + { + set_wep_key(priv, 1); + priv->pmib->dot11StationConfigEntry.sc_security_type= 4; + } + GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyKeyIndex = 0; + } + GET_MIB(priv)->dot11RsnIE.rsnielen = 0; + GET_MIB(priv)->dot118021xAuthEntry.dot118021xAlgrthm= 0; + rtk_sc_set_value(SC_CHECK_LINK_TIME, 2); + } + else + { + GET_MIB(priv)->dot1180211AuthEntry.dot11AuthAlgrthm = 2; + GET_MIB(priv)->dot1180211AuthEntry.dot11PrivacyAlgrthm = 2; + strcpy((char *)GET_MIB(priv)->dot1180211AuthEntry.dot11PassPhrase, priv->pmib->dot11StationConfigEntry.sc_passwd); + if(bss->t_stamp[0] & 0xffff0000) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11EnablePSK = 2; + if(((bss->t_stamp[0] & 0xf0000000) >> 28) == 0x4) + { + GET_MIB(priv)->dot118021xAuthEntry.dot118021xAlgrthm = 1; + } + if(((bss->t_stamp[0] & 0x0f000000) >> 24) == 0x5) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11WPA2Cipher = 8; + priv->pmib->dot11StationConfigEntry.sc_security_type= 5; + } + else if(((bss->t_stamp[0] & 0x0f000000) >> 24) == 0x4) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11WPA2Cipher = 8; + priv->pmib->dot11StationConfigEntry.sc_security_type= 5; + } + else if(((bss->t_stamp[0] & 0x0f000000) >> 24) == 0x1) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11WPA2Cipher = 2; + priv->pmib->dot11StationConfigEntry.sc_security_type= 6; + } + } + else if(bss->t_stamp[0] & 0x0000ffff) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11EnablePSK = 1; + if(((bss->t_stamp[0] & 0x0000f000) >> 12) == 0x4) + { + GET_MIB(priv)->dot118021xAuthEntry.dot118021xAlgrthm = 0; + } + if(((bss->t_stamp[0] & 0x00000f00) >> 8) == 0x5) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11WPACipher = 8; + priv->pmib->dot11StationConfigEntry.sc_security_type= 7; + } + else if(((bss->t_stamp[0] & 0x00000f00) >> 8) == 0x4) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11WPACipher = 8; + priv->pmib->dot11StationConfigEntry.sc_security_type= 7; + } + else if(((bss->t_stamp[0] & 0x00000f00) >> 8) == 0x1) + { + GET_MIB(priv)->dot1180211AuthEntry.dot11WPACipher = 2; + priv->pmib->dot11StationConfigEntry.sc_security_type= 8; + } + } + } + } + if(status == 3) + { + rtk_sc_set_value(SC_PRIV_STATUS, 4); + rtk_sc_set_value(SC_STATUS, 4); + } + rtk_sc_sync_vxd_to_root(priv); + rtk_sc_set_value(SC_CONFIG_TIME, 0); + rtk_sc_start_connect_target(priv); + return 0; +} + +int rtk_sc_get_magic(unsigned int *magic, unsigned int len) +{ + int i=0; + unsigned int magic_num[32] = {60, 62, 68, 70, 76, 78, 80, 82}; + for(i=0; ipmib->dot11StationConfigEntry.sc_enabled == 1 && priv->simple_config_could_fix == 1) { + + if(priv->pmib->dot11StationConfigEntry.sc_fix_channel > 0) + return 1; + else if((priv->pmib->dot11StationConfigEntry.sc_fix_channel < 0) + && (priv->pmib->dot11StationConfigEntry.sc_status == 2 || priv->pmib->dot11StationConfigEntry.sc_status == 3) + ) + return 1; + } + +#ifdef UNIVERSAL_REPEATER + if(IS_DRV_OPEN(GET_VXD_PRIV(priv_root))&& + GET_VXD_PRIV(priv_root)->pmib->dot11StationConfigEntry.sc_enabled && priv->simple_config_could_fix == 1) { + + if(GET_VXD_PRIV(priv_root)->pmib->dot11StationConfigEntry.sc_fix_channel > 0) + return 1; + else if((GET_VXD_PRIV(priv_root)->pmib->dot11StationConfigEntry.sc_fix_channel < 0) && + (GET_VXD_PRIV(priv_root)->pmib->dot11StationConfigEntry.sc_status == 2 + || GET_VXD_PRIV(priv_root)->pmib->dot11StationConfigEntry.sc_status == 3) + ) + return 1; + } +#endif + + return 0; +} + + +int rtk_sc_get_scan_offset(struct rtl8192cd_priv * priv, int channel, int bw) +{ + int scan_offset = HT_2NDCH_OFFSET_DONTCARE; + + + + if(bw) { + + if(channel >= 36) { + + if((channel>144) ? ((channel-1)%8) : (channel%8)) + scan_offset = HT_2NDCH_OFFSET_ABOVE; + else + scan_offset = HT_2NDCH_OFFSET_BELOW; + } else { + + if(channel < 5) + scan_offset = HT_2NDCH_OFFSET_ABOVE; + else if(channel > 9) + scan_offset = HT_2NDCH_OFFSET_BELOW; + else { + + if(GET_ROOT(priv)->pshare->offset_2nd_chan == HT_2NDCH_OFFSET_ABOVE) + scan_offset = HT_2NDCH_OFFSET_BELOW; + else + scan_offset = HT_2NDCH_OFFSET_ABOVE; + } + } + } + + return scan_offset; +} + + +int rtk_sc_during_simple_config_scan(struct rtl8192cd_priv * priv) +{ + struct rtl8192cd_priv * priv_root = GET_ROOT(priv); + + if(priv->pmib->dot11StationConfigEntry.sc_enabled == 1) { + + if(priv->simple_config_status == 1) + return 1; + } + +#ifdef UNIVERSAL_REPEATER + if(IS_DRV_OPEN(GET_VXD_PRIV(priv_root))&& + GET_VXD_PRIV(priv_root)->pmib->dot11StationConfigEntry.sc_enabled) { + + if(GET_VXD_PRIV(priv_root)->simple_config_status == 1) + return 1; + } +#endif + + return 0; +} + + +#endif diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_util.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_util.h new file mode 100755 index 000000000..876262343 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192cd_util.h @@ -0,0 +1,1787 @@ +/* + * Header file defines some common inline funtions + * + * $Id: 8192cd_util.h,v 1.10.2.4 2010/11/09 09:10:03 button Exp $ + * + * Copyright (c) 2009 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192CD_UTIL_H_ +#define _8192CD_UTIL_H_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./wifi.h" +#include "./8192cd_hw.h" + +#if !defined(NOT_RTK_BSP) +#if defined(__LINUX_2_6__) +//#include +#else +#ifndef __ECOS + #include +#endif +#endif +#endif + +#ifdef CONFIG_RTK_MESH +#include "../mesh_ext/mesh_util.h" +#endif + +#ifdef CONFIG_USB_HCI +#include "./usb/8188eu/8192cd_usb.h" +#endif + +#ifdef CONFIG_SDIO_HCI +#ifdef CONFIG_RTL_88E_SUPPORT +#include "./sdio/8189es/8188e_sdio.h" +#endif +#ifdef CONFIG_WLAN_HAL_8192EE +#include "./sdio/8192es/8192e_sdio.h" +#endif +#endif + +#ifdef GREEN_HILL +#define SAVE_INT_AND_CLI(x) { x = save_and_cli(); } +#define RESTORE_INT(x) restore_flags(x) +#define SMP_LOCK(__x__) +#define SMP_UNLOCK(__x__) +#define SMP_TRY_LOCK(__x__,__y__) +#define SMP_LOCK_XMIT(__x__) +#define SMP_UNLOCK_XMIT(__x__) +#define SMP_LOCK_ACL(__x__) +#define SMP_UNLOCK_ACL(__x__) +#define SMP_LOCK_HASH_LIST(__x__) +#define SMP_UNLOCK_HASH_LIST(__x__) +#define SMP_LOCK_ASOC_LIST(__x__) +#define SMP_UNLOCK_ASOC_LIST(__x__) +#define SMP_LOCK_SLEEP_LIST(__x__) +#define SMP_UNLOCK_SLEEP_LIST(__x__) +#define SMP_LOCK_MESH_ACL(__x__) +#define SMP_UNLOCK_MESH_ACL(__x__) +#define SMP_LOCK_MESH_MP_HDR(__X__) +#define SMP_UNLOCK_MESH_MP_HDR(__X__) +#define SMP_LOCK_SKB(__x__) +#define SMP_UNLOCK_SKB(__x__) +#define SMP_LOCK_BUF(__x__) +#define SMP_UNLOCK_BUF(__x__) +#define SMP_LOCK_RECV(__x__) +#define SMP_UNLOCK_RECV(__x__) +#define SMP_LOCK_RX_DATA(__x__) +#define SMP_UNLOCK_RX_DATA(__x__) +#define SMP_LOCK_RX_MGT(__x__) +#define SMP_UNLOCK_RX_MGT(__x__) +#define SMP_LOCK_RX_CTRL(__x__) +#define SMP_UNLOCK_RX_CTRL(__x__) +#define SMP_LOCK_REORDER_CTRL(__x__) +#define SMP_UNLOCK_REORDER_CTRL(__x__) +#define DEFRAG_LOCK(__x__) { x = save_and_cli(); } +#define DEFRAG_UNLOCK(__x__) restore_flags(x) +#define SMP_LOCK_PSK_RESEND(__x__) +#define SMP_UNLOCK_PSK_RESEND(__x__) +#define SMP_LOCK_PSK_GKREKEY(__x__) +#define SMP_UNLOCK_PSK_GKREKEY(__x__) +#define SMP_LOCK_ASSERT() + +#elif defined(SMP_SYNC) //Add these spin locks to avoid deadlock under SMP platforms. +#define SAVE_INT_AND_CLI(__x__) do { } while (0) +#define RESTORE_INT(__x__) do { } while (0) +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#define SMP_LOCK(__x__) do { } while (0) +#define SMP_UNLOCK(__x__) do { } while (0) +#define SMP_TRY_LOCK(__x__,__y__) do { } while (0) +#define SMP_LOCK_ASSERT() do { } while (0) +#define SMP_LOCK_XMIT(__x__) do { } while (0) +#define SMP_UNLOCK_XMIT(__x__) do { } while (0) +#define SMP_LOCK_MBSSID(__x__) _enter_critical_mutex(&priv->pshare->mbssid_lock, (__x__)) +#define SMP_UNLOCK_MBSSID(__x__) _exit_critical_mutex(&priv->pshare->mbssid_lock, (__x__)) +#define SMP_LOCK_ACL(__x__) do { spin_lock(&priv->wlan_acl_list_lock); (void)(__x__); } while (0) +#define SMP_UNLOCK_ACL(__x__) do { spin_unlock(&priv->wlan_acl_list_lock); (void)(__x__); } while (0) +#ifdef __ECOS +#define SMP_LOCK_HASH_LIST(__x__) _enter_critical_mutex(&priv->hash_list_lock, (__x__)) +#define SMP_UNLOCK_HASH_LIST(__x__) _exit_critical_mutex(&priv->hash_list_lock, (__x__)) +#define SMP_LOCK_ASOC_LIST(__x__) _enter_critical_mutex(&priv->asoc_list_lock, (__x__)) +#define SMP_UNLOCK_ASOC_LIST(__x__) _exit_critical_mutex(&priv->asoc_list_lock, (__x__)) +#define SMP_LOCK_AUTH_LIST(__x__) _enter_critical_mutex(&priv->auth_list_lock, (__x__)) +#define SMP_UNLOCK_AUTH_LIST(__x__) _exit_critical_mutex(&priv->auth_list_lock, (__x__)) +#define SMP_LOCK_SLEEP_LIST(__x__) _enter_critical_mutex(&priv->sleep_list_lock, (__x__)) +#define SMP_UNLOCK_SLEEP_LIST(__x__) _exit_critical_mutex(&priv->sleep_list_lock, (__x__)) +#define SMP_LOCK_WAKEUP_LIST(__x__) _enter_critical_mutex(&priv->wakeup_list_lock, (__x__)) +#define SMP_UNLOCK_WAKEUP_LIST(__x__) _exit_critical_mutex(&priv->wakeup_list_lock, (__x__)) +#else +#define SMP_LOCK_HASH_LIST(__x__) do { spin_lock_bh(&priv->hash_list_lock); (void)(__x__); } while (0) +#define SMP_UNLOCK_HASH_LIST(__x__) do { spin_unlock_bh(&priv->hash_list_lock); (void)(__x__); } while (0) +#define SMP_LOCK_ASOC_LIST(__x__) do { spin_lock_bh(&priv->asoc_list_lock); (void)(__x__); } while (0) +#define SMP_UNLOCK_ASOC_LIST(__x__) do { spin_unlock_bh(&priv->asoc_list_lock); (void)(__x__); } while (0) +#define SMP_LOCK_AUTH_LIST(__x__) do { spin_lock_bh(&priv->auth_list_lock); (void)(__x__); } while (0) +#define SMP_UNLOCK_AUTH_LIST(__x__) do { spin_unlock_bh(&priv->auth_list_lock); (void)(__x__); } while (0) +#define SMP_LOCK_SLEEP_LIST(__x__) do { spin_lock_bh(&priv->sleep_list_lock); (void)(__x__); } while (0) +#define SMP_UNLOCK_SLEEP_LIST(__x__) do { spin_unlock_bh(&priv->sleep_list_lock); (void)(__x__); } while (0) +#define SMP_LOCK_WAKEUP_LIST(__x__) do { spin_lock_bh(&priv->wakeup_list_lock); (void)(__x__); } while (0) +#define SMP_UNLOCK_WAKEUP_LIST(__x__) do { spin_unlock_bh(&priv->wakeup_list_lock); (void)(__x__); } while (0) +#endif +#define SMP_LOCK_MESH_MP_HDR(__X__) do { spin_lock_bh(&priv->mesh_mp_hdr_lock); (void)(__x__); } while (0) +#define SMP_UNLOCK_MESH_MP_HDR(__X__) do { spin_unlock_bh(&priv->mesh_mp_hdr_lock); (void)(__x__); } while (0) +#define SMP_LOCK_MESH_ACL(__x__) do { spin_lock(&priv->mesh_acl_list_lock); (void)(__x__); } while (0) +#define SMP_UNLOCK_MESH_ACL(__x__) do { spin_unlock(&priv->mesh_acl_list_lock); (void)(__x__); } while (0) +#elif defined(CONFIG_PCI_HCI) +#define SMP_LOCK(__x__) \ + do { \ + if(priv->pshare->lock_owner!=smp_processor_id()) \ + spin_lock_irqsave(&priv->pshare->lock, priv->pshare->lock_flags); \ + else {\ + panic_printk("[%s %d] recursion detection, caller=%p\n",__FUNCTION__,__LINE__,__builtin_return_address(0)); \ + panic_printk("Previous Lock Function is %s\n",priv->pshare->lock_func); \ + } \ + strcpy(priv->pshare->lock_func, __FUNCTION__);\ + priv->pshare->lock_owner=smp_processor_id();\ + }while(0) +#define SMP_UNLOCK(__x__) do {priv->pshare->lock_owner=-1;spin_unlock_irqrestore(&priv->pshare->lock, priv->pshare->lock_flags);}while(0) +#define SMP_TRY_LOCK(__x__,__y__) \ + do { \ + if(priv->pshare->lock_owner != smp_processor_id()) { \ + SMP_LOCK(__x__); \ + __y__ = 1; \ + } else \ + __y__ = 0; \ + } while(0) +#define SMP_LOCK_ASSERT() \ + do { \ + if(priv->pshare->lock_owner!=smp_processor_id()) { \ + panic_printk("ERROR: Without obtaining SMP_LOCK(). Please calling SMP_LOCK() before entering into %s()\n\n\n",__FUNCTION__); \ + return; \ + } \ + }while(0) + +//#define SMP_LOCK_XMIT(__x__) spin_lock_irqsave(&priv->pshare->lock_xmit, (__x__)) +//#define SMP_UNLOCK_XMIT(__x__) spin_unlock_irqrestore(&priv->pshare->lock_xmit, (__x__)) +//#define SMP_LOCK_XMIT(__x__) spin_lock_irqsave(&priv->pshare->lock_xmit, priv->pshare->lock_xmit_flags) +//#define SMP_UNLOCK_XMIT(__x__) spin_unlock_irqrestore(&priv->pshare->lock_xmit, priv->pshare->lock_xmit_flags) +#define SMP_LOCK_XMIT(__x__) \ + do { \ + if(priv->pshare->lock_xmit_owner!=smp_processor_id()) \ + spin_lock_irqsave(&priv->pshare->lock_xmit, priv->pshare->lock_xmit_flags); \ + else {\ + panic_printk("[%s %d] recursion detection, caller=%p\n",__FUNCTION__,__LINE__,__builtin_return_address(0)); \ + panic_printk("Previous Lock Function is %s\n",priv->pshare->lock_xmit_func); \ + }\ + strcpy(priv->pshare->lock_xmit_func, __FUNCTION__);\ + priv->pshare->lock_xmit_owner=smp_processor_id();\ + }while(0) +#define SMP_UNLOCK_XMIT(__x__) do {priv->pshare->lock_xmit_owner=-1;spin_unlock_irqrestore(&priv->pshare->lock_xmit, priv->pshare->lock_xmit_flags);}while(0) +#define SMP_TRY_LOCK_XMIT(__x__,__y__) \ + do { \ + if(priv->pshare->lock_xmit_owner != smp_processor_id()) { \ + SMP_LOCK_XMIT(__x__); \ + __y__ = 1; \ + } else \ + __y__ = 0; \ + } while(0) + +#define SMP_LOCK_HASH_LIST(__x__) spin_lock_irqsave(&priv->hash_list_lock, (__x__)) +#define SMP_UNLOCK_HASH_LIST(__x__) spin_unlock_irqrestore(&priv->hash_list_lock, (__x__)) + + +#define SMP_LOCK_ACL(__x__) +#define SMP_UNLOCK_ACL(__x__) +#define SMP_LOCK_ASOC_LIST(__x__) +#define SMP_UNLOCK_ASOC_LIST(__x__) +#define SMP_LOCK_SLEEP_LIST(__x__) +#define SMP_UNLOCK_SLEEP_LIST(__x__) +#define SMP_LOCK_MESH_MP_HDR(__X__) +#define SMP_UNLOCK_MESH_MP_HDR(__X__) +#define SMP_LOCK_MESH_ACL(__x__) +#define SMP_UNLOCK_MESH_ACL(__x__) +#endif + +#define isEqualMACAddr(addr1,addr2) ((((unsigned long)(addr1)|(unsigned long)(addr2))&0x01) ? \ + ((*(unsigned char*)(addr1) ^ (*(unsigned char*)(addr2))) | (*(unsigned char*)(addr1+1) ^ (*(unsigned char*)(addr2+1))) | (*(unsigned char*)(addr1+2) ^ (*(unsigned char*)(addr2+2)))|\ + (*(unsigned char*)(addr1+3) ^ (*(unsigned char*)(addr2+3))) | (*(unsigned char*)(addr1+4) ^ (*(unsigned char*)(addr2+4))) | (*(unsigned char*)(addr1+5) ^ (*(unsigned char*)(addr2+5))))==0 :\ + ((*(unsigned short*)(addr1) ^ (*(unsigned short*)(addr2))) | (*(unsigned short*)(addr1+2) ^ (*(unsigned short*)(addr2+2))) | (*(unsigned short*)(addr1+4) ^ (*(unsigned short*)(addr2+4))))==0) + +#ifdef __KERNEL__ +#define SMP_LOCK_SKB(__x__) spin_lock_irqsave(&priv->pshare->lock_skb, (__x__)) +#define SMP_UNLOCK_SKB(__x__) spin_unlock_irqrestore(&priv->pshare->lock_skb, (__x__)) +#if defined(CONFIG_SDIO_HCI) +#define SMP_LOCK_BUF(__x__) do { spin_lock_bh(&priv->pshare->lock_buf); (void)(__x__); } while (0) +#define SMP_UNLOCK_BUF(__x__) do { spin_unlock_bh(&priv->pshare->lock_buf); (void)(__x__); } while (0) +#elif defined(CONFIG_PCI_HCI) || defined(CONFIG_USB_HCI) +#define SMP_LOCK_BUF(__x__) spin_lock_irqsave(&priv->pshare->lock_buf, (__x__)) +#define SMP_UNLOCK_BUF(__x__) spin_unlock_irqrestore(&priv->pshare->lock_buf, (__x__)) +#endif +#define SMP_LOCK_RECV(__x__) \ + do { \ + if(priv->pshare->lock_recv_owner!=smp_processor_id()) \ + spin_lock_irqsave(&priv->pshare->lock_recv, (__x__)); \ + else \ + panic_printk("[%s %d] recursion detection\n",__FUNCTION__,__LINE__); \ + priv->pshare->lock_recv_owner=smp_processor_id();\ + }while(0) +#define SMP_UNLOCK_RECV(__x__) do {priv->pshare->lock_recv_owner=-1;spin_unlock_irqrestore(&priv->pshare->lock_recv, (__x__));}while(0) +#define SMP_TRY_LOCK_RECV(__x__,__y__) \ + do { \ + if(priv->pshare->lock_recv_owner != smp_processor_id()) { \ + SMP_LOCK_RECV(__x__); \ + __y__ = 1; \ + } else \ + __y__ = 0; \ + } while(0) + +//#define SMP_LOCK_RECV(__x__) spin_lock_irqsave(&priv->pshare->lock_recv, (__x__)) +//#define SMP_UNLOCK_RECV(__x__) spin_unlock_irqrestore(&priv->pshare->lock_recv, (__x__)) +#define SMP_LOCK_RX_DATA(__x__) spin_lock_irqsave(&priv->rx_datalist_lock, (__x__)) +#define SMP_UNLOCK_RX_DATA(__x__) spin_unlock_irqrestore(&priv->rx_datalist_lock, (__x__)) +#define SMP_LOCK_RX_MGT(__x__) spin_lock_irqsave(&priv->rx_mgtlist_lock, (__x__)) +#define SMP_UNLOCK_RX_MGT(__x__) spin_unlock_irqrestore(&priv->rx_mgtlist_lock, (__x__)) +#define SMP_LOCK_RX_CTRL(__x__) spin_lock_irqsave(&priv->rx_ctrllist_lock, (__x__)) +#define SMP_UNLOCK_RX_CTRL(__x__) spin_unlock_irqrestore(&priv->rx_ctrllist_lock, (__x__)) + +#ifdef RTK_NL80211 +#define SMP_LOCK_CFG80211(__x__) spin_lock_irqsave(&priv->cfg80211_lock, (__x__)) +#define SMP_UNLOCK_CFG80211(__x__) spin_unlock_irqrestore(&priv->cfg80211_lock, (__x__)) +#endif +#endif + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#ifdef __ECOS +#define SMP_LOCK_BUF(__x__) _enter_critical_mutex(&(priv->pshare->lock_buf), (__x__)) +#define SMP_UNLOCK_BUF(__x__) _exit_critical_mutex(&(priv->pshare->lock_buf), (__x__)) +#define SMP_LOCK_REORDER_CTRL(__x__) _enter_critical_mutex(&priv->rc_packet_q_lock, (__x__)) +#define SMP_UNLOCK_REORDER_CTRL(__x__) _exit_critical_mutex(&priv->rc_packet_q_lock, (__x__)) +#else +#define SMP_LOCK_REORDER_CTRL(__x__) do { spin_lock_bh(&priv->rc_packet_q_lock); (void)(__x__); } while (0) +#define SMP_UNLOCK_REORDER_CTRL(__x__) do { spin_unlock_bh(&priv->rc_packet_q_lock); (void)(__x__); } while (0) +#endif +#define DEFRAG_LOCK(__x__) do { spin_lock_bh(&priv->defrag_lock); (void)(__x__); } while (0) +#define DEFRAG_UNLOCK(__x__) do { spin_unlock_bh(&priv->defrag_lock); (void)(__x__); } while (0) +#define SMP_LOCK_PSK_RESEND(__x__) do { } while (0) +#define SMP_UNLOCK_PSK_RESEND(__x__) do { } while (0) +#define SMP_LOCK_PSK_GKREKEY(__x__) do { } while (0) +#define SMP_UNLOCK_PSK_GKREKEY(__x__) do { } while (0) +#elif defined(CONFIG_PCI_HCI) +#define SMP_LOCK_REORDER_CTRL(__x__) spin_lock_irqsave(&priv->rc_packet_q_lock, (__x__)) +#define SMP_UNLOCK_REORDER_CTRL(__x__) spin_unlock_irqrestore(&priv->rc_packet_q_lock, (__x__)) +#define DEFRAG_LOCK(__x__) spin_lock_irqsave(&priv->defrag_lock, (__x__)) +#define DEFRAG_UNLOCK(__x__) spin_unlock_irqrestore(&priv->defrag_lock, (__x__)) +#define SMP_LOCK_PSK_RESEND(__x__) spin_lock_irqsave(&priv->psk_resend_lock, (__x__)) +#define SMP_UNLOCK_PSK_RESEND(__x__) spin_unlock_irqrestore(&priv->psk_resend_lock, (__x__)) +#define SMP_LOCK_PSK_GKREKEY(__x__) spin_lock_irqsave(&priv->psk_gkrekey_lock, (__x__)) +#define SMP_UNLOCK_PSK_GKREKEY(__x__) spin_unlock_irqrestore(&priv->psk_gkrekey_lock, (__x__)) +#endif + +#else +#define SAVE_INT_AND_CLI(__x__) spin_lock_irqsave(&priv->pshare->lock, (__x__)) +#define RESTORE_INT(__x__) spin_unlock_irqrestore(&priv->pshare->lock, (__x__)) +#ifndef __ECOS +#define SMP_LOCK(__x__) +#define SMP_UNLOCK(__x__) +#endif +#define SMP_LOCK_XMIT(__x__) +#define SMP_UNLOCK_XMIT(__x__) +#define SMP_LOCK_ACL(__x__) +#define SMP_UNLOCK_ACL(__x__) +#define SMP_LOCK_HASH_LIST(__x__) +#define SMP_UNLOCK_HASH_LIST(__x__) +#define SMP_LOCK_ASOC_LIST(__x__) +#define SMP_UNLOCK_ASOC_LIST(__x__) +#define SMP_LOCK_SLEEP_LIST(__x__) +#define SMP_UNLOCK_SLEEP_LIST(__x__) +#define SMP_LOCK_MESH_ACL(__x__) +#define SMP_UNLOCK_MESH_ACL(__x__) +#define SMP_LOCK_MESH_MP_HDR(__X__) +#define SMP_UNLOCK_MESH_MP_HDR(__X__) +#define SMP_LOCK_SKB(__x__) +#define SMP_UNLOCK_SKB(__x__) +#define SMP_LOCK_BUF(__x__) +#define SMP_UNLOCK_BUF(__x__) +#define SMP_LOCK_RECV(__x__) +#define SMP_UNLOCK_RECV(__x__) +#define SMP_LOCK_RX_DATA(__x__) +#define SMP_UNLOCK_RX_DATA(__x__) +#define SMP_LOCK_RX_MGT(__x__) +#define SMP_UNLOCK_RX_MGT(__x__) +#define SMP_LOCK_RX_CTRL(__x__) +#define SMP_UNLOCK_RX_CTRL(__x__) +#define SMP_LOCK_REORDER_CTRL(__x__) +#define SMP_UNLOCK_REORDER_CTRL(__x__) +#define DEFRAG_LOCK(__x__) spin_lock_irqsave(&priv->defrag_lock, (__x__)) +#define DEFRAG_UNLOCK(__x__) spin_unlock_irqrestore(&priv->defrag_lock, (__x__)) +#define SMP_LOCK_PSK_RESEND(__x__) +#define SMP_UNLOCK_PSK_RESEND(__x__) +#define SMP_LOCK_PSK_GKREKEY(__x__) +#define SMP_UNLOCK_PSK_GKREKEY(__x__) +#define SMP_LOCK_ASSERT() +#ifdef RTK_NL80211 +#define SMP_LOCK_CFG80211(__x__) +#define SMP_UNLOCK_CFG80211(__x__) +#endif +#endif + +#ifdef __LINUX_2_6__ +#ifdef __MIPSEB__ +#ifdef virt_to_bus + #undef virt_to_bus + #define virt_to_bus CPHYSADDR +#endif +#endif +#endif + +#define REMAP_AID(p) p->remapped_aid + + +/*NOTE if 1.5 seconds should be RTL_SECONDS_TO_JIFFIES(15)/10 + *RTL_MILISECONDS_TO_JIFFIES shoud consider the HZ value + *for example HZ=100, x should large than 10 + */ +#define RTL_SECONDS_TO_JIFFIES(x) ((x)*HZ) +#define RTL_MILISECONDS_TO_JIFFIES(x) (((x)*HZ-1)/1000+1) +#define RTL_10MILISECONDS_TO_JIFFIES(x) (((x)*HZ)/100) +#define RTL_JIFFIES_TO_MICROSECOND ((1000*1000)/HZ) +#define RTL_JIFFIES_TO_MILISECONDS(x) (((x)*1000)/HZ) + +#define CHIP_VER_92X_SERIES(priv) ( (priv->pshare->version_id&0xf) < 3) + +#define GET_CHIP_VER(priv) ((priv->pshare->version_id&VERSION_MASK)) +//#if defined(CONFIG_RTL_92C_SUPPORT) || defined(SUPPORT_RTL8188E_TC) +#define IS_TEST_CHIP(priv) ((priv->pshare->version_id&0x100)) +//#endif + +#if defined(USE_OUT_SRC) +#define IS_OUTSRC_CHIP(priv) (priv->pshare->use_outsrc) +#endif + +#define IS_HAL_CHIP(priv) (priv->pshare->use_hal) + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#undef GET_CHIP_VER +#if defined(CONFIG_RTL_92C_SUPPORT) +#define GET_CHIP_VER(priv) VERSION_8192C +#elif defined(CONFIG_RTL_88E_SUPPORT) +#define GET_CHIP_VER(priv) VERSION_8188E +#elif defined(CONFIG_WLAN_HAL_8192EE) +#define GET_CHIP_VER(priv) VERSION_8192E +#endif + +#if defined(USE_OUT_SRC) +#undef IS_OUTSRC_CHIP +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) +#define IS_OUTSRC_CHIP(priv) 0 +#else +#define IS_OUTSRC_CHIP(priv) 1 +#endif +#endif + +#undef IS_HAL_CHIP +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_88E_SUPPORT) +#define IS_HAL_CHIP(priv) 0 +#else +#define IS_HAL_CHIP(priv) 1 +#endif +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#ifdef CONFIG_RTL_92C_SUPPORT +#define IS_88RE(priv) ((priv->pshare->version_id&0x200)) +#endif +#define IS_UMC_A_CUT(priv) ((priv->pshare->version_id&0x4f0)==0x400) +#define IS_UMC_B_CUT(priv) ((priv->pshare->version_id&0x4f0)==0x410) +#ifdef CONFIG_RTL_92C_SUPPORT +#define IS_UMC_A_CUT_88C(priv) (IS_UMC_A_CUT(priv) && (GET_CHIP_VER(priv) == VERSION_8188C)) +#define IS_UMC_B_CUT_88C(priv) (IS_UMC_B_CUT(priv) && (GET_CHIP_VER(priv) == VERSION_8188C)) +#endif +//#ifdef CONFIG_RTL_8812_SUPPORT +#define IS_B_CUT_8812(priv) ((GET_CHIP_VER(priv) == VERSION_8812E) && ((priv->pshare->version_id&0xf0)==0)) +#define IS_C_CUT_8812(priv) ((GET_CHIP_VER(priv) == VERSION_8812E) && ((priv->pshare->version_id&0xf0)==0x10)) +//#endif + +#define IS_A_CUT_8881A(priv) ((GET_CHIP_VER(priv) == VERSION_8881A) && ((priv->pshare->version_id&0xf0)==0)) +#define IS_C_CUT_8192E(priv) ((GET_CHIP_VER(priv) == VERSION_8192E) && ((priv->pshare->version_id&0xf0)>>4 == 0x2)) +#define IS_D_CUT_8192E(priv) ((GET_CHIP_VER(priv) == VERSION_8192E) && ((priv->pshare->version_id&0xf0)>>4 == 0x3)) + +#define RTL_SET_MASK(reg,mask,val,shift) (((reg)&(~(mask)))|((val)<<(shift))) + +#ifdef CONFIG_PCI_HCI + +#ifdef USE_IO_OPS + +#define get_desc(val) (val) +#define set_desc(val) (val) + +#define RTL_R8(reg) inb(((unsigned long)priv->pshare->ioaddr) + (reg)) +#define RTL_R16(reg) inw(((unsigned long)priv->pshare->ioaddr) + (reg)) +#define RTL_R32(reg) ((unsigned long)inl(((unsigned long)priv->pshare->ioaddr) + (reg))) +#define RTL_W8(reg, val8) outb((val8), ((unsigned long)priv->pshare->ioaddr) + (reg)) +#define RTL_W16(reg, val16) outw((val16), ((unsigned long)priv->pshare->ioaddr) + (reg)) +#define RTL_W32(reg, val32) outl((val32), ((unsigned long)priv->pshare->ioaddr) + (reg)) +#define RTL_W8_F RTL_W8 +#define RTL_W16_F RTL_W16 +#define RTL_W32_F RTL_W32 +#undef readb +#undef readw +#undef readl +#undef writeb +#undef writew +#undef writel +#define readb(addr) inb((unsigned long)(addr)) +#define readw(addr) inw((unsigned long)(addr)) +#define readl(addr) inl((unsigned long)(addr)) +#define writeb(val,addr) outb((val), (unsigned long)(addr)) +#define writew(val,addr) outw((val), (unsigned long)(addr)) +#define writel(val,addr) outl((val), (unsigned long)(addr)) + +#else // !USE_IO_OPS + +#define PAGE_NUM 15 + +#ifdef __LINUX_2_6__ + #define IO_TYPE_CAST (unsigned char *) +#else + #define IO_TYPE_CAST (unsigned int) +#endif + +#ifndef RTK_NL80211 +extern unsigned char rfc1042_header[WLAN_LLC_HEADER_SIZE]; //mark_wrt +#endif + +#ifdef CONFIG_RTL_8198 +#ifndef REG32 + #define REG32(reg) (*(volatile unsigned int *)(reg)) +#endif +#endif + +static __inline__ unsigned char RTL_R8_F(struct rtl8192cd_priv *priv, unsigned int reg) +{ + unsigned long ioaddr = priv->pshare->ioaddr; + unsigned char val8 = 0; + +#ifdef IO_MAPPING + unsigned char page = ((unsigned char)(reg >> 8)) & PAGE_NUM; + if (priv->pshare->io_mapping && page) + { +#ifndef SMP_SYNC + unsigned long x; +#endif + SAVE_INT_AND_CLI(x); + + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) | page, IO_TYPE_CAST(ioaddr + _PSR_)); + val8 = readb(IO_TYPE_CAST(ioaddr + (reg & 0x000000ff))); + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) & (~PAGE_NUM), IO_TYPE_CAST(ioaddr + _PSR_)); + + RESTORE_INT(x); + } + else +#endif + { +#ifdef CONFIG_RTL_8198 + unsigned int data=0; + int swap[4]={0,8,16,24}; + int diff = reg&0x3; + data=REG32((ioaddr + (reg&(0xFFFFFFFC)) ) ); + val8=(unsigned char)(( data>>swap[diff])&0xff); +#else + val8 = readb(IO_TYPE_CAST(ioaddr + reg)); +#endif + } + + return val8; +} + +static __inline__ unsigned short RTL_R16_F(struct rtl8192cd_priv *priv, unsigned int reg) +{ + unsigned long ioaddr = priv->pshare->ioaddr; + unsigned short val16 = 0; + + if (reg & 0x00000001) + panic_printk("Unaligned read to reg 0x%08x!\n", reg); + +#ifdef IO_MAPPING + unsigned char page = ((unsigned char)(reg >> 8)) & PAGE_NUM; + if (priv->pshare->io_mapping && page) + { +#ifndef SMP_SYNC + unsigned long x; +#endif + SAVE_INT_AND_CLI(x); + + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) | page, IO_TYPE_CAST(ioaddr + _PSR_)); + val16 = readw(IO_TYPE_CAST(ioaddr + (reg & 0x000000ff))); + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) & (~PAGE_NUM), IO_TYPE_CAST(ioaddr + _PSR_)); + + RESTORE_INT(x); + } + else +#endif + { +#ifdef CONFIG_RTL_8198 + unsigned int data=0; + int swap[4]={0,8,16,24}; + int diff = reg&0x3; + data=REG32((ioaddr + (reg&(0xFFFFFFFC)) ) ); + val16=(unsigned short)(( data>>swap[diff])&0xffff); +#else + val16 = readw(IO_TYPE_CAST(ioaddr + reg)); +#endif + } + +#ifdef CHECK_SWAP + if (priv->pshare->type & ACCESS_SWAP_IO) + val16 = le16_to_cpu(val16); +#endif + + return val16; +} + +static __inline__ unsigned int RTL_R32_F(struct rtl8192cd_priv *priv, unsigned int reg) +{ + unsigned long ioaddr = priv->pshare->ioaddr; + unsigned int val32 = 0; + + if (reg & 0x00000003) + panic_printk("Unaligned read to reg 0x%08x!\n", reg); + +#ifdef IO_MAPPING + unsigned char page = ((unsigned char)(reg >> 8)) & PAGE_NUM; + if (priv->pshare->io_mapping && page) + { +#ifndef SMP_SYNC + unsigned long x; +#endif + SAVE_INT_AND_CLI(x); + + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) | page, IO_TYPE_CAST(ioaddr + _PSR_)); + val32 = readl(IO_TYPE_CAST(ioaddr + (reg & 0x000000ff))); + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) & (~PAGE_NUM), IO_TYPE_CAST(ioaddr + _PSR_)); + + RESTORE_INT(x); + } + else +#endif + { + val32 = readl(IO_TYPE_CAST(ioaddr + reg)); + } + +#ifdef CHECK_SWAP + if (priv->pshare->type & ACCESS_SWAP_IO) + val32 = le32_to_cpu(val32); +#endif + + return val32; +} + +static __inline__ void RTL_W8_F(struct rtl8192cd_priv *priv, unsigned int reg, unsigned char val8) +{ + unsigned long ioaddr = priv->pshare->ioaddr; +#ifdef IO_MAPPING + unsigned char page = ((unsigned char)(reg >> 8)) & PAGE_NUM; + if (priv->pshare->io_mapping && page) + { +#ifndef SMP_SYNC + unsigned long x; +#endif + SAVE_INT_AND_CLI(x); + + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) | page, IO_TYPE_CAST(ioaddr + _PSR_)); + writeb(val8, IO_TYPE_CAST(ioaddr + (reg & 0x000000ff))); + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) & (~PAGE_NUM), IO_TYPE_CAST(ioaddr + _PSR_)); + + RESTORE_INT(x); + } + else +#endif + { + writeb(val8, IO_TYPE_CAST(ioaddr + reg)); + } +} + +static __inline__ void RTL_W16_F(struct rtl8192cd_priv *priv, unsigned int reg, unsigned short val16) +{ + unsigned long ioaddr = priv->pshare->ioaddr; + unsigned short val16_n = val16; +#ifdef IO_MAPPING + unsigned char page; +#endif + + if (reg & 0x00000001) + panic_printk("Unaligned write to reg 0x%08x!, val16=0x%08x!\n", reg, val16); + +#ifdef CHECK_SWAP + if (priv->pshare->type & ACCESS_SWAP_IO) + val16_n = cpu_to_le16(val16); +#endif + +#ifdef IO_MAPPING + page = ((unsigned char)(reg >> 8)) & PAGE_NUM; + if (priv->pshare->io_mapping && page) + { +#ifndef SMP_SYNC + unsigned long x; +#endif + SAVE_INT_AND_CLI(x); + + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) | page, IO_TYPE_CAST(ioaddr + _PSR_)); + writew(val16_n, IO_TYPE_CAST(ioaddr + (reg & 0x000000ff))); + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) & (~PAGE_NUM), IO_TYPE_CAST(ioaddr + _PSR_)); + + RESTORE_INT(x); + } + else +#endif + { + writew(val16_n, IO_TYPE_CAST(ioaddr + reg)); + } +} + +static __inline__ void RTL_W32_F(struct rtl8192cd_priv *priv, unsigned int reg, unsigned int val32) +{ + unsigned long ioaddr = priv->pshare->ioaddr; + unsigned int val32_n = val32; +#ifdef IO_MAPPING + unsigned char page; +#endif + + if (reg & 0x00000003) + panic_printk("Unaligned write to reg 0x%08x!, val32=0x%08x!\n", reg, val32); + +#ifdef CHECK_SWAP + if (priv->pshare->type & ACCESS_SWAP_IO) + val32_n = cpu_to_le32(val32); +#endif + +#ifdef IO_MAPPING + page = ((unsigned char)(reg >> 8)) & PAGE_NUM; + if (priv->pshare->io_mapping && page) + { +#ifndef SMP_SYNC + unsigned long x; +#endif + SAVE_INT_AND_CLI(x); + + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) | page, IO_TYPE_CAST(ioaddr + _PSR_)); + writel(val32_n, IO_TYPE_CAST(ioaddr + (reg & 0x000000ff))); + writeb(readb(IO_TYPE_CAST(ioaddr + _PSR_)) & (~PAGE_NUM), IO_TYPE_CAST(ioaddr + _PSR_)); + + RESTORE_INT(x); + } + else +#endif + { + writel(val32_n, IO_TYPE_CAST(ioaddr + reg)); + } +} + +#ifdef PCIE_POWER_SAVING + + +#define RTL_R8(reg) \ + (( priv->pwr_state==L2 || priv->pwr_state==L1) ? 0 :(RTL_R8_F(priv, reg)) ) + +#define RTL_R16(reg) \ + (( priv->pwr_state==L2 || priv->pwr_state==L1) ? 0 : (RTL_R16_F(priv, reg))) + +#define RTL_R32(reg) \ + (( priv->pwr_state==L2 || priv->pwr_state==L1) ? 0 : (RTL_R32_F(priv, reg))) + +#define RTL_W8(reg, val8) \ + do { \ + if( priv->pwr_state==L2 || priv->pwr_state==L1) \ + { printk("Error!!! w8:%x,%x in L%d\n", reg, val8, priv->pwr_state);} \ + else \ + RTL_W8_F(priv, reg, val8); \ + } while (0) + +#define RTL_W16(reg, val16) \ + do { \ + if( priv->pwr_state==L2 || priv->pwr_state==L1) \ + printk("Err!!! w16:%x,%x in L%d\n", reg, val16, priv->pwr_state); \ + else \ + RTL_W16_F(priv, reg, val16); \ + } while (0) + +#define RTL_W32(reg, val32) \ + do { \ + if( priv->pwr_state==L2 || priv->pwr_state==L1) \ + printk("Err!!! w32:%x,%x in L%d\n", reg, (unsigned int)val32, priv->pwr_state); \ + else \ + RTL_W32_F(priv, reg, val32) ; \ + } while (0) + +#else + +#define RTL_R8(reg) \ + (RTL_R8_F(priv, reg)) + +#define RTL_R16(reg) \ + (RTL_R16_F(priv, reg)) + +#define RTL_R32(reg) \ + (RTL_R32_F(priv, reg)) + +#define RTL_W8(reg, val8) \ + do { \ + RTL_W8_F(priv, reg, val8); \ + } while (0) + +#define RTL_W16(reg, val16) \ + do { \ + RTL_W16_F(priv, reg, val16); \ + } while (0) + +#define RTL_W32(reg, val32) \ + do { \ + RTL_W32_F(priv, reg, val32) ; \ + } while (0) + +#endif + + +#ifdef CHECK_SWAP +#define get_desc(val) ((priv->pshare->type & ACCESS_SWAP_MEM) ? le32_to_cpu(val) : val) +#define set_desc(val) ((priv->pshare->type & ACCESS_SWAP_MEM) ? cpu_to_le32(val) : val) +#else +#define get_desc(val) (val) +#define set_desc(val) (val) +#endif + +#endif // USE_IO_OPS +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI +#define RTL_R8(reg) usb_read8(priv, reg) +#define RTL_R16(reg) usb_read16(priv, reg) +#define RTL_R32(reg) usb_read32(priv, reg) + +#define RTL_W8(reg, val8) usb_write8(priv, reg, val8) +#define RTL_W16(reg, val16) usb_write16(priv, reg, val16) +#define RTL_W32(reg, val32) usb_write32(priv, reg, val32) +#define RTL_Wn(reg, len, val) usb_writeN(priv, reg, len, val) + +#define get_desc(val) le32_to_cpu(val) +#define set_desc(val) cpu_to_le32(val) +#endif // CONFIG_USB_HCI + +#ifdef CONFIG_SDIO_HCI +#define RTL_R8(reg) sdio_read8(priv, reg, NULL) +#define RTL_R16(reg) sdio_read16(priv, reg, NULL) +#define RTL_R32(reg) sdio_read32(priv, reg, NULL) + +#define RTL_W8(reg, val8) sdio_write8(priv, reg, val8) +#define RTL_W16(reg, val16) sdio_write16(priv, reg, val16) +#define RTL_W32(reg, val32) sdio_write32(priv, reg, val32) +#define RTL_Wn(reg, len, val) sdio_writeN(priv, reg, len, val) + +#define get_desc(val) le32_to_cpu(val) +#define set_desc(val) cpu_to_le32(val) +#endif // CONFIG_SDIO_HCI + +#define get_tofr_ds(pframe) ((GetToDs(pframe) << 1) | GetFrDs(pframe)) + +#define is_qos_data(pframe) ((GetFrameSubType(pframe) & (WIFI_DATA_TYPE | BIT(7))) == (WIFI_DATA_TYPE | BIT(7))) + +#define UINT32_DIFF(a, b) ((a >= b)? (a - b):(0xffffffff - b + a + 1)) + +static __inline__ struct list_head *dequeue_frame(struct rtl8192cd_priv *priv, struct list_head *head) +{ +#ifndef SMP_SYNC + unsigned long flags=0; +#endif + struct list_head *pnext; + + SAVE_INT_AND_CLI(flags); + if (list_empty(head)) { + RESTORE_INT(flags); + return (void *)NULL; + } + + pnext = head->next; + list_del_init(pnext); + + RESTORE_INT(flags); + + return pnext; +} + +static __inline__ int wifi_mac_hash(const unsigned char *mac) +{ + unsigned long x; + + x = mac[0]; + x = (x << 2) ^ mac[1]; + x = (x << 2) ^ mac[2]; + x = (x << 2) ^ mac[3]; + x = (x << 2) ^ mac[4]; + x = (x << 2) ^ mac[5]; + + x ^= x >> 8; + + return x & (NUM_STAT - 1); +} + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +#define get_pfrinfo(pskb) (struct rx_frinfo *)PTR_ALIGN(((unsigned long)(pskb->data) - sizeof(struct rx_frinfo)-4), 4) +#else +#define get_pfrinfo(pskb) ((struct rx_frinfo *)((unsigned long)(pskb->data) - sizeof(struct rx_frinfo))) +#endif + +#define get_pskb(pfrinfo) (pfrinfo->pskb) + +#define get_pframe(pfrinfo) ((unsigned char *)((unsigned long)(pfrinfo->pskb->data))) + +#ifdef CONFIG_NET_PCI +#define IS_PCIBIOS_TYPE (((priv->pshare->type >> TYPE_SHIFT) & TYPE_MASK) == TYPE_PCI_BIOS) +#endif + +#define rtl_atomic_inc(ptr_atomic_t) atomic_inc(ptr_atomic_t) +#define rtl_atomic_dec(ptr_atomic_t) atomic_dec(ptr_atomic_t) +#define rtl_atomic_read(ptr_atomic_t) atomic_read(ptr_atomic_t) +#define rtl_atomic_set(ptr_atomic_t, i) atomic_set(ptr_atomic_t,i) + +enum _skb_flag_ { + _SKB_TX_ = 1, + _SKB_RX_ = 2, + _SKB_RX_IRQ_ = 4, + _SKB_TX_IRQ_ = 8 +}; + +// Allocate net device socket buffer +extern __MIPS16 __IRAM_IN_865X struct sk_buff *alloc_skb_from_queue(struct rtl8192cd_priv *priv); +static __inline__ struct sk_buff *rtl_dev_alloc_skb(struct rtl8192cd_priv *priv, + unsigned int length, int flag, int could_alloc_from_kerenl) +{ + struct sk_buff *skb = NULL; + +#if defined(__ECOS) && defined(CONFIG_SDIO_HCI) + skb = dev_alloc_skb(length); +#else + skb = alloc_skb_from_queue(priv); + + if (skb == NULL && could_alloc_from_kerenl) + skb = dev_alloc_skb(length); +#endif + +#ifdef ENABLE_RTL_SKB_STATS + if (NULL != skb) { + if (flag & (_SKB_TX_ | _SKB_TX_IRQ_)) + rtl_atomic_inc(&priv->rtl_tx_skb_cnt); + else + rtl_atomic_inc(&priv->rtl_rx_skb_cnt); + } +#endif + + return skb; +} + +// Free net device socket buffer +static __inline__ void rtl_kfree_skb(struct rtl8192cd_priv *priv, struct sk_buff *skb, int flag) +{ +#ifdef ENABLE_RTL_SKB_STATS + if (flag & (_SKB_TX_ | _SKB_TX_IRQ_)) + rtl_atomic_dec(&priv->rtl_tx_skb_cnt); + else + rtl_atomic_dec(&priv->rtl_rx_skb_cnt); +#endif + + dev_kfree_skb_any(skb); +} + +static __inline__ int is_CCK_rate(unsigned char rate) +{ + if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) + return TRUE; + else + return FALSE; +} + + +static __inline__ int is_MCS_rate(unsigned char rate) +{ + if (rate >= HT_RATE_ID) + return TRUE; + else + return FALSE; +} + +static __inline__ int is_2T_rate(unsigned char rate) +{ +#ifdef RTK_AC_SUPPORT + if ((rate >= _NSS2_MCS0_RATE_) && (rate <= _NSS2_MCS9_RATE_)) + return TRUE; + else +#endif + return ((rate >= _MCS8_RATE_) && (rate <= _MCS16_RATE_)) ? TRUE : FALSE; +} + + +static __inline__ int is_3T_rate(unsigned char rate) +{ +#ifdef RTK_AC_SUPPORT + if ((rate >= _NSS3_MCS0_RATE_) && (rate <= _NSS3_MCS9_RATE_)) + return TRUE; + else +#endif + return ((rate >= _MCS16_RATE_) && (rate <= _MCS23_RATE_)) ? TRUE : FALSE; +} + +static __inline__ int is_4T_rate(unsigned char rate) +{ +#ifdef RTK_AC_SUPPORT + if ((rate >= _NSS4_MCS0_RATE_) && (rate <= _NSS4_MCS9_RATE_)) + return TRUE; + else +#endif + return ((rate >= _MCS24_RATE_) && (rate <= _MCS31_RATE_)) ? TRUE : FALSE; +} + +static __inline__ int is_auto_rate(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef WDS + if (pstat->state & WIFI_WDS) + return ((priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate==0) ? 1: 0); + else +#endif + return (priv->pmib->dot11StationConfigEntry.autoRate); +} + +static __inline__ int is_fixedMCSTxRate(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef WDS + if (pstat->state & WIFI_WDS) + return (priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate & 0xffff000) ; + else +#endif + return (priv->pmib->dot11StationConfigEntry.fixedTxRate & 0xffff000); +} + + +#ifdef RTK_AC_SUPPORT +static __inline__ int is_VHT_rate(unsigned char rate) +{ + if (rate >= VHT_RATE_ID) + return TRUE; + else + return FALSE; +} + +static __inline__ int is_fixedVHTTxRate(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef WDS + if (pstat->state & WIFI_WDS) + return ((priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate & BIT(31)) ? 1 : 0); + else +#endif + return ((priv->pmib->dot11StationConfigEntry.fixedTxRate & BIT(31)) ? 1 : 0); +} +#endif + +static __inline__ int is_MCS_1SS_rate(unsigned char rate) +{ + if ((rate >= _MCS0_RATE_) && (rate <= _MCS7_RATE_)) + return TRUE; + else + return FALSE; +} + +static __inline__ int is_MCS_2SS_rate(unsigned char rate) +{ + if ((rate >= _MCS8_RATE_) && (rate <= _MCS15_RATE_)) + return TRUE; + else + return FALSE; +} + +static __inline__ int is_MCS_3SS_rate(unsigned char rate) +{ + if ((rate >= _MCS16_RATE_) && (rate <= _MCS23_RATE_)) + return TRUE; + else + return FALSE; +} + +static __inline__ int is_MCS_4SS_rate(unsigned char rate) +{ + if ((rate >= _MCS24_RATE_) && (rate <= _MCS31_RATE_)) + return TRUE; + else + return FALSE; +} + + +#ifdef CONFIG_PCI_HCI + +#ifdef __MIPSEB__ +static __inline__ void rtl_cache_sync_wback(struct rtl8192cd_priv *priv, unsigned long start, + unsigned int size, int direction) +{ + if (0 == size) return; // if the size of cache sync is equal to zero, don't do sync action +#ifdef __LINUX_2_6__ + start = CPHYSADDR(start)+CONFIG_LUNA_SLAVE_PHYMEM_OFFSET;//CPHYSADDR is virt_to_bus +#endif +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if (IS_PCIBIOS_TYPE) { +#ifdef __LINUX_2_6__ + if (direction == PCI_DMA_FROMDEVICE) + pci_dma_sync_single_for_cpu(priv->pshare->pdev, start, size, direction); + else if (direction == PCI_DMA_TODEVICE) + pci_dma_sync_single_for_device(priv->pshare->pdev, start, size, direction); +#else + pci_dma_sync_single(priv->pshare->pdev, start, size, direction); +#endif + } + else + dma_cache_wback_inv((unsigned long)bus_to_virt(start-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), size); +#else +#ifdef TRXBD_CACHABLE_REGION + if (direction == PCI_DMA_FROMDEVICE) + _dma_cache_inv((unsigned long)bus_to_virt(start-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), size); + else +#endif + _dma_cache_wback_inv((unsigned long)bus_to_virt(start-CONFIG_LUNA_SLAVE_PHYMEM_OFFSET), size); +#endif +} +#else +static __inline__ void rtl_cache_sync_wback(struct rtl8192cd_priv *priv, unsigned long start, + unsigned int size, int direction) +{ + if (0 == size) return; // if the size of cache sync is equal to zero, don't do sync action + +#ifdef __LINUX_2_6__ + start = virt_to_bus((void*)start); + if (direction == PCI_DMA_FROMDEVICE) + pci_dma_sync_single_for_cpu(priv->pshare->pdev, start, size, direction); + else if (direction == PCI_DMA_TODEVICE) + pci_dma_sync_single_for_device(priv->pshare->pdev, start, size, direction); +#else + pci_dma_sync_single(priv->pshare->pdev, start, size, direction); +#endif +} +#endif//__MIPSEB__ + + +static __inline__ unsigned long get_physical_addr(struct rtl8192cd_priv *priv, void *ptr, + unsigned int size, int direction) +{ +#if defined(CONFIG_NET_PCI) && !defined(USE_RTL8186_SDK) + if ((IS_PCIBIOS_TYPE) && (0 != size)) + return pci_map_single(priv->pshare->pdev, ptr, size, direction); + else +#endif + return (virt_to_bus(ptr)+CONFIG_LUNA_SLAVE_PHYMEM_OFFSET); +} + +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +/* The following definitions were useless in USB/SDIO I/F. The only purpose is to avoid compiler issue */ +#define PCI_DMA_BIDIRECTIONAL 0 +#define PCI_DMA_TODEVICE 1 +#define PCI_DMA_FROMDEVICE 2 +#define PCI_DMA_NONE 3 + +static __inline__ void rtl_cache_sync_wback(struct rtl8192cd_priv *priv, unsigned long start, + unsigned int size, int direction) +{ +} + +static __inline__ unsigned long get_physical_addr(struct rtl8192cd_priv *priv, void *ptr, + unsigned int size, int direction) +{ + return (unsigned long)ptr; +} + +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +static __inline__ int can_enable_rx_ldpc(struct rtl8192cd_priv *priv) +{ + if(GET_CHIP_VER(priv) >= VERSION_8814A) + return 1; + else +#ifdef RTK_AC_SUPPORT //for 11ac logo + if(AC_SIGMA_MODE != AC_SIGMA_NONE) + return 1; + else +#endif + return 0; +} + + +/* + * find a token in a string. If succes, return pointer of token next. If fail, return null + */ +static __inline__ char *get_value_by_token(char *data, char *token) +{ + int idx=0, src_len=strlen(data), token_len=strlen(token); + + while (src_len >= token_len) { + if (!memcmp(&data[idx], token, token_len)) + return (&data[idx+token_len]); + src_len--; + idx++; + } + return NULL; +} +static __inline__ int get_rf_mimo_mode(struct rtl8192cd_priv *priv) +{ + if ((priv->pshare->phw->MIMO_TR_hw_support == MIMO_1T1R) || + (priv->pmib->dot11RFEntry.MIMO_TR_mode == MIMO_1T1R)) + return MIMO_1T1R; +#ifdef CONFIG_RTL_92D_SUPPORT + else if ((priv->pshare->phw->MIMO_TR_hw_support == MIMO_1T2R) || + (priv->pmib->dot11RFEntry.MIMO_TR_mode == MIMO_1T2R)) + return MIMO_1T2R; +#endif + else if (priv->pshare->phw->MIMO_TR_hw_support == MIMO_2T2R) + return MIMO_2T2R; + else if (priv->pshare->phw->MIMO_TR_hw_support == MIMO_3T3R) + return MIMO_3T3R; + else if (priv->pshare->phw->MIMO_TR_hw_support == MIMO_4T4R) + return MIMO_4T4R; + + return MIMO_2T2R; //2ss as default + +} + +static __inline__ unsigned int get_supported_mcs(struct rtl8192cd_priv *priv) +{ + if (get_rf_mimo_mode(priv) == MIMO_1T1R) + return (priv->pmib->dot11nConfigEntry.dot11nSupportedMCS & 0x00ff); + else if(get_rf_mimo_mode(priv) == MIMO_2T2R) + return (priv->pmib->dot11nConfigEntry.dot11nSupportedMCS & 0xffff); + else if(get_rf_mimo_mode(priv) == MIMO_3T3R) + return (priv->pmib->dot11nConfigEntry.dot11nSupportedMCS & 0xffffff); + + return (priv->pmib->dot11nConfigEntry.dot11nSupportedMCS & 0xffff); //2ss as default +} + +#ifdef CONFIG_RTL8672 +static __inline__ void tx_sum_up(struct rtl8192cd_priv *priv, struct stat_info *pstat, int pktlen, struct tx_insn* txcfg) +#else +static __inline__ void tx_sum_up(struct rtl8192cd_priv *priv, struct stat_info *pstat, int pktlen) +#endif +{ + struct net_device_stats *pnet_stats; + + if (priv) { + pnet_stats = &(priv->net_stats); + pnet_stats->tx_packets++; + pnet_stats->tx_bytes += pktlen; + + priv->ext_stats.tx_byte_cnt += pktlen; + + // bcm old 11n chipset iot debug, and TXOP enlarge + priv->pshare->current_tx_bytes += pktlen; + + if (pstat) + priv->pshare->NumTxBytesUnicast += pktlen; + } + + if (pstat) { + +#if defined(TXREPORT) +#if defined(TESTCHIP_SUPPORT) && defined(CONFIG_RTL_92C_SUPPORT) + if (IS_TEST_CHIP(priv) && (GET_CHIP_VER(priv) <= VERSION_8192C) ) { + pstat->tx_pkts++; + } else +#endif + if(pstat->sta_in_firmware != 1) +#endif //TXREPORT + { +#ifdef CONFIG_RTL8672 + if (txcfg->fr_type == _SKB_FRAME_TYPE_ +#ifdef SUPPORT_TX_MCAST2UNI + && !txcfg->isMC2UC +#endif + ) +#endif + pstat->tx_pkts++; + } + pstat->tx_bytes += pktlen; + pstat->tx_byte_cnt += pktlen; + } +} + + +static __inline__ void rx_sum_up(struct rtl8192cd_priv *priv, struct stat_info *pstat, int pktlen, int retry) +{ + struct net_device_stats *pnet_stats; + + if (priv) { + pnet_stats = &(priv->net_stats); + pnet_stats->rx_packets++; + pnet_stats->rx_bytes += pktlen; + + if (retry) + priv->ext_stats.rx_retrys++; + + priv->ext_stats.rx_byte_cnt += pktlen; + + // bcm old 11n chipset iot debug + priv->pshare->current_rx_bytes += pktlen; + } + + if (pstat) { + pstat->rx_pkts++; + pstat->rx_bytes += pktlen; + pstat->rx_byte_cnt += pktlen; + } +} + + +static __inline__ unsigned char get_cck_swing_idx(unsigned int bandwidth, unsigned char ofdm_swing_idx) +{ + unsigned char cck_swing_idx; + + if (bandwidth == HT_CHANNEL_WIDTH_20) { + if (ofdm_swing_idx >= TxPwrTrk_CCK_SwingTbl_Len) + cck_swing_idx = TxPwrTrk_CCK_SwingTbl_Len - 1; + else + cck_swing_idx = ofdm_swing_idx; + } + else { // 40M bw + if (ofdm_swing_idx < 12) + cck_swing_idx = 0; + else if (ofdm_swing_idx > (TxPwrTrk_CCK_SwingTbl_Len - 1 + 12)) + cck_swing_idx = TxPwrTrk_CCK_SwingTbl_Len - 1; + else + cck_swing_idx = ofdm_swing_idx - 12; + } + + return cck_swing_idx; +} + +//Apollo slave cpu do not use watch dog +#ifdef CONFIG_ARCH_LUNA_SLAVE +#undef CONFIG_RTL_WTDOG +#endif + +#if (defined(__ECOS)&&defined(CONFIG_RTL_819X)) || defined(CONFIG_RTL865X_WTDOG) || defined(CONFIG_RTL_WTDOG) + +#ifndef CONFIG_RTL_8198B +#ifndef BSP_WDTCNR + #define BSP_WDTCNR 0xB800311C +#endif +#endif + +#if defined(__LINUX_2_6__) || defined(__ECOS) +#if defined(CONFIG_RTL_8198B) +#define _WDTCNR_ BSP_WDTCNTRR +#else +#define _WDTCNR_ BSP_WDTCNR +#endif +#else +#define _WDTCNR_ WDTCNR +#endif + +#define _WDTKICK_ (1 << 23) +#ifdef __ECOS +#define _WDTSTOP_ (0xA5000000) +#else +#define _WDTSTOP_ (0xA5f00000) +#endif + +static __inline__ void watchdog_stop(struct rtl8192cd_priv *priv) +{ + *((volatile unsigned long *)_WDTCNR_) |= _WDTKICK_; + priv->pshare->wtval = *((volatile unsigned long *)_WDTCNR_); +#ifdef __ECOS + *((volatile unsigned long *)_WDTCNR_) |= _WDTSTOP_; +#else + *((volatile unsigned long *)_WDTCNR_) = _WDTSTOP_; +#endif +} + +static __inline__ void watchdog_resume(struct rtl8192cd_priv *priv) +{ + *((volatile unsigned long *)_WDTCNR_) = priv->pshare->wtval; + *((volatile unsigned long *)_WDTCNR_) |= _WDTKICK_; +} + + +static __inline__ void watchdog_kick(void) +{ + *((volatile unsigned long *)_WDTCNR_) |= _WDTKICK_; +} + +#else // no watchdog support + +static __inline__ void watchdog_stop(struct rtl8192cd_priv *priv) +{} + +static __inline__ void watchdog_resume(struct rtl8192cd_priv *priv) +{} + +static __inline__ void watchdog_kick(void) +{} + +#endif + + +#if defined(CONFIG_RTL_WAPI_SUPPORT) +void wapi_event_indicate(struct rtl8192cd_priv *priv); +#endif + +#define CIRC_CNT_RTK(head,tail,size) ((head>=tail)?(head-tail):(size-tail+head)) +#define CIRC_SPACE_RTK(head,tail,size) CIRC_CNT_RTK((tail),((head)+1),(size)) + +#ifdef CONFIG_USE_VMALLOC +#define rtw_vmalloc(sz) _rtw_vmalloc((sz)) +#define rtw_zvmalloc(sz) _rtw_zvmalloc((sz)) +#define rtw_vmfree(pbuf, sz) _rtw_vmfree((pbuf), (sz)) +#else // !CONFIG_USE_VMALLOC +#define rtw_vmalloc(sz) _rtw_malloc((sz)) +#define rtw_zvmalloc(sz) _rtw_zmalloc((sz)) +#define rtw_vmfree(pbuf, sz) _rtw_mfree((pbuf), (sz)) +#endif // CONFIG_USE_VMALLOC +#define rtw_malloc(sz) _rtw_malloc((sz)) +#define rtw_zmalloc(sz) _rtw_zmalloc((sz)) +#define rtw_mfree(pbuf, sz) _rtw_mfree((pbuf), (sz)) + +u8* _rtw_vmalloc(u32 sz); +u8* _rtw_zvmalloc(u32 sz); +void _rtw_vmfree(const void *pbuf, u32 sz); +u8* _rtw_zmalloc(u32 sz); +u8* _rtw_malloc(u32 sz); +void _rtw_mfree(const void *pbuf, u32 sz); + +void* rtw_malloc2d(int h, int w, int size); +void rtw_mfree2d(void *pbuf, int h, int w, int size); + +#if defined(USE_PID_NOTIFY) && defined(LINUX_2_6_27_) +extern struct pid *_wlanapp_pid; +extern struct pid *_wlanwapi_pid; +#endif + +#if defined(CONFIG_RTL_CUSTOM_PASSTHRU) +#ifdef __ECOS +INT32 rtl_isWlanPassthruFrame(UINT8 *data); +#else +INT32 rtl_isPassthruFrame(UINT8 *data); +#endif +#endif + +#ifdef USE_TXQUEUE +int init_txq_pool(struct list_head *head, unsigned char **ppool); +void free_txq_pool(struct list_head *head, unsigned char *ppool); +void append_skb_to_txq_head(struct txq_list_head *head, struct rtl8192cd_priv *priv, struct sk_buff *skb, struct net_device *dev, struct list_head *pool); +void append_skb_to_txq_tail(struct txq_list_head *head, struct rtl8192cd_priv *priv, struct sk_buff *skb, struct net_device *dev, struct list_head *pool); +void remove_skb_from_txq(struct txq_list_head *head, struct sk_buff **pskb, struct net_device **pdev, struct list_head *pool); +#endif + +static inline long timeval_to_us(const struct timeval *tv) +{ + return (tv->tv_sec*1000000L)+ tv->tv_usec; +} + +// Get the N-bytes aligment offset from the current length +#define N_BYTE_ALIGMENT(__Value, __Aligment) ((__Aligment == 1) ? (__Value) : (((__Value + __Aligment - 1) / __Aligment) * __Aligment)) + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +static inline int tx_servq_len(struct tx_servq *ptxservq) +{ + return ptxservq->xframe_queue.qlen; +} +#endif + +#ifdef CONFIG_USB_HCI +/* +* Increase and check if the continual_urb_error of this @param dvobjprive is larger than MAX_CONTINUAL_URB_ERR +* @return _TRUE: +* @return _FALSE: +*/ +static inline int rtw_inc_and_chk_continual_urb_error(struct rtl8192cd_priv *priv) +{ + int ret = FALSE; + int value; + if( (value=atomic_inc_return(&priv->pshare->continual_urb_error)) > MAX_CONTINUAL_URB_ERR) { + printk("[ERROR] continual_urb_error:%d > %d\n", value, MAX_CONTINUAL_URB_ERR); + ret = TRUE; + } else { + //printk("continual_urb_error:%d\n", value); + } + return ret; +} + +/* +* Set the continual_urb_error of this @param dvobjprive to 0 +*/ +static inline void rtw_reset_continual_urb_error(struct rtl8192cd_priv *priv) +{ + atomic_set(&priv->pshare->continual_urb_error, 0); +} + +#endif // CONFIG_USB_HCI + + +#ifdef HS2_SUPPORT +void staip_snooping_byarp(struct sk_buff *pskb, struct stat_info *pstat); +void staip_snooping_bydhcp(struct sk_buff *pskb, struct rtl8192cd_priv *priv); +void stav6ip_snooping_bynadvert(struct sk_buff *pskb, struct stat_info *pstat); +void stav6ip_snooping_bynsolic(struct sk_buff *pskb, struct stat_info *pstat); +int proxy_arp_handle(struct rtl8192cd_priv *priv, struct sk_buff *skb); +int proxy_icmpv6_ndisc(struct rtl8192cd_priv *priv, struct sk_buff *skb); +void calcu_sta_v6ip(struct stat_info *pstat); +int check_nei_advt(struct rtl8192cd_priv *priv, struct sk_buff *skb); +#endif + +#if defined(UNIVERSAL_REPEATER) || defined(HS2_SUPPORT) +__MIPS16 __IRAM_IN_865X int __rtl8192cd_start_xmit(struct sk_buff *skb, struct net_device *dev, int tx_flag); +#endif + +#ifdef __KERNEL__ +#ifdef NOT_RTK_BSP +#define __skb_dequeue(skb_queue) skb_dequeue(skb_queue) +#define __skb_queue_tail(skb_queue, skb) skb_queue_tail(skb_queue, skb) +#endif +#endif + +#ifdef CONFIG_PCI_HCI +#ifdef SMP_SYNC +static inline int hash_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned long flags = 0; + unsigned int index; + struct list_head *plist; + int ret = 0; + + index = wifi_mac_hash(pstat->hwaddr); + plist = priv->stat_hash; + plist += index; + + SMP_LOCK_HASH_LIST(flags); + + if (list_empty(&pstat->hash_list)) { + list_add_tail(&pstat->hash_list, plist); + ret = 1; + } + + SMP_UNLOCK_HASH_LIST(flags); + + return ret; +} + +static inline int hash_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned long flags = 0; + int ret = 0; + + SMP_LOCK_HASH_LIST(flags); + + if (!list_empty(&pstat->hash_list)) { + list_del_init(&pstat->hash_list); + ret = 1; + } + + SMP_UNLOCK_HASH_LIST(flags); + + return ret; +} + +#else +static inline int hash_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned int index; + struct list_head *plist; + int ret = 0; + + index = wifi_mac_hash(pstat->hwaddr); + plist = priv->stat_hash; + plist += index; + + if (list_empty(&pstat->hash_list)) { + list_add_tail(&pstat->hash_list, plist); + ret = 1; + } + + return ret; +} + +static inline int hash_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ret = 0; + + if (!list_empty(&pstat->hash_list)) { + list_del_init(&pstat->hash_list); + ret = 1; + } + + return ret; +} +#endif +static inline struct list_head* asoc_list_get_next(struct rtl8192cd_priv *priv, struct list_head *plist) +{ + return plist->next; +} + +static inline void asoc_list_unref(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + +} + +static inline int asoc_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ret = 0; + + if (!list_empty(&pstat->asoc_list)) { + list_del_init(&pstat->asoc_list); + ret = 1; + } + + return ret; +} + +static inline int asoc_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ret = 0; + + if (list_empty(&pstat->asoc_list)) { + list_add_tail(&pstat->asoc_list, &priv->asoc_list); + ret = 1; + } + + return ret; +} + +static inline int auth_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ret = 0; + + if (!list_empty(&pstat->auth_list)) { + list_del_init(&pstat->auth_list); + ret = 1; + } + + return ret; +} + +static inline int auth_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ret = 0; + + if (list_empty(&pstat->auth_list)) { + list_add_tail(&pstat->auth_list, &priv->auth_list); + ret = 1; + } + + return ret; +} + +static inline int sleep_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ret = 0; + + if (!list_empty(&pstat->sleep_list)) { + list_del_init(&pstat->sleep_list); + ret = 1; + } + + return ret; +} + +static inline int sleep_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ret = 0; + + if (list_empty(&pstat->sleep_list)) { + list_add_tail(&pstat->sleep_list, &priv->sleep_list); + ret = 1; + } + + return ret; +} + +static inline int wakeup_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ret = 0; + + if (!list_empty(&pstat->wakeup_list)) { + list_del_init(&pstat->wakeup_list); + ret = 1; + } + + return ret; +} + +static inline int wakeup_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ret = 0; + + if (list_empty(&pstat->wakeup_list)) { + list_add_tail(&pstat->wakeup_list, &priv->wakeup_list); + ret = 1; + } + + return ret; +} +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +static inline int hash_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + unsigned int index; + struct list_head *plist; + int ret = 0; + + index = wifi_mac_hash(pstat->hwaddr); + plist = priv->stat_hash; + plist += index; + + SMP_LOCK_HASH_LIST(flags); + + if (list_empty(&pstat->hash_list)) { + list_add_tail(&pstat->hash_list, plist); + ret = 1; + } + + SMP_UNLOCK_HASH_LIST(flags); + + return ret; +} + +static inline int hash_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + int ret = 0; + + SMP_LOCK_HASH_LIST(flags); + + if (!list_empty(&pstat->hash_list)) { + list_del_init(&pstat->hash_list); + ret = 1; + } + + SMP_UNLOCK_HASH_LIST(flags); + + return ret; +} + +static inline int auth_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + int ret = 0; + + SMP_LOCK_AUTH_LIST(flags); + + if (!list_empty(&pstat->auth_list)) { + list_del_init(&pstat->auth_list); + ret = 1; + } + + SMP_UNLOCK_AUTH_LIST(flags); + + return ret; +} + +static inline int auth_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + int ret = 0; + + SMP_LOCK_AUTH_LIST(flags); + + if (list_empty(&pstat->auth_list)) { + list_add_tail(&pstat->auth_list, &priv->auth_list); + ret = 1; + } + + SMP_UNLOCK_AUTH_LIST(flags); + + return ret; +} + +static inline int sleep_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + int ret = 0; + + SMP_LOCK_SLEEP_LIST(flags); + + if (!list_empty(&pstat->sleep_list)) { + list_del_init(&pstat->sleep_list); + ret = 1; + } + + SMP_UNLOCK_SLEEP_LIST(flags); + + return ret; +} + +static inline int sleep_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + int ret = 0; + + SMP_LOCK_SLEEP_LIST(flags); + + if (list_empty(&pstat->sleep_list)) { + list_add_tail(&pstat->sleep_list, &priv->sleep_list); + ret = 1; + } + + SMP_UNLOCK_SLEEP_LIST(flags); + + return ret; +} + +static inline int wakeup_list_del(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + int ret = 0; + + SMP_LOCK_WAKEUP_LIST(flags); + + if (!list_empty(&pstat->wakeup_list)) { + list_del_init(&pstat->wakeup_list); + ret = 1; + } + + SMP_UNLOCK_WAKEUP_LIST(flags); + + return ret; +} + +static inline int wakeup_list_add(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + int ret = 0; + + SMP_LOCK_WAKEUP_LIST(flags); + + if (list_empty(&pstat->wakeup_list)) { + list_add_tail(&pstat->wakeup_list, &priv->wakeup_list); + ret = 1; + } + + SMP_UNLOCK_WAKEUP_LIST(flags); + + return ret; +} +#endif // CONFIG_USB_HCI || CONFIG_SDIO_HCI + +#endif // _8192CD_UTIL_H_ + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192d_hw.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192d_hw.c new file mode 100755 index 000000000..f300d7334 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192d_hw.c @@ -0,0 +1,880 @@ + +#define _8192D_HW_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_hw.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + + +#ifdef CONFIG_RTL_92D_SUPPORT + +#if defined(CONFIG_RTL_819X) && defined(USE_RLX_BSP) +#if defined(CONFIG_OPENWRT_SDK) && !defined(CONFIG_ARCH_CPU_RLX) +#include +#else +#include +#endif //CONFIG_OPENWRT_SDK +#endif + +#ifndef USE_OUT_SRC +#define IQK_ADDA_REG_NUM 16 +#endif + + +#ifdef CONFIG_RTL_92D_DMDP + +extern u32 if_priv[]; + +__inline__ unsigned char DMDP_RTL_R8(unsigned int phy, unsigned int reg) +{ + struct rtl8192cd_priv *priv; + //printk("++++++++++++++++++++++++++%s(%x)++++++++++++++++++++++++++\n", __FUNCTION__, reg); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return -1; + } + priv = (struct rtl8192cd_priv *)if_priv[phy]; + return RTL_R8(reg); +} + +__inline__ void DMDP_RTL_W8(unsigned int phy, unsigned int reg, unsigned char val8) +{ + struct rtl8192cd_priv *priv; + //printk("++++++++++++++++++++++++++%s(%x,%x)++++++++++++++++++++++++++\n", __FUNCTION__, reg, val8); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return; + } + priv = (struct rtl8192cd_priv *)if_priv[phy]; + RTL_W8(reg, val8); +} + +__inline__ unsigned short DMDP_RTL_R16(unsigned int phy, unsigned int reg) +{ + struct rtl8192cd_priv *priv; + //printk("++++++++++++++++++++++++++%s++++++++++++++++++++++++++\n", __FUNCTION__); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return -1; + } + priv = (struct rtl8192cd_priv *)if_priv[phy]; + return RTL_R16(reg); +} + +__inline__ void DMDP_RTL_W16(unsigned int phy, unsigned int reg, unsigned short val16) +{ + struct rtl8192cd_priv *priv; + //printk("++++++++++++++++++++++++++%s++++++++++++++++++++++++++\n", __FUNCTION__); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return; + } + priv = (struct rtl8192cd_priv *)if_priv[phy]; + RTL_W16(reg, val16); +} + +__inline__ unsigned int DMDP_RTL_R32(unsigned int phy, unsigned int reg) +{ + struct rtl8192cd_priv *priv; + //printk("++++++++++++++++++++++++++%s(%x)++++++++++++++++++++++++++\n", __FUNCTION__, reg); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return -1; + } + priv = (struct rtl8192cd_priv *)if_priv[phy]; + return RTL_R32(reg); +} + +__inline__ void DMDP_RTL_W32(unsigned int phy, unsigned int reg, unsigned int val32) +{ + struct rtl8192cd_priv *priv; + //printk("++++++++++++++++++++++++++%s(%x, %x)++++++++++++++++++++++++++\n", __FUNCTION__, reg, val32); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return; + } + priv = (struct rtl8192cd_priv *)if_priv[phy]; + RTL_W32(reg, val32); +} + +unsigned int DMDP_PHY_QueryBBReg(unsigned int phy, unsigned int RegAddr, unsigned int BitMask) +{ + //printk("++++++++++++++++++++++++++%s++++++++++++++++++++++++++\n", __FUNCTION__); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return -1; + } + return PHY_QueryBBReg((struct rtl8192cd_priv *)if_priv[phy], RegAddr, BitMask); +} + +void DMDP_PHY_SetBBReg(unsigned int phy, unsigned int RegAddr, unsigned int BitMask, unsigned int Data) +{ + //printk("++++++++++++++++++++++++++%s++++++++++++++++++++++++++\n", __FUNCTION__); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return; + } + PHY_SetBBReg((struct rtl8192cd_priv *)if_priv[phy], RegAddr, BitMask, Data); +} + +unsigned int DMDP_PHY_QueryRFReg(unsigned int phy, RF92CD_RADIO_PATH_E eRFPath, + unsigned int RegAddr, unsigned int BitMask, unsigned int dbg_avoid) +{ + //printk("++++++++++++++++++++++++++%s++++++++++++++++++++++++++\n", __FUNCTION__); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return -1; + } + return PHY_QueryRFReg((struct rtl8192cd_priv *)if_priv[phy], eRFPath, RegAddr, BitMask, dbg_avoid); +} + +void DMDP_PHY_SetRFReg(unsigned int phy, RF92CD_RADIO_PATH_E eRFPath, unsigned int RegAddr, + unsigned int BitMask, unsigned int Data) +{ + //printk("++++++++++++++++++++++++++%s++++++++++++++++++++++++++\n", __FUNCTION__); + if (phy >= NUM_WLAN_IFACE || phy < 0) { + printk("%s: phy index[%d] out of bound !!\n", __FUNCTION__, phy); + return; + } + PHY_SetRFReg((struct rtl8192cd_priv *)if_priv[phy], eRFPath, RegAddr, BitMask, Data); +} + +#endif //CONFIG_RTL_92D_DMDP + +void SetSYN_para(struct rtl8192cd_priv *priv, unsigned char channel) +{ + unsigned int eRFPath, tmp=0; + unsigned int idx=-1, i; + unsigned int SYN_PARA[8][8] = { + {0xe43be, 0xfc638, 0x77c0a, 0xde471, 0xd7110, 0x8cb04, 0x00000, 0x00000}, // CH36-140 20MHz + {0xe43be, 0xfc078, 0xf7c1a, 0xe0c71, 0xd7550, 0xacb04, 0x00000, 0x00000}, // CH36-140 40MHz + {0xe43bf, 0xff038, 0xf7c0a, 0xde471, 0xe5550, 0xacb04, 0x00000, 0x00000}, // CH149, 155, 161 + {0xe43bf, 0xff079, 0xf7c1a, 0xde471, 0xe5550, 0xacb04, 0x00000, 0x00000}, // CH151, 153, 163, 165 + {0xe43bf, 0xff038, 0xf7c1a, 0xde471, 0xd7550, 0xacb04, 0x00000, 0x00000}, // CH157, 159 +#ifdef SW_LCK_92D + {0x643bc, 0xfc038, 0x77c1a, 0x00000, 0x00000, 0x00000, 0x61289, 0x01840}, // CH1,2,4,9,10,11,12 + {0x643bc, 0xfc038, 0x07c1a, 0x00000, 0x00000, 0x00000, 0x61289, 0x01840}, // CH3,13,14 + {0x243bc, 0xfc438, 0x07c1a, 0x00000, 0x00000, 0x00000, 0x6128b, 0x0fc41} // CH5-8 +#else + {0x643bc, 0xfc038, 0x77c1a, 0x00000, 0x00000, 0x00000, 0x41289, 0x01840}, // CH1,2,4,9,10,11,12 + {0x643bc, 0xfc038, 0x07c1a, 0x00000, 0x00000, 0x00000, 0x41289, 0x01840}, // CH3,13,14 + {0x243bc, 0xfc438, 0x07c1a, 0x00000, 0x00000, 0x00000, 0x4128b, 0x0fc41} // CH5-8 +#endif + }; + + + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_2G) + eRFPath = RF92CD_PATH_B; + else + eRFPath = RF92CD_PATH_A; + + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_5G){ + if (channel >=36 && channel <=140){ + if (!priv->pshare->CurrentChannelBW) + idx = 0; + else + idx = 1; + } else if (channel == 149 || channel == 155 || channel == 161) + idx = 2; + else if (channel==151 || channel==153 || channel==163 || channel==165) + idx = 3; + else if (channel==157 || channel==159) + idx = 4; + } else { + if (channel==1 || channel==2 || channel==4 || channel==9 || channel==10 || channel==11 || channel==12) + idx = 5; + else if (channel==3 || channel==13 || channel==14) + idx = 6; + else if (channel>=5 && channel<=8) + idx = 7; + } + + if (idx==-1){ + DEBUG_ERR("No suitable channel (%d) for setting synthersizer parameter!\n", channel); + return; + } + + for (i=0;i<8;i++){ +#ifdef CONFIG_RTL_92D_DMDP + if (i==0 && (idx>=0 && idx <=4) && + (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY)) + tmp = 0xe439d; + else +#endif + tmp = SYN_PARA[idx][i]; + + if (tmp!=0) { + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && eRFPath == RF92CD_PATH_B) { + DMDP_PHY_SetRFReg(1, RF92CD_PATH_A, (0x25+i), bMask20Bits, tmp); + //DEBUG_TRACE("DMDP_PHY_SetRFReg(1, %d, 0x%x, bMask20Bits, 0x%x)\n", eRFPath, (0x25+i), tmp); + } else +#endif + { + PHY_SetRFReg(priv, eRFPath, (0x25+i), bMask20Bits, tmp); + //DEBUG_TRACE("PHY_SetRFReg(priv, %d, 0x%x, bMask20Bits, 0x%x)\n", eRFPath, (0x25+i), tmp); + } + if (i==3) + priv->pshare->RegRF28[eRFPath] = tmp; + } + } +} + +unsigned int IMR_SET_N[3][11] = { + {0x00ff0, 0x4400f, 0x00ff0, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x64888, 0xe266c, 0x00090}, //G-mode + {0x22880, 0x4470f, 0x55880, 0x00070, 0x88000, 0x00000, 0x88080, 0x70000, 0x64a82, 0xe466c, 0x00090}, //36-64 + {0x44880, 0x4477f, 0x77880, 0x00070, 0x88000, 0x00000, 0x880b0, 0x00000, 0x64b82, 0xe466c, 0x00090}, // 100-165 +}; + +void SetIMR_n(struct rtl8192cd_priv *priv, unsigned char channel) +{ + unsigned int eRFPath, curMaxRFPath; + int imr_idx = -1; + unsigned char temp_800; + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + curMaxRFPath = RF92CD_PATH_B; + else +#endif + curMaxRFPath = RF92CD_PATH_MAX; + + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_2G) + imr_idx = 0; + else { + if (channel>=36 && channel <=64) + imr_idx = 1; + else + imr_idx = 2; + } + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0xf); + temp_800 = PHY_QueryBBReg(priv, rFPGA0_RFMOD, 0x0f000000); + PHY_SetBBReg(priv, rFPGA0_RFMOD, 0x0f000000, 0); + + for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { + int i; + + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, 0x70000); + //DEBUG_TRACE("IMR [0x00] %05x\n", PHY_QueryRFReg(priv, eRFPath, 0x00, bMask20Bits,1)); + //delay_us(5); + + for (i=0;i<11;i++) { + PHY_SetRFReg(priv, eRFPath, (0x2f+i), bMask20Bits, IMR_SET_N[imr_idx][i]); + //DEBUG_TRACE("IMR [0x%x] %05x\n", (0x2f+i), PHY_QueryRFReg(priv, eRFPath, (0x2f+i), bMask20Bits,1)); + //delay_us(5); + } + + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_2G) + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, 0x32fff); + else + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, 0x32c9a); + + //DEBUG_TRACE("IMR [0x00] %05x\n", PHY_QueryRFReg(priv, eRFPath, 0x00, bMask20Bits,1)); + //delay_us(5); + } + + PHY_SetBBReg(priv, rFPGA0_RFMOD, 0x0f000000, temp_800); + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0); +} + + +/* + * Follow WS-20101228-Willis-xxxx dynamic parameter-R00 + */ +void Update92DRFbyChannel(struct rtl8192cd_priv *priv, unsigned char channel) +{ +#ifdef RTL8192D_INT_PA + u8 eRFPath = 0, curMaxRFPath; + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + curMaxRFPath = RF92CD_PATH_B; + else + curMaxRFPath = RF92CD_PATH_MAX; + + if (priv->pshare->rf_ft_var.use_intpa92d){ + for(eRFPath = RF92CD_PATH_A; eRFPath pmib->dot11RFEntry.phyBandSelect==PHY_BAND_5G){ + if (channel>=36 && channel<=64){ + PHY_SetRFReg(priv, eRFPath, 0x0b, bMask20Bits, 0x01a00); + PHY_SetRFReg(priv, eRFPath, 0x48, bMask20Bits, 0x40443); + PHY_SetRFReg(priv, eRFPath, 0x49, bMask20Bits, 0x00eb5); + //PHY_SetRFReg(priv, eRFPath, 0x4a, bMask20Bits, 0x50f0f); + PHY_SetRFReg(priv, eRFPath, 0x4b, bMask20Bits, 0x89bec); + //PHY_SetRFReg(priv, eRFPath, 0x4c, bMask20Bits, 0x0dded); + PHY_SetRFReg(priv, eRFPath, 0x03, bMask20Bits, 0x94a12); + delay_us(10); + PHY_SetRFReg(priv, eRFPath, 0x04, bMask20Bits, 0x94a12); + PHY_SetRFReg(priv, eRFPath, 0x0e, bMask20Bits, 0x94a12); + }else if (channel>=100 && channel<=140){ + PHY_SetRFReg(priv, eRFPath, 0x0b, bMask20Bits, 0x01800); + PHY_SetRFReg(priv, eRFPath, 0x48, bMask20Bits, 0xc0443); + PHY_SetRFReg(priv, eRFPath, 0x49, bMask20Bits, 0x00730); + //PHY_SetRFReg(priv, eRFPath, 0x4a, bMask20Bits, 0x50f0f); + PHY_SetRFReg(priv, eRFPath, 0x4b, bMask20Bits, 0x896ee); + //PHY_SetRFReg(priv, eRFPath, 0x4c, bMask20Bits, 0x0dded); + PHY_SetRFReg(priv, eRFPath, 0x03, bMask20Bits, 0x94a52); + delay_us(10); + PHY_SetRFReg(priv, eRFPath, 0x04, bMask20Bits, 0x94a52); + PHY_SetRFReg(priv, eRFPath, 0x0e, bMask20Bits, 0x94a52); + }else if (channel>=149 && channel<=165){ + PHY_SetRFReg(priv, eRFPath, 0x0b, bMask20Bits, 0x01800); + PHY_SetRFReg(priv, eRFPath, 0x48, bMask20Bits, 0xc0443); + PHY_SetRFReg(priv, eRFPath, 0x49, bMask20Bits, 0x00730); + //PHY_SetRFReg(priv, eRFPath, 0x4a, bMask20Bits, 0x50f0f); + PHY_SetRFReg(priv, eRFPath, 0x4b, bMask20Bits, 0x896ee); + //PHY_SetRFReg(priv, eRFPath, 0x4c, bMask20Bits, 0x0dded); + PHY_SetRFReg(priv, eRFPath, 0x03, bMask20Bits, 0x94a12); + delay_us(10); + PHY_SetRFReg(priv, eRFPath, 0x04, bMask20Bits, 0x94a12); + PHY_SetRFReg(priv, eRFPath, 0x0e, bMask20Bits, 0x94a12); + } + }else{ + PHY_SetRFReg(priv, eRFPath, 0x0b, bMask20Bits, 0x1c000); + PHY_SetRFReg(priv, eRFPath, 0x03, bMask20Bits, 0x18c63); + delay_us(10); + PHY_SetRFReg(priv, eRFPath, 0x04, bMask20Bits, 0x18c63); + PHY_SetRFReg(priv, eRFPath, 0x0e, bMask20Bits, 0x18c67); + } + } + } +#endif + + if (priv->pmib->dot11RFEntry.phyBandSelect==PHY_BAND_5G){ + //update fc_area + if (priv->pmib->dot11RFEntry.dot11channel<149) + PHY_SetBBReg(priv, rOFDM1_CFOTracking, BIT(14) | BIT(13), 1); + else + PHY_SetBBReg(priv, rOFDM1_CFOTracking, BIT(14) | BIT(13), 2); + // VCO_BF_LDO= 1.12V->1.27V for 40M spur issue + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x2A, BIT(13)|BIT(12), 2); + // RX Ch36 40M spurs + if (channel==36){ + priv->pshare->RegRF28[RF92CD_PATH_A] &= (~BIT(6)); + priv->pshare->RegRF28[RF92CD_PATH_A] |= BIT(5); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x28, bMask20Bits, priv->pshare->RegRF28[RF92CD_PATH_A]); + //PHY_SetRFReg(priv, RF92CD_PATH_A, 0x28, BIT(6)|BIT(5), 0); + } + } else { + //update fc_area + PHY_SetBBReg(priv, rOFDM1_CFOTracking, BIT(14) | BIT(13), 0); + } + +} + +int Load_92D_Firmware(struct rtl8192cd_priv *priv) +{ + int fw_len, wait_cnt=0; + unsigned int CurPtr=0; + unsigned int WriteAddr; + unsigned int Temp; + unsigned char *ptmp; +#ifndef SMP_SYNC + unsigned long flags = 0; +#endif + +#ifdef CONFIG_RTL8672 + printk("val=%x\n",RTL_R8(0x80)); +#endif + +#ifdef MP_TEST + if (priv->pshare->rf_ft_var.mp_specific) + return TRUE; +#endif + + printk("===> %s\n", __FUNCTION__); + + SAVE_INT_AND_CLI(flags); + + printk("Firmware check %x(%x)\n", RTL_R32(MCUFWDL), (RTL_R8(MCUFWDL) & MCUFWDL_RDY)); + if (RTL_R8(MCUFWDL) & MCUFWDL_RDY){ + printk("<=== Firmware Downloaded\n"); + goto check_fwdl_rdy; + } + + wait_cnt=0; + while(RTL_R8(RF_CTRL) & FW_DL_INPROC){ + wait_cnt++; + delay_ms(50); + } + +#ifdef CONFIG_RTL_92D_DMDP + if (wait_cnt==0) { + if (priv->pshare->wlandev_idx == 0) + RTL_W8(RF_CTRL, RTL_R8(RF_CTRL)|FW_DL_INPROC); + else { + if (RTL_R8(RSV_MAC0_CTRL) & MAC0_EN) + goto check_fwdl_rdy; + else + RTL_W8(RF_CTRL, RTL_R8(RF_CTRL)|FW_DL_INPROC); + } + } else { + if (RTL_R8(MCUFWDL) & MCUFWDL_RDY){ + printk("<=== Firmware Downloaded\n"); + RESTORE_INT(flags); + return TRUE; + }else{ + RTL_W8(RF_CTRL, RTL_R8(RF_CTRL)|FW_DL_INPROC); + } + } +#else + if (wait_cnt==0) { + RTL_W8(RF_CTRL, RTL_R8(RF_CTRL)|FW_DL_INPROC); + } else { + if (RTL_R8(MCUFWDL) & MCUFWDL_RDY){ + printk("<=== Firmware Downloaded\n"); + RESTORE_INT(flags); + return TRUE; + }else{ + RTL_W8(RF_CTRL, RTL_R8(RF_CTRL)|FW_DL_INPROC); + } + } + +#endif + + if ((priv->pshare->fw_signature & 0xfff0 ) == 0x92D0) + ptmp = data_rtl8192dfw_n_start + RT_8192CD_FIRMWARE_HDR_SIZE; + else + ptmp = data_rtl8192dfw_n_start; + + fw_len = (int)(data_rtl8192dfw_n_end - ptmp); + printk("[%s][rtl8192dfw_n]\n",__FUNCTION__); + + // Disable SIC + RTL_W16(GPIO_MUXCFG, (RTL_R16(GPIO_MUXCFG) & 0xff) | HTP_EN); + delay_ms(1); + + // Enable MCU + RTL_W16(SYS_FUNC_EN, (RTL_R16(SYS_FUNC_EN) & 0x0ff) | FEN_MREGEN + | FEN_HWPDN | FEN_DIO_RF | FEN_ELDR | FEN_DCORE |FEN_CPUEN | FEN_PCIED); + delay_ms(1); + +#ifdef CONFIG_RTL8672 + RTL_W8(APS_FSMCO, RTL_R8(APS_FSMCO) | PFM_ALDN); + delay_ms(1); //czyao +#endif + + // Load SRAM + WriteAddr = 0x1000; + RTL_W8(MCUFWDL, RTL_R8(MCUFWDL) | MCUFWDL_EN); + delay_ms(1); + + RTL_W32(MCUFWDL, RTL_R32(MCUFWDL) & 0xfff0ffff); + + delay_ms(1); + + while (CurPtr < fw_len) { + if ((CurPtr+4) > fw_len) { + // Reach the end of file. + while (CurPtr < fw_len) { + Temp = *(ptmp + CurPtr); + RTL_W8(WriteAddr, (unsigned char)Temp); + WriteAddr++; + CurPtr++; + } + } else { + // Write FW content to memory. + Temp = *((unsigned int *)(ptmp + CurPtr)); + Temp = cpu_to_le32(Temp); + RTL_W32(WriteAddr, Temp); + WriteAddr += 4; + + if(WriteAddr == 0x2000) { + unsigned char tmp = RTL_R8(MCUFWDL+2); + tmp += 1; + WriteAddr = 0x1000; + RTL_W8(MCUFWDL+2, tmp) ; + delay_ms(10); +// printk("\n[CurPtr=%x, 0x82=%x]\n", CurPtr, RTL_R8(0x82)); + } + CurPtr += 4; + } + } + + watchdog_kick(); + + RTL_W8(TCR+3, 0x7f); + RTL_W8(MCUFWDL, (RTL_R8(MCUFWDL) & 0xfe) | MCUFWDL_RDY); + delay_ms(1); + //RTL_W8(RF_CTRL, RTL_R8(RF_CTRL) | BIT(6)); + RTL_W8(RF_CTRL, RTL_R8(RF_CTRL) & (~FW_DL_INPROC)); + delay_ms(1); + +check_fwdl_rdy: + + printk("<=== %s\n", __FUNCTION__); + // check if firmware is ready + wait_cnt = 0; +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pshare->wlandev_idx == 0) +#endif + { + while (!(RTL_R8(RSV_MAC0_FWCTRL) & MAC0_WINTINI_RDY)) { + if (++wait_cnt > 10) { + RTL_W8(MCUFWDL, RTL_R8(MCUFWDL) & (~MCUFWDL_RDY)); + RESTORE_INT(flags); + DEBUG_ERR("8192d mac0 firmware not ready\n"); + return FALSE; + } + delay_ms(2*wait_cnt); + } + } +#ifdef CONFIG_RTL_92D_DMDP + else { + while (!(RTL_R8(RSV_MAC1_FWCTRL) & MAC1_WINTINI_RDY)) { + if (++wait_cnt > 10) { + RTL_W8(MCUFWDL, RTL_R8(MCUFWDL) & (~MCUFWDL_RDY)); + RESTORE_INT(flags); + DEBUG_ERR("8192d mac1 firmware not ready\n"); + return FALSE; + } + delay_ms(2*wait_cnt); + + } + } +#endif + RESTORE_INT(flags); +#ifdef CONFIG_RTL8672 + printk("val=%x\n",RTL_R8(MCUFWDL)); +#endif + return TRUE; +} + + +/* + * 92DE Operation Mode + */ +void UpdateBBRFVal8192DE(struct rtl8192cd_priv *priv) +{ + u8 eRFPath = 0, curMaxRFPath; + //u32 u4RegValue=0; + + //Update BB + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + /* + * 5G + */ + //r_select_5G for path_A/B + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(16), 0x1); + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(0), 0x1); + //rssi_table_select:index 0 for 2.4G.1~3 for 5G + PHY_SetBBReg(priv, rOFDM0_AGCRSSITable, BIT(7) | BIT(6), 0x01); + //5G PA power on + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(31), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(6))>>6); + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(15), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(4))>>4); + + //TRSW.TRSWB and PAPE2G mode table + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY){ + // TRSW_2, TRSWB_2 + PHY_SetBBReg(priv, 0x870, BIT(22)|BIT(21), 0); + // PAPE2G_2 + PHY_SetBBReg(priv, 0x870, BIT(26), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(7))>>7); + PHY_SetBBReg(priv, 0x864, BIT(10), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(6))>>6); + } + // TRSW_1, TRSWB_1 + PHY_SetBBReg(priv, 0x870, BIT(6)|BIT(5), 0); + // PAPE2G_1 + PHY_SetBBReg(priv, 0x870, BIT(10), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(5))>>5); + PHY_SetBBReg(priv, 0x860, BIT(10), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(4))>>4); +#ifdef RTL8192D_INT_PA + if (!priv->pshare->rf_ft_var.use_intpa92d) +#endif + { + //5G PA power on + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(31), 0x1); + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(15), 0x1); + } + // 5G LNA on + PHY_SetBBReg(priv, 0xb30, 0x00f00000, 0x0); + //fc_area + if (priv->pmib->dot11RFEntry.dot11channel<149) + PHY_SetBBReg(priv, rOFDM1_CFOTracking, BIT(14) | BIT(13), 1); + else + PHY_SetBBReg(priv, rOFDM1_CFOTracking, BIT(14) | BIT(13), 2); + //cck_disable + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, 0x0); + //TX BB gain shift +#ifdef RTL8192D_INT_PA + if (priv->pshare->rf_ft_var.use_intpa92d){ + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, 0x2d4000b5); + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, 0x2d4000b5); + } else +#endif + { + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, 0x20000080); + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, 0x20000080); + } + // Reset IQC + PHY_SetBBReg(priv, 0xc94, 0xF0000000, 0); + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, 0xc9c, 0xF0000000, 0); + //BB/DP IQC + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x010170b8); + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x010170b8); + + } else { + /* + * 2.4G + */ + // r_select_5G for path_A/B + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(16), 0x0); + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(0), 0); + //rssi_table_select:index 0 for 2.4G.1~3 for 5G + PHY_SetBBReg(priv, rOFDM0_AGCRSSITable, BIT(7) | BIT(6), 0x00); + //5G PA power on + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(31), 0x0); + PHY_SetBBReg(priv, rFPGA0_XAB_RFParameter, BIT(15), 0x0); + + //TRSW.TRSWB and PAPE2G mode table + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY){ + // TRSW_2 + PHY_SetBBReg(priv, 0x870, BIT(21), (priv->pmib->dot11RFEntry.trsw_pape_C9 & BIT(7))>>7); + PHY_SetBBReg(priv, 0x864, BIT(5), (priv->pmib->dot11RFEntry.trsw_pape_C9 & BIT(6))>>6); + // TRSWB_2 + PHY_SetBBReg(priv, 0x870, BIT(22), (priv->pmib->dot11RFEntry.trsw_pape_C9 & BIT(5))>>5); + PHY_SetBBReg(priv, 0x864, BIT(6), (priv->pmib->dot11RFEntry.trsw_pape_C9 & BIT(4))>>4); + // PAPE2G_2 + PHY_SetBBReg(priv, 0x870, BIT(26), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(3))>>3); + PHY_SetBBReg(priv, 0x864, BIT(10), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(2))>>2); + } + // TRSW_1 + PHY_SetBBReg(priv, 0x870, BIT(5), (priv->pmib->dot11RFEntry.trsw_pape_C9 & BIT(3))>>3); + PHY_SetBBReg(priv, 0x860, BIT(5), (priv->pmib->dot11RFEntry.trsw_pape_C9 & BIT(2))>>2); + // TRSWB_1 + PHY_SetBBReg(priv, 0x870, BIT(6), (priv->pmib->dot11RFEntry.trsw_pape_C9 & BIT(1))>>1); + PHY_SetBBReg(priv, 0x860, BIT(6), (priv->pmib->dot11RFEntry.trsw_pape_C9 & BIT(0))>>0); + // PAPE2G_1 + PHY_SetBBReg(priv, 0x870, BIT(10), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(1))>>1); + PHY_SetBBReg(priv, 0x860, BIT(10), (priv->pmib->dot11RFEntry.trsw_pape_CC & BIT(0))>>0); + + // 5G LNA on + PHY_SetBBReg(priv, 0xb30, 0x00f00000, 0xa); + //fc_area + PHY_SetBBReg(priv, rOFDM1_CFOTracking, BIT(14) | BIT(13), 0x00); + //cck_enable + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, 0x1); + //TX BB gain shift + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, 0x40000100); + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, 0x40000100); + // Reset IQC + PHY_SetBBReg(priv, 0xc94, 0xF0000000, 0); + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, 0xc9c, 0xF0000000, 0); + //BB/DP IQC + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x01017038); + if (priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x01017038); + } + + //Update RF + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + curMaxRFPath = RF92CD_PATH_B; + else + curMaxRFPath = RF92CD_PATH_MAX; + + for(eRFPath = RF92CD_PATH_A; eRFPath pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) { + /* + * 5G + */ + priv->pshare->RegRF18[eRFPath] &= 0xffffff00; + priv->pshare->RegRF18[eRFPath] |= (BIT(16)|BIT(8)|0x24); //set channel 36 + PHY_SetRFReg(priv,eRFPath, rRfChannel,bMask20Bits, priv->pshare->RegRF18[eRFPath]); + delay_ms(1); + // LDO_DIV + priv->pshare->RegRF28[eRFPath] = RTL_SET_MASK(priv->pshare->RegRF28[eRFPath],BIT(7)|BIT(6),1,6); + //PHY_SetRFReg(priv,eRFPath, 0x28, BIT(7)|BIT(6), 0x01); + PHY_SetRFReg(priv,eRFPath, 0x28, bMask20Bits, priv->pshare->RegRF28[eRFPath]); + + delay_ms(30); + } else { + /* + * 2.4G + */ + priv->pshare->RegRF18[eRFPath] &= ~(BIT(16)|BIT(8)|0xFF); + priv->pshare->RegRF18[eRFPath] |= 1; //set channel 1. + PHY_SetRFReg(priv,eRFPath, rRfChannel,bMask20Bits, priv->pshare->RegRF18[eRFPath]); + delay_ms(1); + // LDO_DIV + priv->pshare->RegRF28[eRFPath] &= (~(BIT(7)|BIT(6))); + //PHY_SetRFReg(priv,eRFPath, 0x28, BIT(7)|BIT(6), 0x00); + PHY_SetRFReg(priv,eRFPath, 0x28, bMask20Bits, priv->pshare->RegRF28[eRFPath]); + + delay_ms(30); + } + } + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) { + //Use antenna 0 & 1 + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, bMaskByte0, 0x11); + PHY_SetBBReg(priv, rOFDM1_TRxPathEnable, bDWord, 0x1); + + //disable ad/da clock1 + if (!(DMDP_RTL_R8(0,SYS_FUNC_EN)&(FEN_BB_GLB_RST|FEN_BBRSTB))){ + DMDP_RTL_W8(0, SYS_FUNC_EN, (DMDP_RTL_R8(0,SYS_FUNC_EN)|FEN_BB_GLB_RST|FEN_BBRSTB)); + } + DMDP_PHY_SetBBReg(0, rFPGA0_AdDaClockEn, BIT(13)|BIT(12), 3); + } else +#endif + { + //Use antenna 0 & 1 + PHY_SetBBReg(priv, rOFDM0_TRxPathEnable, bMaskByte0, 0x33); + PHY_SetBBReg(priv, rOFDM1_TRxPathEnable, bDWord, 0x3); + + //disable ad/da clock1 + PHY_SetBBReg(priv, rFPGA0_AdDaClockEn, BIT(13) | BIT(12), 0); + } +} + + +#if 0 //def CLIENT_MODE +void clnt_save_IQK_res(struct rtl8192cd_priv *priv) +{ + priv->site_survey->bk_iqc[0] = PHY_QueryBBReg(priv,0xc80, bMaskDWord); + priv->site_survey->bk_iqc[1] = PHY_QueryBBReg(priv,0xc94, bMaskByte3); + priv->site_survey->bk_iqc[2] = PHY_QueryBBReg(priv,0xc4c, bMaskByte3); + priv->site_survey->bk_iqc[3] = PHY_QueryBBReg(priv,0xc88, bMaskDWord); + priv->site_survey->bk_iqc[4] = PHY_QueryBBReg(priv,0xc9c, bMaskByte3); + priv->site_survey->bk_iqc[5] = PHY_QueryBBReg(priv,0xc14, bMaskDWord); + priv->site_survey->bk_iqc[6] = PHY_QueryBBReg(priv,0xca0, bMaskByte3); + priv->site_survey->bk_iqc[7] = PHY_QueryBBReg(priv,0xc1c, bMaskDWord); + priv->site_survey->bk_iqc[8] = PHY_QueryBBReg(priv,0xc78, bMaskByte1); + priv->site_survey->bk_iqc[9] = PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x08, bMask20Bits, 1); + priv->site_survey->bk_iqc[10] = PHY_QueryRFReg(priv, RF92CD_PATH_B, 0x08, bMask20Bits, 1); +} + + +void clnt_load_IQK_res(struct rtl8192cd_priv *priv) +{ + PHY_SetBBReg(priv,0xc80, bMaskDWord, priv->site_survey->bk_iqc[0]); + PHY_SetBBReg(priv,0xc94, bMaskByte3, priv->site_survey->bk_iqc[1]); + PHY_SetBBReg(priv,0xc4c, bMaskByte3, priv->site_survey->bk_iqc[2]); + PHY_SetBBReg(priv,0xc88, bMaskDWord, priv->site_survey->bk_iqc[3]); + PHY_SetBBReg(priv,0xc9c, bMaskByte3, priv->site_survey->bk_iqc[4]); + PHY_SetBBReg(priv,0xc14, bMaskDWord, priv->site_survey->bk_iqc[5]); + PHY_SetBBReg(priv,0xca0, bMaskByte3, priv->site_survey->bk_iqc[6]); + PHY_SetBBReg(priv,0xc1c, bMaskDWord, priv->site_survey->bk_iqc[7]); + PHY_SetBBReg(priv,0xc78, bMaskByte1, priv->site_survey->bk_iqc[8]); + PHY_SetRFReg(priv,RF92CD_PATH_A, 0x08, bMask20Bits, priv->site_survey->bk_iqc[9]); + PHY_SetRFReg(priv,RF92CD_PATH_B, 0x08, bMask20Bits, priv->site_survey->bk_iqc[10]); +} + +#endif + +#ifdef CONFIG_RTL_92D_DMDP +#if 0 //def CLIENT_MODE + +void clnt_92D_2T_AGSwitch(struct rtl8192cd_priv * priv, int target) +{ + unsigned int flags, i; + int rtStatus = 0; + unsigned char temp_0522, temp_0550, temp_0551, temp_0800; + unsigned char reg; + + SAVE_INT_AND_CLI(flags); + + /* + * Save MAC default value + */ + temp_0522 = RTL_R8(0x522); + temp_0550 = RTL_R8(0x550); + temp_0551 = RTL_R8(0x551); + + /* + * MAC register setting + */ + RTL_W8(0x522, 0x3f); + RTL_W8(0x550, temp_0550& (~BIT(3))); + RTL_W8(0x551, temp_0551& (~BIT(3))); + + // stop BB + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0xf); + temp_0800 = PHY_QueryBBReg(priv, rFPGA0_RFMOD, 0x0f000000); + PHY_SetBBReg(priv, rFPGA0_RFMOD, 0x0f000000, 0); + + // 5G_PAPE Select & external PA power on + PHY_SetBBReg(priv, 0x878, BIT(0), 0); + PHY_SetBBReg(priv, 0x878, BIT(16), 0); + PHY_SetBBReg(priv, 0x878, BIT(15), 0); + PHY_SetBBReg(priv, 0x878, BIT(31), 0); + // RSSI Table Select + PHY_SetBBReg(priv, 0xc78, BIT(7)|BIT(6), 0); + // fc_area + PHY_SetBBReg(priv, 0xd2c, BIT(14)|BIT(13), 0); + // cck_enable + PHY_SetBBReg(priv, rFPGA0_RFMOD, bCCKEn, 0x1); + // LDO_DIV + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x28, BIT(7)|BIT(6), 0); + PHY_SetRFReg(priv, RF92CD_PATH_B, 0x28, BIT(7)|BIT(6), 0); + // MOD_AG // Set channel number + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x18, BIT(16), 0); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x18, BIT(8), 0); + PHY_SetRFReg(priv, RF92CD_PATH_B, 0x18, BIT(16), 0); + PHY_SetRFReg(priv, RF92CD_PATH_B, 0x18, BIT(8), 0); + // CLOAD for path_A + PHY_SetRFReg(priv, RF92CD_PATH_A, 0xB, BIT(16)|BIT(15)|BIT(14), 0x7); + PHY_SetRFReg(priv, RF92CD_PATH_B, 0xB, BIT(16)|BIT(15)|BIT(14), 0x7); + + // IMR + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x00, bMask20Bits, 0x70000); + for (i=0;i<11;i++) { + PHY_SetRFReg(priv, RF92CD_PATH_A, (0x2f+i), bMask20Bits, IMR_SET_N[0][i]); + } + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x00, bMask20Bits, 0x32fff); + + // Enable BB + PHY_SetBBReg(priv, rFPGA0_RFMOD, 0x0f000000, temp_0800); + // IQK + PHY_SetBBReg(priv, 0xc80, bMaskDWord, 0x40000100); + PHY_SetBBReg(priv, 0xc94, bMaskByte3, 0); + PHY_SetBBReg(priv, 0xc4c, bMaskByte3, 0); + PHY_SetBBReg(priv, 0xc88, bMaskDWord, 0x40000100); + PHY_SetBBReg(priv, 0xc9c, bMaskByte3, 0); + PHY_SetBBReg(priv, 0xc14, bMaskDWord, 0x40000100); + PHY_SetBBReg(priv, 0xca0, bMaskByte3, 0); + PHY_SetBBReg(priv, 0xc1c, bMaskDWord, 0x40000100); + PHY_SetBBReg(priv, 0xc78, bMaskByte1, 0); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x08, bMask20Bits, 0x84000); + PHY_SetRFReg(priv, RF92CD_PATH_B, 0x08, bMask20Bits, 0x84000); + + //Set related registers for BW config + + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0x00f00000, 0x0); + + /* + * Reload MAC default value + */ + RTL_W8(0x550, temp_0550); + RTL_W8(0x551, temp_0551); + RTL_W8(0x522, temp_0522); + + RESTORE_INT(flags); +} + +#endif + +#endif //CONFIG_RTL_92D_DMDP + +#endif // CONFIG_RTL_92D_SUPPORT + + + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192d_reg.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192d_reg.h new file mode 100755 index 000000000..be988fc70 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192d_reg.h @@ -0,0 +1,459 @@ +/* + * Header file of 8192D register + * + * $Id: 8192d_reg.h,v 1.2 2010/05/07 14:29:47 victoryman Exp $ + * + * Copyright (c) 2010 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192D_REG_H_ +#define _8192D_REG_H_ + +//============================================================ +// 8192D Regsiter offset definition +//============================================================ + + +/* + * Project RTL8192d follows most of registers in Project RTL8192c + * This file includes additional registers for RTL8192d only + * Header file of RTL8192C registers should always be included + */ + + +/* + * Register 0x2C overlaps Project RTL8192c + */ +#define MAC_PHY_CTRL_T 0x2C // DMDP,SMSP,DMSP contrl +#define MAC_PHY_CTRL_MP 0xF8 // DMDP,SMSP,DMSP contrl + +#define TXDMA_DBG 0x218 // TXDMA debug port +#define BIST_START_PAUSE 0x240 +#define D_BIST_RDY 0x244 +#define D_BIST_FAIL 0x248 +#define D_BIST_RPT 0x24C // BIST Report +#define MAC_SEL 0x250 // Mac Select +#define RXDMA_DBG 0x28C // RXDMA debug port +#define BT_COEX_GLB_CTRL 0x2C0 // Bt-Coexistence Control +#define BT_COEX_TBL 0x2C4 // BT-Coexistence Arbiter Decision Table +#define BT_SSI 0x2D4 // Bt Signal Strength Index +#define BT_COEXT_CSR_ENH_INTF_CTRL 0x2D6 // Bt-Coexistence CSR Enhanced Interface Control +#define BT_ACT_STATS 0x2D8 // Bt Activity Statistics +#define BT_CMD_WLAN_RPT 0x2E0 // Bt Command Report from WLAN +#define BT_CMD_BT_RPT 0x2E1 // Bt Command Report from BT +#define BT_CMD_LATCH 0x2E2 // Bt Command Data Latched + +#define EARLY_MODE_CTRL 0x4D0 // Early mode control +#define OTHERMAC_TBTTBK_CRTL 0x4D8 // Dis tbttbk othermac +#define PTCL_PKT_NUM 0x4E3 // Pkt nums in protocol function +#define PTCL_DBG 0x4E4 // Ptcl debug port +#define DROP_PKT_NUM 0x4E8 // Tx drop pkt num +#define LIFT_DROP_NUM 0x4EA // Lift drop pkt num + +#define Pkt_Lifetime_CTRL 0x528 // Packet Lifetime Control +#define SCH_TXCMD_NOA 0x5CF // Tx_Cmd_Sel and Noa_Sel +#define SCH_DBG 0x5DC // Scheduler Debug Port +#define DMR 0x5F0 // Dual MAC Co-Existence +#define D_SCH_TXCMD 0x5F8 // TX_CMD Register + +/* + * Register 0x6C0-6CF overlaps Project RTL8192c + */ +#define WL_PRI_MASK 0x6C0 // WLAN Activity Priority Mask +#define BT_COEX_CTRL 0x6C4 // BT-Coexistence Control + + +#define MACID1 0x700 // MAC ID1 Register (Offset 0700h~0705h) + +#define SW_AES_REG 0x750 // Sw Access Aes Engine Data in/Data out/Security key Register +#define SW_AES_CONF 0x760 // Sw Access Aes Engine configure +#define WLAN_ACT_MSK_CTRL 0x768 +#define WMAC_DBG 0x77C // WMAC DBG + +//---------------------------------------------------------------------------- +// 8192D DUALMAC_DUALPHY special bits +//---------------------------------------------------------------------------- +#define RSV_MAC0_CTRL 0x081 // bit-7 for mac0 enable +#define RSV_MAC1_CTRL 0x053 // bit-0 for mac1 enable +#define MAC0_EN BIT(7) // 1 for MAC0 enable +#define BAND_STAT BIT(1) // 0:5G; 1:2G +#define MAC1_EN BIT(0) // 1 for MAC1 enable +#define RSV_MAC0_FWCTRL 0x018 // bit-0 for MAC0_WINTINI_RDY +#define RSV_MAC1_FWCTRL 0x01a // bit-0 for MAC1_WINTINI_RDY +#define MAC0_WINTINI_RDY BIT(0) // 1: init ready +#define MAC1_WINTINI_RDY BIT(0) // 1: init ready + + +//---------------------------------------------------------------------------- +// 8192D RF_CTRL bits (Offset 0x1F, 8 bits) +//---------------------------------------------------------------------------- +#define FW_DL_INPROC BIT(5) // 1 for firmware download inprogress + +//---------------------------------------------------------------------------- +// 8192D MAC_PHY_CTRL bits (Offset 0x2C, 8 bits) +//---------------------------------------------------------------------------- +#define VAUX_EN BIT(4) // 1 for the system supporting aux power +#define R_SINGLE_FUNC BIT(3) // 1 to force PCIE in single function mode +#define SUPER_MAC_EN BIT(2) // 1 to enable super mac mode +#define DUAL_PHY_EN BIT(1) // 1 to enable dual phy mode +#define DUAL_MAC_EN BIT(0) // 1 to enable dual mac mode + + + +//---------------------------------------------------------------------------- +// 8192D LEDCFG bits (Offset 0x4C-4F, 32 bits) +//---------------------------------------------------------------------------- + +#define LED2DIS_92D BIT(23) // LED2 Disabled for analog signal usage, + // 1: disable (input mode), 0:Enable (output mode). +#define LED2SV_92D BIT(19) // LED2 software value. +#define LED1DIS_92D BIT(15) // LED1 Disabled for analog signal usage, + // 1: disable (input mode), 0:Enable (output mode). +#define LED1SV_92D BIT(11) // LED1 software value. +#define LED0DIS_92D BIT(7) // LED0 Disabled for analog signal usage, + // 1: disable (input mode), 0:Enable (output mode). +#define LED0SV_92D BIT(3) // LED0 software value. +#define LED1CM_SHIFT_92D 16 + + + +//---------------------------------------------------------------------------- +// 8192D BIST_START_PAUSE bits (Offset 0x240-243, 32 bits) +//---------------------------------------------------------------------------- +#define BSP_PCIE_PDATASRAM_REAL BIT(30) +#define BSP_PCIE_PHDRSRAM0 BIT(29) +#define TXDMA_BSP_MAC1 BIT(28) +#define TXLLT_BSP_MAC1 BIT(27) +#define TXOQT_BSP_MAC1 BIT(26) +#define TXPKT_BSP_MAC1 BIT(25) +#define RXPKT_BSP_MAC1 BIT(24) +#define TXDBUF_BSP_MAC1 BIT(23) +#define TXFIFO_BSP_MAC1 BIT(22) +#define RXFIFO_BSP_MAC1 BIT(21) +#define WOL_BSP_MAC1 BIT(20) +#define KEY_BSP_MAC1 BIT(19) +#define RXBA_BSP_MAC1 BIT(18) +#define RC4_SBOX1_BSP_MAC1 BIT(17) +#define RC4_SBOX0_BSP_MAC1 BIT(16) +#define BSP_PCIE_PHDRSRAM1 BIT(15) +#define BSP_PCIE_RTYRAM_REAL BIT(14) +#define BSP_PCIE_RTYSOTRAM BIT(13) +#define TXDMA_BSP_MAC0 BIT(12) +#define TXLLT_BSP_MAC0 BIT(11) +#define TXOQT_BSP_MAC0 BIT(10) +#define TXPKT_BSP_MAC0 BIT(9) +#define RXPKT_BSP_MAC0 BIT(8) +#define TXDBUF_BSP_MAC0 BIT(7) +#define TXFIFO_BSP_MAC0 BIT(6) +#define RXFIFO_BSP_MAC0 BIT(5) +#define WOL_BSP_MAC0 BIT(4) +#define KEY_BSP_MAC0 BIT(3) +#define RXBA_BSP_MAC0 BIT(2) +#define RC4_SBOX1_BSP_MAC0 BIT(1) +#define RC4_SBOX0_BSP_MAC0 BIT(0) + +//---------------------------------------------------------------------------- +// 8192D D_BIST_RDY bits (Offset 0x244-247, 32 bits) +//---------------------------------------------------------------------------- +#define BD_PCIE_PDATASRAM_REAL BIT(30) +#define BD_PCIE_PHDRSRAM0 BIT(29) +#define TXDMA_BD_MAC1 BIT(28) +#define TXLLT_BD_MAC1 BIT(27) +#define TXOQT_BD_MAC1 BIT(26) +#define TXPKT_BD_MAC1 BIT(25) +#define RXPKT_BD_MAC1 BIT(24) +#define TXDBUF_BD_MAC1 BIT(23) +#define TXFIFO_BD_MAC1 BIT(22) +#define RXFIFO_BD_MAC1 BIT(21) +#define WOL_BD_MAC1 BIT(20) +#define KEY_BD_MAC1 BIT(19) +#define RXBA_BD_MAC1 BIT(18) +#define RC4_SBOX1_BD_MAC1 BIT(17) +#define RC4_SBOX0_BD_MAC1 BIT(16) +#define BD_PCIE_PHDRSRAM1 BIT(15) +#define BD_PCIE_RTYRAM_REAL BIT(14) +#define BD_PCIE_RTYSOTRAM BIT(13) +#define TXDMA_BD_MAC0 BIT(12) +#define TXLLT_BD_MAC0 BIT(11) +#define TXOQT_BD_MAC0 BIT(10) +#define TXPKT_BD_MAC0 BIT(9) +#define RXPKT_BD_MAC0 BIT(8) +#define TXDBUF_BD_MAC0 BIT(7) +#define TXFIFO_BD_MAC0 BIT(6) +#define RXFIFO_BD_MAC0 BIT(5) +#define WOL_BD_MAC0 BIT(4) +#define KEY_BD_MAC0 BIT(3) +#define RXBA_BD_MAC0 BIT(2) +#define RC4_SBOX1_BD_MAC0 BIT(1) +#define RC4_SBOX0_BD_MAC0 BIT(0) + +//---------------------------------------------------------------------------- +// 8192D D_BIST_FAIL bits (Offset 0x248-24B, 32 bits) +//---------------------------------------------------------------------------- +#define BF_PCIE_PDATASRAM_REAL BIT(30) +#define BF_PCIE_PHDRSRAM0 BIT(29) +#define TXDMA_BF_MAC1 BIT(28) +#define TXLLT_BF_MAC1 BIT(27) +#define TXOQT_BF_MAC1 BIT(26) +#define TXPKT_BF_MAC1 BIT(25) +#define RXPKT_BF_MAC1 BIT(24) +#define TXDBUF_BF_MAC1 BIT(23) +#define TXFIFO_BF_MAC1 BIT(22) +#define RXFIFO_BF_MAC1 BIT(21) +#define WOL_BF_MAC1 BIT(20) +#define KEY_BF_MAC1 BIT(19) +#define RXBA_BF_MAC1 BIT(18) +#define RC4_SBOX1_BF_MAC1 BIT(17) +#define RC4_SBOX0_BF_MAC1 BIT(16) +#define BF_PCIE_PHDRSRAM1 BIT(15) +#define BF_PCIE_RTYRAM_REAL BIT(14) +#define BF_PCIE_RTYSOTRAM BIT(13) +#define TXDMA_BF_MAC0 BIT(12) +#define TXLLT_BF_MAC0 BIT(11) +#define TXOQT_BF_MAC0 BIT(10) +#define TXPKT_BF_MAC0 BIT(9) +#define RXPKT_BF_MAC0 BIT(8) +#define TXDBUF_BF_MAC0 BIT(7) +#define TXFIFO_BF_MAC0 BIT(6) +#define RXFIFO_BF_MAC0 BIT(5) +#define WOL_BF_MAC0 BIT(4) +#define KEY_BF_MAC0 BIT(3) +#define RXBA_BF_MAC0 BIT(2) +#define RC4_SBOX1_BF_MAC0 BIT(1) +#define RC4_SBOX0_BF_MAC0 BIT(0) + +//---------------------------------------------------------------------------- +// 8192D D_BIST_RPT bits (Offset 0x24C-24F, 32 bits) +//---------------------------------------------------------------------------- +#define D_MAC_BIST_FAIL BIT(31) // At leaset one mac BIST FAIL +#define D_USB_IRAM_FAIL BIT(30) +#define D_USB_RAM1_FAIL BIT(29) +#define D_USB_RAM2_FAIL BIT(28) +#define D_USB_PRAM_FAIL BIT(27) +#define D_USB_PROM_FAIL BIT(26) +#define D_USB_RXDMA_FAIL_MAC0 BIT(25) +#define D_USB_RXDMA_FAIL_MAC1 BIT(24) +#define D_PCIE_PD_BIST_FAIL BIT(20) +#define D_PCIE_PH0_BIST_FAIL BIT(19) +#define D_PCIE_PH1_BIST_FAIL BIT(18) +#define D_PCIE_RETRY_BIST_FAIL BIT(17) +#define D_PCIE_SOT_BIST_FAIL BIT(16) +#define D_MAC_BIST_RDY BIT(10) +#define D_USB_BIST_RDY BIT(9) +#define D_PCIE_BIST_RDY BIT(8) +#define D_MAC_BIST_START BIT(2) +#define D_USB_BIST_START BIT(1) +#define D_PCIE_BIST_START BIT(0) + +//---------------------------------------------------------------------------- +// 8192D MAC_SEL bits (Offset 0x250-253, 32 bits) +//---------------------------------------------------------------------------- +#define SIC_LBK_MAC_SEL BIT(3) +#define MAC0_TXRPT_SEL_8051 BIT(2) // Mac0/1 tx report selection +#define MAC0_SEL_MACPHY BIT(1) // Mac0/1 phy seletion +#define R_MAC0_SEL_DBG BIT(0) // Mac0/1 debug port selection + +//---------------------------------------------------------------------------- +// 8192D BT_COEX_GLB_CTRL bits (Offset 0x2C0-2C3, 32 bits) +//---------------------------------------------------------------------------- +#define ERR_CHK_TH_Shift 24 // In RTK 2wire mode, the interval of bt clock will be counted to check whether the communication functions well. This register indicates the check threshold. +#define ERR_CHK_TH_Mask 0x0FF +#define ARB_WIN_WL_Shift 16 // Arbitration window if WLAN device active first +#define ARB_WIN_WL_Mask 0x0FF +#define ARB_WIN_BT_Shift 8 // Arbitration window if bluetooth device active first +#define ARB_WIN_BT_Mask 0x0FF +#define CSR_2W BIT(7) // indicates whether the current operating mode is CSR 2-wire coexstence, which is only available when r_BT_MODE = 2'b10 and r_ENHBT = 1'b0. +#define ANT_SEL_Shift 5 // 2 bits indicates the antenna usage of the wireless and bluetooth device, bit[0] for WL device, bit[1] for BT device 0: use ant a; 1: use ant b +#define ANT_SEL_Mask 0x03 +#define WL_BAND_Shift 3 // Indicating the operating band of the chip, bit[0] for a path, bit[1] for b path; 0: 2.4G; 1: 5G +#define WL_BAND_Mask 0x03 +#define STATIS_BT_RST BIT(2) // Reset BT_ACT_STATISTICS Counters. Write ¡§1¡¨ pulse. +#define STATIS_BT_EN BIT(1) // bit is set, the BT_ACT_STATISTICS counters starts counting +#define ENHBT BIT(0) // Used with r_BT_MODE to select Enhanced BT mode + +//---------------------------------------------------------------------------- +// 8192D BT_SSI bits (Offset 0x2D4-2D5, 16 bits) +//---------------------------------------------------------------------------- +#define BT_TSSI_Shift 8 // BT tx signal strength index +#define BT_TSSI_Mask 0x03F +#define BT_RSSI_Shift 0 // BT rx signal strength index +#define BT_RSSI_Mask 0x03F + +//---------------------------------------------------------------------------- +// 8192D BT_COEXT_CSR_ENH_INTF_CTRL bits (Offset 0x2D6-2D7, 16 bits) +//---------------------------------------------------------------------------- +#define BT_TRX_DELAY_Shift 8 // When BT_PRI is high, if BT goes low from high, then BT will TX after BT_TX_DELAY time. WLAN can pause WLAN TX or RX after this delay to avoid impacting on BT. Unit: 8us +#define BT_TRX_DELAY_Mask 0x0F +#define BT_TRX_INIT_DETECT_Shift 4 // After BT_PRI asserting for BT_TRX_INIT_DETECT us, if BT_STAT is low, then BT will receive packets; otherwise, if BT goes high, BT will TX data. Unit 4us. +#define BT_TRX_INIT_DETECT_Mask 0x0F +#define BT_PRI_DETECT_TO_Shift 0 // After BT_PRI asserting, if BT_STAT is asserted within this TO duration, BT will initiate high priority activities; otherwise, if BT_STAT is not asserted within this duration, it would be low priority activities. Units 1us. +#define BT_PRI_DETECT_TO_Mask 0x0F + +//---------------------------------------------------------------------------- +// 8192D BT_ACT_STATS bits (Offset 0x2D8-2DF, 64 bits) +//---------------------------------------------------------------------------- +#define STATS_BT_LO_RX_Shift 16 // Counters for BT low priority RX. It counts up when STATIS_BT_EN is set. This counter will reset when STTIS_BT_RST is written by 1 pulse. This counter cannot wrap around when overflow occurs. Under overflow, this counter is kept with 0xFFFF. +#define STATS_BT_LO_RX_Mask 0x0FFFF +#define STATS_BT_LO_TX_Shift 0 // Counters for BT low priority TX. It counts up when STATIS_BT_EN is set. This counter will reset when STATIS_BT_RST is written by 1 pulse. This counter cannot wrap around when overflow occurs. Under overflow, this counter is kept with 0xFFFF. +#define STATS_BT_LO_TX_Mask 0x0FFFF + +#define STATS_BT_HI_RX_Shift 16 // Counters for BT high priority RX. It counts up when STATIS_BT_EN is set. This counter will reset when STATIS_BT_RST is written by 1 pulse. This counter cannot wrap around when overflow occurs. Under overflow, this counter is kept with 0xFFFF. +#define STATS_BT_HI_RX_Mask 0x0FFFF +#define STATS_BT_HI_TX_Shift 0 // Counters for BT high priority TX. It counts up when STATIS_BT_EN is set. This counter will reset when STATIS_BT_RST is written by 1 pulse. This counter cannot wrap around when overflow occurs. Under overflow, this counter is kept with 0xFFFF. +#define STATS_BT_HI_TX_Mask 0x0FFFF + +//---------------------------------------------------------------------------- +// 8192D BT_CMD_LATCH bits (Offset 0x2E2-2E3, 16 bits) +//---------------------------------------------------------------------------- +#define BT_CMD_BT_STAT_Shift 8 // Latched data from BT_STAT after CMD pattern is matched. +#define BT_CMD_BT_STAT_Mask 0x0FF +#define BT_CMD_BT_PRI_Shift 0 // Latched data from BT_PRI after CMD pattern is matched. +#define BT_CMD_BT_PRI_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192D EARLY_MODE_CTRL bits (Offset 0x4D0-4D3, 32 bits) +//---------------------------------------------------------------------------- +#define SINGLE_AMPDU_EN BIT(31) // Single pkt will be tx as single ampdu if enabled +#define SINGLE_LEN_TH_Shift 8 // Early mode work on if (single ampdu > thd), default: 512B +#define SINGLE_LEN_TH_Mask 0x07FF +#define EARLY_MODE_EN_Shift 0 // Early mode enable for {BK, BE, VI, VO} +#define EARLY_MODE_EN_Mask 0x0F + +//---------------------------------------------------------------------------- +// 8192D OTHERMAC_TBTTBK_CRTL bits (Offset 0x4D8-4DB, 32 bits) +//---------------------------------------------------------------------------- +#define DIS_TBTTBK_OTHERMAC BIT(0) // Ptcl gen cmd will not cross the othermac's tbtt if set 0 + +//---------------------------------------------------------------------------- +// 8192D Pkt_Lifetime_CTRL bits (Offset 0x528-52A, 24 bits) +//---------------------------------------------------------------------------- +#define EN_NAVEND_RST_TXOP BIT(17) // set this bit, TXOP will be reset while NAV end. +#define EN_FILTER_CCA BIT(16) // Enable CCA filter threshold +#define CCA_FILTER_THRS_Shift 8 // CCA filter threshold value +#define CCA_FILTER_THRS_Mask 0x0FF +#define EDCCA_THRS_Shift 0 // EDCCA threshold value +#define EDCCA_THRS_Mask 0x0FF + +//---------------------------------------------------------------------------- +// 8192D SCH_TXCMD_NOA bits (Offset 0x5CF, 8 bits) +//---------------------------------------------------------------------------- +#define NOA_SEL BIT(4) // Noa1 and noa2 parameter select +#define SCH_TXCMD_SEL_Shift 0 // Select to read which dword of tx_cmd +#define SCH_TXCMD_SEL_Mask 0x0F + +//---------------------------------------------------------------------------- +// 8192D DMR bits (Offset 0x5F0-5F1, 16 bits) +//---------------------------------------------------------------------------- +#define DMR_R_DIS_TXOVER_TBTT_OTHERMAC BIT(8) //set 1, the packet can¡¦t be sent out whose pkt and nav time will be over the tbtt of the other mac +#define DMR_R_BLOCK_BY_SETBCN BIT(7) // tx backoff reset at tbtt of the other MAC in both DMDP and DMSP mode to prevent bcn tx blocked by the tx of the other mac +#define DMR_R_BLOCK_BY_TXPTCLACT BIT(6) // tx blocked by txptcl_active of the other MAC in DMSP mode to protect the whole tx procedure including rx response +#define DMR_R_BLOCK_BY_TXNAV BIT(5) // 1 to enable the co-existence mechanism for blocking Tx to protect rx response and NAV by TXNAV of another MAC in both DMDP and DMSP modes. +#define DMR_R_BLOCK_BY_TXON BIT(4) // 1 to enable the co-existence mechanism for blocking Tx by another MAC Tx in both DMDP and DMSP modes. +#define DMR_R_BLOCK_BY_RXNAV BIT(3) // 1 to enable the co-existence mechanism for blocking Tx to protect tx response and txop by RXNAV of another MAC in both DMDP and DMSP modes. +#define DMR_R_BLOCK_BY_EDCCA BIT(2) // 1 to enable the co-existence mechanism for blocking Tx by EDCCA of another MAC in DMDP mode. +#define DMR_R_BLOCK_BY_RXON BIT(1) // 1 to enable the co-existence mechanism for blocking Tx by another MAC Rx in DMDP mode +#define DMR_R_INTFR_COEXIST_EN BIT(0) // 1 to enable dual MAC co-existence mechanism for avoiding RF interference in DMDP mode. + +//---------------------------------------------------------------------------- +// 8192D WL_PRI_MASK bits (Offset 0x6C0-6C3, 32 bits) +//---------------------------------------------------------------------------- +#define PRI_MASK_WAITRESP BIT(28) // Priority Mask for RX Response Packet +#define PRI_MASK_RXOFDM BIT(27) // Priority Mask for RX OFDM +#define PRI_MASK_RXCCK BIT(26) // Priority Mask for RX CCK +#define PRI_MASK_TXAC_Shift 19 // Priority Mask for Tx Queue +#define PRI_MASK_TXAC_Mask 0x07F +#define PRI_MASK_NAV_Shift 11 // Priority Mask for TX NAV +#define PRI_MASK_NAV_Mask 0x0FF +#define PRI_MASK_TXCCK BIT(10) // Priority Mask for TX CCK +#define PRI_MASK_TXOFDM BIT(9) // Priority Mask for TX OFDM +#define PRI_MASK_RTY BIT(8) // Priority Mask for Tx Retry Packet +#define PRI_MASK_NUM_Shift 4 // Priority Mask for Tx packet number +#define PRI_MASK_NUM_Mask 0x0F +#define PRI_MASK_NEAR_TBTT BIT(2) // Priority Mask for near tbtt +#define PRI_MASK_TX_RESP BIT(1) // Priority Mask for Tx Response Packet +#define PRI_MASK_RX_RESP BIT(0) // Priority Mask for RX Response Packet + +//---------------------------------------------------------------------------- +// 8192D BT_COEX_CTRL bits (Offset 0x6C4-6C7, 32 bits) +//---------------------------------------------------------------------------- +#define PROTECT_RX_RSP BIT(11) // When wlan tx packets, this bit decides whether WLAN_ACT to BT device will overprotect wlan active not be interfered until rx response frame finish. +#define WLRX_TER_BY_CTL BIT(10) // When wlan receive a control packet without fit address, whether the signal indicating wlan rx can be terminated as soon as the address check finish is not only controlled by r_WLRX_TER_BY_AD, but also should be refered to this bit. +#define WLRX_TER_BY_AD BIT(9) // When wlan receive the packet without fit address, the signal indicating wlan rx can be terminated as soon as the address check finish. This feature can be enabled by this bit. +#define D_OOB BIT(8) // indicates the BT is out of the band of WLAN device. It's available only when r_BT_MODE is not the 2wire mode +#define WL_CHNNL_Shift 2 // WLAN channel information only for 2.4G band +#define WL_CHNNL_Mask 0x03F +#define RX_ISO_OK BIT(1) // Isolation check result if OOB is true when WLAN is RX. 1: pass; 0: fail +#define TX_ISO_OK BIT(0) // Isolation check result if OOB is true when WLAN is TX. 1: pass; 0: fail + +//---------------------------------------------------------------------------- +// 8192D SW_AES_CONF bits (Offset 0x760, 8 bits) +//---------------------------------------------------------------------------- +#define SET_SWAES_REG BIT(7) // Set software aes engine request,to start aes engine calculation +#define CLR_SWAES_REQ BIT(6) // Clear software aes engine request +#define R_WMAC_SWAES_WE BIT(3) // Write enable of register ro_WMAC_SWAES_RD +#define R_WMAC_SWAES_SEL BIT(0) // 1,the content of register 0750-075F used to be aes engine data in or data out; 0, the content of register 0750-075F uesed to be aes engine security key + +//---------------------------------------------------------------------------- +// 8192D WLAN_ACT_MSK_CTRL bits (Offset 0x768-76E, 56 bits) +//---------------------------------------------------------------------------- +#define GNTALL_WL_MASK BIT(19) // bit indicates whether to grant all devices or bt device only when WLAN_ACT Mask active. +#define WL_ACT_MASK_Enable BIT(17) // Enable WLAN_ACT Mask Function +//XXX +#define WACTMSK_RX_RESP_ON_DUR_Shift 7 +#define WACTMSK_RX_RESP_ON_DUR_Mask 0x03 + +#define WACTMSK_TX_DATA_OFF_DUR_Shift 24 +#define WACTMSK_TX_DATA_OFF_DUR_Mask 0x0FF +#define WACTMSK_TX_DATA_ON_DUR_Shift 16 +#define WACTMSK_TX_DATA_ON_DUR_Mask 0x0FF +#define WACTMSK_TX_RESP_OFF_DUR_Shift 8 +#define WACTMSK_TX_RESP_OFF_DUR_Mask 0x0FF +#define WACTMSK_TX_RESP_ON_DUR_Shift 0 +#define WACTMSK_TX_RESP_ON_DUR_Mask 0x0FF + + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(EN_EFUSE) + +#define EEPROM_MAC0_MACADDRESS 0x55 // MAC-0 MAC Address +#define EEPROM_MAC1_MACADDRESS 0x5B // MAC-1 MAC Address + +#define EEPROM_2G_TxPowerCCK 0x61 // 2.4G CCK Tx Power base +#define EEPROM_2G_TxPowerHT40_1S 0x67 // 2.4G HT40 Tx Power base +#define EEPROM_2G_TxPowerHT40_2SDiff 0x6D // 2.4G HT40 Tx Power diff +#define EEPROM_2G_TxPowerHT20Diff 0x70 // 2.4G HT20 Tx Power diff +#define EEPROM_2G_TxPowerOFDMDiff 0x73 // 2.4G OFDM Tx Power diff + +#define EEPROM_5GL_TxPowerHT40_1S 0x7C // 5G Ch.36-44 HT40 Tx Power base +#define EEPROM_5GL_TxPowerHT40_2SDiff 0x82 // 5G Ch.36-44 HT40 Tx Power diff +#define EEPROM_5GL_TxPowerHT20Diff 0x85 // 5G Ch.36-44 HT20 Tx Power diff +#define EEPROM_5GL_TxPowerOFDMDiff 0x88 // 5G Ch.36-44 OFDM Tx Power diff + +#define EEPROM_5GM_TxPowerHT40_1S 0x91 // 5G Ch.100-112 HT40 Tx Power base +#define EEPROM_5GM_TxPowerHT40_2SDiff 0x97 // 5G Ch.100-112 HT40 Tx Power diff +#define EEPROM_5GM_TxPowerHT20Diff 0x9A // 5G Ch.100-112 HT20 Tx Power diff +#define EEPROM_5GM_TxPowerOFDMDiff 0x9D // 5G Ch.100-112 OFDM Tx Power diff + +#define EEPROM_5GH_TxPowerHT40_1S 0xA6 // 5G Ch.149-153 HT40 Tx Power base +#define EEPROM_5GH_TxPowerHT40_2SDiff 0xAC // 5G Ch.149-153 HT40 Tx Power diff +#define EEPROM_5GH_TxPowerHT20Diff 0xAF // 5G Ch.149-153 HT20 Tx Power diff +#define EEPROM_5GH_TxPowerOFDMDiff 0xB2 // 5G Ch.149-153 OFDM Tx Power diff + +#define EEPROM_92D_IQK_DELTA 0xBC +#define EEPROM_92D_LCK_DELTA 0xBC +#define EEPROM_92D_XTAL_K 0xBD //[7:0] +#define EEPROM_92D_TSSI_A_5G 0xBE +#define EEPROM_92D_TSSI_B_5G 0xBF +#define EEPROM_92D_TSSI_AB_5G 0xC0 +#define EEPROM_92D_THERMAL_METER 0xC3 //[4:0] +#define EEPROM_92D_TRSW_CTRL 0xC9 +#define EEPROM_92D_PAPE_CTRL 0xCC + +#endif + + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192e_reg.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192e_reg.h new file mode 100755 index 000000000..dcb3dd1be --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8192e_reg.h @@ -0,0 +1,537 @@ +/* + * Header file of 8188E register + * + * $Id: 8188e_reg.h,v 1.1 2011/06/30 11:02:56 victoryman Exp $ + * + * Copyright (c) 2011 Realtek Semiconductor Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _8192E_REG_H_ +#define _8192E_REG_H_ + +//============================================================ +// 8188E Regsiter offset definition +//============================================================ + + +/* + * Project RTL8188E follows most of registers in Project RTL8192c + * This file includes additional registers for RTL8188E only + * Header file of RTL8192C registers should always be included + */ + +// +// 1. System Configure Register. (Offset 0x000 - 0x0FFh) +// +#define REG_92E_BB_PAD_CTRL 0x64 +#define REG_92E_HMEBOX_E0 0x88 +#define REG_92E_HMEBOX_E1 0x8A +#define REG_92E_HMEBOX_E2 0x8C +#define REG_92E_HMEBOX_E3 0x8E +#define REG_92E_WLLPS_CTRL 0x90 +#define REG_92E_RPWM2 0x9E +#define REG_92E_HIMR 0xB0 +#define REG_92E_HISR 0xB4 +#define REG_92E_HIMRE 0xB8 +#define REG_92E_HISRE 0xBC +#define REG_92E_EFUSE_DATA1 0xCC +#define REG_92E_EFUSE_DATA0 0xCD +#define REG_92E_EPPR 0xCF + +#define REG_92E_TQPNT1 0x218 +#define REG_92E_TQPNT2 0x21C +#define REG_92E_TDECTRL1 0x228 +#define REG_92E_WATCHDOG 0x35C +#define REG_92E_VOQ_IDX 0x310 +#define REG_92E_VIQ_IDX 0x314 +#define REG_92E_MGQ_DESA 0x318 +#define REG_92E_VOQ_DESA 0x320 +#define REG_92E_VIQ_DESA 0x328 +#define REG_92E_BEQ_DESA 0x330 +#define REG_92E_BKQ_DESA 0x338 +#define REG_92E_PCIE_HRPWM 0x361 +#define REG_92E_PCIE_CLK_RECOVER 0x362 +#define REG_92E_PCIE_HCPWM 0x363 +#define REG_92E_BEQ_IDX 0x364 +#define REG_92E_BKQ_IDX 0x368 +#define REG_92E_MGQ_IDX 0x36C +#define REG_92E_HI0Q_IDX 0x370 +#define REG_92E_HI1Q_IDX 0x374 +#define REG_92E_HI2Q_IDX 0x378 +#define REG_92E_HI3Q_IDX 0x37C +#define REG_92E_PCIE_HRPWM2 0x380 +#define REG_92E_PCIE_HCPWM2 0x382 +#define REG_92E_HCI_PCIE_H2C_MSG 0x384 +#define REG_92E_HCI_PCIE_C2H_MSG 0x388 +#define REG_92E_RXQ_IDX 0x38C +#define REG_92E_HI4Q_IDX 0x390 +#define REG_92E_HI5Q_IDX 0x394 +#define REG_92E_HI6Q_IDX 0x398 +#define REG_92E_HI7Q_IDX 0x39C +#define REG_92E_HQ_DES_NUM0 0x3A0 +#define REG_92E_HQ_DES_NUM1 0x3A4 +#define REG_92E_HQ_DES_NUM2 0x3A8 +#define REG_92E_HQ_DES_NUM3 0x3AC +#define REG_92E_TSFT_CLRQ 0x3B0 +#define REG_92E_ACQ_DES_NUM0 0x3B4 +#define REG_92E_ACQ_DES_NUM1 0x3B8 +#define REG_92E_ACQ_DES_NUM2 0x3BC +#define REG_92E_HI0Q_DESA 0x3C0 +#define REG_92E_HI1Q_DESA 0x3C8 +#define REG_92E_HI2Q_DESA 0x3D0 +#define REG_92E_HI3Q_DESA 0x3D8 +#define REG_92E_HI4Q_DESA 0x3E0 +#define REG_92E_HI5Q_DESA 0x3E8 +#define REG_92E_HI6Q_DESA 0x3F0 +#define REG_92E_HI7Q_DESA 0x3F8 +#define REG_92E_TXPKTBUF_BCNQ_BDNY1 0x457 +#define REG_92E_MACID_NOLINK 0x484 +#define REG_92E_MACID_PAUSE 0x48C +#define REG_92E_TXRPT_CTRL 0x4EC +#define REG_92E_TXRPT_TIM 0x4F0 +#define REG_92E_TXRPT_STSSET 0x4F2 +#define REG_92E_TXRPT_STSVLD 0x4F4 +#define REG_92E_TXRPT_STSINF 0x4F8 +#define REG_92E_MBSSID_CTRL 0x526 +#define REG_92E_PKT_LIFETIME_CTRL 0x528 +#define REG_92E_ATIMWND1 0x570 +#define REG_92E_PRE_DL_BCN_ITV 0x58F +#define REG_92E_ATIMWND2 0x5A0 +#define REG_92E_ATIMWND3 0x5A1 +#define REG_92E_ATIMWND4 0x5A2 +#define REG_92E_ATIMWND5 0x5A3 +#define REG_92E_ATIMWND6 0x5A4 +#define REG_92E_ATIMWND7 0x5A5 +#define REG_92E_ATIMUGT 0x5A6 +#define REG_92E_HIQ_NO_LMT_EN 0x5A7 +#define REG_92E_DTIM_COUNT_ROOT 0x5A8 +#define REG_92E_DTIM_COUNT_VAP1 0x5A9 +#define REG_92E_DTIM_COUNT_VAP2 0x5AA +#define REG_92E_DTIM_COUNT_VAP3 0x5AB +#define REG_92E_DTIM_COUNT_VAP4 0x5AC +#define REG_92E_DTIM_COUNT_VAP5 0x5AD +#define REG_92E_DTIM_COUNT_VAP6 0x5AE +#define REG_92E_DTIM_COUNT_VAP7 0x5AF +#define REG_92E_DIS_ATIM 0x5B0 +#define REG_92E_UPD_HGQMD 0x604 + +//---------------------------------------------------------------------------- +// 8192E REG_92E_HIMR bits (Offset 0xB0-B3, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192E REG_92E_HISR bits (Offset 0xB4-B7, 32 bits) +//---------------------------------------------------------------------------- +#define HIMR_92E_TXCCK BIT(30) // TXRPT interrupt when CCX bit of the packet is set +#define HIMR_92E_PSTIMEOUT BIT(29) // Power Save Time Out Interrupt +#define HIMR_92E_GTINT4 BIT(28) // When GTIMER4 expires, this bit is set to 1 +#define HIMR_92E_GTINT3 BIT(27) // When GTIMER3 expires, this bit is set to 1 +#define HIMR_92E_TBDER BIT(26) // Transmit Beacon0 Error +#define HIMR_92E_TBDOK BIT(25) // Transmit Beacon0 OK, ad hoc only +#define HIMR_92E_TSF_BIT32_TOGGLE BIT(24) // TSF Timer BIT32 toggle indication interrupt +#define HIMR_92E_BcnInt BIT(20) // Beacon DMA Interrupt 0 +#define HIMR_92E_BDERR0 BIT(16) // Beacon Queue DMA OK0 +#define HIMR_92E_HSISR_IND_ON_INT BIT(15) // HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) +#define HIMR_92E_BCNDMAINT_E BIT(14) // Beacon DMA Interrupt Extension for Win7 +#define HIMR_92E_ATIMEND BIT(12) // CTWidnow End or ATIM Window End +#define HIMR_92E_HISR1_IND_INT BIT(11) // HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1) +#define HIMR_92E_C2HCMD BIT(10) // CPU to Host Command INT Status, Write 1 clear +#define HIMR_92E_CPWM2 BIT(9) // CPU power Mode exchange INT Status, Write 1 clear +#define HIMR_92E_CPWM BIT(8) // CPU power Mode exchange INT Status, Write 1 clear +#define HIMR_92E_HIGHDOK BIT(7) // High Queue DMA OK +#define HIMR_92E_MGNTDOK BIT(6) // Management Queue DMA OK +#define HIMR_92E_BKDOK BIT(5) // AC_BK DMA OK +#define HIMR_92E_BEDOK BIT(4) // AC_BE DMA OK +#define HIMR_92E_VIDOK BIT(3) // AC_VI DMA OK +#define HIMR_92E_VODOK BIT(2) // AC_VO DMA OK +#define HIMR_92E_RDU BIT(1) // Rx Descriptor Unavailable +#define HIMR_92E_ROK BIT(0) // Receive DMA OK + +//---------------------------------------------------------------------------- +// 8192E REG_92E_HIMRE bits (Offset 0xB8-BB, 32 bits) +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// 8192E REG_92E_HIMSE bits (Offset 0xBC-BF, 32 bits) +//---------------------------------------------------------------------------- +#define HIMRE_92E_BCNDMAINT7 BIT(27) // Beacon DMA Interrupt 7 +#define HIMRE_92E_BCNDMAINT6 BIT(26) // Beacon DMA Interrupt 6 +#define HIMRE_92E_BCNDMAINT5 BIT(25) // Beacon DMA Interrupt 5 +#define HIMRE_92E_BCNDMAINT4 BIT(24) // Beacon DMA Interrupt 4 +#define HIMRE_92E_BCNDMAINT3 BIT(23) // Beacon DMA Interrupt 3 +#define HIMRE_92E_BCNDMAINT2 BIT(22) // Beacon DMA Interrupt 2 +#define HIMRE_92E_BCNDMAINT1 BIT(21) // Beacon DMA Interrupt 1 +#define HIMRE_92E_BCNDOK7 BIT(20) // Beacon Queue DMA OK Interrup 7 +#define HIMRE_92E_BCNDOK6 BIT(19) // Beacon Queue DMA OK Interrup 6 +#define HIMRE_92E_BCNDOK5 BIT(18) // Beacon Queue DMA OK Interrup 5 +#define HIMRE_92E_BCNDOK4 BIT(17) // Beacon Queue DMA OK Interrup 4 +#define HIMRE_92E_BCNDOK3 BIT(16) // Beacon Queue DMA OK Interrup 3 +#define HIMRE_92E_BCNDOK2 BIT(15) // Beacon Queue DMA OK Interrup 2 +#define HIMRE_92E_BCNDOK1 BIT(14) // Beacon Queue DMA OK Interrup 1 +#define HIMRE_92E_ATIMEND_E BIT(13) // ATIM Window End Extension for Win7 +#define HIMRE_92E_TXERR BIT(11) // Tx Error Flag Interrupt Status, write 1 clear. +#define HIMRE_92E_RXERR BIT(10) // Rx Error Flag INT Status, Write 1 clear +#define HIMRE_92E_TXFOVW BIT(9) // Transmit FIFO Overflow +#define HIMRE_92E_RXFOVW BIT(8) // Receive FIFO Overflow + +//---------------------------------------------------------------------------- +// 8192E REG_92E_HQ_DES_NUM0 bits (Offset 0x3A0-3A3, 32 bits) +//---------------------------------------------------------------------------- +#define ACQ_92E_H1Q_DESCS_MODE_8SEG BIT(31) +#define ACQ_92E_H1Q_DESC_NUM_MASK 0xfff +#define ACQ_92E_H1Q_DESC_NUM_SHIFT 16 +#define ACQ_92E_H0Q_DESCS_MODE_8SEG BIT(15) +#define ACQ_92E_H0Q_DESC_NUM_MASK 0xfff +#define ACQ_92E_H0Q_DESC_NUM_SHIFT 0 + +//---------------------------------------------------------------------------- +// 8192E REG_92E_HQ_DES_NUM1 bits (Offset 0x3A4-3A7, 32 bits) +//---------------------------------------------------------------------------- +#define ACQ_92E_H3Q_DESCS_MODE_8SEG BIT(31) +#define ACQ_92E_H3Q_DESC_NUM_MASK 0xfff +#define ACQ_92E_H3Q_DESC_NUM_SHIFT 16 +#define ACQ_92E_H2Q_DESCS_MODE_8SEG BIT(15) +#define ACQ_92E_H2Q_DESC_NUM_MASK 0xfff +#define ACQ_92E_H2Q_DESC_NUM_SHIFT 0 + +//---------------------------------------------------------------------------- +// 8192E REG_92E_HQ_DES_NUM2 bits (Offset 0x3A8-3AB, 32 bits) +//---------------------------------------------------------------------------- +#define ACQ_92E_H5Q_DESCS_MODE_8SEG BIT(31) +#define ACQ_92E_H5Q_DESC_NUM_MASK 0xfff +#define ACQ_92E_H5Q_DESC_NUM_SHIFT 16 +#define ACQ_92E_H4Q_DESCS_MODE_8SEG BIT(15) +#define ACQ_92E_H4Q_DESC_NUM_MASK 0xfff +#define ACQ_92E_H4Q_DESC_NUM_SHIFT 0 + +//---------------------------------------------------------------------------- +// 8192E REG_92E_HQ_DES_NUM3 bits (Offset 0x3AC-3AF, 32 bits) +//---------------------------------------------------------------------------- +#define ACQ_92E_H7Q_DESCS_MODE_8SEG BIT(31) +#define ACQ_92E_H7Q_DESC_NUM_MASK 0xfff +#define ACQ_92E_H7Q_DESC_NUM_SHIFT 16 +#define ACQ_92E_H6Q_DESCS_MODE_8SEG BIT(15) +#define ACQ_92E_H6Q_DESC_NUM_MASK 0xfff +#define ACQ_92E_H6Q_DESC_NUM_SHIFT 0 + +//---------------------------------------------------------------------------- +// 8192E REG_92E_CLRQ bits (Offset 0x3B0-3B4, 32 bits) +//---------------------------------------------------------------------------- +#define CLRQ_92E_ALL_IDX 0x3FFF3FFF +#define CLRQ_92E_HI7Q_HW_IDX BIT(29) +#define CLRQ_92E_HI6Q_HW_IDX BIT(28) +#define CLRQ_92E_HI5Q_HW_IDX BIT(27) +#define CLRQ_92E_HI4Q_HW_IDX BIT(26) +#define CLRQ_92E_HI3Q_HW_IDX BIT(25) +#define CLRQ_92E_HI2Q_HW_IDX BIT(24) +#define CLRQ_92E_HI1Q_HW_IDX BIT(23) +#define CLRQ_92E_HI0Q_HW_IDX BIT(22) +#define CLRQ_92E_BKQ_HW_IDX BIT(21) +#define CLRQ_92E_BEQ_HW_IDX BIT(20) +#define CLRQ_92E_VIQ_HW_IDX BIT(19) +#define CLRQ_92E_VOQ_HW_IDX BIT(18) +#define CLRQ_92E_MGQ_HW_IDX BIT(17) +#define CLRQ_92E_RXQ_HW_IDX BIT(16) +#define CLRQ_92E_HI7Q_HOST_IDX BIT(13) +#define CLRQ_92E_HI6Q_HOST_IDX BIT(12) +#define CLRQ_92E_HI5Q_HOST_IDX BIT(11) +#define CLRQ_92E_HI4Q_HOST_IDX BIT(10) +#define CLRQ_92E_HI3Q_HOST_IDX BIT(9) +#define CLRQ_92E_HI2Q_HOST_IDX BIT(8) +#define CLRQ_92E_HI1Q_HOST_IDX BIT(7) +#define CLRQ_92E_HI0Q_HOST_IDX BIT(6) +#define CLRQ_92E_BKQ_HOST_IDX BIT(5) +#define CLRQ_92E_BEQ_HOST_IDX BIT(4) +#define CLRQ_92E_VIQ_HOST_IDX BIT(3) +#define CLRQ_92E_VOQ_HOST_IDX BIT(2) +#define CLRQ_92E_MGQ_HOST_IDX BIT(1) +#define CLRQ_92E_RXQ_HOST_IDX BIT(0) + +//---------------------------------------------------------------------------- +// 8192E REG_92E_ACQ_DES_NUM0 bits (Offset 0x3B4-3B7, 32 bits) +//---------------------------------------------------------------------------- +#define ACQ_92E_VIQ_DESCS_MODE_8SEG BIT(31) +#define ACQ_92E_VIQ_DESC_NUM_MASK 0xfff +#define ACQ_92E_VIQ_DESC_NUM_SHIFT 16 +#define ACQ_92E_VOQ_DESCS_MODE_8SEG BIT(15) +#define ACQ_92E_VOQ_DESC_NUM_MASK 0xfff +#define ACQ_92E_VOQ_DESC_NUM_SHIFT 0 + +//---------------------------------------------------------------------------- +// 8192E REG_92E_ACQ_DES_NUM1 bits (Offset 0x3B8-3BB, 32 bits) +//---------------------------------------------------------------------------- +#define ACQ_92E_BKQ_DESCS_MODE_8SEG BIT(31) +#define ACQ_92E_BKQ_DESC_NUM_MASK 0xfff +#define ACQ_92E_BKQ_DESC_NUM_SHIFT 16 +#define ACQ_92E_BEQ_DESCS_MODE_8SEG BIT(15) +#define ACQ_92E_BEQ_DESC_NUM_MASK 0xfff +#define ACQ_92E_BEQ_DESC_NUM_SHIFT 0 + +//---------------------------------------------------------------------------- +// 8192E REG_92E_ACQ_DES_NUM2 bits (Offset 0x3BC-3BF, 32 bits) +//---------------------------------------------------------------------------- +#define ACQ_92E_RXQ_DESC_NUM_MASK 0xfff +#define ACQ_92E_RXQ_DESC_NUM_SHIFT 16 +#define ACQ_92E_MGQ_DESCS_MODE_8SEG BIT(15) +#define ACQ_92E_MGQ_DESC_NUM_MASK 0xfff +#define ACQ_92E_MGQ_DESC_NUM_SHIFT 0 + +//---------------------------------------------------------------------------- +// 8192E MBID_NUM bits (Offset 0x552, 8 bits) +//---------------------------------------------------------------------------- +#define MBID_NUM_92E_EN_PREDOWN_BCN BIT(3) + +//---------------------------------------------------------------------------- +// 8192E REG_EFUSE_ACCESS (Offset 0xCF, 8 bits) +//---------------------------------------------------------------------------- +#define EFUSE_ACCESS_ON_8192E 0x69 +#define EFUSE_ACCESS_OFF_8192E 0x00 + + +//==================================================== +// EEPROM/Efuse PG Offset for 8192EE/8192EU/8192ES +//==================================================== + +#if defined(EN_EFUSE) +#define PATHA_OFFSET 0x10 +#define PATHB_OFFSET 0x3A +#define PATHC_OFFSET 0x64 +#define PATHD_OFFSET 0x8E +/*2.4 GHz, PATH A, 1T*/ +#define EEPROM_2G_CCK1T_TxPower 0x0 // CCK Tx Power base +#define EEPROM_2G_HT401S_TxPower 0x6 // HT40 Tx Power base +#define EEPROM_2G_HT201S_TxPowerDiff 0xB // HT20 Tx Power Diff [7:4] +#define EEPROM_2G_OFDM1T_TxPowerDiff 0xB // OFDM Tx Power Diff [3:0] +/*2.4 GHz, PATH A, 2T*/ +#define EEPROM_2G_HT402S_TxPowerDiff 0xC // HT40 Tx Power Diff [7:4] +#define EEPROM_2G_HT202S_TxPowerDiff 0xC // HT20 Tx Power Diff [3:0] +#define EEPROM_2G_OFDM2T_TxPowerDiff 0xD // OFDM Tx Power Diff [7:4] +#define EEPROM_2G_CCK2T_TxPowerDiff 0xD // CCK Tx Power Diff [3:0] +/*2.4 GHz, PATH A, 3T*/ +#define EEPROM_2G_HT403S_TxPowerDiff 0xE // HT40 Tx Power Diff [7:4] +#define EEPROM_2G_HT203S_TxPowerDiff 0xE // HT40 Tx Power Diff [3:0] +#define EEPROM_2G_OFDM3T_TxPowerDiff 0xF // OFDM Tx Power Diff [7:4] +#define EEPROM_2G_CCK3T_TxPowerDiff 0xF // CCK Tx Power Diff [3:0] +/*2.4 GHz, PATH A, 4T*/ +#define EEPROM_2G_HT404S_TxPowerDiff 0x10 // HT40 Tx Power Diff [7:4] +#define EEPROM_2G_HT204S_TxPowerDiff 0x10 // HT20 Tx Power Diff [0:3] +#define EEPROM_2G_OFDM4T_TxPowerDiff 0x11 // OFDM Tx Power Diff [7:4] +#define EEPROM_2G_CCK4T_TxPowerDiff 0x11 // CCK Tx Power Diff [3:0] +/*5 GHz, PATH A, 1T*/ +#define EEPROM_5G_HT401S_TxPower 0x12 // HT40 Tx Power Base +#define EEPROM_5G_HT201S_TxPowerDiff 0x20 // HT20 Tx Power Diff [7:4] +#define EEPROM_5G_OFDM1T_TxPowerDiff 0x20 // OFDM Tx Power Diff [3:0] +#define EEPROM_5G_HT801S_TxPowerDiff 0x26 // HT80 Tx Power Diff [7:4] +#define EEPROM_5G_HT1601S_TxPowerDiff 0x26 // HT160 Tx Power Diff [3:0] +/*5 GHz, PATH A, 2T*/ +#define EEPROM_5G_HT402S_TxPowerDiff 0x21 // HT40 Tx Power Diff [7:4] +#define EEPROM_5G_HT202S_TxPowerDiff 0x21 // HT20 Tx Power Diff [3:0] +#define EEPROM_5G_OFDM2T_TxPowerDiff 0x24 // OFDM Tx Power Diff [7:4] +#define EEPROM_5G_HT802S_TxPowerDiff 0x27 // HT80 Tx Power Diff [7:4] +/*5 GHz, PATH A, 3T*/ +#define EEPROM_5G_OFDM3T_TxPowerDiff 0x24 // OFDM Tx Power Diff [3:0] +#define EEPROM_5G_HT403S_TxPowerDiff 0x22 // HT40 Tx Power Diff [7:4] +#define EEPROM_5G_HT203S_TxPowerDiff 0x22 // HT20 Tx Power Diff [3:0] +#define EEPROM_5G_HT803S_TxPowerDiff 0x28 // HT80 Tx Power Diff [7:4] +#define EEPROM_5G_HT1603S_TxPowerDiff 0x28 // HT160 Tx Power Diff [3:0] +/*5 GHz, PATH A, 4T*/ +#define EEPROM_5G_HT404S_TxPowerDiff 0x23 // HT40 Tx Power Diff [7:4] +#define EEPROM_5G_HT204S_TxPowerDiff 0x23 // HT20 Tx Power Diff [3:0] +#define EEPROM_5G_OFDM4T_TxPowerDiff 0x25 // OFDM Tx Power Diff [3:0] +#define EEPROM_5G_HT804S_TxPowerDiff 0x29 // HT80 Tx Power Diff [7:4] +#define EEPROM_5G_HT1604S_TxPowerDiff 0x29 // HT160 Tx Power Diff [3:0] + +#define EEPROM_92E_XTAL_K 0xB9 //Crystal Calibration [5:0] +#define EEPROM_92E_THERMAL_METER 0xBA //Thermal meter + +#ifdef CONFIG_SDIO_HCI +#define EEPROM_92E_SDIOTYPE 0xD0 +#define EEPROM_92E_MACADDRESS 0x11A +#else +#define EEPROM_92E_MACADDRESS 0xD0 // MAC Address +#endif + +#endif + +#if 0 + +#define PATHA_OFFSET 0x10 +#define PATHB_OFFSET 0x3A + + +// 0x10 ~ 0x63 = TX power area. +#define EEPROM_TX_PWR_INX_8192E 0x0 + +#define EEPROM_ChannelPlan_8192E 0xB8 +#define EEPROM_XTAL_8192E 0xB9 +#define EEPROM_THERMAL_METER_8192E 0xBA +#define EEPROM_IQK_LCK_8192E 0xBB +#define EEPROM_2G_5G_PA_TYPE_8192E 0xBC +#define EEPROM_2G_LNA_TYPE_GAIN_SEL_8192E 0xBD +#define EEPROM_5G_LNA_TYPE_GAIN_SEL_8192E 0xBF + +#define EEPROM_RF_BOARD_OPTION_8192E 0xC1 +#define EEPROM_RF_FEATURE_OPTION_8192E 0xC2 +#define EEPROM_RF_BT_SETTING_8192E 0xC3 +#define EEPROM_VERSION_8192E 0xC4 +#define EEPROM_CustomID_8192E 0xC5 +#define EEPROM_TX_BBSWING_2G_8192E 0xC6 +#define EEPROM_TX_BBSWING_5G_8192E 0xC7 +#define EEPROM_TX_PWR_CALIBRATE_RATE_8192E 0xC8 +#define EEPROM_RF_ANTENNA_OPT_8192E 0xC9 + +// RTL8192EE +#define EEPROM_MAC_ADDR_8192EE 0xD0 +#define EEPROM_VID_8192EE 0xD6 +#define EEPROM_DID_8192EE 0xD8 +#define EEPROM_SVID_8192EE 0xDA +#define EEPROM_SMID_8192EE 0xDC + +//RTL8192EU +#define EEPROM_MAC_ADDR_8192EU 0xD7 +#define EEPROM_VID_8192EU 0xD0 +#define EEPROM_PID_8192EU 0xD2 +#define EEPROM_PA_TYPE_8192EU 0xBC +#define EEPROM_LNA_TYPE_2G_8192EU 0xBD +#define EEPROM_LNA_TYPE_5G_8192EU 0xBF + +// RTL8192ES +#define EEPROM_MAC_ADDR_8192ES 0x11B +#endif + + +//----------------------------------------------------- +// +// RTL8192E SDIO Configuration +// +//----------------------------------------------------- + +// I/O bus domain address mapping +#define SDIO_LOCAL_BASE 0x10250000 +#define WLAN_IOREG_BASE 0x10260000 +#define FIRMWARE_FIFO_BASE 0x10270000 +#define TX_HIQ_BASE 0x10310000 +#define TX_MIQ_BASE 0x10320000 +#define TX_LOQ_BASE 0x10330000 +#define TX_EXQ_BASE 0x10350000 // 92E Add +#define RX_RX0FF_BASE 0x10340000 + +// SDIO host local register space mapping. +#define SDIO_LOCAL_MSK 0x0FFF +#define WLAN_IOREG_MSK 0x7FFF +#define WLAN_FIFO_MSK 0x1FFF // Aggregation Length[12:0] +#define WLAN_RX0FF_MSK 0x0003 + +#define SDIO_WITHOUT_REF_DEVICE_ID 0 // Without reference to the SDIO Device ID +#define SDIO_LOCAL_DEVICE_ID 0 // 0b[16], 000b[15:13] +#define WLAN_TX_HIQ_DEVICE_ID 4 // 0b[16], 100b[15:13] +#define WLAN_TX_MIQ_DEVICE_ID 5 // 0b[16], 101b[15:13] +#define WLAN_TX_LOQ_DEVICE_ID 6 // 0b[16], 110b[15:13] +#define WLAN_TX_EXQ_DEVICE_ID 3 // 0b[16], 011b[15:13] (False map) // 0b[16], 111b[15:13] (True map)(92E New) +#define WLAN_RX0FF_DEVICE_ID 7 // 0b[16], 111b[15:13] +#define WLAN_IOREG_DEVICE_ID 8 // 1b[16] + +// SDIO Tx Free Page Index (This order must match SDIO_REG_FREE_TXPG) +#define HI_QUEUE_IDX 0 +#define MID_QUEUE_IDX 1 +#define LOW_QUEUE_IDX 2 +#define PUBLIC_QUEUE_IDX 3 +#define EXTRA_QUEUE_IDX 4 // 92E New + +#define SDIO_MAX_TX_QUEUE 4 // HIQ, MIQ, LOQ and EXQ +#define SDIO_MAX_RX_QUEUE 1 + +#define SDIO_REG_TX_CTRL 0x0000 // SDIO Tx Control +#define SDIO_REG_HIMR 0x0014 // SDIO Host Interrupt Mask +#define SDIO_REG_HISR 0x0018 // SDIO Host Interrupt Service Routine +#define SDIO_REG_RX0_REQ_LEN 0x001C // RXDMA Request Length +#define SDIO_REG_OQT_FREE_SPACE 0x001E // OQT Free Space +#define SDIO_REG_FREE_TXPG 0x0020 // Free Tx Buffer Page +#define SDIO_REG_HCPWM1 0x0025 // HCI Current Power Mode 1 +#define SDIO_REG_HCPWM2 0x0026 // HCI Current Power Mode 2 +#define SDIO_REG_HTSFR_INFO 0x0030 // HTSF Informaion +#define SDIO_REG_HRPWM1 0x0080 // HCI Request Power Mode 1 +#define SDIO_REG_HRPWM2 0x0082 // HCI Request Power Mode 2 +#define SDIO_REG_HSUS_CTRL 0x0086 // SDIO HCI Suspend Control + +#define SDIO_HIMR_DISABLED 0 + +// RTL8188E SDIO Host Interrupt Mask Register +#define SDIO_HIMR_RX_REQUEST_MSK BIT0 +#define SDIO_HIMR_AVAL_MSK BIT1 +#define SDIO_HIMR_TXERR_MSK BIT2 +#define SDIO_HIMR_RXERR_MSK BIT3 +#define SDIO_HIMR_TXFOVW_MSK BIT4 +#define SDIO_HIMR_RXFOVW_MSK BIT5 +#define SDIO_HIMR_TXBCNOK_MSK BIT6 +#define SDIO_HIMR_TXBCNERR_MSK BIT7 +#define SDIO_HIMR_BCNERLY_INT_MSK BIT16 +#define SDIO_HIMR_C2HCMD_MSK BIT17 +#define SDIO_HIMR_CPWM1_MSK BIT18 +#define SDIO_HIMR_CPWM2_MSK BIT19 +#define SDIO_HIMR_HSISR_IND_MSK BIT20 +#define SDIO_HIMR_GTINT3_IND_MSK BIT21 +#define SDIO_HIMR_GTINT4_IND_MSK BIT22 +#define SDIO_HIMR_PSTIMEOUT_MSK BIT23 +#define SDIO_HIMR_OCPINT_MSK BIT24 +#define SDIO_HIMR_ATIMEND_MSK BIT25 +#define SDIO_HIMR_ATIMEND_E_MSK BIT26 +#define SDIO_HIMR_CTWEND_MSK BIT27 + +//RTL8188E SDIO Specific +#define SDIO_HIMR_MCU_ERR_MSK BIT28 +#define SDIO_HIMR_TSF_BIT32_TOGGLE_MSK BIT29 + +// SDIO Host Interrupt Service Routine +#define SDIO_HISR_RX_REQUEST BIT0 +#define SDIO_HISR_AVAL BIT1 +#define SDIO_HISR_TXERR BIT2 +#define SDIO_HISR_RXERR BIT3 +#define SDIO_HISR_TXFOVW BIT4 +#define SDIO_HISR_RXFOVW BIT5 +#define SDIO_HISR_TXBCNOK BIT6 +#define SDIO_HISR_TXBCNERR BIT7 +#define SDIO_HISR_BCNERLY_INT BIT16 +#define SDIO_HISR_C2HCMD BIT17 +#define SDIO_HISR_CPWM1 BIT18 +#define SDIO_HISR_CPWM2 BIT19 +#define SDIO_HISR_HSISR_IND BIT20 +#define SDIO_HISR_GTINT3_IND BIT21 +#define SDIO_HISR_GTINT4_IND BIT22 +#define SDIO_HISR_PSTIMEOUT BIT23 +#define SDIO_HISR_OCPINT BIT24 +#define SDIO_HISR_ATIMEND BIT25 +#define SDIO_HISR_ATIMEND_E BIT26 +#define SDIO_HISR_CTWEND BIT27 + +//RTL8188E SDIO Specific +#define SDIO_HISR_MCU_ERR BIT28 +#define SDIO_HISR_TSF_BIT32_TOGGLE BIT29 + +#define MASK_SDIO_HISR_CLEAR (SDIO_HISR_TXERR |\ + SDIO_HISR_RXERR |\ + SDIO_HISR_TXFOVW |\ + SDIO_HISR_RXFOVW |\ + SDIO_HISR_TXBCNOK |\ + SDIO_HISR_TXBCNERR |\ + SDIO_HISR_C2HCMD |\ + SDIO_HISR_CPWM1 |\ + SDIO_HISR_CPWM2 |\ + SDIO_HISR_HSISR_IND |\ + SDIO_HISR_GTINT3_IND |\ + SDIO_HISR_GTINT4_IND |\ + SDIO_HISR_PSTIMEOUT |\ + SDIO_HISR_OCPINT) + +// SDIO HCI Suspend Control Register +#define HCI_RESUME_PWR_RDY BIT1 +#define HCI_SUS_CTRL BIT0 + +// SDIO Tx FIFO related +#define SDIO_TX_FREE_PG_QUEUE 5 // The number of Tx FIFO free page +#define SDIO_TX_FIFO_PAGE_SZ 256 + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_hw.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_hw.c new file mode 100755 index 000000000..bf3a266ac --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_hw.c @@ -0,0 +1,3500 @@ + +#define _8812_HW_C_ + +#include "8192cd.h" +#include "8192cd_cfg.h" +#include "8192cd_util.h" + +#include "8192c_reg.h" +#include "8812_reg.h" +#include "8812_vht_gen.h" + +#ifdef __KERNEL__ +#include +#endif +//eric_8812 #include "8192cd_debug.h" +#include "8192cd_headers.h" + +#ifdef CONFIG_RTL_8812_SUPPORT + +typedef struct _C2H_EVT_HDR{ + u1Byte CmdID: 4; + u1Byte CmdLen: 4; + u1Byte CmdSeq; +}C2H_EVT_HDR, *PC2H_EVT_HDR; + +typedef enum _RTL8812_C2H_EVT +{ + C2H_8812_DBG = 0, + C2H_8812_LB = 1, + C2H_8812_TXBF = 2, + CCXRPT = 3, + C2H_8812_TXPERORT = 4, + C2H_8812_RA_RPT = 12, +#ifdef TXRETRY_CNT + C2H_8812_TXRETRY = 13, //0x0D +#endif + C2H_8812_RA_PARA_RPT=14, + C2H_8812_EXTEND_IND = 0xFF, + MAX_8812_C2HEVENT +}RTL8812_C2H_EVT; + +typedef enum _RTL8812_EXTEND_C2H_EVT +{ + EXTEND_C2H_8812_DBG_PRINT = 0 + +}RTL8812_EXTEND_C2H_EVT; + +void UpdateBBRFVal8812(struct rtl8192cd_priv *priv, unsigned char channel) +{ + unsigned char current_is_5g = 0, switch_bw = 0; + unsigned char bTmp = 0; + unsigned int dwTmp = 0; + unsigned int tmp_cb0=0, tmp_eb0 = 0; //for_8812_mp_chip + unsigned int eRFPath, curMaxRFPath; + + curMaxRFPath = RF92CD_PATH_MAX; + + //check CCK_CHECK_en BIT7 + if ( RTL_R8(0x454) & BIT(7) ) + current_is_5g = 1; + else + current_is_5g = 0; + + if (((channel > 14) && (current_is_5g == 0)) || ((channel <= 14) && (current_is_5g == 1))) + switch_bw = 1; + + //printk("\n\n eric-current_is_5g = %d switch_bw = %d pre= %d\n\n", current_is_5g, switch_bw, priv->pshare->pre_channel); + + if (channel > 14 && (switch_bw || (priv->pshare->pre_channel == 0))) //2.4G to 5G + RTL_W8(0x454, (RTL_R8(0x454) | BIT(7))); + + //Set fc_area 0x860 + dwTmp = RTL_R32(0x860); + dwTmp &= ~(BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23) | BIT(24) | BIT(25) | BIT(26) | BIT(27) | BIT(28)); + + if (channel <= 14) + dwTmp |= (0x96a << 17); + else if (channel <= 48) + dwTmp |= (0x494 << 17); + else if (channel <= 64) + dwTmp |= (0x453 << 17); + else if (channel <= 116) + dwTmp |= (0x452 << 17); + else if (channel <= 177) + dwTmp |= (0x412 << 17); + + RTL_W32(0x860, dwTmp); + + //Set RF MOD AG rf_0x18 + for (eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { + dwTmp = PHY_QueryRFReg(priv, eRFPath, rRfChannel, bMask20Bits, 1); + dwTmp &= ~(BIT(8) | BIT(9) | BIT(16) | BIT(17) | BIT(18)); + + if (channel <= 14) + dwTmp |= 0x0; + else if (channel <= 64) + dwTmp |= (BIT(8) | BIT(16)); + else if (channel <= 140) + dwTmp |= (BIT(8) | BIT(16) | BIT(17)); + else + dwTmp |= (BIT(8) | BIT(16) | BIT(18)); + + PHY_SetRFReg(priv, eRFPath, rRfChannel, bMask20Bits, dwTmp); + } + + //Set BB registers //for_8812_mp_chip + if (switch_bw) { + if (!IS_TEST_CHIP(priv)) { + tmp_cb0 = RTL_R32(0xcb0); + tmp_cb0 &= ~(BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23)); + tmp_eb0 = RTL_R32(0xeb0); + tmp_eb0 &= ~(BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23)); + } + + if (!current_is_5g) { + bTmp = RTL_R8(0x82c); + bTmp &= ~(BIT(0) | BIT(1)); + bTmp |= BIT(0); + RTL_W8(0x82c, bTmp); + if (GET_CHIP_VER(priv) == VERSION_8881A) { + PHY_SetBBReg(priv, 0xcb0, 0xff, 0x55); + PHY_SetBBReg(priv, 0xcb0, 0xf000, 0x1); + } else { + if (IS_TEST_CHIP(priv)) { + RTL_W32(0xcb8, RTL_R32(0xcb8) | BIT(12)); + RTL_W32(0xeb8, RTL_R32(0xcb8) | BIT(12)); + RTL_W32(0xcb8, RTL_R32(0xcb8) & (~BIT(15))); + RTL_W32(0xeb8, RTL_R32(0xeb8) & (~BIT(15))); + } else { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) + { + #if 0 + if (priv->pmib->dot11RFEntry.pa_type == PA_RFMD_4501) { + RTL_W32(0xcb0, tmp_cb0 | (0x53 << 16)); + RTL_W32(0xeb0, tmp_eb0 | (0x53 << 16)); + } else { + RTL_W32(0xcb0, tmp_cb0 | (0x54 << 16)); + RTL_W32(0xeb0, tmp_eb0 | (0x54 << 16)); + } + #else + //For 8812 PHY_PARAMETER after V40. + RTL_W32(0xcb0, 0x77337717); + RTL_W32(0xeb0, 0x77337717); + + if (priv->pmib->dot11RFEntry.pa_type == PA_RFMD_4501 || priv->pmib->dot11RFEntry.pa_type == PA_SKYWORKS_85712_HP) { + PHY_SetBBReg(priv, 0xcb4, 0x3ff00000, 0x00); + PHY_SetBBReg(priv, 0xeb4, 0x3ff00000, 0x00); + } else { + PHY_SetBBReg(priv, 0xcb4, 0x3ff00000, 0x10); + PHY_SetBBReg(priv, 0xeb4, 0x3ff00000, 0x10); + } + #endif + } else +#endif + { +#ifdef CONFIG_PA_RTC5634 + // internal PA+PAPE + if (priv->pmib->dot11RFEntry.pa_type == PA_RTC5634) { + //panic_printk("Set PAPE on\n"); + RTL_W32(0xcb0, 0x77537717); + RTL_W32(0xeb0, 0x77537717); + } +#endif + } + } + } +// RTL_W32(0x808, RTL_R32(0x808) & (~BIT(28))); + RTL_W32(0x808, RTL_R32(0x808) | BIT(28)); + RTL_W8(0xa07, RTL_R8(0xa07) | 0xf); + RTL_W32(0x8c0, RTL_R32(0x8c0) & (~BIT(17))); + PHY_SetBBReg(priv, 0x830, BIT(17)|BIT(16)|BIT(15)|BIT(14)|BIT(13), 0x15); + } else { + bTmp = RTL_R8(0x82c); + bTmp &= ~(BIT(0) | BIT(1)); + RTL_W8(0x82c, bTmp); + + if (IS_TEST_CHIP(priv)) { + RTL_W32(0xcb8, RTL_R32(0xcb8) & (~BIT(12))); + RTL_W32(0xeb8, RTL_R32(0xcb8) & (~BIT(12))); + RTL_W32(0xcb8, RTL_R32(0xcb8) | BIT(15)); + RTL_W32(0xeb8, RTL_R32(0xeb8) | BIT(15)); + } else { + //RTL_W32(0xcb0, tmp_cb0 | (0x77 << 16)); + //RTL_W32(0xeb0, tmp_eb0 | (0x77 << 16)); + RTL_W32(0xcb0, 0x77777777); + RTL_W32(0xeb0, 0x77777777); + } + + RTL_W32(0x808, RTL_R32(0x808) | BIT(28)); + RTL_W8(0xa07, (RTL_R8(0xa07) & 0xf0)|0x01); + RTL_W32(0x8c0, RTL_R32(0x8c0) | BIT(17)); + PHY_SetBBReg(priv, 0x830, BIT(17)|BIT(16)|BIT(15)|BIT(14)|BIT(13), 0x17); + } + } else if (priv->pshare->pre_channel == 0) { //first launch + if (channel > 14) { + bTmp = RTL_R8(0x82c); + bTmp &= ~(BIT(0) | BIT(1)); + bTmp |= BIT(0); + RTL_W8(0x82c, bTmp); + + if (IS_TEST_CHIP(priv)) { + RTL_W32(0xcb8, RTL_R32(0xcb8) | BIT(12)); + RTL_W32(0xeb8, RTL_R32(0xcb8) | BIT(12)); + RTL_W32(0xcb8, RTL_R32(0xcb8) & (~BIT(15))); + RTL_W32(0xeb8, RTL_R32(0xeb8) & (~BIT(15))); + } else { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) + { + #if 0 + if (priv->pmib->dot11RFEntry.pa_type == PA_RFMD_4501) { + RTL_W32(0xcb0, tmp_cb0 | (0x53 << 16)); + RTL_W32(0xeb0, tmp_eb0 | (0x53 << 16)); + } else { + RTL_W32(0xcb0, tmp_cb0 | (0x54 << 16)); + RTL_W32(0xeb0, tmp_eb0 | (0x54 << 16)); + } + #else + //For 8812 PHY_PARAMETER after V40. + RTL_W32(0xcb0, 0x77337717); + RTL_W32(0xeb0, 0x77337717); + + if (priv->pmib->dot11RFEntry.pa_type == PA_RFMD_4501 || priv->pmib->dot11RFEntry.pa_type == PA_SKYWORKS_85712_HP) { + PHY_SetBBReg(priv, 0xcb4, 0x3ff00000, 0x00); + PHY_SetBBReg(priv, 0xeb4, 0x3ff00000, 0x00); + } else { + PHY_SetBBReg(priv, 0xcb4, 0x3ff00000, 0x10); + PHY_SetBBReg(priv, 0xeb4, 0x3ff00000, 0x10); + } + #endif + } else +#endif + { +#ifdef CONFIG_PA_RTC5634 + // internal PA+PAPE + if (priv->pmib->dot11RFEntry.pa_type == PA_RTC5634) { + //panic_printk("Set PAPE on\n"); + RTL_W32(0xcb0, 0x77537717); + RTL_W32(0xeb0, 0x77537717); + } +#endif + } + } +// RTL_W32(0x808, RTL_R32(0x808) & (~BIT(28))); + RTL_W32(0x808, RTL_R32(0x808) | BIT(28)); + RTL_W8(0xa07, RTL_R8(0xa07) | 0xf); + RTL_W32(0x8c0, RTL_R32(0x8c0) & (~BIT(17))); + PHY_SetBBReg(priv, 0x830, BIT(17)|BIT(16)|BIT(15)|BIT(14)|BIT(13), 0x15); + } else { + bTmp = RTL_R8(0x82c); + bTmp &= ~(BIT(0) | BIT(1)); + RTL_W8(0x82c, bTmp); + if (GET_CHIP_VER(priv) == VERSION_8881A) { + PHY_SetBBReg(priv, 0xcb0, 0xff, 0x00); + PHY_SetBBReg(priv, 0xcb0, 0xf000, 0x0); + } else { + + if (IS_TEST_CHIP(priv)) { + RTL_W32(0xcb8, RTL_R32(0xcb8) & (~BIT(12))); + RTL_W32(0xeb8, RTL_R32(0xcb8) & (~BIT(12))); + RTL_W32(0xcb8, RTL_R32(0xcb8) | BIT(15)); + RTL_W32(0xeb8, RTL_R32(0xeb8) | BIT(15)); + } else { + //RTL_W32(0xcb0, tmp_cb0 | (0x77 << 16)); + //RTL_W32(0xeb0, tmp_eb0 | (0x77 << 16)); + RTL_W32(0xcb0, 0x77777777); + RTL_W32(0xeb0, 0x77777777); + } + } + RTL_W32(0x808, RTL_R32(0x808) | BIT(28)); + RTL_W32(0x8c0, RTL_R32(0x8c0) | BIT(17)); + PHY_SetBBReg(priv, 0x830, BIT(17)|BIT(16)|BIT(15)|BIT(14)|BIT(13), 0x17); + } + } + + if (channel <= 14 && (switch_bw || (priv->pshare->pre_channel == 0))) + RTL_W8(0x454, (RTL_R8(0x454) & ~(BIT(7)))); + +#ifdef AC2G_256QAM + if(is_ac2g(priv)) + { + RTL_W32(0x8c0, RTL_R32(0x8c0) & (~BIT(17))); //enable tx vht rates + } +#endif + SpurCheck8812(priv, 1, channel, 0); + + priv->pshare->pre_channel = channel; + +} + + +/* 8812 2.4G spur at 2480MHz */ +void SpurCheck8812(struct rtl8192cd_priv *priv, unsigned char ch_bw, unsigned char channel, unsigned int bandwidth) +{ + unsigned int dwTmp = 0; + unsigned char primary_channel = 0; + + if(ch_bw == 1){ /* if switch channel */ + if((priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_40 && (channel == 11 || channel == 12)) || + (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_20 && (channel == 13 || channel == 14))){ + RTL_W32(0x8ac,0x0ff0ff04); + RTL_W32(0X8c4,0x40000000); + }else if((priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_40 && (priv->pshare->pre_channel == 11 || priv->pshare->pre_channel == 12)) || + (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_20 && (priv->pshare->pre_channel == 13 || priv->pshare->pre_channel == 14))){ + + /* Restore 0x8ac, 0x8c4*/ + PHY_SetBBReg(priv, 0x8ac, BIT(10), 0); + RTL_W32(0X8c4,0); + primary_channel = priv->pshare->txsc_20; + dwTmp = RTL_R32(0x8ac); + dwTmp &= ~(BIT(0) | BIT(1) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(20) | BIT(21)); + + switch (priv->pshare->CurrentChannelBW) { + case HT_CHANNEL_WIDTH_AC_5: + dwTmp |= (BIT(6) | BIT(20)); + RTL_W32(0x8ac, dwTmp); + break; + case HT_CHANNEL_WIDTH_AC_10: + dwTmp |= (BIT(7) | BIT(8) | BIT(21)); + RTL_W32(0x8ac, dwTmp); + break; + case HT_CHANNEL_WIDTH_AC_20: + dwTmp |= (BIT(9) | BIT(20) | BIT(21)); + RTL_W32(0x8ac, dwTmp); + break; + case HT_CHANNEL_WIDTH_AC_40: + dwTmp |= (BIT(0) | BIT(9) | BIT(20) | BIT(21)); + RTL_W32(0x8ac, dwTmp); + break; + } + if (IS_C_CUT_8812(priv)) { + switch (priv->pshare->CurrentChannelBW) + { + case HT_CHANNEL_WIDTH_AC_5: + PHY_SetBBReg(priv, 0x8c4, BIT(30), 0); + break; + case HT_CHANNEL_WIDTH_AC_10: + PHY_SetBBReg(priv, 0x8c4, BIT(30), 0); + break; + case HT_CHANNEL_WIDTH_AC_20: + PHY_SetBBReg(priv, 0x8c4, BIT(30), 0); + break; + case HT_CHANNEL_WIDTH_AC_40: + PHY_SetBBReg(priv, 0x8c4, BIT(30), 0); + break; + } + } + + dwTmp = RTL_R32(0x8ac); + dwTmp &= ~(BIT(2)|BIT(3)|BIT(4)|BIT(5)); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_AC_5: + case HT_CHANNEL_WIDTH_AC_10: + case HT_CHANNEL_WIDTH_AC_20: + break; + case HT_CHANNEL_WIDTH_AC_40: + dwTmp |= (primary_channel << 2); + RTL_W32(0x8ac, dwTmp); + break; + } + } + }else if(ch_bw == 0){ /* if switch bandwidth */ + if((bandwidth == HT_CHANNEL_WIDTH_AC_20 && (priv->pmib->dot11RFEntry.dot11channel == 13 || priv->pmib->dot11RFEntry.dot11channel == 14)) || + (bandwidth == HT_CHANNEL_WIDTH_AC_40 && (priv->pmib->dot11RFEntry.dot11channel == 11 || priv->pmib->dot11RFEntry.dot11channel == 12)) + ){ + RTL_W32(0x8ac,0x0ff0ff04); + RTL_W32(0X8c4,0x40000000); + } + } +} + + +signed char convert_diff(signed char value) +{ + // range from -8 ~ 7 + if (value <= 7) + return value; + else + return (value - 16); +} + +void Write_OFDM_A(struct rtl8192cd_priv *priv, unsigned int writeVal) +{ + RTL_W32(rTxAGC_A_Ofdm18_Ofdm6_JAguar, writeVal); + RTL_W32(rTxAGC_A_Ofdm54_Ofdm24_JAguar, writeVal); +} + +void Write_1S_A(struct rtl8192cd_priv *priv, unsigned int writeVal) +{ + RTL_W32(rTxAGC_A_MCS3_MCS0_JAguar, writeVal); + RTL_W32(rTxAGC_A_MCS7_MCS4_JAguar, writeVal); + RTL_W32(rTxAGC_A_Nss1Index3_Nss1Index0_JAguar, writeVal); + RTL_W32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar, writeVal); + RTL_W32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar, writeVal); +} + +void Write_2S_A(struct rtl8192cd_priv *priv, unsigned int writeVal) +{ + RTL_W32(rTxAGC_A_MCS11_MCS8_JAguar, writeVal); + RTL_W32(rTxAGC_A_MCS15_MCS12_JAguar, writeVal); + RTL_W32(rTxAGC_A_Nss2Index5_Nss2Index2_JAguar, writeVal); + RTL_W32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar, writeVal); + writeVal = (writeVal & 0xffff0000) | (RTL_R32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar) & 0xffff); + RTL_W32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar, writeVal); +} + +void Write_OFDM_B(struct rtl8192cd_priv *priv, unsigned int writeVal) +{ + RTL_W32(rTxAGC_B_Ofdm18_Ofdm6_JAguar, writeVal); + RTL_W32(rTxAGC_B_Ofdm54_Ofdm24_JAguar, writeVal); +} + + +void Write_1S_B(struct rtl8192cd_priv *priv, unsigned int writeVal) +{ + RTL_W32(rTxAGC_B_MCS3_MCS0_JAguar, writeVal); + RTL_W32(rTxAGC_B_MCS7_MCS4_JAguar, writeVal); + RTL_W32(rTxAGC_B_Nss1Index3_Nss1Index0_JAguar, writeVal); + RTL_W32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar, writeVal); + RTL_W32(rTxAGC_B_Nss2Index1_Nss1Index8_JAguar, writeVal); +} + +void Write_2S_B(struct rtl8192cd_priv *priv, unsigned int writeVal) +{ + RTL_W32(rTxAGC_B_MCS11_MCS8_JAguar, writeVal); + RTL_W32(rTxAGC_B_MCS15_MCS12_JAguar, writeVal); + RTL_W32(rTxAGC_B_Nss2Index5_Nss2Index2_JAguar, writeVal); + RTL_W32(rTxAGC_B_Nss2Index9_Nss2Index6_JAguar, writeVal); + writeVal = (writeVal & 0xffff0000) | (RTL_R32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar) & 0xffff); + RTL_W32(rTxAGC_B_Nss2Index1_Nss1Index8_JAguar, writeVal); +} + +void use_DefaultOFDMTxPower_8812(struct rtl8192cd_priv *priv) +{ + + unsigned int def_power = 0x20202020;//0x12121212; + //printk("NO Calibration data, use default OFDM power = 0x%x\n", def_power); + + RTL_W32(rTxAGC_A_Ofdm18_Ofdm6_JAguar, def_power); + RTL_W32(rTxAGC_A_Ofdm54_Ofdm24_JAguar, def_power); + RTL_W32(rTxAGC_A_MCS3_MCS0_JAguar, def_power); + RTL_W32(rTxAGC_A_MCS7_MCS4_JAguar, def_power); + RTL_W32(rTxAGC_A_MCS11_MCS8_JAguar, def_power); + RTL_W32(rTxAGC_A_MCS15_MCS12_JAguar, def_power); + RTL_W32(rTxAGC_A_Nss1Index3_Nss1Index0_JAguar, def_power); + RTL_W32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar, def_power); + RTL_W32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar, def_power); + RTL_W32(rTxAGC_A_Nss2Index5_Nss2Index2_JAguar, def_power); + RTL_W32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar, def_power); + + RTL_W32(rTxAGC_B_Ofdm18_Ofdm6_JAguar, def_power); + RTL_W32(rTxAGC_B_Ofdm54_Ofdm24_JAguar, def_power); + RTL_W32(rTxAGC_B_MCS3_MCS0_JAguar, def_power); + RTL_W32(rTxAGC_B_MCS7_MCS4_JAguar, def_power); + RTL_W32(rTxAGC_B_MCS11_MCS8_JAguar, def_power); + RTL_W32(rTxAGC_B_MCS15_MCS12_JAguar, def_power); + RTL_W32(rTxAGC_B_Nss1Index3_Nss1Index0_JAguar, def_power); + RTL_W32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar, def_power); + RTL_W32(rTxAGC_B_Nss2Index1_Nss1Index8_JAguar, def_power); + RTL_W32(rTxAGC_B_Nss2Index5_Nss2Index2_JAguar, def_power); + RTL_W32(rTxAGC_B_Nss2Index9_Nss2Index6_JAguar, def_power); + +} + + +void Cal_OFDMTxPower_5G(struct rtl8192cd_priv *priv, unsigned char ch_idx) +{ + unsigned char tmp_TPI = 0; + unsigned char pwr_40_1s = 0; + signed char diff_ofdm_1t = 0; + signed char diff_bw40_2s = 0; + signed char diff_bw20_1s = 0; + signed char diff_bw20_2s = 0; + signed char diff_bw80_1s = 0; + signed char diff_bw80_2s = 0; + + unsigned int writeVal = 0; +#ifdef POWER_PERCENT_ADJUSTMENT + signed char pwrdiff_percent = PwrPercent2PwrLevel(priv->pmib->dot11RFEntry.power_percent); +#endif + + // PATH A, OFDM + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_ofdm_1t = (priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_A[ch_idx] & 0x0f); + diff_ofdm_1t = convert_diff(diff_ofdm_1t); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_ofdm_1t); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_OFDM_A(priv, writeVal); + + //printk("Write_OFDM_A %d = %d + %d \n", tmp_TPI, pwr_40_1s , diff_ofdm_1t); + + + // PATH B, OFDM + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_ofdm_1t = (priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_B[ch_idx] & 0x0f); + diff_ofdm_1t = convert_diff(diff_ofdm_1t); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_ofdm_1t); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_OFDM_B(priv, writeVal); + + //printk("Write_OFDM_A %d = %d + %d \n", tmp_TPI, pwr_40_1s , diff_ofdm_1t); + + + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == 0 || priv->pmib->dot11nConfigEntry.dot11nUse40M == 4 || priv->pmib->dot11nConfigEntry.dot11nUse40M == 5) { + //PATH A, BW20-1S + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_bw20_1s = ((priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_A[ch_idx] & 0xf0) >> 4); + diff_bw20_1s = convert_diff(diff_bw20_1s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw20_1s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_A(priv, writeVal); + + //printk("Write_1S_A %d = %d + %d \n", tmp_TPI, pwr_40_1s , diff_bw20_1s); + + + //PATH A, BW20-2S + diff_bw20_2s = (priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_A[ch_idx] & 0x0f); + diff_bw20_2s = convert_diff(diff_bw20_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw20_1s + diff_bw20_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_A(priv, writeVal); + + //printk("Write_2S_A %d = %d + %d + %d\n", tmp_TPI, pwr_40_1s , diff_bw20_1s, diff_bw20_2s); + + // ==== // + + //PATH B, BW20-1S + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_bw20_1s = ((priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_B[ch_idx] & 0xf0) >> 4); + diff_bw20_1s = convert_diff(diff_bw20_1s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw20_1s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_B(priv, writeVal); + + //printk("Write_1S_B %d = %d + %d \n", tmp_TPI, pwr_40_1s , diff_bw20_1s); + + //PATH B, BW20-2S + diff_bw20_2s = (priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_B[ch_idx] & 0x0f); + diff_bw20_2s = convert_diff(diff_bw20_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw20_1s + diff_bw20_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_B(priv, writeVal); + + //printk("Write_2S_B %d = %d + %d + %d\n", tmp_TPI, pwr_40_1s , diff_bw20_1s, diff_bw20_2s); + + } else if (priv->pshare->CurrentChannelBW == 1) { + //PATH A, BW40-1S + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + tmp_TPI = pwr_40_1s ; + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_A(priv, writeVal); + + //printk("Write_1S_A %d = %d \n", tmp_TPI, pwr_40_1s); + + + //PATH A, BW40-2S + diff_bw40_2s = ((priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_A[ch_idx] & 0xf0) >> 4); + diff_bw40_2s = convert_diff(diff_bw40_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw40_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_A(priv, writeVal); + + //printk("Write_2S_A %d = %d + %d \n", tmp_TPI, pwr_40_1s , diff_bw40_2s); + + // ==== // + + //PATH B, BW40-1S + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + tmp_TPI = pwr_40_1s ; + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_B(priv, writeVal); + + //printk("Write_1S_B %d = %d \n", tmp_TPI, pwr_40_1s); + + + //PATH A, BW40-2S + diff_bw40_2s = ((priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_B[ch_idx] & 0xf0) >> 4); + diff_bw40_2s = convert_diff(diff_bw40_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw40_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_B(priv, writeVal); + + //printk("Write_2S_B %d = %d + %d \n", tmp_TPI, pwr_40_1s , diff_bw40_2s); + + } else if (priv->pshare->CurrentChannelBW == 2) { + //PATH A, BW80-1S + pwr_40_1s = (priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[ch_idx - 4] + + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[ch_idx + 4]) / 2 ; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_bw80_1s = ((priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_A[ch_idx] & 0xf0) >> 4); + diff_bw80_1s = convert_diff(diff_bw80_1s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw80_1s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_A(priv, writeVal); + + //printk("Write_1S_A %d = %d + %d \n", tmp_TPI, pwr_40_1s , diff_bw80_1s); + + + //PATH A, BW80-2S + diff_bw80_2s = ((priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_A[ch_idx] & 0xf0) >> 4); + diff_bw80_2s = convert_diff(diff_bw80_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw80_1s + diff_bw80_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_A(priv, writeVal); + + //printk("Write_2S_A %d = %d + %d + %d \n", tmp_TPI, pwr_40_1s , diff_bw80_1s, diff_bw80_1s); + + + //PATH B, BW80-1S + pwr_40_1s = (priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[ch_idx - 4] + + priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[ch_idx + 4]) / 2 ; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_bw80_1s = ((priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_B[ch_idx] & 0xf0) >> 4); + diff_bw80_1s = convert_diff(diff_bw80_1s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw80_1s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_B(priv, writeVal); + + //printk("Write_1S_B %d = %d + %d \n", tmp_TPI, pwr_40_1s , diff_bw80_1s); + + + //PATH B, BW80-2S + diff_bw80_2s = ((priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_B[ch_idx] & 0xf0) >> 4); + diff_bw80_2s = convert_diff(diff_bw80_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw80_1s + diff_bw80_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_B(priv, writeVal); + + //printk("Write_2S_B %d = %d + %d + %d \n", tmp_TPI, pwr_40_1s , diff_bw80_1s, diff_bw80_1s); + + } +} + +void Cal_OFDMTxPower_2G(struct rtl8192cd_priv *priv, unsigned char ch_idx) +{ + unsigned char tmp_TPI = 0; + unsigned char pwr_40_1s = 0; + signed char diff_ofdm_1t = 0; + signed char diff_bw40_2s = 0; + signed char diff_bw20_1s = 0; + signed char diff_bw20_2s = 0; + + unsigned int writeVal = 0; +#ifdef POWER_PERCENT_ADJUSTMENT + signed char pwrdiff_percent = PwrPercent2PwrLevel(priv->pmib->dot11RFEntry.power_percent); +#endif + + // PATH A, OFDM + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_ofdm_1t = (priv->pmib->dot11RFEntry.pwrdiff_20BW1S_OFDM1T_A[ch_idx] & 0x0f); + diff_ofdm_1t = convert_diff(diff_ofdm_1t); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_ofdm_1t); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_OFDM_A(priv, writeVal); + + + // PATH B, OFDM + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_ofdm_1t = (priv->pmib->dot11RFEntry.pwrdiff_20BW1S_OFDM1T_B[ch_idx] & 0x0f); + diff_ofdm_1t = convert_diff(diff_ofdm_1t); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_ofdm_1t); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_OFDM_B(priv, writeVal); + + if (priv->pshare->CurrentChannelBW == 0) { + //PATH A, BW20-1S + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_bw20_1s = ((priv->pmib->dot11RFEntry.pwrdiff_20BW1S_OFDM1T_A[ch_idx] & 0xf0) >> 4); + diff_bw20_1s = convert_diff(diff_bw20_1s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw20_1s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_A(priv, writeVal); + + + //PATH A, BW20-2S + diff_bw20_2s = (priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_A[ch_idx] & 0x0f); + diff_bw20_2s = convert_diff(diff_bw20_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw20_1s + diff_bw20_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_A(priv, writeVal); + + // ==== // + + //PATH B, BW20-1S + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + diff_bw20_1s = ((priv->pmib->dot11RFEntry.pwrdiff_20BW1S_OFDM1T_B[ch_idx] & 0xf0) >> 4); + diff_bw20_1s = convert_diff(diff_bw20_1s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw20_1s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_B(priv, writeVal); + + //PATH B, BW20-2S + diff_bw20_2s = (priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_B[ch_idx] & 0x0f); + diff_bw20_2s = convert_diff(diff_bw20_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw20_1s + diff_bw20_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_B(priv, writeVal); + + } else if (priv->pshare->CurrentChannelBW == 1) { + //PATH A, BW40-1S + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + tmp_TPI = pwr_40_1s ; + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_A(priv, writeVal); + + + //PATH A, BW40-2S + diff_bw40_2s = ((priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_A[ch_idx] & 0xf0) >> 4); + diff_bw40_2s = convert_diff(diff_bw40_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw40_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_A(priv, writeVal); + + // ==== // + + //PATH B, BW40-1S + pwr_40_1s = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + pwr_40_1s = POWER_RANGE_CHECK(pwr_40_1s + pwrdiff_percent); +#endif + tmp_TPI = pwr_40_1s ; + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_1S_B(priv, writeVal); + + + //PATH A, BW40-2S + diff_bw40_2s = ((priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_B[ch_idx] & 0xf0) >> 4); + diff_bw40_2s = convert_diff(diff_bw40_2s); + tmp_TPI = POWER_RANGE_CHECK(pwr_40_1s + diff_bw40_2s); + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + Write_2S_B(priv, writeVal); + + } +} +#ifdef TX_PG_8812 +void get_tx_pwr(unsigned int tmp_dw, unsigned char *tmp_b1, unsigned char *tmp_b2, + unsigned char *tmp_b3, unsigned char *tmp_b4) +{ + *tmp_b1 = (tmp_dw & (0xff)); + *tmp_b2 = ((tmp_dw & (0xff00)) >> 8); + *tmp_b3 = ((tmp_dw & (0xff0000)) >> 16); + *tmp_b4 = ((tmp_dw & (0xff000000)) >> 24); +} + +void TxPG_CCK_8812(struct rtl8192cd_priv *priv) +{ + unsigned char b1, b2, b3, b4; + unsigned char* tmp_b1 = &b1; + unsigned char* tmp_b2 = &b2; + unsigned char* tmp_b3 = &b3; + unsigned char* tmp_b4 = &b4; + unsigned int tmp_dw = 0; + unsigned int writeVal = 0; + + tmp_dw = RTL_R32(rTxAGC_A_CCK11_CCK1_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = (unsigned char)(POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->CCKTxAgc_A[3])); + *tmp_b2 = (unsigned char)(POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->CCKTxAgc_A[2])); + *tmp_b3 = (unsigned char)(POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->CCKTxAgc_A[1])); + *tmp_b4 = (unsigned char)(POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->CCKTxAgc_A[0])); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_CCK11_CCK1_JAguar, writeVal); + + tmp_dw = RTL_R32(rTxAGC_B_CCK11_CCK1_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = (unsigned char)(POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->CCKTxAgc_B[3])); + *tmp_b2 = (unsigned char)(POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->CCKTxAgc_B[2])); + *tmp_b3 = (unsigned char)(POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->CCKTxAgc_B[1])); + *tmp_b4 = (unsigned char)(POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->CCKTxAgc_B[0])); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_CCK11_CCK1_JAguar, writeVal); +} + + +void TxPG_OFDM_8812_A(struct rtl8192cd_priv *priv) +{ + unsigned char b1, b2, b3, b4, b5; + unsigned char* tmp_b1 = &b1; + unsigned char* tmp_b2 = &b2; + unsigned char* tmp_b3 = &b3; + unsigned char* tmp_b4 = &b4; + unsigned char* tmp_b5 = &b5; + unsigned int tmp_dw = 0; + unsigned int tmp_dw1 =0; + unsigned int writeVal = 0; + + //printk("TxPG_OFDM_8812_A!!\n"); + tmp_dw = RTL_R32(rTxAGC_A_Ofdm18_Ofdm6_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->OFDMTxAgcOffset_A[3]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->OFDMTxAgcOffset_A[2]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->OFDMTxAgcOffset_A[1]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->OFDMTxAgcOffset_A[0]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_Ofdm18_Ofdm6_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_A_Ofdm54_Ofdm24_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->OFDMTxAgcOffset_A[7]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->OFDMTxAgcOffset_A[6]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->OFDMTxAgcOffset_A[5]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->OFDMTxAgcOffset_A[4]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_Ofdm54_Ofdm24_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_A_MCS3_MCS0_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->MCSTxAgcOffset_A[3]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->MCSTxAgcOffset_A[2]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->MCSTxAgcOffset_A[1]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->MCSTxAgcOffset_A[0]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_MCS3_MCS0_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_A_MCS7_MCS4_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->MCSTxAgcOffset_A[7]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->MCSTxAgcOffset_A[6]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->MCSTxAgcOffset_A[5]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->MCSTxAgcOffset_A[4]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_MCS7_MCS4_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_A_MCS11_MCS8_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->MCSTxAgcOffset_A[11]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->MCSTxAgcOffset_A[10]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->MCSTxAgcOffset_A[9]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->MCSTxAgcOffset_A[8]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_MCS11_MCS8_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_A_MCS15_MCS12_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->MCSTxAgcOffset_A[15]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->MCSTxAgcOffset_A[14]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->MCSTxAgcOffset_A[13]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->MCSTxAgcOffset_A[12]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_MCS15_MCS12_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_A_Nss1Index3_Nss1Index0_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->VHTTxAgcOffset_A[3]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->VHTTxAgcOffset_A[2]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->VHTTxAgcOffset_A[1]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->VHTTxAgcOffset_A[0]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_Nss1Index3_Nss1Index0_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->VHTTxAgcOffset_A[7]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->VHTTxAgcOffset_A[6]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->VHTTxAgcOffset_A[5]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->VHTTxAgcOffset_A[4]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar, writeVal); + + tmp_dw = RTL_R32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar); + tmp_dw1= RTL_R32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar); + get_tx_pwr(tmp_dw1, tmp_b1, tmp_b2, tmp_b3, tmp_b5); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b5 - priv->pshare->phw->VHTTxAgcOffset_A[11]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b5 - priv->pshare->phw->VHTTxAgcOffset_A[10]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->VHTTxAgcOffset_A[9]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->VHTTxAgcOffset_A[8]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_Nss2Index1_Nss1Index8_JAguar, writeVal); + + tmp_dw = RTL_R32(rTxAGC_A_Nss2Index5_Nss2Index2_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->VHTTxAgcOffset_A[15]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->VHTTxAgcOffset_A[14]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->VHTTxAgcOffset_A[13]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->VHTTxAgcOffset_A[12]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_Nss2Index5_Nss2Index2_JAguar, writeVal); + + tmp_dw = RTL_R32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->VHTTxAgcOffset_A[19]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->VHTTxAgcOffset_A[18]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 - priv->pshare->phw->VHTTxAgcOffset_A[17]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 - priv->pshare->phw->VHTTxAgcOffset_A[16]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar, writeVal); +} + + +void TxPG_OFDM_8812_B(struct rtl8192cd_priv *priv) +{ + unsigned char b1, b2, b3, b4, b5; + unsigned char* tmp_b1 = &b1; + unsigned char* tmp_b2 = &b2; + unsigned char* tmp_b3 = &b3; + unsigned char* tmp_b4 = &b4; + unsigned char* tmp_b5 = &b5; + unsigned int tmp_dw = 0; + unsigned int tmp_dw1 =0; + unsigned int writeVal = 0; + + //printk("TxPG_OFDM_8812_B!!\n"); + tmp_dw = RTL_R32(rTxAGC_B_Ofdm18_Ofdm6_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->OFDMTxAgcOffset_B[3]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->OFDMTxAgcOffset_B[2]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->OFDMTxAgcOffset_B[1]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->OFDMTxAgcOffset_B[0]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_Ofdm18_Ofdm6_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_Ofdm54_Ofdm24_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->OFDMTxAgcOffset_B[7]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->OFDMTxAgcOffset_B[6]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->OFDMTxAgcOffset_B[5]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->OFDMTxAgcOffset_B[4]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_Ofdm54_Ofdm24_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_MCS3_MCS0_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->MCSTxAgcOffset_B[3]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->MCSTxAgcOffset_B[2]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->MCSTxAgcOffset_B[1]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->MCSTxAgcOffset_B[0]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_MCS3_MCS0_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_MCS7_MCS4_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->MCSTxAgcOffset_B[7]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->MCSTxAgcOffset_B[6]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->MCSTxAgcOffset_B[5]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->MCSTxAgcOffset_B[4]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_MCS7_MCS4_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_MCS11_MCS8_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->MCSTxAgcOffset_B[11]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->MCSTxAgcOffset_B[10]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->MCSTxAgcOffset_B[9]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->MCSTxAgcOffset_B[8]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_MCS11_MCS8_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_MCS15_MCS12_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->MCSTxAgcOffset_B[15]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->MCSTxAgcOffset_B[14]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->MCSTxAgcOffset_B[13]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->MCSTxAgcOffset_B[12]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_MCS15_MCS12_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_Nss1Index3_Nss1Index0_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->VHTTxAgcOffset_B[3]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->VHTTxAgcOffset_B[2]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->VHTTxAgcOffset_B[1]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->VHTTxAgcOffset_B[0]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_Nss1Index3_Nss1Index0_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->VHTTxAgcOffset_B[7]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->VHTTxAgcOffset_B[6]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->VHTTxAgcOffset_B[5]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->VHTTxAgcOffset_B[4]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_Nss2Index1_Nss1Index8_JAguar); + tmp_dw1= RTL_R32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar); + get_tx_pwr(tmp_dw1, tmp_b1, tmp_b2, tmp_b3, tmp_b5); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b5 - priv->pshare->phw->VHTTxAgcOffset_B[11]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b5 - priv->pshare->phw->VHTTxAgcOffset_B[10]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->VHTTxAgcOffset_B[9]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->VHTTxAgcOffset_B[8]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_Nss2Index1_Nss1Index8_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_Nss2Index5_Nss2Index2_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->VHTTxAgcOffset_B[15]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->VHTTxAgcOffset_B[14]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 + priv->pshare->phw->VHTTxAgcOffset_B[13]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 + priv->pshare->phw->VHTTxAgcOffset_B[12]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_Nss2Index5_Nss2Index2_JAguar, writeVal); + tmp_dw = RTL_R32(rTxAGC_B_Nss2Index9_Nss2Index6_JAguar); + get_tx_pwr(tmp_dw, tmp_b1, tmp_b2, tmp_b3, tmp_b4); + *tmp_b1 = POWER_RANGE_CHECK(*tmp_b1 + priv->pshare->phw->VHTTxAgcOffset_B[19]); + *tmp_b2 = POWER_RANGE_CHECK(*tmp_b2 + priv->pshare->phw->VHTTxAgcOffset_B[18]); + *tmp_b3 = POWER_RANGE_CHECK(*tmp_b3 - priv->pshare->phw->VHTTxAgcOffset_B[17]); + *tmp_b4 = POWER_RANGE_CHECK(*tmp_b4 - priv->pshare->phw->VHTTxAgcOffset_B[16]); + writeVal = (*tmp_b4 << 24) | (*tmp_b3 << 16) | (*tmp_b2 << 8) | *tmp_b1; + RTL_W32(rTxAGC_B_Nss2Index9_Nss2Index6_JAguar, writeVal); +} +#endif + + +#ifdef TXPWR_LMT_8812 + +unsigned char get_byte_from_dw(unsigned int tmp_dw, unsigned char byte_num) +{ + + if (byte_num == 0) + return (tmp_dw & (0xff)); + else if (byte_num == 1) + return ((tmp_dw & (0xff00)) >> 8); + else if (byte_num == 2) + return ((tmp_dw & (0xff0000)) >> 16); + else if (byte_num == 3) + return ((tmp_dw & (0xff000000)) >> 24); + else + return 0; +} + +unsigned int assign_lmt_reg_value(struct rtl8192cd_priv *priv, unsigned int reg_offset, unsigned char max_idx, unsigned char max_idx2) +{ + + unsigned int tmp_dw; + unsigned char reg_val[4]; + unsigned char i=0; + + tmp_dw = RTL_R32(reg_offset); + + //printk("[0x%03x] 0x%08x >> ", reg_offset, tmp_dw); + + get_tx_pwr(tmp_dw, (unsigned char *)®_val[0], (unsigned char *)®_val[1], + (unsigned char *)®_val[2], (unsigned char *)®_val[3]); + + if((reg_offset == rTxAGC_A_Nss2Index1_Nss1Index8_JAguar) || + (reg_offset == rTxAGC_B_Nss2Index1_Nss1Index8_JAguar)) + { + reg_val[0] = POWER_MIN_CHECK(reg_val[0], max_idx); + reg_val[1] = POWER_MIN_CHECK(reg_val[1], max_idx); + reg_val[2] = POWER_MIN_CHECK(reg_val[2], max_idx2); + reg_val[3] = POWER_MIN_CHECK(reg_val[3], max_idx2); + } + else + { + for(i=0; i<4; i++) + { + reg_val[i] = POWER_MIN_CHECK(reg_val[i], max_idx); + } + } + + for(i=0; i<4; i++) + { + reg_val[i] = POWER_RANGE_CHECK(reg_val[i]); + } + + tmp_dw = (reg_val[3] << 24) | (reg_val[2] << 16) | (reg_val[1] << 8) | reg_val[0]; + + //printk("0x%08x\n", tmp_dw); + + RTL_W32(reg_offset, tmp_dw); + +} + +unsigned char check_lmt_valid(struct rtl8192cd_priv *priv, unsigned char phy_band) +{ + unsigned char lmt_valid = 1; + + if(phy_band == PHY_BAND_2G) + if(priv->pshare->txpwr_lmt_CCK == 0) + lmt_valid = 0; + + if(priv->pshare->txpwr_lmt_OFDM == 0) + lmt_valid = 0; + + if(priv->pshare->txpwr_lmt_HT1S == 0) + lmt_valid = 0; + + if(priv->pshare->txpwr_lmt_HT2S == 0) + lmt_valid = 0; + + if(phy_band == PHY_BAND_5G) + { + if(priv->pshare->txpwr_lmt_VHT1S == 0) + lmt_valid = 0; + + if(priv->pshare->txpwr_lmt_VHT2S == 0) + lmt_valid = 0; + } + + if(lmt_valid == 0) + DEBUG_WARN("NO Limit Value, NO limit TX POWER !!!\n limit for cck=%d, ofdm=%d, ht1s=%d, ht2s=%d, vht1s=%d, vht2s=%d\n", + priv->pshare->txpwr_lmt_CCK, + priv->pshare->txpwr_lmt_OFDM, + priv->pshare->txpwr_lmt_HT1S, + priv->pshare->txpwr_lmt_HT2S, + priv->pshare->txpwr_lmt_VHT1S, + priv->pshare->txpwr_lmt_VHT2S + ); + + return lmt_valid; + +} + + +void TxLMT_CCK_8812_A(struct rtl8192cd_priv *priv) +{ + + unsigned int tmp_dw = 0; + unsigned char idx_cck_11m = 0; + char lmt_pg_idx_cck = 0; + unsigned char max_lmt_idx_cck = 0; + + lmt_pg_idx_cck = priv->pshare->txpwr_lmt_CCK - priv->pshare->tgpwr_CCK_new[0]; + + //Cal Max tx pwr idx for CCK + tmp_dw = RTL_R32(rTxAGC_A_CCK11_CCK1_JAguar); + idx_cck_11m = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_cck = idx_cck_11m + lmt_pg_idx_cck; + + assign_lmt_reg_value(priv, rTxAGC_A_CCK11_CCK1_JAguar, max_lmt_idx_cck, 0); +} + +void TxLMT_CCK_8812_B(struct rtl8192cd_priv *priv) +{ + + unsigned int tmp_dw = 0; + unsigned char idx_cck_11m = 0; + char lmt_pg_idx_cck = 0; + unsigned char max_lmt_idx_cck = 0; + + lmt_pg_idx_cck = priv->pshare->txpwr_lmt_CCK - priv->pshare->tgpwr_CCK_new[0]; + + //Cal Max tx pwr idx for CCK + tmp_dw = RTL_R32(rTxAGC_B_CCK11_CCK1_JAguar); + idx_cck_11m = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_cck = idx_cck_11m + lmt_pg_idx_cck; + + assign_lmt_reg_value(priv, rTxAGC_B_CCK11_CCK1_JAguar, max_lmt_idx_cck, 0); +} + + +void TxLMT_OFDM_8812_A(struct rtl8192cd_priv *priv) +{ + + unsigned int tmp_dw = 0; + + unsigned char idx_cck_11m = 0; + unsigned char idx_odfm_54m = 0; + unsigned char idx_ht_mcs7 = 0; + unsigned char idx_ht_mcs15 = 0; + unsigned char idx_vht_1ss_mcs7 =0; + unsigned char idx_vht_2ss_mcs7 =0; + + char lmt_pg_idx_cck, lmt_pg_idx_ofdm = 0; + char lmt_pg_idx_ht1s, lmt_pg_idx_ht2s = 0; + char lmt_pg_idx_vht1s, lmt_pg_idx_vht2s = 0; + + unsigned char max_lmt_idx_cck, max_lmt_idx_ofdm = 0; + unsigned char max_lmt_idx_ht1s, max_lmt_idx_ht2s = 0; + unsigned char max_lmt_idx_vht1s, max_lmt_idx_vht2s = 0; + + lmt_pg_idx_cck = priv->pshare->txpwr_lmt_CCK - priv->pshare->tgpwr_CCK_new[0]; + lmt_pg_idx_ofdm = priv->pshare->txpwr_lmt_OFDM - priv->pshare->tgpwr_OFDM_new[0]; + lmt_pg_idx_ht1s = priv->pshare->txpwr_lmt_HT1S - priv->pshare->tgpwr_HT1S_new[0]; + lmt_pg_idx_ht2s = priv->pshare->txpwr_lmt_HT2S - priv->pshare->tgpwr_HT2S_new[0]; + lmt_pg_idx_vht1s = priv->pshare->txpwr_lmt_VHT1S - priv->pshare->tgpwr_VHT1S_new[0]; + lmt_pg_idx_vht2s = priv->pshare->txpwr_lmt_VHT2S - priv->pshare->tgpwr_VHT2S_new[0]; + + //printk("%d %d %d %d %d %d\n", lmt_pg_idx_cck, lmt_pg_idx_ofdm, + //lmt_pg_idx_ht1s, lmt_pg_idx_ht2s, lmt_pg_idx_vht1s, lmt_pg_idx_vht2s); + + + //Cal Max tx pwr idx for CCK + tmp_dw = RTL_R32(rTxAGC_A_CCK11_CCK1_JAguar); + idx_cck_11m = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_cck = idx_cck_11m + lmt_pg_idx_cck; + + //Cal Max tx pwr idx for OFDM + tmp_dw = RTL_R32(rTxAGC_A_Ofdm54_Ofdm24_JAguar); + idx_odfm_54m = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_ofdm = idx_odfm_54m + lmt_pg_idx_ofdm; + + //Cal Max tx pwr idx for HT1S + tmp_dw = RTL_R32(rTxAGC_A_MCS7_MCS4_JAguar); + idx_ht_mcs7 = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_ht1s = idx_ht_mcs7 + lmt_pg_idx_ht1s; + + //Cal Max tx pwr idx for HT2S + tmp_dw = RTL_R32(rTxAGC_A_MCS15_MCS12_JAguar); + idx_ht_mcs15 = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_ht2s = idx_ht_mcs15 + lmt_pg_idx_ht2s; + + //Cal Max tx pwr idx for VHT1S + tmp_dw = RTL_R32(rTxAGC_A_Nss1Index7_Nss1Index4_JAguar); + idx_vht_1ss_mcs7 = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_vht1s = idx_vht_1ss_mcs7 + lmt_pg_idx_vht1s; + + //Cal Max tx pwr idx for VHT2S + tmp_dw = RTL_R32(rTxAGC_A_Nss2Index9_Nss2Index6_JAguar); + idx_vht_2ss_mcs7 = get_byte_from_dw(tmp_dw, 1); + max_lmt_idx_vht2s = idx_vht_2ss_mcs7 + lmt_pg_idx_vht2s; + + assign_lmt_reg_value(priv, rTxAGC_A_CCK11_CCK1_JAguar, max_lmt_idx_cck, 0); + + assign_lmt_reg_value(priv, rTxAGC_A_Ofdm18_Ofdm6_JAguar, max_lmt_idx_ofdm, 0); + assign_lmt_reg_value(priv, rTxAGC_A_Ofdm54_Ofdm24_JAguar, max_lmt_idx_ofdm, 0); + + assign_lmt_reg_value(priv, rTxAGC_A_MCS3_MCS0_JAguar, max_lmt_idx_ht1s, 0); + assign_lmt_reg_value(priv, rTxAGC_A_MCS7_MCS4_JAguar, max_lmt_idx_ht1s, 0); + assign_lmt_reg_value(priv, rTxAGC_A_MCS11_MCS8_JAguar, max_lmt_idx_ht2s, 0); + assign_lmt_reg_value(priv, rTxAGC_A_MCS15_MCS12_JAguar, max_lmt_idx_ht2s, 0); + + assign_lmt_reg_value(priv, rTxAGC_A_Nss1Index3_Nss1Index0_JAguar, max_lmt_idx_vht1s, 0); + assign_lmt_reg_value(priv, rTxAGC_A_Nss1Index7_Nss1Index4_JAguar, max_lmt_idx_vht1s, 0); + assign_lmt_reg_value(priv, rTxAGC_A_Nss2Index1_Nss1Index8_JAguar, max_lmt_idx_vht1s, max_lmt_idx_vht2s); + assign_lmt_reg_value(priv, rTxAGC_A_Nss2Index5_Nss2Index2_JAguar, max_lmt_idx_vht2s, 0); + assign_lmt_reg_value(priv, rTxAGC_A_Nss2Index9_Nss2Index6_JAguar, max_lmt_idx_vht2s, 0); + +} + + +void TxLMT_OFDM_8812_B(struct rtl8192cd_priv *priv) +{ + + unsigned int tmp_dw = 0; + + unsigned char idx_cck_11m = 0; + unsigned char idx_odfm_54m = 0; + unsigned char idx_ht_mcs7 = 0; + unsigned char idx_ht_mcs15 = 0; + unsigned char idx_vht_1ss_mcs7 =0; + unsigned char idx_vht_2ss_mcs7 =0; + + char lmt_pg_idx_cck, lmt_pg_idx_ofdm = 0; + char lmt_pg_idx_ht1s, lmt_pg_idx_ht2s = 0; + char lmt_pg_idx_vht1s, lmt_pg_idx_vht2s = 0; + + unsigned char max_lmt_idx_cck, max_lmt_idx_ofdm = 0; + unsigned char max_lmt_idx_ht1s, max_lmt_idx_ht2s = 0; + unsigned char max_lmt_idx_vht1s, max_lmt_idx_vht2s = 0; + + lmt_pg_idx_cck = priv->pshare->txpwr_lmt_CCK - priv->pshare->tgpwr_CCK_new[1]; + lmt_pg_idx_ofdm = priv->pshare->txpwr_lmt_OFDM - priv->pshare->tgpwr_OFDM_new[1]; + lmt_pg_idx_ht1s = priv->pshare->txpwr_lmt_HT1S - priv->pshare->tgpwr_HT1S_new[1]; + lmt_pg_idx_ht2s = priv->pshare->txpwr_lmt_HT2S - priv->pshare->tgpwr_HT2S_new[1]; + lmt_pg_idx_vht1s = priv->pshare->txpwr_lmt_VHT1S - priv->pshare->tgpwr_VHT1S_new[1]; + lmt_pg_idx_vht2s = priv->pshare->txpwr_lmt_VHT2S - priv->pshare->tgpwr_VHT2S_new[1]; + + //printk("%d %d %d %d %d %d\n", lmt_pg_idx_cck, lmt_pg_idx_ofdm, + //lmt_pg_idx_ht1s, lmt_pg_idx_ht2s, lmt_pg_idx_vht1s, lmt_pg_idx_vht2s); + + //Cal Max tx pwr idx for CCK + tmp_dw = RTL_R32(rTxAGC_B_CCK11_CCK1_JAguar); + idx_cck_11m = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_cck = idx_cck_11m + lmt_pg_idx_cck; + + //Cal Max tx pwr idx for OFDM + tmp_dw = RTL_R32(rTxAGC_B_Ofdm54_Ofdm24_JAguar); + idx_odfm_54m = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_ofdm = idx_odfm_54m + lmt_pg_idx_ofdm; + + //Cal Max tx pwr idx for HT1S + tmp_dw = RTL_R32(rTxAGC_B_MCS7_MCS4_JAguar); + idx_ht_mcs7 = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_ht1s = idx_ht_mcs7 + lmt_pg_idx_ht1s; + + //Cal Max tx pwr idx for HT2S + tmp_dw = RTL_R32(rTxAGC_B_MCS15_MCS12_JAguar); + idx_ht_mcs15 = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_ht2s = idx_ht_mcs15 + lmt_pg_idx_ht2s; + + //Cal Max tx pwr idx for VHT1S + tmp_dw = RTL_R32(rTxAGC_B_Nss1Index7_Nss1Index4_JAguar); + idx_vht_1ss_mcs7 = get_byte_from_dw(tmp_dw, 3); + max_lmt_idx_vht1s = idx_vht_1ss_mcs7 + lmt_pg_idx_vht1s; + + //Cal Max tx pwr idx for VHT2S + tmp_dw = RTL_R32(rTxAGC_B_Nss2Index9_Nss2Index6_JAguar); + idx_vht_2ss_mcs7 = get_byte_from_dw(tmp_dw, 1); + max_lmt_idx_vht2s = idx_vht_2ss_mcs7 + lmt_pg_idx_vht2s; + + assign_lmt_reg_value(priv, rTxAGC_B_CCK11_CCK1_JAguar, max_lmt_idx_cck, 0); + + assign_lmt_reg_value(priv, rTxAGC_B_Ofdm18_Ofdm6_JAguar, max_lmt_idx_ofdm, 0); + assign_lmt_reg_value(priv, rTxAGC_B_Ofdm54_Ofdm24_JAguar, max_lmt_idx_ofdm, 0); + + assign_lmt_reg_value(priv, rTxAGC_B_MCS3_MCS0_JAguar, max_lmt_idx_ht1s, 0); + assign_lmt_reg_value(priv, rTxAGC_B_MCS7_MCS4_JAguar, max_lmt_idx_ht1s, 0); + assign_lmt_reg_value(priv, rTxAGC_B_MCS11_MCS8_JAguar, max_lmt_idx_ht2s, 0); + assign_lmt_reg_value(priv, rTxAGC_B_MCS15_MCS12_JAguar, max_lmt_idx_ht2s, 0); + + assign_lmt_reg_value(priv, rTxAGC_B_Nss1Index3_Nss1Index0_JAguar, max_lmt_idx_vht1s, 0); + assign_lmt_reg_value(priv, rTxAGC_B_Nss1Index7_Nss1Index4_JAguar, max_lmt_idx_vht1s, 0); + assign_lmt_reg_value(priv, rTxAGC_B_Nss2Index1_Nss1Index8_JAguar, max_lmt_idx_vht1s, max_lmt_idx_vht2s); + assign_lmt_reg_value(priv, rTxAGC_B_Nss2Index5_Nss2Index2_JAguar, max_lmt_idx_vht2s, 0); + assign_lmt_reg_value(priv, rTxAGC_B_Nss2Index9_Nss2Index6_JAguar, max_lmt_idx_vht2s, 0); + +} + + +#endif + +void PHY_SetOFDMTxPower_8812(struct rtl8192cd_priv *priv, unsigned char channel) +{ + unsigned char ch_idx = 0; + // unsigned char tmp_TPI = 0; + unsigned char phy_band = 0; + u4Byte pwrdiff = 0x06060606; + + if (channel > 0) + ch_idx = (channel - 1); + else { + printk("Error Channel !!\n"); + return; + } + + if (channel > 14) + phy_band = PHY_BAND_5G; + else + phy_band = PHY_BAND_2G; + +#if 0 + printk("pwrlevel5GHT40_1S_A[%d]= %d \n", channel, priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[ch_idx]); + printk("pwrdiff_5G_20BW1S_OFDM1T_A[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_A[ch_idx]); + printk("pwrdiff_40BW2S_20BW2S_A[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_A[ch_idx]); + printk("pwrdiff_5G_20BW1S_OFDM1T_A[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_A[ch_idx]); + printk("pwrdiff_5G_40BW2S_20BW2S_A[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_A[ch_idx]); + printk("pwrdiff_5G_80BW1S_160BW1S_A[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_A[ch_idx]); + printk("pwrdiff_5G_80BW2S_160BW2S_A[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_A[ch_idx]); + + printk("pwrlevel5GHT40_1S_B[%d]= %d \n", channel, priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[ch_idx]); + printk("pwrdiff_5G_20BW1S_OFDM1T_B[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_B[ch_idx]); + printk("pwrdiff_40BW2S_20BW2S_B[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_40BW2S_20BW2S_B[ch_idx]); + printk("pwrdiff_5G_20BW1S_OFDM1T_B[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_20BW1S_OFDM1T_B[ch_idx]); + printk("pwrdiff_5G_40BW2S_20BW2S_B[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_40BW2S_20BW2S_B[ch_idx]); + printk("pwrdiff_5G_80BW1S_160BW1S_B[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_80BW1S_160BW1S_B[ch_idx]); + printk("pwrdiff_5G_80BW2S_160BW2S_B[%d]= 0x%x \n", channel, priv->pmib->dot11RFEntry.pwrdiff_5G_80BW2S_160BW2S_B[ch_idx]); +#endif + + if (phy_band == PHY_BAND_5G) { + if ((priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[ch_idx] == 0) + || (priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[ch_idx] == 0)) { + use_DefaultOFDMTxPower_8812(priv); + return; + } + Cal_OFDMTxPower_5G(priv, ch_idx); + } else if (phy_band == PHY_BAND_2G) { + if ((priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[ch_idx] == 0) + || (priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[ch_idx] == 0)) { + use_DefaultOFDMTxPower_8812(priv); + return; + } + Cal_OFDMTxPower_2G(priv, ch_idx); + } + +#ifdef TX_PG_8812 + TxPG_OFDM_8812_A(priv); + TxPG_OFDM_8812_B(priv); +#endif + +#ifdef TXPWR_LMT_8812 + if (!priv->pshare->rf_ft_var.disable_txpwrlmt) + { + if (check_lmt_valid(priv, phy_band)) + { + TxLMT_OFDM_8812_A(priv); + TxLMT_OFDM_8812_B(priv); + } + } + +#endif + +} + +void PHY_SetCCKTxPower_8812(struct rtl8192cd_priv *priv, unsigned char channel) +{ + unsigned int def_power = 0x20202020;//0x12121212; + unsigned char ch_idx = 0; + unsigned char tmp_TPI = 0; + unsigned char phy_band = 0; + unsigned int writeVal = 0; + u4Byte pwrdiff = 0x06060606; +#ifdef POWER_PERCENT_ADJUSTMENT + signed char pwrdiff_percent = PwrPercent2PwrLevel(priv->pmib->dot11RFEntry.power_percent); +#endif + + if (channel > 0) + ch_idx = (channel - 1); + else { + printk("Error Channel !!\n"); + return; + } + + if (channel > 14) + phy_band = PHY_BAND_5G; + else + phy_band = PHY_BAND_2G; + + if ((priv->pmib->dot11RFEntry.pwrlevelCCK_A[ch_idx] == 0) + && (priv->pmib->dot11RFEntry.pwrlevelCCK_B[ch_idx] == 0)) { + //printk("NO Calibration data, use default CCK power = 0x%x\n", def_power); + RTL_W32(rTxAGC_A_CCK11_CCK1_JAguar, def_power); + RTL_W32(rTxAGC_B_CCK11_CCK1_JAguar, def_power); + return; + } + + if (phy_band == PHY_BAND_2G) { + //printk("pwrlevelCCK_A[%d]= %d \n", ch_idx, priv->pmib->dot11RFEntry.pwrlevelCCK_A[ch_idx]); + //printk("pwrlevelCCK_B[%d]= %d \n", ch_idx, priv->pmib->dot11RFEntry.pwrlevelCCK_B[ch_idx]); + + //PATH A + tmp_TPI = priv->pmib->dot11RFEntry.pwrlevelCCK_A[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + tmp_TPI = POWER_RANGE_CHECK(tmp_TPI + pwrdiff_percent); +#endif + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + RTL_W32(rTxAGC_A_CCK11_CCK1_JAguar, writeVal); + + //PATH B + tmp_TPI = priv->pmib->dot11RFEntry.pwrlevelCCK_B[ch_idx]; +#ifdef POWER_PERCENT_ADJUSTMENT + tmp_TPI = POWER_RANGE_CHECK(tmp_TPI + pwrdiff_percent); +#endif + writeVal = (tmp_TPI << 24) | (tmp_TPI << 16) | (tmp_TPI << 8) | tmp_TPI; + RTL_W32(rTxAGC_B_CCK11_CCK1_JAguar, writeVal); + } +#ifdef TX_PG_8812 + TxPG_CCK_8812(priv); +#endif + +#ifdef TXPWR_LMT_8812 + if (!priv->pshare->rf_ft_var.disable_txpwrlmt) + { + if (check_lmt_valid(priv, phy_band)) + { + TxLMT_CCK_8812_A(priv); + TxLMT_CCK_8812_B(priv); + } + } +#endif + +} + + + + + + + + +// Firmware + +#define MAX_PAGE_SIZE 4096 // @ page : 4k bytes +#define FW_START_ADDRESS 0x1000 +#define FWDL_ChkSum_rpt BIT(2) + +extern unsigned char *data_rtl8812fw_start, *data_rtl8812fw_end; +extern unsigned char *data_rtl8812fw_n_start, *data_rtl8812fw_n_end; //for_8812_mp_chip +#ifdef AC2G_256QAM +extern unsigned char *data_rtl8812fw_n_2g_start, *data_rtl8812fw_n_2g_end; +#endif + + +VOID +_8051Reset8812( + struct rtl8192cd_priv *priv +) +{ + u1Byte u1bTmp; + u1bTmp = RTL_R8(REG_SYS_FUNC_EN_8812 + 1); + RTL_W8(REG_SYS_FUNC_EN_8812 + 1, u1bTmp & (~BIT2)); + RTL_W8( REG_SYS_FUNC_EN_8812 + 1, u1bTmp | (BIT2)); +// RT_TRACE(COMP_INIT, DBG_LOUD, ("=====> _8051Reset8812(): 8051 reset success .\n")); +} + + +VOID +_FWDownloadEnable_8812( + struct rtl8192cd_priv *priv, + BOOLEAN enable +) +{ + u1Byte tmp; + + if (enable) { + // MCU firmware download enable. + RTL_W8( REG_MCUFWDL_8812, 0x05); + + // Clear Rom DL enable + tmp = RTL_R8( REG_MCUFWDL_8812 + 2); + RTL_W8( REG_MCUFWDL_8812 + 2, tmp & 0xf7); + } else { + // MCU firmware download enable. + tmp = RTL_R8( REG_MCUFWDL_8812); + RTL_W8( REG_MCUFWDL_8812, tmp & 0xfe); + } +} + +VOID +_FillDummy_8812( + pu1Byte pFwBuf, + pu4Byte pFwLen +) +{ + u4Byte FwLen = *pFwLen; + u1Byte remain = (u1Byte)(FwLen % 4); + remain = (remain == 0) ? 0 : (4 - remain); + + while (remain > 0) { + pFwBuf[FwLen] = 0; + FwLen++; + remain--; + } + + *pFwLen = FwLen; +} + + + +// BlockWrite: +// 92DU----------use 64-Byte/8-Byte/1-Byte (PlatformIOWriteNByte) +// 92CU/8723U----use 4-Byte/1-Byte (PlatformIOWriteNByte) +// PCI/SDIO------use 4-Byte/1-Byte (PlatformEFIOWrite4Byte) +// 92CU [MacOS]-- use 196-Byte/8-Byte/1-Byte (PlatformIOWriteNByte) + +VOID +_BlockWrite_8812( + struct rtl8192cd_priv *priv, + IN PVOID buffer, + IN u4Byte buffSize +) +{ + u4Byte blockSize_p1 = 4; // (Default) Phase #1 : PCI muse use 4-byte write to download FW + u4Byte blockSize_p2 = 8; // Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. + u4Byte blockSize_p3 = 1; // Phase #3 : Use 1-byte, the remnant of FW image. + u4Byte blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0; + u4Byte remainSize_p1 = 0, remainSize_p2 = 0; + pu1Byte bufferPtr = (pu1Byte)buffer; + u4Byte i = 0, offset = 0; + + + //3 Phase #1 + blockCount_p1 = buffSize / blockSize_p1; + remainSize_p1 = buffSize % blockSize_p1; + + + for (i = 0 ; i < blockCount_p1 ; i++) { + RTL_W32( (FW_START_ADDRESS + i * blockSize_p1), cpu_to_le32(*((pu4Byte)(bufferPtr + i * blockSize_p1)))); + } + + //3 Phase #2 + if (remainSize_p1) { + offset = blockCount_p1 * blockSize_p1; + + blockCount_p2 = remainSize_p1 / blockSize_p2; + remainSize_p2 = remainSize_p1 % blockSize_p2; + + } + + //3 Phase #3 + if (remainSize_p2) { + offset = (blockCount_p1 * blockSize_p1) + (blockCount_p2 * blockSize_p2); + blockCount_p3 = remainSize_p2 / blockSize_p3; + + // RT_TRACE(COMP_INIT,DBG_LOUD,("_BlockWrite_8812[P3] ::buffSize_p3( %d) blockSize_p3( %d) blockCount_p3( %d) \n",(buffSize-offset),blockSize_p3, blockCount_p3)); + + for (i = 0 ; i < blockCount_p3 ; i++) { + RTL_W8( (FW_START_ADDRESS + offset + i), *(bufferPtr + offset + i)); + } + } +} + + +VOID +_PageWrite_8812( + struct rtl8192cd_priv *priv, + IN u4Byte page, + IN PVOID buffer, + IN u4Byte size +) +{ + u1Byte value8; + u1Byte u8Page = (u1Byte) (page & 0x07) ; + + value8 = (RTL_R8(REG_MCUFWDL_8812 + 2) & 0xF8 ) | u8Page ; + RTL_W8(REG_MCUFWDL_8812 + 2, value8); + + _BlockWrite_8812(priv, buffer, size); +} + + +VOID +_WriteFW_8812( + struct rtl8192cd_priv *priv, + IN PVOID buffer, + IN u4Byte size +) +{ + // Since we need dynamic decide method of dwonload fw, so we call this function to get chip version. + // We can remove _ReadChipVersion from ReadAdapterInfo8192C later. + u4Byte pageNums, remainSize ; + u4Byte page, offset; + pu1Byte bufferPtr = (pu1Byte)buffer; + +#if 1//DEV_BUS_TYPE==RT_PCI_INTERFACE + // 20100120 Joseph: Add for 88CE normal chip. + // Fill in zero to make firmware image to dword alignment. + // _FillDummy_8812(bufferPtr, &size); +#endif + + pageNums = size / MAX_PAGE_SIZE ; + + // RT_ASSERT((pageNums <= 8), ("Page numbers should not greater then 8 \n")); + + remainSize = size % MAX_PAGE_SIZE; + + for (page = 0; page < pageNums; page++) { + offset = page * MAX_PAGE_SIZE; + _PageWrite_8812(priv, page, (bufferPtr + offset), MAX_PAGE_SIZE); + } + if (remainSize) { + offset = pageNums * MAX_PAGE_SIZE; + page = pageNums; + _PageWrite_8812(priv, page, (bufferPtr + offset), remainSize); + } + // RT_TRACE(COMP_INIT, DBG_LOUD, ("_WriteFW_8812 Done- for Normal chip.\n")); +} + + +RT_STATUS +_FWFreeToGo8812( + struct rtl8192cd_priv *priv + +) +{ + u4Byte counter = 0; + u4Byte value32; + + // polling CheckSum report + do { + value32 = RTL_R32( REG_MCUFWDL_8812); + } while ((counter ++ < 6000) && (!(value32 & FWDL_ChkSum_rpt ))); + + if (counter >= 24000) { + // RT_TRACE(COMP_INIT, DBG_SERIOUS, ("_FWFreeToGo8812:: chksum report faill ! REG_MCUFWDL:0x%08x .\n",value32)); + return RT_STATUS_FAILURE; + } + // RT_TRACE(COMP_INIT, DBG_LOUD, ("_FWFreeToGo8812:: Checksum report OK ! REG_MCUFWDL:0x%08x .\n",value32)); + + value32 = RTL_R32( REG_MCUFWDL_8812); + value32 |= MCUFWDL_RDY; + value32 &= ~WINTINI_RDY; + RTL_W32( REG_MCUFWDL_8812, value32); + + _8051Reset8812(priv); + + // polling for FW ready + counter = 0; + do { + if (RTL_R32( REG_MCUFWDL_8812) & WINTINI_RDY) { + // RT_TRACE(COMP_INIT, DBG_SERIOUS, ("Polling FW ready success!! REG_MCUFWDL:0x%08x in %d times.\n",PlatformEFIORead4Byte(Adapter, REG_MCUFWDL_8812),counter)); + return RT_STATUS_SUCCESS; + } + // PlatformStallExecution(5); + delay_us(5); + } while (counter++ < 24000); + + panic_printk("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", RTL_R32( REG_MCUFWDL_8812) ); + return RT_STATUS_FAILURE; +} + + +RT_STATUS +FirmwareDownload8812( + struct rtl8192cd_priv *priv +) +{ + RT_STATUS rtStatus = RT_STATUS_SUCCESS; + + //u4Byte FwImageLen = 0; + u1Byte *pFirmwareBuf; + u4Byte FirmwareLen; + + RTL_W8( 0xf0, (RTL_R8(0xf0)& ~BIT(7))); + + if (IS_TEST_CHIP(priv)) { //for_8812_mp_chip + pFirmwareBuf = data_rtl8812fw_start + 32; + FirmwareLen = data_rtl8812fw_end - data_rtl8812fw_start - 32; +#ifdef AC2G_256QAM + } else if (is_ac2g(priv)) { + pFirmwareBuf = data_rtl8812fw_n_2g_start + 32; + FirmwareLen = data_rtl8812fw_n_2g_end - data_rtl8812fw_n_2g_start - 32; +#endif + } else { + pFirmwareBuf = data_rtl8812fw_n_start + 32; + FirmwareLen = data_rtl8812fw_n_end - data_rtl8812fw_n_start - 32; + } + + // panic_printk("%s, %d%x, %x\n", __FUNCTION__, __LINE__, pFirmwareBuf, FirmwareLen); + + + { + if (RTL_R8( REG_MCUFWDL_8812)&BIT7) { //8051 RAM code + RTL_W8(REG_MCUFWDL_8812, 0x00); + _8051Reset8812(priv); + } + } + + + + _FWDownloadEnable_8812(priv, TRUE); + + _WriteFW_8812(priv, pFirmwareBuf, FirmwareLen); + + _FWDownloadEnable_8812(priv, FALSE); + + + rtStatus = _FWFreeToGo8812(priv); + + if (RT_STATUS_SUCCESS != rtStatus) { + panic_printk("Firmware is not ready to run!\n") ; + goto Exit; + } + + +Exit: + + panic_printk(" <=== FirmwareDownload8812()\n"); + return rtStatus; + +} + + +// 8812 H2C + +BOOLEAN +CheckFwReadLastH2C_8812( + struct rtl8192cd_priv *priv, + IN u1Byte BoxNum +) +{ + u1Byte valHMETFR; + BOOLEAN Result = FALSE; + + valHMETFR = RTL_R8( REG_HMETFR_8812); + + // Do not seperate to 91C and 88C, we use the same setting. Suggested by SD4 Filen. 2009.12.03. + if (((valHMETFR >> BoxNum)&BIT0) == 0) + Result = TRUE; + + return Result; +} + + +u1Byte +FillH2CCmd8812( + struct rtl8192cd_priv *priv, + IN u1Byte ElementID, + IN u4Byte CmdLen, + IN pu1Byte pCmdBuffer +) +{ + + u1Byte ioStatus = 0; + u1Byte BoxNum; + u2Byte BOXReg = 0, BOXExtReg = 0; + // u1Byte U1btmp; //Read 0x1bf + BOOLEAN bFwReadClear = FALSE; + u1Byte BufIndex = 0; + u1Byte WaitH2cLimmit = 0; + u1Byte BoxContent[4], BoxExtContent[4]; + u1Byte idx = 0; + + if (!GET_ROOT(priv)->bFWReady) + return 1; + + // 1. Find the last BOX number which has been writen. + BoxNum = priv->pshare->fw_q_fifo_count; //pHalData->LastHMEBoxNum; + switch (BoxNum) { + case 0: + BOXReg = REG_HMEBOX_0_8812; + BOXExtReg = REG_HMEBOX_EXT0_8812; + break; + case 1: + BOXReg = REG_HMEBOX_1_8812; + BOXExtReg = REG_HMEBOX_EXT1_8812; + break; + case 2: + BOXReg = REG_HMEBOX_2_8812; + BOXExtReg = REG_HMEBOX_EXT2_8812; + break; + case 3: + BOXReg = REG_HMEBOX_3_8812; + BOXExtReg = REG_HMEBOX_EXT3_8812; + break; + default: + break; + } + + // 2. Check if the box content is empty. + while (!bFwReadClear) { + bFwReadClear = CheckFwReadLastH2C_8812(priv, BoxNum); + if (WaitH2cLimmit++ >= 100) { + ioStatus = 1; + return ioStatus; + } else if (!bFwReadClear) { + delay_us(10); //us + } + } + + // 4. Fill the H2C cmd into box + memset(BoxContent, 0, sizeof(BoxContent)); + memset(BoxExtContent, 0, sizeof(BoxExtContent)); + + BoxContent[0] = ElementID; // Fill element ID + // RTPRINT(FFW, FW_MSG_H2C_CONTENT, ("[FW], Write ElementID BOXReg(%4x) = %2x \n", BOXReg, ElementID)); + + switch (CmdLen) { + case 1: + case 2: + case 3: { + //BoxContent[0] &= ~(BIT7); + memcpy((pu1Byte)(BoxContent) + 1, pCmdBuffer + BufIndex, CmdLen); + //For Endian Free. + for (idx = 0; idx < 4; idx++) { + RTL_W8(BOXReg + idx, BoxContent[idx]); + } + break; + } + case 4: + case 5: + case 6: + case 7: { + //BoxContent[0] |= (BIT7); + memcpy((pu1Byte)(BoxExtContent), pCmdBuffer + BufIndex + 3, (CmdLen - 3)); + memcpy((pu1Byte)(BoxContent) + 1, pCmdBuffer + BufIndex, 3); + //For Endian Free. + for (idx = 0 ; idx < 4 ; idx ++) { + RTL_W8( BOXExtReg + idx, BoxExtContent[idx]); + } + for (idx = 0 ; idx < 4 ; idx ++) { + RTL_W8( BOXReg + idx, BoxContent[idx]); + } + break; + } + + default: + // RTPRINT(FFW, FW_MSG_H2C_STATE, ("[FW], Invalid command len=%d!!!\n", CmdLen)); + ioStatus = 2; + return ioStatus; + break; + } + + if (++priv->pshare->fw_q_fifo_count > 3) + priv->pshare->fw_q_fifo_count = 0; + + // RTPRINT(FFW, FW_MSG_H2C_CONTENT, ("[FW], pHalData->LastHMEBoxNum = %d\n", pHalData->LastHMEBoxNum)); + return ioStatus; +} + + + + + + + +VOID +SetBcnCtrlReg_8812( + struct rtl8192cd_priv *priv, + IN u1Byte SetBits, + IN u1Byte ClearBits +) +{ + u1Byte tmp = RTL_R8(REG_BCN_CTRL_8812); + + tmp |= SetBits; + tmp &= ~ClearBits; + + RTL_W8(REG_BCN_CTRL_8812, tmp); +} + + +u1Byte +MRateIdxToARFRId8812( + struct rtl8192cd_priv *priv, + u1Byte RateIdx, + u1Byte RfType +) +{ + u1Byte Ret = 0; + + switch (RateIdx) { + + case RATR_INX_WIRELESS_NGB: + if (RfType == MIMO_1T1R) + Ret = 1; + else + Ret = 0; + break; + + case RATR_INX_WIRELESS_N: + case RATR_INX_WIRELESS_NG: + if (RfType == MIMO_1T1R) + Ret = 5; + else + Ret = 4; + break; + + case RATR_INX_WIRELESS_NB: + if (RfType == MIMO_1T1R) + Ret = 3; + else + Ret = 2; + break; + + case RATR_INX_WIRELESS_GB: + Ret = 6; + break; + + case RATR_INX_WIRELESS_G: + Ret = 7; + break; + + case RATR_INX_WIRELESS_B: + Ret = 8; + break; + + case RATR_INX_WIRELESS_MC: + if (!(priv->pmib->dot11BssType.net_work_type & WIRELESS_11A)) + Ret = 6; + else + Ret = 7; + break; + case RATR_INX_WIRELESS_AC_N: + if (RfType == MIMO_1T1R) + Ret = 10; + else + Ret = 9; + break; + + default: + Ret = 0; + break; + } + + return Ret; +} + +u1Byte +Get_RA_BW( + BOOLEAN bCurTxBW80MHz, + BOOLEAN bCurTxBW40MHz +) +{ + u1Byte BW = 0; + if (bCurTxBW80MHz) + BW = 2; + else if (bCurTxBW40MHz) + BW = 1; + else + BW = 0; + + return BW; +} + + + +#if 0 +typedef enum _WIRELESS_MODE { + WIRELESS_MODE_UNKNOWN = 0x00, + WIRELESS_MODE_A = 0x01, + WIRELESS_MODE_B = 0x02, + WIRELESS_MODE_G = 0x04, + WIRELESS_MODE_AUTO = 0x08, + WIRELESS_MODE_N_24G = 0x10, + WIRELESS_MODE_N_5G = 0x20, + WIRELESS_MODE_AC_5G = 0x40 +} WIRELESS_MODE; +#endif + +#define MIMO_PS_STATIC 0 +#define MIMO_PS_DYNAMIC 1 +#define MIMO_PS_NOLIMIT 3 + +#define FillOctetString(_os,_octet,_len) \ + (_os).Octet=(pu1Byte)(_octet); \ + (_os).Length=(_len); + + +u1Byte +Get_VHT_ENI( + u4Byte IOTAction, + u1Byte WirelessMode, + u4Byte ratr_bitmap +) +{ + u1Byte Ret = 0; + if (WirelessMode < WIRELESS_MODE_N_24G) + Ret = 0; + else if (WirelessMode == WIRELESS_MODE_N_24G || WirelessMode == WIRELESS_MODE_N_5G) { +#if 0 + //if(IOTAction == HT_IOT_VHT_HT_MIX_MODE) + { + if (ratr_bitmap & BIT20) // Mix , 2SS + Ret = 3; + else // Mix, 1SS + Ret = 2; + } +#else + Ret = 0; +#endif + + } else if (WirelessMode == WIRELESS_MODE_AC_5G) + Ret = 1; // VHT + + return (Ret << 4); +} + + + +BOOLEAN +Get_RA_ShortGI( + struct rtl8192cd_priv *priv, + struct stat_info * pEntry, + IN WIRELESS_MODE WirelessMode, + IN u1Byte ChnlBW +) +{ + BOOLEAN bShortGI; + + BOOLEAN bShortGI20MHz = FALSE, bShortGI40MHz = FALSE, bShortGI80MHz = FALSE; + + if ( WirelessMode == WIRELESS_MODE_N_24G || + WirelessMode == WIRELESS_MODE_N_5G || + WirelessMode == WIRELESS_MODE_AC_5G ) { + if (pEntry->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_) && + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M) { + bShortGI20MHz = TRUE; + } + if (pEntry->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_) + && priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M) { + bShortGI40MHz = TRUE; + } + if (WirelessMode == WIRELESS_MODE_AC_5G) { + if ( (cpu_to_le32(pEntry->vht_cap_buf.vht_cap_info) & BIT(SHORT_GI80M_E)) + && priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M) + bShortGI80MHz = TRUE; +#if 0 +// disable SGI when LDPC is enabled in AC mode + if((pEntry->is_realtek_sta) && (priv->pmib->dot11nConfigEntry.dot11nLDPC == 1) && + ((pEntry->ht_cap_len && cpu_to_le16(pEntry->ht_cap_buf.ht_cap_info) & _HTCAP_SUPPORT_RX_LDPC_) || + (pEntry->vht_cap_len && (cpu_to_le32(pEntry->vht_cap_buf.vht_cap_info) & BIT(RX_LDPC_E)))) ) { + bShortGI80MHz = bShortGI40MHz = bShortGI20MHz = 0; + } +#endif + } + } + + switch (ChnlBW) { + case HT_CHANNEL_WIDTH_20_40: + bShortGI = bShortGI40MHz; + break; + case HT_CHANNEL_WIDTH_80: + bShortGI = bShortGI80MHz; + break; + default: + case HT_CHANNEL_WIDTH_20: + bShortGI = bShortGI20MHz; + break; + } + return bShortGI; +} + + +u4Byte +RateToBitmap_2SSVHT( + pu1Byte pVHTRate +) +{ + + u1Byte i, j , tmpRate; + u4Byte RateBitmap = 0; + + for (i = j = 0; i < 4; i += 2, j += 10) { + tmpRate = (pVHTRate[0] >> i) & 3; + + switch (tmpRate) { + case 2: + RateBitmap = RateBitmap | (0x03ff << j); + break; + case 1: + RateBitmap = RateBitmap | (0x01ff << j); + break; + + case 0: + RateBitmap = RateBitmap | (0x00ff << j); + break; + + default: + break; + } + } + + return RateBitmap; +} + + +u4Byte +Get_VHT_HT_Mix_Ratrbitmap( + u4Byte IOTAction, + WIRELESS_MODE WirelessMode, + u4Byte HT_ratr_bitmap, + u4Byte VHT_ratr_bitmap +) +{ + u4Byte ratr_bitmap = 0; + if (WirelessMode == WIRELESS_MODE_N_24G || WirelessMode == WIRELESS_MODE_N_5G) { + /* + if(IOTAction == HT_IOT_VHT_HT_MIX_MODE) + ratr_bitmap = HT_ratr_bitmap | BIT28 | BIT29; + else + ratr_bitmap = HT_ratr_bitmap; + */ + } else + ratr_bitmap = VHT_ratr_bitmap; + + return ratr_bitmap; +} + + +#ifdef AC2G_256QAM +char is_ac2g(struct rtl8192cd_priv * priv) +{ + + unsigned char ac2g = 0; + + if((GET_CHIP_VER(priv)== VERSION_8812E) || (GET_CHIP_VER(priv)== VERSION_8881A)) + if(priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC + && ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) == 0) + && (priv->pshare->rf_ft_var.ac2g_enable) + ) + ac2g = 1; + + return ac2g; + +} +#endif + +VOID +UpdateHalRAMask8812( + struct rtl8192cd_priv *priv, + struct stat_info *pEntry, + u1Byte rssi_level +) +{ + + u1Byte WirelessMode = WIRELESS_MODE_A; + u1Byte BW = HT_CHANNEL_WIDTH_20; + // u2Byte RateSet=0, i; + u1Byte MimoPs = MIMO_PS_NOLIMIT, ratr_index = 8, H2CCommand[7] = { 0}; + u4Byte ratr_bitmap = 0, IOTAction = 0; + BOOLEAN bShortGI = FALSE, bCurTxBW80MHz = FALSE, bCurTxBW40MHz = FALSE; + struct stat_info *pstat = pEntry; + u1Byte rf_mimo_mode = get_rf_mimo_mode(priv); + + unsigned int VHT_TxMap = priv->pmib->dot11acConfigEntry.dot11VHT_TxMap; + + if (pEntry == NULL) { + return; + } + { + if (pEntry->MIMO_ps & _HT_MIMO_PS_STATIC_) + MimoPs = MIMO_PS_STATIC; + else if (pEntry->MIMO_ps & _HT_MIMO_PS_DYNAMIC_) + MimoPs = MIMO_PS_DYNAMIC; + +#if 1 + BW = pstat->tx_bw; + if( BW > priv->pshare->CurrentChannelBW) + BW = priv->pshare->CurrentChannelBW; +#endif + add_RATid(priv, pEntry); + rssi_level = pstat->rssi_level; + ratr_bitmap = 0xfffffff; + // + // if(pstat->vht_cap_len && ( priv->pshare->rf_ft_var.support_11ac)) { + if (pstat->vht_cap_len && (priv->pmib->dot11BssType.net_work_type & WIRELESS_11AC) && (!should_restrict_Nrate(priv, pstat))) { //for 11ac logo + + if( (IS_B_CUT_8812(priv)) + && ((priv->pmib->dot11nConfigEntry.dot11nUse40M==0)||(BW == 0)) ) + { + //printk("\n !!! B CUT + AC STA + 20M, NO AC RATES !!!\n"); + //printk("AP=%dM, STA=%dM\n", (0x1<<(priv->pmib->dot11nConfigEntry.dot11nUse40M))*20 , (0x1<<(pstat->tx_bw))*20 ); + WirelessMode = WIRELESS_MODE_N_5G; + } + else{ + WirelessMode = WIRELESS_MODE_AC_5G; + } + + if (((le32_to_cpu(pstat->vht_cap_buf.vht_support_mcs[0]) >> 2) & 3) == 3) + rf_mimo_mode = MIMO_1T1R; + if (pstat->nss == 1) + rf_mimo_mode = MIMO_1T1R; + } else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && (!should_restrict_Nrate(priv, pstat))) { + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) + WirelessMode = WIRELESS_MODE_N_5G; + else + WirelessMode = WIRELESS_MODE_N_24G; + if ((pstat->tx_ra_bitmap & 0xff00000) == 0) + rf_mimo_mode = MIMO_1T1R; + } else if (((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat))) { + WirelessMode = WIRELESS_MODE_G; + } else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) && + ((OPMODE & WIFI_AP_STATE) || (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G))) { + WirelessMode = WIRELESS_MODE_A; + } else if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11B) { + WirelessMode = WIRELESS_MODE_B; + } + + pstat->WirelessMode = WirelessMode; + + if (WirelessMode == WIRELESS_MODE_AC_5G) { + int tmp32 = (pstat->vht_cap_buf.vht_support_mcs[0]); + ratr_bitmap &= 0xfff; + // special 1SS & 2SS + if (pstat->nss == 1) + tmp32 |= cpu_to_le32(0xfffc); + else if ((pstat->nss == 2) && (le32_to_cpu(tmp32) & 0x0c) == 0x0c) + tmp32 &= cpu_to_le32(0xfffffff3); + // + ratr_bitmap |= RateToBitmap_2SSVHT((pu1Byte)&tmp32) << 12; + + if (IS_TEST_CHIP(priv)) { // Test Chip... 2SS MCS7 + if (rf_mimo_mode == MIMO_1T1R) + ratr_bitmap &= 0x000fffff; + else + ratr_bitmap &= 0x3FCFFFFF; + } else { // MP Chip... MCS0~9 + if (rf_mimo_mode == MIMO_1T1R) + ratr_bitmap &= 0x003fffff; + } + + if (BW == HT_CHANNEL_WIDTH_80) + bCurTxBW80MHz = TRUE; + } +// if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40)) +// bCurTxBW40MHz = TRUE; + + if (priv->pshare->is_40m_bw && (BW == HT_CHANNEL_WIDTH_20_40) +#ifdef WIFI_11N_2040_COEXIST + && !((((GET_MIB(priv))->dot11OperationEntry.opmode) & WIFI_AP_STATE) + && priv->pmib->dot11nConfigEntry.dot11nCoexist + && (priv->bg_ap_timeout || orForce20_Switch20Map(priv) + + )) +#endif + ) + + bCurTxBW40MHz = TRUE; + + } + + if(((GET_MIB(priv))->dot11OperationEntry.opmode) & WIFI_STATION_STATE) { + if(((GET_MIB(priv))->dot11Bss.t_stamp[1] & 0x6) == 0) { + bCurTxBW40MHz = bCurTxBW80MHz = FALSE; + } + } + BW = Get_RA_BW(bCurTxBW80MHz, bCurTxBW40MHz); + + if(BW == 0) + { + //remove MCS9 for BW=20m + if (rf_mimo_mode == MIMO_1T1R) + VHT_TxMap &= ~(BIT(9)); + else if (rf_mimo_mode == MIMO_2T2R) + VHT_TxMap &= ~(BIT(9)|BIT(19)); + } + + // assign band mask and rate bitmap + switch (WirelessMode) { + case WIRELESS_MODE_B: { + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) //11M or 5.5M enable + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + } + break; + + case WIRELESS_MODE_G: { + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + } + break; + + case WIRELESS_MODE_A: { + ratr_index = RATR_INX_WIRELESS_G; + ratr_bitmap &= 0x00000ff0; + } + break; + + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: { + if (WirelessMode == WIRELESS_MODE_N_24G) + ratr_index = RATR_INX_WIRELESS_NGB; + else + ratr_index = RATR_INX_WIRELESS_NG; + + // if(MimoPs <= MIMO_PS_DYNAMIC) + if (MimoPs < MIMO_PS_DYNAMIC) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } else { + if (rf_mimo_mode == MIMO_1T1R) { + if (bCurTxBW40MHz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (bCurTxBW40MHz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0fff0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0ffff000; + else + ratr_bitmap &= 0x0ffff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0fff0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0ffff000; + else + ratr_bitmap &= 0x0ffff005; + } + } + } + } + break; + + case WIRELESS_MODE_AC_5G: { + ratr_index = RATR_INX_WIRELESS_AC_N; + + if (rf_mimo_mode == MIMO_1T1R) + ratr_bitmap &= 0x003ff010; + else + ratr_bitmap &= 0xfffff010; + + ratr_bitmap &= (VHT_TxMap << 12)|0xff0; + + } + break; + + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rf_mimo_mode == MIMO_1T1R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0ffff0ff; + break; + } + + bShortGI = Get_RA_ShortGI(priv, pEntry, WirelessMode, BW); + + + + pstat->ratr_idx = MRateIdxToARFRId8812(priv, ratr_index, rf_mimo_mode) ; + pstat->tx_bw_fw = BW; + +#ifdef AC2G_256QAM + + if(is_ac2g(priv) && pstat->vht_cap_len ) + { + printk("AC2G STA Associated !!\n"); + if (rf_mimo_mode == MIMO_1T1R) + { + //bShortGI = 1; + ratr_bitmap = 0x003ff015; + + if(BW == 2) + pstat->ratr_idx = 10; + else + pstat->ratr_idx = 11; + + if(BW == 0) + VHT_TxMap = 0x1ff; + else + VHT_TxMap = 0x3ff; + + } + else if (rf_mimo_mode == MIMO_2T2R) + { + // bShortGI = 0; + ratr_bitmap = 0xffcff015; + + if(BW == 2) + pstat->ratr_idx = 9; + else + pstat->ratr_idx = 12; + + if(BW == 0) + VHT_TxMap = 0x7fdff; + else + VHT_TxMap = 0xfffff; + } + + ratr_bitmap &= ((VHT_TxMap << 12)|0xfff); + + pstat->WirelessMode = WIRELESS_MODE_AC_24G; + } + +#endif + + H2CCommand[0] = REMAP_AID(pstat); + H2CCommand[1] = (pstat->ratr_idx) | (bShortGI ? 0x80 : 0x00) ; + H2CCommand[2] = BW | Get_VHT_ENI(IOTAction, WirelessMode, ratr_bitmap); + + + H2CCommand[2] |= BIT6; // DisableTXPowerTraining + + H2CCommand[3] = (u1Byte)(ratr_bitmap & 0x000000ff); + H2CCommand[4] = (u1Byte)((ratr_bitmap & 0x0000ff00) >> 8); + H2CCommand[5] = (u1Byte)((ratr_bitmap & 0x00ff0000) >> 16); + H2CCommand[6] = (u1Byte)((ratr_bitmap & 0xff000000) >> 24); + + FillH2CCmd8812(priv, H2C_8812_RA_MASK, 7, H2CCommand); + + SetBcnCtrlReg_8812(priv, BIT3, 0); + /* + panic_printk("UpdateHalRAMask8812E(): bitmap = %x ratr_index = %1x, MacID:%x, ShortGI:%x, MimoPs=%d\n", + ratr_bitmap, pstat->ratr_idx, (pstat->aid), bShortGI, MimoPs); + + panic_printk("Cmd: %02x, %02x, %02x, %02x, %02x, %02x, %02x \n", + H2CCommand[0] ,H2CCommand[1], H2CCommand[2], + H2CCommand[3] ,H2CCommand[4], H2CCommand[5], H2CCommand[6] ); + */ +} +void +UpdateHalMSRRPT8812( + struct rtl8192cd_priv *priv, + struct stat_info *pstat, + unsigned char opmode +) +{ + u1Byte H2CCommand[3] = { 0}; + + update_remapAid(priv,pstat); + H2CCommand[0] = opmode & 0x01; + H2CCommand[1] = REMAP_AID(pstat) & 0xff; + H2CCommand[2] = 0; + FillH2CCmd8812(priv, H2C_8812_MSRRPT, 3, H2CCommand); + + // panic_printk("UpdateHalMSRRPT8812 Cmd: %02x, %02x, %02x \n", + // H2CCommand[0] ,H2CCommand[1], H2CCommand[2]); +} +#if 0 +void check_txrate_by_reg_8812(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned char initial_rate = 0x7f; + unsigned char legacyRA = 0 ; + unsigned int autoRate1 = 0; + +// if (!priv->pshare->rf_ft_var.update_rainfo) +// return; + + RTL_W8(0x8d, 0x01); + RTL_W8(0x8f, 0x40); + + if ( should_restrict_Nrate(priv, pstat) && is_fixedMCSTxRate(priv)) + legacyRA = 1; + + if (pstat->sta_in_firmware == 1) { + + +#ifdef WDS + if (pstat->state & WIFI_WDS) { + autoRate1 = (priv->pmib->dot11WdsInfo.entry[pstat->wds_idx].txRate == 0) ? 1 : 0; + } else +#endif + { + autoRate1 = priv->pmib->dot11StationConfigEntry.autoRate; + } + + if (autoRate1 || legacyRA) { + RTL_W8(0x8c, REMAP_AID(pstat) & 0x1f); + initial_rate = RTL_R8(0x2f0); + if ((initial_rate & 0x7f) == 0x7f) + return; + + + if ((initial_rate & 0x3f) < 12) { + pstat->current_tx_rate = dot11_rate_table[initial_rate & 0x3f]; + pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; + } else { + if ((initial_rate & 0x3f) >= 44) + pstat->current_tx_rate = VHT_RATE_ID + ((initial_rate & 0x3f) - 44); + else + pstat->current_tx_rate = HT_RATE_ID + ((initial_rate & 0x3f) - 12); + + if (initial_rate & BIT(7)) + pstat->ht_current_tx_info |= TX_USE_SHORT_GI; + else + pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; + } + + priv->pshare->current_tx_rate = pstat->current_tx_rate; + priv->pshare->ht_current_tx_info = pstat->ht_current_tx_info; + } + } +} +#endif + + +void odm_TXPowerTrackingCallback_ThermalMeter_8812E(struct rtl8192cd_priv * priv) +{ + unsigned char ThermalValue = 0, delta, channel, is_decrease, rf_mimo_mode; + unsigned char ThermalValue_AVG_count = 0; + unsigned int ThermalValue_AVG = 0; + int ele_D; + char OFDM_index[2]; + unsigned int i = 0, rf = 2; + + unsigned char OFDM_min_index = 7; //OFDM BB Swing should be less than +2.5dB, which is required by Arthur + + rf_mimo_mode = get_rf_mimo_mode(priv); + +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { + channel = priv->pshare->working_channel; + if (priv->pshare->mp_txpwr_tracking == FALSE) + return; + } else +#endif + { + channel = (priv->pmib->dot11RFEntry.dot11channel); + } + + if (priv->pshare->Power_tracking_on_8812 == 0) { + priv->pshare->Power_tracking_on_8812 = 1; + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x42, (BIT(17) | BIT(16)), 0x03); + return; + } else { + priv->pshare->Power_tracking_on_8812 = 0; + ThermalValue = (unsigned char)PHY_QueryRFReg(priv, RF_PATH_A, 0x42, 0xfc00, 1); //0x42: RF Reg[15:10] 88E + //printk("\nReadback Thermal Meter = 0x%x pre thermal meter 0x%x EEPROMthermalmeter 0x%x\n", ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther); + } + + switch (rf_mimo_mode) { + case MIMO_1T1R: + rf = 1; + break; + case MIMO_2T2R: + rf = 2; + break; + default: + panic_printk("%s:%d get_rf_mimo_mode error!\n", __FUNCTION__, __LINE__); + break; + } + + //Query OFDM path A default setting Bit[31:21] + ele_D = PHY_QueryBBReg(priv, 0xc1c, 0xffe00000); + for (i = 0; i < OFDM_TABLE_SIZE_8812; i++) { + if (ele_D == OFDMSwingTable_8812[i]) { + OFDM_index[0] = (unsigned char)i; + //printk("PathA 0xc1c[32:21] = 0x%x, OFDM_index=%d\n", ele_D, OFDM_index[0]); + break; + } + } + + //Query OFDM path B default setting + if (rf_mimo_mode == MIMO_2T2R) { + ele_D = PHY_QueryBBReg(priv, 0xe1c, 0xffe00000); + for (i = 0; i < OFDM_TABLE_SIZE_8812; i++) { + if (ele_D == OFDMSwingTable_8812[i]) { + OFDM_index[1] = (unsigned char)i; + //printk("PathB 0xe1c[31:21] = 0x%x, OFDM_index=%d\n", ele_D, OFDM_index[1]); + break; + } + } + } + + /* Initialize */ + if (!priv->pshare->ThermalValue) { + priv->pshare->ThermalValue = priv->pmib->dot11RFEntry.ther; + + } + + /* calculate average thermal meter */ + { + priv->pshare->ThermalValue_AVG_8812[priv->pshare->ThermalValue_AVG_index_8812] = ThermalValue; + priv->pshare->ThermalValue_AVG_index_8812++; + if (priv->pshare->ThermalValue_AVG_index_8812 == AVG_THERMAL_NUM_8812) + priv->pshare->ThermalValue_AVG_index_8812 = 0; + + for (i = 0; i < AVG_THERMAL_NUM_8812; i++) { + if (priv->pshare->ThermalValue_AVG_8812[i]) { + ThermalValue_AVG += priv->pshare->ThermalValue_AVG_8812[i]; + ThermalValue_AVG_count++; + } + } + + if (ThermalValue_AVG_count) { + ThermalValue = (unsigned char)(ThermalValue_AVG / ThermalValue_AVG_count); + //printk("AVG Thermal Meter = 0x%x \n", ThermalValue); + } + } + + if (ThermalValue != priv->pshare->ThermalValue) { + //printk("\n******** START:%s() ********\n", __FUNCTION__); + //printk("\nReadback Thermal Meter = 0x%x pre thermal meter 0x%x EEPROMthermalmeter 0x%x\n", ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther); + + delta = RTL_ABS(ThermalValue, priv->pmib->dot11RFEntry.ther); + is_decrease = ((ThermalValue < priv->pmib->dot11RFEntry.ther) ? 1 : 0); + if (1) { //AC2G_256QAM (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { +#ifdef _TRACKING_TABLE_FILE + if (priv->pshare->rf_ft_var.pwr_track_file) { + if (is_decrease) { + for (i = 0; i < rf; i++) { + OFDM_index[i] = priv->pshare->OFDM_index0[i] + get_tx_tracking_index(priv, channel, i, delta, is_decrease, 0); + OFDM_index[i] = ((OFDM_index[i] > (OFDM_TABLE_SIZE_8812 - 1)) ? (OFDM_TABLE_SIZE_8812 - 1) : OFDM_index[i]); + //printk(">>> decrese power ---> new OFDM_INDEX:%d (%d + %d)\n", OFDM_index[i], priv->pshare->OFDM_index0[i], get_tx_tracking_index(priv, channel, i, delta, is_decrease, 0)); + } + } else { + for (i = 0; i < rf; i++) { + OFDM_index[i] = priv->pshare->OFDM_index0[i] - get_tx_tracking_index(priv, channel, i, delta, is_decrease, 0); + OFDM_index[i] = ((OFDM_index[i] < OFDM_min_index) ? OFDM_min_index : OFDM_index[i]); + //printk(">>> increse power ---> new OFDM_INDEX:%d (%d - %d)\n", OFDM_index[i], priv->pshare->OFDM_index0[i], get_tx_tracking_index(priv, channel, i, delta, is_decrease, 0)); + } + } + } +#endif + PHY_SetBBReg(priv, 0xc1c, 0xffe00000, OFDMSwingTable_8812[(unsigned int)OFDM_index[0]]); + if (rf_mimo_mode == MIMO_2T2R) + PHY_SetBBReg(priv, 0xe1c, 0xffe00000, OFDMSwingTable_8812[(unsigned int)OFDM_index[1]]); + + + } +/* + printk("PathA >>>>> 0xc1c[31:21] = 0x%x, OFDM_index:%d\n", PHY_QueryBBReg(priv, 0xc1c, 0xffe00000), OFDM_index[0]); + if (rf_mimo_mode == MIMO_2T2R) + printk("PathB >>>>> 0xe1c[31:21] = 0x%x, OFDM_index:%d\n", PHY_QueryBBReg(priv, 0xe1c, 0xffe00000), OFDM_index[1]); + printk("\n******** END:%s() ********\n", __FUNCTION__); +*/ + //update thermal meter value + priv->pshare->ThermalValue = ThermalValue; + for (i = 0 ; i < rf ; i++) + priv->pshare->OFDM_index[i] = OFDM_index[i]; + } +} + + +void requestTxReport_8812(struct rtl8192cd_priv *priv) +{ + unsigned char h2cresult, counter = 20; + struct stat_info *sta; + unsigned char H2CCommand[2] = {0xff, 0xff}; + + if ( priv->pshare->sta_query_idx == -1) + return; + + while (is_h2c_buf_occupy(priv)) { + delay_ms(2); + if (--counter == 0) + break; + } + + if (!counter) + return; + + sta = findNextSTA(priv, &priv->pshare->sta_query_idx); + if (sta) + H2CCommand[0] = REMAP_AID(sta); + else { + priv->pshare->sta_query_idx = -1; + return; + } + + sta = findNextSTA(priv, &priv->pshare->sta_query_idx); + if (sta) { + H2CCommand[1] = REMAP_AID(sta); + } else { + priv->pshare->sta_query_idx = -1; + } + + //WDEBUG("\n"); + h2cresult = FillH2CCmd8812(priv, H2C_8812_TX_REPORT, 2 , H2CCommand); + //WDEBUG("h2cresult=%d\n",h2cresult); + + +} + + +/*C2H_isr_8812() +AP Req Txrpt +"Start Address:USB:0xFD20PCIe/USB: 0x01A0" +|ID|SEQ |CONTENT |LEN|TRIGGER| +----------------------------------------- +|0 | 1 |2~13 |14 |15 | +----------------------------------------- + +|ID=0x04|SEQ|STA1 MACID(1B)|Tx_ok1(2B)|Tx_fail1(2B)|initial rate1(1B)|STA2 MACID(1B)|Tx_ok2(2B)|Tx_fail2(2B)|Initial rate2(1B)|Len=12(1B)|FF(1B)| +*/ +void C2H_isr_8812(struct rtl8192cd_priv *priv) +{ + struct tx_rpt rpt1; + int j, C2H_ID; + unsigned char MacID = 0xff; + int idx = 0x1a2; +#ifndef SMP_SYNC + unsigned long flags=0; +#endif + + //WDEBUG("\n"); + + SAVE_INT_AND_CLI(flags); + C2H_ID = RTL_R8(0x1a0); + + if ( (C2H_ID) == C2H_8812_TX_REPORT ) { + + for (j = 0; j < 2; j++) { + + MacID = RTL_R8(idx); + if (MacID == 0xff) + continue; + + rpt1.macid = MacID & TXdesc_92E_MacIdMask; + + if (rpt1.macid) { + + rpt1.txok = (RTL_R8(idx + 2)<<8) | RTL_R8(idx + 1); + rpt1.txfail = (RTL_R8(idx + 4)<<8) | RTL_R8(idx + 3); +/* +#ifdef _BIG_ENDIAN_ + rpt1.txok = le16_to_cpu(RTL_R16(idx + 1)); + rpt1.txfail = le16_to_cpu(RTL_R16(idx + 3)); +#else + rpt1.txok = be16_to_cpu(RTL_R16(idx + 1)); + rpt1.txfail = be16_to_cpu(RTL_R16(idx + 3)); +#endif +*/ + rpt1.initil_tx_rate = RTL_R8(idx + 5); + txrpt_handler(priv, &rpt1); // add inital tx rate handle for 8812E + } + idx += 6; + } + } + +// check sounding BW also... + + + + RTL_W8( 0x1af, 0); + if ( (C2H_ID) == C2H_8812_TX_REPORT ) + requestTxReport_8812(priv); + RESTORE_INT(flags); +} +VOID +C2HRaReportHandler_8812( + struct rtl8192cd_priv *priv, + pu1Byte CmdBuf, + u1Byte CmdLen +) +{ + u1Byte Rate = CmdBuf[0] & 0x3F; + u1Byte MacId = CmdBuf[1]; + BOOLEAN bLDPC = CmdBuf[2] & BIT0; + BOOLEAN bTxBF = (CmdBuf[2] & BIT1) >> 1; +#ifdef BEAMFORMING_SUPPORT + Beamforming_SetTxBFen(priv, MacId, bTxBF); +#endif +} + +VOID +C2HTxTxReportHandler_8812( + struct rtl8192cd_priv *priv, + pu1Byte CmdBuf, + u1Byte CmdLen +) +{ + struct tx_rpt rpt1; + int k=0, j=0; + for(j=0; j<2; j++) { + rpt1.macid= CmdBuf[k]; + rpt1.txok = CmdBuf[k+1] | ((short)CmdBuf[k+2]<<8); + rpt1.txfail = CmdBuf[k+3] | ((short)CmdBuf[k+4]<<8); + rpt1.initil_tx_rate = CmdBuf[k+5]; + if(rpt1.macid != 0xff) + txrpt_handler(priv, &rpt1); + k+=6; + } +} + +#ifdef BEAMFORMING_SUPPORT +VOID C2HTxBeamformingHandler_8812( struct rtl8192cd_priv *priv, pu1Byte CmdBuf, u1Byte CmdLen); +#endif + +VOID +_C2HContentParsing8812( + struct rtl8192cd_priv *priv, + u1Byte c2hCmdId, + u1Byte c2hCmdLen, + pu1Byte tmpBuf +) +{ + + switch(c2hCmdId) + { + case C2H_8812_TXBF: +#ifdef BEAMFORMING_SUPPORT + C2HTxBeamformingHandler_8812(priv, tmpBuf, c2hCmdLen); +#endif + break; + case C2H_8812_TXPERORT: +#ifdef TXREPORT + C2HTxTxReportHandler_8812(priv, tmpBuf, c2hCmdLen); + requestTxReport_8812(priv); +#endif + break; + + default: + if(!(phydm_c2H_content_parsing(ODMPTR, c2hCmdId, c2hCmdLen, tmpBuf))) { + printk("[C2H], Unkown packet!! CmdId(%#X)!\n", c2hCmdId); + } + break; + } +} + +VOID +C2HPacketHandler_8812( + struct rtl8192cd_priv *priv, + pu1Byte Buffer, + u1Byte Length + ) +{ + u1Byte c2hCmdId=0, c2hCmdSeq=0, c2hCmdLen=0; + pu1Byte tmpBuf=NULL; + c2hCmdId = Buffer[0]; + c2hCmdSeq = Buffer[1]; +/* +#ifdef CONFIG_WLAN_HAL + if(c2hCmdId==C2H_88XX_EXTEND_IND) + { + c2hCmdLen = Length; + tmpBuf = Buffer; + C2HExtEventHandler88XX(NULL, c2hCmdId, c2hCmdLen, tmpBuf); + } + else +#endif +*/ + { + c2hCmdLen = Length -2; + tmpBuf = Buffer+2; + + _C2HContentParsing8812(priv, c2hCmdId, c2hCmdLen, tmpBuf); + } +} + +#ifdef BEAMFORMING_SUPPORT +VOID +SetBeamformRfMode8812( + struct rtl8192cd_priv *priv, + PRT_BEAMFORMING_INFO pBeamformingInfo + ) +{ + u1Byte i; + BOOLEAN bSelfBeamformer = FALSE; + BOOLEAN bSelfBeamformee = FALSE; + RT_BEAMFORMING_ENTRY BeamformEntry; + BEAMFORMING_CAP BeamformCap = BEAMFORMING_CAP_NONE; + + BeamformCap = Beamforming_GetBeamCap(pBeamformingInfo); + + if(BeamformCap == pBeamformingInfo->BeamformCap) + return; + else + pBeamformingInfo->BeamformCap = BeamformCap; + if(get_rf_mimo_mode(priv) == MIMO_1T1R) + return; + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_WeLut_Jaguar, 0x80000,0x1); // RF Mode table write enable + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_WeLut_Jaguar, 0x80000,0x1); // RF Mode table write enable + + bSelfBeamformer = BeamformCap & BEAMFORMER_CAP; + bSelfBeamformee = BeamformCap & BEAMFORMEE_CAP; + + if(bSelfBeamformer) + { + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_ModeTableAddr, 0x78000,0x3); // Select RX mode + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_ModeTableData0, 0xfffff,0x3F7FF); // Set Table data + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_ModeTableData1, 0xfffff,0xE26BF); // Enable TXIQGEN in RX mode + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_ModeTableAddr, 0x78000, 0x3); // Select RX mode + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_ModeTableData0, 0xfffff,0x3F7FF); // Set Table data + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_ModeTableData1, 0xfffff,0xE26BF); // Enable TXIQGEN in RX mode + } + else + { + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_ModeTableAddr, 0x78000, 0x3); // Select RX mode + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_ModeTableData0, 0xfffff,0x3F7FF); // Set Table data + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_ModeTableData1, 0xfffff,0xC26BF); // Disable TXIQGEN in RX mode + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_ModeTableAddr, 0x78000, 0x3); // Select RX mode + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_ModeTableData0, 0xfffff,0x3F7FF); // Set Table data + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_ModeTableData1, 0xfffff,0xC26BF); // Disable TXIQGEN in RX mode + } + PHY_SetRFReg(priv, ODM_RF_PATH_A, RF_WeLut_Jaguar, 0x80000,0x0); // RF Mode table write disable + PHY_SetRFReg(priv, ODM_RF_PATH_B, RF_WeLut_Jaguar, 0x80000,0x0); // RF Mode table write disable + + if(bSelfBeamformer) { + PHY_SetBBReg(priv, rTxPath_Jaguar, bMaskByte1, 0x33); +#ifdef RF_MIMO_SWITCH + priv->pshare->rf_phy_bb_backup[1] &= ~ bMaskByte1; + priv->pshare->rf_phy_bb_backup[1] |= 0x3300; +#endif + + } else { + PHY_SetBBReg(priv, rTxPath_Jaguar, bMaskByte1, 0x11); +#ifdef RF_MIMO_SWITCH + priv->pshare->rf_phy_bb_backup[1] &= ~ bMaskByte1; + priv->pshare->rf_phy_bb_backup[1] |= 0x1100; +#endif + } +} +VOID +SetBeamformEnter8812( + struct rtl8192cd_priv *priv, + u1Byte BFerBFeeIdx + ) +{ + u1Byte i = 0; + u1Byte BFerIdx = (BFerBFeeIdx & 0xF0)>>4; + u1Byte BFeeIdx = (BFerBFeeIdx & 0xF); + u4Byte CSI_Param; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + RT_BEAMFORMING_ENTRY BeamformeeEntry; + RT_BEAMFORMER_ENTRY BeamformerEntry; + u2Byte STAid = 0; + + SetBeamformRfMode8812(priv, pBeamformingInfo); + + if(get_rf_mimo_mode(priv) == MIMO_2T2R) + RTL_W32(0x9B4, 0x01081008); + + if((pBeamformingInfo->BeamformCap & BEAMFORMEE_CAP) && (BFerIdx < BEAMFORMER_ENTRY_NUM)) + { + BeamformerEntry = pBeamformingInfo->BeamformerEntry[BFerIdx]; + + if (!IS_TEST_CHIP(priv)) { + if (IS_C_CUT_8812(priv)) + RTL_W16( REG_SND_PTCL_CTRL_8812, 0x2CB); // Disable SIG-B CRC8 check + else + RTL_W16( REG_SND_PTCL_CTRL_8812, 0x0B); + } + else + RTL_W16( REG_SND_PTCL_CTRL_8812, 0x1B); + + // MAC addresss/Partial AID of Beamformer + if(BFerIdx == 0) + { + for(i = 0; i < 6 ; i++) + RTL_W8( (REG_BFMER0_INFO_8812+i), BeamformerEntry.MacAddr[i]); + + //RTL_W16( REG_BFMER0_INFO_8812+6, BeamformerEntry.P_AID); + } + else + { + for(i = 0; i < 6 ; i++) + RTL_W8( (REG_BFMER1_INFO_8812+i), BeamformerEntry.MacAddr[i]); + + //RTL_W16( REG_BFMER1_INFO_8812+6, BeamformerEntry.P_AID); + } + + // CSI report parameters of Beamformer + if((BeamformerEntry.BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU) ||(BeamformerEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU) ) + CSI_Param = 0x01080108; + else + CSI_Param = 0x03080308; + + RTL_W32( REG_CSI_RPT_PARAM_BW20_8812, CSI_Param); + RTL_W32( REG_CSI_RPT_PARAM_BW40_8812, CSI_Param); + RTL_W32( REG_CSI_RPT_PARAM_BW80_8812, CSI_Param); + + // Timeout value for MAC to leave NDP_RX_standby_state 60 us + // RTL_W8( REG_SND_PTCL_CTRL_8812+3, 0x3C); + RTL_W8( REG_SND_PTCL_CTRL_8812+3, 0x50); // // ndp_rx_standby_timer + } + + if((pBeamformingInfo->BeamformCap & BEAMFORMER_CAP) && (BFeeIdx < BEAMFORMEE_ENTRY_NUM)) + { + BeamformeeEntry = pBeamformingInfo->BeamformeeEntry[BFeeIdx]; + + if(OPMODE & WIFI_ADHOC_STATE) + STAid = BeamformeeEntry.AID; + else + STAid = BeamformeeEntry.P_AID; + + // P_AID of Beamformee & enable NDPA transmission + if(BFeeIdx == 0) + { + RTL_W16( REG_TXBF_CTRL_8812, STAid); + RTL_W8( REG_TXBF_CTRL_8812+3, RTL_R8( REG_TXBF_CTRL_8812+3)|BIT6|BIT7|BIT4); + } + else + { + RTL_W16( REG_TXBF_CTRL_8812+2, STAid |BIT14| BIT15|BIT12); + } + + // CSI report parameters of Beamformee + if(BFeeIdx == 0) + { + // Get BIT24 & BIT25 + u1Byte tmp = RTL_R8( REG_BFMEE_SEL_8812+3) & 0x3; + RTL_W8( REG_BFMEE_SEL_8812+3, tmp | 0x60); + RTL_W16( REG_BFMEE_SEL_8812, STAid | BIT9); + } + else + { + // Set BIT25 + RTL_W16( REG_BFMEE_SEL_8812+2, STAid | 0xE200); + } + + // if(pHalData->bIsMPChip == FALSE) + if (IS_TEST_CHIP(priv)) + { + // VHT category value + RTL_W8( REG_SND_PTCL_CTRL_8812+1, ACT_CAT_VHT); + // NDPA subtype + RTL_W8( REG_SND_PTCL_CTRL_8812+2, Type_NDPA >> 4); + } + + Beamforming_Notify(priv); + } +} + + +VOID +SetBeamformLeave8812( + struct rtl8192cd_priv *priv, + u1Byte Idx + ) +{ + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + RT_BEAMFORMING_ENTRY BeamformeeEntry = pBeamformingInfo->BeamformeeEntry[Idx]; + RT_BEAMFORMER_ENTRY BeamformerEntry = pBeamformingInfo->BeamformerEntry[Idx]; + + /* Clear P_AID of Beamformee + * Clear MAC addresss of Beamformer + * Clear Associated Bfmee Sel + */ + if (BeamformeeEntry.BeamformEntryCap == BEAMFORMING_CAP_NONE) + { + if(Idx == 0) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BeamformeeEntryCap == NONE, Idx=%d\n", __FUNCTION__, Idx)); + RTL_W16( REG_TXBF_CTRL_8812, 0); + RTL_W16( REG_BFMEE_SEL_8812, 0); + } + else + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BeamformeeEntryCap == NONE, Idx=%d\n", __FUNCTION__, Idx)); + RTL_R16( (REG_TXBF_CTRL_8812+2) & 0xF000); + RTL_W16( REG_BFMEE_SEL_8812+2, RTL_R16( REG_BFMEE_SEL_8812+2) & 0x60); + } + } + + if (BeamformerEntry.BeamformEntryCap == BEAMFORMING_CAP_NONE) + { + if(Idx == 0) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BeamformerEntryCap == NONE, Idx=%d\n", __FUNCTION__, Idx)); + RTL_W32( REG_BFMER0_INFO_8812, 0); + RTL_W16( REG_BFMER0_INFO_8812+4, 0); + } + else + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BeamformerEntryCap == NONE, Idx=%d\n", __FUNCTION__, Idx)); + RTL_W32( REG_BFMER1_INFO_8812, 0); + RTL_W16( REG_BFMER1_INFO_8812+4, 0); + } + } + + if(((pBeamformingInfo->BeamformerEntry[0]).BeamformEntryCap == BEAMFORMING_CAP_NONE) + && ((pBeamformingInfo->BeamformerEntry[1]).BeamformEntryCap == BEAMFORMING_CAP_NONE)){ + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, All BeamformerEntryCap == NONE, STOP feedback CSI\n", __FUNCTION__, Idx)); + RTL_W8( REG_SND_PTCL_CTRL_8812, 0xC8); + } + +} +VOID +SetBeamformStatus8812( + struct rtl8192cd_priv *priv, + u1Byte Idx + ) +{ + u2Byte BeamCtrlVal; + u4Byte BeamCtrlReg; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + RT_BEAMFORMING_ENTRY BeamformEntry = pBeamformingInfo->BeamformeeEntry[Idx]; + if(OPMODE & WIFI_ADHOC_STATE) + BeamCtrlVal = BeamformEntry.MacId; + else + BeamCtrlVal = BeamformEntry.P_AID; + if(Idx == 0) + BeamCtrlReg = REG_TXBF_CTRL_8812; + else + { + BeamCtrlReg = REG_TXBF_CTRL_8812+2; + BeamCtrlVal |= BIT12 | BIT14|BIT15; + } + if((BeamformEntry.BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED)&& (priv->pshare->rf_ft_var.applyVmatrix)) + { + if(BeamformEntry.BW == HT_CHANNEL_WIDTH_20) + BeamCtrlVal |= BIT9; + else if(BeamformEntry.BW == HT_CHANNEL_WIDTH_20_40) + BeamCtrlVal |= (BIT9 | BIT10); + else if(BeamformEntry.BW == HT_CHANNEL_WIDTH_80) + BeamCtrlVal |= (BIT9 | BIT10 | BIT11); + } else { + BeamCtrlVal &= ~(BIT9|BIT10|BIT11); + } + RTL_W16(BeamCtrlReg, BeamCtrlVal); +} +//2REG_C2HEVT_CLEAR +#define C2H_EVT_HOST_CLOSE 0x00 // Set by driver and notify FW that the driver has read the C2H command message +#define C2H_EVT_FW_CLOSE 0xFF // Set by FW indicating that FW had set the C2H command message and it's not yet read by driver. + + + +VOID Beamforming_NDPARate_8812( + struct rtl8192cd_priv *priv, + BOOLEAN Mode, + u1Byte BW, + u1Byte Rate) +{ + + u2Byte NDPARate = Rate; + + if(NDPARate == 0) + { +// ??? +#if 0 + if(Mode == 1 || Mode == 4) + NDPARate = 0x0c; //MGN_MCS0; + else + NDPARate = 0x2c; //MGN_VHT1SS_MCS0; +#else + if(priv->pshare->rssi_min > 30) // link RSSI > 30% + NDPARate = 8; //MGN_24M + else + NDPARate = 4; //MGN_6M + +#endif + } + + if(NDPARate < 0x0c) + BW = HT_CHANNEL_WIDTH_20; + + RTL_W8(REG_NDPA_OPT_CTRL_8812, (NDPARate<<2) | (BW & 0x03)); + + +} + +VOID +C2HTxBeamformingHandler_8812( + struct rtl8192cd_priv *priv, + pu1Byte CmdBuf, + u1Byte CmdLen +) +{ + u1Byte status = CmdBuf[0] & BIT0; + Beamforming_End(priv, status); +} + +VOID HW_VAR_HW_REG_TIMER_START_8812(struct rtl8192cd_priv *priv) +{ + RTL_W8(0x15F, 0x0); + RTL_W8(0x15F, 0x5); + +} + +VOID HW_VAR_HW_REG_TIMER_INIT_8812(struct rtl8192cd_priv *priv, int t) +{ + RTL_W8(0x164, 1); + RTL_W16(0x15C, t); + +} + +VOID HW_VAR_HW_REG_TIMER_STOP_8812(struct rtl8192cd_priv *priv) +{ + RTL_W8(0x15F, 0); +} + + +VOID _Beamforming_CLK(struct rtl8192cd_priv *priv) +{ + u2Byte u2btmp; + u1Byte QueueID, Count = 0, u1btmp; +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if(priv->pshare->bScanInProcess==TRUE) + return; + + SAVE_INT_AND_CLI(flags); + + // Stop Usb TxDMA + RTL_W16(PCIE_CTRL_REG, 0xff00 ); + + // Wait TXFF empty + for(Count = 0; Count < 100; Count++) { + u2btmp = RTL_R16(REG_TXPKT_EMPTY_8812); + u2btmp = u2btmp & 0xfff; + if(u2btmp != 0xfff) { + delay_ms(10); + continue; + } else { + break; + } + } + + // TX pause + RTL_W8(REG_TXPAUSE_8812, 0xFF); + + // Wait TX State Machine OK + for(Count = 0; Count < 100; Count++) { + if(RTL_R32(REG_SCH_TXCMD_8812) != 0) + continue; + else + break; + } + + // Stop RX DMA path + u1btmp = RTL_R8(REG_RXDMA_CONTROL_8812); + RTL_W8(REG_RXDMA_CONTROL_8812, u1btmp| BIT2); + + for(Count = 0; Count < 100; Count++) { + u1btmp = RTL_R8( REG_RXDMA_CONTROL_8812); + if(u1btmp & BIT1) + break; + else + delay_ms(10); + } + + // Disable clock + RTL_W8(REG_SYS_CLKR_8812+1, 0xf0); + // Disable 320M + RTL_W8(REG_AFE_PLL_CTRL_8812+3, 0x8); + // Enable 320M + RTL_W8(REG_AFE_PLL_CTRL_8812+3, 0xa); + // Enable clock + RTL_W8( REG_SYS_CLKR_8812+1, 0xfc); + + // Release Tx pause + RTL_W8(REG_TXPAUSE_8812, 0); + + // Enable RX DMA path + u1btmp = RTL_R8(REG_RXDMA_CONTROL_8812); + RTL_W8(REG_RXDMA_CONTROL_8812, u1btmp & (~ BIT2)); + + // Start Usb TxDMA + RTL_W16(PCIE_CTRL_REG, 0x00 ); + RESTORE_INT(flags); +// panic_printk("FBEAM_ERROR <==%s\n", __FUNCTION__); +} + + +#endif + + +VOID RTL8812_MACID_PAUSE( + struct rtl8192cd_priv *priv, + BOOLEAN bSleep, + u4Byte aid +) +{ + if (priv->pshare->rf_ft_var.enable_macid_sleep) { + if (bSleep) { + if (aid > MACID_REGION3_LIMIT) + RTL_W32(REG_MACID_PKT_SLEEP_3, RTL_R32(REG_MACID_PKT_SLEEP_3) | BIT(aid-MACID_REGION3_LIMIT-1)); + else if(aid > MACID_REGION2_LIMIT) + RTL_W32(REG_MACID_PKT_SLEEP_2, RTL_R32(REG_MACID_PKT_SLEEP_2) | BIT(aid-MACID_REGION2_LIMIT-1)); + else if(aid > MACID_REGION1_LIMIT) + RTL_W32(REG_MACID_PKT_SLEEP_1, RTL_R32(REG_MACID_PKT_SLEEP_1) | BIT(aid-MACID_REGION1_LIMIT-1)); + else + RTL_W32(REG_MACID_PKT_SLEEP_0, RTL_R32(REG_MACID_PKT_SLEEP_0) | BIT(aid)); + } else { + if (aid > MACID_REGION3_LIMIT) + RTL_W32(REG_MACID_PKT_SLEEP_3, RTL_R32(REG_MACID_PKT_SLEEP_3) & ~BIT(aid-MACID_REGION3_LIMIT-1)); + else if(aid > MACID_REGION2_LIMIT) + RTL_W32(REG_MACID_PKT_SLEEP_2, RTL_R32(REG_MACID_PKT_SLEEP_2) & ~BIT(aid-MACID_REGION2_LIMIT-1)); + else if(aid > MACID_REGION1_LIMIT) + RTL_W32(REG_MACID_PKT_SLEEP_1, RTL_R32(REG_MACID_PKT_SLEEP_1) & ~BIT(aid-MACID_REGION1_LIMIT-1)); + else + RTL_W32(REG_MACID_PKT_SLEEP_0, RTL_R32(REG_MACID_PKT_SLEEP_0) & ~BIT(aid)); + } + } +} + + +#endif //CONFIG_RTL_8812_SUPPORT + + +#if defined(DFS) || defined(RTK_AC_SUPPORT) //for 11ac logo +void SwitchChannel(struct rtl8192cd_priv *priv) +{ + + int ch = priv->pshare->dfsSwitchChannel; + int staidx = 0; +//#ifndef SMP_SYNC + unsigned long flags=0; +//#endif + struct stat_info *pstat = findNextSTA(priv, &staidx); + + priv->pmib->dot11RFEntry.dot11channel = ch; + priv->pshare->dfsSwitchChannel = 0; + RTL_W8(TXPAUSE, 0xff); + + PHY_SetBBReg(priv, 0x924, BIT(15), 0); // disable HW DFS report +#ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS && + (OPMODE & WIFI_AP_STATE)) { + if (timer_pending(&priv->DFS_timer)) + del_timer_sync(&priv->DFS_timer); + + if (timer_pending(&priv->ch_avail_chk_timer)) + del_timer_sync(&priv->ch_avail_chk_timer); + + if (timer_pending(&priv->dfs_det_chk_timer)) + del_timer_sync(&priv->dfs_det_chk_timer); + } +#endif + + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw = priv->pmib->dot11nConfigEntry.dot11nUse40M; + + if (priv->pmib->dot11nConfigEntry.dot11nUse40M == HT_CHANNEL_WIDTH_80 && + priv->pmib->dot11RFEntry.band5GSelected == PHY_BAND_5G_3) + { + int channel = priv->pmib->dot11RFEntry.dot11channel; + + if (!is80MChannel(priv->available_chnl, priv->available_chnl_num, channel)) { + priv->pshare->CurrentChannelBW = priv->pshare->is_40m_bw = HT_CHANNEL_WIDTH_AC_20; + } + } +#ifdef DFS + if(priv->pshare->rf_ft_var.dfs_next_ch != 0){ + priv->pmib->dot11RFEntry.dot11channel = priv->pshare->rf_ft_var.dfs_next_ch; + } +#endif + panic_printk("4. Swiching channel to %d! BW %dM mode\n", priv->pmib->dot11RFEntry.dot11channel, + (priv->pshare->CurrentChannelBW == 2)? 80 : ((priv->pshare->CurrentChannelBW == 1)? 40 : 20)); + + if ((ch>144) ? ((ch-1)%8) : (ch%8)) { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE; + } else { + GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW; + priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW; + } + + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + SwBWMode(priv, priv->pshare->CurrentChannelBW, priv->pshare->offset_2nd_chan); + SwChnl(priv, priv->pmib->dot11RFEntry.dot11channel, priv->pshare->offset_2nd_chan); + PHY_IQCalibrate(priv); //FOR_8812_IQK + SMP_UNLOCK(flags); + RESTORE_INT(flags); + + + priv->pmib->dot11DFSEntry.DFS_detected = 0; + priv->ht_cap_len = 0; + +#ifdef MBSSID + if (priv->pmib->miscEntry.vap_enable) { + int i; + for (i=0; ipvap_priv[i])) { + priv->pvap_priv[i]->pmib->dot11RFEntry.dot11channel = ch; + priv->pvap_priv[i]->ht_cap_len = 0; + } + } + } +#endif + + RTL_W8(TXPAUSE, 0x00); + + + while(pstat) + { +#ifdef TX_SHORTCUT + if (!priv->pmib->dot11OperationEntry.disable_txsc) { + clearTxShortCutBufSize(priv, pstat); + } +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8812E) { + UpdateHalRAMask8812(priv, pstat, 3); + } +#endif +#ifdef CONFIG_WLAN_HAL + if (IS_HAL_CHIP(priv)) { + GET_HAL_INTERFACE(priv)->UpdateHalRAMaskHandler(priv, pstat, 3); + } +#endif + + pstat = findNextSTA(priv, &staidx); + + } + +#ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS && + (OPMODE & WIFI_AP_STATE) && + (((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)) || + ((priv->pmib->dot11RFEntry.dot11channel >= 100) && + (priv->pmib->dot11RFEntry.dot11channel <= 140)))) { + + init_timer(&priv->ch_avail_chk_timer); + priv->ch_avail_chk_timer.data = (unsigned long) priv; + priv->ch_avail_chk_timer.function = rtl8192cd_ch_avail_chk_timer; + + if ((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_ETSI) && + ((priv->pmib->dot11RFEntry.dot11channel >= 120) && + (priv->pmib->dot11RFEntry.dot11channel <= 132))) + mod_timer(&priv->ch_avail_chk_timer, jiffies + CH_AVAIL_CHK_TO_CE); + else + mod_timer(&priv->ch_avail_chk_timer, jiffies + CH_AVAIL_CHK_TO); + + init_timer(&priv->DFS_timer); + priv->DFS_timer.data = (unsigned long) priv; + priv->DFS_timer.function = rtl8192cd_DFS_timer; + + init_timer(&priv->DFS_TXPAUSE_timer); + priv->DFS_TXPAUSE_timer.data = (unsigned long) priv; + priv->DFS_TXPAUSE_timer.function = rtl8192cd_DFS_TXPAUSE_timer; + + /* DFS activated after 5 sec; prevent switching channel due to DFS false alarm */ + mod_timer(&priv->DFS_timer, jiffies + RTL_SECONDS_TO_JIFFIES(5)); + + init_timer(&priv->dfs_det_chk_timer); + priv->dfs_det_chk_timer.data = (unsigned long) priv; + priv->dfs_det_chk_timer.function = rtl8192cd_dfs_det_chk_timer; + + mod_timer(&priv->dfs_det_chk_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(priv->pshare->rf_ft_var.dfs_det_period*10)); + + DFS_SetReg(priv); + + priv->pmib->dot11DFSEntry.disable_tx = 1; + } + else + priv->pmib->dot11DFSEntry.disable_tx = 0; +#endif +} +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_reg.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_reg.h new file mode 100755 index 000000000..2076babdb --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_reg.h @@ -0,0 +1,1819 @@ +/***************************************************************************** + * Copyright(c) 2009, RealTEK Technology Inc. All Right Reserved. + * + * Module: __INC_HAL8812REG_H + * + * + * Note: 1. Define Mac register address and corresponding bit mask map + * + * + * Export: Constants, macro, functions(API), global variables(None). + * + * Abbrev: + * + * History: + * Data Who Remark + * + *****************************************************************************/ +#ifndef __INC_HAL8812REG_H +#define __INC_HAL8812REG_H + +#ifndef WLAN_HAL_INTERNAL_USED + +#if 1 //FOR_8812_IQK + +#define RF_AC 0x00 + +#define rPdp_AntA 0xb00 +#define rBndA 0xb30 +#define rPdp_AntB 0xb70 +#define rBndB 0xba0 + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define rTxAGC_B_CCK11_A_CCK2_11 0x86c + +#define RF_TX_G3 0x22 + +#define RF_TXPA_G1 0x31 // RF TX PA control +#define RF_TXPA_G2 0x32 // RF TX PA control +#define RF_TXPA_G3 0x33 // RF TX PA control +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C +#define RF_TRSW 0x3F + +#define RF_TXPA_G1 0x31 // RF TX PA control +#define RF_TXPA_G2 0x32 // RF TX PA control +#define RF_TXPA_G3 0x33 // RF TX PA control +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C +#define RF_TRSW 0x3F + +#define RF_TXRF_A2 0x41 +#define RF_TXPA_G4 0x46 +#define RF_TXPA_A4 0x4B + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_BS_PA_APSET_G1_G4 0x03 +#define RF_BS_PA_APSET_G5_G8 0x04 +#define RF_POW_TRSW 0x05 + +#define DP_OFFSET_NUM 9 +#define DP_AP_CUREVE_SELECT_NUM 3 +#define DP_gain_loss 1 +#define DP_PA_BIAS_NUM 4 + +#define rTxAGC_B_CCK1_55_Mcs32 0x838 + +#define RF_TXBIAS 0x16 + +// +// RL6052 Register definition +// + +#define RF_IQADJ_G1 0x01 // +#define RF_IQADJ_G2 0x02 // +#define RF_BS_PA_APSET_G1_G4 0x03 +#define RF_BS_PA_APSET_G5_G8 0x04 +#define RF_POW_TRSW 0x05 // + +#define RF_GAIN_RX 0x06 // +#define RF_GAIN_TX 0x07 // + +#define RF_TXM_IDAC 0x08 // +#define RF_IPA_G 0x09 // +#define RF_TXBIAS_G 0x0A +#define RF_TXPA_AG 0x0B +#define RF_IPA_A 0x0C // +#define RF_TXBIAS_A 0x0D +#define RF_BS_PA_APSET_G9_G11 0x0E +#define RF_BS_IQGEN 0x0F // + +#define RF_MODE1 0x10 // +#define RF_MODE2 0x11 // + +#define RF_RX_AGC_HP 0x12 // +#define RF_TX_AGC 0x13 // +#define RF_BIAS 0x14 // +#define RF_IPA 0x15 // +#define RF_TXBIAS 0x16 +#define RF_POW_ABILITY 0x17 // +#define RF_CHNLBW 0x18 // RF channel and BW switch +#define RF_TOP 0x19 // + +#define RF_RX_G1 0x1A // +#define RF_RX_G2 0x1B // + +#define RF_RX_BB2 0x1C // +#define RF_RX_BB1 0x1D // + +#define RF_RCK1 0x1E // +#define RF_RCK2 0x1F // + +#define RF_TX_G1 0x20 // +#define RF_TX_G2 0x21 // +#define RF_TX_G3 0x22 // + +#define RF_TX_BB1 0x23 // + + +// +// PageB(0xB00) +// +#define rPdp_AntA 0xb00 +#define rPdp_AntA_4 0xb04 +#define rPdp_AntA_8 0xb08 +#define rPdp_AntA_C 0xb0c +#define rPdp_AntA_10 0xb10 +#define rPdp_AntA_14 0xb14 +#define rPdp_AntA_18 0xb18 +#define rPdp_AntA_1C 0xb1c +#define rPdp_AntA_20 0xb20 +#define rPdp_AntA_24 0xb24 + +#define rConfig_Pmpd_AntA 0xb28 +#define rConfig_ram64x16 0xb2c + +#define rBndA 0xb30 +#define rHssiPar 0xb34 + +#define rConfig_AntA 0xb68 +#define rConfig_AntB 0xb6c + +#define rPdp_AntB 0xb70 +#define rPdp_AntB_4 0xb74 +#define rPdp_AntB_8 0xb78 +#define rPdp_AntB_C 0xb7c +#define rPdp_AntB_10 0xb80 +#define rPdp_AntB_14 0xb84 +#define rPdp_AntB_18 0xb88 +#define rPdp_AntB_1C 0xb8c +#define rPdp_AntB_20 0xb90 +#define rPdp_AntB_24 0xb94 + +#define rConfig_Pmpd_AntB 0xb98 + +#define rBndB 0xba0 + +#define rAPK 0xbd8 +#define rPm_Rx0_AntA 0xbdc +#define rPm_Rx1_AntA 0xbe0 +#define rPm_Rx2_AntA 0xbe4 +#define rPm_Rx3_AntA 0xbe8 +#define rPm_Rx0_AntB 0xbec +#define rPm_Rx1_AntB 0xbf0 +#define rPm_Rx2_AntB 0xbf4 +#define rPm_Rx3_AntB 0xbf8 + +//for power tracking +#define rA_TxScale_Jaguar 0xc1c // Pah_A TX scaling factor +#define rB_TxScale_Jaguar 0xe1c // Path_B TX scaling factor +#define rC_TxScale_Jaguar2 0x181c // Pah_C TX scaling factor +#define rD_TxScale_Jaguar2 0x1A1c // Path_D TX scaling factor +#define rRF_TxGainOffset 0x55 + + +//============================================================ +// Registers for 8188E IQK +//============================================================ + + +#define rFPGA0_IQK 0xe28 +#define rTx_IQK_Tone_A 0xe30 +#define rRx_IQK_Tone_A 0xe34 +#define rTx_IQK_PI_A 0xe38 +#define rRx_IQK_PI_A 0xe3c + +#define rTx_IQK 0xe40 +#define rRx_IQK 0xe44 +#define rIQK_AGC_Pts 0xe48 +#define rIQK_AGC_Rsp 0xe4c +#define rTx_IQK_Tone_B 0xe50 +#define rRx_IQK_Tone_B 0xe54 +#define rTx_IQK_PI_B 0xe58 +#define rRx_IQK_PI_B 0xe5c +#define rIQK_AGC_Cont 0xe60 + +#define rRx_Power_Before_IQK_A 0xea0 +#define rRx_Power_Before_IQK_A_2 0xea4 +#define rRx_Power_After_IQK_A 0xea8 +#define rRx_Power_After_IQK_A_2 0xeac + +#define rTx_Power_Before_IQK_A 0xe94 +#define rTx_Power_After_IQK_A 0xe9c + + +#define rTx_Power_Before_IQK_B 0xeb4 +#define rTx_Power_After_IQK_B 0xebc + +#define rRx_Power_Before_IQK_B 0xec0 +#define rRx_Power_Before_IQK_B_2 0xec4 +#define rRx_Power_After_IQK_B 0xec8 +#define rRx_Power_After_IQK_B_2 0xecc + + +#define RF_RCK_OS 0x30 // RF TX PA control +#define RF_TXPA_G1 0x31 // RF TX PA control +#define RF_TXPA_G2 0x32 // RF TX PA control +#define RF_TXPA_G3 0x33 // RF TX PA control +#define RF_TX_BIAS_A 0x35 +#define RF_TX_BIAS_D 0x36 +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C // +#define RF_TRSW 0x3F + +#define RF_TXRF_A2 0x41 +#define RF_TXPA_G4 0x46 +#define RF_TXPA_A4 0x4B + +#define RF_WE_LUT 0xEF + + +//#define rFPGA0_XAB_SwitchControl 0x858 // RF Channel switch +//#define rFPGA0_XCD_SwitchControl 0x85c + +//#define rFPGA0_XAB_RFInterfaceSW 0x870 // RF Interface Software Control +//#define rFPGA0_XCD_RFInterfaceSW 0x874 + +//#define rFPGA0_XAB_RFParameter 0x878 // RF Parameter +//#define rFPGA0_XCD_RFParameter 0x87c +#define rFPGA0_XCD_RFParam 0x87c + +//#define rFPGA0_AnalogParameter1 0x880 // Crystal cap setting RF-R/W protection for parameter4?? +//#define rFPGA0_AnalogParameter2 0x884 +//#define rFPGA0_AnalogParameter3 0x888 +//#define rFPGA0_AdDaClockEn 0x888 // enable ad/da clock1 for dual-phy +//#define rFPGA0_AnalogParameter4 0x88c + +//#define rFPGA0_XA_LSSIReadBack 0x8a0 // Tranceiver LSSI Readback +//#define rFPGA0_XB_LSSIReadBack 0x8a4 +#define rFPGA0_XC_LSSIReadBack 0x8a8 +#define rFPGA0_XD_LSSIReadBack 0x8ac + +//#define rFPGA0_PSDReport 0x8b4 // Useless now +//#define TransceiverA_HSPI_Readback 0x8b8 // Transceiver A HSPI Readback +//#define TransceiverB_HSPI_Readback 0x8bc // Transceiver B HSPI Readback +//#define rFPGA0_XAB_RFInterfaceRB 0x8e0 // Useless now // RF Interface Readback Value +#define rFPGA0_XCD_RFInterfaceRB 0x8e4 // Useless now + + +#define rBlue_Tooth 0xe6c +#define rRx_Wait_CCA 0xe70 +#define rTx_CCK_RFON 0xe74 +#define rTx_CCK_BBON 0xe78 +#define rTx_OFDM_RFON 0xe7c +#define rTx_OFDM_BBON 0xe80 +#define rTx_To_Rx 0xe84 +#define rTx_To_Tx 0xe88 +#define rRx_CCK 0xe8c + +#define rRx_OFDM 0xed0 +#define rRx_Wait_RIFS 0xed4 +#define rRx_TO_Rx 0xed8 +#define rStandby 0xedc +#define rSleep 0xee0 +#define rPMPD_ANAEN 0xeec + +#ifndef REG_MACID_PKT_SLEEP_0 +#define REG_MACID_PKT_SLEEP_3 0x0484 +#define REG_MACID_PKT_SLEEP_1 0x0488 +#define REG_MACID_PKT_SLEEP_2 0x04D0 +#define REG_MACID_PKT_SLEEP_0 0x04D4 +#endif +#ifndef MACID_REGION1_LIMIT +#define MACID_REGION1_LIMIT 31 +#define MACID_REGION2_LIMIT 63 +#define MACID_REGION3_LIMIT 95 +#endif +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_TSFTR_SNC_OFFSET 0x0518 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 + + +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_BCN_CTRL_1 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 // The same as REG_MBSSID_BCN_SPACE +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_TSFTR1 0x0568 // HW Port 1 TSF Register +#define REG_P2P_CTWIN 0x0572 // 1 Byte long (in unit of TU) +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACMHWCTRL 0x05C0 +#define REG_NOA_DESC_SEL 0x05CF +#define REG_NOA_DESC_DURATION 0x05E0 +#define REG_NOA_DESC_INTERVAL 0x05E4 +#define REG_NOA_DESC_START 0x05E8 +#define REG_NOA_DESC_COUNT 0x05EC + + +#define REG_SYS_ISO_CTRL 0x0000 +//#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS0_CTRL_6 0x0016 +#define REG_POWER_OFF_IN_PROCESS 0x0017 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001C +//#define REG_RF_CTRL 0x001F +#define REG_LDOA15_CTRL 0x0020 +#define REG_LDOV12D_CTRL 0x0021 +//#define REG_LDOHCI12_CTRL 0x0022 +#define REG_LPLDO_CTRL 0x0023 +//#define REG_AFE_XTAL_CTRL 0x0024 +//#define REG_AFE_PLL_CTRL 0x0028 +#define REG_MAC_PHY_CTRL 0x002c //for 92d, DMDP,SMSP,DMSP contrl +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_HSIMR 0x0058 +#define REG_HSISR 0x005c +#define REG_GPIO_PIN_CTRL_2 0x0060 // RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. +#define REG_GPIO_IO_SEL_2 0x0062 // RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. +#define REG_MULTI_FUNC_CTRL 0x0068 // RTL8723 WIFI/BT/GPS Multi-Function control source. +#define REG_GPIO_OUTPUT 0x006c +#define REG_AFE_XTAL_CTRL_EXT 0x0078 //RTL8188E +#define REG_XCK_OUT_CTRL 0x007c //RTL8188E +//#define REG_MCUFWDL 0x0080 +#define REG_WOL_EVENT 0x0081 //RTL8188E +#define REG_MCUTSTCFG 0x0084 +#define REG_HMEBOX_EXT_0 0x0088 +#define REG_HMEBOX_EXT_1 0x008A +#define REG_HMEBOX_EXT_2 0x008C +#define REG_HMEBOX_EXT_3 0x008E +#define REG_HOST_SUSP_CNT 0x00BC // RTL8192C Host suspend counter on FPGA platform +#define REG_HIMR_88E 0x00B0 //RTL8188E +#define REG_HISR_88E 0x00B4 //RTL8188E +#define REG_HIMRE_88E 0x00B8 //RTL8188E +#define REG_HISRE_88E 0x00BC //RTL8188E +#define REG_EFUSE_ACCESS 0x00CF // Efuse access protection for RTL8723 +#define REG_BIST_SCAN 0x00D0 +#define REG_BIST_RPT 0x00D4 +#define REG_BIST_ROM_RPT 0x00D8 +#define REG_USB_SIE_INTF 0x00E0 +#define REG_PCIE_MIO_INTF 0x00E4 +#define REG_PCIE_MIO_INTD 0x00E8 +#define REG_HPON_FSM 0x00EC +#define REG_SYS_CFG 0x00F0 +#define REG_GPIO_OUTSTS 0x00F4 // For RTL8723 only. +#define REG_TYPE_ID 0x00FC + +#define rConfig_AntA 0xb68 +#define rConfig_AntB 0xb6c + +#endif //FOR_8812_IQK + +//============================================================ +// +//============================================================ + +//----------------------------------------------------- +// +// 0x0000h ~ 0x00FFh System Configuration +// +//----------------------------------------------------- +#define REG_SYS_ISO_CTRL_8812 0x0000 // 2 Byte +#define REG_SYS_FUNC_EN_8812 0x0002 // 2 Byte +#define REG_APS_FSMCO_8812 0x0004 // 4 Byte +#define REG_SYS_CLKR_8812 0x0008 // 2 Byte +#define REG_9346CR_8812 0x000A // 2 Byte +#define REG_EE_VPD_8812 0x000C // 2 Byte +#define REG_AFE_MISC_8812 0x0010 // 1 Byte +#define REG_SPS0_CTRL_8812 0x0011 // 7 Byte +#define REG_SPS_OCP_CFG_8812 0x0018 // 4 Byte +#define REG_RSV_CTRL_8812 0x001C // 3 Byte +#define REG_RF_CTRL_8812 0x001F // 1 Byte +#define REG_LPLDO_CTRL_8812 0x0023 // 1 Byte +#define REG_AFE_XTAL_CTRL_8812 0x0024 // 4 Byte +#define REG_AFE_PLL_CTRL_8812 0x0028 // 4 Byte +#define REG_MAC_PLL_CTRL_EXT_8812 0x002c // 4 Byte +#define REG_EFUSE_CTRL_8812 0x0030 +#define REG_EFUSE_TEST_8812 0x0034 +#define REG_PWR_DATA_8812 0x0038 +#define REG_CAL_TIMER_8812 0x003C +#define REG_ACLK_MON_8812 0x003E +#define REG_GPIO_MUXCFG_8812 0x0040 +#define REG_GPIO_IO_SEL_8812 0x0042 +#define REG_MAC_PINMUX_CFG_8812 0x0043 +#define REG_GPIO_PIN_CTRL_8812 0x0044 +#define REG_GPIO_INTM_8812 0x0048 +#define REG_LEDCFG0_8812 0x004C +#define REG_LEDCFG1_8812 0x004D +#define REG_LEDCFG2_8812 0x004E +#define REG_LEDCFG3_8812 0x004F +#define REG_FSIMR_8812 0x0050 +#define REG_FSISR_8812 0x0054 +#define REG_HSIMR_8812 0x0058 +#define REG_HSISR_8812 0x005c +#define REG_GPIO_STATUS_8812 0x006C +#define REG_SDIO_CTRL_8812 0x0070 +#define REG_OPT_CTRL_8812 0x0074 +#define REG_AFE_XTAL_CTRL_EXT_8812 0x0078 +#define REG_MCUFWDL_8812 0x0080 +#define REG_HIMR0_8812 0x00B0 +#define REG_HISR0_8812 0x00B4 +#define REG_HIMR1_8812 0x00B8 +#define REG_PG_PASSWD_8812 0x00CF +#define REG_HISR1_8812 0x00BC +#define REG_HPON_FSM_8812 0x00EC +#define REG_SYS_CFG_8812 0x00F0 + + +//----------------------------------------------------- +// +// 0x0100h ~ 0x01FFh MACTOP General Configuration +// +//----------------------------------------------------- +#define REG_CR_8812 0x0100 +#define REG_PBP_8812 0x0104 +#define REG_PKT_BUFF_ACCESS_CTRL_8812 0x0106 +#define REG_TRXDMA_CTRL_8812 0x010C +#define REG_TRXFF_BNDY_8812 0x0114 +#define REG_TRXFF_STATUS_8812 0x0118 +#define REG_RXFF_PTR_8812 0x011C +#define REG_CPWM_8812 0x012F +#define REG_FWIMR_8812 0x0130 +#define REG_FWISR_8812 0x0134 +#define REG_FTIMR_8812 0x0138 +#define REG_PKTBUF_DBG_CTRL_8812 0x0140 +#define REG_RXPKTBUF_CTRL_8812 0x0142 +#define REG_PKTBUF_DBG_DATA_L_8812 0x0144 +#define REG_PKTBUF_DBG_DATA_H_8812 0x0148 + +#define REG_TC0_CTRL_8812 0x0150 +#define REG_TC1_CTRL_8812 0x0154 +#define REG_TC2_CTRL_8812 0x0158 +#define REG_TC3_CTRL_8812 0x015C +#define REG_TC4_CTRL_8812 0x0160 +#define REG_TCUNIT_BASE_8812 0x0164 +#define REG_RSVD3_8812 0x0168 +#define REG_C2HEVT_MSG_NORMAL_8812 0x01A0 +#define REG_C2HEVT_CLEAR_8812 0x01AF +#define REG_MCUTST_1_8812 0x01C0 +#define REG_MCUTST_WOWLAN_8812 0x01C7 +#define REG_FMETHR_8812 0x01C8 +#define REG_HMETFR_8812 0x01CC +#define REG_HMEBOX_0_8812 0x01D0 +#define REG_HMEBOX_1_8812 0x01D4 +#define REG_HMEBOX_2_8812 0x01D8 +#define REG_HMEBOX_3_8812 0x01DC +#define REG_LLT_INIT_8812 0x01E0 +#define REG_HMEBOX_EXT0_8812 0x01F0 +#define REG_HMEBOX_EXT1_8812 0x01F4 +#define REG_HMEBOX_EXT2_8812 0x01F8 +#define REG_HMEBOX_EXT3_8812 0x01FC + +//----------------------------------------------------- +// +// 0x0200h ~ 0x027Fh TXDMA Configuration +// +//----------------------------------------------------- +#define REG_RQPN_8812 0x0200 +#define REG_FIFOPAGE_8812 0x0204 +#define REG_TDECTRL_8812 0x0208 +#define REG_TXDMA_OFFSET_CHK_8812 0x020C +#define REG_TXDMA_STATUS_8812 0x0210 +#define REG_RQPN_NPQ_8812 0x0214 + +//----------------------------------------------------- +// +// 0x0280h ~ 0x02FFh RXDMA Configuration +// +//----------------------------------------------------- +#define REG_RXDMA_AGG_PG_TH_8812 0x0280 +#define REG_FW_UPD_RDPTR_8812 0x0284 // FW shall update this register before FW write RXPKT_RELEASE_POLL to 1 +#define REG_RXDMA_CONTROL_8812 0x0286 // Control the RX DMA. +#define REG_RXPKT_NUM_8812 0x0287 // The number of packets in RXPKTBUF. +#define REG_RXDMA_STATUS_8812 0x0288 +#define REG_RXDMA_PRO_8812 0x0290 +#define REG_EARLY_MODE_CONTROL_8812 0x02BC +#define REG_RSVD5_8812 0x02F0 +#define REG_RSVD6_8812 0x02F4 + + +//----------------------------------------------------- +// +// 0x0300h ~ 0x03FFh PCIe +// +//----------------------------------------------------- +#define REG_PCIE_CTRL_REG_8812 0x0300 +#define REG_INT_MIG_8812 0x0304 // Interrupt Migration +#define REG_BCNQ_DESA_8812 0x0308 // TX Beacon Descriptor Address +#define REG_HQ_DESA_8812 0x0310 // TX High Queue Descriptor Address +#define REG_MGQ_DESA_8812 0x0318 // TX Manage Queue Descriptor Address +#define REG_VOQ_DESA_8812 0x0320 // TX VO Queue Descriptor Address +#define REG_VIQ_DESA_8812 0x0328 // TX VI Queue Descriptor Address +#define REG_BEQ_DESA_8812 0x0330 // TX BE Queue Descriptor Address +#define REG_BKQ_DESA_8812 0x0338 // TX BK Queue Descriptor Address +#define REG_RX_DESA_8812 0x0340 // RX Queue Descriptor Address +#define REG_MDIO_8812 0x0354 // MDIO for Access PCIE PHY +#define REG_DBG_SEL_8812 0x0360 // Debug Selection Register +#define REG_PCIE_HRPWM_8812 0x0361 //PCIe RPWM +#define REG_PCIE_HCPWM_8812 0x0363 //PCIe CPWM +#define REG_PCIE_MULTIFET_CTRL_8812 0x036A //PCIE Multi-Fethc Control + +// spec version 11 +//----------------------------------------------------- +// +// 0x0400h ~ 0x047Fh Protocol Configuration +// +//----------------------------------------------------- +#define REG_VOQ_INFORMATION_8812 0x0400 +#define REG_VIQ_INFORMATION_8812 0x0404 +#define REG_BEQ_INFORMATION_8812 0x0408 +#define REG_BKQ_INFORMATION_8812 0x040C +#define REG_MGQ_INFORMATION_8812 0x0410 +#define REG_HGQ_INFORMATION_8812 0x0414 +#define REG_BCNQ_INFORMATION_8812 0x0418 +#define REG_TXPKT_EMPTY_8812 0x041A + +#define REG_FWHW_TXQ_CTRL_8812 0x0420 +#define REG_HWSEQ_CTRL_8812 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY_8812 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY_8812 0x0425 +#define REG_LIFECTRL_CTRL_8812 0x0426 +#define REG_MULTI_BCNQ_OFFSET_8812 0x0427 +#define REG_SPEC_SIFS_8812 0x0428 +#define REG_RL_8812 0x042A +#define REG_TXBF_CTRL_8812 0x042C +#define REG_DARFRC_8812 0x0430 +#define REG_RARFRC_8812 0x0438 +#define REG_RRSR_8812 0x0440 +#define REG_ARFR0_8812 0x0444 +#define REG_ARFR1_8812 0x044C +#define REG_CCK_CHECK_8812 0x0454 +#define REG_AMPDU_MAX_TIME_8812 0x0456 +#define REG_AMPDU_MAX_LENGTH_8812 0x0458 +#define REG_TXPKTBUF_WMAC_LBK_BF_HD_8812 0x045D +#define REG_NDPA_OPT_CTRL_8812 0x045F +#define REG_FAST_EDCA_CTRL_8812 0x0460 +#define REG_RD_RESP_PKT_TH_8812 0x0463 +#define REG_DATA_SC_8812 0x0483 +#define REG_TXRPT_START_OFFSET 0x04AC +#define REG_POWER_STAGE1_8812 0x04B4 +#define REG_POWER_STAGE2_8812 0x04B8 +#define REG_AMPDU_BURST_MODE_8812 0x04BC +#define REG_PKT_VO_VI_LIFE_TIME_8812 0x04C0 +#define REG_PKT_BE_BK_LIFE_TIME_8812 0x04C2 +#define REG_STBC_SETTING_8812 0x04C4 +#define REG_PROT_MODE_CTRL_8812 0x04C8 +#define REG_MAX_AGGR_NUM_8812 0x04CA +#define REG_RTS_MAX_AGGR_NUM_8812 0x04CB +#define REG_BAR_MODE_CTRL_8812 0x04CC +#define REG_RA_TRY_RATE_AGG_LMT_8812 0x04CF +#define REG_MACID_PKT_DROP0_8812 0x04D0 + +//----------------------------------------------------- +// +// 0x0500h ~ 0x05FFh EDCA Configuration +// +//----------------------------------------------------- +#define REG_EDCA_VO_PARAM_8812 0x0500 +#define REG_EDCA_VI_PARAM_8812 0x0504 +#define REG_EDCA_BE_PARAM_8812 0x0508 +#define REG_EDCA_BK_PARAM_8812 0x050C +#define REG_BCNTCFG_8812 0x0510 +#define REG_PIFS_8812 0x0512 +#define REG_RDG_PIFS_8812 0x0513 +#define REG_SIFS_CTX_8812 0x0514 +#define REG_SIFS_TRX_8812 0x0516 +#define REG_AGGR_BREAK_TIME_8812 0x051A +#define REG_SLOT_8812 0x051B +#define REG_TX_PTCL_CTRL_8812 0x0520 +#define REG_TXPAUSE_8812 0x0522 +#define REG_DIS_TXREQ_CLR_8812 0x0523 +#define REG_RD_CTRL_8812 0x0524 +// +// Format for offset 540h-542h: +// [3:0]: TBTT prohibit setup in unit of 32us. The time for HW getting beacon content before TBTT. +// [7:4]: Reserved. +// [19:8]: TBTT prohibit hold in unit of 32us. The time for HW holding to send the beacon packet. +// [23:20]: Reserved +// Description: +// | +// |<--Setup--|--Hold------------>| +// --------------|---------------------- +// | +// TBTT +// Note: We cannot update beacon content to HW or send any AC packets during the time between Setup and Hold. +// Described by Designer Tim and Bruce, 2011-01-14. +// +#define REG_TBTT_PROHIBIT_8812 0x0540 +#define REG_RD_NAV_NXT_8812 0x0544 +#define REG_NAV_PROT_LEN_8812 0x0546 +#define REG_BCN_CTRL_8812 0x0550 +#define REG_BCN_CTRL_1_8812 0x0551 +#define REG_MBID_NUM_8812 0x0552 +#define REG_DUAL_TSF_RST_8812 0x0553 +#define REG_BCN_INTERVAL_8812 0x0554 +#define REG_DRVERLYINT_8812 0x0558 +#define REG_BCNDMATIM_8812 0x0559 +#define REG_ATIMWND_8812 0x055A +#define REG_BCN_MAX_ERR_8812 0x055D +#define REG_RXTSF_OFFSET_CCK_8812 0x055E +#define REG_RXTSF_OFFSET_OFDM_8812 0x055F +#define REG_TSFTR_8812 0x0560 +#define REG_CTWND_8812 0x0572 +#define REG_PSTIMER_8812 0x0580 +#define REG_TIMER0_8812 0x0584 +#define REG_TIMER1_8812 0x0588 +#define REG_ACMHWCTRL_8812 0x05C0 +#define REG_SCH_TXCMD_8812 0x05F8 + +//----------------------------------------------------- +// +// 0x0600h ~ 0x07FFh WMAC Configuration +// +//----------------------------------------------------- +#define REG_MAC_CR_8812 0x0600 +#define REG_TCR_8812 0x0604 +#define REG_RCR_8812 0x0608 +#define REG_RX_PKT_LIMIT_8812 0x060C +#define REG_RX_DLK_TIME_8812 0x060D +#define REG_RX_DRVINFO_SZ_8812 0x060F + +#define REG_MACID_8812 0x0610 +#define REG_BSSID_8812 0x0618 +#define REG_MAR_8812 0x0620 +#define REG_MBIDCAMCFG_8812 0x0628 + +#define REG_USTIME_EDCA_8812 0x0638 +#define REG_MAC_SPEC_SIFS_8812 0x063A +#define REG_RESP_SIFP_CCK_8812 0x063C +#define REG_RESP_SIFS_OFDM_8812 0x063E +#define REG_ACKTO_8812 0x0640 +#define REG_CTS2TO_8812 0x0641 +#define REG_EIFS_8812 0x0642 + +#define REG_NAV_UPPER_8812 0x0652 // unit of 128 +#define REG_TRXPTCL_CTL_8812 0x0668 + +// Security +#define REG_CAMCMD_8812 0x0670 +#define REG_CAMWRITE_8812 0x0674 +#define REG_CAMREAD_8812 0x0678 +#define REG_CAMDBG_8812 0x067C +#define REG_SECCFG_8812 0x0680 + +// Power +#define REG_WOW_CTRL_8812 0x0690 +#define REG_PS_RX_INFO_8812 0x0692 +#define REG_UAPSD_TID_8812 0x0693 +#define REG_WKFMCAM_CMD_8812 0x0698 +#define REG_WKFMCAM_NUM_8812 0x0698 +#define REG_WKFMCAM_RWD_8812 0x069C +#define REG_RXFLTMAP0_8812 0x06A0 +#define REG_RXFLTMAP1_8812 0x06A2 +#define REG_RXFLTMAP2_8812 0x06A4 +#define REG_BCN_PSR_RPT_8812 0x06A8 +#define REG_BT_COEX_TABLE_8812 0x06C0 +#define REG_BFMER0_INFO_8812 0x06E4 +#define REG_BFMER1_INFO_8812 0x06EC +#define REG_CSI_RPT_PARAM_BW20_8812 0x06F4 +#define REG_CSI_RPT_PARAM_BW40_8812 0x06F8 +#define REG_CSI_RPT_PARAM_BW80_8812 0x06FC + +// Hardware Port 2 +#define REG_MACID1_8812 0x0700 +#define REG_BSSID1_8812 0x0708 +#define REG_BFMEE_SEL_8812 0x0714 +#define REG_SND_PTCL_CTRL_8812 0x0718 + + +// Misc functions +#define rEDCCA_Jaguar 0x8a4 // EDCCA +#define bEDCCA_Jaguar 0xffff +#define rAGC_table_Jaguar 0x82c // AGC tabel select +#define bAGC_table_Jaguar 0x3 +#define rA_RFE_Pinmux_Jaguar 0xcb0 // Path_A RFE cotrol pinmux +#define rB_RFE_Pinmux_Jaguar 0xeb0 // Path_B RFE control pinmux +#define rA_RFE_Jaguar 0xcb8 // Path_A RFE cotrol +#define rB_RFE_Jaguar 0xeb8 // Path_B RFE control +#define b_sel5g_Jaguar 0x1000 // sel5g +#define b_LNA_sw_Jaguar 0x8000 // HW/WS control for LNA +#define rFc_area_Jaguar 0x860 // fc_area +#define bFc_area_Jaguar 0x1ffe000 +#define rSingleTone_ContTx_Jaguar 0x914 +#define rfc_cck_enable_JAguar 0x808 +#define rfc_Enabl_VHT_JAguar 0x8c0 + +// DIG-related +#define rA_IGI_Jaguar 0xc50 // Initial Gain for path-A +#define rB_IGI_Jaguar 0xe50 // Initial Gain for path-B +#define rOFDM_FalseAlarm1_Jaguar 0xf48 // counter for break +#define rOFDM_FalseAlarm2_Jaguar 0xf4c // counter for spoofing +#define rCCK_FalseAlarm_Jaguar 0xa5c // counter for cck false alarm +#define b_FalseAlarm_Jaguar 0xffff +#define rCCK_CCA_Jaguar 0xa08 // cca threshold + +#define bCCK_CCA_Jaguar 0x00ff0000 + +#if 0 +// TX AGC +#define rTxAGC_A_CCK11_CCK1_JAguar 0xc20 +#define rTxAGC_A_Ofdm18_Ofdm6_JAguar 0xc24 +#define rTxAGC_A_Ofdm54_Ofdm24_JAguar 0xc28 +#define rTxAGC_A_MCS3_MCS0_JAguar 0xc2c +#define rTxAGC_A_MCS7_MCS4_JAguar 0xc30 +#define rTxAGC_A_MCS11_MCS8_JAguar 0xc34 +#define rTxAGC_A_MCS15_MCS12_JAguar 0xc38 +#define rTxAGC_A_Nss1Index3_Nss1Index0_JAguar 0xc3c +#define rTxAGC_A_Nss1Index7_Nss1Index4_JAguar 0xc40 +#define rTxAGC_A_Nss2Index1_Nss1Index8_JAguar 0xc44 +#define rTxAGC_A_Nss2Index5_Nss2Index2_JAguar 0xc48 +#define rTxAGC_A_Nss2Index9_Nss2Index6_JAguar 0xc4c +#define rTxAGC_B_CCK11_CCK1_JAguar 0xe20 +#define rTxAGC_B_Ofdm18_Ofdm6_JAguar 0xe24 +#define rTxAGC_B_Ofdm54_Ofdm24_JAguar 0xe28 +#define rTxAGC_B_MCS3_MCS0_JAguar 0xe2c +#define rTxAGC_B_MCS7_MCS4_JAguar 0xe30 +#define rTxAGC_B_MCS11_MCS8_JAguar 0xe34 +#define rTxAGC_B_MCS15_MCS12_JAguar 0xe38 +#define rTxAGC_B_Nss1Index3_Nss1Index0_JAguar 0xe3c +#define rTxAGC_B_Nss1Index7_Nss1Index4_JAguar 0xe40 +#define rTxAGC_B_Nss2Index1_Nss1Index8_JAguar 0xe44 +#define rTxAGC_B_Nss2Index5_Nss2Index2_JAguar 0xe48 +#define rTxAGC_B_Nss2Index9_Nss2Index6_JAguar 0xe4c +#define bTxAGC_byte0_Jaguar 0xff +#define bTxAGC_byte1_Jaguar 0xff00 +#define bTxAGC_byte2_Jaguar 0xff0000 +#define bTxAGC_byte3_Jaguar 0xff000000 +#endif + +#define rOFDMCCKEN_Jaguar 0x808 // OFDM/CCK block enable +#define bOFDMEN_Jaguar 0x20000000 +#define bCCKEN_Jaguar 0x10000000 +#define rRxPath_Jaguar 0x808 // Rx antenna +#define bRxPath_Jaguar 0xff +#define rTxPath_Jaguar 0x80c // Tx antenna +#define bTxPath_Jaguar 0x0fffffff +#define rCCK_RX_Jaguar 0xa04 // for cck rx path selection +#define bCCK_RX_Jaguar 0x0c000000 +#define rVhtlen_Use_Lsig_Jaguar 0x8c3 // Use LSIG for VHT length +#define RF_AC_Jaguar 0x00 // +#define RF_RF_Top_Jaguar 0x07 // +#define RF_TXLOK_Jaguar 0x08 // +#define RF_TXAPK_Jaguar 0x0B +#define RF_CHNLBW_Jaguar 0x18 // RF channel and BW switch +#define RF_RCK1_Jaguar 0x1c // +#define RF_RCK2_Jaguar 0x1d +#define RF_RCK3_Jaguar 0x1e +#define RF_ModeTableAddr 0x30 +#define RF_ModeTableData0 0x31 +#define RF_ModeTableData1 0x32 +#define RF_TxLCTank_Jaguar 0x54 +#define RF_APK_Jaguar 0x63 +#define RF_LCK 0xB4 +#define RF_WeLut_Jaguar 0xEF +#define bRF_CHNLBW_MOD_AG_Jaguar 0x70300 +#define bRF_CHNLBW_BW 0xc00 + +//----------------------------------------------------- +// +// 0xFE00h ~ 0xFE55h USB Configuration +// +//----------------------------------------------------- +/* +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + + +// For normal chip +#define REG_NORMAL_SIE_VID 0xFE60 // 0xFE60~0xFE61 +#define REG_NORMAL_SIE_PID 0xFE62 // 0xFE62~0xFE63 +#define REG_NORMAL_SIE_OPTIONAL 0xFE64 +#define REG_NORMAL_SIE_EP 0xFE65 // 0xFE65~0xFE67 +#define REG_NORMAL_SIE_PHY 0xFE68 // 0xFE68~0xFE6B +#define REG_NORMAL_SIE_OPTIONAL2 0xFE6C +#define REG_NORMAL_SIE_GPS_EP 0xFE6D // 0xFE6D, for RTL8723 only. +#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 // 0xFE70~0xFE75 +#define REG_NORMAL_SIE_STRING 0xFE80 // 0xFE80~0xFEDF +*/ + +//----------------------------------------------------- +// +// Redifine 8192C register definition for compatibility +// +//----------------------------------------------------- + +// TODO: use these definition when using REG_xxx naming rule. +// NOTE: DO NOT Remove these definition. Use later. +#define EFUSE_CTRL_8812 REG_EFUSE_CTRL_8812 // E-Fuse Control. +#define EFUSE_TEST_8812 REG_EFUSE_TEST_8812 // E-Fuse Test. +#define MSR_8812 (REG_CR_8812 + 2) // Media Status register +#define ISR_8812 REG_HISR0_8812 +#define TSFR_8812 REG_TSFTR_8812 // Timing Sync Function Timer Register. + +#define PBP_8812 REG_PBP_8812 + +// Redifine MACID register, to compatible prior ICs. +#define IDR0_8812 REG_MACID_8812 // MAC ID Register, Offset 0x0050-0x0053 +#define IDR4_8812 (REG_MACID_8812 + 4) // MAC ID Register, Offset 0x0054-0x0055 + + +// +// 9. Security Control Registers (Offset: ) +// +#define RWCAM_8812 REG_CAMCMD_8812 //IN 8190 Data Sheet is called CAMcmd +#define WCAMI_8812 REG_CAMWRITE_8812 // Software write CAM input content +#define RCAMO_8812 REG_CAMREAD_8812 // Software read/write CAM config +#define CAMDBG_8812 REG_CAMDBG_8812 +#define SECR_8812 REG_SECCFG_8812 //Security Configuration Register + +/* + +// Unused register +#define UnusedRegister 0x1BF +#define DCAM UnusedRegister +#define PSR UnusedRegister +#define BBAddr UnusedRegister +#define PhyDataR UnusedRegister + + + +//---------------------------------------------------------------------------- +// 8192C Cmd9346CR bits (Offset 0xA, 16bit) +//---------------------------------------------------------------------------- +#define CmdEEPROM_En BIT5 // EEPROM enable when set 1 +#define CmdEERPOMSEL BIT4 // System EEPROM select, 0: boot from E-FUSE, 1: The EEPROM used is 9346 +#define Cmd9346CR_9356SEL BIT4 + +//---------------------------------------------------------------------------- +// 8192C GPIO MUX Configuration Register (offset 0x40, 4 byte) +//---------------------------------------------------------------------------- +#define GPIOSEL_GPIO BIT0 +#define GPIOSEL_ENBT BIT5 + +//---------------------------------------------------------------------------- +// 8192C GPIO PIN Control Register (offset 0x44, 4 byte) +//---------------------------------------------------------------------------- +#define GPIO_IN REG_GPIO_PIN_CTRL_8195 // GPIO pins input value +#define GPIO_OUT (REG_GPIO_PIN_CTRL_8195+1) // GPIO pins output value +#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL_8195+2) // GPIO pins output enable when a bit is set to "1"; otherwise, input is configured. +#define GPIO_MOD (REG_GPIO_PIN_CTRL_8195+3) +#define HAL_8192C_HW_GPIO_WPS_BIT BIT2 + +//---------------------------------------------------------------------------- +// 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) +//---------------------------------------------------------------------------- +#define HSIMR_GPIO12_0_INT_EN BIT0 +#define HSIMR_SPS_OCP_INT_EN BIT5 +#define HSIMR_RON_INT_EN BIT6 +#define HSIMR_PDN_INT_EN BIT7 +#define HSIMR_GPIO9_INT_EN BIT25 + + +//---------------------------------------------------------------------------- +// 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) +//---------------------------------------------------------------------------- +#define HSISR_GPIO12_0_INT BIT0 +#define HSISR_SPS_OCP_INT BIT5 +#define HSISR_RON_INT_EN BIT6 +#define HSISR_PDNINT BIT7 +#define HSISR_GPIO9_INT BIT25 + +//---------------------------------------------------------------------------- +// 8195 (MSR) Media Status Register (Offset 0x4C, 8 bits) +//---------------------------------------------------------------------------- +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 + +//---------------------------------------------------------------------------- +// 88EU (MSR) Media Status Register (Offset 0x4C, 8 bits) +//---------------------------------------------------------------------------- +#define USB_INTR_CONTENT_HISR_OFFSET 48 +#define USB_INTR_CONTENT_HISRE_OFFSET 52 + + +// +// 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) +// +//---------------------------------------------------------------------------- +// 8192C Response Rate Set Register (offset 0x181, 24bits) +//---------------------------------------------------------------------------- +#define RRSR_1M BIT0 +#define RRSR_2M BIT1 +#define RRSR_5_5M BIT2 +#define RRSR_11M BIT3 +#define RRSR_6M BIT4 +#define RRSR_9M BIT5 +#define RRSR_12M BIT6 +#define RRSR_18M BIT7 +#define RRSR_24M BIT8 +#define RRSR_36M BIT9 +#define RRSR_48M BIT10 +#define RRSR_54M BIT11 +#define RRSR_MCS0 BIT12 +#define RRSR_MCS1 BIT13 +#define RRSR_MCS2 BIT14 +#define RRSR_MCS3 BIT15 +#define RRSR_MCS4 BIT16 +#define RRSR_MCS5 BIT17 +#define RRSR_MCS6 BIT18 +#define RRSR_MCS7 BIT19 + + +//---------------------------------------------------------------------------- +// 8192C Response Rate Set Register (offset 0x1BF, 8bits) +//---------------------------------------------------------------------------- +// WOL bit information +#define HAL92C_WOL_PTK_UPDATE_EVENT BIT0 +#define HAL92C_WOL_GTK_UPDATE_EVENT BIT1 + + +//---------------------------------------------------------------------------- +// 8192C Rate Definition +//---------------------------------------------------------------------------- +//CCK +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +//OFDM +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +//MCS 1 Spatial Stream +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +//MCS 2 Spatial Stream +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + + +// NOTE: For 92CU - Ziv +//CCK +#define RATE_1M BIT(0) +#define RATE_2M BIT(1) +#define RATE_5_5M BIT(2) +#define RATE_11M BIT(3) +//OFDM +#define RATE_6M BIT(4) +#define RATE_9M BIT(5) +#define RATE_12M BIT(6) +#define RATE_18M BIT(7) +#define RATE_24M BIT(8) +#define RATE_36M BIT(9) +#define RATE_48M BIT(10) +#define RATE_54M BIT(11) +//MCS 1 Spatial Stream +#define RATE_MCS0 BIT(12) +#define RATE_MCS1 BIT(13) +#define RATE_MCS2 BIT(14) +#define RATE_MCS3 BIT(15) +#define RATE_MCS4 BIT(16) +#define RATE_MCS5 BIT(17) +#define RATE_MCS6 BIT(18) +#define RATE_MCS7 BIT(19) +//MCS 2 Spatial Stream +#define RATE_MCS8 BIT(20) +#define RATE_MCS9 BIT(21) +#define RATE_MCS10 BIT(22) +#define RATE_MCS11 BIT(23) +#define RATE_MCS12 BIT(24) +#define RATE_MCS13 BIT(25) +#define RATE_MCS14 BIT(26) +#define RATE_MCS15 BIT(27) + + + + +// ALL CCK Rate +#define RATE_ALL_CCK RATR_1M|RATR_2M|RATR_55M|RATR_11M +#define RATE_ALL_OFDM_AG RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M|\ + RATR_36M|RATR_48M|RATR_54M +#define RATE_ALL_OFDM_1SS RATR_MCS0|RATR_MCS1|RATR_MCS2|RATR_MCS3 |\ + RATR_MCS4|RATR_MCS5|RATR_MCS6 |RATR_MCS7 +#define RATE_ALL_OFDM_2SS RATR_MCS8|RATR_MCS9 |RATR_MCS10|RATR_MCS11|\ + RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15 + +#define RATE_BITMAP_ALL 0xFFFFF + +// Only use CCK 1M rate for ACK +#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 +//---------------------------------------------------------------------------- +// 8192C BW_OPMODE bits (Offset 0x203, 8bit) +//---------------------------------------------------------------------------- +#define BW_OPMODE_20MHZ BIT2 +#define BW_OPMODE_5G BIT1 + +// +// 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) +// +#define WOW_PMEN BIT0 // Power management Enable. +#define WOW_WOMEN BIT1 // WoW function on or off. +#define WOW_MAGIC BIT2 // Magic packet +#define WOW_UWF BIT3 // Unicast Wakeup frame. + +*/ + + + +//---------------------------------------------------------------------------- +// 8195 IMR/ISR bits (offset 0xB0, 8bits) +//---------------------------------------------------------------------------- +#define IMR_DISABLED_8812 0 +// IMR DW0(0x00B0-00B3) Bit 0-31 +#define IMR_TIMER2_8812 BIT31 // Timeout interrupt 2 +#define IMR_TIMER1_8812 BIT30 // Timeout interrupt 1 +#define IMR_PSTIMEOUT_8812 BIT29 // Power Save Time Out Interrupt +#define IMR_GTINT4_8812 BIT28 // When GTIMER4 expires, this bit is set to 1 +#define IMR_GTINT3_8812 BIT27 // When GTIMER3 expires, this bit is set to 1 +#define IMR_TXBCN0ERR_8812 BIT26 // Transmit Beacon0 Error +#define IMR_TXBCN0OK_8812 BIT25 // Transmit Beacon0 OK +#define IMR_TSF_BIT32_TOGGLE_8812 BIT24 // TSF Timer BIT32 toggle indication interrupt +#define IMR_BCNDMAINT0_8812 BIT20 // Beacon DMA Interrupt 0 +#define IMR_BCNDERR0_8812 BIT16 // Beacon Queue DMA OK0 +#define IMR_BCNDMAINT_E_8812 BIT14 // Beacon DMA Interrupt Extension for Win7 +#define IMR_ATIMEND_8812 BIT12 // CTWidnow End or ATIM Window End +#define IMR_C2HCMD_8812 BIT10 // CPU to Host Command INT Status, Write 1 clear +#define IMR_CPWM2_8812 BIT9 // CPU power Mode exchange INT Status, Write 1 clear +#define IMR_CPWM_8812 BIT8 // CPU power Mode exchange INT Status, Write 1 clear +#define IMR_HIGHDOK_8812 BIT7 // High Queue DMA OK +#define IMR_MGNTDOK_8812 BIT6 // Management Queue DMA OK +#define IMR_BKDOK_8812 BIT5 // AC_BK DMA OK +#define IMR_BEDOK_8812 BIT4 // AC_BE DMA OK +#define IMR_VIDOK_8812 BIT3 // AC_VI DMA OK +#define IMR_VODOK_8812 BIT2 // AC_VO DMA OK +#define IMR_RDU_8812 BIT1 // Rx Descriptor Unavailable +#define IMR_ROK_8812 BIT0 // Receive DMA OK + +// IMR DW1(0x00B4-00B7) Bit 0-31 +#define IMR_BCNDMAINT7_8812 BIT27 // Beacon DMA Interrupt 7 +#define IMR_BCNDMAINT6_8812 BIT26 // Beacon DMA Interrupt 6 +#define IMR_BCNDMAINT5_8812 BIT25 // Beacon DMA Interrupt 5 +#define IMR_BCNDMAINT4_8812 BIT24 // Beacon DMA Interrupt 4 +#define IMR_BCNDMAINT3_8812 BIT23 // Beacon DMA Interrupt 3 +#define IMR_BCNDMAINT2_8812 BIT22 // Beacon DMA Interrupt 2 +#define IMR_BCNDMAINT1_8812 BIT21 // Beacon DMA Interrupt 1 +#define IMR_BCNDOK7_8812 BIT20 // Beacon Queue DMA OK Interrup 7 +#define IMR_BCNDOK6_8812 BIT19 // Beacon Queue DMA OK Interrup 6 +#define IMR_BCNDOK5_8812 BIT18 // Beacon Queue DMA OK Interrup 5 +#define IMR_BCNDOK4_8812 BIT17 // Beacon Queue DMA OK Interrup 4 +#define IMR_BCNDOK3_8812 BIT16 // Beacon Queue DMA OK Interrup 3 +#define IMR_BCNDOK2_8812 BIT15 // Beacon Queue DMA OK Interrup 2 +#define IMR_BCNDOK1_8812 BIT14 // Beacon Queue DMA OK Interrup 1 +#define IMR_ATIMEND_E_8812 BIT13 // ATIM Window End Extension for Win7 +#define IMR_TXERR_8812 BIT11 // Tx Error Flag Interrupt Status, write 1 clear. +#define IMR_RXERR_8812 BIT10 // Rx Error Flag INT Status, Write 1 clear +#define IMR_TXFOVW_8812 BIT9 // Transmit FIFO Overflow +#define IMR_RXFOVW_8812 BIT8 // Receive FIFO Overflow + + + + + +/*=================================================================== +===================================================================== +Here the register defines are for 92C. When the define is as same with 92C, +we will use the 92C's define for the consistency +So the following defines for 92C is not entire!!!!!! +===================================================================== +=====================================================================*/ +/* +Based on Datasheet V33---090401 +Register Summary +Current IOREG MAP +0x0000h ~ 0x00FFh System Configuration (256 Bytes) +0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes) +0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes) +0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes) +0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes) +0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes) +0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes) +0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes) +0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes) +*/ +//---------------------------------------------------------------------------- +// 8195 (TXPAUSE) transmission pause (Offset 0x522, 8 bits) +//---------------------------------------------------------------------------- +/* +#define StopBecon BIT6 +#define StopHigh BIT5 +#define StopMgt BIT4 +#define StopVO BIT3 +#define StopVI BIT2 +#define StopBE BIT1 +#define StopBK BIT0 +*/ + + +//----------------------------------------------------- +// +// 0xFE00h ~ 0xFE55h USB Configuration +// +//----------------------------------------------------- +/*#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_USB_HRPWM 0xFE58 +#define REG_USB_HCPWM 0xFE57 + +//2 USB Information (0xFE17) +#define USB_IS_HIGH_SPEED 0 +#define USB_IS_FULL_SPEED 1 +#define USB_SPEED_MASK BIT(5) + +#define USB_NORMAL_SIE_EP_MASK 0xF +#define USB_NORMAL_SIE_EP_SHIFT 4 + +//2 Special Option +#define USB_AGG_EN BIT(3) + +*/ +//============================================================================ +// 8192C Regsiter Bit and Content definition +//============================================================================ +//----------------------------------------------------- +// +// 0x0000h ~ 0x00FFh System Configuration +// +//----------------------------------------------------- +/* +//2 SYS_ISO_CTRL +#define ISO_MD2PP BIT(0) +#define ISO_UA2USB BIT(1) +#define ISO_UD2CORE BIT(2) +#define ISO_PA2PCIE BIT(3) +#define ISO_PD2CORE BIT(4) +#define ISO_IP2MAC BIT(5) +#define ISO_DIOP BIT(6) +#define ISO_DIOE BIT(7) +#define ISO_EB2CORE BIT(8) +#define ISO_DIOR BIT(9) +#define PWC_EV12V BIT(15) + + +//2 SYS_FUNC_EN +#define FEN_BBRSTB BIT(0) +#define FEN_BB_GLB_RSTn BIT(1) +#define FEN_USBA BIT(2) +#define FEN_UPLL BIT(3) +#define FEN_USBD BIT(4) +#define FEN_DIO_PCIE BIT(5) +#define FEN_PCIEA BIT(6) +#define FEN_PPLL BIT(7) +#define FEN_PCIED BIT(8) +#define FEN_DIOE BIT(9) +#define FEN_CPUEN BIT(10) +#define FEN_DCORE BIT(11) +#define FEN_ELDR BIT(12) +#define FEN_DIO_RF BIT(13) +#define FEN_HWPDN BIT(14) +#define FEN_MREGEN BIT(15) + +//2 APS_FSMCO +#define PFM_LDALL BIT(0) +#define PFM_ALDN BIT(1) +#define PFM_LDKP BIT(2) +#define PFM_WOWL BIT(3) +#define EnPDN BIT(4) +#define PDN_PL BIT(5) +#define APFM_ONMAC BIT(8) +#define APFM_OFF BIT(9) +#define APFM_RSM BIT(10) +#define AFSM_HSUS BIT(11) +#define AFSM_PCIE BIT(12) +#define APDM_MAC BIT(13) +#define APDM_HOST BIT(14) +#define APDM_HPDN BIT(15) +#define RDY_MACON BIT(16) +#define SUS_HOST BIT(17) +#define ROP_ALD BIT(20) +#define ROP_PWR BIT(21) +#define ROP_SPS BIT(22) +#define SOP_MRST BIT(25) +#define SOP_FUSE BIT(26) +#define SOP_ABG BIT(27) +#define SOP_AMB BIT(28) +#define SOP_RCK BIT(29) +#define SOP_A8M BIT(30) +#define XOP_BTCK BIT(31) + +//2 SYS_CLKR +#define ANAD16V_EN BIT(0) +#define ANA8M BIT(1) +#define MACSLP BIT(4) +#define LOADER_CLK_EN BIT(5) + + +//2 9346CR + +#define BOOT_FROM_EEPROM BIT(4) +#define EEPROM_EN BIT(5) + + +//2 RF_CTRL +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +//2 LDOV12D_CTRL +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) +#define _LDV12_VADJ(x) (((x) & 0xF) << 4) + + +//2 EFUSE_TEST (For RTL8723 partially) +#define EF_TRPT BIT(7) +#define EF_CELL_SEL (BIT(8)|BIT(9)) // 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 +#define LDOE25_EN BIT(31) +#define EFUSE_SEL(x) (((x) & 0x3) << 8) +#define EFUSE_SEL_MASK 0x300 +#define EFUSE_WIFI_SEL_0 0x0 +#define EFUSE_BT_SEL_0 0x1 +#define EFUSE_BT_SEL_1 0x2 +#define EFUSE_BT_SEL_2 0x3 + + +//2 8051FWDL +//2 MCUFWDL +#define MCUFWDL_EN BIT(0) +#define MCUFWDL_RDY BIT(1) +#define FWDL_ChkSum_rpt BIT(2) +#define MACINI_RDY BIT(3) +#define BBINI_RDY BIT(4) +#define RFINI_RDY BIT(5) +#define WINTINI_RDY BIT(6) +#define RAM_DL_SEL BIT(7) +#define ROM_DLEN BIT(19) +#define CPRST BIT(23) + + + +//2 REG_SYS_CFG +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define CHIP_VER (BIT(12)|BIT(13)|BIT(14)|BIT(15)) +#define BT_FUNC BIT(16) +#define VENDOR_ID BIT(19) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) // RTL ID +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +#define CHIP_VER_RTL_MASK 0xF000 //Bit 12 ~ 15 +#define CHIP_VER_RTL_SHIFT 12 + +*/ +//----------------------------------------------------- +// +// 0x0100h ~ 0x01FFh MACTOP General Configuration +// +//----------------------------------------------------- +/* + +//2 Function Enable Registers +//2 CR 0x0100-0x0103 + + +#define HCI_TXDMA_EN BIT(0) +#define HCI_RXDMA_EN BIT(1) +#define TXDMA_EN BIT(2) +#define RXDMA_EN BIT(3) +#define PROTOCOL_EN BIT(4) +#define SCHEDULE_EN BIT(5) +#define MACTXEN BIT(6) +#define MACRXEN BIT(7) +#define ENSWBCN BIT(8) +#define ENSEC BIT(9) +#define CALTMR_EN BIT(10) // 32k CAL TMR enable + +// Network type +#define _NETTYPE(x) (((x) & 0x3) << 16) +#define MASK_NETTYPE 0x30000 +#define NT_NO_LINK 0x0 +#define NT_LINK_AD_HOC 0x1 +#define NT_LINK_AP 0x2 +#define NT_AS_AP 0x3 + + +//2 PBP - Page Size Register 0x0104 +#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) +#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) +#define _PSRX_MASK 0xF +#define _PSTX_MASK 0xF0 +#define _PSRX(x) (x) +#define _PSTX(x) ((x) << 4) + +#define PBP_64 0x0 +#define PBP_128 0x1 +#define PBP_256 0x2 +#define PBP_512 0x3 +#define PBP_1024 0x4 + + +//2 TX/RXDMA 0x010C +#define RXDMA_ARBBW_EN BIT(0) +#define RXSHFT_EN BIT(1) +#define RXDMA_AGG_EN BIT(2) +#define QS_VO_QUEUE BIT(8) +#define QS_VI_QUEUE BIT(9) +#define QS_BE_QUEUE BIT(10) +#define QS_BK_QUEUE BIT(11) +#define QS_MANAGER_QUEUE BIT(12) +#define QS_HIGH_QUEUE BIT(13) + +#define HQSEL_VOQ BIT(0) +#define HQSEL_VIQ BIT(1) +#define HQSEL_BEQ BIT(2) +#define HQSEL_BKQ BIT(3) +#define HQSEL_MGTQ BIT(4) +#define HQSEL_HIQ BIT(5) + +// For normal driver, 0x10C +#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) +#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) +#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) +#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8 ) +#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6 ) +#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4 ) + +#define QUEUE_LOW 1 +#define QUEUE_NORMAL 2 +#define QUEUE_HIGH 3 + + +//2 REG_C2HEVT_CLEAR 0x01AF +#define C2H_EVT_HOST_CLOSE 0x00 // Set by driver and notify FW that the driver has read the C2H command message +#define C2H_EVT_FW_CLOSE 0xFF // Set by FW indicating that FW had set the C2H command message and it's not yet read by driver. + + + +//2 LLT_INIT 0x01E0 +#define _LLT_NO_ACTIVE 0x0 +#define _LLT_WRITE_ACCESS 0x1 +#define _LLT_READ_ACCESS 0x2 + +#define _LLT_INIT_DATA(x) ((x) & 0xFF) +#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) +#define _LLT_OP(x) (((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) + +*/ +//----------------------------------------------------- +// +// 0x0200h ~ 0x027Fh TXDMA Configuration +// +//----------------------------------------------------- +/* +//2 TDECTL 0x0208 +#define BLK_DESC_NUM_SHIFT 4 +#define BLK_DESC_NUM_MASK 0xF + + +//2 TXDMA_OFFSET_CHK 0x020C +#define DROP_DATA_EN BIT(9) +*/ +//----------------------------------------------------- +// +// 0x0280h ~ 0x028Bh RX DMA Configuration +// +//----------------------------------------------------- +/* +//2 REG_RXDMA_CONTROL, 0x0286h + +// Write only. When this bit is set, RXDMA will decrease RX PKT counter by one. Before +// this bit is polled, FW shall update RXFF_RD_PTR first. This register is write pulse and auto clear. +#define RXPKT_RELEASE_POLL BIT(0) +// Read only. When RXMA finishes on-going DMA operation, RXMDA will report idle state in +// this bit. FW can start releasing packets after RXDMA entering idle mode. +#define RXDMA_IDLE BIT(1) +// When this bit is set, RXDMA will enter this mode after on-going RXDMA packet to host +// completed, and stop DMA packet to host. RXDMA will then report Default: 0; +#define RW_RELEASE_EN BIT(2) +*/ +//----------------------------------------------------- +// +// 0x0400h ~ 0x047Fh Protocol Configuration +// +//----------------------------------------------------- +/* +//2 FWHW_TXQ_CTRL 0x0420 +#define EN_AMPDU_RTY_NEW BIT(7) + + +//2 REG_LIFECTRL_CTRL 0x0426 +#define HAL92C_EN_PKT_LIFE_TIME_BK BIT3 +#define HAL92C_EN_PKT_LIFE_TIME_BE BIT2 +#define HAL92C_EN_PKT_LIFE_TIME_VI BIT1 +#define HAL92C_EN_PKT_LIFE_TIME_VO BIT0 + +#define HAL92C_MSDU_LIFE_TIME_UNIT 128 // in us, said by Tim. + + +//2 SPEC SIFS 0x0428 +#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) +#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) + +//2 RL 0x042A +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define _LRL(x) ((x) & 0x3F) +#define _SRL(x) (((x) & 0x3F) << 8) +*/ + +//----------------------------------------------------- +// +// 0x0500h ~ 0x05FFh EDCA Configuration +// +//----------------------------------------------------- +/* +//2 EDCA setting 0x050C +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + + +//2 BCN_CTRL 0x0550 +#define EN_TXBCN_RPT BIT(2) +#define EN_BCN_FUNCTION BIT(3) + +//2 TxPause 0x0522 +#define STOP_BCNQ BIT(6) +*/ + + +//2 ACMHWCTRL 0x05C0 +#define AcmHw_HwEn_8812 BIT(0) +#define AcmHw_VoqEn_8812 BIT(1) +#define AcmHw_ViqEn_8812 BIT(2) +#define AcmHw_BeqEn_8812 BIT(3) +#define AcmHw_VoqStatus_8812 BIT(5) +#define AcmHw_ViqStatus_8812 BIT(6) +#define AcmHw_BeqStatus_8812 BIT(7) + + + +//----------------------------------------------------- +// +// 0x0600h ~ 0x07FFh WMAC Configuration +// +//----------------------------------------------------- +/* + +//2 TCR 0x0604 +#define DIS_GCLK BIT(1) +#define PAD_SEL BIT(2) +#define PWR_ST BIT(6) +#define PWRBIT_OW_EN BIT(7) +#define ACRC BIT(8) +#define CFENDFORM BIT(9) +#define ICV BIT(10) +*/ + +//---------------------------------------------------------------------------- +// 8195 (RCR) Receive Configuration Register (Offset 0x608, 32 bits) +//---------------------------------------------------------------------------- +/* +#define RCR_APPFCS BIT31 // WMAC append FCS after pauload +#define RCR_APP_MIC BIT30 // MACRX will retain the MIC at the bottom of the packet. +#define RCR_APP_ICV BIT29 // MACRX will retain the ICV at the bottom of the packet. +#define RCR_APP_PHYST_RXFF BIT28 // HY Status is appended before RX packet in RXFF +#define RCR_APP_BA_SSN BIT27 // SSN of previous TXBA is appended as after original RXDESC as the 4-th DW of RXDESC. +#define RCR_RSVD_BIT26 BIT26 // Reserved +*/ +#define RCR_TCPOFLD_EN BIT25 // Enable TCP checksum offload +/*#define RCR_ENMBID BIT24 // Enable Multiple BssId. Only response ACK to the packets whose DID(A1) matching to the addresses in the MBSSID CAM Entries. +#define RCR_LSIGEN BIT23 // Enable LSIG TXOP Protection function. Search KEYCAM for each rx packet to check if LSIGEN bit is set. +#define RCR_MFBEN BIT22 // Enable immediate MCS Feedback function. When Rx packet with MRQ = 1'b1, then search KEYCAM to find sender's MCS Feedback function and send response. +*/ +/*#define RCR_RSVD_BIT19 BIT19 // Reserved +#define RCR_TIM_PARSER_EN BIT18 // RX Beacon TIM Parser. +#define RCR_BM_DATA_EN BIT17 // Broadcast data packet interrupt enable. +#define RCR_UC_DATA_EN BIT16 // Unicast data packet interrupt enable. +*/ +/*#define RCR_HTC_LOC_CTRL BIT14 // MFC<--HTC=1 MFC-->HTC=0 +#define RCR_AMF BIT13 // Accept management type frame +#define RCR_ACF BIT12 // Accept control type frame. Control frames BA, BAR, and PS-Poll (when in AP mode) are not controlled by this bit. They are controlled by ADF. +#define RCR_ADF BIT11 // Accept data type frame. This bit also regulates BA, BAR, and PS-Poll (AP mode only). +*/ +/*#define RCR_AICV BIT9 // Accept ICV error packet +#define RCR_ACRC32 BIT8 // Accept CRC32 error packet +#define RCR_CBSSID_BCN BIT7 // Accept BSSID match packet (Rx beacon, probe rsp) +#define RCR_CBSSID_DATA BIT6 // Accept BSSID match packet (Data) +#define RCR_CBSSID RCR_CBSSID_DATA // Accept BSSID match packet +#define RCR_APWRMGT BIT5 // Accept power management packet +#define RCR_ADD3 BIT4 // Accept address 3 match packet +#define RCR_AB BIT3 // Accept broadcast packet +#define RCR_AM BIT2 // Accept multicast packet +#define RCR_APM BIT1 // Accept physical match packet +#define RCR_AAP BIT0 // Accept all unicast packet + +#define AAP BIT(0) +#define APM BIT(1) +#define AM BIT(2) +#define AB BIT(3) +#define ADD3 BIT(4) +#define APWRMGT BIT(5) +#define CBSSID BIT(6) +#define CBSSID_DATA BIT(6) +#define CBSSID_BCN BIT(7) +#define ACRC32 BIT(8) +#define AICV BIT(9) +#define ADF BIT(11) +#define ACF BIT(12) +#define AMF BIT(13) +#define HTC_LOC_CTRL BIT(14) +#define UC_DATA_EN BIT(16) +#define BM_DATA_EN BIT(17) +#define MFBEN BIT(22) +#define LSIGEN BIT(23) +#define EnMBID BIT(24) +#define APP_BASSN BIT(27) +#define APP_PHYSTS BIT(28) +#define APP_ICV BIT(29) +#define APP_MIC BIT(30) +*/ + +//---------------------------------------------------------------------------- +// 8195 CAM Config Setting (offset 0x680, 1 byte) +//---------------------------------------------------------------------------- +/* +#define SCR_TxUseDK BIT(0) //Force Tx Use Default Key +#define SCR_RxUseDK BIT(1) //Force Rx Use Default Key +#define SCR_TxEncEnable BIT(2) //Enable Tx Encryption +#define SCR_RxDecEnable BIT(3) //Enable Rx Decryption +#define SCR_SKByA2 BIT(4) //Search kEY BY A2 +#define SCR_NoSKMC BIT(5) //No Key Search Multicast +#define SCR_TXBCUSEDK BIT(6) // Force Tx Broadcast packets Use Default Key +#define SCR_RXBCUSEDK BIT(7) // Force Rx Broadcast packets Use Default Key + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 +#define CAM_SMS4 0x6 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_CONFIG_USEDK TRUE +#define CAM_CONFIG_NO_USEDK FALSE + + +#define SCR_UseDK 0x01 +#define SCR_TxSecEnable 0x02 +#define SCR_RxSecEnable 0x04 +*/ + + +//----------------------------------------------------- +// +// 0xFE00h ~ 0xFE55h RTL8723 SDIO Configuration +// +//----------------------------------------------------- +/* +//SDIO host local register space mapping. +#define SDIO_LOCAL_MSK 0x0FFF +#define WLAN_IOREG_MSK 0x7FFF +#define WLAN_FIFO_MSK 0x1FFF // Aggregation Length[12:0] + +#define SDIO_WITHOUT_REF_DEVICE_ID 0 // Without reference to the SDIO Device ID +#define SDIO_LOCAL_DEVICE_ID 0 // 0b[16], 000b[15:13] +#define WLAN_TX_HIQ_DEVICE_ID 4 // 0b[16], 100b[15:13] +#define WLAN_TX_MIQ_DEVICE_ID 5 // 0b[16], 101b[15:13] +#define WLAN_TX_LOQ_DEVICE_ID 6 // 0b[16], 110b[15:13] +#define WLAN_RX0FF_DEVICE_ID 7 // 0b[16], 111b[15:13] +#define WLAN_IOREG_DEVICE_ID 8 // 1b[16] + +//SDIO Tx Free Page Index +#define HI_QUEUE_IDX 0 +#define MID_QUEUE_IDX 1 +#define LOW_QUEUE_IDX 2 +#define PUBLIC_QUEUE_IDX 3 + +#define SDIO_REG_TX_CTRL 0x0000 // SDIO Tx Control +#define SDIO_REG_HIMR 0x0014 // SDIO Host Interrupt Mask +#define SDIO_REG_HISR 0x0018 // SDIO Host Interrupt Service Routine +#define SDIO_REG_HCPWM 0x0019 // HCI Current Power Mode +#define SDIO_REG_RX0_REQ_LEN 0x001C // RXDMA Request Length +#define SDIO_REG_FREE_TXPG 0x0020 // Free Tx Buffer Page +#define SDIO_REG_HCPWM1 0x0024 // HCI Current Power Mode 1 +#define SDIO_REG_HCPWM2 0x0026 // HCI Current Power Mode 2 +#define SDIO_REG_HTSFR_INFO 0x0030 // HTSF Informaion +#define SDIO_REG_HRPWM1 0x0080 // HCI Request Power Mode 1 +#define SDIO_REG_HRPWM2 0x0082 // HCI Request Power Mode 2 +#define SDIO_REG_HPS_CLKR 0x0084 // HCI Power Save Clock +#define SDIO_REG_HSUS_CTRL 0x0086 // SDIO HCI Suspend Control +#define SDIO_REG_HIMR_ON 0x0090 //SDIO Host Extension Interrupt Mask Always +#define SDIO_REG_HISR_ON 0x0091 //SDIO Host Extension Interrupt Status Always + +#define SDIO_HIMR_DISABLED 0 + +// RTL8723/RTL8188E SDIO Host Interrupt Mask Register +#define SDIO_HIMR_RX_REQUEST_MSK BIT0 +#define SDIO_HIMR_AVAL_MSK BIT1 +#define SDIO_HIMR_TXERR_MSK BIT2 +#define SDIO_HIMR_RXERR_MSK BIT3 +#define SDIO_HIMR_TXFOVW_MSK BIT4 +#define SDIO_HIMR_RXFOVW_MSK BIT5 +#define SDIO_HIMR_TXBCNOK_MSK BIT6 +#define SDIO_HIMR_TXBCNERR_MSK BIT7 +#define SDIO_HIMR_BCNERLY_INT_MSK BIT16 +#define SDIO_HIMR_C2HCMD_MSK BIT17 +#define SDIO_HIMR_CPWM1_MSK BIT18 +#define SDIO_HIMR_CPWM2_MSK BIT19 +#define SDIO_HIMR_HSISR_IND_MSK BIT20 +#define SDIO_HIMR_GTINT3_IND_MSK BIT21 +#define SDIO_HIMR_GTINT4_IND_MSK BIT22 +#define SDIO_HIMR_PSTIMEOUT_MSK BIT23 +#define SDIO_HIMR_OCPINT_MSK BIT24 +#define SDIO_HIMR_ATIMEND_MSK BIT25 +#define SDIO_HIMR_ATIMEND_E_MSK BIT26 +#define SDIO_HIMR_CTWEND_MSK BIT27 + +//RTL8188E SDIO Specific +#define SDIO_HIMR_MCU_ERR_MSK BIT28 +#define SDIO_HIMR_TSF_BIT32_TOGGLE_MSK BIT29 + +// SDIO Host Interrupt Service Routine +#define SDIO_HISR_RX_REQUEST BIT0 +#define SDIO_HISR_AVAL BIT1 +#define SDIO_HISR_TXERR BIT2 +#define SDIO_HISR_RXERR BIT3 +#define SDIO_HISR_TXFOVW BIT4 +#define SDIO_HISR_RXFOVW BIT5 +#define SDIO_HISR_TXBCNOK BIT6 +#define SDIO_HISR_TXBCNERR BIT7 +#define SDIO_HISR_BCNERLY_INT BIT16 +#define SDIO_HISR_C2HCMD BIT17 +#define SDIO_HISR_CPWM1 BIT18 +#define SDIO_HISR_CPWM2 BIT19 +#define SDIO_HISR_HSISR_IND BIT20 +#define SDIO_HISR_GTINT3_IND BIT21 +#define SDIO_HISR_GTINT4_IND BIT22 +#define SDIO_HISR_PSTIMEOUT BIT23 +#define SDIO_HISR_OCPINT BIT24 +#define SDIO_HISR_ATIMEND BIT25 +#define SDIO_HISR_ATIMEND_E BIT26 +#define SDIO_HISR_CTWEND BIT27 + +//RTL8188E SDIO Specific +#define SDIO_HISR_MCU_ERR BIT28 +#define SDIO_HISR_TSF_BIT32_TOGGLE BIT29 + + +// SDIO HCI Suspend Control Register +#define HCI_RESUME_PWR_RDY BIT1 +#define HCI_SUS_CTRL BIT0 + + +#if DEV_BUS_TYPE == RT_SDIO_INTERFACE + #define MAX_TX_AGG_PACKET_NUMBER 0x8 +#else + #define MAX_TX_AGG_PACKET_NUMBER 0xFF +#endif + +*/ +#if defined(EN_EFUSE) +#define PATHA_OFFSET 0x10 +#define PATHB_OFFSET 0x3A +#define PATHC_OFFSET 0x64 +#define PATHD_OFFSET 0x8E +/*2.4 GHz, PATH A, 1T*/ +#define EEPROM_2G_CCK1T_TxPower 0x0 // CCK Tx Power base +#define EEPROM_2G_HT401S_TxPower 0x6 // HT40 Tx Power base +#define EEPROM_2G_HT201S_TxPowerDiff 0xB // HT20 Tx Power Diff [7:4] +#define EEPROM_2G_OFDM1T_TxPowerDiff 0xB // OFDM Tx Power Diff [3:0] +/*2.4 GHz, PATH A, 2T*/ +#define EEPROM_2G_HT402S_TxPowerDiff 0xC // HT40 Tx Power Diff [7:4] +#define EEPROM_2G_HT202S_TxPowerDiff 0xC // HT20 Tx Power Diff [3:0] +#define EEPROM_2G_OFDM2T_TxPowerDiff 0xD // OFDM Tx Power Diff [7:4] +#define EEPROM_2G_CCK2T_TxPowerDiff 0xD // CCK Tx Power Diff [3:0] +/*2.4 GHz, PATH A, 3T*/ +#define EEPROM_2G_HT403S_TxPowerDiff 0xE // HT40 Tx Power Diff [7:4] +#define EEPROM_2G_HT203S_TxPowerDiff 0xE // HT40 Tx Power Diff [3:0] +#define EEPROM_2G_OFDM3T_TxPowerDiff 0xF // OFDM Tx Power Diff [7:4] +#define EEPROM_2G_CCK3T_TxPowerDiff 0xF // CCK Tx Power Diff [3:0] +/*2.4 GHz, PATH A, 4T*/ +#define EEPROM_2G_HT404S_TxPowerDiff 0x10 // HT40 Tx Power Diff [7:4] +#define EEPROM_2G_HT204S_TxPowerDiff 0x10 // HT20 Tx Power Diff [0:3] +#define EEPROM_2G_OFDM4T_TxPowerDiff 0x11 // OFDM Tx Power Diff [7:4] +#define EEPROM_2G_CCK4T_TxPowerDiff 0x11 // CCK Tx Power Diff [3:0] +/*5 GHz, PATH A, 1T*/ +#define EEPROM_5G_HT401S_TxPower 0x12 // HT40 Tx Power Base +#define EEPROM_5G_HT201S_TxPowerDiff 0x20 // HT20 Tx Power Diff [7:4] +#define EEPROM_5G_OFDM1T_TxPowerDiff 0x20 // OFDM Tx Power Diff [3:0] +#define EEPROM_5G_HT801S_TxPowerDiff 0x26 // HT80 Tx Power Diff [7:4] +#define EEPROM_5G_HT1601S_TxPowerDiff 0x26 // HT160 Tx Power Diff [3:0] +/*5 GHz, PATH A, 2T*/ +#define EEPROM_5G_HT402S_TxPowerDiff 0x21 // HT40 Tx Power Diff [7:4] +#define EEPROM_5G_HT202S_TxPowerDiff 0x21 // HT20 Tx Power Diff [3:0] +#define EEPROM_5G_OFDM2T_TxPowerDiff 0x24 // OFDM Tx Power Diff [7:4] +#define EEPROM_5G_HT802S_TxPowerDiff 0x27 // HT80 Tx Power Diff [7:4] +/*5 GHz, PATH A, 3T*/ +#define EEPROM_5G_OFDM3T_TxPowerDiff 0x24 // OFDM Tx Power Diff [3:0] +#define EEPROM_5G_HT403S_TxPowerDiff 0x22 // HT40 Tx Power Diff [7:4] +#define EEPROM_5G_HT203S_TxPowerDiff 0x22 // HT20 Tx Power Diff [3:0] +#define EEPROM_5G_HT803S_TxPowerDiff 0x28 // HT80 Tx Power Diff [7:4] +#define EEPROM_5G_HT1603S_TxPowerDiff 0x28 // HT160 Tx Power Diff [3:0] +/*5 GHz, PATH A, 4T*/ +#define EEPROM_5G_HT404S_TxPowerDiff 0x23 // HT40 Tx Power Diff [7:4] +#define EEPROM_5G_HT204S_TxPowerDiff 0x23 // HT20 Tx Power Diff [3:0] +#define EEPROM_5G_OFDM4T_TxPowerDiff 0x25 // OFDM Tx Power Diff [3:0] +#define EEPROM_5G_HT804S_TxPowerDiff 0x29 // HT80 Tx Power Diff [7:4] +#define EEPROM_5G_HT1604S_TxPowerDiff 0x29 // HT160 Tx Power Diff [3:0] + +#define EEPROM_8812_CHANNEL_PLAN 0xB8 +#define EEPROM_8812_XTAL_K 0xB9 //[5:0] +#define EEPROM_8812_THERMAL_METER 0xBA +#define EEPROM_8812_LCK_DELTA 0xBB //[3:2] +#define EEPROM_8812_IQK_DELTA 0xBB //[1:0] + +#define EEPROM_8812_VERSION 0xC4 +#define EEPROM_8812_CUSTOMER_ID 0xC5 +#define EEPROM_2G_TxBBSwing 0xC6 +#define EEPROM_5G_TxBBSwing 0xC7 + +#define EEPROM_8812_MACADDRESS 0xD0 // MAC Address +#endif + +#endif //#ifndef WLAN_HAL_INTERNAL_USED + +#endif // #ifndef __INC_HAL8195REG_H + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_vht_gen.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_vht_gen.c new file mode 100755 index 000000000..7af08778b --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_vht_gen.c @@ -0,0 +1,617 @@ + + +#include "8192cd.h" +#include "8192cd_cfg.h" +#include "8192cd_util.h" +#include "8192cd_headers.h" + +#include "8812_vht_gen.h" + +#ifdef RTK_AC_SUPPORT + +void input_value_32(unsigned long *p, unsigned char start, unsigned char end, unsigned int value) +{ + unsigned int bit_mask = 0; + + if(value > 0) //only none-zero value needs to be assigned + { + if(start == end) //1-bit value + { + *p |= BIT(start); + } + else + { + unsigned char x = 0; + + for(x = 0; x<=(end-start); x ++) + bit_mask |= BIT(x); + + *p |= ((value&bit_mask) << start); + } + } + +} + +// 20/40/80, ShortGI, MCS Rate +const u2Byte VHT_MCS_DATA_RATE[3][2][30] = + { { {13, 26, 39, 52, 78, 104, 117, 130, 156, 156, + 26, 52, 78, 104, 156, 208, 234, 260, 312, 312, + 39, 78, 117, 156, 234, 312, 351, 390, 468, 520}, // Long GI, 20MHz + + {14, 29, 43, 58, 87, 116, 130, 144, 173, 173, + 29, 58, 87, 116, 173, 231, 260, 289, 347, 347, + 43, 86, 130, 173, 260, 347, 390, 433, 520, 578} }, // Short GI, 20MHz + + { {27, 54, 81, 108, 162, 216, 243, 270, 324, 360, + 54, 108, 162, 216, 324, 432, 486, 540, 648, 720, + 81, 162, 243, 342, 486, 648, 729, 810, 972, 1080}, // Long GI, 40MHz + + {30, 60, 90, 120, 180, 240, 270, 300,360, 400, + 60, 120, 180, 240, 360, 480, 540, 600, 720, 800, + 90, 180, 270, 360, 540, 720, 810, 900, 1080, 1200} }, // Short GI, 40MHz + + { {59, 117, 176, 234, 351, 468, 527, 585, 702, 780, + 117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560, + 176, 351, 527, 702, 1053, 1408, 1408, 1745, 2106, 2340}, // Long GI, 80MHz + + {65, 130, 195, 260, 390, 520, 585, 650, 780, 867, + 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1733, + 195, 390, 585, 780, 1170, 1560, 1560, 1950, 2340, 2600} } // Short GI, 80MHz + + }; + +enum _VHT_SUPPORT_RATE_MAP_ { + SUPPORT_MCS_0_7_RATES = 0, + SUPPORT_MCS_0_8_RATES = 1, + SUPPORT_MCS_0_9_RATES = 2, + NOT_SUPPORT_VHT_RATES = 3 +}; + +/* +* Description: +* This function will get the highest speed rate in input MCS set. +* +* /param Adapter Pionter to Adapter entity +* pMCSRateSet Pointer to MCS rate bitmap +* pMCSFilter Pointer to MCS rate filter +* +* /return Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter. +* +*/ +u1Byte +VHTGetHighestMCSRate( + struct rtl8192cd_priv *priv, + IN pu1Byte pVHTMCSRateSet + ) +{ + u1Byte i, j; + u1Byte bitMap; + u1Byte VHTMcsRate = 0; + + for(i = 0; i < 2; i++) + { + if(pVHTMCSRateSet[i] != 0xff) + { + for(j = 0; j < 8; j += 2) + { + bitMap = (pVHTMCSRateSet[i] >> j) & 3; + + if(bitMap != 3) + VHTMcsRate = _NSS1_MCS7_RATE_ + 5*j + i*40 + bitMap; //VHT rate indications begin from 0x90 + } + } + } + + return VHTMcsRate; +} + +u2Byte +VHTMcsToDataRate( + struct rtl8192cd_priv *priv + ) +{ + BOOLEAN isShortGI = FALSE; + u2Byte VHTMcsRate; + +#if 1 + + if(priv->pshare->rf_ft_var.lgirate == 0) + return 0; + + isShortGI = 0; + if((priv->pmib->dot11acConfigEntry.dot11SupportedVHT & 0x30) != 0x30) + VHTMcsRate = _NSS3_MCS7_RATE_ +((priv->pmib->dot11acConfigEntry.dot11SupportedVHT>>4) &3); + else if((priv->pmib->dot11acConfigEntry.dot11SupportedVHT & 0x000c) != 0x0c) + VHTMcsRate = _NSS2_MCS7_RATE_ +((priv->pmib->dot11acConfigEntry.dot11SupportedVHT>>2) &3); + else + VHTMcsRate = _NSS1_MCS7_RATE_ +((priv->pmib->dot11acConfigEntry.dot11SupportedVHT) &3); ; +#else + + + switch(priv->pshare->CurrentChannelBW){ + case HT_CHANNEL_WIDTH_20: + isShortGI = priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M?1:0; + break; + case HT_CHANNEL_WIDTH_20_40: + isShortGI = priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M?1:0; + break; + case HT_CHANNEL_WIDTH_80: + isShortGI = priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M?1:0; // ?? + break; + } +#endif + VHTMcsRate -=_NSS1_MCS0_RATE_; + + if( ((VHTMcsRate>20)&&get_rf_mimo_mode(priv)==MIMO_2T2R)|| (priv->pshare->is_40m_bw > 2)) + return 600; + else + return VHT_MCS_DATA_RATE[priv->pshare->is_40m_bw][isShortGI][(VHTMcsRate&0x3f)]; +} + +unsigned int filter_mcs_9(unsigned int supported_vht, int num_ss) +{ + int tmp = 0; + + //panic_printk(" +++ supported_vht = 0x%x \n", supported_vht); + + for(tmp = 1; tmp <= num_ss; tmp++) + { + int bit_shift = ((tmp-1)*2); + + if(tmp > 8) + break; + + if((tmp==3) || (tmp==6)) //3SS & 6SS support 20M + MCS9 + continue; + + if(( supported_vht & (3 << bit_shift)) == (SUPPORT_MCS_0_9_RATES << bit_shift)) + { + supported_vht &= ~(3 << bit_shift); + supported_vht |= (SUPPORT_MCS_0_8_RATES << bit_shift); + } + + } + + //panic_printk(" --- supported_vht = 0x%x \n", supported_vht); + + return supported_vht; + +} + +#ifdef MCR_WIRELESS_EXTEND +void construct_vht_ie_mcr(struct rtl8192cd_priv *priv, unsigned char channel_center, struct stat_info *pstat) +{ + struct vht_cap_elmt *vht_cap; + struct vht_oper_elmt *vht_oper; + unsigned int value; + + unsigned char txbf_max_ant, txbf_sounding_dim; + + unsigned int supported_vht = priv->pmib->dot11acConfigEntry.dot11SupportedVHT; + + +//// ===== VHT CAPABILITIES ELEMENT ===== ///// +//VHT CAPABILITIES INFO field + + priv->vht_cap_len = sizeof(struct vht_cap_elmt); + vht_cap = &priv->vht_cap_buf; + memset(vht_cap, 0, sizeof(struct vht_cap_elmt)); + + switch(get_rf_mimo_mode(priv)) { + case MIMO_1T1R: + supported_vht |= 0xfffe; + break; + case MIMO_3T3R: + case MIMO_4T4R: + supported_vht |= 0xffea; + break; + default: //2T2R + supported_vht |= 0xfffa; + break; + } + + // TODO: MAX_MPDU_LENGTH_E in 11AC + if(priv->pmib->dot11nConfigEntry.dot11nAMSDURecvMax) + input_value_32(&vht_cap->vht_cap_info, MAX_MPDU_LENGTH_S, MAX_MPDU_LENGTH_E, (priv->pmib->dot11nConfigEntry.dot11nAMSDURecvMax & 0x3)); + else + input_value_32(&vht_cap->vht_cap_info, MAX_MPDU_LENGTH_S, MAX_MPDU_LENGTH_E, 0); + + //0 - not support 160/80+80; 1 - support 160; 2 - support 80+80 + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_160) + value = 1; + else + value = 0; + input_value_32(&vht_cap->vht_cap_info, CHL_WIDTH_S, CHL_WIDTH_E, value); + + if((GET_CHIP_VER(priv) == VERSION_8814A) && (priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_AC_80)) + input_value_32(&vht_cap->vht_cap_info, SHORT_GI80M_S, SHORT_GI80M_E, (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M ? 1 : 0)); + + input_value_32(&vht_cap->vht_cap_info, SHORT_GI160M_S, SHORT_GI160M_E, 0); + + + if( (priv->pmib->dot11nConfigEntry.dot11nLDPC&1) +#if defined(CONFIG_WLAN_HAL_8881A) + && (GET_CHIP_VER(priv) != VERSION_8881A) +#endif + ) + input_value_32(&vht_cap->vht_cap_info, RX_LDPC_S, RX_LDPC_E, 1); + else + input_value_32(&vht_cap->vht_cap_info, RX_LDPC_S, RX_LDPC_E, 0); + +#if 1 + if (priv->pmib->dot11nConfigEntry.dot11nSTBC) + { + if ((get_rf_mimo_mode(priv) == MIMO_2T2R) || (get_rf_mimo_mode(priv) == MIMO_3T3R)) //eric_8814 + input_value_32(&vht_cap->vht_cap_info, TX_STBC_S, TX_STBC_E, 1); + + input_value_32(&vht_cap->vht_cap_info, RX_STBC_S, RX_STBC_E, 1); + } + else +#endif + { + input_value_32(&vht_cap->vht_cap_info, TX_STBC_S, TX_STBC_E, 0); + input_value_32(&vht_cap->vht_cap_info, RX_STBC_S, RX_STBC_E, 0); + } + +#ifdef BEAMFORMING_SUPPORT + if (priv->pmib->dot11RFEntry.txbf == 1) { + if(priv->pmib->dot11RFEntry.txbfer == 1) + input_value_32(&vht_cap->vht_cap_info, SU_BFER_S, SU_BFER_E, 1); + if(priv->pmib->dot11RFEntry.txbfee == 1) + input_value_32(&vht_cap->vht_cap_info, SU_BFEE_S, SU_BFEE_E, 1); + } else +#endif + { + input_value_32(&vht_cap->vht_cap_info, SU_BFER_S, SU_BFER_E, 0); + input_value_32(&vht_cap->vht_cap_info, SU_BFEE_S, SU_BFEE_E, 0); + } +#ifdef CONFIG_WLAN_HAL_8814AE + if(priv->pshare->rf_ft_var.bf_sup_val != 0){ + input_value_32(&vht_cap->vht_cap_info, MAX_ANT_SUPP_S, MAX_ANT_SUPP_E, priv->pshare->rf_ft_var.bf_sup_val); + input_value_32(&vht_cap->vht_cap_info, SOUNDING_DIMENSIONS_S, SOUNDING_DIMENSIONS_E, priv->pshare->rf_ft_var.bf_sup_val); + }else +#endif + { +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv)==VERSION_8814A) { + if(get_rf_mimo_mode(priv) == MIMO_4T4R) { + txbf_max_ant = 3; + txbf_sounding_dim = 3; + } else if(get_rf_mimo_mode(priv) == MIMO_3T3R) { + txbf_max_ant = 2; + txbf_sounding_dim = 3; + } else if(get_rf_mimo_mode(priv) == MIMO_2T4R) { + txbf_max_ant = 2; + txbf_sounding_dim = 1; + } else if(get_rf_mimo_mode(priv) == MIMO_2T2R) { + txbf_max_ant = 2; + txbf_sounding_dim = 1; + } else { + txbf_max_ant = 1; + txbf_sounding_dim = 1; + } + input_value_32(&vht_cap->vht_cap_info, MAX_ANT_SUPP_S, MAX_ANT_SUPP_E, txbf_max_ant); + input_value_32(&vht_cap->vht_cap_info, SOUNDING_DIMENSIONS_S, SOUNDING_DIMENSIONS_E, txbf_sounding_dim); + } + else +#endif + { + input_value_32(&vht_cap->vht_cap_info, MAX_ANT_SUPP_S, MAX_ANT_SUPP_E, BEAMFORM_MAX_ANT_SUPP); + input_value_32(&vht_cap->vht_cap_info, SOUNDING_DIMENSIONS_S, SOUNDING_DIMENSIONS_E, BEAMFORM_SOUNDING_DIMENSIONS); + } + } + + + input_value_32(&vht_cap->vht_cap_info, MU_BFER_S, MU_BFER_E, 0); + input_value_32(&vht_cap->vht_cap_info, MU_BFEE_S, MU_BFEE_E, 0); + + input_value_32(&vht_cap->vht_cap_info, TXOP_PS_S, TXOP_PS_E, 0); + + input_value_32(&vht_cap->vht_cap_info, HTC_VHT_S, HTC_VHT_E, 1); +#ifdef MCR_WIRELESS_EXTEND + input_value_32(&vht_cap->vht_cap_info, MAX_RXAMPDU_FACTOR_S, MAX_RXAMPDU_FACTOR_E, priv->pshare->rf_ft_var.ampdu_den_vht); +#else + input_value_32(&vht_cap->vht_cap_info, MAX_RXAMPDU_FACTOR_S, MAX_RXAMPDU_FACTOR_E, 7); +#endif + input_value_32(&vht_cap->vht_cap_info, LINK_ADAPTION_S, LINK_ADAPTION_E, 0); + + input_value_32(&vht_cap->vht_cap_info, RX_ANT_PC_S, RX_ANT_PC_E, 0); + input_value_32(&vht_cap->vht_cap_info, TX_ANT_PC_S, TX_ANT_PC_E, 0); + + //printk("vht_cap->vht_cap_info 0x%08X ", vht_cap->vht_cap_info); + vht_cap->vht_cap_info = cpu_to_le32(vht_cap->vht_cap_info); + //printk("0x%08X\n", vht_cap->vht_cap_info); + +#if defined(AC2G_256QAM) || defined(WLAN_HAL_8814AE) + if(is_ac2g(priv) && ((priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_20)||(GET_CHIP_VER(priv)==VERSION_8814A))) //if bw = 20M, not support MCS9 + { + if(get_rf_mimo_mode(priv) == MIMO_1T1R) + { + supported_vht = 0xfffd; + } + else if(get_rf_mimo_mode(priv) == MIMO_2T2R) + { + supported_vht = 0xfff5; + } + else if(get_rf_mimo_mode(priv) == MIMO_3T3R || get_rf_mimo_mode(priv) == MIMO_4T4R) + { + supported_vht = 0xffd5; + } + else + supported_vht = 0xfff5; //2ss as default + } +#endif + + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_20) + { + // 1SS & 2SS do NOT support MCS9 in BW 20m + if(get_rf_mimo_mode(priv) == MIMO_1T1R) + supported_vht = filter_mcs_9(supported_vht, 1); + else if(get_rf_mimo_mode(priv) == MIMO_2T2R) + supported_vht = filter_mcs_9(supported_vht, 2); + } + + if (GET_CHIP_VER(priv)==VERSION_8814A && get_rf_mimo_mode(priv) == MIMO_2T2R) { + if (pstat->IOTPeer == HT_IOT_PEER_REALTEK_8812) { + supported_vht = 0xfff5; + } + } + + { + input_value_32(&vht_cap->vht_support_mcs[0], MCS_RX_MAP_S, MCS_RX_MAP_E, supported_vht); + value = (VHTMcsToDataRate(priv)+1)>>1; + input_value_32(&vht_cap->vht_support_mcs[0], MCS_RX_HIGHEST_RATE_S, MCS_RX_HIGHEST_RATE_E, value); + vht_cap->vht_support_mcs[0] = cpu_to_le32(vht_cap->vht_support_mcs[0]); + + input_value_32(&vht_cap->vht_support_mcs[1], MCS_TX_MAP_S, MCS_TX_MAP_E, supported_vht); + value = (VHTMcsToDataRate(priv)+1)>>1; + input_value_32(&vht_cap->vht_support_mcs[1], MCS_TX_HIGHEST_RATE_S, MCS_TX_HIGHEST_RATE_E, value); + vht_cap->vht_support_mcs[1] = cpu_to_le32(vht_cap->vht_support_mcs[1]); + } + +//// ===== VHT CAPABILITIES ELEMENT ===== ///// + priv->vht_oper_len = sizeof(struct vht_oper_elmt); + vht_oper = &priv->vht_oper_buf; + memset(vht_oper, 0, sizeof(struct vht_oper_elmt)); + + if((priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_AC_80) || (GET_CHIP_VER(priv)==VERSION_8814A)) + { + vht_oper->vht_oper_info[0] = (priv->pshare->is_40m_bw ==2) ? 1 : 0; + + if(OPMODE & (WIFI_STATION_STATE)) + vht_oper->vht_oper_info[0] = 1; //8812_client + + if(priv->pshare->is_40m_bw ==2) { + int channel = priv->pmib->dot11RFEntry.dot11channel; + if (channel <= 48) + channel_center = 42; + else if (channel <= 64) + channel_center = 58; + else if (channel <= 112) + channel_center = 106; + else if (channel <= 128) + channel_center = 122; + else if (channel <= 144) + channel_center = 138; + else if (channel <= 161) + channel_center = 155; + else if (channel <= 177) + channel_center = 171; + } + + vht_oper->vht_oper_info[1] = channel_center; + vht_oper->vht_oper_info[2] = 0; + } + + if(get_rf_mimo_mode(priv) == MIMO_1T1R) + value = 0xfffc; + else if(get_rf_mimo_mode(priv) == MIMO_2T2R) + value = 0xfff0; + else if(get_rf_mimo_mode(priv) == MIMO_3T3R || get_rf_mimo_mode(priv) == MIMO_4T4R) + value = 0xffea; + else + value = 0xfff0; //2ss as default + + vht_oper->vht_basic_msc = value; + vht_oper->vht_basic_msc = cpu_to_le16(vht_oper->vht_basic_msc); + + +} + +#endif + + +void construct_vht_ie(struct rtl8192cd_priv *priv, unsigned char channel_center) +{ + struct vht_cap_elmt *vht_cap; + struct vht_oper_elmt *vht_oper; + unsigned int value; + + unsigned int supported_vht = priv->pmib->dot11acConfigEntry.dot11SupportedVHT; + + +//// ===== VHT CAPABILITIES ELEMENT ===== ///// +//VHT CAPABILITIES INFO field + + priv->vht_cap_len = sizeof(struct vht_cap_elmt); + vht_cap = &priv->vht_cap_buf; + memset(vht_cap, 0, sizeof(struct vht_cap_elmt)); + + switch(get_rf_mimo_mode(priv)) { + case MIMO_1T1R: + supported_vht |= 0xfffe; + break; + case MIMO_3T3R: + case MIMO_4T4R: + supported_vht |= 0xffea; + break; + default: //2T2R + supported_vht |= 0xfffa; + break; + } + + // TODO: MAX_MPDU_LENGTH_E in 11AC + if(priv->pmib->dot11nConfigEntry.dot11nAMSDURecvMax) + input_value_32(&vht_cap->vht_cap_info, MAX_MPDU_LENGTH_S, MAX_MPDU_LENGTH_E, (priv->pmib->dot11nConfigEntry.dot11nAMSDURecvMax & 0x3)); + else + input_value_32(&vht_cap->vht_cap_info, MAX_MPDU_LENGTH_S, MAX_MPDU_LENGTH_E, 0); + + //0 - not support 160/80+80; 1 - support 160; 2 - support 80+80 + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_160) + value = 1; + else + value = 0; + input_value_32(&vht_cap->vht_cap_info, CHL_WIDTH_S, CHL_WIDTH_E, value); + + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_80) + input_value_32(&vht_cap->vht_cap_info, SHORT_GI80M_S, SHORT_GI80M_E, (priv->pmib->dot11nConfigEntry.dot11nShortGIfor80M ? 1 : 0)); + + input_value_32(&vht_cap->vht_cap_info, SHORT_GI160M_S, SHORT_GI160M_E, 0); + + + if( (priv->pmib->dot11nConfigEntry.dot11nLDPC&1) && (can_enable_rx_ldpc(priv)) ) + input_value_32(&vht_cap->vht_cap_info, RX_LDPC_S, RX_LDPC_E, 1); + else + input_value_32(&vht_cap->vht_cap_info, RX_LDPC_S, RX_LDPC_E, 0); + +#if 1 + if (priv->pmib->dot11nConfigEntry.dot11nSTBC) + { + if ((get_rf_mimo_mode(priv) == MIMO_2T2R) || (get_rf_mimo_mode(priv) == MIMO_3T3R)) //eric_8814 + input_value_32(&vht_cap->vht_cap_info, TX_STBC_S, TX_STBC_E, 1); + + input_value_32(&vht_cap->vht_cap_info, RX_STBC_S, RX_STBC_E, 1); + } + else +#endif + { + input_value_32(&vht_cap->vht_cap_info, TX_STBC_S, TX_STBC_E, 0); + input_value_32(&vht_cap->vht_cap_info, RX_STBC_S, RX_STBC_E, 0); + } + +#ifdef BEAMFORMING_SUPPORT + if (priv->pmib->dot11RFEntry.txbf == 1) { + if(priv->pmib->dot11RFEntry.txbfer == 1) + input_value_32(&vht_cap->vht_cap_info, SU_BFER_S, SU_BFER_E, 1); + if(priv->pmib->dot11RFEntry.txbfee == 1) + input_value_32(&vht_cap->vht_cap_info, SU_BFEE_S, SU_BFEE_E, 1); + } else +#endif + { + input_value_32(&vht_cap->vht_cap_info, SU_BFER_S, SU_BFER_E, 0); + input_value_32(&vht_cap->vht_cap_info, SU_BFEE_S, SU_BFEE_E, 0); + } + + input_value_32(&vht_cap->vht_cap_info, MAX_ANT_SUPP_S, MAX_ANT_SUPP_E, BEAMFORM_SUPPORT_VALUE); + input_value_32(&vht_cap->vht_cap_info, SOUNDING_DIMENSIONS_S, SOUNDING_DIMENSIONS_E, BEAMFORM_SUPPORT_VALUE); + + input_value_32(&vht_cap->vht_cap_info, MU_BFER_S, MU_BFER_E, 0); + input_value_32(&vht_cap->vht_cap_info, MU_BFEE_S, MU_BFEE_E, 0); + + input_value_32(&vht_cap->vht_cap_info, TXOP_PS_S, TXOP_PS_E, 0); + + input_value_32(&vht_cap->vht_cap_info, HTC_VHT_S, HTC_VHT_E, 1); + + input_value_32(&vht_cap->vht_cap_info, MAX_RXAMPDU_FACTOR_S, MAX_RXAMPDU_FACTOR_E, 7); + + input_value_32(&vht_cap->vht_cap_info, LINK_ADAPTION_S, LINK_ADAPTION_E, 0); + + input_value_32(&vht_cap->vht_cap_info, RX_ANT_PC_S, RX_ANT_PC_E, 0); + input_value_32(&vht_cap->vht_cap_info, TX_ANT_PC_S, TX_ANT_PC_E, 0); + + //printk("vht_cap->vht_cap_info 0x%08X ", vht_cap->vht_cap_info); + vht_cap->vht_cap_info = cpu_to_le32(vht_cap->vht_cap_info); + //printk("0x%08X\n", vht_cap->vht_cap_info); + +#if defined(AC2G_256QAM) || defined(WLAN_HAL_8814AE) + if(is_ac2g(priv) && ((priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_20)||(GET_CHIP_VER(priv)==VERSION_8814A))) //if bw = 20M, not support MCS9 + { + if(get_rf_mimo_mode(priv) == MIMO_1T1R) + { + supported_vht = 0xfffd; + } + else if(get_rf_mimo_mode(priv) == MIMO_2T2R) + { + supported_vht = 0xfff5; + } + else if(get_rf_mimo_mode(priv) == MIMO_3T3R || get_rf_mimo_mode(priv) == MIMO_4T4R) + { + supported_vht = 0xffd5; + } + else + supported_vht = 0xfff5; //2ss as default + } +#endif + + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_AC_20) + { + // 1SS & 2SS do NOT support MCS9 in BW 20m + if(get_rf_mimo_mode(priv) == MIMO_1T1R) + supported_vht = filter_mcs_9(supported_vht, 1); + else if(get_rf_mimo_mode(priv) == MIMO_2T2R) + supported_vht = filter_mcs_9(supported_vht, 2); + } + + { + input_value_32(&vht_cap->vht_support_mcs[0], MCS_RX_MAP_S, MCS_RX_MAP_E, supported_vht); + value = (VHTMcsToDataRate(priv)+1)>>1; + input_value_32(&vht_cap->vht_support_mcs[0], MCS_RX_HIGHEST_RATE_S, MCS_RX_HIGHEST_RATE_E, value); + vht_cap->vht_support_mcs[0] = cpu_to_le32(vht_cap->vht_support_mcs[0]); + + input_value_32(&vht_cap->vht_support_mcs[1], MCS_TX_MAP_S, MCS_TX_MAP_E, supported_vht); + value = (VHTMcsToDataRate(priv)+1)>>1; + input_value_32(&vht_cap->vht_support_mcs[1], MCS_TX_HIGHEST_RATE_S, MCS_TX_HIGHEST_RATE_E, value); + vht_cap->vht_support_mcs[1] = cpu_to_le32(vht_cap->vht_support_mcs[1]); + } + +//// ===== VHT CAPABILITIES ELEMENT ===== ///// + priv->vht_oper_len = sizeof(struct vht_oper_elmt); + vht_oper = &priv->vht_oper_buf; + memset(vht_oper, 0, sizeof(struct vht_oper_elmt)); + + if((priv->pshare->is_40m_bw == HT_CHANNEL_WIDTH_AC_80) || (GET_CHIP_VER(priv)==VERSION_8814A)) + { + vht_oper->vht_oper_info[0] = (priv->pshare->is_40m_bw ==2) ? 1 : 0; + + if(OPMODE & (WIFI_STATION_STATE)) + vht_oper->vht_oper_info[0] = 1; //8812_client + + if(priv->pshare->is_40m_bw ==2) { + int channel = priv->pmib->dot11RFEntry.dot11channel; + if (channel <= 48) + channel_center = 42; + else if (channel <= 64) + channel_center = 58; + else if (channel <= 112) + channel_center = 106; + else if (channel <= 128) + channel_center = 122; + else if (channel <= 144) + channel_center = 138; + else if (channel <= 161) + channel_center = 155; + else if (channel <= 177) + channel_center = 171; + } + + vht_oper->vht_oper_info[1] = channel_center; + vht_oper->vht_oper_info[2] = 0; + } + + if(get_rf_mimo_mode(priv) == MIMO_1T1R) + value = 0xfffc; + else if(get_rf_mimo_mode(priv) == MIMO_2T2R) + value = 0xfff0; + else if(get_rf_mimo_mode(priv) == MIMO_3T3R || get_rf_mimo_mode(priv) == MIMO_4T4R) + value = 0xffea; + else + value = 0xfff0; //2ss as default + + vht_oper->vht_basic_msc = value; + vht_oper->vht_basic_msc = cpu_to_le16(vht_oper->vht_basic_msc); + + +} + +#endif //CONFIG_RTL_8812_SUPPORT + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_vht_gen.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_vht_gen.h new file mode 100755 index 000000000..30365153e --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/8812_vht_gen.h @@ -0,0 +1,105 @@ +/***************************************************************************** + * Copyright(c) 2009, RealTEK Technology Inc. All Right Reserved. + * + * Module: __INC_HAL8812REG_H + * + * + * Note: 1. Define Mac register address and corresponding bit mask map + * + * + * Export: Constants, macro, functions(API), global variables(None). + * + * Abbrev: + * + * History: + * Data Who Remark + * + *****************************************************************************/ + +#ifdef RTK_AC_SUPPORT + +#ifdef CONFIG_WLAN_HAL_8814AE +#define BEAMFORM_SUPPORT_VALUE 3 +#else +#define BEAMFORM_SUPPORT_VALUE 1 +#endif + + +//=== VHT capability info field === + +#define MAX_MPDU_LENGTH_S 0 +#define MAX_MPDU_LENGTH_E 1 + +#define CHL_WIDTH_S 2 +#define CHL_WIDTH_E 3 + +#define RX_LDPC_S 4 +#define RX_LDPC_E 4 + +#define SHORT_GI80M_S 5 +#define SHORT_GI80M_E 5 + +#define SHORT_GI160M_S 6 +#define SHORT_GI160M_E 6 + +#define TX_STBC_S 7 +#define TX_STBC_E 7 + +#define RX_STBC_S 8 +#define RX_STBC_E 10 + +#define SU_BFER_S 11 +#define SU_BFER_E 11 + +#define SU_BFEE_S 12 +#define SU_BFEE_E 12 + +#define MAX_ANT_SUPP_S 13 +#define MAX_ANT_SUPP_E 15 + +#define SOUNDING_DIMENSIONS_S 16 +#define SOUNDING_DIMENSIONS_E 18 + +#define MU_BFER_S 19 +#define MU_BFER_E 19 + +#define MU_BFEE_S 20 +#define MU_BFEE_E 20 + +#define TXOP_PS_S 21 +#define TXOP_PS_E 21 + +#define HTC_VHT_S 22 +#define HTC_VHT_E 22 + +#define MAX_RXAMPDU_FACTOR_S 23 +#define MAX_RXAMPDU_FACTOR_E 25 + +#define LINK_ADAPTION_S 26 +#define LINK_ADAPTION_E 27 + +#define RX_ANT_PC_S 28 +#define RX_ANT_PC_E 28 + +#define TX_ANT_PC_S 29 +#define TX_ANT_PC_E 29 + +//30 - 31 Reserved + + +//=== VHT supported mcs set field === + +#define MCS_RX_MAP_S 0 +#define MCS_RX_MAP_E 15 + +#define MCS_RX_HIGHEST_RATE_S 16 +#define MCS_RX_HIGHEST_RATE_E 28 + +#define MCS_TX_MAP_S 0 //32-32 +#define MCS_TX_MAP_E 15 //47-32 + +#define MCS_TX_HIGHEST_RATE_S 16 //48-32 +#define MCS_TX_HIGHEST_RATE_E 28 //60-32 + + +#endif diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Beamforming.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Beamforming.c new file mode 100755 index 000000000..2bc82e70f --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Beamforming.c @@ -0,0 +1,2210 @@ +#include "8192cd.h" +#include "8192cd_cfg.h" +#include "8192cd_util.h" +#include "8192cd_headers.h" +#include "Beamforming.h" +#include "8812_reg.h" +#include "8812_vht_gen.h" + + + +#ifdef BEAMFORMING_SUPPORT + + +VOID +Beamforming_SetBeamFormLeave( + struct rtl8192cd_priv *priv, + u1Byte Idx + ) +{ + +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv) == VERSION_8812E) + SetBeamformLeave8812(priv, Idx); +#endif + +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv) == VERSION_8192E) + SetBeamformLeave92E(priv,Idx); +#endif + +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv) == VERSION_8814A) + SetBeamformLeave8814A(priv,Idx); +#endif + +} + +VOID +Beamforming_SetBeamFormStatus( + struct rtl8192cd_priv *priv, + u1Byte Idx + ) +{ + +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv)== VERSION_8192E) + SetBeamformStatus92E(priv, Idx); +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + SetBeamformStatus8812(priv, Idx); +#endif + +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv) == VERSION_8814A) + SetBeamformStatus8814A(priv,Idx); +#endif + +} + +VOID +Beamforming_SetBeamFormEnter( + struct rtl8192cd_priv *priv, + u1Byte Idx + ) +{ + +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv)== VERSION_8192E) + SetBeamformEnter92E(priv, Idx); +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if (GET_CHIP_VER(priv)== VERSION_8812E) + SetBeamformEnter8812(priv, Idx); +#endif +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv) == VERSION_8814A) + SetBeamformEnter8814A(priv,Idx); +#endif + +} + + +VOID +Beamforming_NDPARate( + struct rtl8192cd_priv *priv, + BOOLEAN Mode, + u1Byte BW, + u1Byte Rate + ) +{ +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv)== VERSION_8192E){ + Beamforming_NDPARate_92E(priv, Mode, BW, Rate); + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) { + Beamforming_NDPARate_8812(priv, Mode, BW, Rate); // + } +#endif +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv)== VERSION_8814A){ + Beamforming_NDPARate_8814A(priv, Mode, BW, Rate); + } +#endif + +} + +VOID +Beamforming_SetHWTimer( + struct rtl8192cd_priv *priv, + u2Byte t + ) +{ +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv)== VERSION_8192E) + { + HW_VAR_HW_REG_TIMER_STOP_92E(priv); + HW_VAR_HW_REG_TIMER_INIT_92E(priv, t); + HW_VAR_HW_REG_TIMER_START_92E(priv); + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + { + HW_VAR_HW_REG_TIMER_STOP_8812(priv); + HW_VAR_HW_REG_TIMER_INIT_8812(priv, t); + HW_VAR_HW_REG_TIMER_START_8812(priv); + } +#endif +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv)== VERSION_8814A) + { + HW_VAR_HW_REG_TIMER_STOP_8814A(priv); + HW_VAR_HW_REG_TIMER_INIT_8814A(priv, t); + HW_VAR_HW_REG_TIMER_START_8814A(priv); + } +#endif +} + +VOID +Beamforming_StopHWTimer( + struct rtl8192cd_priv *priv + ) +{ +#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv)== VERSION_8192E) + { + HW_VAR_HW_REG_TIMER_STOP_92E(priv); + } +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + { + HW_VAR_HW_REG_TIMER_STOP_8812(priv); + } +#endif +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv)== VERSION_8814A) + { + HW_VAR_HW_REG_TIMER_STOP_8814A(priv); + } +#endif +} + +u1Byte +Beamforming_GetHTNDPTxRate( + struct rtl8192cd_priv *priv, + u1Byte CompSteeringNumofBFer +) +{ + u1Byte Nr_index = 0; + u1Byte NDPTxRate; + +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv)== VERSION_8814A) + Nr_index = TxBF_Nr(halTxbf8814A_GetNtx(priv), CompSteeringNumofBFer); /*find Nr*/ + else +#endif + Nr_index = TxBF_Nr(1, CompSteeringNumofBFer); /*find Nr*/ + switch(Nr_index) + { + case 1: + NDPTxRate = _MCS8_RATE_; + break; + + case 2: + NDPTxRate = _MCS16_RATE_; + break; + + case 3: + NDPTxRate = _MCS24_RATE_; + break; + + default: + NDPTxRate = _MCS8_RATE_; + break; + + } + +return NDPTxRate; + +} + +u1Byte +Beamforming_GetVHTNDPTxRate( + struct rtl8192cd_priv *priv, + u1Byte CompSteeringNumofBFer +) +{ + u1Byte Nr_index = 0; + u1Byte NDPTxRate; + +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv)== VERSION_8814A) + Nr_index = TxBF_Nr(halTxbf8814A_GetNtx(priv), CompSteeringNumofBFer); /*find Nr*/ + else +#endif + Nr_index = TxBF_Nr(1, CompSteeringNumofBFer); /*find Nr*/ + + switch(Nr_index) + { + case 1: + NDPTxRate = _NSS2_MCS0_RATE_; + break; + + case 2: + NDPTxRate = _NSS3_MCS0_RATE_; + break; + + case 3: + NDPTxRate = _NSS4_MCS0_RATE_; + break; + + default: + NDPTxRate = _NSS2_MCS0_RATE_; + break; + + } + +return NDPTxRate; + +} + + +VOID +PacketAppendData( + IN POCTET_STRING packet, + IN OCTET_STRING data + ) +{ + pu1Byte buf = packet->Octet + packet->Length; + memcpy( buf, data.Octet, data.Length); + packet->Length = packet->Length + data.Length; +} + +VOID +Beamforming_GidPAid( + struct rtl8192cd_priv *priv, + struct stat_info *pstat) +{ + + if (OPMODE & WIFI_AP_STATE) + { + u2Byte AID = (u2Byte) ((pstat->aid) & 0x1ff); //AID[0:8] + u2Byte bssid = 0; + + pstat->g_id = 63; + + bssid = ((BSSID[5] & 0xf0) >> 4) ^ (BSSID[5] & 0xf); // BSSID[44:47] xor BSSID[40:43] + pstat->p_aid = (AID + bssid * 32) & 0x1ff; // (dec(A) + dec(B)*32) mod 512 + + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + pstat->p_aid = REMAP_AID(pstat); + pstat->g_id = 63; + + } + else if (OPMODE & WIFI_STATION_STATE) + { + pstat->g_id = 0; + pstat->p_aid = ((int)(pstat->hwaddr[5])<<1) | (pstat->hwaddr[4]>>7); + } +} + +BEAMFORMING_CAP +Beamforming_GetEntryBeamCapByMacId( + struct rtl8192cd_priv *priv, + IN u1Byte MacId + ) +{ + u1Byte i = 0; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + BEAMFORMING_CAP BeamformEntryCap = BEAMFORMING_CAP_NONE; + + for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) + { + if(pBeamformingInfo->BeamformeeEntry[i].bUsed && + (MacId == pBeamformingInfo->BeamformeeEntry[i].MacId)) + { + BeamformEntryCap = pBeamformingInfo->BeamformeeEntry[i].BeamformEntryCap; + i = BEAMFORMEE_ENTRY_NUM; + } + } + + return BeamformEntryCap; +} + + +PRT_BEAMFORMING_ENTRY +Beamforming_GetBFeeEntryByAddr( + struct rtl8192cd_priv *priv, + IN pu1Byte RA, + OUT pu1Byte Idx + ) +{ + u1Byte i = 0; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + + for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) + { + if((pBeamformingInfo->BeamformeeEntry[i].bUsed) && + ((memcmp(RA, pBeamformingInfo->BeamformeeEntry[i].MacAddr, MACADDRLEN)) == 0)) + { + *Idx = i; + return &(pBeamformingInfo->BeamformeeEntry[i]); + } + } + return NULL; +} + +PRT_BEAMFORMER_ENTRY +Beamforming_GetBFerEntryByAddr( + struct rtl8192cd_priv *priv, + IN pu1Byte RA, + OUT pu1Byte Idx + ) +{ + u1Byte i = 0; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + + for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++) + { + if((pBeamformingInfo->BeamformerEntry[i].bUsed) && + ((memcmp(RA, pBeamformingInfo->BeamformerEntry[i].MacAddr, MACADDRLEN)) == 0)) + { + *Idx = i; + return &(pBeamformingInfo->BeamformerEntry[i]); + } + } + return NULL; +} + + +PRT_BEAMFORMING_ENTRY +Beamforming_GetEntryByMacId( + struct rtl8192cd_priv *priv, + u1Byte MacId, + pu1Byte Idx + ) +{ + u1Byte i = 0; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + + for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) + { + if(pBeamformingInfo->BeamformeeEntry[i].bUsed && + (MacId == pBeamformingInfo->BeamformeeEntry[i].MacId)) + { + *Idx = i; + return &(pBeamformingInfo->BeamformeeEntry[i]); + } + } + + return NULL; + +} + +PRT_BEAMFORMING_ENTRY +Beamforming_GetFreeBFeeEntry( + struct rtl8192cd_priv *priv, + OUT pu1Byte Idx, + pu1Byte RA + ) +{ + u1Byte i = 0; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__)); + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s, RA= 0x %x%x%x%x%x%x\n", + __FUNCTION__, + RA[0],RA[1],RA[2],RA[3],RA[4],RA[5])); + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s, BFeeEntry_Idx0= 0x %x%x%x%x%x%x\n", + __FUNCTION__, + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[0], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[1], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[2], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[3], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[4], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[5])); + + + if( !(memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0, MACADDRLEN)) ){ + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, (memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0, MACADDRLEN)) == 1, return NULL!!\n", __FUNCTION__)); + return NULL; + } + else if(!(memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1, MACADDRLEN))){ + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, (memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1, MACADDRLEN)) == 1, return NULL!!\n", __FUNCTION__)); + return NULL; + } + + for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) + { + if(pBeamformingInfo->BeamformeeEntry[i].bUsed == FALSE) + { + *Idx = i; + return &(pBeamformingInfo->BeamformeeEntry[i]); + } + } + return NULL; +} + +PRT_BEAMFORMER_ENTRY +Beamforming_GetFreeBFerEntry( + struct rtl8192cd_priv *priv, + OUT pu1Byte Idx, + pu1Byte RA + ) +{ + u1Byte i = 0; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__)); + + if(!(memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx0, MACADDRLEN))){ + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, (memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx0, MACADDRLEN)) == 1, return NULL!!\n", __FUNCTION__)); + return NULL; + } + else if(!(memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx1, MACADDRLEN))){ + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, (memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx1, MACADDRLEN)) == 1, return NULL!!\n", __FUNCTION__)); + return NULL; + } + + for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++) + { + if(pBeamformingInfo->BeamformerEntry[i].bUsed == FALSE) + { + *Idx = i; + return &(pBeamformingInfo->BeamformerEntry[i]); + } + } + return NULL; +} + +PRT_BEAMFORMING_ENTRY +Beamforming_AddBFeeEntry( + struct rtl8192cd_priv *priv, + struct stat_info *pSTA, + pu1Byte RA, + u2Byte AID, + u2Byte MacID, + u1Byte BW, + BEAMFORMING_CAP BeamformCap, + pu1Byte Idx, + u2Byte CompSteeringNumofBFer + ) +{ + PRT_BEAMFORMING_ENTRY pEntry; + pEntry = Beamforming_GetFreeBFeeEntry(priv, Idx,RA); + + // Check if this MAC address is in DelEntryList + + + if(pEntry != NULL) + { + pEntry->bUsed = TRUE; + pEntry->AID = AID; + pEntry->MacId = MacID; + pEntry->BW = BW; + + // AID -> P_AID + if (OPMODE & WIFI_AP_STATE) + { + u2Byte bssid = ((GET_MY_HWADDR[5]>> 4) & 0x0f ) ^ + (GET_MY_HWADDR[5] & 0xf); // BSSID[44:47] xor BSSID[40:43] + pEntry->P_AID = (AID + (bssid <<5)) & 0x1ff; // (dec(A) + dec(B)*32) mod 512 + + } + else if (OPMODE & WIFI_ADHOC_STATE) + { +// pEntry->P_AID = AID; + pEntry->P_AID = 0; + + } + else if (OPMODE & WIFI_STATION_STATE) { + pEntry->P_AID = RA[5]; // BSSID[39:47] + pEntry->P_AID = (pEntry->P_AID << 1) | (RA[4] >> 7 ); + } + // + + memcpy(pEntry->MacAddr, RA, MACADDRLEN); + pEntry->bTxBF = FALSE; + pEntry->bSound = FALSE; + + pEntry->BeamformEntryCap = BeamformCap; + pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE; + pEntry->LogStatusFailCnt = 0; + + pEntry->CompSteeringNumofBFer = CompSteeringNumofBFer; + pEntry->pSTA = pSTA; + +#ifdef MBSSID + if(GET_CHIP_VER(priv) == VERSION_8812E) + if (GET_MIB(GET_ROOT(priv))->miscEntry.vap_enable) + rtl8192cd_set_mbssid(priv, RA, *Idx); +#endif + return pEntry; + } + else + return NULL; +} + +PRT_BEAMFORMER_ENTRY +Beamforming_AddBFerEntry( + struct rtl8192cd_priv *priv, + pu1Byte RA, + u2Byte AID, + BEAMFORMING_CAP BeamformCap, + pu1Byte Idx, + u2Byte NumofSoundingDim + ) +{ + PRT_BEAMFORMER_ENTRY pEntry; + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__)); + + pEntry = Beamforming_GetFreeBFerEntry(priv, Idx, RA); + + if(pEntry != NULL) + { + pEntry->bUsed = TRUE; + + // AID -> P_AID + if (OPMODE & WIFI_AP_STATE) + { + u2Byte bssid = ((GET_MY_HWADDR[5]>> 4) & 0x0f ) ^ (GET_MY_HWADDR[5] & 0xf); // BSSID[44:47] xor BSSID[40:43] + pEntry->P_AID = (AID + (bssid <<5)) & 0x1ff; // (dec(A) + dec(B)*32) mod 512 + + } + else if (OPMODE & WIFI_ADHOC_STATE) + { + pEntry->P_AID = 0; + } + else if (OPMODE & WIFI_STATION_STATE) { + pEntry->P_AID = RA[5]; // BSSID[39:47] + pEntry->P_AID = (pEntry->P_AID << 1) | (RA[4] >> 7 ); + } + + memcpy(pEntry->MacAddr, RA, MACADDRLEN); + pEntry->BeamformEntryCap = BeamformCap; + pEntry->NumofSoundingDim = NumofSoundingDim; + + pEntry->ClockResetTimes = 0; + pEntry->NDPAPreLogSeq = 0; + pEntry->NDPALogSeq = 0; + pEntry->NDPALogRetryCnt = 0; + pEntry->NDPALogSuccess = 0; +// pEntry->LogStatusFailCnt = 0; + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BFer Entry!=NULL\n", __FUNCTION__)); + + return pEntry; + } + else + return NULL; +} + + +BOOLEAN +Beamforming_RemoveEntry( + struct rtl8192cd_priv *priv, + IN pu1Byte RA, + OUT pu1Byte Idx + ) +{ + PRT_BEAMFORMER_ENTRY pBFerEntry = Beamforming_GetBFerEntryByAddr(priv, RA, Idx); + PRT_BEAMFORMING_ENTRY pBFeeEntry = Beamforming_GetBFeeEntryByAddr(priv, RA, Idx); + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + + u1Byte i; + // CurDelBFerBFeeEntrySel had been decided by the function who calls Beamforming_DeInitEntry + DEL_ENTRY_TYPE_SEL CurDelBFerBFeeEntrySel=pBeamformingInfo->CurDelBFerBFeeEntrySel; + + BOOLEAN ret = FALSE; + +// if( (CurDelBFerBFeeEntrySel== BFerEntry)||(CurDelBFerBFeeEntrySel == BFerBFeeEntry) ) +/* + if( CurDelBFerBFeeEntrySel == BFerEntry) + { + if (pBFerEntry != NULL) + { + pBFerEntry->bUsed = FALSE; + pBFerEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE; + + if(*Idx==0) + memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx0[0], RA, 6); + else + memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx1[0], RA, 6); + + ret = TRUE; + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, Remove BFerEntry idx=%d\n", __FUNCTION__, *Idx)); + } + } +*/ + if (pBFerEntry != NULL) + { + pBFerEntry->bUsed = FALSE; + pBFerEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE; + + if(CurDelBFerBFeeEntrySel == BFerEntry) + { + if(*Idx==0) + memcpy(pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx0, RA, 6); + else + memcpy(pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx1, RA, 6); + } + + ret = TRUE; + } + + if (pBFeeEntry != NULL) + { + pBFeeEntry->bUsed = FALSE; + pBFeeEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE; + + if(CurDelBFerBFeeEntrySel == BFeeEntry) + { + if(*Idx==0) + memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[0], RA, 6); + else + memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[0], RA, 6); + } + + ret = TRUE; + } + +/* + if( (CurDelBFerBFeeEntrySel == BFeeEntry)||(CurDelBFerBFeeEntrySel == BFerBFeeEntry) ) + { + if (pBFeeEntry != NULL) + { + pBFeeEntry->bUsed = FALSE; + pBFeeEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE; + + if(*Idx==0) + memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[0], RA, 6); + else + memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[0], RA, 6); + + ret = TRUE; + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, Remove BFeeEntry idx=%d\n", __FUNCTION__, *Idx)); + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, RA=0x%x%x%x%x%x%x\n", + __FUNCTION__, + RA[0],RA[1],RA[2],RA[3],RA[4],RA[5])); + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BFeeEntry_Idx0=0x%x%x%x%x%x%x, BFeeEntry_Idx1=0x%x%x%x%x%x%x\n", + __FUNCTION__, + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[0], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[1], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[2], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[3], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[4], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[5], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[0], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[1], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[2], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[3], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[4], + pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[5] + )); + + } + + } +*/ + return ret; +} + +BOOLEAN +Beamforming_InitEntry( + struct rtl8192cd_priv *priv, + struct stat_info *pSTA, + pu1Byte BFerBFeeIdx + ) +{ + + PRT_BEAMFORMING_ENTRY pBeamformEntry = NULL; + PRT_BEAMFORMER_ENTRY pBeamformerEntry = NULL; + pu1Byte RA; + u2Byte AID, MacID; + u1Byte WirelessMode; + u1Byte BW = HT_CHANNEL_WIDTH_20; + BEAMFORMING_CAP BeamformCap = BEAMFORMING_CAP_NONE; + u1Byte BFerIdx = 0xF, BFeeIdx = 0xF; + u2Byte CompSteeringNumofBFer = 0, NumofSoundingDim = 0; + + // The current setting does not support Beaforming + if (priv->pmib->dot11RFEntry.txbf == 0) + { + return FALSE; + } + + // IBSS, AP mode + if(pSTA != NULL) + { + AID = pSTA->aid; + RA = pSTA->hwaddr; + MacID = pSTA->aid; + + WirelessMode = pSTA->WirelessMode; + BW = pSTA->tx_bw; + } + else // Client mode + { + return FALSE; + } + + if( WirelessMode < WIRELESS_MODE_N_24G) + return FALSE; + + else + { + +// BIT 4 implies capable of sending NDPA (BFER), +// BIT 3 implies capable of receiving NDPA (BFEE), + + if(pSTA->ht_cap_len && (cpu_to_le32(pSTA->ht_cap_buf.txbf_cap) & 0x8)&& (priv->pmib->dot11RFEntry.txbfer == 1)) //bfer + { + BeamformCap |=BEAMFORMER_CAP_HT_EXPLICIT; + CompSteeringNumofBFer = (u1Byte)((cpu_to_le32(pSTA->ht_cap_buf.txbf_cap) & (BIT(23)|BIT(24)))>>23); +// panic_printk("[%d] BeamformCap = BEAMFORMER_CAP_HT_EXPLICIT \n",__LINE__); + } + if (pSTA->ht_cap_len && (cpu_to_le32(pSTA->ht_cap_buf.txbf_cap) & 0x10)&& (priv->pmib->dot11RFEntry.txbfee == 1)) //bfee + { + BeamformCap |=BEAMFORMEE_CAP_HT_EXPLICIT; + NumofSoundingDim = (u1Byte)((cpu_to_le32(pSTA->ht_cap_buf.txbf_cap) & (BIT(27)|BIT(28)))>>27); +// panic_printk("[%d] BeamformCap = BEAMFORMEE_CAP_HT_EXPLICIT \n",__LINE__); + } + +#ifdef RTK_AC_SUPPORT + if(WirelessMode == WIRELESS_MODE_AC_5G) + { + if(pSTA->vht_cap_len && (cpu_to_le32(pSTA->vht_cap_buf.vht_cap_info) & BIT(SU_BFEE_S)) && (priv->pmib->dot11RFEntry.txbfer == 1)) // ACÁÙ¨S¨Ì¾Úbfer or bfee¾× + { + BeamformCap |=BEAMFORMER_CAP_VHT_SU; + CompSteeringNumofBFer = (u1Byte)((cpu_to_le32(pSTA->vht_cap_buf.vht_cap_info) & (BIT(MAX_ANT_SUPP_S)|BIT(MAX_ANT_SUPP_S+1)|BIT(MAX_ANT_SUPP_E)))>>MAX_ANT_SUPP_S); + } + if(pSTA->vht_cap_len && (cpu_to_le32(pSTA->vht_cap_buf.vht_cap_info) & BIT(SU_BFER_S)) && (priv->pmib->dot11RFEntry.txbfee == 1)) + { + BeamformCap |=BEAMFORMEE_CAP_VHT_SU; + NumofSoundingDim = (u1Byte)((cpu_to_le32(pSTA->vht_cap_buf.vht_cap_info) & (BIT(SOUNDING_DIMENSIONS_S)|BIT(SOUNDING_DIMENSIONS_S+1)|BIT(SOUNDING_DIMENSIONS_E)))>>SOUNDING_DIMENSIONS_S); + } + } +#endif + } + + if(BeamformCap == BEAMFORMING_CAP_NONE) + return FALSE; + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, CompSteeringNumofBFer = %d, NumofSoundingDim = %d\n", __FUNCTION__, CompSteeringNumofBFer, NumofSoundingDim)); +// bfme + if((BeamformCap & BEAMFORMEE_CAP_HT_EXPLICIT) || (BeamformCap & BEAMFORMEE_CAP_VHT_SU)) + { + pBeamformerEntry = Beamforming_GetBFerEntryByAddr(priv, RA, &BFerIdx); + + if(pBeamformerEntry == NULL) + { + pBeamformerEntry = Beamforming_AddBFerEntry(priv, RA, AID, BeamformCap, &BFerIdx, NumofSoundingDim); + + if(pBeamformerEntry == NULL) + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Not enough BFer entry!\n", __FUNCTION__)); + } + } + +// bfer + if((BeamformCap & BEAMFORMER_CAP_HT_EXPLICIT) || (BeamformCap & BEAMFORMER_CAP_VHT_SU)) + { + pBeamformEntry = Beamforming_GetBFeeEntryByAddr(priv, RA, &BFeeIdx); + + if(pBeamformEntry == NULL) + { + pBeamformEntry = Beamforming_AddBFeeEntry(priv, pSTA, RA, AID, MacID, BW, BeamformCap, &BFeeIdx, CompSteeringNumofBFer); + + if(pBeamformEntry == NULL) + { + return FALSE; + } + else + pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING; + } + else + { + // Entry has been created. If entry is initialing or progressing then errors occur. + if( pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED && + pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Error State of Beamforming\n", __FUNCTION__)); + return FALSE; + } + else + pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING; + } + + pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED; + Beamforming_AutoTest(priv, BFeeIdx, pBeamformEntry); + } + + *BFerBFeeIdx = (BFerIdx<<4) | BFeeIdx; + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, BFerIdx=%d, BFeeIdx=%d, BFerBFeeIdx=%d \n", __FUNCTION__, BFerIdx, BFeeIdx, *BFerBFeeIdx)); + + return TRUE; +} + +BOOLEAN +Beamforming_DeInitEntry( + struct rtl8192cd_priv *priv, + pu1Byte RA + ) +{ + u1Byte Idx = 0; + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s Start!!!\n", __FUNCTION__)); + + if(Beamforming_RemoveEntry(priv, RA, &Idx) == TRUE) + { + Beamforming_SetBeamFormLeave(priv, Idx); + +#ifdef CONFIG_RTL_8812_SUPPORT // 8812 only?? +#ifdef MBSSID + if (GET_MIB(GET_ROOT(priv))->miscEntry.vap_enable) + rtl8192cd_clear_mbssid(priv, Idx); +#endif +#endif + + return TRUE; + } + else + { + // For AP debug, because when STA disconnect AP, release_stainfo will be triggered many times + return FALSE; + } + +} + +VOID +BeamformingReset( + struct rtl8192cd_priv *priv + ) +{ + u1Byte Idx = 0; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + + for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++) + { + if(pBeamformingInfo->BeamformeeEntry[Idx].bUsed == TRUE) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Reset entry idx=%d\n", __FUNCTION__, Idx)); + pBeamformingInfo->BeamformeeEntry[Idx].bUsed = FALSE; + pBeamformingInfo->BeamformeeEntry[Idx].BeamformEntryCap = BEAMFORMING_CAP_NONE; + //pBeamformingInfo->BeamformeeEntry[Idx].BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE; + pBeamformingInfo->BeamformeeEntry[Idx].bBeamformingInProgress = FALSE; + + Beamforming_SetBeamFormLeave(priv, Idx); + } + } + + for(Idx = 0; Idx < BEAMFORMER_ENTRY_NUM; Idx++) + { + pBeamformingInfo->BeamformerEntry[Idx].bUsed = FALSE; + } + +} + + + +#define FillOctetString(_os,_octet,_len) \ + (_os).Octet=(pu1Byte)(_octet); \ + (_os).Length=(_len); + +VOID +ConstructHTNDPAPacket( + struct rtl8192cd_priv *priv, + pu1Byte RA, + pu1Byte Buffer, + pu4Byte pLength, + u1Byte BW + ) +{ + u2Byte Duration= 0; + OCTET_STRING pNDPAFrame, ActionContent; + u1Byte ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c}; + int aSifsTime = ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && (priv->pshare->ht_sta_num)) ? 0x10 : 10; + + + SET_80211_HDR_FRAME_CONTROL(Buffer,0); + SET_80211_HDR_ORDER(Buffer, 1); + SET_80211_HDR_TYPE_AND_SUBTYPE(Buffer,Type_Action_No_Ack); + + memcpy((void *)GetAddr1Ptr(Buffer), RA, MACADDRLEN); + memcpy((void *)GetAddr2Ptr(Buffer), GET_MY_HWADDR, MACADDRLEN); + memcpy((void *)GetAddr3Ptr(Buffer), BSSID, MACADDRLEN); + + Duration = 2*aSifsTime + 40; + + if(BW== HT_CHANNEL_WIDTH_20_40) + Duration+= 87; + else + Duration+= 180; + + SET_80211_HDR_DURATION(Buffer, Duration); + + //HT control field + SET_HT_CTRL_CSI_STEERING(Buffer+sMacHdrLng, 3); + SET_HT_CTRL_NDP_ANNOUNCEMENT(Buffer+sMacHdrLng, 1); + + FillOctetString(pNDPAFrame, Buffer, sMacHdrLng+sHTCLng); + + FillOctetString(ActionContent, ActionHdr, 4); + PacketAppendData(&pNDPAFrame, ActionContent); + + *pLength = 32; +} + + +BOOLEAN +SendHTNDPAPacket( + struct rtl8192cd_priv *priv, + pu1Byte RA, + u1Byte BW, + u1Byte NDPTxRate + ) +{ + BOOLEAN ret = TRUE; + unsigned char *pbuf = get_wlanllchdr_from_poll(priv); + u4Byte PacketLength; + DECLARE_TXINSN(txinsn); + + if(pbuf) + { + memset(pbuf, 0, sizeof(struct wlan_hdr)); + ConstructHTNDPAPacket( + priv, + RA, + pbuf, + &PacketLength, + BW + ); + + txinsn.q_num = MGNT_QUEUE; + txinsn.fr_type = _PRE_ALLOCLLCHDR_; + + txinsn.phdr = pbuf; + txinsn.hdr_len = PacketLength; + txinsn.fr_len = 0; + txinsn.lowest_tx_rate = txinsn.tx_rate = NDPTxRate; //_MCS8_RATE_;, According to Nr + txinsn.fixed_rate = 1; + txinsn.ndpa = 1; + + if (rtl8192cd_wlantx(priv, &txinsn) == CONGESTED) { + netif_stop_queue(priv->dev); + priv->ext_stats.tx_drops++; +// panic_printk("TX DROP: Congested!\n"); + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return 0; + } + } + else + ret = FALSE; + + return ret; +} + + + + +VOID +ConstructVHTNDPAPacket( + struct rtl8192cd_priv *priv, + pu1Byte RA, + u2Byte AID, + pu1Byte Buffer, + pu4Byte pLength, + u1Byte BW + ) +{ + u2Byte Duration= 0; + u1Byte Sequence = 0; + pu1Byte pNDPAFrame = Buffer; + u2Byte tmp16; + + RT_NDPA_STA_INFO STAInfo; + int aSifsTime = ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && (priv->pshare->ht_sta_num)) ? 0x10 : 10; + + // Frame control. + SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0); + SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA); + + memcpy((void *)GetAddr1Ptr(pNDPAFrame), RA, MACADDRLEN); + memcpy((void *)GetAddr2Ptr(pNDPAFrame), GET_MY_HWADDR, MACADDRLEN); + + Duration = 2*aSifsTime + 44; + + if(BW == HT_CHANNEL_WIDTH_80) + Duration += 40; + else if(BW == HT_CHANNEL_WIDTH_20_40) + Duration+= 87; + else + Duration+= 180; + + SetDuration(pNDPAFrame, Duration); + Sequence = GET_HW(priv)->sounding_seq<<2; + GET_HW(priv)->sounding_seq = (GET_HW(priv)->sounding_seq+1) & 0xfff; + + memcpy(pNDPAFrame+16, &Sequence,1); + + if (OPMODE & WIFI_ADHOC_STATE) + AID = 0; + + STAInfo.AID = AID; + + STAInfo.FeedbackType = 0; + STAInfo.NcIndex = 0; + + memcpy(&tmp16, (pu1Byte)&STAInfo, 2); + tmp16 = cpu_to_le16(tmp16); + + memcpy(pNDPAFrame+17, &tmp16, 2); + + *pLength = 19; +} + + +BOOLEAN +SendVHTNDPAPacket( + struct rtl8192cd_priv *priv, + IN pu1Byte RA, + IN u2Byte AID, + u1Byte BW, + u1Byte NDPTxRate + ) +{ + BOOLEAN ret = TRUE; + u4Byte PacketLength; + unsigned char *pbuf = get_wlanllchdr_from_poll(priv); + DECLARE_TXINSN(txinsn); + + if(pbuf) + { + memset(pbuf, 0, sizeof(struct wlan_hdr)); + + ConstructVHTNDPAPacket ( + priv, + RA, + AID, + pbuf, + &PacketLength, + BW + ); + + txinsn.q_num = MANAGE_QUE_NUM; + txinsn.fr_type = _PRE_ALLOCLLCHDR_; + txinsn.phdr = pbuf; + txinsn.hdr_len = PacketLength; + txinsn.fr_len = 0; + txinsn.fixed_rate = 1; + txinsn.lowest_tx_rate = txinsn.tx_rate = NDPTxRate; // According to Nr + txinsn.ndpa = 1; + + if (rtl8192cd_wlantx(priv, &txinsn) == CONGESTED) { + netif_stop_queue(priv->dev); + priv->ext_stats.tx_drops++; +// panic_printk("TX DROP: Congested!\n"); + if (txinsn.phdr) + release_wlanhdr_to_poll(priv, txinsn.phdr); + if (txinsn.pframe) + release_mgtbuf_to_poll(priv, txinsn.pframe); + return 0; + } + } + else + ret = FALSE; + + return ret; +} + + + +u1Byte +beamforming_SoundingIdx( + PRT_BEAMFORMING_INFO pBeamInfo + ) +{ + u1Byte Idx = 0; + PRT_BEAMFORMING_PERIOD_INFO pBeamPeriodInfo = &(pBeamInfo->BeamformingPeriodInfo); + + if( pBeamPeriodInfo->Mode == SOUNDING_SW_VHT_TIMER ||pBeamPeriodInfo->Mode == SOUNDING_SW_HT_TIMER || + pBeamPeriodInfo->Mode == SOUNDING_HW_VHT_TIMER ||pBeamPeriodInfo->Mode == SOUNDING_HW_HT_TIMER) + Idx = pBeamPeriodInfo->Idx; + else + Idx = 0; + + return Idx; +} + + +BEAMFORMING_NOTIFY_STATE +beamfomring_bSounding( + PRT_BEAMFORMING_INFO pBeamInfo, + pu1Byte Idx + ) +{ + BEAMFORMING_NOTIFY_STATE bSounding = BEAMFORMING_NOTIFY_NONE; + //RT_BEAMFORMING_ENTRY Entry = pBeamInfo->BeamformeeEntry[*Idx]; + RT_BEAMFORMING_PERIOD_INFO BeamPeriodInfo = pBeamInfo->BeamformingPeriodInfo; + + if(BeamPeriodInfo.Mode == SOUNDING_STOP_All_TIMER) + bSounding = BEAMFORMING_NOTIFY_RESET; +// else if(BeamPeriodInfo.Mode == SOUNDING_STOP_OID_TIMER && Entry.bTxBF == FALSE) +// bSounding = BEAMFORMING_NOTIFY_RESET; + else + { + u1Byte i; + + for(i=0;iBeamformeeEntry[i].bUsed, pBeamInfo->BeamformeeEntry[i].bSound); + if(pBeamInfo->BeamformeeEntry[i].bUsed && (!pBeamInfo->BeamformeeEntry[i].bSound)) + { + *Idx = i; + bSounding = BEAMFORMING_NOTIFY_ADD; + } + + if((!pBeamInfo->BeamformeeEntry[i].bUsed) && pBeamInfo->BeamformeeEntry[i].bSound) + { + *Idx = i; + bSounding = BEAMFORMING_NOTIFY_DELETE; + } + } + } + + return bSounding; +} + + +SOUNDING_MODE +beamforming_SoundingMode( + PRT_BEAMFORMING_INFO pBeamInfo, + u1Byte Idx + ) +{ + RT_BEAMFORMING_PERIOD_INFO BeamPeriodInfo = pBeamInfo->BeamformingPeriodInfo; + SOUNDING_MODE Mode = BeamPeriodInfo.Mode; + RT_BEAMFORMING_ENTRY Entry = pBeamInfo->BeamformeeEntry[Idx]; + + if( BeamPeriodInfo.Mode == SOUNDING_SW_VHT_TIMER || BeamPeriodInfo.Mode == SOUNDING_SW_HT_TIMER || + BeamPeriodInfo.Mode == SOUNDING_HW_VHT_TIMER || BeamPeriodInfo.Mode == SOUNDING_HW_HT_TIMER ) + Mode = BeamPeriodInfo.Mode; + else if(Entry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU) + Mode = SOUNDING_AUTO_VHT_TIMER; + else if(Entry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT) + Mode = SOUNDING_AUTO_HT_TIMER; + + return Mode; +} + + +u2Byte +beamforming_SoundingTime( + PRT_BEAMFORMING_INFO pBeamInfo, + SOUNDING_MODE Mode + ) +{ + u2Byte SoundingTime = 0xffff; + RT_BEAMFORMING_PERIOD_INFO BeamPeriodInfo = pBeamInfo->BeamformingPeriodInfo; + + if(Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER) + SoundingTime = BeamPeriodInfo.BeamPeriod * 32; + else if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER) + SoundingTime = BeamPeriodInfo.BeamPeriod ; + else + SoundingTime = 20*32; + + return SoundingTime; +} + + +u1Byte +beamforming_SoundingBW( + PRT_BEAMFORMING_INFO pBeamInfo, + SOUNDING_MODE Mode, + u1Byte Idx + ) +{ + u1Byte SoundingBW = HT_CHANNEL_WIDTH_20; + RT_BEAMFORMING_ENTRY Entry = pBeamInfo->BeamformeeEntry[Idx]; + RT_BEAMFORMING_PERIOD_INFO BeamPeriodInfo = pBeamInfo->BeamformingPeriodInfo; + + if(Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER) + SoundingBW = BeamPeriodInfo.BW; + else if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER) + SoundingBW = BeamPeriodInfo.BW; + else + SoundingBW = Entry.BW; + + return SoundingBW; +} + + +VOID +beamforming_StartPeriod( + struct rtl8192cd_priv *priv, + u1Byte Idx + ) +{ + + PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo); + PRT_BEAMFORMING_TIMER_INFO pBeamTimerInfo = &(pBeamInfo->BeamformingTimerInfo[Idx]); + + +// pBeamTimerInfo->Idx = Idx; + pBeamTimerInfo->Mode = beamforming_SoundingMode(pBeamInfo, Idx); + pBeamTimerInfo->BW = beamforming_SoundingBW(pBeamInfo, pBeamTimerInfo->Mode, Idx); + pBeamTimerInfo->BeamPeriod = beamforming_SoundingTime(pBeamInfo, pBeamTimerInfo->Mode); + + if(pBeamTimerInfo->Mode == SOUNDING_SW_VHT_TIMER || pBeamTimerInfo->Mode == SOUNDING_SW_HT_TIMER) + { + ODM_SetTimer(ODMPTR, &pBeamInfo->BeamformingTimer, pBeamTimerInfo->BeamPeriod); + } + else + { + Beamforming_SetHWTimer(priv, pBeamTimerInfo->BeamPeriod); + } + +// panic_printk ("%s Idx %d Mode %d BW %d Period %d\n", __FUNCTION__, +// Idx, pBeamTimerInfo->Mode, pBeamTimerInfo->BW, pBeamTimerInfo->BeamPeriod); +} + + +VOID +beamforming_EndPeriod_SW( + struct rtl8192cd_priv *priv, + u1Byte Idx + ) +{ +// u1Byte Idx = 0; + PRT_BEAMFORMING_ENTRY pBeamformEntry; + PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo); + PRT_BEAMFORMING_TIMER_INFO pBeamTimerInfo = &(pBeamInfo->BeamformingTimerInfo[Idx]); + + if(pBeamTimerInfo->Mode == SOUNDING_SW_VHT_TIMER || pBeamTimerInfo->Mode == SOUNDING_SW_HT_TIMER) + { + ODM_CancelTimer(ODMPTR, &pBeamInfo->BeamformingTimer); + } + else + { + Beamforming_StopHWTimer(priv); + } + +} + +VOID +beamforming_EndPeriod_FW( + struct rtl8192cd_priv *priv, + u1Byte Idx + ) +{ + return; +} + +VOID +beamforming_ClearEntry_SW( + struct rtl8192cd_priv *priv, + BOOLEAN IsDelete, + u1Byte DeleteIdx + ) +{ + u1Byte Idx = 0; + PRT_BEAMFORMING_ENTRY pBeamformEntry; + PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo); + + if(IsDelete) + { + if(DeleteIdxBeamformeeEntry + DeleteIdx; + + if(!((!pBeamformEntry->bUsed) && pBeamformEntry->bSound)) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, SW DeleteIdx is wrong!\n", __FUNCTION__)); + return; + } + + if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING) + { + pBeamformEntry->bBeamformingInProgress = FALSE; + pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE; + } + else if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED) + { + pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE; + Beamforming_SetBeamFormStatus(priv, DeleteIdx); + } + pBeamformEntry->bSound=FALSE; + } + } + else + { + for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++) + { + pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx; + + if(pBeamformEntry->bSound) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, SW Reset entry %d\n", __FUNCTION__, Idx)); + + /* + * If End procedure is + * 1. Between (Send NDPA, C2H packet return), reset state to initialized. + * After C2H packet return , status bit will be set to zero. + *r + * 2. After C2H packet, then reset state to initialized and clear status bit. + */ + if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING) + { + Beamforming_End(priv, 0); + } + else if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED) + { + pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED; + Beamforming_SetBeamFormStatus(priv, Idx); + } + + pBeamformEntry->bSound=FALSE; + } + } + } + +} + +VOID +beamforming_ClearEntry_FW( + struct rtl8192cd_priv *priv, + BOOLEAN IsDelete, + u1Byte DeleteIdx + ) +{ + return; +} + +struct rtl8192cd_priv* +getBeamEntryDev(struct rtl8192cd_priv *priv, PRT_BEAMFORMING_ENTRY pEntry) +{ + struct stat_info *pstat; + struct rtl8192cd_priv *vxd_priv; + int j; + + pstat = get_stainfo(priv, pEntry->MacAddr); + if(pstat) + return priv; + +#ifdef MBSSID + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->miscEntry.vap_enable) + { + for (j=0; jpvap_priv[j]->assoc_num > 0) && IS_DRV_OPEN(priv->pvap_priv[j])) + { + pstat = get_stainfo(priv->pvap_priv[j], pEntry->MacAddr); + if(pstat) + return priv->pvap_priv[j]; + + } + } + } +#endif +#ifdef UNIVERSAL_REPEATER + vxd_priv = GET_VXD_PRIV(priv); + if((OPMODE & WIFI_STATION_STATE) && (vxd_priv->assoc_num > 0) && IS_DRV_OPEN(vxd_priv) ) + { + pstat = get_stainfo(vxd_priv, pEntry->MacAddr); + if(pstat) + return vxd_priv; + } +#endif + return NULL; + +} + + +BOOLEAN +BeamformingStart_V2( + struct rtl8192cd_priv *priv, + u1Byte Idx, + u1Byte Mode, + u1Byte BW + ) +{ + pu1Byte RA = NULL; + PRT_BEAMFORMING_ENTRY pEntry; + BOOLEAN ret = TRUE; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + u1Byte NDPTxRate; + pEntry = &(pBeamformingInfo->BeamformeeEntry[Idx]); + + priv = getBeamEntryDev(priv, pEntry); + if( !priv) + return FALSE; + + if(pEntry->bUsed == FALSE) + { + pEntry->bBeamformingInProgress = FALSE; + return FALSE; + } + else + { + if(pEntry->bBeamformingInProgress) + return FALSE; + pEntry->bBeamformingInProgress = TRUE; + + RA = pEntry->MacAddr; + + if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER) + { + if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)) + { +// pBeamformingInfo->bBeamformingInProgress = FALSE; + pEntry->bBeamformingInProgress = FALSE; + return FALSE; + } + } + else if(Mode == SOUNDING_SW_VHT_TIMER || Mode == SOUNDING_HW_VHT_TIMER || Mode == SOUNDING_AUTO_VHT_TIMER) + { + if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)) + { +// pBeamformingInfo->bBeamformingInProgress = FALSE; + pEntry->bBeamformingInProgress = FALSE; + return FALSE; + } + } + + if(pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED && pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED) + { +// pBeamformingInfo->bBeamformingInProgress = FALSE; + pEntry->bBeamformingInProgress = FALSE; + return FALSE; + } + else + { + pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING; + pEntry->bSound = TRUE; + } + } + + pEntry->BW = BW; + pBeamformingInfo->BeamformeeCurIdx = Idx; + + Beamforming_SetBeamFormStatus(priv, (pBeamformingInfo->BeamformeeCurIdx)); + Beamforming_NDPARate(priv, Mode, BW, 0); // soundingpreiod only for debug, use 0 for all case + +// debug + if(!priv->pshare->rf_ft_var.soundingEnable) + return TRUE; + +#ifdef CONFIG_WLAN_HAL_8192EE + if ((OPMODE & WIFI_AP_STATE) && (priv->pshare->soundingLock)) + return TRUE; +#endif +// + if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER) + { + NDPTxRate = Beamforming_GetHTNDPTxRate(priv, pEntry->CompSteeringNumofBFer); + ret = SendHTNDPAPacket(priv,RA, BW, NDPTxRate); + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, HT NDP Rate = %d\n", __FUNCTION__, NDPTxRate)); + } + else + { + NDPTxRate = Beamforming_GetVHTNDPTxRate(priv, pEntry->CompSteeringNumofBFer); + +#ifdef CONFIG_WLAN_HAL_8814AE + if(((pEntry->pSTA->current_tx_rate >=_NSS3_MCS7_RATE_) && (pEntry->pSTA->current_tx_rate <=_NSS3_MCS9_RATE_)) && + priv->pshare->rf_ft_var.Nsnding3SS &&(GET_CHIP_VER(priv)== VERSION_8814A) ) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT3SS 7,8,9, not sounding!!\n", __FUNCTION__)); + } + else +#endif + +#ifdef CONFIG_RTL_8812_SUPPORT + if(((pEntry->pSTA->current_tx_rate >=_NSS2_MCS0_RATE_) && (pEntry->pSTA->current_tx_rate <=_NSS2_MCS9_RATE_)) && + priv->pshare->rf_ft_var.Nsnding3SS && (GET_CHIP_VER(priv)== VERSION_8812E) ) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT2SS 0-9 Not sounding!!\n", __FUNCTION__)); + } + else +#endif + +/* +#ifdef CONFIG_WLAN_HAL_8192EE + if(((pEntry->pSTA->current_tx_rate >=_MCS8_RATE_) && (pEntry->pSTA->current_tx_rate <=_MCS15_RATE_)) && + priv->pshare->rf_ft_var.Nsnding3SS && (GET_CHIP_VER(priv)== VERSION_8192E) ) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, HT MCS 8-15 Not sounding!!\n", __FUNCTION__)); + } + else + +#endif +*/ + { + if(priv->pshare->rf_ft_var.ndpaaid != 0xff) + ret = SendVHTNDPAPacket(priv,RA, priv->pshare->rf_ft_var.ndpaaid, BW, NDPTxRate); + else + ret = SendVHTNDPAPacket(priv,RA, pEntry->AID, BW, NDPTxRate); + } + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT NDP Rate = %d\n", __FUNCTION__, NDPTxRate)); + } + + if(ret == FALSE) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Beamforming_RemoveEntry because of failure sending NDPA for addr =\n", __FUNCTION__)); +// Beamforming_RemoveEntry(priv, RA, &Idx); + Beamforming_Leave(priv, RA); +// pBeamformingInfo->bBeamformingInProgress = FALSE; + pEntry->bBeamformingInProgress = FALSE; + return FALSE; + } + + return TRUE; +} + + +VOID +Beamforming_Notify( + struct rtl8192cd_priv *priv + ) +{ + u1Byte Idx=BEAMFORMEE_ENTRY_NUM; + BEAMFORMING_NOTIFY_STATE bSounding = BEAMFORMING_NOTIFY_NONE; + PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo); + PRT_BEAMFORMING_TIMER_INFO pBeamTimerInfo = NULL; + + bSounding = beamfomring_bSounding(pBeamInfo, &Idx); + + if(IdxBeamformingTimerInfo[Idx]); + else if(bSounding == BEAMFORMING_NOTIFY_RESET) + pBeamTimerInfo = &(pBeamInfo->BeamformingTimerInfo[0]); + + if(pBeamInfo->BeamformState == BEAMFORMING_STATE_END) + { + if(bSounding==BEAMFORMING_NOTIFY_ADD) + { + beamforming_StartPeriod(priv, Idx); + pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee; + } + } + else if(pBeamInfo->BeamformState == BEAMFORMING_STATE_START_1BFee) + { + if(bSounding==BEAMFORMING_NOTIFY_ADD) + { + beamforming_StartPeriod(priv, Idx); + pBeamInfo->BeamformState = BEAMFORMING_STATE_START_2BFee; + } + else if(bSounding == BEAMFORMING_NOTIFY_DELETE) + { + if(pBeamTimerInfo->Mode == SOUNDING_FW_HT_TIMER || pBeamTimerInfo->Mode == SOUNDING_FW_VHT_TIMER) + { + beamforming_EndPeriod_FW(priv, Idx); + beamforming_ClearEntry_FW(priv, TRUE, Idx); + } + else + { + beamforming_EndPeriod_SW(priv, Idx); + beamforming_ClearEntry_SW(priv, TRUE, Idx); + } + + pBeamInfo->BeamformState = BEAMFORMING_STATE_END; + } + else if(bSounding == BEAMFORMING_NOTIFY_RESET) + { + if(pBeamTimerInfo->Mode == SOUNDING_FW_HT_TIMER || pBeamTimerInfo->Mode == SOUNDING_FW_VHT_TIMER) + { + beamforming_EndPeriod_FW(priv, Idx); + beamforming_ClearEntry_FW(priv, FALSE, Idx); + } + else + { + beamforming_EndPeriod_SW(priv, Idx); + beamforming_ClearEntry_SW(priv, FALSE, Idx); + } + + pBeamInfo->BeamformState = BEAMFORMING_STATE_END; + } + } + else if(pBeamInfo->BeamformState == BEAMFORMING_STATE_START_2BFee) + { + if(bSounding == BEAMFORMING_NOTIFY_ADD) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, should be block\n", __FUNCTION__)); + + } + else if(bSounding == BEAMFORMING_NOTIFY_DELETE) + { + if(pBeamTimerInfo->Mode == SOUNDING_FW_HT_TIMER || pBeamTimerInfo->Mode == SOUNDING_FW_VHT_TIMER) + { + beamforming_EndPeriod_FW(priv, Idx); + beamforming_ClearEntry_FW(priv, TRUE, Idx); + } + else + { + // For 2->1 entry, we should not cancel SW timer + beamforming_ClearEntry_SW(priv, TRUE, Idx); + } + + pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee; + } + else if(bSounding == BEAMFORMING_NOTIFY_RESET) + { + if(pBeamTimerInfo->Mode == SOUNDING_FW_HT_TIMER || pBeamTimerInfo->Mode == SOUNDING_FW_VHT_TIMER) + { + beamforming_EndPeriod_FW(priv, Idx); + beamforming_ClearEntry_FW(priv, FALSE, Idx); + } + else + { + beamforming_EndPeriod_SW(priv, Idx); + beamforming_ClearEntry_SW(priv, FALSE, Idx); + } + + pBeamInfo->BeamformState = BEAMFORMING_STATE_END; + } + } + +} + + +VOID +Beamforming_AutoTest( + struct rtl8192cd_priv *priv, + u1Byte Idx, + PRT_BEAMFORMING_ENTRY pBeamformEntry + ) +{ + SOUNDING_MODE Mode; + + BEAMFORMING_CAP BeamformCap = pBeamformEntry->BeamformEntryCap; + PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo); + PRT_BEAMFORMING_PERIOD_INFO pBeamPeriodInfo = &(pBeamInfo->BeamformingPeriodInfo); + + if(BeamformCap & BEAMFORMER_CAP_VHT_SU) + Mode = SOUNDING_SW_VHT_TIMER; + else if(BeamformCap & BEAMFORMER_CAP_HT_EXPLICIT) + { + Mode = SOUNDING_SW_HT_TIMER; // use sw timer for all IC + +/*#ifdef CONFIG_WLAN_HAL_8192EE + if(GET_CHIP_VER(priv)== VERSION_8192E) + Mode = SOUNDING_SW_HT_TIMER; +#endif +#ifdef CONFIG_RTL_8812_SUPPORT + if(GET_CHIP_VER(priv)== VERSION_8812E) + Mode = SOUNDING_HW_HT_TIMER; +#endif +#ifdef CONFIG_WLAN_HAL_8814AE + if(GET_CHIP_VER(priv)== VERSION_8814A) + Mode = SOUNDING_HW_HT_TIMER; +#endif*/ + } + else + return; + + pBeamPeriodInfo->Idx = Idx; + pBeamPeriodInfo->Mode = Mode; + pBeamPeriodInfo->BW = pBeamformEntry->BW; + + pBeamPeriodInfo->BeamPeriod = priv->pshare->rf_ft_var.soundingPeriod; + + +} + + +VOID +Beamforming_End( + struct rtl8192cd_priv *priv, + BOOLEAN Status + ) +{ + + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + PRT_BEAMFORMING_ENTRY pBFeeEntry = &(pBeamformingInfo->BeamformeeEntry[pBeamformingInfo->BeamformeeCurIdx]); + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BeamformEntryState=%d, pBFeeEntry->bUsed=%d\n", + __FUNCTION__, + pBFeeEntry->BeamformEntryState, + pBFeeEntry->bUsed + )); + + if((pBFeeEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSING)||(pBFeeEntry->bUsed==0)) + { + return; + } + + // Because in this case 8814A STOP sounding @BeamformingStart_V2 , so NOT apply V-matrix here. + if(((pBFeeEntry->pSTA->current_tx_rate >=_NSS3_MCS7_RATE_) && (pBFeeEntry->pSTA->current_tx_rate <=_NSS3_MCS9_RATE_)) && + priv->pshare->rf_ft_var.Nsnding3SS) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT3SS 7,8,9, do not apply V matrix.\n", __FUNCTION__)); + pBFeeEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED; + Beamforming_SetBeamFormStatus(priv, (pBeamformingInfo->BeamformeeCurIdx)); + } + else if(Status == 1) // Receive CSI successful + { + pBFeeEntry->LogStatusFailCnt = 0; + pBFeeEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSED; + Beamforming_SetBeamFormStatus(priv, (pBeamformingInfo->BeamformeeCurIdx)); + } + else // Receive CSI failure + { + pBFeeEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED; + pBFeeEntry->LogStatusFailCnt++; + } + + pBFeeEntry->bBeamformingInProgress = FALSE; + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, pEntry->LogStatusFailCnt : %d\n", __FUNCTION__, pBFeeEntry->LogStatusFailCnt)); + + // Receive CSI failure + if(pBFeeEntry->LogStatusFailCnt > 50) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, LogStatusFailCnt > 50\n", __FUNCTION__)); + + pBeamformingInfo->CurDelBFerBFeeEntrySel = BFeeEntry; + if(Beamforming_DeInitEntry(priv, pBFeeEntry->MacAddr)) + Beamforming_Notify(priv); + } + +} + +int shortenSoundingPeriod(struct rtl8192cd_priv *priv) +{ + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + PRT_BEAMFORMING_ENTRY pEntry = &(pBeamformingInfo->BeamformeeEntry[0]); + struct stat_info *pstat; + struct rtl8192cd_priv *vxd_priv; + u4Byte idx, j, ret=0; + pBeamformingInfo->BeamformingPeriodState = 0; // + + for(idx=0 ; idxBeamformeeEntry[idx]); + if( pEntry->bUsed) + { + pstat = get_stainfo(priv, pEntry->MacAddr); + if(pstat) + { + if(pstat->tx_avarage > (1<<16))//0.5Mbps + { + ++ret; + if(idx == 0) // + pBeamformingInfo->BeamformingPeriodState+=1; // entry 0 only = 1 + else // entry 1 only = 2 + pBeamformingInfo->BeamformingPeriodState+=2; // entry 0 and 1 = 3 + } + } + +#ifdef MBSSID + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->miscEntry.vap_enable) + { + for (j=0; jpvap_priv[j]->assoc_num > 0) && IS_DRV_OPEN(priv->pvap_priv[j])) + { + pstat = get_stainfo(priv->pvap_priv[j], pEntry->MacAddr); + if(pstat) + { + if(pstat->tx_avarage > (1<<16)) // 0.5Mbps + ++ret; + } + } + } + } +#endif +#ifdef UNIVERSAL_REPEATER + vxd_priv = GET_VXD_PRIV(priv); + if((OPMODE & WIFI_STATION_STATE) && (vxd_priv->assoc_num > 0) && IS_DRV_OPEN(vxd_priv) ) + { + pstat = get_stainfo(vxd_priv, pEntry->MacAddr); + if(pstat) + { + if(pstat->tx_avarage > (1<<16)) // 0.5Mbps + ++ret; + } + } +#endif + + } + } + //panic_printk("BeamformPeriodState = %d\n", pBeamformingInfo->BeamformingPeriodState); + return ret; +} + +u1Byte +getBFeeStaNum( + struct rtl8192cd_priv *priv + ) +{ + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + int idx; + u1Byte BFee_STA_Num = 0; + for(idx=0 ; idxBeamformeeEntry[idx].bUsed) + BFee_STA_Num++; + } + return BFee_STA_Num; +} + + +VOID +Beamforming_TimerCallback( + struct rtl8192cd_priv *priv + ) +{ + BOOLEAN ret = FALSE;//, timer_set=FALSE; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + int idx = pBeamformingInfo->BeamformeeCurIdx; + PRT_BEAMFORMING_ENTRY pEntry = &(pBeamformingInfo->BeamformeeEntry[idx]); + PRT_BEAMFORMING_TIMER_INFO pBeamformingTimerInfo = &(pBeamformingInfo->BeamformingTimerInfo[idx]); + u1Byte BFee_STA_Num = 0; + u1Byte index = 0; + + BFee_STA_Num = getBFeeStaNum(priv); + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + +#if 0 + for(idx=0 ; idxBeamformingPeriodState == 0 || pBeamformingInfo->BeamformingPeriodState == 3) + { + if(pBeamformingInfo->BeamformeeEntry[idx^1].bUsed) + idx ^=1; + } + else if(pBeamformingInfo->BeamformingPeriodState == 2) + { + idx = 1; + } + else + idx = 0; + } + else + { + if(pBeamformingInfo->BeamformeeEntry[0].bUsed) + idx = 0; + else if(pBeamformingInfo->BeamformeeEntry[1].bUsed) + idx = 1; + } + + pBeamformingInfo->BeamformeeCurIdx = idx; +#endif + pEntry = &(pBeamformingInfo->BeamformeeEntry[idx]); + pBeamformingTimerInfo = &(pBeamformingInfo->BeamformingTimerInfo[idx]); + + if(pEntry->bBeamformingInProgress) + { + Beamforming_End(priv, 0); + } + if( pEntry->bUsed) + { + ret = BeamformingStart_V2( priv, idx, pBeamformingTimerInfo->Mode, pEntry->BW); + + } + +// if(ret && !timer_set) +// if(ret) + if(pBeamformingInfo->BeamformeeEntry[0].bUsed || pBeamformingInfo->BeamformeeEntry[1].bUsed) + { + if(pBeamformingInfo->BeamformState >= BEAMFORMING_STATE_START_1BFee) + { + if(pBeamformingTimerInfo->Mode == SOUNDING_SW_VHT_TIMER || pBeamformingTimerInfo->Mode == SOUNDING_SW_HT_TIMER) + { + if(shortenSoundingPeriod(priv)){ + if(pBeamformingInfo->BeamformingPeriodState == 1 || pBeamformingInfo->BeamformingPeriodState == 2) + { + ODM_SetTimer(ODMPTR, &pBeamformingInfo->BeamformingTimer, pBeamformingTimerInfo->BeamPeriod/100); + } + else // pBeamformingInfo->BeamformingPeriodState == 3 + { + ODM_SetTimer(ODMPTR, &pBeamformingInfo->BeamformingTimer, pBeamformingTimerInfo->BeamPeriod/200); + } + } + else + { + ODM_SetTimer(ODMPTR, &pBeamformingInfo->BeamformingTimer, pBeamformingTimerInfo->BeamPeriod); + } + } + else + { + int BeamPeriod = priv->pshare->rf_ft_var.soundingPeriod; + + if(pBeamformingTimerInfo->Mode == SOUNDING_HW_VHT_TIMER || pBeamformingTimerInfo->Mode == SOUNDING_HW_HT_TIMER) + BeamPeriod *=32; //HW timer, clock = 32K + + if(shortenSoundingPeriod(priv)) + { + if(pBeamformingInfo->BeamformingPeriodState == 1 || pBeamformingInfo->BeamformingPeriodState == 2) //only one entry is in used + BeamPeriod /= 100; + else //two entries are in used + BeamPeriod /= 200; + } + + if(pBeamformingTimerInfo->BeamPeriod != BeamPeriod) + { + pBeamformingTimerInfo->BeamPeriod = BeamPeriod; + } + Beamforming_SetHWTimer(priv, pBeamformingTimerInfo->BeamPeriod); + } +// timer_set = 1; + } + } + + + } + +} + +VOID Beamforming_SWTimerCallback(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + Beamforming_TimerCallback(priv); +// mod_timer(&priv->txbf_swtimer, jiffies + priv->pshare->rf_ft_var.soundingPeriod); +} + +VOID +Beamforming_Init( + struct rtl8192cd_priv *priv + ) +{ + PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo); + PRT_BEAMFORMING_PERIOD_INFO pBeamPeriodInfo = &(pBeamInfo->BeamformingPeriodInfo); + + pBeamInfo->BeamformingPeriodState = 0; + pBeamPeriodInfo->Mode = SOUNDING_STOP_OID_TIMER; + + init_timer(&pBeamInfo->BeamformingTimer); + pBeamInfo->BeamformingTimer.function = Beamforming_SWTimerCallback; + pBeamInfo->BeamformingTimer.data = (unsigned long)priv; +} + +VOID +Beamforming_Release( + struct rtl8192cd_priv *priv + ) +{ + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + ODM_CancelTimer(ODMPTR, &pBeamformingInfo->BeamformingTimer); +} + + + +VOID +Beamforming_Enter( + struct rtl8192cd_priv *priv, + struct stat_info *pstat +) +{ + u1Byte BFerBFeeIdx = 0xff; + if(Beamforming_InitEntry(priv, pstat, &BFerBFeeIdx)) + { + Beamforming_SetBeamFormEnter(priv, BFerBFeeIdx); + } +} + + +VOID +Beamforming_Leave( + struct rtl8192cd_priv *priv, + pu1Byte RA + ) +{ + u1Byte Idx = 0; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + Beamforming_GetBFeeEntryByAddr(priv, RA, &Idx); + + if(RA == NULL) + { + BeamformingReset(priv); + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Reset entry\n", __FUNCTION__)); + } + else + { + pBeamformingInfo->CurDelBFerBFeeEntrySel = BFerBFeeEntry; + Beamforming_DeInitEntry(priv, RA); + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, DeInit entry %d\n", __FUNCTION__, Idx)); + } + + Beamforming_Notify(priv); + +} + + +VOID +Beamforming_SetTxBFen( + struct rtl8192cd_priv *priv, + u1Byte MacId, + BOOLEAN bTxBF + ) +{ + u1Byte Idx = 0; +// PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + PRT_BEAMFORMING_ENTRY pEntry; + + pEntry = Beamforming_GetEntryByMacId(priv, MacId, &Idx); + + if(pEntry == NULL) + return; + else + pEntry->bTxBF = bTxBF; + + Beamforming_Notify(priv); +} + +BEAMFORMING_CAP +Beamforming_GetBeamCap( + IN PRT_BEAMFORMING_INFO pBeamInfo + ) +{ + u1Byte i; + BOOLEAN bSelfBeamformer = FALSE; + BOOLEAN bSelfBeamformee = FALSE; + RT_BEAMFORMING_ENTRY BeamformeeEntry; + RT_BEAMFORMER_ENTRY BeamformerEntry; + BEAMFORMING_CAP BeamformCap = BEAMFORMING_CAP_NONE; + + /* + for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) + { + BeamformEntry = pBeamInfo->BeamformeeEntry[i]; + + if(BeamformEntry.bUsed) + { + if( (BeamformEntry.BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU) || + (BeamformEntry.BeamformEntryCap & BEAMFORMEE_CAP_HT_EXPLICIT)) + bSelfBeamformee = TRUE; + if( (BeamformEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU) || + (BeamformEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)) + bSelfBeamformer = TRUE; + } + + if(bSelfBeamformer && bSelfBeamformee) + i = BEAMFORMEE_ENTRY_NUM; + } + */ + + for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) + { + BeamformeeEntry = pBeamInfo->BeamformeeEntry[i]; + + if(BeamformeeEntry.bUsed) + { + bSelfBeamformer = TRUE; + //panic_printk("[Beamform]%s, BFee entry %d bUsed=TRUE\n", __FUNCTION__, i); + } + } + + for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++) + { + BeamformerEntry = pBeamInfo->BeamformerEntry[i]; + + if(BeamformerEntry.bUsed) + { + bSelfBeamformee = TRUE; + //panic_printk"[Beamform]%s, BFer entry %d bUsed=TRUE\n", __FUNCTION__, i); + } + } + + if(bSelfBeamformer) + BeamformCap |= BEAMFORMER_CAP; + if(bSelfBeamformee) + BeamformCap |= BEAMFORMEE_CAP; + + return BeamformCap; +} + +VOID +Beamforming_GetNDPAFrame( + struct rtl8192cd_priv *priv, + pu1Byte pNDPAFrame + ) +{ + pu1Byte TA ; + u1Byte Idx, Sequence; + PRT_BEAMFORMER_ENTRY pBeamformerEntry = NULL; + PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo); + + if (GET_CHIP_VER(priv) != VERSION_8812E) + return; + if(IsCtrlNDPA(pNDPAFrame) == FALSE) + return; + + TA = GetAddr2Ptr(pNDPAFrame); + // Remove signaling TA. + TA[0] = TA[0] & 0xFE; + + pBeamformerEntry = Beamforming_GetBFerEntryByAddr(priv, TA, &Idx); + + if(pBeamformerEntry == NULL) + return; + else if(!(pBeamformerEntry->BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU)) + return; + + // NDPALogSuccess: As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is NO LONGER needed !2015-04-10, Jeffery + // ClockResetTimes: While BFer entry always doesn't receive our CSI, clock will reset again and again.So ClockResetTimes is limited to 5 times.2015-04-13, Jeffery + else if( pBeamformerEntry->NDPALogSuccess==1 ) + { + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s ,ClockResetTimes=%d, NDPALogSuccess=%d, clock reset is no longer needed!!\n", + __FUNCTION__, + pBeamformerEntry->ClockResetTimes, + pBeamformerEntry->NDPALogSuccess)); + + return; + } + else if( pBeamformerEntry->ClockResetTimes==3 ) + { + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s ,ClockResetTimes=%d, NDPALogSuccess=%d, DeInit BFer Entry !!\n", + __FUNCTION__, + pBeamformerEntry->ClockResetTimes, + pBeamformerEntry->NDPALogSuccess)); + pBeamformingInfo->CurDelBFerBFeeEntrySel = BFerEntry ; + Beamforming_DeInitEntry(priv, pBeamformerEntry->MacAddr); + return; + } + + Sequence = (pNDPAFrame[16]) >> 2; + + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s Start, Sequence=%d, NDPALogSeq=%d, NDPAPreLogSeq=%d, NDPALogRetryCnt=%d, ClockResetTimes=%d, NDPALogSuccess=%d\n", + __FUNCTION__, + Sequence, + pBeamformerEntry->NDPALogSeq, + pBeamformerEntry->NDPAPreLogSeq, + pBeamformerEntry->NDPALogRetryCnt, + pBeamformerEntry->ClockResetTimes, + pBeamformerEntry->NDPALogSuccess)); + + if ((pBeamformerEntry->NDPALogSeq != 0) && (pBeamformerEntry->NDPAPreLogSeq != 0)) + { + //2 Success Condition + if( (pBeamformerEntry->NDPALogSeq!=Sequence)&&(pBeamformerEntry->NDPALogSeq!=pBeamformerEntry->NDPAPreLogSeq) ) + { + /* break option for clcok reset, 2015-03-30, Jeffery */ + pBeamformerEntry->NDPALogRetryCnt = 0; + + /*As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is no longer needed.*/ + /*That is, NDPALogSuccess is NOT needed to be reset to zero, 2015-04-13, Jeffery*/ + pBeamformerEntry->NDPALogSuccess=1; + } + + //2 Fail Condition + else + { + + if (pBeamformerEntry->NDPALogRetryCnt == 5) + { + + pBeamformerEntry->ClockResetTimes++; + pBeamformerEntry->NDPALogRetryCnt = 0; + + watchdog_kick(); + ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s ,Clock Reset!!! ClockResetTimes=%d\n", + __FUNCTION__, + pBeamformerEntry->ClockResetTimes)); + +#ifdef CONFIG_RTL_8812_SUPPORT + _Beamforming_CLK(priv); +#endif + } + else + pBeamformerEntry->NDPALogRetryCnt++; + } + } + + pBeamformerEntry->NDPAPreLogSeq = pBeamformerEntry->NDPALogSeq; + pBeamformerEntry->NDPALogSeq = Sequence; + +} + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Beamforming.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Beamforming.h new file mode 100755 index 000000000..332082e37 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Beamforming.h @@ -0,0 +1,128 @@ +#ifdef BEAMFORMING_SUPPORT + +#define TxBF_Nr(a,b) ((a>b) ? (b) : (a)) + +u1Byte +Beamforming_GetHTNDPTxRate( + struct rtl8192cd_priv *priv, + u1Byte CompSteeringNumofBFer +); + +u1Byte +Beamforming_GetVHTNDPTxRate( + struct rtl8192cd_priv *priv, + u1Byte CompSteeringNumofBFer +); + +VOID +Beamforming_GidPAid( + struct rtl8192cd_priv *priv, + struct stat_info *pstat +); + +enum _BEAMFORMING_CAP + +Beamforming_GetEntryBeamCapByMacId( + struct rtl8192cd_priv *priv, + IN u1Byte MacId +); + +BOOLEAN +Beamforming_InitEntry( + struct rtl8192cd_priv *priv, + struct stat_info *pSTA, + pu1Byte Idx +); + +BOOLEAN +Beamforming_DeInitEntry( + struct rtl8192cd_priv *priv, + pu1Byte RA +); + +VOID +Beamforming_Notify( + struct rtl8192cd_priv *priv +); + +VOID +Beamforming_Enter( + struct rtl8192cd_priv *priv, + struct stat_info *pstat +); + +VOID +Beamforming_TimerCallback( + struct rtl8192cd_priv *priv +); + +VOID +Beamforming_AutoTest( + struct rtl8192cd_priv *priv, + u1Byte Idx, + struct _RT_BEAMFORMING_ENTRY *pBeamformEntry +); + +VOID +Beamforming_End( + struct rtl8192cd_priv *priv, + BOOLEAN Status +); + +VOID +Beamforming_Leave( + struct rtl8192cd_priv *priv, + pu1Byte RA +); +VOID +Beamforming_Release( + struct rtl8192cd_priv *priv +); + +BEAMFORMING_CAP +Beamforming_GetBeamCap( + IN PRT_BEAMFORMING_INFO pBeamInfo +); + +VOID +Beamforming_Init( + struct rtl8192cd_priv *priv +); + +VOID +Beamforming_SetTxBFen( + struct rtl8192cd_priv *priv, + u1Byte MacId, + BOOLEAN bTxBF +); + +PRT_BEAMFORMING_ENTRY +Beamforming_GetEntryByMacId( + struct rtl8192cd_priv *priv, + u1Byte MacId, + pu1Byte Idx + ); + +PRT_BEAMFORMING_ENTRY +Beamforming_GetFreeBFeeEntry( + struct rtl8192cd_priv *priv, + pu1Byte Idx, + pu1Byte RA + ); + +PRT_BEAMFORMER_ENTRY +Beamforming_GetFreeBFerEntry( + struct rtl8192cd_priv *priv, + OUT pu1Byte Idx, + pu1Byte RA + ); + +VOID +Beamforming_GetNDPAFrame( + struct rtl8192cd_priv *priv, + pu1Byte pNDPAFrame + ); + + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Config.in b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Config.in new file mode 100755 index 000000000..08d47796e --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Config.in @@ -0,0 +1,31 @@ +# +# Wireless LAN device configuration +# + +tristate ' RTL8192C/D 802.11b/g/n support' CONFIG_RTL8192CD + +if [ "$CONFIG_RTL8192CD" != "n" ]; then + bool ' Private skb buffer management' CONFIG_RTL8190_PRIV_SKB + bool ' WAPI support' CONFIG_RTL_WAPI_SUPPORT + if [ "$CONFIG_RTL_WAPI_SUPPORT" = "y" ]; then + bool ' support local AS' CONFIG_RTL_WAPI_LOCAL_AS_SUPPORT + #bool ' enable WAPI module' CONFIG_RTL_WAPI_MODULE_SUPPORT + #bool ' dynamic IRAM mapping for WAPI' CONFIG_RTL_DYNAMIC_IRAM_MAPPING_FOR_WAPI + fi + bool ' Client Mode support' CONFIG_RTL_CLIENT_MODE_SUPPORT + if [ "$CONFIG_RTL_CLIENT_MODE_SUPPORT" = "y" ]; then + bool ' Repeater Mode support' CONFIG_RTL_REPEATER_MODE_SUPPORT +fi + bool ' Mesh Mode support' CONFIG_MESH_ENABLE + if [ "$CONFIG_MESH_ENABLE" = "y" ]; then + dep_bool ' Enable Mesh NMS' CONFIG_NMS $CONFIG_MESH_ENABLE + # bool 'Test Package(netperf, test_traffic ...)' CONFIG_TEST_PKG + # bool 'Enable 11s Test Mode' CONFIG_11S_TEST_MODE + fi + bool ' WDS Support' CONFIG_RTL_WDS_SUPPORT + bool ' Virtual AP Support' CONFIG_RTL_VAP_SUPPORT + bool ' Efuse Support' CONFIG_ENABLE_EFUSE + bool ' Config File support' CONFIG_RTL_COMAPI_CFGFILE + dep_bool ' Wireless Tools v29 support' CONFIG_RTL_COMAPI_WLTOOLS $CONFIG_WIRELESS_EXT_V18 +fi + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/EdcaTurboCheck.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/EdcaTurboCheck.c new file mode 100755 index 000000000..aba0e5ed5 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/EdcaTurboCheck.c @@ -0,0 +1,916 @@ +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_util.h" + +void EdcaParaInit( + struct rtl8192cd_priv *priv + ) +{ + int mode=priv->pmib->dot11BssType.net_work_type; + + static unsigned int slot_time, sifs_time; + struct ParaRecord EDCA[4]; + + memset(EDCA, 0, 4*sizeof(struct ParaRecord)); + + sifs_time = 10; + slot_time = 20; + + if (mode & (WIRELESS_11N)) + sifs_time = 16; + + if (mode & (WIRELESS_11N| WIRELESS_11G|WIRELESS_11A)) + slot_time = 9; + + +#ifdef RTK_AC_SUPPORT //for 11ac logo, edit aifs time for cca test cases + if(AC_SIGMA_MODE != AC_SIGMA_NONE) + sifs_time = 10; +#endif + + +#if(defined(RTL_MANUAL_EDCA)) + if( priv->pmib->dot11QosEntry.ManualEDCA ) { + if( OPMODE & WIFI_AP_STATE ) + memcpy(EDCA, priv->pmib->dot11QosEntry.AP_manualEDCA, 4*sizeof(struct ParaRecord)); + else + memcpy(EDCA, priv->pmib->dot11QosEntry.STA_manualEDCA, 4*sizeof(struct ParaRecord)); + + #ifdef WIFI_WMM + if (QOS_ENABLE) + RTL_W32(0x504, (EDCA[VI].TXOPlimit<< 16) | (EDCA[VI].ECWmax<< 12) | (EDCA[VI].ECWmin<< 8) | (sifs_time + EDCA[VI].AIFSN* slot_time)); + else + #endif + RTL_W32(0x504, (EDCA[BE].TXOPlimit<< 16) | (EDCA[BE].ECWmax<< 12) | (EDCA[BE].ECWmin<< 8) | (sifs_time + EDCA[VI].AIFSN* slot_time)); + + }else + #endif //RTL_MANUAL_EDCA + { + + if(OPMODE & WIFI_AP_STATE) + { + memcpy(EDCA, rtl_ap_EDCA, 2*sizeof(struct ParaRecord)); + + if(mode & (WIRELESS_11A|WIRELESS_11G|WIRELESS_11N)) + memcpy(&EDCA[VI], &rtl_ap_EDCA[VI_AG], 2*sizeof(struct ParaRecord)); + else + memcpy(&EDCA[VI], &rtl_ap_EDCA[VI], 2*sizeof(struct ParaRecord)); + } + else + { + memcpy(EDCA, rtl_sta_EDCA, 2*sizeof(struct ParaRecord)); + + if(mode & (WIRELESS_11A|WIRELESS_11G|WIRELESS_11N)) + memcpy(&EDCA[VI], &rtl_sta_EDCA[VI_AG], 2*sizeof(struct ParaRecord)); + else + memcpy(&EDCA[VI], &rtl_sta_EDCA[VI], 2*sizeof(struct ParaRecord)); + } + + #ifdef WIFI_WMM + if (QOS_ENABLE) + RTL_W32(0x504, (EDCA[VI].TXOPlimit<< 16) | (EDCA[VI].ECWmax<< 12) | (EDCA[VI].ECWmin<< 8) | (sifs_time + EDCA[VI].AIFSN* slot_time)); + else + #endif + + RTL_W32(0x504, (EDCA[BK].ECWmax<< 12) | (EDCA[BK].ECWmin<< 8) | (sifs_time + EDCA[VI].AIFSN* slot_time)); + + + } + + RTL_W32(0x500, (EDCA[VO].TXOPlimit<< 16) | (EDCA[VO].ECWmax<< 12) | (EDCA[VO].ECWmin<< 8) | (sifs_time + EDCA[VO].AIFSN* slot_time)); + RTL_W32(0x508, (EDCA[BE].TXOPlimit<< 16) | (EDCA[BE].ECWmax<< 12) | (EDCA[BE].ECWmin<< 8) | (sifs_time + EDCA[BE].AIFSN* slot_time)); + RTL_W32(0x50C, (EDCA[BK].TXOPlimit<< 16) | (EDCA[BK].ECWmax<< 12) | (EDCA[BK].ECWmin<< 8) | (sifs_time + EDCA[BK].AIFSN* slot_time)); + +#if defined(RTK_AC_SUPPORT) && defined(RTL_MANUAL_EDCA) //for 11ac logo, make BK worse to seperate with BE. + if((AC_SIGMA_MODE != AC_SIGMA_NONE) && (priv->pmib->dot11QosEntry.ManualEDCA)) + { + RTL_W32(0x50C, (EDCA[BK].TXOPlimit<< 16) | (EDCA[BK].ECWmax<< 12) | (EDCA[BK].ECWmin<< 8) | 0xa4 ); + } +#endif + +// ODM_Write1Byte(pDM_Odm,ACMHWCTRL, 0x00); + + priv->pshare->iot_mode_enable = 0; + + if (priv->pshare->rf_ft_var.wifi_beq_iot) + priv->pshare->iot_mode_VI_exist = 0; + + #ifdef WMM_VIBE_PRI + priv->pshare->iot_mode_BE_exist = 0; + #endif + +#ifdef WMM_BEBK_PRI + priv->pshare->iot_mode_BK_exist = 0; +#endif + + #ifdef LOW_TP_TXOP + priv->pshare->BE_cwmax_enhance = 0; + #endif + + + priv->pshare->iot_mode_VO_exist = 0; +} + +BOOLEAN +ChooseIotMainSTA( + struct rtl8192cd_priv *priv, + IN PSTA_INFO_T pstat + ) +{ + BOOLEAN bhighTP_found_pstat=FALSE; + + if ((GET_ROOT(priv)->up_time % 2) == 0) { + unsigned int tx_2s_avg = 0; + unsigned int rx_2s_avg = 0; + int i=0, aggReady=0; + unsigned long total_sum = (priv->pshare->current_tx_bytes+priv->pshare->current_rx_bytes); + int assoc_num = GET_ROOT(priv)->assoc_num; +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable){ + for (i=0; ipvap_priv[i]-> assoc_num; + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(GET_ROOT(priv)))) + assoc_num += GET_VXD_PRIV(GET_ROOT(priv))-> assoc_num; +#endif +#ifdef WDS + if(GET_ROOT(priv)->pmib->dot11WdsInfo.wdsEnabled) + assoc_num ++; +#endif + + + pstat->current_tx_bytes += pstat->tx_byte_cnt; + pstat->current_rx_bytes += pstat->rx_byte_cnt; + + if (total_sum != 0) { + if (total_sum <= 1000000) { + tx_2s_avg = (unsigned int)((pstat->current_tx_bytes*100) / total_sum); + rx_2s_avg = (unsigned int)((pstat->current_rx_bytes*100) / total_sum); + } else { + tx_2s_avg = (unsigned int)(pstat->current_tx_bytes / (total_sum / 100)); + rx_2s_avg = (unsigned int)(pstat->current_rx_bytes / (total_sum / 100)); + } + + } + + for(i=0; i<8; i++) + aggReady += (pstat->ADDBA_ready[i]); + + if ((pstat->ht_cap_len && ( +#ifdef SUPPORT_TX_AMSDU + AMSDU_ENABLE || +#endif + aggReady)) || (pstat->IOTPeer==HT_IOT_PEER_INTEL) || (tx_2s_avg >= 50)) + { + if ((assoc_num==1) || (tx_2s_avg + rx_2s_avg >= 25)) { + priv->pshare->highTP_found_pstat = pstat; + } + + #ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { + if ((tx_2s_avg + rx_2s_avg) >= 20) + priv->pshare->highTP_found_pstat = pstat; + } + #endif + } + + } + else { + pstat->current_tx_bytes = pstat->tx_byte_cnt; + pstat->current_rx_bytes = pstat->rx_byte_cnt; + } + + return bhighTP_found_pstat; +} + + +#ifdef WIFI_WMM +VOID +IotEdcaSwitch( + struct rtl8192cd_priv *priv, + IN unsigned char enable + ) +{ + int mode=priv->pmib->dot11BssType.net_work_type; + unsigned int slot_time = 20, sifs_time = 10, BE_TXOP = 47, VI_TXOP = 94; + unsigned int vi_cw_max = 4, vi_cw_min = 3, vi_aifs; +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + u32 be_edca, vi_edca; +#endif + + if (!(!priv->pmib->dot11OperationEntry.wifi_specific || + ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific)) + #ifdef CLIENT_MODE + || ((OPMODE & WIFI_STATION_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific)) + #endif + )) + return; + + +#ifdef RTK_AC_SUPPORT //for 11ac logo, do not dynamic switch edca + if(AC_SIGMA_MODE != AC_SIGMA_NONE) + return; +#endif + + if ((mode & WIRELESS_11N) && (priv->pshare->ht_sta_num + #ifdef WDS + || ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum) + #endif + )) + sifs_time = 16; + + if (mode & (WIRELESS_11N|WIRELESS_11G|WIRELESS_11A)) { + slot_time = 9; + } + else + { + BE_TXOP = 94; + VI_TXOP = 188; + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = -1; + vi_edca = -1; +#endif + + + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11OperationEntry.wifi_specific) { + if (priv->pshare->iot_mode_VO_exist) { + #ifdef WMM_VIBE_PRI + if (priv->pshare->iot_mode_BE_exist) + { + vi_cw_max = 5; + vi_cw_min = 3; + vi_aifs = (sifs_time + ((OPMODE & WIFI_AP_STATE)?1:2) * slot_time); + } + else + #endif + { + vi_cw_max = 6; + vi_cw_min = 4; + vi_aifs = 0x2b; + } + } + else { + vi_aifs = (sifs_time + ((OPMODE & WIFI_AP_STATE)?1:2) * slot_time); + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + vi_edca = ((VI_TXOP*(1-priv->pshare->iot_mode_VO_exist)) << 16) + | (vi_cw_max << 12) | (vi_cw_min << 8) | vi_aifs; +#else + RTL_W32(0x504, ((VI_TXOP*(1-priv->pshare->iot_mode_VO_exist)) << 16) + | (vi_cw_max << 12) | (vi_cw_min << 8) | vi_aifs); +#endif + + #ifdef WMM_BEBK_PRI + #ifdef CONFIG_RTL_88E_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188E) && priv->pshare->iot_mode_BK_exist) { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (10 << 12) | (6 << 8) | 0x4f; +#else + RTL_W32(0x50C, (10 << 12) | (6 << 8) | 0x4f); +#endif + } + #endif + #endif +#if defined(CONFIG_WLAN_HAL_8881A) + if (GET_CHIP_VER(priv) == VERSION_8881A) + RTL_W32(0x50C, 0xa64f); +#endif + } + + + + + + if (priv->pshare->rf_ft_var.wifi_beq_iot && priv->pshare->iot_mode_VI_exist) { +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + if (GET_CHIP_VER(priv) == VERSION_8188E || GET_CHIP_VER(priv) == VERSION_8812E) { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (10 << 12) | (6 << 8) | 0x4f; +#else + RTL_W32(0x508, (10 << 12) | (6 << 8) | 0x4f); +#endif + } + else +#endif + { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (10 << 12) | (4 << 8) | 0x4f; +#else + RTL_W32(0x508, (10 << 12) | (4 << 8) | 0x4f); +#endif + } + } else if(!enable) + { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (((OPMODE & WIFI_AP_STATE)?6:10) << 12) | (4 << 8) + | (sifs_time + 3 * slot_time); +#else + RTL_W32(0x508, (((OPMODE & WIFI_AP_STATE)?6:10) << 12) | (4 << 8) + | (sifs_time + 3 * slot_time)); +#endif +#ifdef CONFIG_PCI_HCI +// ODM_Write2Byte(pDM_Odm, RD_CTRL, ODM_Read2Byte(pDM_Odm, RD_CTRL) | (DIS_TXOP_CFE)); +#endif + } + else + { + int txop; + unsigned int cw_max; +#ifdef LOW_TP_TXOP + unsigned int txop_close; +#endif + + #if(defined LOW_TP_TXOP) + cw_max = ((priv->pshare->BE_cwmax_enhance) ? 10 : 6); + txop_close = ((priv->pshare->rf_ft_var.low_tp_txop && priv->pshare->rf_ft_var.low_tp_txop_close) ? 1 : 0); + + if(priv->pshare->txop_enlarge == 0xe) //if intel case + txop = (txop_close ? 0 : (BE_TXOP*2)); + else //if other case + txop = (txop_close ? 0: (BE_TXOP*priv->pshare->txop_enlarge)); + #else + cw_max=6; + if((priv->pshare->txop_enlarge==0xe)||(priv->pshare->txop_enlarge==0xd)) + txop=BE_TXOP*2; + else + txop=BE_TXOP*priv->pshare->txop_enlarge; + + #endif + + if (priv->pshare->ht_sta_num + #ifdef WDS + || ((OPMODE & WIFI_AP_STATE) && (mode & WIRELESS_11N) && + priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum) + #endif + ) + { + + if (priv->pshare->txop_enlarge == 0xe) { + // is intel client, use a different edca value + //ODM_Write4Byte(pDM_Odm, ODM_EDCA_BE_PARAM, (txop<< 16) | (cw_max<< 12) | (4 << 8) | 0x1f); + if (get_rf_mimo_mode(priv)==MIMO_1T1R) { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (txop << 16) | (5 << 12) | (3 << 8) | 0x1f; +#else + RTL_W32(0x508, (txop << 16) | (5 << 12) | (3 << 8) | 0x1f); +#endif + } + else { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (txop << 16) | (8 << 12) | (5 << 8) | 0x1f; +#else + RTL_W32(0x508, (txop << 16) | (8 << 12) | (5 << 8) | 0x1f); +#endif + } + +#ifdef CONFIG_PCI_HCI +// ODM_Write2Byte(pDM_Odm, RD_CTRL, ODM_Read2Byte(pDM_Odm, RD_CTRL) & ~(DIS_TXOP_CFE)); +#endif + priv->pshare->txop_enlarge = 2; + } + + #ifndef LOW_TP_TXOP + else if (priv->pshare->txop_enlarge == 0xd) { + // is intel ralink, use a different edca value +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (txop << 16) | (6 << 12) | (5 << 8) | 0x2b; +#else + RTL_W32(0x508, (txop << 16) | (6 << 12) | (5 << 8) | 0x2b); +#endif + priv->pshare->txop_enlarge = 2; + } + #endif + + else + { + if (get_rf_mimo_mode(priv)==MIMO_2T2R) { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (txop << 16) | (cw_max << 12) | (4 << 8) | (sifs_time + 3 * slot_time); +#else + RTL_W32(0x508, (txop << 16) | + (cw_max << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); +#endif + } + else + #if(DM_ODM_SUPPORT_TYPE==ODM_AP)&&(defined LOW_TP_TXOP) + { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (txop << 16) | + (((priv->pshare->BE_cwmax_enhance) ? 10 : 5) << 12) | (3 << 8) | (sifs_time + 2 * slot_time); +#else + RTL_W32(0x508, (txop << 16) | + (((priv->pshare->BE_cwmax_enhance) ? 10 : 5) << 12) | (3 << 8) | (sifs_time + 2 * slot_time)); +#endif + } + #else + { + PSTA_INFO_T pstat = priv->pshare->highTP_found_pstat; + if ((GET_CHIP_VER(priv)==VERSION_8881A) && pstat && (pstat->IOTPeer == HT_IOT_PEER_HTC)) + RTL_W32(0x508, 0x642b); + else { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (txop << 16) | (5 << 12) | (3 << 8) | (sifs_time + 2 * slot_time); +#else + RTL_W32(0x508, (txop << 16) | + (5 << 12) | (3 << 8) | (sifs_time + 2 * slot_time)); +#endif + } + } + #endif + } + } + else + { +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + be_edca = (BE_TXOP << 16) | (cw_max << 12) | (4 << 8) | (sifs_time + 3 * slot_time); +#else +#if(defined LOW_TP_TXOP) + RTL_W32(0x508, (BE_TXOP << 16) | (cw_max << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); +#endif +#endif + } + + } + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_IOT_EDCA_switch(priv, be_edca, vi_edca); +#endif +} +#endif + +VOID +IotEngine( + struct rtl8192cd_priv *priv + ) +{ + PSTA_INFO_T pstat = NULL; + u4Byte i; +#ifdef SW_TX_QUEUE + int swqd = priv->swq_decision; +#endif +#ifdef WIFI_WMM + unsigned int switch_turbo = 0, avg_tp; +#endif +//////////////////////////////////////////////////////// +// if EDCA Turbo function is not supported or Manual EDCA Setting +// then return +//////////////////////////////////////////////////////// + + +#if(defined(RTL_MANUAL_EDCA) && defined(WIFI_WMM)) + if(priv->pmib->dot11QosEntry.ManualEDCA){ + return ; + } +#endif + + pstat=priv->pshare->highTP_found_pstat; +// if(pstat) { +// if((pstat->tx_avarage + pstat->rx_avarage) < (1<<17)) // 1M bps +// pstat = NULL; +// } + +#ifdef WIFI_WMM + if (QOS_ENABLE) { + if (!priv->pmib->dot11OperationEntry.wifi_specific + ||((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific)) + ) { + if (priv->pshare->iot_mode_enable && + ((priv->pshare->phw->VO_pkt_count > 50) || + (priv->pshare->phw->VI_pkt_count > 50) || + (priv->pshare->phw->BK_pkt_count > 50))) { + priv->pshare->iot_mode_enable = 0; + switch_turbo++; +#ifdef CONFIG_WLAN_HAL_8881A + if (GET_CHIP_VER(priv) == VERSION_8881A) { + RTL_W32(0x460, 0x03086666); + } +#endif //CONFIG_WLAN_HAL_8881A + } else if ((!priv->pshare->iot_mode_enable) && + ((priv->pshare->phw->VO_pkt_count < 50) && + (priv->pshare->phw->VI_pkt_count < 50) && + (priv->pshare->phw->BK_pkt_count < 50))) { + priv->pshare->iot_mode_enable++; + switch_turbo++; +//#ifdef CONFIG_WLAN_HAL_8881A +#if 0 + if (GET_CHIP_VER(priv) == VERSION_8881A) { + if (get_bonding_type_8881A()==BOND_8881AB) { + RTL_W32(0x460, 0x03086666); + } + else { + RTL_W32(0x460, 0x0320ffff); + } + } +#endif //CONFIG_WLAN_HAL_8881A + } + } + + + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11OperationEntry.wifi_specific) + { + if (!priv->pshare->iot_mode_VO_exist && (priv->pshare->phw->VO_pkt_count > 50)) { + priv->pshare->iot_mode_VO_exist++; + switch_turbo++; + } else if (priv->pshare->iot_mode_VO_exist && (priv->pshare->phw->VO_pkt_count < 50)) { + priv->pshare->iot_mode_VO_exist = 0; + switch_turbo++; + } +#if(defined WMM_VIBE_PRI) + if (priv->pshare->iot_mode_VO_exist) { + //printk("[%s %d] BE_pkt_count=%d\n", __FUNCTION__, __LINE__, priv->pshare->phw->BE_pkt_count); + if (!priv->pshare->iot_mode_BE_exist && (priv->pshare->phw->BE_pkt_count > 250)) { + priv->pshare->iot_mode_BE_exist++; + switch_turbo++; + } else if (priv->pshare->iot_mode_BE_exist && (priv->pshare->phw->BE_pkt_count < 250)) { + priv->pshare->iot_mode_BE_exist = 0; + switch_turbo++; + } + } +#endif + +#if(defined WMM_BEBK_PRI) + if (priv->pshare->phw->BE_pkt_count) { + //printk("[%s %d] BK_pkt_count=%d\n", __FUNCTION__, __LINE__, priv->pshare->phw->BK_pkt_count); + if (!priv->pshare->iot_mode_BK_exist && (priv->pshare->phw->BK_pkt_count > 250)) { + priv->pshare->iot_mode_BK_exist++; + switch_turbo++; + } else if (priv->pshare->iot_mode_BK_exist && (priv->pshare->phw->BK_pkt_count < 250)) { + priv->pshare->iot_mode_BK_exist = 0; + switch_turbo++; + } + } +#endif + + + if (priv->pshare->rf_ft_var.wifi_beq_iot) + { + if (!priv->pshare->iot_mode_VI_exist && (priv->pshare->phw->VI_rx_pkt_count > 50)) { + priv->pshare->iot_mode_VI_exist++; + switch_turbo++; + } else if (priv->pshare->iot_mode_VI_exist && (priv->pshare->phw->VI_rx_pkt_count < 50)) { + priv->pshare->iot_mode_VI_exist = 0; + switch_turbo++; + } + } + + + } + else if (!pstat || pstat->rssi < priv->pshare->rf_ft_var.txop_enlarge_lower) { + if (priv->pshare->txop_enlarge) { + priv->pshare->txop_enlarge = 0; + if (priv->pshare->iot_mode_enable) + switch_turbo++; + } + } + +#if(defined(CLIENT_MODE) ) + if ((OPMODE & WIFI_STATION_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific)) + { + if (priv->pshare->iot_mode_enable && + (((priv->pshare->phw->VO_pkt_count > 50) || + (priv->pshare->phw->VI_pkt_count > 50) || + (priv->pshare->phw->BK_pkt_count > 50)) || + (pstat && (!pstat->ADDBA_ready[0]) & (!pstat->ADDBA_ready[3])))) + { + priv->pshare->iot_mode_enable = 0; + switch_turbo++; + } + else if ((!priv->pshare->iot_mode_enable) && + (((priv->pshare->phw->VO_pkt_count < 50) && + (priv->pshare->phw->VI_pkt_count < 50) && + (priv->pshare->phw->BK_pkt_count < 50)) && + (pstat && (pstat->ADDBA_ready[0] | pstat->ADDBA_ready[3])))) + { + priv->pshare->iot_mode_enable++; + switch_turbo++; + } + } +#endif + + priv->pshare->phw->VO_pkt_count = 0; + priv->pshare->phw->VI_pkt_count = 0; + priv->pshare->phw->BK_pkt_count = 0; + + #if(defined WMM_VIBE_PRI) + priv->pshare->phw->BE_pkt_count = 0; + #endif + + if (priv->pshare->rf_ft_var.wifi_beq_iot) + priv->pshare->phw->VI_rx_pkt_count = 0; + + } +#endif + + if ((priv->up_time % 2) == 0) { + /* + * decide EDCA content for different chip vendor + */ +#ifdef WIFI_WMM + if (QOS_ENABLE && (!priv->pmib->dot11OperationEntry.wifi_specific || + ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2)) + #ifdef CLIENT_MODE + || ((OPMODE & WIFI_STATION_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2)) + #endif + )) + + { + + if (pstat && pstat->rssi >= priv->pshare->rf_ft_var.txop_enlarge_upper) { +#ifdef LOW_TP_TXOP + if (pstat->IOTPeer==HT_IOT_PEER_INTEL) + { + if (priv->pshare->txop_enlarge != 0xe) + { + priv->pshare->txop_enlarge = 0xe; + + if (priv->pshare->iot_mode_enable) + switch_turbo++; + } + } + else if (priv->pshare->txop_enlarge != 2) + { + priv->pshare->txop_enlarge = 2; + if (priv->pshare->iot_mode_enable) + switch_turbo++; + } +#else + if (priv->pshare->txop_enlarge != 2) + { + if (pstat->IOTPeer==HT_IOT_PEER_INTEL) + priv->pshare->txop_enlarge = 0xe; + else if (pstat->IOTPeer==HT_IOT_PEER_RALINK) + priv->pshare->txop_enlarge = 0xd; + else if (pstat->IOTPeer==HT_IOT_PEER_HTC) + priv->pshare->txop_enlarge = 0; + else + priv->pshare->txop_enlarge = 2; + + if (priv->pshare->iot_mode_enable) + switch_turbo++; + } +#endif + } + else if ((!pstat || pstat->rssi < priv->pshare->rf_ft_var.txop_enlarge_lower) +#ifdef SW_TX_QUEUE + && (priv->swq_en == 0) +#endif + ) + { + if (priv->pshare->txop_enlarge) { + priv->pshare->txop_enlarge = 0; + if (priv->pshare->iot_mode_enable) + switch_turbo++; + } + } + +#if(defined LOW_TP_TXOP) + // for Intel IOT, need to enlarge CW MAX from 6 to 10 + if (pstat && pstat->IOTPeer==HT_IOT_PEER_INTEL && (((pstat->tx_avarage+pstat->rx_avarage)>>10) < + priv->pshare->rf_ft_var.cwmax_enhance_thd)) + { + if (!priv->pshare->BE_cwmax_enhance && priv->pshare->iot_mode_enable) + { + priv->pshare->BE_cwmax_enhance = 1; + switch_turbo++; + } + } else { + if (priv->pshare->BE_cwmax_enhance) { + priv->pshare->BE_cwmax_enhance = 0; + switch_turbo++; + } + } +#endif + } +#endif + priv->pshare->current_tx_bytes = 0; + priv->pshare->current_rx_bytes = 0; + }else { + if ((GET_CHIP_VER(priv) == VERSION_8881A)||(GET_CHIP_VER(priv) == VERSION_8192E)|| (GET_CHIP_VER(priv) == VERSION_8188E) ){ + unsigned int uldl_tp = (priv->pshare->current_tx_bytes+priv->pshare->current_rx_bytes)>>17; + if((uldl_tp > 40) && (priv->pshare->agg_to!= 1)) { + RTL_W8(0x462, 0x08); + priv->pshare->agg_to = 1; + } else if((uldl_tp < 35) && (priv->pshare->agg_to !=0)) { + RTL_W8(0x462, 0x02); + priv->pshare->agg_to = 0; + } + } + } + +#if(defined SW_TX_QUEUE) + if(AMPDU_ENABLE) { +#ifdef TX_EARLY_MODE + if (GET_TX_EARLY_MODE) { + if (!GET_EM_SWQ_ENABLE && + ((priv->assoc_num > 1) || + (pstat && pstat->IOTPeer != HT_IOT_PEER_UNKNOWN))) { + if ((priv->pshare->em_tx_byte_cnt >> 17) > EM_TP_UP_BOUND) + priv->pshare->reach_tx_limit_cnt++; + else + priv->pshare->reach_tx_limit_cnt = 0; + + if (priv->pshare->txop_enlarge && priv->pshare->reach_tx_limit_cnt /*>= WAIT_TP_TIME*/) { + GET_EM_SWQ_ENABLE = 1; + priv->pshare->reach_tx_limit_cnt = 0; + + if (pstat->IOTPeer == HT_IOT_PEER_INTEL) + MAX_EM_QUE_NUM = 12; + else if (pstat->IOTPeer == HT_IOT_PEER_RALINK) + MAX_EM_QUE_NUM = 10; + + enable_em(priv); + } + } + else if (GET_EM_SWQ_ENABLE) { + if ((priv->pshare->em_tx_byte_cnt >> 17) < EM_TP_LOW_BOUND) + priv->pshare->reach_tx_limit_cnt++; + else + priv->pshare->reach_tx_limit_cnt = 0; + + if (!priv->pshare->txop_enlarge || priv->pshare->reach_tx_limit_cnt >= WAIT_TP_TIME) { + GET_EM_SWQ_ENABLE = 0; + priv->pshare->reach_tx_limit_cnt = 0; + disable_em(priv); + } + } + } +#endif + +#if defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8192EE) || defined(CONFIG_RTL_8812_SUPPORT) + if ((GET_CHIP_VER(priv) == VERSION_8188E) || (priv->assoc_num > 9)) +#endif + { + if((priv->ext_stats.tx_avarage>>17)>TP_HIGH_WATER_MARK /*|| (priv->ext_stats.rx_avarage>>17)> TP_HIGH_WATER_MARK*/) { + if ((priv->swq_decision == 0)){ + switch_turbo++; + + if (pstat) { + if (pstat->IOTPeer==HT_IOT_PEER_INTEL) + priv->pshare->txop_enlarge = 0xe; + else if (pstat->IOTPeer==HT_IOT_PEER_RALINK) + priv->pshare->txop_enlarge = 0xd; + else if (pstat->IOTPeer==HT_IOT_PEER_HTC) + priv->pshare->txop_enlarge = 0; + else + priv->pshare->txop_enlarge = 2; + + } else if (priv->pshare->txop_enlarge == 0) { + priv->pshare->txop_enlarge = 2; + } + priv->swq_decision = 1; + } + } + else{ + if (priv->swq_txmac_chg >= priv->pshare->rf_ft_var.swq_en_highthd){ + if ((priv->swq_decision == 0)){ + switch_turbo++; + if (priv->pshare->txop_enlarge == 0) + priv->pshare->txop_enlarge = 2; + priv->swq_decision = 1; + } + else + { + if ((switch_turbo > 0) && (priv->pshare->txop_enlarge == 0) && (priv->pshare->iot_mode_enable != 0)) + { + priv->pshare->txop_enlarge = 2; + switch_turbo--; + } + } + } + else if(priv->swq_txmac_chg <= priv->pshare->rf_ft_var.swq_dis_lowthd){ + priv->swq_decision = 0; + } + else if ((priv->swq_decision == 1) && (switch_turbo > 0) && (priv->pshare->txop_enlarge == 0) && (priv->pshare->iot_mode_enable != 0)){ + priv->pshare->txop_enlarge = 2; + switch_turbo--; + } + } + + + } + + if( swqd ^priv->swq_decision ) { + if((priv->swq_decision == 1) +#if (defined(TX_EARLY_MODE)) + || (GET_EM_SWQ_ENABLE == 1) +#endif + ) { + priv->swq_en = 1; + priv->swqen_keeptime = priv->up_time; + + extern void init_STA_SWQAggNum(struct rtl8192cd_priv *priv); + init_STA_SWQAggNum(priv); + + } else { + priv->swq_en = 0; + priv->swqen_keeptime = 0; + } + } + } + if(priv->pshare->rf_ft_var.swq_enable == 0) { + priv->swq_en = 0; + priv->swqen_keeptime = 0; + } +#endif + +#ifdef WIFI_WMM +#ifdef LOW_TP_TXOP + if ((!priv->pmib->dot11OperationEntry.wifi_specific || (priv->pmib->dot11OperationEntry.wifi_specific == 2)) + && QOS_ENABLE) { + if (switch_turbo || priv->pshare->rf_ft_var.low_tp_txop) { + unsigned int thd_tp; + unsigned char under_thd; + unsigned int curr_tp; + + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N| WIRELESS_11G)) + { + // Determine the upper bound throughput threshold. + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + if (priv->assoc_num && priv->assoc_num != priv->pshare->ht_sta_num) + thd_tp = priv->pshare->rf_ft_var.low_tp_txop_thd_g; + else + thd_tp = priv->pshare->rf_ft_var.low_tp_txop_thd_n; + } + else + thd_tp = priv->pshare->rf_ft_var.low_tp_txop_thd_g; + + // Determine to close txop. +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if(IS_STA_VALID(pstat)) + { + struct rtl8192cd_priv *tmppriv; + struct aid_obj *aidarray; + aidarray = container_of(pstat, struct aid_obj, station); + tmppriv = aidarray->priv; + + curr_tp = (unsigned int)(tmppriv->ext_stats.tx_avarage>>17) + (unsigned int)(tmppriv->ext_stats.rx_avarage>>17); + } + else +#endif + curr_tp = (unsigned int)(priv->ext_stats.tx_avarage>>17) + (unsigned int)(priv->ext_stats.rx_avarage>>17); + if (curr_tp <= thd_tp && curr_tp >= priv->pshare->rf_ft_var.low_tp_txop_thd_low) + under_thd = 1; + else + under_thd = 0; + } + else + { + under_thd = 0; + } + + if (switch_turbo) + { + priv->pshare->rf_ft_var.low_tp_txop_close = under_thd; + priv->pshare->rf_ft_var.low_tp_txop_count = 0; + } + else if (priv->pshare->iot_mode_enable && (priv->pshare->rf_ft_var.low_tp_txop_close != under_thd)) { + priv->pshare->rf_ft_var.low_tp_txop_count++; + if (priv->pshare->rf_ft_var.low_tp_txop_close) { + priv->pshare->rf_ft_var.low_tp_txop_count = priv->pshare->rf_ft_var.low_tp_txop_delay; + } + if (priv->pshare->rf_ft_var.low_tp_txop_count ==priv->pshare->rf_ft_var.low_tp_txop_delay) + + { + priv->pshare->rf_ft_var.low_tp_txop_count = 0; + priv->pshare->rf_ft_var.low_tp_txop_close = under_thd; + switch_turbo++; + } + } + else + { + priv->pshare->rf_ft_var.low_tp_txop_count = 0; + } + } + } +#endif + +#ifdef WMM_DSCP_C42 + if (switch_turbo) { + if (!priv->pshare->iot_mode_enable && !priv->pshare->aggrmax_change) { + RTL_W16(0x4ca, 0x0404); + priv->pshare->aggrmax_change = 1; + } + else if (priv->pshare->iot_mode_enable && priv->pshare->aggrmax_change) { + RTL_W16(0x4ca, priv->pshare->aggrmax_bak); + priv->pshare->aggrmax_change = 0; + } + } +#endif +#ifdef TX_EARLY_MODE + unsigned int em_tp = ((priv->ext_stats.tx_avarage>>17) + (priv->ext_stats.rx_avarage>>17)); + if (em_tp > 80) + RTL_W32(0x508, (0x5e << 16) | (4 << 12) | (3 << 8) | 0x19); + else //if (em_tp < 75) + RTL_W32(0x508, (0x5e << 16) | (6 << 12) | (5 << 8) | 0x2b); +#endif + if (switch_turbo) + IotEdcaSwitch( priv, priv->pshare->iot_mode_enable ); +#endif +} + + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/EdcaTurboCheck.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/EdcaTurboCheck.h new file mode 100755 index 000000000..8f5516ebf --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/EdcaTurboCheck.h @@ -0,0 +1,30 @@ + + +#ifndef __EDCATURBOCHECK_H__ +#define __EDCATURBOCHECK_H__ + +void EdcaParaInit( + struct rtl8192cd_priv *priv + ); + +#ifdef WIFI_WMM +VOID +IotEdcaSwitch( + struct rtl8192cd_priv *priv, + unsigned char enable + ); +#endif + +BOOLEAN +ChooseIotMainSTA( + struct rtl8192cd_priv *priv, + PSTA_INFO_T pstat + ); + +VOID +IotEngine( + struct rtl8192cd_priv *priv + ); + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Hal8188EPwrSeq.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Hal8188EPwrSeq.c new file mode 100755 index 000000000..9219cd562 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Hal8188EPwrSeq.c @@ -0,0 +1,103 @@ +/*++ +Copyright (c) Realtek Semiconductor Corp. All rights reserved. + +Module Name: + Hal8188EPwrSeq.c + +Abstract: + This file includes all kinds of Power Action event for RTL8188E and corresponding hardware configurtions which are released from HW SD. + +Major Change History: + When Who What + ---------- --------------- ------------------------------- + 2011-07-07 Roger Create. + +--*/ +#ifdef __ECOS +#include +#endif +#include "8192cd.h" + +#ifdef CONFIG_RTL_88E_SUPPORT + +#include "HalPwrSeqCmd.h" +#include "Hal8188EPwrSeq.h" + + +/* + * drivers should parse below arrays and do the corresponding actions + */ + +/* Power on Array */ +WLAN_PWR_CFG rtl8188E_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS+RTL8188E_TRANS_END_STEPS]= +{ + RTL8188E_TRANS_CARDEMU_TO_ACT + RTL8188E_TRANS_END +}; + +/* Radio off Array */ +WLAN_PWR_CFG rtl8188E_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_END_STEPS]= +{ + RTL8188E_TRANS_ACT_TO_CARDEMU + RTL8188E_TRANS_END +}; + +/* Card Disable Array */ +WLAN_PWR_CFG rtl8188E_card_disable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS+RTL8188E_TRANS_END_STEPS]= +{ + RTL8188E_TRANS_ACT_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_CARDDIS + RTL8188E_TRANS_END +}; + +/* Card Enable Array */ +WLAN_PWR_CFG rtl8188E_card_enable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS+RTL8188E_TRANS_END_STEPS]= +{ + RTL8188E_TRANS_CARDDIS_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_ACT + RTL8188E_TRANS_END +}; + +/* Suspend Array */ +WLAN_PWR_CFG rtl8188E_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS+RTL8188E_TRANS_END_STEPS]= +{ + RTL8188E_TRANS_ACT_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_SUS + RTL8188E_TRANS_END +}; + +/* Resume Array */ +WLAN_PWR_CFG rtl8188E_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS+RTL8188E_TRANS_END_STEPS]= +{ + RTL8188E_TRANS_SUS_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_ACT + RTL8188E_TRANS_END +}; + + + +/* HWPDN Array */ +WLAN_PWR_CFG rtl8188E_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS+RTL8188E_TRANS_END_STEPS]= +{ + RTL8188E_TRANS_ACT_TO_CARDEMU + RTL8188E_TRANS_CARDEMU_TO_PDN + RTL8188E_TRANS_END +}; + +/* Enter LPS */ +WLAN_PWR_CFG rtl8188E_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS+RTL8188E_TRANS_END_STEPS]= +{ + //FW behavior + RTL8188E_TRANS_ACT_TO_LPS + RTL8188E_TRANS_END +}; + +/* Leave LPS */ +WLAN_PWR_CFG rtl8188E_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS+RTL8188E_TRANS_END_STEPS]= +{ + //FW behavior + RTL8188E_TRANS_LPS_TO_ACT + RTL8188E_TRANS_END +}; +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Hal8188EPwrSeq.h b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Hal8188EPwrSeq.h new file mode 100755 index 000000000..8ab70daeb --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Hal8188EPwrSeq.h @@ -0,0 +1,164 @@ +#ifdef CONFIG_RTL_88E_SUPPORT +#ifndef REALTEK_POWER_SEQUENCE_8188E +#define REALTEK_POWER_SEQUENCE_8188E + +#include "typedef.h" + +#ifdef BIT +#undef BIT +#endif +#define BIT(x) (1 << (x)) + + +/* + Check document WM-20110607-Paul-RTL8188E_Power_Architecture-R02.vsd + There are 6 HW Power States: + 0: POFF--Power Off + 1: PDN--Power Down + 2: CARDEMU--Card Emulation + 3: ACT--Active Mode + 4: LPS--Low Power State + 5: SUS--Suspend + + The transision from different states are defined below + TRANS_CARDEMU_TO_ACT + TRANS_ACT_TO_CARDEMU + TRANS_CARDEMU_TO_SUS + TRANS_SUS_TO_CARDEMU + TRANS_CARDEMU_TO_PDN + TRANS_ACT_TO_LPS + TRANS_LPS_TO_ACT + + TRANS_END + + PWR SEQ Version: rtl8188E_PwrSeq_V09.h +*/ +#define RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS 10 +#define RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS 10 +#define RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS 10 +#define RTL8188E_TRANS_SUS_TO_CARDEMU_STEPS 10 +#define RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS 10 +#define RTL8188E_TRANS_PDN_TO_CARDEMU_STEPS 10 +#define RTL8188E_TRANS_ACT_TO_LPS_STEPS 15 +#define RTL8188E_TRANS_LPS_TO_ACT_STEPS 15 +#define RTL8188E_TRANS_END_STEPS 1 + + +#define RTL8188E_TRANS_CARDEMU_TO_ACT \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_POLLING, BIT1, BIT1},/* wait till 0x04[17] = 1 power ready*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT0|BIT1, 0}, /* 0x02[1:0] = 0 reset BB*/ \ +/* {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT7, BIT7},*/ /*0x24[23] = 2b'01 schmit trigger */ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT7, 0}, /* 0x04[15] = 0 disable HWPDN (control by DRV)*/\ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT4|BIT3, 0}, /*0x04[12:11] = 2b'00 disable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT0, BIT0}, /*0x04[8] = 1 polling until return 0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_POLLING, BIT0, 0}, /*wait till 0x04[8] = 0*/ \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT4, 0}, /*LDO normal mode*/ \ + {0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT4, BIT4}, /*SDIO Driving*/ \ + +#define RTL8188E_TRANS_ACT_TO_CARDEMU \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0},/*0x1F[7:0] = 0 turn off RF*/ \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT4, BIT4}, /*LDO Sleep mode*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT1, BIT1}, /*0x04[9] = 1 turn off MAC by HW state machine*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_POLLING, BIT1, 0}, /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ + +#define RTL8188E_TRANS_CARDEMU_TO_SUS \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3|BIT4, BIT3}, /*0x04[12:11] = 2b'01enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3|BIT4, BIT3|BIT4}, /*0x04[12:11] = 2b'11enable WL suspend for PCIe*/ \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, BIT7}, /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */ \ + {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT4, 0}, /*Clear SIC_EN register 0x40[12] = 1'b0 */ \ + {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT4, BIT4}, /*Set USB suspend enable local register 0xfe10[4]=1 */ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_SDIO,PWR_CMD_WRITE, BIT0, BIT0}, /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_SDIO,PWR_CMD_POLLING, BIT1, 0}, /*wait power state to suspend*/ + +#define RTL8188E_TRANS_SUS_TO_CARDEMU \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_SDIO,PWR_CMD_WRITE, BIT0, 0}, /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_SDIO,PWR_CMD_POLLING, BIT1, BIT1}, /*wait power state to suspend*/\ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3|BIT4, 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ + +#define RTL8188E_TRANS_CARDEMU_TO_CARDDIS \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ +/* {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT7, BIT7},*/ /*0x24[23] = 2b'01 schmit trigger */ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3|BIT4, BIT3}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0}, /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */ \ + {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT4, 0}, /*Clear SIC_EN register 0x40[12] = 1'b0 */ \ + {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT4, BIT4}, /*Set USB suspend enable local register 0xfe10[4]=1 */ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_SDIO,PWR_CMD_WRITE, BIT0, BIT0}, /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_SDIO,PWR_CMD_POLLING, BIT1, 0}, /*wait power state to suspend*/ + +#define RTL8188E_TRANS_CARDDIS_TO_CARDEMU \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_SDIO,PWR_CMD_WRITE, BIT0, 0}, /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_SDIO,PWR_CMD_POLLING, BIT1, BIT1}, /*wait power state to suspend*/\ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT3|BIT4, 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ + +#define RTL8188E_TRANS_CARDEMU_TO_PDN \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT0, 0},/* 0x04[16] = 0*/\ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT7, BIT7},/* 0x04[15] = 1*/ + +#define RTL8188E_TRANS_PDN_TO_CARDEMU \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT7, 0},/* 0x04[15] = 0*/ + +//This is used by driver for LPSRadioOff Procedure, not for FW LPS Step +#define RTL8188E_TRANS_ACT_TO_LPS \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/ \ + {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ + {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ + {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ + {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT0, 0},/*CCK and OFDM are disabled,and clock are gated*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/ \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/ \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT1, 0},/*check if removed later*/ \ + {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT5, BIT5},/*Respond TxOK to scheduler*/ \ + + +#define RTL8188E_TRANS_LPS_TO_ACT \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,PWR_BASEADDR_SDIO,PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/\ + {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\ + {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/\ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT4, 0}, /*. 0x08[4] = 0 switch TSF to 40M*/\ + {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_POLLING, BIT7, 0}, /*Polling 0x109[7]=0 TSF in 40M*/\ + {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT6|BIT7, 0}, /*. 0x29[7:6] = 2b'00 enable BB clock*/\ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT1, BIT1}, /*. 0x101[1] = 1*/\ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0xFF}, /*. 0x100[7:0] = 0xFF enable WMAC TRX*/\ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, BIT1|BIT0, BIT1|BIT0}, /*. 0x02[1:0] = 2b'11 enable BB macro*/\ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,PWR_BASEADDR_MAC,PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/ + +#define RTL8188E_TRANS_END \ + /* format */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, // comments here*/ \ + {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,0,PWR_CMD_END, 0, 0}, // + + +extern WLAN_PWR_CFG rtl8188E_power_on_flow[RTL8188E_TRANS_CARDEMU_TO_ACT_STEPS+RTL8188E_TRANS_END_STEPS]; +extern WLAN_PWR_CFG rtl8188E_radio_off_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_END_STEPS]; +extern WLAN_PWR_CFG rtl8188E_card_disable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS+RTL8188E_TRANS_END_STEPS]; +extern WLAN_PWR_CFG rtl8188E_card_enable_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS+RTL8188E_TRANS_END_STEPS]; +extern WLAN_PWR_CFG rtl8188E_suspend_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS+RTL8188E_TRANS_END_STEPS]; +extern WLAN_PWR_CFG rtl8188E_resume_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_SUS_STEPS+RTL8188E_TRANS_END_STEPS]; +extern WLAN_PWR_CFG rtl8188E_hwpdn_flow[RTL8188E_TRANS_ACT_TO_CARDEMU_STEPS+RTL8188E_TRANS_CARDEMU_TO_PDN_STEPS+RTL8188E_TRANS_END_STEPS]; +extern WLAN_PWR_CFG rtl8188E_enter_lps_flow[RTL8188E_TRANS_ACT_TO_LPS_STEPS+RTL8188E_TRANS_END_STEPS]; +extern WLAN_PWR_CFG rtl8188E_leave_lps_flow[RTL8188E_TRANS_LPS_TO_ACT_STEPS+RTL8188E_TRANS_END_STEPS]; + +#endif +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Hal8192CDMOutSrc.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Hal8192CDMOutSrc.c new file mode 100755 index 000000000..9fb125c45 --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Hal8192CDMOutSrc.c @@ -0,0 +1,9606 @@ +//============================================================ +// +// File Name: Hal8192CDMOutSrc.c +// +// Description: +// +// This file is for 92CE/92CU outsource dynamic mechanism for partner. +// +// +//============================================================ + +#ifndef _HAL8192CDM_C_ +#define _HAL8192CDM_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#include +#elif defined(__ECOS) +#include +#include +#include +#include +#endif + +#include "./8192cd_cfg.h" +#include "./8192cd.h" +#include "./8192cd_hw.h" +#include "./8192cd_headers.h" +#include "./8192cd_debug.h" + +#ifdef __KERNEL__ +#ifdef __LINUX_2_6__ +#include +#else +#include +#endif +#endif + +#if defined(CONFIG_RTL_819X) && defined(USE_RLX_BSP) +#if defined(CONFIG_OPENWRT_SDK) && !defined(CONFIG_ARCH_CPU_RLX) +#include +#else +#include +#endif //CONFIG_OPENWRT_SDK +#endif + + +//Analog Pre-distortion calibration +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +//============================================================ +// Global var +//============================================================ + +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +unsigned int OFDMSwingTable[] = { + 0x7f8001fe, // 0, +6.0dB + 0x788001e2, // 1, +5.5dB + 0x71c001c7, // 2, +5.0dB + 0x6b8001ae, // 3, +4.5dB + 0x65400195, // 4, +4.0dB + 0x5fc0017f, // 5, +3.5dB + 0x5a400169, // 6, +3.0dB + 0x55400155, // 7, +2.5dB + 0x50800142, // 8, +2.0dB + 0x4c000130, // 9, +1.5dB + 0x47c0011f, // 10, +1.0dB + 0x43c0010f, // 11, +0.5dB + 0x40000100, // 12, +0dB + 0x3c8000f2, // 13, -0.5dB + 0x390000e4, // 14, -1.0dB + 0x35c000d7, // 15, -1.5dB + 0x32c000cb, // 16, -2.0dB + 0x300000c0, // 17, -2.5dB + 0x2d4000b5, // 18, -3.0dB + 0x2ac000ab, // 19, -3.5dB + 0x288000a2, // 20, -4.0dB + 0x26000098, // 21, -4.5dB + 0x24000090, // 22, -5.0dB + 0x22000088, // 23, -5.5dB + 0x20000080, // 24, -6.0dB + 0x1e400079, // 25, -6.5dB + 0x1c800072, // 26, -7.0dB + 0x1b00006c, // 27. -7.5dB + 0x19800066, // 28, -8.0dB + 0x18000060, // 29, -8.5dB + 0x16c0005b, // 30, -9.0dB + 0x15800056, // 31, -9.5dB + 0x14400051, // 32, -10.0dB + 0x1300004c, // 33, -10.5dB + 0x12000048, // 34, -11.0dB + 0x11000044, // 35, -11.5dB + 0x10000040, // 36, -12.0dB +}; + + +unsigned int TxPwrTrk_OFDM_SwingTbl[TxPwrTrk_OFDM_SwingTbl_Len] = { + /* +6.0dB */ 0x7f8001fe, + /* +5.5dB */ 0x788001e2, + /* +5.0dB */ 0x71c001c7, + /* +4.5dB */ 0x6b8001ae, + /* +4.0dB */ 0x65400195, + /* +3.5dB */ 0x5fc0017f, + /* +3.0dB */ 0x5a400169, + /* +2.5dB */ 0x55400155, + /* +2.0dB */ 0x50800142, + /* +1.5dB */ 0x4c000130, + /* +1.0dB */ 0x47c0011f, + /* +0.5dB */ 0x43c0010f, + /* 0.0dB */ 0x40000100, + /* -0.5dB */ 0x3c8000f2, + /* -1.0dB */ 0x390000e4, + /* -1.5dB */ 0x35c000d7, + /* -2.0dB */ 0x32c000cb, + /* -2.5dB */ 0x300000c0, + /* -3.0dB */ 0x2d4000b5, + /* -3.5dB */ 0x2ac000ab, + /* -4.0dB */ 0x288000a2, + /* -4.5dB */ 0x26000098, + /* -5.0dB */ 0x24000090, + /* -5.5dB */ 0x22000088, + /* -6.0dB */ 0x20000080, + /* -6.5dB */ 0x1a00006c, + /* -7.0dB */ 0x1c800072, + /* -7.5dB */ 0x18000060, + /* -8.0dB */ 0x19800066, + /* -8.5dB */ 0x15800056, + /* -9.0dB */ 0x26c0005b, + /* -9.5dB */ 0x14400051, + /* -10.0dB */ 0x24400051, + /* -10.5dB */ 0x1300004c, + /* -11.0dB */ 0x12000048, + /* -11.5dB */ 0x11000044, + /* -12.0dB */ 0x10000040 +}; + +unsigned char TxPwrTrk_CCK_SwingTbl[TxPwrTrk_CCK_SwingTbl_Len][8] = { + /* 0.0dB */ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, + /* 0.5dB */ {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, + /* 1.0dB */ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, + /* 1.5dB */ {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, + /* 2.0dB */ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, + /* 2.5dB */ {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, + /* 3.0dB */ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, + /* 3.5dB */ {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, + /* 4.0dB */ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, + /* 4.5dB */ {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, + /* 5.0dB */ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, + /* 5.5dB */ {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, + /* 6.0dB */ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, + /* 6.5dB */ {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, + /* 7.0dB */ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, + /* 7.5dB */ {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, + /* 8.0dB */ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, + /* 8.5dB */ {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, + /* 9.0dB */ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, + /* 9.5dB */ {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + /* 10.0dB */ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + /* 10.5dB */ {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, + /* 11.0dB */ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} +}; + +unsigned char TxPwrTrk_CCK_SwingTbl_CH14[TxPwrTrk_CCK_SwingTbl_Len][8] = { + /* 0.0dB */ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, + /* 0.5dB */ {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, + /* 1.0dB */ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, + /* 1.5dB */ {0x2d, 0x2d, 0x27, 0x17, 0x00, 0x00, 0x00, 0x00}, + /* 2.0dB */ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, + /* 2.5dB */ {0x28, 0x28, 0x22, 0x14, 0x00, 0x00, 0x00, 0x00}, + /* 3.0dB */ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, + /* 3.5dB */ {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, + /* 4.0dB */ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, + /* 4.5dB */ {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, + /* 5.0dB */ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, + /* 5.5dB */ {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, + /* 6.0dB */ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, + /* 6.5dB */ {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, + /* 7.0dB */ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, + /* 7.5dB */ {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, + /* 8.0dB */ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, + /* 8.5dB */ {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, + /* 9.0dB */ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, + /* 9.5dB */ {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + /* 10.0dB */ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + /* 10.5dB */ {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, + /* 11.0dB */ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} +}; + +//#ifndef USE_OUT_SRC + +unsigned char CCKSwingTable_Ch1_Ch13[][8] = { +{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, // 0, +0dB +{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, // 1, -0.5dB +{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, // 2, -1.0dB +{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, // 3, -1.5dB +{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, // 4, -2.0dB +{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, // 5, -2.5dB +{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, // 6, -3.0dB +{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, // 7, -3.5dB +{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, // 8, -4.0dB +{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, // 9, -4.5dB +{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, // 10, -5.0dB +{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, // 11, -5.5dB +{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, // 12, -6.0dB +{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, // 13, -6.5dB +{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, // 14, -7.0dB +{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, // 15, -7.5dB +{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, // 16, -8.0dB +{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, // 17, -8.5dB +{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, // 18, -9.0dB +{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, // 19, -9.5dB +{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, // 20, -10.0dB +{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, // 21, -10.5dB +{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, // 22, -11.0dB +{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, // 23, -11.5dB +{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, // 24, -12.0dB +{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, // 25, -12.5dB +{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, // 26, -13.0dB +{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, // 27, -13.5dB +{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, // 28, -14.0dB +{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, // 29, -14.5dB +{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, // 30, -15.0dB +{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, // 31, -15.5dB +{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} // 32, -16.0dB +}; + +unsigned char CCKSwingTable_Ch14 [][8]= { +{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, // 0, +0dB +{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, // 1, -0.5dB +{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, // 2, -1.0dB +{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, // 3, -1.5dB +{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, // 4, -2.0dB +{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, // 5, -2.5dB +{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, // 6, -3.0dB +{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, // 7, -3.5dB +{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, // 8, -4.0dB +{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, // 9, -4.5dB +{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, // 10, -5.0dB +{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, // 11, -5.5dB +{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, // 12, -6.0dB +{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, // 13, -6.5dB +{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, // 14, -7.0dB +{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, // 15, -7.5dB +{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, // 16, -8.0dB +{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, // 17, -8.5dB +{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, // 18, -9.0dB +{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, // 19, -9.5dB +{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, // 20, -10.0dB +{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, // 21, -10.5dB +{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, // 22, -11.0dB +{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, // 23, -11.5dB +{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, // 24, -12.0dB +{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, // 25, -12.5dB +{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, // 26, -13.0dB +{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, // 27, -13.5dB +{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, // 28, -14.0dB +{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, // 29, -14.5dB +{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, // 30, -15.0dB +{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, // 31, -15.5dB +{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} // 32, -16.0dB +}; + +#endif + +//#if defined(_OUTSRC_COEXIST) +#if !defined(USE_OUT_SRC) || defined(_OUTSRC_COEXIST) +const int OFDM_TABLE_SIZE= sizeof(OFDMSwingTable)/sizeof(int); +const int CCK_TABLE_SIZE= sizeof(CCKSwingTable_Ch1_Ch13) >>3; +#endif + + +#ifdef CONFIG_RTL_92D_SUPPORT + +static unsigned int OFDMSwingTable_92D[] = { + 0x7f8001fe, // 0, +6.0dB + 0x788001e2, // 1, +5.5dB + 0x71c001c7, // 2, +5.0dB + 0x6b8001ae, // 3, +4.5dB + 0x65400195, // 4, +4.0dB + 0x5fc0017f, // 5, +3.5dB + 0x5a400169, // 6, +3.0dB + 0x55400155, // 7, +2.5dB + 0x50800142, // 8, +2.0dB + 0x4c000130, // 9, +1.5dB + 0x47c0011f, // 10, +1.0dB + 0x43c0010f, // 11, +0.5dB + 0x40000100, // 12, +0dB + 0x3c8000f2, // 13, -0.5dB + 0x390000e4, // 14, -1.0dB + 0x35c000d7, // 15, -1.5dB + 0x32c000cb, // 16, -2.0dB + 0x300000c0, // 17, -2.5dB + 0x2d4000b5, // 18, -3.0dB + 0x2ac000ab, // 19, -3.5dB + 0x288000a2, // 20, -4.0dB + 0x26000098, // 21, -4.5dB + 0x24000090, // 22, -5.0dB + 0x22000088, // 23, -5.5dB + 0x20000080, // 24, -6.0dB + 0x1e400079, // 25, -6.5dB + 0x1c800072, // 26, -7.0dB + 0x1b00006c, // 27. -7.5dB + 0x19800066, // 28, -8.0dB + 0x18000060, // 29, -8.5dB + 0x16c0005b, // 30, -9.0dB + 0x15800056, // 31, -9.5dB + 0x14400051, // 32, -10.0dB + 0x1300004c, // 33, -10.5dB + 0x12000048, // 34, -11.0dB + 0x11000044, // 35, -11.5dB + 0x10000040, // 36, -12.0dB + 0x0f00003c,// 37, -12.5dB + 0x0e400039,// 38, -13.0dB + 0x0d800036,// 39, -13.5dB + 0x0cc00033,// 40, -14.0dB + 0x0c000030,// 41, -14.5dB + 0x0b40002d,// 42, -15.0dB +}; +#endif + + +#ifdef HW_ANT_SWITCH +#define RXDVY_A_EN ((HW_DIV_ENABLE && !priv->pshare->rf_ft_var.antSw_select) ? 0x80 : 0) +#define RXDVY_B_EN ((HW_DIV_ENABLE && priv->pshare->rf_ft_var.antSw_select) ? 0x80 : 0) +#endif + + +//3 ============================================================ +//3 DIG related functions +//3 ============================================================ +#if 0 +int getIGIFor1RCCA(int value_IGI) +{ + #define ONERCCA_LOW_TH 0x30 + #define ONERCCA_LOW_DIFF 8 + + if (value_IGI < ONERCCA_LOW_TH) { + if ((ONERCCA_LOW_TH - value_IGI) < ONERCCA_LOW_DIFF) + return ONERCCA_LOW_TH; + else + return value_IGI + ONERCCA_LOW_DIFF; + } else { + return value_IGI; + } +} + + +void set_DIG_state(struct rtl8192cd_priv *priv, int state) +{ + int value_IGI; + + if (state) { + priv->pshare->DIG_on = 1; + priv->pshare->restore = 0; + } + else { + priv->pshare->DIG_on = 0; + if (priv->pshare->restore == 0) { + if (priv->pshare->rf_ft_var.use_ext_lna == 1) + value_IGI = 0x30; + else + value_IGI = 0x20; + +#if defined(HW_ANT_SWITCH) + // wirte new initial gain index into regC50/C58 + if (priv->pshare->rf_ft_var.one_path_cca == 0) { + RTL_W8(0xc50, value_IGI | RXDVY_A_EN); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, value_IGI | RXDVY_B_EN); +#endif + } else if (priv->pshare->rf_ft_var.one_path_cca == 1) { + RTL_W8(0xc50, value_IGI | RXDVY_A_EN); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, getIGIFor1RCCA(value_IGI) | RXDVY_B_EN); +#endif + } else if (priv->pshare->rf_ft_var.one_path_cca == 2) { + RTL_W8(0xc50, getIGIFor1RCCA(value_IGI) | RXDVY_A_EN); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, value_IGI | RXDVY_B_EN); +#endif + } +#else + // Write IGI into HW + if (priv->pshare->rf_ft_var.one_path_cca == 0) { + RTL_W8(0xc50, value_IGI); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, value_IGI); +#endif + } else if (priv->pshare->rf_ft_var.one_path_cca == 1) { + RTL_W8(0xc50, value_IGI); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, getIGIFor1RCCA(value_IGI)); +#endif + } else if (priv->pshare->rf_ft_var.one_path_cca == 2) { + RTL_W8(0xc50, getIGIFor1RCCA(value_IGI)); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, value_IGI); +#endif + } +#endif + priv->pshare->restore = 1; + } +#ifdef INTERFERENCE_CONTROL + priv->pshare->phw->signal_strength = 0; +#endif + } +} +#endif + +#ifdef CONFIG_RTL_92D_SUPPORT +void MP_DIG_process(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + u4Byte RXOK_cal, RxPWDBAve; + //unsigned int FA_cnt_ofdm = priv->pshare->ofdm_FA_cnt1 + priv->pshare->ofdm_FA_cnt2 + + // priv->pshare->ofdm_FA_cnt3 + priv->pshare->ofdm_FA_cnt4; + //unsigned int FA_cnt_cck = priv->pshare->cck_FA_cnt; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (!(priv->pshare->rf_ft_var.mp_specific && priv->pshare->mp_dig_on)) + return; + + //printk("===> %s, pBandType = %d\n", __FUNCTION__, priv->pmib->dot11RFEntry.phyBandSelect); + + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + + FA_statistic(priv); + + priv->pshare->LastNumQryPhyStatusAll = priv->pshare->NumQryPhyStatus; + priv->pshare->NumQryPhyStatus = priv->pshare->NumQryPhyStatusCCK + priv->pshare->NumQryPhyStatusOFDM; + RXOK_cal = priv->pshare->NumQryPhyStatus - priv->pshare->LastNumQryPhyStatusAll; + + if (RXOK_cal == 0) + RxPWDBAve = 0; + else + RxPWDBAve = priv->pshare->RxPWDBAve/RXOK_cal; + + priv->pshare->RxPWDBAve= 0; + + //printk("RX OK = %d\n", RXOK_cal); + //printk("RSSI = %d\n", RxPWDBAve); + //printk("DIG = (%x, %x), Cnt_all = %d, Cnt_Ofdm_fail = %d, Cnt_Cck_fail = %d\n", RTL_R8(0xc50), RTL_R8(0xc58), priv->pshare->FA_total_cnt, FA_cnt_ofdm, FA_cnt_cck); + + if (RXOK_cal >= 70) { + if (RxPWDBAve <= 40) { + RTL_W8(0xc50, 0x1C); + RTL_W8(0xc58, 0x1C); + } else if (RxPWDBAve > 45) { + RTL_W8(0xc50, 0x20); + RTL_W8(0xc58, 0x20); + } + } + else { + RTL_W8(0xc50, 0x20); + RTL_W8(0xc58, 0x20); + } + } + mod_timer(&priv->pshare->MP_DIGTimer, RTL_MILISECONDS_TO_JIFFIES(700)); +} +#endif + +void DIG_process(struct rtl8192cd_priv *priv) +{ + #define DEAD_POINT_TH 10000 + #define DOWN_IG_HIT_TH 5 + #define DEAD_POINT_HIT_TH 3 + + unsigned char value_IGI; + signed char value8; + unsigned int IGI_target; + unsigned char Adap_IGI_Upper; +#ifdef INTERFERENCE_CONTROL + unsigned short thd0 = priv->pshare->threshold0; + unsigned short thd1 = priv->pshare->threshold1; + unsigned short thd2 = priv->pshare->threshold2; +#endif + + if (priv->pshare->DIG_on == 1) + { +#ifdef HIGH_POWER_EXT_LNA + if (priv->pshare->rf_ft_var.use_ext_lna == 1) { +// priv->pshare->FA_upper = 0x42; + priv->pshare->FA_upper = MIN_NUM(0x42, priv->pshare->rssi_min+36); + priv->pshare->FA_lower = 0x30; + } else +#endif + { + // Reset initial gain upper & lower bounds +#ifdef DFS + if (!priv->pmib->dot11DFSEntry.disable_DFS && + (OPMODE & WIFI_AP_STATE) && + (((priv->pmib->dot11RFEntry.dot11channel >= 52) && + (priv->pmib->dot11RFEntry.dot11channel <= 64)) || + ((priv->pmib->dot11RFEntry.dot11channel >= 100) && + (priv->pmib->dot11RFEntry.dot11channel <= 140)))){ + priv->pshare->FA_upper = 0x24; + priv->pshare->FA_lower = 0x20; + } + else +#endif + { +#ifdef INTERFERENCE_CONTROL + priv->pshare->FA_lower = 0x20; + + if (priv->pshare->rssi_min != 0xFF) + { +// priv->pshare->FA_upper = 0x3E; + + if (priv->pshare->rssi_min > 30) + priv->pshare->FA_lower = 0x24; + else if (priv->pshare->rssi_min > 25) + priv->pshare->FA_lower = 0x22; + + // limit upper bound to prevent the minimal signal sta from disconnect +// if ((priv->pshare->rssi_min + 10) < priv->pshare->FA_upper) +// priv->pshare->FA_upper = priv->pshare->rssi_min + 10; + priv->pshare->FA_upper = MIN_NUM(0x3E, priv->pshare->rssi_min+20); + } + else // before link + { + priv->pshare->FA_upper = 0x32; + + thd0 = 500; + thd1 = 8000; + thd2 = 10000; + } +#else + if (priv->pmib->dot11RFEntry.tx2path) { + if (priv->pmib->dot11BssType.net_work_type == WIRELESS_11B) + priv->pshare->FA_upper = MIN_NUM(0x2A, priv->pshare->rssi_min+10); + else + priv->pshare->FA_upper = MIN_NUM(0x3E, priv->pshare->rssi_min+10); + } + else + priv->pshare->FA_upper = MIN_NUM(0x3E, priv->pshare->rssi_min+10); + priv->pshare->FA_lower = 0x20; + + if (priv->pshare->rssi_min > 30) + priv->pshare->FA_lower = 0x24; + else if (priv->pshare->rssi_min > 25) + priv->pshare->FA_lower = 0x22; +#endif + } + } + + // determine a new initial gain index according to the sumation of all FA counters as well as upper & lower bounds + value8 = RTL_R8(0xc50); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) { + if(priv->pshare->rf_ft_var.one_path_cca==2) + value8 = RTL_R8(0xc58); + } +#endif + + value_IGI = (value8 & 0x7F); + +#if defined(CONFIG_RTL_NOISE_CONTROL_92C) + if(priv->pshare->rf_ft_var.dnc_enable) + if ((GET_CHIP_VER(priv) == VERSION_8192C)||(GET_CHIP_VER(priv) == VERSION_8188C)){ + unsigned long tp_now = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; +#ifdef HIGH_POWER_EXT_LNA + if(priv->pshare->rf_ft_var.use_ext_lna) { + if( (priv->pshare->rssi_min > 50) ) { + if((!priv->pshare->DNC_on) && (value_IGI >= priv->pshare->FA_upper) && (priv->pshare->FA_total_cnt > priv->pshare->threshold2)) { + priv->pshare->DNC_on = 1; + priv->ext_stats.tp_average_pre = tp_now; + priv->pshare->FA_lower = 0x20; + PHY_SetBBReg(priv, 0x870, bMaskDWord, RTL_R32(0x870)|BIT(5)|BIT(6)|BIT(21)|BIT(22)); + +#ifdef HW_ANT_SWITCH + PHY_SetBBReg(priv, 0xc50, bMaskByte0, priv->pshare->FA_lower | RXDVY_A_EN); + PHY_SetBBReg(priv, 0xc58, bMaskByte0, priv->pshare->FA_lower | RXDVY_B_EN); +#else + PHY_SetBBReg(priv, 0xc50, bMaskByte0, priv->pshare->FA_lower); + PHY_SetBBReg(priv, 0xc58, bMaskByte0, priv->pshare->FA_lower); +#endif + + } else if(priv->pshare->DNC_on ==1) { + if(tp_now < priv->ext_stats.tp_average_pre + 2) { + priv->pshare->DNC_on = 0; + } + else { + priv->pshare->DNC_on =2; + priv->ext_stats.tp_average_pre = tp_now; + } + } else if(priv->pshare->DNC_on >= 2 ) { + if(( tp_now+10 < priv->ext_stats.tp_average_pre ) || (tp_now < 1) ) { + priv->pshare->DNC_on = 0; + } else if(priv->pshare->DNC_on<5) { + priv->ext_stats.tp_average_pre = tp_now; + ++priv->pshare->DNC_on; + } + } + }else { + priv->pshare->DNC_on = 0; + } + + if( priv->pshare->DNC_on ) + return; + else + PHY_SetBBReg(priv, 0x870, bMaskDWord, RTL_R32(0x870)& ~(BIT(5)|BIT(6)|BIT(21)|BIT(22))); + + } else +#endif + { + if( (priv->pshare->rssi_min > 40) && (value_IGI >= priv->pshare->FA_upper) ) { +// unsigned long tp_now = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; + if((!priv->pshare->DNC_on) && (priv->pshare->FA_total_cnt > priv->pshare->threshold2)) { + priv->pshare->DNC_on = 1; + priv->ext_stats.tp_average_pre = tp_now; + } else if(priv->pshare->DNC_on ==1) { + if(tp_now < priv->ext_stats.tp_average_pre + 2) { + priv->pshare->DNC_on = 0; + } + else { + priv->pshare->DNC_on = 2; + priv->ext_stats.tp_average_pre = tp_now; + } + } else if(priv->pshare->DNC_on >= 2 ) { + if((tp_now +10 < priv->ext_stats.tp_average_pre ) + || ((priv->ext_stats.tp_average_pre < 10) && (priv->pshare->FA_total_cnt < priv->pshare->threshold1))) { + priv->pshare->DNC_on = 0; + } else if(priv->pshare->DNC_on<6) { + priv->ext_stats.tp_average_pre = tp_now; + ++priv->pshare->DNC_on; + } + } + if(priv->pshare->DNC_on) { + priv->pshare->FA_upper = 0x3e; + } + }else { + priv->pshare->DNC_on = 0; + } + } + } +#endif + + if ((priv->pshare->digDeadPoint == 0) && (priv->pshare->FA_total_cnt > DEAD_POINT_TH)) { + if ((priv->pshare->digDeadPointHitCount > 0) && (priv->pshare->digDeadPointCandidate == value_IGI)) { + priv->pshare->digDeadPointHitCount++; + if (priv->pshare->digDeadPointHitCount == DEAD_POINT_HIT_TH) { + priv->pshare->digDeadPoint = priv->pshare->digDeadPointCandidate; + } + } else { + priv->pshare->digDeadPointCandidate = value_IGI; + priv->pshare->digDeadPointHitCount = 1; + } + } + +#ifdef INTERFERENCE_CONTROL + if (priv->pshare->FA_total_cnt < thd0) { +#else + if (priv->pshare->FA_total_cnt < priv->pshare->threshold0) { +#endif + priv->pshare->digDownCount++; + if (priv->pshare->digDownCount > DOWN_IG_HIT_TH) { + // Reset deadpoint hit count + if ((priv->pshare->digDeadPoint == 0) && (priv->pshare->digDeadPointHitCount > 0) && (value_IGI == priv->pshare->digDeadPointCandidate)) + priv->pshare->digDeadPointHitCount = 0; + + value_IGI--; + + // Check if the new value is dead point + if ((priv->pshare->digDeadPoint > 0) && (value_IGI == priv->pshare->digDeadPoint)) + value_IGI++; + } +#ifdef INTERFERENCE_CONTROL + } else if (priv->pshare->FA_total_cnt < thd1) { +#else + } else if (priv->pshare->FA_total_cnt < priv->pshare->threshold1) { +#endif + value_IGI += 0; + priv->pshare->digDownCount = 0; +#ifdef INTERFERENCE_CONTROL + } else if (priv->pshare->FA_total_cnt < thd2) { +#else + } else if (priv->pshare->FA_total_cnt < priv->pshare->threshold2) { +#endif + value_IGI++; + priv->pshare->digDownCount = 0; +#ifdef INTERFERENCE_CONTROL + } else if (priv->pshare->FA_total_cnt >= thd2) { +#else + } else if (priv->pshare->FA_total_cnt >= priv->pshare->threshold2) { +#endif + value_IGI += 2; + priv->pshare->digDownCount = 0; + } else { + priv->pshare->digDownCount = 0; + } + + if (value_IGI > priv->pshare->FA_upper) + value_IGI = priv->pshare->FA_upper; + else if (value_IGI < priv->pshare->FA_lower) + value_IGI = priv->pshare->FA_lower; + if (priv->pshare->rf_ft_var.adaptivity_enable && priv->pshare->rf_ft_var.adaptivity_flag == TRUE) + { + Adap_IGI_Upper = priv->pshare->rf_ft_var.Adaptivity_IGI_upper; + if(value_IGI > Adap_IGI_Upper) + value_IGI = Adap_IGI_Upper; + } + +#if defined(HW_ANT_SWITCH) + // wirte new initial gain index into regC50/C58 + if (priv->pshare->rf_ft_var.one_path_cca == 0) { + RTL_W8(0xc50, value_IGI | RXDVY_A_EN); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, value_IGI | RXDVY_B_EN); +#endif + } else if (priv->pshare->rf_ft_var.one_path_cca == 1) { + RTL_W8(0xc50, value_IGI | RXDVY_A_EN); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, getIGIFor1RCCA(value_IGI) | RXDVY_B_EN); +#endif + } else if (priv->pshare->rf_ft_var.one_path_cca == 2) { + RTL_W8(0xc50, getIGIFor1RCCA(value_IGI) | RXDVY_A_EN); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, value_IGI| RXDVY_B_EN); +#endif + } +#else + // Write IGI into HW + if (priv->pshare->rf_ft_var.one_path_cca == 0) { + RTL_W8(0xc50, value_IGI); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, value_IGI); +#endif + } else if (priv->pshare->rf_ft_var.one_path_cca == 1) { + RTL_W8(0xc50, value_IGI); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, getIGIFor1RCCA(value_IGI)); +#endif + } else if (priv->pshare->rf_ft_var.one_path_cca == 2) { + RTL_W8(0xc50, getIGIFor1RCCA(value_IGI)); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, value_IGI); +#endif + } +#endif + + } +} + +#if 0 +void check_DIG_by_rssi(struct rtl8192cd_priv *priv, unsigned char rssi_strength) +{ + unsigned int dig_on = 0; + + if (OPMODE & WIFI_SITE_MONITOR) + return; + + if ((rssi_strength > priv->pshare->rf_ft_var.digGoUpperLevel) + && (rssi_strength < HP_LOWER+1) && (priv->pshare->phw->signal_strength != 2)) { +#ifndef CONFIG_RTL_92D_SUPPORT + if (priv->pshare->is_40m_bw) + // RTL_W8(0xc87, (RTL_R8(0xc87) & 0xf) | 0x30); 92D + RTL_W8(0xc87, 0x30); + else + RTL_W8(0xc30, 0x44); +#endif + + if (priv->pshare->phw->signal_strength != 3) + dig_on++; + + priv->pshare->phw->signal_strength = 2; + } + else if ((rssi_strength > HP_LOWER+5) && (priv->pshare->phw->signal_strength != 3)) { +#ifndef CONFIG_RTL_92D_SUPPORT + if (priv->pshare->is_40m_bw) + // RTL_W8(0xc87, (RTL_R8(0xc87) & 0xf) | 0x30); 92D + RTL_W8(0xc87, 0x30); + else + RTL_W8(0xc30, 0x44); +#endif + + if (priv->pshare->phw->signal_strength != 2) + dig_on++; + + priv->pshare->phw->signal_strength = 3; + } + else if (((rssi_strength < priv->pshare->rf_ft_var.digGoLowerLevel) + && (priv->pshare->phw->signal_strength != 1)) || !priv->pshare->phw->signal_strength) { + // DIG off +// set_DIG_state(priv, 0); + +#ifndef CONFIG_RTL_92D_SUPPORT + if (priv->pshare->is_40m_bw) + //RTL_W8(0xc87, (RTL_R8(0xc87) & 0xf) | 0x30); 92D + RTL_W8(0xc87, 0x30); + else + RTL_W8(0xc30, 0x44); +#endif + + priv->pshare->phw->signal_strength = 1; + } + + if (dig_on) { + // DIG on + set_DIG_state(priv, 1); + } + + //check_DC_TH_by_rssi(priv, rssi_strength); +} + + +void DIG_for_site_survey(struct rtl8192cd_priv *priv, int do_ss) +{ + if (do_ss) { + // DIG off + set_DIG_state(priv, 0); + } + else { + // DIG on +#ifndef INTERFERENCE_CONTROL + if (priv->pshare->phw->signal_strength > 1) +#endif + { + set_DIG_state(priv, 1); + } + } +} +#endif + +#if 0 +//#ifdef INTERFERENCE_CONTROL +void check_NBI_by_rssi(struct rtl8192cd_priv *priv, unsigned char rssi_strength) +{ + if (OPMODE & WIFI_SITE_MONITOR) + return; + + if (priv->pshare->phw->nbi_filter_on) { + if (rssi_strength < 20) { + priv->pshare->phw->nbi_filter_on = 0; + RTL_W16(rOFDM0_RxDSP, RTL_R16(rOFDM0_RxDSP) & ~ BIT(9)); // NBI off + } + } else { // NBI OFF previous + if (rssi_strength > 25) { + priv->pshare->phw->nbi_filter_on = 1; + RTL_W16(rOFDM0_RxDSP, RTL_R16(rOFDM0_RxDSP) | BIT(9)); // NBI on + } + } +} +#endif + +/* + * dynamic CCK CCA enhance by rssi + */ +void CCK_CCA_dynamic_enhance(struct rtl8192cd_priv *priv, unsigned char rssi_strength) +{ +#if 1 + unsigned int cck_fa = priv->pshare->FA_total_cnt; + int rssi_thd = 30; + + if (rssi_strength == 0xff) { + if (cck_fa < 1000) { + if (priv->pshare->phw->CCK_CCA_enhanced != 2) { + RTL_W8(0xa0a, 0x40); + priv->pshare->phw->CCK_CCA_enhanced = 2; + } + } else { + if (priv->pshare->phw->CCK_CCA_enhanced != 1) { + RTL_W8(0xa0a, 0x83); + priv->pshare->phw->CCK_CCA_enhanced = 1; + } + } + return; + } + + if (rssi_strength > rssi_thd+5) { + if (priv->pshare->phw->CCK_CCA_enhanced != 0) { + RTL_W8(0xa0a, 0xcd); + priv->pshare->phw->CCK_CCA_enhanced = 0; + } + } else if (rssi_strength< rssi_thd) { + if ((rssi_strength > 9) || (priv->assoc_num >1)) { + if (priv->pshare->phw->CCK_CCA_enhanced != 1) { + RTL_W8(0xa0a, 0x83); + priv->pshare->phw->CCK_CCA_enhanced = 1; + } + } else { + if(cck_fa<1000) { + if (priv->pshare->phw->CCK_CCA_enhanced != 2) { + RTL_W8(0xa0a, 0x40); + priv->pshare->phw->CCK_CCA_enhanced = 2; + } + } else { + if (priv->pshare->phw->CCK_CCA_enhanced != 1) { + RTL_W8(0xa0a, 0x83); + priv->pshare->phw->CCK_CCA_enhanced = 1; + } + } + } + } + +#else + + if (rssi_strength == 0xff) + return; + + if (!priv->pshare->phw->CCK_CCA_enhanced && (rssi_strength < 30)) { + priv->pshare->phw->CCK_CCA_enhanced = TRUE; + RTL_W8(0xa0a, 0x83); + } + else if (priv->pshare->phw->CCK_CCA_enhanced && (rssi_strength > 35)) { + priv->pshare->phw->CCK_CCA_enhanced = FALSE; + RTL_W8(0xa0a, 0xcd); + } +#endif +} + + +//3 ============================================================ +//3 Dynamic Tx Power / Power Tracking +//3 ============================================================ + +#ifdef HIGH_POWER_EXT_PA +void tx_power_control(struct rtl8192cd_priv *priv) +{ +#ifndef SMP_SYNC + unsigned long x; +#endif + + int pwr_value = 0x10101010; + if( priv->pshare->phw->signal_strength == 3 && priv->pshare->phw->lower_tx_power== 0) { + SAVE_INT_AND_CLI(x); + priv->pshare->phw->power_backup[0x00] = RTL_R32(rTxAGC_A_Rate18_06); + priv->pshare->phw->power_backup[0x01] = RTL_R32(rTxAGC_A_Rate54_24); + priv->pshare->phw->power_backup[0x02] = RTL_R32(rTxAGC_B_Rate18_06); + priv->pshare->phw->power_backup[0x03] = RTL_R32(rTxAGC_B_Rate54_24); + priv->pshare->phw->power_backup[0x04] = RTL_R32(rTxAGC_A_Mcs03_Mcs00); + priv->pshare->phw->power_backup[0x05] = RTL_R32(rTxAGC_A_Mcs07_Mcs04); + priv->pshare->phw->power_backup[0x06] = RTL_R32(rTxAGC_A_Mcs11_Mcs08); + priv->pshare->phw->power_backup[0x07] = RTL_R32(rTxAGC_A_Mcs15_Mcs12); + priv->pshare->phw->power_backup[0x08] = RTL_R32(rTxAGC_B_Mcs03_Mcs00); + priv->pshare->phw->power_backup[0x09] = RTL_R32(rTxAGC_B_Mcs07_Mcs04); + priv->pshare->phw->power_backup[0x0a] = RTL_R32(rTxAGC_B_Mcs11_Mcs08); + priv->pshare->phw->power_backup[0x0b] = RTL_R32(rTxAGC_B_Mcs15_Mcs12); + priv->pshare->phw->power_backup[0x0c] = RTL_R32(rTxAGC_A_CCK11_2_B_CCK11); + priv->pshare->phw->power_backup[0x0d] = RTL_R32(rTxAGC_A_CCK1_Mcs32); + priv->pshare->phw->power_backup[0x0e] = RTL_R32(rTxAGC_B_CCK5_1_Mcs32); + RTL_W32(rTxAGC_A_Rate18_06, pwr_value); + RTL_W32(rTxAGC_A_Rate54_24, pwr_value); + RTL_W32(rTxAGC_B_Rate18_06, pwr_value); + RTL_W32(rTxAGC_B_Rate54_24, pwr_value); + RTL_W32(rTxAGC_A_Mcs03_Mcs00, pwr_value); + RTL_W32(rTxAGC_A_Mcs07_Mcs04, pwr_value); + RTL_W32(rTxAGC_A_Mcs11_Mcs08, pwr_value); + RTL_W32(rTxAGC_A_Mcs15_Mcs12, pwr_value); + RTL_W32(rTxAGC_B_Mcs03_Mcs00, pwr_value); + RTL_W32(rTxAGC_B_Mcs07_Mcs04, pwr_value); + RTL_W32(rTxAGC_B_Mcs11_Mcs08, pwr_value); + RTL_W32(rTxAGC_B_Mcs15_Mcs12, pwr_value); + RTL_W32(rTxAGC_A_CCK11_2_B_CCK11, pwr_value); + RTL_W32(rTxAGC_A_CCK1_Mcs32, (pwr_value & 0x0000ff00) | (priv->pshare->phw->power_backup[0x0d] &0xffff00ff)); + RTL_W32(rTxAGC_B_CCK5_1_Mcs32, (pwr_value & 0xffffff00) | (priv->pshare->phw->power_backup[0x0e] &0x000000ff)); + priv->pshare->phw->lower_tx_power = 1; + RESTORE_INT(x); + } + else if( priv->pshare->phw->signal_strength != 3 && priv->pshare->phw->lower_tx_power) { + SAVE_INT_AND_CLI(x); + RTL_W32(rTxAGC_A_Rate18_06, priv->pshare->phw->power_backup[0x00]); + RTL_W32(rTxAGC_A_Rate54_24, priv->pshare->phw->power_backup[0x01]); + RTL_W32(rTxAGC_B_Rate18_06, priv->pshare->phw->power_backup[0x02]); + RTL_W32(rTxAGC_B_Rate54_24, priv->pshare->phw->power_backup[0x03]); + RTL_W32(rTxAGC_A_Mcs03_Mcs00, priv->pshare->phw->power_backup[0x04]); + RTL_W32(rTxAGC_A_Mcs07_Mcs04, priv->pshare->phw->power_backup[0x05]); + RTL_W32(rTxAGC_A_Mcs11_Mcs08, priv->pshare->phw->power_backup[0x06]); + RTL_W32(rTxAGC_A_Mcs15_Mcs12, priv->pshare->phw->power_backup[0x07]); + RTL_W32(rTxAGC_B_Mcs03_Mcs00, priv->pshare->phw->power_backup[0x08]); + RTL_W32(rTxAGC_B_Mcs07_Mcs04, priv->pshare->phw->power_backup[0x09]); + RTL_W32(rTxAGC_B_Mcs11_Mcs08, priv->pshare->phw->power_backup[0x0a]); + RTL_W32(rTxAGC_B_Mcs15_Mcs12, priv->pshare->phw->power_backup[0x0b]); + RTL_W32(rTxAGC_A_CCK11_2_B_CCK11, priv->pshare->phw->power_backup[0x0c]); + RTL_W32(rTxAGC_A_CCK1_Mcs32, priv->pshare->phw->power_backup[0x0d]); + RTL_W32(rTxAGC_B_CCK5_1_Mcs32, priv->pshare->phw->power_backup[0x0e]); + priv->pshare->phw->lower_tx_power = 0; + RESTORE_INT(x); + } +} +#endif + +#if 0 +int get_CCK_swing_index(struct rtl8192cd_priv *priv) +{ + int TempCCk, index=12, i; + short channel; +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) + channel=priv->pshare->working_channel; + else +#endif + channel = (priv->pmib->dot11RFEntry.dot11channel); + + //Query CCK default setting From 0xa24 + TempCCk = PHY_QueryBBReg(priv, rCCK0_TxFilter2, bMaskDWord)&bMaskCCK; + TempCCk = cpu_to_le32(TempCCk); + for(i=0 ; ipshare->rf_ft_var.mp_specific) + channel=priv->pshare->working_channel; + else +#endif + channel = (priv->pmib->dot11RFEntry.dot11channel); + + +#ifdef CONFIG_RTL_88E_SUPPORT //for 88e tx power tracking + if(GET_CHIP_VER(priv) == VERSION_8188E){ + if(channel !=14) { + RTL_W8( 0xa22, 0x1c); + RTL_W8( 0xa23, 0x1a); + RTL_W8( 0xa24, 0x18); + RTL_W8( 0xa25, 0x12); + RTL_W8( 0xa26, 0xe); + RTL_W8( 0xa27, 0x8); + RTL_W8( 0xa28, 0x4); + RTL_W8( 0xa29, 0x2); + } + else{ + RTL_W8( 0xa22, 0x1c); + RTL_W8( 0xa23, 0x1a); + RTL_W8( 0xa24, 0x18); + RTL_W8( 0xa25, 0x12); + RTL_W8( 0xa26, 0x0); + RTL_W8( 0xa27, 0x0); + RTL_W8( 0xa28, 0x0); + RTL_W8( 0xa29, 0x0); + } + } + else +#endif + if(channel !=14) { + RTL_W8( 0xa22, CCKSwingTable_Ch1_Ch13[CCK_index][0]); + RTL_W8( 0xa23, CCKSwingTable_Ch1_Ch13[CCK_index][1]); + RTL_W8( 0xa24, CCKSwingTable_Ch1_Ch13[CCK_index][2]); + RTL_W8( 0xa25, CCKSwingTable_Ch1_Ch13[CCK_index][3]); + RTL_W8( 0xa26, CCKSwingTable_Ch1_Ch13[CCK_index][4]); + RTL_W8( 0xa27, CCKSwingTable_Ch1_Ch13[CCK_index][5]); + RTL_W8( 0xa28, CCKSwingTable_Ch1_Ch13[CCK_index][6]); + RTL_W8( 0xa29, CCKSwingTable_Ch1_Ch13[CCK_index][7]); + } + else{ + RTL_W8( 0xa22, CCKSwingTable_Ch14[CCK_index][0]); + RTL_W8( 0xa23, CCKSwingTable_Ch14[CCK_index][1]); + RTL_W8( 0xa24, CCKSwingTable_Ch14[CCK_index][2]); + RTL_W8( 0xa25, CCKSwingTable_Ch14[CCK_index][3]); + RTL_W8( 0xa26, CCKSwingTable_Ch14[CCK_index][4]); + RTL_W8( 0xa27, CCKSwingTable_Ch14[CCK_index][5]); + RTL_W8( 0xa28, CCKSwingTable_Ch14[CCK_index][6]); + RTL_W8( 0xa29, CCKSwingTable_Ch14[CCK_index][7]); + } +} +#endif + +unsigned char getThermalValue(struct rtl8192cd_priv *priv) +{ + unsigned char ThermalValue; + int sum=0, i=0; + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_T_METER, bMask20Bits, 0x60); + while ((PHY_QueryRFReg(priv, RF92CD_PATH_A, RF_T_METER, bMask20Bits, 1) > 0x1f) && ((i++) < 1000)) {//<20ms, test is in 20 us + delay_us(20); + } + ThermalValue =(unsigned char)PHY_QueryRFReg(priv, RF92CD_PATH_A, RF_T_METER, bMask20Bits, 1) & 0x01f; + priv->pshare->Thermal_idx = (priv->pshare->Thermal_idx+1)%8; + priv->pshare->Thermal_log[ priv->pshare->Thermal_idx ] = ThermalValue; + for(i=0; i<8; i++) { + if(!priv->pshare->Thermal_log[i]) + return ThermalValue; + sum += priv->pshare->Thermal_log[i]; + } + return (sum+4)>>3; +} + + +#ifdef CONFIG_RTL_92C_SUPPORT + +#ifdef HIGH_POWER_EXT_PA +void swingIndexRemap2(int *a, int b, int i) +{ + + u8 index_mapping_HighPower_92C[4][15] = { + {0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 18, 18}, //2.4G, path A/MAC 0, decrease power + {0, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22}, //2.4G, path A/MAC 0, increase power + {0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 18, 18}, //2.4G, path A/MAC 0, decrease power + {0, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18, 20, 21, 23}, //2.4G, path A/MAC 0, increase power + }; + + int d = RTL_ABS(*a, b); + int offset = 0; + + + if(i == 0) + offset = 1; + else + offset = 3; + + if(*a < b ) + { + //printk("\n\n Increase Power !! \n\n"); + *a = b - index_mapping_HighPower_92C[offset][d]; + } + else + { + //printk("\n\n Decrease Power !! \n\n"); + offset = offset - 1; + *a = b + index_mapping_HighPower_92C[offset][d]; + } + + //printk("\n\ a = %d, b = %d, offset = %d, d = %d, diff = %d \n\n", + //*a, b, offset, d, index_mapping_HighPower_92C[offset][d]); + +} +void swingIndexRemap(int *a, int b) +{ + int d = (RTL_ABS(*a, b) *3)>>1; + if(*a < b ) + *a = b - d; + else + *a = b + d; +} +#endif + +void tx_power_tracking(struct rtl8192cd_priv *priv) +{ + unsigned char ThermalValue = 0, delta, delta_LCK, delta_IQK; + int ele_A, ele_D, value32, X, Y, ele_C; + int OFDM_index[2]={0,0}, CCK_index; + int i = 0; + char is2T = ((GET_CHIP_VER(priv) == VERSION_8192C) ?1 :0); + unsigned char TxPwrLevel[2]; + unsigned char channel, OFDM_min_index = 6, rf=1; //OFDM BB Swing should be less than +3.0dB, which is required by Arthur +#ifdef POWER_PERCENT_ADJUSTMENT + signed char pwrdiff_percent; +#endif +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { + channel=priv->pshare->working_channel; + if(priv->pshare->mp_txpwr_tracking == FALSE) + return; + } else +#endif + { + channel = (priv->pmib->dot11RFEntry.dot11channel); + } + + ThermalValue = getThermalValue(priv); + + rf += is2T; + if(ThermalValue) { + + if(!priv->pshare->ThermalValue) { + priv->pshare->ThermalValue = priv->pmib->dot11RFEntry.ther; + priv->pshare->ThermalValue_LCK = ThermalValue; + priv->pshare->ThermalValue_IQK = ThermalValue; + + //Query OFDM path A default setting + ele_D = PHY_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D; + for(i=0; ipshare->OFDM_index[0] = i; + priv->pshare->OFDM_index0[0] = i; + break; + } + } + + //Query OFDM path B default setting + if(is2T) { + ele_D = PHY_QueryBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D; + for(i=0; ipshare->OFDM_index[1] = i; + priv->pshare->OFDM_index0[1] = i; + break; + } + } + } + priv->pshare->CCK_index = get_CCK_swing_index(priv); + priv->pshare->CCK_index0 = priv->pshare->CCK_index; + + } + + delta = RTL_ABS(ThermalValue, priv->pshare->ThermalValue); + delta_LCK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_LCK); + delta_IQK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_IQK); + +// printk("Readback Thermal Meter = 0x%lx pre thermal meter 0x%lx EEPROMthermalmeter 0x%lx delta 0x%lx delta_LCK 0x%lx delta_IQK 0x%lx\n", +// ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther, delta, delta_LCK, delta_IQK); + + if(delta_LCK > 1) { + priv->pshare->ThermalValue_LCK = ThermalValue; +#ifdef MP_TEST + if(priv->pshare->rf_ft_var.mp_specific) + { + if((OPMODE & WIFI_MP_CTX_BACKGROUND) && !(OPMODE & WIFI_MP_CTX_PACKET)) + printk("NOT do LCK during ctx !!!! \n"); + else + PHY_LCCalibrate(priv); + } + else +#endif + PHY_LCCalibrate(priv); + } + + if(delta > 0) { + if(ThermalValue > priv->pshare->ThermalValue) { + for(i = 0; i < rf; i++) + priv->pshare->OFDM_index[i] -= delta; + priv->pshare->CCK_index -= delta; + } else { + for(i = 0; i < rf; i++) + priv->pshare->OFDM_index[i] += delta; + priv->pshare->CCK_index += delta; + } + if(ThermalValue > priv->pmib->dot11RFEntry.ther) { + for(i = 0; i < rf; i++) + OFDM_index[i] = priv->pshare->OFDM_index[i]+1; + CCK_index = priv->pshare->CCK_index+1; + } else { + for(i = 0; i < rf; i++) + OFDM_index[i] = priv->pshare->OFDM_index[i]; + CCK_index = priv->pshare->CCK_index; + } +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { + TxPwrLevel[0] = priv->pshare->mp_txpwr_patha; + TxPwrLevel[1] = priv->pshare->mp_txpwr_pathb; + } else +#endif + { + TxPwrLevel[0] = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[channel-1]; + TxPwrLevel[1] = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_B[channel-1]; + + if (priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) { + unsigned char offset = (priv->pmib->dot11RFEntry.pwrdiffHT20[channel-1] & 0x0f); + TxPwrLevel[0] = COUNT_SIGN_OFFSET(TxPwrLevel[0], offset); + offset = ((priv->pmib->dot11RFEntry.pwrdiffOFDM[channel-1] & 0xf0) >> 4); + TxPwrLevel[1] = COUNT_SIGN_OFFSET(TxPwrLevel[1], offset); + } +#ifdef POWER_PERCENT_ADJUSTMENT + pwrdiff_percent = PwrPercent2PwrLevel(priv->pmib->dot11RFEntry.power_percent); + TxPwrLevel[0] = POWER_RANGE_CHECK(TxPwrLevel[0]+pwrdiff_percent); + TxPwrLevel[1] = POWER_RANGE_CHECK(TxPwrLevel[1]+pwrdiff_percent); +#endif + } + +// printk("TxPwrLevel[0]=%d, TxPwrLevel[1]=%d\n", TxPwrLevel[0], TxPwrLevel[1]); + for(i = 0; i < rf; i++) { + if(/*TxPwrLevel[i] >=0 &&*/ TxPwrLevel[i] <=26) { + if(ThermalValue > priv->pmib->dot11RFEntry.ther) { + if (delta < 5) + OFDM_index[i] -= 1; + else + OFDM_index[i] -= 2; + } else if(delta > 5 && ThermalValue < priv->pmib->dot11RFEntry.ther) { + OFDM_index[i] += 1; + } + } else if (TxPwrLevel[i] >= 27 && TxPwrLevel[i] <= 32 && ThermalValue > priv->pmib->dot11RFEntry.ther) { + if (delta < 5) + OFDM_index[i] -= 1; + else + OFDM_index[i] -= 2; + } else if (TxPwrLevel[i] >= 32 && TxPwrLevel[i] <= 38 && ThermalValue > priv->pmib->dot11RFEntry.ther && delta > 5) { + OFDM_index[i] -= 1; + } + +#ifdef _TRACKING_TABLE_FILE + if (priv->pshare->rf_ft_var.pwr_track_file) + { + int d = 0; + + OFDM_index[i] = priv->pshare->OFDM_index[i]; + d = RTL_ABS(OFDM_index[i], priv->pshare->OFDM_index0[i]); + + if(OFDM_index[i] < priv->pshare->OFDM_index0[i]) + { + OFDM_index[i] = priv->pshare->OFDM_index0[i] - get_tx_tracking_index(priv, channel, i, d, 0, 0); + } + else + { + OFDM_index[i] = priv->pshare->OFDM_index0[i] + get_tx_tracking_index(priv, channel, i, d, 1, 0); + } + + } + else +#endif + { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + OFDM_index[i] = priv->pshare->OFDM_index[i]; + swingIndexRemap2(&OFDM_index[i], priv->pshare->OFDM_index0[i], i); //Modify HP tracking table, from Arthur 2012.02.13 + //swingIndexRemap(&OFDM_index[i], priv->pshare->OFDM_index0[i]); + } +#endif + } + if(OFDM_index[i] > OFDM_TABLE_SIZE-1) + OFDM_index[i] = OFDM_TABLE_SIZE-1; + else if (OFDM_index[i] < OFDM_min_index) + OFDM_index[i] = OFDM_min_index; + } + i=0; + { + if(/*TxPwrLevel[i] >=0 &&*/ TxPwrLevel[i] <=26) { + if(ThermalValue > priv->pmib->dot11RFEntry.ther) { + if (delta < 5) + CCK_index -= 1; + else + CCK_index -= 2; + } else if(delta > 5 && ThermalValue < priv->pmib->dot11RFEntry.ther) { + CCK_index += 1; + } + } else if (TxPwrLevel[i] >= 27 && TxPwrLevel[i] <= 32 && ThermalValue > priv->pmib->dot11RFEntry.ther) { + if (delta < 5) + CCK_index -= 1; + else + CCK_index -= 2; + } else if (TxPwrLevel[i] >= 32 && TxPwrLevel[i] <= 38 && ThermalValue > priv->pmib->dot11RFEntry.ther && delta > 5) { + CCK_index -= 1; + } + +#ifdef _TRACKING_TABLE_FILE + if (priv->pshare->rf_ft_var.pwr_track_file) + { + int d = 0; + + CCK_index = priv->pshare->CCK_index; + d = RTL_ABS(CCK_index, priv->pshare->CCK_index0); + + if(CCK_index < priv->pshare->CCK_index0) + { + CCK_index = priv->pshare->CCK_index0 - get_tx_tracking_index(priv, channel, i, d, 0, 1); + } + else + { + CCK_index = priv->pshare->CCK_index0 + get_tx_tracking_index(priv, channel, i, d, 1, 1); + } + + } + else +#endif + { +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + CCK_index = priv->pshare->CCK_index; + swingIndexRemap2( &CCK_index, priv->pshare->CCK_index0, i); //Modify HP tracking table, from Arthur 2012.02.13 + //swingIndexRemap( &CCK_index, priv->pshare->CCK_index0); + } +#endif + } + if(CCK_index > CCK_TABLE_SIZE-1) + CCK_index = CCK_TABLE_SIZE-1; + else if (CCK_index < 0) + CCK_index = 0; + } + + //Adujst OFDM Ant_A according to IQK result + ele_D = (OFDMSwingTable[(unsigned int)OFDM_index[0]] & 0xFFC00000)>>22; + X = priv->pshare->RegE94; + Y = priv->pshare->RegE9C; + + if(X != 0) { + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + ele_A = ((X * ele_D)>>8)&0x000003FF; + + //new element C = element D x Y + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + ele_C = ((Y * ele_D)>>8)&0x000003FF; + + //wirte new elements A, C, D to regC80 and regC94, element B is always 0 + value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, value32); + + value32 = (ele_C&0x000003C0)>>6; + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, value32); + + value32 = ((X * ele_D)>>7)&0x01; + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), value32); + + } else { + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned int)OFDM_index[0]]); + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), 0x00); + } + + + set_CCK_swing_index(priv, CCK_index); + + + if(is2T) { + ele_D = (OFDMSwingTable[(unsigned int)OFDM_index[1]] & 0xFFC00000)>>22; + X = priv->pshare->RegEB4; + Y = priv->pshare->RegEBC; + + if(X != 0) { + if ((X & 0x00000200) != 0) //consider minus + X = X | 0xFFFFFC00; + ele_A = ((X * ele_D)>>8)&0x000003FF; + + //new element C = element D x Y + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + ele_C = ((Y * ele_D)>>8)&0x00003FF; + + //wirte new elements A, C, D to regC88 and regC9C, element B is always 0 + value32=(ele_D<<22)|((ele_C&0x3F)<<16) |ele_A; + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, value32); + + value32 = (ele_C&0x000003C0)>>6; + PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, value32); + + value32 = ((X * ele_D)>>7)&0x01; + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), value32); + + } else { + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned int)OFDM_index[1]]); + PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), 0x00); + } + } + } + + if(delta_IQK > 3) { + priv->pshare->ThermalValue_IQK = ThermalValue; +#ifdef MP_TEST + if(priv->pshare->rf_ft_var.mp_specific) + { + if((OPMODE & WIFI_MP_CTX_BACKGROUND) && !(OPMODE & WIFI_MP_CTX_PACKET)) + printk("NOT do IQK during ctx !!!! \n"); + else + PHY_IQCalibrate(priv); + } + else +#endif + PHY_IQCalibrate(priv); + } + + //update thermal meter value + priv->pshare->ThermalValue = ThermalValue; + + } +} +#endif + + +#ifdef RX_GAIN_TRACK_92D +static void rx_gain_tracking_92D(struct rtl8192cd_priv *priv) +{ + u8 index_mapping[Rx_index_mapping_NUM] = { + 0x0f, 0x0f, 0x0f, 0x0f, 0x0b, + 0x0a, 0x09, 0x08, 0x07, 0x06, + 0x05, 0x04, 0x04, 0x03, 0x02 + }; + + u8 eRFPath, curMaxRFPath; + u32 u4tmp; + + u4tmp = (index_mapping[(priv->pmib->dot11RFEntry.ther - priv->pshare->ThermalValue_RxGain)]) << 12; + + DEBUG_INFO("===>%s interface %d Rx Gain %x\n", __FUNCTION__, priv->pshare->wlandev_idx, u4tmp); + + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + curMaxRFPath = RF92CD_PATH_B; + else + curMaxRFPath = RF92CD_PATH_MAX; + + for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) + PHY_SetRFReg(priv, eRFPath, 0x3C, bMask20Bits, (priv->pshare->RegRF3C[eRFPath]&(~(0xF000)))|u4tmp); + +}; + +#endif + +#if 0 +//#ifdef CONFIG_RTL_88E_SUPPORT //for 88e tx power tracking + +void ODM_ResetIQKResult(struct rtl8192cd_priv *priv) +{ +/* +#if (DM_ODM_SUPPORT_TYPE == ODM_WIN || DM_ODM_SUPPORT_TYPE == ODM_CE) + PADAPTER Adapter = pDM_Odm->Adapter; + u1Byte i; + + if (!IS_HARDWARE_TYPE_8192D(Adapter)) + return; +#endif +*/ + + unsigned char i; + + //printk("PHY_ResetIQKResult:: settings regs %d default regs %d\n", sizeof(priv->pshare->IQKMatrixRegSetting)/sizeof(IQK_MATRIX_REGS_SETTING), IQK_Matrix_Settings_NUM); + //0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc + + for(i = 0; i < IQK_Matrix_Settings_NUM; i++) + { + { + priv->pshare->IQKMatrixRegSetting[i].Value[0][0] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][2] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][4] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][6] = 0x100; + + priv->pshare->IQKMatrixRegSetting[i].Value[0][1] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][3] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][5] = + priv->pshare->IQKMatrixRegSetting[i].Value[0][7] = 0x0; + + priv->pshare->IQKMatrixRegSetting[i].bIQKDone = FALSE; + + } + } + +} + +#define RF_PATH_A 0 //Radio Path A +#define OFDM_TABLE_SIZE_92D 43 + +#define bRFRegOffsetMask 0xfffff + + +//091212 chiyokolin +void odm_TXPowerTrackingCallback_ThermalMeter_8188E(struct rtl8192cd_priv *priv) +{ + + //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter); + + unsigned char ThermalValue = 0, delta, delta_LCK, delta_IQK, offset; + unsigned char ThermalValue_AVG_count = 0; + unsigned int ThermalValue_AVG = 0; + int ele_A=0, ele_D, TempCCk, X, value32; + int Y, ele_C=0; + char OFDM_index[2], CCK_index=0, OFDM_index_old[2]={0,0}, CCK_index_old=0, index; + unsigned int i = 0, j = 0; + char is2T = FALSE; + //char bInteralPA = FALSE; + + unsigned char OFDM_min_index = 6, rf; //OFDM BB Swing should be less than +3.0dB, which is required by Arthur + unsigned char Indexforchannel = 0/*GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/; + char OFDM_index_mapping[2][index_mapping_NUM_88E] = { + {0, 0, 2, 3, 4, 4, //2.4G, decrease power + 5, 6, 7, 7, 8, 9, + 10, 10, 11}, // For lower temperature, 20120220 updated on 20120220. + {0, 0, -1, -2, -3, -4, //2.4G, increase power + -4, -4, -4, -5, -7, -8, + -9, -9, -10}, + }; + unsigned char Thermal_mapping[2][index_mapping_NUM_88E] = { + {0, 2, 4, 6, 8, 10, //2.4G, decrease power + 12, 14, 16, 18, 20, 22, + 24, 26, 27}, + {0, 2, 4, 6, 8, 10, //2.4G,, increase power + 12, 14, 16, 18, 20, 22, + 25, 25, 25}, + }; + + priv->pshare->TXPowerTrackingCallbackCnt++; //cosa add for debug + priv->pshare->bTXPowerTrackingInit = TRUE; + +#if (MP_DRIVER == 1) + priv->pshare->TxPowerTrackControl = 1; //priv->pshare->TxPowerTrackControl; //_eric_?? // We should keep updating the control variable according to HalData. + // pshare->RegA24 will be initialized when ODM HW configuring, but MP configures with para files. + priv->pshare->RegA24 = 0x090e1317; +#endif + + +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { + if(priv->pshare->mp_txpwr_tracking == FALSE) + return; + } +#endif + + if(priv->pshare->Power_tracking_on_88E == 0) + { + priv->pshare->Power_tracking_on_88E = 1; + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x42, (BIT(17) | BIT(16)), 0x03); + return; + } + else + { + + priv->pshare->Power_tracking_on_88E = 0; + + //printk("===>dm_TXPowerTrackingCallback_ThermalMeter_8188E txpowercontrol %d\n", priv->pshare->TxPowerTrackControl); + + ThermalValue = (unsigned char)PHY_QueryRFReg(priv, RF_PATH_A, RF_T_METER_88E, 0xfc00, 1); //0x42: RF Reg[15:10] 88E + + printk("\nReadback Thermal Meter = 0x%x pre thermal meter 0x%x EEPROMthermalmeter 0x%x\n", ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther); + + } + + if(is2T) + rf = 2; + else + rf = 1; + + if(ThermalValue) + { +// if(!pHalData->ThermalValue) + { + //Query OFDM path A default setting + ele_D = PHY_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D; + + for(i=0; ipshare->RegA24; + + for(i=0 ; ipshare->bCCKinCH14) + { + if(memcmp((void*)&TempCCk, (void*)&CCKSwingTable_Ch14[i][2], 4)==0) + { + CCK_index_old =(unsigned char) i; + //printk("Initial reg0x%x = 0x%x, CCK_index=0x%x, ch 14 %d\n", + //rCCK0_TxFilter2, TempCCk, CCK_index_old, priv->pshare->bCCKinCH14); + break; + } + } + else + { + //printk("RegA24: 0x%X, CCKSwingTable_Ch1_Ch13[%d][2]: CCKSwingTable_Ch1_Ch13[i][2]: 0x%X\n", TempCCk, i, CCKSwingTable_Ch1_Ch13[i][2]); + if(memcmp((void*)&TempCCk, (void*)&CCKSwingTable_Ch1_Ch13[i][2], 4)==0) + { + CCK_index_old =(unsigned char) i; + //printk("Initial reg0x%x = 0x%x, CCK_index=0x%x, ch14 %d\n", + //rCCK0_TxFilter2, TempCCk, CCK_index_old, priv->pshare->bCCKinCH14); + break; + } + } + } + } + + if(!priv->pshare->ThermalValue) + { + priv->pshare->ThermalValue = priv->pmib->dot11RFEntry.ther; + priv->pshare->ThermalValue_LCK = ThermalValue; + priv->pshare->ThermalValue_IQK = ThermalValue; + + for(i = 0; i < rf; i++) + priv->pshare->OFDM_index[i] = OFDM_index_old[i]; + priv->pshare->CCK_index = CCK_index_old; + } + + if(priv->pshare->bReloadtxpowerindex) + { + printk("reload ofdm index for band switch\n"); + } + + //calculate average thermal meter + { + priv->pshare->ThermalValue_AVG[priv->pshare->ThermalValue_AVG_index] = ThermalValue; + priv->pshare->ThermalValue_AVG_index++; + if(priv->pshare->ThermalValue_AVG_index == AVG_THERMAL_NUM_88E) + priv->pshare->ThermalValue_AVG_index = 0; + + for(i = 0; i < AVG_THERMAL_NUM_88E; i++) + { + if(priv->pshare->ThermalValue_AVG[i]) + { + ThermalValue_AVG += priv->pshare->ThermalValue_AVG[i]; + ThermalValue_AVG_count++; + } + } + + if(ThermalValue_AVG_count) + { + ThermalValue = (unsigned char)(ThermalValue_AVG / ThermalValue_AVG_count); + printk("AVG Thermal Meter = 0x%x \n", ThermalValue); + } + } + } + + if(priv->pshare->bReloadtxpowerindex) + { + delta = ThermalValue > priv->pmib->dot11RFEntry.ther?(ThermalValue - priv->pmib->dot11RFEntry.ther):(priv->pmib->dot11RFEntry.ther - ThermalValue); + priv->pshare->bReloadtxpowerindex = FALSE; + priv->pshare->bDoneTxpower = FALSE; + } + else if(priv->pshare->bDoneTxpower) + { + delta = (ThermalValue > priv->pshare->ThermalValue)?(ThermalValue - priv->pshare->ThermalValue):(priv->pshare->ThermalValue - ThermalValue); + } + else + { + delta = ThermalValue > priv->pmib->dot11RFEntry.ther?(ThermalValue - priv->pmib->dot11RFEntry.ther):(priv->pmib->dot11RFEntry.ther - ThermalValue); + } + delta_LCK = (ThermalValue > priv->pshare->ThermalValue_LCK)?(ThermalValue - priv->pshare->ThermalValue_LCK):(priv->pshare->ThermalValue_LCK - ThermalValue); + delta_IQK = (ThermalValue > priv->pshare->ThermalValue_IQK)?(ThermalValue - priv->pshare->ThermalValue_IQK):(priv->pshare->ThermalValue_IQK - ThermalValue); + + printk("Readback Thermal Meter = 0x%x \npre thermal meter 0x%x EEPROMthermalmeter 0x%x delta 0x%x \ndelta_LCK 0x%x delta_IQK 0x%x \n", ThermalValue, priv->pshare->ThermalValue, priv->pshare->EEPROMThermalMeter, delta, delta_LCK, delta_IQK); + printk("pre thermal meter LCK 0x%x \npre thermal meter IQK 0x%x \ndelta_LCK_bound 0x%x delta_IQK_bound 0x%x\n", priv->pshare->ThermalValue_LCK, priv->pshare->ThermalValue_IQK, priv->pshare->Delta_LCK, priv->pshare->Delta_IQK); + + + //if((delta_LCK > pHalData->Delta_LCK) && (pHalData->Delta_LCK != 0)) + if (delta_LCK >= 8) // Delta temperature is equal to or larger than 20 centigrade. + { + priv->pshare->ThermalValue_LCK = ThermalValue; + PHY_LCCalibrate(priv); + } + + + if(delta > 0 && priv->pshare->TxPowerTrackControl) + { + delta = ThermalValue > priv->pmib->dot11RFEntry.ther?(ThermalValue - priv->pmib->dot11RFEntry.ther):(priv->pmib->dot11RFEntry.ther - ThermalValue); + + //calculate new OFDM / CCK offset + { + { + if(ThermalValue > priv->pmib->dot11RFEntry.ther) + j = 1; + else + j = 0; + + for(offset = 0; offset < index_mapping_NUM_88E; offset++) + { + if(delta < Thermal_mapping[j][offset]) + { + if(offset != 0) + offset--; + break; + } + } + if(offset >= index_mapping_NUM_88E) + offset = index_mapping_NUM_88E-1; + + index = OFDM_index_mapping[j][offset]; + + printk("\nj = %d delta = %d, index = %d\n\n", j, delta, index); + + for(i = 0; i < rf; i++) + OFDM_index[i] = priv->pshare->OFDM_index[i] + OFDM_index_mapping[j][offset]; + CCK_index = priv->pshare->CCK_index + OFDM_index_mapping[j][offset]; + } + + if(is2T) + { + printk("temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n", + priv->pshare->OFDM_index[0], priv->pshare->OFDM_index[1], priv->pshare->CCK_index); + } + else + { + printk("temp OFDM_A_index=0x%x, CCK_index=0x%x\n", + priv->pshare->OFDM_index[0], priv->pshare->CCK_index); + } + + for(i = 0; i < rf; i++) + { + if(OFDM_index[i] > OFDM_TABLE_SIZE_92D-1) + { + OFDM_index[i] = OFDM_TABLE_SIZE_92D-1; + } + else if (OFDM_index[i] < OFDM_min_index) + { + OFDM_index[i] = OFDM_min_index; + } + } + + { + if(CCK_index > CCK_TABLE_SIZE-1) + CCK_index = CCK_TABLE_SIZE-1; + else if (CCK_index < 0) + CCK_index = 0; + } + + if(is2T) + { + printk("new OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n", + OFDM_index[0], OFDM_index[1], CCK_index); + } + else + { + printk("new OFDM_A_index=0x%x, CCK_index=0x%x\n", + OFDM_index[0], CCK_index); + } + } + + //2 temporarily remove bNOPG + //Config by SwingTable + if(priv->pshare->TxPowerTrackControl /*&& !pHalData->bNOPG*/) + { + priv->pshare->bDoneTxpower = TRUE; + + //Adujst OFDM Ant_A according to IQK result + ele_D = (OFDMSwingTable[(unsigned char)OFDM_index[0]] & 0xFFC00000)>>22; + X = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][0]; + Y = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][1]; + + if(X != 0) + { + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + ele_A = ((X * ele_D)>>8)&0x000003FF; + + //new element C = element D x Y + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + ele_C = ((Y * ele_D)>>8)&0x000003FF; + + //wirte new elements A, C, D to regC80 and regC94, element B is always 0 + value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, value32); + + value32 = (ele_C&0x000003C0)>>6; + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, value32); + + value32 = ((X * ele_D)>>7)&0x01; + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), value32); + + } + else + { + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned char)OFDM_index[0]]); + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), 0x00); + } + + //printk("TxPwrTracking for path A: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x 0xe94 = 0x%x 0xe9c = 0x%x\n", + //(unsigned int)X, (unsigned int)Y, (unsigned int)ele_A, (unsigned int)ele_C, (unsigned int)ele_D, (unsigned int)X, (unsigned int)Y); + + { + //Adjust CCK according to IQK result + if(!priv->pshare->bCCKinCH14){ + RTL_W8(0xa22, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][0]); + RTL_W8(0xa23, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][1]); + RTL_W8(0xa24, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][2]); + RTL_W8(0xa25, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][3]); + RTL_W8(0xa26, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][4]); + RTL_W8(0xa27, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][5]); + RTL_W8(0xa28, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][6]); + RTL_W8(0xa29, CCKSwingTable_Ch1_Ch13[(unsigned char)CCK_index][7]); + } + else{ + RTL_W8(0xa22, CCKSwingTable_Ch14[(unsigned char)CCK_index][0]); + RTL_W8(0xa23, CCKSwingTable_Ch14[(unsigned char)CCK_index][1]); + RTL_W8(0xa24, CCKSwingTable_Ch14[(unsigned char)CCK_index][2]); + RTL_W8(0xa25, CCKSwingTable_Ch14[(unsigned char)CCK_index][3]); + RTL_W8(0xa26, CCKSwingTable_Ch14[(unsigned char)CCK_index][4]); + RTL_W8(0xa27, CCKSwingTable_Ch14[(unsigned char)CCK_index][5]); + RTL_W8(0xa28, CCKSwingTable_Ch14[(unsigned char)CCK_index][6]); + RTL_W8(0xa29, CCKSwingTable_Ch14[(unsigned char)CCK_index][7]); + } + } + + if(is2T) + { + ele_D = (OFDMSwingTable[(unsigned char)OFDM_index[1]] & 0xFFC00000)>>22; + + //new element A = element D x X + X = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][4]; + Y = priv->pshare->IQKMatrixRegSetting[Indexforchannel].Value[0][5]; + + //if(X != 0 && pHalData->CurrentBandType92D == ODM_BAND_ON_2_4G) + if((X != 0) && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G)) + + { + if ((X & 0x00000200) != 0) //consider minus + X = X | 0xFFFFFC00; + ele_A = ((X * ele_D)>>8)&0x000003FF; + + //new element C = element D x Y + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + ele_C = ((Y * ele_D)>>8)&0x00003FF; + + //wirte new elements A, C, D to regC88 and regC9C, element B is always 0 + value32=(ele_D<<22)|((ele_C&0x3F)<<16) |ele_A; + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, value32); + + value32 = (ele_C&0x000003C0)>>6; + PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, value32); + + value32 = ((X * ele_D)>>7)&0x01; + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), value32); + + } + else + { + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable[(unsigned char)OFDM_index[1]]); + PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), 0x00); + } + + //printk("TxPwrTracking path B: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x 0xeb4 = 0x%x 0xebc = 0x%x\n", + //(unsigned int)X, (unsigned int)Y, (unsigned int)ele_A, (unsigned int)ele_C, (unsigned int)ele_D, (unsigned int)X, (unsigned int)Y); + } + + printk("TxPwrTracking 0xc80 = 0x%x, 0xc94 = 0x%x RF 0x24 = 0x%x\n\n", PHY_QueryBBReg(priv, 0xc80, bMaskDWord), PHY_QueryBBReg(priv, 0xc94, bMaskDWord), PHY_QueryRFReg(priv, RF_PATH_A, 0x24, bRFRegOffsetMask, 1)); + } + } + + +#if 0 //DO NOT do IQK during 88E power tracking + // if((delta_IQK > pHalData->Delta_IQK) && (pHalData->Delta_IQK != 0)) + if (delta_IQK >= 8) // Delta temperature is equal to or larger than 20 centigrade. + { + ODM_ResetIQKResult(priv); + +/* +#if(DM_ODM_SUPPORT_TYPE & ODM_WIN) +#if (DEV_BUS_TYPE == RT_PCI_INTERFACE) +#if USE_WORKITEM + PlatformAcquireMutex(&pHalData->mxChnlBwControl); +#else + PlatformAcquireSpinLock(Adapter, RT_CHANNEL_AND_BANDWIDTH_SPINLOCK); +#endif +#elif((DEV_BUS_TYPE == RT_USB_INTERFACE) || (DEV_BUS_TYPE == RT_SDIO_INTERFACE)) + PlatformAcquireMutex(&pHalData->mxChnlBwControl); +#endif +#endif +*/ + priv->pshare->ThermalValue_IQK= ThermalValue; + PHY_IQCalibrate_8188E(priv, FALSE); + +/* +#if(DM_ODM_SUPPORT_TYPE & ODM_WIN) +#if (DEV_BUS_TYPE == RT_PCI_INTERFACE) +#if USE_WORKITEM + PlatformReleaseMutex(&pHalData->mxChnlBwControl); +#else + PlatformReleaseSpinLock(Adapter, RT_CHANNEL_AND_BANDWIDTH_SPINLOCK); +#endif +#elif((DEV_BUS_TYPE == RT_USB_INTERFACE) || (DEV_BUS_TYPE == RT_SDIO_INTERFACE)) + PlatformReleaseMutex(&pHalData->mxChnlBwControl); +#endif +#endif +*/ + } +#endif + + //update thermal meter value + if(priv->pshare->TxPowerTrackControl) + { + //Adapter->HalFunc.SetHalDefVarHandler(Adapter, HAL_DEF_THERMAL_VALUE, &ThermalValue); + priv->pshare->ThermalValue = ThermalValue; + } + + } + + //printk("<===dm_TXPowerTrackingCallback_ThermalMeter_8188E\n"); + + priv->pshare->TXPowercount = 0; + +} + + + + +#endif + + + +#ifdef CONFIG_RTL_92D_SUPPORT + +void getDeltaValue(struct rtl8192cd_priv *priv) +{ + unsigned int tempval[2]; + + tempval[0] = priv->pmib->dot11RFEntry.deltaIQK; + tempval[1] = priv->pmib->dot11RFEntry.deltaLCK; + + switch(tempval[0]) + { + case 0: + tempval[0] = 5; + break; + + case 1: + tempval[0] = 4; + break; + + case 2: + tempval[0] = 3; + break; + + case 3: + default: + tempval[0] = 0; + break; + } + + switch(tempval[1]) + { + case 0: + tempval[1] = 4; + break; + + case 1: + tempval[1] = 3; + break; + + case 2: + tempval[1] = 2; + break; + + case 3: + default: + tempval[1] = 0; + break; + } + + priv->pshare->Delta_IQK = tempval[0]; + priv->pshare->Delta_LCK = tempval[1]; +} + +void tx_power_tracking_92D(struct rtl8192cd_priv *priv) +{ + u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, index[2], offset, ThermalValue_AVG_count = 0; + u32 ThermalValue_AVG = 0; + int ele_A, ele_D, X, value32, Y, ele_C; + char OFDM_index[2], CCK_index=0; + int i = 0; + char is2T = ((priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) ?1 :0); + u8 OFDM_min_index = 6, OFDM_min_index_internalPA = 5, rf=1, channel; //OFDM BB Swing should be less than +3.0dB, which is required by Arthur u1Byte OFDM_min_index = 6, rf; //OFDM BB Swing should be less than +3.0dB, which is required by Arthur + + u8 index_mapping[5][index_mapping_NUM] = { + {0, 1, 3, 6, 8, 9, //5G, path A/MAC 0, decrease power + 11, 13, 14, 16, 17, 18, 18}, + {0, 2, 4, 5, 7, 10, //5G, path A/MAC 0, increase power + 12, 14, 16, 18, 18, 18, 18}, + {0, 2, 3, 6, 8, 9, //5G, path B/MAC 1, decrease power + 11, 13, 14, 16, 17, 18, 18}, + {0, 2, 4, 5, 7, 10, //5G, path B/MAC 1, increase power + 13, 16, 16, 18, 18, 18, 18}, + {0, 1, 2, 3, 4, 5, //2.4G, for decreas power + 6, 7, 7, 8, 9, 10, 10}, + }; + +#if defined(RTL8192D_INT_PA) + + u8 index_mapping_internalPA[8][index_mapping_NUM] = { + {0, 1, 3, 4, 6, 7, //5G, path A/MAC 0, ch36-64, decrease power + 9, 11, 13, 15, 16, 16, 16}, + {0, 1, 3, 4, 6, 7, //5G, path A/MAC 0, ch36-64, increase power + 9, 11, 13, 15, 16, 18, 20}, + {0, 1, 3, 4, 6, 7, //5G, path A/MAC 0, ch100-165, decrease power + 9, 11, 13, 15, 16, 16, 16}, + {0, 1, 3, 4, 6, 7, //5G, path A/MAC 0, ch100-165, increase power + 9, 11, 13, 15, 16, 18, 20}, + {0, 1, 3, 4, 6, 7, //5G, path B/MAC 1, ch36-64, decrease power + 9, 11, 13, 15, 16, 16, 16}, + {0, 1, 3, 4, 6, 7, //5G, path B/MAC 1, ch36-64, increase power + 9, 11, 13, 15, 16, 18, 20}, + {0, 1, 3, 4, 6, 7, //5G, path B/MAC 1, ch100-165, decrease power + 9, 11, 13, 15, 16, 16, 16}, + {0, 1, 3, 4, 6, 7, //5G, path B/MAC 1, ch100-165, increase power + 9, 11, 13, 15, 16, 18, 20}, + }; + + u8 bInteralPA[2]; + +#endif + +#ifdef DPK_92D + short index_mapping_DPK[4][index_mapping_DPK_NUM]={ + {0, 0, 1, 2, 2, //path A current thermal > PG thermal + 3, 4, 5, 5, 6, + 7, 7, 8, 9, 9}, + {0, 0, -1, -2, -3, //path A current thermal < PG thermal + -3, -4, -5, -6, -6, + -7, -8, -9, -9, -10}, + {0, 0, 1, 2, 2, //path B current thermal > PG thermal + 3, 4, 5, 5, 6, + 7, 7, 8, 9, 9}, + {0, 0, -1, -2, -3, //path B current thermal < PG thermal + -3, -4, -5, -6, -6, + -7, -8, -9, -9, -10} + }; + + u8 delta_DPK; + short index_DPK[2] = { 0xb68, 0xb6c }, value_DPK, value_DPK_shift; + int j; + + if(priv->pshare->bDPKworking) { + DEBUG_INFO("DPK in progress abort tx power tracking \n"); + return; + } + +#endif + + +#ifdef HIGH_POWER_EXT_PA //Modify HP tracking table, from Arthur 2012.02.13 + +u8 index_mapping_HighPower_PA[12][index_mapping_NUM] = { + {0, 2, 3, 4, 7, 8, 10, 12, 13, 15, 16, 17, 18}, //5G, path A/MAC 0, ch36-64, decrease power + {0, 2, 4, 7, 8, 10, 11, 15, 17, 19, 21, 23, 23}, //5G, path A/MAC 0, ch36-64, increase power + {0, 4, 5, 8, 9, 11, 14, 15, 16, 17, 18, 19, 20}, //5G, path A/MAC 0, ch100-140, decrease power + {0, 2, 4, 5, 7, 9, 13, 15, 19, 21, 22, 23, 23}, //5G, path A/MAC 0, ch100-140, increase power + {0, 4, 5, 8, 9, 11, 14, 15, 17, 18, 19, 20, 21}, //5G, path A/MAC 0, ch149-165, decrease power + {0, 2, 4, 6, 8, 10, 14, 16, 19, 21, 22, 24, 24}, //5G, path A/MAC 0, ch149-165, increase power + {0, 4, 5, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17}, //5G, path B/MAC 1, ch36-64, decrease power + {0, 2, 4, 7, 8, 10, 11, 15, 17, 19, 21, 23, 23}, //5G, path B/MAC 1, ch36-64, increase power + {0, 3, 4, 6, 7, 9, 12, 13, 14, 15, 17, 18, 19}, //5G, path B/MAC 1, ch100-140, decrease power + {0, 2, 4, 5, 7, 9, 13, 15, 19, 21, 22, 23, 23}, //5G, path B/MAC 1, ch100-140, increase power + {0, 3, 4, 6, 7, 9, 12, 13, 15, 16, 17, 18, 19}, //5G, path B/MAC 1, ch149-165, decrease power + {0, 3, 5, 7, 9, 11, 13, 17, 19, 21, 22, 23, 23}, //5G, path B/MAC 1, ch149-165, increase power + }; + +#endif + +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) { + channel=priv->pshare->working_channel; + if(priv->pshare->mp_txpwr_tracking == FALSE) + return; + } else +#endif + { + channel = (priv->pmib->dot11RFEntry.dot11channel); + } +#if 0 + if (priv->pshare->pwr_trk_ongoing==0) { + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_T_METER_92D, bMask20Bits, 0x30000); + priv->pshare->pwr_trk_ongoing = 1; + return; + } + else +#endif + { + ThermalValue =(unsigned char)PHY_QueryRFReg(priv, RF92CD_PATH_A, RF_T_METER_92D, 0xf800, 1); +// priv->pshare->pwr_trk_ongoing = 0; +#ifdef DPK_92D + priv->pshare->ThermalValue_DPKtrack = ThermalValue; +#endif + } + DEBUG_INFO("Readback Thermal Meter = 0x%lx pre thermal meter 0x%lx EEPROMthermalmeter 0x%lx\n", ThermalValue, + priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther); + + if(is2T) + rf = 2; + else + rf = 1; + + if (ThermalValue) { + + //Query OFDM path A default setting + ele_D = PHY_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D; + for(i=0; ipshare->OFDM_index0[0] = i; + DEBUG_INFO("Initial pathA ele_D reg0x%x = 0x%lx, OFDM_index=0x%x\n", + rOFDM0_XATxIQImbalance, ele_D, priv->pshare->OFDM_index0[0]); + break; + } + } + + //Query OFDM path B default setting + if(is2T) { + ele_D = PHY_QueryBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord)&bMaskOFDM_D; + for(i=0; ipshare->OFDM_index0[1] = i; + DEBUG_INFO("Initial pathB ele_D reg0x%x = 0x%lx, OFDM_index=0x%x\n", + rOFDM0_XBTxIQImbalance, ele_D, priv->pshare->OFDM_index0[1]); + break; + } + } + } + + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { + priv->pshare->CCK_index0 = get_CCK_swing_index(priv); + } else { + priv->pshare->CCK_index0 = 12; + } + + if(!priv->pshare->ThermalValue) { + priv->pshare->ThermalValue = priv->pmib->dot11RFEntry.ther; + priv->pshare->ThermalValue_LCK = ThermalValue; + priv->pshare->ThermalValue_IQK = ThermalValue; +#ifdef RX_GAIN_TRACK_92D + priv->pshare->ThermalValue_RxGain = priv->pmib->dot11RFEntry.ther; +#endif +#ifdef DPK_92D + priv->pshare->ThermalValue_DPK = ThermalValue; +#endif + for(i = 0; i < rf; i++) + priv->pshare->OFDM_index[i] = priv->pshare->OFDM_index0[i]; + priv->pshare->CCK_index = priv->pshare->CCK_index0; + } + + + //calculate average thermal meter + { + priv->pshare->Thermal_log[priv->pshare->Thermal_idx] = ThermalValue; + priv->pshare->Thermal_idx = (priv->pshare->Thermal_idx+1)%8; + + for(i=0; i<8; i++) { + if(priv->pshare->Thermal_log[i]) { + ThermalValue_AVG += priv->pshare->Thermal_log[i]; + ThermalValue_AVG_count++; + } + } + + if(ThermalValue_AVG_count) + ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count); + } + + + delta = RTL_ABS(ThermalValue, priv->pshare->ThermalValue); + delta_LCK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_LCK); + delta_IQK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_IQK); + +// printk("Readback Thermal Meter = 0x%lx pre thermal meter 0x%lx EEPROMthermalmeter 0x%lx delta 0x%lx delta_LCK 0x%lx delta_IQK 0x%lx\n", +// ThermalValue, priv->pshare->ThermalValue, priv->pmib->dot11RFEntry.ther, delta, delta_LCK, delta_IQK); + + getDeltaValue(priv); + +#ifdef DPK_92D + + if(priv->pshare->bDPKstore) { + + priv->pshare->ThermalValue_DPK = ThermalValue; + delta_DPK = 0; + + for(j = 0; j < rf; j++) { + + if(priv->pshare->ThermalValue_DPKstore > priv->pmib->dot11RFEntry.ther) + value_DPK_shift = index_mapping_DPK[j*2][priv->pshare->ThermalValue_DPKstore- priv->pmib->dot11RFEntry.ther]; + else + value_DPK_shift = index_mapping_DPK[j*2+1][priv->pmib->dot11RFEntry.ther- priv->pshare->ThermalValue_DPKstore]; + + for(i = 0; i < index_mapping_DPK_NUM; i++) { + priv->pshare->index_mapping_DPK_current[j*2][i] = + index_mapping_DPK[j*2][i]-value_DPK_shift; + priv->pshare->index_mapping_DPK_current[j*2+1][i] = + index_mapping_DPK[j*2+1][i]-value_DPK_shift; + } + } + } + else + { + delta_DPK = RTL_ABS(ThermalValue, priv->pshare->ThermalValue_DPK); + } + + for(j = 0; j < rf; j++) { + if(!priv->pshare->bDPKdone[j]) + priv->pshare->OFDM_min_index_internalPA_DPK[j] = 0; + } + +#endif + +#if 1 + if ((delta_LCK > priv->pshare->Delta_LCK) && (priv->pshare->Delta_LCK != 0)) { + priv->pshare->ThermalValue_LCK = ThermalValue; + PHY_LCCalibrate_92D(priv); + } +#endif + if(delta > 0 +#ifdef DPK_92D + ||(priv->pshare->bDPKstore) +#endif + ){ + if(delta == 0 && priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) + goto TxPowerDPK; +#ifdef DPK_92D + if(priv->pshare->bDPKstore) + priv->pshare->bDPKstore = FALSE; +#endif + delta = RTL_ABS(ThermalValue, priv->pmib->dot11RFEntry.ther); + + //calculate new OFDM / CCK offset + { + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G){ + +#ifdef _TRACKING_TABLE_FILE + if (priv->pshare->rf_ft_var.pwr_track_file) { + if(ThermalValue > priv->pmib->dot11RFEntry.ther) + { + for(i = 0; i < rf; i++) + OFDM_index[i] = priv->pshare->OFDM_index[i] - get_tx_tracking_index(priv, channel, i, delta, 0, 0); + + CCK_index = priv->pshare->CCK_index - get_tx_tracking_index(priv, channel, 0, delta, 0, 1); + } + else + { + for(i = 0; i < rf; i++) + OFDM_index[i] = priv->pshare->OFDM_index[i] + get_tx_tracking_index(priv, channel, i, delta, 1, 0); + + CCK_index = priv->pshare->CCK_index + get_tx_tracking_index(priv, channel, i, delta, 1, 1); + } + } + else +#endif + { + offset = 4; + + if(delta > index_mapping_NUM-1) + index[0] = index_mapping[offset][index_mapping_NUM-1]; + else + index[0] = index_mapping[offset][delta]; + + if(ThermalValue > priv->pmib->dot11RFEntry.ther) { + for(i = 0; i < rf; i++) + OFDM_index[i] = priv->pshare->OFDM_index[i] - delta; + CCK_index = priv->pshare->CCK_index - delta; + } + else { + for(i = 0; i < rf; i++) + OFDM_index[i] = priv->pshare->OFDM_index[i] + index[0]; + CCK_index = priv->pshare->CCK_index + index[0]; + } + } + } else if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + for(i = 0; i < rf; i++){ + +#if defined(RTL8192D_INT_PA) + + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx==1) //MAC 1 5G + bInteralPA[i] = priv->pshare->phw->InternalPA5G[1]; + else + bInteralPA[i] = priv->pshare->phw->InternalPA5G[i]; + + if(bInteralPA[i]) { + if(priv->pshare->wlandev_idx == 1 || i == 1/*rf*/) + offset = 4; + else + offset = 0; + if(channel >= 100 && channel <= 165) + offset += 2; + } + else +#endif + { + if(priv->pshare->wlandev_idx == 1 || i == 1) + offset = 2; + else + offset = 0; + } + + +#ifdef HIGH_POWER_EXT_PA //Modify HP tracking table, from Arthur 2012.02.13 + if(i == 0) + { + if(channel <= 99) + offset = 0; + else if(channel <= 140) + offset = 2; + else + offset = 4; + } + else + { + if(channel <= 99) + offset = 6; + else if(channel <= 140) + offset = 8; + else + offset = 10; + } +#endif + + + if(ThermalValue > priv->pmib->dot11RFEntry.ther) //set larger Tx power + offset++; +#if defined(RTL8192D_INT_PA) + if(bInteralPA[i]) { + if(delta > index_mapping_NUM-1) + index[i] = index_mapping_internalPA[offset][index_mapping_NUM-1]; + else + index[i] = index_mapping_internalPA[offset][delta]; + } else +#endif + { + if(delta > index_mapping_NUM-1) + index[i] = index_mapping[offset][index_mapping_NUM-1]; + else + index[i] = index_mapping[offset][delta]; + } + + + +#ifdef _TRACKING_TABLE_FILE + if (priv->pshare->rf_ft_var.pwr_track_file) + { + if(ThermalValue > priv->pmib->dot11RFEntry.ther) + index[i] = get_tx_tracking_index(priv, channel, i, delta, 0, 0); + else + index[i] = get_tx_tracking_index(priv, channel, i, delta, 1, 0); + } + else +#endif + { +#ifdef HIGH_POWER_EXT_PA //Modify HP tracking table, from Arthur 2012.02.13 + { + if(delta > index_mapping_NUM-1) + index[i] = index_mapping_HighPower_PA[offset][index_mapping_NUM-1]; + else + index[i] = index_mapping_HighPower_PA[offset][delta]; + + //printk("\n\n offset = %d delta = %d \n", offset, delta); + //printk("index[%d]= %d\n\n", i, index[i]); + } +#endif + } + + + + if(ThermalValue > priv->pmib->dot11RFEntry.ther) //set larger Tx power + { +#if 0 + if(bInteralPA[i] && ThermalValue > 0x12) + index[i] = ((delta/2)*3+(delta%2)); +#endif + OFDM_index[i] = priv->pshare->OFDM_index[i] -index[i]; + } + else + { + OFDM_index[i] = priv->pshare->OFDM_index[i] + index[i]; + } + } + } + + if(is2T) + { + DEBUG_INFO("temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n", + priv->pshare->OFDM_index[0], priv->pshare->OFDM_index[1], priv->pshare->CCK_index); + } + else + { + DEBUG_INFO("temp OFDM_A_index=0x%x, CCK_index=0x%x\n", + priv->pshare->OFDM_index[0], priv->pshare->CCK_index); + } + + for(i = 0; i < rf; i++) + { + if(OFDM_index[i] > OFDM_TABLE_SIZE_92D-1) { + OFDM_index[i] = OFDM_TABLE_SIZE_92D-1; + } + else if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) { + if (OFDM_index[i] < (OFDM_min_index_internalPA)) + OFDM_index[i] = (OFDM_min_index_internalPA); + } else if(bInteralPA[i]) { +#ifdef DPK_92D + if (OFDM_index[i] < (OFDM_min_index_internalPA+ priv->pshare->OFDM_min_index_internalPA_DPK[i])) + { + priv->pshare->TxPowerLevelDPK[i] = OFDM_min_index_internalPA+ priv->pshare->OFDM_min_index_internalPA_DPK[i]-OFDM_index[i]; + OFDM_index[i] = (OFDM_min_index_internalPA+ priv->pshare->OFDM_min_index_internalPA_DPK[i]); + } + else + { + priv->pshare->TxPowerLevelDPK[i] = 0; + } +#else + if (OFDM_index[i] < (OFDM_min_index_internalPA)) + { + OFDM_index[i] = (OFDM_min_index_internalPA); + } +#endif + } else if(OFDM_index[i] < OFDM_min_index) { +#ifdef HIGH_POWER_EXT_PA //Modify HP tracking table, from Arthur 2012.02.13 +#else + OFDM_index[i] = OFDM_min_index; +#endif + } + } + + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G){ + if(CCK_index > CCK_TABLE_SIZE_92D-1) + CCK_index = CCK_TABLE_SIZE_92D-1; + else if (CCK_index < 0) + CCK_index = 0; + } + + if(is2T) { + DEBUG_INFO("new OFDM_A_index=0x%x, OFDM_B_index=0x%x, CCK_index=0x%x\n", + OFDM_index[0], OFDM_index[1], CCK_index); + } + else + { + DEBUG_INFO("new OFDM_A_index=0x%x, CCK_index=0x%x\n", + OFDM_index[0], CCK_index); + } + } + + //Config by SwingTable + { + //Adujst OFDM Ant_A according to IQK result + ele_D = (OFDMSwingTable_92D[(unsigned int)OFDM_index[0]] & 0xFFC00000)>>22; + X = priv->pshare->RegE94; + Y = priv->pshare->RegE9C; + + if(X != 0 && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G)){ + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + ele_A = ((X * ele_D)>>8)&0x000003FF; + + //new element C = element D x Y + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + ele_C = ((Y * ele_D)>>8)&0x000003FF; + + //wirte new elements A, C, D to regC80 and regC94, element B is always 0 + value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A; + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, value32); + + value32 = (ele_C&0x000003C0)>>6; + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, value32); + + value32 = ((X * ele_D)>>7)&0x01; + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), value32); + + } + else + { + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable_92D[(unsigned int)OFDM_index[0]]); + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(24), 0x00); +#ifdef MP_TEST + if ((priv->pshare->rf_ft_var.mp_specific) && (!is2T)) { + unsigned char str[50]; + sprintf(str, "patha=%d,pathb=%d", priv->pshare->mp_txpwr_patha, priv->pshare->mp_txpwr_pathb); + mp_set_tx_power(priv, str); + } +#endif + } + DEBUG_INFO("TxPwrTracking for interface %d path A: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x\n", + priv->pshare->wlandev_idx, X, Y, ele_A, ele_C, ele_D); + + + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) + { + //Adjust CCK according to IQK result + set_CCK_swing_index(priv, CCK_index); + } + + if(is2T) + { + ele_D = (OFDMSwingTable_92D[(unsigned int)OFDM_index[1]] & 0xFFC00000)>>22; + + //new element A = element D x X + X = priv->pshare->RegEB4; + Y = priv->pshare->RegEBC; + + if(X != 0 && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G)){ + if ((X & 0x00000200) != 0) //consider minus + X = X | 0xFFFFFC00; + ele_A = ((X * ele_D)>>8)&0x000003FF; + + //new element C = element D x Y + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + ele_C = ((Y * ele_D)>>8)&0x00003FF; + + //wirte new elements A, C, D to regC88 and regC9C, element B is always 0 + value32=(ele_D<<22)|((ele_C&0x3F)<<16) |ele_A; + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, value32); + + value32 = (ele_C&0x000003C0)>>6; + PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, value32); + + value32 = ((X * ele_D)>>7)&0x01; + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), value32); + + } + else{ + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable_92D[(unsigned int)OFDM_index[1]]); + PHY_SetBBReg(priv, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(28), 0x00); +#ifdef MP_TEST + if ((priv->pshare->rf_ft_var.mp_specific) ) { + unsigned char str[50]; + sprintf(str, "patha=%d,pathb=%d", priv->pshare->mp_txpwr_patha, priv->pshare->mp_txpwr_pathb); + mp_set_tx_power(priv, str); + + } +#endif + } + + DEBUG_INFO("TxPwrTracking path B: X = 0x%x, Y = 0x%x ele_A = 0x%x ele_C = 0x%x ele_D = 0x%x\n", + X, Y, ele_A, ele_C, ele_D); + } + + DEBUG_INFO("TxPwrTracking 0xc80 = 0x%x, 0xc94 = 0x%x RF 0x24 = 0x%x\n", PHY_QueryBBReg(priv, 0xc80, bMaskDWord), + PHY_QueryBBReg(priv, 0xc94, bMaskDWord), PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x24, bMask20Bits,1)); + } + } + +TxPowerDPK: +#ifdef DPK_92D + { + char bNOPG = FALSE; + unsigned char pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[channel-1]; + if (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_A[channel-1]; +#ifdef CONFIG_RTL_92D_DMDP + if ((priv->pmib->dot11RFEntry.macPhyMode==DUALMAC_DUALPHY) && + (priv->pshare->wlandev_idx == 1) && (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) + pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevel5GHT40_1S_B[channel-1]; + if (pwrlevelHT40_1S_A == 0) + bNOPG = TRUE; +#endif + + //for DPK + if(delta_DPK > 0 && !bNOPG /*&& pHalData->bDPKdone*/) { + for(i = 0; i < rf; i++) { + if(bInteralPA[i] && priv->pshare->bDPKdone[i]) { + if(ThermalValue > priv->pmib->dot11RFEntry.ther) + value_DPK = priv->pshare->index_mapping_DPK_current[i*2][ThermalValue-priv->pmib->dot11RFEntry.ther]; + else + value_DPK = priv->pshare->index_mapping_DPK_current[i*2+1][priv->pmib->dot11RFEntry.ther-ThermalValue]; + + PHY_SetBBReg(priv, index_DPK[i], 0x7c00, value_DPK); + } + } + priv->pshare->ThermalValue_DPK = ThermalValue; + } + } +#endif + priv->pshare->pwr_trk_ongoing = 0; +#if 1 + if ((delta_IQK > priv->pshare->Delta_IQK) && (priv->pshare->Delta_IQK != 0)) { + priv->pshare->ThermalValue_IQK = ThermalValue; + PHY_IQCalibrate(priv); + } +#endif + +#ifdef RX_GAIN_TRACK_92D + if(priv->pmib->dot11RFEntry.ther && (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) && + (ThermalValue < priv->pmib->dot11RFEntry.ther)) { + priv->pshare->ThermalValue_RxGain = ThermalValue; + rx_gain_tracking_92D(priv); + } +#endif + + //update thermal meter value + priv->pshare->ThermalValue = ThermalValue; + } +} + +#endif + +//3 ============================================================ +//3 EDCA Turbo +//3 ============================================================ + +void init_EDCA_para(struct rtl8192cd_priv *priv, int mode) +{ + static unsigned int slot_time, VO_TXOP, VI_TXOP, sifs_time; + + struct ParaRecord EDCA[4]; +#ifdef RTL_MANUAL_EDCA + //unsigned char acm_bitmap; +#endif + + slot_time = 20; + sifs_time = 10; + + if (mode & WIRELESS_11N) + sifs_time = 16; + +#ifdef RTL_MANUAL_EDCA + if( priv->pmib->dot11QosEntry.ManualEDCA ) { + memset(EDCA, 0, 4*sizeof(struct ParaRecord)); + if( OPMODE & WIFI_AP_STATE ) + memcpy(EDCA, priv->pmib->dot11QosEntry.AP_manualEDCA, 4*sizeof(struct ParaRecord)); + else + memcpy(EDCA, priv->pmib->dot11QosEntry.STA_manualEDCA, 4*sizeof(struct ParaRecord)); + + + if ((mode & WIRELESS_11N) || + (mode & WIRELESS_11G)) { + slot_time = 9; + } + + + RTL_W32(EDCA_VO_PARA, (EDCA[VO].TXOPlimit << 16) | (EDCA[VO].ECWmax << 12) | (EDCA[VO].ECWmin << 8) | (sifs_time + EDCA[VO].AIFSN * slot_time)); +#ifdef WIFI_WMM + if (QOS_ENABLE) + RTL_W32(EDCA_VI_PARA, (EDCA[VI].TXOPlimit << 16) | (EDCA[VI].ECWmax << 12) | (EDCA[VI].ECWmin << 8) | (sifs_time + EDCA[VI].AIFSN * slot_time)); + else +#endif + RTL_W32(EDCA_VI_PARA, (EDCA[BE].TXOPlimit << 16) | (EDCA[BE].ECWmax << 12) | (EDCA[BE].ECWmin << 8) | (sifs_time + EDCA[VI].AIFSN * slot_time)); + + RTL_W32(EDCA_BE_PARA, (EDCA[BE].TXOPlimit << 16) | (EDCA[BE].ECWmax << 12) | (EDCA[BE].ECWmin << 8) | (sifs_time + EDCA[BE].AIFSN * slot_time)); + + RTL_W32(EDCA_BK_PARA, (EDCA[BK].TXOPlimit << 16) | (EDCA[BK].ECWmax << 12) | (EDCA[BK].ECWmin << 8) | (sifs_time + EDCA[BK].AIFSN * slot_time)); + }else +#endif //RTL_MANUAL_EDCA + { + memset(EDCA, 0, 4*sizeof(struct ParaRecord)); + /* copy BE, BK from static data */ + if( OPMODE & WIFI_AP_STATE ) + memcpy(EDCA, rtl_ap_EDCA, 2*sizeof(struct ParaRecord)); + else + memcpy(EDCA, rtl_sta_EDCA, 2*sizeof(struct ParaRecord)); + + /* VI, VO apply settings in AG by default */ + if( OPMODE & WIFI_AP_STATE ) + memcpy(&EDCA[2], &rtl_ap_EDCA[VI_AG], 2*sizeof(struct ParaRecord)); + else + memcpy(&EDCA[2], &rtl_sta_EDCA[VI_AG], 2*sizeof(struct ParaRecord)); + + if ((mode & WIRELESS_11N) || + (mode & WIRELESS_11G)) { + slot_time = 9; + } else { + /* replace with settings in B */ + if( OPMODE & WIFI_AP_STATE ) + memcpy(&EDCA[2], &rtl_ap_EDCA[VI], 2*sizeof(struct ParaRecord)); + else + memcpy(&EDCA[2], &rtl_sta_EDCA[VI], 2*sizeof(struct ParaRecord)); + } + VO_TXOP = EDCA[VO].TXOPlimit; + VI_TXOP = EDCA[VI].TXOPlimit; + + RTL_W32(EDCA_VO_PARA, (VO_TXOP << 16) | (EDCA[VO].ECWmax << 12) | (EDCA[VO].ECWmin << 8) | (sifs_time + EDCA[VO].AIFSN * slot_time)); +#ifdef WIFI_WMM + if (QOS_ENABLE) + RTL_W32(EDCA_VI_PARA, (VI_TXOP << 16) | (EDCA[VI].ECWmax << 12) | (EDCA[VI].ECWmin << 8) | (sifs_time + EDCA[VI].AIFSN * slot_time)); + else +#endif + RTL_W32(EDCA_VI_PARA, (EDCA[BK].ECWmax << 12) | (EDCA[BK].ECWmin << 8) | (sifs_time + EDCA[VI].AIFSN * slot_time)); + + RTL_W32(EDCA_BE_PARA, ((EDCA[BE].ECWmax) << 12) | (EDCA[BE].ECWmin << 8) | (sifs_time + EDCA[BE].AIFSN * slot_time)); + RTL_W32(EDCA_BK_PARA, (EDCA[BK].ECWmax << 12) | (EDCA[BK].ECWmin << 8) | (sifs_time + EDCA[BK].AIFSN * slot_time)); + + + RTL_W8(ACMHWCTRL, 0x00); + } + + priv->pshare->iot_mode_enable = 0; + if (priv->pshare->rf_ft_var.wifi_beq_iot) + priv->pshare->iot_mode_VI_exist = 0; + priv->pshare->iot_mode_VO_exist = 0; + +#ifdef WMM_VIBE_PRI + priv->pshare->iot_mode_BE_exist = 0; +#endif +#ifdef WMM_BEBK_PRI + priv->pshare->iot_mode_BK_exist = 0; +#endif +#ifdef LOW_TP_TXOP + priv->pshare->BE_cwmax_enhance = 0; +#endif +} + +void choose_IOT_main_sta(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int i, assoc_num = GET_ROOT(priv)->assoc_num; +#ifdef MBSSID + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable){ + for (i=0; ipvap_priv[i]-> assoc_num; + } +#endif +#ifdef UNIVERSAL_REPEATER + if (IS_DRV_OPEN(GET_VXD_PRIV(GET_ROOT(priv)))) + assoc_num += GET_VXD_PRIV(GET_ROOT(priv))-> assoc_num; +#endif +#ifdef WDS + if(GET_ROOT(priv)->pmib->dot11WdsInfo.wdsEnabled) + assoc_num ++; +#endif + + if (priv->pshare->rf_ft_var.low_tp_no_aggr) { + unsigned long sta_tp = (pstat->current_tx_bytes + pstat->current_rx_bytes) >> 17; + if (!pstat->low_tp_disable_ampdu && sta_tp <= 2) + pstat->low_tp_disable_ampdu = 1; + else if (pstat->low_tp_disable_ampdu && sta_tp >= 5) + pstat->low_tp_disable_ampdu = 0; + } + + if ((GET_ROOT(priv)->up_time % 2) == 0) { + unsigned int tx_2s_avg = 0; + unsigned int rx_2s_avg = 0; + int i=0, aggReady=0; + unsigned long total_sum = (priv->pshare->current_tx_bytes+priv->pshare->current_rx_bytes); + + pstat->current_tx_bytes += pstat->tx_byte_cnt; + pstat->current_rx_bytes += pstat->rx_byte_cnt; + + if (total_sum != 0) { + if (total_sum <= 1000000) { + tx_2s_avg = (unsigned int)((pstat->current_tx_bytes*100) / total_sum); + rx_2s_avg = (unsigned int)((pstat->current_rx_bytes*100) / total_sum); + } else { + tx_2s_avg = (unsigned int)(pstat->current_tx_bytes / (total_sum / 100)); + rx_2s_avg = (unsigned int)(pstat->current_rx_bytes / (total_sum / 100)); + } + } + + for(i=0; i<8; i++) + aggReady += (pstat->ADDBA_ready[i]); + + if( (pstat->IOTPeer==HT_IOT_PEER_INTEL) + || (pstat->ht_cap_len && aggReady)) { + + if ((assoc_num==1) || (tx_2s_avg + rx_2s_avg >= 25)) { + priv->pshare->highTP_found_pstat = pstat; + } /*this STA's TXRX packet very close AP's total TXRX packet then let it as highTP_found_pstat*/ + else if(RTL_ABS((pstat->current_tx_bytes + pstat->current_rx_bytes) , total_sum)<50){ + priv->pshare->highTP_found_pstat = pstat; + } +#ifdef CLIENT_MODE + if (OPMODE & WIFI_STATION_STATE) { +// if(pstat->is_ralink_sta && ((tx_2s_avg + rx_2s_avg) >= 45)) + if(pstat->IOTPeer == HT_IOT_PEER_RALINK && ((tx_2s_avg + rx_2s_avg) >= 45)) + priv->pshare->highTP_found_pstat = pstat; + } +#endif + } + } + else { + pstat->current_tx_bytes = pstat->tx_byte_cnt; + pstat->current_rx_bytes = pstat->rx_byte_cnt; + } +} + + +void rxBB_dm(struct rtl8192cd_priv *priv) +{ + if ((priv->up_time % 3) == 1) { + if (priv->pshare->rssi_min != 0xff) { + if (priv->pshare->rf_ft_var.dig_enable) { + // for DIG checking + check_DIG_by_rssi(priv, priv->pshare->rssi_min); + } +//#ifdef INTERFERENCE_CONTROL + if (priv->pshare->rf_ft_var.nbi_filter_enable) { + check_NBI_by_rssi(priv, priv->pshare->rssi_min); + } +//#endif + } + +#ifdef MP_TEST + if (!((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific)) +#endif + { +#ifdef HIGH_POWER_EXT_LNA + if (!priv->pshare->rf_ft_var.use_ext_lna) +#endif + CCK_CCA_dynamic_enhance(priv, priv->pshare->rssi_min); + } + } + if (priv->pshare->rf_ft_var.adaptivity_enable){ + unsigned char IGI; + IGI = RTL_R8(0xc50); + rtl8192cd_Adaptivity(priv,IGI); + } +} + +/* + * IOT related functions + */ +void IOT_engine(struct rtl8192cd_priv *priv) +{ +#ifdef WIFI_WMM + unsigned int switch_turbo = 0; +#endif + struct stat_info *pstat = priv->pshare->highTP_found_pstat; + + if(pstat) { + if((pstat->tx_avarage + pstat->rx_avarage) < (1<<17)) // 1M bps + pstat = NULL; + } +#if defined(RTL_MANUAL_EDCA) && defined(WIFI_WMM) + if(priv->pmib->dot11QosEntry.ManualEDCA) + return ; +#endif + +#ifdef WIFI_WMM + if (QOS_ENABLE) { + if (!priv->pmib->dot11OperationEntry.wifi_specific || + ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific))) { + if (priv->pshare->iot_mode_enable && + ((priv->pshare->phw->VO_pkt_count > 50) || + (priv->pshare->phw->VI_pkt_count > 50) || + (priv->pshare->phw->BK_pkt_count > 50))) { + priv->pshare->iot_mode_enable = 0; + switch_turbo++; + } else if ((!priv->pshare->iot_mode_enable) && + ((priv->pshare->phw->VO_pkt_count < 50) && + (priv->pshare->phw->VI_pkt_count < 50) && + (priv->pshare->phw->BK_pkt_count < 50))) { + priv->pshare->iot_mode_enable++; + switch_turbo++; + } + } + + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11OperationEntry.wifi_specific) { + if (!priv->pshare->iot_mode_VO_exist && (priv->pshare->phw->VO_pkt_count > 50)) { + priv->pshare->iot_mode_VO_exist++; + switch_turbo++; + } else if (priv->pshare->iot_mode_VO_exist && (priv->pshare->phw->VO_pkt_count < 50)) { + priv->pshare->iot_mode_VO_exist = 0; + switch_turbo++; + } + +#ifdef WMM_VIBE_PRI + if (priv->pshare->iot_mode_VO_exist) { + //printk("[%s %d] BE_pkt_count=%d\n", __FUNCTION__, __LINE__, priv->pshare->phw->BE_pkt_count); + if (!priv->pshare->iot_mode_BE_exist && (priv->pshare->phw->BE_pkt_count > 250)) { + priv->pshare->iot_mode_BE_exist++; + switch_turbo++; + } else if (priv->pshare->iot_mode_BE_exist && (priv->pshare->phw->BE_pkt_count < 250)) { + priv->pshare->iot_mode_BE_exist = 0; + switch_turbo++; + } + } +#endif + +#ifdef WMM_BEBK_PRI + if (priv->pshare->phw->BE_pkt_count) { + //printk("[%s %d] BK_pkt_count=%d\n", __FUNCTION__, __LINE__, priv->pshare->phw->BK_pkt_count); + if (!priv->pshare->iot_mode_BK_exist && (priv->pshare->phw->BK_pkt_count > 250)) { + priv->pshare->iot_mode_BK_exist++; + switch_turbo++; + EDEBUG("switch_turbo++\n"); + } else if (priv->pshare->iot_mode_BE_exist && (priv->pshare->phw->BK_pkt_count < 250)) { + priv->pshare->iot_mode_BK_exist = 0; + switch_turbo++; + EDEBUG("switch_turbo++\n"); + } + } +#endif + + if (priv->pshare->rf_ft_var.wifi_beq_iot) { + if (!priv->pshare->iot_mode_VI_exist && (priv->pshare->phw->VI_rx_pkt_count > 50)) { + priv->pshare->iot_mode_VI_exist++; + switch_turbo++; + } else if (priv->pshare->iot_mode_VI_exist && (priv->pshare->phw->VI_rx_pkt_count < 50)) { + priv->pshare->iot_mode_VI_exist = 0; + switch_turbo++; + } + } + +#ifdef CONFIG_RTL_92D_DMDP + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY)) { + unsigned int tp = (unsigned int)(priv->ext_stats.tx_avarage>>17) + (unsigned int)(priv->ext_stats.rx_avarage>>17); + if (priv->pshare->rf_ft_var.wifi_beq_iot) { + if (priv->pshare->wifi_beq_lower && priv->pshare->iot_mode_VI_exist && tp <= 20) { + priv->pshare->wifi_beq_lower= 0; + switch_turbo++; + } else if (!priv->pshare->wifi_beq_lower&& (!priv->pshare->iot_mode_VI_exist || tp > 20)) { + priv->pshare->wifi_beq_lower= 1; + switch_turbo++; + } + } + } +#endif + } + +#ifdef CLIENT_MODE + if ((OPMODE & WIFI_STATION_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific)) + { + if (priv->pshare->iot_mode_enable && + (((priv->pshare->phw->VO_pkt_count > 50) || + (priv->pshare->phw->VI_pkt_count > 50) || + (priv->pshare->phw->BK_pkt_count > 50)) || + (pstat && (!pstat->ADDBA_ready[0]) & (!pstat->ADDBA_ready[3])))) + { + priv->pshare->iot_mode_enable = 0; + switch_turbo++; + } + else if ((!priv->pshare->iot_mode_enable) && + (((priv->pshare->phw->VO_pkt_count < 50) && + (priv->pshare->phw->VI_pkt_count < 50) && + (priv->pshare->phw->BK_pkt_count < 50)) && + (pstat && (pstat->ADDBA_ready[0] | pstat->ADDBA_ready[3])))) + { + priv->pshare->iot_mode_enable++; + switch_turbo++; + } + } +#endif + + priv->pshare->phw->VO_pkt_count = 0; + priv->pshare->phw->VI_pkt_count = 0; + if (priv->pshare->rf_ft_var.wifi_beq_iot) + priv->pshare->phw->VI_rx_pkt_count = 0; + priv->pshare->phw->BK_pkt_count = 0; +#ifdef WMM_VIBE_PRI + priv->pshare->phw->BE_pkt_count = 0; +#endif + } +#endif + + if ((priv->up_time % 2) == 0) { + /* + * decide EDCA content for different chip vendor + */ +#ifdef WIFI_WMM + if (QOS_ENABLE && (!priv->pmib->dot11OperationEntry.wifi_specific || + ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2)) +#ifdef CLIENT_MODE + || ((OPMODE & WIFI_STATION_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific == 2)) +#endif + )) { + if (pstat && pstat->rssi >= priv->pshare->rf_ft_var.txop_enlarge_upper) { +#ifdef LOW_TP_TXOP + + + if (pstat->IOTPeer==HT_IOT_PEER_INTEL) + + { + + if (priv->pshare->txop_enlarge != 0xe) { + priv->pshare->txop_enlarge = 0xe; + if (priv->pshare->iot_mode_enable) + switch_turbo++; + } + } else if (priv->pshare->txop_enlarge != 2) { + priv->pshare->txop_enlarge = 2; + if (priv->pshare->iot_mode_enable) + switch_turbo++; + } +#else //LOW_TP_TXOP + + if (priv->pshare->txop_enlarge != 2) { + + + { + if (pstat->IOTPeer==HT_IOT_PEER_INTEL) + priv->pshare->txop_enlarge = 0xe; + else if (pstat->IOTPeer==HT_IOT_PEER_RALINK) + priv->pshare->txop_enlarge = 0xd; + else + priv->pshare->txop_enlarge = 2; + + } + + if (priv->pshare->iot_mode_enable) + switch_turbo++; + } +#endif //LOW_TP_TXOP + } else if (!pstat || pstat->rssi < priv->pshare->rf_ft_var.txop_enlarge_lower) { + if (priv->pshare->txop_enlarge) { + priv->pshare->txop_enlarge = 0; + if (priv->pshare->iot_mode_enable) + switch_turbo++; + } + } +#ifdef LOW_TP_TXOP + // for Intel IOT, need to enlarge CW MAX from 6 to 10 + + + if (pstat && pstat->IOTPeer==HT_IOT_PEER_INTEL && (((pstat->tx_avarage+pstat->rx_avarage)>>10) < + priv->pshare->rf_ft_var.cwmax_enhance_thd)) + + { + if (!priv->pshare->BE_cwmax_enhance && priv->pshare->iot_mode_enable) { + priv->pshare->BE_cwmax_enhance = 1; + switch_turbo++; + } + } else { + if (priv->pshare->BE_cwmax_enhance) { + priv->pshare->BE_cwmax_enhance = 0; + switch_turbo++; + } + } +#endif + } +#endif + + priv->pshare->current_tx_bytes = 0; + priv->pshare->current_rx_bytes = 0; + } + +#ifdef SW_TX_QUEUE + if ((priv->assoc_num > 1) && (AMPDU_ENABLE)) + { + unsigned int total_tp = (unsigned int)(priv->ext_stats.tx_avarage>>17)+(unsigned int)(priv->ext_stats.rx_avarage>>17); + if(total_tp > 0) { + if (((unsigned int)(priv->ext_stats.tx_avarage>>17) * 100/total_tp) > 30) + { + if (priv->swq_txmac_chg >= priv->pshare->rf_ft_var.swq_en_highthd) + { + if ((priv->swq_en == 0)) + { + switch_turbo++; + if (priv->pshare->txop_enlarge == 0) + priv->pshare->txop_enlarge = 2; + priv->swq_en = 1; + priv->swqen_keeptime = priv->up_time; + } + else + { + if ((switch_turbo > 0) && (priv->pshare->txop_enlarge == 0) && (priv->pshare->iot_mode_enable != 0)) + { + priv->pshare->txop_enlarge = 2; + switch_turbo--; + } + } + } + else if(priv->swq_txmac_chg <= priv->pshare->rf_ft_var.swq_dis_lowthd) + { + priv->swq_en = 0; + priv->swqen_keeptime = 0; + } + else if ((priv->swq_en == 1) && (switch_turbo > 0) && (priv->pshare->txop_enlarge == 0) && (priv->pshare->iot_mode_enable != 0)) + { + priv->pshare->txop_enlarge = 2; + switch_turbo--; + } + } + else if (((unsigned int)(priv->ext_stats.tx_avarage>>17) * 100/total_tp) < 20) + { + priv->swq_en = 0; + priv->swqen_keeptime = 0; + } + } + //debug msg + //printk("swq=%d,sw=%d,en=%d,mode=%d\n", priv->swq_en, switch_turbo, priv->pshare->txop_enlarge, priv->pshare->iot_mode_enable); + } +#if 1//defined(CONFIG_RTL_819XD) + else if( (priv->assoc_num == 1) && (priv->up_time % 2)== 0 && (AMPDU_ENABLE) ) { + //if (pstat) { +// if ((pstat) && pstat->is_intel_sta) { + if ((pstat) && pstat->IOTPeer == HT_IOT_PEER_INTEL) { +// int en_thd = 14417920; + //if ((priv->swq_en == 0) && (pstat->current_tx_bytes > en_thd) && (pstat->current_rx_bytes > en_thd) ) { //50Mbps + if ((pstat->current_tx_bytes > 14417920) && (priv->swq_en == 0)) { // && (pstat->current_rx_bytes > 14417920) && (priv->swq_en == 0)) { //55Mbps + priv->swq_en = 1; + priv->swqen_keeptime = priv->up_time; + } + //else if ((priv->swq_en == 1) && ((pstat->tx_avarage < 4587520) || (pstat->rx_avarage < 4587520))) { //35Mbps + else if ((pstat->tx_avarage < 9175040) && (priv->swq_en == 1)) { //35Mbps + priv->swq_en = 0; + priv->swqen_keeptime = 0; + } + } + else { + priv->swq_en = 0; + priv->swqen_keeptime = 0; + } + } +#endif +#endif + +#ifdef WIFI_WMM +#ifdef LOW_TP_TXOP + if ((!priv->pmib->dot11OperationEntry.wifi_specific || (priv->pmib->dot11OperationEntry.wifi_specific == 2)) + && QOS_ENABLE) { + + if (switch_turbo || priv->pshare->rf_ft_var.low_tp_txop) { + unsigned int thd_tp; + unsigned char under_thd; + unsigned int curr_tp; + + if (priv->pmib->dot11BssType.net_work_type & (WIRELESS_11N | WIRELESS_11G)) + { + // Determine the upper bound throughput threshold. + if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) { + if (priv->assoc_num && priv->assoc_num != priv->pshare->ht_sta_num) + thd_tp = priv->pshare->rf_ft_var.low_tp_txop_thd_g; + else + thd_tp = priv->pshare->rf_ft_var.low_tp_txop_thd_n; + } + else + thd_tp = priv->pshare->rf_ft_var.low_tp_txop_thd_g; + + // Determine to close txop. +#if defined(UNIVERSAL_REPEATER) || defined(MBSSID) + if(pstat && pstat->expire_to) + { + struct rtl8192cd_priv *tmppriv; + struct aid_obj *aidarray; + aidarray = container_of(pstat, struct aid_obj, station); + tmppriv = aidarray->priv; + + curr_tp = (unsigned int)(tmppriv->ext_stats.tx_avarage>>17) + (unsigned int)(tmppriv->ext_stats.rx_avarage>>17); + } + else +#endif + curr_tp = (unsigned int)(priv->ext_stats.tx_avarage>>17) + (unsigned int)(priv->ext_stats.rx_avarage>>17); + if (curr_tp <= thd_tp && curr_tp >= priv->pshare->rf_ft_var.low_tp_txop_thd_low) + under_thd = 1; + else + under_thd = 0; + } + else + { + under_thd = 0; + } + + if (switch_turbo) { + priv->pshare->rf_ft_var.low_tp_txop_close = under_thd; + priv->pshare->rf_ft_var.low_tp_txop_count = 0; + } else if (priv->pshare->iot_mode_enable && (priv->pshare->rf_ft_var.low_tp_txop_close != under_thd)) { + priv->pshare->rf_ft_var.low_tp_txop_count++; + if (priv->pshare->rf_ft_var.low_tp_txop_close) { + priv->pshare->rf_ft_var.low_tp_txop_count = priv->pshare->rf_ft_var.low_tp_txop_delay; + } + if (priv->pshare->rf_ft_var.low_tp_txop_count == priv->pshare->rf_ft_var.low_tp_txop_delay) { + priv->pshare->rf_ft_var.low_tp_txop_count = 0; + priv->pshare->rf_ft_var.low_tp_txop_close = under_thd; + switch_turbo++; + } + } else { + priv->pshare->rf_ft_var.low_tp_txop_count = 0; + } + } + } +#endif + + if (switch_turbo) + IOT_EDCA_switch(priv, priv->pmib->dot11BssType.net_work_type, priv->pshare->iot_mode_enable); +#endif +} + + +#ifdef WIFI_WMM +void IOT_EDCA_switch(struct rtl8192cd_priv *priv, int mode, char enable) +{ + unsigned int slot_time = 20, sifs_time = 10, BE_TXOP = 47, VI_TXOP = 94; + unsigned int vi_cw_max = 4, vi_cw_min = 3, vi_aifs; + + if (!(!priv->pmib->dot11OperationEntry.wifi_specific || + ((OPMODE & WIFI_AP_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific)) +#ifdef CLIENT_MODE + || ((OPMODE & WIFI_STATION_STATE) && (priv->pmib->dot11OperationEntry.wifi_specific)) +#endif + )) + return; + + if ((mode & WIRELESS_11N) && (priv->pshare->ht_sta_num +#ifdef WDS + || ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum) +#endif + )) + sifs_time = 16; + + if (mode & (WIRELESS_11G | WIRELESS_11N)) { + slot_time = 9; + } else { + BE_TXOP = 94; + VI_TXOP = 188; + } + +#if 0 //defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) + if (priv->pshare->is_40m_bw) + { + BE_TXOP = 23; + } +#endif + + if ((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11OperationEntry.wifi_specific) { + if (priv->pshare->iot_mode_VO_exist) { +#ifdef WMM_VIBE_PRI + if (priv->pshare->iot_mode_BE_exist) { + vi_cw_max = 5; + vi_cw_min = 3; + vi_aifs = (sifs_time + ((OPMODE & WIFI_AP_STATE)?1:2) * slot_time); + } else +#endif + { + vi_cw_max = 6; + vi_cw_min = 4; + vi_aifs = 0x2b; + } + } else { + vi_aifs = (sifs_time + ((OPMODE & WIFI_AP_STATE)?1:2) * slot_time); + } + + RTL_W32(EDCA_VI_PARA, ((VI_TXOP*(1-priv->pshare->iot_mode_VO_exist)) << 16) + | (vi_cw_max << 12) | (vi_cw_min << 8) | vi_aifs); + +#ifdef WMM_BEBK_PRI +#ifdef CONFIG_RTL_88E_SUPPORT + if ((GET_CHIP_VER(priv) == VERSION_8188E ) && priv->pshare->iot_mode_BK_exist) { + RTL_W32(EDCA_BK_PARA, (10 << 12) | (6 << 8) | 0x4f); + } +#endif +#endif + } + + if (!enable || (priv->pshare->rf_ft_var.wifi_beq_iot && priv->pshare->iot_mode_VI_exist)) { + if (priv->pshare->rf_ft_var.wifi_beq_iot && priv->pshare->iot_mode_VI_exist) { +#ifdef CONFIG_RTL_92D_DMDP + if ((GET_CHIP_VER(priv) == VERSION_8192D) && (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY)) { + if (priv->pshare->wifi_beq_lower) + RTL_W32(EDCA_BE_PARA, (10 << 12) | (4 << 8) | (sifs_time + 10 * slot_time)); + else + RTL_W32(EDCA_BE_PARA, (6 << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); + } else +#endif + RTL_W32(EDCA_BE_PARA, (10 << 12) | (4 << 8) | 0x4f); + } else { + RTL_W32(EDCA_BE_PARA, (((OPMODE & WIFI_AP_STATE)?6:10) << 12) | (4 << 8) + | (sifs_time + 3 * slot_time)); + } + RTL_W16(RD_CTRL, RTL_R16(RD_CTRL) | DIS_TXOP_CFE); + } else { +#ifdef LOW_TP_TXOP + int txop; + unsigned int cw_max; + unsigned int txop_close; + + cw_max = ((priv->pshare->BE_cwmax_enhance) ? 10 : 6); + txop_close = ((priv->pshare->rf_ft_var.low_tp_txop && priv->pshare->rf_ft_var.low_tp_txop_close) ? 1 : 0); + txop = (txop_close ? 0 : (BE_TXOP*2)); +#endif + if (priv->pshare->ht_sta_num +#ifdef WDS + || ((OPMODE & WIFI_AP_STATE) && (mode & WIRELESS_11N) && + priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum) +#endif + ) { +/* + if (priv->pshare->txop_enlarge == 0xf) { + // is 8192S client + RTL_W32(EDCA_BE_PARA, ((BE_TXOP*2) << 16) | + (6 << 12) | (4 << 8) | (sifs_time + slot_time+ 0xf)); // 0xf is 92s circuit delay + priv->pshare->txop_enlarge = 2; + } + else +*/ + if (priv->pshare->txop_enlarge == 0xe) { +#ifndef LOW_TP_TXOP + // is intel client, use a different edca value +#if 0 //defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) + RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (5 << 8) | 0x1f); +#else + //RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (4 << 8) | 0x1f); + if (get_rf_mimo_mode(priv) == MIMO_1T1R) + RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (5 << 8) | 0x1f); + else + RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (8 << 12) | (5 << 8) | 0x1f); + + RTL_W16(RD_CTRL, RTL_R16(RD_CTRL) & ~(DIS_TXOP_CFE)); +#endif + priv->pshare->txop_enlarge = 2; + } else if (priv->pshare->txop_enlarge == 0xd) { + // is intel ralink, use a different edca value + RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (4 << 12) | (3 << 8) | 0x19); + priv->pshare->txop_enlarge = 2; + } else { + if (priv->pshare->txop_enlarge == 0) + RTL_W16(RD_CTRL, RTL_R16(RD_CTRL) | DIS_TXOP_CFE); + + if (get_rf_mimo_mode(priv) == MIMO_2T2R) +#if 0 //defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) + RTL_W32(EDCA_BE_PARA, ((BE_TXOP*priv->pshare->txop_enlarge) << 16) | + (6 << 12) | (5 << 8) | (sifs_time + 3 * slot_time)); +#else + RTL_W32(EDCA_BE_PARA, ((BE_TXOP*priv->pshare->txop_enlarge) << 16) | + (6 << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); +#endif + else +#if 0 //defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) + RTL_W32(EDCA_BE_PARA, ((BE_TXOP*priv->pshare->txop_enlarge) << 16) | + (5 << 12) | (4 << 8) | (sifs_time + 2 * slot_time)); +#else + RTL_W32(EDCA_BE_PARA, ((BE_TXOP*priv->pshare->txop_enlarge) << 16) | + (5 << 12) | (3 << 8) | (sifs_time + 2 * slot_time)); +#endif + +#else + // is intel client, use a different edca value + if (get_rf_mimo_mode(priv) == MIMO_1T1R) + RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (5 << 8) | 0x1f); + else + RTL_W32(EDCA_BE_PARA, (txop << 16) | (cw_max << 12) | (4 << 8) | 0x1f); + } else { + txop = (txop_close ? 0: (BE_TXOP*priv->pshare->txop_enlarge)); + + if (get_rf_mimo_mode(priv) == MIMO_2T2R) + RTL_W32(EDCA_BE_PARA, (txop << 16) | (cw_max << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); + else + RTL_W32(EDCA_BE_PARA, (txop << 16) | (((priv->pshare->BE_cwmax_enhance) ? 10 : 5) << 12) | + (3 << 8) | (sifs_time + 2 * slot_time)); +#endif + } + } else { +#ifdef LOW_TP_TXOP + RTL_W32(EDCA_BE_PARA, (txop << 16) | (cw_max << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); +#else +#if defined(CONFIG_RTL_8196D) || defined(CONFIG_RTL_8197DL) || defined(CONFIG_RTL_8196E) || (defined(CONFIG_RTL_8197D) && !defined(CONFIG_PORT0_EXT_GIGA)) + RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (5 << 8) | (sifs_time + 3 * slot_time)); +#else + RTL_W32(EDCA_BE_PARA, (BE_TXOP*2 << 16) | (6 << 12) | (4 << 8) | (sifs_time + 3 * slot_time)); +#endif + if (priv->pshare->txop_enlarge == 0xe) + RTL_W16(RD_CTRL, RTL_R16(RD_CTRL) & ~(DIS_TXOP_CFE)); + else + RTL_W16(RD_CTRL, RTL_R16(RD_CTRL) | DIS_TXOP_CFE); +#endif + } +/* + if (priv->pmib->dot11OperationEntry.wifi_specific == 2) { + RTL_W16(NAV_PROT_LEN, 0x01C0); + RTL_W8(CFEND_TH, 0xFF); + set_fw_reg(priv, 0xfd000ab0, 0, 0); + } +*/ + } +} + +//end of IOT_EDCA_switch +//======================================================================================================== + +#if 0 +void check_NAV_prot_len(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned int disassoc) +{ + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat + && pstat->ht_cap_len && pstat->is_intel_sta) { + if (!disassoc && (pstat->MIMO_ps & _HT_MIMO_PS_DYNAMIC_)) { + setSTABitMap(&priv->pshare->mimo_ps_dynamic_sta, pstat->aid); + } else { + clearSTABitMap(&priv->pshare->mimo_ps_dynamic_sta, pstat->aid); + } + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) != VERSION_8188E) +#endif + { + if (orSTABitMap(&priv->pshare->mimo_ps_dynamic_sta) { + RTL_W8(NAV_PROT_LEN, 0x40); + } else { + RTL_W8(NAV_PROT_LEN, 0x20); + } + } + } +} +#endif +#endif + + +//3 ============================================================ +//3 FA statistic functions +//3 ============================================================ +#if 0 + +#if !defined(CONFIG_RTL_NEW_AUTOCH) +static +#endif +void reset_FA_reg(struct rtl8192cd_priv *priv) +{ +#if !defined(CONFIG_RTL_NEW_AUTOCH) + unsigned char value8; + + value8 = RTL_R8(0xd03); + RTL_W8(0xd03, value8 | 0x08); // regD00[27]=1 to reset these OFDM FA counters + value8 = RTL_R8(0xd03); + RTL_W8(0xd03, value8 & 0xF7); // regD00[27]=0 to start counting + value8 = RTL_R8(0xa2d); + RTL_W8(0xa2d, value8 & 0x3F); // regA2D[7:6]=00 to disable counting + value8 = RTL_R8(0xa2d); + RTL_W8(0xa2d, value8 | 0x80); // regA2D[7:6]=10 to enable counting +#else + /* cck CCA */ + PHY_SetBBReg(priv, 0xa2c, BIT(13) | BIT(12), 0); + PHY_SetBBReg(priv, 0xa2c, BIT(13) | BIT(12), 2); + /* cck FA*/ + PHY_SetBBReg(priv, 0xa2c, BIT(15) | BIT(14), 0); + PHY_SetBBReg(priv, 0xa2c, BIT(15) | BIT(14), 2); + /* ofdm */ + PHY_SetBBReg(priv, 0xd00, BIT(27), 1); + PHY_SetBBReg(priv, 0xd00, BIT(27), 0); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + PHY_SetBBReg(priv, 0xf14, BIT(16),1); + PHY_SetBBReg(priv, 0xf14, BIT(16),0); + RTL_W32(RXERR_RPT, RTL_R32(RXERR_RPT)|BIT(27)); + RTL_W32(RXERR_RPT, RTL_R32(RXERR_RPT)&(~BIT(27))); + } +#endif + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + PHY_SetBBReg(priv, 0xc0c, BIT(31), 1); + PHY_SetBBReg(priv, 0xc0c, BIT(31), 0); + } +#endif +} + +#if defined(CONFIG_RTL_NEW_AUTOCH) +void hold_CCA_FA_counter(struct rtl8192cd_priv *priv) +{ + /* hold cck CCA & FA counter */ + PHY_SetBBReg(priv, 0xa2c, BIT(12), 1); + PHY_SetBBReg(priv, 0xa2c, BIT(14), 1); + + /* hold ofdm CCA & FA counter */ + PHY_SetBBReg(priv, 0xc00, BIT(31), 1); + PHY_SetBBReg(priv, 0xd00, BIT(31), 1); +} + +void release_CCA_FA_counter(struct rtl8192cd_priv *priv) +{ + /* release cck CCA & FA counter */ + PHY_SetBBReg(priv, 0xa2c, BIT(12), 0); + PHY_SetBBReg(priv, 0xa2c, BIT(14), 0); + + /* release ofdm CCA & FA counter */ + PHY_SetBBReg(priv, 0xc00, BIT(31), 0); + PHY_SetBBReg(priv, 0xd00, BIT(31), 0); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + PHY_SetBBReg(priv, 0xc0c, BIT(31), 1); + PHY_SetBBReg(priv, 0xc0c, BIT(31), 0); + } +#endif +} + + +void _FA_statistic(struct rtl8192cd_priv *priv) +{ + // read OFDM FA counters + priv->pshare->ofdm_FA_cnt1 = RTL_R16(0xda2); + priv->pshare->ofdm_FA_cnt2 = RTL_R16(0xda4); + priv->pshare->ofdm_FA_cnt3 = RTL_R16(0xda6); + priv->pshare->ofdm_FA_cnt4 = RTL_R16(0xda8); + + priv->pshare->cck_FA_cnt = (RTL_R8(0xa5b) << 8) + RTL_R8(0xa5c); + +#ifdef INTERFERENCE_CONTROL + priv->pshare->ofdm_FA_total_cnt = (unsigned int) priv->pshare->ofdm_FA_cnt1 + + priv->pshare->ofdm_FA_cnt2 + priv->pshare->ofdm_FA_cnt3 + + priv->pshare->ofdm_FA_cnt4 + RTL_R16(0xcf0) + RTL_R16(0xcf2); + + priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_total_cnt + priv->pshare->cck_FA_cnt; +#else + priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_cnt1 + priv->pshare->ofdm_FA_cnt2 + + priv->pshare->ofdm_FA_cnt3 + priv->pshare->ofdm_FA_cnt4 + + priv->pshare->cck_FA_cnt + RTL_R16(0xcf0) + RTL_R16(0xcf2); +#endif +} +#endif + +void FA_statistic(struct rtl8192cd_priv *priv) +{ + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ +// priv->pshare->F90_cnt = PHY_QueryBBReg(priv, 0xf90, bMaskHWord); + priv->pshare->F94_cnt = PHY_QueryBBReg(priv, 0xf94, bMaskHWord); + priv->pshare->F94_cntOK = PHY_QueryBBReg(priv, 0xf94, bMaskLWord); + RTL_W32(RXERR_RPT,(RTL_R32(RXERR_RPT)&0x0fffffff)|0x70000000); + priv->pshare->Reg664_cnt = RTL_R32(RXERR_RPT) & 0xfffff; + RTL_W32(RXERR_RPT,(RTL_R32(RXERR_RPT)&0x0fffffff)|0x60000000); + priv->pshare->Reg664_cntOK = RTL_R32(RXERR_RPT) & 0xfffff; + } +#endif + +#if !defined(CONFIG_RTL_NEW_AUTOCH) + signed char value8; + + // read OFDM FA counters + priv->pshare->ofdm_FA_cnt1 = RTL_R16(0xda2); + priv->pshare->ofdm_FA_cnt2 = RTL_R16(0xda4); + priv->pshare->ofdm_FA_cnt3 = RTL_R16(0xda6); + priv->pshare->ofdm_FA_cnt4 = RTL_R16(0xda8); + + // read the CCK FA counters + value8 = RTL_R8(0xa2d); + RTL_W8(0xa2d, value8 | 0x40); // regA2D[6]=1 to hold and read the CCK FA counters + priv->pshare->cck_FA_cnt = RTL_R8(0xa5b); + priv->pshare->cck_FA_cnt = priv->pshare->cck_FA_cnt << 8; + priv->pshare->cck_FA_cnt += RTL_R8(0xa5c); +#ifdef INTERFERENCE_CONTROL + priv->pshare->ofdm_FA_total_cnt = (unsigned int) priv->pshare->ofdm_FA_cnt1 + + priv->pshare->ofdm_FA_cnt2 + priv->pshare->ofdm_FA_cnt3 + + priv->pshare->ofdm_FA_cnt4 + RTL_R16(0xcf0) + RTL_R16(0xcf2); + + priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_total_cnt + priv->pshare->cck_FA_cnt; +#else + + priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_cnt1 + priv->pshare->ofdm_FA_cnt2 + + priv->pshare->ofdm_FA_cnt3 + priv->pshare->ofdm_FA_cnt4 + + priv->pshare->cck_FA_cnt + RTL_R16(0xcf0) + RTL_R16(0xcf2); +#endif + if (priv->pshare->rf_ft_var.rssi_dump) + priv->pshare->CCA_total_cnt = ((RTL_R8(0xa60)<<8)|RTL_R8(0xa61)) + RTL_R16(0xda0); +#else + hold_CCA_FA_counter(priv); + _FA_statistic(priv); + + if (priv->pshare->rf_ft_var.rssi_dump) + priv->pshare->CCA_total_cnt = ((RTL_R8(0xa60)<<8)|RTL_R8(0xa61)) + RTL_R16(0xda0); + + release_CCA_FA_counter(priv); +#endif + + reset_FA_reg(priv); + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G && !(OPMODE & WIFI_SITE_MONITOR)) { + if (priv->pshare->DNC_on == 0){ + //if ((priv->pshare->F94_cnt + priv->pshare->F90_cnt)> 3000){ + /* Reg 664: x > y && x > 1000 + Reg F94: x > 0.75*y && x > 1000 */ + if (((priv->pshare->Reg664_cnt>priv->pshare->Reg664_cntOK) && (priv->pshare->Reg664_cnt > 1000))|| + ((priv->pshare->F94_cnt > ((priv->pshare->Reg664_cntOK*3)>>2)) && (priv->pshare->F94_cnt > 1000))) { + priv->ext_stats.tp_average_pre = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; + priv->pshare->DNC_on = 1; + priv->pshare->DNC_chk_cnt = 1; + priv->pshare->DNC_chk = 2; // 0: don't check, 1; check, 2: just entering DNC + //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0x00a00000); + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07600760); + PHY_SetBBReg(priv, 0xc50, bMaskByte0, 0x20); + PHY_SetBBReg(priv, 0xc58, bMaskByte0, 0x20); + //printk("Dynamic Noise Control ON\n"); + } + } else { + if ((priv->pshare->DNC_chk_cnt % 5)==0){ // check every 5*2=10 seconds + unsigned long tp_now = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; + priv->pshare->DNC_chk_cnt = 0; + + if ((priv->pshare->DNC_chk == 2) && (tp_now < priv->ext_stats.tp_average_pre+5)){ + //no advantage, leave DNC state + priv->pshare->DNC_on = 0; + priv->pshare->DNC_chk = 0; + //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0); + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); + } + else + { + priv->pshare->DNC_chk = 0; + + /* If TP < 20M or TP varies more than 5M. Start Checking...*/ + if ((tp_now < 20) || ((tp_now < (priv->ext_stats.tp_average_pre-5))|| (tp_now > (priv->ext_stats.tp_average_pre+5)))){ + priv->pshare->DNC_chk = 1; + //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0); + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); + if (!timer_pending(&priv->dnc_timer)) { + //printk("... Start Check Noise ...\n"); + mod_timer(&priv->dnc_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(100)); // 100 ms + } + } + } + + priv->ext_stats.tp_average_pre = tp_now; + + } else if ((priv->pshare->DNC_chk_cnt % 5)==1 && priv->pshare->DNC_chk == 1) { + priv->pshare->DNC_chk = 0; + //if ((priv->pshare->F94_cnt + priv->pshare->F90_cnt) < 120) { + if ((priv->pshare->F94_cnt + priv->pshare->Reg664_cnt) < 120) { + priv->pshare->DNC_on = 0; + //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0); + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); + //printk("Dynamic Noise Control OFF\n"); + } + } + priv->pshare->DNC_chk_cnt++; + } + } + } +#endif +} + + +//3 ============================================================ +//3 Rate Adaptive +//3 ============================================================ + +void check_RA_by_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int level = 0; + + switch (pstat->rssi_level) { + case 1: + if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper) + level = 1; + else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) || + ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && + (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) + level = 2; + else + level = 3; + break; + case 2: + if (pstat->rssi > priv->pshare->rf_ft_var.raGoUpUpper) + level = 1; + else if ((pstat->rssi < priv->pshare->rf_ft_var.raGoDown40MLower) || + ((!pstat->ht_cap_len || !priv->pshare->is_40m_bw || + !(pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))) && + (pstat->rssi < priv->pshare->rf_ft_var.raGoDown20MLower))) + level = 3; + else + level = 2; + break; + case 3: + if (pstat->rssi > priv->pshare->rf_ft_var.raGoUpUpper) + level = 1; + else if ((pstat->rssi > priv->pshare->rf_ft_var.raGoUp20MLower) || + ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && + (pstat->rssi > priv->pshare->rf_ft_var.raGoUp40MLower) && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) + level = 2; + else + level = 3; + break; + default: + if (isErpSta(pstat)) + DEBUG_ERR("wrong rssi level setting\n"); + break; + } + + if (level != pstat->rssi_level) { + pstat->rssi_level = level; +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } + } +} +#endif + +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + +void check_txrate_by_reg(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned char initial_rate = 0x7f; + unsigned char legacyRA =0 ; + + if( should_restrict_Nrate(priv, pstat) && is_fixedMCSTxRate(priv, pstat)) + legacyRA = 1; + + if (pstat->sta_in_firmware == 1) + { + if (is_auto_rate(priv , pstat) || legacyRA) + { + initial_rate = RTL_R8(INIDATA_RATE_SEL + REMAP_AID(pstat)) & 0x7f; + if (initial_rate == 0x7f) + return; + + if ((initial_rate&0x3f) < 12) { + pstat->current_tx_rate = dot11_rate_table[initial_rate&0x3f]; + pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; + } else { + pstat->current_tx_rate = HT_RATE_ID + ((initial_rate&0x3f) -12); + if (initial_rate & BIT(6)) + pstat->ht_current_tx_info |= TX_USE_SHORT_GI; + else + pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; + } + + priv->pshare->current_tx_rate = pstat->current_tx_rate; + priv->pshare->ht_current_tx_info = pstat->ht_current_tx_info; + } else if (pstat->ht_cap_len) { + unsigned int is_sgi = 0; + + if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40) +#ifdef WIFI_11N_2040_COEXIST + && !((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11nConfigEntry.dot11nCoexist && + (priv->bg_ap_timeout || orForce20_Switch20Map(priv) + )) +#endif + ) { + if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M + && (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_))) + is_sgi++; + } else if (priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M + && (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_))) { + is_sgi++; + } + + if (is_sgi) + pstat->ht_current_tx_info |= TX_USE_SHORT_GI; + else + pstat->ht_current_tx_info &= ~TX_USE_SHORT_GI; + } + + if (pstat->ht_cap_len) { + if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40)) + pstat->ht_current_tx_info |= TX_USE_40M_MODE; + else + pstat->ht_current_tx_info &= ~TX_USE_40M_MODE; + } + + priv->pshare->ht_current_tx_info = pstat->ht_current_tx_info; + } else { + DEBUG_INFO("sta has no aid found to check current tx rate\n"); + } +} +#endif +#if 0 +void add_RATid(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned char limit=16; + int i; + unsigned long flags; + unsigned int update_reg=0; + + SAVE_INT_AND_CLI(flags); + + pstat->tx_ra_bitmap = 0; + + for (i=0; i<32; i++) { + if (pstat->bssrateset[i]) + pstat->tx_ra_bitmap |= get_bit_value_from_ieee_value(pstat->bssrateset[i]&0x7f); + } + + if (pstat->ht_cap_len) { + if ((pstat->MIMO_ps & _HT_MIMO_PS_STATIC_) || + (get_rf_mimo_mode(priv)== MIMO_1T2R) || + (get_rf_mimo_mode(priv)== MIMO_1T1R)) + limit=8; + + for (i=0; iht_cap_buf.support_mcs[i/8] & BIT(i%8)) + pstat->tx_ra_bitmap |= BIT(i+12); + } + } + + if (pstat->ht_cap_len) { + unsigned int set_sgi = 0; + if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40) +#ifdef WIFI_11N_2040_COEXIST + && !((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11nConfigEntry.dot11nCoexist && + (priv->bg_ap_timeout || orForce20_Switch20Map(priv) + )) +#endif + ) { + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_) + && priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M) + set_sgi++; + } else if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_) && + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M) { + set_sgi++; + } + + if (set_sgi) { +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv)==VERSION_8188E) + priv->pshare->RaInfo[pstat->aid].SGIEnable = 1; + else +#endif + pstat->tx_ra_bitmap |= BIT(28); + } +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + else { + if (GET_CHIP_VER(priv)==VERSION_8188E) + priv->pshare->RaInfo[pstat->aid].SGIEnable = 0; + } +#endif + } +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + else { + if (GET_CHIP_VER(priv)==VERSION_8188E) + priv->pshare->RaInfo[pstat->aid].SGIEnable = 0; + } +#endif + + if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3)) { + if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper) + pstat->rssi_level = 1; + else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) || + ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && + (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) + pstat->rssi_level = 2; + else + pstat->rssi_level = 3; + } + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) && + ((OPMODE & WIFI_AP_STATE) || (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G))) + pstat->tx_ra_bitmap &= 0xfffffff0; //disable cck rate + +#ifdef P2P_SUPPORT + if(pstat->is_p2p_client){ + pstat->tx_ra_bitmap &= 0xfffffff0; //disable cck rate + } +#endif + + // rate adaptive by rssi + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && (!should_restrict_Nrate(priv, pstat))) { + if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R)) { + switch (pstat->rssi_level) { + case 1: + pstat->tx_ra_bitmap &= 0x100f0000; + break; + case 2: + pstat->tx_ra_bitmap &= 0x100ff000; + break; + case 3: + if (priv->pshare->is_40m_bw) + pstat->tx_ra_bitmap &= 0x100ff005; + else + pstat->tx_ra_bitmap &= 0x100ff001; + break; + } + } else { + switch (pstat->rssi_level) { + case 1: + pstat->tx_ra_bitmap &= 0x1f8f0000; + break; + case 2: + pstat->tx_ra_bitmap &= 0x1f8ff000; + break; + case 3: + if (priv->pshare->is_40m_bw) + pstat->tx_ra_bitmap &= 0x010ff005; + else + pstat->tx_ra_bitmap &= 0x010ff001; + break; + } + + // Don't need to mask high rates due to new rate adaptive parameters + //if (pstat->is_broadcom_sta) // use MCS12 as the highest rate vs. Broadcom sta + // pstat->tx_ra_bitmap &= 0x81ffffff; + + // NIC driver will report not supporting MCS15 and MCS14 in asoc req + //if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta) + // pstat->tx_ra_bitmap &= 0x83ffffff; // if Realtek 1x2 sta, don't use MCS15 and MCS14 + } + } + else if (((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat)) || + ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) && + ((OPMODE & WIFI_AP_STATE) || (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)))) + { + switch (pstat->rssi_level) { + case 1: + pstat->tx_ra_bitmap &= 0x00000f00; + break; + case 2: + pstat->tx_ra_bitmap &= 0x00000ff0; + break; + case 3: + pstat->tx_ra_bitmap &= 0x00000ff5; + break; + } + } else { + pstat->tx_ra_bitmap &= 0x0000000d; + } + +// Client mode IOT issue, Button 2009.07.17 +#ifdef CLIENT_MODE + if(OPMODE & WIFI_STATION_STATE) { + if(!pstat->is_rtl8192s_sta && pstat->is_realtek_sta && pstat->is_legacy_encrpt) + pstat->tx_ra_bitmap &= 0x0001ffff; // up to MCS4 + } +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) && defined (USB_POWER_SUPPORT) + if ((GET_CHIP_VER(priv)==VERSION_8192D) && (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) + pstat->tx_ra_bitmap &= USB_RA_MASK; +#endif + + update_remapAid(priv, pstat); + +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifndef RATEADAPTIVE_BY_ODM + if (pstat->tx_ra_bitmap & 0xff000) { + if (priv->pshare->is_40m_bw) + priv->pshare->RaInfo[pstat->aid].RateID = ARFR_1T_40M; + else + priv->pshare->RaInfo[pstat->aid].RateID = ARFR_1T_20M; + } else if (pstat->tx_ra_bitmap & 0xff0) { + priv->pshare->RaInfo[pstat->aid].RateID = ARFR_BG_MIX; + } else { + priv->pshare->RaInfo[pstat->aid].RateID = ARFR_B_ONLY; + } + + priv->pshare->RaInfo[pstat->aid].RateMask = pstat->tx_ra_bitmap; + ARFBRefresh(priv, &priv->pshare->RaInfo[pstat->aid]); +#else + PODM_RA_INFO_T pRAInfo = &(ODMPTR->RAInfo[pstat->aid]); + if (pstat->tx_ra_bitmap & 0xff000) { + if (priv->pshare->is_40m_bw) + pRAInfo->RateID = ARFR_1T_40M; + else + pRAInfo->RateID = ARFR_1T_20M; + } else if (pstat->tx_ra_bitmap & 0xff0) { + pRAInfo->RateID = ARFR_BG_MIX; + } else { + pRAInfo->RateID = ARFR_B_ONLY; + } + ODM_RA_UpdateRateInfo_8188E(ODMPTR, pstat->aid, pRAInfo->RateID, pstat->tx_ra_bitmap, pRAInfo->RateSGI); +#endif + } else +#endif +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + { + + if (pstat->sta_in_firmware == 1) + { +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + { + pstat->tx_ra_bitmap &= 0xfffffff0; + if (pstat->tx_ra_bitmap & 0xff00000) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_40M, pstat->tx_ra_bitmap); + else + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_20M, pstat->tx_ra_bitmap); + update_reg++; + } else if (pstat->tx_ra_bitmap & 0xff000) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_40M, pstat->tx_ra_bitmap); + else + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_20M, pstat->tx_ra_bitmap); + } else if (pstat->tx_ra_bitmap & 0xff0) { + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_Band_A_BMC, pstat->tx_ra_bitmap); + } else { + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_Band_A_BMC, pstat->tx_ra_bitmap); + } + } else +#endif + { + if (pstat->tx_ra_bitmap & 0xff00000) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_40M, pstat->tx_ra_bitmap); + else + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_20M, pstat->tx_ra_bitmap); + update_reg++; + } else if (pstat->tx_ra_bitmap & 0xff000) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_1T_40M, pstat->tx_ra_bitmap); + else + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_1T_20M, pstat->tx_ra_bitmap); + } else if (pstat->tx_ra_bitmap & 0xff0) { + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_BG_MIX, pstat->tx_ra_bitmap); + } else { + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_B_ONLY, pstat->tx_ra_bitmap); + } + } + + /* + * Rate adaptive algorithm. + * If the STA is 2R, we set the inti rate to MCS 15 + */ + if (update_reg) { + if (!pstat->check_init_tx_rate && (pstat->rssi > 55)) { + //RTL_W8(INIDATA_RATE_SEL + REMAP_AID(pstat), 0x0c); + pstat->check_init_tx_rate = 1; + } + } + DEBUG_INFO("Add id %d val %08x to ratr\n", pstat->aid, pstat->tx_ra_bitmap); + } else { +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, priv->pshare->fw_support_sta_num, ARFR_2T_Band_A_40M, 0x1ffffff0); + else + set_RATid_cmd(priv, priv->pshare->fw_support_sta_num, ARFR_2T_Band_A_20M, 0x1ffffff0); + } else +#endif + { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, priv->pshare->fw_support_sta_num, ARFR_2T_40M, 0x1fffffff); + else + set_RATid_cmd(priv, priv->pshare->fw_support_sta_num, ARFR_2T_20M, 0x1fffffff); + } + + } + } +#endif + + RESTORE_INT(flags); +} +#endif + +void set_rssi_cmd(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + unsigned int content = 0; + + int rssi = pstat->rssi; + +#ifdef HIGH_POWER_EXT_PA + if( priv->pshare->rf_ft_var.use_ext_pa ) + rssi += RSSI_DIFF_PA; + if( rssi > 100) + rssi = 100; +#endif + + + SAVE_INT_AND_CLI(flags); + + /* + * set rssi + */ + content = rssi<< 24; + +#ifdef CONFIG_RTL_92D_SUPPORT + /* + * set max macid + */ + if (GET_CHIP_VER(priv) == VERSION_8192D){ + content |= priv->pshare->max_fw_macid << 16; + } +#endif + + /* + * set macid + */ + content |= REMAP_AID(pstat) << 8; + + /* + * set cmd id + */ + content |= H2C_CMD_RSSI; + + signin_h2c_cmd(priv, content, 0); + + RESTORE_INT(flags); +} + +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) +#ifdef CONFIG_PCI_HCI +void add_rssi_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + struct stat_info *pstat = NULL; + unsigned int set_timer = 0; + unsigned long flags = 0; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (timer_pending(&priv->add_rssi_timer)) + del_timer_sync(&priv->add_rssi_timer); + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) + return; +#endif + + if (!list_empty(&priv->addrssi_list)) { + pstat = list_entry(priv->addrssi_list.next, struct stat_info, addrssi_list); + if (!pstat) + return; + + if (!is_h2c_buf_occupy(priv)) { + set_rssi_cmd(priv, pstat); + if (!list_empty(&pstat->addrssi_list)) { + SAVE_INT_AND_CLI(flags); + SMP_LOCK(flags); + list_del_init(&pstat->addrssi_list); + RESTORE_INT(flags); + SMP_UNLOCK(flags); + } + + if (!list_empty(&priv->addrssi_list)) + set_timer++; + } else { + set_timer++; + } + } + + if (set_timer) + mod_timer(&priv->add_rssi_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(50)); // 50 ms +} + + +void add_update_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ +#ifndef SMP_SYNC + unsigned long flags; +#endif + + if (is_h2c_buf_occupy(priv)) { + if (list_empty(&pstat->addrssi_list)) { + SAVE_INT_AND_CLI(flags); + list_add_tail(&(pstat->addrssi_list), &(priv->addrssi_list)); + RESTORE_INT(flags); + + if (!timer_pending(&priv->add_rssi_timer)) + mod_timer(&priv->add_rssi_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(50)); // 50 ms + } + } else { + set_rssi_cmd(priv, pstat); + } +} +#endif // CONFIG_PCI_HCI + +#ifdef CONFIG_USB_HCI +void add_update_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + notify_update_sta_rssi(priv, pstat); +} +#endif // CONFIG_USB_HCI +#endif // CONFIG_RTL_92D_SUPPORT || CONFIG_RTL_92C_SUPPORT + + +void set_RATid_cmd(struct rtl8192cd_priv *priv, unsigned int macid, unsigned int rateid, unsigned int ratemask) +{ + unsigned int content = 0; + unsigned short ext_content = 0; + +//#ifdef CONFIG_RTL_8812_SUPPORT + if(! CHIP_VER_92X_SERIES(priv)) + return; +//#endif + + /* + * set ratemask + */ + ext_content = ratemask & 0xffff; + content = ((ratemask & 0xfff0000) >> 16) << 8; + + /* + * set short GI + */ + if (ratemask & BIT(28)) + content |= BIT(29); + + /* + * set macid (station aid) + */ + content |= (macid & 0x1f) << 24; + + /* + * set rateid (ARFR table) + */ + content |= (rateid & 0xf) << 20; + + /* + * set ext_content used + */ + content |= BIT(7); + + /* + * set cmd id + */ + content |= H2C_CMD_MACID; + + signin_h2c_cmd(priv, content, ext_content); +} + + + +//3 ============================================================ +//3 EDCCA +//3 ============================================================ +#if 0 +void check_EDCCA(struct rtl8192cd_priv *priv, short rssi) +{ + if ((priv->pshare->rf_ft_var.edcca_thd) && (priv->pmib->dot11RFEntry.dot11channel==14 + || priv->pshare->is_40m_bw +#if defined(CONFIG_RTL_92D_SUPPORT) + || (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G) +#endif + )) { + if((rssi > priv->pshare->rf_ft_var.edcca_thd) && (priv->pshare->phw->EDCCA_on == 0)) { + RTL_W32(rOFDM0_ECCAThreshold, 0xfc03fd); + priv->pshare->phw->EDCCA_on =1; + } else if( (rssi < priv->pshare->rf_ft_var.edcca_thd-5) && priv->pshare->phw->EDCCA_on) { + RTL_W32(rOFDM0_ECCAThreshold, 0x7f037f); + priv->pshare->phw->EDCCA_on =0; + } + } + if ((!priv->pshare->rf_ft_var.edcca_thd) && priv->pshare->phw->EDCCA_on) { + RTL_W32(0xc4c, 0x7f037f); + priv->pshare->phw->EDCCA_on = 0; + } +} +#endif + +//3 ============================================================ +//3 Antenna Diversity +//3 ============================================================ +#ifdef SW_ANT_SWITCH + +// +// 20100514 Luke/Joseph: +// Add new function to reset antenna diversity state after link. +// + +void resetSwAntDivVariable(struct rtl8192cd_priv *priv) +{ + priv->pshare->RSSI_sum_R = 0; + priv->pshare->RSSI_cnt_R = 0; + priv->pshare->RSSI_sum_L = 0; + priv->pshare->RSSI_cnt_L = 0; + priv->pshare->TXByteCnt_R = 0; + priv->pshare->TXByteCnt_L = 0; + priv->pshare->RXByteCnt_R = 0; + priv->pshare->RXByteCnt_L = 0; + +} +void SwAntDivRestAfterLink(struct rtl8192cd_priv *priv) +{ + priv->pshare->RSSI_test = FALSE; + priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_RESET; + memset(priv->pshare->DM_SWAT_Table.SelectAntennaMap, 0, sizeof(priv->pshare->DM_SWAT_Table.SelectAntennaMap)); + priv->pshare->DM_SWAT_Table.mapIndex = 0; + priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; + priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; + resetSwAntDivVariable(priv); +} + + +void dm_SW_AntennaSwitchInit(struct rtl8192cd_priv *priv) +{ + if(!priv->pshare->rf_ft_var.antSw_enable) + return; + +// if (GET_CHIP_VER(priv) == VERSION_8188C) + if(get_rf_mimo_mode(priv)== MIMO_1T1R) + priv->pshare->rf_ft_var.antSw_select = 0; + + //RT_TRACE(COMP_SWAS, DBG_LOUD, ("SWAS:Init SW Antenna Switch\n")); + resetSwAntDivVariable(priv); + priv->pshare->DM_SWAT_Table.CurAntenna = Antenna_L; + priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_RESET; + memset(priv->pshare->DM_SWAT_Table.SelectAntennaMap, 0, sizeof(priv->pshare->DM_SWAT_Table.SelectAntennaMap)); + priv->pshare->DM_SWAT_Table.mapIndex = 0; + +#ifdef GPIO_ANT_SWITCH +#ifdef CONFIG_RTL_92D_DMDP + if(priv->pshare->wlandev_idx==0) + priv->pshare->rf_ft_var.antHw_enable=0; + else + return; +#endif +// GPIO 45 : +// GPIO_MOD => data port +// GPIO_IO_SEL => output + RTL_W32(GPIO_PIN_CTRL, 0x00300000| RTL_R32(GPIO_PIN_CTRL)); + PHY_SetBBReg(priv, GPIO_PIN_CTRL, 0x3000, priv->pshare->DM_SWAT_Table.CurAntenna); + RTL_W32(rFPGA0_XCD_RFParameter, RTL_R32(rFPGA0_XCD_RFParameter)| BIT(15)|BIT(16)); // enable ANTSEL + +#else + RTL_W32(LEDCFG, RTL_R32(LEDCFG) | BIT(23) ); //enable LED[1:0] pin as ANTSEL + + if ( !priv->pshare->rf_ft_var.antSw_select) { + RTL_W32(rFPGA0_XAB_RFParameter, RTL_R32(rFPGA0_XAB_RFParameter) | BIT(13) ); //select ANTESEL from path A + RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) | BIT(8)| BIT(9) ); // enable ANTSEL A as SW control + RTL_W32(rFPGA0_XA_RFInterfaceOE, (RTL_R32(rFPGA0_XA_RFInterfaceOE) & ~(BIT(8)|BIT(9)))| 0x01<<8 ); // 0x01: left antenna, 0x02: right antenna + } else { + RTL_W32(rFPGA0_XAB_RFParameter, RTL_R32(rFPGA0_XAB_RFParameter) & ~ BIT(13) ); //select ANTESEL from path B + RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) | BIT(24)| BIT(25) ); // enable ANTSEL B as SW control + RTL_W32(rFPGA0_XB_RFInterfaceOE, (RTL_R32(rFPGA0_XB_RFInterfaceOE) & ~(BIT(8)|BIT(9)))| 0x01<<8 ); // 0x01: left antenna, 0x02: right antenna + } + RTL_W16(rFPGA0_TxInfo, (RTL_R16(rFPGA0_TxInfo)&0xf0ff) | BIT(8) ); // b11-b8=0001 +#endif + + // Move the timer initialization to InitializeVariables function. + //PlatformInitializeTimer(Adapter, &pMgntInfo->SwAntennaSwitchTimer, (RT_TIMER_CALL_BACK)dm_SW_AntennaSwitchCallback, NULL, "SwAntennaSwitchTimer"); +} +// +// 20100514 Luke/Joseph: +// Add new function for antenna diversity after link. +// This is the main function of antenna diversity after link. +// This function is called in HalDmWatchDog() and dm_SW_AntennaSwitchCallback(). +// HalDmWatchDog() calls this function with SWAW_STEP_PEAK to initialize the antenna test. +// In SWAW_STEP_PEAK, another antenna and a 500ms timer will be set for testing. +// After 500ms, dm_SW_AntennaSwitchCallback() calls this function to compare the signal just +// listened on the air with the RSSI of original antenna. +// It chooses the antenna with better RSSI. +// There is also a aged policy for error trying. Each error trying will cost more 5 seconds waiting +// penalty to get next try. +// +void dm_SW_AntennaSwitch(struct rtl8192cd_priv *priv, char Step) +{ + unsigned int curTxOkCnt, curRxOkCnt; + unsigned int CurByteCnt, PreByteCnt; + int Score_R=0, Score_L=0; + int RSSI_R, RSSI_L; + char nextAntenna=priv->pshare->DM_SWAT_Table.CurAntenna; + int i; + +//1 1. Determine which condition should turn off Antenna Diversity + +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) + return; +#endif + +// if(!(GET_CHIP_VER(priv) == VERSION_8188C) || !priv->pshare->rf_ft_var.antSw_enable) +// return; + + if((!priv->assoc_num) +#ifdef PCIE_POWER_SAVING + || (priv->pwr_state == L2) || (priv->pwr_state == L1) +#endif + ){ + SwAntDivRestAfterLink(priv); + return; + } + + // Handling step mismatch condition. + // Peak step is not finished at last time. Recover the variable and check again. + if( Step != priv->pshare->DM_SWAT_Table.try_flag) + { + SwAntDivRestAfterLink(priv); + } + +//1 2. Initialization: Select a assocaiated AP or STA as RSSI target + if(priv->pshare->DM_SWAT_Table.try_flag == SWAW_STEP_RESET) { +#ifdef CLIENT_MODE + if((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) { + // Target: Infrastructure mode AP. + priv->pshare->RSSI_target = NULL; + } +#endif + resetSwAntDivVariable(priv); + priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_PEAK; + return; + } + else { + +//1 3. Antenna Diversity + + //2 Calculate TX and RX OK bytes + + curTxOkCnt = priv->net_stats.tx_bytes - priv->pshare->lastTxOkCnt; + curRxOkCnt = priv->net_stats.rx_bytes - priv->pshare->lastRxOkCnt; + priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; + priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; + + //2 Try State + if(priv->pshare->DM_SWAT_Table.try_flag == SWAW_STEP_DETERMINE) { + //3 1. Seperately caculate TX and RX OK byte counter for ant A and B + if(priv->pshare->DM_SWAT_Table.CurAntenna == Antenna_R) { + priv->pshare->TXByteCnt_R += curTxOkCnt; + priv->pshare->RXByteCnt_R += curRxOkCnt; + } else { + priv->pshare->TXByteCnt_L += curTxOkCnt; + priv->pshare->RXByteCnt_L += curRxOkCnt; + } + + //3 2. Change anntena for testing + if(priv->pshare->DM_SWAT_Table.RSSI_Trying != 0) { + nextAntenna = (priv->pshare->DM_SWAT_Table.CurAntenna ) ^ Antenna_MAX; + priv->pshare->DM_SWAT_Table.RSSI_Trying--; + } + + //2 Try State End: Determine the best antenna + + if(priv->pshare->DM_SWAT_Table.RSSI_Trying==0) { + nextAntenna = priv->pshare->DM_SWAT_Table.CurAntenna; + priv->pshare->DM_SWAT_Table.mapIndex = (priv->pshare->DM_SWAT_Table.mapIndex+1)%SELANT_MAP_SIZE; + + //3 TP Mode: Determine the best antenna by throuhgput + if(priv->pshare->DM_SWAT_Table.TestMode == TP_MODE) { + + + + //3 (1) Saperately caculate total byte count for two antennas + if(priv->pshare->DM_SWAT_Table.CurAntenna == Antenna_R) { + CurByteCnt = (priv->pshare->TXByteCnt_R + (priv->pshare->RXByteCnt_R<<1)); + PreByteCnt = (priv->pshare->TXByteCnt_L + (priv->pshare->RXByteCnt_L<<1)); + } else { + CurByteCnt = (priv->pshare->TXByteCnt_L + (priv->pshare->RXByteCnt_L<<1)); + PreByteCnt = (priv->pshare->TXByteCnt_R + (priv->pshare->RXByteCnt_R<<1)); + } + + //3 (2) Throughput Normalization + if(priv->pshare->TrafficLoad == TRAFFIC_HIGH) + CurByteCnt >>=3; + else if(priv->pshare->TrafficLoad == TRAFFIC_LOW) + CurByteCnt >>=1; + + if(priv->pshare->DM_SWAT_Table.CurAntenna == Antenna_R) { + priv->pshare->DM_SWAT_Table.SelectAntennaMap[0][priv->pshare->DM_SWAT_Table.mapIndex] = PreByteCnt; + priv->pshare->DM_SWAT_Table.SelectAntennaMap[1][priv->pshare->DM_SWAT_Table.mapIndex] = CurByteCnt; + } else { + priv->pshare->DM_SWAT_Table.SelectAntennaMap[0][priv->pshare->DM_SWAT_Table.mapIndex] = CurByteCnt; + priv->pshare->DM_SWAT_Table.SelectAntennaMap[1][priv->pshare->DM_SWAT_Table.mapIndex] = PreByteCnt; + } + + Score_R = Score_L=0; + for (i= 0; ipshare->DM_SWAT_Table.SelectAntennaMap[0][i]; + Score_R += priv->pshare->DM_SWAT_Table.SelectAntennaMap[1][i]; + } + + nextAntenna = (Score_L > Score_R) ? Antenna_L : Antenna_R; + + if(priv->pshare->rf_ft_var.ant_dump&8) + panic_printk("Mode TP, select Ant%d, [Score1=%d,Score2=%d]\n", nextAntenna, Score_L, Score_R); + + } + + //3 RSSI Mode: Determine the best anntena by RSSI + else if(priv->pshare->DM_SWAT_Table.TestMode == RSSI_MODE) { + + //2 Saperately caculate average RSSI for two antennas + RSSI_L = RSSI_R = 0; + + if(priv->pshare->RSSI_cnt_R > 0) + RSSI_R = priv->pshare->RSSI_sum_R/priv->pshare->RSSI_cnt_R; + if(priv->pshare->RSSI_cnt_L > 0) + RSSI_L = priv->pshare->RSSI_sum_L/priv->pshare->RSSI_cnt_L; + + if(RSSI_L && RSSI_R ) + nextAntenna = (RSSI_L > RSSI_R) ? Antenna_L : Antenna_R; + + if(priv->pshare->rf_ft_var.ant_dump&8) + panic_printk("Mode RSSI, RSSI_R=%d(%d), RSSI_L=%d(%d), Ant=%d\n", + RSSI_R, priv->pshare->RSSI_cnt_R, RSSI_L, priv->pshare->RSSI_cnt_L, nextAntenna); + + } + + //3 Reset state + resetSwAntDivVariable(priv); + priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_PEAK; + priv->pshare->RSSI_test = FALSE; + } + } + + //1 Normal State + else if(priv->pshare->DM_SWAT_Table.try_flag == SWAW_STEP_PEAK) { + + //3 Determine TP/RSSI mode by TRX OK count + if((curRxOkCnt+curTxOkCnt) > TP_MODE_THD) { + //2 Determine current traffic is high or low + if((curTxOkCnt+curRxOkCnt) > TRAFFIC_THRESHOLD) + priv->pshare->TrafficLoad = TRAFFIC_HIGH; + else + priv->pshare->TrafficLoad = TRAFFIC_LOW; + + priv->pshare->DM_SWAT_Table.RSSI_Trying = 10; + priv->pshare->DM_SWAT_Table.TestMode = TP_MODE; + } else { + + int idx = 0; + struct stat_info* pEntry = findNextSTA(priv, &idx); + priv->pshare->RSSI_target = NULL; + while(pEntry) { + if(pEntry && pEntry->expire_to) { + if(!priv->pshare->RSSI_target) + priv->pshare->RSSI_target = pEntry; + else if( pEntry->rssi < priv->pshare->RSSI_target->rssi ) + priv->pshare->RSSI_target = pEntry; + } + pEntry = findNextSTA(priv, &idx); + }; + + priv->pshare->DM_SWAT_Table.RSSI_Trying = 6; + priv->pshare->DM_SWAT_Table.TestMode = RSSI_MODE; + + if(priv->pshare->RSSI_target == NULL) { + SwAntDivRestAfterLink(priv); + return; + } + + //3 reset state + memset(priv->pshare->DM_SWAT_Table.SelectAntennaMap, 0, sizeof(priv->pshare->DM_SWAT_Table.SelectAntennaMap)); + } + + //3 Begin to enter Try State + nextAntenna = (priv->pshare->DM_SWAT_Table.CurAntenna ) ^ Antenna_MAX; + priv->pshare->DM_SWAT_Table.try_flag = SWAW_STEP_DETERMINE; + priv->pshare->RSSI_test = TRUE; + + //3 Reset variables + resetSwAntDivVariable(priv); + } + } + +//1 4.Change TRX antenna + if(nextAntenna != priv->pshare->DM_SWAT_Table.CurAntenna) { +#if defined(CONFIG_PCI_HCI) +#ifdef GPIO_ANT_SWITCH + PHY_SetBBReg(priv, GPIO_PIN_CTRL, 0x3000, nextAntenna); +#else + if (!priv->pshare->rf_ft_var.antSw_select) + PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, 0x300, nextAntenna); + else + PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, 0x300, nextAntenna); +#endif + +//1 5.Reset Statistics + priv->pshare->DM_SWAT_Table.CurAntenna = nextAntenna; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_antenna_switch(priv, nextAntenna); +#endif + } + +//1 6.Set next timer + + if(priv->pshare->DM_SWAT_Table.RSSI_Trying == 0) { + return; + } + + if(priv->pshare->DM_SWAT_Table.TestMode == RSSI_MODE) { + mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(400)); // 400 ms + } else if(priv->pshare->DM_SWAT_Table.TestMode == TP_MODE) { + + if(priv->pshare->TrafficLoad == TRAFFIC_HIGH) { + if(priv->pshare->DM_SWAT_Table.RSSI_Trying%2 == 0) + mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(10)); // 10 ms + else + mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(80)); // 80 ms + + } else if(priv->pshare->TrafficLoad == TRAFFIC_LOW) { + if(priv->pshare->DM_SWAT_Table.RSSI_Trying%2 == 0) + mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(40)); // 40 ms + else + mod_timer(&priv->pshare->swAntennaSwitchTimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(80)); // 80 ms + } + } + +} + + +void dm_SW_AntennaSwitchCallback(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv*)task_priv; +#ifndef SMP_SYNC + unsigned long flags = 0; +#endif + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + SAVE_INT_AND_CLI(flags); + dm_SW_AntennaSwitch(priv, SWAW_STEP_DETERMINE); + RESTORE_INT(flags); +} + +// +// 20100514 Luke/Joseph: +// This function is used to gather the RSSI information for antenna testing. +// It selects the RSSI of the peer STA that we want to know. +// +void dm_SWAW_RSSI_Check(struct rtl8192cd_priv *priv, struct rx_frinfo *pfrinfo) +{ + struct stat_info* pEntry = NULL; + pEntry = get_stainfo(priv, GetAddr2Ptr(get_pframe(pfrinfo))); + + if((priv->pshare->RSSI_target==NULL)||(priv->pshare->RSSI_target==pEntry)) { + //1 RSSI for SW Antenna Switch + if(priv->pshare->DM_SWAT_Table.CurAntenna == Antenna_R) + { + priv->pshare->RSSI_sum_R += pfrinfo->rssi; + priv->pshare->RSSI_cnt_R++; + } else { + priv->pshare->RSSI_sum_L += pfrinfo->rssi; + priv->pshare->RSSI_cnt_L++; + } + } +} + +#ifndef HW_ANT_SWITCH + +int diversity_antenna_select(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int ant = _atoi(data, 16); +// if(GET_CHIP_VER(priv) != VERSION_8188C) +// return 0; + +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); +#endif + if(ant==Antenna_L || ant==Antenna_R) { +#ifdef GPIO_ANT_SWITCH + PHY_SetBBReg(priv, GPIO_PIN_CTRL, 0x3000, ant); +#else + if (!priv->pshare->rf_ft_var.antSw_select) + PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, 0x300, ant); + else + PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, 0x300, ant); +#endif + priv->pshare->DM_SWAT_Table.CurAntenna = ant; + priv->pshare->rf_ft_var.antSw_enable = 0; + SwAntDivRestAfterLink(priv); + memset(priv->pshare->DM_SWAT_Table.SelectAntennaMap, 0, sizeof(priv->pshare->DM_SWAT_Table.SelectAntennaMap)); + return 1; + } else { + priv->pshare->rf_ft_var.antSw_enable = 1; + priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; + priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; + + return 0; + } +} +#endif +#endif +#if defined(HW_ANT_SWITCH) + +void dm_HW_AntennaSwitchInit(struct rtl8192cd_priv *priv) +{ + if(!priv->pshare->rf_ft_var.antHw_enable) + return; +#ifdef SW_ANT_SWITCH + priv->pshare->rf_ft_var.antSw_enable =0; +#endif + +// if (GET_CHIP_VER(priv) == VERSION_8188C) + if(get_rf_mimo_mode(priv)== MIMO_1T1R) + priv->pshare->rf_ft_var.antSw_select = 0; + + if ( !priv->pshare->rf_ft_var.antSw_select) { + RTL_W32(rFPGA0_XAB_RFParameter, RTL_R32(rFPGA0_XAB_RFParameter) | BIT(13) ); //select ANTESEL from path A + RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) & ~(BIT(8)| BIT(9)) ); // ANTSEL as HW control + RTL_W32(rFPGA0_XA_RFInterfaceOE, (RTL_R32(rFPGA0_XA_RFInterfaceOE) & ~(BIT(8)|BIT(9)))| 0x01<<8 ); // 0x01: left antenna, 0x02: right antenna + RTL_W8(0xc50, RTL_R8(0xc50) | BIT(7)); // Enable Hardware antenna switch + RTL_W32(0xc54, RTL_R32(0xc54) | BIT(23) ); // Decide final antenna by comparing 2 antennas' pwdb + } else { + RTL_W32(rFPGA0_XAB_RFParameter, RTL_R32(rFPGA0_XAB_RFParameter) & ~ BIT(13) ); //select ANTESEL from path B + RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) & ~(BIT(24)| BIT(25)) ); // ANTSEL as HW control + RTL_W32(rFPGA0_XB_RFInterfaceOE, (RTL_R32(rFPGA0_XB_RFInterfaceOE) & ~(BIT(8)|BIT(9)))| 0x01<<8 ); // 0x01: left antenna, 0x02: right antenna +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, RTL_R8(0xc58) | BIT(7)); // Enable Hardware antenna switch +#endif + RTL_W32(0xc5C, RTL_R32(0xc5c) | BIT(23) ); // Decide final antenna by comparing 2 antennas' pwdb + } + + priv->pshare->rf_ft_var.CurAntenna = 0; + + RTL_W32(LEDCFG, RTL_R32(LEDCFG) | BIT(23) ); //enable LED[1:0] pin as ANTSEL + RTL_W16(0xca4, (RTL_R16(0xca4) & ~(0xfff))|0x0c0); // Pwdb threshold=12dB + RTL_W32(0x874, RTL_R32(0x874) & ~ BIT(23) ); // No update ANTSEL during GNT_BT=1 + RTL_W16(rFPGA0_TxInfo, (RTL_R16(rFPGA0_TxInfo)&0xf0ff) | BIT(8) ); // b11-b8=0001 + RTL_W32(0x80c, RTL_R32(0x80c) | BIT(21) ); // assign antenna by tx desc + + // CCK setting + RTL_W8(0xa01, RTL_R8(0xa01) | BIT(7)); // enable hw ant diversity + RTL_W8(0xa0c, (RTL_R8(0xa0c) & 0xe0) | 0x0f ); // b4=0, b3:0 = 1111 32 sample + RTL_W8(0xa11, RTL_R8(0xa11) | BIT(5)); // do not change default optional antenna + RTL_W8(0xa14, (RTL_R8(0xa14) & 0xe0) | 0x08 ); // default : optional = 1:1 +#ifdef GPIO_ANT_SWITCH + PHY_SetBBReg(priv, rFPGA0_XCD_RFParameter, 0x40000000, 0x01); // enable ANTSEL +#endif + +} + +void setRxIdleAnt(struct rtl8192cd_priv *priv, char Ant) +{ + if(priv->pshare->rf_ft_var.CurAntenna != Ant) { + if(Ant) { + RTL_W32(0x858, 0x65a965a9); +// RTL_W8(0x6d8, RTL_R8(0x6d8) | BIT(6) ); + } + else { + RTL_W32(0x858, 0x569a569a); +// RTL_W8(0x6d8, RTL_R8(0x6d8) & (~ BIT(6))); + } + priv->pshare->rf_ft_var.CurAntenna = Ant; + } +} + +void dm_STA_Ant_Select(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int ScoreA=0, ScoreB=0, i, nextAnt= pstat->CurAntenna, idleAnt=priv->pshare->rf_ft_var.CurAntenna; + + if((priv->pshare->rf_ft_var.CurAntenna & 0x80) + || ((pstat->hwRxAntSel[0] + pstat->hwRxAntSel[1])==0 && (pstat->cckPktCount[0] + pstat->cckPktCount[1])<10) ) + return; + + for(i=0; i<2; i++) { + if(pstat->cckPktCount[i]==0 && pstat->hwRxAntSel[i]==0) + pstat->AntRSSI[i] = 0; + } + + if(pstat->hwRxAntSel[0] || pstat->hwRxAntSel[1]) { + ScoreA = pstat->hwRxAntSel[0]; + ScoreB = pstat->hwRxAntSel[1]; + + if(ScoreA != ScoreB) { + if(ScoreA > ScoreB) + nextAnt = 0; + else + nextAnt = 1; + } + } else { + ScoreA = pstat->cckPktCount[0]; + ScoreB = pstat->cckPktCount[1]; + + if(ScoreA > 5*ScoreB) + nextAnt = 0; + else if(ScoreB > 5*ScoreA) + nextAnt = 1; + else if(ScoreA > ScoreB) + nextAnt = 1; + else if(ScoreB > ScoreA) + nextAnt = 0; + } + + pstat->CurAntenna = nextAnt; + + if(priv->pshare->rf_ft_var.ant_dump&2) { + panic_printk("id=%d, OFDM/CCK: (%d, %d/%d, %d), RSSI:(%d, %d), ant=%d, RxIdle=%d\n", + pstat->aid, + pstat->hwRxAntSel[1], + pstat->hwRxAntSel[0], + pstat->cckPktCount[1], + pstat->cckPktCount[0], + pstat->AntRSSI[1], + pstat->AntRSSI[0], + (pstat->CurAntenna==0 ? 2: 1) + ,((priv->pshare->rf_ft_var.CurAntenna&1)==0 ? 2 : 1) + ); + } + + if(pstat->AntRSSI[idleAnt]==0) + pstat->AntRSSI[idleAnt] = pstat->AntRSSI[idleAnt^1]; + +// reset variables + pstat->hwRxAntSel[1] = pstat->hwRxAntSel[0] =0; + pstat->cckPktCount[1]= pstat->cckPktCount[0] =0; + +} + +void dm_HW_IdleAntennaSelect(struct rtl8192cd_priv *priv) +{ + struct stat_info *pstat, *pstat_min=NULL; + struct list_head *phead, *plist; + int rssi_min= 0xff, i; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + if(priv->pshare->rf_ft_var.CurAntenna & 0x80) + return; + + phead = &priv->asoc_list; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while(plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if((pstat->expire_to) && (pstat->AntRSSI[0] || pstat->AntRSSI[1])) { + int rssi = (pstat->AntRSSI[0] < pstat->AntRSSI[1]) ? pstat->AntRSSI[0] : pstat->AntRSSI[1]; + if((!pstat_min) || ( rssi < rssi_min) ) { + pstat_min = pstat; + rssi_min = rssi; + } + } + }; + + SMP_UNLOCK_ASOC_LIST(flags); + + if(pstat_min) + setRxIdleAnt(priv, pstat_min->CurAntenna); + + +#ifdef TX_SHORTCUT + if (!priv->pmib->dot11OperationEntry.disable_txsc) { + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while(plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if(pstat->expire_to) { + for (i=0; itx_sc_ent[i].hwdesc1); + pdesc->Dword2 &= set_desc(~ (BIT(24)|BIT(25))); + if((pstat->CurAntenna^priv->pshare->rf_ft_var.CurAntenna)&1) + pdesc->Dword2 |= set_desc(BIT(24)|BIT(25)); + #ifdef CONFIG_PCI_HCI + pdesc= &(pstat->tx_sc_ent[i].hwdesc2); + pdesc->Dword2 &= set_desc(~ (BIT(24)|BIT(25))); + if((pstat->CurAntenna^priv->pshare->rf_ft_var.CurAntenna)&1) + pdesc->Dword2 |= set_desc(BIT(24)|BIT(25)); + #endif + } + } + }; + + SMP_UNLOCK_ASOC_LIST(flags); + } +#endif + +} + +int diversity_antenna_select(struct rtl8192cd_priv *priv, unsigned char *data) +{ + int ant = _atoi(data, 16); + +#ifdef PCIE_POWER_SAVING + PCIeWakeUp(priv, POWER_DOWN_T0); +#endif + + if (ant==Antenna_L || ant==Antenna_R) { + +#ifdef GPIO_ANT_SWITCH + if(priv->pshare->rf_ft_var.antSw_enable) { + PHY_SetBBReg(priv, GPIO_PIN_CTRL, 0x3000, ant); + } else +#endif + { + if ( !priv->pshare->rf_ft_var.antSw_select) { + RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) | BIT(8)| BIT(9) ); // ANTSEL A as SW control + RTL_W8(0xc50, RTL_R8(0xc50) & (~ BIT(7))); // rx OFDM SW control + PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, 0x300, ant); + } else { + RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) | BIT(24)| BIT(25) ); // ANTSEL B as HW control + PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, 0x300, ant); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, RTL_R8(0xc58) & (~ BIT(7))); // rx OFDM SW control +#endif + } + RTL_W8(0xa01, RTL_R8(0xa01) & (~ BIT(7))); // rx CCK SW control + RTL_W32(0x80c, RTL_R32(0x80c) & (~ BIT(21))); // select ant by tx desc + RTL_W32(0x858, 0x569a569a); + } + if(HW_DIV_ENABLE) + priv->pshare->rf_ft_var.antHw_enable = BIT(5); + priv->pshare->rf_ft_var.CurAntenna = (ant%2); +#ifdef SW_ANT_SWITCH + if(priv->pshare->rf_ft_var.antSw_enable) + priv->pshare->rf_ft_var.antSw_enable = BIT(5); + priv->pshare->DM_SWAT_Table.CurAntenna = ant; + priv->pshare->RSSI_test =0; +#endif + } + else if(ant==0){ +#ifdef GPIO_ANT_SWITCH + if(priv->pshare->rf_ft_var.antHw_enable) +#endif + { + if (!priv->pshare->rf_ft_var.antSw_select) { + RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) & ~(BIT(8)| BIT(9)) ); + RTL_W8(0xc50, RTL_R8(0xc50) | BIT(7)); // OFDM HW control + } else { + RTL_W32(rFPGA0_XAB_RFInterfaceSW, RTL_R32(rFPGA0_XAB_RFInterfaceSW) & ~(BIT(24)| BIT(25)) ); +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if ( +#ifdef CONFIG_RTL_92C_SUPPORT + (GET_CHIP_VER(priv)==VERSION_8192C) || (GET_CHIP_VER(priv)==VERSION_8188C) +#endif +#ifdef CONFIG_RTL_92D_SUPPORT +#ifdef CONFIG_RTL_92C_SUPPORT + || +#endif + (GET_CHIP_VER(priv)==VERSION_8192D) +#endif + ) + RTL_W8(0xc58, RTL_R8(0xc58) | BIT(7)); // OFDM HW control +#endif + } + RTL_W8(0xa01, RTL_R8(0xa01) | BIT(7)); // CCK HW control + RTL_W32(0x80c, RTL_R32(0x80c) | BIT(21) ); // by tx desc + priv->pshare->rf_ft_var.CurAntenna = 0; + RTL_W32(0x858, 0x569a569a); + priv->pshare->rf_ft_var.antHw_enable = 1; +#ifdef SW_ANT_SWITCH + priv->pshare->rf_ft_var.antSw_enable = 0; + priv->pshare->RSSI_test =0; +#endif + } +#ifdef SW_ANT_SWITCH + if(priv->pshare->rf_ft_var.antSw_enable) { + dm_SW_AntennaSwitchInit(priv); + RTL_W32(0x858, 0x569a569a); + priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; + priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; + priv->pshare->rf_ft_var.antHw_enable = 0; + priv->pshare->rf_ft_var.antSw_enable = 1; + } +#endif + + } +#if defined(SW_ANT_SWITCH) && !defined(GPIO_ANT_SWITCH) + else if(ant==3) { + if(!priv->pshare->rf_ft_var.antSw_enable) { + dm_SW_AntennaSwitchInit(priv); + RTL_W32(0x858, 0x569a569a); + priv->pshare->lastTxOkCnt = priv->net_stats.tx_bytes; + priv->pshare->lastRxOkCnt = priv->net_stats.rx_bytes; + } +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + RTL_W8(0xc50, RTL_R8(0xc50) & (~ BIT(7))); // rx OFDM SW control + } else +#endif + { + if ( !priv->pshare->rf_ft_var.antSw_select) + RTL_W8(0xc50, RTL_R8(0xc50) & (~ BIT(7))); // rx OFDM SW control + else + RTL_W8(0xc58, RTL_R8(0xc58) & (~ BIT(7))); // rx OFDM SW control + } + + RTL_W8(0xa01, RTL_R8(0xa01) & (~ BIT(7))); // rx CCK SW control + RTL_W32(0x80c, RTL_R32(0x80c) & (~ BIT(21))); // select ant by tx desc + priv->pshare->rf_ft_var.antHw_enable = 0; + priv->pshare->rf_ft_var.antSw_enable = 1; + + } +#endif + + return 1; +} + +#endif + +//3 ============================================================ +//3 Dynamic Noise Control +//3 ============================================================ + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) +void dnc_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + struct stat_info *pstat = NULL; + unsigned int set_timer = 0; + unsigned long flags; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (timer_pending(&priv->dnc_timer)) + del_timer_sync(&priv->dnc_timer); + +#ifdef PCIE_POWER_SAVING + if ((priv->pwr_state == L2) || (priv->pwr_state == L1)) + return; +#endif + + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0x00a00000); + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07600760); + PHY_SetBBReg(priv, 0xc50, bMaskByte0, 0x20); + PHY_SetBBReg(priv, 0xc58, bMaskByte0, 0x20); + } +} +#endif + + +//3 ============================================================ +//3 Leaving STA check +//3 ============================================================ +#if 0 +//#if defined(DETECT_STA_EXISTANCE) //&& (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT)) +// Check for STA existance. If STA disappears, disconnect it. Added by Annie, 2010-08-10. +void DetectSTAExistance(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat) +{ + unsigned char tmpbuf[16]; + + // Parameters + const unsigned int maxTxFailCnt = 300; // MAX Tx fail packet count + const unsigned int minTxFailCnt = 30; // MIN Tx fail packet count; this value should be less than maxTxFailCnt. + const unsigned int txFailSecThr= 3; // threshold of Tx Fail Time (in second) + + // Temporarily change Retry Limit when TxFail. (tfrl: TxFailRetryLimit) + const unsigned char TFRL = 7; // New Retry Limit value + const unsigned char TFRL_FailCnt = 2; // Tx Fail Count threshold to set Retry Limit + const unsigned char TFRL_SetTime = 2; // Time to set Retry Limit (in second) + const unsigned char TFRL_RcvTime = 10; // Time to recover Retry Limit (in second) + + if(OPMODE & WIFI_STATION_STATE) + return; + + if( report->txok != 0 ) + { // Reset Counter + pstat->tx_conti_fail_cnt = 0; + pstat->tx_last_good_time = priv->up_time; + pstat->leave = 0; + } + else if( report->txfail != 0 ) + { + pstat->tx_conti_fail_cnt += report->txfail; + DEBUG_WARN( "detect: txfail=%d, tx_conti_fail_cnt=%d\n", report->txfail, pstat->tx_conti_fail_cnt ); + + if( CHIP_VER_92X_SERIES(priv) && (priv->up_time >= (pstat->tx_last_good_time+TFRL_SetTime)) && + pstat->tx_conti_fail_cnt >= TFRL_FailCnt && + #if defined(CONFIG_RTL8672) || defined (NOT_RTK_BSP) + !pstat->ht_cap_len && // legacy rate only + #endif + !priv->pshare->bRLShortened ) + { // Shorten retry limit, because AP spending too much time to send out g mode STA pending packets in HW queue. + RTL_W16(RL, (TFRL&SRL_Mask)<pshare->bRLShortened = TRUE; + DEBUG_WARN( "== Shorten RetryLimit to 0x%04X ==\n", RTL_R16(RL) ); + } + + if( (pstat->tx_conti_fail_cnt >= maxTxFailCnt) || + (pstat->tx_conti_fail_cnt >= minTxFailCnt && priv->up_time >= (pstat->tx_last_good_time+txFailSecThr) ) + ) + { // This STA is considered as disappeared, so delete it. + DEBUG_WARN( "** tx_conti_fail_cnt=%d (min=%d,max=%d)\n", pstat->tx_conti_fail_cnt, minTxFailCnt, maxTxFailCnt); + DEBUG_WARN( "** tx_last_good_time=%d, up_time=%d (Thr:%d)\n", (int)pstat->tx_last_good_time, (int)priv->up_time, txFailSecThr ); + DEBUG_WARN( "AP is going to del_sta %02X:%02X:%02X:%02X:%02X:%02X\n", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5] ); + + sprintf((char *)tmpbuf, "%02x%02x%02x%02x%02x%02x", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); + +// del_sta(priv, tmpbuf); + ++(pstat->leave); + + if(CHIP_VER_92X_SERIES(priv) { + if (timer_pending(&priv->pshare->rl_recover_timer)) + del_timer_sync (&priv->pshare->rl_recover_timer); + mod_timer(&priv->pshare->rl_recover_timer, jiffies + EXPIRE_TO*TFRL_RcvTime); + } + + // Reset Counter + pstat->tx_conti_fail_cnt = 0; + pstat->tx_last_good_time = priv->up_time; + } + } +} + +// Timer callback function to recover hardware retry limit register. Added by Annie, 2010-08-10. +#ifdef __KERNEL__ +void RetryLimitRecovery(unsigned long task_priv) +#elif defined(__ECOS) +void RetryLimitRecovery(void *task_priv) +#endif +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + if( priv->pshare->bRLShortened ) + { + RTL_W16(RL, priv->pshare->RL_setting); + priv->pshare->bRLShortened = FALSE; + DEBUG_WARN( "== Recover RetryLimit to 0x%04X ==\n", RTL_R16(RL) ); + } +} + +// Chack STA leaving status; per interface. Added by Annie, 2010-08-10. +unsigned char NoLeavingSTA(struct rtl8192cd_priv *priv) +{ + unsigned char bStaAllOK = TRUE; + struct list_head *phead, *plist; + struct stat_info *pstat; + + phead = &priv->asoc_list; + if (!netif_running(priv->dev) || list_empty(phead)) + return bStaAllOK; + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + if( pstat->tx_conti_fail_cnt != 0 ) { + bStaAllOK = FALSE; + break; + } + plist = plist->next; + } + + return bStaAllOK; +} + +// Chack STA leaving status for all active interface and recover retry limit register value. Added by Annie, 2010-08-10. +void LeavingSTA_RLCheck(struct rtl8192cd_priv *priv) +{ + unsigned char bIfAllOK = TRUE; + static int AllOKTimes = 0; +#ifdef MBSSID + int i; +#endif + // Parameter + const unsigned char TFRL_RcvTime = 10; // Time to recover Retry Limit (in second) + + if( !NoLeavingSTA(priv) ) + bIfAllOK = FALSE; + +#ifdef UNIVERSAL_REPEATER + if (IS_ROOT_INTERFACE(priv) && GET_VXD_PRIV(priv) ) { + if( !NoLeavingSTA(GET_VXD_PRIV(priv)) ) + bIfAllOK = FALSE; + } +#endif + +#ifdef MBSSID + if (IS_ROOT_INTERFACE(priv)) { + if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) { + if( !NoLeavingSTA(priv->pvap_priv[i]) ) + bIfAllOK = FALSE; + } + } + } + } +#endif + + if( bIfAllOK ) { + AllOKTimes ++; + + if( AllOKTimes >= TFRL_RcvTime ) +#ifdef __KERNEL__ + RetryLimitRecovery((unsigned long)priv); +#elif defined(__ECOS) + RetryLimitRecovery((void *)priv); +#endif + } + else { + AllOKTimes = 0; + } +} +#endif + + + +#ifdef CONFIG_RTL_92C_SUPPORT + +/* + * PA Analog Pre-distortion Calibration R06 + */ +void APK_MAIN(struct rtl8192cd_priv *priv, unsigned int is2T) +{ + unsigned int regD[PATH_NUM]; + unsigned int tmpReg, index, offset, path, i=0, pathbound = PATH_NUM, apkbound=6; + unsigned int BB_backup[APK_BB_REG_NUM]; + unsigned int BB_REG[APK_BB_REG_NUM] = {0x904, 0xc04, 0x800, 0xc08, 0x874}; + unsigned int BB_AP_MODE[APK_BB_REG_NUM] = {0x00000020, 0x00a05430, 0x02040000, 0x000800e4, 0x00204000}; + unsigned int BB_normal_AP_MODE[APK_BB_REG_NUM] = {0x00000020, 0x00a05430, 0x02040000, 0x000800e4, 0x22204000}; + unsigned int AFE_backup[APK_AFE_REG_NUM]; + unsigned int AFE_REG[APK_AFE_REG_NUM] = { 0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec}; + unsigned int MAC_backup[IQK_MAC_REG_NUM]; + unsigned int MAC_REG[IQK_MAC_REG_NUM] = {0x522, 0x550, 0x551, 0x040}; + unsigned int APK_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = {{0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c}, + {0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e}}; + unsigned int APK_normal_RF_init_value[PATH_NUM][APK_BB_REG_NUM] = + { {0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c}, //path settings equal to path b settings + {0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c} }; + + unsigned int APK_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = + { {0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d}, + {0x5201a, 0x52019, 0x52016, 0x52033, 0x52050}}; + + unsigned int APK_normal_RF_value_0[PATH_NUM][APK_BB_REG_NUM] = + { {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}, //path settings equal to path b settings + {0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a} }; + + unsigned int AFE_on_off[PATH_NUM] = {0x04db25a4, 0x0b1b25a4}; //path A on path B off / path A off path B on + unsigned int APK_offset[PATH_NUM] = {0xb68, 0xb6c}; + unsigned int APK_normal_offset[PATH_NUM] = {0xb28, 0xb98}; + unsigned int APK_value[PATH_NUM] = {0x92fc0000, 0x12fc0000}; + unsigned int APK_normal_value[PATH_NUM] = {0x92680000, 0x12680000}; + char APK_delta_mapping[APK_BB_REG_NUM][13] = {{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6}, + {-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0}}; + unsigned int APK_normal_setting_value_1[13] = + { 0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28, + 0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3, + 0x12680000, 0x00880000, 0x00880000 }; + unsigned int APK_normal_setting_value_2[16] = + { 0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3, + 0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025, + 0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008, + 0x00050006 }; + + + unsigned int APK_normal_RF_init_value_old[PATH_NUM][APK_BB_REG_NUM] = + {{0x0852c, 0x5a52c, 0x0a52c, 0x5a52c, 0x4a52c}, //path settings equal to path b settings + {0x0852c, 0x5a52c, 0x0a52c, 0x5a52c, 0x4a52c}}; + unsigned int APK_normal_RF_value_0_old[PATH_NUM][APK_BB_REG_NUM] = + {{0x52019, 0x52017, 0x52010, 0x5200d, 0x5200a}, //path settings equal to path b settings + {0x52019, 0x52017, 0x52010, 0x5200d, 0x5200a}}; + unsigned int APK_normal_setting_value_1_old[13] = + {0x01017018, 0xf7ed8f84, 0x40372d20, 0x5b554e48, 0x6f6a6560, + 0x807c7873, 0x8f8b8884, 0x9d999693, 0xa9a6a3a0, 0xb5b2afac, + 0x12680000, 0x00880000, 0x00880000}; + unsigned int APK_normal_setting_value_2_old[16] = + {0x00810100, 0x00400056, 0x002b0032, 0x001f0024, 0x0019001c, + 0x00150017, 0x00120013, 0x00100011, 0x000e000f, 0x000c000d, + 0x000b000c, 0x000a000b, 0x0009000a, 0x00090009, 0x00080008, + 0x00080008}; + unsigned int AP_curve[PATH_NUM][APK_CURVE_REG_NUM]; + + unsigned int APK_result[PATH_NUM][APK_BB_REG_NUM]; //val_1_1a, val_1_2a, val_2a, val_3a, val_4a + unsigned int ThermalValue = 0; + int BB_offset, delta_V, delta_offset; + int newVerAPK = (IS_UMC_A_CUT_88C(priv)) ? 1 : 0; + unsigned int *pAPK_normal_setting_value_1 = APK_normal_setting_value_1, *pAPK_normal_setting_value_2 = APK_normal_setting_value_2 ; +#ifdef HIGH_POWER_EXT_PA + unsigned int tmp0x870=0, tmp0x860=0, tmp0x864=0; + + if(priv->pshare->rf_ft_var.use_ext_pa) + newVerAPK = 1; +#endif + + if(!newVerAPK) { + apkbound = 12; + pAPK_normal_setting_value_1 = APK_normal_setting_value_1_old; + pAPK_normal_setting_value_2 = APK_normal_setting_value_2_old; + } + + if(!is2T) + pathbound = 1; + + for(index = 0; index < PATH_NUM; index ++) { + APK_offset[index] = APK_normal_offset[index]; + APK_value[index] = APK_normal_value[index]; + AFE_on_off[index] = 0x6fdb25a4; + } + + for(index = 0; index < APK_BB_REG_NUM; index ++) { + for(path = 0; path < pathbound; path++) { + if(newVerAPK) { + APK_RF_init_value[path][index] = APK_normal_RF_init_value[path][index]; + APK_RF_value_0[path][index] = APK_normal_RF_value_0[path][index]; + } else { + APK_RF_init_value[path][index] = APK_normal_RF_init_value_old[path][index]; + APK_RF_value_0[path][index] = APK_normal_RF_value_0_old[path][index]; + } + + } + BB_AP_MODE[index] = BB_normal_AP_MODE[index]; + } + + /* + * save BB default value + */ + for(index = 1; index < APK_BB_REG_NUM ; index++) + BB_backup[index] = PHY_QueryBBReg(priv, BB_REG[index], bMaskDWord); + +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + tmp0x870 = PHY_QueryBBReg(priv, 0x870, bMaskDWord); + tmp0x860 = PHY_QueryBBReg(priv, 0x860, bMaskDWord); + tmp0x864 = PHY_QueryBBReg(priv, 0x864, bMaskDWord); + } +#endif + + //save MAC default value + _PHY_SaveMACRegisters(priv, MAC_REG, MAC_backup); + + //save AFE default value + _PHY_SaveADDARegisters(priv, AFE_REG, AFE_backup, APK_AFE_REG_NUM); + + for(path = 0; path < pathbound; path++) { + /* + * save old AP curve + */ + if(path == RF92CD_PATH_A) { + /* + * path A APK + * load APK setting + * path-A + */ + offset = 0xb00; + for(index = 0; index < 11; index ++) { + PHY_SetBBReg(priv, offset, bMaskDWord, pAPK_normal_setting_value_1[index]); + offset += 0x04; + } + PHY_SetBBReg(priv, 0xb98, bMaskDWord, 0x12680000); + + offset = 0xb68; + for(; index < 13; index ++) { + PHY_SetBBReg(priv, offset, bMaskDWord, pAPK_normal_setting_value_1[index]); + offset += 0x04; + } + + /* + * page-B1 + */ + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x400000); + + /* + *path A + */ + offset = 0xb00; + for(index = 0; index < 16; index++) { + PHY_SetBBReg(priv, offset, bMaskDWord, pAPK_normal_setting_value_2[index]); + offset += 0x04; + } + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + } else if(path == RF92CD_PATH_B) { + /* + * path B APK + * load APK setting + * path-B + */ + offset = 0xb70; + for(index = 0; index < 10; index ++) { + PHY_SetBBReg(priv, offset, bMaskDWord, pAPK_normal_setting_value_1[index]); + offset += 0x04; + } + PHY_SetBBReg(priv, 0xb28, bMaskDWord, 0x12680000); + PHY_SetBBReg(priv, 0xb98, bMaskDWord, 0x12680000); + + offset = 0xb68; + index = 11; + for(; index < 13; index ++) { + //offset 0xb68, 0xb6c + PHY_SetBBReg(priv, offset, bMaskDWord, pAPK_normal_setting_value_1[index]); + offset += 0x04; + } + + /* + * page-B1 + */ + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x400000); + + /* + * path B + */ + offset = 0xb60; + for(index = 0; index < 16; index++) { + PHY_SetBBReg(priv, offset, bMaskDWord, pAPK_normal_setting_value_2[index]); + offset += 0x04; + } + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + } + + if(!newVerAPK) { + tmpReg = PHY_QueryRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0x3, bMaskDWord, 1); + + AP_curve[path][0] = tmpReg & 0x1F; //[4:0] + + tmpReg = PHY_QueryRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0x4, bMaskDWord, 1); + AP_curve[path][1] = (tmpReg & 0xF8000) >> 15; //[19:15] + AP_curve[path][2] = (tmpReg & 0x7C00) >> 10; //[14:10] + AP_curve[path][3] = (tmpReg & 0x3E0) >> 5; //[9:5] + } + + /* + * save RF default value + */ + regD[path] = PHY_QueryRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0xd, bMaskDWord, 1); + + /* + * Path A AFE all on, path B AFE All off or vise versa + */ + for(index = 0; index < APK_AFE_REG_NUM ; index++) + PHY_SetBBReg(priv, AFE_REG[index], bMaskDWord, AFE_on_off[path]); + + /* + * BB to AP mode + */ + if(path == RF92CD_PATH_A) { + for(index = 1; index < APK_BB_REG_NUM ; index++) + PHY_SetBBReg(priv, BB_REG[index], bMaskDWord, BB_AP_MODE[index]); + } + +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + PHY_SetBBReg(priv, 0x870, BIT(10), 1); + PHY_SetBBReg(priv, 0x870, BIT(26), 1); + PHY_SetBBReg(priv, 0x860, BIT(10), 0); + PHY_SetBBReg(priv, 0x864, BIT(10), 0); + } +#endif + + if(newVerAPK) { + if(path == RF92CD_PATH_A) { + PHY_SetBBReg(priv, 0xe30 , bMaskDWord, 0x01008c00); + PHY_SetBBReg(priv, 0xe34 , bMaskDWord, 0x01008c00); + } else if(path == RF92CD_PATH_B) { + PHY_SetBBReg(priv, 0xe50 , bMaskDWord, 0x01008c00); + PHY_SetBBReg(priv, 0xe54 , bMaskDWord, 0x01008c00); + } + } + + //MAC settings + _PHY_MACSettingCalibration(priv, MAC_REG, MAC_backup); + + + if(path == RF92CD_PATH_A) { + //Path B to standby mode + PHY_SetRFReg(priv, RF92CD_PATH_B, 0x0, bMaskDWord, 0x10000); + } else { + //Path A to standby mode + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x00, bMaskDWord, 0x10000); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x10, bMaskDWord, 0x1000f); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x11, bMaskDWord, 0x20103); + } + + /* + * Check Thermal value delta + */ + if (priv->pmib->dot11RFEntry.ther) { + ThermalValue = PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x24, 0x1f, 1) & 0xff; + ThermalValue -= priv->pmib->dot11RFEntry.ther; + } + + delta_offset = ((ThermalValue+14)/2); + if(delta_offset < 0) + delta_offset = 0; + else if (delta_offset > 12) + delta_offset = 12; + + //AP calibration + for(index = 1; index < APK_BB_REG_NUM; index++) { + tmpReg = APK_RF_init_value[path][index]; + if (priv->pmib->dot11RFEntry.ther) { + BB_offset = (tmpReg & 0xF0000) >> 16; + + if(!(tmpReg & BIT(15))) //sign bit 0 + BB_offset = -BB_offset; + delta_V = APK_delta_mapping[index][delta_offset]; + BB_offset += delta_V; + + if(BB_offset < 0) { + tmpReg = tmpReg & (~BIT(15)); + BB_offset = -BB_offset; + } else { + tmpReg = tmpReg | BIT(15); + } + tmpReg = (tmpReg & 0xFFF0FFFF) | (BB_offset << 16); + } + + if(newVerAPK) + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0xc, bMaskDWord, 0x8992e); + else + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0xc, bMaskDWord, 0x8992f); + + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0x0, bMaskDWord, APK_RF_value_0[path][index]); + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0xd, bMaskDWord, tmpReg); + + /* + * PA11+PAD01111, one shot + */ + i = 0; + do { + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x800000); + PHY_SetBBReg(priv, APK_offset[path], bMaskDWord, APK_value[0]); + delay_ms(3); + PHY_SetBBReg(priv, APK_offset[path], bMaskDWord, APK_value[1]); + delay_ms(20); + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + + if(!newVerAPK) { + tmpReg = PHY_QueryRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0xb, bMaskDWord, 1); + tmpReg = (tmpReg & 0x3E00) >> 9; + } else { + if(path == RF92CD_PATH_A) + tmpReg = PHY_QueryBBReg(priv, 0xbd8, 0x03E00000); + else + tmpReg = PHY_QueryBBReg(priv, 0xbd8, 0xF8000000); + } + i++; + } while((tmpReg > apkbound) && i < 4); + + APK_result[path][index] = tmpReg; + } + } + + /* + * reload MAC default value + */ + _PHY_ReloadMACRegisters(priv, MAC_REG, MAC_backup); + + /* + * reload BB default value + */ + for(index = 1; index < APK_BB_REG_NUM ; index++) + PHY_SetBBReg(priv, BB_REG[index], bMaskDWord, BB_backup[index]); + +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + PHY_SetBBReg(priv, 0x870, bMaskDWord, tmp0x870); + PHY_SetBBReg(priv, 0x860, bMaskDWord, tmp0x860); + PHY_SetBBReg(priv, 0x864, bMaskDWord, tmp0x864); + } +#endif + + /* + * reload AFE default value + */ + _PHY_ReloadADDARegisters(priv, AFE_REG, AFE_backup, 16); + + + /* + * reload RF path default value + */ + for(path = 0; path < pathbound; path++) { + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0xd, bMaskDWord, regD[path]); + if(path == RF92CD_PATH_B) { + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x10, bMaskDWord, 0x1000f); + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x11, bMaskDWord, 0x20101); + } + + if(newVerAPK) { + if (APK_result[path][1] > 6) + APK_result[path][1] = 6; + } else { + if(APK_result[path][1] < 1) + APK_result[path][1] = 1; + else if (APK_result[path][1] > 5) + APK_result[path][1] = 5; + + if(APK_result[path][2] < 2) + APK_result[path][2] = 2; + else if (APK_result[path][2] > 6) + APK_result[path][2] = 6; + + if(APK_result[path][3] < 2) + APK_result[path][3] = 2; + else if (APK_result[path][3] > 6) + APK_result[path][3] = 6; + + if(APK_result[path][4] < 5) + APK_result[path][4] = 5; + else if (APK_result[path][4] > 9) + APK_result[path][4] = 9; + } + } + + for(path = 0; path < pathbound; path++) { + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0x3, bMaskDWord, + ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (APK_result[path][1] << 5) | APK_result[path][1])); + if(newVerAPK) { + if(path == RF92CD_PATH_A) + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0x4, bMaskDWord, + ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (0x00 << 5) | 0x05)); + else + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0x4, bMaskDWord, + ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (0x02 << 5) | 0x05)); + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0xe, bMaskDWord, + ((0x08 << 15) | (0x08 << 10) | (0x08 << 5) | 0x08)); + } else { + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0x4, bMaskDWord, + ((APK_result[path][1] << 15) | (APK_result[path][1] << 10) | (APK_result[path][2] << 5) | APK_result[path][3])); + PHY_SetRFReg(priv, (RF92CD_RADIO_PATH_E)path, 0xe, bMaskDWord, + ((APK_result[path][4] << 15) | (APK_result[path][4] << 10) | (APK_result[path][4] << 5) | APK_result[path][4])); + } + } +} + + + +/* +return FALSE => do IQK again +*/ +char _PHY_SimularityCompare(struct rtl8192cd_priv *priv, int result[][8], unsigned char c1, unsigned char c2) +{ + unsigned int i, j, diff, SimularityBitMap, bound = 0; + unsigned char final_candidate[2] = {0xFF, 0xFF}; //for path A and path B + char bResult = TRUE, is2T = (GET_CHIP_VER(priv) == VERSION_8192C ? 1 : 0); + + bound = (is2T) ? 8 : 4; + SimularityBitMap = 0; + + for( i = 0; i < bound; i++ ) { + diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - result[c2][i]) : (result[c2][i] - result[c1][i]); + if (diff > MAX_TOLERANCE) { + if((i == 2 || i == 6) && !SimularityBitMap) { + if( result[c1][i]+ result[c1][i+1] == 0) + final_candidate[(i>>2)] = c2; + else if (result[c2][i]+result[c2][i+1] == 0) + final_candidate[(i>>2)] = c1; + else + SimularityBitMap |= (1<>2); i++ ) { + if(final_candidate[i] != 0xFF) { + for( j = (i<<2); j < ((i+1)<<2)-2; j++) + result[3][j] = result[final_candidate[i]][j]; + bResult = FALSE; + } + } + return bResult; + } + else if (!(SimularityBitMap & 0x03)) { //path A TX OK + for(i = 0; i < 2; i++) + result[3][i] = result[c1][i]; + return FALSE; + } + else if (!(SimularityBitMap & 0x0c)) { //path A RX OK + for(i = 2; i < 4; i++) + result[3][i] = result[c1][i]; + return FALSE; + } + else if (!(SimularityBitMap & 0x30) && is2T) { //path B TX OK + for(i = 4; i < 6; i++) + result[3][i] = result[c1][i]; + return FALSE; + } + else if (!(SimularityBitMap & 0xc0) && is2T) { //path B RX OK + for(i = 6; i < 8; i++) + result[3][i] = result[c1][i]; + return FALSE; + } + else + return FALSE; + +} + + +//bit0 = 1 => Tx OK, bit1 = 1 => Rx OK +unsigned char _PHY_PathA_IQK(struct rtl8192cd_priv *priv, char configPathB) +{ + unsigned int regEAC, regE94, regE9C, regEA4; + unsigned char result = 0x00; + + + // RTPRINT(FINIT, INIT_IQK, ("Path-A IQK setting!\n")); +#if defined(HIGH_POWER_EXT_PA) && defined(CONFIG_RTL_92C_SUPPORT) + if (priv->pshare->rf_ft_var.use_ext_pa){ + + //path-A IQK setting + PHY_SetBBReg(priv, 0xe30, bMaskDWord, 0x18008c1f); + PHY_SetBBReg(priv, 0xe34, bMaskDWord, 0x18008c1f); + PHY_SetBBReg(priv, 0xe38, bMaskDWord, 0x82140102); + PHY_SetBBReg(priv, 0xe3c, bMaskDWord, 0x28160804); + + //path-B IQK setting + if(configPathB) { + PHY_SetBBReg(priv, 0xe50, bMaskDWord, 0x18008c22); + PHY_SetBBReg(priv, 0xe54, bMaskDWord, 0x18008c22); + PHY_SetBBReg(priv, 0xe58, bMaskDWord, 0x82140102); + PHY_SetBBReg(priv, 0xe5c, bMaskDWord, 0x28160804); + } +}else +#endif +{ + //path-A IQK setting + PHY_SetBBReg(priv, 0xe30, bMaskDWord, 0x10008c1f); + PHY_SetBBReg(priv, 0xe34, bMaskDWord, 0x10008c1f); + PHY_SetBBReg(priv, 0xe38, bMaskDWord, 0x82140102); + PHY_SetBBReg(priv, 0xe3c, bMaskDWord, ((configPathB |IS_UMC_B_CUT_88C(priv)) ? 0x28160202 : 0x28160502)); + + //path-B IQK setting + if(configPathB) { + PHY_SetBBReg(priv, 0xe50, bMaskDWord, 0x10008c22); + PHY_SetBBReg(priv, 0xe54, bMaskDWord, 0x10008c22); + PHY_SetBBReg(priv, 0xe58, bMaskDWord, 0x82140102); + PHY_SetBBReg(priv, 0xe5c, bMaskDWord, 0x28160202); + } +} + + + + //LO calibration setting + PHY_SetBBReg(priv, 0xe4c, bMaskDWord, 0x001028d1); + + //One shot, path A LOK & IQK + PHY_SetBBReg(priv, 0xe48, bMaskDWord, 0xf9000000); + PHY_SetBBReg(priv, 0xe48, bMaskDWord, 0xf8000000); + + // delay x ms + delay_ms(IQK_DELAY_TIME); + + // Check failed + regEAC = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + regE94 = PHY_QueryBBReg(priv, 0xe94, bMaskDWord); + regE9C= PHY_QueryBBReg(priv, 0xe9c, bMaskDWord); + regEA4= PHY_QueryBBReg(priv, 0xea4, bMaskDWord); + + if(!(regEAC & BIT(28)) && + (((regE94 & 0x03FF0000)>>16) != 0x142) && + (((regE9C & 0x03FF0000)>>16) != 0x42) ) + result |= 0x01; + else //if Tx not OK, ignore Rx + return result; + + if(!(regEAC & BIT(27)) && //if Tx is OK, check whether Rx is OK + (((regEA4 & 0x03FF0000)>>16) != 0x132) && + (((regEAC & 0x03FF0000)>>16) != 0x36)) + result |= 0x02; + else { +// RTPRINT(FINIT, INIT_IQK, ("Path A Rx IQK fail!!\n")); + } + + return result; +} + +//bit0 = 1 => Tx OK, bit1 = 1 => Rx OK +unsigned char _PHY_PathB_IQK(struct rtl8192cd_priv *priv) +{ + unsigned int regEAC, regEB4, regEBC, regEC4, regECC; + unsigned char result = 0x00; +#if 0 + //path-B IQK setting + RTPRINT(FINIT, INIT_IQK, ("Path-B IQK setting!\n")); + PHY_SetBBReg(pAdapter, 0xe50, bMaskDWord, 0x10008c22); + PHY_SetBBReg(pAdapter, 0xe54, bMaskDWord, 0x10008c22); + PHY_SetBBReg(pAdapter, 0xe58, bMaskDWord, 0x82140102); + PHY_SetBBReg(pAdapter, 0xe5c, bMaskDWord, 0x28160202); + + //LO calibration setting + RTPRINT(FINIT, INIT_IQK, ("LO calibration setting!\n")); + PHY_SetBBReg(pAdapter, 0xe4c, bMaskDWord, 0x001028d1); +#endif + //One shot, path B LOK & IQK +// RTPRINT(FINIT, INIT_IQK, ("One shot, path A LOK & IQK!\n")); + PHY_SetBBReg(priv, 0xe60, bMaskDWord, 0x00000002); + PHY_SetBBReg(priv, 0xe60, bMaskDWord, 0x00000000); + + // delay x ms + delay_ms(IQK_DELAY_TIME); + + // Check failed + regEAC = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + regEB4 = PHY_QueryBBReg(priv, 0xeb4, bMaskDWord); + regEBC= PHY_QueryBBReg(priv, 0xebc, bMaskDWord); + regEC4= PHY_QueryBBReg(priv, 0xec4, bMaskDWord); + regECC= PHY_QueryBBReg(priv, 0xecc, bMaskDWord); + + if(!(regEAC & BIT(31)) && + (((regEB4 & 0x03FF0000)>>16) != 0x142) && + (((regEBC & 0x03FF0000)>>16) != 0x42)) + result |= 0x01; + else + return result; + + if(!(regEAC & BIT(30)) && + (((regEC4 & 0x03FF0000)>>16) != 0x132) && + (((regECC & 0x03FF0000)>>16) != 0x36)) + result |= 0x02; + else { +// RTPRINT(FINIT, INIT_IQK, ("Path B Rx IQK fail!!\n")); + } + + return result; + +} + +void _PHY_PathAFillIQKMatrix(struct rtl8192cd_priv *priv, char bIQKOK, int result[][8], unsigned char final_candidate, char bTxOnly) +{ + int Oldval_0, X, TX0_A, reg; + int Y, TX0_C; + + if(final_candidate == 0xFF) + return; + + else if(bIQKOK) { + Oldval_0 = (PHY_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF; + + X = result[final_candidate][0]; + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + TX0_A = (X * Oldval_0) >> 8; + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(31), ((X* Oldval_0>>7) & 0x1)); + + Y = result[final_candidate][1]; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + TX0_C = (Y * Oldval_0) >> 8; + PHY_SetBBReg(priv, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6)); + PHY_SetBBReg(priv, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C&0x3F)); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(29), ((Y* Oldval_0>>7) & 0x1)); + + if(bTxOnly) { +// RTPRINT(FINIT, INIT_IQK, ("_PHY_PathAFillIQKMatrix only Tx OK\n")); + return; + } + + reg = result[final_candidate][2]; + PHY_SetBBReg(priv, rOFDM0_XARxIQImbalance, 0x3FF, reg); + + reg = result[final_candidate][3] & 0x3F; + PHY_SetBBReg(priv, rOFDM0_XARxIQImbalance, 0xFC00, reg); + + reg = (result[final_candidate][3] >> 6) & 0xF; + PHY_SetBBReg(priv, 0xca0, 0xF0000000, reg); + } +} + + +void _PHY_PathBFillIQKMatrix(struct rtl8192cd_priv *priv, char bIQKOK, int result[][8], unsigned char final_candidate, char bTxOnly) +{ + int Oldval_1, X, TX1_A, reg; + int Y, TX1_C; + + //RTPRINT(FINIT, INIT_IQK, ("Path B IQ Calibration %s !\n",(bIQKOK)?"Success":"Failed")); + + if(final_candidate == 0xFF) + return; + + else if(bIQKOK) + { + Oldval_1 = (PHY_QueryBBReg(priv, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF; + + X = result[final_candidate][4]; + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + TX1_A = (X * Oldval_1) >> 8; + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(27), ((X* Oldval_1>>7) & 0x1)); + + Y = result[final_candidate][5]; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + TX1_C = (Y * Oldval_1) >> 8; + PHY_SetBBReg(priv, rOFDM0_XDTxAFE, 0xF0000000, ((TX1_C&0x3C0)>>6)); + PHY_SetBBReg(priv, rOFDM0_XBTxIQImbalance, 0x003F0000, (TX1_C&0x3F)); + PHY_SetBBReg(priv, rOFDM0_ECCAThreshold, BIT(25), ((Y* Oldval_1>>7) & 0x1)); + + if(bTxOnly) + return; + + reg = result[final_candidate][6]; + PHY_SetBBReg(priv, rOFDM0_XBRxIQImbalance, 0x3FF, reg); + + reg = result[final_candidate][7] & 0x3F; + PHY_SetBBReg(priv, rOFDM0_XBRxIQImbalance, 0xFC00, reg); + + reg = (result[final_candidate][7] >> 6) & 0xF; + PHY_SetBBReg(priv, rOFDM0_AGCRSSITable, 0x0000F000, reg); + } +} + +void _PHY_PathAStandBy(struct rtl8192cd_priv *priv) +{ + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + PHY_SetBBReg(priv, 0x840, bMaskDWord, 0x00010000); + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); +} + +void _PHY_IQCalibrate(struct rtl8192cd_priv *priv, int result[][8], unsigned char t, char is2T) +{ + unsigned int i; + unsigned char PathAOK, PathBOK; + unsigned int ADDA_REG[IQK_ADDA_REG_NUM] = { 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec }; + unsigned int IQK_MAC_REG[IQK_MAC_REG_NUM] = {0x522, 0x550, 0x551, 0x040}; + + char isNormal = IS_TEST_CHIP(priv) ? 0 : 1; + unsigned int retryCount = 2; + +#ifdef MP_TEST + if(priv->pshare->rf_ft_var.mp_specific) + retryCount = 9; +#endif + + if(t==0) { + // Save ADDA parameters, turn Path A ADDA on + _PHY_SaveADDARegisters(priv, ADDA_REG, priv->pshare->ADDA_backup, APK_AFE_REG_NUM); + _PHY_SaveMACRegisters(priv, IQK_MAC_REG, priv->pshare->IQK_MAC_backup); + } + + _PHY_PathADDAOn(priv, ADDA_REG, TRUE, is2T); + + if(t==0) { + // Store 0xC04, 0xC08, 0x874 vale + priv->pshare->RegC04 = PHY_QueryBBReg(priv, 0xc04, bMaskDWord); + priv->pshare->RegC08 = PHY_QueryBBReg(priv, 0xc08, bMaskDWord); + priv->pshare->Reg874 = PHY_QueryBBReg(priv, 0x874, bMaskDWord); + } + + //MAC settings + _PHY_MACSettingCalibration(priv, IQK_MAC_REG, priv->pshare->IQK_MAC_backup); + + //PHY_SetBBReg(priv, 0x800, bMaskDWord, (PHY_QueryBBReg(priv, 0x800, bMaskDWord)& ~ BIT(24))); + PHY_SetBBReg(priv, 0xa04, bMaskDWord, (0x0f000000 | (PHY_QueryBBReg(priv, 0xa04, bMaskDWord))) ); + PHY_SetBBReg(priv, 0xc04, bMaskDWord, 0x03a05600); + PHY_SetBBReg(priv, 0xc08, bMaskDWord, 0x000800e4); + PHY_SetBBReg(priv, 0x874, bMaskDWord, 0x22204000); + + PHY_SetBBReg(priv, 0x870, BIT(10), 1); + PHY_SetBBReg(priv, 0x870, BIT(26), 1); + PHY_SetBBReg(priv, 0x860, BIT(10), 0); + PHY_SetBBReg(priv, 0x864, BIT(10), 0); + +#if defined(HIGH_POWER_EXT_PA) && defined(CONFIG_RTL_92C_SUPPORT) + //Allen TRSW to TX for external PA + PHY_SetBBReg(priv, 0x870, 0x60, 3); + PHY_SetBBReg(priv, 0x870, 0x600000, 3); + PHY_SetBBReg(priv, 0x860, 0x60, 1); + PHY_SetBBReg(priv, 0x864, 0x60, 1); +#endif + + if(is2T) { + PHY_SetBBReg(priv, 0x840, bMaskDWord, 0x00010000); + PHY_SetBBReg(priv, 0x844, bMaskDWord, 0x00010000); + } + + //Page B init + if(isNormal) + PHY_SetBBReg(priv, 0xb68, bMaskDWord, 0x00080000); + else + PHY_SetBBReg(priv, 0xb68, bMaskDWord, 0x0f600000); + + if(is2T) { + if(isNormal) + PHY_SetBBReg(priv, 0xb6c, bMaskDWord, 0x00080000); + else + PHY_SetBBReg(priv, 0xb6c, bMaskDWord, 0x0f600000); + } + + // IQ calibration setting + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); + PHY_SetBBReg(priv, 0xe40, bMaskDWord, 0x01007c00); + PHY_SetBBReg(priv, 0xe44, bMaskDWord, 0x01004800); + + for(i = 0 ; i < retryCount ; i++){ + PathAOK = _PHY_PathA_IQK(priv, is2T); + if(PathAOK == 0x03){ + result[t][0] = (PHY_QueryBBReg(priv, 0xe94, bMaskDWord)&0x3FF0000)>>16; + result[t][1] = (PHY_QueryBBReg(priv, 0xe9c, bMaskDWord)&0x3FF0000)>>16; + result[t][2] = (PHY_QueryBBReg(priv, 0xea4, bMaskDWord)&0x3FF0000)>>16; + result[t][3] = (PHY_QueryBBReg(priv, 0xeac, bMaskDWord)&0x3FF0000)>>16; + break; + } + else if (i == (retryCount-1) && PathAOK == 0x01) //Tx IQK OK + { + result[t][0] = (PHY_QueryBBReg(priv, 0xe94, bMaskDWord)&0x3FF0000)>>16; + result[t][1] = (PHY_QueryBBReg(priv, 0xe9c, bMaskDWord)&0x3FF0000)>>16; + } + } + + if(0x00 == PathAOK){ +// RTPRINT(FINIT, INIT_IQK, ("Path A IQK failed!!\n")); + } + + if(is2T){ + _PHY_PathAStandBy(priv); + + // Turn Path B ADDA on + _PHY_PathADDAOn(priv, ADDA_REG, FALSE, is2T); + + for(i = 0 ; i < retryCount ; i++){ + PathBOK = _PHY_PathB_IQK(priv); + if(PathBOK == 0x03){ +// RTPRINT(FINIT, INIT_IQK, ("Path B IQK Success!!\n")); + result[t][4] = (PHY_QueryBBReg(priv, 0xeb4, bMaskDWord)&0x3FF0000)>>16; + result[t][5] = (PHY_QueryBBReg(priv, 0xebc, bMaskDWord)&0x3FF0000)>>16; + result[t][6] = (PHY_QueryBBReg(priv, 0xec4, bMaskDWord)&0x3FF0000)>>16; + result[t][7] = (PHY_QueryBBReg(priv, 0xecc, bMaskDWord)&0x3FF0000)>>16; + break; + } + else if (i == (retryCount - 1) && PathBOK == 0x01) //Tx IQK OK + { +// RTPRINT(FINIT, INIT_IQK, ("Path B Only Tx IQK Success!!\n")); + result[t][4] = (PHY_QueryBBReg(priv, 0xeb4, bMaskDWord)&0x3FF0000)>>16; + result[t][5] = (PHY_QueryBBReg(priv, 0xebc, bMaskDWord)&0x3FF0000)>>16; + } + } + + if(0x00 == PathBOK){ +// RTPRINT(FINIT, INIT_IQK, ("Path B IQK failed!!\n")); + } + } + + //Back to BB mode, load original value +// RTPRINT(FINIT, INIT_IQK, ("IQK:Back to BB mode, load original value!\n")); + PHY_SetBBReg(priv, 0xc04, bMaskDWord, priv->pshare->RegC04); + PHY_SetBBReg(priv, 0x874, bMaskDWord, priv->pshare->Reg874); + PHY_SetBBReg(priv, 0xc08, bMaskDWord, priv->pshare->RegC08); + + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + + // Restore RX initial gain + PHY_SetBBReg(priv, 0x840, bMaskDWord, 0x00032ed3); + + if(is2T) + PHY_SetBBReg(priv, 0x844, bMaskDWord, 0x00032ed3); + + if(t!=0) { + // Reload ADDA power saving parameters + _PHY_ReloadADDARegisters(priv, ADDA_REG, priv->pshare->ADDA_backup, 16); + + // Reload MAC parameters + _PHY_ReloadMACRegisters(priv, IQK_MAC_REG, priv->pshare->IQK_MAC_backup); + } +} + + +void PHY_IQCalibrate_92C(struct rtl8192cd_priv *priv) +{ + int result[4][8]; //last is final result + unsigned char i, final_candidate; + char bPathAOK, bPathBOK; + int RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC, RegTmp = 0; + char is12simular, is13simular, is23simular; + unsigned int temp_870, temp_860, temp_864, temp_a04; + +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + { + if (priv->pshare->iqk_2g_done) + return; + priv->pshare->iqk_2g_done = 1; + } + + priv->pshare->IQK_total_cnt++; + + temp_870 = PHY_QueryBBReg(priv, 0x870, bMaskDWord); + temp_860 = PHY_QueryBBReg(priv, 0x860, bMaskDWord); + temp_864 = PHY_QueryBBReg(priv, 0x864, bMaskDWord); + //temp_800 = PHY_QueryBBReg(priv, 0x800, bMaskDWord); + temp_a04 = PHY_QueryBBReg(priv, 0xa04, bMaskDWord); + + memset(result, 0, sizeof(result)); + + final_candidate = 0xff; + bPathAOK = FALSE; + bPathBOK = FALSE; + is12simular = FALSE; + is23simular = FALSE; + is13simular = FALSE; + + for (i=0; i<3; i++) { + _PHY_IQCalibrate(priv, result, i, (GET_CHIP_VER(priv) == VERSION_8192C ? 1 : 0)); + + if(i == 1) { + is12simular = _PHY_SimularityCompare(priv, result, 0, 1); + if(is12simular) { + final_candidate = 0; + break; + } + } + + if(i == 2) { + is13simular = _PHY_SimularityCompare(priv, result, 0, 2); + if(is13simular) { + final_candidate = 0; + break; + } + + is23simular = _PHY_SimularityCompare(priv, result, 1, 2); + if(is23simular) + final_candidate = 1; + else + { + for(i = 0; i < 8; i++) + RegTmp += result[3][i]; + + if(RegTmp != 0) + final_candidate = 3; + else + final_candidate = 0xFF; + } + } + } + + + RTL_W32(0x870, temp_870); + RTL_W32(0x860, temp_860); + RTL_W32(0x864, temp_864); + //RTL_W32(0x800, temp_800); + RTL_W32(0xa04, temp_a04); + + //load 0xe30 IQC default value + if(GET_CHIP_VER(priv) == VERSION_8188C) { + RTL_W32(0xe30, 0x01008c00); + RTL_W32(0xe34, 0x01008c00); + } + + for (i=0; i<4; i++) { + RegE94 = result[i][0]; + RegE9C = result[i][1]; + RegEA4 = result[i][2]; + RegEAC = result[i][3]; + RegEB4 = result[i][4]; + RegEBC = result[i][5]; + RegEC4 = result[i][6]; + RegECC = result[i][7]; + DEBUG_INFO("IQK: RegE94=%x RegE9C=%x RegEA4=%x RegEAC=%x RegEB4=%x RegEBC=%x RegEC4=%x RegECC=%x\n ", RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC); + } + + if(final_candidate != 0xff) { + priv->pshare->RegE94 = RegE94 = result[final_candidate][0]; + priv->pshare->RegE9C = RegE9C = result[final_candidate][1]; + RegEA4 = result[final_candidate][2]; + RegEAC = result[final_candidate][3]; + priv->pshare->RegEB4 = RegEB4 = result[final_candidate][4]; + priv->pshare->RegEBC = RegEBC = result[final_candidate][5]; + RegEC4 = result[final_candidate][6]; + RegECC = result[final_candidate][7]; + DEBUG_INFO ("IQK: final_candidate is %x\n",final_candidate); + DEBUG_INFO ("IQK: RegE94=%x RegE9C=%x RegEA4=%x RegEAC=%x RegEB4=%x RegEBC=%x RegEC4=%x RegECC=%x\n ", RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC); + bPathAOK = bPathBOK = TRUE; + } + else { + priv->pshare->RegE94 = priv->pshare->RegEB4 = 0x100; //X default value + priv->pshare->RegE9C = priv->pshare->RegEBC = 0x0; //Y default value + priv->pshare->IQK_fail_cnt++; + } + + if((RegE94 != 0)/*&&(RegEA4 != 0)*/) + _PHY_PathAFillIQKMatrix(priv, bPathAOK, result, final_candidate, (RegEA4 == 0)? 1 :0); + if(GET_CHIP_VER(priv) == VERSION_8192C){ + if((RegEB4 != 0)/*&&(RegEC4 != 0)*/) + _PHY_PathBFillIQKMatrix(priv, bPathBOK, result, final_candidate, (RegEC4 == 0)? 1 :0); + } +} + +#endif + + +// 92d IQK +#ifdef CONFIG_RTL_92D_SUPPORT +void IQK_92D_5G_n(struct rtl8192cd_priv *priv) +{ + unsigned int temp_a04, temp_c04, temp_874, temp_c08, temp_870, + temp_860, temp_864, temp_88c, temp_c50, temp_c58, temp_b30, + switch2PI=0, X, reg; //Oldval_0, Oldval_1, TX0_A, TX1_A; + u8 temp_522, temp_550, temp_551; + unsigned int cal_num=0, cal_retry=0, ADDA_backup[IQK_ADDA_REG_NUM]; + int Y, result[8][3], result_final[8]={0,0,0,0,0,0,0,0}; //TX0_C, TX1_C; + + unsigned int i, RX0REG0xe40[3], RX0REG0xe40_final=0, REG0xe40, REG0xe94, REG0xe9c, delay_count; + unsigned int REG0xeac, RX1REG0xe40[3], RX1REG0xe40_final=0, REG0xeb4, REG0xea4,REG0xec4; + unsigned char TX0IQKOK = FALSE, TX1IQKOK = FALSE; + unsigned int TX_X0, TX_Y0, TX_X1, TX_Y1, RX_X0, RX_Y0, RX_X1, RX_Y1; + unsigned int ADDA_REG[IQK_ADDA_REG_NUM] = {0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec}; +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + return IQK_92D_5G_phy0_n(priv); +#endif + + //always do IQK for MP mode +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + { + if (priv->pmib->dot11RFEntry.macPhyMode == SINGLEMAC_SINGLEPHY) { + if (priv->pshare->iqk_5g_done) + return; + priv->pshare->iqk_5g_done = 1; + } + } + + printk(">> %s \n",__FUNCTION__); + + watchdog_kick(); + + /* + * Save MAC default value + */ + temp_522 = RTL_R8(0x522); + temp_550 = RTL_R8(0x550); + temp_551 = RTL_R8(0x551); + + /* + * Save BB Parameter + */ + temp_a04 = RTL_R32(0xa04);//RTL_R32(0x800); + temp_c04 = RTL_R32(0xc04); + temp_874 = RTL_R32(0x874); + temp_c08 = RTL_R32(0xc08); + temp_870 = RTL_R32(0x870); + temp_860 = RTL_R32(0x860); + temp_864 = RTL_R32(0x864); + temp_88c = RTL_R32(0x88c); + temp_c50 = RTL_R32(0xc50); // 01/11/2011 update + temp_c58 = RTL_R32(0xc58); // 01/11/2011 update + temp_b30 = RTL_R32(0xb30); // 03/03/2011 update + + /* + * Save AFE Parameters + */ + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + ADDA_backup[i] = RTL_R32(ADDA_REG[i]); + + /* + * ============== + * Path-A TX/RX IQK + * ============== + */ + while (cal_num < 3) { + /* + * Path-A AFE all on + */ + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + RTL_W32(ADDA_REG[i], 0x04db25a4); + + /* + * MAC register setting + */ + RTL_W8(0x522, 0x3f); + RTL_W8(0x550, RTL_R8(0x550)& (~BIT(3))); + RTL_W8(0x551, RTL_R8(0x551)& (~BIT(3))); + + /* + * IQK must be done in PI mode + */ + if (!PHY_QueryBBReg(priv, 0x820, BIT(8)) || !PHY_QueryBBReg(priv, 0x828, BIT(8))) { + PHY_SetBBReg(priv, 0x820, bMaskDWord, 0x01000100); + PHY_SetBBReg(priv, 0x828, bMaskDWord, 0x01000100); + switch2PI++; + } + + /* + * BB setting + */ + //PHY_SetBBReg(priv, 0x800, BIT(24), 0); + PHY_SetBBReg(priv, 0xa04, bMaskDWord, (0x0f000000 | temp_a04) ); + PHY_SetBBReg(priv, 0xc04, bMaskDWord, 0x03a05600); + PHY_SetBBReg(priv, 0xc08, bMaskDWord, 0x000800e4); + PHY_SetBBReg(priv, 0x874, bMaskDWord, 0x22208000); + PHY_SetBBReg(priv, 0x88c, BIT(23)|BIT(22)|BIT(21)|BIT(20), 0xf); + PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0x00a00000); // 03/03/2011 update + + /* + * AP or IQK + */ + //PHY_SetBBReg(priv, 0xb68, bMaskDWord, 0x0f600000); + //PHY_SetBBReg(priv, 0xb6c, bMaskDWord, 0x0f600000); + + // IQK-R03 2011/02/16 update + + //path A AP setting for IQK + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0); + PHY_SetBBReg(priv, 0xb68, bMaskDWord, 0x20000000); + //path B AP setting for IQK + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0); + PHY_SetBBReg(priv, 0xb6c, bMaskDWord, 0x20000000); + + /* + * IQK global setting + */ + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); + PHY_SetBBReg(priv, 0xe40, bMaskDWord, 0x10007c00); + PHY_SetBBReg(priv, 0xe44, bMaskDWord, 0x01004800); + + /* + * path-A IQK setting + */ + PHY_SetBBReg(priv, 0xe30, bMaskDWord, 0x18008c1f); + PHY_SetBBReg(priv, 0xe34, bMaskDWord, 0x18008c1f); + PHY_SetBBReg(priv, 0xe38, bMaskDWord, 0x82140307); // 01/11/2011 update +#ifdef USB_POWER_SUPPORT + PHY_SetBBReg(priv, 0xe3c, bMaskDWord, 0x68160c66); +#else + PHY_SetBBReg(priv, 0xe3c, bMaskDWord, 0x68160960); // 01/11/2011 update +#endif + + /* + * path-B IQK setting + */ + PHY_SetBBReg(priv, 0xe50, bMaskDWord, 0x18008c2f); + PHY_SetBBReg(priv, 0xe54, bMaskDWord, 0x18008c2f); + PHY_SetBBReg(priv, 0xe58, bMaskDWord, 0x82110000); + PHY_SetBBReg(priv, 0xe5c, bMaskDWord, 0x68110000); + + /* + * LO calibration setting + */ + PHY_SetBBReg(priv, 0xe4c, bMaskDWord, 0x00462911); + +#ifdef USB_POWER_SUPPORT + // path-A TRSW setting + PHY_SetBBReg(priv, 0x870, BIT(6)|BIT(5), 3); + PHY_SetBBReg(priv, 0x860, BIT(6)|BIT(5), 3); +#else + /* + * path-A PA on + */ + /* + PHY_SetBBReg(priv, 0x870, BIT(11)|BIT(10), 3); + PHY_SetBBReg(priv, 0x870, BIT(6)|BIT(5), 3); + PHY_SetBBReg(priv, 0x860, BIT(11)|BIT(10), 3); + */ + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000f60); // 01/11/2011 update + PHY_SetBBReg(priv, 0x860, bMaskDWord, 0x66e60e30); // 01/11/2011 update +#endif + /* + * One shot, path A LOK & IQK + */ + PHY_SetBBReg(priv, 0xe48, bMaskDWord, 0xf9000000); + PHY_SetBBReg(priv, 0xe48, bMaskDWord, 0xf8000000); + + /* + * Delay 10 ms + */ + delay_ms(10); + + delay_count = 0; + while (1){ + REG0xeac = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + if ((REG0xeac&BIT(26))||(delay_count>20)){ + break; + }else { + delay_ms(1); + delay_count++; + } + } + /* + * Check_TX_IQK_A_result + */ + REG0xe40 = PHY_QueryBBReg(priv, 0xe40, bMaskDWord); + REG0xe94 = PHY_QueryBBReg(priv, 0xe94, bMaskDWord); + if(((REG0xeac&BIT(28)) == 0) && (((REG0xe94&0x3FF0000)>>16)!=0x142)) { + TX0IQKOK = TRUE; + REG0xe9c = PHY_QueryBBReg(priv, 0xe9c, bMaskDWord); + TX_X0 = (PHY_QueryBBReg(priv, 0xe94, bMaskDWord)&0x3FF0000)>>16; + TX_Y0 = (PHY_QueryBBReg(priv, 0xe9c, bMaskDWord)&0x3FF0000)>>16; + RX0REG0xe40[cal_num] = (REG0xe40 & 0xfc00fc00) | (TX_X0<<16) | TX_Y0; + DEBUG_INFO("TX_X0 %08x TX_Y0 %08x RX0REG0xe40 %08x\n", TX_X0, TX_Y0, RX0REG0xe40[cal_num]); + result[0][cal_num] = TX_X0; + result[1][cal_num] = TX_Y0; + } else { + TX0IQKOK = FALSE; + if (++cal_retry >= 10) { + printk("%s Path-A Tx/Rx Check\n",__FUNCTION__); + break; + } + } + + /* + * Check_RX_IQK_A_result + */ + if(TX0IQKOK == TRUE) { + REG0xeac = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + REG0xea4 = PHY_QueryBBReg(priv, 0xea4, bMaskDWord); + if(((REG0xeac&BIT(27)) == 0) && (((REG0xea4&0x3FF0000)>>16)!=0x132)) { + RX_X0 = (PHY_QueryBBReg(priv, 0xea4, bMaskDWord)&0x3FF0000)>>16; + RX_Y0 = (PHY_QueryBBReg(priv, 0xeac, bMaskDWord)&0x3FF0000)>>16; + DEBUG_INFO("RX_X0 %08x RX_Y0 %08x\n", RX_X0, RX_Y0); + result[2][cal_num] = RX_X0; + result[3][cal_num] = RX_Y0; + cal_num++; + } else { + PHY_SetBBReg(priv, 0xc14, bMaskDWord, 0x40000100); + PHY_SetBBReg(priv, 0xe34, bMaskDWord, 0x19008c00); + if (++cal_retry >= 10) { + printk("%s Path-A Tx/Rx Check\n",__FUNCTION__); + break; + } + } + } + } + + if (cal_num == 3) { + result_final[0] = get_mean_of_2_close_value(result[0]); + result_final[1] = get_mean_of_2_close_value(result[1]); + result_final[2] = get_mean_of_2_close_value(result[2]); + result_final[3] = get_mean_of_2_close_value(result[3]); + RX0REG0xe40_final = 0x80000000 | get_mean_of_2_close_value(RX0REG0xe40); + + priv->pshare->RegE94=result_final[0]; + priv->pshare->RegE9C=result_final[1]; + } else { + priv->pshare->RegE94=0x100; + priv->pshare->RegE9C=0x00; + } + + /* + * Path-A PA off + */ + PHY_SetBBReg(priv, 0x870, bMaskDWord, temp_870); + PHY_SetBBReg(priv, 0x860, bMaskDWord, temp_860); + + + /* + * ============== + * Path-B TX/RX IQK + * ============== + */ + cal_num = cal_retry = 0; + while (cal_num < 3) { + /* + * Path-B AFE all on + */ + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + PHY_SetBBReg(priv, ADDA_REG[i], bMaskDWord, 0x0b1b25a4); + + /* + * path-A IQK setting + */ + PHY_SetBBReg(priv, 0xe30, bMaskDWord, 0x18008c1f); + PHY_SetBBReg(priv, 0xe34, bMaskDWord, 0x18008c1f); + PHY_SetBBReg(priv, 0xe38, bMaskDWord, 0x82110000); + PHY_SetBBReg(priv, 0xe3c, bMaskDWord, 0x68110000); + + /* + * path-B IQK setting + */ + PHY_SetBBReg(priv, 0xe50, bMaskDWord, 0x18008c22); + PHY_SetBBReg(priv, 0xe54, bMaskDWord, 0x18008c22); + PHY_SetBBReg(priv, 0xe58, bMaskDWord, 0x82140307); // 01/11/2011 update + + // 01/11/2011 update +#ifdef USB_POWER_SUPPORT + PHY_SetBBReg(priv, 0xe5c, bMaskDWord, 0x68160c66); +#else + PHY_SetBBReg(priv, 0xe5c, bMaskDWord, 0x68160960); // 01/11/2011 update +#endif + + /* + * LO calibration setting + */ + PHY_SetBBReg(priv, 0xe4c, bMaskDWord, 0x00462911); + +#ifdef USB_POWER_SUPPORT + PHY_SetBBReg(priv, 0x870, BIT(22)|BIT(21), 3); + PHY_SetBBReg(priv, 0x864, BIT(6)|BIT(5), 3); +#else + /* + * path-B PA on + */ + /* + PHY_SetBBReg(priv, 0x870, BIT(27)|BIT(26), 3); + PHY_SetBBReg(priv, 0x870, BIT(22)|BIT(21), 3); + PHY_SetBBReg(priv, 0x864, BIT(11)|BIT(10), 3); + */ + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x0f600700); + PHY_SetBBReg(priv, 0x864, bMaskDWord, 0x061f0d30); +#endif + + /* + * One shot, path A LOK & IQK + */ + PHY_SetBBReg(priv, 0xe60, bMaskDWord, 0x00000002); + PHY_SetBBReg(priv, 0xe60, bMaskDWord, 0x00000000); + + /* + * Delay 10 ms + */ + delay_ms(10); + + delay_count = 0; + while (1){ + REG0xeac = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + if ((REG0xeac&BIT(29))||(delay_count>20)){ + break; + }else { + delay_ms(1); + delay_count++; + } + } + /* + * Check_TX_IQK_B_result + */ + REG0xe40 = PHY_QueryBBReg(priv, 0xe40, bMaskDWord); + REG0xeac = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + REG0xeb4 = PHY_QueryBBReg(priv, 0xeb4, bMaskDWord); + if(((REG0xeac&BIT(31)) == 0) && ((REG0xeb4&0x3FF0000)!=0x142)) { + TX1IQKOK = TRUE; + TX_X1 = (PHY_QueryBBReg(priv, 0xeb4, bMaskDWord)&0x3FF0000)>>16; + TX_Y1 = (PHY_QueryBBReg(priv, 0xebc, bMaskDWord)&0x3FF0000)>>16; + RX1REG0xe40[cal_num] = (REG0xe40 & 0xfc00fc00) | (TX_X1<<16) | TX_Y1; + DEBUG_INFO("TX_X1 %08x TX_Y1 %08x RX1REG0xe40 %08x\n", TX_X1, TX_Y1, RX1REG0xe40[cal_num]); + result[4][cal_num] = TX_X1; + result[5][cal_num] = TX_Y1; + } else { + TX1IQKOK = FALSE; + if (++cal_retry >= 10) { + printk("%s Path-B Tx/Rx Check\n",__FUNCTION__); + break; + } + } + + /* + * Check_RX_IQK_B_result + */ + if(TX1IQKOK == TRUE) { + REG0xeac = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + REG0xec4 = PHY_QueryBBReg(priv, 0xec4, bMaskDWord); + if(((REG0xeac&BIT(30)) == 0) && (((REG0xec4&0x3FF0000)>>16)!=0x132)) { + RX_X1 = (PHY_QueryBBReg(priv, 0xec4, bMaskDWord)&0x3FF0000)>>16; + RX_Y1 = (PHY_QueryBBReg(priv, 0xecc, bMaskDWord)&0x3FF0000)>>16; + DEBUG_INFO("RX_X1 %08x RX_Y1 %08x\n", RX_X1, RX_Y1); + result[6][cal_num] = RX_X1; + result[7][cal_num] = RX_Y1; + cal_num++; + } else { + PHY_SetBBReg(priv, 0xc1c, bMaskDWord, 0x40000100); + PHY_SetBBReg(priv, 0xe54, bMaskDWord, 0x19008c00); + if (++cal_retry >= 10) { + printk("%s Path-B Tx/Rx Check\n",__FUNCTION__); + break; + } + } + } + } + + if (cal_num == 3) { + result_final[4] = get_mean_of_2_close_value(result[4]); + result_final[5] = get_mean_of_2_close_value(result[5]); + result_final[6] = get_mean_of_2_close_value(result[6]); + result_final[7] = get_mean_of_2_close_value(result[7]); + RX1REG0xe40_final = 0x80000000 | get_mean_of_2_close_value(RX1REG0xe40); + + priv->pshare->RegEB4=result_final[4]; + priv->pshare->RegEBC=result_final[5]; + } else { + priv->pshare->RegEB4=0x100; + priv->pshare->RegEBC=0x00; + } + + /* + * Fill IQK result for Path A + */ + if (result_final[0]) { + /* + Oldval_0 = (PHY_QueryBBReg(priv, 0xc80, bMaskDWord) >> 22) & 0x3FF; + X = result_final[0]; + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + TX0_A = (X * Oldval_0) >> 8; + PHY_SetBBReg(priv, 0xc80, 0x3FF, TX0_A); + PHY_SetBBReg(priv, 0xc4c, BIT(24), ((X* Oldval_0>>7) & 0x1)); + + Y = result_final[1]; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + TX0_C = (Y * Oldval_0) >> 8; + PHY_SetBBReg(priv, 0xc94, 0xF0000000, ((TX0_C&0x3C0)>>6)); + PHY_SetBBReg(priv, 0xc80, 0x003F0000, (TX0_C&0x3F)); + PHY_SetBBReg(priv, 0xc4c, BIT(26), ((Y* Oldval_0>>7) & 0x1)); + */ + + // IQK-R03 2011/02/16 update + X = result_final[0]; + Y = result_final[1]; + //printk("X=%x Y=%x\n",X,Y); + //Path-A OFDM_A + PHY_SetBBReg(priv, 0xe30, 0x03FF0000, X); + PHY_SetBBReg(priv, 0xc4c, BIT(24), 0); + //Path-A OFDM_C + PHY_SetBBReg(priv, 0xe30, 0x000003FF, Y); + PHY_SetBBReg(priv, 0xc4c, BIT(26), 0); + + if(result_final[2]) { + reg = result_final[2]; + PHY_SetBBReg(priv, 0xc14, 0x3FF, reg); + reg = result_final[3] & 0x3F; + PHY_SetBBReg(priv, 0xc14, 0xFC00, reg); + + reg = (result_final[3] >> 6) & 0xF; + PHY_SetBBReg(priv, 0xca0, 0xF0000000, reg); + + PHY_SetBBReg(priv, 0xe34, 0x03FF0000, result_final[2]); // X + PHY_SetBBReg(priv, 0xe34, 0x3FF, result_final[3]); //Y + } + } + + /* + * Fill IQK result for Path B + */ + if (result_final[4]) { + /* + Oldval_1 = (PHY_QueryBBReg(priv, 0xc88, bMaskDWord) >> 22) & 0x3FF; + + X = result_final[4]; + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + TX1_A = (X * Oldval_1) >> 8; + PHY_SetBBReg(priv, 0xc88, 0x3FF, TX1_A); + PHY_SetBBReg(priv, 0xc4c, BIT(28), ((X* Oldval_1>>7) & 0x1)); + + Y = result_final[5]; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + TX1_C = (Y * Oldval_1) >> 8; + PHY_SetBBReg(priv, 0xc9c, 0xF0000000, ((TX1_C&0x3C0)>>6)); + PHY_SetBBReg(priv, 0xc88, 0x003F0000, (TX1_C&0x3F)); + PHY_SetBBReg(priv, 0xc4c, BIT(30), ((Y* Oldval_1>>7) & 0x1)); + */ + + // IQK-R03 2011/02/16 update + X = result_final[4]; + Y = result_final[5]; + //printk("X=%x Y=%x\n",X,Y); + //Path-A OFDM_A + PHY_SetBBReg(priv, 0xe50, 0x03FF0000, X); + PHY_SetBBReg(priv, 0xc4c, BIT(28), 0); + //Path-A OFDM_C + PHY_SetBBReg(priv, 0xe50, 0x000003FF, Y); + PHY_SetBBReg(priv, 0xc4c, BIT(30), 0); + + if(result_final[6]) { + reg = result_final[6]; + PHY_SetBBReg(priv, 0xc1c, 0x3FF, reg); + + reg = result_final[7] & 0x3F; + PHY_SetBBReg(priv, 0xc1c, 0xFC00, reg); + + reg = (result_final[7] >> 6) & 0xF; + PHY_SetBBReg(priv, 0xc78, 0x0000F000, reg); + + PHY_SetBBReg(priv, 0xe54, 0x03FF0000, result_final[6]); // X + PHY_SetBBReg(priv, 0xe54, 0x3FF, result_final[7]); //Y + } + } + + /* + * Path B PA off + */ + PHY_SetBBReg(priv, 0x870, bMaskDWord, temp_870); + PHY_SetBBReg(priv, 0x864, bMaskDWord, temp_864); + + /* + * Exit IQK mode + */ + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + PHY_SetBBReg(priv, 0xc04, bMaskDWord, temp_c04); + PHY_SetBBReg(priv, 0xc08, bMaskDWord, temp_c08); + PHY_SetBBReg(priv, 0x874, bMaskDWord, temp_874); + //PHY_SetBBReg(priv, 0x800, bMaskDWord, temp_800); + PHY_SetBBReg(priv, 0xa04, bMaskDWord, temp_a04); + PHY_SetBBReg(priv, 0x88c, bMaskDWord, temp_88c); + PHY_SetBBReg(priv, 0xb30, bMaskDWord, temp_b30); // 03/03/2011 update + //PHY_SetBBReg(priv, 0x840, bMaskDWord, 0x00032fff); // 01/11/2011 update + //PHY_SetBBReg(priv, 0x844, bMaskDWord, 0x00032fff); // 01/11/2011 update + + // IQK-R03 2011/02/16 update + //path A IQ path to DP block + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x010170b8); + //path B IQ path to DP block + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x010170b8); + + //path AB to initial gain + PHY_SetBBReg(priv, 0xc50, bMaskDWord, 0x50); // 01/11/2011 update + PHY_SetBBReg(priv, 0xc50, bMaskDWord, temp_c50); // 01/11/2011 update + PHY_SetBBReg(priv, 0xc58, bMaskDWord, 0x50); // 01/11/2011 update + PHY_SetBBReg(priv, 0xc58, bMaskDWord, temp_c58); // 01/11/2011 update + + + /* + * Reload MAC default value + */ + RTL_W8(0x550, temp_550); + RTL_W8(0x551, temp_551); + RTL_W8(0x522, temp_522); + + /* + * Switch back to SI if needed, after IQK + */ + if (switch2PI) { + PHY_SetBBReg(priv, 0x820, bMaskDWord, 0x01000000); + PHY_SetBBReg(priv, 0x828, bMaskDWord, 0x01000000); + } + + /* + * Reload ADDA power saving parameters + */ + for(i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + PHY_SetBBReg(priv, ADDA_REG[i], bMaskDWord, ADDA_backup[i]); + + +#if 0 //def CLIENT_MODE + clnt_save_IQK_res(priv); +#endif + + if (!TX0IQKOK && !TX1IQKOK) + priv->pshare->IQK_fail_cnt++; +} + + +void IQK_92D_2G(struct rtl8192cd_priv *priv) +{ + unsigned int cal_num=0, cal_retry=0, Oldval=0, temp_c04=0, temp_c08=0, temp_874=0, temp_eac; + unsigned int cal_e94, cal_e9c, cal_ea4, cal_eac, cal_eb4, cal_ebc, cal_ec4, cal_ecc; + unsigned int X, Y, val_e94[3], val_e9c[3], val_ea4[3], val_eac[3], val_eb4[3], val_ebc[3], val_ec4[3], val_ecc[3]; + unsigned int ADDA_REG[IQK_ADDA_REG_NUM] = {0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec}; + unsigned int ADDA_backup[IQK_ADDA_REG_NUM], i; + u8 temp_522, temp_550, temp_551; + u32 temp_040, temp_a04, temp_870, temp_860, temp_864, temp_88c; + u8 switch2PI = 0; + unsigned char IQKOK = 0; + +#ifdef CONFIG_RTL_92D_DMDP + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + return IQK_92D_2G_phy1(priv); +#endif + + //always do IQK for MP mode +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + { + if (priv->pmib->dot11RFEntry.macPhyMode == SINGLEMAC_SINGLEPHY) { + if (priv->pshare->iqk_2g_done) + return; + priv->pshare->iqk_2g_done = 1; + } + } + + printk(">> %s \n",__FUNCTION__); + + // Save ADDA power saving parameters + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + ADDA_backup[i] = RTL_R32(ADDA_REG[i]); + + /* + * Save MAC default value + */ + temp_522 = RTL_R8(0x522); + temp_550 = RTL_R8(0x550); + temp_551 = RTL_R8(0x551); + temp_040 = RTL_R32(0x40); + + // Save BB default + temp_a04 = RTL_R32(0xa04);//RTL_R32(0x800); + temp_870 = RTL_R32(0x870); + temp_860 = RTL_R32(0x860); + temp_864 = RTL_R32(0x864); + temp_88c = RTL_R32(0x88c); + + // Path-A ADDA all on + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + RTL_W32(ADDA_REG[i], 0x04db25a4); + + // IQ&LO calibration Setting + //IQK must be done in PI mode + if (!PHY_QueryBBReg(priv, 0x820, BIT(8)) || !PHY_QueryBBReg(priv, 0x828, BIT(8))) { + PHY_SetBBReg(priv, 0x820, bMaskDWord, 0x01000100); + PHY_SetBBReg(priv, 0x828, bMaskDWord, 0x01000100); + switch2PI++; + } + + //MAC register setting + RTL_W8(0x522, 0x3f); + RTL_W8(0x550, RTL_R8(0x550)& (~BIT(3))); + RTL_W8(0x551, RTL_R8(0x551)& (~BIT(3))); + RTL_W32(0x40, 0); + + //BB setting + temp_c04 = RTL_R32(0xc04); + temp_c08 = RTL_R32(0xc08); + temp_874 = RTL_R32(0x874); + //PHY_SetBBReg(priv,0x800,BIT(24),0); + PHY_SetBBReg(priv, 0xa04, bMaskDWord, (0x0f000000 | temp_a04) ); + RTL_W32(0xc04, 0x03a05600); + RTL_W32(0xc08, 0x000800e4); + RTL_W32(0x874, 0x22204000); + + PHY_SetBBReg(priv, 0x870, BIT(10), 1); + PHY_SetBBReg(priv, 0x870, BIT(26), 1); + PHY_SetBBReg(priv, 0x860, BIT(10), 0); + PHY_SetBBReg(priv, 0x864, BIT(10), 0); + + PHY_SetBBReg(priv,0x88c,0x00f00000,0xf); + RTL_W32(0x840, 0x00010000); + RTL_W32(0x844, 0x00010000); + + //AP or IQK + RTL_W32(0xb68 , 0x0f600000); + RTL_W32(0xb6c , 0x0f600000); + + // IQK setting + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); + RTL_W32(0xe40, 0x01007c00); + RTL_W32(0xe44, 0x01004800); + // path-A IQK setting + RTL_W32(0xe30, 0x10008c1f); + RTL_W32(0xe34, 0x10008c1f); + RTL_W32(0xe38, 0x82140102); + RTL_W32(0xe3c, 0x28160206); + // path-B IQK setting + RTL_W32(0xe50, 0x10008c22); + RTL_W32(0xe54, 0x10008c22); + RTL_W32(0xe58, 0x82140102); + RTL_W32(0xe5c, 0x28160206); + // LO calibration setting + RTL_W32(0xe4c, 0x00462911); + + // delay to ensure Path-A IQK success + delay_ms(10); + + // step 4: One shot, path A LOK & IQK + while (cal_num < 3) { + // One shot, path A LOK & IQK + RTL_W32(0xe48, 0xf9000000); + RTL_W32(0xe48, 0xf8000000); + // delay 1ms + delay_ms(1); + + // check fail bit and check abnormal condition, then fill BB IQ matrix + cal_e94 = (RTL_R32(0xe94) >> 16) & 0x3ff; + cal_e9c = (RTL_R32(0xe9c) >> 16) & 0x3ff; + cal_ea4 = (RTL_R32(0xea4) >> 16) & 0x3ff; + temp_eac = RTL_R32(0xeac); + cal_eac = (temp_eac >> 16) & 0x3ff; + if (!(temp_eac & BIT(28)) && !(temp_eac & BIT(27)) && + (cal_e94 != 0x142) && (cal_e9c != 0x42) && + (cal_ea4 != 0x132) && (cal_eac != 0x36)) { + val_e94[cal_num] = cal_e94; + val_e9c[cal_num] = cal_e9c; + val_ea4[cal_num] = cal_ea4; + val_eac[cal_num] = cal_eac; + cal_num++; + } else { + if (++cal_retry >= 10) { + printk("%s Path-A Check\n",__FUNCTION__); + break; + } + } + } + + if (cal_num == 3) { + cal_e94 = get_mean_of_2_close_value(val_e94); + cal_e9c = get_mean_of_2_close_value(val_e9c); + cal_ea4 = get_mean_of_2_close_value(val_ea4); + cal_eac = get_mean_of_2_close_value(val_eac); + + priv->pshare->RegE94=cal_e94; + priv->pshare->RegE9C=cal_e9c; + + Oldval = (RTL_R32(0xc80) >> 22) & 0x3ff; + + X = cal_e94; + PHY_SetBBReg(priv, 0xc80, 0x3ff, (X * Oldval)>>8); + PHY_SetBBReg(priv, 0xc4c, BIT(24), ((X * Oldval) >> 7) & 0x1); + + Y = cal_e9c; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + PHY_SetBBReg(priv, 0xc94, 0xf0000000, (((Y * Oldval) >> 8) >> 6) & 0xf); + PHY_SetBBReg(priv, 0xc80, 0x003f0000, ((Y * Oldval) >> 8) & 0x3f); + PHY_SetBBReg(priv, 0xc4c, BIT(26), ((Y * Oldval) >> 7) & 0x1); + + PHY_SetBBReg(priv, 0xc14, 0x3ff, cal_ea4); + + PHY_SetBBReg(priv, 0xc14, 0xfc00, cal_eac & 0x3f); + + PHY_SetBBReg(priv, 0xca0, 0xf0000000, (cal_eac >> 6) & 0xf); + }else { + IQKOK++; + priv->pshare->RegE94=0x100; + priv->pshare->RegE9C=0x00; + } + + // step 5: Path-A standby mode + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + RTL_W32(0x840, 0x00010000); + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); + + // step 6: Path-B ADDA all on + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + RTL_W32(ADDA_REG[i], 0x0b1b25a4); + + // step 7: One shot, path B LOK & IQK + cal_num = 0; + cal_retry = 0; + while (cal_num < 3) { + // One shot, path B LOK & IQK + RTL_W32(0xe60, 2); + RTL_W32(0xe60, 0); + // delay 1ms + delay_ms(1); + + // check fail bit and check abnormal condition, then fill BB IQ matrix + cal_eb4 = (RTL_R32(0xeb4) >> 16) & 0x3ff; + cal_ebc = (RTL_R32(0xebc) >> 16) & 0x3ff; + cal_ec4 = (RTL_R32(0xec4) >> 16) & 0x3ff; + cal_ecc = (RTL_R32(0xecc) >> 16) & 0x3ff; + temp_eac = RTL_R32(0xeac); + if (!(temp_eac & BIT(31)) && !(temp_eac & BIT(30)) && + (cal_eb4 != 0x142) && (cal_ebc != 0x42) && + (cal_ec4 != 0x132) && (cal_ecc != 0x36)) { + val_eb4[cal_num] = cal_eb4; + val_ebc[cal_num] = cal_ebc; + val_ec4[cal_num] = cal_ec4; + val_ecc[cal_num] = cal_ecc; + cal_num++; + } else { + if (++cal_retry >= 10) { + printk("%s Path-B Check\n",__FUNCTION__); + break; + } + } + } + + if (cal_num == 3) { + cal_eb4 = get_mean_of_2_close_value(val_eb4); + cal_ebc = get_mean_of_2_close_value(val_ebc); + cal_ec4 = get_mean_of_2_close_value(val_ec4); + cal_ecc = get_mean_of_2_close_value(val_ecc); + + priv->pshare->RegEB4=cal_eb4; + priv->pshare->RegEBC=cal_ebc; + + Oldval = (RTL_R32(0xc88) >> 22) & 0x3ff; + + X = cal_eb4; + PHY_SetBBReg(priv, 0xc88, 0x3ff, (X * Oldval) >> 8 ); + PHY_SetBBReg(priv, 0xc4c, BIT(28), ((X * Oldval) >> 7) & 0x1); + + Y = cal_ebc; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + PHY_SetBBReg(priv, 0xc9c, 0xf0000000, (((Y * Oldval) >> 8 ) >> 6) & 0xf); + PHY_SetBBReg(priv, 0xc88, 0x003f0000, ((Y * Oldval) >> 8 ) & 0x3f); + PHY_SetBBReg(priv, 0xc4c, BIT(30), ((Y * Oldval) >> 7) & 0x1); + + PHY_SetBBReg(priv, 0xc1c, 0x3ff, cal_ec4); + + PHY_SetBBReg(priv, 0xc1c, 0xfc00, cal_ecc & 0x3f); + + PHY_SetBBReg(priv, 0xc78, 0xf000, (cal_ecc >> 6) & 0xf); + }else { + IQKOK++; + priv->pshare->RegEB4=0x100; + priv->pshare->RegEBC=0x00; + } + + // step 8: back to BB mode, load original values + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + RTL_W32(0xc04, temp_c04); + RTL_W32(0xc08, temp_c08); + RTL_W32(0x874, temp_874); + //RTL_W32(0x800, temp_800); + RTL_W32(0xa04, temp_a04); + RTL_W32(0x88c, temp_88c); + RTL_W32(0x840, 0x32fff); + RTL_W32(0x844, 0x32fff); + RTL_W32(0x870, temp_870); + RTL_W32(0x860, temp_860); + RTL_W32(0x864, temp_864); + + /* + * Switch back to SI if needed, after IQK + */ + if (switch2PI) { + PHY_SetBBReg(priv, 0x820, bMaskDWord, 0x01000000); + PHY_SetBBReg(priv, 0x828, bMaskDWord, 0x01000000); + } + + watchdog_kick(); + + /* + * Reload ADDA power saving parameters + */ + for(i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + PHY_SetBBReg(priv, ADDA_REG[i], bMaskDWord, ADDA_backup[i]); + + /* + * Reload MAC default value + */ + RTL_W8(0x550, temp_550); + RTL_W8(0x551, temp_551); + RTL_W32(0x40, temp_040); + RTL_W8(0x522, temp_522); + + +#if 0 //def CLIENT_MODE + clnt_save_IQK_res(priv); +#endif + if (!IQKOK) + priv->pshare->IQK_fail_cnt++; +} +#ifdef CONFIG_RTL_92D_DMDP + +void IQK_92D_2G_phy1(struct rtl8192cd_priv *priv) +{ + unsigned int cal_num=0, cal_retry=0, Oldval=0, temp_c04=0, temp_c08=0, temp_874=0, temp_eac; + unsigned int cal_e94, cal_e9c, cal_ea4, cal_eac; + unsigned int X, Y, val_e94[3], val_e9c[3], val_ea4[3], val_eac[3]; + unsigned int ADDA_REG[IQK_ADDA_REG_NUM] = {0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec}; + unsigned int ADDA_backup[IQK_ADDA_REG_NUM], i; + u8 temp_522, temp_550, temp_551; + u32 temp_040, temp_870, temp_860, temp_864, temp_a04, temp_88c; + u8 switch2PI = 0; + unsigned char IQKOK = 0; + +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + { + if (priv->pshare->iqk_2g_done) + return; + priv->pshare->iqk_2g_done = 1; + } + + printk(">> %s \n",__FUNCTION__); + + // Save ADDA power saving parameters + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + ADDA_backup[i] = RTL_R32(ADDA_REG[i]); + + /* + * Save MAC default value + */ + temp_522 = RTL_R8(0x522); + temp_550 = RTL_R8(0x550); + temp_551 = RTL_R8(0x551); + temp_040 = RTL_R32(0x40); + + // Save BB default + temp_a04 = RTL_R32(0xa04);//RTL_R32(0x800); + temp_870 = RTL_R32(0x870); + temp_860 = RTL_R32(0x860); + temp_864 = RTL_R32(0x864); + temp_88c = RTL_R32(0x88c); + + // Path-A ADDA all on + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) { +#ifdef NON_INTR_ANTDIV + if (DMDP_PHY_QueryBBReg(0, 0xb30,BIT(27))) + RTL_W32(ADDA_REG[i], 0x04db25a4); + else +#endif + RTL_W32(ADDA_REG[i], 0x0b1b25a4); + } + + + // IQ&LO calibration Setting + + /* + * IQK must be done in PI mode + */ + if (!PHY_QueryBBReg(priv, 0x820, BIT(8)) || !PHY_QueryBBReg(priv, 0x828, BIT(8))) { + PHY_SetBBReg(priv, 0x820, bMaskDWord, 0x01000100); + PHY_SetBBReg(priv, 0x828, bMaskDWord, 0x01000100); + switch2PI++; + } + + //MAC register setting + RTL_W8(0x522, 0x3f); + RTL_W8(0x550, RTL_R8(0x550)& (~BIT(3))); + RTL_W8(0x551, RTL_R8(0x551)& (~BIT(3))); + RTL_W32(0x40, 0); + + //BB setting + temp_c04 = RTL_R32(0xc04); + temp_c08 = RTL_R32(0xc08); + temp_874 = RTL_R32(0x874); + //PHY_SetBBReg(priv, 0x800, BIT(24), 0); + PHY_SetBBReg(priv, 0xa04, bMaskDWord, (0x0f000000 | temp_a04) ); + RTL_W32(0xc04, 0x03a05600); + RTL_W32(0xc08, 0x000800e4); + RTL_W32(0x874, 0x22204000); + + PHY_SetBBReg(priv, 0x870, BIT(10), 1); + PHY_SetBBReg(priv, 0x870, BIT(26), 1); + PHY_SetBBReg(priv, 0x860, BIT(10), 0); + PHY_SetBBReg(priv, 0x864, BIT(10), 0); + + PHY_SetBBReg(priv,0x88c,0x00f00000,0xf); + + RTL_W32(0x840, 0x00010000); + + //AP or IQK + RTL_W32(0xb68 , 0x0f600000); + RTL_W32(0xb6c , 0x0f600000); + + // IQK setting + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); + RTL_W32(0xe40, 0x01007c00); + RTL_W32(0xe44, 0x01004800); + + // path-A IQK setting + RTL_W32(0xe30, 0x10008c22); + RTL_W32(0xe34, 0x10008c22); + RTL_W32(0xe38, 0x82140102); + RTL_W32(0xe3c, 0x28160206); + + // LO calibration setting + RTL_W32(0xe4c, 0x00462911); + + // delay to ensure Path-A IQK success + delay_ms(10); + + // step 4: One shot, path A LOK & IQK + while (cal_num < 3) { + // One shot, path A LOK & IQK + RTL_W32(0xe48, 0xf9000000); + RTL_W32(0xe48, 0xf8000000); + // delay 1ms + delay_ms(1); + + // check fail bit and check abnormal condition, then fill BB IQ matrix + cal_e94 = (RTL_R32(0xe94) >> 16) & 0x3ff; + cal_e9c = (RTL_R32(0xe9c) >> 16) & 0x3ff; + cal_ea4 = (RTL_R32(0xea4) >> 16) & 0x3ff; + temp_eac = RTL_R32(0xeac); + cal_eac = (temp_eac >> 16) & 0x3ff; + if (!(temp_eac & BIT(28)) && !(temp_eac & BIT(27)) && + (cal_e94 != 0x142) && (cal_e9c != 0x42) && + (cal_ea4 != 0x132) && (cal_eac != 0x36)) { + val_e94[cal_num] = cal_e94; + val_e9c[cal_num] = cal_e9c; + val_ea4[cal_num] = cal_ea4; + val_eac[cal_num] = cal_eac; + cal_num++; + } else { + if (++cal_retry >= 10) { + printk("%s Path-A Check\n",__FUNCTION__); + break; + } + } + } + + if (cal_num == 3) { + cal_e94 = get_mean_of_2_close_value(val_e94); + cal_e9c = get_mean_of_2_close_value(val_e9c); + cal_ea4 = get_mean_of_2_close_value(val_ea4); + cal_eac = get_mean_of_2_close_value(val_eac); + + priv->pshare->RegE94=cal_e94; + priv->pshare->RegE9C=cal_e9c; + + Oldval = (RTL_R32(0xc80) >> 22) & 0x3ff; + + X = cal_e94; + PHY_SetBBReg(priv, 0xc80, 0x3ff, (X * Oldval) >> 8); + PHY_SetBBReg(priv, 0xc4c, BIT(24), ((X * Oldval) >> 7) & 0x1); + + Y = cal_e9c; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + PHY_SetBBReg(priv, 0xc94, 0xf0000000, (((Y * Oldval) >> 8) >> 6) & 0xf); + PHY_SetBBReg(priv, 0xc80, 0x003f0000, ((Y * Oldval) >> 8) & 0x3f); + PHY_SetBBReg(priv, 0xc4c, BIT(26), ((Y * Oldval) >> 7) & 0x1); + + PHY_SetBBReg(priv, 0xc14, 0x3ff, cal_ea4); + + PHY_SetBBReg(priv, 0xc14, 0xfc00, cal_eac & 0x3f); + + PHY_SetBBReg(priv, 0xca0, 0xf0000000, (cal_eac >> 6) & 0xf); + }else { + IQKOK++; + priv->pshare->RegE94=0x100; + priv->pshare->RegE9C=0x00; + } + + // back to BB mode, load original values + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + RTL_W32(0xc04, temp_c04); + RTL_W32(0xc08, temp_c08); + RTL_W32(0x874, temp_874); + //RTL_W32(0x800, temp_800); + RTL_W32(0xa04, temp_a04); + + RTL_W32(0x88c, temp_88c); + RTL_W32(0x840, 0x32fff); + RTL_W32(0x870, temp_870); + RTL_W32(0x860, temp_860); + RTL_W32(0x864, temp_864); + + // return to SI mode + if (switch2PI) { + RTL_W32(0x820, 0x01000000); + RTL_W32(0x828, 0x01000000); + } + + watchdog_kick(); + + /* + * Reload ADDA power saving parameters + */ + for(i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + PHY_SetBBReg(priv, ADDA_REG[i], bMaskDWord, ADDA_backup[i]); + + /* + * Reload MAC default value + */ + RTL_W8(0x550, temp_550); + RTL_W8(0x551, temp_551); + RTL_W32(0x40, temp_040); + RTL_W8(0x522, temp_522); + + if (!IQKOK) + priv->pshare->IQK_fail_cnt++; +} + + +void IQK_92D_5G_phy0_n(struct rtl8192cd_priv *priv) +{ + unsigned int temp_a04, temp_c04, temp_874, temp_c08, temp_870, temp_860, temp_88c, temp_c50, temp_b30, + switch2PI=0, X, reg; //, Oldval_0, TX0_A; + u8 temp_522, temp_550, temp_551; + unsigned int cal_num=0, cal_retry=0, ADDA_backup[IQK_ADDA_REG_NUM]; + int Y, result[8][3], result_final[8]={0,0,0,0,0,0,0,0}; //, TX0_C; + + unsigned int i, RX0REG0xe40[3], RX0REG0xe40_final=0, REG0xe40, REG0xe94, REG0xe9c, delay_count; + unsigned int REG0xeac, REG0xea4; + unsigned char TX0IQKOK = FALSE; + unsigned int TX_X0, TX_Y0, RX_X0, RX_Y0; + unsigned int ADDA_REG[IQK_ADDA_REG_NUM] = {0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec}; + +#ifdef MP_TEST + if (!priv->pshare->rf_ft_var.mp_specific) +#endif + { + if (priv->pshare->iqk_5g_done) + return; + priv->pshare->iqk_5g_done = 1; + } + + printk(">> %s \n",__FUNCTION__); + + watchdog_kick(); + + /* + * Save MAC default value + */ + temp_522 = RTL_R8(0x522); + temp_550 = RTL_R8(0x550); + temp_551 = RTL_R8(0x551); + + /* + * Save BB Parameter + */ + temp_a04 = RTL_R32(0xa04);//RTL_R32(0x800); + temp_c04 = RTL_R32(0xc04); + temp_874 = RTL_R32(0x874); + temp_c08 = RTL_R32(0xc08); + temp_870 = RTL_R32(0x870); + temp_860 = RTL_R32(0x860); + temp_88c = RTL_R32(0x88c); + temp_c50 = RTL_R32(0xc50); + temp_b30 = RTL_R32(0xb30); // 03/03/2011 update + + /* + * Save AFE Parameters + */ + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + ADDA_backup[i] = RTL_R32(ADDA_REG[i]); + + /* + * ============== + * Path-A TX/RX IQK + * ============== + */ + while (cal_num < 3) { + /* + * Path-A AFE all on + */ + for( i = 0 ; i < IQK_ADDA_REG_NUM ; i++) { +#ifdef NON_INTR_ANTDIV + if (DMDP_PHY_QueryBBReg(0, 0xb30,BIT(27))) + RTL_W32(ADDA_REG[i], 0x0b1b25a4); + else +#endif + RTL_W32(ADDA_REG[i], 0x04db25a4); + } + + /* + * MAC register setting + */ + RTL_W8(0x522, 0x3f); + RTL_W8(0x550, RTL_R8(0x550)& (~BIT(3))); + RTL_W8(0x551, RTL_R8(0x551)& (~BIT(3))); + + /* + * IQK must be done in PI mode + */ + if (!PHY_QueryBBReg(priv, 0x820, BIT(8)) || !PHY_QueryBBReg(priv, 0x828, BIT(8))) { + PHY_SetBBReg(priv, 0x820, bMaskDWord, 0x01000100); + PHY_SetBBReg(priv, 0x828, bMaskDWord, 0x01000100); + switch2PI++; + } + + /* + * BB setting + */ + //PHY_SetBBReg(priv, 0x800, BIT(24), 0); + PHY_SetBBReg(priv, 0xa04, bMaskDWord, (0x0f000000 | temp_a04) ); + PHY_SetBBReg(priv, 0xc04, bMaskDWord, 0x03a05600); + PHY_SetBBReg(priv, 0xc08, bMaskDWord, 0x000800e4); + PHY_SetBBReg(priv, 0x874, bMaskDWord, 0x22208000); + PHY_SetBBReg(priv, 0x88c, BIT(23)|BIT(22)|BIT(21)|BIT(20), 0xf); + PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0x00a00000); // 03/03/2011 update + + /* + * AP or IQK + */ + //PHY_SetBBReg(priv, 0xb68, bMaskDWord, 0x0f600000); + //PHY_SetBBReg(priv, 0xb6c, bMaskDWord, 0x0f600000); + + // IQK-R03 2011/02/16 update + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0); + PHY_SetBBReg(priv, 0xb68, bMaskDWord, 0x20000000); + + /* + * IQK global setting + */ + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x808000); + PHY_SetBBReg(priv, 0xe40, bMaskDWord, 0x10007c00); + PHY_SetBBReg(priv, 0xe44, bMaskDWord, 0x01004800); + + /* + * path-A IQK setting + */ + PHY_SetBBReg(priv, 0xe30, bMaskDWord, 0x18008c1f); + PHY_SetBBReg(priv, 0xe34, bMaskDWord, 0x18008c1f); + PHY_SetBBReg(priv, 0xe38, bMaskDWord, 0x82140307); // 01/11/2011 update + +#ifdef USB_POWER_SUPPORT + PHY_SetBBReg(priv, 0xe3c, bMaskDWord, 0x68160c66); +#else + PHY_SetBBReg(priv, 0xe3c, bMaskDWord, 0x68160960); // 01/11/2011 update +#endif + /* + * LO calibration setting + */ + PHY_SetBBReg(priv, 0xe4c, bMaskDWord, 0x00462911); + +#ifdef USB_POWER_SUPPORT + // PHY0 TRSW seting + PHY_SetBBReg(priv, 0x870, BIT(6)|BIT(5), 3); + PHY_SetBBReg(priv, 0x860, BIT(6)|BIT(5), 3); +#else + /* + * path-A PA on + */ + /* + PHY_SetBBReg(priv, 0x870, BIT(11)|BIT(10), 3); + PHY_SetBBReg(priv, 0x870, BIT(6)|BIT(5), 3); + PHY_SetBBReg(priv, 0x860, BIT(11)|BIT(10), 3); + */ + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000f60); // 01/11/2011 update + PHY_SetBBReg(priv, 0x860, bMaskDWord, 0x66e60e30); // 01/11/2011 update +#endif + /* + * One shot, path A LOK & IQK + */ + PHY_SetBBReg(priv, 0xe48, bMaskDWord, 0xf9000000); + PHY_SetBBReg(priv, 0xe48, bMaskDWord, 0xf8000000); + + /* + * Delay 10 ms + */ + delay_ms(10); + + delay_count = 0; + while (1){ + REG0xeac = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + if ((REG0xeac&BIT(26))||(delay_count>20)){ + break; + }else { + delay_ms(1); + delay_count++; + } + } + + /* + * Check_TX_IQK_A_result + */ + REG0xe40 = PHY_QueryBBReg(priv, 0xe40, bMaskDWord); + REG0xeac = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + REG0xe94 = PHY_QueryBBReg(priv, 0xe94, bMaskDWord); + if(((REG0xeac&BIT(28)) == 0) && (((REG0xe94&0x3FF0000)>>16)!=0x142)) { + TX0IQKOK = TRUE; + REG0xe9c = PHY_QueryBBReg(priv, 0xe9c, bMaskDWord); + TX_X0 = (PHY_QueryBBReg(priv, 0xe94, bMaskDWord)&0x3FF0000)>>16; + TX_Y0 = (PHY_QueryBBReg(priv, 0xe9c, bMaskDWord)&0x3FF0000)>>16; + RX0REG0xe40[cal_num] = (REG0xe40 & 0xfc00fc00) | (TX_X0<<16) | TX_Y0; + DEBUG_INFO("TX_X0 %08x TX_Y0 %08x RX0REG0xe40 %08x\n", TX_X0, TX_Y0, RX0REG0xe40[cal_num]); + result[0][cal_num] = TX_X0; + result[1][cal_num] = TX_Y0; + } else { + TX0IQKOK = FALSE; + if (++cal_retry >= 10) { + printk("%s Path-A Tx/Rx Check\n",__FUNCTION__); + break; + } + } + + /* + * Check_RX_IQK_A_result + */ + if(TX0IQKOK == TRUE) { + REG0xeac = PHY_QueryBBReg(priv, 0xeac, bMaskDWord); + REG0xea4 = PHY_QueryBBReg(priv, 0xea4, bMaskDWord); + if(((REG0xeac&BIT(27)) == 0) && (((REG0xea4&0x3FF0000)>>16)!=0x132)) { + RX_X0 = (PHY_QueryBBReg(priv, 0xea4, bMaskDWord)&0x3FF0000)>>16; + RX_Y0 = (PHY_QueryBBReg(priv, 0xeac, bMaskDWord)&0x3FF0000)>>16; + DEBUG_INFO("RX_X0 %08x RX_Y0 %08x\n", RX_X0, RX_Y0); + result[2][cal_num] = RX_X0; + result[3][cal_num] = RX_Y0; + cal_num++; + } else { + PHY_SetBBReg(priv, 0xc14, bMaskDWord, 0x40000100); + PHY_SetBBReg(priv, 0xe34, bMaskDWord, 0x19008c00); + if (++cal_retry >= 10) { + printk("%s Path-A Tx/Rx Check\n",__FUNCTION__); + break; + } + } + } + } + + if (cal_num == 3) { + result_final[0] = get_mean_of_2_close_value(result[0]); + result_final[1] = get_mean_of_2_close_value(result[1]); + result_final[2] = get_mean_of_2_close_value(result[2]); + result_final[3] = get_mean_of_2_close_value(result[3]); + RX0REG0xe40_final = 0x80000000 | get_mean_of_2_close_value(RX0REG0xe40); + + priv->pshare->RegE94=result_final[0]; + priv->pshare->RegE9C=result_final[1]; + } else { + priv->pshare->RegE94=0x100; + priv->pshare->RegE9C=0x00; + } + + /* + * Fill IQK result for Path A + */ + if (result_final[0]) { + /* + Oldval_0 = (PHY_QueryBBReg(priv, 0xc80, bMaskDWord) >> 22) & 0x3FF; + X = result_final[0]; + if ((X & 0x00000200) != 0) + X = X | 0xFFFFFC00; + TX0_A = (X * Oldval_0) >> 8; + PHY_SetBBReg(priv, 0xc80, 0x3FF, TX0_A); + PHY_SetBBReg(priv, 0xc4c, BIT(24), ((X* Oldval_0>>7) & 0x1)); + + Y = result_final[1]; + if ((Y & 0x00000200) != 0) + Y = Y | 0xFFFFFC00; + TX0_C = (Y * Oldval_0) >> 8; + PHY_SetBBReg(priv, 0xc94, 0xF0000000, ((TX0_C&0x3C0)>>6)); + PHY_SetBBReg(priv, 0xc80, 0x003F0000, (TX0_C&0x3F)); + PHY_SetBBReg(priv, 0xc4c, BIT(26), ((Y* Oldval_0>>7) & 0x1)); + */ + + // IQK-R03 2011/02/16 update + X = result_final[0]; + Y = result_final[1]; + //printk("X=%x Y=%x\n",X,Y); + //Path-A OFDM_A + PHY_SetBBReg(priv, 0xe30, 0x03FF0000, X); + PHY_SetBBReg(priv, 0xc4c, BIT(24), 0); + //Path-A OFDM_C + PHY_SetBBReg(priv, 0xe30, 0x000003FF, Y); + PHY_SetBBReg(priv, 0xc4c, BIT(26), 0); + + + if(result_final[2]) { + reg = result_final[2]; + PHY_SetBBReg(priv, 0xc14, 0x3FF, reg); + + reg = result_final[3] & 0x3F; + PHY_SetBBReg(priv, 0xc14, 0xFC00, reg); + + reg = (result_final[3] >> 6) & 0xF; + PHY_SetBBReg(priv, 0xca0, 0xF0000000, reg); + + PHY_SetBBReg(priv, 0xe34, 0x03FF0000, result_final[2]); // X + PHY_SetBBReg(priv, 0xe34, 0x3FF, result_final[3]); //Y + } + } + + /* + * Path-A PA off + */ + PHY_SetBBReg(priv, 0x870, bMaskDWord, temp_870); + PHY_SetBBReg(priv, 0x860, bMaskDWord, temp_860); + + /* + * Exit IQK mode + */ + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + PHY_SetBBReg(priv, 0xc04, bMaskDWord, temp_c04); + PHY_SetBBReg(priv, 0xc08, bMaskDWord, temp_c08); + PHY_SetBBReg(priv, 0x874, bMaskDWord, temp_874); + //PHY_SetBBReg(priv, 0x800, bMaskDWord, temp_800); + PHY_SetBBReg(priv, 0xa04, bMaskDWord, temp_a04); + PHY_SetBBReg(priv, 0x88c, bMaskDWord, temp_88c); + PHY_SetBBReg(priv, 0xb30, bMaskDWord, temp_b30); // 03/03/2011 update + //PHY_SetBBReg(priv, 0x840, bMaskDWord, 0x00032fff); // 01/11/2011 update + + //PHY0 IQ path to DP block + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x010170b8); + + PHY_SetBBReg(priv, 0xc50, bMaskDWord, 0x50); + PHY_SetBBReg(priv, 0xc50, bMaskDWord, temp_c50); + + /* + * Reload MAC default value + */ + RTL_W8(0x550, temp_550); + RTL_W8(0x551, temp_551); + RTL_W8(0x522, temp_522); + + /* + * Switch back to SI if needed, after IQK + */ + if (switch2PI) { + PHY_SetBBReg(priv, 0x820, bMaskDWord, 0x01000000); + PHY_SetBBReg(priv, 0x828, bMaskDWord, 0x01000000); + } + + /* + * Reload ADDA power saving parameters + */ + for(i = 0 ; i < IQK_ADDA_REG_NUM ; i++) + PHY_SetBBReg(priv, ADDA_REG[i], bMaskDWord, ADDA_backup[i]); + + if (!TX0IQKOK) + priv->pshare->IQK_fail_cnt++; +} +#endif + +#ifdef SW_LCK_92D + +#define TARGET_CHNL_NUM_5G 221 +#define TARGET_CHNL_NUM_2G 14 +#define CV_CURVE_CNT 64 + +unsigned int CurveIndex_5G[TARGET_CHNL_NUM_5G]={0}; +unsigned int CurveIndex_2G[TARGET_CHNL_NUM_2G]={0}; + +static unsigned int TargetChnl_5G[TARGET_CHNL_NUM_5G] = { +25141, 25116, 25091, 25066, 25041, +25016, 24991, 24966, 24941, 24917, +24892, 24867, 24843, 24818, 24794, +24770, 24765, 24721, 24697, 24672, +24648, 24624, 24600, 24576, 24552, +24528, 24504, 24480, 24457, 24433, +24409, 24385, 24362, 24338, 24315, +24291, 24268, 24245, 24221, 24198, +24175, 24151, 24128, 24105, 24082, +24059, 24036, 24013, 23990, 23967, +23945, 23922, 23899, 23876, 23854, +23831, 23809, 23786, 23764, 23741, +23719, 23697, 23674, 23652, 23630, +23608, 23586, 23564, 23541, 23519, +23498, 23476, 23454, 23432, 23410, +23388, 23367, 23345, 23323, 23302, +23280, 23259, 23237, 23216, 23194, +23173, 23152, 23130, 23109, 23088, +23067, 23046, 23025, 23003, 22982, +22962, 22941, 22920, 22899, 22878, +22857, 22837, 22816, 22795, 22775, +22754, 22733, 22713, 22692, 22672, +22652, 22631, 22611, 22591, 22570, +22550, 22530, 22510, 22490, 22469, +22449, 22429, 22409, 22390, 22370, +22350, 22336, 22310, 22290, 22271, +22251, 22231, 22212, 22192, 22173, +22153, 22134, 22114, 22095, 22075, +22056, 22037, 22017, 21998, 21979, +21960, 21941, 21921, 21902, 21883, +21864, 21845, 21826, 21807, 21789, +21770, 21751, 21732, 21713, 21695, +21676, 21657, 21639, 21620, 21602, +21583, 21565, 21546, 21528, 21509, +21491, 21473, 21454, 21436, 21418, +21400, 21381, 21363, 21345, 21327, +21309, 21291, 21273, 21255, 21237, +21219, 21201, 21183, 21166, 21148, +21130, 21112, 21095, 21077, 21059, +21042, 21024, 21007, 20989, 20972, +25679, 25653, 25627, 25601, 25575, +25549, 25523, 25497, 25471, 25446, +25420, 25394, 25369, 25343, 25318, +25292, 25267, 25242, 25216, 25191, +25166 }; + +static unsigned int TargetChnl_2G[TARGET_CHNL_NUM_2G] = { // channel 1~14 +26084, 26030, 25976, 25923, 25869, 25816, 25764, +25711, 25658, 25606, 25554, 25502, 25451, 25328 +}; + +void _PHY_CalcCurvIndex(struct rtl8192cd_priv *priv, unsigned int *TargetChnl, + unsigned int *CurveCountVal, char is5G, unsigned int *CurveIndex) +{ + unsigned int smallestABSVal = 0xffffffff, u4tmp; + unsigned char i, j; + unsigned char chnl_num = is5G?(TARGET_CHNL_NUM_5G) : (TARGET_CHNL_NUM_2G); + + + for(i=0; ipmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G? RF92CD_PATH_A:(priv->pmib->dot11RFEntry.macPhyMode==SINGLEMAC_SINGLEPHY?RF92CD_PATH_B:RF92CD_PATH_A); + unsigned int u4tmp = 0; +// unsigned char bNeedPowerDownRadio = FALSE; + unsigned int channel = priv->pshare->RegRF18[eRFPath]&0xff; + //unsigned int channel = PHY_QueryRFReg(priv, eRFPath, rRfChannel, 0xff, 1); + + DEBUG_INFO("====>phy_ReloadLCKSetting interface %d path %d ch %d [0x%05x]\n", priv->pshare->wlandev_idx, eRFPath, channel, priv->pshare->RegRF28[eRFPath]); + + //only for 92D C-cut SMSP + if(GET_CHIP_VER(priv)!=VERSION_8192D +#ifdef CONFIG_RTL_92C_SUPPORT + || IS_TEST_CHIP(priv) +#endif + ) + return; + + if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + { + //Path-A for 5G + u4tmp = CurveIndex_5G[channel-1]; + //printk("%s ver 1 set RF-A, 5G, 0x28 = 0x%x !!\n",__FUNCTION__, u4tmp); +#ifdef CONFIG_RTL_92D_DMDP + if(priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 1) + { + priv->pshare->RegRF28[RF92CD_PATH_A] = RTL_SET_MASK(priv->pshare->RegRF28[RF92CD_PATH_A],0x3f800,u4tmp,11); //DMDP_PHY_SetRFReg(0, RF92CD_PATH_A, 0x28, 0x3f800, u4tmp); + DMDP_PHY_SetRFReg(0, RF92CD_PATH_A, 0x28, bMask20Bits, priv->pshare->RegRF28[RF92CD_PATH_A]); + }else +#endif + { + priv->pshare->RegRF28[eRFPath] = RTL_SET_MASK(priv->pshare->RegRF28[eRFPath],0x3f800,u4tmp,11); //PHY_SetRFReg(priv, eRFPath, 0x28, 0x3f800, u4tmp); + PHY_SetRFReg(priv, eRFPath, 0x28, bMask20Bits, priv->pshare->RegRF28[eRFPath]); + } + DEBUG_INFO("%s ver 3 set RF-B, 2G, 0x28 = 0x%05x [0x%05x]!!\n", __FUNCTION__, PHY_QueryRFReg(priv, eRFPath, 0x28, bMask20Bits, 1), priv->pshare->RegRF28[eRFPath]); + } + else if(priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_2G) + { + u4tmp = CurveIndex_2G[channel-1]; + //printk("%s ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", __FUNCTION__, u4tmp); +#ifdef CONFIG_RTL_92D_DMDP + if(priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY && priv->pshare->wlandev_idx == 0) + { + priv->pshare->RegRF28[RF92CD_PATH_A] = RTL_SET_MASK(priv->pshare->RegRF28[RF92CD_PATH_A],0x3f800,u4tmp,11); //DMDP_PHY_SetRFReg(1, RF92CD_PATH_A, 0x28, 0x3f800, u4tmp); + DMDP_PHY_SetRFReg(1, RF92CD_PATH_A, 0x28, bMask20Bits, priv->pshare->RegRF28[RF92CD_PATH_A]); + }else +#endif + { + priv->pshare->RegRF28[eRFPath] = RTL_SET_MASK(priv->pshare->RegRF28[eRFPath],0x3f800,u4tmp,11); // PHY_SetRFReg(priv, eRFPath, 0x28, 0x3f800, u4tmp); + PHY_SetRFReg(priv, eRFPath, 0x28, bMask20Bits, priv->pshare->RegRF28[eRFPath]); + } + DEBUG_INFO("%s ver 3 set RF-B, 2G, 0x28 = 0x%05x [0x%05x]!!\n", __FUNCTION__, PHY_QueryRFReg(priv, eRFPath, 0x28, bMask20Bits, 1), priv->pshare->RegRF28[eRFPath]); + } + +} + +/* Software LCK */ +void PHY_LCCalibrate_92D(struct rtl8192cd_priv *priv) +{ + unsigned char tmpReg; + unsigned int RF_mode[2]; + unsigned int eRFPath, curMaxRFPath; + unsigned int i; + unsigned int curveCountVal[CV_CURVE_CNT*2]={0}; + unsigned short timeout = 800, timecount = 0; + + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + curMaxRFPath = RF92CD_PATH_B; + else + curMaxRFPath = RF92CD_PATH_MAX; + + //Check continuous TX and Packet TX + tmpReg = RTL_R8(0xd03); + + if ((tmpReg & 0x70) != 0) // Deal with contisuous TX case + RTL_W8(0xd03, tmpReg&0x8F); // disable all continuous TX + else // Deal with Packet TX case + RTL_W8(TXPAUSE, 0xFF); // block all queues + + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0xF00000, 0x0F); + + for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { + // 1. Read original RF mode + RF_mode[eRFPath] = PHY_QueryRFReg(priv, eRFPath, 0x00, bMask20Bits, 1); + + // 2. Set RF mode = standby mode + PHY_SetRFReg(priv, eRFPath, 0x00, 0x70000, 0x01); + + // switch CV-curve control by LC-calibration + PHY_SetRFReg(priv, eRFPath, 0x2B, BIT(17), 0x0); + + // jenyu suggest + PHY_SetRFReg(priv, eRFPath, 0x28, BIT(8), 0x1); + + //4. Set LC calibration begin + PHY_SetRFReg(priv, eRFPath, 0x18, BIT(15), 0x01); + + while(!(PHY_QueryRFReg(priv, eRFPath, 0x2A, BIT(11), 1) && + timecount <= timeout)){ + //DEBUG_INFO("PHY_LCK delay for %d ms=2\n", timecount); + delay_ms(50); + timecount+=50; + } + + //u4tmp = PHY_QueryRFReg(priv, eRFPath, 0x28, bMask20Bits, 1); + + memset((void *)curveCountVal, 0, CV_CURVE_CNT*2); + + //Set LC calibration off + PHY_SetRFReg(priv, eRFPath, 0x18, BIT(15), 0x00); + + // jenyu suggest + PHY_SetRFReg(priv, eRFPath, 0x28, BIT(8), 0x0); + + //save Curve-counting number + for(i=0; i> 5; + + readVal2 = PHY_QueryRFReg(priv, eRFPath, 0x50, 0xffc00, 1); + + curveCountVal[2*i] = (((readVal & 0x1F) << 10) | readVal2); + } + + if(eRFPath == RF92CD_PATH_A +#ifdef CONFIG_RTL_92D_DMDP + && priv->pshare->wlandev_idx == 0 +#endif + ) + _PHY_CalcCurvIndex(priv, TargetChnl_5G, curveCountVal, TRUE, CurveIndex_5G); + else + _PHY_CalcCurvIndex(priv, TargetChnl_2G, curveCountVal, FALSE, CurveIndex_2G); + + // switch CV-curve control mode + PHY_SetRFReg(priv, eRFPath, 0x2B, BIT(17), 0x1); + + // store 0x28 for Reload_LCK + priv->pshare->RegRF28[eRFPath] = PHY_QueryRFReg(priv, eRFPath, 0x28, bMask20Bits, 1); + } + + //Restore original situation + for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) + { + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, RF_mode[eRFPath]); + } + + if((tmpReg&0x70) != 0) + { + //Path-A + RTL_W8(0xd03, tmpReg); + } + else // Deal with Packet TX case + { + RTL_W8(TXPAUSE, 0x00); + } + + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0xF00000, 0x00); + + phy_ReloadLCKSetting(priv); + +} + +#else +/* Hardware LCK */ +static void PHY_LCCalibrate_92D(struct rtl8192cd_priv *priv) +{ + unsigned char tmpReg; + unsigned int RF_mode[2], tmpu4Byte[2]; + + unsigned int eRFPath, curMaxRFPath; + unsigned char timeout = 800, timecount = 0; + + if (priv->pmib->dot11RFEntry.macPhyMode == DUALMAC_DUALPHY) + curMaxRFPath = RF92CD_PATH_B; + else + curMaxRFPath = RF92CD_PATH_MAX; + + + // Check continuous TX and Packet TX + tmpReg = RTL_R8(0xd03); + + if ((tmpReg & 0x70) != 0) // Deal with contisuous TX case + RTL_W8(0xd03, tmpReg&0x8F); // disable all continuous TX + else // Deal with Packet TX case + RTL_W8(TXPAUSE, 0xFF); // block all queues + + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0xF00000, 0x0F); + + for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { + // 1. Read original RF mode + RF_mode[eRFPath] = PHY_QueryRFReg(priv, eRFPath, 0x00, bMask20Bits, 1); + + // 2. Set RF mode = standby mode + PHY_SetRFReg(priv, eRFPath, 0x00, 0x70000, 0x01); + + tmpu4Byte[eRFPath] = PHY_QueryRFReg(priv, eRFPath, 0x28, bMask20Bits, 1); + PHY_SetRFReg(priv, eRFPath, 0x28, 0x700, 0x07); + + //4. Set LC calibration begin + PHY_SetRFReg(priv, eRFPath, 0x18, 0x08000, 0x01); + } + + watchdog_kick(); + + for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { + while(!(PHY_QueryRFReg(priv, eRFPath, 0x2A, BIT(11), 1) && + timecount <= timeout)){ + DEBUG_INFO("PHY_LCK delay for %d ms=2\n", timecount); + delay_ms(50); + timecount+=50; + } + } + + for(eRFPath = RF92CD_PATH_A; eRFPath < curMaxRFPath; eRFPath++) { + PHY_SetRFReg(priv, eRFPath, 0x28, bMask20Bits, tmpu4Byte[eRFPath]); + priv->pshare->RegRF28[eRFPath] = tmpu4Byte[eRFPath]; + PHY_SetRFReg(priv, eRFPath, 0x00, bMask20Bits, RF_mode[eRFPath]); + } + + // Restore original situation + if ((tmpReg & 0x70) != 0) // Deal with contisuous TX case + RTL_W8(0xd03, tmpReg); + else // Deal with Packet TX case + RTL_W8(TXPAUSE, 0x00); + + PHY_SetBBReg(priv, rFPGA0_AnalogParameter4, 0xF00000, 0x0); + +} + + +#endif //LCK_SW + +#ifdef DPK_92D + +#if 1 //copy from driver of station team +#define RF_AC 0x00 + +#define rPdp_AntA 0xb00 +#define rBndA 0xb30 +#define rPdp_AntB 0xb70 +#define rBndB 0xba0 + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define rTxAGC_A_CCK11_2_B_CCK11 0x86c + +#define RF_TX_G3 0x22 + +#define RF_TXPA_G1 0x31 // RF TX PA control +#define RF_TXPA_G2 0x32 // RF TX PA control +#define RF_TXPA_G3 0x33 // RF TX PA control +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C +#define RF_TRSW 0x3F + +#define RF_TXPA_G1 0x31 // RF TX PA control +#define RF_TXPA_G2 0x32 // RF TX PA control +#define RF_TXPA_G3 0x33 // RF TX PA control +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C +#define RF_TRSW 0x3F + +#define RF_TXRF_A2 0x41 +#define RF_TXPA_G4 0x46 +#define RF_TXPA_A4 0x4B + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_BS_PA_APSET_G1_G4 0x03 +#define RF_BS_PA_APSET_G5_G8 0x04 +#define RF_POW_TRSW 0x05 + +#define DP_OFFSET_NUM 9 +#define DP_AP_CUREVE_SELECT_NUM 3 +#define DP_gain_loss 1 +#define DP_PA_BIAS_NUM 4 + +#define rTxAGC_B_CCK5_1_Mcs32 0x838 + +#define RF_TXBIAS 0x16 +#endif + +#define DPK_DEBUG(fmt,args...) + +#define DP_BB_REG_NUM 7 +//#define DP_BB_REG_NUM_A 11 +//#define DP_BB_REG_NUM_B 10 +#define DP_BB_REG_NUM_A 10 +#define DP_BB_REG_NUM_B 9 + +#define DP_BB_REG_NUM_settings 6 +#define DP_BB_REG_NUM_loop 30 +#define DP_BB_REG_NUM_loop_tx 12 +#define DP_BB_REG_NUM_loop_rx 8 +#define DP_BB_REG_NUM_loop_pa 4 +#define DP_RF_REG_NUM 4 +#define DP_SRAM_NUM 16 +//#define DP_SRAM_NUM_db 22 +#define DP_SRAM_NUM_db 86 + +#define DP_PATH_NUM 2 +#define DP_PA_MODEL_NUM 32 +#define DP_PA_MODEL_RUN_NUM 8 +#define DP_PA_MODEL_PER_RUN_NUM 4 +#define DP_RETRY_LIMIT 10 +#define DP_DPK_NUM 3 +#define DP_DPK_VALUE_NUM 2 +#if 1 +#define DP_GAIN_LOSS_BOUND_NUM 14 +#else +#define DP_GAIN_LOSS_BOUND_NUM 8 +#endif +#define DP_OFFSET_NUM 9 +//#define DP_AP_CUREVE_SELECT_NUM 2 // 3 +#define DP_gain_loss 1 + + +void rtl8192cd_DPK_timer(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + + if (!(priv->drv_state & DRV_STATE_OPEN)) + return; + + if (priv->pshare->pwr_trk_ongoing){ + DPK_DEBUG("==>_PHY_DigitalPredistortion() TxPowerTrackingInProgress() delay 100ms\n"); + mod_timer(&priv->pshare->DPKTimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(100)); + }else{ + PHY_DPCalibrate(priv); + } +} + +void _PHY_DPK_polling(struct rtl8192cd_priv *priv) +{ + unsigned int delaycount = 0, delaybound = 30, delay = 800; + unsigned int u4tmp; + + delaycount = 0; + + do{ + delay_us(delay); + + u4tmp = PHY_QueryBBReg(priv, 0xdf4, bMaskDWord); + //RTPRINT(FINIT, INIT_IQK, ("0xdf4 = 0x%x, delay %d us\n", u4tmp, delaycount*delay+800)); + delaycount++; + delay = 100; + u4tmp = (u4tmp & BIT(26)) >> 26; + }while(u4tmp == 0x01 && delaycount < delaybound); + +} + +// if AP curve check fail return FALSE +int _PHY_DPK_AP_curve_check(struct rtl8192cd_priv *priv, unsigned int *PA_power, unsigned int RegiesterNum) +{ + unsigned int PA_power_temp[DP_PA_MODEL_NUM], i = 0, index = 5, + base = 532, ref1, ref2; + int power_I, power_Q; + + //store I, Q + + for(i = 0; i < DP_PA_MODEL_NUM; i++){ + power_I = (PA_power[i] >> 8); + if(power_I & BIT(7)) + power_I |= bMaskH3Bytes; + + power_Q = PA_power[i] & bMaskByte0; + if(power_Q & BIT(7)) + power_Q |= bMaskH3Bytes; + + PA_power_temp[i] = power_I*power_I+power_Q*power_Q; + } + + ref1 = PA_power_temp[0]; + for(i = 0; i < index; i++) + ref1 = (ref1 > PA_power_temp[i])?ref1:PA_power_temp[i]; + + ref2 = PA_power_temp[index]; + for(i = index; i < index*2; i++) + ref2 = (ref2 > PA_power_temp[i])?ref2:PA_power_temp[i]; + + DPK_DEBUG("==>_PHY_DPK_AP_cureve_check ref1 = 0x%x ref2 = 0x%x\n", ref1, ref2); + + if(ref1 == 0) + return FALSE; + + return ((ref2 << 9)/ref1) < base; +} + +// if DPK fail return FALSE +int _PHY_DPK_check(struct rtl8192cd_priv *priv, unsigned int *PA_power, unsigned int RegiesterNum) +{ + unsigned int base = 407, PA_power_temp[2], i = 0; + int power_I, power_Q; + + while(i ==0 || i == (RegiesterNum-1)) + { + power_I = (PA_power[i] >> 8); + if(power_I & BIT(7)) + power_I |= bMaskH3Bytes; + + power_Q = PA_power[i] & bMaskByte0; + if(power_Q & BIT(7)) + power_Q |= bMaskH3Bytes; + + PA_power_temp[i==0?0:1] = power_I*power_I+ power_Q*power_Q; + + DPK_DEBUG("==>_PHY_DPK_check pa_power_temp[%d] 0x%x\n", i, PA_power_temp[i==0?0:1]); + + if(i == 0) + i = RegiesterNum -1; + else if (i == RegiesterNum -1) + break; + } + + //normalization + if(PA_power_temp[0] == 0) + return TRUE; + else + return (((PA_power_temp[1] << 9) /PA_power_temp[0]) <= base); + +} + +int _PHY_Find_Tx_Power_Index(struct rtl8192cd_priv *priv, unsigned int *PA_power, unsigned char path, unsigned char bPlus3db, char bDecreaseTxIndex, unsigned char *tx_index_out) +{ + unsigned char i, tx_index = bDecreaseTxIndex?0x0f:0x15; + unsigned int tmpReg[11], tmpBase, RegNum = 11, base = /*323*/256; + unsigned int PA_power_normal[11]; +// unsigned int check_base =bPlus3db?(400-base):(323-base); + unsigned int check_base =bPlus3db?400:323; + + int power_I, power_Q; + int index = -1; + + DPK_DEBUG("==>tx_index minus %d bplus3db %d\n", base, bPlus3db); + + _PHY_DPK_polling(priv); + + if(path == RF92CD_PATH_A) + { + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x01017018); + tmpReg[0] = PHY_QueryBBReg(priv, 0xbdc, bMaskDWord); + tmpReg[1] = PHY_QueryBBReg(priv, 0xbe8, bMaskDWord); + + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x01017019); + tmpReg[2] = PHY_QueryBBReg(priv, 0xbdc, bMaskDWord); + tmpReg[3] = PHY_QueryBBReg(priv, 0xbe0, bMaskDWord); + tmpReg[4] = PHY_QueryBBReg(priv, 0xbe8, bMaskDWord); + + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x0101701a); + tmpReg[5] = PHY_QueryBBReg(priv, 0xbe0, bMaskDWord); + + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x0101701b); + tmpReg[6] = PHY_QueryBBReg(priv, 0xbdc, bMaskDWord); + tmpReg[7] = PHY_QueryBBReg(priv, 0xbe8, bMaskDWord); + + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x0101701c); + tmpReg[8] = PHY_QueryBBReg(priv, 0xbe8, bMaskDWord); + + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x0101701e); + tmpReg[9] = PHY_QueryBBReg(priv, 0xbdc, bMaskDWord); + + PHY_SetBBReg(priv, 0xb00, bMaskDWord, 0x0101701f); + tmpReg[10] = PHY_QueryBBReg(priv, 0xbe8, bMaskDWord); + + //RTPRINT(FINIT, INIT_IQK, ("==>_PHY_Find_Tx_Power_Index path A\n")); + + } + else if(path == RF92CD_PATH_B) + { + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x01017018); + tmpReg[0] = PHY_QueryBBReg(priv, 0xbec, bMaskDWord); + tmpReg[1] = PHY_QueryBBReg(priv, 0xbf8, bMaskDWord); + + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x01017019); + tmpReg[2] = PHY_QueryBBReg(priv, 0xbec, bMaskDWord); + tmpReg[3] = PHY_QueryBBReg(priv, 0xbf0, bMaskDWord); + tmpReg[4] = PHY_QueryBBReg(priv, 0xbf8, bMaskDWord); + + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x0101701a); + tmpReg[5] = PHY_QueryBBReg(priv, 0xbf4, bMaskDWord); + + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x0101701b); + tmpReg[6] = PHY_QueryBBReg(priv, 0xbec, bMaskDWord); + tmpReg[7] = PHY_QueryBBReg(priv, 0xbf8, bMaskDWord); + + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x0101701c); + tmpReg[8] = PHY_QueryBBReg(priv, 0xbf8, bMaskDWord); + + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x0101701e); + tmpReg[9] = PHY_QueryBBReg(priv, 0xbec, bMaskDWord); + + PHY_SetBBReg(priv, 0xb70, bMaskDWord, 0x0101701f); + tmpReg[10] = PHY_QueryBBReg(priv, 0xbf8, bMaskDWord); + + //RTPRINT(FINIT, INIT_IQK, ("==>_PHY_Find_Tx_Power_Index path B\n")); + + } + + for(i = 0; i < RegNum; i++) + { + power_I = (tmpReg[i] >> 8); + if(power_I & BIT(7)) + power_I |= bMaskH3Bytes; + + power_Q = tmpReg[i] & bMaskByte0; + if(power_Q & BIT(7)) + power_Q |= bMaskH3Bytes; + + PA_power[i] = power_I*power_I+ power_Q*power_Q; + } + + //normalization + tmpBase = PA_power[0]; + //RTPRINT(FINIT, INIT_IQK, ("==>PA_power START normalized\n")); + + if(tmpBase == 0) + DPK_DEBUG("==>PA_power[0] is ZERO !!!!!\n"); + + for(i = 0; i < RegNum; i++) + { + if(tmpBase != 0) + PA_power[i] = (PA_power[i] << 9) /tmpBase; + else + PA_power[i] = (PA_power[i] << 9) ; + PA_power_normal[i] = PA_power[i]; + PA_power[i] = (PA_power[i] > base)?(PA_power[i] - base):(base - PA_power[i]); + DPK_DEBUG("==>PA_power normalized index %d value 0x%x\n", i, PA_power[i]); + } + + //choose min for TX index to do DPK + base = bMaskDWord; + for(i = 0; i < RegNum; i++) + { + if(PA_power[i] < base) + { + base = PA_power[i]; + index = i; + } + } + + if(index == -1) + { + tx_index = 0x1c; + index = 0x1f - tx_index; + } + else + { + tx_index += index; + } + + DPK_DEBUG("==>tx_index result 0x%x PA_power[%d] = 0x%x\n", tx_index, index, PA_power[index]); + + *tx_index_out = tx_index; + + //Check pattern reliability + if(((PA_power_normal[index] > check_base) && (tx_index == 0x1f)) || + ((PA_power_normal[10] > base) && (!bPlus3db)) || + ((tx_index < 0x1a) && (!bPlus3db)) || + ((tx_index < 0x13) && (bDecreaseTxIndex)) + ) + return FALSE; + else + return TRUE; +// return tx_index; + +} + +unsigned char _PHY_Find_Rx_Power_Index(struct rtl8192cd_priv *priv, unsigned char tx_index, unsigned char rx_index, unsigned char path, char *bDecreaseTxIndex) +{ +// u1Byte rx_index = 0x04; + unsigned int tmpReg; + int power_I, power_Q, tmp; + unsigned char bPlus = FALSE, bMinus = FALSE; + unsigned short offset[2][2] = {{ //path, offset + 0xb28, 0xbe8},{ + 0xb98, 0xbf8}}; + + while (TRUE){ + tmpReg = 0x52000 | tx_index | (rx_index << 5); + PHY_SetRFReg(priv, path, RF_AC, bMask20Bits, tmpReg); + //RTPRINT(FINIT, INIT_IQK, ("==>RF 0ffset 0 = 0x%x readback = 0x%x\n", tmpReg, + //PHY_QueryRFReg(pAdapter, path, RF_AC, bRFRegOffsetMask))); + + //----send one shot signal----// + PHY_SetBBReg(priv, offset[path][0], bMaskDWord, 0x80080000); //0xb28, 0xb98 + PHY_SetBBReg(priv, offset[path][0], bMaskDWord, 0x00080000); + + _PHY_DPK_polling(priv); + + tmpReg = PHY_QueryBBReg(priv, offset[path][1], bMaskDWord); + power_I = ((tmpReg & bMaskByte1) >> 8); + power_Q = tmpReg & bMaskByte0; + + if(power_I & BIT(7)) + { + power_I |= bMaskH3Bytes; + power_I = 0-power_I; //absolute value + } + + if(power_Q & BIT(7)) + { + power_Q |= bMaskH3Bytes; + power_Q = 0-power_Q; + } + //RTPRINT(FINIT, INIT_IQK, ("==>rx_index 0x%x I = 0x%x Q = 0x%x offset 0xbe8 = 0x%x\n", rx_index, power_I, power_Q, tmpReg)); + + tmp = (power_I > power_Q)? power_I:power_Q; + +#if 0 + if((rx_index == 0 && tmp > 0x6f)||(rx_index == 31 && tmp < 0x50)) + break; +#endif + + if((tmp<= 0x6f && tmp >= 0x50) ) + { + break; + } + else if(tmp < 0x50) + { + bPlus = TRUE; + if(bMinus) + { + rx_index++; + break; + } +// rx_index++; + rx_index += 2; + } + else if (tmp > 0x6f) + { + bMinus = TRUE; + if(bPlus) + { + rx_index--; + break; + } +// rx_index--; + rx_index -= 2; + } + + if(rx_index == 0 || rx_index == 31) + break; + + } + if(rx_index == 0 && tmp > 0x6f) + *bDecreaseTxIndex = TRUE; + + DPK_DEBUG("==>rx_index FINAL 0x%x I = 0x%x Q = 0x%x\n", rx_index, power_I, power_Q); + + return rx_index; + +} + +void PHY_DPCalibrate(struct rtl8192cd_priv *priv) +{ + char is2T = ((priv->pmib->dot11RFEntry.macPhyMode != DUALMAC_DUALPHY) ?1 :0); + + unsigned int tmpReg, value32/*, checkbit*/; + unsigned int AFE_backup[IQK_ADDA_REG_NUM]; + static unsigned int AFE_REG[IQK_ADDA_REG_NUM] = { + rFPGA0_XCD_SwitchControl, 0xe6c, 0xe70, 0xe74, 0xe78, + 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, + 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, + 0xeec}; + + static unsigned int BB_backup[DP_BB_REG_NUM]; + static unsigned int BB_REG[DP_BB_REG_NUM] = { + rOFDM0_TRxPathEnable, rFPGA0_RFMOD, + rOFDM0_TRMuxPar, rFPGA0_XCD_RFInterfaceSW, + rFPGA0_AnalogParameter4, rFPGA0_XAB_RFInterfaceSW, + rTxAGC_B_CCK11_A_CCK2_11 + }; + + static unsigned int BB_backup_A[DP_BB_REG_NUM_A]; + static unsigned int BB_REG_A[DP_BB_REG_NUM_A] = { + rFPGA0_XA_RFInterfaceOE, rTxAGC_A_Rate18_06, + rTxAGC_A_Rate54_24, rTxAGC_A_CCK1_Mcs32, + 0xe0c, rTxAGC_A_Mcs03_Mcs00, + rTxAGC_A_Mcs07_Mcs04, rTxAGC_A_Mcs11_Mcs08, + rTxAGC_A_Mcs15_Mcs12, rOFDM0_XAAGCCore1/*, + rBndA*/ + }; + + + static unsigned int BB_backup_B[DP_BB_REG_NUM_B]; + static unsigned int BB_REG_B[DP_BB_REG_NUM_B] = { + rFPGA0_XB_RFInterfaceOE, rTxAGC_B_Rate18_06, + rTxAGC_B_Rate54_24, rTxAGC_B_CCK1_55_Mcs32, + rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04, + rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12, + rOFDM0_XBAGCCore1 /*, rBndB*/ + }; + + static unsigned int BB_settings[DP_BB_REG_NUM_settings] = { + 0x00a05430, 0x02040000, 0x000800e4, 0x22208000, + 0xccf000c0/*, 0x07600760*/}; + + static unsigned int BB_REG_loop[DP_PATH_NUM][DP_BB_REG_NUM_loop] = { + {0xb00, 0xb04, 0xb28, 0xb68, + 0xb08, 0xb0c, 0xb10, 0xb14, + 0xb18, 0xb1c, 0xb20, 0xb24, + 0xe28, 0xb00, 0xb04, 0xb08, + 0xb0c, 0xb10, 0xb14, 0xb18, + 0xb1c, 0xb20, 0xb24, 0xb28, + 0xb2c, rBndA, 0xb34, 0xb38, + 0xb3c, 0xe28}, + {0xb70, 0xb74, 0xb98, 0xb6C, + 0xb78, 0xb7c, 0xb80, 0xb84, + 0xb88, 0xb8c, 0xb90, 0xb94, + 0xe28, 0xb60, 0xb64, 0xb68, + 0xb6c, 0xb70, 0xb74, 0xb78, + 0xb7c, 0xb80, 0xb84, 0xb88, + 0xb8c, 0xb90, 0xb94, 0xb98, + 0xb9c, 0xe28} + }; + + static unsigned int BB_settings_loop[DP_BB_REG_NUM_loop] = { + 0x01017e18, 0xf76d9f84, 0x00080000, 0x11880000, + 0x41382e21, 0x5b554f48, 0x6f6b6661, 0x817d7874, + 0x908c8884, 0x9d9a9793, 0xaaa7a4a1, 0xb6b3b0ad, + 0x40000000, 0x7d327c18, 0x7e057db3, 0x7e5f7e37, + 0x7e967e7c, 0x7ebe7eac, 0x7ed77ecc, 0x7eee7ee4, + 0x7f017ef9, 0x7f0e7f07, 0x7f1c7f15, 0x7f267f20, + 0x7f2f7f2a, 0x7f377f34, 0x7f3e7f3b, 0x7f457f42, + 0x7f4b7f48, 0x00000000 + }; + + static unsigned int BB_settings_loop_3db[DP_BB_REG_NUM_loop] = { + 0x01017e18, 0xf76d9f84, 0x00080000, 0x11880000, + 0x5b4e402e, 0x7f776f65, 0x9c968f88, 0xb5afa8a3, + 0xcac4bfb9, 0xdcd8d4ce, 0xeeeae6e2, 0xfffbf7f2, + 0x40000000, 0x7dfe7d32, 0x7e967e59, 0x7ed77eba, + 0x7efd7eeb, 0x7f1a7f0e, 0x7f2d7f25, 0x7f3c7f36, + 0x7f4a7f44, 0x7f547f4e, 0x7f5d7f58, 0x7f657f60, + 0x7f6a7f68, 0x7f717f6e, 0x7f767f73, 0x7f7b7f78, + 0x7f7f7f7d, 0x00000000 + }; + + static unsigned int BB_settings_loop_tx[DP_BB_REG_NUM_loop] = { + 0x01017e18, 0xf76d9f84, 0x00080000, 0x11880000, + 0x21212121, 0x21212121, 0x21212121, 0x21212121, + 0x21212121, 0x21212121, 0x21212121, 0x21212121, + 0x40000000, 0x7c187c18, 0x7c187c18, 0x7c187c18, + 0x7c187c18, 0x7c187c18, 0x7c187c18, 0x7c187c18, + 0x7c187c18, 0x7c187c18, 0x7c187c18, 0x7c187c18, + 0x7c187c18, 0x7c187c18, 0x7c187c18, 0x7c187c18, + 0x7c187c18, 0x00000000 + }; + + static unsigned int BB_settings_loop_tx_3db[DP_BB_REG_NUM_loop] = { + 0x01017e18, 0xf76d9f84, 0x00080000, 0x11880000, + 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, + 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, 0x2e2e2e2e, + 0x40000000, 0x7d327d32, 0x7d327d32, 0x7d327d32, + 0x7d327d32, 0x7d327d32, 0x7d327d32, 0x7d327d32, + 0x7d327d32, 0x7d327d32, 0x7d327d32, 0x7d327d32, + 0x7d327d32, 0x7d327d32, 0x7d327d32, 0x7d327d32, + 0x7d327d32, 0x00000000 + }; + + + //for find 2dB loss point + static unsigned int BB_settings_loop_tx_2[DP_BB_REG_NUM_loop] = { + 0x01017e18, 0xf76d9f84, 0x00080000, 0x11880000, + 0x41382e21, 0x5b554f48, 0x6f6b6661, 0x817d7874, + 0x908c8884, 0x9d9a9793, 0xaaa7a4a1, 0xb6b3b0ad, + 0x40000000, 0x7d327c18, 0x7e057db3, 0x7e5f7e37, + 0x7e967e7c, 0x7ebe7eac, 0x7ed77ecc, 0x7eee7ee4, + 0x7f017ef9, 0x7f0e7f07, 0x7f1c7f15, 0x7f267f20, + 0x7f2f7f2a, 0x7f377f34, 0x7f3e7f3b, 0x7f457f42, + 0x7f4b7f48, 0x00000000 + }; + + //for find 2dB loss point + static unsigned int BB_settings_loop_tx_2_3db[DP_BB_REG_NUM_loop] = { + 0x01017e18, 0xf76d9f84, 0x00080000, 0x11880000, + 0x5b4e402e, 0x7f776f65, 0x9c968f88, 0xb5afa8a3, + 0xcac4bfb9, 0xdcd8d4ce, 0xeeeae6e2, 0xfffbf7f2, + 0x40000000, 0x7dfe7d32, 0x7e967e59, 0x7ed77eba, + 0x7efd7eeb, 0x7f1a7f0e, 0x7f2d7f25, 0x7f3c7f36, + 0x7f4a7f44, 0x7f547f4e, 0x7f5d7f58, 0x7f657f60, + 0x7f6a7f68, 0x7f717f6e, 0x7f767f73, 0x7f7b7f78, + 0x7f7f7f7d, 0x00000000 + }; + + + static unsigned int BB_settings_loop_rx[DP_BB_REG_NUM_loop_rx] = { + 0x01017e18, 0xf76d9f84, 0x00080000, 0x11880000, + 0x21212121, 0x40000000, 0x7c187c18, 0x00000000 + }; + + static unsigned int BB_settings_loop_rx_3db[DP_BB_REG_NUM_loop_rx] = { + 0x01017e18, 0xf76d9f84, 0x00080000, 0x11880000, + 0x2e2e2e2e, 0x40000000, 0x7d327d32, 0x00000000 + }; + + static unsigned int BB_settings_loop_pa[DP_BB_REG_NUM_loop_pa] = { + 0x02096eb8, 0xf76d9f84, 0x00044499, 0x02880140 + }; + + static unsigned int BB_settings_loop_dp[DP_BB_REG_NUM_loop_pa] = { + 0x01017098, 0x776d9f84, 0x00000000, 0x08080000 + }; + + unsigned int *BB_settings_temp; + + static unsigned char Sram_db_settings[DP_SRAM_NUM_db] = { + 0xfe, 0xf0, 0xe3, 0xd6, 0xca, + 0xbf, 0xb4, 0xaa, 0xa0, 0x97, + 0x8f, 0x87, 0x7f, 0x78, 0x71, + 0x6b, 0x65, 0x5f, 0x5a, 0x55, + 0x50, 0x4c, 0x47, 0x43, 0x40, + 0x3c, 0x39, 0x35, 0x32, 0x2f, + 0x2d, 0x2a, 0x28, 0x26, 0x23, + 0x21, 0x20, 0x1e, 0x1c, 0x1a, + 0x19, 0x18, 0x16, 0x16, 0x14, + 0x13, 0x12, 0x11, 0x10, 0x0f, + 0x0e, 0x0d, 0x0c, 0x0c, 0x0b, + 0x0a, 0x0a, 0x09, 0x09, 0x08, + 0x08, 0x07, 0x07, 0x06, 0x06, + 0x06, 0x05, 0x05, 0x05, 0x04, + 0x04, 0x04, 0x04, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, + 0x01 + }; + + //unsigned int pwsf[DP_SRAM_NUM]; + + static unsigned int offset[2][DP_OFFSET_NUM] = {{ //path, offset + 0xe34, 0xb28, 0xb00, 0xbdc, 0xbc0, + 0xbe8, rOFDM0_XATxIQImbalance, rBndA, + 0xb68},{ + 0xe54, 0xb98, 0xb70, 0xbec, 0xbc4, + 0xbf8, rOFDM0_XBTxIQImbalance, rBndB, + 0xb6c}}; + + //unsigned char OFDM_min_index = 6, OFDM_min_index_internalPA = 3; + unsigned char OFDM_index[2]; + //unsigned char retrycount = 0, retrybound = 1; + + unsigned int RF_backup[DP_PATH_NUM][DP_RF_REG_NUM]; + static unsigned int RF_REG[DP_RF_REG_NUM] = { + RF_TX_G3, RF_TXPA_A4, RF_RXRF_A3, + RF_BS_PA_APSET_G1_G4/*, RF_BS_PA_APSET_G5_G8, + RF_BS_PA_APSET_G9_G11*/}; + + static unsigned int RF_AP_curve_select[DP_AP_CUREVE_SELECT_NUM] = { + 0x7bdef, 0x94a52, 0xa5294/*, 0xb5ad6*/ }; + + static unsigned int RF_PA_BIAS[3][DP_PA_BIAS_NUM] = {{ //40MHz / 20MHz, original + 0xe189f, 0xa189f, 0x6189f, 0x2189f },{ + 0xe087f, 0xa087f, 0x6087f, 0x2087f },{ + 0xe1874, 0xa1874, 0x61874, 0x21874}}; + + unsigned int PA_model_backup[DP_PATH_NUM][DP_PA_MODEL_NUM]; + + unsigned int PA_power[DP_PATH_NUM][DP_PA_MODEL_RUN_NUM*2]; + +#if DP_gain_loss == 1 + + int power_I, power_Q, coef; + + int gain_loss_backup[DP_PATH_NUM][DP_PA_MODEL_NUM]; //I,Q + + static unsigned int gain_loss_bound[DP_GAIN_LOSS_BOUND_NUM] = { + 63676, 60114 , 56751 , 53577 , 49145, + 47750, 45079 , 42557 , 40177 , 37929 , + 35807 , 33804 , 31913, 30128 + }; + + static int gain_loss_coef[DP_GAIN_LOSS_BOUND_NUM+1] = { + 512, 527, 543, 558, 573, + 589, 609, 625, 645, 666, + 681, 701, 722, 742, 768 + }; + +// BOOLEAN bNegative = FALSE; +// unsigned char index_for_zero_db = 24, AP_curve_index = 0; + unsigned char GainLossIndex = 0; //0db, 0x40 + char SramIndex = 24; + unsigned char /*index_for_zero_db = 6,*/ AP_curve_index = 0; + +#else + + unsigned char index_for_zero_db = 6, AP_curve_index = 0; + int power_I, power_Q; + static unsigned int gain_loss_bound[DP_GAIN_LOSS_BOUND_NUM] = { + 61870, 55142, 49145, 43801, 39037, + 34792, 31008, 27636 + }; +#endif + + unsigned int MAC_backup[IQK_MAC_REG_NUM]; + static unsigned int MAC_REG[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040}; + + //unsigned int AFE_on_off[PATH_NUM] = { + // 0x04db25a4, 0x0b1b25a4}; //path A on path B path A off path B on + + unsigned char path_num, /*path_bound,*/ path = RF92CD_PATH_A, i, j, tx_index, rx_index; + int index, index_1, index_repeat; + + char bInternalPA = FALSE; +#if (DP_gain_loss != 1) + char SkipStep5 = FALSE; +#endif + char bPlus3db = FALSE, bDecreaseTxIndex = FALSE, bDecreaseTxIndexWithRx = FALSE; + +#ifdef DFS + if ((priv->pshare->rf_ft_var.dfsdelayiqk) && + (OPMODE & WIFI_AP_STATE) && + !priv->pmib->dot11DFSEntry.disable_DFS && + (timer_pending(&priv->ch_avail_chk_timer) || + priv->pmib->dot11DFSEntry.disable_tx)) + return; +#endif + + DPK_DEBUG("==>_PHY_DigitalPredistortion() interface index %d is2T = %d\n", priv->pshare->wlandev_idx, is2T); //anchin + + DPK_DEBUG("_PHY_DigitalPredistortion for %s\n", (is2T ? "2T2R" : "1T1R")); + + DPK_DEBUG("==>_PHY_DigitalPredistortion() current thermal meter = 0x%x PG thermal meter = 0x%x bPlus3db %d\n", + priv->pshare->ThermalValue_DPKtrack, priv->pmib->dot11RFEntry.ther, bPlus3db); + + if ((priv->pmib->dot11RFEntry.phyBandSelect!= PHY_BAND_5G)||(GET_CHIP_VER(priv)!=VERSION_8192D)) + return; + + bInternalPA = priv->pshare->rf_ft_var.use_intpa92d; + + if(!is2T) + path_num = 1; + else + path_num = 2; + + if(!bInternalPA) { + DPK_DEBUG("==>_PHY_DigitalPredistortion() NOT internal5G\n"); + return; + } + + if(priv->pshare->pwr_trk_ongoing){ + DPK_DEBUG("==>_PHY_DigitalPredistortion() TxPowerTrackingInProgress() delay 100ms\n"); + mod_timer(&priv->pshare->DPKTimer, jiffies + RTL_MILISECONDS_TO_JIFFIES(100)); + return; + } + + OFDM_index[RF92CD_PATH_A] = priv->pshare->OFDM_index[RF92CD_PATH_A]; + OFDM_index[RF92CD_PATH_B] = priv->pshare->OFDM_index[RF92CD_PATH_B]; + + DPK_DEBUG("original index 0x%x \n", priv->pshare->OFDM_index[0]); + + priv->pshare->bDPKworking = TRUE; + + //save global setting + //save BB default value + _PHY_SaveADDARegisters(priv, BB_REG, BB_backup, DP_BB_REG_NUM); + + //save MAC default value + _PHY_SaveMACRegisters(priv, MAC_REG, MAC_backup); + + //save AFE default value + _PHY_SaveADDARegisters(priv, AFE_REG, AFE_backup, IQK_ADDA_REG_NUM); + + //save path A default value + //save path A BB default value + _PHY_SaveADDARegisters(priv, BB_REG_A, BB_backup_A, DP_BB_REG_NUM_A); + + //save path B BB default value + if(is2T) + _PHY_SaveADDARegisters(priv, BB_REG_B, BB_backup_B, DP_BB_REG_NUM_B); + + //save pathA/B RF default value + for(path=0; pathInternalPA5G[path]) + //continue; + + if(path == RF92CD_PATH_B) + { + //BB pah A register setting:fix TRSW to TX;external LNA off + if(!bInternalPA) + { + PHY_SetBBReg(priv, rFPGA0_XAB_RFInterfaceSW, bMaskDWord, 0x0f600f60); + PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, ~(BIT8|BIT9), 0x66e60230); + } + else + { + PHY_SetBBReg(priv, rFPGA0_XAB_RFInterfaceSW, bMaskDWord, 0x07600760); + PHY_SetBBReg(priv, rFPGA0_XA_RFInterfaceOE, ~(BIT8|BIT9), 0x66e60230); + } + PHY_SetBBReg(priv, rBndA, 0xF00000, 0x0a); + + //BB pah B register setting:fix TRSW to TX;external LNA off + if(is2T) + { + if(!bInternalPA) + { + PHY_SetBBReg(priv, rFPGA0_XAB_RFInterfaceSW, bMaskDWord, 0x0f600f60); + PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, bMaskDWord, 0x061f0930); + } + else + { + PHY_SetBBReg(priv, rFPGA0_XAB_RFInterfaceSW, bMaskDWord, 0x07600760); + PHY_SetBBReg(priv, rFPGA0_XB_RFInterfaceOE, bMaskDWord, 0x061f0130); + } + PHY_SetBBReg(priv, rBndB, 0xF00000, 0x0a); + } + } + + AP_curve_index = 1; + rx_index = 0x06; + bPlus3db = FALSE; + bDecreaseTxIndex = FALSE; + + if(path == RF92CD_PATH_A) + { + _PHY_PathADDAOn(priv, AFE_REG, TRUE, is2T); + } + else + { + _PHY_PathADDAOn(priv, AFE_REG, FALSE, is2T); + } + + if(path == RF92CD_PATH_B) + PHY_SetBBReg(priv, rFPGA1_DebugSelect, bMaskDWord, 0x00000303); + + //path A/B RF setting + //internal lopback off + if(path == RF92CD_PATH_A && !bInternalPA) + { + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_MODE1, bMask20Bits, 0x5007f); + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_MODE2, bMask20Bits, 0x6f1f9); + } + else if(path == RF92CD_PATH_B) + { + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_MODE1, bMask20Bits, 0x1000f); + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_MODE2, bMask20Bits, 0x60103); + } + + PHY_SetRFReg(priv, path, RF_RXRF_A3, bMask20Bits, 0xef456); + + //Path A/B to standby mode + PHY_SetRFReg(priv, path==RF92CD_PATH_A?RF92CD_PATH_B:RF92CD_PATH_A, + RF_AC, bMask20Bits, 0x10000); + + //set DPK PA bias table + index = priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40?0:1; + if(path == RF92CD_PATH_A) + { + for(i = 0; i < path_num; i++) + { + for(j = 0; j < DP_PA_BIAS_NUM; j++) + PHY_SetRFReg(priv, i, RF_TXBIAS, bMask20Bits, RF_PA_BIAS[index][j]); + } + } + +Step1: + + DPK_DEBUG("==>AP curve select 0x%x bplus3db %d path%s!!\n", RF_AP_curve_select[AP_curve_index], bPlus3db, path==RF92CD_PATH_A?"A":"B"); + + //RF setting for AP curve selection + //default AP curve = 15 + PHY_SetRFReg(priv, path, RF_BS_PA_APSET_G1_G4, bMask20Bits, RF_AP_curve_select[AP_curve_index]); + + ////////////////////////////////////////////////// + // step 1: find RF TX/RX index + ///////////////////////////////////////////////// + //find RF TX index + //============================= + // PAGE_B for Path-A PM setting + //============================= + // open inner loopback @ b00[19]:od 0xb00 0x01097018 + if(bPlus3db) + BB_settings_temp = &(BB_settings_loop_tx_3db[0]); + else + BB_settings_temp = &(BB_settings_loop_tx[0]); + _PHY_SetADDARegisters(priv, BB_REG_loop[path], BB_settings_temp, DP_BB_REG_NUM_loop); + + if(bDecreaseTxIndex) + tx_index = 0x19; + else + tx_index = 0x1f; + bDecreaseTxIndexWithRx = FALSE; + + //Set Tx GAC = 0x1f, than find Rx AGC + rx_index = _PHY_Find_Rx_Power_Index(priv, tx_index, rx_index, path, &bDecreaseTxIndexWithRx); + if(bDecreaseTxIndexWithRx) + { + if(bDecreaseTxIndex) + { + PHY_SetBBReg(priv, offset[path][2], bMaskDWord, 0x01017098); //0xb00, 0xb70 + PHY_SetBBReg(priv, offset[path][8], bMaskDWord, 0x28080000); //0xb68, 0xb6c + + for(i = 3; i < DP_RF_REG_NUM; i++) + PHY_SetRFReg(priv, path, RF_REG[i], bMask20Bits, RF_backup[path][i]); + + //set original DPK bias table + for(j = 0; j < DP_PA_BIAS_NUM; j++) + PHY_SetRFReg(priv, path, RF_TXBIAS, bMask20Bits, RF_PA_BIAS[2][j]); + continue; + } + else + { + bDecreaseTxIndex = TRUE; + goto Step1; + } + } + + //find 2dB loss point + //============================= + // PAGE_B for Path-A PM setting + //============================= + // open inner loopback @ b00[19]:od 0xb00 0x01097018 + if(bPlus3db) + BB_settings_temp = &(BB_settings_loop_tx_2_3db[0]); + else + BB_settings_temp = &(BB_settings_loop_tx_2[0]); + _PHY_SetADDARegisters(priv, BB_REG_loop[path], BB_settings_temp, DP_BB_REG_NUM_loop); + + //RF setting + PHY_SetRFReg(priv, path, RF_AC, bMask20Bits, 0x52000 | tx_index | (rx_index << 5)); + + //----send one shot signal----// + PHY_SetBBReg(priv, offset[path][1], bMaskDWord, 0x80080000); //0xb28, 0xb98 + PHY_SetBBReg(priv, offset[path][1], bMaskDWord, 0x00080000); + + //get power + if(!_PHY_Find_Tx_Power_Index(priv, PA_power[path], path, bPlus3db, bDecreaseTxIndex, &tx_index)) + { + if(/*tx_index == 0x1f &&*/ !bPlus3db) + { + if(bDecreaseTxIndex) + { + if(tx_index < 0x11) + { + PHY_SetBBReg(priv, offset[path][2], bMaskDWord, 0x01017098); //0xb00, 0xb70 + PHY_SetBBReg(priv, offset[path][8], bMaskDWord, 0x28080000); //0xb68, 0xb6c + + for(i = 3; i < DP_RF_REG_NUM; i++) + PHY_SetRFReg(priv, path, RF_REG[i], bMask20Bits, RF_backup[path][i]); + + //set original DPK bias table + for(j = 0; j < DP_PA_BIAS_NUM; j++) + PHY_SetRFReg(priv, path, RF_TXBIAS, bMask20Bits, RF_PA_BIAS[2][j]); + + continue; + } + else + { + //RTPRINT(FINIT, INIT_IQK, ("==>Check pattern reliability path%s SUCCESS tx_index = 0x1b!!!!\n", path==RF90_PATH_A?"A":"B")); + } + } + else if(tx_index < 0x1a) + { + bDecreaseTxIndex = TRUE; + goto Step1; + } + else + { + bPlus3db = TRUE; + goto Step1; + } + } + else if(tx_index == 0x1f) + { + DPK_DEBUG("==>Check pattern reliability path%s FAIL!!!!\n", path==RF92CD_PATH_A?"A":"B"); + PHY_SetBBReg(priv, offset[path][2], bMaskDWord, 0x01017098); //0xb00, 0xb70 + PHY_SetBBReg(priv, offset[path][8], bMaskDWord, 0x28080000); //0xb68, 0xb6c + + for(i = 3; i < DP_RF_REG_NUM; i++) + PHY_SetRFReg(priv, path, RF_REG[i], bMask20Bits, RF_backup[path][i]); + + //set original DPK bias table + for(j = 0; j < DP_PA_BIAS_NUM; j++) + PHY_SetRFReg(priv, path, RF_TXBIAS, bMask20Bits, RF_PA_BIAS[2][j]); + + continue; + } + + + } + else + { + DPK_DEBUG("==>Check pattern reliability path%s SUCCESS!!!!\n", path==RF92CD_PATH_A?"A":"B"); + } + + //find RF RX index + //============================= + // PAGE_B for Path-A PM setting + //============================= + // open inner loopback @ b00[19]:od 0xb00 0x01097018 + if(bPlus3db) + BB_settings_temp = &(BB_settings_loop_rx_3db[0]); + else + BB_settings_temp = &(BB_settings_loop_rx[0]); + + for(i = 0; i < 4; i++) + PHY_SetBBReg(priv, BB_REG_loop[path][i], bMaskDWord, BB_settings_temp[i]); + for(; i < 12; i++) + PHY_SetBBReg(priv, BB_REG_loop[path][i], bMaskDWord, BB_settings_temp[4]); + PHY_SetBBReg(priv, BB_REG_loop[path][i], bMaskDWord, BB_settings_temp[5]); + for(; i < 29; i++) + PHY_SetBBReg(priv, BB_REG_loop[path][i], bMaskDWord, BB_settings_temp[6]); + PHY_SetBBReg(priv, BB_REG_loop[path][i], bMaskDWord, BB_settings_temp[7]); + + rx_index = _PHY_Find_Rx_Power_Index(priv, tx_index, rx_index, path, &bDecreaseTxIndex); + + ////////////////////////////////////// + //2.measure PA model + ////////////////////////////////////// + //========================================= + //PAGE_B for Path-A PAS setting //========================================= + // open inner loopback @ b00[19]:10 od 0xb00 0x01097018 + if(bPlus3db) + BB_settings_temp = &(BB_settings_loop_3db[0]); + else + BB_settings_temp = &(BB_settings_loop[0]); + _PHY_SetADDARegisters(priv, BB_REG_loop[path], BB_settings_temp, DP_BB_REG_NUM_loop); + + //LNA VDD to gnd + PHY_SetRFReg(priv,path, RF_AC, bMask20Bits, 0x52000 | tx_index | (rx_index << 5)); + + //----send one shot signal----// + // Path A + PHY_SetBBReg(priv, offset[path][1], bMaskDWord, 0x80080000); //0xb28, 0xb98 + PHY_SetBBReg(priv, offset[path][1], bMaskDWord, 0x00080000); + + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_T_METER, BIT17|BIT16, 0x03); + + _PHY_DPK_polling(priv); + + priv->pshare->ThermalValue_DPKstore = (unsigned char)PHY_QueryRFReg(priv, RF92CD_PATH_A, RF_T_METER, 0xf800, 1); //0x42: RF Reg[15:11] 92D + + // read PA model and save to PA_model_A[32] + for(i = 0; i < DP_PA_MODEL_RUN_NUM; i++) + { + PHY_SetBBReg(priv, offset[path][2], bMaskDWord, 0x01017018+i); //0xb00, 0xb70 + for(index = 0; index < DP_PA_MODEL_PER_RUN_NUM; index++) + { + PA_model_backup[path][i*4+index] = PHY_QueryBBReg(priv, offset[path][3]+index*4, bMaskDWord); //0xbdc, 0xbec + DPK_DEBUG("==>PA_model_backup index %d value 0x%x()\n", i*4+index, PA_model_backup[path][i*4+index]); + } + } + +#if 0 + //find appropriate AP curve + if(AP_curve_index != (DP_AP_CUREVE_SELECT_NUM-1)) + { + if(!_PHY_DPK_AP_curve_check(priv, PA_model_backup[path], DP_PA_MODEL_NUM)) + { + DPK_DEBUG("==>find appropriate AP curve 0x%x path%s FAIL!!!!\n", RF_AP_curve_select[AP_curve_index], path==RF92CD_PATH_A?"A":"B"); + AP_curve_index++; + if(AP_curve_index < DP_AP_CUREVE_SELECT_NUM) + goto Step1; + } + else + { + DPK_DEBUG("==>find appropriate AP curve path%s SUCCESS!!!!\n", path==RF92CD_PATH_A?"A":"B"); + } + } +#endif + + //check PA model + if(!_PHY_DPK_check(priv, PA_model_backup[path], DP_PA_MODEL_NUM)) + { + PHY_SetBBReg(priv, offset[path][2], bMaskDWord, 0x01017098); // add in 2011-06-02 + PHY_SetBBReg(priv, offset[path][8], bMaskDWord, 0x28080000); //0xb68, 0xb6c + + for(i = 3; i < DP_RF_REG_NUM; i++) + PHY_SetRFReg(priv, path, RF_REG[i], bMaskDWord, RF_backup[path][i]); + DPK_DEBUG("==>PA model path%s FAIL!!!!\n", path==RF92CD_PATH_A?"A":"B"); + priv->pshare->bDPKdone[path] = FALSE; + //set original DPK bias table + for(j = 0; j < DP_PA_BIAS_NUM; j++) + PHY_SetRFReg(priv, path, RF_TXBIAS, bMask20Bits, RF_PA_BIAS[2][j]); + + continue; + } + else + { + DPK_DEBUG("==>PA model path%s SUCCESS!!!!\n", path==RF92CD_PATH_A?"A":"B"); +// priv->pshare->bDPKdone[path] = TRUE; +// priv->pshare->bDPKstore = TRUE; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // step 3: fill PA model to DP Calibration + ///////////////////////////////////////////////////////////////////////////////////////////////////// + //fill BB TX index for the DPK reference + DPK_DEBUG("==>fill PA model to DP Calibration\n"); + + if(path == RF92CD_PATH_A){ + for(index = 0; index < DP_PA_MODEL_RUN_NUM; index++){ + if(index != 3){ + PHY_SetBBReg(priv, 0xe00+index*4, bMaskDWord, 0x3c3c3c3c); + } else { + PHY_SetBBReg(priv, 0xe00+index*4, bMaskDWord, 0x03903c3c); + } + } + PHY_SetBBReg(priv, 0x86c, bMaskDWord, 0x3c3c3c3c); + }else if (path == RF92CD_PATH_B){ + for(index = 0; index < 4; index++) { + PHY_SetBBReg(priv, 0x830+index*4, bMaskDWord, 0x3c3c3c3c); + } + for(index = 0; index < 2; index++) { + PHY_SetBBReg(priv, 0x848+index*4, bMaskDWord, 0x3c3c3c3c); + } + for(index = 0; index < 2; index++) { + PHY_SetBBReg(priv, 0x868+index*4, bMaskDWord, 0x3c3c3c3c); + } + } + + // SRAM boundary setting + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x400000); + + if(priv->pshare->phw->bNewTxGainTable) + PHY_SetBBReg(priv, offset[path][4], bMaskDWord, 0x0008421f); //0xbc0, 0xbc4 + else + PHY_SetBBReg(priv, offset[path][4], bMaskDWord, 0x0009ce7f); //0xbc0, 0xbc4 + + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + + _PHY_SetADDARegisters(priv, BB_REG_loop[path], BB_settings_loop_pa, DP_BB_REG_NUM_loop_pa); + + // fill PA model to page B1 registers + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0x400000); + for(index = 0; index < (DP_PA_MODEL_NUM/2); index++){ //path A = 0xb00, path B = 0xb60 + PHY_SetBBReg(priv, 0xb00+index*4+path*0x60, bMaskDWord, + (PA_model_backup[path][index*2+1] << 16) | PA_model_backup[path][index*2]); + } + PHY_SetBBReg(priv, 0xe28, 0xffffff00, 0); + + //one shot + PHY_SetBBReg(priv, offset[path][1], bMaskDWord, 0x80044499); //0xb28, 0xb98 + PHY_SetBBReg(priv, offset[path][1], bMaskDWord, 0x00044499); + + _PHY_DPK_polling(priv); + +#if 1 + ////////////////////////////////////////////////////// + // step 4: calculate gain loss caused by DP + ////////////////////////////////////////////////////// + PHY_SetBBReg(priv, offset[path][2], bMaskDWord, 0x0029701f); //0xb00, 0xb70 + tmpReg = PHY_QueryBBReg(priv, offset[path][5], bMaskDWord); //0xbe8, 0xbf8 + + power_I = (tmpReg >> 16); + if(power_I & BIT(15)) + power_I |= bMaskLWord; ////////ZZZZZZZZZZZZZZZZZZ + + power_Q = tmpReg & bMaskLWord; + if(power_Q & BIT(15)) + power_Q |= bMaskHWord; + + DPK_DEBUG("0x%x = 0x%x power_I = 0x%x power_Q = 0x%x\n", offset[path][5], tmpReg, power_I, power_Q); + + tmpReg = power_I*power_I + power_Q*power_Q; + + DPK_DEBUG("gain loss = 0x%x \n", tmpReg); + + if(tmpReg < 26090) + { + PHY_SetBBReg(priv, offset[path][2], bMaskDWord, 0x01017098); //0xb00, 0xb70 + PHY_SetBBReg(priv, offset[path][8], bMaskDWord, 0x28080000); //0xb68, 0xb6c + + for(i = 3; i < DP_RF_REG_NUM; i++) + PHY_SetRFReg(priv, path, RF_REG[i], bMask20Bits, RF_backup[path][i]); + priv->pshare->bDPKdone[path] = FALSE; + //set original DPK bias table + for(j = 0; j < DP_PA_BIAS_NUM; j++) + PHY_SetRFReg(priv, path, RF_TXBIAS, bMask20Bits, RF_PA_BIAS[2][j]); + + continue; + } + else + { + priv->pshare->bDPKdone[path] = TRUE; + priv->pshare->bDPKstore = TRUE; + } + + for(i = 0; i < DP_GAIN_LOSS_BOUND_NUM; i++) + { +#if DP_gain_loss == 1 + if(tmpReg > gain_loss_bound[i]/* || i == (DP_GAIN_LOSS_BOUND_NUM -1)*/) +#else + if(tmpReg > gain_loss_bound[i] || i == (DP_GAIN_LOSS_BOUND_NUM -1)) +#endif + { +#if DP_gain_loss == 0 + if(i == 0) + break; + + index = OFDM_index[path] > i?OFDM_index[path]-i:0; + if(index < OFDM_min_index_internalPA) + index = OFDM_min_index_internalPA; + PHY_SetBBReg(priv, offset[path][6], bMaskDWord, OFDMSwingTable[index]); //0xc80, 0xc88 + DPK_DEBUG("original index 0x%x gain_loss minus index 0x%x\n", priv->pshare->OFDM_index[0], i); +#endif + break; + } + } + +#if DP_gain_loss == 1 + + DPK_DEBUG("gain_loss Compensated coefficient %d\n", gain_loss_coef[i]); + coef = gain_loss_coef[i]; + GainLossIndex = i; + priv->pshare->OFDM_min_index_internalPA_DPK[path] = GainLossIndex == 0?0:(GainLossIndex/2+GainLossIndex%2); + + //read DP LUT value from register + for(i = 0; i < DP_PA_MODEL_RUN_NUM; i++) + { + PHY_SetBBReg(priv, offset[path][2], bMaskDWord, 0x00297018+i); //0xb00, 0xb70 + for(index = 0; index < DP_PA_MODEL_PER_RUN_NUM; index++) + { + tmpReg = (i == 0 && index==0)?0x01000000:PHY_QueryBBReg(priv, offset[path][3]+index*4, bMaskDWord); //0xbdc, 0xbec + + gain_loss_backup[1][i*4+index] = (tmpReg >> 16); //I + if(gain_loss_backup[1][i*4+index] & BIT(15)) + gain_loss_backup[1][i*4+index] |= bMaskHWord; + + gain_loss_backup[0][i*4+index] = (tmpReg & bMaskLWord); //Q + if(gain_loss_backup[0][i*4+index] & BIT(15)) + gain_loss_backup[0][i*4+index] |= bMaskHWord; + DPK_DEBUG("==>DP LUT index %d value 0x%x() I = 0x%x, Q = 0x%x\n", i*4+index, tmpReg, gain_loss_backup[1][i*4+index], gain_loss_backup[0][i*4+index]); + + //gain * LUT + for(j = 0; j < 2; j++) + { + // RTPRINT(FINIT, INIT_IQK, ("==>0DP LUT sram %s index %d value %d()\n", j == 0?"Q":"I", i*4+index, gain_loss_backup[j][i*4+index])); + + gain_loss_backup[j][i*4+index] = (gain_loss_backup[j][i*4+index] * coef) / (int)(512); + // RTPRINT(FINIT, INIT_IQK, ("==>1DP LUT sram %s index %d value 0x%x()\n", j == 0?"Q":"I", i*4+index, gain_loss_backup[j][i*4+index])); + + gain_loss_backup[j][i*4+index] = gain_loss_backup[j][i*4+index] >= (int)(512)?(int)(511):gain_loss_backup[j][i*4+index] < (int)(-512)?(int)(-512):gain_loss_backup[j][i*4+index]; + // RTPRINT(FINIT, INIT_IQK, ("==>2DP LUT sram %s index %d value 0x%x()\n", j == 0?"Q":"I", i*4+index, gain_loss_backup[j][i*4+index])); + + gain_loss_backup[j][i*4+index] = gain_loss_backup[j][i*4+index] >> 2; + // RTPRINT(FINIT, INIT_IQK, ("==>3DP LUT sram %s index %d value 0x%x()\n", j == 0?"Q":"I", i*4+index, gain_loss_backup[j][i*4+index])); + + } + tmpReg = ((gain_loss_backup[1][i*4+index] & bMaskByte0) << 8 ) | ((gain_loss_backup[0][i*4+index] & bMaskByte0)); + gain_loss_backup[0][i*4+index] = tmpReg & bMaskLWord; + DPK_DEBUG("==>DP LUT sram index %d value 0x%x()\n", i*4+index, tmpReg); + } + } + + //write DP LUT into sram + for(i = 0; i < DP_PA_MODEL_NUM; i++) + { + value32 = (path==RF92CD_PATH_A?((i%2 == 0)?0x01000000:0x02000000): + ((i%2 == 0)?0x04000000:0x08000000)) | + gain_loss_backup[0][(DP_PA_MODEL_NUM-1)-i] |( (i/2) << 16); + DPK_DEBUG("0xb2c value = 0x%x\n", value32); + PHY_SetBBReg(priv, 0xb2c , bMaskDWord, value32); + } +// PHY_SetBBReg(priv, 0xb2c , bMaskDWord, 0x00000000); + +#endif + +#endif + + /////////////////////////////////////////////////////////////// + // step 5: Enable Digital Predistortion + /////////////////////////////////////////////////////////////// + // LUT from sram +#if DP_gain_loss == 1 + { + _PHY_SetADDARegisters(priv, BB_REG_loop[path], BB_settings_loop_dp, DP_BB_REG_NUM_loop_pa); + + // pwsf boundary + PHY_SetBBReg(priv, offset[path][7], bMaskDWord, 0x000fffff); //0xb30, 0xba0 + + // write pwsf to sram + //find tx_index index value + SramIndex = 24; //restore default value + SramIndex -= GainLossIndex; + if(bPlus3db) + SramIndex += 3*4; + + SramIndex = SramIndex >= DP_SRAM_NUM_db?DP_SRAM_NUM_db-1:(SramIndex<0?0:SramIndex); + + DPK_DEBUG("tx_index = 0x%x, sram value 0x%x gainloss index %d bPlus3db %d\n", tx_index, Sram_db_settings[SramIndex], GainLossIndex, bPlus3db); + + index = 0x1f - tx_index; + if(SramIndex >= index*4) + { + index = SramIndex - index*4; + index_repeat = -2; + SramIndex = -2; + } + else + { + index_repeat = index - SramIndex/4; + SramIndex %= 4; + index = 0; + } + + index = index >= DP_SRAM_NUM_db?DP_SRAM_NUM_db-1:index; + if(index_repeat == 1) + index_1 = SramIndex; + else + index_1 = index < (DP_SRAM_NUM_db-1)?(index_repeat==-2?index+1*4:index):index; + + DPK_DEBUG("0x1f value = 0x%x, index 0x%x repeat %d SramIndex %d\n", Sram_db_settings[index], index, index_repeat, SramIndex); + + for(i = 0; i < DP_SRAM_NUM; i++) + { + value32 = (path==RF92CD_PATH_A?0x10000000:0x20000000) | (i << 16) | + (Sram_db_settings[index_1] << 8 )| Sram_db_settings[index]; + DPK_DEBUG("0xb2c value = 0x%x\n", value32); + + PHY_SetBBReg(priv, 0xb2c , bMaskDWord, value32); + if(index_repeat >= 0) + index_repeat -= 2; + else if(index_repeat == -1) + index_repeat = -2; + + if((index < (DP_SRAM_NUM_db-1)-1)) + { + if(index_repeat == -2) + { + index+=2*4; + index_1 = index < (DP_SRAM_NUM_db-1)?index+1*4:index; + } + if(index_repeat == 0) + { + index = SramIndex; + index_1 = index < (DP_SRAM_NUM_db-1)?index+1*4:index; + } + else if(index_repeat == 1) + { + index_1 = SramIndex; + } + else if(index_repeat == -1) + { + index = index_1+1*4; + index_1 = index < (DP_SRAM_NUM_db-1)?index+1*4:index; + } + } + else + { + index = index_1 = (DP_SRAM_NUM_db-1); + } + + index = index < DP_SRAM_NUM_db?index:DP_SRAM_NUM_db-1; + index_1 = index_1 < DP_SRAM_NUM_db?index_1:DP_SRAM_NUM_db-1; + } + } +#else + if(!SkipStep5) + { + _PHY_SetADDARegisters(priv, BB_REG_loop[path], BB_settings_loop_dp, DP_BB_REG_NUM_loop_pa); + + // pwsf boundary + PHY_SetBBReg(priv, offset[path][7], bMaskDWord, 0x000fffff); //0xb30, 0xba0 + + // write pwsf to sram + //find RF0x1f index value + if(bPlus3db) + tx_index += 3; + +// tx_index = 0x21; + + index = 0x1f - tx_index; + if(index_for_zero_db >= index) + { + index = index_for_zero_db - index; + index_repeat = -2; + } + else + { + index_repeat = index - index_for_zero_db; + index = 0; + } + + index = index >= DP_SRAM_NUM_db?DP_SRAM_NUM_db-1:index; + index_1 = index < (DP_SRAM_NUM_db-1)?(index_repeat==-2?index+1:index):index; + + DPK_DEBUG("0x1f value = 0x%x, index 0x%x repeat %d\n", Sram_db_settings[index], index, index_repeat); + + for(i = 0; i < DP_SRAM_NUM; i++) + { + value32 = (path==RF92CD_PATH_A?0x10000000:0x20000000) | (i << 16) | + (Sram_db_settings[index_1] << 8 )| Sram_db_settings[index]; + DPK_DEBUG("0xb2c value = 0x%x\n", value32); + + PHY_SetBBReg(priv, 0xb2c , bMaskDWord, value32); + if(index_repeat >= 0) + index_repeat -= 2; + else if(index_repeat == -1) + index_repeat = -2; + + if((index < (DP_SRAM_NUM_db-1)-1)) + { + if(index_repeat == -2) + { + index += 2; + index_1 = index < (DP_SRAM_NUM_db-1)?index+1:index; + } + if(index_repeat == 0) + { + index_1 = index < (DP_SRAM_NUM_db-1)?index+1:index; + } + else if(index_repeat == -1) + { + index++; + index_1 = index < (DP_SRAM_NUM_db-1)?index+1:index; + } + } + else + { + index = index_1 = (DP_SRAM_NUM_db-1); + } + } + } +#endif + } + + //reload RF default value + for(path = 0; pathpshare->phw->InternalPA5G[RF92CD_PATH_B]) + { + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_MODE1, bMask20Bits, 0x1000f); + PHY_SetRFReg(priv, RF92CD_PATH_A, RF_MODE2, bMask20Bits, 0x60101); + } + + //reload BB default value + for(index=0; indexpshare->bDPKworking = FALSE; + + DPK_DEBUG("<==_PHY_DigitalPredistortion()\n"); +} + +#endif +#endif + +#endif diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/HalDMOutSrc.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/HalDMOutSrc.c new file mode 100755 index 000000000..57550569f --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/HalDMOutSrc.c @@ -0,0 +1,1956 @@ +//============================================================ +// +// File Name: HalDMOutSrc_AP.c +// +// Description: +// +// This file is for common outsource dynamic mechanism for partner. +// +// +//============================================================ + +#ifndef _HALDM_COMMON_C_ +#define _HALDM_COMMON_C_ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "8192cd_cfg.h" +#include "8192cd.h" +#include "8192cd_hw.h" +#include "8192cd_headers.h" +#include "8192cd_debug.h" + +#ifdef USE_OUT_SRC +#include "./OUTSRC/phydm_precomp.h" +#else +#define TX_POWER_NEAR_FIELD_THRESH_AP HP_LOWER +#endif + +#if defined(CONFIG_RTL_819X) && defined(USE_RLX_BSP) +#if defined(CONFIG_OPENWRT_SDK) && !defined(CONFIG_ARCH_CPU_RLX) +#include +#else +#include +#endif //CONFIG_OPENWRT_SDK +#endif + +#ifdef HW_ANT_SWITCH +#define RXDVY_A_EN ((HW_DIV_ENABLE && !priv->pshare->rf_ft_var.antSw_select) ? 0x80 : 0) +#define RXDVY_B_EN ((HW_DIV_ENABLE && priv->pshare->rf_ft_var.antSw_select) ? 0x80 : 0) +#endif + + +//3 ============================================================ +//3 DIG related functions +//3 ============================================================ + +int getIGIFor1RCCA(int value_IGI) +{ + #define ONERCCA_LOW_TH 0x30 + #define ONERCCA_LOW_DIFF 8 + + if (value_IGI < ONERCCA_LOW_TH) { + if ((ONERCCA_LOW_TH - value_IGI) < ONERCCA_LOW_DIFF) + return ONERCCA_LOW_TH; + else + return value_IGI + ONERCCA_LOW_DIFF; + } else { + return value_IGI; + } +} + +#if 1 + +#if defined(DETECT_STA_EXISTANCE) && defined(CONFIG_WLAN_HAL) +// Check for STA existance. If STA disappears, disconnect it. Added by Annie, 2010-08-10. +void DetectSTAExistance88XX(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat) +{ + //unsigned char tmpbuf[16]; + + // Parameters + const unsigned int maxTxFailCnt = 300; // MAX Tx fail packet count + const unsigned int minTxFailCnt = 30; // MIN Tx fail packet count; this value should be less than maxTxFailCnt. + const unsigned int txFailSecThr= 3; // threshold of Tx Fail Time (in second) + //const unsigned int NoTXOKSecThr= 5; // threshold of NO Tx ok Time (in second) + //const unsigned int NoRXOKSecThr= 5; // threshold of NO Tx ok Time (in second) + + // Temporarily change Retry Limit when TxFail. (tfrl: TxFailRetryLimit) + //const unsigned char TFRL = 7; // New Retry Limit value + //const unsigned char TFRL_FailCnt = 2; // Tx Fail Count threshold to set Retry Limit + //const unsigned char TFRL_SetTime = 2; // Time to set Retry Limit (in second) + //const unsigned char TFRL_RcvTime = 3; // Time to recover Retry Limit (in second) + + //const unsigned short Back_retty_value = 0x10; + +#ifdef MCR_WIRELESS_EXTEND + if (pstat->IOTPeer==HT_IOT_PEER_CMW) + return; +#endif + if( report->txok != 0 ) + { // Reset Counter + pstat->tx_conti_fail_cnt = 0; + pstat->tx_last_good_time = priv->up_time; + if (pstat->leave) { +#if defined(CONFIG_PCI_HCI) + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, INCREASE); +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_update_sta_msr(priv, pstat, INCREASE); +#endif + pstat->leave = 0; + } + } + else if( report->txfail != 0 ) + { + if (pstat->leave) + return; + + pstat->tx_conti_fail_cnt += report->txfail; + DEBUG_WARN( "detect: txfail=%d, tx_conti_fail_cnt=%d\n", report->txfail, pstat->tx_conti_fail_cnt ); + + //RTL_W16(RL, (TFRL&SRL_Mask)<up_time >= (pstat->tx_last_good_time+TFRL_SetTime) && + pstat->tx_conti_fail_cnt >= TFRL_FailCnt && + #if defined(CONFIG_RTL8672) || defined (NOT_RTK_BSP) + !pstat->ht_cap_len && // legacy rate only + #endif + !priv->pshare->bRLShortened ) + { // Shorten retry limit, because AP spending too much time to send out g mode STA pending packets in HW queue. + + priv->pshare->bRLShortened = TRUE; + printk( "== Shorten RetryLimit to 0x%04X ==\n", RTL_R16(RL) ); + } + #endif + + if( (pstat->tx_conti_fail_cnt >= maxTxFailCnt) || + (pstat->tx_conti_fail_cnt >= minTxFailCnt && priv->up_time >= (pstat->tx_last_good_time+txFailSecThr) ) + ) + { + // This STA is considered as disappeared, so delete it. + DEBUG_WARN( "** tx_conti_fail_cnt=%d (min=%d,max=%d)\n", pstat->tx_conti_fail_cnt, minTxFailCnt, maxTxFailCnt); + DEBUG_WARN( "** tx_last_good_time=%d, up_time=%d (Thr:%d)\n", (int)pstat->tx_last_good_time, (int)priv->up_time, txFailSecThr ); + DEBUG_WARN( "AP is going to del_sta %02X:%02X:%02X:%02X:%02X:%02X\n", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5] ); + + // del_sta(priv, tmpbuf); + ++(pstat->leave); + +#if defined(CONFIG_PCI_HCI) + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, DECREASE); + pstat->bDrop = 1; +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_update_sta_msr(priv, pstat, DECREASE); +#endif + //printk("Drop client packet, AID = %x TxFailCnt= %x \n",pstat->aid,pstat->tx_conti_fail_cnt); + //RTL_W16(RL, (Back_retty_value&SRL_Mask)<tx_conti_fail_cnt = 0; + pstat->tx_last_good_time = priv->up_time; + + } + } + else + { +#if 0 + //printk("AID[%x](pstat->leave)=%x priv->up_time=%x (pstat->tx_last_good_time+NoTXOKSecThr)=%x \n",pstat->aid,(pstat->leave),priv->up_time,(pstat->tx_last_good_time+NoTXOKSecThr)); + if (!(pstat->leave) && (priv->up_time > (pstat->tx_last_good_time+NoTXOKSecThr)) + && (priv->up_time > (pstat->rx_last_good_time+NoRXOKSecThr)) ) + { + DEBUG_WARN("%s %d expire timeout, set MACID 0 AID = %x \n",__FUNCTION__,__LINE__,REMAP_AID(pstat)); + GET_HAL_INTERFACE(priv)->UpdateHalMSRRPTHandler(priv, pstat, DECREASE); + pstat->bDrop = 1; + printk("Client no TRX over 10 Secs , Drop client packet, AID = %x \n",pstat->aid); + ++(pstat->leave); + } +#endif + } +} +#endif +#if defined(DETECT_STA_EXISTANCE) && (defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT)) +void DetectSTAExistance(struct rtl8192cd_priv *priv, struct tx_rpt *report, struct stat_info *pstat) +{ + const unsigned int maxTxFailCnt = 300; // MAX Tx fail packet count + const unsigned int minTxFailCnt = 30; // MIN Tx fail packet count; this value should be less than maxTxFailCnt. + const unsigned int txFailSecThr= 3; // threshold of Tx Fail Time (in second) + const unsigned char TFRL = 7; // New Retry Limit value + const unsigned char TFRL_FailCnt = 2; // Tx Fail Count threshold to set Retry Limit + const unsigned char TFRL_SetTime = 2; // Time to set Retry Limit (in second) + const unsigned char TFRL_RcvTime = 10; // Time to recover Retry Limit (in second) + if(OPMODE & WIFI_STATION_STATE) + return; + if( report->txok != 0 ) + { // Reset Counter + pstat->tx_conti_fail_cnt = 0; + pstat->tx_last_good_time = priv->up_time; + pstat->leave = 0; + } + else if( report->txfail != 0 ) + { + pstat->tx_conti_fail_cnt += report->txfail; + DEBUG_WARN( "detect: txfail=%d, tx_conti_fail_cnt=%d\n", report->txfail, pstat->tx_conti_fail_cnt ); + + if (pstat->leave) + return; + + if( CHIP_VER_92X_SERIES(priv) && (priv->up_time >= (pstat->tx_last_good_time+TFRL_SetTime)) && + pstat->tx_conti_fail_cnt >= TFRL_FailCnt && + #if defined(CONFIG_RTL8672) || defined (NOT_RTK_BSP) + !pstat->ht_cap_len && // legacy rate only + #endif + !priv->pshare->bRLShortened ) + { // Shorten retry limit, because AP spending too much time to send out g mode STA pending packets in HW queue. + RTL_W16(RL, (TFRL&SRL_Mask)<pshare->bRLShortened = TRUE; + DEBUG_WARN( "== Shorten RetryLimit to 0x%04X ==\n", RTL_R16(RL) ); + } + if( (pstat->tx_conti_fail_cnt >= maxTxFailCnt) || + (pstat->tx_conti_fail_cnt >= minTxFailCnt && priv->up_time >= (pstat->tx_last_good_time+txFailSecThr) ) + ) + { // This STA is considered as disappeared, so delete it. + DEBUG_WARN( "** tx_conti_fail_cnt=%d (min=%d,max=%d)\n", pstat->tx_conti_fail_cnt, minTxFailCnt, maxTxFailCnt); + DEBUG_WARN( "** tx_last_good_time=%d, up_time=%d (Thr:%d)\n", (int)pstat->tx_last_good_time, (int)priv->up_time, txFailSecThr ); + DEBUG_WARN( "AP is going to del_sta %02X:%02X:%02X:%02X:%02X:%02X\n", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5] ); + ++(pstat->leave); + pstat->tx_conti_fail_cnt = 0; + pstat->tx_last_good_time = priv->up_time; + } + } +} +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + +// Timer callback function to recover hardware retry limit register. Added by Annie, 2010-08-10. +void RetryLimitRecovery(unsigned long task_priv) +{ + struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; + if( priv->pshare->bRLShortened ) + { +// RTL_W16(RL, (priv->pshare->RLShort&SRL_Mask)<pshare->RLLong&LRL_Mask)<pshare->RL_setting); + priv->pshare->bRLShortened = FALSE; + DEBUG_WARN( "== Recover RetryLimit to 0x%04X ==\n", RTL_R16(RL) ); + } +} + + +// Chack STA leaving status; per interface. Added by Annie, 2010-08-10. +unsigned char NoLeavingSTA(struct rtl8192cd_priv *priv) +{ + unsigned char bStaAllOK = TRUE; + struct list_head *phead, *plist; + struct stat_info *pstat; +#ifdef SMP_SYNC + unsigned long flags = 0; +#endif + + phead = &priv->asoc_list; + if (!netif_running(priv->dev) || list_empty(phead)) + return bStaAllOK; + + SMP_LOCK_ASOC_LIST(flags); + + plist = phead->next; + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if( pstat->tx_conti_fail_cnt != 0 ) { + if (pstat->leave) + pstat->tx_conti_fail_cnt = 0; + bStaAllOK = FALSE; + break; + } + } + + SMP_UNLOCK_ASOC_LIST(flags); + return bStaAllOK; +} + + +// Chack STA leaving status for all active interface and recover retry limit register value. Added by Annie, 2010-08-10. +void LeavingSTA_RLCheck(struct rtl8192cd_priv *priv) +{ + unsigned char bIfAllOK = TRUE; + static int AllOKTimes = 0; +#ifdef MBSSID + int i; +#endif + // Parameter + const unsigned char TFRL_RcvTime = 10; // Time to recover Retry Limit (in second) + + if (FALSE == priv->pshare->bRLShortened) + return; + + if( !NoLeavingSTA(priv) ) + bIfAllOK = FALSE; +#ifdef UNIVERSAL_REPEATER + else if (IS_DRV_OPEN(GET_VXD_PRIV(priv)) && + !NoLeavingSTA(GET_VXD_PRIV(priv))) { + bIfAllOK = FALSE; + } +#endif +#ifdef MBSSID + else if (priv->pmib->miscEntry.vap_enable) { + for (i=0; ipvap_priv[i])) { + if( !NoLeavingSTA(priv->pvap_priv[i]) ) { + bIfAllOK = FALSE; + break; + } + } + } + } +#endif + + if( bIfAllOK ) { + AllOKTimes ++; + + if( AllOKTimes >= TFRL_RcvTime ) +#ifdef __KERNEL__ + RetryLimitRecovery((unsigned long)priv); +#elif defined(__ECOS) + RetryLimitRecovery((void *)priv); +#endif + } + else { + AllOKTimes = 0; + } +} +#endif + +#endif //#if defined(DETECT_STA_EXISTANCE) + +#endif + + + +void set_DIG_state(struct rtl8192cd_priv *priv, int state) +{ + int value_IGI; + + if (state) { + priv->pshare->DIG_on = 1; +#if defined(USE_OUT_SRC) + if(IS_OUTSRC_CHIP(priv) && priv->pshare->restore) { + ODM_Write_DIG(ODMPTR, priv->pshare->restore); +// panic_printk("%s, 1-> %x, %x\n", __FUNCTION__, RTL_R8(0xc50), priv->pshare->restore); + } +#endif + priv->pshare->restore = 0; + } else { + priv->pshare->DIG_on = 0; + if (priv->pshare->restore == 0) { +#if defined(CONFIG_RTL_92C_SUPPORT) && defined(HIGH_POWER_EXT_LNA) + if ((GET_CHIP_VER(priv)==VERSION_8192C) && priv->pshare->rf_ft_var.use_ext_lna == 1) + value_IGI = 0x30; + else +#endif + value_IGI = 0x20; + + priv->pshare->restore = PHY_QueryBBReg(priv, 0xc50, 0x7f); +#if defined(USE_OUT_SRC) + if(IS_OUTSRC_CHIP(priv) ) { + ODM_Write_DIG(ODMPTR, value_IGI); + //panic_printk("%s, 0-> %x, %x\n", __FUNCTION__, RTL_R8(0xc50), priv->pshare->restore); + } +#endif +#if defined(CONFIG_RTL_92C_SUPPORT) || defined(CONFIG_RTL_92D_SUPPORT) + if(CHIP_VER_92X_SERIES(priv)) { + if (priv->pshare->rf_ft_var.one_path_cca == 0) { + PHY_SetBBReg(priv, 0xc50, 0x7f, value_IGI); + PHY_SetBBReg(priv, 0xc58, 0x7f, value_IGI); + } else if (priv->pshare->rf_ft_var.one_path_cca == 1) { + PHY_SetBBReg(priv, 0xc50, 0x7f, value_IGI); + PHY_SetBBReg(priv, 0xc58, 0x7f, getIGIFor1RCCA(value_IGI)); + } else if (priv->pshare->rf_ft_var.one_path_cca == 2) { + PHY_SetBBReg(priv, 0xc50, 0x7f, getIGIFor1RCCA(value_IGI)); + PHY_SetBBReg(priv, 0xc58, 0x7f, value_IGI); + } + } +#endif + } +#ifdef INTERFERENCE_CONTROL + priv->pshare->phw->signal_strength = 0; +#endif + } +} + +void check_DIG_by_rssi(struct rtl8192cd_priv *priv, unsigned char rssi_strength) +{ + unsigned int dig_on = 0; + + if (OPMODE & WIFI_SITE_MONITOR) + return; + +#if defined(CONFIG_RTL_8812_SUPPORT)||defined(CONFIG_WLAN_HAL_8881A)||defined(CONFIG_WLAN_HAL_8814AE) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A)||(GET_CHIP_VER(priv)== VERSION_8814A)) + return; +#endif + + if ((rssi_strength > priv->pshare->rf_ft_var.digGoUpperLevel) + && (rssi_strength < TX_POWER_NEAR_FIELD_THRESH_AP+1) && (priv->pshare->phw->signal_strength != 2)) { +#ifndef CONFIG_RTL_92D_SUPPORT + if (priv->pshare->is_40m_bw) + // RTL_W8(0xc87, (RTL_R8(0xc87) & 0xf) | 0x30); 92D + RTL_W8(0xc87, 0x30); + else + RTL_W8(0xc30, 0x44); +#endif + + if (priv->pshare->phw->signal_strength != 3) + dig_on++; + + priv->pshare->phw->signal_strength = 2; + } + else if ((rssi_strength > TX_POWER_NEAR_FIELD_THRESH_AP+5) && (priv->pshare->phw->signal_strength != 3)) { +#ifndef CONFIG_RTL_92D_SUPPORT + if (priv->pshare->is_40m_bw) + // RTL_W8(0xc87, (RTL_R8(0xc87) & 0xf) | 0x30); 92D + RTL_W8(0xc87, 0x30); + else + RTL_W8(0xc30, 0x44); +#endif + + if (priv->pshare->phw->signal_strength != 2) + dig_on++; + + priv->pshare->phw->signal_strength = 3; + } + else if (((rssi_strength < priv->pshare->rf_ft_var.digGoLowerLevel) + && (priv->pshare->phw->signal_strength != 1)) || !priv->pshare->phw->signal_strength) { + // DIG off +#if 0 + set_DIG_state(priv, 0); +#endif + +#ifndef CONFIG_RTL_92D_SUPPORT + if (priv->pshare->is_40m_bw) + //RTL_W8(0xc87, (RTL_R8(0xc87) & 0xf) | 0x30); 92D + RTL_W8(0xc87, 0x30); + else + RTL_W8(0xc30, 0x44); +#endif + + priv->pshare->phw->signal_strength = 1; + } + + if (dig_on) { + // DIG on + set_DIG_state(priv, 1); + } + + //check_DC_TH_by_rssi(priv, rssi_strength); +} + + +void DIG_for_site_survey(struct rtl8192cd_priv *priv, int do_ss) +{ + if (do_ss) { + // DIG off + set_DIG_state(priv, 0); + } + else { + // DIG on +#ifndef INTERFERENCE_CONTROL +// if (priv->pshare->phw->signal_strength > 1) +#endif + { + set_DIG_state(priv, 1); + } + } +} + + extern unsigned char CCKSwingTable_Ch14 [][8]; + extern unsigned char CCKSwingTable_Ch1_Ch13[][8]; +#ifndef CCK_TABLE_SIZE +#define CCK_TABLE_SIZE 33 +#endif + + int get_CCK_swing_index(struct rtl8192cd_priv *priv) + { + int TempCCk, index=12, i; + short channel; +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) + channel=priv->pshare->working_channel; + else +#endif + channel = (priv->pmib->dot11RFEntry.dot11channel); + + //Query CCK default setting From 0xa24 + TempCCk = PHY_QueryBBReg(priv, rCCK0_TxFilter2, bMaskDWord)&bMaskCCK; + TempCCk = cpu_to_le32(TempCCk); + for(i=0 ; ipshare->rf_ft_var.mp_specific) + channel=priv->pshare->working_channel; + else +#endif + channel = (priv->pmib->dot11RFEntry.dot11channel); + +#ifdef USE_OUT_SRC +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) == VERSION_8188E) { + CCK_index = ((CCK_index > (CCK_TABLE_SIZE - 1)) ? (CCK_TABLE_SIZE - 1) : CCK_index); + if (channel !=14) { + RTL_W8( 0xa22, CCKSwingTable_Ch1_Ch13_New[CCK_index][0]); + RTL_W8( 0xa23, CCKSwingTable_Ch1_Ch13_New[CCK_index][1]); + RTL_W8( 0xa24, CCKSwingTable_Ch1_Ch13_New[CCK_index][2]); + RTL_W8( 0xa25, CCKSwingTable_Ch1_Ch13_New[CCK_index][3]); + RTL_W8( 0xa26, CCKSwingTable_Ch1_Ch13_New[CCK_index][4]); + RTL_W8( 0xa27, CCKSwingTable_Ch1_Ch13_New[CCK_index][5]); + RTL_W8( 0xa28, CCKSwingTable_Ch1_Ch13_New[CCK_index][6]); + RTL_W8( 0xa29, CCKSwingTable_Ch1_Ch13_New[CCK_index][7]); + } + else{ + RTL_W8( 0xa22, CCKSwingTable_Ch14_New[CCK_index][0]); + RTL_W8( 0xa23, CCKSwingTable_Ch14_New[CCK_index][1]); + RTL_W8( 0xa24, CCKSwingTable_Ch14_New[CCK_index][2]); + RTL_W8( 0xa25, CCKSwingTable_Ch14_New[CCK_index][3]); + RTL_W8( 0xa26, CCKSwingTable_Ch14_New[CCK_index][4]); + RTL_W8( 0xa27, CCKSwingTable_Ch14_New[CCK_index][5]); + RTL_W8( 0xa28, CCKSwingTable_Ch14_New[CCK_index][6]); + RTL_W8( 0xa29, CCKSwingTable_Ch14_New[CCK_index][7]); + } + } else +#endif +#ifdef CONFIG_WLAN_HAL_8192EE + if (GET_CHIP_VER(priv) == VERSION_8192E) { + CCK_index = ((CCK_index > (CCK_TABLE_SIZE_92E - 1)) ? (CCK_TABLE_SIZE_92E - 1) : CCK_index); + if (channel !=14) { + RTL_W8( 0xa22, CCKSwingTable_Ch1_Ch13_92E[CCK_index][0]); + RTL_W8( 0xa23, CCKSwingTable_Ch1_Ch13_92E[CCK_index][1]); + RTL_W8( 0xa24, CCKSwingTable_Ch1_Ch13_92E[CCK_index][2]); + RTL_W8( 0xa25, CCKSwingTable_Ch1_Ch13_92E[CCK_index][3]); + RTL_W8( 0xa26, CCKSwingTable_Ch1_Ch13_92E[CCK_index][4]); + RTL_W8( 0xa27, CCKSwingTable_Ch1_Ch13_92E[CCK_index][5]); + RTL_W8( 0xa28, CCKSwingTable_Ch1_Ch13_92E[CCK_index][6]); + RTL_W8( 0xa29, CCKSwingTable_Ch1_Ch13_92E[CCK_index][7]); + } + else{ + RTL_W8( 0xa22, CCKSwingTable_Ch14_92E[CCK_index][0]); + RTL_W8( 0xa23, CCKSwingTable_Ch14_92E[CCK_index][1]); + RTL_W8( 0xa24, CCKSwingTable_Ch14_92E[CCK_index][2]); + RTL_W8( 0xa25, CCKSwingTable_Ch14_92E[CCK_index][3]); + RTL_W8( 0xa26, CCKSwingTable_Ch14_92E[CCK_index][4]); + RTL_W8( 0xa27, CCKSwingTable_Ch14_92E[CCK_index][5]); + RTL_W8( 0xa28, CCKSwingTable_Ch14_92E[CCK_index][6]); + RTL_W8( 0xa29, CCKSwingTable_Ch14_92E[CCK_index][7]); + } + } else +#endif +#endif + { + CCK_index = ((CCK_index > (CCK_TABLE_SIZE - 1)) ? (CCK_TABLE_SIZE - 1) : CCK_index); + if(channel !=14) { + RTL_W8( 0xa22, CCKSwingTable_Ch1_Ch13[CCK_index][0]); + RTL_W8( 0xa23, CCKSwingTable_Ch1_Ch13[CCK_index][1]); + RTL_W8( 0xa24, CCKSwingTable_Ch1_Ch13[CCK_index][2]); + RTL_W8( 0xa25, CCKSwingTable_Ch1_Ch13[CCK_index][3]); + RTL_W8( 0xa26, CCKSwingTable_Ch1_Ch13[CCK_index][4]); + RTL_W8( 0xa27, CCKSwingTable_Ch1_Ch13[CCK_index][5]); + RTL_W8( 0xa28, CCKSwingTable_Ch1_Ch13[CCK_index][6]); + RTL_W8( 0xa29, CCKSwingTable_Ch1_Ch13[CCK_index][7]); + } + else{ + RTL_W8( 0xa22, CCKSwingTable_Ch14[CCK_index][0]); + RTL_W8( 0xa23, CCKSwingTable_Ch14[CCK_index][1]); + RTL_W8( 0xa24, CCKSwingTable_Ch14[CCK_index][2]); + RTL_W8( 0xa25, CCKSwingTable_Ch14[CCK_index][3]); + RTL_W8( 0xa26, CCKSwingTable_Ch14[CCK_index][4]); + RTL_W8( 0xa27, CCKSwingTable_Ch14[CCK_index][5]); + RTL_W8( 0xa28, CCKSwingTable_Ch14[CCK_index][6]); + RTL_W8( 0xa29, CCKSwingTable_Ch14[CCK_index][7]); + } + } +} + +#ifdef WIFI_WMM +void check_NAV_prot_len(struct rtl8192cd_priv *priv, struct stat_info *pstat, unsigned int disassoc) +{ +#if defined(CONFIG_RTL_8812_SUPPORT)||defined(CONFIG_WLAN_HAL_8881A) ||defined(CONFIG_WLAN_HAL_8814AE) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A)||(GET_CHIP_VER(priv)== VERSION_8814A)) + return; +#endif + + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat + && pstat->ht_cap_len && (pstat->IOTPeer==HT_IOT_PEER_INTEL)) + { + if (!disassoc && (pstat->MIMO_ps & _HT_MIMO_PS_DYNAMIC_)) { + setSTABitMap(&priv->pshare->mimo_ps_dynamic_sta, pstat->aid); + } else { + clearSTABitMap(&priv->pshare->mimo_ps_dynamic_sta, pstat->aid); + } + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv) != VERSION_8188E) +#endif + { +#if defined(CONFIG_PCI_HCI) + if (orSTABitMap(&priv->pshare->mimo_ps_dynamic_sta)) { + RTL_W8(NAV_PROT_LEN, 0x40); + } else { + RTL_W8(NAV_PROT_LEN, 0x20); + } +#elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) + notify_NAV_prot_len_change(priv); +#endif + } + } +} +#endif + + +//3 ============================================================ +//3 FA statistic functions +//3 ============================================================ + +#if !defined(CONFIG_RTL_NEW_AUTOCH) +static +#endif +void reset_FA_reg(struct rtl8192cd_priv *priv) +{ +#if defined(CONFIG_RTL_8812_SUPPORT)||defined(CONFIG_WLAN_HAL_8881A) ||defined(CONFIG_WLAN_HAL_8814AE) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A)||(GET_CHIP_VER(priv)== VERSION_8814A)) { + + // reset OFDM FA coutner + PHY_SetBBReg(priv, 0x9a4, BIT(17), 1); + PHY_SetBBReg(priv, 0x9a4, BIT(17), 0); + + // reset CCK FA counter + PHY_SetBBReg(priv, 0xa2c, BIT(17), 0); + PHY_SetBBReg(priv, 0xa2c, BIT(17), 1); + + // reset CCA counter + PHY_SetBBReg(priv, 0xb58, BIT(17), 1); + PHY_SetBBReg(priv, 0xb58, BIT(17), 0); + + return; + } +#endif + +#if !defined(CONFIG_RTL_NEW_AUTOCH) + unsigned char value8; + + value8 = RTL_R8(0xd03); + RTL_W8(0xd03, value8 | 0x08); // regD00[27]=1 to reset these OFDM FA counters + value8 = RTL_R8(0xd03); + RTL_W8(0xd03, value8 & 0xF7); // regD00[27]=0 to start counting + value8 = RTL_R8(0xa2d); + RTL_W8(0xa2d, value8 & 0x3F); // regA2D[7:6]=00 to disable counting + value8 = RTL_R8(0xa2d); + RTL_W8(0xa2d, value8 | 0x80); // regA2D[7:6]=10 to enable counting +#else + /* cck CCA */ + PHY_SetBBReg(priv, 0xa2c, BIT(13) | BIT(12), 0); + PHY_SetBBReg(priv, 0xa2c, BIT(13) | BIT(12), 2); + /* cck FA*/ + PHY_SetBBReg(priv, 0xa2c, BIT(15) | BIT(14), 0); + PHY_SetBBReg(priv, 0xa2c, BIT(15) | BIT(14), 2); + /* ofdm */ + PHY_SetBBReg(priv, 0xd00, BIT(27), 1); + PHY_SetBBReg(priv, 0xd00, BIT(27), 0); +#endif + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + PHY_SetBBReg(priv, 0xf14, BIT(16),1); + PHY_SetBBReg(priv, 0xf14, BIT(16),0); + RTL_W32(RXERR_RPT, RTL_R32(RXERR_RPT)|BIT(27)); + RTL_W32(RXERR_RPT, RTL_R32(RXERR_RPT)&(~BIT(27))); + } +#endif + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE) + if (GET_CHIP_VER(priv)==VERSION_8188E || GET_CHIP_VER(priv)==VERSION_8192E) { + PHY_SetBBReg(priv, 0xc0c, BIT(31), 1); + PHY_SetBBReg(priv, 0xc0c, BIT(31), 0); + } +#endif +} + +#if defined(CONFIG_RTL_NEW_AUTOCH) +void hold_CCA_FA_counter(struct rtl8192cd_priv *priv) +{ +#if defined(CONFIG_RTL_8812_SUPPORT)||defined(CONFIG_WLAN_HAL_8881A) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A)) + return; +#endif + + /* hold cck CCA & FA counter */ + PHY_SetBBReg(priv, 0xa2c, BIT(12), 1); + PHY_SetBBReg(priv, 0xa2c, BIT(14), 1); + + /* hold ofdm CCA & FA counter */ + PHY_SetBBReg(priv, 0xc00, BIT(31), 1); + PHY_SetBBReg(priv, 0xd00, BIT(31), 1); +} + +void release_CCA_FA_counter(struct rtl8192cd_priv *priv) +{ +#if defined(CONFIG_RTL_8812_SUPPORT)||defined(CONFIG_WLAN_HAL_8881A) || defined(CONFIG_WLAN_HAL_8814AE) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A) ||(GET_CHIP_VER(priv)== VERSION_8814A)) + return; +#endif + + /* release cck CCA & FA counter */ + PHY_SetBBReg(priv, 0xa2c, BIT(12), 0); + PHY_SetBBReg(priv, 0xa2c, BIT(14), 0); + + /* release ofdm CCA & FA counter */ + PHY_SetBBReg(priv, 0xc00, BIT(31), 0); + PHY_SetBBReg(priv, 0xd00, BIT(31), 0); + +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { + PHY_SetBBReg(priv, 0xc0c, BIT(31), 1); + PHY_SetBBReg(priv, 0xc0c, BIT(31), 0); + } +#endif +} + + +void _FA_statistic(struct rtl8192cd_priv *priv) +{ +#if defined(CONFIG_RTL_8812_SUPPORT)||defined(CONFIG_WLAN_HAL_8881A)||defined(CONFIG_WLAN_HAL_8814AE) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A)||(GET_CHIP_VER(priv)== VERSION_8814A)) + return; +#endif + + // read OFDM FA counters + priv->pshare->ofdm_FA_cnt1 = RTL_R16(0xda2); + priv->pshare->ofdm_FA_cnt2 = RTL_R16(0xda4); + priv->pshare->ofdm_FA_cnt3 = RTL_R16(0xda6); + priv->pshare->ofdm_FA_cnt4 = RTL_R16(0xda8); + + priv->pshare->cck_FA_cnt = (RTL_R8(0xa5b) << 8) + RTL_R8(0xa5c); + +#ifdef INTERFERENCE_CONTROL + priv->pshare->ofdm_FA_total_cnt = (unsigned int) priv->pshare->ofdm_FA_cnt1 + + priv->pshare->ofdm_FA_cnt2 + priv->pshare->ofdm_FA_cnt3 + + priv->pshare->ofdm_FA_cnt4 + RTL_R16(0xcf0) + RTL_R16(0xcf2); + + priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_total_cnt + priv->pshare->cck_FA_cnt; +#else + priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_cnt1 + priv->pshare->ofdm_FA_cnt2 + + priv->pshare->ofdm_FA_cnt3 + priv->pshare->ofdm_FA_cnt4 + + priv->pshare->cck_FA_cnt + RTL_R16(0xcf0) + RTL_R16(0xcf2); +#endif +} +#endif + +void FA_statistic(struct rtl8192cd_priv *priv) +{ +#if defined(CONFIG_RTL_8812_SUPPORT)||defined(CONFIG_WLAN_HAL_8881A) + if((GET_CHIP_VER(priv)== VERSION_8812E)||(GET_CHIP_VER(priv)== VERSION_8881A)) + return; +#endif + + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ +// priv->pshare->F90_cnt = PHY_QueryBBReg(priv, 0xf90, bMaskHWord); + priv->pshare->F94_cnt = PHY_QueryBBReg(priv, 0xf94, bMaskHWord); + priv->pshare->F94_cntOK = PHY_QueryBBReg(priv, 0xf94, bMaskLWord); + RTL_W32(RXERR_RPT,(RTL_R32(RXERR_RPT)&0x0fffffff)|0x70000000); + priv->pshare->Reg664_cnt = RTL_R32(RXERR_RPT) & 0xfffff; + RTL_W32(RXERR_RPT,(RTL_R32(RXERR_RPT)&0x0fffffff)|0x60000000); + priv->pshare->Reg664_cntOK = RTL_R32(RXERR_RPT) & 0xfffff; + } +#endif + +#if !defined(CONFIG_RTL_NEW_AUTOCH) + signed char value8; + + // read OFDM FA counters + priv->pshare->ofdm_FA_cnt1 = RTL_R16(0xda2); + priv->pshare->ofdm_FA_cnt2 = RTL_R16(0xda4); + priv->pshare->ofdm_FA_cnt3 = RTL_R16(0xda6); + priv->pshare->ofdm_FA_cnt4 = RTL_R16(0xda8); + + // read the CCK FA counters + value8 = RTL_R8(0xa2d); + RTL_W8(0xa2d, value8 | 0x40); // regA2D[6]=1 to hold and read the CCK FA counters + priv->pshare->cck_FA_cnt = RTL_R8(0xa5b); + priv->pshare->cck_FA_cnt = priv->pshare->cck_FA_cnt << 8; + priv->pshare->cck_FA_cnt += RTL_R8(0xa5c); + + priv->pshare->FA_total_cnt = priv->pshare->ofdm_FA_cnt1 + priv->pshare->ofdm_FA_cnt2 + + priv->pshare->ofdm_FA_cnt3 + priv->pshare->ofdm_FA_cnt4 + + priv->pshare->cck_FA_cnt + RTL_R16(0xcf0) + RTL_R16(0xcf2); + + if (priv->pshare->rf_ft_var.rssi_dump) + priv->pshare->CCA_total_cnt = ((RTL_R8(0xa60)<<8)|RTL_R8(0xa61)) + RTL_R16(0xda0); +#else + hold_CCA_FA_counter(priv); + _FA_statistic(priv); + + if (priv->pshare->rf_ft_var.rssi_dump) + priv->pshare->CCA_total_cnt = ((RTL_R8(0xa60)<<8)|RTL_R8(0xa61)) + RTL_R16(0xda0); + + release_CCA_FA_counter(priv); +#endif + + reset_FA_reg(priv); + +#if defined(CONFIG_RTL_92D_SUPPORT) && defined(CONFIG_RTL_NOISE_CONTROL) + if (GET_CHIP_VER(priv) == VERSION_8192D){ + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G && !(OPMODE & WIFI_SITE_MONITOR)) { + if (priv->pshare->DNC_on == 0){ + //if ((priv->pshare->F94_cnt + priv->pshare->F90_cnt)> 3000){ + /* Reg 664: x > y && x > 1000 + Reg F94: x > 0.75*y && x > 1000 */ + if (((priv->pshare->Reg664_cnt>priv->pshare->Reg664_cntOK) && (priv->pshare->Reg664_cnt > 1000))|| + ((priv->pshare->F94_cnt > ((priv->pshare->Reg664_cntOK*3)>>2)) && (priv->pshare->F94_cnt > 1000))) { + priv->ext_stats.tp_average_pre = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; + priv->pshare->DNC_on = 1; + priv->pshare->DNC_chk_cnt = 1; + priv->pshare->DNC_chk = 2; // 0: don't check, 1; check, 2: just entering DNC + //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0x00a00000); + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07600760); + PHY_SetBBReg(priv, 0xc50, bMaskByte0, 0x20); + PHY_SetBBReg(priv, 0xc58, bMaskByte0, 0x20); + //printk("Dynamic Noise Control ON\n"); + } + } else { + if ((priv->pshare->DNC_chk_cnt % 5)==0){ // check every 5*2=10 seconds + unsigned long tp_now = (priv->ext_stats.tx_avarage+priv->ext_stats.rx_avarage)>>17; + priv->pshare->DNC_chk_cnt = 0; + + if ((priv->pshare->DNC_chk == 2) && (tp_now < priv->ext_stats.tp_average_pre+5)){ + //no advantage, leave DNC state + priv->pshare->DNC_on = 0; + priv->pshare->DNC_chk = 0; + //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0); + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); + } + else + { + priv->pshare->DNC_chk = 0; + + /* If TP < 20M or TP varies more than 5M. Start Checking...*/ + if ((tp_now < 20) || ((tp_now < (priv->ext_stats.tp_average_pre-5))|| (tp_now > (priv->ext_stats.tp_average_pre+5)))){ + priv->pshare->DNC_chk = 1; + //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0); + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); + if (!timer_pending(&priv->dnc_timer)) { + //printk("... Start Check Noise ...\n"); + mod_timer(&priv->dnc_timer, jiffies + RTL_MILISECONDS_TO_JIFFIES(100)); // 100 ms + } + } + } + + priv->ext_stats.tp_average_pre = tp_now; + + } else if ((priv->pshare->DNC_chk_cnt % 5)==1 && priv->pshare->DNC_chk == 1) { + priv->pshare->DNC_chk = 0; + //if ((priv->pshare->F94_cnt + priv->pshare->F90_cnt) < 120) { + if ((priv->pshare->F94_cnt + priv->pshare->Reg664_cnt) < 120) { + priv->pshare->DNC_on = 0; + //PHY_SetBBReg(priv, 0xb30, bMaskDWord, 0); + PHY_SetBBReg(priv, 0x870, bMaskDWord, 0x07000700); + //printk("Dynamic Noise Control OFF\n"); + } + } + priv->pshare->DNC_chk_cnt++; + } + } + } +#endif +} + + +//3 ============================================================ +//3 Rate Adaptive +//3 ============================================================ + +void check_RA_by_rssi(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + int level = 0; + + switch (pstat->rssi_level) { + case 1: + if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper) + level = 1; + else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) || + ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && + (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) + level = 2; + else + level = 3; + break; + case 2: + if (pstat->rssi > priv->pshare->rf_ft_var.raGoUpUpper) + level = 1; + else if ((pstat->rssi < priv->pshare->rf_ft_var.raGoDown40MLower) || + ((!pstat->ht_cap_len || !priv->pshare->is_40m_bw || + !(pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))) && + (pstat->rssi < priv->pshare->rf_ft_var.raGoDown20MLower))) + level = 3; + else + level = 2; + break; + case 3: + if (pstat->rssi > priv->pshare->rf_ft_var.raGoUpUpper) + level = 1; + else if ((pstat->rssi > priv->pshare->rf_ft_var.raGoUp20MLower) || + ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && + (pstat->rssi > priv->pshare->rf_ft_var.raGoUp40MLower) && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) + level = 2; + else + level = 3; + break; + default: + if (isErpSta(pstat)) + DEBUG_ERR("wrong rssi level setting\n"); + break; + } + + if (level != pstat->rssi_level && CHIP_VER_92X_SERIES(priv)) { + pstat->rssi_level = level; +#ifdef CONFIG_RTL_88E_SUPPORT + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifdef TXREPORT + add_RATid(priv, pstat); +#endif + } else +#endif + { +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + add_update_RATid(priv, pstat); +#endif + } + } +} + + + +void add_RATid(struct rtl8192cd_priv *priv, struct stat_info *pstat) +{ + unsigned char limit=16; + int i; +#ifndef SMP_SYNC + unsigned long flags; +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + unsigned int update_reg=0; +#endif + + SAVE_INT_AND_CLI(flags); + + pstat->tx_ra_bitmap = 0; + + for (i=0; i<32; i++) { + if (pstat->bssrateset[i]) + pstat->tx_ra_bitmap |= get_bit_value_from_ieee_value(pstat->bssrateset[i]&0x7f); + } + + if (pstat->ht_cap_len) { + if ((pstat->MIMO_ps & _HT_MIMO_PS_STATIC_) || + (get_rf_mimo_mode(priv)== MIMO_1T2R) || + (get_rf_mimo_mode(priv)== MIMO_1T1R)) + limit=8; + + for (i=0; iht_cap_buf.support_mcs[i/8] & BIT(i%8)) + pstat->tx_ra_bitmap |= BIT(i+12); + } + } + + if (pstat->ht_cap_len) { + unsigned int set_sgi = 0; + if (priv->pshare->is_40m_bw && (pstat->tx_bw == HT_CHANNEL_WIDTH_20_40) +#ifdef WIFI_11N_2040_COEXIST + && !((OPMODE & WIFI_AP_STATE) && priv->pmib->dot11nConfigEntry.dot11nCoexist && + (priv->bg_ap_timeout || orForce20_Switch20Map(priv) + )) +#endif + ) { + if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_40M_) + && priv->pmib->dot11nConfigEntry.dot11nShortGIfor40M) + set_sgi++; + } else if (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SHORTGI_20M_) && + priv->pmib->dot11nConfigEntry.dot11nShortGIfor20M) { + set_sgi++; + } + + if (set_sgi) { +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv)==VERSION_8188E) +#ifdef RATEADAPTIVE_BY_ODM + ODMPTR->RAInfo[pstat->aid].SGIEnable = 1; +#else + priv->pshare->RaInfo[pstat->aid].SGIEnable = 1; +#endif + else +#endif + pstat->tx_ra_bitmap |= BIT(28); + } +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + else { + if (GET_CHIP_VER(priv)==VERSION_8188E) +#ifdef RATEADAPTIVE_BY_ODM + ODMPTR->RAInfo[pstat->aid].SGIEnable = 0; +#else + priv->pshare->RaInfo[pstat->aid].SGIEnable = 0; +#endif + } +#endif + } +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + else { + if (GET_CHIP_VER(priv)==VERSION_8188E) +#ifdef RATEADAPTIVE_BY_ODM + ODMPTR->RAInfo[pstat->aid].SGIEnable = 0; +#else + priv->pshare->RaInfo[pstat->aid].SGIEnable = 0; +#endif + } +#endif + +#ifdef USE_OUT_SRC + if(IS_OUTSRC_CHIP(priv)) { + if ((pstat->rssi_level < 1) || (pstat->rssi_level > 4)) + ODM_RAStateCheck(ODMPTR, (s4Byte)pstat->rssi, FALSE, &pstat->rssi_level) ; + } else +#endif + { + if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3)) { + if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper) + pstat->rssi_level = 1; + else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) || + ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && + (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) && + (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) + pstat->rssi_level = 2; + else + pstat->rssi_level = 3; + } + } + + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) && + ((OPMODE & WIFI_AP_STATE) || (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G))) + pstat->tx_ra_bitmap &= 0xfffffff0; //disable cck rate + +#ifdef P2P_SUPPORT + if(pstat->is_p2p_client){ + pstat->tx_ra_bitmap &= 0xfffffff0; //disable cck rate + } +#endif + + // rate adaptive by rssi + if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && (!should_restrict_Nrate(priv, pstat))) { + if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R)) { + switch (pstat->rssi_level) { + case 1: + pstat->tx_ra_bitmap &= 0x100f0000; + break; + case 2: + pstat->tx_ra_bitmap &= 0x100ff000; + break; + case 3: + if (priv->pshare->is_40m_bw) + pstat->tx_ra_bitmap &= 0x100fe00f; + else + pstat->tx_ra_bitmap &= 0x100fe00f; + break; + } + } else { + switch (pstat->rssi_level) { + case 1: + pstat->tx_ra_bitmap &= 0x1f8f0000; + break; + case 2: + pstat->tx_ra_bitmap &= 0x1f8ff00D; + break; + case 3: + if (priv->pshare->is_40m_bw) + pstat->tx_ra_bitmap &= 0x010fe00f; + else + pstat->tx_ra_bitmap &= 0x010ff00f; + break; + } + + // Don't need to mask high rates due to new rate adaptive parameters + //if (pstat->is_broadcom_sta) // use MCS12 as the highest rate vs. Broadcom sta + // pstat->tx_ra_bitmap &= 0x81ffffff; + + // NIC driver will report not supporting MCS15 and MCS14 in asoc req + //if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta) + // pstat->tx_ra_bitmap &= 0x83ffffff; // if Realtek 1x2 sta, don't use MCS15 and MCS14 + } + } + else if (((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat)) || + ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) && + ((OPMODE & WIFI_AP_STATE) || (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)))) + { + switch (pstat->rssi_level) { + case 1: + pstat->tx_ra_bitmap &= 0x00000f00; + break; + case 2: + pstat->tx_ra_bitmap &= 0x00000ff0; + break; + case 3: + pstat->tx_ra_bitmap &= 0x00000fef; + break; + } + } else { + pstat->tx_ra_bitmap &= 0x0000000d; + } + +// Client mode IOT issue, Button 2009.07.17 +#ifdef CLIENT_MODE + if(OPMODE & WIFI_STATION_STATE) { + + if((pstat->IOTPeer!=HT_IOT_PEER_REALTEK_92SE) && pstat->is_realtek_sta && pstat->is_legacy_encrpt) + + pstat->tx_ra_bitmap &= 0x0001ffff; // up to MCS4 + } +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) && defined (USB_POWER_SUPPORT) + if ((GET_CHIP_VER(priv)==VERSION_8192D) && (priv->pmib->dot11RFEntry.phyBandSelect & PHY_BAND_5G)) + pstat->tx_ra_bitmap &= USB_RA_MASK; +#endif + update_remapAid(priv,pstat); +#if defined(CONFIG_RTL_88E_SUPPORT) && defined(TXREPORT) + if (GET_CHIP_VER(priv)==VERSION_8188E) { +#ifndef RATEADAPTIVE_BY_ODM + if (pstat->tx_ra_bitmap & 0xff000) { + if (priv->pshare->is_40m_bw) + priv->pshare->RaInfo[pstat->aid].RateID = ARFR_1T_40M; + else + priv->pshare->RaInfo[pstat->aid].RateID = ARFR_1T_20M; + } else if (pstat->tx_ra_bitmap & 0xff0) { + priv->pshare->RaInfo[pstat->aid].RateID = ARFR_BG_MIX; + } else { + priv->pshare->RaInfo[pstat->aid].RateID = ARFR_B_ONLY; + } + + priv->pshare->RaInfo[pstat->aid].RateMask = pstat->tx_ra_bitmap; + ARFBRefresh(priv, &priv->pshare->RaInfo[pstat->aid]); +#else + PODM_RA_INFO_T pRAInfo = &(ODMPTR->RAInfo[pstat->aid]); + if (pstat->tx_ra_bitmap & 0xff000) { + if (priv->pshare->is_40m_bw) + pRAInfo->RateID = ARFR_1T_40M; + else + pRAInfo->RateID = ARFR_1T_20M; + } else if (pstat->tx_ra_bitmap & 0xff0) { + pRAInfo->RateID = ARFR_BG_MIX; + } else { + pRAInfo->RateID = ARFR_B_ONLY; + } + ODM_RA_UpdateRateInfo_8188E(ODMPTR, pstat->aid, pRAInfo->RateID, pstat->tx_ra_bitmap, pRAInfo->SGIEnable); +#endif + } else +#endif +#if defined(CONFIG_RTL_92D_SUPPORT) || defined(CONFIG_RTL_92C_SUPPORT) + if(CHIP_VER_92X_SERIES(priv)) + { + if (pstat->sta_in_firmware == 1) + { +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + { + pstat->tx_ra_bitmap &= 0xfffffff0; + if (pstat->tx_ra_bitmap & 0xff00000) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_40M, pstat->tx_ra_bitmap); + else + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_20M, pstat->tx_ra_bitmap); + update_reg++; + } else if (pstat->tx_ra_bitmap & 0xff000) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_40M, pstat->tx_ra_bitmap); + else + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_Band_A_20M, pstat->tx_ra_bitmap); + } else if (pstat->tx_ra_bitmap & 0xff0) { + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_Band_A_BMC, pstat->tx_ra_bitmap); + } else { + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_Band_A_BMC, pstat->tx_ra_bitmap); + } + } else +#endif + { + if (pstat->tx_ra_bitmap & 0xff00000) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_40M, pstat->tx_ra_bitmap); + else + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_2T_20M, pstat->tx_ra_bitmap); + update_reg++; + } else if (pstat->tx_ra_bitmap & 0xff000) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_1T_40M, pstat->tx_ra_bitmap); + else + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_1T_20M, pstat->tx_ra_bitmap); + } else if (pstat->tx_ra_bitmap & 0xff0) { + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_BG_MIX, pstat->tx_ra_bitmap); + } else { + set_RATid_cmd(priv, REMAP_AID(pstat), ARFR_B_ONLY, pstat->tx_ra_bitmap); + } + } + + /* + * Rate adaptive algorithm. + * If the STA is 2R, we set the inti rate to MCS 15 + */ + if (update_reg) { + if (!pstat->check_init_tx_rate && (pstat->rssi > 55)) { + RTL_W8(INIDATA_RATE_SEL + REMAP_AID(pstat), 0x1b); + pstat->check_init_tx_rate = 1; + } + } + DEBUG_INFO("Add id %d val %08x to ratr\n", pstat->aid, pstat->tx_ra_bitmap); + } else { +#ifdef CONFIG_RTL_92D_SUPPORT + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, priv->pshare->fw_support_sta_num, ARFR_2T_Band_A_40M, 0x1ffffff0); + else + set_RATid_cmd(priv, priv->pshare->fw_support_sta_num, ARFR_2T_Band_A_20M, 0x1ffffff0); + } else +#endif + { + if (priv->pshare->is_40m_bw) + set_RATid_cmd(priv, priv->pshare->fw_support_sta_num, ARFR_2T_40M, 0x1fffffff); + else + set_RATid_cmd(priv, priv->pshare->fw_support_sta_num, ARFR_2T_20M, 0x1fffffff); + } + } + } +#endif + RESTORE_INT(flags); +} + +void rtl8192cd_NHMBBInit(struct rtl8192cd_priv *priv) +{ + RTL_W16(0x894+2, 0xc350); //0x894[31:16]=0xffff Time duration for NHM unit: 4us, 0x2710=40ms + RTL_W16(0x890+2, 0xffff); //0x890[31:16]=0xffff th_9, th_10 + RTL_W32(0x898, 0xffffff50); //0x898=0xffffff50 th_3, th_2, th_1, th_0 + RTL_W32(0x89c, 0xffffffff); //0x89c=0xffffffff th_7, th_6, th_5, th_4 + PHY_SetBBReg(priv, 0xe28, bMaskByte0, 0xff); //0xe28[7:0]=0xff th_8 + PHY_SetBBReg(priv, 0x890, BIT10|BIT9|BIT8, 0x1); //0x890[9:8]=3 enable CCX + PHY_SetBBReg(priv, 0xc0c, BIT7, 0x1); //0xc0c[7]=1 +} + +void rtl8192cd_GetNHMCounterStatistics(struct rtl8192cd_priv *priv) +{ + u4Byte value32 = 0; + + value32 = PHY_QueryBBReg(priv, 0x8d8, bMaskDWord); + + priv->pshare->rf_ft_var.NHM_cnt_0 = (u1Byte)(value32 & bMaskByte0); + priv->pshare->rf_ft_var.NHM_cnt_1 = (u1Byte)((value32 & bMaskByte1)>>8); + +} + +void rtl8192cd_NHMCounterStatisticsReset(struct rtl8192cd_priv *priv) +{ + PHY_SetBBReg(priv, 0x890, BIT1, 0); + PHY_SetBBReg(priv, 0x890, BIT1, 1); +} + +void rtl8192cd_NHMCounterStatistics(struct rtl8192cd_priv *priv) +{ + // Get NHM report + rtl8192cd_GetNHMCounterStatistics(priv); + // Reset NHM counter + rtl8192cd_NHMCounterStatisticsReset(priv); +} + +void rtl8192cd_SetTRxMux(struct rtl8192cd_priv *priv, u1Byte txMode, u1Byte rxMode) +{ + PHY_SetBBReg(priv, 0x824, BIT3|BIT2|BIT1, txMode); // set TXmode to standby mode to remove outside noise affect + PHY_SetBBReg(priv, 0x824, BIT22|BIT21|BIT20, rxMode); // set RXmode to standby mode to remove outside noise affect + + if(get_rf_mimo_mode(priv) != MIMO_1T1R) + { + PHY_SetBBReg(priv, 0x82c, BIT3|BIT2|BIT1, txMode); // set TXmode to standby mode to remove outside noise affect + PHY_SetBBReg(priv, 0x82c, BIT22|BIT21|BIT20, rxMode); // set RXmode to standby mode to remove outside noise affect + } + +} + + +void rtl8192cd_SetEDCCAThreshold(struct rtl8192cd_priv *priv, s1Byte H2L, s1Byte L2H) +{ + PHY_SetBBReg(priv,rOFDM0_ECCAThreshold, bMaskByte0, (u1Byte)L2H); + PHY_SetBBReg(priv,rOFDM0_ECCAThreshold, bMaskByte2, (u1Byte)H2L); +} + + +void rtl8192cd_SearchPwdBLowerBound(struct rtl8192cd_priv *priv) +{ + u4Byte value32; + u1Byte cnt, IGI_Pause = 0x7f, IGI_Resume = 0x20, IGI = 0x50; //IGI = 0x50 for cal EDCCA lower bound + BOOLEAN bAdjust = TRUE, bAdjust2 = TRUE;; + s1Byte TH_L2H_dmc, TH_H2L_dmc, Diff, IGI_target = 0x32; + u1Byte txEdcca1 = 0, txEdcca0 = 0; + + rtl8192cd_SetTRxMux(priv, 1, 1); // Set both Tx mode and Rx mode to standby mode + RTL_W8(0xc50,IGI_Pause); + RTL_W8(0xc58,IGI_Pause); + + Diff = IGI_target -(s1Byte)IGI; + TH_L2H_dmc = priv->pshare->rf_ft_var.TH_L2H_ini + Diff; + + if(TH_L2H_dmc > 10) + TH_L2H_dmc = 10; + + TH_H2L_dmc = TH_L2H_dmc - priv->pshare->rf_ft_var.TH_EDCCA_HL_diff; + rtl8192cd_SetEDCCAThreshold(priv,TH_H2L_dmc,TH_L2H_dmc); + + delay_ms(5); + while(bAdjust) + { + for(cnt=0; cnt<250; cnt ++) + { + value32 = PHY_QueryBBReg(priv,0xDF4, bMaskDWord); + + if ( (GET_CHIP_VER(priv) == VERSION_8188E) && (value32 & BIT30) ) + txEdcca1 = txEdcca1 + 1; + else if(value32 & BIT29) + txEdcca1 = txEdcca1 + 1; + else + txEdcca0 = txEdcca0 + 1; + } + + if(txEdcca1 > 1) + { + IGI = IGI -1; + TH_L2H_dmc = TH_L2H_dmc + 1; + if(TH_L2H_dmc > 10) + TH_L2H_dmc = 10; + TH_H2L_dmc = TH_L2H_dmc - priv->pshare->rf_ft_var.TH_EDCCA_HL_diff; + + rtl8192cd_SetEDCCAThreshold(priv,TH_H2L_dmc,TH_L2H_dmc); + + txEdcca1 = 0; + txEdcca0 = 0; + + if(TH_L2H_dmc == 10) + { + bAdjust = FALSE; + priv->pshare->rf_ft_var.H2L_lb = TH_H2L_dmc; + priv->pshare->rf_ft_var.L2H_lb = TH_L2H_dmc; + priv->pshare->rf_ft_var.Adaptivity_IGI_upper = IGI; + } + } + else + { + bAdjust = FALSE; + txEdcca1 = 0; + txEdcca0 = 0; + priv->pshare->rf_ft_var.H2L_lb = TH_H2L_dmc; + priv->pshare->rf_ft_var.L2H_lb = TH_L2H_dmc; + priv->pshare->rf_ft_var.Adaptivity_IGI_upper = IGI; + } + } + + while (bAdjust2) + { + rtl8192cd_SetEDCCAThreshold(priv, priv->pshare->rf_ft_var.H2L_lb, priv->pshare->rf_ft_var.L2H_lb); + + for (cnt = 0; cnt < 250; cnt++) + { + value32 = PHY_QueryBBReg(priv,0xDF4, bMaskDWord); + + if ( (GET_CHIP_VER(priv) == VERSION_8188E) && (value32 & BIT30) ) + txEdcca1 = txEdcca1 + 1; + else if (value32 & BIT29) + txEdcca1 = txEdcca1 + 1; + else + txEdcca0 = txEdcca0 + 1; + } + + if (txEdcca1 > 1) + { + priv->pshare->rf_ft_var.Adaptivity_IGI_upper -= 1; + priv->pshare->rf_ft_var.H2L_lb += 1; + priv->pshare->rf_ft_var.L2H_lb += 1; + } + else + bAdjust2 = FALSE; + } + + priv->pshare->rf_ft_var.Adaptivity_IGI_upper -= priv->pshare->rf_ft_var.dcbackoff; + priv->pshare->rf_ft_var.H2L_lb += priv->pshare->rf_ft_var.dcbackoff; + priv->pshare->rf_ft_var.L2H_lb += priv->pshare->rf_ft_var.dcbackoff; + + rtl8192cd_SetTRxMux(priv, 2, 3); // Set 2:Tx mode and 3:Rx mode + RTL_W8(0xc50,IGI_Resume); + RTL_W8(0xc58,IGI_Resume); + rtl8192cd_SetEDCCAThreshold(priv,0x7f,0x7f); +} + +void rtl8192cd_MACEDCCAState(struct rtl8192cd_priv *priv, u1Byte State) +{ + if(State == 0)//ignore edcca + { + PHY_SetBBReg(priv, REG_TX_PTCL_CTRL, BIT15, 1); //ignore EDCCA reg520[15]=1 + PHY_SetBBReg(priv, REG_RD_CTRL, BIT11, 0); //reg524[11]=0 + } + else // don't set MAC ignore EDCCA signal + { + PHY_SetBBReg(priv, REG_TX_PTCL_CTRL, BIT15, 0); //don't ignore EDCCA reg520[15]=0 + PHY_SetBBReg(priv, REG_RD_CTRL, BIT11, 1); //reg524[11]=1 + } +} + +void rtl8192cd_AdaptivityInit(struct rtl8192cd_priv *priv) +{ + rtl8192cd_NHMBBInit(priv); + + priv->pshare->rf_ft_var.TH_L2H_ini = priv->pshare->rf_ft_var.TH_L2H_ini_backup; + priv->pshare->rf_ft_var.TH_EDCCA_HL_diff = 7; + priv->pshare->rf_ft_var.TH_L2H_ini_mode2 = 20; + priv->pshare->rf_ft_var.TH_EDCCA_HL_diff_mode2 = 8; + priv->pshare->rf_ft_var.TH_EDCCA_HL_diff_backup = priv->pshare->rf_ft_var.TH_EDCCA_HL_diff ; + priv->pshare->rf_ft_var.IGI_Base = 0x32; + priv->pshare->rf_ft_var.IGI_target = 0x1c; + priv->pshare->rf_ft_var.H2L_lb = 0; + priv->pshare->rf_ft_var.L2H_lb = 0; + priv->pshare->rf_ft_var.Adaptivity_IGI_upper = 0; + priv->pshare->rf_ft_var.NHMWait = 0; + + priv->pshare->rf_ft_var.bCheck = FALSE; + priv->pshare->rf_ft_var.bFirstLink = TRUE; + priv->pshare->rf_ft_var.Adaptivity_enable = FALSE; // use this flag to judge enable or disable + + if(priv->pshare->rf_ft_var.adaptivity_enable == 2) + priv->pshare->rf_ft_var.DynamicLinkAdaptivity = TRUE; + else + priv->pshare->rf_ft_var.DynamicLinkAdaptivity = FALSE; + + rtl8192cd_MACEDCCAState(priv, 1); + PHY_SetBBReg(priv,0x908, bMaskDWord, 0x208); + PHY_SetBBReg(priv, 0xc4c, BIT9 | BIT8, 0x0);// set forgetting factor = 0 for all n series IC + rtl8192cd_SearchPwdBLowerBound(priv); +} + + +BOOLEAN rtl8192cd_CalNHMcnt(struct rtl8192cd_priv *priv) +{ + u2Byte Base = 0; + + Base = priv->pshare->rf_ft_var.NHM_cnt_0 + priv->pshare->rf_ft_var.NHM_cnt_1; + + if(Base != 0) + { + priv->pshare->rf_ft_var.NHM_cnt_0 = ((priv->pshare->rf_ft_var.NHM_cnt_0) << 8) / Base; + priv->pshare->rf_ft_var.NHM_cnt_1 = ((priv->pshare->rf_ft_var.NHM_cnt_1) << 8) / Base; + } + + if((priv->pshare->rf_ft_var.NHM_cnt_0 - priv->pshare->rf_ft_var.NHM_cnt_1) >= 100) + return TRUE; // clean environment + else + return FALSE; //noisy environment + +} + + +void rtl8192cd_CheckEnvironment(struct rtl8192cd_priv *priv) +{ + BOOLEAN isCleanEnvironment = FALSE; + + if(priv->pshare->rf_ft_var.bFirstLink == TRUE) + { + priv->pshare->rf_ft_var.adaptivity_flag = TRUE; + priv->pshare->rf_ft_var.bFirstLink = FALSE; + return; + } + else + { + if(priv->pshare->rf_ft_var.NHMWait < 3) // Start enter NHM after 4 NHMWait + { + priv->pshare->rf_ft_var.NHMWait ++; + rtl8192cd_NHMCounterStatistics(priv); + return; + } + else + { + rtl8192cd_NHMCounterStatistics(priv); + isCleanEnvironment = rtl8192cd_CalNHMcnt(priv); + if(isCleanEnvironment == TRUE) + { + priv->pshare->rf_ft_var.TH_L2H_ini = priv->pshare->rf_ft_var.TH_L2H_ini_backup; //mode 1 + priv->pshare->rf_ft_var.TH_EDCCA_HL_diff= priv->pshare->rf_ft_var.TH_EDCCA_HL_diff_backup; + priv->pshare->rf_ft_var.Adaptivity_enable = TRUE; + priv->pshare->rf_ft_var.adaptivity_flag = TRUE; + } + else + { + priv->pshare->rf_ft_var.TH_L2H_ini = priv->pshare->rf_ft_var.TH_L2H_ini_mode2; // for AP mode 2 + priv->pshare->rf_ft_var.TH_EDCCA_HL_diff= priv->pshare->rf_ft_var.TH_EDCCA_HL_diff_mode2; + priv->pshare->rf_ft_var.Adaptivity_enable = FALSE; + priv->pshare->rf_ft_var.adaptivity_flag = FALSE; + } + + priv->pshare->rf_ft_var.bFirstLink = TRUE; + priv->pshare->rf_ft_var.bCheck = TRUE; + } + + } + +} + +void rtl8192cd_CheckAdaptivity(struct rtl8192cd_priv *priv) +{ + if(priv->pshare->rf_ft_var.adaptivity_enable) + { + if(priv->pshare->rf_ft_var.DynamicLinkAdaptivity == TRUE) + { + if( priv->pshare->rf_ft_var.bLinked && !priv->pshare->rf_ft_var.bCheck ) + { + rtl8192cd_NHMCounterStatistics(priv); + rtl8192cd_CheckEnvironment(priv); + } + else if( !priv->pshare->rf_ft_var.bLinked ) + { + priv->pshare->rf_ft_var.bCheck = FALSE; + } + } + else + { + priv->pshare->rf_ft_var.Adaptivity_enable = TRUE; + priv->pshare->rf_ft_var.adaptivity_flag = TRUE; + } + } + else + { + priv->pshare->rf_ft_var.Adaptivity_enable = FALSE; + priv->pshare->rf_ft_var.adaptivity_flag = FALSE; + } +} + +void rtl8192cd_Adaptivity(struct rtl8192cd_priv *priv, u1Byte IGI) +{ + s1Byte Diff, IGI_target, TH_L2H_dmc, TH_H2L_dmc; + + if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + IGI_target = priv->pshare->rf_ft_var.IGI_Base; + else if(priv->pshare->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + IGI_target = priv->pshare->rf_ft_var.IGI_Base + 2; + else + IGI_target = priv->pshare->rf_ft_var.IGI_Base; + priv->pshare->rf_ft_var.IGI_target = IGI_target; + + if ( priv->pshare->rf_ft_var.adap_debug ) + { + printk("DynamicLinkAdaptivity=%d, adaptivity_flag=%d, Adaptivity_enable=%d, bLinked=%d\n", + priv->pshare->rf_ft_var.DynamicLinkAdaptivity, priv->pshare->rf_ft_var.adaptivity_flag, + priv->pshare->rf_ft_var.Adaptivity_enable, priv->pshare->rf_ft_var.bLinked); + } + + if ( priv->pshare->rf_ft_var.DynamicLinkAdaptivity + && !priv->pshare->rf_ft_var.bLinked + && !priv->pshare->rf_ft_var.Adaptivity_enable ) + { + rtl8192cd_SetEDCCAThreshold(priv, 0x7f, 0x7f); + return; + } + + Diff = IGI_target -IGI; + TH_L2H_dmc = priv->pshare->rf_ft_var.TH_L2H_ini + Diff; + TH_H2L_dmc = TH_L2H_dmc - priv->pshare->rf_ft_var.TH_EDCCA_HL_diff; + + if(TH_L2H_dmc >10) + TH_L2H_dmc = 10; + + TH_H2L_dmc = TH_L2H_dmc - priv->pshare->rf_ft_var.TH_EDCCA_HL_diff; + + //replace lower bound to prevent EDCCA always equal 1 + if(TH_H2L_dmc < priv->pshare->rf_ft_var.H2L_lb) + TH_H2L_dmc = priv->pshare->rf_ft_var.H2L_lb; + if(TH_L2H_dmc < priv->pshare->rf_ft_var.L2H_lb) + TH_L2H_dmc = priv->pshare->rf_ft_var.L2H_lb; + + if(priv->pshare->rf_ft_var.adap_debug) + { + printk("TH_L2H_ini=%d, TH_EDCCA_HL_diff=%d\n", priv->pshare->rf_ft_var.TH_L2H_ini, priv->pshare->rf_ft_var.TH_EDCCA_HL_diff); + printk("IGI=0x%02x, TH_H2L_dmc=%d, TH_L2H_dmc=%d\n", IGI, TH_H2L_dmc, TH_L2H_dmc); + printk("Adaptivity_IGI_upper=0x%02x, H2L_lb=%d, L2H_lb=%d\n", priv->pshare->rf_ft_var.Adaptivity_IGI_upper, priv->pshare->rf_ft_var.H2L_lb, priv->pshare->rf_ft_var.L2H_lb); + } + rtl8192cd_SetEDCCAThreshold(priv,TH_H2L_dmc,TH_L2H_dmc); +} + +void check_NBI_by_rssi(struct rtl8192cd_priv *priv, unsigned char rssi_strength) +{ + if (OPMODE & WIFI_SITE_MONITOR) + return; + + if (priv->pmib->dot11RFEntry.phyBandSelect == PHY_BAND_5G) + return; + + if (priv->pshare->phw->nbi_filter_on) { + if (rssi_strength < 20) + NBI_filter_off(priv); + + } else { // NBI OFF previous + if (rssi_strength > 25) + NBI_filter_on(priv); + } +} + + +void NBI_filter_on(struct rtl8192cd_priv *priv) +{ + priv->pshare->phw->nbi_filter_on = 1; + +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) + return; +#endif + +#ifdef RTK_AC_SUPPORT + if((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A)) + RTL_W16(rFPGA0_XCD_RFParam, RTL_R16(rFPGA0_XCD_RFParam) | BIT(13)); // NBI on + else +#endif + RTL_W16(rOFDM0_RxDSP, RTL_R16(rOFDM0_RxDSP) | BIT(9)); // NBI on +} + +void NBI_filter_off(struct rtl8192cd_priv *priv) +{ + priv->pshare->phw->nbi_filter_on = 0; + +#ifdef MP_TEST + if ((OPMODE & WIFI_MP_STATE) || priv->pshare->rf_ft_var.mp_specific) + return; +#endif + +#ifdef RTK_AC_SUPPORT + if((GET_CHIP_VER(priv) == VERSION_8812E) || (GET_CHIP_VER(priv) == VERSION_8881A)) + RTL_W16(rFPGA0_XCD_RFParam, RTL_R16(rFPGA0_XCD_RFParam) & ~ BIT(13)); // NBI off + else +#endif + RTL_W16(rOFDM0_RxDSP, RTL_R16(rOFDM0_RxDSP) & ~ BIT(9)); // NBI off +} + +#if defined(CONFIG_WLAN_HAL_8192EE) +#ifdef CONFIG_PCI_HCI +void RRSR_power_control_11n(struct rtl8192cd_priv *priv, int lower) +{ +#ifndef SMP_SYNC + unsigned long x; +#endif + unsigned long pwrdiff= 0x0c; +#ifdef HIGH_POWER_EXT_PA + u4Byte pwr_value = 0x16161616; +#endif + u1Byte pwrlevelHT40_1S_A = priv->pmib->dot11RFEntry.pwrlevelHT40_1S_A[priv->pshare->working_channel-1]; + if ((pwrlevelHT40_1S_A == 0) ) + return; + + if (priv->pmib->dot11RFEntry.tx2path) + pwrdiff= 0x16; + + pwrdiff = (priv->pshare->rf_ft_var.min_pwr_idex > pwrdiff) ? pwrdiff: priv->pshare->rf_ft_var.min_pwr_idex; + pwrdiff |= (pwrdiff<<24) | (pwrdiff<<16) | (pwrdiff<<8); + + if( lower && priv->pshare->phw->lower_tx_power== 0) { + SAVE_INT_AND_CLI(x); + #ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + priv->pshare->phw->power_backup[0x00] = RTL_R32(rTxAGC_A_Rate18_06); + priv->pshare->phw->power_backup[0x01] = RTL_R32(rTxAGC_A_Rate54_24); + priv->pshare->phw->power_backup[0x02] = RTL_R32(rTxAGC_B_Rate18_06); + priv->pshare->phw->power_backup[0x03] = RTL_R32(rTxAGC_B_Rate54_24); + priv->pshare->phw->power_backup[0x04] = RTL_R32(rTxAGC_A_Mcs03_Mcs00); + priv->pshare->phw->power_backup[0x05] = RTL_R32(rTxAGC_A_Mcs07_Mcs04); + priv->pshare->phw->power_backup[0x06] = RTL_R32(rTxAGC_A_Mcs11_Mcs08); + priv->pshare->phw->power_backup[0x07] = RTL_R32(rTxAGC_A_Mcs15_Mcs12); + priv->pshare->phw->power_backup[0x08] = RTL_R32(rTxAGC_B_Mcs03_Mcs00); + priv->pshare->phw->power_backup[0x09] = RTL_R32(rTxAGC_B_Mcs07_Mcs04); + priv->pshare->phw->power_backup[0x0a] = RTL_R32(rTxAGC_B_Mcs11_Mcs08); + priv->pshare->phw->power_backup[0x0b] = RTL_R32(rTxAGC_B_Mcs15_Mcs12); + priv->pshare->phw->power_backup[0x0c] = RTL_R32(rTxAGC_A_CCK11_2_B_CCK11); + priv->pshare->phw->power_backup[0x0d] = RTL_R32(rTxAGC_A_CCK1_Mcs32); + priv->pshare->phw->power_backup[0x0e] = RTL_R32(rTxAGC_B_CCK5_1_Mcs32); + RTL_W32(rTxAGC_A_Mcs03_Mcs00, pwr_value); + RTL_W32(rTxAGC_A_Mcs07_Mcs04, pwr_value); + RTL_W32(rTxAGC_A_Mcs11_Mcs08, pwr_value); + RTL_W32(rTxAGC_A_Mcs15_Mcs12, pwr_value); + RTL_W32(rTxAGC_B_Mcs03_Mcs00, pwr_value); + RTL_W32(rTxAGC_B_Mcs07_Mcs04, pwr_value); + RTL_W32(rTxAGC_B_Mcs11_Mcs08, pwr_value); + RTL_W32(rTxAGC_B_Mcs15_Mcs12, pwr_value); + RTL_W32(rTxAGC_A_CCK1_Mcs32, (pwr_value & 0x0000ff00) | (priv->pshare->phw->power_backup[0x0d] &0xffff00ff)); // A 1M + RTL_W32(rTxAGC_B_CCK5_1_Mcs32, (pwr_value & 0x0000ff00) | (priv->pshare->phw->power_backup[0x0e] &0xffff00ff)); // B 1M + } else +#endif + { + priv->pshare->phw->power_backup[0x00] = RTL_R32(rTxAGC_A_Rate18_06); + priv->pshare->phw->power_backup[0x01] = RTL_R32(rTxAGC_A_Rate54_24); + priv->pshare->phw->power_backup[0x02] = RTL_R32(rTxAGC_B_Rate18_06); + priv->pshare->phw->power_backup[0x03] = RTL_R32(rTxAGC_B_Rate54_24); + priv->pshare->phw->power_backup[0x0c] = RTL_R32(rTxAGC_A_CCK11_2_B_CCK11); + priv->pshare->phw->power_backup[0x0e] = RTL_R32(rTxAGC_B_CCK5_1_Mcs32); + } + + RTL_W32(rTxAGC_A_Rate18_06, priv->pshare->phw->power_backup[0x00]-pwrdiff); + RTL_W32(rTxAGC_A_Rate54_24, priv->pshare->phw->power_backup[0x01]-(pwrdiff & 0xff)); + RTL_W32(rTxAGC_B_Rate18_06, priv->pshare->phw->power_backup[0x02]-pwrdiff); + RTL_W32(rTxAGC_B_Rate54_24, priv->pshare->phw->power_backup[0x03]-(pwrdiff & 0xff)); + RTL_W32(rTxAGC_A_CCK11_2_B_CCK11, priv->pshare->phw->power_backup[0x0c]-pwrdiff); + RTL_W32(rTxAGC_B_CCK5_1_Mcs32, priv->pshare->phw->power_backup[0x0e]-(pwrdiff & 0xffff0000) ); + priv->pshare->phw->lower_tx_power = 1; + RESTORE_INT(x); + } + else if( !lower && priv->pshare->phw->lower_tx_power) { + SAVE_INT_AND_CLI(x); +#ifdef HIGH_POWER_EXT_PA + if (priv->pshare->rf_ft_var.use_ext_pa) { + RTL_W32(rTxAGC_A_Mcs03_Mcs00, priv->pshare->phw->power_backup[0x04]); + RTL_W32(rTxAGC_A_Mcs07_Mcs04, priv->pshare->phw->power_backup[0x05]); + RTL_W32(rTxAGC_A_Mcs11_Mcs08, priv->pshare->phw->power_backup[0x06]); + RTL_W32(rTxAGC_A_Mcs15_Mcs12, priv->pshare->phw->power_backup[0x07]); + RTL_W32(rTxAGC_B_Mcs03_Mcs00, priv->pshare->phw->power_backup[0x08]); + RTL_W32(rTxAGC_B_Mcs07_Mcs04, priv->pshare->phw->power_backup[0x09]); + RTL_W32(rTxAGC_B_Mcs11_Mcs08, priv->pshare->phw->power_backup[0x0a]); + RTL_W32(rTxAGC_B_Mcs15_Mcs12, priv->pshare->phw->power_backup[0x0b]); + RTL_W32(rTxAGC_A_CCK1_Mcs32, priv->pshare->phw->power_backup[0x0d]); + } +#endif + { + RTL_W32(rTxAGC_A_Rate18_06, priv->pshare->phw->power_backup[0x00]); + RTL_W32(rTxAGC_A_Rate54_24, priv->pshare->phw->power_backup[0x01]); + RTL_W32(rTxAGC_B_Rate18_06, priv->pshare->phw->power_backup[0x02]); + RTL_W32(rTxAGC_B_Rate54_24, priv->pshare->phw->power_backup[0x03]); + RTL_W32(rTxAGC_A_CCK11_2_B_CCK11, priv->pshare->phw->power_backup[0x0c]); + RTL_W32(rTxAGC_B_CCK5_1_Mcs32, priv->pshare->phw->power_backup[0x0e]); + } + priv->pshare->phw->lower_tx_power = 0; + RESTORE_INT(x); + } +} +#endif // CONFIG_PCI_HCI + +#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) +void RRSR_power_control_11n(struct rtl8192cd_priv *priv, int lower) +{ + u4Byte val32; + + if (lower && priv->pshare->phw->lower_tx_power == 0) { + priv->pshare->phw->lower_tx_power = 1; + + val32 = RTL_R32(0x6d8); + val32 = (val32 & ~0x001C0000) | 0x00080000; // [ 20:18] = 2 ( -7dB) + RTL_W32(0x6d8, val32); + } else if (!lower && priv->pshare->phw->lower_tx_power) { + priv->pshare->phw->lower_tx_power = 0; + + val32 = RTL_R32(0x6d8); + val32 &= ~0x001C0000; // [ 20:18] = 0 + RTL_W32(0x6d8, val32); + } +} +#endif +#endif // CONFIG_WLAN_HAL_8192EE + +#ifdef CONFIG_WLAN_HAL_8814AE +void RRSR_power_control_14(struct rtl8192cd_priv *priv, int lower) +{ + u4Byte val32; + if (lower && priv->pshare->phw->lower_tx_power == 0) { + priv->pshare->phw->lower_tx_power = 1; + val32 = RTL_R32(0x6d8); + val32 = (val32 & ~0x001C0000) | 0x00080000; // [ 20:18] = 2 ( -7dB) + RTL_W32(0x6d8, val32); + } else if (!lower && priv->pshare->phw->lower_tx_power) { + priv->pshare->phw->lower_tx_power = 0; + val32 = RTL_R32(0x6d8); + val32 &= ~0x001C0000; // [ 20:18] = 0 + RTL_W32(0x6d8, val32); + } +} +#endif + +//3 ============================================================ +//3 PHY calibration +//3 ============================================================ +#ifndef CALIBRATE_BY_ODM + + +void _PHY_SaveADDARegisters(struct rtl8192cd_priv *priv, unsigned int* ADDAReg, unsigned int* ADDABackup, unsigned int RegisterNum) +{ + unsigned int i; + for( i = 0 ; i < RegisterNum ; i++){ + ADDABackup[i] = PHY_QueryBBReg(priv, ADDAReg[i], bMaskDWord); + } +} + +void _PHY_SetADDARegisters(struct rtl8192cd_priv *priv, unsigned int* ADDAReg, unsigned int* ADDASettings, unsigned int RegisterNum) +{ + unsigned int i; + + for( i = 0 ; i < RegisterNum ; i++){ + PHY_SetBBReg(priv, ADDAReg[i], bMaskDWord, ADDASettings[i]); + } +} + +void _PHY_SaveMACRegisters(struct rtl8192cd_priv *priv, unsigned int* MACReg, unsigned int* MACBackup) +{ + unsigned int i; + for( i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++){ + MACBackup[i] = RTL_R8(MACReg[i]); + } + MACBackup[i] = RTL_R32( MACReg[i]); +} + +void _PHY_ReloadADDARegisters(struct rtl8192cd_priv *priv, unsigned int* ADDAReg, unsigned int* ADDABackup, unsigned int RegiesterNum) +{ + unsigned int i; + for(i = 0 ; i < RegiesterNum; i++){ + PHY_SetBBReg(priv, ADDAReg[i], bMaskDWord, ADDABackup[i]); + } +} + +void _PHY_ReloadMACRegisters(struct rtl8192cd_priv *priv,unsigned int* MACReg, unsigned int* MACBackup) +{ + unsigned int i; + for(i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++){ + RTL_W8( MACReg[i], (unsigned char)MACBackup[i]); + } + RTL_W32( MACReg[i], MACBackup[i]); +} + +void _PHY_MACSettingCalibration(struct rtl8192cd_priv *priv, unsigned int* MACReg, unsigned int* MACBackup) +{ + unsigned int i = 0; + RTL_W8(MACReg[i], 0x3F); + for(i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++){ + RTL_W8( MACReg[i], (unsigned char)(MACBackup[i]&(~ BIT(3)))); + } + RTL_W8( MACReg[i], (unsigned char)(MACBackup[i]&(~ BIT(5)))); +} + +void _PHY_PathADDAOn(struct rtl8192cd_priv *priv, unsigned int* ADDAReg, char isPathAOn, char is2T) +{ + unsigned int pathOn; + unsigned int i; + + pathOn = isPathAOn ? 0x04db25a4 : 0x0b1b25a4; + if(FALSE == is2T){ + pathOn = 0x0bdb25a0; + PHY_SetBBReg(priv, ADDAReg[0], bMaskDWord, 0x0b1b25a0); + } + else{ + PHY_SetBBReg(priv, ADDAReg[0], bMaskDWord, pathOn); + } + + for( i = 1 ; i < IQK_ADDA_REG_NUM ; i++){ + PHY_SetBBReg(priv, ADDAReg[i], bMaskDWord, pathOn); + } +} +#endif + + +void PHY_LCCalibrate(struct rtl8192cd_priv *priv) +{ + unsigned char tmpReg, value_IGI; + unsigned int LC_Cal; + int isNormal; + +#if defined(TESTCHIP_SUPPORT) && defined(CONFIG_RTL_92C_SUPPORT) + isNormal = (IS_TEST_CHIP(priv)? 0 : 1); +#else + isNormal = 1; +#endif + + /* Check continuous TX and Packet TX */ + tmpReg = RTL_R8(0xd03); + + if ((tmpReg & 0x70) != 0) /* Deal with contisuous TX case */ + RTL_W8(0xd03, tmpReg&0x8F); /* disable all continuous TX */ + else /* Deal with Packet TX case */ + RTL_W8(0x522, 0xFF); /* block all queues */ + + /* 2. Set RF mode = standby mode */ + if ((tmpReg & 0x70) != 0) { + /* Path-A */ + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x00, bMask20Bits, 0x10000); + + /* Path-B */ + if (get_rf_mimo_mode(priv) != MIMO_1T1R) + PHY_SetRFReg(priv, RF92CD_PATH_B, 0x00, bMask20Bits, 0x10000); + } + + /* 3. Read RF reg18 */ + LC_Cal = PHY_QueryRFReg(priv, RF92CD_PATH_A, 0x18, bMask12Bits, 1); + + /* 4. Set LC calibration begin */ + PHY_SetRFReg(priv, RF92CD_PATH_A, 0x18, bMask12Bits, LC_Cal|0x08000); + + if (GET_CHIP_VER(priv)==VERSION_8192D) + watchdog_kick(); + + if (isNormal) + delay_ms(100); + else + delay_ms(3); + + /* Restore original situation */ + if ((tmpReg & 0x70) != 0) { + /* Deal with contisuous TX case */ + + /* Path-A */ + RTL_W8(0xd03, tmpReg); + + /* Restore RF mdoe & RF gain by change IGI to trigger HW tristate */ + value_IGI = (RTL_R8(0xc50) & 0x7F); + RTL_W8(0xc50, ((value_IGI!=0x30)?0x30:0x31)); + RTL_W8(0xc50, value_IGI); + + /* Path-B */ + if (get_rf_mimo_mode(priv) != MIMO_1T1R) { + /* Restore RF mdoe & RF gain by change IGI to trigger HW tristate */ + value_IGI = (RTL_R8(0xc58) & 0x7F); + RTL_W8(0xc58, ((value_IGI!=0x30)?0x30:0x31)); + RTL_W8(0xc58, value_IGI); + } + } else { + /* Deal with Packet TX case */ + + RTL_W8(0x522, 0x00); + } +} + +#endif + diff --git a/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/HalPwrSeqCmd.c b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/HalPwrSeqCmd.c new file mode 100755 index 000000000..66464d6ff --- /dev/null +++ b/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/HalPwrSeqCmd.c @@ -0,0 +1,177 @@ +/*++ +Copyright (c) Realtek Semiconductor Corp. All rights reserved. + +Module Name: + HalPwrSeqCmd.c + +Abstract: + Implement HW Power sequence configuration CMD handling routine for Realtek devices. + +Major Change History: + When Who What + ---------- --------------- ------------------------------- + 2011-07-07 Roger Create. + +--*/ +#ifdef __ECOS +#include +#include +#include +#include +#endif + + +//#include "Mp_Precomp.h" +#ifdef __KERNEL__ +#include +#endif +#include "8192cd.h" +#include "8192cd_debug.h" +#include "8192cd_headers.h" +#include "8192cd_util.h" + +#if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_RTL_8812_SUPPORT) + +#define TRUE 1 +#define FALSE 0 + +// +// Description: +// This routine deal with the Power Configuration CMDs parsing for RTL8723/RTL8188E Series IC. +// +// Assumption: +// We should follow specific format which was released from HW SD. +// +// 2011.07.07, added by Roger. +// +unsigned int HalPwrSeqCmdParsing(struct rtl8192cd_priv *priv, unsigned char CutVersion, unsigned char FabVersion, + unsigned char InterfaceType, WLAN_PWR_CFG PwrSeqCmd[]) +{ + + WLAN_PWR_CFG PwrCfgCmd = {0}; + unsigned int bPollingBit = FALSE; + unsigned int AryIdx=0; + unsigned char value = 0; + unsigned int offset = 0; + unsigned int pollingCount = 0; // polling autoload done. + unsigned int maxPollingCnt = 5000; + + do { + PwrCfgCmd=PwrSeqCmd[AryIdx]; + + DEBUG_INFO("%s %d, ENTRY, offset:0x%x, cut_msk:0x%x, fab_msk:0x%x, if_msk:0x%x, base:0x%x, cmd:0x%x, msk:0x%x, value:0x%x\n", + __FUNCTION__, __LINE__, GET_PWR_CFG_OFFSET(PwrCfgCmd), GET_PWR_CFG_CUT_MASK(PwrCfgCmd), + GET_PWR_CFG_FAB_MASK(PwrCfgCmd), GET_PWR_CFG_INTF_MASK(PwrCfgCmd), GET_PWR_CFG_BASE(PwrCfgCmd), + GET_PWR_CFG_CMD(PwrCfgCmd), GET_PWR_CFG_MASK(PwrCfgCmd), GET_PWR_CFG_VALUE(PwrCfgCmd)); + + //2 Only Handle the command whose FAB, CUT, and Interface are matched + if((GET_PWR_CFG_FAB_MASK(PwrCfgCmd)&FabVersion)&& + (GET_PWR_CFG_CUT_MASK(PwrCfgCmd)&CutVersion)&& + (GET_PWR_CFG_INTF_MASK(PwrCfgCmd)&InterfaceType)) { + switch(GET_PWR_CFG_CMD(PwrCfgCmd)) + { + case PWR_CMD_READ: + DEBUG_INFO("%s %d, PWR_CMD_READ\n", __FUNCTION__, __LINE__); + break; + + case PWR_CMD_WRITE: + DEBUG_INFO("%s %d, PWR_CMD_WRITE\n", __FUNCTION__, __LINE__); + offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); + +#ifdef CONFIG_SDIO_HCI + // + // We should deal with interface specific address mapping for some interfaces, e.g., SDIO interface + // 2011.07.07. + // + if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) + { + // Read Back SDIO Local value + value = SdioLocalCmd52Read1Byte(priv, offset); + + value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd)); + value |= (GET_PWR_CFG_VALUE(PwrCfgCmd) & GET_PWR_CFG_MASK(PwrCfgCmd)); + + // Write Back SDIO Local value + SdioLocalCmd52Write1Byte(priv, offset, value); + } + else +#endif + { + //Read the value from system register + value = RTL_R8(offset); + value = value&(~(GET_PWR_CFG_MASK(PwrCfgCmd))); + value = value|(GET_PWR_CFG_VALUE(PwrCfgCmd)&GET_PWR_CFG_MASK(PwrCfgCmd)); + + //Write the value back to sytem register + RTL_W8(offset, value); + } + break; + + case PWR_CMD_POLLING: + DEBUG_INFO("%s %d, PWR_CMD_POLLING\n", __FUNCTION__, __LINE__); + bPollingBit = FALSE; + offset = GET_PWR_CFG_OFFSET(PwrCfgCmd); + + do { +#ifdef CONFIG_SDIO_HCI + if (GET_PWR_CFG_BASE(PwrCfgCmd) == PWR_BASEADDR_SDIO) + value = SdioLocalCmd52Read1Byte(priv, offset); + else +#endif + value = RTL_R8(offset); + value=value&GET_PWR_CFG_MASK(PwrCfgCmd); + if(value==(GET_PWR_CFG_VALUE(PwrCfgCmd)&GET_PWR_CFG_MASK(PwrCfgCmd))) + bPollingBit=TRUE; + else + delay_us(10); + + if(pollingCount++ > maxPollingCnt){ + int i, j, len; + unsigned char tmpbuf[100]; + + printk("%s %d, PWR_CMD_POLLING, Fail to polling Offset[0x%x]\n", __FUNCTION__, __LINE__, offset); + + panic_printk("\nMAC Registers:\n"); + for (i=0; i<0x100; i+=0x10) { + len = sprintf((char *)tmpbuf, "%03X\t", i); + for (j=i; j