[flashrom] [PATCH] Add support for every single SiS chipset out there

Carl-Daniel Hailfinger c-d.hailfinger.devel.2006 at gmx.net
Sat Nov 14 16:25:39 CET 2009


Add support for every single SiS chipset out there.
The two existing SiS chipset enables (compared to the 28 in this patch)
were refactored, and one of them was fixed.

A function to match PCI vendor/class combinations was added to generic code.

Untested. This is not based on any docs, but rather on detailed analysis
of existing opensource code for some of the chipsets.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>

Index: flashrom-sis_all/flash.h
===================================================================
--- flashrom-sis_all/flash.h	(Revision 758)
+++ flashrom-sis_all/flash.h	(Arbeitskopie)
@@ -389,6 +389,7 @@
 
 /* internal.c */
 struct pci_dev *pci_dev_find_filter(struct pci_filter filter);
+struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class);
 struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device);
 struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
 			      uint16_t card_vendor, uint16_t card_device);
Index: flashrom-sis_all/chipset_enable.c
===================================================================
--- flashrom-sis_all/chipset_enable.c	(Revision 758)
+++ flashrom-sis_all/chipset_enable.c	(Arbeitskopie)
@@ -70,54 +70,190 @@
 	return 0;
 }
 
+static int enable_flash_sis85c496(struct pci_dev *dev, const char *name)
+{
+	uint8_t tmp;
+
+	tmp = pci_read_byte(dev, 0xd0);
+	tmp |= 0xf8;
+	pci_write_byte(dev, 0xd0, tmp);
+
+	return 0;
+}
+
+static int enable_flash_sis_mapping(struct pci_dev *dev, const char *name)
+{
+	uint8_t new, newer;
+
+	/* Extended BIOS enable = 1, Lower BIOS Enable = 1 */
+	/* This is 0xFFF8000~0xFFFF0000 decoding on SiS 540/630. */
+	new = pci_read_byte(dev, 0x40);
+	new &= (~0x04); /* No idea why we clear bit 2. */
+	new |= 0xb; /* 0x3 for some chipsets, bit 7 seems to be don't care. */
+	pci_write_byte(dev, 0x40, new);
+	newer = pci_read_byte(dev, 0x40);
+	if (newer != new) {
+		printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x40, new, name);
+		printf_debug("Stuck at 0x%x\n", newer);
+		return -1;
+	}
+	return 0;
+}
+
+static struct pci_dev *find_southbridge(uint16_t vendor, const char *name)
+{
+	struct pci_dev *sbdev;
+	
+	sbdev = pci_dev_find_vendorclass(vendor, 0x0601);
+	if (!sbdev)
+		sbdev = pci_dev_find_vendorclass(vendor, 0x0680);
+	if (!sbdev)
+		sbdev = pci_dev_find_vendorclass(vendor, 0x0000);
+	if (!sbdev)
+		fprintf(stderr, "No southbridge found for %s!\n", name);
+
+	return sbdev;
+}
+
+static int enable_flash_sis501(struct pci_dev *dev, const char *name)
+{
+	uint8_t tmp;
+	int ret = 0;
+	struct pci_dev *sbdev;
+
+	sbdev = find_southbridge(dev->vendor_id, name);
+	if (!sbdev)
+		return -1;
+
+	ret = enable_flash_sis_mapping(sbdev, name);
+
+	tmp = sio_read(0x22, 0x80);
+	tmp &= (~0x20);
+	tmp |= 0x4;
+	sio_write(0x22, 0x80, tmp);
+
+	tmp = sio_read(0x22, 0x70);
+	tmp &= (~0x20);
+	tmp |= 0x4;
+	sio_write(0x22, 0x70, tmp);
+	
+	return ret;
+}
+
+static int enable_flash_sis5511(struct pci_dev *dev, const char *name)
+{
+	uint8_t tmp;
+	int ret = 0;
+	struct pci_dev *sbdev;
+
+	sbdev = find_southbridge(dev->vendor_id, name);
+	if (!sbdev)
+		return -1;
+
+	ret = enable_flash_sis_mapping(sbdev, name);
+
+	tmp = sio_read(0x22, 0x50);
+	tmp &= (~0x20);
+	tmp |= 0x4;
+	sio_write(0x22, 0x50, tmp);
+
+	return ret;
+}
+
+static int enable_flash_sis5596(struct pci_dev *dev, const char *name)
+{
+	int ret;
+
+	ret = enable_flash_sis5511(dev, name);
+
+	/* FIXME: Needs same superio handling as enable_flash_sis630 */
+	return ret;
+}
+
+static int enable_flash_sis530(struct pci_dev *dev, const char *name)
+{
+	uint8_t new, newer;
+	int ret = 0;
+	struct pci_dev *sbdev;
+
+	sbdev = find_southbridge(dev->vendor_id, name);
+	if (!sbdev)
+		return -1;
+
+	ret = enable_flash_sis_mapping(sbdev, name);
+
+	new = pci_read_byte(sbdev, 0x45);
+	new &= (~0x20);
+	new |= 0x4;
+	pci_write_byte(sbdev, 0x45, new);
+	newer = pci_read_byte(dev, 0x45);
+	if (newer != new) {
+		printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x45, new, name);
+		printf_debug("Stuck at 0x%x\n", newer);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+static int enable_flash_sis540(struct pci_dev *dev, const char *name)
+{
+	uint8_t new, newer;
+	int ret = 0;
+	struct pci_dev *sbdev;
+
+	sbdev = find_southbridge(dev->vendor_id, name);
+	if (!sbdev)
+		return -1;
+
+	ret = enable_flash_sis_mapping(sbdev, name);
+
+	new = pci_read_byte(sbdev, 0x45);
+	new &= (~0x80);
+	new |= 0x40;
+	pci_write_byte(sbdev, 0x45, new);
+	newer = pci_read_byte(dev, 0x45);
+	if (newer != new) {
+		printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x45, new, name);
+		printf_debug("Stuck at 0x%x\n", newer);
+		ret = -1;
+	}
+
+	return ret;
+}
+
 static int enable_flash_sis630(struct pci_dev *dev, const char *name)
 {
-	uint8_t b;
+	uint8_t tmp;
+	uint16_t siobase;
+	int ret;
 
-	/* Enable 0xFFF8000~0xFFFF0000 decoding on SiS 540/630. */
-	b = pci_read_byte(dev, 0x40);
-	pci_write_byte(dev, 0x40, b | 0xb);
+	ret = enable_flash_sis540(dev, name);
 
-	/* Flash write enable on SiS 540/630. */
-	b = pci_read_byte(dev, 0x45);
-	pci_write_byte(dev, 0x45, b | 0x40);
-
 	/* The same thing on SiS 950 Super I/O side... */
 
 	/* First probe for Super I/O on config port 0x2e. */
-	OUTB(0x87, 0x2e);
-	OUTB(0x01, 0x2e);
-	OUTB(0x55, 0x2e);
-	OUTB(0x55, 0x2e);
+	siobase = 0x2e;
+	enter_conf_mode_ite(siobase);
 
-	if (INB(0x2f) != 0x87) {
+	if (INB(siobase + 1) != 0x87) {
 		/* If that failed, try config port 0x4e. */
-		OUTB(0x87, 0x4e);
-		OUTB(0x01, 0x4e);
-		OUTB(0x55, 0x4e);
-		OUTB(0xaa, 0x4e);
-		if (INB(0x4f) != 0x87) {
-			printf("Can not access SiS 950\n");
+		siobase = 0x4e;
+		enter_conf_mode_ite(siobase);
+		if (INB(siobase + 1) != 0x87) {
+			printf("Can not find SuperI/O.\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_debug("2f is %#x\n", INB(0x2f));
-	b = INB(0x2f) | 0xfc;
-	OUTB(0x24, 0x2e);
-	OUTB(b, 0x2f);
+	/* Enable flash mapping. Works for most old ITE style SuperI/O. */
+	tmp = sio_read(siobase, 0x24);
+	tmp |= 0xfc;
+	sio_write(siobase, 0x24, tmp);
 
-	OUTB(0x02, 0x2e);
-	OUTB(0x02, 0x2f);
+	exit_conf_mode_ite(siobase);
 
-	return 0;
+	return ret;
 }
 
 /* Datasheet:
@@ -603,38 +739,6 @@
 	return 0;
 }
 
-static int enable_flash_sis5595(struct pci_dev *dev, const char *name)
-{
-	uint8_t new, newer;
-
-	new = pci_read_byte(dev, 0x45);
-
-	new &= (~0x20);		/* Clear bit 5. */
-	new |= 0x4;		/* Set bit 2. */
-
-	pci_write_byte(dev, 0x45, new);
-
-	newer = pci_read_byte(dev, 0x45);
-	if (newer != new) {
-		printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x45, new, name);
-		printf_debug("Stuck at 0x%x\n", newer);
-		return -1;
-	}
-
-	/* Extended BIOS enable = 1, Lower BIOS Enable = 1 */
-	new = pci_read_byte(dev, 0x40);
-	new &= 0xFB;
-	new |= 0x3;
-	pci_write_byte(dev, 0x40, new);
-	newer = pci_read_byte(dev, 0x40);
-	if (newer != new) {
-		printf_debug("tried to set register 0x%x to 0x%x on %s failed (WARNING ONLY)\n", 0x40, new, name);
-		printf_debug("Stuck at 0x%x\n", newer);
-		return -1;
-	}
-	return 0;
-}
-
 /* Works for AMD-8111, VIA VT82C586A/B, VIA VT82C686A/B. */
 static int enable_flash_amd8111(struct pci_dev *dev, const char *name)
 {
@@ -1048,8 +1152,34 @@
 	{0x10de, 0x0366, OK, "NVIDIA", "MCP55",		enable_flash_mcp55}, /* LPC */
 	{0x10de, 0x0367, OK, "NVIDIA", "MCP55",		enable_flash_mcp55}, /* Pro */
 	{0x10de, 0x0548, OK, "NVIDIA", "MCP67",		enable_flash_mcp55},
-	{0x1039, 0x0008, OK, "SiS", "SiS5595",		enable_flash_sis5595},
-	{0x1039, 0x0630, NT, "SiS", "SiS630",		enable_flash_sis630},
+	{0x1039, 0x0496, NT, "SiS", "SiS 85C496+497",	enable_flash_sis85c496},
+	{0x1039, 0x0406, NT, "SiS", "SiS 501/5101/5501", enable_flash_sis501},
+	{0x1039, 0x5511, NT, "SiS", "SiS 5511",		enable_flash_sis5511},
+	{0x1039, 0x5596, NT, "SiS", "SiS 5596",		enable_flash_sis5596},
+	{0x1039, 0x5571, NT, "SiS", "SiS 5571",		enable_flash_sis530},
+	{0x1039, 0x5591, NT, "SiS", "SiS 5591/5592",	enable_flash_sis530},
+	{0x1039, 0x5597, NT, "SiS", "SiS 5597/5598/5581/5120", enable_flash_sis530},
+	{0x1039, 0x0530, NT, "SiS", "SiS 530",		enable_flash_sis530},
+	{0x1039, 0x5600, NT, "SiS", "SiS 600",		enable_flash_sis530},
+	{0x1039, 0x0620, NT, "SiS", "SiS 620",		enable_flash_sis530},
+	{0x1039, 0x0540, NT, "SiS", "SiS 540",		enable_flash_sis540},
+	{0x1039, 0x0630, NT, "SiS", "SiS 630",		enable_flash_sis630},
+	{0x1039, 0x0635, NT, "SiS", "SiS 635",		enable_flash_sis630},
+	{0x1039, 0x0640, NT, "SiS", "SiS 640",		enable_flash_sis630},
+	{0x1039, 0x0645, NT, "SiS", "SiS 645",		enable_flash_sis630},
+	{0x1039, 0x0646, NT, "SiS", "SiS 645DX",	enable_flash_sis630},
+	{0x1039, 0x0648, NT, "SiS", "SiS 648",		enable_flash_sis630},
+	{0x1039, 0x0650, NT, "SiS", "SiS 650",		enable_flash_sis630},
+	{0x1039, 0x0651, NT, "SiS", "SiS 651",		enable_flash_sis630},
+	{0x1039, 0x0655, NT, "SiS", "SiS 655",		enable_flash_sis630},
+	{0x1039, 0x0730, NT, "SiS", "SiS 730",		enable_flash_sis630},
+	{0x1039, 0x0733, NT, "SiS", "SiS 733",		enable_flash_sis630},
+	{0x1039, 0x0735, NT, "SiS", "SiS 735",		enable_flash_sis630},
+	{0x1039, 0x0740, NT, "SiS", "SiS 740",		enable_flash_sis630},
+	{0x1039, 0x0745, NT, "SiS", "SiS 745",		enable_flash_sis630},
+	{0x1039, 0x0746, NT, "SiS", "SiS 746",		enable_flash_sis630},
+	{0x1039, 0x0748, NT, "SiS", "SiS 748",		enable_flash_sis630},
+	{0x1039, 0x0755, NT, "SiS", "SiS 755",		enable_flash_sis630},
 	{0x1106, 0x8324, OK, "VIA", "CX700",		enable_flash_vt823x},
 	{0x1106, 0x8231, NT, "VIA", "VT8231",		enable_flash_vt823x},
 	{0x1106, 0x3074, NT, "VIA", "VT8233",		enable_flash_vt823x},
Index: flashrom-sis_all/internal.c
===================================================================
--- flashrom-sis_all/internal.c	(Revision 758)
+++ flashrom-sis_all/internal.c	(Arbeitskopie)
@@ -42,6 +42,26 @@
 	return NULL;
 }
 
+struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t class)
+{
+	struct pci_dev *temp;
+	struct pci_filter filter;
+	uint16_t tmp2;
+
+	pci_filter_init(NULL, &filter);
+	filter.vendor = vendor;
+
+	for (temp = pacc->devices; temp; temp = temp->next)
+		if (pci_filter_match(&filter, temp)) {
+			/* Read PCI class */
+			tmp2 = pci_read_word(temp, 0x0a);
+			if (tmp2 == class)
+				return temp;
+		}
+
+	return NULL;
+}
+
 struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
 {
 	struct pci_dev *temp;


-- 
Developer quote of the week: 
"We are juggling too many chainsaws and flaming arrows and tigers."





More information about the flashrom mailing list