Subject: kern/35438: uGuru 2005 support
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <kefren@netbsd.ro>
List: netbsd-bugs
Date: 01/17/2007 18:00:01
>Number:         35438
>Category:       kern
>Synopsis:       patch for uGuru 2005 support
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed Jan 17 18:00:01 +0000 2007
>Originator:     Mihai Chelaru
>Release:        NetBSD 4.0_BETA2
>Organization:
	
>Environment:
	
	
System: NetBSD kefren64.netbsd.ro 4.0_BETA2 NetBSD 4.0_BETA2 (Kefren.MPACPI) #0: Wed Jan 17 18:55:42 EET 2007 root@kefren64.netbsd.ro:/usr/src/sys/arch/amd64/compile/Kefren.MPACPI amd64
Architecture: x86_64
Machine: amd64
>Description:
	
	Because my old Abit AX8 broke and I'm using temporary an Abit AL8 mainboard, 
	I was surprised to find out that post 2005 Abit uGuru have
	a different sensor firmware. So different that the two weeks ago submitted driver is not
	usable. Anyway, more details on http://forum.abit-usa.com/showthread.php?t=80051

	So, here is a patch that works on my Abit AL8. It's mostly inspired by
	linux driver.
>How-To-Repeat:
	
~$ dmesg | grep ^ug
ug0 at isa0 port 0xe0-0xe7: Abit uGuru 2005 system monitor
ug0: mainboard Abit AL8 (000E)
~$ envstat -r
         CPU Core:      1.240 V
              DDR:      1.830 V
          DDR VTT:      0.910 V
     CPU VTT 1.2V:      1.230 V
  MCH & PCIE 1.5V:      1.530 V
         MCH 2.5V:      2.580 V
        ICH 1.05V:      1.030 V
ATX +12V (24-Pin):     12.240 V
 ATX +12V (4-pin):     12.180 V
          ATX +5V:      5.130 V
            +3.3V:      3.340 V
             5VSB:      5.040 V
              CPU:     51.000 degC
           System:     34.000 degC
              PWM:     43.000 degC
          CPU Fan:       1380 RPM
           NB Fan:       4680 RPM
          SYS Fan:       1140 RPM
~$
>Fix:
	
Index: sys/dev/isa/ug.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/ug.c,v
retrieving revision 1.1.4.1
diff -u -r1.1.4.1 ug.c
--- sys/dev/isa/ug.c	12 Jan 2007 23:16:49 -0000	1.1.4.1
+++ sys/dev/isa/ug.c	17 Jan 2007 17:32:07 -0000
@@ -28,6 +28,7 @@
 /*
  * Driver for Abit uGuru (interface is inspired from it.c and nslm7x.c)
  * Inspired by olle sandberg linux driver as Abit didn't care to release docs
+ * Support for uGuru 2005 from Louis Kruger and Hans de Goede linux driver
  */
 
 #include <sys/cdefs.h>
@@ -53,6 +54,7 @@
 #include <dev/sysmon/sysmonvar.h>
 
 #include <dev/isa/ugvar.h>
+#include <dev/isa/ugvar2.h>
 
 /* autoconf(9) functions */
 static int  ug_isa_match(struct device *, struct cfdata *, void *);
@@ -66,15 +68,24 @@
 uint8_t ug_read(struct ug_softc *, unsigned short);
 int ug_waitfor(struct ug_softc *, uint16_t, uint8_t);
 void ug_setup_sensors(struct ug_softc*);
+void ug2_attach(struct ug_softc*);
+int ug2_wait_ready(struct ug_softc*);
+int ug2_wait_readable(struct ug_softc*);
+int ug2_sync(struct ug_softc*);
+int ug2_read(struct ug_softc*, uint8_t, uint8_t, uint8_t, uint8_t*);
 
 /* envsys(9) glue */
 static int ug_gtredata(struct sysmon_envsys *, envsys_tre_data_t *);
-static int ug_streinfo(struct sysmon_envsys *, envsys_basic_info_t *);
+static int ug2_gtredata(struct sysmon_envsys *, envsys_tre_data_t *);
+static int ug_streinfo_ni(struct sysmon_envsys *, envsys_basic_info_t *);
+
+static uint8_t ug_ver;
 
 static int
 ug_isa_match(struct device *parent, struct cfdata *match, void *aux)
 {
 	struct isa_attach_args *ia = aux;
+	struct ug_softc wrap_sc;
 	bus_space_handle_t bsh;
 	uint8_t valc, vald;
 
@@ -93,9 +104,25 @@
 	valc = bus_space_read_1(ia->ia_iot, bsh, UG_CMD);
 	vald = bus_space_read_1(ia->ia_iot, bsh, UG_DATA);
 
+	ug_ver = 0;
+
+	/* Check for uGuru 2003 */
+
+	if (((vald == 0) || (vald == 8)) && (valc == 0xAC))
+		ug_ver = 1;
+
+	/* Check for uGuru 2005 */
+
+	wrap_sc.sc_iot = ia->ia_iot;
+	wrap_sc.sc_ioh = bsh;
+
+	if (ug2_sync(&wrap_sc) == 1)
+		ug_ver = 2;
+
+	/* unmap, prepare ia and bye */
 	bus_space_unmap(ia->ia_iot, bsh, 8);
 
-	if (((vald == 0) || (vald == 8)) && (valc == 0xAC)) {
+	if (ug_ver != 0) {
 		ia->ia_nio = 1;
 		ia->ia_io[0].ir_size = 8;
 		ia->ia_niomem = 0;
@@ -105,6 +132,7 @@
 	}
 
 	return 0;
+
 }
 
 static void
@@ -121,6 +149,12 @@
 	}
 
 	ia->ia_iot = sc->sc_iot;
+	sc->version = ug_ver;
+
+	if (sc->version == 2) {
+		ug2_attach(sc);
+		return;
+	}
 
 	aprint_normal(": Abit uGuru system monitor\n");
 
@@ -141,13 +175,13 @@
 	sc->sc_sysmon.sme_sensor_data = sc->sc_data;
 	sc->sc_sysmon.sme_cookie = sc;
 	sc->sc_sysmon.sme_gtredata = ug_gtredata;
-	sc->sc_sysmon.sme_streinfo = ug_streinfo;
+	sc->sc_sysmon.sme_streinfo = ug_streinfo_ni;
 	sc->sc_sysmon.sme_nsensors = UG_NUM_SENSORS;
-	sc->sc_sysmon.sme_envsys_version = 1000;
+	sc->sc_sysmon.sme_envsys_version = UG_DRV_VERSION;
 	sc->sc_sysmon.sme_flags = 0;
 
 	if (sysmon_envsys_register(&sc->sc_sysmon))
-		printf("%s: unable to register with sysmon\n",
+		aprint_error("%s: unable to register with sysmon\n",
 		    sc->sc_dev.dv_xname);
 
 }
@@ -272,7 +306,7 @@
 	struct ug_softc *sc = sme->sme_cookie;
 	envsys_tre_data_t *t = sc->sc_data;	/* For easier read */
 
-	/* Sensors returns C while we need uK */
+	/* Sensors return C while we need uK */
 	t[0].cur.data_us = ug_read(sc, UG_CPUTEMP) * 1000000 + 273150000;
 	t[1].cur.data_us = ug_read(sc, UG_SYSTEMP) * 1000000 + 273150000;
 	t[2].cur.data_us = ug_read(sc, UG_PWMTEMP) * 1000000 + 273150000;
@@ -302,10 +336,221 @@
 }
 
 static int
-ug_streinfo(struct sysmon_envsys *sme, envsys_basic_info_t *binfo)
+ug_streinfo_ni(struct sysmon_envsys *sme, envsys_basic_info_t *binfo)
 {
 	/* not implemented */
 	binfo->validflags = 0;
 
 	return 0;
 }
+
+void
+ug2_attach(struct ug_softc *sc)
+{
+	uint8_t buf[2];
+	int i, i2;
+	struct ug2_motherboard_info *ai;
+	struct ug2_sensor_info *si;
+	struct envsys_range ug2_ranges[7];	/* XXX: why only 7 ?! */
+
+	aprint_normal(": Abit uGuru 2005 system monitor\n");
+
+	bcopy(ug_ranges, ug2_ranges, 7 * sizeof(struct envsys_range));
+	for(i = 0; i < 7; i++)
+		ug2_ranges[i].low = ug2_ranges[i].high = 0xFF;
+
+	if (ug2_read(sc, UG2_MISC_BANK, UG2_BOARD_ID, 2, buf) != 2) {
+		aprint_error("%s: Cannot detect board ID. Using default\n",
+			sc->sc_dev.dv_xname);
+		buf[0] = UG_MAX_MSB_BOARD;
+		buf[1] = UG_MAX_LSB_BOARD;
+	}
+
+	if (buf[0] > UG_MAX_MSB_BOARD || buf[1] > UG_MAX_LSB_BOARD ||
+		buf[1] < UG_MIN_LSB_BOARD) {
+		aprint_error("%s: Invalid board ID(%X,%X). Using default\n",
+			sc->sc_dev.dv_xname, buf[0], buf[1]);
+		buf[0] = UG_MAX_MSB_BOARD;
+		buf[1] = UG_MAX_LSB_BOARD;
+	}
+
+	ai = &ug2_mb[buf[1] - UG_MIN_LSB_BOARD];
+
+	aprint_normal("%s: mainboard %s (%.2X%.2X)\n", sc->sc_dev.dv_xname,
+	    ai->name, buf[0], buf[1]);
+
+#define COPYDESCR(x, y)				\
+	do {					\
+		strlcpy((x), (y), sizeof(x));	\
+	} while (0)
+
+	sc->mbsens = (void*)ai->sensors;
+
+	for (i = 0, si = ai->sensors; si && si->name; si++, i++) {
+		COPYDESCR(sc->sc_info[i].desc, si->name);
+		sc->sc_data[i].sensor = sc->sc_info[i].sensor = i;
+		sc->sc_data[i].validflags = (ENVSYS_FVALID|ENVSYS_FCURVALID);
+		sc->sc_info[i].validflags = ENVSYS_FVALID;
+		sc->sc_data[i].warnflags = ENVSYS_WARN_OK;
+		sc->sc_info[i].rfact = 1;
+		switch(si->type) {
+			case UG2_VOLTAGE_SENSOR:
+				sc->sc_data[i].units = sc->sc_info[i].units = 
+					ENVSYS_SVOLTS_DC;
+				sc->sc_info[i].rfact = UG_RFACT;
+				ug2_ranges[3].high = i;
+				if (ug2_ranges[3].low == 0xFF)
+					ug2_ranges[3].low = i;
+				break;
+			case UG2_TEMP_SENSOR:
+				sc->sc_data[i].units = sc->sc_info[i].units =
+					ENVSYS_STEMP;
+				ug2_ranges[0].high = i;
+				if (ug2_ranges[0].low == 0xFF)
+					ug2_ranges[0].low = i;
+				break;
+			case UG2_FAN_SENSOR:
+				sc->sc_data[i].units = sc->sc_info[i].units =
+					ENVSYS_SFANRPM;
+				ug2_ranges[1].high = i;
+				if (ug2_ranges[0].low == 0xFF)
+					ug2_ranges[0].low = i;
+		}
+	}
+#undef COPYDESCR
+
+	for (i2 = 0; i2 < 7; i2++)
+		if (ug2_ranges[i2].low == 0xFF ||
+		    ug2_ranges[i2].high == 0xFF) {
+			ug2_ranges[i2].low = 1;
+			ug2_ranges[i2].high = 0;
+		}
+
+	sc->sc_sysmon.sme_ranges = ug2_ranges;
+	sc->sc_sysmon.sme_sensor_info = sc->sc_info;
+	sc->sc_sysmon.sme_sensor_data = sc->sc_data;
+	sc->sc_sysmon.sme_cookie = sc;
+	sc->sc_sysmon.sme_gtredata = ug2_gtredata;
+	sc->sc_sysmon.sme_streinfo = ug_streinfo_ni;
+	sc->sc_sysmon.sme_nsensors = i;
+	sc->sc_sysmon.sme_envsys_version = UG_DRV_VERSION;
+	sc->sc_sysmon.sme_flags = 0;
+
+	if (sysmon_envsys_register(&sc->sc_sysmon))
+		aprint_error("%s: unable to register with sysmon\n",
+		    sc->sc_dev.dv_xname);
+}
+
+static int
+ug2_gtredata(struct sysmon_envsys *sme, envsys_tre_data_t *tred)
+{
+	struct ug_softc *sc = sme->sme_cookie;
+	envsys_tre_data_t *t = sc->sc_data;	/* makes code readable */
+	struct ug2_sensor_info *si = (struct ug2_sensor_info*)sc->mbsens;
+	int i, rfact;
+	uint8_t v;
+
+#define SENSOR_VALUE ( v * si->multiplier * rfact / si->divisor + si->offset )
+
+	for (i = 0; i< sc->sc_sysmon.sme_nsensors; i++, si++)
+		if (ug2_read(sc, UG2_SENSORS_BANK, UG2_VALUES_OFFSET +
+		    si->port, 1, &v) == 1)
+			switch (si->type) {
+			case UG2_TEMP_SENSOR:
+			    rfact = 1;
+			    t[i].cur.data_us = SENSOR_VALUE * 1000000 + 273150000;
+			    break;
+			case UG2_VOLTAGE_SENSOR:
+			    rfact = UG_RFACT;
+			    t[i].cur.data_us = SENSOR_VALUE;
+			    break;
+			default:
+			    rfact = 1;
+			    t[i].cur.data_s = SENSOR_VALUE;
+			}
+#undef SENSOR_VALUE
+	*tred = sc->sc_data[tred->sensor];
+	return 0;
+}
+
+int
+ug2_wait_ready(struct ug_softc *sc)
+{
+	int cnt = 0;
+
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, 0x1a);
+	while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_DATA) & UG2_STATUS_BUSY) {
+		if (cnt++ > UG_DELAY_CYCLES)
+			return 0;
+	}
+	return 1;
+}
+
+int
+ug2_wait_readable(struct ug_softc *sc)
+{
+	int cnt = 0;
+
+	while (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_DATA) &
+		UG2_STATUS_READY_FOR_READ)) {
+		if (cnt++ > UG_DELAY_CYCLES)
+			return 0;
+	}
+	return 1;
+}
+
+int
+ug2_sync(struct ug_softc *sc)
+{
+	int cnt = 0;
+
+#define UG2_WAIT_READY if(ug2_wait_ready(sc) == 0) return 0;
+
+	/* Don't sync two times in a row */
+	if(ug_ver != 0) {
+		ug_ver = 0;
+		return 1;
+	}
+
+	UG2_WAIT_READY;
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, 0x20);
+	UG2_WAIT_READY;
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, 0x10);
+	UG2_WAIT_READY;
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, 0x00);
+	UG2_WAIT_READY;
+	if(ug2_wait_readable(sc) == 0)
+		return 0;
+	while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_CMD) != 0xAC)
+		if (cnt++ > UG_DELAY_CYCLES)
+			return 0;
+	return 1;
+}
+
+int
+ug2_read(struct ug_softc *sc, uint8_t bank, uint8_t offset, uint8_t count, uint8_t *ret)
+{
+	int i;
+
+	if(ug2_sync(sc) == 0)
+		return 0;
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_DATA, 0x1A);
+	UG2_WAIT_READY;
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, bank);
+	UG2_WAIT_READY;
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, offset);
+	UG2_WAIT_READY;
+	bus_space_write_1(sc->sc_iot, sc->sc_ioh, UG_CMD, count);
+	UG2_WAIT_READY;
+
+#undef UG2_WAIT_READY
+
+	/* Now wait for the results */
+	for (i = 0; i<count; i++) {
+		if(ug2_wait_readable(sc) == 0)
+			break;
+		ret[i] = bus_space_read_1(sc->sc_iot, sc->sc_ioh, UG_CMD);
+	}
+
+	return i;
+}
Index: sys/dev/isa/ugvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/ugvar.h,v
retrieving revision 1.1.4.1
diff -u -r1.1.4.1 ugvar.h
--- sys/dev/isa/ugvar.h	12 Jan 2007 23:16:49 -0000	1.1.4.1
+++ sys/dev/isa/ugvar.h	17 Jan 2007 17:32:07 -0000
@@ -28,8 +28,11 @@
 #ifndef _DEV_ISA_UGVAR_H
 #define _DEV_ISA_UGVAR_H
 
-#define UG_DELAY_CYCLES	50000
+#define UG_DRV_VERSION	1000
+
+#define UG_DELAY_CYCLES	5000
 #define UG_NUM_SENSORS	19
+#define UG_MAX_SENSORS	32
 
 /* Data and Cmd offsets - Base is ussualy 0xE0 */
 #define UG_CMD		0
@@ -67,7 +70,6 @@
 
 /*
  * sc->sensors sub-intervals for each unit type.
- * XXX: is this correct ?
  */
 static const struct envsys_range ug_ranges[] = {
 	{ 0,	2,	ENVSYS_STEMP },
@@ -86,9 +88,10 @@
 	bus_space_handle_t sc_ioh;
 
 	struct sysmon_envsys sc_sysmon;
-	envsys_tre_data_t sc_data[UG_NUM_SENSORS];
-	envsys_basic_info_t sc_info[UG_NUM_SENSORS];
-
+	envsys_tre_data_t sc_data[UG_MAX_SENSORS];
+	envsys_basic_info_t sc_info[UG_MAX_SENSORS];
+	uint8_t version;
+	void *mbsens;
 };
 
 #endif /* _DEV_ISA_UGVAR_H_ */
Index: sys/dev/isa/ugvar2.h
===================================================================
RCS file: sys/dev/isa/ugvar2.h
diff -N sys/dev/isa/ugvar2.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/dev/isa/ugvar2.h	17 Jan 2007 17:32:07 -0000
@@ -0,0 +1,346 @@
+/*     $NetBSD */
+
+/*
+ * Copyright (c) 2007 Mihai Chelaru <kefren@netbsd.ro>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_ISA_UGVAR2_H
+#define _DEV_ISA_UGVAR2_H
+
+/*
+ * Abit uGuru2 or uGuru 2005 settings
+ */ 
+
+/* Sensor banks */
+#define UG2_SETTINGS_BANK		0x01
+#define UG2_SENSORS_BANK		0x08
+#define UG2_MISC_BANK			0x09
+
+/* Sensor offsets */
+#define UG2_ALARMS_OFFSET		0x1E
+#define UG2_SETTINGS_OFFSET		0x24
+#define UG2_VALUES_OFFSET		0x80
+
+/* Misc Sensor */
+#define UG2_BOARD_ID			0x0A
+
+/* sensor types */
+#define UG2_VOLTAGE_SENSOR			0
+#define UG2_TEMP_SENSOR				1
+#define UG2_FAN_SENSOR				2
+
+/* uGuru status flags */
+#define UG2_STATUS_READY_FOR_READ	0x01
+#define UG2_STATUS_BUSY			0x02
+/* No more than 32 sensors */
+#define UG2_MAX_NO_SENSORS 32
+
+struct ug2_sensor_info {
+	const char* name;
+	int port;
+	int type;
+	int multiplier;
+	int divisor;
+	int offset;
+};
+
+struct ug2_motherboard_info {
+	uint16_t id;
+	const char *name;
+	struct ug2_sensor_info sensors[UG2_MAX_NO_SENSORS + 1];
+};
+
+
+/* Unknown board should be the last. Now is 0x0016 */
+#define UG_MAX_MSB_BOARD 0x00
+#define UG_MAX_LSB_BOARD 0x16
+#define UG_MIN_LSB_BOARD 0x0c
+
+/*
+ * Imported from linux driver
+ */
+
+struct ug2_motherboard_info ug2_mb[] = {
+	{ 0x000C, "unknown. Please send-pr(1)", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 10, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V", 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "System", 25, 1, 1, 1, 0 },
+		{ "PWM", 26, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS FAN", 34, 2, 60, 1, 0 },
+		{ "AUX1 Fan", 35, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x000D, "Abit AW8", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 10, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V", 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "System", 25, 1, 1, 1, 0 },
+		{ "PWM1", 26, 1, 1, 1, 0 },
+		{ "PWM2", 27, 1, 1, 1, 0 },
+		{ "PWM3", 28, 1, 1, 1, 0 },
+		{ "PWM4", 29, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS Fan", 34, 2, 60, 1, 0 },
+		{ "AUX1 Fan", 35, 2, 60, 1, 0 },
+		{ "AUX2 Fan", 36, 2, 60, 1, 0 },
+		{ "AUX3 Fan", 37, 2, 60, 1, 0 },
+		{ "AUX4 Fan", 38, 2, 60, 1, 0 },
+		{ "AUX5 Fan", 39, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x000E, "Abit AL8", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 10, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V", 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "System", 25, 1, 1, 1, 0 },
+		{ "PWM", 26, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS Fan", 34, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x000F, "unknown. Please send-pr(1)", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 10, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V", 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "System", 25, 1, 1, 1, 0 },
+		{ "PWM", 26, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS Fan", 34, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0010, "Abit NI8 SLI GR", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 10, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
+		{ "NB 1.4V", 4, 0, 10, 1, 0 },
+		{ "SB 1.5V", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "SYS", 25, 1, 1, 1, 0 },
+		{ "PWM", 26, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS Fan", 34, 2, 60, 1, 0 },
+		{ "AUX1 Fan", 35, 2, 60, 1, 0 },
+		{ "OTES1 Fan", 36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0011, "Abit AT8 32X", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 20, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "CPU VDDA 2.5V", 6, 0, 20, 1, 0 },
+		{ "NB 1.8V", 4, 0, 10, 1, 0 },
+		{ "NB 1.8V Dual", 5, 0, 10, 1, 0 },
+		{ "HTV 1.2", 3, 0, 10, 1, 0 },
+		{ "PCIE 1.2V", 12, 0, 10, 1, 0 },
+		{ "NB 1.2V", 13, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "NB", 25, 1, 1, 1, 0 },
+		{ "System", 26, 1, 1, 1, 0 },
+		{ "PWM", 27, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS Fan", 34, 2, 60, 1, 0 },
+		{ "AUX1 Fan", 35, 2, 60, 1, 0 },
+		{ "AUX2 Fan", 36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0012, "unknown. Please send-pr(1)", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 20, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "HyperTransport", 3, 0, 10, 1, 0 },
+		{ "CPU VDDA 2.5V", 5, 0, 20, 1, 0 },
+		{ "NB", 4, 0, 10, 1, 0 },
+		{ "SB", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "SYS", 25, 1, 1, 1, 0 },
+		{ "PWM", 26, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS Fan", 34, 2, 60, 1, 0 },
+		{ "AUX1 Fan", 36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0013, "unknown. Please send-pr(1)", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 10, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V", 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "System", 25, 1, 1, 1, 0 },
+		{ "PWM1", 26, 1, 1, 1, 0 },
+		{ "PWM2", 27, 1, 1, 1, 0 },
+		{ "PWM3", 28, 1, 1, 1, 0 },
+		{ "PWM4", 29, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS Fan", 34, 2, 60, 1, 0 },
+		{ "AUX1 Fan", 35, 2, 60, 1, 0 },
+		{ "AUX2 Fan", 36, 2, 60, 1, 0 },
+		{ "AUX3 Fan", 37, 2, 60, 1, 0 },
+		{ "AUX4 Fan", 38, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0014, "Abit AB9 Pro", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 10, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V", 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "System", 25, 1, 1, 1, 0 },
+		{ "PWM", 26, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS Fan", 34, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0015, "unknown. Please send-pr(1)", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 20, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "HyperTransport", 3, 0, 10, 1, 0 },
+		{ "CPU VDDA 2.5V", 5, 0, 20, 1, 0 },
+		{ "NB", 4, 0, 10, 1, 0 },
+		{ "SB", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "SYS", 25, 1, 1, 1, 0 },
+		{ "PWM", 26, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS Fan", 34, 2, 60, 1, 0 },
+		{ "AUX1 Fan", 33, 2, 60, 1, 0 },
+		{ "AUX2 Fan", 35, 2, 60, 1, 0 },
+		{ "AUX3 Fan", 36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0016, "generic", {
+		{ "CPU Core", 0, 0, 10, 1, 0 },
+		{ "DDR", 1, 0, 20, 1, 0 },
+		{ "DDR VTT", 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V", 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V", 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V", 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)", 8, 0, 60, 1, 0 },
+		{ "ATX +5V", 9, 0, 30, 1, 0 },
+		{ "+3.3V", 10, 0, 20, 1, 0 },
+		{ "5VSB", 11, 0, 30, 1, 0 },
+		{ "CPU", 24, 1, 1, 1, 0 },
+		{ "System", 25, 1, 1, 1, 0 },
+		{ "PWM", 26, 1, 1, 1, 0 },
+		{ "CPU Fan", 32, 2, 60, 1, 0 },
+		{ "NB Fan", 33, 2, 60, 1, 0 },
+		{ "SYS FAN", 34, 2, 60, 1, 0 },
+		{ "AUX1 Fan", 35, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
+};
+
+#endif	/* _DEV_ISA_UGVAR2_H */

>Unformatted: