diff -ur linux-2.4.6-actiontec/Makefile linux-2.4.6-actiontec-lightner-1.3/Makefile
--- linux-2.4.6-actiontec/Makefile	2004-12-02 16:43:58.000000000 +0100
+++ linux-2.4.6-actiontec-lightner-1.3/Makefile	2004-04-21 00:01:43.000000000 +0200
@@ -109,7 +109,7 @@
 # standard CFLAGS
 #
 
-CPPFLAGS := -D__KERNEL__ -I$(HPATH)
+CPPFLAGS := -D__KERNEL__ -I$(HPATH) -DACTION_TEC
 
 ifdef CONFIG_FRIO
 CPPFLAGS += -mno-underscore -DDEBUG
diff -ur linux-2.4.6-actiontec/arch/armnommu/mach-cx821xx/cnxtbsp.c linux-2.4.6-actiontec-lightner-1.3/arch/armnommu/mach-cx821xx/cnxtbsp.c
--- linux-2.4.6-actiontec/arch/armnommu/mach-cx821xx/cnxtbsp.c	2003-08-14 00:49:35.000000000 +0200
+++ linux-2.4.6-actiontec-lightner-1.3/arch/armnommu/mach-cx821xx/cnxtbsp.c	2004-03-19 22:36:14.000000000 +0100
@@ -149,6 +149,10 @@
 |
 *******************************************************************************/
 
+#ifdef ACTION_TEC
+char fixed_mac=0xcc;
+#endif
+
 void CnxtBsp_Get_Mac_Address( int emac_num, char *mac_addr_array )
 {
 	// Return a hardcoded mac address for now until
@@ -159,7 +163,11 @@
 	*mac_addr_array++ = 0xcd;
 	*mac_addr_array++ = 0x00;
 	*mac_addr_array++ = 0x02;
-	*mac_addr_array = CnxtBsp_Get_Random_Byte();
+    #ifdef ACTION_TEC
+        *mac_addr_array = fixed_mac++;
+    #else
+        *mac_addr_array = CnxtBsp_Get_Random_Byte();
+    #endif
 }
 
 /******************************************************************************
diff -ur linux-2.4.6-actiontec/arch/armnommu/mach-cx821xx/cnxtflash.c linux-2.4.6-actiontec-lightner-1.3/arch/armnommu/mach-cx821xx/cnxtflash.c
--- linux-2.4.6-actiontec/arch/armnommu/mach-cx821xx/cnxtflash.c	2003-08-14 00:49:35.000000000 +0200
+++ linux-2.4.6-actiontec-lightner-1.3/arch/armnommu/mach-cx821xx/cnxtflash.c	2004-03-19 22:36:14.000000000 +0100
@@ -27,11 +27,25 @@
 #include <asm/system.h>
 #include <linux/spinlock.h>
 
+#define ACTION_TEC_SUPPORT_SST
 #define CNXT_FLASH_TOTAL_SIZE		0x4000		// Total amount of reserved flash (16 Kbytes)
+#ifdef ACTION_TEC
+#define CNXT_FLASH_WRITE_START		0x0404000	// starting address
+#else
 #define CNXT_FLASH_WRITE_START		0x040C000	// starting address
-#define CNXT_FLASH_MAX_SEGMENTS		(CNXT_FLASH_TOTAL_SIZE / CNXT_FLASH_SEGMENT_SIZE)		// Number of segments
+#endif
+#ifdef ACTION_TEC
+#define CNXT_FLASH_MAX_SEGMENTS		8		// Number of segments
+#else
+#define CNXT_FLASH_MAX_SEGMENTS		16		// Number of segments
+#endif
 #define UNUSED __attribute__((unused))
 #define CNXT_FLASH_DRIVER_VERSION	"001"
+#ifndef ACTION_TEC_SUPPORT_SST
+#define CNXT_FLASH_MIN_BLOCK_SIZE	0x2000	 	// Smallest writable area (8 Kbytes)
+#else 
+static unsigned long CNXT_FLASH_MIN_BLOCK_SIZE=0x2000;	 	// Smallest writable area (8 Kbytes)
+#endif  ACTION_TEC_SUPPORT_SST
 #define CNXT_FLASH_BLOCK_OFFSET		(CNXT_FLASH_TOTAL_SIZE / CNXT_FLASH_MIN_BLOCK_SIZE)
 
 #if 0
@@ -54,53 +68,149 @@
 BOOL CnxtFlashVerifyMemory( UINT16* pSrcAddr, UINT16* pDestAddr, UINT32 uBytes );
 void CnxtFlashSetupSST ( void );
 void CnxtFlashToggleBit ( void ); 
-static DWORD CnxtFlashCalcCRC32( BYTE *buf, DWORD len );
-static void CnxtFlashFullStatusCheck( void );
+DWORD CnxtFlashCalcCRC32( BYTE *pData, DWORD dataLength );
 
 #if 0
 static CNXT_FLASH_SEGMENT_T cnxtFlashSegments[CNXT_FLASH_MAX_SEGMENTS];
-static BYTE cnxtFlashBuffer[CNXT_FLASH_TOTAL_SIZE];
+static BYTE cnxtFlashBuffer[CNXT_FLASH_MIN_BLOCK_SIZE];
 static BOOL cnxtFlashLocked[CNXT_FLASH_MAX_SEGMENTS];
 #else
 CNXT_FLASH_SEGMENT_T cnxtFlashSegments[CNXT_FLASH_MAX_SEGMENTS];
-BYTE cnxtFlashBuffer[CNXT_FLASH_TOTAL_SIZE];
+#ifdef ACTION_TEC_SUPPORT_SST
+BYTE cnxtFlashBuffer[0x2000];   //0X2000 must be the max in the min block sizes
+#else
+BYTE cnxtFlashBuffer[CNXT_FLASH_MIN_BLOCK_SIZE];
+#endif ACTION_TEC_SUPPORT_SST
+
 BOOL cnxtFlashLocked[CNXT_FLASH_MAX_SEGMENTS];
 #endif
 
+#ifdef ACTION_TEC_SUPPORT_SST
+/*
+ *  set    CNXT_FLASH_MIN_BLOCK_SIZE according to the flash id
+*/
+void __init setBootsectorBlocksize( void )
+{
+	UINT16 uDeviceID;
+	UINT16 uMfrId;
+    UINT16 DeviceIDofFLASH;
+    UINT16 *uDeviceIDofFLASH=&DeviceIDofFLASH;
+
+	/* Go into "read identifer" mode for the Intel type part*/
+	*pCUIReg = READ_IDENTIFIER;
+
+	uDeviceID = *pDeviceIDReg;
+	uMfrId	  = *pMfrIDReg;
+
+	/*Check to see if it is an Intel or Sharp flash*/
+	switch ( uDeviceID )
+	{
+		case DEVICE_ID_INTELB3_BB_2M: 
+		case DEVICE_ID_INTELC3_BB_2M: 
+		case DEVICE_ID_INTELB3_BB_4M: 
+		case DEVICE_ID_INTELC3_BB_4M:
+		case DEVICE_ID_INTELB3_BB_1M:
+			*uDeviceIDofFLASH = INTEL_TYPE_FLASH_BB;
+			*pCUIReg = READ_ARRAY_INTEL;
+			break;
+		
+		case DEVICE_ID_SHARP_BB_2M:
+			*uDeviceIDofFLASH = SHARP_TYPE_FLASH_BB_2M;
+			*pCUIReg = READ_ARRAY_INTEL;
+			break;
+
+		case DEVICE_ID_INTELB3_TB_2M: case DEVICE_ID_INTELC3_TB_2M:
+			*uDeviceIDofFLASH = INTEL_TYPE_FLASH_TB_2M;
+			*pCUIReg = READ_ARRAY_INTEL;
+			break;
+			
+		default:
+			*uDeviceIDofFLASH = UNSUPPORTED_FLASH;
+			*pCUIReg = READ_ARRAY_INTEL;
+			break;
+	}
+
+	if( *uDeviceIDofFLASH == UNSUPPORTED_FLASH )
+	{
+
+    	*pCUIReg = READ_ARRAY_SST;
+    	CnxtFlashSetupSST();
+    	*p5555Reg = READ_IDENTIFIER;
+    	
+    	uDeviceID = *pDeviceIDReg;
+    	uMfrId	  = *pMfrIDReg;
+    		/* Check to see if it is an SST, ST-Micro, AMD or MXIC flash */
+    	switch ( uDeviceID )
+    	{
+    		case DEVICE_ID_SST_2M:
+    			DPRINTK("SST 2MB FLASH device!\n");
+#ifdef ACTION_TEC_SUPPORT_SST
+                CNXT_FLASH_MIN_BLOCK_SIZE = 0x1000;
+#endif ACTION_TEC
+    			*uDeviceIDofFLASH = SST_TYPE_FLASH_BB_2M;
+    			*pCUIReg = READ_ARRAY_SST;    	
+    			break;
+    		
+            case DEVICE_ID_STM_TB_2M:
+    			*uDeviceIDofFLASH = STM_TYPE_FLASH_TB_2M;
+    			*pCUIReg = READ_ARRAY_SST;    	
+    			break;
+    
+    		case DEVICE_ID_STM_BB_2M:
+    			if ( uMfrId == MFR_ID_MXIC)
+    				*uDeviceIDofFLASH = MXIC_TYPE_FLASH_BB_2M;
+    			else	 
+    				*uDeviceIDofFLASH = STM_TYPE_FLASH_BB_2M;
+    			*pCUIReg = READ_ARRAY_SST;    	
+    			break;
+    
+    		case DEVICE_ID_AMD_BB_4M:
+    			*uDeviceIDofFLASH = AMD_TYPE_FLASH_BB_4M;
+    			*pCUIReg = READ_ARRAY_SST;    	
+    			break;
+    
+    		case DEVICE_ID_HYNIX_BB_4M:
+    			*uDeviceIDofFLASH = HYNIX_TYPE_FLASH_BB_4M;
+    			*pCUIReg = READ_ARRAY_SST;    	
+    			break;
+    
+    		case DEVICE_ID_MXIC_BB_4M:
+    			*uDeviceIDofFLASH = MXIC_TYPE_FLASH_BB_4M;
+    			*pCUIReg = READ_ARRAY_SST;    	
+    			break;
+    					
+    	// Derek 8.20.2002
+    		case DEVICE_ID_ATMEL_BB_2M:
+    			*uDeviceIDofFLASH = ATMEL_TYPE_FLASH_BB_2M;
+    			*pCUIReg = READ_ARRAY_SST;    	
+    			break;
+    
+    		default:
+    			*uDeviceIDofFLASH = UNSUPPORTED_FLASH;
+    	    	*pCUIReg = READ_ARRAY_SST;    	
+    			break;
+    	}
+	}
+
+	if(*uDeviceIDofFLASH == UNSUPPORTED_FLASH) 
+	{
+		printk("Unsupported FLASH device!\n");
+	}
+}
+#endif ACTION_TEC_SUPPORT_SST
+
 static int __init UNUSED CnxtFlashInit( void )
 {
 	int Status = 0;
 	int i;
-	BYTE  * startOfBufferAddress = (BYTE *)cnxtFlashBuffer;
 	BYTE  * startOfSegmentAddress = (BYTE *)CNXT_FLASH_WRITE_START;
 	DWORD	headerCRC;
 	DWORD	headerSize = sizeof( CNXT_FLASH_SEGMENT_T );
-	BOOLEAN InitFlashSegment = FALSE;
-	BOOLEAN bSuccess = FALSE;
 
 	// Substract out the dataLength, headerCRC and dataCRC from CRC32 calulations
 	DWORD 	headerDataSize = headerSize - sizeof( DWORD ) - sizeof( DWORD ) - sizeof(DWORD);
 	
-	printk("Conexant Flash Driver version: %s\n", CNXT_FLASH_DRIVER_VERSION );
-
-	DPRINTK("segmentNumber: %ld\n", sizeof(cnxtFlashSegments[0].segmentNumber));
-	DPRINTK("segmentSize: %ld\n", sizeof(cnxtFlashSegments[0].segmentSize));
-	DPRINTK("startFlashAddress: %ld\n", sizeof(cnxtFlashSegments[0].startFlashAddress));
-	DPRINTK("startDataAddress: %ld\n", sizeof(cnxtFlashSegments[0].startDataAddress));
-	DPRINTK("owner: %ld\n", sizeof(cnxtFlashSegments[0].owner));
-	DPRINTK("version: %ld\n", sizeof(cnxtFlashSegments[0].version));
-	DPRINTK("reserved1: %ld\n", sizeof(cnxtFlashSegments[0].reserved1));
-	DPRINTK("reserved2: %ld\n", sizeof(cnxtFlashSegments[0].reserved2));
-	DPRINTK("dataLength: %ld\n", sizeof(cnxtFlashSegments[0].dataLength));
-	DPRINTK("headerCRC: %ld\n", sizeof(cnxtFlashSegments[0].headerCRC));
-	DPRINTK("dataCRC: %ld\n", sizeof(cnxtFlashSegments[0].dataCRC));
-
-	//Keep a copy in RAM.				
-	memcpy( 
-		cnxtFlashBuffer, 
-		(BYTE *)CNXT_FLASH_WRITE_START,
-		CNXT_FLASH_TOTAL_SIZE
-	);		
+	printk("**********************************Conexant Flash Driver version: %s\n", CNXT_FLASH_DRIVER_VERSION );
 
 	for( i = 0; i < CNXT_FLASH_MAX_SEGMENTS; i++ )
 	{
@@ -111,16 +221,14 @@
 		// Load flash segment headers 
 		memcpy( 
 			&cnxtFlashSegments[i], 
-			startOfBufferAddress,
+			startOfSegmentAddress,
 			headerSize
-		);
-	
+		);	
+		
 		headerCRC = CnxtFlashCalcCRC32( (BYTE *) &cnxtFlashSegments[i], headerDataSize );
 
-		//See if CRC does not agree with previously stored value. 
 		if( headerCRC != cnxtFlashSegments[i].headerCRC )
 		{
-			InitFlashSegment = TRUE;
 			printk("Initializing Flash Segment %d\n", i + 1);
 
 			cnxtFlashSegments[i].segmentNumber = i;	
@@ -128,42 +236,25 @@
 			cnxtFlashSegments[i].startFlashAddress = (DWORD)startOfSegmentAddress;
 			cnxtFlashSegments[i].startDataAddress = (DWORD)startOfSegmentAddress + headerSize;
 			cnxtFlashSegments[i].owner = i;					
-			cnxtFlashSegments[i].dataLength = 0;
-			cnxtFlashSegments[i].dataCRC = 0;						
+			printk("Initializing Flash data Segment %d,  %lX  \n", i + 1,cnxtFlashSegments[i].startDataAddress);
 
 			// Calculate the new headerCRC and save it.
 			headerCRC = CnxtFlashCalcCRC32( (BYTE *) &cnxtFlashSegments[i], headerDataSize );
 			cnxtFlashSegments[i].headerCRC = headerCRC;
-						
-			// Copy the segment header into the RAM buffer.
-			memcpy( 
-				(UINT16*)startOfBufferAddress, 
-				(UINT16*)&cnxtFlashSegments[i],
-				sizeof( CNXT_FLASH_SEGMENT_T )
-			);
+			
+			// Store new header info. along with headerCRC to the flash segment.
+			CnxtFlashWrite( 
+				(UINT16 *)startOfSegmentAddress, 
+				(UINT16 *)&cnxtFlashSegments[i], 
+				headerSize
+			); 
+
 		} 
 
 		startOfSegmentAddress += CNXT_FLASH_SEGMENT_SIZE;
-		startOfBufferAddress += CNXT_FLASH_SEGMENT_SIZE;
 
 	}
 
-	if( InitFlashSegment )
-	{
-	
-		//Write the entire flash region to flash (its easier).
-		bSuccess = CnxtFlashWrite( 
-				(UINT16 *)CNXT_FLASH_WRITE_START, 
-				(UINT16 *)&cnxtFlashBuffer, 
-				CNXT_FLASH_TOTAL_SIZE
-		); 
-
-		if( !bSuccess )  
-			Status = CNXT_FLASH_DATA_ERROR;
-
-	}
-
-
 	return Status;
 }
 
@@ -191,73 +282,116 @@
 CNXT_FLASH_STATUS_E CnxtFlashOpen( CNXT_FLASH_SEGMENT_E segment )
 {
 	CNXT_FLASH_STATUS_E Status = CNXT_FLASH_SUCCESS;
-	BYTE  * startOfSegmentAddress = (BYTE *)cnxtFlashBuffer;
+	DWORD	headerSize = sizeof( CNXT_FLASH_SEGMENT_T );
 	DWORD   dataCRC;
-	
+	ULONG  	offset;
+
 	// Check for a valid segment number.
-   	if( segment < CNXT_FLASH_SEGMENT_1 || 
-		segment >= CNXT_FLASH_TOTAL_SIZE / CNXT_FLASH_SEGMENT_SIZE )
+   	if( segment < CNXT_FLASH_SEGMENT_1 || segment > CNXT_FLASH_SEGMENT_16 )
 	{
 		printk("Incorrect Flash Segment number!\n" );
 		return CNXT_FLASH_DATA_ERROR;
 	}
 
-
 	// Check for owner
 	if( segment != cnxtFlashSegments[segment].owner )
 	{
 		printk("Incorrect owner for Flash Segment!\n" );
 		return CNXT_FLASH_OWNER_ERROR;
 	}
-
-	if( cnxtFlashSegments[segment].dataLength > CNXT_FLASH_SEGMENT_SIZE ) 
-	{
-		cnxtFlashSegments[segment].dataLength = CNXT_FLASH_SEGMENT_SIZE;
 	
-		DPRINTK(
-			"dataLength Adjusted to: %x\n", 
-			cnxtFlashSegments[segment].dataLength
-		);
-		DPRINTK(
-			"CNXT_FLASH_SEGMENT_SIZE: %x\n", 
-			CNXT_FLASH_SEGMENT_SIZE
-		);
-	}
-
-	// Calculate the new segment data CRC.
-	dataCRC = CnxtFlashCalcCRC32( 
-		(BYTE *) cnxtFlashSegments[segment].startDataAddress, 
-		cnxtFlashSegments[segment].dataLength 
+	DPRINTK(
+		"CnxtFlashOpen: &cnxtFlashSegments[%d] = %x\n", 
+		segment, 
+		&cnxtFlashSegments[segment]
+	);
+	DPRINTK(
+		"cnxtFlashSegments[%d].startFlashAddress = %x\n", 
+		segment,
+		cnxtFlashSegments[segment].startFlashAddress
 	);
 
-	// Mark the segment as unlocked.
-	cnxtFlashLocked[segment] = FALSE;
+	// Copy the header from flash.
+	memcpy( 
+		(UINT16*)&cnxtFlashSegments[segment], 
+		(UINT16*)cnxtFlashSegments[segment].startFlashAddress,
+		headerSize
+	);	
+	
 
-	startOfSegmentAddress = startOfSegmentAddress + (segment * CNXT_FLASH_SEGMENT_SIZE);
+	if( cnxtFlashSegments[segment].dataLength > CNXT_FLASH_SEGMENT_SIZE )
+		cnxtFlashSegments[segment].dataLength = CNXT_FLASH_SEGMENT_SIZE;
+#ifdef ACTION_TEC_SUPPORT_SST
+    offset = ((segment * CNXT_FLASH_SEGMENT_SIZE)/ CNXT_FLASH_MIN_BLOCK_SIZE + 1) * 
+        CNXT_FLASH_MIN_BLOCK_SIZE - CNXT_FLASH_SEGMENT_SIZE;
+
+    if( cnxtFlashSegments[segment].startDataAddress > ( CNXT_FLASH_WRITE_START + offset ) ) {
+        return CNXT_FLASH_DATA_ERROR;	
+    }
+    else {
+        // Calculate the new segment data CRC.
+        dataCRC = CnxtFlashCalcCRC32( 
+            (BYTE *) cnxtFlashSegments[segment].startDataAddress, 
+            cnxtFlashSegments[segment].dataLength 
+        );
+    }
+#else
+	if( segment > CNXT_FLASH_SEGMENT_8 )
+	{	
+		offset = CNXT_FLASH_BLOCK_OFFSET * CNXT_FLASH_MIN_BLOCK_SIZE - CNXT_FLASH_SEGMENT_SIZE;
+		
+		DPRINTK("CNXT_FLASH_BLOCK_OFFSET: %x\n", CNXT_FLASH_BLOCK_OFFSET);
+		DPRINTK("CNXT_FLASH_MIN_BLOCK_SIZE: %x\n", CNXT_FLASH_MIN_BLOCK_SIZE);
 
-	DPRINTK("CnxtFlashOpen: startOfSegmentAddress = %x\n", startOfSegmentAddress);
+		DPRINTK("offset: %lx\n", offset);
+		DPRINTK("cnxtFlashSegments[segment].startDataAddress: %lx\n",cnxtFlashSegments[segment].startDataAddress);
+		DPRINTK("cnxtFlashSegments[segment].startFlashAddress: %lx\n", cnxtFlashSegments[segment].startFlashAddress);
+		DPRINTK("CNXT_FLASH_WRITE_START + offset: %lx\n", CNXT_FLASH_WRITE_START + offset);
+
+		if( cnxtFlashSegments[segment].startFlashAddress > (CNXT_FLASH_WRITE_START + offset) ) {
+			return CNXT_FLASH_DATA_ERROR;		
+        }
+		else {
+			// Calculate the new segment data CRC.
+			dataCRC = CnxtFlashCalcCRC32( 
+				(BYTE *) cnxtFlashSegments[segment].startDataAddress, 
+				cnxtFlashSegments[segment].dataLength 
+			);
+		}
 
-	// Copy the segment header into the RAM buffer.
-	memcpy( 
-		(UINT16*)startOfSegmentAddress, 
-		(UINT16*)&cnxtFlashSegments[segment],
-		sizeof( CNXT_FLASH_SEGMENT_T )
+	} else {
+        if( cnxtFlashSegments[segment].startDataAddress > ( CNXT_FLASH_WRITE_START + offset ) ) {
+			return CNXT_FLASH_DATA_ERROR;	
+        }
+		else {
+			// Calculate the new segment data CRC.
+			dataCRC = CnxtFlashCalcCRC32( 
+				(BYTE *) cnxtFlashSegments[segment].startDataAddress, 
+				cnxtFlashSegments[segment].dataLength 
+			);
+
+		}
+	}
+#endif ACTION_TEC_SUPPORT_SST
+	DPRINTK(
+		"cnxtFlashSegments[%d].dataCRC = %x        dataCRC = %x\n",
+		segment,
+		cnxtFlashSegments[segment].dataCRC,
+		dataCRC
 	);
 
 	// Check the data CRC
-	if( cnxtFlashSegments[segment].dataCRC != dataCRC )
-	{
-		DPRINTK("CnxtFlashOpen: Check data CRC failed!\n");
+	if( cnxtFlashSegments[segment].dataCRC != dataCRC ){
+		#ifdef ACTION_TEC
+		printk("Flash data crc error\n");
+		Status = CNXT_FLASH_DATA_CRC_ERROR;
+		#else
 		Status = CNXT_FLASH_DATA_ERROR;
+		#endif
 	}
 
-	// Check the data to see if there is any.
-	if( !cnxtFlashSegments[segment].dataLength )
-	{
-		DPRINTK("CnxtFlashOpen: No data in Segment!\n");
-		Status = CNXT_FLASH_DATA_ERROR;
-	}
-	
+	// Mark the segment as unmarked.
+	cnxtFlashLocked[segment] = FALSE;
 	return Status;
 }
 /****************************************************************************
@@ -284,11 +418,13 @@
 
 	// Make sure maximum size is not exceeded.
 	if( size > CNXT_FLASH_SEGMENT_SIZE - sizeof( CNXT_FLASH_SEGMENT_T ) )
+#ifdef ACTION_TEC	
+		size=CNXT_FLASH_SEGMENT_SIZE - sizeof( CNXT_FLASH_SEGMENT_T );
+#else
 		return FALSE;
-
+#endif
 	// Check for a valid segment number.
-	if( segment < CNXT_FLASH_SEGMENT_1 || 
-		segment >= CNXT_FLASH_TOTAL_SIZE / CNXT_FLASH_SEGMENT_SIZE )
+	if( segment < CNXT_FLASH_SEGMENT_1 || segment > CNXT_FLASH_SEGMENT_16 )
 	{
 		return FALSE;
 	} else {
@@ -321,38 +457,39 @@
 {
 	DWORD dataCRC;
 	DWORD headerSize = sizeof( CNXT_FLASH_SEGMENT_T );
-	BOOLEAN	bSuccess;
-	BYTE  * startOfSegmentAddress = (BYTE *)cnxtFlashBuffer;
-
-	DPRINTK("CnxtFlashWriteRequest: Entry.\n");
+	DWORD flashBlockOffset;
+	DWORD flashBlock;
+	BOOL bSuccess = FALSE;
 
-	// Make sure data pointer is not NULL.
+    // Make sure data pointer is not NULL.
 	if( !psdramStartAddr ) {
-		printk("CnxtFlashWriteRequest: NULL data pointer!\n");
-		return CNXT_FLASH_DATA_ERROR;
+		return bSuccess;
 	}
 
 	// Make sure there is enough room for the data.
 	if( size > CNXT_FLASH_SEGMENT_SIZE - sizeof( CNXT_FLASH_SEGMENT_T ) )
 	{
-		return CNXT_FLASH_OWNER_ERROR;
+#ifdef ACTION_TEC	
+		size=CNXT_FLASH_SEGMENT_SIZE - sizeof( CNXT_FLASH_SEGMENT_T );
+#else
+		return bSuccess;
+#endif
 	}
 
 	// Check for a valid segment number.
-	if( segment < CNXT_FLASH_SEGMENT_1 || 
-		segment >= CNXT_FLASH_TOTAL_SIZE / CNXT_FLASH_SEGMENT_SIZE )
+	if( segment < CNXT_FLASH_SEGMENT_1 || segment > CNXT_FLASH_SEGMENT_16 )
 	{
-		return CNXT_FLASH_OWNER_ERROR;
+		return bSuccess;
 	} else {
 
 		// Make sure the segment is not locked.
-		if( cnxtFlashLocked[segment] ) {
+    	if( cnxtFlashLocked[segment] ) {
 			printk( "Flash Segment Locked! (Try opening it first)\n" );
-			return CNXT_FLASH_OWNER_ERROR;
+			return FALSE;
 		}
-
+    
 		if( size > CNXT_FLASH_SEGMENT_SIZE - headerSize )
-			return CNXT_FLASH_DATA_ERROR;
+			return FALSE;
 		else
 			cnxtFlashSegments[segment].dataLength = size;
 	
@@ -361,41 +498,104 @@
 			(BYTE *) psdramStartAddr, 
 			size 
 		);
-		
-		//Save the new CRC.
+
 		cnxtFlashSegments[segment].dataCRC = dataCRC;
-					
-		startOfSegmentAddress += segment * ( CNXT_FLASH_TOTAL_SIZE / CNXT_FLASH_MAX_SEGMENTS );
+		
+		DPRINTK(
+			"cnxtFlashSegments[%d].dataCRC = %x\n", 
+			segment,
+			cnxtFlashSegments[segment].dataCRC
+		);
+		DPRINTK(
+			"headerSize = %x\n",
+			headerSize
+		);
 
-		// Copy the segment header into the RAM buffer.
-		memcpy( 
-			(UINT16*)startOfSegmentAddress, 
-			(UINT16*)&cnxtFlashSegments[segment],
-			sizeof( CNXT_FLASH_SEGMENT_T )
+
+		if( segment > CNXT_FLASH_SEGMENT_8 )
+		{
+			flashBlock = CNXT_FLASH_SEGMENT_9;
+			flashBlockOffset = (segment * CNXT_FLASH_SEGMENT_SIZE) - CNXT_FLASH_MIN_BLOCK_SIZE;
+		}
+		else
+		{
+			flashBlock = CNXT_FLASH_SEGMENT_1;
+			flashBlockOffset = (segment * CNXT_FLASH_SEGMENT_SIZE);
+		}
+
+		DPRINTK("flashBlock = %d\n", flashBlock	);
+#ifdef ACTION_TEC_SUPPORT_SST
+        if (CNXT_FLASH_SEGMENT_SIZE == CNXT_FLASH_MIN_BLOCK_SIZE) {
+            flashBlock = segment; 
+            flashBlockOffset = 0;
+        }
+        else {
+            //flashblock        - the first segment num of the block which this segment is in
+            //flashBlockOffset  - the offset of this segment in the block
+            int num_block;   //start from 0   segment start from 0
+            int segs_per_block;
+
+            segs_per_block = CNXT_FLASH_MIN_BLOCK_SIZE / (CNXT_FLASH_SEGMENT_SIZE);
+            num_block = (segment * CNXT_FLASH_SEGMENT_SIZE)/ CNXT_FLASH_MIN_BLOCK_SIZE;
+            flashBlock = num_block * segs_per_block;
+			flashBlockOffset = segment * (CNXT_FLASH_SEGMENT_SIZE) -
+                num_block * CNXT_FLASH_MIN_BLOCK_SIZE;
+/*            printk ("flashBlock2 = %ld, %ld seg=%ld, %ld, %ld, m/s=%ld, %ld\n", flashBlock,  flashBlockOffset,
+                    segment, CNXT_FLASH_SEGMENT_SIZE, CNXT_FLASH_MIN_BLOCK_SIZE, 
+                    num_block, 
+                    segs_per_block);*/
+        }
+#endif ACTION_TEC_SUPPORT_SST
+		// Read in the minimum flash block size (8kbytes)
+		memcpy
+		(
+			&cnxtFlashBuffer[0],
+			(BYTE *)cnxtFlashSegments[flashBlock].startFlashAddress,
+			CNXT_FLASH_MIN_BLOCK_SIZE	
 		);
 
-		// Copy the segment data into the RAM buffer.
-		memcpy( 
-			(UINT16*)(startOfSegmentAddress + sizeof( CNXT_FLASH_SEGMENT_T )), 
-			(UINT16*)psdramStartAddr,
-			size
+		// Copy the flash segment header
+		DPRINTK("flashBlockOffset = %x\n", flashBlockOffset	);
+
+		memcpy
+		(
+			&cnxtFlashBuffer[flashBlockOffset], 
+			&cnxtFlashSegments[segment], 
+			headerSize
 		);
 
+		// Copy the data
+		memcpy
+		( 
+			&cnxtFlashBuffer[flashBlockOffset + headerSize],
+			psdramStartAddr,
+			size
+		);			
+		
+		DPRINTK(
+			"cnxtFlashSegments[%d].startFlashAddress = %x\n",
+			flashBlock,
+			cnxtFlashSegments[flashBlock].startFlashAddress
+		);
+		DPRINTK(
+			"CNXT_FLASH_MIN_BLOCK_SIZE: %x\n",
+			CNXT_FLASH_MIN_BLOCK_SIZE
+		);
 
-		//Write the entire flash region to flash (its easier).
 		bSuccess = CnxtFlashWrite( 
-				(UINT16 *)CNXT_FLASH_WRITE_START, 
-				(UINT16 *)&cnxtFlashBuffer, 
-				CNXT_FLASH_TOTAL_SIZE
+				(UINT16 *)cnxtFlashSegments[flashBlock].startFlashAddress, 
+				(UINT16 *)&cnxtFlashBuffer[0], 
+				CNXT_FLASH_MIN_BLOCK_SIZE
 		); 
 
 		if( !bSuccess )  {
-			return CNXT_FLASH_DATA_ERROR;
+
+			return FALSE;
 		}
 
 	}
 
-	return CNXT_FLASH_SUCCESS;
+	return TRUE;
 }
 
 /****************************************************************************
@@ -449,6 +649,8 @@
 	UINT32 uBytesChk;
 	UINT16 uDeviceID;
 
+    printk ("CnxtFlashProg src=%x, dst=%x, size=%d\n", 
+            pSrcAddr, pDestAddr, uBytes);
 	/* Save the addresses and byte count for later validation */
 	pSrcAddrChk = pSrcAddr;
 	pDestAddrChk = pDestAddr;
@@ -613,14 +816,11 @@
  *  Outputs:		none
  *
  ***************************************************************************/
-#define INTEL_MIN_BLOCK_SIZE 0x2000/sizeof(WORD) //Convert KBytes to KWords
-#define SST_MIN_BLOCK_SIZE   0x1000/sizeof(WORD) //Convert KBytes to KWords
 
 BOOL CnxtFlashEraseBlock( volatile UINT16* pBlockAddr, UINT16 *uDeviceIDofFLASH )
 {
 	BOOL bSuccess=TRUE;
 	eFlashErase EraseProcedure = DONT_ERASE;
-	short i;
 
 	switch ( *uDeviceIDofFLASH )
 	{
@@ -634,9 +834,6 @@
 			break;	
 		
 		case MXIC_TYPE_FLASH_BB_4M:
-			EraseProcedure = MXIC;
-			break;
-
 		case AMD_TYPE_FLASH_BB_4M:
 			if(	(pBlockAddr < BOOT_BLOCK_END) && (((UINT32)pBlockAddr & 0x1fff) == 0x0) )
 				EraseProcedure = STM;		 
@@ -666,7 +862,11 @@
 		case STM_TYPE_FLASH_BB_2M:
 		case MXIC_TYPE_FLASH_BB_2M:
 		case HYNIX_TYPE_FLASH_BB_4M:
-			EraseProcedure = STM;
+			if( ( ((pBlockAddr < BOOT_BLOCK_END) && ( ( (UINT32)pBlockAddr == (UINT32)0x406000) 
+				|| ( ( UINT32 )pBlockAddr == ( UINT32 )0x404000 ) 
+				|| ( ( UINT32 )pBlockAddr == ( UINT32 )0x408000 ) )) 
+				|| (((UINT32)pBlockAddr & 0xffff) == 0x0000) ) )
+				EraseProcedure = STM;
 
 			break;
 
@@ -689,69 +889,76 @@
 		case INTEL:
 		{
 
-			/* Erase the first 8Kbytes */
-			DPRINTK("Erasing 8KBytes starting at %x\n", pBlockAddr);
-			/* Clear the status register */
-			CnxtFlashClearStatusReg();
-
+#if 0
 			/*  To unlock the blocks of memory in Intel C3 flash */  
-			*pCUIReg = UNLOCK_SETUP;
+			*pBlockAddr = UNLOCK_SETUP;
 			*pBlockAddr = ERASE_CONFIRM_INTEL;
 			
+			*pCUIReg = READ_ARRAY_INTEL;
+			/* Clear the status register */
+			CnxtFlashClearStatusReg();
+
 			if( *uDeviceIDofFLASH == SHARP_TYPE_FLASH_BB_2M )
 				bSuccess = CnxtFlashWaitForDone(0);
 			
 			/* Write erase setup, erase confirm, and block address */
-			*pCUIReg = ERASE_SETUP_INTEL;
+			*pBlockAddr = ERASE_SETUP_INTEL;
 			*pBlockAddr = ERASE_CONFIRM_INTEL;
-			*pCUIReg = ERASE_CONFIRM_INTEL;
 
 			/* Wait for erase complete */
 			bSuccess &= CnxtFlashWaitForDone(0);
 
-			CnxtFlashFullStatusCheck();			
-			
-			/* Increment to the next flash block.c */
-			pBlockAddr += INTEL_MIN_BLOCK_SIZE;
-			DPRINTK("Erasing 8KBytes starting at %x\n", pBlockAddr );
+			/* Return to "read array" mode */
+			*pCUIReg = READ_ARRAY_INTEL;
+#else
+			/* Clear the status register */
+			CnxtFlashClearStatusReg();
 
+			/*  To unlock the blocks of memory in Intel C3 flash */  
+			*pCUIReg = UNLOCK_SETUP;
+			*pBlockAddr = ERASE_CONFIRM_INTEL;
+			
+			if( *uDeviceIDofFLASH == SHARP_TYPE_FLASH_BB_2M )
+				bSuccess = CnxtFlashWaitForDone(0);
+			
+			/* Write erase setup, erase confirm, and block address */
 			*pCUIReg = ERASE_SETUP_INTEL;
 			*pBlockAddr = ERASE_CONFIRM_INTEL;
 			*pCUIReg = ERASE_CONFIRM_INTEL;
 
+			/* Wait for erase complete */
 			bSuccess &= CnxtFlashWaitForDone(0);
 
-			CnxtFlashFullStatusCheck();			
-
 			/* Return to "read array" mode */
 			*pCUIReg = READ_ARRAY_INTEL;
 
+#endif		
 		}
 		break;
 
 		case SST:
 		{
-	
-			/* Unlike Intel, SST has sectors each 2KWords in size 	*/
-			/* So we need to erase 4 sectors.			*/
-			for(i=0; i < 4; i++)
-			{ 
-				CnxtFlashSetupSST();
-				*p5555Reg = ERASE_SETUP_SST;
-				CnxtFlashSetupSST();
-				
-				DPRINTK("Erasing 4KBytes starting at %x\n", pBlockAddr );
+			CnxtFlashSetupSST();
+			*p5555Reg = ERASE_SETUP_SST;
+			CnxtFlashSetupSST();
+
+			if(	pBlockAddr >= BOOT_BLOCK_END )
+			{
+				DPRINTK("SST BLOCK_ERASE_CONFIRM.\n");
+				*pBlockAddr = BLOCK_ERASE_CONFIRM;
+
+			} else {
+				DPRINTK("SST SECTOR_ERASE_CONFIRM.\n");
 				*pBlockAddr = SECTOR_ERASE_CONFIRM;	
-	
-				while(!(*pBlockAddr & DQ7));
 				
-				pBlockAddr += SST_MIN_BLOCK_SIZE;
 			}
+			while(!(*pBlockAddr & DQ7));
+			
+			//CnxtFlashToggleBit();
 
 			DPRINTK("SST returning to read array mode.\n");
 			/* Return to "read array" mode */
 			*pCUIReg = READ_ARRAY_SST;
-	
 		}
 		break;
 
@@ -770,35 +976,6 @@
 			*pCUIReg = READ_ARRAY_SST;
 		}
 		break;
-
-		case MXIC:
-			/* Erase the first 8Kbytes */
-			DPRINTK("Erasing 8KBytes starting at %x\n", pBlockAddr);
-
-			CnxtFlashSetupSST();
-			*p5555Reg = ERASE_SETUP_SST;
-			CnxtFlashSetupSST();
-			
-			*pBlockAddr = SECTOR_ERASE_CONFIRM;	
-				
-			while(!(*pBlockAddr & DQ7));
-						
-			CnxtFlashSetupSST();
-			*p5555Reg = ERASE_SETUP_SST;
-			CnxtFlashSetupSST();
-
-			/* Increment to the next flash block.c */
-			pBlockAddr += INTEL_MIN_BLOCK_SIZE;
-			DPRINTK("Erasing 8KBytes starting at %x\n", pBlockAddr );
-			
-			*pBlockAddr = SECTOR_ERASE_CONFIRM;	
-				
-			while(!(*pBlockAddr & DQ7));
-			
-			/* Return to "read array" mode */
-			*pCUIReg = READ_ARRAY_SST;
-
-			break;
 		
 		default:
 			break;	
@@ -883,24 +1057,6 @@
 	return;
 }
 
-void CnxtFlashFullStatusCheck( void )
-{
-	UINT16 uStatus;	
-
-	/* Write the "read status register" command */
-	*pCUIReg = READ_STATUS_REG;
-
-	/* Read the status register */
-	uStatus = *pCUIReg;
-
-	if( uStatus & ERASE_ERR ) printk("Block Erase Error!\n");
-	if( uStatus & PROG_ERR ) printk("Command Sequence Erase!\n");
-	if( uStatus & Vpp_ERR ) printk("Vpp Range Error!\n");
-	if( uStatus & ERASE_ERR ) printk("Attempted Erase of Locked Block!\n");
-
-
-}
-
 /****************************************************************************
  *
  *  Name:			BOOL CnxtFlashWaitForDone( BOOL )
@@ -1008,79 +1164,6 @@
 	return bSuccess;
 }
 
-#define INITIAL_CRC_VAL		0xffffffff  // negative one
-
-#if 1
-static DWORD CnxtFlashCalcCRC32
-(
-	BYTE		*buf,
-	DWORD		len	
-)
-{
-  static const unsigned long crc32_table[256] =
-    {
-      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
-      0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
-      0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
-      0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
-      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
-      0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
-      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
-      0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
-      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
-      0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
-      0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
-      0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
-      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
-      0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
-      0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
-      0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
-      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
-      0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
-      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
-      0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
-      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
-      0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
-      0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
-      0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
-      0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
-      0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
-      0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
-      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
-      0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
-      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
-      0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
-      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
-      0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
-      0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
-      0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
-      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
-      0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
-      0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
-      0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
-      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
-      0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
-      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
-      0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
-      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
-      0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
-      0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
-      0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
-      0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
-      0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
-      0x2d02ef8d
-    };
-  unsigned char *end;
-  DWORD crc;
-
-  crc = INITIAL_CRC_VAL;
-  for (end = buf + len; buf < end; ++buf)
-    crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
-  return ~crc & 0xffffffff;;
-}
-#else
 /****************************************************************************
  *
  *  Name:		DWORD CnxtFlashCalcCRC32
@@ -1158,13 +1241,15 @@
 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
-0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+0xf0a5bd1d, 0xf464a0aa797, 0xf9278673, 0xfde69bc4,
 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
 };
 
+#define INITIAL_CRC_VAL		0xffffffff  // negative one
+
 DWORD CnxtFlashCalcCRC32
 (
 	BYTE		*pData,
@@ -1182,7 +1267,6 @@
 	return (crc32_val);
 
 }
-#endif
 
 void CnxtFlashSetupSST(void)
 {
diff -ur linux-2.4.6-actiontec/arch/armnommu/mach-cx821xx/cnxtflash.h linux-2.4.6-actiontec-lightner-1.3/arch/armnommu/mach-cx821xx/cnxtflash.h
--- linux-2.4.6-actiontec/arch/armnommu/mach-cx821xx/cnxtflash.h	2003-08-14 00:49:35.000000000 +0200
+++ linux-2.4.6-actiontec-lightner-1.3/arch/armnommu/mach-cx821xx/cnxtflash.h	2004-04-21 00:15:18.000000000 +0200
@@ -146,7 +146,11 @@
 #define BLOCK_LOCK_ERR			( UINT16 )( 1 << 1 )
 
 #define FLASH_ERR	( UINT16 )( ERASE_ERR | PROG_ERR | Vpp_ERR | BLOCK_LOCK_ERR )
+#ifdef ACTION_TEC
+#define CNXT_FLASH_SEGMENT_SIZE		2*1024
+#else
 #define CNXT_FLASH_SEGMENT_SIZE		1024
+#endif
 
 #include <linux/cnxtflash.h>
 
diff -ur linux-2.4.6-actiontec/arch/armnommu/mach-cx821xx/gpioisr.c linux-2.4.6-actiontec-lightner-1.3/arch/armnommu/mach-cx821xx/gpioisr.c
--- linux-2.4.6-actiontec/arch/armnommu/mach-cx821xx/gpioisr.c	2003-08-14 00:49:35.000000000 +0200
+++ linux-2.4.6-actiontec-lightner-1.3/arch/armnommu/mach-cx821xx/gpioisr.c	2004-03-19 22:36:14.000000000 +0100
@@ -23,14 +23,23 @@
 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
 ****************************************************************************
-*  $Author:   belljl  $
-*  $Revision:   1.1  $
+*  $Author: shell $
+*  $Revision: 1.3 $
 *  $Modtime:   Jun 30 2003 15:25:18  $
 ****************************************************************************/
 
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/version.h>
+#ifdef ACTION_TEC
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/mtd/compatmac.h>
+#include <linux/mtd/mtd.h>
+#include <asm/arch/bsptypes.h>
+#include <linux/cnxtflash.h>
+#endif
 #include "bsptypes.h"
 #include "bspcfg.h"
 #include "syslib.h"
@@ -38,6 +47,11 @@
 #include "cnxtirq.h"
 #include "OsTools.h"
 #include "gpio.h"
+#ifdef ACTION_TEC
+#define WD_REG 0x350038  	/* WatchDog TM_Lmt3 register */
+#define RESET_VALUE 0x270F	/* Enable & SetUp WatchDog value */
+#define MTDRAM_TOTAL_SIZE (CONFIG_MTDRAM_TOTAL_SIZE * 1024)
+#endif
 
 #if CONFIG_CNXT_GSHDSL || CONFIG_CNXT_GSHDSL_MODULE
     void (*pHostPort_ISR)(void *) = 0;
@@ -290,6 +304,7 @@
 }
     
 
+/*ACTION_TEC*/
 void GPIOB25_Handler(int gpio_num)
 {
       //Linux Console
@@ -297,8 +312,21 @@
 	   void rs_interrupt(int irq, void * dev_id, struct pt_regs * regs) ;
 	   rs_interrupt( GPIOINT_UART1, NULL, NULL ) ;
    #endif
+//      printk("GPIOB25_Handler\n");
    ClearGPIOIntStatus(GPIOINT_UART1);  
 }
+#if 0
+void GPIOB5_Handler(int gpio_num)
+{
+      //Linux Console
+   #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
+	   void rs_interrupt_buildin(int irq, void * dev_id, struct pt_regs * regs) ;
+	   rs_interrupt_buildin( GPIOINT_UART_BUILDIN, NULL, NULL ) ;
+   #endif
+//ACTION_TEC      printk("GPIOB5_Handler\n");
+   ClearGPIOIntStatus(GPIOINT_UART_BUILDIN);  
+}
+#endif
 
 void GPIOB30_Handler( int gpio_num )
 {
@@ -319,4 +347,86 @@
 	#endif
 }
 
+#ifdef ACTION_TEC
+void GPIOB27_Handler( int gpio_num )
+{
+      /* Clearing level */
+    unsigned long pre_value, cur_value;
+    int index = 0;
+	int in27 = 0;
+	SetGPIOIntEnable(GPIO27, 0);
+	WriteGPIOData( GPIO27, 1);
+#if 0
+    pre_value = cnxt_gettimeoffset();
+	while (in27 == 0) {
+		cur_value = cnxt_gettimeoffset();
+		if (cur_value <= pre_value)
+			index++;
+		pre_value = cur_value;		
+      	in27 = ReadGPIOData(GPIO27);
+      	printk("Index=%d, GPIOB27=%d, Time = %d\n", index, in27, cur_value);
+	}
+	if(index < 180)
+		*(unsigned short *)WD_REG = RESET_VALUE;
+	else {
+  	// Put restore to default routine here
+		Flush_MTD_Flash(MTDRAM_TOTAL_SIZE);
+		*(unsigned short *)WD_REG = RESET_VALUE;
+	}
+#endif	
+    ClearGPIOIntStatus(GPIO27);
+}
+#if 0
+int Flush_MTD_Flash(size_t len)
+{
+#define CONF_START 53
+    CNXT_FLASH_STATUS_E flashStatus;
+    CNXT_FLASH_SEGMENT_E segment = CNXT_FLASH_SEGMENT_3;
+
+    char *buf;
+    char *tmp_start;
+    buf = (char *)kmalloc(len, GFP_KERNEL);
+    memset(tmp_start, 0xff, len);
+try_avoid_CRC_error:
+    flashStatus = CnxtFlashOpen( segment );
+
+    switch ( flashStatus ) {
+      	case CNXT_FLASH_DATA_ERROR:
+            printk("Open to Flash Data Error(Open in mtdc for write): CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+            break;
+        case CNXT_FLASH_DATA_CRC_ERROR:
+            printk("Open to Flash Data CRC Error(Open in mtdc for write): CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+//            flashStatus = CnxtFlashWriteRequest(segment, (UINT16 *)buf, MTDRAM_TOTAL_SIZE);
+            goto try_avoid_CRC_error;
+            break;
+        case CNXT_FLASH_DATA_SIZE_ERROR:
+            printk("Open to Flash Data SIZE Error(Open in mtdc for write): CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+            break;
+        case CNXT_FLASH_OWNER_ERROR:
+            printk("Open to Wrong owner for requested Flash Segment!\n");
+            break;
+        default:
+            printk("Open to Flash Data Success: CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+    }
+
+    while (CnxtFlashReadRequest(segment, (UINT16 *)buf, MTDRAM_TOTAL_SIZE)==FALSE) {
+            printk("Read from Flash error, try !!!\n");
+    }
+
+    tmp_start = buf + CONF_START;
+    memset(tmp_start, 0xff, len-CONF_START);
+//        memset(buf,'\0',len);
+
+    while (flashStatus = CnxtFlashWriteRequest(segment, (UINT16 *)buf, MTDRAM_TOTAL_SIZE)==FALSE) {
+//        sleep(1);
+        printk("Writing to Flash error, try !!!\n");
+    }
+   
+	kfree(buf);
+    return 0;
+}
+#endif
+#endif
+
 EXPORT_SYMBOL(GPIO_SetGPIOIRQCallback);
+EXPORT_SYMBOL(GPIO_SetGPIOIRQRoutine);
Only in linux-2.4.6-actiontec-lightner-1.3/: config.works
diff -ur linux-2.4.6-actiontec/drivers/mtd/devices/mtdram.c linux-2.4.6-actiontec-lightner-1.3/drivers/mtd/devices/mtdram.c
--- linux-2.4.6-actiontec/drivers/mtd/devices/mtdram.c	2001-06-12 19:30:27.000000000 +0200
+++ linux-2.4.6-actiontec-lightner-1.3/drivers/mtd/devices/mtdram.c	2004-03-19 22:18:34.000000000 +0100
@@ -15,6 +15,13 @@
 #include <linux/ioport.h>
 #include <linux/mtd/compatmac.h>
 #include <linux/mtd/mtd.h>
+#include <asm/arch/bsptypes.h>
+#include <linux/cnxtflash.h>
+
+#define ACTION_TEC_SUPPORT_SST
+#ifdef ACTION_TEC
+  #include <asm/arch/gpio.h>
+#endif
 
 #ifndef CONFIG_MTDRAM_ABS_POS
   #define CONFIG_MTDRAM_ABS_POS 0
@@ -85,19 +92,157 @@
 
   memcpy(buf, mtd->priv + from, len);
 
+  { /* ACTION_TEC DEBUG */
+    int i;
+    for (i=0;i<len;i++)
+      printk("-%c-",buf[i]);
+    printk("\n\n");
+  }
+
   *retlen=len;
   return 0;
 }
 
+
+/*ACTION_TEC IMPORTANT NOTICE:
+    Don't expect you can read full 2 * 1024 bytes, because you will lose 
+        sizeof( CNXT_FLASH_SEGMENT_T )  about 128 bytes
+  But we don't give any failed to read msg.
+  So the maximum size is about
+       2 * 1024 - 128 bytes
+*/
+static char savetoflash[]="SaveToFlash";
+static char readfrflash[]="ReadFrFlash";
+static char resetmodem[]="ResetModem***";
+static char ledon[]="LedOn***";
+static char ledoff[]="LedOff***";
 static int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
 	      size_t *retlen, const u_char *buf)
 {
+  CNXT_FLASH_STATUS_E flashStatus;
+  CNXT_FLASH_SEGMENT_E segment = CNXT_FLASH_SEGMENT_3;
+
   DEBUG(MTD_DEBUG_LEVEL2, "ram_write(pos:%ld, len:%ld)\n", (long)to, (long)len);
   if (to + len > mtd->size) {
     DEBUG(MTD_DEBUG_LEVEL1, "ram_write() out of bounds (%ld > %ld)\n", (long)(to + len), (long)mtd->size);
     return -EINVAL;
   }
 
+  printk("\n\nmtdram staming = %s \n\n",buf);
+  if (strstr(buf,ledon)) {
+#define  LED_DELAY_PERIOD 30				//should be 15/25   mapping reset / ready
+    WriteGPIOData( GPIO19,0 );  //GPIO18 is being use for modem reset for TIBURON
+    printk("LED ON\n");
+    memset(buf,'\0',len);
+    *retlen=len;
+    return 0;
+  }
+
+  if (strstr(buf,ledoff)) {
+#define  LED_DELAY_PERIOD 30				//should be 15/25   mapping reset / ready
+    WriteGPIOData( GPIO19,1 );  //GPIO18 is being use for modem reset for TIBURON
+    printk("LED OFF\n");
+    memset(buf,'\0',len);
+    *retlen=len;
+    return 0;
+  }
+
+  if (strstr(buf,resetmodem)) {
+#define  LED_DELAY_PERIOD 30				//should be 15/25   mapping reset / ready
+    WriteGPIOData( GPIO17,0 );  //GPIO17 is being use for modem reset for TIBURON
+    TaskDelayMsec(LED_DELAY_PERIOD);
+    printk("Reset Modem\n");
+    WriteGPIOData( GPIO17,1 );
+    TaskDelayMsec(LED_DELAY_PERIOD);
+    memset(buf,'\0',len);
+    *retlen=len;
+    return 0;
+  }
+
+//  if(strcmp(buf,savetoflash)==0){
+  if (strstr(buf,savetoflash)) {
+    try_avoid_CRC_error:
+    flashStatus = CnxtFlashOpen( segment );
+
+    switch ( flashStatus ) {
+    case CNXT_FLASH_DATA_ERROR:
+      printk("Open to Flash Data Error(Open in mtdc for write): CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+      break;
+
+    case CNXT_FLASH_DATA_CRC_ERROR:
+      printk("Open to Flash Data CRC Error(Open in mtdc for write): CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+      flashStatus = CnxtFlashWriteRequest(
+                                         segment, 
+                                         (UINT16 *)mtd->priv,
+//                                         (MTDRAM_TOTAL_SIZE+1)/2
+                                         (MTDRAM_TOTAL_SIZE)
+                                         );
+      goto try_avoid_CRC_error;
+      break;
+
+    case CNXT_FLASH_DATA_SIZE_ERROR:
+      printk("Open to Flash Data SIZE Error(Open in mtdc for write): CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+      break;
+
+    case CNXT_FLASH_OWNER_ERROR:
+      printk("Open to Wrong owner for requested Flash Segment!\n");
+      break;
+
+    default:
+      printk("Open to Flash Data Success: CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+    }
+
+    while (flashStatus = CnxtFlashWriteRequest(
+                                              segment, 
+                                              (UINT16 *)mtd->priv,
+//                                              (MTDRAM_TOTAL_SIZE+1)/2)==FALSE){
+                                              MTDRAM_TOTAL_SIZE)==FALSE) {
+      printk("Writing to Flash error, try !!!\n");
+    }
+    memset(buf,'\0',len);
+    /*For write command, must return here, othewise will rule the original data which just coming from FLASH.*/
+    *retlen=len;
+    return 0;
+  }
+
+  if (strstr(buf,readfrflash)) {
+
+    flashStatus = CnxtFlashOpen( segment );
+
+    switch ( flashStatus ) {
+    case CNXT_FLASH_DATA_CRC_ERROR:
+      printk("Open to Flash Data CRC Error (Open in mtdc for read): CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+      break;
+
+    case CNXT_FLASH_DATA_SIZE_ERROR:
+      printk("Open to Flash Data SIZE Error (Open in mtdc for read): CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+      break;
+
+    case CNXT_FLASH_DATA_ERROR:
+      printk("Open to Flash Data Error (Open in mtdc for read): CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+      break;
+
+    case CNXT_FLASH_OWNER_ERROR:
+      printk("Open to Wrong owner for requested Flash Segment!\n");
+      break;
+
+    default:
+      printk("Open to Flash Data Success: CNXT_FLASH_SEGMENT_%d\n", segment+1 );
+    }
+
+    while (CnxtFlashReadRequest(
+                               segment, 
+                               (UINT16 *)mtd->priv,
+//                               (MTDRAM_TOTAL_SIZE+1)/2)==FALSE){
+                               MTDRAM_TOTAL_SIZE)==FALSE) {
+      printk("Read from Flash error, try !!!\n");
+    }
+    memset(buf,'\0',len);
+    /*For read command, must return here, othewise will rule the original data which just coming from FLASH.*/
+    *retlen=len;
+    return 0;
+  }
+
   memcpy ((char *)mtd->priv + to, buf, len);
 
   *retlen=len;
@@ -110,7 +255,7 @@
 #endif
 
 //static void __exit cleanup_mtdram(void)
-mod_exit_t cleanup_mtdram(void)
+mod_exit_t cleanup_mtdflash(void)
 {
   if (mtd_info) {
     del_mtd_device(mtd_info);
@@ -124,8 +269,28 @@
   }
 }
 
-mod_init_t init_mtdram(void)
+mod_init_t init_mtdflash(void)
 {
+  /*Just for init flash*/
+  CNXT_FLASH_STATUS_E flashStatus;
+  CNXT_FLASH_SEGMENT_E segment = CNXT_FLASH_SEGMENT_3;
+
+#ifdef ACTION_TEC_SUPPORT_SST
+  setBootsectorBlocksize ();
+#endif ACTION_TEC_SUPPORT_SST
+  flashStatus = CnxtFlashOpen( segment );
+
+#ifdef ACTION_TEC //SMao Enable GPIO 27 interrupt
+  SetGPIOIntEnable(GPIO27, 0);
+  SetGPIODir( GPIO27, GP_INPUT );
+//  SetGPIOIntPolarity (GPIO27, GP_IRQ_POL_POSITIVE);
+  SetGPIOIntPolarity (GPIO27, GP_IRQ_POL_NEGATIVE);  // Negtive	
+  SetGPIOInputEnable( GPIO27, GP_INPUTON );
+
+  GPIO_SetGPIOIRQRoutine(GPIO27, GPIOB27_Handler);
+  SetGPIOIntEnable(GPIO27, 1);
+#endif
+
    // Allocate some memory
    mtd_info = (struct mtd_info *)kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
    if (!mtd_info)
@@ -134,7 +299,7 @@
    memset(mtd_info, 0, sizeof(*mtd_info));
 
    // Setup the MTD structure
-   mtd_info->name = "mtdram test device";
+   mtd_info->name = "mtdflash device";
    mtd_info->type = MTD_RAM;
    mtd_info->flags = MTD_CAP_RAM;
    mtd_info->size = MTDRAM_TOTAL_SIZE;
@@ -152,6 +317,7 @@
      return -ENOMEM;
    }
    memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
+   DEBUG(MTD_DEBUG_LEVEL1, "/dev/mtdc0:%ld)\n", (long)MTDRAM_TOTAL_SIZE)
 
    mtd_info->module = THIS_MODULE;			
    mtd_info->erase = ram_erase;
@@ -174,5 +340,5 @@
    return 0;
 }
 
-module_init(init_mtdram);
-module_exit(cleanup_mtdram);
+module_init(init_mtdflash);
+module_exit(cleanup_mtdflash);
diff -ur linux-2.4.6-actiontec/include/asm-armnommu/arch-cx821xx/gpio.h linux-2.4.6-actiontec-lightner-1.3/include/asm-armnommu/arch-cx821xx/gpio.h
--- linux-2.4.6-actiontec/include/asm-armnommu/arch-cx821xx/gpio.h	2003-08-14 00:49:45.000000000 +0200
+++ linux-2.4.6-actiontec-lightner-1.3/include/asm-armnommu/arch-cx821xx/gpio.h	2004-04-21 00:13:18.000000000 +0200
@@ -236,6 +236,9 @@
 #define GPIOINT_F2_IRQ2	GPIO11
 #define GPIOINT_USB_PWR GPIO22
 
+/* ACTION_TEC */
+#define GPIOINT_UART_BUILDIN   GPIO5
+
 #if DEBUG_CONSOLE_ON_UART_2
 	#ifdef CONFIG_BD_RUSHMORE
 		#define GPIOINT_UART1   GPIO14
@@ -453,6 +456,9 @@
 extern void GPIOB24_Handler(int gpio_num);
 extern void GPIOB25_Handler(int gpio_num);
 extern void GPIOB30_Handler(int gpio_num);
+/* ACTION_TEC */
+extern void GPIOB27_Handler(int gpio_num);
+extern void GPIOB5_Handler(int gpio_num);
 
 #define MISC_BASE       ((UINT32)0x00350000)
 
diff -ur linux-2.4.6-actiontec/include/linux/cnxtflash.h linux-2.4.6-actiontec-lightner-1.3/include/linux/cnxtflash.h
--- linux-2.4.6-actiontec/include/linux/cnxtflash.h	2003-08-14 00:49:45.000000000 +0200
+++ linux-2.4.6-actiontec-lightner-1.3/include/linux/cnxtflash.h	2004-04-21 00:13:21.000000000 +0200
@@ -62,7 +62,11 @@
 {
 	CNXT_FLASH_SUCCESS,
 	CNXT_FLASH_DATA_ERROR,
-	CNXT_FLASH_OWNER_ERROR
+	CNXT_FLASH_OWNER_ERROR,
+#ifdef ACTION_TEC
+	CNXT_FLASH_DATA_CRC_ERROR,
+	CNXT_FLASH_DATA_SIZE_ERROR
+#endif
 } CNXT_FLASH_STATUS_E;
 
 typedef struct CNXT_FLASH_SEGMENT

