Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: chromeos/drivers/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c

Issue 646055: Atheros AR600x driver + build glue (Closed)
Patch Set: Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //------------------------------------------------------------------------------
2 // <copyright file="ar6k_prot_hciUart.c" company="Atheros">
3 // Copyright (c) 2007-2008 Atheros Corporation. All rights reserved.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License version 2 as
7 // published by the Free Software Foundation;
8 //
9 // Software distributed under the License is distributed on an "AS
10 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 // implied. See the License for the specific language governing
12 // rights and limitations under the License.
13 //
14 //
15 //------------------------------------------------------------------------------
16 //==============================================================================
17 // Protocol module for use in bridging HCI-UART packets over the GMBOX interface
18 //
19 // Author(s): ="Atheros"
20 //==============================================================================
21 #include "a_config.h"
22 #include "athdefs.h"
23 #include "a_types.h"
24 #include "a_osapi.h"
25 #include "../htc_debug.h"
26 #include "hif.h"
27 #include "htc_packet.h"
28 #include "ar6k.h"
29 #include "hci_transport_api.h"
30 #include "gmboxif.h"
31
32 #ifdef ATH_AR6K_ENABLE_GMBOX
33 #define HCI_UART_COMMAND_PKT 0x01
34 #define HCI_UART_ACL_PKT 0x02
35 #define HCI_UART_SCO_PKT 0x03
36 #define HCI_UART_EVENT_PKT 0x04
37
38 #define HCI_RECV_WAIT_BUFFERS (1 << 0)
39
40 #define HCI_SEND_WAIT_CREDITS (1 << 0)
41
42 #define HCI_UART_BRIDGE_CREDIT_SIZE 128
43
44 #define CREDIT_POLL_COUNT 256
45
46 #define HCI_DELAY_PER_INTERVAL_MS 10
47 #define BTON_TIMEOUT_MS 500
48 #define BTOFF_TIMEOUT_MS 500
49
50 typedef struct {
51 HCI_TRANSPORT_CONFIG_INFO HCIConfig;
52 A_BOOL HCIAttached;
53 A_BOOL HCIStopped;
54 A_UINT32 RecvStateFlags;
55 A_UINT32 SendStateFlags;
56 HCI_TRANSPORT_PACKET_TYPE WaitBufferType;
57 HTC_PACKET_QUEUE SendQueue; /* write queue holding HCI Co mmand and ACL packets */
58 HTC_PACKET_QUEUE HCIACLRecvBuffers; /* recv queue holding buffer s for incomming ACL packets */
59 HTC_PACKET_QUEUE HCIEventBuffers; /* recv queue holding buffer s for incomming event packets */
60 AR6K_DEVICE *pDev;
61 A_MUTEX_T HCIRxLock;
62 A_MUTEX_T HCITxLock;
63 int CreditsMax;
64 int CreditsConsumed;
65 int CreditsAvailable;
66 int CreditSize;
67 int CreditsCurrentSeek;
68 int SendProcessCount;
69 } GMBOX_PROTO_HCI_UART;
70
71 #define LOCK_HCI_RX(t) A_MUTEX_LOCK(&(t)->HCIRxLock);
72 #define UNLOCK_HCI_RX(t) A_MUTEX_UNLOCK(&(t)->HCIRxLock);
73 #define LOCK_HCI_TX(t) A_MUTEX_LOCK(&(t)->HCITxLock);
74 #define UNLOCK_HCI_TX(t) A_MUTEX_UNLOCK(&(t)->HCITxLock);
75
76 #define DO_HCI_RECV_INDICATION(p,pt) \
77 { AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI: Indicate Recv on packet:0x%X status:%d len:%d type:%d \n", \
78 (A_UINT32)(pt),(pt)->Status, A_SUCCESS((pt)->Status) ? (pt)->ActualLength : 0, HCI_GET_PACKET_TYPE(pt))); \
79 (p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt)); \
80 }
81
82 #define DO_HCI_SEND_INDICATION(p,pt) \
83 { AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Indicate Send on packet:0x%X status:%d type:%d \n", \
84 (A_UINT32)(pt),(pt)->Status,HCI_GET_PACKET_TYPE(pt))); \
85 (p)->HCIConfig.pHCISendComplete((p)->HCIConfig.pContext, (pt)); \
86 }
87
88 static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B OOL Synchronous);
89
90 static void HCIUartCleanup(GMBOX_PROTO_HCI_UART *pProtocol)
91 {
92 A_ASSERT(pProtocol != NULL);
93
94 A_MUTEX_DELETE(&pProtocol->HCIRxLock);
95 A_MUTEX_DELETE(&pProtocol->HCITxLock);
96
97 A_FREE(pProtocol);
98 }
99
100 static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
101 {
102 A_STATUS status;
103 int credits;
104 int creditPollCount = CREDIT_POLL_COUNT;
105 A_BOOL gotCredits = FALSE;
106
107 pProt->CreditsConsumed = 0;
108
109 do {
110
111 if (pProt->CreditsMax != 0) {
112 /* we can only call this only once per target reset */
113 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI: InitTxCreditState - already cal led! \n"));
114 A_ASSERT(FALSE);
115 status = A_EINVAL;
116 break;
117 }
118
119 /* read the credit counter. At startup the target will set the credit co unter
120 * to the max available, we read this in a loop because it may take
121 * multiple credit counter reads to get all credits */
122
123 while (creditPollCount) {
124
125 credits = 0;
126
127 status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credi ts);
128
129 if (A_FAILED(status)) {
130 break;
131 }
132
133 if (!gotCredits && (0 == credits)) {
134 creditPollCount--;
135 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: credit is 0, retrying (%d) \n",creditPollCount));
136 A_MDELAY(HCI_DELAY_PER_INTERVAL_MS);
137 continue;
138 } else {
139 gotCredits = TRUE;
140 }
141
142 if (0 == credits) {
143 break;
144 }
145
146 pProt->CreditsMax += credits;
147 }
148
149 if (A_FAILED(status)) {
150 break;
151 }
152
153 if (0 == creditPollCount) {
154 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
155 ("** HCI : Failed to get credits! GMBOX Target was not avail able \n"));
156 status = A_ERROR;
157 break;
158 }
159
160 /* now get the size */
161 status = DevGMboxReadCreditSize(pProt->pDev, &pProt->CreditSize);
162
163 if (A_FAILED(status)) {
164 break;
165 }
166
167 } while (FALSE);
168
169 if (A_SUCCESS(status)) {
170 pProt->CreditsAvailable = pProt->CreditsMax;
171 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI : InitTxCreditState - credits avail: %d, size: %d \n",
172 pProt->CreditsAvailable, pProt->CreditSize));
173 }
174
175 return status;
176 }
177
178 static A_STATUS CreditsAvailableCallback(void *pContext, int Credits, A_BOOL Cre ditIRQEnabled)
179 {
180 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
181 A_BOOL enableCreditIrq = FALSE;
182 A_BOOL disableCreditIrq = FALSE;
183 A_BOOL doPendingSends = FALSE;
184 A_STATUS status = A_OK;
185
186 /** this callback is called under 2 conditions:
187 * 1. The credit IRQ interrupt was enabled and signaled.
188 * 2. A credit counter read completed.
189 *
190 * The function must not assume that the calling context can block !
191 */
192
193 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback (Credits:%d, IRQ: %s) \n",
194 Credits, CreditIRQEnabled ? "ON" : "OFF"));
195
196 LOCK_HCI_RX(pProt);
197
198 do {
199
200 if (0 == Credits) {
201 if (!CreditIRQEnabled) {
202 /* enable credit IRQ */
203 enableCreditIrq = TRUE;
204 }
205 break;
206 }
207
208 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: current credit state, consumed:%d available:%d max:%d seek:%d\n",
209 pProt->CreditsConsumed,
210 pProt->CreditsAvailable,
211 pProt->CreditsMax,
212 pProt->CreditsCurrentSeek));
213
214 pProt->CreditsAvailable += Credits;
215 A_ASSERT(pProt->CreditsAvailable <= pProt->CreditsMax);
216 pProt->CreditsConsumed -= Credits;
217 A_ASSERT(pProt->CreditsConsumed >= 0);
218
219 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state, consumed:%d avai lable:%d max:%d seek:%d\n",
220 pProt->CreditsConsumed,
221 pProt->CreditsAvailable,
222 pProt->CreditsMax,
223 pProt->CreditsCurrentSeek));
224
225 if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) {
226 /* we have enough credits to fullfill at least 1 packet waiting in the queue */
227 pProt->CreditsCurrentSeek = 0;
228 pProt->SendStateFlags &= ~HCI_SEND_WAIT_CREDITS;
229 doPendingSends = TRUE;
230 if (CreditIRQEnabled) {
231 /* credit IRQ was enabled, we shouldn't need it anymore */
232 disableCreditIrq = TRUE;
233 }
234 } else {
235 /* not enough credits yet, enable credit IRQ if we haven't alrea dy */
236 if (!CreditIRQEnabled) {
237 enableCreditIrq = TRUE;
238 }
239 }
240
241 } while (FALSE);
242
243 UNLOCK_HCI_RX(pProt);
244
245 if (enableCreditIrq) {
246 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Enabling credit count IRQ...\n"));
247 /* must use async only */
248 status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_ENABLE, PROC_IO _ASYNC);
249 } else if (disableCreditIrq) {
250 /* must use async only */
251 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Disabling credit count IRQ...\n"));
252 status = DevGMboxIRQAction(pProt->pDev, GMBOX_CREDIT_IRQ_DISABLE, PROC_I O_ASYNC);
253 }
254
255 if (doPendingSends) {
256 HCITrySend(pProt, NULL, FALSE);
257 }
258
259 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback \n"));
260 return status;
261 }
262
263 static INLINE void NotifyTransportFailure(GMBOX_PROTO_HCI_UART *pProt, A_STATUS status)
264 {
265 if (pProt->HCIConfig.TransportFailure != NULL) {
266 pProt->HCIConfig.TransportFailure(pProt->HCIConfig.pContext, status);
267 }
268 }
269
270 static void FailureCallback(void *pContext, A_STATUS Status)
271 {
272 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
273
274 /* target assertion occured */
275 NotifyTransportFailure(pProt, Status);
276 }
277
278 static void StateDumpCallback(void *pContext)
279 {
280 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
281
282 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("============ HCIUart State ================= =====\n"));
283 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("RecvStateFlags : 0x%X \n",pProt->RecvStat eFlags));
284 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendStateFlags : 0x%X \n",pProt->SendStat eFlags));
285 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("WaitBufferType : %d \n",pProt->WaitBuff erType));
286 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("SendQueue Depth : %d \n",HTC_PACKET_QUEU E_DEPTH(&pProt->SendQueue)));
287 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsMax : %d \n",pProt->CreditsM ax));
288 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsConsumed : %d \n",pProt->CreditsC onsumed));
289 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("CreditsAvailable : %d \n",pProt->CreditsA vailable));
290 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("============================================ ======\n"));
291 }
292
293 static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[], int ValidBytes)
294 {
295 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
296 A_STATUS status = A_OK;
297 int totalRecvLength = 0;
298 HCI_TRANSPORT_PACKET_TYPE pktType = HCI_PACKET_INVALID;
299 A_BOOL recvRefillCalled = FALSE;
300 A_BOOL blockRecv = FALSE;
301 HTC_PACKET *pPacket = NULL;
302
303 /** caller guarantees that this is a fully block-able context (synch I/O is allowed) */
304
305 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCIUartMessagePending Lookahead Bytes:%d \ n",ValidBytes));
306
307 LOCK_HCI_RX(pProt);
308
309 do {
310
311 if (ValidBytes < 3) {
312 /* not enough for ACL or event header */
313 break;
314 }
315
316 if ((LookAheadBytes[0] == HCI_UART_ACL_PKT) && (ValidBytes < 5)) {
317 /* not enough for ACL data header */
318 break;
319 }
320
321 switch (LookAheadBytes[0]) {
322 case HCI_UART_EVENT_PKT:
323 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n",
324 LookAheadBytes[1], LookAheadBytes[2]));
325 totalRecvLength = LookAheadBytes[2];
326 totalRecvLength += 3; /* add type + event code + length field */
327 pktType = HCI_EVENT_TYPE;
328 break;
329 case HCI_UART_ACL_PKT:
330 totalRecvLength = (LookAheadBytes[4] << 8) | LookAheadBytes[3];
331 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI ACL: conn:0x%X length: %d \ n",
332 ((LookAheadBytes[2] & 0xF0) << 8) | LookAheadBytes[1], t otalRecvLength));
333 totalRecvLength += 5; /* add type + connection handle + length f ield */
334 pktType = HCI_ACL_TYPE;
335 break;
336 default:
337 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n ",LookAheadBytes[0]));
338 status = A_EPROTO;
339 break;
340 }
341
342 if (A_FAILED(status)) {
343 break;
344 }
345
346 if (pProt->HCIConfig.pHCIPktRecvAlloc != NULL) {
347 UNLOCK_HCI_RX(pProt);
348 /* user is using a per-packet allocation callback */
349 pPacket = pProt->HCIConfig.pHCIPktRecvAlloc(pProt->HCIConfig.pContex t,
350 pktType,
351 totalRecvLength);
352 LOCK_HCI_RX(pProt);
353
354 } else {
355 HTC_PACKET_QUEUE *pQueue;
356 /* user is using a refill handler that can refill multiple HTC b uffers */
357
358 /* select buffer queue */
359 if (pktType == HCI_ACL_TYPE) {
360 pQueue = &pProt->HCIACLRecvBuffers;
361 } else {
362 pQueue = &pProt->HCIEventBuffers;
363 }
364
365 if (HTC_QUEUE_EMPTY(pQueue)) {
366 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
367 ("** HCI pkt type: %d has no buffers available calling alloc ation handler \n",
368 pktType));
369 /* check for refill handler */
370 if (pProt->HCIConfig.pHCIPktRecvRefill != NULL) {
371 recvRefillCalled = TRUE;
372 UNLOCK_HCI_RX(pProt);
373 /* call the re-fill handler */
374 pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext ,
375 pktType,
376 0);
377 LOCK_HCI_RX(pProt);
378 /* check if we have more buffers */
379 pPacket = HTC_PACKET_DEQUEUE(pQueue);
380 /* fall through */
381 }
382 } else {
383 pPacket = HTC_PACKET_DEQUEUE(pQueue);
384 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
385 ("HCI pkt type: %d now has %d recv buffers left \n",
386 pktType, HTC_PACKET_QUEUE_DEPTH(pQueue)));
387 }
388 }
389
390 if (NULL == pPacket) {
391 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
392 ("** HCI pkt type: %d has no buffers available stopping recv ...\n", pktType));
393 /* this is not an error, we simply need to mark that we are wait ing for buffers.*/
394 pProt->RecvStateFlags |= HCI_RECV_WAIT_BUFFERS;
395 pProt->WaitBufferType = pktType;
396 blockRecv = TRUE;
397 break;
398 }
399
400 if (totalRecvLength > (int)pPacket->BufferLength) {
401 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI-UART pkt: %d requires %d byte s (%d buffer bytes avail) ! \n",
402 LookAheadBytes[0], totalRecvLength, pPacket->BufferLength));
403 status = A_EINVAL;
404 break;
405 }
406
407 } while (FALSE);
408
409 UNLOCK_HCI_RX(pProt);
410
411 /* locks are released, we can go fetch the packet */
412
413 do {
414
415 if (A_FAILED(status) || (NULL == pPacket)) {
416 break;
417 }
418
419 /* do this synchronously, we don't need to be fast here */
420 pPacket->Completion = NULL;
421
422 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI : getting recv packet len:%d hci-ua rt-type: %s \n",
423 totalRecvLength, (LookAheadBytes[0] == HCI_UART_EVENT_PKT) ? "EV ENT" : "ACL"));
424
425 status = DevGMboxRead(pProt->pDev, pPacket, totalRecvLength);
426
427 if (A_FAILED(status)) {
428 break;
429 }
430
431 if (pPacket->pBuffer[0] != LookAheadBytes[0]) {
432 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not contain expec ted packet type: %d ! \n",
433 pPacket->pBuffer[0]));
434 status = A_EPROTO;
435 break;
436 }
437
438 if (pPacket->pBuffer[0] == HCI_UART_EVENT_PKT) {
439 /* validate event header fields */
440 if ((pPacket->pBuffer[1] != LookAheadBytes[1]) ||
441 (pPacket->pBuffer[2] != LookAheadBytes[2])) {
442 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match loo kahead! \n"));
443 DebugDumpBytes(LookAheadBytes, 3, "Expected HCI-UART Header");
444 DebugDumpBytes(pPacket->pBuffer, 3, "** Bad HCI-UART Header");
445 status = A_EPROTO;
446 break;
447 }
448 } else if (pPacket->pBuffer[0] == HCI_UART_ACL_PKT) {
449 /* validate acl header fields */
450 if ((pPacket->pBuffer[1] != LookAheadBytes[1]) ||
451 (pPacket->pBuffer[2] != LookAheadBytes[2]) ||
452 (pPacket->pBuffer[3] != LookAheadBytes[3]) ||
453 (pPacket->pBuffer[4] != LookAheadBytes[4])) {
454 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** HCI buffer does not match loo kahead! \n"));
455 DebugDumpBytes(LookAheadBytes, 5, "Expected HCI-UART Header");
456 DebugDumpBytes(pPacket->pBuffer, 5, "** Bad HCI-UART Header");
457 status = A_EPROTO;
458 break;
459 }
460 }
461
462 /* adjust buffer to move past packet ID */
463 pPacket->pBuffer++;
464 pPacket->ActualLength = totalRecvLength - 1;
465 pPacket->Status = A_OK;
466 /* indicate packet */
467 DO_HCI_RECV_INDICATION(pProt,pPacket);
468 pPacket = NULL;
469
470 /* check if we need to refill recv buffers */
471 if ((pProt->HCIConfig.pHCIPktRecvRefill != NULL) && !recvRefillCalled) {
472 HTC_PACKET_QUEUE *pQueue;
473 int watermark;
474
475 if (pktType == HCI_ACL_TYPE) {
476 watermark = pProt->HCIConfig.ACLRecvBufferWaterMark;
477 pQueue = &pProt->HCIACLRecvBuffers;
478 } else {
479 watermark = pProt->HCIConfig.EventRecvBufferWaterMark;
480 pQueue = &pProt->HCIEventBuffers;
481 }
482
483 if (HTC_PACKET_QUEUE_DEPTH(pQueue) < watermark) {
484 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
485 ("** HCI pkt type: %d watermark hit (%d) current:%d \n",
486 pktType, watermark, HTC_PACKET_QUEUE_DEPTH(pQueue)));
487 /* call the re-fill handler */
488 pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext,
489 pktType,
490 HTC_PACKET_QUEUE_DEPTH(pQueue ));
491 }
492 }
493
494 } while (FALSE);
495
496 /* check if we need to disable the reciever */
497 if (A_FAILED(status) || blockRecv) {
498 DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_DISABLE, PROC_IO_SYNC);
499 }
500
501 /* see if we need to recycle the recv buffer */
502 if (A_FAILED(status) && (pPacket != NULL)) {
503 HTC_PACKET_QUEUE queue;
504
505 if (A_EPROTO == status) {
506 DebugDumpBytes(pPacket->pBuffer, totalRecvLength, "Bad HCI-UART Recv packet");
507 }
508 /* recycle packet */
509 HTC_PACKET_RESET_RX(pPacket);
510 INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket);
511 HCI_TransportAddReceivePkts(pProt,&queue);
512 NotifyTransportFailure(pProt,status);
513 }
514
515
516 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCIUartMessagePending \n"));
517
518 return status;
519 }
520
521 static void HCISendPacketCompletion(void *Context, HTC_PACKET *pPacket)
522 {
523 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)Context;
524 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion (pPacket:0x%X) \n" ,(A_UINT32)pPacket));
525
526 if (A_FAILED(pPacket->Status)) {
527 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Send Packet (0x%X) failed: %d , len:%d \n",
528 (A_UINT32)pPacket, pPacket->Status, pPacket->ActualLength));
529 }
530
531 DO_HCI_SEND_INDICATION(pProt,pPacket);
532
533 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion \n"));
534 }
535
536 static A_STATUS SeekCreditsSynch(GMBOX_PROTO_HCI_UART *pProt)
537 {
538 A_STATUS status = A_OK;
539 int credits;
540 int retry = 100;
541
542 while (TRUE) {
543 credits = 0;
544 status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits) ;
545 if (A_FAILED(status)) {
546 break;
547 }
548 LOCK_HCI_TX(pProt);
549 pProt->CreditsAvailable += credits;
550 if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) {
551 pProt->CreditsCurrentSeek = 0;
552 UNLOCK_HCI_TX(pProt);
553 break;
554 }
555 UNLOCK_HCI_TX(pProt);
556 retry--;
557 if (0 == retry) {
558 status = A_EBUSY;
559 break;
560 }
561 A_MDELAY(20);
562 }
563
564 return status;
565 }
566
567 static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B OOL Synchronous)
568 {
569 A_STATUS status = A_OK;
570 int transferLength;
571 int creditsRequired, remainder;
572 A_UINT8 hciUartType;
573 A_BOOL synchSendComplete = FALSE;
574
575 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCITrySend (pPacket:0x%X) %s \n",(A_UINT32 )pPacket,
576 Synchronous ? "SYNC" :"ASYNC"));
577
578 LOCK_HCI_TX(pProt);
579
580 /* increment write processing count on entry */
581 pProt->SendProcessCount++;
582
583 do {
584
585 if (pProt->HCIStopped) {
586 status = A_ECANCELED;
587 break;
588 }
589
590 if (pPacket != NULL) {
591 /* packet was supplied */
592 if (Synchronous) {
593 /* in synchronous mode, the send queue can only hold 1 packe t */
594 if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
595 status = A_EBUSY;
596 A_ASSERT(FALSE);
597 break;
598 }
599
600 if (pProt->SendProcessCount > 1) {
601 /* another thread or task is draining the TX queues */
602 status = A_EBUSY;
603 A_ASSERT(FALSE);
604 break;
605 }
606
607 HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket);
608
609 } else {
610 /* see if adding this packet hits the max depth (asynchronou s mode only) */
611 if ((pProt->HCIConfig.MaxSendQueueDepth > 0) &&
612 ((HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue) + 1) >= pProt->H CIConfig.MaxSendQueueDepth)) {
613 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("HCI Send queue is full, De pth:%d, Max:%d \n",
614 HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue),
615 pProt->HCIConfig.MaxSendQueueDepth));
616 /* queue will be full, invoke any callbacks to determine what action to take */
617 if (pProt->HCIConfig.pHCISendFull != NULL) {
618 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
619 ("HCI : Calling driver's send full callback. ... \n"));
620 if (pProt->HCIConfig.pHCISendFull(pProt->HCIConfig.pCont ext,
621 pPacket) == HCI_SEND_F ULL_DROP) {
622 /* drop it */
623 status = A_NO_RESOURCE;
624 break;
625 }
626 }
627 }
628
629 HTC_PACKET_ENQUEUE(&pProt->SendQueue,pPacket);
630 }
631
632 }
633
634 if (pProt->SendStateFlags & HCI_SEND_WAIT_CREDITS) {
635 break;
636 }
637
638 if (pProt->SendProcessCount > 1) {
639 /* another thread or task is draining the TX queues */
640 break;
641 }
642
643 /***** beyond this point only 1 thread may enter ******/
644
645 /* now drain the send queue for transmission as long as we have enough
646 * credits */
647 while (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
648
649 pPacket = HTC_PACKET_DEQUEUE(&pProt->SendQueue);
650
651 switch (HCI_GET_PACKET_TYPE(pPacket)) {
652 case HCI_COMMAND_TYPE:
653 hciUartType = HCI_UART_COMMAND_PKT;
654 break;
655 case HCI_ACL_TYPE:
656 hciUartType = HCI_UART_ACL_PKT;
657 break;
658 default:
659 status = A_EINVAL;
660 A_ASSERT(FALSE);
661 break;
662 }
663
664 if (A_FAILED(status)) {
665 break;
666 }
667
668 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Got head packet:0x%X , Type:%d Length: %d Remaining Queue Depth: %d\n",
669 (A_UINT32)pPacket, HCI_GET_PACKET_TYPE(pPacket), pPacket->Actual Length,
670 HTC_PACKET_QUEUE_DEPTH(&pProt->SendQueue)));
671
672 transferLength = 1; /* UART type header is 1 byte */
673 transferLength += pPacket->ActualLength;
674 transferLength = DEV_CALC_SEND_PADDED_LEN(pProt->pDev, transferLengt h);
675
676 /* figure out how many credits this message requires */
677 creditsRequired = transferLength / pProt->CreditSize;
678 remainder = transferLength % pProt->CreditSize;
679
680 if (remainder) {
681 creditsRequired++;
682 }
683
684 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Creds Required:%d Got:%d\n",
685 creditsRequired, pProt->CreditsAvailable));
686
687 if (creditsRequired > pProt->CreditsAvailable) {
688 if (Synchronous) {
689 /* in synchronous mode we need to seek credits in synchr onously */
690 pProt->CreditsCurrentSeek = creditsRequired;
691 UNLOCK_HCI_TX(pProt);
692 status = SeekCreditsSynch(pProt);
693 LOCK_HCI_TX(pProt);
694 if (A_FAILED(status)) {
695 break;
696 }
697 /* fall through and continue processing this send op */
698 } else {
699 /* not enough credits, queue back to the head */
700 HTC_PACKET_ENQUEUE_TO_HEAD(&pProt->SendQueue,pPacket);
701 /* waiting for credits */
702 pProt->SendStateFlags |= HCI_SEND_WAIT_CREDITS;
703 /* provide a hint to reduce attempts to re-send if credi ts are dribbling back
704 * this hint is the short fall of credits */
705 pProt->CreditsCurrentSeek = creditsRequired;
706 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: packet:0x%X placed bac k in queue. head packet needs: %d credits \n",
707 (A_UINT32)pPacket, pProt->CreditsCurrent Seek));
708 pPacket = NULL;
709 UNLOCK_HCI_TX(pProt);
710
711 /* schedule a credit counter read, our CreditsAvailableC allback callback will be called
712 * with the result */
713 DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_ASYNC, NULL);
714
715 LOCK_HCI_TX(pProt);
716 break;
717 }
718 }
719
720 /* caller guarantees some head room */
721 pPacket->pBuffer--;
722 pPacket->pBuffer[0] = hciUartType;
723
724 pProt->CreditsAvailable -= creditsRequired;
725 pProt->CreditsConsumed += creditsRequired;
726 A_ASSERT(pProt->CreditsConsumed <= pProt->CreditsMax);
727
728 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: new credit state: consumed:%d available:%d max:%d\n",
729 pProt->CreditsConsumed, pProt->CreditsAvailable, p Prot->CreditsMax));
730
731 UNLOCK_HCI_TX(pProt);
732
733 /* write it out */
734 if (Synchronous) {
735 pPacket->Completion = NULL;
736 pPacket->pContext = NULL;
737 } else {
738 pPacket->Completion = HCISendPacketCompletion;
739 pPacket->pContext = pProt;
740 }
741
742 status = DevGMboxWrite(pProt->pDev,pPacket,transferLength);
743 if (Synchronous) {
744 synchSendComplete = TRUE;
745 } else {
746 pPacket = NULL;
747 }
748
749 LOCK_HCI_TX(pProt);
750
751 }
752
753 } while (FALSE);
754
755 pProt->SendProcessCount--;
756 A_ASSERT(pProt->SendProcessCount >= 0);
757 UNLOCK_HCI_TX(pProt);
758
759 if (Synchronous) {
760 A_ASSERT(pPacket != NULL);
761 if (A_SUCCESS(status) && (!synchSendComplete)) {
762 status = A_EBUSY;
763 A_ASSERT(FALSE);
764 LOCK_HCI_TX(pProt);
765 if (pPacket->ListLink.pNext != NULL) {
766 /* remove from the queue */
767 HTC_PACKET_REMOVE(&pProt->SendQueue,pPacket);
768 }
769 UNLOCK_HCI_TX(pProt);
770 }
771 } else {
772 if (A_FAILED(status) && (pPacket != NULL)) {
773 pPacket->Status = status;
774 DO_HCI_SEND_INDICATION(pProt,pPacket);
775 }
776 }
777
778 AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HCITrySend: \n"));
779 return status;
780 }
781
782 static void FlushSendQueue(GMBOX_PROTO_HCI_UART *pProt)
783 {
784 HTC_PACKET *pPacket;
785 HTC_PACKET_QUEUE discardQueue;
786
787 INIT_HTC_PACKET_QUEUE(&discardQueue);
788
789 LOCK_HCI_TX(pProt);
790
791 if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
792 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->SendQueue);
793 }
794
795 UNLOCK_HCI_TX(pProt);
796
797 /* discard packets */
798 while (!HTC_QUEUE_EMPTY(&discardQueue)) {
799 pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
800 pPacket->Status = A_ECANCELED;
801 DO_HCI_SEND_INDICATION(pProt,pPacket);
802 }
803
804 }
805
806 static void FlushRecvBuffers(GMBOX_PROTO_HCI_UART *pProt)
807 {
808 HTC_PACKET_QUEUE discardQueue;
809 HTC_PACKET *pPacket;
810
811 INIT_HTC_PACKET_QUEUE(&discardQueue);
812
813 LOCK_HCI_RX(pProt);
814 /*transfer list items from ACL and event buffer queues to the discard qu eue */
815 if (!HTC_QUEUE_EMPTY(&pProt->HCIACLRecvBuffers)) {
816 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIACLRecvBuffer s);
817 }
818 if (!HTC_QUEUE_EMPTY(&pProt->HCIEventBuffers)) {
819 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&discardQueue,&pProt->HCIEventBuffers) ;
820 }
821 UNLOCK_HCI_RX(pProt);
822
823 /* now empty the discard queue */
824 while (!HTC_QUEUE_EMPTY(&discardQueue)) {
825 pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
826 pPacket->Status = A_ECANCELED;
827 DO_HCI_RECV_INDICATION(pProt,pPacket);
828 }
829
830 }
831
832 /*** protocol module install entry point ***/
833
834 A_STATUS GMboxProtocolInstall(AR6K_DEVICE *pDev)
835 {
836 A_STATUS status = A_OK;
837 GMBOX_PROTO_HCI_UART *pProtocol = NULL;
838
839 do {
840
841 pProtocol = A_MALLOC(sizeof(GMBOX_PROTO_HCI_UART));
842
843 if (NULL == pProtocol) {
844 status = A_NO_MEMORY;
845 break;
846 }
847
848 A_MEMZERO(pProtocol, sizeof(*pProtocol));
849 pProtocol->pDev = pDev;
850 INIT_HTC_PACKET_QUEUE(&pProtocol->SendQueue);
851 INIT_HTC_PACKET_QUEUE(&pProtocol->HCIACLRecvBuffers);
852 INIT_HTC_PACKET_QUEUE(&pProtocol->HCIEventBuffers);
853 A_MUTEX_INIT(&pProtocol->HCIRxLock);
854 A_MUTEX_INIT(&pProtocol->HCITxLock);
855
856 } while (FALSE);
857
858 if (A_SUCCESS(status)) {
859 LOCK_AR6K(pDev);
860 DEV_GMBOX_SET_PROTOCOL(pDev,
861 HCIUartMessagePending,
862 CreditsAvailableCallback,
863 FailureCallback,
864 StateDumpCallback,
865 pProtocol);
866 UNLOCK_AR6K(pDev);
867 } else {
868 if (pProtocol != NULL) {
869 HCIUartCleanup(pProtocol);
870 }
871 }
872
873 return status;
874 }
875
876 /*** protocol module uninstall entry point ***/
877 void GMboxProtocolUninstall(AR6K_DEVICE *pDev)
878 {
879 GMBOX_PROTO_HCI_UART *pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROT OCOL(pDev);
880
881 if (pProtocol != NULL) {
882
883 /* notify anyone attached */
884 if (pProtocol->HCIAttached) {
885 A_ASSERT(pProtocol->HCIConfig.TransportRemoved != NULL);
886 pProtocol->HCIConfig.TransportRemoved(pProtocol->HCIConfig.pContext) ;
887 pProtocol->HCIAttached = FALSE;
888 }
889
890 HCIUartCleanup(pProtocol);
891 DEV_GMBOX_SET_PROTOCOL(pDev,NULL,NULL,NULL,NULL,NULL);
892 }
893
894 }
895
896 static A_STATUS NotifyTransportReady(GMBOX_PROTO_HCI_UART *pProt)
897 {
898 HCI_TRANSPORT_PROPERTIES props;
899 A_STATUS status = A_OK;
900
901 do {
902
903 A_MEMZERO(&props,sizeof(props));
904
905 /* HCI UART only needs one extra byte at the head to indicate the pa cket TYPE */
906 props.HeadRoom = 1;
907 props.TailRoom = 0;
908 props.IOBlockPad = pProt->pDev->BlockSize;
909 if (pProt->HCIAttached) {
910 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI: notifying attached client to tr ansport... \n"));
911 A_ASSERT(pProt->HCIConfig.TransportReady != NULL);
912 status = pProt->HCIConfig.TransportReady(pProt,
913 &props,
914 pProt->HCIConfig.pContext);
915 }
916
917 } while (FALSE);
918
919 return status;
920 }
921
922 /*********** HCI UART protocol implementation ********************************* ***************/
923
924 HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_I NFO *pInfo)
925 {
926 GMBOX_PROTO_HCI_UART *pProtocol = NULL;
927 AR6K_DEVICE *pDev;
928
929 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportAttach \n"));
930
931 pDev = HTCGetAR6KDevice(HTCHandle);
932
933 LOCK_AR6K(pDev);
934
935 do {
936
937 pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROTOCOL(pDev);
938
939 if (NULL == pProtocol) {
940 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not installed! \n"));
941 break;
942 }
943
944 if (pProtocol->HCIAttached) {
945 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol already attached! \n" ));
946 break;
947 }
948
949 A_MEMCPY(&pProtocol->HCIConfig, pInfo, sizeof(HCI_TRANSPORT_CONFIG_INFO) );
950
951 A_ASSERT(pProtocol->HCIConfig.pHCIPktRecv != NULL);
952 A_ASSERT(pProtocol->HCIConfig.pHCISendComplete != NULL);
953
954 pProtocol->HCIAttached = TRUE;
955
956 } while (FALSE);
957
958 UNLOCK_AR6K(pDev);
959
960 if (pProtocol != NULL) {
961 /* TODO ... should we use a worker? */
962 NotifyTransportReady(pProtocol);
963 }
964
965 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach (0x%X) \n",(A_UINT32)pP rotocol));
966 return (HCI_TRANSPORT_HANDLE)pProtocol;
967 }
968
969 void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans)
970 {
971 GMBOX_PROTO_HCI_UART *pProtocol = (GMBOX_PROTO_HCI_UART *)HciTrans;
972 AR6K_DEVICE *pDev = pProtocol->pDev;
973
974 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportDetach \n"));
975
976 LOCK_AR6K(pDev);
977 if (!pProtocol->HCIAttached) {
978 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not attached! \n"));
979 UNLOCK_AR6K(pDev);
980 return;
981 }
982 pProtocol->HCIAttached = FALSE;
983 UNLOCK_AR6K(pDev);
984
985 HCI_TransportStop(HciTrans);
986 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach \n"));
987 }
988
989 A_STATUS HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_Q UEUE *pQueue)
990 {
991 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
992 A_STATUS status = A_OK;
993 A_BOOL unblockRecv = FALSE;
994 HTC_PACKET *pPacket;
995
996 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCI_TransportAddReceivePkt \n"));
997
998 LOCK_HCI_RX(pProt);
999
1000 do {
1001
1002 if (pProt->HCIStopped) {
1003 status = A_ECANCELED;
1004 break;
1005 }
1006
1007 pPacket = HTC_GET_PKT_AT_HEAD(pQueue);
1008
1009 if (NULL == pPacket) {
1010 status = A_EINVAL;
1011 break;
1012 }
1013
1014 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv packet added, type :%d, len:% d num:%d \n",
1015 HCI_GET_PACKET_TYPE(pPacket), pPacket->BufferLength, HTC _PACKET_QUEUE_DEPTH(pQueue)));
1016
1017 if (HCI_GET_PACKET_TYPE(pPacket) == HCI_EVENT_TYPE) {
1018 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIEventBuffers, pQueue);
1019 } else if (HCI_GET_PACKET_TYPE(pPacket) == HCI_ACL_TYPE) {
1020 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pProt->HCIACLRecvBuffers, pQueue) ;
1021 } else {
1022 status = A_EINVAL;
1023 break;
1024 }
1025
1026 if (pProt->RecvStateFlags & HCI_RECV_WAIT_BUFFERS) {
1027 if (pProt->WaitBufferType == HCI_GET_PACKET_TYPE(pPacket)) {
1028 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" HCI recv was blocked on packet type :%d, unblocking.. \n",
1029 pProt->WaitBufferType));
1030 pProt->RecvStateFlags &= ~HCI_RECV_WAIT_BUFFERS;
1031 pProt->WaitBufferType = HCI_PACKET_INVALID;
1032 unblockRecv = TRUE;
1033 }
1034 }
1035
1036 } while (FALSE);
1037
1038 UNLOCK_HCI_RX(pProt);
1039
1040 if (A_FAILED(status)) {
1041 while (!HTC_QUEUE_EMPTY(pQueue)) {
1042 pPacket = HTC_PACKET_DEQUEUE(pQueue);
1043 pPacket->Status = A_ECANCELED;
1044 DO_HCI_RECV_INDICATION(pProt,pPacket);
1045 }
1046 }
1047
1048 if (unblockRecv) {
1049 DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_ASYNC);
1050 }
1051
1052 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCI_TransportAddReceivePkt \n"));
1053
1054 return A_OK;
1055 }
1056
1057 A_STATUS HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket , A_BOOL Synchronous)
1058 {
1059 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1060
1061 return HCITrySend(pProt,pPacket,Synchronous);
1062 }
1063
1064 void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans)
1065 {
1066 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1067
1068 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStop \n"));
1069
1070 LOCK_AR6K(pProt->pDev);
1071 if (pProt->HCIStopped) {
1072 UNLOCK_AR6K(pProt->pDev);
1073 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
1074 return;
1075 }
1076 pProt->HCIStopped = TRUE;
1077 UNLOCK_AR6K(pProt->pDev);
1078
1079 /* disable interrupts */
1080 DevGMboxIRQAction(pProt->pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC);
1081 FlushSendQueue(pProt);
1082 FlushRecvBuffers(pProt);
1083
1084 /* signal bridge side to power down BT */
1085 DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_OFF, BTOFF_TI MEOUT_MS);
1086
1087 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
1088 }
1089
1090 A_STATUS HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans)
1091 {
1092 A_STATUS status;
1093 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1094
1095 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStart \n"));
1096
1097 /* set stopped in case we have a problem in starting */
1098 pProt->HCIStopped = TRUE;
1099
1100 do {
1101
1102 status = InitTxCreditState(pProt);
1103
1104 if (A_FAILED(status)) {
1105 break;
1106 }
1107
1108 status = DevGMboxIRQAction(pProt->pDev, GMBOX_ERRORS_IRQ_ENABLE, PROC_IO _SYNC);
1109
1110 if (A_FAILED(status)) {
1111 break;
1112 }
1113 /* enable recv */
1114 status = DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_S YNC);
1115
1116 if (A_FAILED(status)) {
1117 break;
1118 }
1119 /* signal bridge side to power up BT */
1120 status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_ ON, BTON_TIMEOUT_MS);
1121
1122 if (A_FAILED(status)) {
1123 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI_TransportStart : Failed to trigg er BT ON \n"));
1124 break;
1125 }
1126
1127 /* we made it */
1128 pProt->HCIStopped = FALSE;
1129
1130 } while (FALSE);
1131
1132 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStart \n"));
1133
1134 return status;
1135 }
1136
1137 A_STATUS HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, A_BO OL Enable)
1138 {
1139 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1140 return DevGMboxIRQAction(pProt->pDev,
1141 Enable ? GMBOX_RECV_IRQ_ENABLE : GMBOX_RECV_IRQ_DIS ABLE,
1142 PROC_IO_SYNC);
1143
1144 }
1145
1146 A_STATUS HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
1147 HTC_PACKET *pPacket,
1148 int MaxPollMS)
1149 {
1150 GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
1151 A_STATUS status = A_OK;
1152 A_UINT8 lookAhead[8];
1153 int bytes;
1154 int totalRecvLength;
1155
1156 MaxPollMS = MaxPollMS / 16;
1157
1158 if (MaxPollMS < 2) {
1159 MaxPollMS = 2;
1160 }
1161
1162 while (MaxPollMS) {
1163
1164 bytes = sizeof(lookAhead);
1165 status = DevGMboxRecvLookAheadPeek(pProt->pDev,lookAhead,&bytes);
1166 if (A_FAILED(status)) {
1167 break;
1168 }
1169
1170 if (bytes < 3) {
1171 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI recv poll got bytes: %d, retry : %d \n",
1172 bytes, MaxPollMS));
1173 A_MDELAY(16);
1174 MaxPollMS--;
1175 continue;
1176 }
1177
1178 totalRecvLength = 0;
1179 switch (lookAhead[0]) {
1180 case HCI_UART_EVENT_PKT:
1181 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI Event: %d param length: %d \n",
1182 lookAhead[1], lookAhead[2]));
1183 totalRecvLength = lookAhead[2];
1184 totalRecvLength += 3; /* add type + event code + length field */
1185 break;
1186 default:
1187 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("**Invalid HCI packet type: %d \n ",lookAhead[0]));
1188 status = A_EPROTO;
1189 break;
1190 }
1191
1192 if (A_FAILED(status)) {
1193 break;
1194 }
1195
1196 pPacket->Completion = NULL;
1197 status = DevGMboxRead(pProt->pDev,pPacket,totalRecvLength);
1198 if (A_FAILED(status)) {
1199 break;
1200 }
1201
1202 pPacket->pBuffer++;
1203 pPacket->ActualLength = totalRecvLength - 1;
1204 pPacket->Status = A_OK;
1205 break;
1206 }
1207
1208 if (MaxPollMS == 0) {
1209 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI recv poll timeout! \n"));
1210 status = A_ERROR;
1211 }
1212
1213 return status;
1214 }
1215
1216 #endif //ATH_AR6K_ENABLE_GMBOX
1217
OLDNEW
« no previous file with comments | « chromeos/drivers/ath6kl/htc2/AR6000/ar6k_gmbox.c ('k') | chromeos/drivers/ath6kl/htc2/AR6000/makefile » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698