Merge branch 'topic/hda' into for-linus
[linux-2.6] / drivers / staging / rt2860 / common / 2860_rtmp_init.c
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         2860_rtmp_init.c
29
30         Abstract:
31         Miniport generic portion header file
32
33         Revision History:
34         Who         When          What
35         --------    ----------    ----------------------------------------------
36         Paul Lin    2002-08-01    created
37     John Chang  2004-08-20    RT2561/2661 use scatter-gather scheme
38     Jan Lee  2006-09-15    RT2860. Change for 802.11n , EEPROM, Led, BA, HT.
39 */
40 #include "../rt_config.h"
41
42
43
44
45 /*
46         ========================================================================
47
48         Routine Description:
49                 Allocate DMA memory blocks for send, receive
50
51         Arguments:
52                 Adapter         Pointer to our adapter
53
54         Return Value:
55                 NDIS_STATUS_SUCCESS
56                 NDIS_STATUS_FAILURE
57                 NDIS_STATUS_RESOURCES
58
59         IRQL = PASSIVE_LEVEL
60
61         Note:
62
63         ========================================================================
64 */
65 NDIS_STATUS     RTMPAllocTxRxRingMemory(
66         IN      PRTMP_ADAPTER   pAd)
67 {
68         NDIS_STATUS             Status = NDIS_STATUS_SUCCESS;
69         ULONG                   RingBasePaHigh;
70         ULONG                   RingBasePaLow;
71         PVOID                   RingBaseVa;
72         INT                             index, num;
73         PTXD_STRUC              pTxD;
74         PRXD_STRUC              pRxD;
75         ULONG                   ErrorValue = 0;
76         PRTMP_TX_RING   pTxRing;
77         PRTMP_DMABUF    pDmaBuf;
78         PNDIS_PACKET    pPacket;
79
80         DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
81         do
82         {
83                 //
84                 // Allocate all ring descriptors, include TxD, RxD, MgmtD.
85                 // Although each size is different, to prevent cacheline and alignment
86                 // issue, I intentional set them all to 64 bytes.
87                 //
88                 for (num=0; num<NUM_OF_TX_RING; num++)
89                 {
90                         ULONG  BufBasePaHigh;
91                         ULONG  BufBasePaLow;
92                         PVOID  BufBaseVa;
93
94                         //
95                         // Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA)
96                         //
97                         pAd->TxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE;
98                         RTMP_AllocateTxDescMemory(
99                                 pAd,
100                                 num,
101                                 pAd->TxDescRing[num].AllocSize,
102                                 FALSE,
103                                 &pAd->TxDescRing[num].AllocVa,
104                                 &pAd->TxDescRing[num].AllocPa);
105
106                         if (pAd->TxDescRing[num].AllocVa == NULL)
107                         {
108                                 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
109                                 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
110                                 Status = NDIS_STATUS_RESOURCES;
111                                 break;
112                         }
113
114                         // Zero init this memory block
115                         NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize);
116
117                         // Save PA & VA for further operation
118                         RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa);
119                         RingBasePaLow  = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa);
120                         RingBaseVa     = pAd->TxDescRing[num].AllocVa;
121
122                         //
123                         // Allocate all 1st TXBuf's memory for this TxRing
124                         //
125                         pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE;
126                         RTMP_AllocateFirstTxBuffer(
127                                 pAd,
128                                 num,
129                                 pAd->TxBufSpace[num].AllocSize,
130                                 FALSE,
131                                 &pAd->TxBufSpace[num].AllocVa,
132                                 &pAd->TxBufSpace[num].AllocPa);
133
134                         if (pAd->TxBufSpace[num].AllocVa == NULL)
135                         {
136                                 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
137                                 DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
138                                 Status = NDIS_STATUS_RESOURCES;
139                                 break;
140                         }
141
142                         // Zero init this memory block
143                         NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize);
144
145                         // Save PA & VA for further operation
146                         BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa);
147                         BufBasePaLow  = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa);
148                         BufBaseVa     = pAd->TxBufSpace[num].AllocVa;
149
150                         //
151                         // Initialize Tx Ring Descriptor and associated buffer memory
152                         //
153                         pTxRing = &pAd->TxRing[num];
154                         for (index = 0; index < TX_RING_SIZE; index++)
155                         {
156                                 pTxRing->Cell[index].pNdisPacket = NULL;
157                                 pTxRing->Cell[index].pNextNdisPacket = NULL;
158                                 // Init Tx Ring Size, Va, Pa variables
159                                 pTxRing->Cell[index].AllocSize = TXD_SIZE;
160                                 pTxRing->Cell[index].AllocVa = RingBaseVa;
161                                 RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh);
162                                 RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow);
163
164                                 // Setup Tx Buffer size & address. only 802.11 header will store in this space
165                                 pDmaBuf = &pTxRing->Cell[index].DmaBuf;
166                                 pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE;
167                                 pDmaBuf->AllocVa = BufBaseVa;
168                                 RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh);
169                                 RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow);
170
171                                 // link the pre-allocated TxBuf to TXD
172                                 pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa;
173                                 pTxD->SDPtr0 = BufBasePaLow;
174                                 // advance to next ring descriptor address
175                                 pTxD->DMADONE = 1;
176 #ifdef RT_BIG_ENDIAN
177                                 RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
178 #endif
179                                 RingBasePaLow += TXD_SIZE;
180                                 RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
181
182                                 // advance to next TxBuf address
183                                 BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE;
184                                 BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE;
185                         }
186                         DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index));
187                 }
188                 if (Status == NDIS_STATUS_RESOURCES)
189                         break;
190
191                 //
192                 // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler
193                 //
194                 pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE;
195                 RTMP_AllocateMgmtDescMemory(
196                         pAd,
197                         pAd->MgmtDescRing.AllocSize,
198                         FALSE,
199                         &pAd->MgmtDescRing.AllocVa,
200                         &pAd->MgmtDescRing.AllocPa);
201
202                 if (pAd->MgmtDescRing.AllocVa == NULL)
203                 {
204                         ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
205                         DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
206                         Status = NDIS_STATUS_RESOURCES;
207                         break;
208                 }
209
210                 // Zero init this memory block
211                 NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
212
213                 // Save PA & VA for further operation
214                 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa);
215                 RingBasePaLow  = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa);
216                 RingBaseVa     = pAd->MgmtDescRing.AllocVa;
217
218                 //
219                 // Initialize MGMT Ring and associated buffer memory
220                 //
221                 for (index = 0; index < MGMT_RING_SIZE; index++)
222                 {
223                         pAd->MgmtRing.Cell[index].pNdisPacket = NULL;
224                         pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL;
225                         // Init MGMT Ring Size, Va, Pa variables
226                         pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE;
227                         pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa;
228                         RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh);
229                         RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow);
230
231                         // Offset to next ring descriptor address
232                         RingBasePaLow += TXD_SIZE;
233                         RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
234
235                         // link the pre-allocated TxBuf to TXD
236                         pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa;
237                         pTxD->DMADONE = 1;
238
239 #ifdef RT_BIG_ENDIAN
240                         RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
241 #endif
242                         // no pre-allocated buffer required in MgmtRing for scatter-gather case
243                 }
244                 DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index));
245
246                 //
247                 // Allocate RX ring descriptor's memory except Tx ring which allocated eariler
248                 //
249                 pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE;
250                 RTMP_AllocateRxDescMemory(
251                         pAd,
252                         pAd->RxDescRing.AllocSize,
253                         FALSE,
254                         &pAd->RxDescRing.AllocVa,
255                         &pAd->RxDescRing.AllocPa);
256
257                 if (pAd->RxDescRing.AllocVa == NULL)
258                 {
259                         ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
260                         DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
261                         Status = NDIS_STATUS_RESOURCES;
262                         break;
263                 }
264
265                 // Zero init this memory block
266                 NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize);
267
268
269                 printk("RX DESC %p  size = %ld\n", pAd->RxDescRing.AllocVa,
270                                         pAd->RxDescRing.AllocSize);
271
272                 // Save PA & VA for further operation
273                 RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa);
274                 RingBasePaLow  = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa);
275                 RingBaseVa     = pAd->RxDescRing.AllocVa;
276
277                 //
278                 // Initialize Rx Ring and associated buffer memory
279                 //
280                 for (index = 0; index < RX_RING_SIZE; index++)
281                 {
282                         // Init RX Ring Size, Va, Pa variables
283                         pAd->RxRing.Cell[index].AllocSize = RXD_SIZE;
284                         pAd->RxRing.Cell[index].AllocVa = RingBaseVa;
285                         RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh);
286                         RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow);
287
288                         // Offset to next ring descriptor address
289                         RingBasePaLow += RXD_SIZE;
290                         RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE;
291
292                         // Setup Rx associated Buffer size & allocate share memory
293                         pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf;
294                         pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE;
295                         pPacket = RTMP_AllocateRxPacketBuffer(
296                                 pAd,
297                                 pDmaBuf->AllocSize,
298                                 FALSE,
299                                 &pDmaBuf->AllocVa,
300                                 &pDmaBuf->AllocPa);
301
302                         /* keep allocated rx packet */
303                         pAd->RxRing.Cell[index].pNdisPacket = pPacket;
304
305                         // Error handling
306                         if (pDmaBuf->AllocVa == NULL)
307                         {
308                                 ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
309                                 DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n"));
310                                 Status = NDIS_STATUS_RESOURCES;
311                                 break;
312                         }
313
314                         // Zero init this memory block
315                         NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize);
316
317                         // Write RxD buffer address & allocated buffer length
318                         pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa;
319                         pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa);
320                         pRxD->DDONE = 0;
321
322 #ifdef RT_BIG_ENDIAN
323                         RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
324 #endif
325                 }
326
327                 DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index));
328
329         }       while (FALSE);
330
331
332         NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
333         pAd->FragFrame.pFragPacket =  RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
334
335         if (pAd->FragFrame.pFragPacket == NULL)
336         {
337                 Status = NDIS_STATUS_RESOURCES;
338         }
339
340         if (Status != NDIS_STATUS_SUCCESS)
341         {
342                 // Log error inforamtion
343                 NdisWriteErrorLogEntry(
344                         pAd->AdapterHandle,
345                         NDIS_ERROR_CODE_OUT_OF_RESOURCES,
346                         1,
347                         ErrorValue);
348         }
349
350         DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
351         return Status;
352 }
353
354
355 /*
356         ========================================================================
357
358         Routine Description:
359                 Initialize transmit data structures
360
361         Arguments:
362                 Adapter                                         Pointer to our adapter
363
364         Return Value:
365                 None
366
367         IRQL = PASSIVE_LEVEL
368
369         Note:
370                 Initialize all transmit releated private buffer, include those define
371                 in RTMP_ADAPTER structure and all private data structures.
372
373         ========================================================================
374 */
375 VOID    NICInitTxRxRingAndBacklogQueue(
376         IN      PRTMP_ADAPTER   pAd)
377 {
378         //WPDMA_GLO_CFG_STRUC   GloCfg;
379         int i;
380
381         DBGPRINT(RT_DEBUG_TRACE, ("<--> NICInitTxRxRingAndBacklogQueue\n"));
382
383         // Initialize all transmit related software queues
384         InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BE]);
385         InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BK]);
386         InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VI]);
387         InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VO]);
388         InitializeQueueHeader(&pAd->TxSwQueue[QID_HCCA]);
389
390         // Init RX Ring index pointer
391         pAd->RxRing.RxSwReadIdx = 0;
392         pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1;
393
394         // Init TX rings index pointer
395                 for (i=0; i<NUM_OF_TX_RING; i++)
396                 {
397                         pAd->TxRing[i].TxSwFreeIdx = 0;
398                         pAd->TxRing[i].TxCpuIdx = 0;
399                 }
400
401         // init MGMT ring index pointer
402         pAd->MgmtRing.TxSwFreeIdx = 0;
403         pAd->MgmtRing.TxCpuIdx = 0;
404
405         pAd->PrivateInfo.TxRingFullCnt       = 0;
406 }
407
408
409 /*
410         ========================================================================
411
412         Routine Description:
413                 Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero.
414
415         Arguments:
416                 Adapter                                         Pointer to our adapter
417
418         Return Value:
419                 None
420
421         IRQL = PASSIVE_LEVEL
422         IRQL = DISPATCH_LEVEL
423
424         Note:
425                 Reset NIC to initial state AS IS system boot up time.
426
427         ========================================================================
428 */
429 VOID    RTMPRingCleanUp(
430         IN      PRTMP_ADAPTER   pAd,
431         IN      UCHAR                   RingType)
432 {
433         PTXD_STRUC              pTxD;
434         PRXD_STRUC              pRxD;
435         PQUEUE_ENTRY    pEntry;
436         PNDIS_PACKET    pPacket;
437         int                             i;
438         PRTMP_TX_RING   pTxRing;
439         unsigned long   IrqFlags;
440
441         DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount));
442         switch (RingType)
443         {
444                 case QID_AC_BK:
445                 case QID_AC_BE:
446                 case QID_AC_VI:
447                 case QID_AC_VO:
448                 case QID_HCCA:
449                         RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
450                         pTxRing = &pAd->TxRing[RingType];
451
452                         // We have to clean all descriptors in case some error happened with reset
453                         for (i=0; i<TX_RING_SIZE; i++) // We have to scan all TX ring
454                         {
455                                 pTxD  = (PTXD_STRUC) pTxRing->Cell[i].AllocVa;
456
457                                 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket;
458                                 // release scatter-and-gather NDIS_PACKET
459                                 if (pPacket)
460                                 {
461                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
462                                         pTxRing->Cell[i].pNdisPacket = NULL;
463                                 }
464
465                                 pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket;
466                                 // release scatter-and-gather NDIS_PACKET
467                                 if (pPacket)
468                                 {
469                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
470                                         pTxRing->Cell[i].pNextNdisPacket = NULL;
471                                 }
472                         }
473
474                         RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx);
475                         pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx;
476                         pTxRing->TxCpuIdx = pTxRing->TxDmaIdx;
477                         RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx);
478
479                         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
480                         RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
481                         while (pAd->TxSwQueue[RingType].Head != NULL)
482                         {
483                                 pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]);
484                                 pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
485                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
486                                 DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n"));
487                         }
488                         RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
489                         break;
490
491                 case QID_MGMT:
492                         // We have to clean all descriptors in case some error happened with reset
493                         NdisAcquireSpinLock(&pAd->MgmtRingLock);
494
495                         for (i=0; i<MGMT_RING_SIZE; i++)
496                         {
497                                 pTxD  = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa;
498
499                                 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket;
500                                 // rlease scatter-and-gather NDIS_PACKET
501                                 if (pPacket)
502                                 {
503                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
504                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
505                                 }
506                                 pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
507
508                                 pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket;
509                                 // release scatter-and-gather NDIS_PACKET
510                                 if (pPacket)
511                                 {
512                                         PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
513                                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
514                                 }
515                                 pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL;
516
517                         }
518
519                         RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx);
520                         pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx;
521                         pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx;
522                         RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
523
524                         NdisReleaseSpinLock(&pAd->MgmtRingLock);
525                         pAd->RalinkCounters.MgmtRingFullCount = 0;
526                         break;
527
528                 case QID_RX:
529                         // We have to clean all descriptors in case some error happened with reset
530                         NdisAcquireSpinLock(&pAd->RxRingLock);
531
532                         for (i=0; i<RX_RING_SIZE; i++)
533                         {
534                                 pRxD  = (PRXD_STRUC) pAd->RxRing.Cell[i].AllocVa;
535                                 pRxD->DDONE = 0 ;
536                         }
537
538                         RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx);
539                         pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx;
540                         pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1));
541                         RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
542
543                         NdisReleaseSpinLock(&pAd->RxRingLock);
544                         break;
545
546                 default:
547                         break;
548         }
549 }
550
551
552 NDIS_STATUS AdapterBlockAllocateMemory(
553         IN PVOID        handle,
554         OUT     PVOID   *ppAd)
555 {
556         PPCI_DEV pci_dev;
557         dma_addr_t      *phy_addr;
558         POS_COOKIE pObj = (POS_COOKIE) handle;
559
560         pci_dev = pObj->pci_dev;
561         phy_addr = &pObj->pAd_pa;
562
563         *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr);
564
565         if (*ppAd)
566         {
567                 NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER));
568                 ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle;
569                 return (NDIS_STATUS_SUCCESS);
570         } else {
571                 return (NDIS_STATUS_FAILURE);
572         }
573 }
574
575
576 void RTMP_AllocateTxDescMemory(
577         IN      PRTMP_ADAPTER pAd,
578         IN      UINT    Index,
579         IN      ULONG   Length,
580         IN      BOOLEAN Cached,
581         OUT     PVOID   *VirtualAddress,
582         OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
583 {
584         POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
585
586         *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
587
588 }
589
590 void RTMP_AllocateMgmtDescMemory(
591         IN      PRTMP_ADAPTER pAd,
592         IN      ULONG   Length,
593         IN      BOOLEAN Cached,
594         OUT     PVOID   *VirtualAddress,
595         OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
596 {
597         POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
598
599         *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
600
601 }
602
603 void RTMP_AllocateRxDescMemory(
604         IN      PRTMP_ADAPTER pAd,
605         IN      ULONG   Length,
606         IN      BOOLEAN Cached,
607         OUT     PVOID   *VirtualAddress,
608         OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
609 {
610         POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
611
612         *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
613
614 }
615
616 void RTMP_FreeRxDescMemory(
617         IN      PRTMP_ADAPTER pAd,
618         IN      ULONG   Length,
619         IN      PVOID   VirtualAddress,
620         IN      NDIS_PHYSICAL_ADDRESS PhysicalAddress)
621 {
622         POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
623
624         PCI_FREE_CONSISTENT(pObj->pci_dev, Length, VirtualAddress, PhysicalAddress);
625 }
626
627
628 void RTMP_AllocateFirstTxBuffer(
629         IN      PRTMP_ADAPTER pAd,
630         IN      UINT    Index,
631         IN      ULONG   Length,
632         IN      BOOLEAN Cached,
633         OUT     PVOID   *VirtualAddress,
634         OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
635 {
636         POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
637
638         *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
639 }
640
641 /*
642  * FUNCTION: Allocate a common buffer for DMA
643  * ARGUMENTS:
644  *     AdapterHandle:  AdapterHandle
645  *     Length:  Number of bytes to allocate
646  *     Cached:  Whether or not the memory can be cached
647  *     VirtualAddress:  Pointer to memory is returned here
648  *     PhysicalAddress:  Physical address corresponding to virtual address
649  */
650
651 void RTMP_AllocateSharedMemory(
652         IN      PRTMP_ADAPTER pAd,
653         IN      ULONG   Length,
654         IN      BOOLEAN Cached,
655         OUT     PVOID   *VirtualAddress,
656         OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
657 {
658         POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
659
660         *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
661 }
662
663 VOID RTMPFreeTxRxRingMemory(
664     IN  PRTMP_ADAPTER   pAd)
665 {
666         int index, num , j;
667         PRTMP_TX_RING pTxRing;
668         PTXD_STRUC        pTxD;
669         PNDIS_PACKET  pPacket;
670         unsigned int  IrqFlags;
671
672         POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie;
673
674         DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n"));
675
676         // Free TxSwQueue Packet
677         for (index=0; index <NUM_OF_TX_RING; index++)
678         {
679                 PQUEUE_ENTRY pEntry;
680                 PNDIS_PACKET pPacket;
681                 PQUEUE_HEADER   pQueue;
682
683                 RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
684                 pQueue = &pAd->TxSwQueue[index];
685                 while (pQueue->Head)
686                 {
687                         pEntry = RemoveHeadQueue(pQueue);
688                         pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
689                         RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
690                 }
691                 RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
692         }
693
694         // Free Tx Ring Packet
695         for (index=0;index< NUM_OF_TX_RING;index++)
696         {
697                 pTxRing = &pAd->TxRing[index];
698
699                 for (j=0; j< TX_RING_SIZE; j++)
700                 {
701                         pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa);
702                         pPacket = pTxRing->Cell[j].pNdisPacket;
703
704                         if (pPacket)
705                         {
706                 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
707                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
708                         }
709                         //Always assign pNdisPacket as NULL after clear
710                         pTxRing->Cell[j].pNdisPacket = NULL;
711
712                         pPacket = pTxRing->Cell[j].pNextNdisPacket;
713
714                         if (pPacket)
715                         {
716                 PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
717                                 RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
718                         }
719                         //Always assign pNextNdisPacket as NULL after clear
720                         pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
721
722                 }
723         }
724
725         for (index = RX_RING_SIZE - 1 ; index >= 0; index--)
726         {
727                 if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket))
728                 {
729                         PCI_UNMAP_SINGLE(pObj->pci_dev, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
730                         RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS);
731                 }
732         }
733         NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB));
734
735         if (pAd->RxDescRing.AllocVa)
736     {
737         PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa);
738     }
739     NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF));
740
741         if (pAd->MgmtDescRing.AllocVa)
742         {
743                 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa);
744         }
745         NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF));
746
747         for (num = 0; num < NUM_OF_TX_RING; num++)
748         {
749         if (pAd->TxBufSpace[num].AllocVa)
750             {
751                 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxBufSpace[num].AllocSize, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa);
752             }
753             NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF));
754
755         if (pAd->TxDescRing[num].AllocVa)
756             {
757                 PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa);
758             }
759             NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF));
760         }
761
762         if (pAd->FragFrame.pFragPacket)
763                 RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
764
765         DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n"));
766 }
767
768
769 /*
770  * FUNCTION: Allocate a packet buffer for DMA
771  * ARGUMENTS:
772  *     AdapterHandle:  AdapterHandle
773  *     Length:  Number of bytes to allocate
774  *     Cached:  Whether or not the memory can be cached
775  *     VirtualAddress:  Pointer to memory is returned here
776  *     PhysicalAddress:  Physical address corresponding to virtual address
777  * Notes:
778  *     Cached is ignored: always cached memory
779  */
780 PNDIS_PACKET RTMP_AllocateRxPacketBuffer(
781         IN      PRTMP_ADAPTER pAd,
782         IN      ULONG   Length,
783         IN      BOOLEAN Cached,
784         OUT     PVOID   *VirtualAddress,
785         OUT     PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
786 {
787         PNDIS_PACKET pkt;
788
789         pkt = RTPKT_TO_OSPKT(DEV_ALLOC_SKB(Length));
790
791         if (pkt == NULL) {
792                 DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length));
793         }
794
795         if (pkt) {
796                 RTMP_SET_PACKET_SOURCE(pkt, PKTSRC_NDIS);
797                 *VirtualAddress = (PVOID) RTPKT_TO_OSPKT(pkt)->data;
798                 *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE);
799         } else {
800                 *VirtualAddress = (PVOID) NULL;
801                 *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL;
802         }
803
804         return (PNDIS_PACKET) pkt;
805 }
806
807
808 VOID Invalid_Remaining_Packet(
809         IN      PRTMP_ADAPTER pAd,
810         IN       ULONG VirtualAddress)
811 {
812         NDIS_PHYSICAL_ADDRESS PhysicalAddress;
813
814         PhysicalAddress = PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress+1600), RX_BUFFER_NORMSIZE-1600, -1, PCI_DMA_FROMDEVICE);
815 }
816
817 PNDIS_PACKET GetPacketFromRxRing(
818         IN              PRTMP_ADAPTER   pAd,
819         OUT             PRT28XX_RXD_STRUC       pSaveRxD,
820         OUT             BOOLEAN                 *pbReschedule,
821         IN OUT  UINT32                  *pRxPending)
822 {
823         PRXD_STRUC                              pRxD;
824 #ifdef RT_BIG_ENDIAN
825         PRXD_STRUC                              pDestRxD;
826         RXD_STRUC                               RxD;
827 #endif
828         PNDIS_PACKET                    pRxPacket = NULL;
829         PNDIS_PACKET                    pNewPacket;
830         PVOID                                   AllocVa;
831         NDIS_PHYSICAL_ADDRESS   AllocPa;
832         BOOLEAN                                 bReschedule = FALSE;
833
834         RTMP_SEM_LOCK(&pAd->RxRingLock);
835
836         if (*pRxPending == 0)
837         {
838                 // Get how may packets had been received
839                 RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx);
840
841                 if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx)
842                 {
843                         // no more rx packets
844                         bReschedule = FALSE;
845                         goto done;
846                 }
847
848                 // get rx pending count
849                 if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx)
850                         *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx;
851                 else
852                         *pRxPending     = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx;
853
854         }
855
856 #ifdef RT_BIG_ENDIAN
857         pDestRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa;
858         RxD = *pDestRxD;
859         pRxD = &RxD;
860         RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
861 #else
862         // Point to Rx indexed rx ring descriptor
863         pRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa;
864 #endif
865
866         if (pRxD->DDONE == 0)
867         {
868                 *pRxPending = 0;
869                 // DMAIndx had done but DDONE bit not ready
870                 bReschedule = TRUE;
871                 goto done;
872         }
873
874
875         // return rx descriptor
876         NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE);
877
878         pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa);
879
880         if (pNewPacket)
881         {
882                 // unmap the rx buffer
883                 PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa,
884                                          pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
885                 pRxPacket = pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket;
886
887                 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize      = RX_BUFFER_AGGRESIZE;
888                 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket           = (PNDIS_PACKET) pNewPacket;
889                 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocVa        = AllocVa;
890                 pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa        = AllocPa;
891                 /* update SDP0 to new buffer of rx packet */
892                 pRxD->SDP0 = AllocPa;
893         }
894         else
895         {
896                 //printk("No Rx Buffer\n");
897                 pRxPacket = NULL;
898                 bReschedule = TRUE;
899         }
900
901         pRxD->DDONE = 0;
902
903         // had handled one rx packet
904         *pRxPending = *pRxPending - 1;
905
906         // update rx descriptor and kick rx
907 #ifdef RT_BIG_ENDIAN
908         RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
909         WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD);
910 #endif
911         INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE);
912
913         pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1);
914         RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
915
916 done:
917         RTMP_SEM_UNLOCK(&pAd->RxRingLock);
918         *pbReschedule = bReschedule;
919         return pRxPacket;
920 }
921 /* End of 2860_rtmp_init.c */
922