summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUwe Hermann <uwe@hermann-uwe.de>2009-09-30 18:29:55 +0000
committerUwe Hermann <uwe@hermann-uwe.de>2009-09-30 18:29:55 +0000
commit2bc98f6c915f615fe5262eceeeb280c12d337357 (patch)
tree38ba744f115d9c9673f2edc35176e2ba7bb211d1
parent547872b4ea74b821caec03f9ae6498f4a3e82443 (diff)
downloadast2050-flashrom-2bc98f6c915f615fe5262eceeeb280c12d337357.zip
ast2050-flashrom-2bc98f6c915f615fe5262eceeeb280c12d337357.tar.gz
Add initial support for flashing some NVIDIA graphics cards
The new option is '-p gfxnvidia', rest of the interface is as usual. I tested a successful identify and read on a "RIVA TNT2 Model 64/Model 64 Pro" card for now, erase and write did NOT work properly so far! Please do not attempt to write/erase cards yet, unless you can recover! In addition to the NVIDIA handling code it was required to call programmer_shutdown() in a lot more places, otherwise the graphics card will be disabled in the init function, but never enabled again as the shutdown function is not called. The shutdown handling may be changed to use atexit() later. Corresponding to flashrom svn r737. Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de> Acked-by: Luc Verhaegen <libv@skynet.be>
-rw-r--r--Makefile8
-rw-r--r--flash.h10
-rw-r--r--flashrom.83
-rw-r--r--flashrom.c40
-rw-r--r--gfxnvidia.c104
-rw-r--r--pcidev.c16
6 files changed, 175 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index df9f73d..5cc0077 100644
--- a/Makefile
+++ b/Makefile
@@ -74,6 +74,9 @@ CONFIG_BITBANG_SPI ?= no
# Always enable 3Com NICs for now.
CONFIG_NIC3COM ?= yes
+# Always enable NVIDIA graphics cards for now.
+CONFIG_GFXNVIDIA ?= yes
+
# Always enable SiI SATA controllers for now.
CONFIG_SATASII ?= yes
@@ -107,6 +110,11 @@ FEATURE_CFLAGS += -D'NIC3COM_SUPPORT=1'
OBJS += nic3com.o
endif
+ifeq ($(CONFIG_GFXNVIDIA), yes)
+FEATURE_CFLAGS += -D'GFXNVIDIA_SUPPORT=1'
+OBJS += gfxnvidia.o
+endif
+
ifeq ($(CONFIG_SATASII), yes)
FEATURE_CFLAGS += -D'SATASII_SUPPORT=1'
OBJS += satasii.o
diff --git a/flash.h b/flash.h
index 376204a..b5b9ff5 100644
--- a/flash.h
+++ b/flash.h
@@ -88,6 +88,9 @@ enum programmer {
#if NIC3COM_SUPPORT == 1
PROGRAMMER_NIC3COM,
#endif
+#if GFXNVIDIA_SUPPORT == 1
+ PROGRAMMER_GFXNVIDIA,
+#endif
#if DRKAISER_SUPPORT == 1
PROGRAMMER_DRKAISER,
#endif
@@ -437,6 +440,13 @@ void nic3com_chip_writeb(uint8_t val, chipaddr addr);
uint8_t nic3com_chip_readb(const chipaddr addr);
extern struct pcidev_status nics_3com[];
+/* gfxnvidia.c */
+int gfxnvidia_init(void);
+int gfxnvidia_shutdown(void);
+void gfxnvidia_chip_writeb(uint8_t val, chipaddr addr);
+uint8_t gfxnvidia_chip_readb(const chipaddr addr);
+extern struct pcidev_status gfx_nvidia[];
+
/* drkaiser.c */
int drkaiser_init(void);
int drkaiser_shutdown(void);
diff --git a/flashrom.8 b/flashrom.8
index 6ceeded..3986f75 100644
--- a/flashrom.8
+++ b/flashrom.8
@@ -140,6 +140,8 @@ Specify the programmer device. Currently supported are:
.sp
.BR "* nic3com" " (for flash ROMs on 3COM network cards)"
.sp
+.BR "* gfxnvidia" " (for flash ROMs on NVIDIA graphics cards)"
+.sp
.BR "* drkaiser" " (for flash ROMs on Dr. Kaiser PC-Waechter PCI cards)"
.sp
.BR "* satasii" " (for flash ROMs on Silicon Image SATA/IDE controllers)"
@@ -180,6 +182,7 @@ Example:
.sp
Currently the following programmers support this mechanism:
.BR nic3com ,
+.BR gfxnvidia ,
.BR satasii .
.sp
The it87spi programmer has an optional parameter which will set the I/O base
diff --git a/flashrom.c b/flashrom.c
index 7eb4962..8eb3d39 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -92,6 +92,25 @@ const struct programmer_entry programmer_table[] = {
},
#endif
+#if GFXNVIDIA_SUPPORT == 1
+ {
+ .name = "gfxnvidia",
+ .init = gfxnvidia_init,
+ .shutdown = gfxnvidia_shutdown,
+ .map_flash_region = fallback_map,
+ .unmap_flash_region = fallback_unmap,
+ .chip_readb = gfxnvidia_chip_readb,
+ .chip_readw = fallback_chip_readw,
+ .chip_readl = fallback_chip_readl,
+ .chip_readn = fallback_chip_readn,
+ .chip_writeb = gfxnvidia_chip_writeb,
+ .chip_writew = fallback_chip_writew,
+ .chip_writel = fallback_chip_writel,
+ .chip_writen = fallback_chip_writen,
+ .delay = internal_delay,
+ },
+#endif
+
#if DRKAISER_SUPPORT == 1
{
.name = "drkaiser",
@@ -824,6 +843,9 @@ int main(int argc, char *argv[])
#if NIC3COM_SUPPORT == 1
print_supported_pcidevs(nics_3com);
#endif
+#if GFXNVIDIA_SUPPORT == 1
+ print_supported_pcidevs(gfx_nvidia);
+#endif
#if DRKAISER_SUPPORT == 1
print_supported_pcidevs(drkaiser_pcidev);
#endif
@@ -868,6 +890,7 @@ int main(int argc, char *argv[])
for (i = 0; i < ARRAY_SIZE(flashes) && flashes[i]; i++)
printf(" %s", flashes[i]->name);
printf("\nPlease specify which chip to use with the -c <chipname> option.\n");
+ programmer_shutdown();
exit(1);
} else if (!flashes[0]) {
printf("No EEPROM/flash device found.\n");
@@ -890,6 +913,7 @@ int main(int argc, char *argv[])
return read_flash(flashes[0], filename);
}
// FIXME: flash writes stay enabled!
+ programmer_shutdown();
exit(1);
}
@@ -935,12 +959,14 @@ int main(int argc, char *argv[])
if (!(read_it | write_it | verify_it | erase_it)) {
printf("No operations were specified.\n");
// FIXME: flash writes stay enabled!
+ programmer_shutdown();
exit(1);
}
if (!filename && !erase_it) {
printf("Error: No filename specified.\n");
// FIXME: flash writes stay enabled!
+ programmer_shutdown();
exit(1);
}
@@ -956,6 +982,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Erase is not working on this chip. ");
if (!force) {
fprintf(stderr, "Aborting.\n");
+ programmer_shutdown();
return 1;
} else {
fprintf(stderr, "Continuing anyway.\n");
@@ -963,11 +990,14 @@ int main(int argc, char *argv[])
}
if (erase_flash(flash)) {
emergency_help_message();
+ programmer_shutdown();
return 1;
}
} else if (read_it) {
- if (read_flash(flash, filename))
+ if (read_flash(flash, filename)) {
+ programmer_shutdown();
return 1;
+ }
} else {
struct stat image_stat;
@@ -976,6 +1006,7 @@ int main(int argc, char *argv[])
"and erase is needed for write. ");
if (!force) {
fprintf(stderr, "Aborting.\n");
+ programmer_shutdown();
return 1;
} else {
fprintf(stderr, "Continuing anyway.\n");
@@ -985,6 +1016,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Write is not working on this chip. ");
if (!force) {
fprintf(stderr, "Aborting.\n");
+ programmer_shutdown();
return 1;
} else {
fprintf(stderr, "Continuing anyway.\n");
@@ -992,14 +1024,17 @@ int main(int argc, char *argv[])
}
if ((image = fopen(filename, "r")) == NULL) {
perror(filename);
+ programmer_shutdown();
exit(1);
}
if (fstat(fileno(image), &image_stat) != 0) {
perror(filename);
+ programmer_shutdown();
exit(1);
}
if (image_stat.st_size != flash->total_size * 1024) {
fprintf(stderr, "Error: Image size doesn't match\n");
+ programmer_shutdown();
exit(1);
}
@@ -1008,6 +1043,7 @@ int main(int argc, char *argv[])
fclose(image);
if (numbytes != size) {
fprintf(stderr, "Error: Failed to read file. Got %ld bytes, wanted %ld!\n", numbytes, size);
+ programmer_shutdown();
return 1;
}
}
@@ -1022,12 +1058,14 @@ int main(int argc, char *argv[])
printf("Writing flash chip... ");
if (!flash->write) {
fprintf(stderr, "Error: flashrom has no write function for this flash chip.\n");
+ programmer_shutdown();
return 1;
}
ret = flash->write(flash, buf);
if (ret) {
fprintf(stderr, "FAILED!\n");
emergency_help_message();
+ programmer_shutdown();
return 1;
} else {
printf("COMPLETE.\n");
diff --git a/gfxnvidia.c b/gfxnvidia.c
new file mode 100644
index 0000000..1e9b679
--- /dev/null
+++ b/gfxnvidia.c
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2009 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include "flash.h"
+
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+
+uint8_t *nvidia_bar;
+
+struct pcidev_status gfx_nvidia[] = {
+ {0x10de, 0x0010, PCI_NT, "NVIDIA", "Mutara V08 [NV2]" },
+ {0x10de, 0x0018, PCI_NT, "NVIDIA", "RIVA 128" },
+ {0x10de, 0x0020, PCI_NT, "NVIDIA", "RIVA TNT" },
+ {0x10de, 0x0028, PCI_NT, "NVIDIA", "RIVA TNT2/TNT2 Pro" },
+ {0x10de, 0x0029, PCI_NT, "NVIDIA", "RIVA TNT2 Ultra" },
+ {0x10de, 0x002c, PCI_NT, "NVIDIA", "Vanta/Vanta LT" },
+ {0x10de, 0x002d, PCI_OK, "NVIDIA", "RIVA TNT2 Model 64/Model 64 Pro" },
+ {0x10de, 0x00a0, PCI_NT, "NVIDIA", "Aladdin TNT2" },
+ {0x10de, 0x0100, PCI_NT, "NVIDIA", "GeForce 256" },
+ {0x10de, 0x0101, PCI_NT, "NVIDIA", "GeForce DDR" },
+ {0x10de, 0x0103, PCI_NT, "NVIDIA", "Quadro" },
+ {0x10de, 0x0110, PCI_NT, "NVIDIA", "GeForce2 MX" },
+ {0x10de, 0x0111, PCI_NT, "NVIDIA", "GeForce2 MX" },
+ {0x10de, 0x0112, PCI_NT, "NVIDIA", "GeForce2 GO" },
+ {0x10de, 0x0113, PCI_NT, "NVIDIA", "Quadro2 MXR" },
+ {0x10de, 0x0150, PCI_NT, "NVIDIA", "GeForce2 GTS/Pro" },
+ {0x10de, 0x0151, PCI_NT, "NVIDIA", "GeForce2 GTS" },
+ {0x10de, 0x0152, PCI_NT, "NVIDIA", "GeForce2 Ultra" },
+ {0x10de, 0x0153, PCI_NT, "NVIDIA", "Quadro2 Pro" },
+ {0x10de, 0x0200, PCI_NT, "NVIDIA", "GeForce 3 nFX" },
+ {0x10de, 0x0201, PCI_NT, "NVIDIA", "GeForce 3 nFX" },
+ {0x10de, 0x0202, PCI_NT, "NVIDIA", "GeForce 3 nFX Ultra" },
+ {0x10de, 0x0203, PCI_NT, "NVIDIA", "Quadro 3 DDC" },
+
+ {},
+};
+
+int gfxnvidia_init(void)
+{
+ uint32_t reg32;
+
+ get_io_perms();
+
+ io_base_addr = pcidev_init(PCI_VENDOR_ID_NVIDIA, PCI_BASE_ADDRESS_0,
+ gfx_nvidia, programmer_param);
+ io_base_addr += 0x300000;
+ printf("Detected NVIDIA I/O base address: 0x%x.\n", io_base_addr);
+
+ /* Allow access to flash interface (will disable screen). */
+ reg32 = pci_read_long(pcidev_dev, 0x50);
+ reg32 &= ~(1 << 0);
+ pci_write_long(pcidev_dev, 0x50, reg32);
+
+ nvidia_bar = physmap("NVIDIA", io_base_addr, 16 * 1024 * 1024);
+
+ buses_supported = CHIP_BUSTYPE_PARALLEL;
+
+ return 0;
+}
+
+int gfxnvidia_shutdown(void)
+{
+ uint32_t reg32;
+
+ /* Disallow access to flash interface (and re-enable screen). */
+ reg32 = pci_read_long(pcidev_dev, 0x50);
+ reg32 |= (1 << 0);
+ pci_write_long(pcidev_dev, 0x50, reg32);
+
+ free(programmer_param);
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+}
+
+void gfxnvidia_chip_writeb(uint8_t val, chipaddr addr)
+{
+ mmio_writeb(val, nvidia_bar + addr);
+}
+
+uint8_t gfxnvidia_chip_readb(const chipaddr addr)
+{
+ return mmio_readb(nvidia_bar + addr);
+}
diff --git a/pcidev.c b/pcidev.c
index 3ad9db5..9630786 100644
--- a/pcidev.c
+++ b/pcidev.c
@@ -28,7 +28,8 @@ struct pci_access *pacc;
struct pci_filter filter;
struct pci_dev *pcidev_dev = NULL;
-uint32_t pcidev_validate(struct pci_dev *dev, uint32_t bar, struct pcidev_status *devs)
+uint32_t pcidev_validate(struct pci_dev *dev, uint32_t bar,
+ struct pcidev_status *devs)
{
int i;
uint32_t addr;
@@ -37,12 +38,16 @@ uint32_t pcidev_validate(struct pci_dev *dev, uint32_t bar, struct pcidev_status
if (dev->device_id != devs[i].device_id)
continue;
- /* Don't use dev->base_addr[x] (as value for 'bar'), won't work on older libpci. */
+ /*
+ * Don't use dev->base_addr[x] (as value for 'bar'), won't
+ * work on older libpci.
+ */
addr = pci_read_long(dev, bar) & ~0x03;
printf("Found \"%s %s\" (%04x:%04x, BDF %02x:%02x.%x).\n",
- devs[i].vendor_name, devs[i].device_name, dev->vendor_id,
- dev->device_id, dev->bus, dev->dev, dev->func);
+ devs[i].vendor_name, devs[i].device_name,
+ dev->vendor_id, dev->device_id, dev->bus, dev->dev,
+ dev->func);
if (devs[i].status == PCI_NT) {
printf("===\nThis PCI device is UNTESTED. Please "
@@ -57,7 +62,8 @@ uint32_t pcidev_validate(struct pci_dev *dev, uint32_t bar, struct pcidev_status
return 0;
}
-uint32_t pcidev_init(uint16_t vendor_id, uint32_t bar, struct pcidev_status *devs, char *pcidev_bdf)
+uint32_t pcidev_init(uint16_t vendor_id, uint32_t bar,
+ struct pcidev_status *devs, char *pcidev_bdf)
{
struct pci_dev *dev;
char *msg = NULL;
OpenPOWER on IntegriCloud