Add ar6000 wireless driver.
[kernel.git] / drivers / ar6000 / bmi / bmi.c
1 /*
2  * Copyright (c) 2004-2007 Atheros Communications Inc.
3  * All rights reserved.
4  *
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License version 2 as
8  *  published by the Free Software Foundation;
9  *
10  *  Software distributed under the License is distributed on an "AS
11  *  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12  *  implied. See the License for the specific language governing
13  *  rights and limitations under the License.
14  *
15  *
16  *
17  */
18
19 #include "hif.h"
20 #include "bmi.h"
21 #include "htc_api.h"
22 #include "bmi_internal.h"
23
24 /*
25 Although we had envisioned BMI to run on top of HTC, this is not what the
26 final implementation boiled down to on dragon. Its a part of BSP and does
27 not use the HTC protocol either. On the host side, however, we were still
28 living with the original idea. I think the time has come to accept the truth
29 and separate it from HTC which has been carrying BMI's burden all this while.
30 It shall make HTC state machine relatively simpler
31 */
32
33 /* APIs visible to the driver */
34 void
35 BMIInit(void)
36 {
37     bmiDone = FALSE;
38 }
39
40 A_STATUS
41 BMIDone(HIF_DEVICE *device)
42 {
43     A_STATUS status;
44     A_UINT32 cid;
45
46     if (bmiDone) {
47         AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
48         return A_OK;
49     }
50
51     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
52     bmiDone = TRUE;
53     cid = BMI_DONE;
54
55     status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
56     if (status != A_OK) {
57         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
58         return A_ERROR;
59     }
60     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
61
62     return A_OK;
63 }
64
65 A_STATUS
66 BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
67 {
68     A_STATUS status;
69     A_UINT32 cid;
70
71     if (bmiDone) {
72         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
73         return A_ERROR;
74     }
75
76     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
77     cid = BMI_GET_TARGET_INFO;
78
79     status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
80     if (status != A_OK) {
81         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
82         return A_ERROR;
83     }
84
85     status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_ver,
86                                                 sizeof(targ_info->target_ver));
87     if (status != A_OK) {
88         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
89         return A_ERROR;
90     }
91
92     if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
93         /* Determine how many bytes are in the Target's targ_info */
94         status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_info_byte_count,
95                                             sizeof(targ_info->target_info_byte_count));
96         if (status != A_OK) {
97             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
98             return A_ERROR;
99         }
100
101         /*
102          * The Target's targ_info doesn't match the Host's targ_info.
103          * We need to do some backwards compatibility work to make this OK.
104          */
105         A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
106
107         /* Read the remainder of the targ_info */
108         status = bmiBufferReceive(device,
109                         ((A_UCHAR *)targ_info)+sizeof(targ_info->target_info_byte_count),
110                         sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count));
111         if (status != A_OK) {
112             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
113                                                                 targ_info->target_info_byte_count));
114             return A_ERROR;
115         }
116     } else {
117         /*
118          * Target must be an AR6001 whose firmware does not
119          * support BMI_GET_TARGET_INFO.  Construct the data
120          * that it would have sent.
121          */
122         targ_info->target_info_byte_count = sizeof(targ_info);
123         targ_info->target_type = TARGET_TYPE_AR6001;
124     }
125
126     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
127                                                                 targ_info->target_ver, targ_info->target_type));
128     printk("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
129            targ_info->target_ver, targ_info->target_type);
130
131     return A_OK;
132 }
133
134 A_STATUS
135 BMIReadMemory(HIF_DEVICE *device,
136               A_UINT32 address,
137               A_UCHAR *buffer,
138               A_UINT32 length)
139 {
140     A_UINT32 cid;
141     A_STATUS status;
142     A_UINT32 offset;
143     A_UINT32 remaining, rxlen;
144     static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)];
145     memset (&data, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
146
147     if (bmiDone) {
148         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
149         return A_ERROR;
150     }
151
152     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
153                         ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
154                                 device, address, length));
155
156     cid = BMI_READ_MEMORY;
157
158     remaining = length;
159
160     while (remaining)
161     {
162         rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
163         offset = 0;
164         A_MEMCPY(&data[offset], &cid, sizeof(cid));
165         offset += sizeof(cid);
166         A_MEMCPY(&data[offset], &address, sizeof(address));
167         offset += sizeof(address);
168         A_MEMCPY(&data[offset], &rxlen, sizeof(rxlen));
169         offset += sizeof(length);
170
171         status = bmiBufferSend(device, data, offset);
172         if (status != A_OK) {
173             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
174             return A_ERROR;
175         }
176         status = bmiBufferReceive(device, data, rxlen);
177         if (status != A_OK) {
178             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
179             return A_ERROR;
180         }
181         A_MEMCPY(&buffer[length - remaining], data, rxlen);
182         remaining -= rxlen; address += rxlen;
183     }
184
185     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
186     return A_OK;
187 }
188
189 A_STATUS
190 BMIWriteMemory(HIF_DEVICE *device,
191                A_UINT32 address,
192                A_UCHAR *buffer,
193                A_UINT32 length)
194 {
195     A_UINT32 cid;
196     A_STATUS status;
197     A_UINT32 offset;
198     A_UINT32 remaining, txlen;
199     const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length);
200     static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)];
201         memset (&data, 0, header);
202
203     if (bmiDone) {
204         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
205         return A_ERROR;
206     }
207
208     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
209          ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
210          device, address, length));
211
212     cid = BMI_WRITE_MEMORY;
213
214     remaining = length;
215     while (remaining)
216     {
217         txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
218                                        remaining : (BMI_DATASZ_MAX - header);
219         offset = 0;
220         A_MEMCPY(&data[offset], &cid, sizeof(cid));
221         offset += sizeof(cid);
222         A_MEMCPY(&data[offset], &address, sizeof(address));
223         offset += sizeof(address);
224         A_MEMCPY(&data[offset], &txlen, sizeof(txlen));
225         offset += sizeof(txlen);
226         A_MEMCPY(&data[offset], &buffer[length - remaining], txlen);
227         offset += txlen;
228         status = bmiBufferSend(device, data, offset);
229         if (status != A_OK) {
230             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
231             return A_ERROR;
232         }
233         remaining -= txlen; address += txlen;
234     }
235
236     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
237
238     return A_OK;
239 }
240
241 A_STATUS
242 BMIExecute(HIF_DEVICE *device,
243            A_UINT32 address,
244            A_UINT32 *param)
245 {
246     A_UINT32 cid;
247     A_STATUS status;
248     A_UINT32 offset;
249     static A_UCHAR data[sizeof(cid) + sizeof(address) + sizeof(*param)];
250     memset (&data, 0, sizeof(cid) + sizeof(address) + sizeof(*param));
251
252     if (bmiDone) {
253         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
254         return A_ERROR;
255     }
256
257     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
258        ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
259         device, address, *param));
260
261     cid = BMI_EXECUTE;
262
263     offset = 0;
264     A_MEMCPY(&data[offset], &cid, sizeof(cid));
265     offset += sizeof(cid);
266     A_MEMCPY(&data[offset], &address, sizeof(address));
267     offset += sizeof(address);
268     A_MEMCPY(&data[offset], param, sizeof(*param));
269     offset += sizeof(*param);
270     status = bmiBufferSend(device, data, offset);
271     if (status != A_OK) {
272         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
273         return A_ERROR;
274     }
275
276     status = bmiBufferReceive(device, data, sizeof(*param));
277     if (status != A_OK) {
278         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
279         return A_ERROR;
280     }
281
282     A_MEMCPY(param, data, sizeof(*param));
283
284     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
285     return A_OK;
286 }
287
288 A_STATUS
289 BMISetAppStart(HIF_DEVICE *device,
290                A_UINT32 address)
291 {
292     A_UINT32 cid;
293     A_STATUS status;
294     A_UINT32 offset;
295     static A_UCHAR data[sizeof(cid) + sizeof(address)];
296     memset (&data, 0, sizeof(cid) + sizeof(address));
297
298     if (bmiDone) {
299         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
300         return A_ERROR;
301     }
302
303     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
304        ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
305         device, address));
306
307     cid = BMI_SET_APP_START;
308
309     offset = 0;
310     A_MEMCPY(&data[offset], &cid, sizeof(cid));
311     offset += sizeof(cid);
312     A_MEMCPY(&data[offset], &address, sizeof(address));
313     offset += sizeof(address);
314     status = bmiBufferSend(device, data, offset);
315     if (status != A_OK) {
316         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
317         return A_ERROR;
318     }
319
320     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
321     return A_OK;
322 }
323
324 A_STATUS
325 BMIReadSOCRegister(HIF_DEVICE *device,
326                    A_UINT32 address,
327                    A_UINT32 *param)
328 {
329     A_UINT32 cid;
330     A_STATUS status;
331     A_UINT32 offset;
332     static A_UCHAR data[sizeof(cid) + sizeof(address)];
333     memset (&data, 0, sizeof(cid) + sizeof(address));
334
335     if (bmiDone) {
336         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
337         return A_ERROR;
338     }
339
340     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
341        ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
342        device, address));
343
344     cid = BMI_READ_SOC_REGISTER;
345
346     offset = 0;
347     A_MEMCPY(&data[offset], &cid, sizeof(cid));
348     offset += sizeof(cid);
349     A_MEMCPY(&data[offset], &address, sizeof(address));
350     offset += sizeof(address);
351
352     status = bmiBufferSend(device, data, offset);
353     if (status != A_OK) {
354         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
355         return A_ERROR;
356     }
357
358     status = bmiBufferReceive(device, data, sizeof(*param));
359     if (status != A_OK) {
360         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
361         return A_ERROR;
362     }
363     A_MEMCPY(param, data, sizeof(*param));
364
365     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
366     return A_OK;
367 }
368
369 A_STATUS
370 BMIWriteSOCRegister(HIF_DEVICE *device,
371                     A_UINT32 address,
372                     A_UINT32 param)
373 {
374     A_UINT32 cid;
375     A_STATUS status;
376     A_UINT32 offset;
377     static A_UCHAR data[sizeof(cid) + sizeof(address) + sizeof(param)];
378
379     memset (&data, 0, sizeof(cid) + sizeof(address) + sizeof(param));
380
381     if (bmiDone) {
382         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
383         return A_ERROR;
384     }
385
386     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
387      ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
388      device, address, param));
389
390     cid = BMI_WRITE_SOC_REGISTER;
391
392     offset = 0;
393     A_MEMCPY(&data[offset], &cid, sizeof(cid));
394     offset += sizeof(cid);
395     A_MEMCPY(&data[offset], &address, sizeof(address));
396     offset += sizeof(address);
397     A_MEMCPY(&data[offset], &param, sizeof(param));
398     offset += sizeof(param);
399     status = bmiBufferSend(device, data, offset);
400     if (status != A_OK) {
401         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
402         return A_ERROR;
403     }
404
405     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
406     return A_OK;
407 }
408
409 A_STATUS
410 BMIrompatchInstall(HIF_DEVICE *device,
411                    A_UINT32 ROM_addr,
412                    A_UINT32 RAM_addr,
413                    A_UINT32 nbytes,
414                    A_UINT32 do_activate,
415                    A_UINT32 *rompatch_id)
416 {
417     A_UINT32 cid;
418     A_STATUS status;
419     A_UINT32 offset;
420     static A_UCHAR data[sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
421                                 sizeof(nbytes) + sizeof(do_activate)];
422
423         memset (&data, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
424                       sizeof(nbytes) + sizeof(do_activate));
425
426     if (bmiDone) {
427         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
428         return A_ERROR;
429     }
430
431     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
432          ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n",
433          device, ROM_addr, RAM_addr, nbytes, do_activate));
434
435     cid = BMI_ROMPATCH_INSTALL;
436
437     offset = 0;
438     A_MEMCPY(&data[offset], &cid, sizeof(cid));
439     offset += sizeof(cid);
440     A_MEMCPY(&data[offset], &ROM_addr, sizeof(ROM_addr));
441     offset += sizeof(ROM_addr);
442     A_MEMCPY(&data[offset], &RAM_addr, sizeof(RAM_addr));
443     offset += sizeof(RAM_addr);
444     A_MEMCPY(&data[offset], &nbytes, sizeof(nbytes));
445     offset += sizeof(nbytes);
446     A_MEMCPY(&data[offset], &do_activate, sizeof(do_activate));
447     offset += sizeof(do_activate);
448     status = bmiBufferSend(device, data, offset);
449     if (status != A_OK) {
450         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
451         return A_ERROR;
452     }
453
454     status = bmiBufferReceive(device, (A_UCHAR *)rompatch_id, sizeof(*rompatch_id));
455     if (status != A_OK) {
456         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
457         return A_ERROR;
458     }
459
460     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
461     return A_OK;
462 }
463
464 A_STATUS
465 BMIrompatchUninstall(HIF_DEVICE *device,
466                      A_UINT32 rompatch_id)
467 {
468     A_UINT32 cid;
469     A_STATUS status;
470     A_UINT32 offset;
471     static A_UCHAR data[sizeof(cid) + sizeof(rompatch_id)];
472     memset (&data, 0, sizeof(cid) + sizeof(rompatch_id));
473
474     if (bmiDone) {
475         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
476         return A_ERROR;
477     }
478
479     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
480          ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
481                                                                          device, rompatch_id));
482
483     cid = BMI_ROMPATCH_UNINSTALL;
484
485     offset = 0;
486     A_MEMCPY(&data[offset], &cid, sizeof(cid));
487     offset += sizeof(cid);
488     A_MEMCPY(&data[offset], &rompatch_id, sizeof(rompatch_id));
489     offset += sizeof(rompatch_id);
490     status = bmiBufferSend(device, data, offset);
491     if (status != A_OK) {
492         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
493         return A_ERROR;
494     }
495
496     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
497     return A_OK;
498 }
499
500 static A_STATUS
501 _BMIrompatchChangeActivation(HIF_DEVICE *device,
502                              A_UINT32 rompatch_count,
503                              A_UINT32 *rompatch_list,
504                              A_UINT32 do_activate)
505 {
506     A_UINT32 cid;
507     A_STATUS status;
508     A_UINT32 offset;
509     static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)];
510     A_UINT32 length;
511
512         memset (&data, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
513
514     if (bmiDone) {
515         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
516         return A_ERROR;
517     }
518
519     AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
520          ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
521            device, rompatch_count));
522
523     cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
524
525     offset = 0;
526     A_MEMCPY(&data[offset], &cid, sizeof(cid));
527     offset += sizeof(cid);
528     A_MEMCPY(&data[offset], &rompatch_count, sizeof(rompatch_count));
529     offset += sizeof(rompatch_count);
530     length = rompatch_count * sizeof(*rompatch_list);
531     A_MEMCPY(&data[offset], rompatch_list, length);
532     offset += length;
533     status = bmiBufferSend(device, data, offset);
534     if (status != A_OK) {
535         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
536         return A_ERROR;
537     }
538
539     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
540
541     return A_OK;
542 }
543
544 A_STATUS
545 BMIrompatchActivate(HIF_DEVICE *device,
546                     A_UINT32 rompatch_count,
547                     A_UINT32 *rompatch_list)
548 {
549     return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
550 }
551
552 A_STATUS
553 BMIrompatchDeactivate(HIF_DEVICE *device,
554                       A_UINT32 rompatch_count,
555                       A_UINT32 *rompatch_list)
556 {
557     return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
558 }
559
560 /* BMI Access routines */
561 A_STATUS
562 bmiBufferSend(HIF_DEVICE *device,
563               A_UCHAR *buffer,
564               A_UINT32 length)
565 {
566     A_STATUS status;
567     A_UINT32 timeout;
568     A_UINT32 address;
569     static A_UINT32 cmdCredits;
570     A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
571
572     HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
573                        &mboxAddress, sizeof(mboxAddress));
574
575     cmdCredits = 0;
576     timeout = BMI_COMMUNICATION_TIMEOUT;
577
578     while(timeout-- && !cmdCredits) {
579         /* Read the counter register to get the command credits */
580         address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
581         /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
582          * a decrement, while the remaining 3 bytes has no effect.  The rationale behind this is to
583          * make all HIF accesses 4-byte aligned */
584         status = HIFReadWrite(device, address, (A_UINT8 *)&cmdCredits, 4,
585             HIF_RD_SYNC_BYTE_INC, NULL);
586         if (status != A_OK) {
587             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
588             return A_ERROR;
589         }
590         /* the counter is only 8=bits, ignore anything in the upper 3 bytes */
591         cmdCredits &= 0xFF;
592     }
593
594     if (cmdCredits) {
595         address = mboxAddress[ENDPOINT1];
596         status = HIFReadWrite(device, address, buffer, length,
597             HIF_WR_SYNC_BYTE_INC, NULL);
598         if (status != A_OK) {
599             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
600             return A_ERROR;
601         }
602     } else {
603         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout\n"));
604         return A_ERROR;
605     }
606
607     return status;
608 }
609
610 A_STATUS
611 bmiBufferReceive(HIF_DEVICE *device,
612                  A_UCHAR *buffer,
613                  A_UINT32 length)
614 {
615     A_STATUS status;
616     A_UINT32 address;
617     A_UINT32 timeout;
618     static A_UINT32 cmdCredits;
619     A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
620
621     HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
622                        &mboxAddress, sizeof(mboxAddress));
623
624     cmdCredits = 0;
625     timeout = BMI_COMMUNICATION_TIMEOUT;
626     while(timeout-- && !cmdCredits) {
627         /* Read the counter register to get the command credits */
628         address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
629         /* read the counter using a 4-byte read.  Since the counter is NOT auto-decrementing,
630          * we can read this counter multiple times using a non-incrementing address mode.
631          * The rationale here is to make all HIF accesses a multiple of 4 bytes */
632         status = HIFReadWrite(device, address, (A_UINT8 *)&cmdCredits, sizeof(cmdCredits),
633             HIF_RD_SYNC_BYTE_FIX, NULL);
634         if (status != A_OK) {
635             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
636             return A_ERROR;
637         }
638             /* we did a 4-byte read to the same count register so mask off upper bytes */
639         cmdCredits &= 0xFF;
640         status = A_ERROR;
641     }
642
643     if (cmdCredits) {
644         address = mboxAddress[ENDPOINT1];
645         status = HIFReadWrite(device, address, buffer, length,
646             HIF_RD_SYNC_BYTE_INC, NULL);
647         if (status != A_OK) {
648             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
649             return A_ERROR;
650         }
651     } else {
652         AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Communication timeout\n"));
653         return A_ERROR;
654     }
655
656     return status;
657 }