Author: stepan Date: 2007-04-05 00:45:58 +0200 (Thu, 05 Apr 2007) New Revision: 2581
Added: trunk/LinuxBIOSv2/util/flashrom/board_enable.c trunk/LinuxBIOSv2/util/flashrom/chipset_enable.c Removed: trunk/LinuxBIOSv2/util/flashrom/flash_enable.c Modified: trunk/LinuxBIOSv2/util/flashrom/Makefile trunk/LinuxBIOSv2/util/flashrom/flash.h trunk/LinuxBIOSv2/util/flashrom/flash_rom.c Log: 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@skynet.be Acked-by: Stefan Reinauer stepan@coresystems.de
Modified: trunk/LinuxBIOSv2/util/flashrom/Makefile =================================================================== --- trunk/LinuxBIOSv2/util/flashrom/Makefile 2007-04-03 10:45:53 UTC (rev 2580) +++ trunk/LinuxBIOSv2/util/flashrom/Makefile 2007-04-04 22:45:58 UTC (rev 2581) @@ -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)
Added: trunk/LinuxBIOSv2/util/flashrom/board_enable.c =================================================================== --- trunk/LinuxBIOSv2/util/flashrom/board_enable.c (rev 0) +++ trunk/LinuxBIOSv2/util/flashrom/board_enable.c 2007-04-04 22:45:58 UTC (rev 2581) @@ -0,0 +1,299 @@ +/* + * flash rom utility: enable flash writes (board specific) + * + * Copyright (C) 2005-2007 coresystems GmbH stepan@coresystems.de + * Copyright (C) 2006 Uwe Hermann uwe@hermann-uwe.de + * Copyright (C) 2007 Luc Verhaegen libv@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" + +/* + * 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) +{ + /* Extended function index register, either 0x2e or 0x4e */ +#define EFIR 0x2e + /* Extended function data register, one plus the index reg. */ +#define EFDR EFIR + 1 + 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) { + fprintf(stderr, "\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; +}
Added: trunk/LinuxBIOSv2/util/flashrom/chipset_enable.c =================================================================== --- trunk/LinuxBIOSv2/util/flashrom/chipset_enable.c (rev 0) +++ trunk/LinuxBIOSv2/util/flashrom/chipset_enable.c 2007-04-04 22:45:58 UTC (rev 2581) @@ -0,0 +1,469 @@ +/* + * flash rom utility: enable flash writes + * + * Copyright (C) 2000 Silicon Integrated System Corporation + * Copyright (C) 2005-2007 coresystems GmbH stepan@coresystems.de + * Copyright (C) 2006 Uwe Hermann uwe@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; +} + +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) { + fprintf(stderr, "ERROR: 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; +} + +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, 0x27b0, "ICH7DH", 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; +}
Modified: trunk/LinuxBIOSv2/util/flashrom/flash.h =================================================================== --- trunk/LinuxBIOSv2/util/flashrom/flash.h 2007-04-03 10:45:53 UTC (rev 2580) +++ trunk/LinuxBIOSv2/util/flashrom/flash.h 2007-04-04 22:45:58 UTC (rev 2581) @@ -3,7 +3,7 @@ * * Copyright 2000 Silicon Integrated System Corporation * Copyright 2000 Ronald G. Minnich rminnich@gmail.com - * Copyright 2005 coresystems GmbH stepan@coresystems.de + * Copyright 2005-2007 coresystems GmbH stepan@coresystems.de * * 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 @@ -128,8 +128,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))
Deleted: trunk/LinuxBIOSv2/util/flashrom/flash_enable.c =================================================================== --- trunk/LinuxBIOSv2/util/flashrom/flash_enable.c 2007-04-03 10:45:53 UTC (rev 2580) +++ trunk/LinuxBIOSv2/util/flashrom/flash_enable.c 2007-04-04 22:45:58 UTC (rev 2581) @@ -1,597 +0,0 @@ -/* - * flash rom utility: enable flash writes - * - * Copyright (C) 2000-2004 ??? - * Copyright (C) 2005 coresystems GmbH stepan@openbios.org - * Copyright (C) 2006 Uwe Hermann uwe@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, 0x27b0, "ICH7DH", 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; -}
Modified: trunk/LinuxBIOSv2/util/flashrom/flash_rom.c =================================================================== --- trunk/LinuxBIOSv2/util/flashrom/flash_rom.c 2007-04-03 10:45:53 UTC (rev 2580) +++ trunk/LinuxBIOSv2/util/flashrom/flash_rom.c 2007-04-04 22:45:58 UTC (rev 2581) @@ -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; @@ -72,10 +125,11 @@ __FUNCTION__, flash->total_size * 1024, (unsigned long) size); } + bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t) (0xffffffff - size + 1)); if (bios == MAP_FAILED) { - perror("Error: Can't mmap /dev/mem."); + perror("Error: Can't mmap " MEM_DEV "."); exit(1); } flash->virt_addr = bios; @@ -92,7 +146,7 @@ bios = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED, fd_mem, (off_t) (0x9400000)); if (bios == MAP_FAILED) { - perror("Error: Can't mmap /dev/mem."); + perror("Error: Can't mmap " MEM_DEV "."); exit(1); } flash->virt_addr = bios; @@ -281,6 +335,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 +363,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);