]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
Staging: rtl8192e: delete some dead cruft
[karo-tx-linux.git] / drivers / staging / rtl8192e / rtl8192e / r8192E_cmdpkt.c
1 /******************************************************************************
2  * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3  *
4  * This program is distributed in the hope that it will be useful, but WITHOUT
5  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
7  * more details.
8  *
9  * You should have received a copy of the GNU General Public License along with
10  * this program; if not, write to the Free Software Foundation, Inc.,
11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
12  *
13  * The full GNU General Public License is included in this distribution in the
14  * file called LICENSE.
15  *
16  * Contact Information:
17  * wlanfae <wlanfae@realtek.com>
18 ******************************************************************************/
19
20 #include "rtl_core.h"
21 #include "r8192E_hw.h"
22 #include "r8192E_cmdpkt.h"
23
24 bool cmpk_message_handle_tx(
25         struct net_device *dev,
26         u8      *code_virtual_address,
27         u32     packettype,
28         u32     buffer_len)
29 {
30
31         bool                            rt_status = true;
32         struct r8192_priv *priv = rtllib_priv(dev);
33         u16                             frag_threshold;
34         u16                             frag_length = 0, frag_offset = 0;
35         struct rt_firmware *pfirmware = priv->pFirmware;
36         struct sk_buff          *skb;
37         unsigned char           *seg_ptr;
38         struct cb_desc *tcb_desc;
39         u8                              bLastIniPkt;
40
41         struct tx_fwinfo_8190pci *pTxFwInfo = NULL;
42
43         RT_TRACE(COMP_CMDPKT, "%s(),buffer_len is %d\n", __func__, buffer_len);
44         firmware_init_param(dev);
45         frag_threshold = pfirmware->cmdpacket_frag_thresold;
46
47         do {
48                 if ((buffer_len - frag_offset) > frag_threshold) {
49                         frag_length = frag_threshold ;
50                         bLastIniPkt = 0;
51
52                 } else {
53                         frag_length = (u16)(buffer_len - frag_offset);
54                         bLastIniPkt = 1;
55                 }
56
57                 skb  = dev_alloc_skb(frag_length +
58                                      priv->rtllib->tx_headroom + 4);
59
60                 if (skb == NULL) {
61                         rt_status = false;
62                         goto Failed;
63                 }
64
65                 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
66                 tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
67                 tcb_desc->queue_index = TXCMD_QUEUE;
68                 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
69                 tcb_desc->bLastIniPkt = bLastIniPkt;
70                 tcb_desc->pkt_size = frag_length;
71
72                 seg_ptr = skb_put(skb, priv->rtllib->tx_headroom);
73                 pTxFwInfo = (struct tx_fwinfo_8190pci *)seg_ptr;
74                 memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci));
75                 memset(pTxFwInfo, 0x12, 8);
76
77                 seg_ptr = skb_put(skb, frag_length);
78                 memcpy(seg_ptr, code_virtual_address, (u32)frag_length);
79
80                 priv->rtllib->softmac_hard_start_xmit(skb, dev);
81
82                 code_virtual_address += frag_length;
83                 frag_offset += frag_length;
84
85         } while (frag_offset < buffer_len);
86
87         write_nic_byte(dev, TPPoll, TPPoll_CQ);
88 Failed:
89         return rt_status;
90 }
91
92 static  void
93 cmpk_count_txstatistic(
94         struct net_device *dev,
95         struct cmpk_txfb *pstx_fb)
96 {
97         struct r8192_priv *priv = rtllib_priv(dev);
98 #ifdef ENABLE_PS
99         enum rt_rf_power_state rtState;
100
101         pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
102                                           (pu1Byte)(&rtState));
103
104         if (rtState == eRfOff)
105                 return;
106 #endif
107
108         if (pstx_fb->tok) {
109                 priv->stats.txfeedbackok++;
110                 priv->stats.txoktotal++;
111                 priv->stats.txokbytestotal += pstx_fb->pkt_length;
112                 priv->stats.txokinperiod++;
113
114                 if (pstx_fb->pkt_type == PACKET_MULTICAST) {
115                         priv->stats.txmulticast++;
116                         priv->stats.txbytesmulticast += pstx_fb->pkt_length;
117                 } else if (pstx_fb->pkt_type == PACKET_BROADCAST) {
118                         priv->stats.txbroadcast++;
119                         priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
120                 } else {
121                         priv->stats.txunicast++;
122                         priv->stats.txbytesunicast += pstx_fb->pkt_length;
123                 }
124         } else {
125                 priv->stats.txfeedbackfail++;
126                 priv->stats.txerrtotal++;
127                 priv->stats.txerrbytestotal += pstx_fb->pkt_length;
128
129                 if (pstx_fb->pkt_type == PACKET_MULTICAST)
130                         priv->stats.txerrmulticast++;
131                 else if (pstx_fb->pkt_type == PACKET_BROADCAST)
132                         priv->stats.txerrbroadcast++;
133                 else
134                         priv->stats.txerrunicast++;
135         }
136
137         priv->stats.txretrycount += pstx_fb->retry_cnt;
138         priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
139 }
140
141 static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg)
142 {
143         struct r8192_priv *priv = rtllib_priv(dev);
144         struct cmpk_txfb rx_tx_fb;
145
146         priv->stats.txfeedback++;
147
148
149         memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(struct cmpk_txfb));
150         cmpk_count_txstatistic(dev, &rx_tx_fb);
151 }
152
153 static void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev)
154 {
155         struct r8192_priv *priv = rtllib_priv(dev);
156         u16 tx_rate;
157
158         if ((priv->rtllib->current_network.mode == IEEE_A)  ||
159             (priv->rtllib->current_network.mode == IEEE_N_5G) ||
160             ((priv->rtllib->current_network.mode == IEEE_N_24G)  &&
161             (!priv->rtllib->pHTInfo->bCurSuppCCK))) {
162                 tx_rate = 60;
163                 DMESG("send beacon frame  tx rate is 6Mbpm\n");
164         } else {
165                 tx_rate = 10;
166                 DMESG("send beacon frame  tx rate is 1Mbpm\n");
167         }
168 }
169
170 static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg)
171 {
172         struct cmpk_intr_sta rx_intr_status;    /* */
173         struct r8192_priv *priv = rtllib_priv(dev);
174
175         DMESG("---> cmpk_Handle_Interrupt_Status()\n");
176
177         rx_intr_status.length = pmsg[1];
178         if (rx_intr_status.length != (sizeof(struct cmpk_intr_sta) - 2)) {
179                 DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
180                 return;
181         }
182
183         if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
184                 rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
185
186                 DMESG("interrupt status = 0x%x\n",
187                       rx_intr_status.interrupt_status);
188
189                 if (rx_intr_status.interrupt_status & ISR_TxBcnOk) {
190                         priv->rtllib->bibsscoordinator = true;
191                         priv->stats.txbeaconokint++;
192                 } else if (rx_intr_status.interrupt_status & ISR_TxBcnErr) {
193                         priv->rtllib->bibsscoordinator = false;
194                         priv->stats.txbeaconerr++;
195                 }
196
197                 if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr)
198                         cmdpkt_beacontimerinterrupt_819xusb(dev);
199         }
200
201         DMESG("<---- cmpk_handle_interrupt_status()\n");
202
203 }
204
205 static  void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg)
206 {
207         cmpk_query_cfg_t        rx_query_cfg;
208
209
210         rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000)>>31;
211         rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5;
212         rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3;
213         rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0;
214         rx_query_cfg.cfg_offset  = pmsg[7];
215         rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) |
216                              (pmsg[10] << 8) | (pmsg[11] << 0);
217         rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) |
218                             (pmsg[14] << 8) | (pmsg[15] << 0);
219
220 }
221
222 static void cmpk_count_tx_status(struct net_device *dev,
223                                  struct cmpk_tx_status *pstx_status)
224 {
225         struct r8192_priv *priv = rtllib_priv(dev);
226
227 #ifdef ENABLE_PS
228
229         enum rt_rf_power_state rtstate;
230
231         pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
232                                           (pu1Byte)(&rtState));
233
234         if (rtState == eRfOff)
235                 return;
236 #endif
237
238         priv->stats.txfeedbackok        += pstx_status->txok;
239         priv->stats.txoktotal           += pstx_status->txok;
240
241         priv->stats.txfeedbackfail      += pstx_status->txfail;
242         priv->stats.txerrtotal          += pstx_status->txfail;
243
244         priv->stats.txretrycount                += pstx_status->txretry;
245         priv->stats.txfeedbackretry     += pstx_status->txretry;
246
247
248         priv->stats.txmulticast += pstx_status->txmcok;
249         priv->stats.txbroadcast += pstx_status->txbcok;
250         priv->stats.txunicast           += pstx_status->txucok;
251
252         priv->stats.txerrmulticast      += pstx_status->txmcfail;
253         priv->stats.txerrbroadcast      += pstx_status->txbcfail;
254         priv->stats.txerrunicast        += pstx_status->txucfail;
255
256         priv->stats.txbytesmulticast    += pstx_status->txmclength;
257         priv->stats.txbytesbroadcast    += pstx_status->txbclength;
258         priv->stats.txbytesunicast              += pstx_status->txuclength;
259
260         priv->stats.last_packet_rate            = pstx_status->rate;
261 }
262
263 static  void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg)
264 {
265         struct cmpk_tx_status rx_tx_sts;
266
267         memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(struct cmpk_tx_status));
268         cmpk_count_tx_status(dev, &rx_tx_sts);
269 }
270
271 static  void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg)
272 {
273         struct cmpk_tx_rahis *ptxrate;
274         u8 i, j;
275         u16                             length = sizeof(struct cmpk_tx_rahis);
276         u32 *ptemp;
277         struct r8192_priv *priv = rtllib_priv(dev);
278
279 #ifdef ENABLE_PS
280         pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
281                                          (pu1Byte)(&rtState));
282
283         if (rtState == eRfOff)
284                 return;
285 #endif
286
287         ptemp = (u32 *)pmsg;
288
289         for (i = 0; i < (length / 4); i++) {
290                 u16      temp1, temp2;
291
292                 temp1 = ptemp[i] & 0x0000FFFF;
293                 temp2 = ptemp[i] >> 16;
294                 ptemp[i] = (temp1 << 16) | temp2;
295         }
296
297         ptxrate = (struct cmpk_tx_rahis *)pmsg;
298
299         if (ptxrate == NULL)
300                 return;
301
302         for (i = 0; i < 16; i++) {
303                 if (i < 4)
304                         priv->stats.txrate.cck[i] += ptxrate->cck[i];
305
306                 if (i < 8)
307                         priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
308
309                 for (j = 0; j < 4; j++)
310                         priv->stats.txrate.ht_mcs[j][i] +=
311                                                          ptxrate->ht_mcs[j][i];
312         }
313 }
314
315 u32 cmpk_message_handle_rx(struct net_device *dev,
316                            struct rtllib_rx_stats *pstats)
317 {
318         int                     total_length;
319         u8                      cmd_length, exe_cnt = 0;
320         u8                      element_id;
321         u8                      *pcmd_buff;
322
323         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx()\n");
324
325         if (pstats == NULL)
326                 return 0;
327
328         total_length = pstats->Length;
329
330         pcmd_buff = pstats->virtual_address;
331
332         element_id = pcmd_buff[0];
333
334         while (total_length > 0 || exe_cnt++ > 100) {
335                 element_id = pcmd_buff[0];
336
337                 switch (element_id) {
338                 case RX_TX_FEEDBACK:
339                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
340                                  "RX_TX_FEEDBACK\n");
341                         cmpk_handle_tx_feedback(dev, pcmd_buff);
342                         cmd_length = CMPK_RX_TX_FB_SIZE;
343                         break;
344                 case RX_INTERRUPT_STATUS:
345                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
346                                  "RX_INTERRUPT_STATUS\n");
347                         cmpk_handle_interrupt_status(dev, pcmd_buff);
348                         cmd_length = sizeof(struct cmpk_intr_sta);
349                         break;
350                 case BOTH_QUERY_CONFIG:
351                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
352                                  "BOTH_QUERY_CONFIG\n");
353                         cmpk_handle_query_config_rx(dev, pcmd_buff);
354                         cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
355                         break;
356                 case RX_TX_STATUS:
357                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
358                                  "RX_TX_STATUS\n");
359                         cmpk_handle_tx_status(dev, pcmd_buff);
360                         cmd_length = CMPK_RX_TX_STS_SIZE;
361                         break;
362                 case RX_TX_PER_PKT_FEEDBACK:
363                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
364                                  "RX_TX_PER_PKT_FEEDBACK\n");
365                         cmd_length = CMPK_RX_TX_FB_SIZE;
366                         break;
367                 case RX_TX_RATE_HISTORY:
368                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
369                                  "RX_TX_HISTORY\n");
370                         cmpk_handle_tx_rate_history(dev, pcmd_buff);
371                         cmd_length = CMPK_TX_RAHIS_SIZE;
372                         break;
373                 default:
374
375                         RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx():"
376                                  "unknow CMD Element\n");
377                         return 1;
378                 }
379
380                 total_length -= cmd_length;
381                 pcmd_buff    += cmd_length;
382         }
383         return  1;
384 }