1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#ifdef THREAD_X
27#include <string.h>
28#endif
29
30#include "hif.h"
31#include "bmi.h"
32#include "htc_api.h"
33#include "bmi_internal.h"
34
35#ifdef ATH_DEBUG_MODULE
36static struct ath_debug_mask_description bmi_debug_desc[] = {
37 { ATH_DEBUG_BMI , "BMI Tracing"},
38};
39
40ATH_DEBUG_INSTANTIATE_MODULE_VAR(bmi,
41 "bmi",
42 "Boot Manager Interface",
43 ATH_DEBUG_MASK_DEFAULTS,
44 ATH_DEBUG_DESCRIPTION_COUNT(bmi_debug_desc),
45 bmi_debug_desc);
46
47#endif
48
49
50
51
52
53
54
55
56static bool pendingEventsFuncCheck = false;
57static u32 *pBMICmdCredits;
58static u8 *pBMICmdBuf;
59#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
60 sizeof(u32) + \
61 sizeof(u32) + \
62 sizeof(u32))
63#define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ)
64
65
66void
67BMIInit(void)
68{
69 bmiDone = false;
70 pendingEventsFuncCheck = false;
71
72
73
74
75
76
77
78
79
80
81 if (!pBMICmdCredits) {
82 pBMICmdCredits = (u32 *)A_MALLOC_NOWAIT(4);
83 A_ASSERT(pBMICmdCredits);
84 }
85
86 if (!pBMICmdBuf) {
87 pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
88 A_ASSERT(pBMICmdBuf);
89 }
90
91 A_REGISTER_MODULE_DEBUG_INFO(bmi);
92}
93
94void
95BMICleanup(void)
96{
97 if (pBMICmdCredits) {
98 A_FREE(pBMICmdCredits);
99 pBMICmdCredits = NULL;
100 }
101
102 if (pBMICmdBuf) {
103 A_FREE(pBMICmdBuf);
104 pBMICmdBuf = NULL;
105 }
106}
107
108int
109BMIDone(struct hif_device *device)
110{
111 int status;
112 u32 cid;
113
114 if (bmiDone) {
115 AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
116 return 0;
117 }
118
119 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
120 bmiDone = true;
121 cid = BMI_DONE;
122
123 status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
124 if (status) {
125 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
126 return A_ERROR;
127 }
128
129 if (pBMICmdCredits) {
130 A_FREE(pBMICmdCredits);
131 pBMICmdCredits = NULL;
132 }
133
134 if (pBMICmdBuf) {
135 A_FREE(pBMICmdBuf);
136 pBMICmdBuf = NULL;
137 }
138
139 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
140
141 return 0;
142}
143
144int
145BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info)
146{
147 int status;
148 u32 cid;
149
150 if (bmiDone) {
151 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
152 return A_ERROR;
153 }
154
155 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
156 cid = BMI_GET_TARGET_INFO;
157
158 status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
159 if (status) {
160 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
161 return A_ERROR;
162 }
163
164 status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver,
165 sizeof(targ_info->target_ver), true);
166 if (status) {
167 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
168 return A_ERROR;
169 }
170
171 if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
172
173 status = bmiBufferReceive(device, (u8 *)&targ_info->target_info_byte_count,
174 sizeof(targ_info->target_info_byte_count), true);
175 if (status) {
176 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
177 return A_ERROR;
178 }
179
180
181
182
183
184 A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
185
186
187 status = bmiBufferReceive(device,
188 ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count),
189 sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true);
190 if (status) {
191 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
192 targ_info->target_info_byte_count));
193 return A_ERROR;
194 }
195 }
196
197 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
198 targ_info->target_ver, targ_info->target_type));
199
200 return 0;
201}
202
203int
204BMIReadMemory(struct hif_device *device,
205 u32 address,
206 u8 *buffer,
207 u32 length)
208{
209 u32 cid;
210 int status;
211 u32 offset;
212 u32 remaining, rxlen;
213
214 A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)));
215 memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
216
217 if (bmiDone) {
218 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
219 return A_ERROR;
220 }
221
222 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
223 ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
224 device, address, length));
225
226 cid = BMI_READ_MEMORY;
227
228 remaining = length;
229
230 while (remaining)
231 {
232 rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
233 offset = 0;
234 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
235 offset += sizeof(cid);
236 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
237 offset += sizeof(address);
238 memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
239 offset += sizeof(length);
240
241 status = bmiBufferSend(device, pBMICmdBuf, offset);
242 if (status) {
243 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
244 return A_ERROR;
245 }
246 status = bmiBufferReceive(device, pBMICmdBuf, rxlen, true);
247 if (status) {
248 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
249 return A_ERROR;
250 }
251 memcpy(&buffer[length - remaining], pBMICmdBuf, rxlen);
252 remaining -= rxlen; address += rxlen;
253 }
254
255 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
256 return 0;
257}
258
259int
260BMIWriteMemory(struct hif_device *device,
261 u32 address,
262 u8 *buffer,
263 u32 length)
264{
265 u32 cid;
266 int status;
267 u32 offset;
268 u32 remaining, txlen;
269 const u32 header = sizeof(cid) + sizeof(address) + sizeof(length);
270 u8 alignedBuffer[BMI_DATASZ_MAX];
271 u8 *src;
272
273 A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
274 memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header);
275
276 if (bmiDone) {
277 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
278 return A_ERROR;
279 }
280
281 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
282 ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
283 device, address, length));
284
285 cid = BMI_WRITE_MEMORY;
286
287 remaining = length;
288 while (remaining)
289 {
290 src = &buffer[length - remaining];
291 if (remaining < (BMI_DATASZ_MAX - header)) {
292 if (remaining & 3) {
293
294 remaining = remaining + (4 - (remaining & 3));
295 memcpy(alignedBuffer, src, remaining);
296 src = alignedBuffer;
297 }
298 txlen = remaining;
299 } else {
300 txlen = (BMI_DATASZ_MAX - header);
301 }
302 offset = 0;
303 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
304 offset += sizeof(cid);
305 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
306 offset += sizeof(address);
307 memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
308 offset += sizeof(txlen);
309 memcpy(&(pBMICmdBuf[offset]), src, txlen);
310 offset += txlen;
311 status = bmiBufferSend(device, pBMICmdBuf, offset);
312 if (status) {
313 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
314 return A_ERROR;
315 }
316 remaining -= txlen; address += txlen;
317 }
318
319 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
320
321 return 0;
322}
323
324int
325BMIExecute(struct hif_device *device,
326 u32 address,
327 u32 *param)
328{
329 u32 cid;
330 int status;
331 u32 offset;
332
333 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
334 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
335
336 if (bmiDone) {
337 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
338 return A_ERROR;
339 }
340
341 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
342 ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
343 device, address, *param));
344
345 cid = BMI_EXECUTE;
346
347 offset = 0;
348 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
349 offset += sizeof(cid);
350 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
351 offset += sizeof(address);
352 memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param));
353 offset += sizeof(*param);
354 status = bmiBufferSend(device, pBMICmdBuf, offset);
355 if (status) {
356 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
357 return A_ERROR;
358 }
359
360 status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), false);
361 if (status) {
362 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
363 return A_ERROR;
364 }
365
366 memcpy(param, pBMICmdBuf, sizeof(*param));
367
368 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
369 return 0;
370}
371
372int
373BMISetAppStart(struct hif_device *device,
374 u32 address)
375{
376 u32 cid;
377 int status;
378 u32 offset;
379
380 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
381 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
382
383 if (bmiDone) {
384 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
385 return A_ERROR;
386 }
387
388 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
389 ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
390 device, address));
391
392 cid = BMI_SET_APP_START;
393
394 offset = 0;
395 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
396 offset += sizeof(cid);
397 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
398 offset += sizeof(address);
399 status = bmiBufferSend(device, pBMICmdBuf, offset);
400 if (status) {
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 Set App Start: Exit\n"));
406 return 0;
407}
408
409int
410BMIReadSOCRegister(struct hif_device *device,
411 u32 address,
412 u32 *param)
413{
414 u32 cid;
415 int status;
416 u32 offset;
417
418 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
419 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
420
421 if (bmiDone) {
422 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
423 return A_ERROR;
424 }
425
426 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
427 ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
428 device, address));
429
430 cid = BMI_READ_SOC_REGISTER;
431
432 offset = 0;
433 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
434 offset += sizeof(cid);
435 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
436 offset += sizeof(address);
437
438 status = bmiBufferSend(device, pBMICmdBuf, offset);
439 if (status) {
440 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
441 return A_ERROR;
442 }
443
444 status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), true);
445 if (status) {
446 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
447 return A_ERROR;
448 }
449 memcpy(param, pBMICmdBuf, sizeof(*param));
450
451 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
452 return 0;
453}
454
455int
456BMIWriteSOCRegister(struct hif_device *device,
457 u32 address,
458 u32 param)
459{
460 u32 cid;
461 int status;
462 u32 offset;
463
464 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
465 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
466
467 if (bmiDone) {
468 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
469 return A_ERROR;
470 }
471
472 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
473 ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
474 device, address, param));
475
476 cid = BMI_WRITE_SOC_REGISTER;
477
478 offset = 0;
479 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
480 offset += sizeof(cid);
481 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
482 offset += sizeof(address);
483 memcpy(&(pBMICmdBuf[offset]), ¶m, sizeof(param));
484 offset += sizeof(param);
485 status = bmiBufferSend(device, pBMICmdBuf, offset);
486 if (status) {
487 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
488 return A_ERROR;
489 }
490
491 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
492 return 0;
493}
494
495int
496BMIrompatchInstall(struct hif_device *device,
497 u32 ROM_addr,
498 u32 RAM_addr,
499 u32 nbytes,
500 u32 do_activate,
501 u32 *rompatch_id)
502{
503 u32 cid;
504 int status;
505 u32 offset;
506
507 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
508 sizeof(nbytes) + sizeof(do_activate)));
509 memset(pBMICmdBuf, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
510 sizeof(nbytes) + sizeof(do_activate));
511
512 if (bmiDone) {
513 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
514 return A_ERROR;
515 }
516
517 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
518 ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n",
519 device, ROM_addr, RAM_addr, nbytes, do_activate));
520
521 cid = BMI_ROMPATCH_INSTALL;
522
523 offset = 0;
524 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
525 offset += sizeof(cid);
526 memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
527 offset += sizeof(ROM_addr);
528 memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
529 offset += sizeof(RAM_addr);
530 memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
531 offset += sizeof(nbytes);
532 memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
533 offset += sizeof(do_activate);
534 status = bmiBufferSend(device, pBMICmdBuf, offset);
535 if (status) {
536 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
537 return A_ERROR;
538 }
539
540 status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), true);
541 if (status) {
542 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
543 return A_ERROR;
544 }
545 memcpy(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
546
547 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
548 return 0;
549}
550
551int
552BMIrompatchUninstall(struct hif_device *device,
553 u32 rompatch_id)
554{
555 u32 cid;
556 int status;
557 u32 offset;
558
559 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id)));
560 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id));
561
562 if (bmiDone) {
563 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
564 return A_ERROR;
565 }
566
567 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
568 ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
569 device, rompatch_id));
570
571 cid = BMI_ROMPATCH_UNINSTALL;
572
573 offset = 0;
574 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
575 offset += sizeof(cid);
576 memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
577 offset += sizeof(rompatch_id);
578 status = bmiBufferSend(device, pBMICmdBuf, offset);
579 if (status) {
580 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
581 return A_ERROR;
582 }
583
584 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
585 return 0;
586}
587
588static int
589_BMIrompatchChangeActivation(struct hif_device *device,
590 u32 rompatch_count,
591 u32 *rompatch_list,
592 u32 do_activate)
593{
594 u32 cid;
595 int status;
596 u32 offset;
597 u32 length;
598
599 A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)));
600 memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
601
602 if (bmiDone) {
603 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
604 return A_ERROR;
605 }
606
607 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
608 ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
609 device, rompatch_count));
610
611 cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
612
613 offset = 0;
614 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
615 offset += sizeof(cid);
616 memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
617 offset += sizeof(rompatch_count);
618 length = rompatch_count * sizeof(*rompatch_list);
619 memcpy(&(pBMICmdBuf[offset]), rompatch_list, length);
620 offset += length;
621 status = bmiBufferSend(device, pBMICmdBuf, offset);
622 if (status) {
623 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
624 return A_ERROR;
625 }
626
627 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
628
629 return 0;
630}
631
632int
633BMIrompatchActivate(struct hif_device *device,
634 u32 rompatch_count,
635 u32 *rompatch_list)
636{
637 return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
638}
639
640int
641BMIrompatchDeactivate(struct hif_device *device,
642 u32 rompatch_count,
643 u32 *rompatch_list)
644{
645 return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
646}
647
648int
649BMILZData(struct hif_device *device,
650 u8 *buffer,
651 u32 length)
652{
653 u32 cid;
654 int status;
655 u32 offset;
656 u32 remaining, txlen;
657 const u32 header = sizeof(cid) + sizeof(length);
658
659 A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header));
660 memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header);
661
662 if (bmiDone) {
663 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
664 return A_ERROR;
665 }
666
667 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
668 ("BMI Send LZ Data: Enter (device: 0x%p, length: %d)\n",
669 device, length));
670
671 cid = BMI_LZ_DATA;
672
673 remaining = length;
674 while (remaining)
675 {
676 txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
677 remaining : (BMI_DATASZ_MAX - header);
678 offset = 0;
679 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
680 offset += sizeof(cid);
681 memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
682 offset += sizeof(txlen);
683 memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
684 offset += txlen;
685 status = bmiBufferSend(device, pBMICmdBuf, offset);
686 if (status) {
687 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
688 return A_ERROR;
689 }
690 remaining -= txlen;
691 }
692
693 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n"));
694
695 return 0;
696}
697
698int
699BMILZStreamStart(struct hif_device *device,
700 u32 address)
701{
702 u32 cid;
703 int status;
704 u32 offset;
705
706 A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
707 memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
708
709 if (bmiDone) {
710 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
711 return A_ERROR;
712 }
713
714 AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
715 ("BMI LZ Stream Start: Enter (device: 0x%p, address: 0x%x)\n",
716 device, address));
717
718 cid = BMI_LZ_STREAM_START;
719 offset = 0;
720 memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
721 offset += sizeof(cid);
722 memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
723 offset += sizeof(address);
724 status = bmiBufferSend(device, pBMICmdBuf, offset);
725 if (status) {
726 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n"));
727 return A_ERROR;
728 }
729
730 AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n"));
731
732 return 0;
733}
734
735
736int
737bmiBufferSend(struct hif_device *device,
738 u8 *buffer,
739 u32 length)
740{
741 int status;
742 u32 timeout;
743 u32 address;
744 u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
745
746 HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
747 &mboxAddress[0], sizeof(mboxAddress));
748
749 *pBMICmdCredits = 0;
750 timeout = BMI_COMMUNICATION_TIMEOUT;
751
752 while(timeout-- && !(*pBMICmdCredits)) {
753
754 address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
755
756
757
758 status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, 4,
759 HIF_RD_SYNC_BYTE_INC, NULL);
760 if (status) {
761 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
762 return A_ERROR;
763 }
764
765 (*pBMICmdCredits) &= 0xFF;
766 }
767
768 if (*pBMICmdCredits) {
769 address = mboxAddress[ENDPOINT1];
770 status = HIFReadWrite(device, address, buffer, length,
771 HIF_WR_SYNC_BYTE_INC, NULL);
772 if (status) {
773 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
774 return A_ERROR;
775 }
776 } else {
777 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferSend\n"));
778 return A_ERROR;
779 }
780
781 return status;
782}
783
784int
785bmiBufferReceive(struct hif_device *device,
786 u8 *buffer,
787 u32 length,
788 bool want_timeout)
789{
790 int status;
791 u32 address;
792 u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
793 struct hif_pending_events_info hifPendingEvents;
794 static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL;
795
796 if (!pendingEventsFuncCheck) {
797
798
799 HIFConfigureDevice(device,
800 HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
801 &getPendingEventsFunc,
802 sizeof(getPendingEventsFunc));
803 pendingEventsFuncCheck = true;
804 }
805
806 HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
807 &mboxAddress[0], sizeof(mboxAddress));
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855 if (length >= 4) {
856
857
858
859
860 static u32 word_available;
861 u32 timeout;
862
863 word_available = 0;
864 timeout = BMI_COMMUNICATION_TIMEOUT;
865 while((!want_timeout || timeout--) && !word_available) {
866
867 if (getPendingEventsFunc != NULL) {
868 status = getPendingEventsFunc(device,
869 &hifPendingEvents,
870 NULL);
871 if (status) {
872 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
873 break;
874 }
875
876 if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) {
877 word_available = 1;
878 }
879 continue;
880 }
881
882 status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available,
883 sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
884 if (status) {
885 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n"));
886 return A_ERROR;
887 }
888
889 word_available &= (1 << ENDPOINT1);
890 }
891
892 if (!word_available) {
893 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout - bmiBufferReceive FIFO empty\n"));
894 return A_ERROR;
895 }
896 }
897
898#define CONSERVATIVE_BMI_READ 0
899#if CONSERVATIVE_BMI_READ
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922 if ((length > 4) && (length < 128)) {
923 u32 timeout;
924
925 *pBMICmdCredits = 0;
926 timeout = BMI_COMMUNICATION_TIMEOUT;
927 while((!want_timeout || timeout--) && !(*pBMICmdCredits) {
928
929 address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
930
931
932
933 status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
934 HIF_RD_SYNC_BYTE_FIX, NULL);
935 if (status) {
936 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
937 return A_ERROR;
938 }
939
940 (*pBMICmdCredits) &= 0xFF;
941 }
942
943 if (!(*pBMICmdCredits)) {
944 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout- bmiBufferReceive no credit\n"));
945 return A_ERROR;
946 }
947 }
948#endif
949
950 address = mboxAddress[ENDPOINT1];
951 status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL);
952 if (status) {
953 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
954 return A_ERROR;
955 }
956
957 return 0;
958}
959
960int
961BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length)
962{
963 int status = A_ERROR;
964 u32 lastWord = 0;
965 u32 lastWordOffset = length & ~0x3;
966 u32 unalignedBytes = length & 0x3;
967
968 status = BMILZStreamStart (device, address);
969 if (status) {
970 return A_ERROR;
971 }
972
973 if (unalignedBytes) {
974
975 memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes);
976 }
977
978 status = BMILZData(device, buffer, lastWordOffset);
979
980 if (status) {
981 return A_ERROR;
982 }
983
984 if (unalignedBytes) {
985 status = BMILZData(device, (u8 *)&lastWord, 4);
986 }
987
988 if (!status) {
989
990
991
992 status = BMILZStreamStart (device, 0x00);
993 if (status) {
994 return A_ERROR;
995 }
996 }
997 return status;
998}
999
1000int
1001BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length)
1002{
1003 return bmiBufferSend(device, buffer, length);
1004}
1005
1006int
1007BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout)
1008{
1009 return bmiBufferReceive(device, buffer, length, want_timeout);
1010}
1011