1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26 
27 	Module Name:
28 	rtusb_data.c
29 
30 	Abstract:
31 	Ralink USB driver Tx/Rx functions.
32 
33 	Revision History:
34 	Who         When          What
35 	--------    ----------    ----------------------------------------------
36 	Jan            03-25-2006    created
37 
38 */
39 
40 #ifdef RTMP_MAC_USB
41 
42 #include "../rt_config.h"
43 
44 extern u8 Phy11BGNextRateUpward[];	/* defined in mlme.c */
45 extern u8 EpToQueue[];
46 
REPORT_AMSDU_FRAMES_TO_LLC(struct rt_rtmp_adapter * pAd,u8 * pData,unsigned long DataSize)47 void REPORT_AMSDU_FRAMES_TO_LLC(struct rt_rtmp_adapter *pAd,
48 				u8 *pData, unsigned long DataSize)
49 {
50 	void *pPacket;
51 	u32 nMSDU;
52 	struct sk_buff *pSkb;
53 
54 	nMSDU = 0;
55 	/* allocate a rx packet */
56 	pSkb = dev_alloc_skb(RX_BUFFER_AGGRESIZE);
57 	pPacket = (void *)OSPKT_TO_RTPKT(pSkb);
58 	if (pSkb) {
59 
60 		/* convert 802.11 to 802.3 packet */
61 		pSkb->dev = get_netdev_from_bssid(pAd, BSS0);
62 		RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
63 		deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
64 	} else {
65 		DBGPRINT(RT_DEBUG_ERROR, ("Can't allocate skb\n"));
66 	}
67 }
68 
69 /*
70 	========================================================================
71 
72 	Routine	Description:
73 		This subroutine will scan through releative ring descriptor to find
74 		out available free ring descriptor and compare with request size.
75 
76 	Arguments:
77 		pAd	Pointer	to our adapter
78 		RingType	Selected Ring
79 
80 	Return Value:
81 		NDIS_STATUS_FAILURE		Not enough free descriptor
82 		NDIS_STATUS_SUCCESS		Enough free descriptor
83 
84 	Note:
85 
86 	========================================================================
87 */
RTUSBFreeDescriptorRequest(struct rt_rtmp_adapter * pAd,u8 BulkOutPipeId,u32 NumberRequired)88 int RTUSBFreeDescriptorRequest(struct rt_rtmp_adapter *pAd,
89 				       u8 BulkOutPipeId,
90 				       u32 NumberRequired)
91 {
92 /*      u8                   FreeNumber = 0; */
93 /*      u32                    Index; */
94 	int Status = NDIS_STATUS_FAILURE;
95 	unsigned long IrqFlags;
96 	struct rt_ht_tx_context *pHTTXContext;
97 
98 	pHTTXContext = &pAd->TxContext[BulkOutPipeId];
99 	RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
100 	if ((pHTTXContext->CurWritePosition < pHTTXContext->NextBulkOutPosition)
101 	    &&
102 	    ((pHTTXContext->CurWritePosition + NumberRequired +
103 	      LOCAL_TXBUF_SIZE) > pHTTXContext->NextBulkOutPosition)) {
104 
105 		RTUSB_SET_BULK_FLAG(pAd,
106 				    (fRTUSB_BULK_OUT_DATA_NORMAL <<
107 				     BulkOutPipeId));
108 	} else if ((pHTTXContext->CurWritePosition == 8)
109 		   && (pHTTXContext->NextBulkOutPosition <
110 		       (NumberRequired + LOCAL_TXBUF_SIZE))) {
111 		RTUSB_SET_BULK_FLAG(pAd,
112 				    (fRTUSB_BULK_OUT_DATA_NORMAL <<
113 				     BulkOutPipeId));
114 	} else if (pHTTXContext->bCurWriting == TRUE) {
115 		DBGPRINT(RT_DEBUG_TRACE,
116 			 ("RTUSBFreeD c3 --> QueIdx=%d, CWPos=%ld, NBOutPos=%ld!\n",
117 			  BulkOutPipeId, pHTTXContext->CurWritePosition,
118 			  pHTTXContext->NextBulkOutPosition));
119 		RTUSB_SET_BULK_FLAG(pAd,
120 				    (fRTUSB_BULK_OUT_DATA_NORMAL <<
121 				     BulkOutPipeId));
122 	} else {
123 		Status = NDIS_STATUS_SUCCESS;
124 	}
125 	RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
126 
127 	return Status;
128 }
129 
RTUSBFreeDescriptorRelease(struct rt_rtmp_adapter * pAd,u8 BulkOutPipeId)130 int RTUSBFreeDescriptorRelease(struct rt_rtmp_adapter *pAd,
131 				       u8 BulkOutPipeId)
132 {
133 	unsigned long IrqFlags;
134 	struct rt_ht_tx_context *pHTTXContext;
135 
136 	pHTTXContext = &pAd->TxContext[BulkOutPipeId];
137 	RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
138 	pHTTXContext->bCurWriting = FALSE;
139 	RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
140 
141 	return NDIS_STATUS_SUCCESS;
142 }
143 
RTUSBNeedQueueBackForAgg(struct rt_rtmp_adapter * pAd,u8 BulkOutPipeId)144 BOOLEAN RTUSBNeedQueueBackForAgg(struct rt_rtmp_adapter *pAd, u8 BulkOutPipeId)
145 {
146 	unsigned long IrqFlags;
147 	struct rt_ht_tx_context *pHTTXContext;
148 	BOOLEAN needQueBack = FALSE;
149 
150 	pHTTXContext = &pAd->TxContext[BulkOutPipeId];
151 
152 	RTMP_IRQ_LOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
153 	if ((pHTTXContext->IRPPending ==
154 	     TRUE) /*&& (pAd->TxSwQueue[BulkOutPipeId].Number == 0) */) {
155 		if ((pHTTXContext->CurWritePosition <
156 		     pHTTXContext->ENextBulkOutPosition)
157 		    &&
158 		    (((pHTTXContext->ENextBulkOutPosition +
159 		       MAX_AGGREGATION_SIZE) < MAX_TXBULK_LIMIT)
160 		     || (pHTTXContext->CurWritePosition >
161 			 MAX_AGGREGATION_SIZE))) {
162 			needQueBack = TRUE;
163 		} else
164 		    if ((pHTTXContext->CurWritePosition >
165 			 pHTTXContext->ENextBulkOutPosition)
166 			&&
167 			((pHTTXContext->ENextBulkOutPosition +
168 			  MAX_AGGREGATION_SIZE) <
169 			 pHTTXContext->CurWritePosition)) {
170 			needQueBack = TRUE;
171 		}
172 	}
173 	RTMP_IRQ_UNLOCK(&pAd->TxContextQueueLock[BulkOutPipeId], IrqFlags);
174 
175 	return needQueBack;
176 
177 }
178 
179 /*
180 	========================================================================
181 
182 	Routine Description:
183 
184 	Arguments:
185 
186 	Return Value:
187 
188 	IRQL =
189 
190 	Note:
191 
192 	========================================================================
193 */
RTUSBRejectPendingPackets(struct rt_rtmp_adapter * pAd)194 void RTUSBRejectPendingPackets(struct rt_rtmp_adapter *pAd)
195 {
196 	u8 Index;
197 	struct rt_queue_entry *pEntry;
198 	void *pPacket;
199 	struct rt_queue_header *pQueue;
200 
201 	for (Index = 0; Index < 4; Index++) {
202 		NdisAcquireSpinLock(&pAd->TxSwQueueLock[Index]);
203 		while (pAd->TxSwQueue[Index].Head != NULL) {
204 			pQueue = (struct rt_queue_header *)&(pAd->TxSwQueue[Index]);
205 			pEntry = RemoveHeadQueue(pQueue);
206 			pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
207 			RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
208 		}
209 		NdisReleaseSpinLock(&pAd->TxSwQueueLock[Index]);
210 
211 	}
212 
213 }
214 
215 /*
216 	========================================================================
217 
218 	Routine	Description:
219 		Calculates the duration which is required to transmit out frames
220 	with given size and specified rate.
221 
222 	Arguments:
223 		pTxD		Pointer to transmit descriptor
224 		Ack			Setting for Ack requirement bit
225 		Fragment	Setting for Fragment bit
226 		RetryMode	Setting for retry mode
227 		Ifs			Setting for IFS gap
228 		Rate		Setting for transmit rate
229 		Service		Setting for service
230 		Length		Frame length
231 		TxPreamble  Short or Long preamble when using CCK rates
232 		QueIdx - 0-3, according to 802.11e/d4.4 June/2003
233 
234 	Return Value:
235 		None
236 
237 	IRQL = PASSIVE_LEVEL
238 	IRQL = DISPATCH_LEVEL
239 
240 	========================================================================
241 */
242 
RTMPWriteTxInfo(struct rt_rtmp_adapter * pAd,struct rt_txinfo * pTxInfo,u16 USBDMApktLen,IN BOOLEAN bWiv,u8 QueueSel,u8 NextValid,u8 TxBurst)243 void RTMPWriteTxInfo(struct rt_rtmp_adapter *pAd,
244 		     struct rt_txinfo *pTxInfo,
245 		     u16 USBDMApktLen,
246 		     IN BOOLEAN bWiv,
247 		     u8 QueueSel, u8 NextValid, u8 TxBurst)
248 {
249 	pTxInfo->USBDMATxPktLen = USBDMApktLen;
250 	pTxInfo->QSEL = QueueSel;
251 	if (QueueSel != FIFO_EDCA)
252 		DBGPRINT(RT_DEBUG_TRACE,
253 			 ("====> QueueSel != FIFO_EDCA<============\n"));
254 	pTxInfo->USBDMANextVLD = FALSE;	/*NextValid;  // Need to check with Jan about this. */
255 	pTxInfo->USBDMATxburst = TxBurst;
256 	pTxInfo->WIV = bWiv;
257 	pTxInfo->SwUseLastRound = 0;
258 	pTxInfo->rsv = 0;
259 	pTxInfo->rsv2 = 0;
260 }
261 
262 #endif /* RTMP_MAC_USB // */
263