xref: /openbmc/linux/drivers/staging/vt6655/dpc.c (revision de1c1862)
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