blob: bea1330f7ea6952aae258d26af35c114ed5f8e3a [file] [log] [blame]
#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)))