Esempio n. 1
0
File: fw.c Progetto: 020gzh/linux
int rtl88eu_download_fw(struct adapter *adapt)
{
	struct dvobj_priv *dvobj = adapter_to_dvobj(adapt);
	struct device *device = dvobj_to_dev(dvobj);
	const struct firmware *fw;
	const char fw_name[] = "rtlwifi/rtl8188eufw.bin";
	struct rtl92c_firmware_header *pfwheader = NULL;
	u8 *download_data, *fw_data;
	size_t download_size;
	unsigned int trailing_zeros_length;

	if (request_firmware(&fw, fw_name, device)) {
		dev_err(device, "Firmware %s not available\n", fw_name);
		return -ENOENT;
	}

	if (fw->size > FW_8188E_SIZE) {
		dev_err(device, "Firmware size exceed 0x%X. Check it.\n",
			FW_8188E_SIZE);
		release_firmware(fw);
		return -1;
	}

	trailing_zeros_length = (4 - fw->size % 4) % 4;

	fw_data = kmalloc(fw->size + trailing_zeros_length, GFP_KERNEL);
	if (!fw_data) {
		release_firmware(fw);
		return -ENOMEM;
	}

	memcpy(fw_data, fw->data, fw->size);
	memset(fw_data + fw->size, 0, trailing_zeros_length);

	pfwheader = (struct rtl92c_firmware_header *)fw_data;

	if (IS_FW_HEADER_EXIST(pfwheader)) {
		download_data = fw_data + 32;
		download_size = fw->size + trailing_zeros_length - 32;
	} else {
		download_data = fw_data;
		download_size = fw->size + trailing_zeros_length;
	}

	release_firmware(fw);

	if (usb_read8(adapt, REG_MCUFWDL) & RAM_DL_SEL) {
		usb_write8(adapt, REG_MCUFWDL, 0);
		rtl88e_firmware_selfreset(adapt);
	}
	_rtl88e_enable_fw_download(adapt, true);
	usb_write8(adapt, REG_MCUFWDL, usb_read8(adapt, REG_MCUFWDL) | FWDL_ChkSum_rpt);
	_rtl88e_write_fw(adapt, download_data, download_size);
	_rtl88e_enable_fw_download(adapt, false);

	kfree(fw_data);
	return _rtl88e_fw_free_to_go(adapt);
}
//
//	Description:
//		Download 8192C firmware code.
//
//
int FirmwareDownload92C(
	IN	PADAPTER			Adapter
)
{	
	int	rtStatus = _SUCCESS;	
	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(Adapter);

	char 			R92CFwImageFileName_TSMC[] ={RTL8192C_FW_TSMC_IMG};
	char 			R92CFwImageFileName_UMC[] ={RTL8192C_FW_UMC_IMG};
	char 			R8723FwImageFileName_UMC[] ={RTL8723_FW_UMC_IMG};

	char *			FwImage;
	u32				FwImageLen;	
	
	char*			pFwImageFileName;	

	//vivi, merge 92c and 92s into one driver, 20090817
	//vivi modify this temply, consider it later!!!!!!!!
	//PRT_FIRMWARE	pFirmware = GET_FIRMWARE_819X(Adapter);	
	//PRT_FIRMWARE_92C	pFirmware = GET_FIRMWARE_8192C(Adapter);
	PRT_FIRMWARE_92C	pFirmware = NULL;
	PRT_8192C_FIRMWARE_HDR		pFwHdr = NULL;
	u8		*pFirmwareBuf;
	u32		FirmwareLen;

	pFirmware = (PRT_FIRMWARE_92C)_rtw_malloc(sizeof(RT_FIRMWARE_92C));
	if(!pFirmware)
	{
		rtStatus = _FAIL;
		goto Exit;
	}
	
	

	//RT_TRACE(COMP_INIT, DBG_LOUD, (" ===> FirmwareDownload91C() fw:%s\n", pFwImageFileName));

#ifdef CONFIG_EMBEDDED_FWIMG
	pFirmware->eFWSource = FW_SOURCE_HEADER_FILE;
#else
	pFirmware->eFWSource = FW_SOURCE_IMG_FILE; 
#endif
	if(IS_NORMAL_CHIP(pHalData->VersionID))
	{
		if(IS_VENDOR_UMC_A_CUT(pHalData->VersionID) && !IS_92C_SERIAL(pHalData->VersionID))// UMC , 8188
		{						
			pFwImageFileName = R92CFwImageFileName_UMC;
			FwImage = Rtl819XFwUMCImageArray;
			FwImageLen = UMCImgArrayLength;
			DBG_871X(" ===> FirmwareDownload91C() fw:Rtl819XFwImageArray_UMC\n");
				
		}
		else
		{
			pFwImageFileName = R92CFwImageFileName_TSMC;
			FwImage = Rtl819XFwTSMCImageArray;
			FwImageLen = TSMCImgArrayLength;
			DBG_871X(" ===> FirmwareDownload91C() fw:Rtl819XFwImageArray_TSMC\n");
		}
	}
	else
	{
	#if 0
		pFwImageFileName = TestChipFwFile;
		FwImage = Rtl8192CTestFwImg;
		FwImageLen = Rtl8192CTestFwImgLen;
		RT_TRACE(COMP_INIT, DBG_LOUD, (" ===> FirmwareDownload91C() fw:Rtl8192CTestFwImg\n"));
	#endif
	}
		

	switch(pFirmware->eFWSource)
	{
		case FW_SOURCE_IMG_FILE:
			//TODO:load fw bin file
			break;
		case FW_SOURCE_HEADER_FILE:
			if(TSMCImgArrayLength > FW_8192C_SIZE){
				rtStatus = _FAIL;
				//RT_TRACE(COMP_INIT, DBG_SERIOUS, ("Firmware size exceed 0x%X. Check it.\n", FW_8192C_SIZE) );
				DBG_871X("Firmware size exceed 0x%X. Check it.\n", FW_8192C_SIZE);
				goto Exit;
			}
			_rtw_memcpy(pFirmware->szFwBuffer, FwImage, FwImageLen);
			pFirmware->ulFwLength = FwImageLen;
			break;
	}

	pFirmwareBuf = pFirmware->szFwBuffer;
	FirmwareLen = pFirmware->ulFwLength;

	// To Check Fw header. 
	pFwHdr = (PRT_8192C_FIRMWARE_HDR)pFirmware->szFwBuffer;

	pHalData->FirmwareVersion =  le16_to_cpu(pFwHdr->Version); 
	pHalData->FirmwareSubVersion = le16_to_cpu(pFwHdr->Subversion); 

	//RT_TRACE(COMP_INIT, DBG_LOUD, (" FirmwareVersion(%#x), Signature(%#x)\n", 
	//	Adapter->MgntInfo.FirmwareVersion, pFwHdr->Signature));

	DBG_8192C("fw_ver=v%d, fw_subver=%d, sig=0x%x\n", 
		pHalData->FirmwareVersion, pHalData->FirmwareSubVersion, le16_to_cpu(pFwHdr->Signature)&0xFFF0);

	if(IS_FW_HEADER_EXIST(pFwHdr))
	{
		//RT_TRACE(COMP_INIT, DBG_LOUD,("Shift 32 bytes for FW header!!\n"));
		pFirmwareBuf = pFirmwareBuf + 32;
		FirmwareLen = FirmwareLen -32;
	}
		
	// Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself,
	// or it will cause download Fw fail. 2010.02.01. by tynli.
	if(rtw_read8(Adapter, REG_MCUFWDL)&BIT7) //8051 RAM code
	{	
		DBG_8192C("8051 in Ram......prepare to reset by itself\n");
		_FirmwareSelfReset(Adapter);
		rtw_write8(Adapter, REG_MCUFWDL, 0x00);		
	}

		
	_FWDownloadEnable(Adapter, _TRUE);
	_WriteFW(Adapter, pFirmwareBuf, FirmwareLen);
	_FWDownloadEnable(Adapter, _FALSE);

	rtStatus = _FWFreeToGo(Adapter);
	if(_SUCCESS != rtStatus){
		//RT_TRACE(COMP_INIT, DBG_SERIOUS, ("DL Firmware failed!\n") );	
		goto Exit;
	}	
	//RT_TRACE(COMP_INIT, DBG_LOUD, (" Firmware is ready to run!\n"));

Exit:

	if(pFirmware)
		_rtw_mfree((u8*)pFirmware, sizeof(RT_FIRMWARE_92C));

	//RT_TRACE(COMP_INIT, DBG_LOUD, (" <=== FirmwareDownload91C()\n"));
	return rtStatus;

}