Import it(4) and lm(4), supporting most popular Super I/O Hardware Monitors.
Submitted by: Constantine A. Murenin <cnst@FreeBSD.org> Sponsored by: Google Summer of Code 2007 (GSoC2007/cnst-sensors) Mentored by: syrinx Tested by: many OKed by: kensmith Obtained from: OpenBSD (parts)
This commit is contained in:
parent
99f6b270e3
commit
989500bf1a
@ -131,6 +131,7 @@ MAN= aac.4 \
|
||||
iscsi_initiator.4 \
|
||||
isp.4 \
|
||||
ispfw.4 \
|
||||
${_it.4} \
|
||||
iwi.4 \
|
||||
ixgb.4 \
|
||||
joy.4 \
|
||||
@ -143,6 +144,7 @@ MAN= aac.4 \
|
||||
le.4 \
|
||||
led.4 \
|
||||
lge.4 \
|
||||
lm.4 \
|
||||
lmc.4 \
|
||||
lo.4 \
|
||||
lp.4 \
|
||||
@ -547,6 +549,7 @@ _ichwd.4= ichwd.4
|
||||
_if_nfe.4= if_nfe.4
|
||||
_if_nve.4= if_nve.4
|
||||
_if_nxge.4= if_nxge.4
|
||||
_it.4= it.4
|
||||
_ipmi.4= ipmi.4
|
||||
_nfsmb.4= nfsmb.4
|
||||
_nfe.4= nfe.4
|
||||
|
104
share/man/man4/it.4
Normal file
104
share/man/man4/it.4
Normal file
@ -0,0 +1,104 @@
|
||||
.\" $FreeBSD$
|
||||
.\" $OpenBSD: it.4,v 1.8 2006/09/08 15:09:14 jmc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2003 Julien Bordet <zejames@greygats.org>
|
||||
.\" 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.
|
||||
.\"
|
||||
.Dd 13 September 2007
|
||||
.Dt IT 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm it
|
||||
.Nd ITE IT8705F/12F/16F and SiS SiS950 Super I/O Hardware Monitor
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device isa"
|
||||
.Cd "device it"
|
||||
.Pp
|
||||
In
|
||||
.Pa /boot/device.hints :
|
||||
.Cd hint.it.0.at="isa"
|
||||
.Cd hint.it.0.port="0x290"
|
||||
.Cd hint.it.1.at="isa"
|
||||
.Cd hint.it.1.port="0xc00"
|
||||
.Cd hint.it.2.at="isa"
|
||||
.Cd hint.it.2.port="0xd00"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver provides support for the
|
||||
.Tn IT8705F , IT8712F , IT8716F
|
||||
and
|
||||
.Tn SiS950
|
||||
hardware monitors.
|
||||
The values are exposed through the
|
||||
.Va HW_SENSORS
|
||||
.Xr sysctl 3
|
||||
interface.
|
||||
.Pp
|
||||
Most supported devices possess 15 sensors:
|
||||
.Bl -column "Sensor" "Units" "Typical" -offset indent
|
||||
.It Sy "Sensor" Ta Sy "Units" Ta Sy "Typical Use"
|
||||
.It Li "Fan0" Ta "RPM" Ta "CPU Fan"
|
||||
.It Li "Fan1" Ta "RPM" Ta "Fan"
|
||||
.It Li "Fan2" Ta "RPM" Ta "Fan"
|
||||
.It Li "IN0" Ta "uV DC" Ta "Core voltage"
|
||||
.It Li "IN1" Ta "uV DC" Ta "Core voltage"
|
||||
.It Li "IN2" Ta "uV DC" Ta "+3.3V"
|
||||
.It Li "IN3" Ta "uV DC" Ta "+5V"
|
||||
.It Li "IN4" Ta "uV DC" Ta "+12V"
|
||||
.It Li "IN5" Ta "uV DC" Ta "Unknown"
|
||||
.It Li "IN6" Ta "uV DC" Ta "-12V"
|
||||
.It Li "IN7" Ta "uV DC" Ta "-5V"
|
||||
.It Li "IN8" Ta "uV DC" Ta "VBAT"
|
||||
.It Li "Temp" Ta "uK" Ta "Motherboard Temperature"
|
||||
.It Li "Temp" Ta "uK" Ta "Motherboard Temperature"
|
||||
.It Li "Temp" Ta "uK" Ta "CPU Temperature"
|
||||
.El
|
||||
.Pp
|
||||
For some devices, sensors' names and numbers will be different.
|
||||
.Sh SEE ALSO
|
||||
.Xr systat 1 ,
|
||||
.Xr sysctl 3 ,
|
||||
.Xr sensorsd 8 ,
|
||||
.Xr sysctl 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver first appeared in
|
||||
.Ox 3.4 .
|
||||
.Fx
|
||||
support was added in
|
||||
.Fx 7.XXX .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm
|
||||
driver was written by
|
||||
.An Julien Bordet Aq zejames@greyhats.org .
|
||||
It was ported to
|
||||
.Fx
|
||||
by
|
||||
.An Constantine A. Murenin Aq cnst@FreeBSD.org
|
||||
as a part of a Google Summer of Code 2007 project.
|
||||
.Sh BUGS
|
||||
Interrupt support is unimplemented.
|
138
share/man/man4/lm.4
Normal file
138
share/man/man4/lm.4
Normal file
@ -0,0 +1,138 @@
|
||||
.\" $FreeBSD$
|
||||
.\" $OpenBSD: lm.4,v 1.16 2007/05/26 22:38:55 cnst Exp $
|
||||
.\" $NetBSD: lm.4,v 1.11 2001/09/22 01:22:49 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||
.\" by Bill Squier.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" 3. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by the NetBSD
|
||||
.\" Foundation, Inc. and its contributors.
|
||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
.\" contributors may be used to endorse or promote products derived
|
||||
.\" from this software without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
.\" ``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 FOUNDATION OR CONTRIBUTORS
|
||||
.\" 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.
|
||||
.\"
|
||||
.Dd 19 August 2007
|
||||
.Dt LM 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm lm
|
||||
.Nd NatSemi LM78/79/81 and Winbond Super I/O Hardware Monitor
|
||||
.Sh SYNOPSIS
|
||||
.Cd "device isa"
|
||||
.Cd "device lm"
|
||||
.Pp
|
||||
In
|
||||
.Pa /boot/device.hints :
|
||||
.Cd hint.lm.0.at="isa"
|
||||
.Cd hint.lm.0.port="0x290"
|
||||
.Cd hint.lm.1.at="isa"
|
||||
.Cd hint.lm.1.port="0x280"
|
||||
.Cd hint.lm.2.at="isa"
|
||||
.Cd hint.lm.2.port="0x310"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver provides support for the
|
||||
.Tn National Semiconductor
|
||||
LM 78/79/81 and
|
||||
.Tn Winbond
|
||||
Super I/O
|
||||
hardware monitors,
|
||||
and registers compatible chips under the
|
||||
.Va HW_SENSORS
|
||||
.Xr sysctl 3
|
||||
tree.
|
||||
.Sh HARDWARE
|
||||
Chips supported by the
|
||||
.Nm
|
||||
driver include:
|
||||
.Pp
|
||||
.Bl -dash -offset indent -compact
|
||||
.It
|
||||
National Semiconductor LM78 and LM78-J
|
||||
.It
|
||||
National Semiconductor LM79
|
||||
.It
|
||||
National Semiconductor LM81
|
||||
.It
|
||||
Winbond W83627HF, W83627THF, W83637HF and W83697HF
|
||||
.It
|
||||
Winbond W83627DHG and W83627EHF
|
||||
.It
|
||||
Winbond W83781D, W83782D and W83783S
|
||||
.It
|
||||
Winbond W83791D, W83791SD and W83792D
|
||||
.It
|
||||
ASUS AS99127F
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr systat 1 ,
|
||||
.Xr sysctl 3 ,
|
||||
.Xr sensorsd 8 ,
|
||||
.Xr sysctl 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver first appeared in
|
||||
.Nx 1.5 ;
|
||||
.Ox
|
||||
support was added in
|
||||
.Ox 3.4 ;
|
||||
.Fx
|
||||
support was added in
|
||||
.Fx 7.XXX .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm
|
||||
driver was written by
|
||||
.An Bill Squier
|
||||
and ported to
|
||||
.Ox 3.4
|
||||
by
|
||||
.An Alexander Yurchenko Aq grange@openbsd.org .
|
||||
The driver was largely rewritten for
|
||||
.Ox 3.9
|
||||
by
|
||||
.An Mark Kettenis Aq kettenis@openbsd.org .
|
||||
The driver was then ported to
|
||||
.Fx
|
||||
by
|
||||
.An Constantine A. Murenin Aq cnst@FreeBSD.org
|
||||
as a part of a Google Summer of Code 2007 project.
|
||||
.Sh CAVEATS
|
||||
Some vendors connect these chips to non-standard thermal diodes and
|
||||
resistors.
|
||||
This will result in bogus sensor values.
|
||||
.Sh BUGS
|
||||
Interrupt support is unimplemented.
|
||||
.Pp
|
||||
There are currently no known pnpbios IDs assigned to LM chips.
|
||||
.Pp
|
||||
This driver attaches to the Winbond W83791SD chip even though that
|
||||
chip does not have any sensors.
|
@ -33,3 +33,11 @@ hint.sio.3.port="0x2E8"
|
||||
hint.sio.3.irq="9"
|
||||
hint.ppc.0.at="isa"
|
||||
hint.ppc.0.irq="7"
|
||||
hint.lm.0.at="isa"
|
||||
hint.lm.0.port="0x290"
|
||||
hint.it.0.at="isa"
|
||||
hint.it.0.port="0x290"
|
||||
hint.it.1.at="isa"
|
||||
hint.it.1.port="0xc00"
|
||||
hint.it.2.at="isa"
|
||||
hint.it.2.port="0xd00"
|
||||
|
@ -758,6 +758,8 @@ dev/le/if_le_pci.c optional le pci
|
||||
dev/le/lance.c optional le
|
||||
dev/led/led.c standard
|
||||
dev/lge/if_lge.c optional lge
|
||||
dev/lm/lm78.c optional lm
|
||||
dev/lm/lm78_isa.c optional lm isa
|
||||
dev/lmc/if_lmc.c optional lmc
|
||||
dev/mc146818/mc146818.c optional mc146818
|
||||
dev/mca/mca_bus.c optional mca
|
||||
|
@ -169,6 +169,7 @@ dev/ipmi/ipmi_smbus.c optional ipmi smbus
|
||||
dev/ipmi/ipmi_smbios.c optional ipmi
|
||||
dev/ipmi/ipmi_ssif.c optional ipmi smbus
|
||||
dev/ipmi/ipmi_pci.c optional ipmi pci
|
||||
dev/it/it.c optional it isa
|
||||
dev/fdc/fdc.c optional fdc
|
||||
dev/fdc/fdc_acpi.c optional fdc
|
||||
dev/fdc/fdc_isa.c optional fdc isa
|
||||
|
@ -204,6 +204,7 @@ dev/ipmi/ipmi_smbus.c optional ipmi smbus
|
||||
dev/ipmi/ipmi_smbios.c optional ipmi
|
||||
dev/ipmi/ipmi_ssif.c optional ipmi smbus
|
||||
dev/ipmi/ipmi_pci.c optional ipmi pci
|
||||
dev/it/it.c optional it isa
|
||||
dev/kbd/kbd.c optional atkbd | sc | ukbd | vt
|
||||
dev/le/if_le_isa.c optional le isa
|
||||
dev/mem/memutil.c optional mem
|
||||
|
346
sys/dev/it/it.c
Normal file
346
sys/dev/it/it.c
Normal file
@ -0,0 +1,346 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: it.c,v 1.22 2007/03/22 16:55:31 deraadt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 Julien Bordet <zejames@greyhats.org>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/module.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <sys/sensors.h>
|
||||
|
||||
#include <dev/it/itvar.h>
|
||||
|
||||
#if defined(ITDEBUG)
|
||||
#define DPRINTF(x) do { printf x; } while (0)
|
||||
#else
|
||||
#define DPRINTF(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IT87-compatible chips can typically measure voltages up to 4.096 V.
|
||||
* To measure higher voltages the input is attenuated with (external)
|
||||
* resistors. Negative voltages are measured using a reference
|
||||
* voltage. So we have to convert the sensor values back to real
|
||||
* voltages by applying the appropriate resistor factor.
|
||||
*/
|
||||
#define RFACT_NONE 10000
|
||||
#define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y))
|
||||
|
||||
int it_probe(struct device *);
|
||||
int it_attach(struct device *);
|
||||
int it_detach(struct device *);
|
||||
u_int8_t it_readreg(struct it_softc *, int);
|
||||
void it_writereg(struct it_softc *, int, int);
|
||||
void it_setup_volt(struct it_softc *, int, int);
|
||||
void it_setup_temp(struct it_softc *, int, int);
|
||||
void it_setup_fan(struct it_softc *, int, int);
|
||||
|
||||
void it_generic_stemp(struct it_softc *, struct ksensor *);
|
||||
void it_generic_svolt(struct it_softc *, struct ksensor *);
|
||||
void it_generic_fanrpm(struct it_softc *, struct ksensor *);
|
||||
|
||||
void it_refresh_sensor_data(struct it_softc *);
|
||||
void it_refresh(void *);
|
||||
|
||||
extern struct cfdriver it_cd;
|
||||
|
||||
static device_method_t it_methods[] = {
|
||||
/* Methods from the device interface */
|
||||
DEVMETHOD(device_probe, it_probe),
|
||||
DEVMETHOD(device_attach, it_attach),
|
||||
DEVMETHOD(device_detach, it_detach),
|
||||
|
||||
/* Terminate method list */
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t it_driver = {
|
||||
"it",
|
||||
it_methods,
|
||||
sizeof (struct it_softc)
|
||||
};
|
||||
|
||||
static devclass_t it_devclass;
|
||||
|
||||
DRIVER_MODULE(it, isa, it_driver, it_devclass, NULL, NULL);
|
||||
|
||||
|
||||
const int it_vrfact[] = {
|
||||
RFACT_NONE,
|
||||
RFACT_NONE,
|
||||
RFACT_NONE,
|
||||
RFACT(68, 100),
|
||||
RFACT(30, 10),
|
||||
RFACT(21, 10),
|
||||
RFACT(83, 20),
|
||||
RFACT(68, 100),
|
||||
RFACT_NONE
|
||||
};
|
||||
|
||||
int
|
||||
it_probe(struct device *dev)
|
||||
{
|
||||
struct resource *iores;
|
||||
int iorid = 0;
|
||||
bus_space_tag_t iot;
|
||||
bus_space_handle_t ioh;
|
||||
u_int8_t cr;
|
||||
|
||||
iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &iorid,
|
||||
0ul, ~0ul, 8, RF_ACTIVE);
|
||||
if (iores == NULL) {
|
||||
DPRINTF(("%s: can't map i/o space\n", __func__));
|
||||
return 1;
|
||||
}
|
||||
iot = rman_get_bustag(iores);
|
||||
ioh = rman_get_bushandle(iores);
|
||||
|
||||
/* Check Vendor ID */
|
||||
bus_space_write_1(iot, ioh, ITC_ADDR, ITD_CHIPID);
|
||||
cr = bus_space_read_1(iot, ioh, ITC_DATA);
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores);
|
||||
DPRINTF(("it: vendor id 0x%x\n", cr));
|
||||
if (cr != IT_ID_IT87)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
it_attach(struct device *dev)
|
||||
{
|
||||
struct it_softc *sc = device_get_softc(dev);
|
||||
int i;
|
||||
u_int8_t cr;
|
||||
|
||||
sc->sc_dev = dev;
|
||||
sc->sc_iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_iorid,
|
||||
0ul, ~0ul, 8, RF_ACTIVE);
|
||||
if (sc->sc_iores == NULL) {
|
||||
device_printf(dev, "can't map i/o space\n");
|
||||
return 1;
|
||||
}
|
||||
sc->sc_iot = rman_get_bustag(sc->sc_iores);
|
||||
sc->sc_ioh = rman_get_bushandle(sc->sc_iores);
|
||||
|
||||
sc->numsensors = IT_NUM_SENSORS;
|
||||
|
||||
it_setup_fan(sc, 0, 3);
|
||||
it_setup_volt(sc, 3, 9);
|
||||
it_setup_temp(sc, 12, 3);
|
||||
|
||||
if (sensor_task_register(sc, it_refresh, 5)) {
|
||||
device_printf(sc->sc_dev, "unable to register update task\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Activate monitoring */
|
||||
cr = it_readreg(sc, ITD_CONFIG);
|
||||
cr |= 0x01 | 0x08;
|
||||
it_writereg(sc, ITD_CONFIG, cr);
|
||||
|
||||
/* Initialize sensors */
|
||||
strlcpy(sc->sensordev.xname, device_get_nameunit(sc->sc_dev),
|
||||
sizeof(sc->sensordev.xname));
|
||||
for (i = 0; i < sc->numsensors; ++i)
|
||||
sensor_attach(&sc->sensordev, &sc->sensors[i]);
|
||||
sensordev_install(&sc->sensordev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
it_detach(struct device *dev)
|
||||
{
|
||||
struct it_softc *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
sensordev_deinstall(&sc->sensordev);
|
||||
sensor_task_unregister(sc);
|
||||
|
||||
error = bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_iorid,
|
||||
sc->sc_iores);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u_int8_t
|
||||
it_readreg(struct it_softc *sc, int reg)
|
||||
{
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, ITC_ADDR, reg);
|
||||
return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, ITC_DATA));
|
||||
}
|
||||
|
||||
void
|
||||
it_writereg(struct it_softc *sc, int reg, int val)
|
||||
{
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, ITC_ADDR, reg);
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, ITC_DATA, val);
|
||||
}
|
||||
|
||||
void
|
||||
it_setup_volt(struct it_softc *sc, int start, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
sc->sensors[start + i].type = SENSOR_VOLTS_DC;
|
||||
}
|
||||
|
||||
snprintf(sc->sensors[start + 0].desc, sizeof(sc->sensors[0].desc),
|
||||
"VCORE_A");
|
||||
snprintf(sc->sensors[start + 1].desc, sizeof(sc->sensors[1].desc),
|
||||
"VCORE_B");
|
||||
snprintf(sc->sensors[start + 2].desc, sizeof(sc->sensors[2].desc),
|
||||
"+3.3V");
|
||||
snprintf(sc->sensors[start + 3].desc, sizeof(sc->sensors[3].desc),
|
||||
"+5V");
|
||||
snprintf(sc->sensors[start + 4].desc, sizeof(sc->sensors[4].desc),
|
||||
"+12V");
|
||||
snprintf(sc->sensors[start + 5].desc, sizeof(sc->sensors[5].desc),
|
||||
"Unused");
|
||||
snprintf(sc->sensors[start + 6].desc, sizeof(sc->sensors[6].desc),
|
||||
"-12V");
|
||||
snprintf(sc->sensors[start + 7].desc, sizeof(sc->sensors[7].desc),
|
||||
"+5VSB");
|
||||
snprintf(sc->sensors[start + 8].desc, sizeof(sc->sensors[8].desc),
|
||||
"VBAT");
|
||||
}
|
||||
|
||||
void
|
||||
it_setup_temp(struct it_softc *sc, int start, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
sc->sensors[start + i].type = SENSOR_TEMP;
|
||||
}
|
||||
|
||||
void
|
||||
it_setup_fan(struct it_softc *sc, int start, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
sc->sensors[start + i].type = SENSOR_FANRPM;
|
||||
}
|
||||
|
||||
void
|
||||
it_generic_stemp(struct it_softc *sc, struct ksensor *sensors)
|
||||
{
|
||||
int i, sdata;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
sdata = it_readreg(sc, ITD_SENSORTEMPBASE + i);
|
||||
/* Convert temperature to Fahrenheit degres */
|
||||
sensors[i].value = sdata * 1000000 + 273150000;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
it_generic_svolt(struct it_softc *sc, struct ksensor *sensors)
|
||||
{
|
||||
int i, sdata;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
sdata = it_readreg(sc, ITD_SENSORVOLTBASE + i);
|
||||
DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata));
|
||||
/* voltage returned as (mV >> 4) */
|
||||
sensors[i].value = (sdata << 4);
|
||||
/* these two values are negative and formula is different */
|
||||
if (i == 5 || i == 6)
|
||||
sensors[i].value = ((sdata << 4) - IT_VREF);
|
||||
/* rfact is (factor * 10^4) */
|
||||
sensors[i].value *= it_vrfact[i];
|
||||
/* division by 10 gets us back to uVDC */
|
||||
sensors[i].value /= 10;
|
||||
if (i == 5 || i == 6)
|
||||
sensors[i].value += IT_VREF * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
it_generic_fanrpm(struct it_softc *sc, struct ksensor *sensors)
|
||||
{
|
||||
int i, sdata, divisor, odivisor, ndivisor;
|
||||
|
||||
odivisor = ndivisor = divisor = it_readreg(sc, ITD_FAN);
|
||||
for (i = 0; i < 3; i++, divisor >>= 3) {
|
||||
sensors[i].flags &= ~SENSOR_FINVALID;
|
||||
if ((sdata = it_readreg(sc, ITD_SENSORFANBASE + i)) == 0xff) {
|
||||
sensors[i].flags |= SENSOR_FINVALID;
|
||||
if (i == 2)
|
||||
ndivisor ^= 0x40;
|
||||
else {
|
||||
ndivisor &= ~(7 << (i * 3));
|
||||
ndivisor |= ((divisor + 1) & 7) << (i * 3);
|
||||
}
|
||||
} else if (sdata == 0) {
|
||||
sensors[i].value = 0;
|
||||
} else {
|
||||
if (i == 2)
|
||||
divisor = divisor & 1 ? 3 : 1;
|
||||
sensors[i].value = 1350000 / (sdata << (divisor & 7));
|
||||
}
|
||||
}
|
||||
if (ndivisor != odivisor)
|
||||
it_writereg(sc, ITD_FAN, ndivisor);
|
||||
}
|
||||
|
||||
/*
|
||||
* pre: last read occurred >= 1.5 seconds ago
|
||||
* post: sensors[] current data are the latest from the chip
|
||||
*/
|
||||
void
|
||||
it_refresh_sensor_data(struct it_softc *sc)
|
||||
{
|
||||
/* Refresh our stored data for every sensor */
|
||||
it_generic_stemp(sc, &sc->sensors[12]);
|
||||
it_generic_svolt(sc, &sc->sensors[3]);
|
||||
it_generic_fanrpm(sc, &sc->sensors[0]);
|
||||
}
|
||||
|
||||
void
|
||||
it_refresh(void *arg)
|
||||
{
|
||||
struct it_softc *sc = (struct it_softc *)arg;
|
||||
|
||||
it_refresh_sensor_data(sc);
|
||||
}
|
95
sys/dev/it/itvar.h
Normal file
95
sys/dev/it/itvar.h
Normal file
@ -0,0 +1,95 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: itvar.h,v 1.4 2007/03/22 16:55:31 deraadt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 Julien Bordet <zejames@greyhats.org>
|
||||
* 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_ITVAR_H
|
||||
#define _DEV_ISA_ITVAR_H
|
||||
|
||||
#define IT_NUM_SENSORS 15
|
||||
|
||||
/* chip ids */
|
||||
#define IT_ID_IT87 0x90
|
||||
|
||||
/* ctl registers */
|
||||
|
||||
#define ITC_ADDR 0x05
|
||||
#define ITC_DATA 0x06
|
||||
|
||||
/* data registers */
|
||||
|
||||
#define ITD_CONFIG 0x00
|
||||
#define ITD_ISR1 0x01
|
||||
#define ITD_ISR2 0x02
|
||||
#define ITD_ISR3 0x03
|
||||
#define ITD_SMI1 0x04
|
||||
#define ITD_SMI2 0x05
|
||||
#define ITD_SMI3 0x06
|
||||
#define ITD_IMR1 0x07
|
||||
#define ITD_IMR2 0x08
|
||||
#define ITD_IMR3 0x09
|
||||
#define ITD_VID 0x0a
|
||||
#define ITD_FAN 0x0b
|
||||
|
||||
#define ITD_FANMINBASE 0x10
|
||||
#define ITD_FANENABLE 0x13
|
||||
|
||||
#define ITD_SENSORFANBASE 0x0d /* Fan from 0x0d to 0x0f */
|
||||
#define ITD_SENSORVOLTBASE 0x20 /* Fan from 0x20 to 0x28 */
|
||||
#define ITD_SENSORTEMPBASE 0x29 /* Fan from 0x29 to 0x2b */
|
||||
|
||||
#define ITD_VOLTMAXBASE 0x30
|
||||
#define ITD_VOLTMINBASE 0x31
|
||||
|
||||
#define ITD_TEMPMAXBASE 0x40
|
||||
#define ITD_TEMPMINBASE 0x41
|
||||
|
||||
#define ITD_SBUSADDR 0x48
|
||||
#define ITD_VOLTENABLE 0x50
|
||||
#define ITD_TEMPENABLE 0x51
|
||||
|
||||
#define ITD_CHIPID 0x58
|
||||
|
||||
#define IT_VREF (4096) /* Vref = 4.096 V */
|
||||
|
||||
struct it_softc {
|
||||
struct device *sc_dev;
|
||||
|
||||
struct resource *sc_iores;
|
||||
int sc_iorid;
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
|
||||
struct ksensor sensors[IT_NUM_SENSORS];
|
||||
struct ksensordev sensordev;
|
||||
u_int numsensors;
|
||||
void (*refresh_sensor_data)(struct it_softc *);
|
||||
|
||||
u_int8_t (*it_readreg)(struct it_softc *, int);
|
||||
void (*it_writereg)(struct it_softc *, int, int);
|
||||
};
|
||||
|
||||
#endif
|
909
sys/dev/lm/lm78.c
Normal file
909
sys/dev/lm/lm78.c
Normal file
@ -0,0 +1,909 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: lm78.c,v 1.18 2007/05/26 22:47:39 cnst Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2005, 2006 Mark Kettenis
|
||||
* Copyright (c) 2006, 2007 Constantine A. Murenin
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/sensors.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/lm/lm78var.h>
|
||||
|
||||
#if defined(LMDEBUG)
|
||||
#define DPRINTF(x) do { printf x; } while (0)
|
||||
#else
|
||||
#define DPRINTF(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* LM78-compatible chips can typically measure voltages up to 4.096 V.
|
||||
* To measure higher voltages the input is attenuated with (external)
|
||||
* resistors. Negative voltages are measured using inverting op amps
|
||||
* and resistors. So we have to convert the sensor values back to
|
||||
* real voltages by applying the appropriate resistor factor.
|
||||
*/
|
||||
#define RFACT_NONE 10000
|
||||
#define RFACT(x, y) (RFACT_NONE * ((x) + (y)) / (y))
|
||||
#define NRFACT(x, y) (-RFACT_NONE * (x) / (y))
|
||||
|
||||
int lm_match(struct lm_softc *);
|
||||
int wb_match(struct lm_softc *);
|
||||
int def_match(struct lm_softc *);
|
||||
|
||||
void lm_setup_sensors(struct lm_softc *, struct lm_sensor *);
|
||||
void lm_refresh(void *);
|
||||
|
||||
void lm_refresh_sensor_data(struct lm_softc *);
|
||||
void lm_refresh_volt(struct lm_softc *, int);
|
||||
void lm_refresh_temp(struct lm_softc *, int);
|
||||
void lm_refresh_fanrpm(struct lm_softc *, int);
|
||||
|
||||
void wb_refresh_sensor_data(struct lm_softc *);
|
||||
void wb_w83637hf_refresh_vcore(struct lm_softc *, int);
|
||||
void wb_refresh_nvolt(struct lm_softc *, int);
|
||||
void wb_w83627ehf_refresh_nvolt(struct lm_softc *, int);
|
||||
void wb_refresh_temp(struct lm_softc *, int);
|
||||
void wb_refresh_fanrpm(struct lm_softc *, int);
|
||||
void wb_w83792d_refresh_fanrpm(struct lm_softc *, int);
|
||||
|
||||
void as_refresh_temp(struct lm_softc *, int);
|
||||
|
||||
struct lm_chip {
|
||||
int (*chip_match)(struct lm_softc *);
|
||||
};
|
||||
|
||||
struct lm_chip lm_chips[] = {
|
||||
{ wb_match },
|
||||
{ lm_match },
|
||||
{ def_match } /* Must be last */
|
||||
};
|
||||
|
||||
struct lm_sensor lm78_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
|
||||
{ "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(68, 100) },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(30, 10) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(240, 60) },
|
||||
{ "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(100, 60) },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct lm_sensor w83627hf_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
|
||||
{ "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
|
||||
{ "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
|
||||
{ "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
|
||||
{ "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* The W83627EHF can measure voltages up to 2.048 V instead of the
|
||||
* traditional 4.096 V. For measuring positive voltages, this can be
|
||||
* accounted for by halving the resistor factor. Negative voltages
|
||||
* need special treatment, also because the reference voltage is 2.048 V
|
||||
* instead of the traditional 3.6 V.
|
||||
*/
|
||||
struct lm_sensor w83627ehf_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
|
||||
{ "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
|
||||
{ "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
|
||||
{ "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
|
||||
{ "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
|
||||
{ "", SENSOR_VOLTS_DC, 5, 0x52, lm_refresh_volt, RFACT_NONE / 2 },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* w83627dhg is almost identical to w83627ehf, except that
|
||||
* it has 9 instead of 10 voltage sensors
|
||||
*/
|
||||
struct lm_sensor w83627dhg_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE / 2},
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(56, 10) / 2 },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT(34, 34) / 2 },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 34) / 2 },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_w83627ehf_refresh_nvolt },
|
||||
{ "", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, RFACT_NONE / 2 },
|
||||
{ "", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT_NONE / 2 },
|
||||
{ "3.3VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 34) / 2 },
|
||||
{ "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE / 2 },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct lm_sensor w83637hf_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore", SENSOR_VOLTS_DC, 0, 0x20, wb_w83637hf_refresh_vcore },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT(28, 10) },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 51) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x24, wb_refresh_nvolt, RFACT(232, 56) },
|
||||
{ "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(34, 51) },
|
||||
{ "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct lm_sensor w83697hf_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
|
||||
{ "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
|
||||
{ "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
|
||||
{ "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* The datasheet doesn't mention the (internal) resistors used for the
|
||||
* +5V, but using the values from the W83782D datasheets seems to
|
||||
* provide sensible results.
|
||||
*/
|
||||
struct lm_sensor w83781d_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
|
||||
{ "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x25, lm_refresh_volt, NRFACT(2100, 604) },
|
||||
{ "-5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, NRFACT(909, 604) },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct lm_sensor w83782d_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
|
||||
{ "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
|
||||
{ "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
|
||||
{ "5VSB", SENSOR_VOLTS_DC, 5, 0x50, lm_refresh_volt, RFACT(17, 33) },
|
||||
{ "VBAT", SENSOR_VOLTS_DC, 5, 0x51, lm_refresh_volt, RFACT_NONE },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 2, 0x50, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct lm_sensor w83783s_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
|
||||
{ "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 1, 0x50, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct lm_sensor w83791d_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
|
||||
{ "VINR0", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
|
||||
{ "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
|
||||
{ "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
|
||||
{ "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
|
||||
{ "VINR1", SENSOR_VOLTS_DC, 0, 0xb2, lm_refresh_volt, RFACT_NONE },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0xba, wb_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0xbb, wb_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct lm_sensor w83792d_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
|
||||
{ "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "-5V", SENSOR_VOLTS_DC, 0, 0x23, wb_refresh_nvolt, RFACT(120, 56) },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x26, lm_refresh_volt, RFACT(34, 50) },
|
||||
{ "5VSB", SENSOR_VOLTS_DC, 0, 0xb0, lm_refresh_volt, RFACT(17, 33) },
|
||||
{ "VBAT", SENSOR_VOLTS_DC, 0, 0xb1, lm_refresh_volt, RFACT_NONE },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 0, 0xc0, wb_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 0, 0xc8, wb_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, wb_w83792d_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, wb_w83792d_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, wb_w83792d_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0xb8, wb_w83792d_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0xb9, wb_w83792d_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0xba, wb_w83792d_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0xbe, wb_w83792d_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
struct lm_sensor as99127f_sensors[] = {
|
||||
/* Voltage */
|
||||
{ "VCore A", SENSOR_VOLTS_DC, 0, 0x20, lm_refresh_volt, RFACT_NONE },
|
||||
{ "VCore B", SENSOR_VOLTS_DC, 0, 0x21, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+3.3V", SENSOR_VOLTS_DC, 0, 0x22, lm_refresh_volt, RFACT_NONE },
|
||||
{ "+5V", SENSOR_VOLTS_DC, 0, 0x23, lm_refresh_volt, RFACT(34, 50) },
|
||||
{ "+12V", SENSOR_VOLTS_DC, 0, 0x24, lm_refresh_volt, RFACT(28, 10) },
|
||||
{ "-12V", SENSOR_VOLTS_DC, 0, 0x25, wb_refresh_nvolt, RFACT(232, 56) },
|
||||
{ "-5V", SENSOR_VOLTS_DC, 0, 0x26, wb_refresh_nvolt, RFACT(120, 56) },
|
||||
|
||||
/* Temperature */
|
||||
{ "", SENSOR_TEMP, 0, 0x27, lm_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 1, 0x50, as_refresh_temp },
|
||||
{ "", SENSOR_TEMP, 2, 0x50, as_refresh_temp },
|
||||
|
||||
/* Fans */
|
||||
{ "", SENSOR_FANRPM, 0, 0x28, lm_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x29, lm_refresh_fanrpm },
|
||||
{ "", SENSOR_FANRPM, 0, 0x2a, lm_refresh_fanrpm },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
void
|
||||
lm_probe(struct lm_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++)
|
||||
if (lm_chips[i].chip_match(sc))
|
||||
break;
|
||||
}
|
||||
|
||||
void
|
||||
lm_attach(struct lm_softc *sc)
|
||||
{
|
||||
u_int i, config;
|
||||
|
||||
/* No point in doing anything if we don't have any sensors. */
|
||||
if (sc->numsensors == 0)
|
||||
return;
|
||||
|
||||
if (sensor_task_register(sc, lm_refresh, 5)) {
|
||||
device_printf(sc->sc_dev, "unable to register update task\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Start the monitoring loop */
|
||||
config = sc->lm_readreg(sc, LM_CONFIG);
|
||||
sc->lm_writereg(sc, LM_CONFIG, config | 0x01);
|
||||
|
||||
/* Add sensors */
|
||||
strlcpy(sc->sensordev.xname, device_get_nameunit(sc->sc_dev),
|
||||
sizeof(sc->sensordev.xname));
|
||||
for (i = 0; i < sc->numsensors; ++i)
|
||||
sensor_attach(&sc->sensordev, &sc->sensors[i]);
|
||||
sensordev_install(&sc->sensordev);
|
||||
}
|
||||
|
||||
int
|
||||
lm_detach(struct lm_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Remove sensors */
|
||||
sensordev_deinstall(&sc->sensordev);
|
||||
for (i = 0; i < sc->numsensors; i++)
|
||||
sensor_detach(&sc->sensordev, &sc->sensors[i]);
|
||||
|
||||
sensor_task_unregister(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lm_match(struct lm_softc *sc)
|
||||
{
|
||||
int chipid;
|
||||
const char *cdesc;
|
||||
char fulldesc[64];
|
||||
|
||||
/* See if we have an LM78 or LM79. */
|
||||
chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
|
||||
switch(chipid) {
|
||||
case LM_CHIPID_LM78:
|
||||
cdesc = "LM78";
|
||||
break;
|
||||
case LM_CHIPID_LM78J:
|
||||
cdesc = "LM78J";
|
||||
break;
|
||||
case LM_CHIPID_LM79:
|
||||
cdesc = "LM79";
|
||||
break;
|
||||
case LM_CHIPID_LM81:
|
||||
cdesc = "LM81";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
snprintf(fulldesc, sizeof(fulldesc),
|
||||
"National Semiconductor %s Hardware Monitor", cdesc);
|
||||
device_set_desc_copy(sc->sc_dev, fulldesc);
|
||||
|
||||
lm_setup_sensors(sc, lm78_sensors);
|
||||
sc->refresh_sensor_data = lm_refresh_sensor_data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
def_match(struct lm_softc *sc)
|
||||
{
|
||||
int chipid;
|
||||
char fulldesc[64];
|
||||
|
||||
chipid = sc->lm_readreg(sc, LM_CHIPID) & LM_CHIPID_MASK;
|
||||
snprintf(fulldesc, sizeof(fulldesc),
|
||||
"unknown Hardware Monitor (ID 0x%x)", chipid);
|
||||
device_set_desc_copy(sc->sc_dev, fulldesc);
|
||||
|
||||
lm_setup_sensors(sc, lm78_sensors);
|
||||
sc->refresh_sensor_data = lm_refresh_sensor_data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
wb_match(struct lm_softc *sc)
|
||||
{
|
||||
int banksel, vendid, devid;
|
||||
const char *cdesc;
|
||||
char desc[64];
|
||||
char fulldesc[64];
|
||||
|
||||
/* Read vendor ID */
|
||||
banksel = sc->lm_readreg(sc, WB_BANKSEL);
|
||||
sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_HBAC);
|
||||
vendid = sc->lm_readreg(sc, WB_VENDID) << 8;
|
||||
sc->lm_writereg(sc, WB_BANKSEL, 0);
|
||||
vendid |= sc->lm_readreg(sc, WB_VENDID);
|
||||
sc->lm_writereg(sc, WB_BANKSEL, banksel);
|
||||
DPRINTF((" winbond vend id 0x%x\n", vendid));
|
||||
if (vendid != WB_VENDID_WINBOND && vendid != WB_VENDID_ASUS)
|
||||
return 0;
|
||||
|
||||
/* Read device/chip ID */
|
||||
sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
|
||||
devid = sc->lm_readreg(sc, LM_CHIPID);
|
||||
sc->chipid = sc->lm_readreg(sc, WB_BANK0_CHIPID);
|
||||
sc->lm_writereg(sc, WB_BANKSEL, banksel);
|
||||
DPRINTF((" winbond chip id 0x%x\n", sc->chipid));
|
||||
switch(sc->chipid) {
|
||||
case WB_CHIPID_W83627HF:
|
||||
cdesc = "W83627HF";
|
||||
lm_setup_sensors(sc, w83627hf_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83627THF:
|
||||
cdesc = "W83627THF";
|
||||
lm_setup_sensors(sc, w83637hf_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83627EHF:
|
||||
cdesc = "W83627EHF";
|
||||
lm_setup_sensors(sc, w83627ehf_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83627DHG:
|
||||
cdesc = "W83627DHG";
|
||||
lm_setup_sensors(sc, w83627dhg_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83637HF:
|
||||
cdesc = "W83637HF";
|
||||
sc->lm_writereg(sc, WB_BANKSEL, WB_BANKSEL_B0);
|
||||
if (sc->lm_readreg(sc, WB_BANK0_CONFIG) & WB_CONFIG_VMR9)
|
||||
sc->vrm9 = 1;
|
||||
sc->lm_writereg(sc, WB_BANKSEL, banksel);
|
||||
lm_setup_sensors(sc, w83637hf_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83697HF:
|
||||
cdesc = "W83697HF";
|
||||
lm_setup_sensors(sc, w83697hf_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83781D:
|
||||
case WB_CHIPID_W83781D_2:
|
||||
cdesc = "W83781D";
|
||||
lm_setup_sensors(sc, w83781d_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83782D:
|
||||
cdesc = "W83782D";
|
||||
lm_setup_sensors(sc, w83782d_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83783S:
|
||||
cdesc = "W83783S";
|
||||
lm_setup_sensors(sc, w83783s_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83791D:
|
||||
cdesc = "W83791D";
|
||||
lm_setup_sensors(sc, w83791d_sensors);
|
||||
break;
|
||||
case WB_CHIPID_W83791SD:
|
||||
cdesc = "W83791SD";
|
||||
break;
|
||||
case WB_CHIPID_W83792D:
|
||||
if (devid >= 0x10 && devid <= 0x29)
|
||||
snprintf(desc, sizeof(desc),
|
||||
"W83792D rev %c", 'A' + devid - 0x10);
|
||||
else
|
||||
snprintf(desc, sizeof(desc),
|
||||
"W83792D rev 0x%x", devid);
|
||||
cdesc = desc;
|
||||
lm_setup_sensors(sc, w83792d_sensors);
|
||||
break;
|
||||
case WB_CHIPID_AS99127F:
|
||||
if (vendid == WB_VENDID_ASUS) {
|
||||
cdesc = "AS99127F";
|
||||
lm_setup_sensors(sc, w83781d_sensors);
|
||||
} else {
|
||||
cdesc = "AS99127F rev 2";
|
||||
lm_setup_sensors(sc, as99127f_sensors);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
snprintf(fulldesc, sizeof(fulldesc),
|
||||
"unknown Winbond Hardware Monitor (Chip ID 0x%x)",
|
||||
sc->chipid);
|
||||
device_set_desc_copy(sc->sc_dev, fulldesc);
|
||||
/* Handle as a standard LM78. */
|
||||
lm_setup_sensors(sc, lm78_sensors);
|
||||
sc->refresh_sensor_data = lm_refresh_sensor_data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cdesc[0] == 'W')
|
||||
snprintf(fulldesc, sizeof(fulldesc),
|
||||
"Winbond %s Hardware Monitor", cdesc);
|
||||
else
|
||||
snprintf(fulldesc, sizeof(fulldesc),
|
||||
"ASUS %s Hardware Monitor", cdesc);
|
||||
device_set_desc_copy(sc->sc_dev, fulldesc);
|
||||
|
||||
sc->refresh_sensor_data = wb_refresh_sensor_data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
lm_setup_sensors(struct lm_softc *sc, struct lm_sensor *sensors)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; sensors[i].desc; i++) {
|
||||
sc->sensors[i].type = sensors[i].type;
|
||||
strlcpy(sc->sensors[i].desc, sensors[i].desc,
|
||||
sizeof(sc->sensors[i].desc));
|
||||
sc->numsensors++;
|
||||
}
|
||||
sc->lm_sensors = sensors;
|
||||
}
|
||||
|
||||
void
|
||||
lm_refresh(void *arg)
|
||||
{
|
||||
struct lm_softc *sc = arg;
|
||||
|
||||
sc->refresh_sensor_data(sc);
|
||||
}
|
||||
|
||||
void
|
||||
lm_refresh_sensor_data(struct lm_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sc->numsensors; i++)
|
||||
sc->lm_sensors[i].refresh(sc, i);
|
||||
}
|
||||
|
||||
void
|
||||
lm_refresh_volt(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int data;
|
||||
|
||||
data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
|
||||
sensor->value = (data << 4);
|
||||
sensor->value *= sc->lm_sensors[n].rfact;
|
||||
sensor->value /= 10;
|
||||
}
|
||||
|
||||
void
|
||||
lm_refresh_temp(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int sdata;
|
||||
|
||||
/*
|
||||
* The data sheet suggests that the range of the temperature
|
||||
* sensor is between -55 degC and +125 degC.
|
||||
*/
|
||||
sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
|
||||
if (sdata > 0x7d && sdata < 0xc9) {
|
||||
sensor->flags |= SENSOR_FINVALID;
|
||||
sensor->value = 0;
|
||||
} else {
|
||||
if (sdata & 0x80)
|
||||
sdata -= 0x100;
|
||||
sensor->flags &= ~SENSOR_FINVALID;
|
||||
sensor->value = sdata * 1000000 + 273150000;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lm_refresh_fanrpm(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int data, divisor = 1;
|
||||
|
||||
/*
|
||||
* We might get more accurate fan readings by adjusting the
|
||||
* divisor, but that might interfere with APM or other SMM
|
||||
* BIOS code reading the fan speeds.
|
||||
*/
|
||||
|
||||
/* FAN3 has a fixed fan divisor. */
|
||||
if (sc->lm_sensors[n].reg == LM_FAN1 ||
|
||||
sc->lm_sensors[n].reg == LM_FAN2) {
|
||||
data = sc->lm_readreg(sc, LM_VIDFAN);
|
||||
if (sc->lm_sensors[n].reg == LM_FAN1)
|
||||
divisor = (data >> 4) & 0x03;
|
||||
else
|
||||
divisor = (data >> 6) & 0x03;
|
||||
}
|
||||
|
||||
data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
|
||||
if (data == 0xff || data == 0x00) {
|
||||
sensor->flags |= SENSOR_FINVALID;
|
||||
sensor->value = 0;
|
||||
} else {
|
||||
sensor->flags &= ~SENSOR_FINVALID;
|
||||
sensor->value = 1350000 / (data << divisor);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wb_refresh_sensor_data(struct lm_softc *sc)
|
||||
{
|
||||
int banksel, bank, i;
|
||||
|
||||
/*
|
||||
* Properly save and restore bank selection register.
|
||||
*/
|
||||
|
||||
banksel = bank = sc->lm_readreg(sc, WB_BANKSEL);
|
||||
for (i = 0; i < sc->numsensors; i++) {
|
||||
if (bank != sc->lm_sensors[i].bank) {
|
||||
bank = sc->lm_sensors[i].bank;
|
||||
sc->lm_writereg(sc, WB_BANKSEL, bank);
|
||||
}
|
||||
sc->lm_sensors[i].refresh(sc, i);
|
||||
}
|
||||
sc->lm_writereg(sc, WB_BANKSEL, banksel);
|
||||
}
|
||||
|
||||
void
|
||||
wb_w83637hf_refresh_vcore(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int data;
|
||||
|
||||
data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
|
||||
|
||||
/*
|
||||
* Depending on the voltage detection method,
|
||||
* one of the following formulas is used:
|
||||
* VRM8 method: value = raw * 0.016V
|
||||
* VRM9 method: value = raw * 0.00488V + 0.70V
|
||||
*/
|
||||
if (sc->vrm9)
|
||||
sensor->value = (data * 4880) + 700000;
|
||||
else
|
||||
sensor->value = (data * 16000);
|
||||
}
|
||||
|
||||
void
|
||||
wb_refresh_nvolt(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int data;
|
||||
|
||||
data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
|
||||
sensor->value = ((data << 4) - WB_VREF);
|
||||
sensor->value *= sc->lm_sensors[n].rfact;
|
||||
sensor->value /= 10;
|
||||
sensor->value += WB_VREF * 1000;
|
||||
}
|
||||
|
||||
void
|
||||
wb_w83627ehf_refresh_nvolt(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int data;
|
||||
|
||||
data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
|
||||
sensor->value = ((data << 3) - WB_W83627EHF_VREF);
|
||||
sensor->value *= RFACT(232, 10);
|
||||
sensor->value /= 10;
|
||||
sensor->value += WB_W83627EHF_VREF * 1000;
|
||||
}
|
||||
|
||||
void
|
||||
wb_refresh_temp(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int sdata;
|
||||
|
||||
/*
|
||||
* The data sheet suggests that the range of the temperature
|
||||
* sensor is between -55 degC and +125 degC. However, values
|
||||
* around -48 degC seem to be a very common bogus values.
|
||||
* Since such values are unreasonably low, we use -45 degC for
|
||||
* the lower limit instead.
|
||||
*/
|
||||
sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
|
||||
sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
|
||||
if (sdata > 0x0fa && sdata < 0x1a6) {
|
||||
sensor->flags |= SENSOR_FINVALID;
|
||||
sensor->value = 0;
|
||||
} else {
|
||||
if (sdata & 0x100)
|
||||
sdata -= 0x200;
|
||||
sensor->flags &= ~SENSOR_FINVALID;
|
||||
sensor->value = sdata * 500000 + 273150000;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wb_refresh_fanrpm(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int fan, data, divisor = 0;
|
||||
|
||||
/*
|
||||
* This is madness; the fan divisor bits are scattered all
|
||||
* over the place.
|
||||
*/
|
||||
|
||||
if (sc->lm_sensors[n].reg == LM_FAN1 ||
|
||||
sc->lm_sensors[n].reg == LM_FAN2 ||
|
||||
sc->lm_sensors[n].reg == LM_FAN3) {
|
||||
data = sc->lm_readreg(sc, WB_BANK0_VBAT);
|
||||
fan = (sc->lm_sensors[n].reg - LM_FAN1);
|
||||
if ((data >> 5) & (1 << fan))
|
||||
divisor |= 0x04;
|
||||
}
|
||||
|
||||
if (sc->lm_sensors[n].reg == LM_FAN1 ||
|
||||
sc->lm_sensors[n].reg == LM_FAN2) {
|
||||
data = sc->lm_readreg(sc, LM_VIDFAN);
|
||||
if (sc->lm_sensors[n].reg == LM_FAN1)
|
||||
divisor |= (data >> 4) & 0x03;
|
||||
else
|
||||
divisor |= (data >> 6) & 0x03;
|
||||
} else if (sc->lm_sensors[n].reg == LM_FAN3) {
|
||||
data = sc->lm_readreg(sc, WB_PIN);
|
||||
divisor |= (data >> 6) & 0x03;
|
||||
} else if (sc->lm_sensors[n].reg == WB_BANK0_FAN4 ||
|
||||
sc->lm_sensors[n].reg == WB_BANK0_FAN5) {
|
||||
data = sc->lm_readreg(sc, WB_BANK0_FAN45);
|
||||
if (sc->lm_sensors[n].reg == WB_BANK0_FAN4)
|
||||
divisor |= (data >> 0) & 0x07;
|
||||
else
|
||||
divisor |= (data >> 4) & 0x07;
|
||||
}
|
||||
|
||||
data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
|
||||
if (data == 0xff || data == 0x00) {
|
||||
sensor->flags |= SENSOR_FINVALID;
|
||||
sensor->value = 0;
|
||||
} else {
|
||||
sensor->flags &= ~SENSOR_FINVALID;
|
||||
sensor->value = 1350000 / (data << divisor);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wb_w83792d_refresh_fanrpm(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int reg, shift, data, divisor = 1;
|
||||
|
||||
switch (sc->lm_sensors[n].reg) {
|
||||
case 0x28:
|
||||
reg = 0x47; shift = 0;
|
||||
break;
|
||||
case 0x29:
|
||||
reg = 0x47; shift = 4;
|
||||
break;
|
||||
case 0x2a:
|
||||
reg = 0x5b; shift = 0;
|
||||
break;
|
||||
case 0xb8:
|
||||
reg = 0x5b; shift = 4;
|
||||
break;
|
||||
case 0xb9:
|
||||
reg = 0x5c; shift = 0;
|
||||
break;
|
||||
case 0xba:
|
||||
reg = 0x5c; shift = 4;
|
||||
break;
|
||||
case 0xbe:
|
||||
reg = 0x9e; shift = 0;
|
||||
break;
|
||||
default:
|
||||
reg = 0; shift = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
data = sc->lm_readreg(sc, sc->lm_sensors[n].reg);
|
||||
if (data == 0xff || data == 0x00) {
|
||||
sensor->flags |= SENSOR_FINVALID;
|
||||
sensor->value = 0;
|
||||
} else {
|
||||
if (reg != 0)
|
||||
divisor = (sc->lm_readreg(sc, reg) >> shift) & 0x7;
|
||||
sensor->flags &= ~SENSOR_FINVALID;
|
||||
sensor->value = 1350000 / (data << divisor);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
as_refresh_temp(struct lm_softc *sc, int n)
|
||||
{
|
||||
struct ksensor *sensor = &sc->sensors[n];
|
||||
int sdata;
|
||||
|
||||
/*
|
||||
* It seems a shorted temperature diode produces an all-ones
|
||||
* bit pattern.
|
||||
*/
|
||||
sdata = sc->lm_readreg(sc, sc->lm_sensors[n].reg) << 1;
|
||||
sdata += sc->lm_readreg(sc, sc->lm_sensors[n].reg + 1) >> 7;
|
||||
if (sdata == 0x1ff) {
|
||||
sensor->flags |= SENSOR_FINVALID;
|
||||
sensor->value = 0;
|
||||
} else {
|
||||
if (sdata & 0x100)
|
||||
sdata -= 0x200;
|
||||
sensor->flags &= ~SENSOR_FINVALID;
|
||||
sensor->value = sdata * 500000 + 273150000;
|
||||
}
|
||||
}
|
251
sys/dev/lm/lm78_isa.c
Normal file
251
sys/dev/lm/lm78_isa.c
Normal file
@ -0,0 +1,251 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: lm78_isa.c,v 1.2 2007/07/01 21:48:57 cnst Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2005, 2006 Mark Kettenis
|
||||
* Copyright (c) 2007 Constantine A. Murenin, Google Summer of Code
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <isa/isavar.h>
|
||||
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <sys/sensors.h>
|
||||
|
||||
#include <dev/lm/lm78var.h>
|
||||
|
||||
/* ISA registers */
|
||||
#define LMC_ADDR 0x05
|
||||
#define LMC_DATA 0x06
|
||||
|
||||
extern struct cfdriver lm_cd;
|
||||
|
||||
#if defined(LMDEBUG)
|
||||
#define DPRINTF(x) do { printf x; } while (0)
|
||||
#else
|
||||
#define DPRINTF(x)
|
||||
#endif
|
||||
|
||||
struct lm_isa_softc {
|
||||
struct lm_softc sc_lmsc;
|
||||
|
||||
struct resource *sc_iores;
|
||||
int sc_iorid;
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_handle_t sc_ioh;
|
||||
};
|
||||
|
||||
static int lm_isa_probe(struct device *);
|
||||
static int lm_isa_attach(struct device *);
|
||||
static int lm_isa_detach(struct device *);
|
||||
u_int8_t lm_isa_readreg(struct lm_softc *, int);
|
||||
void lm_isa_writereg(struct lm_softc *, int, int);
|
||||
|
||||
static device_method_t lm_isa_methods[] = {
|
||||
/* Methods from the device interface */
|
||||
DEVMETHOD(device_probe, lm_isa_probe),
|
||||
DEVMETHOD(device_attach, lm_isa_attach),
|
||||
DEVMETHOD(device_detach, lm_isa_detach),
|
||||
|
||||
/* Terminate method list */
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t lm_isa_driver = {
|
||||
"lm",
|
||||
lm_isa_methods,
|
||||
sizeof (struct lm_isa_softc)
|
||||
};
|
||||
|
||||
static devclass_t lm_devclass;
|
||||
|
||||
DRIVER_MODULE(lm, isa, lm_isa_driver, lm_devclass, NULL, NULL);
|
||||
|
||||
int
|
||||
lm_isa_probe(struct device *dev)
|
||||
{
|
||||
struct lm_isa_softc *sc = device_get_softc(dev);
|
||||
struct resource *iores;
|
||||
int iorid = 0;
|
||||
bus_space_tag_t iot;
|
||||
bus_space_handle_t ioh;
|
||||
int banksel, vendid, chipid, addr;
|
||||
|
||||
iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &iorid,
|
||||
0ul, ~0ul, 8, RF_ACTIVE);
|
||||
if (iores == NULL) {
|
||||
DPRINTF(("%s: can't map i/o space\n", __func__));
|
||||
return (1);
|
||||
}
|
||||
iot = rman_get_bustag(iores);
|
||||
ioh = rman_get_bushandle(iores);
|
||||
|
||||
/* Probe for Winbond chips. */
|
||||
bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
|
||||
banksel = bus_space_read_1(iot, ioh, LMC_DATA);
|
||||
bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
|
||||
vendid = bus_space_read_1(iot, ioh, LMC_DATA);
|
||||
if (((banksel & 0x80) && vendid == (WB_VENDID_WINBOND >> 8)) ||
|
||||
(!(banksel & 0x80) && vendid == (WB_VENDID_WINBOND & 0xff)))
|
||||
goto found;
|
||||
|
||||
/* Probe for ITE chips (and don't attach if we find one). */
|
||||
bus_space_write_1(iot, ioh, LMC_ADDR, 0x58 /*ITD_CHIPID*/);
|
||||
vendid = bus_space_read_1(iot, ioh, LMC_DATA);
|
||||
if (vendid == 0x90 /*IT_ID_IT87*/)
|
||||
goto notfound;
|
||||
|
||||
/*
|
||||
* Probe for National Semiconductor LM78/79/81.
|
||||
*
|
||||
* XXX This assumes the address has not been changed from the
|
||||
* power up default. This is probably a reasonable
|
||||
* assumption, and if it isn't true, we should be able to
|
||||
* access the chip using the serial bus.
|
||||
*/
|
||||
bus_space_write_1(iot, ioh, LMC_ADDR, LM_SBUSADDR);
|
||||
addr = bus_space_read_1(iot, ioh, LMC_DATA);
|
||||
if ((addr & 0xfc) == 0x2c) {
|
||||
bus_space_write_1(iot, ioh, LMC_ADDR, LM_CHIPID);
|
||||
chipid = bus_space_read_1(iot, ioh, LMC_DATA);
|
||||
|
||||
switch (chipid & LM_CHIPID_MASK) {
|
||||
case LM_CHIPID_LM78:
|
||||
case LM_CHIPID_LM78J:
|
||||
case LM_CHIPID_LM79:
|
||||
case LM_CHIPID_LM81:
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
notfound:
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores);
|
||||
|
||||
return (1);
|
||||
|
||||
found:
|
||||
/* Bus-independent probe */
|
||||
sc->sc_lmsc.sc_dev = dev;
|
||||
sc->sc_iot = iot;
|
||||
sc->sc_ioh = ioh;
|
||||
sc->sc_lmsc.lm_writereg = lm_isa_writereg;
|
||||
sc->sc_lmsc.lm_readreg = lm_isa_readreg;
|
||||
lm_probe(&sc->sc_lmsc);
|
||||
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores);
|
||||
sc->sc_iot = 0;
|
||||
sc->sc_ioh = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
lm_isa_attach(struct device *dev)
|
||||
{
|
||||
struct lm_isa_softc *sc = device_get_softc(dev);
|
||||
#ifdef notyet
|
||||
struct lm_softc *lmsc;
|
||||
int i;
|
||||
u_int8_t sbusaddr;
|
||||
#endif
|
||||
|
||||
sc->sc_iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_iorid,
|
||||
0ul, ~0ul, 8, RF_ACTIVE);
|
||||
if (sc->sc_iores == NULL) {
|
||||
device_printf(dev, "can't map i/o space\n");
|
||||
return (1);
|
||||
}
|
||||
sc->sc_iot = rman_get_bustag(sc->sc_iores);
|
||||
sc->sc_ioh = rman_get_bushandle(sc->sc_iores);
|
||||
|
||||
/* Bus-independent attachment */
|
||||
lm_attach(&sc->sc_lmsc);
|
||||
|
||||
#ifdef notyet
|
||||
/*
|
||||
* Most devices supported by this driver can attach to iic(4)
|
||||
* as well. However, we prefer to attach them to isa(4) since
|
||||
* that causes less overhead and is more reliable. We look
|
||||
* through all previously attached devices, and if we find an
|
||||
* identical chip at the same serial bus address, we stop
|
||||
* updating its sensors and mark them as invalid.
|
||||
*/
|
||||
|
||||
sbusaddr = lm_isa_readreg(&sc->sc_lmsc, LM_SBUSADDR);
|
||||
if (sbusaddr == 0)
|
||||
return (0);
|
||||
|
||||
for (i = 0; i < lm_cd.cd_ndevs; i++) {
|
||||
lmsc = lm_cd.cd_devs[i];
|
||||
if (lmsc == &sc->sc_lmsc)
|
||||
continue;
|
||||
if (lmsc && lmsc->sbusaddr == sbusaddr &&
|
||||
lmsc->chipid == sc->sc_lmsc.chipid)
|
||||
config_detach(&lmsc->sc_dev, 0);
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
lm_isa_detach(struct device *dev)
|
||||
{
|
||||
struct lm_isa_softc *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
/* Bus-independent detachment */
|
||||
error = lm_detach(&sc->sc_lmsc);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_iorid,
|
||||
sc->sc_iores);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
u_int8_t
|
||||
lm_isa_readreg(struct lm_softc *lmsc, int reg)
|
||||
{
|
||||
struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
|
||||
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
|
||||
return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, LMC_DATA));
|
||||
}
|
||||
|
||||
void
|
||||
lm_isa_writereg(struct lm_softc *lmsc, int reg, int val)
|
||||
{
|
||||
struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
|
||||
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_DATA, val);
|
||||
}
|
158
sys/dev/lm/lm78var.h
Normal file
158
sys/dev/lm/lm78var.h
Normal file
@ -0,0 +1,158 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: lm78var.h,v 1.12 2007/05/25 02:26:43 cnst Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2005, 2006 Mark Kettenis
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* National Semiconductor LM78/79/81 registers
|
||||
*/
|
||||
|
||||
#define LM_POST_RAM 0x00 /* POST RAM occupies 0x00 -- 0x1f */
|
||||
#define LM_VALUE_RAM 0x20 /* Value RAM occupies 0x20 -- 0x3f */
|
||||
#define LM_FAN1 0x28 /* FAN1 reading */
|
||||
#define LM_FAN2 0x29 /* FAN2 reading */
|
||||
#define LM_FAN3 0x2a /* FAN3 reading */
|
||||
|
||||
#define LM_CONFIG 0x40 /* Configuration */
|
||||
#define LM_ISR1 0x41 /* Interrupt Status 1 */
|
||||
#define LM_ISR2 0x42 /* Interrupt Status 2 */
|
||||
#define LM_SMI1 0x43 /* SMI# Mask 1 */
|
||||
#define LM_SMI2 0x44 /* SMI# Mask 2 */
|
||||
#define LM_NMI1 0x45 /* NMI Mask 1 */
|
||||
#define LM_NMI2 0x46 /* NMI Mask 2 */
|
||||
#define LM_VIDFAN 0x47 /* VID/Fan Divisor */
|
||||
#define LM_SBUSADDR 0x48 /* Serial Bus Address */
|
||||
#define LM_CHIPID 0x49 /* Chip Reset/ID */
|
||||
|
||||
/* Chip IDs */
|
||||
|
||||
#define LM_CHIPID_LM78 0x00
|
||||
#define LM_CHIPID_LM78J 0x40
|
||||
#define LM_CHIPID_LM79 0xC0
|
||||
#define LM_CHIPID_LM81 0x80
|
||||
#define LM_CHIPID_MASK 0xfe
|
||||
|
||||
/*
|
||||
* Winbond registers
|
||||
*
|
||||
* Several models exists. The W83781D is mostly compatible with the
|
||||
* LM78, but has two extra temperatures. Later models add extra
|
||||
* voltage sensors, fans and bigger fan divisors to accomodate slow
|
||||
* running fans. To accomodate the extra sensors some models have
|
||||
* different memory banks.
|
||||
*/
|
||||
|
||||
#define WB_T23ADDR 0x4a /* Temperature 2 and 3 Serial Bus Address */
|
||||
#define WB_PIN 0x4b /* Pin Control */
|
||||
#define WB_BANKSEL 0x4e /* Bank Select */
|
||||
#define WB_VENDID 0x4f /* Vendor ID */
|
||||
|
||||
/* Bank 0 regs */
|
||||
#define WB_BANK0_CHIPID 0x58 /* Chip ID */
|
||||
#define WB_BANK0_FAN45 0x5c /* Fan 4/5 Divisor Control (W83791D only) */
|
||||
#define WB_BANK0_VBAT 0x5d /* VBAT Monitor Control */
|
||||
#define WB_BANK0_FAN4 0xba /* Fan 4 reading (W83791D only) */
|
||||
#define WB_BANK0_FAN5 0xbb /* Fan 5 reading (W83791D only) */
|
||||
|
||||
#define WB_BANK0_CONFIG 0x18 /* VRM & OVT Config (W83627THF/W83637HF) */
|
||||
|
||||
/* Bank 1 registers */
|
||||
#define WB_BANK1_T2H 0x50 /* Temperature 2 High Byte */
|
||||
#define WB_BANK1_T2L 0x51 /* Temperature 2 Low Byte */
|
||||
|
||||
/* Bank 2 registers */
|
||||
#define WB_BANK2_T3H 0x50 /* Temperature 3 High Byte */
|
||||
#define WB_BANK2_T3L 0x51 /* Temperature 3 Low Byte */
|
||||
|
||||
/* Bank 4 registers (W83782D/W83627HF and later models only) */
|
||||
#define WB_BANK4_T1OFF 0x54 /* Temperature 1 Offset */
|
||||
#define WB_BANK4_T2OFF 0x55 /* Temperature 2 Offset */
|
||||
#define WB_BANK4_T3OFF 0x56 /* Temperature 3 Offset */
|
||||
|
||||
/* Bank 5 registers (W83782D/W83627HF and later models only) */
|
||||
#define WB_BANK5_5VSB 0x50 /* 5VSB reading */
|
||||
#define WB_BANK5_VBAT 0x51 /* VBAT reading */
|
||||
|
||||
/* Bank selection */
|
||||
#define WB_BANKSEL_B0 0x00 /* Bank 0 */
|
||||
#define WB_BANKSEL_B1 0x01 /* Bank 1 */
|
||||
#define WB_BANKSEL_B2 0x02 /* Bank 2 */
|
||||
#define WB_BANKSEL_B3 0x03 /* Bank 3 */
|
||||
#define WB_BANKSEL_B4 0x04 /* Bank 4 */
|
||||
#define WB_BANKSEL_B5 0x05 /* Bank 5 */
|
||||
#define WB_BANKSEL_HBAC 0x80 /* Register 0x4f High Byte Access */
|
||||
|
||||
/* Vendor IDs */
|
||||
#define WB_VENDID_WINBOND 0x5ca3 /* Winbond */
|
||||
#define WB_VENDID_ASUS 0x12c3 /* ASUS */
|
||||
|
||||
/* Chip IDs */
|
||||
#define WB_CHIPID_W83781D 0x10
|
||||
#define WB_CHIPID_W83781D_2 0x11
|
||||
#define WB_CHIPID_W83627HF 0x21
|
||||
#define WB_CHIPID_AS99127F 0x31 /* Asus W83781D clone */
|
||||
#define WB_CHIPID_W83782D 0x30
|
||||
#define WB_CHIPID_W83783S 0x40
|
||||
#define WB_CHIPID_W83697HF 0x60
|
||||
#define WB_CHIPID_W83791D 0x71
|
||||
#define WB_CHIPID_W83791SD 0x72
|
||||
#define WB_CHIPID_W83792D 0x7a
|
||||
#define WB_CHIPID_W83637HF 0x80
|
||||
#define WB_CHIPID_W83627THF 0x90
|
||||
#define WB_CHIPID_W83627EHF 0xa1
|
||||
#define WB_CHIPID_W83627DHG 0xc1
|
||||
|
||||
/* Config bits */
|
||||
#define WB_CONFIG_VMR9 0x01
|
||||
|
||||
/* Reference voltage (mV) */
|
||||
#define WB_VREF 3600
|
||||
#define WB_W83627EHF_VREF 2048
|
||||
|
||||
#define WB_MAX_SENSORS 19
|
||||
|
||||
struct lm_softc;
|
||||
|
||||
struct lm_sensor {
|
||||
char *desc;
|
||||
enum sensor_type type;
|
||||
u_int8_t bank;
|
||||
u_int8_t reg;
|
||||
void (*refresh)(struct lm_softc *, int);
|
||||
int rfact;
|
||||
};
|
||||
|
||||
struct lm_softc {
|
||||
struct device *sc_dev;
|
||||
|
||||
struct ksensor sensors[WB_MAX_SENSORS];
|
||||
struct ksensordev sensordev;
|
||||
struct lm_sensor *lm_sensors;
|
||||
u_int numsensors;
|
||||
void (*refresh_sensor_data) (struct lm_softc *);
|
||||
|
||||
u_int8_t (*lm_readreg)(struct lm_softc *, int);
|
||||
void (*lm_writereg)(struct lm_softc *, int, int);
|
||||
|
||||
u_int8_t sbusaddr;
|
||||
u_int8_t chipid;
|
||||
u_int8_t vrm9;
|
||||
};
|
||||
|
||||
void lm_probe(struct lm_softc *);
|
||||
void lm_attach(struct lm_softc *);
|
||||
int lm_detach(struct lm_softc *);
|
@ -76,3 +76,11 @@ hint.le.0.disabled="1"
|
||||
hint.le.0.port="0x280"
|
||||
hint.le.0.irq="10"
|
||||
hint.le.0.drq="0"
|
||||
hint.lm.0.at="isa"
|
||||
hint.lm.0.port="0x290"
|
||||
hint.it.0.at="isa"
|
||||
hint.it.0.port="0x290"
|
||||
hint.it.1.at="isa"
|
||||
hint.it.1.port="0xc00"
|
||||
hint.it.2.at="isa"
|
||||
hint.it.2.port="0xd00"
|
||||
|
@ -131,6 +131,7 @@ SUBDIR= ${_3dfx} \
|
||||
iscsi \
|
||||
isp \
|
||||
ispfw \
|
||||
${_it} \
|
||||
${_iwi} \
|
||||
${_iwifw} \
|
||||
${_ixgb} \
|
||||
@ -146,6 +147,7 @@ SUBDIR= ${_3dfx} \
|
||||
${_linprocfs} \
|
||||
${_linsysfs} \
|
||||
${_linux} \
|
||||
${_lm} \
|
||||
lmc \
|
||||
lpt \
|
||||
mac_biba \
|
||||
@ -453,9 +455,11 @@ _ipmi= ipmi
|
||||
_ips= ips
|
||||
_ipw= ipw
|
||||
_ipwfw= ipwfw
|
||||
_it= it
|
||||
_iwi= iwi
|
||||
_iwifw= iwifw
|
||||
_ixgb= ixgb
|
||||
_lm= lm
|
||||
_mly= mly
|
||||
_nfe= nfe
|
||||
_nve= nve
|
||||
@ -511,10 +515,12 @@ _ipmi= ipmi
|
||||
_ips= ips
|
||||
_ipw= ipw
|
||||
_ipwfw= ipwfw
|
||||
_it= it
|
||||
_ixgb= ixgb
|
||||
_linprocfs= linprocfs
|
||||
_linsysfs= linsysfs
|
||||
_linux= linux
|
||||
_lm= lm
|
||||
_mly= mly
|
||||
_ndis= ndis
|
||||
_nfe= nfe
|
||||
|
9
sys/modules/it/Makefile
Normal file
9
sys/modules/it/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../dev/it
|
||||
|
||||
KMOD= it
|
||||
SRCS= it.c
|
||||
SRCS+= device_if.h bus_if.h isa_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
9
sys/modules/lm/Makefile
Normal file
9
sys/modules/lm/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../dev/lm
|
||||
|
||||
KMOD= lm
|
||||
SRCS= lm78.c lm78_isa.c
|
||||
SRCS+= device_if.h bus_if.h isa_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
Loading…
Reference in New Issue
Block a user