staging: rtl8188eu:Remove rtw_zmalloc(), wrapper for kzalloc()
[deliverable/linux.git] / drivers / staging / rtl8188eu / core / rtw_efuse.c
index 40afe48a12efad6b360d8cd1524dd6bf819620c5..82a54b56aff6186bff1dd87d401d13dcbe43d777 100644 (file)
 #include <osdep_service.h>
 #include <drv_types.h>
 #include <rtw_efuse.h>
+#include <usb_ops_linux.h>
+#include <rtl8188e_hal.h>
+#include <rtw_iol.h>
 
-
-
-/*------------------------Define local variable------------------------------*/
-u8 fakeEfuseBank;
-u32 fakeEfuseUsedBytes;
-u8 fakeEfuseContent[EFUSE_MAX_HW_SIZE] = {0};
-u8 fakeEfuseInitMap[EFUSE_MAX_MAP_LEN] = {0};
-u8 fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN] = {0};
-
-u32 BTEfuseUsedBytes;
-u8 BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
-u8 BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-u8 BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-
-u32 fakeBTEfuseUsedBytes;
-u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
-u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0};
-/*------------------------Define local variable------------------------------*/
-
-/*  */
 #define REG_EFUSE_CTRL         0x0030
 #define EFUSE_CTRL                     REG_EFUSE_CTRL          /*  E-Fuse Control. */
-/*  */
-
-bool
-Efuse_Read1ByteFromFakeContent(
-                       struct adapter *pAdapter,
-                       u16 Offset,
-               u8 *Value);
-bool
-Efuse_Read1ByteFromFakeContent(
-                       struct adapter *pAdapter,
-                       u16 Offset,
-               u8 *Value)
-{
-       if (Offset >= EFUSE_MAX_HW_SIZE)
-               return false;
-       if (fakeEfuseBank == 0)
-               *Value = fakeEfuseContent[Offset];
-       else
-               *Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
-       return true;
-}
 
-static bool
-Efuse_Write1ByteToFakeContent(
-                       struct adapter *pAdapter,
-                       u16 Offset,
-                       u8 Value)
-{
-       if (Offset >= EFUSE_MAX_HW_SIZE)
-               return false;
-       if (fakeEfuseBank == 0)
-               fakeEfuseContent[Offset] = Value;
-       else
-               fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
-       return true;
-}
+enum{
+               VOLTAGE_V25                                             = 0x03,
+               LDOE25_SHIFT                                            = 28 ,
+       };
 
-/*-----------------------------------------------------------------------------
+/*
  * Function:   Efuse_PowerSwitch
  *
  * Overview:   When we want to enable write operation, we should change to
  *                             pwr on state. When we stop write, we should switch to 500k mode
  *                             and disable LDO 2.5V.
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When                        Who             Remark
- * 11/17/2008  MHC             Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-void
-Efuse_PowerSwitch(
+ */
+
+void Efuse_PowerSwitch(
                struct adapter *pAdapter,
-               u8 write,
+               u8 bWrite,
                u8 PwrState)
 {
-       pAdapter->HalFunc.EfusePowerSwitch(pAdapter, write, PwrState);
+       u8 tempval;
+       u16     tmpV16;
+
+       if (PwrState) {
+               usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
+
+               /*  1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */
+               tmpV16 = usb_read16(pAdapter, REG_SYS_ISO_CTRL);
+               if (!(tmpV16 & PWC_EV12V)) {
+                       tmpV16 |= PWC_EV12V;
+                        usb_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16);
+               }
+               /*  Reset: 0x0000h[28], default valid */
+               tmpV16 =  usb_read16(pAdapter, REG_SYS_FUNC_EN);
+               if (!(tmpV16 & FEN_ELDR)) {
+                       tmpV16 |= FEN_ELDR;
+                       usb_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16);
+               }
+
+               /*  Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
+               tmpV16 = usb_read16(pAdapter, REG_SYS_CLKR);
+               if ((!(tmpV16 & LOADER_CLK_EN))  || (!(tmpV16 & ANA8M))) {
+                       tmpV16 |= (LOADER_CLK_EN | ANA8M);
+                       usb_write16(pAdapter, REG_SYS_CLKR, tmpV16);
+               }
+
+               if (bWrite) {
+                       /*  Enable LDO 2.5V before read/write action */
+                       tempval = usb_read8(pAdapter, EFUSE_TEST+3);
+                       tempval &= 0x0F;
+                       tempval |= (VOLTAGE_V25 << 4);
+                       usb_write8(pAdapter, EFUSE_TEST+3, (tempval | 0x80));
+               }
+       } else {
+               usb_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
+
+               if (bWrite) {
+                       /*  Disable LDO 2.5V after read/write action */
+                       tempval = usb_read8(pAdapter, EFUSE_TEST+3);
+                       usb_write8(pAdapter, EFUSE_TEST+3, (tempval & 0x7F));
+               }
+       }
 }
 
-/*-----------------------------------------------------------------------------
- * Function:   efuse_GetCurrentSize
- *
- * Overview:   Get current efuse size!!!
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When                        Who             Remark
- * 11/16/2008  MHC             Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-u16
-Efuse_GetCurrentSize(
-       struct adapter *pAdapter,
-       u8 efuseType,
-       bool pseudo)
+static void
+efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8  *pbuf)
 {
-       u16 ret = 0;
+       u8 *efuseTbl = NULL;
+       u8 rtemp8;
+       u16     eFuse_Addr = 0;
+       u8 offset, wren;
+       u16     i, j;
+       u16     **eFuseWord = NULL;
+       u16     efuse_utilized = 0;
+       u8 u1temp = 0;
+
+       efuseTbl = kzalloc(EFUSE_MAP_LEN_88E, GFP_KERNEL);
+       if (efuseTbl == NULL) {
+               DBG_88E("%s: alloc efuseTbl fail!\n", __func__);
+               goto exit;
+       }
 
-       ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType, pseudo);
+       eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
+       if (eFuseWord == NULL) {
+               DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
+               goto exit;
+       }
 
-       return ret;
+       /*  0. Refresh efuse init map as all oxFF. */
+       for (i = 0; i < EFUSE_MAX_SECTION_88E; i++)
+               for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++)
+                       eFuseWord[i][j] = 0xFFFF;
+
+       /*  */
+       /*  1. Read the first byte to check if efuse is empty!!! */
+       /*  */
+       /*  */
+       rtemp8 = *(phymap+eFuse_Addr);
+       if (rtemp8 != 0xFF) {
+               efuse_utilized++;
+               eFuse_Addr++;
+       } else {
+               DBG_88E("EFUSE is empty efuse_Addr-%d efuse_data =%x\n", eFuse_Addr, rtemp8);
+               goto exit;
+       }
+
+       /*  */
+       /*  2. Read real efuse content. Filter PG header and every section data. */
+       /*  */
+       while ((rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+               /*  Check PG header for section num. */
+               if ((rtemp8 & 0x1F) == 0x0F) {          /* extended header */
+                       u1temp = ((rtemp8 & 0xE0) >> 5);
+                       rtemp8 = *(phymap+eFuse_Addr);
+                       if ((rtemp8 & 0x0F) == 0x0F) {
+                               eFuse_Addr++;
+                               rtemp8 = *(phymap+eFuse_Addr);
+
+                               if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E))
+                                       eFuse_Addr++;
+                               continue;
+                       } else {
+                               offset = ((rtemp8 & 0xF0) >> 1) | u1temp;
+                               wren = (rtemp8 & 0x0F);
+                               eFuse_Addr++;
+                       }
+               } else {
+                       offset = ((rtemp8 >> 4) & 0x0f);
+                       wren = (rtemp8 & 0x0f);
+               }
+
+               if (offset < EFUSE_MAX_SECTION_88E) {
+                       /*  Get word enable value from PG header */
+                       for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
+                               /*  Check word enable condition in the section */
+                               if (!(wren & 0x01)) {
+                                       rtemp8 = *(phymap+eFuse_Addr);
+                                       eFuse_Addr++;
+                                       efuse_utilized++;
+                                       eFuseWord[offset][i] = (rtemp8 & 0xff);
+                                       if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+                                               break;
+                                       rtemp8 = *(phymap+eFuse_Addr);
+                                       eFuse_Addr++;
+                                       efuse_utilized++;
+                                       eFuseWord[offset][i] |= (((u16)rtemp8 << 8) & 0xff00);
+
+                                       if (eFuse_Addr >= EFUSE_REAL_CONTENT_LEN_88E)
+                                               break;
+                               }
+                               wren >>= 1;
+                       }
+               }
+               /*  Read next PG header */
+               rtemp8 = *(phymap+eFuse_Addr);
+
+               if (rtemp8 != 0xFF && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN_88E)) {
+                       efuse_utilized++;
+                       eFuse_Addr++;
+               }
+       }
+
+       /*  */
+       /*  3. Collect 16 sections and 4 word unit into Efuse map. */
+       /*  */
+       for (i = 0; i < EFUSE_MAX_SECTION_88E; i++) {
+               for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) {
+                       efuseTbl[(i*8)+(j*2)] = (eFuseWord[i][j] & 0xff);
+                       efuseTbl[(i*8)+((j*2)+1)] = ((eFuseWord[i][j] >> 8) & 0xff);
+               }
+       }
+
+       /*  */
+       /*  4. Copy from Efuse map to output pointer memory!!! */
+       /*  */
+       for (i = 0; i < _size_byte; i++)
+               pbuf[i] = efuseTbl[_offset+i];
+
+       /*  */
+       /*  5. Calculate Efuse utilization. */
+       /*  */
+
+exit:
+       kfree(efuseTbl);
+
+       if (eFuseWord)
+               kfree(eFuseWord);
 }
 
-/*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
-u8
-Efuse_CalculateWordCnts(u8 word_en)
+static void efuse_read_phymap_from_txpktbuf(
+       struct adapter  *adapter,
+       int bcnhead,    /* beacon head, where FW store len(2-byte) and efuse physical map. */
+       u8 *content,    /* buffer to store efuse physical map */
+       u16 *size       /* for efuse content: the max byte to read. will update to byte read */
+       )
 {
-       u8 word_cnts = 0;
-       if (!(word_en & BIT(0)))
-               word_cnts++; /*  0 : write enable */
-       if (!(word_en & BIT(1)))
-               word_cnts++;
-       if (!(word_en & BIT(2)))
-               word_cnts++;
-       if (!(word_en & BIT(3)))
-               word_cnts++;
-       return word_cnts;
+       u16 dbg_addr = 0;
+       u32 start  = 0, passing_time = 0;
+       u8 reg_0x143 = 0;
+       u32 lo32 = 0, hi32 = 0;
+       u16 len = 0, count = 0;
+       int i = 0;
+       u16 limit = *size;
+
+       u8 *pos = content;
+
+       if (bcnhead < 0) /* if not valid */
+               bcnhead = usb_read8(adapter, REG_TDECTRL+1);
+
+       DBG_88E("%s bcnhead:%d\n", __func__, bcnhead);
+
+       usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
+
+       dbg_addr = bcnhead*128/8; /* 8-bytes addressing */
+
+       while (1) {
+               usb_write16(adapter, REG_PKTBUF_DBG_ADDR, dbg_addr+i);
+
+               usb_write8(adapter, REG_TXPKTBUF_DBG, 0);
+               start = jiffies;
+               while (!(reg_0x143 = usb_read8(adapter, REG_TXPKTBUF_DBG)) &&
+                      (passing_time = rtw_get_passing_time_ms(start)) < 1000) {
+                       DBG_88E("%s polling reg_0x143:0x%02x, reg_0x106:0x%02x\n", __func__, reg_0x143, usb_read8(adapter, 0x106));
+                       msleep(1);
+               }
+
+               lo32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_L);
+               hi32 = usb_read32(adapter, REG_PKTBUF_DBG_DATA_H);
+
+               if (i == 0) {
+                       u8 lenc[2];
+                       u16 lenbak, aaabak;
+                       u16 aaa;
+                       lenc[0] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L);
+                       lenc[1] = usb_read8(adapter, REG_PKTBUF_DBG_DATA_L+1);
+
+                       aaabak = le16_to_cpup((__le16 *)lenc);
+                       lenbak = le16_to_cpu(*((__le16 *)lenc));
+                       aaa = le16_to_cpup((__le16 *)&lo32);
+                       len = le16_to_cpu(*((__le16 *)&lo32));
+
+                       limit = (len-2 < limit) ? len-2 : limit;
+
+                       DBG_88E("%s len:%u, lenbak:%u, aaa:%u, aaabak:%u\n", __func__, len, lenbak, aaa, aaabak);
+
+                       memcpy(pos, ((u8 *)&lo32)+2, (limit >= count+2) ? 2 : limit-count);
+                       count += (limit >= count+2) ? 2 : limit-count;
+                       pos = content+count;
+
+               } else {
+                       memcpy(pos, ((u8 *)&lo32), (limit >= count+4) ? 4 : limit-count);
+                       count += (limit >= count+4) ? 4 : limit-count;
+                       pos = content+count;
+               }
+
+               if (limit > count && len-2 > count) {
+                       memcpy(pos, (u8 *)&hi32, (limit >= count+4) ? 4 : limit-count);
+                       count += (limit >= count+4) ? 4 : limit-count;
+                       pos = content+count;
+               }
+
+               if (limit <= count || len-2 <= count)
+                       break;
+               i++;
+       }
+       usb_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
+       DBG_88E("%s read count:%u\n", __func__, count);
+       *size = count;
 }
 
-/*
- * Description:
- * Execute E-Fuse read byte operation.
- * Referred from SD1 Richard.
- * Assumption:
- *             1. Boot from E-Fuse and successfully auto-load.
- *             2. PASSIVE_LEVEL (USB interface)
- * Created by Roger, 2008.10.21.
- */
-void
-ReadEFuseByte(
-               struct adapter *Adapter,
-               u16 _offset,
-               u8 *pbuf,
-               bool pseudo)
-{
-       u32 value32;
-       u8 readbyte;
-       u16 retry;
-
-       if (pseudo) {
-               Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
-               return;
+static s32 iol_read_efuse(struct adapter *padapter, u8 txpktbuf_bndy, u16 offset, u16 size_byte, u8 *logical_map)
+{
+       s32 status = _FAIL;
+       u8 physical_map[512];
+       u16 size = 512;
+
+       usb_write8(padapter, REG_TDECTRL+1, txpktbuf_bndy);
+       memset(physical_map, 0xFF, 512);
+       usb_write8(padapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
+       status = iol_execute(padapter, CMD_READ_EFUSE_MAP);
+       if (status == _SUCCESS)
+               efuse_read_phymap_from_txpktbuf(padapter, txpktbuf_bndy, physical_map, &size);
+       efuse_phymap_to_logical(physical_map, offset, size_byte, logical_map);
+       return status;
+}
+
+void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
+{
+
+       if (rtw_IOL_applied(Adapter)) {
+               rtw_hal_power_on(Adapter);
+               iol_mode_enable(Adapter, 1);
+               iol_read_efuse(Adapter, 0, _offset, _size_byte, pbuf);
+               iol_mode_enable(Adapter, 0);
        }
+       return;
+}
 
-       /* Write Address */
-       rtw_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
-       readbyte = rtw_read8(Adapter, EFUSE_CTRL+2);
-       rtw_write8(Adapter, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
-
-       /* Write bit 32 0 */
-       readbyte = rtw_read8(Adapter, EFUSE_CTRL+3);
-       rtw_write8(Adapter, EFUSE_CTRL+3, (readbyte & 0x7f));
-
-       /* Check bit 32 read-ready */
-       retry = 0;
-       value32 = rtw_read32(Adapter, EFUSE_CTRL);
-       while (!(((value32 >> 24) & 0xff) & 0x80)  && (retry < 10000)) {
-               value32 = rtw_read32(Adapter, EFUSE_CTRL);
-               retry++;
+/* Do not support BT */
+void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut)
+{
+       switch (type) {
+       case TYPE_EFUSE_MAX_SECTION:
+               {
+                       u8 *pMax_section;
+                       pMax_section = (u8 *)pOut;
+                       *pMax_section = EFUSE_MAX_SECTION_88E;
+               }
+               break;
+       case TYPE_EFUSE_REAL_CONTENT_LEN:
+               {
+                       u16 *pu2Tmp;
+                       pu2Tmp = (u16 *)pOut;
+                       *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
+               }
+               break;
+       case TYPE_EFUSE_CONTENT_LEN_BANK:
+               {
+                       u16 *pu2Tmp;
+                       pu2Tmp = (u16 *)pOut;
+                       *pu2Tmp = EFUSE_REAL_CONTENT_LEN_88E;
+               }
+               break;
+       case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
+               {
+                       u16 *pu2Tmp;
+                       pu2Tmp = (u16 *)pOut;
+                       *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
+               }
+               break;
+       case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
+               {
+                       u16 *pu2Tmp;
+                       pu2Tmp = (u16 *)pOut;
+                       *pu2Tmp = (u16)(EFUSE_REAL_CONTENT_LEN_88E-EFUSE_OOB_PROTECT_BYTES_88E);
+               }
+               break;
+       case TYPE_EFUSE_MAP_LEN:
+               {
+                       u16 *pu2Tmp;
+                       pu2Tmp = (u16 *)pOut;
+                       *pu2Tmp = (u16)EFUSE_MAP_LEN_88E;
+               }
+               break;
+       case TYPE_EFUSE_PROTECT_BYTES_BANK:
+               {
+                       u8 *pu1Tmp;
+                       pu1Tmp = (u8 *)pOut;
+                       *pu1Tmp = (u8)(EFUSE_OOB_PROTECT_BYTES_88E);
+               }
+               break;
+       default:
+               {
+                       u8 *pu1Tmp;
+                       pu1Tmp = (u8 *)pOut;
+                       *pu1Tmp = 0;
+               }
+               break;
        }
+}
 
-       /*  20100205 Joseph: Add delay suggested by SD1 Victor. */
-       /*  This fix the problem that Efuse read error in high temperature condition. */
-       /*  Designer says that there shall be some delay after ready bit is set, or the */
-       /*  result will always stay on last data we read. */
-       udelay(50);
-       value32 = rtw_read32(Adapter, EFUSE_CTRL);
-
-       *pbuf = (u8)(value32 & 0xff);
-}
-
-/* Description:
- *     1. Execute E-Fuse read byte operation according as map offset and
- *     save to E-Fuse table.
- *     2. Referred from SD1 Richard.
- * Assumption:
- *     1. Boot from E-Fuse and successfully auto-load.
- *     2. PASSIVE_LEVEL (USB interface)
- *     Created by Roger, 2008.10.21.
- * 2008/12/12 MH
- *     1. Reorganize code flow and reserve bytes. and add description.
- *     2. Add efuse utilization collect.
- * 2008/12/22 MH
- *     Read Efuse must check if we write section 1 data again!!!
- *     Sec1 write addr must be after sec5.
- */
+u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data)
+{
+       u16     tmpaddr = 0;
+       u16     start_addr = efuse_addr;
+       u8 badworden = 0x0F;
+       u8 tmpdata[8];
+
+       memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
+
+       if (!(word_en&BIT0)) {
+               tmpaddr = start_addr;
+               efuse_OneByteWrite(pAdapter, start_addr++, data[0]);
+               efuse_OneByteWrite(pAdapter, start_addr++, data[1]);
+
+               efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[0]);
+               efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[1]);
+               if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1]))
+                       badworden &= (~BIT0);
+       }
+       if (!(word_en&BIT1)) {
+               tmpaddr = start_addr;
+               efuse_OneByteWrite(pAdapter, start_addr++, data[2]);
+               efuse_OneByteWrite(pAdapter, start_addr++, data[3]);
+
+               efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[2]);
+               efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[3]);
+               if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3]))
+                       badworden &= (~BIT1);
+       }
+       if (!(word_en&BIT2)) {
+               tmpaddr = start_addr;
+               efuse_OneByteWrite(pAdapter, start_addr++, data[4]);
+               efuse_OneByteWrite(pAdapter, start_addr++, data[5]);
+
+               efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[4]);
+               efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[5]);
+               if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5]))
+                       badworden &= (~BIT2);
+       }
+       if (!(word_en&BIT3)) {
+               tmpaddr = start_addr;
+               efuse_OneByteWrite(pAdapter, start_addr++, data[6]);
+               efuse_OneByteWrite(pAdapter, start_addr++, data[7]);
+
+               efuse_OneByteRead(pAdapter, tmpaddr, &tmpdata[6]);
+               efuse_OneByteRead(pAdapter, tmpaddr+1, &tmpdata[7]);
+               if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7]))
+                       badworden &= (~BIT3);
+       }
+       return badworden;
+}
 
-static void efuse_ReadEFuse(struct adapter *Adapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool pseudo)
+u16 Efuse_GetCurrentSize(struct adapter *pAdapter)
 {
-       Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, pseudo);
+       int     bContinual = true;
+       u16     efuse_addr = 0;
+       u8 hoffset = 0, hworden = 0;
+       u8 efuse_data, word_cnts = 0;
+
+       rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
+
+       while (bContinual &&
+              efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) &&
+              AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+               if (efuse_data != 0xFF) {
+                       if ((efuse_data&0x1F) == 0x0F) {                /* extended header */
+                               hoffset = efuse_data;
+                               efuse_addr++;
+                               efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
+                               if ((efuse_data & 0x0F) == 0x0F) {
+                                       efuse_addr++;
+                                       continue;
+                               } else {
+                                       hoffset = ((hoffset & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+                                       hworden = efuse_data & 0x0F;
+                               }
+                       } else {
+                               hoffset = (efuse_data>>4) & 0x0F;
+                               hworden =  efuse_data & 0x0F;
+                       }
+                       word_cnts = Efuse_CalculateWordCnts(hworden);
+                       /* read next header */
+                       efuse_addr = efuse_addr + (word_cnts*2)+1;
+               } else {
+                       bContinual = false;
+               }
+       }
+
+       rtw_hal_set_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&efuse_addr);
+
+       return efuse_addr;
 }
 
-void EFUSE_GetEfuseDefinition(struct adapter *pAdapter, u8 efuseType, u8 type, void *pOut, bool pseudo
-       )
+int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data)
 {
-       pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType, type, pOut, pseudo);
+       u8 ReadState = PG_STATE_HEADER;
+       int     bContinual = true;
+       int     bDataEmpty = true;
+       u8 efuse_data, word_cnts = 0;
+       u16     efuse_addr = 0;
+       u8 hoffset = 0, hworden = 0;
+       u8 tmpidx = 0;
+       u8 tmpdata[8];
+       u8 max_section = 0;
+       u8 tmp_header = 0;
+
+       EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, (void *)&max_section);
+
+       if (data == NULL)
+               return false;
+       if (offset > max_section)
+               return false;
+
+       memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
+       memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
+
+       /*  <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
+       /*  Skip dummy parts to prevent unexpected data read from Efuse. */
+       /*  By pass right now. 2009.02.19. */
+       while (bContinual && AVAILABLE_EFUSE_ADDR(efuse_addr)) {
+               /*   Header Read ------------- */
+               if (ReadState & PG_STATE_HEADER) {
+                       if (efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data) && (efuse_data != 0xFF)) {
+                               if (EXT_HEADER(efuse_data)) {
+                                       tmp_header = efuse_data;
+                                       efuse_addr++;
+                                       efuse_OneByteRead(pAdapter, efuse_addr, &efuse_data);
+                                       if (!ALL_WORDS_DISABLED(efuse_data)) {
+                                               hoffset = ((tmp_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+                                               hworden = efuse_data & 0x0F;
+                                       } else {
+                                               DBG_88E("Error, All words disabled\n");
+                                               efuse_addr++;
+                                               continue;
+                                       }
+                               } else {
+                                       hoffset = (efuse_data>>4) & 0x0F;
+                                       hworden =  efuse_data & 0x0F;
+                               }
+                               word_cnts = Efuse_CalculateWordCnts(hworden);
+                               bDataEmpty = true;
+
+                               if (hoffset == offset) {
+                                       for (tmpidx = 0; tmpidx < word_cnts*2; tmpidx++) {
+                                               if (efuse_OneByteRead(pAdapter, efuse_addr+1+tmpidx, &efuse_data)) {
+                                                       tmpdata[tmpidx] = efuse_data;
+                                                       if (efuse_data != 0xff)
+                                                               bDataEmpty = false;
+                                               }
+                                       }
+                                       if (bDataEmpty == false) {
+                                               ReadState = PG_STATE_DATA;
+                                       } else {/* read next header */
+                                               efuse_addr = efuse_addr + (word_cnts*2)+1;
+                                               ReadState = PG_STATE_HEADER;
+                                       }
+                               } else {/* read next header */
+                                       efuse_addr = efuse_addr + (word_cnts*2)+1;
+                                       ReadState = PG_STATE_HEADER;
+                               }
+                       } else {
+                               bContinual = false;
+                       }
+               } else if (ReadState & PG_STATE_DATA) {
+               /*   Data section Read ------------- */
+                       efuse_WordEnableDataRead(hworden, tmpdata, data);
+                       efuse_addr = efuse_addr + (word_cnts*2)+1;
+                       ReadState = PG_STATE_HEADER;
+               }
+
+       }
+
+       if ((data[0] == 0xff) && (data[1] == 0xff) && (data[2] == 0xff)  && (data[3] == 0xff) &&
+           (data[4] == 0xff) && (data[5] == 0xff) && (data[6] == 0xff)  && (data[7] == 0xff))
+               return false;
+       else
+               return true;
 }
 
-/*-----------------------------------------------------------------------------
- * Function:   EFUSE_Read1Byte
- *
- * Overview:   Copy from WMAC fot EFUSE read 1 byte.
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When                        Who             Remark
- * 09/23/2008  MHC             Copy from WMAC.
- *
- *---------------------------------------------------------------------------*/
-u8 EFUSE_Read1Byte(struct adapter *Adapter, u16 Address)
-{
-       u8 data;
-       u8 Bytetemp = {0x00};
-       u8 temp = {0x00};
-       u32 k = 0;
-       u16 contentLen = 0;
-
-       EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&contentLen, false);
-
-       if (Address < contentLen) {     /* E-fuse 512Byte */
-               /* Write E-fuse Register address bit0~7 */
-               temp = Address & 0xFF;
-               rtw_write8(Adapter, EFUSE_CTRL+1, temp);
-               Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
-               /* Write E-fuse Register address bit8~9 */
-               temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
-               rtw_write8(Adapter, EFUSE_CTRL+2, temp);
-
-               /* Write 0x30[31]= 0 */
-               Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
-               temp = Bytetemp & 0x7F;
-               rtw_write8(Adapter, EFUSE_CTRL+3, temp);
-
-               /* Wait Write-ready (0x30[31]= 1) */
-               Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
-               while (!(Bytetemp & 0x80)) {
-                       Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
-                       k++;
-                       if (k == 1000) {
-                               k = 0;
+static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, struct pgpkt *pFixPkt, u16 *pAddr)
+{
+       u8 originaldata[8], badworden = 0;
+       u16     efuse_addr = *pAddr;
+       u32     PgWriteSuccess = 0;
+
+       memset((void *)originaldata, 0xff, 8);
+
+       if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) {
+               /* check if data exist */
+               badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pFixPkt->word_en, originaldata);
+
+               if (badworden != 0xf) { /*  write fail */
+                       PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pFixPkt->offset, badworden, originaldata);
+
+                       if (!PgWriteSuccess)
+                               return false;
+                       else
+                               efuse_addr = Efuse_GetCurrentSize(pAdapter);
+               } else {
+                       efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
+               }
+       } else {
+               efuse_addr = efuse_addr + (pFixPkt->word_cnts*2) + 1;
+       }
+       *pAddr = efuse_addr;
+       return true;
+}
+
+static bool hal_EfusePgPacketWrite2ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+       bool bRet = false;
+       u16     efuse_addr = *pAddr, efuse_max_available_len = 0;
+       u8 pg_header = 0, tmp_header = 0, pg_header_temp = 0;
+       u8 repeatcnt = 0;
+
+       EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len);
+
+       while (efuse_addr < efuse_max_available_len) {
+               pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
+               efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+               efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+
+               while (tmp_header == 0xFF) {
+                       if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+                               return false;
+
+                       efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+                       efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+               }
+
+               /* to write ext_header */
+               if (tmp_header == pg_header) {
+                       efuse_addr++;
+                       pg_header_temp = pg_header;
+                       pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
+
+                       efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+                       efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+
+                       while (tmp_header == 0xFF) {
+                               if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+                                       return false;
+
+                               efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+                               efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+                       }
+
+                       if ((tmp_header & 0x0F) == 0x0F) {      /* word_en PG fail */
+                               if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
+                                       return false;
+                               } else {
+                                       efuse_addr++;
+                                       continue;
+                               }
+                       } else if (pg_header != tmp_header) {   /* offset PG fail */
+                               struct pgpkt    fixPkt;
+                               fixPkt.offset = ((pg_header_temp & 0xE0) >> 5) | ((tmp_header & 0xF0) >> 1);
+                               fixPkt.word_en = tmp_header & 0x0F;
+                               fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
+                               if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
+                                       return false;
+                       } else {
+                               bRet = true;
                                break;
                        }
+               } else if ((tmp_header & 0x1F) == 0x0F) {               /* wrong extended header */
+                       efuse_addr += 2;
+                       continue;
                }
-               data = rtw_read8(Adapter, EFUSE_CTRL);
-               return data;
-       } else {
-               return 0xFF;
        }
 
-} /* EFUSE_Read1Byte */
+       *pAddr = efuse_addr;
+       return bRet;
+}
 
-/*  11/16/2008 MH Read one byte from real Efuse. */
-u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data, bool pseudo)
+static bool hal_EfusePgPacketWrite1ByteHeader(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
 {
-       u8 tmpidx = 0;
-       u8 result;
+       bool bRet = false;
+       u8 pg_header = 0, tmp_header = 0;
+       u16     efuse_addr = *pAddr;
+       u8 repeatcnt = 0;
 
-       if (pseudo) {
-               result = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
-               return result;
+       pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
+
+       efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+       efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
+
+       while (tmp_header == 0xFF) {
+               if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
+                       return false;
+               efuse_OneByteWrite(pAdapter, efuse_addr, pg_header);
+               efuse_OneByteRead(pAdapter, efuse_addr, &tmp_header);
        }
-       /*  -----------------e-fuse reg ctrl --------------------------------- */
-       /* address */
-       rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
-       rtw_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
-                  (rtw_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
 
-       rtw_write8(pAdapter, EFUSE_CTRL+3,  0x72);/* read cmd */
+       if (pg_header == tmp_header) {
+               bRet = true;
+       } else {
+               struct pgpkt    fixPkt;
+               fixPkt.offset = (tmp_header>>4) & 0x0F;
+               fixPkt.word_en = tmp_header & 0x0F;
+               fixPkt.word_cnts = Efuse_CalculateWordCnts(fixPkt.word_en);
+               if (!hal_EfuseFixHeaderProcess(pAdapter, efuseType, &fixPkt, &efuse_addr))
+                       return false;
+       }
 
-       while (!(0x80 & rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
-               tmpidx++;
-       if (tmpidx < 100) {
-               *data = rtw_read8(pAdapter, EFUSE_CTRL);
-               result = true;
+       *pAddr = efuse_addr;
+       return bRet;
+}
+
+static bool hal_EfusePgPacketWriteData(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+       u16     efuse_addr = *pAddr;
+       u8 badworden = 0;
+       u32     PgWriteSuccess = 0;
+
+       badworden = 0x0f;
+       badworden = Efuse_WordEnableDataWrite(pAdapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data);
+       if (badworden == 0x0F) {
+               /*  write ok */
+               return true;
        } else {
-               *data = 0xff;
-               result = false;
+               /* reorganize other pg packet */
+               PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
+               if (!PgWriteSuccess)
+                       return false;
+               else
+                       return true;
        }
-       return result;
 }
 
-/*  11/16/2008 MH Write one byte to reald Efuse. */
-u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data, bool pseudo)
+static bool
+hal_EfusePgPacketWriteHeader(
+                               struct adapter *pAdapter,
+                               u8 efuseType,
+                               u16                             *pAddr,
+                               struct pgpkt *pTargetPkt)
 {
-       u8 tmpidx = 0;
-       u8 result;
+       bool bRet = false;
+
+       if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
+               bRet = hal_EfusePgPacketWrite2ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
+       else
+               bRet = hal_EfusePgPacketWrite1ByteHeader(pAdapter, efuseType, pAddr, pTargetPkt);
+
+       return bRet;
+}
+
+static bool wordEnMatched(struct pgpkt *pTargetPkt, struct pgpkt *pCurPkt,
+                         u8 *pWden)
+{
+       u8 match_word_en = 0x0F;        /*  default all words are disabled */
+
+       /*  check if the same words are enabled both target and current PG packet */
+       if (((pTargetPkt->word_en & BIT0) == 0) &&
+           ((pCurPkt->word_en & BIT0) == 0))
+               match_word_en &= ~BIT0;                         /*  enable word 0 */
+       if (((pTargetPkt->word_en & BIT1) == 0) &&
+           ((pCurPkt->word_en & BIT1) == 0))
+               match_word_en &= ~BIT1;                         /*  enable word 1 */
+       if (((pTargetPkt->word_en & BIT2) == 0) &&
+           ((pCurPkt->word_en & BIT2) == 0))
+               match_word_en &= ~BIT2;                         /*  enable word 2 */
+       if (((pTargetPkt->word_en & BIT3) == 0) &&
+           ((pCurPkt->word_en & BIT3) == 0))
+               match_word_en &= ~BIT3;                         /*  enable word 3 */
+
+       *pWden = match_word_en;
+
+       if (match_word_en != 0xf)
+               return true;
+       else
+               return false;
+}
 
-       if (pseudo) {
-               result = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
-               return result;
+static bool hal_EfuseCheckIfDatafollowed(struct adapter *pAdapter, u8 word_cnts, u16 startAddr)
+{
+       bool bRet = false;
+       u8 i, efuse_data;
+
+       for (i = 0; i < (word_cnts*2); i++) {
+               if (efuse_OneByteRead(pAdapter, (startAddr+i), &efuse_data) && (efuse_data != 0xFF))
+                       bRet = true;
        }
+       return bRet;
+}
 
-       /*  -----------------e-fuse reg ctrl --------------------------------- */
-       /* address */
-       rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
-       rtw_write8(pAdapter, EFUSE_CTRL+2,
-                  (rtw_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
-                  (u8)((addr>>8) & 0x03));
-       rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
+static bool hal_EfusePartialWriteCheck(struct adapter *pAdapter, u8 efuseType, u16 *pAddr, struct pgpkt *pTargetPkt)
+{
+       bool bRet = false;
+       u8 i, efuse_data = 0, cur_header = 0;
+       u8 matched_wden = 0, badworden = 0;
+       u16     startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
+       struct pgpkt curPkt;
 
-       rtw_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
+       EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, (void *)&efuse_max_available_len);
+       EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&efuse_max);
 
-       while ((0x80 &  rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
-               tmpidx++;
+       rtw_hal_get_hwreg(pAdapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
+       startAddr %= EFUSE_REAL_CONTENT_LEN;
 
-       if (tmpidx < 100)
-               result = true;
-       else
-               result = false;
+       while (1) {
+               if (startAddr >= efuse_max_available_len) {
+                       bRet = false;
+                       break;
+               }
 
-       return result;
+               if (efuse_OneByteRead(pAdapter, startAddr, &efuse_data) && (efuse_data != 0xFF)) {
+                       if (EXT_HEADER(efuse_data)) {
+                               cur_header = efuse_data;
+                               startAddr++;
+                               efuse_OneByteRead(pAdapter, startAddr, &efuse_data);
+                               if (ALL_WORDS_DISABLED(efuse_data)) {
+                                       bRet = false;
+                                       break;
+                               } else {
+                                       curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
+                                       curPkt.word_en = efuse_data & 0x0F;
+                               }
+                       } else {
+                               cur_header  =  efuse_data;
+                               curPkt.offset = (cur_header>>4) & 0x0F;
+                               curPkt.word_en = cur_header & 0x0F;
+                       }
+
+                       curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
+                       /*  if same header is found but no data followed */
+                       /*  write some part of data followed by the header. */
+                       if ((curPkt.offset == pTargetPkt->offset) &&
+                           (!hal_EfuseCheckIfDatafollowed(pAdapter, curPkt.word_cnts, startAddr+1)) &&
+                           wordEnMatched(pTargetPkt, &curPkt, &matched_wden)) {
+                               /*  Here to write partial data */
+                               badworden = Efuse_WordEnableDataWrite(pAdapter, startAddr+1, matched_wden, pTargetPkt->data);
+                               if (badworden != 0x0F) {
+                                       u32     PgWriteSuccess = 0;
+                                       /*  if write fail on some words, write these bad words again */
+
+                                       PgWriteSuccess = Efuse_PgPacketWrite(pAdapter, pTargetPkt->offset, badworden, pTargetPkt->data);
+
+                                       if (!PgWriteSuccess) {
+                                               bRet = false;   /*  write fail, return */
+                                               break;
+                                       }
+                               }
+                               /*  partial write ok, update the target packet for later use */
+                               for (i = 0; i < 4; i++) {
+                                       if ((matched_wden & (0x1<<i)) == 0)     /*  this word has been written */
+                                               pTargetPkt->word_en |= (0x1<<i);        /*  disable the word */
+                               }
+                               pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
+                       }
+                       /*  read from next header */
+                       startAddr = startAddr + (curPkt.word_cnts*2) + 1;
+               } else {
+                       /*  not used header, 0xff */
+                       *pAddr = startAddr;
+                       bRet = true;
+                       break;
+               }
+       }
+       return bRet;
 }
 
-int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data, bool pseudo)
+static bool
+hal_EfusePgCheckAvailableAddr(
+               struct adapter *pAdapter,
+               u8 efuseType
+       )
 {
-       int     ret = 0;
+       u16     efuse_max_available_len = 0;
 
-       ret =  pAdapter->HalFunc.Efuse_PgPacketRead(pAdapter, offset, data, pseudo);
+       /* Change to check TYPE_EFUSE_MAP_LEN , because 8188E raw 256, logic map over 256. */
+       EFUSE_GetEfuseDefinition(pAdapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&efuse_max_available_len);
 
-       return ret;
+       if (Efuse_GetCurrentSize(pAdapter) >= efuse_max_available_len)
+               return false;
+       return true;
 }
 
-int Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
+static void hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData, struct pgpkt *pTargetPkt)
 {
-       int ret;
+       memset((void *)pTargetPkt->data, 0xFF, sizeof(u8)*8);
+       pTargetPkt->offset = offset;
+       pTargetPkt->word_en = word_en;
+       efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
+       pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
+}
 
-       ret =  pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, pseudo);
+bool Efuse_PgPacketWrite(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *pData)
+{
+       struct pgpkt    targetPkt;
+       u16                     startAddr = 0;
+       u8 efuseType = EFUSE_WIFI;
 
-       return ret;
+       if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType))
+               return false;
+
+       hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
+
+       if (!hal_EfusePartialWriteCheck(pAdapter, efuseType, &startAddr, &targetPkt))
+               return false;
+
+       if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType, &startAddr, &targetPkt))
+               return false;
+
+       if (!hal_EfusePgPacketWriteData(pAdapter, efuseType, &startAddr, &targetPkt))
+               return false;
+
+       return true;
 }
 
+u8 Efuse_CalculateWordCnts(u8 word_en)
+{
+       u8 word_cnts = 0;
+       if (!(word_en & BIT(0)))
+               word_cnts++; /*  0 : write enable */
+       if (!(word_en & BIT(1)))
+               word_cnts++;
+       if (!(word_en & BIT(2)))
+               word_cnts++;
+       if (!(word_en & BIT(3)))
+               word_cnts++;
+       return word_cnts;
+}
 
-static int Efuse_PgPacketWrite_BT(struct adapter *pAdapter, u8 offset, u8 word_en, u8 *data, bool pseudo)
+u8 efuse_OneByteRead(struct adapter *pAdapter, u16 addr, u8 *data)
 {
-       int ret;
+       u8 tmpidx = 0;
+       u8 result;
 
-       ret =  pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, pseudo);
+       usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr & 0xff));
+       usb_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) & 0x03)) |
+                  (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC));
 
-       return ret;
+       usb_write8(pAdapter, EFUSE_CTRL+3,  0x72);/* read cmd */
+
+       while (!(0x80 & usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
+               tmpidx++;
+       if (tmpidx < 100) {
+               *data = usb_read8(pAdapter, EFUSE_CTRL);
+               result = true;
+       } else {
+               *data = 0xff;
+               result = false;
+       }
+       return result;
 }
 
-/*-----------------------------------------------------------------------------
- * Function:   efuse_WordEnableDataRead
- *
- * Overview:   Read allowed word in current efuse section data.
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When                        Who             Remark
- * 11/16/2008  MHC             Create Version 0.
- * 11/21/2008  MHC             Fix Write bug when we only enable late word.
- *
- *---------------------------------------------------------------------------*/
+u8 efuse_OneByteWrite(struct adapter *pAdapter, u16 addr, u8 data)
+{
+       u8 tmpidx = 0;
+       u8 result;
+
+       usb_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
+       usb_write8(pAdapter, EFUSE_CTRL+2,
+                  (usb_read8(pAdapter, EFUSE_CTRL+2) & 0xFC) |
+                  (u8)((addr>>8) & 0x03));
+       usb_write8(pAdapter, EFUSE_CTRL, data);/* data */
+
+       usb_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
+
+       while ((0x80 &  usb_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx < 100))
+               tmpidx++;
+
+       if (tmpidx < 100)
+               result = true;
+       else
+               result = false;
+
+       return result;
+}
+
+/*
+ * Overview:   Read allowed word in current efuse section data.
+ */
 void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
 {
        if (!(word_en&BIT(0))) {
@@ -419,23 +982,14 @@ void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata)
        }
 }
 
-u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data, bool pseudo)
-{
-       u8 ret = 0;
-
-       ret =  pAdapter->HalFunc.Efuse_WordEnableDataWrite(pAdapter, efuse_addr, word_en, data, pseudo);
-
-       return ret;
-}
-
 static u8 efuse_read8(struct adapter *padapter, u16 address, u8 *value)
 {
-       return efuse_OneByteRead(padapter, address, value, false);
+       return efuse_OneByteRead(padapter, address, value);
 }
 
 static u8 efuse_write8(struct adapter *padapter, u16 address, u8 *value)
 {
-       return efuse_OneByteWrite(padapter, address, *value, false);
+       return efuse_OneByteWrite(padapter, address, *value);
 }
 
 /*
@@ -448,8 +1002,8 @@ u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts
        u8 res = _FAIL;
        u8 (*rw8)(struct adapter *, u16, u8*);
 
-       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len, false);
-       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size, false);
+       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (void *)&real_content_len);
+       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_available_size);
 
        if (start_addr > real_content_len)
                return _FAIL;
@@ -480,59 +1034,41 @@ u8 rtw_efuse_access(struct adapter *padapter, u8 write, u16 start_addr, u16 cnts
 
        return res;
 }
-/*  */
+
 u16 efuse_GetMaxSize(struct adapter *padapter)
 {
        u16 max_size;
-       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size, false);
+       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (void *)&max_size);
        return max_size;
 }
-/*  */
+
 u8 efuse_GetCurrentSize(struct adapter *padapter, u16 *size)
 {
        Efuse_PowerSwitch(padapter, false, true);
-       *size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, false);
+       *size = Efuse_GetCurrentSize(padapter);
        Efuse_PowerSwitch(padapter, false, false);
 
        return _SUCCESS;
 }
-/*  */
+
 u8 rtw_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 {
        u16 mapLen = 0;
 
-       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
 
        if ((addr + cnts) > mapLen)
                return _FAIL;
 
        Efuse_PowerSwitch(padapter, false, true);
 
-       efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, false);
+       efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data);
 
        Efuse_PowerSwitch(padapter, false, false);
 
        return _SUCCESS;
 }
 
-u8 rtw_BT_efuse_map_read(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
-{
-       u16 mapLen = 0;
-
-       EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
-
-       if ((addr + cnts) > mapLen)
-               return _FAIL;
-
-       Efuse_PowerSwitch(padapter, false, true);
-
-       efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, false);
-
-       Efuse_PowerSwitch(padapter, false, false);
-
-       return _SUCCESS;
-}
-/*  */
 u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 {
        u8 offset, word_en;
@@ -542,12 +1078,12 @@ u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
        u8 ret = _SUCCESS;
        u16 mapLen = 0;
 
-       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
+       EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
 
        if ((addr + cnts) > mapLen)
                return _FAIL;
 
-       map = rtw_zmalloc(mapLen);
+       map = kzalloc(mapLen, GFP_KERNEL);
        if (map == NULL)
                return _FAIL;
 
@@ -559,7 +1095,7 @@ u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
 
        offset = (addr >> 3);
        word_en = 0xF;
-       _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
+       memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
        i = addr & 0x7; /*  index of one package */
        idx = 0;        /*  data index */
 
@@ -599,7 +1135,7 @@ u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
                }
 
                if (word_en != 0xF) {
-                       ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, false);
+                       ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata);
                        DBG_88E("offset=%x\n", offset);
                        DBG_88E("word_en=%x\n", word_en);
 
@@ -615,7 +1151,7 @@ u8 rtw_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
                offset++;
                i = 0;
                word_en = 0xF;
-               _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
+               memset(newdata, 0xFF, PGPKT_DATA_SIZE);
        } while (1);
 
        Efuse_PowerSwitch(padapter, true, false);
@@ -624,121 +1160,13 @@ exit:
        return ret;
 }
 
-/*  */
-u8 rtw_BT_efuse_map_write(struct adapter *padapter, u16 addr, u16 cnts, u8 *data)
-{
-       u8 offset, word_en;
-       u8 *map;
-       u8 newdata[PGPKT_DATA_SIZE + 1];
-       s32     i, idx;
-       u8 ret = _SUCCESS;
-       u16 mapLen = 0;
-
-       EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, false);
-
-       if ((addr + cnts) > mapLen)
-               return _FAIL;
-
-       map = rtw_zmalloc(mapLen);
-       if (map == NULL)
-               return _FAIL;
-
-       ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
-       if (ret == _FAIL)
-               goto exit;
-
-       Efuse_PowerSwitch(padapter, true, true);
-
-       offset = (addr >> 3);
-       word_en = 0xF;
-       _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE + 1);
-       i = addr & 0x7; /*  index of one package */
-       idx = 0;        /*  data index */
-
-       if (i & 0x1) {
-               /*  odd start */
-               if (data[idx] != map[addr+idx]) {
-                       word_en &= ~BIT(i >> 1);
-                       newdata[i-1] = map[addr+idx-1];
-                       newdata[i] = data[idx];
-               }
-               i++;
-               idx++;
-       }
-       do {
-               for (; i < PGPKT_DATA_SIZE; i += 2) {
-                       if (cnts == idx)
-                               break;
-                       if ((cnts - idx) == 1) {
-                               if (data[idx] != map[addr+idx]) {
-                                       word_en &= ~BIT(i >> 1);
-                                       newdata[i] = data[idx];
-                                       newdata[i+1] = map[addr+idx+1];
-                               }
-                               idx++;
-                               break;
-                       } else {
-                               if ((data[idx] != map[addr+idx]) ||
-                                   (data[idx+1] != map[addr+idx+1])) {
-                                       word_en &= ~BIT(i >> 1);
-                                       newdata[i] = data[idx];
-                                       newdata[i+1] = data[idx + 1];
-                               }
-                               idx += 2;
-                       }
-                       if (idx == cnts)
-                               break;
-               }
-
-               if (word_en != 0xF) {
-                       DBG_88E("%s: offset=%#X\n", __func__, offset);
-                       DBG_88E("%s: word_en=%#X\n", __func__, word_en);
-                       DBG_88E("%s: data=", __func__);
-                       for (i = 0; i < PGPKT_DATA_SIZE; i++)
-                               DBG_88E("0x%02X ", newdata[i]);
-                       DBG_88E("\n");
-
-                       ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, false);
-                       if (ret == _FAIL)
-                               break;
-               }
-
-               if (idx == cnts)
-                       break;
-
-               offset++;
-               i = 0;
-               word_en = 0xF;
-               _rtw_memset(newdata, 0xFF, PGPKT_DATA_SIZE);
-       } while (1);
-
-       Efuse_PowerSwitch(padapter, true, false);
-
-exit:
-
-       kfree(map);
-
-       return ret;
-}
-
-/*-----------------------------------------------------------------------------
- * Function:   efuse_ShadowRead1Byte
- *                     efuse_ShadowRead2Byte
- *                     efuse_ShadowRead4Byte
- *
- * Overview:   Read from efuse init map by one/two/four bytes !!!!!
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When                        Who             Remark
- * 11/12/2008  MHC             Create Version 0.
+/*
+ * Function:   efuse_ShadowRead1Byte
+ *             efuse_ShadowRead2Byte
+ *             efuse_ShadowRead4Byte
  *
- *---------------------------------------------------------------------------*/
+ * Overview:   Read from efuse init map by one/two/four bytes !!!!!
+ */
 static void
 efuse_ShadowRead1Byte(
                struct adapter *pAdapter,
@@ -749,9 +1177,8 @@ efuse_ShadowRead1Byte(
 
        *Value = pEEPROM->efuse_eeprom_data[Offset];
 
-}      /*  EFUSE_ShadowRead1Byte */
+}
 
-/* Read Two Bytes */
 static void
 efuse_ShadowRead2Byte(
                struct adapter *pAdapter,
@@ -763,9 +1190,8 @@ efuse_ShadowRead2Byte(
        *Value = pEEPROM->efuse_eeprom_data[Offset];
        *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
 
-}      /*  EFUSE_ShadowRead2Byte */
+}
 
-/* Read Four Bytes */
 static void
 efuse_ShadowRead4Byte(
                struct adapter *pAdapter,
@@ -779,85 +1205,45 @@ efuse_ShadowRead4Byte(
        *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
        *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
 
-}      /*  efuse_ShadowRead4Byte */
+}
 
-/*-----------------------------------------------------------------------------
- * Function:   Efuse_ReadAllMap
- *
+/*
  * Overview:   Read All Efuse content
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When                        Who             Remark
- * 11/11/2008  MHC             Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse, bool pseudo)
+ */
+static void Efuse_ReadAllMap(struct adapter *pAdapter, u8 efuseType, u8 *Efuse)
 {
        u16 mapLen = 0;
 
        Efuse_PowerSwitch(pAdapter, false, true);
 
-       EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
+       EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
 
-       efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, pseudo);
+       efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse);
 
        Efuse_PowerSwitch(pAdapter, false, false);
 }
 
-/*-----------------------------------------------------------------------------
- * Function:   EFUSE_ShadowMapUpdate
- *
+/*
  * Overview:   Transfer current EFUSE content to shadow init and modify map.
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When                        Who             Remark
- * 11/13/2008  MHC             Create Version 0.
- *
- *---------------------------------------------------------------------------*/
+ */
 void EFUSE_ShadowMapUpdate(
        struct adapter *pAdapter,
-       u8 efuseType,
-       bool pseudo)
+       u8 efuseType)
 {
        struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
        u16 mapLen = 0;
 
-       EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen, pseudo);
+       EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
 
        if (pEEPROM->bautoload_fail_flag)
-               _rtw_memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
+               memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
        else
-               Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data, pseudo);
-} /*  EFUSE_ShadowMapUpdate */
+               Efuse_ReadAllMap(pAdapter, efuseType, pEEPROM->efuse_eeprom_data);
+}
 
-/*-----------------------------------------------------------------------------
- * Function:   EFUSE_ShadowRead
- *
+/*
  * Overview:   Read from efuse init map !!!!!
- *
- * Input:       NONE
- *
- * Output:      NONE
- *
- * Return:      NONE
- *
- * Revised History:
- * When                        Who             Remark
- * 11/12/2008  MHC             Create Version 0.
- *
- *---------------------------------------------------------------------------*/
+ */
 void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
 {
        if (Type == 1)
@@ -866,5 +1252,4 @@ void EFUSE_ShadowRead(struct adapter *pAdapter, u8 Type, u16 Offset, u32 *Value)
                efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
        else if (Type == 4)
                efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
-
-}      /*  EFUSE_ShadowRead */
+}
This page took 0.041855 seconds and 5 git commands to generate.