/* read write an internal SPI register- ALWAYS synchronous */ static A_STATUS SPIReadWriteInternal(HIF_DEVICE *device, UINT16 address, UINT16 *pValue, BOOL Read) { SDIO_STATUS status; SDREQUEST *sdrequest; BUS_REQUEST *busrequest = NULL; A_STATUS a_status = A_OK; do { /* Allocate a new bus request */ busrequest = hifAllocateBusRequest(device); if (busrequest == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate bus request\n")); a_status = A_ERROR; break; } sdrequest = busrequest->request; if (Read) { ATH_SET_PIO_INTERNAL_READ_OPERATION(sdrequest,address); } else { ATH_SET_PIO_INTERNAL_WRITE_OPERATION(sdrequest,address,*pValue); } /* always synchronous */ sdrequest->Flags = SDREQ_FLAGS_RAW; sdrequest->pCompleteContext = NULL; sdrequest->pCompletion = NULL; /* issue the request */ status = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest); if (!SDIO_SUCCESS(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Spi Internal Read/Write failure: %d\n", status)); a_status = A_ERROR; } else { if (Read) { /* get the read result */ *pValue = ATH_GET_PIO_INTERNAL_READ_RESULT(sdrequest); } } } while (FALSE); if (busrequest != NULL) { hifFreeBusRequest(device, busrequest); } return a_status; }
/* queue a read/write request */ A_STATUS HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, A_UINT32 request, void *context) { A_STATUS status = A_OK; BUS_REQUEST *busrequest; AR_DEBUG_ASSERT(device != NULL); AR_DEBUG_ASSERT(device->func != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: %p addr:0x%X\n", device,address)); do { if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)){ /* serialize all requests through the async thread */ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Execution mode: %s\n", (request & HIF_ASYNCHRONOUS)?"Async":"Synch")); busrequest = hifAllocateBusRequest(device); if (busrequest == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: no async bus requests available (%s, addr:0x%X, len:%d) \n", request & HIF_READ ? "READ":"WRITE", address, length)); return A_ERROR; } busrequest->address = address; busrequest->buffer = buffer; busrequest->length = length; busrequest->request = request; busrequest->context = context; AddToAsyncList(device, busrequest); if (request & HIF_SYNCHRONOUS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%X\n", (unsigned int)busrequest)); /* wait for completion */ up(&device->sem_async); if (down_interruptible(&busrequest->sem_req) != 0) { /* interrupted, exit */ return A_ERROR; } else { A_STATUS status = busrequest->status; AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%X: 0x%X\n", (unsigned int)busrequest, busrequest->status)); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request)); hifFreeBusRequest(device, busrequest); return status; } } else { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%X\n", (unsigned int)busrequest)); up(&device->sem_async); return A_PENDING; } } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: Invalid execution mode: 0x%08x\n", (unsigned int)request)); status = A_EINVAL; break; } } while(0); return status; }
/* setup of HIF scatter resources */ A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo) { A_STATUS status = A_ERROR; int i; HIF_SCATTER_REQ_PRIV *pReqPriv; BUS_REQUEST *busrequest; do { /* check if host supports scatter requests and it meets our requirements */ if (device->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : host only supports scatter of : %d entries, need: %d \n", device->func->card->host->max_segs, MAX_SCATTER_ENTRIES_PER_REQ)); status = A_ENOTSUP; break; } AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HIF-SCATTER Enabled: max scatter req : %d entries: %d \n", MAX_SCATTER_REQUESTS, MAX_SCATTER_ENTRIES_PER_REQ)); for (i = 0; i < MAX_SCATTER_REQUESTS; i++) { /* allocate the private request blob */ pReqPriv = (HIF_SCATTER_REQ_PRIV *)A_MALLOC(sizeof(HIF_SCATTER_REQ_PRIV)); if (NULL == pReqPriv) { break; } A_MEMZERO(pReqPriv, sizeof(HIF_SCATTER_REQ_PRIV)); /* save the device instance*/ pReqPriv->device = device; /* allocate the scatter request */ pReqPriv->pHifScatterReq = (HIF_SCATTER_REQ *)A_MALLOC(sizeof(HIF_SCATTER_REQ) + (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM))); if (NULL == pReqPriv->pHifScatterReq) { A_FREE(pReqPriv); break; } /* just zero the main part of the scatter request */ A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(HIF_SCATTER_REQ)); /* back pointer to the private struct */ pReqPriv->pHifScatterReq->HIFPrivate[0] = pReqPriv; /* allocate a bus request for this scatter request */ busrequest = hifAllocateBusRequest(device); if (NULL == busrequest) { A_FREE(pReqPriv->pHifScatterReq); A_FREE(pReqPriv); break; } /* assign the scatter request to this bus request */ busrequest->pScatterReq = pReqPriv; /* point back to the request */ pReqPriv->busrequest = busrequest; /* add it to the scatter pool */ FreeScatterReq(device,pReqPriv->pHifScatterReq); } if (i != MAX_SCATTER_REQUESTS) { status = A_NO_MEMORY; AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HIF-SCATTER : failed to alloc scatter resources !\n")); break; } /* set scatter function pointers */ pInfo->pAllocateReqFunc = AllocScatterReq; pInfo->pFreeReqFunc = FreeScatterReq; pInfo->pReadWriteScatterFunc = HifReadWriteScatter; pInfo->MaxScatterEntries = MAX_SCATTER_ENTRIES_PER_REQ; pInfo->MaxTransferSizePerScatterReq = MAX_SCATTER_REQ_TRANSFER_SIZE; status = A_OK; } while (FALSE); if (A_FAILED(status)) { CleanupHIFScatterResources(device); } return status; }
A_STATUS HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, A_UINT32 request, void *context) { A_STATUS status = A_OK; //unsigned long flags; BUS_REQUEST *busrequest; BUS_REQUEST *async; BUS_REQUEST *active; AR_DEBUG_ASSERT(device != NULL); do { if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)) { /* serialize all requests through the async thread */ NDIS_DEBUG_PRINTF(DBG_TRACE, "AR6000: Execution mode: %s\n", (request & HIF_ASYNCHRONOUS) ?"Async":"Synch"); busrequest = hifAllocateBusRequest(device); if (busrequest == NULL) { NDIS_DEBUG_PRINTF(DBG_ERR, "AR6000: no async bus requests available\n"); return A_ERROR; } Hif_Lock(); busrequest->address = address; busrequest->buffer = buffer; busrequest->length = length; busrequest->request = request; busrequest->context = context; //NDIS_DEBUG_PRINTF(1, " add = %x, length = %x, request = %d \r\n", address, length, request); /* add to async list */ active = device->asyncreq; if (active == NULL) { device->asyncreq = busrequest; device->asyncreq->inusenext = NULL; } else { for (async = device->asyncreq; async != NULL; async = async->inusenext) { active = async; } active->inusenext = busrequest; busrequest->inusenext = NULL; } Hif_Unlock(); if (request & HIF_SYNCHRONOUS) { NdisSetEvent(&device->sem_async); /* Wait Read/Write Complete from the async_task */ if( ! NdisWaitEvent(&busrequest->sem_req, HIF_SYNCHRONOUS_WAIT_TIME)) { NDIS_DEBUG_PRINTF(DBG_ERR, " HIF Synchronous Read/Write Time Out !! \r\n"); NdisResetEvent(&busrequest->sem_req); return A_ERROR; } NdisResetEvent(&busrequest->sem_req); hifFreeBusRequest(device, busrequest); if(busrequest->status != A_OK) NDIS_DEBUG_PRINTF(DBG_ERR, "%s() Read/Write Err \r\n", __FUNCTION__); return busrequest->status; } else { NdisSetEvent(&device->sem_async); return A_PENDING; } } else { NDIS_DEBUG_PRINTF(DBG_ERR, "AR6000: Invalid execution mode: 0x%08x\n", (unsigned int)request); status = A_EINVAL; break; } }while(0); NDIS_DEBUG_PRINTF(0, "%s() : - Exit \r\n",__FUNCTION__); return status; }
/* queue a read/write request */ A_STATUS HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, A_UINT32 request, void *context) { A_STATUS status = A_OK; unsigned long flags; BUS_REQUEST *busrequest; BUS_REQUEST *async; BUS_REQUEST *active; AR_DEBUG_ASSERT(device != NULL); AR_DEBUG_ASSERT(device->func != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: %p\n", device)); do { if ((request & HIF_ASYNCHRONOUS) || (request & HIF_SYNCHRONOUS)){ /* serialize all requests through the async thread */ AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Execution mode: %s\n", (request & HIF_ASYNCHRONOUS)?"Async":"Synch")); busrequest = hifAllocateBusRequest(device); if (busrequest == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: no async bus requests available\n")); return A_ERROR; } spin_lock_irqsave(&device->asynclock, flags); busrequest->address = address; busrequest->buffer = buffer; busrequest->length = length; busrequest->request = request; busrequest->context = context; /* add to async list */ active = device->asyncreq; if (active == NULL) { device->asyncreq = busrequest; device->asyncreq->inusenext = NULL; } else { for (async = device->asyncreq; async != NULL; async = async->inusenext) { active = async; } active->inusenext = busrequest; busrequest->inusenext = NULL; } spin_unlock_irqrestore(&device->asynclock, flags); if (request & HIF_SYNCHRONOUS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued sync req: 0x%X\n", (unsigned int)busrequest)); /* wait for completion */ up(&device->sem_async); if (down_interruptible(&busrequest->sem_req) != 0) { /* interrupted, exit */ return A_ERROR; } else { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%X: 0x%X\n", (unsigned int)busrequest, busrequest->status)); AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request)); hifFreeBusRequest(device, busrequest); return busrequest->status; } } else { AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: queued async req: 0x%X\n", (unsigned int)busrequest)); up(&device->sem_async); return A_PENDING; } } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: Invalid execution mode: 0x%08x\n", (unsigned int)request)); status = A_EINVAL; break; } } while(0); return status; }
A_STATUS HIFReadWrite(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length, A_UINT32 request, void *context) { SDIO_STATUS status; SDREQUEST *sdrequest; BUS_REQUEST *busrequest = NULL; A_STATUS a_status = A_OK; /* Return any new requests if the shutdown is already in progress */ if (device->shutdownInProgress) { if (request & HIF_ASYNCHRONOUS) { device->htcCallbacks.rwCompletionHandler(context, A_ERROR); return A_PENDING; } return A_ERROR; } AR_DEBUG_ASSERT(device != NULL); AR_DEBUG_ASSERT(device->handle != NULL); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Device: %p\n", device)); if (length > device->curBlockSize) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid data length: %d\n", length)); return A_ERROR; } /* * We do not differentiate between the extended and the basic I/O so * we do not process the request type. */ /* * We do not differentiate between the byte and block data mode so * we do not process the request dmode. */ do { /* Addressing mode */ if (request & HIF_FIXED_ADDRESS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Address mode: Fixed\n")); } else if (request & HIF_INCREMENTAL_ADDRESS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Address mode: Incremental\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid address mode: 0x%08x\n", request)); a_status = A_ERROR; break; } /* * Mailbox write. Adjust the address so that the last byte * falls on the EOM address. */ if (request & HIF_WRITE) { if ((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3))) { DBG_ASSERT(length <= HIF_MBOX_WIDTH); address += (HIF_MBOX_WIDTH - length); } } /* Allocate a new bus request */ busrequest = hifAllocateBusRequest(device); if (busrequest == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate bus request\n")); a_status = A_ERROR; break; } sdrequest = busrequest->request; sdrequest->pDataBuffer = buffer; if (request & HIF_SYNCHRONOUS) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Execution mode: Synchronous\n")); sdrequest->Flags = SDREQ_FLAGS_RAW; sdrequest->pCompleteContext = NULL; sdrequest->pCompletion = NULL; } else if (request & HIF_ASYNCHRONOUS) { /* Populate the bus request to be passed in as context */ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Execution mode: Asynchronous\n")); /* setup async context */ busrequest->device = device; busrequest->context = context; sdrequest->pCompleteContext = busrequest; sdrequest->Flags = SDREQ_FLAGS_RAW | SDREQ_FLAGS_TRANS_ASYNC; sdrequest->pCompletion = hifRWCompletionHandler; } /* Indicate to the bus driver if its a read or a write */ if (request & HIF_WRITE) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Direction: Write\n")); if (((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3)))) { /* trapping HTC WRITE to mailbox, these will use the special DMA operation */ AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("--- MAILBOX WRITE ACCESS!!!!\n")); ATH_SET_DMA_OPERATION(sdrequest,ATH_TRANS_WRITE,address,length); } else { ATH_SET_PIO_EXTERNAL_WRITE_OPERATION(sdrequest, address, (request & HIF_INCREMENTAL_ADDRESS) ? TRUE : FALSE, length); } } else if (request & HIF_READ) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Direction: Read\n")); if (((address >= HIF_MBOX_START_ADDR(0)) && (address <= HIF_MBOX_END_ADDR(3)))) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" --- MAILBOX READ ACCESS!!!!\n")); /* trapping on HTC READ mailbox , these will use the special DMA operation */ ATH_SET_DMA_OPERATION(sdrequest,ATH_TRANS_READ,address,length); } else { ATH_SET_PIO_EXTERNAL_READ_OPERATION(sdrequest, address, request & HIF_INCREMENTAL_ADDRESS ? TRUE : FALSE, length); } } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Invalid direction: 0x%08x\n", request)); a_status = A_ERROR; break; } /* issue the request */ status = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest); if (!SDIO_SUCCESS(status)) { AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF Read/Write failure: %d\n", status)); a_status = A_ERROR; } } while (FALSE); if ((busrequest != NULL) && (request & HIF_SYNCHRONOUS)) { hifFreeBusRequest(device,busrequest); } return a_status; }