initial limits support

git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1598 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
Mark D. Studebaker committed 2002-11-11 02:02:17 +00:00
1 parent 04e0399c6f
commit c8b57bbe40
1 file changed
+117 -77
+117 -77
View File
@@ -118,7 +118,7 @@ static bmcsensors_initialized;
#define MAX_SDR_ENTRIES 50
#define SDR_LIMITS 13
#define SDR_LIMITS 8
#define SDR_MAX_ID_LENGTH 16
#define SDR_MAX_UNPACKED_ID_LENGTH ((SDR_MAX_ID_LENGTH * 4 / 3) + 2)
struct sdrdata {
@@ -127,11 +127,16 @@ struct sdrdata {
/* retrieved from SDR, not expected to change */
u8 stype;
u8 number;
u8 capab;
u16 thresh_mask;
u8 linear;
s16 m;
s16 b;
u8 k;
u8 nominal;
u8 limits[SDR_LIMITS];
int lim1, lim2;
u8 lim1_write, lim2_write;
u8 string_type;
u8 id_length;
u8 id[SDR_MAX_ID_LENGTH];
@@ -220,9 +225,80 @@ static void ipmi_sprintf(u8 * to, u8 * from, u8 type, u8 length)
}
}
static const char * threshold_text[] = {
"upper non-recoverable threshold",
"upper critical threshold",
"upper non-critical threshold",
"lower non-recoverable threshold",
"lower critical threshold",
"lower non-critical threshold",
"positive-going hysteresis", /* not used */
"negative-going hysteresis"
};
/* select two out of the 8 possible readable thresholds, and place indexes into the limits
array into lim1 and lim2. Set writable flags */
static void bmcsensors_select_thresholds(int i)
{
u8 capab = sdrd[i].capab;
u16 mask = sdrd[i].thresh_mask;
sdrd[i].lim1 = -1;
sdrd[i].lim2 = -1;
sdrd[i].lim1_write = 0;
sdrd[i].lim2_write = 0;
if(((capab & 0x0c) == 0x04) || /* readable thresholds ? */
((capab & 0x0c) == 0x08)) {
/* select upper threshold */
if(mask & 0x10) { /* upper crit */
sdrd[i].lim1 = 1;
if((capab & 0x0c) == 0x08 && (mask & 0x1000))
sdrd[i].lim1_write = 1;
}
else if(mask & 0x20) { /* upper non-recov */
sdrd[i].lim1 = 0;
if((capab & 0x0c) == 0x08 && (mask & 0x2000))
sdrd[i].lim1_write = 1;
}
else if(mask & 0x08) { /* upper non-crit */
sdrd[i].lim1 = 2;
if((capab & 0x0c) == 0x08 && (mask & 0x0800))
sdrd[i].lim1_write = 1;
}
/* select lower threshold */
if(((capab & 0x30) == 0x10) || /* readable hysteresis ? */
((capab & 0x30) == 0x20)) /* neg hyst */
sdrd[i].lim2 = 7;
else if(mask & 0x02) { /* lower crit */
sdrd[i].lim2 = 4;
if((capab & 0x0c) == 0x08 && (mask & 0x0200))
sdrd[i].lim2_write = 1;
}
else if(mask & 0x04) { /* lower non-recov */
sdrd[i].lim2 = 3;
if((capab & 0x0c) == 0x08 && (mask & 0x0400))
sdrd[i].lim2_write = 1;
}
else if(mask & 0x01) { /* lower non-crit */
sdrd[i].lim2 = 5;
if((capab & 0x0c) == 0x08 && (mask & 0x0100))
sdrd[i].lim2_write = 1;
}
}
if(sdrd[i].lim1 >= 0)
printk(KERN_INFO "bmcsensors.o: sensor %d: using %s for upper limit\n",
i, threshold_text[sdrd[i].lim1]);
else
printk(KERN_INFO "bmcsensors.o: sensor %d: no readable upper limit\n", i);
if(sdrd[i].lim2 >= 0)
printk(KERN_INFO "bmcsensors.o: sensor %d: using %s for lower limit\n",
i, threshold_text[sdrd[i].lim2]);
else
printk(KERN_INFO "bmcsensors.o: sensor %d: no readable lower limit\n", i);
}
/* After we have received all the SDR entries and picked out the ones
we are interested in, build a table of the /proc entries and register.
@@ -247,7 +323,6 @@ static void bmcsensors_build_proc_table()
bmcsensors_dir_table[i].procname = bmcsensors_proc_name_pool + (i * MAX_PROCNAME_SIZE);
bmcsensors_dir_table[i].data = NULL;
bmcsensors_dir_table[i].maxlen = 0;
bmcsensors_dir_table[i].mode = 0644;
bmcsensors_dir_table[i].child = NULL;
bmcsensors_dir_table[i].proc_handler = &i2c_proc_real;
bmcsensors_dir_table[i].strategy = &i2c_sysctl_real;
@@ -284,10 +359,16 @@ static void bmcsensors_build_proc_table()
i, sdrd[i].stype, sdrd[i].linear);
}
ipmi_sprintf(id, sdrd[i].id, sdrd[i].string_type, sdrd[i].id_length);
printk(KERN_INFO "bmcsensors.o: registering sensor %d: '%s' (type 0x%x) as %s "
"(m=%d; b=%d; k1=%d; k2=%d)\n",
printk(KERN_INFO "bmcsensors.o: registering sensor %d: '%s' (type 0x%.2x) as %s "
"(m=%d; b=%d; k1=%d; k2=%d; cap=0x%.2x; mask=0x%.4x)\n",
i, id, sdrd[i].stype, bmcsensors_dir_table[i].procname,
sdrd[i].m, sdrd[i].b,sdrd[i].k & 0xf, sdrd[i].k >> 4);
sdrd[i].m, sdrd[i].b,sdrd[i].k & 0xf, sdrd[i].k >> 4,
sdrd[i].capab, sdrd[i].thresh_mask);
bmcsensors_select_thresholds(i);
if(sdrd[i].lim1_write || sdrd[i].lim2_write)
bmcsensors_dir_table[i].mode = 0644;
else
bmcsensors_dir_table[i].mode = 0444;
}
bmcsensors_dir_table[sdrd_count].ctl_name = 0;
@@ -337,7 +418,7 @@ static int bmcsensors_rcv_sdr_msg(struct ipmi_msg *msg, int state)
{
u16 record, nextrecord;
int version, type, length, owner, lun, number, entity, instance, init;
int capab, stype, code;
int stype, code;
int id_length;
int i;
int rstate = STATE_SDR;
@@ -382,11 +463,12 @@ static int bmcsensors_rcv_sdr_msg(struct ipmi_msg *msg, int state)
version = data[5];
type = data[6];
if(type == 1 || type == 2) { /* known SDR type */
/*
owner = data[8];
lun = data[9];
entity = data[11];
init = data[13];
capab = data[14];
*/
stype = data[15];
if(stype <= STYPE_MAX) { /* known sensor type */
@@ -405,6 +487,8 @@ static int bmcsensors_rcv_sdr_msg(struct ipmi_msg *msg, int state)
/* add SDR database entry */
sdrd[sdrd_count].stype = stype;
sdrd[sdrd_count].number = data[10];
sdrd[sdrd_count].capab = data[14];
sdrd[sdrd_count].thresh_mask = (data[22] << 8) | data[21];
if(type == 1) {
sdrd[sdrd_count].linear = data[26] & 0x7f;
sdrd[sdrd_count].m = data[27];
@@ -416,8 +500,9 @@ static int bmcsensors_rcv_sdr_msg(struct ipmi_msg *msg, int state)
if(sdrd[sdrd_count].b & 0x0200)
sdrd[sdrd_count].b |= 0xfc00; /* sign extend */
sdrd[sdrd_count].k = data[32];
for(i = 0; i < SDR_LIMITS; i++)
sdrd[sdrd_count].limits[i] = data[34 + i];
sdrd[sdrd_count].nominal = data[34];
for(i = 0; i < SDR_LIMITS; i++) /* assume readable */
sdrd[sdrd_count].limits[i] = data[39 + i];
sdrd[sdrd_count].string_type = data[50] >> 6;
id_length = data[50] & 0x1f;
if(id_length > 0)
@@ -432,6 +517,7 @@ static int bmcsensors_rcv_sdr_msg(struct ipmi_msg *msg, int state)
if(id_length > 0)
memcpy(sdrd[sdrd_count].id, &data[35], id_length);
sdrd[sdrd_count].id_length = id_length;
/* limits?? */
}
bmcs_count[stype]++;
sdrd_count++;
@@ -490,7 +576,6 @@ static void bmcsensors_rcv_msg(struct ipmi_msg *msg)
state = bmcsensors_rcv_sdr_msg(msg, state);
break;
case STATE_READING:
state = bmcsensors_rcv_reading_msg(msg);
break;
@@ -713,7 +798,7 @@ int find_sdrd(int sysctl)
/* IPMI V1.5 Section 30 */
static const int exps[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};
static int decplaces(i)
static int decplaces(int i)
{
u8 k2;
@@ -724,7 +809,7 @@ static int decplaces(i)
return 16 - k2;
}
static long convert_reading(i)
static long convert_value(u8 value, int i)
{
u8 k1, k2;
long r;
@@ -732,7 +817,7 @@ static long convert_reading(i)
k1 = sdrd[i].k & 0x0f;
k2 = sdrd[i].k >> 4;
r = sdrd[i].reading * sdrd[i].m;
r = value * sdrd[i].m;
if(k1 < 8)
r += sdrd[i].b * exps[k1];
else
@@ -765,8 +850,25 @@ void bmcsensors_all(struct i2c_client *client, int operation, int ctl_name,
*nrels_mag = decplaces(i);
else if (operation == SENSORS_PROC_REAL_READ) {
bmcsensors_update_client(client);
results[0] = convert_reading(i);
*nrels_mag = 1;
if(sdrd[i].stype == STYPE_FAN) { /* lower limit only */
if(sdrd[i].lim2 >= 0)
results[0] = convert_value(sdrd[i].limits[sdrd[i].lim2], i);
else
results[0] = 0;
results[1] = convert_value(sdrd[i].reading, i);
*nrels_mag = 2;
} else {
if(sdrd[i].lim1 >= 0)
results[0] = convert_value(sdrd[i].limits[sdrd[i].lim1], i);
else
results[0] = 0;
if(sdrd[i].lim2 >= 0)
results[1] = convert_value(sdrd[i].limits[sdrd[i].lim2], i);
else
results[1] = 0;
results[2] = convert_value(sdrd[i].reading, i);
*nrels_mag = 3;
}
} else if (operation == SENSORS_PROC_REAL_WRITE) {
if (*nrels_mag >= 1) {
}
@@ -788,68 +890,6 @@ void bmcsensors_alarms(struct i2c_client *client, int operation, int ctl_name,
#endif
}
void bmcsensors_fan_div(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
struct bmcsensors_data *data = client->data;
int old;
#if 0
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
bmcsensors_update_client(client);
results[0] = DIV_FROM_REG(data->fan_div[0]);
results[1] = DIV_FROM_REG(data->fan_div[1]);
*nrels_mag = 2;
} else if (operation == SENSORS_PROC_REAL_WRITE) {
old = bmcsensors_read_value(client, BMCSENSORS_REG_FANDIV);
if (*nrels_mag >= 2) {
data->fan_div[1] = DIV_TO_REG(results[1]);
old = (old & 0x3f) | (data->fan_div[1] << 6);
}
if (*nrels_mag >= 1) {
data->fan_div[0] = DIV_TO_REG(results[0]);
old = (old & 0xcf) | (data->fan_div[0] << 4);
bmcsensors_write_value(client, BMCSENSORS_REG_FANDIV, old);
}
}
#endif
}
void bmcsensors_pwm(struct i2c_client *client, int operation, int ctl_name,
int *nrels_mag, long *results)
{
struct bmcsensors_data *data = client->data;
#if 0
int nr = 1 + ctl_name - BMCSENSORS_SYSCTL_PWM1;
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
bmcsensors_update_client(client);
results[0] = PWM_FROM_REG(data->pwm[nr - 1]);
results[1] = data->pwm[nr - 1] >> 7;
*nrels_mag = 2;
} else if (operation == SENSORS_PROC_REAL_WRITE) {
if (*nrels_mag >= 1) {
data->pwm[nr - 1] &= 0x80;
data->pwm[nr - 1] |= PWM_TO_REG(results[0]);
if (*nrels_mag >= 2) {
if(results[1] && (!(data->pwm[nr-1] & 0x80))) {
/* output PWM */
bmcsensors_write_value(client,
BMCSENSORS_REG_PPIN(nr), 0x04);
data->pwm[nr - 1] |= 0x80;
}
}
bmcsensors_write_value(client, BMCSENSORS_REG_PWM(nr),
data->pwm[nr - 1]);
}
}
#endif
}
int __init sensors_bmcsensors_init(void)
{
int res, addr;