예제 #1
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);
}
예제 #2
0
/* 
 * SDIO_RegisterFunction - register a function driver
*/
SDIO_STATUS SDIO_RegisterFunction(PSDFUNCTION pFunction) {
    int error;
    SDIO_STATUS status;

    DBG_PRINT(SDDBG_TRACE, ("SDIO BusDriver - SDIO_RegisterFunction\n"));
    
        /* since we do PnP registration first, we need to check the version */
    if (!CHECK_FUNCTION_DRIVER_VERSION(pFunction)) {
        DBG_PRINT(SDDBG_ERROR, 
           ("SDIO Bus Driver: Function Major Version Mismatch (hcd = %d, bus driver = %d)\n",
           GET_SDIO_STACK_VERSION_MAJOR(pFunction), CT_SDIO_STACK_VERSION_MAJOR(g_Version)));
        return SDIO_STATUS_INVALID_PARAMETER;       
    }
    
    /* we are the exported verison, call the internal verison after registering with the bus
       we handle probes internally to the bus driver */
    if ((error = RegisterDriver(pFunction)) < 0) {
        DBG_PRINT(SDDBG_ERROR, 
            ("SDIO BusDriver - SDIO_RegisterFunction, failed to register with system bus driver: %d\n",
            error)); 
        status = OSErrorToSDIOError(error);       
    } else {
        status = _SDIO_RegisterFunction(pFunction);
        if (!SDIO_SUCCESS(status)) {
            UnregisterDriver(pFunction);   
        }
    }
    
    return status;
}
예제 #3
0
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  @function: Post a message queue

  @function name: SDLIB_PostMessage
  @prototype: SDIO_STATUS SDLIB_PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength)
  @category: Support_Reference
  
  @input: pQueue - message queue to post to
  @input: pMessage - message to post
  @input: MessageLength - length of message (for validation)
  
  @return: SDIO_STATUS
  
  @notes: The message queue uses an internal list of user defined message structures.  When
          posting a message the message is copied into an allocated structure and queued.  The memory 
          pointed to by pMessage does not need to be allocated and can reside on the stack. 
          The length of the message to post can be smaller that the maximum message size. This allows
          for variable length messages up to the maximum message size. This 
          function returns SDIO_STATUS_NO_RESOURCES, if the message queue is full.  This
          function returns SDIO_STATUS_BUFFER_TOO_SMALL, if the message size exceeds the maximum
          size of a message.  Posting and getting messsages from a message queue is safe in any
          driver context.
            
  @see also: SDLIB_CreateMessageQueue , SDLIB_GetMessage
  
  @example: Posting a message
       MyMessage message;
           // set up message
       message.code = MESSAGE_DATA_READY;
       message.pData = pInstance->pDataBuffers[currentIndex];
           // post message       
       status = SDLIB_PostMessage(pInstance->pReadQueue,&message,sizeof(message));
       if (!SDIO_SUCCESS(status)) {
           // failed
       }
  
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
SDIO_STATUS _PostMessage(PSDMESSAGE_QUEUE pQueue, PVOID pMessage, INT MessageLength)
{
    SDIO_STATUS status2;
    SDIO_STATUS status = SDIO_STATUS_SUCCESS;
    PSDMESSAGE_BLOCK pMsg;  
    CT_DECLARE_IRQ_SYNC_CONTEXT();
    
    if (MessageLength > pQueue->MaxMessageLength) {
        return SDIO_STATUS_BUFFER_TOO_SMALL;
    }
   
    status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection);
    if (!SDIO_SUCCESS(status)) {
        return status;
    }
    
    do {        
            /* get a message block */
        pMsg = GetFreeMessageBlock(pQueue);       
        if (NULL == pMsg) {
            status = SDIO_STATUS_NO_RESOURCES;
            break;    
        }
            /* copy the message */
        memcpy(pMsg->MessageStart,pMessage,MessageLength);
            /* set the length of the message */
        pMsg->MessageLength = MessageLength;
            /* queue the message to the list  */
        QueueMessageBlock(pQueue,pMsg);
    } while (FALSE);
    
    status2 = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection);
    return status; 
}
예제 #4
0
void SampleCompleteDMATransferCallback(pContext)
{
    PSDHCD_HW_DEVICE pHWDevice = (PSDHCD_HW_DEVICE)pContext;
    PSDHCD_DEVICE    pDevice;  
    SDIO_STATUS      status = SDIO_STATUS_SUCCESS;

    DBG_PRINT(ATH_SPI_TRACE_DATA, ("SPI  DMA COMPLETE - \n"));
   
    /* TODO : driver should check if DMA completed successfully, this is platform dependent */
    
    pDevice = pHWDevice->pDevice;  
    
    do {
        if (!SDIO_SUCCESS(status)) {
            break;
        }        
        
        if (pHWDevice->CommonBufferDMA && pDevice->CurrentTransferDirRx) {
                /* copy common buffer back for RX */
            HcdCommonBufferCopy(pDevice->CurrentDmaWidth,
                                pDevice->pCurrentBuffer,
                                pHWDevice->pDmaCommonBuffer,
                                pDevice->CurrentTransferLength,
                                pDevice->HostDMABufferCopyMode);
            
        }
        
    } while (FALSE);
            
    return;    
}   
예제 #5
0
/* ------ 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;
}
예제 #6
0
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  @function: Create a message queue

  @function name: SDLIB_CreateMessageQueue
  @prototype: PSDMESSAGE_QUEUE SDLIB_CreateMessageQueue(INT MaxMessages, INT MaxMessageLength)
  @category: Support_Reference
  
  @input: MaxMessages - Maximum number of messages this queue supports
  @input: MaxMessageLength - Maximum size of each message
 
  @return: Message queue object, NULL on failure
  
  @notes:  This function creates a simple first-in-first-out message queue.  The caller must determine 
           the maximum number of messages the queue supports and the size of each message.  This
           function will pre-allocate memory for each message. A producer of data posts a message
           using SDLIB_PostMessage with a user defined data structure. A consumer of this data 
           can retrieve the message (in FIFO order) using SDLIB_GetMessage. A message queue does not
           provide a signaling mechanism for notifying a consumer of data. Notifying a consumer is 
           user defined.
  
  @see also: SDLIB_DeleteMessageQueue, SDLIB_GetMessage, SDLIB_PostMessage.
  
  @example: Creating a message queue:
       typedef struct _MyMessage {
           UINT8 Code;
           PVOID pDataBuffer;
       } MyMessage;
            // create message queue, 16 messages max.
       pMsgQueue = SDLIB_CreateMessageQueue(16,sizeof(MyMessage));
       if (NULL == pMsgQueue) {
           .. failed
       }
  
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
PSDMESSAGE_QUEUE _CreateMessageQueue(INT MaxMessages, INT MaxMessageLength)
{
    PSDMESSAGE_QUEUE pQueue = NULL;
    SDIO_STATUS      status = SDIO_STATUS_SUCCESS;
    INT              ii;
    PSDMESSAGE_BLOCK pMsg;
    
    do {
        pQueue = (PSDMESSAGE_QUEUE)KernelAlloc(sizeof(SDMESSAGE_QUEUE));   
        
        if (NULL == pQueue) {
            status = SDIO_STATUS_NO_RESOURCES;
            break; 
        }
        SDLIST_INIT(&pQueue->MessageList);  
        SDLIST_INIT(&pQueue->FreeMessageList);  
        pQueue->MaxMessageLength = MaxMessageLength;       
        status = CriticalSectionInit(&pQueue->MessageCritSection);
        if (!SDIO_SUCCESS(status)) {
            break;   
        }       
            /* allocate message blocks */
        for (ii = 0; ii < MaxMessages; ii++) {
            pMsg = (PSDMESSAGE_BLOCK)KernelAlloc(sizeof(SDMESSAGE_BLOCK) + MaxMessageLength -1); 
            if (NULL == pMsg) {
                break;    
            }
            FreeMessageBlock(pQueue, pMsg);
        } 
       
        if (0 == ii) {
            status = SDIO_STATUS_NO_RESOURCES;
            break; 
        }
        
    } while (FALSE);      
  
    if (!SDIO_SUCCESS(status)) {
        if (pQueue != NULL) {
            _DeleteMessageQueue(pQueue);    
            pQueue = NULL;  
        } 
    }
    return pQueue;  
}
예제 #7
0
void
HIFAckInterrupt(HIF_DEVICE *device)
{
    SDIO_STATUS status;

    /* Acknowledge our function IRQ */
    status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ACK_IRQ, 
                               NULL, 0);
    AR_DEBUG_ASSERT(SDIO_SUCCESS(status));
}
예제 #8
0
///////////////////////////////////////////////////////////////////////////////
//  DRG_Init - the init entry point for the memory driver
//  Input:  dwContext - the context for this init
//  Output:
//  Return: non-zero context
//  Notes:
///////////////////////////////////////////////////////////////////////////////
extern
DWORD WINAPI DRG_Init(DWORD dwContext)
{
    PWCHAR                          pRegPath = NULL;
    DWORD                           dwRetCode = 0;
    HANDLE 		                    wlanHandle = NULL;
    SDIO_CLIENT_INIT_CONTEXT        *pContext;
    DWORD                           initContext = 0;
    SDIO_STATUS                     status;

    do {

        status = SDLIB_GetRegistryKeyDWORD(HKEY_LOCAL_MACHINE,
                                           (WCHAR  *)dwContext,
                                           DEVLOAD_CLIENTINFO_VALNAME,
                                           (DWORD *)&pContext);

        if (!SDIO_SUCCESS(status)) {
            break;
        }

        if (pContext->Magic != SDIO_CLIENT_INIT_MAGIC) {
            return 0;
        }

        memcpy(&g_ClientInitContext,pContext,sizeof(SDIO_CLIENT_INIT_CONTEXT));

        if (drvInit() != A_OK) {
            break;
        }

        if (!createRegKeyValues()) {
            break;
        }

        //
        // Create Named Event to notify AR6K Monitor Service program
        //
        wlanHandle = CreateEvent (NULL, FALSE, FALSE, L"ATHRWLAN6KEVENT");
        dwRetCode  = GetLastError ();
        if (NULL == wlanHandle) {
            break;
        }
        //
        // Set the event to trigger the service
        //
        SetEvent (wlanHandle);

        /* just return non-zero */
        initContext = 1;

    } while (FALSE);

    return initContext;
}
예제 #9
0
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));

}
예제 #10
0
/* 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;
}
예제 #11
0
    /* ASYNC completion callback */
static void HifReadWriteScatterCompletion(SDREQUEST *sdrequest)
{
    HIF_SCATTER_REQ *pReq = sdrequest->pCompleteContext;
    HIF_DEVICE      *device;
    
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("+HIF Scatter Completion \n"));
                            
    if (!SDIO_SUCCESS(sdrequest->Status)) {
        pReq->CompletionStatus = A_ERROR;    
    } else {
        pReq->CompletionStatus = A_OK;         
    }
    
    device = GET_HIFDEVICE_SR(pReq);
    
        /* complete the request */
    pReq->CompletionRoutine(pReq);
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("-HIF Scatter Completion \n"));
        
}
예제 #12
0
void
HIFUnMaskInterrupt(HIF_DEVICE *device)
{
    SDIO_STATUS status;

    AR_DEBUG_ASSERT(device != NULL);
    AR_DEBUG_ASSERT(device->handle != NULL);
    
    /* Unmask our function IRQ */
    status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_UNMASK_IRQ, 
                               NULL, 0);
    AR_DEBUG_ASSERT(SDIO_SUCCESS(status));
   
    /*
     * It was observed that if ar6000 module was removed while an interrupt
     * was pending then when its reloaded subsequently, the hcd/bus driver
     * expects an explicit acknowledgment before it can start reporting
     * interrupts. Under normal conditions, this should be harmless.
     */
    HIFAckInterrupt(device);
}
예제 #13
0
void
HIFShutDownDevice(HIF_DEVICE *device)
{
    SDIO_STATUS status;

    if (device != NULL) {
        
        device->shutdownInProgress = TRUE;
        AR_DEBUG_ASSERT(device->handle != NULL);
    
    } else {
        /* 
         * Unregister with bus driver core. This should flush the pending 
         * requests in the HCD's queues.
         */
        AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Unregistering with the bus driver\n"));
        status = SDIO_UnregisterFunction(&FunctionContext.function);
        AR_DEBUG_ASSERT(SDIO_SUCCESS(status));

    }
}
예제 #14
0
/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  @function: Get a message from a message queue

  @function name: SDLIB_GetMessage
  @prototype: SDIO_STATUS SDLIB_GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength) 
  @category: Support_Reference
  
  @input: pQueue - message queue to retreive a message from
  @input: pBufferLength - on entry, the length of the data buffer
  @output: pData - buffer to hold the message
  @output: pBufferLength - on return, contains the number of bytes copied

  @return: SDIO_STATUS
  
  @notes: The message queue uses an internal list of user defined message structures.  The message is
          dequeued (FIFO order) and copied to the callers buffer.  The internal allocation for the message
          is returned back to the message queue. This function returns SDIO_STATUS_NO_MORE_MESSAGES
          if the message queue is empty. If the length of the buffer is smaller than the length of 
          the message at the head of the queue,this function returns SDIO_STATUS_BUFFER_TOO_SMALL and
          returns the required length in pBufferLength.
            
  @see also: SDLIB_CreateMessageQueue , SDLIB_PostMessage
  
  @example: Getting a message
       MyMessage message;
       INT       length;
           // set length
       length = sizeof(message);
           // post message       
       status = SDLIB_GetMessage(pInstance->pReadQueue,&message,&length);
       if (!SDIO_SUCCESS(status)) {
           // failed
       }
       
  @example: Checking queue for a message and getting the size of the message
       INT       length;
           // use zero length to get the size of the message
       length = 0;
       status = SDLIB_GetMessage(pInstance->pReadQueue,NULL,&length);
       if (status == SDIO_STATUS_NO_MORE_MESSAGES) {
            // no messages in queue 
       } else if (status == SDIO_STATUS_BUFFER_TOO_SMALL) {
            // message exists in queue and length of message is returned
            messageSizeInQueue = length;
       } else {
            // some other failure
       }
       
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
SDIO_STATUS _GetMessage(PSDMESSAGE_QUEUE pQueue, PVOID pData, INT *pBufferLength) 
{
    SDIO_STATUS status2;
    SDIO_STATUS status = SDIO_STATUS_SUCCESS;  
    PSDMESSAGE_BLOCK pMsg; 
    CT_DECLARE_IRQ_SYNC_CONTEXT();
    
    status = CriticalSectionAcquireSyncIrq(&pQueue->MessageCritSection);
    if (!SDIO_SUCCESS(status)) {
        return status;
    }
    
    do {
        pMsg = GetQueuedMessage(pQueue);
        if (NULL == pMsg) {
            status = SDIO_STATUS_NO_MORE_MESSAGES;
            break;    
        } 
        if (*pBufferLength < pMsg->MessageLength) {
                /* caller buffer is too small */
            *pBufferLength = pMsg->MessageLength;
                /* stick it back to the front */
            QueueMessageToHead(pQueue, pMsg);
            status = SDIO_STATUS_BUFFER_TOO_SMALL;
            break;
        }    
            /* copy the message to the callers buffer */
        memcpy(pData,pMsg->MessageStart,pMsg->MessageLength);
            /* return actual length */
        *pBufferLength = pMsg->MessageLength; 
            /* return this message block back to the free list  */
        FreeMessageBlock(pQueue, pMsg);
        
    } while (FALSE);
    
    status2 = CriticalSectionReleaseSyncIrq(&pQueue->MessageCritSection);
    
    return status;     
}
예제 #15
0
SDHCD_HW_DEVICE *InitializeSPIHW(PTSTR pRegPath)
{
    
    PSDHCD_DEVICE   pDevice;   
    SDHCD_HW_DEVICE *pHWDevice;                  
    DWORD           threadId;  
    SDIO_STATUS     status = SDIO_STATUS_SUCCESS;
     
    do {      
            /* for now this is a static, single instance allocation */
        pHWDevice = &g_HWDevice;
        ZERO_POBJECT(pHWDevice);       
        pDevice = &pHWDevice->SpiCommon; 
        pHWDevice->pDevice = pDevice;
            /* set the HW portion */
        pDevice->pHWDevice = pHWDevice; 
        pHWDevice = GET_HW_DEVICE(pDevice);         
        SET_SDIO_STACK_VERSION(&pDevice->Hcd);
        pDevice->Hcd.pName = SDIO_RAW_BD_BASE;
        pDevice->Hcd.Attributes = 0;
        pDevice->Hcd.pContext = pDevice;
        pDevice->Hcd.pRequest = HcdRequest;
        pDevice->Hcd.pConfigure = HcdConfig;
        
            /* TODO : adjust these to match controller hardware */
        pDevice->OperationalClock = 12000000;  /* 12 mhz */
        pDevice->Hcd.MaxBytesPerBlock = 4096;  /* used as a hint to indicate max size of common buffer */
        pDevice->Hcd.MaxBlocksPerTrans = 1;    /* must be one*/
        pDevice->Hcd.MaxClockRate = 48000000;  /* 48 Mhz */
        pDevice->PowerUpDelay = 100;
            /* set all the supported frame widths the controller can do
             * 8/16/24/32 bit frames */
        pDevice->SpiHWCapabilitiesFlags = HW_SPI_FRAME_WIDTH_8  | 
                                          HW_SPI_FRAME_WIDTH_16 | 
                                          HW_SPI_FRAME_WIDTH_24 |
                                          HW_SPI_FRAME_WIDTH_32;

  
        pDevice->MiscFlags |= MISC_FLAG_DUMP_STATE_ON_SHUTDOWN | MISC_FLAG_RESET_SPI_IF_SHUTDOWN;
        
        SDLIB_InitializeWorkerTask(&pHWDevice->IOCompleteWorkTask,
                                   IOCompleteWork,
                                   pHWDevice);
        
        pHWDevice->pWorker = SDLIB_CreateWorker(WORKER_THREAD_PRIORITY);
        
        if (NULL == pHWDevice->pWorker) {
            status = SDIO_STATUS_NO_RESOURCES;
            break;    
        }
        
        /* TODO : allocate hardware resources (I/O , interrupt, DMA etc..) */



        /*************************************/
        
        status = HcdInitialize(pDevice);
   
            /* initialize common layer */
        if (!SDIO_SUCCESS(status)) {
            DBG_PRINT(SDDBG_ERROR, ("SPI - failed to init common layer, status =%d\n", status));
            break;
        } 
                       
        pHWDevice->InitStateMask |= SDHC_COMMON_INIT;
        
             /* create the interrupt event */
        pHWDevice->hIstEventSPIGpioIRQ = CreateEvent(NULL, FALSE, FALSE, NULL);
        
        if (NULL == pHWDevice->hIstEventSPIGpioIRQ) {
            status = SDIO_STATUS_NO_RESOURCES;
            break;
        }

            /* TODO set appropriate system interrupt for GPIO IRQ,
             * GPIO IRQ must be level sensitive, active LOW */
        pHWDevice->SysIntrSPIGpioIRQ = 0;

        /* TODO : uncomment the following to associate the GPIO IRQ to the interrupt event :
        if (!InterruptInitialize(pHWDevice->SysIntrSPIGpioIRQ,
                                 pHWDevice->hIstEventSPIGpioIRQ,
                                 NULL,
                                 0)) {
            DBG_PRINT(SDDBG_ERROR,("SPI HCD: Failed to initialize Interrupt! \n"));
            status = SDIO_STATUS_NO_RESOURCES;
            break;
        }
        */
        
            /* create the IST thread */
        pHWDevice->hIstSPIGpioIRQ = CreateThread(NULL,
                                     0,
                                     (LPTHREAD_START_ROUTINE)SpiGpioIRQInterruptThread,
                                     (LPVOID)pHWDevice,
                                     0,
                                     &threadId);
                                     
        if (NULL == pHWDevice->hIstSPIGpioIRQ) {
            status = SDIO_STATUS_NO_RESOURCES;
            DBG_PRINT(SDDBG_ERROR,("SPI HCD: Failed to Create IST! \n"));
            break;
        }
        
           /* register with the SDIO bus driver */
        if (!SDIO_SUCCESS((status = SDIO_RegisterHostController(&pDevice->Hcd)))) {
            DBG_PRINT(SDDBG_ERROR, ("SPI HCD: Probe - failed to register with host, status =%d\n",status));
            break;
        }   
          
        pHWDevice->InitStateMask |= SDHC_REGISTERED;
                           
    } while (FALSE);
     
    if (!SDIO_SUCCESS(status)) {
        if (pHWDevice != NULL) {
            CleanupSPIHW(pHWDevice);
            pHWDevice = NULL;
        }
    } else {
        DBG_PRINT(SDDBG_ERROR, ("SPI - HCD ready! \n"));
    }
    
    DBG_PRINT(SDDBG_TRACE, ("-SPI HCD: Setup - status : %d\n", status));
    return SDIO_SUCCESS(status) ? pHWDevice : NULL;  
}    
예제 #16
0
static A_STATUS HifReadWriteScatter(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
{
   
    A_STATUS        status = A_EINVAL;   
    SDREQUEST       *sdrequest;
    A_UINT8         rw;
    A_UINT8         mode;
    A_UINT8         funcNo;
    A_UINT8         opcode;
    A_UINT16        count;
    SDIO_STATUS     sdiostatus;
    A_UINT32        request = pReq->Request;
    
    do {
        
        AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("HIF Scatter : %d Scatter Entries: %d\n", 
                            pReq->TotalLength, pReq->ValidScatterEntries));
        
        if (pReq->TotalLength > MAX_SCATTER_REQ_TRANSFER_SIZE) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("Invalid length: %d \n", pReq->TotalLength));
            break;          
        }
        
        if (pReq->TotalLength == 0) {
            A_ASSERT(FALSE);
            break;    
        }
        
            /* get the sd bus request associated with this scatter request */         
        sdrequest = GET_SDREQUEST_SR(pReq);
        
        if (request & HIF_SYNCHRONOUS) {
            sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS;
            sdrequest->pCompleteContext = NULL;
            sdrequest->pCompletion = NULL;
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,("  Synchronous \n"));
        } else if (request & HIF_ASYNCHRONOUS) {
            sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS |
                               SDREQ_FLAGS_TRANS_ASYNC;  
            sdrequest->pCompleteContext = pReq;
            sdrequest->pCompletion = HifReadWriteScatterCompletion;
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,("  Asynchronous \n"));
        } else {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("Invalid execution mode: 0x%08x\n", request));
            break;
        }

        if (!(request & HIF_EXTENDED_IO)) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("Invalid command type: 0x%08x\n", request));
            break;
        }

        sdrequest->Command = CMD53;
            
        if (!(request & HIF_BLOCK_BASIS)) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("Invalid data mode: 0x%08x\n", request));
            break;   
        }
            /* only block-mode commands */
        mode = CMD53_BLOCK_BASIS;
        sdrequest->BlockLen = HIF_MBOX_BLOCK_SIZE;
        sdrequest->BlockCount = pReq->TotalLength / HIF_MBOX_BLOCK_SIZE;
        count = sdrequest->BlockCount;
        AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
                        ("  Block mode (BlockLen: %d, BlockCount: %d)\n",
                        sdrequest->BlockLen, sdrequest->BlockCount));
             
        if (request & HIF_WRITE) {
            rw = CMD53_WRITE;
            sdrequest->Flags |= SDREQ_FLAGS_DATA_WRITE;
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("  Direction: Write\n"));
        } else if (request & HIF_READ) {
            rw = CMD53_READ;
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("  Direction: Read\n"));
        } else {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("Invalid direction: 0x%08x\n", request));
            break;
        }

        if (request & HIF_FIXED_ADDRESS) {
            opcode = CMD53_FIXED_ADDRESS;
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("  Address mode: Fixed\n"));
        } else if (request & HIF_INCREMENTAL_ADDRESS) {
            opcode = CMD53_INCR_ADDRESS;
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("  Address mode: Incremental\n"));
        } else {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("Invalid address mode: 0x%08x\n", request));
            break;
        }
        
        
        funcNo = SDDEVICE_GET_SDIO_FUNCNO(device->handle);
       
        SDIO_SET_CMD53_ARG(sdrequest->Argument, rw, funcNo,
                           mode, opcode, pReq->Address, count);
        
        AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("HIF Scatter : SDIO CMD53 card address: 0x%X blocks: %d\n", 
                            pReq->Address, count));
                            
        AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("HIF Scatter : SDIO CMD53 , request flags:0x%X arg:0x%X\n", 
                            sdrequest->Flags, sdrequest->Argument));
                            
        status = SetupBusRequestForDMA(device, sdrequest, pReq);
        
        if (A_FAILED(status)){
            break;    
        }

        if (sdrequest->pDataBuffer == NULL) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            (" sdrequest->pDataBuffer is NULL!!!\n"));
            status = A_ERROR;
            // A_ASSERT(FALSE);
            break;    
        }
                    
            /* Send the command out */
        sdiostatus = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest);
        
        if (!SDIO_SUCCESS(sdiostatus)) {
            status = A_ERROR;
            break;
        }
            
        status = A_OK;
       
    } while (FALSE);

    if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
        pReq->CompletionStatus = status;
        pReq->CompletionRoutine(pReq);
        status = A_OK;
    }
        
    return status;  
}
예제 #17
0
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;
}