/** * \fn busDrv_PrepareTxnParts * \brief Prepare write or read transaction parts * * Called by busDrv_Transact(). * Prepares the actual sequence of SDIO bus transactions in a table. * Use a DMA-able buffer for the bus transaction, so all data is copied * to it from the host buffer(s) before write transactions, * or copied from it to the host buffers after read transactions. * * \note * \param pBusDrv - The module's object * \param pTxn - The transaction object * \return TRUE if we are in the middle of a Tx aggregation * \sa busDrv_Transact, busDrv_SendTxnParts, */ static TI_BOOL busDrv_PrepareTxnParts (TBusDrvObj *pBusDrv, TTxnStruct *pTxn) { TI_UINT32 uPartNum = 0; TI_UINT32 uCurrHwAddr = pTxn->uHwAddr; TI_BOOL bFixedHwAddr = TXN_PARAM_GET_FIXED_ADDR(pTxn); TI_BOOL bWrite = (TXN_PARAM_GET_DIRECTION(pTxn) == TXN_DIRECTION_WRITE) ? TI_TRUE : TI_FALSE; TI_UINT8 *pHostBuf = bWrite ? pBusDrv->pTxDmaBuf : pBusDrv->pRxDmaBuf; /* Use DMA buffer (Rx or Tx) for actual transaction */ TI_UINT32 uBufNum; TI_UINT32 uBufLen; TI_UINT32 uRemainderLen; /* Go over the transaction buffers */ for (uBufNum = 0; uBufNum < MAX_XFER_BUFS; uBufNum++) { uBufLen = pTxn->aLen[uBufNum]; /* If no more buffers, exit the loop */ if (uBufLen == 0) { break; } /* For write transaction, copy the data to the DMA buffer */ if (bWrite) { os_memoryCopy (pBusDrv->hOs, pHostBuf + pBusDrv->uTxnLength, pTxn->aBuf[uBufNum], uBufLen); } /* Add buffer length to total transaction length */ pBusDrv->uTxnLength += uBufLen; } /* If in a Tx aggregation, return TRUE (need to accumulate all parts before sending the transaction) */ if (TXN_PARAM_GET_AGGREGATE(pTxn) == TXN_AGGREGATE_ON) { TRACE6(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_PrepareTxnParts: In aggregation so exit, uTxnLength=%d, bWrite=%d, Len0=%d, Len1=%d, Len2=%d, Len3=%d\n", pBusDrv->uTxnLength, bWrite, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3]); return TI_TRUE; } /* If current buffer has a remainder, prepare its transaction part */ uRemainderLen = pBusDrv->uTxnLength & pBusDrv->uBlkSizeMask; if (uRemainderLen > 0) { pBusDrv->aTxnParts[uPartNum].bBlkMode = TI_FALSE; pBusDrv->aTxnParts[uPartNum].uLength = uRemainderLen; pBusDrv->aTxnParts[uPartNum].uHwAddr = uCurrHwAddr; pBusDrv->aTxnParts[uPartNum].pHostAddr = (void *)pHostBuf; pBusDrv->aTxnParts[uPartNum].bMore = TI_TRUE; /* If not fixed HW address, increment it by this part's size */ if (!bFixedHwAddr) { uCurrHwAddr += uRemainderLen; } uPartNum++; } #ifdef DISABLE_SDIO_MULTI_BLK_MODE /* SDIO multi-block mode is disabled so split to 512 bytes blocks */ { TI_UINT32 uLen; for (uLen = uRemainderLen; uLen < pBusDrv->uTxnLength; uLen += pBusDrv->uBlkSize) { pBusDrv->aTxnParts[uPartNum].bBlkMode = TI_FALSE; pBusDrv->aTxnParts[uPartNum].uLength = pBusDrv->uBlkSize; pBusDrv->aTxnParts[uPartNum].uHwAddr = uCurrHwAddr; pBusDrv->aTxnParts[uPartNum].pHostAddr = (void *)(pHostBuf + uLen); pBusDrv->aTxnParts[uPartNum].bMore = TI_TRUE; /* If not fixed HW address, increment it by this part's size */ if (!bFixedHwAddr) { uCurrHwAddr += pBusDrv->uBlkSize; } uPartNum++; } } #else /* Use SDIO block mode (this is the default behavior) */ /* If current buffer has full SDIO blocks, prepare a block-mode transaction part */ if (pBusDrv->uTxnLength >= pBusDrv->uBlkSize) { pBusDrv->aTxnParts[uPartNum].bBlkMode = TI_TRUE; pBusDrv->aTxnParts[uPartNum].uLength = pBusDrv->uTxnLength - uRemainderLen; pBusDrv->aTxnParts[uPartNum].uHwAddr = uCurrHwAddr; pBusDrv->aTxnParts[uPartNum].pHostAddr = (void *)(pHostBuf + uRemainderLen); pBusDrv->aTxnParts[uPartNum].bMore = TI_TRUE; uPartNum++; } #endif /* DISABLE_SDIO_MULTI_BLK_MODE */ /* Set last More flag as specified for the whole Txn */ pBusDrv->aTxnParts[uPartNum - 1].bMore = TXN_PARAM_GET_MORE(pTxn); pBusDrv->uCurrTxnPartsNum = uPartNum; TRACE9(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_PrepareTxnParts: Txn prepared, PartsNum=%d, bWrite=%d, uTxnLength=%d, uRemainderLen=%d, uHwAddr=0x%x, Len0=%d, Len1=%d, Len2=%d, Len3=%d\n", uPartNum, bWrite, pBusDrv->uTxnLength, uRemainderLen, pTxn->uHwAddr, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3]); pBusDrv->uTxnLength = 0; /* Return FALSE to indicate that we are not in the middle of a Tx aggregation so the Txn is ready to send */ return TI_FALSE; }
/************************************************************************ * findAndInsertSiteEntry * ************************************************************************ DESCRIPTION: Perform the following things: - Compute the site's hash entry based on the site BSSID and hash function - Look for the site entry in the linked list pointed by the hash entry - If the site is found in the site table, returns a pointer to the site entry - If the site is not found in the site table, tries to add the site - If succeeds, returns a pointer to the site entry - Otherwise, returns NULL INPUT: pSiteMgr - Handle to site mgr mac - The site BSSID band - The site band OUTPUT: RETURN: Pointer to the site entry if site found/inserted, NULL otherwise ************************************************************************/ siteEntry_t *findAndInsertSiteEntry(siteMgr_t *pSiteMgr, TMacAddr *mac, ERadioBand band) { TI_UINT8 i, emptySiteIndex=0, nextSite2Remove=0; siteEntry_t *pSiteEntry, *pPrimarySite=pSiteMgr->pSitesMgmtParams->pPrimarySite; sitesMgmtParams_t *pSitesMgmtParams = pSiteMgr->pSitesMgmtParams; siteTablesParams_t *pCurrentSiteTable; TI_BOOL firstEmptySiteFound = TI_FALSE; TI_UINT32 oldestTS; /* choose site table according to AP's band */ if ( RADIO_BAND_2_4_GHZ == band ) { pCurrentSiteTable = &(pSitesMgmtParams->dot11BG_sitesTables); } else if (RADIO_BAND_5_0_GHZ == band) { pCurrentSiteTable = (siteTablesParams_t*) &(pSitesMgmtParams->dot11A_sitesTables); } else { TRACE1(pSiteMgr->hReport, REPORT_SEVERITY_ERROR, "Bad band: %d\n\n", band); pCurrentSiteTable = &(pSitesMgmtParams->dot11BG_sitesTables); } /* Set the first TS to a site which is not the Primary site */ if (pPrimarySite != &(pCurrentSiteTable->siteTable[0])) { oldestTS = pCurrentSiteTable->siteTable[0].localTimeStamp; } else { oldestTS = pCurrentSiteTable->siteTable[1].localTimeStamp; } /* It looks like it never happens. Anyway decided to check */ if ( pCurrentSiteTable->maxNumOfSites > MAX_SITES_BG_BAND ) { TRACE2( pSiteMgr->hReport, REPORT_SEVERITY_ERROR, "findAndInsertSiteEntry. pCurrentSiteTable->maxNumOfSites=%d exceeds the limit %d\n", pCurrentSiteTable->maxNumOfSites, MAX_SITES_BG_BAND); handleRunProblem(PROBLEM_BUF_SIZE_VIOLATION); return NULL; } /* Loop all the sites till the desired MAC is found */ for (i = 0; i < pCurrentSiteTable->maxNumOfSites; i++) { pSiteEntry = &(pCurrentSiteTable->siteTable[i]); if (MAC_EQUAL (pSiteEntry->bssid, *mac)) { TRACE6(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "FIND success, bssid: %X-%X-%X-%X-%X-%X\n\n", (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5]); return pSiteEntry; } else if (pSiteEntry->siteType == SITE_NULL) { /* Save the first empty site, in case the desired MAC is not found */ if (!firstEmptySiteFound) { emptySiteIndex = i; firstEmptySiteFound=TI_TRUE; } } else if (oldestTS == pSiteEntry->localTimeStamp) { /* Save the oldest site's index, according to TS */ nextSite2Remove = i; } } TRACE4(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "INSERT failure, no free entry!, oldestTS=%d, nextSite2Remove=%d, " "[0].localTimeStamp=%d, [1]localTimeStamp%d \n", oldestTS, nextSite2Remove, pCurrentSiteTable->siteTable[0].localTimeStamp, pCurrentSiteTable->siteTable[1].localTimeStamp); if ((!firstEmptySiteFound) || (pCurrentSiteTable->numOfSites>=pCurrentSiteTable->maxNumOfSites)) { /* No NULL entry has been found. Remove the oldest site */ pSiteEntry = &(pCurrentSiteTable->siteTable[nextSite2Remove]); TRACE9(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "INSERT failure, no free entry!, numOfSites=%d, removing site index=%d,\n bssid: %X-%X-%X-%X-%X-%X, ts=%d \n", pCurrentSiteTable->numOfSites, nextSite2Remove, pSiteEntry->bssid[0], pSiteEntry->bssid[1], pSiteEntry->bssid[2], pSiteEntry->bssid[3], pSiteEntry->bssid[4], pSiteEntry->bssid[5], pSiteEntry->localTimeStamp); removeSiteEntry(pSiteMgr, pCurrentSiteTable, pSiteEntry); emptySiteIndex = nextSite2Remove; } pCurrentSiteTable->numOfSites++; pSiteEntry = &(pCurrentSiteTable->siteTable[emptySiteIndex]); /* fill the entry with the station mac */ MAC_COPY (pSiteEntry->bssid, *mac); /* Some parameters have to be initialized immediately after entry allocation */ if(pSiteMgr->siteMgrOperationalMode == DOT11_G_MODE) pSiteEntry->currentSlotTime = pSiteMgr->pDesiredParams->siteMgrDesiredSlotTime; TRACE8(pSiteMgr->hReport, REPORT_SEVERITY_INFORMATION, "INSERT success, bssid: %X-%X-%X-%X-%X-%X, band=%d, index=%d\n\n", (*mac)[0], (*mac)[1], (*mac)[2], (*mac)[3], (*mac)[4], (*mac)[5], band, emptySiteIndex); return pSiteEntry; }