void k8_powernow_init(struct cpu_info *ci) { uint64_t status; u_int maxfid, maxvid, i; u_int32_t extcpuid, dummy; struct k8pnow_cpu_state *cstate; struct k8pnow_state *state; char * techname = NULL; if (setperf_prio > 1) return; cstate = malloc(sizeof(struct k8pnow_cpu_state), M_DEVBUF, M_NOWAIT); if (!cstate) return; cstate->n_states = 0; status = rdmsr(MSR_AMDK7_FIDVID_STATUS); maxfid = PN8_STA_MFID(status); maxvid = PN8_STA_MVID(status); /* * If start FID is different to max FID, then it is a * mobile processor. If not, it is a low powered desktop * processor. */ if (PN8_STA_SFID(status) != PN8_STA_MFID(status)) techname = "PowerNow! K8"; else techname = "Cool'n'Quiet K8"; #if NACPICPU > 0 /* If we have acpi check acpi first */ if (!k8pnow_acpi_init(cstate, status)) #endif { if (!k8pnow_states(cstate, ci->ci_signature, maxfid, maxvid)) { /* Extended CPUID signature value */ CPUID(0x80000001, extcpuid, dummy, dummy, dummy); k8pnow_states(cstate, extcpuid, maxfid, maxvid); } } if (cstate->n_states) { printf("%s: %s %d MHz: speeds:", ci->ci_dev->dv_xname, techname, cpuspeed); for (i = cstate->n_states; i > 0; i--) { state = &cstate->state_table[i-1]; printf(" %d", state->freq); } printf(" MHz\n"); k8pnow_current_state = cstate; cpu_setperf = k8_powernow_setperf; setperf_prio = 1; return; } free(cstate, M_DEVBUF, sizeof(*cstate)); }
static int powernow_init(void) { uint64_t status; size_t len , freq_len; uint32_t maxfid, maxvid, i; struct k8pnow_cpu_state *cstate; struct k8pnow_state *state; const char *techname; u_int32_t regs [4]; cpuspeed = 0; struct sysctl_oid *oid, *leaf; do_cpuid(0x80000000, regs); if (regs[0] < 0x80000007) return 1; do_cpuid(0x80000007, regs); if (!(regs[3] & AMD_PN_FID_VID)) return 2; /* Extended CPUID signature value */ do_cpuid(0x80000001, regs); cstate = kmalloc(sizeof(struct k8pnow_cpu_state), M_DEVBUF, M_WAITOK); cstate->n_states = 0; status = rdmsr(MSR_AMDK7_FIDVID_STATUS); maxfid = PN8_STA_MFID(status); maxvid = PN8_STA_MVID(status); if (PN8_STA_SFID(status) != PN8_STA_MFID(status)) techname = "PowerNow!"; else techname = "Cool`n'Quiet"; k8pnow_states(cstate, regs[0], maxfid, maxvid); len = 0; if (cstate->n_states) { freq_len = cstate->n_states * (sizeof("9999 ") - 1) + 1; kprintf("%s speeds:", techname); for (i = cstate->n_states; i > 0; i--) { state = &cstate->state_table[i - 1]; kprintf(" %d", state->freq); len += ksnprintf(freqs_available + len, freq_len - len, "%d%s", state->freq, i > 1 ? " " : ""); } kprintf(" MHz\n"); k8pnow_current_state = cstate; k8_powernow_setperf(k8_get_curfreq()); } else { kfree(cstate, M_DEVBUF); kprintf("powernow: no power states found\n"); return 3; } /* * Setup the sysctl sub-tree machdep.powernow.* */ oid = SYSCTL_ADD_NODE(&machdep_powernow_ctx, SYSCTL_STATIC_CHILDREN(_machdep), OID_AUTO, "powernow", CTLFLAG_RD, NULL, ""); if (oid == NULL) return (EOPNOTSUPP); oid = SYSCTL_ADD_NODE(&machdep_powernow_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "frequency", CTLFLAG_RD, NULL, ""); if (oid == NULL) return (EOPNOTSUPP); leaf = SYSCTL_ADD_PROC(&machdep_powernow_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "target", CTLTYPE_INT | CTLFLAG_RW, NULL, 0, powernow_sysctl_helper, "I", "Target CPU frequency for AMD PowerNow!"); if (leaf == NULL) return (EOPNOTSUPP); leaf = SYSCTL_ADD_PROC(&machdep_powernow_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "current", CTLTYPE_INT | CTLFLAG_RD, NULL, 0, powernow_sysctl_helper, "I", "Current CPU frequency for AMD PowerNow!"); if (leaf == NULL) return (EOPNOTSUPP); leaf = SYSCTL_ADD_STRING(&machdep_powernow_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "available", CTLFLAG_RD, freqs_available, sizeof(freqs_available), "CPU frequencies supported by AMD PowerNow!"); if (leaf == NULL) return (EOPNOTSUPP); return (0); }