2025-05-10 21:58:58 +08:00

1617 lines
45 KiB
C
Executable File

/******************************************************************************
*
* Copyright(c) 2007 - 2020 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* 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.
*
*****************************************************************************/
#if defined(CONFIG_MP_INCLUDED)
#include <rtw_efuse.h>
static u8 rtw_efuse_cmd(_adapter *padapter,
struct rtw_efuse_phl_arg *pefuse_arg ,
enum rtw_efuse_phl_cmdid cmdid)
{
u32 i = 0;
u8 ret = _FAIL;
pefuse_arg->mp_class = RTW_MP_CLASS_EFUSE;
pefuse_arg->cmd = cmdid;
pefuse_arg->cmd_ok = 0;
rtw_mp_set_phl_cmd(padapter, (void*)pefuse_arg, sizeof(struct rtw_efuse_phl_arg));
while (i <= 50) {
rtw_msleep_os(10);
rtw_mp_get_phl_cmd(padapter, (void*)pefuse_arg, sizeof(struct rtw_efuse_phl_arg));
if (pefuse_arg->cmd_ok && pefuse_arg->status == RTW_PHL_STATUS_SUCCESS) {
RTW_INFO("%s,eFuse GET CMD OK !!!\n", __func__);
ret = _SUCCESS;
break;
} else {
rtw_msleep_os(10);
if (i > 50) {
RTW_INFO("%s, eFuse GET CMD FAIL !!!\n", __func__);
break;
}
i++;
}
}
return ret;
}
u32 rtw_efuse_get_map_size(_adapter *padapter , u16 *size , enum rtw_efuse_phl_cmdid cmdid)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 res = _FAIL;
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
_rtw_memset((void *)efuse_arg, 0, sizeof(struct rtw_efuse_phl_arg));
rtw_efuse_cmd(padapter, efuse_arg, cmdid);
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS) {
*size = efuse_arg->io_value;
res = _SUCCESS;
} else {
*size = 0;
res = _FAIL;
}
}
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
u32 rtw_efuse_get_available_size(_adapter *padapter , u16 *size, u8 efuse_type)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 res = _FAIL;
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
_rtw_memset((void *)efuse_arg, 0, sizeof(struct rtw_efuse_phl_arg));
if (efuse_type == RTW_EFUSE_WIFI)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_WIFI_GET_AVL_SIZE);
else
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_BT_GET_AVL_SIZE);
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS) {
*size = efuse_arg->io_value;
res = _SUCCESS;
} else {
*size = 0;
res = _FAIL;
}
}
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
static u8 rtw_efuse_fake2map(_adapter *padapter, u8 efuse_type)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 res = _SUCCESS;
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
_rtw_memset((void *)efuse_arg, 0, sizeof(struct rtw_efuse_phl_arg));
if (efuse_type == RTW_EFUSE_WIFI)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_WIFI_UPDATE);
else if (efuse_type == RTW_EFUSE_BT)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_BT_UPDATE);
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS)
res = _SUCCESS;
else
res = _FAIL;
}
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
static u8 rtw_efuse_read_map2shadow(_adapter *padapter, u8 efuse_type)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 res = _SUCCESS;
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
_rtw_memset((void *)efuse_arg, 0, sizeof(struct rtw_efuse_phl_arg));
if (efuse_type == RTW_EFUSE_WIFI)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_WIFI_UPDATE_MAP);
else if (efuse_type == RTW_EFUSE_BT)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_BT_UPDATE_MAP);
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS)
res = _SUCCESS;
else
res = _FAIL;
}
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
static u8 rtw_efuse_get_shadow_map(_adapter *padapter, u8 *map, u16 size, u8 efuse_type)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 res = _FAIL;
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
efuse_arg->buf_len = size;
if (efuse_type == RTW_EFUSE_WIFI)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_SHADOW_MAP2BUF);
else if (efuse_type == RTW_EFUSE_BT)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_BT_SHADOW_MAP2BUF);
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS) {
_rtw_memcpy((void *)map, efuse_arg->poutbuf, size);
res = _SUCCESS;
} else
res = _FAIL;
}
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
static u8 rtw_efuse_renew_update(_adapter *padapter, u8 efuse_type)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 res = _SUCCESS;
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
_rtw_memset((void *)efuse_arg, 0, sizeof(struct rtw_efuse_phl_arg));
if (efuse_type == RTW_EFUSE_WIFI)
rtw_efuse_cmd(padapter, efuse_arg, RTW_MP_EFUSE_CMD_WIFI_SET_RENEW);
else if (efuse_type == RTW_EFUSE_BT)
RTW_INFO("halmac_get_logical_efuse_size fail\n");
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS)
res = _SUCCESS;
else
res = _FAIL;
}
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
static bool rtw_file_efuse_ismasked(_adapter *padapter, u16 offset, u8 *maskbuf)
{
int r = offset / 16;
int c = (offset % 16) / 2;
int result = 0;
if (padapter->registrypriv.boffefusemask)
return _FALSE;
if (c < 4) /* Upper double word */
result = (maskbuf[r] & (0x10 << c));
else
result = (maskbuf[r] & (0x01 << (c - 4)));
return (result > 0) ? 0 : 1;
}
static u8 rtw_efuse_compare_data(_adapter *padapter,
u8 addr, u32 len, u8 *dst, u8 *src, u8 efuse_type)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
enum rtw_efuse_phl_cmdid cmdid = RTW_EFUSE_CMD_WIFI_GET_MASK_BUF;
u8 res = _FAIL;
u16 idx = addr;
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
_rtw_memset((void *)efuse_arg, 0, sizeof(struct rtw_efuse_phl_arg));
if (efuse_type == RTW_EFUSE_WIFI)
cmdid = RTW_EFUSE_CMD_WIFI_GET_MASK_BUF;
else if (efuse_type == RTW_EFUSE_BT)
cmdid = RTW_EFUSE_CMD_BT_GET_MASK_BUF;
efuse_arg->status = 0;
efuse_arg->cmd_ok = 0;
efuse_arg->buf_len = 0;
if (rtw_efuse_cmd(padapter, efuse_arg, cmdid) == _SUCCESS) {
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "efuse mask buf:",
efuse_arg->poutbuf, efuse_arg->buf_len);
for (; idx <= len; idx++) {
if (!rtw_file_efuse_ismasked(padapter, idx, efuse_arg->poutbuf)) {
if (_rtw_memcmp((void *)dst+idx , (void *)src+idx, 1)) {
RTW_INFO("mask cmp success addr: 0x%x dst: %02x <=> src:%02x\n",
idx, dst[idx], src[idx]);
res = _SUCCESS;
} else {
RTW_INFO("mask cmp Fail addr: 0x%x dst: %02x <=> src:%02x\n",
idx, dst[idx], src[idx]);
res = _FAIL;
break;
}
}
}
} else {
RTW_INFO("rtw_efuse_cmd:%d, status:%d,mask len: %d\n",
efuse_arg->cmd_ok, efuse_arg->status, efuse_arg->buf_len);
res = _FAIL;
}
}
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
u8 rtw_efuse_map_read(_adapter * adapter, u16 addr, u16 cnts, u8 *data, u8 efuse_type)
{
struct dvobj_priv *d;
u8 *efuse = NULL;
u16 size, i;
int err = _FAIL;
u8 status = _SUCCESS;
if (efuse_type == RTW_EFUSE_WIFI)
err = rtw_efuse_get_map_size(adapter, &size, RTW_EFUSE_CMD_WIFI_GET_LOG_SIZE);
else if (efuse_type == RTW_EFUSE_BT)
err = rtw_efuse_get_map_size(adapter, &size, RTW_EFUSE_CMD_BT_GET_LOG_SIZE);
if (err == _FAIL) {
status = _FAIL;
RTW_INFO("halmac_get_logical_efuse_size fail\n");
goto exit;
}
/* size error handle */
if ((addr + cnts) > size) {
if (addr < size)
cnts = size - addr;
else {
status = _FAIL;
RTW_INFO(" %s() ,addr + cnts) > size fail\n", __func__);
goto exit;
}
}
efuse = rtw_zmalloc(size);
if (efuse) {
if (rtw_efuse_read_map2shadow(adapter, efuse_type) == _SUCCESS) {
err = rtw_efuse_get_shadow_map(adapter, efuse, size, efuse_type);
if (err == _FAIL) {
rtw_mfree(efuse, size);
status = _FAIL;
RTW_INFO(" %s() ,halmac_read_logical_efus map fail\n", __func__);
goto exit;
}
} else {
RTW_INFO(" %s() ,rtw_efuse_read_map2shadow FAIL !!!\n", __func__);
rtw_mfree(efuse, size);
status = _FAIL;
goto exit;
}
if (efuse) {
RTW_INFO(" %s() ,cp efuse to data\n", __func__);
_rtw_memcpy(data, efuse + addr, cnts);
rtw_mfree(efuse, size);
}
} else {
RTW_INFO(" %s() ,alloc efuse fail\n", __func__);
goto exit;
}
status = _SUCCESS;
exit:
return status;
}
u8 rtw_efuse_map_write(_adapter * adapter, u16 addr, u16 cnts, u8 *data, u8 efuse_type, u8 bpg)
{
struct dvobj_priv *d;
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
u16 size;
int err = _FAIL;
u8 mask_buf[64] = "";
u32 backupRegs[4] = {0};
u8 status = _SUCCESS;
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u16 i = 0;
efuse_arg = rtw_zmalloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_type == RTW_EFUSE_WIFI)
err = rtw_efuse_get_map_size(adapter, &size, RTW_EFUSE_CMD_WIFI_GET_LOG_SIZE);
else if (efuse_type == RTW_EFUSE_BT)
err = rtw_efuse_get_map_size(adapter, &size, RTW_EFUSE_CMD_BT_GET_LOG_SIZE);
if (err == _FAIL) {
status = _FAIL;
goto exit;
}
if ((addr + cnts) > size) {
status = _FAIL;
goto exit;
}
if (efuse_type == RTW_EFUSE_WIFI) {
while (i != cnts) {
efuse_arg->io_type = 1;
efuse_arg->io_offset = addr + i;
efuse_arg->io_value = data[i];
rtw_efuse_cmd(adapter, efuse_arg, RTW_EFUSE_CMD_WIFI_WRITE);
if (i > cnts)
break;
i++;
}
} else if (efuse_type == RTW_EFUSE_BT) {
while (i != cnts) {
efuse_arg->io_type = 1;
efuse_arg->io_offset = addr + i;
efuse_arg->io_value = data[i];
rtw_efuse_cmd(adapter, efuse_arg, RTW_EFUSE_CMD_BT_WRITE);
if (i > cnts)
break;
i++;
}
}
if (bpg) {
RTW_INFO(" in PG state !!!\n");
if (efuse_type == RTW_EFUSE_WIFI)
err = rtw_efuse_fake2map(adapter, efuse_type);
else if (efuse_type == RTW_EFUSE_BT) {
u8 reg2chkbt = 0;
rtw_phl_write8(dvobj->phl, 0xa3, 0x05);
rtw_msleep_os(10);
reg2chkbt = rtw_phl_read8(dvobj->phl, 0xa0);
if (reg2chkbt != 0x04) {
RTW_ERR("BT State not Active:0x%x ,can't Write \n", reg2chkbt);
goto exit;
}
err = rtw_efuse_fake2map(adapter, efuse_type);
}
if (err == _FAIL) {
status = _FAIL;
goto exit;
}
}
status = _SUCCESS;
exit :
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return status;
}
static u8 rtw_efuse_map_file_load(_adapter *padapter, u8 *filepath, u8 efuse_type)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 res = _FAIL;
if (filepath) {
RTW_INFO("efuse file path %s len %zu", filepath, strlen(filepath));
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
_rtw_memset((void *)efuse_arg, 0, sizeof(struct rtw_efuse_phl_arg));
_rtw_memcpy(efuse_arg->pfile_path, filepath, strlen(filepath));
if (efuse_type == RTW_EFUSE_WIFI)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_FILE_MAP_LOAD);
else
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_BT_FILE_MAP_LOAD);
}
}
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS)
res = _SUCCESS;
else
res = _FAIL;
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
static u8 rtw_efuse_mask_file_load(_adapter *padapter, u8 *filepath, u8 efuse_type)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 res = _FAIL;
if (filepath) {
RTW_INFO("efuse file path %s len %zu", filepath, strlen(filepath));
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
_rtw_memset((void *)efuse_arg, 0, sizeof(struct rtw_efuse_phl_arg));
_rtw_memcpy(efuse_arg->pfile_path, filepath, strlen(filepath));
if (efuse_type == RTW_EFUSE_WIFI)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_FILE_MASK_LOAD);
else
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_BT_FILE_MASK_LOAD);
}
}
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS)
res = _SUCCESS;
else
res = _FAIL;
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
int rtw_ioctl_efuse_get(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
_adapter *padapter = rtw_netdev_priv(dev);
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
char *pch, *ptmp, *token, *tmp[3] = {0x00, 0x00, 0x00};
u16 i = 0, j = 0, mapLen = 0, addr = 0, cnts = 0;
int err = 0;
char *pextra = NULL;
u8 *pre_efuse_map = NULL;
u16 max_available_len = 0;
if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) {
err = -EFAULT;
goto exit;
}
*(extra + wrqu->data.length) = '\0';
pch = extra;
RTW_INFO("%s: in=%s\n", __FUNCTION__, extra);
i = 0;
/* mac 16 "00e04c871200" rmap,00,2 */
while ((token = strsep(&pch, ",")) != NULL) {
if (i > 2)
break;
tmp[i] = token;
i++;
}
pre_efuse_map = rtw_zmalloc(RTW_MAX_EFUSE_MAP_LEN);
if (pre_efuse_map == NULL)
goto exit;
if (strcmp(tmp[0], "status") == 0) {
//sprintf(extra, "Load File efuse=%s,Load File MAC=%s"
// , efuse->file_status == EFUSE_FILE_FAILED ? "FAIL" : "OK"
// , pHalData->macaddr_file_status == MACADDR_FILE_FAILED ? "FAIL" : "OK"
// );
goto exit;
} else if (strcmp(tmp[0], "drvmap") == 0) {
static u8 drvmaporder = 0;
u8 *efuse_data = NULL;
u32 shift, cnt;
u32 blksz = 0x200; /* The size of one time show, default 512 */
//EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, _FALSE);
//efuse_data = efuse->data;
shift = blksz * drvmaporder;
efuse_data += shift;
cnt = mapLen - shift;
if (cnt > blksz) {
cnt = blksz;
drvmaporder++;
} else
drvmaporder = 0;
sprintf(extra, "\n");
for (i = 0; i < cnt; i += 16) {
pextra = extra + strlen(extra);
pextra += sprintf(pextra, "0x%02x\t", shift + i);
for (j = 0; j < 8; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\t");
for (; j < 16; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\n");
}
if ((shift + cnt) < mapLen)
pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen-(shift + cnt), mapLen);
} else if (strcmp(tmp[0], "realmap") == 0) {
static u8 order = 0;
u32 shift, cnt;
u32 blksz = 0x200; /* The size of one time show, default 512 */
u8 *efuse_data = NULL;
rtw_efuse_get_map_size(padapter, &mapLen, RTW_EFUSE_CMD_WIFI_GET_LOG_SIZE);
if (pre_efuse_map) {
if (rtw_efuse_map_read(padapter, 0, mapLen, pre_efuse_map, RTW_EFUSE_WIFI) == _FAIL) {
RTW_INFO("%s: read realmap Fail!!\n", __FUNCTION__);
err = -EFAULT;
} else {
efuse_data = pre_efuse_map;
_rtw_memset(extra, '\0', strlen(extra));
shift = blksz * order;
efuse_data += shift;
cnt = mapLen - shift;
if (cnt > blksz) {
cnt = blksz;
order++;
} else
order = 0;
sprintf(extra, "\n");
for (i = 0; i < cnt; i += 16) {
pextra = extra + strlen(extra);
pextra += sprintf(pextra, "0x%02x\t", shift + i);
for (j = 0; j < 8; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\t");
for (; j < 16; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\n");
if (strlen(extra) > 0x7FF)
break;
}
if ((shift + cnt) < mapLen)
pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen - (shift + cnt), mapLen);
}
}
} else if (strcmp(tmp[0], "rmap") == 0) {
u8 *data = NULL;
if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
RTW_INFO("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
err = -EINVAL;
goto exit;
}
/* rmap addr cnts */
addr = simple_strtoul(tmp[1], &ptmp, 16);
RTW_INFO("%s: addr=%x\n", __FUNCTION__, addr);
cnts = simple_strtoul(tmp[2], &ptmp, 10);
if (cnts == 0) {
RTW_INFO("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
err = -EINVAL;
goto exit;
}
RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
rtw_efuse_get_map_size(padapter, &mapLen, RTW_EFUSE_CMD_WIFI_GET_LOG_SIZE);
if ((addr + cnts) > mapLen) {
RTW_INFO("%s: addr(0x%X)+cnts(%d) over mapLen %d parameter error!\n", __FUNCTION__, addr, cnts, mapLen);
err = -EINVAL;
goto exit;
}
if (pre_efuse_map) {
if (rtw_efuse_map_read(padapter, addr, cnts, pre_efuse_map, RTW_EFUSE_WIFI) == _FAIL) {
RTW_INFO("%s: rtw_efuse_map_read Fail!!\n", __FUNCTION__);
err = -EFAULT;
} else {
data = pre_efuse_map;
*extra = 0;
pextra = extra;
for (i = 0; i < cnts; i++) {
pextra += sprintf(pextra, "0x%02X ", data[i]);
}
}
}
} else if (strcmp(tmp[0], "wlrfkmap") == 0) {
static u8 order = 0;
u32 shift, cnt;
u32 blksz = 0x200; /* The size of one time show, default 512 */
u8 *efuse_data = NULL;
rtw_efuse_get_map_size(padapter, &mapLen, RTW_EFUSE_CMD_WIFI_GET_LOG_SIZE);
if (pre_efuse_map) {
if (rtw_efuse_get_shadow_map(padapter, pre_efuse_map, mapLen, RTW_EFUSE_WIFI) == _FAIL) {
RTW_INFO("%s: read wifi fake map Fail!!\n", __FUNCTION__);
err = -EFAULT;
} else {
efuse_data = pre_efuse_map;
_rtw_memset(extra, '\0', strlen(extra));
shift = blksz * order;
efuse_data += shift;
cnt = mapLen - shift;
if (cnt > blksz) {
cnt = blksz;
order++;
} else
order = 0;
sprintf(extra, "\n");
for (i = 0; i < cnt; i += 16) {
pextra = extra + strlen(extra);
pextra += sprintf(pextra, "0x%02x\t", shift + i);
for (j = 0; j < 8; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\t");
for (; j < 16; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\n");
if (strlen(extra) > 0x7FF)
break;
}
if ((shift + cnt) < mapLen)
pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen - (shift + cnt), mapLen);
}
}
} else if (strcmp(tmp[0], "wlrfkrmap") == 0) {
u8 *data = NULL;
if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
RTW_INFO("%s: rmap Fail!! Parameters error!\n", __FUNCTION__);
err = -EINVAL;
goto exit;
}
/* rmap addr cnts */
addr = simple_strtoul(tmp[1], &ptmp, 16);
RTW_INFO("%s: addr=%x\n", __FUNCTION__, addr);
cnts = simple_strtoul(tmp[2], &ptmp, 10);
if (cnts == 0) {
RTW_INFO("%s: rmap Fail!! cnts error!\n", __FUNCTION__);
err = -EINVAL;
goto exit;
}
RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
rtw_efuse_get_map_size(padapter, &mapLen, RTW_EFUSE_CMD_WIFI_GET_LOG_SIZE);
if ((addr + cnts) > mapLen) {
RTW_INFO("%s: addr(0x%X)+cnts(%d) over mapLen %d parameter error!\n", __FUNCTION__, addr, cnts, mapLen);
err = -EINVAL;
goto exit;
}
if (pre_efuse_map) {
if (rtw_efuse_get_shadow_map(padapter, pre_efuse_map, mapLen, RTW_EFUSE_WIFI) == _FAIL) {
RTW_INFO("%s: read wifi fake map Fail!!\n", __FUNCTION__);
err = -EFAULT;
} else {
data = pre_efuse_map;
*extra = 0;
pextra = extra;
for (i = addr; i < addr + cnts; i++)
pextra += sprintf(pextra, "0x%02X ", data[i]);
}
}
} else if (strcmp(tmp[0], "btrealmap") == 0) {
static u8 order = 0;
u32 shift, cnt;
u32 blksz = 0x200; /* The size of one time show, default 512 */
u8 *efuse_data = NULL;
rtw_efuse_get_map_size(padapter, &mapLen, RTW_EFUSE_CMD_BT_GET_LOG_SIZE);
if (pre_efuse_map) {
if (rtw_efuse_map_read(padapter, 0, mapLen, pre_efuse_map, RTW_EFUSE_BT) == _FAIL) {
RTW_INFO("%s: read BT realmap Fail!!\n", __FUNCTION__);
err = -EFAULT;
} else {
efuse_data = pre_efuse_map;
_rtw_memset(extra, '\0', strlen(extra));
shift = blksz * order;
efuse_data += shift;
cnt = mapLen - shift;
if (cnt > blksz) {
cnt = blksz;
order++;
} else
order = 0;
sprintf(extra, "\n");
for (i = 0; i < cnt; i += 16) {
pextra = extra + strlen(extra);
pextra += sprintf(pextra, "0x%02x\t", shift + i);
for (j = 0; j < 8; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\t");
for (; j < 16; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\n");
if (strlen(extra) > 0x7FF)
break;
}
if ((shift + cnt) < mapLen)
pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen - (shift + cnt), mapLen);
}
}
} else if (strcmp(tmp[0], "btrmap") == 0) {
u8 *data = NULL;
if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
RTW_INFO("%s: btrmap Fail!! Parameters error!\n", __FUNCTION__);
err = -EINVAL;
goto exit;
}
/* rmap addr cnts */
addr = simple_strtoul(tmp[1], &ptmp, 16);
RTW_INFO("%s: addr=%x\n", __FUNCTION__, addr);
cnts = simple_strtoul(tmp[2], &ptmp, 10);
if (cnts == 0) {
RTW_INFO("%s: btrmap Fail!! cnts error!\n", __FUNCTION__);
err = -EINVAL;
goto exit;
}
RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
rtw_efuse_get_map_size(padapter, &mapLen, RTW_EFUSE_CMD_BT_GET_LOG_SIZE);
if ((addr + cnts) > mapLen) {
RTW_INFO("%s: addr(0x%X)+cnts(%d) over mapLen %d parameter error!\n", __FUNCTION__, addr, cnts, mapLen);
err = -EINVAL;
goto exit;
}
if (pre_efuse_map) {
if (rtw_efuse_map_read(padapter, addr, cnts, pre_efuse_map, RTW_EFUSE_BT) == _FAIL) {
RTW_INFO("%s: rtw_efuse_map_read Fail!!\n", __FUNCTION__);
err = -EFAULT;
} else {
data = pre_efuse_map;
*extra = 0;
pextra = extra;
for (i = 0; i < cnts; i++)
pextra += sprintf(pextra, "0x%02X ", data[i]);
}
}
} else if (strcmp(tmp[0], "btrfkmap") == 0) {
static u8 order = 0;
u32 shift, cnt;
u32 blksz = 0x200; /* The size of one time show, default 512 */
u8 *efuse_data = NULL;
rtw_efuse_get_map_size(padapter, &mapLen, RTW_EFUSE_CMD_BT_GET_LOG_SIZE);
if (pre_efuse_map) {
if (rtw_efuse_get_shadow_map(padapter, pre_efuse_map, mapLen, RTW_EFUSE_BT) == _FAIL) {
RTW_INFO("%s: read BT fake map Fail!!\n", __FUNCTION__);
err = -EFAULT;
} else {
efuse_data = pre_efuse_map;
_rtw_memset(extra, '\0', strlen(extra));
shift = blksz * order;
efuse_data += shift;
cnt = mapLen - shift;
if (cnt > blksz) {
cnt = blksz;
order++;
} else
order = 0;
sprintf(extra, "\n");
for (i = 0; i < cnt; i += 16) {
pextra = extra + strlen(extra);
pextra += sprintf(pextra, "0x%02x\t", shift + i);
for (j = 0; j < 8; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\t");
for (; j < 16; j++)
pextra += sprintf(pextra, "%02X ", efuse_data[i + j]);
pextra += sprintf(pextra, "\n");
if (strlen(extra) > 0x7FF)
break;
}
if ((shift + cnt) < mapLen)
pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen - (shift + cnt), mapLen);
}
}
} else if (strcmp(tmp[0], "ableraw") == 0) {
rtw_efuse_get_available_size(padapter, &max_available_len, RTW_EFUSE_WIFI);
sprintf(extra, "[WIFI available raw size]= %d bytes\n", max_available_len);
} else if (strcmp(tmp[0], "btableraw") == 0) {
rtw_efuse_get_available_size(padapter, &max_available_len, RTW_EFUSE_BT);
sprintf(extra, "[BT available raw size]= %d bytes\n", max_available_len);
} else if (strcmp(tmp[0], "realraw") == 0) {
static u8 raw_order = 0;
u32 shift, cnt;
u32 blksz = 0x200; /* The size of one time show, default 512 */
u8 *realraw_map_data = NULL;
rtw_efuse_get_map_size(padapter, &mapLen, RTW_EFUSE_CMD_WIFI_GET_SIZE);
if (pre_efuse_map) {
if (rtw_efuse_raw_map_read (padapter, 0, mapLen, pre_efuse_map, RTW_EFUSE_WIFI) == _FAIL) {
RTW_INFO("%s: read wifi raw map Fail!!\n", __FUNCTION__);
err = -EFAULT;
} else {
realraw_map_data = pre_efuse_map;
_rtw_memset(extra, '\0', strlen(extra));
shift = blksz * raw_order;
realraw_map_data += shift;
cnt = mapLen - shift;
if (cnt > blksz) {
cnt = blksz;
raw_order++;
} else
raw_order = 0;
sprintf(extra, "\n");
for (i = 0; i < cnt; i += 16) {
pextra = extra + strlen(extra);
pextra += sprintf(pextra, "0x%02x\t", shift + i);
for (j = 0; j < 8; j++)
pextra += sprintf(pextra, "%02X ", realraw_map_data[i + j]);
pextra += sprintf(pextra, "\t");
for (; j < 16; j++)
pextra += sprintf(pextra, "%02X ", realraw_map_data[i + j]);
pextra += sprintf(pextra, "\n");
if (strlen(extra) > 0x7FF)
break;
}
if ((shift + cnt) < mapLen)
pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen - (shift + cnt), mapLen);
}
}
} else if (strcmp(tmp[0], "btrealraw")== 0) {
static u8 raw_order = 0;
u32 shift, cnt;
u32 blksz = 0x200; /* The size of one time show, default 512 */
u8 *realraw_map_data = NULL;
rtw_efuse_get_map_size(padapter, &mapLen, RTW_EFUSE_CMD_BT_GET_SIZE);
if (pre_efuse_map) {
if (rtw_efuse_raw_map_read (padapter, 0, mapLen, pre_efuse_map, RTW_EFUSE_BT) == _FAIL) {
RTW_INFO("%s: read bt raw map Fail!!\n", __FUNCTION__);
err = -EFAULT;
} else {
realraw_map_data = pre_efuse_map;
_rtw_memset(extra, '\0', strlen(extra));
shift = blksz * raw_order;
realraw_map_data += shift;
cnt = mapLen - shift;
if (cnt > blksz) {
cnt = blksz;
raw_order++;
} else
raw_order = 0;
sprintf(extra, "\n");
for (i = 0; i < cnt; i += 16) {
pextra = extra + strlen(extra);
pextra += sprintf(pextra, "0x%02x\t", shift + i);
for (j = 0; j < 8; j++)
pextra += sprintf(pextra, "%02X ", realraw_map_data[i + j]);
pextra += sprintf(pextra, "\t");
for (; j < 16; j++)
pextra += sprintf(pextra, "%02X ", realraw_map_data[i + j]);
pextra += sprintf(pextra, "\n");
if (strlen(extra) > 0x7FF)
break;
}
if ((shift + cnt) < mapLen)
pextra += sprintf(pextra, "\t...more (left:%d/%d)\n", mapLen - (shift + cnt), mapLen);
}
}
} else
sprintf(extra, "Command not found!");
exit:
if (pre_efuse_map)
rtw_mfree(pre_efuse_map, RTW_MAX_EFUSE_MAP_LEN);
if (!err)
wrqu->data.length = strlen(extra);
RTW_INFO("%s: strlen(extra) =%zu\n", __FUNCTION__, strlen(extra));
if (copy_to_user(wrqu->data.pointer, extra, wrqu->data.length))
err = -EFAULT;
return err;
}
int rtw_ioctl_efuse_set(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wdata, char *extra)
{
struct iw_point *wrqu;
struct pwrctrl_priv *pwrctrlpriv ;
_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
u8 ips_mode = IPS_NUM; /* init invalid value */
u8 lps_mode = PM_PS_MODE_NUM; /* init invalid value */
u32 i = 0, j = 0, jj = 0, kk = 0;
u8 *setdata = NULL;
u8 *shadowmap = NULL;
u8 *setrawdata = NULL;
char *pch, *ptmp, *token, *tmp[3] = {0x00, 0x00, 0x00};
u16 addr = 0xFF, cnts = 0, max_available_len = 0;
u16 wifimaplen;
int err = 0;
boolean bcmpchk = _TRUE;
u8 status = _SUCCESS;
u16 size;
u8 bpg = true;
wrqu = (struct iw_point *)wdata;
pwrctrlpriv = adapter_to_pwrctl(padapter);
if (copy_from_user(extra, wrqu->pointer, wrqu->length))
return -EFAULT;
*(extra + wrqu->length) = '\0';
setdata = rtw_zmalloc(RTW_MAX_EFUSE_MAP_LEN);
if (setdata == NULL) {
err = -ENOMEM;
goto exit;
}
#ifdef CONFIG_LPS
lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */
rtw_pm_set_lps(padapter, PM_PS_MODE_ACTIVE);
#endif
#ifdef CONFIG_IPS
ips_mode = pwrctrlpriv->ips_mode;/* keep org value */
rtw_pm_set_ips(padapter, IPS_NONE);
#endif
pch = extra;
RTW_INFO("%s: in=%s\n", __FUNCTION__, extra);
i = 0;
while ((token = strsep(&pch, ",")) != NULL) {
if (i > 2)
break;
tmp[i] = token;
i++;
}
/* tmp[0],[1],[2] */
/* wmap,addr,00e04c871200 */
if ((strcmp(tmp[0], "wmap") == 0) || (strcmp(tmp[0], "wlwfake") == 0)) {
if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
err = -EINVAL;
goto exit;
}
addr = simple_strtoul(tmp[1], &ptmp, 16);
addr &= 0xFFF;
cnts = strlen(tmp[2]);
if (cnts % 2) {
err = -EINVAL;
goto exit;
}
cnts /= 2;
if (cnts == 0) {
err = -EINVAL;
goto exit;
}
RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
RTW_INFO("%s: map data=%s\n", __FUNCTION__, tmp[2]);
for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
err = rtw_efuse_get_map_size(padapter, &size, RTW_EFUSE_CMD_WIFI_GET_LOG_SIZE);
max_available_len = size;
if (err == _FAIL) {
status = _FAIL;
goto exit;
}
if ((addr + cnts) > max_available_len) {
RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
err = -EFAULT;
goto exit;
}
if (strcmp(tmp[0], "wlwfake") == 0)
bpg = false;
if (rtw_efuse_map_write(padapter, addr, cnts, setdata, RTW_EFUSE_WIFI, bpg) == _FAIL) {
RTW_INFO("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
err = -EFAULT;
goto exit;
}
*extra = 0;
if (bpg) {
RTW_INFO("%s: after rtw_efuse_map_write to _rtw_memcmp\n", __func__);
shadowmap = rtw_zmalloc(size);
if (shadowmap == NULL) {
RTW_INFO("%s: ShadowMapWiFi rtw_zmalloc Fail\n", __func__);
err = 0;
goto exit;
}
if (rtw_efuse_get_shadow_map(padapter, shadowmap, size,RTW_EFUSE_WIFI) == _SUCCESS) {
if (rtw_efuse_compare_data(padapter, addr, cnts, shadowmap, setdata, RTW_EFUSE_WIFI)) {
RTW_INFO("%s: WiFi write map afterf compare success\n", __FUNCTION__);
sprintf(extra, "WiFi write map compare OK\n");
err = 0;
goto exit;
} else {
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "shadowmap :", shadowmap + addr, cnts);
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "map_pged :", setdata, cnts);
sprintf(extra, "WiFi write map compare FAIL\n");
RTW_INFO("%s: WiFi write map compare Fail\n", __FUNCTION__);
err = 0;
goto exit;
}
}
} else {
sprintf(extra, "WiFi write fake map OK\n");
RTW_INFO("%s: WiFi write fake map OK\n", __FUNCTION__);
err = 0;
goto exit;
}
} else if ((strcmp(tmp[0], "btwmap") == 0) || (strcmp(tmp[0], "btwfake") == 0)) {
if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
err = -EINVAL;
goto exit;
}
addr = simple_strtoul(tmp[1], &ptmp, 16);
addr &= 0xFFF;
cnts = strlen(tmp[2]);
if (cnts % 2) {
err = -EINVAL;
goto exit;
}
cnts /= 2;
if (cnts == 0) {
err = -EINVAL;
goto exit;
}
RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
RTW_INFO("%s: map data=%s\n", __FUNCTION__, tmp[2]);
for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
err = rtw_efuse_get_map_size(padapter, &size, RTW_EFUSE_CMD_BT_GET_LOG_SIZE);
max_available_len = size;
if (err == _FAIL) {
status = _FAIL;
goto exit;
}
if ((addr + cnts) > max_available_len) {
RTW_INFO("%s: addr(0x%X)+cnts(%d) parameter error!\n", __FUNCTION__, addr, cnts);
err = -EFAULT;
goto exit;
}
if (strcmp(tmp[0], "btwfake") == 0)
bpg = false;
if (rtw_efuse_map_write(padapter, addr, cnts, setdata, RTW_EFUSE_BT, bpg) == _FAIL) {
RTW_INFO("%s: rtw_efuse_map_write error!!\n", __FUNCTION__);
err = -EFAULT;
goto exit;
}
*extra = 0;
RTW_INFO("%s: after rtw_efuse_map_write to _rtw_memcmp\n", __func__);
if (bpg) {
shadowmap = rtw_zmalloc(size);
if (shadowmap == NULL) {
RTW_INFO("%s: shadowmap rtw_zmalloc Fail\n", __func__);
err = 0;
goto exit;
}
if (rtw_efuse_get_shadow_map(padapter, shadowmap, size,RTW_EFUSE_BT) == _SUCCESS) {
if (rtw_efuse_compare_data(padapter, addr, cnts, shadowmap, setdata, RTW_EFUSE_BT)) {
RTW_INFO("%s: BT write map afterf compare success\n", __func__);
sprintf(extra, "BT write map compare OK\n");
err = 0;
goto exit;
} else {
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "shadowmap :", shadowmap, cnts);
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "map_pged :", setdata, cnts);
sprintf(extra, "BT write map compare FAIL\n");
RTW_INFO("%s: BT write map compare Fail\n", __func__);
err = 0;
goto exit;
}
}
} else {
sprintf(extra, "BT write fake map OK\n");
RTW_INFO("%s: BT write fake map OK\n", __FUNCTION__);
err = 0;
goto exit;
}
} else if (strcmp(tmp[0], "btwraw") == 0) {
u8 reg2chkbt = 0;
if ((tmp[1] == NULL) || (tmp[2] == NULL)) {
err = -EINVAL;
goto exit;
}
addr = simple_strtoul(tmp[1], &ptmp, 16);
addr &= 0xFFF;
cnts = strlen(tmp[2]);
if (cnts % 2) {
err = -EINVAL;
goto exit;
}
cnts /= 2;
if (cnts == 0) {
err = -EINVAL;
goto exit;
}
RTW_INFO("%s: addr=0x%X\n", __FUNCTION__, addr);
RTW_INFO("%s: cnts=%d\n", __FUNCTION__, cnts);
RTW_INFO("%s: raw data=%s\n", __FUNCTION__, tmp[2]);
rtw_phl_write8(dvobj->phl, 0xa3, 0x05);
rtw_msleep_os(10);
reg2chkbt = rtw_phl_read8(dvobj->phl, 0xa0);
RTW_INFO("%s: btfk2map before read 0xa0 BT Status =0x%x\n", __func__,
rtw_phl_read32(dvobj->phl, 0xa0));
if (reg2chkbt != 0x04) {
sprintf(extra, "Error ! BT State not Active:0x%x ,can't Write \n" , reg2chkbt);
goto exit;
}
for (jj = 0, kk = 0; jj < cnts; jj++, kk += 2)
setdata[jj] = key_2char2num(tmp[2][kk], tmp[2][kk + 1]);
if (rtw_efuse_bt_write_raw_hidden(padapter, addr, cnts, setdata) == _FAIL) {
RTW_INFO("%s: rtw_efuse_bt_write_hidden error!!\n", __FUNCTION__);
err = -EFAULT;
goto exit;
}
} else if (strcmp(tmp[0], "wlfk2map") == 0) {
u16 mapsize = 0;
u8 *map_pged = NULL;
RTW_INFO("%s:do rtw_efuse_fake2map\n", __func__);
rtw_efuse_get_map_size(padapter, &mapsize, RTW_EFUSE_CMD_WIFI_GET_LOG_SIZE);
shadowmap = rtw_zmalloc(mapsize);
if (shadowmap == NULL) {
RTW_INFO("%s: shadowmap rtw_zmalloc Fail\n", __func__);
err = 0;
goto exit;
}
if (rtw_efuse_get_shadow_map(padapter, shadowmap, mapsize, RTW_EFUSE_WIFI) == _FAIL) {
RTW_INFO("%s:rtw_efuse_get_shadow_map Fail\n", __func__);
err = 0;
goto exit;
}
status = rtw_efuse_fake2map(padapter, RTW_EFUSE_WIFI);
if (status == _SUCCESS)
RTW_INFO("WIFI write map OK\n");
else
RTW_INFO("WIFI write map FAIL\n");
map_pged = rtw_zmalloc(mapsize);
if (map_pged == NULL) {
RTW_INFO("%s: map_pged rtw_zmalloc Fail\n", __func__);
err = 0;
goto exit;
}
if (rtw_efuse_map_read(padapter, 0x00, mapsize, map_pged, RTW_EFUSE_WIFI) == _SUCCESS) {
if (rtw_efuse_compare_data(padapter, 0x00, mapsize, map_pged, shadowmap, RTW_EFUSE_WIFI)) {
RTW_INFO("%s: WiFi write map afterf compare success\n", __func__);
sprintf(extra, "WiFi write map compare OK\n");
} else {
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "shadowmap :", shadowmap, mapsize);
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "map_pged :", map_pged, mapsize);
sprintf(extra, "WiFi write map compare FAIL\n");
RTW_INFO("%s: WiFi write map compare Fail\n", __func__);
}
}
if (map_pged)
rtw_mfree(map_pged, mapsize);
err = 0;
goto exit;
} else if (strcmp(tmp[0], "btfk2map") == 0) {
u8 reg2chkbt = 0;
u16 mapsize = 0;
u8 *map_pged = NULL;
RTW_INFO("%s:do rtw_efuse_fake2map\n", __func__);
rtw_efuse_get_map_size(padapter, &mapsize, RTW_EFUSE_CMD_BT_GET_LOG_SIZE);
shadowmap = rtw_zmalloc(mapsize);
if (shadowmap == NULL) {
RTW_INFO("%s: shadowmap rtw_zmalloc Fail\n", __func__);
err = 0;
goto exit;
}
if (rtw_efuse_get_shadow_map(padapter, shadowmap, mapsize, RTW_EFUSE_BT) == _FAIL) {
RTW_INFO("%s:rtw_efuse_get_shadow_map Fail\n", __func__);
err = 0;
goto exit;
}
rtw_phl_write8(dvobj->phl, 0xa3, 0x05);
rtw_msleep_os(10);
reg2chkbt = rtw_phl_read8(dvobj->phl, 0xa0);
RTW_INFO("%s: btfk2map before read 0xa0 BT Status =0x%x\n", __func__,
rtw_phl_read32(dvobj->phl, 0xa0));
if (reg2chkbt != 0x04) {
sprintf(extra, "Error ! BT State not Active:0x%x ,can't Write \n" , reg2chkbt);
goto exit;
}
status = rtw_efuse_fake2map(padapter, RTW_EFUSE_BT);
if (status == _SUCCESS)
RTW_INFO("BT write map OK\n");
else
RTW_INFO("BT write map FAIL\n");
map_pged = rtw_zmalloc(mapsize);
if (map_pged == NULL) {
RTW_INFO("%s: map_pged rtw_zmalloc Fail\n", __func__);
err = 0;
goto exit;
}
if (rtw_efuse_map_read(padapter, 0x00, mapsize, map_pged, RTW_EFUSE_BT) == _SUCCESS) {
if (rtw_efuse_compare_data(padapter, 0x00, mapsize, map_pged, shadowmap, RTW_EFUSE_BT)) {
RTW_INFO("%s: BT write map afterf compare success\n", __func__);
sprintf(extra, "BT write map compare OK\n");
} else {
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "shadowmap :", shadowmap, mapsize);
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "map_pged :", map_pged, mapsize);
sprintf(extra, "BT write map compare FAIL\n");
RTW_INFO("%s: BT write map compare Fail\n", __func__);
}
}
if (map_pged)
rtw_mfree(map_pged, mapsize);
err = 0;
goto exit;
} else if (strcmp(tmp[0], "update") == 0) {
if (rtw_efuse_renew_update(padapter, RTW_EFUSE_WIFI) == _FAIL) {
RTW_INFO("%s: rtw_efuse_renew_update error!!\n", __FUNCTION__);
sprintf(extra, "WIFI update FAIL\n");
err = -EFAULT;
goto exit;
} else
sprintf(extra, "WIFI update OK\n");
}
exit:
if (setdata)
rtw_mfree(setdata, RTW_MAX_EFUSE_MAP_LEN);
if (shadowmap)
rtw_mfree(shadowmap, size);
wrqu->length = strlen(extra);
if (padapter->registrypriv.mp_mode == 0) {
#ifdef CONFIG_IPS
rtw_pm_set_ips(padapter, ips_mode);
#endif /* CONFIG_IPS */
#ifdef CONFIG_LPS
rtw_pm_set_lps(padapter, lps_mode);
#endif /* CONFIG_LPS */
}
return err;
}
int rtw_ioctl_efuse_file_map_load(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
char *rtw_efuse_file_map_path;
u8 Status = 0;
_adapter *padapter= rtw_netdev_priv(dev);
struct mp_priv *pmp_priv = &padapter->mppriv;
if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
return -EFAULT;
rtw_efuse_file_map_path = extra;
if (rtw_is_file_readable(rtw_efuse_file_map_path) == _TRUE) {
RTW_INFO("%s do rtw_efuse_mask_file_read = %s!\n", __func__, rtw_efuse_file_map_path);
Status = rtw_efuse_map_file_load(padapter, rtw_efuse_file_map_path, RTW_EFUSE_WIFI);
if (Status == _TRUE) {
pmp_priv->bloadefusemap = _TRUE;
sprintf(extra, "efuse Map file file_read OK\n");
} else {
pmp_priv->bloadefusemap = _FALSE;
sprintf(extra, "efuse Map file file_read FAIL\n");
}
} else {
sprintf(extra, "efuse file readable FAIL\n");
RTW_INFO("%s rtw_is_file_readable fail!\n", __func__);
}
wrqu->data.length = strlen(extra);
return 0;
}
int rtw_ioctl_efuse_file_mask_load(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
char *rtw_efuse_file_map_path;
u8 Status = 0;
_adapter *padapter= rtw_netdev_priv(dev);
struct mp_priv *pmp_priv = &padapter->mppriv;
if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
return -EFAULT;
rtw_efuse_file_map_path = extra;
if (rtw_is_file_readable(rtw_efuse_file_map_path) == _TRUE) {
RTW_INFO("%s do rtw_efuse_mask_file_read = %s!\n", __func__, rtw_efuse_file_map_path);
Status = rtw_efuse_mask_file_load(padapter, rtw_efuse_file_map_path, RTW_EFUSE_WIFI);
if (Status == _TRUE) {
pmp_priv->bloadefusemap = _TRUE;
sprintf(extra, "efuse Mask file file_read OK\n");
} else {
pmp_priv->bloadefusemap = _FALSE;
sprintf(extra, "efuse Mask file file_read FAIL\n");
}
} else {
sprintf(extra, "efuse file readable FAIL\n");
RTW_INFO("%s rtw_is_file_readable fail!\n", __func__);
}
wrqu->data.length = strlen(extra);
return 0;
}
int rtw_ioctl_efuse_bt_file_map_load(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
char *rtw_efuse_file_map_path;
u8 Status = 0;
_adapter *padapter= rtw_netdev_priv(dev);
struct mp_priv *pmp_priv = &padapter->mppriv;
if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
return -EFAULT;
rtw_efuse_file_map_path = extra;
if (rtw_is_file_readable(rtw_efuse_file_map_path) == _TRUE) {
RTW_INFO("%s BT do rtw_efuse_mask_file_read = %s!\n", __func__, rtw_efuse_file_map_path);
Status = rtw_efuse_map_file_load(padapter, rtw_efuse_file_map_path, RTW_EFUSE_BT);
if (Status == _TRUE) {
pmp_priv->bloadefusemap = _TRUE;
sprintf(extra, "BT efuse Map file file_read OK\n");
} else {
pmp_priv->bloadefusemap = _FALSE;
sprintf(extra, "BT efuse Map file file_read FAIL\n");
}
} else {
sprintf(extra, "BT efuse file readable FAIL\n");
RTW_INFO("%s BT rtw_is_file_readable fail!\n", __func__);
}
wrqu->data.length = strlen(extra);
return 0;
}
int rtw_ioctl_efuse_bt_file_mask_load(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
char *rtw_efuse_file_map_path;
u8 Status = 0;
_adapter *padapter= rtw_netdev_priv(dev);
struct mp_priv *pmp_priv = &padapter->mppriv;
if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length))
return -EFAULT;
rtw_efuse_file_map_path = extra;
if (rtw_is_file_readable(rtw_efuse_file_map_path) == _TRUE) {
RTW_INFO("%s BT mask do rtw_efuse_mask_file_read = %s!\n", __func__, rtw_efuse_file_map_path);
Status = rtw_efuse_mask_file_load(padapter, rtw_efuse_file_map_path, RTW_EFUSE_BT);
if (Status == _TRUE) {
pmp_priv->bloadefusemap = _TRUE;
sprintf(extra, "BT efuse Mask file file_read OK\n");
} else {
pmp_priv->bloadefusemap = _FALSE;
sprintf(extra, "BT efuse Mask file file_read FAIL\n");
}
} else {
sprintf(extra, "BT efuse file readable FAIL\n");
RTW_INFO("%s BT rtw_is_file_readable fail!\n", __func__);
}
wrqu->data.length = strlen(extra);
return 0;
}
s8 rtw_efuse_get_map_from(_adapter *padapter)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 map_status = -1;
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
_rtw_memset((void *)efuse_arg,
0,
sizeof(struct rtw_efuse_phl_arg));
rtw_efuse_cmd(padapter,
efuse_arg,
RTW_MP_EFUSE_CMD_WIFI_GET_MAP_FROM);
if (efuse_arg->cmd_ok &&
efuse_arg->status == RTW_PHL_STATUS_SUCCESS) {
map_status = efuse_arg->io_value;
RTW_INFO("%s: OK value:%d\n",
__func__, map_status);
} else {
map_status = -1;
RTW_INFO("%s: fail !\n", __func__);
}
}
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return map_status;
}
static u8 rtw_efuse_get_realraw(_adapter *padapter, u8 *map, u16 addr, u16 size, u8 efuse_type)
{
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u8 res = _FAIL;
efuse_arg = _rtw_malloc(sizeof(struct rtw_efuse_phl_arg));
if (efuse_arg) {
efuse_arg->io_offset = addr;
efuse_arg->buf_len = size;
if (efuse_type == RTW_EFUSE_WIFI)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_WIFI_GET_PHY_MAP);
else if (efuse_type == RTW_EFUSE_BT)
rtw_efuse_cmd(padapter, efuse_arg, RTW_EFUSE_CMD_BT_GET_PHY_MAP);
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS) {
_rtw_memcpy((void *)map, efuse_arg->poutbuf, size);
res = _SUCCESS;
} else
res = _FAIL;
}
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return res;
}
u8 rtw_efuse_raw_map_read(_adapter * adapter, u16 addr, u16 cnts, u8 *data, u8 efuse_type)
{
struct dvobj_priv *d;
u8 *efuse = NULL;
u16 size, i;
int err = _FAIL;
u8 status = _SUCCESS;
if (efuse_type == RTW_EFUSE_WIFI)
err = rtw_efuse_get_map_size(adapter, &size, RTW_EFUSE_CMD_WIFI_GET_SIZE);
else if (efuse_type == RTW_EFUSE_BT)
err = rtw_efuse_get_map_size(adapter, &size, RTW_EFUSE_CMD_BT_GET_SIZE);
if (err == _FAIL) {
status = _FAIL;
RTW_INFO("get_efuse_size fail\n");
goto exit;
}
/* size error handle */
if ((addr + cnts) > size) {
if (addr < size)
cnts = size - addr;
else {
status = _FAIL;
RTW_INFO(" %s() ,addr + cnts) > size fail\n", __func__);
goto exit;
}
}
efuse = rtw_zmalloc(size);
if (efuse) {
err = rtw_efuse_get_realraw (adapter, efuse, addr, size, efuse_type);
if (err == _FAIL) {
rtw_mfree(efuse, size);
status = _FAIL;
RTW_INFO(" %s() , phl get realraw fail\n", __func__);
goto exit;
}
if (efuse) {
RTW_INFO(" %s() ,cp efuse to data\n", __func__);
_rtw_memcpy(data, efuse + addr, cnts);
rtw_mfree(efuse, size);
}
} else {
RTW_INFO(" %s() ,alloc efuse fail\n", __func__);
goto exit;
}
status = _SUCCESS;
exit:
return status;
}
u8 rtw_efuse_bt_write_raw_hidden(_adapter * adapter, u16 addr, u16 cnts, u8 *data)
{
u8 status = _SUCCESS;
struct rtw_efuse_phl_arg *efuse_arg = NULL;
u16 i = 0;
efuse_arg = _rtw_zmalloc(sizeof(struct rtw_efuse_phl_arg));
while (i < cnts) {
efuse_arg->io_type = 1;
efuse_arg->io_offset = addr + i;
efuse_arg->io_value = data[i];
rtw_efuse_cmd(adapter, efuse_arg, RTW_EFUSE_CMD_BT_WRITE_HIDDEN);
if (efuse_arg->cmd_ok && efuse_arg->status == RTW_PHL_STATUS_SUCCESS)
status = _SUCCESS;
else{
status = _FAIL;
break;
}
i++;
}
exit :
if (efuse_arg)
_rtw_mfree(efuse_arg, sizeof(struct rtw_efuse_phl_arg));
return status;
}
#endif /*#if defined(CONFIG_MP_INCLUDED)*/