15449c685SForest Bond /* 25449c685SForest Bond * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 35449c685SForest Bond * All rights reserved. 45449c685SForest Bond * 55449c685SForest Bond * This program is free software; you can redistribute it and/or modify 65449c685SForest Bond * it under the terms of the GNU General Public License as published by 75449c685SForest Bond * the Free Software Foundation; either version 2 of the License, or 85449c685SForest Bond * (at your option) any later version. 95449c685SForest Bond * 105449c685SForest Bond * This program is distributed in the hope that it will be useful, 115449c685SForest Bond * but WITHOUT ANY WARRANTY; without even the implied warranty of 125449c685SForest Bond * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 135449c685SForest Bond * GNU General Public License for more details. 145449c685SForest Bond * 155449c685SForest Bond * You should have received a copy of the GNU General Public License along 165449c685SForest Bond * with this program; if not, write to the Free Software Foundation, Inc., 175449c685SForest Bond * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 185449c685SForest Bond * 195449c685SForest Bond * File: dpc.c 205449c685SForest Bond * 215449c685SForest Bond * Purpose: handle dpc rx functions 225449c685SForest Bond * 235449c685SForest Bond * Author: Lyndon Chen 245449c685SForest Bond * 255449c685SForest Bond * Date: May 20, 2003 265449c685SForest Bond * 275449c685SForest Bond * Functions: 285449c685SForest Bond * 295449c685SForest Bond * Revision History: 305449c685SForest Bond * 315449c685SForest Bond */ 325449c685SForest Bond 335449c685SForest Bond #include "device.h" 345449c685SForest Bond #include "baseband.h" 355449c685SForest Bond #include "rf.h" 3604d52197SJames A Shackleford #include "dpc.h" 375449c685SForest Bond 3833b1c8c1SMalcolm Priestley static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, 3933b1c8c1SMalcolm Priestley u16 bytes_received) 4033b1c8c1SMalcolm Priestley { 4133b1c8c1SMalcolm Priestley struct ieee80211_hw *hw = priv->hw; 4233b1c8c1SMalcolm Priestley struct ieee80211_supported_band *sband; 4333b1c8c1SMalcolm Priestley struct ieee80211_rx_status rx_status = { 0 }; 4433b1c8c1SMalcolm Priestley struct ieee80211_hdr *hdr; 4533b1c8c1SMalcolm Priestley __le16 fc; 4633b1c8c1SMalcolm Priestley u8 *rsr, *new_rsr, *rssi; 4733b1c8c1SMalcolm Priestley __le64 *tsf_time; 4833b1c8c1SMalcolm Priestley u16 frame_size; 4933b1c8c1SMalcolm Priestley int ii, r; 5033b1c8c1SMalcolm Priestley u8 *rx_sts, *rx_rate, *sq; 5133b1c8c1SMalcolm Priestley u8 *skb_data; 5233b1c8c1SMalcolm Priestley u8 rate_idx = 0; 5333b1c8c1SMalcolm Priestley u8 rate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; 5433b1c8c1SMalcolm Priestley long rx_dbm; 5533b1c8c1SMalcolm Priestley 5633b1c8c1SMalcolm Priestley /* [31:16]RcvByteCount ( not include 4-byte Status ) */ 5733b1c8c1SMalcolm Priestley frame_size = le16_to_cpu(*((__le16 *)(skb->data + 2))); 5833b1c8c1SMalcolm Priestley if (frame_size > 2346 || frame_size < 14) { 5933b1c8c1SMalcolm Priestley dev_dbg(&priv->pcid->dev, "------- WRONG Length 1\n"); 6033b1c8c1SMalcolm Priestley return false; 6133b1c8c1SMalcolm Priestley } 6233b1c8c1SMalcolm Priestley 6333b1c8c1SMalcolm Priestley skb_data = (u8 *)skb->data; 6433b1c8c1SMalcolm Priestley 6533b1c8c1SMalcolm Priestley rx_sts = skb_data; 6633b1c8c1SMalcolm Priestley rx_rate = skb_data + 1; 6733b1c8c1SMalcolm Priestley 6833b1c8c1SMalcolm Priestley sband = hw->wiphy->bands[hw->conf.chandef.chan->band]; 6933b1c8c1SMalcolm Priestley 7033b1c8c1SMalcolm Priestley for (r = RATE_1M; r < MAX_RATE; r++) { 7133b1c8c1SMalcolm Priestley if (*rx_rate == rate[r]) 7233b1c8c1SMalcolm Priestley break; 7333b1c8c1SMalcolm Priestley } 7433b1c8c1SMalcolm Priestley 7533b1c8c1SMalcolm Priestley priv->rx_rate = r; 7633b1c8c1SMalcolm Priestley 7733b1c8c1SMalcolm Priestley for (ii = 0; ii < sband->n_bitrates; ii++) { 7833b1c8c1SMalcolm Priestley if (sband->bitrates[ii].hw_value == r) { 7933b1c8c1SMalcolm Priestley rate_idx = ii; 8033b1c8c1SMalcolm Priestley break; 8133b1c8c1SMalcolm Priestley } 8233b1c8c1SMalcolm Priestley } 8333b1c8c1SMalcolm Priestley 8433b1c8c1SMalcolm Priestley if (ii == sband->n_bitrates) { 8533b1c8c1SMalcolm Priestley dev_dbg(&priv->pcid->dev, "Wrong RxRate %x\n", *rx_rate); 8633b1c8c1SMalcolm Priestley return false; 8733b1c8c1SMalcolm Priestley } 8833b1c8c1SMalcolm Priestley 8933b1c8c1SMalcolm Priestley tsf_time = (__le64 *)(skb_data + bytes_received - 12); 9033b1c8c1SMalcolm Priestley sq = skb_data + bytes_received - 4; 9133b1c8c1SMalcolm Priestley new_rsr = skb_data + bytes_received - 3; 9233b1c8c1SMalcolm Priestley rssi = skb_data + bytes_received - 2; 9333b1c8c1SMalcolm Priestley rsr = skb_data + bytes_received - 1; 946d854127SMalcolm Priestley if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) 956d854127SMalcolm Priestley return false; 9633b1c8c1SMalcolm Priestley 9733b1c8c1SMalcolm Priestley RFvRSSITodBm(priv, *rssi, &rx_dbm); 9833b1c8c1SMalcolm Priestley 9933b1c8c1SMalcolm Priestley priv->byBBPreEDRSSI = (u8)rx_dbm + 1; 100f218f40dSMalcolm Priestley priv->uCurrRSSI = *rssi; 10133b1c8c1SMalcolm Priestley 10233b1c8c1SMalcolm Priestley skb_pull(skb, 4); 10333b1c8c1SMalcolm Priestley skb_trim(skb, frame_size); 10433b1c8c1SMalcolm Priestley 10533b1c8c1SMalcolm Priestley rx_status.mactime = le64_to_cpu(*tsf_time); 10633b1c8c1SMalcolm Priestley rx_status.band = hw->conf.chandef.chan->band; 10733b1c8c1SMalcolm Priestley rx_status.signal = rx_dbm; 10833b1c8c1SMalcolm Priestley rx_status.flag = 0; 10933b1c8c1SMalcolm Priestley rx_status.freq = hw->conf.chandef.chan->center_freq; 11033b1c8c1SMalcolm Priestley 1116d854127SMalcolm Priestley if (!(*rsr & RSR_CRCOK)) 1126d854127SMalcolm Priestley rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; 1136d854127SMalcolm Priestley 11433b1c8c1SMalcolm Priestley hdr = (struct ieee80211_hdr *)(skb->data); 11533b1c8c1SMalcolm Priestley fc = hdr->frame_control; 11633b1c8c1SMalcolm Priestley 11733b1c8c1SMalcolm Priestley rx_status.rate_idx = rate_idx; 11833b1c8c1SMalcolm Priestley 11933b1c8c1SMalcolm Priestley if (ieee80211_has_protected(fc)) { 12033b1c8c1SMalcolm Priestley if (priv->byLocalID > REV_ID_VT3253_A1) 1216d854127SMalcolm Priestley rx_status.flag |= RX_FLAG_DECRYPTED; 1226d854127SMalcolm Priestley 1236d854127SMalcolm Priestley /* Drop packet */ 1246d854127SMalcolm Priestley if (!(*new_rsr & NEWRSR_DECRYPTOK)) 1256d854127SMalcolm Priestley return false; 12633b1c8c1SMalcolm Priestley } 12733b1c8c1SMalcolm Priestley 12833b1c8c1SMalcolm Priestley memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); 12933b1c8c1SMalcolm Priestley 13033b1c8c1SMalcolm Priestley ieee80211_rx_irqsafe(priv->hw, skb); 13133b1c8c1SMalcolm Priestley 13233b1c8c1SMalcolm Priestley return true; 13333b1c8c1SMalcolm Priestley } 13433b1c8c1SMalcolm Priestley 13533b1c8c1SMalcolm Priestley bool vnt_receive_frame(struct vnt_private *priv, PSRxDesc curr_rd) 13633b1c8c1SMalcolm Priestley { 13733b1c8c1SMalcolm Priestley PDEVICE_RD_INFO rd_info = curr_rd->pRDInfo; 13833b1c8c1SMalcolm Priestley struct sk_buff *skb; 13933b1c8c1SMalcolm Priestley u16 frame_size; 14033b1c8c1SMalcolm Priestley 14133b1c8c1SMalcolm Priestley skb = rd_info->skb; 14233b1c8c1SMalcolm Priestley 143a1c6dcdaSQuentin Lambert dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma, 144a1c6dcdaSQuentin Lambert priv->rx_buf_sz, DMA_FROM_DEVICE); 14533b1c8c1SMalcolm Priestley 14633b1c8c1SMalcolm Priestley frame_size = le16_to_cpu(curr_rd->m_rd1RD1.wReqCount) 147de1c1862SMalcolm Priestley - le16_to_cpu(curr_rd->rd0.res_count); 14833b1c8c1SMalcolm Priestley 14933b1c8c1SMalcolm Priestley if ((frame_size > 2364) || (frame_size < 33)) { 15033b1c8c1SMalcolm Priestley /* Frame Size error drop this packet.*/ 15133b1c8c1SMalcolm Priestley dev_dbg(&priv->pcid->dev, "Wrong frame size %d\n", frame_size); 15233b1c8c1SMalcolm Priestley dev_kfree_skb_irq(skb); 15333b1c8c1SMalcolm Priestley return true; 15433b1c8c1SMalcolm Priestley } 15533b1c8c1SMalcolm Priestley 15633b1c8c1SMalcolm Priestley if (vnt_rx_data(priv, skb, frame_size)) 15733b1c8c1SMalcolm Priestley return true; 15833b1c8c1SMalcolm Priestley 15933b1c8c1SMalcolm Priestley dev_kfree_skb_irq(skb); 16033b1c8c1SMalcolm Priestley 16133b1c8c1SMalcolm Priestley return true; 16233b1c8c1SMalcolm Priestley } 163