📄 eeprom.c
字号:
} printk("efuseFreeNumber is %d\n",efusefreenum); return TRUE;}INT set_eFusedump_Proc( IN PRTMP_ADAPTER pAd, IN PUCHAR arg){USHORT InBuf[3]; INT i=0; if(!pAd->bUseEfuse) return FALSE; for(i =0; i<EFUSE_USAGE_MAP_END/2; i++) { InBuf[0] = 2*i; InBuf[1] = 2; InBuf[2] = 0x0; eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); if(i%4==0) printk("\nBlock %x:",i/8); printk("%04x ",InBuf[2]); } return TRUE;}INT set_eFuseLoadFromBin_Proc( IN PRTMP_ADAPTER pAd, IN PUCHAR arg){ CHAR *src; struct file *srcf; INT retval, orgfsuid, orgfsgid; mm_segment_t orgfs; UCHAR *buffer; UCHAR BinFileSize=0; INT i = 0,j=0,k=1; USHORT *PDATA; USHORT DATA; BinFileSize=strlen("RT30xxEEPROM.bin"); src = kmalloc(128, MEM_ALLOC_FLAG); NdisZeroMemory(src, 128); if(strlen(arg)>0) { NdisMoveMemory(src, arg, strlen(arg)); } else { NdisMoveMemory(src, "RT30xxEEPROM.bin", BinFileSize); } DBGPRINT(RT_DEBUG_TRACE, ("FileName=%s\n",src)); buffer = kmalloc(MAX_EEPROM_BIN_FILE_SIZE, MEM_ALLOC_FLAG); if(buffer == NULL) { kfree(src); return FALSE;} PDATA=kmalloc(sizeof(USHORT)*8,MEM_ALLOC_FLAG); if(PDATA==NULL) { kfree(src); kfree(buffer); return FALSE; } orgfsuid = current->fsuid; orgfsgid = current->fsgid; current->fsuid=current->fsgid = 0; orgfs = get_fs(); set_fs(KERNEL_DS); if (src && *src) { srcf = filp_open(src, O_RDONLY, 0); if (IS_ERR(srcf)) { DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src)); return FALSE; } else { // The object must have a read method if (srcf->f_op && srcf->f_op->read) { memset(buffer, 0x00, MAX_EEPROM_BIN_FILE_SIZE); while(srcf->f_op->read(srcf, &buffer[i], 1, &srcf->f_pos)==1) { DBGPRINT(RT_DEBUG_TRACE, ("%02X ",buffer[i])); if((i+1)%8==0) DBGPRINT(RT_DEBUG_TRACE, ("\n")); i++; if(i>=MAX_EEPROM_BIN_FILE_SIZE) { DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld reading %s, The file is too large[1024]\n", -PTR_ERR(srcf),src)); kfree(PDATA); kfree(buffer); kfree(src); return FALSE; } } } else { DBGPRINT(RT_DEBUG_ERROR, ("--> Error!! System doest not support read function\n")); kfree(PDATA); kfree(buffer); kfree(src); return FALSE; } } } else { DBGPRINT(RT_DEBUG_ERROR, ("--> Error src or srcf is null\n")); kfree(PDATA); kfree(buffer); return FALSE; } retval=filp_close(srcf,NULL); if (retval) { DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); } set_fs(orgfs); current->fsuid = orgfsuid; current->fsgid = orgfsgid; for(j=0;j<i;j++) { DBGPRINT(RT_DEBUG_TRACE, ("%02X ",buffer[j])); if((j+1)%2==0) PDATA[j/2%8]=((buffer[j]<<8)&0xff00)|(buffer[j-1]&0xff); if(j%16==0) { k=buffer[j]; } else { k&=buffer[j]; if((j+1)%16==0) { DBGPRINT(RT_DEBUG_TRACE, (" result=%02X,blk=%02x\n",k,j/16)); if(k!=0xff) eFuseWriteRegistersFromBin(pAd,(USHORT)j-15, 16, PDATA); else { if(eFuseReadRegisters(pAd,j, 2,(PUSHORT)&DATA)!=0x3f) eFuseWriteRegistersFromBin(pAd,(USHORT)j-15, 16, PDATA); } /* for(l=0;l<8;l++) printk("%04x ",PDATA[l]); printk("\n"); */ NdisZeroMemory(PDATA,16); } } } kfree(PDATA); kfree(buffer); kfree(src); return TRUE; }NTSTATUS eFuseWriteRegistersFromBin( IN PRTMP_ADAPTER pAd, IN USHORT Offset, IN USHORT Length, IN USHORT* pData){ USHORT i; USHORT eFuseData; USHORT LogicalAddress, BlkNum = 0xffff; UCHAR EFSROM_AOUT,Loop=0; EFUSE_CTRL_STRUC eFuseCtrlStruc; USHORT efuseDataOffset; UINT32 data,tempbuffer; USHORT addr,tmpaddr, InBuf[3], tmpOffset; UINT32 buffer[4]; BOOLEAN bWriteSuccess = TRUE; BOOLEAN bNotWrite=TRUE; BOOLEAN bAllocateNewBlk=TRUE; DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin Offset=%x, pData=%04x:%04x:%04x:%04x\n", Offset, *pData,*(pData+1),*(pData+2),*(pData+3))); do { //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. Loop++; 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 bAllocateNewBlk=TRUE; 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 { bAllocateNewBlk=FALSE; 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.1.0 //If the block is not existing in mapping table, create one //and write down the 16-bytes data to the new block if(bAllocateNewBlk) { DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk\n")); efuseDataOffset = EFUSE_DATA3; for(i=0; i< 4; i++) { DBGPRINT(RT_DEBUG_TRACE, ("Allocate New Blk, Data%d=%04x%04x\n",3-i,pData[2*i+1],pData[2*i])); tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i]; RTMP_IO_WRITE32(pAd, efuseDataOffset,tempbuffer); efuseDataOffset -= 4; } ///////////////////////////////////////////////////////////////// //Step1.1.1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. eFuseCtrlStruc.field.EFSROM_AIN = BlkNum* 0x10 ; //Step1.1.2. Write EFSROM_MODE (0x580, bit7:bit6) to 3. eFuseCtrlStruc.field.EFSROM_MODE = 3; //Step1.1.3. 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); //Step1.1.4. 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++; } } else { //Step1.2. //If the same logical number is existing, check if the writting data and the data //saving in this block are the same. ///////////////////////////////////////////////////////////////// //read current values of 16-byte block RTMP_IO_READ32(pAd, EFUSE_CTRL, (PUINT32) &eFuseCtrlStruc); //Step1.2.0. 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.2.1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. eFuseCtrlStruc.field.EFSROM_MODE = 0; //Step1.2.2. 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); //Step1.2.3. 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++; } //Step1.2.4. 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) &buffer[i]); efuseDataOffset -= 4; } //Step1.2.5. Check if the data of efuse and the writing data are the same. for(i =0; i<4; i++) { tempbuffer=((pData[2*i+1]<<16)&0xffff0000)|pData[2*i]; DBGPRINT(RT_DEBUG_TRACE, ("buffer[%d]=%x,pData[%d]=%x,pData[%d]=%x,tempbuffer=%x\n",i,buffer[i],2*i,pData[2*i],2*i+1,pData[2*i+1],tempbuffer)); if(((buffer[i]&0xffff0000)==(pData[2*i+1]<<16))&&((buffer[i]&0xffff)==pData[2*i])) bNotWrite&=TRUE; else { bNotWrite&=FALSE; break; } } if(!bNotWrite) { printk("The data is not the same\n"); for(i =0; i<8; i++) { addr = BlkNum * 0x10 ; InBuf[0] = addr+2*i; InBuf[1] = 2; InBuf[2] = pData[i]; eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); } } else return TRUE; } //Step 2. 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 3. 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); DBGPRINT(RT_DEBUG_TRACE, ("addr=%x, buffer[i]=%x,InBuf[2]=%x\n",InBuf[0],pData[i],InBuf[2])); if(pData[i] != InBuf[2]) { bWriteSuccess = FALSE; break; } } //Step 4. invlidate mapping entry and find a free mapping entry if not succeed if (!bWriteSuccess&&Loop<2) { DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin::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, ("eFuseWriteRegistersFromBin::Not bWriteSuccess new BlkNum = %d\n", BlkNum)); if(BlkNum == 0xffff) { DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegistersFromBin: 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&&Loop<2); return TRUE;}#endif // RT30xx ////2008/09/11:KH add to support efuse-->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -