/* Fill SMU command structure */
cmd.cmd = SMU_CMD_FAN_COMMAND;
/* The SMU has an "old" and a "new" way of setting the fan speed * Unfortunately, I found no reliable way to know which one works * on a given machine model. After some investigations it appears * that MacOS X just tries the new one, and if it fails fallbacks * to the old ones ... Ugh.
*/
retry: if (smu_supports_new_fans_ops) {
buffer[0] = 0x30;
buffer[1] = id;
*((u16 *)(&buffer[2])) = value;
cmd.data_len = 4;
} else { if (id > 7) return -EINVAL; /* Fill argument buffer */
memset(buffer, 0, 16);
buffer[0] = pwm ? 0x10 : 0x00;
buffer[1] = 0x01 << id;
*((u16 *)&buffer[2 + id * 2]) = value;
cmd.data_len = 14;
}
rc = smu_queue_cmd(&cmd); if (rc) return rc;
wait_for_completion(&comp);
/* Handle fallback (see comment above) */ if (cmd.status != 0 && smu_supports_new_fans_ops) {
printk(KERN_WARNING "windfarm: SMU failed new fan command " "falling back to old method\n");
smu_supports_new_fans_ops = 0; goto retry;
}
/* We use the name & location here the same way we do for SMU sensors, * see the comment in windfarm_smu_sensors.c. The locations are a bit * less consistent here between the iMac and the desktop models, but * that is good enough for our needs for now at least. * * One problem though is that Apple seem to be inconsistent with case * and the kernel doesn't have strcasecmp =P
*/
fct->ctrl.name = NULL;
/* Names used on desktop models */ if (!strcmp(l, "Rear Fan 0") || !strcmp(l, "Rear Fan") ||
!strcmp(l, "Rear fan 0") || !strcmp(l, "Rear fan") ||
!strcmp(l, "CPU A EXHAUST"))
fct->ctrl.name = "cpu-rear-fan-0"; elseif (!strcmp(l, "Rear Fan 1") || !strcmp(l, "Rear fan 1") ||
!strcmp(l, "CPU B EXHAUST"))
fct->ctrl.name = "cpu-rear-fan-1"; elseif (!strcmp(l, "Front Fan 0") || !strcmp(l, "Front Fan") ||
!strcmp(l, "Front fan 0") || !strcmp(l, "Front fan") ||
!strcmp(l, "CPU A INTAKE"))
fct->ctrl.name = "cpu-front-fan-0"; elseif (!strcmp(l, "Front Fan 1") || !strcmp(l, "Front fan 1") ||
!strcmp(l, "CPU B INTAKE"))
fct->ctrl.name = "cpu-front-fan-1"; elseif (!strcmp(l, "CPU A PUMP"))
fct->ctrl.name = "cpu-pump-0"; elseif (!strcmp(l, "CPU B PUMP"))
fct->ctrl.name = "cpu-pump-1"; elseif (!strcmp(l, "Slots Fan") || !strcmp(l, "Slots fan") ||
!strcmp(l, "EXPANSION SLOTS INTAKE"))
fct->ctrl.name = "slots-fan"; elseif (!strcmp(l, "Drive Bay") || !strcmp(l, "Drive bay") ||
!strcmp(l, "DRIVE BAY A INTAKE"))
fct->ctrl.name = "drive-bay-fan"; elseif (!strcmp(l, "BACKSIDE"))
fct->ctrl.name = "backside-fan";
/* Unrecognized fan, bail out */ if (fct->ctrl.name == NULL) goto fail;
/* Get min & max values*/
v = of_get_property(node, "min-value", NULL); if (v == NULL) goto fail;
fct->min = *v;
v = of_get_property(node, "max-value", NULL); if (v == NULL) goto fail;
fct->max = *v;
/* Get "reg" value */
reg = of_get_property(node, "reg", NULL); if (reg == NULL) goto fail;
fct->reg = *reg;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.