📄 artear.c
字号:
if (EarDebugLevel >= EAR_DEBUG_EXTREME) {
printf("ar5212EarAllocate: reg data %2d memory location 0x%08X\n", i, (A_UINT32)currentAlloc);
}
pRH = &((*ppEarHead)->pRH[i]);
pRH->regs = currentAlloc;
currentAlloc += earAlloc->locsPerRH[i];
}
return TRUE;
}
void
ar5212EarFree(EAR_HEADER *pEarHead)
{
if(pEarHead == NULL) {
//already free
return;
}
if(pEarHead->pRH) {
free(pEarHead->pRH);
pEarHead->pRH = NULL;
}
free(pEarHead);
pEarHead = NULL;
return;
}
/**************************************************************************
* ar5212EarCheckAndFill
*
* Save away EAR contents
*/
static A_BOOL
ar5212EarCheckAndFill(EAR_HEADER *earHead, A_UINT32 *in, int totalLocs, EAR_ALLOC *pEarAlloc)
{
int curEarLoc = 0, currentRH = 0, regLoc, i;
A_UINT16 regHead, tag, last, currentVerMask, addr, num, numBits, startBit;
REGISTER_HEADER *pRH, tempRH;
A_UINT16 tempRHregs[EAR_MAX_RH_REGS], *pReg16;
A_BOOL verMaskUsed, verMaskMatch;
/* Setup the temporary register header */
/* Save the version Id */
earHead->versionId = (A_UINT16)in[curEarLoc++];
/* Save the first version mask */
verMaskUsed = 0;
verMaskMatch = IS_EAR_VMATCH(earHead->versionId, in[curEarLoc]);
currentVerMask = (A_UINT16)in[curEarLoc++];
if (!IS_VER_MASK(currentVerMask)) {
printf("ar5212EarCheckAndFill: ERROR: First entry after Version ID is not a Version Mask\n");
return FALSE;
}
while (curEarLoc < totalLocs) {
/* Parse Version/Header/End */
if (IS_VER_MASK(in[curEarLoc])) {
if (!verMaskUsed) {
printf("ar5212EarCheckAndFill: ERROR: Multiple version masks setup with no register headers location %d\n",
curEarLoc);
return FALSE;
}
verMaskUsed = 0;
verMaskMatch = IS_EAR_VMATCH(earHead->versionId, in[curEarLoc]);
currentVerMask = (A_UINT16)in[curEarLoc++];
} else if (IS_END_HEADER(in[curEarLoc])) {
printf("ar5212EarCheckAndFill: ERROR: Somehow we've hit the END location but parse shouldn't let us get here. loc %d\n",
curEarLoc);
return FALSE;
} else {
if (currentRH > earHead->numRHs) {
printf("ar5212EarCheckAndFill: ERROR: Exceeded number of register headers found in preParse. loc %d\n",
curEarLoc);
return FALSE;
}
memset(&tempRH, 0, sizeof(REGISTER_HEADER));
memset(&tempRHregs, 0, sizeof(A_UINT16) * EAR_MAX_RH_REGS);
tempRH.regs = tempRHregs;
pRH = &tempRH;
/* Must be a register header - save last version mask */
pRH->versionMask = currentVerMask;
regHead = (A_UINT16)in[curEarLoc++];
pRH->modes = (A_UINT16)(regHead & RH_MODES_M);
if ((pRH->modes != RH_ALL_MODES) && (pRH->modes & RH_RESERVED_MODES)) {
printf("ar5212EarCheckAndFill: WARNING: Detected that reserved modes have been set. loc %d\n", curEarLoc);
}
pRH->type = (A_UINT16)((regHead & RH_TYPE_M) >> RH_TYPE_S);
pRH->stage = (A_UINT16)((regHead & RH_STAGE_M) >> RH_STAGE_S);
if (IS_CM_SET(regHead)) {
pRH->channel = (A_UINT16)in[curEarLoc++];
if (IS_CM_SINGLE(pRH->channel) && !IS_5GHZ_CHAN(pRH->channel) &&
!IS_2GHZ_CHAN(pRH->channel))
{
printf("ar5212EarCheckAndFill: WARNING: Specified single channel %d is not within tunable range. loc %d\n",
pRH->channel & CM_SINGLE_CHAN_M, curEarLoc);
}
}
if (IS_DISABLER_SET(regHead)) {
pRH->disabler.valid = TRUE;
pRH->disabler.disableField = (A_UINT16)in[curEarLoc++];
if (IS_PLL_SET(pRH->disabler.disableField)) {
pRH->disabler.pllValue = (A_UINT16)in[curEarLoc++];
if (pRH->disabler.pllValue & RH_RESERVED_PLL_BITS) {
printf("ar5212EarCheckAndFill: WARNING: Detected that reserved pll bits have been set. loc %d\n", curEarLoc);
}
}
}
/* Now into the actual register writes */
regLoc = 0;
switch (pRH->type) {
case EAR_TYPE0:
do {
pRH->regs[regLoc] = (A_UINT16)in[curEarLoc++];
tag = (A_UINT16)(pRH->regs[regLoc] & T0_TAG_M);
if (!IS_VALID_ADDR(pRH->regs[regLoc] & ~T0_TAG_M)) {
printf("ar5212EarCheckAndFill: WARNING: Detected invalid register address 0x%04X at loc %d\n",
pRH->regs[regLoc] & ~T0_TAG_M, curEarLoc);
}
regLoc++;
if ((tag == T0_TAG_32BIT) || (tag == T0_TAG_32BIT_LAST)) {
/* Full word writes */
pRH->regs[regLoc++] = (A_UINT16)in[curEarLoc++];
pRH->regs[regLoc++] = (A_UINT16)in[curEarLoc++];
} else {
/* Half word writes */
pRH->regs[regLoc++] = (A_UINT16)in[curEarLoc++];
}
} while ((tag != T0_TAG_32BIT_LAST) && (curEarLoc < totalLocs));
break;
case EAR_TYPE1:
pRH->regs[regLoc] = (A_UINT16)in[curEarLoc++];
addr = (A_UINT16)(pRH->regs[regLoc] & ~T1_NUM_M);
num = (A_UINT16)(pRH->regs[regLoc] & T1_NUM_M);
regLoc++;
for (i = 0; i < num + 1; i++) {
/* Full word writes */
if (!IS_VALID_ADDR(addr + (sizeof(A_UINT32) * i))) {
printf("ar5212EarCheckAndFill: WARNING: Detected invalid register address 0x%04X at loc %d\n",
addr + (sizeof(A_UINT32) * i), curEarLoc);
}
pRH->regs[regLoc++] = (A_UINT16)in[curEarLoc++];
pRH->regs[regLoc++] = (A_UINT16)in[curEarLoc++];
}
break;
case EAR_TYPE2:
do {
pRH->regs[regLoc] = (A_UINT16)in[curEarLoc++];
last = (A_UINT16)(IS_TYPE2_LAST(pRH->regs[regLoc]));
if (((pRH->regs[regLoc] & T2_BANK_M) >> T2_BANK_S) == 0) {
printf("ar5212EarCheckAndFill: WARNING: Bank 0 update found in Type2 write at loc %d\n", curEarLoc);
}
startBit = (A_UINT16)(pRH->regs[regLoc] & T2_START_M);
if (IS_TYPE2_EXTENDED(pRH->regs[regLoc])) {
regLoc++;
pRH->regs[regLoc] = (A_UINT16)in[curEarLoc++];
if (pRH->regs[regLoc] < 12) {
printf("ar5212EarCheckAndFill: WARNING: Type2 Extended Write used when number of bits is under 12 at loc %d\n",
curEarLoc);
}
num = (A_UINT16)(A_DIV_UP(pRH->regs[regLoc], 16));
numBits = pRH->regs[regLoc];
if (startBit + numBits > MAX_ANALOG_START) {
printf("ar5212EarCheckAndFill: ERROR: Type2 write will exceed analog buffer limits (at loc %d)\n", curEarLoc);
return FALSE;
}
regLoc++;
for (i = 0; i < num; i++) {
/* Add check data exceeds num bits check? */
pRH->regs[regLoc++] = (A_UINT16)in[curEarLoc++];
}
if (~((1 << (numBits % 16)) - 1) & in[curEarLoc - 1]) {
printf("ar5212EarCheckAndFill: WARNING: Type2 extended Write data exceeds number of bits specified at loc %d\n",
curEarLoc);
}
} else {
regLoc++;
pRH->regs[regLoc] = (A_UINT16)in[curEarLoc++];
numBits = (A_UINT16)((pRH->regs[regLoc] & T2_NUMB_M) >> T2_NUMB_S);
if (startBit + numBits > MAX_ANALOG_START) {
printf("ar5212EarCheckAndFill: ERROR: Type2 write will exceed analog buffer limits (at loc %d)\n", curEarLoc);
return FALSE;
}
if (~((1 << numBits) - 1) &
(pRH->regs[regLoc] & T2_DATA_M))
{
printf("ar5212EarCheckAndFill: WARNING: Type2 Write data exceeds number of bits specified at loc %d\n",
curEarLoc);
}
regLoc++;
}
} while (!last && (curEarLoc < totalLocs));
break;
case EAR_TYPE3:
do {
pRH->regs[regLoc] = (A_UINT16)in[curEarLoc++];
last = (A_UINT16)(IS_TYPE3_LAST(pRH->regs[regLoc]));
num = (A_UINT16)(A_DIV_UP((pRH->regs[regLoc] & T3_NUMB_M), 16));
if (((pRH->regs[regLoc] & T3_START_M) >> T3_START_S) +
(pRH->regs[regLoc] & T3_NUMB_M) > 31)
{
printf("ar5212EarCheckAndFill: WARNING: Type4 StartBit plus Number of Bits > 31 at loc %d\n",
curEarLoc);
}
if (((pRH->regs[regLoc] & T3_OPCODE_M) >> T3_OPCODE_S) > T3_MAX_OPCODE) {
printf("ar5212EarCheckAndFill: WARNING: Type4 OpCode exceeds largest selectable opcode at loc %d\n",
curEarLoc);
}
if (pRH->regs[regLoc] & T3_RESERVED_BITS) {
printf("ar5212EarCheckAndFill: WARNING: Type4 Reserved bits used at loc %d\n",
curEarLoc);
}
numBits = (A_UINT16)(pRH->regs[regLoc] & T3_NUMB_M);
regLoc++;
/* Grab Address */
pRH->regs[regLoc] = (A_UINT16)in[curEarLoc++];
if (!IS_VALID_ADDR(pRH->regs[regLoc])) {
printf("ar5212EarCheckAndFill: WARNING: Detected invalid register address 0x%04X at loc %d\n",
pRH->regs[regLoc], curEarLoc);
}
regLoc++;
for (i = 0; i < num; i++) {
pRH->regs[regLoc++] = (A_UINT16)in[curEarLoc++];
}
if (~((1 << (numBits % 16)) - 1) & in[curEarLoc - 1])
{
// printf("ar5212EarCheckAndFill: WARNING: Type3 write data exceeds number of bits specified at loc %d\n",
// curEarLoc);
}
} while (!last && (curEarLoc < totalLocs));
break;
}
verMaskUsed = 1;
/* Save any register headers that match the version mask*/
if (verMaskMatch) {
if (regLoc != pEarAlloc->locsPerRH[currentRH]) {
printf("ar5212EarCheckAndFill: Ear Allocation did not match Ear Usage\n");
return FALSE;
}
/*
* Copy stack register header to real register header on match
* BCOPY the regs, save away the reg16 ptr as the struct copy will overwrite it
* finally restore the reg16 ptr.
*/
memcpy(earHead->pRH[currentRH].regs, pRH->regs, regLoc * sizeof(A_UINT16));
pReg16 = earHead->pRH[currentRH].regs;
earHead->pRH[currentRH] = *pRH;
earHead->pRH[currentRH].regs = pReg16;
currentRH++;
}
} /* End Register Header Parse */
} /* End Location Reading */
return TRUE;
}
static void
showEarAlloc(EAR_ALLOC *earAlloc)
{
int i;
printf("Found %d register headers\n", earAlloc->numRHs);
for (i = 0; i < earAlloc->numRHs; i++) {
printf("Register Header %3d requires %2d 16-bit locations\n", i + 1,
earAlloc->locsPerRH[i]);
}
}
A_BOOL
readEar
(
A_UINT32 devNum,
A_UINT32 earStartLocation
)
{
EAR_ALLOC earAlloc;
int earLocs = 0, parsedLocs;
A_UINT32 *earBuffer = NULL;
LIB_DEV_INFO *pLibDev = gLibInfo.pLibDevArray[devNum];
if(!pLibDev->libCfgParams.loadEar) {
// printf("Information: Called readEar and loadEar was not set, returning\n");
return TRUE;
}
if (earStartLocation) {
if((earStartLocation < ATHEROS_EEPROM_OFFSET) ||
(earStartLocation > ATHEROS_EEPROM_END)) {
mError(devNum, EINVAL, "Illegal EAR start location\n");
return FALSE;
}
//allocation a block of memory to take the eeprom locations
earLocs = ATHEROS_EEPROM_END - earStartLocation;
earBuffer = (A_UINT32 *)malloc(sizeof(A_UINT32) * earLocs);
if(earBuffer == NULL) {
mError(devNum, ENOMEM, "readEar: Unable to allocate memory for earBuffer\n");
return FALSE;
}
eepromReadBlock(devNum, earStartLocation, earLocs, earBuffer);
}
if (earBuffer) {
memset(&earAlloc, 0, sizeof(EAR_ALLOC));
parsedLocs = ar5212EarPreParse(earBuffer, earLocs, &earAlloc);
//#ifdef DEBUG
if (EarDebugLevel >= EAR_DEBUG_VERBOSE) {
showEarAlloc(&earAlloc);
}
//#endif
/* Do not allocate EAR if no registers exist */
if (earAlloc.numRHs) {
if(pLibDev->pEarHead) {
//free up previous allocation first
ar5212EarFree(pLibDev->pEarHead);
}
if (ar5212EarAllocate(&earAlloc, &(pLibDev->pEarHead)) == FALSE) {
printf("ar5212Attach: Could not allocate memory for EAR structures\n");
return FALSE;
}
if(!ar5212EarCheckAndFill(pLibDev->pEarHead, earBuffer, parsedLocs, &earAlloc)) {
/* Ear is bad */
printf("ar5212Attach: An unrecoverable EAR error was detected\n");
return FALSE;
}
#ifdef DEBUG
// if (EarDebugLevel >= EAR_DEBUG_BASIC) {
// printEar(pDev->pHalInfo->pEarHead, &earAlloc);
// }
#endif
}
}
free(earBuffer);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -