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