/* ************************************************************************* * Ralink Tech Inc. * 5F., No.36, Taiyuan St., Jhubei City, * Hsinchu County 302, * Taiwan, R.O.C. * * (c) Copyright 2002-2010, Ralink Technology, Inc. * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * *************************************************************************/ #include "rt_config.h" static NDIS_STATUS rtmp_ee_flash_init(PRTMP_ADAPTER pAd, PUCHAR start); static USHORT EE_FLASH_ID_LIST[]={ #ifdef RT35xx 0x3572, #endif /* RT35xx */ #ifdef RT5592 #ifdef RTMP_MAC_USB 0x5572, #endif /* RTMP_MAC_USB */ #endif /* RT5592 */ #ifdef RT3593 #endif /* RT3593 */ }; #define EE_FLASH_ID_NUM (sizeof(EE_FLASH_ID_LIST) / sizeof(USHORT)) /******************************************************************************* * * Flash-based EEPROM read/write procedures. * some chips use the flash memory instead of internal EEPROM to save the * calibration info, we need these functions to do the read/write. * ******************************************************************************/ int rtmp_ee_flash_read( IN PRTMP_ADAPTER pAd, IN USHORT Offset, OUT USHORT *pValue) { if (!pAd->chipCap.ee_inited) { *pValue = 0xffff; } else { memcpy(pValue, pAd->eebuf + Offset, 2); } return (*pValue); } int rtmp_ee_flash_write(PRTMP_ADAPTER pAd, USHORT Offset, USHORT Data) { if (pAd->chipCap.ee_inited) { memcpy(pAd->eebuf + Offset, &Data, 2); /*rt_nv_commit();*/ /*rt_cfg_commit();*/ #ifdef MULTIPLE_CARD_SUPPORT DBGPRINT(RT_DEBUG_TRACE, ("rtmp_ee_flash_write:pAd->MC_RowID = %d\n", pAd->MC_RowID)); DBGPRINT(RT_DEBUG_TRACE, ("E2P_OFFSET = 0x%08x\n", pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID])); if ((pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]==0x48000) || (pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]==0x40000)) RtmpFlashWrite(pAd->eebuf, pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID], EEPROM_SIZE); #else RtmpFlashWrite(pAd->eebuf, RF_OFFSET, EEPROM_SIZE); #endif /* MULTIPLE_CARD_SUPPORT */ } return 0; } VOID rtmp_ee_flash_read_all(PRTMP_ADAPTER pAd, USHORT *Data) { if (!pAd->chipCap.ee_inited) return; memcpy(Data, pAd->eebuf, EEPROM_SIZE); } VOID rtmp_ee_flash_write_all(PRTMP_ADAPTER pAd, USHORT *Data) { if (!pAd->chipCap.ee_inited) return; memcpy(pAd->eebuf, Data, EEPROM_SIZE); #ifdef MULTIPLE_CARD_SUPPORT DBGPRINT(RT_DEBUG_TRACE, ("rtmp_ee_flash_write_all:pAd->MC_RowID = %d\n", pAd->MC_RowID)); DBGPRINT(RT_DEBUG_TRACE, ("E2P_OFFSET = 0x%08x\n", pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID])); if ((pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]==0x48000) || (pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]==0x40000)) RtmpFlashWrite(pAd->eebuf, pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID], EEPROM_SIZE); #else RtmpFlashWrite(pAd->eebuf, RF_OFFSET, EEPROM_SIZE); #endif /* MULTIPLE_CARD_SUPPORT */ } static NDIS_STATUS rtmp_ee_flash_reset( IN RTMP_ADAPTER *pAd, IN PUCHAR start) { PUCHAR src; RTMP_OS_FS_INFO osFsInfo; RTMP_OS_FD srcf; INT retval; src = EEPROM_DEFAULT_FILE_PATH; RtmpOSFSInfoChange(&osFsInfo, TRUE); if (src && *src) { srcf = RtmpOSFileOpen(src, O_RDONLY, 0); if (IS_FILE_OPEN_ERR(srcf)) { DBGPRINT(RT_DEBUG_TRACE, ("--> Error opening file %s\n", src)); return NDIS_STATUS_FAILURE; } else { /* The object must have a read method*/ NdisZeroMemory(start, EEPROM_SIZE); retval = RtmpOSFileRead(srcf, start, EEPROM_SIZE); if (retval < 0) { DBGPRINT(RT_DEBUG_TRACE, ("--> Read %s error %d\n", src, -retval)); } else { DBGPRINT(RT_DEBUG_TRACE, ("--> rtmp_ee_flash_reset copy %s to eeprom buffer\n", src)); } retval = RtmpOSFileClose(srcf); if (retval) { DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); } } } RtmpOSFSInfoChange(&osFsInfo, FALSE); return NDIS_STATUS_SUCCESS; } #ifdef LINUX /* 0 -- Show ee buffer */ /* 1 -- force reset to default */ /* 2 -- Change ee settings */ int Set_EECMD_Proc( IN PRTMP_ADAPTER pAd, IN PUCHAR arg) { USHORT i; i = simple_strtol(arg, 0, 10); switch(i) { case 0: { USHORT value, k; for (k = 0; k < EEPROM_SIZE; k+=2) { RT28xx_EEPROM_READ16(pAd, k, value); DBGPRINT(RT_DEBUG_OFF, ("%4.4x ", value)); if (((k+2) % 0x20) == 0) DBGPRINT(RT_DEBUG_OFF,("\n")); } } break; case 1: if (pAd->infType == RTMP_DEV_INF_RBUS) { DBGPRINT(RT_DEBUG_OFF, ("EEPROM reset to default......\n")); DBGPRINT(RT_DEBUG_OFF, ("The last byte of MAC address will be re-generated...\n")); if (rtmp_ee_flash_reset(pAd, pAd->eebuf) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR, ("Set_EECMD_Proc: rtmp_ee_flash_reset() failed\n")); return FALSE; } /* Random number for the last bytes of MAC address*/ { USHORT Addr45; rtmp_ee_flash_read(pAd, 0x08, &Addr45); Addr45 = Addr45 & 0xff; Addr45 = Addr45 | (RandomByte(pAd)&0xf8) << 8; DBGPRINT(RT_DEBUG_OFF, ("Addr45 = %4x\n", Addr45)); rtmp_ee_flash_write(pAd, 0x08, Addr45); } if ((rtmp_ee_flash_read(pAd, 0, &i) != 0x2880) && (rtmp_ee_flash_read(pAd, 0, &i) != 0x2860)) { DBGPRINT(RT_DEBUG_ERROR, ("Set_EECMD_Proc: invalid eeprom\n")); return FALSE; } } break; case 2: { USHORT offset, value = 0; PUCHAR p; p = arg+2; offset = simple_strtol(p, 0, 10); p+=2; while (*p != '\0') { if (*p >= '0' && *p <= '9') value = (value << 4) + (*p - 0x30); else if (*p >= 'a' && *p <= 'f') value = (value << 4) + (*p - 0x57); else if (*p >= 'A' && *p <= 'F') value = (value << 4) + (*p - 0x37); p++; } RT28xx_EEPROM_WRITE16(pAd, offset, value); } break; default: break; } return TRUE; } #endif /* LINUX */ static BOOLEAN validFlashEepromID(RTMP_ADAPTER *pAd) { USHORT eeFlashId; int listIdx; rtmp_ee_flash_read(pAd, 0, &eeFlashId); for(listIdx =0 ; listIdx < EE_FLASH_ID_NUM; listIdx++) { if (eeFlashId == EE_FLASH_ID_LIST[listIdx]) return TRUE; } return FALSE; } static NDIS_STATUS rtmp_ee_flash_init(PRTMP_ADAPTER pAd, PUCHAR start) { pAd->chipCap.ee_inited = 1; if (validFlashEepromID(pAd) == FALSE) { if (rtmp_ee_flash_reset(pAd, start) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR, ("rtmp_ee_init(): rtmp_ee_flash_init() failed\n")); return NDIS_STATUS_FAILURE; } /* Random number for the last bytes of MAC address*/ { USHORT Addr45; rtmp_ee_flash_read(pAd, 0x08, &Addr45); Addr45 = Addr45 & 0xff; Addr45 = Addr45 | (RandomByte(pAd)&0xf8) << 8; rtmp_ee_flash_write(pAd, 0x08, Addr45); DBGPRINT(RT_DEBUG_ERROR, ("The EEPROM in Flash is wrong, use default\n")); } if (validFlashEepromID(pAd) == FALSE) { DBGPRINT(RT_DEBUG_ERROR, ("rtmp_ee_flash_init(): invalid eeprom\n")); return NDIS_STATUS_FAILURE; } } return NDIS_STATUS_SUCCESS; } NDIS_STATUS rtmp_nv_init(PRTMP_ADAPTER pAd) { #ifdef MULTIPLE_CARD_SUPPORT UCHAR *eepromBuf; #endif /* MULTIPLE_CARD_SUPPORT */ DBGPRINT(RT_DEBUG_TRACE, ("--> rtmp_nv_init\n")); if (pAd->chipCap.eebuf == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("pAd->chipCap.eebuf == NULL!!!\n")); return NDIS_STATUS_FAILURE; } /* ASSERT((pAd->eebuf == NULL)); */ pAd->eebuf = pAd->chipCap.eebuf; #ifdef MULTIPLE_CARD_SUPPORT DBGPRINT(RT_DEBUG_OFF, ("rtmp_nv_init:pAd->MC_RowID = %d\n", pAd->MC_RowID)); os_alloc_mem(pAd, &eepromBuf, EEPROM_SIZE); if (eepromBuf) { pAd->eebuf = eepromBuf; NdisMoveMemory(pAd->eebuf, pAd->chipCap.eebuf, EEPROM_SIZE); } else { DBGPRINT(RT_DEBUG_ERROR,("rtmp_nv_init:Alloc memory for pAd->MC_RowID[%d] failed! used default one!\n", pAd->MC_RowID)); } DBGPRINT(RT_DEBUG_OFF, ("E2P_OFFSET = 0x%08x\n", pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID])); RtmpFlashRead(pAd->eebuf, pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID], EEPROM_SIZE); #else RtmpFlashRead(pAd->eebuf, RF_OFFSET, EEPROM_SIZE); #endif /* MULTIPLE_CARD_SUPPORT */ return rtmp_ee_flash_init(pAd, pAd->eebuf); }