Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nvm.c
Go to the documentation of this file.
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 NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter);
16 
17 static int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, 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, FLASH2X_SECTION_VAL Section);
21 static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section);
22 
23 static int ReadDSDPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd);
24 static int ReadDSDSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd);
25 static int ReadISOPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso);
26 static int ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso);
27 
28 static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal);
29 static int CorruptISOSig(struct bcm_mini_adapter *Adapter, 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  FLASH2X_SECTION_VAL eFlash2xSectionVal,
33  unsigned int uiOffset, unsigned int uiNumBytes);
34 static FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter);
35 static 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  BOOLEAN 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;
67  unsigned int uiStatus = 0;
68  unsigned int value = 0;
69  unsigned int value1 = 0;
70 
71  /* Read the EEPROM 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 
126  DWORD dwAddress,
127  DWORD *pdwData,
128  DWORD dwNumWords)
129 {
130  DWORD dwIndex = 0;
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. */
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 
271 {
272  int Status;
273  unsigned char puMacAddr[6];
274 
275  Status = BeceemNVMRead(Adapter,
276  (PUINT)&puMacAddr[0],
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 
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(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  BOOLEAN 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  BOOLEAN 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: PropagateCalParamsFromEEPROMToMemory
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 
1370 {
1371  PCHAR pBuff = kmalloc(BUFFER_4K, GFP_KERNEL);
1372  unsigned int uiEepromSize = 0;
1373  unsigned int uiIndex = 0;
1374  unsigned int uiBytesToCopy = 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  if (!pBuff)
1381  return -ENOMEM;
1382 
1383  if (0 != BeceemEEPROMBulkRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4)) {
1384  kfree(pBuff);
1385  return -1;
1386  }
1387 
1388  uiEepromSize >>= 16;
1389  if (uiEepromSize > 1024 * 1024) {
1390  kfree(pBuff);
1391  return -1;
1392  }
1393 
1394  uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);
1395 
1396  while (uiBytesToCopy) {
1397  if (0 != BeceemEEPROMBulkRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiBytesToCopy)) {
1398  Status = -1;
1399  break;
1400  }
1401  wrm(Adapter, uiMemoryLoc, (PCHAR)(((PULONG)pBuff) + uiIndex), uiBytesToCopy);
1402  uiMemoryLoc += uiBytesToCopy;
1403  uiEepromSize -= uiBytesToCopy;
1404  uiCalStartAddr += uiBytesToCopy;
1405  uiIndex += uiBytesToCopy / 4;
1406  uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);
1407 
1408  }
1409  value = 0xbeadbead;
1410  wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
1411  value = 0xbeadbead;
1412  wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
1413  kfree(pBuff);
1414 
1415  return Status;
1416 }
1417 
1418 /*
1419  * Procedure: PropagateCalParamsFromFlashToMemory
1420  *
1421  * Description: Dumps the calibration section of EEPROM to DDR.
1422  *
1423  * Arguments:
1424  * Adapter - ptr to Adapter object instance
1425  * Returns:
1426  * OSAL_STATUS_CODE
1427  *
1428  */
1429 
1431 {
1432  PCHAR pBuff, pPtr;
1433  unsigned int uiEepromSize = 0;
1434  unsigned int uiBytesToCopy = 0;
1435  /* unsigned int uiIndex = 0; */
1436  unsigned int uiCalStartAddr = EEPROM_CALPARAM_START;
1437  unsigned int uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC;
1438  unsigned int value;
1439  int Status = 0;
1440 
1441  /*
1442  * Write the signature first. This will ensure firmware does not access EEPROM.
1443  */
1444  value = 0xbeadbead;
1445  wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
1446  value = 0xbeadbead;
1447  wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
1448 
1449  if (0 != BeceemNVMRead(Adapter, &uiEepromSize, EEPROM_SIZE_OFFSET, 4))
1450  return -1;
1451 
1452  uiEepromSize = ntohl(uiEepromSize);
1453  uiEepromSize >>= 16;
1454 
1455  /*
1456  * subtract the auto init section size
1457  */
1458  uiEepromSize -= EEPROM_CALPARAM_START;
1459 
1460  if (uiEepromSize > 1024 * 1024)
1461  return -1;
1462 
1463  pBuff = kmalloc(uiEepromSize, GFP_KERNEL);
1464  if (pBuff == NULL)
1465  return -ENOMEM;
1466 
1467  if (0 != BeceemNVMRead(Adapter, (PUINT)pBuff, uiCalStartAddr, uiEepromSize)) {
1468  kfree(pBuff);
1469  return -1;
1470  }
1471 
1472  pPtr = pBuff;
1473 
1474  uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);
1475 
1476  while (uiBytesToCopy) {
1477  Status = wrm(Adapter, uiMemoryLoc, (PCHAR)pPtr, uiBytesToCopy);
1478  if (Status) {
1479  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm failed with status :%d", Status);
1480  break;
1481  }
1482 
1483  pPtr += uiBytesToCopy;
1484  uiEepromSize -= uiBytesToCopy;
1485  uiMemoryLoc += uiBytesToCopy;
1486  uiBytesToCopy = MIN(BUFFER_4K, uiEepromSize);
1487  }
1488 
1489  kfree(pBuff);
1490  return Status;
1491 }
1492 
1493 /*
1494  * Procedure: BeceemEEPROMReadBackandVerify
1495  *
1496  * Description: Read back the data written and verifies.
1497  *
1498  * Arguments:
1499  * Adapter - ptr to Adapter object instance
1500  * pBuffer - Data to be written.
1501  * uiOffset - Offset of the flash where data needs to be written to.
1502  * uiNumBytes - Number of bytes to be written.
1503  * Returns:
1504  * OSAL_STATUS_CODE
1505  *
1506  */
1507 
1508 static int BeceemEEPROMReadBackandVerify(struct bcm_mini_adapter *Adapter,
1509  PUINT pBuffer,
1510  unsigned int uiOffset,
1511  unsigned int uiNumBytes)
1512 {
1513  unsigned int uiRdbk = 0;
1514  unsigned int uiIndex = 0;
1515  unsigned int uiData = 0;
1516  unsigned int auiData[4] = {0};
1517 
1518  while (uiNumBytes) {
1519  if (Adapter->device_removed)
1520  return -1;
1521 
1522  if (uiNumBytes >= MAX_RW_SIZE) {
1523  /* for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. */
1524  BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE);
1525 
1526  if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE)) {
1527  /* re-write */
1528  BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, MAX_RW_SIZE, FALSE);
1529  mdelay(3);
1530  BeceemEEPROMBulkRead(Adapter, &auiData[0], uiOffset, MAX_RW_SIZE);
1531 
1532  if (memcmp(&pBuffer[uiIndex], &auiData[0], MAX_RW_SIZE))
1533  return -1;
1534  }
1535  uiOffset += MAX_RW_SIZE;
1536  uiNumBytes -= MAX_RW_SIZE;
1537  uiIndex += 4;
1538  } else if (uiNumBytes >= 4) {
1539  BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4);
1540  if (uiData != pBuffer[uiIndex]) {
1541  /* re-write */
1542  BeceemEEPROMBulkWrite(Adapter, (PUCHAR)(pBuffer + uiIndex), uiOffset, 4, FALSE);
1543  mdelay(3);
1544  BeceemEEPROMBulkRead(Adapter, &uiData, uiOffset, 4);
1545  if (uiData != pBuffer[uiIndex])
1546  return -1;
1547  }
1548  uiOffset += 4;
1549  uiNumBytes -= 4;
1550  uiIndex++;
1551  } else {
1552  /* Handle the reads less than 4 bytes... */
1553  uiData = 0;
1554  memcpy(&uiData, ((PUCHAR)pBuffer) + (uiIndex * sizeof(unsigned int)), uiNumBytes);
1555  BeceemEEPROMBulkRead(Adapter, &uiRdbk, uiOffset, 4);
1556 
1557  if (memcmp(&uiData, &uiRdbk, uiNumBytes))
1558  return -1;
1559 
1560  uiNumBytes = 0;
1561  }
1562  }
1563 
1564  return 0;
1565 }
1566 
1567 static VOID BcmSwapWord(unsigned int *ptr1)
1568 {
1569  unsigned int tempval = (unsigned int)*ptr1;
1570  char *ptr2 = (char *)&tempval;
1571  char *ptr = (char *)ptr1;
1572 
1573  ptr[0] = ptr2[3];
1574  ptr[1] = ptr2[2];
1575  ptr[2] = ptr2[1];
1576  ptr[3] = ptr2[0];
1577 }
1578 
1579 /*
1580  * Procedure: BeceemEEPROMWritePage
1581  *
1582  * Description: Performs page write (16bytes) to the EEPROM
1583  *
1584  * Arguments:
1585  * Adapter - ptr to Adapter object instance
1586  * uiData - Data to be written.
1587  * uiOffset - Offset of the EEPROM where data needs to be written to.
1588  * Returns:
1589  * OSAL_STATUS_CODE
1590  *
1591  */
1592 
1593 static int BeceemEEPROMWritePage(struct bcm_mini_adapter *Adapter, unsigned int uiData[], unsigned int uiOffset)
1594 {
1595  unsigned int uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
1596  unsigned int uiStatus = 0;
1597  UCHAR uiEpromStatus = 0;
1598  unsigned int value = 0;
1599 
1600  /* Flush the Write/Read/Cmd queues. */
1602  wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
1603  value = 0;
1604  wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
1605 
1606  /* Clear the Empty/Avail/Full bits. After this it has been confirmed
1607  * that the bit was cleared by reading back the register. See NOTE below.
1608  * We also clear the Read queues as we do a EEPROM status register read
1609  * later.
1610  */
1612  wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
1613 
1614  /* Enable write */
1615  value = EEPROM_WRITE_ENABLE;
1616  wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));
1617 
1618  /* We can write back to back 8bits * 16 into the queue and as we have
1619  * checked for the queue to be empty we can write in a burst.
1620  */
1621 
1622  value = uiData[0];
1623  BcmSwapWord(&value);
1624  wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);
1625 
1626  value = uiData[1];
1627  BcmSwapWord(&value);
1628  wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);
1629 
1630  value = uiData[2];
1631  BcmSwapWord(&value);
1632  wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);
1633 
1634  value = uiData[3];
1635  BcmSwapWord(&value);
1636  wrm(Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4);
1637 
1638  /* NOTE : After this write, on readback of EEPROM_SPI_Q_STATUS1_REG
1639  * shows that we see 7 for the EEPROM data write. Which means that
1640  * queue got full, also space is available as well as the queue is empty.
1641  * This may happen in sequence.
1642  */
1643  value = EEPROM_16_BYTE_PAGE_WRITE | uiOffset;
1644  wrmalt(Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value));
1645 
1646  /* Ideally we should loop here without tries and eventually succeed.
1647  * What we are checking if the previous write has completed, and this
1648  * may take time. We should wait till the Empty bit is set.
1649  */
1650  uiStatus = 0;
1651  rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
1652  while ((uiStatus & EEPROM_WRITE_QUEUE_EMPTY) == 0) {
1653  uiRetries--;
1654  if (uiRetries == 0) {
1655  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, %d retries failed.\n", uiStatus, MAX_EEPROM_RETRIES * RETRIES_PER_DELAY);
1656  return STATUS_FAILURE;
1657  }
1658 
1659  if (!(uiRetries%RETRIES_PER_DELAY))
1660  udelay(1000);
1661 
1662  uiStatus = 0;
1663  rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus));
1664  if (Adapter->device_removed == TRUE) {
1665  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem got removed hence exiting from loop....");
1666  return -ENODEV;
1667  }
1668  }
1669 
1670  if (uiRetries != 0) {
1671  /* Clear the ones that are set - either, Empty/Full/Avail bits */
1672  value = (uiStatus & (EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL));
1673  wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
1674  }
1675 
1676  /* Here we should check if the EEPROM status register is correct before
1677  * proceeding. Bit 0 in the EEPROM Status register should be 0 before
1678  * we proceed further. A 1 at Bit 0 indicates that the EEPROM is busy
1679  * with the previous write. Note also that issuing this read finally
1680  * means the previous write to the EEPROM has completed.
1681  */
1682  uiRetries = MAX_EEPROM_RETRIES * RETRIES_PER_DELAY;
1683  uiEpromStatus = 0;
1684  while (uiRetries != 0) {
1685  uiEpromStatus = ReadEEPROMStatusRegister(Adapter);
1686  if (Adapter->device_removed == TRUE) {
1687  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting from loop...");
1688  return -ENODEV;
1689  }
1690  if ((EEPROM_STATUS_REG_WRITE_BUSY & uiEpromStatus) == 0) {
1691  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM status register = %x tries = %d\n", uiEpromStatus, (MAX_EEPROM_RETRIES * RETRIES_PER_DELAY - uiRetries));
1692  return STATUS_SUCCESS;
1693  }
1694  uiRetries--;
1695  if (uiRetries == 0) {
1696  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);
1697  return STATUS_FAILURE;
1698  }
1699  uiEpromStatus = 0;
1700  if (!(uiRetries%RETRIES_PER_DELAY))
1701  udelay(1000);
1702  }
1703 
1704  return STATUS_SUCCESS;
1705 } /* BeceemEEPROMWritePage */
1706 
1707 /*
1708  * Procedure: BeceemEEPROMBulkWrite
1709  *
1710  * Description: Performs write to the EEPROM
1711  *
1712  * Arguments:
1713  * Adapter - ptr to Adapter object instance
1714  * pBuffer - Data to be written.
1715  * uiOffset - Offset of the EEPROM where data needs to be written to.
1716  * uiNumBytes - Number of bytes to be written.
1717  * bVerify - read verify flag.
1718  * Returns:
1719  * OSAL_STATUS_CODE
1720  *
1721  */
1722 
1724  PUCHAR pBuffer,
1725  unsigned int uiOffset,
1726  unsigned int uiNumBytes,
1727  BOOLEAN bVerify)
1728 {
1729  unsigned int uiBytesToCopy = uiNumBytes;
1730  /* unsigned int uiRdbk = 0; */
1731  unsigned int uiData[4] = {0};
1732  unsigned int uiIndex = 0;
1733  unsigned int uiTempOffset = 0;
1734  unsigned int uiExtraBytes = 0;
1735  /* PUINT puiBuffer = (PUINT)pBuffer;
1736  * int value;
1737  */
1738 
1739  if (uiOffset % MAX_RW_SIZE && uiBytesToCopy) {
1740  uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE);
1741  uiExtraBytes = uiOffset - uiTempOffset;
1742 
1743  BeceemEEPROMBulkRead(Adapter, &uiData[0], uiTempOffset, MAX_RW_SIZE);
1744 
1745  if (uiBytesToCopy >= (16 - uiExtraBytes)) {
1746  memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, MAX_RW_SIZE - uiExtraBytes);
1747 
1748  if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset))
1749  return STATUS_FAILURE;
1750 
1751  uiBytesToCopy -= (MAX_RW_SIZE - uiExtraBytes);
1752  uiIndex += (MAX_RW_SIZE - uiExtraBytes);
1753  uiOffset += (MAX_RW_SIZE - uiExtraBytes);
1754  } else {
1755  memcpy((((PUCHAR)&uiData[0]) + uiExtraBytes), pBuffer, uiBytesToCopy);
1756 
1757  if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiTempOffset))
1758  return STATUS_FAILURE;
1759 
1760  uiIndex += uiBytesToCopy;
1761  uiOffset += uiBytesToCopy;
1762  uiBytesToCopy = 0;
1763  }
1764  }
1765 
1766  while (uiBytesToCopy) {
1767  if (Adapter->device_removed)
1768  return -1;
1769 
1770  if (uiBytesToCopy >= MAX_RW_SIZE) {
1771  if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, (PUINT) &pBuffer[uiIndex], uiOffset))
1772  return STATUS_FAILURE;
1773 
1774  uiIndex += MAX_RW_SIZE;
1775  uiOffset += MAX_RW_SIZE;
1776  uiBytesToCopy -= MAX_RW_SIZE;
1777  } else {
1778  /*
1779  * To program non 16byte aligned data, read 16byte and then update.
1780  */
1781  BeceemEEPROMBulkRead(Adapter, &uiData[0], uiOffset, 16);
1782  memcpy(&uiData[0], pBuffer + uiIndex, uiBytesToCopy);
1783 
1784  if (STATUS_FAILURE == BeceemEEPROMWritePage(Adapter, uiData, uiOffset))
1785  return STATUS_FAILURE;
1786 
1787  uiBytesToCopy = 0;
1788  }
1789  }
1790 
1791  return 0;
1792 }
1793 
1794 /*
1795  * Procedure: BeceemNVMRead
1796  *
1797  * Description: Reads n number of bytes from NVM.
1798  *
1799  * Arguments:
1800  * Adapter - ptr to Adapter object instance
1801  * pBuffer - Buffer to store the data read from NVM
1802  * uiOffset - Offset of NVM from where data should be read
1803  * uiNumBytes - Number of bytes to be read from the NVM.
1804  *
1805  * Returns:
1806  * OSAL_STATUS_SUCCESS - if NVM read is successful.
1807  * <FAILURE> - if failed.
1808  */
1809 
1810 int BeceemNVMRead(struct bcm_mini_adapter *Adapter,
1811  PUINT pBuffer,
1812  unsigned int uiOffset,
1813  unsigned int uiNumBytes)
1814 {
1815  int Status = 0;
1816 
1817  #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
1818  unsigned int uiTemp = 0, value;
1819  #endif
1820 
1821  if (Adapter->eNVMType == NVM_FLASH) {
1822  if (Adapter->bFlashRawRead == FALSE) {
1823  if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD))
1824  return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes);
1825 
1826  uiOffset = uiOffset + Adapter->ulFlashCalStart;
1827  }
1828 
1829  #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
1830  Status = bcmflash_raw_read((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
1831  #else
1832  rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
1833  value = 0;
1834  wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
1835  Status = BeceemFlashBulkRead(Adapter,
1836  pBuffer,
1837  uiOffset,
1838  uiNumBytes);
1839  wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
1840  #endif
1841  } else if (Adapter->eNVMType == NVM_EEPROM) {
1842  Status = BeceemEEPROMBulkRead(Adapter,
1843  pBuffer,
1844  uiOffset,
1845  uiNumBytes);
1846  } else {
1847  Status = -1;
1848  }
1849 
1850  return Status;
1851 }
1852 
1853 /*
1854  * Procedure: BeceemNVMWrite
1855  *
1856  * Description: Writes n number of bytes to NVM.
1857  *
1858  * Arguments:
1859  * Adapter - ptr to Adapter object instance
1860  * pBuffer - Buffer contains the data to be written.
1861  * uiOffset - Offset of NVM where data to be written to.
1862  * uiNumBytes - Number of bytes to be written..
1863  *
1864  * Returns:
1865  * OSAL_STATUS_SUCCESS - if NVM write is successful.
1866  * <FAILURE> - if failed.
1867  */
1868 
1869 int BeceemNVMWrite(struct bcm_mini_adapter *Adapter,
1870  PUINT pBuffer,
1871  unsigned int uiOffset,
1872  unsigned int uiNumBytes,
1873  BOOLEAN bVerify)
1874 {
1875  int Status = 0;
1876  unsigned int uiTemp = 0;
1877  unsigned int uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC;
1878  unsigned int uiIndex = 0;
1879 
1880  #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
1881  unsigned int value;
1882  #endif
1883 
1884  unsigned int uiFlashOffset = 0;
1885 
1886  if (Adapter->eNVMType == NVM_FLASH) {
1887  if (IsSectionExistInVendorInfo(Adapter, Adapter->eActiveDSD))
1888  Status = vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, Adapter->eActiveDSD, uiOffset, uiNumBytes, bVerify);
1889  else {
1890  uiFlashOffset = uiOffset + Adapter->ulFlashCalStart;
1891 
1892  #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
1893  Status = bcmflash_raw_write((uiFlashOffset / FLASH_PART_SIZE), (uiFlashOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer, uiNumBytes);
1894  #else
1895  rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
1896  value = 0;
1897  wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
1898 
1899  if (Adapter->bStatusWrite == TRUE)
1900  Status = BeceemFlashBulkWriteStatus(Adapter,
1901  pBuffer,
1902  uiFlashOffset,
1903  uiNumBytes ,
1904  bVerify);
1905  else
1906 
1907  Status = BeceemFlashBulkWrite(Adapter,
1908  pBuffer,
1909  uiFlashOffset,
1910  uiNumBytes,
1911  bVerify);
1912  #endif
1913  }
1914 
1915  if (uiOffset >= EEPROM_CALPARAM_START) {
1916  uiMemoryLoc += (uiOffset - EEPROM_CALPARAM_START);
1917  while (uiNumBytes) {
1918  if (uiNumBytes > BUFFER_4K) {
1919  wrm(Adapter, (uiMemoryLoc+uiIndex), (PCHAR)(pBuffer + (uiIndex / 4)), BUFFER_4K);
1920  uiNumBytes -= BUFFER_4K;
1921  uiIndex += BUFFER_4K;
1922  } else {
1923  wrm(Adapter, uiMemoryLoc+uiIndex, (PCHAR)(pBuffer + (uiIndex / 4)), uiNumBytes);
1924  uiNumBytes = 0;
1925  break;
1926  }
1927  }
1928  } else {
1929  if ((uiOffset + uiNumBytes) > EEPROM_CALPARAM_START) {
1930  ULONG ulBytesTobeSkipped = 0;
1931  PUCHAR pcBuffer = (PUCHAR)pBuffer; /* char pointer to take care of odd byte cases. */
1932  uiNumBytes -= (EEPROM_CALPARAM_START - uiOffset);
1933  ulBytesTobeSkipped += (EEPROM_CALPARAM_START - uiOffset);
1934  uiOffset += (EEPROM_CALPARAM_START - uiOffset);
1935  while (uiNumBytes) {
1936  if (uiNumBytes > BUFFER_4K) {
1937  wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], BUFFER_4K);
1938  uiNumBytes -= BUFFER_4K;
1939  uiIndex += BUFFER_4K;
1940  } else {
1941  wrm(Adapter, uiMemoryLoc + uiIndex, (PCHAR)&pcBuffer[ulBytesTobeSkipped + uiIndex], uiNumBytes);
1942  uiNumBytes = 0;
1943  break;
1944  }
1945  }
1946  }
1947  }
1948  /* restore the values. */
1949  wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
1950  } else if (Adapter->eNVMType == NVM_EEPROM) {
1951  Status = BeceemEEPROMBulkWrite(Adapter,
1952  (PUCHAR)pBuffer,
1953  uiOffset,
1954  uiNumBytes,
1955  bVerify);
1956  if (bVerify)
1957  Status = BeceemEEPROMReadBackandVerify(Adapter, (PUINT)pBuffer, uiOffset, uiNumBytes);
1958  } else {
1959  Status = -1;
1960  }
1961  return Status;
1962 }
1963 
1964 /*
1965  * Procedure: BcmUpdateSectorSize
1966  *
1967  * Description: Updates the sector size to FLASH.
1968  *
1969  * Arguments:
1970  * Adapter - ptr to Adapter object instance
1971  * uiSectorSize - sector size
1972  *
1973  * Returns:
1974  * OSAL_STATUS_SUCCESS - if NVM write is successful.
1975  * <FAILURE> - if failed.
1976  */
1977 
1978 int BcmUpdateSectorSize(struct bcm_mini_adapter *Adapter, unsigned int uiSectorSize)
1979 {
1980  int Status = -1;
1981  FLASH_CS_INFO sFlashCsInfo = {0};
1982  unsigned int uiTemp = 0;
1983  unsigned int uiSectorSig = 0;
1984  unsigned int uiCurrentSectorSize = 0;
1985  unsigned int value;
1986 
1987  rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
1988  value = 0;
1989  wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
1990 
1991  /*
1992  * Before updating the sector size in the reserved area, check if already present.
1993  */
1994  BeceemFlashBulkRead(Adapter, (PUINT)&sFlashCsInfo, Adapter->ulFlashControlSectionStart, sizeof(sFlashCsInfo));
1995  uiSectorSig = ntohl(sFlashCsInfo.FlashSectorSizeSig);
1996  uiCurrentSectorSize = ntohl(sFlashCsInfo.FlashSectorSize);
1997 
1998  if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) {
1999  if ((uiCurrentSectorSize <= MAX_SECTOR_SIZE) && (uiCurrentSectorSize >= MIN_SECTOR_SIZE)) {
2000  if (uiSectorSize == uiCurrentSectorSize) {
2001  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Provided sector size is same as programmed in Flash");
2002  Status = STATUS_SUCCESS;
2003  goto Restore;
2004  }
2005  }
2006  }
2007 
2008  if ((uiSectorSize <= MAX_SECTOR_SIZE) && (uiSectorSize >= MIN_SECTOR_SIZE)) {
2009  sFlashCsInfo.FlashSectorSize = htonl(uiSectorSize);
2010  sFlashCsInfo.FlashSectorSizeSig = htonl(FLASH_SECTOR_SIZE_SIG);
2011 
2012  Status = BeceemFlashBulkWrite(Adapter,
2013  (PUINT)&sFlashCsInfo,
2014  Adapter->ulFlashControlSectionStart,
2015  sizeof(sFlashCsInfo),
2016  TRUE);
2017  }
2018 
2019 Restore:
2020  /* restore the values. */
2021  wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
2022 
2023  return Status;
2024 }
2025 
2026 /*
2027  * Procedure: BcmGetFlashSectorSize
2028  *
2029  * Description: Finds the sector size of the FLASH.
2030  *
2031  * Arguments:
2032  * Adapter - ptr to Adapter object instance
2033  *
2034  * Returns:
2035  * unsigned int - sector size.
2036  *
2037  */
2038 
2039 static unsigned int BcmGetFlashSectorSize(struct bcm_mini_adapter *Adapter, unsigned int FlashSectorSizeSig, unsigned int FlashSectorSize)
2040 {
2041  unsigned int uiSectorSize = 0;
2042  unsigned int uiSectorSig = 0;
2043 
2044  if (Adapter->bSectorSizeOverride &&
2045  (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE &&
2046  Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)) {
2047  Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG;
2048  } else {
2049  uiSectorSig = FlashSectorSizeSig;
2050 
2051  if (uiSectorSig == FLASH_SECTOR_SIZE_SIG) {
2052  uiSectorSize = FlashSectorSize;
2053  /*
2054  * If the sector size stored in the FLASH makes sense then use it.
2055  */
2056  if (uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) {
2057  Adapter->uiSectorSize = uiSectorSize;
2058  } else if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE &&
2059  Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) {
2060  /* No valid size in FLASH, check if Config file has it. */
2061  Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG;
2062  } else {
2063  /* Init to Default, if none of the above works. */
2064  Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE;
2065  }
2066  } else {
2067  if (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE &&
2068  Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)
2069  Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG;
2070  else
2071  Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE;
2072  }
2073  }
2074 
2075  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector size :%x\n", Adapter->uiSectorSize);
2076 
2077  return Adapter->uiSectorSize;
2078 }
2079 
2080 /*
2081  * Procedure: BcmInitEEPROMQueues
2082  *
2083  * Description: Initialization of EEPROM queues.
2084  *
2085  * Arguments:
2086  * Adapter - ptr to Adapter object instance
2087  *
2088  * Returns:
2089  * <OSAL_STATUS_CODE>
2090  */
2091 
2092 static int BcmInitEEPROMQueues(struct bcm_mini_adapter *Adapter)
2093 {
2094  unsigned int value = 0;
2095  /* CHIP Bug : Clear the Avail bits on the Read queue. The default
2096  * value on this register is supposed to be 0x00001102.
2097  * But we get 0x00001122.
2098  */
2099  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Fixing reset value on 0x0f003004 register\n");
2100  value = EEPROM_READ_DATA_AVAIL;
2101  wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value));
2102 
2103  /* Flush the all the EEPROM queues. */
2104  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Flushing the queues\n");
2105  value = EEPROM_ALL_QUEUE_FLUSH;
2106  wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
2107 
2108  value = 0;
2109  wrmalt(Adapter, SPI_FLUSH_REG, &value, sizeof(value));
2110 
2111  /* Read the EEPROM Status Register. Just to see, no real purpose. */
2112  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "EEPROM Status register value = %x\n", ReadEEPROMStatusRegister(Adapter));
2113 
2114  return STATUS_SUCCESS;
2115 } /* BcmInitEEPROMQueues() */
2116 
2117 /*
2118  * Procedure: BcmInitNVM
2119  *
2120  * Description: Initialization of NVM, EEPROM size,FLASH size, sector size etc.
2121  *
2122  * Arguments:
2123  * Adapter - ptr to Adapter object instance
2124  *
2125  * Returns:
2126  * <OSAL_STATUS_CODE>
2127  */
2128 
2129 int BcmInitNVM(struct bcm_mini_adapter *ps_adapter)
2130 {
2131  BcmValidateNvmType(ps_adapter);
2132  BcmInitEEPROMQueues(ps_adapter);
2133 
2134  if (ps_adapter->eNVMType == NVM_AUTODETECT) {
2135  ps_adapter->eNVMType = BcmGetNvmType(ps_adapter);
2136  if (ps_adapter->eNVMType == NVM_UNKNOWN)
2137  BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "NVM Type is unknown!!\n");
2138  } else if (ps_adapter->eNVMType == NVM_FLASH) {
2139  BcmGetFlashCSInfo(ps_adapter);
2140  }
2141 
2142  BcmGetNvmSize(ps_adapter);
2143 
2144  return STATUS_SUCCESS;
2145 }
2146 
2147 /* BcmGetNvmSize : set the EEPROM or flash size in Adapter.
2148  *
2149  * Input Parameter:
2150  * Adapter data structure
2151  * Return Value :
2152  * 0. means success;
2153  */
2154 
2155 static int BcmGetNvmSize(struct bcm_mini_adapter *Adapter)
2156 {
2157  if (Adapter->eNVMType == NVM_EEPROM)
2158  Adapter->uiNVMDSDSize = BcmGetEEPROMSize(Adapter);
2159  else if (Adapter->eNVMType == NVM_FLASH)
2160  Adapter->uiNVMDSDSize = BcmGetFlashSize(Adapter);
2161 
2162  return 0;
2163 }
2164 
2165 /*
2166  * Procedure: BcmValidateNvm
2167  *
2168  * Description: Validates the NVM Type option selected against the device
2169  *
2170  * Arguments:
2171  * Adapter - ptr to Adapter object instance
2172  *
2173  * Returns:
2174  * <VOID>
2175  */
2176 
2177 static VOID BcmValidateNvmType(struct bcm_mini_adapter *Adapter)
2178 {
2179  /*
2180  * if forcing the FLASH through CFG file, we should ensure device really has a FLASH.
2181  * Accessing the FLASH address without the FLASH being present can cause hang/freeze etc.
2182  * So if NVM_FLASH is selected for older chipsets, change it to AUTODETECT where EEPROM is 1st choice.
2183  */
2184 
2185  if (Adapter->eNVMType == NVM_FLASH &&
2186  Adapter->chip_id < 0xBECE3300)
2187  Adapter->eNVMType = NVM_AUTODETECT;
2188 }
2189 
2190 /*
2191  * Procedure: BcmReadFlashRDID
2192  *
2193  * Description: Reads ID from Serial Flash
2194  *
2195  * Arguments:
2196  * Adapter - ptr to Adapter object instance
2197  *
2198  * Returns:
2199  * Flash ID
2200  */
2201 
2202 static ULONG BcmReadFlashRDID(struct bcm_mini_adapter *Adapter)
2203 {
2204  ULONG ulRDID = 0;
2205  unsigned int value;
2206 
2207  /*
2208  * Read ID Instruction.
2209  */
2210  value = (FLASH_CMD_READ_ID << 24);
2211  wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value));
2212 
2213  /* Delay */
2214  udelay(10);
2215 
2216  /*
2217  * Read SPI READQ REG. The output will be WWXXYYZZ.
2218  * The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored.
2219  */
2220  rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulRDID, sizeof(ulRDID));
2221 
2222  return ulRDID >> 8;
2223 }
2224 
2226 {
2227  if (!psAdapter) {
2228  BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL");
2229  return -EINVAL;
2230  }
2231  psAdapter->psFlashCSInfo = (PFLASH_CS_INFO)kzalloc(sizeof(FLASH_CS_INFO), GFP_KERNEL);
2232  if (psAdapter->psFlashCSInfo == NULL) {
2233  BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 1.x");
2234  return -ENOMEM;
2235  }
2236 
2237  psAdapter->psFlash2xCSInfo = (PFLASH2X_CS_INFO)kzalloc(sizeof(FLASH2X_CS_INFO), GFP_KERNEL);
2238  if (!psAdapter->psFlash2xCSInfo) {
2239  BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate memory for Flash 2.x");
2240  kfree(psAdapter->psFlashCSInfo);
2241  return -ENOMEM;
2242  }
2243 
2245  if (!psAdapter->psFlash2xVendorInfo) {
2246  BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Can't Allocate Vendor Info Memory for Flash 2.x");
2247  kfree(psAdapter->psFlashCSInfo);
2248  kfree(psAdapter->psFlash2xCSInfo);
2249  return -ENOMEM;
2250  }
2251 
2252  return STATUS_SUCCESS;
2253 }
2254 
2256 {
2257  if (!psAdapter) {
2258  BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL");
2259  return -EINVAL;
2260  }
2261  kfree(psAdapter->psFlashCSInfo);
2262  kfree(psAdapter->psFlash2xCSInfo);
2263  kfree(psAdapter->psFlash2xVendorInfo);
2264  return STATUS_SUCCESS;
2265 }
2266 
2267 static int BcmDumpFlash2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo, struct bcm_mini_adapter *Adapter)
2268 {
2269  unsigned int Index = 0;
2270 
2271  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "**********************FLASH2X CS Structure *******************");
2272  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x", (psFlash2xCSInfo->MagicNumber));
2273  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Major Version :%d", MAJOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion));
2274  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Minor Version :%d", MINOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion));
2275  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ISOImageMajorVersion:0x%x", (psFlash2xCSInfo->ISOImageVersion));
2276  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSIFirmwareMajorVersion :0x%x", (psFlash2xCSInfo->SCSIFirmwareVersion));
2277  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart1ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage));
2278  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForScsiFirmware :0x%x", (psFlash2xCSInfo->OffsetFromZeroForScsiFirmware));
2279  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SizeOfScsiFirmware :0x%x", (psFlash2xCSInfo->SizeOfScsiFirmware));
2280  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart2ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage));
2281  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDStart));
2282  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDEnd));
2283  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAStart));
2284  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAEnd));
2285  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionStart));
2286  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionData :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionData));
2287  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CDLessInactivityTimeout :0x%x", (psFlash2xCSInfo->CDLessInactivityTimeout));
2288  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "NewImageSignature :0x%x", (psFlash2xCSInfo->NewImageSignature));
2289  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSizeSig :0x%x", (psFlash2xCSInfo->FlashSectorSizeSig));
2290  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSize :0x%x", (psFlash2xCSInfo->FlashSectorSize));
2291  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashWriteSupportSize :0x%x", (psFlash2xCSInfo->FlashWriteSupportSize));
2292  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "TotalFlashSize :0x%X", (psFlash2xCSInfo->TotalFlashSize));
2293  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashBaseAddr :0x%x", (psFlash2xCSInfo->FlashBaseAddr));
2294  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashPartMaxSize :0x%x", (psFlash2xCSInfo->FlashPartMaxSize));
2295  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "IsCDLessDeviceBootSig :0x%x", (psFlash2xCSInfo->IsCDLessDeviceBootSig));
2296  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "MassStorageTimeout :0x%x", (psFlash2xCSInfo->MassStorageTimeout));
2297  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1Start));
2298  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1End));
2299  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2Start));
2300  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2End));
2301  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3Start));
2302  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3End));
2303  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1Start));
2304  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1End));
2305  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2Start));
2306  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2End));
2307  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3Start));
2308  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3End));
2309  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromDSDStartForDSDHeader :0x%x", (psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader));
2310  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1Start));
2311  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1End));
2312  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2Start));
2313  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2End));
2314  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1Start));
2315  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1End));
2316  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2Start));
2317  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2End));
2318  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector Access Bit Map is Defined as :");
2319 
2320  for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++)
2321  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectorAccessBitMap[%d] :0x%x", Index,
2322  (psFlash2xCSInfo->SectorAccessBitMap[Index]));
2323 
2324  return STATUS_SUCCESS;
2325 }
2326 
2327 static int ConvertEndianOf2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo)
2328 {
2329  unsigned int Index = 0;
2330 
2331  psFlash2xCSInfo->MagicNumber = ntohl(psFlash2xCSInfo->MagicNumber);
2332  psFlash2xCSInfo->FlashLayoutVersion = ntohl(psFlash2xCSInfo->FlashLayoutVersion);
2333  /* psFlash2xCSInfo->FlashLayoutMinorVersion = ntohs(psFlash2xCSInfo->FlashLayoutMinorVersion); */
2334  psFlash2xCSInfo->ISOImageVersion = ntohl(psFlash2xCSInfo->ISOImageVersion);
2335  psFlash2xCSInfo->SCSIFirmwareVersion = ntohl(psFlash2xCSInfo->SCSIFirmwareVersion);
2336  psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage);
2337  psFlash2xCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlash2xCSInfo->OffsetFromZeroForScsiFirmware);
2338  psFlash2xCSInfo->SizeOfScsiFirmware = ntohl(psFlash2xCSInfo->SizeOfScsiFirmware);
2339  psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage);
2340  psFlash2xCSInfo->OffsetFromZeroForDSDStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDStart);
2341  psFlash2xCSInfo->OffsetFromZeroForDSDEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDEnd);
2342  psFlash2xCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAStart);
2343  psFlash2xCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAEnd);
2346  psFlash2xCSInfo->CDLessInactivityTimeout = ntohl(psFlash2xCSInfo->CDLessInactivityTimeout);
2347  psFlash2xCSInfo->NewImageSignature = ntohl(psFlash2xCSInfo->NewImageSignature);
2348  psFlash2xCSInfo->FlashSectorSizeSig = ntohl(psFlash2xCSInfo->FlashSectorSizeSig);
2349  psFlash2xCSInfo->FlashSectorSize = ntohl(psFlash2xCSInfo->FlashSectorSize);
2350  psFlash2xCSInfo->FlashWriteSupportSize = ntohl(psFlash2xCSInfo->FlashWriteSupportSize);
2351  psFlash2xCSInfo->TotalFlashSize = ntohl(psFlash2xCSInfo->TotalFlashSize);
2352  psFlash2xCSInfo->FlashBaseAddr = ntohl(psFlash2xCSInfo->FlashBaseAddr);
2353  psFlash2xCSInfo->FlashPartMaxSize = ntohl(psFlash2xCSInfo->FlashPartMaxSize);
2354  psFlash2xCSInfo->IsCDLessDeviceBootSig = ntohl(psFlash2xCSInfo->IsCDLessDeviceBootSig);
2355  psFlash2xCSInfo->MassStorageTimeout = ntohl(psFlash2xCSInfo->MassStorageTimeout);
2356  psFlash2xCSInfo->OffsetISOImage1Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1Start);
2357  psFlash2xCSInfo->OffsetISOImage1Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1End);
2358  psFlash2xCSInfo->OffsetISOImage1Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2Start);
2359  psFlash2xCSInfo->OffsetISOImage1Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2End);
2360  psFlash2xCSInfo->OffsetISOImage1Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3Start);
2361  psFlash2xCSInfo->OffsetISOImage1Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3End);
2362  psFlash2xCSInfo->OffsetISOImage2Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1Start);
2363  psFlash2xCSInfo->OffsetISOImage2Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1End);
2364  psFlash2xCSInfo->OffsetISOImage2Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2Start);
2365  psFlash2xCSInfo->OffsetISOImage2Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2End);
2366  psFlash2xCSInfo->OffsetISOImage2Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3Start);
2367  psFlash2xCSInfo->OffsetISOImage2Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3End);
2368  psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader = ntohl(psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader);
2369  psFlash2xCSInfo->OffsetFromZeroForDSD1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1Start);
2370  psFlash2xCSInfo->OffsetFromZeroForDSD1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1End);
2371  psFlash2xCSInfo->OffsetFromZeroForDSD2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2Start);
2372  psFlash2xCSInfo->OffsetFromZeroForDSD2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2End);
2373  psFlash2xCSInfo->OffsetFromZeroForVSA1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1Start);
2374  psFlash2xCSInfo->OffsetFromZeroForVSA1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1End);
2375  psFlash2xCSInfo->OffsetFromZeroForVSA2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2Start);
2376  psFlash2xCSInfo->OffsetFromZeroForVSA2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2End);
2377 
2378  for (Index = 0; Index < (FLASH2X_TOTAL_SIZE / (DEFAULT_SECTOR_SIZE * 16)); Index++)
2379  psFlash2xCSInfo->SectorAccessBitMap[Index] = ntohl(psFlash2xCSInfo->SectorAccessBitMap[Index]);
2380 
2381  return STATUS_SUCCESS;
2382 }
2383 
2384 static int ConvertEndianOfCSStructure(PFLASH_CS_INFO psFlashCSInfo)
2385 {
2386  /* unsigned int Index = 0; */
2387  psFlashCSInfo->MagicNumber = ntohl(psFlashCSInfo->MagicNumber);
2388  psFlashCSInfo->FlashLayoutVersion = ntohl(psFlashCSInfo->FlashLayoutVersion);
2389  psFlashCSInfo->ISOImageVersion = ntohl(psFlashCSInfo->ISOImageVersion);
2390  /* won't convert according to old assumption */
2391  psFlashCSInfo->SCSIFirmwareVersion = (psFlashCSInfo->SCSIFirmwareVersion);
2392  psFlashCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart1ISOImage);
2393  psFlashCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlashCSInfo->OffsetFromZeroForScsiFirmware);
2394  psFlashCSInfo->SizeOfScsiFirmware = ntohl(psFlashCSInfo->SizeOfScsiFirmware);
2395  psFlashCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart2ISOImage);
2398  psFlashCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlashCSInfo->OffsetFromZeroForVSAStart);
2399  psFlashCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlashCSInfo->OffsetFromZeroForVSAEnd);
2402  psFlashCSInfo->CDLessInactivityTimeout = ntohl(psFlashCSInfo->CDLessInactivityTimeout);
2403  psFlashCSInfo->NewImageSignature = ntohl(psFlashCSInfo->NewImageSignature);
2404  psFlashCSInfo->FlashSectorSizeSig = ntohl(psFlashCSInfo->FlashSectorSizeSig);
2405  psFlashCSInfo->FlashSectorSize = ntohl(psFlashCSInfo->FlashSectorSize);
2406  psFlashCSInfo->FlashWriteSupportSize = ntohl(psFlashCSInfo->FlashWriteSupportSize);
2407  psFlashCSInfo->TotalFlashSize = ntohl(psFlashCSInfo->TotalFlashSize);
2408  psFlashCSInfo->FlashBaseAddr = ntohl(psFlashCSInfo->FlashBaseAddr);
2409  psFlashCSInfo->FlashPartMaxSize = ntohl(psFlashCSInfo->FlashPartMaxSize);
2410  psFlashCSInfo->IsCDLessDeviceBootSig = ntohl(psFlashCSInfo->IsCDLessDeviceBootSig);
2411  psFlashCSInfo->MassStorageTimeout = ntohl(psFlashCSInfo->MassStorageTimeout);
2412 
2413  return STATUS_SUCCESS;
2414 }
2415 
2416 static int IsSectionExistInVendorInfo(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL section)
2417 {
2418  return (Adapter->uiVendorExtnFlag &&
2421 }
2422 
2423 static VOID UpdateVendorInfo(struct bcm_mini_adapter *Adapter)
2424 {
2425  B_UINT32 i = 0;
2426  unsigned int uiSizeSection = 0;
2427 
2428  Adapter->uiVendorExtnFlag = FALSE;
2429 
2430  for (i = 0; i < TOTAL_SECTIONS; i++)
2432 
2434  return;
2435 
2436  i = 0;
2437  while (i < TOTAL_SECTIONS) {
2439  i++;
2440  continue;
2441  }
2442 
2443  Adapter->uiVendorExtnFlag = TRUE;
2444  uiSizeSection = (Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionEnd -
2446 
2447  switch (i) {
2448  case DSD0:
2449  if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) &&
2452  else
2454  break;
2455 
2456  case DSD1:
2457  if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) &&
2460  else
2462  break;
2463 
2464  case DSD2:
2465  if ((uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) &&
2468  else
2470  break;
2471  case VSA0:
2474  else
2476  break;
2477 
2478  case VSA1:
2481  else
2483  break;
2484  case VSA2:
2487  else
2489  break;
2490 
2491  default:
2492  break;
2493  }
2494  i++;
2495  }
2496 }
2497 
2498 /*
2499  * Procedure: BcmGetFlashCSInfo
2500  *
2501  * Description: Reads control structure and gets Cal section addresses.
2502  *
2503  * Arguments:
2504  * Adapter - ptr to Adapter object instance
2505  *
2506  * Returns:
2507  * <VOID>
2508  */
2509 
2510 static int BcmGetFlashCSInfo(struct bcm_mini_adapter *Adapter)
2511 {
2512  /* FLASH_CS_INFO sFlashCsInfo = {0}; */
2513 
2514  #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
2515  unsigned int value;
2516  #endif
2517 
2518  unsigned int uiFlashLayoutMajorVersion;
2519  Adapter->uiFlashLayoutMinorVersion = 0;
2520  Adapter->uiFlashLayoutMajorVersion = 0;
2522 
2523  Adapter->uiFlashBaseAdd = 0;
2524  Adapter->ulFlashCalStart = 0;
2525  memset(Adapter->psFlashCSInfo, 0 , sizeof(FLASH_CS_INFO));
2526  memset(Adapter->psFlash2xCSInfo, 0 , sizeof(FLASH2X_CS_INFO));
2527 
2528  if (!Adapter->bDDRInitDone) {
2530  wrmalt(Adapter, 0xAF00A080, &value, sizeof(value));
2531  }
2532 
2533  /* Reading first 8 Bytes to get the Flash Layout
2534  * MagicNumber(4 bytes) +FlashLayoutMinorVersion(2 Bytes) +FlashLayoutMajorVersion(2 Bytes)
2535  */
2536  BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, 8);
2537 
2539  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Version :%X", (Adapter->psFlashCSInfo->FlashLayoutVersion));
2540  /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Minor Version :%d\n", ntohs(sFlashCsInfo.FlashLayoutMinorVersion)); */
2541  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x\n", ntohl(Adapter->psFlashCSInfo->MagicNumber));
2542 
2544  uiFlashLayoutMajorVersion = MAJOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion));
2546  } else {
2547  Adapter->uiFlashLayoutMinorVersion = 0;
2548  uiFlashLayoutMajorVersion = 0;
2549  }
2550 
2551  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FLASH LAYOUT MAJOR VERSION :%X", uiFlashLayoutMajorVersion);
2552 
2553  if (uiFlashLayoutMajorVersion < FLASH_2X_MAJOR_NUMBER) {
2554  BeceemFlashBulkRead(Adapter, (PUINT)Adapter->psFlashCSInfo, Adapter->ulFlashControlSectionStart, sizeof(FLASH_CS_INFO));
2555  ConvertEndianOfCSStructure(Adapter->psFlashCSInfo);
2557 
2558  if (!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
2560 
2565  Adapter->ulFlashWriteSize = (Adapter->psFlashCSInfo->FlashWriteSupportSize);
2566  Adapter->fpFlashWrite = flashByteWrite;
2567  Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus;
2568  } else {
2569  Adapter->ulFlashWriteSize = MAX_RW_SIZE;
2570  Adapter->fpFlashWrite = flashWrite;
2571  Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus;
2572  }
2573 
2574  BcmGetFlashSectorSize(Adapter, (Adapter->psFlashCSInfo->FlashSectorSizeSig),
2575  (Adapter->psFlashCSInfo->FlashSectorSize));
2576  Adapter->uiFlashBaseAdd = Adapter->psFlashCSInfo->FlashBaseAddr & 0xFCFFFFFF;
2577  } else {
2578  if (BcmFlash2xBulkRead(Adapter, (PUINT)Adapter->psFlash2xCSInfo, NO_SECTION_VAL,
2579  Adapter->ulFlashControlSectionStart, sizeof(FLASH2X_CS_INFO))) {
2580  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to read CS structure\n");
2581  return STATUS_FAILURE;
2582  }
2583 
2584  ConvertEndianOf2XCSStructure(Adapter->psFlash2xCSInfo);
2585  BcmDumpFlash2XCSStructure(Adapter->psFlash2xCSInfo, Adapter);
2591  Adapter->fpFlashWrite = flashByteWrite;
2592  Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus;
2593  } else {
2594  Adapter->ulFlashWriteSize = MAX_RW_SIZE;
2595  Adapter->fpFlashWrite = flashWrite;
2596  Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus;
2597  }
2598 
2599  BcmGetFlashSectorSize(Adapter, Adapter->psFlash2xCSInfo->FlashSectorSizeSig,
2600  Adapter->psFlash2xCSInfo->FlashSectorSize);
2601 
2602  UpdateVendorInfo(Adapter);
2603 
2604  BcmGetActiveDSD(Adapter);
2605  BcmGetActiveISO(Adapter);
2606  Adapter->uiFlashBaseAdd = Adapter->psFlash2xCSInfo->FlashBaseAddr & 0xFCFFFFFF;
2608  }
2609  /*
2610  * Concerns: what if CS sector size does not match with this sector size ???
2611  * what is the indication of AccessBitMap in CS in flash 2.x ????
2612  */
2613  Adapter->ulFlashID = BcmReadFlashRDID(Adapter);
2614  Adapter->uiFlashLayoutMajorVersion = uiFlashLayoutMajorVersion;
2615 
2616  return STATUS_SUCCESS;
2617 }
2618 
2619 /*
2620  * Procedure: BcmGetNvmType
2621  *
2622  * Description: Finds the type of NVM used.
2623  *
2624  * Arguments:
2625  * Adapter - ptr to Adapter object instance
2626  *
2627  * Returns:
2628  * NVM_TYPE
2629  *
2630  */
2631 
2632 static NVM_TYPE BcmGetNvmType(struct bcm_mini_adapter *Adapter)
2633 {
2634  unsigned int uiData = 0;
2635 
2636  BeceemEEPROMBulkRead(Adapter, &uiData, 0x0, 4);
2637  if (uiData == BECM)
2638  return NVM_EEPROM;
2639 
2640  /*
2641  * Read control struct and get cal addresses before accessing the flash
2642  */
2643  BcmGetFlashCSInfo(Adapter);
2644 
2645  BeceemFlashBulkRead(Adapter, &uiData, 0x0 + Adapter->ulFlashCalStart, 4);
2646  if (uiData == BECM)
2647  return NVM_FLASH;
2648 
2649  /*
2650  * even if there is no valid signature on EEPROM/FLASH find out if they really exist.
2651  * if exist select it.
2652  */
2653  if (BcmGetEEPROMSize(Adapter))
2654  return NVM_EEPROM;
2655 
2656  /* TBD for Flash. */
2657  return NVM_UNKNOWN;
2658 }
2659 
2660 /*
2661  * BcmGetSectionValStartOffset - this will calculate the section's starting offset if section val is given
2662  * @Adapter : Drivers Private Data structure
2663  * @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL
2664  *
2665  * Return value:-
2666  * On success it return the start offset of the provided section val
2667  * On Failure -returns STATUS_FAILURE
2668  */
2669 
2671 {
2672  /*
2673  * Considering all the section for which end offset can be calculated or directly given
2674  * in CS Structure. if matching case does not exist, return STATUS_FAILURE indicating section
2675  * endoffset can't be calculated or given in CS Structure.
2676  */
2677 
2678  int SectStartOffset = 0;
2679 
2680  SectStartOffset = INVALID_OFFSET;
2681 
2682  if (IsSectionExistInVendorInfo(Adapter, eFlashSectionVal))
2683  return Adapter->psFlash2xVendorInfo->VendorSection[eFlashSectionVal].OffsetFromZeroForSectionStart;
2684 
2685  switch (eFlashSectionVal) {
2686  case ISO_IMAGE1:
2688  (IsNonCDLessDevice(Adapter) == FALSE))
2689  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start);
2690  break;
2691  case ISO_IMAGE2:
2693  (IsNonCDLessDevice(Adapter) == FALSE))
2694  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start);
2695  break;
2696  case DSD0:
2698  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart);
2699  break;
2700  case DSD1:
2702  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start);
2703  break;
2704  case DSD2:
2706  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start);
2707  break;
2708  case VSA0:
2710  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart);
2711  break;
2712  case VSA1:
2714  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start);
2715  break;
2716  case VSA2:
2718  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start);
2719  break;
2720  case SCSI:
2722  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware);
2723  break;
2724  case CONTROL_SECTION:
2726  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart);
2727  break;
2728  case ISO_IMAGE1_PART2:
2730  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start);
2731  break;
2732  case ISO_IMAGE1_PART3:
2734  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start);
2735  break;
2736  case ISO_IMAGE2_PART2:
2738  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start);
2739  break;
2740  case ISO_IMAGE2_PART3:
2742  SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start);
2743  break;
2744  default:
2745  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x");
2746  SectStartOffset = INVALID_OFFSET;
2747  }
2748 
2749  return SectStartOffset;
2750 }
2751 
2752 /*
2753  * BcmGetSectionValEndOffset - this will calculate the section's Ending offset if section val is given
2754  * @Adapter : Drivers Private Data structure
2755  * @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL
2756  *
2757  * Return value:-
2758  * On success it return the end offset of the provided section val
2759  * On Failure -returns STATUS_FAILURE
2760  */
2761 
2762 int BcmGetSectionValEndOffset(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal)
2763 {
2764  int SectEndOffset = 0;
2765 
2766  SectEndOffset = INVALID_OFFSET;
2767  if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal))
2768  return Adapter->psFlash2xVendorInfo->VendorSection[eFlash2xSectionVal].OffsetFromZeroForSectionEnd;
2769 
2770  switch (eFlash2xSectionVal) {
2771  case ISO_IMAGE1:
2773  (IsNonCDLessDevice(Adapter) == FALSE))
2774  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End);
2775  break;
2776  case ISO_IMAGE2:
2778  (IsNonCDLessDevice(Adapter) == FALSE))
2779  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End);
2780  break;
2781  case DSD0:
2783  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd);
2784  break;
2785  case DSD1:
2787  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End);
2788  break;
2789  case DSD2:
2791  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End);
2792  break;
2793  case VSA0:
2795  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd);
2796  break;
2797  case VSA1:
2799  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End);
2800  break;
2801  case VSA2:
2803  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End);
2804  break;
2805  case SCSI:
2807  SectEndOffset = ((Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) +
2808  (Adapter->psFlash2xCSInfo->SizeOfScsiFirmware));
2809  break;
2810  case CONTROL_SECTION:
2811  /* Not Clear So Putting failure. confirm and fix it. */
2812  SectEndOffset = STATUS_FAILURE;
2813  case ISO_IMAGE1_PART2:
2815  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End);
2816  break;
2817  case ISO_IMAGE1_PART3:
2819  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End);
2820  break;
2821  case ISO_IMAGE2_PART2:
2823  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End);
2824  break;
2825  case ISO_IMAGE2_PART3:
2827  SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End);
2828  break;
2829  default:
2830  SectEndOffset = INVALID_OFFSET;
2831  }
2832 
2833  return SectEndOffset ;
2834 }
2835 
2836 /*
2837  * BcmFlash2xBulkRead:- Read API for Flash Map 2.x .
2838  * @Adapter :Driver Private Data Structure
2839  * @pBuffer : Buffer where data has to be put after reading
2840  * @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL
2841  * @uiOffsetWithinSectionVal :- Offset with in provided section
2842  * @uiNumBytes : Number of Bytes for Read
2843  *
2844  * Return value:-
2845  * return true on success and STATUS_FAILURE on fail.
2846  */
2847 
2849  PUINT pBuffer,
2850  FLASH2X_SECTION_VAL eFlash2xSectionVal,
2851  unsigned int uiOffsetWithinSectionVal,
2852  unsigned int uiNumBytes)
2853 {
2854  int Status = STATUS_SUCCESS;
2855  int SectionStartOffset = 0;
2856  unsigned int uiAbsoluteOffset = 0;
2857  unsigned int uiTemp = 0, value = 0;
2858 
2859  if (!Adapter) {
2860  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL");
2861  return -EINVAL;
2862  }
2863  if (Adapter->device_removed) {
2864  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed");
2865  return -ENODEV;
2866  }
2867 
2868  /* NO_SECTION_VAL means absolute offset is given. */
2869  if (eFlash2xSectionVal == NO_SECTION_VAL)
2870  SectionStartOffset = 0;
2871  else
2872  SectionStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
2873 
2874  if (SectionStartOffset == STATUS_FAILURE) {
2875  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exixt in Flash 2.x Map ", eFlash2xSectionVal);
2876  return -EINVAL;
2877  }
2878 
2879  if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal))
2880  return vendorextnReadSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectionVal, uiOffsetWithinSectionVal, uiNumBytes);
2881 
2882  /* calculating the absolute offset from FLASH; */
2883  uiAbsoluteOffset = uiOffsetWithinSectionVal + SectionStartOffset;
2884  rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
2885  value = 0;
2886  wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
2887  Status = BeceemFlashBulkRead(Adapter, pBuffer, uiAbsoluteOffset, uiNumBytes);
2888  wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
2889  if (Status) {
2890  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Read Failed with Status :%d", Status);
2891  return Status;
2892  }
2893 
2894  return Status;
2895 }
2896 
2897 /*
2898  * BcmFlash2xBulkWrite :-API for Writing on the Flash Map 2.x.
2899  * @Adapter :Driver Private Data Structure
2900  * @pBuffer : Buffer From where data has to taken for writing
2901  * @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL
2902  * @uiOffsetWithinSectionVal :- Offset with in provided section
2903  * @uiNumBytes : Number of Bytes for Write
2904  *
2905  * Return value:-
2906  * return true on success and STATUS_FAILURE on fail.
2907  *
2908  */
2909 
2911  PUINT pBuffer,
2912  FLASH2X_SECTION_VAL eFlash2xSectVal,
2913  unsigned int uiOffset,
2914  unsigned int uiNumBytes,
2915  unsigned int bVerify)
2916 {
2917  int Status = STATUS_SUCCESS;
2918  unsigned int FlashSectValStartOffset = 0;
2919  unsigned int uiTemp = 0, value = 0;
2920 
2921  if (!Adapter) {
2922  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL");
2923  return -EINVAL;
2924  }
2925 
2926  if (Adapter->device_removed) {
2927  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device has been removed");
2928  return -ENODEV;
2929  }
2930 
2931  /* NO_SECTION_VAL means absolute offset is given. */
2932  if (eFlash2xSectVal == NO_SECTION_VAL)
2933  FlashSectValStartOffset = 0;
2934  else
2935  FlashSectValStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectVal);
2936 
2937  if (FlashSectValStartOffset == STATUS_FAILURE) {
2938  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "This Section<%d> does not exixt in Flash Map 2.x", eFlash2xSectVal);
2939  return -EINVAL;
2940  }
2941 
2942  if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectVal))
2943  return vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectVal, uiOffset, uiNumBytes, bVerify);
2944 
2945  /* calculating the absolute offset from FLASH; */
2946  uiOffset = uiOffset + FlashSectValStartOffset;
2947 
2948  rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
2949  value = 0;
2950  wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
2951 
2952  Status = BeceemFlashBulkWrite(Adapter, pBuffer, uiOffset, uiNumBytes, bVerify);
2953 
2954  wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
2955  if (Status) {
2956  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Write failed with Status :%d", Status);
2957  return Status;
2958  }
2959 
2960  return Status;
2961 }
2962 
2963 /*
2964  * BcmGetActiveDSD : Set the Active DSD in Adapter Structure which has to be dumped in DDR
2965  * @Adapter :-Drivers private Data Structure
2966  *
2967  * Return Value:-
2968  * Return STATUS_SUCESS if get success in setting the right DSD else negaive error code
2969  *
2970  */
2971 
2972 static int BcmGetActiveDSD(struct bcm_mini_adapter *Adapter)
2973 {
2974  FLASH2X_SECTION_VAL uiHighestPriDSD = 0;
2975 
2976  uiHighestPriDSD = getHighestPriDSD(Adapter);
2977  Adapter->eActiveDSD = uiHighestPriDSD;
2978 
2979  if (DSD0 == uiHighestPriDSD)
2981  if (DSD1 == uiHighestPriDSD)
2983  if (DSD2 == uiHighestPriDSD)
2985  if (Adapter->eActiveDSD)
2986  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active DSD :%d", Adapter->eActiveDSD);
2987  if (Adapter->eActiveDSD == 0) {
2988  /* if No DSD gets Active, Make Active the DSD with WR permission */
2989  if (IsSectionWritable(Adapter, DSD2)) {
2990  Adapter->eActiveDSD = DSD2;
2992  } else if (IsSectionWritable(Adapter, DSD1)) {
2993  Adapter->eActiveDSD = DSD1;
2995  } else if (IsSectionWritable(Adapter, DSD0)) {
2996  Adapter->eActiveDSD = DSD0;
2998  }
2999  }
3000 
3001  return STATUS_SUCCESS;
3002 }
3003 
3004 /*
3005  * BcmGetActiveISO :- Set the Active ISO in Adapter Data Structue
3006  * @Adapter : Driver private Data Structure
3007  *
3008  * Return Value:-
3009  * Sucsess:- STATUS_SUCESS
3010  * Failure- : negative erro code
3011  *
3012  */
3013 
3014 static int BcmGetActiveISO(struct bcm_mini_adapter *Adapter)
3015 {
3016  int HighestPriISO = 0;
3017 
3018  HighestPriISO = getHighestPriISO(Adapter);
3019 
3020  Adapter->eActiveISO = HighestPriISO;
3021  if (Adapter->eActiveISO == ISO_IMAGE2)
3023  else if (Adapter->eActiveISO == ISO_IMAGE1)
3025 
3026  if (Adapter->eActiveISO)
3027  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active ISO :%x", Adapter->eActiveISO);
3028 
3029  return STATUS_SUCCESS;
3030 }
3031 
3032 /*
3033  * IsOffsetWritable :- it will tell the access permission of the sector having passed offset
3034  * @Adapter : Drivers Private Data Structure
3035  * @uiOffset : Offset provided in the Flash
3036  *
3037  * Return Value:-
3038  * Success:-TRUE , offset is writable
3039  * Failure:-FALSE, offset is RO
3040  *
3041  */
3042 
3043 B_UINT8 IsOffsetWritable(struct bcm_mini_adapter *Adapter, unsigned int uiOffset)
3044 {
3045  unsigned int uiSectorNum = 0;
3046  unsigned int uiWordOfSectorPermission = 0;
3047  unsigned int uiBitofSectorePermission = 0;
3048  B_UINT32 permissionBits = 0;
3049 
3050  uiSectorNum = uiOffset/Adapter->uiSectorSize;
3051 
3052  /* calculating the word having this Sector Access permission from SectorAccessBitMap Array */
3053  uiWordOfSectorPermission = Adapter->psFlash2xCSInfo->SectorAccessBitMap[uiSectorNum / 16];
3054 
3055  /* calculating the bit index inside the word for this sector */
3056  uiBitofSectorePermission = 2 * (15 - uiSectorNum % 16);
3057 
3058  /* Setting Access permission */
3059  permissionBits = uiWordOfSectorPermission & (0x3 << uiBitofSectorePermission);
3060  permissionBits = (permissionBits >> uiBitofSectorePermission) & 0x3;
3061  if (permissionBits == SECTOR_READWRITE_PERMISSION)
3062  return TRUE;
3063  else
3064  return FALSE;
3065 }
3066 
3067 static int BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap)
3068 {
3069  struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
3070 
3071  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "***************Flash 2.x Section Bitmap***************");
3072  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE1 :0X%x", psFlash2xBitMap->ISO_IMAGE1);
3073  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO_IMAGE2 :0X%x", psFlash2xBitMap->ISO_IMAGE2);
3074  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD0 :0X%x", psFlash2xBitMap->DSD0);
3075  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD1 :0X%x", psFlash2xBitMap->DSD1);
3076  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD2 :0X%x", psFlash2xBitMap->DSD2);
3077  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA0 :0X%x", psFlash2xBitMap->VSA0);
3078  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA1 :0X%x", psFlash2xBitMap->VSA1);
3079  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "VSA2 :0X%x", psFlash2xBitMap->VSA2);
3080  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSI :0X%x", psFlash2xBitMap->SCSI);
3081  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CONTROL_SECTION :0X%x", psFlash2xBitMap->CONTROL_SECTION);
3082 
3083  return STATUS_SUCCESS;
3084 }
3085 
3086 /*
3087  * BcmGetFlash2xSectionalBitMap :- It will provide the bit map of all the section present in Flash
3088  * 8bit has been assigned to every section.
3089  * bit[0] :Section present or not
3090  * bit[1] :section is valid or not
3091  * bit[2] : Secton is read only or has write permission too.
3092  * bit[3] : Active Section -
3093  * bit[7...4] = Reserved .
3094  *
3095  * @Adapter:-Driver private Data Structure
3096  *
3097  * Return value:-
3098  * Success:- STATUS_SUCESS
3099  * Failure:- negative error code
3100  */
3101 
3103 {
3104  PFLASH2X_CS_INFO psFlash2xCSInfo = Adapter->psFlash2xCSInfo;
3105  FLASH2X_SECTION_VAL uiHighestPriDSD = 0;
3106  FLASH2X_SECTION_VAL uiHighestPriISO = 0;
3107  BOOLEAN SetActiveDSDDone = FALSE;
3108  BOOLEAN SetActiveISODone = FALSE;
3109 
3110  /* For 1.x map all the section except DSD0 will be shown as not present
3111  * This part will be used by calibration tool to detect the number of DSD present in Flash.
3112  */
3113  if (IsFlash2x(Adapter) == FALSE) {
3114  psFlash2xBitMap->ISO_IMAGE2 = 0;
3115  psFlash2xBitMap->ISO_IMAGE1 = 0;
3116  psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; /* 0xF; 0000(Reseved)1(Active)0(RW)1(valid)1(present) */
3117  psFlash2xBitMap->DSD1 = 0;
3118  psFlash2xBitMap->DSD2 = 0;
3119  psFlash2xBitMap->VSA0 = 0;
3120  psFlash2xBitMap->VSA1 = 0;
3121  psFlash2xBitMap->VSA2 = 0;
3122  psFlash2xBitMap->CONTROL_SECTION = 0;
3123  psFlash2xBitMap->SCSI = 0;
3124  psFlash2xBitMap->Reserved0 = 0;
3125  psFlash2xBitMap->Reserved1 = 0;
3126  psFlash2xBitMap->Reserved2 = 0;
3127 
3128  return STATUS_SUCCESS;
3129  }
3130 
3131  uiHighestPriDSD = getHighestPriDSD(Adapter);
3132  uiHighestPriISO = getHighestPriISO(Adapter);
3133 
3134  /*
3135  * IS0 IMAGE 2
3136  */
3137  if ((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) {
3138  /* Setting the 0th Bit representing the Section is present or not. */
3139  psFlash2xBitMap->ISO_IMAGE2 = psFlash2xBitMap->ISO_IMAGE2 | FLASH2X_SECTION_PRESENT;
3140 
3141  if (ReadISOSignature(Adapter, ISO_IMAGE2) == ISO_IMAGE_MAGIC_NUMBER)
3142  psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_VALID;
3143 
3144  /* Calculation for extrating the Access permission */
3145  if (IsSectionWritable(Adapter, ISO_IMAGE2) == FALSE)
3146  psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_RO;
3147 
3148  if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE2) {
3149  psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_ACT;
3150  SetActiveISODone = TRUE;
3151  }
3152  }
3153 
3154  /*
3155  * IS0 IMAGE 1
3156  */
3157  if ((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) {
3158  /* Setting the 0th Bit representing the Section is present or not. */
3159  psFlash2xBitMap->ISO_IMAGE1 = psFlash2xBitMap->ISO_IMAGE1 | FLASH2X_SECTION_PRESENT;
3160 
3161  if (ReadISOSignature(Adapter, ISO_IMAGE1) == ISO_IMAGE_MAGIC_NUMBER)
3162  psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_VALID;
3163 
3164  /* Calculation for extrating the Access permission */
3165  if (IsSectionWritable(Adapter, ISO_IMAGE1) == FALSE)
3166  psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_RO;
3167 
3168  if (SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE1) {
3169  psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_ACT;
3170  SetActiveISODone = TRUE;
3171  }
3172  }
3173 
3174  /*
3175  * DSD2
3176  */
3177  if ((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) {
3178  /* Setting the 0th Bit representing the Section is present or not. */
3179  psFlash2xBitMap->DSD2 = psFlash2xBitMap->DSD2 | FLASH2X_SECTION_PRESENT;
3180 
3181  if (ReadDSDSignature(Adapter, DSD2) == DSD_IMAGE_MAGIC_NUMBER)
3182  psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_VALID;
3183 
3184  /* Calculation for extrating the Access permission */
3185  if (IsSectionWritable(Adapter, DSD2) == FALSE) {
3186  psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_RO;
3187  } else {
3188  /* Means section is writable */
3189  if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD2)) {
3190  psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT;
3191  SetActiveDSDDone = TRUE;
3192  }
3193  }
3194  }
3195 
3196  /*
3197  * DSD 1
3198  */
3199  if ((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) {
3200  /* Setting the 0th Bit representing the Section is present or not. */
3201  psFlash2xBitMap->DSD1 = psFlash2xBitMap->DSD1 | FLASH2X_SECTION_PRESENT;
3202 
3203  if (ReadDSDSignature(Adapter, DSD1) == DSD_IMAGE_MAGIC_NUMBER)
3204  psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_VALID;
3205 
3206  /* Calculation for extrating the Access permission */
3207  if (IsSectionWritable(Adapter, DSD1) == FALSE) {
3208  psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_RO;
3209  } else {
3210  /* Means section is writable */
3211  if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD1)) {
3212  psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT;
3213  SetActiveDSDDone = TRUE;
3214  }
3215  }
3216  }
3217 
3218  /*
3219  * For DSD 0
3220  */
3221  if ((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) {
3222  /* Setting the 0th Bit representing the Section is present or not. */
3223  psFlash2xBitMap->DSD0 = psFlash2xBitMap->DSD0 | FLASH2X_SECTION_PRESENT;
3224 
3225  if (ReadDSDSignature(Adapter, DSD0) == DSD_IMAGE_MAGIC_NUMBER)
3226  psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_VALID;
3227 
3228  /* Setting Access permission */
3229  if (IsSectionWritable(Adapter, DSD0) == FALSE) {
3230  psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_RO;
3231  } else {
3232  /* Means section is writable */
3233  if ((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD0)) {
3234  psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT;
3235  SetActiveDSDDone = TRUE;
3236  }
3237  }
3238  }
3239 
3240  /*
3241  * VSA 0
3242  */
3243  if ((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) {
3244  /* Setting the 0th Bit representing the Section is present or not. */
3245  psFlash2xBitMap->VSA0 = psFlash2xBitMap->VSA0 | FLASH2X_SECTION_PRESENT;
3246 
3247  /* Setting the Access Bit. Map is not defined hece setting it always valid */
3248  psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_VALID;
3249 
3250  /* Calculation for extrating the Access permission */
3251  if (IsSectionWritable(Adapter, VSA0) == FALSE)
3252  psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_RO;
3253 
3254  /* By Default section is Active */
3255  psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_ACT;
3256  }
3257 
3258  /*
3259  * VSA 1
3260  */
3261  if ((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) {
3262  /* Setting the 0th Bit representing the Section is present or not. */
3263  psFlash2xBitMap->VSA1 = psFlash2xBitMap->VSA1 | FLASH2X_SECTION_PRESENT;
3264 
3265  /* Setting the Access Bit. Map is not defined hece setting it always valid */
3266  psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_VALID;
3267 
3268  /* Checking For Access permission */
3269  if (IsSectionWritable(Adapter, VSA1) == FALSE)
3270  psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_RO;
3271 
3272  /* By Default section is Active */
3273  psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_ACT;
3274  }
3275 
3276  /*
3277  * VSA 2
3278  */
3279  if ((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) {
3280  /* Setting the 0th Bit representing the Section is present or not. */
3281  psFlash2xBitMap->VSA2 = psFlash2xBitMap->VSA2 | FLASH2X_SECTION_PRESENT;
3282 
3283  /* Setting the Access Bit. Map is not defined hece setting it always valid */
3284  psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_VALID;
3285 
3286  /* Checking For Access permission */
3287  if (IsSectionWritable(Adapter, VSA2) == FALSE)
3288  psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_RO;
3289 
3290  /* By Default section is Active */
3291  psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_ACT;
3292  }
3293 
3294  /*
3295  * SCSI Section
3296  */
3297  if ((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) {
3298  /* Setting the 0th Bit representing the Section is present or not. */
3299  psFlash2xBitMap->SCSI = psFlash2xBitMap->SCSI | FLASH2X_SECTION_PRESENT;
3300 
3301  /* Setting the Access Bit. Map is not defined hece setting it always valid */
3302  psFlash2xBitMap->SCSI |= FLASH2X_SECTION_VALID;
3303 
3304  /* Checking For Access permission */
3305  if (IsSectionWritable(Adapter, SCSI) == FALSE)
3306  psFlash2xBitMap->SCSI |= FLASH2X_SECTION_RO;
3307 
3308  /* By Default section is Active */
3309  psFlash2xBitMap->SCSI |= FLASH2X_SECTION_ACT;
3310  }
3311 
3312  /*
3313  * Control Section
3314  */
3315  if ((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) {
3316  /* Setting the 0th Bit representing the Section is present or not. */
3317  psFlash2xBitMap->CONTROL_SECTION = psFlash2xBitMap->CONTROL_SECTION | (FLASH2X_SECTION_PRESENT);
3318 
3319  /* Setting the Access Bit. Map is not defined hece setting it always valid */
3320  psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_VALID;
3321 
3322  /* Checking For Access permission */
3323  if (IsSectionWritable(Adapter, CONTROL_SECTION) == FALSE)
3324  psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_RO;
3325 
3326  /* By Default section is Active */
3327  psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_ACT;
3328  }
3329 
3330  /*
3331  * For Reserved Sections
3332  */
3333  psFlash2xBitMap->Reserved0 = 0;
3334  psFlash2xBitMap->Reserved0 = 0;
3335  psFlash2xBitMap->Reserved0 = 0;
3336  BcmDumpFlash2xSectionBitMap(psFlash2xBitMap);
3337 
3338  return STATUS_SUCCESS;
3339 }
3340 
3341 /*
3342  * BcmSetActiveSection :- Set Active section is used to make priority field highest over other
3343  * section of same type.
3344  *
3345  * @Adapater :- Bcm Driver Private Data Structure
3346  * @eFlash2xSectionVal :- Flash section val whose priority has to be made highest.
3347  *
3348  * Return Value:- Make the priorit highest else return erorr code
3349  *
3350  */
3351 
3352 int BcmSetActiveSection(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectVal)
3353 {
3354  unsigned int SectImagePriority = 0;
3355  int Status = STATUS_SUCCESS;
3356 
3357  /* DSD_HEADER sDSD = {0};
3358  * ISO_HEADER sISO = {0};
3359  */
3360  int HighestPriDSD = 0 ;
3361  int HighestPriISO = 0;
3362 
3363  Status = IsSectionWritable(Adapter, eFlash2xSectVal);
3364  if (Status != TRUE) {
3365  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section <%d> is not writable", eFlash2xSectVal);
3366  return STATUS_FAILURE;
3367  }
3368 
3369  Adapter->bHeaderChangeAllowed = TRUE;
3370  switch (eFlash2xSectVal) {
3371  case ISO_IMAGE1:
3372  case ISO_IMAGE2:
3373  if (ReadISOSignature(Adapter, eFlash2xSectVal) == ISO_IMAGE_MAGIC_NUMBER) {
3374  HighestPriISO = getHighestPriISO(Adapter);
3375 
3376  if (HighestPriISO == eFlash2xSectVal) {
3377  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal);
3378  Status = STATUS_SUCCESS;
3379  break;
3380  }
3381 
3382  SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1;
3383 
3384  if ((SectImagePriority <= 0) && IsSectionWritable(Adapter, HighestPriISO)) {
3385  /* This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF.
3386  * We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO
3387  * by user
3388  */
3389  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal);
3390  SectImagePriority = htonl(0x1);
3391  Status = BcmFlash2xBulkWrite(Adapter,
3392  &SectImagePriority,
3393  HighestPriISO,
3394  0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority),
3396  TRUE);
3397  if (Status) {
3398  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
3399  Status = STATUS_FAILURE;
3400  break;
3401  }
3402 
3403  HighestPriISO = getHighestPriISO(Adapter);
3404 
3405  if (HighestPriISO == eFlash2xSectVal) {
3406  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given ISO<%x> already has highest priority", eFlash2xSectVal);
3407  Status = STATUS_SUCCESS;
3408  break;
3409  }
3410 
3411  SectImagePriority = 2;
3412  }
3413 
3414  SectImagePriority = htonl(SectImagePriority);
3415 
3416  Status = BcmFlash2xBulkWrite(Adapter,
3417  &SectImagePriority,
3418  eFlash2xSectVal,
3419  0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority),
3421  TRUE);
3422  if (Status) {
3423  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
3424  break;
3425  }
3426  } else {
3427  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority");
3428  Status = STATUS_FAILURE;
3429  break;
3430  }
3431  break;
3432  case DSD0:
3433  case DSD1:
3434  case DSD2:
3435  if (ReadDSDSignature(Adapter, eFlash2xSectVal) == DSD_IMAGE_MAGIC_NUMBER) {
3436  HighestPriDSD = getHighestPriDSD(Adapter);
3437  if ((HighestPriDSD == eFlash2xSectVal)) {
3438  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given DSD<%x> already has highest priority", eFlash2xSectVal);
3439  Status = STATUS_SUCCESS;
3440  break;
3441  }
3442 
3443  SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1;
3444  if (SectImagePriority <= 0) {
3445  /* This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF.
3446  * We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD
3447  * by user
3448  */
3449  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n", eFlash2xSectVal);
3450  SectImagePriority = htonl(0x1);
3451 
3452  Status = BcmFlash2xBulkWrite(Adapter,
3453  &SectImagePriority,
3454  HighestPriDSD,
3457  TRUE);
3458  if (Status) {
3459  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
3460  break;
3461  }
3462 
3463  HighestPriDSD = getHighestPriDSD(Adapter);
3464 
3465  if ((HighestPriDSD == eFlash2xSectVal)) {
3466  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Made the DSD: %x highest by reducing priority of other\n", eFlash2xSectVal);
3467  Status = STATUS_SUCCESS;
3468  break;
3469  }
3470 
3471  SectImagePriority = htonl(0x2);
3472  Status = BcmFlash2xBulkWrite(Adapter,
3473  &SectImagePriority,
3474  HighestPriDSD,
3477  TRUE);
3478  if (Status) {
3479  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
3480  break;
3481  }
3482 
3483  HighestPriDSD = getHighestPriDSD(Adapter);
3484  if ((HighestPriDSD == eFlash2xSectVal)) {
3485  Status = STATUS_SUCCESS;
3486  break;
3487  }
3488 
3489  SectImagePriority = 3;
3490  }
3491  SectImagePriority = htonl(SectImagePriority);
3492  Status = BcmFlash2xBulkWrite(Adapter,
3493  &SectImagePriority,
3494  eFlash2xSectVal,
3497  TRUE);
3498  if (Status) {
3499  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly");
3500  Status = STATUS_FAILURE;
3501  break;
3502  }
3503  } else {
3504  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority");
3505  Status = STATUS_FAILURE;
3506  break;
3507  }
3508  break;
3509  case VSA0:
3510  case VSA1:
3511  case VSA2:
3512  /* Has to be decided */
3513  break;
3514  default:
3515  Status = STATUS_FAILURE;
3516  break;
3517  }
3518 
3519  Adapter->bHeaderChangeAllowed = FALSE;
3520  return Status;
3521 }
3522 
3523 /*
3524  * BcmCopyISO - Used only for copying the ISO section
3525  * @Adapater :- Bcm Driver Private Data Structure
3526  * @sCopySectStrut :- Section copy structure
3527  *
3528  * Return value:- SUCCESS if copies successfully else negative error code
3529  *
3530  */
3531 
3532 int BcmCopyISO(struct bcm_mini_adapter *Adapter, FLASH2X_COPY_SECTION sCopySectStrut)
3533 {
3534  PCHAR Buff = NULL;
3535  FLASH2X_SECTION_VAL eISOReadPart = 0, eISOWritePart = 0;
3536  unsigned int uiReadOffsetWithinPart = 0, uiWriteOffsetWithinPart = 0;
3537  unsigned int uiTotalDataToCopy = 0;
3538  BOOLEAN IsThisHeaderSector = FALSE;
3539  unsigned int sigOffset = 0;
3540  unsigned int ISOLength = 0;
3541  unsigned int Status = STATUS_SUCCESS;
3542  unsigned int SigBuff[MAX_RW_SIZE];
3543  unsigned int i = 0;
3544 
3545  if (ReadISOSignature(Adapter, sCopySectStrut.SrcSection) != ISO_IMAGE_MAGIC_NUMBER) {
3546  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature");
3547  return STATUS_FAILURE;
3548  }
3549 
3550  Status = BcmFlash2xBulkRead(Adapter,
3551  &ISOLength,
3552  sCopySectStrut.SrcSection,
3553  0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageSize),
3554  4);
3555  if (Status) {
3556  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO\n");
3557  return Status;
3558  }
3559 
3560  ISOLength = htonl(ISOLength);
3561  if (ISOLength % Adapter->uiSectorSize)
3562  ISOLength = Adapter->uiSectorSize * (1 + ISOLength/Adapter->uiSectorSize);
3563 
3564  sigOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber);
3565 
3566  Buff = kzalloc(Adapter->uiSectorSize, GFP_KERNEL);
3567 
3568  if (!Buff) {
3569  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for section size");
3570  return -ENOMEM;
3571  }
3572 
3573  if (sCopySectStrut.SrcSection == ISO_IMAGE1 && sCopySectStrut.DstSection == ISO_IMAGE2) {
3574  eISOReadPart = ISO_IMAGE1;
3575  eISOWritePart = ISO_IMAGE2;
3576  uiReadOffsetWithinPart = 0;
3577  uiWriteOffsetWithinPart = 0;
3578 
3579  uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) -
3585 
3586  if (uiTotalDataToCopy < ISOLength) {
3587  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature");
3588  Status = STATUS_FAILURE;
3589  goto out;
3590  }
3591 
3592  uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) -
3598 
3599  if (uiTotalDataToCopy < ISOLength) {
3600  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size");
3601  Status = STATUS_FAILURE;
3602  goto out;
3603  }
3604 
3605  uiTotalDataToCopy = ISOLength;
3606 
3607  CorruptISOSig(Adapter, ISO_IMAGE2);
3608  while (uiTotalDataToCopy) {
3609  if (uiTotalDataToCopy == Adapter->uiSectorSize) {
3610  /* Setting for write of first sector. First sector is assumed to be written in last */
3611  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector");
3612  eISOReadPart = ISO_IMAGE1;
3613  uiReadOffsetWithinPart = 0;
3614  eISOWritePart = ISO_IMAGE2;
3615  uiWriteOffsetWithinPart = 0;
3616  IsThisHeaderSector = TRUE;
3617  } else {
3618  uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize;
3619  uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize;
3620 
3621  if ((eISOReadPart == ISO_IMAGE1) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) {
3622  eISOReadPart = ISO_IMAGE1_PART2;
3623  uiReadOffsetWithinPart = 0;
3624  }
3625 
3626  if ((eISOReadPart == ISO_IMAGE1_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) {
3627  eISOReadPart = ISO_IMAGE1_PART3;
3628  uiReadOffsetWithinPart = 0;
3629  }
3630 
3631  if ((eISOWritePart == ISO_IMAGE2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) {
3632  eISOWritePart = ISO_IMAGE2_PART2;
3633  uiWriteOffsetWithinPart = 0;
3634  }
3635 
3636  if ((eISOWritePart == ISO_IMAGE2_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) {
3637  eISOWritePart = ISO_IMAGE2_PART3;
3638  uiWriteOffsetWithinPart = 0;
3639  }
3640  }
3641 
3642  Status = BcmFlash2xBulkRead(Adapter,
3643  (PUINT)Buff,
3644  eISOReadPart,
3645  uiReadOffsetWithinPart,
3646  Adapter->uiSectorSize);
3647  if (Status) {
3648  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart);
3649  break;
3650  }
3651 
3652  if (IsThisHeaderSector == TRUE) {
3653  /* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */
3654  memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE);
3655 
3656  for (i = 0; i < MAX_RW_SIZE; i++)
3657  *(Buff + sigOffset + i) = 0xFF;
3658  }
3659  Adapter->bHeaderChangeAllowed = TRUE;
3660  Status = BcmFlash2xBulkWrite(Adapter,
3661  (PUINT)Buff,
3662  eISOWritePart,
3663  uiWriteOffsetWithinPart,
3664  Adapter->uiSectorSize,
3665  TRUE);
3666  if (Status) {
3667  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart);
3668  break;
3669  }
3670 
3671  Adapter->bHeaderChangeAllowed = FALSE;
3672  if (IsThisHeaderSector == TRUE) {
3673  WriteToFlashWithoutSectorErase(Adapter,
3674  SigBuff,
3675  eISOWritePart,
3676  sigOffset,
3677  MAX_RW_SIZE);
3678  IsThisHeaderSector = FALSE;
3679  }
3680  /* subtracting the written Data */
3681  uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize;
3682  }
3683  }
3684 
3685  if (sCopySectStrut.SrcSection == ISO_IMAGE2 && sCopySectStrut.DstSection == ISO_IMAGE1) {
3686  eISOReadPart = ISO_IMAGE2;
3687  eISOWritePart = ISO_IMAGE1;
3688  uiReadOffsetWithinPart = 0;
3689  uiWriteOffsetWithinPart = 0;
3690 
3691  uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) -
3697 
3698  if (uiTotalDataToCopy < ISOLength) {
3699  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature");
3700  Status = STATUS_FAILURE;
3701  goto out;
3702  }
3703 
3704  uiTotalDataToCopy = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) -
3710 
3711  if (uiTotalDataToCopy < ISOLength) {
3712  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "error as Dest ISO Section does not have enough section size");
3713  Status = STATUS_FAILURE;
3714  goto out;
3715  }
3716 
3717  uiTotalDataToCopy = ISOLength;
3718 
3719  CorruptISOSig(Adapter, ISO_IMAGE1);
3720 
3721  while (uiTotalDataToCopy) {
3722  if (uiTotalDataToCopy == Adapter->uiSectorSize) {
3723  /* Setting for write of first sector. First sector is assumed to be written in last */
3724  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Writing the signature sector");
3725  eISOReadPart = ISO_IMAGE2;
3726  uiReadOffsetWithinPart = 0;
3727  eISOWritePart = ISO_IMAGE1;
3728  uiWriteOffsetWithinPart = 0;
3729  IsThisHeaderSector = TRUE;
3730  } else {
3731  uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize;
3732  uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize;
3733 
3734  if ((eISOReadPart == ISO_IMAGE2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) {
3735  eISOReadPart = ISO_IMAGE2_PART2;
3736  uiReadOffsetWithinPart = 0;
3737  }
3738 
3739  if ((eISOReadPart == ISO_IMAGE2_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) {
3740  eISOReadPart = ISO_IMAGE2_PART3;
3741  uiReadOffsetWithinPart = 0;
3742  }
3743 
3744  if ((eISOWritePart == ISO_IMAGE1) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) {
3745  eISOWritePart = ISO_IMAGE1_PART2;
3746  uiWriteOffsetWithinPart = 0;
3747  }
3748 
3749  if ((eISOWritePart == ISO_IMAGE1_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) {
3750  eISOWritePart = ISO_IMAGE1_PART3;
3751  uiWriteOffsetWithinPart = 0;
3752  }
3753  }
3754 
3755  Status = BcmFlash2xBulkRead(Adapter,
3756  (PUINT)Buff,
3757  eISOReadPart,
3758  uiReadOffsetWithinPart,
3759  Adapter->uiSectorSize);
3760  if (Status) {
3761  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart);
3762  break;
3763  }
3764 
3765  if (IsThisHeaderSector == TRUE) {
3766  /* If this is header sector write 0xFFFFFFFF at the sig time and in last write sig */
3767  memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE);
3768 
3769  for (i = 0; i < MAX_RW_SIZE; i++)
3770  *(Buff + sigOffset + i) = 0xFF;
3771  }
3772  Adapter->bHeaderChangeAllowed = TRUE;
3773  Status = BcmFlash2xBulkWrite(Adapter,
3774  (PUINT)Buff,
3775  eISOWritePart,
3776  uiWriteOffsetWithinPart,
3777  Adapter->uiSectorSize,
3778  TRUE);
3779  if (Status) {
3780  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart);
3781  break;
3782  }
3783 
3784  Adapter->bHeaderChangeAllowed = FALSE;
3785  if (IsThisHeaderSector == TRUE) {
3786  WriteToFlashWithoutSectorErase(Adapter,
3787  SigBuff,
3788  eISOWritePart,
3789  sigOffset,
3790  MAX_RW_SIZE);
3791 
3792  IsThisHeaderSector = FALSE;
3793  }
3794 
3795  /* subtracting the written Data */
3796  uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize;
3797  }
3798  }
3799 out:
3800  kfree(Buff);
3801 
3802  return Status;
3803 }
3804 
3805 /*
3806  * BcmFlash2xCorruptSig : this API is used to corrupt the written sig in Bcm Header present in flash section.
3807  * It will corrupt the sig, if Section is writable, by making first bytes as zero.
3808  * @Adapater :- Bcm Driver Private Data Structure
3809  * @eFlash2xSectionVal :- Flash section val which has header
3810  *
3811  * Return Value :-
3812  * Success :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS
3813  * Failure :-Return negative error code
3814  */
3815 
3816 int BcmFlash2xCorruptSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal)
3817 {
3818  int Status = STATUS_SUCCESS;
3819 
3820  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Value :%x\n", eFlash2xSectionVal);
3821 
3822  if ((eFlash2xSectionVal == DSD0) || (eFlash2xSectionVal == DSD1) || (eFlash2xSectionVal == DSD2)) {
3823  Status = CorruptDSDSig(Adapter, eFlash2xSectionVal);
3824  } else if (eFlash2xSectionVal == ISO_IMAGE1 || eFlash2xSectionVal == ISO_IMAGE2) {
3825  Status = CorruptISOSig(Adapter, eFlash2xSectionVal);
3826  } else {
3827  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Given Section <%d>does not have Header", eFlash2xSectionVal);
3828  return STATUS_SUCCESS;
3829  }
3830  return Status;
3831 }
3832 
3833 /*
3834  *BcmFlash2xWriteSig :-this API is used to Write the sig if requested Section has
3835  * header and Write Permission.
3836  * @Adapater :- Bcm Driver Private Data Structure
3837  * @eFlashSectionVal :- Flash section val which has header
3838  *
3839  * Return Value :-
3840  * Success :- If Section is present and writable write the sig and return STATUS_SUCCESS
3841  * Failure :-Return negative error code
3842  */
3843 
3844 int BcmFlash2xWriteSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlashSectionVal)
3845 {
3846  unsigned int uiSignature = 0;
3847  unsigned int uiOffset = 0;
3848 
3849  /* DSD_HEADER dsdHeader = {0}; */
3850  if (Adapter->bSigCorrupted == FALSE) {
3851  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is not corrupted by driver, hence not restoring\n");
3852  return STATUS_SUCCESS;
3853  }
3854 
3855  if (Adapter->bAllDSDWriteAllow == FALSE) {
3856  if (IsSectionWritable(Adapter, eFlashSectionVal) == FALSE) {
3857  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Write signature");
3858  return SECTOR_IS_NOT_WRITABLE;
3859  }
3860  }
3861 
3862  if ((eFlashSectionVal == DSD0) || (eFlashSectionVal == DSD1) || (eFlashSectionVal == DSD2)) {
3863  uiSignature = htonl(DSD_IMAGE_MAGIC_NUMBER);
3864  uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader;
3865 
3866  uiOffset += FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImageMagicNumber);
3867 
3868  if ((ReadDSDSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) {
3869  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Corrupted Pattern is not there. Hence won't write sig");
3870  return STATUS_FAILURE;
3871  }
3872  } else if ((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) {
3873  uiSignature = htonl(ISO_IMAGE_MAGIC_NUMBER);
3874  /* uiOffset = 0; */
3875  uiOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber);
3876  if ((ReadISOSignature(Adapter, eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) {
3877  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Currupted Pattern is not there. Hence won't write sig");
3878  return STATUS_FAILURE;
3879  }
3880  } else {
3881  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "GIVEN SECTION< %d > IS NOT VALID FOR SIG WRITE...", eFlashSectionVal);
3882  return STATUS_FAILURE;
3883  }
3884 
3885  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature");
3886 
3887  Adapter->bHeaderChangeAllowed = TRUE;
3888  Adapter->bSigCorrupted = FALSE;
3889  BcmFlash2xBulkWrite(Adapter, &uiSignature, eFlashSectionVal, uiOffset, SIGNATURE_SIZE, TRUE);
3890  Adapter->bHeaderChangeAllowed = FALSE;
3891 
3892  return STATUS_SUCCESS;
3893 }
3894 
3895 /*
3896  * validateFlash2xReadWrite :- This API is used to validate the user request for Read/Write.
3897  * if requested Bytes goes beyond the Requested section, it reports error.
3898  * @Adapater :- Bcm Driver Private Data Structure
3899  * @psFlash2xReadWrite :-Flash2x Read/write structure pointer
3900  *
3901  * Return values:-Return TRUE is request is valid else FALSE.
3902  */
3903 
3904 int validateFlash2xReadWrite(struct bcm_mini_adapter *Adapter, PFLASH2X_READWRITE psFlash2xReadWrite)
3905 {
3906  unsigned int uiNumOfBytes = 0;
3907  unsigned int uiSectStartOffset = 0;
3908  unsigned int uiSectEndOffset = 0;
3909 
3910  uiNumOfBytes = psFlash2xReadWrite->numOfBytes;
3911 
3912  if (IsSectionExistInFlash(Adapter, psFlash2xReadWrite->Section) != TRUE) {
3913  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%x> does not exixt in Flash", psFlash2xReadWrite->Section);
3914  return FALSE;
3915  }
3916  uiSectStartOffset = BcmGetSectionValStartOffset(Adapter, psFlash2xReadWrite->Section);
3917  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Start offset :%x ,section :%d\n", uiSectStartOffset, psFlash2xReadWrite->Section);
3918  if ((psFlash2xReadWrite->Section == ISO_IMAGE1) || (psFlash2xReadWrite->Section == ISO_IMAGE2)) {
3919  if (psFlash2xReadWrite->Section == ISO_IMAGE1) {
3920  uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1) -
3922  BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART2) -
3924  BcmGetSectionValEndOffset(Adapter, ISO_IMAGE1_PART3) -
3926  } else if (psFlash2xReadWrite->Section == ISO_IMAGE2) {
3927  uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2) -
3929  BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART2) -
3931  BcmGetSectionValEndOffset(Adapter, ISO_IMAGE2_PART3) -
3933  }
3934 
3935  /* since this uiSectEndoffset is the size of iso Image. hence for calculating the virtual endoffset
3936  * it should be added in startoffset. so that check done in last of this function can be valued.
3937  */
3938  uiSectEndOffset = uiSectStartOffset + uiSectEndOffset;
3939 
3940  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Total size of the ISO Image :%x", uiSectEndOffset);
3941  } else
3942  uiSectEndOffset = BcmGetSectionValEndOffset(Adapter, psFlash2xReadWrite->Section);
3943 
3944  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "End offset :%x\n", uiSectEndOffset);
3945 
3946  /* Checking the boundary condition */
3947  if ((uiSectStartOffset + psFlash2xReadWrite->offset + uiNumOfBytes) <= uiSectEndOffset)
3948  return TRUE;
3949  else {
3950  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid Request....");
3951  return FALSE;
3952  }
3953 }
3954 
3955 /*
3956  * IsFlash2x :- check for Flash 2.x
3957  * Adapater :- Bcm Driver Private Data Structure
3958  *
3959  * Return value:-
3960  * return TRUE if flah2.x of hgher version else return false.
3961  */
3962 
3963 int IsFlash2x(struct bcm_mini_adapter *Adapter)
3964 {
3966  return TRUE;
3967  else
3968  return FALSE;
3969 }
3970 
3971 /*
3972  * GetFlashBaseAddr :- Calculate the Flash Base address
3973  * @Adapater :- Bcm Driver Private Data Structure
3974  *
3975  * Return Value:-
3976  * Success :- Base Address of the Flash
3977  */
3978 
3979 static int GetFlashBaseAddr(struct bcm_mini_adapter *Adapter)
3980 {
3981  unsigned int uiBaseAddr = 0;
3982 
3983  if (Adapter->bDDRInitDone) {
3984  /*
3985  * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr
3986  * In case of Raw Read... use the default value
3987  */
3988  if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) &&
3989  !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
3990  uiBaseAddr = Adapter->uiFlashBaseAdd;
3991  else
3993  } else {
3994  /*
3995  * For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr
3996  * In case of Raw Read... use the default value
3997  */
3998  if (Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) &&
3999  !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)))
4001  else
4003  }
4004 
4005  return uiBaseAddr;
4006 }
4007 
4008 /*
4009  * BcmCopySection :- This API is used to copy the One section in another. Both section should
4010  * be contiuous and of same size. Hence this Will not be applicabe to copy ISO.
4011  *
4012  * @Adapater :- Bcm Driver Private Data Structure
4013  * @SrcSection :- Source section From where data has to be copied
4014  * @DstSection :- Destination section to which data has to be copied
4015  * @offset :- Offset from/to where data has to be copied from one section to another.
4016  * @numOfBytes :- number of byes that has to be copyed from one section to another at given offset.
4017  * in case of numofBytes equal zero complete section will be copied.
4018  * Return Values-
4019  * Success : Return STATUS_SUCCESS
4020  * Faillure :- return negative error code
4021  */
4022 
4023 int BcmCopySection(struct bcm_mini_adapter *Adapter,
4024  FLASH2X_SECTION_VAL SrcSection,
4025  FLASH2X_SECTION_VAL DstSection,
4026  unsigned int offset,
4027  unsigned int numOfBytes)
4028 {
4029  unsigned int BuffSize = 0;
4030  unsigned int BytesToBeCopied = 0;
4031  PUCHAR pBuff = NULL;
4032  int Status = STATUS_SUCCESS;
4033 
4034  if (SrcSection == DstSection) {
4035  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source and Destination should be different ...try again");
4036  return -EINVAL;
4037  }
4038 
4039  if ((SrcSection != DSD0) && (SrcSection != DSD1) && (SrcSection != DSD2)) {
4040  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source should be DSD subsection");
4041  return -EINVAL;
4042  }
4043 
4044  if ((DstSection != DSD0) && (DstSection != DSD1) && (DstSection != DSD2)) {
4045  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destination should be DSD subsection");
4046  return -EINVAL;
4047  }
4048 
4049  /* if offset zero means have to copy complete secton */
4050  if (numOfBytes == 0) {
4051  numOfBytes = BcmGetSectionValEndOffset(Adapter, SrcSection)
4052  - BcmGetSectionValStartOffset(Adapter, SrcSection);
4053 
4054  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Section Size :0x%x", numOfBytes);
4055  }
4056 
4057  if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, SrcSection)
4058  - BcmGetSectionValStartOffset(Adapter, SrcSection)) {
4059  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " Input parameters going beyond the section offS: %x numB: %x of Source Section\n",
4060  offset, numOfBytes);
4061  return -EINVAL;
4062  }
4063 
4064  if ((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter, DstSection)
4065  - BcmGetSectionValStartOffset(Adapter, DstSection)) {
4066  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Input parameters going beyond the section offS: %x numB: %x of Destination Section\n",
4067  offset, numOfBytes);
4068  return -EINVAL;
4069  }
4070 
4071  if (numOfBytes > Adapter->uiSectorSize)
4072  BuffSize = Adapter->uiSectorSize;
4073  else
4074  BuffSize = numOfBytes;
4075 
4076  pBuff = (PCHAR)kzalloc(BuffSize, GFP_KERNEL);
4077  if (!pBuff) {
4078  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed.. ");
4079  return -ENOMEM;
4080  }
4081 
4082  BytesToBeCopied = Adapter->uiSectorSize;
4083  if (offset % Adapter->uiSectorSize)
4084  BytesToBeCopied = Adapter->uiSectorSize - (offset % Adapter->uiSectorSize);
4085  if (BytesToBeCopied > numOfBytes)
4086  BytesToBeCopied = numOfBytes;
4087 
4088  Adapter->bHeaderChangeAllowed = TRUE;
4089 
4090  do {
4091  Status = BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, SrcSection , offset, BytesToBeCopied);
4092  if (Status) {
4093  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read failed at offset :%d for NOB :%d", SrcSection, BytesToBeCopied);
4094  break;
4095  }
4096  Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pBuff, DstSection, offset, BytesToBeCopied, FALSE);
4097  if (Status) {
4098  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Write failed at offset :%d for NOB :%d", DstSection, BytesToBeCopied);
4099  break;
4100  }
4101  offset = offset + BytesToBeCopied;
4102  numOfBytes = numOfBytes - BytesToBeCopied;
4103  if (numOfBytes) {
4104  if (numOfBytes > Adapter->uiSectorSize)
4105  BytesToBeCopied = Adapter->uiSectorSize;
4106  else
4107  BytesToBeCopied = numOfBytes;
4108  }
4109  } while (numOfBytes > 0);
4110 
4111  kfree(pBuff);
4112  Adapter->bHeaderChangeAllowed = FALSE;
4113 
4114  return Status;
4115 }
4116 
4117 /*
4118  * SaveHeaderIfPresent :- This API is use to Protect the Header in case of Header Sector write
4119  * @Adapater :- Bcm Driver Private Data Structure
4120  * @pBuff :- Data buffer that has to be written in sector having the header map.
4121  * @uiOffset :- Flash offset that has to be written.
4122  *
4123  * Return value :-
4124  * Success :- On success return STATUS_SUCCESS
4125  * Faillure :- Return negative error code
4126  */
4127 
4128 int SaveHeaderIfPresent(struct bcm_mini_adapter *Adapter, PUCHAR pBuff, unsigned int uiOffset)
4129 {
4130  unsigned int offsetToProtect = 0, HeaderSizeToProtect = 0;
4131  BOOLEAN bHasHeader = FALSE;
4132  PUCHAR pTempBuff = NULL;
4133  unsigned int uiSectAlignAddr = 0;
4134  unsigned int sig = 0;
4135 
4136  /* making the offset sector aligned */
4137  uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);
4138 
4139  if ((uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD2) - Adapter->uiSectorSize) ||
4140  (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD1) - Adapter->uiSectorSize) ||
4141  (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter, DSD0) - Adapter->uiSectorSize)) {
4142  /* offset from the sector boundary having the header map */
4143  offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize;
4144  HeaderSizeToProtect = sizeof(DSD_HEADER);
4145  bHasHeader = TRUE;
4146  }
4147 
4148  if (uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE1) ||
4149  uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2)) {
4150  offsetToProtect = 0;
4151  HeaderSizeToProtect = sizeof(ISO_HEADER);
4152  bHasHeader = TRUE;
4153  }
4154  /* If Header is present overwrite passed buffer with this */
4155  if (bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) {
4156  pTempBuff = (PUCHAR)kzalloc(HeaderSizeToProtect, GFP_KERNEL);
4157  if (!pTempBuff) {
4158  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed");
4159  return -ENOMEM;
4160  }
4161  /* Read header */
4162  BeceemFlashBulkRead(Adapter, (PUINT)pTempBuff, (uiSectAlignAddr + offsetToProtect), HeaderSizeToProtect);
4163  BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pTempBuff, HeaderSizeToProtect);
4164  /* Replace Buffer content with Header */
4165  memcpy(pBuff + offsetToProtect, pTempBuff, HeaderSizeToProtect);
4166 
4167  kfree(pTempBuff);
4168  }
4169  if (bHasHeader && Adapter->bSigCorrupted) {
4170  sig = *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImageMagicNumber)));
4171  sig = ntohl(sig);
4172  if ((sig & 0xFF000000) != CORRUPTED_PATTERN) {
4173  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Desired pattern is not at sig offset. Hence won't restore");
4174  Adapter->bSigCorrupted = FALSE;
4175  return STATUS_SUCCESS;
4176  }
4177  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Corrupted sig is :%X", sig);
4178  *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImageMagicNumber))) = htonl(DSD_IMAGE_MAGIC_NUMBER);
4179  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Restoring the signature in Header Write only");
4180  Adapter->bSigCorrupted = FALSE;
4181  }
4182 
4183  return STATUS_SUCCESS;
4184 }
4185 
4186 /*
4187  * BcmDoChipSelect : This will selcet the appropriate chip for writing.
4188  * @Adapater :- Bcm Driver Private Data Structure
4189  *
4190  * OutPut:-
4191  * Select the Appropriate chip and retrn status Success
4192  */
4193 static int BcmDoChipSelect(struct bcm_mini_adapter *Adapter, unsigned int offset)
4194 {
4195  unsigned int FlashConfig = 0;
4196  int ChipNum = 0;
4197  unsigned int GPIOConfig = 0;
4198  unsigned int PartNum = 0;
4199 
4200  ChipNum = offset / FLASH_PART_SIZE;
4201 
4202  /*
4203  * Chip Select mapping to enable flash0.
4204  * To select flash 0, we have to OR with (0<<12).
4205  * ORing 0 will have no impact so not doing that part.
4206  * In future if Chip select value changes from 0 to non zero,
4207  * That needs be taken care with backward comaptibility. No worries for now.
4208  */
4209 
4210  /*
4211  * SelectedChip Variable is the selection that the host is 100% Sure the same as what the register will hold. This can be ONLY ensured
4212  * if the Chip doesn't goes to low power mode while the flash operation is in progress (NVMRdmWrmLock is taken)
4213  * Before every new Flash Write operation, we reset the variable. This is to ensure that after any wake-up from
4214  * power down modes (Idle mode/shutdown mode), the values in the register will be different.
4215  */
4216 
4217  if (Adapter->SelectedChip == ChipNum)
4218  return STATUS_SUCCESS;
4219 
4220  /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Selected Chip :%x", ChipNum); */
4221  Adapter->SelectedChip = ChipNum;
4222 
4223  /* bit[13..12] will select the appropriate chip */
4224  rdmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4);
4225  rdmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4);
4226  {
4227  switch (ChipNum) {
4228  case 0:
4229  PartNum = 0;
4230  break;
4231  case 1:
4232  PartNum = 3;
4233  GPIOConfig |= (0x4 << CHIP_SELECT_BIT12);
4234  break;
4235  case 2:
4236  PartNum = 1;
4237  GPIOConfig |= (0x1 << CHIP_SELECT_BIT12);
4238  break;
4239  case 3:
4240  PartNum = 2;
4241  GPIOConfig |= (0x2 << CHIP_SELECT_BIT12);
4242  break;
4243  }
4244  }
4245  /* In case the bits already written in the FLASH_CONFIG_REG is same as what the user desired,
4246  * nothing to do... can return immediately.
4247  * ASSUMPTION: FLASH_GPIO_CONFIG_REG will be in sync with FLASH_CONFIG_REG.
4248  * Even if the chip goes to low power mode, it should wake with values in each register in sync with each other.
4249  * These values are not written by host other than during CHIP_SELECT.
4250  */
4251  if (PartNum == ((FlashConfig >> CHIP_SELECT_BIT12) & 0x3))
4252  return STATUS_SUCCESS;
4253 
4254  /* clearing the bit[13..12] */
4255  FlashConfig &= 0xFFFFCFFF;
4256  FlashConfig = (FlashConfig | (PartNum<<CHIP_SELECT_BIT12)); /* 00 */
4257 
4258  wrmalt(Adapter, FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4);
4259  udelay(100);
4260 
4261  wrmalt(Adapter, FLASH_CONFIG_REG, &FlashConfig, 4);
4262  udelay(100);
4263 
4264  return STATUS_SUCCESS;
4265 }
4266 
4267 int ReadDSDSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd)
4268 {
4269  unsigned int uiDSDsig = 0;
4270  /* unsigned int sigoffsetInMap = 0;
4271  * DSD_HEADER dsdHeader = {0};
4272  */
4273 
4274  /* sigoffsetInMap =(PUCHAR)&(dsdHeader.DSDImageMagicNumber) -(PUCHAR)&dsdHeader; */
4275 
4276  if (dsd != DSD0 && dsd != DSD1 && dsd != DSD2) {
4277  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for DSDs");
4278  return STATUS_FAILURE;
4279  }
4280  BcmFlash2xBulkRead(Adapter,
4281  &uiDSDsig,
4282  dsd,
4284  SIGNATURE_SIZE);
4285 
4286  uiDSDsig = ntohl(uiDSDsig);
4287  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD SIG :%x", uiDSDsig);
4288 
4289  return uiDSDsig;
4290 }
4291 
4292 int ReadDSDPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL dsd)
4293 {
4294  /* unsigned int priOffsetInMap = 0 ; */
4295  unsigned int uiDSDPri = STATUS_FAILURE;
4296  /* DSD_HEADER dsdHeader = {0};
4297  * priOffsetInMap = (PUCHAR)&(dsdHeader.DSDImagePriority) -(PUCHAR)&dsdHeader;
4298  */
4299  if (IsSectionWritable(Adapter, dsd)) {
4300  if (ReadDSDSignature(Adapter, dsd) == DSD_IMAGE_MAGIC_NUMBER) {
4301  BcmFlash2xBulkRead(Adapter,
4302  &uiDSDPri,
4303  dsd,
4305  4);
4306 
4307  uiDSDPri = ntohl(uiDSDPri);
4308  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSD<%x> Priority :%x", dsd, uiDSDPri);
4309  }
4310  }
4311 
4312  return uiDSDPri;
4313 }
4314 
4315 FLASH2X_SECTION_VAL getHighestPriDSD(struct bcm_mini_adapter *Adapter)
4316 {
4317  int DSDHighestPri = STATUS_FAILURE;
4318  int DsdPri = 0;
4319  FLASH2X_SECTION_VAL HighestPriDSD = 0;
4320 
4321  if (IsSectionWritable(Adapter, DSD2)) {
4322  DSDHighestPri = ReadDSDPriority(Adapter, DSD2);
4323  HighestPriDSD = DSD2;
4324  }
4325 
4326  if (IsSectionWritable(Adapter, DSD1)) {
4327  DsdPri = ReadDSDPriority(Adapter, DSD1);
4328  if (DSDHighestPri < DsdPri) {
4329  DSDHighestPri = DsdPri;
4330  HighestPriDSD = DSD1;
4331  }
4332  }
4333 
4334  if (IsSectionWritable(Adapter, DSD0)) {
4335  DsdPri = ReadDSDPriority(Adapter, DSD0);
4336  if (DSDHighestPri < DsdPri) {
4337  DSDHighestPri = DsdPri;
4338  HighestPriDSD = DSD0;
4339  }
4340  }
4341  if (HighestPriDSD)
4342  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest DSD :%x , and its Pri :%x", HighestPriDSD, DSDHighestPri);
4343 
4344  return HighestPriDSD;
4345 }
4346 
4347 int ReadISOSignature(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso)
4348 {
4349  unsigned int uiISOsig = 0;
4350  /* unsigned int sigoffsetInMap = 0;
4351  * ISO_HEADER ISOHeader = {0};
4352  * sigoffsetInMap =(PUCHAR)&(ISOHeader.ISOImageMagicNumber) -(PUCHAR)&ISOHeader;
4353  */
4354  if (iso != ISO_IMAGE1 && iso != ISO_IMAGE2) {
4355  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "passed section value is not for ISOs");
4356  return STATUS_FAILURE;
4357  }
4358  BcmFlash2xBulkRead(Adapter,
4359  &uiISOsig,
4360  iso,
4361  0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber),
4362  SIGNATURE_SIZE);
4363 
4364  uiISOsig = ntohl(uiISOsig);
4365  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO SIG :%x", uiISOsig);
4366 
4367  return uiISOsig;
4368 }
4369 
4370 int ReadISOPriority(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL iso)
4371 {
4372  unsigned int ISOPri = STATUS_FAILURE;
4373  if (IsSectionWritable(Adapter, iso)) {
4374  if (ReadISOSignature(Adapter, iso) == ISO_IMAGE_MAGIC_NUMBER) {
4375  BcmFlash2xBulkRead(Adapter,
4376  &ISOPri,
4377  iso,
4378  0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority),
4379  4);
4380 
4381  ISOPri = ntohl(ISOPri);
4382  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISO<%x> Priority :%x", iso, ISOPri);
4383  }
4384  }
4385 
4386  return ISOPri;
4387 }
4388 
4389 FLASH2X_SECTION_VAL getHighestPriISO(struct bcm_mini_adapter *Adapter)
4390 {
4391  int ISOHighestPri = STATUS_FAILURE;
4392  int ISOPri = 0;
4393  FLASH2X_SECTION_VAL HighestPriISO = NO_SECTION_VAL;
4394 
4395  if (IsSectionWritable(Adapter, ISO_IMAGE2)) {
4396  ISOHighestPri = ReadISOPriority(Adapter, ISO_IMAGE2);
4397  HighestPriISO = ISO_IMAGE2;
4398  }
4399 
4400  if (IsSectionWritable(Adapter, ISO_IMAGE1)) {
4401  ISOPri = ReadISOPriority(Adapter, ISO_IMAGE1);
4402  if (ISOHighestPri < ISOPri) {
4403  ISOHighestPri = ISOPri;
4404  HighestPriISO = ISO_IMAGE1;
4405  }
4406  }
4407  if (HighestPriISO)
4408  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Highest ISO :%x and its Pri :%x", HighestPriISO, ISOHighestPri);
4409 
4410  return HighestPriISO;
4411 }
4412 
4413 int WriteToFlashWithoutSectorErase(struct bcm_mini_adapter *Adapter,
4414  PUINT pBuff,
4415  FLASH2X_SECTION_VAL eFlash2xSectionVal,
4416  unsigned int uiOffset,
4417  unsigned int uiNumBytes)
4418 {
4419  #if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS)
4420  unsigned int uiTemp = 0, value = 0;
4421  unsigned int i = 0;
4422  unsigned int uiPartOffset = 0;
4423  #endif
4424  unsigned int uiStartOffset = 0;
4425  /* Adding section start address */
4426  int Status = STATUS_SUCCESS;
4427  PUCHAR pcBuff = (PUCHAR)pBuff;
4428 
4429  if (uiNumBytes % Adapter->ulFlashWriteSize) {
4430  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Writing without Sector Erase for non-FlashWriteSize number of bytes 0x%x\n", uiNumBytes);
4431  return STATUS_FAILURE;
4432  }
4433 
4434  uiStartOffset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
4435 
4436  if (IsSectionExistInVendorInfo(Adapter, eFlash2xSectionVal))
4437  return vendorextnWriteSectionWithoutErase(Adapter, pcBuff, eFlash2xSectionVal, uiOffset, uiNumBytes);
4438 
4439  uiOffset = uiOffset + uiStartOffset;
4440 
4441  #if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS)
4442  Status = bcmflash_raw_writenoerase((uiOffset / FLASH_PART_SIZE), (uiOffset % FLASH_PART_SIZE), pcBuff, uiNumBytes);
4443  #else
4444  rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
4445  value = 0;
4446  wrmalt(Adapter, 0x0f000C80, &value, sizeof(value));
4447 
4448  Adapter->SelectedChip = RESET_CHIP_SELECT;
4449  BcmDoChipSelect(Adapter, uiOffset);
4450  uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter);
4451 
4452  for (i = 0 ; i < uiNumBytes; i += Adapter->ulFlashWriteSize) {
4453  if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT)
4454  Status = flashByteWrite(Adapter, uiPartOffset, pcBuff);
4455  else
4456  Status = flashWrite(Adapter, uiPartOffset, pcBuff);
4457 
4458  if (Status != STATUS_SUCCESS)
4459  break;
4460 
4461  pcBuff = pcBuff + Adapter->ulFlashWriteSize;
4462  uiPartOffset = uiPartOffset + Adapter->ulFlashWriteSize;
4463  }
4464  wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp));
4465  Adapter->SelectedChip = RESET_CHIP_SELECT;
4466  #endif
4467 
4468  return Status;
4469 }
4470 
4472 {
4473  BOOLEAN SectionPresent = FALSE;
4474 
4475  switch (section) {
4476  case ISO_IMAGE1:
4478  (IsNonCDLessDevice(Adapter) == FALSE))
4479  SectionPresent = TRUE;
4480  break;
4481  case ISO_IMAGE2:
4483  (IsNonCDLessDevice(Adapter) == FALSE))
4484  SectionPresent = TRUE;
4485  break;
4486  case DSD0:
4488  SectionPresent = TRUE;
4489  break;
4490  case DSD1:
4492  SectionPresent = TRUE;
4493  break;
4494  case DSD2:
4496  SectionPresent = TRUE;
4497  break;
4498  case VSA0:
4500  SectionPresent = TRUE;
4501  break;
4502  case VSA1:
4504  SectionPresent = TRUE;
4505  break;
4506  case VSA2:
4508  SectionPresent = TRUE;
4509  break;
4510  case SCSI:
4512  SectionPresent = TRUE;
4513  break;
4514  case CONTROL_SECTION:
4516  SectionPresent = TRUE;
4517  break;
4518  default:
4519  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section Does not exist in Flash 2.x");
4520  SectionPresent = FALSE;
4521  }
4522 
4523  return SectionPresent;
4524 }
4525 
4526 int IsSectionWritable(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL Section)
4527 {
4528  int offset = STATUS_FAILURE;
4529  int Status = FALSE;
4530 
4531  if (IsSectionExistInFlash(Adapter, Section) == FALSE) {
4532  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section <%d> does not exixt", Section);
4533  return FALSE;
4534  }
4535 
4536  offset = BcmGetSectionValStartOffset(Adapter, Section);
4537  if (offset == INVALID_OFFSET) {
4538  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section<%d> does not exixt", Section);
4539  return FALSE;
4540  }
4541 
4542  if (IsSectionExistInVendorInfo(Adapter, Section))
4543  return !(Adapter->psFlash2xVendorInfo->VendorSection[Section].AccessFlags & FLASH2X_SECTION_RO);
4544 
4545  Status = IsOffsetWritable(Adapter, offset);
4546  return Status;
4547 }
4548 
4549 static int CorruptDSDSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal)
4550 {
4551  PUCHAR pBuff = NULL;
4552  unsigned int sig = 0;
4553  unsigned int uiOffset = 0;
4554  unsigned int BlockStatus = 0;
4555  unsigned int uiSectAlignAddr = 0;
4556 
4557  Adapter->bSigCorrupted = FALSE;
4558  if (Adapter->bAllDSDWriteAllow == FALSE) {
4559  if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) {
4560  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature");
4561  return SECTOR_IS_NOT_WRITABLE;
4562  }
4563  }
4564 
4565  pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL);
4566  if (!pBuff) {
4567  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
4568  return -ENOMEM;
4569  }
4570 
4571  uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER);
4572  uiOffset -= MAX_RW_SIZE;
4573 
4574  BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE);
4575 
4576  sig = *((PUINT)(pBuff + 12));
4577  sig = ntohl(sig);
4578  BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE);
4579  /* Now corrupting the sig by corrupting 4th last Byte. */
4580  *(pBuff + 12) = 0;
4581 
4582  if (sig == DSD_IMAGE_MAGIC_NUMBER) {
4583  Adapter->bSigCorrupted = TRUE;
4584  if (Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) {
4585  uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);
4586  BlockStatus = BcmFlashUnProtectBlock(Adapter, uiSectAlignAddr, Adapter->uiSectorSize);
4587 
4588  WriteToFlashWithoutSectorErase(Adapter, (PUINT)(pBuff + 12), eFlash2xSectionVal,
4589  (uiOffset + 12), BYTE_WRITE_SUPPORT);
4590  if (BlockStatus) {
4591  BcmRestoreBlockProtectStatus(Adapter, BlockStatus);
4592  BlockStatus = 0;
4593  }
4594  } else {
4595  WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal,
4596  uiOffset, MAX_RW_SIZE);
4597  }
4598  } else {
4599  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header");
4600  kfree(pBuff);
4601 
4602  return STATUS_FAILURE;
4603  }
4604 
4605  kfree(pBuff);
4606  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature");
4607 
4608  return STATUS_SUCCESS;
4609 }
4610 
4611 static int CorruptISOSig(struct bcm_mini_adapter *Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal)
4612 {
4613  PUCHAR pBuff = NULL;
4614  unsigned int sig = 0;
4615  unsigned int uiOffset = 0;
4616 
4617  Adapter->bSigCorrupted = FALSE;
4618 
4619  if (IsSectionWritable(Adapter, eFlash2xSectionVal) != TRUE) {
4620  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Section is not Writable...Hence can't Corrupt signature");
4621  return SECTOR_IS_NOT_WRITABLE;
4622  }
4623 
4624  pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL);
4625  if (!pBuff) {
4626  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey");
4627  return -ENOMEM;
4628  }
4629 
4630  uiOffset = 0;
4631 
4632  BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, eFlash2xSectionVal, uiOffset, MAX_RW_SIZE);
4633 
4634  sig = *((PUINT)pBuff);
4635  sig = ntohl(sig);
4636 
4637  /* corrupt signature */
4638  *pBuff = 0;
4639 
4640  if (sig == ISO_IMAGE_MAGIC_NUMBER) {
4641  Adapter->bSigCorrupted = TRUE;
4642  WriteToFlashWithoutSectorErase(Adapter, (PUINT)pBuff, eFlash2xSectionVal,
4643  uiOffset, Adapter->ulFlashWriteSize);
4644  } else {
4645  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "BCM Signature is not present in header");
4646  kfree(pBuff);
4647 
4648  return STATUS_FAILURE;
4649  }
4650 
4651  BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Corrupted the signature");
4652  BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, pBuff, MAX_RW_SIZE);
4653 
4654  kfree(pBuff);
4655  return STATUS_SUCCESS;
4656 }
4657 
4659 {
4661  return TRUE;
4662  else
4663  return FALSE;
4664 }