[s3c24xx] bump to 2.6.30-rc6
[openwrt/svn-archive/archive.git] / target / linux / s3c24xx / files-2.6.30 / 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 }