Exemple #1
0
/*
 * \brief	Config the FwEvent module object
 *
 * \param  hFwEvent  - FwEvent Driver handle
 * \param  hTWD  - Handle to TWD module
 * \return TI_OK
 *
 * \par Description
 * From hTWD we extract : hOs, hReport, hTwIf, hContext,
 *      hHealthMonitor, hEventMbox, hCmdMbox, hRxXfer,
 *      hTxHwQueue, hTxResult
 * In this function we also register the FwEvent to the context engine
 *
 * \sa
 */
TI_STATUS fwEvent_Init (TI_HANDLE hFwEvent, TI_HANDLE hTWD)
{
	TfwEvent  *pFwEvent = (TfwEvent *)hFwEvent;
	TTwd      *pTWD = (TTwd *)hTWD;
	TTxnStruct* pTxn;

	pFwEvent->hTWD              = hTWD;
	pFwEvent->hOs               = pTWD->hOs;
	pFwEvent->hReport           = pTWD->hReport;
	pFwEvent->hContext          = pTWD->hContext;
	pFwEvent->hTwIf             = pTWD->hTwIf;
	pFwEvent->hHealthMonitor    = pTWD->hHealthMonitor;
	pFwEvent->hEventMbox        = pTWD->hEventMbox;
	pFwEvent->hCmdMbox          = pTWD->hCmdMbox;
	pFwEvent->hRxXfer           = pTWD->hRxXfer;
	pFwEvent->hTxHwQueue        = pTWD->hTxHwQueue;
	pFwEvent->hTxXfer           = pTWD->hTxXfer;
	pFwEvent->hTxResult         = pTWD->hTxResult;

	pFwEvent->eSmState          = FWEVENT_STATE_IDLE;
	pFwEvent->bIntrPending      = TI_FALSE;
	pFwEvent->uNumPendHndlrs    = 0;
	pFwEvent->uEventMask        = 0;
	pFwEvent->uEventVector      = 0;

	/* Prepare Interrupts Mask regiter Txn structure */
	/*
	 * Note!!: The mask transaction is sent in low priority because it is used in the
	 *           init process which includes a long sequence of low priority transactions,
	 *           and the order of this sequence is important so we must use the same priority
	 */
	pTxn = (TTxnStruct*)&pFwEvent->tMaskTxn.tTxnStruct;
	TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
	BUILD_TTxnStruct(pTxn, HINT_MASK, &pFwEvent->tMaskTxn.uData, REGISTER_SIZE, NULL, NULL)

	/* Prepare FW status Txn structure (includes 4 bytes interrupt status reg and 64 bytes FW-status from memory area) */
	/* Note: This is the only transaction that is sent in high priority.
	 *       The original reason was to lower the interrupt latency, but we may consider using the
	 *         same priority as all other transaction for simplicity.
	 */
	pTxn = (TTxnStruct*)&pFwEvent->tFwStatusTxn.tTxnStruct;
	TXN_PARAM_SET(pTxn, TXN_HIGH_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
	BUILD_TTxnStruct(pTxn, FW_STATUS_ADDR, &pFwEvent->tFwStatusTxn.tFwStatus, sizeof(FwStatus_t), (TTxnDoneCb)fwEvent_StateMachine, hFwEvent)

	/*
	 *  Register the FwEvent to the context engine and get the client ID.
	 *  The FwEvent() will be called from the context_DriverTask() after scheduled
	 *    by a FW-Interrupt (see fwEvent_InterruptRequest()).
	 */
	pFwEvent->uContextId = context_RegisterClient (pFwEvent->hContext,
	                       fwEvent_NewEvent,
	                       hFwEvent,
	                       TI_FALSE,
	                       "FW_EVENT",
	                       sizeof("FW_EVENT"));

	return TI_OK;
}
Exemple #2
0
/*
 * \brief	Send the Command to the Mailbox
 * 
 * \param  hCmdMbox  - Handle to CmdMbox
 * \param  cmdType  - 
 * \param  pParamsBuf  - The buffer that will be written to the mailbox
 * \param  uWriteLen  - Length of data to write to the mailbox
 * \param  uReadLen  - Length of data to read from the mailbox (when the result is received)
 * \return TI_PENDING
 * 
 * \par Description
 * Copy the buffer given to a local struct, update the write & read lengths
 * and send to the FW's mailbox.
 *             
 *       ------------------------------------------------------
 *      | CmdMbox Header | Cmd Header    | Command parameters |
 *      ------------------------------------------------------
 *      | ID   | Status  | Type | Length | Command parameters |
 *      ------------------------------------------------------
 *       16bit   16bit    16bit   16bit     
 *
 * \sa cmdMbox_CommandComplete
 */
TI_STATUS cmdMbox_SendCommand       (TI_HANDLE hCmdMbox, Command_e cmdType, TI_UINT8* pParamsBuf, TI_UINT32 uWriteLen, TI_UINT32 uReadLen)
{
    TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    TTxnStruct *pCmdTxn = (TTxnStruct*)&pCmdMbox->aCmdTxn[0].tTxnStruct;
    TTxnStruct *pRegTxn = (TTxnStruct*)&pCmdMbox->aRegTxn[0].tTxnStruct;
    Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[0].tCmdMbox;
    

    if (pCmdMbox->bCmdInProgress)
    {
        TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR, "cmdMbox_SendCommand(): Trying to send Cmd while other Cmd is still in progres!\n");
        return TI_NOK;
    }

    /* Add the CMDMBOX_HEADER_LEN to the read length, used when reading the result later on */
    pCmdMbox->uReadLen = uReadLen + CMDMBOX_HEADER_LEN;
    /* Prepare the Cmd Hw template */
    pCmd->cmdID = cmdType;
    pCmd->cmdStatus = CMD_STATUS_SUCCESS;
    os_memoryCopy (pCmdMbox->hOs, (void *)pCmd->parameters, (void *)pParamsBuf, uWriteLen);

    /* Add the CMDMBOX_HEADER_LEN to the write length */
    pCmdMbox->uWriteLen = uWriteLen + CMDMBOX_HEADER_LEN;

    /* Must make sure that the length is multiple of 32 bit */
    if (pCmdMbox->uWriteLen & 0x3)
    {
        TRACE1(pCmdMbox->hReport, REPORT_SEVERITY_WARNING, "cmdMbox_SendCommand(): Command length isn't 32bit aligned! CmdId=%d\n", pCmd->cmdID);
        pCmdMbox->uWriteLen = (pCmdMbox->uWriteLen + 4) & 0xFFFFFFFC;
    }

    /* no other command can start the send process  till bCmdInProgress will return to TI_FALSE*/
    pCmdMbox->bCmdInProgress = TI_TRUE;

    /* Build the command TxnStruct */
    TXN_PARAM_SET(pCmdTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
    BUILD_TTxnStruct(pCmdTxn, pCmdMbox->uFwAddr, pCmd, pCmdMbox->uWriteLen, NULL, NULL)
    /* Send the command */
    twIf_Transact(pCmdMbox->hTwIf, pCmdTxn);

    /* Build the trig TxnStruct */
    pCmdMbox->aRegTxn[0].uRegister = INTR_TRIG_CMD;
    TXN_PARAM_SET(pRegTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
    BUILD_TTxnStruct(pRegTxn, ACX_REG_INTERRUPT_TRIG, &(pCmdMbox->aRegTxn[0].uRegister), REGISTER_SIZE, NULL, NULL)

    /* start the CmdMbox timer */
    tmr_StartTimer (pCmdMbox->hCmdMboxTimer, cmdMbox_TimeOut, hCmdMbox, CMDMBOX_WAIT_TIMEOUT, TI_FALSE);

    /* Send the FW trigger */
    twIf_Transact(pCmdMbox->hTwIf, pRegTxn);


    return TXN_STATUS_PENDING;
}
Exemple #3
0
/*
 * \brief	Read the command's result
 * 
 * \param  hCmdMbox  - Handle to CmdMbox
 * \return void
 * 
 * \par Description
 * This function is called from FwEvent module uppon receiving command complete interrupt.
 * It issues a read transaction from the mailbox with a CB.
 * 
 * \sa cmdMbox_SendCommand, cmdMbox_TransferComplete
 */
ETxnStatus cmdMbox_CommandComplete (TI_HANDLE hCmdMbox)
{
    TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    TTxnStruct *pCmdTxn = (TTxnStruct*)&pCmdMbox->aCmdTxn[1].tTxnStruct;
    Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
    ETxnStatus  rc;

    /* stop the CmdMbox timer */
    tmr_StopTimer(pCmdMbox->hCmdMboxTimer);

    /* Build the command TxnStruct */
    TXN_PARAM_SET(pCmdTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
    /* Applying a CB in case of an async read */
    BUILD_TTxnStruct(pCmdTxn, pCmdMbox->uFwAddr, pCmd, pCmdMbox->uReadLen,(TTxnDoneCb)cmdMbox_TransferComplete, hCmdMbox)
    /* Send the command */
    rc = twIf_Transact(pCmdMbox->hTwIf, pCmdTxn);

    /* In case of a sync read, call the CB directly */
    if (rc == TXN_STATUS_COMPLETE)
    {
        cmdMbox_TransferComplete(hCmdMbox);
    }

    return TXN_STATUS_COMPLETE;
}
/*
 * \brief	Read Address to FW
 * 
 * \param  hFwDebug  - Handle to FW Debug
 * \param  Address - Absolute HW address
 * \param  Length - Length in byte to write
 * \param  Buffer - Buffer to copy to FW
 * \param  fCb - CB function
 * \param  hCb - CB Handle
 * \return none
 * 
 * \par Description
 * Read from HW, must receive length in byte max size 256 bytes
 * address must be absolute HW address.
 * 
 * \sa 
 */
TI_STATUS fwDbg_ReadAddr (TI_HANDLE hFwDebug,
                          TI_UINT32 Address,
                          TI_UINT32 Length,
                          TI_UINT8* Buffer,
                          TFwDubCallback fCb,
                          TI_HANDLE hCb)
{
	TI_STATUS rc;
	TTxnStruct *pTxn;
	TFwDebug *pFwDebug = (TFwDebug*)hFwDebug;
	pTxn = &pFwDebug->tTxn;
	/* check if length is large than default threshold */
	if (Length > DMA_SIZE_BUF)
	{
TRACE1(pFwDebug->hReport, REPORT_SEVERITY_ERROR, "fwDbg_ReadAddr : Buffer Length too large -- %d",Length);
		return TXN_STATUS_ERROR;
	}

	pFwDebug->fCb = fCb;
	pFwDebug->hCb = hCb;
	pFwDebug->pReadBuf = Buffer;

	/* Build the command TxnStruct */
    TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
	/* Applying a CB in case of an async read */
    BUILD_TTxnStruct(pTxn, Address, pFwDebug->pDMABuf, Length,(TTxnDoneCb)fwDbg_ReadAddrCb, pFwDebug)
	rc = twIf_Transact(pFwDebug->hTwif,pTxn);
	if (rc == TXN_STATUS_COMPLETE)
    {
		/* copy from DMA buufer to given buffer */
		os_memoryCopy(pFwDebug->hOs,pFwDebug->pReadBuf,pFwDebug->pDMABuf,Length);
	}
	return rc;
}
/** 
 * \fn     ifSlpMng_Init
 * \brief  Interface Sleep Manager object initialization
 * 
 */ 
EMcpfRes ifSlpMng_Init (handle_t 		 	 hIfSlpMng, 
						  const handle_t 	 hTxnQ,
						  const handle_t 	 hBusDrv,
						  const McpU32 	 	 uFuncId,
						  const McpHalChipId tChipId, 
						  const McpHalTranId tTransId)
{
	TifSlpMngObj  * pIfSlpMng = (TifSlpMngObj *) hIfSlpMng;
	McpHalPmHandler pmHandler = {pmEventHandler};

	pIfSlpMng->hTxnQ 	= hTxnQ;			/* Transaction queue handle 	 	*/
	pIfSlpMng->hBusDrv 	= hBusDrv;			/* Bus driver handle 	 			*/
	pIfSlpMng->uFuncId	= uFuncId;     		/* Transaction queue function id 	*/
	pIfSlpMng->tChipId 	= tChipId;      	/* PM chip id for power management 	*/
	pIfSlpMng->tTransId = tTransId;     	/* PM transport layer id for power management */

    /* Build Sleep Management transaction */
    TXN_PARAM_SET (pIfSlpMng->pMngTxn, TXN_HIGH_PRIORITY, TXN_FUNC_ID_CTRL, TXN_DIRECTION_WRITE, 0);
    BUILD_TTxnStruct (pIfSlpMng->pMngTxn, 0, NULL, 0, NULL, NULL);
    TXN_PARAM_SET_SINGLE_STEP(pIfSlpMng->pMngTxn, 1);  /* Sleep Management transaction is always single step */

	pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE;

	MCP_HAL_PM_RegisterTransport (pIfSlpMng->tChipId, pIfSlpMng->tTransId, &pmHandler);

	return RES_OK;
}
/*
 * \brief	Read mailbox address
 *
 * \param  hEventMbox  - Handle to EventMbox
 * \param  fCb		   - CB function to return in Async mode
 * \param  hCb		   - CB Habdle
 * \return TXN_STATUS_COMPLETE, TXN_STATUS_PENDING, TXN_STATUS_ERROR
 *
 * \par Description
 * This function is called for initialize the Event MBOX addresses.
 * It issues a read transaction from the Twif with a CB.
 *
 * \sa
 */
TI_STATUS eventMbox_InitMboxAddr(TI_HANDLE hEventMbox, fnotify_t fCb, TI_HANDLE hCb)
{
	TTxnStruct  *pTxn;
	TEventMbox* pEventMbox;
	ETxnStatus  rc;
	pEventMbox = (TEventMbox*)hEventMbox;
	pTxn = &pEventMbox->iTxnGenRegSize.tTxnReg;

	/* Store the Callabck address of the modules that called us in case of Asynchronuous transaction that will complete later */
	pEventMbox->fCb = fCb;
	pEventMbox->hCb = hCb;

	/* Build the command TxnStruct */
	TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
	/* Applying a CB in case of an async read */
	BUILD_TTxnStruct(pTxn, REG_EVENT_MAILBOX_PTR, &pEventMbox->iTxnGenRegSize.iRegBuffer, REGISTER_SIZE, eventMbox_ReadAddrCb, hEventMbox)
	rc = twIf_Transact(pEventMbox->hTwif,pTxn);
	if (rc == TXN_STATUS_COMPLETE) {
		pEventMbox->EventMboxAddr[0] = pEventMbox->iTxnGenRegSize.iRegBuffer;
		pEventMbox->EventMboxAddr[1] = pEventMbox->EventMboxAddr[0] + sizeof(EventMailBox_t);
		TRACE3(pEventMbox->hReport, REPORT_SEVERITY_INIT , "eventMbox_ConfigHw: event A Address=0x%x, event B Address=0x%x, sizeof=%d\n", pEventMbox->EventMboxAddr[0], pEventMbox->EventMboxAddr[1], sizeof(EventMailBox_t));

	}
	return rc;
}
Exemple #7
0
/*
 * \brief	configure the mailbox address.
 *
 * \param  hCmdMbox  - Handle to CmdMbox
 * \param  fCb  - Pointer to the CB
 * \param  hCb  - Cb's handle
 * \return TI_OK or TI_PENDING
 *
 * \par Description
 * Called from HwInit to read the command mailbox address.
 *
 * \sa
 */
TI_STATUS cmdMbox_ConfigHw (TI_HANDLE hCmdMbox, fnotify_t fCb, TI_HANDLE hCb)
{
	TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
	TTxnStruct *pRegTxn = (TTxnStruct*)&pCmdMbox->aRegTxn[1].tTxnStruct;
	TI_STATUS   rc;

	pCmdMbox->fCb = fCb;
	pCmdMbox->hCb = hCb;
	/* Build the command TxnStruct */
	TXN_PARAM_SET(pRegTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
	BUILD_TTxnStruct(pRegTxn, REG_COMMAND_MAILBOX_PTR, &(pCmdMbox->aRegTxn[1].uRegister), REGISTER_SIZE,(TTxnDoneCb)cmdMbox_ConfigHwCb, hCmdMbox)
	/* Get the command mailbox address */
	rc = twIf_Transact(pCmdMbox->hTwIf, pRegTxn);
	if (rc == TXN_STATUS_COMPLETE) {
		pCmdMbox->uFwAddr = pCmdMbox->aRegTxn[1].uRegister;
	}

	return rc;
}
/*
 * \brief	Handle the incoming event read the Mbox data
 *
 * \param  hEventMbox  - Handle to EventMbox
 * \param  TFwStatus  - FW status
 * \return none
 *
 * \par Description
 * This function is called from the FW Event upon receiving MBOX event.
 * \sa
 */
ETxnStatus eventMbox_Handle(TI_HANDLE hEventMbox,FwStatus_t* pFwStatus)
{
	ETxnStatus	rc;
	TTxnStruct  *pTxn;
	TEventMbox *pEventMbox = (TEventMbox *)hEventMbox;

	pTxn = &pEventMbox->iTxnEventMbox.tEventMbox;

	TRACE1(pEventMbox->hReport, REPORT_SEVERITY_INFORMATION, "eventMbox_Handle : Reading from MBOX -- %d",pEventMbox->ActiveMbox);

#ifdef TI_DBG
	/* Check if missmatch MBOX */
	if (pEventMbox->ActiveMbox == 0) {
		if (pFwStatus->intrStatus & ACX_INTR_EVENT_B) {
			TRACE0(pEventMbox->hReport, REPORT_SEVERITY_ERROR, "eventMbox_Handle : incorrect MBOX SW MBOX -- A FW MBOX -- B");
		}
	} else if (pEventMbox->ActiveMbox == 1) {
		if (pFwStatus->intrStatus & ACX_INTR_EVENT_A) {
			TRACE0(pEventMbox->hReport, REPORT_SEVERITY_ERROR, "eventMbox_Handle : incorrect MBOX SW MBOX -- B FW MBOX -- A");
		}
	}
#endif /* TI_DBG */

	if (pEventMbox->CurrentState != EVENT_MBOX_STATE_IDLE) {
		TRACE0(pEventMbox->hReport, REPORT_SEVERITY_ERROR, "eventMbox_Handle : Receiving event not in Idle state");
	}
	pEventMbox->CurrentState = EVENT_MBOX_STATE_READING;

	/* Build the command TxnStruct */
	TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
	/* Applying a CB in case of an async read */
	BUILD_TTxnStruct(pTxn, pEventMbox->EventMboxAddr[pEventMbox->ActiveMbox], &pEventMbox->iTxnEventMbox.iEventMboxBuf, sizeof(EventMailBox_t),(TTxnDoneCb)eventMbox_ReadCompleteCB, pEventMbox)
	rc = twIf_Transact(pEventMbox->hTwif,pTxn);

	pEventMbox->ActiveMbox = 1 - pEventMbox->ActiveMbox;
	if (rc == TXN_STATUS_COMPLETE) {
		eventMbox_ReadCompleteCB(pEventMbox,pTxn);
	}

	return TXN_STATUS_COMPLETE;
}
/*
 * \brief	Process the event
 *
 * \param  hEventMbox  - Handle to EventMbox
 * \param  pTxnStruct  - the Txn data
 * \return none
 *
 * \par Description
 * This function is called from the upon reading completion of the event MBOX
 * it will call all registered event according to the pending bits in event MBOX vector.
 * \sa
 */
static void eventMbox_ReadCompleteCB(TI_HANDLE hEventMbox, TTxnStruct *pTxnStruct)
{
	TI_UINT32	EvID;
	TTxnStruct*	pTxn;
	TEventMbox *pEventMbox = (TEventMbox *)hEventMbox;
	pTxn = &pEventMbox->iTxnGenRegSize.tTxnReg;

	pEventMbox->iTxnGenRegSize.iRegBuffer = INTR_TRIG_EVENT_ACK;

	for (EvID = 0; EvID < TWD_OWN_EVENT_ALL; EvID++) {
		if (pEventMbox->iTxnEventMbox.iEventMboxBuf.eventsVector & eventTable[EvID].bitMask) {
			if (eventTable[EvID].dataLen) {
				((TEventMboxDataCb)pEventMbox->CbTable[EvID].fCb)(pEventMbox->CbTable[EvID].hCb,(TI_CHAR*)pEventMbox->CbTable[EvID].pDataOffset,eventTable[EvID].dataLen);
			} else {
				((TEventMboxEvCb)pEventMbox->CbTable[EvID].fCb)(pEventMbox->CbTable[EvID].hCb);
			}
		}
	}

	/* Check if the state is changed in the context of the event callbacks */
	if (pEventMbox->CurrentState == EVENT_MBOX_STATE_IDLE) {
		/*
		 * When eventMbox_stop is called state is changed to IDLE
		 * This is done in the context of the above events callbacks
		 * Don't send the EVENT ACK transaction because the driver stop process includes power off
		 */
		TRACE0(pEventMbox->hReport, REPORT_SEVERITY_WARNING, "eventMbox_ReadCompleteCB : State is IDLE ! don't send the EVENT ACK");
		return;
	}

	pEventMbox->CurrentState = EVENT_MBOX_STATE_IDLE;

	/* Build the command TxnStruct */
	TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
	/* Applying a CB in case of an async read */
	BUILD_TTxnStruct(pTxn, ACX_REG_INTERRUPT_TRIG, &pEventMbox->iTxnGenRegSize.iRegBuffer, sizeof(pEventMbox->iTxnGenRegSize.iRegBuffer), NULL, NULL)
	twIf_Transact(pEventMbox->hTwif,pTxn);
}
Exemple #10
0
void twIf_SetPartition(TI_HANDLE hTwIf, TPartition * pPartition)
{
	TTwIfObj *pTwIf = (TTwIfObj *) hTwIf;
	TPartitionRegTxn *pPartitionRegTxn;	/* The partition transaction structure for one register */
	TTxnStruct *pTxnHdr;	/* The partition transaction header (as used in the TxnQ API) */
	ETxnStatus eStatus;
	int i;

	/* Save partition information for translation and validation. */
	pTwIf->uMemAddr1 = pPartition[0].uMemAdrr;
	pTwIf->uMemSize1 = pPartition[0].uMemSize;
	pTwIf->uMemAddr2 = pPartition[1].uMemAdrr;
	pTwIf->uMemSize2 = pPartition[1].uMemSize;
	pTwIf->uMemAddr3 = pPartition[2].uMemAdrr;
	pTwIf->uMemSize3 = pPartition[2].uMemSize;
	pTwIf->uMemAddr4 = pPartition[3].uMemAdrr;

	/* Allocate memory for the current 4 partition transactions */
	pPartitionRegTxn =
	    (TPartitionRegTxn *) os_memoryAlloc(pTwIf->hOs,
						7 * sizeof(TPartitionRegTxn));
	pTxnHdr = &(pPartitionRegTxn->tHdr);

	/* Zero the allocated memory to be certain that unused fields will be initialized */
	os_memoryZero(pTwIf->hOs, pPartitionRegTxn,
		      7 * sizeof(TPartitionRegTxn));

	/* Prepare partition transaction data */
	pPartitionRegTxn[0].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr1);
	pPartitionRegTxn[1].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemSize1);
	pPartitionRegTxn[2].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr2);
	pPartitionRegTxn[3].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemSize2);
	pPartitionRegTxn[4].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr3);
	pPartitionRegTxn[5].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemSize3);
	pPartitionRegTxn[6].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr4);

	/* Prepare partition Txn header */
	for (i = 0; i < 7; i++) {
		pTxnHdr = &(pPartitionRegTxn[i].tHdr);
		TXN_PARAM_SET(pTxnHdr, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN,
			      TXN_DIRECTION_WRITE, TXN_INC_ADDR)
		    TXN_PARAM_SET_MORE(pTxnHdr, 1);
		TXN_PARAM_SET_SINGLE_STEP(pTxnHdr, 0);
	}

	/* Memory address */
	pTxnHdr = &(pPartitionRegTxn[0].tHdr);
	BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 4,
			 &(pPartitionRegTxn[0].tData), REGISTER_SIZE, 0, 0)
	    twIf_SendTransaction(pTwIf, pTxnHdr);

	/* Memory size */
	pTxnHdr = &(pPartitionRegTxn[1].tHdr);
	BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 0,
			 &(pPartitionRegTxn[1].tData), REGISTER_SIZE, 0, 0)
	    twIf_SendTransaction(pTwIf, pTxnHdr);

	/* Registers address */
	pTxnHdr = &(pPartitionRegTxn[2].tHdr);
	BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 12,
			 &(pPartitionRegTxn[2].tData), REGISTER_SIZE, 0, 0)
	    twIf_SendTransaction(pTwIf, pTxnHdr);

	/* Registers size */
	pTxnHdr = &(pPartitionRegTxn[3].tHdr);
	BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 8,
			 &(pPartitionRegTxn[3].tData), REGISTER_SIZE, 0, 0)
	    eStatus = twIf_SendTransaction(pTwIf, pTxnHdr);

	/* Registers address */
	pTxnHdr = &(pPartitionRegTxn[4].tHdr);
	BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 20,
			 &(pPartitionRegTxn[4].tData), REGISTER_SIZE, 0, 0)
	    twIf_SendTransaction(pTwIf, pTxnHdr);

	/* Registers size */
	pTxnHdr = &(pPartitionRegTxn[5].tHdr);
	BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 16,
			 &(pPartitionRegTxn[5].tData), REGISTER_SIZE, 0, 0)
	    eStatus = twIf_SendTransaction(pTwIf, pTxnHdr);

	/* Registers address */
	pTxnHdr = &(pPartitionRegTxn[6].tHdr);
	BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 24,
			 &(pPartitionRegTxn[6].tData), REGISTER_SIZE,
			 twIf_PartitionTxnDoneCb, pTwIf)
	    twIf_SendTransaction(pTwIf, pTxnHdr);

	/* If the transaction is done, free the allocated memory (otherwise freed in the partition CB) */
	if (eStatus != TXN_STATUS_PENDING) {
		os_memoryFree(pTwIf->hOs, pPartitionRegTxn,
			      7 * sizeof(TPartitionRegTxn));
	}
}
Exemple #11
0
/** 
 * \fn     twIf_Init 
 * \brief  Init module 
 * 
 * - Init required handles and module variables
 * - Create the TxnDone-queue
 * - Register to TxnQ
 * - Register to context module
 * 
 * \note    
 * \param  hTwIf       - The module's object
 * \param  hXxx        - Handles to other modules
 * \param  fRecoveryCb - Callback function for recovery completed after TxnDone
 * \param  hRecoveryCb - Handle for fRecoveryCb
 * \return void        
 * \sa     
 */
void twIf_Init(TI_HANDLE hTwIf,
	       TI_HANDLE hReport,
	       TI_HANDLE hContext,
	       TI_HANDLE hTimer,
	       TI_HANDLE hTxnQ, TRecoveryCb fRecoveryCb, TI_HANDLE hRecoveryCb)
{
	TTwIfObj *pTwIf = (TTwIfObj *) hTwIf;
	TI_UINT32 uNodeHeaderOffset;
	TTxnStruct *pTxnHdr;	/* The ELP transactions header (as used in the TxnQ API) */

	pTwIf->hReport = hReport;
	pTwIf->hContext = hContext;
	pTwIf->hTimer = hTimer;
	pTwIf->hTxnQ = hTxnQ;
	pTwIf->fRecoveryCb = fRecoveryCb;
	pTwIf->hRecoveryCb = hRecoveryCb;

	/* Prepare ELP sleep transaction */
	pTwIf->tElpTxnSleep.uElpData = ELP_CTRL_REG_SLEEP;
	pTxnHdr = &(pTwIf->tElpTxnSleep.tHdr);
	TXN_PARAM_SET(pTxnHdr, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN,
		      TXN_DIRECTION_WRITE, TXN_INC_ADDR)
	    TXN_PARAM_SET_MORE(pTxnHdr, 0);	/* Sleep is the last transaction! */
	/* NOTE: Function id for single step will be replaced to 0 by the bus driver */
	TXN_PARAM_SET_SINGLE_STEP(pTxnHdr, 1);	/* ELP write is always single step (TxnQ is topped)! */
	BUILD_TTxnStruct(pTxnHdr, ELP_CTRL_REG_ADDR,
			 &(pTwIf->tElpTxnSleep.uElpData), sizeof(TI_UINT8),
			 NULL, NULL)

	    /* Prepare ELP awake transaction */
	    pTwIf->tElpTxnAwake.uElpData = ELP_CTRL_REG_AWAKE;
	pTxnHdr = &(pTwIf->tElpTxnAwake.tHdr);
	TXN_PARAM_SET(pTxnHdr, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN,
		      TXN_DIRECTION_WRITE, TXN_INC_ADDR)
	    TXN_PARAM_SET_MORE(pTxnHdr, 1);
	/* NOTE: Function id for single step will be replaced to 0 by the bus driver */
	TXN_PARAM_SET_SINGLE_STEP(pTxnHdr, 1);	/* ELP write is always single step (TxnQ is topped)! */
	BUILD_TTxnStruct(pTxnHdr, ELP_CTRL_REG_ADDR,
			 &(pTwIf->tElpTxnAwake.uElpData), sizeof(TI_UINT8),
			 NULL, NULL)

	    /* Create the TxnDone queue. */
	    uNodeHeaderOffset = TI_FIELD_OFFSET(TTxnStruct, tTxnQNode);
	pTwIf->hTxnDoneQueue =
	    que_Create(pTwIf->hOs, pTwIf->hReport, TXN_DONE_QUE_SIZE,
		       uNodeHeaderOffset);
	if (pTwIf->hTxnDoneQueue == NULL) {
		TRACE0(pTwIf->hReport, REPORT_SEVERITY_ERROR,
		       "twIf_Init: TxnDone queue creation failed!\n");
	}

	/* Register to the context engine and get the client ID */
	pTwIf->uContextId = context_RegisterClient(pTwIf->hContext,
						   twIf_HandleTxnDone,
						   hTwIf,
						   TI_TRUE,
						   "TWIF", sizeof("TWIF"));

	/* Allocate timer */
	pTwIf->hPendRestartTimer = tmr_CreateTimer(hTimer);
	if (pTwIf->hPendRestartTimer == NULL) {
		TRACE0(pTwIf->hReport, REPORT_SEVERITY_ERROR,
		       "twIf_Init: Failed to create PendRestartTimer!\n");
		return;
	}
	pTwIf->bPendRestartTimerRunning = TI_FALSE;

	/* Register to TxnQ */
	txnQ_Open(pTwIf->hTxnQ, TXN_FUNC_ID_WLAN, TXN_NUM_PRIORITYS,
		  (TTxnQueueDoneCb) twIf_TxnDoneCb, hTwIf);

	/* Restart TwIf and TxnQ modules */
	twIf_Restart(hTwIf);
}
/*
 * \brief	
 * 
 * \param  hFwDebug    - Handle to FW Debug
 * \param  pTxnNotUsed - Pointer to Transacton struct [Not used. Must be present due to CB compatibility]
 * \return none
 * 
 * \par Description
 * This function 
 * 
 * \sa 
 */
static void fwDbg_SdioValidationSM (TI_HANDLE hFwDebug, TTxnStruct* pTxnNotUsed)
{
    TFwDebug   *pFwDebug              = (TFwDebug*)hFwDebug;
    
    TI_UINT8   *pWriteBuf             = pFwDebug->pSdioTestWriteBuf;
    TI_UINT8   *pReadBuf              = pFwDebug->pSdioTestReadBuf;    
    TI_UINT32   uTxnSize              = pFwDebug->uSdioTestTxnSize;
    
    TTxnStruct *pTxn                  = NULL;           /* Used for write / read transactions */
    
    TI_STATUS   rc                    = TI_OK;
    TI_UINT32   uComparisonErrorCount = 0;              /* Counts the comparison errors per iteration */
    TI_UINT32   uBufIdx               = 0;



    while(1)
    {
        switch(pFwDebug->eSdioTestState)
        {

        case FWDEBUG_SDIO_TEST_STATE_WRITE_READ:

            /* Write Transaction - Write data to chip */
            
            pTxn = &pFwDebug->tSdioTestWriteTxnSt;

            TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
            BUILD_TTxnStruct(pTxn, TWD_SDIO_VALIDATION_TXN_ADDRESS, pWriteBuf, uTxnSize, NULL, pFwDebug)  /* No CB is needed here. We wait for the read operation to finish */
                
            rc = twIf_Transact(pFwDebug->hTwif, pTxn);
            
            if(rc == TXN_STATUS_ERROR)
            {
                WLAN_OS_REPORT(("fwDbg_SdioValidationSM() - Write SDIO transaction has failed! \n"));
                
                /* Free allocated buffers */
                os_memoryFree(pFwDebug->hOs, pWriteBuf, uTxnSize);
                os_memoryFree(pFwDebug->hOs, pReadBuf, uTxnSize);
                
                return;
            }
            
            
            /* Read Transaction - Read data from chip */
            
            pTxn = &pFwDebug->tSdioTestReadTxnSt;

            TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
            BUILD_TTxnStruct(pTxn, TWD_SDIO_VALIDATION_TXN_ADDRESS, pReadBuf, uTxnSize, (TTxnDoneCb)fwDbg_SdioValidationSM, pFwDebug)
                
            rc = twIf_Transact(pFwDebug->hTwif, pTxn);            
            
            if(rc == TXN_STATUS_ERROR)
            {
                WLAN_OS_REPORT(("fwDbg_SdioValidationSM() - Read SDIO transaction has failed! \n"));
                
                /* Free allocated buffers */
                os_memoryFree(pFwDebug->hOs, pWriteBuf, uTxnSize);
                os_memoryFree(pFwDebug->hOs, pReadBuf, uTxnSize);

                return;
            }
        
            /* Update state */
            pFwDebug->eSdioTestState = FWDEBUG_SDIO_TEST_STATE_COMPARE;

            /* Updating the loop number is dove only in FWDEBUG_SDIO_TEST_STATE_COMPARE */

            break;
        

        case FWDEBUG_SDIO_TEST_STATE_COMPARE:

            /* Compare read data to written data */
            for(uBufIdx = 0; uBufIdx < uTxnSize; uBufIdx++)
            {
                if(pWriteBuf[uBufIdx] != pReadBuf[uBufIdx])
                {
                    uComparisonErrorCount++;
                }
            }

            /* Print error message in case of comparison error */
            if(uComparisonErrorCount)
            {
                WLAN_OS_REPORT((" fwDbg_SdioValidationSM() - Found %d errors in iteration %d. \n", 
                    uComparisonErrorCount, pFwDebug->uSdioTestCurrentLoopNum));

                /* Reset uComparisonErrorCount for next iterations, and set bSdioTestPassed to mark test as failed */
                uComparisonErrorCount     = 0;
                pFwDebug->bSdioTestPassed = TI_FALSE;
            }


            /* Update loop number and state */
            pFwDebug->uSdioTestCurrentLoopNum++;
            pFwDebug->eSdioTestState = FWDEBUG_SDIO_TEST_STATE_WRITE_READ; 


            /* If this is the last loop free allocated memory and return */
            if(pFwDebug->uSdioTestCurrentLoopNum == pFwDebug->uSdioTestNumOfLoops)
            {
                if(pFwDebug->bSdioTestPassed)
                {
                    WLAN_OS_REPORT(("----- SDIO Validation Test Completed ----> Passed. \n\n"));
                }
                else
                {
                    WLAN_OS_REPORT(("----- SDIO Validation Test Completed ----> Failed. \n\n"));
                }

                /* Free allocated buffers */
                os_memoryFree(pFwDebug->hOs, pWriteBuf, uTxnSize);
                os_memoryFree(pFwDebug->hOs, pReadBuf, uTxnSize);

                return;
            }


            break;
        

        default:

            WLAN_OS_REPORT(("fwDbg_SdioValidationSM() - eSdioTestState is invalid (%d) !! \n", pFwDebug->eSdioTestState));

            /* Free allocated buffers */
            os_memoryFree(pFwDebug->hOs, pWriteBuf, uTxnSize);
            os_memoryFree(pFwDebug->hOs, pReadBuf, uTxnSize);

            return;

        }   /* Switch */


        /* If the transactionis still pending - return. 
           fwDbg_SdioValidationSM() will be called after transaction completion (since it is supplied as the CB function), 
        */
        if(rc == TXN_STATUS_PENDING)
        {
            return;
        }

    }   /* While loop */
}
/*
 * \brief	This function is validating the SDIO lines by write / read / compare operations.
 * 
 * \param  hFwDebug    - Handle to FW Debug.
 * \param  uNumOfLoops - Number of times to run the validation test.
 * \param  uTxnSize    - Size of the transaction (in bytes) to use in the validation test.
 *
 * \return TI_STATUS
 * 
 * \par Description
 * This function is validating the SDIO lines by writing data to the chip
 * memory, and then reading it and compares it to the written data.
 * The following steps are taken:
 *  1. Disables ELP so the chip won't go to sleep.
 *  2. Disables all interrupts - This is done to disable Watchdog so no recovery will be done on the driver side.
 *  3. Halts the coretex.
 *  4. Make the read / write / compare - Most of this part is done by calling fwDbg_SdioValidationSM().
 * 
 * \sa 
 */
TI_STATUS fwDbg_ValidateSdio(TI_HANDLE hFwDebug, TI_UINT32 uNumOfLoops, TI_UINT32 uTxnSize)
{
    TFwDebug   *pFwDebug       = (TFwDebug *)hFwDebug;

    TI_UINT8    aDataBuffer[8] = { 'B', 'E', 'E', 'F', '4' ,'4' ,'7' ,'8' };  /* Constant data to fill in write buffer */
    TI_UINT32   uWriteBufIdx   = 0;                                           /* Index in write buffer - used to fill data inside */
    
    TTxnStruct *pTxn           = &pFwDebug->tTxn;




    WLAN_OS_REPORT(("----- SDIO Validation Test ----> Started [Performing %d iterations of %d bytes in transaction]. \n\n",
        uNumOfLoops, uTxnSize));



    /* Parameter range check - Make sure uTxnSize is in range */
    if( (uTxnSize == 0) || (uTxnSize > TWD_SDIO_VALIDATION_TXN_SIZE_MAX) )
    {
        WLAN_OS_REPORT(("fwDbg_ValidateSdio() - uTxnSize (%d) is out of range. Set to %d. \n", 
            uTxnSize, TWD_SDIO_VALIDATION_TXN_SIZE_DEFAULT));

        uTxnSize = TWD_SDIO_VALIDATION_TXN_SIZE_DEFAULT;
    }

    /* Parameter range check - Make sure uNumOfLoops is in range */
    if(uNumOfLoops > TWD_SDIO_VALIDATION_NUM_LOOPS_MAX)
    {
        WLAN_OS_REPORT(("fwDbg_ValidateSdio() - uNumOfLoops (%d) is out of range. Set to %d. \n", 
            uNumOfLoops, TWD_SDIO_VALIDATION_NUM_LOOPS_DEFAULT));
        
        uNumOfLoops = TWD_SDIO_VALIDATION_NUM_LOOPS_DEFAULT;
    }


    /* 
       1. Disable ELP:
          ------------
          - Call twIf_Awake() - it is not enough for disabling the ELP.
          - Only after the next transaction, it is promised that the chip will be awake (ELP disabled)
    */

    twIf_Awake(pFwDebug->hTwif);


    /* 2. Disable all interrupts */
    /*    ---------------------- */
    
    fwEvent_MaskAllFwInterrupts(pFwDebug->hFwEvent);


    /* 3. Halt Coretex */
    /*    ------------ */

    pFwDebug->uSdioTestZero = 0;

    TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
    BUILD_TTxnStruct(pTxn, ACX_REG_ECPU_CONTROL, &(pFwDebug->uSdioTestZero), REGISTER_SIZE, NULL, pFwDebug)
    
    twIf_Transact(pFwDebug->hTwif, pTxn);


    /* 4. Make the read / write / compare */
    /*    ------------------------------- */


    /* Allocate memory for pFwDebug->pSdioTestWriteBuf */
    pFwDebug->pSdioTestWriteBuf = (TI_UINT8 *)os_memoryAlloc(pFwDebug->hOs, uTxnSize);


    /* Assert Allocation */
    if(NULL == pFwDebug->pSdioTestWriteBuf)
    {
        WLAN_OS_REPORT(("fwDbg_ValidateSdio() - Allocation for write buffer failed! \n"));
    
        return TI_NOK;
    }


    /* Allocate memory for pFwDebug->pSdioTestReadBuf */
    pFwDebug->pSdioTestReadBuf = (TI_UINT8 *)os_memoryAlloc(pFwDebug->hOs, uTxnSize);

    /* Assert Allocation */
    if(NULL == pFwDebug->pSdioTestReadBuf)
    {
        WLAN_OS_REPORT(("fwDbg_ValidateSdio() - Allocation for read buffer failed! \n"));

        /* Free pre-allocated pFwDebug->pSdioTestWriteBuf */
        os_memoryFree(pFwDebug->hOs, pFwDebug->pSdioTestWriteBuf, uTxnSize);

        return TI_NOK;
    }

    /* Set pFwDebug struct fields */
    pFwDebug->uSdioTestTxnSize        = uTxnSize;
    pFwDebug->uSdioTestNumOfLoops     = uNumOfLoops;
    pFwDebug->uSdioTestCurrentLoopNum = 0;
    pFwDebug->eSdioTestState          = FWDEBUG_SDIO_TEST_STATE_WRITE_READ;
    pFwDebug->bSdioTestPassed         = TI_TRUE;



    /* Fill data in pFwDebug->pSdioTestWriteBuf */
    for(uWriteBufIdx = 0; uWriteBufIdx < uTxnSize; uWriteBufIdx++)
    {
        pFwDebug->pSdioTestWriteBuf[uWriteBufIdx] = aDataBuffer[uWriteBufIdx % sizeof(aDataBuffer)];
    }

    /* Call the SM function to perform the Read / Write / Compare test */
    fwDbg_SdioValidationSM(hFwDebug, NULL);


    return TI_OK;
}