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#include "a_config.h"
26#include "athdefs.h"
27#include "a_types.h"
28#include "a_osapi.h"
29#include "../htc_debug.h"
30#include "hif.h"
31#include "htc_packet.h"
32#include "ar6k.h"
33#include "hci_transport_api.h"
34#include "gmboxif.h"
35#include "ar6000_diag.h"
36#include "hw/apb_map.h"
37#include "hw/mbox_reg.h"
38
39#ifdef ATH_AR6K_ENABLE_GMBOX
40#define HCI_UART_COMMAND_PKT 0x01
41#define HCI_UART_ACL_PKT 0x02
42#define HCI_UART_SCO_PKT 0x03
43#define HCI_UART_EVENT_PKT 0x04
44
45#define HCI_RECV_WAIT_BUFFERS (1 << 0)
46
47#define HCI_SEND_WAIT_CREDITS (1 << 0)
48
49#define HCI_UART_BRIDGE_CREDIT_SIZE 128
50
51#define CREDIT_POLL_COUNT 256
52
53#define HCI_DELAY_PER_INTERVAL_MS 10
54#define BTON_TIMEOUT_MS 500
55#define BTOFF_TIMEOUT_MS 500
56#define BAUD_TIMEOUT_MS 1
57#define BTPWRSAV_TIMEOUT_MS 1
58
59typedef struct {
60 HCI_TRANSPORT_CONFIG_INFO HCIConfig;
61 A_BOOL HCIAttached;
62 A_BOOL HCIStopped;
63 A_UINT32 RecvStateFlags;
64 A_UINT32 SendStateFlags;
65 HCI_TRANSPORT_PACKET_TYPE WaitBufferType;
66 HTC_PACKET_QUEUE SendQueue;
67 HTC_PACKET_QUEUE HCIACLRecvBuffers;
68 HTC_PACKET_QUEUE HCIEventBuffers;
69 AR6K_DEVICE *pDev;
70 A_MUTEX_T HCIRxLock;
71 A_MUTEX_T HCITxLock;
72 int CreditsMax;
73 int CreditsConsumed;
74 int CreditsAvailable;
75 int CreditSize;
76 int CreditsCurrentSeek;
77 int SendProcessCount;
78} GMBOX_PROTO_HCI_UART;
79
80#define LOCK_HCI_RX(t) A_MUTEX_LOCK(&(t)->HCIRxLock);
81#define UNLOCK_HCI_RX(t) A_MUTEX_UNLOCK(&(t)->HCIRxLock);
82#define LOCK_HCI_TX(t) A_MUTEX_LOCK(&(t)->HCITxLock);
83#define UNLOCK_HCI_TX(t) A_MUTEX_UNLOCK(&(t)->HCITxLock);
84
85#define DO_HCI_RECV_INDICATION(p,pt) \
86{ AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI: Indicate Recv on packet:0x%lX status:%d len:%d type:%d \n", \
87 (unsigned long)(pt),(pt)->Status, A_SUCCESS((pt)->Status) ? (pt)->ActualLength : 0, HCI_GET_PACKET_TYPE(pt))); \
88 (p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt)); \
89}
90
91#define DO_HCI_SEND_INDICATION(p,pt) \
92{ AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Indicate Send on packet:0x%lX status:%d type:%d \n", \
93 (unsigned long)(pt),(pt)->Status,HCI_GET_PACKET_TYPE(pt))); \
94 (p)->HCIConfig.pHCISendComplete((p)->HCIConfig.pContext, (pt)); \
95}
96
97static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_BOOL Synchronous);
98
99static void HCIUartCleanup(GMBOX_PROTO_HCI_UART *pProtocol)
100{
101 A_ASSERT(pProtocol != NULL);
102
103 A_MUTEX_DELETE(&pProtocol->HCIRxLock);
104 A_MUTEX_DELETE(&pProtocol->HCITxLock);
105
106 A_FREE(pProtocol);
107}
108
109static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
110{
111 A_STATUS status;
112 int credits;
113 int creditPollCount = CREDIT_POLL_COUNT;
114 A_BOOL gotCredits = FALSE;
115
116 pProt->CreditsConsumed = 0;
117
118 do {
119
120 if (pProt->CreditsMax != 0) {
121
122 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI: InitTxCreditState - already called! \n"));
123 A_ASSERT(FALSE);
124 status = A_EINVAL;
125 break;
126 }
127
128
129
130
131
132 while (creditPollCount) {
133
134 credits = 0;
135
136 status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);
137
138 if (A_FAILED(status)) {
139 break;
140 }
141
142 if (!gotCredits && (0 == credits)) {
143 creditPollCount--;
144 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: credit is 0, retrying (%d) \n",creditPollCount));
145 A_MDELAY(HCI_DELAY_PER_INTERVAL_MS);
146 continue;
147 } else {
148 gotCredits = TRUE;
149 }
150
151 if (0 == credits) {
152 break;
153 }
154
155 pProt->CreditsMax += credits;
156 }
157
158 if (A_FAILED(status)) {
159 break;
160 }
161
162 if (0 == creditPollCount) {
163 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
164 ("** HCI : Failed to get credits! GMBOX Target was not available \n"));
165 status = A_ERROR;
166 break;
167 }
168
169
170 status = DevGMboxReadCreditSize(pProt->pDev, &pProt->CreditSize);
171
172 if (A_FAILED(status)) {
173 break;
174 }
175
176 } while (FALSE);
177
178 if (A_SUCCESS(status)) {
179 pProt->CreditsAvailable = pProt->CreditsMax;
180 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI : InitTxCreditState - credits avail: %d, size: %d \n",
181 pProt->CreditsAvailable, pProt->CreditSize));
182 }
183
184 return status;
185}
186
187static A_STATUS CreditsAvailableCallback(void *pContext, int Credits, A_BOOL CreditIRQEnabled)
188{
189 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
190 A_BOOL enableCreditIrq = FALSE;
191 A_BOOL disableCreditIrq = FALSE;
192 A_BOOL doPendingSends = FALSE;
193 A_STATUS status = A_OK;
194
195
196
197
198
199
200
201
202 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback (Credits:%d, IRQ:%s) \n",
203 Credits, CreditIRQEnabled ? "ON" : "OFF"));
204
205 LOCK_HCI_TX(pProt);
206
207 do {
208
209 if (0 == Credits) {
210 if (!CreditIRQEnabled) {
211
212 enableCreditIrq = TRUE;
213 }
214 break;
215 }
216
217 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: current credit state, consumed:%d available:%d max:%d seek:%d\n",
218 pProt->CreditsConsumed,
219 pProt->CreditsAvailable,
220 pProt->CreditsMax,
221 pProt->CreditsCurrentSeek));
222
223 pProt->CreditsAvailable += Credits;
224 A_ASSERT(pProt->CreditsAvailable <= pProt->CreditsMax);
225 pProt->CreditsConsumed -= Credits;
226 A_ASSERT(pProt->CreditsConsumed >= 0);
227
228 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state, consumed:%d available:%d max:%d seek:%d\n",
229 pProt->CreditsConsumed,
230 pProt->CreditsAvailable,
231 pProt->CreditsMax,
232 pProt->CreditsCurrentSeek));
233
234 if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) {
235
236 pProt->CreditsCurrentSeek = 0;
237 pProt->SendStateFlags &= ~HCI_SEND_WAIT_CREDITS;
238 doPendingSends = TRUE;
239 if (CreditIRQEnabled) {
240
241 disableCreditIrq = TRUE;
242 }
243 } else {
244
245 if (!CreditIRQEnabled) {
246 enableCreditIrq = TRUE;
247 }
248 }
249
250 } while (FALSE);
251
252 UNLOCK_HCI_TX(pProt);
253
254 if (enableCreditIrq) {
255 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Enabling credit count IRQ...\n"));
256
257 status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_ENABLE, PROC_IO_ASYNC);
258 } else if (disableCreditIrq) {
259
260 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Disabling credit count IRQ...\n"));
261 status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_DISABLE, PROC_IO_ASYNC);
262 }
263
264 if (doPendingSends) {
265 HCITrySend(pProt, NULL, FALSE);
266 }
267
268 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback \n"));
269 return status;
270}
271
272static INLINE void NotifyTransportFailure(GMBOX_PROTO_HCI_UART *pProt, A_STATUS status)
273{
274 if (pProt->HCIConfig.TransportFailure != NULL) {
275 pProt->HCIConfig.TransportFailure(pProt->HCIConfig.pContext, status);
276 }
277}
278
279static void FailureCallback(void *pContext, A_STATUS Status)
280{
281 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
282
283
284 NotifyTransportFailure(pProt, Status);
285}
286
287static void StateDumpCallback(void *pContext)
288{
289 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
290
291 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("============ HCIUart State ======================\n"));
292 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("RecvStateFlags : 0x%X \n",pProt->RecvStateFlags));
293 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendStateFlags : 0x%X \n",pProt->SendStateFlags));
294 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("WaitBufferType : %d \n",pProt->WaitBufferType));
295 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendQueue Depth : %d \n",HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue)));
296 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsMax : %d \n",pProt->CreditsMax));
297 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsConsumed : %d \n",pProt->CreditsConsumed));
298 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsAvailable : %d \n",pProt->CreditsAvailable));
299 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("==================================================\n"));
300}
301
302static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[], int ValidBytes)
303{
304 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
305 A_STATUS status = A_OK;
306 int totalRecvLength = 0;
307 HCI_TRANSPORT_PACKET_TYPE pktType = HCI_PACKET_INVALID;
308 A_BOOL recvRefillCalled = FALSE;
309 A_BOOL blockRecv = FALSE;
310 HTC_PACKET *pPacket = NULL;
311
312
313
314 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCIUartMessagePending Lookahead Bytes:%d \n",ValidBytes));
315
316 LOCK_HCI_RX(pProt);
317
318 do {
319
320 if (ValidBytes < 3) {
321
322 break;
323 }
324
325 if ((LookAheadBytes[0] == HCI_UART_ACL_PKT) && (ValidBytes < 5)) {
326
327 break;
328 }
329
330 switch (LookAheadBytes[0]) {
331 case HCI_UART_EVENT_PKT:
332 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n",
333 LookAheadBytes[1], LookAheadBytes[2]));
334 totalRecvLength = LookAheadBytes[2];
335 totalRecvLength += 3;
336 pktType = HCI_EVENT_TYPE;
337 break;
338 case HCI_UART_ACL_PKT:
339 totalRecvLength = (LookAheadBytes[4] << 8) | LookAheadBytes[3];
340 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI ACL: conn:0x%X length: %d \n",
341 ((LookAheadBytes[2] & 0xF0) << 8) | LookAheadBytes[1], totalRecvLength));
342 totalRecvLength += 5;
343 pktType = HCI_ACL_TYPE;
344 break;
345 default:
346 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",LookAheadBytes[0]));
347 status = A_EPROTO;
348 break;
349 }
350
351 if (A_FAILED(status)) {
352 break;
353 }
354
355 if (pProt->HCIConfig.pHCIPktRecvAlloc != NULL) {
356 UNLOCK_HCI_RX(pProt);
357
358 pPacket = pProt->HCIConfig.pHCIPktRecvAlloc(pProt->HCIConfig.pContext,
359 pktType,
360 totalRecvLength);
361 LOCK_HCI_RX(pProt);
362
363 } else {
364 HTC_PACKET_QUEUE *pQueue;
365
366
367
368 if (pktType == HCI_ACL_TYPE) {
369 pQueue = &pProt->HCIACLRecvBuffers;
370 } else {
371 pQueue = &pProt->HCIEventBuffers;
372 }
373
374 if (HTC_QUEUE_EMPTY(pQueue)) {
375 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
376 ("** HCI pkt type: %d has no buffers available calling allocation handler \n",
377 pktType));
378
379 if (pProt->HCIConfig.pHCIPktRecvRefill != NULL) {
380 recvRefillCalled = TRUE;
381 UNLOCK_HCI_RX(pProt);
382
383 pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext,
384 pktType,
385 0);
386 LOCK_HCI_RX(pProt);
387
388 pPacket = HTC_PACKET_DEQUEUE(pQueue);
389
390 }
391 } else {
392 pPacket = HTC_PACKET_DEQUEUE(pQueue);
393 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
394 ("HCI pkt type: %d now has %d recv buffers left \n",
395 pktType, HTC_PACKET_QUEUE_DEPTH(pQueue)));
396 }
397 }
398
399 if (NULL == pPacket) {
400 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
401 ("** HCI pkt type: %d has no buffers available stopping recv...\n", pktType));
402
403 pProt->RecvStateFlags |= HCI_RECV_WAIT_BUFFERS;
404 pProt->WaitBufferType = pktType;
405 blockRecv = TRUE;
406 break;
407 }
408
409 if (totalRecvLength > (int)pPacket->BufferLength) {
410 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI-UART pkt: %d requires %d bytes (%d buffer bytes avail) ! \n",
411 LookAheadBytes[0], totalRecvLength, pPacket->BufferLength));
412 status = A_EINVAL;
413 break;
414 }
415
416 } while (FALSE);
417
418 UNLOCK_HCI_RX(pProt);
419
420
421
422 do {
423
424 if (A_FAILED(status) || (NULL == pPacket)) {
425 break;
426 }
427
428
429 pPacket->Completion = NULL;
430
431 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI : getting recv packet len:%d hci-uart-type: %s \n",
432 totalRecvLength, (LookAheadBytes[0] == HCI_UART_EVENT_PKT) ? "EVENT" : "ACL"));
433
434 status = DevGMboxRead(pProt->pDev, pPacket, totalRecvLength);
435
436 if (A_FAILED(status)) {
437 break;
438 }
439
440 if (pPacket->pBuffer[0] != LookAheadBytes[0]) {
441 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not contain expected packet type: %d ! \n",
442 pPacket->pBuffer[0]));
443 status = A_EPROTO;
444 break;
445 }
446
447 if (pPacket->pBuffer[0] == HCI_UART_EVENT_PKT) {
448
449 if ((pPacket->pBuffer[1] != LookAheadBytes[1]) ||
450 (pPacket->pBuffer[2] != LookAheadBytes[2])) {
451 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n"));
452 DebugDumpBytes(LookAheadBytes, 3, "Expected HCI-UART Header");
453 DebugDumpBytes(pPacket->pBuffer, 3, "** Bad HCI-UART Header");
454 status = A_EPROTO;
455 break;
456 }
457 } else if (pPacket->pBuffer[0] == HCI_UART_ACL_PKT) {
458
459 if ((pPacket->pBuffer[1] != LookAheadBytes[1]) ||
460 (pPacket->pBuffer[2] != LookAheadBytes[2]) ||
461 (pPacket->pBuffer[3] != LookAheadBytes[3]) ||
462 (pPacket->pBuffer[4] != LookAheadBytes[4])) {
463 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match lookahead! \n"));
464 DebugDumpBytes(LookAheadBytes, 5, "Expected HCI-UART Header");
465 DebugDumpBytes(pPacket->pBuffer, 5, "** Bad HCI-UART Header");
466 status = A_EPROTO;
467 break;
468 }
469 }
470
471
472 pPacket->pBuffer++;
473 pPacket->ActualLength = totalRecvLength - 1;
474 pPacket->Status = A_OK;
475
476 DO_HCI_RECV_INDICATION(pProt,pPacket);
477 pPacket = NULL;
478
479
480 if ((pProt->HCIConfig.pHCIPktRecvRefill != NULL) && !recvRefillCalled) {
481 HTC_PACKET_QUEUE *pQueue;
482 int watermark;
483
484 if (pktType == HCI_ACL_TYPE) {
485 watermark = pProt->HCIConfig.ACLRecvBufferWaterMark;
486 pQueue = &pProt->HCIACLRecvBuffers;
487 } else {
488 watermark = pProt->HCIConfig.EventRecvBufferWaterMark;
489 pQueue = &pProt->HCIEventBuffers;
490 }
491
492 if (HTC_PACKET_QUEUE_DEPTH(pQueue) < watermark) {
493 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
494 ("** HCI pkt type: %d watermark hit (%d) current:%d \n",
495 pktType, watermark, HTC_PACKET_QUEUE_DEPTH(pQueue)));
496
497 pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext,
498 pktType,
499 HTC_PACKET_QUEUE_DEPTH(pQueue));
500 }
501 }
502
503 } while (FALSE);
504
505
506 if (A_FAILED(status) || blockRecv) {
507 DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_DISABLE, PROC_IO_SYNC);
508 }
509
510
511 if (A_FAILED(status) && (pPacket != NULL)) {
512 HTC_PACKET_QUEUE queue;
513
514 if (A_EPROTO == status) {
515 DebugDumpBytes(pPacket->pBuffer, totalRecvLength, "Bad HCI-UART Recv packet");
516 }
517
518 HTC_PACKET_RESET_RX(pPacket);
519 INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
520 HCI_TransportAddReceivePkts(pProt,&queue);
521 NotifyTransportFailure(pProt,status);
522 }
523
524
525 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCIUartMessagePending \n"));
526
527 return status;
528}
529
530static void HCISendPacketCompletion(void *Context, HTC_PACKET *pPacket)
531{
532 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)Context;
533 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion (pPacket:0x%lX) \n",(unsigned long)pPacket));
534
535 if (A_FAILED(pPacket->Status)) {
536 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Send Packet (0x%lX) failed: %d , len:%d \n",
537 (unsigned long)pPacket, pPacket->Status, pPacket->ActualLength));
538 }
539
540 DO_HCI_SEND_INDICATION(pProt,pPacket);
541
542 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion \n"));
543}
544
545static A_STATUS SeekCreditsSynch(GMBOX_PROTO_HCI_UART *pProt)
546{
547 A_STATUS status = A_OK;
548 int credits;
549 int retry = 100;
550
551 while (TRUE) {
552 credits = 0;
553 status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);
554 if (A_FAILED(status)) {
555 break;
556 }
557 LOCK_HCI_TX(pProt);
558 pProt->CreditsAvailable += credits;
559 pProt->CreditsConsumed -= credits;
560 if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) {
561 pProt->CreditsCurrentSeek = 0;
562 UNLOCK_HCI_TX(pProt);
563 break;
564 }
565 UNLOCK_HCI_TX(pProt);
566 retry--;
567 if (0 == retry) {
568 status = A_EBUSY;
569 break;
570 }
571 A_MDELAY(20);
572 }
573
574 return status;
575}
576
577static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_BOOL Synchronous)
578{
579 A_STATUS status = A_OK;
580 int transferLength;
581 int creditsRequired, remainder;
582 A_UINT8 hciUartType;
583 A_BOOL synchSendComplete = FALSE;
584
585 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCITrySend (pPacket:0x%lX) %s \n",(unsigned long)pPacket,
586 Synchronous ? "SYNC" :"ASYNC"));
587
588 LOCK_HCI_TX(pProt);
589
590
591 pProt->SendProcessCount++;
592
593 do {
594
595 if (pProt->HCIStopped) {
596 status = A_ECANCELED;
597 break;
598 }
599
600 if (pPacket != NULL) {
601
602 if (Synchronous) {
603
604 if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
605 status = A_EBUSY;
606 A_ASSERT(FALSE);
607 break;
608 }
609
610 if (pProt->SendProcessCount > 1) {
611
612 status = A_EBUSY;
613 A_ASSERT(FALSE);
614 break;
615 }
616
617 HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket);
618
619 } else {
620
621 if ((pProt->HCIConfig.MaxSendQueueDepth > 0) &&
622 ((HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue) + 1) >= pProt->HCIConfig.MaxSendQueueDepth)) {
623 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("HCI Send queue is full, Depth:%d, Max:%d \n",
624 HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue),
625 pProt->HCIConfig.MaxSendQueueDepth));
626
627 if (pProt->HCIConfig.pHCISendFull != NULL) {
628 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
629 ("HCI : Calling driver's send full callback.... \n"));
630 if (pProt->HCIConfig.pHCISendFull(pProt->HCIConfig.pContext,
631 pPacket) == HCI_SEND_FULL_DROP) {
632
633 status = A_NO_RESOURCE;
634 break;
635 }
636 }
637 }
638
639 HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket);
640 }
641
642 }
643
644 if (pProt->SendStateFlags & HCI_SEND_WAIT_CREDITS) {
645 break;
646 }
647
648 if (pProt->SendProcessCount > 1) {
649
650 break;
651 }
652
653
654
655
656
657 while (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
658
659 pPacket = HTC_PACKET_DEQUEUE(&pProt->SendQueue);
660
661 switch (HCI_GET_PACKET_TYPE(pPacket)) {
662 case HCI_COMMAND_TYPE:
663 hciUartType = HCI_UART_COMMAND_PKT;
664 break;
665 case HCI_ACL_TYPE:
666 hciUartType = HCI_UART_ACL_PKT;
667 break;
668 default:
669 status = A_EINVAL;
670 A_ASSERT(FALSE);
671 break;
672 }
673
674 if (A_FAILED(status)) {
675 break;
676 }
677
678 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Got head packet:0x%lX , Type:%d Length: %d Remaining Queue Depth: %d\n",
679 (unsigned long)pPacket, HCI_GET_PACKET_TYPE(pPacket), pPacket->ActualLength,
680 HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue)));
681
682 transferLength = 1;
683 transferLength += pPacket->ActualLength;
684 transferLength = DEV_CALC_SEND_PADDED_LEN(pProt->pDev, transferLength);
685
686
687 creditsRequired = transferLength / pProt->CreditSize;
688 remainder = transferLength % pProt->CreditSize;
689
690 if (remainder) {
691 creditsRequired++;
692 }
693
694 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Creds Required:%d Got:%d\n",
695 creditsRequired, pProt->CreditsAvailable));
696
697 if (creditsRequired > pProt->CreditsAvailable) {
698 if (Synchronous) {
699
700 pProt->CreditsCurrentSeek = creditsRequired;
701 UNLOCK_HCI_TX(pProt);
702 status = SeekCreditsSynch(pProt);
703 LOCK_HCI_TX(pProt);
704 if (A_FAILED(status)) {
705 break;
706 }
707
708 } else {
709
710 HTC_PACKET_ENQUEUE_TO_HEAD(&pProt->SendQueue,pPacket);
711
712 pProt->SendStateFlags |= HCI_SEND_WAIT_CREDITS;
713
714
715 pProt->CreditsCurrentSeek = creditsRequired;
716 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: packet:0x%lX placed back in queue. head packet needs: %d credits \n",
717 (unsigned long)pPacket, pProt->CreditsCurrentSeek));
718 pPacket = NULL;
719 UNLOCK_HCI_TX(pProt);
720
721
722
723 DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_ASYNC, NULL);
724
725 LOCK_HCI_TX(pProt);
726 break;
727 }
728 }
729
730
731 pPacket->pBuffer--;
732 pPacket->pBuffer[0] = hciUartType;
733
734 pProt->CreditsAvailable -= creditsRequired;
735 pProt->CreditsConsumed += creditsRequired;
736 A_ASSERT(pProt->CreditsConsumed <= pProt->CreditsMax);
737
738 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state: consumed:%d available:%d max:%d\n",
739 pProt->CreditsConsumed, pProt->CreditsAvailable, pProt->CreditsMax));
740
741 UNLOCK_HCI_TX(pProt);
742
743
744 if (Synchronous) {
745 pPacket->Completion = NULL;
746 pPacket->pContext = NULL;
747 } else {
748 pPacket->Completion = HCISendPacketCompletion;
749 pPacket->pContext = pProt;
750 }
751
752 status = DevGMboxWrite(pProt->pDev,pPacket,transferLength);
753 if (Synchronous) {
754 synchSendComplete = TRUE;
755 } else {
756 pPacket = NULL;
757 }
758
759 LOCK_HCI_TX(pProt);
760
761 }
762
763 } while (FALSE);
764
765 pProt->SendProcessCount--;
766 A_ASSERT(pProt->SendProcessCount >= 0);
767 UNLOCK_HCI_TX(pProt);
768
769 if (Synchronous) {
770 A_ASSERT(pPacket != NULL);
771 if (A_SUCCESS(status) && (!synchSendComplete)) {
772 status = A_EBUSY;
773 A_ASSERT(FALSE);
774 LOCK_HCI_TX(pProt);
775 if (pPacket->ListLink.pNext != NULL) {
776
777 HTC_PACKET_REMOVE(&pProt->SendQueue,pPacket);
778 }
779 UNLOCK_HCI_TX(pProt);
780 }
781 } else {
782 if (A_FAILED(status) && (pPacket != NULL)) {
783 pPacket->Status = status;
784 DO_HCI_SEND_INDICATION(pProt,pPacket);
785 }
786 }
787
788 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HCITrySend: \n"));
789 return status;
790}
791
792static void FlushSendQueue(GMBOX_PROTO_HCI_UART *pProt)
793{
794 HTC_PACKET *pPacket;
795 HTC_PACKET_QUEUE discardQueue;
796
797 INIT_HTC_PACKET_QUEUE(&discardQueue);
798
799 LOCK_HCI_TX(pProt);
800
801 if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
802 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->SendQueue);
803 }
804
805 UNLOCK_HCI_TX(pProt);
806
807
808 while (!HTC_QUEUE_EMPTY(&discardQueue)) {
809 pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
810 pPacket->Status = A_ECANCELED;
811 DO_HCI_SEND_INDICATION(pProt,pPacket);
812 }
813
814}
815
816static void FlushRecvBuffers(GMBOX_PROTO_HCI_UART *pProt)
817{
818 HTC_PACKET_QUEUE discardQueue;
819 HTC_PACKET *pPacket;
820
821 INIT_HTC_PACKET_QUEUE(&discardQueue);
822
823 LOCK_HCI_RX(pProt);
824
825 if (!HTC_QUEUE_EMPTY(&pProt->HCIACLRecvBuffers)) {
826 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIACLRecvBuffers);
827 }
828 if (!HTC_QUEUE_EMPTY(&pProt->HCIEventBuffers)) {
829 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIEventBuffers);
830 }
831 UNLOCK_HCI_RX(pProt);
832
833
834 while (!HTC_QUEUE_EMPTY(&discardQueue)) {
835 pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
836 pPacket->Status = A_ECANCELED;
837 DO_HCI_RECV_INDICATION(pProt,pPacket);
838 }
839
840}
841
842
843
844A_STATUS GMboxProtocolInstall(AR6K_DEVICE *pDev)
845{
846 A_STATUS status = A_OK;
847 GMBOX_PROTO_HCI_UART *pProtocol = NULL;
848
849 do {
850
851 pProtocol = A_MALLOC(sizeof(GMBOX_PROTO_HCI_UART));
852
853 if (NULL == pProtocol) {
854 status = A_NO_MEMORY;
855 break;
856 }
857
858 A_MEMZERO(pProtocol, sizeof(*pProtocol));
859 pProtocol->pDev = pDev;
860 INIT_HTC_PACKET_QUEUE(&pProtocol->SendQueue);
861 INIT_HTC_PACKET_QUEUE(&pProtocol->HCIACLRecvBuffers);
862 INIT_HTC_PACKET_QUEUE(&pProtocol->HCIEventBuffers);
863 A_MUTEX_INIT(&pProtocol->HCIRxLock);
864 A_MUTEX_INIT(&pProtocol->HCITxLock);
865
866 } while (FALSE);
867
868 if (A_SUCCESS(status)) {
869 LOCK_AR6K(pDev);
870 DEV_GMBOX_SET_PROTOCOL(pDev,
871 HCIUartMessagePending,
872 CreditsAvailableCallback,
873 FailureCallback,
874 StateDumpCallback,
875 pProtocol);
876 UNLOCK_AR6K(pDev);
877 } else {
878 if (pProtocol != NULL) {
879 HCIUartCleanup(pProtocol);
880 }
881 }
882
883 return status;
884}
885
886
887void GMboxProtocolUninstall(AR6K_DEVICE *pDev)
888{
889 GMBOX_PROTO_HCI_UART *pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROTOCOL(pDev);
890
891 if (pProtocol != NULL) {
892
893
894 if (pProtocol->HCIAttached) {
895 A_ASSERT(pProtocol->HCIConfig.TransportRemoved != NULL);
896 pProtocol->HCIConfig.TransportRemoved(pProtocol->HCIConfig.pContext);
897 pProtocol->HCIAttached = FALSE;
898 }
899
900 HCIUartCleanup(pProtocol);
901 DEV_GMBOX_SET_PROTOCOL(pDev,NULL,NULL,NULL,NULL,NULL);
902 }
903
904}
905
906static A_STATUS NotifyTransportReady(GMBOX_PROTO_HCI_UART *pProt)
907{
908 HCI_TRANSPORT_PROPERTIES props;
909 A_STATUS status = A_OK;
910
911 do {
912
913 A_MEMZERO(&props,sizeof(props));
914
915
916 props.HeadRoom = 1;
917 props.TailRoom = 0;
918 props.IOBlockPad = pProt->pDev->BlockSize;
919 if (pProt->HCIAttached) {
920 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI: notifying attached client to transport... \n"));
921 A_ASSERT(pProt->HCIConfig.TransportReady != NULL);
922 status = pProt->HCIConfig.TransportReady(pProt,
923 &props,
924 pProt->HCIConfig.pContext);
925 }
926
927 } while (FALSE);
928
929 return status;
930}
931
932
933
934HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo)
935{
936 GMBOX_PROTO_HCI_UART *pProtocol = NULL;
937 AR6K_DEVICE *pDev;
938
939 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportAttach \n"));
940
941 pDev = HTCGetAR6KDevice(HTCHandle);
942
943 LOCK_AR6K(pDev);
944
945 do {
946
947 pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROTOCOL(pDev);
948
949 if (NULL == pProtocol) {
950 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not installed! \n"));
951 break;
952 }
953
954 if (pProtocol->HCIAttached) {
955 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol already attached! \n"));
956 break;
957 }
958
959 A_MEMCPY(&pProtocol->HCIConfig, pInfo, sizeof(HCI_TRANSPORT_CONFIG_INFO));
960
961 A_ASSERT(pProtocol->HCIConfig.pHCIPktRecv != NULL);
962 A_ASSERT(pProtocol->HCIConfig.pHCISendComplete != NULL);
963
964 pProtocol->HCIAttached = TRUE;
965
966 } while (FALSE);
967
968 UNLOCK_AR6K(pDev);
969
970 if (pProtocol != NULL) {
971
972 NotifyTransportReady(pProtocol);
973 }
974
975 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach (0x%lX) \n",(unsigned long)pProtocol));
976 return (HCI_TRANSPORT_HANDLE)pProtocol;
977}
978
979void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans)
980{
981 GMBOX_PROTO_HCI_UART *pProtocol = (GMBOX_PROTO_HCI_UART *)HciTrans;
982 AR6K_DEVICE *pDev = pProtocol->pDev;
983
984 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportDetach \n"));
985
986 LOCK_AR6K(pDev);
987 if (!pProtocol->HCIAttached) {
988 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not attached! \n"));
989 UNLOCK_AR6K(pDev);
990 return;
991 }
992 pProtocol->HCIAttached = FALSE;
993 UNLOCK_AR6K(pDev);
994
995 HCI_TransportStop(HciTrans);
996 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach \n"));
997}
998
999A_STATUS HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue)
1000{
1001 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1002 A_STATUS status = A_OK;
1003 A_BOOL unblockRecv = FALSE;
1004 HTC_PACKET *pPacket;
1005
1006 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCI_TransportAddReceivePkt \n"));
1007
1008 LOCK_HCI_RX(pProt);
1009
1010 do {
1011
1012 if (pProt->HCIStopped) {
1013 status = A_ECANCELED;
1014 break;
1015 }
1016
1017 pPacket = HTC_GET_PKT_AT_HEAD(pQueue);
1018
1019 if (NULL == pPacket) {
1020 status = A_EINVAL;
1021 break;
1022 }
1023
1024 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv packet added, type :%d, len:%d num:%d \n",
1025 HCI_GET_PACKET_TYPE(pPacket), pPacket->BufferLength, HTC_PACKET_QUEUE_DEPTH(pQueue)));
1026
1027 if (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) {
1028 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIEventBuffers, pQueue);
1029 } else if (HCI_GET_PACKET_TYPE(pPacket) == HCI_ACL_TYPE) {
1030 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIACLRecvBuffers, pQueue);
1031 } else {
1032 status = A_EINVAL;
1033 break;
1034 }
1035
1036 if (pProt->RecvStateFlags & HCI_RECV_WAIT_BUFFERS) {
1037 if (pProt->WaitBufferType == HCI_GET_PACKET_TYPE(pPacket)) {
1038 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv was blocked on packet type :%d, unblocking.. \n",
1039 pProt->WaitBufferType));
1040 pProt->RecvStateFlags &= ~HCI_RECV_WAIT_BUFFERS;
1041 pProt->WaitBufferType = HCI_PACKET_INVALID;
1042 unblockRecv = TRUE;
1043 }
1044 }
1045
1046 } while (FALSE);
1047
1048 UNLOCK_HCI_RX(pProt);
1049
1050 if (A_FAILED(status)) {
1051 while (!HTC_QUEUE_EMPTY(pQueue)) {
1052 pPacket = HTC_PACKET_DEQUEUE(pQueue);
1053 pPacket->Status = A_ECANCELED;
1054 DO_HCI_RECV_INDICATION(pProt,pPacket);
1055 }
1056 }
1057
1058 if (unblockRecv) {
1059 DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_ASYNC);
1060 }
1061
1062 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCI_TransportAddReceivePkt \n"));
1063
1064 return A_OK;
1065}
1066
1067A_STATUS HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous)
1068{
1069 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1070
1071 return HCITrySend(pProt,pPacket,Synchronous);
1072}
1073
1074void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans)
1075{
1076 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1077
1078 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStop \n"));
1079
1080 LOCK_AR6K(pProt->pDev);
1081 if (pProt->HCIStopped) {
1082 UNLOCK_AR6K(pProt->pDev);
1083 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
1084 return;
1085 }
1086 pProt->HCIStopped = TRUE;
1087 UNLOCK_AR6K(pProt->pDev);
1088
1089
1090 DevGMboxIRQAction(pProt->pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC);
1091 FlushSendQueue(pProt);
1092 FlushRecvBuffers(pProt);
1093
1094
1095 DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_OFF, BTOFF_TIMEOUT_MS);
1096
1097 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
1098}
1099
1100A_STATUS HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans)
1101{
1102 A_STATUS status;
1103 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1104
1105 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStart \n"));
1106
1107
1108 pProt->HCIStopped = TRUE;
1109
1110 do {
1111
1112 status = InitTxCreditState(pProt);
1113
1114 if (A_FAILED(status)) {
1115 break;
1116 }
1117
1118 status = DevGMboxIRQAction(pProt->pDev, GMBOX_ERRORS_IRQ_ENABLE, PROC_IO_SYNC);
1119
1120 if (A_FAILED(status)) {
1121 break;
1122 }
1123
1124 status = DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_SYNC);
1125
1126 if (A_FAILED(status)) {
1127 break;
1128 }
1129
1130 status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_ON, BTON_TIMEOUT_MS);
1131
1132 if (A_FAILED(status)) {
1133 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI_TransportStart : Failed to trigger BT ON \n"));
1134 break;
1135 }
1136
1137
1138 pProt->HCIStopped = FALSE;
1139
1140 } while (FALSE);
1141
1142 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStart \n"));
1143
1144 return status;
1145}
1146
1147A_STATUS HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable)
1148{
1149 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1150 return DevGMboxIRQAction(pProt->pDev,
1151 Enable ? GMBOX_RECV_IRQ_ENABLE : GMBOX_RECV_IRQ_DISABLE,
1152 PROC_IO_SYNC);
1153
1154}
1155
1156A_STATUS HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
1157 HTC_PACKET *pPacket,
1158 int MaxPollMS)
1159{
1160 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1161 A_STATUS status = A_OK;
1162 A_UINT8 lookAhead[8];
1163 int bytes;
1164 int totalRecvLength;
1165
1166 MaxPollMS = MaxPollMS / 16;
1167
1168 if (MaxPollMS < 2) {
1169 MaxPollMS = 2;
1170 }
1171
1172 while (MaxPollMS) {
1173
1174 bytes = sizeof(lookAhead);
1175 status = DevGMboxRecvLookAheadPeek(pProt->pDev,lookAhead,&bytes);
1176 if (A_FAILED(status)) {
1177 break;
1178 }
1179
1180 if (bytes < 3) {
1181 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI recv poll got bytes: %d, retry : %d \n",
1182 bytes, MaxPollMS));
1183 A_MDELAY(16);
1184 MaxPollMS--;
1185 continue;
1186 }
1187
1188 totalRecvLength = 0;
1189 switch (lookAhead[0]) {
1190 case HCI_UART_EVENT_PKT:
1191 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n",
1192 lookAhead[1], lookAhead[2]));
1193 totalRecvLength = lookAhead[2];
1194 totalRecvLength += 3;
1195 break;
1196 default:
1197 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n",lookAhead[0]));
1198 status = A_EPROTO;
1199 break;
1200 }
1201
1202 if (A_FAILED(status)) {
1203 break;
1204 }
1205
1206 pPacket->Completion = NULL;
1207 status = DevGMboxRead(pProt->pDev,pPacket,totalRecvLength);
1208 if (A_FAILED(status)) {
1209 break;
1210 }
1211
1212 pPacket->pBuffer++;
1213 pPacket->ActualLength = totalRecvLength - 1;
1214 pPacket->Status = A_OK;
1215 break;
1216 }
1217
1218 if (MaxPollMS == 0) {
1219 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI recv poll timeout! \n"));
1220 status = A_ERROR;
1221 }
1222
1223 return status;
1224}
1225
1226#define LSB_SCRATCH_IDX 4
1227#define MSB_SCRATCH_IDX 5
1228A_STATUS HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud)
1229{
1230 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1231 HIF_DEVICE *pHIFDevice = (HIF_DEVICE *)(pProt->pDev->HIFDevice);
1232 A_UINT32 scaledBaud, scratchAddr;
1233 A_STATUS status = A_OK;
1234
1235
1236
1237
1238
1239 scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * LSB_SCRATCH_IDX);
1240 scaledBaud = (Baud / 100) & LOCAL_SCRATCH_VALUE_MASK;
1241 status = ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud);
1242 scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * MSB_SCRATCH_IDX);
1243 scaledBaud = ((Baud / 100) >> (LOCAL_SCRATCH_VALUE_MSB+1)) & LOCAL_SCRATCH_VALUE_MASK;
1244 status |= ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud);
1245 if (A_OK != status) {
1246 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to set up baud rate in scratch register!"));
1247 return status;
1248 }
1249
1250
1251 status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BAUD_SET, BAUD_TIMEOUT_MS);
1252 if (A_OK != status) {
1253 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to tell target to change baud rate!"));
1254 }
1255
1256 return status;
1257}
1258
1259A_STATUS HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable)
1260{
1261 A_STATUS status;
1262 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1263
1264 if (Enable) {
1265 status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON, BTPWRSAV_TIMEOUT_MS);
1266 } else {
1267 status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF, BTPWRSAV_TIMEOUT_MS);
1268 }
1269
1270 if (A_FAILED(status)) {
1271 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to enable/disable HCI power management!\n"));
1272 } else {
1273 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI power management enabled/disabled!\n"));
1274 }
1275
1276 return status;
1277}
1278
1279#endif
1280
1281