Subject: [PATCH] chipset_enable: enable the ATI SB200 flash programming gate

Enable port 0xc6f bit 6 and restore its original value at shutdown.
The sequence is present in the ASUS P4R8L BIOS.
Tested on ASUS Pundit-R / P4R8L with an SST49LF004B: program a scratch
area, erase its 4 KiB sector, and verify restoration of the whole chip.

--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -1660,6 +1660,41 @@
 	return 0;
 }
 
+static int disable_flash_sb200(void *data)
+{
+	uint8_t saved = *(uint8_t *)data;
+	free(data);
+	OUTB(saved, 0xc6f);
+	msg_pdbg("Restoring SB200 flash gate 0xc6f to 0x%02x\n", saved);
+	return INB(0xc6f) != saved;
+}
+
+/* Sequence observed in the ASUS P4R8L 1006.004 flash enable/disable routines. */
+static int enable_flash_sb200(const struct programmer_cfg *cfg, struct pci_dev *dev, const char *name)
+{
+	uint8_t *saved = malloc(sizeof(*saved));
+	if (!saved)
+		return ERROR_FLASHROM_FATAL;
+
+	*saved = INB(0xc6f);
+	if (*saved == 0xff) {
+		msg_perr("SB200 flash program control port is not decoded.\n");
+		free(saved);
+		return ERROR_FLASHROM_FATAL;
+	}
+	if (register_shutdown(disable_flash_sb200, saved)) {
+		free(saved);
+		return ERROR_FLASHROM_FATAL;
+	}
+	OUTB(*saved | 0x40, 0xc6f);
+	msg_pdbg("SB200 flash gate 0xc6f: 0x%02x -> 0x%02x\n", *saved, INB(0xc6f));
+	if (!(INB(0xc6f) & 0x40)) {
+		msg_perr("SB200 flash program enable did not latch.\n");
+		return ERROR_FLASHROM_FATAL;
+	}
+	return 0;
+}
+
 /* ATI Technologies Inc IXP SB400 PCI-ISA Bridge (rev 80) */
 static int enable_flash_sb400(const struct programmer_cfg *cfg, struct pci_dev *dev, const char *name)
 {
@@ -1855,6 +1890,7 @@
 /* Please keep this list numerically sorted by vendor/device ID. */
 const struct penable chipset_enables[] = {
 #if defined(__i386__) || defined(__x86_64__)
+	{0x1002, 0x434c, B_FL,   OK,  "ATI", "SB200",				enable_flash_sb200},
 	{0x1002, 0x4377, B_PFL,  OK,  "ATI", "SB400",				enable_flash_sb400},
 	{0x1002, 0x438d, B_FLS,  OK,  "AMD", "SB600",				enable_flash_sb600},
 	{0x1002, 0x439d, B_FLS,  OK,  "AMD", "SB7x0/SB8x0/SB9x0",		enable_flash_sb600},
