| #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, |
| bool 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: |
| */ |
| |
| static 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, |
| bool 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, |
| bool 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: 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, |
| bool 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, |
| bool 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 |
| */ |
| |
| static 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 exist 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; */ |
| |