From 363bdddf694863339f6629340cfb324771b8ffe7 Mon Sep 17 00:00:00 2001 From: wpaul Date: Fri, 9 Feb 2001 00:45:29 +0000 Subject: [PATCH] Apply patch to add support for the intergrated ethernet in the SiS630E chipset. The MAC address is stored in the APC CMOS RAM and we have to commit trememdous evil in order to read it. The code to do this is only activated on the i386 platform. Thanks to Cameron Grant for providing access to a test box for me to tinker with. This will fix the problem where the sis driver ends up with a station address of 00:00:00:00:00:00 on boards that use the 630E chipset. --- sys/pci/if_sis.c | 99 ++++++++++++++++++++++++++++++++++++++++++++- sys/pci/if_sisreg.h | 7 ++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/sys/pci/if_sis.c b/sys/pci/if_sis.c index ce4b09706a20..b5b96cea6847 100644 --- a/sys/pci/if_sis.c +++ b/sys/pci/if_sis.c @@ -142,6 +142,12 @@ static void sis_eeprom_putbyte __P((struct sis_softc *, int)); static void sis_eeprom_getword __P((struct sis_softc *, int, u_int16_t *)); static void sis_read_eeprom __P((struct sis_softc *, caddr_t, int, int, int)); +#ifdef __i386__ +static void sis_read_cmos __P((struct sis_softc *, device_t, caddr_t, + int, int)); +static device_t sis_find_bridge __P((device_t)); +#endif + static int sis_miibus_readreg __P((device_t, int, int)); static int sis_miibus_writereg __P((device_t, int, int, int)); static void sis_miibus_statchg __P((device_t)); @@ -359,6 +365,73 @@ static void sis_read_eeprom(sc, dest, off, cnt, swap) return; } +#ifdef __i386__ +static device_t sis_find_bridge(dev) + device_t dev; +{ + devclass_t pci_devclass; + device_t *pci_devices; + int pci_count = 0; + device_t *pci_children; + int pci_childcount = 0; + device_t *busp, *childp; + int i, j; + + if ((pci_devclass = devclass_find("pci")) == NULL) + return(NULL); + + devclass_get_devices(pci_devclass, &pci_devices, &pci_count); + + for (i = 0, busp = pci_devices; i < pci_count; i++, busp++) { + pci_childcount = 0; + device_get_children(*busp, &pci_children, &pci_childcount); + for (j = 0, childp = pci_children; + j < pci_childcount; j++, childp++) { + if (pci_get_vendor(*childp) == SIS_VENDORID && + pci_get_device(*childp) == 0x0008) { + free(pci_devices, M_TEMP); + free(pci_children, M_TEMP); + return(*childp); + } + } + } + + free(pci_devices, M_TEMP); + free(pci_children, M_TEMP); + return(NULL); +} + +static void sis_read_cmos(sc, dev, dest, off, cnt) + struct sis_softc *sc; + device_t dev; + caddr_t dest; + int off; + int cnt; +{ + device_t bridge; + u_int8_t reg; + int i; + bus_space_tag_t btag; + + bridge = sis_find_bridge(dev); + if (bridge == NULL) + return; + reg = pci_read_config(bridge, 0x48, 1); + pci_write_config(bridge, 0x48, reg|0x40, 1); + + /* XXX */ + btag = I386_BUS_SPACE_IO; + + for (i = 0; i < cnt; i++) { + bus_space_write_1(btag, 0x0, 0x70, i + off); + *(dest + i) = bus_space_read_1(btag, 0x0, 0x71); + } + + pci_write_config(bridge, 0x48, reg & ~0x40, 1); + return; +} +#endif + static int sis_miibus_readreg(dev, phy, reg) device_t dev; int phy, reg; @@ -776,7 +849,31 @@ static int sis_attach(dev) break; case SIS_VENDORID: default: - sis_read_eeprom(sc, (caddr_t)&eaddr, SIS_EE_NODEADDR, 3, 0); +#ifdef __i386__ + /* + * If this is a SiS 630E chipset with an embedded + * SiS 900 controller, we have to read the MAC address + * from the APC CMOS RAM. Our method for doing this + * is very ugly since we have to reach out and grab + * ahold of hardware for which we cannot properly + * allocate resources. This code is only compiled on + * the i386 architecture since the SiS 630E chipset + * is for x86 motherboards only. Note that there are + * a lot of magic numbers in this hack. These are + * taken from SiS's Linux driver. I'd like to replace + * them with proper symbolic definitions, but that + * requires some datasheets that I don't have access + * to at the moment. + */ + command = pci_read_config(dev, PCIR_REVID, 1); + if (command == SIS_REV_630S || + command == SIS_REV_630E || + command == SIS_REV_630EA1) + sis_read_cmos(sc, dev, (caddr_t)&eaddr, 0x9, 6); + else +#endif + sis_read_eeprom(sc, (caddr_t)&eaddr, + SIS_EE_NODEADDR, 3, 0); break; } diff --git a/sys/pci/if_sisreg.h b/sys/pci/if_sisreg.h index d1781b7a0429..96bbd6d0da89 100644 --- a/sys/pci/if_sisreg.h +++ b/sys/pci/if_sisreg.h @@ -355,6 +355,13 @@ struct sis_ring_data { #define SIS_DEVICEID_900 0x0900 #define SIS_DEVICEID_7016 0x7016 +/* + * SiS 900 PCI revision codes. + */ +#define SIS_REV_630E 0x0081 +#define SIS_REV_630S 0x0082 +#define SIS_REV_630EA1 0x0083 + /* * NatSemi vendor ID */