diff --git a/sys/dev/it8613hwm/it8613hwm.c b/sys/dev/it8613hwm/it8613hwm.c new file mode 100644 --- /dev/null +++ b/sys/dev/it8613hwm/it8613hwm.c @@ -0,0 +1,151 @@ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +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); diff --git a/sys/dev/superio/superio.c b/sys/dev/superio/superio.c --- a/sys/dev/superio/superio.c +++ b/sys/dev/superio/superio.c @@ -269,6 +269,11 @@ { .type = SUPERIO_DEV_NONE }, }; +const struct sio_device itehwm_devices[] = { + { .ldn = 4, .type = SUPERIO_DEV_HWM }, + { .type = SUPERIO_DEV_NONE }, +}; + const struct sio_device nvt_devices[] = { { .ldn = 8, .type = SUPERIO_DEV_WDT }, { .type = SUPERIO_DEV_NONE }, @@ -293,6 +298,10 @@ const char *descr; const struct sio_device *devices; } superio_table[] = { + { + .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8613, + .devices = itehwm_devices, + }, { .vendor = SUPERIO_VENDOR_ITE, .devid = 0x8712, .devices = ite_devices, diff --git a/sys/modules/Makefile b/sys/modules/Makefile --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -192,6 +192,7 @@ ${_iser} \ isp \ ${_ispfw} \ + ${_it8613hwm} \ ${_itwd} \ ${_iwi} \ ${_iwifw} \ @@ -685,6 +686,7 @@ _if_ndis= if_ndis _igc= igc _io= io +_it8613hwm= it8613hwm _itwd= itwd _ix= ix _ixv= ixv diff --git a/sys/modules/it8613hwm/Makefile b/sys/modules/it8613hwm/Makefile new file mode 100644 --- /dev/null +++ b/sys/modules/it8613hwm/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/dev/it8613hwm + +KMOD= it8613hwm +SRCS= it8613hwm.c +SRCS+= device_if.h bus_if.h isa_if.h + +.include