[LinuxBIOS] [PATCH] flashrom: board specific enables based on matching pci-ids.

Luc Verhaegen libv at skynet.be
Mon Mar 26 16:59:18 CEST 2007


On Sun, Mar 25, 2007 at 08:09:22PM +0200, Stefan Reinauer wrote:
> 
> maybe chipset_enable?
>  
> sounds good.
> 
Done.

The island aruma got renamed to agami aruma at some point, the board 
specific match has been adjusted to that now. I hope that the pci ids i 
gathered from its src/mainboards/ directory are ok. I of course have no 
way of testing this.

The rest is pretty much last patch. Except that board enable functions 
only get passed the name now. The board enable function needs to claim 
its own pci device, this is safer as the ordering of both found pci 
devices (and the need for not having to match this and thus handing the 
callbacks a NULL) was going to get us into trouble.

The difference for chipset enable and flash_enable is the much cleaner 
chipset_flash_enable routine. iopl and preparing of the pci_access has 
been relegated to flash_rom.c. Then there's only some extraneous
whitespace removal and replacing // with /* */. I'm not sure how svn 
handles moving of files, but that's usually a good point to do such 
function-less changes.

Has been tested on all the same machines again. Needs a quick test on 
the agami.

Luc Verhaegen.
-------------- next part --------------
flashrom: split flash_enable.c into chipset_enable.c and board_enable.c

This splits up the ROM Write enable code into chipset specific and
board specific parts. This of course means that a lot of code is
plainly moved about.

* Allows for linuxbios name matching and pci-subsystem id matching.
  The latter uses a double set to properly distuinguish boards despite
  of some known vendors being lax about it.
* Fixes GPIO15 being raised on every VT8235 southbridge, regardless of what
  that line actually controls; rom on EPIA-M, backlight on mitac 8999 laptop.
* Adds flashrom support for Asus A7V400-MX (KM400 + VT8235)
* Island aruma was renamed agami aruma, the board specific code now got
  adjusted. A set of pci-ids was retrieved from source code.

signed-off-by: Luc Verhaegen <libv at skynet.be>

Index: util/flashrom/flash.h
===================================================================
--- util/flashrom/flash.h	(revision 2573)
+++ util/flashrom/flash.h	(working copy)
@@ -124,8 +124,16 @@
 
 extern void myusec_delay(int time);
 extern void myusec_calibrate_delay();
-extern int enable_flash_write(void);
 
+/* pci handling for board/chipset_enable */
+extern struct pci_access *pacc; /* For board and chipset_enable */
+extern struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device);
+extern struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
+                                     uint16_t card_vendor, uint16_t card_device);
+
+extern int board_flash_enable(char *vendor, char *part); /* board_enable.c */
+extern int chipset_flash_enable(void); /* chipset_enable.c */
+
 /* physical memory mapping device */
 
 #if defined (__sun) && (defined(__i386) || defined(__amd64))
Index: util/flashrom/flash_enable.c
===================================================================
--- util/flashrom/flash_enable.c	(revision 2573)
+++ util/flashrom/flash_enable.c	(working copy)
@@ -1,596 +0,0 @@
-/*
- *   flash rom utility: enable flash writes
- *
- *   Copyright (C) 2000-2004 ???
- *   Copyright (C) 2005 coresystems GmbH <stepan at openbios.org>
- *   Copyright (C) 2006 Uwe Hermann <uwe at hermann-uwe.de>
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   version 2
- *
- */
-
-#include <stdio.h>
-#include <pci/pci.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#if defined (__sun) && (defined(__i386) || defined(__amd64))
-#include <strings.h>
-#include <sys/sysi86.h>
-#include <sys/psw.h>
-#include <asm/sunddi.h>
-#endif
-#include "flash.h"
-#include "lbtable.h"
-#include "debug.h"
-
-// We keep this for the others.
-static struct pci_access *pacc;
-
-static int enable_flash_sis630(struct pci_dev *dev, char *name)
-{
-	char b;
-
-	/* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630 */
-	outl(0x80000840, 0x0cf8);
-	b = inb(0x0cfc) | 0x0b;
-	outb(b, 0xcfc);
-	/* Flash write enable on SiS 540/630 */
-	outl(0x80000845, 0x0cf8);
-	b = inb(0x0cfd) | 0x40;
-	outb(b, 0xcfd);
-
-	/* The same thing on SiS 950 SuperIO side */
-	outb(0x87, 0x2e);
-	outb(0x01, 0x2e);
-	outb(0x55, 0x2e);
-	outb(0x55, 0x2e);
-
-	if (inb(0x2f) != 0x87) {
-		outb(0x87, 0x4e);
-		outb(0x01, 0x4e);
-		outb(0x55, 0x4e);
-		outb(0xaa, 0x4e);
-		if (inb(0x4f) != 0x87) {
-			printf("Can not access SiS 950\n");
-			return -1;
-		}
-		outb(0x24, 0x4e);
-		b = inb(0x4f) | 0xfc;
-		outb(0x24, 0x4e);
-		outb(b, 0x4f);
-		outb(0x02, 0x4e);
-		outb(0x02, 0x4f);
-	}
-
-	outb(0x24, 0x2e);
-	printf("2f is %#x\n", inb(0x2f));
-	b = inb(0x2f) | 0xfc;
-	outb(0x24, 0x2e);
-	outb(b, 0x2f);
-
-	outb(0x02, 0x2e);
-	outb(0x02, 0x2f);
-
-	return 0;
-}
-
-/* Datasheet:
- *   - Name: 82371AB PCI-TO-ISA / IDE XCELERATOR (PIIX4)
- *   - URL: http://www.intel.com/design/intarch/datashts/290562.htm
- *   - PDF: http://www.intel.com/design/intarch/datashts/29056201.pdf
- *   - Order Number: 290562-001
- */
-static int enable_flash_piix4(struct pci_dev *dev, char *name)
-{
-	uint16_t old, new;
-	uint16_t xbcs = 0x4e; /* X-Bus Chip Select register. */
-
-	old = pci_read_word(dev, xbcs);
-
-	/* Set bit 9: 1-Meg Extended BIOS Enable (PCI master accesses to
-                      FFF00000-FFF7FFFF are forwarded to ISA).
-           Set bit 7: Extended BIOS Enable (PCI master accesses to
-                      FFF80000-FFFDFFFF are forwarded to ISA).
-           Set bit 6: Lower BIOS Enable (PCI master, or ISA master accesses to
-                      the lower 64-Kbyte BIOS block (E0000-EFFFF) at the top
-                      of 1 Mbyte, or the aliases at the top of 4 Gbyte
-                      (FFFE0000-FFFEFFFF) result in the generation of BIOSCS#.
-           Note: Accesses to FFFF0000-FFFFFFFF are always forwarded to ISA.
-           Set bit 2: BIOSCS# Write Enable (1=enable, 0=disable). */
-	new = old | 0x2c4;
-
-	if (new == old)
-		return 0;
-
-	pci_write_word(dev, xbcs, new);
-
-	if (pci_read_word(dev, xbcs) != new) {
-		printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", xbcs, new, name);
-		return -1;
-	}
-	return 0;
-}
-
-static int enable_flash_ich(struct pci_dev *dev, char *name, int bios_cntl)
-{
-	/* register 4e.b gets or'ed with one */
-	uint8_t old, new;
-
-	/* if it fails, it fails. There are so many variations of broken mobos
-	 * that it is hard to argue that we should quit at this point. 
-	 */
-
-	/* Note: the ICH0-ICH5 BIOS_CNTL register is actually 16 bit wide, but
-         * just treating it as 8 bit wide seems to work fine in practice. 
-	 */
-
-	/* see ie. page 375 of "Intel ICH7 External Design Specification"
-	 * http://download.intel.com/design/chipsets/datashts/30701302.pdf 
-	 */
-
-	old = pci_read_byte(dev, bios_cntl);
-
-	new = old | 1;
-
-	if (new == old)
-		return 0;
-
-	pci_write_byte(dev, bios_cntl, new);
-
-	if (pci_read_byte(dev, bios_cntl) != new) {
-		printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
-		       bios_cntl, new, name);
-		return -1;
-	}
-	return 0;
-}
-
-static int enable_flash_ich_4e(struct pci_dev *dev, char *name)
-{
-	return enable_flash_ich(dev, name, 0x4e);
-}
-
-static int enable_flash_ich_dc(struct pci_dev *dev, char *name)
-{
-	return enable_flash_ich(dev, name, 0xdc);
-}
-
-static int enable_flash_vt823x(struct pci_dev *dev, char *name)
-{
-	uint8_t val;
-        int ret = 0;
-
-        /* ROM Write enable */
-	val = pci_read_byte(dev, 0x40);
-	val |= 0x10;
-	pci_write_byte(dev, 0x40, val);
-
-	if (pci_read_byte(dev, 0x40) != val) {
-		printf("Warning: Failed to enable ROM Write on %s\n", name);
-		ret = -1;
-	}
-
-        if (dev->device_id == 0x3177) { /* VT8235 */
-                if (!iopl(3)) { /* enable full IO access */
-                        unsigned int base;
-
-                        /* GPIO12-15 -> output */
-                        val = pci_read_byte(dev, 0xE4);
-                        val |= 0x38;
-                        pci_write_byte(dev, 0xE4, val);
-
-                        /* Get Power Management IO address. */
-                        base = pci_read_word(dev, 0x88) & 0xFF80;
-
-                        /* enable GPIO15 which is connected to write protect. */
-                        val = inb(base + 0x4d);
-                        val |= 0xFF;
-                        outb(val, base + 0x4d);
-
-                        val = inb(base + 0x4E);
-                        val |= 0x0F;
-                        outb(val, base + 0x4E);
-                } else {
-                        printf("Warning; Failed to disable Write Protect"
-                               " on %s (iopl failed)\n", name);
-                        return -1;
-                }
-        }
-
-	return ret;
-}
-
-static int enable_flash_cs5530(struct pci_dev *dev, char *name)
-{
-	uint8_t new;
-
-	pci_write_byte(dev, 0x52, 0xee);
-
-	new = pci_read_byte(dev, 0x52);
-
-	if (new != 0xee) {
-		printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
-		       0x52, new, name);
-		return -1;
-	}
-	
-	new = pci_read_byte(dev, 0x5b) | 0x20;
-	pci_write_byte(dev, 0x5b, new);
-	
-	return 0;
-}
-
-
-static int enable_flash_sc1100(struct pci_dev *dev, char *name)
-{
-	uint8_t new;
-
-	pci_write_byte(dev, 0x52, 0xee);
-
-	new = pci_read_byte(dev, 0x52);
-
-	if (new != 0xee) {
-		printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
-		       0x52, new, name);
-		return -1;
-	}
-	return 0;
-}
-
-static int enable_flash_sis5595(struct pci_dev *dev, char *name)
-{
-	uint8_t new, newer;
-
-	new = pci_read_byte(dev, 0x45);
-
-	/* clear bit 5 */
-	new &= (~0x20);
-	/* set bit 2 */
-	new |= 0x4;
-
-	pci_write_byte(dev, 0x45, new);
-
-	newer = pci_read_byte(dev, 0x45);
-	if (newer != new) {
-		printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
-		       0x45, new, name);
-		printf("Stuck at 0x%x\n", newer);
-		return -1;
-	}
-	return 0;
-}
-
-static int enable_flash_amd8111(struct pci_dev *dev, char *name)
-{
-	/* register 4e.b gets or'ed with one */
-	uint8_t old, new;
-	/* if it fails, it fails. There are so many variations of broken mobos
-	 * that it is hard to argue that we should quit at this point. 
-	 */
-
-	/* enable decoding at 0xffb00000 to 0xffffffff */
-	old = pci_read_byte(dev, 0x43);
-	new = old | 0xC0;
-	if (new != old) {
-		pci_write_byte(dev, 0x43, new);
-		if (pci_read_byte(dev, 0x43) != new) {
-			printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
-			       0x43, new, name);
-		}
-	}
-
-	old = pci_read_byte(dev, 0x40);
-	new = old | 0x01;
-	if (new == old)
-		return 0;
-	pci_write_byte(dev, 0x40, new);
-
-	if (pci_read_byte(dev, 0x40) != new) {
-		printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
-		       0x40, new, name);
-		return -1;
-	}
-	return 0;
-}
-
-//By yhlu
-static int enable_flash_ck804(struct pci_dev *dev, char *name)
-{
-        /* register 4e.b gets or'ed with one */
-        uint8_t old, new;
-        /* if it fails, it fails. There are so many variations of broken mobos
-         * that it is hard to argue that we should quit at this point. 
-         */
-
-        //dump_pci_device(dev); 
-        
-        old = pci_read_byte(dev, 0x88);
-        new = old | 0xc0;
-        if (new != old) {
-                pci_write_byte(dev, 0x88, new);
-                if (pci_read_byte(dev, 0x88) != new) {
-                        printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
-                               0x88, new, name);
-                }
-        }
-
-        old = pci_read_byte(dev, 0x6d);
-        new = old | 0x01;
-        if (new == old)
-                return 0;
-        pci_write_byte(dev, 0x6d, new);
-
-        if (pci_read_byte(dev, 0x6d) != new) {
-                printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
-                       0x6d, new, name);
-                return -1;
-        }
-        return 0;
-}
-
-static int enable_flash_sb400(struct pci_dev *dev, char *name)
-{
-        uint8_t tmp;
-
-	struct pci_filter f;
-	struct pci_dev *smbusdev;
-
-	/* then look for the smbus device */
-	pci_filter_init((struct pci_access *) 0, &f);
-	f.vendor = 0x1002;
-	f.device = 0x4372;
-	
-	for (smbusdev = pacc->devices; smbusdev; smbusdev = smbusdev->next) {
-		if (pci_filter_match(&f, smbusdev)) {
-			break;
-		}
-	}
-	
-	if(!smbusdev) {
-		perror("smbus device not found. aborting\n");
-		exit(1);
-	}
-	
-	// enable some smbus stuff
-	tmp=pci_read_byte(smbusdev, 0x79);
-	tmp|=0x01;
-	pci_write_byte(smbusdev, 0x79, tmp);
-
-	// change southbridge
-	tmp=pci_read_byte(dev, 0x48);
-	tmp|=0x21;
-	pci_write_byte(dev, 0x48, tmp);
-
-	// now become a bit silly. 
-	tmp=inb(0xc6f);
-	outb(tmp,0xeb);
-	outb(tmp, 0xeb);
-	tmp|=0x40;
-	outb(tmp, 0xc6f);
-	outb(tmp, 0xeb);
-	outb(tmp, 0xeb);
-
-	return 0;
-}
-
-//By yhlu
-static int enable_flash_mcp55(struct pci_dev *dev, char *name)
-{
-        /* register 4e.b gets or'ed with one */
-        unsigned char old, new, byte;
-        unsigned short word;
-	
-        /* if it fails, it fails. There are so many variations of broken mobos
-         * that it is hard to argue that we should quit at this point. 
-         */
-
-        //dump_pci_device(dev); 
-
-        /* Set the 4MB enable bit bit */
-        byte = pci_read_byte(dev, 0x88);
-        byte |= 0xff; //256K
-        pci_write_byte(dev, 0x88, byte);
-        byte = pci_read_byte(dev, 0x8c);
-        byte |= 0xff; //1M
-        pci_write_byte(dev, 0x8c, byte);
-        word = pci_read_word(dev, 0x90);
-        word |= 0x7fff; //15M
-        pci_write_word(dev, 0x90, word);
-        
-        old = pci_read_byte(dev, 0x6d);
-        new = old | 0x01;
-        if (new == old)
-                return 0;
-        pci_write_byte(dev, 0x6d, new);
-
-        if (pci_read_byte(dev, 0x6d) != new) {
-                printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
-                       0x6d, new, name);
-                return -1;
-        }
-
-	return 0;
-
-}
-
-typedef struct penable {
-	unsigned short vendor, device;
-	char *name;
-	int (*doit) (struct pci_dev * dev, char *name);
-} FLASH_ENABLE;
-
-static FLASH_ENABLE enables[] = {
-	{0x1039, 0x0630, "SIS630", enable_flash_sis630},
-	{0x8086, 0x7110, "PIIX4/PIIX4E/PIIX4M", enable_flash_piix4},
-	{0x8086, 0x2410, "ICH", enable_flash_ich_4e},
-	{0x8086, 0x2420, "ICH0", enable_flash_ich_4e},
-	{0x8086, 0x2440, "ICH2", enable_flash_ich_4e},
-	{0x8086, 0x244c, "ICH2-M", enable_flash_ich_4e},
-	{0x8086, 0x2480, "ICH3-S", enable_flash_ich_4e},
-	{0x8086, 0x248c, "ICH3-M", enable_flash_ich_4e},
-	{0x8086, 0x24c0, "ICH4/ICH4-L", enable_flash_ich_4e},
-	{0x8086, 0x24cc, "ICH4-M", enable_flash_ich_4e},
-	{0x8086, 0x24d0, "ICH5/ICH5R", enable_flash_ich_4e},
-	{0x8086, 0x2640, "ICH6/ICH6R", enable_flash_ich_dc},
-	{0x8086, 0x2641, "ICH6-M", enable_flash_ich_dc},
-	{0x8086, 0x27b8, "ICH7/ICH7R", enable_flash_ich_dc},
-	{0x8086, 0x27b9, "ICH7M", enable_flash_ich_dc},
-	{0x8086, 0x27bd, "ICH7MDH", enable_flash_ich_dc},
-	{0x8086, 0x2810, "ICH8/ICH8R", enable_flash_ich_dc},
-	{0x8086, 0x2812, "ICH8DH", enable_flash_ich_dc},
-	{0x8086, 0x2814, "ICH8DO", enable_flash_ich_dc},
-	{0x1106, 0x8231, "VT8231", enable_flash_vt823x},
-	{0x1106, 0x3177, "VT8235", enable_flash_vt823x},
-	{0x1106, 0x3227, "VT8237", enable_flash_vt823x},
-	{0x1106, 0x0686, "VT82C686", enable_flash_amd8111},
-	{0x1078, 0x0100, "CS5530", enable_flash_cs5530},
-	{0x100b, 0x0510, "SC1100", enable_flash_sc1100},
-	{0x1039, 0x0008, "SIS5595", enable_flash_sis5595},
-	{0x1022, 0x7468, "AMD8111", enable_flash_amd8111},
-	// this fallthrough looks broken.
-        {0x10de, 0x0050, "NVIDIA CK804", enable_flash_ck804}, // LPC
-        {0x10de, 0x0051, "NVIDIA CK804", enable_flash_ck804}, // Pro
-        {0x10de, 0x00d3, "NVIDIA CK804", enable_flash_ck804}, // Slave, should not be here, to fix known bug for A01.
-
-        {0x10de, 0x0260, "NVidia MCP51", enable_flash_ck804},
-        {0x10de, 0x0261, "NVidia MCP51", enable_flash_ck804},
-        {0x10de, 0x0262, "NVidia MCP51", enable_flash_ck804},
-        {0x10de, 0x0263, "NVidia MCP51", enable_flash_ck804},
-
-	{0x10de, 0x0360, "NVIDIA MCP55", enable_flash_mcp55}, // Gigabyte m57sli-s4
-	{0x10de, 0x0361, "NVIDIA MCP55", enable_flash_mcp55}, // LPC
-	{0x10de, 0x0362, "NVIDIA MCP55", enable_flash_mcp55}, // LPC
-	{0x10de, 0x0363, "NVIDIA MCP55", enable_flash_mcp55}, // LPC
-	{0x10de, 0x0364, "NVIDIA MCP55", enable_flash_mcp55}, // LPC
-	{0x10de, 0x0365, "NVIDIA MCP55", enable_flash_mcp55}, // LPC
-	{0x10de, 0x0366, "NVIDIA MCP55", enable_flash_mcp55}, // LPC
-	{0x10de, 0x0367, "NVIDIA MCP55", enable_flash_mcp55}, // Pro
-
-	{0x1002, 0x4377, "ATI SB400", enable_flash_sb400}, // ATI Technologies Inc IXP SB400 PCI-ISA Bridge (rev 80)
-};
-
-static int mbenable_island_aruma(void)
-{
-#define EFIR 0x2e      /* Extended function index register, either 0x2e or 0x4e    */
-#define EFDR EFIR + 1  /* Extended function data register, one plus the index reg. */
-	char b;
-
-/*  Disable the flash write protect.  The flash write protect is 
- *  connected to the WinBond w83627hf GPIO 24.
- */
-
-	printf("Disabling mainboard flash write protection.\n");
-
-	outb(0x87, EFIR); // sequence to unlock extended functions
-	outb(0x87, EFIR);
-
-	outb(0x20, EFIR); // SIO device ID register
-	b = inb(EFDR); 
-	printf_debug("W83627HF device ID = 0x%x\n",b);
-
-	if (b != 0x52) {
-		perror("Incorrect device ID, aborting write protect disable\n");
-		exit(1);
-	}
-
-	outb(0x2b, EFIR); // GPIO multiplexed pin reg.
-	b = inb(EFDR) | 0x10; 
-	outb(0x2b, EFIR); 
-	outb(b, EFDR); // select GPIO 24 instead of WDTO
-
-	outb(0x7, EFIR); // logical device select
-	outb(0x8, EFDR); // point to device 8, GPIO port 2
-
-	outb(0x30, EFIR); // logic device activation control
-	outb(0x1, EFDR); // activate
-
-	outb(0xf0, EFIR); // GPIO 20-27 I/O selection register
-	b = inb(EFDR) & ~0x10; 
-	outb(0xf0, EFIR); 
-	outb(b, EFDR); // set GPIO 24 as an output
-
-	outb(0xf1, EFIR); // GPIO 20-27 data register
-	b = inb(EFDR) | 0x10; 
-	outb(0xf1, EFIR); 
-	outb(b, EFDR); // set GPIO 24
-
-	outb(0xaa, EFIR); // command to exit extended functions
-
-	return 0;
-}
-
-typedef struct mbenable {
-	char *vendor, *part;
-	int (*doit)(void);
-} MAINBOARD_ENABLE;
-
-static MAINBOARD_ENABLE mbenables[] = {
-	{ "ISLAND", "ARUMA", mbenable_island_aruma },
-};
-
-int enable_flash_write()
-{
-	int i;
-	struct pci_dev *dev = 0;
-	FLASH_ENABLE *enable = 0;
-
-	/* get io privilege access PCI configuration space */
-#if defined (__sun) && (defined(__i386) || defined(__amd64))
-	if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0){
-#else
-	if (iopl(3) != 0) {
-#endif
-		perror("Can not set io privilege");
-		exit(1);
-	}
-
-
-	/* Initialize PCI access */
-	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 */
-
-	
-	/* First look whether we have to do something for this
-	 * motherboard.
-	 */
-	for (i = 0; i < sizeof(mbenables) / sizeof(mbenables[0]); i++) {
-		if(lb_vendor && !strcmp(mbenables[i].vendor, lb_vendor) &&
-		   lb_part && !strcmp(mbenables[i].part, lb_part)) {
-			mbenables[i].doit();
-			break;
-		}
-	}
-	
-	/* now let's try to find the chipset we have ... */
-	for (i = 0; i < sizeof(enables) / sizeof(enables[0]) && (!dev);
-	     i++) {
-		struct pci_filter f;
-		struct pci_dev *z;
-		/* the first param is unused. */
-		pci_filter_init((struct pci_access *) 0, &f);
-		f.vendor = enables[i].vendor;
-		f.device = enables[i].device;
-		for (z = pacc->devices; z; z = z->next)
-			if (pci_filter_match(&f, z)) {
-				enable = &enables[i];
-				dev = z;
-			}
-	}
-
-	if (!enable) {
-		printf("Warning: Unknown system. Flash detection "
-			"will most likely fail.\n");
-		return 1;
-	}
-	
-	/* now do the deed. */
-	printf("Enabling flash write on %s...", enable->name);
-	if (enable->doit(dev, enable->name) == 0)
-		printf("OK\n");
-	return 0;
-}
Index: util/flashrom/Makefile
===================================================================
--- util/flashrom/Makefile	(revision 2573)
+++ util/flashrom/Makefile	(working copy)
@@ -20,10 +20,11 @@
 STRIP_ARGS = -s
 endif
 
-OBJS  = flash_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 flash_rom.o sharplhf00l04.o
+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 flash_rom.o \
+	sharplhf00l04.o
 
 all: pciutils dep $(PROGRAM)
 
@@ -32,7 +33,7 @@
 	$(STRIP) $(STRIP_ARGS) $(PROGRAM)
 
 clean:
-	rm -f *.o *~
+	rm -f *.o *~ flashrom
 
 distclean: clean
 	rm -f $(PROGRAM) .dependencies
Index: util/flashrom/chipset_enable.c
===================================================================
--- util/flashrom/chipset_enable.c	(revision 0)
+++ util/flashrom/chipset_enable.c	(revision 0)
@@ -0,0 +1,470 @@
+/*
+ *   flash rom utility: enable flash writes
+ *
+ *   Copyright (C) 2000-2004 ???
+ *   Copyright (C) 2005 coresystems GmbH <stepan at openbios.org>
+ *   Copyright (C) 2006 Uwe Hermann <uwe at hermann-uwe.de>
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   version 2
+ *
+ */
+
+#include <stdio.h>
+#include <pci/pci.h>
+#include <stdlib.h>
+
+#include "flash.h"
+#include "debug.h"
+
+static int enable_flash_sis630(struct pci_dev *dev, char *name)
+{
+	char b;
+
+	/* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630 */
+	outl(0x80000840, 0x0cf8);
+	b = inb(0x0cfc) | 0x0b;
+	outb(b, 0xcfc);
+	/* Flash write enable on SiS 540/630 */
+	outl(0x80000845, 0x0cf8);
+	b = inb(0x0cfd) | 0x40;
+	outb(b, 0xcfd);
+
+	/* The same thing on SiS 950 SuperIO side */
+	outb(0x87, 0x2e);
+	outb(0x01, 0x2e);
+	outb(0x55, 0x2e);
+	outb(0x55, 0x2e);
+
+	if (inb(0x2f) != 0x87) {
+		outb(0x87, 0x4e);
+		outb(0x01, 0x4e);
+		outb(0x55, 0x4e);
+		outb(0xaa, 0x4e);
+		if (inb(0x4f) != 0x87) {
+			printf("Can not access SiS 950\n");
+			return -1;
+		}
+		outb(0x24, 0x4e);
+		b = inb(0x4f) | 0xfc;
+		outb(0x24, 0x4e);
+		outb(b, 0x4f);
+		outb(0x02, 0x4e);
+		outb(0x02, 0x4f);
+	}
+
+	outb(0x24, 0x2e);
+	printf("2f is %#x\n", inb(0x2f));
+	b = inb(0x2f) | 0xfc;
+	outb(0x24, 0x2e);
+	outb(b, 0x2f);
+
+	outb(0x02, 0x2e);
+	outb(0x02, 0x2f);
+
+	return 0;
+}
+
+/* Datasheet:
+ *   - Name: 82371AB PCI-TO-ISA / IDE XCELERATOR (PIIX4)
+ *   - URL: http://www.intel.com/design/intarch/datashts/290562.htm
+ *   - PDF: http://www.intel.com/design/intarch/datashts/29056201.pdf
+ *   - Order Number: 290562-001
+ */
+static int enable_flash_piix4(struct pci_dev *dev, char *name)
+{
+	uint16_t old, new;
+	uint16_t xbcs = 0x4e; /* X-Bus Chip Select register. */
+
+	old = pci_read_word(dev, xbcs);
+
+	/* Set bit 9: 1-Meg Extended BIOS Enable (PCI master accesses to
+                      FFF00000-FFF7FFFF are forwarded to ISA).
+           Set bit 7: Extended BIOS Enable (PCI master accesses to
+                      FFF80000-FFFDFFFF are forwarded to ISA).
+           Set bit 6: Lower BIOS Enable (PCI master, or ISA master accesses to
+                      the lower 64-Kbyte BIOS block (E0000-EFFFF) at the top
+                      of 1 Mbyte, or the aliases at the top of 4 Gbyte
+                      (FFFE0000-FFFEFFFF) result in the generation of BIOSCS#.
+           Note: Accesses to FFFF0000-FFFFFFFF are always forwarded to ISA.
+           Set bit 2: BIOSCS# Write Enable (1=enable, 0=disable). */
+	new = old | 0x2c4;
+
+	if (new == old)
+		return 0;
+
+	pci_write_word(dev, xbcs, new);
+
+	if (pci_read_word(dev, xbcs) != new) {
+		printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n", xbcs, new, name);
+		return -1;
+	}
+	return 0;
+}
+
+static int enable_flash_ich(struct pci_dev *dev, char *name, int bios_cntl)
+{
+	/* register 4e.b gets or'ed with one */
+	uint8_t old, new;
+
+	/* if it fails, it fails. There are so many variations of broken mobos
+	 * that it is hard to argue that we should quit at this point.
+	 */
+
+	/* Note: the ICH0-ICH5 BIOS_CNTL register is actually 16 bit wide, but
+         * just treating it as 8 bit wide seems to work fine in practice.
+	 */
+
+	/* see ie. page 375 of "Intel ICH7 External Design Specification"
+	 * http://download.intel.com/design/chipsets/datashts/30701302.pdf
+	 */
+
+	old = pci_read_byte(dev, bios_cntl);
+
+	new = old | 1;
+
+	if (new == old)
+		return 0;
+
+	pci_write_byte(dev, bios_cntl, new);
+
+	if (pci_read_byte(dev, bios_cntl) != new) {
+		printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
+		       bios_cntl, new, name);
+		return -1;
+	}
+	return 0;
+}
+
+static int enable_flash_ich_4e(struct pci_dev *dev, char *name)
+{
+	return enable_flash_ich(dev, name, 0x4e);
+}
+
+static int enable_flash_ich_dc(struct pci_dev *dev, char *name)
+{
+	return enable_flash_ich(dev, name, 0xdc);
+}
+
+/*
+ *
+ */
+static int
+enable_flash_vt823x(struct pci_dev *dev, char *name)
+{
+	uint8_t val;
+
+        /* ROM Write enable */
+	val = pci_read_byte(dev, 0x40);
+	val |= 0x10;
+	pci_write_byte(dev, 0x40, val);
+
+	if (pci_read_byte(dev, 0x40) != val) {
+		printf("\nWARNING: Failed to enable ROM Write on \"%s\"\n",
+                       name);
+		return -1;
+	}
+
+        return 0;
+}
+
+static int enable_flash_cs5530(struct pci_dev *dev, char *name)
+{
+	uint8_t new;
+
+	pci_write_byte(dev, 0x52, 0xee);
+
+	new = pci_read_byte(dev, 0x52);
+
+	if (new != 0xee) {
+		printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
+		       0x52, new, name);
+		return -1;
+	}
+
+	new = pci_read_byte(dev, 0x5b) | 0x20;
+	pci_write_byte(dev, 0x5b, new);
+
+	return 0;
+}
+
+
+static int enable_flash_sc1100(struct pci_dev *dev, char *name)
+{
+	uint8_t new;
+
+	pci_write_byte(dev, 0x52, 0xee);
+
+	new = pci_read_byte(dev, 0x52);
+
+	if (new != 0xee) {
+		printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
+		       0x52, new, name);
+		return -1;
+	}
+	return 0;
+}
+
+static int enable_flash_sis5595(struct pci_dev *dev, char *name)
+{
+	uint8_t new, newer;
+
+	new = pci_read_byte(dev, 0x45);
+
+	/* clear bit 5 */
+	new &= (~0x20);
+	/* set bit 2 */
+	new |= 0x4;
+
+	pci_write_byte(dev, 0x45, new);
+
+	newer = pci_read_byte(dev, 0x45);
+	if (newer != new) {
+		printf("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
+		       0x45, new, name);
+		printf("Stuck at 0x%x\n", newer);
+		return -1;
+	}
+	return 0;
+}
+
+static int enable_flash_amd8111(struct pci_dev *dev, char *name)
+{
+	/* register 4e.b gets or'ed with one */
+	uint8_t old, new;
+	/* if it fails, it fails. There are so many variations of broken mobos
+	 * that it is hard to argue that we should quit at this point.
+	 */
+
+	/* enable decoding at 0xffb00000 to 0xffffffff */
+	old = pci_read_byte(dev, 0x43);
+	new = old | 0xC0;
+	if (new != old) {
+		pci_write_byte(dev, 0x43, new);
+		if (pci_read_byte(dev, 0x43) != new) {
+			printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
+			       0x43, new, name);
+		}
+	}
+
+	old = pci_read_byte(dev, 0x40);
+	new = old | 0x01;
+	if (new == old)
+		return 0;
+	pci_write_byte(dev, 0x40, new);
+
+	if (pci_read_byte(dev, 0x40) != new) {
+		printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
+		       0x40, new, name);
+		return -1;
+	}
+	return 0;
+}
+
+/* By yhlu */
+static int enable_flash_ck804(struct pci_dev *dev, char *name)
+{
+        /* register 4e.b gets or'ed with one */
+        uint8_t old, new;
+        /* if it fails, it fails. There are so many variations of broken mobos
+         * that it is hard to argue that we should quit at this point.
+         */
+
+        /* dump_pci_device(dev); */
+
+        old = pci_read_byte(dev, 0x88);
+        new = old | 0xc0;
+        if (new != old) {
+                pci_write_byte(dev, 0x88, new);
+                if (pci_read_byte(dev, 0x88) != new) {
+                        printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
+                               0x88, new, name);
+                }
+        }
+
+        old = pci_read_byte(dev, 0x6d);
+        new = old | 0x01;
+        if (new == old)
+                return 0;
+        pci_write_byte(dev, 0x6d, new);
+
+        if (pci_read_byte(dev, 0x6d) != new) {
+                printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
+                       0x6d, new, name);
+                return -1;
+        }
+        return 0;
+}
+
+static int enable_flash_sb400(struct pci_dev *dev, char *name)
+{
+        uint8_t tmp;
+
+	struct pci_filter f;
+	struct pci_dev *smbusdev;
+
+	/* then look for the smbus device */
+	pci_filter_init((struct pci_access *) 0, &f);
+	f.vendor = 0x1002;
+	f.device = 0x4372;
+
+	for (smbusdev = pacc->devices; smbusdev; smbusdev = smbusdev->next) {
+		if (pci_filter_match(&f, smbusdev)) {
+			break;
+		}
+	}
+
+	if(!smbusdev) {
+		perror("smbus device not found. aborting\n");
+		exit(1);
+	}
+
+	/* enable some smbus stuff */
+	tmp=pci_read_byte(smbusdev, 0x79);
+	tmp|=0x01;
+	pci_write_byte(smbusdev, 0x79, tmp);
+
+	/* change southbridge */
+	tmp=pci_read_byte(dev, 0x48);
+	tmp|=0x21;
+	pci_write_byte(dev, 0x48, tmp);
+
+	/* now become a bit silly. */
+	tmp=inb(0xc6f);
+	outb(tmp,0xeb);
+	outb(tmp, 0xeb);
+	tmp|=0x40;
+	outb(tmp, 0xc6f);
+	outb(tmp, 0xeb);
+	outb(tmp, 0xeb);
+
+	return 0;
+}
+
+/* By yhlu */
+static int enable_flash_mcp55(struct pci_dev *dev, char *name)
+{
+        /* register 4e.b gets or'ed with one */
+        unsigned char old, new, byte;
+        unsigned short word;
+
+        /* if it fails, it fails. There are so many variations of broken mobos
+         * that it is hard to argue that we should quit at this point.
+         */
+
+        /* dump_pci_device(dev); */
+
+        /* Set the 4MB enable bit bit */
+        byte = pci_read_byte(dev, 0x88);
+        byte |= 0xff; /* 256K */
+        pci_write_byte(dev, 0x88, byte);
+        byte = pci_read_byte(dev, 0x8c);
+        byte |= 0xff; /* 1M */
+        pci_write_byte(dev, 0x8c, byte);
+        word = pci_read_word(dev, 0x90);
+        word |= 0x7fff; /* 15M */
+        pci_write_word(dev, 0x90, word);
+
+        old = pci_read_byte(dev, 0x6d);
+        new = old | 0x01;
+        if (new == old)
+                return 0;
+        pci_write_byte(dev, 0x6d, new);
+
+        if (pci_read_byte(dev, 0x6d) != new) {
+                printf("tried to set 0x%x to 0x%x on %s failed (WARNING ONLY)\n",
+                       0x6d, new, name);
+                return -1;
+        }
+
+	return 0;
+
+}
+
+typedef struct penable {
+	unsigned short vendor, device;
+	char *name;
+	int (*doit) (struct pci_dev * dev, char *name);
+} FLASH_ENABLE;
+
+static FLASH_ENABLE enables[] = {
+	{0x1039, 0x0630, "SIS630", enable_flash_sis630},
+	{0x8086, 0x7110, "PIIX4/PIIX4E/PIIX4M", enable_flash_piix4},
+	{0x8086, 0x2410, "ICH", enable_flash_ich_4e},
+	{0x8086, 0x2420, "ICH0", enable_flash_ich_4e},
+	{0x8086, 0x2440, "ICH2", enable_flash_ich_4e},
+	{0x8086, 0x244c, "ICH2-M", enable_flash_ich_4e},
+	{0x8086, 0x2480, "ICH3-S", enable_flash_ich_4e},
+	{0x8086, 0x248c, "ICH3-M", enable_flash_ich_4e},
+	{0x8086, 0x24c0, "ICH4/ICH4-L", enable_flash_ich_4e},
+	{0x8086, 0x24cc, "ICH4-M", enable_flash_ich_4e},
+	{0x8086, 0x24d0, "ICH5/ICH5R", enable_flash_ich_4e},
+	{0x8086, 0x2640, "ICH6/ICH6R", enable_flash_ich_dc},
+	{0x8086, 0x2641, "ICH6-M", enable_flash_ich_dc},
+	{0x8086, 0x27b8, "ICH7/ICH7R", enable_flash_ich_dc},
+	{0x8086, 0x27b9, "ICH7M", enable_flash_ich_dc},
+	{0x8086, 0x27bd, "ICH7MDH", enable_flash_ich_dc},
+	{0x8086, 0x2810, "ICH8/ICH8R", enable_flash_ich_dc},
+	{0x8086, 0x2812, "ICH8DH", enable_flash_ich_dc},
+	{0x8086, 0x2814, "ICH8DO", enable_flash_ich_dc},
+	{0x1106, 0x8231, "VT8231", enable_flash_vt823x},
+	{0x1106, 0x3177, "VT8235", enable_flash_vt823x},
+	{0x1106, 0x3227, "VT8237", enable_flash_vt823x},
+	{0x1106, 0x0686, "VT82C686", enable_flash_amd8111},
+	{0x1078, 0x0100, "CS5530", enable_flash_cs5530},
+	{0x100b, 0x0510, "SC1100", enable_flash_sc1100},
+	{0x1039, 0x0008, "SIS5595", enable_flash_sis5595},
+	{0x1022, 0x7468, "AMD8111", enable_flash_amd8111},
+	/* this fallthrough looks broken. */
+        {0x10de, 0x0050, "NVIDIA CK804", enable_flash_ck804}, /* LPC */
+        {0x10de, 0x0051, "NVIDIA CK804", enable_flash_ck804}, /* Pro */
+        {0x10de, 0x00d3, "NVIDIA CK804", enable_flash_ck804}, /* Slave, should not be here, to fix known bug for A01. */
+
+        {0x10de, 0x0260, "NVidia MCP51", enable_flash_ck804},
+        {0x10de, 0x0261, "NVidia MCP51", enable_flash_ck804},
+        {0x10de, 0x0262, "NVidia MCP51", enable_flash_ck804},
+        {0x10de, 0x0263, "NVidia MCP51", enable_flash_ck804},
+
+	{0x10de, 0x0360, "NVIDIA MCP55", enable_flash_mcp55}, /* Gigabyte m57sli-s4 */
+	{0x10de, 0x0361, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */
+	{0x10de, 0x0362, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */
+	{0x10de, 0x0363, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */
+        {0x10de, 0x0364, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */
+	{0x10de, 0x0365, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */
+	{0x10de, 0x0366, "NVIDIA MCP55", enable_flash_mcp55}, /* LPC */
+	{0x10de, 0x0367, "NVIDIA MCP55", enable_flash_mcp55}, /* Pro */
+
+	{0x1002, 0x4377, "ATI SB400", enable_flash_sb400}, /* ATI Technologies Inc IXP SB400 PCI-ISA Bridge (rev 80) */
+};
+
+/*
+ *
+ */
+int
+chipset_flash_enable(void)
+{
+        struct pci_dev *dev = 0;
+        int ret = -2; /* nothing! */
+        int i;
+
+	/* now let's try to find the chipset we have ... */
+	for (i = 0; i < sizeof(enables) / sizeof(enables[0]); i++) {
+                dev = pci_dev_find(enables[i].vendor, enables[i].device);
+                if (dev)
+                        break;
+        }
+
+        if (dev) {
+                printf("Found chipset \"%s\": Enabling flash write... ",
+                       enables[i].name);
+
+                ret = enables[i].doit(dev, enables[i].name);
+                if (ret)
+                        printf("Failed!\n");
+                else
+                        printf("OK.\n");
+	}
+
+        return ret;
+}
Index: util/flashrom/flash_rom.c
===================================================================
--- util/flashrom/flash_rom.c	(revision 2573)
+++ util/flashrom/flash_rom.c	(working copy)
@@ -35,17 +35,70 @@
 #include <string.h>
 #include <stdlib.h>
 #include <getopt.h>
+#include <pci/pci.h>
 
+/* for iopl */
+#if defined (__sun) && (defined(__i386) || defined(__amd64))
+#include <strings.h>
+#include <sys/sysi86.h>
+#include <sys/psw.h>
+#include <asm/sunddi.h>
+#endif
+
 #include "flash.h"
 #include "lbtable.h"
 #include "layout.h"
 #include "debug.h"
 
 char *chip_to_probe = NULL;
-
+struct pci_access *pacc; /* For board and chipset_enable */
 int exclude_start_page, exclude_end_page;
 int force=0, verbose=0;
 
+/*
+ *
+ */
+struct pci_dev *
+pci_dev_find(uint16_t vendor, uint16_t device)
+{
+        struct pci_dev  *temp;
+        struct pci_filter  filter;
+
+        pci_filter_init(NULL, &filter);
+        filter.vendor = vendor;
+        filter.device = device;
+
+        for (temp = pacc->devices; temp; temp = temp->next)
+                if (pci_filter_match(&filter, temp))
+                        return temp;
+
+        return NULL;
+}
+
+/*
+ *
+ */
+struct pci_dev *
+pci_card_find(uint16_t vendor, uint16_t device,
+              uint16_t card_vendor, uint16_t card_device)
+{
+        struct pci_dev  *temp;
+        struct pci_filter  filter;
+
+        pci_filter_init(NULL, &filter);
+        filter.vendor = vendor;
+        filter.device = device;
+
+        for (temp = pacc->devices; temp; temp = temp->next)
+                if (pci_filter_match(&filter, temp)) {
+                        if ((card_vendor == pci_read_word(temp, 0x2C)) &&
+                            (card_device == pci_read_word(temp, 0x2E)))
+                                return temp;
+                }
+
+        return NULL;
+}
+
 struct flashchip *probe_flash(struct flashchip *flash)
 {
 	int fd_mem;
@@ -281,6 +334,22 @@
 	if (optind < argc)
 		filename = argv[optind++];
 
+        /* First get full io access */
+#if defined (__sun) && (defined(__i386) || defined(__amd64))
+	if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0){
+#else
+	if (iopl(3) != 0) {
+#endif
+		fprintf(stderr, "ERROR: iopl failed: \"%s\"\n", strerror(errno));
+		exit(1);
+	}
+
+        /* 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 */
+
 	printf("Calibrating delay loop... ");
 	myusec_calibrate_delay();
 	printf("ok\n");
@@ -293,8 +362,14 @@
 	/* try to enable it. Failure IS an option, since not all motherboards
 	 * really need this to be done, etc., etc.
 	 */
-	(void) enable_flash_write();
+        ret = chipset_flash_enable();
+        if (ret == -2)
+                printf("WARNING: No chipset found. Flash detection "
+                       "will most likely fail.\n");
 
+        board_flash_enable(lb_vendor, lb_part);
+
+
 	if ((flash = probe_flash(flashchips)) == NULL) {
 		printf("No EEPROM/flash device found.\n");
 		exit(1);
Index: util/flashrom/board_enable.c
===================================================================
--- util/flashrom/board_enable.c	(revision 0)
+++ util/flashrom/board_enable.c	(revision 0)
@@ -0,0 +1,301 @@
+/*
+ *   flash rom utility: enable flash writes
+ *
+ *   Copyright (C) 2000-2004 ???
+ *   Copyright (C) 2005 coresystems GmbH <stepan at openbios.org>
+ *   Copyright (C) 2006 Uwe Hermann <uwe at hermann-uwe.de>
+ *   Copyright (C) 2007 Luc Verhaegen <libv at skynet.be>
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   version 2
+ *
+ */
+
+/*
+ *
+ * Contains the board specific flash enables.
+ *
+ */
+
+#include <stdio.h>
+#include <pci/pci.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "flash.h"
+#include "debug.h"
+
+/*
+ * Used to be called Island Aruma.
+ *
+ * Will not match on the linuxbios name Island Aruma, new name is
+ * Agami aruma anyway.
+ *
+ * Match on pci-ids, no report received, just data from the mainboard
+ * specific code:
+ *   main: 0x1022:0x746B, which is the SMBUS controller.
+ *   card: 0x1022:0x36C0...
+ */
+static int
+board_agami_aruma(char *name)
+{
+#define EFIR 0x2e      /* Extended function index register, either 0x2e or 0x4e    */
+#define EFDR EFIR + 1  /* Extended function data register, one plus the index reg. */
+	char b;
+
+        /*  Disable the flash write protect.  The flash write protect is
+         *  connected to the WinBond w83627hf GPIO 24.
+         */
+	outb(0x87, EFIR); /* sequence to unlock extended functions */
+	outb(0x87, EFIR);
+
+	outb(0x20, EFIR); /* SIO device ID register */
+	b = inb(EFDR);
+	printf_debug("\nW83627HF device ID = 0x%x\n",b);
+
+	if (b != 0x52) {
+		perror("\nIncorrect device ID, aborting write protect disable\n");
+		return -1;
+	}
+
+	outb(0x2b, EFIR); /* GPIO multiplexed pin reg. */
+	b = inb(EFDR) | 0x10;
+	outb(0x2b, EFIR);
+	outb(b, EFDR); /* select GPIO 24 instead of WDTO */
+
+	outb(0x7, EFIR); /* logical device select */
+        outb(0x8, EFDR); /* point to device 8, GPIO port 2 */
+
+	outb(0x30, EFIR); /* logic device activation control */
+	outb(0x1, EFDR); /* activate */
+
+	outb(0xf0, EFIR); /* GPIO 20-27 I/O selection register */
+	b = inb(EFDR) & ~0x10;
+	outb(0xf0, EFIR);
+	outb(b, EFDR); /* set GPIO 24 as an output */
+
+	outb(0xf1, EFIR); /* GPIO 20-27 data register */
+	b = inb(EFDR) | 0x10;
+	outb(0xf1, EFIR);
+	outb(b, EFDR); /* set GPIO 24 */
+
+	outb(0xaa, EFIR); /* command to exit extended functions */
+
+	return 0;
+}
+
+/*
+ * Suited for VIAs EPIA M and MII, and maybe other CLE266 based EPIAs.
+ *
+ * We don't need to do this when using linuxbios, GPIO15 is never lowered there.
+ */
+static int
+board_via_epia_m(char *name)
+{
+        struct pci_dev *dev;
+        unsigned int base;
+        uint8_t val;
+
+        dev = pci_dev_find(0x1106, 0x3177); /* VT8235 ISA bridge */
+        if (!dev) {
+                fprintf(stderr, "\nERROR: VT8235 ISA Bridge not found.\n");
+                return -1;
+        }
+
+        /* GPIO12-15 -> output */
+        val = pci_read_byte(dev, 0xE4);
+        val |= 0x10;
+        pci_write_byte(dev, 0xE4, val);
+
+        /* Get Power Management IO address. */
+        base = pci_read_word(dev, 0x88) & 0xFF80;
+
+        /* enable GPIO15 which is connected to write protect. */
+        val = inb(base + 0x4D);
+        val |= 0x80;
+        outb(val, base + 0x4D);
+
+        return 0;
+}
+
+/*
+ * Winbond LPC super IO.
+ *
+ * Raises the ROM MEMW# line.
+ */
+static void
+w83697_rom_memw_enable(void)
+{
+        uint8_t val;
+
+        outb(0x87, 0x2E); /* enable extended functions */
+        outb(0x87, 0x2E);
+
+        outb(0x24, 0x2E); /* rom bits live here */
+
+        val = inb(0x2F);
+        if (!(val & 0x02)) /* flash rom enabled? */
+                outb(val | 0x08, 0x2F); /* enable MEMW# */
+
+        outb(0xAA, 0x2E); /* disable extended functions */
+}
+
+/*
+ * Suited for Asus A7V8X-MX SE and A7V400-MX.
+ *
+ */
+static int
+board_asus_a7v8x_mx(char *name)
+{
+        struct pci_dev *dev;
+        uint8_t val;
+
+        dev = pci_dev_find(0x1106, 0x3177); /* VT8235 ISA bridge */
+        if (!dev) {
+                fprintf(stderr, "\nERROR: VT8235 ISA Bridge not found.\n");
+                return -1;
+        }
+
+        /* This bit is marked reserved actually */
+        val = pci_read_byte(dev, 0x59);
+        val &= 0x7F;
+        pci_write_byte(dev, 0x59, val);
+
+        w83697_rom_memw_enable();
+
+        return 0;
+}
+
+/*
+ * We use 2 sets of ids here, you're free to choose which is which. This to
+ * provide a very high degree of certainty when matching a board on the basis of
+ * Subsystem/card ids. As not every vendor handles subsystem/card ids in a sane
+ * manner.
+ *
+ * Keep the second set nulled if it should be ignored.
+ *
+ */
+struct board_pciid_enable {
+        /* Any device, but make it sensible, like the isa bridge. */
+        uint16_t  first_vendor;
+        uint16_t  first_device;
+        uint16_t  first_card_vendor;
+        uint16_t  first_card_device;
+
+        /* Any device, but make it sensible, like the host bridge. May be null */
+        uint16_t  second_vendor;
+        uint16_t  second_device;
+        uint16_t  second_card_vendor;
+        uint16_t  second_card_device;
+
+        /* From linuxbios table */
+        char  *lb_vendor;
+        char  *lb_part;
+
+        char  *name;
+        int  (*enable)(char *name);
+};
+
+struct board_pciid_enable board_pciid_enables[] = {
+        { 0x1022, 0x746B, 0x1022, 0x36C0,  0x0000, 0x0000, 0x0000, 0x0000, "AGAMI", "ARUMA", "Agami Aruma", board_agami_aruma },
+        { 0x1106, 0x3177, 0x1106, 0xAA01,  0x1106, 0x3123, 0x1106, 0xAA01, NULL, NULL, "VIA EPIA M/MII/...", board_via_epia_m },
+        { 0x1106, 0x3177, 0x1043, 0x80A1,  0x1106, 0x3205, 0x1043, 0x8118, NULL, NULL, "Asus A7V8-MX SE", board_asus_a7v8x_mx },
+        { 0, 0, 0, 0,  0, 0, 0, 0, NULL, NULL } /* Keep this */
+
+};
+
+/*
+ * Match boards on linuxbios table gathered vendor and part name.
+ * Require main pci-ids to match too as extra safety.
+ *
+ */
+static struct board_pciid_enable *
+board_match_linuxbios_name(char *vendor, char *part)
+{
+        struct board_pciid_enable *board = board_pciid_enables;
+
+        for (; board->name; board++) {
+                if (!board->lb_vendor || strcmp(board->lb_vendor, vendor))
+                        continue;
+
+                if (!board->lb_part || strcmp(board->lb_part, part))
+                        continue;
+
+                if (!pci_dev_find(board->first_vendor, board->first_device))
+                        continue;
+
+                if (board->second_vendor &&
+                    !pci_dev_find(board->second_vendor, board->second_device))
+                        continue;
+                return board;
+        }
+        return NULL;
+}
+
+/*
+ * Match boards on pci ids and subsystem ids.
+ * Second set of ids can be main only or missing completely.
+ */
+static struct board_pciid_enable *
+board_match_pci_card_ids(void)
+{
+        struct board_pciid_enable *board = board_pciid_enables;
+
+        for (; board->name; board++) {
+                if (!board->first_card_vendor || !board->first_card_device)
+                        continue;
+
+                if (!pci_card_find(board->first_vendor, board->first_device,
+                                   board->first_card_vendor,
+                                   board->first_card_device))
+                        continue;
+
+                if (board->second_vendor) {
+                        if (board->second_card_vendor) {
+                                if (!pci_card_find(board->second_vendor,
+                                                   board->second_device,
+                                                   board->second_card_vendor,
+                                                   board->second_card_device))
+                                        continue;
+                        } else {
+                                if (!pci_dev_find(board->second_vendor,
+                                                  board->second_device))
+                                        continue;
+                        }
+                }
+
+                return board;
+        }
+
+        return NULL;
+}
+
+/*
+ *
+ */
+int
+board_flash_enable(char *vendor, char *part)
+{
+        struct board_pciid_enable *board = NULL;
+        int ret = 0;
+
+        if (vendor && part)
+                board = board_match_linuxbios_name(vendor, part);
+
+        if (!board)
+                board = board_match_pci_card_ids();
+
+        if (board) {
+                printf("Found board \"%s\": Enabling flash write... ",
+                       board->name);
+
+                ret = board->enable(board->name);
+                if (ret)
+                        printf("Failed!\n");
+                else
+                        printf("OK.\n");
+        }
+
+        return ret;
+}


More information about the coreboot mailing list