[flashrom] GSoCs Winflashrom versus r126.

Luc Verhaegen libv at skynet.be
Sun Aug 9 01:47:09 CEST 2009


Here's the diff of winflashrom versus what seems to be the closest 
revision, namely r126.

diffstat:
 82802ab.h            |    2 
 Makefile             |   59 +--
 README               |   64 +++
 am29f040b.c          |    4 
 board_enable.c       |    4 
 chipset_enable.c     |    7 
 direct_io.c          |  654 +++++++++++++++++++++++++++++++++++++
 direct_io.h          |   28 +
 driver/sources       |   17 
 driver/winflashrom.c |  899 +++++++++++++++++++++++++++++++++++++++++++++++++++
 driver/winflashrom.h |   83 ++++
 error_msg.c          |   30 +
 error_msg.h          |   11 
 flashchips.c         |    3 
 flashrom.c           |   77 +++-
 interfaces.h         |   81 ++++
 jedec.h              |    7 
 layout.c             |    7 
 lbtable.c            |   13 
 libpci/Makefile      |   27 +
 libpci/access.c      |  282 +++++++++++++++
 libpci/filter.c      |   39 ++
 libpci/generic.c     |  214 ++++++++++++
 libpci/header.h      |  421 +++++++++++++++++++++++
 libpci/i386-ports.c  |  222 ++++++++++++
 libpci/internal.h    |   39 ++
 libpci/pci.h         |  135 +++++++
 m29f400bt.h          |    2 
 msys_doc.c           |    2 
 sharplhf00l04.h      |    3 
 sst49lfxxxc.c        |    2 
 todo.txt             |   11 
 udelay.h             |    6 
 w39v040fa.c          |  112 ++++++
 w39v040fa.h          |    6 
 winflashrom.rc       |    6 
 36 files changed, 3528 insertions(+), 51 deletions(-)

He pulled in a copy of libpci, not sure why.

Diff created from two cleaned up copies (.svn and created files removed) 
with -urN.

Have fun with it :)

Luc Verhaegen.
-------------- next part --------------
diff -urN flashrom-126/82802ab.h winflashrom/82802ab.h
--- flashrom-126/82802ab.h	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/82802ab.h	2009-08-09 01:25:02.000000000 +0200
@@ -43,7 +43,7 @@
 	*(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
 	*(volatile uint8_t *)(bios + 0x5555) = 0xA0;
 
-	usleep(200);
+	myusec_delay(200);
 }
 
 #endif				/* !__82802AB_H__ */
diff -urN flashrom-126/am29f040b.c winflashrom/am29f040b.c
--- flashrom-126/am29f040b.c	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/am29f040b.c	2009-08-09 01:25:00.000000000 +0200
@@ -24,9 +24,11 @@
 
 #include <stdio.h>
 #include <stdint.h>
+#include <windows.h>
 #include "flash.h"
 #include "jedec.h"
 #include "debug.h"
+//#include "udelay.h"
 
 static __inline__ int erase_sector_29f040b(volatile uint8_t *bios,
 					   unsigned long address)
@@ -38,7 +40,7 @@
 	*(bios + 0x2AA) = 0x55;
 	*(bios + address) = 0x30;
 
-	sleep(2);
+	myusec_delay(2000000);
 
 	/* wait for Toggle bit ready         */
 	toggle_ready_jedec(bios + address);
diff -urN flashrom-126/board_enable.c winflashrom/board_enable.c
--- flashrom-126/board_enable.c	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/board_enable.c	2009-08-09 01:25:00.000000000 +0200
@@ -16,13 +16,15 @@
  */
 
 #include <stdio.h>
-#include <pci/pci.h>
+#include "libpci/pci.h"
 #include <stdint.h>
 #include <string.h>
 
 #include "flash.h"
 #include "debug.h"
 
+#include "direct_io.h"
+
 /*
  * Helper functions for many Winbond superIOs of the w836xx range.
  */
diff -urN flashrom-126/chipset_enable.c winflashrom/chipset_enable.c
--- flashrom-126/chipset_enable.c	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/chipset_enable.c	2009-08-09 01:25:00.000000000 +0200
@@ -12,12 +12,14 @@
  */
 
 #include <stdio.h>
-#include <pci/pci.h>
+#include "libpci/pci.h"
 #include <stdlib.h>
 
 #include "flash.h"
 #include "debug.h"
 
+#include "direct_io.h"
+
 static int enable_flash_ali_m1533(struct pci_dev *dev, char *name)
 {
 	uint8_t tmp;
@@ -333,6 +335,9 @@
 
 	if (!smbusdev) {
 		fprintf(stderr, "ERROR: SMBus device not found. aborting\n");
+#ifdef __MINGW32_VERSION
+		cleanup_driver();
+#endif
 		exit(1);
 	}
 
diff -urN flashrom-126/direct_io.c winflashrom/direct_io.c
--- flashrom-126/direct_io.c	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/direct_io.c	2009-08-09 01:25:00.000000000 +0200
@@ -0,0 +1,654 @@
+#include <windows.h>
+#include <winioctl.h>
+#include <stdio.h>
+
+#include "interfaces.h" // Must be included after winioctl.h
+#include "direct_io.h"
+#include "error_msg.h"
+
+#define DRIVER_NAME       "winflashrom"
+
+//
+// verbosity of messages
+//
+#define VEBOSE_DEBUG_MESSAGE
+#undef VEBOSE_DEBUG_MESSAGE
+
+//
+// Globals
+//
+static HANDLE h_device = INVALID_HANDLE_VALUE;
+static UCHAR driver_path[MAX_PATH];
+
+//
+// Function implementation
+//
+
+static BOOLEAN setup_driver_name( PUCHAR driver_path )
+{
+    HANDLE file_handle;
+    unsigned long err_no;
+    unsigned long driver_path_len = 0;
+
+    //
+    // Get the current directory.
+    //
+    driver_path_len = GetCurrentDirectory(MAX_PATH, driver_path );
+
+    if (!driver_path_len) {
+	err_no = GetLastError();	    
+        printf("GetCurrentDirectory failed!  Error = %d \n",(int) err_no);
+				display_error_message(err_no);
+
+        return FALSE;
+    }
+
+    //
+    // Setup path name to driver file.
+    //
+
+    strcat(driver_path, "\\");
+    strcat(driver_path, DRIVER_NAME);
+    strcat(driver_path, ".sys");
+
+    //
+    // Insure driver file is in the specified directory.
+    //
+
+    if ((file_handle = CreateFile(driver_path,
+                                 GENERIC_READ | GENERIC_WRITE,
+                                 0,
+                                 NULL,
+                                 OPEN_EXISTING,
+                                 FILE_ATTRIBUTE_NORMAL,
+                                 NULL
+                                 )) == INVALID_HANDLE_VALUE) {
+
+
+        printf("Driver: BIOS_PROBE.SYS is not in the system directory. \n");
+
+        //
+        // Indicate failure.
+        //
+
+        return FALSE;
+    }
+
+    //
+    // Close open file handle.
+    //
+
+    if (file_handle) {
+
+        CloseHandle(file_handle);
+    }
+
+    //
+    // Indicate success.
+    //
+
+    return TRUE;
+
+
+}   // setup_driver_name
+
+
+static BOOL extract_driver(char *sz_driver, char *sz_out)
+/*++
+Routine Description:
+	find, load and extract the driver from resource
+
+Arguments: 
+	sz_driver = resource name or number
+	sz_out    = output filename
+    
+Return Value:
+	FALSE = function fails
+	TRUE = function succeds
+--*/
+
+{
+	HRSRC h_res;
+	HGLOBAL h_sys;
+	LPVOID p_sys;
+	HANDLE h_file;
+	unsigned long dw_size, dw_wri;
+
+	// find and load resources, return false if failed
+	if(!(h_res = FindResource(NULL, sz_driver, TEXT("DRIVER"))))
+		return FALSE;
+
+	if(!(h_sys = LoadResource(0, h_res)))
+		return FALSE;
+
+	dw_size = SizeofResource(0, h_res);
+	p_sys = LockResource(h_sys);
+
+	// create the driver file to the choosen path
+	if((h_file = CreateFile(sz_out, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE)
+		return FALSE;
+
+	// write the driver and and close the file handle
+	if(!WriteFile(h_file, p_sys, dw_size, &dw_wri, 0))
+	{
+		CloseHandle(h_file);
+	 	return FALSE;
+	}
+	
+	CloseHandle(h_file);
+	return TRUE;
+}
+
+
+static BOOL activate_driver(char *sz_serv, char *sz_path, BOOL activate)
+/*++
+Routine Description:
+	register, run, stop and unregister driver
+
+Arguments: 
+	sz_serv   = driver service name
+	sz_path   = path to driver
+	activate = register/unregisterNone
+    
+Return Value:
+	0 = function fails
+	1 = function succeds
+--*/
+{
+	BOOL b_stat;
+	SC_HANDLE h_sc, h_sr;
+	SERVICE_STATUS srv_stat;
+
+	b_stat = FALSE;
+	
+	h_sc = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
+	if(!h_sc) 
+	{
+	    printf("Error: failed to open service control manager\n");
+	    return FALSE;
+	}
+
+	if(activate)
+	{
+	    // start debug		
+ 	    printf("creating new service... \n");
+	    // end debug
+	    
+	    h_sr = CreateService(h_sc, sz_serv, sz_serv, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, 
+				SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, sz_path, 
+				NULL, NULL, NULL, NULL, NULL);
+		
+	    if(!h_sr) 
+	    {
+	    	// start debug		
+ 	    	printf("invalid service handle... \n");
+	    	// end debug
+		    
+		if(GetLastError() == ERROR_SERVICE_EXISTS)
+		{
+		    h_sr = OpenService(h_sc, sz_serv, SERVICE_ALL_ACCESS);
+		    
+		    if(!h_sr)
+		    {
+			printf("Error: failed to open access to the service (service already exists)\n");
+			    
+			CloseServiceHandle(h_sc);
+			return FALSE;
+		    }
+
+		    printf("Error: service already exist!\n");
+		}   
+		else
+		{
+		    // start debug
+		    printf("CreateService failed. But, not because of service exists :(\n");
+		    // end debug
+		    
+		    CloseServiceHandle(h_sc);
+		    return FALSE;
+		}
+	    }
+	    else
+	    {
+		if(StartService(h_sr, 0, NULL) == 0) 
+		{
+		    if(ERROR_SERVICE_ALREADY_RUNNING != GetLastError())
+		    {    
+                        CloseServiceHandle(h_sc);
+                        CloseServiceHandle(h_sr);
+                        return FALSE;
+		    }
+		} 
+		else 
+		{
+		    b_stat = TRUE;
+		}
+	    }
+	}
+	else
+	{
+		if(!(h_sr = OpenService(h_sc, sz_serv, SERVICE_ALL_ACCESS)))
+			b_stat = FALSE;
+		else
+			b_stat = (ControlService(h_sr, SERVICE_CONTROL_STOP, &srv_stat) == 0) ? FALSE : TRUE;
+
+		// unregister the driver
+		b_stat = (DeleteService(h_sr) == 0) ? FALSE : TRUE;
+	}
+
+	// close the service handle
+	if(h_sr) CloseServiceHandle(h_sr);
+	if(h_sc) CloseServiceHandle(h_sc);
+	return b_stat;
+}
+
+
+int init_driver()
+/*++
+Routine Description:
+	Initialize the driver interface
+
+Arguments: None
+    
+Return Value:
+    0 if error
+    1 if succeeded
+--*/
+{
+	unsigned long err_no;
+
+	// 
+    // Extract the driver binary from the resource in the executable
+    // 
+    if (extract_driver(TEXT("WINFLASHROMDRV"), "winflashrom.sys") == TRUE) {
+		printf("The driver has been extracted\n");
+		
+    } else {
+		display_error_message(GetLastError());
+		printf("Exiting..\n");
+		return 0;
+    }
+    
+    
+    //
+    // Setup full path to driver name.
+    //
+    if (!setup_driver_name(driver_path)) {
+		printf("Error: failed to setup driver name \n");
+        return 0;
+    }
+
+
+    //
+    // Try to activate the driver 
+    //
+    if(activate_driver(DRIVER_NAME, driver_path, TRUE) == TRUE) {
+		printf("The driver is registered and activated\n"); 
+    } else {
+		printf("Error: unable to register and activate the driver\n");
+		DeleteFile(driver_path);
+		return 0;		
+    }
+
+    //
+    // Try to open the newly installed driver.
+    //
+        
+    h_device = CreateFile( "\\\\.\\winflashrom",
+                GENERIC_READ | GENERIC_WRITE,
+                0,
+                NULL,
+                OPEN_EXISTING,
+                FILE_ATTRIBUTE_NORMAL,
+                NULL);
+
+    if ( h_device == INVALID_HANDLE_VALUE ){
+        err_no = GetLastError();	
+		printf ( "Error: CreateFile Failed : %d\n", (int) err_no );
+		display_error_message(err_no);
+
+		// cleanup resurces created and used up to now
+		activate_driver(DRIVER_NAME, driver_path, FALSE);
+		DeleteFile(driver_path);
+	
+        return 0;
+    }
+
+	return 1;
+}
+
+
+void cleanup_driver()
+{
+    //
+    // Close the access to the exported device interface in user-mode
+    //
+	if(h_device != INVALID_HANDLE_VALUE) {
+		CloseHandle(h_device); 
+	}
+
+    //
+    // Unload the driver.  Ignore any errors.
+    //
+    if(activate_driver(DRIVER_NAME, driver_path, FALSE) == TRUE) {
+		printf("The driver stopped and unloaded\n"); 
+    } else {
+		printf("Error: failed to stop and unload the driver\n");
+    }
+
+    //
+    // Delete the driver file
+    // 
+    DeleteFile(driver_path);
+}
+
+
+
+unsigned char inb(unsigned short port)
+{
+    IO_BYTE ioBuf;
+    unsigned long bytes_returned;
+    
+    ioBuf.port8 = port; // port address to read from
+    
+
+    if( INVALID_HANDLE_VALUE == h_device) {
+	printf("(inl) Error: the driver handle is invalid!\n");
+	return -1;
+    }
+    
+    if( FALSE == DeviceIoControl( h_device, 
+				 IOCTL_READ_PORT_BYTE,
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &bytes_returned,
+				 NULL))
+    {
+	display_error_message(GetLastError());
+	return -1;
+    }
+
+#ifdef VEBOSE_DEBUG_MESSAGE
+    printf("number of bytes returned from kernel (IOCTL_READ_PORT_BYTE) : %d\n", 
+	    bytes_returned);
+#endif //VEBOSE_DEBUG_MESSAGE
+
+    return ioBuf.value8;
+}
+
+
+void outb(unsigned char value, unsigned short port)
+{
+    IO_BYTE ioBuf;
+    unsigned long bytes_returned;
+    
+    ioBuf.port8 = port; // port address to write to
+    ioBuf.value8 = value; 
+
+    if( INVALID_HANDLE_VALUE == h_device) {
+	printf("(outw) Error: the driver handle is invalid!\n");
+	return;
+    }
+    
+    if( FALSE == DeviceIoControl( h_device, 
+				 IOCTL_WRITE_PORT_BYTE,
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &bytes_returned,
+				 NULL))
+    {
+	display_error_message(GetLastError());
+    }
+    
+ #ifdef VEBOSE_DEBUG_MESSAGE
+    printf("number of bytes returned from kernel (IOCTL_WRITE_PORT_BYTE) : %d\n", 
+	    bytes_returned);
+ #endif //VEBOSE_DEBUG_MESSAGE
+}
+
+
+unsigned short inw(unsigned short port)
+{
+    IO_WORD ioBuf;
+    unsigned long bytes_returned;
+    
+    ioBuf.port16 = port; // port address to read from
+    
+
+    if( INVALID_HANDLE_VALUE == h_device) {
+	printf("(inl) Error: the driver handle is invalid!\n");
+	return -1;
+    }
+    
+    if( FALSE == DeviceIoControl( h_device, 
+				 IOCTL_READ_PORT_WORD,
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &bytes_returned,
+				 NULL))
+    {
+	display_error_message(GetLastError());
+	return -1;
+    }
+
+#ifdef VEBOSE_DEBUG_MESSAGE
+    printf("number of bytes returned from kernel (IOCTL_READ_PORT_WORD) : %d\n", 
+	    bytes_returned);
+#endif //VEBOSE_DEBUG_MESSAGE
+
+    return ioBuf.value16;
+}
+
+
+void outw(unsigned short value, unsigned short port)
+{
+    IO_WORD ioBuf;
+    unsigned long bytes_returned;
+    
+    ioBuf.port16 = port; // port address to write to
+    ioBuf.value16 = value; 
+
+    if( INVALID_HANDLE_VALUE == h_device) {
+	printf("(outw) Error: the driver handle is invalid!\n");
+	return;
+    }
+    
+    if( FALSE == DeviceIoControl( h_device, 
+				 IOCTL_WRITE_PORT_WORD,
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &bytes_returned,
+				 NULL))
+    {
+	display_error_message(GetLastError());
+    }
+
+#ifdef VEBOSE_DEBUG_MESSAGE
+    printf("number of bytes returned from kernel (IOCTL_WRITE_PORT_WORD) : %d\n", 
+	    bytes_returned);
+#endif //VEBOSE_DEBUG_MESSAGE
+}
+
+
+unsigned long inl(unsigned short port)
+{
+    IO_LONG ioBuf;
+    unsigned long bytes_returned;
+    
+    ioBuf.port32 = port; // port address to read from
+    
+
+    if( INVALID_HANDLE_VALUE == h_device) {
+	printf("(inl) Error: the driver handle is invalid!\n");
+	return -1;
+    }
+    
+    if( FALSE == DeviceIoControl( h_device, 
+				 IOCTL_READ_PORT_LONG,
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &bytes_returned,
+				 NULL))
+    {
+	display_error_message(GetLastError());
+	return -1;
+    }
+
+	 #ifdef VEBOSE_DEBUG_MESSAGE
+    printf("number of bytes returned from kernel (IOCTL_READ_PORT_LONG) : %d\n", 
+	    bytes_returned);
+	 #endif //VEBOSE_DEBUG_MESSAGE
+
+    return ioBuf.value32;
+}
+
+
+void outl(unsigned long value, unsigned short port)
+{
+    IO_LONG ioBuf;
+    unsigned long bytes_returned;
+    
+    ioBuf.port32 = port; // port address to write to
+    ioBuf.value32 = value; 
+
+    if( INVALID_HANDLE_VALUE == h_device) {
+	printf("(outl) Error: the driver handle is invalid!\n");
+	return;
+    }
+    
+    if( FALSE == DeviceIoControl( h_device, 
+				 IOCTL_WRITE_PORT_LONG,
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &ioBuf,
+				 sizeof(ioBuf),
+				 &bytes_returned,
+				 NULL))
+    {
+	display_error_message(GetLastError());
+    }
+
+ #ifdef VEBOSE_DEBUG_MESSAGE
+    printf("number of bytes returned from kernel (IOCTL_WRITE_PORT_LONG) : %d\n", 
+	    bytes_returned);
+ #endif //VEBOSE_DEBUG_MESSAGE
+}
+
+
+void* map_physical_addr_range( unsigned long phy_addr_start, unsigned long size )
+/*++
+Routine Description:
+	Maps an MMIO range.
+
+Arguments:
+    phy_addr_start -  The start of physical address to be mapped.
+	size - The size of the MMIO range to map, in bytes.
+
+Return Value:
+    NULL - on error
+	pointer to the virtual address of the mapped MMIO range - on success
+
+Note:
+	-	The pointer returned from this function is in the context of the 
+	    usermode application that use this function.
+	-	You must call unmap_physical_addr_range when you are done with the  
+		mapped physical memory/MMIO range that you obtain with this function.
+--*/
+{
+	MMIO_MAP mmio_map;
+	unsigned long bytes_returned;
+
+	if( INVALID_HANDLE_VALUE == h_device) {
+		printf("(map_physical_addr_range) Error: the driver handle is invalid!\n");
+		return 0; // error
+    }
+    
+	mmio_map.phy_addr_start = phy_addr_start;
+	mmio_map.size = size;
+
+    if( FALSE == DeviceIoControl( h_device, 
+					IOCTL_MAP_MMIO,
+					&mmio_map,
+					sizeof(mmio_map),
+					&mmio_map,
+					sizeof(mmio_map),
+					&bytes_returned,
+					NULL))
+    {
+		display_error_message(GetLastError());
+		return NULL; // error
+    }
+
+ #ifdef VEBOSE_DEBUG_MESSAGE
+    printf("number of bytes returned from kernel (IOCTL_MAP_BIOS_CHIP) : %d\n", 
+	    bytes_returned);
+ #endif //VEBOSE_DEBUG_MESSAGE
+
+    return mmio_map.usermode_virt_addr; 
+}	
+
+
+int unmap_physical_addr_range( void* virt_addr_start, unsigned long size )
+/*++
+Routine Description:
+	Unmaps a previously mapped MMIO range.
+
+Arguments:
+    virt_addr_start - The start address of the mapped physical address.
+	                This parameter _must_ _be_ in the context of the 
+					currently executing application. It must be a 
+					pointer returned from a previous call to 
+					map_physical_addr_range function.
+	size - The size of the mapped MMIO range in bytes.
+
+Return Value:
+    0 - on error
+	1 - on success
+
+Note:
+	This function must be called when you are done with a 
+	mapped physical memory/MMIO range.
+--*/
+{
+	MMIO_MAP mmio_map;
+	unsigned long bytes_returned;
+
+	if( INVALID_HANDLE_VALUE == h_device) {
+		printf("(unmap_physical_addr_range) Error: the driver handle is invalid!\n");
+		return 0; // error
+    	}
+    
+	mmio_map.usermode_virt_addr = virt_addr_start;
+	mmio_map.size = size;
+
+    if( FALSE == DeviceIoControl( h_device, 
+					IOCTL_UNMAP_MMIO,
+					&mmio_map,
+					sizeof(mmio_map),
+					&mmio_map,
+					sizeof(mmio_map),
+					&bytes_returned,
+					NULL))
+    {
+		display_error_message(GetLastError());
+		return 0; // error
+    }
+
+ #ifdef VEBOSE_DEBUG_MESSAGE
+    printf("number of bytes returned from kernel (IOCTL_UNMAP_BIOS_CHIP) : %d\n", 
+	    bytes_returned);
+ #endif //VEBOSE_DEBUG_MESSAGE
+
+	return 1; // success
+}
+
diff -urN flashrom-126/direct_io.h winflashrom/direct_io.h
--- flashrom-126/direct_io.h	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/direct_io.h	2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,28 @@
+#ifndef __DIRECT_IO_H__
+#define __DIRECT_IO_H__
+
+int init_driver(); // returns 0 on error, 1 on success
+void cleanup_driver(); // must be called after done using the driver
+
+void* map_physical_addr_range( unsigned long phy_addr_start, 
+						 unsigned long size ); // returns NULL on error, valid pointer on success
+int unmap_physical_addr_range( void* virt_addr_start, 
+		        unsigned long size ); // must be called after done with the mapped physical memory
+
+unsigned long hal_pci_read_offset( unsigned long  bus, unsigned long  device,
+		                   unsigned long  function, unsigned long  offset, 
+				   unsigned char length);
+
+void hal_pci_write_offset( unsigned long  bus, unsigned long  device, 
+			   unsigned long  function, unsigned long  offset, 
+			   unsigned long value, unsigned char length );
+
+void outb(unsigned char value, unsigned short port);
+void outw(unsigned short value, unsigned short port);
+void outl(unsigned long value, unsigned short port);
+
+unsigned char inb(unsigned short port);
+unsigned short inw(unsigned short port);
+unsigned long inl(unsigned short port);
+
+#endif //__DIRECT_IO_H__
diff -urN flashrom-126/driver/sources winflashrom/driver/sources
--- flashrom-126/driver/sources	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/driver/sources	2007-06-27 02:15:18.000000000 +0200
@@ -0,0 +1,17 @@
+TARGETNAME=winflashrom
+TARGETPATH=.
+TARGETTYPE=DRIVER
+
+#
+# The  WinXP DDK has introduced the DDK_TARGET_OS environemnt variable
+# for conditional compilation.  The test here is designed to make this
+# sources file portable to the standalone Win 2K DDK environment.  Note,
+# however, that the required csq.h and csq.lib are not present in that
+# environment.
+#
+!if "$(DDK_TARGET_OS)"!="WinXP"
+C_DEFINES=$(C_DEFINES) -DW2K=1
+TARGETLIBS=$(DDK_LIB_PATH)\csq.lib
+!endif
+
+SOURCES=winflashrom.c
diff -urN flashrom-126/driver/winflashrom.c winflashrom/driver/winflashrom.c
--- flashrom-126/driver/winflashrom.c	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/driver/winflashrom.c	2007-08-20 07:13:56.000000000 +0200
@@ -0,0 +1,899 @@
+/*! \file
+ 
+Module Name:	winflashrom.c
+
+Abstract:   Main file of winflashrom device driver 
+
+Author:	    Darmawan Salihun 
+
+Environment:	Kernel mode
+
+Revision History:
+    
+    - (June 2007) BIOS Probing device driver Modified to work with winflashrom
+    - (July 29th) MMIO mapping limited to low 1MB and 4GB-20MB to 4GB physical address range
+*/
+
+#include "winflashrom.h"
+#include <devioctl.h>
+#include "../interfaces.h"
+
+static const ULONG _1MB = 0x100000;
+static const ULONG64 _4GB = 0x100000000 ;
+static const ULONG _4GB_min_20MB = (0x100000000 - (20*0x100000)); 
+
+
+NTSTATUS DriverEntry( IN PDRIVER_OBJECT  DriverObject, IN PUNICODE_STRING RegistryPath )
+/*!
+
+\brief 	Installable driver initialization entry point.
+    	This entry point is called directly by the I/O system.
+
+
+\param	DriverObject - pointer to the driver object
+
+\param 	RegistryPath - pointer to a unicode string representing the path,
+                   to driver-specific key in the registry.
+
+\retval    STATUS_SUCCESS if successful,
+\retval    STATUS_UNSUCCESSFUL otherwise
+
+*/
+{
+    NTSTATUS            status = STATUS_SUCCESS;
+    UNICODE_STRING      unicodeDeviceName;   
+    UNICODE_STRING      unicodeDosDeviceName;  
+    PDEVICE_OBJECT      deviceObject;
+    PDEVICE_EXTENSION	pDevExt;
+    ULONG		i;
+    
+    UNREFERENCED_PARAMETER (RegistryPath);
+
+    WINFLASHROM_KDPRINT(("DriverEntry Enter \n"));
+
+    DriverObject->DriverUnload = DispatchUnload;    
+
+    DriverObject->MajorFunction[IRP_MJ_CREATE]= DispatchCreate;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
+    DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead; 
+    DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoControl;
+
+   
+    (void) RtlInitUnicodeString(&unicodeDeviceName, WINFLASHROM_DEVICE_NAME_U);
+
+    status = IoCreateDevice(
+                DriverObject,
+                sizeof(DEVICE_EXTENSION),
+                &unicodeDeviceName,
+                FILE_DEVICE_UNKNOWN,
+                0,
+                (BOOLEAN) FALSE,
+                &deviceObject
+                );
+
+    if (!NT_SUCCESS(status))
+    {
+        return status;
+    }
+
+    WINFLASHROM_KDPRINT(("DeviceObject %p\n", deviceObject));
+
+    //
+    // Set the flag signifying that we will do direct I/O. This causes NT
+    // to lock the user buffer into memory when it's accessed
+    //
+    deviceObject->Flags |= DO_DIRECT_IO;
+
+    
+    //
+    // Allocate and initialize a Unicode String containing the Win32 name
+    // for our device.
+    //
+    (void)RtlInitUnicodeString( &unicodeDosDeviceName, WINFLASHROM_DOS_DEVICE_NAME_U );
+
+
+    status = IoCreateSymbolicLink(  (PUNICODE_STRING) &unicodeDosDeviceName,
+				    (PUNICODE_STRING) &unicodeDeviceName );
+
+    if (!NT_SUCCESS(status))
+    {
+        IoDeleteDevice(deviceObject);
+        return status;
+    }
+
+    //
+    // Initialize device extension
+    //
+    pDevExt = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
+    for(i = 0; i < MAX_MAPPED_MMIO; i++) 
+    {
+	pDevExt->mapZone[i].sysAddrBase = NULL;
+	pDevExt->mapZone[i].phyAddrStart = _4GB; // Note: _4GB is considered invalid phyAddrStart
+	pDevExt->mapZone[i].size = 0;
+	pDevExt->mapZone[i].usermodeAddrBase = NULL;
+	pDevExt->mapZone[i].pMdl = NULL;
+    }    
+    
+    WINFLASHROM_KDPRINT(("DriverEntry Exit = %x\n", status));
+
+    return status;
+}
+
+
+NTSTATUS DispatchCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
+/*!
+\brief
+   Process the create IRPs sent to this device.
+   This routine does nothing but signalling 
+   successful IRP handling.
+
+\param 	DeviceObject - pointer to a device object.
+\param	Irp - pointer to an I/O Request Packet.
+
+\retval	NT Status code
+*/
+{
+    NTSTATUS             status = STATUS_SUCCESS;
+
+    WINFLASHROM_KDPRINT(("DispatchCreate Enter\n"));
+
+    // 
+    // The dispatch routine for IRP_MJ_CREATE is called when a 
+    // file object associated with the device is created. 
+    // This is typically because of a call to CreateFile() in 
+    // a user-mode program or because another driver is 
+    // layering itself over a this driver. A driver is 
+    // required to supply a dispatch routine for IRP_MJ_CREATE.
+    //
+    WINFLASHROM_KDPRINT(("IRP_MJ_CREATE\n"));
+    Irp->IoStatus.Information = 0;
+    
+    //
+    // Save Status for return and complete Irp
+    //
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    WINFLASHROM_KDPRINT((" DispatchCreate Exit = %x\n", status));
+
+    return status;
+}
+
+
+NTSTATUS ReadPortByte(PIRP pIrp)
+/*!
+\brief
+    Process the IRPs with IOCTL_READ_PORT_BYTE code. 
+    This routine reads a byte from the designated port, 
+    and returns the value to usermode application 
+    through pointer to the locked-down usermode buffer 
+    in the IRP.
+
+
+\param	pIrp - pointer to an I/O Request Packet.
+
+\retval	NT Status code
+*/
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    IO_BYTE* pUsermodeMem =  (IO_BYTE*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+    if( NULL != pUsermodeMem) {
+        __asm
+	{
+	    pushad		    ;// save all register contents
+
+	    mov ebx, pUsermodeMem ;// build user-mode memory pointer register	
+	    mov dx,[ebx].port8	    ;// fetch input port addr
+	    in  al,dx		    ;// read the byte from the device
+	    mov [ebx].value8, al   ;// write probing result directly to user-mode memory
+
+	    popad		    ;// restore all saved register value
+	}
+	
+    } else {
+	status = STATUS_INVALID_USER_BUFFER;
+    }
+
+    return status;
+}
+
+
+NTSTATUS ReadPortWord(PIRP pIrp)
+/*!
+\brief
+    Process the IRPs with IOCTL_READ_PORT_WORD code. 
+    This routine reads a word from the designated port, 
+    and returns the value to usermode application 
+    through pointer to the locked-down usermode buffer 
+    in the IRP.
+
+\param 	pIrp - pointer to an I/O Request Packet.
+
+\retval	NT Status code
+*/
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    IO_WORD* pUsermodeMem =  (IO_WORD*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+    if( NULL != pUsermodeMem) {
+        __asm
+	{
+	    pushad		    ;// save all register contents
+
+	    mov ebx, pUsermodeMem	;// build user-mode memory pointer register	
+	    mov dx, [ebx].port16	;// fetch input port addr
+	    in  ax, dx			;// read the bytes from the device
+	    mov [ebx].value16, ax	;// write probing result directly to user-mode memory
+
+	    popad		    ;// restore all saved register value
+	}
+	
+    } else {
+	status = STATUS_INVALID_USER_BUFFER;
+    }
+
+    return status;
+}
+
+
+NTSTATUS ReadPortLong(PIRP pIrp)
+/*!
+\brief
+    Process the IRPs with IOCTL_READ_PORT_LONG code. 
+    This routine reads a DWORD from the designated port, 
+    and returns the value to usermode application 
+    through pointer to the locked-down usermode buffer 
+    in the IRP.
+
+\param	pIrp - pointer to an I/O Request Packet.
+
+\retval	NT Status code
+*/
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    IO_LONG* pUsermodeMem =  (IO_LONG*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+    if( NULL != pUsermodeMem) {
+        __asm
+	{
+	    pushad		    ;// save all register contents
+
+	    mov ebx, pUsermodeMem	;// build user-mode memory pointer register	
+	    mov dx, [ebx].port32	;// fetch input port addr
+	    in  eax, dx			;// read the bytes from the device
+	    mov [ebx].value32, eax	;// write probing result directly to user-mode memory
+
+	    popad		    ;// restore all saved register value
+	}
+	
+    } else {
+	status = STATUS_INVALID_USER_BUFFER;
+    }
+
+    return status;
+}
+
+
+NTSTATUS WritePortByte(PIRP pIrp)
+/*!
+\brief
+    Process the IRPs with IOCTL_WRITE_PORT_BYTE code. 
+    This routine writes a byte to the designated port. 
+    The value of the byte and the port address are obtained  
+    through pointer to the locked-down buffer in the IRP.
+
+\param 	pIrp - pointer to an I/O Request Packet.
+
+\retval	NT Status code
+--*/
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    IO_BYTE* pUsermodeMem =  (IO_BYTE*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+    if( NULL != pUsermodeMem) {
+        __asm
+	{
+	    pushad		    ;// save all register contents
+
+	    mov ebx, pUsermodeMem	;// build user-mode memory pointer register	
+	    mov dx, [ebx].port8	;// fetch input port addr
+    	    mov al, [ebx].value8	;// read the value to be written directly from user-mode memory
+	    out dx, al			;// write the byte to the device
+
+	    popad		    ;// restore all saved register value
+	}
+	
+    } else {
+	status = STATUS_INVALID_USER_BUFFER;
+    }
+
+    return status;
+}
+
+
+NTSTATUS WritePortWord(PIRP pIrp)
+/*!
+\brief
+    Process the IRPs with IOCTL_WRITE_PORT_WORD code. 
+    This routine writes a word to the designated port. 
+    The value of the word and the port address are obtained  
+    through pointer to the locked-down buffer in the IRP.
+
+\param	pIrp - pointer to an I/O Request Packet.
+
+\retval	NT Status code
+*/
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    IO_WORD* pUsermodeMem =  (IO_WORD*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+    if( NULL != pUsermodeMem) {
+        __asm
+	{
+	    pushad		    ;// save all register contents
+
+	    mov ebx, pUsermodeMem	;// build user-mode memory pointer register	
+	    mov dx, [ebx].port16	;// fetch input port addr
+    	    mov ax, [ebx].value16	;// read the value to be written directly from user-mode memory
+	    out dx, ax			;// write the bytes to the device
+
+	    popad		    ;// restore all saved register value
+	}
+	
+    } else {
+	status = STATUS_INVALID_USER_BUFFER;
+    }
+
+    return status;
+}
+
+
+NTSTATUS WritePortLong(PIRP pIrp)
+/*!
+\brief
+    Process the IRPs with IOCTL_WRITE_PORT_LONG code. 
+    This routine writes a dword to the designated port. 
+    The value of the dword and the port address are obtained  
+    through pointer to the locked-down buffer in the IRP.
+
+\param	pIrp - pointer to an I/O Request Packet.
+
+\retval	NT Status code
+--*/
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    IO_LONG* pUsermodeMem =  (IO_LONG*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+    if( NULL != pUsermodeMem) {
+        __asm
+	{
+	    pushad		    ;// save all register contents
+
+	    mov ebx, pUsermodeMem	;// build user-mode memory pointer register	
+	    mov dx, [ebx].port32	;// fetch input port addr
+    	    mov eax, [ebx].value32	;// read the value to be written directly from user-mode memory
+	    out dx, eax			;// write the bytes to the device
+
+	    popad		    ;// restore all saved register value
+	}
+	
+    } else {
+	status = STATUS_INVALID_USER_BUFFER;
+    }
+
+    return status;
+}
+
+
+bool VerifyMmioAddressRange(ULONG64 phyAddrStart, ULONG size, PDEVICE_EXTENSION pDevExt)
+/*!
+\brief
+   Verify whether the memory-mapped I/O address range 
+   requested by the user mode application lies within 
+   the "correct" address range that this driver will handle.
+
+   This verification is needed to prevent user mode 
+   application from mapping dangerous memory-mapped I/O 
+   address range to user mode application
+
+\param	phyAddrStart - starting physical address of the MMIO range to be mapped
+\param	size - the size of the MMIO range to be mapped
+\param	pDevExt - pointer to the DEVICE_EXTENSION of this driver
+
+\retval false if the MMIO range contains "incorrect" address range
+\retval true if the MMIO range doesn't contain "incorrect" address range
+*/
+{
+  int i;	
+  ULONG64 bottom, top ;
+
+  WINFLASHROM_KDPRINT(("phyAddrStart = 0x%X \n", phyAddrStart));
+  WINFLASHROM_KDPRINT(("size = 0x%X \n", size));
+    
+  /* First, check whether the MMIO range lies in the low 1MB range __or__ 
+   * whether the MMIO range lies between the 4GB-20MB and 4GB limit 
+   */
+
+  if((phyAddrStart > _1MB ) && ((phyAddrStart + size) < _4GB_min_20MB)) {
+  	return false;
+
+  } else if (phyAddrStart > _4GB) {
+	return false;
+  }
+  
+  /* Now, check whether part or all of the requested physical address range 
+   * has been mapped previously by the application that open access to this driver. 
+   */ 
+  
+    for(i = 0; i < MAX_MAPPED_MMIO; i++)
+    {
+	if( pDevExt->mapZone[i].phyAddrStart != _4GB)
+	{
+      	  bottom = pDevExt->mapZone[i].phyAddrStart;
+	  top = pDevExt->mapZone[i].phyAddrStart + pDevExt->mapZone[i].size;
+      
+	  WINFLASHROM_KDPRINT(("pDevExt->mapZone[%u].phyAddrStart = 0x%X \n", i, pDevExt->mapZone[i].phyAddrStart));
+	  WINFLASHROM_KDPRINT(("pDevExt->mapZone[%u].size = 0x%X \n", i, pDevExt->mapZone[i].size));
+          	  
+	  if( (phyAddrStart < bottom ) && ((phyAddrStart + size) > bottom) ){ // enclosing or intersection in lower limit of mapZone[i]
+	   	return false;
+		
+	  } else if ((phyAddrStart > bottom) && ((phyAddrStart + size) < top )) { // enclosed by mapZone[i]
+	   	return false;
+		
+	  } else if ((phyAddrStart < top) && ((phyAddrStart + size) > top )) {  // enclosing or intersection in upper limit of mapZone[i]
+		return false;			  
+	  }    
+   	}	
+	
+    }	    
+
+    return true;
+}
+
+
+
+NTSTATUS MapMmio(PDEVICE_OBJECT pDO, PIRP pIrp)
+/*!
+\brief
+    Process the IRPs with IOCTL_MAP_MMIO code. 
+    This routine maps a physical address range 
+    to the usermode application address space. 
+
+    This function can only map the area 
+    below the 4GB limit.
+
+\param	pDO - pointer to the device object of this driver.
+\param	pIrp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+    PDEVICE_EXTENSION pDevExt;
+    PHYSICAL_ADDRESS phyAddr;
+    MMIO_MAP* pUsermodeMem;
+    ULONG   i, free_idx;
+	    
+    pDevExt = (PDEVICE_EXTENSION) pDO->DeviceExtension;
+
+    //
+    // Check for free mapZone in the device extension.
+    // If none is free, return an error code.
+    //
+    for(i = 0; i < MAX_MAPPED_MMIO; i++)
+    {
+	if( pDevExt->mapZone[i].sysAddrBase == NULL )
+	{
+	    free_idx = i;
+	    break;
+	}	
+    }	    
+    
+    if( i == MAX_MAPPED_MMIO )
+    {
+	return STATUS_UNSUCCESSFUL;
+    }
+    
+    //
+    // We have obtained a free mapZone, check whether the requested address range  
+    // is valid and map the MMIO if it's valid
+    //    
+    pUsermodeMem =  (MMIO_MAP*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+    if( NULL == pUsermodeMem) {
+	return STATUS_INVALID_USER_BUFFER;
+    } 
+   
+    if( false == VerifyMmioAddressRange(pUsermodeMem->phy_addr_start, pUsermodeMem->size, pDevExt)){
+	return STATUS_UNSUCCESSFUL;
+    }
+	
+    
+    phyAddr.HighPart = 0;
+    phyAddr.LowPart = pUsermodeMem->phy_addr_start;
+
+    pDevExt->mapZone[free_idx].sysAddrBase = MmMapIoSpace( phyAddr, pUsermodeMem->size, MmNonCached);
+    if(NULL == pDevExt->mapZone[free_idx].sysAddrBase) {
+	return STATUS_BUFFER_TOO_SMALL;
+    
+    } else {
+	pDevExt->mapZone[free_idx].phyAddrStart = pUsermodeMem->phy_addr_start;
+    }
+	    
+    
+    pDevExt->mapZone[free_idx].pMdl = IoAllocateMdl(pDevExt->mapZone[free_idx].sysAddrBase, 
+						    pUsermodeMem->size, FALSE, FALSE, NULL);
+    if(NULL == pDevExt->mapZone[free_idx].pMdl) 	    
+    {
+	MmUnmapIoSpace(pDevExt->mapZone[free_idx].sysAddrBase, pUsermodeMem->size);
+	pDevExt->mapZone[free_idx].sysAddrBase = NULL;
+	pDevExt->mapZone[free_idx].phyAddrStart =  _4GB;
+	return STATUS_BUFFER_TOO_SMALL;
+    }
+
+    pDevExt->mapZone[free_idx].size = pUsermodeMem->size;
+
+    //
+    // Map the system virtual address to usermode virtual address
+    // 
+    MmBuildMdlForNonPagedPool(pDevExt->mapZone[free_idx].pMdl);
+    pDevExt->mapZone[free_idx].usermodeAddrBase = MmMapLockedPagesSpecifyCache(	pDevExt->mapZone[free_idx].pMdl, 
+										UserMode, MmNonCached, 
+										NULL, FALSE,  
+										NormalPagePriority);
+    if(NULL ==  pDevExt->mapZone[free_idx].usermodeAddrBase)
+    {
+	IoFreeMdl(pDevExt->mapZone[free_idx].pMdl);
+	MmUnmapIoSpace(pDevExt->mapZone[free_idx].sysAddrBase, pDevExt->mapZone[free_idx].size);
+	pDevExt->mapZone[free_idx].sysAddrBase = NULL;
+	pDevExt->mapZone[free_idx].phyAddrStart =  _4GB;
+	pDevExt->mapZone[free_idx].size = 0;
+	return STATUS_BUFFER_TOO_SMALL;
+    } 
+
+    // copy the resulting usermode virtual address to IRP "buffer"
+    pUsermodeMem->usermode_virt_addr = pDevExt->mapZone[free_idx].usermodeAddrBase;
+    
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS CleanupMmioMapping(PDEVICE_EXTENSION pDevExt, ULONG i)
+/*!
+\brief
+    This routine cleanup the mapping of a MMIO range 
+    and resources it consumes.
+    
+
+\param	pDevExt - pointer to the device extension of the driver
+\param	i - index of the mapZone to cleanup
+
+\retval	NT Status code
+*/
+{
+    if( NULL != pDevExt->mapZone[i].usermodeAddrBase )
+    {
+	MmUnmapLockedPages( pDevExt->mapZone[i].usermodeAddrBase, 
+			    pDevExt->mapZone[i].pMdl); 
+	pDevExt->mapZone[i].usermodeAddrBase = NULL;
+    }
+	    
+    if( NULL != pDevExt->mapZone[i].pMdl )
+    {
+	IoFreeMdl(pDevExt->mapZone[i].pMdl); 
+	pDevExt->mapZone[i].pMdl = NULL;
+    }
+	
+    if( NULL != pDevExt->mapZone[i].sysAddrBase )
+    {
+        MmUnmapIoSpace(	pDevExt->mapZone[i].sysAddrBase, 
+			pDevExt->mapZone[i].size); 
+        pDevExt->mapZone[i].sysAddrBase = NULL;
+	pDevExt->mapZone[i].phyAddrStart = _4GB;
+	pDevExt->mapZone[i].size = 0;
+    } 
+
+    return STATUS_SUCCESS; 
+}
+
+	
+NTSTATUS UnmapMmio(PDEVICE_OBJECT pDO, PIRP pIrp)
+/*!
+\brief
+    Process the IRPs with IOCTL_UNMAP_MMIO code. 
+    This routine unmaps a previously mapped physical 
+    address range.
+
+    This function can only unmap the area 
+    below the 4-GB limit.
+
+
+\param	pDO - pointer to the device object of this driver.
+\param	pIrp - pointer to an I/O Request Packet.
+
+\retval	NT Status code
+*/
+{
+    PDEVICE_EXTENSION pDevExt;
+    MMIO_MAP* pMmioMap;
+    ULONG i;
+    
+    // 
+    // Unmap the requested zone from the system address space 
+    // and update the device extension data
+    // 
+    pDevExt = (PDEVICE_EXTENSION) pDO->DeviceExtension;
+    pMmioMap = (MMIO_MAP*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+    for(i = 0 ; i < MAX_MAPPED_MMIO; i++)
+    {
+	if(pDevExt->mapZone[i].usermodeAddrBase == pMmioMap->usermode_virt_addr)
+	{
+	    CleanupMmioMapping(pDevExt, i);
+	    break;
+	}
+    }
+    
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS DispatchIoControl( IN PDEVICE_OBJECT pDO, IN PIRP pIrp )
+/*!
+\brief
+    Io control code dispatch routine
+           
+\param	pDO - pointer to a device object.
+\param	pIrp  - pointer to current Irp
+  
+\retval	NT status code.
+*/
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(pIrp);
+	
+    switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
+    {
+	case IOCTL_READ_PORT_BYTE:
+	    {
+		if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_BYTE)) {	
+		    status = ReadPortByte(pIrp);
+				
+		} else {
+		    status = STATUS_BUFFER_TOO_SMALL;
+		}
+	    }break;
+
+	case IOCTL_READ_PORT_WORD:
+	    {
+		if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_WORD)) {	
+		    status = ReadPortWord(pIrp);
+				
+		} else {
+		    status = STATUS_BUFFER_TOO_SMALL;
+		}
+	    }break;
+
+	case IOCTL_READ_PORT_LONG:
+	    {
+		if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_LONG)) {	
+		    status = ReadPortLong(pIrp);
+				
+		} else {
+		    status = STATUS_BUFFER_TOO_SMALL;
+		}
+	    }break;
+
+	case IOCTL_WRITE_PORT_BYTE:
+	    {
+		if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_BYTE)) {	
+		    status = WritePortByte(pIrp);
+				
+		} else {
+		    status = STATUS_BUFFER_TOO_SMALL;
+		}
+	    }break;
+
+	case IOCTL_WRITE_PORT_WORD:
+	    {
+		if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_WORD)) {	
+		    status = WritePortWord(pIrp);
+				
+		} else {
+		    status = STATUS_BUFFER_TOO_SMALL;
+		}
+	    }break;
+
+	case IOCTL_WRITE_PORT_LONG:
+	    {
+		if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_LONG)) {	
+		    status = WritePortLong(pIrp);
+				
+		} else {
+		    status = STATUS_BUFFER_TOO_SMALL;
+		}
+	    }break;
+
+	case IOCTL_MAP_MMIO:
+	    {
+		if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(MMIO_MAP)) {	
+		    status = MapMmio(pDO, pIrp);
+				
+		} else {
+		    status = STATUS_BUFFER_TOO_SMALL;
+		}
+	    }break;
+	    
+	case IOCTL_UNMAP_MMIO:
+	    {
+		if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(MMIO_MAP)) {	
+		    status = UnmapMmio(pDO, pIrp);
+				
+		} else {
+		    status = STATUS_BUFFER_TOO_SMALL;
+		}
+	    }break;
+	    
+	default:	    
+	    {
+		status = STATUS_INVALID_DEVICE_REQUEST;
+	    }break;
+    }
+    
+    //
+    // complete the I/O request and return appropriate values
+    //
+    pIrp->IoStatus.Status = status;
+    
+    // Set number of bytes to copy back to user-mode
+    if(status == STATUS_SUCCESS)
+    {
+	pIrp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
+    }
+    else
+    {
+	pIrp->IoStatus.Information = 0;
+    }
+    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
+
+    return status;
+}
+
+
+NTSTATUS DispatchRead( IN PDEVICE_OBJECT pDO, IN PIRP pIrp )
+/*!
+\brief
+    Read dispatch routine
+
+    This function does nothing. It's merely a place holder	 
+    to satisfy the need of the user mode code to open the driver 
+    with a GENERIC_READ parameter.
+ 
+\param	pDO - pointer to a device object.
+\param	pIrp  - pointer to current Irp
+  
+\retval	NT status code.
+*/
+{
+    // Just complete the I/O request right away
+    pIrp->IoStatus.Status = STATUS_SUCCESS;
+    pIrp->IoStatus.Information = 0;
+    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
+
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS DispatchWrite( IN PDEVICE_OBJECT pDO, IN PIRP pIrp )
+/*!
+\brief
+    Write dispatch routine
+
+    This function does nothing. It's merely a place holder	 
+    to satisfy the need of the user mode code to open the driver 
+    with a GENERIC_WRITE parameter.
+    
+\param	pDO - pointer to a device object.
+\param	pIrp  - pointer to current Irp
+  
+\retval	NT status code.
+*/
+{
+    // Just complete the I/O request right away
+    pIrp->IoStatus.Status = STATUS_SUCCESS;
+    pIrp->IoStatus.Information = 0;
+    IoCompleteRequest( pIrp, IO_NO_INCREMENT );
+
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS DispatchClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
+/*!
+\brief
+   Process the close IRPs sent to this device.
+
+   This function clean-up the mapped MMIO ranges that 
+   haven't been cleaned-up by a "buggy" usermode application.
+
+\param	DeviceObject - pointer to a device object.
+\param	Irp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+    PDEVICE_EXTENSION pDevExt;
+    ULONG	i;
+    NTSTATUS	status = STATUS_SUCCESS;
+    
+    WINFLASHROM_KDPRINT(("DispatchClose Enter\n"));
+
+    pDevExt = DeviceObject->DeviceExtension ;
+    
+    //
+    // Clean-up the mapped MMIO space in case the usermode
+    // application forget to call UnmapMmio for some MMIO zone.
+    // This is to guard against some buggy usermode application.
+    //
+    for(i = 0; i < MAX_MAPPED_MMIO; i++)
+    {
+	if(pDevExt->mapZone[i].sysAddrBase != NULL)
+	{
+	    CleanupMmioMapping(pDevExt, i);
+	}
+    }
+    
+    //
+    // The IRP_MJ_CLOSE dispatch routine is called when a file object
+    // opened on the driver is being removed from the system; that is,
+    // all file object handles have been closed and the reference count
+    // of the file object is down to 0. 
+    //
+    WINFLASHROM_KDPRINT(("IRP_MJ_CLOSE\n"));
+    Irp->IoStatus.Information = 0;
+
+    //
+    // Save Status for return and complete Irp
+    //
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    WINFLASHROM_KDPRINT((" DispatchClose Exit = %x\n", status));
+
+    return status;
+}
+
+
+VOID DispatchUnload( IN PDRIVER_OBJECT DriverObject )
+/*!
+\brief
+    Free all the allocated resources, etc.
+
+\param	DriverObject - pointer to a driver object.
+
+\retval	VOID
+*/
+{
+    PDEVICE_OBJECT  deviceObject = DriverObject->DeviceObject;
+    UNICODE_STRING  uniWin32NameString;
+
+    WINFLASHROM_KDPRINT(("DispatchUnload Enter\n"));
+
+    //
+    // Create counted string version of our Win32 device name.
+    //
+
+    RtlInitUnicodeString( &uniWin32NameString, WINFLASHROM_DOS_DEVICE_NAME_U );
+
+    IoDeleteSymbolicLink( &uniWin32NameString );
+
+    ASSERT(!deviceObject->AttachedDevice);
+    
+    IoDeleteDevice( deviceObject );
+ 
+    WINFLASHROM_KDPRINT(("DispatchUnload Exit\n"));
+    return;
+}
+
+
diff -urN flashrom-126/driver/winflashrom.h winflashrom/driver/winflashrom.h
--- flashrom-126/driver/winflashrom.h	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/driver/winflashrom.h	2007-07-28 20:23:42.000000000 +0200
@@ -0,0 +1,83 @@
+#ifndef __WINFLASHROM_H__
+#define __WINFLASHROM_H__
+
+#include <ntddk.h>
+#include "../interfaces.h"
+
+//  Debugging macros
+
+#if DBG
+#define WINFLASHROM_KDPRINT(_x_) \
+                DbgPrint("WINFLASHROM.SYS: ");\
+                DbgPrint _x_;
+#else
+
+#define WINFLASHROM_KDPRINT(_x_)
+
+#endif
+
+
+
+#define WINFLASHROM_DEVICE_NAME_U     L"\\Device\\winflashrom"
+#define WINFLASHROM_DOS_DEVICE_NAME_U L"\\DosDevices\\winflashrom"
+
+
+typedef struct _MMIO_RING_0_MAP{
+    PVOID  sysAddrBase;	    	// start of system virtual address of the mapped physical address range 
+    ULONG64 phyAddrStart;    	// start of physical address of the mapped MMIO
+    ULONG  size;		// size of the mapped physical address range 
+    PVOID  usermodeAddrBase; 	// pointer to the usermode virtual address where this range is mapped
+    PMDL pMdl;		    	// Memory Descriptor List for the memory mapped I/O range to be mapped
+}MMIO_RING_0_MAP, *PMMIO_RING_0_MAP;
+
+typedef struct _DEVICE_EXTENSION{
+    MMIO_RING_0_MAP mapZone[MAX_MAPPED_MMIO];   
+}DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+typedef enum {false = 0, true = 1} bool;
+
+NTSTATUS
+DriverEntry(
+    IN PDRIVER_OBJECT  DriverObject,
+    IN PUNICODE_STRING registryPath
+);
+
+NTSTATUS
+DispatchCreate(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    );
+
+NTSTATUS
+DispatchClose(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    );
+
+VOID
+DispatchUnload(
+    IN PDRIVER_OBJECT DriverObject
+    );
+
+NTSTATUS
+DispatchRead(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+);
+
+
+NTSTATUS
+DispatchWrite(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+);
+
+NTSTATUS
+DispatchIoControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+);
+
+#endif //__WINFLASHROM_H__
+
+
diff -urN flashrom-126/error_msg.c winflashrom/error_msg.c
--- flashrom-126/error_msg.c	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/error_msg.c	2009-08-09 01:25:00.000000000 +0200
@@ -0,0 +1,30 @@
+#include <windows.h>
+#include <stdio.h>
+#include "error_msg.h"
+
+VOID display_error_message(DWORD error_number)
+{
+	
+    LPVOID lpMsgBuf;
+    if (!FormatMessage( 
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+        FORMAT_MESSAGE_FROM_SYSTEM | 
+		FORMAT_MESSAGE_IGNORE_INSERTS,
+        NULL,
+		error_number,
+        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+		(LPTSTR) &lpMsgBuf,
+        0,
+		NULL ))
+    {
+	// Handle the error.
+	return;
+    }
+
+    // Display the string.
+    printf("Error! %s\n", (LPCTSTR)lpMsgBuf );
+
+    // Free the buffer.
+    LocalFree( lpMsgBuf );
+}
+
diff -urN flashrom-126/error_msg.h winflashrom/error_msg.h
--- flashrom-126/error_msg.h	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/error_msg.h	2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,11 @@
+#ifndef __ERROR_MSG_H__
+#define __ERROR_MSG_H__
+
+/*
+ * Note: Error number can be found easily with GetLastError() function
+ */
+
+void display_error_message(unsigned long error_number);
+
+#endif //__ERROR_MSG_H__
+
diff -urN flashrom-126/flashchips.c winflashrom/flashchips.c
--- flashrom-126/flashchips.c	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/flashchips.c	2009-08-09 01:25:00.000000000 +0200
@@ -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,
diff -urN flashrom-126/flashrom.c winflashrom/flashrom.c
--- flashrom-126/flashrom.c	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/flashrom.c	2009-08-09 01:25:00.000000000 +0200
@@ -27,7 +27,6 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -35,7 +34,14 @@
 #include <string.h>
 #include <stdlib.h>
 #include <getopt.h>
+
+#ifdef __MINGW32_VERSION
+#include "libpci/pci.h"
+#include "direct_io.h"
+#else
+#include <sys/mman.h>
 #include <pci/pci.h>
+#endif
 
 /* for iopl */
 #if defined (__sun) && (defined(__i386) || defined(__amd64))
@@ -104,6 +110,14 @@
 	volatile uint8_t *registers;
 	size_t size = flash->total_size * 1024;
 
+#ifdef __MINGW32_VERSION
+	registers = map_physical_addr_range((0xFFFFFFFF - 0x400000 - size + 1), size);
+ 	if (registers == NULL) {
+ 		perror("Can't map registers");
+ 		cleanup_driver();
+ 		exit(1);
+ 	}
+#else
 	registers = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
 			 fd_mem, (off_t) (0xFFFFFFFF - 0x400000 - size + 1));
 
@@ -111,6 +125,8 @@
 		perror("Can't mmap registers using " MEM_DEV);
 		exit(1);
 	}
+#endif
+	
 	flash->virtual_registers = registers;
 
 	return 0;
@@ -139,6 +155,14 @@
 		flash_baseaddr = (0xffffffff - size + 1);
 #endif
 
+#ifdef	__MINGW32_VERSION	
+		bios = map_physical_addr_range(flash_baseaddr, size);
+		if (bios == NULL) {
+ 			perror("Can't map bios chip");
+ 			cleanup_driver();
+			exit(1);
+		}
+#else
 		/* If getpagesize() > size -> 
 		 * "Can't mmap memory using /dev/mem: Invalid argument"
 		 * This should never happen as we don't support any flash chips
@@ -157,6 +181,7 @@
 			perror("Can't mmap memory using " MEM_DEV);
 			exit(1);
 		}
+#endif //__MINGW32_VERSION
 		flash->virtual_memory = bios;
 
 		if (flash->probe(flash) == 1) {
@@ -164,8 +189,12 @@
 			       flash->name, flash_baseaddr);
 			return flash;
 		}
-		munmap((void *)bios, size);
 
+#ifdef	__MINGW32_VERSION
+		unmap_physical_addr_range((void*)bios, size);	
+#else	
+		munmap((void *)bios, size);
+#endif
 		flash++;
 	}
 	return NULL;
@@ -338,29 +367,38 @@
 		filename = argv[optind++];
 
 	/* First get full io access */
+/* // I don't know yet how to include #ifdef __MINGW32_VERSION here :-(	
 #if defined (__sun) && (defined(__i386) || defined(__amd64))
 	if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
-#else
+#else 
 	if (iopl(3) != 0) {
 #endif
 		fprintf(stderr, "ERROR: iopl failed: \"%s\"\n",
 			strerror(errno));
 		exit(1);
 	}
-
+*/
+#ifdef __MINGW32_VERSION
+ 	if( init_driver() == 0)
+ 	{
+ 		printf("Error: failed to initialize driver interface\n");
+ 		exit(1);
+ 	}
+#endif
 	/* Initialize PCI access for flash enables */
 	pacc = pci_alloc();	/* Get the pci_access structure */
 	/* Set all options you want -- here we stick with the defaults */
 	pci_init(pacc);		/* Initialize the PCI library */
 	pci_scan_bus(pacc);	/* We want to get the list of devices */
 
+#ifndef __MINGW32_VERSION	
 	/* Open the memory device. A lot of functions need it */
 	if ((fd_mem = open(MEM_DEV, O_RDWR)) < 0) {
 		perror("Error: Can not access memory using " MEM_DEV
 		       ". You need to be root.");
 		exit(1);
 	}
-
+#endif
 	myusec_calibrate_delay();
 
 	/* We look at the lbtable first to see if we need a
@@ -381,6 +419,9 @@
 
 	if ((flash = probe_flash(flashchips)) == NULL) {
 		printf("No EEPROM/flash device found.\n");
+#ifdef __MINGW32_VERSION
+		cleanup_driver();
+#endif
 		exit(1);
 	}
 
@@ -389,6 +430,9 @@
 	if (!filename && !erase_it) {
 		// FIXME: Do we really want this feature implicitly?
 		printf("OK, only ENABLING flash write, but NOT FLASHING.\n");
+#ifdef __MINGW32_VERSION
+		cleanup_driver();
+#endif
 		return 0;
 	}
 
@@ -398,10 +442,16 @@
 	if (erase_it) {
 		printf("Erasing flash chip\n");
 		flash->erase(flash);
+#ifdef __MINGW32_VERSION
+		cleanup_driver();
+#endif
 		exit(0);
 	} else if (read_it) {
-		if ((image = fopen(filename, "w")) == NULL) {
+		if ((image = fopen(filename, "wb")) == NULL) {
 			perror(filename);
+#ifdef __MINGW32_VERSION
+		cleanup_driver();
+#endif
 			exit(1);
 		}
 		printf("Reading Flash...");
@@ -420,16 +470,25 @@
 	} else {
 		struct stat image_stat;
 
-		if ((image = fopen(filename, "r")) == NULL) {
+		if ((image = fopen(filename, "rb")) == NULL) {
 			perror(filename);
+#ifdef __MINGW32_VERSION
+		cleanup_driver();
+#endif
 			exit(1);
 		}
 		if (fstat(fileno(image), &image_stat) != 0) {
 			perror(filename);
+#ifdef __MINGW32_VERSION
+		cleanup_driver();
+#endif
 			exit(1);
 		}
 		if (image_stat.st_size != flash->total_size * 1024) {
 			fprintf(stderr, "Error: Image size doesnt match\n");
+#ifdef __MINGW32_VERSION
+		cleanup_driver();
+#endif
 			exit(1);
 		}
 
@@ -471,5 +530,9 @@
 	if (verify_it)
 		ret |= verify_flash(flash, buf);
 
+#ifdef __MINGW32_VERSION
+	cleanup_driver();
+#endif
 	return ret;
 }
+
diff -urN flashrom-126/interfaces.h winflashrom/interfaces.h
--- flashrom-126/interfaces.h	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/interfaces.h	2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,81 @@
+/*
+ *  This is the interface file that connects the user mode application and the kernel mode driver
+ *
+ *  NOTE:
+ *  -----
+ *  - You __have__ to put #include <winioctl.h> prior to including this file in your user mode application
+ *  - You probably need to put #include <devioctl.h> prior to including this file in your kernel mode driver 
+ *  These includes are needed for the CTL_CODE macro to work.
+ */
+
+#ifndef __INTERFACES_H__
+#define __INTERFACES_H__
+
+#define IOCTL_READ_PORT_BYTE	CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0801, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_READ_PORT_WORD	CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0802, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_READ_PORT_LONG	CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0803, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+
+#define IOCTL_WRITE_PORT_BYTE	CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0804, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_WRITE_PORT_WORD	CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0805, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_WRITE_PORT_LONG	CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0806, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+
+#define IOCTL_MAP_MMIO		CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0809, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_UNMAP_MMIO	CTL_CODE(FILE_DEVICE_UNKNOWN, 0x080A, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+
+
+#ifdef __GNUC__ // are we using GCC to compile this code?
+#define PACK_STRUC __attribute__((packed))
+#else
+#define PACK_STRUC 
+#endif 
+
+
+enum {
+    MAX_MAPPED_MMIO = 256 // maximum number of mapped memory-mapped I/O zones
+};
+
+#ifdef _MSC_VER // are we using MSVC to compile this code?
+#pragma pack (push, 1)
+#endif
+
+struct _IO_BYTE {
+    unsigned short port8;
+    unsigned char value8;
+}PACK_STRUC; 
+typedef struct _IO_BYTE IO_BYTE;
+
+struct _IO_WORD {
+    unsigned short port16; 
+    unsigned short value16;
+}PACK_STRUC;
+typedef struct _IO_WORD IO_WORD;
+
+struct _IO_LONG {
+    unsigned short port32;
+    unsigned long value32;
+}PACK_STRUC;
+typedef struct _IO_LONG IO_LONG; 
+
+struct _MMIO_MAP {
+    unsigned long phy_addr_start; // start address in physical address space to be mapped
+    unsigned long size; // size of the physical address space to map
+    void * usermode_virt_addr; // starting virtual address of the MMIO as seen from user mode
+}PACK_STRUC;
+typedef struct _MMIO_MAP MMIO_MAP;
+
+struct _PCI_ADDRESS {
+	unsigned long bus;
+	unsigned long device;
+	unsigned long function;
+	unsigned long value;
+	unsigned char offset;
+	unsigned char length; // length of the value to be written/read in bytes
+}PACK_STRUC;
+typedef struct _PCI_ADDRESS PCI_ADDRESS;
+
+#ifdef _MSC_VER // are we using MSVC to compile this code?
+#pragma pack (pop)
+#endif
+
+
+#endif //__INTERFACES_H__
diff -urN flashrom-126/jedec.h winflashrom/jedec.h
--- flashrom-126/jedec.h	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/jedec.h	2009-08-09 01:25:02.000000000 +0200
@@ -1,5 +1,8 @@
 #ifndef __JEDEC_H__
 #define __JEDEC_H__ 1
+
+#include "udelay.h"
+
 int write_byte_program_jedec(volatile uint8_t *bios, uint8_t *src,
 			     volatile uint8_t *dst);
 
@@ -51,7 +54,7 @@
 	*(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
 	*(volatile uint8_t *)(bios + 0x5555) = 0x20;
 
-	usleep(200);
+	myusec_delay(200);
 }
 
 extern __inline__ void protect_jedec(volatile uint8_t *bios)
@@ -60,7 +63,7 @@
 	*(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
 	*(volatile uint8_t *)(bios + 0x5555) = 0xA0;
 
-	usleep(200);
+	myusec_delay(200);
 }
 
 #endif				/* !__JEDEC_H__ */
diff -urN flashrom-126/layout.c winflashrom/layout.c
--- flashrom-126/layout.c	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/layout.c	2009-08-09 01:25:00.000000000 +0200
@@ -6,6 +6,10 @@
 #include "lbtable.h"
 #include "debug.h"
 
+#ifdef __MINGW32_VERSION
+#include "direct_io.h"
+#endif
+
 char *mainboard_vendor = NULL;
 char *mainboard_part = NULL;
 int romimages = 0;
@@ -90,6 +94,9 @@
 			       "values with --mainboard <vendor>:<mainboard>.\n\n",
 			       mainboard_vendor, mainboard_part, lb_vendor,
 			       lb_part);
+#ifdef __MINGW32_VERSION
+			cleanup_driver();
+#endif
 			exit(1);
 		}
 	}
diff -urN flashrom-126/lbtable.c winflashrom/lbtable.c
--- flashrom-126/lbtable.c	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/lbtable.c	2009-08-09 01:25:00.000000000 +0200
@@ -29,10 +29,10 @@
 #include <sys/types.h>
 #include <string.h>
 #include <errno.h>
-#include <sys/mman.h>
 #include "flash.h"
 #include "linuxbios_tables.h"
 #include "debug.h"
+#include "direct_io.h"
 
 char *lb_part = NULL, *lb_vendor = NULL;
 
@@ -181,12 +181,23 @@
 	struct lb_header *lb_table;
 	struct lb_record *rec, *last;
 
+#ifdef __MINGW32_VERSION
+	low_1MB = map_physical_addr_range(0x00000000, 1024 * 1024);
+	if (low_1MB == NULL) {
+		perror("Can't map low 1MB");
+		cleanup_driver();
+		exit(-2);
+	}
+#else
 	low_1MB = mmap(0, 1024 * 1024, PROT_READ, MAP_SHARED, fd_mem,
 		       0x00000000);
 	if (low_1MB == MAP_FAILED) {
 		perror("Can't mmap memory using " MEM_DEV);
 		exit(-2);
 	}
+#endif	
+
+	
 	lb_table = 0;
 	if (!lb_table)
 		lb_table = find_lb_table(low_1MB, 0x00000, 0x1000);
diff -urN flashrom-126/libpci/access.c winflashrom/libpci/access.c
--- flashrom-126/libpci/access.c	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/access.c	2007-08-20 07:13:56.000000000 +0200
@@ -0,0 +1,282 @@
+/*
+ *	$Id: access.c,v 1.10 2003/01/04 11:04:39 mj Exp $
+ *
+ *	The PCI Library -- User Access
+ *
+ *	Copyright (c) 1997--1999 Martin Mares <mj at ucw.cz>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "internal.h"
+
+static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
+  &pm_intel_conf1,
+  &pm_intel_conf2,
+};
+
+struct pci_access *
+pci_alloc(void)
+{
+  struct pci_access *a = malloc(sizeof(struct pci_access));
+  int i;
+
+  memset(a, 0, sizeof(*a));
+  for(i=0; i<PCI_ACCESS_MAX; i++)
+    if (pci_methods[i] && pci_methods[i]->config)
+      pci_methods[i]->config(a);
+  return a;
+}
+
+void *
+pci_malloc(struct pci_access *a, int size)
+{
+  void *x = malloc(size);
+
+  if (!x)
+    a->error("Out of memory (allocation of %d bytes failed)", size);
+  return x;
+}
+
+void
+pci_mfree(void *x)
+{
+  if (x)
+    free(x);
+}
+
+static void
+pci_generic_error(char *msg, ...)
+{
+  va_list args;
+
+  va_start(args, msg);
+  fputs("pcilib: ", stderr);
+  vfprintf(stderr, msg, args);
+  fputc('\n', stderr);
+  exit(1);
+}
+
+static void
+pci_generic_warn(char *msg, ...)
+{
+  va_list args;
+
+  va_start(args, msg);
+  fputs("pcilib: ", stderr);
+  vfprintf(stderr, msg, args);
+  fputc('\n', stderr);
+}
+
+static void
+pci_generic_debug(char *msg, ...)
+{
+  va_list args;
+
+  va_start(args, msg);
+  vfprintf(stdout, msg, args);
+  va_end(args);
+}
+
+
+void
+pci_init(struct pci_access *a)
+{
+  if (!a->error)
+    a->error = pci_generic_error;
+  if (!a->warning)
+    a->warning = pci_generic_warn;
+  if (!a->debug)
+    a->debug = pci_generic_debug;
+
+  if (a->method)
+    {
+      if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method])
+	a->error("This access method is not supported.\n");
+      a->methods = pci_methods[a->method];
+    }
+  else
+    {
+      unsigned int i;
+      for(i=0; i<PCI_ACCESS_MAX; i++)
+	if (pci_methods[i])
+	  {
+	    a->debug("Trying method %d...\n", i);
+	    if (pci_methods[i]->detect(a))
+	      {
+		a->debug("...OK\n");
+		a->methods = pci_methods[i];
+		a->method = i;
+		break;
+	      }
+	    a->debug("...No.\n");
+	  }
+      if (!a->methods)
+	a->error("Cannot find any working access method.");
+    }
+  a->debug("Decided to use %s\n", a->methods->name);
+
+  if( NULL != a->methods->init )
+  {
+    a->methods->init(a); //this is the bug, we don't need iopl3 init in windows
+  }
+}
+
+void
+pci_cleanup(struct pci_access *a)
+{
+  struct pci_dev *d, *e;
+
+  for(d=a->devices; d; d=e)
+  {
+      e = d->next;
+      pci_free_dev(d);
+  }
+  
+  if (a->methods)
+  {
+    if( a->methods->cleanup != NULL )
+    {  a->methods->cleanup(a); } //this is the bug, we don't need iopl3 cleanup in windows
+  }
+  
+  pci_mfree(a);
+}
+
+void
+pci_scan_bus(struct pci_access *a)
+{
+  a->methods->scan(a);
+}
+
+struct pci_dev *
+pci_alloc_dev(struct pci_access *a)
+{
+  struct pci_dev *d = pci_malloc(a, sizeof(struct pci_dev));
+
+  memset(d, 0, sizeof(*d));
+  d->access = a;
+  d->methods = a->methods;
+  if (d->methods->init_dev)
+    d->methods->init_dev(d);
+  return d;
+}
+
+int
+pci_link_dev(struct pci_access *a, struct pci_dev *d)
+{
+  d->next = a->devices;
+  a->devices = d;
+
+  return 1;
+}
+
+struct pci_dev *
+pci_get_dev(struct pci_access *a, word bus, byte dev, byte func)
+{
+  struct pci_dev *d = pci_alloc_dev(a);
+
+  d->bus = bus;
+  d->dev = dev;
+  d->func = func;
+  return d;
+}
+
+void pci_free_dev(struct pci_dev *d)
+{
+  if (d->methods->cleanup_dev)
+    d->methods->cleanup_dev(d);
+  pci_mfree(d);
+}
+
+static void
+pci_read_data(struct pci_dev *d, void *buf, int pos, int len)
+{
+  if (pos & (len-1))
+    d->access->error("Unaligned read: pos=%02x, len=%d", pos, len);
+  else if (!d->methods->read(d, pos, buf, len))
+    memset(buf, 0xff, len);
+}
+
+byte
+pci_read_byte(struct pci_dev *d, int pos)
+{
+  byte buf;
+  pci_read_data(d, &buf, pos, 1);
+  return buf;
+}
+
+word
+pci_read_word(struct pci_dev *d, int pos)
+{
+  word buf;
+  pci_read_data(d, &buf, pos, 2);
+  return buf;
+}
+
+u32
+pci_read_long(struct pci_dev *d, int pos)
+{
+  u32 buf;
+  pci_read_data(d, &buf, pos, 4);
+  return buf;
+}
+
+int
+pci_read_block(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  return d->methods->read(d, pos, buf, len);
+}
+
+static int
+pci_write_data(struct pci_dev *d, void *buf, int pos, int len)
+{
+  if (pos & (len-1))
+    d->access->error("Unaligned write: pos=%02x,len=%d", pos, len);
+  return d->methods->write(d, pos, buf, len);
+}
+
+int
+pci_write_byte(struct pci_dev *d, int pos, byte data)
+{
+  return pci_write_data(d, &data, pos, 1);
+}
+
+int
+pci_write_word(struct pci_dev *d, int pos, word data)
+{
+  word buf = data;
+  return pci_write_data(d, &buf, pos, 2);
+}
+
+int
+pci_write_long(struct pci_dev *d, int pos, u32 data)
+{
+  u32 buf = data;
+  return pci_write_data(d, &buf, pos, 4);
+}
+
+int
+pci_write_block(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  return d->methods->write(d, pos, buf, len);
+}
+
+int
+pci_fill_info(struct pci_dev *d, int flags)
+{
+  if (flags & PCI_FILL_RESCAN)
+    {
+      flags &= ~PCI_FILL_RESCAN;
+      d->known_fields = 0;
+    }
+  if (flags & ~d->known_fields)
+    d->known_fields |= d->methods->fill_info(d, flags & ~d->known_fields);
+  return d->known_fields;
+}
+
+
diff -urN flashrom-126/libpci/filter.c winflashrom/libpci/filter.c
--- flashrom-126/libpci/filter.c	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/filter.c	2007-06-27 02:13:02.000000000 +0200
@@ -0,0 +1,39 @@
+/*
+ *	$Id: filter.c,v 1.3 2002/03/30 15:39:25 mj Exp $
+ *
+ *	Linux PCI Library -- Device Filtering
+ *
+ *	Copyright (c) 1998--2002 Martin Mares <mj at ucw.cz>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "internal.h"
+
+void
+pci_filter_init(struct pci_access * a, struct pci_filter *f)
+{
+  f->bus = f->slot = f->func = -1;
+  f->vendor = f->device = -1;
+}
+
+
+int
+pci_filter_match(struct pci_filter *f, struct pci_dev *d)
+{
+  if ((f->bus >= 0 && f->bus != d->bus) ||
+      (f->slot >= 0 && f->slot != d->dev) ||
+      (f->func >= 0 && f->func != d->func))
+    return 0;
+  if (f->device >= 0 || f->vendor >= 0)
+    {
+      pci_fill_info(d, PCI_FILL_IDENT);
+      if ((f->device >= 0 && f->device != d->device_id) ||
+	  (f->vendor >= 0 && f->vendor != d->vendor_id))
+	return 0;
+    }
+  return 1;
+}
diff -urN flashrom-126/libpci/generic.c winflashrom/libpci/generic.c
--- flashrom-126/libpci/generic.c	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/generic.c	2007-06-27 02:13:02.000000000 +0200
@@ -0,0 +1,214 @@
+/*
+ *	$Id: generic.c,v 1.8 2002/12/27 19:01:51 mj Exp $
+ *
+ *	The PCI Library -- Generic Direct Access Functions
+ *
+ *	Copyright (c) 1997--2000 Martin Mares <mj at ucw.cz>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <string.h>
+
+#include "internal.h"
+
+void
+pci_generic_scan_bus(struct pci_access *a, byte *busmap, word bus)
+{
+  int multi, ht;
+  u32 vd;
+  u8 dev;
+  struct pci_dev *d;
+
+  struct pci_dev *t = pci_alloc_dev(a);
+
+  a->debug("Scanning bus %02x for devices...\n", bus);
+  if (busmap[bus])
+    {
+      a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus);
+      return;
+    }
+  busmap[bus] = 1;
+  t->bus = bus;
+  for(dev=0; dev<32; dev++)
+    {
+      t->dev = dev;
+      multi = 0;
+      for(t->func=0; !t->func || (multi && t->func<8); t->func++)
+	{
+	  vd = pci_read_long(t, PCI_VENDOR_ID);
+
+	  if (!vd || vd == 0xffffffff)
+	    continue;
+	  ht = pci_read_byte(t, PCI_HEADER_TYPE);
+	  if (!t->func)
+	    multi = ht & 0x80;
+	  ht &= 0x7f;
+	  d = pci_alloc_dev(a);
+	  d->bus = t->bus;
+	  d->dev = t->dev;
+	  d->func = t->func;
+	  d->vendor_id = (word)(vd & 0xffff);
+	  d->device_id = (word)(vd >> 16U);
+	  d->known_fields = PCI_FILL_IDENT;
+	  d->hdrtype = ht;
+	  pci_link_dev(a, d);
+	  switch (ht)
+	    {
+	    case PCI_HEADER_TYPE_NORMAL:
+	      break;
+	    case PCI_HEADER_TYPE_BRIDGE:
+	    case PCI_HEADER_TYPE_CARDBUS:
+	      pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
+	      break;
+	    default:
+	      a->debug("Device %02x:%02x.%d has unknown header type %02x.\n", d->bus, d->dev, d->func, ht);
+	    }
+	}
+    }
+}
+
+void
+pci_generic_scan(struct pci_access *a)
+{
+  byte busmap[256];
+
+  memset(busmap, 0, sizeof(busmap));
+  pci_generic_scan_bus(a, busmap, 0);
+}
+
+int
+pci_generic_fill_info(struct pci_dev *d, int flags)
+{
+  struct pci_access *a = d->access;
+
+  if (flags & PCI_FILL_IDENT)
+    {
+      d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
+      d->device_id = pci_read_word(d, PCI_DEVICE_ID);
+    }
+  if (flags & PCI_FILL_IRQ)
+    d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
+  if (flags & PCI_FILL_BASES)
+    {
+      int cnt = 0, i;
+      memset(d->base_addr, 0,  sizeof(d->base_addr));
+      switch (d->hdrtype)
+	{
+	case PCI_HEADER_TYPE_NORMAL:
+	  cnt = 6;
+	  break;
+	case PCI_HEADER_TYPE_BRIDGE:
+	  cnt = 2;
+	  break;
+	case PCI_HEADER_TYPE_CARDBUS:
+	  cnt = 1;
+	  break;
+	}
+      if (cnt)
+	{
+	  u16 cmd = pci_read_word(d, PCI_COMMAND);
+	  for(i=0; i<cnt; i++)
+	    {
+	      u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
+	      if (!x || x == (u32) ~0)
+		continue;
+	      d->base_addr[i] = x;
+	      if (x & PCI_BASE_ADDRESS_SPACE_IO)
+		{
+		  if (!a->buscentric && !(cmd & PCI_COMMAND_IO))
+		    d->base_addr[i] = 0;
+		}
+	      else if (a->buscentric || (cmd & PCI_COMMAND_MEMORY))
+		{
+		  if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
+		    {
+		      if (i >= cnt-1)
+			a->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d->bus, d->dev, d->func);
+		      else
+			{
+			  u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
+#ifdef HAVE_64BIT_ADDRESS
+			  d->base_addr[i-1] |= ((pciaddr_t) y) << 32;
+#else
+			  if (y)
+			    {
+			      a->warning("%02x:%02x.%d 64-bit device address ignored.", d->bus, d->dev, d->func);
+			      d->base_addr[i-1] = 0;
+			    }
+#endif
+			}
+		    }
+		}
+	      else
+		d->base_addr[i] = 0;
+	    }
+	}
+    }
+  if (flags & PCI_FILL_ROM_BASE)
+    {
+      int reg = 0;
+      d->rom_base_addr = 0;
+      switch (d->hdrtype)
+	{
+	case PCI_HEADER_TYPE_NORMAL:
+	  reg = PCI_ROM_ADDRESS;
+	  break;
+	case PCI_HEADER_TYPE_BRIDGE:
+	  reg = PCI_ROM_ADDRESS1;
+	  break;
+	}
+      if (reg)
+	{
+	  u32 a = pci_read_long(d, reg);
+	  if (a & PCI_ROM_ADDRESS_ENABLE)
+	    d->rom_base_addr = a;
+	}
+    }
+  return flags & ~PCI_FILL_SIZES;
+}
+
+static int
+pci_generic_block_op(struct pci_dev *d, int pos, byte *buf, int len,
+		 int (*r)(struct pci_dev *d, int pos, byte *buf, int len))
+{
+  if ((pos & 1) && len >= 1)
+    {
+      if (!r(d, pos, buf, 1))
+	return 0;
+      pos++; buf++; len--;
+    }
+  if ((pos & 3) && len >= 2)
+    {
+      if (!r(d, pos, buf, 2))
+	return 0;
+      pos += 2; buf += 2; len -= 2;
+    }
+  while (len >= 4)
+    {
+      if (!r(d, pos, buf, 4))
+	return 0;
+      pos += 4; buf += 4; len -= 4;
+    }
+  if (len >= 2)
+    {
+      if (!r(d, pos, buf, 2))
+	return 0;
+      pos += 2; buf += 2; len -= 2;
+    }
+  if (len && !r(d, pos, buf, 1))
+    return 0;
+  return 1;
+}
+
+int
+pci_generic_block_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  return pci_generic_block_op(d, pos, buf, len, d->access->methods->read);
+}
+
+int
+pci_generic_block_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  return pci_generic_block_op(d, pos, buf, len, d->access->methods->write);
+}
diff -urN flashrom-126/libpci/header.h winflashrom/libpci/header.h
--- flashrom-126/libpci/header.h	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/header.h	2007-06-27 02:13:02.000000000 +0200
@@ -0,0 +1,421 @@
+/*
+ *	$Id: header.h,v 1.9 2002/12/26 20:24:50 mj Exp $
+ *
+ *	The PCI Library -- PCI Header Structure (extracted from <linux/pci.h>)
+ *
+ *	Copyright (c) 1997--2002 Martin Mares <mj at ucw.cz>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID		0x00	/* 16 bits */
+#define PCI_DEVICE_ID		0x02	/* 16 bits */
+#define PCI_COMMAND		0x04	/* 16 bits */
+#define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
+#define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
+#define  PCI_COMMAND_MASTER	0x4	/* Enable bus mastering */
+#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
+#define  PCI_COMMAND_INVALIDATE	0x10	/* Use memory write and invalidate */
+#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
+#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
+#define  PCI_COMMAND_WAIT 	0x80	/* Enable address/data stepping */
+#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
+#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
+
+#define PCI_STATUS		0x06	/* 16 bits */
+#define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
+#define  PCI_STATUS_66MHZ	0x20	/* Support 66 Mhz PCI 2.1 bus */
+#define  PCI_STATUS_UDF		0x40	/* Support User Definable Features [obsolete] */
+#define  PCI_STATUS_FAST_BACK	0x80	/* Accept fast-back to back */
+#define  PCI_STATUS_PARITY	0x100	/* Detected parity error */
+#define  PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
+#define  PCI_STATUS_DEVSEL_FAST	0x000	
+#define  PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define  PCI_STATUS_DEVSEL_SLOW 0x400
+#define  PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define  PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define  PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define  PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define  PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION	0x08	/* High 24 bits are class, low 8
+					   revision */
+#define PCI_REVISION_ID         0x08    /* Revision ID */
+#define PCI_CLASS_PROG          0x09    /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE        0x0a    /* Device class */
+
+#define PCI_CACHE_LINE_SIZE	0x0c	/* 8 bits */
+#define PCI_LATENCY_TIMER	0x0d	/* 8 bits */
+#define PCI_HEADER_TYPE		0x0e	/* 8 bits */
+#define  PCI_HEADER_TYPE_NORMAL	0
+#define  PCI_HEADER_TYPE_BRIDGE 1
+#define  PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_BIST		0x0f	/* 8 bits */
+#define PCI_BIST_CODE_MASK	0x0f	/* Return result */
+#define PCI_BIST_START		0x40	/* 1 to start BIST, 2 secs or less */
+#define PCI_BIST_CAPABLE	0x80	/* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of 
+ * 0xffffffff to the register, and reading it back.  Only 
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
+#define PCI_BASE_ADDRESS_1	0x14	/* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3	0x1c	/* 32 bits */
+#define PCI_BASE_ADDRESS_4	0x20	/* 32 bits */
+#define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
+#define  PCI_BASE_ADDRESS_SPACE	0x01	/* 0 = memory, 1 = I/O */
+#define  PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define  PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define  PCI_BASE_ADDRESS_MEM_TYPE_32	0x00	/* 32 bit address */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_1M	0x02	/* Below 1M [obsolete] */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_64	0x04	/* 64 bit address */
+#define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
+#define  PCI_BASE_ADDRESS_MEM_MASK	(~0x0fUL)
+#define  PCI_BASE_ADDRESS_IO_MASK	(~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS		0x28
+#define PCI_SUBSYSTEM_VENDOR_ID	0x2c
+#define PCI_SUBSYSTEM_ID	0x2e  
+#define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
+#define  PCI_ROM_ADDRESS_ENABLE	0x01
+#define PCI_ROM_ADDRESS_MASK	(~0x7ffUL)
+
+#define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
+#define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
+#define PCI_MIN_GNT		0x3e	/* 8 bits */
+#define PCI_MAX_LAT		0x3f	/* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
+#define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
+#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER	0x1b	/* Latency timer for secondary interface */
+#define PCI_IO_BASE		0x1c	/* I/O range behind the bridge */
+#define PCI_IO_LIMIT		0x1d
+#define  PCI_IO_RANGE_TYPE_MASK	0x0f	/* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16	0x00
+#define  PCI_IO_RANGE_TYPE_32	0x01
+#define  PCI_IO_RANGE_MASK	~0x0f
+#define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE		0x20	/* Memory range behind */
+#define PCI_MEMORY_LIMIT	0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define  PCI_MEMORY_RANGE_MASK	~0x0f
+#define PCI_PREF_MEMORY_BASE	0x24	/* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT	0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define  PCI_PREF_RANGE_TYPE_32	0x00
+#define  PCI_PREF_RANGE_TYPE_64	0x01
+#define  PCI_PREF_RANGE_MASK	~0x0f
+#define PCI_PREF_BASE_UPPER32	0x28	/* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32	0x2c
+#define PCI_IO_BASE_UPPER16	0x30	/* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16	0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL	0x3e
+#define  PCI_BRIDGE_CTL_PARITY	0x01	/* Enable parity detection on secondary interface */
+#define  PCI_BRIDGE_CTL_SERR	0x02	/* The same for SERR forwarding */
+#define  PCI_BRIDGE_CTL_NO_ISA	0x04	/* Disable bridging of ISA ports */
+#define  PCI_BRIDGE_CTL_VGA	0x08	/* Forward VGA addresses */
+#define  PCI_BRIDGE_CTL_MASTER_ABORT 0x20  /* Report master aborts */
+#define  PCI_BRIDGE_CTL_BUS_RESET 0x40	/* Secondary bus reset */
+#define  PCI_BRIDGE_CTL_FAST_BACK 0x80	/* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+/* 0x14-0x15 reserved */
+#define PCI_CB_SEC_STATUS	0x16	/* Secondary status */
+#define PCI_CB_PRIMARY_BUS	0x18	/* PCI bus number */
+#define PCI_CB_CARD_BUS		0x19	/* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS	0x1a	/* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER	0x1b	/* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0	0x1c
+#define PCI_CB_MEMORY_LIMIT_0	0x20
+#define PCI_CB_MEMORY_BASE_1	0x24
+#define PCI_CB_MEMORY_LIMIT_1	0x28
+#define PCI_CB_IO_BASE_0	0x2c
+#define PCI_CB_IO_BASE_0_HI	0x2e
+#define PCI_CB_IO_LIMIT_0	0x30
+#define PCI_CB_IO_LIMIT_0_HI	0x32
+#define PCI_CB_IO_BASE_1	0x34
+#define PCI_CB_IO_BASE_1_HI	0x36
+#define PCI_CB_IO_LIMIT_1	0x38
+#define PCI_CB_IO_LIMIT_1_HI	0x3a
+#define  PCI_CB_IO_RANGE_MASK	~0x03
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL	0x3e
+#define  PCI_CB_BRIDGE_CTL_PARITY	0x01	/* Similar to standard bridge control register */
+#define  PCI_CB_BRIDGE_CTL_SERR		0x02
+#define  PCI_CB_BRIDGE_CTL_ISA		0x04
+#define  PCI_CB_BRIDGE_CTL_VGA		0x08
+#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT	0x20
+#define  PCI_CB_BRIDGE_CTL_CB_RESET	0x40	/* CardBus reset */
+#define  PCI_CB_BRIDGE_CTL_16BIT_INT	0x80	/* Enable interrupt for 16-bit cards */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100	/* Prefetch enable for both memory regions */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define  PCI_CB_BRIDGE_CTL_POST_WRITES	0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define PCI_CB_SUBSYSTEM_ID	0x42
+#define PCI_CB_LEGACY_MODE_BASE	0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID		0	/* Capability ID */
+#define  PCI_CAP_ID_PM		0x01	/* Power Management */
+#define  PCI_CAP_ID_AGP		0x02	/* Accelerated Graphics Port */
+#define  PCI_CAP_ID_VPD		0x03	/* Vital Product Data */
+#define  PCI_CAP_ID_SLOTID	0x04	/* Slot Identification */
+#define  PCI_CAP_ID_MSI		0x05	/* Message Signalled Interrupts */
+#define  PCI_CAP_ID_CHSWP	0x06	/* CompactPCI HotSwap */
+#define  PCI_CAP_ID_PCIX        0x07    /* PCI-X */
+#define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
+#define PCI_CAP_FLAGS		2	/* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF		4
+
+/* Power Management Registers */
+
+#define  PCI_PM_CAP_VER_MASK	0x0007	/* Version (2=PM1.1) */
+#define  PCI_PM_CAP_PME_CLOCK	0x0008	/* Clock required for PME generation */
+#define  PCI_PM_CAP_DSI		0x0020	/* Device specific initialization required */
+#define  PCI_PM_CAP_AUX_C_MASK	0x01c0	/* Maximum aux current required in D3cold */
+#define  PCI_PM_CAP_D1		0x0200	/* D1 power state support */
+#define  PCI_PM_CAP_D2		0x0400	/* D2 power state support */
+#define  PCI_PM_CAP_PME_D0	0x0800	/* PME can be asserted from D0 */
+#define  PCI_PM_CAP_PME_D1	0x1000	/* PME can be asserted from D1 */
+#define  PCI_PM_CAP_PME_D2	0x2000	/* PME can be asserted from D2 */
+#define  PCI_PM_CAP_PME_D3_HOT	0x4000	/* PME can be asserted from D3hot */
+#define  PCI_PM_CAP_PME_D3_COLD	0x8000	/* PME can be asserted from D3cold */
+#define PCI_PM_CTRL		4	/* PM control and status register */
+#define  PCI_PM_CTRL_STATE_MASK	0x0003	/* Current power state (D0 to D3) */
+#define  PCI_PM_CTRL_PME_ENABLE	0x0100	/* PME pin enable */
+#define  PCI_PM_CTRL_DATA_SEL_MASK	0x1e00	/* PM table data index */
+#define  PCI_PM_CTRL_DATA_SCALE_MASK	0x6000	/* PM table data scaling factor */
+#define  PCI_PM_CTRL_PME_STATUS	0x8000	/* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS	6	/* PPB support extensions */
+#define  PCI_PM_PPB_B2_B3	0x40	/* If bridge enters D3hot, bus enters: 0=B3, 1=B2 */
+#define  PCI_PM_BPCC_ENABLE	0x80	/* Secondary bus is power managed */
+#define PCI_PM_DATA_REGISTER	7	/* PM table contents read here */
+#define PCI_PM_SIZEOF		8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION		2	/* BCD version number */
+#define PCI_AGP_RFU		3	/* Rest of capability flags */
+#define PCI_AGP_STATUS		4	/* Status register */
+#define  PCI_AGP_STATUS_RQ_MASK	0xff000000	/* Maximum number of requests - 1 */
+#define  PCI_AGP_STATUS_ISOCH	0x10000	/* Isochronous transactions supported */
+#define  PCI_AGP_STATUS_ARQSZ_MASK	0xe000	/* log2(optimum async req size in bytes) - 4 */
+#define  PCI_AGP_STATUS_CAL_MASK	0x1c00	/* Calibration cycle timing */
+#define  PCI_AGP_STATUS_SBA	0x0200	/* Sideband addressing supported */
+#define  PCI_AGP_STATUS_ITA_COH	0x0100	/* In-aperture accesses always coherent */
+#define  PCI_AGP_STATUS_GART64	0x0080	/* 64-bit GART entries supported */
+#define  PCI_AGP_STATUS_HTRANS	0x0040	/* If 0, core logic can xlate host CPU accesses thru aperture */
+#define  PCI_AGP_STATUS_64BIT	0x0020	/* 64-bit addressing cycles supported */
+#define  PCI_AGP_STATUS_FW	0x0010	/* Fast write transfers supported */
+#define  PCI_AGP_STATUS_AGP3	0x0008	/* AGP3 mode supported */
+#define  PCI_AGP_STATUS_RATE4	0x0004	/* 4x transfer rate supported (RFU in AGP3 mode) */
+#define  PCI_AGP_STATUS_RATE2	0x0002	/* 2x transfer rate supported (8x in AGP3 mode) */
+#define  PCI_AGP_STATUS_RATE1	0x0001	/* 1x transfer rate supported (4x in AGP3 mode) */
+#define PCI_AGP_COMMAND		8	/* Control register */
+#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of requests */
+#define  PCI_AGP_COMMAND_ARQSZ_MASK	0xe000	/* log2(optimum async req size in bytes) - 4 */
+#define  PCI_AGP_COMMAND_CAL_MASK	0x1c00	/* Calibration cycle timing */
+#define  PCI_AGP_COMMAND_SBA	0x0200	/* Sideband addressing enabled */
+#define  PCI_AGP_COMMAND_AGP	0x0100	/* Allow processing of AGP transactions */
+#define  PCI_AGP_COMMAND_GART64	0x0080	/* 64-bit GART entries enabled */
+#define  PCI_AGP_COMMAND_64BIT	0x0020 	/* Allow generation of 64-bit addr cycles */
+#define  PCI_AGP_COMMAND_FW	0x0010 	/* Enable FW transfers */
+#define  PCI_AGP_COMMAND_RATE4	0x0004	/* Use 4x rate (RFU in AGP3 mode) */
+#define  PCI_AGP_COMMAND_RATE2	0x0002	/* Use 2x rate (8x in AGP3 mode) */
+#define  PCI_AGP_COMMAND_RATE1	0x0001	/* Use 1x rate (4x in AGP3 mode) */
+#define PCI_AGP_SIZEOF		12
+
+/* Slot Identification */
+
+#define PCI_SID_ESR		2	/* Expansion Slot Register */
+#define  PCI_SID_ESR_NSLOTS	0x1f	/* Number of expansion slots available */
+#define  PCI_SID_ESR_FIC	0x20	/* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR	3	/* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS		2	/* Various flags */
+#define  PCI_MSI_FLAGS_64BIT	0x80	/* 64-bit addresses allowed */
+#define  PCI_MSI_FLAGS_QSIZE	0x70	/* Message queue size configured */
+#define  PCI_MSI_FLAGS_QMASK	0x0e	/* Maximum queue size available */
+#define  PCI_MSI_FLAGS_ENABLE	0x01	/* MSI feature enabled */
+#define PCI_MSI_RFU		3	/* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO	4	/* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI	8	/* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32		8	/* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64		12	/* 16 bits of data for 64-bit devices */
+
+/* PCI-X */
+#define PCI_PCIX_COMMAND                                                2 /* Command register offset */
+#define PCI_PCIX_COMMAND_DPERE                                     0x0001 /* Data Parity Error Recover Enable */
+#define PCI_PCIX_COMMAND_ERO                                       0x0002 /* Enable Relaxed Ordering */
+#define PCI_PCIX_COMMAND_MAX_MEM_READ_BYTE_COUNT                   0x000c /* Maximum Memory Read Byte Count */
+#define PCI_PCIX_COMMAND_MAX_OUTSTANDING_SPLIT_TRANS               0x0070  
+#define PCI_PCIX_COMMAND_RESERVED                                   0xf80
+#define PCI_PCIX_STATUS                                                 4 /* Status register offset */
+#define PCI_PCIX_STATUS_FUNCTION                               0x00000007
+#define PCI_PCIX_STATUS_DEVICE                                 0x000000f8
+#define PCI_PCIX_STATUS_BUS                                    0x0000ff00
+#define PCI_PCIX_STATUS_64BIT                                  0x00010000
+#define PCI_PCIX_STATUS_133MHZ                                 0x00020000
+#define PCI_PCIX_STATUS_SC_DISCARDED                           0x00040000 /* Split Completion Discarded */
+#define PCI_PCIX_STATUS_UNEXPECTED_SC                          0x00080000 /* Unexpected Split Completion */
+#define PCI_PCIX_STATUS_DEVICE_COMPLEXITY                      0x00100000 /* 0 = simple device, 1 = bridge device */
+#define PCI_PCIX_STATUS_DESIGNED_MAX_MEM_READ_BYTE_COUNT       0x00600000 /* 0 = 512 bytes, 1 = 1024, 2 = 2048, 3 = 4096 */
+#define PCI_PCIX_STATUS_DESIGNED_MAX_OUTSTANDING_SPLIT_TRANS   0x03800000
+#define PCI_PCIX_STATUS_DESIGNED_MAX_CUMULATIVE_READ_SIZE      0x1c000000
+#define PCI_PCIX_STATUS_RCVD_SC_ERR_MESS                       0x20000000 /* Received Split Completion Error Message */
+#define PCI_PCIX_STATUS_RESERVED                               0xc0000000
+#define PCI_PCIX_SIZEOF		4
+
+/* PCI-X Bridges */
+#define PCI_PCIX_BRIDGE_SEC_STATUS                                      2 /* Secondary bus status register offset */
+#define PCI_PCIX_BRIDGE_SEC_STATUS_64BIT                           0x0001
+#define PCI_PCIX_BRIDGE_SEC_STATUS_133MHZ                          0x0002
+#define PCI_PCIX_BRIDGE_SEC_STATUS_SC_DISCARDED                    0x0004 /* Split Completion Discarded on secondary bus */
+#define PCI_PCIX_BRIDGE_SEC_STATUS_UNEXPECTED_SC                   0x0008 /* Unexpected Split Completion on secondary bus */
+#define PCI_PCIX_BRIDGE_SEC_STATUS_SC_OVERRUN                      0x0010 /* Split Completion Overrun on secondary bus */
+#define PCI_PCIX_BRIDGE_SEC_STATUS_SPLIT_REQUEST_DELAYED           0x0020
+#define PCI_PCIX_BRIDGE_SEC_STATUS_CLOCK_FREQ                      0x01c0
+#define PCI_PCIX_BRIDGE_SEC_STATUS_RESERVED                        0xfe00
+#define PCI_PCIX_BRIDGE_STATUS                                          4 /* Primary bus status register offset */
+#define PCI_PCIX_BRIDGE_STATUS_FUNCTION                        0x00000007
+#define PCI_PCIX_BRIDGE_STATUS_DEVICE                          0x000000f8
+#define PCI_PCIX_BRIDGE_STATUS_BUS                             0x0000ff00
+#define PCI_PCIX_BRIDGE_STATUS_64BIT                           0x00010000
+#define PCI_PCIX_BRIDGE_STATUS_133MHZ                          0x00020000
+#define PCI_PCIX_BRIDGE_STATUS_SC_DISCARDED                    0x00040000 /* Split Completion Discarded */
+#define PCI_PCIX_BRIDGE_STATUS_UNEXPECTED_SC                   0x00080000 /* Unexpected Split Completion */
+#define PCI_PCIX_BRIDGE_STATUS_SC_OVERRUN                      0x00100000 /* Split Completion Overrun */
+#define PCI_PCIX_BRIDGE_STATUS_SPLIT_REQUEST_DELAYED           0x00200000
+#define PCI_PCIX_BRIDGE_STATUS_RESERVED                        0xffc00000
+#define PCI_PCIX_BRIDGE_UPSTREAM_SPLIT_TRANS_CTRL                       8 /* Upstream Split Transaction Register offset */
+#define PCI_PCIX_BRIDGE_DOWNSTREAM_SPLIT_TRANS_CTRL                    12 /* Downstream Split Transaction Register offset */
+#define PCI_PCIX_BRIDGE_STR_CAPACITY                           0x0000ffff
+#define PCI_PCIX_BRIDGE_STR_COMMITMENT_LIMIT                   0xffff0000
+#define PCI_PCIX_BRIDGE_SIZEOF 12
+
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices.  The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ *	7:3 = slot
+ *	2:0 = function
+ */
+#define PCI_DEVFN(slot,func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn)		((devfn) & 0x07)
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED		0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA	0x0001
+
+#define PCI_BASE_CLASS_STORAGE		0x01
+#define PCI_CLASS_STORAGE_SCSI		0x0100
+#define PCI_CLASS_STORAGE_IDE		0x0101
+#define PCI_CLASS_STORAGE_FLOPPY	0x0102
+#define PCI_CLASS_STORAGE_IPI		0x0103
+#define PCI_CLASS_STORAGE_RAID		0x0104
+#define PCI_CLASS_STORAGE_OTHER		0x0180
+
+#define PCI_BASE_CLASS_NETWORK		0x02
+#define PCI_CLASS_NETWORK_ETHERNET	0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING	0x0201
+#define PCI_CLASS_NETWORK_FDDI		0x0202
+#define PCI_CLASS_NETWORK_ATM		0x0203
+#define PCI_CLASS_NETWORK_OTHER		0x0280
+
+#define PCI_BASE_CLASS_DISPLAY		0x03
+#define PCI_CLASS_DISPLAY_VGA		0x0300
+#define PCI_CLASS_DISPLAY_XGA		0x0301
+#define PCI_CLASS_DISPLAY_OTHER		0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA	0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO	0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO	0x0401
+#define PCI_CLASS_MULTIMEDIA_OTHER	0x0480
+
+#define PCI_BASE_CLASS_MEMORY		0x05
+#define  PCI_CLASS_MEMORY_RAM		0x0500
+#define  PCI_CLASS_MEMORY_FLASH		0x0501
+#define  PCI_CLASS_MEMORY_OTHER		0x0580
+
+#define PCI_BASE_CLASS_BRIDGE		0x06
+#define  PCI_CLASS_BRIDGE_HOST		0x0600
+#define  PCI_CLASS_BRIDGE_ISA		0x0601
+#define  PCI_CLASS_BRIDGE_EISA		0x0602
+#define  PCI_CLASS_BRIDGE_MC		0x0603
+#define  PCI_CLASS_BRIDGE_PCI		0x0604
+#define  PCI_CLASS_BRIDGE_PCMCIA	0x0605
+#define  PCI_CLASS_BRIDGE_NUBUS		0x0606
+#define  PCI_CLASS_BRIDGE_CARDBUS	0x0607
+#define  PCI_CLASS_BRIDGE_OTHER		0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION	0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL	0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_OTHER	0x0780
+
+#define PCI_BASE_CLASS_SYSTEM		0x08
+#define PCI_CLASS_SYSTEM_PIC		0x0800
+#define PCI_CLASS_SYSTEM_DMA		0x0801
+#define PCI_CLASS_SYSTEM_TIMER		0x0802
+#define PCI_CLASS_SYSTEM_RTC		0x0803
+#define PCI_CLASS_SYSTEM_OTHER		0x0880
+
+#define PCI_BASE_CLASS_INPUT		0x09
+#define PCI_CLASS_INPUT_KEYBOARD	0x0900
+#define PCI_CLASS_INPUT_PEN		0x0901
+#define PCI_CLASS_INPUT_MOUSE		0x0902
+#define PCI_CLASS_INPUT_OTHER		0x0980
+
+#define PCI_BASE_CLASS_DOCKING		0x0a
+#define PCI_CLASS_DOCKING_GENERIC	0x0a00
+#define PCI_CLASS_DOCKING_OTHER		0x0a01
+
+#define PCI_BASE_CLASS_PROCESSOR	0x0b
+#define PCI_CLASS_PROCESSOR_386		0x0b00
+#define PCI_CLASS_PROCESSOR_486		0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM	0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA	0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC	0x0b20
+#define PCI_CLASS_PROCESSOR_CO		0x0b40
+
+#define PCI_BASE_CLASS_SERIAL		0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE	0x0c00
+#define PCI_CLASS_SERIAL_ACCESS		0x0c01
+#define PCI_CLASS_SERIAL_SSA		0x0c02
+#define PCI_CLASS_SERIAL_USB		0x0c03
+#define PCI_CLASS_SERIAL_FIBER		0x0c04
+
+#define PCI_CLASS_OTHERS		0xff
+
+/* Several ID's we need in the library */
+
+#define PCI_VENDOR_ID_INTEL		0x8086
+#define PCI_VENDOR_ID_COMPAQ		0x0e11
diff -urN flashrom-126/libpci/i386-ports.c winflashrom/libpci/i386-ports.c
--- flashrom-126/libpci/i386-ports.c	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/i386-ports.c	2007-08-15 14:03:34.000000000 +0200
@@ -0,0 +1,222 @@
+/*
+ *	$Id: i386-ports.c,v 1.3 2002/03/30 15:39:25 mj Exp $
+ *
+ *	The PCI Library -- Direct Configuration access via i386 Ports
+ *
+ *	Copyright (c) 1997--1999 Martin Mares <mj at ucw.cz>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdlib.h>
+
+#include "../direct_io.h"
+#include "internal.h"
+
+/*
+ * Before we decide to use direct hardware access mechanisms, we try to do some
+ * trivial checks to ensure it at least _seems_ to be working -- we just test
+ * whether bus 00 contains a host bridge (this is similar to checking
+ * techniques used in XFree86, but ours should be more reliable since we
+ * attempt to make use of direct access hints provided by the PCI BIOS).
+ *
+ * This should be close to trivial, but it isn't, because there are buggy
+ * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
+ */
+
+static int
+intel_sanity_check(struct pci_access *a, struct pci_methods *m)
+{
+  struct pci_dev d;
+
+  a->debug("...sanity check \n");
+  d.bus = 0;
+  d.func = 0;
+  for(d.dev = 0; d.dev < 32; d.dev++)
+    {
+      u16 class, vendor;
+      if ( (m->read(&d, PCI_CLASS_DEVICE, (byte *) &class, sizeof(class)) &&
+	  (class == (PCI_CLASS_BRIDGE_HOST) || class == (PCI_CLASS_DISPLAY_VGA))) ||
+	  (m->read(&d, PCI_VENDOR_ID, (byte *) &vendor, sizeof(vendor)) &&
+	  (vendor == (PCI_VENDOR_ID_INTEL) || vendor == (PCI_VENDOR_ID_COMPAQ))) )
+	{
+	  a->debug("...outside the Asylum at 0/%02x/0 \n", d.dev);
+	  return 1;
+	}
+    }
+  a->debug("...insane\n");
+  return 0;
+}
+
+/*
+ *	Configuration type 1
+ */
+
+#define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
+
+static int
+conf1_detect(struct pci_access *a)
+{
+  unsigned int tmp;
+  int res = 0;
+
+  outb (0x01, 0xCFB);
+  tmp = inl (0xCF8);
+  outl (0x80000000, 0xCF8);
+  if (inl (0xCF8) == 0x80000000)
+    res = 1;
+  outl (tmp, 0xCF8);
+  if (res)
+    res = intel_sanity_check(a, &pm_intel_conf1);
+  return res;
+}
+
+static int
+conf1_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  u16 addr = 0xcfc + (pos&3);
+  outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
+
+  switch (len)
+    {
+    case 1:
+      buf[0] = inb(addr);
+      break;
+    case 2:
+      ((u16 *) buf)[0] = (inw(addr));
+      break;
+    case 4:
+      ((u32 *) buf)[0] = (inl(addr));
+      break;
+    default:
+      return pci_generic_block_read(d, pos, buf, len);
+    }
+  return 1;
+}
+
+static int
+conf1_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  u16 addr = 0xcfc + (pos&3);
+  outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
+
+  switch (len)
+    {
+    case 1:
+      outb(buf[0], addr);
+      break;
+    case 2:
+      outw((((u16 *) buf)[0]), addr);
+      break;
+    case 4:
+      outl((((u32 *) buf)[0]), addr);
+      break;
+    default:
+      return pci_generic_block_write(d, pos, buf, len);
+    }
+  return 1;
+}
+
+/*
+ *	Configuration type 2. Obsolete and brain-damaged, but existing.
+ */
+
+static int
+conf2_detect(struct pci_access *a)
+{
+  /* This is ugly and tends to produce false positives. Beware. */
+
+  outb(0x00, 0xCFB);
+  outb(0x00, 0xCF8);
+  outb(0x00, 0xCFA);
+  if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00)
+    return intel_sanity_check(a, &pm_intel_conf2);
+  else
+    return 0;
+}
+
+static int
+conf2_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  u16 addr = 0xc000 | (d->dev << 8) | pos;
+
+  if (d->dev >= 16)
+    /* conf2 supports only 16 devices per bus */
+    return 0;
+  outb((d->func << 1) | 0xf0, 0xcf8);
+  outb((u8)d->bus, 0xcfa);
+  switch (len)
+    {
+    case 1:
+      buf[0] = inb(addr);
+      break;
+    case 2:
+      ((u16 *) buf)[0] = (inw(addr));
+      break;
+    case 4:
+      ((u32 *) buf)[0] = (inl(addr));
+      break;
+    default:
+      outb(0, 0xcf8);
+      return pci_generic_block_read(d, pos, buf, len);
+    }
+  outb(0, 0xcf8);
+  return 1;
+}
+
+static int
+conf2_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+  u16 addr = 0xc000 | (d->dev << 8) | pos;
+
+  if (d->dev >= 16)
+    d->access->error("conf2_write: only first 16 devices exist.");
+  outb((d->func << 1) | 0xf0, 0xcf8);
+  outb((u8)d->bus, 0xcfa);
+  switch (len)
+    {
+    case 1:
+      outb(buf[0], addr);
+      break;
+    case 2:
+      outw((* (u16 *) buf), addr);
+      break;
+    case 4:
+      outl((* (u32 *) buf), addr);
+      break;
+    default:
+      outb(0, 0xcf8);
+      return pci_generic_block_write(d, pos, buf, len);
+    }
+  outb(0, 0xcf8);
+  return 1;
+}
+
+
+struct pci_methods pm_intel_conf1 = {
+  "Intel-conf1",
+  NULL,					/* config */
+  conf1_detect,
+  NULL,
+  NULL,
+  pci_generic_scan,
+  pci_generic_fill_info,
+  conf1_read,
+  conf1_write,
+  NULL,					/* init_dev */
+  NULL					/* cleanup_dev */
+};
+
+struct pci_methods pm_intel_conf2 = {
+  "Intel-conf2",
+  NULL,					/* config */
+  conf2_detect,
+  NULL,
+  NULL,
+  pci_generic_scan,
+  pci_generic_fill_info,
+  conf2_read,
+  conf2_write,
+  NULL,					/* init_dev */
+  NULL					/* cleanup_dev */
+};
diff -urN flashrom-126/libpci/internal.h winflashrom/libpci/internal.h
--- flashrom-126/libpci/internal.h	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/internal.h	2007-08-20 07:13:56.000000000 +0200
@@ -0,0 +1,39 @@
+/*
+ *	$Id: internal.h,v 1.7 2002/12/26 19:28:33 mj Exp $
+ *
+ *	The PCI Library -- Internal Include File
+ *
+ *	Copyright (c) 1997--2000 Martin Mares <mj at ucw.cz>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include "pci.h"
+
+struct pci_methods {
+  char *name;
+  void (*config)(struct pci_access *);
+  int (*detect)(struct pci_access *);
+  void (*init)(struct pci_access *);
+  void (*cleanup)(struct pci_access *);
+  void (*scan)(struct pci_access *);
+  int (*fill_info)(struct pci_dev *, int flags);
+  int (*read)(struct pci_dev *, int pos, byte *buf, int len);
+  int (*write)(struct pci_dev *, int pos, byte *buf, int len);
+  void (*init_dev)(struct pci_dev *);
+  void (*cleanup_dev)(struct pci_dev *);
+};
+
+void pci_generic_scan_bus(struct pci_access *, byte *busmap, word bus);
+void pci_generic_scan(struct pci_access *);
+int pci_generic_fill_info(struct pci_dev *, int flags);
+int pci_generic_block_read(struct pci_dev *, int pos, byte *buf, int len);
+int pci_generic_block_write(struct pci_dev *, int pos, byte *buf, int len);
+
+void *pci_malloc(struct pci_access *, int);
+void pci_mfree(void *);
+
+struct pci_dev *pci_alloc_dev(struct pci_access *);
+int pci_link_dev(struct pci_access *, struct pci_dev *);
+
+extern struct pci_methods pm_intel_conf1, pm_intel_conf2;
diff -urN flashrom-126/libpci/Makefile winflashrom/libpci/Makefile
--- flashrom-126/libpci/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/Makefile	2007-08-20 07:13:56.000000000 +0200
@@ -0,0 +1,27 @@
+#
+# Makefile for temporary PCI library 
+# 
+# by Darmawan Salihun <darmawan.salihun at gmail.com>
+#
+
+
+LIBRARY = libpci.a
+
+AR 	= ar
+CC      = gcc
+STRIP	= strip
+CFLAGS  = -O2 -g -Wall -Werror
+STRIP_ARGS = -s
+
+OBJS = access.o filter.o generic.o i386-ports.o 
+
+all: $(LIBRARY)
+
+$(LIBRARY): $(OBJS)
+	$(AR) -r $(LIBRARY) $(OBJS)
+
+clean:
+	rm -f *.o *~ *.a
+
+.PHONY: all clean
+
diff -urN flashrom-126/libpci/pci.h winflashrom/libpci/pci.h
--- flashrom-126/libpci/pci.h	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/pci.h	2007-08-15 14:03:34.000000000 +0200
@@ -0,0 +1,135 @@
+/*
+ *	$Id: pci.h,v 1.12 2003/01/04 11:04:39 mj Exp $
+ *
+ *	The PCI Library
+ *
+ *	Copyright (c) 1997--2002 Martin Mares <mj at ucw.cz>
+ *
+ *	Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _PCI_LIB_H
+#define _PCI_LIB_H
+
+#include "header.h"
+
+/*
+ *	Types
+ */
+
+typedef unsigned char byte;
+typedef unsigned char u8;
+typedef unsigned short word;
+typedef unsigned short u16;
+typedef unsigned long u32;
+
+typedef unsigned long pciaddr_t;
+
+/*
+ *	PCI Access Structure
+ */
+
+struct pci_methods;
+
+enum pci_access_type {
+  /* Known access methods, remember to update access.c as well */
+  PCI_ACCESS_WINDOWS_HAL,		/* Windows Hardware Abstraction Layer */
+  PCI_ACCESS_I386_TYPE1,		/* i386 ports, type 1 (params: none) */
+  PCI_ACCESS_I386_TYPE2,		/* i386 ports, type 2 (params: none) */
+  PCI_ACCESS_MAX
+};
+
+struct pci_access {
+  /* Options you can change: */
+  unsigned int method;			/* Access method */
+  char *method_params[PCI_ACCESS_MAX];	/* Parameters for the methods */
+  int buscentric;			/* Bus-centric view of the world */
+
+  /* Functions you can override: */
+  void (*error)(char *msg, ...);	/* Write error message and quit */
+  void (*warning)(char *msg, ...);	/* Write a warning message */
+  void (*debug)(char *msg, ...);	/* Write a debugging message */
+
+  struct pci_dev *devices;		/* Devices found on this bus */
+
+  /* Fields used internally: */
+  struct pci_methods *methods;
+};
+
+/* Initialize PCI access */
+struct pci_access *pci_alloc(void);
+void pci_init(struct pci_access *);
+void pci_cleanup(struct pci_access *);
+
+/* Scanning of devices */
+void pci_scan_bus(struct pci_access *acc);
+struct pci_dev *pci_get_dev(struct pci_access *acc, word bus, byte dev, byte func); /* Raw access to specified device */
+void pci_free_dev(struct pci_dev *);
+
+/*
+ *	Devices
+ */
+
+struct pci_dev {
+  struct pci_dev *next;			/* Next device in the chain */
+  word bus;				/* Higher byte can select host bridges */
+  byte dev, func;			/* Device and function */
+
+  /* These fields are set by pci_fill_info() */
+  int known_fields;			/* Set of info fields already known */
+  word vendor_id, device_id;		/* Identity of the device */
+  int irq;				/* IRQ number */
+  pciaddr_t base_addr[6];		/* Base addresses */
+  pciaddr_t size[6];			/* Region sizes */
+  pciaddr_t rom_base_addr;		/* Expansion ROM base address */
+  pciaddr_t rom_size;			/* Expansion ROM size */
+
+  /* Fields used internally: */
+  struct pci_access *access;
+  struct pci_methods *methods;
+  int hdrtype;				/* Direct methods: header type */
+  void *aux;				/* Auxillary data */
+};
+
+#define PCI_ADDR_IO_MASK (~(pciaddr_t) 0x3)
+#define PCI_ADDR_MEM_MASK (~(pciaddr_t) 0xf)
+
+byte pci_read_byte(struct pci_dev *, int pos); /* Access to configuration space */
+word pci_read_word(struct pci_dev *, int pos);
+u32  pci_read_long(struct pci_dev *, int pos);
+int pci_read_block(struct pci_dev *, int pos, byte *buf, int len);
+int pci_write_byte(struct pci_dev *, int pos, byte data);
+int pci_write_word(struct pci_dev *, int pos, word data);
+int pci_write_long(struct pci_dev *, int pos, u32 data);
+int pci_write_block(struct pci_dev *, int pos, byte *buf, int len);
+
+int pci_fill_info(struct pci_dev *, int flags); /* Fill in device information */
+
+#define PCI_FILL_IDENT		1
+#define PCI_FILL_IRQ		2
+#define PCI_FILL_BASES		4
+#define PCI_FILL_ROM_BASE	8
+#define PCI_FILL_SIZES		16
+#define PCI_FILL_RESCAN		0x10000
+
+
+/*
+ *	Filters
+ */
+
+struct pci_filter {
+  int bus, slot, func;			/* -1 = ANY */
+  int vendor, device;
+};
+
+void pci_filter_init(struct pci_access *, struct pci_filter *);
+int pci_filter_match(struct pci_filter *, struct pci_dev *);
+
+#define PCI_LOOKUP_VENDOR 1
+#define PCI_LOOKUP_DEVICE 2
+#define PCI_LOOKUP_CLASS 4
+#define PCI_LOOKUP_SUBSYSTEM 8
+#define PCI_LOOKUP_PROGIF 16
+#define PCI_LOOKUP_NUMERIC 0x10000
+
+#endif
diff -urN flashrom-126/m29f400bt.h winflashrom/m29f400bt.h
--- flashrom-126/m29f400bt.h	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/m29f400bt.h	2009-08-09 01:25:02.000000000 +0200
@@ -48,7 +48,7 @@
 	*(volatile uint8_t *)(bios + 0x555) = 0x55;
 	*(volatile uint8_t *)(bios + 0xAAA) = 0xA0;
 
-	usleep(200);
+	myusec_delay(200);
 }
 
 extern __inline__ void write_page_m29f400bt(volatile uint8_t *bios,
diff -urN flashrom-126/Makefile winflashrom/Makefile
--- flashrom-126/Makefile	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/Makefile	2009-08-09 01:35:56.000000000 +0200
@@ -6,53 +6,62 @@
 
 PROGRAM = flashrom
 
+RC 	= windres
 CC      = gcc
 STRIP	= strip
 INSTALL = /usr/bin/install
 PREFIX  = /usr/local
+MAKE 	= make
 #CFLAGS  = -O2 -g -Wall -Werror
 CFLAGS  = -Os -Wall -Werror -DDISABLE_DOC # -DTS5300
-OS_ARCH	= $(shell uname)
-ifeq ($(OS_ARCH), SunOS)
-LDFLAGS = -lpci -lz
-else
-LDFLAGS = -lpci -lz -static 
+#OS_ARCH	= $(shell uname)
+#ifeq ($(OS_ARCH), SunOS)
+#LDFLAGS = -lpci -lz
+#else
+#LDFLAGS = -lpci -lz -static 
+LDFLAGS = -L./libpci -lpci -static 
 STRIP_ARGS = -s
-endif
+#endif
 
 OBJS = chipset_enable.o board_enable.o udelay.o jedec.o sst28sf040.o \
 	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
+	w39v040fa.o sst_fwhub.o layout.o lbtable.o flashchips.o \
+	flashrom.o sharplhf00l04.o direct_io.o error_msg.o 
 
-all: pciutils dep $(PROGRAM)
+RESOURCES = winflashrom.rc
+RESOURCE_OBJ = winflashrom.o
+
+all: dep $(PROGRAM)
 
 $(PROGRAM): $(OBJS)
-	$(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
-	$(STRIP) $(STRIP_ARGS) $(PROGRAM)
+	$(RC) -o $(RESOURCE_OBJ) $(RESOURCES)
+	$(CC) -o $(PROGRAM) $(OBJS) $(RESOURCE_OBJ) $(LDFLAGS)
+	$(STRIP) $(STRIP_ARGS) $(PROGRAM).exe
 
 clean:
-	rm -f *.o *~
+	$(MAKE) -C libpci clean
+	rm -f $(PROGRAM).exe *.o *~
 
 distclean: clean
-	rm -f $(PROGRAM) .dependencies
+	rm -f $(PROGRAM).exe .dependencies
 	
 dep:
 	@$(CC) -MM *.c > .dependencies
+	$(MAKE) -C libpci
 
-pciutils:
-	@echo; echo -n "Checking for pciutils and zlib... "
-	@$(shell ( echo "#include <pci/pci.h>";		   \
-		   echo "struct pci_access *pacc;";	   \
-		   echo "int main(int argc, char **argv)"; \
-		   echo "{ pacc = pci_alloc(); return 0; }"; ) > .test.c )
-	@$(CC) $(CFLAGS) .test.c -o .test $(LDFLAGS) &>/dev/null &&	\
-		echo "found." || ( echo "not found."; echo;		\
-		echo "Please install pciutils-devel and zlib-devel.";	\
-		echo "See README for more information."; echo;		\
-		rm -f .test.c .test; exit 1)
-	@rm -f .test.c .test
+#pciutils:
+#	@echo; echo -n "Checking for pciutils and zlib... "
+#	@$(shell ( echo "#include <pci/pci.h>";		   \
+#		   echo "struct pci_access *pacc;";	   \
+#		   echo "int main(int argc, char **argv)"; \
+#		   echo "{ pacc = pci_alloc(); return 0; }"; ) > .test.c )
+#	@$(CC) $(CFLAGS) .test.c -o .test $(LDFLAGS) &>/dev/null &&	\
+#		echo "found." || ( echo "not found."; echo;		\
+#		echo "Please install pciutils-devel and zlib-devel.";	\
+#		echo "See README for more information."; echo;		\
+#		rm -f .test.c .test; exit 1)
+#	@rm -f .test.c .test
 
 install: $(PROGRAM)
 	$(INSTALL) flashrom $(PREFIX)/bin
diff -urN flashrom-126/msys_doc.c winflashrom/msys_doc.c
--- flashrom-126/msys_doc.c	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/msys_doc.c	2009-08-09 01:25:00.000000000 +0200
@@ -200,7 +200,7 @@
 	doc_read_4nop(bios);
 
 	while (_doc_busy(bios) && (i != 0)) {
-		usleep(timeout * 1000 / 20);
+		myusec_delay(timeout * 1000 / 20);
 		i--;
 	}
 
diff -urN flashrom-126/README winflashrom/README
--- flashrom-126/README	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/README	2009-08-09 01:25:34.000000000 +0200
@@ -1,18 +1,58 @@
 -------------------------------------------------------------------------------
-Flashrom README
+Winflashrom README
 -------------------------------------------------------------------------------
 
-This is the universal (LinuxBIOS) flash utility.
+This is the Windows port of the universal (LinuxBIOS) flash utility.
+It's named winflashrom. This code has not been merged into the LinuxBIOS 
+repository. Therefore, it's available publicly only from Google Project 
+hosting for a while. There are still some minor issues that prevent us 
+to merge it into the LinuxBIOS repository. Anyway, you might want to 
+watch LinuxBIOS mailing list 
+(http://www.linuxbios.org/mailman/listinfo/linuxbios)
+for further updates on Winflashrom. 
+Once a stable release of Winflashrom is available. The code in 
+Google Project hosting will be updated as well.
+
 
 Build Requirements
 ------------------
 
-To build the flashrom utility you need to have the following packages
-installed on your Linux system:
+To build the winflashrom utility you need to have the following packages
+installed on your Windows system:
 
-* pciutils
-* pciutils-devel / pciutils-dev
-* zlib-devel / zlib1g-dev
+* MinGW
+* MSys
+* Windows XP DDK or Windows Driver Kit (WDK). This tool is optional because the
+  package comes with a precompiled driver. However, if you want to make changes 
+  to the driver source code, you will need one of them.
+* DbgView (optional). You can use this tool for remote debugging if you want to 
+  try some changes to the driver code. DbgView is available from Sysinternals as 
+  a freeware.
+
+How to build winflashrom from the source code
+----------------------------------------------
+* Building the application
+  To build the application, "cd" to the source code root directory of the source code 
+  from within MSys (or other compatible shell that you might use) and invoke "make".
+  
+* Building the driver
+  To build the driver, run the Windows XP DKK or WDK shell (The WinXP Free Build 
+  environment or the WinXP Checked Build environment). Then, "cd" to the directory 
+  named "driver" in the root directory of the source code and invoke "build" from 
+  there. If you would like to have debugging message, use the "The WinXP checked 
+  build environment" of the Windows XP DDK or WDK shell.
+
+* Remote debugging the driver
+  To do a remote debugging, first run the DbgView client in the _test machine_ by invoking 
+  the following command in DbgView installation directory:
+  DbgView.exe /c /t
+  
+  Then, connect to the test machine from the _remote machine_ by running DbgView.exe.
+  In the remote DbgView window, activate the Capture|Capture Kernel option, 
+  Capture|Pass-Through option, and Capture|Capture Events option and 
+  Disable the Capture|Capture Wind32 option as it will clutter the output with 
+  unnecessary messages. Now, you can monitor the debug messages from the _test machine_.
+  
 
 
 Usage
@@ -179,3 +219,13 @@
 VIA VT8237
 VIA VT82C686
 
+Note on the current state of tested platform(s)
+-----------------------------------------------
+This code has been successfully tested on Pentium 4 
+(single core) system with ICH5 chipset and Winbond 
+W39V040FA flash chip. 
+
+The driver architecture is still messy at this point.
+However, I'm working on to improve it right now and it 
+should come with better code very soon.
+
diff -urN flashrom-126/sharplhf00l04.h winflashrom/sharplhf00l04.h
--- flashrom-126/sharplhf00l04.h	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/sharplhf00l04.h	2009-08-09 01:25:02.000000000 +0200
@@ -42,7 +42,8 @@
 	*(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
 	*(volatile uint8_t *)(bios + 0x5555) = 0xA0;
 
-	usleep(200);
+	//usleep(200);
+	myusec_delay(200);
 }
 
 #endif				/* !__SHARPLHF00L04_H__ */
diff -urN flashrom-126/sst49lfxxxc.c winflashrom/sst49lfxxxc.c
--- flashrom-126/sst49lfxxxc.c	2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/sst49lfxxxc.c	2009-08-09 01:25:00.000000000 +0200
@@ -27,7 +27,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <sys/mman.h>
+//#include <sys/mman.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
diff -urN flashrom-126/todo.txt winflashrom/todo.txt
--- flashrom-126/todo.txt	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/todo.txt	2009-08-09 01:25:29.000000000 +0200
@@ -0,0 +1,11 @@
+############################################################################################
+#  
+#  TODO list by Darmawan Salihun 28th June 2007
+#
+#
+
+1. Code review to find logic incompatibilities.
+2. Creating diff/patch from the last modified code with regard to flashrom base code.
+
+
+
diff -urN flashrom-126/udelay.h winflashrom/udelay.h
--- flashrom-126/udelay.h	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/udelay.h	2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,6 @@
+#ifndef __UDELAY_H__
+#define __UDELAY_H__
+
+void myusec_delay(int time);
+
+#endif
diff -urN flashrom-126/w39v040fa.c winflashrom/w39v040fa.c
--- flashrom-126/w39v040fa.c	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/w39v040fa.c	2009-08-09 01:25:00.000000000 +0200
@@ -0,0 +1,112 @@
+/*
+ * w39v040fa.c: driver for Winbond 39V040FA 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:
+ *	W39V040FA data sheet
+ *
+ */
+
+#include <stdio.h>
+#include "flash.h"
+#include "jedec.h"
+#include "w39v040fa.h"
+#include "direct_io.h"
+
+enum {
+	BLOCKING_REGS_PHY_RANGE = 0x80000,
+	BLOCKING_REGS_PHY_BASE = 0xFFB80000,
+};
+
+
+static volatile char * unprotect_39v040fa(void)
+{
+	unsigned char i, byte_val;
+	volatile char * block_regs_base;
+
+	block_regs_base = (volatile char*) map_physical_addr_range( BLOCKING_REGS_PHY_BASE, BLOCKING_REGS_PHY_RANGE);
+	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 =  *(block_regs_base + 2 + i*0x10000);
+		myusec_delay(10);
+		byte_val &= 0xF8; // Enable full access to the chip
+		*(block_regs_base + 2 + i*0x10000) = byte_val;
+		myusec_delay(10);
+	}
+
+	return block_regs_base;
+}
+
+
+static void protect_39v040fa(volatile char * reg_base)
+{
+	//
+	// Protect the BIOS chip address range
+	//
+	unsigned char i, byte_val;
+	volatile char * block_regs_base = reg_base;
+
+	for( i = 0; i < 8 ; i++ )
+	{
+		byte_val = *(block_regs_base + 2 + i*0x10000);
+		myusec_delay(10);
+		byte_val |= 1; // Prohibited to write in the block where set
+		*(block_regs_base + 2 + i*0x10000) = byte_val;
+		myusec_delay(10);
+	}
+
+	unmap_physical_addr_range((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 char * 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);
+}
diff -urN flashrom-126/w39v040fa.h winflashrom/w39v040fa.h
--- flashrom-126/w39v040fa.h	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/w39v040fa.h	2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,6 @@
+#ifndef __W39V040FA_H__
+#define __W39V040FA_H__ 1
+
+extern int write_39v040fa(struct flashchip *flash, uint8_t *buf);
+
+#endif				/* !__W39V040FA_H__ */
diff -urN flashrom-126/winflashrom.rc winflashrom/winflashrom.rc
--- flashrom-126/winflashrom.rc	1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/winflashrom.rc	2007-06-28 13:10:34.000000000 +0200
@@ -0,0 +1,6 @@
+/////////////////////////////////////////////////////////////////////////
+//  winflashrom resource file
+//  28 June 2007 Darmawan Salihun
+//
+
+WINFLASHROMDRV	DRIVER	DISCARDABLE	"driver/i386/winflashrom.sys"	


More information about the flashrom mailing list