static int abituguru_send_address(struct abituguru_data *data, u8 bank_addr, u8 sensor_addr, int retries) { int report_errors = retries; for (;;) { if (abituguru_ready(data) != 0) return -EIO; outb(bank_addr, data->addr + ABIT_UGURU_DATA); data->uguru_ready = 0; if (abituguru_wait(data, ABIT_UGURU_STATUS_INPUT)) { if (retries) { ABIT_UGURU_DEBUG(3, "timeout exceeded " "waiting for more input state, %d " "tries remaining\n", retries); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(ABIT_UGURU_RETRY_DELAY); retries--; continue; } if (report_errors) ABIT_UGURU_DEBUG(1, "timeout exceeded " "waiting for more input state " "(bank: %d)\n", (int)bank_addr); return -EBUSY; } outb(sensor_addr, data->addr + ABIT_UGURU_CMD); return 0; } }
static struct abituguru_data *abituguru_update_device(struct device *dev) { int i, err; struct abituguru_data *data = dev_get_drvdata(dev); char success = 1; mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ)) { success = 0; err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, data->alarms, 3, 0); if (err != 3) goto LEAVE_UPDATE; for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i, &data->bank1_value[i], 1, 0); if (err != 1) goto LEAVE_UPDATE; err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, i, data->bank1_settings[i], 3, 0); if (err != 3) goto LEAVE_UPDATE; } for (i = 0; i < data->bank2_sensors; i++) { err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i, &data->bank2_value[i], 1, 0); if (err != 1) goto LEAVE_UPDATE; } success = 1; data->update_timeouts = 0; LEAVE_UPDATE: if (!success && (err == -EBUSY || err >= 0)) { if (data->update_timeouts < 255u) data->update_timeouts++; if (data->update_timeouts <= ABIT_UGURU_MAX_TIMEOUTS) { ABIT_UGURU_DEBUG(3, "timeout exceeded, will " "try again next update\n"); success = 1; } else ABIT_UGURU_DEBUG(1, "timeout exceeded %d " "times waiting for more input state\n", (int)data->update_timeouts); } if (success) data->last_updated = jiffies; } mutex_unlock(&data->update_lock); if (success) return data; else return NULL; }
static int abituguru_write(struct abituguru_data *data, u8 bank_addr, u8 sensor_addr, u8 *buf, int count) { int i, timeout = ABIT_UGURU_READY_TIMEOUT; i = abituguru_send_address(data, bank_addr, sensor_addr, ABIT_UGURU_MAX_RETRIES); if (i) return i; for (i = 0; i < count; i++) { if (abituguru_wait(data, ABIT_UGURU_STATUS_WRITE)) { ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for " "write state (bank: %d, sensor: %d)\n", (int)bank_addr, (int)sensor_addr); break; } outb(buf[i], data->addr + ABIT_UGURU_CMD); } if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state " "after write (bank: %d, sensor: %d)\n", (int)bank_addr, (int)sensor_addr); return -EIO; } while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { timeout--; if (timeout == 0) { ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after " "write (bank: %d, sensor: %d)\n", (int)bank_addr, (int)sensor_addr); return -EIO; } msleep(0); } abituguru_ready(data); return i; }
static int abituguru_read(struct abituguru_data *data, u8 bank_addr, u8 sensor_addr, u8 *buf, int count, int retries) { int i; i = abituguru_send_address(data, bank_addr, sensor_addr, retries); if (i) return i; for (i = 0; i < count; i++) { if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { ABIT_UGURU_DEBUG(retries ? 1 : 3, "timeout exceeded waiting for " "read state (bank: %d, sensor: %d)\n", (int)bank_addr, (int)sensor_addr); break; } buf[i] = inb(data->addr + ABIT_UGURU_CMD); } abituguru_ready(data); return i; }
static int abituguru_ready(struct abituguru_data *data) { int timeout = ABIT_UGURU_READY_TIMEOUT; if (data->uguru_ready) return 0; outb(0x00, data->addr + ABIT_UGURU_DATA); if (abituguru_wait(data, ABIT_UGURU_STATUS_READY)) { ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for ready state\n"); return -EIO; } while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { timeout--; if (timeout == 0) { ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after ready command\n"); return -EIO; } msleep(0); } timeout = ABIT_UGURU_READY_TIMEOUT; while (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT) { timeout--; if (timeout == 0) { ABIT_UGURU_DEBUG(1, "state != more input after ready command\n"); return -EIO; } msleep(0); } data->uguru_ready = 1; return 0; }
static int __init abituguru_detect(void) { u8 cmd_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_CMD); u8 data_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_DATA); if (((data_val == 0x00) || (data_val == 0x08)) && ((cmd_val == 0x00) || (cmd_val == 0xAC))) return ABIT_UGURU_BASE; ABIT_UGURU_DEBUG(2, "no Abit uGuru found, data = 0x%02X, cmd = " "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); if (force) { pr_info("Assuming Abit uGuru is present because of \"force\" parameter\n"); return ABIT_UGURU_BASE; } return -ENODEV; }
static void __devinit abituguru_detect_no_bank2_sensors(struct abituguru_data *data) { int i; if (fan_sensors > 0 && fan_sensors <= ABIT_UGURU_MAX_BANK2_SENSORS) { data->bank2_sensors = fan_sensors; ABIT_UGURU_DEBUG(2, "assuming %d fan sensors because of " "\"fan_sensors\" module param\n", (int)data->bank2_sensors); return; } ABIT_UGURU_DEBUG(2, "detecting number of fan sensors\n"); for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { if (data->bank2_settings[i][0] & ~0xC9) { ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " "to be a fan sensor: settings[0] = %02X\n", i, (unsigned int)data->bank2_settings[i][0]); break; } if (data->bank2_settings[i][1] < abituguru_bank2_min_threshold) { ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " "to be a fan sensor: the threshold (%d) is " "below the minimum (%d)\n", i, (int)data->bank2_settings[i][1], (int)abituguru_bank2_min_threshold); break; } if (data->bank2_settings[i][1] > abituguru_bank2_max_threshold) { ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " "to be a fan sensor: the threshold (%d) is " "above the maximum (%d)\n", i, (int)data->bank2_settings[i][1], (int)abituguru_bank2_max_threshold); break; } } data->bank2_sensors = i; ABIT_UGURU_DEBUG(2, " found: %d fan sensors\n", (int)data->bank2_sensors); }
static void __devinit abituguru_detect_no_pwms(struct abituguru_data *data) { int i, j; if (pwms > 0 && pwms <= ABIT_UGURU_MAX_PWMS) { data->pwms = pwms; ABIT_UGURU_DEBUG(2, "assuming %d PWM outputs because of " "\"pwms\" module param\n", (int)data->pwms); return; } ABIT_UGURU_DEBUG(2, "detecting number of PWM outputs\n"); for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { if (data->pwm_settings[i][0] & ~0x8F) { ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " "to be a pwm channel: settings[0] = %02X\n", i, (unsigned int)data->pwm_settings[i][0]); break; } for (j = 0; j < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; j++) { if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][j] == (data->pwm_settings[i][0] & 0x0F)) break; } if (j == data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) { ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " "to be a pwm channel: %d is not a valid temp " "sensor address\n", i, data->pwm_settings[i][0] & 0x0F); break; } for (j = 1; j < 5; j++) { u8 min; if ((i == 0) && ((j == 1) || (j == 2))) min = 77; else min = abituguru_pwm_min[j]; if (data->pwm_settings[i][j] < min) { ABIT_UGURU_DEBUG(2, " pwm channel %d does " "not seem to be a pwm channel: " "setting %d (%d) is below the minimum " "value (%d)\n", i, j, (int)data->pwm_settings[i][j], (int)min); goto abituguru_detect_no_pwms_exit; } if (data->pwm_settings[i][j] > abituguru_pwm_max[j]) { ABIT_UGURU_DEBUG(2, " pwm channel %d does " "not seem to be a pwm channel: " "setting %d (%d) is above the maximum " "value (%d)\n", i, j, (int)data->pwm_settings[i][j], (int)abituguru_pwm_max[j]); goto abituguru_detect_no_pwms_exit; } } if (data->pwm_settings[i][1] >= data->pwm_settings[i][2]) { ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " "to be a pwm channel: min pwm (%d) >= " "max pwm (%d)\n", i, (int)data->pwm_settings[i][1], (int)data->pwm_settings[i][2]); break; } if (data->pwm_settings[i][3] >= data->pwm_settings[i][4]) { ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " "to be a pwm channel: min temp (%d) >= " "max temp (%d)\n", i, (int)data->pwm_settings[i][3], (int)data->pwm_settings[i][4]); break; } } abituguru_detect_no_pwms_exit: data->pwms = i; ABIT_UGURU_DEBUG(2, " found: %d PWM outputs\n", (int)data->pwms); }
static int __devinit abituguru_detect_bank1_sensor_type(struct abituguru_data *data, u8 sensor_addr) { u8 val, test_flag, buf[3]; int i, ret = -ENODEV; if (bank1_types[sensor_addr] >= ABIT_UGURU_IN_SENSOR && bank1_types[sensor_addr] <= ABIT_UGURU_NC) { ABIT_UGURU_DEBUG(2, "assuming sensor type %d for bank1 sensor " "%d because of \"bank1_types\" module param\n", bank1_types[sensor_addr], (int)sensor_addr); return bank1_types[sensor_addr]; } if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, sensor_addr, &val, 1, ABIT_UGURU_MAX_RETRIES) != 1) return -ENODEV; if ((val < 10u) || (val > 250u)) { pr_warn("bank1-sensor: %d reading (%d) too close to limits, " "unable to determine sensor type, skipping sensor\n", (int)sensor_addr, (int)val); return ABIT_UGURU_NC; } ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr); if (val <= 240u) { buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE; buf[1] = 245; buf[2] = 250; test_flag = ABIT_UGURU_VOLT_LOW_ALARM_FLAG; } else { buf[0] = ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE; buf[1] = 5; buf[2] = 10; test_flag = ABIT_UGURU_VOLT_HIGH_ALARM_FLAG; } if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, buf, 3) != 3) goto abituguru_detect_bank1_sensor_type_exit; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/50); if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) goto abituguru_detect_bank1_sensor_type_exit; if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, sensor_addr, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) goto abituguru_detect_bank1_sensor_type_exit; if (buf[0] & test_flag) { ABIT_UGURU_DEBUG(2, " found volt sensor\n"); ret = ABIT_UGURU_IN_SENSOR; goto abituguru_detect_bank1_sensor_type_exit; } else ABIT_UGURU_DEBUG(2, " alarm raised during volt " "sensor test, but volt range flag not set\n"); } else ABIT_UGURU_DEBUG(2, " alarm not raised during volt sensor " "test\n"); buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE; buf[1] = 5; buf[2] = 10; if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, buf, 3) != 3) goto abituguru_detect_bank1_sensor_type_exit; set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/20); if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) goto abituguru_detect_bank1_sensor_type_exit; if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, sensor_addr, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) goto abituguru_detect_bank1_sensor_type_exit; if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) { ABIT_UGURU_DEBUG(2, " found temp sensor\n"); ret = ABIT_UGURU_TEMP_SENSOR; goto abituguru_detect_bank1_sensor_type_exit; } else ABIT_UGURU_DEBUG(2, " alarm raised during temp " "sensor test, but temp high flag not set\n"); } else ABIT_UGURU_DEBUG(2, " alarm not raised during temp sensor " "test\n"); ret = ABIT_UGURU_NC; abituguru_detect_bank1_sensor_type_exit: for (i = 0; i < 3; i++) if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, data->bank1_settings[sensor_addr], 3) == 3) break; if (i == 3) { pr_err("Fatal error could not restore original settings. %s %s\n", never_happen, report_this); return -ENODEV; } return ret; }