aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/asmc/asmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/asmc/asmc.c')
-rw-r--r--sys/dev/asmc/asmc.c696
1 files changed, 487 insertions, 209 deletions
diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c
index d99c1d56e67c..4a6734e22786 100644
--- a/sys/dev/asmc/asmc.c
+++ b/sys/dev/asmc/asmc.c
@@ -34,6 +34,8 @@
* Inspired by the Linux applesmc driver.
*/
+#include "opt_asmc.h"
+
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
@@ -49,12 +51,16 @@
#include <sys/rman.h>
#include <machine/resource.h>
+#include <netinet/in.h>
#include <contrib/dev/acpica/include/acpi.h>
#include <dev/acpica/acpivar.h>
#include <dev/asmc/asmcvar.h>
+#include <dev/backlight/backlight.h>
+#include "backlight_if.h"
+
/*
* Device interface.
*/
@@ -64,6 +70,15 @@ static int asmc_detach(device_t dev);
static int asmc_resume(device_t dev);
/*
+ * Backlight interface.
+ */
+static int asmc_backlight_update_status(device_t dev,
+ struct backlight_props *props);
+static int asmc_backlight_get_status(device_t dev,
+ struct backlight_props *props);
+static int asmc_backlight_get_info(device_t dev, struct backlight_info *info);
+
+/*
* SMC functions.
*/
static int asmc_init(device_t dev);
@@ -83,7 +98,7 @@ static void asmc_sms_calibrate(device_t dev);
static int asmc_sms_intrfast(void *arg);
static void asmc_sms_printintr(device_t dev, uint8_t);
static void asmc_sms_task(void *arg, int pending);
-#ifdef DEBUG
+#ifdef ASMC_DEBUG
void asmc_dumpall(device_t);
static int asmc_key_dump(device_t, int);
#endif
@@ -97,6 +112,7 @@ static int asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS);
+static int asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS);
static int asmc_temp_sysctl(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS);
@@ -105,10 +121,11 @@ static int asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS);
static int asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS);
static int asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS);
static int asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS);
+static int asmc_wol_sysctl(SYSCTL_HANDLER_ARGS);
struct asmc_model {
- const char *smc_model; /* smbios.system.product env var. */
- const char *smc_desc; /* driver description */
+ const char *smc_model; /* smbios.system.product env var. */
+ const char *smc_desc; /* driver description */
/* Helper functions */
int (*smc_sms_x)(SYSCTL_HANDLER_ARGS);
@@ -131,48 +148,68 @@ struct asmc_model {
static const struct asmc_model *asmc_match(device_t dev);
-#define ASMC_SMS_FUNCS asmc_mb_sysctl_sms_x, asmc_mb_sysctl_sms_y, \
- asmc_mb_sysctl_sms_z
-
-#define ASMC_SMS_FUNCS_DISABLED NULL,NULL,NULL
-
-#define ASMC_FAN_FUNCS asmc_mb_sysctl_fanid, asmc_mb_sysctl_fanspeed, asmc_mb_sysctl_fansafespeed, \
- asmc_mb_sysctl_fanminspeed, \
- asmc_mb_sysctl_fanmaxspeed, \
- asmc_mb_sysctl_fantargetspeed
-
-#define ASMC_FAN_FUNCS2 asmc_mb_sysctl_fanid, asmc_mb_sysctl_fanspeed, NULL, \
- asmc_mb_sysctl_fanminspeed, \
- asmc_mb_sysctl_fanmaxspeed, \
- asmc_mb_sysctl_fantargetspeed
-
-#define ASMC_LIGHT_FUNCS asmc_mbp_sysctl_light_left, \
- asmc_mbp_sysctl_light_right, \
- asmc_mbp_sysctl_light_control
+#define ASMC_SMS_FUNCS \
+ .smc_sms_x = asmc_mb_sysctl_sms_x, \
+ .smc_sms_y = asmc_mb_sysctl_sms_y, \
+ .smc_sms_z = asmc_mb_sysctl_sms_z
+
+#define ASMC_SMS_FUNCS_DISABLED \
+ .smc_sms_x = NULL, \
+ .smc_sms_y = NULL, \
+ .smc_sms_z = NULL
+
+#define ASMC_FAN_FUNCS \
+ .smc_fan_id = asmc_mb_sysctl_fanid, \
+ .smc_fan_speed = asmc_mb_sysctl_fanspeed, \
+ .smc_fan_safespeed = asmc_mb_sysctl_fansafespeed, \
+ .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \
+ .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \
+ .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed
+
+#define ASMC_FAN_FUNCS2 \
+ .smc_fan_id = asmc_mb_sysctl_fanid, \
+ .smc_fan_speed = asmc_mb_sysctl_fanspeed, \
+ .smc_fan_safespeed = NULL, \
+ .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \
+ .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \
+ .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed
+
+#define ASMC_LIGHT_FUNCS \
+ .smc_light_left = asmc_mbp_sysctl_light_left, \
+ .smc_light_right = asmc_mbp_sysctl_light_right, \
+ .smc_light_control = asmc_mbp_sysctl_light_control
#define ASMC_LIGHT_FUNCS_10BYTE \
- asmc_mbp_sysctl_light_left_10byte, \
- NULL, \
- asmc_mbp_sysctl_light_control
+ .smc_light_left = asmc_mbp_sysctl_light_left_10byte, \
+ .smc_light_right = NULL, \
+ .smc_light_control = asmc_mbp_sysctl_light_control
-#define ASMC_LIGHT_FUNCS_DISABLED NULL, NULL, NULL
+#define ASMC_LIGHT_FUNCS_DISABLED \
+ .smc_light_left = NULL, \
+ .smc_light_right = NULL, \
+ .smc_light_control = NULL
+
+#define ASMC_TEMPS_FUNCS_DISABLED \
+ .smc_temps = {}, \
+ .smc_tempnames = {}, \
+ .smc_tempdescs = {} \
static const struct asmc_model asmc_models[] = {
{
"MacBook1,1", "Apple SMC MacBook Core Duo",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL,
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS
},
{
"MacBook2,1", "Apple SMC MacBook Core 2 Duo",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL,
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS
},
{
"MacBook3,1", "Apple SMC MacBook Core 2 Duo",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL,
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MB31_TEMPS, ASMC_MB31_TEMPNAMES, ASMC_MB31_TEMPDESCS
},
@@ -255,6 +292,12 @@ static const struct asmc_model asmc_models[] = {
},
{
+ "MacBookPro8,3", "Apple SMC MacBook Pro (early 2011, 17-inch)",
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
+ ASMC_MBP83_TEMPS, ASMC_MBP83_TEMPNAMES, ASMC_MBP83_TEMPDESCS
+ },
+
+ {
"MacBookPro9,1", "Apple SMC MacBook Pro (mid 2012, 15-inch)",
ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
ASMC_MBP91_TEMPS, ASMC_MBP91_TEMPNAMES, ASMC_MBP91_TEMPDESCS
@@ -280,16 +323,23 @@ static const struct asmc_model asmc_models[] = {
{
"MacBookPro11,4", "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch)",
- ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
+ ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
ASMC_MBP114_TEMPS, ASMC_MBP114_TEMPNAMES, ASMC_MBP114_TEMPDESCS
},
+ {
+ "MacBookPro11,5",
+ "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch, AMD GPU)",
+ ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS,
+ ASMC_MBP115_TEMPS, ASMC_MBP115_TEMPNAMES, ASMC_MBP115_TEMPDESCS
+ },
+
/* The Mac Mini has no SMS */
{
"Macmini1,1", "Apple SMC Mac Mini",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MM_TEMPS, ASMC_MM_TEMPNAMES, ASMC_MM_TEMPDESCS
},
@@ -305,9 +355,9 @@ static const struct asmc_model asmc_models[] = {
/* The Mac Mini 3,1 has no SMS */
{
"Macmini3,1", "Apple SMC Mac Mini 3,1",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MM31_TEMPS, ASMC_MM31_TEMPNAMES, ASMC_MM31_TEMPDESCS
},
@@ -315,7 +365,7 @@ static const struct asmc_model asmc_models[] = {
{
"Macmini4,1", "Apple SMC Mac mini 4,1 (Mid-2010)",
ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS,
+ ASMC_FAN_FUNCS2,
ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MM41_TEMPS, ASMC_MM41_TEMPNAMES, ASMC_MM41_TEMPDESCS
},
@@ -324,18 +374,18 @@ static const struct asmc_model asmc_models[] = {
/* - same sensors as Mac Mini 5,2 */
{
"Macmini5,1", "Apple SMC Mac Mini 5,1",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS2,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS
},
/* The Mac Mini 5,2 has no SMS */
{
"Macmini5,2", "Apple SMC Mac Mini 5,2",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS2,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS
},
@@ -343,63 +393,72 @@ static const struct asmc_model asmc_models[] = {
/* - same sensors as Mac Mini 5,2 */
{
"Macmini5,3", "Apple SMC Mac Mini 5,3",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS2,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS
},
/* The Mac Mini 6,1 has no SMS */
{
"Macmini6,1", "Apple SMC Mac Mini 6,1",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS2,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MM61_TEMPS, ASMC_MM61_TEMPNAMES, ASMC_MM61_TEMPDESCS
},
/* The Mac Mini 6,2 has no SMS */
{
"Macmini6,2", "Apple SMC Mac Mini 6,2",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS2,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MM62_TEMPS, ASMC_MM62_TEMPNAMES, ASMC_MM62_TEMPDESCS
},
/* The Mac Mini 7,1 has no SMS */
{
"Macmini7,1", "Apple SMC Mac Mini 7,1",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS2,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MM71_TEMPS, ASMC_MM71_TEMPNAMES, ASMC_MM71_TEMPDESCS
},
/* Idem for the Mac Pro "Quad Core" (original) */
{
"MacPro1,1", "Apple SMC Mac Pro (Quad Core)",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MP1_TEMPS, ASMC_MP1_TEMPNAMES, ASMC_MP1_TEMPDESCS
},
+ /* Idem for the Mac Pro (Early 2008) */
+ {
+ "MacPro3,1", "Apple SMC Mac Pro (Early 2008)",
+ ASMC_SMS_FUNCS_DISABLED,
+ ASMC_FAN_FUNCS,
+ ASMC_LIGHT_FUNCS_DISABLED,
+ ASMC_MP31_TEMPS, ASMC_MP31_TEMPNAMES, ASMC_MP31_TEMPDESCS
+ },
+
/* Idem for the Mac Pro (8-core) */
{
"MacPro2", "Apple SMC Mac Pro (8-core)",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MP2_TEMPS, ASMC_MP2_TEMPNAMES, ASMC_MP2_TEMPDESCS
},
/* Idem for the MacPro 2010*/
{
"MacPro5,1", "Apple SMC MacPro (2010)",
- NULL, NULL, NULL,
+ ASMC_SMS_FUNCS_DISABLED,
ASMC_FAN_FUNCS,
- NULL, NULL, NULL,
+ ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MP5_TEMPS, ASMC_MP5_TEMPNAMES, ASMC_MP5_TEMPDESCS
},
@@ -414,20 +473,20 @@ static const struct asmc_model asmc_models[] = {
{
"MacBookAir1,1", "Apple SMC MacBook Air",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL,
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MBA_TEMPS, ASMC_MBA_TEMPNAMES, ASMC_MBA_TEMPDESCS
},
{
"MacBookAir3,1", "Apple SMC MacBook Air Core 2 Duo (Late 2010)",
- ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL,
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED,
ASMC_MBA3_TEMPS, ASMC_MBA3_TEMPNAMES, ASMC_MBA3_TEMPDESCS
},
{
"MacBookAir4,1", "Apple SMC Macbook Air 11-inch (Mid 2011)",
ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
+ ASMC_FAN_FUNCS2,
ASMC_LIGHT_FUNCS,
ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS
},
@@ -435,7 +494,7 @@ static const struct asmc_model asmc_models[] = {
{
"MacBookAir4,2", "Apple SMC Macbook Air 13-inch (Mid 2011)",
ASMC_SMS_FUNCS_DISABLED,
- ASMC_FAN_FUNCS2,
+ ASMC_FAN_FUNCS2,
ASMC_LIGHT_FUNCS,
ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS
},
@@ -482,8 +541,42 @@ static const struct asmc_model asmc_models[] = {
ASMC_FAN_FUNCS2,
ASMC_LIGHT_FUNCS,
ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS
+ }
+};
+
+static const struct asmc_model asmc_generic_models[] = {
+ {
+ .smc_model = "MacBookAir",
+ .smc_desc = NULL,
+ ASMC_SMS_FUNCS_DISABLED,
+ ASMC_FAN_FUNCS2,
+ ASMC_LIGHT_FUNCS,
+ ASMC_TEMPS_FUNCS_DISABLED
},
- { NULL, NULL }
+ {
+ .smc_model = "MacBookPro",
+ .smc_desc = NULL,
+ ASMC_SMS_FUNCS_DISABLED,
+ ASMC_FAN_FUNCS2,
+ ASMC_LIGHT_FUNCS,
+ ASMC_TEMPS_FUNCS_DISABLED
+ },
+ {
+ .smc_model = "MacPro",
+ .smc_desc = NULL,
+ ASMC_SMS_FUNCS_DISABLED,
+ ASMC_FAN_FUNCS2,
+ ASMC_LIGHT_FUNCS_DISABLED,
+ ASMC_TEMPS_FUNCS_DISABLED
+ },
+ {
+ .smc_model = "Macmini",
+ .smc_desc = NULL,
+ ASMC_SMS_FUNCS_DISABLED,
+ ASMC_FAN_FUNCS2,
+ ASMC_LIGHT_FUNCS_DISABLED,
+ ASMC_TEMPS_FUNCS_DISABLED
+ }
};
#undef ASMC_SMS_FUNCS
@@ -500,7 +593,13 @@ static device_method_t asmc_methods[] = {
DEVMETHOD(device_attach, asmc_attach),
DEVMETHOD(device_detach, asmc_detach),
DEVMETHOD(device_resume, asmc_resume),
- { 0, 0 }
+
+ /* Backlight interface */
+ DEVMETHOD(backlight_update_status, asmc_backlight_update_status),
+ DEVMETHOD(backlight_get_status, asmc_backlight_get_status),
+ DEVMETHOD(backlight_get_info, asmc_backlight_get_info),
+
+ DEVMETHOD_END
};
static driver_t asmc_driver = {
@@ -514,10 +613,10 @@ static driver_t asmc_driver = {
*/
#define _COMPONENT ACPI_OEM
ACPI_MODULE_NAME("ASMC")
-#ifdef DEBUG
-#define ASMC_DPRINTF(str) device_printf(dev, str)
+#ifdef ASMC_DEBUG
+#define ASMC_DPRINTF(str, ...) device_printf(dev, str, ##__VA_ARGS__)
#else
-#define ASMC_DPRINTF(str)
+#define ASMC_DPRINTF(str, ...)
#endif
/* NB: can't be const */
@@ -525,34 +624,49 @@ static char *asmc_ids[] = { "APP0001", NULL };
static unsigned int light_control = 0;
+ACPI_PNP_INFO(asmc_ids);
DRIVER_MODULE(asmc, acpi, asmc_driver, NULL, NULL);
MODULE_DEPEND(asmc, acpi, 1, 1, 1);
+MODULE_DEPEND(asmc, backlight, 1, 1, 1);
static const struct asmc_model *
asmc_match(device_t dev)
{
+ const struct asmc_model *model;
+ char *model_name;
int i;
- char *model;
- model = kern_getenv("smbios.system.product");
- if (model == NULL)
- return (NULL);
+ model = NULL;
+
+ model_name = kern_getenv("smbios.system.product");
+ if (model_name == NULL)
+ goto out;
- for (i = 0; asmc_models[i].smc_model; i++) {
- if (!strncmp(model, asmc_models[i].smc_model, strlen(model))) {
- freeenv(model);
- return (&asmc_models[i]);
+ for (i = 0; i < nitems(asmc_models); i++) {
+ if (strncmp(model_name, asmc_models[i].smc_model,
+ strlen(model_name)) == 0) {
+ model = &asmc_models[i];
+ goto out;
+ }
+ }
+ for (i = 0; i < nitems(asmc_generic_models); i++) {
+ if (strncmp(model_name, asmc_generic_models[i].smc_model,
+ strlen(asmc_generic_models[i].smc_model)) == 0) {
+ model = &asmc_generic_models[i];
+ goto out;
}
}
- freeenv(model);
- return (NULL);
+out:
+ freeenv(model_name);
+ return (model);
}
static int
asmc_probe(device_t dev)
{
const struct asmc_model *model;
+ const char *device_desc;
int rv;
if (resource_disabled("asmc", 0))
@@ -562,11 +676,13 @@ asmc_probe(device_t dev)
return (rv);
model = asmc_match(dev);
- if (!model) {
+ if (model == NULL) {
device_printf(dev, "model not recognized\n");
return (ENXIO);
}
- device_set_desc(dev, model->smc_desc);
+ device_desc = model->smc_desc == NULL ?
+ model->smc_model : model->smc_desc;
+ device_set_desc(dev, device_desc);
return (rv);
}
@@ -589,7 +705,7 @@ asmc_attach(device_t dev)
return (ENOMEM);
}
- sysctlctx = device_get_sysctl_ctx(dev);
+ sysctlctx = device_get_sysctl_ctx(dev);
sysctlnode = device_get_sysctl_tree(dev);
model = asmc_match(dev);
@@ -611,51 +727,51 @@ asmc_attach(device_t dev)
name[0] = '0' + j;
name[1] = 0;
sc->sc_fan_tree[i] = SYSCTL_ADD_NODE(sysctlctx,
- SYSCTL_CHILDREN(sc->sc_fan_tree[0]),
- OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
- "Fan Subtree");
+ SYSCTL_CHILDREN(sc->sc_fan_tree[0]), OID_AUTO, name,
+ CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Subtree");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "id",
- CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
- dev, j, model->smc_fan_id, "I",
- "Fan ID");
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
+ model->smc_fan_id, "I", "Fan ID");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "speed",
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
- dev, j, model->smc_fan_speed, "I",
- "Fan speed in RPM");
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
+ model->smc_fan_speed, "I", "Fan speed in RPM");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "safespeed",
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
- dev, j, model->smc_fan_safespeed, "I",
- "Fan safe speed in RPM");
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j,
+ model->smc_fan_safespeed, "I", "Fan safe speed in RPM");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "minspeed",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
- dev, j, model->smc_fan_minspeed, "I",
- "Fan minimum speed in RPM");
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
+ model->smc_fan_minspeed, "I", "Fan minimum speed in RPM");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "maxspeed",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
- dev, j, model->smc_fan_maxspeed, "I",
- "Fan maximum speed in RPM");
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
+ model->smc_fan_maxspeed, "I", "Fan maximum speed in RPM");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "targetspeed",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
- dev, j, model->smc_fan_targetspeed, "I",
- "Fan target speed in RPM");
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
+ model->smc_fan_targetspeed, "I", "Fan target speed in RPM");
+
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
+ OID_AUTO, "manual",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j,
+ asmc_mb_sysctl_fanmanual, "I",
+ "Fan manual mode (0=auto, 1=manual)");
}
/*
@@ -669,8 +785,8 @@ asmc_attach(device_t dev)
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_temp_tree),
OID_AUTO, model->smc_tempnames[i],
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
- dev, i, asmc_temp_sysctl, "I",
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, i,
+ asmc_temp_sysctl, "I",
model->smc_tempdescs[i]);
}
@@ -686,24 +802,30 @@ asmc_attach(device_t dev)
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_light_tree),
OID_AUTO, "left",
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
dev, 0, model->smc_light_left, "I",
"Keyboard backlight left sensor");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_light_tree),
OID_AUTO, "right",
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
- dev, 0, model->smc_light_right, "I",
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0,
+ model->smc_light_right, "I",
"Keyboard backlight right sensor");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_light_tree),
OID_AUTO, "control",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY |
- CTLFLAG_NEEDGIANT, dev, 0,
- model->smc_light_control, "I",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE,
+ dev, 0, model->smc_light_control, "I",
"Keyboard backlight brightness control");
+
+ sc->sc_kbd_bkl = backlight_register("asmc", dev);
+ if (sc->sc_kbd_bkl == NULL) {
+ device_printf(dev, "Can not register backlight\n");
+ ret = ENXIO;
+ goto err;
+ }
}
if (model->smc_sms_x == NULL)
@@ -719,21 +841,21 @@ asmc_attach(device_t dev)
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_sms_tree),
OID_AUTO, "x",
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
dev, 0, model->smc_sms_x, "I",
"Sudden Motion Sensor X value");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_sms_tree),
OID_AUTO, "y",
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
dev, 0, model->smc_sms_y, "I",
"Sudden Motion Sensor Y value");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_sms_tree),
OID_AUTO, "z",
- CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
dev, 0, model->smc_sms_z, "I",
"Sudden Motion Sensor Z value");
@@ -757,33 +879,26 @@ asmc_attach(device_t dev)
* Allocate an IRQ for the SMS.
*/
sc->sc_rid_irq = 0;
- sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &sc->sc_rid_irq, RF_ACTIVE);
+ sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq,
+ RF_ACTIVE);
if (sc->sc_irq == NULL) {
device_printf(dev, "unable to allocate IRQ resource\n");
ret = ENXIO;
- goto err2;
+ goto err;
}
- ret = bus_setup_intr(dev, sc->sc_irq,
- INTR_TYPE_MISC | INTR_MPSAFE,
- asmc_sms_intrfast, NULL,
- dev, &sc->sc_cookie);
-
+ ret = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE,
+ asmc_sms_intrfast, NULL, dev, &sc->sc_cookie);
if (ret) {
device_printf(dev, "unable to setup SMS IRQ\n");
- goto err1;
+ goto err;
}
+
nosms:
return (0);
-err1:
- bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq, sc->sc_irq);
-err2:
- bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port,
- sc->sc_ioport);
- mtx_destroy(&sc->sc_mtx);
- if (sc->sc_sms_tq)
- taskqueue_free(sc->sc_sms_tq);
+
+err:
+ asmc_detach(dev);
return (ret);
}
@@ -793,19 +908,31 @@ asmc_detach(device_t dev)
{
struct asmc_softc *sc = device_get_softc(dev);
+ if (sc->sc_kbd_bkl != NULL)
+ backlight_destroy(sc->sc_kbd_bkl);
+
if (sc->sc_sms_tq) {
taskqueue_drain(sc->sc_sms_tq, &sc->sc_sms_task);
taskqueue_free(sc->sc_sms_tq);
+ sc->sc_sms_tq = NULL;
}
- if (sc->sc_cookie)
+ if (sc->sc_cookie) {
bus_teardown_intr(dev, sc->sc_irq, sc->sc_cookie);
- if (sc->sc_irq)
+ sc->sc_cookie = NULL;
+ }
+ if (sc->sc_irq) {
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq,
sc->sc_irq);
- if (sc->sc_ioport)
+ sc->sc_irq = NULL;
+ }
+ if (sc->sc_ioport) {
bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port,
sc->sc_ioport);
- mtx_destroy(&sc->sc_mtx);
+ sc->sc_ioport = NULL;
+ }
+ if (mtx_initialized(&sc->sc_mtx)) {
+ mtx_destroy(&sc->sc_mtx);
+ }
return (0);
}
@@ -813,20 +940,29 @@ asmc_detach(device_t dev)
static int
asmc_resume(device_t dev)
{
- uint8_t buf[2];
- buf[0] = light_control;
- buf[1] = 0x00;
- asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof buf);
- return (0);
+ uint8_t buf[2];
+
+ buf[0] = light_control;
+ buf[1] = 0x00;
+ asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf));
+
+ return (0);
}
-#ifdef DEBUG
-void asmc_dumpall(device_t dev)
+#ifdef ASMC_DEBUG
+void
+asmc_dumpall(device_t dev)
{
+ struct asmc_softc *sc = device_get_softc(dev);
int i;
- /* XXX magic number */
- for (i=0; i < 0x100; i++)
+ if (sc->sc_nkeys == 0) {
+ device_printf(dev, "asmc_dumpall: key count not available\n");
+ return;
+ }
+
+ device_printf(dev, "asmc_dumpall: dumping %d keys\n", sc->sc_nkeys);
+ for (i = 0; i < sc->sc_nkeys; i++)
asmc_key_dump(dev, i);
}
#endif
@@ -835,8 +971,17 @@ static int
asmc_init(device_t dev)
{
struct asmc_softc *sc = device_get_softc(dev);
+ struct sysctl_ctx_list *sysctlctx;
+ uint8_t buf[6];
int i, error = 1;
- uint8_t buf[4];
+
+ sysctlctx = device_get_sysctl_ctx(dev);
+
+ error = asmc_key_read(dev, ASMC_KEY_REV, buf, 6);
+ if (error != 0)
+ goto out_err;
+ device_printf(dev, "SMC revision: %x.%x%x%x\n", buf[0], buf[1], buf[2],
+ ntohs(*(uint16_t *)buf + 4));
if (sc->sc_model->smc_sms_x == NULL)
goto nosms;
@@ -907,25 +1052,40 @@ asmc_init(device_t dev)
out:
asmc_sms_calibrate(dev);
nosms:
+ /* Wake-on-LAN convenience sysctl */
+ if (asmc_key_read(dev, ASMC_KEY_AUPO, buf, 1) == 0) {
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "wol",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+ dev, 0, asmc_wol_sysctl, "I",
+ "Wake-on-LAN enable (0=off, 1=on)");
+ }
+
sc->sc_nfan = asmc_fan_count(dev);
if (sc->sc_nfan > ASMC_MAXFANS) {
- device_printf(dev, "more than %d fans were detected. Please "
- "report this.\n", ASMC_MAXFANS);
+ device_printf(dev,
+ "more than %d fans were detected. Please report this.\n",
+ ASMC_MAXFANS);
sc->sc_nfan = ASMC_MAXFANS;
}
- if (bootverbose) {
- /*
- * The number of keys is a 32 bit buffer
- */
- asmc_key_read(dev, ASMC_NKEYS, buf, 4);
- device_printf(dev, "number of keys: %d\n", ntohl(*(uint32_t*)buf));
+ /*
+ * Read and cache the number of SMC keys (32 bit buffer)
+ */
+ if (asmc_key_read(dev, ASMC_NKEYS, buf, 4) == 0) {
+ sc->sc_nkeys = be32dec(buf);
+ if (bootverbose)
+ device_printf(dev, "number of keys: %d\n",
+ sc->sc_nkeys);
+ } else {
+ sc->sc_nkeys = 0;
}
-#ifdef DEBUG
+out_err:
+#ifdef ASMC_DEBUG
asmc_dumpall(dev);
#endif
-
return (error);
}
@@ -957,21 +1117,18 @@ asmc_wait_ack(device_t dev, uint8_t val, int amount)
static int
asmc_wait(device_t dev, uint8_t val)
{
-#ifdef DEBUG
+#ifdef ASMC_DEBUG
struct asmc_softc *sc;
#endif
if (asmc_wait_ack(dev, val, 1000) == 0)
return (0);
-#ifdef DEBUG
+#ifdef ASMC_DEBUG
sc = device_get_softc(dev);
-#endif
- val = val & ASMC_STATUS_MASK;
-#ifdef DEBUG
- device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, val,
- ASMC_CMDPORT_READ(sc));
+ device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__,
+ val & ASMC_STATUS_MASK, ASMC_CMDPORT_READ(sc));
#endif
return (1);
}
@@ -981,18 +1138,19 @@ asmc_wait(device_t dev, uint8_t val)
* the acknowledgement fails.
*/
static int
-asmc_command(device_t dev, uint8_t command) {
+asmc_command(device_t dev, uint8_t command)
+{
int i;
struct asmc_softc *sc = device_get_softc(dev);
- for (i=0; i < 10; i++) {
+ for (i = 0; i < 10; i++) {
ASMC_CMDPORT_WRITE(sc, command);
if (asmc_wait_ack(dev, 0x0c, 100) == 0) {
return (0);
}
}
-#ifdef DEBUG
+#ifdef ASMC_DEBUG
device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, command,
ASMC_CMDPORT_READ(sc));
#endif
@@ -1028,9 +1186,10 @@ begin:
error = 0;
out:
if (error) {
- if (++try < 10) goto begin;
- device_printf(dev,"%s for key %s failed %d times, giving up\n",
- __func__, key, try);
+ if (++try < 10)
+ goto begin;
+ device_printf(dev, "%s for key %s failed %d times, giving up\n",
+ __func__, key, try);
}
mtx_unlock_spin(&sc->sc_mtx);
@@ -1038,7 +1197,7 @@ out:
return (error);
}
-#ifdef DEBUG
+#ifdef ASMC_DEBUG
static int
asmc_key_dump(device_t dev, int number)
{
@@ -1096,12 +1255,12 @@ begin:
error = 0;
out:
if (error) {
- if (++try < 10) goto begin;
- device_printf(dev,"%s for key %s failed %d times, giving up\n",
- __func__, key, try);
+ if (++try < 10)
+ goto begin;
+ device_printf(dev, "%s for key %s failed %d times, giving up\n",
+ __func__, key, try);
mtx_unlock_spin(&sc->sc_mtx);
- }
- else {
+ } else {
char buf[1024];
char buf2[8];
mtx_unlock_spin(&sc->sc_mtx);
@@ -1110,16 +1269,17 @@ out:
type[5] = 0;
if (maxlen > sizeof(v)) {
device_printf(dev,
- "WARNING: cropping maxlen from %d to %zu\n",
- maxlen, sizeof(v));
+ "WARNING: cropping maxlen from %d to %zu\n", maxlen,
+ sizeof(v));
maxlen = sizeof(v);
}
for (i = 0; i < sizeof(v); i++) {
v[i] = 0;
}
asmc_key_read(dev, key, v, maxlen);
- snprintf(buf, sizeof(buf), "key %d is: %s, type %s "
- "(len %d), data", number, key, type, maxlen);
+ snprintf(buf, sizeof(buf),
+ "key %d is: %s, type %s (len %d), data",
+ number, key, type, maxlen);
for (i = 0; i < maxlen; i++) {
snprintf(buf2, sizeof(buf2), " %02x", v[i]);
strlcat(buf, buf2, sizeof(buf));
@@ -1164,15 +1324,15 @@ begin:
error = 0;
out:
if (error) {
- if (++try < 10) goto begin;
- device_printf(dev,"%s for key %s failed %d times, giving up\n",
- __func__, key, try);
+ if (++try < 10)
+ goto begin;
+ device_printf(dev, "%s for key %s failed %d times, giving up\n",
+ __func__, key, try);
}
mtx_unlock_spin(&sc->sc_mtx);
return (error);
-
}
/*
@@ -1183,7 +1343,7 @@ asmc_fan_count(device_t dev)
{
uint8_t buf[1];
- if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof buf) != 0)
+ if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof(buf)) != 0)
return (-1);
return (buf[0]);
@@ -1197,23 +1357,24 @@ asmc_fan_getvalue(device_t dev, const char *key, int fan)
char fankey[5];
snprintf(fankey, sizeof(fankey), key, fan);
- if (asmc_key_read(dev, fankey, buf, sizeof buf) != 0)
+ if (asmc_key_read(dev, fankey, buf, sizeof(buf)) != 0)
return (-1);
speed = (buf[0] << 6) | (buf[1] >> 2);
return (speed);
}
-static char*
-asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf, uint8_t buflen)
+static char *
+asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf,
+ uint8_t buflen)
{
char fankey[5];
- char* desc;
+ char *desc;
snprintf(fankey, sizeof(fankey), key, fan);
if (asmc_key_read(dev, fankey, buf, buflen) != 0)
return (NULL);
- desc = buf+4;
+ desc = buf + 4;
return (desc);
}
@@ -1226,11 +1387,11 @@ asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed)
speed *= 4;
- buf[0] = speed>>8;
+ buf[0] = speed >> 8;
buf[1] = speed;
snprintf(fankey, sizeof(fankey), key, fan);
- if (asmc_key_write(dev, fankey, buf, sizeof buf) < 0)
+ if (asmc_key_write(dev, fankey, buf, sizeof(buf)) < 0)
return (-1);
return (0);
@@ -1239,7 +1400,7 @@ asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed)
static int
asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
int fan = arg2;
int error;
int32_t v;
@@ -1254,10 +1415,10 @@ static int
asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS)
{
uint8_t buf[16];
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
int fan = arg2;
int error = true;
- char* desc;
+ char *desc;
desc = asmc_fan_getstring(dev, ASMC_KEY_FANID, fan, buf, sizeof(buf));
@@ -1270,7 +1431,7 @@ asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS)
static int
asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
int fan = arg2;
int error;
int32_t v;
@@ -1284,7 +1445,7 @@ asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS)
static int
asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
int fan = arg2;
int error;
int32_t v;
@@ -1303,7 +1464,7 @@ asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS)
static int
asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
int fan = arg2;
int error;
int32_t v;
@@ -1322,7 +1483,7 @@ asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS)
static int
asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
int fan = arg2;
int error;
int32_t v;
@@ -1338,6 +1499,55 @@ asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS)
return (error);
}
+static int
+asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev = (device_t)arg1;
+ int fan = arg2;
+ int error;
+ int32_t v;
+ uint8_t buf[2];
+ uint16_t val;
+
+ /* Read current FS! bitmask (asmc_key_read locks internally) */
+ error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf));
+ if (error != 0)
+ return (error);
+
+ /* Extract manual bit for this fan (big-endian) */
+ val = (buf[0] << 8) | buf[1];
+ v = (val >> fan) & 0x01;
+
+ /* Let sysctl handle the value */
+ error = sysctl_handle_int(oidp, &v, 0, req);
+
+ if (error == 0 && req->newptr != NULL) {
+ /* Validate input (0 = auto, 1 = manual) */
+ if (v != 0 && v != 1)
+ return (EINVAL);
+ /* Read-modify-write of FS! bitmask */
+ error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf,
+ sizeof(buf));
+ if (error == 0) {
+ val = (buf[0] << 8) | buf[1];
+
+ /* Modify single bit */
+ if (v)
+ val |= (1 << fan); /* Set to manual */
+ else
+ val &= ~(1 << fan); /* Set to auto */
+
+ /* Write back */
+ buf[0] = val >> 8;
+ buf[1] = val & 0xff;
+ error = asmc_key_write(dev, ASMC_KEY_FANMANUAL, buf,
+ sizeof(buf));
+ }
+ }
+
+ return (error);
+}
+
/*
* Temperature functions.
*/
@@ -1349,7 +1559,7 @@ asmc_temp_getvalue(device_t dev, const char *key)
/*
* Check for invalid temperatures.
*/
- if (asmc_key_read(dev, key, buf, sizeof buf) != 0)
+ if (asmc_key_read(dev, key, buf, sizeof(buf)) != 0)
return (-1);
return (buf[0]);
@@ -1358,7 +1568,7 @@ asmc_temp_getvalue(device_t dev, const char *key)
static int
asmc_temp_sysctl(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
struct asmc_softc *sc = device_get_softc(dev);
int error, val;
@@ -1382,12 +1592,12 @@ asmc_sms_read(device_t dev, const char *key, int16_t *val)
case 'X':
case 'Y':
case 'Z':
- error = asmc_key_read(dev, key, buf, sizeof buf);
+ error = asmc_key_read(dev, key, buf, sizeof(buf));
break;
default:
device_printf(dev, "%s called with invalid argument %s\n",
- __func__, key);
- error = 1;
+ __func__, key);
+ error = EINVAL;
goto out;
}
*val = ((int16_t)buf[0] << 8) | buf[1];
@@ -1409,7 +1619,7 @@ static int
asmc_sms_intrfast(void *arg)
{
uint8_t type;
- device_t dev = (device_t) arg;
+ device_t dev = (device_t)arg;
struct asmc_softc *sc = device_get_softc(dev);
if (!sc->sc_sms_intr_works)
return (FILTER_HANDLED);
@@ -1482,13 +1692,13 @@ asmc_sms_task(void *arg, int pending)
static int
asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
int error;
int16_t val;
int32_t v;
asmc_sms_read(dev, ASMC_KEY_SMS_X, &val);
- v = (int32_t) val;
+ v = (int32_t)val;
error = sysctl_handle_int(oidp, &v, 0, req);
return (error);
@@ -1497,13 +1707,13 @@ asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS)
static int
asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
int error;
int16_t val;
int32_t v;
asmc_sms_read(dev, ASMC_KEY_SMS_Y, &val);
- v = (int32_t) val;
+ v = (int32_t)val;
error = sysctl_handle_int(oidp, &v, 0, req);
return (error);
@@ -1512,13 +1722,13 @@ asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS)
static int
asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
int error;
int16_t val;
int32_t v;
asmc_sms_read(dev, ASMC_KEY_SMS_Z, &val);
- v = (int32_t) val;
+ v = (int32_t)val;
error = sysctl_handle_int(oidp, &v, 0, req);
return (error);
@@ -1527,12 +1737,12 @@ asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS)
static int
asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
uint8_t buf[6];
int error;
int32_t v;
- asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof buf);
+ asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf));
v = buf[2];
error = sysctl_handle_int(oidp, &v, 0, req);
@@ -1542,12 +1752,12 @@ asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS)
static int
asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
uint8_t buf[6];
int error;
int32_t v;
- asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof buf);
+ asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof(buf));
v = buf[2];
error = sysctl_handle_int(oidp, &v, 0, req);
@@ -1557,7 +1767,8 @@ asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS)
static int
asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
+ struct asmc_softc *sc = device_get_softc(dev);
uint8_t buf[2];
int error;
int v;
@@ -1569,9 +1780,10 @@ asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS)
if (v < 0 || v > 255)
return (EINVAL);
light_control = v;
+ sc->sc_kbd_bkl_level = v * 100 / 255;
buf[0] = light_control;
buf[1] = 0x00;
- asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof buf);
+ asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf));
}
return (error);
}
@@ -1579,12 +1791,12 @@ asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS)
static int
asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
+ device_t dev = (device_t)arg1;
uint8_t buf[10];
int error;
uint32_t v;
- asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof buf);
+ asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf));
/*
* This seems to be a 32 bit big endian value from buf[6] -> buf[9].
@@ -1605,3 +1817,69 @@ asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS)
return (error);
}
+
+/*
+ * Wake-on-LAN convenience sysctl.
+ * Reading returns 1 if WoL is enabled, 0 if disabled.
+ * Writing 1 enables WoL, 0 disables it.
+ */
+static int
+asmc_wol_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev = (device_t)arg1;
+ uint8_t aupo;
+ int val, error;
+
+ /* Read current AUPO value */
+ if (asmc_key_read(dev, ASMC_KEY_AUPO, &aupo, 1) != 0)
+ return (EIO);
+
+ val = (aupo != 0) ? 1 : 0;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ /* Clamp to 0 or 1 */
+ aupo = (val != 0) ? 1 : 0;
+
+ /* Write AUPO */
+ if (asmc_key_write(dev, ASMC_KEY_AUPO, &aupo, 1) != 0)
+ return (EIO);
+
+ return (0);
+}
+
+static int
+asmc_backlight_update_status(device_t dev, struct backlight_props *props)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ uint8_t buf[2];
+
+ sc->sc_kbd_bkl_level = props->brightness;
+ light_control = props->brightness * 255 / 100;
+ buf[0] = light_control;
+ buf[1] = 0x00;
+ asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf));
+
+ return (0);
+}
+
+static int
+asmc_backlight_get_status(device_t dev, struct backlight_props *props)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+
+ props->brightness = sc->sc_kbd_bkl_level;
+ props->nlevels = 0;
+
+ return (0);
+}
+
+static int
+asmc_backlight_get_info(device_t dev, struct backlight_info *info)
+{
+ info->type = BACKLIGHT_TYPE_KEYBOARD;
+ strlcpy(info->name, "Apple MacBook Keyboard", BACKLIGHTMAXNAMELENGTH);
+
+ return (0);
+}