From 3a429077981db3a7cf96d1e503c0bbbc932cab32 Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Mon, 1 Dec 2014 01:55:47 +0530 Subject: [PATCH] added_missing_driver_code --- drivers/staging/mt7601u/TODO~ | 10 + drivers/staging/mt7601u/common/image.bin | Bin 0 -> 67936 bytes drivers/staging/mt7601u/common/rt2870_wow.bin | Bin 0 -> 12288 bytes drivers/staging/mt7601u/mcu/bin/MT7601.bin | Bin 0 -> 45412 bytes .../staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin | Bin 0 -> 47032 bytes .../mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin | Bin 0 -> 51944 bytes drivers/staging/mt7601u/mcu/bin/MT7650.bin | Bin 0 -> 59580 bytes drivers/staging/mt7601u/mcu/bin/RT85592.bin | Bin 0 -> 35060 bytes drivers/staging/mt7601u/mcu/bin/rt2860.bin | Bin 0 -> 512 bytes drivers/staging/mt7601u/mcu/bin/rt2870.bin | Bin 0 -> 8192 bytes drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin | Bin 0 -> 12288 bytes drivers/staging/mt7601u/os/linux/rt_linux.c~ | 6215 ++++++++++++++++++++ 12 files changed, 6225 insertions(+) create mode 100644 drivers/staging/mt7601u/TODO~ create mode 100755 drivers/staging/mt7601u/common/image.bin create mode 100755 drivers/staging/mt7601u/common/rt2870_wow.bin create mode 100755 drivers/staging/mt7601u/mcu/bin/MT7601.bin create mode 100755 drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin create mode 100755 drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin create mode 100755 drivers/staging/mt7601u/mcu/bin/MT7650.bin create mode 100755 drivers/staging/mt7601u/mcu/bin/RT85592.bin create mode 100755 drivers/staging/mt7601u/mcu/bin/rt2860.bin create mode 100755 drivers/staging/mt7601u/mcu/bin/rt2870.bin create mode 100755 drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin create mode 100755 drivers/staging/mt7601u/os/linux/rt_linux.c~ diff --git a/drivers/staging/mt7601u/TODO~ b/drivers/staging/mt7601u/TODO~ new file mode 100644 index 0000000..891bd12 --- /dev/null +++ b/drivers/staging/mt7601u/TODO~ @@ -0,0 +1,10 @@ +This driver is functional and has been tested on Raspian(Debian Wheezy) with excellent expected behaviour. + +TODO: + - kernel coding style + - checkpatch warnings + - dead code elimination + - device tree bindings + - possibly eliminate the extra "hardware abstraction layer" + +Contact: Parth Sane or diff --git a/drivers/staging/mt7601u/common/image.bin b/drivers/staging/mt7601u/common/image.bin new file mode 100755 index 0000000000000000000000000000000000000000..f357c59ab407d3a24c6032ac955403bae675806b GIT binary patch literal 67936 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 Q?_95QEoy5MS?2HbA3OKtssI20 literal 0 HcmV?d00001 diff --git a/drivers/staging/mt7601u/common/rt2870_wow.bin b/drivers/staging/mt7601u/common/rt2870_wow.bin new file mode 100755 index 0000000000000000000000000000000000000000..bfae0f0ab0e30fbf06a1e3a32cbe94238d0439f7 GIT binary patch literal 12288 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 BP2~Up literal 0 HcmV?d00001 diff --git a/drivers/staging/mt7601u/mcu/bin/MT7601.bin b/drivers/staging/mt7601u/mcu/bin/MT7601.bin new file mode 100755 index 0000000000000000000000000000000000000000..62b3894310da4d8c77b97f6b8df9ab6d3d6b28d0 GIT binary patch literal 45412 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 EU!&NiyZ`_I literal 0 HcmV?d00001 diff --git a/drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin b/drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin new file mode 100755 index 0000000000000000000000000000000000000000..da534ee0a88337ba207fab8bbabb8fae7cc3d98e GIT binary patch literal 47032 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 literal 0 HcmV?d00001 diff --git a/drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin b/drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin new file mode 100755 index 0000000000000000000000000000000000000000..2cd32e72fc70c55d50b327195a6b17799ea78dc5 GIT binary patch literal 51944 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 CnsToI literal 0 HcmV?d00001 diff --git a/drivers/staging/mt7601u/mcu/bin/MT7650.bin b/drivers/staging/mt7601u/mcu/bin/MT7650.bin new file mode 100755 index 0000000000000000000000000000000000000000..766aaba744e6e067aa18479812e2e06cc5968b53 GIT binary patch literal 59580 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 literal 0 HcmV?d00001 diff --git a/drivers/staging/mt7601u/mcu/bin/RT85592.bin b/drivers/staging/mt7601u/mcu/bin/RT85592.bin new file mode 100755 index 0000000000000000000000000000000000000000..cee5252de2ea770ebb94ef0c660ce668024cbba0 GIT binary patch literal 35060 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 QjWq)S!5BdtP%5q7rD(55hAGbL5M_RN7I#^?A zh69?R3cVBB0eq0SZ`@EZ6BU5%%+sV+I7vHLcyRrIG^czke>HTdns&ig$>+Uhq?uzz z;sew`n`t9zUow-Yn4ifN$R38ra4kF()K$BYcf)Vk!NUjFVx|#w(mAk$!smKO_zZlq z@S0PWQSAJ{ld0lK?8hSh7dt_GsAcEd;@|~IRTDT9HVE94=FV?%f(~iG|4RAH+y}if z{o>S^Jb}Eypl5CR^UKs0l6f!VJnNYjKFXvhHaI#VKhOBB$kn;%mQ5YMQ89u^$eFlz zY}y}JcpzauGpbQ-bg5x^J@HYfXi_|L_)f%O+q#mMBkls;dN~RYKu888y$RYSjpDn? z3wS=O^3%@Go;vgNH$VM*#7MiX9E0GBsHVLi;e|tZz89s|A2d%kip4dev|Y%EjOH4= zJ1?N`vf!fD#f;oVHLb{ye8{y6ZP&*cXqQgIqAka~dx~L2`M&&$q12BGQJX(Rp%0w0 zo6=$`T4Anv3^BrB43dg{cyCONjBYpDOZGLeh!1tWs%lxTWvFJkUhiUnpa1#|enyi} ztD03pGMGE3YvEx4MyN_=!{@E)cl3QG!UcJQ8f!I_S}(Y7UAg(aV?r!`aXUY4fR zqTcAfX6K@nG|Fg7q{G5bqcYUxRL5;QpL=?0LTTOebk?)?(`up}rxU-jaCsCI4Cw!; zgz8?!i7P^m2l5oyH*^6NKPlO`zB)P@VXxnx%AZ^>)%8A9$7UGqhEczwK4SD8syLMG zK88IT@3@~N2YwQMvik+-Q4OSeJs0C=?OqBgbVJX0bvmhrKjhómomDJFy54r;9J*ngD9 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 E17Xg7aR2}S literal 0 HcmV?d00001 diff --git a/drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin b/drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin new file mode 100755 index 0000000000000000000000000000000000000000..bfae0f0ab0e30fbf06a1e3a32cbe94238d0439f7 GIT binary patch literal 12288 zcmeG?3vd)ib~`<@A4wqX&VGd?SmsuI76ZfAwgi$6Nq}KN0v48!fPqplwjm7m?zx<@ z*oiQyx=ZdD>#!3ib>%B5bxEkW6cZWSbvbaY9GB~yPi0lfxhip013O$L7}OOrHaM0x zuX}f`m9VgElZ#V9Tbk*9{od=>J>9S0>-VzREOO36&U)nhJ>=bwybAKQAm0x~U#o8l`?piDOO|Mz%&PC7OgPr zpi<&6>IQf|W3GitDXnm{lJ6lcFu`tSsVw{9>B8F^+jKQRXi--yNgh%53Tclv2U@V% zsH6E9a4YfX@IELLd7aSTs0l_R@Imv2i>He}&W?P~zn^=`C$f&N2KS=uGOJPBBls@Ilm>uSBbC0gd zq>q^4l>dttBb``SPd~ovQqf_sy7K`7yD#3vK4~;*#&A^ARp=2oWR2L+%T3L?y3B~> z08qq(FAtp&nx4X;&j|g_OL3cSwGd-xv_cV*e%Q_~-O3Gv*c^%TBr8r2Yl8(A%P562 z&qAi$Lc)}}yv1aiQjf($OBPmX(NwX03KO&;Z7s|-+wz6AqdcRj`8o8_wQhEdLxbrz zc9TA156R@dhMTTxrA4c!$iUZ6iOs#^h-AOJNGu#BW~_BDtYgqOl-RDTwe%ZHlF`t* zS}8ReybWrpceQ5AEnNoXk+0kcgI4mD$A4P8*zC?MkC-R1@;k{BqQ7A{I@*FpXfb3g zPFiYV2Zk(WcYISrf43g_bJ8~q^6oHW$s`~H0DsztYhz~jf2`PHo*X9Dm=RNvb;sZt z&De2s^QO3rPP zHwo6YDZyxK-K;o_HgB7XyqjT=OF}o43XkISC}K!Z1ETM^=1sL~u8cWbo0cv~m!`|o z(=;?B4T4fcxWz$EJ=}fjp_9fkVl3^09f5H46C%kTSVongmtbK9aNC!wpOi=TDXD(l zDZow#g@mJ4GiG#ja_Vd&22dH>=oZxk47=2b$(NT{_ZWNB1=ii#T&UtIqXV$iA|%#c z2JLpr6sXeulJ2a&PUpKXUJCoG8k;+H=S&>D^bxewP;l9JaQ{vzwJ{YjTHpxtKVu2l zg#hpHUvc_>81%oQ_%Hm_VhNO-THkzX!ZP4Y-#s>OYV?^kS zwW|lVHCJdIryglOwQ?N%Nui`0HE`7#068!=MGVy6HifV*qEO%J>E!vm5(@7@a#De1euPp>vN1kJ8d* zbnZxEQB&|Sq4%&hM?P#b*7jc3YACjlj20x^6gTRX=^Q@!%P`sSF>$@>Dv|&V^Ql~I5mi7gQo#? zSdZ#Dx|!s4d{#p@v!|IE5FI5(Gb}KVGA%R;|Ger>-O?)3x3n^2t$dlu*>g)?XYFr9 zRcEM$Kws2?seq?Lfn^6443DbN7x4a!7+@+h?)Wnt(u<&n^B#Sgd1VP1wG1akFo%SYX#v%5N<=UaN7LzZLO}TH*MivM7s@3{qsq?t)X#3 zfe6Dyg0)-br1n?z8ZjE9*IHY_w#*cauvRd_TJuJjbh0OEKoQ`_ImL+{)W`9Q)mV+r?4W>Bq(}$Q0idBD0^C3BIotrE-urw-^T%Z;At0YS$|V`kQ%_Vap z_$MzC+MMFR9bgDsVR;KM_L`q1wgN|<8EfU#A_^!oL3|9u0Q0E|-t$58TcIpLc>w`y z5eC>&0RzcBpb5s!v%&blssbmZ4}7A$DV5~FmZBe}$&fyp4G`XnrATZZKnSnh-^HRqlOI?Y< zm)ji$FM=83T~@}8N&5XRl&}0;ob~-KK3@TupYIa#m0!?GNxt&BIO|Wl9Qn$5TCwLV zui+6YV5rNM2MiPdoH*+*Gb8ZO9M-wUTrj}qz@T8rxxU%3Bt~>cG0#FOyo<2LfnbJc z-;!kc=6|yfXxVRp|Np@x{{Q*^dH?@xkstBD=>Jb520K0PjsJgks{a4kd*uJ;hxB#* z|4C+qxndLj|H*K_P5%E`{T})McNy$&!v9}?PyGM&+FSHXPU*&B{g^?!I9~Aoi)Y~u z|G&7AdgGJ$|9P~p=Ktr3?)(4u{r{=>|L5=f|M&g>wRcVzWgD|LI!7Vchj$R^# zAQTPh>T2Dv(5aAG%?*z*8mgb2Hag{%g+6mNl% zsP%a0jJ>H&M+>MAQ;(ze(Kz?+jdvXy8eI1NXE*ml3qy%37`G9voG~29 zF$DJRd2m767l+G3xKS)b5g{_@`51YIAyAx;D;6Luin*6TbN3gys|$u*oZT?N5h{>R zA-e&hD71Il5nSCnaA%O!b4d>1aDC+rhe<@CUf?KYH*)>fRWrttA-){d?EcY72>9I< z`#0_UXK2JfRh9Ck{E5B!p#NF;L^QTv{L|HkU}Zd<%K|7T>DDh^V&fv%g%3w(3*s92 zOn}MeY4S{f2Iv{Q?m{L&<5(s@I_fgZX; z-N5}gD5#0xd7yxtMK?!b=Xkx`3IS0nq$~pKt(fzx{ z+X9g(#oPQV*c{~IZGi}jw*?|J-WG@y#oGXFEZ+7x8VW#sHWzOTG~cs$+ul3lZ8;E& zx9$Dv@ivI_-#y+22!(iCrSG1{+b&Oxx82>|uB?>5mGL$S%!jKA?;Dh^dp;gwwND*a zHz?DnS#i}DP&wKZ%8q=vJPV+Y9q(L!XGo&zYeq^}m(vYNH=P0X3%a_3)gc;q9QL;W z(ZJ&t0uKby$FMkKP(RM&(M-say|G*y6|3r-gw&&u9r7s4&>11Uk9Hqw2kr1MXb1Vx zgA)mW4;}%I_^4U}MivfLk7%gN@~mZeVfMp@QE|rA0&$)nNC8>|sE#RK`ht!#%eB+p z5Zwhh$KqMF?b9C{U&oumITBnJ10z zkQGWRPC^Gk2$IiC{kxojSot%#%4C?ADCYRa@&cQz{`4703Hxn0nf9yWH@SyCrc<$M4@2`$;~QFWQ1v} z)DK&+d>Im7S3@*ii|L0U4WN9`tvzy$O)}*e<+CavK-NNqw)7%b#)<@TSG3SLq>Bi! zIEppxA`eNvP^4JEnp_Ln^WwqR%+2v?tUxXer+6?}#}&BKs+3|#-Lm3Ny9!C1lMEnx z!g5g)l8B}b4TsKVGYzA;@jPphGeVa@HwbKx8>>dgX5^U4-C&)j53#Si8bcb?RJ%C; zb-NH$$WxxuD9%l}3-v(ykhT{l6x;}P`xM!~J$3ddeQ4-jM8dy$EdBo?hs#eK`)|m} BP2~Up literal 0 HcmV?d00001 diff --git a/drivers/staging/mt7601u/os/linux/rt_linux.c~ b/drivers/staging/mt7601u/os/linux/rt_linux.c~ new file mode 100755 index 0000000..49193e6 --- /dev/null +++ b/drivers/staging/mt7601u/os/linux/rt_linux.c~ @@ -0,0 +1,6215 @@ +/**************************************************************************** + + Module Name: + UTIL/rt_linux.c + + Abstract: + All functions provided from OS module are put here. + + Note: + 1. Can not use sizeof() for a structure with any parameter included + by any compile option, such as RTMP_ADAPTER. + + Because the RTMP_ADAPTER size in the UTIL module is different with + DRIVER/NETIF. + + 2. Do not use any structure with any parameter included by PCI/USB/RBUS/ + AP/STA. + + Because the structure size in the UTIL module is different with + DRIVER/NETIF. + + 3. Do not use any structure defined in DRIVER module, EX: pAd. + So we can do module partition. + + Revision History: + Who When What + --------- ---------- ------------------------------------------- + +***************************************************************************/ + +#define RTMP_MODULE_OS +#define RTMP_MODULE_OS_UTIL + + +#include "rtmp_comm.h" +#include "rtmp_osabl.h" +#include "rt_os_util.h" +#include + +#if defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE) +#include "../../../../../../net/nat/hw_nat/ra_nat.h" +#include "../../../../../../net/nat/hw_nat/frame_engine.h" +#endif + +/* TODO */ +#undef RT_CONFIG_IF_OPMODE_ON_AP +#undef RT_CONFIG_IF_OPMODE_ON_STA + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) if (__OpMode == OPMODE_AP) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) if (__OpMode == OPMODE_STA) +#else +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) +#endif + +ULONG RTDebugLevel = RT_DEBUG_TRACE; +ULONG RTDebugFunc = 0; + +#ifdef OS_ABL_FUNC_SUPPORT +ULONG RTPktOffsetData = 0, RTPktOffsetLen = 0, RTPktOffsetCB = 0; +#endif /* OS_ABL_FUNC_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT +#if defined(CONFIG_RA_CLASSIFIER) || defined(CONFIG_RA_CLASSIFIER_MODULE) +extern int (*ra_classifier_hook_rx) (struct sk_buff *skb, unsigned long cycle); +extern volatile unsigned long classifier_cur_cycle; +#endif /* CONFIG_RA_CLASSIFIER */ +#endif /* RTMP_RBUS_SUPPORT */ + +#ifdef VENDOR_FEATURE4_SUPPORT +ULONG OS_NumOfMemAlloc = 0, OS_NumOfMemFree = 0; +#endif /* VENDOR_FEATURE4_SUPPORT */ +#ifdef VENDOR_FEATURE2_SUPPORT +ULONG OS_NumOfPktAlloc = 0, OS_NumOfPktFree = 0; +#endif /* VENDOR_FEATURE2_SUPPORT */ + +/* + * the lock will not be used in TX/RX + * path so throughput should not be impacted + */ +BOOLEAN FlgIsUtilInit = FALSE; +OS_NDIS_SPIN_LOCK UtilSemLock; + +#if 0 /* os abl move to os/linux/rt_profile.c */ +#ifdef SYSTEM_LOG_SUPPORT +/* for wireless system event message */ +char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = { + /* system status event */ + "had associated successfully", /* IW_ASSOC_EVENT_FLAG */ + "had disassociated", /* IW_DISASSOC_EVENT_FLAG */ + "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */ + "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */ + "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */ + /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */ + "occurred replay counter different in Key Handshaking", + /* IW_RSNIE_DIFF_EVENT_FLAG */ + "occurred RSNIE different in Key Handshaking", + /* IW_MIC_DIFF_EVENT_FLAG */ + "occurred MIC different in Key Handshaking", + "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */ + "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */ + "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */ + /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */ + "Pairwise Key Handshaking timeout", + "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */ + "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */ + "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */ + "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */ + /* IW_STA_LINKDOWN_EVENT_FLAG */ + "disconnects with our wireless client", + "scan completed", /* IW_SCAN_COMPLETED_EVENT_FLAG */ + /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */ + "scan terminate!! Busy!! Enqueue fail!!", + "channel switch to ", /* IW_CHANNEL_CHANGE_EVENT_FLAG */ + "wireless mode is not support", /* IW_STA_MODE_EVENT_FLAG */ + /* IW_MAC_FILTER_LIST_EVENT_FLAG */ + "blacklisted in MAC filter list", + /* IW_AUTH_REJECT_CHALLENGE_FAILURE */ + "Authentication rejected because of challenge failure", + "Scanning", /* IW_SCANNING_EVENT_FLAG */ + "Start a new IBSS", /* IW_START_IBSS_FLAG */ + "Join the IBSS", /* IW_JOIN_IBSS_FLAG */ + "Shared WEP fail", /* IW_SHARED_WEP_FAIL */ +}; + +#ifdef IDS_SUPPORT +/* for wireless IDS_spoof_attack event message */ +char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = { + "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */ + /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */ + "detected spoofed association response", + /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */ + "detected spoofed reassociation responses", + /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */ + "detected spoofed probe response", + "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */ + "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */ + "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */ + "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */ + /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */ + "detected spoofed unknown management frame", + "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */ +}; + +/* for wireless IDS_flooding_attack event message */ +char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = { + "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */ + /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */ + "detected association request flooding", + /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */ + "detected reassociation request flooding", + "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */ + /* IW_FLOOD_DISASSOC_EVENT_FLAG */ + "detected disassociation flooding", + /* IW_FLOOD_DEAUTH_EVENT_FLAG */ + "detected deauthentication flooding", + /* IW_FLOOD_EAP_REQ_EVENT_FLAG */ + "detected 802.1x eap-request flooding" +}; +#endif /* IDS_SUPPORT */ + +#ifdef WSC_INCLUDED +/* for WSC wireless event message */ +char const *pWirelessWscEventText[IW_WSC_EVENT_TYPE_NUM] = { + "PBC Session Overlap", /* IW_WSC_PBC_SESSION_OVERLAP */ + /* IW_WSC_REGISTRAR_SUPPORT_PBC */ + "This WPS Registrar supports PBC", + /* IW_WSC_REGISTRAR_SUPPORT_PIN */ + "This WPS Registrar supports PIN", + "WPS status success", /* IW_WSC_STATUS_SUCCESS */ + "WPS status fail", /* IW_WSC_STATUS_FAIL */ + "WPS 2 mins time out!", /* IW_WSC_2MINS_TIMEOUT */ + "WPS Send EAPOL_Start!", /* IW_WSC_SEND_EAPOL_START */ + "WPS Send WscStart!", /* IW_WSC_SEND_WSC_START */ + "WPS Send M1!", /* IW_WSC_SEND_M1 */ + "WPS Send M2!", /* IW_WSC_SEND_M2 */ + "WPS Send M3!", /* IW_WSC_SEND_M3 */ + "WPS Send M4!", /* IW_WSC_SEND_M4 */ + "WPS Send M5!", /* IW_WSC_SEND_M5 */ + "WPS Send M6!", /* IW_WSC_SEND_M6 */ + "WPS Send M7!", /* IW_WSC_SEND_M7 */ + "WPS Send M8!", /* IW_WSC_SEND_M8 */ + "WPS Send WscDone!", /* IW_WSC_SEND_DONE */ + "WPS Send WscAck!", /* IW_WSC_SEND_ACK */ + "WPS Send WscNack!", /* IW_WSC_SEND_NACK */ + "WPS Receive WscStart!", /* IW_WSC_RECEIVE_WSC_START */ + "WPS Receive M1!", /* IW_WSC_RECEIVE_M1 */ + "WPS Receive M2!", /* IW_WSC_RECEIVE_M2 */ + "WPS Receive M3!", /* IW_WSC_RECEIVE_M3 */ + "WPS Receive M4!", /* IW_WSC_RECEIVE_M4 */ + "WPS Receive M5!", /* IW_WSC_RECEIVE_M5 */ + "WPS Receive M6!", /* IW_WSC_RECEIVE_M6 */ + "WPS Receive M7!", /* IW_WSC_RECEIVE_M7 */ + "WPS Receive M8!", /* IW_WSC_RECEIVE_M8 */ + "WPS Receive WscDone!", /* IW_WSC_RECEIVE_DONE */ + "WPS Receive WscAck!", /* IW_WSC_RECEIVE_ACK */ + "WPS Receive WscNack!", /* IW_WSC_RECEIVE_NACK */ + "Not only one candidate found" /* IW_WSC_MANY_CANDIDATE */ +}; +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_STA_SUPPORT +#ifdef IWSC_SUPPORT +/* for IWSC wireless event message */ +char const *pWirelessIWscEventText[IW_IWSC_EVENT_TYPE_NUM] = { + "IWSC - T1 mins time out!", /* IW_IWSC_T1_TIMER_TIMEOUT */ + "IWSC - T2 mins time out!", /* IW_IWSC_T2_TIMER_TIMEOUT */ + "IWSC - Become Registrar", /* IW_IWSC_BECOME_REGISTRAR */ + "IWSC - Become Enrollee", /* IW_IWSC_BECOME_ENROLLEE */ + "IWSC - Entry time out", /* IW_IWSC_ENTRY_TIMER_TIMEOUT */ + }; +#endif /* IWSC_SUPPORT */ +#endif /* CONFIG_STA_SUPPORT */ +#endif /* SYSTEM_LOG_SUPPORT */ +#endif /* 0 */ + +BOOLEAN RTMP_OS_Alloc_RscOnly(VOID *pRscSrc, UINT32 RscLen); +BOOLEAN RTMP_OS_Remove_Rsc(LIST_HEADER *pRscList, VOID *pRscSrc); + +/* +======================================================================== +Routine Description: + Initialize something in UTIL module. + +Arguments: + None + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpUtilInit(VOID) +{ + if (FlgIsUtilInit == FALSE) { + OS_NdisAllocateSpinLock(&UtilSemLock); + FlgIsUtilInit = TRUE; + } +} + +/* timeout -- ms */ +static inline VOID __RTMP_SetPeriodicTimer( + IN OS_NDIS_MINIPORT_TIMER * pTimer, + IN unsigned long timeout) +{ + timeout = ((timeout * OS_HZ) / 1000); + pTimer->expires = jiffies + timeout; + add_timer(pTimer); +} + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +static inline VOID __RTMP_OS_Init_Timer( + IN VOID *pReserved, + IN OS_NDIS_MINIPORT_TIMER * pTimer, + IN TIMER_FUNCTION function, + IN PVOID data) +{ + if (!timer_pending(pTimer)) { + init_timer(pTimer); + pTimer->data = (unsigned long)data; + pTimer->function = function; + } +} + +static inline VOID __RTMP_OS_Add_Timer( + IN OS_NDIS_MINIPORT_TIMER * pTimer, + IN unsigned long timeout) +{ + if (timer_pending(pTimer)) + return; + + timeout = ((timeout * OS_HZ) / 1000); + pTimer->expires = jiffies + timeout; + add_timer(pTimer); +} + +static inline VOID __RTMP_OS_Mod_Timer( + IN OS_NDIS_MINIPORT_TIMER * pTimer, + IN unsigned long timeout) +{ + timeout = ((timeout * OS_HZ) / 1000); + mod_timer(pTimer, jiffies + timeout); +} + +static inline VOID __RTMP_OS_Del_Timer( + IN OS_NDIS_MINIPORT_TIMER * pTimer, + OUT BOOLEAN *pCancelled) +{ + if (timer_pending(pTimer)) + *pCancelled = del_timer_sync(pTimer); + else + *pCancelled = TRUE; +} + +static inline VOID __RTMP_OS_Release_Timer( + IN OS_NDIS_MINIPORT_TIMER * pTimer) +{ + /* nothing to do */ +} + +#if 0 +VOID RTMP_OS_Release_Packet( + IN PRTMP_ADAPTER pAd, + IN PQUEUE_ENTRY pEntry) +{ + /*RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); */ +} +#endif /* Unused */ + +/* Unify all delay routine by using udelay */ +VOID RTMPusecDelay(ULONG usec) +{ + ULONG i; + + for (i = 0; i < (usec / 50); i++) + udelay(50); + + if (usec % 50) + udelay(usec % 50); +} + + +/* Unify all delay routine by using udelay */ +VOID RtmpOsUsDelay(ULONG value) +{ + ULONG i; + + udelay(value); +} + +VOID RtmpOsMsDelay(ULONG msec) +{ + mdelay(msec); +} + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER * time) +{ + time->u.LowPart = jiffies; +} + +void RTMP_GetCurrentSystemTick(ULONG *pNow) +{ + *pNow = jiffies; +} + +/* pAd MUST allow to be NULL */ + +NDIS_STATUS os_alloc_mem( + IN VOID *pReserved, + OUT UCHAR **mem, + IN ULONG size) +{ + *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC); + if (*mem) { +#ifdef VENDOR_FEATURE4_SUPPORT + OS_NumOfMemAlloc++; +#endif /* VENDOR_FEATURE4_SUPPORT */ + + return NDIS_STATUS_SUCCESS; + } else + return NDIS_STATUS_FAILURE; +} + +NDIS_STATUS os_alloc_mem_suspend( + IN VOID *pReserved, + OUT UCHAR **mem, + IN ULONG size) +{ + *mem = (PUCHAR) kmalloc(size, GFP_KERNEL); + if (*mem) { +#ifdef VENDOR_FEATURE4_SUPPORT + OS_NumOfMemAlloc++; +#endif /* VENDOR_FEATURE4_SUPPORT */ + + return NDIS_STATUS_SUCCESS; + } else + return NDIS_STATUS_FAILURE; +} + +/* pAd MUST allow to be NULL */ +NDIS_STATUS os_free_mem( + IN VOID *pReserved, + IN PVOID mem) +{ + ASSERT(mem); + kfree(mem); + +#ifdef VENDOR_FEATURE4_SUPPORT + OS_NumOfMemFree++; +#endif /* VENDOR_FEATURE4_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + +#if defined(RTMP_RBUS_SUPPORT) || defined (RTMP_FLASH_SUPPORT) +/* The flag "CONFIG_RALINK_FLASH_API" is used for APSoC Linux SDK */ +#ifdef CONFIG_RALINK_FLASH_API + +int32_t FlashRead( + uint32_t *dst, + uint32_t *src, + uint32_t count); + +int32_t FlashWrite( + uint16_t *source, + uint16_t *destination, + uint32_t numBytes); +#else /* CONFIG_RALINK_FLASH_API */ + +#ifdef RA_MTD_RW_BY_NUM +#if defined (CONFIG_RT2880_FLASH_32M) +#define MTD_NUM_FACTORY 5 +#else +#define MTD_NUM_FACTORY 2 +#endif +extern int ra_mtd_write(int num, loff_t to, size_t len, const u_char *buf); +extern int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf); +#else +extern int ra_mtd_write_nm(char *name, loff_t to, size_t len, const u_char *buf); +extern int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf); +#endif + +#endif /* CONFIG_RALINK_FLASH_API */ + +void RtmpFlashRead( + UCHAR *p, + ULONG a, + ULONG b) +{ +#ifdef CONFIG_RALINK_FLASH_API + FlashRead((uint32_t *) p, (uint32_t *) a, (uint32_t) b); +#else +#ifdef RA_MTD_RW_BY_NUM + ra_mtd_read(MTD_NUM_FACTORY, 0, (size_t) b, p); +#else + ra_mtd_read_nm("Factory", a&0xFFFF, (size_t) b, p); +#endif +#endif /* CONFIG_RALINK_FLASH_API */ +} + +void RtmpFlashWrite( + UCHAR * p, + ULONG a, + ULONG b) +{ +#ifdef CONFIG_RALINK_FLASH_API + FlashWrite((uint16_t *) p, (uint16_t *) a, (uint32_t) b); +#else +#ifdef RA_MTD_RW_BY_NUM + ra_mtd_write(MTD_NUM_FACTORY, 0, (size_t) b, p); +#else + ra_mtd_write_nm("Factory", a&0xFFFF, (size_t) b, p); +#endif +#endif /* CONFIG_RALINK_FLASH_API */ +} +#endif /* defined(RTMP_RBUS_SUPPORT) || defined (RTMP_FLASH_SUPPORT) */ + + +PNDIS_PACKET RtmpOSNetPktAlloc(VOID *dummy, int size) +{ + struct sk_buff *skb; + /* Add 2 more bytes for ip header alignment */ + skb = dev_alloc_skb(size + 2); + if (skb != NULL) + MEM_DBG_PKT_ALLOC_INC(skb); + + return ((PNDIS_PACKET) skb); +} + +PNDIS_PACKET RTMP_AllocateFragPacketBuffer(VOID *dummy, ULONG len) +{ + struct sk_buff *pkt; + + pkt = dev_alloc_skb(len); + + if (pkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("can't allocate frag rx %ld size packet\n", len)); + } + + if (pkt) { + MEM_DBG_PKT_ALLOC_INC(pkt); + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + } + + return (PNDIS_PACKET) pkt; +} + +#if 0 /* os abl move to os/linux/rt_profile.c */ +VOID RTMPFreeAdapter( + IN PRTMP_ADAPTER pAd) +{ + POS_COOKIE os_cookie; + int index; + + os_cookie = (POS_COOKIE) pAd->OS_Cookie; + + if (pAd->BeaconBuf) + os_free_mem(NULL, pAd->BeaconBuf); + + NdisFreeSpinLock(&pAd->MgmtRingLock); + +#ifdef RTMP_MAC_PCI + NdisFreeSpinLock(&pAd->RxRingLock); +#if defined(RT3090) || defined(RT3592) || defined(RT3390) || defined(RT3593) + NdisFreeSpinLock(&pAd->McuCmdLock); +#endif /* defined(RT3090) || defined(RT3592) || defined(RT3390) || defined(RT3593) */ +#endif /* RTMP_MAC_PCI */ + + for (index = 0; index < NUM_OF_TX_RING; index++) { + NdisFreeSpinLock(&pAd->TxSwQueueLock[index]); + NdisFreeSpinLock(&pAd->DeQueueLock[index]); + pAd->DeQueueRunning[index] = FALSE; + } + + NdisFreeSpinLock(&pAd->irq_lock); + NdisFreeSpinLock(&pAd->TimerSemLock); + +#ifdef CONFIG_AP_SUPPORT +#ifdef UAPSD_SUPPORT + NdisFreeSpinLock(&pAd->UAPSDEOSPLock); /* OS_ABL_SUPPORT */ +#endif /* UAPSD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + if (os_cookie) + os_free_mem(NULL, os_cookie); + + { +#ifdef VENDOR_FEATURE4_SUPPORT + extern ULONG OS_NumOfMemAlloc, OS_NumOfMemFree; + printk(KERN_ERR "OS_NumOfMemAlloc = %ld, OS_NumOfMemFree = %ld\n", + OS_NumOfMemAlloc, OS_NumOfMemFree); +#endif /* VENDOR_FEATURE4_SUPPORT */ +#ifdef VENDOR_FEATURE2_SUPPORT + printk(KERN_ERR "Number of Packet Allocated = %d\n" + , pAd->NumOfPktAlloc); + printk(KERN_ERR "Number of Packet Freed = %d\n" + , pAd->NumOfPktFree); +#endif /* VENDOR_FEATURE2_SUPPORT */ + } + + /* + * pci_free_consistent(os_cookie->pci_dev, + * sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa); + */ + vfree(pAd); +} +#endif /* 0 */ + +#if 0 +VOID build_tx_packet( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pFrame, + IN ULONG FrameLen) +{ + + struct sk_buff *pTxPkt; + + ASSERT(pPacket); + pTxPkt = RTPKT_TO_OSPKT(pPacket); + + NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen); +} + +PNDIS_PACKET RTMP_AllocateTxPacketBuffer( + IN PRTMP_ADAPTER pAd, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID * VirtualAddress) +{ + struct sk_buff *pkt; + + pkt = dev_alloc_skb(Length); + + if (pkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("can't allocate tx %ld size packet\n", Length)); + } + + if (pkt) { + MEM_DBG_PKT_ALLOC_INC(pkt); + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + *VirtualAddress = (PVOID) pkt->data; + } else { + *VirtualAddress = (PVOID) NULL; + } + + return (PNDIS_PACKET) pkt; +} + +BOOLEAN OS_Need_Clone_Packet( + void) +{ + return (FALSE); +} + +/* + ======================================================================== + + Routine Description: + clone an input NDIS PACKET to another one. The new internally + created NDIS PACKET must have only one NDIS BUFFER + return - byte copied. 0 means can't create NDIS PACKET + NOTE: internally created NDIS_PACKET should be destroyed + by RTMPFreeNdisPacket + + Arguments: + pAd Pointer to our adapter + pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if + TRUE, insert this 14-byte hdr in front of MSDU. + *pSrcTotalLen return total packet length. This lenght is + calculated with 802.3 format packet. + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPCloneNdisPacket( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN pInsAMSDUHdr, + IN PNDIS_PACKET pInPacket, + OUT PNDIS_PACKET *ppOutPacket) +{ + + struct sk_buff *pkt; + + ASSERT(pInPacket); + ASSERT(ppOutPacket); + + /* 1. Allocate a packet */ + pkt = dev_alloc_skb(2048); + + if (pkt == NULL) + return NDIS_STATUS_FAILURE; + + MEM_DBG_PKT_ALLOC_INC(pkt); + skb_put(pkt, GET_OS_PKT_LEN(pInPacket)); + NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), + GET_OS_PKT_LEN(pInPacket)); + *ppOutPacket = OSPKT_TO_RTPKT(pkt); + + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS); + + printk(KERN_ERR "###Clone###\n"); + + return NDIS_STATUS_SUCCESS; +} +#endif /* Unused */ + +/* + The allocated NDIS PACKET must be freed via RTMPFreeNdisPacket() +*/ +NDIS_STATUS RTMPAllocateNdisPacket( + IN VOID *pReserved, + OUT PNDIS_PACKET *ppPacket, + IN UCHAR *pHeader, + IN UINT HeaderLen, + IN UCHAR *pData, + IN UINT DataLen) +{ + struct sk_buff *pPacket; + + + ASSERT(pData); + ASSERT(DataLen); + + pPacket = dev_alloc_skb(HeaderLen + DataLen + RTMP_PKT_TAIL_PADDING); + if (pPacket == NULL) { + *ppPacket = NULL; +#ifdef DEBUG + printk(KERN_ERR "RTMPAllocateNdisPacket Fail\n\n"); +#endif + return NDIS_STATUS_FAILURE; + } + MEM_DBG_PKT_ALLOC_INC(pPacket); + + /* Clone the frame content and update the length of packet */ + if (HeaderLen > 0) + NdisMoveMemory(pPacket->data, pHeader, HeaderLen); + if (DataLen > 0) + NdisMoveMemory(pPacket->data + HeaderLen, pData, DataLen); + skb_put(pPacket, HeaderLen + DataLen); +/* printk(KERN_ERR "%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket));*/ + + RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS); + *ppPacket = (PNDIS_PACKET)pPacket; + + return NDIS_STATUS_SUCCESS; +} + + +/* + ======================================================================== + Description: + This routine frees a miniport internally allocated NDIS_PACKET and its + corresponding NDIS_BUFFER and allocated memory. + ======================================================================== +*/ +VOID RTMPFreeNdisPacket( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket) +{ + dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket)); + MEM_DBG_PKT_FREE_INC(pPacket); +} + + +/* IRQL = DISPATCH_LEVEL */ +/* NOTE: we do have an assumption here, that Byte0 and Byte1 + * always reasid at the same scatter gather buffer + */ +NDIS_STATUS Sniff2BytesFromNdisBuffer( + IN PNDIS_BUFFER pFirstBuffer, + IN UCHAR DesiredOffset, + OUT PUCHAR pByte0, + OUT PUCHAR pByte1) +{ + *pByte0 = *(PUCHAR) (pFirstBuffer + DesiredOffset); + *pByte1 = *(PUCHAR) (pFirstBuffer + DesiredOffset + 1); + + return NDIS_STATUS_SUCCESS; +} + + +void RTMP_QueryPacketInfo( + IN PNDIS_PACKET pPacket, + OUT PACKET_INFO *info, + OUT UCHAR **pSrcBufVA, + OUT UINT *pSrcBufLen) +{ + info->BufferCount = 1; + info->pFirstBuffer = (PNDIS_BUFFER) GET_OS_PKT_DATAPTR(pPacket); + info->PhysicalBufferCount = 1; + info->TotalPacketLength = GET_OS_PKT_LEN(pPacket); + + *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + *pSrcBufLen = GET_OS_PKT_LEN(pPacket); + +#ifdef TX_PKT_SG + if (RTMP_GET_PKT_SG(pPacket)) { + struct sk_buff *skb = (struct sk_buff *)pPacket; + int i, nr_frags = skb_shinfo(skb)->nr_frags; + + info->BufferCount = nr_frags + 1; + info->PhysicalBufferCount = info->BufferCount; + info->sg_list[0].data = (VOID *)GET_OS_PKT_DATAPTR(pPacket); + info->sg_list[0].len = skb_headlen(skb); + for (i = 0; i < nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + info->sg_list[i+1].data = ((void *) page_address(frag->page) + + frag->page_offset); + info->sg_list[i+1].len = frag->size; + } + } +#endif /* TX_PKT_SG */ +} + + +#if 0 +void RTMP_QueryNextPacketInfo( + IN PNDIS_PACKET *ppPacket, + OUT PACKET_INFO * pPacketInfo, + OUT PUCHAR * pSrcBufVA, + OUT UINT * pSrcBufLen) +{ + PNDIS_PACKET pPacket = NULL; + + if (*ppPacket) + pPacket = GET_OS_PKT_NEXT(*ppPacket); + + if (pPacket) { + pPacketInfo->BufferCount = 1; + pPacketInfo->pFirstBuffer = + (PNDIS_BUFFER) GET_OS_PKT_DATAPTR(pPacket); + pPacketInfo->PhysicalBufferCount = 1; + pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket); + + *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket); + *pSrcBufLen = GET_OS_PKT_LEN(pPacket); + *ppPacket = GET_OS_PKT_NEXT(pPacket); + } else { + pPacketInfo->BufferCount = 0; + pPacketInfo->pFirstBuffer = NULL; + pPacketInfo->PhysicalBufferCount = 0; + pPacketInfo->TotalPacketLength = 0; + + *pSrcBufVA = NULL; + *pSrcBufLen = 0; + *ppPacket = NULL; + } +} +#endif /* Unused */ + + +PNDIS_PACKET DuplicatePacket( + IN PNET_DEV pNetDev, + IN PNDIS_PACKET pPacket, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *skb; + PNDIS_PACKET pRetPacket = NULL; + USHORT DataSize; + UCHAR *pData; + + DataSize = (USHORT) GET_OS_PKT_LEN(pPacket); + pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket); + + skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG); + if (skb) { + MEM_DBG_PKT_ALLOC_INC(skb); + skb->dev = pNetDev; /*get_netdev_from_bssid(pAd, FromWhichBSSID); */ + pRetPacket = OSPKT_TO_RTPKT(skb); + } +#if 0 + if ((skb = __dev_alloc_skb(DataSize + 2 + 32, MEM_ALLOC_FLAG)) != NULL) { + skb_reserve(skb, 2 + 32); + NdisMoveMemory(skb->tail, pData, DataSize); + skb_put(skb, DataSize); + skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID); + pRetPacket = OSPKT_TO_RTPKT(skb); + } +#endif + + return pRetPacket; + +} + + +PNDIS_PACKET duplicate_pkt( + IN PNET_DEV pNetDev, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID) +{ + struct sk_buff *skb; + PNDIS_PACKET pPacket = NULL; + + if ((skb = + __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) { + MEM_DBG_PKT_ALLOC_INC(skb); + + skb_reserve(skb, 2); + NdisMoveMemory(skb->tail, pHeader802_3, HdrLen); + skb_put(skb, HdrLen); + NdisMoveMemory(skb->tail, pData, DataSize); + skb_put(skb, DataSize); + skb->dev = pNetDev; /*get_netdev_from_bssid(pAd, FromWhichBSSID); */ + pPacket = OSPKT_TO_RTPKT(skb); + } + + return pPacket; +} + + +#define TKIP_TX_MIC_SIZE 8 +PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket) +{ + struct sk_buff *skb, *newskb; + + skb = RTPKT_TO_OSPKT(pPacket); + if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE) { + /* alloc a new skb and copy the packet */ + newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC); + + dev_kfree_skb_any(skb); + MEM_DBG_PKT_FREE_INC(skb); + + if (newskb == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n")); + return NULL; + } + skb = newskb; + MEM_DBG_PKT_ALLOC_INC(skb); + } + + return OSPKT_TO_RTPKT(skb); + +#if 0 + if ((data = skb_put(skb, TKIP_TX_MIC_SIZE)) != NULL) { /* If we can extend it, well, copy it first. */ + NdisMoveMemory(data, pAd->PrivateInfo.Tx.MIC, TKIP_TX_MIC_SIZE); + } else { + /* Otherwise, copy the packet. */ + newskb = + skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, + GFP_ATOMIC); + dev_kfree_skb_any(skb); + MEM_DBG_PKT_FREE_INC(skb); + + if (newskb == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("Extend Tx.MIC to packet failed!, dropping packet\n")); + return NULL; + } + skb = newskb; + MEM_DBG_PKT_ALLOC_INC(skb); + + NdisMoveMemory(skb->tail, pAd->PrivateInfo.Tx.MIC, + TKIP_TX_MIC_SIZE); + skb_put(skb, TKIP_TX_MIC_SIZE); + } + + return OSPKT_TO_RTPKT(skb); +#endif + +} + +#ifdef CONFIG_AP_SUPPORT +PNDIS_PACKET duplicate_pkt_with_VLAN( + IN PNET_DEV pNetDev, + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR FromWhichBSSID, + IN UCHAR *TPID) +{ + struct sk_buff *skb; + PNDIS_PACKET pPacket = NULL; + UINT16 VLAN_Size; + + if ((skb = __dev_alloc_skb(HdrLen + DataSize + LENGTH_802_1Q + 2, + MEM_ALLOC_FLAG)) != NULL) { + MEM_DBG_PKT_ALLOC_INC(skb); + + skb_reserve(skb, 2); + + /* copy header (maybe +VLAN tag) */ + VLAN_Size = VLAN_8023_Header_Copy(VLAN_VID, VLAN_Priority, + pHeader802_3, HdrLen, + skb->tail, FromWhichBSSID, + TPID); + skb_put(skb, HdrLen + VLAN_Size); + + /* copy data body */ + NdisMoveMemory(skb->tail, pData, DataSize); + skb_put(skb, DataSize); + skb->dev = pNetDev; /*get_netdev_from_bssid(pAd, FromWhichBSSID); */ + pPacket = OSPKT_TO_RTPKT(skb); + } + + return pPacket; +} +#endif /* CONFIG_AP_SUPPORT */ + +/* + ======================================================================== + + Routine Description: + Send a L2 frame to upper daemon to trigger state machine + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPL2FrameTxAction( + IN VOID * pCtrlBkPtr, + IN PNET_DEV pNetDev, + IN RTMP_CB_8023_PACKET_ANNOUNCE _announce_802_3_packet, + IN UCHAR apidx, + IN PUCHAR pData, + IN UINT32 data_len, + IN UCHAR OpMode) +{ + struct sk_buff *skb = dev_alloc_skb(data_len + 2); + + if (!skb) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Error! Can't allocate a skb.\n", __FUNCTION__)); + return FALSE; + } + + MEM_DBG_PKT_ALLOC_INC(skb); + /*get_netdev_from_bssid(pAd, apidx)); */ + SET_OS_PKT_NETDEV(skb, pNetDev); + + /* 16 byte align the IP header */ + skb_reserve(skb, 2); + + /* Insert the frame content */ + NdisMoveMemory(GET_OS_PKT_DATAPTR(skb), pData, data_len); + + /* End this frame */ + skb_put(GET_OS_PKT_TYPE(skb), data_len); + + DBGPRINT(RT_DEBUG_TRACE, ("%s doen\n", __FUNCTION__)); + + _announce_802_3_packet(pCtrlBkPtr, skb, OpMode); + + return TRUE; + +} + + +PNDIS_PACKET ExpandPacket( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket, + IN UINT32 ext_head_len, + IN UINT32 ext_tail_len) +{ + struct sk_buff *skb, *newskb; + + skb = RTPKT_TO_OSPKT(pPacket); + if (skb_cloned(skb) || (skb_headroom(skb) < ext_head_len) + || (skb_tailroom(skb) < ext_tail_len)) { + UINT32 head_len = + (skb_headroom(skb) < + ext_head_len) ? ext_head_len : skb_headroom(skb); + UINT32 tail_len = + (skb_tailroom(skb) < + ext_tail_len) ? ext_tail_len : skb_tailroom(skb); + + /* alloc a new skb and copy the packet */ + newskb = skb_copy_expand(skb, head_len, tail_len, GFP_ATOMIC); + + dev_kfree_skb_any(skb); + MEM_DBG_PKT_FREE_INC(skb); + + if (newskb == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("Extend Tx buffer for WPI failed!, dropping packet!\n")); + return NULL; + } + skb = newskb; + MEM_DBG_PKT_ALLOC_INC(skb); + } + + return OSPKT_TO_RTPKT(skb); + +} + +PNDIS_PACKET ClonePacket( + IN VOID *pReserved, + IN PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize) +{ + struct sk_buff *pRxPkt; + struct sk_buff *pClonedPkt; + + ASSERT(pPacket); + pRxPkt = RTPKT_TO_OSPKT(pPacket); + + /* clone the packet */ + pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG); + + if (pClonedPkt) { + /* set the correct dataptr and data len */ + MEM_DBG_PKT_ALLOC_INC(pClonedPkt); + pClonedPkt->dev = pRxPkt->dev; + pClonedPkt->data = pData; + pClonedPkt->len = DataSize; + pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len; + ASSERT(DataSize < 1530); + } + return pClonedPkt; +} + +VOID RtmpOsPktInit( + IN PNDIS_PACKET pNetPkt, + IN PNET_DEV pNetDev, + IN UCHAR *pData, + IN USHORT DataSize) +{ + PNDIS_PACKET pRxPkt; + + pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + + SET_OS_PKT_NETDEV(pRxPkt, pNetDev); + SET_OS_PKT_DATAPTR(pRxPkt, pData); + SET_OS_PKT_LEN(pRxPkt, DataSize); + SET_OS_PKT_DATATAIL(pRxPkt, pData, DataSize); +} + + +void wlan_802_11_to_802_3_packet( + IN PNET_DEV pNetDev, + IN UCHAR OpMode, + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PNDIS_PACKET pRxPacket, + IN UCHAR *pData, + IN ULONG DataSize, + IN PUCHAR pHeader802_3, + IN UCHAR FromWhichBSSID, + IN UCHAR *TPID) +{ + struct sk_buff *pOSPkt; + + ASSERT(pHeader802_3); + + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); + + /*get_netdev_from_bssid(pAd, FromWhichBSSID); */ + pOSPkt->dev = pNetDev; + pOSPkt->data = pData; + pOSPkt->len = DataSize; + pOSPkt->tail = pOSPkt->data + pOSPkt->len; + + /* copy 802.3 header */ +#ifdef CONFIG_AP_SUPPORT + RT_CONFIG_IF_OPMODE_ON_AP(OpMode) + { + /* maybe insert VLAN tag to the received packet */ + UCHAR VLAN_Size = 0; + UCHAR *data_p; + + if (VLAN_VID != 0) + VLAN_Size = LENGTH_802_1Q; + + data_p = skb_push(pOSPkt, LENGTH_802_3 + VLAN_Size); + + VLAN_8023_Header_Copy(VLAN_VID, VLAN_Priority, + pHeader802_3, LENGTH_802_3, + data_p, FromWhichBSSID, TPID); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + RT_CONFIG_IF_OPMODE_ON_STA(OpMode) + { + NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3); + } +#endif /* CONFIG_STA_SUPPORT */ + +} + + +#ifdef HDR_TRANS_SUPPORT +VOID RtmpOsSetPacket( + IN PNET_DEV pNetDev, + IN PNDIS_PACKET pRxPacket, + IN UCHAR *pData, + IN ULONG DataSize) +{ + + struct sk_buff *pOSPkt; + + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); + + pOSPkt->dev = pNetDev; + pOSPkt->data = pData; + pOSPkt->len = DataSize; + pOSPkt->tail = pOSPkt->data + pOSPkt->len; +} + +#endif /* HDR_TRANS_SUPPORT */ + + +void hex_dump(char *str, UCHAR *pSrcBufVA, UINT SrcBufLen) +{ +#ifdef DBG + unsigned char *pt; + int x; + + if (RTDebugLevel < RT_DEBUG_TRACE) + return; + + pt = pSrcBufVA; + printk("%s: %p, len = %d\n", str, pSrcBufVA, SrcBufLen); + for (x = 0; x < SrcBufLen; x++) { + if (x % 16 == 0) + printk("0x%04x : ", x); + printk("%02x ", ((unsigned char)pt[x])); + if (x % 16 == 15) + printk("\n"); + } + printk("\n"); +#endif /* DBG */ +} + +#ifdef SYSTEM_LOG_SUPPORT +/* + ======================================================================== + + Routine Description: + Send log message through wireless event + + Support standard iw_event with IWEVCUSTOM. It is used below. + + iwreq_data.data.flags is used to store event_flag that is + defined by user. iwreq_data.data.length is the length of the + event log. + + The format of the event log is composed of the entry's MAC + address and the desired log message (refer to + pWirelessEventText). + + ex: 11:22:33:44:55:66 has associated successfully + + p.s. The requirement of Wireless Extension is v15 or newer. + + ======================================================================== +*/ +VOID RtmpOsSendWirelessEvent( + IN VOID *pAd, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR BssIdx, + IN CHAR Rssi, + IN RTMP_OS_SEND_WLAN_EVENT pFunc) +{ +#if WIRELESS_EXT >= 15 + pFunc(pAd, Event_flag, pAddr, BssIdx, Rssi); +#else + DBGPRINT(RT_DEBUG_ERROR, + ("%s : The Wireless Extension MUST be v15 or newer.\n", + __FUNCTION__)); +#endif /* WIRELESS_EXT >= 15 */ +} +#endif /* SYSTEM_LOG_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +VOID SendSignalToDaemon( + IN INT sig, + RTMP_OS_PID pid, + unsigned long pid_no) +{ +#if 0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + if (pid == NULL) { + DBGPRINT(RT_DEBUG_TRACE, ("SignalError:Pid is NULL!\n")); + return; + } + + if (pid_no != GET_PID_NUMBER(pid)) { + DBGPRINT(RT_DEBUG_TRACE, + ("SignalError:pid_no(%ld) != pid_nr(%d)\n", pid_no, + GET_PID_NUMBER(pid))); + return; + } +#endif + CHECK_PID_LEGALITY(pid) { + DBGPRINT(RT_DEBUG_TRACE, + ("SendSignalToDaemon : Pid=%d\n", + GET_PID_NUMBER(pid))); + KILL_THREAD_PID(pid, sig, 0); + } +#if 0 + if (pid != 0) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#define GET_PID(_pid) find_get_pid(_pid) +#else +#define GET_PID(_pid) (_pid) +#endif + + KILL_THREAD_PID(pid), sig, 0); + } +#endif +#endif +} +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT +INT32 ralinkrate[] = { +2, 4, 11, 22, /* CCK */ +12, 18, 24, 36, 48, 72, 96, 108, /* OFDM */ +/* 20MHz, 800ns GI, MCS: 0 ~ 15 */ +13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, +39, 78, 117, 156, 234, 312, 351, 390, /* 20MHz, 800ns GI, MCS: 16 ~ 23 */ +/* 40MHz, 800ns GI, MCS: 0 ~ 15 */ +27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, +81, 162, 243, 324, 486, 648, 729, 810, /* 40MHz, 800ns GI, MCS: 16 ~ 23 */ +/* 20MHz, 400ns GI, MCS: 0 ~ 15 */ +14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, +43, 87, 130, 173, 260, 317, 390, 433, /* 20MHz, 400ns GI, MCS: 16 ~ 23 */ +/* 40MHz, 400ns GI, MCS: 0 ~ 15 */ +30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, +90, 180, 270, 360, 540, 720, 810, 900}; /* 40MHz, 400ns GI, MCS: 16 ~ 23 */ + +UINT32 RT_RateSize = sizeof (ralinkrate); + +void send_monitor_packets(IN PNET_DEV pNetDev, + IN PNDIS_PACKET pRxPacket, + IN PHEADER_802_11 pHeader, + IN UCHAR * pData, + IN USHORT DataSize, + IN UCHAR L2PAD, + IN UCHAR PHYMODE, + IN UCHAR BW, + IN UCHAR ShortGI, + IN UCHAR MCS, + IN UCHAR AMPDU, + IN UCHAR STBC, + IN UCHAR RSSI1, + IN UCHAR BssMonitorFlag11n, + IN UCHAR * pDevName, + IN UCHAR Channel, + IN UCHAR CentralChannel, + IN UINT32 MaxRssi) { + struct sk_buff *pOSPkt; + wlan_ng_prism2_header *ph; +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + ETHEREAL_RADIO h, + *ph_11n33; /* for new 11n sniffer format */ +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + int rate_index = 0; + USHORT header_len = 0; + UCHAR temp_header[40] = { + 0}; + + MEM_DBG_PKT_FREE_INC(pRxPacket); + +#if 0 /* os abl move */ + ASSERT(pRxBlk->pRxPacket); + if (pRxBlk->DataSize < 10) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Size is too small! (%d)\n", __FUNCTION__, + pRxBlk->DataSize)); + goto err_free_sk_buff; + } + + if (pRxBlk->DataSize + sizeof (wlan_ng_prism2_header) > + RX_BUFFER_AGGRESIZE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Size is too large! (%d)\n", __FUNCTION__, + pRxBlk->DataSize + sizeof (wlan_ng_prism2_header))); + goto err_free_sk_buff; + } +#endif + + pOSPkt = RTPKT_TO_OSPKT(pRxPacket); /*pRxBlk->pRxPacket); */ + pOSPkt->dev = pNetDev; /*get_netdev_from_bssid(pAd, BSS0); */ + if (pHeader->FC.Type == BTYPE_DATA) { + DataSize -= LENGTH_802_11; + if ((pHeader->FC.ToDs == 1) && (pHeader->FC.FrDs == 1)) + header_len = LENGTH_802_11_WITH_ADDR4; + else + header_len = LENGTH_802_11; + + /* QOS */ + if (pHeader->FC.SubType & 0x08) { + header_len += 2; + /* Data skip QOS contorl field */ + DataSize -= 2; + } + + /* Order bit: A-Ralink or HTC+ */ + if (pHeader->FC.Order) { + header_len += 4; + /* Data skip HTC contorl field */ + DataSize -= 4; + } + + /* Copy Header */ + if (header_len <= 40) + NdisMoveMemory(temp_header, pData, header_len); + + /* skip HW padding */ + if (L2PAD) + pData += (header_len + 2); + else + pData += header_len; + } + + if (DataSize < pOSPkt->len) { + skb_trim(pOSPkt, DataSize); + } else { + skb_put(pOSPkt, (DataSize - pOSPkt->len)); + } + + if ((pData - pOSPkt->data) > 0) { + skb_put(pOSPkt, (pData - pOSPkt->data)); + skb_pull(pOSPkt, (pData - pOSPkt->data)); + } + + if (skb_headroom(pOSPkt) < (sizeof (wlan_ng_prism2_header) + header_len)) { + if (pskb_expand_head(pOSPkt, (sizeof (wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s : Reallocate header size of sk_buff fail!\n", + __FUNCTION__)); + goto err_free_sk_buff; + } + } + + if (header_len > 0) + NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, + header_len); + +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + if (BssMonitorFlag11n == 0) +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + { + ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, + sizeof(wlan_ng_prism2_header)); + NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header)); + + ph->msgcode = DIDmsg_lnxind_wlansniffrm; + ph->msglen = sizeof (wlan_ng_prism2_header); + strcpy((PSTRING) ph->devname, (PSTRING) pDevName); + + ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; + ph->hosttime.status = 0; + ph->hosttime.len = 4; + ph->hosttime.data = jiffies; + + ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; + ph->mactime.status = 0; + ph->mactime.len = 0; + ph->mactime.data = 0; + + ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; + ph->istx.status = 0; + ph->istx.len = 0; + ph->istx.data = 0; + + ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; + ph->channel.status = 0; + ph->channel.len = 4; + + ph->channel.data = (u_int32_t) Channel; + + ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; + ph->rssi.status = 0; + ph->rssi.len = 4; + ph->rssi.data = MaxRssi; +#if 0 + (u_int32_t) RTMPMaxRssiOrg(pAd + , ConvertToRssiOrg(pAd, pRxBlk->pRxWI->RxWIRSSI0, RSSI_0) + , ConvertToRssiOrg(pAd, pRxBlk->pRxWI->RxWIRSSI1, RSSI_1) + , ConvertToRssiOrg(pAd, pRxBlk->pRxWI->RxWIRSSI2, RSSI_2)); +#endif + ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; + ph->signal.status = 0; + ph->signal.len = 4; + ph->signal.data = 0; /*rssi + noise; */ + + ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; + ph->noise.status = 0; + ph->noise.len = 4; + ph->noise.data = 0; + +#ifdef DOT11_N_SUPPORT + if (PHYMODE >= MODE_HTMIX) { + rate_index = 12 + ((UCHAR) BW * 24) + ((UCHAR) ShortGI * 48) + ((UCHAR) MCS); + } else +#endif /* DOT11_N_SUPPORT */ + if (PHYMODE == MODE_OFDM) + rate_index = (UCHAR) (MCS) + 4; + else + rate_index = (UCHAR) (MCS); + + if (rate_index < 0) + rate_index = 0; + if (rate_index >= (sizeof (ralinkrate) / sizeof (ralinkrate[0]))) + rate_index = (sizeof (ralinkrate) / sizeof (ralinkrate[0])) - 1; + + ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; + ph->rate.status = 0; + ph->rate.len = 4; + /* real rate = ralinkrate[rate_index] / 2 */ + ph->rate.data = ralinkrate[rate_index]; + + ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; + ph->frmlen.status = 0; + ph->frmlen.len = 4; + ph->frmlen.data = (u_int32_t) DataSize; + } +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT + else { + ph_11n33 = &h; + NdisZeroMemory((unsigned char *)ph_11n33, + sizeof (ETHEREAL_RADIO)); + + /*802.11n fields */ + if (MCS > 15) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_3x3; + + if (PHYMODE == MODE_HTGREENFIELD) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_GF; + + if (BW == 1) { + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_BW40; + } else if (Channel < CentralChannel) { + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_BW20U; + } else if (Channel > CentralChannel) { + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_BW20D; + } else { + ph_11n33->Flag_80211n |= + (WIRESHARK_11N_FLAG_BW20U | + WIRESHARK_11N_FLAG_BW20D); + } + + if (ShortGI == 1) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_SGI; + + if (AMPDU) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_AMPDU; + + if (STBC) + ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_STBC; + + ph_11n33->signal_level = (UCHAR) RSSI1; + + /* data_rate is the rate index in the wireshark rate table */ + if (PHYMODE >= MODE_HTMIX) { + if (MCS == 32) { + if (ShortGI) + ph_11n33->data_rate = 16; + else + ph_11n33->data_rate = 4; + } else if (MCS > 15) + ph_11n33->data_rate = + (16 * 4 + ((UCHAR) BW * 16) + + ((UCHAR) ShortGI * 32) + ((UCHAR) MCS)); + else + ph_11n33->data_rate = + 16 + ((UCHAR) BW * 16) + + ((UCHAR) ShortGI * 32) + ((UCHAR) MCS); + } else if (PHYMODE == MODE_OFDM) + ph_11n33->data_rate = (UCHAR) (MCS) + 4; + else + ph_11n33->data_rate = (UCHAR) (MCS); + + /*channel field */ + ph_11n33->channel = (UCHAR) Channel; + + NdisMoveMemory(skb_put(pOSPkt, sizeof (ETHEREAL_RADIO)), + (UCHAR *) ph_11n33, sizeof (ETHEREAL_RADIO)); + } +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + + pOSPkt->pkt_type = PACKET_OTHERHOST; + pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev); + pOSPkt->ip_summed = CHECKSUM_NONE; + netif_rx(pOSPkt); + + return; + + err_free_sk_buff: + RELEASE_NDIS_PACKET(NULL, pRxPacket, NDIS_STATUS_FAILURE); + return; + +} +#endif /* CONFIG_STA_SUPPORT */ + + +/******************************************************************************* + + File open/close related functions. + + *******************************************************************************/ +RTMP_OS_FD RtmpOSFileOpen(char *pPath, int flag, int mode) +{ + struct file *filePtr; + + if (flag == RTMP_FILE_RDONLY) + flag = O_RDONLY; + else if (flag == RTMP_FILE_WRONLY) + flag = O_WRONLY; + else if (flag == RTMP_FILE_CREAT) + flag = O_CREAT; + else if (flag == RTMP_FILE_TRUNC) + flag = O_TRUNC; + + filePtr = filp_open(pPath, flag, 0); + if (IS_ERR(filePtr)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Error %ld opening %s\n", __FUNCTION__, + -PTR_ERR(filePtr), pPath)); + } + + return (RTMP_OS_FD) filePtr; +} + +int RtmpOSFileClose(RTMP_OS_FD osfd) +{ + filp_close(osfd, NULL); + return 0; +} + +void RtmpOSFileSeek(RTMP_OS_FD osfd, int offset) +{ + osfd->f_pos = offset; +} + + +int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen) +{ + /* The object must have a read method */ + if (osfd->f_op && osfd->f_op->read) { + return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n")); + return -1; + } +} + +int RtmpOSFileWrite(RTMP_OS_FD osfd, char *pDataPtr, int writeLen) +{ + return osfd->f_op->write(osfd, pDataPtr, (size_t) writeLen, &osfd->f_pos); +} + +static inline void __RtmpOSFSInfoChange(OS_FS_INFO * pOSFSInfo, BOOLEAN bSet) +{ + if (bSet) { + /* Save uid and gid used for filesystem access. */ + /* Set user and group to 0 (root) */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + pOSFSInfo->fsuid = current->fsuid; + pOSFSInfo->fsgid = current->fsgid; + current->fsuid = current->fsgid = 0; +#else + pOSFSInfo->fsuid = current_fsuid(); + pOSFSInfo->fsgid = current_fsgid(); +#endif + pOSFSInfo->fs = get_fs(); + set_fs(KERNEL_DS); + } else { + set_fs(pOSFSInfo->fs); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) + current->fsuid = pOSFSInfo->fsuid; + current->fsgid = pOSFSInfo->fsgid; +#endif + } +} + + +/******************************************************************************* + + Task create/management/kill related functions. + + *******************************************************************************/ +static inline NDIS_STATUS __RtmpOSTaskKill(OS_TASK *pTask) +{ + int ret = NDIS_STATUS_FAILURE; + +#ifdef KTHREAD_SUPPORT + if (pTask->kthread_task) { + kthread_stop(pTask->kthread_task); + ret = NDIS_STATUS_SUCCESS; + } +#else + CHECK_PID_LEGALITY(pTask->taskPID) { + DBGPRINT(RT_DEBUG_TRACE, + ("Terminate the task(%s) with pid(%d)!\n", + pTask->taskName, GET_PID_NUMBER(pTask->taskPID))); + mb(); + pTask->task_killed = 1; + mb(); + ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1); + if (ret) { + printk(KERN_WARNING + "kill task(%s) with pid(%d) failed(retVal=%d)!\n", + pTask->taskName, GET_PID_NUMBER(pTask->taskPID), + ret); + } else { + wait_for_completion(&pTask->taskComplete); + pTask->taskPID = THREAD_PID_INIT_VALUE; + pTask->task_killed = 0; + RTMP_SEM_EVENT_DESTORY(&pTask->taskSema); + ret = NDIS_STATUS_SUCCESS; + } + } +#endif + + return ret; + +} + +static inline INT __RtmpOSTaskNotifyToExit(OS_TASK *pTask) +{ +#ifndef KTHREAD_SUPPORT + pTask->taskPID = THREAD_PID_INIT_VALUE; + complete_and_exit(&pTask->taskComplete, 0); +#endif + + return 0; +} + +static inline void __RtmpOSTaskCustomize(OS_TASK *pTask) +{ +#ifndef KTHREAD_SUPPORT + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + daemonize((PSTRING) & pTask->taskName[0] /*"%s",pAd->net_dev->name */ ); + + allow_signal(SIGTERM); + allow_signal(SIGKILL); + current->flags |= PF_NOFREEZE; +#else + unsigned long flags; + + daemonize(); + reparent_to_init(); + strcpy(current->comm, &pTask->taskName[0]); + + siginitsetinv(¤t->blocked, sigmask(SIGTERM) | sigmask(SIGKILL)); + + /* Allow interception of SIGKILL only + * Don't allow other signals to interrupt the transmission */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) + spin_lock_irqsave(¤t->sigmask_lock, flags); + flush_signals(current); + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); +#endif +#endif + + RTMP_GET_OS_PID(pTask->taskPID, current->pid); + + /* signal that we've started the thread */ + complete(&pTask->taskComplete); + +#endif +} + +static inline NDIS_STATUS __RtmpOSTaskAttach( + IN OS_TASK *pTask, + IN RTMP_OS_TASK_CALLBACK fn, + IN ULONG arg) +{ + NDIS_STATUS status = NDIS_STATUS_SUCCESS; +#ifndef KTHREAD_SUPPORT + pid_t pid_number = -1; +#endif /* KTHREAD_SUPPORT */ + +#ifdef KTHREAD_SUPPORT + pTask->task_killed = 0; + pTask->kthread_task = NULL; + pTask->kthread_task = + kthread_run((cast_fn) fn, (void *)arg, pTask->taskName); + if (IS_ERR(pTask->kthread_task)) + status = NDIS_STATUS_FAILURE; +#else + pid_number = + kernel_thread((cast_fn) fn, (void *)arg, RTMP_OS_MGMT_TASK_FLAGS); + if (pid_number < 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("Attach task(%s) failed!\n", pTask->taskName)); + status = NDIS_STATUS_FAILURE; + } else { + /* Wait for the thread to start */ + wait_for_completion(&pTask->taskComplete); + status = NDIS_STATUS_SUCCESS; + } +#endif + return status; +} + +static inline NDIS_STATUS __RtmpOSTaskInit( + IN OS_TASK *pTask, + IN PSTRING pTaskName, + IN VOID *pPriv, + IN LIST_HEADER *pSemList) +{ + int len; + + ASSERT(pTask); + +#ifndef KTHREAD_SUPPORT + NdisZeroMemory((PUCHAR) (pTask), sizeof (OS_TASK)); +#endif + + len = strlen(pTaskName); + len = len > (RTMP_OS_TASK_NAME_LEN - 1) ? (RTMP_OS_TASK_NAME_LEN - 1) : len; + NdisMoveMemory(&pTask->taskName[0], pTaskName, len); + pTask->priv = pPriv; + +#ifndef KTHREAD_SUPPORT + RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema), pSemList); + pTask->taskPID = THREAD_PID_INIT_VALUE; + init_completion(&pTask->taskComplete); +#endif + +#ifdef KTHREAD_SUPPORT + init_waitqueue_head(&(pTask->kthread_q)); +#endif /* KTHREAD_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + +BOOLEAN __RtmpOSTaskWait( + IN VOID *pReserved, + IN OS_TASK *pTask, + IN INT32 *pStatus) +{ +#ifdef KTHREAD_SUPPORT + RTMP_WAIT_EVENT_INTERRUPTIBLE((*pStatus), pTask); + + if ((pTask->task_killed == 1) || ((*pStatus) != 0)) + return FALSE; +#else + + RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), (*pStatus)); + + /* unlock the device pointers */ + if ((*pStatus) != 0) { +/* RTMP_SET_FLAG_(*pFlags, fRTMP_ADAPTER_HALT_IN_PROGRESS); */ + return FALSE; + } +#endif /* KTHREAD_SUPPORT */ + + return TRUE; +} + +#if 0 /* os abl move to os/linux/rt_profile.c */ +void RTMP_IndicateMediaState(IN PRTMP_ADAPTER pAd, + IN NDIS_MEDIA_STATE media_state) { + pAd->IndicateMediaState = media_state; +#ifdef SYSTEM_LOG_SUPPORT + if (pAd->IndicateMediaState == NdisMediaStateConnected) { + RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID].Addr, + BSS0, 0); + } else { + RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, + pAd->MacTab.Content[BSSID_WCID].Addr, + BSS0, 0); + } +#endif /* SYSTEM_LOG_SUPPORT */ +} +#endif + +#if LINUX_VERSION_CODE <= 0x20402 /* Red Hat 7.1 */ +#if 0 +static struct net_device *alloc_netdev(int sizeof_priv, const char *mask + , void (*setup)(struct net_device *)) //sample +#endif +struct net_device *alloc_netdev( + int sizeof_priv, + const char *mask, + void (*setup) (struct net_device *)) +{ + struct net_device *dev; + INT alloc_size; + + /* ensure 32-byte alignment of the private area */ + alloc_size = sizeof (*dev) + sizeof_priv + 31; + + dev = (struct net_device *)kmalloc(alloc_size, GFP_KERNEL); + if (dev == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("alloc_netdev: Unable to allocate device memory.\n")); + return NULL; + } + + memset(dev, 0, alloc_size); + + if (sizeof_priv) + dev->priv = (void *)(((long)(dev + 1) + 31) & ~31); + + setup(dev); + strcpy(dev->name, mask); + + return dev; +} +#endif /* LINUX_VERSION_CODE */ + + +static UINT32 RtmpOSWirelessEventTranslate(IN UINT32 eventType) +{ + switch (eventType) { + case RT_WLAN_EVENT_CUSTOM: + eventType = IWEVCUSTOM; + break; + + case RT_WLAN_EVENT_CGIWAP: + eventType = SIOCGIWAP; + break; + +#if WIRELESS_EXT > 17 + case RT_WLAN_EVENT_ASSOC_REQ_IE: + eventType = IWEVASSOCREQIE; + break; +#endif /* WIRELESS_EXT */ + +#if WIRELESS_EXT >= 14 + case RT_WLAN_EVENT_SCAN: + eventType = SIOCGIWSCAN; + break; +#endif /* WIRELESS_EXT */ + + case RT_WLAN_EVENT_EXPIRED: + eventType = IWEVEXPIRED; + break; +#ifdef P2P_SUPPORT + case RT_WLAN_EVENT_SHOWPIN: + eventType = 0x8C05; /* IWEVP2PKEYSHOWPIN; */ + break; + case RT_WLAN_EVENT_PIN: + eventType = 0x8C06; /* IWEVP2PKEYPIN; */ + break; +#endif /* P2P_SUPPORT */ + + default: + printk("Unknown event: 0x%x\n", eventType); + break; + } + + return eventType; +} + +int RtmpOSWrielessEventSend( + IN PNET_DEV pNetDev, + IN UINT32 eventType, + IN INT flags, + IN PUCHAR pSrcMac, + IN PUCHAR pData, + IN UINT32 dataLen) +{ +#ifdef DPA_S + RtmpOSNotifyRawData(pNetDev, &flags, sizeof(flags), 0, ETH_P_DPA_S_NOTIF); +#else + union iwreq_data wrqu; + + /* translate event type */ + eventType = RtmpOSWirelessEventTranslate(eventType); + + memset(&wrqu, 0, sizeof (wrqu)); + + if (flags > -1) + wrqu.data.flags = flags; + + if (pSrcMac) + memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN); + + if ((pData != NULL) && (dataLen > 0)) + wrqu.data.length = dataLen; + else + wrqu.data.length = 0; + + wireless_send_event(pNetDev, eventType, &wrqu, (char *)pData); +#endif + return 0; +} + +int RtmpOSWrielessEventSendExt( + IN PNET_DEV pNetDev, + IN UINT32 eventType, + IN INT flags, + IN PUCHAR pSrcMac, + IN PUCHAR pData, + IN UINT32 dataLen, + IN UINT32 family) +{ + union iwreq_data wrqu; + + /* translate event type */ + eventType = RtmpOSWirelessEventTranslate(eventType); + + /* translate event type */ + memset(&wrqu, 0, sizeof (wrqu)); + + if (flags > -1) + wrqu.data.flags = flags; + + if (pSrcMac) + memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN); + + if ((pData != NULL) && (dataLen > 0)) + wrqu.data.length = dataLen; + + wrqu.addr.sa_family = family; + + wireless_send_event(pNetDev, eventType, &wrqu, (char *)pData); + return 0; +} + +int RtmpOSNetDevAddrSet( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN PUCHAR pMacAddr, + IN PUCHAR dev_name) +{ + struct net_device *net_dev; + + net_dev = pNetDev; +/* GET_PAD_FROM_NET_DEV(pAd, net_dev); */ + +#ifdef CONFIG_STA_SUPPORT + /* work-around for the SuSE due to it has it's own interface name management system. */ + RT_CONFIG_IF_OPMODE_ON_STA(OpMode) { +/* NdisZeroMemory(pAd->StaCfg.dev_name, 16); */ +/* NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name)); */ + if (dev_name != NULL) { + NdisZeroMemory(dev_name, 16); + NdisMoveMemory(dev_name, net_dev->name, strlen(net_dev->name)); + } + } +#endif /* CONFIG_STA_SUPPORT */ + + NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6); + + return 0; +} + +/* + * Assign the network dev name for created Ralink WiFi interface. + */ +static int RtmpOSNetDevRequestName( + IN INT32 MC_RowID, + IN UINT32 *pIoctlIF, + IN PNET_DEV dev, + IN PSTRING pPrefixStr, + IN INT devIdx) +{ + PNET_DEV existNetDev; + STRING suffixName[IFNAMSIZ]; + STRING desiredName[IFNAMSIZ]; + int ifNameIdx, + prefixLen, + slotNameLen; + int Status; + + prefixLen = strlen(pPrefixStr); + ASSERT((prefixLen < IFNAMSIZ)); + + for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++) { + memset(suffixName, 0, IFNAMSIZ); + memset(desiredName, 0, IFNAMSIZ); + strncpy(&desiredName[0], pPrefixStr, prefixLen); + +#ifdef MULTIPLE_CARD_SUPPORT + if (MC_RowID >= 0) + sprintf(suffixName, "%02d_%d", MC_RowID, ifNameIdx); + else +#endif /* MULTIPLE_CARD_SUPPORT */ + sprintf(suffixName, "%d", ifNameIdx); + + slotNameLen = strlen(suffixName); + ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ)); + strcat(desiredName, suffixName); + + existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]); + if (existNetDev == NULL) + break; + else + RtmpOSNetDeviceRefPut(existNetDev); + } + + if (ifNameIdx < 32) { +#ifdef HOSTAPD_SUPPORT + *pIoctlIF = ifNameIdx; +#endif /*HOSTAPD_SUPPORT */ + strcpy(&dev->name[0], &desiredName[0]); +#ifdef RELEASE_EXCLUDE + DBGPRINT(RT_DEBUG_INFO, + ("Assign the net device name as %s\n", &dev->name[0])); +#endif /* RELEASE_EXCLUDE */ + Status = NDIS_STATUS_SUCCESS; + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n", + pPrefixStr)); + Status = NDIS_STATUS_FAILURE; + } + + return Status; +} + +void RtmpOSNetDevClose(PNET_DEV pNetDev) +{ + dev_close(pNetDev); +} + +void RtmpOSNetDevFree(PNET_DEV pNetDev) +{ + DEV_PRIV_INFO *pDevInfo = NULL; + + + ASSERT(pNetDev); + + /* free assocaited private information */ + pDevInfo = _RTMP_OS_NETDEV_GET_PRIV(pNetDev); + if (pDevInfo != NULL) + os_free_mem(NULL, pDevInfo); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + free_netdev(pNetDev); +#else + kfree(pNetDev); +#endif + +#ifdef VENDOR_FEATURE4_SUPPORT + printk("OS_NumOfMemAlloc = %ld, OS_NumOfMemFree = %ld\n", + OS_NumOfMemAlloc, OS_NumOfMemFree); +#endif /* VENDOR_FEATURE4_SUPPORT */ +#ifdef VENDOR_FEATURE2_SUPPORT + printk("OS_NumOfPktAlloc = %ld, OS_NumOfPktFree = %ld\n", + OS_NumOfPktAlloc, OS_NumOfPktFree); +#endif /* VENDOR_FEATURE2_SUPPORT */ +} + +INT RtmpOSNetDevAlloc( + IN PNET_DEV *new_dev_p, + IN UINT32 privDataSize) +{ + *new_dev_p = NULL; + + DBGPRINT(RT_DEBUG_TRACE, + ("Allocate a net device with private data size=%d!\n", + privDataSize)); +#if LINUX_VERSION_CODE <= 0x20402 /* Red Hat 7.1 */ + *new_dev_p = alloc_netdev(privDataSize, "eth%d", ether_setup); +#else + *new_dev_p = alloc_etherdev(privDataSize); +#endif /* LINUX_VERSION_CODE */ + + if (*new_dev_p) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) +INT RtmpOSNetDevOpsAlloc(PVOID *pNetDevOps) +{ + *pNetDevOps = (PVOID) vmalloc(sizeof (struct net_device_ops)); + if (*pNetDevOps) { + NdisZeroMemory(*pNetDevOps, sizeof (struct net_device_ops)); + return NDIS_STATUS_SUCCESS; + } else { + return NDIS_STATUS_FAILURE; + } +} +#endif + + +PNET_DEV RtmpOSNetDevGetByName(PNET_DEV pNetDev, PSTRING pDevName) +{ + PNET_DEV pTargetNetDev = NULL; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName); +#else + ASSERT(pNetDev); + pTargetNetDev = dev_get_by_name(pNetDev->nd_net, pDevName); +#endif +#else + pTargetNetDev = dev_get_by_name(pDevName); +#endif /* KERNEL_VERSION(2,6,24) */ + +#else + int devNameLen; + + devNameLen = strlen(pDevName); + ASSERT((devNameLen <= IFNAMSIZ)); + + for (pTargetNetDev = dev_base; pTargetNetDev != NULL; + pTargetNetDev = pTargetNetDev->next) { + if (strncmp(pTargetNetDev->name, pDevName, devNameLen) == 0) + break; + } +#endif /* KERNEL_VERSION(2,5,0) */ + + return pTargetNetDev; +} + + +void RtmpOSNetDeviceRefPut(PNET_DEV pNetDev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + /* + every time dev_get_by_name is called, and it has returned a valid struct + net_device*, dev_put should be called afterwards, because otherwise the + machine hangs when the device is unregistered (since dev->refcnt > 1). + */ + if (pNetDev) + dev_put(pNetDev); +#endif /* LINUX_VERSION_CODE */ +} + + +INT RtmpOSNetDevDestory(VOID *pReserved, PNET_DEV pNetDev) +{ + + /* TODO: Need to fix this */ + printk("WARNING: This function(%s) not implement yet!!!\n", + __FUNCTION__); + return 0; +} + + +void RtmpOSNetDevDetach(PNET_DEV pNetDev) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + struct net_device_ops *pNetDevOps = (struct net_device_ops *)pNetDev->netdev_ops; +#endif + int ret; + + ret = rtnl_trylock(); + + unregister_netdevice(pNetDev); + + if ( ret ) + rtnl_unlock(); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + vfree(pNetDevOps); +#endif +} + + +void RtmpOSNetDevProtect(BOOLEAN lock_it) +{ + +/* + if (lock_it) + rtnl_lock(); + else + rtnl_unlock(); +*/ +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) +static void RALINK_ET_DrvInfoGet( + struct net_device *pDev, + struct ethtool_drvinfo *pInfo) +{ + strcpy(pInfo->driver, "RALINK WLAN"); + +#if 0 /* os abl move */ +#ifdef CONFIG_AP_SUPPORT + strcpy(pInfo->version, AP_DRIVER_VERSION); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_STA_SUPPORT + strcpy(pInfo->version, STA_DRIVER_VERSION); +#endif /* CONFIG_STA_SUPPORT */ +#endif + + sprintf(pInfo->bus_info, "CSR 0x%lx", pDev->base_addr); +} + +static struct ethtool_ops RALINK_Ethtool_Ops = { + .get_drvinfo = RALINK_ET_DrvInfoGet, +}; +#endif + + +int RtmpOSNetDevAttach( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook) +{ + int ret, + rtnl_locked = FALSE; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + struct net_device_ops *pNetDevOps = (struct net_device_ops *)pNetDev->netdev_ops; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n")); + + /* If we need hook some callback function to the net device structrue, now do it. */ + if (pDevOpHook) { +/* PRTMP_ADAPTER pAd = NULL; */ + +/* GET_PAD_FROM_NET_DEV(pAd, pNetDev); */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + pNetDevOps->ndo_open = pDevOpHook->open; + pNetDevOps->ndo_stop = pDevOpHook->stop; + pNetDevOps->ndo_start_xmit = + (HARD_START_XMIT_FUNC) (pDevOpHook->xmit); + pNetDevOps->ndo_do_ioctl = pDevOpHook->ioctl; +#else + pNetDev->open = pDevOpHook->open; + pNetDev->stop = pDevOpHook->stop; + pNetDev->hard_start_xmit = + (HARD_START_XMIT_FUNC) (pDevOpHook->xmit); + pNetDev->do_ioctl = pDevOpHook->ioctl; +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) + pNetDev->ethtool_ops = &RALINK_Ethtool_Ops; +#endif + + /* if you don't implement get_stats, just leave the callback function as NULL, a dummy + function will make kernel panic. + */ + if (pDevOpHook->get_stats) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + pNetDevOps->ndo_get_stats = pDevOpHook->get_stats; +#else + pNetDev->get_stats = pDevOpHook->get_stats; +#endif + + /* OS specific flags, here we used to indicate if we are virtual interface */ +/* pNetDev->priv_flags = pDevOpHook->priv_flags; */ + RT_DEV_PRIV_FLAGS_SET(pNetDev, pDevOpHook->priv_flags); + +#if (WIRELESS_EXT < 21) && (WIRELESS_EXT >= 12) +/* pNetDev->get_wireless_stats = rt28xx_get_wireless_stats; */ + pNetDev->get_wireless_stats = pDevOpHook->get_wstats; +#endif + +#ifdef CONFIG_STA_SUPPORT +#if WIRELESS_EXT >= 12 + if (OpMode == OPMODE_STA) { +/* pNetDev->wireless_handlers = &rt28xx_iw_handler_def; */ + pNetDev->wireless_handlers = pDevOpHook->iw_handler; + } +#endif /*WIRELESS_EXT >= 12 */ +#endif /* CONFIG_STA_SUPPORT */ + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +#if WIRELESS_EXT >= 12 + if (OpMode == OPMODE_AP) { +/* pNetDev->wireless_handlers = &rt28xx_ap_iw_handler_def; */ + pNetDev->wireless_handlers = pDevOpHook->iw_handler; + } +#endif /*WIRELESS_EXT >= 12 */ +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + + /* copy the net device mac address to the net_device structure. */ + NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], + MAC_ADDR_LEN); + + rtnl_locked = pDevOpHook->needProtcted; + +#if 0 /* os abl move */ +#ifdef RT_CFG80211_SUPPORT + /* + In 2.6.32, cfg80211 register must be before register_netdevice(); + We can not put the register in rt28xx_open(); + Or you will suffer NULL pointer in list_add of + cfg80211_netdev_notifier_call(). + */ + RT_CFG80211_REGISTER(pAd, pAd->pCfgDev, pNetDev); +#endif /* RT_CFG80211_SUPPORT */ +#endif + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + pNetDevOps->ndo_validate_addr = NULL; + /*pNetDev->netdev_ops = ops; */ +#else + pNetDev->validate_addr = NULL; +#endif +#endif + + if (rtnl_locked) + ret = register_netdevice(pNetDev); + else + ret = register_netdev(pNetDev); + + netif_stop_queue(pNetDev); + + DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret)); + if (ret == 0) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; +} + +PNET_DEV RtmpOSNetDevCreate( + IN INT32 MC_RowID, + IN UINT32 *pIoctlIF, + IN INT devType, + IN INT devNum, + IN INT privMemSize, + IN PSTRING pNamePrefix) +{ + struct net_device *pNetDev = NULL; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + struct net_device_ops *pNetDevOps = NULL; +#endif + int status; + + /* allocate a new network device */ + status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize */ ); + if (status != NDIS_STATUS_SUCCESS) { + /* allocation fail, exit */ + DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (%s)...\n", pNamePrefix)); + return NULL; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) + status = RtmpOSNetDevOpsAlloc((PVOID) & pNetDevOps); + if (status != NDIS_STATUS_SUCCESS) { + /* error! no any available ra name can be used! */ + DBGPRINT(RT_DEBUG_TRACE, ("Allocate net device ops fail!\n")); + RtmpOSNetDevFree(pNetDev); + + return NULL; + } else { + DBGPRINT(RT_DEBUG_TRACE, ("Allocate net device ops success!\n")); + pNetDev->netdev_ops = pNetDevOps; + } +#endif + /* find a available interface name, max 32 interfaces */ + status = RtmpOSNetDevRequestName(MC_RowID, pIoctlIF, pNetDev, pNamePrefix, devNum); + if (status != NDIS_STATUS_SUCCESS) { + /* error! no any available ra name can be used! */ + DBGPRINT(RT_DEBUG_ERROR, ("Assign interface name (%s with suffix 0~32) failed...\n", + pNamePrefix)); + RtmpOSNetDevFree(pNetDev); + + return NULL; + } else { + DBGPRINT(RT_DEBUG_TRACE, ("The name of the new %s interface is %s...\n", + pNamePrefix, pNetDev->name)); + } + + return pNetDev; +} + +#if 0 /* os abl move to common/rtmp_init.c */ +/* OS_ABL_SUPPORT */ +/* not yet support MBSS */ +PNET_DEV get_netdev_from_bssid(IN PRTMP_ADAPTER pAd, + IN UCHAR FromWhichBSSID) { + PNET_DEV dev_p = NULL; + +#ifdef MESH_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) { + dev_p = pAd->MeshTab.dev; + } else +#endif /* MESH_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + UCHAR infRealIdx; + + infRealIdx = FromWhichBSSID & (NET_DEVICE_REAL_IDX_MASK); +#ifdef APCLI_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_APCLI) { + dev_p = + (infRealIdx >= + MAX_APCLI_NUM ? NULL : pAd->ApCfg. + ApCliTab[infRealIdx].dev); + } else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_WDS) { + dev_p = + ((infRealIdx >= + MAX_WDS_ENTRY) ? NULL : pAd->WdsTab. + WdsEntry[infRealIdx].dev); + } else +#endif /* WDS_SUPPORT */ + { + if (FromWhichBSSID >= pAd->ApCfg.BssidNum) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: fatal error ssid > ssid num!\n", + __FUNCTION__)); + dev_p = pAd->net_dev; + } + + if (FromWhichBSSID == BSS0) + dev_p = pAd->net_dev; + else { + dev_p = + pAd->ApCfg.MBSSID[FromWhichBSSID].MSSIDDev; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_STA_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) { + dev_p = pAd->net_dev; + } +#endif /* CONFIG_STA_SUPPORT */ + + ASSERT(dev_p); + return dev_p; /* return one of MBSS */ +} +#endif + + +#ifdef CONFIG_AP_SUPPORT +UCHAR VLAN_8023_Header_Copy( + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + OUT PUCHAR pData, + IN UCHAR FromWhichBSSID, + IN UCHAR *TPID) +{ + UINT16 TCI; + UCHAR VLAN_Size = 0; + + if (VLAN_VID != 0) { + /* need to insert VLAN tag */ + VLAN_Size = LENGTH_802_1Q; + + /* make up TCI field */ + TCI = (VLAN_VID & 0x0fff) | ((VLAN_Priority & 0x7) << 13); + +#ifndef RT_BIG_ENDIAN + TCI = SWAP16(TCI); +#endif /* RT_BIG_ENDIAN */ + + /* copy dst + src MAC (12B) */ + memcpy(pData, pHeader802_3, LENGTH_802_3_NO_TYPE); + + /* copy VLAN tag (4B) */ + /* do NOT use memcpy to speed up */ + *(UINT16 *) (pData + LENGTH_802_3_NO_TYPE) = *(UINT16 *) TPID; + *(UINT16 *) (pData + LENGTH_802_3_NO_TYPE + 2) = TCI; + + /* copy type/len (2B) */ + *(UINT16 *) (pData + LENGTH_802_3_NO_TYPE + LENGTH_802_1Q) = + *(UINT16 *) & pHeader802_3[LENGTH_802_3 - + LENGTH_802_3_TYPE]; + + /* copy tail if exist */ + if (HdrLen > LENGTH_802_3) + memcpy(pData + LENGTH_802_3 + LENGTH_802_1Q, pHeader802_3 + LENGTH_802_3, HdrLen - LENGTH_802_3); + } + else + { + /* no VLAN tag is needed to insert */ + memcpy(pData, pHeader802_3, HdrLen); + } + + return VLAN_Size; +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* +======================================================================== +Routine Description: + Allocate memory for adapter control block. + +Arguments: + pAd Pointer to our adapter + +Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + +Note: +======================================================================== +*/ +NDIS_STATUS AdapterBlockAllocateMemory(VOID *handle, VOID **ppAd, UINT32 SizeOfpAd) +{ +#ifdef OS_ABL_FUNC_SUPPORT + /* get offset for sk_buff */ + { + struct sk_buff *pPkt = NULL; + + pPkt = kmalloc(sizeof (struct sk_buff), GFP_ATOMIC); + if (pPkt == NULL) { + *ppAd = NULL; + return NDIS_STATUS_FAILURE; + } + + RTPktOffsetData = (ULONG) (&(pPkt->data)) - (ULONG) pPkt; + RTPktOffsetLen = (ULONG) (&(pPkt->len)) - (ULONG) pPkt; + RTPktOffsetCB = (ULONG) (pPkt->cb) - (ULONG) pPkt; + kfree(pPkt); + + DBGPRINT(RT_DEBUG_TRACE, ("packet> data offset = %lu\n", RTPktOffsetData)); + DBGPRINT(RT_DEBUG_TRACE, ("packet> len offset = %lu\n", RTPktOffsetLen)); + DBGPRINT(RT_DEBUG_TRACE, ("packet> cb offset = %lu\n", RTPktOffsetCB)); + } +#endif /* OS_ABL_FUNC_SUPPORT */ + +/* *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); */ + *ppAd = (PVOID) vmalloc(SizeOfpAd); /*pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); */ + if (*ppAd) { + NdisZeroMemory(*ppAd, SizeOfpAd); + return NDIS_STATUS_SUCCESS; + } else + return NDIS_STATUS_FAILURE; +} + + +/* ========================================================================== */ + +UINT RtmpOsWirelessExtVerGet(VOID) +{ + return WIRELESS_EXT; +} + + +VOID RtmpDrvAllMacPrint( + IN VOID *pReserved, + IN UINT32 *pBufMac, + IN UINT32 AddrStart, + IN UINT32 AddrEnd, + IN UINT32 AddrStep) +{ + struct file *file_w; + PSTRING fileName = "MacDump.txt"; + mm_segment_t orig_fs; + STRING *msg; + UINT32 macAddr = 0, macValue = 0; + + os_alloc_mem(NULL, (UCHAR **)&msg, 1024); + if (!msg) + return; + + orig_fs = get_fs(); + set_fs(KERNEL_DS); + + /* open file */ + file_w = filp_open(fileName, O_WRONLY | O_CREAT, 0); + if (IS_ERR(file_w)) { + DBGPRINT(RT_DEBUG_TRACE, + ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, + -PTR_ERR(file_w), fileName)); + } else { + if (file_w->f_op && file_w->f_op->write) { + file_w->f_pos = 0; + macAddr = AddrStart; + + while (macAddr <= AddrEnd) { +/* RTMP_IO_READ32(pAd, macAddr, &macValue); // sample */ + macValue = *pBufMac++; + sprintf(msg, "%04x = %08x\n", macAddr, macValue); + + /* write data to file */ + file_w->f_op->write(file_w, msg, strlen(msg), &file_w->f_pos); + + printk("%s", msg); + macAddr += AddrStep; + } + sprintf(msg, "\nDump all MAC values to %s\n", fileName); + } + filp_close(file_w, NULL); + } + set_fs(orig_fs); + os_free_mem(NULL, msg); +} + + +VOID RtmpDrvAllE2PPrint( + IN VOID *pReserved, + IN USHORT *pMacContent, + IN UINT32 AddrEnd, + IN UINT32 AddrStep) +{ + struct file *file_w; + PSTRING fileName = "EEPROMDump.txt"; + mm_segment_t orig_fs; + STRING *msg; + USHORT eepAddr = 0; + USHORT eepValue; + + os_alloc_mem(NULL, (UCHAR **)&msg, 1024); + if (!msg) + return; + + orig_fs = get_fs(); + set_fs(KERNEL_DS); + + /* open file */ + file_w = filp_open(fileName, O_WRONLY | O_CREAT, 0); + if (IS_ERR(file_w)) { + DBGPRINT(RT_DEBUG_TRACE, + ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, + -PTR_ERR(file_w), fileName)); + } else { + if (file_w->f_op && file_w->f_op->write) { + file_w->f_pos = 0; + eepAddr = 0x00; + + while (eepAddr <= AddrEnd) { + eepValue = *pMacContent; + sprintf(msg, "%08x = %04x\n", eepAddr, eepValue); + + /* write data to file */ + file_w->f_op->write(file_w, msg, strlen(msg), &file_w->f_pos); + + printk("%s", msg); + eepAddr += AddrStep; + pMacContent += (AddrStep >> 1); + } + sprintf(msg, "\nDump all EEPROM values to %s\n", + fileName); + } + filp_close(file_w, NULL); + } + set_fs(orig_fs); + os_free_mem(NULL, msg); +} + + +VOID RtmpDrvAllRFPrint( + IN VOID *pReserved, + IN UINT32 *pBuf, + IN UINT32 BufLen) +{ + struct file *file_w; + PSTRING fileName = "RFDump.txt"; + mm_segment_t orig_fs; + UINT32 macAddr = 0, macValue = 0; + + orig_fs = get_fs(); + set_fs(KERNEL_DS); + + /* open file */ + file_w = filp_open(fileName, O_WRONLY | O_CREAT, 0); + if (IS_ERR(file_w)) { + DBGPRINT(RT_DEBUG_TRACE, + ("-->2) %s: Error %ld opening %s\n", __FUNCTION__, + -PTR_ERR(file_w), fileName)); + } else { + if (file_w->f_op && file_w->f_op->write) { + file_w->f_pos = 0; + /* write data to file */ + file_w->f_op->write(file_w, pBuf, BufLen, &file_w->f_pos); + } + filp_close(file_w, NULL); + } + set_fs(orig_fs); +} + +/* +======================================================================== +Routine Description: + Check if the network interface is up. + +Arguments: + *pDev - Network Interface + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN RtmpOSNetDevIsUp(VOID *pDev) +{ + struct net_device *pNetDev = (struct net_device *)pDev; + + if ((pNetDev == NULL) || !(pNetDev->flags & IFF_UP)) + return FALSE; + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Wake up the command thread. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsCmdUp(RTMP_OS_TASK *pCmdQTask) +{ + OS_TASK *pTask = RTMP_OS_TASK_GET(pCmdQTask); +#ifdef KTHREAD_SUPPORT + pTask->kthread_running = TRUE; + wake_up(&pTask->kthread_q); +#else + CHECK_PID_LEGALITY(pTask->taskPID) { + RTMP_SEM_EVENT_UP(&(pTask->taskSema)); + } +#endif /* KTHREAD_SUPPORT */ +} + + +/* +======================================================================== +Routine Description: + Wake up USB Mlme thread. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsMlmeUp(IN RTMP_OS_TASK *pMlmeQTask) +{ +#ifdef RTMP_USB_SUPPORT + OS_TASK *pTask = RTMP_OS_TASK_GET(pMlmeQTask); + +#ifdef KTHREAD_SUPPORT + if ((pTask != NULL) && (pTask->kthread_task)) { + pTask->kthread_running = TRUE; + wake_up(&pTask->kthread_q); + } +#else + if (pTask != NULL) { + CHECK_PID_LEGALITY(pTask->taskPID) { + RTMP_SEM_EVENT_UP(&(pTask->taskSema)); + } + } +#endif /* KTHREAD_SUPPORT */ +#endif /* RTMP_USB_SUPPORT */ +} + + +/* +======================================================================== +Routine Description: + Check if the file is error. + +Arguments: + pFile - the file + +Return Value: + OK or any error + +Note: + rt_linux.h, not rt_drv.h +======================================================================== +*/ +INT32 RtmpOsFileIsErr(IN VOID *pFile) +{ + return IS_FILE_OPEN_ERR(pFile); +} + +int RtmpOSIRQRelease( + IN PNET_DEV pNetDev, + IN UINT32 infType, + IN PPCI_DEV pci_dev, + IN BOOLEAN *pHaveMsi) +{ + struct net_device *net_dev = (struct net_device *)pNetDev; + +#ifdef RTMP_PCI_SUPPORT + if (infType == RTMP_DEV_INF_PCI || infType == RTMP_DEV_INF_PCIE) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + synchronize_irq(pci_dev->irq); +#endif + free_irq(pci_dev->irq, (net_dev)); + RTMP_MSI_DISABLE(pci_dev, pHaveMsi); + } +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef RTMP_RBUS_SUPPORT + if (infType == RTMP_DEV_INF_RBUS) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + synchronize_irq(net_dev->irq); +#endif + free_irq(net_dev->irq, (net_dev)); + } +#endif /* RTMP_RBUS_SUPPORT */ + + return 0; +} + + +/* +======================================================================== +Routine Description: + Enable or disable wireless event sent. + +Arguments: + pReserved - Reserved + FlgIsWEntSup - TRUE or FALSE + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsWlanEventSet( + IN VOID *pReserved, + IN BOOLEAN *pCfgWEnt, + IN BOOLEAN FlgIsWEntSup) +{ +#if WIRELESS_EXT >= 15 +/* pAd->CommonCfg.bWirelessEvent = FlgIsWEntSup; */ + *pCfgWEnt = FlgIsWEntSup; +#else + *pCfgWEnt = 0; /* disable */ +#endif +} + +/* +======================================================================== +Routine Description: + vmalloc + +Arguments: + Size - memory size + +Return Value: + the memory + +Note: +======================================================================== +*/ +VOID *RtmpOsVmalloc(ULONG Size) +{ + return vmalloc(Size); +} + +/* +======================================================================== +Routine Description: + vfree + +Arguments: + pMem - the memory + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsVfree(VOID *pMem) +{ + if (pMem != NULL) + vfree(pMem); +} + +/* +======================================================================== +Routine Description: + Get network interface name. + +Arguments: + pDev - the device + +Return Value: + the name + +Note: +======================================================================== +*/ +char *RtmpOsGetNetDevName(VOID *pDev) +{ + return ((PNET_DEV) pDev)->name; +} + +/* +======================================================================== +Routine Description: + Assign protocol to the packet. + +Arguments: + pPkt - the packet + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktProtocolAssign(PNDIS_PACKET pNetPkt) +{ + struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); +} + + +BOOLEAN RtmpOsStatsAlloc( + IN VOID **ppStats, + IN VOID **ppIwStats) +{ + os_alloc_mem(NULL, (UCHAR **) ppStats, sizeof (struct net_device_stats)); + if ((*ppStats) == NULL) + return FALSE; + NdisZeroMemory((UCHAR *) *ppStats, sizeof (struct net_device_stats)); + +#if WIRELESS_EXT >= 12 + os_alloc_mem(NULL, (UCHAR **) ppIwStats, sizeof (struct iw_statistics)); + if ((*ppIwStats) == NULL) { + os_free_mem(NULL, *ppStats); + return FALSE; + } + NdisZeroMemory((UCHAR *)* ppIwStats, sizeof (struct iw_statistics)); +#endif + + return TRUE; +} + +/* +======================================================================== +Routine Description: + Pass the received packet to OS. + +Arguments: + pPkt - the packet + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktRcvHandle(PNDIS_PACKET pNetPkt) +{ + struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt); +#ifdef CONFIG_CSO_SUPPORT + struct net_device *pNetDev = GET_OS_PKT_NETDEV(pNetPkt); + + if (pNetDev->features & NETIF_F_HW_CSUM) + { + if (RTMP_GET_TCP_CHKSUM_FAIL(pNetPkt)) + pRxPkt->ip_summed = CHECKSUM_NONE; + else + pRxPkt->ip_summed = CHECKSUM_UNNECESSARY; + } +#endif /* CONFIG_CSO_SUPPORT */ + +#ifdef CONFIG_RX_CSO_SUPPORT + + if (RTMP_GET_TCP_CHKSUM_FAIL(pNetPkt)) + pRxPkt->ip_summed = CHECKSUM_NONE; + else + pRxPkt->ip_summed = CHECKSUM_UNNECESSARY; + +#endif + + netif_rx(pRxPkt); +} + + +VOID RtmpOsTaskPidInit(RTMP_OS_PID *pPid) +{ + *pPid = THREAD_PID_INIT_VALUE; +} + +/* +======================================================================== +Routine Description: + Get the network interface for the packet. + +Arguments: + pPkt - the packet + +Return Value: + None + +Note: +======================================================================== +*/ +PNET_DEV RtmpOsPktNetDevGet(VOID *pPkt) +{ + return GET_OS_PKT_NETDEV(pPkt); +} + + +#ifdef IAPP_SUPPORT +/* Layer 2 Update frame to switch/bridge */ +/* For any Layer2 devices, e.g., bridges, switches and other APs, the frame + can update their forwarding tables with the correct port to reach the new + location of the STA */ +typedef struct GNU_PACKED _RT_IAPP_L2_UPDATE_FRAME { + + UCHAR DA[ETH_ALEN]; /* broadcast MAC address */ + UCHAR SA[ETH_ALEN]; /* the MAC address of the STA that has just associated + or reassociated */ + USHORT Len; /* 8 octets */ + UCHAR DSAP; /* null */ + UCHAR SSAP; /* null */ + UCHAR Control; /* reference to IEEE Std 802.2 */ + UCHAR XIDInfo[3]; /* reference to IEEE Std 802.2 */ +} RT_IAPP_L2_UPDATE_FRAME, *PRT_IAPP_L2_UPDATE_FRAME; + + +PNDIS_PACKET RtmpOsPktIappMakeUp( + IN PNET_DEV pNetDev, + IN UINT8 *pMac) +{ + RT_IAPP_L2_UPDATE_FRAME frame_body; + INT size = sizeof (RT_IAPP_L2_UPDATE_FRAME); + PNDIS_PACKET pNetBuf; + + if (pNetDev == NULL) + return NULL; + + pNetBuf = RtmpOSNetPktAlloc(NULL, size); + if (!pNetBuf) { + DBGPRINT(RT_DEBUG_ERROR, ("Error! Can't allocate a skb.\n")); + return NULL; + } + + /* init the update frame body */ + NdisZeroMemory(&frame_body, size); + + memset(frame_body.DA, 0xFF, ETH_ALEN); + memcpy(frame_body.SA, pMac, ETH_ALEN); + + frame_body.Len = OS_HTONS(ETH_ALEN); + frame_body.DSAP = 0; + frame_body.SSAP = 0x01; + frame_body.Control = 0xAF; + + frame_body.XIDInfo[0] = 0x81; + frame_body.XIDInfo[1] = 1; + frame_body.XIDInfo[2] = 1 << 1; + + SET_OS_PKT_NETDEV(pNetBuf, pNetDev); + skb_reserve(pNetBuf, 2); + memcpy(skb_put(pNetBuf, size), &frame_body, size); + return pNetBuf; +} +#endif /* IAPP_SUPPORT */ + + +VOID RtmpOsPktNatMagicTag(PNDIS_PACKET pNetPkt) +{ +#ifdef RTMP_RBUS_SUPPORT +#if !defined(CONFIG_RA_NAT_NONE) +#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) + struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + FOE_MAGIC_TAG(pRxPkt) = FOE_MAGIC_WLAN; +#endif /* CONFIG_RA_HW_NAT || CONFIG_RA_HW_NAT_MODULE */ +#endif /* CONFIG_RA_NAT_NONE */ +#endif /* RTMP_RBUS_SUPPORT */ +} + +VOID RtmpOsPktNatNone(PNDIS_PACKET pNetPkt) +{ +#ifdef RTMP_RBUS_SUPPORT +#if defined(CONFIG_RA_NAT_NONE) +#if defined (CONFIG_RA_HW_NAT) || defined (CONFIG_RA_HW_NAT_MODULE) + FOE_AI(((struct sk_buff *)pNetPkt)) = UN_HIT; +#endif /* CONFIG_RA_HW_NAT || CONFIG_RA_HW_NAT_MODULE */ +#endif /* CONFIG_RA_NAT_NONE */ +#endif /* RTMP_RBUS_SUPPORT */ +} + + +#ifdef RT_CFG80211_SUPPORT +/* all available channels */ +UCHAR Cfg80211_Chan[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + + /* 802.11 UNI / HyperLan 2 */ + 36, 38, 40, 44, 46, 48, 52, 54, 56, 60, 62, 64, + + /* 802.11 HyperLan 2 */ + 100, 104, 108, 112, 116, 118, 120, 124, 126, 128, 132, 134, 136, + + /* 802.11 UNII */ + 140, 149, 151, 153, 157, 159, 161, 165, 167, 169, 171, 173, + + /* Japan */ + 184, 188, 192, 196, 208, 212, 216, +}; + +/* + Array of bitrates the hardware can operate with + in this band. Must be sorted to give a valid "supported + rates" IE, i.e. CCK rates first, then OFDM. + + For HT, assign MCS in another structure, ieee80211_sta_ht_cap. +*/ +const struct ieee80211_rate Cfg80211_SupRate[12] = { + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 10, + .hw_value = 0, + .hw_value_short = 0, + }, + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 20, + .hw_value = 1, + .hw_value_short = 1, + }, + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 55, + .hw_value = 2, + .hw_value_short = 2, + }, + { + .flags = IEEE80211_RATE_SHORT_PREAMBLE, + .bitrate = 110, + .hw_value = 3, + .hw_value_short = 3, + }, + { + .flags = 0, + .bitrate = 60, + .hw_value = 4, + .hw_value_short = 4, + }, + { + .flags = 0, + .bitrate = 90, + .hw_value = 5, + .hw_value_short = 5, + }, + { + .flags = 0, + .bitrate = 120, + .hw_value = 6, + .hw_value_short = 6, + }, + { + .flags = 0, + .bitrate = 180, + .hw_value = 7, + .hw_value_short = 7, + }, + { + .flags = 0, + .bitrate = 240, + .hw_value = 8, + .hw_value_short = 8, + }, + { + .flags = 0, + .bitrate = 360, + .hw_value = 9, + .hw_value_short = 9, + }, + { + .flags = 0, + .bitrate = 480, + .hw_value = 10, + .hw_value_short = 10, + }, + { + .flags = 0, + .bitrate = 540, + .hw_value = 11, + .hw_value_short = 11, + }, +}; + +static const UINT32 CipherSuites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +}; + +/* +======================================================================== +Routine Description: + UnRegister MAC80211 Module. + +Arguments: + pCB - CFG80211 control block pointer + pNetDev - Network device + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID CFG80211OS_UnRegister( + IN VOID *pCB, + IN VOID *pNetDevOrg) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct net_device *pNetDev = (struct net_device *)pNetDevOrg; + + + /* unregister */ + if (pCfg80211_CB->pCfg80211_Wdev != NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> unregister/free wireless device\n")); + + /* + Must unregister, or you will suffer problem when you change + regulatory domain by using iw. + */ + +#ifdef RFKILL_HW_SUPPORT + wiphy_rfkill_stop_polling(pCfg80211_CB->pCfg80211_Wdev->wiphy); +#endif /* RFKILL_HW_SUPPORT */ + wiphy_unregister(pCfg80211_CB->pCfg80211_Wdev->wiphy); + wiphy_free(pCfg80211_CB->pCfg80211_Wdev->wiphy); + kfree(pCfg80211_CB->pCfg80211_Wdev); + + if (pCfg80211_CB->pCfg80211_Channels != NULL) + kfree(pCfg80211_CB->pCfg80211_Channels); + + if (pCfg80211_CB->pCfg80211_Rates != NULL) + kfree(pCfg80211_CB->pCfg80211_Rates); + + pCfg80211_CB->pCfg80211_Wdev = NULL; + pCfg80211_CB->pCfg80211_Channels = NULL; + pCfg80211_CB->pCfg80211_Rates = NULL; + + /* must reset to NULL; or kernel will panic in unregister_netdev */ + pNetDev->ieee80211_ptr = NULL; + SET_NETDEV_DEV(pNetDev, NULL); + } + + os_free_mem(NULL, pCfg80211_CB); +} + + +/* +======================================================================== +Routine Description: + Initialize wireless channel in 2.4GHZ and 5GHZ. + +Arguments: + pAd - WLAN control block pointer + pWiphy - WLAN PHY interface + pChannels - Current channel info + pRates - Current rate info + +Return Value: + TRUE - init successfully + FALSE - init fail + +Note: + TX Power related: + + 1. Suppose we can send power to 15dBm in the board. + 2. A value 0x0 ~ 0x1F for a channel. We will adjust it based on 15dBm/ + 54Mbps. So if value == 0x07, the TX power of 54Mbps is 15dBm and + the value is 0x07 in the EEPROM. + 3. Based on TX power value of 54Mbps/channel, adjust another value + 0x0 ~ 0xF for other data rate. (-6dBm ~ +6dBm) + + Other related factors: + 1. TX power percentage from UI/users; + 2. Maximum TX power limitation in the regulatory domain. +======================================================================== +*/ +BOOLEAN CFG80211_SupBandInit( + IN VOID *pCB, + IN CFG80211_BAND *pBandInfo, + IN VOID *pWiphyOrg, + IN VOID *pChannelsOrg, + IN VOID *pRatesOrg) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; + struct ieee80211_channel *pChannels = (struct ieee80211_channel *)pChannelsOrg; + struct ieee80211_rate *pRates = (struct ieee80211_rate *)pRatesOrg; + struct ieee80211_supported_band *pBand; + UINT32 NumOfChan, NumOfRate; + UINT32 IdLoop; + UINT32 CurTxPower; + + + /* sanity check */ + if (pBandInfo->RFICType == 0) + pBandInfo->RFICType = RFIC_24GHZ | RFIC_5GHZ; + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> RFICType = %d\n", + pBandInfo->RFICType)); + + /* init */ + if (pBandInfo->RFICType & RFIC_5GHZ) + NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ + CFG80211_NUM_OF_CHAN_5GHZ; + else + NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ; + + if (pBandInfo->FlgIsBMode == TRUE) + NumOfRate = 4; + else + NumOfRate = 4 + 8; + + if (pChannels == NULL) + { + pChannels = kzalloc(sizeof(*pChannels) * NumOfChan, GFP_KERNEL); + if (!pChannels) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> ieee80211_channel allocation fail!\n")); + return FALSE; + } + } + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Number of channel = %d\n", + CFG80211_NUM_OF_CHAN_5GHZ)); + + if (pRates == NULL) + { + pRates = kzalloc(sizeof(*pRates) * NumOfRate, GFP_KERNEL); + if (!pRates) + { + os_free_mem(NULL, pChannels); + DBGPRINT(RT_DEBUG_ERROR, ("80211> ieee80211_rate allocation fail!\n")); + return FALSE; + } + } + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> Number of rate = %d\n", NumOfRate)); + + /* get TX power */ +#ifdef SINGLE_SKU + CurTxPower = pBandInfo->DefineMaxTxPwr; /* dBm */ +#else + CurTxPower = 0; /* unknown */ +#endif /* SINGLE_SKU */ + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> CurTxPower = %d dBm\n", CurTxPower)); + + /* init channel */ + for(IdLoop=0; IdLoopCfg80211_bands[IEEE80211_BAND_2GHZ]; + if (pBandInfo->RFICType & RFIC_24GHZ) + { + pBand->n_channels = CFG80211_NUM_OF_CHAN_2GHZ; + pBand->n_bitrates = NumOfRate; + pBand->channels = pChannels; + pBand->bitrates = pRates; + +#ifdef DOT11_N_SUPPORT + /* for HT, assign pBand->ht_cap */ + pBand->ht_cap.ht_supported = true; + pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SM_PS | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_DSSSCCK40; + pBand->ht_cap.ampdu_factor = 3; /* 2 ^ 16 */ + pBand->ht_cap.ampdu_density = pBandInfo->MpduDensity; + + memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); + CFG80211DBG(RT_DEBUG_ERROR, + ("80211> TxStream = %d\n", pBandInfo->TxStream)); + + switch(pBandInfo->TxStream) + { + case 1: + default: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + break; + + case 2: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + break; + + case 3: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + pBand->ht_cap.mcs.rx_mask[2] = 0xff; + break; + } + + pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; +#endif /* DOT11_N_SUPPORT */ + + pWiphy->bands[IEEE80211_BAND_2GHZ] = pBand; + } + else + { + pWiphy->bands[IEEE80211_BAND_2GHZ] = NULL; + pBand->channels = NULL; + pBand->bitrates = NULL; + } + + pBand = &pCfg80211_CB->Cfg80211_bands[IEEE80211_BAND_5GHZ]; + if (pBandInfo->RFICType & RFIC_5GHZ) + { + pBand->n_channels = CFG80211_NUM_OF_CHAN_5GHZ; + pBand->n_bitrates = NumOfRate - 4; + pBand->channels = &pChannels[CFG80211_NUM_OF_CHAN_2GHZ]; + pBand->bitrates = &pRates[4]; + + /* for HT, assign pBand->ht_cap */ +#ifdef DOT11_N_SUPPORT + /* for HT, assign pBand->ht_cap */ + pBand->ht_cap.ht_supported = true; + pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SM_PS | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_DSSSCCK40; + pBand->ht_cap.ampdu_factor = 3; /* 2 ^ 16 */ + pBand->ht_cap.ampdu_density = pBandInfo->MpduDensity; + + memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs)); + switch(pBandInfo->RxStream) + { + case 1: + default: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + break; + + case 2: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + break; + + case 3: + pBand->ht_cap.mcs.rx_mask[0] = 0xff; + pBand->ht_cap.mcs.rx_mask[1] = 0xff; + pBand->ht_cap.mcs.rx_mask[2] = 0xff; + break; + } + + pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; +#endif /* DOT11_N_SUPPORT */ + + pWiphy->bands[IEEE80211_BAND_5GHZ] = pBand; + } + else + { + pWiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + pBand->channels = NULL; + pBand->bitrates = NULL; + } + + pCfg80211_CB->pCfg80211_Channels = pChannels; + pCfg80211_CB->pCfg80211_Rates = pRates; + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Re-Initialize wireless channel/PHY in 2.4GHZ and 5GHZ. + +Arguments: + pCB - CFG80211 control block pointer + pBandInfo - Band information + +Return Value: + TRUE - re-init successfully + FALSE - re-init fail + +Note: + CFG80211_SupBandInit() is called in xx_probe(). + But we do not have complete chip information in xx_probe() so we + need to re-init bands in xx_open(). +======================================================================== +*/ +BOOLEAN CFG80211OS_SupBandReInit( + IN VOID *pCB, + IN CFG80211_BAND *pBandInfo) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy; + + + if ((pCfg80211_CB == NULL) || (pCfg80211_CB->pCfg80211_Wdev == NULL)) + return FALSE; + + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + + if (pWiphy != NULL) + { + CFG80211DBG(RT_DEBUG_ERROR, ("80211> re-init bands...\n")); + + /* re-init bands */ + CFG80211_SupBandInit(pCfg80211_CB, pBandInfo, pWiphy, + pCfg80211_CB->pCfg80211_Channels, + pCfg80211_CB->pCfg80211_Rates); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) + /* re-init PHY */ + pWiphy->rts_threshold = pBandInfo->RtsThreshold; + pWiphy->frag_threshold = pBandInfo->FragmentThreshold; + pWiphy->retry_short = pBandInfo->RetryMaxCnt & 0xff; + pWiphy->retry_long = (pBandInfo->RetryMaxCnt & 0xff00)>>8; +#endif /* LINUX_VERSION_CODE */ + + return TRUE; + } + + return FALSE; +} + + +/* +======================================================================== +Routine Description: + Hint to the wireless core a regulatory domain from driver. + +Arguments: + pAd - WLAN control block pointer + pCountryIe - pointer to the country IE + CountryIeLen - length of the country IE + +Return Value: + NONE + +Note: + Must call the function in kernel thread. +======================================================================== +*/ +VOID CFG80211OS_RegHint( + IN VOID *pCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + + + CFG80211DBG(RT_DEBUG_ERROR, + ("crda> regulatory domain hint: %c%c\n", + pCountryIe[0], pCountryIe[1])); + + if ((pCfg80211_CB->pCfg80211_Wdev == NULL) || (pCountryIe == NULL)) + { + CFG80211DBG(RT_DEBUG_ERROR, ("crda> regulatory domain hint not support!\n")); + return; + } + + /* hints a country IE as a regulatory domain "without" channel/power info. */ +/* regulatory_hint(pCfg80211_CB->pMac80211_Hw->wiphy, pCountryIe); */ + regulatory_hint(pCfg80211_CB->pCfg80211_Wdev->wiphy, (const char *)pCountryIe); +} + + +/* +======================================================================== +Routine Description: + Hint to the wireless core a regulatory domain from country element. + +Arguments: + pAdCB - WLAN control block pointer + pCountryIe - pointer to the country IE + CountryIeLen - length of the country IE + +Return Value: + NONE + +Note: + Must call the function in kernel thread. +======================================================================== +*/ +VOID CFG80211OS_RegHint11D( + IN VOID *pCB, + IN UCHAR *pCountryIe, + IN ULONG CountryIeLen) +{ + /* no regulatory_hint_11d() in 2.6.32 */ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + + + if ((pCfg80211_CB->pCfg80211_Wdev == NULL) || (pCountryIe == NULL)) + { + CFG80211DBG(RT_DEBUG_ERROR, ("crda> regulatory domain hint not support!\n")); + return; + } + + CFG80211DBG(RT_DEBUG_ERROR, + ("crda> regulatory domain hint: %c%c\n", + pCountryIe[0], pCountryIe[1])); + + /* + hints a country IE as a regulatory domain "with" channel/power info. + but if you use regulatory_hint(), it only hint "regulatory domain". + */ +/* regulatory_hint_11d(pCfg80211_CB->pMac80211_Hw->wiphy, pCountryIe, CountryIeLen); */ + regulatory_hint_11d(pCfg80211_CB->pCfg80211_Wdev->wiphy, pCountryIe, CountryIeLen); +#endif /* LINUX_VERSION_CODE */ +} + + +BOOLEAN CFG80211OS_BandInfoGet( + IN VOID *pCB, + IN VOID *pWiphyOrg, + OUT VOID **ppBand24, + OUT VOID **ppBand5) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; + + + if (pWiphy == NULL) + { + if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL)) + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + } + + if (pWiphy == NULL) + return FALSE; + + *ppBand24 = pWiphy->bands[IEEE80211_BAND_2GHZ]; + *ppBand5 = pWiphy->bands[IEEE80211_BAND_5GHZ]; + return TRUE; +} + + +UINT32 CFG80211OS_ChanNumGet( + IN VOID *pCB, + IN VOID *pWiphyOrg, + IN UINT32 IdBand) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; + + + if (pWiphy == NULL) + { + if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL)) + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + } + + if (pWiphy == NULL) + return 0; + + if (pWiphy->bands[IdBand] != NULL) + return pWiphy->bands[IdBand]->n_channels; + + return 0; +} + + +BOOLEAN CFG80211OS_ChanInfoGet( + IN VOID *pCB, + IN VOID *pWiphyOrg, + IN UINT32 IdBand, + IN UINT32 IdChan, + OUT UINT32 *pChanId, + OUT UINT32 *pPower, + OUT BOOLEAN *pFlgIsRadar) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg; + struct ieee80211_supported_band *pSband; + struct ieee80211_channel *pChan; + + + if (pWiphy == NULL) + { + if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL)) + pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; + } + + if (pWiphy == NULL) + return FALSE; + + pSband = pWiphy->bands[IdBand]; + pChan = &pSband->channels[IdChan]; + + *pChanId = ieee80211_frequency_to_channel(pChan->center_freq); + + if (pChan->flags & IEEE80211_CHAN_DISABLED) + { + CFG80211DBG(RT_DEBUG_ERROR, + ("Chan %03d (frq %d):\tnot allowed!\n", + (*pChanId), pChan->center_freq)); + return FALSE; + } + + *pPower = pChan->max_power; + + if (pChan->flags & IEEE80211_CHAN_RADAR) + *pFlgIsRadar = TRUE; + else + *pFlgIsRadar = FALSE; + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Initialize a channel information used in scan inform. + +Arguments: + +Return Value: + TRUE - Successful + FALSE - Fail + +Note: +======================================================================== +*/ +BOOLEAN CFG80211OS_ChanInfoInit( + IN VOID *pCB, + IN UINT32 InfoIndex, + IN UCHAR ChanId, + IN UCHAR MaxTxPwr, + IN BOOLEAN FlgIsNMode, + IN BOOLEAN FlgIsBW20M) +{ + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + struct ieee80211_channel *pChan; + + + if (InfoIndex >= MAX_NUM_OF_CHANNELS) + return FALSE; + + pChan = (struct ieee80211_channel *)&(pCfg80211_CB->ChanInfo[InfoIndex]); + memset(pChan, 0, sizeof(*pChan)); + + if (ChanId > 14) + pChan->band = IEEE80211_BAND_5GHZ; + else + pChan->band = IEEE80211_BAND_2GHZ; + + pChan->center_freq = ieee80211_channel_to_frequency(ChanId); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) + if (FlgIsNMode == TRUE) + { + if (FlgIsBW20M == TRUE) + pChan->max_bandwidth = 20; /* 20MHz */ + else + pChan->max_bandwidth = 40; /* 40MHz */ + } + else + pChan->max_bandwidth = 5; /* 5MHz for non-HT device */ +#endif /* LINUX_VERSION_CODE */ + + /* no use currently in 2.6.30 */ +/* if (ieee80211_is_beacon(((struct ieee80211_mgmt *)pFrame)->frame_control)) */ +/* pChan->beacon_found = 1; */ + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Inform us that a scan is got. + +Arguments: + pAdCB - WLAN control block pointer + +Return Value: + NONE + +Note: + Call RT_CFG80211_SCANNING_INFORM, not CFG80211_Scaning +======================================================================== +*/ +VOID CFG80211OS_Scaning( + IN VOID *pCB, + IN UINT32 ChanId, + IN UCHAR *pFrame, + IN UINT32 FrameLen, + IN INT32 RSSI, + IN BOOLEAN FlgIsNMode, + IN UINT8 BW) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) +#ifdef CONFIG_STA_SUPPORT + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + UINT32 IdChan; + UINT32 CenFreq; + + + /* get channel information */ + CenFreq = ieee80211_channel_to_frequency(ChanId); + + for(IdChan=0; IdChanChanInfo[IdChan].center_freq == CenFreq) + break; + } + if (IdChan >= MAX_NUM_OF_CHANNELS) + { + DBGPRINT(RT_DEBUG_ERROR, ("80211> Can not find any chan info!\n")); + return; + } + + /* inform 80211 a scan is got */ + /* we can use cfg80211_inform_bss in 2.6.31, it is easy more than the one */ + /* in cfg80211_inform_bss_frame(), it will memcpy pFrame but pChan */ + cfg80211_inform_bss_frame(pCfg80211_CB->pCfg80211_Wdev->wiphy, + &pCfg80211_CB->ChanInfo[IdChan], + (struct ieee80211_mgmt *)pFrame, + FrameLen, + RSSI, + GFP_ATOMIC); + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> cfg80211_inform_bss_frame\n")); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* LINUX_VERSION_CODE */ +} + + +/* +======================================================================== +Routine Description: + Inform us that scan ends. + +Arguments: + pAdCB - WLAN control block pointer + FlgIsAborted - 1: scan is aborted + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID CFG80211OS_ScanEnd( + IN VOID *pCB, + IN BOOLEAN FlgIsAborted) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) +#ifdef CONFIG_STA_SUPPORT + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + + + CFG80211DBG(RT_DEBUG_ERROR, ("80211> cfg80211_scan_done\n")); + cfg80211_scan_done(pCfg80211_CB->pCfg80211_ScanReq, FlgIsAborted); +#endif /* CONFIG_STA_SUPPORT */ +#endif /* LINUX_VERSION_CODE */ +} + + +/* +======================================================================== +Routine Description: + Inform CFG80211 about association status. + +Arguments: + pAdCB - WLAN control block pointer + pBSSID - the BSSID of the AP + pReqIe - the element list in the association request frame + ReqIeLen - the request element length + pRspIe - the element list in the association response frame + RspIeLen - the response element length + FlgIsSuccess - 1: success; otherwise: fail + +Return Value: + None + +Note: +======================================================================== +*/ +void CFG80211OS_ConnectResultInform( + IN VOID *pCB, + IN UCHAR *pBSSID, + IN UCHAR *pReqIe, + IN UINT32 ReqIeLen, + IN UCHAR *pRspIe, + IN UINT32 RspIeLen, + IN UCHAR FlgIsSuccess) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)) + CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB; + + + if ((pCfg80211_CB->pCfg80211_Wdev->netdev == NULL) || (pBSSID == NULL)) + return; + + if (FlgIsSuccess) + { + cfg80211_connect_result(pCfg80211_CB->pCfg80211_Wdev->netdev, + pBSSID, + pReqIe, + ReqIeLen, + pRspIe, + RspIeLen, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } + else + { + cfg80211_connect_result(pCfg80211_CB->pCfg80211_Wdev->netdev, + pBSSID, + NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } +#endif /* LINUX_VERSION_CODE */ +} +#endif /* RT_CFG80211_SUPPORT */ + + +/* +======================================================================== +Routine Description: + Flush a data cache line. + +Arguments: + AddrStart - the start address + Size - memory size + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsDCacheFlush( + IN ULONG AddrStart, + IN ULONG Size) +{ + RTMP_UTIL_DCACHE_FLUSH(AddrStart, Size); +} + + +/* +======================================================================== +Routine Description: + Assign private data pointer to the network interface. + +Arguments: + pDev - the device + pPriv - the pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSetNetDevPriv(VOID *pDev, VOID *pPriv) +{ + DEV_PRIV_INFO *pDevInfo = NULL; + + + pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev); + if (pDevInfo == NULL) + { + os_alloc_mem(NULL, (UCHAR **)&pDevInfo, sizeof(DEV_PRIV_INFO)); + if (pDevInfo == NULL) + return; + } + + pDevInfo->pPriv = (VOID *)pPriv; + pDevInfo->priv_flags = 0; + + _RTMP_OS_NETDEV_SET_PRIV((PNET_DEV) pDev, pDevInfo); +} + + +/* +======================================================================== +Routine Description: + Get private data pointer from the network interface. + +Arguments: + pDev - the device + pPriv - the pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID *RtmpOsGetNetDevPriv(VOID *pDev) +{ + DEV_PRIV_INFO *pDevInfo = NULL; + + + pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev); + if (pDevInfo != NULL) + return pDevInfo->pPriv; + return NULL; +} + + +/* +======================================================================== +Routine Description: + Get private flags from the network interface. + +Arguments: + pDev - the device + +Return Value: + pPriv - the pointer + +Note: +======================================================================== +*/ +USHORT RtmpDevPrivFlagsGet(VOID *pDev) +{ + + DEV_PRIV_INFO *pDevInfo = NULL; + + + pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev); + if (pDevInfo != NULL) + return pDevInfo->priv_flags; + return 0; +} + + +/* +======================================================================== +Routine Description: + Get private flags from the network interface. + +Arguments: + pDev - the device + +Return Value: + pPriv - the pointer + +Note: +======================================================================== +*/ +VOID RtmpDevPrivFlagsSet(VOID *pDev, USHORT PrivFlags) +{ + DEV_PRIV_INFO *pDevInfo = NULL; + + + pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev); + if (pDevInfo != NULL) + pDevInfo->priv_flags = PrivFlags; +} + + +#ifdef WIDI_SUPPORT +#ifdef CONFIG_STA_SUPPORT +INT RtmpOSWidiNotify( + IN PNET_DEV pNetDev, + IN PUCHAR buff, + IN INT len, + IN ULONG type) +{ + struct sk_buff *skb = NULL; + + skb = dev_alloc_skb(len + 2); + + if (!skb) + { + DBGPRINT(RT_DEBUG_ERROR,( "%s: failed to allocate sk_buff for notification\n", pNetDev->name)); + return -ENOMEM; + } + else + { + skb_reserve(skb, 2); + memcpy(skb_put(skb, len), buff, len); + skb->len = len; + skb->dev = pNetDev; +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)) + skb->mac.raw = skb->data; +#else + skb_set_mac_header(skb, 0); +#endif + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_WIDI_NOTIF); + memset(skb->cb, 0, sizeof(skb->cb)); +#if 0 + hex_dump("data", skb->data, skb->len); +#endif + netif_rx(skb); + } + return 0; +} +#endif /* CONFIG_STA_SUPPORT */ +#endif /*WIDI_SUPPORT */ + + +#ifdef OS_ABL_FUNC_SUPPORT +/* +======================================================================== +Routine Description: + Change/Recover file UID/GID. + +Arguments: + pOSFSInfoOrg - the file + bSet - Change (TRUE) or Recover (FALSE) + +Return Value: + None + +Note: + rt_linux.h, not rt_drv.h +======================================================================== +*/ +void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfoOrg, BOOLEAN bSet) +{ + OS_FS_INFO *pOSFSInfo; + + if (bSet == TRUE) { + os_alloc_mem(NULL, (UCHAR **) & (pOSFSInfoOrg->pContent), + sizeof (OS_FS_INFO)); + if (pOSFSInfoOrg->pContent == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc file info fail!\n", __FUNCTION__)); + return; + } else + memset(pOSFSInfoOrg->pContent, 0, sizeof (OS_FS_INFO)); + } + + pOSFSInfo = (OS_FS_INFO *) (pOSFSInfoOrg->pContent); + if (pOSFSInfo == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pOSFSInfo == NULL!\n", __FUNCTION__)); + return; + } + + __RtmpOSFSInfoChange(pOSFSInfo, bSet); + + if (bSet == FALSE) { + if (pOSFSInfoOrg->pContent != NULL) { + os_free_mem(NULL, pOSFSInfoOrg->pContent); + pOSFSInfoOrg->pContent = NULL; + } + } +} + + +/* +======================================================================== +Routine Description: + Activate a tasklet. + +Arguments: + pTasklet - the tasklet + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsTaskletSche(RTMP_NET_TASK_STRUCT *pTasklet) +{ + if (pTasklet->pContent == NULL) + return FALSE; + +#ifdef WORKQUEUE_BH + schedule_work((struct work_struct *)(pTasklet->pContent)); +#else + tasklet_hi_schedule((OS_NET_TASK_STRUCT *) (pTasklet->pContent)); +#endif /* WORKQUEUE_BH */ + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Initialize a tasklet. + +Arguments: + pTasklet - the tasklet + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsTaskletInit( + RTMP_NET_TASK_STRUCT *pTasklet, + VOID (*pFunc) (unsigned long data), + ULONG Data, + LIST_HEADER *pTaskletList) +{ +#ifdef WORKQUEUE_BH + if (RTMP_OS_Alloc_RscOnly(pTasklet, sizeof (struct work_struct)) == FALSE) + return FALSE; + + INIT_WORK((struct work_struct *)(pTasklet->pContent), pFunc); +#else + + if (RTMP_OS_Alloc_RscOnly(pTasklet, sizeof (OS_NET_TASK_STRUCT)) == FALSE) + return FALSE; + + tasklet_init((OS_NET_TASK_STRUCT *) (pTasklet->pContent), pFunc, Data); +#endif /* WORKQUEUE_BH */ + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Delete a tasklet. + +Arguments: + pTasklet - the tasklet + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsTaskletKill(RTMP_NET_TASK_STRUCT *pTasklet) +{ + if (pTasklet->pContent != NULL) { +#ifndef WORKQUEUE_BH + tasklet_kill((OS_NET_TASK_STRUCT *) (pTasklet->pContent)); +#endif /* WORKQUEUE_BH */ + + os_free_mem(NULL, pTasklet->pContent); + pTasklet->pContent = NULL; + } + + return TRUE; +} + + +VOID RtmpOsTaskletDataAssign(RTMP_NET_TASK_STRUCT *pTasklet, ULONG Data) +{ +#ifndef WORKQUEUE_BH + if (pTasklet->pContent != NULL) + ((OS_NET_TASK_STRUCT *) (pTasklet->pContent))->data = Data; +#endif /* WORKQUEUE_BH */ +} + + +INT32 RtmpOsTaskIsKilled(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return 1; + return pTask->task_killed; +} + + +VOID RtmpOsTaskWakeUp(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return; + +#ifdef KTHREAD_SUPPORT + WAKE_UP(pTask); +#else + RTMP_SEM_EVENT_UP(&pTask->taskSema); +#endif +} + + +/* +======================================================================== +Routine Description: + Check if the task is legal. + +Arguments: + pPkt - the packet + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsCheckTaskLegality(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (!pTask) + return FALSE; + +#ifdef KTHREAD_SUPPORT + if (pTask->kthread_task == NULL) +#else + CHECK_PID_LEGALITY(pTask->taskPID); + else +#endif + return FALSE; + + return TRUE; +} + + +/* timeout -- ms */ +VOID RTMP_SetPeriodicTimer(NDIS_MINIPORT_TIMER *pTimerOrg, ULONG timeout) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) + __RTMP_SetPeriodicTimer(pTimer, timeout); +} + + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +VOID RTMP_OS_Init_Timer( + VOID *pReserved, + NDIS_MINIPORT_TIMER *pTimerOrg, + TIMER_FUNCTION function, + PVOID data, + LIST_HEADER *pTimerList) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + if (RTMP_OS_Alloc_RscOnly(pTimerOrg, sizeof (OS_NDIS_MINIPORT_TIMER)) == FALSE) + return; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) + __RTMP_OS_Init_Timer(pReserved, pTimer, function, data); +} + + +VOID RTMP_OS_Add_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, ULONG timeout) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + + if (pTimer) { + if (timer_pending(pTimer)) + return; + + __RTMP_OS_Add_Timer(pTimer, timeout); + } +} + + +VOID RTMP_OS_Mod_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, ULONG timeout) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) + __RTMP_OS_Mod_Timer(pTimer, timeout); +} + + +VOID RTMP_OS_Del_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, BOOLEAN *pCancelled) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) + __RTMP_OS_Del_Timer(pTimer, pCancelled); +} + + +VOID RTMP_OS_Release_Timer(NDIS_MINIPORT_TIMER *pTimerOrg) +{ + OS_NDIS_MINIPORT_TIMER *pTimer; + + pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent); + if (pTimer) { + __RTMP_OS_Release_Timer(pTimer); + + os_free_mem(NULL, pTimer); + pTimerOrg->pContent = NULL; + } +} + + +/* +======================================================================== +Routine Description: + Allocate a OS resource. + +Arguments: + pAd - WLAN control block pointer + pRsc - the resource + RscLen - resource length + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RTMP_OS_Alloc_Rsc( + LIST_HEADER *pRscList, + VOID *pRscSrc, + UINT32 RscLen) +{ + OS_RSTRUC *pRsc = (OS_RSTRUC *) pRscSrc; + + if (pRsc->pContent == NULL) { + /* new entry */ + os_alloc_mem(NULL, (UCHAR **) & (pRsc->pContent), RscLen); + if (pRsc->pContent == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc timer fail!\n", __FUNCTION__)); + return FALSE; + } else { + LIST_RESOURCE_OBJ_ENTRY *pObj; + + /* allocate resource record entry */ + os_alloc_mem(NULL, (UCHAR **) & (pObj), + sizeof (LIST_RESOURCE_OBJ_ENTRY)); + if (pObj == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc timer obj fail!\n", + __FUNCTION__)); + os_free_mem(NULL, pRsc->pContent); + pRsc->pContent = NULL; + return FALSE; + } else { + memset(pRsc->pContent, 0, RscLen); + pObj->pRscObj = (VOID *) pRsc; + + OS_SEM_LOCK(&UtilSemLock); + insertTailList(pRscList, (LIST_ENTRY *) pObj); + OS_SEM_UNLOCK(&UtilSemLock); + } + } + } + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Allocate a OS resource. + +Arguments: + pAd - WLAN control block pointer + pRsc - the resource + RscLen - resource length + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RTMP_OS_Alloc_RscOnly(VOID *pRscSrc, UINT32 RscLen) +{ + OS_RSTRUC *pRsc = (OS_RSTRUC *) pRscSrc; + + if (pRsc->pContent == NULL) { + /* new entry */ + os_alloc_mem(NULL, (UCHAR **) & (pRsc->pContent), RscLen); + if (pRsc->pContent == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc timer fail!\n", __FUNCTION__)); + return FALSE; + } + memset(pRsc->pContent, 0, RscLen); + } + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Remove a OS resource. + +Arguments: + pAd - WLAN control block pointer + pRsc - the resource + +Return Value: + TRUE or FALSE + +Note: +======================================================================== +*/ +BOOLEAN RTMP_OS_Remove_Rsc( + LIST_HEADER *pRscList, + VOID *pRscSrc) +{ + LIST_RESOURCE_OBJ_ENTRY *pObj; + OS_RSTRUC *pRscHead, *pRsc, *pRscRev = (OS_RSTRUC *) pRscSrc; + pRscHead = NULL; + + OS_SEM_LOCK(&UtilSemLock); + while(TRUE) + { + pObj = (LIST_RESOURCE_OBJ_ENTRY *) removeHeadList(pRscList); + if (pRscHead == NULL) + pRscHead = pObj->pRscObj; /* backup first entry */ + else if (((ULONG)pRscHead) == ((ULONG)(pObj->pRscObj))) + break; /* has searched all entries */ + + pRsc = (OS_RSTRUC *) (pObj->pRscObj); + if ((ULONG)pRsc == (ULONG)pRscRev) + break; /* find it */ + + /* re-insert it */ + insertTailList(pRscList, (LIST_ENTRY *) pObj); + } + OS_SEM_UNLOCK(&UtilSemLock); + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Free all timers. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_OS_Free_Rscs(LIST_HEADER *pRscList) +{ + LIST_RESOURCE_OBJ_ENTRY *pObj; + OS_RSTRUC *pRsc; + + OS_SEM_LOCK(&UtilSemLock); + while (TRUE) { + pObj = (LIST_RESOURCE_OBJ_ENTRY *) removeHeadList(pRscList); + if (pObj == NULL) + break; + pRsc = (OS_RSTRUC *) (pObj->pRscObj); + + if (pRsc->pContent != NULL) { + /* free the timer memory */ + os_free_mem(NULL, pRsc->pContent); + pRsc->pContent = NULL; + } else { + /* + The case is possible because some timers are released during + the driver life time, EX: we will release some timers in + MacTableDeleteEntry(). + But we do not recommend the behavior, i.e. not to release + timers in the driver life time; Or we can not cancel the + timer for timer preemption problem. + */ + } + + os_free_mem(NULL, pObj); /* free the timer record entry */ + } + OS_SEM_UNLOCK(&UtilSemLock); +} + + +/* +======================================================================== +Routine Description: + Allocate a kernel task. + +Arguments: + pTask - the task + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN RtmpOSTaskAlloc(RTMP_OS_TASK *pTask, LIST_HEADER *pTaskList) +{ + if (RTMP_OS_Alloc_RscOnly(pTask, sizeof (OS_TASK)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc task fail!\n", __FUNCTION__)); + return FALSE; /* allocate fail */ + } + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Free a kernel task. + +Arguments: + pTask - the task + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOSTaskFree(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask != NULL) { + os_free_mem(NULL, pTask); + pTaskOrg->pContent = NULL; + } +} + + +/* +======================================================================== +Routine Description: + Kill a kernel task. + +Arguments: + pTaskOrg - the task + +Return Value: + None + +Note: +======================================================================== +*/ +NDIS_STATUS RtmpOSTaskKill(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + NDIS_STATUS Status; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask != NULL) { + Status = __RtmpOSTaskKill(pTask); + RtmpOSTaskFree(pTaskOrg); + return Status; + } + + return NDIS_STATUS_FAILURE; +} + + +/* +======================================================================== +Routine Description: + Notify kernel the task exit. + +Arguments: + pTaskOrg - the task + +Return Value: + None + +Note: +======================================================================== +*/ +INT RtmpOSTaskNotifyToExit(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return 0; + return __RtmpOSTaskNotifyToExit(pTask); +} + + +/* +======================================================================== +Routine Description: + Customize the task. + +Arguments: + pTaskOrg - the task + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOSTaskCustomize(RTMP_OS_TASK *pTaskOrg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask) + __RtmpOSTaskCustomize(pTask); +} + + +/* +======================================================================== +Routine Description: + Activate a kernel task. + +Arguments: + pTaskOrg - the task + fn - task handler + arg - task input argument + +Return Value: + None + +Note: +======================================================================== +*/ +NDIS_STATUS RtmpOSTaskAttach( + RTMP_OS_TASK *pTaskOrg, + RTMP_OS_TASK_CALLBACK fn, + ULONG arg) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return NDIS_STATUS_FAILURE; + return __RtmpOSTaskAttach(pTask, fn, arg); +} + + +/* +======================================================================== +Routine Description: + Initialize a kernel task. + +Arguments: + pTaskOrg - the task + pTaskName - task name + pPriv - task input argument + +Return Value: + None + +Note: +======================================================================== +*/ +NDIS_STATUS RtmpOSTaskInit( + RTMP_OS_TASK *pTaskOrg, + PSTRING pTaskName, + VOID *pPriv, + LIST_HEADER *pTaskList, + LIST_HEADER *pSemList) +{ + OS_TASK *pTask; + + if (RtmpOSTaskAlloc(pTaskOrg, pTaskList) == FALSE) + return NDIS_STATUS_FAILURE; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return NDIS_STATUS_FAILURE; + + return __RtmpOSTaskInit(pTask, pTaskName, pPriv, pSemList); +} + + +/* +======================================================================== +Routine Description: + Wait for a event in the task. + +Arguments: + pAd - WLAN control block pointer + pTaskOrg - the task + +Return Value: + TRUE + FALSE + +Note: +======================================================================== +*/ +BOOLEAN RtmpOSTaskWait(VOID *pReserved, RTMP_OS_TASK *pTaskOrg, INT32 *pStatus) +{ + OS_TASK *pTask; + + pTask = (OS_TASK *) (pTaskOrg->pContent); + if (pTask == NULL) + return FALSE; + + return __RtmpOSTaskWait(pReserved, pTask, pStatus); +} + + +/* +======================================================================== +Routine Description: + Get private data for the task. + +Arguments: + pTaskOrg - the task + +Return Value: + None + +Note: +======================================================================== +*/ +VOID *RtmpOsTaskDataGet(RTMP_OS_TASK *pTaskOrg) +{ + if (pTaskOrg->pContent == NULL) + return NULL; + + return (((OS_TASK *) (pTaskOrg->pContent))->priv); +} + + +/* +======================================================================== +Routine Description: + Allocate a lock. + +Arguments: + pLock - the lock + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsAllocateLock(NDIS_SPIN_LOCK *pLock, LIST_HEADER *pLockList) +{ + if (RTMP_OS_Alloc_RscOnly(pLock, sizeof (OS_NDIS_SPIN_LOCK)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc lock fail!\n", __FUNCTION__)); + return FALSE; /* allocate fail */ + } + + OS_NdisAllocateSpinLock(pLock->pContent); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Free a lock. + +Arguments: + pLockOrg - the lock + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsFreeSpinLock(NDIS_SPIN_LOCK *pLockOrg) +{ + /* we will free all locks memory in RTMP_OS_FREE_LOCK() */ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_MINIPORT_TIMER *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_NdisFreeSpinLock(pLock); + + os_free_mem(NULL, pLock); + pLockOrg->pContent = NULL; + } +} + + +/* +======================================================================== +Routine Description: + Spin lock bh. + +Arguments: + pLockOrg - the lock + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSpinLockBh(NDIS_SPIN_LOCK *pLockOrg) +{ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_SEM_LOCK(pLock); + } else + printk("lock> warning! the lock was freed!\n"); +} + + +/* +======================================================================== +Routine Description: + Spin unlock bh. + +Arguments: + pLockOrg - the lock + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSpinUnLockBh(NDIS_SPIN_LOCK *pLockOrg) +{ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_SEM_UNLOCK(pLock); + } else + printk("lock> warning! the lock was freed!\n"); +} + + +/* +======================================================================== +Routine Description: + Interrupt lock. + +Arguments: + pLockOrg - the lock + pIrqFlags - the lock flags + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsIntLock(NDIS_SPIN_LOCK *pLockOrg, ULONG *pIrqFlags) +{ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_INT_LOCK(pLock, *pIrqFlags); + } else + printk("lock> warning! the lock was freed!\n"); +} + + +/* +======================================================================== +Routine Description: + Interrupt unlock. + +Arguments: + pLockOrg - the lock + IrqFlags - the lock flags + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsIntUnLock(NDIS_SPIN_LOCK *pLockOrg, ULONG IrqFlags) +{ + OS_NDIS_SPIN_LOCK *pLock; + + pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent); + if (pLock != NULL) { + OS_INT_UNLOCK(pLock, IrqFlags); + } else + printk("lock> warning! the lock was freed!\n"); +} + + +/* +======================================================================== +Routine Description: + Get MAC address for the network interface. + +Arguments: + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +unsigned char *RtmpOsNetDevGetPhyAddr(VOID *pDev) +{ + return RTMP_OS_NETDEV_GET_PHYADDR((PNET_DEV) pDev); +} + + +/* +======================================================================== +Routine Description: + Start network interface TX queue. + +Arguments: + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsNetQueueStart(PNET_DEV pDev) +{ + RTMP_OS_NETDEV_START_QUEUE(pDev); +} + + +/* +======================================================================== +Routine Description: + Stop network interface TX queue. + +Arguments: + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsNetQueueStop(PNET_DEV pDev) +{ + RTMP_OS_NETDEV_STOP_QUEUE(pDev); +} + + +/* +======================================================================== +Routine Description: + Wake up network interface TX queue. + +Arguments: + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsNetQueueWake(PNET_DEV pDev) +{ + RTMP_OS_NETDEV_WAKE_QUEUE(pDev); +} + + +/* +======================================================================== +Routine Description: + Assign network interface to the packet. + +Arguments: + pPkt - the packet + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSetPktNetDev(VOID *pPkt, VOID *pDev) +{ + SET_OS_PKT_NETDEV(pPkt, (PNET_DEV) pDev); +} + + +/* +======================================================================== +Routine Description: + Assign network interface type. + +Arguments: + pDev - the device + Type - the type + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSetNetDevType(VOID *pDev, USHORT Type) +{ + RTMP_OS_NETDEV_SET_TYPE((PNET_DEV) pDev, Type); +} + + +/* +======================================================================== +Routine Description: + Assign network interface type for monitor mode. + +Arguments: + pDev - the device + Type - the type + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSetNetDevTypeMonitor(VOID *pDev) +{ + RTMP_OS_NETDEV_SET_TYPE((PNET_DEV) pDev, ARPHRD_IEEE80211_PRISM); +} + + +/* +======================================================================== +Routine Description: + Get PID. + +Arguments: + pPkt - the packet + pDev - the device + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsGetPid(IN ULONG *pDst, + IN ULONG PID) +{ + RT_GET_OS_PID(*pDst, PID); +} + + +/* +======================================================================== +Routine Description: + Wait for a moment. + +Arguments: + Time - micro second + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsWait(UINT32 Time) +{ + OS_WAIT(Time); +} + + +/* +======================================================================== +Routine Description: + Check if b is smaller than a. + +Arguments: + Time - micro second + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 RtmpOsTimerAfter(ULONG a, ULONG b) +{ + return RTMP_TIME_AFTER(a, b); +} + + +/* +======================================================================== +Routine Description: + Check if b is not smaller than a. + +Arguments: + Time - micro second + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 RtmpOsTimerBefore(ULONG a, ULONG b) +{ + return RTMP_TIME_BEFORE(a, b); +} + + +/* +======================================================================== +Routine Description: + Get current system time. + +Arguments: + pTime - system time (tick) + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsGetSystemUpTime(ULONG *pTime) +{ + NdisGetSystemUpTime(pTime); +} + +/* +======================================================================== +Routine Description: + Get OS tick unit. + +Arguments: + pOps - Utility table + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 RtmpOsTickUnitGet(VOID) +{ + return HZ; +} + + +/* +======================================================================== +Routine Description: + ntohs + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT16 RtmpOsNtohs(UINT16 Value) +{ + return OS_NTOHS(Value); +} + + +/* +======================================================================== +Routine Description: + htons + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT16 RtmpOsHtons(UINT16 Value) +{ + return OS_HTONS(Value); +} + + +/* +======================================================================== +Routine Description: + ntohl + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT32 RtmpOsNtohl(UINT32 Value) +{ + return OS_NTOHL(Value); +} + +/* +======================================================================== +Routine Description: + htonl + +Arguments: + Value - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT32 RtmpOsHtonl(UINT32 Value) +{ + return OS_HTONL(Value); +} + + +/* +======================================================================== +Routine Description: + get_unaligned for 16-bit value. + +Arguments: + pWord - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT16 RtmpOsGetUnaligned(UINT16 *pWord) +{ + return get_unaligned(pWord); +} + +/* +======================================================================== +Routine Description: + get_unaligned for 32-bit value. + +Arguments: + pWord - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +UINT32 RtmpOsGetUnaligned32(UINT32 *pWord) +{ + return get_unaligned(pWord); +} + +/* +======================================================================== +Routine Description: + get_unaligned for long-bit value. + +Arguments: + pWord - the value + +Return Value: + the value + +Note: +======================================================================== +*/ +ULONG RtmpOsGetUnalignedlong(ULONG *pWord) +{ + return get_unaligned(pWord); +} + + +/* +======================================================================== +Routine Description: + Get maximum scan data length. + +Arguments: + None + +Return Value: + length + +Note: + Used in site servey. +======================================================================== +*/ +ULONG RtmpOsMaxScanDataGet(VOID) +{ + return IW_SCAN_MAX_DATA; +} + + +/* +======================================================================== +Routine Description: + copy_from_user + +Arguments: + to - + from - + n - size + +Return Value: + copy size + +Note: +======================================================================== +*/ +ULONG RtmpOsCopyFromUser(VOID *to, const void *from, ULONG n) +{ + return (copy_from_user(to, from, n)); +} + + +/* +======================================================================== +Routine Description: + copy_to_user + +Arguments: + to - + from - + n - size + +Return Value: + copy size + +Note: +======================================================================== +*/ +ULONG RtmpOsCopyToUser(VOID *to, const void *from, ULONG n) +{ + return (copy_to_user(to, from, n)); +} + + +/* +======================================================================== +Routine Description: + Initialize a semaphore. + +Arguments: + pSem - the semaphore + +Return Value: + TRUE - Successfully + FALSE - Fail + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsSemaInitLocked(RTMP_OS_SEM *pSem, LIST_HEADER *pSemList) +{ + if (RTMP_OS_Alloc_RscOnly(pSem, sizeof (OS_SEM)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc semaphore fail!\n", __FUNCTION__)); + return FALSE; + } + + OS_SEM_EVENT_INIT_LOCKED((OS_SEM *) (pSem->pContent)); + return TRUE; +} + + + +/* +======================================================================== +Routine Description: + Initialize a semaphore. + +Arguments: + pSemOrg - the semaphore + +Return Value: + TRUE - Successfully + FALSE - Fail + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsSemaInit(RTMP_OS_SEM *pSem, LIST_HEADER *pSemList) +{ + if (RTMP_OS_Alloc_RscOnly(pSem, sizeof (OS_SEM)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: alloc semaphore fail!\n", __FUNCTION__)); + return FALSE; + } + + OS_SEM_EVENT_INIT((OS_SEM *) (pSem->pContent)); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Destroy a semaphore. + +Arguments: + pSemOrg - the semaphore + +Return Value: + TRUE - Successfully + FALSE - Fail + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsSemaDestory(RTMP_OS_SEM *pSemOrg) +{ + OS_SEM *pSem; + + pSem = (OS_SEM *) (pSemOrg->pContent); + if (pSem != NULL) { + OS_SEM_EVENT_DESTORY(pSem); + + os_free_mem(NULL, pSem); + pSemOrg->pContent = NULL; + } else + printk("sem> warning! double-free sem!\n"); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Wait a semaphore. + +Arguments: + pSemOrg - the semaphore + +Return Value: + 0 - Successfully + Otherwise - Fail + +Note: +======================================================================== +*/ +INT32 RtmpOsSemaWaitInterruptible(RTMP_OS_SEM *pSemOrg) +{ + OS_SEM *pSem; + INT Status = -1; + + pSem = (OS_SEM *) (pSemOrg->pContent); + if (pSem != NULL) + OS_SEM_EVENT_WAIT(pSem, Status); + return Status; +} + + +/* +======================================================================== +Routine Description: + Wake up a semaphore. + +Arguments: + pSemOrg - the semaphore + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsSemaWakeUp(RTMP_OS_SEM *pSemOrg) +{ + OS_SEM *pSem; + + pSem = (OS_SEM *) (pSemOrg->pContent); + if (pSem != NULL) + OS_SEM_EVENT_UP(pSem); +} + + +/* +======================================================================== +Routine Description: + Check if we are in a interrupt. + +Arguments: + None + +Return Value: + 0 - No + Otherwise - Yes + +Note: +======================================================================== +*/ +INT32 RtmpOsIsInInterrupt(VOID) +{ + return (in_interrupt()); +} + + +/* +======================================================================== +Routine Description: + Copy the data buffer to the packet frame body. + +Arguments: + pAd - WLAN control block pointer + pNetPkt - the packet + ThisFrameLen - copy length + pData - the data buffer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktBodyCopy( + PNET_DEV pNetDev, + PNDIS_PACKET pNetPkt, + ULONG ThisFrameLen, + PUCHAR pData) +{ + memcpy(skb_put(pNetPkt, ThisFrameLen), pData, ThisFrameLen); + SET_OS_PKT_NETDEV(pNetPkt, pNetDev); + RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pNetPkt), PKTSRC_NDIS); +} + + +/* +======================================================================== +Routine Description: + Check if the packet is cloned. + +Arguments: + pNetPkt - the packet + +Return Value: + TRUE - Yes + Otherwise - No + +Note: +======================================================================== +*/ +INT RtmpOsIsPktCloned(PNDIS_PACKET pNetPkt) +{ + return OS_PKT_CLONED(pNetPkt); +} + + +/* +======================================================================== +Routine Description: + Duplicate a packet. + +Arguments: + pNetPkt - the packet + +Return Value: + the new packet + +Note: +======================================================================== +*/ +PNDIS_PACKET RtmpOsPktCopy(PNDIS_PACKET pNetPkt) +{ + return skb_copy(RTPKT_TO_OSPKT(pNetPkt), GFP_ATOMIC); +} + + +/* +======================================================================== +Routine Description: + Clone a packet. + +Arguments: + pNetPkt - the packet + +Return Value: + the cloned packet + +Note: +======================================================================== +*/ +PNDIS_PACKET RtmpOsPktClone(PNDIS_PACKET pNetPkt) +{ + return skb_clone(RTPKT_TO_OSPKT(pNetPkt), MEM_ALLOC_FLAG); +} + + +/* +======================================================================== +Routine Description: + Assign the data pointer for the packet. + +Arguments: + pNetPkt - the packet + *pData - the data buffer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktDataPtrAssign(PNDIS_PACKET pNetPkt, UCHAR *pData) +{ + SET_OS_PKT_DATAPTR(pNetPkt, pData); +} + + +/* +======================================================================== +Routine Description: + Assign the data length for the packet. + +Arguments: + pNetPkt - the packet + Len - the data length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktLenAssign(PNDIS_PACKET pNetPkt, LONG Len) +{ + SET_OS_PKT_LEN(pNetPkt, Len); +} + + +/* +======================================================================== +Routine Description: + Adjust the tail pointer for the packet. + +Arguments: + pNetPkt - the packet + removedTagLen - the size for adjustment + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktTailAdjust(PNDIS_PACKET pNetPkt, UINT removedTagLen) +{ + OS_PKT_TAIL_ADJUST(pNetPkt, removedTagLen); +} + + +/* +======================================================================== +Routine Description: + Adjust the data pointer for the packet. + +Arguments: + pNetPkt - the packet + Len - the size for adjustment + +Return Value: + the new data pointer for the packet + +Note: +======================================================================== +*/ +PUCHAR RtmpOsPktTailBufExtend(PNDIS_PACKET pNetPkt, UINT Len) +{ + return OS_PKT_TAIL_BUF_EXTEND(pNetPkt, Len); +} + + +/* +======================================================================== +Routine Description: + adjust headroom for the packet. + +Arguments: + pNetPkt - the packet + Len - the size for adjustment + +Return Value: + the new data pointer for the packet + +Note: +======================================================================== +*/ +VOID RtmpOsPktReserve(PNDIS_PACKET pNetPkt, UINT Len) +{ + OS_PKT_RESERVE(pNetPkt, Len); +} + + +/* +======================================================================== +Routine Description: + Adjust the data pointer for the packet. + +Arguments: + pNetPkt - the packet + Len - the size for adjustment + +Return Value: + the new data pointer for the packet + +Note: +======================================================================== +*/ +PUCHAR RtmpOsPktHeadBufExtend(PNDIS_PACKET pNetPkt, UINT Len) +{ + return OS_PKT_HEAD_BUF_EXTEND(pNetPkt, Len); +} + + +/* +======================================================================== +Routine Description: + + +Arguments: + pPkt - the packet + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsPktInfPpaSend(PNDIS_PACKET pNetPkt) +{ +#ifdef INF_PPA_SUPPORT + struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt); + int ret = 0; + unsigned int ppa_flags = 0; /* reserved for now */ + + pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev); + + memset(pRxPkt->head, 0, pRxPkt->data - pRxPkt->head - 14); + DBGPRINT(RT_DEBUG_TRACE, + ("ppa_hook_directpath_send_fn rx :ret:%d headroom:%d dev:%s pktlen:%d<===\n", + ret, skb_headroom(pRxPkt) , pRxPkt->dev->name, pRxPkt->len)); + hex_dump("rx packet", pRxPkt->data, 32); + ret = ppa_hook_directpath_send_fn(pAd->g_if_id, pRxPkt, pRxPkt->len, ppa_flags); +#endif /* INF_PPA_SUPPORT */ +} + + +INT32 RtmpThreadPidKill(RTMP_OS_PID PID) +{ + return KILL_THREAD_PID(PID, SIGTERM, 1); +} + + +long RtmpOsSimpleStrtol(const char *cp, char **endp, unsigned int base) +{ + return simple_strtol(cp, endp, base); +} + + +BOOLEAN RtmpOsPktOffsetInit(VOID) +{ + struct sk_buff *pPkt = NULL; + + if ((RTPktOffsetData == 0) && (RTPktOffsetLen == 0) + && (RTPktOffsetCB == 0)) { + pPkt = kmalloc(sizeof (struct sk_buff), GFP_ATOMIC); + if (pPkt == NULL) + return FALSE; + + RTPktOffsetData = (ULONG) (&(pPkt->data)) - (ULONG) pPkt; + RTPktOffsetLen = (ULONG) (&(pPkt->len)) - (ULONG) pPkt; + RTPktOffsetCB = (ULONG) (pPkt->cb) - (ULONG) pPkt; + kfree(pPkt); + + DBGPRINT(RT_DEBUG_TRACE, + ("packet> data offset = %lu\n", RTPktOffsetData)); + DBGPRINT(RT_DEBUG_TRACE, + ("packet> len offset = %lu\n", RTPktOffsetLen)); + DBGPRINT(RT_DEBUG_TRACE, + ("packet> cb offset = %lu\n", RTPktOffsetCB)); + } + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Initialize the OS atomic_t. + +Arguments: + pAtomic - the atomic + +Return Value: + TRUE - allocation successfully + FALSE - allocation fail + +Note: +======================================================================== +*/ +BOOLEAN RtmpOsAtomicInit(RTMP_OS_ATOMIC *pAtomic, LIST_HEADER *pAtomicList) +{ + if (RTMP_OS_Alloc_RscOnly(pAtomic, sizeof (atomic_t)) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc atomic fail!\n", __FUNCTION__)); + return FALSE; /* allocate fail */ + } + + return TRUE; +} + +/* +======================================================================== +Routine Description: + Initialize the OS atomic_t. + +Arguments: + pAtomic - the atomic + +Return Value: + TRUE - allocation successfully + FALSE - allocation fail + +Note: +======================================================================== +*/ +VOID RtmpOsAtomicDestroy(RTMP_OS_ATOMIC *pAtomic) +{ + if (pAtomic->pContent) { + os_free_mem(NULL, pAtomic->pContent); + pAtomic->pContent = NULL; + } +} + +/* +======================================================================== +Routine Description: + Atomic read a variable. + +Arguments: + pAtomic - the atomic + +Return Value: + content + +Note: +======================================================================== +*/ +LONG RtmpOsAtomicRead(RTMP_OS_ATOMIC *pAtomicSrc) +{ + if (pAtomicSrc->pContent) + return atomic_read((atomic_t *) (pAtomicSrc->pContent)); + else + return 0; +} + + +/* +======================================================================== +Routine Description: + Atomic dec a variable. + +Arguments: + pAtomic - the atomic + +Return Value: + content + +Note: +======================================================================== +*/ +VOID RtmpOsAtomicDec(RTMP_OS_ATOMIC *pAtomicSrc) +{ + if (pAtomicSrc->pContent) + atomic_dec((atomic_t *) (pAtomicSrc->pContent)); +} + + +/* +======================================================================== +Routine Description: + Sets a 32-bit variable to the specified value as an atomic operation. + +Arguments: + pAtomic - the atomic + Value - the value to be exchanged + +Return Value: + the initial value of the pAtomicSrc parameter + +Note: +======================================================================== +*/ +VOID RtmpOsAtomicInterlockedExchange( + RTMP_OS_ATOMIC *pAtomicSrc, + LONG Value) +{ + if (pAtomicSrc->pContent) + InterlockedExchange((atomic_t *) (pAtomicSrc->pContent), Value); +} + + +/* +======================================================================== +Routine Description: + Initialize the OS utilities. + +Arguments: + pOps - Utility table + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpOsOpsInit(RTMP_OS_ABL_OPS *pOps) +{ + pOps->ra_printk = (RTMP_PRINTK)printk; + pOps->ra_snprintf = (RTMP_SNPRINTF)snprintf; +} + +#else /* OS_ABL_FUNC_SUPPORT */ + + +void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfoOrg, BOOLEAN bSet) +{ + __RtmpOSFSInfoChange(pOSFSInfoOrg, bSet); +} + + +/* timeout -- ms */ +VOID RTMP_SetPeriodicTimer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout) +{ + __RTMP_SetPeriodicTimer(pTimerOrg, timeout); +} + + +/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */ +VOID RTMP_OS_Init_Timer( + VOID *pReserved, + NDIS_MINIPORT_TIMER *pTimerOrg, + TIMER_FUNCTION function, + PVOID data, + LIST_HEADER *pTimerList) +{ + __RTMP_OS_Init_Timer(pReserved, pTimerOrg, function, data); +} + + +VOID RTMP_OS_Add_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout) +{ + __RTMP_OS_Add_Timer(pTimerOrg, timeout); +} + + +VOID RTMP_OS_Mod_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout) +{ + __RTMP_OS_Mod_Timer(pTimerOrg, timeout); +} + + +VOID RTMP_OS_Del_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, BOOLEAN *pCancelled) +{ + __RTMP_OS_Del_Timer(pTimerOrg, pCancelled); +} + + +VOID RTMP_OS_Release_Timer(NDIS_MINIPORT_TIMER *pTimerOrg) +{ + __RTMP_OS_Release_Timer(pTimerOrg); +} + + +NDIS_STATUS RtmpOSTaskKill(RTMP_OS_TASK *pTask) +{ + return __RtmpOSTaskKill(pTask); +} + + +INT RtmpOSTaskNotifyToExit(RTMP_OS_TASK *pTask) +{ + return __RtmpOSTaskNotifyToExit(pTask); +} + + +void RtmpOSTaskCustomize(RTMP_OS_TASK *pTask) +{ + __RtmpOSTaskCustomize(pTask); +} + + +NDIS_STATUS RtmpOSTaskAttach( + RTMP_OS_TASK *pTask, + RTMP_OS_TASK_CALLBACK fn, + ULONG arg) +{ + return __RtmpOSTaskAttach(pTask, fn, arg); +} + + +NDIS_STATUS RtmpOSTaskInit( + RTMP_OS_TASK *pTask, + PSTRING pTaskName, + VOID *pPriv, + LIST_HEADER *pTaskList, + LIST_HEADER *pSemList) +{ + return __RtmpOSTaskInit(pTask, pTaskName, pPriv, pSemList); +} + + +BOOLEAN RtmpOSTaskWait(VOID *pReserved, RTMP_OS_TASK * pTask, INT32 *pStatus) +{ + return __RtmpOSTaskWait(pReserved, pTask, pStatus); +} + + +VOID RtmpOsTaskWakeUp(RTMP_OS_TASK *pTask) +{ +#ifdef KTHREAD_SUPPORT + WAKE_UP(pTask); +#else + RTMP_SEM_EVENT_UP(&pTask->taskSema); +#endif +} + +#endif /* OS_ABL_FUNC_SUPPORT */ + -- 1.9.1