📄 eeprom.c
字号:
========================================================================*/NTSTATUS eFuseRead( IN PRTMP_ADAPTER pAd, IN USHORT Offset, OUT PUCHAR pData, IN USHORT Length){ USHORT* pOutBuf = (USHORT*)pData; NTSTATUS Status = STATUS_SUCCESS; UCHAR EFSROM_AOUT; int i; for(i=0; i<Length; i+=2) { EFSROM_AOUT = eFuseReadRegisters(pAd, Offset+i, 2, &pOutBuf[i/2]); } return Status;}/* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ========================================================================*/VOID eFusePhysicalWriteRegisters( IN PRTMP_ADAPTER pAd, IN USHORT Offset, IN USHORT Length, OUT USHORT* pData){ EFUSE_CTRL_STRUC eFuseCtrlStruc; int i; USHORT efuseDataOffset; UINT32 data, eFuseDataBuffer[4]; //Step0. Write 16-byte of data to EFUSE_DATA0-3 (0x590-0x59C), where EFUSE_DATA0 is the LSB DW, EFUSE_DATA3 is the MSB DW. ///////////////////////////////////////////////////////////////// //read current values of 16-byte block RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); //Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; //Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. eFuseCtrlStruc.field.EFSROM_MODE = 1; //Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. eFuseCtrlStruc.field.EFSROM_KICK = 1; NdisMoveMemory(&data, &eFuseCtrlStruc, 4); RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); //Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. i = 0; while(i < 100) { RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); if(eFuseCtrlStruc.field.EFSROM_KICK == 0) break; RTMPusecDelay(2); i++; } //Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) efuseDataOffset = EFUSE_DATA3; for(i=0; i< 4; i++) { RTMP_IO_READ32(pAd, efuseDataOffset, (PUINT32) &eFuseDataBuffer[i]); efuseDataOffset -= 4; } //Update the value, the offset is multiple of 2, length is 2 efuseDataOffset = (Offset & 0xc) >> 2; data = pData[0] & 0xffff; //The offset should be 0x***10 or 0x***00 if((Offset % 4) != 0) { eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff) | (data << 16); } else { eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff0000) | data; } efuseDataOffset = EFUSE_DATA3; for(i=0; i< 4; i++) { RTMP_IO_WRITE32(pAd, efuseDataOffset, eFuseDataBuffer[i]); efuseDataOffset -= 4; } ///////////////////////////////////////////////////////////////// //Step1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; //Step2. Write EFSROM_MODE (0x580, bit7:bit6) to 3. eFuseCtrlStruc.field.EFSROM_MODE = 3; //Step3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure. eFuseCtrlStruc.field.EFSROM_KICK = 1; NdisMoveMemory(&data, &eFuseCtrlStruc, 4); RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); //Step4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. Itˇs done. i = 0; while(i < 100) { RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); if(eFuseCtrlStruc.field.EFSROM_KICK == 0) break; RTMPusecDelay(2); i++; }}/* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ========================================================================*/NTSTATUS eFuseWriteRegisters( IN PRTMP_ADAPTER pAd, IN USHORT Offset, IN USHORT Length, IN USHORT* pData){ USHORT i; USHORT eFuseData; USHORT LogicalAddress, BlkNum = 0xffff; UCHAR EFSROM_AOUT; USHORT addr,tmpaddr, InBuf[3], tmpOffset; USHORT buffer[8]; BOOLEAN bWriteSuccess = TRUE; DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters Offset=%x, pData=%x\n", Offset, *pData)); //Step 0. find the entry in the mapping table //The address of EEPROM is 2-bytes alignment. //The last bit is used for alignment, so it must be 0. tmpOffset = Offset & 0xfffe; EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData); if( EFSROM_AOUT == 0x3f) { //find available logical address pointer //the logical address does not exist, find an empty one //from the first address of block 45=16*45=0x2d0 to the last address of block 47 //==>48*16-3(reserved)=2FC for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) { //Retrive the logical block nubmer form each logical address pointer //It will access two logical address pointer each time. eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); if( (LogicalAddress & 0xff) == 0) {//Not used logical address pointer BlkNum = i-EFUSE_USAGE_MAP_START; break; } else if(( (LogicalAddress >> 8) & 0xff) == 0) {//Not used logical address pointer if (i != EFUSE_USAGE_MAP_END) { BlkNum = i-EFUSE_USAGE_MAP_START+1; } break; } } } else { BlkNum = EFSROM_AOUT; } DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum)); if(BlkNum == 0xffff) { DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); return FALSE; } //Step 1. Save data of this block which is pointed by the avaible logical address pointer // read and save the original block data for(i =0; i<8; i++) { addr = BlkNum * 0x10 ; InBuf[0] = addr+2*i; InBuf[1] = 2; InBuf[2] = 0x0; eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); buffer[i] = InBuf[2]; } //Step 2. Update the data in buffer, and write the data to Efuse buffer[ (Offset >> 1) % 8] = pData[0]; do { //Step 3. Write the data to Efuse if(!bWriteSuccess) { for(i =0; i<8; i++) { addr = BlkNum * 0x10 ; InBuf[0] = addr+2*i; InBuf[1] = 2; InBuf[2] = buffer[i]; eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); } } else { addr = BlkNum * 0x10 ; InBuf[0] = addr+(Offset % 16); InBuf[1] = 2; InBuf[2] = pData[0]; eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); } //Step 4. Write mapping table addr = EFUSE_USAGE_MAP_START+BlkNum; tmpaddr = addr; if(addr % 2 != 0) addr = addr -1; InBuf[0] = addr; InBuf[1] = 2; //convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry tmpOffset = Offset; tmpOffset >>= 4; tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40; tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80; // write the logical address if(tmpaddr%2 != 0) InBuf[2] = tmpOffset<<8; else InBuf[2] = tmpOffset; eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0); //Step 5. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted bWriteSuccess = TRUE; for(i =0; i<8; i++) { addr = BlkNum * 0x10 ; InBuf[0] = addr+2*i; InBuf[1] = 2; InBuf[2] = 0x0; eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); if(buffer[i] != InBuf[2]) { bWriteSuccess = FALSE; break; } } //Step 6. invlidate mapping entry and find a free mapping entry if not succeed if (!bWriteSuccess) { DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess BlkNum = %d\n", BlkNum)); // the offset of current mapping entry addr = EFUSE_USAGE_MAP_START+BlkNum; //find a new mapping entry BlkNum = 0xffff; for (i=EFUSE_USAGE_MAP_START; i<=EFUSE_USAGE_MAP_END; i+=2) { eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); if( (LogicalAddress & 0xff) == 0) { BlkNum = i-EFUSE_USAGE_MAP_START; break; } else if(( (LogicalAddress >> 8) & 0xff) == 0) { if (i != EFUSE_USAGE_MAP_END) { BlkNum = i+1-EFUSE_USAGE_MAP_START; } break; } } DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess new BlkNum = %d\n", BlkNum)); if(BlkNum == 0xffff) { DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); return FALSE; } //invalidate the original mapping entry if new entry is not found tmpaddr = addr; if(addr % 2 != 0) addr = addr -1; InBuf[0] = addr; InBuf[1] = 2; eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); // write the logical address if(tmpaddr%2 != 0) { // Invalidate the high byte for (i=8; i<15; i++) { if( ( (InBuf[2] >> i) & 0x01) == 0) { InBuf[2] |= (0x1 <<i); break; } } } else { // invalidate the low byte for (i=0; i<8; i++) { if( ( (InBuf[2] >> i) & 0x01) == 0) { InBuf[2] |= (0x1 <<i); break; } } } eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 0); } } while(!bWriteSuccess); return TRUE;}/* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ========================================================================*/VOID eFuseWritePhysical( IN PRTMP_ADAPTER pAd, PUSHORT lpInBuffer, ULONG nInBufferSize, PUCHAR lpOutBuffer, ULONG nOutBufferSize ){ USHORT* pInBuf = (USHORT*)lpInBuffer; int i; //USHORT* pOutBuf = (USHORT*)ioBuffer; USHORT Offset = pInBuf[0]; //addr USHORT Length = pInBuf[1]; //length USHORT* pValueX = &pInBuf[2]; //value ... // Little-endian S | S Big-endian // addr 3 2 1 0 | 0 1 2 3 // Ori-V D C B A | A B C D //After swapping // D C B A | D C B A //Both the little and big-endian use the same sequence to write data. //Therefore, we only need swap data when read the data. for(i=0; i<Length; i+=2) { eFusePhysicalWriteRegisters(pAd, Offset+i, 2, &pValueX[i/2]); } }/* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ========================================================================*/NTSTATUS eFuseWrite( IN PRTMP_ADAPTER pAd, IN USHORT Offset, IN PUCHAR pData, IN USHORT length){ int i; USHORT* pValueX = (PUSHORT) pData; //value ... //The input value=3070 will be stored as following // Little-endian S | S Big-endian // addr 1 0 | 0 1 // Ori-V 30 70 | 30 70 //After swapping // 30 70 | 70 30 //Casting // 3070 | 7030 (x) //The swapping should be removed for big-endian for(i=0; i<length; i+=2) { eFuseWriteRegisters(pAd, Offset+i, 2, &pValueX[i/2]); } return TRUE;}/* ======================================================================== Routine Description: Arguments: Return Value: IRQL = Note: ========================================================================*/INT set_eFuseGetFreeBlockCount_Proc( IN PRTMP_ADAPTER pAd, IN PUCHAR arg){ USHORT i; USHORT LogicalAddress; USHORT efusefreenum=0; if(!pAd->bUseEfuse) return FALSE; for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i+=2) { eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); if( (LogicalAddress & 0xff) == 0) { efusefreenum= (UCHAR) (EFUSE_USAGE_MAP_END-i+1); break; } else if(( (LogicalAddress >> 8) & 0xff) == 0) { efusefreenum = (UCHAR) (EFUSE_USAGE_MAP_END-i); break; } if(i == EFUSE_USAGE_MAP_END) efusefreenum = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -