]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/rt_pci_rbus.c
Staging: rt28xx: Make PCI_{MAP,UNMAP}_SINGLE type-safe
[net-next-2.6.git] / drivers / staging / rt2860 / rt_pci_rbus.c
CommitLineData
ca97b838
BZ
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 rt_pci_rbus.c
29
30 Abstract:
31 Create and register network interface.
32
33 Revision History:
34 Who When What
35 -------- ---------- ----------------------------------------------
36*/
37
38#include "rt_config.h"
39#include <linux/pci.h>
40
41IRQ_HANDLE_TYPE rt2860_interrupt(int irq, void *dev_instance);
42
43static void rx_done_tasklet(unsigned long data);
44static void mgmt_dma_done_tasklet(unsigned long data);
45static void ac0_dma_done_tasklet(unsigned long data);
46static void ac1_dma_done_tasklet(unsigned long data);
47static void ac2_dma_done_tasklet(unsigned long data);
48static void ac3_dma_done_tasklet(unsigned long data);
49static void fifo_statistic_full_tasklet(unsigned long data);
50
ca97b838
BZ
51/*---------------------------------------------------------------------*/
52/* Symbol & Macro Definitions */
53/*---------------------------------------------------------------------*/
9f548a2a
BZ
54#define RT2860_INT_RX_DLY (1<<0) /* bit 0 */
55#define RT2860_INT_TX_DLY (1<<1) /* bit 1 */
56#define RT2860_INT_RX_DONE (1<<2) /* bit 2 */
57#define RT2860_INT_AC0_DMA_DONE (1<<3) /* bit 3 */
58#define RT2860_INT_AC1_DMA_DONE (1<<4) /* bit 4 */
59#define RT2860_INT_AC2_DMA_DONE (1<<5) /* bit 5 */
60#define RT2860_INT_AC3_DMA_DONE (1<<6) /* bit 6 */
61#define RT2860_INT_HCCA_DMA_DONE (1<<7) /* bit 7 */
62#define RT2860_INT_MGMT_DONE (1<<8) /* bit 8 */
ca97b838
BZ
63
64#define INT_RX RT2860_INT_RX_DONE
65
9f548a2a
BZ
66#define INT_AC0_DLY (RT2860_INT_AC0_DMA_DONE) /*| RT2860_INT_TX_DLY) */
67#define INT_AC1_DLY (RT2860_INT_AC1_DMA_DONE) /*| RT2860_INT_TX_DLY) */
68#define INT_AC2_DLY (RT2860_INT_AC2_DMA_DONE) /*| RT2860_INT_TX_DLY) */
69#define INT_AC3_DLY (RT2860_INT_AC3_DMA_DONE) /*| RT2860_INT_TX_DLY) */
70#define INT_HCCA_DLY (RT2860_INT_HCCA_DMA_DONE) /*| RT2860_INT_TX_DLY) */
ca97b838
BZ
71#define INT_MGMT_DLY RT2860_INT_MGMT_DONE
72
ca97b838
BZ
73/***************************************************************************
74 *
75 * Interface-depended memory allocation/Free related procedures.
76 * Mainly for Hardware TxDesc/RxDesc/MgmtDesc, DMA Memory for TxData/RxData, etc.,
77 *
78 **************************************************************************/
9f548a2a 79/* Function for TxDesc Memory allocation. */
62eb734b 80void RTMP_AllocateTxDescMemory(struct rt_rtmp_adapter *pAd,
51126deb
BZ
81 u32 Index,
82 unsigned long Length,
66cd8d6e 83 IN BOOLEAN Cached,
51126deb 84 void ** VirtualAddress,
8a10a546 85 dma_addr_t *PhysicalAddress)
ca97b838 86{
8a10a546 87 struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 88
66cd8d6e 89 *VirtualAddress =
51126deb 90 (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length,
66cd8d6e 91 PhysicalAddress);
ca97b838
BZ
92
93}
94
9f548a2a 95/* Function for MgmtDesc Memory allocation. */
62eb734b 96void RTMP_AllocateMgmtDescMemory(struct rt_rtmp_adapter *pAd,
51126deb 97 unsigned long Length,
66cd8d6e 98 IN BOOLEAN Cached,
51126deb 99 void ** VirtualAddress,
8a10a546 100 dma_addr_t *PhysicalAddress)
ca97b838 101{
8a10a546 102 struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 103
66cd8d6e 104 *VirtualAddress =
51126deb 105 (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length,
66cd8d6e 106 PhysicalAddress);
ca97b838
BZ
107
108}
109
9f548a2a 110/* Function for RxDesc Memory allocation. */
62eb734b 111void RTMP_AllocateRxDescMemory(struct rt_rtmp_adapter *pAd,
51126deb 112 unsigned long Length,
66cd8d6e 113 IN BOOLEAN Cached,
51126deb 114 void ** VirtualAddress,
8a10a546 115 dma_addr_t *PhysicalAddress)
ca97b838 116{
8a10a546 117 struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 118
66cd8d6e 119 *VirtualAddress =
51126deb 120 (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length,
66cd8d6e 121 PhysicalAddress);
ca97b838
BZ
122
123}
124
9f548a2a 125/* Function for free allocated Desc Memory. */
62eb734b 126void RTMP_FreeDescMemory(struct rt_rtmp_adapter *pAd,
51126deb
BZ
127 unsigned long Length,
128 void *VirtualAddress,
8a10a546 129 dma_addr_t PhysicalAddress)
ca97b838 130{
8a10a546 131 struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 132
66cd8d6e
BZ
133 pci_free_consistent(pObj->pci_dev, Length, VirtualAddress,
134 PhysicalAddress);
ca97b838
BZ
135}
136
9f548a2a 137/* Function for TxData DMA Memory allocation. */
62eb734b 138void RTMP_AllocateFirstTxBuffer(struct rt_rtmp_adapter *pAd,
51126deb
BZ
139 u32 Index,
140 unsigned long Length,
66cd8d6e 141 IN BOOLEAN Cached,
51126deb 142 void ** VirtualAddress,
8a10a546 143 dma_addr_t *PhysicalAddress)
ca97b838 144{
8a10a546 145 struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 146
66cd8d6e 147 *VirtualAddress =
51126deb 148 (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length,
66cd8d6e 149 PhysicalAddress);
ca97b838
BZ
150}
151
62eb734b 152void RTMP_FreeFirstTxBuffer(struct rt_rtmp_adapter *pAd,
51126deb 153 unsigned long Length,
66cd8d6e 154 IN BOOLEAN Cached,
51126deb 155 void *VirtualAddress,
8a10a546 156 dma_addr_t PhysicalAddress)
ca97b838 157{
8a10a546 158 struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 159
66cd8d6e
BZ
160 pci_free_consistent(pObj->pci_dev, Length, VirtualAddress,
161 PhysicalAddress);
ca97b838
BZ
162}
163
ca97b838
BZ
164/*
165 * FUNCTION: Allocate a common buffer for DMA
166 * ARGUMENTS:
167 * AdapterHandle: AdapterHandle
168 * Length: Number of bytes to allocate
169 * Cached: Whether or not the memory can be cached
170 * VirtualAddress: Pointer to memory is returned here
171 * PhysicalAddress: Physical address corresponding to virtual address
172 */
62eb734b 173void RTMP_AllocateSharedMemory(struct rt_rtmp_adapter *pAd,
51126deb 174 unsigned long Length,
66cd8d6e 175 IN BOOLEAN Cached,
51126deb 176 void ** VirtualAddress,
8a10a546 177 dma_addr_t *PhysicalAddress)
ca97b838 178{
8a10a546 179 struct os_cookie *pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 180
66cd8d6e 181 *VirtualAddress =
51126deb 182 (void *)pci_alloc_consistent(pObj->pci_dev, sizeof(char) * Length,
66cd8d6e 183 PhysicalAddress);
ca97b838
BZ
184}
185
ca97b838
BZ
186/*
187 * FUNCTION: Allocate a packet buffer for DMA
188 * ARGUMENTS:
189 * AdapterHandle: AdapterHandle
190 * Length: Number of bytes to allocate
191 * Cached: Whether or not the memory can be cached
192 * VirtualAddress: Pointer to memory is returned here
193 * PhysicalAddress: Physical address corresponding to virtual address
194 * Notes:
195 * Cached is ignored: always cached memory
196 */
62eb734b 197void *RTMP_AllocateRxPacketBuffer(struct rt_rtmp_adapter *pAd,
51126deb 198 unsigned long Length,
66cd8d6e 199 IN BOOLEAN Cached,
51126deb 200 void ** VirtualAddress,
8a10a546 201 OUT dma_addr_t *
66cd8d6e 202 PhysicalAddress)
ca97b838
BZ
203{
204 struct sk_buff *pkt;
205
206 pkt = dev_alloc_skb(Length);
207
208 if (pkt == NULL) {
66cd8d6e
BZ
209 DBGPRINT(RT_DEBUG_ERROR,
210 ("can't allocate rx %ld size packet\n", Length));
ca97b838
BZ
211 }
212
213 if (pkt) {
214 RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
51126deb 215 *VirtualAddress = (void *)pkt->data;
66cd8d6e
BZ
216 *PhysicalAddress =
217 PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1,
218 PCI_DMA_FROMDEVICE);
ca97b838 219 } else {
51126deb 220 *VirtualAddress = (void *)NULL;
8a10a546 221 *PhysicalAddress = (dma_addr_t)NULL;
ca97b838
BZ
222 }
223
8a10a546 224 return (void *)pkt;
ca97b838
BZ
225}
226
62eb734b 227void Invalid_Remaining_Packet(struct rt_rtmp_adapter *pAd, unsigned long VirtualAddress)
ca97b838 228{
8a10a546 229 dma_addr_t PhysicalAddress;
ca97b838 230
66cd8d6e
BZ
231 PhysicalAddress =
232 PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress + 1600),
233 RX_BUFFER_NORMSIZE - 1600, -1, PCI_DMA_FROMDEVICE);
ca97b838
BZ
234}
235
62eb734b 236int RtmpNetTaskInit(struct rt_rtmp_adapter *pAd)
ca97b838 237{
8a10a546 238 struct os_cookie *pObj;
ca97b838 239
8a10a546 240 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838
BZ
241
242 tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (unsigned long)pAd);
66cd8d6e
BZ
243 tasklet_init(&pObj->mgmt_dma_done_task, mgmt_dma_done_tasklet,
244 (unsigned long)pAd);
245 tasklet_init(&pObj->ac0_dma_done_task, ac0_dma_done_tasklet,
246 (unsigned long)pAd);
247 tasklet_init(&pObj->ac1_dma_done_task, ac1_dma_done_tasklet,
248 (unsigned long)pAd);
249 tasklet_init(&pObj->ac2_dma_done_task, ac2_dma_done_tasklet,
250 (unsigned long)pAd);
251 tasklet_init(&pObj->ac3_dma_done_task, ac3_dma_done_tasklet,
252 (unsigned long)pAd);
ca97b838 253 tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd);
66cd8d6e
BZ
254 tasklet_init(&pObj->fifo_statistic_full_task,
255 fifo_statistic_full_tasklet, (unsigned long)pAd);
ca97b838
BZ
256
257 return NDIS_STATUS_SUCCESS;
258}
259
62eb734b 260void RtmpNetTaskExit(struct rt_rtmp_adapter *pAd)
ca97b838 261{
8a10a546 262 struct os_cookie *pObj;
ca97b838 263
8a10a546 264 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838
BZ
265
266 tasklet_kill(&pObj->rx_done_task);
267 tasklet_kill(&pObj->mgmt_dma_done_task);
268 tasklet_kill(&pObj->ac0_dma_done_task);
269 tasklet_kill(&pObj->ac1_dma_done_task);
270 tasklet_kill(&pObj->ac2_dma_done_task);
271 tasklet_kill(&pObj->ac3_dma_done_task);
272 tasklet_kill(&pObj->tbtt_task);
273 tasklet_kill(&pObj->fifo_statistic_full_task);
274}
275
62eb734b 276int RtmpMgmtTaskInit(struct rt_rtmp_adapter *pAd)
ca97b838
BZ
277{
278
ca97b838
BZ
279 return NDIS_STATUS_SUCCESS;
280}
281
ca97b838
BZ
282/*
283========================================================================
284Routine Description:
285 Close kernel threads.
286
287Arguments:
288 *pAd the raxx interface data pointer
289
290Return Value:
291 NONE
292
293Note:
294========================================================================
295*/
62eb734b 296void RtmpMgmtTaskExit(struct rt_rtmp_adapter *pAd)
ca97b838
BZ
297{
298
ca97b838
BZ
299 return;
300}
301
62eb734b 302static inline void rt2860_int_enable(struct rt_rtmp_adapter *pAd, unsigned int mode)
ca97b838
BZ
303{
304 u32 regValue;
305
306 pAd->int_disable_mask &= ~(mode);
307 regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask);
9f548a2a 308 /*if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) */
ca97b838 309 {
9f548a2a 310 RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); /* 1:enable */
ca97b838 311 }
9f548a2a
BZ
312 /*else */
313 /* DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_DOZE !\n")); */
ca97b838
BZ
314
315 if (regValue != 0)
316 RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE);
317}
318
62eb734b 319static inline void rt2860_int_disable(struct rt_rtmp_adapter *pAd, unsigned int mode)
ca97b838
BZ
320{
321 u32 regValue;
322
323 pAd->int_disable_mask |= mode;
66cd8d6e 324 regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask);
9f548a2a 325 RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); /* 0: disable */
ca97b838 326
66cd8d6e 327 if (regValue == 0) {
ca97b838
BZ
328 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE);
329 }
330}
331
ca97b838
BZ
332/***************************************************************************
333 *
334 * tasklet related procedures.
335 *
336 **************************************************************************/
337static void mgmt_dma_done_tasklet(unsigned long data)
338{
339 unsigned long flags;
62eb734b 340 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data;
66cd8d6e 341 INT_SOURCE_CSR_STRUC IntSource;
8a10a546 342 struct os_cookie *pObj;
ca97b838 343
9f548a2a
BZ
344 /* Do nothing if the driver is starting halt state. */
345 /* This might happen when timer already been fired before cancel timer with mlmehalt */
66cd8d6e
BZ
346 if (RTMP_TEST_FLAG
347 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
ca97b838
BZ
348 return;
349
8a10a546 350 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 351
9f548a2a 352/* printk("mgmt_dma_done_process\n"); */
ca97b838
BZ
353 IntSource.word = 0;
354 IntSource.field.MgmtDmaDone = 1;
355 pAd->int_pending &= ~INT_MGMT_DLY;
356
357 RTMPHandleMgmtRingDmaDoneInterrupt(pAd);
358
9f548a2a
BZ
359 /* if you use RTMP_SEM_LOCK, sometimes kernel will hang up, no any */
360 /* bug report output */
ca97b838
BZ
361 RTMP_INT_LOCK(&pAd->irq_lock, flags);
362 /*
363 * double check to avoid lose of interrupts
364 */
66cd8d6e 365 if (pAd->int_pending & INT_MGMT_DLY) {
ca97b838
BZ
366 tasklet_hi_schedule(&pObj->mgmt_dma_done_task);
367 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
368 return;
369 }
370
371 /* enable TxDataInt again */
372 rt2860_int_enable(pAd, INT_MGMT_DLY);
373 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
374}
375
ca97b838
BZ
376static void rx_done_tasklet(unsigned long data)
377{
378 unsigned long flags;
62eb734b 379 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data;
66cd8d6e 380 BOOLEAN bReschedule = 0;
8a10a546 381 struct os_cookie *pObj;
ca97b838 382
9f548a2a
BZ
383 /* Do nothing if the driver is starting halt state. */
384 /* This might happen when timer already been fired before cancel timer with mlmehalt */
66cd8d6e
BZ
385 if (RTMP_TEST_FLAG
386 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
ca97b838
BZ
387 return;
388
8a10a546 389 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838
BZ
390
391 pAd->int_pending &= ~(INT_RX);
66cd8d6e 392 bReschedule = STARxDoneInterruptHandle(pAd, 0);
ca97b838
BZ
393
394 RTMP_INT_LOCK(&pAd->irq_lock, flags);
395 /*
396 * double check to avoid rotting packet
397 */
66cd8d6e 398 if (pAd->int_pending & INT_RX || bReschedule) {
ca97b838
BZ
399 tasklet_hi_schedule(&pObj->rx_done_task);
400 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
401 return;
402 }
403
51126deb 404 /* enable Rxint again */
ca97b838
BZ
405 rt2860_int_enable(pAd, INT_RX);
406 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
407
408}
409
ca97b838
BZ
410void fifo_statistic_full_tasklet(unsigned long data)
411{
412 unsigned long flags;
62eb734b 413 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data;
8a10a546 414 struct os_cookie *pObj;
ca97b838 415
9f548a2a
BZ
416 /* Do nothing if the driver is starting halt state. */
417 /* This might happen when timer already been fired before cancel timer with mlmehalt */
66cd8d6e
BZ
418 if (RTMP_TEST_FLAG
419 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
ca97b838
BZ
420 return;
421
8a10a546 422 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838
BZ
423
424 pAd->int_pending &= ~(FifoStaFullInt);
425 NICUpdateFifoStaCounters(pAd);
426
427 RTMP_INT_LOCK(&pAd->irq_lock, flags);
428 /*
429 * double check to avoid rotting packet
430 */
66cd8d6e 431 if (pAd->int_pending & FifoStaFullInt) {
ca97b838
BZ
432 tasklet_hi_schedule(&pObj->fifo_statistic_full_task);
433 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
434 return;
435 }
436
51126deb 437 /* enable Rxint again */
ca97b838
BZ
438
439 rt2860_int_enable(pAd, FifoStaFullInt);
440 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
441
442}
443
444static void ac3_dma_done_tasklet(unsigned long data)
445{
446 unsigned long flags;
62eb734b 447 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data;
66cd8d6e 448 INT_SOURCE_CSR_STRUC IntSource;
8a10a546 449 struct os_cookie *pObj;
ca97b838
BZ
450 BOOLEAN bReschedule = 0;
451
9f548a2a
BZ
452 /* Do nothing if the driver is starting halt state. */
453 /* This might happen when timer already been fired before cancel timer with mlmehalt */
66cd8d6e
BZ
454 if (RTMP_TEST_FLAG
455 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
ca97b838
BZ
456 return;
457
8a10a546 458 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 459
9f548a2a 460/* printk("ac0_dma_done_process\n"); */
ca97b838
BZ
461 IntSource.word = 0;
462 IntSource.field.Ac3DmaDone = 1;
463 pAd->int_pending &= ~INT_AC3_DLY;
464
465 bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
466
467 RTMP_INT_LOCK(&pAd->irq_lock, flags);
468 /*
469 * double check to avoid lose of interrupts
470 */
66cd8d6e 471 if ((pAd->int_pending & INT_AC3_DLY) || bReschedule) {
ca97b838
BZ
472 tasklet_hi_schedule(&pObj->ac3_dma_done_task);
473 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
474 return;
475 }
476
477 /* enable TxDataInt again */
478 rt2860_int_enable(pAd, INT_AC3_DLY);
479 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
480}
481
ca97b838
BZ
482static void ac2_dma_done_tasklet(unsigned long data)
483{
484 unsigned long flags;
62eb734b 485 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data;
66cd8d6e 486 INT_SOURCE_CSR_STRUC IntSource;
8a10a546 487 struct os_cookie *pObj;
ca97b838
BZ
488 BOOLEAN bReschedule = 0;
489
9f548a2a
BZ
490 /* Do nothing if the driver is starting halt state. */
491 /* This might happen when timer already been fired before cancel timer with mlmehalt */
66cd8d6e
BZ
492 if (RTMP_TEST_FLAG
493 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
ca97b838
BZ
494 return;
495
8a10a546 496 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838
BZ
497
498 IntSource.word = 0;
499 IntSource.field.Ac2DmaDone = 1;
500 pAd->int_pending &= ~INT_AC2_DLY;
501
502 bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
503
504 RTMP_INT_LOCK(&pAd->irq_lock, flags);
505
506 /*
507 * double check to avoid lose of interrupts
508 */
66cd8d6e 509 if ((pAd->int_pending & INT_AC2_DLY) || bReschedule) {
ca97b838
BZ
510 tasklet_hi_schedule(&pObj->ac2_dma_done_task);
511 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
512 return;
513 }
514
515 /* enable TxDataInt again */
516 rt2860_int_enable(pAd, INT_AC2_DLY);
517 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
518}
519
ca97b838
BZ
520static void ac1_dma_done_tasklet(unsigned long data)
521{
522 unsigned long flags;
62eb734b 523 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data;
66cd8d6e 524 INT_SOURCE_CSR_STRUC IntSource;
8a10a546 525 struct os_cookie *pObj;
ca97b838
BZ
526 BOOLEAN bReschedule = 0;
527
9f548a2a
BZ
528 /* Do nothing if the driver is starting halt state. */
529 /* This might happen when timer already been fired before cancel timer with mlmehalt */
66cd8d6e
BZ
530 if (RTMP_TEST_FLAG
531 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
ca97b838
BZ
532 return;
533
8a10a546 534 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 535
9f548a2a 536/* printk("ac0_dma_done_process\n"); */
ca97b838
BZ
537 IntSource.word = 0;
538 IntSource.field.Ac1DmaDone = 1;
539 pAd->int_pending &= ~INT_AC1_DLY;
540
541 bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
542
543 RTMP_INT_LOCK(&pAd->irq_lock, flags);
544 /*
545 * double check to avoid lose of interrupts
546 */
66cd8d6e 547 if ((pAd->int_pending & INT_AC1_DLY) || bReschedule) {
ca97b838
BZ
548 tasklet_hi_schedule(&pObj->ac1_dma_done_task);
549 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
550 return;
551 }
552
553 /* enable TxDataInt again */
554 rt2860_int_enable(pAd, INT_AC1_DLY);
555 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
556}
557
ca97b838
BZ
558static void ac0_dma_done_tasklet(unsigned long data)
559{
560 unsigned long flags;
62eb734b 561 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)data;
66cd8d6e 562 INT_SOURCE_CSR_STRUC IntSource;
8a10a546 563 struct os_cookie *pObj;
ca97b838
BZ
564 BOOLEAN bReschedule = 0;
565
9f548a2a
BZ
566 /* Do nothing if the driver is starting halt state. */
567 /* This might happen when timer already been fired before cancel timer with mlmehalt */
66cd8d6e
BZ
568 if (RTMP_TEST_FLAG
569 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
ca97b838
BZ
570 return;
571
8a10a546 572 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 573
9f548a2a 574/* printk("ac0_dma_done_process\n"); */
ca97b838
BZ
575 IntSource.word = 0;
576 IntSource.field.Ac0DmaDone = 1;
577 pAd->int_pending &= ~INT_AC0_DLY;
578
9f548a2a 579/* RTMPHandleMgmtRingDmaDoneInterrupt(pAd); */
ca97b838
BZ
580 bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
581
582 RTMP_INT_LOCK(&pAd->irq_lock, flags);
583 /*
584 * double check to avoid lose of interrupts
585 */
66cd8d6e 586 if ((pAd->int_pending & INT_AC0_DLY) || bReschedule) {
ca97b838
BZ
587 tasklet_hi_schedule(&pObj->ac0_dma_done_task);
588 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
589 return;
590 }
591
592 /* enable TxDataInt again */
593 rt2860_int_enable(pAd, INT_AC0_DLY);
594 RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
595}
596
ca97b838
BZ
597/***************************************************************************
598 *
599 * interrupt handler related procedures.
600 *
601 **************************************************************************/
602int print_int_count;
603
604IRQ_HANDLE_TYPE rt2860_interrupt(int irq, void *dev_instance)
605{
66cd8d6e 606 struct net_device *net_dev = (struct net_device *)dev_instance;
62eb734b 607 struct rt_rtmp_adapter *pAd = NULL;
66cd8d6e 608 INT_SOURCE_CSR_STRUC IntSource;
8a10a546 609 struct os_cookie *pObj;
ca97b838
BZ
610
611 GET_PAD_FROM_NET_DEV(pAd, net_dev);
612
8a10a546 613 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 614
ca97b838 615 /* Note 03312008: we can not return here before
66cd8d6e
BZ
616 RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word);
617 RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word);
618 Or kernel will panic after ifconfig ra0 down sometimes */
ca97b838 619
9f548a2a
BZ
620 /* */
621 /* Inital the Interrupt source. */
622 /* */
ca97b838 623 IntSource.word = 0x00000000L;
9f548a2a
BZ
624/* McuIntSource.word = 0x00000000L; */
625
626 /* */
627 /* Get the interrupt sources & saved to local variable */
628 /* */
629 /*RTMP_IO_READ32(pAd, where, &McuIntSource.word); */
630 /*RTMP_IO_WRITE32(pAd, , McuIntSource.word); */
631
632 /* */
633 /* Flag fOP_STATUS_DOZE On, means ASIC put to sleep, elase means ASICK WakeUp */
634 /* And at the same time, clock maybe turned off that say there is no DMA service. */
635 /* when ASIC get to sleep. */
636 /* To prevent system hang on power saving. */
637 /* We need to check it before handle the INT_SOURCE_CSR, ASIC must be wake up. */
638 /* */
639 /* RT2661 => when ASIC is sleeping, MAC register cannot be read and written. */
640 /* RT2860 => when ASIC is sleeping, MAC register can be read and written. */
641/* if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) */
ca97b838
BZ
642 {
643 RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word);
9f548a2a 644 RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); /* write 1 to clear */
ca97b838 645 }
9f548a2a
BZ
646/* else */
647/* DBGPRINT(RT_DEBUG_TRACE, (">>>fOP_STATUS_DOZE<<<\n")); */
ca97b838 648
9f548a2a
BZ
649/* RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IsrAfterClear); */
650/* RTMP_IO_READ32(pAd, MCU_INT_SOURCE_CSR, &McuIsrAfterClear); */
651/* DBGPRINT(RT_DEBUG_INFO, ("====> RTMPHandleInterrupt(ISR=%08x,Mcu ISR=%08x, After clear ISR=%08x, MCU ISR=%08x)\n", */
652/* IntSource.word, McuIntSource.word, IsrAfterClear, McuIsrAfterClear)); */
ca97b838 653
9f548a2a 654 /* Do nothing if Reset in progress */
66cd8d6e
BZ
655 if (RTMP_TEST_FLAG
656 (pAd,
657 (fRTMP_ADAPTER_RESET_IN_PROGRESS |
658 fRTMP_ADAPTER_HALT_IN_PROGRESS))) {
659 return IRQ_HANDLED;
ca97b838 660 }
9f548a2a
BZ
661 /* */
662 /* Handle interrupt, walk through all bits */
663 /* Should start from highest priority interrupt */
664 /* The priority can be adjust by altering processing if statement */
665 /* */
ca97b838
BZ
666
667#ifdef DBG
668
669#endif
670
ca97b838
BZ
671 pAd->bPCIclkOff = FALSE;
672
9f548a2a
BZ
673 /* If required spinlock, each interrupt service routine has to acquire */
674 /* and release itself. */
675 /* */
ca97b838 676
9f548a2a 677 /* Do nothing if NIC doesn't exist */
66cd8d6e
BZ
678 if (IntSource.word == 0xffffffff) {
679 RTMP_SET_FLAG(pAd,
680 (fRTMP_ADAPTER_NIC_NOT_EXIST |
681 fRTMP_ADAPTER_HALT_IN_PROGRESS));
682 return IRQ_HANDLED;
ca97b838
BZ
683 }
684
66cd8d6e 685 if (IntSource.word & TxCoherent) {
ca97b838
BZ
686 DBGPRINT(RT_DEBUG_ERROR, (">>>TxCoherent<<<\n"));
687 RTMPHandleRxCoherentInterrupt(pAd);
688 }
689
66cd8d6e 690 if (IntSource.word & RxCoherent) {
ca97b838
BZ
691 DBGPRINT(RT_DEBUG_ERROR, (">>>RxCoherent<<<\n"));
692 RTMPHandleRxCoherentInterrupt(pAd);
693 }
694
66cd8d6e
BZ
695 if (IntSource.word & FifoStaFullInt) {
696 if ((pAd->int_disable_mask & FifoStaFullInt) == 0) {
ca97b838
BZ
697 /* mask FifoStaFullInt */
698 rt2860_int_disable(pAd, FifoStaFullInt);
699 tasklet_hi_schedule(&pObj->fifo_statistic_full_task);
700 }
701 pAd->int_pending |= FifoStaFullInt;
702 }
703
66cd8d6e
BZ
704 if (IntSource.word & INT_MGMT_DLY) {
705 if ((pAd->int_disable_mask & INT_MGMT_DLY) == 0) {
ca97b838
BZ
706 rt2860_int_disable(pAd, INT_MGMT_DLY);
707 tasklet_hi_schedule(&pObj->mgmt_dma_done_task);
708 }
66cd8d6e 709 pAd->int_pending |= INT_MGMT_DLY;
ca97b838
BZ
710 }
711
66cd8d6e
BZ
712 if (IntSource.word & INT_RX) {
713 if ((pAd->int_disable_mask & INT_RX) == 0) {
ca97b838 714
51126deb 715 /* mask Rxint */
ca97b838
BZ
716 rt2860_int_disable(pAd, INT_RX);
717 tasklet_hi_schedule(&pObj->rx_done_task);
718 }
719 pAd->int_pending |= INT_RX;
720 }
721
66cd8d6e 722 if (IntSource.word & INT_AC3_DLY) {
ca97b838 723
66cd8d6e 724 if ((pAd->int_disable_mask & INT_AC3_DLY) == 0) {
ca97b838
BZ
725 /* mask TxDataInt */
726 rt2860_int_disable(pAd, INT_AC3_DLY);
727 tasklet_hi_schedule(&pObj->ac3_dma_done_task);
728 }
729 pAd->int_pending |= INT_AC3_DLY;
730 }
731
66cd8d6e 732 if (IntSource.word & INT_AC2_DLY) {
ca97b838 733
66cd8d6e 734 if ((pAd->int_disable_mask & INT_AC2_DLY) == 0) {
ca97b838
BZ
735 /* mask TxDataInt */
736 rt2860_int_disable(pAd, INT_AC2_DLY);
737 tasklet_hi_schedule(&pObj->ac2_dma_done_task);
738 }
739 pAd->int_pending |= INT_AC2_DLY;
740 }
741
66cd8d6e 742 if (IntSource.word & INT_AC1_DLY) {
ca97b838
BZ
743
744 pAd->int_pending |= INT_AC1_DLY;
745
66cd8d6e 746 if ((pAd->int_disable_mask & INT_AC1_DLY) == 0) {
ca97b838
BZ
747 /* mask TxDataInt */
748 rt2860_int_disable(pAd, INT_AC1_DLY);
749 tasklet_hi_schedule(&pObj->ac1_dma_done_task);
750 }
751
752 }
753
66cd8d6e 754 if (IntSource.word & INT_AC0_DLY) {
ca97b838
BZ
755
756/*
757 if (IntSource.word & 0x2) {
758 u32 reg;
759 RTMP_IO_READ32(pAd, DELAY_INT_CFG, &reg);
760 printk("IntSource.word = %08x, DELAY_REG = %08x\n", IntSource.word, reg);
761 }
762*/
763 pAd->int_pending |= INT_AC0_DLY;
764
66cd8d6e 765 if ((pAd->int_disable_mask & INT_AC0_DLY) == 0) {
ca97b838
BZ
766 /* mask TxDataInt */
767 rt2860_int_disable(pAd, INT_AC0_DLY);
768 tasklet_hi_schedule(&pObj->ac0_dma_done_task);
769 }
770
771 }
772
66cd8d6e 773 if (IntSource.word & PreTBTTInt) {
ca97b838
BZ
774 RTMPHandlePreTBTTInterrupt(pAd);
775 }
776
66cd8d6e 777 if (IntSource.word & TBTTInt) {
ca97b838
BZ
778 RTMPHandleTBTTInterrupt(pAd);
779 }
780
781 {
782 if (IntSource.word & AutoWakeupInt)
783 RTMPHandleTwakeupInterrupt(pAd);
784 }
785
66cd8d6e 786 return IRQ_HANDLED;
ca97b838
BZ
787}
788
789/*
790 * invaild or writeback cache
791 * and convert virtual address to physical address
792 */
9fd453c9
BH
793dma_addr_t linux_pci_map_single(struct rt_rtmp_adapter *pAd, void *ptr,
794 size_t size, int sd_idx, int direction)
ca97b838 795{
8a10a546 796 struct os_cookie *pObj;
ca97b838
BZ
797
798 /*
66cd8d6e
BZ
799 ------ Porting Information ------
800 > For Tx Alloc:
801 mgmt packets => sd_idx = 0
802 SwIdx: pAd->MgmtRing.TxCpuIdx
803 pTxD : pAd->MgmtRing.Cell[SwIdx].AllocVa;
804
805 data packets => sd_idx = 1
806 TxIdx : pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx
807 QueIdx: pTxBlk->QueIdx
808 pTxD : pAd->TxRing[pTxBlk->QueIdx].Cell[TxIdx].AllocVa;
809
810 > For Rx Alloc:
811 sd_idx = -1
812 */
ca97b838 813
8a10a546 814 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 815
66cd8d6e 816 if (sd_idx == 1) {
62eb734b
BZ
817 struct rt_tx_blk *pTxBlk;
818 pTxBlk = (struct rt_tx_blk *)ptr;
66cd8d6e
BZ
819 return pci_map_single(pObj->pci_dev, pTxBlk->pSrcBufData,
820 pTxBlk->SrcBufLen, direction);
821 } else {
ca97b838
BZ
822 return pci_map_single(pObj->pci_dev, ptr, size, direction);
823 }
824
825}
826
9fd453c9
BH
827void linux_pci_unmap_single(struct rt_rtmp_adapter *pAd, dma_addr_t dma_addr,
828 size_t size, int direction)
ca97b838 829{
8a10a546 830 struct os_cookie *pObj;
ca97b838 831
8a10a546 832 pObj = (struct os_cookie *)pAd->OS_Cookie;
ca97b838 833
e44fd1cf 834 pci_unmap_single(pObj->pci_dev, dma_addr, size, direction);
ca97b838
BZ
835
836}