1#include "headers.h" 2 3#define DWORD unsigned int 4 5static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter, 6 unsigned int offset); 7static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter); 8static int BcmGetActiveISO(struct bcm_mini_adapter *Adapter); 9static unsigned int BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter); 10static int BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter); 11static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, 12 unsigned int FlashSectorSizeSig, 13 unsigned int FlashSectorSize); 14 15static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter); 16static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter); 17static unsigned int BcmGetFlashSize(struct bcm_mini_adapter *Adapter); 18static enum bcm_nvm_type BcmGetNvmType(struct bcm_mini_adapter *Adapter); 19 20static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, 21 enum bcm_flash2x_section_val eFlash2xSectionVal); 22 23static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, 24 unsigned int uiOffset); 25static int IsSectionWritable(struct bcm_mini_adapter *Adapter, 26 enum bcm_flash2x_section_val Section); 27static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, 28 enum bcm_flash2x_section_val section); 29 30static int ReadDSDPriority(struct bcm_mini_adapter *Adapter, 31 enum bcm_flash2x_section_val dsd); 32static int ReadDSDSignature(struct bcm_mini_adapter *Adapter, 33 enum bcm_flash2x_section_val dsd); 34static int ReadISOPriority(struct bcm_mini_adapter *Adapter, 35 enum bcm_flash2x_section_val iso); 36static int ReadISOSignature(struct bcm_mini_adapter *Adapter, 37 enum bcm_flash2x_section_val iso); 38 39static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, 40 enum bcm_flash2x_section_val eFlash2xSectionVal); 41static int CorruptISOSig(struct bcm_mini_adapter *Adapter, 42 enum bcm_flash2x_section_val eFlash2xSectionVal); 43static int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, 44 PUCHAR pBuff, 45 unsigned int uiSectAlignAddr); 46static int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, 47 PUINT pBuff, 48 enum bcm_flash2x_section_val eFlash2xSectionVal, 49 unsigned int uiOffset, 50 unsigned int uiNumBytes); 51static enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter); 52static enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter); 53 54static int BeceemFlashBulkRead( 55 struct bcm_mini_adapter *Adapter, 56 PUINT pBuffer, 57 unsigned int uiOffset, 58 unsigned int uiNumBytes); 59 60static int BeceemFlashBulkWrite( 61 struct bcm_mini_adapter *Adapter, 62 PUINT pBuffer, 63 unsigned int uiOffset, 64 unsigned int uiNumBytes, 65 bool bVerify); 66 67static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter); 68 69static int ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, unsigned int dwAddress, unsigned int *pdwData, unsigned int dwNumData); 70 71/* Procedure: ReadEEPROMStatusRegister 72 * 73 * Description: Reads the standard EEPROM Status Register. 74 * 75 * Arguments: 76 * Adapter - ptr to Adapter object instance 77 * Returns: 78 * OSAL_STATUS_CODE 79 */ 80static UCHAR ReadEEPROMStatusRegister(struct bcm_mini_adapter *Adapter) 81{ 82 UCHAR uiData = 0; 83 DWORD dwRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; 84 unsigned int uiStatus = 0; 85 unsigned int value = 0; 86 unsigned int value1 = 0; 87 88 /* Read the EEPROM status register */ 89 value = EEPROM_READ_STATUS_REGISTER; 90 wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); 91 92 while (dwRetries != 0) { 93 value = 0; 94 uiStatus = 0; 95 rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); 96 if (Adapter->device_removed == TRUE) { 97 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting...."); 98 break; 99 } 100 101 /* Wait for Avail bit to be set. */ 102 if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) { 103 /* Clear the Avail/Full bits - which ever is set. */ 104 value = uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL); 105 wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); 106 107 value = 0; 108 rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); 109 uiData = (UCHAR)value; 110 111 break; 112 } 113 114 dwRetries--; 115 if (dwRetries == 0) { 116 rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); 117 rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1)); 118 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); 119 return uiData; 120 } 121 if (!(dwRetries%RETRIES_PER_DELAY)) 122 udelay(1000); 123 uiStatus = 0; 124 } 125 return uiData; 126} /* ReadEEPROMStatusRegister */ 127 128/* 129 * Procedure: ReadBeceemEEPROMBulk 130 * 131 * Description: This routine reads 16Byte data from EEPROM 132 * 133 * Arguments: 134 * Adapter - ptr to Adapter object instance 135 * dwAddress - EEPROM Offset to read the data from. 136 * pdwData - Pointer to double word where data needs to be stored in. // dwNumWords - Number of words. Valid values are 4 ONLY. 137 * 138 * Returns: 139 * OSAL_STATUS_CODE: 140 */ 141 142static int ReadBeceemEEPROMBulk(struct bcm_mini_adapter *Adapter, 143 DWORD dwAddress, 144 DWORD *pdwData, 145 DWORD dwNumWords) 146{ 147 DWORD dwIndex = 0; 148 DWORD dwRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; 149 unsigned int uiStatus = 0; 150 unsigned int value = 0; 151 unsigned int value1 = 0; 152 UCHAR *pvalue; 153 154 /* Flush the read and cmd queue. */ 155 value = (EEPROM_READ_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH); 156 wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); 157 value = 0; 158 wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); 159 160 /* Clear the Avail/Full bits. */ 161 value = (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL); 162 wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); 163 164 value = dwAddress | ((dwNumWords == 4) ? EEPROM_16_BYTE_PAGE_READ : EEPROM_4_BYTE_PAGE_READ); 165 wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); 166 167 while (dwRetries != 0) { 168 uiStatus = 0; 169 rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); 170 if (Adapter->device_removed == TRUE) { 171 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got Removed.hence exiting from loop..."); 172 return -ENODEV; 173 } 174 175 /* If we are reading 16 bytes we want to be sure that the queue 176 * is full before we read. In the other cases we are ok if the 177 * queue has data available 178 */ 179 if (dwNumWords == 4) { 180 if ((uiStatus & EEPROM_READ_DATA_FULL) != 0) { 181 /* Clear the Avail/Full bits - which ever is set. */ 182 value = (uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL)); 183 wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); 184 break; 185 } 186 } else if (dwNumWords == 1) { 187 if ((uiStatus & EEPROM_READ_DATA_AVAIL) != 0) { 188 /* We just got Avail and we have to read 32bits so we 189 * need this sleep for Cardbus kind of devices. 190 */ 191 if (Adapter->chip_id == 0xBECE0210) 192 udelay(800); 193 194 /* Clear the Avail/Full bits - which ever is set. */ 195 value = (uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL)); 196 wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); 197 break; 198 } 199 } 200 201 uiStatus = 0; 202 203 dwRetries--; 204 if (dwRetries == 0) { 205 value = 0; 206 value1 = 0; 207 rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); 208 rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG, &value1, sizeof(value1)); 209 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "dwNumWords %d 0x3004 = %x 0x3008 = %x retries = %d failed.\n", 210 dwNumWords, value, value1, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY); 211 return STATUS_FAILURE; 212 } 213 214 if (!(dwRetries%RETRIES_PER_DELAY)) 215 udelay(1000); 216 } 217 218 for (dwIndex = 0; dwIndex < dwNumWords; dwIndex++) { 219 /* We get only a byte at a time - from LSB to MSB. We shift it into an integer. */ 220 pvalue = (PUCHAR)(pdwData + dwIndex); 221 222 value = 0; 223 rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); 224 225 pvalue[0] = value; 226 227 value = 0; 228 rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); 229 230 pvalue[1] = value; 231 232 value = 0; 233 rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); 234 235 pvalue[2] = value; 236 237 value = 0; 238 rdmalt(Adapter, EEPROM_READ_DATAQ_REG, &value, sizeof(value)); 239 240 pvalue[3] = value; 241 } 242 243 return STATUS_SUCCESS; 244} /* ReadBeceemEEPROMBulk() */ 245 246/* 247 * Procedure: ReadBeceemEEPROM 248 * 249 * Description: This routine reads 4 data from EEPROM. It uses 1 or 2 page 250 * reads to do this operation. 251 * 252 * Arguments: 253 * Adapter - ptr to Adapter object instance 254 * uiOffset - EEPROM Offset to read the data from. 255 * pBuffer - Pointer to word where data needs to be stored in. 256 * 257 * Returns: 258 * OSAL_STATUS_CODE: 259 */ 260 261int ReadBeceemEEPROM(struct bcm_mini_adapter *Adapter, 262 DWORD uiOffset, 263 DWORD *pBuffer) 264{ 265 unsigned int uiData[8] = {0}; 266 unsigned int uiByteOffset = 0; 267 unsigned int uiTempOffset = 0; 268 269 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ====> "); 270 271 uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); 272 uiByteOffset = uiOffset - uiTempOffset; 273 274 ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4); 275 276 /* A word can overlap at most over 2 pages. In that case we read the 277 * next page too. 278 */ 279 if (uiByteOffset > 12) 280 ReadBeceemEEPROMBulk(Adapter, uiTempOffset + MAX_RW_SIZE, (PUINT)&uiData[4], 4); 281 282 memcpy((PUCHAR)pBuffer, (((PUCHAR)&uiData[0]) + uiByteOffset), 4); 283 284 return STATUS_SUCCESS; 285} /* ReadBeceemEEPROM() */ 286 287int ReadMacAddressFromNVM(struct bcm_mini_adapter *Adapter) 288{ 289 int Status; 290 unsigned char puMacAddr[6]; 291 292 Status = BeceemNVMRead(Adapter, 293 (PUINT)&puMacAddr[0], 294 INIT_PARAMS_1_MACADDRESS_ADDRESS, 295 MAC_ADDRESS_SIZE); 296 297 if (Status == STATUS_SUCCESS) 298 memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); 299 300 return Status; 301} 302 303/* 304 * Procedure: BeceemEEPROMBulkRead 305 * 306 * Description: Reads the EEPROM and returns the Data. 307 * 308 * Arguments: 309 * Adapter - ptr to Adapter object instance 310 * pBuffer - Buffer to store the data read from EEPROM 311 * uiOffset - Offset of EEPROM from where data should be read 312 * uiNumBytes - Number of bytes to be read from the EEPROM. 313 * 314 * Returns: 315 * OSAL_STATUS_SUCCESS - if EEPROM read is successful. 316 * <FAILURE> - if failed. 317 */ 318 319int BeceemEEPROMBulkRead(struct bcm_mini_adapter *Adapter, 320 PUINT pBuffer, 321 unsigned int uiOffset, 322 unsigned int uiNumBytes) 323{ 324 unsigned int uiData[4] = {0}; 325 /* unsigned int uiAddress = 0; */ 326 unsigned int uiBytesRemaining = uiNumBytes; 327 unsigned int uiIndex = 0; 328 unsigned int uiTempOffset = 0; 329 unsigned int uiExtraBytes = 0; 330 unsigned int uiFailureRetries = 0; 331 PUCHAR pcBuff = (PUCHAR)pBuffer; 332 333 if (uiOffset % MAX_RW_SIZE && uiBytesRemaining) { 334 uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); 335 uiExtraBytes = uiOffset - uiTempOffset; 336 ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4); 337 if (uiBytesRemaining >= (MAX_RW_SIZE - uiExtraBytes)) { 338 memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), MAX_RW_SIZE - uiExtraBytes); 339 uiBytesRemaining -= (MAX_RW_SIZE - uiExtraBytes); 340 uiIndex += (MAX_RW_SIZE - uiExtraBytes); 341 uiOffset += (MAX_RW_SIZE - uiExtraBytes); 342 } else { 343 memcpy(pBuffer, (((PUCHAR)&uiData[0]) + uiExtraBytes), uiBytesRemaining); 344 uiIndex += uiBytesRemaining; 345 uiOffset += uiBytesRemaining; 346 uiBytesRemaining = 0; 347 } 348 } 349 350 while (uiBytesRemaining && uiFailureRetries != 128) { 351 if (Adapter->device_removed) 352 return -1; 353 354 if (uiBytesRemaining >= MAX_RW_SIZE) { 355 /* For the requests more than or equal to 16 bytes, use bulk 356 * read function to make the access faster. 357 * We read 4 Dwords of data 358 */ 359 if (ReadBeceemEEPROMBulk(Adapter, uiOffset, &uiData[0], 4) == 0) { 360 memcpy(pcBuff + uiIndex, &uiData[0], MAX_RW_SIZE); 361 uiOffset += MAX_RW_SIZE; 362 uiBytesRemaining -= MAX_RW_SIZE; 363 uiIndex += MAX_RW_SIZE; 364 } else { 365 uiFailureRetries++; 366 mdelay(3); /* sleep for a while before retry... */ 367 } 368 } else if (uiBytesRemaining >= 4) { 369 if (ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0]) == 0) { 370 memcpy(pcBuff + uiIndex, &uiData[0], 4); 371 uiOffset += 4; 372 uiBytesRemaining -= 4; 373 uiIndex += 4; 374 } else { 375 uiFailureRetries++; 376 mdelay(3); /* sleep for a while before retry... */ 377 } 378 } else { 379 /* Handle the reads less than 4 bytes... */ 380 PUCHAR pCharBuff = (PUCHAR)pBuffer; 381 382 pCharBuff += uiIndex; 383 if (ReadBeceemEEPROM(Adapter, uiOffset, &uiData[0]) == 0) { 384 memcpy(pCharBuff, &uiData[0], uiBytesRemaining); /* copy only bytes requested. */ 385 uiBytesRemaining = 0; 386 } else { 387 uiFailureRetries++; 388 mdelay(3); /* sleep for a while before retry... */ 389 } 390 } 391 } 392 393 return 0; 394} 395 396/* 397 * Procedure: BeceemFlashBulkRead 398 * 399 * Description: Reads the FLASH and returns the Data. 400 * 401 * Arguments: 402 * Adapter - ptr to Adapter object instance 403 * pBuffer - Buffer to store the data read from FLASH 404 * uiOffset - Offset of FLASH from where data should be read 405 * uiNumBytes - Number of bytes to be read from the FLASH. 406 * 407 * Returns: 408 * OSAL_STATUS_SUCCESS - if FLASH read is successful. 409 * <FAILURE> - if failed. 410 */ 411 412static int BeceemFlashBulkRead(struct bcm_mini_adapter *Adapter, 413 PUINT pBuffer, 414 unsigned int uiOffset, 415 unsigned int uiNumBytes) 416{ 417 unsigned int uiIndex = 0; 418 unsigned int uiBytesToRead = uiNumBytes; 419 int Status = 0; 420 unsigned int uiPartOffset = 0; 421 int bytes; 422 423 if (Adapter->device_removed) { 424 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device Got Removed"); 425 return -ENODEV; 426 } 427 428 /* Adding flash Base address 429 * uiOffset = uiOffset + GetFlashBaseAddr(Adapter); 430 */ 431 #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) 432 Status = bcmflash_raw_read((uiOffset/FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes); 433 return Status; 434 #endif 435 436 Adapter->SelectedChip = RESET_CHIP_SELECT; 437 438 if (uiOffset % MAX_RW_SIZE) { 439 BcmDoChipSelect(Adapter, uiOffset); 440 uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); 441 442 uiBytesToRead = MAX_RW_SIZE - (uiOffset % MAX_RW_SIZE); 443 uiBytesToRead = MIN(uiNumBytes, uiBytesToRead); 444 445 bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer + uiIndex, uiBytesToRead); 446 if (bytes < 0) { 447 Status = bytes; 448 Adapter->SelectedChip = RESET_CHIP_SELECT; 449 return Status; 450 } 451 452 uiIndex += uiBytesToRead; 453 uiOffset += uiBytesToRead; 454 uiNumBytes -= uiBytesToRead; 455 } 456 457 while (uiNumBytes) { 458 BcmDoChipSelect(Adapter, uiOffset); 459 uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); 460 461 uiBytesToRead = MIN(uiNumBytes, MAX_RW_SIZE); 462 463 bytes = rdm(Adapter, uiPartOffset, (PCHAR)pBuffer + uiIndex, uiBytesToRead); 464 if (bytes < 0) { 465 Status = bytes; 466 break; 467 } 468 469 uiIndex += uiBytesToRead; 470 uiOffset += uiBytesToRead; 471 uiNumBytes -= uiBytesToRead; 472 } 473 Adapter->SelectedChip = RESET_CHIP_SELECT; 474 return Status; 475} 476 477/* 478 * Procedure: BcmGetFlashSize 479 * 480 * Description: Finds the size of FLASH. 481 * 482 * Arguments: 483 * Adapter - ptr to Adapter object instance 484 * 485 * Returns: 486 * unsigned int - size of the FLASH Storage. 487 * 488 */ 489 490static unsigned int BcmGetFlashSize(struct bcm_mini_adapter *Adapter) 491{ 492 if (IsFlash2x(Adapter)) 493 return Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header); 494 else 495 return 32 * 1024; 496} 497 498/* 499 * Procedure: BcmGetEEPROMSize 500 * 501 * Description: Finds the size of EEPROM. 502 * 503 * Arguments: 504 * Adapter - ptr to Adapter object instance 505 * 506 * Returns: 507 * unsigned int - size of the EEPROM Storage. 508 * 509 */ 510 511static unsigned int BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter) 512{ 513 unsigned int uiData = 0; 514 unsigned int uiIndex = 0; 515 516 /* 517 * if EEPROM is present and already Calibrated,it will have 518 * 'BECM' string at 0th offset. 519 * To find the EEPROM size read the possible boundaries of the 520 * EEPROM like 4K,8K etc..accessing the EEPROM beyond its size will 521 * result in wrap around. So when we get the End of the EEPROM we will 522 * get 'BECM' string which is indeed at offset 0. 523 */ 524 BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4); 525 if (uiData == BECM) { 526 for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) { 527 BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4); 528 if (uiData == BECM) 529 return uiIndex * 1024; 530 } 531 } else { 532 /* 533 * EEPROM may not be present or not programmed 534 */ 535 uiData = 0xBABEFACE; 536 if (BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&uiData, 0, 4, TRUE) == 0) { 537 uiData = 0; 538 for (uiIndex = 2; uiIndex <= 256; uiIndex *= 2) { 539 BeceemEEPROMBulkRead(Adapter, &uiData, uiIndex * 1024, 4); 540 if (uiData == 0xBABEFACE) 541 return uiIndex * 1024; 542 } 543 } 544 } 545 return 0; 546} 547 548/* 549 * Procedure: FlashSectorErase 550 * 551 * Description: Finds the sector size of the FLASH. 552 * 553 * Arguments: 554 * Adapter - ptr to Adapter object instance 555 * addr - sector start address 556 * numOfSectors - number of sectors to be erased. 557 * 558 * Returns: 559 * OSAL_STATUS_CODE 560 * 561 */ 562 563static int FlashSectorErase(struct bcm_mini_adapter *Adapter, 564 unsigned int addr, 565 unsigned int numOfSectors) 566{ 567 unsigned int iIndex = 0, iRetries = 0; 568 unsigned int uiStatus = 0; 569 unsigned int value; 570 int bytes; 571 572 for (iIndex = 0; iIndex < numOfSectors; iIndex++) { 573 value = 0x06000000; 574 wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); 575 576 value = (0xd8000000 | (addr & 0xFFFFFF)); 577 wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); 578 iRetries = 0; 579 580 do { 581 value = (FLASH_CMD_STATUS_REG_READ << 24); 582 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 583 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); 584 return STATUS_FAILURE; 585 } 586 587 bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); 588 if (bytes < 0) { 589 uiStatus = bytes; 590 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails"); 591 return uiStatus; 592 } 593 iRetries++; 594 /* After every try lets make the CPU free for 10 ms. generally time taken by the 595 * the sector erase cycle is 500 ms to 40000 msec. hence sleeping 10 ms 596 * won't hamper performance in any case. 597 */ 598 mdelay(10); 599 } while ((uiStatus & 0x1) && (iRetries < 400)); 600 601 if (uiStatus & 0x1) { 602 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "iRetries crossing the limit of 80000\n"); 603 return STATUS_FAILURE; 604 } 605 606 addr += Adapter->uiSectorSize; 607 } 608 return 0; 609} 610/* 611 * Procedure: flashByteWrite 612 * 613 * Description: Performs Byte by Byte write to flash 614 * 615 * Arguments: 616 * Adapter - ptr to Adapter object instance 617 * uiOffset - Offset of the flash where data needs to be written to. 618 * pData - Address of Data to be written. 619 * Returns: 620 * OSAL_STATUS_CODE 621 * 622 */ 623 624static int flashByteWrite(struct bcm_mini_adapter *Adapter, 625 unsigned int uiOffset, 626 PVOID pData) 627{ 628 unsigned int uiStatus = 0; 629 int iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */ 630 unsigned int value; 631 ULONG ulData = *(PUCHAR)pData; 632 int bytes; 633 /* 634 * need not write 0xFF because write requires an erase and erase will 635 * make whole sector 0xFF. 636 */ 637 638 if (0xFF == ulData) 639 return STATUS_SUCCESS; 640 641 /* DumpDebug(NVM_RW,("flashWrite ====>\n")); */ 642 value = (FLASH_CMD_WRITE_ENABLE << 24); 643 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 644 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails"); 645 return STATUS_FAILURE; 646 } 647 648 if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) { 649 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails"); 650 return STATUS_FAILURE; 651 } 652 value = (0x02000000 | (uiOffset & 0xFFFFFF)); 653 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 654 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails"); 655 return STATUS_FAILURE; 656 } 657 658 /* __udelay(950); */ 659 660 do { 661 value = (FLASH_CMD_STATUS_REG_READ << 24); 662 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 663 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); 664 return STATUS_FAILURE; 665 } 666 /* __udelay(1); */ 667 bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); 668 if (bytes < 0) { 669 uiStatus = bytes; 670 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails"); 671 return uiStatus; 672 } 673 iRetries--; 674 if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) 675 udelay(1000); 676 677 } while ((uiStatus & 0x1) && (iRetries > 0)); 678 679 if (uiStatus & 0x1) { 680 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); 681 return STATUS_FAILURE; 682 } 683 684 return STATUS_SUCCESS; 685} 686 687/* 688 * Procedure: flashWrite 689 * 690 * Description: Performs write to flash 691 * 692 * Arguments: 693 * Adapter - ptr to Adapter object instance 694 * uiOffset - Offset of the flash where data needs to be written to. 695 * pData - Address of Data to be written. 696 * Returns: 697 * OSAL_STATUS_CODE 698 * 699 */ 700 701static int flashWrite(struct bcm_mini_adapter *Adapter, 702 unsigned int uiOffset, 703 PVOID pData) 704{ 705 /* unsigned int uiStatus = 0; 706 * int iRetries = 0; 707 * unsigned int uiReadBack = 0; 708 */ 709 unsigned int uiStatus = 0; 710 int iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */ 711 unsigned int value; 712 unsigned int uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; 713 int bytes; 714 /* 715 * need not write 0xFFFFFFFF because write requires an erase and erase will 716 * make whole sector 0xFFFFFFFF. 717 */ 718 if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE)) 719 return 0; 720 721 value = (FLASH_CMD_WRITE_ENABLE << 24); 722 723 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 724 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails"); 725 return STATUS_FAILURE; 726 } 727 728 if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) { 729 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails..."); 730 return STATUS_FAILURE; 731 } 732 733 /* __udelay(950); */ 734 do { 735 value = (FLASH_CMD_STATUS_REG_READ << 24); 736 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 737 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); 738 return STATUS_FAILURE; 739 } 740 /* __udelay(1); */ 741 bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); 742 if (bytes < 0) { 743 uiStatus = bytes; 744 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails"); 745 return uiStatus; 746 } 747 748 iRetries--; 749 /* this will ensure that in there will be no changes in the current path. 750 * currently one rdm/wrm takes 125 us. 751 * Hence 125 *2 * FLASH_PER_RETRIES_DELAY > 3 ms(worst case delay) 752 * Hence current implementation cycle will intoduce no delay in current path 753 */ 754 if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) 755 udelay(1000); 756 } while ((uiStatus & 0x1) && (iRetries > 0)); 757 758 if (uiStatus & 0x1) { 759 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); 760 return STATUS_FAILURE; 761 } 762 763 return STATUS_SUCCESS; 764} 765 766/*----------------------------------------------------------------------------- 767 * Procedure: flashByteWriteStatus 768 * 769 * Description: Performs byte by byte write to flash with write done status check 770 * 771 * Arguments: 772 * Adapter - ptr to Adapter object instance 773 * uiOffset - Offset of the flash where data needs to be written to. 774 * pData - Address of the Data to be written. 775 * Returns: 776 * OSAL_STATUS_CODE 777 * 778 */ 779static int flashByteWriteStatus(struct bcm_mini_adapter *Adapter, 780 unsigned int uiOffset, 781 PVOID pData) 782{ 783 unsigned int uiStatus = 0; 784 int iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */ 785 ULONG ulData = *(PUCHAR)pData; 786 unsigned int value; 787 int bytes; 788 789 /* 790 * need not write 0xFFFFFFFF because write requires an erase and erase will 791 * make whole sector 0xFFFFFFFF. 792 */ 793 794 if (0xFF == ulData) 795 return STATUS_SUCCESS; 796 797 /* DumpDebug(NVM_RW,("flashWrite ====>\n")); */ 798 799 value = (FLASH_CMD_WRITE_ENABLE << 24); 800 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 801 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write enable in FLASH_SPI_CMDQ_REG register fails"); 802 return STATUS_SUCCESS; 803 } 804 if (wrm(Adapter, FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) { 805 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "DATA Write on FLASH_SPI_WRITEQ_REG fails"); 806 return STATUS_FAILURE; 807 } 808 value = (0x02000000 | (uiOffset & 0xFFFFFF)); 809 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 810 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programming of FLASH_SPI_CMDQ_REG fails"); 811 return STATUS_FAILURE; 812 } 813 814 /* msleep(1); */ 815 816 do { 817 value = (FLASH_CMD_STATUS_REG_READ << 24); 818 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 819 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); 820 return STATUS_FAILURE; 821 } 822 /* __udelay(1); */ 823 bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); 824 if (bytes < 0) { 825 uiStatus = bytes; 826 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails"); 827 return uiStatus; 828 } 829 830 iRetries--; 831 if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) 832 udelay(1000); 833 834 } while ((uiStatus & 0x1) && (iRetries > 0)); 835 836 if (uiStatus & 0x1) { 837 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); 838 return STATUS_FAILURE; 839 } 840 841 return STATUS_SUCCESS; 842} 843/* 844 * Procedure: flashWriteStatus 845 * 846 * Description: Performs write to flash with write done status check 847 * 848 * Arguments: 849 * Adapter - ptr to Adapter object instance 850 * uiOffset - Offset of the flash where data needs to be written to. 851 * pData - Address of the Data to be written. 852 * Returns: 853 * OSAL_STATUS_CODE 854 * 855 */ 856 857static int flashWriteStatus(struct bcm_mini_adapter *Adapter, 858 unsigned int uiOffset, 859 PVOID pData) 860{ 861 unsigned int uiStatus = 0; 862 int iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; /* 3 */ 863 /* unsigned int uiReadBack = 0; */ 864 unsigned int value; 865 unsigned int uiErasePattern[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; 866 int bytes; 867 868 /* 869 * need not write 0xFFFFFFFF because write requires an erase and erase will 870 * make whole sector 0xFFFFFFFF. 871 */ 872 if (!memcmp(pData, uiErasePattern, MAX_RW_SIZE)) 873 return 0; 874 875 value = (FLASH_CMD_WRITE_ENABLE << 24); 876 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 877 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write Enable of FLASH_SPI_CMDQ_REG fails"); 878 return STATUS_FAILURE; 879 } 880 881 if (wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) { 882 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Data write fails..."); 883 return STATUS_FAILURE; 884 } 885 /* __udelay(1); */ 886 887 do { 888 value = (FLASH_CMD_STATUS_REG_READ << 24); 889 if (wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) { 890 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Programing of FLASH_SPI_CMDQ_REG fails"); 891 return STATUS_FAILURE; 892 } 893 /* __udelay(1); */ 894 bytes = rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)); 895 if (bytes < 0) { 896 uiStatus = bytes; 897 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reading status of FLASH_SPI_READQ_REG fails"); 898 return uiStatus; 899 } 900 iRetries--; 901 /* this will ensure that in there will be no changes in the current path. 902 * currently one rdm/wrm takes 125 us. 903 * Hence 125 *2 * FLASH_PER_RETRIES_DELAY >3 ms(worst case delay) 904 * Hence current implementation cycle will intoduce no delay in current path 905 */ 906 if (iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) 907 udelay(1000); 908 909 } while ((uiStatus & 0x1) && (iRetries > 0)); 910 911 if (uiStatus & 0x1) { 912 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write fails even after checking status for 200 times."); 913 return STATUS_FAILURE; 914 } 915 916 return STATUS_SUCCESS; 917} 918 919/* 920 * Procedure: BcmRestoreBlockProtectStatus 921 * 922 * Description: Restores the original block protection status. 923 * 924 * Arguments: 925 * Adapter - ptr to Adapter object instance 926 * ulWriteStatus -Original status 927 * Returns: 928 * <VOID> 929 * 930 */ 931 932static VOID BcmRestoreBlockProtectStatus(struct bcm_mini_adapter *Adapter, ULONG ulWriteStatus) 933{ 934 unsigned int value; 935 936 value = (FLASH_CMD_WRITE_ENABLE << 24); 937 wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); 938 939 udelay(20); 940 value = (FLASH_CMD_STATUS_REG_WRITE << 24) | (ulWriteStatus << 16); 941 wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); 942 udelay(20); 943} 944 945/* 946 * Procedure: BcmFlashUnProtectBlock 947 * 948 * Description: UnProtects appropriate blocks for writing. 949 * 950 * Arguments: 951 * Adapter - ptr to Adapter object instance 952 * uiOffset - Offset of the flash where data needs to be written to. This should be Sector aligned. 953 * Returns: 954 * ULONG - Status value before UnProtect. 955 * 956 */ 957 958static ULONG BcmFlashUnProtectBlock(struct bcm_mini_adapter *Adapter, unsigned int uiOffset, unsigned int uiLength) 959{ 960 ULONG ulStatus = 0; 961 ULONG ulWriteStatus = 0; 962 unsigned int value; 963 964 uiOffset = uiOffset&0x000FFFFF; 965 /* 966 * Implemented only for 1MB Flash parts. 967 */ 968 if (FLASH_PART_SST25VF080B == Adapter->ulFlashID) { 969 /* 970 * Get Current BP status. 971 */ 972 value = (FLASH_CMD_STATUS_REG_READ << 24); 973 wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); 974 udelay(10); 975 /* 976 * Read status will be WWXXYYZZ. We have to take only WW. 977 */ 978 rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulStatus, sizeof(ulStatus)); 979 ulStatus >>= 24; 980 ulWriteStatus = ulStatus; 981 /* 982 * Bits [5-2] give current block level protection status. 983 * Bit5: BP3 - DONT CARE 984 * BP2-BP0: 0 - NO PROTECTION, 1 - UPPER 1/16, 2 - UPPER 1/8, 3 - UPPER 1/4 985 * 4 - UPPER 1/2. 5 to 7 - ALL BLOCKS 986 */ 987 988 if (ulStatus) { 989 if ((uiOffset+uiLength) <= 0x80000) { 990 /* 991 * Offset comes in lower half of 1MB. Protect the upper half. 992 * Clear BP1 and BP0 and set BP2. 993 */ 994 ulWriteStatus |= (0x4<<2); 995 ulWriteStatus &= ~(0x3<<2); 996 } else if ((uiOffset + uiLength) <= 0xC0000) { 997 /* 998 * Offset comes below Upper 1/4. Upper 1/4 can be protected. 999 * Clear BP2 and set BP1 and BP0. 1000 */ 1001 ulWriteStatus |= (0x3<<2); 1002 ulWriteStatus &= ~(0x1<<4); 1003 } else if ((uiOffset + uiLength) <= 0xE0000) { 1004 /* 1005 * Offset comes below Upper 1/8. Upper 1/8 can be protected. 1006 * Clear BP2 and BP0 and set BP1 1007 */ 1008 ulWriteStatus |= (0x1<<3); 1009 ulWriteStatus &= ~(0x5<<2); 1010 } else if ((uiOffset + uiLength) <= 0xF0000) { 1011 /* 1012 * Offset comes below Upper 1/16. Only upper 1/16 can be protected. 1013 * Set BP0 and Clear BP2,BP1. 1014 */ 1015 ulWriteStatus |= (0x1<<2); 1016 ulWriteStatus &= ~(0x3<<3); 1017 } else { 1018 /* 1019 * Unblock all. 1020 * Clear BP2,BP1 and BP0. 1021 */ 1022 ulWriteStatus &= ~(0x7<<2); 1023 } 1024 1025 value = (FLASH_CMD_WRITE_ENABLE << 24); 1026 wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); 1027 udelay(20); 1028 value = (FLASH_CMD_STATUS_REG_WRITE << 24) | (ulWriteStatus << 16); 1029 wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); 1030 udelay(20); 1031 } 1032 } 1033 return ulStatus; 1034} 1035 1036static int bulk_read_complete_sector(struct bcm_mini_adapter *ad, 1037 UCHAR read_bk[], 1038 PCHAR tmpbuff, 1039 unsigned int offset, 1040 unsigned int partoff) 1041{ 1042 unsigned int i; 1043 int j; 1044 int bulk_read_stat; 1045 FP_FLASH_WRITE_STATUS writef = 1046 ad->fpFlashWriteWithStatusCheck; 1047 1048 for (i = 0; i < ad->uiSectorSize; i += MAX_RW_SIZE) { 1049 bulk_read_stat = BeceemFlashBulkRead(ad, 1050 (PUINT)read_bk, 1051 offset + i, 1052 MAX_RW_SIZE); 1053 1054 if (bulk_read_stat != STATUS_SUCCESS) 1055 continue; 1056 1057 if (ad->ulFlashWriteSize == 1) { 1058 for (j = 0; j < 16; j++) { 1059 if ((read_bk[j] != tmpbuff[i + j]) && 1060 (STATUS_SUCCESS != (*writef)(ad, partoff + i + j, &tmpbuff[i + j]))) { 1061 return STATUS_FAILURE; 1062 } 1063 } 1064 } else { 1065 if ((memcmp(read_bk, &tmpbuff[i], MAX_RW_SIZE)) && 1066 (STATUS_SUCCESS != (*writef)(ad, partoff + i, &tmpbuff[i]))) { 1067 return STATUS_FAILURE; 1068 } 1069 } 1070 } 1071 1072 return STATUS_SUCCESS; 1073} 1074 1075/* 1076 * Procedure: BeceemFlashBulkWrite 1077 * 1078 * Description: Performs write to the flash 1079 * 1080 * Arguments: 1081 * Adapter - ptr to Adapter object instance 1082 * pBuffer - Data to be written. 1083 * uiOffset - Offset of the flash where data needs to be written to. 1084 * uiNumBytes - Number of bytes to be written. 1085 * bVerify - read verify flag. 1086 * Returns: 1087 * OSAL_STATUS_CODE 1088 * 1089 */ 1090 1091static int BeceemFlashBulkWrite(struct bcm_mini_adapter *Adapter, 1092 PUINT pBuffer, 1093 unsigned int uiOffset, 1094 unsigned int uiNumBytes, 1095 bool bVerify) 1096{ 1097 PCHAR pTempBuff = NULL; 1098 PUCHAR pcBuffer = (PUCHAR)pBuffer; 1099 unsigned int uiIndex = 0; 1100 unsigned int uiOffsetFromSectStart = 0; 1101 unsigned int uiSectAlignAddr = 0; 1102 unsigned int uiCurrSectOffsetAddr = 0; 1103 unsigned int uiSectBoundary = 0; 1104 unsigned int uiNumSectTobeRead = 0; 1105 UCHAR ucReadBk[16] = {0}; 1106 ULONG ulStatus = 0; 1107 int Status = STATUS_SUCCESS; 1108 unsigned int uiTemp = 0; 1109 unsigned int index = 0; 1110 unsigned int uiPartOffset = 0; 1111 1112 #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) 1113 Status = bcmflash_raw_write((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes); 1114 return Status; 1115 #endif 1116 1117 uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); 1118 1119 /* Adding flash Base address 1120 * uiOffset = uiOffset + GetFlashBaseAddr(Adapter); 1121 */ 1122 1123 uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); 1124 uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); 1125 uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; 1126 1127 pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL); 1128 if (!pTempBuff) 1129 goto BeceemFlashBulkWrite_EXIT; 1130 /* 1131 * check if the data to be written is overlapped across sectors 1132 */ 1133 if (uiOffset+uiNumBytes < uiSectBoundary) { 1134 uiNumSectTobeRead = 1; 1135 } else { 1136 /* Number of sectors = Last sector start address/First sector start address */ 1137 uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize; 1138 if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize) 1139 uiNumSectTobeRead++; 1140 } 1141 /* Check whether Requested sector is writable or not in case of flash2x write. But if write call is 1142 * for DSD calibration, allow it without checking of sector permission 1143 */ 1144 1145 if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == false)) { 1146 index = 0; 1147 uiTemp = uiNumSectTobeRead; 1148 while (uiTemp) { 1149 if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == false) { 1150 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%X> is not writable", 1151 (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); 1152 Status = SECTOR_IS_NOT_WRITABLE; 1153 goto BeceemFlashBulkWrite_EXIT; 1154 } 1155 uiTemp = uiTemp - 1; 1156 index = index + 1; 1157 } 1158 } 1159 Adapter->SelectedChip = RESET_CHIP_SELECT; 1160 while (uiNumSectTobeRead) { 1161 /* do_gettimeofday(&tv1); 1162 * 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)); 1163 */ 1164 uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); 1165 1166 BcmDoChipSelect(Adapter, uiSectAlignAddr); 1167 1168 if (0 != BeceemFlashBulkRead(Adapter, 1169 (PUINT)pTempBuff, 1170 uiOffsetFromSectStart, 1171 Adapter->uiSectorSize)) { 1172 Status = -1; 1173 goto BeceemFlashBulkWrite_EXIT; 1174 } 1175 1176 /* do_gettimeofday(&tr); 1177 * 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)); 1178 */ 1179 ulStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize); 1180 1181 if (uiNumSectTobeRead > 1) { 1182 memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); 1183 pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr))); 1184 uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); 1185 } else { 1186 memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes); 1187 } 1188 1189 if (IsFlash2x(Adapter)) 1190 SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart); 1191 1192 FlashSectorErase(Adapter, uiPartOffset, 1); 1193 /* do_gettimeofday(&te); 1194 * 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)); 1195 */ 1196 for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) { 1197 if (Adapter->device_removed) { 1198 Status = -1; 1199 goto BeceemFlashBulkWrite_EXIT; 1200 } 1201 1202 if (STATUS_SUCCESS != (*Adapter->fpFlashWrite)(Adapter, uiPartOffset + uiIndex, (&pTempBuff[uiIndex]))) { 1203 Status = -1; 1204 goto BeceemFlashBulkWrite_EXIT; 1205 } 1206 } 1207 1208 /* do_gettimeofday(&tw); 1209 * 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)); 1210 */ 1211 1212 if (STATUS_FAILURE == bulk_read_complete_sector(Adapter, 1213 ucReadBk, 1214 pTempBuff, 1215 uiOffsetFromSectStart, 1216 uiPartOffset)) { 1217 Status = STATUS_FAILURE; 1218 goto BeceemFlashBulkWrite_EXIT; 1219 } 1220 1221 /* do_gettimeofday(&twv); 1222 * 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)); 1223 */ 1224 if (ulStatus) { 1225 BcmRestoreBlockProtectStatus(Adapter, ulStatus); 1226 ulStatus = 0; 1227 } 1228 1229 uiCurrSectOffsetAddr = 0; 1230 uiSectAlignAddr = uiSectBoundary; 1231 uiSectBoundary += Adapter->uiSectorSize; 1232 uiOffsetFromSectStart += Adapter->uiSectorSize; 1233 uiNumSectTobeRead--; 1234 } 1235 /* do_gettimeofday(&tv2); 1236 * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Time after Write :%ld ms\n",(tv2.tv_sec *1000 + tv2.tv_usec/1000)); 1237 * 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)); 1238 * 1239 * Cleanup. 1240 */ 1241BeceemFlashBulkWrite_EXIT: 1242 if (ulStatus) 1243 BcmRestoreBlockProtectStatus(Adapter, ulStatus); 1244 1245 kfree(pTempBuff); 1246 1247 Adapter->SelectedChip = RESET_CHIP_SELECT; 1248 return Status; 1249} 1250 1251/* 1252 * Procedure: BeceemFlashBulkWriteStatus 1253 * 1254 * Description: Writes to Flash. Checks the SPI status after each write. 1255 * 1256 * Arguments: 1257 * Adapter - ptr to Adapter object instance 1258 * pBuffer - Data to be written. 1259 * uiOffset - Offset of the flash where data needs to be written to. 1260 * uiNumBytes - Number of bytes to be written. 1261 * bVerify - read verify flag. 1262 * Returns: 1263 * OSAL_STATUS_CODE 1264 * 1265 */ 1266 1267static int BeceemFlashBulkWriteStatus(struct bcm_mini_adapter *Adapter, 1268 PUINT pBuffer, 1269 unsigned int uiOffset, 1270 unsigned int uiNumBytes, 1271 bool bVerify) 1272{ 1273 PCHAR pTempBuff = NULL; 1274 PUCHAR pcBuffer = (PUCHAR)pBuffer; 1275 unsigned int uiIndex = 0; 1276 unsigned int uiOffsetFromSectStart = 0; 1277 unsigned int uiSectAlignAddr = 0; 1278 unsigned int uiCurrSectOffsetAddr = 0; 1279 unsigned int uiSectBoundary = 0; 1280 unsigned int uiNumSectTobeRead = 0; 1281 UCHAR ucReadBk[16] = {0}; 1282 ULONG ulStatus = 0; 1283 unsigned int Status = STATUS_SUCCESS; 1284 unsigned int uiTemp = 0; 1285 unsigned int index = 0; 1286 unsigned int uiPartOffset = 0; 1287 1288 uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); 1289 1290 /* uiOffset += Adapter->ulFlashCalStart; 1291 * Adding flash Base address 1292 * uiOffset = uiOffset + GetFlashBaseAddr(Adapter); 1293 */ 1294 uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); 1295 uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); 1296 uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; 1297 1298 pTempBuff = kmalloc(Adapter->uiSectorSize, GFP_KERNEL); 1299 if (!pTempBuff) 1300 goto BeceemFlashBulkWriteStatus_EXIT; 1301 1302 /* 1303 * check if the data to be written is overlapped across sectors 1304 */ 1305 if (uiOffset+uiNumBytes < uiSectBoundary) { 1306 uiNumSectTobeRead = 1; 1307 } else { 1308 /* Number of sectors = Last sector start address/First sector start address */ 1309 uiNumSectTobeRead = (uiCurrSectOffsetAddr + uiNumBytes) / Adapter->uiSectorSize; 1310 if ((uiCurrSectOffsetAddr + uiNumBytes)%Adapter->uiSectorSize) 1311 uiNumSectTobeRead++; 1312 } 1313 1314 if (IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == false)) { 1315 index = 0; 1316 uiTemp = uiNumSectTobeRead; 1317 while (uiTemp) { 1318 if (IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize) == false) { 1319 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Sector Starting at offset <0X%x> is not writable", 1320 (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); 1321 Status = SECTOR_IS_NOT_WRITABLE; 1322 goto BeceemFlashBulkWriteStatus_EXIT; 1323 } 1324 uiTemp = uiTemp - 1; 1325 index = index + 1; 1326 } 1327 } 1328 1329 Adapter->SelectedChip = RESET_CHIP_SELECT; 1330 while (uiNumSectTobeRead) { 1331 uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); 1332 1333 BcmDoChipSelect(Adapter, uiSectAlignAddr); 1334 if (0 != BeceemFlashBulkRead(Adapter, 1335 (PUINT)pTempBuff, 1336 uiOffsetFromSectStart, 1337 Adapter->uiSectorSize)) { 1338 Status = -1; 1339 goto BeceemFlashBulkWriteStatus_EXIT; 1340 } 1341 1342 ulStatus = BcmFlashUnProtectBlock(Adapter, uiOffsetFromSectStart, Adapter->uiSectorSize); 1343 1344 if (uiNumSectTobeRead > 1) { 1345 memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); 1346 pcBuffer += ((uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr))); 1347 uiNumBytes -= (uiSectBoundary - (uiSectAlignAddr + uiCurrSectOffsetAddr)); 1348 } else { 1349 memcpy(&pTempBuff[uiCurrSectOffsetAddr], pcBuffer, uiNumBytes); 1350 } 1351 1352 if (IsFlash2x(Adapter)) 1353 SaveHeaderIfPresent(Adapter, (PUCHAR)pTempBuff, uiOffsetFromSectStart); 1354 1355 FlashSectorErase(Adapter, uiPartOffset, 1); 1356 1357 for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += Adapter->ulFlashWriteSize) { 1358 if (Adapter->device_removed) { 1359 Status = -1; 1360 goto BeceemFlashBulkWriteStatus_EXIT; 1361 } 1362 1363 if (STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter, uiPartOffset+uiIndex, &pTempBuff[uiIndex])) { 1364 Status = -1; 1365 goto BeceemFlashBulkWriteStatus_EXIT; 1366 } 1367 } 1368 1369 if (bVerify) { 1370 for (uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex += MAX_RW_SIZE) { 1371 if (STATUS_SUCCESS == BeceemFlashBulkRead(Adapter, (PUINT)ucReadBk, uiOffsetFromSectStart + uiIndex, MAX_RW_SIZE)) { 1372 if (memcmp(ucReadBk, &pTempBuff[uiIndex], MAX_RW_SIZE)) { 1373 Status = STATUS_FAILURE; 1374 goto BeceemFlashBulkWriteStatus_EXIT; 1375 } 1376 } 1377 } 1378 } 1379 1380 if (ulStatus) { 1381 BcmRestoreBlockProtectStatus(Adapter, ulStatus); 1382 ulStatus = 0; 1383 } 1384 1385 uiCurrSectOffsetAddr = 0; 1386 uiSectAlignAddr = uiSectBoundary; 1387 uiSectBoundary += Adapter->uiSectorSize; 1388 uiOffsetFromSectStart += Adapter->uiSectorSize; 1389 uiNumSectTobeRead--; 1390 } 1391/* 1392 * Cleanup. 1393 */ 1394BeceemFlashBulkWriteStatus_EXIT: 1395 if (ulStatus) 1396 BcmRestoreBlockProtectStatus(Adapter, ulStatus); 1397 1398 kfree(pTempBuff); 1399 Adapter->SelectedChip = RESET_CHIP_SELECT; 1400 return Status; 1401} 1402 1403/* 1404 * Procedure: PropagateCalParamsFromFlashToMemory 1405 * 1406 * Description: Dumps the calibration section of EEPROM to DDR. 1407 * 1408 * Arguments: 1409 * Adapter - ptr to Adapter object instance 1410 * Returns: 1411 * OSAL_STATUS_CODE 1412 * 1413 */ 1414 1415int PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter *Adapter) 1416{ 1417 PCHAR pBuff, pPtr; 1418 unsigned int uiEepromSize = 0; 1419 unsigned int uiBytesToCopy = 0; 1420 /* unsigned int uiIndex = 0; */ 1421 unsigned int uiCalStartAddr = EEPROM_CALPARAM_START; 1422 unsigned int uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC; 1423 unsigned int value; 1424 int Status = 0; 1425 1426 /* 1427 * Write the signature first. This will ensure firmware does not access EEPROM. 1428 */ 1429 value = 0xbeadbead; 1430 wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); 1431 value = 0xbeadbead; 1432 wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); 1433 1434 if (0 != BeceemNVMRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4)) 1435 return -1; 1436 1437 uiEepromSize = ntohl(uiEepromSize); 1438 uiEepromSize >>= 16; 1439 1440 /* 1441 * subtract the auto init section size 1442 */ 1443 uiEepromSize -= EEPROM_CALPARAM_START; 1444 1445 if (uiEepromSize > 1024 * 1024) 1446 return -1; 1447 1448 pBuff = kmalloc(uiEepromSize, GFP_KERNEL); 1449 if (pBuff == NULL) 1450 return -ENOMEM; 1451 1452 if (0 != BeceemNVMRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiEepromSize)) { 1453 kfree(pBuff); 1454 return -1; 1455 } 1456 1457 pPtr = pBuff; 1458 1459 uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize); 1460 1461 while (uiBytesToCopy) { 1462 Status = wrm(Adapter, uiMemoryLoc, (PCHAR)pPtr, uiBytesToCopy); 1463 if (Status) { 1464 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm failed with status :%d", Status); 1465 break; 1466 } 1467 1468 pPtr += uiBytesToCopy; 1469 uiEepromSize -= uiBytesToCopy; 1470 uiMemoryLoc += uiBytesToCopy; 1471 uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize); 1472 } 1473 1474 kfree(pBuff); 1475 return Status; 1476} 1477 1478/* 1479 * Procedure: BeceemEEPROMReadBackandVerify 1480 * 1481 * Description: Read back the data written and verifies. 1482 * 1483 * Arguments: 1484 * Adapter - ptr to Adapter object instance 1485 * pBuffer - Data to be written. 1486 * uiOffset - Offset of the flash where data needs to be written to. 1487 * uiNumBytes - Number of bytes to be written. 1488 * Returns: 1489 * OSAL_STATUS_CODE 1490 * 1491 */ 1492 1493static int BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter, 1494 PUINT pBuffer, 1495 unsigned int uiOffset, 1496 unsigned int uiNumBytes) 1497{ 1498 unsigned int uiRdbk = 0; 1499 unsigned int uiIndex = 0; 1500 unsigned int uiData = 0; 1501 unsigned int auiData[4] = {0}; 1502 1503 while (uiNumBytes) { 1504 if (Adapter->device_removed) 1505 return -1; 1506 1507 if (uiNumBytes >= MAX_RW_SIZE) { 1508 /* for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. */ 1509 BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE); 1510 1511 if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) { 1512 /* re-write */ 1513 BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, MAX_RW_SIZE, false); 1514 mdelay(3); 1515 BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE); 1516 1517 if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) 1518 return -1; 1519 } 1520 uiOffset += MAX_RW_SIZE; 1521 uiNumBytes -= MAX_RW_SIZE; 1522 uiIndex += 4; 1523 } else if (uiNumBytes >= 4) { 1524 BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4); 1525 if (uiData != pBuffer[uiIndex]) { 1526 /* re-write */ 1527 BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, 4, false); 1528 mdelay(3); 1529 BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4); 1530 if (uiData != pBuffer[uiIndex]) 1531 return -1; 1532 } 1533 uiOffset += 4; 1534 uiNumBytes -= 4; 1535 uiIndex++; 1536 } else { 1537 /* Handle the reads less than 4 bytes... */ 1538 uiData = 0; 1539 memcpy(&uiData, ((PUCHAR)pBuffer) + (uiIndex * sizeof(unsigned int)), uiNumBytes); 1540 BeceemEEPROMBulkRead(Adapter, &uiRdbk, uiOffset, 4); 1541 1542 if (memcmp(&uiData, &uiRdbk, uiNumBytes)) 1543 return -1; 1544 1545 uiNumBytes = 0; 1546 } 1547 } 1548 1549 return 0; 1550} 1551 1552static VOID BcmSwapWord(unsigned int *ptr1) 1553{ 1554 unsigned int tempval = (unsigned int)*ptr1; 1555 char *ptr2 = (char *)&tempval; 1556 char *ptr = (char *)ptr1; 1557 1558 ptr[0] = ptr2[3]; 1559 ptr[1] = ptr2[2]; 1560 ptr[2] = ptr2[1]; 1561 ptr[3] = ptr2[0]; 1562} 1563 1564/* 1565 * Procedure: BeceemEEPROMWritePage 1566 * 1567 * Description: Performs page write (16bytes) to the EEPROM 1568 * 1569 * Arguments: 1570 * Adapter - ptr to Adapter object instance 1571 * uiData - Data to be written. 1572 * uiOffset - Offset of the EEPROM where data needs to be written to. 1573 * Returns: 1574 * OSAL_STATUS_CODE 1575 * 1576 */ 1577 1578static int BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, unsigned int uiData[], unsigned int uiOffset) 1579{ 1580 unsigned int uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; 1581 unsigned int uiStatus = 0; 1582 UCHAR uiEpromStatus = 0; 1583 unsigned int value = 0; 1584 1585 /* Flush the Write/Read/Cmd queues. */ 1586 value = (EEPROM_WRITE_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH | EEPROM_READ_QUEUE_FLUSH); 1587 wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); 1588 value = 0; 1589 wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); 1590 1591 /* Clear the Empty/Avail/Full bits. After this it has been confirmed 1592 * that the bit was cleared by reading back the register. See NOTE below. 1593 * We also clear the Read queues as we do a EEPROM status register read 1594 * later. 1595 */ 1596 value = (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL | EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL); 1597 wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); 1598 1599 /* Enable write */ 1600 value = EEPROM_WRITE_ENABLE; 1601 wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); 1602 1603 /* We can write back to back 8bits * 16 into the queue and as we have 1604 * checked for the queue to be empty we can write in a burst. 1605 */ 1606 1607 value = uiData[0]; 1608 BcmSwapWord(&value); 1609 wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); 1610 1611 value = uiData[1]; 1612 BcmSwapWord(&value); 1613 wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); 1614 1615 value = uiData[2]; 1616 BcmSwapWord(&value); 1617 wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); 1618 1619 value = uiData[3]; 1620 BcmSwapWord(&value); 1621 wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); 1622 1623 /* NOTE : After this write, on readback of EEPROM_SPI_Q_STATUS1_REG 1624 * shows that we see 7 for the EEPROM data write. Which means that 1625 * queue got full, also space is available as well as the queue is empty. 1626 * This may happen in sequence. 1627 */ 1628 value = EEPROM_16_BYTE_PAGE_WRITE | uiOffset; 1629 wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); 1630 1631 /* Ideally we should loop here without tries and eventually succeed. 1632 * What we are checking if the previous write has completed, and this 1633 * may take time. We should wait till the Empty bit is set. 1634 */ 1635 uiStatus = 0; 1636 rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); 1637 while ((uiStatus & EEPROM_WRITE_QUEUE_EMPTY) == 0) { 1638 uiRetries--; 1639 if (uiRetries == 0) { 1640 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, %d retries failed.\n", uiStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY); 1641 return STATUS_FAILURE; 1642 } 1643 1644 if (!(uiRetries%RETRIES_PER_DELAY)) 1645 udelay(1000); 1646 1647 uiStatus = 0; 1648 rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); 1649 if (Adapter->device_removed == TRUE) { 1650 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem got removed hence exiting from loop...."); 1651 return -ENODEV; 1652 } 1653 } 1654 1655 if (uiRetries != 0) { 1656 /* Clear the ones that are set - either, Empty/Full/Avail bits */ 1657 value = (uiStatus & (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL)); 1658 wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); 1659 } 1660 1661 /* Here we should check if the EEPROM status register is correct before 1662 * proceeding. Bit 0 in the EEPROM Status register should be 0 before 1663 * we proceed further. A 1 at Bit 0 indicates that the EEPROM is busy 1664 * with the previous write. Note also that issuing this read finally 1665 * means the previous write to the EEPROM has completed. 1666 */ 1667 uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY; 1668 uiEpromStatus = 0; 1669 while (uiRetries != 0) { 1670 uiEpromStatus = ReadEEPROMStatusRegister(Adapter); 1671 if (Adapter->device_removed == TRUE) { 1672 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting from loop..."); 1673 return -ENODEV; 1674 } 1675 if ((EEPROM_STATUS_REG_WRITE_BUSY & uiEpromStatus) == 0) { 1676 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM status register = %x tries = %d\n", uiEpromStatus, (MAX_EEPROM_RETRIES * RETRIES_PER_DELAY - uiRetries)); 1677 return STATUS_SUCCESS; 1678 } 1679 uiRetries--; 1680 if (uiRetries == 0) { 1681 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); 1682 return STATUS_FAILURE; 1683 } 1684 uiEpromStatus = 0; 1685 if (!(uiRetries%RETRIES_PER_DELAY)) 1686 udelay(1000); 1687 } 1688 1689 return STATUS_SUCCESS; 1690} /* BeceemEEPROMWritePage */ 1691 1692/* 1693 * Procedure: BeceemEEPROMBulkWrite 1694 * 1695 * Description: Performs write to the EEPROM 1696 * 1697 * Arguments: 1698 * Adapter - ptr to Adapter object instance 1699 * pBuffer - Data to be written. 1700 * uiOffset - Offset of the EEPROM where data needs to be written to. 1701 * uiNumBytes - Number of bytes to be written. 1702 * bVerify - read verify flag. 1703 * Returns: 1704 * OSAL_STATUS_CODE 1705 * 1706 */ 1707 1708int BeceemEEPROMBulkWrite(struct bcm_mini_adapter *Adapter, 1709 PUCHAR pBuffer, 1710 unsigned int uiOffset, 1711 unsigned int uiNumBytes, 1712 bool bVerify) 1713{ 1714 unsigned int uiBytesToCopy = uiNumBytes; 1715 /* unsigned int uiRdbk = 0; */ 1716 unsigned int uiData[4] = {0}; 1717 unsigned int uiIndex = 0; 1718 unsigned int uiTempOffset = 0; 1719 unsigned int uiExtraBytes = 0; 1720 /* PUINT puiBuffer = (PUINT)pBuffer; 1721 * int value; 1722 */ 1723 1724 if (uiOffset % MAX_RW_SIZE && uiBytesToCopy) { 1725 uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); 1726 uiExtraBytes = uiOffset - uiTempOffset; 1727 1728 BeceemEEPROMBulkRead(Adapter, &uiData[0], uiTempOffset, MAX_RW_SIZE); 1729 1730 if (uiBytesToCopy >= (16 - uiExtraBytes)) { 1731 memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, MAX_RW_SIZE - uiExtraBytes); 1732 1733 if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset)) 1734 return STATUS_FAILURE; 1735 1736 uiBytesToCopy -= (MAX_RW_SIZE - uiExtraBytes); 1737 uiIndex += (MAX_RW_SIZE - uiExtraBytes); 1738 uiOffset += (MAX_RW_SIZE - uiExtraBytes); 1739 } else { 1740 memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, uiBytesToCopy); 1741 1742 if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset)) 1743 return STATUS_FAILURE; 1744 1745 uiIndex += uiBytesToCopy; 1746 uiOffset += uiBytesToCopy; 1747 uiBytesToCopy = 0; 1748 } 1749 } 1750 1751 while (uiBytesToCopy) { 1752 if (Adapter->device_removed) 1753 return -1; 1754 1755 if (uiBytesToCopy >= MAX_RW_SIZE) { 1756 if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, (PUINT) &pBuffer[uiIndex], uiOffset)) 1757 return STATUS_FAILURE; 1758 1759 uiIndex += MAX_RW_SIZE; 1760 uiOffset += MAX_RW_SIZE; 1761 uiBytesToCopy -= MAX_RW_SIZE; 1762 } else { 1763 /* 1764 * To program non 16byte aligned data, read 16byte and then update. 1765 */ 1766 BeceemEEPROMBulkRead(Adapter, &uiData[0], uiOffset, 16); 1767 memcpy(&uiData[0], pBuffer + uiIndex, uiBytesToCopy); 1768 1769 if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiOffset)) 1770 return STATUS_FAILURE; 1771 1772 uiBytesToCopy = 0; 1773 } 1774 } 1775 1776 return 0; 1777} 1778 1779/* 1780 * Procedure: BeceemNVMRead 1781 * 1782 * Description: Reads n number of bytes from NVM. 1783 * 1784 * Arguments: 1785 * Adapter - ptr to Adapter object instance 1786 * pBuffer - Buffer to store the data read from NVM 1787 * uiOffset - Offset of NVM from where data should be read 1788 * uiNumBytes - Number of bytes to be read from the NVM. 1789 * 1790 * Returns: 1791 * OSAL_STATUS_SUCCESS - if NVM read is successful. 1792 * <FAILURE> - if failed. 1793 */ 1794 1795int BeceemNVMRead(struct bcm_mini_adapter *Adapter, 1796 PUINT pBuffer, 1797 unsigned int uiOffset, 1798 unsigned int uiNumBytes) 1799{ 1800 int Status = 0; 1801 1802 #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) 1803 unsigned int uiTemp = 0, value; 1804 #endif 1805 1806 if (Adapter->eNVMType == NVM_FLASH) { 1807 if (Adapter->bFlashRawRead == false) { 1808 if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD)) 1809 return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes); 1810 1811 uiOffset = uiOffset + Adapter->ulFlashCalStart; 1812 } 1813 1814 #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) 1815 Status = bcmflash_raw_read((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes); 1816 #else 1817 rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 1818 value = 0; 1819 wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); 1820 Status = BeceemFlashBulkRead(Adapter, 1821 pBuffer, 1822 uiOffset, 1823 uiNumBytes); 1824 wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 1825 #endif 1826 } else if (Adapter->eNVMType == NVM_EEPROM) { 1827 Status = BeceemEEPROMBulkRead(Adapter, 1828 pBuffer, 1829 uiOffset, 1830 uiNumBytes); 1831 } else { 1832 Status = -1; 1833 } 1834 1835 return Status; 1836} 1837 1838/* 1839 * Procedure: BeceemNVMWrite 1840 * 1841 * Description: Writes n number of bytes to NVM. 1842 * 1843 * Arguments: 1844 * Adapter - ptr to Adapter object instance 1845 * pBuffer - Buffer contains the data to be written. 1846 * uiOffset - Offset of NVM where data to be written to. 1847 * uiNumBytes - Number of bytes to be written.. 1848 * 1849 * Returns: 1850 * OSAL_STATUS_SUCCESS - if NVM write is successful. 1851 * <FAILURE> - if failed. 1852 */ 1853 1854int BeceemNVMWrite(struct bcm_mini_adapter *Adapter, 1855 PUINT pBuffer, 1856 unsigned int uiOffset, 1857 unsigned int uiNumBytes, 1858 bool bVerify) 1859{ 1860 int Status = 0; 1861 unsigned int uiTemp = 0; 1862 unsigned int uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC; 1863 unsigned int uiIndex = 0; 1864 1865 #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) 1866 unsigned int value; 1867 #endif 1868 1869 unsigned int uiFlashOffset = 0; 1870 1871 if (Adapter->eNVMType == NVM_FLASH) { 1872 if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD)) 1873 Status = vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes, bVerify); 1874 else { 1875 uiFlashOffset = uiOffset + Adapter->ulFlashCalStart; 1876 1877 #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) 1878 Status = bcmflash_raw_write((uiFlashOffset / FLASH_PART_SIZE), (uiFlashOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes); 1879 #else 1880 rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 1881 value = 0; 1882 wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); 1883 1884 if (Adapter->bStatusWrite == TRUE) 1885 Status = BeceemFlashBulkWriteStatus(Adapter, 1886 pBuffer, 1887 uiFlashOffset, 1888 uiNumBytes , 1889 bVerify); 1890 else 1891 1892 Status = BeceemFlashBulkWrite(Adapter, 1893 pBuffer, 1894 uiFlashOffset, 1895 uiNumBytes, 1896 bVerify); 1897 #endif 1898 } 1899 1900 if (uiOffset >= EEPROM_CALPARAM_START) { 1901 uiMemoryLoc += (uiOffset - EEPROM_CALPARAM_START); 1902 while (uiNumBytes) { 1903 if (uiNumBytes > BUFFER_4K) { 1904 wrm(Adapter, (uiMemoryLoc+uiIndex), (PCHAR)(pBuffer + (uiIndex / 4)), BUFFER_4K); 1905 uiNumBytes -= BUFFER_4K; 1906 uiIndex += BUFFER_4K; 1907 } else { 1908 wrm(Adapter, uiMemoryLoc+uiIndex, (PCHAR)(pBuffer + (uiIndex / 4)), uiNumBytes); 1909 uiNumBytes = 0; 1910 break; 1911 } 1912 } 1913 } else { 1914 if ((uiOffset + uiNumBytes) > EEPROM_CALPARAM_START) { 1915 ULONG ulBytesTobeSkipped = 0; 1916 PUCHAR pcBuffer = (PUCHAR)pBuffer; /* char pointer to take care of odd byte cases. */ 1917 1918 uiNumBytes -= (EEPROM_CALPARAM_START - uiOffset); 1919 ulBytesTobeSkipped += (EEPROM_CALPARAM_START - uiOffset); 1920 uiOffset += (EEPROM_CALPARAM_START - uiOffset); 1921 while (uiNumBytes) { 1922 if (uiNumBytes > BUFFER_4K) { 1923 wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], BUFFER_4K); 1924 uiNumBytes -= BUFFER_4K; 1925 uiIndex += BUFFER_4K; 1926 } else { 1927 wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], uiNumBytes); 1928 uiNumBytes = 0; 1929 break; 1930 } 1931 } 1932 } 1933 } 1934 /* restore the values. */ 1935 wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 1936 } else if (Adapter->eNVMType == NVM_EEPROM) { 1937 Status = BeceemEEPROMBulkWrite(Adapter, 1938 (PUCHAR)pBuffer, 1939 uiOffset, 1940 uiNumBytes, 1941 bVerify); 1942 if (bVerify) 1943 Status = BeceemEEPROMReadBackandVerify(Adapter, (PUINT)pBuffer, uiOffset, uiNumBytes); 1944 } else { 1945 Status = -1; 1946 } 1947 return Status; 1948} 1949 1950/* 1951 * Procedure: BcmUpdateSectorSize 1952 * 1953 * Description: Updates the sector size to FLASH. 1954 * 1955 * Arguments: 1956 * Adapter - ptr to Adapter object instance 1957 * uiSectorSize - sector size 1958 * 1959 * Returns: 1960 * OSAL_STATUS_SUCCESS - if NVM write is successful. 1961 * <FAILURE> - if failed. 1962 */ 1963 1964int BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, unsigned int uiSectorSize) 1965{ 1966 int Status = -1; 1967 struct bcm_flash_cs_info sFlashCsInfo = {0}; 1968 unsigned int uiTemp = 0; 1969 unsigned int uiSectorSig = 0; 1970 unsigned int uiCurrentSectorSize = 0; 1971 unsigned int value; 1972 1973 rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 1974 value = 0; 1975 wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); 1976 1977 /* 1978 * Before updating the sector size in the reserved area, check if already present. 1979 */ 1980 BeceemFlashBulkRead(Adapter, (PUINT)&sFlashCsInfo, Adapter->ulFlashControlSectionStart, sizeof(sFlashCsInfo)); 1981 uiSectorSig = ntohl(sFlashCsInfo.FlashSectorSizeSig); 1982 uiCurrentSectorSize = ntohl(sFlashCsInfo.FlashSectorSize); 1983 1984 if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) { 1985 if ((uiCurrentSectorSize <= MAX_SECTOR_SIZE) && (uiCurrentSectorSize >= MIN_SECTOR_SIZE)) { 1986 if (uiSectorSize == uiCurrentSectorSize) { 1987 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Provided sector size is same as programmed in Flash"); 1988 Status = STATUS_SUCCESS; 1989 goto Restore; 1990 } 1991 } 1992 } 1993 1994 if ((uiSectorSize <= MAX_SECTOR_SIZE) && (uiSectorSize >= MIN_SECTOR_SIZE)) { 1995 sFlashCsInfo.FlashSectorSize = htonl(uiSectorSize); 1996 sFlashCsInfo.FlashSectorSizeSig = htonl(FLASH_SECTOR_SIZE_SIG); 1997 1998 Status = BeceemFlashBulkWrite(Adapter, 1999 (PUINT)&sFlashCsInfo, 2000 Adapter->ulFlashControlSectionStart, 2001 sizeof(sFlashCsInfo), 2002 TRUE); 2003 } 2004 2005Restore: 2006 /* restore the values. */ 2007 wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 2008 2009 return Status; 2010} 2011 2012/* 2013 * Procedure: BcmGetFlashSectorSize 2014 * 2015 * Description: Finds the sector size of the FLASH. 2016 * 2017 * Arguments: 2018 * Adapter - ptr to Adapter object instance 2019 * 2020 * Returns: 2021 * unsigned int - sector size. 2022 * 2023 */ 2024 2025static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, unsigned int FlashSectorSizeSig, unsigned int FlashSectorSize) 2026{ 2027 unsigned int uiSectorSize = 0; 2028 unsigned int uiSectorSig = 0; 2029 2030 if (Adapter->bSectorSizeOverride && 2031 (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && 2032 Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)) { 2033 Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; 2034 } else { 2035 uiSectorSig = FlashSectorSizeSig; 2036 2037 if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) { 2038 uiSectorSize = FlashSectorSize; 2039 /* 2040 * If the sector size stored in the FLASH makes sense then use it. 2041 */ 2042 if (uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) { 2043 Adapter->uiSectorSize = uiSectorSize; 2044 } else if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && 2045 Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) { 2046 /* No valid size in FLASH, check if Config file has it. */ 2047 Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; 2048 } else { 2049 /* Init to Default, if none of the above works. */ 2050 Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE; 2051 } 2052 } else { 2053 if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && 2054 Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) 2055 Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; 2056 else 2057 Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE; 2058 } 2059 } 2060 2061 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector size :%x\n", Adapter->uiSectorSize); 2062 2063 return Adapter->uiSectorSize; 2064} 2065 2066/* 2067 * Procedure: BcmInitEEPROMQueues 2068 * 2069 * Description: Initialization of EEPROM queues. 2070 * 2071 * Arguments: 2072 * Adapter - ptr to Adapter object instance 2073 * 2074 * Returns: 2075 * <OSAL_STATUS_CODE> 2076 */ 2077 2078static int BcmInitEEPROMQueues(struct bcm_mini_adapter *Adapter) 2079{ 2080 unsigned int value = 0; 2081 /* CHIP Bug : Clear the Avail bits on the Read queue. The default 2082 * value on this register is supposed to be 0x00001102. 2083 * But we get 0x00001122. 2084 */ 2085 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Fixing reset value on 0x0f003004 register\n"); 2086 value = EEPROM_READ_DATA_AVAIL; 2087 wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); 2088 2089 /* Flush the all the EEPROM queues. */ 2090 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Flushing the queues\n"); 2091 value = EEPROM_ALL_QUEUE_FLUSH; 2092 wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); 2093 2094 value = 0; 2095 wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value)); 2096 2097 /* Read the EEPROM Status Register. Just to see, no real purpose. */ 2098 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "EEPROM Status register value = %x\n", ReadEEPROMStatusRegister(Adapter)); 2099 2100 return STATUS_SUCCESS; 2101} /* BcmInitEEPROMQueues() */ 2102 2103/* 2104 * Procedure: BcmInitNVM 2105 * 2106 * Description: Initialization of NVM, EEPROM size,FLASH size, sector size etc. 2107 * 2108 * Arguments: 2109 * Adapter - ptr to Adapter object instance 2110 * 2111 * Returns: 2112 * <OSAL_STATUS_CODE> 2113 */ 2114 2115int BcmInitNVM(struct bcm_mini_adapter *ps_adapter) 2116{ 2117 BcmValidateNvmType(ps_adapter); 2118 BcmInitEEPROMQueues(ps_adapter); 2119 2120 if (ps_adapter->eNVMType == NVM_AUTODETECT) { 2121 ps_adapter->eNVMType = BcmGetNvmType(ps_adapter); 2122 if (ps_adapter->eNVMType == NVM_UNKNOWN) 2123 BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "NVM Type is unknown!!\n"); 2124 } else if (ps_adapter->eNVMType == NVM_FLASH) { 2125 BcmGetFlashCSInfo(ps_adapter); 2126 } 2127 2128 BcmGetNvmSize(ps_adapter); 2129 2130 return STATUS_SUCCESS; 2131} 2132 2133/* BcmGetNvmSize : set the EEPROM or flash size in Adapter. 2134 * 2135 * Input Parameter: 2136 * Adapter data structure 2137 * Return Value : 2138 * 0. means success; 2139 */ 2140 2141static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter) 2142{ 2143 if (Adapter->eNVMType == NVM_EEPROM) 2144 Adapter->uiNVMDSDSize = BcmGetEEPROMSize(Adapter); 2145 else if (Adapter->eNVMType == NVM_FLASH) 2146 Adapter->uiNVMDSDSize = BcmGetFlashSize(Adapter); 2147 2148 return 0; 2149} 2150 2151/* 2152 * Procedure: BcmValidateNvm 2153 * 2154 * Description: Validates the NVM Type option selected against the device 2155 * 2156 * Arguments: 2157 * Adapter - ptr to Adapter object instance 2158 * 2159 * Returns: 2160 * <VOID> 2161 */ 2162 2163static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter) 2164{ 2165 /* 2166 * if forcing the FLASH through CFG file, we should ensure device really has a FLASH. 2167 * Accessing the FLASH address without the FLASH being present can cause hang/freeze etc. 2168 * So if NVM_FLASH is selected for older chipsets, change it to AUTODETECT where EEPROM is 1st choice. 2169 */ 2170 2171 if (Adapter->eNVMType == NVM_FLASH && 2172 Adapter->chip_id < 0xBECE3300) 2173 Adapter->eNVMType = NVM_AUTODETECT; 2174} 2175 2176/* 2177 * Procedure: BcmReadFlashRDID 2178 * 2179 * Description: Reads ID from Serial Flash 2180 * 2181 * Arguments: 2182 * Adapter - ptr to Adapter object instance 2183 * 2184 * Returns: 2185 * Flash ID 2186 */ 2187 2188static ULONG BcmReadFlashRDID(struct bcm_mini_adapter *Adapter) 2189{ 2190 ULONG ulRDID = 0; 2191 unsigned int value; 2192 2193 /* 2194 * Read ID Instruction. 2195 */ 2196 value = (FLASH_CMD_READ_ID << 24); 2197 wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); 2198 2199 /* Delay */ 2200 udelay(10); 2201 2202 /* 2203 * Read SPI READQ REG. The output will be WWXXYYZZ. 2204 * The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored. 2205 */ 2206 rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID)); 2207 2208 return ulRDID >> 8; 2209} 2210 2211int BcmAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) 2212{ 2213 if (!psAdapter) { 2214 BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL"); 2215 return -EINVAL; 2216 } 2217 psAdapter->psFlashCSInfo = kzalloc(sizeof(struct bcm_flash_cs_info), GFP_KERNEL); 2218 if (psAdapter->psFlashCSInfo == NULL) { 2219 BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 1.x"); 2220 return -ENOMEM; 2221 } 2222 2223 psAdapter->psFlash2xCSInfo = kzalloc(sizeof(struct bcm_flash2x_cs_info), GFP_KERNEL); 2224 if (!psAdapter->psFlash2xCSInfo) { 2225 BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 2.x"); 2226 kfree(psAdapter->psFlashCSInfo); 2227 return -ENOMEM; 2228 } 2229 2230 psAdapter->psFlash2xVendorInfo = kzalloc(sizeof(struct bcm_flash2x_vendor_info), GFP_KERNEL); 2231 if (!psAdapter->psFlash2xVendorInfo) { 2232 BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate Vendor Info Memory for Flash 2.x"); 2233 kfree(psAdapter->psFlashCSInfo); 2234 kfree(psAdapter->psFlash2xCSInfo); 2235 return -ENOMEM; 2236 } 2237 2238 return STATUS_SUCCESS; 2239} 2240 2241int BcmDeAllocFlashCSStructure(struct bcm_mini_adapter *psAdapter) 2242{ 2243 if (!psAdapter) { 2244 BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL"); 2245 return -EINVAL; 2246 } 2247 kfree(psAdapter->psFlashCSInfo); 2248 kfree(psAdapter->psFlash2xCSInfo); 2249 kfree(psAdapter->psFlash2xVendorInfo); 2250 return STATUS_SUCCESS; 2251} 2252 2253static int BcmDumpFlash2XCSStructure(struct bcm_flash2x_cs_info *psFlash2xCSInfo, struct bcm_mini_adapter *Adapter) 2254{ 2255 unsigned int Index = 0; 2256 2257 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "**********************FLASH2X CS Structure *******************"); 2258 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x", (psFlash2xCSInfo->MagicNumber)); 2259 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Major Version :%d", MAJOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion)); 2260 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Minor Version :%d", MINOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion)); 2261 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ISOImageMajorVersion:0x%x", (psFlash2xCSInfo->ISOImageVersion)); 2262 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSIFirmwareMajorVersion :0x%x", (psFlash2xCSInfo->SCSIFirmwareVersion)); 2263 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart1ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage)); 2264 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForScsiFirmware :0x%x", (psFlash2xCSInfo->OffsetFromZeroForScsiFirmware)); 2265 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SizeOfScsiFirmware :0x%x", (psFlash2xCSInfo->SizeOfScsiFirmware)); 2266 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart2ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage)); 2267 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDStart)); 2268 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDEnd)); 2269 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAStart)); 2270 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAEnd)); 2271 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionStart)); 2272 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionData :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionData)); 2273 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CDLessInactivityTimeout :0x%x", (psFlash2xCSInfo->CDLessInactivityTimeout)); 2274 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "NewImageSignature :0x%x", (psFlash2xCSInfo->NewImageSignature)); 2275 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSizeSig :0x%x", (psFlash2xCSInfo->FlashSectorSizeSig)); 2276 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSize :0x%x", (psFlash2xCSInfo->FlashSectorSize)); 2277 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashWriteSupportSize :0x%x", (psFlash2xCSInfo->FlashWriteSupportSize)); 2278 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "TotalFlashSize :0x%X", (psFlash2xCSInfo->TotalFlashSize)); 2279 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashBaseAddr :0x%x", (psFlash2xCSInfo->FlashBaseAddr)); 2280 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashPartMaxSize :0x%x", (psFlash2xCSInfo->FlashPartMaxSize)); 2281 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "IsCDLessDeviceBootSig :0x%x", (psFlash2xCSInfo->IsCDLessDeviceBootSig)); 2282 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "MassStorageTimeout :0x%x", (psFlash2xCSInfo->MassStorageTimeout)); 2283 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1Start)); 2284 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1End)); 2285 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2Start)); 2286 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2End)); 2287 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3Start)); 2288 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3End)); 2289 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1Start)); 2290 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1End)); 2291 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2Start)); 2292 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2End)); 2293 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3Start)); 2294 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3End)); 2295 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromDSDStartForDSDHeader :0x%x", (psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader)); 2296 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1Start)); 2297 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1End)); 2298 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2Start)); 2299 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2End)); 2300 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1Start)); 2301 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1End)); 2302 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2Start)); 2303 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2End)); 2304 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector Access Bit Map is Defined as :"); 2305 2306 for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++) 2307 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectorAccessBitMap[%d] :0x%x", Index, 2308 (psFlash2xCSInfo->SectorAccessBitMap[Index])); 2309 2310 return STATUS_SUCCESS; 2311} 2312 2313static int ConvertEndianOf2XCSStructure(struct bcm_flash2x_cs_info *psFlash2xCSInfo) 2314{ 2315 unsigned int Index = 0; 2316 2317 psFlash2xCSInfo->MagicNumber = ntohl(psFlash2xCSInfo->MagicNumber); 2318 psFlash2xCSInfo->FlashLayoutVersion = ntohl(psFlash2xCSInfo->FlashLayoutVersion); 2319 /* psFlash2xCSInfo->FlashLayoutMinorVersion = ntohs(psFlash2xCSInfo->FlashLayoutMinorVersion); */ 2320 psFlash2xCSInfo->ISOImageVersion = ntohl(psFlash2xCSInfo->ISOImageVersion); 2321 psFlash2xCSInfo->SCSIFirmwareVersion = ntohl(psFlash2xCSInfo->SCSIFirmwareVersion); 2322 psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage); 2323 psFlash2xCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlash2xCSInfo->OffsetFromZeroForScsiFirmware); 2324 psFlash2xCSInfo->SizeOfScsiFirmware = ntohl(psFlash2xCSInfo->SizeOfScsiFirmware); 2325 psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage); 2326 psFlash2xCSInfo->OffsetFromZeroForDSDStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDStart); 2327 psFlash2xCSInfo->OffsetFromZeroForDSDEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDEnd); 2328 psFlash2xCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAStart); 2329 psFlash2xCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAEnd); 2330 psFlash2xCSInfo->OffsetFromZeroForControlSectionStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForControlSectionStart); 2331 psFlash2xCSInfo->OffsetFromZeroForControlSectionData = ntohl(psFlash2xCSInfo->OffsetFromZeroForControlSectionData); 2332 psFlash2xCSInfo->CDLessInactivityTimeout = ntohl(psFlash2xCSInfo->CDLessInactivityTimeout); 2333 psFlash2xCSInfo->NewImageSignature = ntohl(psFlash2xCSInfo->NewImageSignature); 2334 psFlash2xCSInfo->FlashSectorSizeSig = ntohl(psFlash2xCSInfo->FlashSectorSizeSig); 2335 psFlash2xCSInfo->FlashSectorSize = ntohl(psFlash2xCSInfo->FlashSectorSize); 2336 psFlash2xCSInfo->FlashWriteSupportSize = ntohl(psFlash2xCSInfo->FlashWriteSupportSize); 2337 psFlash2xCSInfo->TotalFlashSize = ntohl(psFlash2xCSInfo->TotalFlashSize); 2338 psFlash2xCSInfo->FlashBaseAddr = ntohl(psFlash2xCSInfo->FlashBaseAddr); 2339 psFlash2xCSInfo->FlashPartMaxSize = ntohl(psFlash2xCSInfo->FlashPartMaxSize); 2340 psFlash2xCSInfo->IsCDLessDeviceBootSig = ntohl(psFlash2xCSInfo->IsCDLessDeviceBootSig); 2341 psFlash2xCSInfo->MassStorageTimeout = ntohl(psFlash2xCSInfo->MassStorageTimeout); 2342 psFlash2xCSInfo->OffsetISOImage1Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1Start); 2343 psFlash2xCSInfo->OffsetISOImage1Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1End); 2344 psFlash2xCSInfo->OffsetISOImage1Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2Start); 2345 psFlash2xCSInfo->OffsetISOImage1Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2End); 2346 psFlash2xCSInfo->OffsetISOImage1Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3Start); 2347 psFlash2xCSInfo->OffsetISOImage1Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3End); 2348 psFlash2xCSInfo->OffsetISOImage2Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1Start); 2349 psFlash2xCSInfo->OffsetISOImage2Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1End); 2350 psFlash2xCSInfo->OffsetISOImage2Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2Start); 2351 psFlash2xCSInfo->OffsetISOImage2Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2End); 2352 psFlash2xCSInfo->OffsetISOImage2Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3Start); 2353 psFlash2xCSInfo->OffsetISOImage2Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3End); 2354 psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader = ntohl(psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader); 2355 psFlash2xCSInfo->OffsetFromZeroForDSD1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1Start); 2356 psFlash2xCSInfo->OffsetFromZeroForDSD1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1End); 2357 psFlash2xCSInfo->OffsetFromZeroForDSD2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2Start); 2358 psFlash2xCSInfo->OffsetFromZeroForDSD2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2End); 2359 psFlash2xCSInfo->OffsetFromZeroForVSA1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1Start); 2360 psFlash2xCSInfo->OffsetFromZeroForVSA1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1End); 2361 psFlash2xCSInfo->OffsetFromZeroForVSA2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2Start); 2362 psFlash2xCSInfo->OffsetFromZeroForVSA2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2End); 2363 2364 for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++) 2365 psFlash2xCSInfo->SectorAccessBitMap[Index] = ntohl(psFlash2xCSInfo->SectorAccessBitMap[Index]); 2366 2367 return STATUS_SUCCESS; 2368} 2369 2370static int ConvertEndianOfCSStructure(struct bcm_flash_cs_info *psFlashCSInfo) 2371{ 2372 /* unsigned int Index = 0; */ 2373 psFlashCSInfo->MagicNumber = ntohl(psFlashCSInfo->MagicNumber); 2374 psFlashCSInfo->FlashLayoutVersion = ntohl(psFlashCSInfo->FlashLayoutVersion); 2375 psFlashCSInfo->ISOImageVersion = ntohl(psFlashCSInfo->ISOImageVersion); 2376 /* won't convert according to old assumption */ 2377 psFlashCSInfo->SCSIFirmwareVersion = (psFlashCSInfo->SCSIFirmwareVersion); 2378 psFlashCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart1ISOImage); 2379 psFlashCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlashCSInfo->OffsetFromZeroForScsiFirmware); 2380 psFlashCSInfo->SizeOfScsiFirmware = ntohl(psFlashCSInfo->SizeOfScsiFirmware); 2381 psFlashCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart2ISOImage); 2382 psFlashCSInfo->OffsetFromZeroForCalibrationStart = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationStart); 2383 psFlashCSInfo->OffsetFromZeroForCalibrationEnd = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationEnd); 2384 psFlashCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlashCSInfo->OffsetFromZeroForVSAStart); 2385 psFlashCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlashCSInfo->OffsetFromZeroForVSAEnd); 2386 psFlashCSInfo->OffsetFromZeroForControlSectionStart = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionStart); 2387 psFlashCSInfo->OffsetFromZeroForControlSectionData = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionData); 2388 psFlashCSInfo->CDLessInactivityTimeout = ntohl(psFlashCSInfo->CDLessInactivityTimeout); 2389 psFlashCSInfo->NewImageSignature = ntohl(psFlashCSInfo->NewImageSignature); 2390 psFlashCSInfo->FlashSectorSizeSig = ntohl(psFlashCSInfo->FlashSectorSizeSig); 2391 psFlashCSInfo->FlashSectorSize = ntohl(psFlashCSInfo->FlashSectorSize); 2392 psFlashCSInfo->FlashWriteSupportSize = ntohl(psFlashCSInfo->FlashWriteSupportSize); 2393 psFlashCSInfo->TotalFlashSize = ntohl(psFlashCSInfo->TotalFlashSize); 2394 psFlashCSInfo->FlashBaseAddr = ntohl(psFlashCSInfo->FlashBaseAddr); 2395 psFlashCSInfo->FlashPartMaxSize = ntohl(psFlashCSInfo->FlashPartMaxSize); 2396 psFlashCSInfo->IsCDLessDeviceBootSig = ntohl(psFlashCSInfo->IsCDLessDeviceBootSig); 2397 psFlashCSInfo->MassStorageTimeout = ntohl(psFlashCSInfo->MassStorageTimeout); 2398 2399 return STATUS_SUCCESS; 2400} 2401 2402static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section) 2403{ 2404 return (Adapter->uiVendorExtnFlag && 2405 (Adapter->psFlash2xVendorInfo->VendorSection[section].AccessFlags & FLASH2X_SECTION_PRESENT) && 2406 (Adapter->psFlash2xVendorInfo->VendorSection[section].OffsetFromZeroForSectionStart != UNINIT_PTR_IN_CS)); 2407} 2408 2409static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter) 2410{ 2411 B_UINT32 i = 0; 2412 unsigned int uiSizeSection = 0; 2413 2414 Adapter->uiVendorExtnFlag = false; 2415 2416 for (i = 0; i < TOTAL_SECTIONS; i++) 2417 Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart = UNINIT_PTR_IN_CS; 2418 2419 if (STATUS_SUCCESS != vendorextnGetSectionInfo(Adapter, Adapter->psFlash2xVendorInfo)) 2420 return; 2421 2422 i = 0; 2423 while (i < TOTAL_SECTIONS) { 2424 if (!(Adapter->psFlash2xVendorInfo->VendorSection[i].AccessFlags & FLASH2X_SECTION_PRESENT)) { 2425 i++; 2426 continue; 2427 } 2428 2429 Adapter->uiVendorExtnFlag = TRUE; 2430 uiSizeSection = (Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionEnd - 2431 Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart); 2432 2433 switch (i) { 2434 case DSD0: 2435 if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header))) && 2436 (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) 2437 Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = VENDOR_PTR_IN_CS; 2438 else 2439 Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = UNINIT_PTR_IN_CS; 2440 break; 2441 2442 case DSD1: 2443 if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header))) && 2444 (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) 2445 Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = VENDOR_PTR_IN_CS; 2446 else 2447 Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = UNINIT_PTR_IN_CS; 2448 break; 2449 2450 case DSD2: 2451 if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header))) && 2452 (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) 2453 Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = VENDOR_PTR_IN_CS; 2454 else 2455 Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = UNINIT_PTR_IN_CS; 2456 break; 2457 case VSA0: 2458 if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) 2459 Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = VENDOR_PTR_IN_CS; 2460 else 2461 Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = UNINIT_PTR_IN_CS; 2462 break; 2463 2464 case VSA1: 2465 if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) 2466 Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = VENDOR_PTR_IN_CS; 2467 else 2468 Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = UNINIT_PTR_IN_CS; 2469 break; 2470 case VSA2: 2471 if (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) 2472 Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = VENDOR_PTR_IN_CS; 2473 else 2474 Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = UNINIT_PTR_IN_CS; 2475 break; 2476 2477 default: 2478 break; 2479 } 2480 i++; 2481 } 2482} 2483 2484/* 2485 * Procedure: BcmGetFlashCSInfo 2486 * 2487 * Description: Reads control structure and gets Cal section addresses. 2488 * 2489 * Arguments: 2490 * Adapter - ptr to Adapter object instance 2491 * 2492 * Returns: 2493 * <VOID> 2494 */ 2495 2496static int BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter) 2497{ 2498 /* struct bcm_flash_cs_info sFlashCsInfo = {0}; */ 2499 2500 #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) 2501 unsigned int value; 2502 #endif 2503 2504 unsigned int uiFlashLayoutMajorVersion; 2505 2506 Adapter->uiFlashLayoutMinorVersion = 0; 2507 Adapter->uiFlashLayoutMajorVersion = 0; 2508 Adapter->ulFlashControlSectionStart = FLASH_CS_INFO_START_ADDR; 2509 2510 Adapter->uiFlashBaseAdd = 0; 2511 Adapter->ulFlashCalStart = 0; 2512 memset(Adapter->psFlashCSInfo, 0 , sizeof(struct bcm_flash_cs_info)); 2513 memset(Adapter->psFlash2xCSInfo, 0 , sizeof(struct bcm_flash2x_cs_info)); 2514 2515 if (!Adapter->bDDRInitDone) { 2516 value = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; 2517 wrmalt(Adapter, 0xAF00A080, &value, sizeof(value)); 2518 } 2519 2520 /* Reading first 8 Bytes to get the Flash Layout 2521 * MagicNumber(4 bytes) +FlashLayoutMinorVersion(2 Bytes) +FlashLayoutMajorVersion(2 Bytes) 2522 */ 2523 BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, 8); 2524 2525 Adapter->psFlashCSInfo->FlashLayoutVersion = ntohl(Adapter->psFlashCSInfo->FlashLayoutVersion); 2526 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Version :%X", (Adapter->psFlashCSInfo->FlashLayoutVersion)); 2527 /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Minor Version :%d\n", ntohs(sFlashCsInfo.FlashLayoutMinorVersion)); */ 2528 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x\n", ntohl(Adapter->psFlashCSInfo->MagicNumber)); 2529 2530 if (FLASH_CONTROL_STRUCT_SIGNATURE == ntohl(Adapter->psFlashCSInfo->MagicNumber)) { 2531 uiFlashLayoutMajorVersion = MAJOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion)); 2532 Adapter->uiFlashLayoutMinorVersion = MINOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion)); 2533 } else { 2534 Adapter->uiFlashLayoutMinorVersion = 0; 2535 uiFlashLayoutMajorVersion = 0; 2536 } 2537 2538 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FLASH LAYOUT MAJOR VERSION :%X", uiFlashLayoutMajorVersion); 2539 2540 if (uiFlashLayoutMajorVersion < FLASH_2X_MAJOR_NUMBER) { 2541 BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, sizeof(struct bcm_flash_cs_info)); 2542 ConvertEndianOfCSStructure(Adapter->psFlashCSInfo); 2543 Adapter->ulFlashCalStart = (Adapter->psFlashCSInfo->OffsetFromZeroForCalibrationStart); 2544 2545 if (!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) 2546 Adapter->ulFlashControlSectionStart = Adapter->psFlashCSInfo->OffsetFromZeroForControlSectionStart; 2547 2548 if ((FLASH_CONTROL_STRUCT_SIGNATURE == (Adapter->psFlashCSInfo->MagicNumber)) && 2549 (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlashCSInfo->SCSIFirmwareVersion)) && 2550 (FLASH_SECTOR_SIZE_SIG == (Adapter->psFlashCSInfo->FlashSectorSizeSig)) && 2551 (BYTE_WRITE_SUPPORT == (Adapter->psFlashCSInfo->FlashWriteSupportSize))) { 2552 Adapter->ulFlashWriteSize = (Adapter->psFlashCSInfo->FlashWriteSupportSize); 2553 Adapter->fpFlashWrite = flashByteWrite; 2554 Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; 2555 } else { 2556 Adapter->ulFlashWriteSize = MAX_RW_SIZE; 2557 Adapter->fpFlashWrite = flashWrite; 2558 Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; 2559 } 2560 2561 BcmGetFlashSectorSize(Adapter, (Adapter->psFlashCSInfo->FlashSectorSizeSig), 2562 (Adapter->psFlashCSInfo->FlashSectorSize)); 2563 Adapter->uiFlashBaseAdd = Adapter->psFlashCSInfo->FlashBaseAddr & 0xFCFFFFFF; 2564 } else { 2565 if (BcmFlash2xBulkRead(Adapter, (PUINT)Adapter->psFlash2xCSInfo, NO_SECTION_VAL, 2566 Adapter->ulFlashControlSectionStart, sizeof(struct bcm_flash2x_cs_info))) { 2567 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to read CS structure\n"); 2568 return STATUS_FAILURE; 2569 } 2570 2571 ConvertEndianOf2XCSStructure(Adapter->psFlash2xCSInfo); 2572 BcmDumpFlash2XCSStructure(Adapter->psFlash2xCSInfo, Adapter); 2573 if ((FLASH_CONTROL_STRUCT_SIGNATURE == Adapter->psFlash2xCSInfo->MagicNumber) && 2574 (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlash2xCSInfo->SCSIFirmwareVersion)) && 2575 (FLASH_SECTOR_SIZE_SIG == Adapter->psFlash2xCSInfo->FlashSectorSizeSig) && 2576 (BYTE_WRITE_SUPPORT == Adapter->psFlash2xCSInfo->FlashWriteSupportSize)) { 2577 Adapter->ulFlashWriteSize = Adapter->psFlash2xCSInfo->FlashWriteSupportSize; 2578 Adapter->fpFlashWrite = flashByteWrite; 2579 Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; 2580 } else { 2581 Adapter->ulFlashWriteSize = MAX_RW_SIZE; 2582 Adapter->fpFlashWrite = flashWrite; 2583 Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; 2584 } 2585 2586 BcmGetFlashSectorSize(Adapter, Adapter->psFlash2xCSInfo->FlashSectorSizeSig, 2587 Adapter->psFlash2xCSInfo->FlashSectorSize); 2588 2589 UpdateVendorInfo(Adapter); 2590 2591 BcmGetActiveDSD(Adapter); 2592 BcmGetActiveISO(Adapter); 2593 Adapter->uiFlashBaseAdd = Adapter->psFlash2xCSInfo->FlashBaseAddr & 0xFCFFFFFF; 2594 Adapter->ulFlashControlSectionStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart; 2595 } 2596 /* 2597 * Concerns: what if CS sector size does not match with this sector size ??? 2598 * what is the indication of AccessBitMap in CS in flash 2.x ???? 2599 */ 2600 Adapter->ulFlashID = BcmReadFlashRDID(Adapter); 2601 Adapter->uiFlashLayoutMajorVersion = uiFlashLayoutMajorVersion; 2602 2603 return STATUS_SUCCESS; 2604} 2605 2606/* 2607 * Procedure: BcmGetNvmType 2608 * 2609 * Description: Finds the type of NVM used. 2610 * 2611 * Arguments: 2612 * Adapter - ptr to Adapter object instance 2613 * 2614 * Returns: 2615 * NVM_TYPE 2616 * 2617 */ 2618 2619static enum bcm_nvm_type BcmGetNvmType(struct bcm_mini_adapter *Adapter) 2620{ 2621 unsigned int uiData = 0; 2622 2623 BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4); 2624 if (uiData == BECM) 2625 return NVM_EEPROM; 2626 2627 /* 2628 * Read control struct and get cal addresses before accessing the flash 2629 */ 2630 BcmGetFlashCSInfo(Adapter); 2631 2632 BeceemFlashBulkRead(Adapter, &uiData, 0x0 + Adapter->ulFlashCalStart, 4); 2633 if (uiData == BECM) 2634 return NVM_FLASH; 2635 2636 /* 2637 * even if there is no valid signature on EEPROM/FLASH find out if they really exist. 2638 * if exist select it. 2639 */ 2640 if (BcmGetEEPROMSize(Adapter)) 2641 return NVM_EEPROM; 2642 2643 /* TBD for Flash. */ 2644 return NVM_UNKNOWN; 2645} 2646 2647/* 2648 * BcmGetSectionValStartOffset - this will calculate the section's starting offset if section val is given 2649 * @Adapter : Drivers Private Data structure 2650 * @eFlashSectionVal : Flash secion value defined in enum bcm_flash2x_section_val 2651 * 2652 * Return value:- 2653 * On success it return the start offset of the provided section val 2654 * On Failure -returns STATUS_FAILURE 2655 */ 2656 2657int BcmGetSectionValStartOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal) 2658{ 2659 /* 2660 * Considering all the section for which end offset can be calculated or directly given 2661 * in CS Structure. if matching case does not exist, return STATUS_FAILURE indicating section 2662 * endoffset can't be calculated or given in CS Structure. 2663 */ 2664 2665 int SectStartOffset = 0; 2666 2667 SectStartOffset = INVALID_OFFSET; 2668 2669 if (IsSectionExistInVendorInfo(Adapter, eFlashSectionVal)) 2670 return Adapter->psFlash2xVendorInfo->VendorSection[eFlashSectionVal].OffsetFromZeroForSectionStart; 2671 2672 switch (eFlashSectionVal) { 2673 case ISO_IMAGE1: 2674 if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && 2675 (IsNonCDLessDevice(Adapter) == false)) 2676 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start); 2677 break; 2678 case ISO_IMAGE2: 2679 if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && 2680 (IsNonCDLessDevice(Adapter) == false)) 2681 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start); 2682 break; 2683 case DSD0: 2684 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) 2685 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart); 2686 break; 2687 case DSD1: 2688 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) 2689 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start); 2690 break; 2691 case DSD2: 2692 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) 2693 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start); 2694 break; 2695 case VSA0: 2696 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) 2697 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart); 2698 break; 2699 case VSA1: 2700 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) 2701 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start); 2702 break; 2703 case VSA2: 2704 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) 2705 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start); 2706 break; 2707 case SCSI: 2708 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) 2709 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware); 2710 break; 2711 case CONTROL_SECTION: 2712 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) 2713 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart); 2714 break; 2715 case ISO_IMAGE1_PART2: 2716 if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start != UNINIT_PTR_IN_CS) 2717 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start); 2718 break; 2719 case ISO_IMAGE1_PART3: 2720 if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start != UNINIT_PTR_IN_CS) 2721 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); 2722 break; 2723 case ISO_IMAGE2_PART2: 2724 if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start != UNINIT_PTR_IN_CS) 2725 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start); 2726 break; 2727 case ISO_IMAGE2_PART3: 2728 if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start != UNINIT_PTR_IN_CS) 2729 SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); 2730 break; 2731 default: 2732 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x"); 2733 SectStartOffset = INVALID_OFFSET; 2734 } 2735 2736 return SectStartOffset; 2737} 2738 2739/* 2740 * BcmGetSectionValEndOffset - this will calculate the section's Ending offset if section val is given 2741 * @Adapter : Drivers Private Data structure 2742 * @eFlashSectionVal : Flash secion value defined in enum bcm_flash2x_section_val 2743 * 2744 * Return value:- 2745 * On success it return the end offset of the provided section val 2746 * On Failure -returns STATUS_FAILURE 2747 */ 2748 2749static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal) 2750{ 2751 int SectEndOffset = 0; 2752 2753 SectEndOffset = INVALID_OFFSET; 2754 if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal)) 2755 return Adapter->psFlash2xVendorInfo->VendorSection[eFlash2xSectionVal].OffsetFromZeroForSectionEnd; 2756 2757 switch (eFlash2xSectionVal) { 2758 case ISO_IMAGE1: 2759 if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End != UNINIT_PTR_IN_CS) && 2760 (IsNonCDLessDevice(Adapter) == false)) 2761 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End); 2762 break; 2763 case ISO_IMAGE2: 2764 if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End != UNINIT_PTR_IN_CS) && 2765 (IsNonCDLessDevice(Adapter) == false)) 2766 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End); 2767 break; 2768 case DSD0: 2769 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd != UNINIT_PTR_IN_CS) 2770 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd); 2771 break; 2772 case DSD1: 2773 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End != UNINIT_PTR_IN_CS) 2774 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End); 2775 break; 2776 case DSD2: 2777 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End != UNINIT_PTR_IN_CS) 2778 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End); 2779 break; 2780 case VSA0: 2781 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd != UNINIT_PTR_IN_CS) 2782 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd); 2783 break; 2784 case VSA1: 2785 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End != UNINIT_PTR_IN_CS) 2786 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End); 2787 break; 2788 case VSA2: 2789 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End != UNINIT_PTR_IN_CS) 2790 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End); 2791 break; 2792 case SCSI: 2793 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) 2794 SectEndOffset = ((Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) + 2795 (Adapter->psFlash2xCSInfo->SizeOfScsiFirmware)); 2796 break; 2797 case CONTROL_SECTION: 2798 /* Not Clear So Putting failure. confirm and fix it. */ 2799 SectEndOffset = STATUS_FAILURE; 2800 break; 2801 case ISO_IMAGE1_PART2: 2802 if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End != UNINIT_PTR_IN_CS) 2803 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End); 2804 break; 2805 case ISO_IMAGE1_PART3: 2806 if (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End != UNINIT_PTR_IN_CS) 2807 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End); 2808 break; 2809 case ISO_IMAGE2_PART2: 2810 if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End != UNINIT_PTR_IN_CS) 2811 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End); 2812 break; 2813 case ISO_IMAGE2_PART3: 2814 if (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End != UNINIT_PTR_IN_CS) 2815 SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End); 2816 break; 2817 default: 2818 SectEndOffset = INVALID_OFFSET; 2819 } 2820 2821 return SectEndOffset; 2822} 2823 2824/* 2825 * BcmFlash2xBulkRead:- Read API for Flash Map 2.x . 2826 * @Adapter :Driver Private Data Structure 2827 * @pBuffer : Buffer where data has to be put after reading 2828 * @eFlashSectionVal :Flash Section Val defined in enum bcm_flash2x_section_val 2829 * @uiOffsetWithinSectionVal :- Offset with in provided section 2830 * @uiNumBytes : Number of Bytes for Read 2831 * 2832 * Return value:- 2833 * return true on success and STATUS_FAILURE on fail. 2834 */ 2835 2836int BcmFlash2xBulkRead(struct bcm_mini_adapter *Adapter, 2837 PUINT pBuffer, 2838 enum bcm_flash2x_section_val eFlash2xSectionVal, 2839 unsigned int uiOffsetWithinSectionVal, 2840 unsigned int uiNumBytes) 2841{ 2842 int Status = STATUS_SUCCESS; 2843 int SectionStartOffset = 0; 2844 unsigned int uiAbsoluteOffset = 0; 2845 unsigned int uiTemp = 0, value = 0; 2846 2847 if (!Adapter) { 2848 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); 2849 return -EINVAL; 2850 } 2851 if (Adapter->device_removed) { 2852 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); 2853 return -ENODEV; 2854 } 2855 2856 /* NO_SECTION_VAL means absolute offset is given. */ 2857 if (eFlash2xSectionVal == NO_SECTION_VAL) 2858 SectionStartOffset = 0; 2859 else 2860 SectionStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal); 2861 2862 if (SectionStartOffset == STATUS_FAILURE) { 2863 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exist in Flash 2.x Map ", eFlash2xSectionVal); 2864 return -EINVAL; 2865 } 2866 2867 if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal)) 2868 return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectionVal, uiOffsetWithinSectionVal, uiNumBytes); 2869 2870 /* calculating the absolute offset from FLASH; */ 2871 uiAbsoluteOffset = uiOffsetWithinSectionVal + SectionStartOffset; 2872 rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 2873 value = 0; 2874 wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); 2875 Status = BeceemFlashBulkRead(Adapter, pBuffer, uiAbsoluteOffset, uiNumBytes); 2876 wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 2877 if (Status) { 2878 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Read Failed with Status :%d", Status); 2879 return Status; 2880 } 2881 2882 return Status; 2883} 2884 2885/* 2886 * BcmFlash2xBulkWrite :-API for Writing on the Flash Map 2.x. 2887 * @Adapter :Driver Private Data Structure 2888 * @pBuffer : Buffer From where data has to taken for writing 2889 * @eFlashSectionVal :Flash Section Val defined in enum bcm_flash2x_section_val 2890 * @uiOffsetWithinSectionVal :- Offset with in provided section 2891 * @uiNumBytes : Number of Bytes for Write 2892 * 2893 * Return value:- 2894 * return true on success and STATUS_FAILURE on fail. 2895 * 2896 */ 2897 2898int BcmFlash2xBulkWrite(struct bcm_mini_adapter *Adapter, 2899 PUINT pBuffer, 2900 enum bcm_flash2x_section_val eFlash2xSectVal, 2901 unsigned int uiOffset, 2902 unsigned int uiNumBytes, 2903 unsigned int bVerify) 2904{ 2905 int Status = STATUS_SUCCESS; 2906 unsigned int FlashSectValStartOffset = 0; 2907 unsigned int uiTemp = 0, value = 0; 2908 2909 if (!Adapter) { 2910 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); 2911 return -EINVAL; 2912 } 2913 2914 if (Adapter->device_removed) { 2915 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); 2916 return -ENODEV; 2917 } 2918 2919 /* NO_SECTION_VAL means absolute offset is given. */ 2920 if (eFlash2xSectVal == NO_SECTION_VAL) 2921 FlashSectValStartOffset = 0; 2922 else 2923 FlashSectValStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectVal); 2924 2925 if (FlashSectValStartOffset == STATUS_FAILURE) { 2926 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exist in Flash Map 2.x", eFlash2xSectVal); 2927 return -EINVAL; 2928 } 2929 2930 if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectVal)) 2931 return vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectVal, uiOffset, uiNumBytes, bVerify); 2932 2933 /* calculating the absolute offset from FLASH; */ 2934 uiOffset = uiOffset + FlashSectValStartOffset; 2935 2936 rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 2937 value = 0; 2938 wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); 2939 2940 Status = BeceemFlashBulkWrite(Adapter, pBuffer, uiOffset, uiNumBytes, bVerify); 2941 2942 wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 2943 if (Status) { 2944 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write failed with Status :%d", Status); 2945 return Status; 2946 } 2947 2948 return Status; 2949} 2950 2951/* 2952 * BcmGetActiveDSD : Set the Active DSD in Adapter Structure which has to be dumped in DDR 2953 * @Adapter :-Drivers private Data Structure 2954 * 2955 * Return Value:- 2956 * Return STATUS_SUCESS if get success in setting the right DSD else negative error code 2957 * 2958 */ 2959 2960static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter) 2961{ 2962 enum bcm_flash2x_section_val uiHighestPriDSD = 0; 2963 2964 uiHighestPriDSD = getHighestPriDSD(Adapter); 2965 Adapter->eActiveDSD = uiHighestPriDSD; 2966 2967 if (DSD0 == uiHighestPriDSD) 2968 Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart; 2969 if (DSD1 == uiHighestPriDSD) 2970 Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start; 2971 if (DSD2 == uiHighestPriDSD) 2972 Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start; 2973 if (Adapter->eActiveDSD) 2974 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active DSD :%d", Adapter->eActiveDSD); 2975 if (Adapter->eActiveDSD == 0) { 2976 /* if No DSD gets Active, Make Active the DSD with WR permission */ 2977 if (IsSectionWritable(Adapter, DSD2)) { 2978 Adapter->eActiveDSD = DSD2; 2979 Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start; 2980 } else if (IsSectionWritable(Adapter, DSD1)) { 2981 Adapter->eActiveDSD = DSD1; 2982 Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start; 2983 } else if (IsSectionWritable(Adapter, DSD0)) { 2984 Adapter->eActiveDSD = DSD0; 2985 Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart; 2986 } 2987 } 2988 2989 return STATUS_SUCCESS; 2990} 2991 2992/* 2993 * BcmGetActiveISO :- Set the Active ISO in Adapter Data Structue 2994 * @Adapter : Driver private Data Structure 2995 * 2996 * Return Value:- 2997 * Sucsess:- STATUS_SUCESS 2998 * Failure- : negative erro code 2999 * 3000 */ 3001 3002static int BcmGetActiveISO(struct bcm_mini_adapter *Adapter) 3003{ 3004 int HighestPriISO = 0; 3005 3006 HighestPriISO = getHighestPriISO(Adapter); 3007 3008 Adapter->eActiveISO = HighestPriISO; 3009 if (Adapter->eActiveISO == ISO_IMAGE2) 3010 Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start); 3011 else if (Adapter->eActiveISO == ISO_IMAGE1) 3012 Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start); 3013 3014 if (Adapter->eActiveISO) 3015 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active ISO :%x", Adapter->eActiveISO); 3016 3017 return STATUS_SUCCESS; 3018} 3019 3020/* 3021 * IsOffsetWritable :- it will tell the access permission of the sector having passed offset 3022 * @Adapter : Drivers Private Data Structure 3023 * @uiOffset : Offset provided in the Flash 3024 * 3025 * Return Value:- 3026 * Success:-TRUE , offset is writable 3027 * Failure:-false, offset is RO 3028 * 3029 */ 3030 3031static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, unsigned int uiOffset) 3032{ 3033 unsigned int uiSectorNum = 0; 3034 unsigned int uiWordOfSectorPermission = 0; 3035 unsigned int uiBitofSectorePermission = 0; 3036 B_UINT32 permissionBits = 0; 3037 3038 uiSectorNum = uiOffset/Adapter->uiSectorSize; 3039 3040 /* calculating the word having this Sector Access permission from SectorAccessBitMap Array */ 3041 uiWordOfSectorPermission = Adapter->psFlash2xCSInfo->SectorAccessBitMap[uiSectorNum / 16]; 3042 3043 /* calculating the bit index inside the word for this sector */ 3044 uiBitofSectorePermission = 2 * (15 - uiSectorNum % 16); 3045 3046 /* Setting Access permission */ 3047 permissionBits = uiWordOfSectorPermission & (0x3 << uiBitofSectorePermission); 3048 permissionBits = (permissionBits >> uiBitofSectorePermission) & 0x3; 3049 if (permissionBits == SECTOR_READWRITE_PERMISSION) 3050 return TRUE; 3051 else 3052 return false; 3053} 3054 3055static int BcmDumpFlash2xSectionBitMap(struct bcm_flash2x_bitmap *psFlash2xBitMap) 3056{ 3057 struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); 3058 3059 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "***************Flash 2.x Section Bitmap***************"); 3060 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE1 :0X%x", psFlash2xBitMap->ISO_IMAGE1); 3061 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE2 :0X%x", psFlash2xBitMap->ISO_IMAGE2); 3062 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD0 :0X%x", psFlash2xBitMap->DSD0); 3063 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD1 :0X%x", psFlash2xBitMap->DSD1); 3064 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD2 :0X%x", psFlash2xBitMap->DSD2); 3065 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA0 :0X%x", psFlash2xBitMap->VSA0); 3066 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA1 :0X%x", psFlash2xBitMap->VSA1); 3067 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA2 :0X%x", psFlash2xBitMap->VSA2); 3068 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSI :0X%x", psFlash2xBitMap->SCSI); 3069 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CONTROL_SECTION :0X%x", psFlash2xBitMap->CONTROL_SECTION); 3070 3071 return STATUS_SUCCESS; 3072} 3073 3074/* 3075 * BcmGetFlash2xSectionalBitMap :- It will provide the bit map of all the section present in Flash 3076 * 8bit has been assigned to every section. 3077 * bit[0] :Section present or not 3078 * bit[1] :section is valid or not 3079 * bit[2] : Secton is read only or has write permission too. 3080 * bit[3] : Active Section - 3081 * bit[7...4] = Reserved . 3082 * 3083 * @Adapter:-Driver private Data Structure 3084 * 3085 * Return value:- 3086 * Success:- STATUS_SUCESS 3087 * Failure:- negative error code 3088 */ 3089 3090int BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_bitmap *psFlash2xBitMap) 3091{ 3092 struct bcm_flash2x_cs_info *psFlash2xCSInfo = Adapter->psFlash2xCSInfo; 3093 enum bcm_flash2x_section_val uiHighestPriDSD = 0; 3094 enum bcm_flash2x_section_val uiHighestPriISO = 0; 3095 bool SetActiveDSDDone = false; 3096 bool SetActiveISODone = false; 3097 3098 /* For 1.x map all the section except DSD0 will be shown as not present 3099 * This part will be used by calibration tool to detect the number of DSD present in Flash. 3100 */ 3101 if (IsFlash2x(Adapter) == false) { 3102 psFlash2xBitMap->ISO_IMAGE2 = 0; 3103 psFlash2xBitMap->ISO_IMAGE1 = 0; 3104 psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; /* 0xF; 0000(Reseved)1(Active)0(RW)1(valid)1(present) */ 3105 psFlash2xBitMap->DSD1 = 0; 3106 psFlash2xBitMap->DSD2 = 0; 3107 psFlash2xBitMap->VSA0 = 0; 3108 psFlash2xBitMap->VSA1 = 0; 3109 psFlash2xBitMap->VSA2 = 0; 3110 psFlash2xBitMap->CONTROL_SECTION = 0; 3111 psFlash2xBitMap->SCSI = 0; 3112 psFlash2xBitMap->Reserved0 = 0; 3113 psFlash2xBitMap->Reserved1 = 0; 3114 psFlash2xBitMap->Reserved2 = 0; 3115 3116 return STATUS_SUCCESS; 3117 } 3118 3119 uiHighestPriDSD = getHighestPriDSD(Adapter); 3120 uiHighestPriISO = getHighestPriISO(Adapter); 3121 3122 /* 3123 * IS0 IMAGE 2 3124 */ 3125 if ((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) { 3126 /* Setting the 0th Bit representing the Section is present or not. */ 3127 psFlash2xBitMap->ISO_IMAGE2 = psFlash2xBitMap->ISO_IMAGE2 | FLASH2X_SECTION_PRESENT; 3128 3129 if (ReadISOSignature(Adapter, ISO_IMAGE2) == ISO_IMAGE_MAGIC_NUMBER) 3130 psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_VALID; 3131 3132 /* Calculation for extrating the Access permission */ 3133 if (IsSectionWritable(Adapter, ISO_IMAGE2) == false) 3134 psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_RO; 3135 3136 if (SetActiveISODone == false && uiHighestPriISO == ISO_IMAGE2) { 3137 psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_ACT; 3138 SetActiveISODone = TRUE; 3139 } 3140 } 3141 3142 /* 3143 * IS0 IMAGE 1 3144 */ 3145 if ((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) { 3146 /* Setting the 0th Bit representing the Section is present or not. */ 3147 psFlash2xBitMap->ISO_IMAGE1 = psFlash2xBitMap->ISO_IMAGE1 | FLASH2X_SECTION_PRESENT; 3148 3149 if (ReadISOSignature(Adapter, ISO_IMAGE1) == ISO_IMAGE_MAGIC_NUMBER) 3150 psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_VALID; 3151 3152 /* Calculation for extrating the Access permission */ 3153 if (IsSectionWritable(Adapter, ISO_IMAGE1) == false) 3154 psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_RO; 3155 3156 if (SetActiveISODone == false && uiHighestPriISO == ISO_IMAGE1) { 3157 psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_ACT; 3158 SetActiveISODone = TRUE; 3159 } 3160 } 3161 3162 /* 3163 * DSD2 3164 */ 3165 if ((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) { 3166 /* Setting the 0th Bit representing the Section is present or not. */ 3167 psFlash2xBitMap->DSD2 = psFlash2xBitMap->DSD2 | FLASH2X_SECTION_PRESENT; 3168 3169 if (ReadDSDSignature(Adapter, DSD2) == DSD_IMAGE_MAGIC_NUMBER) 3170 psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_VALID; 3171 3172 /* Calculation for extrating the Access permission */ 3173 if (IsSectionWritable(Adapter, DSD2) == false) { 3174 psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_RO; 3175 } else { 3176 /* Means section is writable */ 3177 if ((SetActiveDSDDone == false) && (uiHighestPriDSD == DSD2)) { 3178 psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT; 3179 SetActiveDSDDone = TRUE; 3180 } 3181 } 3182 } 3183 3184 /* 3185 * DSD 1 3186 */ 3187 if ((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) { 3188 /* Setting the 0th Bit representing the Section is present or not. */ 3189 psFlash2xBitMap->DSD1 = psFlash2xBitMap->DSD1 | FLASH2X_SECTION_PRESENT; 3190 3191 if (ReadDSDSignature(Adapter, DSD1) == DSD_IMAGE_MAGIC_NUMBER) 3192 psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_VALID; 3193 3194 /* Calculation for extrating the Access permission */ 3195 if (IsSectionWritable(Adapter, DSD1) == false) { 3196 psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_RO; 3197 } else { 3198 /* Means section is writable */ 3199 if ((SetActiveDSDDone == false) && (uiHighestPriDSD == DSD1)) { 3200 psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT; 3201 SetActiveDSDDone = TRUE; 3202 } 3203 } 3204 } 3205 3206 /* 3207 * For DSD 0 3208 */ 3209 if ((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) { 3210 /* Setting the 0th Bit representing the Section is present or not. */ 3211 psFlash2xBitMap->DSD0 = psFlash2xBitMap->DSD0 | FLASH2X_SECTION_PRESENT; 3212 3213 if (ReadDSDSignature(Adapter, DSD0) == DSD_IMAGE_MAGIC_NUMBER) 3214 psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_VALID; 3215 3216 /* Setting Access permission */ 3217 if (IsSectionWritable(Adapter, DSD0) == false) { 3218 psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_RO; 3219 } else { 3220 /* Means section is writable */ 3221 if ((SetActiveDSDDone == false) && (uiHighestPriDSD == DSD0)) { 3222 psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT; 3223 SetActiveDSDDone = TRUE; 3224 } 3225 } 3226 } 3227 3228 /* 3229 * VSA 0 3230 */ 3231 if ((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) { 3232 /* Setting the 0th Bit representing the Section is present or not. */ 3233 psFlash2xBitMap->VSA0 = psFlash2xBitMap->VSA0 | FLASH2X_SECTION_PRESENT; 3234 3235 /* Setting the Access Bit. Map is not defined hece setting it always valid */ 3236 psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_VALID; 3237 3238 /* Calculation for extrating the Access permission */ 3239 if (IsSectionWritable(Adapter, VSA0) == false) 3240 psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_RO; 3241 3242 /* By Default section is Active */ 3243 psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_ACT; 3244 } 3245 3246 /* 3247 * VSA 1 3248 */ 3249 if ((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) { 3250 /* Setting the 0th Bit representing the Section is present or not. */ 3251 psFlash2xBitMap->VSA1 = psFlash2xBitMap->VSA1 | FLASH2X_SECTION_PRESENT; 3252 3253 /* Setting the Access Bit. Map is not defined hece setting it always valid */ 3254 psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_VALID; 3255 3256 /* Checking For Access permission */ 3257 if (IsSectionWritable(Adapter, VSA1) == false) 3258 psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_RO; 3259 3260 /* By Default section is Active */ 3261 psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_ACT; 3262 } 3263 3264 /* 3265 * VSA 2 3266 */ 3267 if ((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) { 3268 /* Setting the 0th Bit representing the Section is present or not. */ 3269 psFlash2xBitMap->VSA2 = psFlash2xBitMap->VSA2 | FLASH2X_SECTION_PRESENT; 3270 3271 /* Setting the Access Bit. Map is not defined hece setting it always valid */ 3272 psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_VALID; 3273 3274 /* Checking For Access permission */ 3275 if (IsSectionWritable(Adapter, VSA2) == false) 3276 psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_RO; 3277 3278 /* By Default section is Active */ 3279 psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_ACT; 3280 } 3281 3282 /* 3283 * SCSI Section 3284 */ 3285 if ((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) { 3286 /* Setting the 0th Bit representing the Section is present or not. */ 3287 psFlash2xBitMap->SCSI = psFlash2xBitMap->SCSI | FLASH2X_SECTION_PRESENT; 3288 3289 /* Setting the Access Bit. Map is not defined hece setting it always valid */ 3290 psFlash2xBitMap->SCSI |= FLASH2X_SECTION_VALID; 3291 3292 /* Checking For Access permission */ 3293 if (IsSectionWritable(Adapter, SCSI) == false) 3294 psFlash2xBitMap->SCSI |= FLASH2X_SECTION_RO; 3295 3296 /* By Default section is Active */ 3297 psFlash2xBitMap->SCSI |= FLASH2X_SECTION_ACT; 3298 } 3299 3300 /* 3301 * Control Section 3302 */ 3303 if ((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) { 3304 /* Setting the 0th Bit representing the Section is present or not. */ 3305 psFlash2xBitMap->CONTROL_SECTION = psFlash2xBitMap->CONTROL_SECTION | (FLASH2X_SECTION_PRESENT); 3306 3307 /* Setting the Access Bit. Map is not defined hece setting it always valid */ 3308 psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_VALID; 3309 3310 /* Checking For Access permission */ 3311 if (IsSectionWritable(Adapter, CONTROL_SECTION) == false) 3312 psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_RO; 3313 3314 /* By Default section is Active */ 3315 psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_ACT; 3316 } 3317 3318 /* 3319 * For Reserved Sections 3320 */ 3321 psFlash2xBitMap->Reserved0 = 0; 3322 psFlash2xBitMap->Reserved0 = 0; 3323 psFlash2xBitMap->Reserved0 = 0; 3324 BcmDumpFlash2xSectionBitMap(psFlash2xBitMap); 3325 3326 return STATUS_SUCCESS; 3327} 3328 3329/* 3330 * BcmSetActiveSection :- Set Active section is used to make priority field highest over other 3331 * section of same type. 3332 * 3333 * @Adapater :- Bcm Driver Private Data Structure 3334 * @eFlash2xSectionVal :- Flash section val whose priority has to be made highest. 3335 * 3336 * Return Value:- Make the priorit highest else return erorr code 3337 * 3338 */ 3339 3340int BcmSetActiveSection(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectVal) 3341{ 3342 unsigned int SectImagePriority = 0; 3343 int Status = STATUS_SUCCESS; 3344 3345 /* struct bcm_dsd_header sDSD = {0}; 3346 * struct bcm_iso_header sISO = {0}; 3347 */ 3348 int HighestPriDSD = 0; 3349 int HighestPriISO = 0; 3350 3351 Status = IsSectionWritable(Adapter, eFlash2xSectVal); 3352 if (Status != TRUE) { 3353 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section <%d> is not writable", eFlash2xSectVal); 3354 return STATUS_FAILURE; 3355 } 3356 3357 Adapter->bHeaderChangeAllowed = TRUE; 3358 switch (eFlash2xSectVal) { 3359 case ISO_IMAGE1: 3360 case ISO_IMAGE2: 3361 if (ReadISOSignature(Adapter, eFlash2xSectVal) == ISO_IMAGE_MAGIC_NUMBER) { 3362 HighestPriISO = getHighestPriISO(Adapter); 3363 3364 if (HighestPriISO == eFlash2xSectVal) { 3365 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal); 3366 Status = STATUS_SUCCESS; 3367 break; 3368 } 3369 3370 SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1; 3371 3372 if ((SectImagePriority == 0) && IsSectionWritable(Adapter, HighestPriISO)) { 3373 /* This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF. 3374 * We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO 3375 * by user 3376 */ 3377 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); 3378 SectImagePriority = htonl(0x1); 3379 Status = BcmFlash2xBulkWrite(Adapter, 3380 &SectImagePriority, 3381 HighestPriISO, 3382 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImagePriority), 3383 SIGNATURE_SIZE, 3384 TRUE); 3385 if (Status) { 3386 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); 3387 Status = STATUS_FAILURE; 3388 break; 3389 } 3390 3391 HighestPriISO = getHighestPriISO(Adapter); 3392 3393 if (HighestPriISO == eFlash2xSectVal) { 3394 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal); 3395 Status = STATUS_SUCCESS; 3396 break; 3397 } 3398 3399 SectImagePriority = 2; 3400 } 3401 3402 SectImagePriority = htonl(SectImagePriority); 3403 3404 Status = BcmFlash2xBulkWrite(Adapter, 3405 &SectImagePriority, 3406 eFlash2xSectVal, 3407 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImagePriority), 3408 SIGNATURE_SIZE, 3409 TRUE); 3410 if (Status) { 3411 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); 3412 break; 3413 } 3414 } else { 3415 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); 3416 Status = STATUS_FAILURE; 3417 break; 3418 } 3419 break; 3420 case DSD0: 3421 case DSD1: 3422 case DSD2: 3423 if (ReadDSDSignature(Adapter, eFlash2xSectVal) == DSD_IMAGE_MAGIC_NUMBER) { 3424 HighestPriDSD = getHighestPriDSD(Adapter); 3425 if (HighestPriDSD == eFlash2xSectVal) { 3426 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given DSD<%x> already has highest priority", eFlash2xSectVal); 3427 Status = STATUS_SUCCESS; 3428 break; 3429 } 3430 3431 SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1; 3432 if (SectImagePriority == 0) { 3433 /* This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF. 3434 * We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD 3435 * by user 3436 */ 3437 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal); 3438 SectImagePriority = htonl(0x1); 3439 3440 Status = BcmFlash2xBulkWrite(Adapter, 3441 &SectImagePriority, 3442 HighestPriDSD, 3443 Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority), 3444 SIGNATURE_SIZE, 3445 TRUE); 3446 if (Status) { 3447 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); 3448 break; 3449 } 3450 3451 HighestPriDSD = getHighestPriDSD(Adapter); 3452 3453 if (HighestPriDSD == eFlash2xSectVal) { 3454 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Made the DSD: %x highest by reducing priority of other\n", eFlash2xSectVal); 3455 Status = STATUS_SUCCESS; 3456 break; 3457 } 3458 3459 SectImagePriority = htonl(0x2); 3460 Status = BcmFlash2xBulkWrite(Adapter, 3461 &SectImagePriority, 3462 HighestPriDSD, 3463 Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority), 3464 SIGNATURE_SIZE, 3465 TRUE); 3466 if (Status) { 3467 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); 3468 break; 3469 } 3470 3471 HighestPriDSD = getHighestPriDSD(Adapter); 3472 if (HighestPriDSD == eFlash2xSectVal) { 3473 Status = STATUS_SUCCESS; 3474 break; 3475 } 3476 3477 SectImagePriority = 3; 3478 } 3479 SectImagePriority = htonl(SectImagePriority); 3480 Status = BcmFlash2xBulkWrite(Adapter, 3481 &SectImagePriority, 3482 eFlash2xSectVal, 3483 Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority), 3484 SIGNATURE_SIZE, 3485 TRUE); 3486 if (Status) { 3487 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); 3488 Status = STATUS_FAILURE; 3489 break; 3490 } 3491 } else { 3492 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); 3493 Status = STATUS_FAILURE; 3494 break; 3495 } 3496 break; 3497 case VSA0: 3498 case VSA1: 3499 case VSA2: 3500 /* Has to be decided */ 3501 break; 3502 default: 3503 Status = STATUS_FAILURE; 3504 break; 3505 } 3506 3507 Adapter->bHeaderChangeAllowed = false; 3508 return Status; 3509} 3510 3511/* 3512 * BcmCopyISO - Used only for copying the ISO section 3513 * @Adapater :- Bcm Driver Private Data Structure 3514 * @sCopySectStrut :- Section copy structure 3515 * 3516 * Return value:- SUCCESS if copies successfully else negative error code 3517 * 3518 */ 3519 3520int BcmCopyISO(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_copy_section sCopySectStrut) 3521{ 3522 PCHAR Buff = NULL; 3523 enum bcm_flash2x_section_val eISOReadPart = 0, eISOWritePart = 0; 3524 unsigned int uiReadOffsetWithinPart = 0, uiWriteOffsetWithinPart = 0; 3525 unsigned int uiTotalDataToCopy = 0; 3526 bool IsThisHeaderSector = false; 3527 unsigned int sigOffset = 0; 3528 unsigned int ISOLength = 0; 3529 unsigned int Status = STATUS_SUCCESS; 3530 unsigned int SigBuff[MAX_RW_SIZE]; 3531 unsigned int i = 0; 3532 3533 if (ReadISOSignature(Adapter, sCopySectStrut.SrcSection) != ISO_IMAGE_MAGIC_NUMBER) { 3534 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); 3535 return STATUS_FAILURE; 3536 } 3537 3538 Status = BcmFlash2xBulkRead(Adapter, &ISOLength, 3539 sCopySectStrut.SrcSection, 3540 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageSize), 3541 4); 3542 if (Status) { 3543 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO\n"); 3544 return Status; 3545 } 3546 3547 ISOLength = htonl(ISOLength); 3548 if (ISOLength % Adapter->uiSectorSize) 3549 ISOLength = Adapter->uiSectorSize * (1 + ISOLength/Adapter->uiSectorSize); 3550 3551 sigOffset = FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageMagicNumber); 3552 3553 Buff = kzalloc(Adapter->uiSectorSize, GFP_KERNEL); 3554 3555 if (!Buff) { 3556 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for section size"); 3557 return -ENOMEM; 3558 } 3559 3560 if (sCopySectStrut.SrcSection == ISO_IMAGE1 && sCopySectStrut.DstSection == ISO_IMAGE2) { 3561 eISOReadPart = ISO_IMAGE1; 3562 eISOWritePart = ISO_IMAGE2; 3563 uiReadOffsetWithinPart = 0; 3564 uiWriteOffsetWithinPart = 0; 3565 3566 uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - 3567 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) + 3568 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) - 3569 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start) + 3570 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - 3571 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); 3572 3573 if (uiTotalDataToCopy < ISOLength) { 3574 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); 3575 Status = STATUS_FAILURE; 3576 goto out; 3577 } 3578 3579 uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - 3580 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) + 3581 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) - 3582 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start) + 3583 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - 3584 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); 3585 3586 if (uiTotalDataToCopy < ISOLength) { 3587 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size"); 3588 Status = STATUS_FAILURE; 3589 goto out; 3590 } 3591 3592 uiTotalDataToCopy = ISOLength; 3593 3594 CorruptISOSig(Adapter, ISO_IMAGE2); 3595 while (uiTotalDataToCopy) { 3596 if (uiTotalDataToCopy == Adapter->uiSectorSize) { 3597 /* Setting for write of first sector. First sector is assumed to be written in last */ 3598 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector"); 3599 eISOReadPart = ISO_IMAGE1; 3600 uiReadOffsetWithinPart = 0; 3601 eISOWritePart = ISO_IMAGE2; 3602 uiWriteOffsetWithinPart = 0; 3603 IsThisHeaderSector = TRUE; 3604 } else { 3605 uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize; 3606 uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize; 3607 3608 if ((eISOReadPart == ISO_IMAGE1) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) { 3609 eISOReadPart = ISO_IMAGE1_PART2; 3610 uiReadOffsetWithinPart = 0; 3611 } 3612 3613 if ((eISOReadPart == ISO_IMAGE1_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) { 3614 eISOReadPart = ISO_IMAGE1_PART3; 3615 uiReadOffsetWithinPart = 0; 3616 } 3617 3618 if ((eISOWritePart == ISO_IMAGE2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) { 3619 eISOWritePart = ISO_IMAGE2_PART2; 3620 uiWriteOffsetWithinPart = 0; 3621 } 3622 3623 if ((eISOWritePart == ISO_IMAGE2_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) { 3624 eISOWritePart = ISO_IMAGE2_PART3; 3625 uiWriteOffsetWithinPart = 0; 3626 } 3627 } 3628 3629 Status = BcmFlash2xBulkRead(Adapter, 3630 (PUINT)Buff, 3631 eISOReadPart, 3632 uiReadOffsetWithinPart, 3633 Adapter->uiSectorSize); 3634 if (Status) { 3635 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); 3636 break; 3637 } 3638 3639 if (IsThisHeaderSector == TRUE) { 3640 /* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */ 3641 memcpy(SigBuff, Buff + sigOffset, sizeof(SigBuff)); 3642 3643 for (i = 0; i < MAX_RW_SIZE; i++) 3644 *(Buff + sigOffset + i) = 0xFF; 3645 } 3646 Adapter->bHeaderChangeAllowed = TRUE; 3647 Status = BcmFlash2xBulkWrite(Adapter, 3648 (PUINT)Buff, 3649 eISOWritePart, 3650 uiWriteOffsetWithinPart, 3651 Adapter->uiSectorSize, 3652 TRUE); 3653 if (Status) { 3654 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); 3655 break; 3656 } 3657 3658 Adapter->bHeaderChangeAllowed = false; 3659 if (IsThisHeaderSector == TRUE) { 3660 WriteToFlashWithoutSectorErase(Adapter, 3661 SigBuff, 3662 eISOWritePart, 3663 sigOffset, 3664 MAX_RW_SIZE); 3665 IsThisHeaderSector = false; 3666 } 3667 /* subtracting the written Data */ 3668 uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize; 3669 } 3670 } 3671 3672 if (sCopySectStrut.SrcSection == ISO_IMAGE2 && sCopySectStrut.DstSection == ISO_IMAGE1) { 3673 eISOReadPart = ISO_IMAGE2; 3674 eISOWritePart = ISO_IMAGE1; 3675 uiReadOffsetWithinPart = 0; 3676 uiWriteOffsetWithinPart = 0; 3677 3678 uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - 3679 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) + 3680 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) - 3681 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start) + 3682 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - 3683 (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); 3684 3685 if (uiTotalDataToCopy < ISOLength) { 3686 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); 3687 Status = STATUS_FAILURE; 3688 goto out; 3689 } 3690 3691 uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - 3692 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) + 3693 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) - 3694 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start) + 3695 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - 3696 (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); 3697 3698 if (uiTotalDataToCopy < ISOLength) { 3699 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size"); 3700 Status = STATUS_FAILURE; 3701 goto out; 3702 } 3703 3704 uiTotalDataToCopy = ISOLength; 3705 3706 CorruptISOSig(Adapter, ISO_IMAGE1); 3707 3708 while (uiTotalDataToCopy) { 3709 if (uiTotalDataToCopy == Adapter->uiSectorSize) { 3710 /* Setting for write of first sector. First sector is assumed to be written in last */ 3711 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector"); 3712 eISOReadPart = ISO_IMAGE2; 3713 uiReadOffsetWithinPart = 0; 3714 eISOWritePart = ISO_IMAGE1; 3715 uiWriteOffsetWithinPart = 0; 3716 IsThisHeaderSector = TRUE; 3717 } else { 3718 uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize; 3719 uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize; 3720 3721 if ((eISOReadPart == ISO_IMAGE2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) { 3722 eISOReadPart = ISO_IMAGE2_PART2; 3723 uiReadOffsetWithinPart = 0; 3724 } 3725 3726 if ((eISOReadPart == ISO_IMAGE2_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) { 3727 eISOReadPart = ISO_IMAGE2_PART3; 3728 uiReadOffsetWithinPart = 0; 3729 } 3730 3731 if ((eISOWritePart == ISO_IMAGE1) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) { 3732 eISOWritePart = ISO_IMAGE1_PART2; 3733 uiWriteOffsetWithinPart = 0; 3734 } 3735 3736 if ((eISOWritePart == ISO_IMAGE1_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) { 3737 eISOWritePart = ISO_IMAGE1_PART3; 3738 uiWriteOffsetWithinPart = 0; 3739 } 3740 } 3741 3742 Status = BcmFlash2xBulkRead(Adapter, 3743 (PUINT)Buff, 3744 eISOReadPart, 3745 uiReadOffsetWithinPart, 3746 Adapter->uiSectorSize); 3747 if (Status) { 3748 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); 3749 break; 3750 } 3751 3752 if (IsThisHeaderSector == TRUE) { 3753 /* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */ 3754 memcpy(SigBuff, Buff + sigOffset, sizeof(SigBuff)); 3755 3756 for (i = 0; i < MAX_RW_SIZE; i++) 3757 *(Buff + sigOffset + i) = 0xFF; 3758 } 3759 Adapter->bHeaderChangeAllowed = TRUE; 3760 Status = BcmFlash2xBulkWrite(Adapter, 3761 (PUINT)Buff, 3762 eISOWritePart, 3763 uiWriteOffsetWithinPart, 3764 Adapter->uiSectorSize, 3765 TRUE); 3766 if (Status) { 3767 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); 3768 break; 3769 } 3770 3771 Adapter->bHeaderChangeAllowed = false; 3772 if (IsThisHeaderSector == TRUE) { 3773 WriteToFlashWithoutSectorErase(Adapter, 3774 SigBuff, 3775 eISOWritePart, 3776 sigOffset, 3777 MAX_RW_SIZE); 3778 3779 IsThisHeaderSector = false; 3780 } 3781 3782 /* subtracting the written Data */ 3783 uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize; 3784 } 3785 } 3786out: 3787 kfree(Buff); 3788 3789 return Status; 3790} 3791 3792/* 3793 * BcmFlash2xCorruptSig : this API is used to corrupt the written sig in Bcm Header present in flash section. 3794 * It will corrupt the sig, if Section is writable, by making first bytes as zero. 3795 * @Adapater :- Bcm Driver Private Data Structure 3796 * @eFlash2xSectionVal :- Flash section val which has header 3797 * 3798 * Return Value :- 3799 * Success :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS 3800 * Failure :-Return negative error code 3801 */ 3802 3803int BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal) 3804{ 3805 int Status = STATUS_SUCCESS; 3806 3807 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Value :%x\n", eFlash2xSectionVal); 3808 3809 if ((eFlash2xSectionVal == DSD0) || (eFlash2xSectionVal == DSD1) || (eFlash2xSectionVal == DSD2)) { 3810 Status = CorruptDSDSig(Adapter, eFlash2xSectionVal); 3811 } else if (eFlash2xSectionVal == ISO_IMAGE1 || eFlash2xSectionVal == ISO_IMAGE2) { 3812 Status = CorruptISOSig(Adapter, eFlash2xSectionVal); 3813 } else { 3814 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given Section <%d>does not have Header", eFlash2xSectionVal); 3815 return STATUS_SUCCESS; 3816 } 3817 return Status; 3818} 3819 3820/* 3821 *BcmFlash2xWriteSig :-this API is used to Write the sig if requested Section has 3822 * header and Write Permission. 3823 * @Adapater :- Bcm Driver Private Data Structure 3824 * @eFlashSectionVal :- Flash section val which has header 3825 * 3826 * Return Value :- 3827 * Success :- If Section is present and writable write the sig and return STATUS_SUCCESS 3828 * Failure :-Return negative error code 3829 */ 3830 3831int BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlashSectionVal) 3832{ 3833 unsigned int uiSignature = 0; 3834 unsigned int uiOffset = 0; 3835 3836 /* struct bcm_dsd_header dsdHeader = {0}; */ 3837 if (Adapter->bSigCorrupted == false) { 3838 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is not corrupted by driver, hence not restoring\n"); 3839 return STATUS_SUCCESS; 3840 } 3841 3842 if (Adapter->bAllDSDWriteAllow == false) { 3843 if (IsSectionWritable(Adapter, eFlashSectionVal) == false) { 3844 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Write signature"); 3845 return SECTOR_IS_NOT_WRITABLE; 3846 } 3847 } 3848 3849 if ((eFlashSectionVal == DSD0) || (eFlashSectionVal == DSD1) || (eFlashSectionVal == DSD2)) { 3850 uiSignature = htonl(DSD_IMAGE_MAGIC_NUMBER); 3851 uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader; 3852 3853 uiOffset += FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber); 3854 3855 if ((ReadDSDSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) { 3856 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Corrupted Pattern is not there. Hence won't write sig"); 3857 return STATUS_FAILURE; 3858 } 3859 } else if ((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) { 3860 uiSignature = htonl(ISO_IMAGE_MAGIC_NUMBER); 3861 /* uiOffset = 0; */ 3862 uiOffset = FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageMagicNumber); 3863 if ((ReadISOSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) { 3864 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Currupted Pattern is not there. Hence won't write sig"); 3865 return STATUS_FAILURE; 3866 } 3867 } else { 3868 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GIVEN SECTION< %d > IS NOT VALID FOR SIG WRITE...", eFlashSectionVal); 3869 return STATUS_FAILURE; 3870 } 3871 3872 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature"); 3873 3874 Adapter->bHeaderChangeAllowed = TRUE; 3875 Adapter->bSigCorrupted = false; 3876 BcmFlash2xBulkWrite(Adapter, &uiSignature, eFlashSectionVal, uiOffset, SIGNATURE_SIZE, TRUE); 3877 Adapter->bHeaderChangeAllowed = false; 3878 3879 return STATUS_SUCCESS; 3880} 3881 3882/* 3883 * validateFlash2xReadWrite :- This API is used to validate the user request for Read/Write. 3884 * if requested Bytes goes beyond the Requested section, it reports error. 3885 * @Adapater :- Bcm Driver Private Data Structure 3886 * @psFlash2xReadWrite :-Flash2x Read/write structure pointer 3887 * 3888 * Return values:-Return TRUE is request is valid else false. 3889 */ 3890 3891int validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, struct bcm_flash2x_readwrite *psFlash2xReadWrite) 3892{ 3893 unsigned int uiNumOfBytes = 0; 3894 unsigned int uiSectStartOffset = 0; 3895 unsigned int uiSectEndOffset = 0; 3896 3897 uiNumOfBytes = psFlash2xReadWrite->numOfBytes; 3898 3899 if (IsSectionExistInFlash(Adapter, psFlash2xReadWrite->Section) != TRUE) { 3900 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%x> does not exist in Flash", psFlash2xReadWrite->Section); 3901 return false; 3902 } 3903 uiSectStartOffset = BcmGetSectionValStartOffset(Adapter, psFlash2xReadWrite->Section); 3904 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Start offset :%x ,section :%d\n", uiSectStartOffset, psFlash2xReadWrite->Section); 3905 if ((psFlash2xReadWrite->Section == ISO_IMAGE1) || (psFlash2xReadWrite->Section == ISO_IMAGE2)) { 3906 if (psFlash2xReadWrite->Section == ISO_IMAGE1) { 3907 uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1) - 3908 BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) + 3909 BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART2) - 3910 BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART2) + 3911 BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART3) - 3912 BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1_PART3); 3913 } else if (psFlash2xReadWrite->Section == ISO_IMAGE2) { 3914 uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2) - 3915 BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2) + 3916 BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART2) - 3917 BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART2) + 3918 BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART3) - 3919 BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART3); 3920 } 3921 3922 /* since this uiSectEndoffset is the size of iso Image. hence for calculating the virtual endoffset 3923 * it should be added in startoffset. so that check done in last of this function can be valued. 3924 */ 3925 uiSectEndOffset = uiSectStartOffset + uiSectEndOffset; 3926 3927 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Total size of the ISO Image :%x", uiSectEndOffset); 3928 } else 3929 uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, psFlash2xReadWrite->Section); 3930 3931 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "End offset :%x\n", uiSectEndOffset); 3932 3933 /* psFlash2xReadWrite->offset and uiNumOfBytes are user controlled and can lead to integer overflows */ 3934 if (psFlash2xReadWrite->offset > uiSectEndOffset) { 3935 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request...."); 3936 return false; 3937 } 3938 if (uiNumOfBytes > uiSectEndOffset) { 3939 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request...."); 3940 return false; 3941 } 3942 /* Checking the boundary condition */ 3943 if ((uiSectStartOffset + psFlash2xReadWrite->offset + uiNumOfBytes) <= uiSectEndOffset) 3944 return TRUE; 3945 else { 3946 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request...."); 3947 return false; 3948 } 3949} 3950 3951/* 3952 * IsFlash2x :- check for Flash 2.x 3953 * Adapater :- Bcm Driver Private Data Structure 3954 * 3955 * Return value:- 3956 * return TRUE if flah2.x of hgher version else return false. 3957 */ 3958 3959int IsFlash2x(struct bcm_mini_adapter *Adapter) 3960{ 3961 if (Adapter->uiFlashLayoutMajorVersion >= FLASH_2X_MAJOR_NUMBER) 3962 return TRUE; 3963 else 3964 return false; 3965} 3966 3967/* 3968 * GetFlashBaseAddr :- Calculate the Flash Base address 3969 * @Adapater :- Bcm Driver Private Data Structure 3970 * 3971 * Return Value:- 3972 * Success :- Base Address of the Flash 3973 */ 3974 3975static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter) 3976{ 3977 unsigned int uiBaseAddr = 0; 3978 3979 if (Adapter->bDDRInitDone) { 3980 /* 3981 * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr 3982 * In case of Raw Read... use the default value 3983 */ 3984 if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == false) && 3985 !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) 3986 uiBaseAddr = Adapter->uiFlashBaseAdd; 3987 else 3988 uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT; 3989 } else { 3990 /* 3991 * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr 3992 * In case of Raw Read... use the default value 3993 */ 3994 if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == false) && 3995 !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) 3996 uiBaseAddr = Adapter->uiFlashBaseAdd | FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; 3997 else 3998 uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; 3999 } 4000 4001 return uiBaseAddr; 4002} 4003 4004/* 4005 * BcmCopySection :- This API is used to copy the One section in another. Both section should 4006 * be contiuous and of same size. Hence this Will not be applicabe to copy ISO. 4007 * 4008 * @Adapater :- Bcm Driver Private Data Structure 4009 * @SrcSection :- Source section From where data has to be copied 4010 * @DstSection :- Destination section to which data has to be copied 4011 * @offset :- Offset from/to where data has to be copied from one section to another. 4012 * @numOfBytes :- number of byes that has to be copyed from one section to another at given offset. 4013 * in case of numofBytes equal zero complete section will be copied. 4014 * Return Values- 4015 * Success : Return STATUS_SUCCESS 4016 * Faillure :- return negative error code 4017 */ 4018 4019int BcmCopySection(struct bcm_mini_adapter *Adapter, 4020 enum bcm_flash2x_section_val SrcSection, 4021 enum bcm_flash2x_section_val DstSection, 4022 unsigned int offset, 4023 unsigned int numOfBytes) 4024{ 4025 unsigned int BuffSize = 0; 4026 unsigned int BytesToBeCopied = 0; 4027 PUCHAR pBuff = NULL; 4028 int Status = STATUS_SUCCESS; 4029 4030 if (SrcSection == DstSection) { 4031 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source and Destination should be different ...try again"); 4032 return -EINVAL; 4033 } 4034 4035 if ((SrcSection != DSD0) && (SrcSection != DSD1) && (SrcSection != DSD2)) { 4036 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source should be DSD subsection"); 4037 return -EINVAL; 4038 } 4039 4040 if ((DstSection != DSD0) && (DstSection != DSD1) && (DstSection != DSD2)) { 4041 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destination should be DSD subsection"); 4042 return -EINVAL; 4043 } 4044 4045 /* if offset zero means have to copy complete secton */ 4046 if (numOfBytes == 0) { 4047 numOfBytes = BcmGetSectionValEndOffset(Adapter, SrcSection) 4048 - BcmGetSectionValStartOffset(Adapter, SrcSection); 4049 4050 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Section Size :0x%x", numOfBytes); 4051 } 4052 4053 if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, SrcSection) 4054 - BcmGetSectionValStartOffset(Adapter, SrcSection)) { 4055 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " Input parameters going beyond the section offS: %x numB: %x of Source Section\n", 4056 offset, numOfBytes); 4057 return -EINVAL; 4058 } 4059 4060 if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, DstSection) 4061 - BcmGetSectionValStartOffset(Adapter, DstSection)) { 4062 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Input parameters going beyond the section offS: %x numB: %x of Destination Section\n", 4063 offset, numOfBytes); 4064 return -EINVAL; 4065 } 4066 4067 if (numOfBytes > Adapter->uiSectorSize) 4068 BuffSize = Adapter->uiSectorSize; 4069 else 4070 BuffSize = numOfBytes; 4071 4072 pBuff = kzalloc(BuffSize, GFP_KERNEL); 4073 if (!pBuff) { 4074 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed.. "); 4075 return -ENOMEM; 4076 } 4077 4078 BytesToBeCopied = Adapter->uiSectorSize; 4079 if (offset % Adapter->uiSectorSize) 4080 BytesToBeCopied = Adapter->uiSectorSize - (offset % Adapter->uiSectorSize); 4081 if (BytesToBeCopied > numOfBytes) 4082 BytesToBeCopied = numOfBytes; 4083 4084 Adapter->bHeaderChangeAllowed = TRUE; 4085 4086 do { 4087 Status = BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, SrcSection , offset, BytesToBeCopied); 4088 if (Status) { 4089 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed at offset :%d for NOB :%d", SrcSection, BytesToBeCopied); 4090 break; 4091 } 4092 Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pBuff, DstSection, offset, BytesToBeCopied, false); 4093 if (Status) { 4094 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed at offset :%d for NOB :%d", DstSection, BytesToBeCopied); 4095 break; 4096 } 4097 offset = offset + BytesToBeCopied; 4098 numOfBytes = numOfBytes - BytesToBeCopied; 4099 if (numOfBytes) { 4100 if (numOfBytes > Adapter->uiSectorSize) 4101 BytesToBeCopied = Adapter->uiSectorSize; 4102 else 4103 BytesToBeCopied = numOfBytes; 4104 } 4105 } while (numOfBytes > 0); 4106 4107 kfree(pBuff); 4108 Adapter->bHeaderChangeAllowed = false; 4109 4110 return Status; 4111} 4112 4113/* 4114 * SaveHeaderIfPresent :- This API is use to Protect the Header in case of Header Sector write 4115 * @Adapater :- Bcm Driver Private Data Structure 4116 * @pBuff :- Data buffer that has to be written in sector having the header map. 4117 * @uiOffset :- Flash offset that has to be written. 4118 * 4119 * Return value :- 4120 * Success :- On success return STATUS_SUCCESS 4121 * Faillure :- Return negative error code 4122 */ 4123 4124static int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned int uiOffset) 4125{ 4126 unsigned int offsetToProtect = 0, HeaderSizeToProtect = 0; 4127 bool bHasHeader = false; 4128 PUCHAR pTempBuff = NULL; 4129 unsigned int uiSectAlignAddr = 0; 4130 unsigned int sig = 0; 4131 4132 /* making the offset sector aligned */ 4133 uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); 4134 4135 if ((uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD2) - Adapter->uiSectorSize) || 4136 (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD1) - Adapter->uiSectorSize) || 4137 (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD0) - Adapter->uiSectorSize)) { 4138 /* offset from the sector boundary having the header map */ 4139 offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize; 4140 HeaderSizeToProtect = sizeof(struct bcm_dsd_header); 4141 bHasHeader = TRUE; 4142 } 4143 4144 if (uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) || 4145 uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2)) { 4146 offsetToProtect = 0; 4147 HeaderSizeToProtect = sizeof(struct bcm_iso_header); 4148 bHasHeader = TRUE; 4149 } 4150 /* If Header is present overwrite passed buffer with this */ 4151 if (bHasHeader && (Adapter->bHeaderChangeAllowed == false)) { 4152 pTempBuff = kzalloc(HeaderSizeToProtect, GFP_KERNEL); 4153 if (!pTempBuff) { 4154 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed"); 4155 return -ENOMEM; 4156 } 4157 /* Read header */ 4158 BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, (uiSectAlignAddr + offsetToProtect), HeaderSizeToProtect); 4159 BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pTempBuff, HeaderSizeToProtect); 4160 /* Replace Buffer content with Header */ 4161 memcpy(pBuff + offsetToProtect, pTempBuff, HeaderSizeToProtect); 4162 4163 kfree(pTempBuff); 4164 } 4165 if (bHasHeader && Adapter->bSigCorrupted) { 4166 sig = *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber))); 4167 sig = ntohl(sig); 4168 if ((sig & 0xFF000000) != CORRUPTED_PATTERN) { 4169 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Desired pattern is not at sig offset. Hence won't restore"); 4170 Adapter->bSigCorrupted = false; 4171 return STATUS_SUCCESS; 4172 } 4173 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Corrupted sig is :%X", sig); 4174 *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber))) = htonl(DSD_IMAGE_MAGIC_NUMBER); 4175 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature in Header Write only"); 4176 Adapter->bSigCorrupted = false; 4177 } 4178 4179 return STATUS_SUCCESS; 4180} 4181 4182/* 4183 * BcmDoChipSelect : This will selcet the appropriate chip for writing. 4184 * @Adapater :- Bcm Driver Private Data Structure 4185 * 4186 * OutPut:- 4187 * Select the Appropriate chip and retrn status Success 4188 */ 4189static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter, unsigned int offset) 4190{ 4191 unsigned int FlashConfig = 0; 4192 int ChipNum = 0; 4193 unsigned int GPIOConfig = 0; 4194 unsigned int PartNum = 0; 4195 4196 ChipNum = offset / FLASH_PART_SIZE; 4197 4198 /* 4199 * Chip Select mapping to enable flash0. 4200 * To select flash 0, we have to OR with (0<<12). 4201 * ORing 0 will have no impact so not doing that part. 4202 * In future if Chip select value changes from 0 to non zero, 4203 * That needs be taken care with backward comaptibility. No worries for now. 4204 */ 4205 4206 /* 4207 * SelectedChip Variable is the selection that the host is 100% Sure the same as what the register will hold. This can be ONLY ensured 4208 * if the Chip doesn't goes to low power mode while the flash operation is in progress (NVMRdmWrmLock is taken) 4209 * Before every new Flash Write operation, we reset the variable. This is to ensure that after any wake-up from 4210 * power down modes (Idle mode/shutdown mode), the values in the register will be different. 4211 */ 4212 4213 if (Adapter->SelectedChip == ChipNum) 4214 return STATUS_SUCCESS; 4215 4216 /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Selected Chip :%x", ChipNum); */ 4217 Adapter->SelectedChip = ChipNum; 4218 4219 /* bit[13..12] will select the appropriate chip */ 4220 rdmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4); 4221 rdmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); 4222 { 4223 switch (ChipNum) { 4224 case 0: 4225 PartNum = 0; 4226 break; 4227 case 1: 4228 PartNum = 3; 4229 GPIOConfig |= (0x4 << CHIP_SELECT_BIT12); 4230 break; 4231 case 2: 4232 PartNum = 1; 4233 GPIOConfig |= (0x1 << CHIP_SELECT_BIT12); 4234 break; 4235 case 3: 4236 PartNum = 2; 4237 GPIOConfig |= (0x2 << CHIP_SELECT_BIT12); 4238 break; 4239 } 4240 } 4241 /* In case the bits already written in the FLASH_CONFIG_REG is same as what the user desired, 4242 * nothing to do... can return immediately. 4243 * ASSUMPTION: FLASH_GPIO_CONFIG_REG will be in sync with FLASH_CONFIG_REG. 4244 * Even if the chip goes to low power mode, it should wake with values in each register in sync with each other. 4245 * These values are not written by host other than during CHIP_SELECT. 4246 */ 4247 if (PartNum == ((FlashConfig >> CHIP_SELECT_BIT12) & 0x3)) 4248 return STATUS_SUCCESS; 4249 4250 /* clearing the bit[13..12] */ 4251 FlashConfig &= 0xFFFFCFFF; 4252 FlashConfig = (FlashConfig | (PartNum<<CHIP_SELECT_BIT12)); /* 00 */ 4253 4254 wrmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); 4255 udelay(100); 4256 4257 wrmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4); 4258 udelay(100); 4259 4260 return STATUS_SUCCESS; 4261} 4262 4263static int ReadDSDSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd) 4264{ 4265 unsigned int uiDSDsig = 0; 4266 /* unsigned int sigoffsetInMap = 0; 4267 * struct bcm_dsd_header dsdHeader = {0}; 4268 */ 4269 4270 /* sigoffsetInMap =(PUCHAR)&(dsdHeader.DSDImageMagicNumber) -(PUCHAR)&dsdHeader; */ 4271 4272 if (dsd != DSD0 && dsd != DSD1 && dsd != DSD2) { 4273 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for DSDs"); 4274 return STATUS_FAILURE; 4275 } 4276 BcmFlash2xBulkRead(Adapter, 4277 &uiDSDsig, 4278 dsd, 4279 Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImageMagicNumber), 4280 SIGNATURE_SIZE); 4281 4282 uiDSDsig = ntohl(uiDSDsig); 4283 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD SIG :%x", uiDSDsig); 4284 4285 return uiDSDsig; 4286} 4287 4288static int ReadDSDPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val dsd) 4289{ 4290 /* unsigned int priOffsetInMap = 0 ; */ 4291 unsigned int uiDSDPri = STATUS_FAILURE; 4292 /* struct bcm_dsd_header dsdHeader = {0}; 4293 * priOffsetInMap = (PUCHAR)&(dsdHeader.DSDImagePriority) -(PUCHAR)&dsdHeader; 4294 */ 4295 if (IsSectionWritable(Adapter, dsd)) { 4296 if (ReadDSDSignature(Adapter, dsd) == DSD_IMAGE_MAGIC_NUMBER) { 4297 BcmFlash2xBulkRead(Adapter, 4298 &uiDSDPri, 4299 dsd, 4300 Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(struct bcm_dsd_header *, DSDImagePriority), 4301 4); 4302 4303 uiDSDPri = ntohl(uiDSDPri); 4304 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD<%x> Priority :%x", dsd, uiDSDPri); 4305 } 4306 } 4307 4308 return uiDSDPri; 4309} 4310 4311static enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter) 4312{ 4313 int DSDHighestPri = STATUS_FAILURE; 4314 int DsdPri = 0; 4315 enum bcm_flash2x_section_val HighestPriDSD = 0; 4316 4317 if (IsSectionWritable(Adapter, DSD2)) { 4318 DSDHighestPri = ReadDSDPriority(Adapter, DSD2); 4319 HighestPriDSD = DSD2; 4320 } 4321 4322 if (IsSectionWritable(Adapter, DSD1)) { 4323 DsdPri = ReadDSDPriority(Adapter, DSD1); 4324 if (DSDHighestPri < DsdPri) { 4325 DSDHighestPri = DsdPri; 4326 HighestPriDSD = DSD1; 4327 } 4328 } 4329 4330 if (IsSectionWritable(Adapter, DSD0)) { 4331 DsdPri = ReadDSDPriority(Adapter, DSD0); 4332 if (DSDHighestPri < DsdPri) { 4333 DSDHighestPri = DsdPri; 4334 HighestPriDSD = DSD0; 4335 } 4336 } 4337 if (HighestPriDSD) 4338 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest DSD :%x , and its Pri :%x", HighestPriDSD, DSDHighestPri); 4339 4340 return HighestPriDSD; 4341} 4342 4343static int ReadISOSignature(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso) 4344{ 4345 unsigned int uiISOsig = 0; 4346 /* unsigned int sigoffsetInMap = 0; 4347 * struct bcm_iso_header ISOHeader = {0}; 4348 * sigoffsetInMap =(PUCHAR)&(ISOHeader.ISOImageMagicNumber) -(PUCHAR)&ISOHeader; 4349 */ 4350 if (iso != ISO_IMAGE1 && iso != ISO_IMAGE2) { 4351 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for ISOs"); 4352 return STATUS_FAILURE; 4353 } 4354 BcmFlash2xBulkRead(Adapter, 4355 &uiISOsig, 4356 iso, 4357 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImageMagicNumber), 4358 SIGNATURE_SIZE); 4359 4360 uiISOsig = ntohl(uiISOsig); 4361 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO SIG :%x", uiISOsig); 4362 4363 return uiISOsig; 4364} 4365 4366static int ReadISOPriority(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val iso) 4367{ 4368 unsigned int ISOPri = STATUS_FAILURE; 4369 4370 if (IsSectionWritable(Adapter, iso)) { 4371 if (ReadISOSignature(Adapter, iso) == ISO_IMAGE_MAGIC_NUMBER) { 4372 BcmFlash2xBulkRead(Adapter, 4373 &ISOPri, 4374 iso, 4375 0 + FIELD_OFFSET_IN_HEADER(struct bcm_iso_header *, ISOImagePriority), 4376 4); 4377 4378 ISOPri = ntohl(ISOPri); 4379 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO<%x> Priority :%x", iso, ISOPri); 4380 } 4381 } 4382 4383 return ISOPri; 4384} 4385 4386static enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter) 4387{ 4388 int ISOHighestPri = STATUS_FAILURE; 4389 int ISOPri = 0; 4390 enum bcm_flash2x_section_val HighestPriISO = NO_SECTION_VAL; 4391 4392 if (IsSectionWritable(Adapter, ISO_IMAGE2)) { 4393 ISOHighestPri = ReadISOPriority(Adapter, ISO_IMAGE2); 4394 HighestPriISO = ISO_IMAGE2; 4395 } 4396 4397 if (IsSectionWritable(Adapter, ISO_IMAGE1)) { 4398 ISOPri = ReadISOPriority(Adapter, ISO_IMAGE1); 4399 if (ISOHighestPri < ISOPri) { 4400 ISOHighestPri = ISOPri; 4401 HighestPriISO = ISO_IMAGE1; 4402 } 4403 } 4404 if (HighestPriISO) 4405 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest ISO :%x and its Pri :%x", HighestPriISO, ISOHighestPri); 4406 4407 return HighestPriISO; 4408} 4409 4410static int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter, 4411 PUINT pBuff, 4412 enum bcm_flash2x_section_val eFlash2xSectionVal, 4413 unsigned int uiOffset, 4414 unsigned int uiNumBytes) 4415{ 4416 #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) 4417 unsigned int uiTemp = 0, value = 0; 4418 unsigned int i = 0; 4419 unsigned int uiPartOffset = 0; 4420 #endif 4421 unsigned int uiStartOffset = 0; 4422 /* Adding section start address */ 4423 int Status = STATUS_SUCCESS; 4424 PUCHAR pcBuff = (PUCHAR)pBuff; 4425 4426 if (uiNumBytes % Adapter->ulFlashWriteSize) { 4427 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Writing without Sector Erase for non-FlashWriteSize number of bytes 0x%x\n", uiNumBytes); 4428 return STATUS_FAILURE; 4429 } 4430 4431 uiStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal); 4432 4433 if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal)) 4434 return vendorextnWriteSectionWithoutErase(Adapter, pcBuff, eFlash2xSectionVal, uiOffset, uiNumBytes); 4435 4436 uiOffset = uiOffset + uiStartOffset; 4437 4438 #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) 4439 Status = bcmflash_raw_writenoerase((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), pcBuff, uiNumBytes); 4440 #else 4441 rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 4442 value = 0; 4443 wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); 4444 4445 Adapter->SelectedChip = RESET_CHIP_SELECT; 4446 BcmDoChipSelect(Adapter, uiOffset); 4447 uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); 4448 4449 for (i = 0; i < uiNumBytes; i += Adapter->ulFlashWriteSize) { 4450 if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) 4451 Status = flashByteWrite(Adapter, uiPartOffset, pcBuff); 4452 else 4453 Status = flashWrite(Adapter, uiPartOffset, pcBuff); 4454 4455 if (Status != STATUS_SUCCESS) 4456 break; 4457 4458 pcBuff = pcBuff + Adapter->ulFlashWriteSize; 4459 uiPartOffset = uiPartOffset + Adapter->ulFlashWriteSize; 4460 } 4461 wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); 4462 Adapter->SelectedChip = RESET_CHIP_SELECT; 4463 #endif 4464 4465 return Status; 4466} 4467 4468bool IsSectionExistInFlash(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val section) 4469{ 4470 bool SectionPresent = false; 4471 4472 switch (section) { 4473 case ISO_IMAGE1: 4474 if ((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && 4475 (IsNonCDLessDevice(Adapter) == false)) 4476 SectionPresent = TRUE; 4477 break; 4478 case ISO_IMAGE2: 4479 if ((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && 4480 (IsNonCDLessDevice(Adapter) == false)) 4481 SectionPresent = TRUE; 4482 break; 4483 case DSD0: 4484 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) 4485 SectionPresent = TRUE; 4486 break; 4487 case DSD1: 4488 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) 4489 SectionPresent = TRUE; 4490 break; 4491 case DSD2: 4492 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) 4493 SectionPresent = TRUE; 4494 break; 4495 case VSA0: 4496 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) 4497 SectionPresent = TRUE; 4498 break; 4499 case VSA1: 4500 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) 4501 SectionPresent = TRUE; 4502 break; 4503 case VSA2: 4504 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) 4505 SectionPresent = TRUE; 4506 break; 4507 case SCSI: 4508 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) 4509 SectionPresent = TRUE; 4510 break; 4511 case CONTROL_SECTION: 4512 if (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) 4513 SectionPresent = TRUE; 4514 break; 4515 default: 4516 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x"); 4517 SectionPresent = false; 4518 } 4519 4520 return SectionPresent; 4521} 4522 4523static int IsSectionWritable(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val Section) 4524{ 4525 int offset = STATUS_FAILURE; 4526 int Status = false; 4527 4528 if (IsSectionExistInFlash(Adapter, Section) == false) { 4529 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section <%d> does not exist", Section); 4530 return false; 4531 } 4532 4533 offset = BcmGetSectionValStartOffset(Adapter, Section); 4534 if (offset == INVALID_OFFSET) { 4535 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%d> does not exist", Section); 4536 return false; 4537 } 4538 4539 if (IsSectionExistInVendorInfo(Adapter, Section)) 4540 return !(Adapter->psFlash2xVendorInfo->VendorSection[Section].AccessFlags & FLASH2X_SECTION_RO); 4541 4542 Status = IsOffsetWritable(Adapter, offset); 4543 return Status; 4544} 4545 4546static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal) 4547{ 4548 PUCHAR pBuff = NULL; 4549 unsigned int sig = 0; 4550 unsigned int uiOffset = 0; 4551 unsigned int BlockStatus = 0; 4552 unsigned int uiSectAlignAddr = 0; 4553 4554 Adapter->bSigCorrupted = false; 4555 if (Adapter->bAllDSDWriteAllow == false) { 4556 if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) { 4557 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature"); 4558 return SECTOR_IS_NOT_WRITABLE; 4559 } 4560 } 4561 4562 pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL); 4563 if (!pBuff) { 4564 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey"); 4565 return -ENOMEM; 4566 } 4567 4568 uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(struct bcm_dsd_header); 4569 uiOffset -= MAX_RW_SIZE; 4570 4571 BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE); 4572 4573 sig = *((PUINT)(pBuff + 12)); 4574 sig = ntohl(sig); 4575 BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE); 4576 /* Now corrupting the sig by corrupting 4th last Byte. */ 4577 *(pBuff + 12) = 0; 4578 4579 if (sig == DSD_IMAGE_MAGIC_NUMBER) { 4580 Adapter->bSigCorrupted = TRUE; 4581 if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) { 4582 uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); 4583 BlockStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize); 4584 4585 WriteToFlashWithoutSectorErase(Adapter, (PUINT)(pBuff + 12), eFlash2xSectionVal, 4586 (uiOffset + 12), BYTE_WRITE_SUPPORT); 4587 if (BlockStatus) { 4588 BcmRestoreBlockProtectStatus(Adapter, BlockStatus); 4589 BlockStatus = 0; 4590 } 4591 } else { 4592 WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal, 4593 uiOffset, MAX_RW_SIZE); 4594 } 4595 } else { 4596 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header"); 4597 kfree(pBuff); 4598 4599 return STATUS_FAILURE; 4600 } 4601 4602 kfree(pBuff); 4603 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature"); 4604 4605 return STATUS_SUCCESS; 4606} 4607 4608static int CorruptISOSig(struct bcm_mini_adapter *Adapter, enum bcm_flash2x_section_val eFlash2xSectionVal) 4609{ 4610 PUCHAR pBuff = NULL; 4611 unsigned int sig = 0; 4612 unsigned int uiOffset = 0; 4613 4614 Adapter->bSigCorrupted = false; 4615 4616 if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) { 4617 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature"); 4618 return SECTOR_IS_NOT_WRITABLE; 4619 } 4620 4621 pBuff = kzalloc(MAX_RW_SIZE, GFP_KERNEL); 4622 if (!pBuff) { 4623 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey"); 4624 return -ENOMEM; 4625 } 4626 4627 uiOffset = 0; 4628 4629 BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE); 4630 4631 sig = *((PUINT)pBuff); 4632 sig = ntohl(sig); 4633 4634 /* corrupt signature */ 4635 *pBuff = 0; 4636 4637 if (sig == ISO_IMAGE_MAGIC_NUMBER) { 4638 Adapter->bSigCorrupted = TRUE; 4639 WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal, 4640 uiOffset, Adapter->ulFlashWriteSize); 4641 } else { 4642 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header"); 4643 kfree(pBuff); 4644 4645 return STATUS_FAILURE; 4646 } 4647 4648 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature"); 4649 BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE); 4650 4651 kfree(pBuff); 4652 return STATUS_SUCCESS; 4653} 4654 4655bool IsNonCDLessDevice(struct bcm_mini_adapter *Adapter) 4656{ 4657 if (Adapter->psFlash2xCSInfo->IsCDLessDeviceBootSig == NON_CDLESS_DEVICE_BOOT_SIG) 4658 return TRUE; 4659 else 4660 return false; 4661} 4662