Improvements to asmc(4):

1. changed the code so that 2**16 keys are supported
2. changed the number of possible fans in a system from 2 to 6
3. added write support for some fan sysctls
4. added a new sysctl which shows the ID of the fan
5. added four more apple models with their temperature keys
6. changed the maxnumber of temperature keys from 36 to 80
7. replaced several fixed buf sizes to sizeof buf

Obtained from:	Denis Ahrens denis at h3q.com
MFC after:	4 weeks
This commit is contained in:
Rui Paulo 2014-09-22 16:20:38 +00:00
parent 8a07b9a5c4
commit 447666f08b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=271975
2 changed files with 226 additions and 19 deletions

View file

@ -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 }
};
@ -359,6 +389,12 @@ asmc_attach(device_t dev)
OID_AUTO, name, CTLFLAG_RD, 0,
"Fan Subtree");
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,
@ -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 @@ asmc_init(device_t dev)
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)
{
@ -941,6 +1009,22 @@ asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS)
return (error);
}
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)
{
@ -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);

View file

@ -27,7 +27,7 @@
*
*/
#define ASMC_MAXFANS 2
#define ASMC_MAXFANS 6
struct asmc_softc {
device_t sc_dev;
@ -83,6 +83,7 @@ struct asmc_softc {
*/
#define ASMC_KEY_FANCOUNT "FNum" /* RO; 1 byte */
#define ASMC_KEY_FANMANUAL "FS! " /* RW; 2 bytes */
#define ASMC_KEY_FANID "F%dID" /* RO; 16 bytes */
#define ASMC_KEY_FANSPEED "F%dAc" /* RO; 2 bytes */
#define ASMC_KEY_FANMINSPEED "F%dMn" /* RO; 2 bytes */
#define ASMC_KEY_FANMAXSPEED "F%dMx" /* RO; 2 bytes */
@ -132,7 +133,7 @@ struct asmc_softc {
*
*/
/* maximum array size for temperatures including the last NULL */
#define ASMC_TEMP_MAX 36
#define ASMC_TEMP_MAX 80
#define ASMC_MB_TEMPS { "TB0T", "TN0P", "TN1P", "Th0H", "Th1H", \
"TM0P", NULL }
#define ASMC_MB_TEMPNAMES { "enclosure", "northbridge1", \
@ -175,6 +176,57 @@ struct asmc_softc {
"Unknown", "Unknown", \
"Wireless Module", }
#define ASMC_MBP8_TEMPS { "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", \
"TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
"TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \
"TCTD", "TG0D", "TG0P", "THSP", "TM0S", \
"TMBS", "TP0P", "TPCD", "TW0P", "Th1H", \
"Th2H", "Tm0P", "Ts0P", "Ts0S", NULL }
#define ASMC_MBP8_TEMPNAMES { "enclosure", "TB1T", "TB2T", "TC0C", "TC0D", \
"TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
"TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \
"TCTD", "graphics", "TG0P", "THSP", "TM0S", \
"TMBS", "TP0P", "TPCD", "wireless", "Th1H", \
"Th2H", "memory", "Ts0P", "Ts0S" }
#define ASMC_MBP8_TEMPDESCS { "Enclosure Bottomside", "TB1T", "TB2T", "TC0C", "TC0D", \
"TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
"TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \
"TCTD", "TG0D", "TG0P", "THSP", "TM0S", \
"TMBS", "TP0P", "TPCD", "TW0P", "Th1H", \
"Th2H", "Tm0P", "Ts0P", "Ts0S" }
#define ASMC_MBP11_TEMPS { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
"TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
"TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
"TCXC", "TG0D", "TG0P", "TG1D", "TG1F", \
"TG1d", "TH0A", "TH0B", "TH0F", "TH0R", \
"TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
"TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
"TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
"Ts1S", NULL }
#define ASMC_MBP11_TEMPNAMES { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
"TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
"TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
"TCXC", "TG0D", "TG0P", "TG1D", "TG1F", \
"TG1d", "TH0A", "TH0B", "TH0F", "TH0R", \
"TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
"TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
"TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
"Ts1S" }
#define ASMC_MBP11_TEMPDESCS { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
"TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
"TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
"TCXC", "TG0D", "TG0P", "TG1D", "TG1F", \
"TG1d", "TH0A", "TH0B", "TH0F", "TH0R", \
"TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
"TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
"TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
"Ts1S" }
#define ASMC_MM_TEMPS { "TN0P", "TN1P", NULL }
#define ASMC_MM_TEMPNAMES { "northbridge1", "northbridge2" }
#define ASMC_MM_TEMPDESCS { "Northbridge Point 1", \
@ -214,8 +266,7 @@ struct asmc_softc {
"TH0P", "TH1P", "TH2P", "TH3P", "TMAP", \
"TMAS", "TMBS", "TM0P", "TM0S", "TM1P", \
"TM1S", "TM2P", "TM2S", "TM3S", "TM8P", \
"TM8S", "TM9P", "TM9S", "TN0H", "TS0C", \
NULL }
"TM8S", "TM9P", "TM9S", "TN0H", "TS0C", }
#define ASMC_MP_TEMPDESCS { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", \
"TC0C", "TC0D", "TC0P", "TC1C", "TC1D", \
@ -223,9 +274,66 @@ struct asmc_softc {
"TH0P", "TH1P", "TH2P", "TH3P", "TMAP", \
"TMAS", "TMBS", "TM0P", "TM0S", "TM1P", \
"TM1S", "TM2P", "TM2S", "TM3S", "TM8P", \
"TM8S", "TM9P", "TM9S", "TN0H", "TS0C", \
"TM8S", "TM9P", "TM9S", "TN0H", "TS0C", }
#define ASMC_MP5_TEMPS { "TA0P", "TCAC", "TCAD", "TCAG", "TCAH", \
"TCAS", "TCBC", "TCBD", "TCBG", "TCBH", \
"TCBS", "TH1F", "TH1P", "TH1V", "TH2F", \
"TH2P", "TH2V", "TH3F", "TH3P", "TH3V", \
"TH4F", "TH4P", "TH4V", "THPS", "THTG", \
"TM1P", "TM2P", "TM2V", "TM3P", "TM3V", \
"TM4P", "TM5P", "TM6P", "TM6V", "TM7P", \
"TM7V", "TM8P", "TM8V", "TM9V", "TMA1", \
"TMA2", "TMA3", "TMA4", "TMB1", "TMB2", \
"TMB3", "TMB4", "TMHS", "TMLS", "TMPS", \
"TMPV", "TMTG", "TN0D", "TN0H", "TNTG", \
"Te1F", "Te1P", "Te1S", "Te2F", "Te2S", \
"Te3F", "Te3S", "Te4F", "Te4S", "Te5F", \
"Te5S", "TeGG", "TeGP", "TeRG", "TeRP", \
"TeRV", "Tp0C", "Tp1C", "TpPS", "TpTG", \
NULL }
#define ASMC_MP5_TEMPNAMES { "ambient", "TCAC", "TCAD", "TCAG", "TCAH", \
"TCAS", "TCBC", "TCBD", "TCBG", "TCBH", \
"TCBS", "TH1F", "TH1P", "TH1V", "TH2F", \
"TH2P", "TH2V", "TH3F", "TH3P", "TH3V", \
"TH4F", "TH4P", "TH4V", "THPS", "THTG", \
"TM1P", "TM2P", "TM2V", "TM3P", "TM3V", \
"TM4P", "TM5P", "TM6P", "TM6V", "TM7P", \
"TM7V", "TM8P", "TM8V", "TM9V", "ram_a1", \
"ram_a2", "ram_a3", "ram_a4", "ram_b1", "ram_b2", \
"ram_b3", "ram_b4", "TMHS", "TMLS", "TMPS", \
"TMPV", "TMTG", "TN0D", "TN0H", "TNTG", \
"Te1F", "Te1P", "Te1S", "Te2F", "Te2S", \
"Te3F", "Te3S", "Te4F", "Te4S", "Te5F", \
"Te5S", "TeGG", "TeGP", "TeRG", "TeRP", \
"TeRV", "Tp0C", "Tp1C", "TpPS", "TpTG", }
#define ASMC_MP5_TEMPDESCS { "TA0P", "TCAC", "TCAD", "TCAG", "TCAH", \
"TCAS", "TCBC", "TCBD", "TCBG", "TCBH", \
"TCBS", "TH1F", "TH1P", "TH1V", "TH2F", \
"TH2P", "TH2V", "TH3F", "TH3P", "TH3V", \
"TH4F", "TH4P", "TH4V", "THPS", "THTG", \
"TM1P", "TM2P", "TM2V", "TM3P", "TM3V", \
"TM4P", "TM5P", "TM6P", "TM6V", "TM7P", \
"TM7V", "TM8P", "TM8V", "TM9V", "TMA1", \
"TMA2", "TMA3", "TMA4", "TMB1", "TMB2", \
"TMB3", "TMB4", "TMHS", "TMLS", "TMPS", \
"TMPV", "TMTG", "TN0D", "TN0H", "TNTG", \
"Te1F", "Te1P", "Te1S", "Te2F", "Te2S", \
"Te3F", "Te3S", "Te4F", "Te4S", "Te5F", \
"Te5S", "TeGG", "TeGP", "TeRG", "TeRP", \
"TeRV", "Tp0C", "Tp1C", "TpPS", "TpTG", }
#define ASMC_MBA_TEMPS { "TB0T", NULL }
#define ASMC_MBA_TEMPNAMES { "enclosure" }
#define ASMC_MBA_TEMPDESCS { "Enclosure Bottom" }
#define ASMC_MBA3_TEMPS { "TB0T", "TB1T", "TB2T", \
"TC0D", "TC0E", "TC0P", NULL }
#define ASMC_MBA3_TEMPNAMES { "enclosure", "TB1T", "TB2T", \
"TC0D", "TC0E", "TC0P" }
#define ASMC_MBA3_TEMPDESCS { "Enclosure Bottom", "TB1T", "TB2T", \
"TC0D", "TC0E", "TC0P" }