#include "headers.h"

#define DWORD unsigned int

static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter, unsigned int offset);
static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter);
static int BcmGetActiveISO(struct bcm_mini_adapter *Adapter);
static unsigned int BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter);
static int BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter);
static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, unsigned int FlashSectorSizeSig, unsigned int FlashSectorSize);

static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter);
static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter);
static unsigned int BcmGetFlashSize(struct bcm_mini_adapter *Adapter);
static enum bcm_nvm_type BcmGetNvmType(struct bcm_mini_adapter *Adapter);

static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);

static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, unsigned int uiOffset);
static int IsSectionWritable(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val Section);
static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section);

static int ReadDSDPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd);
static int ReadDSDSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd);
static int ReadISOPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso);
static int ReadISOSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso);

static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal);
static int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned int uiSectAlignAddr);
static int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, PUINT pBuff,
					enum bcm_flash2x_section_val eFlash2xSectionVal,
					unsigned int uiOffset, unsigned int uiNumBytes);
static enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter);
static enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter);

static int BeceemFlashBulkRead(
	struct bcm_mini_adapter *Adapter,
	PUINT pBuffer,
	unsigned int uiOffset,
	unsigned int uiNumBytes);

static int BeceemFlashBulkWrite(
	struct bcm_mini_adapter *Adapter,
	PUINT pBuffer,
	unsigned int uiOffset,
	unsigned int uiNumBytes,
	BOOLEAN bVerify);

static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter);

static int ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, unsigned int dwAddress, unsigned int *pdwData, unsigned int dwNumData);

/* Procedure:	ReadEEPROMStatusRegister
 *
 * Description: Reads the standard EEPROM Status Register.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 * Returns:
 *		OSAL_STATUS_CODE
 */
static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter)
{
	UCHAR uiData = 0;
	DWORD dwRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
	unsigned int uiStatus = 0;
	unsigned int value = 0;
	unsigned int value1 = 0;

	/* Read the EEPROM status register */
	value = EEPROM_READ_STATUS_REGISTER;
	wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));

	while (dwRetries != 0) {
		value = 0;
		uiStatus = 0;
		rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
		if (Adapter->device_removed == TRUE) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting....");
			break;
		}

		/* Wait for Avail bit to be set. */
		if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) {
			/* Clear the Avail/Full bits - which ever is set. */
			value = uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL);
			wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));

			value = 0;
			rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));
			uiData = (UCHAR)value;

			break;
		}

		dwRetries--;
		if (dwRetries == 0) {
			rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
			rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1));
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x3004 = %x 0x3008 = %x, retries = %d failed.\n", value, value1, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY);
			return uiData;
		}
		if (!(dwRetries%RETRIES_PER_DELAY))
			udelay(1000);
		uiStatus = 0 ;
	}
	return uiData;
} /* ReadEEPROMStatusRegister */

/*
 * Procedure:	ReadBeceemEEPROMBulk
 *
 * Description: This routine reads 16Byte data from EEPROM
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *      dwAddress   - EEPROM Offset to read the data from.
 *      pdwData     - Pointer to double word where data needs to be stored in.  //		dwNumWords  - Number of words.  Valid values are 4 ONLY.
 *
 * Returns:
 *		OSAL_STATUS_CODE:
 */

int ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter,
			DWORD dwAddress,
			DWORD *pdwData,
			DWORD dwNumWords)
{
	DWORD dwIndex = 0;
	DWORD dwRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
	unsigned int uiStatus  = 0;
	unsigned int value = 0;
	unsigned int value1 = 0;
	UCHAR *pvalue;

	/* Flush the read and cmd queue. */
	value = (EEPROM_READ_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH);
	wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
	value = 0;
	wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));

	/* Clear the Avail/Full bits. */
	value = (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL);
	wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));

	value = dwAddress | ((dwNumWords == 4) ? EEPROM_16_BYTE_PAGE_READ : EEPROM_4_BYTE_PAGE_READ);
	wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));

	while (dwRetries != 0) {
		uiStatus = 0;
		rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
		if (Adapter->device_removed == TRUE) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got Removed.hence exiting from loop...");
			return -ENODEV;
		}

		/* If we are reading 16 bytes we want to be sure that the queue
		 * is full before we read.  In the other cases we are ok if the
		 * queue has data available
		 */
		if (dwNumWords == 4) {
			if ((uiStatus & EEPROM_READ_DATA_FULL) != 0) {
				/* Clear the Avail/Full bits - which ever is set. */
				value = (uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL));
				wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
				break;
			}
		} else if (dwNumWords == 1) {
			if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) {
				/* We just got Avail and we have to read 32bits so we
				 * need this sleep for Cardbus kind of devices.
				 */
				if (Adapter->chip_id == 0xBECE0210)
					udelay(800);

				/* Clear the Avail/Full bits - which ever is set. */
				value = (uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL));
				wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
				break;
			}
		}

		uiStatus = 0;

		dwRetries--;
		if (dwRetries == 0) {
			value = 0;
			value1 = 0;
			rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
			rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1));
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "dwNumWords %d 0x3004 = %x 0x3008 = %x  retries = %d failed.\n",
					dwNumWords, value,  value1,  MAX_EEPROM_RETRIES * RETRIES_PER_DELAY);
			return STATUS_FAILURE;
		}

		if (!(dwRetries%RETRIES_PER_DELAY))
			udelay(1000);
	}

	for (dwIndex = 0; dwIndex < dwNumWords; dwIndex++) {
		/* We get only a byte at a time - from LSB to MSB. We shift it into an integer. */
		pvalue = (PUCHAR)(pdwData + dwIndex);

		value = 0;
		rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));

		pvalue[0] = value;

		value = 0;
		rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));

		pvalue[1] = value;

		value = 0;
		rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));

		pvalue[2] = value;

		value = 0;
		rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value));

		pvalue[3] = value;
	}

	return STATUS_SUCCESS;
} /* ReadBeceemEEPROMBulk() */

/*
 * Procedure:	ReadBeceemEEPROM
 *
 * Description: This routine reads 4 data from EEPROM.  It uses 1 or 2 page
 *				reads to do this operation.
 *
 * Arguments:
 *		Adapter     - ptr to Adapter object instance
 *      uiOffset	- EEPROM Offset to read the data from.
 *      pBuffer		- Pointer to word where data needs to be stored in.
 *
 * Returns:
 *		OSAL_STATUS_CODE:
 */

int ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter,
		DWORD uiOffset,
		DWORD *pBuffer)
{
	unsigned int uiData[8]		= {0};
	unsigned int uiByteOffset	= 0;
	unsigned int uiTempOffset	= 0;

	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ====> ");

	uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE);
	uiByteOffset = uiOffset - uiTempOffset;

	ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4);

	/* A word can overlap at most over 2 pages. In that case we read the
	 * next page too.
	 */
	if (uiByteOffset > 12)
		ReadBeceemEEPROMBulk(Adapter, uiTempOffset + MAX_RW_SIZE, (PUINT)&uiData[4], 4);

	memcpy((PUCHAR)pBuffer, (((PUCHAR)&uiData[0]) + uiByteOffset), 4);

	return STATUS_SUCCESS;
} /* ReadBeceemEEPROM() */

int ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter)
{
	int Status;
	unsigned char puMacAddr[6];

	Status = BeceemNVMRead(Adapter,
			(PUINT)&puMacAddr[0],
			INIT_PARAMS_1_MACADDRESS_ADDRESS,
			MAC_ADDRESS_SIZE);

	if (Status == STATUS_SUCCESS)
		memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE);

	return Status;
}

/*
 * Procedure:	BeceemEEPROMBulkRead
 *
 * Description: Reads the EEPROM and returns the Data.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *		pBuffer    - Buffer to store the data read from EEPROM
 *		uiOffset   - Offset of EEPROM from where data should be read
 *		uiNumBytes - Number of bytes to be read from the EEPROM.
 *
 * Returns:
 *		OSAL_STATUS_SUCCESS - if EEPROM read is successful.
 *		<FAILURE>			- if failed.
 */

int BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter,
			PUINT pBuffer,
			unsigned int uiOffset,
			unsigned int uiNumBytes)
{
	unsigned int uiData[4]		= {0};
	/* unsigned int uiAddress	= 0; */
	unsigned int uiBytesRemaining	= uiNumBytes;
	unsigned int uiIndex		= 0;
	unsigned int uiTempOffset	= 0;
	unsigned int uiExtraBytes	= 0;
	unsigned int uiFailureRetries	= 0;
	PUCHAR pcBuff = (PUCHAR)pBuffer;

	if (uiOffset % MAX_RW_SIZE && uiBytesRemaining) {
		uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE);
		uiExtraBytes = uiOffset - uiTempOffset;
		ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4);
		if (uiBytesRemaining >= (MAX_RW_SIZE - uiExtraBytes)) {
			memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), MAX_RW_SIZE - uiExtraBytes);
			uiBytesRemaining -= (MAX_RW_SIZE - uiExtraBytes);
			uiIndex += (MAX_RW_SIZE - uiExtraBytes);
			uiOffset += (MAX_RW_SIZE - uiExtraBytes);
		} else {
			memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), uiBytesRemaining);
			uiIndex += uiBytesRemaining;
			uiOffset += uiBytesRemaining;
			uiBytesRemaining = 0;
		}
	}

	while (uiBytesRemaining && uiFailureRetries != 128) {
		if (Adapter->device_removed)
			return -1;

		if (uiBytesRemaining >= MAX_RW_SIZE) {
			/* For the requests more than or equal to 16 bytes, use bulk
			 * read function to make the access faster.
			 * We read 4 Dwords of data
			 */
			if (ReadBeceemEEPROMBulk(Adapter, uiOffset, &uiData[0], 4) == 0) {
				memcpy(pcBuff + uiIndex, &uiData[0], MAX_RW_SIZE);
				uiOffset += MAX_RW_SIZE;
				uiBytesRemaining -= MAX_RW_SIZE;
				uiIndex += MAX_RW_SIZE;
			} else {
				uiFailureRetries++;
				mdelay(3); /* sleep for a while before retry... */
			}
		} else if (uiBytesRemaining >= 4) {
			if (ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0]) == 0) {
				memcpy(pcBuff + uiIndex, &uiData[0], 4);
				uiOffset += 4;
				uiBytesRemaining -= 4;
				uiIndex += 4;
			} else {
				uiFailureRetries++;
				mdelay(3); /* sleep for a while before retry... */
			}
		} else {
			/* Handle the reads less than 4 bytes... */
			PUCHAR pCharBuff = (PUCHAR)pBuffer;
			pCharBuff += uiIndex;
			if (ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0]) == 0) {
				memcpy(pCharBuff, &uiData[0], uiBytesRemaining); /* copy only bytes requested. */
				uiBytesRemaining = 0;
			} else {
				uiFailureRetries++;
				mdelay(3); /* sleep for a while before retry... */
			}
		}
	}

	return 0;
}

/*
 * Procedure:	BeceemFlashBulkRead
 *
 * Description: Reads the FLASH and returns the Data.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *		pBuffer    - Buffer to store the data read from FLASH
 *		uiOffset   - Offset of FLASH from where data should be read
 *		uiNumBytes - Number of bytes to be read from the FLASH.
 *
 * Returns:
 *		OSAL_STATUS_SUCCESS - if FLASH read is successful.
 *		<FAILURE>			- if failed.
 */

static int BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter,
			PUINT pBuffer,
			unsigned int uiOffset,
			unsigned int uiNumBytes)
{
	unsigned int uiIndex = 0;
	unsigned int uiBytesToRead = uiNumBytes;
	int Status = 0;
	unsigned int uiPartOffset = 0;
	int bytes;

	if (Adapter->device_removed) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device Got Removed");
		return -ENODEV;
	}

	/* Adding flash Base address
	 * uiOffset = uiOffset + GetFlashBaseAddr(Adapter);
	 */
	#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
		Status = bcmflash_raw_read((uiOffset/FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
		return Status;
	#endif

	Adapter->SelectedChip = RESET_CHIP_SELECT;

	if (uiOffset % MAX_RW_SIZE) {
		BcmDoChipSelect(Adapter, uiOffset);
		uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);

		uiBytesToRead = MAX_RW_SIZE - (uiOffset % MAX_RW_SIZE);
		uiBytesToRead = MIN(uiNumBytes, uiBytesToRead);

		bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer + uiIndex, uiBytesToRead);
		if (bytes < 0) {
			Status = bytes;
			Adapter->SelectedChip = RESET_CHIP_SELECT;
			return Status;
		}

		uiIndex += uiBytesToRead;
		uiOffset += uiBytesToRead;
		uiNumBytes -= uiBytesToRead;
	}

	while (uiNumBytes) {
		BcmDoChipSelect(Adapter, uiOffset);
		uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);

		uiBytesToRead = MIN(uiNumBytes, MAX_RW_SIZE);

		bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer + uiIndex, uiBytesToRead);
		if (bytes < 0) {
			Status = bytes;
			break;
		}

		uiIndex += uiBytesToRead;
		uiOffset += uiBytesToRead;
		uiNumBytes -= uiBytesToRead;
	}
	Adapter->SelectedChip = RESET_CHIP_SELECT;
	return Status;
}

/*
 * Procedure:	BcmGetFlashSize
 *
 * Description: Finds the size of FLASH.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *
 * Returns:
 *		unsigned int - size of the FLASH Storage.
 *
 */

static unsigned int BcmGetFlashSize(struct bcm_mini_adapter *Adapter)
{
	if (IsFlash2x(Adapter))
		return Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header);
	else
		return 32 * 1024;
}

/*
 * Procedure:	BcmGetEEPROMSize
 *
 * Description: Finds the size of EEPROM.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *
 * Returns:
 *		unsigned int - size of the EEPROM Storage.
 *
 */

static unsigned int BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter)
{
	unsigned int uiData = 0;
	unsigned int uiIndex = 0;

	/*
	 * if EEPROM is present and already Calibrated,it will have
	 * 'BECM' string at 0th offset.
	 * To find the EEPROM size read the possible boundaries of the
	 * EEPROM like 4K,8K etc..accessing the EEPROM beyond its size will
	 * result in wrap around. So when we get the End of the EEPROM we will
	 * get 'BECM' string which is indeed at offset 0.
	 */
	BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4);
	if (uiData == BECM) {
		for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2)	{
			BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4);
			if (uiData == BECM)
				return uiIndex * 1024;
		}
	} else {
		/*
		 * EEPROM may not be present or not programmed
		 */
		uiData = 0xBABEFACE;
		if (BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&uiData, 0, 4, TRUE) == 0) {
			uiData = 0;
			for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) {
				BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4);
				if (uiData == 0xBABEFACE)
					return uiIndex * 1024;
			}
		}
	}
	return 0;
}

/*
 * Procedure:	FlashSectorErase
 *
 * Description: Finds the sector size of the FLASH.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *		addr	   - sector start address
 *		numOfSectors - number of sectors to  be erased.
 *
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

static int FlashSectorErase(struct bcm_mini_adapter *Adapter,
			unsigned int addr,
			unsigned int numOfSectors)
{
	unsigned int iIndex = 0, iRetries = 0;
	unsigned int uiStatus = 0;
	unsigned int value;
	int bytes;

	for (iIndex = 0; iIndex < numOfSectors; iIndex++) {
		value = 0x06000000;
		wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));

		value = (0xd8000000 | (addr & 0xFFFFFF));
		wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
		iRetries = 0;

		do {
			value = (FLASH_CMD_STATUS_REG_READ << 24);
			if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
				return STATUS_FAILURE;
			}

			bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
			if (bytes < 0) {
				uiStatus = bytes;
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
				return uiStatus;
			}
			iRetries++;
			/* After every try lets make the CPU free for 10 ms. generally time taken by the
			 * the sector erase cycle is 500 ms to 40000 msec. hence sleeping 10 ms
			 * won't hamper performance in any case.
			 */
			mdelay(10);
		} while ((uiStatus & 0x1) && (iRetries < 400));

		if (uiStatus & 0x1) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "iRetries crossing the limit of 80000\n");
			return STATUS_FAILURE;
		}

		addr += Adapter->uiSectorSize;
	}
	return 0;
}
/*
 * Procedure:	flashByteWrite
 *
 * Description: Performs Byte by Byte write to flash
 *
 * Arguments:
 *		Adapter   - ptr to Adapter object instance
 *		uiOffset   - Offset of the flash where data needs to be written to.
 *		pData	- Address of Data to be written.
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

static int flashByteWrite(struct bcm_mini_adapter *Adapter,
			unsigned int uiOffset,
			PVOID pData)
{
	unsigned int uiStatus = 0;
	int  iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */
	unsigned int value;
	ULONG ulData = *(PUCHAR)pData;
	int bytes;
	/*
	 * need not write 0xFF because write requires an erase and erase will
	 * make whole sector 0xFF.
	 */

	if (0xFF == ulData)
		return STATUS_SUCCESS;

	/* DumpDebug(NVM_RW,("flashWrite ====>\n")); */
	value = (FLASH_CMD_WRITE_ENABLE << 24);
	if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails");
		return STATUS_FAILURE;
	}

	if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails");
		return STATUS_FAILURE;
	}
	value = (0x02000000 | (uiOffset & 0xFFFFFF));
	if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails");
		return STATUS_FAILURE;
	}

	/* __udelay(950); */

	do {
		value = (FLASH_CMD_STATUS_REG_READ << 24);
		if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
			return STATUS_FAILURE;
		}
		/* __udelay(1); */
		bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
		if (bytes < 0) {
			uiStatus = bytes;
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
			return uiStatus;
		}
		iRetries--;
		if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0))
			udelay(1000);

	} while ((uiStatus & 0x1) && (iRetries  > 0));

	if (uiStatus & 0x1) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times.");
		return STATUS_FAILURE;
	}

	return STATUS_SUCCESS;
}

/*
 * Procedure:	flashWrite
 *
 * Description: Performs write to flash
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *		uiOffset   - Offset of the flash where data needs to be written to.
 *		pData	- Address of Data to be written.
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

static int flashWrite(struct bcm_mini_adapter *Adapter,
		unsigned int uiOffset,
		PVOID pData)
{
	/* unsigned int uiStatus = 0;
	 * int  iRetries = 0;
	 * unsigned int uiReadBack = 0;
	 */
	unsigned int uiStatus = 0;
	int  iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */
	unsigned int value;
	unsigned int uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
	int bytes;
	/*
	 * need not write 0xFFFFFFFF because write requires an erase and erase will
	 * make whole sector 0xFFFFFFFF.
	 */
	if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE))
		return 0;

	value = (FLASH_CMD_WRITE_ENABLE << 24);

	if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails");
		return STATUS_FAILURE;
	}

	if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails...");
		return STATUS_FAILURE;
	}

	/* __udelay(950); */
	do {
		value = (FLASH_CMD_STATUS_REG_READ << 24);
		if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
			return STATUS_FAILURE;
		}
		/* __udelay(1); */
		bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
		if (bytes < 0) {
			uiStatus = bytes;
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
			return uiStatus;
		}

		iRetries--;
		/* this will ensure that in there will be no changes in the current path.
		 * currently one rdm/wrm takes 125 us.
		 * Hence  125 *2 * FLASH_PER_RETRIES_DELAY > 3 ms(worst case delay)
		 * Hence current implementation cycle will intoduce no delay in current path
		 */
		if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0))
			udelay(1000);
	} while ((uiStatus & 0x1) && (iRetries > 0));

	if (uiStatus & 0x1) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times.");
		return STATUS_FAILURE;
	}

	return STATUS_SUCCESS;
}

/*-----------------------------------------------------------------------------
 * Procedure:	flashByteWriteStatus
 *
 * Description: Performs byte by byte write to flash with write done status check
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *		uiOffset    - Offset of the flash where data needs to be written to.
 *		pData	 - Address of the Data to be written.
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */
static int flashByteWriteStatus(struct bcm_mini_adapter *Adapter,
				unsigned int uiOffset,
				PVOID pData)
{
	unsigned int uiStatus = 0;
	int  iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */
	ULONG ulData  = *(PUCHAR)pData;
	unsigned int value;
	int bytes;

	/*
	 * need not write 0xFFFFFFFF because write requires an erase and erase will
	 * make whole sector 0xFFFFFFFF.
	 */

	if (0xFF == ulData)
		return STATUS_SUCCESS;

	/* DumpDebug(NVM_RW,("flashWrite ====>\n")); */

	value = (FLASH_CMD_WRITE_ENABLE << 24);
	if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails");
		return STATUS_SUCCESS;
	}
	if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails");
		return STATUS_FAILURE;
	}
	value = (0x02000000 | (uiOffset & 0xFFFFFF));
	if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails");
		return STATUS_FAILURE;
	}

	/* msleep(1); */

	do {
		value = (FLASH_CMD_STATUS_REG_READ << 24);
		if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
			return STATUS_FAILURE;
		}
		/* __udelay(1); */
		bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
		if (bytes < 0) {
			uiStatus = bytes;
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
			return uiStatus;
		}

		iRetries--;
		if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0))
			udelay(1000);

	} while ((uiStatus & 0x1) && (iRetries > 0));

	if (uiStatus & 0x1) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times.");
		return STATUS_FAILURE;
	}

	return STATUS_SUCCESS;
}
/*
 * Procedure:	flashWriteStatus
 *
 * Description: Performs write to flash with write done status check
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *		uiOffset    - Offset of the flash where data needs to be written to.
 *		pData	 - Address of the Data to be written.
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

static int flashWriteStatus(struct bcm_mini_adapter *Adapter,
			unsigned int uiOffset,
			PVOID pData)
{
	unsigned int uiStatus = 0;
	int  iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */
	/* unsigned int uiReadBack = 0; */
	unsigned int value;
	unsigned int uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
	int bytes;

	/*
	 * need not write 0xFFFFFFFF because write requires an erase and erase will
	 * make whole sector 0xFFFFFFFF.
	 */
	if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE))
		return 0;

	value = (FLASH_CMD_WRITE_ENABLE << 24);
	if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails");
		return STATUS_FAILURE;
	}

	if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails...");
		return STATUS_FAILURE;
	}
	/* __udelay(1); */

	do {
		value = (FLASH_CMD_STATUS_REG_READ << 24);
		if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails");
			return STATUS_FAILURE;
		}
		/* __udelay(1); */
		bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus));
		if (bytes < 0) {
			uiStatus = bytes;
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails");
			return uiStatus;
		}
		iRetries--;
		/* this will ensure that in there will be no changes in the current path.
		 * currently one rdm/wrm takes 125 us.
		 * Hence  125 *2  * FLASH_PER_RETRIES_DELAY  >3 ms(worst case delay)
		 * Hence current implementation cycle will intoduce no delay in current path
		 */
		if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0))
			udelay(1000);

	} while ((uiStatus & 0x1) && (iRetries > 0));

	if (uiStatus & 0x1) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times.");
		return STATUS_FAILURE;
	}

	return STATUS_SUCCESS;
}

/*
 * Procedure:	BcmRestoreBlockProtectStatus
 *
 * Description: Restores the original block protection status.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *		ulWriteStatus   -Original status
 * Returns:
 *		<VOID>
 *
 */

static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter, ULONG ulWriteStatus)
{
	unsigned int value;
	value = (FLASH_CMD_WRITE_ENABLE << 24);
	wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));

	udelay(20);
	value = (FLASH_CMD_STATUS_REG_WRITE << 24) | (ulWriteStatus << 16);
	wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
	udelay(20);
}

/*
 * Procedure:	BcmFlashUnProtectBlock
 *
 * Description: UnProtects appropriate blocks for writing.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *		uiOffset   - Offset of the flash where data needs to be written to. This should be Sector aligned.
 * Returns:
 *		ULONG   - Status value before UnProtect.
 *
 */

static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter, unsigned int uiOffset, unsigned int uiLength)
{
	ULONG ulStatus		= 0;
	ULONG ulWriteStatus	= 0;
	unsigned int value;

	uiOffset = uiOffset&0x000FFFFF;
	/*
	 * Implemented only for 1MB Flash parts.
	 */
	if (FLASH_PART_SST25VF080B == Adapter->ulFlashID) {
		/*
		 * Get Current BP status.
		 */
		value = (FLASH_CMD_STATUS_REG_READ << 24);
		wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
		udelay(10);
		/*
		 * Read status will be WWXXYYZZ. We have to take only WW.
		 */
		rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulStatus, sizeof(ulStatus));
		ulStatus >>= 24;
		ulWriteStatus = ulStatus;
		/*
		 * Bits [5-2] give current block level protection status.
		 * Bit5: BP3 - DONT CARE
		 * BP2-BP0: 0 - NO PROTECTION, 1 - UPPER 1/16, 2 - UPPER 1/8, 3 - UPPER 1/4
		 *                4 - UPPER 1/2. 5 to 7 - ALL BLOCKS
		 */

		if (ulStatus) {
			if ((uiOffset+uiLength) <= 0x80000) {
				/*
				 * Offset comes in lower half of 1MB. Protect the upper half.
				 * Clear BP1 and BP0 and set BP2.
				 */
				ulWriteStatus |= (0x4<<2);
				ulWriteStatus &= ~(0x3<<2);
			} else if ((uiOffset + uiLength) <= 0xC0000) {
				/*
				 * Offset comes below Upper 1/4. Upper 1/4 can be protected.
				 *  Clear BP2 and set BP1 and BP0.
				 */
				ulWriteStatus |= (0x3<<2);
				ulWriteStatus &= ~(0x1<<4);
			} else if ((uiOffset + uiLength) <= 0xE0000) {
				/*
				 * Offset comes below Upper 1/8. Upper 1/8 can be protected.
				 * Clear BP2 and BP0  and set BP1
				 */
				ulWriteStatus |= (0x1<<3);
				ulWriteStatus &= ~(0x5<<2);
			} else if ((uiOffset + uiLength) <= 0xF0000) {
				/*
				 * Offset comes below Upper 1/16. Only upper 1/16 can be protected.
				 * Set BP0 and Clear BP2,BP1.
				 */
				ulWriteStatus |= (0x1<<2);
				ulWriteStatus &= ~(0x3<<3);
			} else {
				/*
				 * Unblock all.
				 * Clear BP2,BP1 and BP0.
				 */
				ulWriteStatus &= ~(0x7<<2);
			}

			value = (FLASH_CMD_WRITE_ENABLE << 24);
			wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
			udelay(20);
			value = (FLASH_CMD_STATUS_REG_WRITE << 24) | (ulWriteStatus << 16);
			wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
			udelay(20);
		}
	}
	return ulStatus;
}

/*
 * Procedure:	BeceemFlashBulkWrite
 *
 * Description: Performs write to the flash
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 * pBuffer - Data to be written.
 *		uiOffset   - Offset of the flash where data needs to be written to.
 *		uiNumBytes - Number of bytes to be written.
 *		bVerify    - read verify flag.
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

static int BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter,
				PUINT pBuffer,
				unsigned int uiOffset,
				unsigned int uiNumBytes,
				BOOLEAN bVerify)
{
	PCHAR pTempBuff			= NULL;
	PUCHAR pcBuffer			= (PUCHAR)pBuffer;
	unsigned int uiIndex			= 0;
	unsigned int uiOffsetFromSectStart	= 0;
	unsigned int uiSectAlignAddr		= 0;
	unsigned int uiCurrSectOffsetAddr	= 0;
	unsigned int uiSectBoundary		= 0;
	unsigned int uiNumSectTobeRead		= 0;
	UCHAR ucReadBk[16]		= {0};
	ULONG ulStatus			= 0;
	int Status			= STATUS_SUCCESS;
	unsigned int uiTemp			= 0;
	unsigned int index			= 0;
	unsigned int uiPartOffset		= 0;

	#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
		Status = bcmflash_raw_write((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
		return Status;
	#endif

	uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1);

	/* Adding flash Base address
	 * uiOffset = uiOffset + GetFlashBaseAddr(Adapter);
	 */

	uiSectAlignAddr	= uiOffset & ~(Adapter->uiSectorSize - 1);
	uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1);
	uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize;

	pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL);
	if (!pTempBuff)
		goto BeceemFlashBulkWrite_EXIT;
	/*
	 * check if the data to be written is overlapped across sectors
	 */
	if (uiOffset+uiNumBytes < uiSectBoundary) {
		uiNumSectTobeRead = 1;
	} else {
		/* Number of sectors  = Last sector start address/First sector start address */
		uiNumSectTobeRead =  (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize;
		if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize)
			uiNumSectTobeRead++;
	}
	/* Check whether Requested sector is writable or not in case of flash2x write. But if  write call is
	 * for DSD calibration, allow it without checking of sector permission
	 */

	if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) {
		index = 0;
		uiTemp = uiNumSectTobeRead;
		while (uiTemp) {
			if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%X> is not writable",
						(uiOffsetFromSectStart + index * Adapter->uiSectorSize));
				Status = SECTOR_IS_NOT_WRITABLE;
				goto BeceemFlashBulkWrite_EXIT;
			}
			uiTemp = uiTemp - 1;
			index = index + 1 ;
		}
	}
	Adapter->SelectedChip = RESET_CHIP_SELECT;
	while (uiNumSectTobeRead) {
		/* do_gettimeofday(&tv1);
		 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nTime In start of write :%ld ms\n",(tv1.tv_sec *1000 + tv1.tv_usec /1000));
		 */
		uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);

		BcmDoChipSelect(Adapter, uiSectAlignAddr);

		if (0 != BeceemFlashBulkRead(Adapter,
						(PUINT)pTempBuff,
						uiOffsetFromSectStart,
						Adapter->uiSectorSize)) {
			Status = -1;
			goto BeceemFlashBulkWrite_EXIT;
		}

		/* do_gettimeofday(&tr);
		 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Read :%ld ms\n", (tr.tv_sec *1000 + tr.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000));
		 */
		ulStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize);

		if (uiNumSectTobeRead > 1) {
			memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr));
			pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)));
			uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr));
		} else {
			memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes);
		}

		if (IsFlash2x(Adapter))
			SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart);

		FlashSectorErase(Adapter, uiPartOffset, 1);
		/* do_gettimeofday(&te);
		 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Erase :%ld ms\n", (te.tv_sec *1000 + te.tv_usec/1000) - (tr.tv_sec *1000 + tr.tv_usec/1000));
		 */
		for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) {
			if (Adapter->device_removed) {
				Status = -1;
				goto BeceemFlashBulkWrite_EXIT;
			}

			if (STATUS_SUCCESS != (*Adapter->fpFlashWrite)(Adapter, uiPartOffset + uiIndex, (&pTempBuff[uiIndex]))) {
				Status = -1;
				goto BeceemFlashBulkWrite_EXIT;
			}
		}

		/* do_gettimeofday(&tw);
		 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write  to Flash :%ld ms\n", (tw.tv_sec *1000 + tw.tv_usec/1000) - (te.tv_sec *1000 + te.tv_usec/1000));
		 */
		for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) {
			if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) {
				if (Adapter->ulFlashWriteSize == 1) {
					unsigned int uiReadIndex = 0;
					for (uiReadIndex = 0; uiReadIndex < 16; uiReadIndex++) {
						if (ucReadBk[uiReadIndex] != pTempBuff[uiIndex + uiReadIndex]) {
							if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex + uiReadIndex, &pTempBuff[uiIndex+uiReadIndex])) {
								Status = STATUS_FAILURE;
								goto BeceemFlashBulkWrite_EXIT;
							}
						}
					}
				} else {
					if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) {
						if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset + uiIndex, &pTempBuff[uiIndex])) {
							Status = STATUS_FAILURE;
							goto BeceemFlashBulkWrite_EXIT;
						}
					}
				}
			}
		}
		/* do_gettimeofday(&twv);
		 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write  to Flash verification :%ld ms\n", (twv.tv_sec *1000 + twv.tv_usec/1000) - (tw.tv_sec *1000 + tw.tv_usec/1000));
		 */
		if (ulStatus) {
			BcmRestoreBlockProtectStatus(Adapter, ulStatus);
			ulStatus = 0;
		}

		uiCurrSectOffsetAddr = 0;
		uiSectAlignAddr = uiSectBoundary;
		uiSectBoundary += Adapter->uiSectorSize;
		uiOffsetFromSectStart += Adapter->uiSectorSize;
		uiNumSectTobeRead--;
	}
	/* do_gettimeofday(&tv2);
	 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Time after Write :%ld ms\n",(tv2.tv_sec *1000 + tv2.tv_usec/1000));
	 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by in Write is :%ld ms\n", (tv2.tv_sec *1000 + tv2.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000));
	 *
	 * Cleanup.
	 */
BeceemFlashBulkWrite_EXIT:
	if (ulStatus)
		BcmRestoreBlockProtectStatus(Adapter, ulStatus);

	kfree(pTempBuff);

	Adapter->SelectedChip = RESET_CHIP_SELECT;
	return Status;
}

/*
 * Procedure:	BeceemFlashBulkWriteStatus
 *
 * Description: Writes to Flash. Checks the SPI status after each write.
 *
 * Arguments:
 *		Adapter		- ptr to Adapter object instance
 *		pBuffer		- Data to be written.
 *		uiOffset	- Offset of the flash where data needs to be written to.
 *		uiNumBytes	- Number of bytes to be written.
 *		bVerify		- read verify flag.
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

static int BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter,
				PUINT pBuffer,
				unsigned int uiOffset,
				unsigned int uiNumBytes,
				BOOLEAN bVerify)
{
	PCHAR pTempBuff			= NULL;
	PUCHAR pcBuffer			= (PUCHAR)pBuffer;
	unsigned int uiIndex			= 0;
	unsigned int uiOffsetFromSectStart	= 0;
	unsigned int uiSectAlignAddr		= 0;
	unsigned int uiCurrSectOffsetAddr	= 0;
	unsigned int uiSectBoundary		= 0;
	unsigned int uiNumSectTobeRead		= 0;
	UCHAR ucReadBk[16]		= {0};
	ULONG ulStatus			= 0;
	unsigned int Status			= STATUS_SUCCESS;
	unsigned int uiTemp			= 0;
	unsigned int index			= 0;
	unsigned int uiPartOffset		= 0;

	uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1);

	/* uiOffset += Adapter->ulFlashCalStart;
	 * Adding flash Base address
	 * uiOffset = uiOffset + GetFlashBaseAddr(Adapter);
	 */
	uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);
	uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1);
	uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize;

	pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL);
	if (!pTempBuff)
		goto BeceemFlashBulkWriteStatus_EXIT;

	/*
	 * check if the data to be written is overlapped across sectors
	 */
	if (uiOffset+uiNumBytes < uiSectBoundary) {
		uiNumSectTobeRead = 1;
	} else {
		/* Number of sectors  = Last sector start address/First sector start address */
		uiNumSectTobeRead =  (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize;
		if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize)
			uiNumSectTobeRead++;
	}

	if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) {
		index = 0;
		uiTemp = uiNumSectTobeRead;
		while (uiTemp) {
			if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == FALSE) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%x> is not writable",
						(uiOffsetFromSectStart + index * Adapter->uiSectorSize));
				Status = SECTOR_IS_NOT_WRITABLE;
				goto BeceemFlashBulkWriteStatus_EXIT;
			}
			uiTemp = uiTemp - 1;
			index = index + 1 ;
		}
	}

	Adapter->SelectedChip = RESET_CHIP_SELECT;
	while (uiNumSectTobeRead) {
		uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);

		BcmDoChipSelect(Adapter, uiSectAlignAddr);
		if (0 != BeceemFlashBulkRead(Adapter,
						(PUINT)pTempBuff,
						uiOffsetFromSectStart,
						Adapter->uiSectorSize))	{
			Status = -1;
			goto BeceemFlashBulkWriteStatus_EXIT;
		}

		ulStatus = BcmFlashUnProtectBlock(Adapter, uiOffsetFromSectStart, Adapter->uiSectorSize);

		if (uiNumSectTobeRead > 1) {
			memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr));
			pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)));
			uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr));
		} else {
			memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes);
		}

		if (IsFlash2x(Adapter))
			SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart);

		FlashSectorErase(Adapter, uiPartOffset, 1);

		for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) {
			if (Adapter->device_removed) {
				Status = -1;
				goto BeceemFlashBulkWriteStatus_EXIT;
			}

			if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset+uiIndex, &pTempBuff[uiIndex])) {
				Status = -1;
				goto BeceemFlashBulkWriteStatus_EXIT;
			}
		}

		if (bVerify) {
			for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) {
				if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) {
					if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) {
						Status = STATUS_FAILURE;
						goto BeceemFlashBulkWriteStatus_EXIT;
					}
				}
			}
		}

		if (ulStatus) {
			BcmRestoreBlockProtectStatus(Adapter, ulStatus);
			ulStatus = 0;
		}

		uiCurrSectOffsetAddr = 0;
		uiSectAlignAddr = uiSectBoundary;
		uiSectBoundary += Adapter->uiSectorSize;
		uiOffsetFromSectStart += Adapter->uiSectorSize;
		uiNumSectTobeRead--;
	}
/*
 * Cleanup.
 */
BeceemFlashBulkWriteStatus_EXIT:
	if (ulStatus)
		BcmRestoreBlockProtectStatus(Adapter, ulStatus);

	kfree(pTempBuff);
	Adapter->SelectedChip = RESET_CHIP_SELECT;
	return Status;
}

/*
 * Procedure:	PropagateCalParamsFromEEPROMToMemory
 *
 * Description: Dumps the calibration section of EEPROM to DDR.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

int PropagateCalParamsFromEEPROMToMemory(struct bcm_mini_adapter *Adapter)
{
	PCHAR pBuff = kmalloc(BUFFER_4K, GFP_KERNEL);
	unsigned int uiEepromSize = 0;
	unsigned int uiIndex = 0;
	unsigned int uiBytesToCopy = 0;
	unsigned int uiCalStartAddr = EEPROM_CALPARAM_START;
	unsigned int uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC;
	unsigned int value;
	int Status = 0;

	if (!pBuff)
		return -ENOMEM;

	if (0 != BeceemEEPROMBulkRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4)) {
		kfree(pBuff);
		return -1;
	}

	uiEepromSize >>= 16;
	if (uiEepromSize > 1024 * 1024) {
		kfree(pBuff);
		return -1;
	}

	uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);

	while (uiBytesToCopy) {
		if (0 != BeceemEEPROMBulkRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiBytesToCopy)) {
			Status = -1;
			break;
		}
		wrm(Adapter, uiMemoryLoc, (PCHAR)(((PULONG)pBuff) + uiIndex), uiBytesToCopy);
		uiMemoryLoc += uiBytesToCopy;
		uiEepromSize -= uiBytesToCopy;
		uiCalStartAddr += uiBytesToCopy;
		uiIndex += uiBytesToCopy / 4;
		uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);

	}
	value = 0xbeadbead;
	wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
	value = 0xbeadbead;
	wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
	kfree(pBuff);

	return Status;
}

/*
 * Procedure:	PropagateCalParamsFromFlashToMemory
 *
 * Description: Dumps the calibration section of EEPROM to DDR.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

int PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter)
{
	PCHAR pBuff, pPtr;
	unsigned int uiEepromSize = 0;
	unsigned int uiBytesToCopy = 0;
	/* unsigned int uiIndex = 0; */
	unsigned int uiCalStartAddr = EEPROM_CALPARAM_START;
	unsigned int uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC;
	unsigned int value;
	int Status = 0;

	/*
	 * Write the signature first. This will ensure firmware does not access EEPROM.
	 */
	value = 0xbeadbead;
	wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
	value = 0xbeadbead;
	wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));

	if (0 != BeceemNVMRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4))
		return -1;

	uiEepromSize = ntohl(uiEepromSize);
	uiEepromSize >>= 16;

	/*
	 * subtract the auto init section size
	 */
	uiEepromSize -= EEPROM_CALPARAM_START;

	if (uiEepromSize > 1024 * 1024)
		return -1;

	pBuff = kmalloc(uiEepromSize, GFP_KERNEL);
	if (pBuff == NULL)
		return -ENOMEM;

	if (0 != BeceemNVMRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiEepromSize)) {
		kfree(pBuff);
		return -1;
	}

	pPtr = pBuff;

	uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);

	while (uiBytesToCopy) {
		Status = wrm(Adapter, uiMemoryLoc, (PCHAR)pPtr, uiBytesToCopy);
		if (Status) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm failed with status :%d", Status);
			break;
		}

		pPtr += uiBytesToCopy;
		uiEepromSize -= uiBytesToCopy;
		uiMemoryLoc += uiBytesToCopy;
		uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);
	}

	kfree(pBuff);
	return Status;
}

/*
 * Procedure:	BeceemEEPROMReadBackandVerify
 *
 * Description: Read back the data written and verifies.
 *
 * Arguments:
 *		Adapter		- ptr to Adapter object instance
 *		pBuffer		- Data to be written.
 *		uiOffset	- Offset of the flash where data needs to be written to.
 *		uiNumBytes	- Number of bytes to be written.
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

static int BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter,
					PUINT pBuffer,
					unsigned int uiOffset,
					unsigned int uiNumBytes)
{
	unsigned int uiRdbk	= 0;
	unsigned int uiIndex	= 0;
	unsigned int uiData	= 0;
	unsigned int auiData[4]	= {0};

	while (uiNumBytes) {
		if (Adapter->device_removed)
			return -1;

		if (uiNumBytes >= MAX_RW_SIZE) {
			/* for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. */
			BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE);

			if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) {
				/* re-write */
				BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, MAX_RW_SIZE, FALSE);
				mdelay(3);
				BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE);

				if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE))
					return -1;
			}
			uiOffset += MAX_RW_SIZE;
			uiNumBytes -= MAX_RW_SIZE;
			uiIndex += 4;
		} else if (uiNumBytes >= 4) {
			BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4);
			if (uiData != pBuffer[uiIndex]) {
				/* re-write */
				BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, 4, FALSE);
				mdelay(3);
				BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4);
				if (uiData != pBuffer[uiIndex])
					return -1;
			}
			uiOffset += 4;
			uiNumBytes -= 4;
			uiIndex++;
		} else {
			/* Handle the reads less than 4 bytes... */
			uiData = 0;
			memcpy(&uiData, ((PUCHAR)pBuffer) + (uiIndex * sizeof(unsigned int)), uiNumBytes);
			BeceemEEPROMBulkRead(Adapter, &uiRdbk, uiOffset, 4);

			if (memcmp(&uiData, &uiRdbk, uiNumBytes))
				return -1;

			uiNumBytes = 0;
		}
	}

	return 0;
}

static VOID BcmSwapWord(unsigned int *ptr1)
{
	unsigned int tempval = (unsigned int)*ptr1;
	char *ptr2 = (char *)&tempval;
	char *ptr = (char *)ptr1;

	ptr[0] = ptr2[3];
	ptr[1] = ptr2[2];
	ptr[2] = ptr2[1];
	ptr[3] = ptr2[0];
}

/*
 * Procedure:	BeceemEEPROMWritePage
 *
 * Description: Performs page write (16bytes) to the EEPROM
 *
 * Arguments:
 *		Adapter		- ptr to Adapter object instance
 *		uiData		- Data to be written.
 *		uiOffset	- Offset of the EEPROM where data needs to be written to.
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

static int BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, unsigned int uiData[], unsigned int uiOffset)
{
	unsigned int uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
	unsigned int uiStatus = 0;
	UCHAR uiEpromStatus = 0;
	unsigned int value = 0;

	/* Flush the Write/Read/Cmd queues. */
	value = (EEPROM_WRITE_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH | EEPROM_READ_QUEUE_FLUSH);
	wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
	value = 0;
	wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));

	/* Clear the Empty/Avail/Full bits.  After this it has been confirmed
	 * that the bit was cleared by reading back the register. See NOTE below.
	 * We also clear the Read queues as we do a EEPROM status register read
	 * later.
	 */
	value = (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL | EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL);
	wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));

	/* Enable write */
	value = EEPROM_WRITE_ENABLE;
	wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));

	/* We can write back to back 8bits * 16 into the queue and as we have
	 * checked for the queue to be empty we can write in a burst.
	 */

	value = uiData[0];
	BcmSwapWord(&value);
	wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);

	value = uiData[1];
	BcmSwapWord(&value);
	wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);

	value = uiData[2];
	BcmSwapWord(&value);
	wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);

	value = uiData[3];
	BcmSwapWord(&value);
	wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);

	/* NOTE : After this write, on readback of EEPROM_SPI_Q_STATUS1_REG
	 * shows that we see 7 for the EEPROM data write.  Which means that
	 * queue got full, also space is available as well as the queue is empty.
	 * This may happen in sequence.
	 */
	value =  EEPROM_16_BYTE_PAGE_WRITE | uiOffset;
	wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));

	/* Ideally we should loop here without tries and eventually succeed.
	 * What we are checking if the previous write has completed, and this
	 * may take time. We should wait till the Empty bit is set.
	 */
	uiStatus = 0;
	rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
	while ((uiStatus & EEPROM_WRITE_QUEUE_EMPTY) == 0) {
		uiRetries--;
		if (uiRetries == 0) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, %d retries failed.\n", uiStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY);
			return STATUS_FAILURE;
		}

		if (!(uiRetries%RETRIES_PER_DELAY))
			udelay(1000);

		uiStatus = 0;
		rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
		if (Adapter->device_removed == TRUE) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem got removed hence exiting from loop....");
			return -ENODEV;
		}
	}

	if (uiRetries != 0) {
		/* Clear the ones that are set - either, Empty/Full/Avail bits */
		value = (uiStatus & (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL));
		wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
	}

	/* Here we should check if the EEPROM status register is correct before
	 * proceeding. Bit 0 in the EEPROM Status register should be 0 before
	 * we proceed further.  A 1 at Bit 0 indicates that the EEPROM is busy
	 * with the previous write. Note also that issuing this read finally
	 * means the previous write to the EEPROM has completed.
	 */
	uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
	uiEpromStatus = 0;
	while (uiRetries != 0) {
		uiEpromStatus = ReadEEPROMStatusRegister(Adapter);
		if (Adapter->device_removed == TRUE) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting from loop...");
			return -ENODEV;
		}
		if ((EEPROM_STATUS_REG_WRITE_BUSY & uiEpromStatus) == 0) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM status register = %x tries = %d\n", uiEpromStatus, (MAX_EEPROM_RETRIES * RETRIES_PER_DELAY - uiRetries));
			return STATUS_SUCCESS;
		}
		uiRetries--;
		if (uiRetries == 0) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, for EEPROM status read %d retries failed.\n", uiEpromStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY);
			return STATUS_FAILURE;
		}
		uiEpromStatus = 0;
		if (!(uiRetries%RETRIES_PER_DELAY))
			udelay(1000);
	}

	return STATUS_SUCCESS;
} /* BeceemEEPROMWritePage */

/*
 * Procedure:	BeceemEEPROMBulkWrite
 *
 * Description: Performs write to the EEPROM
 *
 * Arguments:
 *		Adapter		- ptr to Adapter object instance
 *		pBuffer		- Data to be written.
 *		uiOffset	- Offset of the EEPROM where data needs to be written to.
 *		uiNumBytes	- Number of bytes to be written.
 *		bVerify		- read verify flag.
 * Returns:
 *		OSAL_STATUS_CODE
 *
 */

int BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter,
			PUCHAR pBuffer,
			unsigned int uiOffset,
			unsigned int uiNumBytes,
			BOOLEAN bVerify)
{
	unsigned int uiBytesToCopy	= uiNumBytes;
	/* unsigned int uiRdbk		= 0; */
	unsigned int uiData[4]		= {0};
	unsigned int uiIndex		= 0;
	unsigned int uiTempOffset	= 0;
	unsigned int uiExtraBytes	= 0;
	/* PUINT puiBuffer	= (PUINT)pBuffer;
	 * int value;
	 */

	if (uiOffset % MAX_RW_SIZE && uiBytesToCopy) {
		uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE);
		uiExtraBytes = uiOffset - uiTempOffset;

		BeceemEEPROMBulkRead(Adapter, &uiData[0], uiTempOffset, MAX_RW_SIZE);

		if (uiBytesToCopy >= (16 - uiExtraBytes)) {
			memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, MAX_RW_SIZE - uiExtraBytes);

			if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset))
				return STATUS_FAILURE;

			uiBytesToCopy -= (MAX_RW_SIZE - uiExtraBytes);
			uiIndex += (MAX_RW_SIZE - uiExtraBytes);
			uiOffset += (MAX_RW_SIZE - uiExtraBytes);
		} else {
			memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, uiBytesToCopy);

			if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset))
				return STATUS_FAILURE;

			uiIndex += uiBytesToCopy;
			uiOffset += uiBytesToCopy;
			uiBytesToCopy = 0;
		}
	}

	while (uiBytesToCopy) {
		if (Adapter->device_removed)
			return -1;

		if (uiBytesToCopy >= MAX_RW_SIZE) {
			if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, (PUINT) &pBuffer[uiIndex], uiOffset))
				return STATUS_FAILURE;

			uiIndex += MAX_RW_SIZE;
			uiOffset += MAX_RW_SIZE;
			uiBytesToCopy -= MAX_RW_SIZE;
		} else {
			/*
			 * To program non 16byte aligned data, read 16byte and then update.
			 */
			BeceemEEPROMBulkRead(Adapter, &uiData[0], uiOffset, 16);
			memcpy(&uiData[0], pBuffer + uiIndex, uiBytesToCopy);

			if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiOffset))
				return STATUS_FAILURE;

			uiBytesToCopy = 0;
		}
	}

	return 0;
}

/*
 * Procedure:	BeceemNVMRead
 *
 * Description: Reads n number of bytes from NVM.
 *
 * Arguments:
 *		Adapter      - ptr to Adapter object instance
 *		pBuffer       - Buffer to store the data read from NVM
 *		uiOffset       - Offset of NVM from where data should be read
 *		uiNumBytes - Number of bytes to be read from the NVM.
 *
 * Returns:
 *		OSAL_STATUS_SUCCESS - if NVM read is successful.
 *		<FAILURE>			- if failed.
 */

int BeceemNVMRead(struct bcm_mini_adapter *Adapter,
		PUINT pBuffer,
		unsigned int uiOffset,
		unsigned int uiNumBytes)
{
	int Status = 0;

	#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
		unsigned int uiTemp = 0, value;
	#endif

	if (Adapter->eNVMType == NVM_FLASH) {
		if (Adapter->bFlashRawRead == FALSE) {
			if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD))
				return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes);

			uiOffset = uiOffset + Adapter->ulFlashCalStart;
		}

		#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
			Status = bcmflash_raw_read((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
		#else
			rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
			value = 0;
			wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
			Status = BeceemFlashBulkRead(Adapter,
						pBuffer,
						uiOffset,
						uiNumBytes);
			wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
		#endif
	} else if (Adapter->eNVMType == NVM_EEPROM) {
		Status = BeceemEEPROMBulkRead(Adapter,
					pBuffer,
					uiOffset,
					uiNumBytes);
	} else {
		Status = -1;
	}

	return Status;
}

/*
 * Procedure:	BeceemNVMWrite
 *
 * Description: Writes n number of bytes to NVM.
 *
 * Arguments:
 *		Adapter      - ptr to Adapter object instance
 *		pBuffer       - Buffer contains the data to be written.
 *		uiOffset       - Offset of NVM where data to be written to.
 *		uiNumBytes - Number of bytes to be written..
 *
 * Returns:
 *		OSAL_STATUS_SUCCESS - if NVM write is successful.
 *		<FAILURE>			- if failed.
 */

int BeceemNVMWrite(struct bcm_mini_adapter *Adapter,
		PUINT pBuffer,
		unsigned int uiOffset,
		unsigned int uiNumBytes,
		BOOLEAN bVerify)
{
	int Status = 0;
	unsigned int uiTemp = 0;
	unsigned int uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC;
	unsigned int uiIndex = 0;

	#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
		unsigned int value;
	#endif

	unsigned int uiFlashOffset = 0;

	if (Adapter->eNVMType == NVM_FLASH) {
		if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD))
			Status = vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes, bVerify);
		else {
			uiFlashOffset = uiOffset + Adapter->ulFlashCalStart;

			#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
				Status = bcmflash_raw_write((uiFlashOffset / FLASH_PART_SIZE), (uiFlashOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
			#else
				rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
				value = 0;
				wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));

				if (Adapter->bStatusWrite == TRUE)
					Status = BeceemFlashBulkWriteStatus(Adapter,
									pBuffer,
									uiFlashOffset,
									uiNumBytes ,
									bVerify);
				else

					Status = BeceemFlashBulkWrite(Adapter,
								pBuffer,
								uiFlashOffset,
								uiNumBytes,
								bVerify);
			#endif
		}

		if (uiOffset >= EEPROM_CALPARAM_START) {
			uiMemoryLoc += (uiOffset - EEPROM_CALPARAM_START);
			while (uiNumBytes) {
				if (uiNumBytes > BUFFER_4K) {
					wrm(Adapter, (uiMemoryLoc+uiIndex), (PCHAR)(pBuffer + (uiIndex / 4)), BUFFER_4K);
					uiNumBytes -= BUFFER_4K;
					uiIndex += BUFFER_4K;
				} else {
					wrm(Adapter, uiMemoryLoc+uiIndex, (PCHAR)(pBuffer + (uiIndex / 4)), uiNumBytes);
					uiNumBytes = 0;
					break;
				}
			}
		} else {
			if ((uiOffset + uiNumBytes) > EEPROM_CALPARAM_START) {
				ULONG ulBytesTobeSkipped = 0;
				PUCHAR pcBuffer = (PUCHAR)pBuffer; /* char pointer to take care of odd byte cases. */
				uiNumBytes -= (EEPROM_CALPARAM_START - uiOffset);
				ulBytesTobeSkipped += (EEPROM_CALPARAM_START - uiOffset);
				uiOffset += (EEPROM_CALPARAM_START - uiOffset);
				while (uiNumBytes) {
					if (uiNumBytes > BUFFER_4K) {
						wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], BUFFER_4K);
						uiNumBytes -= BUFFER_4K;
						uiIndex += BUFFER_4K;
					} else {
						wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], uiNumBytes);
						uiNumBytes = 0;
						break;
					}
				}
			}
		}
		/* restore the values. */
		wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
	} else if (Adapter->eNVMType == NVM_EEPROM) {
		Status = BeceemEEPROMBulkWrite(Adapter,
					(PUCHAR)pBuffer,
					uiOffset,
					uiNumBytes,
					bVerify);
		if (bVerify)
			Status = BeceemEEPROMReadBackandVerify(Adapter, (PUINT)pBuffer, uiOffset, uiNumBytes);
	} else {
		Status = -1;
	}
	return Status;
}

/*
 * Procedure:	BcmUpdateSectorSize
 *
 * Description: Updates the sector size to FLASH.
 *
 * Arguments:
 *		Adapter       - ptr to Adapter object instance
 *          uiSectorSize - sector size
 *
 * Returns:
 *		OSAL_STATUS_SUCCESS - if NVM write is successful.
 *		<FAILURE>			- if failed.
 */

int BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, unsigned int uiSectorSize)
{
	int Status = -1;
	struct bcm_flash_cs_info sFlashCsInfo = {0};
	unsigned int uiTemp = 0;
	unsigned int uiSectorSig = 0;
	unsigned int uiCurrentSectorSize = 0;
	unsigned int value;

	rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
	value = 0;
	wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));

	/*
	 * Before updating the sector size in the reserved area, check if already present.
	 */
	BeceemFlashBulkRead(Adapter, (PUINT)&sFlashCsInfo, Adapter->ulFlashControlSectionStart, sizeof(sFlashCsInfo));
	uiSectorSig = ntohl(sFlashCsInfo.FlashSectorSizeSig);
	uiCurrentSectorSize = ntohl(sFlashCsInfo.FlashSectorSize);

	if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) {
		if ((uiCurrentSectorSize <= MAX_SECTOR_SIZE) && (uiCurrentSectorSize >= MIN_SECTOR_SIZE)) {
			if (uiSectorSize == uiCurrentSectorSize) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Provided sector size is same as programmed in Flash");
				Status = STATUS_SUCCESS;
				goto Restore;
			}
		}
	}

	if ((uiSectorSize <= MAX_SECTOR_SIZE) && (uiSectorSize >= MIN_SECTOR_SIZE)) {
		sFlashCsInfo.FlashSectorSize = htonl(uiSectorSize);
		sFlashCsInfo.FlashSectorSizeSig = htonl(FLASH_SECTOR_SIZE_SIG);

		Status = BeceemFlashBulkWrite(Adapter,
					(PUINT)&sFlashCsInfo,
					Adapter->ulFlashControlSectionStart,
					sizeof(sFlashCsInfo),
					TRUE);
	}

Restore:
	/* restore the values. */
	wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));

	return Status;
}

/*
 * Procedure:	BcmGetFlashSectorSize
 *
 * Description: Finds the sector size of the FLASH.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *
 * Returns:
 *		unsigned int - sector size.
 *
 */

static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, unsigned int FlashSectorSizeSig, unsigned int FlashSectorSize)
{
	unsigned int uiSectorSize = 0;
	unsigned int uiSectorSig = 0;

	if (Adapter->bSectorSizeOverride &&
		(Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE &&
			Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)) {
		Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG;
	} else {
		uiSectorSig = FlashSectorSizeSig;

		if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) {
			uiSectorSize = FlashSectorSize;
			/*
			 * If the sector size stored in the FLASH makes sense then use it.
			 */
			if (uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) {
				Adapter->uiSectorSize = uiSectorSize;
			} else if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE &&
				Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) {
				/* No valid size in FLASH, check if Config file has it. */
				Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG;
			} else {
				/* Init to Default, if none of the above works. */
				Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE;
			}
		} else {
			if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE &&
				Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)
				Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG;
			else
				Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE;
		}
	}

	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector size  :%x\n", Adapter->uiSectorSize);

	return Adapter->uiSectorSize;
}

/*
 * Procedure:	BcmInitEEPROMQueues
 *
 * Description: Initialization of EEPROM queues.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *
 * Returns:
 *		<OSAL_STATUS_CODE>
 */

static int BcmInitEEPROMQueues(struct bcm_mini_adapter *Adapter)
{
	unsigned int value = 0;
	/* CHIP Bug : Clear the Avail bits on the Read queue. The default
	 * value on this register is supposed to be 0x00001102.
	 * But we get 0x00001122.
	 */
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Fixing reset value on 0x0f003004 register\n");
	value = EEPROM_READ_DATA_AVAIL;
	wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));

	/* Flush the all the EEPROM queues. */
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Flushing the queues\n");
	value = EEPROM_ALL_QUEUE_FLUSH;
	wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));

	value = 0;
	wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));

	/* Read the EEPROM Status Register. Just to see, no real purpose. */
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "EEPROM Status register value = %x\n", ReadEEPROMStatusRegister(Adapter));

	return STATUS_SUCCESS;
} /* BcmInitEEPROMQueues() */

/*
 * Procedure:	BcmInitNVM
 *
 * Description: Initialization of NVM, EEPROM size,FLASH size, sector size etc.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *
 * Returns:
 *		<OSAL_STATUS_CODE>
 */

int BcmInitNVM(struct bcm_mini_adapter *ps_adapter)
{
	BcmValidateNvmType(ps_adapter);
	BcmInitEEPROMQueues(ps_adapter);

	if (ps_adapter->eNVMType == NVM_AUTODETECT) {
		ps_adapter->eNVMType = BcmGetNvmType(ps_adapter);
		if (ps_adapter->eNVMType == NVM_UNKNOWN)
			BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "NVM Type is unknown!!\n");
	} else if (ps_adapter->eNVMType == NVM_FLASH) {
		BcmGetFlashCSInfo(ps_adapter);
	}

	BcmGetNvmSize(ps_adapter);

	return STATUS_SUCCESS;
}

/* BcmGetNvmSize : set the EEPROM or flash size in Adapter.
 *
 * Input Parameter:
 *		Adapter data structure
 * Return Value :
 *		0. means success;
 */

static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter)
{
	if (Adapter->eNVMType == NVM_EEPROM)
		Adapter->uiNVMDSDSize = BcmGetEEPROMSize(Adapter);
	else if (Adapter->eNVMType == NVM_FLASH)
		Adapter->uiNVMDSDSize = BcmGetFlashSize(Adapter);

	return 0;
}

/*
 * Procedure:	BcmValidateNvm
 *
 * Description: Validates the NVM Type option selected against the device
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *
 * Returns:
 *		<VOID>
 */

static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter)
{
	/*
	 * if forcing the FLASH through CFG file, we should ensure device really has a FLASH.
	 * Accessing the FLASH address without the FLASH being present can cause hang/freeze etc.
	 * So if NVM_FLASH is selected for older chipsets, change it to AUTODETECT where EEPROM is 1st choice.
	 */

	if (Adapter->eNVMType == NVM_FLASH &&
		Adapter->chip_id < 0xBECE3300)
		Adapter->eNVMType = NVM_AUTODETECT;
}

/*
 * Procedure:	BcmReadFlashRDID
 *
 * Description: Reads ID from Serial Flash
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *
 * Returns:
 *		Flash ID
 */

static ULONG BcmReadFlashRDID(struct bcm_mini_adapter *Adapter)
{
	ULONG ulRDID = 0;
	unsigned int value;

	/*
	 * Read ID Instruction.
	 */
	value = (FLASH_CMD_READ_ID << 24);
	wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));

	/* Delay */
	udelay(10);

	/*
	 * Read SPI READQ REG. The output will be WWXXYYZZ.
	 * The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored.
	 */
	rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID));

	return ulRDID >> 8;
}

int BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter)
{
	if (!psAdapter) {
		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL");
		return -EINVAL;
	}
	psAdapter->psFlashCSInfo = kzalloc(sizeof(struct bcm_flash_cs_info), GFP_KERNEL);
	if (psAdapter->psFlashCSInfo == NULL) {
		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 1.x");
		return -ENOMEM;
	}

	psAdapter->psFlash2xCSInfo = kzalloc(sizeof(struct bcm_flash2x_cs_info), GFP_KERNEL);
	if (!psAdapter->psFlash2xCSInfo) {
		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 2.x");
		kfree(psAdapter->psFlashCSInfo);
		return -ENOMEM;
	}

	psAdapter->psFlash2xVendorInfo = kzalloc(sizeof(struct bcm_flash2x_vendor_info), GFP_KERNEL);
	if (!psAdapter->psFlash2xVendorInfo) {
		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate Vendor Info Memory for Flash 2.x");
		kfree(psAdapter->psFlashCSInfo);
		kfree(psAdapter->psFlash2xCSInfo);
		return -ENOMEM;
	}

	return STATUS_SUCCESS;
}

int BcmDeAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter)
{
	if (!psAdapter) {
		BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL");
		return -EINVAL;
	}
	kfree(psAdapter->psFlashCSInfo);
	kfree(psAdapter->psFlash2xCSInfo);
	kfree(psAdapter->psFlash2xVendorInfo);
	return STATUS_SUCCESS;
}

static int BcmDumpFlash2XCSStructure(struct bcm_flash2x_cs_info *psFlash2xCSInfo, struct bcm_mini_adapter *Adapter)
{
	unsigned int Index = 0;

	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "**********************FLASH2X CS Structure *******************");
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is  :%x", (psFlash2xCSInfo->MagicNumber));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Major Version :%d", MAJOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Minor Version :%d", MINOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ISOImageMajorVersion:0x%x", (psFlash2xCSInfo->ISOImageVersion));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSIFirmwareMajorVersion :0x%x", (psFlash2xCSInfo->SCSIFirmwareVersion));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart1ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForScsiFirmware :0x%x", (psFlash2xCSInfo->OffsetFromZeroForScsiFirmware));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SizeOfScsiFirmware  :0x%x", (psFlash2xCSInfo->SizeOfScsiFirmware));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart2ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDStart));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDEnd));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAStart));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAEnd));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionStart));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionData :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionData));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CDLessInactivityTimeout :0x%x", (psFlash2xCSInfo->CDLessInactivityTimeout));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "NewImageSignature :0x%x", (psFlash2xCSInfo->NewImageSignature));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSizeSig :0x%x", (psFlash2xCSInfo->FlashSectorSizeSig));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSize :0x%x", (psFlash2xCSInfo->FlashSectorSize));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashWriteSupportSize :0x%x", (psFlash2xCSInfo->FlashWriteSupportSize));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "TotalFlashSize :0x%X", (psFlash2xCSInfo->TotalFlashSize));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashBaseAddr :0x%x", (psFlash2xCSInfo->FlashBaseAddr));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashPartMaxSize :0x%x", (psFlash2xCSInfo->FlashPartMaxSize));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "IsCDLessDeviceBootSig :0x%x", (psFlash2xCSInfo->IsCDLessDeviceBootSig));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "MassStorageTimeout :0x%x", (psFlash2xCSInfo->MassStorageTimeout));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1End	:0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromDSDStartForDSDHeader :0x%x", (psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2Start));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2End));
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector Access Bit Map is Defined as :");

	for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++)
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectorAccessBitMap[%d] :0x%x", Index,
				(psFlash2xCSInfo->SectorAccessBitMap[Index]));

	return STATUS_SUCCESS;
}

static int ConvertEndianOf2XCSStructure(struct bcm_flash2x_cs_info *psFlash2xCSInfo)
{
	unsigned int Index = 0;

	psFlash2xCSInfo->MagicNumber = ntohl(psFlash2xCSInfo->MagicNumber);
	psFlash2xCSInfo->FlashLayoutVersion = ntohl(psFlash2xCSInfo->FlashLayoutVersion);
	/* psFlash2xCSInfo->FlashLayoutMinorVersion = ntohs(psFlash2xCSInfo->FlashLayoutMinorVersion); */
	psFlash2xCSInfo->ISOImageVersion = ntohl(psFlash2xCSInfo->ISOImageVersion);
	psFlash2xCSInfo->SCSIFirmwareVersion = ntohl(psFlash2xCSInfo->SCSIFirmwareVersion);
	psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage);
	psFlash2xCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlash2xCSInfo->OffsetFromZeroForScsiFirmware);
	psFlash2xCSInfo->SizeOfScsiFirmware = ntohl(psFlash2xCSInfo->SizeOfScsiFirmware);
	psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage);
	psFlash2xCSInfo->OffsetFromZeroForDSDStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDStart);
	psFlash2xCSInfo->OffsetFromZeroForDSDEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDEnd);
	psFlash2xCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAStart);
	psFlash2xCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAEnd);
	psFlash2xCSInfo->OffsetFromZeroForControlSectionStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForControlSectionStart);
	psFlash2xCSInfo->OffsetFromZeroForControlSectionData = ntohl(psFlash2xCSInfo->OffsetFromZeroForControlSectionData);
	psFlash2xCSInfo->CDLessInactivityTimeout = ntohl(psFlash2xCSInfo->CDLessInactivityTimeout);
	psFlash2xCSInfo->NewImageSignature = ntohl(psFlash2xCSInfo->NewImageSignature);
	psFlash2xCSInfo->FlashSectorSizeSig = ntohl(psFlash2xCSInfo->FlashSectorSizeSig);
	psFlash2xCSInfo->FlashSectorSize = ntohl(psFlash2xCSInfo->FlashSectorSize);
	psFlash2xCSInfo->FlashWriteSupportSize = ntohl(psFlash2xCSInfo->FlashWriteSupportSize);
	psFlash2xCSInfo->TotalFlashSize = ntohl(psFlash2xCSInfo->TotalFlashSize);
	psFlash2xCSInfo->FlashBaseAddr = ntohl(psFlash2xCSInfo->FlashBaseAddr);
	psFlash2xCSInfo->FlashPartMaxSize = ntohl(psFlash2xCSInfo->FlashPartMaxSize);
	psFlash2xCSInfo->IsCDLessDeviceBootSig = ntohl(psFlash2xCSInfo->IsCDLessDeviceBootSig);
	psFlash2xCSInfo->MassStorageTimeout = ntohl(psFlash2xCSInfo->MassStorageTimeout);
	psFlash2xCSInfo->OffsetISOImage1Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1Start);
	psFlash2xCSInfo->OffsetISOImage1Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1End);
	psFlash2xCSInfo->OffsetISOImage1Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2Start);
	psFlash2xCSInfo->OffsetISOImage1Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2End);
	psFlash2xCSInfo->OffsetISOImage1Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3Start);
	psFlash2xCSInfo->OffsetISOImage1Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3End);
	psFlash2xCSInfo->OffsetISOImage2Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1Start);
	psFlash2xCSInfo->OffsetISOImage2Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1End);
	psFlash2xCSInfo->OffsetISOImage2Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2Start);
	psFlash2xCSInfo->OffsetISOImage2Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2End);
	psFlash2xCSInfo->OffsetISOImage2Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3Start);
	psFlash2xCSInfo->OffsetISOImage2Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3End);
	psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader = ntohl(psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader);
	psFlash2xCSInfo->OffsetFromZeroForDSD1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1Start);
	psFlash2xCSInfo->OffsetFromZeroForDSD1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1End);
	psFlash2xCSInfo->OffsetFromZeroForDSD2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2Start);
	psFlash2xCSInfo->OffsetFromZeroForDSD2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2End);
	psFlash2xCSInfo->OffsetFromZeroForVSA1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1Start);
	psFlash2xCSInfo->OffsetFromZeroForVSA1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1End);
	psFlash2xCSInfo->OffsetFromZeroForVSA2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2Start);
	psFlash2xCSInfo->OffsetFromZeroForVSA2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2End);

	for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++)
		psFlash2xCSInfo->SectorAccessBitMap[Index] = ntohl(psFlash2xCSInfo->SectorAccessBitMap[Index]);

	return STATUS_SUCCESS;
}

static int ConvertEndianOfCSStructure(struct bcm_flash_cs_info *psFlashCSInfo)
{
	/* unsigned int Index = 0; */
	psFlashCSInfo->MagicNumber				= ntohl(psFlashCSInfo->MagicNumber);
	psFlashCSInfo->FlashLayoutVersion			= ntohl(psFlashCSInfo->FlashLayoutVersion);
	psFlashCSInfo->ISOImageVersion				= ntohl(psFlashCSInfo->ISOImageVersion);
	/* won't convert according to old assumption */
	psFlashCSInfo->SCSIFirmwareVersion			= (psFlashCSInfo->SCSIFirmwareVersion);
	psFlashCSInfo->OffsetFromZeroForPart1ISOImage		= ntohl(psFlashCSInfo->OffsetFromZeroForPart1ISOImage);
	psFlashCSInfo->OffsetFromZeroForScsiFirmware		= ntohl(psFlashCSInfo->OffsetFromZeroForScsiFirmware);
	psFlashCSInfo->SizeOfScsiFirmware			= ntohl(psFlashCSInfo->SizeOfScsiFirmware);
	psFlashCSInfo->OffsetFromZeroForPart2ISOImage		= ntohl(psFlashCSInfo->OffsetFromZeroForPart2ISOImage);
	psFlashCSInfo->OffsetFromZeroForCalibrationStart	= ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationStart);
	psFlashCSInfo->OffsetFromZeroForCalibrationEnd		= ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationEnd);
	psFlashCSInfo->OffsetFromZeroForVSAStart		= ntohl(psFlashCSInfo->OffsetFromZeroForVSAStart);
	psFlashCSInfo->OffsetFromZeroForVSAEnd			= ntohl(psFlashCSInfo->OffsetFromZeroForVSAEnd);
	psFlashCSInfo->OffsetFromZeroForControlSectionStart	= ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionStart);
	psFlashCSInfo->OffsetFromZeroForControlSectionData	= ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionData);
	psFlashCSInfo->CDLessInactivityTimeout			= ntohl(psFlashCSInfo->CDLessInactivityTimeout);
	psFlashCSInfo->NewImageSignature			= ntohl(psFlashCSInfo->NewImageSignature);
	psFlashCSInfo->FlashSectorSizeSig			= ntohl(psFlashCSInfo->FlashSectorSizeSig);
	psFlashCSInfo->FlashSectorSize				= ntohl(psFlashCSInfo->FlashSectorSize);
	psFlashCSInfo->FlashWriteSupportSize			= ntohl(psFlashCSInfo->FlashWriteSupportSize);
	psFlashCSInfo->TotalFlashSize				= ntohl(psFlashCSInfo->TotalFlashSize);
	psFlashCSInfo->FlashBaseAddr				= ntohl(psFlashCSInfo->FlashBaseAddr);
	psFlashCSInfo->FlashPartMaxSize				= ntohl(psFlashCSInfo->FlashPartMaxSize);
	psFlashCSInfo->IsCDLessDeviceBootSig			= ntohl(psFlashCSInfo->IsCDLessDeviceBootSig);
	psFlashCSInfo->MassStorageTimeout			= ntohl(psFlashCSInfo->MassStorageTimeout);

	return STATUS_SUCCESS;
}

static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section)
{
	return (Adapter->uiVendorExtnFlag &&
		(Adapter->psFlash2xVendorInfo->VendorSection[section].AccessFlags & FLASH2X_SECTION_PRESENT) &&
		(Adapter->psFlash2xVendorInfo->VendorSection[section].OffsetFromZeroForSectionStart != UNINIT_PTR_IN_CS));
}

static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter)
{
	B_UINT32 i = 0;
	unsigned int uiSizeSection = 0;

	Adapter->uiVendorExtnFlag = FALSE;

	for (i = 0; i < TOTAL_SECTIONS; i++)
		Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart = UNINIT_PTR_IN_CS;

	if (STATUS_SUCCESS != vendorextnGetSectionInfo(Adapter, Adapter->psFlash2xVendorInfo))
		return;

	i = 0;
	while (i < TOTAL_SECTIONS) {
		if (!(Adapter->psFlash2xVendorInfo->VendorSection[i].AccessFlags & FLASH2X_SECTION_PRESENT)) {
			i++;
			continue;
		}

		Adapter->uiVendorExtnFlag = TRUE;
		uiSizeSection = (Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionEnd -
				Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart);

		switch (i) {
		case DSD0:
			if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header))) &&
				(UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart))
				Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = VENDOR_PTR_IN_CS;
			else
				Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = UNINIT_PTR_IN_CS;
			break;

		case DSD1:
			if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header))) &&
				(UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart))
				Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = VENDOR_PTR_IN_CS;
			else
				Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = UNINIT_PTR_IN_CS;
			break;

		case DSD2:
			if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header))) &&
				(UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart))
				Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = VENDOR_PTR_IN_CS;
			else
				Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = UNINIT_PTR_IN_CS;
			break;
		case VSA0:
			if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)
				Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = VENDOR_PTR_IN_CS;
			else
				Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = UNINIT_PTR_IN_CS;
			break;

		case VSA1:
			if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)
				Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = VENDOR_PTR_IN_CS;
			else
				Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = UNINIT_PTR_IN_CS;
			break;
		case VSA2:
			if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)
				Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = VENDOR_PTR_IN_CS;
			else
				Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = UNINIT_PTR_IN_CS;
			break;

		default:
			break;
		}
		i++;
	}
}

/*
 * Procedure:	BcmGetFlashCSInfo
 *
 * Description: Reads control structure and gets Cal section addresses.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *
 * Returns:
 *		<VOID>
 */

static int BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter)
{
	/* struct bcm_flash_cs_info sFlashCsInfo = {0}; */

	#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
		unsigned int value;
	#endif

	unsigned int uiFlashLayoutMajorVersion;
	Adapter->uiFlashLayoutMinorVersion = 0;
	Adapter->uiFlashLayoutMajorVersion = 0;
	Adapter->ulFlashControlSectionStart = FLASH_CS_INFO_START_ADDR;

	Adapter->uiFlashBaseAdd = 0;
	Adapter->ulFlashCalStart = 0;
	memset(Adapter->psFlashCSInfo, 0 , sizeof(struct bcm_flash_cs_info));
	memset(Adapter->psFlash2xCSInfo, 0 , sizeof(struct bcm_flash2x_cs_info));

	if (!Adapter->bDDRInitDone) {
		value = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT;
		wrmalt(Adapter, 0xAF00A080, &value, sizeof(value));
	}

	/* Reading first 8 Bytes to get the Flash Layout
	 * MagicNumber(4 bytes) +FlashLayoutMinorVersion(2 Bytes) +FlashLayoutMajorVersion(2 Bytes)
	 */
	BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, 8);

	Adapter->psFlashCSInfo->FlashLayoutVersion =  ntohl(Adapter->psFlashCSInfo->FlashLayoutVersion);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Version :%X", (Adapter->psFlashCSInfo->FlashLayoutVersion));
	/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Minor Version :%d\n", ntohs(sFlashCsInfo.FlashLayoutMinorVersion)); */
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is  :%x\n", ntohl(Adapter->psFlashCSInfo->MagicNumber));

	if (FLASH_CONTROL_STRUCT_SIGNATURE == ntohl(Adapter->psFlashCSInfo->MagicNumber)) {
		uiFlashLayoutMajorVersion = MAJOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion));
		Adapter->uiFlashLayoutMinorVersion = MINOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion));
	} else {
		Adapter->uiFlashLayoutMinorVersion = 0;
		uiFlashLayoutMajorVersion = 0;
	}

	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FLASH LAYOUT MAJOR VERSION :%X", uiFlashLayoutMajorVersion);

	if (uiFlashLayoutMajorVersion < FLASH_2X_MAJOR_NUMBER) {
		BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, sizeof(struct bcm_flash_cs_info));
		ConvertEndianOfCSStructure(Adapter->psFlashCSInfo);
		Adapter->ulFlashCalStart = (Adapter->psFlashCSInfo->OffsetFromZeroForCalibrationStart);

		if (!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
			Adapter->ulFlashControlSectionStart = Adapter->psFlashCSInfo->OffsetFromZeroForControlSectionStart;

		if ((FLASH_CONTROL_STRUCT_SIGNATURE == (Adapter->psFlashCSInfo->MagicNumber)) &&
			(SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlashCSInfo->SCSIFirmwareVersion)) &&
			(FLASH_SECTOR_SIZE_SIG == (Adapter->psFlashCSInfo->FlashSectorSizeSig)) &&
			(BYTE_WRITE_SUPPORT == (Adapter->psFlashCSInfo->FlashWriteSupportSize))) {
			Adapter->ulFlashWriteSize = (Adapter->psFlashCSInfo->FlashWriteSupportSize);
			Adapter->fpFlashWrite = flashByteWrite;
			Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus;
		} else {
			Adapter->ulFlashWriteSize = MAX_RW_SIZE;
			Adapter->fpFlashWrite = flashWrite;
			Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus;
		}

		BcmGetFlashSectorSize(Adapter, (Adapter->psFlashCSInfo->FlashSectorSizeSig),
				(Adapter->psFlashCSInfo->FlashSectorSize));
		Adapter->uiFlashBaseAdd = Adapter->psFlashCSInfo->FlashBaseAddr & 0xFCFFFFFF;
	} else {
		if (BcmFlash2xBulkRead(Adapter, (PUINT)Adapter->psFlash2xCSInfo, NO_SECTION_VAL,
					Adapter->ulFlashControlSectionStart, sizeof(struct bcm_flash2x_cs_info))) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to read CS structure\n");
			return STATUS_FAILURE;
		}

		ConvertEndianOf2XCSStructure(Adapter->psFlash2xCSInfo);
		BcmDumpFlash2XCSStructure(Adapter->psFlash2xCSInfo, Adapter);
		if ((FLASH_CONTROL_STRUCT_SIGNATURE == Adapter->psFlash2xCSInfo->MagicNumber) &&
			(SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlash2xCSInfo->SCSIFirmwareVersion)) &&
			(FLASH_SECTOR_SIZE_SIG == Adapter->psFlash2xCSInfo->FlashSectorSizeSig) &&
			(BYTE_WRITE_SUPPORT == Adapter->psFlash2xCSInfo->FlashWriteSupportSize)) {
			Adapter->ulFlashWriteSize = Adapter->psFlash2xCSInfo->FlashWriteSupportSize;
			Adapter->fpFlashWrite = flashByteWrite;
			Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus;
		} else {
			Adapter->ulFlashWriteSize = MAX_RW_SIZE;
			Adapter->fpFlashWrite = flashWrite;
			Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus;
		}

		BcmGetFlashSectorSize(Adapter, Adapter->psFlash2xCSInfo->FlashSectorSizeSig,
				Adapter->psFlash2xCSInfo->FlashSectorSize);

		UpdateVendorInfo(Adapter);

		BcmGetActiveDSD(Adapter);
		BcmGetActiveISO(Adapter);
		Adapter->uiFlashBaseAdd = Adapter->psFlash2xCSInfo->FlashBaseAddr & 0xFCFFFFFF;
		Adapter->ulFlashControlSectionStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart;
	}
	/*
	 * Concerns: what if CS sector size does not match with this sector size ???
	 * what is the indication of AccessBitMap  in CS in flash 2.x ????
	 */
	Adapter->ulFlashID = BcmReadFlashRDID(Adapter);
	Adapter->uiFlashLayoutMajorVersion = uiFlashLayoutMajorVersion;

	return STATUS_SUCCESS;
}

/*
 * Procedure:	BcmGetNvmType
 *
 * Description: Finds the type of NVM used.
 *
 * Arguments:
 *		Adapter    - ptr to Adapter object instance
 *
 * Returns:
 *		NVM_TYPE
 *
 */

static enum bcm_nvm_type BcmGetNvmType(struct bcm_mini_adapter *Adapter)
{
	unsigned int uiData = 0;

	BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4);
	if (uiData == BECM)
		return NVM_EEPROM;

	/*
	 * Read control struct and get cal addresses before accessing the flash
	 */
	BcmGetFlashCSInfo(Adapter);

	BeceemFlashBulkRead(Adapter, &uiData, 0x0 + Adapter->ulFlashCalStart, 4);
	if (uiData == BECM)
		return NVM_FLASH;

	/*
	 * even if there is no valid signature on EEPROM/FLASH find out if they really exist.
	 * if exist select it.
	 */
	if (BcmGetEEPROMSize(Adapter))
		return NVM_EEPROM;

	/* TBD for Flash. */
	return NVM_UNKNOWN;
}

/*
 * BcmGetSectionValStartOffset - this will calculate the section's starting offset if section val is given
 * @Adapter : Drivers Private Data structure
 * @eFlashSectionVal : Flash secion value defined in enum bcm_flash2x_section_val
 *
 * Return value:-
 * On success it return the start offset of the provided section val
 * On Failure -returns STATUS_FAILURE
 */

int BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal)
{
	/*
	 * Considering all the section for which end offset can be calculated or directly given
	 * in CS Structure. if matching case does not exist, return STATUS_FAILURE indicating section
	 * endoffset can't be calculated or given in CS Structure.
	 */

	int SectStartOffset = 0;

	SectStartOffset = INVALID_OFFSET;

	if (IsSectionExistInVendorInfo(Adapter, eFlashSectionVal))
		return Adapter->psFlash2xVendorInfo->VendorSection[eFlashSectionVal].OffsetFromZeroForSectionStart;

	switch (eFlashSectionVal) {
	case ISO_IMAGE1:
		if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) &&
			(IsNonCDLessDevice(Adapter) == FALSE))
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start);
		break;
	case ISO_IMAGE2:
		if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) &&
			(IsNonCDLessDevice(Adapter) == FALSE))
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start);
		break;
	case DSD0:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart);
		break;
	case DSD1:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start);
		break;
	case DSD2:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start);
		break;
	case VSA0:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart);
		break;
	case VSA1:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start);
		break;
	case VSA2:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start);
		break;
	case SCSI:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware);
		break;
	case CONTROL_SECTION:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart);
		break;
	case ISO_IMAGE1_PART2:
		if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start);
		break;
	case ISO_IMAGE1_PART3:
		if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start);
		break;
	case ISO_IMAGE2_PART2:
		if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start);
		break;
	case ISO_IMAGE2_PART3:
		if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start != UNINIT_PTR_IN_CS)
			SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start);
		break;
	default:
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x");
		SectStartOffset = INVALID_OFFSET;
	}

	return SectStartOffset;
}

/*
 * BcmGetSectionValEndOffset - this will calculate the section's Ending offset if section val is given
 * @Adapter : Drivers Private Data structure
 * @eFlashSectionVal : Flash secion value defined in enum bcm_flash2x_section_val
 *
 * Return value:-
 * On success it return the end offset of the provided section val
 * On Failure -returns STATUS_FAILURE
 */

int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
{
	int SectEndOffset = 0;

	SectEndOffset = INVALID_OFFSET;
	if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal))
		return Adapter->psFlash2xVendorInfo->VendorSection[eFlash2xSectionVal].OffsetFromZeroForSectionEnd;

	switch (eFlash2xSectionVal) {
	case ISO_IMAGE1:
		if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End != UNINIT_PTR_IN_CS) &&
			(IsNonCDLessDevice(Adapter) == FALSE))
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End);
		break;
	case ISO_IMAGE2:
		if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End != UNINIT_PTR_IN_CS) &&
			(IsNonCDLessDevice(Adapter) == FALSE))
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End);
		break;
	case DSD0:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd);
		break;
	case DSD1:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End);
		break;
	case DSD2:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End);
		break;
	case VSA0:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd);
		break;
	case VSA1:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End);
		break;
	case VSA2:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End);
		break;
	case SCSI:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS)
			SectEndOffset = ((Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) +
					(Adapter->psFlash2xCSInfo->SizeOfScsiFirmware));
		break;
	case CONTROL_SECTION:
		/* Not Clear So Putting failure. confirm and fix it. */
		SectEndOffset = STATUS_FAILURE;
		break;
	case ISO_IMAGE1_PART2:
		if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End);
		break;
	case ISO_IMAGE1_PART3:
		if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End);
		break;
	case ISO_IMAGE2_PART2:
		if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End);
		break;
	case ISO_IMAGE2_PART3:
		if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End != UNINIT_PTR_IN_CS)
			SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End);
		break;
	default:
		SectEndOffset = INVALID_OFFSET;
	}

	return SectEndOffset ;
}

/*
 * BcmFlash2xBulkRead:- Read API for Flash Map 2.x .
 * @Adapter :Driver Private Data Structure
 * @pBuffer : Buffer where data has to be put after reading
 * @eFlashSectionVal :Flash Section Val defined in enum bcm_flash2x_section_val
 * @uiOffsetWithinSectionVal :- Offset with in provided section
 * @uiNumBytes : Number of Bytes for Read
 *
 * Return value:-
 * return true on success and STATUS_FAILURE on fail.
 */

int BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter,
		PUINT pBuffer,
		enum bcm_flash2x_section_val eFlash2xSectionVal,
		unsigned int uiOffsetWithinSectionVal,
		unsigned int uiNumBytes)
{
	int Status = STATUS_SUCCESS;
	int SectionStartOffset = 0;
	unsigned int uiAbsoluteOffset = 0;
	unsigned int uiTemp = 0, value = 0;

	if (!Adapter) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL");
		return -EINVAL;
	}
	if (Adapter->device_removed) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed");
		return -ENODEV;
	}

	/* NO_SECTION_VAL means absolute offset is given. */
	if (eFlash2xSectionVal == NO_SECTION_VAL)
		SectionStartOffset = 0;
	else
		SectionStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);

	if (SectionStartOffset == STATUS_FAILURE) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exixt in Flash 2.x Map ", eFlash2xSectionVal);
		return -EINVAL;
	}

	if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal))
		return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectionVal, uiOffsetWithinSectionVal, uiNumBytes);

	/* calculating  the absolute offset from FLASH; */
	uiAbsoluteOffset = uiOffsetWithinSectionVal + SectionStartOffset;
	rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
	value = 0;
	wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
	Status = BeceemFlashBulkRead(Adapter, pBuffer, uiAbsoluteOffset, uiNumBytes);
	wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
	if (Status) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Read Failed with Status :%d", Status);
		return Status;
	}

	return Status;
}

/*
 * BcmFlash2xBulkWrite :-API for Writing on the Flash Map 2.x.
 * @Adapter :Driver Private Data Structure
 * @pBuffer : Buffer From where data has to taken for writing
 * @eFlashSectionVal :Flash Section Val defined in enum bcm_flash2x_section_val
 * @uiOffsetWithinSectionVal :- Offset with in provided section
 * @uiNumBytes : Number of Bytes for Write
 *
 * Return value:-
 * return true on success and STATUS_FAILURE on fail.
 *
 */

int BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter,
			PUINT pBuffer,
			enum bcm_flash2x_section_val eFlash2xSectVal,
			unsigned int uiOffset,
			unsigned int uiNumBytes,
			unsigned int bVerify)
{
	int Status = STATUS_SUCCESS;
	unsigned int FlashSectValStartOffset = 0;
	unsigned int uiTemp = 0, value = 0;

	if (!Adapter) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL");
		return -EINVAL;
	}

	if (Adapter->device_removed) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed");
		return -ENODEV;
	}

	/* NO_SECTION_VAL means absolute offset is given. */
	if (eFlash2xSectVal == NO_SECTION_VAL)
		FlashSectValStartOffset = 0;
	else
		FlashSectValStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectVal);

	if (FlashSectValStartOffset == STATUS_FAILURE) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exixt in Flash Map 2.x", eFlash2xSectVal);
		return -EINVAL;
	}

	if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectVal))
		return vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectVal, uiOffset, uiNumBytes, bVerify);

	/* calculating  the absolute offset from FLASH; */
	uiOffset = uiOffset + FlashSectValStartOffset;

	rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
	value = 0;
	wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));

	Status = BeceemFlashBulkWrite(Adapter, pBuffer, uiOffset, uiNumBytes, bVerify);

	wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
	if (Status) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write failed with Status :%d", Status);
		return Status;
	}

	return Status;
}

/*
 * BcmGetActiveDSD : Set the Active DSD in Adapter Structure which has to be dumped in DDR
 * @Adapter :-Drivers private Data Structure
 *
 * Return Value:-
 * Return STATUS_SUCESS if get success in setting the right DSD else negaive error code
 *
 */

static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter)
{
	enum bcm_flash2x_section_val uiHighestPriDSD = 0;

	uiHighestPriDSD = getHighestPriDSD(Adapter);
	Adapter->eActiveDSD = uiHighestPriDSD;

	if (DSD0  == uiHighestPriDSD)
		Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart;
	if (DSD1 == uiHighestPriDSD)
		Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start;
	if (DSD2 == uiHighestPriDSD)
		Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start;
	if (Adapter->eActiveDSD)
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active DSD :%d", Adapter->eActiveDSD);
	if (Adapter->eActiveDSD == 0) {
		/* if No DSD gets Active, Make Active the DSD with WR  permission */
		if (IsSectionWritable(Adapter, DSD2)) {
			Adapter->eActiveDSD = DSD2;
			Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start;
		} else if (IsSectionWritable(Adapter, DSD1)) {
			Adapter->eActiveDSD = DSD1;
			Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start;
		} else if (IsSectionWritable(Adapter, DSD0)) {
			Adapter->eActiveDSD = DSD0;
			Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart;
		}
	}

	return STATUS_SUCCESS;
}

/*
 * BcmGetActiveISO :- Set the Active ISO in Adapter Data Structue
 * @Adapter : Driver private Data Structure
 *
 * Return Value:-
 * Sucsess:- STATUS_SUCESS
 * Failure- : negative erro code
 *
 */

static int BcmGetActiveISO(struct bcm_mini_adapter *Adapter)
{
	int HighestPriISO = 0;

	HighestPriISO = getHighestPriISO(Adapter);

	Adapter->eActiveISO = HighestPriISO;
	if (Adapter->eActiveISO == ISO_IMAGE2)
		Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start);
	else if (Adapter->eActiveISO == ISO_IMAGE1)
		Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start);

	if (Adapter->eActiveISO)
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active ISO :%x", Adapter->eActiveISO);

	return STATUS_SUCCESS;
}

/*
 * IsOffsetWritable :- it will tell the access permission of the sector having passed offset
 * @Adapter : Drivers Private Data Structure
 * @uiOffset : Offset provided in the Flash
 *
 * Return Value:-
 * Success:-TRUE ,  offset is writable
 * Failure:-FALSE, offset is RO
 *
 */

B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, unsigned int uiOffset)
{
	unsigned int uiSectorNum = 0;
	unsigned int uiWordOfSectorPermission = 0;
	unsigned int uiBitofSectorePermission = 0;
	B_UINT32 permissionBits = 0;

	uiSectorNum = uiOffset/Adapter->uiSectorSize;

	/* calculating the word having this Sector Access permission from SectorAccessBitMap Array */
	uiWordOfSectorPermission = Adapter->psFlash2xCSInfo->SectorAccessBitMap[uiSectorNum / 16];

	/* calculating the bit index inside the word for  this sector */
	uiBitofSectorePermission = 2 * (15 - uiSectorNum % 16);

	/* Setting Access permission */
	permissionBits = uiWordOfSectorPermission & (0x3 << uiBitofSectorePermission);
	permissionBits = (permissionBits >> uiBitofSectorePermission) & 0x3;
	if (permissionBits == SECTOR_READWRITE_PERMISSION)
		return TRUE;
	else
		return FALSE;
}

static int BcmDumpFlash2xSectionBitMap(struct bcm_flash2x_bitmap *psFlash2xBitMap)
{
	struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);

	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "***************Flash 2.x Section Bitmap***************");
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE1  :0X%x", psFlash2xBitMap->ISO_IMAGE1);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE2  :0X%x", psFlash2xBitMap->ISO_IMAGE2);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD0  :0X%x", psFlash2xBitMap->DSD0);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD1  :0X%x", psFlash2xBitMap->DSD1);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD2  :0X%x", psFlash2xBitMap->DSD2);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA0  :0X%x", psFlash2xBitMap->VSA0);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA1  :0X%x", psFlash2xBitMap->VSA1);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA2  :0X%x", psFlash2xBitMap->VSA2);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSI  :0X%x", psFlash2xBitMap->SCSI);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CONTROL_SECTION  :0X%x", psFlash2xBitMap->CONTROL_SECTION);

	return STATUS_SUCCESS;
}

/*
 * BcmGetFlash2xSectionalBitMap :- It will provide the bit map of all the section present in Flash
 * 8bit has been assigned to every section.
 * bit[0] :Section present or not
 * bit[1] :section is valid or not
 * bit[2] : Secton is read only or has write permission too.
 * bit[3] : Active Section -
 * bit[7...4] = Reserved .
 *
 * @Adapter:-Driver private Data Structure
 *
 * Return value:-
 * Success:- STATUS_SUCESS
 * Failure:- negative error code
 */

int BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_bitmap *psFlash2xBitMap)
{
	struct bcm_flash2x_cs_info *psFlash2xCSInfo = Adapter->psFlash2xCSInfo;
	enum bcm_flash2x_section_val uiHighestPriDSD = 0;
	enum bcm_flash2x_section_val uiHighestPriISO = 0;
	BOOLEAN SetActiveDSDDone = FALSE;
	BOOLEAN SetActiveISODone = FALSE;

	/* For 1.x map all the section except DSD0 will be shown as not present
	 * This part will be used by calibration tool to detect the number of DSD present in Flash.
	 */
	if (IsFlash2x(Adapter) == FALSE) {
		psFlash2xBitMap->ISO_IMAGE2 = 0;
		psFlash2xBitMap->ISO_IMAGE1 = 0;
		psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; /* 0xF; 0000(Reseved)1(Active)0(RW)1(valid)1(present) */
		psFlash2xBitMap->DSD1  = 0;
		psFlash2xBitMap->DSD2 = 0;
		psFlash2xBitMap->VSA0 = 0;
		psFlash2xBitMap->VSA1 = 0;
		psFlash2xBitMap->VSA2 = 0;
		psFlash2xBitMap->CONTROL_SECTION = 0;
		psFlash2xBitMap->SCSI = 0;
		psFlash2xBitMap->Reserved0 = 0;
		psFlash2xBitMap->Reserved1 = 0;
		psFlash2xBitMap->Reserved2 = 0;

		return STATUS_SUCCESS;
	}

	uiHighestPriDSD = getHighestPriDSD(Adapter);
	uiHighestPriISO = getHighestPriISO(Adapter);

	/*
	 * IS0 IMAGE 2
	 */
	if ((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->ISO_IMAGE2 = psFlash2xBitMap->ISO_IMAGE2 | FLASH2X_SECTION_PRESENT;

		if (ReadISOSignature(Adapter, ISO_IMAGE2) == ISO_IMAGE_MAGIC_NUMBER)
			psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_VALID;

		/* Calculation for extrating the Access permission */
		if (IsSectionWritable(Adapter, ISO_IMAGE2) == FALSE)
			psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_RO;

		if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE2) {
			psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_ACT;
			SetActiveISODone = TRUE;
		}
	}

	/*
	 * IS0 IMAGE 1
	 */
	if ((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->ISO_IMAGE1 = psFlash2xBitMap->ISO_IMAGE1 | FLASH2X_SECTION_PRESENT;

		if (ReadISOSignature(Adapter, ISO_IMAGE1) == ISO_IMAGE_MAGIC_NUMBER)
			psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_VALID;

		/* Calculation for extrating the Access permission */
		if (IsSectionWritable(Adapter, ISO_IMAGE1) == FALSE)
			psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_RO;

		if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE1) {
			psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_ACT;
			SetActiveISODone = TRUE;
		}
	}

	/*
	 * DSD2
	 */
	if ((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->DSD2 = psFlash2xBitMap->DSD2 | FLASH2X_SECTION_PRESENT;

		if (ReadDSDSignature(Adapter, DSD2) == DSD_IMAGE_MAGIC_NUMBER)
			psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_VALID;

		/* Calculation for extrating the Access permission */
		if (IsSectionWritable(Adapter, DSD2) == FALSE) {
			psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_RO;
		} else {
			/* Means section is writable */
			if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD2)) {
				psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT;
				SetActiveDSDDone = TRUE;
			}
		}
	}

	/*
	 * DSD 1
	 */
	if ((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->DSD1 = psFlash2xBitMap->DSD1 | FLASH2X_SECTION_PRESENT;

		if (ReadDSDSignature(Adapter, DSD1) == DSD_IMAGE_MAGIC_NUMBER)
			psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_VALID;

		/* Calculation for extrating the Access permission */
		if (IsSectionWritable(Adapter, DSD1) == FALSE) {
			psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_RO;
		} else {
			/* Means section is writable */
			if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD1)) {
				psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT;
				SetActiveDSDDone = TRUE;
			}
		}
	}

	/*
	 * For DSD 0
	 */
	if ((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->DSD0 = psFlash2xBitMap->DSD0 | FLASH2X_SECTION_PRESENT;

		if (ReadDSDSignature(Adapter, DSD0) == DSD_IMAGE_MAGIC_NUMBER)
			psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_VALID;

		/* Setting Access permission */
		if (IsSectionWritable(Adapter, DSD0) == FALSE) {
			psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_RO;
		} else {
			/* Means section is writable */
			if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD0)) {
				psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT;
				SetActiveDSDDone = TRUE;
			}
		}
	}

	/*
	 * VSA 0
	 */
	if ((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->VSA0 = psFlash2xBitMap->VSA0 | FLASH2X_SECTION_PRESENT;

		/* Setting the Access Bit. Map is not defined hece setting it always valid */
		psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_VALID;

		/* Calculation for extrating the Access permission */
		if (IsSectionWritable(Adapter, VSA0) == FALSE)
			psFlash2xBitMap->VSA0 |=  FLASH2X_SECTION_RO;

		/* By Default section is Active */
		psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_ACT;
	}

	/*
	 * VSA 1
	 */
	if ((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->VSA1 = psFlash2xBitMap->VSA1 | FLASH2X_SECTION_PRESENT;

		/* Setting the Access Bit. Map is not defined hece setting it always valid */
		psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_VALID;

		/* Checking For Access permission */
		if (IsSectionWritable(Adapter, VSA1) == FALSE)
			psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_RO;

		/* By Default section is Active */
		psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_ACT;
	}

	/*
	 * VSA 2
	 */
	if ((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->VSA2 = psFlash2xBitMap->VSA2 | FLASH2X_SECTION_PRESENT;

		/* Setting the Access Bit. Map is not defined hece setting it always valid */
		psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_VALID;

		/* Checking For Access permission */
		if (IsSectionWritable(Adapter, VSA2) == FALSE)
			psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_RO;

		/* By Default section is Active */
		psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_ACT;
	}

	/*
	 * SCSI Section
	 */
	if ((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->SCSI = psFlash2xBitMap->SCSI | FLASH2X_SECTION_PRESENT;

		/* Setting the Access Bit. Map is not defined hece setting it always valid */
		psFlash2xBitMap->SCSI |= FLASH2X_SECTION_VALID;

		/* Checking For Access permission */
		if (IsSectionWritable(Adapter, SCSI) == FALSE)
			psFlash2xBitMap->SCSI |= FLASH2X_SECTION_RO;

		/* By Default section is Active */
		psFlash2xBitMap->SCSI |= FLASH2X_SECTION_ACT;
	}

	/*
	 * Control Section
	 */
	if ((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) {
		/* Setting the 0th Bit representing the Section is present or not. */
		psFlash2xBitMap->CONTROL_SECTION = psFlash2xBitMap->CONTROL_SECTION | (FLASH2X_SECTION_PRESENT);

		/* Setting the Access Bit. Map is not defined hece setting it always valid */
		psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_VALID;

		/* Checking For Access permission */
		if (IsSectionWritable(Adapter, CONTROL_SECTION) == FALSE)
			psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_RO;

		/* By Default section is Active */
		psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_ACT;
	}

	/*
	 * For Reserved Sections
	 */
	psFlash2xBitMap->Reserved0 = 0;
	psFlash2xBitMap->Reserved0 = 0;
	psFlash2xBitMap->Reserved0 = 0;
	BcmDumpFlash2xSectionBitMap(psFlash2xBitMap);

	return STATUS_SUCCESS;
}

/*
 * BcmSetActiveSection :- Set Active section is used to make priority field highest over other
 * section of same type.
 *
 * @Adapater :- Bcm Driver Private Data Structure
 * @eFlash2xSectionVal :- Flash section val whose priority has to be made highest.
 *
 * Return Value:- Make the priorit highest else return erorr code
 *
 */

int BcmSetActiveSection(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectVal)
{
	unsigned int SectImagePriority = 0;
	int Status = STATUS_SUCCESS;

	/* struct bcm_dsd_header sDSD = {0};
	 * struct bcm_iso_header sISO = {0};
	 */
	int HighestPriDSD = 0 ;
	int HighestPriISO = 0;

	Status = IsSectionWritable(Adapter, eFlash2xSectVal);
	if (Status != TRUE) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section <%d> is not writable", eFlash2xSectVal);
		return STATUS_FAILURE;
	}

	Adapter->bHeaderChangeAllowed = TRUE;
	switch (eFlash2xSectVal) {
	case ISO_IMAGE1:
	case ISO_IMAGE2:
		if (ReadISOSignature(Adapter, eFlash2xSectVal) == ISO_IMAGE_MAGIC_NUMBER) {
			HighestPriISO = getHighestPriISO(Adapter);

			if (HighestPriISO == eFlash2xSectVal) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal);
				Status = STATUS_SUCCESS;
				break;
			}

			SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1;

			if ((SectImagePriority <= 0) && IsSectionWritable(Adapter, HighestPriISO)) {
				/* This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF.
				 * We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO
				 * by user
				 */
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal);
				SectImagePriority = htonl(0x1);
				Status = BcmFlash2xBulkWrite(Adapter,
							&SectImagePriority,
							HighestPriISO,
							0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImagePriority),
							SIGNATURE_SIZE,
							TRUE);
				if (Status) {
					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
					Status = STATUS_FAILURE;
					break;
				}

				HighestPriISO = getHighestPriISO(Adapter);

				if (HighestPriISO == eFlash2xSectVal) {
					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal);
					Status = STATUS_SUCCESS;
					break;
				}

				SectImagePriority = 2;
			}

			SectImagePriority = htonl(SectImagePriority);

			Status = BcmFlash2xBulkWrite(Adapter,
						&SectImagePriority,
						eFlash2xSectVal,
						0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImagePriority),
						SIGNATURE_SIZE,
						TRUE);
			if (Status) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
				break;
			}
		} else {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority");
			Status = STATUS_FAILURE;
			break;
		}
		break;
	case DSD0:
	case DSD1:
	case DSD2:
		if (ReadDSDSignature(Adapter, eFlash2xSectVal) == DSD_IMAGE_MAGIC_NUMBER) {
			HighestPriDSD = getHighestPriDSD(Adapter);
			if ((HighestPriDSD == eFlash2xSectVal)) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given DSD<%x> already has highest priority", eFlash2xSectVal);
				Status = STATUS_SUCCESS;
				break;
			}

			SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1;
			if (SectImagePriority <= 0) {
				/* This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF.
				 * We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD
				 * by user
				 */
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal);
				SectImagePriority = htonl(0x1);

				Status = BcmFlash2xBulkWrite(Adapter,
							&SectImagePriority,
							HighestPriDSD,
							Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority),
							SIGNATURE_SIZE,
							TRUE);
				if (Status) {
					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
					break;
				}

				HighestPriDSD = getHighestPriDSD(Adapter);

				if ((HighestPriDSD == eFlash2xSectVal)) {
					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Made the DSD: %x highest by reducing priority of other\n", eFlash2xSectVal);
					Status = STATUS_SUCCESS;
					break;
				}

				SectImagePriority = htonl(0x2);
				Status = BcmFlash2xBulkWrite(Adapter,
							&SectImagePriority,
							HighestPriDSD,
							Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority),
							SIGNATURE_SIZE,
							TRUE);
				if (Status) {
					BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
					break;
				}

				HighestPriDSD = getHighestPriDSD(Adapter);
				if ((HighestPriDSD == eFlash2xSectVal)) {
					Status = STATUS_SUCCESS;
					break;
				}

				SectImagePriority = 3;
			}
			SectImagePriority = htonl(SectImagePriority);
			Status = BcmFlash2xBulkWrite(Adapter,
						&SectImagePriority,
						eFlash2xSectVal,
						Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority),
						SIGNATURE_SIZE,
						TRUE);
			if (Status) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
				Status = STATUS_FAILURE;
				break;
			}
		} else {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority");
			Status = STATUS_FAILURE;
			break;
		}
		break;
	case VSA0:
	case VSA1:
	case VSA2:
		/* Has to be decided */
		break;
	default:
		Status = STATUS_FAILURE;
		break;
	}

	Adapter->bHeaderChangeAllowed = FALSE;
	return Status;
}

/*
 * BcmCopyISO - Used only for copying the ISO section
 * @Adapater :- Bcm Driver Private Data Structure
 * @sCopySectStrut :- Section copy structure
 *
 * Return value:- SUCCESS if copies successfully else negative error code
 *
 */

int BcmCopyISO(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_copy_section sCopySectStrut)
{
	PCHAR Buff = NULL;
	enum bcm_flash2x_section_val eISOReadPart = 0, eISOWritePart = 0;
	unsigned int uiReadOffsetWithinPart = 0, uiWriteOffsetWithinPart = 0;
	unsigned int uiTotalDataToCopy = 0;
	BOOLEAN IsThisHeaderSector = FALSE;
	unsigned int sigOffset = 0;
	unsigned int ISOLength = 0;
	unsigned int Status = STATUS_SUCCESS;
	unsigned int SigBuff[MAX_RW_SIZE];
	unsigned int i = 0;

	if (ReadISOSignature(Adapter, sCopySectStrut.SrcSection) != ISO_IMAGE_MAGIC_NUMBER) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature");
		return STATUS_FAILURE;
	}

	Status = BcmFlash2xBulkRead(Adapter,
				&ISOLength,
				sCopySectStrut.SrcSection,
				0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageSize),
				4);
	if (Status) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO\n");
		return Status;
	}

	ISOLength = htonl(ISOLength);
	if (ISOLength % Adapter->uiSectorSize)
		ISOLength = Adapter->uiSectorSize * (1 + ISOLength/Adapter->uiSectorSize);

	sigOffset = FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageMagicNumber);

	Buff = kzalloc(Adapter->uiSectorSize, GFP_KERNEL);

	if (!Buff) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for section size");
		return -ENOMEM;
	}

	if (sCopySectStrut.SrcSection == ISO_IMAGE1 && sCopySectStrut.DstSection == ISO_IMAGE2) {
		eISOReadPart = ISO_IMAGE1;
		eISOWritePart = ISO_IMAGE2;
		uiReadOffsetWithinPart =  0;
		uiWriteOffsetWithinPart = 0;

		uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) +
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start) +
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start);

		if (uiTotalDataToCopy < ISOLength) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature");
			Status = STATUS_FAILURE;
			goto out;
		}

		uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) +
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start) +
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start);

		if (uiTotalDataToCopy < ISOLength) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size");
			Status = STATUS_FAILURE;
			goto out;
		}

		uiTotalDataToCopy = ISOLength;

		CorruptISOSig(Adapter, ISO_IMAGE2);
		while (uiTotalDataToCopy) {
			if (uiTotalDataToCopy == Adapter->uiSectorSize) {
				/* Setting for write of first sector. First sector is assumed to be written in last */
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector");
				eISOReadPart = ISO_IMAGE1;
				uiReadOffsetWithinPart = 0;
				eISOWritePart = ISO_IMAGE2;
				uiWriteOffsetWithinPart = 0;
				IsThisHeaderSector = TRUE;
			} else {
				uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize;
				uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize;

				if ((eISOReadPart == ISO_IMAGE1) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) {
					eISOReadPart = ISO_IMAGE1_PART2;
					uiReadOffsetWithinPart = 0;
				}

				if ((eISOReadPart == ISO_IMAGE1_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) {
					eISOReadPart = ISO_IMAGE1_PART3;
					uiReadOffsetWithinPart = 0;
				}

				if ((eISOWritePart == ISO_IMAGE2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) {
					eISOWritePart = ISO_IMAGE2_PART2;
					uiWriteOffsetWithinPart = 0;
				}

				if ((eISOWritePart == ISO_IMAGE2_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) {
					eISOWritePart = ISO_IMAGE2_PART3;
					uiWriteOffsetWithinPart = 0;
				}
			}

			Status = BcmFlash2xBulkRead(Adapter,
						(PUINT)Buff,
						eISOReadPart,
						uiReadOffsetWithinPart,
						Adapter->uiSectorSize);
			if (Status) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart);
				break;
			}

			if (IsThisHeaderSector == TRUE) {
				/* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */
				memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE);

				for (i = 0; i < MAX_RW_SIZE; i++)
					*(Buff + sigOffset + i) = 0xFF;
			}
			Adapter->bHeaderChangeAllowed = TRUE;
			Status = BcmFlash2xBulkWrite(Adapter,
						(PUINT)Buff,
						eISOWritePart,
						uiWriteOffsetWithinPart,
						Adapter->uiSectorSize,
						TRUE);
			if (Status) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart);
				break;
			}

			Adapter->bHeaderChangeAllowed = FALSE;
			if (IsThisHeaderSector == TRUE) {
				WriteToFlashWithoutSectorErase(Adapter,
							SigBuff,
							eISOWritePart,
							sigOffset,
							MAX_RW_SIZE);
				IsThisHeaderSector = FALSE;
			}
			/* subtracting the written Data */
			uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize;
		}
	}

	if (sCopySectStrut.SrcSection == ISO_IMAGE2 && sCopySectStrut.DstSection == ISO_IMAGE1) {
		eISOReadPart = ISO_IMAGE2;
		eISOWritePart = ISO_IMAGE1;
		uiReadOffsetWithinPart = 0;
		uiWriteOffsetWithinPart = 0;

		uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) +
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start) +
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start);

		if (uiTotalDataToCopy < ISOLength) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature");
			Status = STATUS_FAILURE;
			goto out;
		}

		uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) +
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start) +
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) -
			(Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start);

		if (uiTotalDataToCopy < ISOLength) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size");
			Status = STATUS_FAILURE;
			goto out;
		}

		uiTotalDataToCopy = ISOLength;

		CorruptISOSig(Adapter, ISO_IMAGE1);

		while (uiTotalDataToCopy) {
			if (uiTotalDataToCopy == Adapter->uiSectorSize) {
				/* Setting for write of first sector. First sector is assumed to be written in last */
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector");
				eISOReadPart = ISO_IMAGE2;
				uiReadOffsetWithinPart = 0;
				eISOWritePart = ISO_IMAGE1;
				uiWriteOffsetWithinPart = 0;
				IsThisHeaderSector = TRUE;
			} else {
				uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize;
				uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize;

				if ((eISOReadPart == ISO_IMAGE2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) {
					eISOReadPart = ISO_IMAGE2_PART2;
					uiReadOffsetWithinPart = 0;
				}

				if ((eISOReadPart == ISO_IMAGE2_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) {
					eISOReadPart = ISO_IMAGE2_PART3;
					uiReadOffsetWithinPart = 0;
				}

				if ((eISOWritePart == ISO_IMAGE1) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) {
					eISOWritePart = ISO_IMAGE1_PART2;
					uiWriteOffsetWithinPart = 0;
				}

				if ((eISOWritePart == ISO_IMAGE1_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) {
					eISOWritePart = ISO_IMAGE1_PART3;
					uiWriteOffsetWithinPart = 0;
				}
			}

			Status = BcmFlash2xBulkRead(Adapter,
						(PUINT)Buff,
						eISOReadPart,
						uiReadOffsetWithinPart,
						Adapter->uiSectorSize);
			if (Status) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart);
				break;
			}

			if (IsThisHeaderSector == TRUE) {
				/* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */
				memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE);

				for (i = 0; i < MAX_RW_SIZE; i++)
					*(Buff + sigOffset + i) = 0xFF;
			}
			Adapter->bHeaderChangeAllowed = TRUE;
			Status = BcmFlash2xBulkWrite(Adapter,
						(PUINT)Buff,
						eISOWritePart,
						uiWriteOffsetWithinPart,
						Adapter->uiSectorSize,
						TRUE);
			if (Status) {
				BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart);
				break;
			}

			Adapter->bHeaderChangeAllowed = FALSE;
			if (IsThisHeaderSector == TRUE) {
				WriteToFlashWithoutSectorErase(Adapter,
							SigBuff,
							eISOWritePart,
							sigOffset,
							MAX_RW_SIZE);

				IsThisHeaderSector = FALSE;
			}

			/* subtracting the written Data */
			uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize;
		}
	}
out:
	kfree(Buff);

	return Status;
}

/*
 * BcmFlash2xCorruptSig : this API is used to corrupt the written sig in Bcm Header present in flash section.
 * It will corrupt the sig, if Section is writable, by making first bytes as zero.
 * @Adapater :- Bcm Driver Private Data Structure
 * @eFlash2xSectionVal :- Flash section val which has header
 *
 * Return Value :-
 *	Success :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS
 *	Failure :-Return negative error code
 */

int BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
{
	int Status = STATUS_SUCCESS;

	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Value :%x\n", eFlash2xSectionVal);

	if ((eFlash2xSectionVal == DSD0) || (eFlash2xSectionVal == DSD1) || (eFlash2xSectionVal == DSD2)) {
		Status = CorruptDSDSig(Adapter, eFlash2xSectionVal);
	} else if (eFlash2xSectionVal == ISO_IMAGE1 || eFlash2xSectionVal == ISO_IMAGE2) {
		Status = CorruptISOSig(Adapter, eFlash2xSectionVal);
	} else {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given Section <%d>does not have Header", eFlash2xSectionVal);
		return STATUS_SUCCESS;
	}
	return Status;
}

/*
 *BcmFlash2xWriteSig :-this API is used to Write the sig if requested Section has
 *					  header and  Write Permission.
 * @Adapater :- Bcm Driver Private Data Structure
 * @eFlashSectionVal :- Flash section val which has header
 *
 * Return Value :-
 *	Success :- If Section is present and writable write the sig and return STATUS_SUCCESS
 *	Failure :-Return negative error code
 */

int BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal)
{
	unsigned int uiSignature = 0;
	unsigned int uiOffset = 0;

	/* struct bcm_dsd_header dsdHeader = {0}; */
	if (Adapter->bSigCorrupted == FALSE) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is not corrupted by driver, hence not restoring\n");
		return STATUS_SUCCESS;
	}

	if (Adapter->bAllDSDWriteAllow == FALSE) {
		if (IsSectionWritable(Adapter, eFlashSectionVal) == FALSE) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Write signature");
			return SECTOR_IS_NOT_WRITABLE;
		}
	}

	if ((eFlashSectionVal == DSD0) || (eFlashSectionVal == DSD1) || (eFlashSectionVal == DSD2)) {
		uiSignature = htonl(DSD_IMAGE_MAGIC_NUMBER);
		uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader;

		uiOffset += FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber);

		if ((ReadDSDSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Corrupted Pattern is not there. Hence won't write sig");
			return STATUS_FAILURE;
		}
	} else if ((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) {
		uiSignature = htonl(ISO_IMAGE_MAGIC_NUMBER);
		/* uiOffset = 0; */
		uiOffset = FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageMagicNumber);
		if ((ReadISOSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Currupted Pattern is not there. Hence won't write sig");
			return STATUS_FAILURE;
		}
	} else {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GIVEN SECTION< %d > IS NOT VALID FOR SIG WRITE...", eFlashSectionVal);
		return STATUS_FAILURE;
	}

	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature");

	Adapter->bHeaderChangeAllowed = TRUE;
	Adapter->bSigCorrupted = FALSE;
	BcmFlash2xBulkWrite(Adapter, &uiSignature, eFlashSectionVal, uiOffset, SIGNATURE_SIZE, TRUE);
	Adapter->bHeaderChangeAllowed = FALSE;

	return STATUS_SUCCESS;
}

/*
 * validateFlash2xReadWrite :- This API is used to validate the user request for Read/Write.
 *						      if requested Bytes goes beyond the Requested section, it reports error.
 * @Adapater :- Bcm Driver Private Data Structure
 * @psFlash2xReadWrite :-Flash2x Read/write structure pointer
 *
 * Return values:-Return TRUE is request is valid else FALSE.
 */

int validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_readwrite *psFlash2xReadWrite)
{
	unsigned int uiNumOfBytes = 0;
	unsigned int uiSectStartOffset = 0;
	unsigned int uiSectEndOffset = 0;

	uiNumOfBytes = psFlash2xReadWrite->numOfBytes;

	if (IsSectionExistInFlash(Adapter, psFlash2xReadWrite->Section) != TRUE) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%x> does not exixt in Flash", psFlash2xReadWrite->Section);
		return FALSE;
	}
	uiSectStartOffset = BcmGetSectionValStartOffset(Adapter, psFlash2xReadWrite->Section);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Start offset :%x ,section :%d\n", uiSectStartOffset, psFlash2xReadWrite->Section);
	if ((psFlash2xReadWrite->Section == ISO_IMAGE1) || (psFlash2xReadWrite->Section == ISO_IMAGE2)) {
		if (psFlash2xReadWrite->Section == ISO_IMAGE1) {
			uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1) -
				BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) +
				BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART2) -
				BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART2) +
				BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART3) -
				BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART3);
		} else if (psFlash2xReadWrite->Section == ISO_IMAGE2) {
			uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2) -
				BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2) +
				BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART2) -
				BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART2) +
				BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART3) -
				BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART3);
		}

		/* since this uiSectEndoffset is the size of iso Image. hence for calculating the virtual endoffset
		 * it should be added in startoffset. so that check done in last of this function can be valued.
		 */
		uiSectEndOffset = uiSectStartOffset + uiSectEndOffset;

		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Total size of the ISO Image :%x", uiSectEndOffset);
	} else
		uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, psFlash2xReadWrite->Section);

	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "End offset :%x\n", uiSectEndOffset);

	/* Checking the boundary condition */
	if ((uiSectStartOffset + psFlash2xReadWrite->offset + uiNumOfBytes) <= uiSectEndOffset)
		return TRUE;
	else {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request....");
		return FALSE;
	}
}

/*
 * IsFlash2x :- check for Flash 2.x
 * Adapater :- Bcm Driver Private Data Structure
 *
 * Return value:-
 *	return TRUE if flah2.x of hgher version else return false.
 */

int IsFlash2x(struct bcm_mini_adapter *Adapter)
{
	if (Adapter->uiFlashLayoutMajorVersion >= FLASH_2X_MAJOR_NUMBER)
		return TRUE;
	else
		return FALSE;
}

/*
 * GetFlashBaseAddr :- Calculate the Flash Base address
 * @Adapater :- Bcm Driver Private Data Structure
 *
 * Return Value:-
 *	Success :- Base Address of the Flash
 */

static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter)
{
	unsigned int uiBaseAddr = 0;

	if (Adapter->bDDRInitDone) {
		/*
		 * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr
		 * In case of Raw Read... use the default value
		 */
		if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) &&
			!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
			uiBaseAddr = Adapter->uiFlashBaseAdd;
		else
			uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT;
	} else {
		/*
		 * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr
		 * In case of Raw Read... use the default value
		 */
		if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) &&
			!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
			uiBaseAddr = Adapter->uiFlashBaseAdd | FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT;
		else
			uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT;
	}

	return uiBaseAddr;
}

/*
 * BcmCopySection :- This API is used to copy the One section in another. Both section should
 *				    be contiuous and of same size. Hence this Will not be applicabe to copy ISO.
 *
 * @Adapater :- Bcm Driver Private Data Structure
 * @SrcSection :- Source section From where data has to be copied
 * @DstSection :- Destination section to which data has to be copied
 * @offset :- Offset from/to  where data has to be copied from one section to another.
 * @numOfBytes :- number of byes that has to be copyed from one section to another at given offset.
 *			     in case of numofBytes  equal zero complete section will be copied.
 * Return Values-
 *	Success : Return STATUS_SUCCESS
 *	Faillure :- return negative error code
 */

int BcmCopySection(struct bcm_mini_adapter *Adapter,
		enum bcm_flash2x_section_val SrcSection,
		enum bcm_flash2x_section_val DstSection,
		unsigned int offset,
		unsigned int numOfBytes)
{
	unsigned int BuffSize = 0;
	unsigned int BytesToBeCopied = 0;
	PUCHAR pBuff = NULL;
	int Status = STATUS_SUCCESS;

	if (SrcSection == DstSection) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source and Destination should be different ...try again");
		return -EINVAL;
	}

	if ((SrcSection != DSD0) && (SrcSection != DSD1) && (SrcSection != DSD2)) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source should be DSD subsection");
		return -EINVAL;
	}

	if ((DstSection != DSD0) && (DstSection != DSD1) && (DstSection != DSD2)) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destination should be DSD subsection");
		return -EINVAL;
	}

	/* if offset zero means have to copy complete secton */
	if (numOfBytes == 0) {
		numOfBytes = BcmGetSectionValEndOffset(Adapter, SrcSection)
			- BcmGetSectionValStartOffset(Adapter, SrcSection);

		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Section Size :0x%x", numOfBytes);
	}

	if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, SrcSection)
		- BcmGetSectionValStartOffset(Adapter, SrcSection)) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " Input parameters going beyond the section offS: %x numB: %x of Source Section\n",
				offset, numOfBytes);
		return -EINVAL;
	}

	if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, DstSection)
		- BcmGetSectionValStartOffset(Adapter, DstSection)) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Input parameters going beyond the section offS: %x numB: %x of Destination Section\n",
				offset, numOfBytes);
		return -EINVAL;
	}

	if (numOfBytes > Adapter->uiSectorSize)
		BuffSize = Adapter->uiSectorSize;
	else
		BuffSize = numOfBytes;

	pBuff = kzalloc(BuffSize, GFP_KERNEL);
	if (!pBuff) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed.. ");
		return -ENOMEM;
	}

	BytesToBeCopied = Adapter->uiSectorSize;
	if (offset % Adapter->uiSectorSize)
		BytesToBeCopied = Adapter->uiSectorSize - (offset % Adapter->uiSectorSize);
	if (BytesToBeCopied > numOfBytes)
		BytesToBeCopied = numOfBytes;

	Adapter->bHeaderChangeAllowed = TRUE;

	do {
		Status = BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, SrcSection , offset, BytesToBeCopied);
		if (Status) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed at offset :%d for NOB :%d", SrcSection, BytesToBeCopied);
			break;
		}
		Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pBuff, DstSection, offset, BytesToBeCopied, FALSE);
		if (Status) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed at offset :%d for NOB :%d", DstSection, BytesToBeCopied);
			break;
		}
		offset = offset + BytesToBeCopied;
		numOfBytes = numOfBytes - BytesToBeCopied;
		if (numOfBytes) {
			if (numOfBytes > Adapter->uiSectorSize)
				BytesToBeCopied = Adapter->uiSectorSize;
			else
				BytesToBeCopied = numOfBytes;
		}
	} while (numOfBytes > 0);

	kfree(pBuff);
	Adapter->bHeaderChangeAllowed = FALSE;

	return Status;
}

/*
 * SaveHeaderIfPresent :- This API is use to Protect the Header in case of Header Sector write
 * @Adapater :- Bcm Driver Private Data Structure
 * @pBuff :- Data buffer that has to be written in sector having the header map.
 * @uiOffset :- Flash offset that has to be written.
 *
 * Return value :-
 *	Success :- On success return STATUS_SUCCESS
 *	Faillure :- Return negative error code
 */

int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned int uiOffset)
{
	unsigned int offsetToProtect = 0, HeaderSizeToProtect = 0;
	BOOLEAN bHasHeader = FALSE;
	PUCHAR pTempBuff = NULL;
	unsigned int uiSectAlignAddr = 0;
	unsigned int sig = 0;

	/* making the offset sector aligned */
	uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);

	if ((uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD2) - Adapter->uiSectorSize) ||
		(uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD1) - Adapter->uiSectorSize) ||
		(uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD0) - Adapter->uiSectorSize)) {
		/* offset from the sector boundary having the header map */
		offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize;
		HeaderSizeToProtect = sizeof(struct bcm_dsd_header);
		bHasHeader = TRUE;
	}

	if (uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) ||
		uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2)) {
		offsetToProtect = 0;
		HeaderSizeToProtect = sizeof(struct bcm_iso_header);
		bHasHeader = TRUE;
	}
	/* If Header is present overwrite passed buffer with this */
	if (bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) {
		pTempBuff = kzalloc(HeaderSizeToProtect, GFP_KERNEL);
		if (!pTempBuff) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed");
			return -ENOMEM;
		}
		/* Read header */
		BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, (uiSectAlignAddr + offsetToProtect), HeaderSizeToProtect);
		BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pTempBuff, HeaderSizeToProtect);
		/* Replace Buffer content with Header */
		memcpy(pBuff + offsetToProtect, pTempBuff, HeaderSizeToProtect);

		kfree(pTempBuff);
	}
	if (bHasHeader && Adapter->bSigCorrupted) {
		sig = *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber)));
		sig = ntohl(sig);
		if ((sig & 0xFF000000) != CORRUPTED_PATTERN) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Desired pattern is not at sig offset. Hence won't restore");
			Adapter->bSigCorrupted = FALSE;
			return STATUS_SUCCESS;
		}
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Corrupted sig is :%X", sig);
		*((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber))) = htonl(DSD_IMAGE_MAGIC_NUMBER);
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature in Header Write only");
		Adapter->bSigCorrupted = FALSE;
	}

	return STATUS_SUCCESS;
}

/*
 * BcmDoChipSelect : This will selcet the appropriate chip for writing.
 * @Adapater :- Bcm Driver Private Data Structure
 *
 * OutPut:-
 *	Select the Appropriate chip and retrn status Success
 */
static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter, unsigned int offset)
{
	unsigned int FlashConfig = 0;
	int ChipNum = 0;
	unsigned int GPIOConfig = 0;
	unsigned int PartNum = 0;

	ChipNum = offset / FLASH_PART_SIZE;

	/*
	 * Chip Select mapping to enable flash0.
	 * To select flash 0, we have to OR with (0<<12).
	 * ORing 0 will have no impact so not doing that part.
	 * In future if Chip select value changes from 0 to non zero,
	 * That needs be taken care with backward comaptibility. No worries for now.
	 */

	/*
	 * SelectedChip Variable is the selection that the host is 100% Sure the same as what the register will hold. This can be ONLY ensured
	 * if the Chip doesn't goes to low power mode while the flash operation is in progress (NVMRdmWrmLock is taken)
	 * Before every new Flash Write operation, we reset the variable. This is to ensure that after any wake-up from
	 * power down modes (Idle mode/shutdown mode), the values in the register will be different.
	 */

	if (Adapter->SelectedChip == ChipNum)
		return STATUS_SUCCESS;

	/* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Selected Chip :%x", ChipNum); */
	Adapter->SelectedChip = ChipNum;

	/* bit[13..12]  will select the appropriate chip */
	rdmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4);
	rdmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4);
	{
		switch (ChipNum) {
		case 0:
			PartNum = 0;
			break;
		case 1:
			PartNum = 3;
			GPIOConfig |= (0x4 << CHIP_SELECT_BIT12);
			break;
		case 2:
			PartNum = 1;
			GPIOConfig |= (0x1 << CHIP_SELECT_BIT12);
			break;
		case 3:
			PartNum = 2;
			GPIOConfig |= (0x2 << CHIP_SELECT_BIT12);
			break;
		}
	}
	/* In case the bits already written in the FLASH_CONFIG_REG is same as what the user desired,
	 * nothing to do... can return immediately.
	 * ASSUMPTION: FLASH_GPIO_CONFIG_REG will be in sync with FLASH_CONFIG_REG.
	 * Even if the chip goes to low power mode, it should wake with values in each register in sync with each other.
	 * These values are not written by host other than during CHIP_SELECT.
	 */
	if (PartNum == ((FlashConfig >> CHIP_SELECT_BIT12) & 0x3))
		return STATUS_SUCCESS;

	/* clearing the bit[13..12] */
	FlashConfig &= 0xFFFFCFFF;
	FlashConfig = (FlashConfig | (PartNum<<CHIP_SELECT_BIT12)); /* 00 */

	wrmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4);
	udelay(100);

	wrmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4);
	udelay(100);

	return STATUS_SUCCESS;
}

int ReadDSDSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd)
{
	unsigned int uiDSDsig = 0;
	/* unsigned int sigoffsetInMap = 0;
	 * struct bcm_dsd_header dsdHeader = {0};
	 */

	/* sigoffsetInMap =(PUCHAR)&(dsdHeader.DSDImageMagicNumber) -(PUCHAR)&dsdHeader; */

	if (dsd != DSD0 && dsd != DSD1 && dsd != DSD2) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for DSDs");
		return STATUS_FAILURE;
	}
	BcmFlash2xBulkRead(Adapter,
			&uiDSDsig,
			dsd,
			Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber),
			SIGNATURE_SIZE);

	uiDSDsig = ntohl(uiDSDsig);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD SIG :%x", uiDSDsig);

	return uiDSDsig;
}

int ReadDSDPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd)
{
	/* unsigned int priOffsetInMap = 0 ; */
	unsigned int uiDSDPri = STATUS_FAILURE;
	/* struct bcm_dsd_header dsdHeader = {0};
	 * priOffsetInMap = (PUCHAR)&(dsdHeader.DSDImagePriority) -(PUCHAR)&dsdHeader;
	 */
	if (IsSectionWritable(Adapter, dsd)) {
		if (ReadDSDSignature(Adapter, dsd) == DSD_IMAGE_MAGIC_NUMBER) {
			BcmFlash2xBulkRead(Adapter,
					&uiDSDPri,
					dsd,
					Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority),
					4);

			uiDSDPri = ntohl(uiDSDPri);
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD<%x> Priority :%x", dsd, uiDSDPri);
		}
	}

	return uiDSDPri;
}

enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter)
{
	int DSDHighestPri = STATUS_FAILURE;
	int DsdPri = 0;
	enum bcm_flash2x_section_val HighestPriDSD = 0;

	if (IsSectionWritable(Adapter, DSD2)) {
		DSDHighestPri = ReadDSDPriority(Adapter, DSD2);
		HighestPriDSD = DSD2;
	}

	if (IsSectionWritable(Adapter, DSD1)) {
		DsdPri = ReadDSDPriority(Adapter, DSD1);
		if (DSDHighestPri  < DsdPri) {
			DSDHighestPri = DsdPri;
			HighestPriDSD = DSD1;
		}
	}

	if (IsSectionWritable(Adapter, DSD0)) {
		DsdPri = ReadDSDPriority(Adapter, DSD0);
		if (DSDHighestPri  < DsdPri) {
			DSDHighestPri = DsdPri;
			HighestPriDSD = DSD0;
		}
	}
	if (HighestPriDSD)
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest DSD :%x , and its  Pri :%x", HighestPriDSD, DSDHighestPri);

	return  HighestPriDSD;
}

int ReadISOSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso)
{
	unsigned int uiISOsig = 0;
	/* unsigned int sigoffsetInMap = 0;
	 * struct bcm_iso_header ISOHeader = {0};
	 * sigoffsetInMap =(PUCHAR)&(ISOHeader.ISOImageMagicNumber) -(PUCHAR)&ISOHeader;
	 */
	if (iso != ISO_IMAGE1 && iso != ISO_IMAGE2) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for ISOs");
		return STATUS_FAILURE;
	}
	BcmFlash2xBulkRead(Adapter,
			&uiISOsig,
			iso,
			0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageMagicNumber),
			SIGNATURE_SIZE);

	uiISOsig = ntohl(uiISOsig);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO SIG :%x", uiISOsig);

	return uiISOsig;
}

int ReadISOPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso)
{
	unsigned int ISOPri = STATUS_FAILURE;
	if (IsSectionWritable(Adapter, iso)) {
		if (ReadISOSignature(Adapter, iso) == ISO_IMAGE_MAGIC_NUMBER) {
			BcmFlash2xBulkRead(Adapter,
					&ISOPri,
					iso,
					0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImagePriority),
					4);

			ISOPri = ntohl(ISOPri);
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO<%x> Priority :%x", iso, ISOPri);
		}
	}

	return ISOPri;
}

enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter)
{
	int ISOHighestPri = STATUS_FAILURE;
	int ISOPri = 0;
	enum bcm_flash2x_section_val HighestPriISO = NO_SECTION_VAL;

	if (IsSectionWritable(Adapter, ISO_IMAGE2)) {
		ISOHighestPri = ReadISOPriority(Adapter, ISO_IMAGE2);
		HighestPriISO = ISO_IMAGE2;
	}

	if (IsSectionWritable(Adapter, ISO_IMAGE1)) {
		ISOPri = ReadISOPriority(Adapter, ISO_IMAGE1);
		if (ISOHighestPri  < ISOPri) {
			ISOHighestPri = ISOPri;
			HighestPriISO = ISO_IMAGE1;
		}
	}
	if (HighestPriISO)
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest ISO :%x and its Pri :%x", HighestPriISO, ISOHighestPri);

	return HighestPriISO;
}

int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter,
				PUINT pBuff,
				enum bcm_flash2x_section_val eFlash2xSectionVal,
				unsigned int uiOffset,
				unsigned int uiNumBytes)
{
	#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
		unsigned int uiTemp = 0, value = 0;
		unsigned int i = 0;
		unsigned int uiPartOffset = 0;
	#endif
	unsigned int uiStartOffset = 0;
	/* Adding section start address */
	int Status = STATUS_SUCCESS;
	PUCHAR pcBuff = (PUCHAR)pBuff;

	if (uiNumBytes % Adapter->ulFlashWriteSize) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Writing without Sector Erase for non-FlashWriteSize number of bytes 0x%x\n", uiNumBytes);
		return STATUS_FAILURE;
	}

	uiStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);

	if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal))
		return vendorextnWriteSectionWithoutErase(Adapter, pcBuff, eFlash2xSectionVal, uiOffset, uiNumBytes);

	uiOffset = uiOffset + uiStartOffset;

	#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
		Status = bcmflash_raw_writenoerase((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), pcBuff, uiNumBytes);
	#else
		rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
		value = 0;
		wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));

		Adapter->SelectedChip = RESET_CHIP_SELECT;
		BcmDoChipSelect(Adapter, uiOffset);
		uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);

		for (i = 0 ; i < uiNumBytes; i += Adapter->ulFlashWriteSize) {
			if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT)
				Status = flashByteWrite(Adapter, uiPartOffset, pcBuff);
			else
				Status = flashWrite(Adapter, uiPartOffset, pcBuff);

			if (Status != STATUS_SUCCESS)
				break;

			pcBuff = pcBuff + Adapter->ulFlashWriteSize;
			uiPartOffset = uiPartOffset +  Adapter->ulFlashWriteSize;
		}
		wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
		Adapter->SelectedChip = RESET_CHIP_SELECT;
	#endif

	return Status;
}

BOOLEAN IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section)
{
	BOOLEAN SectionPresent = FALSE;

	switch (section) {
	case ISO_IMAGE1:
		if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) &&
			(IsNonCDLessDevice(Adapter) == FALSE))
			SectionPresent = TRUE;
		break;
	case ISO_IMAGE2:
		if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) &&
			(IsNonCDLessDevice(Adapter) == FALSE))
			SectionPresent = TRUE;
		break;
	case DSD0:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS)
			SectionPresent = TRUE;
		break;
	case DSD1:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS)
			SectionPresent = TRUE;
		break;
	case DSD2:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS)
			SectionPresent = TRUE;
		break;
	case VSA0:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS)
			SectionPresent = TRUE;
		break;
	case VSA1:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS)
			SectionPresent = TRUE;
		break;
	case VSA2:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS)
			SectionPresent = TRUE;
		break;
	case SCSI:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS)
			SectionPresent = TRUE;
		break;
	case CONTROL_SECTION:
		if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS)
			SectionPresent = TRUE;
		break;
	default:
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x");
		SectionPresent =  FALSE;
	}

	return SectionPresent;
}

int IsSectionWritable(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val Section)
{
	int offset = STATUS_FAILURE;
	int Status = FALSE;

	if (IsSectionExistInFlash(Adapter, Section) == FALSE) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section <%d> does not exixt", Section);
		return FALSE;
	}

	offset = BcmGetSectionValStartOffset(Adapter, Section);
	if (offset == INVALID_OFFSET) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%d> does not exixt", Section);
		return FALSE;
	}

	if (IsSectionExistInVendorInfo(Adapter, Section))
		return !(Adapter->psFlash2xVendorInfo->VendorSection[Section].AccessFlags & FLASH2X_SECTION_RO);

	Status = IsOffsetWritable(Adapter, offset);
	return Status;
}

static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
{
	PUCHAR pBuff = NULL;
	unsigned int sig = 0;
	unsigned int uiOffset = 0;
	unsigned int BlockStatus = 0;
	unsigned int uiSectAlignAddr = 0;

	Adapter->bSigCorrupted = FALSE;
	if (Adapter->bAllDSDWriteAllow == FALSE) {
		if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) {
			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature");
			return SECTOR_IS_NOT_WRITABLE;
		}
	}

	pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL);
	if (!pBuff) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
		return -ENOMEM;
	}

	uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header);
	uiOffset -= MAX_RW_SIZE;

	BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE);

	sig = *((PUINT)(pBuff + 12));
	sig = ntohl(sig);
	BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE);
	/* Now corrupting the sig by corrupting 4th last Byte. */
	*(pBuff + 12) = 0;

	if (sig == DSD_IMAGE_MAGIC_NUMBER) {
		Adapter->bSigCorrupted = TRUE;
		if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) {
			uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);
			BlockStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize);

			WriteToFlashWithoutSectorErase(Adapter, (PUINT)(pBuff + 12), eFlash2xSectionVal,
						(uiOffset + 12), BYTE_WRITE_SUPPORT);
			if (BlockStatus) {
				BcmRestoreBlockProtectStatus(Adapter, BlockStatus);
				BlockStatus = 0;
			}
		} else {
			WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal,
						uiOffset, MAX_RW_SIZE);
		}
	} else {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header");
		kfree(pBuff);

		return STATUS_FAILURE;
	}

	kfree(pBuff);
	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature");

	return STATUS_SUCCESS;
}

static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal)
{
	PUCHAR pBuff = NULL;
	unsigned int sig = 0;
	unsigned int uiOffset = 0;

	Adapter->bSigCorrupted = FALSE;

	if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature");
		return SECTOR_IS_NOT_WRITABLE;
	}

	pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL);
	if (!pBuff) {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
		return -ENOMEM;
	}

	uiOffset = 0;

	BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE);

	sig = *((PUINT)pBuff);
	sig = ntohl(sig);

	/* corrupt signature */
	*pBuff = 0;

	if (sig == ISO_IMAGE_MAGIC_NUMBER) {
		Adapter->bSigCorrupted = TRUE;
		WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal,
					uiOffset, Adapter->ulFlashWriteSize);
	} else {
		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header");
		kfree(pBuff);

		return STATUS_FAILURE;
	}

	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature");
	BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE);

	kfree(pBuff);
	return STATUS_SUCCESS;
}

BOOLEAN IsNonCDLessDevice(struct bcm_mini_adapter *Adapter)
{
	if (Adapter->psFlash2xCSInfo->IsCDLessDeviceBootSig == NON_CDLESS_DEVICE_BOOT_SIG)
		return TRUE;
	else
		return FALSE;
}