#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/conf.h>
#include <machine/amdmsr.h>
#include <machine/cpufunc.h>
#ifdef APERTURE
static int amdmsr_open_cnt;
extern int allowaperture;
#endif
#define GLX_CPU_GLD_MSR_CAP 0x00002000
#define GLX_CPU_DID 0x0864
#define GLX_GP_GLD_MSR_CAP 0xa0002000
#define GLX_GP_DID 0x03d4
struct amdmsr_softc {
struct device sc_dev;
};
struct cfdriver amdmsr_cd = {
NULL, "amdmsr", DV_DULL
};
int amdmsr_match(struct device *, void *, void *);
void amdmsr_attach(struct device *, struct device *, void *);
const struct cfattach amdmsr_ca = {
sizeof(struct amdmsr_softc), amdmsr_match, amdmsr_attach
};
int
amdmsr_probe(void)
{
#ifdef APERTURE
u_int64_t gld_msr_cap;
int family, model;
family = (cpu_id >> 8) & 0xf;
model = (cpu_id >> 4) & 0xf;
if (strcmp(cpu_vendor, "AuthenticAMD") == 0 && family == 0x5 &&
model == 0x0a) {
gld_msr_cap = rdmsr(GLX_CPU_GLD_MSR_CAP);
if (((gld_msr_cap >> 8) & 0x0fff) == GLX_CPU_DID) {
gld_msr_cap = rdmsr(GLX_GP_GLD_MSR_CAP);
if (((gld_msr_cap >> 8) & 0x0fff) == GLX_GP_DID)
return 1;
}
}
#endif
return 0;
}
int
amdmsr_match(struct device *parent, void *match, void *aux)
{
const char **busname = (const char **)aux;
return (strcmp(*busname, amdmsr_cd.cd_name) == 0);
}
void
amdmsr_attach(struct device *parent, struct device *self, void *aux)
{
printf("\n");
}
int
amdmsropen(dev_t dev, int flags, int devtype, struct proc *p)
{
#ifdef APERTURE
if (amdmsr_cd.cd_ndevs == 0 || minor(dev) != 0)
return ENXIO;
if (suser(p) != 0 || !allowaperture)
return EPERM;
if (amdmsr_open_cnt > 0)
return EPERM;
amdmsr_open_cnt++;
return 0;
#else
return ENXIO;
#endif
}
int
amdmsrclose(dev_t dev, int flags, int devtype, struct proc *p)
{
#ifdef APERTURE
amdmsr_open_cnt--;
#endif
return 0;
}
int
amdmsrioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
struct amdmsr_req *req = (struct amdmsr_req *)data;
switch (cmd) {
case RDMSR:
req->val = rdmsr(req->addr);
break;
case WRMSR:
wrmsr(req->addr, req->val);
break;
default:
return EINVAL;
}
return 0;
}