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@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;