static void RefillRecvBuffers(struct ar6k_hci_bridge_info *pHcidevInfo, HCI_TRANSPORT_PACKET_TYPE Type, int NumBuffers) { int length, i; void *osBuf = NULL; struct htc_packet_queue queue; struct htc_packet *pPacket; INIT_HTC_PACKET_QUEUE(&queue); if (Type == HCI_ACL_TYPE) { if (pHcidevInfo->HciNormalMode) { length = HCI_MAX_FRAME_SIZE; } else { length = MAX_ACL_RECV_LENGTH; } } else { length = MAX_EVT_RECV_LENGTH; } /* add on transport head and tail room */ length += pHcidevInfo->HCIProps.HeadRoom + pHcidevInfo->HCIProps.TailRoom; /* round up to the required I/O padding */ length = BLOCK_ROUND_UP_PWR2(length,pHcidevInfo->HCIProps.IOBlockPad); for (i = 0; i < NumBuffers; i++) { if (pHcidevInfo->HciNormalMode) { osBuf = bt_alloc_buffer(pHcidevInfo,length); } else { osBuf = A_NETBUF_ALLOC(length); } if (NULL == osBuf) { break; } pPacket = AllocHTCStruct(pHcidevInfo); if (NULL == pPacket) { FreeBtOsBuf(pHcidevInfo,osBuf); AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); break; } SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),length,Type); /* add to queue */ HTC_PACKET_ENQUEUE(&queue,pPacket); } if (i > 0) { HCI_TransportAddReceivePkts(pHcidevInfo->pHCIDev, &queue); } }
static A_STATUS RecvHCIEvent(AR3K_CONFIG_INFO *pConfig, A_UINT8 *pBuffer, int *pLength) { A_STATUS status = A_OK; HTC_PACKET *pRecvPacket = NULL; do { pRecvPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET)); if (NULL == pRecvPacket) { status = A_NO_MEMORY; AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); break; } A_MEMZERO(pRecvPacket,sizeof(HTC_PACKET)); SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE); status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev, pRecvPacket, HCI_EVENT_RESP_TIMEOUTMS); if (A_FAILED(status)) { break; } *pLength = pRecvPacket->ActualLength; } while (FALSE); if (pRecvPacket != NULL) { A_FREE(pRecvPacket); } return status; }
static int RecvHCIEvent(struct ar3k_config_info *pConfig, u8 *pBuffer, int *pLength) { int status = 0; struct htc_packet *pRecvPacket = NULL; do { pRecvPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet)); if (NULL == pRecvPacket) { status = A_NO_MEMORY; AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n")); break; } A_MEMZERO(pRecvPacket,sizeof(struct htc_packet)); SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE); status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev, pRecvPacket, HCI_EVENT_RESP_TIMEOUTMS); if (status) { break; } *pLength = pRecvPacket->ActualLength; } while (false); if (pRecvPacket != NULL) { kfree(pRecvPacket); } return status; }
A_STATUS DevSetup(AR6K_DEVICE *pDev) { A_UINT32 blocksizes[AR6K_MAILBOXES]; A_STATUS status = A_OK; int i; HTC_CALLBACKS htcCallbacks; do { DL_LIST_INIT(&pDev->ScatterReqHead); /* initialize our free list of IO packets */ INIT_HTC_PACKET_QUEUE(&pDev->RegisterIOList); A_MUTEX_INIT(&pDev->Lock); A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS)); /* the device layer handles these */ htcCallbacks.rwCompletionHandler = DevRWCompletionHandler; htcCallbacks.dsrHandler = DevDsrHandler; htcCallbacks.context = pDev; status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks); if (A_FAILED(status)) { break; } pDev->HifAttached = TRUE; /* get the addresses for all 4 mailboxes */ status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR, &pDev->MailBoxInfo, sizeof(pDev->MailBoxInfo)); if (status != A_OK) { A_ASSERT(FALSE); break; } /* carve up register I/O packets (these are for ASYNC register I/O ) */ for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) { HTC_PACKET *pIOPacket; pIOPacket = &pDev->RegIOBuffers[i].HtcPacket; SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket, pDev, pDev->RegIOBuffers[i].Buffer, AR6K_REG_IO_BUFFER_SIZE, 0); /* don't care */ AR6KFreeIOPacket(pDev,pIOPacket); } /* get the block sizes */ status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, blocksizes, sizeof(blocksizes)); if (status != A_OK) { A_ASSERT(FALSE); break; } /* note: we actually get the block size of a mailbox other than 0, for SDIO the block * size on mailbox 0 is artificially set to 1. So we use the block size that is set * for the other 3 mailboxes */ pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE]; /* must be a power of 2 */ A_ASSERT((pDev->BlockSize & (pDev->BlockSize - 1)) == 0); /* assemble mask, used for padding to a block */ pDev->BlockMask = pDev->BlockSize - 1; AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("BlockSize: %d, MailboxAddress:0x%X \n", pDev->BlockSize, pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX])); pDev->GetPendingEventsFunc = NULL; /* see if the HIF layer implements the get pending events function */ HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_PENDING_EVENTS_FUNC, &pDev->GetPendingEventsFunc, sizeof(pDev->GetPendingEventsFunc)); /* assume we can process HIF interrupt events asynchronously */ pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC; /* see if the HIF layer overrides this assumption */ HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_IRQ_PROC_MODE, &pDev->HifIRQProcessingMode, sizeof(pDev->HifIRQProcessingMode)); switch (pDev->HifIRQProcessingMode) { case HIF_DEVICE_IRQ_SYNC_ONLY: AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HIF Interrupt processing is SYNC ONLY\n")); /* see if HIF layer wants HTC to yield */ HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_IRQ_YIELD_PARAMS, &pDev->HifIRQYieldParams, sizeof(pDev->HifIRQYieldParams)); if (pDev->HifIRQYieldParams.RecvPacketYieldCount > 0) { AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requests that DSR yield per %d RECV packets \n", pDev->HifIRQYieldParams.RecvPacketYieldCount)); pDev->DSRCanYield = TRUE; } break; case HIF_DEVICE_IRQ_ASYNC_SYNC: AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n")); break; default: A_ASSERT(FALSE); } pDev->HifMaskUmaskRecvEvent = NULL; /* see if the HIF layer implements the mask/unmask recv events function */ HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, &pDev->HifMaskUmaskRecvEvent, sizeof(pDev->HifMaskUmaskRecvEvent)); AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%lX , 0x%lX\n", (unsigned long)pDev->GetPendingEventsFunc, (unsigned long)pDev->HifMaskUmaskRecvEvent)); status = DevDisableInterrupts(pDev); if (A_FAILED(status)) { break; } status = DevSetupGMbox(pDev); } while (FALSE); if (A_FAILED(status)) { if (pDev->HifAttached) { HIFDetachHTC(pDev->HIFDevice); pDev->HifAttached = FALSE; } } return status; }
int ar6000_htc_raw_open(AR_SOFTC_T *ar) { A_STATUS status; int streamID, endPt, count2; raw_htc_buffer *buffer; HTC_SERVICE_ID servicepriority; AR_RAW_HTC_T *arRaw = ar->arRawHtc; if (!arRaw) { arRaw = ar->arRawHtc = A_MALLOC(sizeof(AR_RAW_HTC_T)); if (arRaw) { A_MEMZERO(arRaw, sizeof(AR_RAW_HTC_T)); } } A_ASSERT(ar->arHtcTarget != NULL); if (!arRaw) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Faile to allocate memory for HTC RAW interface\n")); return -ENOMEM; } /* wait for target */ status = HTCWaitTarget(ar->arHtcTarget); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTCWaitTarget failed (%d)\n", status)); return -ENODEV; } for (endPt = 0; endPt < ENDPOINT_MAX; endPt++) { arRaw->arEp2RawMapping[endPt] = HTC_RAW_STREAM_NOT_MAPPED; } for (streamID = HTC_RAW_STREAM_0; streamID < HTC_RAW_STREAM_NUM_MAX; streamID++) { /* Initialize the data structures */ init_MUTEX(&arRaw->raw_htc_read_sem[streamID]); init_MUTEX(&arRaw->raw_htc_write_sem[streamID]); init_waitqueue_head(&arRaw->raw_htc_read_queue[streamID]); init_waitqueue_head(&arRaw->raw_htc_write_queue[streamID]); /* try to connect to the raw service */ status = ar6000_connect_raw_service(ar,streamID); if (A_FAILED(status)) { break; } if (arRawStream2EndpointID(ar,streamID) == 0) { break; } for (count2 = 0; count2 < RAW_HTC_READ_BUFFERS_NUM; count2 ++) { /* Initialize the receive buffers */ buffer = &arRaw->raw_htc_write_buffer[streamID][count2]; memset(buffer, 0, sizeof(raw_htc_buffer)); buffer = &arRaw->raw_htc_read_buffer[streamID][count2]; memset(buffer, 0, sizeof(raw_htc_buffer)); SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket, buffer, buffer->data, HTC_RAW_BUFFER_SIZE, arRawStream2EndpointID(ar,streamID)); /* Queue buffers to HTC for receive */ if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != A_OK) { BMIInit(); return -EIO; } } for (count2 = 0; count2 < RAW_HTC_WRITE_BUFFERS_NUM; count2 ++) { /* Initialize the receive buffers */ buffer = &arRaw->raw_htc_write_buffer[streamID][count2]; memset(buffer, 0, sizeof(raw_htc_buffer)); } arRaw->read_buffer_available[streamID] = FALSE; arRaw->write_buffer_available[streamID] = TRUE; } if (A_FAILED(status)) { return -EIO; } AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("HTC RAW, number of streams the target supports: %d \n", streamID)); servicepriority = HTC_RAW_STREAMS_SVC; /* only 1 */ /* set callbacks and priority list */ HTCSetCreditDistribution(ar->arHtcTarget, ar, NULL, /* use default */ NULL, /* use default */ &servicepriority, 1); /* Start the HTC component */ if ((status = HTCStart(ar->arHtcTarget)) != A_OK) { BMIInit(); return -EIO; } (ar)->arRawIfInit = TRUE; return 0; }
/* registered target arrival callback from the HIF layer */ HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo) { HTC_TARGET *target = NULL; A_STATUS status = A_OK; int i; A_UINT32 ctrl_bufsz; A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX]; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Enter\n")); printk("HTCCreate !!\n"); do { /* allocate target memory */ if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); status = A_ERROR; break; } A_MEMZERO(target, sizeof(HTC_TARGET)); A_MUTEX_INIT(&target->HTCLock); A_MUTEX_INIT(&target->HTCRxLock); A_MUTEX_INIT(&target->HTCTxLock); INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList); INIT_HTC_PACKET_QUEUE(&target->ControlBufferRXFreeList); /* give device layer the hif device handle */ target->Device.HIFDevice = hif_handle; /* give the device layer our context (for event processing) * the device layer will register it's own context with HIF * so we need to set this so we can fetch it in the target remove handler */ target->Device.HTCContext = target; /* set device layer target failure callback */ target->Device.TargetFailureCallback = HTCReportFailure; /* set device layer recv message pending callback */ target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler; target->EpWaitingForBuffers = ENDPOINT_MAX; A_MEMCPY(&target->HTCInitInfo,pInfo,sizeof(HTC_INIT_INFO)); /* setup device layer */ status = DevSetup(&target->Device); if (A_FAILED(status)) { break; } /* get the block sizes */ status = HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, blocksizes, sizeof(blocksizes)); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get block size info from HIF layer...\n")); break; } /* Set the control buffer size based on the block size */ if (blocksizes[1] > HTC_MAX_CONTROL_MESSAGE_LENGTH) { ctrl_bufsz = blocksizes[1] + HTC_HDR_LENGTH; } else { ctrl_bufsz = HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH; } for (i = 0;i < NUM_CONTROL_BUFFERS;i++) { target->HTCControlBuffers[i].Buffer = A_MALLOC(ctrl_bufsz); if (target->HTCControlBuffers[i].Buffer == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); status = A_ERROR; break; } } if (A_FAILED(status)) { break; } /* carve up buffers/packets for control messages */ for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) { HTC_PACKET *pControlPacket; pControlPacket = &target->HTCControlBuffers[i].HtcPacket; SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket, target, target->HTCControlBuffers[i].Buffer, ctrl_bufsz, ENDPOINT_0); HTC_FREE_CONTROL_RX(target,pControlPacket); } for (;i < NUM_CONTROL_BUFFERS;i++) { HTC_PACKET *pControlPacket; pControlPacket = &target->HTCControlBuffers[i].HtcPacket; INIT_HTC_PACKET_INFO(pControlPacket, target->HTCControlBuffers[i].Buffer, ctrl_bufsz); HTC_FREE_CONTROL_TX(target,pControlPacket); } } while (FALSE); if (A_FAILED(status)) { if (target != NULL) { HTCCleanup(target); target = NULL; } } AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Exit\n")); return target; }