ETxnStatus sdioAdapt_Transact (unsigned int uFuncId, unsigned int uHwAddr, void * pHostAddr, unsigned int uLength, unsigned int bDirection, unsigned int bBlkMode, unsigned int bFixedAddr, unsigned int bMore) { int iStatus,i; if (bDirection) { /* Read */ iStatus = sdioDrv_ReadSync (uFuncId, uHwAddr, pHostAddr, uLength, bBlkMode, bFixedAddr, bMore); if (iStatus) { return TXN_STATUS_ERROR; } return TXN_STATUS_COMPLETE; } else { /* Write */ if (use52) { // printk("use 52\n");jj = 0; for (i = 0; i < uLength ; ++i) { // printk("uHwAddr = 0x%x *pHostValue = 0x%x\n",uHwAddr,(unsigned char)(*((unsigned char*)pHostAddr))); sdioAdapt_TransactBytes(uFuncId,uHwAddr,pHostAddr,1,bDirection,bMore); uHwAddr += 1; pHostAddr = (void *)((unsigned int)pHostAddr+1); } return TXN_STATUS_COMPLETE; } else { iStatus = sdioDrv_WriteSync (uFuncId, uHwAddr, pHostAddr, uLength, bBlkMode, bFixedAddr, bMore); } if (iStatus) { return TXN_STATUS_ERROR; } return TXN_STATUS_COMPLETE; } }
/** * \fn busDrv_SendTxnParts * \brief Send prepared transaction parts * * Called first by busDrv_Transact(), and also from TxnDone CB after Async completion. * Sends the prepared transaction parts in a loop. * If a transaction part is Async, the loop continues later in the TxnDone ISR context. * When all parts are done, the upper layer TxnDone CB is called. * * \note * \param pBusDrv - The module's object * \return void * \sa busDrv_Transact, busDrv_PrepareTxnParts */ static void busDrv_SendTxnParts (TBusDrvObj *pBusDrv) { ETxnStatus eStatus; TTxnPart *pTxnPart; TTxnStruct *pTxn = pBusDrv->pCurrTxn; /* While there are transaction parts to send */ while (pBusDrv->uCurrTxnPartsCount < pBusDrv->uCurrTxnPartsNum) { pTxnPart = &(pBusDrv->aTxnParts[pBusDrv->uCurrTxnPartsCount]); pBusDrv->uCurrTxnPartsCount++; /* Assume pending to be ready in case we are preempted by the TxnDon CB !! */ pBusDrv->eCurrTxnStatus = TXN_STATUS_PENDING; /* If single step, send ELP byte */ if (TXN_PARAM_GET_SINGLE_STEP(pTxn)) { /* Overwrite the function id with function 0 - for ELP register !!!! */ eStatus = sdioAdapt_TransactBytes (TXN_FUNC_ID_CTRL, pTxnPart->uHwAddr, pTxnPart->pHostAddr, pTxnPart->uLength, TXN_PARAM_GET_DIRECTION(pTxn), pTxnPart->bMore); /* If first write failed try once again (may happen once upon chip wakeup) */ if (eStatus == TXN_STATUS_ERROR) { /* Overwrite the function id with function 0 - for ELP register !!!! */ eStatus = sdioAdapt_TransactBytes (TXN_FUNC_ID_CTRL, pTxnPart->uHwAddr, pTxnPart->pHostAddr, pTxnPart->uLength, TXN_PARAM_GET_DIRECTION(pTxn), pTxnPart->bMore); TRACE0(pBusDrv->hReport, REPORT_SEVERITY_WARNING, "busDrv_SendTxnParts: SDIO Single-Step transaction failed once so try again"); } } else { eStatus = sdioAdapt_Transact (TXN_PARAM_GET_FUNC_ID(pTxn), pTxnPart->uHwAddr, pTxnPart->pHostAddr, pTxnPart->uLength, TXN_PARAM_GET_DIRECTION(pTxn), pTxnPart->bBlkMode, ((TXN_PARAM_GET_FIXED_ADDR(pTxn) == 1) ? 0 : 1), pTxnPart->bMore); } TRACE7(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_SendTxnParts: PartNum = %d, SingleStep = %d, Direction = %d, HwAddr = 0x%x, HostAddr = 0x%x, Length = %d, BlkMode = %d\n", pBusDrv->uCurrTxnPartsCount-1, TXN_PARAM_GET_SINGLE_STEP(pTxn), TXN_PARAM_GET_DIRECTION(pTxn), pTxnPart->uHwAddr, pTxnPart->pHostAddr, pTxnPart->uLength, pTxnPart->bBlkMode); /* If pending TxnDone (Async), continue this loop in the next TxnDone interrupt */ if (eStatus == TXN_STATUS_PENDING) { return; } /* Update current transaction status to deduce if it is all finished in the original context (Sync) or not. */ pBusDrv->eCurrTxnStatus = eStatus; pBusDrv->uCurrTxnPartsCountSync++; /* If error, set error in Txn struct, call TxnDone CB if not fully sync, and exit */ if (eStatus == TXN_STATUS_ERROR) { TXN_PARAM_SET_STATUS(pTxn, TXN_PARAM_STATUS_ERROR); if (pBusDrv->uCurrTxnPartsCountSync != pBusDrv->uCurrTxnPartsCount) { pBusDrv->fTxnDoneCb (pBusDrv->hCbHandle, pTxn); } return; } } /* If we got here we sent all buffers and we don't pend transaction end */ TRACE3(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_SendTxnParts: Txn finished successfully, Status = %d, PartsCount = %d, SyncCount = %d\n", pBusDrv->eCurrTxnStatus, pBusDrv->uCurrTxnPartsCount, pBusDrv->uCurrTxnPartsCountSync); /* For read transaction, copy the data from the DMA-able buffer to the host buffer(s) */ if (TXN_PARAM_GET_DIRECTION(pTxn) == TXN_DIRECTION_READ) { TI_UINT32 uBufNum; TI_UINT32 uBufLen; TI_UINT8 *pDmaBuf = pBusDrv->pRxDmaBuf; /* After the read transaction the data is in the Rx DMA buffer */ for (uBufNum = 0; uBufNum < MAX_XFER_BUFS; uBufNum++) { uBufLen = pTxn->aLen[uBufNum]; /* If no more buffers, exit the loop */ if (uBufLen == 0) { break; } os_memoryCopy (pBusDrv->hOs, pTxn->aBuf[uBufNum], pDmaBuf, uBufLen); pDmaBuf += uBufLen; } } /* If not fully sync, call TxnDone CB */ if (pBusDrv->uCurrTxnPartsCountSync != pBusDrv->uCurrTxnPartsCount) { pBusDrv->fTxnDoneCb (pBusDrv->hCbHandle, pTxn); } }