summaryrefslogtreecommitdiffstats
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.c127
1 files changed, 113 insertions, 14 deletions
diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c
index 099e7f1..5933307 100644
--- a/sys/dev/asmc/asmc.c
+++ b/sys/dev/asmc/asmc.c
@@ -77,6 +77,7 @@ static int asmc_key_read(device_t dev, const char *key, uint8_t *buf,
uint8_t);
static int asmc_fan_count(device_t dev);
static int asmc_fan_getvalue(device_t dev, const char *key, int fan);
+static int asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed);
static int asmc_temp_getvalue(device_t dev, const char *key);
static int asmc_sms_read(device_t, const char *key, int16_t *val);
static void asmc_sms_calibrate(device_t dev);
@@ -94,6 +95,7 @@ static int asmc_key_dump(device_t, int);
/*
* Model functions.
*/
+static int asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS);
@@ -115,6 +117,7 @@ struct asmc_model {
int (*smc_sms_x)(SYSCTL_HANDLER_ARGS);
int (*smc_sms_y)(SYSCTL_HANDLER_ARGS);
int (*smc_sms_z)(SYSCTL_HANDLER_ARGS);
+ int (*smc_fan_id)(SYSCTL_HANDLER_ARGS);
int (*smc_fan_speed)(SYSCTL_HANDLER_ARGS);
int (*smc_fan_safespeed)(SYSCTL_HANDLER_ARGS);
int (*smc_fan_minspeed)(SYSCTL_HANDLER_ARGS);
@@ -134,7 +137,7 @@ static 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_FAN_FUNCS asmc_mb_sysctl_fanspeed, asmc_mb_sysctl_fansafespeed, \
+#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
@@ -196,6 +199,18 @@ struct asmc_model asmc_models[] = {
ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
ASMC_MBP4_TEMPS, ASMC_MBP4_TEMPNAMES, ASMC_MBP4_TEMPDESCS
},
+
+ {
+ "MacBookPro8,2", "Apple SMC MacBook Pro (early 2011)",
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
+ ASMC_MBP8_TEMPS, ASMC_MBP8_TEMPNAMES, ASMC_MBP8_TEMPDESCS
+ },
+
+ {
+ "MacBookPro11,3", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)",
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
+ ASMC_MBP11_TEMPS, ASMC_MBP11_TEMPNAMES, ASMC_MBP11_TEMPDESCS
+ },
/* The Mac Mini has no SMS */
{
@@ -224,12 +239,27 @@ struct asmc_model asmc_models[] = {
ASMC_MP_TEMPS, ASMC_MP_TEMPNAMES, ASMC_MP_TEMPDESCS
},
+ /* Idem for the MacPro 2010*/
+ {
+ "MacPro5,1", "Apple SMC MacPro (2010)",
+ NULL, NULL, NULL,
+ ASMC_FAN_FUNCS,
+ NULL, NULL, NULL,
+ ASMC_MP5_TEMPS, ASMC_MP5_TEMPNAMES, ASMC_MP5_TEMPDESCS
+ },
+
{
"MacBookAir1,1", "Apple SMC MacBook Air",
ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL,
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_MBA3_TEMPS, ASMC_MBA3_TEMPNAMES, ASMC_MBA3_TEMPDESCS
+ },
+
{ NULL, NULL }
};
@@ -361,6 +391,12 @@ asmc_attach(device_t dev)
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
+ OID_AUTO, "id", CTLTYPE_STRING | CTLFLAG_RD,
+ 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,
dev, j, model->smc_fan_speed, "I",
"Fan speed in RPM");
@@ -375,21 +411,21 @@ asmc_attach(device_t dev)
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "minspeed",
- CTLTYPE_INT | CTLFLAG_RD,
+ CTLTYPE_INT | CTLFLAG_RW,
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_RD,
+ CTLTYPE_INT | CTLFLAG_RW,
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_RD,
+ CTLTYPE_INT | CTLFLAG_RW,
dev, j, model->smc_fan_targetspeed, "I",
"Fan target speed in RPM");
}
@@ -641,11 +677,10 @@ nosms:
if (bootverbose) {
/*
- * XXX: The number of keys is a 32 bit buffer, but
- * right now Apple only uses the last 8 bit.
+ * 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", buf[3]);
+ device_printf(dev, "number of keys: %d\n", ntohl(*(uint32_t*)buf));
}
#ifdef DEBUG
@@ -906,7 +941,7 @@ asmc_fan_count(device_t dev)
{
uint8_t buf[1];
- if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, 1) < 0)
+ if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof buf) < 0)
return (-1);
return (buf[0]);
@@ -920,13 +955,46 @@ 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, 2) < 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[16];
+ char fankey[5];
+ char* desc;
+
+ snprintf(fankey, sizeof(fankey), key, fan);
+ if (asmc_key_read(dev, fankey, buf, sizeof buf) < 0)
+ return (NULL);
+ desc = buf+4;
+
+ return (desc);
+}
+
+static int
+asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed)
+{
+ uint8_t buf[2];
+ char fankey[5];
+
+ speed *= 4;
+
+ buf[0] = speed>>8;
+ buf[1] = speed;
+
+ snprintf(fankey, sizeof(fankey), key, fan);
+ if (asmc_key_write(dev, fankey, buf, sizeof buf) < 0)
+ return (-1);
+
+ return (0);
+}
+
static int
asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS)
{
@@ -942,6 +1010,22 @@ asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS)
}
static int
+asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev = (device_t) arg1;
+ int fan = arg2;
+ int error = true;
+ char* desc;
+
+ desc = asmc_fan_getstring(dev, ASMC_KEY_FANID, fan);
+
+ if (desc != NULL)
+ error = sysctl_handle_string(oidp, desc, 0, req);
+
+ return (error);
+}
+
+static int
asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS)
{
device_t dev = (device_t) arg1;
@@ -967,6 +1051,11 @@ asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS)
v = asmc_fan_getvalue(dev, ASMC_KEY_FANMINSPEED, fan);
error = sysctl_handle_int(oidp, &v, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ unsigned int newspeed = *(unsigned int *)req->newptr;
+ asmc_fan_setvalue(dev, ASMC_KEY_FANMINSPEED, fan, newspeed);
+ }
+
return (error);
}
@@ -981,6 +1070,11 @@ asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS)
v = asmc_fan_getvalue(dev, ASMC_KEY_FANMAXSPEED, fan);
error = sysctl_handle_int(oidp, &v, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ unsigned int newspeed = *(unsigned int *)req->newptr;
+ asmc_fan_setvalue(dev, ASMC_KEY_FANMAXSPEED, fan, newspeed);
+ }
+
return (error);
}
@@ -995,6 +1089,11 @@ asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS)
v = asmc_fan_getvalue(dev, ASMC_KEY_FANTARGETSPEED, fan);
error = sysctl_handle_int(oidp, &v, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ unsigned int newspeed = *(unsigned int *)req->newptr;
+ asmc_fan_setvalue(dev, ASMC_KEY_FANTARGETSPEED, fan, newspeed);
+ }
+
return (error);
}
@@ -1009,7 +1108,7 @@ asmc_temp_getvalue(device_t dev, const char *key)
/*
* Check for invalid temperatures.
*/
- if (asmc_key_read(dev, key, buf, 2) < 0)
+ if (asmc_key_read(dev, key, buf, sizeof buf) < 0)
return (-1);
return (buf[0]);
@@ -1042,7 +1141,7 @@ 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, 2);
+ error = asmc_key_read(dev, key, buf, sizeof buf);
break;
default:
device_printf(dev, "%s called with invalid argument %s\n",
@@ -1197,7 +1296,7 @@ asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS)
int error;
int32_t v;
- asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, 6);
+ asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof buf);
v = buf[2];
error = sysctl_handle_int(oidp, &v, sizeof(v), req);
@@ -1212,7 +1311,7 @@ asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS)
int error;
int32_t v;
- asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, 6);
+ asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof buf);
v = buf[2];
error = sysctl_handle_int(oidp, &v, sizeof(v), req);
@@ -1236,7 +1335,7 @@ asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS)
v = level;
buf[0] = level;
buf[1] = 0x00;
- asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, 2);
+ asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof buf);
}
return (error);
OpenPOWER on IntegriCloud