Index: flashchips.c
===================================================================
--- flashchips.c	(revision 2744)
+++ flashchips.c	(working copy)
@@ -32,6 +32,7 @@
 #include "sst28sf040.h"
 #include "sst49lfxxxc.h"
 #include "w49f002u.h"
+#include "w39v040fa.h"
 #include "sst39sf020.h"
 #include "sst49lf040.h"
 #include "pm49fl004.h"
@@ -105,7 +106,7 @@
 	{"W49V002FA", 	WINBOND_ID, 	W_49V002FA,	256, 128,
 	 probe_jedec,	erase_chip_jedec, write_49f002},
 	{"W39V040FA", 	WINBOND_ID, 	W_39V040FA,	512, 64*1024,
-	 probe_jedec,	erase_chip_jedec, write_39sf020},
+	 probe_jedec,	erase_chip_jedec, write_39v040fa},
 	{"W39V040A", 	WINBOND_ID, 	W_39V040A,	512, 64*1024,
 	 probe_jedec,	erase_chip_jedec, write_39sf020},
 	{"W39V040B",    WINBOND_ID,     W_39V040B,      512, 64*1024,
Index: Makefile
===================================================================
--- Makefile	(revision 2744)
+++ Makefile	(working copy)
@@ -24,7 +24,7 @@
 	am29f040b.o mx29f002.o sst39sf020.o m29f400bt.o w49f002u.o \
 	82802ab.o msys_doc.o pm49fl004.o sst49lf040.o sst49lfxxxc.o \
 	sst_fwhub.o layout.o lbtable.o flashchips.o flashrom.o \
-	sharplhf00l04.o
+	sharplhf00l04.o w39v040fa.o
 
 all: pciutils dep $(PROGRAM)
 
Index: w39v040fa.c
===================================================================
--- w39v040fa.c	(revision 0)
+++ w39v040fa.c	(revision 0)
@@ -0,0 +1,109 @@
+/*
+ * w39v040fa.c: driver for Winbond W39V040FAx flash models.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * Reference:
+ *	Winbond W39V040FA data sheets
+ *
+ */
+#include <sys/mman.h>
+#include <stdio.h>
+
+#include "flash.h"
+#include "jedec.h"
+#include "debug.h"
+
+enum {
+	BLOCKING_REGS_PHY_RANGE = 0x80000,
+     	BLOCKING_REGS_PHY_BASE = 0xFFB80000,
+};
+
+static volatile uint8_t* unprotect_39v040fa(void)
+{
+	uint8_t i, byte_val;
+	volatile uint8_t *block_regs_base;
+
+	block_regs_base = (volatile uint8_t*) mmap( 0, BLOCKING_REGS_PHY_RANGE, PROT_WRITE | PROT_READ, 
+			                            MAP_SHARED, fd_mem, (off_t)BLOCKING_REGS_PHY_BASE );
+	if (block_regs_base == NULL) {
+		perror("Error: Unable to map Winbond w39v040fa blocking registers!\n");
+		return NULL;
+	}
+
+	// 
+	// Unprotect the BIOS chip address range
+	//
+	for( i = 0; i < 8 ; i++ )
+	{
+		byte_val =  *(volatile uint8_t*)(block_regs_base + 2 + i*0x10000);
+		usleep(10);
+		byte_val &= 0xF8; // Enable full access to the chip
+		*(volatile uint8_t*)(block_regs_base + 2 + i*0x10000) = byte_val;
+		usleep(10);
+	}
+	
+	return block_regs_base;
+}
+
+static void protect_39v040fa(volatile uint8_t * reg_base)
+{
+	//
+ 	// Protect the BIOS chip address range
+	//
+	uint8_t i, byte_val;
+	volatile uint8_t *block_regs_base = reg_base;
+
+	for( i = 0; i < 8 ; i++ )
+	{
+		byte_val = *(volatile uint8_t*)(block_regs_base + 2 + i*0x10000);
+		usleep(10);
+		byte_val |= 1; // Prohibited to write in the block where set
+		*(volatile uint8_t*)(block_regs_base + 2 + i*0x10000) = byte_val;
+		usleep(10);
+	}
+	
+	munmap((void*) reg_base, BLOCKING_REGS_PHY_RANGE);
+}
+
+int write_39v040fa(struct flashchip *flash, uint8_t *buf)
+{
+ 	int i;
+	int total_size = flash->total_size * 1024;
+	int page_size = flash->page_size;
+	volatile uint8_t *bios = flash->virtual_memory;
+	volatile uint8_t * reg_base;
+					
+	reg_base = unprotect_39v040fa();
+	erase_chip_jedec(flash);
+
+	printf("Programming Page: ");
+		for (i = 0; i < total_size / page_size; i++) {
+			/* write to the sector */
+			printf("%04d at address: 0x%08x", i, i * page_size);
+			write_sector_jedec(bios, buf + i * page_size, bios + i * page_size, page_size);
+			printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
+			fflush(stdout);
+		}
+		printf("\n");
+
+	if(NULL != reg_base)
+	{
+	    protect_39v040fa(reg_base);
+    	}
+											
+	return (0);
+}
Index: w39v040fa.h
===================================================================
--- w39v040fa.h	(revision 0)
+++ w39v040fa.h	(revision 0)
@@ -0,0 +1,6 @@
+#ifndef __W39V040FA_H__
+#define __W39V040FA_H__ 1
+
+extern int write_39v040fa(struct flashchip *flash, uint8_t *buf);
+
+#endif				/* !__W39V040FA_H__ */
