AMD PowerNow LKM contributed by Olaf 'Rhialto' Seibert.

This commit is contained in:
xtraeme 2006-01-11 00:18:28 +00:00
parent f32583d004
commit 8173ef37e7
6 changed files with 204 additions and 18 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: md.i386,v 1.115 2005/11/12 09:41:28 dsl Exp $
# $NetBSD: md.i386,v 1.116 2006/01/11 00:18:28 xtraeme Exp $
./dev/lms0 base-obsolete obsolete
./dev/mms0 base-obsolete obsolete
./dev/pms0 base-obsolete obsolete
@ -38,6 +38,7 @@
./usr/lkm/exec_linux_elf.o base-sys-lkm
./usr/lkm/exec_pecoff.o base-sys-lkm
./usr/lkm/exec_svr4_elf.o base-sys-lkm
./usr/lkm/powernow.o base-sys-lkm
./usr/lkm/wi_pcmcia.o base-sys-lkm
./usr/mdec/biosboot base-obsolete obsolete
./usr/mdec/biosboot.sym base-obsolete obsolete

View File

@ -1,4 +1,4 @@
/* $NetBSD: powernow_k7.c,v 1.2 2006/01/10 15:31:11 xtraeme Exp $ */
/* $NetBSD: powernow_k7.c,v 1.3 2006/01/11 00:18:28 xtraeme Exp $ */
/*
* Copyright (c) 2004 Martin Végiard.
@ -32,7 +32,7 @@
/* Sysctl related code was adapted from NetBSD's i386/est.c for compatibility */
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: powernow_k7.c,v 1.2 2006/01/10 15:31:11 xtraeme Exp $");
__KERNEL_RCSID(0, "$NetBSD: powernow_k7.c,v 1.3 2006/01/11 00:18:28 xtraeme Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -55,6 +55,11 @@ __KERNEL_RCSID(0, "$NetBSD: powernow_k7.c,v 1.2 2006/01/10 15:31:11 xtraeme Exp
#define cpufreq(x) fsb * fid_codes[x] / 10
/* pnowk7_init() already declared on i386/include/cpu.h */
#if defined(_LKM)
void pnowk7_destroy(void);
#endif
struct psb_s {
char signature[10]; /* AMDK7PNOW! */
uint8_t version;
@ -97,7 +102,13 @@ static unsigned int ttime;
static unsigned int n_states;
static struct freq_table_s *freq_table;
static int powernow_node_target, powernow_node_current;
static char *freq_names;
#if defined(_LKM)
static struct sysctllog *sysctllog;
#define SYSCTLLOG &sysctllog
#else
#define SYSCTLLOG NULL
#endif
/* Prototypes */
struct state_s *pnowk7_getstates(cpuid_t cpuid);
@ -260,7 +271,7 @@ pnowk7_init(struct cpu_info *ci)
{
int rc;
unsigned int i, freq_names_len, len = 0;
char *freq_names, *cpuname;
char *cpuname;
const struct sysctlnode *node, *pnownode, *freqnode;
struct state_s *s = pnowk7_getstates(ci->ci_signature);
@ -274,9 +285,8 @@ pnowk7_init(struct cpu_info *ci)
freq_names_len = n_states * (sizeof("9999 ")-1) + 1;
freq_names = malloc(freq_names_len, M_SYSCTLDATA, M_WAITOK);
freq_table = malloc(sizeof(struct freq_table_s) * n_states, \
M_TEMP, M_WAITOK);
freq_table = malloc(sizeof(struct freq_table_s) * n_states, M_TEMP,
M_WAITOK);
for (i = 0; i < n_states; i++, s++) {
freq_table[i].frequency = cpufreq(s->fid);
@ -286,49 +296,57 @@ pnowk7_init(struct cpu_info *ci)
freq_table[i].frequency, i < n_states - 1 ? " " : "");
}
/* On bootup the frequency should be at it's max */
/* On bootup the frequency should be at its max */
cur_freq = freq_table[i-1].frequency;
/* Create sysctl machdep.powernow.frequency. */
if ((rc = sysctl_createv(NULL, 0, NULL, &node,
if ((rc = sysctl_createv(SYSCTLLOG, 0, NULL, &node,
CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL)) != 0)
goto err;
if ((rc = sysctl_createv(NULL, 0, &node, &pnownode,
if ((rc = sysctl_createv(SYSCTLLOG, 0, &node, &pnownode,
0, CTLTYPE_NODE, "powernow", NULL,
NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
goto err;
if ((rc = sysctl_createv(NULL, 0, &pnownode, &freqnode,
if ((rc = sysctl_createv(SYSCTLLOG, 0, &pnownode, &freqnode,
0, CTLTYPE_NODE, "frequency", NULL,
NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
goto err;
if ((rc = sysctl_createv(NULL, 0, &freqnode, &node,
if ((rc = sysctl_createv(SYSCTLLOG, 0, &freqnode, &node,
CTLFLAG_READWRITE, CTLTYPE_INT, "target", NULL,
powernow_sysctl_helper, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
goto err;
powernow_node_target = node->sysctl_num;
if ((rc = sysctl_createv(NULL, 0, &freqnode, &node,
if ((rc = sysctl_createv(SYSCTLLOG, 0, &freqnode, &node,
0, CTLTYPE_INT, "current", NULL,
powernow_sysctl_helper, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
goto err;
powernow_node_current = node->sysctl_num;
if ((rc = sysctl_createv(NULL, 0, &freqnode, &node,
if ((rc = sysctl_createv(SYSCTLLOG, 0, &freqnode, &node,
0, CTLTYPE_STRING, "available", NULL,
NULL, 0, freq_names, freq_names_len, CTL_CREATE, CTL_EOL)) != 0)
goto err;
/* aprint_normal("AMD PowerNow supported current frequency : %d Mhz\n", \
cur_freq); */
aprint_normal("%s: AMD PowerNow! Technology supported\n", cpuname);
aprint_normal("%s: available frequencies (Mhz): %s\n",
cpuname, freq_names);
cpuname, freq_names);
aprint_normal("%s: current frequency (Mhz): %d\n", cpuname, cur_freq);
return;
err:
aprint_normal("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
}
#if defined(_LKM)
void
pnowk7_destroy(void)
{
sysctl_teardown(&sysctllog);
}
#endif

View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.1 2006/01/11 00:18:29 xtraeme Exp $
SUBDIR= powernow
.include <bsd.subdir.mk>

View File

@ -0,0 +1,5 @@
# $NetBSD: Makefile.inc,v 1.1 2006/01/11 00:18:29 xtraeme Exp $
S!= cd ${.CURDIR}/../../../..;pwd
.include "../../Makefile.inc"

View File

@ -0,0 +1,20 @@
# $NetBSD: Makefile,v 1.1 2006/01/11 00:18:29 xtraeme Exp $
#
# Makefile for loadable AMD PowerNow K7 device driver kernel module
#
.include "../Makefile.inc"
.PATH: $S/arch/i386/i386
CFILES= lkminit_powernow.c powernow_k7.c
SRCS= ${CFILES}
WARNS= 3
KMOD= powernow
MAN=
CLEANFILES+= *~ ${KMOD}
.include <bsd.kmod.mk>

View File

@ -0,0 +1,137 @@
/* $NetBSD: lkminit_powernow.c,v 1.1 2006/01/11 00:18:29 xtraeme Exp $ */
/*
* Derived from:
*
* Copyright (c) 1993 Terrence R. Lambert.
* Copyright (c) 2005 Olaf 'Rhialto' Seibert.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Terrence R. Lambert.
* 4. The name Terrence R. Lambert may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY TERRENCE R. LAMBERT ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: lkminit_powernow.c,v 1.1 2006/01/11 00:18:29 xtraeme Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lkm.h>
#include <sys/errno.h>
#include <machine/cpu.h>
int powernow_lkmentry(struct lkm_table *, int, int);
static int powernow_mod_handle(struct lkm_table *, int);
MOD_MISC("powernow");
void pnowk7_destroy(void);
/*
* This function is called each time the module is loaded or unloaded.
* Since we are a miscellaneous module, we have to provide whatever
* code is necessary to patch ourselves into the area we are being
* loaded to change.
*
* The stat information is basically common to all modules, so there
* is no real issue involved with stat; we will leave it lkm_nofunc(),
* since we don't have to do anything about it.
*/
static int
powernow_mod_handle(struct lkm_table *lkmtp, int cmd)
{
int err = 0; /* default = success*/
extern int sys_lkmnosys(struct lwp *, void *, register_t *);
struct cpu_info *ci;
uint32_t lfunc;
uint32_t descs[4];
switch (cmd) {
case LKM_E_LOAD:
/*
* Don't load twice! (lkmexists() is exported by kern_lkm.c)
*/
if (lkmexists(lkmtp))
return EEXIST;
/*
* Partial copy from /sys/arch/i386/i386/identcpu.c
* amd_family6_probe().
* This is only a partial protection against the wrong
* cpu.
*/
CPUID(0x80000000, lfunc, descs[1], descs[2], descs[3]);
ci = curcpu();
if (lfunc >= 0x80000007) {
CPUID(0x80000007, descs[0], descs[1], descs[2], descs[3]);
if ((descs[3] & 0x06)) {
if ((ci->ci_signature & 0xF00) == 0x600)
pnowk7_init(ci);
}
}
break; /* Success */
case LKM_E_UNLOAD:
pnowk7_destroy();
break; /* Success */
default: /* we only understand load/unload*/
err = EINVAL;
break;
}
return err;
}
/*
* External entry point; should generally match name of .o file + '_lkmentry'.
* The arguments are always the same for all loaded modules. The "load",
* "unload", and "stat" functions in "DISPATCH" will be called under
* their respective circumstances. If no function is desired, lkm_nofunc()
* should be supplied. They are called with the same arguments (cmd is
* included to allow the use of a single function, ver is included for
* version matching between modules and the kernel loader for the modules).
*
* Since we expect to link in the kernel and add external symbols to
* the kernel symbol name space in a future version, generally all
* functions used in the implementation of a particular module should
* be static unless they are expected to be seen in other modules or
* to resolve unresolved symbols alread existing in the kernel (the
* second case is not likely to ever occur).
*
* The entry point should return 0 unless it is refusing load (in which
* case it should return an errno from errno.h).
*/
int
powernow_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
{
DISPATCH(lkmtp, cmd, ver, powernow_mod_handle,
powernow_mod_handle, lkm_nofunc)
}