⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eeprom.c

📁 ralink最新rt3070 usb wifi 无线网卡驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		========================================================================*/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 + -