/* set HTC/Mbox operational parameters, this can only be called when the target is in the * BMI phase */ A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_UINT32 MboxIsrYieldValue, A_UINT8 HtcControlBuffers) { A_STATUS status; A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX]; do { /* get the block sizes */ status = HIFConfigureDevice(hifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, blocksizes, sizeof(blocksizes)); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_LOG_ERR,("Failed to get block size info from HIF layer...\n")); break; } /* note: we actually get the block size for mailbox 1, for SDIO the block * size on mailbox 0 is artificially set to 1 */ /* must be a power of 2 */ A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0); if (HtcControlBuffers != 0) { /* set override for number of control buffers to use */ blocksizes[1] |= ((A_UINT32)HtcControlBuffers) << 16; } /* set the host interest area for the block size */ status = BMIWriteMemory(hifDevice, HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz), (A_UCHAR *)&blocksizes[1], 4); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for IO block size failed \n")); break; } AR_DEBUG_PRINTF(ATH_LOG_INF,("Block Size Set: %d (target address:0x%X)\n", blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz))); if (MboxIsrYieldValue != 0) { /* set the host interest area for the mbox ISR yield limit */ status = BMIWriteMemory(hifDevice, HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_isr_yield_limit), (A_UCHAR *)&MboxIsrYieldValue, 4); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for yield limit failed \n")); break; } } } while (FALSE); return status; }
static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig) { A_STATUS status = A_OK; A_UINT8 hciBaudChangeCommand[] = {0x0c,0xfc,0x2,0,0}; A_UINT16 baudVal; A_UINT8 *pEvent = NULL; A_UINT8 *pBufferToFree = NULL; do { if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) { baudVal = (A_UINT16)(pConfig->AR3KBaudRate / 100); hciBaudChangeCommand[3] = (A_UINT8)baudVal; hciBaudChangeCommand[4] = (A_UINT8)(baudVal >> 8); status = SendHCICommandWaitCommandComplete(pConfig, hciBaudChangeCommand, sizeof(hciBaudChangeCommand), &pEvent, &pBufferToFree); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n")); break; } if (pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET] != 0) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR3K Config: Baud change command event status failed: %d \n", pEvent[BAUD_CHANGE_COMMAND_STATUS_OFFSET])); status = A_ECOMM; break; } AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("AR3K Config: Baud Changed to %d \n",pConfig->AR3KBaudRate)); } if (pConfig->Flags & AR3K_CONFIG_FLAG_AR3K_BAUD_CHANGE_DELAY) { /* some versions of AR3K do not switch baud immediately, up to 300MS */ A_MDELAY(325); } if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP) { /* Tell target to change UART baud rate for AR6K */ status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR3K Config: failed to set scale and step values: %d \n", status)); break; } AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate)); } } while (FALSE);
A_STATUS Abf_WlanIssueFrontEndConfig(ATHBT_FILTER_INFO * pInfo) { WMI_SET_BTCOEX_FE_ANT_CMD btcoexFeAntCmd; WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD btcoexCoLocatedBtCmd; A_UINT32 buf_fe_ant_cmd[sizeof(A_UINT32) + sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)]; A_UINT32 buf_co_located_bt_cmd[sizeof(A_UINT32) + sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)]; A_STATUS status; /* Set co-located bt type to 1, generic for any PTA based bluetooth */ buf_co_located_bt_cmd[0] = AR6000_XIOCTL_WMI_SET_BTCOEX_COLOCATED_BT_DEV; if (pInfo->Flags & ABF_BT_CHIP_IS_QCOM) { btcoexCoLocatedBtCmd.btcoexCoLocatedBTdev = 2; } else { btcoexCoLocatedBtCmd.btcoexCoLocatedBTdev = 1; } A_MEMCPY(&buf_co_located_bt_cmd[1], (void *)&btcoexCoLocatedBtCmd, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)); status = Abf_WlanDispatchIO(pInfo, AR6000_IOCTL_EXTENDED, (void *)buf_co_located_bt_cmd, (sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD) + sizeof(A_UINT32))); if (A_FAILED(status)) { A_ERR("[%s] Failed to issue Co-located BT configuration\n", __FUNCTION__); return A_ERROR; } if(pInfo->Flags & ABF_FE_ANT_IS_SA) { /* Indicate front end antenna configuration as single antenna */ A_INFO("FLAGS = %x, Issue FE antenna configuration as single \n", pInfo->Flags); btcoexFeAntCmd.btcoexFeAntType = WMI_BTCOEX_FE_ANT_SINGLE; }else { A_INFO("FLAGS = %x, Issue FE antenna configuration as dual \n", pInfo->Flags); btcoexFeAntCmd.btcoexFeAntType = WMI_BTCOEX_FE_ANT_DUAL; } buf_fe_ant_cmd[0] = AR6000_XIOCTL_WMI_SET_BTCOEX_FE_ANT; A_MEMCPY(&buf_fe_ant_cmd[1], (void *)&btcoexFeAntCmd, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)); status = Abf_WlanDispatchIO(pInfo, AR6000_IOCTL_EXTENDED, (void *)buf_fe_ant_cmd, (sizeof(WMI_SET_BTCOEX_FE_ANT_CMD) + sizeof(A_UINT32))); if (A_FAILED(status)) { A_ERR("[%s] Failed to issue FE ant configuration\n", __FUNCTION__); return A_ERROR; } return A_OK; }
A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev) { A_STATUS status = A_OK; A_UINT8 muxControl[4]; do { if (0 == pDev->MailBoxInfo.GMboxAddress) { break; } AR_DEBUG_PRINTF(ATH_DEBUG_ANY,(" GMBOX Advertised: Address:0x%X , size:%d \n", pDev->MailBoxInfo.GMboxAddress, pDev->MailBoxInfo.GMboxSize)); status = DevGMboxIRQAction(pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC); if (A_FAILED(status)) { break; } /* write to mailbox look ahead mux control register, we want the * GMBOX lookaheads to appear on lookaheads 2 and 3 * the register is 1-byte wide so we need to hit it 4 times to align the operation * to 4-bytes */ muxControl[0] = GMBOX_LA_MUX_OVERRIDE_2_3; muxControl[1] = GMBOX_LA_MUX_OVERRIDE_2_3; muxControl[2] = GMBOX_LA_MUX_OVERRIDE_2_3; muxControl[3] = GMBOX_LA_MUX_OVERRIDE_2_3; status = HIFReadWrite(pDev->HIFDevice, GMBOX_LOOKAHEAD_MUX_REG, muxControl, sizeof(muxControl), HIF_WR_SYNC_BYTE_FIX, /* hit this register 4 times */ NULL); if (A_FAILED(status)) { break; } status = GMboxProtocolInstall(pDev); if (A_FAILED(status)) { break; } pDev->GMboxEnabled = TRUE; } while (FALSE); return status; }
/* function to set up virtual scatter support if HIF layer has not implemented the interface */ static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev) { A_STATUS status = A_OK; int bufferSize, sgreqSize; int i; DEV_SCATTER_DMA_VIRTUAL_INFO *pVirtualInfo; HIF_SCATTER_REQ *pReq; bufferSize = sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO) + 2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER; sgreqSize = sizeof(HIF_SCATTER_REQ) + (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM)); for (i = 0; i < AR6K_SCATTER_REQS; i++) { /* allocate the scatter request, buffer info and the actual virtual buffer itself */ pReq = (HIF_SCATTER_REQ *)A_MALLOC(sgreqSize + bufferSize); if (NULL == pReq) { status = A_NO_MEMORY; break; } A_MEMZERO(pReq, sgreqSize); /* the virtual DMA starts after the scatter request struct */ pVirtualInfo = (DEV_SCATTER_DMA_VIRTUAL_INFO *)((A_UINT8 *)pReq + sgreqSize); A_MEMZERO(pVirtualInfo, sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO)); pVirtualInfo->pVirtDmaBuffer = &pVirtualInfo->DataArea[0]; /* align buffer to cache line in case host controller can actually DMA this */ pVirtualInfo->pVirtDmaBuffer = A_ALIGN_TO_CACHE_LINE(pVirtualInfo->pVirtDmaBuffer); /* store the structure in the private area */ pReq->HIFPrivate[0] = pVirtualInfo; /* we emulate a DMA bounce interface */ pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE; pReq->pScatterBounceBuffer = pVirtualInfo->pVirtDmaBuffer; /* free request to the list */ DevFreeScatterReq((HIF_DEVICE *)pDev,pReq); } if (A_FAILED(status)) { DevCleanupVirtualScatterSupport(pDev); } else { pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq; pDev->HifScatterInfo.pFreeReqFunc = DevFreeScatterReq; pDev->HifScatterInfo.pReadWriteScatterFunc = DevReadWriteScatter; if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) { AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K: SPI bus requires RX scatter limits\n")); pDev->HifScatterInfo.MaxScatterEntries = AR6K_MIN_SCATTER_ENTRIES_PER_REQ; pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MIN_TRANSFER_SIZE_PER_SCATTER; } else { pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ; pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER; } pDev->ScatterIsVirtual = TRUE; } return status; }
A_STATUS HTCStart(HTC_HANDLE HTCHandle) { adf_nbuf_t netbuf; A_STATUS status = A_OK; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_SETUP_COMPLETE_MSG *SetupComp; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); do { HTCConfigTargetHIFPipe(HTCHandle); #ifdef HTC_HOST_CREDIT_DIST adf_os_assert(target->InitCredits != NULL); adf_os_assert(target->EpCreditDistributionListHead != NULL); adf_os_assert(target->EpCreditDistributionListHead->pNext != NULL); /* call init credits callback to do the distribution , * NOTE: the first entry in the distribution list is ENDPOINT_0, so * we pass the start of the list after this one. */ target->InitCredits(target->pCredDistContext, target->EpCreditDistributionListHead->pNext, target->TargetCredits); #if 1 adf_os_timer_init(target->os_handle, &target->host_htc_credit_debug_timer, host_htc_credit_show, target); adf_os_timer_start(&target->host_htc_credit_debug_timer, 10000); #endif #endif /* allocate a buffer to send */ //netbuf = adf_nbuf_alloc(anet, sizeof(HTC_SETUP_COMPLETE_MSG), HTC_HDR_LENGTH, 0); netbuf = adf_nbuf_alloc(50, HTC_HDR_LENGTH, 0); if (netbuf == ADF_NBUF_NULL) { status = A_NO_MEMORY; break; } /* assemble setup complete message */ SetupComp = (HTC_SETUP_COMPLETE_MSG *)adf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_MSG)); SetupComp->MessageID = adf_os_htons(HTC_MSG_SETUP_COMPLETE_ID); /* assemble the HTC header and send to HIF layer */ status = HTCIssueSend(target, ADF_NBUF_NULL, netbuf, 0, sizeof(HTC_SETUP_COMPLETE_MSG), ENDPOINT0); if (A_FAILED(status)) { break; } } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); return status; }
/* APIs exported to other modules */ A_STATUS Abf_WlanStackNotificationInit(ATH_BT_FILTER_INSTANCE *pInstance, A_UINT32 flags) { A_STATUS status; ATHBT_FILTER_INFO *pInfo; ABF_WLAN_INFO *pAbfWlanInfo; pInfo = (ATHBT_FILTER_INFO *)pInstance->pContext; if (pInfo->pWlanInfo) { return A_OK; } pAbfWlanInfo = (ABF_WLAN_INFO *)A_MALLOC(sizeof(ABF_WLAN_INFO)); A_MEMZERO(pAbfWlanInfo,sizeof(ABF_WLAN_INFO)); A_MUTEX_INIT(&pAbfWlanInfo->hWaitEventLock); A_COND_INIT(&pAbfWlanInfo->hWaitEvent); A_MEMZERO(pAbfWlanInfo, sizeof(ABF_WLAN_INFO)); pAbfWlanInfo->pInfo = pInfo; pAbfWlanInfo->Loop = TRUE; pInfo->pWlanInfo = pAbfWlanInfo; /* Spawn a thread which will be used to process events from WLAN */ status = A_TASK_CREATE(&pInfo->hWlanThread, WlanEventThread, pAbfWlanInfo); if (A_FAILED(status)) { A_ERR("[%s] Failed to spawn a WLAN thread\n", __FUNCTION__); return A_ERROR; } A_INFO("WLAN Stack Notification init complete\n"); return A_OK; }
void DumpAR6KDevState(AR6K_DEVICE *pDev) { A_STATUS status; AR6K_IRQ_ENABLE_REGISTERS regs; AR6K_IRQ_PROC_REGISTERS procRegs; LOCK_AR6K(pDev); /* copy into our temp area */ A_MEMCPY(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); UNLOCK_AR6K(pDev); /* load the register table from the device */ status = HIFReadWrite(pDev->HIFDevice, HOST_INT_STATUS_ADDRESS, (A_UINT8 *)&procRegs, AR6K_IRQ_PROC_REGS_SIZE, HIF_RD_SYNC_BYTE_INC, NULL); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("DumpAR6KDevState : Failed to read register table (%d) \n",status)); return; } DevDumpRegisters(pDev,&procRegs,®s); if (pDev->GMboxInfo.pStateDumpCallback != NULL) { pDev->GMboxInfo.pStateDumpCallback(pDev->GMboxInfo.pProtocolContext); } /* dump any bus state at the HIF layer */ HIFConfigureDevice(pDev->HIFDevice,HIF_DEVICE_DEBUG_BUS_STATE,NULL,0); }
/* registered target arrival callback from the HIF layer */ HTC_HANDLE HTCCreate(void *hHIF, HTC_INIT_INFO *pInfo) { A_STATUS status = A_OK; HTC_TARGET *target = NULL; do { if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTC : Unable to allocate memory\n")); status = A_ERROR; break; } A_MEMCPY(&target->HTCInitInfo,pInfo,sizeof(HTC_INIT_INFO)); adf_os_mem_zero(target, sizeof(HTC_TARGET)); adf_os_spinlock_init(&target->HTCLock); adf_os_spinlock_init(&target->HTCRxLock); adf_os_spinlock_init(&target->HTCTxLock); /* setup HIF layer callbacks */ adf_os_mem_zero(&htcCallbacks, sizeof(completion_callbacks_t)); htcCallbacks.Context = target; htcCallbacks.rxCompletionHandler = HTCRxCompletionHandler; htcCallbacks.txCompletionHandler = HTCTxCompletionHandler; HIFPostInit(hHIF, target, &htcCallbacks); target->hif_dev = hHIF; adf_os_init_mutex(&target->htc_rdy_mutex); adf_os_mutex_acquire(&target->htc_rdy_mutex); /* Get HIF default pipe for HTC message exchange */ pEndpoint = &target->EndPoint[ENDPOINT0]; HIFGetDefaultPipe(hHIF, &pEndpoint->UL_PipeID, &pEndpoint->DL_PipeID); adf_os_print("[Default Pipe]UL: %x, DL: %x\n", pEndpoint->UL_PipeID, pEndpoint->DL_PipeID); /* TODO : other init */ } while (FALSE); target->host_handle = htcInfo.pContext; /* TODO INTEGRATION supply from host os handle for any os specific calls*/ target->os_handle = NULL; if (A_FAILED(status)) { HTCCleanup(target); target = NULL; } return (HTC_HANDLE)target; }
A_STATUS ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice) { A_INT32 i; struct forceROM_s { A_UINT32 addr; A_UINT32 data; }; struct forceROM_s *ForceROM; A_INT32 szForceROM; A_STATUS status = A_OK; A_UINT32 address; A_UINT32 data; static struct forceROM_s ForceROM_NEW[] = { {0x52df80, 0x20f31c07}, {0x52df84, 0x92374420}, {0x52df88, 0x1d120c03}, {0x52df8c, 0xff8216f0}, {0x52df90, 0xf01d120c}, {0x52df94, 0x81004136}, {0x52df98, 0xbc9100bd}, {0x52df9c, 0x00bba100}, {0x00008000|MC_TCAM_TARGET_ADDRESS, 0x0012dfe0}, /* Use remap entry 0 */ {0x00008000|MC_TCAM_COMPARE_ADDRESS, 0x000e2380}, {0x00008000|MC_TCAM_MASK_ADDRESS, 0x00000000}, {0x00008000|MC_TCAM_VALID_ADDRESS, 0x00000001}, {0x00018000|(LOCAL_COUNT_ADDRESS+0x10), 0}, /* clear BMI credit counter */ {0x00004000|AR6002_RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK}, }; address = 0x004ed4b0; /* REV1 target software ID is stored here */ status = ar6000_ReadRegDiag(hifDevice, &address, &data); if (A_FAILED(status) || (data != AR6002_VERSION_REV1)) { return A_ERROR; /* Not AR6002 REV1 */ } ForceROM = ForceROM_NEW; szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM); ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Force Target to recognize Host....\n")); for (i = 0; i < szForceROM; i++) { if (ar6000_WriteRegDiag(hifDevice, &ForceROM[i].addr, &ForceROM[i].data) != A_OK) { ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Cannot force Target to recognize Host!\n")); return A_ERROR; } } A_MDELAY(1000); return A_OK; }
A_STATUS HTCStart(HTC_HANDLE HTCHandle) { adf_nbuf_t netbuf; A_STATUS status = A_OK; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_SETUP_COMPLETE_EX_MSG *pSetupComp; HTC_PACKET *pSendPacket; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); do { HTCConfigTargetHIFPipe(target); /* allocate a buffer to send */ pSendPacket = HTCAllocControlTxPacket(target); if (NULL == pSendPacket) { AR_DEBUG_ASSERT(FALSE); adf_os_print("%s: allocControlTxPacket failed\n",__func__); status = A_NO_MEMORY; break; } netbuf = (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); /* assemble setup complete message */ adf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); pSetupComp = (HTC_SETUP_COMPLETE_EX_MSG *) adf_nbuf_data(netbuf); A_MEMZERO(pSetupComp,sizeof(HTC_SETUP_COMPLETE_EX_MSG)); HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG, MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID); //if (!htc_credit_flow) { if (0) { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC will not use TX credit flow control\n")); pSetupComp->SetupFlags |= HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW; } else { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC using TX credit flow control\n")); } SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); status = HTCSendPkt((HTC_HANDLE)target,pSendPacket); if (A_FAILED(status)) { break; } } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); return status; }
/* setup scatter DMA resources for each scatter request */ static A_STATUS SetupScatterResource(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq) { A_STATUS status = A_OK; void *pDMAInfo = NULL; switch (device->ScatterMethod) { case HIF_SCATTER_DMA_REAL : /* just allocate memory for the scatter list */ pDMAInfo = A_MALLOC(sizeof(HIF_SCATTER_DMA_REAL_INFO)); if (NULL == pDMAInfo) { status = A_NO_MEMORY; break; } A_MEMZERO(pDMAInfo, sizeof(HIF_SCATTER_DMA_REAL_INFO)); pReq->ScatterMethod = HIF_SCATTER_DMA_REAL; break; case HIF_SCATTER_DMA_BOUNCE : { HIF_SCATTER_DMA_BOUNCE_INFO *pBounceInfo; /* allocate the management structure */ pBounceInfo = (HIF_SCATTER_DMA_BOUNCE_INFO *)A_MALLOC(sizeof(HIF_SCATTER_DMA_BOUNCE_INFO)); if (NULL == pBounceInfo) { status = A_NO_MEMORY; break; } A_MEMZERO(pBounceInfo, sizeof(HIF_SCATTER_DMA_BOUNCE_INFO)); /* allocate a bounce buffer for the request */ status = AllocateDMABounceBuffer(device, pBounceInfo); if (A_FAILED(status)) { A_FREE(pBounceInfo); break; } pDMAInfo = pBounceInfo; pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE; pReq->pScatterBounceBuffer = pBounceInfo->pBounceBuffer + pBounceInfo->AlignmentOffset; } break; default: break; } if (pDMAInfo != NULL) { SET_DMA_INFO_SR(pReq,pDMAInfo); } return status; }
A_STATUS ConfigPipeCredits(HTC_TARGET *target, a_uint8_t pipeID, a_uint8_t credits) { A_STATUS status = A_OK; adf_nbuf_t netbuf; HTC_CONFIG_PIPE_MSG *CfgPipeCdt; do { /* allocate a buffer to send */ //netbuf = adf_nbuf_alloc(anet, sizeof(HTC_CONFIG_PIPE_MSG), HTC_HDR_LENGTH, 0); netbuf = adf_nbuf_alloc(50, HTC_HDR_LENGTH, 0); if (netbuf == ADF_NBUF_NULL) { status = A_NO_MEMORY; break; } /* assemble config pipe message */ CfgPipeCdt = (HTC_CONFIG_PIPE_MSG *)adf_nbuf_put_tail(netbuf, sizeof(HTC_CONFIG_PIPE_MSG)); CfgPipeCdt->MessageID = adf_os_htons(HTC_MSG_CONFIG_PIPE_ID); CfgPipeCdt->PipeID = pipeID; CfgPipeCdt->CreditCount = credits; /* assemble the HTC header and send to HIF layer */ #ifndef MAGPIE_SINGLE_CPU_CASE htc_spin_prep(&target->spin); #endif status = HTCIssueSend(target, ADF_NBUF_NULL, netbuf, 0, sizeof(HTC_CONFIG_PIPE_MSG), ENDPOINT0); if (A_FAILED(status)) { break; } htc_spin( &target->spin ); if (target->cfg_pipe_rsp_stat == HTC_CONFIGPIPE_SUCCESS) { status = A_OK; } else { status = A_ERROR; } } while(FALSE); return status; }
A_STATUS BMIFastDownload(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length) { A_STATUS status = A_ERROR; A_UINT32 lastWord = 0; A_UINT32 lastWordOffset = length & ~0x3; A_UINT32 unalignedBytes = length & 0x3; status = BMILZStreamStart (device, address); if (A_FAILED(status)) { return A_ERROR; } if (unalignedBytes) { /* copy the last word into a zero padded buffer */ A_MEMCPY(&lastWord, &buffer[lastWordOffset], unalignedBytes); } status = BMILZData(device, buffer, lastWordOffset); if (A_FAILED(status)) { return A_ERROR; } if (unalignedBytes) { status = BMILZData(device, (A_UINT8 *)&lastWord, 4); } if (A_SUCCESS(status)) { // // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches. // status = BMILZStreamStart (device, 0x00); if (A_FAILED(status)) { return A_ERROR; } } return status; }
A_STATUS HTCIssueSend(HTC_TARGET *target, adf_nbuf_t hdr_buf, adf_nbuf_t netbuf, a_uint8_t SendFlags, a_uint16_t len, a_uint8_t EpID) { a_uint8_t pipeID; A_STATUS status = A_OK; //adf_net_handle_t anet = target->pInstanceContext; HTC_ENDPOINT *pEndpoint = &target->EndPoint[EpID]; HTC_FRAME_HDR *HtcHdr; adf_nbuf_t tmp_nbuf; //printk("bharath %s \n",__FUNCTION__); if (hdr_buf == ADF_NBUF_NULL) { /* HTC header needs to be added on the data nbuf */ tmp_nbuf = netbuf; } else { tmp_nbuf = hdr_buf; } /* setup HTC frame header */ HtcHdr = (HTC_FRAME_HDR *)adf_nbuf_push_head(tmp_nbuf, sizeof(HTC_FRAME_HDR)); adf_os_assert(HtcHdr); if ( HtcHdr == NULL ) { adf_os_print("%s_%d: HTC Header is NULL !!!\n", __FUNCTION__, __LINE__); return A_ERROR; } HtcHdr->EndpointID = EpID; HtcHdr->Flags = SendFlags; HtcHdr->PayloadLen = adf_os_htons(len); HTC_ADD_CREDIT_SEQNO(target,pEndpoint,len,HtcHdr); /* lookup the pipe id by the endpoint id */ pipeID = pEndpoint->UL_PipeID; // if (EpID == ENDPOINT0) { /* send the buffer to the HIF layer */ status = HIFSend(target->hif_dev/*anet*/, pipeID, hdr_buf, netbuf); // } #ifdef NBUF_PREALLOC_POOL if ( A_FAILED(status) ) { adf_nbuf_pull_head(netbuf, HTC_HDR_LENGTH); } #endif return status; }
/* callback when our fetch to enable/disable completes */ static void DevGMboxIRQActionAsyncHandler(void *Context, HTC_PACKET *pPacket) { AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context; AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxIRQActionAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev)); if (A_FAILED(pPacket->Status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("IRQAction Operation (%d) failed! status:%d \n", pPacket->PktInfo.AsRx.HTCRxFlags,pPacket->Status)); } /* free this IO packet */ AR6KFreeIOPacket(pDev,pPacket); AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxIRQActionAsyncHandler \n")); }
/* callback when our fetch to enable/disable completes */ static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacket) { AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context; AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); if (A_FAILED(pPacket->Status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Failed to disable receiver, status:%d \n", pPacket->Status)); } /* free this IO packet */ AR6KFreeIOPacket(pDev,pPacket); AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDoEnableDisableRecvAsyncHandler \n")); }
A_STATUS HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen) { A_UINT32 count; A_STATUS status; switch(opcode) { case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; break; case HIF_DEVICE_GET_MBOX_ADDR: for (count = 0; count < 4; count ++) { ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); } if (configLen >= sizeof(HIF_DEVICE_MBOX_INFO)) { SetExtendedMboxWindowInfo((A_UINT16)device->func->device, (HIF_DEVICE_MBOX_INFO *)config); } break; case HIF_DEVICE_GET_IRQ_PROC_MODE: *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_SYNC_ONLY; break; case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT: if (!device->scatter_enabled) { return A_ENOTSUP; } status = SetupHIFScatterSupport(device, (HIF_DEVICE_SCATTER_SUPPORT_INFO *)config); if (A_FAILED(status)) { device->scatter_enabled = FALSE; } return status; case HIF_DEVICE_GET_OS_DEVICE: /* pass back a pointer to the SDIO function's "dev" struct */ ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->dev; break; default: AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: Unsupported configuration opcode: %d\n", opcode)); return A_ERROR; } return A_OK; }
static A_STATUS AcquireWlanAdapter(ABF_WLAN_INFO *pAbfWlanInfo) { int sd; A_STATUS status; if (pAbfWlanInfo->Handle != 0) { return A_OK; } if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { A_ERR("[%s] Error creating socket: %d\n", __FUNCTION__, sd); return A_ERROR; } pAbfWlanInfo->Handle = sd; status = GetAdapterInfo(pAbfWlanInfo); if (A_FAILED(status)) { A_ERR("[%s] Failed to get Adapter Info\n", __FUNCTION__); close(sd); pAbfWlanInfo->Handle = 0; return A_ERROR; } else { /* Try to get RTS to determinate that wlan is enabled */ A_UCHAR buf[sizeof(int)+sizeof(WMI_SET_RTS_CMD)]; ((int *)buf)[0] = AR6000_XIOCTL_AP_GET_RTS; status = Abf_WlanDispatchIO(pAbfWlanInfo->pInfo, AR6000_IOCTL_EXTENDED, (void *)buf, sizeof(buf)); if (A_FAILED(status)) { A_INFO("WMI is ready but wlan is disabled.\n"); return A_ERROR; } } return A_OK; }
A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending) { A_STATUS status = A_OK; A_UCHAR host_int_status = 0x0; A_UINT32 counter = 0x0; if(TimeoutInMs < 100) { TimeoutInMs = 100; } counter = TimeoutInMs / 100; do { //Read the Host Interrupt Status Register status = HIFReadWrite(pDev->HIFDevice, HOST_INT_STATUS_ADDRESS, &host_int_status, sizeof(A_UCHAR), HIF_RD_SYNC_BYTE_INC, NULL); if(A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status)); break; } host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)):0; if(!host_int_status) { status = A_OK; *pbIsRecvPending = FALSE; break; } else { *pbIsRecvPending = TRUE; } A_MDELAY(100); counter--; }while(counter); return status; }
A_STATUS Abf_WlanGetSleepState(ATHBT_FILTER_INFO * pInfo) { /* setup ioctl cmd */ A_UINT32 cmd = AR6000_XIOCTL_GET_WLAN_SLEEP_STATE; A_STATUS status = Abf_WlanDispatchIO(pInfo, AR6000_IOCTL_EXTENDED, (void *)&cmd, sizeof(A_UINT32)); if (A_FAILED(status)) { A_ERR("[%s] Failed to issue get WLAN sleep state\n", __FUNCTION__); return A_ERROR; } return A_OK; }
static void ar6000_hci_send_complete(void *pContext, HTC_PACKET *pPacket) { AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext; void *osbuf = pPacket->pPktContext; A_ASSERT(osbuf != NULL); A_ASSERT(pHcidevInfo != NULL); if (A_FAILED(pPacket->Status)) { if ((pPacket->Status != A_ECANCELED) && (pPacket->Status != A_NO_RESOURCE)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Send Packet Failed: %d \n",pPacket->Status)); } } FreeHTCStruct(pHcidevInfo,pPacket); FreeBtOsBuf(pHcidevInfo,osbuf); }
/* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/ A_STATUS DevDsrHandler(void *context) { AR6K_DEVICE *pDev = (AR6K_DEVICE *)context; A_STATUS status = A_OK; A_BOOL done = FALSE; A_BOOL asyncProc = FALSE; AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%X)\n", (A_UINT32)pDev)); while (!done) { status = ProcessPendingIRQs(pDev, &done, &asyncProc); if (A_FAILED(status)) { break; } if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */ asyncProc = FALSE; /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers. * this has a nice side effect of blocking us until all async read requests are completed. * This behavior is required on some HIF implementations that do not allow ASYNC * processing in interrupt handlers (like Windows CE) */ } if (asyncProc) { /* the function performed some async I/O for performance, we need to exit the ISR immediately, the check below will prevent the interrupt from being Ack'd while we handle it asynchronously */ break; } } if (A_SUCCESS(status) && !asyncProc) { /* Ack the interrupt only if : * 1. we did not get any errors in processing interrupts * 2. there are no outstanding async processing requests */ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler \n")); HIFAckInterrupt(pDev->HIFDevice); } AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n")); return status; }
/* disable packet reception (used in case the host runs out of buffers) * this is the "override" method when the HIF reports another methods to * disable recv events */ static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode) { A_STATUS status = A_OK; HTC_PACKET *pIOPacket = NULL; AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n", EnableRecv,AsyncMode)); do { if (AsyncMode) { pIOPacket = AR6KAllocIOPacket(pDev); if (NULL == pIOPacket) { status = A_NO_MEMORY; A_ASSERT(FALSE); break; } /* stick in our completion routine when the I/O operation completes */ pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler; pIOPacket->pContext = pDev; /* call the HIF layer override and do this asynchronously */ status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice, EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV, pIOPacket); break; } /* if we get here we are doing it synchronously */ status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice, EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV, NULL); } while (FALSE); if (A_FAILED(status) && (pIOPacket != NULL)) { AR6KFreeIOPacket(pDev,pIOPacket); } return status; }
A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer, int *pLookAheadBytes) { A_STATUS status = A_OK; AR6K_IRQ_PROC_REGISTERS procRegs; int maxCopy; do { /* on entry the caller provides the length of the lookahead buffer */ if (*pLookAheadBytes > sizeof(procRegs.rx_gmbox_lookahead_alias)) { A_ASSERT(FALSE); status = A_EINVAL; break; } maxCopy = *pLookAheadBytes; *pLookAheadBytes = 0; /* load the register table from the device */ status = HIFReadWrite(pDev->HIFDevice, HOST_INT_STATUS_ADDRESS, (A_UINT8 *)&procRegs, AR6K_IRQ_PROC_REGS_SIZE, HIF_RD_SYNC_BYTE_INC, NULL); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("DevGMboxRecvLookAheadPeek : Failed to read register table (%d) \n",status)); break; } if (procRegs.gmbox_rx_avail > 0) { int bytes = procRegs.gmbox_rx_avail > maxCopy ? maxCopy : procRegs.gmbox_rx_avail; A_MEMCPY(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes); *pLookAheadBytes = bytes; } } while (FALSE); return status; }
/* assembly action lists from the action table, this is called after the OS-porting layer * has had a chance to alter the action table */ A_STATUS FCore_RefreshActionList(BT_FILTER_CORE_INFO *pCore) { int indication,state; A_STATUS status = A_OK; /* clean up previous ones */ CleanupActionLists(pCore); for (state = 0; (state < STATE_MAX) && A_SUCCESS(status); state++) { for (indication = 0; (indication < ATH_BT_MAX_STATE_INDICATION) && A_SUCCESS(status); indication++) { status = AssembleActionList(pCore, &pCore->ActionDescriptors[indication].Action[state], &pCore->ActionListsState[indication][state]); } } if (A_FAILED(status)) { FCore_Cleanup(pCore); } return status; }
static A_STATUS GetAdapterInfo(ABF_WLAN_INFO *pAbfWlanInfo) { A_STATUS status; struct ar6000_version *revinfo; revinfo = (struct ar6000_version *)A_MALLOC(sizeof(struct ar6000_version)); if (revinfo == NULL) { A_ERR("[%s] Failed to alloc WLAN revision info\n", __FUNCTION__); return A_ERROR; } /* Get the revision info */ status = Abf_WlanDispatchIO(pAbfWlanInfo->pInfo, AR6000_IOCTL_WMI_GETREV, (void *)revinfo, sizeof(struct ar6000_version)); if (A_FAILED(status)) { A_ERR("[%s] Failed to get WLAN revision\n", __FUNCTION__); return A_ERROR; } pAbfWlanInfo->HostVersion = revinfo->host_ver; pAbfWlanInfo->TargetVersion = revinfo->target_ver; A_INFO("Host Rev: 0x%x(%u.%u.%u.%u), Target Rev: 0x%x(%u.%u.%u.%u)\n", revinfo->host_ver, ((revinfo->host_ver)&0xf0000000)>>28, ((revinfo->host_ver)&0x0f000000)>>24, ((revinfo->host_ver)&0x00ff0000)>>16, ((revinfo->host_ver)&0x0000ffff), revinfo->target_ver, ((revinfo->target_ver)&0xf0000000)>>28, ((revinfo->target_ver)&0x0f000000)>>24, ((revinfo->target_ver)&0x00ff0000)>>16, ((revinfo->target_ver)&0x0000ffff)); A_FREE(revinfo); return A_OK; }
/* callback when our fetch to enable/disable completes */ static void DevGMboxReadCreditsAsyncHandler(void *Context, HTC_PACKET *pPacket) { AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context; AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxReadCreditsAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev)); if (A_FAILED(pPacket->Status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Read Credit Operation failed! status:%d \n", pPacket->Status)); } else { int credits = 0; credits = ProcessCreditCounterReadBuffer(pPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE); pDev->GMboxInfo.pCreditsPendingCallback(pDev->GMboxInfo.pProtocolContext, credits, pDev->GMboxInfo.CreditCountIRQEnabled); } /* free this IO packet */ AR6KFreeIOPacket(pDev,pPacket); AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxReadCreditsAsyncHandler \n")); }
/* assemble the action list based on the descriptor list */ static A_STATUS AssembleActionList(BT_FILTER_CORE_INFO * pCore, BT_CONTROL_ACTION_DESC *pDesc, DL_LIST *pActionListHead) { BT_CONTROL_ACTION_ITEM *pControlItem; A_CHAR *pActionString; A_CHAR *pStringToScan; int length; A_STATUS status = A_OK; for ( ;((pDesc != NULL) && A_SUCCESS(status)); pDesc = pDesc->pNext) { if (NULL == pDesc->pActionString) { continue; } /* scan the action string and assemble all actions */ pStringToScan = pDesc->pActionString; while (1) { length = FindActionString(pStringToScan, &pActionString); if (0 == length) { break; } /* found the string, now build the action */ status = BuildActionFromString(pCore, pActionString, length , &pControlItem); if (A_FAILED(status)) { break; } /* insert into the list head in FIFO order */ DL_ListInsertTail(pActionListHead,&pControlItem->ListEntry); /* scan the rest of the string */ pStringToScan = pActionString + length; } } return status; }
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; }