summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Hendricks <dhendrix@google.com>2011-06-14 01:35:36 +0000
committerDavid Hendricks <david.hendricks@gmail.com>2011-06-14 01:35:36 +0000
commit8bb2021d77c8ee213b53d671687b7a1179335522 (patch)
treea77cc4239b59731e98cf6c9681b5a7c665613038
parent9d9a1042332cd08aa66eee6f37d80c0f09f47d70 (diff)
downloadast2050-flashrom-8bb2021d77c8ee213b53d671687b7a1179335522.zip
ast2050-flashrom-8bb2021d77c8ee213b53d671687b7a1179335522.tar.gz
Use shutdown callback mechanism to shutdown programmers
This patch attempts to resolve some programmer shutdown ordering issues by having the programmer init functions register shutdown callbacks explicitly wherever it makes most sense. Before, assumptions were made that could lead to the internal programmer's state changing before the external programmer could be shut down properly. Now, each programmer cleans up after itself and (hopefully) performs each operation in the correct order. As a side-effect, this patch gives us a better usage model for reverse operations such as rpci_* and rmmio_*. In the long-run, this should make reversing the initialization process easier to understand, less tedious, and less error-prone. In short, this patch does the following: - Registers a shutdown callback during initialization for each programmer. - Kills the .shutdown function pointer from programmer_entry struct. Also, make most shutdown functions static. - Adds a few minor clean-ups and corrections (e.g. missing physunmap() calls). TODO: Remove forward declaration of serprog_shutdown() (added to simplify diff) Corresponding to flashrom svn r1338. Signed-off-by: David Hendricks <dhendrix@google.com> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
-rw-r--r--atahpt.c18
-rw-r--r--buspirate_spi.c73
-rw-r--r--cli_classic.c1
-rw-r--r--dediprog.c41
-rw-r--r--drkaiser.c23
-rw-r--r--dummyflasher.c38
-rw-r--r--flash.h2
-rw-r--r--flashrom.c28
-rw-r--r--gfxnvidia.c30
-rw-r--r--hwaccess.c3
-rw-r--r--internal.c15
-rw-r--r--it85spi.c18
-rw-r--r--nic3com.c32
-rw-r--r--nicintel.c29
-rw-r--r--nicintel_spi.c41
-rw-r--r--nicnatsemi.c16
-rw-r--r--nicrealtek.c18
-rw-r--r--ogp_spi.c21
-rw-r--r--pcidev.c3
-rw-r--r--programmer.h21
-rw-r--r--satamv.c19
-rw-r--r--satasii.c22
-rw-r--r--serial.c2
-rw-r--r--serprog.c12
24 files changed, 284 insertions, 242 deletions
diff --git a/atahpt.c b/atahpt.c
index 82b430d..2bf4a11 100644
--- a/atahpt.c
+++ b/atahpt.c
@@ -38,6 +38,14 @@ const struct pcidev_status ata_hpt[] = {
{},
};
+static int atahpt_shutdown(void *data)
+{
+ /* Flash access is disabled automatically by PCI restore. */
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+}
+
int atahpt_init(void)
{
uint32_t reg32;
@@ -53,14 +61,8 @@ int atahpt_init(void)
buses_supported = CHIP_BUSTYPE_PARALLEL;
- return 0;
-}
-
-int atahpt_shutdown(void)
-{
- /* Flash access is disabled automatically by PCI restore. */
- pci_cleanup(pacc);
- release_io_perms();
+ if (register_shutdown(atahpt_shutdown, NULL))
+ return 1;
return 0;
}
diff --git a/buspirate_spi.c b/buspirate_spi.c
index 3ac0929..3b9f487 100644
--- a/buspirate_spi.c
+++ b/buspirate_spi.c
@@ -111,6 +111,41 @@ static const struct buspirate_spispeeds spispeeds[] = {
{NULL, 0x0}
};
+static int buspirate_spi_shutdown(void *data)
+{
+ unsigned char buf[5];
+ int ret = 0;
+
+ /* Exit raw SPI mode (enter raw bitbang mode) */
+ buf[0] = 0x00;
+ ret = buspirate_sendrecv(buf, 1, 5);
+ if (ret)
+ return ret;
+ if (memcmp(buf, "BBIO", 4)) {
+ msg_perr("Entering raw bitbang mode failed!\n");
+ return 1;
+ }
+ msg_pdbg("Raw bitbang mode version %c\n", buf[4]);
+ if (buf[4] != '1') {
+ msg_perr("Can't handle raw bitbang mode version %c!\n",
+ buf[4]);
+ return 1;
+ }
+ /* Reset Bus Pirate (return to user terminal) */
+ buf[0] = 0x0f;
+ ret = buspirate_sendrecv(buf, 1, 0);
+ if (ret)
+ return ret;
+
+ /* Shut down serial port communication */
+ ret = serialport_shutdown(NULL);
+ if (ret)
+ return ret;
+ msg_pdbg("Bus Pirate shutdown completed.\n");
+
+ return 0;
+}
+
int buspirate_spi_init(void)
{
unsigned char buf[512];
@@ -148,6 +183,9 @@ int buspirate_spi_init(void)
return ret;
free(dev);
+ if (register_shutdown(buspirate_spi_shutdown, NULL))
+ return 1;
+
/* This is the brute force version, but it should work. */
for (i = 0; i < 19; i++) {
/* Enter raw bitbang mode */
@@ -253,41 +291,6 @@ int buspirate_spi_init(void)
return 0;
}
-int buspirate_spi_shutdown(void)
-{
- unsigned char buf[5];
- int ret = 0;
-
- /* Exit raw SPI mode (enter raw bitbang mode) */
- buf[0] = 0x00;
- ret = buspirate_sendrecv(buf, 1, 5);
- if (ret)
- return ret;
- if (memcmp(buf, "BBIO", 4)) {
- msg_perr("Entering raw bitbang mode failed!\n");
- return 1;
- }
- msg_pdbg("Raw bitbang mode version %c\n", buf[4]);
- if (buf[4] != '1') {
- msg_perr("Can't handle raw bitbang mode version %c!\n",
- buf[4]);
- return 1;
- }
- /* Reset Bus Pirate (return to user terminal) */
- buf[0] = 0x0f;
- ret = buspirate_sendrecv(buf, 1, 0);
- if (ret)
- return ret;
-
- /* Shut down serial port communication */
- ret = serialport_shutdown();
- if (ret)
- return ret;
- msg_pdbg("Bus Pirate shutdown completed.\n");
-
- return 0;
-}
-
static int buspirate_spi_send_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr)
{
diff --git a/cli_classic.c b/cli_classic.c
index d1b4686..59096a0 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -360,6 +360,7 @@ int cli_classic(int argc, char *argv[])
if (programmer_init(pparam)) {
fprintf(stderr, "Error: Programmer initialization failed.\n");
+ programmer_shutdown();
exit(1);
}
diff --git a/dediprog.c b/dediprog.c
index 1c54c66..1cbde18 100644
--- a/dediprog.c
+++ b/dediprog.c
@@ -536,6 +536,25 @@ static const struct spi_programmer spi_programmer_dediprog = {
.write_256 = dediprog_spi_write_256,
};
+static int dediprog_shutdown(void *data)
+{
+ msg_pspew("%s\n", __func__);
+
+ /* URB 28. Command Set SPI Voltage to 0. */
+ if (dediprog_set_spi_voltage(0x0))
+ return 1;
+
+ if (usb_release_interface(dediprog_handle, 0)) {
+ msg_perr("Could not release USB interface!\n");
+ return 1;
+ }
+ if (usb_close(dediprog_handle)) {
+ msg_perr("Could not close USB device!\n");
+ return 1;
+ }
+ return 0;
+}
+
/* URB numbers refer to the first log ever captured. */
int dediprog_init(void)
{
@@ -587,6 +606,9 @@ int dediprog_init(void)
}
dediprog_endpoint = 2;
+ if (register_shutdown(dediprog_shutdown, NULL))
+ return 1;
+
dediprog_set_leds(PASS_ON|BUSY_ON|ERROR_ON);
/* URB 6. Command A. */
@@ -681,22 +703,3 @@ static int dediprog_do_stuff(void)
return 0;
}
#endif
-
-int dediprog_shutdown(void)
-{
- msg_pspew("%s\n", __func__);
-
- /* URB 28. Command Set SPI Voltage to 0. */
- if (dediprog_set_spi_voltage(0x0))
- return 1;
-
- if (usb_release_interface(dediprog_handle, 0)) {
- msg_perr("Could not release USB interface!\n");
- return 1;
- }
- if (usb_close(dediprog_handle)) {
- msg_perr("Could not close USB device!\n");
- return 1;
- }
- return 0;
-}
diff --git a/drkaiser.c b/drkaiser.c
index c2938dd..db4be60 100644
--- a/drkaiser.c
+++ b/drkaiser.c
@@ -27,6 +27,8 @@
#define PCI_MAGIC_DRKAISER_ADDR 0x50
#define PCI_MAGIC_DRKAISER_VALUE 0xa971
+#define DRKAISER_MEMMAP_SIZE (1024 * 128)
+
/* Mask to restrict flash accesses to the 128kB memory window. */
#define DRKAISER_MEMMAP_MASK ((1 << 17) - 1)
@@ -37,6 +39,15 @@ const struct pcidev_status drkaiser_pcidev[] = {
static uint8_t *drkaiser_bar;
+static int drkaiser_shutdown(void *data)
+{
+ physunmap(drkaiser_bar, DRKAISER_MEMMAP_SIZE);
+ /* Flash write is disabled automatically by PCI restore. */
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+};
+
int drkaiser_init(void)
{
uint32_t addr;
@@ -51,21 +62,15 @@ int drkaiser_init(void)
/* Map 128kB flash memory window. */
drkaiser_bar = physmap("Dr. Kaiser PC-Waechter flash memory",
- addr, 128 * 1024);
+ addr, DRKAISER_MEMMAP_SIZE);
buses_supported = CHIP_BUSTYPE_PARALLEL;
+ if (register_shutdown(drkaiser_shutdown, NULL))
+ return 1;
return 0;
}
-int drkaiser_shutdown(void)
-{
- /* Flash write is disabled automatically by PCI restore. */
- pci_cleanup(pacc);
- release_io_perms();
- return 0;
-};
-
void drkaiser_chip_writeb(uint8_t val, chipaddr addr)
{
pci_mmio_writeb(val, drkaiser_bar + (addr & DRKAISER_MEMMAP_MASK));
diff --git a/dummyflasher.c b/dummyflasher.c
index fdb4f2a..fca228c 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -73,6 +73,23 @@ static const struct spi_programmer spi_programmer_dummyflasher = {
.read = default_spi_read,
.write_256 = dummy_spi_write_256,
};
+
+static int dummy_shutdown(void *data)
+{
+ msg_pspew("%s\n", __func__);
+#if EMULATE_CHIP
+ if (emu_chip != EMULATE_NONE) {
+ if (emu_persistent_image) {
+ msg_pdbg("Writing %s\n", emu_persistent_image);
+ write_buf_to_file(flashchip_contents, emu_chip_size,
+ emu_persistent_image);
+ }
+ free(flashchip_contents);
+ }
+#endif
+ return 0;
+}
+
int dummy_init(void)
{
char *bustext = NULL;
@@ -126,7 +143,7 @@ int dummy_init(void)
if (!tmp) {
msg_pdbg("Not emulating any flash chip.\n");
/* Nothing else to do. */
- return 0;
+ goto dummy_init_out;
}
#if EMULATE_SPI_CHIP
if (!strcmp(tmp, "M25P10.RES")) {
@@ -180,13 +197,14 @@ int dummy_init(void)
msg_perr("Out of memory!\n");
return 1;
}
+
msg_pdbg("Filling fake flash chip with 0xff, size %i\n", emu_chip_size);
memset(flashchip_contents, 0xff, emu_chip_size);
emu_persistent_image = extract_programmer_param("image");
if (!emu_persistent_image) {
/* Nothing else to do. */
- return 0;
+ goto dummy_init_out;
}
if (!stat(emu_persistent_image, &image_stat)) {
msg_pdbg("Found persistent image %s, size %li ",
@@ -201,22 +219,12 @@ int dummy_init(void)
}
}
#endif
- return 0;
-}
-int dummy_shutdown(void)
-{
- msg_pspew("%s\n", __func__);
-#if EMULATE_CHIP
- if (emu_chip != EMULATE_NONE) {
- if (emu_persistent_image) {
- msg_pdbg("Writing %s\n", emu_persistent_image);
- write_buf_to_file(flashchip_contents, emu_chip_size,
- emu_persistent_image);
- }
+dummy_init_out:
+ if (register_shutdown(dummy_shutdown, NULL)) {
free(flashchip_contents);
+ return 1;
}
-#endif
return 0;
}
diff --git a/flash.h b/flash.h
index ec248d9..f875102 100644
--- a/flash.h
+++ b/flash.h
@@ -40,7 +40,7 @@
typedef unsigned long chipaddr;
-int register_shutdown(void (*function) (void *data), void *data);
+int register_shutdown(int (*function) (void *data), void *data);
void *programmer_map_flash_region(const char *descr, unsigned long phys_addr,
size_t len);
void programmer_unmap_flash_region(void *virt_addr, size_t len);
diff --git a/flashrom.c b/flashrom.c
index e9e6a77..663b56b 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -129,7 +129,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "internal",
.init = internal_init,
- .shutdown = internal_shutdown,
.map_flash_region = physmap,
.unmap_flash_region = physunmap,
.chip_readb = internal_chip_readb,
@@ -148,7 +147,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "dummy",
.init = dummy_init,
- .shutdown = dummy_shutdown,
.map_flash_region = dummy_map,
.unmap_flash_region = dummy_unmap,
.chip_readb = dummy_chip_readb,
@@ -167,7 +165,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "nic3com",
.init = nic3com_init,
- .shutdown = nic3com_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = nic3com_chip_readb,
@@ -188,7 +185,6 @@ const struct programmer_entry programmer_table[] = {
.name = "nicrealtek",
//.name = "nicsmc1211",
.init = nicrealtek_init,
- .shutdown = nicrealtek_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = nicrealtek_chip_readb,
@@ -207,7 +203,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "nicnatsemi",
.init = nicnatsemi_init,
- .shutdown = nicnatsemi_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = nicnatsemi_chip_readb,
@@ -226,7 +221,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "gfxnvidia",
.init = gfxnvidia_init,
- .shutdown = gfxnvidia_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = gfxnvidia_chip_readb,
@@ -245,7 +239,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "drkaiser",
.init = drkaiser_init,
- .shutdown = drkaiser_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = drkaiser_chip_readb,
@@ -264,7 +257,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "satasii",
.init = satasii_init,
- .shutdown = satasii_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = satasii_chip_readb,
@@ -283,7 +275,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "atahpt",
.init = atahpt_init,
- .shutdown = atahpt_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = atahpt_chip_readb,
@@ -302,7 +293,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "ft2232_spi",
.init = ft2232_spi_init,
- .shutdown = noop_shutdown, /* Missing shutdown */
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = noop_chip_readb,
@@ -321,7 +311,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "serprog",
.init = serprog_init,
- .shutdown = serprog_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = serprog_chip_readb,
@@ -340,7 +329,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "buspirate_spi",
.init = buspirate_spi_init,
- .shutdown = buspirate_spi_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = noop_chip_readb,
@@ -359,7 +347,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "dediprog",
.init = dediprog_init,
- .shutdown = dediprog_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = noop_chip_readb,
@@ -378,7 +365,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "rayer_spi",
.init = rayer_spi_init,
- .shutdown = noop_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = noop_chip_readb,
@@ -397,7 +383,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "nicintel",
.init = nicintel_init,
- .shutdown = nicintel_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = nicintel_chip_readb,
@@ -416,7 +401,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "nicintel_spi",
.init = nicintel_spi_init,
- .shutdown = nicintel_spi_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = noop_chip_readb,
@@ -435,7 +419,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "ogp_spi",
.init = ogp_spi_init,
- .shutdown = ogp_spi_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = noop_chip_readb,
@@ -454,7 +437,6 @@ const struct programmer_entry programmer_table[] = {
{
.name = "satamv",
.init = satamv_init,
- .shutdown = satamv_shutdown,
.map_flash_region = fallback_map,
.unmap_flash_region = fallback_unmap,
.chip_readb = satamv_chip_readb,
@@ -475,7 +457,7 @@ const struct programmer_entry programmer_table[] = {
#define SHUTDOWN_MAXFN 32
static int shutdown_fn_count = 0;
struct shutdown_func_data {
- void (*func) (void *data);
+ int (*func) (void *data);
void *data;
} static shutdown_fn[SHUTDOWN_MAXFN];
/* Initialize to 0 to make sure nobody registers a shutdown function before
@@ -491,7 +473,7 @@ static int may_register_shutdown = 0;
* Please note that the first (void *data) belongs to the function signature of
* the function passed as first parameter.
*/
-int register_shutdown(void (*function) (void *data), void *data)
+int register_shutdown(int (*function) (void *data), void *data)
{
if (shutdown_fn_count >= SHUTDOWN_MAXFN) {
msg_perr("Tried to register more than %i shutdown functions.\n",
@@ -543,13 +525,15 @@ int programmer_init(char *param)
int programmer_shutdown(void)
{
+ int ret = 0;
+
/* Registering shutdown functions is no longer allowed. */
may_register_shutdown = 0;
while (shutdown_fn_count > 0) {
int i = --shutdown_fn_count;
- shutdown_fn[i].func(shutdown_fn[i].data);
+ ret |= shutdown_fn[i].func(shutdown_fn[i].data);
}
- return programmer_table[programmer].shutdown();
+ return ret;
}
void *programmer_map_flash_region(const char *descr, unsigned long phys_addr,
diff --git a/gfxnvidia.c b/gfxnvidia.c
index 60498b1..3f67c72 100644
--- a/gfxnvidia.c
+++ b/gfxnvidia.c
@@ -29,6 +29,7 @@
* FIXME: Is this size a one-fits-all or card dependent?
*/
#define GFXNVIDIA_MEMMAP_MASK ((1 << 17) - 1)
+#define GFXNVIDIA_MEMMAP_SIZE (16 * 1024 * 1024)
uint8_t *nvidia_bar;
@@ -60,6 +61,17 @@ const struct pcidev_status gfx_nvidia[] = {
{},
};
+static int gfxnvidia_shutdown(void *data)
+{
+ physunmap(nvidia_bar, GFXNVIDIA_MEMMAP_SIZE);
+ /* Flash interface access is disabled (and screen enabled) automatically
+ * by PCI restore.
+ */
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+}
+
int gfxnvidia_init(void)
{
uint32_t reg32;
@@ -71,13 +83,17 @@ int gfxnvidia_init(void)
io_base_addr += 0x300000;
msg_pinfo("Detected NVIDIA I/O base address: 0x%x.\n", io_base_addr);
+ nvidia_bar = physmap("NVIDIA", io_base_addr, GFXNVIDIA_MEMMAP_SIZE);
+
+ /* must be done before rpci calls */
+ if (register_shutdown(gfxnvidia_shutdown, NULL))
+ return 1;
+
/* Allow access to flash interface (will disable screen). */
reg32 = pci_read_long(pcidev_dev, 0x50);
reg32 &= ~(1 << 0);
rpci_write_long(pcidev_dev, 0x50, reg32);
- nvidia_bar = physmap("NVIDIA", io_base_addr, 16 * 1024 * 1024);
-
buses_supported = CHIP_BUSTYPE_PARALLEL;
/* Write/erase doesn't work. */
@@ -86,16 +102,6 @@ int gfxnvidia_init(void)
return 0;
}
-int gfxnvidia_shutdown(void)
-{
- /* Flash interface access is disabled (and screen enabled) automatically
- * by PCI restore.
- */
- pci_cleanup(pacc);
- release_io_perms();
- return 0;
-}
-
void gfxnvidia_chip_writeb(uint8_t val, chipaddr addr)
{
pci_mmio_writeb(val, nvidia_bar + (addr & GFXNVIDIA_MEMMAP_MASK));
diff --git a/hwaccess.c b/hwaccess.c
index 3c4f07a..efe8bb0 100644
--- a/hwaccess.c
+++ b/hwaccess.c
@@ -202,7 +202,7 @@ struct undo_mmio_write_data {
};
};
-void undo_mmio_write(void *p)
+int undo_mmio_write(void *p)
{
struct undo_mmio_write_data *data = p;
msg_pdbg("Restoring MMIO space at %p\n", data->addr);
@@ -219,6 +219,7 @@ void undo_mmio_write(void *p)
}
/* p was allocated in register_undo_mmio_write. */
free(p);
+ return 0;
}
#define register_undo_mmio_write(a, c) \
diff --git a/internal.c b/internal.c
index c9f62c1..32bfb3a 100644
--- a/internal.c
+++ b/internal.c
@@ -127,6 +127,12 @@ int register_superio(struct superio s)
int is_laptop = 0;
int laptop_ok = 0;
+static int internal_shutdown(void *data)
+{
+ release_io_perms();
+ return 0;
+}
+
int internal_init(void)
{
#if __FLASHROM_LITTLE_ENDIAN__
@@ -178,6 +184,8 @@ int internal_init(void)
free(arg);
get_io_perms();
+ if (register_shutdown(internal_shutdown, NULL))
+ return 1;
/* Default to Parallel/LPC/FWH flash devices. If a known host controller
* is found, the init routine sets the buses_supported bitfield.
@@ -287,13 +295,6 @@ int internal_init(void)
return 1;
#endif
}
-
-int internal_shutdown(void)
-{
- release_io_perms();
-
- return 0;
-}
#endif
void internal_chip_writeb(uint8_t val, chipaddr addr)
diff --git a/it85spi.c b/it85spi.c
index c6c945b..d4ca13b 100644
--- a/it85spi.c
+++ b/it85spi.c
@@ -226,6 +226,14 @@ void it85xx_exit_scratch_rom()
#endif
}
+static int it85xx_shutdown(void *data)
+{
+ msg_pdbg("%s():%d\n", __func__, __LINE__);
+ it85xx_exit_scratch_rom();
+
+ return 0; /* FIXME: Should probably return something meaningful */
+}
+
static int it85xx_spi_common_init(struct superio s)
{
chipaddr base;
@@ -233,6 +241,9 @@ static int it85xx_spi_common_init(struct superio s)
msg_pdbg("%s():%d superio.vendor=0x%02x\n", __func__, __LINE__,
s.vendor);
+ if (register_shutdown(it85xx_shutdown, NULL))
+ return 1;
+
#ifdef LPC_IO
/* Get LPCPNP of SHM. That's big-endian */
sio_write(s.port, LDNSEL, 0x0F); /* Set LDN to SHM (0x0F) */
@@ -300,13 +311,6 @@ int it85xx_spi_init(struct superio s)
return ret;
}
-int it85xx_shutdown(void)
-{
- msg_pdbg("%s():%d\n", __func__, __LINE__);
- it85xx_exit_scratch_rom();
- return 0;
-}
-
/* According to ITE 8502 document, the procedure to follow mode is following:
* 1. write 0x00 to LPC/FWH address 0xffff_fexxh (drive CE# high)
* 2. write data to LPC/FWH address 0xffff_fdxxh (drive CE# low and MOSI
diff --git a/nic3com.c b/nic3com.c
index d39ee71..bcc63e0 100644
--- a/nic3com.c
+++ b/nic3com.c
@@ -55,6 +55,21 @@ const struct pcidev_status nics_3com[] = {
{},
};
+static int nic3com_shutdown(void *data)
+{
+ /* 3COM 3C90xB cards need a special fixup. */
+ if (id == 0x9055 || id == 0x9001 || id == 0x9004 || id == 0x9005
+ || id == 0x9006 || id == 0x900a || id == 0x905a || id == 0x9058) {
+ /* Select register window 3 and restore the receiver status. */
+ OUTW(SELECT_REG_WINDOW + 3, io_base_addr + INT_STATUS);
+ OUTL(internal_conf, io_base_addr + INTERNAL_CONFIG);
+ }
+
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+}
+
int nic3com_init(void)
{
get_io_perms();
@@ -84,21 +99,8 @@ int nic3com_init(void)
buses_supported = CHIP_BUSTYPE_PARALLEL;
max_rom_decode.parallel = 128 * 1024;
- return 0;
-}
-
-int nic3com_shutdown(void)
-{
- /* 3COM 3C90xB cards need a special fixup. */
- if (id == 0x9055 || id == 0x9001 || id == 0x9004 || id == 0x9005
- || id == 0x9006 || id == 0x900a || id == 0x905a || id == 0x9058) {
- /* Select register window 3 and restore the receiver status. */
- OUTW(SELECT_REG_WINDOW + 3, io_base_addr + INT_STATUS);
- OUTL(internal_conf, io_base_addr + INTERNAL_CONFIG);
- }
-
- pci_cleanup(pacc);
- release_io_perms();
+ if (register_shutdown(nic3com_shutdown, NULL))
+ return 1;
return 0;
}
diff --git a/nicintel.c b/nicintel.c
index 3d53ec8..2e6e46a 100644
--- a/nicintel.c
+++ b/nicintel.c
@@ -39,8 +39,19 @@ const struct pcidev_status nics_intel[] = {
#define NICINTEL_MEMMAP_SIZE (128 * 1024)
#define NICINTEL_MEMMAP_MASK (NICINTEL_MEMMAP_SIZE - 1)
+#define NICINTEL_CONTROL_MEMMAP_SIZE 0x10
+
#define CSR_FCR 0x0c
+static int nicintel_shutdown(void *data)
+{
+ physunmap(nicintel_control_bar, NICINTEL_CONTROL_MEMMAP_SIZE);
+ physunmap(nicintel_bar, NICINTEL_MEMMAP_SIZE);
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+}
+
int nicintel_init(void)
{
uintptr_t addr;
@@ -58,15 +69,19 @@ int nicintel_init(void)
nicintel_bar = physmap("Intel NIC flash", addr, NICINTEL_MEMMAP_SIZE);
if (nicintel_bar == ERROR_PTR)
- goto error_out;
+ goto error_out_unmap;
/* FIXME: Using pcidev_dev _will_ cause pretty explosions in the future. */
addr = pcidev_validate(pcidev_dev, PCI_BASE_ADDRESS_0, nics_intel);
/* FIXME: This is not an aligned mapping. Use 4k? */
- nicintel_control_bar = physmap("Intel NIC control/status reg", addr, 0x10);
+ nicintel_control_bar = physmap("Intel NIC control/status reg",
+ addr, NICINTEL_CONTROL_MEMMAP_SIZE);
if (nicintel_control_bar == ERROR_PTR)
goto error_out;
+ if (register_shutdown(nicintel_shutdown, NULL))
+ return 1;
+
/* FIXME: This register is pretty undocumented in all publicly available
* documentation from Intel. Let me quote the complete info we have:
* "Flash Control Register: The Flash Control register allows the CPU to
@@ -84,20 +99,14 @@ int nicintel_init(void)
return 0;
+error_out_unmap:
+ physunmap(nicintel_bar, NICINTEL_MEMMAP_SIZE);
error_out:
pci_cleanup(pacc);
release_io_perms();
return 1;
}
-int nicintel_shutdown(void)
-{
- physunmap(nicintel_bar, NICINTEL_MEMMAP_SIZE);
- pci_cleanup(pacc);
- release_io_perms();
- return 0;
-}
-
void nicintel_chip_writeb(uint8_t val, chipaddr addr)
{
pci_mmio_writeb(val, nicintel_bar + (addr & NICINTEL_MEMMAP_MASK));
diff --git a/nicintel_spi.c b/nicintel_spi.c
index 574735f..aacd68c 100644
--- a/nicintel_spi.c
+++ b/nicintel_spi.c
@@ -139,6 +139,25 @@ static const struct bitbang_spi_master bitbang_spi_master_nicintel = {
.release_bus = nicintel_release_spibus,
};
+static int nicintel_spi_shutdown(void *data)
+{
+ uint32_t tmp;
+
+ /* Disable writes manually. See the comment about EECD in
+ * nicintel_spi_init() for details.
+ */
+ tmp = pci_mmio_readl(nicintel_spibar + EECD);
+ tmp &= ~FLASH_WRITES_ENABLED;
+ tmp |= FLASH_WRITES_DISABLED;
+ pci_mmio_writel(tmp, nicintel_spibar + EECD);
+
+ physunmap(nicintel_spibar, 4096);
+ pci_cleanup(pacc);
+ release_io_perms();
+
+ return 0;
+}
+
int nicintel_spi_init(void)
{
uint32_t tmp;
@@ -159,28 +178,12 @@ int nicintel_spi_init(void)
tmp |= FLASH_WRITES_ENABLED;
pci_mmio_writel(tmp, nicintel_spibar + EECD);
+ if (register_shutdown(nicintel_spi_shutdown, NULL))
+ return 1;
+
/* 1 usec halfperiod delay for now. */
if (bitbang_spi_init(&bitbang_spi_master_nicintel, 1))
return 1;
return 0;
}
-
-int nicintel_spi_shutdown(void)
-{
- uint32_t tmp;
-
- /* Disable writes manually. See the comment about EECD in
- * nicintel_spi_init() for details.
- */
- tmp = pci_mmio_readl(nicintel_spibar + EECD);
- tmp &= ~FLASH_WRITES_ENABLED;
- tmp |= FLASH_WRITES_DISABLED;
- pci_mmio_writel(tmp, nicintel_spibar + EECD);
-
- physunmap(nicintel_spibar, 4096);
- pci_cleanup(pacc);
- release_io_perms();
-
- return 0;
-}
diff --git a/nicnatsemi.c b/nicnatsemi.c
index 3cae253..ac37cf0 100644
--- a/nicnatsemi.c
+++ b/nicnatsemi.c
@@ -35,6 +35,13 @@ const struct pcidev_status nics_natsemi[] = {
{},
};
+static int nicnatsemi_shutdown(void *data)
+{
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+}
+
int nicnatsemi_init(void)
{
get_io_perms();
@@ -51,13 +58,8 @@ int nicnatsemi_init(void)
*/
max_rom_decode.parallel = 131072;
- return 0;
-}
-
-int nicnatsemi_shutdown(void)
-{
- pci_cleanup(pacc);
- release_io_perms();
+ if (register_shutdown(nicnatsemi_shutdown, NULL))
+ return 1;
return 0;
}
diff --git a/nicrealtek.c b/nicrealtek.c
index d97deb1..4566e50 100644
--- a/nicrealtek.c
+++ b/nicrealtek.c
@@ -36,6 +36,14 @@ const struct pcidev_status nics_realtek[] = {
{},
};
+static int nicrealtek_shutdown(void *data)
+{
+ /* FIXME: We forgot to disable software access again. */
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+}
+
int nicrealtek_init(void)
{
get_io_perms();
@@ -44,14 +52,8 @@ int nicrealtek_init(void)
buses_supported = CHIP_BUSTYPE_PARALLEL;
- return 0;
-}
-
-int nicrealtek_shutdown(void)
-{
- /* FIXME: We forgot to disable software access again. */
- pci_cleanup(pacc);
- release_io_perms();
+ if (register_shutdown(nicrealtek_shutdown, NULL))
+ return 1;
return 0;
}
diff --git a/ogp_spi.c b/ogp_spi.c
index 2916ae1..dbaa57a 100644
--- a/ogp_spi.c
+++ b/ogp_spi.c
@@ -93,6 +93,15 @@ static const struct bitbang_spi_master bitbang_spi_master_ogp = {
.release_bus = ogp_release_spibus,
};
+static int ogp_spi_shutdown(void *data)
+{
+ physunmap(ogp_spibar, 4096);
+ pci_cleanup(pacc);
+ release_io_perms();
+
+ return 0;
+}
+
int ogp_spi_init(void)
{
char *type;
@@ -124,18 +133,12 @@ int ogp_spi_init(void)
ogp_spibar = physmap("OGP registers", io_base_addr, 4096);
+ if (register_shutdown(ogp_spi_shutdown, NULL))
+ return 1;
+
/* no delay for now. */
if (bitbang_spi_init(&bitbang_spi_master_ogp, 0))
return 1;
return 0;
}
-
-int ogp_spi_shutdown(void)
-{
- physunmap(ogp_spibar, 4096);
- pci_cleanup(pacc);
- release_io_perms();
-
- return 0;
-}
diff --git a/pcidev.c b/pcidev.c
index e498014..1f9a5cc 100644
--- a/pcidev.c
+++ b/pcidev.c
@@ -270,7 +270,7 @@ struct undo_pci_write_data {
};
};
-void undo_pci_write(void *p)
+int undo_pci_write(void *p)
{
struct undo_pci_write_data *data = p;
msg_pdbg("Restoring PCI config space for %02x:%02x:%01x reg 0x%02x\n",
@@ -288,6 +288,7 @@ void undo_pci_write(void *p)
}
/* p was allocated in register_undo_pci_write. */
free(p);
+ return 0;
}
#define register_undo_pci_write(a, b, c) \
diff --git a/programmer.h b/programmer.h
index 83cf5e1..ce0ffa1 100644
--- a/programmer.h
+++ b/programmer.h
@@ -89,7 +89,6 @@ struct programmer_entry {
const char *name;
int (*init) (void);
- int (*shutdown) (void);
void * (*map_flash_region) (const char *descr, unsigned long phys_addr,
size_t len);
@@ -305,7 +304,6 @@ extern int force_boardmismatch;
void probe_superio(void);
int register_superio(struct superio s);
int internal_init(void);
-int internal_shutdown(void);
void internal_chip_writeb(uint8_t val, chipaddr addr);
void internal_chip_writew(uint16_t val, chipaddr addr);
void internal_chip_writel(uint32_t val, chipaddr addr);
@@ -363,7 +361,6 @@ void fallback_chip_readn(uint8_t *buf, const chipaddr addr, size_t len);
/* dummyflasher.c */
#if CONFIG_DUMMY == 1
int dummy_init(void);
-int dummy_shutdown(void);
void *dummy_map(const char *descr, unsigned long phys_addr, size_t len);
void dummy_unmap(void *virt_addr, size_t len);
void dummy_chip_writeb(uint8_t val, chipaddr addr);
@@ -379,7 +376,6 @@ void dummy_chip_readn(uint8_t *buf, const chipaddr addr, size_t len);
/* nic3com.c */
#if CONFIG_NIC3COM == 1
int nic3com_init(void);
-int nic3com_shutdown(void);
void nic3com_chip_writeb(uint8_t val, chipaddr addr);
uint8_t nic3com_chip_readb(const chipaddr addr);
extern const struct pcidev_status nics_3com[];
@@ -388,7 +384,6 @@ extern const struct pcidev_status nics_3com[];
/* gfxnvidia.c */
#if CONFIG_GFXNVIDIA == 1
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 const struct pcidev_status gfx_nvidia[];
@@ -397,7 +392,6 @@ extern const struct pcidev_status gfx_nvidia[];
/* drkaiser.c */
#if CONFIG_DRKAISER == 1
int drkaiser_init(void);
-int drkaiser_shutdown(void);
void drkaiser_chip_writeb(uint8_t val, chipaddr addr);
uint8_t drkaiser_chip_readb(const chipaddr addr);
extern const struct pcidev_status drkaiser_pcidev[];
@@ -406,7 +400,6 @@ extern const struct pcidev_status drkaiser_pcidev[];
/* nicrealtek.c */
#if CONFIG_NICREALTEK == 1
int nicrealtek_init(void);
-int nicrealtek_shutdown(void);
void nicrealtek_chip_writeb(uint8_t val, chipaddr addr);
uint8_t nicrealtek_chip_readb(const chipaddr addr);
extern const struct pcidev_status nics_realtek[];
@@ -415,7 +408,6 @@ extern const struct pcidev_status nics_realtek[];
/* nicnatsemi.c */
#if CONFIG_NICNATSEMI == 1
int nicnatsemi_init(void);
-int nicnatsemi_shutdown(void);
void nicnatsemi_chip_writeb(uint8_t val, chipaddr addr);
uint8_t nicnatsemi_chip_readb(const chipaddr addr);
extern const struct pcidev_status nics_natsemi[];
@@ -424,7 +416,6 @@ extern const struct pcidev_status nics_natsemi[];
/* nicintel.c */
#if CONFIG_NICINTEL == 1
int nicintel_init(void);
-int nicintel_shutdown(void);
void nicintel_chip_writeb(uint8_t val, chipaddr addr);
uint8_t nicintel_chip_readb(const chipaddr addr);
extern const struct pcidev_status nics_intel[];
@@ -433,7 +424,6 @@ extern const struct pcidev_status nics_intel[];
/* nicintel_spi.c */
#if CONFIG_NICINTEL_SPI == 1
int nicintel_spi_init(void);
-int nicintel_spi_shutdown(void);
int nicintel_spi_send_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
void nicintel_spi_chip_writeb(uint8_t val, chipaddr addr);
@@ -443,14 +433,12 @@ extern const struct pcidev_status nics_intel_spi[];
/* ogp_spi.c */
#if CONFIG_OGP_SPI == 1
int ogp_spi_init(void);
-int ogp_spi_shutdown(void);
extern const struct pcidev_status ogp_spi[];
#endif
/* satamv.c */
#if CONFIG_SATAMV == 1
int satamv_init(void);
-int satamv_shutdown(void);
void satamv_chip_writeb(uint8_t val, chipaddr addr);
uint8_t satamv_chip_readb(const chipaddr addr);
extern const struct pcidev_status satas_mv[];
@@ -459,7 +447,6 @@ extern const struct pcidev_status satas_mv[];
/* satasii.c */
#if CONFIG_SATASII == 1
int satasii_init(void);
-int satasii_shutdown(void);
void satasii_chip_writeb(uint8_t val, chipaddr addr);
uint8_t satasii_chip_readb(const chipaddr addr);
extern const struct pcidev_status satas_sii[];
@@ -468,7 +455,6 @@ extern const struct pcidev_status satas_sii[];
/* atahpt.c */
#if CONFIG_ATAHPT == 1
int atahpt_init(void);
-int atahpt_shutdown(void);
void atahpt_chip_writeb(uint8_t val, chipaddr addr);
uint8_t atahpt_chip_readb(const chipaddr addr);
extern const struct pcidev_status ata_hpt[];
@@ -500,13 +486,11 @@ int bitbang_spi_shutdown(const struct bitbang_spi_master *master);
/* buspirate_spi.c */
#if CONFIG_BUSPIRATE_SPI == 1
int buspirate_spi_init(void);
-int buspirate_spi_shutdown(void);
#endif
/* dediprog.c */
#if CONFIG_DEDIPROG == 1
int dediprog_init(void);
-int dediprog_shutdown(void);
#endif
/* flashrom.c */
@@ -591,7 +575,6 @@ int via_init_spi(struct pci_dev *dev);
/* it85spi.c */
int it85xx_spi_init(struct superio s);
-int it85xx_shutdown(void);
/* it87spi.c */
void enter_conf_mode_ite(uint16_t port);
@@ -612,7 +595,6 @@ int wbsio_check_for_spi(void);
/* serprog.c */
#if CONFIG_SERPROG == 1
int serprog_init(void);
-int serprog_shutdown(void);
void serprog_chip_writeb(uint8_t val, chipaddr addr);
uint8_t serprog_chip_readb(const chipaddr addr);
void serprog_chip_readn(uint8_t *buf, const chipaddr addr, size_t len);
@@ -630,7 +612,8 @@ void sp_flush_incoming(void);
fdtype sp_openserport(char *dev, unsigned int baud);
void __attribute__((noreturn)) sp_die(char *msg);
extern fdtype sp_fd;
-int serialport_shutdown(void);
+/* expose serialport_shutdown as it's currently used by buspirate */
+int serialport_shutdown(void *data);
int serialport_write(unsigned char *buf, unsigned int writecnt);
int serialport_read(unsigned char *buf, unsigned int readcnt);
diff --git a/satamv.c b/satamv.c
index 0c0dace..01919d0 100644
--- a/satamv.c
+++ b/satamv.c
@@ -40,6 +40,14 @@ const struct pcidev_status satas_mv[] = {
#define PCI_BAR2_CONTROL 0x00c08
#define GPIO_PORT_CONTROL 0x104f0
+static int satamv_shutdown(void *data)
+{
+ physunmap(mv_bar, 0x20000);
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+}
+
/*
* Random notes:
* FCE# Flash Chip Enable
@@ -73,6 +81,9 @@ int satamv_init(void)
if (mv_bar == ERROR_PTR)
goto error_out;
+ if (register_shutdown(satamv_shutdown, NULL))
+ return 1;
+
tmp = pci_mmio_readl(mv_bar + FLASH_PARAM);
msg_pspew("Flash Parameters:\n");
msg_pspew("TurnOff=0x%01x\n", (tmp >> 0) & 0x7);
@@ -139,14 +150,6 @@ error_out:
return 1;
}
-int satamv_shutdown(void)
-{
- physunmap(mv_bar, 0x20000);
- pci_cleanup(pacc);
- release_io_perms();
- return 0;
-}
-
/* BAR2 (MEM) can map NVRAM and flash. We set it to flash in the init function.
* If BAR2 is disabled, it still can be accessed indirectly via BAR1 (I/O).
* This code only supports indirect accesses for now.
diff --git a/satasii.c b/satasii.c
index 9d05b2d..dbc4f4f 100644
--- a/satasii.c
+++ b/satasii.c
@@ -26,6 +26,8 @@
#define PCI_VENDOR_ID_SII 0x1095
+#define SATASII_MEMMAP_SIZE 0x100
+
uint8_t *sii_bar;
static uint16_t id;
@@ -40,6 +42,14 @@ const struct pcidev_status satas_sii[] = {
{},
};
+static int satasii_shutdown(void *data)
+{
+ physunmap(sii_bar, SATASII_MEMMAP_SIZE);
+ pci_cleanup(pacc);
+ release_io_perms();
+ return 0;
+}
+
int satasii_init(void)
{
uint32_t addr;
@@ -59,7 +69,8 @@ int satasii_init(void)
reg_offset = 0x50;
}
- sii_bar = physmap("SATA SIL registers", addr, 0x100) + reg_offset;
+ sii_bar = physmap("SATA SIL registers", addr, SATASII_MEMMAP_SIZE) +
+ reg_offset;
/* Check if ROM cycle are OK. */
if ((id != 0x0680) && (!(pci_mmio_readl(sii_bar) & (1 << 26))))
@@ -67,13 +78,8 @@ int satasii_init(void)
buses_supported = CHIP_BUSTYPE_PARALLEL;
- return 0;
-}
-
-int satasii_shutdown(void)
-{
- pci_cleanup(pacc);
- release_io_perms();
+ if (register_shutdown(satasii_shutdown, NULL))
+ return 1;
return 0;
}
diff --git a/serial.c b/serial.c
index a04a138..37ea422 100644
--- a/serial.c
+++ b/serial.c
@@ -180,7 +180,7 @@ void sp_flush_incoming(void)
return;
}
-int serialport_shutdown(void)
+int serialport_shutdown(void *data)
{
#ifdef _WIN32
CloseHandle(sp_fd);
diff --git a/serprog.c b/serprog.c
index f869b07..b91e376 100644
--- a/serprog.c
+++ b/serprog.c
@@ -39,6 +39,13 @@
#define MSGHEADER "serprog:"
+/*
+ * FIXME: This prototype was added to help reduce diffs for the shutdown
+ * registration patch, which shifted many lines of code to place
+ * serprog_shutdown() before serprog_init(). It should be removed soon.
+ */
+static int serprog_shutdown(void *data);
+
#define S_ACK 0x06
#define S_NAK 0x15
#define S_CMD_NOP 0x00 /* No operation */
@@ -373,6 +380,9 @@ int serprog_init(void)
return 1;
}
+ if (register_shutdown(serprog_shutdown, NULL))
+ return 1;
+
msg_pdbg(MSGHEADER "connected - attempting to synchronize\n");
sp_check_avail_automatic = 0;
@@ -555,7 +565,7 @@ static void sp_execute_opbuf(void)
sp_flush_stream();
}
-int serprog_shutdown(void)
+static int serprog_shutdown(void *data)
{
msg_pspew("%s\n", __func__);
if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes))
OpenPOWER on IntegriCloud