1 #include "headers.h"
2
3 #define DWORD unsigned int
4
5 static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter,
6 unsigned int offset);
7 static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter);
8 static int BcmGetActiveISO(struct bcm_mini_adapter *Adapter);
9 static unsigned int BcmGetEEPROMSize(struct bcm_mini_adapter *Adapter);
10 static int BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter);
11 static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter,
12 unsigned int FlashSectorSizeSig,
13 unsigned int FlashSectorSize);
14
15 static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter);
16 static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter);
17 static unsigned int BcmGetFlashSize(struct bcm_mini_adapter *Adapter);
18 static enum bcm_nvm_type BcmGetNvmType(struct bcm_mini_adapter *Adapter);
19
20 static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter,
21 enum bcm_flash2x_section_val eFlash2xSectionVal);
22
23 static B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter,
24 unsigned int uiOffset);
25 static int IsSectionWritable(struct bcm_mini_adapter *Adapter,
26 enum bcm_flash2x_section_val Section);
27 static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter,
28 enum bcm_flash2x_section_val section);
29
30 static int ReadDSDPriority(struct bcm_mini_adapter *Adapter,
31 enum bcm_flash2x_section_val dsd);
32 static int ReadDSDSignature(struct bcm_mini_adapter *Adapter,
33 enum bcm_flash2x_section_val dsd);
34 static int ReadISOPriority(struct bcm_mini_adapter *Adapter,
35 enum bcm_flash2x_section_val iso);
36 static int ReadISOSignature(struct bcm_mini_adapter *Adapter,
37 enum bcm_flash2x_section_val iso);
38
39 static int CorruptDSDSig(struct bcm_mini_adapter *Adapter,
40 enum bcm_flash2x_section_val eFlash2xSectionVal);
41 static int CorruptISOSig(struct bcm_mini_adapter *Adapter,
42 enum bcm_flash2x_section_val eFlash2xSectionVal);
43 static int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter,
44 PUCHAR pBuff,
45 unsigned int uiSectAlignAddr);
46 static 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);
51 static enum bcm_flash2x_section_val getHighestPriDSD(struct bcm_mini_adapter *Adapter);
52 static enum bcm_flash2x_section_val getHighestPriISO(struct bcm_mini_adapter *Adapter);
53
54 static int BeceemFlashBulkRead(
55 struct bcm_mini_adapter *Adapter,
56 PUINT pBuffer,
57 unsigned int uiOffset,
58 unsigned int uiNumBytes);
59
60 static int BeceemFlashBulkWrite(
61 struct bcm_mini_adapter *Adapter,
62 PUINT pBuffer,
63 unsigned int uiOffset,
64 unsigned int uiNumBytes,
65 bool bVerify);
66
67 static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter);
68
69 static 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 */
ReadEEPROMStatusRegister(struct bcm_mini_adapter * Adapter)80 static 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
ReadBeceemEEPROMBulk(struct bcm_mini_adapter * Adapter,DWORD dwAddress,DWORD * pdwData,DWORD dwNumWords)142 static 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
ReadBeceemEEPROM(struct bcm_mini_adapter * Adapter,DWORD uiOffset,DWORD * pBuffer)261 int 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
ReadMacAddressFromNVM(struct bcm_mini_adapter * Adapter)287 int 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
BeceemEEPROMBulkRead(struct bcm_mini_adapter * Adapter,PUINT pBuffer,unsigned int uiOffset,unsigned int uiNumBytes)319 int 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
BeceemFlashBulkRead(struct bcm_mini_adapter * Adapter,PUINT pBuffer,unsigned int uiOffset,unsigned int uiNumBytes)412 static 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
BcmGetFlashSize(struct bcm_mini_adapter * Adapter)490 static 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
BcmGetEEPROMSize(struct bcm_mini_adapter * Adapter)511 static 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
FlashSectorErase(struct bcm_mini_adapter * Adapter,unsigned int addr,unsigned int numOfSectors)563 static 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
flashByteWrite(struct bcm_mini_adapter * Adapter,unsigned int uiOffset,PVOID pData)624 static 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
flashWrite(struct bcm_mini_adapter * Adapter,unsigned int uiOffset,PVOID pData)701 static 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 */
flashByteWriteStatus(struct bcm_mini_adapter * Adapter,unsigned int uiOffset,PVOID pData)779 static 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
flashWriteStatus(struct bcm_mini_adapter * Adapter,unsigned int uiOffset,PVOID pData)857 static 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
BcmRestoreBlockProtectStatus(struct bcm_mini_adapter * Adapter,ULONG ulWriteStatus)932 static 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
BcmFlashUnProtectBlock(struct bcm_mini_adapter * Adapter,unsigned int uiOffset,unsigned int uiLength)958 static 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
bulk_read_complete_sector(struct bcm_mini_adapter * ad,UCHAR read_bk[],PCHAR tmpbuff,unsigned int offset,unsigned int partoff)1036 static 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
BeceemFlashBulkWrite(struct bcm_mini_adapter * Adapter,PUINT pBuffer,unsigned int uiOffset,unsigned int uiNumBytes,bool bVerify)1091 static 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 */
1241 BeceemFlashBulkWrite_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
BeceemFlashBulkWriteStatus(struct bcm_mini_adapter * Adapter,PUINT pBuffer,unsigned int uiOffset,unsigned int uiNumBytes,bool bVerify)1267 static 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 */
1394 BeceemFlashBulkWriteStatus_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
PropagateCalParamsFromFlashToMemory(struct bcm_mini_adapter * Adapter)1415 int 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
BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter * Adapter,PUINT pBuffer,unsigned int uiOffset,unsigned int uiNumBytes)1493 static 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
BcmSwapWord(unsigned int * ptr1)1552 static 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
BeceemEEPROMWritePage(struct bcm_mini_adapter * Adapter,unsigned int uiData[],unsigned int uiOffset)1578 static 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
BeceemEEPROMBulkWrite(struct bcm_mini_adapter * Adapter,PUCHAR pBuffer,unsigned int uiOffset,unsigned int uiNumBytes,bool bVerify)1708 int 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
BeceemNVMRead(struct bcm_mini_adapter * Adapter,PUINT pBuffer,unsigned int uiOffset,unsigned int uiNumBytes)1795 int 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
BeceemNVMWrite(struct bcm_mini_adapter * Adapter,PUINT pBuffer,unsigned int uiOffset,unsigned int uiNumBytes,bool bVerify)1854 int 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
BcmUpdateSectorSize(struct bcm_mini_adapter * Adapter,unsigned int uiSectorSize)1964 int 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
2005 Restore:
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
BcmGetFlashSectorSize(struct bcm_mini_adapter * Adapter,unsigned int FlashSectorSizeSig,unsigned int FlashSectorSize)2025 static 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
BcmInitEEPROMQueues(struct bcm_mini_adapter * Adapter)2078 static 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
BcmInitNVM(struct bcm_mini_adapter * ps_adapter)2115 int 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
BcmGetNvmSize(struct bcm_mini_adapter * Adapter)2141 static 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
BcmValidateNvmType(struct bcm_mini_adapter * Adapter)2163 static 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
BcmReadFlashRDID(struct bcm_mini_adapter * Adapter)2188 static 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
BcmAllocFlashCSStructure(struct bcm_mini_adapter * psAdapter)2211 int 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
BcmDeAllocFlashCSStructure(struct bcm_mini_adapter * psAdapter)2241 int 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
BcmDumpFlash2XCSStructure(struct bcm_flash2x_cs_info * psFlash2xCSInfo,struct bcm_mini_adapter * Adapter)2253 static 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
ConvertEndianOf2XCSStructure(struct bcm_flash2x_cs_info * psFlash2xCSInfo)2313 static 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
ConvertEndianOfCSStructure(struct bcm_flash_cs_info * psFlashCSInfo)2370 static 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
IsSectionExistInVendorInfo(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val section)2402 static 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
UpdateVendorInfo(struct bcm_mini_adapter * Adapter)2409 static 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
BcmGetFlashCSInfo(struct bcm_mini_adapter * Adapter)2496 static 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
BcmGetNvmType(struct bcm_mini_adapter * Adapter)2619 static 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
BcmGetSectionValStartOffset(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val eFlashSectionVal)2657 int 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
BcmGetSectionValEndOffset(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val eFlash2xSectionVal)2749 static 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
BcmFlash2xBulkRead(struct bcm_mini_adapter * Adapter,PUINT pBuffer,enum bcm_flash2x_section_val eFlash2xSectionVal,unsigned int uiOffsetWithinSectionVal,unsigned int uiNumBytes)2836 int 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
BcmFlash2xBulkWrite(struct bcm_mini_adapter * Adapter,PUINT pBuffer,enum bcm_flash2x_section_val eFlash2xSectVal,unsigned int uiOffset,unsigned int uiNumBytes,unsigned int bVerify)2898 int 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
BcmGetActiveDSD(struct bcm_mini_adapter * Adapter)2960 static 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
BcmGetActiveISO(struct bcm_mini_adapter * Adapter)3002 static 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
IsOffsetWritable(struct bcm_mini_adapter * Adapter,unsigned int uiOffset)3031 static 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
BcmDumpFlash2xSectionBitMap(struct bcm_flash2x_bitmap * psFlash2xBitMap)3055 static 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
BcmGetFlash2xSectionalBitMap(struct bcm_mini_adapter * Adapter,struct bcm_flash2x_bitmap * psFlash2xBitMap)3090 int 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
BcmSetActiveSection(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val eFlash2xSectVal)3340 int 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
BcmCopyISO(struct bcm_mini_adapter * Adapter,struct bcm_flash2x_copy_section sCopySectStrut)3520 int 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 }
3786 out:
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
BcmFlash2xCorruptSig(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val eFlash2xSectionVal)3803 int 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
BcmFlash2xWriteSig(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val eFlashSectionVal)3831 int 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
validateFlash2xReadWrite(struct bcm_mini_adapter * Adapter,struct bcm_flash2x_readwrite * psFlash2xReadWrite)3891 int 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
IsFlash2x(struct bcm_mini_adapter * Adapter)3959 int 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
GetFlashBaseAddr(struct bcm_mini_adapter * Adapter)3975 static 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
BcmCopySection(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val SrcSection,enum bcm_flash2x_section_val DstSection,unsigned int offset,unsigned int numOfBytes)4019 int 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
SaveHeaderIfPresent(struct bcm_mini_adapter * Adapter,PUCHAR pBuff,unsigned int uiOffset)4124 static 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 */
BcmDoChipSelect(struct bcm_mini_adapter * Adapter,unsigned int offset)4189 static 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
ReadDSDSignature(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val dsd)4263 static 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
ReadDSDPriority(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val dsd)4288 static 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
getHighestPriDSD(struct bcm_mini_adapter * Adapter)4311 static 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
ReadISOSignature(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val iso)4343 static 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
ReadISOPriority(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val iso)4366 static 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
getHighestPriISO(struct bcm_mini_adapter * Adapter)4386 static 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
WriteToFlashWithoutSectorErase(struct bcm_mini_adapter * Adapter,PUINT pBuff,enum bcm_flash2x_section_val eFlash2xSectionVal,unsigned int uiOffset,unsigned int uiNumBytes)4410 static 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
IsSectionExistInFlash(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val section)4468 bool 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
IsSectionWritable(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val Section)4523 static 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
CorruptDSDSig(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val eFlash2xSectionVal)4546 static 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
CorruptISOSig(struct bcm_mini_adapter * Adapter,enum bcm_flash2x_section_val eFlash2xSectionVal)4608 static 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
IsNonCDLessDevice(struct bcm_mini_adapter * Adapter)4655 bool 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