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: