A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks) { SD_API_STATUS sdStatus; AR_DEBUG_ASSERT(callbacks != NULL); /* store the callback handlers */ osdrvCallbacks = *callbacks; /* Register with bus driver core */ NDIS_DEBUG_PRINTF(DBG_LEVEL_HIF, "AR6000: HIFInit registering \r\n"); registered = 1; #if defined(CONFIG_PM) // TODO about power management. #endif /* CONFIG_PM */ /* Register with bus driver core */ sdFunction.pName = "sdio_wlan"; sdFunction.pProbe = hifDeviceInserted; sdFunction.pRemove = hifDeviceRemoved; A_MUTEX_INIT(&hif_lock); NdisAllocateSpinLock(&sLock); sdStatus = SDIORegisterFunction(&sdFunction); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); return A_OK; }
/* * Commit an address to either WINDOW_WRITE_ADDR_REG or to * WINDOW_READ_ADDR_REG. We write the least significan byte (LSB) * last, since it triggers the read/write. */ static void _WRITE_WINDOW_ADDR(HTC_TARGET *target, A_UINT32 whichreg, A_UINT32 value) { A_UINT32 window_addr; HIF_REQUEST request; A_STATUS status; A_UINT32 address; window_addr = value; HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, HIF_BYTE_BASIS, HIF_INCREMENTAL_ADDRESS); address = getRegAddr(whichreg, ENDPOINT_UNUSED); #ifdef ONLY_16BIT status = HIFReadWrite(target->device, address+2, (A_UCHAR *)&window_addr+2, 2, &request, NULL); AR_DEBUG_ASSERT(status == A_OK); status = HIFReadWrite(target->device, address, (A_UCHAR *)&window_addr, 2, &request, NULL); status = HIFReadWrite(target->device, address, (A_UCHAR *)&window_addr, 2, &request, NULL); AR_DEBUG_ASSERT(status == A_OK); #else status = HIFReadWrite(target->device, address+1, (A_UCHAR *)&window_addr+1, 3, &request, NULL); AR_DEBUG_ASSERT(status == A_OK); status = HIFReadWrite(target->device, address, (A_UCHAR *)&window_addr, 1, &request, NULL); AR_DEBUG_ASSERT(status == A_OK); #endif }
static void hifDeviceRemoved(struct sdio_func *func) { A_STATUS status = A_OK; HIF_DEVICE *device; int ret; AR_DEBUG_ASSERT(func != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n")); device = getHifDevice(func); if (device->claimedContext != NULL) { status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device); } do { if (device->is_suspend) { device->is_suspend = FALSE; break; } 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; } /* Disable the card */ sdio_claim_host(device->func); ret = sdio_disable_func(device->func); sdio_release_host(device->func); } while (0); delHifDevice(device); AR_DEBUG_ASSERT(status == A_OK); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n")); }
/* ------ Functions ------ */ A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks) { int status; AR_DEBUG_ASSERT(callbacks != NULL); A_REGISTER_MODULE_DEBUG_INFO(hif); /* store the callback handlers */ osdrvCallbacks = *callbacks; /* Register with bus driver core */ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFInit registering\n")); registered = 1; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) && defined(CONFIG_PM) if (callbacks->deviceSuspendHandler && callbacks->deviceResumeHandler) { ar6k_driver.drv.pm = &ar6k_device_pm_ops; } #endif /* CONFIG_PM */ status = sdio_register_driver(&ar6k_driver); AR_DEBUG_ASSERT(status==0); if (status != 0) { return A_ERROR; } return A_OK; }
static void hifDeviceRemoved(struct sdio_func *func) { A_STATUS status = A_OK; HIF_DEVICE *device; AR_DEBUG_ASSERT(func != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n")); device = getHifDevice(func); if (device->claimedContext != NULL) { status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device); } if (device->is_suspend) { device->is_suspend = FALSE; } else { if (hifDisableFunc(device, func)!=0) { status = A_ERROR; } } CleanupHIFScatterResources(device); delHifDevice(device); AR_DEBUG_ASSERT(status == A_OK); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n")); }
void HIFShutDownDevice(HIF_DEVICE *device) { SD_API_STATUS sdStatus; //SDCONFIG_BUS_MODE_DATA busSettings; UCHAR buffer; if (device == NULL) { HIF_DEBUG_PRINTF(ATH_LOG_ERR, "Invalid Handle passed\n"); return; } /* Remove the allocated current if any */ /* * There is no equivalent for this one in WINCE status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_FREE_SLOT_CURRENT, NULL, 0); DBG_ASSERT(SDIO_SUCCESS(status)); */ /* Disable the card */ SDIODisconnectInterrupt(device->handle); sdStatus = SDSetCardFeature(device->handle, SD_IO_FUNCTION_DISABLE, NULL, 0); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); /* Perform a soft I/O reset */ sdStatus = SDReadWriteRegistersDirect(device->handle, SD_IO_WRITE, 0, SD_IO_REG_IO_ABORT, 1, &buffer, 0); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); /* * WAR - Codetelligence driver does not seem to shutdown correctly in 1 * bit mode. By default it configures the HC in the 4 bit. Its later in * our driver that we switch to 1 bit mode. If we try to shutdown, the * driver hangs so we revert to 4 bit mode, to be transparent to the * underlying bus driver. */ /* * Not sure whether this is required for WINCE hence commenting */ /* if (sdio1bitmode) { ZERO_OBJECT(busSettings); busSettings.BusModeFlags = device->handle->pHcd->CardProperties.BusMode; SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags, SDCONFIG_BUS_WIDTH_4_BIT); // Issue config request to change the bus width to 4 bit status = SDLIB_IssueConfig(device->handle, SDCONFIG_BUS_MODE_CTRL, &busSettings, sizeof(SDCONFIG_BUS_MODE_DATA)); DBG_ASSERT(SDIO_SUCCESS(status)); } */ /* Unregister with bus driver core */ sdStatus = SDIOUnregisterFunction(&sdFunction); AR_DEBUG_ASSERT(SD_API_SUCCESS(sdStatus)); return; }
void htcServiceCPUInterrupt(HTC_TARGET *target) { A_STATUS status; A_UINT32 address; HIF_REQUEST request; A_UINT8 cpu_int_status; HTC_DEBUG_PRINTF(ATH_LOG_INF, "CPU Interrupt\n"); cpu_int_status = target->table.cpu_int_status & target->table.cpu_int_status_enable; AR_DEBUG_ASSERT(cpu_int_status); HTC_DEBUG_PRINTF(ATH_LOG_INF, "Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n", cpu_int_status); /* Figure out the interrupt number */ HTC_DEBUG_PRINTF(ATH_LOG_INF, "Interrupt Number: 0x%x\n", htcGetBitNumSet(cpu_int_status)); /* Clear the interrupt */ target->table.cpu_int_status = cpu_int_status; /* W1C */ HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); address = getRegAddr(CPU_INT_STATUS_REG, ENDPOINT_UNUSED); status = HIFReadWrite(target->device, address, &target->table.cpu_int_status, 1, &request, NULL); AR_DEBUG_ASSERT(status == A_OK); }
SD_API_STATUS hifIRQHandler(SD_DEVICE_HANDLE hDevice, PVOID notUsed) { #ifndef CEPC A_STATUS status; HIF_DEVICE *device; A_BOOL callDSR; #endif HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifIRQHandler : Enter\n"); #ifndef CEPC /* Disable device interrupts */ device = getHifDevice(hDevice); status = htcCallbacks.deviceInterruptDisabler(device, &callDSR); AR_DEBUG_ASSERT(status == A_OK); /* Call the DSR Handler if it is not a Spurious Interrupt */ if (callDSR) { status = htcCallbacks.dsrHandler(device); AR_DEBUG_ASSERT(status == A_OK); } #else NdisSetEvent(&hifIRQEvent); #endif HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifIRQHandler : Exit\n"); return SD_API_STATUS_SUCCESS; }
static A_STATUS CF_BusRequest_16(CF_DEVICE_HANDLE cfHandle, CF_REQUEST *pReq) { volatile A_UINT16 *data, *base; A_UINT32 len, i; CF_DEVICE *device; device = (CF_DEVICE *)cfHandle; if (device == NULL || pReq == NULL) { return A_ERROR; } HIF_DEBUG_PRINTF(ATH_LOG_TRC,"CF_BusRequest_16 \n"); data = (A_UINT16 *)pReq->pDataBuffer; base = (A_UINT16 *)(device->mappedMemBase + pReq->address); len = pReq->length; /* * Assert on odd address and odd length */ AR_DEBUG_ASSERT(!(((A_UINT32)data)%2)); AR_DEBUG_ASSERT(!(((A_UINT32)base)%2)); AR_DEBUG_ASSERT(!(len%2)); len = len/2; if (pReq->flags & CFREQ_FLAGS_DATA_WRITE) { if (pReq->flags & CFREQ_FLAGS_FIXED_ADDRESS) { for (i = 0; i < len; i++) { *base = *data; data++; } } else { for (i = 0; i < len; i++) { *base = *data; base++; data++; } } } else { if (pReq->flags & CFREQ_FLAGS_FIXED_ADDRESS) { for (i = 0; i < len; i++) { *data = *base; data++; } } else { for (i = 0; i < len; i++) { *data = *base; base++; data++; } } } return A_OK; }
static A_STATUS DevServiceErrorInterrupt(AR6K_DEVICE *pDev) { A_STATUS status; A_UINT8 error_int_status; A_UINT8 regBuffer[4]; AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error Interrupt\n")); error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F; AR_DEBUG_ASSERT(error_int_status); AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n", error_int_status)); if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) { /* Wakeup */ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n")); } if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) { /* Rx Underflow */ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n")); if (pDev->TargetFailureCallback != NULL) { pDev->TargetFailureCallback(pDev->HTCContext, AR6K_TARGET_RX_ERROR); } } if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) { /* Tx Overflow */ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n")); if (pDev->TargetFailureCallback != NULL) { pDev->TargetFailureCallback(pDev->HTCContext, AR6K_TARGET_TX_ERROR); } } /* Clear the interrupt */ pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */ /* set up the register transfer buffer to hit the register 4 times , this is done * to make the access 4-byte aligned to mitigate issues with host bus interconnects that * restrict bus transfer lengths to be a multiple of 4-bytes */ /* set W1C value to clear the interrupt, this hits the register first */ regBuffer[0] = error_int_status; /* the remaining 4 values are set to zero which have no-effect */ regBuffer[1] = 0; regBuffer[2] = 0; regBuffer[3] = 0; status = HIFReadWrite(pDev->HIFDevice, ERROR_INT_STATUS_ADDRESS, regBuffer, 4, HIF_WR_SYNC_BYTE_FIX, NULL); AR_DEBUG_ASSERT(status == A_OK); return status; }
A_STATUS htcInterruptEnabler(HIF_DEVICE *device) { A_STATUS status; A_UINT32 address; HIF_REQUEST request; HTC_TARGET *target; HTC_REG_REQUEST_ELEMENT *element; target = getTargetInstance(device); AR_DEBUG_ASSERT(target != NULL); HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcInterruptEnabler Enter target: 0x%p\n", target); target->table.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) | INT_STATUS_ENABLE_CPU_SET(0x01) | INT_STATUS_ENABLE_COUNTER_SET(0x01) | INT_STATUS_ENABLE_MBOX_DATA_SET(0x0F); /* Reenable Dragon Interrupts */ element = allocateRegRequestElement(target); AR_DEBUG_ASSERT(element != NULL); #ifdef ONLY_16BIT FILL_REG_BUFFER(element, (A_UINT16 *)&target->table.int_status_enable, 2, INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); #else FILL_REG_BUFFER(element, &target->table.int_status_enable, 1, INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); #endif HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_ASYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); #ifdef ONLY_16BIT status = HIFReadWrite(target->device, address, &target->table.int_status_enable, 2, &request, element); #else status = HIFReadWrite(target->device, address, &target->table.int_status_enable, 1, &request, element); #endif #ifndef HTC_SYNC AR_DEBUG_ASSERT(status == A_OK); #else AR_DEBUG_ASSERT(status == A_OK || status == A_PENDING); if ( status == A_OK ) { element->completionCB(element, status); } #endif //HTC_SYNC HTC_DEBUG_PRINTF(ATH_LOG_TRC,"htcInterruptEnabler Exit\n"); return A_OK; }
void HIFMaskInterrupt(HIF_DEVICE *device) { SDIO_STATUS status; AR_DEBUG_ASSERT(device != NULL); AR_DEBUG_ASSERT(device->handle != NULL); /* Mask our function IRQ */ status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_MASK_IRQ, NULL, 0); AR_DEBUG_ASSERT(SDIO_SUCCESS(status)); }
A_STATUS htcInterruptPending(HIF_DEVICE *device, A_BOOL *intPending) { A_STATUS status; A_UINT32 address; HTC_TARGET *target; HIF_REQUEST request; A_UCHAR intStatus[2] = {0,0}; A_UCHAR intMask[2] = {0,0}; target = getTargetInstance(device); AR_DEBUG_ASSERT(target != NULL); HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcInterruptPending Enter target: 0x%p\n", target); // get the current interrupt status register HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); address = getRegAddr(INT_STATUS_REG, ENDPOINT_UNUSED); #ifdef ONLY_16BIT status = HIFReadWrite(target->device, address, intStatus, 2, &request, NULL); #else status = HIFReadWrite(target->device, address, intStatus, 1, &request, NULL); #endif AR_DEBUG_ASSERT(status == A_OK); // get the interrupt enable register value HIF_FRAME_REQUEST(&request, HIF_READ, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); #ifdef ONLY_16BIT status = HIFReadWrite(target->device, address, intMask, 2, &request, NULL); #else status = HIFReadWrite(target->device, address, intMask, 1, &request, NULL); #endif AR_DEBUG_ASSERT(status == A_OK); if (!((intMask[0] & intStatus[0]) == 0)) { *intPending = TRUE; } else { *intPending = FALSE; } return A_OK; }
void HIFMaskInterrupt(HIF_DEVICE *device) { int ret;; AR_DEBUG_ASSERT(device != NULL); AR_DEBUG_ASSERT(device->func != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFMaskInterrupt\n")); /* Mask our function IRQ */ sdio_claim_host(device->func); ret = sdio_release_irq(device->func); sdio_release_host(device->func); AR_DEBUG_ASSERT(ret == 0); }
void hifRWCompletionHandler(SDREQUEST *request) { void *context; A_STATUS status = A_OK; HIF_DEVICE *device; BUS_REQUEST *busrequest; busrequest = (BUS_REQUEST *)request->pCompleteContext; AR_DEBUG_ASSERT(busrequest->request == request); device = busrequest->device; context = busrequest->context; if (!SDIO_SUCCESS(request->Status)) { status = A_ERROR; } /* free the request, we have all the info we need */ hifFreeBusRequest(device,busrequest); busrequest = NULL; if (device->shutdownInProgress) { device->htcCallbacks.rwCompletionHandler(context, A_ERROR); return; } device->htcCallbacks.rwCompletionHandler(context, status); }
static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev) { A_UINT32 dummy; A_STATUS status; /* Send a target failure event to the application */ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n")); if (pDev->TargetFailureCallback != NULL) { pDev->TargetFailureCallback(pDev->HTCContext); } /* clear the interrupt , the debug error interrupt is * counter 0 */ /* read counter to clear interrupt */ status = HIFReadWrite(pDev->HIFDevice, COUNT_DEC_ADDRESS, (A_UINT8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC, NULL); AR_DEBUG_ASSERT(status == A_OK); return status; }
/** * Returns a lexicographically sorted list of merged barcodes, each paired with * the 0-based index of corresponding barcode in the source vector. */ barcode_vec sort_barcodes(const fastq_pair_vec& barcodes) { AR_DEBUG_ASSERT(!barcodes.empty()); barcode_vec sorted_barcodes; const size_t max_key_1_len = barcodes.front().first.length(); const size_t max_key_2_len = barcodes.front().second.length(); for (auto it = barcodes.begin(); it != barcodes.end(); ++it) { if (it->first.length() != max_key_1_len) { throw barcode_error("mate 1 barcodes do not have the same length"); } else if (it->second.length() != max_key_2_len) { throw barcode_error("mate 2 barcodes do not have the same length"); } std::string barcode; barcode.reserve(max_key_1_len + max_key_2_len); barcode.append(it->first.sequence()); barcode.append(it->second.sequence()); sorted_barcodes.push_back(barcode_pair(barcode, it - barcodes.begin())); } std::sort(sorted_barcodes.begin(), sorted_barcodes.end()); return sorted_barcodes; }
DWORD hifIRQThread(void *Context) { A_STATUS status = A_OK; HIF_DEVICE *device; device = (HIF_DEVICE *)Context; NDIS_DEBUG_PRINTF(DBG_LEVEL_HIF, " %s() is Running... \r\n",__FUNCTION__); while (TRUE) { NdisWaitEvent(&hifIRQEvent, 0); NdisResetEvent(&hifIRQEvent); NDIS_DEBUG_PRINTF(DBG_TRACE, "%s() - Running & ",__FUNCTION__); status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context); AR_DEBUG_ASSERT(status == A_OK); NDIS_DEBUG_PRINTF(DBG_TRACE, " Exit \r\n"); SDIOConnectInterrupt(device->handle,hifIRQHandler); } // while return SD_API_STATUS_SUCCESS; }
void HIFRegisterCallbacks(HTC_CALLBACKS *callbacks) { A_STATUS status; /* Store the callback and event handlers */ htcCallbacks.deviceInsertedHandler = callbacks->deviceInsertedHandler; htcCallbacks.deviceRemovedHandler = callbacks->deviceRemovedHandler; htcCallbacks.deviceSuspendHandler = callbacks->deviceSuspendHandler; htcCallbacks.deviceResumeHandler = callbacks->deviceResumeHandler; htcCallbacks.deviceWakeupHandler = callbacks->deviceWakeupHandler; htcCallbacks.rwCompletionHandler = callbacks->rwCompletionHandler; htcCallbacks.deviceInterruptDisabler = callbacks->deviceInterruptDisabler; htcCallbacks.deviceInterruptEnabler = callbacks->deviceInterruptEnabler; htcCallbacks.dsrHandler = callbacks->dsrHandler; /* Register the callback handlers with the lower driver */ cfFunction.pName = "cf_wlan"; cfFunction.pProbe = hifDeviceInserted; cfFunction.pRemove = hifDeviceRemoved; cfFunction.pIsr = hifISRHandler; cfFunction.pDsr = hifDSRHandler; status = CF_RegisterFunction(&cfFunction); AR_DEBUG_ASSERT(status == A_OK); }
/* callback when a control message arrives on this endpoint */ void HTCControlRecv(void *Context, HTC_PACKET *pPacket) { AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0); if (pPacket->Status == A_ECANCELED) { /* this is a flush operation, return the control packet back to the pool */ HTC_FREE_CONTROL_RX((HTC_TARGET*)Context,pPacket); return; } /* the only control messages we are expecting are NULL messages (credit resports) */ if (pPacket->ActualLength > 0) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCControlRecv, got message with length:%d \n", pPacket->ActualLength + (A_UINT32)HTC_HDR_LENGTH)); #ifdef ATH_DEBUG_MODULE /* dump header and message */ DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH, pPacket->ActualLength + HTC_HDR_LENGTH, "Unexpected ENDPOINT 0 Message"); #endif } HTC_RECYCLE_RX_PKT((HTC_TARGET*)Context,pPacket,&((HTC_TARGET*)Context)->EndPoint[0]); }
void HIFUnMaskInterrupt(HIF_DEVICE *device) { int ret;; AR_DEBUG_ASSERT(device != NULL); AR_DEBUG_ASSERT(device->func != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFUnMaskInterrupt\n")); /* Register the IRQ Handler */ sdio_claim_host(device->func); ret = sdio_claim_irq(device->func, hifIRQHandler); sdio_release_host(device->func); AR_DEBUG_ASSERT(ret == 0); }
void HIFAckInterrupt(HIF_DEVICE *device) { AR_DEBUG_ASSERT(device != NULL); /* Acknowledge our function IRQ */ }
void HIFShutDownDevice(HIF_DEVICE *device) { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n")); if (device != NULL) { AR_DEBUG_ASSERT(device->func != NULL); } else { /* since we are unloading the driver anyways, reset all cards in case the SDIO card * is externally powered and we are unloading the SDIO stack. This avoids the problem when * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already * enumerated */ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: HIFShutDownDevice, resetting\n")); ResetAllCards(); /* Unregister with bus driver core */ if (registered) { registered = 0; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Unregistering with the bus driver\n")); sdio_unregister_driver(&ar6k_driver); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Unregistered\n")); } } AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -HIFShutDownDevice\n")); }
void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, void *pCreditDistContext, HTC_CREDIT_DIST_CALLBACK CreditDistFunc, HTC_CREDIT_INIT_CALLBACK CreditInitFunc, HTC_SERVICE_ID ServicePriorityOrder[], int ListLength) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); int i; int ep; if (CreditInitFunc != NULL) { /* caller has supplied their own distribution functions */ target->InitCredits = CreditInitFunc; AR_DEBUG_ASSERT(CreditDistFunc != NULL); target->DistributeCredits = CreditDistFunc; target->pCredDistContext = pCreditDistContext; } else { /* caller wants HTC to do distribution */ /* if caller wants service to handle distributions then * it must set both of these to NULL! */ AR_DEBUG_ASSERT(CreditDistFunc == NULL); target->InitCredits = HTCDefaultCreditInit; target->DistributeCredits = HTCDefaultCreditDist; target->pCredDistContext = target; } /* always add HTC control endpoint first, we only expose the list after the * first one, this is added for TX queue checking */ AddToEndpointDistList(target, &target->EndPoint[ENDPOINT_0].CreditDist); /* build the list of credit distribution structures in priority order * supplied by the caller, these will follow endpoint 0 */ for (i = 0; i < ListLength; i++) { /* match services with endpoints and add the endpoints to the distribution list * in FIFO order */ for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) { if (target->EndPoint[ep].ServiceID == ServicePriorityOrder[i]) { /* queue this one to the list */ AddToEndpointDistList(target, &target->EndPoint[ep].CreditDist); break; } } AR_DEBUG_ASSERT(ep < ENDPOINT_MAX); } }
/* Makes a buffer available to the HTC module */ A_STATUS HTCBufferReceive(HTC_TARGET *target, HTC_ENDPOINT_ID endPointId, A_UCHAR *buffer, A_UINT32 length, void *cookie) { A_STATUS status; HTC_ENDPOINT *endPoint; HTC_DATA_REQUEST_QUEUE *recvQueue; HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "HTCBufferReceive: Enter (endPointId: %d, buffer: 0x%p, length: %d, cookie: 0x%p)\n", endPointId, buffer, length, cookie); AR_DEBUG_ASSERT((endPointId >= ENDPOINT1) && (endPointId <= ENDPOINT4)); /* Extract the end point instance */ endPoint = &target->endPoint[endPointId]; AR_DEBUG_ASSERT(endPoint != NULL); recvQueue = &endPoint->recvQueue; HTC_DEBUG_PRINTF(ATH_LOG_INF | ATH_LOG_RECV, "recvQueue: %p\n", recvQueue); /* Add this posted buffer to the pending receive queue */ status = addToMboxQueue(recvQueue, buffer, length, 0, cookie); if (status != A_OK) { HTC_DEBUG_PRINTF(ATH_LOG_ERR | ATH_LOG_RECV, "Mailbox (%d) Send queue full. Unable to add buffer\n", GET_ENDPOINT_ID(endPoint)); return A_ERROR; } /* * If this API was called as a result of a HTC_DATA_AVAILABLE event to * the upper layer, indicating that HTC is out of buffers, then we should * receive the frame in the buffer supplied otherwise we simply add the * buffer to the Pending Receive Queue */ if (endPoint->rxLengthPending) { htcReceiveFrame(endPoint); } HTC_DEBUG_PRINTF(ATH_LOG_TRC | ATH_LOG_RECV, "HTCBufferReceive: Exit\n"); return A_OK; }
/* called by the HTC layer when it wants us to check if the device has any more pending * recv messages, this starts off a series of async requests to read interrupt registers */ A_STATUS DevCheckPendingRecvMsgsAsync(void *context) { AR6K_DEVICE *pDev = (AR6K_DEVICE *)context; A_STATUS status = A_OK; HTC_PACKET *pIOPacket; /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can * cause us to switch contexts */ AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%X)\n", (A_UINT32)pDev)); do { if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { /* break the async processing chain right here, no need to continue. * The DevDsrHandler() will handle things in a loop when things are driven * synchronously */ break; } /* first allocate one of our HTC packets we created for async I/O * we reuse HTC packet definitions so that we can use the completion mechanism * in DevRWCompletionHandler() */ pIOPacket = AR6KAllocIOPacket(pDev); if (NULL == pIOPacket) { /* there should be only 1 asynchronous request out at a time to read these registers * so this should actually never happen */ status = A_NO_MEMORY; AR_DEBUG_ASSERT(FALSE); break; } /* stick in our completion routine when the I/O operation completes */ pIOPacket->Completion = DevGetEventAsyncHandler; pIOPacket->pContext = pDev; if (pDev->GetPendingEventsFunc) { /* HIF layer has it's own mechanism, pass the IO to it.. */ status = pDev->GetPendingEventsFunc(pDev->HIFDevice, (HIF_PENDING_EVENTS_INFO *)pIOPacket->pBuffer, pIOPacket); } else { /* standard way, read the interrupt register table asynchronously again */ status = HIFReadWrite(pDev->HIFDevice, HOST_INT_STATUS_ADDRESS, pIOPacket->pBuffer, AR6K_IRQ_PROC_REGS_SIZE, HIF_RD_ASYNC_BYTE_INC, pIOPacket); } AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n")); } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n")); return status; }
static HIF_DEVICE * addHifDevice(struct sdio_func *func) { HIF_DEVICE *hifdevice; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice\n")); AR_DEBUG_ASSERT(func != NULL); hifdevice = (HIF_DEVICE *)kzalloc(sizeof(HIF_DEVICE), GFP_KERNEL); AR_DEBUG_ASSERT(hifdevice != NULL); #if HIF_USE_DMA_BOUNCE_BUFFER hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL); AR_DEBUG_ASSERT(hifdevice->dma_buffer != NULL); #endif hifdevice->func = func; sdio_set_drvdata(func, hifdevice); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice; 0x%p\n", hifdevice)); return hifdevice; }
void hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *handle) { A_STATUS status = A_OK; HIF_DEVICE *device; AR_DEBUG_ASSERT(function != NULL); AR_DEBUG_ASSERT(handle != NULL); /* our device is the IRQ context we stored */ device = (HIF_DEVICE *)handle->IrqContext; if (device->claimedContext != NULL) { status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device); } /* cleanup the instance */ hifCleanupDevice(device); AR_DEBUG_ASSERT(status == A_OK); }
/* ------ Functions ------ */ A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks) { SDIO_STATUS status; AR_DEBUG_ASSERT(callbacks != NULL); A_REGISTER_MODULE_DEBUG_INFO(hif); /* Store the callback and event handlers */ osdrvCallbacks = *callbacks; /* Register with bus driver core */ status = SDIO_RegisterFunction(&FunctionContext.function); AR_DEBUG_ASSERT(SDIO_SUCCESS(status)); return SDIO_SUCCESS(status) ? A_OK : A_ERROR; }
A_STATUS htcInterruptDisabler(HIF_DEVICE *device,A_BOOL *callDsr) { A_STATUS status; A_UINT32 address; HTC_TARGET *target; HIF_REQUEST request; A_BOOL interruptPending; target = getTargetInstance(device); AR_DEBUG_ASSERT(target != NULL); HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcInterruptDisabler Enter target: 0x%p\n", target); // Check for spurious interrupt status = htcInterruptPending (device, &interruptPending); if (!interruptPending){ *callDsr=FALSE; } else { /* * Disable the interrupts from Dragon. * We do the interrupt servicing in the bottom half and reenable the * Dragon interrupts at the end of the bottom-half */ target->table.int_status_enable = 0; HIF_FRAME_REQUEST(&request, HIF_WRITE, HIF_EXTENDED_IO, HIF_SYNCHRONOUS, HIF_BYTE_BASIS, HIF_FIXED_ADDRESS); address = getRegAddr(INT_STATUS_ENABLE_REG, ENDPOINT_UNUSED); #ifdef ONLY_16BIT status = HIFReadWrite(target->device, address, &target->table.int_status_enable, 2, &request, NULL); #else status = HIFReadWrite(target->device, address, &target->table.int_status_enable, 1, &request, NULL); #endif AR_DEBUG_ASSERT(status == A_OK); *callDsr=TRUE; } HTC_DEBUG_PRINTF(ATH_LOG_TRC, "htcInterruptDisabler: Exit\n"); return A_OK; }