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