A_STATUS HIF_USBDeviceInserted(adf_os_handle_t os_hdl) { void *hHIF = NULL; A_STATUS status = A_OK; hHIF = HIFInit(os_hdl); /* Inform HTC */ if ( (hHIF != NULL) && htcDrvRegCallbacks.deviceInsertedHandler) { status = htcDrvRegCallbacks.deviceInsertedHandler(hHIF, os_hdl); if (A_SUCCESS(status)) return A_OK; else return A_ERROR; } else { return A_ERROR; } }
/* 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; }
int HIFDoDeviceSuspend(HIF_DEVICE *device) { A_STATUS status = A_OK; if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) { status = osdrvCallbacks.deviceSuspendHandler(device->claimedContext); } if (status == A_OK) { /* Waiting for all pending request */ if (!IS_ERR(device->async_task)) { init_completion(&device->async_completion); device->async_shutdown = 1; up(&device->sem_async); wait_for_completion(&device->async_completion); device->async_task = NULL; } device->is_suspend = TRUE; } else if (status == A_EBUSY) { return -EBUSY; /* Return -1 if customer use all android patch of mmc stack provided by us */ } return A_SUCCESS(status) ? 0 : 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 DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize) { A_STATUS status; A_UINT8 buffer[4]; status = HIFReadWrite(pDev->HIFDevice, AR6K_GMBOX_CREDIT_SIZE_ADDRESS, buffer, sizeof(buffer), HIF_RD_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */ NULL); if (A_SUCCESS(status)) { if (buffer[0] == 0) { *pCreditSize = 256; } else { *pCreditSize = buffer[0]; } } return status; }
/* * Call netif_stop_queue frequently will impact the mboxping tx t-put. * Return HTC_SEND_FULL_KEEP directly in epping_tx_queue_full to avoid. */ return HTC_SEND_FULL_KEEP; } #endif /* HIF_SDIO */ void epping_tx_complete_multiple(void *ctx, HTC_PACKET_QUEUE *pPacketQueue) { epping_context_t *pEpping_ctx = (epping_context_t *)ctx; epping_adapter_t *pAdapter = pEpping_ctx->epping_adapter; struct net_device* dev = pAdapter->dev; A_STATUS status; HTC_ENDPOINT_ID eid; adf_nbuf_t pktSkb; struct epping_cookie *cookie; A_BOOL flushing = FALSE; adf_nbuf_queue_t skb_queue; HTC_PACKET *htc_pkt; adf_nbuf_queue_init(&skb_queue); adf_os_spin_lock_bh(&pAdapter->data_lock); while (!HTC_QUEUE_EMPTY(pPacketQueue)) { htc_pkt = HTC_PACKET_DEQUEUE(pPacketQueue); if (htc_pkt == NULL) break; status=htc_pkt->Status; eid=htc_pkt->Endpoint; pktSkb=GET_HTC_PACKET_NET_BUF_CONTEXT(htc_pkt); cookie = htc_pkt->pPktContext; if (!pktSkb) { EPPING_LOG(VOS_TRACE_LEVEL_ERROR, "%s: pktSkb is NULL", __func__); ASSERT(0); } else { if (htc_pkt->pBuffer != adf_nbuf_data(pktSkb)) { EPPING_LOG(VOS_TRACE_LEVEL_ERROR, "%s: htc_pkt buffer not equal to skb->data", __func__); ASSERT(0); } /* add this to the list, use faster non-lock API */ adf_nbuf_queue_add(&skb_queue,pktSkb); if (A_SUCCESS(status)) if (htc_pkt->ActualLength != adf_nbuf_len(pktSkb)) { EPPING_LOG(VOS_TRACE_LEVEL_ERROR, "%s: htc_pkt length not equal to skb->len", __func__); ASSERT(0); } } EPPING_LOG(VOS_TRACE_LEVEL_INFO, "%s skb=%p data=%p len=0x%x eid=%d ", __func__, pktSkb, htc_pkt->pBuffer, htc_pkt->ActualLength, eid); if (A_FAILED(status)) { if (status == A_ECANCELED) { /* a packet was flushed */ flushing = TRUE; } if (status != A_NO_RESOURCE) { printk("%s() -TX ERROR, status: 0x%x\n", __func__, status); } } else { EPPING_LOG(VOS_TRACE_LEVEL_INFO, "%s: OK\n", __func__); flushing = FALSE; } epping_free_cookie(pAdapter->pEpping_ctx, cookie); } adf_os_spin_unlock_bh(&pAdapter->data_lock); /* free all skbs in our local list */ while (adf_nbuf_queue_len(&skb_queue)) { /* use non-lock version */ pktSkb = adf_nbuf_queue_remove(&skb_queue); if (pktSkb == NULL) break; adf_nbuf_tx_free(pktSkb, ADF_NBUF_PKT_ERROR); pEpping_ctx->total_tx_acks++; } if (!flushing) { netif_wake_queue(dev); } }
/* callback when our fetch to get interrupt status registers completes */ static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket) { AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context; A_UINT32 lookAhead = 0; A_BOOL otherInts = FALSE; AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev)); do { if (A_FAILED(pPacket->Status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" GetEvents I/O request failed, status:%d \n", pPacket->Status)); /* bail out, don't unmask HIF interrupt */ break; } if (pDev->GetPendingEventsFunc != NULL) { /* the HIF layer collected the information for us */ HIF_PENDING_EVENTS_INFO *pEvents = (HIF_PENDING_EVENTS_INFO *)pPacket->pBuffer; if (pEvents->Events & HIF_RECV_MSG_AVAIL) { lookAhead = pEvents->LookAhead; if (0 == lookAhead) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler1, lookAhead is zero! \n")); } } if (pEvents->Events & HIF_OTHER_EVENTS) { otherInts = TRUE; } } else { /* standard interrupt table handling.... */ AR6K_IRQ_PROC_REGISTERS *pReg = (AR6K_IRQ_PROC_REGISTERS *)pPacket->pBuffer; A_UINT8 host_int_status; host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable; if (host_int_status & (1 << HTC_MAILBOX)) { host_int_status &= ~(1 << HTC_MAILBOX); if (pReg->rx_lookahead_valid & (1 << HTC_MAILBOX)) { /* mailbox has a message and the look ahead is valid */ lookAhead = pReg->rx_lookahead[HTC_MAILBOX]; if (0 == lookAhead) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler2, lookAhead is zero! \n")); } } } if (host_int_status) { /* there are other interrupts to handle */ otherInts = TRUE; } } if (otherInts || (lookAhead == 0)) { /* if there are other interrupts to process, we cannot do this in the async handler so * ack the interrupt which will cause our sync handler to run again * if however there are no more messages, we can now ack the interrupt */ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d, lookahead:0x%X)\n", otherInts, lookAhead)); HIFAckInterrupt(pDev->HIFDevice); } else { int fetched = 0; A_STATUS status; AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n", lookAhead)); /* lookahead is non-zero and there are no other interrupts to service, * go get the next message */ status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, NULL, &fetched); if (A_SUCCESS(status) && !fetched) { /* HTC layer could not pull out messages due to lack of resources, stop IRQ processing */ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not pull any messages, force-ack \n")); DevAsyncIrqProcessComplete(pDev); } } } while (FALSE); /* free this IO packet */ AR6KFreeIOPacket(pDev,pPacket); AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n")); }
/* 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%lX)\n", (unsigned long)pDev)); /* reset the recv counter that tracks when we need to yield from the DSR */ pDev->CurrentDSRRecvCount = 0; /* reset counter used to flag a re-scan of IRQ status registers on the target */ pDev->RecheckIRQStatusCnt = 0; 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 (pDev->DSRCanYield && DEV_CHECK_RECV_YIELD(pDev)) { /* ProcessPendingIRQs() pulled enough recv messages to satisfy the yield count, stop * checking for more messages and return */ break; } } 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 */ if (pDev->DSRCanYield) { /* if the DSR can yield do not ACK the interrupt, there could be more pending messages. * The HIF layer must ACK the interrupt on behalf of HTC */ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Yield in effect (cur RX count: %d) \n", pDev->CurrentDSRRecvCount)); } else { AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler \n")); HIFAckInterrupt(pDev->HIFDevice); } } AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n")); return status; }
/** * htc_setup_target_buffer_assignments() - setup target buffer assignments * @target: HTC Target Pointer * * Return: A_STATUS */ A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target) { HTC_SERVICE_TX_CREDIT_ALLOCATION *pEntry; A_STATUS status; int credits; int creditsPerMaxMsg; creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize; if (MAX_MESSAGE_SIZE % target->TargetCreditSize) { creditsPerMaxMsg++; } /* TODO, this should be configured by the caller! */ credits = target->TotalTransmitCredits; pEntry = &target->ServiceTxAllocTable[0]; /* * Allocate all credists/HTC buffers to WMI. * no buffers are used/required for data. data always * remains on host. */ status = A_OK; pEntry++; pEntry->ServiceID = WMI_CONTROL_SVC; pEntry->CreditAllocation = credits; if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { /* endpoint ping is a testing tool directly on top of HTC in * both target and host sides. * In target side, the endppint ping fw has no wlan stack and the * FW mboxping app directly sits on HTC and it simply drops * or loops back TX packets. For rx perf, FW mboxping app * generates packets and passes packets to HTC to send to host. * There is no WMI mesage exchanges between host and target * in endpoint ping case. * In host side, the endpoint ping driver is a Ethernet driver * and it directly sits on HTC. Only HIF, HTC, CDF, ADF are * used by the endpoint ping driver. There is no wifi stack * at all in host side also. For tx perf use case, * the user space mboxping app sends the raw packets to endpoint * ping driver and it directly forwards to HTC for transmission * to stress the bus. For the rx perf, HTC passes the received * packets to endpoint ping driver and it is passed to the user * space through the Ethernet interface. * For credit allocation, in SDIO bus case, only BE service is * used for tx/rx perf testing so that all credits are given * to BE service. In PCIe and USB bus case, endpoint ping uses both * BE and BK services to stress the bus so that the total credits * are equally distributed to BE and BK services. */ pEntry->ServiceID = WMI_DATA_BE_SVC; pEntry->CreditAllocation = (credits >> 1); pEntry++; pEntry->ServiceID = WMI_DATA_BK_SVC; pEntry->CreditAllocation = (credits >> 1); } if (A_SUCCESS(status)) { int i; for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) { if (target->ServiceTxAllocTable[i].ServiceID != 0) { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC Service Index : %d TX : 0x%2.2X : alloc:%d \n", i, target->ServiceTxAllocTable[i]. ServiceID, target->ServiceTxAllocTable[i]. CreditAllocation)); } } } return status; }
/* registered target arrival callback from the HIF layer */ static A_STATUS HTCTargetInsertedHandler(void *hif_handle) { HTC_TARGET *target = NULL; A_STATUS status; int i; A_UINT32 ctrl_bufsz; A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX]; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Enter\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; /* 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_SUCCESS(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" calling AddInstance callback \n")); /* announce ourselves */ HTCInitInfo.AddInstance((HTC_HANDLE)target); } else { if (target != NULL) { HTCCleanup(target); } } AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Exit\n")); return status; }
static A_STATUS WirelessCustomEvent(ATH_BT_FILTER_INSTANCE *pInstance, char *buf, int len) { char *ptr; int length, i; A_UINT16 eventid; WMI_READY_EVENT *ev1; WMI_CONNECT_EVENT *ev2; WMI_REPORT_SLEEP_STATE_EVENT * ev3; A_STATUS status = A_OK; ATHBT_FILTER_INFO *pInfo = (ATHBT_FILTER_INFO *)pInstance->pContext; ABF_WLAN_INFO *pAbfWlanInfo = pInfo->pWlanInfo; do { eventid = *((A_UINT16 *)buf); ptr = buf + 2; //Skip the event id length = len - 2; switch (eventid) { case (WMI_READY_EVENTID): if (length < sizeof(WMI_READY_EVENT)) { A_ERR("[%s:%d] Check Failed\n", __FUNCTION__, __LINE__); status = A_ERROR; break; } ev1 = (WMI_READY_EVENT *)ptr; A_MEMCPY(pAbfWlanInfo->AdapterName, ev1->macaddr, ATH_MAC_LEN); pAbfWlanInfo->PhyCapability = ev1->phyCapability; A_DEBUG("WMI READY: Capability: %d, Address: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", pAbfWlanInfo->PhyCapability, (pAbfWlanInfo->AdapterName[0]), (pAbfWlanInfo->AdapterName[1]), (pAbfWlanInfo->AdapterName[2]), (pAbfWlanInfo->AdapterName[3]), (pAbfWlanInfo->AdapterName[4]), (pAbfWlanInfo->AdapterName[5])); /* * Open a handle for the ioctls that will be issued later * Try 10 times because the driver may not yet be ready to receive * IOCTLs, so we give the driver time to get ready by looping here */ for (i = 0; i <= 10; i++) { status = AcquireWlanAdapter(pAbfWlanInfo); if (A_SUCCESS(status)) { break; /* Break out of FOR loop, but not out of switch case statement */ } sleep(1); } if (A_FAILED(status)) { A_ERR("[%s] Failed to acquire WLAN adapter\n", __FUNCTION__); break; } /* Communicate this to the Filter task */ HandleAdapterEvent(pInfo, ATH_ADAPTER_ARRIVED); A_INFO("WLAN Adapter Added\n"); break; case (WMI_CONNECT_EVENTID): if (length < sizeof(WMI_CONNECT_EVENT)) { A_ERR("[%s:%d] Check Failed\n", __FUNCTION__, __LINE__); status = A_ERROR; break; } ev2 = (WMI_CONNECT_EVENT *)ptr; pAbfWlanInfo->Channel = ev2->u.infra_ibss_bss.channel; A_DEBUG("WMI CONNECT: Channel: %d\n", ev2->u.infra_ibss_bss.channel); IndicateCurrentWLANOperatingChannel(pInfo, pAbfWlanInfo->Channel); break; case (WMI_DISCONNECT_EVENTID): A_DEBUG("WMI DISCONNECT: %d\n", len); IndicateCurrentWLANOperatingChannel(pInfo, 0); break; case (WMI_ERROR_REPORT_EVENTID): A_DEBUG("WMI ERROR REPORT: %d\n", len); break; case (WMI_SCAN_COMPLETE_EVENTID): A_DEBUG("WMI SCAN COMPLETE: %d\n", len); break; case (WMI_REPORT_SLEEP_STATE_EVENTID): A_DEBUG("WMI_REPORT_SLEEP_STATE_EVENTID: %d\n", len); if(length < sizeof(WMI_REPORT_SLEEP_STATE_EVENT)) { A_ERR("[%s]Incorrect length passed - length = %d, len =%d\n", __FUNCTION__, length, len); } ev3 = (WMI_REPORT_SLEEP_STATE_EVENT *)ptr; switch(ev3->sleepState) { case WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP: HandleAdapterEvent(pInfo, ATH_ADAPTER_REMOVED); break; case WMI_REPORT_SLEEP_STATUS_IS_AWAKE: Abf_WlanIssueFrontEndConfig( pInfo); HandleAdapterEvent(pInfo, ATH_ADAPTER_ARRIVED); break; } break; default: //A_DEBUG("Event: 0x%x, Not Handled\n", eventid); break; } } while (FALSE); return status; }
static void usb_hif_usb_recv_bundle_complete(struct urb *urb) { HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context; A_STATUS status = A_OK; adf_nbuf_t buf = NULL; HIF_USB_PIPE *pipe = urb_context->pipe; A_UINT8 *netdata, *netdata_new; A_UINT32 netlen, netlen_new; HTC_FRAME_HDR *HtcHdr; A_UINT16 payloadLen; adf_nbuf_t new_skb = NULL; AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( "+%s: recv pipe: %d, stat:%d,len:%d urb:0x%p\n", __func__, pipe->logical_pipe_num, urb->status, urb->actual_length, urb)); /* this urb is not pending anymore */ usb_hif_remove_pending_transfer(urb_context); do { if (urb->status != 0) { status = A_ECOMM; switch (urb->status) { case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* NOTE: no need to spew these errors when * device is removed * or urb is killed due to driver shutdown */ status = A_ECANCELED; break; default: AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n", __func__, pipe->logical_pipe_num, pipe->ep_address, urb->status)); break; } break; } if (urb->actual_length == 0) break; buf = urb_context->buf; if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) { A_UINT8 *data; A_UINT32 len; adf_nbuf_peek_header(buf, &data, &len); DebugDumpBytes(data, len, "hif recv data"); } adf_nbuf_peek_header(buf, &netdata, &netlen); netlen = urb->actual_length; do { #if defined(AR6004_1_0_ALIGN_WAR) A_UINT8 extra_pad; A_UINT16 act_frame_len; #endif A_UINT16 frame_len; /* Hack into HTC header for bundle processing */ HtcHdr = (HTC_FRAME_HDR *) netdata; if (HtcHdr->EndpointID >= ENDPOINT_MAX) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("athusb: Rx: invalid EndpointID=%d\n", HtcHdr->EndpointID)); break; } payloadLen = HtcHdr->PayloadLen; payloadLen = A_LE2CPU16(payloadLen); #if defined(AR6004_1_0_ALIGN_WAR) act_frame_len = (HTC_HDR_LENGTH + payloadLen); if (HtcHdr->EndpointID == 0 || HtcHdr->EndpointID == 1) { /* assumption: target won't pad on HTC endpoint * 0 & 1. */ extra_pad = 0; } else { extra_pad = A_GET_UINT8_FIELD((A_UINT8 *) HtcHdr, HTC_FRAME_HDR, ControlBytes[1]); } #endif if (payloadLen > HIF_USB_RX_BUFFER_SIZE) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("athusb: payloadLen too long %u\n", payloadLen)); break; } #if defined(AR6004_1_0_ALIGN_WAR) frame_len = (act_frame_len + extra_pad); #else frame_len = (HTC_HDR_LENGTH + payloadLen); #endif if (netlen >= frame_len) { /* allocate a new skb and copy */ #if defined(AR6004_1_0_ALIGN_WAR) new_skb = adf_nbuf_alloc(NULL, act_frame_len, 0, 4, FALSE); if (new_skb == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( "athusb: allocate skb (len=%u) failed\n", act_frame_len)); break; } adf_nbuf_peek_header(new_skb, &netdata_new, &netlen_new); adf_os_mem_copy(netdata_new, netdata, act_frame_len); adf_nbuf_put_tail(new_skb, act_frame_len); #else new_skb = adf_nbuf_alloc(NULL, frame_len, 0, 4, FALSE); if (new_skb == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( "athusb: allocate skb (len=%u) failed\n", frame_len)); break; } adf_nbuf_peek_header(new_skb, &netdata_new, &netlen_new); adf_os_mem_copy(netdata_new, netdata, frame_len); adf_nbuf_put_tail(new_skb, frame_len); #endif skb_queue_tail(&pipe->io_comp_queue, new_skb); new_skb = NULL; netdata += frame_len; netlen -= frame_len; } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( "athusb: subframe length %d not fitted into bundle packet length %d\n" , netlen, frame_len)); break; } } while (netlen); schedule_work(&pipe->io_complete_work); } while (FALSE); if (urb_context->buf == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("athusb: buffer in urb_context is NULL\n")); } /* reset urb_context->buf ==> seems not necessary */ usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context); if (A_SUCCESS(status)) { if (pipe->urb_cnt >= pipe->urb_cnt_thresh) { /* our free urbs are piling up, post more transfers */ usb_hif_post_recv_bundle_transfers(pipe, 0 /* pass zero for not allocating urb-buffer again */ ); } } AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ("-%s\n", __func__)); }
LOCAL void console_mod_start(void) { SERIAL_PORT_PROPERTIES port_properties; SER_PORT_UART_CONFIG port_config; A_STATUS status; #ifdef CONFIG_CLI console_register_commands(Default_console_commands,NUM_DEFAULT_CONSOLE_CMDS); #else console_mod_register_commands(Default_console_commands,NUM_DEFAULT_CONSOLE_CMDS); #endif /* open the logical port */ Console_info->port = SERP_Open(Console_info->config.logical_port_name, NULL, console_serial_event_callback, &port_properties); A_MEMZERO(&port_config,sizeof(port_config)); port_config.Baud = Console_info->config.baud; port_config.DataBits = 8; port_config.StopBits = 1; /* configure port */ status = SERP_Ioctl(Console_info->port, SER_PORT_IOCTL_CONFIG_UART_PORT, &port_config, sizeof(port_config)); A_ASSERT(A_SUCCESS(status)); /* set receiver threshold to 1 character */ SERP_Ioctl(Console_info->port,SER_PORT_IOCTL_SET_RX_THRESH,NULL,1); if (Console_info->config.flags & CONSOLE_CONFIG_FLAGS_ALLOW_RX_SUSPEND) { Console_info->flags |= CONSOLE_FLAGS_ALLOW_RX_SUSPEND; } if (Console_info->config.flags & CONSOLE_CONFIG_FLAGS_USE_HW_RX_WAKE) { /* try using hardware for RX wake */ Console_info->flags |= CONSOLE_FLAGS_USE_HW_RX_SUSP; } if ((UART_SERP_UART0_INSTANCE_ID == Console_info->config.phys_uart_id) || (Console_info->flags & CONSOLE_FLAGS_ALLOW_RX_SUSPEND)) { console_suspend_rx(0,NULL); /* install uart control commands */ #ifdef CONFIG_CLI console_register_commands(&Console_uart_control,1); #else console_mod_register_commands(&Console_uart_control,1); //ychen #endif } #ifndef USE_STANDALONE_CONSOLE _A_OS_INDIRECTION_TABLE->cmnos.serial._serial_putc = console_putc_replacement; #endif _A_OS_INDIRECTION_TABLE->cmnos.serial._serial_getc = console_getc_replacement; _A_OS_INDIRECTION_TABLE->cmnos.serial._serial_restore_funcs = console_restore_replacement; CONSOLE_OUTPUT("\nCLI:"); Console_info->flags = 0; CONSOLE_OUTPUT(CONSOLE_PROMPT_LINE); }
A_STATUS HTCSetupTargetBufferAssignments(HTC_TARGET *target) { HTC_SERVICE_TX_CREDIT_ALLOCATION *pEntry; A_STATUS status; int credits; int creditsPerMaxMsg; #ifdef HIF_USB unsigned int hif_usbaudioclass=0; #else unsigned int hif_usbaudioclass=0; #endif creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize; if (MAX_MESSAGE_SIZE % target->TargetCreditSize) { creditsPerMaxMsg++; } /* TODO, this should be configured by the caller! */ credits = target->TotalTransmitCredits; pEntry = &target->ServiceTxAllocTable[0]; #if defined(HIF_USB) target->avail_tx_credits = target->TotalTransmitCredits - 1 ; #endif status = A_NO_RESOURCE; #if defined(HIF_PCI) || defined(HIF_SIM) || (defined(CONFIG_HL_SUPPORT) && !defined(AR6004_HW))/* TODO: maybe change to HIF_SDIO later */ /* TODO: maybe check ROME service for USB service */ /* * for PCIE allocate all credists/HTC buffers to WMI. * no buffers are used/required for data. data always * remains on host. */ hif_usbaudioclass = 0; /* to keep compiler happy */ /* for PCIE allocate all credits to wmi for now */ status = A_OK; pEntry++; pEntry->ServiceID = WMI_CONTROL_SVC; pEntry->CreditAllocation = credits; #ifdef EPPING_TEST pEntry++; pEntry->ServiceID = WMI_DATA_BE_SVC; pEntry->CreditAllocation = credits >> 1; pEntry++; pEntry->ServiceID = WMI_DATA_BK_SVC; pEntry->CreditAllocation = credits >> 1; #endif #else do { if(hif_usbaudioclass) { AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HTCSetupTargetBufferAssignments For USB Audio Class- Total:%d\n",credits)); pEntry++; pEntry++; //Setup VO Service To have Max Credits pEntry->ServiceID = WMI_DATA_VO_SVC; pEntry->CreditAllocation = (credits -6); if (pEntry->CreditAllocation == 0) { pEntry->CreditAllocation++; } credits -= (int)pEntry->CreditAllocation; if (credits <= 0) { break; } pEntry++; pEntry->ServiceID = WMI_CONTROL_SVC; pEntry->CreditAllocation = creditsPerMaxMsg; credits -= (int)pEntry->CreditAllocation; if (credits <= 0) { break; } /* * HTT_DATA_MSG_SVG is unidirectional from target -> host, * so no target buffers are needed. */ /* leftovers go to best effort */ pEntry++; pEntry++; pEntry->ServiceID = WMI_DATA_BE_SVC; pEntry->CreditAllocation = (A_UINT8)credits; status = A_OK; break; } pEntry++; pEntry->ServiceID = WMI_DATA_VI_SVC; pEntry->CreditAllocation = credits / 4; if (pEntry->CreditAllocation == 0) { pEntry->CreditAllocation++; } credits -= (int)pEntry->CreditAllocation; if (credits <= 0) { break; } pEntry++; pEntry->ServiceID = WMI_DATA_VO_SVC; pEntry->CreditAllocation = credits / 4; if (pEntry->CreditAllocation == 0) { pEntry->CreditAllocation++; } credits -= (int)pEntry->CreditAllocation; if (credits <= 0) { break; } pEntry++; pEntry->ServiceID = WMI_CONTROL_SVC; pEntry->CreditAllocation = creditsPerMaxMsg; credits -= (int)pEntry->CreditAllocation; if (credits <= 0) { break; } /* * HTT_DATA_MSG_SVG is unidirectional from target -> host, * so no target buffers are needed. */ pEntry++; pEntry->ServiceID = WMI_DATA_BK_SVC; pEntry->CreditAllocation = creditsPerMaxMsg; credits -= (int)pEntry->CreditAllocation; if (credits <= 0) { break; } /* leftovers go to best effort */ pEntry++; pEntry->ServiceID = WMI_DATA_BE_SVC; pEntry->CreditAllocation = (A_UINT8)credits; status = A_OK; } while (FALSE); #endif if (A_SUCCESS(status)) { int i; for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) { if (target->ServiceTxAllocTable[i].ServiceID != 0) { AR_DEBUG_PRINTF(ATH_DEBUG_INIT,("HTC Service Index : %d TX : 0x%2.2X : alloc:%d \n", i, target->ServiceTxAllocTable[i].ServiceID, target->ServiceTxAllocTable[i].CreditAllocation)); } } } return status; }
A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCredits) { A_STATUS status = A_OK; HTC_PACKET *pIOPacket = NULL; AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+DevGMboxReadCreditCounter (%s) \n", AsyncMode ? "ASYNC" : "SYNC")); do { pIOPacket = AR6KAllocIOPacket(pDev); if (NULL == pIOPacket) { status = A_NO_MEMORY; A_ASSERT(FALSE); break; } A_MEMZERO(pIOPacket->pBuffer,AR6K_REG_IO_BUFFER_SIZE); if (AsyncMode) { /* stick in our completion routine when the I/O operation completes */ pIOPacket->Completion = DevGMboxReadCreditsAsyncHandler; pIOPacket->pContext = pDev; /* read registers asynchronously */ HIFReadWrite(pDev->HIFDevice, AR6K_GMBOX_CREDIT_DEC_ADDRESS, pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE, /* hit the register multiple times */ HIF_RD_ASYNC_BYTE_FIX, pIOPacket); pIOPacket = NULL; break; } pIOPacket->Completion = NULL; /* if we get here we are doing it synchronously */ status = HIFReadWrite(pDev->HIFDevice, AR6K_GMBOX_CREDIT_DEC_ADDRESS, pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE, HIF_RD_SYNC_BYTE_FIX, NULL); } while (FALSE); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" DevGMboxReadCreditCounter failed! status:%d \n", status)); } if (pIOPacket != NULL) { if (A_SUCCESS(status)) { /* sync mode processing */ *pCredits = ProcessCreditCounterReadBuffer(pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE); } AR6KFreeIOPacket(pDev,pIOPacket); } AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-DevGMboxReadCreditCounter (%s) (%d) \n", AsyncMode ? "ASYNC" : "SYNC", status)); return status; }
A_STATUS download_binary (HIF_DEVICE *hifDevice, A_UINT32 address, wchar_t *fileName, wchar_t *fileRoot, A_BOOL bCompressed, AR6K_BIN_CACHE_INFO *pBinCache) { A_STATUS status = A_OK; A_UCHAR *buffer = NULL; A_UINT32 length = 0; A_UINT32 fileSize = 0; A_UINT32 next_address=0; A_INT32 file_left = 0; size_t nSize; wchar_t filePath[128]; HANDLE fd = NULL; BY_HANDLE_FILE_INFORMATION finfo; A_BOOL fillCache = FALSE; A_MEMZERO(&finfo, sizeof(finfo)); if ( wcslen(fileName) + wcslen(fileRoot) > 127 ) { ATHR_DISPLAY_MSG (L"CAR6K::WARNING!!!! :: File Name Very Long :: ====>"); return A_ERROR; } wcscpy(filePath,fileRoot); wcscat(filePath,fileName); ATHR_DISPLAY_MSG (L"file %s \n",filePath); do { if (pBinCache->Valid) { /* binary cache is valid */ if (bCompressed) { status = BMILZStreamStart (hifDevice, address); if (A_FAILED(status)) { break; } } if (bCompressed) { A_UINT32 lastWord = 0; A_UINT32 lastWordOffset = pBinCache->ActualLength & ~0x3; A_UINT32 unalignedBytes = pBinCache->ActualLength & 0x3; if (unalignedBytes) { /* copy the last word into a zero padded buffer */ A_MEMCPY(&lastWord, &pBinCache->pData[lastWordOffset], unalignedBytes); } status = BMILZData(hifDevice, pBinCache->pData, lastWordOffset); if (A_FAILED(status)) { break; } if (unalignedBytes) { status = BMILZData(hifDevice, (A_UINT8 *)&lastWord, 4); } } else { status = BMIWriteMemory(hifDevice, address, pBinCache->pData, A_ROUND_UP(pBinCache->ActualLength,4)); } if (bCompressed && A_SUCCESS(status)) { // // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches. // status = BMILZStreamStart (hifDevice, 0x00); if (A_FAILED(status)) { break; } } /* all done */ break; } //Determine the length of the file if ( (fd = CreateFile (filePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { status = A_ERROR; ATHR_DISPLAY_MSG (L"CAR6K::WARNING!!!! :: File Not Found :: ====> %s", filePath); break; } if (!GetFileInformationByHandle(fd, &finfo)) { ATHR_DISPLAY_MSG (L"CAR6K::WARNING!!!! :: File Size Error :: ====> %s", filePath); status = A_ERROR; break; } fileSize = finfo.nFileSizeLow; file_left = fileSize; if ((pBinCache->pData != NULL) && (!pBinCache->Static)) { /* binary caching is supported */ A_ASSERT(!pBinCache->Valid); if (fileSize <= pBinCache->MaxLength) { /* size if good, flag to cache this binary when read from the filesystem */ fillCache = TRUE; pBinCache->ActualLength = 0; /* reset */ } else { /* cache is not big enough to hold data */ A_ASSERT(FALSE); ATHR_DISPLAY_MSG (L"AR6K::WARNING!!!! :: File :%s (%d bytes) too big for cache (max=%d)", filePath, fileSize, pBinCache->MaxLength); } } // // zero data buffer and init length // buffer = (A_UCHAR *)A_MALLOC(MAX_BUF); if (NULL == buffer) { status = A_ERROR; break; } if (bCompressed) { status = BMILZStreamStart (hifDevice, address); if (status != A_OK) { break; } } while (file_left) { length = (file_left < (MAX_BUF)) ? file_left : MAX_BUF; if (bCompressed) { // // 0 pad last word of data to avoid messy uncompression // ((A_UINT32 *)buffer)[((length-1)/4)] = 0; } if (!ReadFile( fd, buffer, length, &nSize, NULL) || nSize != length) { ATHR_DISPLAY_MSG (L"CAR6K::WARNING!!!! :: ReadFile Error :: ====>"); status = A_ERROR; break; } next_address = address + fileSize - file_left; // // We round up the requested length because some SDIO Host controllers can't handle other lengths. // This generally isn't a problem for users, but it's something to be aware of. // length = A_ROUND_UP(length, 4); if (bCompressed) { status = BMILZData(hifDevice, buffer, length); } else { status = BMIWriteMemory(hifDevice, next_address, buffer, length); } if (status != A_OK) { break; } if (fillCache) { CopyChunkToBinCache(pBinCache, buffer, length); } if (file_left >= MAX_BUF) { file_left = file_left - MAX_BUF; } else { file_left = 0; } }; if (status != A_OK) { break; } if (fillCache) { /* cache was filled, mark it valid */ pBinCache->Valid = TRUE; } if (bCompressed) { // // Close compressed stream and open a new (fake) one. This serves mainly to flush Target caches. // status = BMILZStreamStart (hifDevice, 0x00); if (status != A_OK) { break; } } } while (FALSE); if (buffer) { free (buffer); buffer = NULL; } if (fd) { CloseHandle (fd); } return status; }
static A_STATUS PowerChangeNotify(HIF_DEVICE *device, HIF_DEVICE_POWER_CHANGE_TYPE PowerChange) { A_STATUS status = A_OK; SD_API_STATUS sdStatus = SD_API_STATUS_SUCCESS; NDIS_DEBUG_PRINTF(1, "%s() : Enter (%d) + \r\n",__FUNCTION__,PowerChange); switch (PowerChange) { case HIF_DEVICE_POWER_UP: if (InterlockedExchange(&device->PowerStateOff, POWER_ON) != POWER_OFF) { /* shouldn't be calling this if we are not powered off */ A_ASSERT(FALSE); break; } if (device->SlotPowerRemoved) { /* power was removed from a previous power down attempt */ device->SlotPowerRemoved = FALSE; /* try powering up */ PowerUpDownSlot(device, TRUE); } /* Reinit SDIO since HIF_DEVICE_POWER_DOWN or HIF_DEVICE_POWER_OFF * would have reset the SDIO interface */ status = ReinitSDIO(device); #ifdef HIF_SDIO_BYPASS if (A_SUCCESS(status)) { /* re-activate */ g_BypassModeActive = ActivateSDIOStackBypassMode(); } #endif break; case HIF_DEVICE_POWER_DOWN: case HIF_DEVICE_POWER_CUT: /* set powered off flag, but check previous value */ if (InterlockedExchange(&device->PowerStateOff, POWER_OFF) != POWER_ON) { /* shouldn't be calling this if we are powered off already */ A_ASSERT(FALSE); break; } #ifdef HIF_SDIO_BYPASS g_BypassModeActive = FALSE; /* de-activeate bypass mode */ DeactivateSDIOStackBypassMode(); #endif /* disable I/O function and reset SDIO controller to minimize power */ sdStatus = SDSetCardFeature(device->handle, SD_IO_FUNCTION_DISABLE, NULL, 0); A_ASSERT(SD_API_SUCCESS(sdStatus)); { A_UINT8 buffer; /* Perform a I/O reset, this causes the SDIO interface * to be in the un-enumerated state */ buffer = 1 << 3; sdStatus = SDReadWriteRegistersDirect(device->handle, SD_IO_WRITE, 0, SD_IO_REG_IO_ABORT, 0, &buffer, 1); A_ASSERT(SD_API_SUCCESS(sdStatus)); } if (PowerChange == HIF_DEVICE_POWER_CUT) { /* caller wants the device to be completely off */ device->SlotPowerRemoved = PowerUpDownSlot (device, FALSE); } break; default: A_ASSERT(FALSE); return A_ERROR; } return status; }
A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int Signal, int AckTimeoutMS) { A_STATUS status = A_OK; int i; A_UINT8 buffer[4]; A_MEMZERO(buffer, sizeof(buffer)); do { if (Signal >= MBOX_SIG_HCI_BRIDGE_MAX) { status = A_EINVAL; break; } /* set the last buffer to do the actual signal trigger */ buffer[3] = (1 << Signal); status = HIFReadWrite(pDev->HIFDevice, INT_WLAN_ADDRESS, buffer, sizeof(buffer), HIF_WR_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */ NULL); if (A_FAILED(status)) { break; } } while (FALSE); if (A_SUCCESS(status)) { /* now read back the register to see if the bit cleared */ while (AckTimeoutMS) { status = HIFReadWrite(pDev->HIFDevice, INT_WLAN_ADDRESS, buffer, sizeof(buffer), HIF_RD_SYNC_BYTE_FIX, NULL); if (A_FAILED(status)) { break; } for (i = 0; i < sizeof(buffer); i++) { if (buffer[i] & (1 << Signal)) { /* bit is still set */ break; } } if (i >= sizeof(buffer)) { /* done */ break; } AckTimeoutMS--; A_MDELAY(1); } if (0 == AckTimeoutMS) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("DevGMboxSetTargetInterrupt : Ack Timed-out (sig:%d) \n",Signal)); status = A_ERROR; } } return status; }
A_STATUS RunConnectionTest() { A_STATUS status = A_OK; HTC_ENDPOINT_ID endpointID; int length; DWORD startTime; DWORD currentTime; DWORD dhcpRequestTimeStart; int dhcpAttempt = 0; /* set initial status and state */ g_WifiMTE.TestState = TEST_STATE_WAIT_WMI_READY; startTime = A_GET_SECONDS_TICK(); while (A_SUCCESS(status) && (g_WifiMTE.TestState != TEST_GEN_FAILURE)) { currentTime = A_GET_SECONDS_TICK(); A_ASSERT(startTime <= currentTime); if ((currentTime - startTime) >= CONNECTION_TEST_EXPIRATION) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("Time Expired! Current State: %d \r\n", g_WifiMTE.TestState)); status = A_ERROR; break; } endpointID = ENDPOINT_MAX; /* poll for a message */ status = HTCGetMessage(g_WifiMTE.htcHandle, &endpointID, g_WifiMTE.pReceivePayloadStart, /* reuse transmit buffer */ MAX_MESSAGE_BUFFER_SIZE, &length, 0); /* no timeout */ if (A_FAILED(status)) { break; } if (endpointID == ENDPOINT_MAX) { /* polling was successful, but no message was retrieved */ continue; } if (endpointID == g_WifiMTE.ControlEp) { /* process control message */ status = wmi_control_rx(g_WifiMTE.pReceivePayloadStart, length); } else if (endpointID == g_WifiMTE.DataEp) { A_UINT8 *pNetFrameStart; int networkFrameLength; A_UINT16 etherType; /* process data message */ /* get the frame information, the payload is the WMI message */ wmi_get_network_frame_info(g_WifiMTE.pReceivePayloadStart, length, &pNetFrameStart, &networkFrameLength, ðerType); if ((networkFrameLength != 0) && (etherType == 0x0800)) { /* an IP packet arrived */ if (!g_WifiMTE.GotDhcpOffer) { /* run it through DHCP */ if (CheckDHCPOffer(pNetFrameStart,networkFrameLength)) { g_WifiMTE.GotDhcpOffer = TRUE; } } } } else { A_ASSERT(FALSE); status = A_EPROTO; break; } if (A_FAILED(status)) { break; } /* run through state machine */ switch (g_WifiMTE.TestState) { case TEST_STATE_WAIT_WMI_READY : if (g_WifiMTE.WMIReady) { DBG_LOG_PRINT(DBG_ZONE_INIT, ("WMI is ready\n")); /* next state is to wait for connection */ g_WifiMTE.TestState = TEST_STATE_WAIT_WMI_CONNECT; status = ar6000_set_wmi_protocol_ver(g_WifiMTE.HifDevice, g_WifiMTE.TargetInfo.target_type, WMI_PROTOCOL_VERSION); if (A_FAILED(status)) { A_ASSERT(FALSE); break; } /* make sure we are fully awake */ DBG_LOG_PRINT(DBG_ZONE_INIT, ("Changing power mode\n")); status = wmi_powermode_cmd(MAX_PERF_POWER); if (A_FAILED(status)) { break; } DBG_LOG_PRINT(DBG_ZONE_INIT, ("Sending connect\n")); /* connect to SSID */ status = wmi_connect_cmd(INFRA_NETWORK, OPEN_AUTH, NONE_AUTH, NONE_CRYPT, 0, NONE_CRYPT, 0, g_WifiMTE.SSIDLength, g_WifiMTE.SSID, NULL, g_WifiMTE.WiFiChannel, 0); } break; case TEST_STATE_WAIT_WMI_CONNECT : if (g_WifiMTE.APConnected) { /* next state */ g_WifiMTE.TestState = TEST_WAIT_DHCP_REPLY; /* capture start time to retry DHCP request */ dhcpRequestTimeStart = A_GET_SECONDS_TICK(); DBG_LOG_PRINT(DBG_ZONE_INIT, ("Sending DHCP Discover... \r\n")); status = SendDhcpDiscover(g_WifiMTE.TransmitBuffer); if (A_FAILED(status)) { break; } } break; case TEST_WAIT_DHCP_REPLY : if ((A_GET_SECONDS_TICK() - dhcpRequestTimeStart) > 1) { dhcpAttempt++; /* time expired, resend DHCP again */ DBG_LOG_PRINT(DBG_ZONE_INIT, ("Retrying DHCP request.. re-attempt : %d \r\n", dhcpAttempt)); dhcpRequestTimeStart = A_GET_SECONDS_TICK(); /* resend again */ status = SendDhcpDiscover(g_WifiMTE.TransmitBuffer); if (A_FAILED(status)) { break; } } if (g_WifiMTE.GotDhcpOffer) { /* issue get status command and wait for response */ g_WifiMTE.TestState = TEST_WAIT_WMI_STATS; status = wmi_get_stats_cmd(); } break; case TEST_WAIT_WMI_STATS: if (g_WifiMTE.ReceivedStats) { g_WifiMTE.TestState = TEST_END_SUCCESS; } break; case TEST_END_SUCCESS: break; default: g_WifiMTE.TestState = TEST_GEN_FAILURE; A_ASSERT(FALSE); break; } if (g_WifiMTE.TestState == TEST_END_SUCCESS) { /* all done */ break; } } if (g_WifiMTE.APConnected) { /* if we were connected, issue the disconnect command to disconnect from the AP */ wmi_disconnect_cmd(); /* before exiting make sure the target sends out the disconnect */ A_MDELAY(200); } g_WifiMTE.MteStatus = GetMTEStatus(); return status; }
A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer) { A_STATUS status; if (pDev->MailBoxInfo.Flags & HIF_MBOX_FLAG_NO_BUNDLING) { AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n")); return A_ENOTSUP; } status = HIFConfigureDevice(pDev->HIFDevice, HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT, &pDev->HifScatterInfo, sizeof(pDev->HifScatterInfo)); if (A_FAILED(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K: ** HIF layer does not support scatter requests (%d) \n",status)); /* we can try to use a virtual DMA scatter mechanism using legacy HIFReadWrite() */ status = DevSetupVirtualScatterSupport(pDev); if (A_SUCCESS(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("AR6K: virtual scatter transfers enabled (max scatter items:%d: maxlen:%d) \n", DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev))); } } else { AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("AR6K: HIF layer supports scatter requests (max scatter items:%d: maxlen:%d) \n", DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev))); } if (A_SUCCESS(status)) { /* for the recv path, the maximum number of bytes per recv bundle is just limited * by the maximum transfer size at the HIF layer */ pDev->MaxRecvBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq; if (pDev->MailBoxInfo.MboxBusIFType == MBOX_BUS_IF_SPI) { AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6K : SPI bus requires TX bundling disabled\n")); pDev->MaxSendBundleSize = 0; } else { /* for the send path, the max transfer size is limited by the existence and size of * the extended mailbox address range */ if (pDev->MailBoxInfo.MboxProp[0].ExtendedAddress != 0) { pDev->MaxSendBundleSize = pDev->MailBoxInfo.MboxProp[0].ExtendedSize; } else { /* legacy */ pDev->MaxSendBundleSize = AR6K_LEGACY_MAX_WRITE_LENGTH; } if (pDev->MaxSendBundleSize > pDev->HifScatterInfo.MaxTransferSizePerScatterReq) { /* limit send bundle size to what the HIF can support for scatter requests */ pDev->MaxSendBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq; } } AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("AR6K: max recv: %d max send: %d \n", DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev), DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev))); } return status; }
A_BOOL RunAR6kTest(A_UINT32 Channel, A_CHAR *pSSID, MTE_WIFI_TEST_STATUS *pTestStatus) { AR6K_FIRMWARE_INFO firmware; A_STATUS status = A_OK; A_MEMZERO(&firmware,sizeof(firmware)); InitializeMTE(); if (!GetFirmwareInfo(&firmware)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("Target Firmware missing!! Aborting.. \r\n")); return FALSE; } g_WifiMTE.SSIDLength = strlen(pSSID); A_ASSERT(g_WifiMTE.SSIDLength <= 32); A_MEMCPY(g_WifiMTE.SSID,pSSID,g_WifiMTE.SSIDLength); A_ASSERT(Channel <= MAX_WIFI_CHANNELS); A_ASSERT(Channel > 0); /* look up the channel hint (in Mhz) */ g_WifiMTE.WiFiChannel = g_ChannelLookUp[Channel]; DBG_LOG_PRINT(DBG_ZONE_INIT, ("Ar6k WiFi MTE Test Start..(SSID: %s , channel:%d) \r\n", g_WifiMTE.SSID, g_WifiMTE.WiFiChannel)); do { /* init test status */ g_WifiMTE.MteStatus = MTE_WIFI_STATUS_SDIO_INIT_FAILED; if (A_FAILED(HIFInit())) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** HIFInit Failed!!! \r\n")); break; } BMIInit(); /* all failures are setup failures this point forward */ g_WifiMTE.MteStatus = MTE_WIFI_STATUS_SETUP_FAILED; g_WifiMTE.HifDevice = HIFGetDevice(); DBG_LOG_PRINT(DBG_ZONE_ERR, ("Getting Target ID... \r\n")); status = BMIGetTargetInfo(g_WifiMTE.HifDevice, &g_WifiMTE.TargetInfo); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** Failed to Get Target Information \r\n")); break; } DBG_LOG_PRINT(DBG_ZONE_INIT, ("TARGET_TYPE:0x%X TARGET_VER : 0x%X \r\n", g_WifiMTE.TargetInfo.target_type, g_WifiMTE.TargetInfo.target_ver)); status = ar6000_prepare_target(g_WifiMTE.HifDevice, g_WifiMTE.TargetInfo.target_type, g_WifiMTE.TargetInfo.target_ver); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** Failed to prepare target \r\n")); break; } status = ar6000_configure_clock (g_WifiMTE.HifDevice, g_WifiMTE.TargetInfo.target_type, g_WifiMTE.TargetInfo.target_ver, BOARD_XTAL_FREQ); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** Failed to configure target XTAL \r\n")); break; } DBG_LOG_PRINT(DBG_ZONE_INIT, ("Download Firmware ... (firmware length: %d, %s) (datapatch len: %d) \r\n", firmware.AthwlanLength, firmware.AthwlanCompressed ? "COMPRESSED" : "UNCOMPRESSED", firmware.DataPatchLength)); status = DownloadFirmware(g_WifiMTE.HifDevice, g_WifiMTE.TargetInfo.target_type, g_WifiMTE.TargetInfo.target_ver, firmware.pAthwlan, firmware.AthwlanLength, firmware.AthwlanCompressed, firmware.pDataPatch, firmware.DataPatchLength); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** Failed to download firmware \r\n")); break; } DBG_LOG_PRINT(DBG_ZONE_INIT, ("Firmware Download Complete.. \r\n")); ar6000_enable_target_console(g_WifiMTE.HifDevice,g_WifiMTE.TargetInfo.target_type); status = ar6000_set_htc_params(g_WifiMTE.HifDevice, g_WifiMTE.TargetInfo.target_type, 0, 0); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** Failed to set HTC Params \r\n")); break; } DBG_LOG_PRINT(DBG_ZONE_INIT, ("Transferring EEPROM settings .. \r\n")); status = eeprom_ar6000_transfer(g_WifiMTE.HifDevice, g_WifiMTE.TargetInfo.target_type); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** Failed to transfer EEPROM settings \r\n")); break; } DBG_LOG_PRINT(DBG_ZONE_INIT, ("Starting Target .. \r\n")); status = BMIDone(g_WifiMTE.HifDevice); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** Target failed to start \r\n")); break; } /* from here on out, all mte failures are boot failures */ g_WifiMTE.MteStatus = MTE_WIFI_STATUS_BOOT_FAILED; DBG_LOG_PRINT(DBG_ZONE_INIT, ("Connecting HTC .. \r\n")); /* connect HTC layer */ g_WifiMTE.htcHandle = HTCConnect(g_WifiMTE.HifDevice); if (g_WifiMTE.htcHandle == NULL) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** HTC connection failed \r\n")); break; } status = HTCConnectService(g_WifiMTE.htcHandle, WMI_CONTROL_SVC, &g_WifiMTE.ControlEp); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** Failed to connect to WMI control service \r\n")); break; } status = HTCConnectService(g_WifiMTE.htcHandle, WMI_DATA_BE_SVC, &g_WifiMTE.DataEp); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** Failed to connect to WMI best effort data service \r\n")); break; } DBG_LOG_PRINT(DBG_ZONE_INIT, ("HTC is connected (wmi_ctrl:%d, data:%d) ... \r\n", g_WifiMTE.ControlEp, g_WifiMTE.DataEp)); status = HTCStart(g_WifiMTE.htcHandle); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** failed to start HTC \r\n")); break; } status = WMIInit(g_WifiMTE.htcHandle,g_WifiMTE.ControlEp,g_WifiMTE.DataEp); if (A_FAILED(status)) { DBG_LOG_PRINT(DBG_ZONE_ERR, ("** failed to init WMI \r\n")); break; } status = RunConnectionTest(); } while (FALSE); pTestStatus->StatusCode = g_WifiMTE.MteStatus; pTestStatus->RSSI = g_WifiMTE.RSSI; return (A_SUCCESS(status)); }
static int hifDeviceResume(struct device *dev) { struct task_struct* pTask; const char *taskName; int (*taskFunc)(void *); struct sdio_func *func = dev_to_sdio_func(dev); A_STATUS ret = A_OK; HIF_DEVICE *device; device = getHifDevice(func); if (device->is_suspend) { /* enable the SDIO function */ sdio_claim_host(func); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) /* give us some time to enable, in ms */ func->enable_timeout = 100; #endif ret = sdio_enable_func(func); if (ret) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n", __FUNCTION__, ret)); sdio_release_host(func); return ret; } ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); sdio_release_host(func); if (ret) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x AR6K: 0x%X\n", __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret)); return ret; } device->is_suspend = FALSE; /* create async I/O thread */ if (!device->async_task) { device->async_shutdown = 0; device->async_task = kthread_create(async_task, (void *)device, "AR6K Async"); if (IS_ERR(device->async_task)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__)); return A_ERROR; } AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n")); wake_up_process(device->async_task ); } } if (!device->claimedContext) { printk("WARNING!!! No claimedContext during resume wlan\n"); taskFunc = startup_task; taskName = "AR6K startup"; } else { taskFunc = resume_task; taskName = "AR6K resume"; } /* create resume thread */ pTask = kthread_create(taskFunc, (void *)device, taskName); if (IS_ERR(pTask)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create resume task\n", __FUNCTION__)); return A_ERROR; } AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start resume task\n")); wake_up_process(pTask); return A_SUCCESS(ret) ? 0 : ret; }
static void usb_hif_usb_recv_complete(struct urb *urb) { HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context; A_STATUS status = A_OK; adf_nbuf_t buf = NULL; HIF_USB_PIPE *pipe = urb_context->pipe; AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( "+%s: recv pipe: %d, stat:%d,len:%d urb:0x%p\n", __func__, pipe->logical_pipe_num, urb->status, urb->actual_length, urb)); /* this urb is not pending anymore */ usb_hif_remove_pending_transfer(urb_context); do { if (urb->status != 0) { status = A_ECOMM; switch (urb->status) { #ifdef RX_SG_SUPPORT case -EOVERFLOW: urb->actual_length = HIF_USB_RX_BUFFER_SIZE; status = A_OK; break; #endif case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* NOTE: no need to spew these errors when * device is removed * or urb is killed due to driver shutdown */ status = A_ECANCELED; break; default: AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n", __func__, pipe->logical_pipe_num, pipe->ep_address, urb->status)); break; } break; } if (urb->actual_length == 0) break; buf = urb_context->buf; /* we are going to pass it up */ urb_context->buf = NULL; adf_nbuf_put_tail(buf, urb->actual_length); if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) { A_UINT8 *data; A_UINT32 len; adf_nbuf_peek_header(buf, &data, &len); DebugDumpBytes(data, len, "hif recv data"); } /* note: queue implements a lock */ skb_queue_tail(&pipe->io_comp_queue, buf); schedule_work(&pipe->io_complete_work); } while (FALSE); usb_hif_cleanup_recv_urb(urb_context); if (A_SUCCESS(status)) { if (pipe->urb_cnt >= pipe->urb_cnt_thresh) { /* our free urbs are piling up, post more transfers */ usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE); } } AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ("-%s\n", __func__)); }