Subject: kern/35367: [patch] Abit uGuru support
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <kefren@netbsd.ro>
List: netbsd-bugs
Date: 01/06/2007 17:40:00
>Number:         35367
>Category:       kern
>Synopsis:       driver for Abit uGuru hw monitor
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Jan 06 17:40:00 +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.ACPI) #26: Sat Jan 6 16:54:46 EET 2007 root@kefren64.netbsd.ro:/disk2/src/sys/arch/amd64/compile/Kefren.ACPI amd64
Architecture: x86_64
Machine: amd64
>Description:
	
	driver for reading values reported by Abit uGuru. This piece of hardware can
	be found on Abit motherboards like: AS8, AG8, [Fatal1ty]AN8[Sli,Ultra], AX8[-V], AV8

	it's my first driver, pls forgive any stupidity found :)

>How-To-Repeat:
	
$ envstat -r
 CPU Temp:     37.000 degC
 SYS Temp:     33.000 degC
 PWN Temp:     37.000 degC
    VCore:      1.081 V
   DDRVdd:      2.669 V
   DDRVtt:      1.341 V
    NBVdd:      1.588 V
    SBVdd:      2.299 V
    HTVdd:      1.218 V
   AGPVdd:      3.339 V
    Vdd5V:      5.123 V
   Vdd3V3:      3.317 V
  Vdd5VSB:      5.025 V
Vdd3VDual:      3.676 V
  CPU Fan:       2340 RPM
   NB Fan:          0 RPM
  SYS Fan:          0 RPM
AUX Fan 1:          0 RPM
AUX Fan 2:          0 RPM

	
>Fix:
	

add
ug0 at isa? port 0xe0
in kernel config and use the following patch:

--- src/sys/dev/isa/files.isa.old	2006-05-13 12:02:19.000000000 +0300
+++ src/sys/dev/isa/files.isa	2007-01-05 20:18:08.000000000 +0200
@@ -469,6 +469,11 @@
 attach	it at isa with it_isa
 file	dev/isa/it.c			it_isa
 
+# Abit uGuru hardware monitor
+device	ug: sysmon_envsys
+attach	ug at isa with ug_isa
+file	dev/isa/ug.c			ug_isa
+
 # ISDN devices
 attach	isic at isa with isic_isa
 file	dev/isa/isic_isa.c		isic_isa
--- src/sys/dev/isa/ug.c.old	1970-01-01 02:00:00.000000000 +0200
+++ src/sys/dev/isa/ug.c	2007-01-06 16:58:55.000000000 +0200
@@ -0,0 +1,339 @@
+/*	$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.
+ */
+
+/*
+ * 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
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
+#include <sys/conf.h>
+#include <sys/envsys.h>
+#include <sys/time.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+
+#include <dev/sysmon/sysmonvar.h>
+
+#include <dev/isa/ugvar.h>
+
+/* autoconf(9) functions */
+static int  ug_isa_match(struct device *, struct cfdata *, void *);
+static void ug_isa_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(ug_isa, sizeof(struct ug_softc),
+    ug_isa_match, ug_isa_attach, NULL, NULL);
+
+/* driver internal functions */
+int ug_reset(bus_space_tag_t, bus_space_handle_t);
+uint8_t ug_read(bus_space_tag_t, bus_space_handle_t, unsigned short);
+int ug_waitfor(bus_space_tag_t, bus_space_handle_t, uint16_t, uint8_t);
+void ug_setup_sensors(struct ug_softc*);
+
+/* envsys(9) glue */
+static int ug_gtredata(struct sysmon_envsys *, envsys_tre_data_t *);
+
+
+static int
+ug_isa_match(struct device *parent, struct cfdata *match,
+    void *aux)
+{
+	struct isa_attach_args *ia = aux;
+	bus_space_handle_t bsh;
+	uint8_t valc, vald;
+
+	if (ia->ia_nio < 1)	/* need base addr */
+		return 0;
+
+	if (ISA_DIRECT_CONFIG(ia))
+		return 0;
+
+	if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT)
+		return 0;
+
+	if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 8, 0, &bsh))
+		return 0;
+
+	valc = bus_space_read_1(ia->ia_iot, bsh, UG_CMD);
+	vald = bus_space_read_1(ia->ia_iot, bsh, UG_DATA);
+
+	bus_space_unmap(ia->ia_iot, bsh, 8);
+
+	if (((vald == 0) || (vald == 8)) && (valc == 0xAC)) {
+		ia->ia_nio = 1;
+		ia->ia_io[0].ir_size = 8;
+		ia->ia_niomem = 0;
+		ia->ia_nirq = 0;
+		ia->ia_ndrq = 0;
+		return 1;
+	}
+
+	return 0;
+}
+
+static void
+ug_isa_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct ug_softc *sc = (void *)self;
+	struct isa_attach_args *ia = aux;
+	bus_space_tag_t iot;
+	bus_space_handle_t ioh;
+	int i;
+
+	if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr,
+			8, 0, &sc->sc_ioh)) {
+		printf(": can't map i/o space\n");
+		return;
+	}
+
+	iot = ia->ia_iot = sc->sc_iot;
+	ioh = sc->sc_ioh;
+
+	printf(": Abit uGuru system monitor\n");
+
+	if (!ug_reset(iot, ioh))
+		printf("%s: reset failed.\n", sc->sc_dev.dv_xname);
+
+	ug_setup_sensors(sc);
+
+	for (i=0;i<UG_NUM_SENSORS;i++) {
+		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_sysmon.sme_ranges = ug_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 = ug_gtredata;
+	sc->sc_sysmon.sme_streinfo = NULL;
+	sc->sc_sysmon.sme_nsensors = UG_NUM_SENSORS;
+	sc->sc_sysmon.sme_envsys_version = 1000;
+	sc->sc_sysmon.sme_flags = 0;
+
+	if (sysmon_envsys_register(&sc->sc_sysmon))
+		printf("%s: unable to register with sysmon\n",
+			sc->sc_dev.dv_xname);
+
+}
+
+int
+ug_reset (bus_space_tag_t iot, bus_space_handle_t ioh)
+{
+	int cnt = 0;
+
+	while (bus_space_read_1(iot, ioh, UG_DATA) != 0x08) {
+	/* 8 meaning Voodoo */
+		
+		if (cnt++ > UG_DELAY_CYCLES)
+			return 0;
+
+		bus_space_write_1(iot, ioh, UG_DATA, 0);
+
+		/* Wait for 0x09 at Data Port */
+		if (!ug_waitfor(iot, ioh, UG_DATA, 0x09))
+			return 0;
+		
+		/* Wait for 0xAC at Cmd Port */
+		if (!ug_waitfor(iot, ioh, UG_CMD, 0xAC))
+			return 0;
+	}
+
+	return 1;
+}
+
+uint8_t
+ug_read (bus_space_tag_t iot, bus_space_handle_t ioh, unsigned short sensor)
+{
+	uint8_t bank, sens, rv;
+
+	bank = (sensor & 0xFF00) >> 8;
+	sens = sensor & 0x00FF;
+
+	bus_space_write_1(iot, ioh, UG_DATA, bank);
+
+	/* Wait 8 at Data Port */
+	if (!ug_waitfor(iot, ioh, UG_DATA, 8))
+		return 0;
+
+	bus_space_write_1(iot, ioh, UG_CMD, sens);
+
+	/* Wait 1 at Data Port */
+	if (!ug_waitfor(iot, ioh, UG_DATA, 1))
+		return 0;
+
+	/* Finally read the sensor */
+	rv = bus_space_read_1(iot, ioh, UG_CMD);
+
+	ug_reset(iot, ioh);
+
+	return rv;
+}
+
+int
+ug_waitfor(bus_space_tag_t iot, bus_space_handle_t ioh,
+	uint16_t offset, uint8_t value)
+{
+	int cnt = 0;
+	while (bus_space_read_1(iot, ioh, offset) != value) {
+		if (cnt++ > UG_DELAY_CYCLES)
+			return 0;
+	}
+	return 1;
+}
+
+void
+ug_setup_sensors(struct ug_softc *sc)
+{
+	int i;
+
+	/* Setup Temps */
+	for (i=0;i<3;i++)
+		sc->sc_data[i].units = sc->sc_info[i].units = ENVSYS_STEMP;
+
+	snprintf(sc->sc_info[0].desc, sizeof(sc->sc_info[0].desc),
+		"CPU Temp");
+	snprintf(sc->sc_info[1].desc, sizeof(sc->sc_info[1].desc),
+		"SYS Temp");
+	snprintf(sc->sc_info[2].desc, sizeof(sc->sc_info[2].desc),
+		"PWN Temp");
+
+	/* Right, Now setup U sensors */
+
+	for (i=3; i<14; i++) {
+		sc->sc_data[i].units = sc->sc_info[i].units = ENVSYS_SVOLTS_DC;
+		sc->sc_info[i].rfact = UG_RFACT;
+	}
+
+	snprintf(sc->sc_info[3].desc, sizeof(sc->sc_info[3].desc),
+		"VCore");
+	snprintf(sc->sc_info[4].desc, sizeof(sc->sc_info[4].desc),
+		"DDRVdd");
+	snprintf(sc->sc_info[5].desc, sizeof(sc->sc_info[5].desc),
+		"DDRVtt");
+	snprintf(sc->sc_info[6].desc, sizeof(sc->sc_info[6].desc),
+		"NBVdd");
+	snprintf(sc->sc_info[7].desc, sizeof(sc->sc_info[7].desc),
+		"SBVdd");
+	snprintf(sc->sc_info[8].desc, sizeof(sc->sc_info[8].desc),
+		"HTVdd");
+	snprintf(sc->sc_info[9].desc, sizeof(sc->sc_info[8].desc),
+		"AGPVdd");
+	snprintf(sc->sc_info[10].desc, sizeof(sc->sc_info[10].desc),
+		"Vdd5V");
+	snprintf(sc->sc_info[11].desc, sizeof(sc->sc_info[11].desc),
+		"Vdd3V3");
+	snprintf(sc->sc_info[12].desc, sizeof(sc->sc_info[12].desc),
+		"Vdd5VSB");
+	snprintf(sc->sc_info[13].desc, sizeof(sc->sc_info[13].desc),
+		"Vdd3VDual");
+
+	/* Fan sensors */
+	for (i=14; i<19; i++)
+		sc->sc_data[i].units = sc->sc_info[i].units = ENVSYS_SFANRPM;
+
+	snprintf(sc->sc_info[14].desc, sizeof(sc->sc_info[14].desc),
+		"CPU Fan");
+	snprintf(sc->sc_info[15].desc, sizeof(sc->sc_info[15].desc),
+		"NB Fan");
+	snprintf(sc->sc_info[16].desc, sizeof(sc->sc_info[16].desc),
+		"SYS Fan");
+	snprintf(sc->sc_info[17].desc, sizeof(sc->sc_info[17].desc),
+		"AUX Fan 1");
+	snprintf(sc->sc_info[18].desc, sizeof(sc->sc_info[18].desc),
+		"AUX Fan 2");
+
+
+}
+
+static int
+ug_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;	/* For easier read */
+
+	/* Sensors returns C while we need uK */
+	t[0].cur.data_us = ug_read(sc->sc_iot, sc->sc_ioh, UG_CPUTEMP) *
+		1000000 + 273150000;
+	t[1].cur.data_us = ug_read(sc->sc_iot, sc->sc_ioh, UG_SYSTEMP) *
+		1000000 + 273150000;
+	t[2].cur.data_us = ug_read(sc->sc_iot, sc->sc_ioh, UG_PWMTEMP) *
+		1000000 + 273150000;
+
+	/* Voltages */
+	t[3].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_VCORE)
+		* UG_RFACT3;
+	t[4].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_DDRVDD)
+		* UG_RFACT3;
+	t[5].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_DDRVTT)
+		* UG_RFACT3;
+	t[6].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_NBVDD)
+		* UG_RFACT3;
+	t[7].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_SBVDD)
+		* UG_RFACT3;
+	t[8].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_HTV)
+		* UG_RFACT3;
+	t[9].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_AGP)
+		* UG_RFACT3;
+	t[10].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_5V)
+		* UG_RFACT6;
+	t[11].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_3V3)
+		* UG_RFACT4;
+	t[12].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_5VSB)
+		* UG_RFACT6;
+	t[13].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_3VDUAL)
+		* UG_RFACT4;
+
+	/* and Fans */
+	t[14].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_CPUFAN)
+		* UG_RFACT_FAN;
+	t[15].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_NBFAN)
+		* UG_RFACT_FAN;
+	t[16].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_SYSFAN)
+		* UG_RFACT_FAN;
+	t[17].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_AUXFAN1)
+		* UG_RFACT_FAN;
+	t[18].cur.data_s = ug_read(sc->sc_iot, sc->sc_ioh, UG_AUXFAN2)
+		* UG_RFACT_FAN;
+
+	*tred = sc->sc_data[tred->sensor];
+	return 0;
+}
--- src/sys/dev/isa/ugvar.h.old	1970-01-01 02:00:00.000000000 +0200
+++ src/sys/dev/isa/ugvar.h	2007-01-06 16:42:35.000000000 +0200
@@ -0,0 +1,94 @@
+/*	$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_UGVAR_H
+#define _DEV_ISA_UGVAR_H
+
+#define UG_DELAY_CYCLES	50000
+#define UG_NUM_SENSORS	19
+
+/* Data and Cmd offsets - Base is ussualy 0xE0 */
+#define UG_CMD		0
+#define UG_DATA		4
+
+/* Temp and Voltage Sensors */
+#define UG_CPUTEMP	0x2100
+#define UG_SYSTEMP	0x2101
+#define UG_HTV		0x2102
+#define UG_VCORE	0x2103
+#define UG_DDRVDD	0x2104
+#define UG_3V3		0x2105
+#define UG_5V		0x2106
+#define UG_NBVDD	0x2108
+#define UG_AGP		0x2109
+#define UG_DDRVTT	0x210A
+#define UG_5VSB		0x210B
+#define UG_3VDUAL	0x210D
+#define UG_SBVDD	0x210E
+#define UG_PWMTEMP	0x210F
+
+/* Fans */
+#define UG_CPUFAN	0x2600
+#define UG_NBFAN	0x2601
+#define UG_SYSFAN	0x2602
+#define UG_AUXFAN1	0x2603
+#define UG_AUXFAN2	0x2604
+
+/* RFacts */
+#define UG_RFACT	1000
+#define UG_RFACT3	3490 * UG_RFACT / 255
+#define UG_RFACT4	4360 * UG_RFACT / 255
+#define UG_RFACT6	6250 * UG_RFACT / 255
+#define UG_RFACT_FAN	15300/255
+
+/*
+ * sc->sensors sub-intervals for each unit type.
+ * XXX: is this correct ?
+ */
+static const struct envsys_range ug_ranges[] = {
+	{ 0, 2,		ENVSYS_STEMP   },
+	{ 14, 18,	ENVSYS_SFANRPM },
+	{ 1, 0,		ENVSYS_SVOLTS_AC },	/* None */
+	{ 3, 13,	ENVSYS_SVOLTS_DC },
+	{ 1, 0,		ENVSYS_SOHMS },		/* None */
+	{ 1, 0,		ENVSYS_SWATTS },	/* None */
+	{ 1, 0,		ENVSYS_SAMPS }		/* None */
+};
+
+struct ug_softc {
+	struct device sc_dev;
+
+	bus_space_tag_t sc_iot;
+	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];
+
+};
+
+#endif /* _DEV_ISA_UGVAR_H_ */

>Unformatted: