/* 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.
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.