Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / drivers / staging / ath6kl / htc2 / AR6000 / ar6k.c
1 //------------------------------------------------------------------------------
2 // <copyright file="ar6k.c" company="Atheros">
3 //    Copyright (c) 2007-2010 Atheros Corporation.  All rights reserved.
4 // 
5 //
6 // Permission to use, copy, modify, and/or distribute this software for any
7 // purpose with or without fee is hereby granted, provided that the above
8 // copyright notice and this permission notice appear in all copies.
9 //
10 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 //
18 //
19 //------------------------------------------------------------------------------
20 //==============================================================================
21 // AR6K device layer that handles register level I/O
22 //
23 // Author(s): ="Atheros"
24 //==============================================================================
25
26 #include "a_config.h"
27 #include "athdefs.h"
28 #include "a_types.h"
29 #include "AR6002/hw2.0/hw/mbox_host_reg.h"
30 #include "a_osapi.h"
31 #include "../htc_debug.h"
32 #include "hif.h"
33 #include "htc_packet.h"
34 #include "ar6k.h"
35
36 #define MAILBOX_FOR_BLOCK_SIZE          1
37
38 A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
39 A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
40
41 static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev);
42
43 void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket)
44 {
45     LOCK_AR6K(pDev);
46     HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket);
47     UNLOCK_AR6K(pDev);
48 }
49
50 HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev)
51 {
52     HTC_PACKET *pPacket;
53
54     LOCK_AR6K(pDev);
55     pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList);
56     UNLOCK_AR6K(pDev);
57
58     return pPacket;
59 }
60
61 void DevCleanup(AR6K_DEVICE *pDev)
62 {
63     DevCleanupGMbox(pDev);
64
65     if (pDev->HifAttached) {
66         HIFDetachHTC(pDev->HIFDevice);
67         pDev->HifAttached = FALSE;
68     }
69
70     DevCleanupVirtualScatterSupport(pDev);
71
72     if (A_IS_MUTEX_VALID(&pDev->Lock)) {
73         A_MUTEX_DELETE(&pDev->Lock);
74     }
75 }
76
77 A_STATUS DevSetup(AR6K_DEVICE *pDev)
78 {
79     A_UINT32 blocksizes[AR6K_MAILBOXES];
80     A_STATUS status = A_OK;
81     int      i;
82     HTC_CALLBACKS htcCallbacks;
83
84     do {
85
86         DL_LIST_INIT(&pDev->ScatterReqHead);
87            /* initialize our free list of IO packets */
88         INIT_HTC_PACKET_QUEUE(&pDev->RegisterIOList);
89         A_MUTEX_INIT(&pDev->Lock);
90
91         A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS));
92             /* the device layer handles these */
93         htcCallbacks.rwCompletionHandler = DevRWCompletionHandler;
94         htcCallbacks.dsrHandler = DevDsrHandler;
95         htcCallbacks.context = pDev;
96
97         status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks);
98
99         if (A_FAILED(status)) {
100             break;
101         }
102
103         pDev->HifAttached = TRUE;
104
105             /* get the addresses for all 4 mailboxes */
106         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
107                                     &pDev->MailBoxInfo, sizeof(pDev->MailBoxInfo));
108
109         if (status != A_OK) {
110             A_ASSERT(FALSE);
111             break;
112         }
113
114             /* carve up register I/O packets (these are for ASYNC register I/O ) */
115         for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) {
116             HTC_PACKET *pIOPacket;
117             pIOPacket = &pDev->RegIOBuffers[i].HtcPacket;
118             SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket,
119                                           pDev,
120                                           pDev->RegIOBuffers[i].Buffer,
121                                           AR6K_REG_IO_BUFFER_SIZE,
122                                           0); /* don't care */
123             AR6KFreeIOPacket(pDev,pIOPacket);
124         }
125
126             /* get the block sizes */
127         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
128                                     blocksizes, sizeof(blocksizes));
129
130         if (status != A_OK) {
131             A_ASSERT(FALSE);
132             break;
133         }
134
135             /* note: we actually get the block size of a mailbox other than 0, for SDIO the block
136              * size on mailbox 0 is artificially set to 1.  So we use the block size that is set
137              * for the other 3 mailboxes */
138         pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE];
139             /* must be a power of 2 */
140         A_ASSERT((pDev->BlockSize & (pDev->BlockSize - 1)) == 0);
141
142             /* assemble mask, used for padding to a block */
143         pDev->BlockMask = pDev->BlockSize - 1;
144
145         AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("BlockSize: %d, MailboxAddress:0x%X \n",
146                     pDev->BlockSize, pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX]));
147
148         pDev->GetPendingEventsFunc = NULL;
149             /* see if the HIF layer implements the get pending events function  */
150         HIFConfigureDevice(pDev->HIFDevice,
151                            HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
152                            &pDev->GetPendingEventsFunc,
153                            sizeof(pDev->GetPendingEventsFunc));
154
155             /* assume we can process HIF interrupt events asynchronously */
156         pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC;
157
158             /* see if the HIF layer overrides this assumption */
159         HIFConfigureDevice(pDev->HIFDevice,
160                            HIF_DEVICE_GET_IRQ_PROC_MODE,
161                            &pDev->HifIRQProcessingMode,
162                            sizeof(pDev->HifIRQProcessingMode));
163
164         switch (pDev->HifIRQProcessingMode) {
165             case HIF_DEVICE_IRQ_SYNC_ONLY:
166                 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HIF Interrupt processing is SYNC ONLY\n"));
167                     /* see if HIF layer wants HTC to yield */
168                 HIFConfigureDevice(pDev->HIFDevice,
169                                    HIF_DEVICE_GET_IRQ_YIELD_PARAMS,
170                                    &pDev->HifIRQYieldParams,
171                                    sizeof(pDev->HifIRQYieldParams));
172
173                 if (pDev->HifIRQYieldParams.RecvPacketYieldCount > 0) {
174                     AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
175                         ("HIF requests that DSR yield per %d RECV packets \n",
176                         pDev->HifIRQYieldParams.RecvPacketYieldCount));
177                     pDev->DSRCanYield = TRUE;
178                 }
179                 break;
180             case HIF_DEVICE_IRQ_ASYNC_SYNC:
181                 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n"));
182                 break;
183             default:
184                 A_ASSERT(FALSE);
185         }
186
187         pDev->HifMaskUmaskRecvEvent = NULL;
188
189             /* see if the HIF layer implements the mask/unmask recv events function  */
190         HIFConfigureDevice(pDev->HIFDevice,
191                            HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC,
192                            &pDev->HifMaskUmaskRecvEvent,
193                            sizeof(pDev->HifMaskUmaskRecvEvent));
194
195         AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%lX , 0x%lX\n",
196                  (unsigned long)pDev->GetPendingEventsFunc, (unsigned long)pDev->HifMaskUmaskRecvEvent));
197
198         status = DevDisableInterrupts(pDev);
199
200         if (A_FAILED(status)) {
201             break;
202         }
203
204         status = DevSetupGMbox(pDev);
205
206     } while (FALSE);
207
208     if (A_FAILED(status)) {
209         if (pDev->HifAttached) {
210             HIFDetachHTC(pDev->HIFDevice);
211             pDev->HifAttached = FALSE;
212         }
213     }
214
215     return status;
216
217 }
218
219 A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev)
220 {
221     A_STATUS                  status;
222     AR6K_IRQ_ENABLE_REGISTERS regs;
223
224     LOCK_AR6K(pDev);
225
226         /* Enable all the interrupts except for the internal AR6000 CPU interrupt */
227     pDev->IrqEnableRegisters.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) |
228                                       INT_STATUS_ENABLE_CPU_SET(0x01) |
229                                       INT_STATUS_ENABLE_COUNTER_SET(0x01);
230
231     if (NULL == pDev->GetPendingEventsFunc) {
232         pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
233     } else {
234         /* The HIF layer provided us with a pending events function which means that
235          * the detection of pending mbox messages is handled in the HIF layer.
236          * This is the case for the SPI2 interface.
237          * In the normal case we enable MBOX interrupts, for the case
238          * with HIFs that offer this mechanism, we keep these interrupts
239          * masked */
240         pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
241     }
242
243
244     /* Set up the CPU Interrupt Status Register */
245     pDev->IrqEnableRegisters.cpu_int_status_enable = CPU_INT_STATUS_ENABLE_BIT_SET(0x00);
246
247     /* Set up the Error Interrupt Status Register */
248     pDev->IrqEnableRegisters.error_status_enable =
249                                   ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) |
250                                   ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01);
251
252     /* Set up the Counter Interrupt Status Register (only for debug interrupt to catch fatal errors) */
253     pDev->IrqEnableRegisters.counter_int_status_enable =
254         COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK);
255
256         /* copy into our temp area */
257     A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
258
259     UNLOCK_AR6K(pDev);
260
261         /* always synchronous */
262     status = HIFReadWrite(pDev->HIFDevice,
263                           INT_STATUS_ENABLE_ADDRESS,
264                           &regs.int_status_enable,
265                           AR6K_IRQ_ENABLE_REGS_SIZE,
266                           HIF_WR_SYNC_BYTE_INC,
267                           NULL);
268
269     if (status != A_OK) {
270         /* Can't write it for some reason */
271         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
272                         ("Failed to update interrupt control registers err: %d\n", status));
273
274     }
275
276     return status;
277 }
278
279 A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev)
280 {
281     AR6K_IRQ_ENABLE_REGISTERS regs;
282
283     LOCK_AR6K(pDev);
284         /* Disable all interrupts */
285     pDev->IrqEnableRegisters.int_status_enable = 0;
286     pDev->IrqEnableRegisters.cpu_int_status_enable = 0;
287     pDev->IrqEnableRegisters.error_status_enable = 0;
288     pDev->IrqEnableRegisters.counter_int_status_enable = 0;
289         /* copy into our temp area */
290     A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
291
292     UNLOCK_AR6K(pDev);
293
294         /* always synchronous */
295     return HIFReadWrite(pDev->HIFDevice,
296                         INT_STATUS_ENABLE_ADDRESS,
297                         &regs.int_status_enable,
298                         AR6K_IRQ_ENABLE_REGS_SIZE,
299                         HIF_WR_SYNC_BYTE_INC,
300                         NULL);
301 }
302
303 /* enable device interrupts */
304 A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev)
305 {
306     /* for good measure, make sure interrupt are disabled before unmasking at the HIF
307      * layer.
308      * The rationale here is that between device insertion (where we clear the interrupts the first time)
309      * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets.
310      * The AR6K interrupt enables reset back to an "enabled" state when this happens.
311      *  */
312     A_STATUS IntStatus = A_OK;
313     DevDisableInterrupts(pDev);
314
315 #ifdef THREAD_X
316     // Tobe verified...
317     IntStatus = DevEnableInterrupts(pDev);
318     /* Unmask the host controller interrupts */
319     HIFUnMaskInterrupt(pDev->HIFDevice);
320 #else
321     /* Unmask the host controller interrupts */
322     HIFUnMaskInterrupt(pDev->HIFDevice);
323     IntStatus = DevEnableInterrupts(pDev);
324 #endif
325
326     return IntStatus;
327 }
328
329 /* disable all device interrupts */
330 A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev)
331 {
332         /* mask the interrupt at the HIF layer, we don't want a stray interrupt taken while
333          * we zero out our shadow registers in DevDisableInterrupts()*/
334     HIFMaskInterrupt(pDev->HIFDevice);
335
336     return DevDisableInterrupts(pDev);
337 }
338
339 /* callback when our fetch to enable/disable completes */
340 static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacket)
341 {
342     AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
343
344     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
345
346     if (A_FAILED(pPacket->Status)) {
347         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
348                 (" Failed to disable receiver, status:%d \n", pPacket->Status));
349     }
350         /* free this IO packet */
351     AR6KFreeIOPacket(pDev,pPacket);
352     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDoEnableDisableRecvAsyncHandler \n"));
353 }
354
355 /* disable packet reception (used in case the host runs out of buffers)
356  * this is the "override" method when the HIF reports another methods to
357  * disable recv events */
358 static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
359 {
360     A_STATUS                  status = A_OK;
361     HTC_PACKET                *pIOPacket = NULL;
362
363     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n",
364             EnableRecv,AsyncMode));
365
366     do {
367
368         if (AsyncMode) {
369
370             pIOPacket = AR6KAllocIOPacket(pDev);
371
372             if (NULL == pIOPacket) {
373                 status = A_NO_MEMORY;
374                 A_ASSERT(FALSE);
375                 break;
376             }
377
378                 /* stick in our completion routine when the I/O operation completes */
379             pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
380             pIOPacket->pContext = pDev;
381
382                 /* call the HIF layer override and do this asynchronously */
383             status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
384                                                  EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
385                                                  pIOPacket);
386             break;
387         }
388
389             /* if we get here we are doing it synchronously */
390         status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
391                                              EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
392                                              NULL);
393
394     } while (FALSE);
395
396     if (A_FAILED(status) && (pIOPacket != NULL)) {
397         AR6KFreeIOPacket(pDev,pIOPacket);
398     }
399
400     return status;
401 }
402
403 /* disable packet reception (used in case the host runs out of buffers)
404  * this is the "normal" method using the interrupt enable registers through
405  * the host I/F */
406 static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
407 {
408     A_STATUS                  status = A_OK;
409     HTC_PACKET                *pIOPacket = NULL;
410     AR6K_IRQ_ENABLE_REGISTERS regs;
411
412         /* take the lock to protect interrupt enable shadows */
413     LOCK_AR6K(pDev);
414
415     if (EnableRecv) {
416         pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
417     } else {
418         pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
419     }
420
421         /* copy into our temp area */
422     A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
423     UNLOCK_AR6K(pDev);
424
425     do {
426
427         if (AsyncMode) {
428
429             pIOPacket = AR6KAllocIOPacket(pDev);
430
431             if (NULL == pIOPacket) {
432                 status = A_NO_MEMORY;
433                 A_ASSERT(FALSE);
434                 break;
435             }
436
437                 /* copy values to write to our async I/O buffer */
438             A_MEMCPY(pIOPacket->pBuffer,&regs,AR6K_IRQ_ENABLE_REGS_SIZE);
439
440                 /* stick in our completion routine when the I/O operation completes */
441             pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
442             pIOPacket->pContext = pDev;
443
444                 /* write it out asynchronously */
445             HIFReadWrite(pDev->HIFDevice,
446                          INT_STATUS_ENABLE_ADDRESS,
447                          pIOPacket->pBuffer,
448                          AR6K_IRQ_ENABLE_REGS_SIZE,
449                          HIF_WR_ASYNC_BYTE_INC,
450                          pIOPacket);
451             break;
452         }
453
454         /* if we get here we are doing it synchronously */
455
456         status = HIFReadWrite(pDev->HIFDevice,
457                               INT_STATUS_ENABLE_ADDRESS,
458                               &regs.int_status_enable,
459                               AR6K_IRQ_ENABLE_REGS_SIZE,
460                               HIF_WR_SYNC_BYTE_INC,
461                               NULL);
462
463     } while (FALSE);
464
465     if (A_FAILED(status) && (pIOPacket != NULL)) {
466         AR6KFreeIOPacket(pDev,pIOPacket);
467     }
468
469     return status;
470 }
471
472
473 A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
474 {
475     if (NULL == pDev->HifMaskUmaskRecvEvent) {
476         return DevDoEnableDisableRecvNormal(pDev,FALSE,AsyncMode);
477     } else {
478         return DevDoEnableDisableRecvOverride(pDev,FALSE,AsyncMode);
479     }
480 }
481
482 A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
483 {
484     if (NULL == pDev->HifMaskUmaskRecvEvent) {
485         return DevDoEnableDisableRecvNormal(pDev,TRUE,AsyncMode);
486     } else {
487         return DevDoEnableDisableRecvOverride(pDev,TRUE,AsyncMode);
488     }
489 }
490
491 A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending)
492 {
493     A_STATUS    status          = A_OK;
494     A_UCHAR     host_int_status = 0x0;
495     A_UINT32    counter         = 0x0;
496
497     if(TimeoutInMs < 100)
498     {
499         TimeoutInMs = 100;
500     }
501
502     counter = TimeoutInMs / 100;
503
504     do
505     {
506         //Read the Host Interrupt Status Register
507         status = HIFReadWrite(pDev->HIFDevice,
508                               HOST_INT_STATUS_ADDRESS,
509                              &host_int_status,
510                               sizeof(A_UCHAR),
511                               HIF_RD_SYNC_BYTE_INC,
512                               NULL);
513         if(A_FAILED(status))
514         {
515             AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status));
516             break;
517         }
518
519         host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)):0;
520         if(!host_int_status)
521         {
522             status          = A_OK;
523            *pbIsRecvPending = FALSE;
524             break;
525         }
526         else
527         {
528             *pbIsRecvPending = TRUE;
529         }
530
531         A_MDELAY(100);
532
533         counter--;
534
535     }while(counter);
536     return status;
537 }
538
539 void DevDumpRegisters(AR6K_DEVICE               *pDev,
540                       AR6K_IRQ_PROC_REGISTERS   *pIrqProcRegs,
541                       AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs)
542 {
543
544     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\n<------- Register Table -------->\n"));
545
546     if (pIrqProcRegs != NULL) {
547         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
548             ("Host Int Status:           0x%x\n",pIrqProcRegs->host_int_status));
549         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
550             ("CPU Int Status:            0x%x\n",pIrqProcRegs->cpu_int_status));
551         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
552             ("Error Int Status:          0x%x\n",pIrqProcRegs->error_int_status));
553         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
554             ("Counter Int Status:        0x%x\n",pIrqProcRegs->counter_int_status));
555         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
556             ("Mbox Frame:                0x%x\n",pIrqProcRegs->mbox_frame));
557         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
558             ("Rx Lookahead Valid:        0x%x\n",pIrqProcRegs->rx_lookahead_valid));
559         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
560             ("Rx Lookahead 0:            0x%x\n",pIrqProcRegs->rx_lookahead[0]));
561         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
562             ("Rx Lookahead 1:            0x%x\n",pIrqProcRegs->rx_lookahead[1]));
563
564         if (pDev->MailBoxInfo.GMboxAddress != 0) {
565                 /* if the target supports GMBOX hardware, dump some additional state */
566             AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
567                 ("GMBOX Host Int Status 2:   0x%x\n",pIrqProcRegs->host_int_status2));
568             AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
569                 ("GMBOX RX Avail:            0x%x\n",pIrqProcRegs->gmbox_rx_avail));
570             AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
571                 ("GMBOX lookahead alias 0:   0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[0]));
572             AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
573                 ("GMBOX lookahead alias 1:   0x%x\n",pIrqProcRegs->rx_gmbox_lookahead_alias[1]));
574         }
575
576     }
577
578     if (pIrqEnableRegs != NULL) {
579         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
580             ("Int Status Enable:         0x%x\n",pIrqEnableRegs->int_status_enable));
581         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
582             ("Counter Int Status Enable: 0x%x\n",pIrqEnableRegs->counter_int_status_enable));
583     }
584     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<------------------------------->\n"));
585 }
586
587
588 #define DEV_GET_VIRT_DMA_INFO(p)  ((DEV_SCATTER_DMA_VIRTUAL_INFO *)((p)->HIFPrivate[0]))
589
590 static HIF_SCATTER_REQ *DevAllocScatterReq(HIF_DEVICE *Context)
591 {
592     DL_LIST *pItem;
593     AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
594     LOCK_AR6K(pDev);
595     pItem = DL_ListRemoveItemFromHead(&pDev->ScatterReqHead);
596     UNLOCK_AR6K(pDev);
597     if (pItem != NULL) {
598         return A_CONTAINING_STRUCT(pItem, HIF_SCATTER_REQ, ListLink);
599     }
600     return NULL;
601 }
602
603 static void DevFreeScatterReq(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
604 {
605     AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
606     LOCK_AR6K(pDev);
607     DL_ListInsertTail(&pDev->ScatterReqHead, &pReq->ListLink);
608     UNLOCK_AR6K(pDev);
609 }
610
611 A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA)
612 {
613     A_UINT8         *pDMABuffer = NULL;
614     int             i, remaining;
615     A_UINT32        length;
616
617     pDMABuffer = pReq->pScatterBounceBuffer;
618
619     if (pDMABuffer == NULL) {
620         A_ASSERT(FALSE);
621         return A_EINVAL;
622     }
623
624     remaining = (int)pReq->TotalLength;
625
626     for (i = 0; i < pReq->ValidScatterEntries; i++) {
627
628         length = min((int)pReq->ScatterList[i].Length, remaining);
629
630         if (length != (int)pReq->ScatterList[i].Length) {
631             A_ASSERT(FALSE);
632                 /* there is a problem with the scatter list */
633             return A_EINVAL;
634         }
635
636         if (FromDMA) {
637                 /* from DMA buffer */
638             A_MEMCPY(pReq->ScatterList[i].pBuffer, pDMABuffer , length);
639         } else {
640                 /* to DMA buffer */
641             A_MEMCPY(pDMABuffer, pReq->ScatterList[i].pBuffer, length);
642         }
643
644         pDMABuffer += length;
645         remaining -= length;
646     }
647
648     return A_OK;
649 }
650
651 static void DevReadWriteScatterAsyncHandler(void *Context, HTC_PACKET *pPacket)
652 {
653     AR6K_DEVICE     *pDev = (AR6K_DEVICE *)Context;
654     HIF_SCATTER_REQ *pReq = (HIF_SCATTER_REQ *)pPacket->pPktContext;
655     
656     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevReadWriteScatterAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
657     
658     pReq->CompletionStatus = pPacket->Status;
659
660     AR6KFreeIOPacket(pDev,pPacket);
661
662     pReq->CompletionRoutine(pReq);
663
664     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevReadWriteScatterAsyncHandler \n"));
665 }
666
667 static A_STATUS DevReadWriteScatter(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
668 {
669     AR6K_DEVICE     *pDev = (AR6K_DEVICE *)Context;
670     A_STATUS        status = A_OK;
671     HTC_PACKET      *pIOPacket = NULL;
672     A_UINT32        request = pReq->Request;
673
674     do {
675
676         if (pReq->TotalLength > AR6K_MAX_TRANSFER_SIZE_PER_SCATTER) {
677             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
678                             ("Invalid length: %d \n", pReq->TotalLength));
679             break;
680         }
681
682         if (pReq->TotalLength == 0) {
683             A_ASSERT(FALSE);
684             break;
685         }
686
687         if (request & HIF_ASYNCHRONOUS) {
688                 /* use an I/O packet to carry this request */
689             pIOPacket = AR6KAllocIOPacket(pDev);
690             if (NULL == pIOPacket) {
691                 status = A_NO_MEMORY;
692                 break;
693             }
694
695                 /* save the request */
696             pIOPacket->pPktContext = pReq;
697                 /* stick in our completion routine when the I/O operation completes */
698             pIOPacket->Completion = DevReadWriteScatterAsyncHandler;
699             pIOPacket->pContext = pDev;
700         }
701
702         if (request & HIF_WRITE) {
703             /* in virtual DMA, we are issuing the requests through the legacy HIFReadWrite API
704              * this API will adjust the address automatically for the last byte to fall on the mailbox
705              * EOM. */
706
707             /* if the address is an extended address, we can adjust the address here since the extended
708              * address will bypass the normal checks in legacy HIF layers */
709             if (pReq->Address == pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress) {
710                 pReq->Address += pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize - pReq->TotalLength;
711             }
712         }
713
714             /* use legacy readwrite */
715         status = HIFReadWrite(pDev->HIFDevice,
716                               pReq->Address,
717                               DEV_GET_VIRT_DMA_INFO(pReq)->pVirtDmaBuffer,
718                               pReq->TotalLength,
719                               request,
720                               (request & HIF_ASYNCHRONOUS) ? pIOPacket : NULL);
721
722     } while (FALSE);
723
724     if ((status != A_PENDING) && A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
725         if (pIOPacket != NULL) {
726             AR6KFreeIOPacket(pDev,pIOPacket);
727         }
728         pReq->CompletionStatus = status;
729         pReq->CompletionRoutine(pReq);
730         status = A_OK;
731     }
732
733     return status;
734 }
735
736
737 static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev)
738 {
739     HIF_SCATTER_REQ *pReq;
740
741     while (1) {
742         pReq = DevAllocScatterReq((HIF_DEVICE *)pDev);
743         if (NULL == pReq) {
744             break;
745         }
746         A_FREE(pReq);
747     }
748
749 }
750
751     /* function to set up virtual scatter support if HIF layer has not implemented the interface */
752 static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
753 {
754     A_STATUS                     status = A_OK;
755     int                          bufferSize, sgreqSize;
756     int                          i;
757     DEV_SCATTER_DMA_VIRTUAL_INFO *pVirtualInfo;
758     HIF_SCATTER_REQ              *pReq;
759
760     bufferSize = sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO) +
761                 2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
762
763     sgreqSize = sizeof(HIF_SCATTER_REQ) +
764                     (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM));
765
766     for (i = 0; i < AR6K_SCATTER_REQS; i++) {
767             /* allocate the scatter request, buffer info and the actual virtual buffer itself */
768         pReq = (HIF_SCATTER_REQ *)A_MALLOC(sgreqSize + bufferSize);
769
770         if (NULL == pReq) {
771             status = A_NO_MEMORY;
772             break;
773         }
774
775         A_MEMZERO(pReq, sgreqSize);
776
777             /* the virtual DMA starts after the scatter request struct */
778         pVirtualInfo = (DEV_SCATTER_DMA_VIRTUAL_INFO *)((A_UINT8 *)pReq + sgreqSize);
779         A_MEMZERO(pVirtualInfo, sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO));
780
781         pVirtualInfo->pVirtDmaBuffer = &pVirtualInfo->DataArea[0];
782             /* align buffer to cache line in case host controller can actually DMA this */
783         pVirtualInfo->pVirtDmaBuffer = A_ALIGN_TO_CACHE_LINE(pVirtualInfo->pVirtDmaBuffer);
784             /* store the structure in the private area */
785         pReq->HIFPrivate[0] = pVirtualInfo;
786             /* we emulate a DMA bounce interface */
787         pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE;
788         pReq->pScatterBounceBuffer = pVirtualInfo->pVirtDmaBuffer;
789             /* free request to the list */
790         DevFreeScatterReq((HIF_DEVICE *)pDev,pReq);
791     }
792
793     if (A_FAILED(status)) {
794         DevCleanupVirtualScatterSupport(pDev);
795     } else {
796         pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq;
797         pDev->HifScatterInfo.pFreeReqFunc = DevFreeScatterReq;
798         pDev->HifScatterInfo.pReadWriteScatterFunc = DevReadWriteScatter;
799         if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) {
800             AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K: SPI bus requires RX scatter limits\n"));
801             pDev->HifScatterInfo.MaxScatterEntries = AR6K_MIN_SCATTER_ENTRIES_PER_REQ;
802             pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MIN_TRANSFER_SIZE_PER_SCATTER;
803         } else {
804             pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ;
805             pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
806         }
807         pDev->ScatterIsVirtual = TRUE;
808     }
809
810     return status;
811 }
812
813
814 A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer)
815 {
816     A_STATUS status;
817
818     if (pDev->MailBoxInfo.Flags & HIF_MBOX_FLAG_NO_BUNDLING) {
819         AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n"));
820         return A_ENOTSUP;
821     }
822
823     status = HIFConfigureDevice(pDev->HIFDevice,
824                                 HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT,
825                                 &pDev->HifScatterInfo,
826                                 sizeof(pDev->HifScatterInfo));
827
828     if (A_FAILED(status)) {
829         AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
830             ("AR6K: ** HIF layer does not support scatter requests (%d) \n",status));
831
832             /* we can try to use a virtual DMA scatter mechanism using legacy HIFReadWrite() */
833         status = DevSetupVirtualScatterSupport(pDev);
834
835         if (A_SUCCESS(status)) {
836              AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
837                 ("AR6K: virtual scatter transfers enabled (max scatter items:%d: maxlen:%d) \n",
838                     DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
839         }
840
841     } else {
842         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
843             ("AR6K: HIF layer supports scatter requests (max scatter items:%d: maxlen:%d) \n",
844                     DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
845     }
846
847     if (A_SUCCESS(status)) {
848             /* for the recv path, the maximum number of bytes per recv bundle is just limited
849              * by the maximum transfer size at the HIF layer */
850         pDev->MaxRecvBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
851
852         if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) {
853             AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K : SPI bus requires TX bundling disabled\n"));
854             pDev->MaxSendBundleSize = 0;
855         } else {
856                 /* for the send path, the max transfer size is limited by the existence and size of
857                  * the extended mailbox address range */
858             if (pDev->MailBoxInfo.MboxProp[0].ExtendedAddress != 0) {
859                 pDev->MaxSendBundleSize = pDev->MailBoxInfo.MboxProp[0].ExtendedSize;
860             } else {
861                     /* legacy */
862                 pDev->MaxSendBundleSize = AR6K_LEGACY_MAX_WRITE_LENGTH;
863             }
864
865             if (pDev->MaxSendBundleSize > pDev->HifScatterInfo.MaxTransferSizePerScatterReq) {
866                     /* limit send bundle size to what the HIF can support for scatter requests */
867                 pDev->MaxSendBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
868             }
869         }
870
871         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
872             ("AR6K: max recv: %d max send: %d \n",
873                     DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev), DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)));
874
875     }
876     return status;
877 }
878
879 A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async)
880 {
881     A_STATUS status;
882
883     if (Read) {
884             /* read operation */
885         pScatterReq->Request = (Async) ? HIF_RD_ASYNC_BLOCK_FIX : HIF_RD_SYNC_BLOCK_FIX;
886         pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
887         A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev));
888     } else {
889         A_UINT32 mailboxWidth;
890
891             /* write operation */
892         pScatterReq->Request = (Async) ? HIF_WR_ASYNC_BLOCK_INC : HIF_WR_SYNC_BLOCK_INC;
893         A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev));
894         if (pScatterReq->TotalLength > AR6K_LEGACY_MAX_WRITE_LENGTH) {
895                 /* for large writes use the extended address */
896             pScatterReq->Address = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress;
897             mailboxWidth = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedSize;
898         } else {
899             pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
900             mailboxWidth = AR6K_LEGACY_MAX_WRITE_LENGTH;
901         }
902
903         if (!pDev->ScatterIsVirtual) {
904             /* we are passing this scatter list down to the HIF layer' scatter request handler, fixup the address
905              * so that the last byte falls on the EOM, we do this for those HIFs that support the
906              * scatter API */
907             pScatterReq->Address += (mailboxWidth - pScatterReq->TotalLength);
908         }
909
910     }
911
912     AR_DEBUG_PRINTF(ATH_DEBUG_RECV | ATH_DEBUG_SEND,
913                 ("DevSubmitScatterRequest, Entries: %d, Total Length: %d Mbox:0x%X (mode: %s : %s)\n",
914                 pScatterReq->ValidScatterEntries,
915                 pScatterReq->TotalLength,
916                 pScatterReq->Address,
917                 Async ? "ASYNC" : "SYNC",
918                 (Read) ? "RD" : "WR"));
919
920     status = DEV_PREPARE_SCATTER_OPERATION(pScatterReq);
921
922     if (A_FAILED(status)) {
923         if (Async) {
924             pScatterReq->CompletionStatus = status;
925             pScatterReq->CompletionRoutine(pScatterReq);
926             return A_OK;
927         }
928         return status;
929     }
930
931     status = pDev->HifScatterInfo.pReadWriteScatterFunc(pDev->ScatterIsVirtual ? pDev : pDev->HIFDevice,
932                                                         pScatterReq);
933     if (!Async) {
934             /* in sync mode, we can touch the scatter request */
935         pScatterReq->CompletionStatus = status;
936         DEV_FINISH_SCATTER_OPERATION(pScatterReq);
937     } else {
938         if (status == A_PENDING) {
939             status = A_OK;
940         }
941     }
942
943     return status;
944 }
945
946
947 #ifdef MBOXHW_UNIT_TEST
948
949
950 /* This is a mailbox hardware unit test that must be called in a schedulable context
951  * This test is very simple, it will send a list of buffers with a counting pattern
952  * and the target will invert the data and send the message back
953  *
954  * the unit test has the following constraints:
955  *
956  * The target has at least 8 buffers of 256 bytes each. The host will send
957  * the following pattern of buffers in rapid succession :
958  *
959  * 1 buffer - 128 bytes
960  * 1 buffer - 256 bytes
961  * 1 buffer - 512 bytes
962  * 1 buffer - 1024 bytes
963  *
964  * The host will send the buffers to one mailbox and wait for buffers to be reflected
965  * back from the same mailbox. The target sends the buffers FIFO order.
966  * Once the final buffer has been received for a mailbox, the next mailbox is tested.
967  *
968  *
969  * Note:  To simplifythe test , we assume that the chosen buffer sizes
970  *        will fall on a nice block pad
971  *
972  * It is expected that higher-order tests will be written to stress the mailboxes using
973  * a message-based protocol (with some performance timming) that can create more
974  * randomness in the packets sent over mailboxes.
975  *
976  * */
977
978 #define A_ROUND_UP_PWR2(x, align)    (((int) (x) + ((align)-1)) & ~((align)-1))
979
980 #define BUFFER_BLOCK_PAD 128
981
982 #if 0
983 #define BUFFER1 128
984 #define BUFFER2 256
985 #define BUFFER3 512
986 #define BUFFER4 1024
987 #endif
988
989 #if 1
990 #define BUFFER1 80
991 #define BUFFER2 200
992 #define BUFFER3 444
993 #define BUFFER4 800
994 #endif
995
996 #define TOTAL_BYTES (A_ROUND_UP_PWR2(BUFFER1,BUFFER_BLOCK_PAD) + \
997                      A_ROUND_UP_PWR2(BUFFER2,BUFFER_BLOCK_PAD) + \
998                      A_ROUND_UP_PWR2(BUFFER3,BUFFER_BLOCK_PAD) + \
999                      A_ROUND_UP_PWR2(BUFFER4,BUFFER_BLOCK_PAD) )
1000
1001 #define TEST_BYTES (BUFFER1 +  BUFFER2 + BUFFER3 + BUFFER4)
1002
1003 #define TEST_CREDITS_RECV_TIMEOUT 100
1004
1005 static A_UINT8  g_Buffer[TOTAL_BYTES];
1006 static A_UINT32 g_MailboxAddrs[AR6K_MAILBOXES];
1007 static A_UINT32 g_BlockSizes[AR6K_MAILBOXES];
1008
1009 #define BUFFER_PROC_LIST_DEPTH 4
1010
1011 typedef struct _BUFFER_PROC_LIST{
1012     A_UINT8  *pBuffer;
1013     A_UINT32 length;
1014 }BUFFER_PROC_LIST;
1015
1016
1017 #define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \
1018 {                                                   \
1019     (pList)->pBuffer = (pCurrpos);                  \
1020     (pList)->length = (len);                        \
1021     (pCurrpos) += (len);                            \
1022     (pList)++;                                      \
1023 }
1024
1025 /* a simple and crude way to send different "message" sizes */
1026 static void AssembleBufferList(BUFFER_PROC_LIST *pList)
1027 {
1028     A_UINT8 *pBuffer = g_Buffer;
1029
1030 #if BUFFER_PROC_LIST_DEPTH < 4
1031 #error "Buffer processing list depth is not deep enough!!"
1032 #endif
1033
1034     PUSH_BUFF_PROC_ENTRY(pList,BUFFER1,pBuffer);
1035     PUSH_BUFF_PROC_ENTRY(pList,BUFFER2,pBuffer);
1036     PUSH_BUFF_PROC_ENTRY(pList,BUFFER3,pBuffer);
1037     PUSH_BUFF_PROC_ENTRY(pList,BUFFER4,pBuffer);
1038
1039 }
1040
1041 #define FILL_ZERO     TRUE
1042 #define FILL_COUNTING FALSE
1043 static void InitBuffers(A_BOOL Zero)
1044 {
1045     A_UINT16 *pBuffer16 = (A_UINT16 *)g_Buffer;
1046     int      i;
1047
1048         /* fill buffer with 16 bit counting pattern or zeros */
1049     for (i = 0; i <  (TOTAL_BYTES / 2) ; i++) {
1050         if (!Zero) {
1051             pBuffer16[i] = (A_UINT16)i;
1052         } else {
1053             pBuffer16[i] = 0;
1054         }
1055     }
1056 }
1057
1058
1059 static A_BOOL CheckOneBuffer(A_UINT16 *pBuffer16, int Length)
1060 {
1061     int      i;
1062     A_UINT16 startCount;
1063     A_BOOL   success = TRUE;
1064
1065         /* get the starting count */
1066     startCount = pBuffer16[0];
1067         /* invert it, this is the expected value */
1068     startCount = ~startCount;
1069         /* scan the buffer and verify */
1070     for (i = 0; i < (Length / 2) ; i++,startCount++) {
1071             /* target will invert all the data */
1072         if ((A_UINT16)pBuffer16[i] != (A_UINT16)~startCount) {
1073             success = FALSE;
1074             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Data Got:0x%X, Expecting:0x%X (offset:%d, total:%d) \n",
1075                         pBuffer16[i], ((A_UINT16)~startCount), i, Length));
1076              AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("0x%X 0x%X 0x%X 0x%X \n",
1077                         pBuffer16[i], pBuffer16[i + 1], pBuffer16[i + 2],pBuffer16[i+3]));
1078             break;
1079         }
1080     }
1081
1082     return success;
1083 }
1084
1085 static A_BOOL CheckBuffers(void)
1086 {
1087     int      i;
1088     A_BOOL   success = TRUE;
1089     BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
1090
1091         /* assemble the list */
1092     AssembleBufferList(checkList);
1093
1094         /* scan the buffers and verify */
1095     for (i = 0; i < BUFFER_PROC_LIST_DEPTH ; i++) {
1096         success = CheckOneBuffer((A_UINT16 *)checkList[i].pBuffer, checkList[i].length);
1097         if (!success) {
1098             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n",
1099                         (A_UINT32)checkList[i].pBuffer, checkList[i].length));
1100             break;
1101         }
1102     }
1103
1104     return success;
1105 }
1106
1107     /* find the end marker for the last buffer we will be sending */
1108 static A_UINT16 GetEndMarker(void)
1109 {
1110     A_UINT8  *pBuffer;
1111     BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
1112
1113         /* fill up buffers with the normal counting pattern */
1114     InitBuffers(FILL_COUNTING);
1115
1116         /* assemble the list we will be sending down */
1117     AssembleBufferList(checkList);
1118         /* point to the last 2 bytes of the last buffer */
1119     pBuffer = &(checkList[BUFFER_PROC_LIST_DEPTH - 1].pBuffer[(checkList[BUFFER_PROC_LIST_DEPTH - 1].length) - 2]);
1120
1121         /* the last count in the last buffer is the marker */
1122     return (A_UINT16)pBuffer[0] | ((A_UINT16)pBuffer[1] << 8);
1123 }
1124
1125 #define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR
1126
1127 /* send the ordered buffers to the target */
1128 static A_STATUS SendBuffers(AR6K_DEVICE *pDev, int mbox)
1129 {
1130     A_STATUS         status = A_OK;
1131     A_UINT32         request = HIF_WR_SYNC_BLOCK_INC;
1132     BUFFER_PROC_LIST sendList[BUFFER_PROC_LIST_DEPTH];
1133     int              i;
1134     int              totalBytes = 0;
1135     int              paddedLength;
1136     int              totalwPadding = 0;
1137
1138     AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sending buffers on mailbox : %d \n",mbox));
1139
1140         /* fill buffer with counting pattern */
1141     InitBuffers(FILL_COUNTING);
1142
1143         /* assemble the order in which we send */
1144     AssembleBufferList(sendList);
1145
1146     for (i = 0; i < BUFFER_PROC_LIST_DEPTH; i++) {
1147
1148             /* we are doing block transfers, so we need to pad everything to a block size */
1149         paddedLength = (sendList[i].length + (g_BlockSizes[mbox] - 1)) &
1150                        (~(g_BlockSizes[mbox] - 1));
1151
1152             /* send each buffer synchronously */
1153         status = HIFReadWrite(pDev->HIFDevice,
1154                               g_MailboxAddrs[mbox],
1155                               sendList[i].pBuffer,
1156                               paddedLength,
1157                               request,
1158                               NULL);
1159         if (status != A_OK) {
1160             break;
1161         }
1162         totalBytes += sendList[i].length;
1163         totalwPadding += paddedLength;
1164     }
1165
1166     AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sent %d bytes (%d padded bytes) to mailbox : %d \n",totalBytes,totalwPadding,mbox));
1167
1168     return status;
1169 }
1170
1171 /* poll the mailbox credit counter until we get a credit or timeout */
1172 static A_STATUS GetCredits(AR6K_DEVICE *pDev, int mbox, int *pCredits)
1173 {
1174     A_STATUS status = A_OK;
1175     int      timeout = TEST_CREDITS_RECV_TIMEOUT;
1176     A_UINT8  credits = 0;
1177     A_UINT32 address;
1178
1179     while (TRUE) {
1180
1181             /* Read the counter register to get credits, this auto-decrements  */
1182         address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4;
1183         status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits),
1184                               HIF_RD_SYNC_BYTE_FIX, NULL);
1185         if (status != A_OK) {
1186             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1187                 ("Unable to decrement the command credit count register (mbox=%d)\n",mbox));
1188             status = A_ERROR;
1189             break;
1190         }
1191
1192         if (credits) {
1193             break;
1194         }
1195
1196         timeout--;
1197
1198         if (timeout <= 0) {
1199               AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
1200                 (" Timeout reading credit registers (mbox=%d, address:0x%X) \n",mbox,address));
1201             status = A_ERROR;
1202             break;
1203         }
1204
1205          /* delay a little, target may not be ready */
1206          A_MDELAY(1000);
1207
1208     }
1209
1210     if (status == A_OK) {
1211         *pCredits = credits;
1212     }
1213
1214     return status;
1215 }
1216
1217
1218 /* wait for the buffers to come back */
1219 static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
1220 {
1221     A_STATUS         status = A_OK;
1222     A_UINT32         request = HIF_RD_SYNC_BLOCK_INC;
1223     BUFFER_PROC_LIST recvList[BUFFER_PROC_LIST_DEPTH];
1224     int              curBuffer;
1225     int              credits;
1226     int              i;
1227     int              totalBytes = 0;
1228     int              paddedLength;
1229     int              totalwPadding = 0;
1230
1231     AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for buffers on mailbox : %d \n",mbox));
1232
1233         /* zero the buffers */
1234     InitBuffers(FILL_ZERO);
1235
1236         /* assemble the order in which we should receive */
1237     AssembleBufferList(recvList);
1238
1239     curBuffer = 0;
1240
1241     while (curBuffer < BUFFER_PROC_LIST_DEPTH) {
1242
1243             /* get number of buffers that have been completed, this blocks
1244              * until we get at least 1 credit or it times out */
1245         status = GetCredits(pDev, mbox, &credits);
1246
1247         if (status != A_OK) {
1248             break;
1249         }
1250
1251         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got %d messages on mailbox : %d \n",credits, mbox));
1252
1253             /* get all the buffers that are sitting on the queue */
1254         for (i = 0; i < credits; i++) {
1255             A_ASSERT(curBuffer < BUFFER_PROC_LIST_DEPTH);
1256                 /* recv the current buffer synchronously, the buffers should come back in
1257                  * order... with padding applied by the target */
1258             paddedLength = (recvList[curBuffer].length + (g_BlockSizes[mbox] - 1)) &
1259                        (~(g_BlockSizes[mbox] - 1));
1260
1261             status = HIFReadWrite(pDev->HIFDevice,
1262                                   g_MailboxAddrs[mbox],
1263                                   recvList[curBuffer].pBuffer,
1264                                   paddedLength,
1265                                   request,
1266                                   NULL);
1267             if (status != A_OK) {
1268                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to read %d bytes on mailbox:%d : address:0x%X \n",
1269                         recvList[curBuffer].length, mbox, g_MailboxAddrs[mbox]));
1270                 break;
1271             }
1272
1273             totalwPadding += paddedLength;
1274             totalBytes += recvList[curBuffer].length;
1275             curBuffer++;
1276         }
1277
1278         if (status != A_OK) {
1279             break;
1280         }
1281             /* go back and get some more */
1282         credits = 0;
1283     }
1284
1285     if (totalBytes != TEST_BYTES) {
1286         A_ASSERT(FALSE);
1287     }  else {
1288         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got all buffers on mbox:%d total recv :%d (w/Padding : %d) \n",
1289             mbox, totalBytes, totalwPadding));
1290     }
1291
1292     return status;
1293
1294
1295 }
1296
1297 static A_STATUS DoOneMboxHWTest(AR6K_DEVICE *pDev, int mbox)
1298 {
1299     A_STATUS status;
1300
1301     do {
1302             /* send out buffers */
1303         status = SendBuffers(pDev,mbox);
1304
1305         if (status != A_OK) {
1306             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox));
1307             break;
1308         }
1309
1310             /* go get them, this will block */
1311         status =  RecvBuffers(pDev, mbox);
1312
1313         if (status != A_OK) {
1314             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox));
1315             break;
1316         }
1317
1318             /* check the returned data patterns */
1319         if (!CheckBuffers()) {
1320             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer Verify Failed : mbox:%d\n",mbox));
1321             status = A_ERROR;
1322             break;
1323         }
1324
1325         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox));
1326
1327     }  while (FALSE);
1328
1329     return status;
1330 }
1331
1332 /* here is where the test starts */
1333 A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
1334 {
1335     int      i;
1336     A_STATUS status;
1337     int      credits = 0;
1338     A_UINT8  params[4];
1339     int      numBufs;
1340     int      bufferSize;
1341     A_UINT16 temp;
1342
1343
1344     AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START -  \n"));
1345
1346     do {
1347             /* get the addresses for all 4 mailboxes */
1348         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
1349                                     g_MailboxAddrs, sizeof(g_MailboxAddrs));
1350
1351         if (status != A_OK) {
1352             A_ASSERT(FALSE);
1353             break;
1354         }
1355
1356             /* get the block sizes */
1357         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
1358                                     g_BlockSizes, sizeof(g_BlockSizes));
1359
1360         if (status != A_OK) {
1361             A_ASSERT(FALSE);
1362             break;
1363         }
1364
1365             /* note, the HIF layer usually reports mbox 0 to have a block size of
1366              * 1, but our test wants to run in block-mode for all mailboxes, so we treat all mailboxes
1367              * the same. */
1368         g_BlockSizes[0] = g_BlockSizes[1];
1369         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Block Size to use: %d \n",g_BlockSizes[0]));
1370
1371         if (g_BlockSizes[1] > BUFFER_BLOCK_PAD) {
1372             AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("%d Block size is too large for buffer pad %d\n",
1373                 g_BlockSizes[1], BUFFER_BLOCK_PAD));
1374             break;
1375         }
1376
1377         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for target.... \n"));
1378
1379             /* the target lets us know it is ready by giving us 1 credit on
1380              * mailbox 0 */
1381         status = GetCredits(pDev, 0, &credits);
1382
1383         if (status != A_OK) {
1384             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n"));
1385             break;
1386         }
1387
1388         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Target is ready ...\n"));
1389
1390             /* read the first 4 scratch registers */
1391         status = HIFReadWrite(pDev->HIFDevice,
1392                               SCRATCH_ADDRESS,
1393                               params,
1394                               4,
1395                               HIF_RD_SYNC_BYTE_INC,
1396                               NULL);
1397
1398         if (status != A_OK) {
1399             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n"));
1400             break;
1401         }
1402
1403         numBufs = params[0];
1404         bufferSize = (int)(((A_UINT16)params[2] << 8) | (A_UINT16)params[1]);
1405
1406         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE,
1407             ("Target parameters: bufs per mailbox:%d, buffer size:%d bytes (total space: %d, minimum required space (w/padding): %d) \n",
1408             numBufs, bufferSize, (numBufs * bufferSize), TOTAL_BYTES));
1409
1410         if ((numBufs * bufferSize) < TOTAL_BYTES) {
1411             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Not Enough buffer space to run test! need:%d, got:%d \n",
1412                 TOTAL_BYTES, (numBufs*bufferSize)));
1413             status = A_ERROR;
1414             break;
1415         }
1416
1417         temp = GetEndMarker();
1418
1419         status = HIFReadWrite(pDev->HIFDevice,
1420                               SCRATCH_ADDRESS + 4,
1421                               (A_UINT8 *)&temp,
1422                               2,
1423                               HIF_WR_SYNC_BYTE_INC,
1424                               NULL);
1425
1426         if (status != A_OK) {
1427             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n"));
1428             break;
1429         }
1430
1431         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp));
1432
1433         temp = (A_UINT16)g_BlockSizes[1];
1434             /* convert to a mask */
1435         temp = temp - 1;
1436         status = HIFReadWrite(pDev->HIFDevice,
1437                               SCRATCH_ADDRESS + 6,
1438                               (A_UINT8 *)&temp,
1439                               2,
1440                               HIF_WR_SYNC_BYTE_INC,
1441                               NULL);
1442
1443         if (status != A_OK) {
1444             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n"));
1445             break;
1446         }
1447
1448         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Set Block Mask: 0x%X \n",temp));
1449
1450             /* execute the test on each mailbox */
1451         for (i = 0; i < AR6K_MAILBOXES; i++) {
1452             status = DoOneMboxHWTest(pDev, i);
1453             if (status != A_OK) {
1454                 break;
1455             }
1456         }
1457
1458     } while (FALSE);
1459
1460     if (status == A_OK) {
1461         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! -  \n"));
1462     } else {
1463         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! -  \n"));
1464     }
1465         /* don't let HTC_Start continue, the target is actually not running any HTC code */
1466     return A_ERROR;
1467 }
1468 #endif
1469
1470
1471