Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/it8613hwm/it8613hwm.c
- This file was added.
#include <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <sys/param.h> | |||||
#include <sys/kernel.h> | |||||
#include <sys/bus.h> | |||||
#include <sys/module.h> | |||||
#include <sys/rman.h> | |||||
#include <sys/sysctl.h> | |||||
#include <sys/mutex.h> | |||||
#include <dev/superio/superio.h> | |||||
#include <machine/bus.h> | |||||
#include <machine/resource.h> | |||||
struct it8613hwm_softc { | |||||
struct resource* ioport_res; | |||||
int ioport_rid; | |||||
struct mtx lock; | |||||
}; | |||||
static int it8613hwm_get_temp_sysctl(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
device_t dev = (device_t) arg1; | |||||
struct it8613hwm_softc* sc = device_get_softc(dev); | |||||
int tempindex = arg2; | |||||
int val = 0; | |||||
if (tempindex >= 0 && tempindex < 3) | |||||
{ | |||||
mtx_lock(&sc->lock); | |||||
bus_write_1(sc->ioport_res, 0, 0x29 + tempindex); | |||||
uint8_t temp_celsius = bus_read_1(sc->ioport_res, 1); | |||||
val = temp_celsius + 273; | |||||
mtx_unlock(&sc->lock); | |||||
} | |||||
// FIXME: bunch of magic parameters coming via SYSCTL_HANDLER_ARGS | |||||
return sysctl_handle_int(oidp, &val, 0, req); | |||||
} | |||||
static int it8613hwm_probe(device_t dev) | |||||
{ | |||||
device_printf(dev, "it8613hwm_probe\n"); | |||||
if (superio_vendor(dev) != SUPERIO_VENDOR_ITE) | |||||
return (ENXIO); | |||||
if (superio_get_type(dev) != SUPERIO_DEV_HWM) | |||||
return (ENXIO); | |||||
if (superio_devid(dev) != 0x8613) | |||||
return (ENXIO); | |||||
device_set_desc(dev, "Hardware monitor on ITE SuperIO"); | |||||
return (BUS_PROBE_DEFAULT); | |||||
} | |||||
static int it8613hwm_attach(device_t dev) | |||||
{ | |||||
// debug | |||||
device_printf(dev, "it8613hwm_attach\n"); | |||||
struct it8613hwm_softc* sc = device_get_softc(dev); | |||||
mtx_init(&sc->lock, device_get_nameunit(dev), "it8613hwm", MTX_DEF); | |||||
uint16_t iobase = superio_get_iobase(dev); | |||||
// debug | |||||
device_printf(dev, "it8613hwm iobase: %i\n", iobase); | |||||
int error = bus_set_resource(dev, SYS_RES_IOPORT, sc->ioport_rid, iobase + 5, 2); | |||||
if (error != 0) | |||||
{ | |||||
device_printf(dev, "bus_set_resource failed\n"); | |||||
mtx_destroy(&sc->lock); | |||||
return (ENXIO); | |||||
} | |||||
sc->ioport_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->ioport_rid, RF_ACTIVE); | |||||
if (sc->ioport_res == NULL) | |||||
{ | |||||
device_printf(dev, "bus_alloc_resource_any failed\n"); | |||||
mtx_destroy(&sc->lock); | |||||
return (ENXIO); | |||||
} | |||||
// check hardware monitor id... this should be 0x90 for the it8613 | |||||
bus_write_1(sc->ioport_res, 0, 0x58); // chip id register | |||||
uint8_t chipid = bus_read_1(sc->ioport_res, 1); | |||||
if (chipid != 0x90) | |||||
{ | |||||
device_printf(dev, "unexpected chip id: actual %i != expected %i\n", chipid, 0x90); | |||||
bus_release_resource(dev, SYS_RES_IOPORT, sc->ioport_rid, sc->ioport_res); | |||||
mtx_destroy(&sc->lock); | |||||
return (ENXIO); | |||||
} | |||||
struct sysctl_ctx_list* ctx = device_get_sysctl_ctx(dev); | |||||
// gets us "dev.it8613hwm.0.temperature0" | |||||
SYSCTL_ADD_PROC(ctx, | |||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), // FIXME: this device parent vs sysctl parent thing is confusing | |||||
OID_AUTO, | |||||
"temperature0", | |||||
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, | |||||
dev, 0, // arg1 and arg2 | |||||
it8613hwm_get_temp_sysctl, | |||||
"IK0", | |||||
"Temperature sensor 0"); | |||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "temperature1", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 1, it8613hwm_get_temp_sysctl, "IK0", "Temperature sensor 1"); | |||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "temperature2", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 2, it8613hwm_get_temp_sysctl, "IK0", "Temperature sensor 2"); | |||||
return (0); | |||||
} | |||||
static int it8613hwm_detach(device_t dev) | |||||
{ | |||||
struct it8613hwm_softc* sc = device_get_softc(dev); | |||||
device_printf(dev, "it8613hwm_detach\n"); | |||||
bus_release_resource(dev, SYS_RES_IOPORT, sc->ioport_rid, sc->ioport_res); | |||||
mtx_destroy(&sc->lock); | |||||
return (0); | |||||
} | |||||
static device_method_t it8613hwm_methods[] = { | |||||
/* Methods from the device interface */ | |||||
DEVMETHOD(device_probe, it8613hwm_probe), | |||||
DEVMETHOD(device_attach, it8613hwm_attach), | |||||
DEVMETHOD(device_detach, it8613hwm_detach), | |||||
/* Terminate method list */ | |||||
{ 0, 0 } | |||||
}; | |||||
static driver_t it8613hwm_driver = { | |||||
"it8613hwm", | |||||
it8613hwm_methods, | |||||
sizeof(struct it8613hwm_softc) | |||||
}; | |||||
static devclass_t it8613hwm_devclass; | |||||
DRIVER_MODULE(it8613hwm, superio, it8613hwm_driver, it8613hwm_devclass, NULL, NULL); | |||||
MODULE_DEPEND(it8613hwm, superio, 1, 1, 1); | |||||
MODULE_VERSION(it8613hwm, 1); |