Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/i386/i386 Add transmeta crusoe cpu support from tos...



details:   https://anonhg.NetBSD.org/src/rev/8da91a79ffd7
branches:  trunk
changeset: 517694:8da91a79ffd7
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Nov 17 08:20:58 2001 +0000

description:
Add transmeta crusoe cpu support from toshi's fiva patches.

diffstat:

 sys/arch/i386/i386/machdep.c |  258 ++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 255 insertions(+), 3 deletions(-)

diffs (truncated from 314 to 300 lines):

diff -r bf0d20343acf -r 8da91a79ffd7 sys/arch/i386/i386/machdep.c
--- a/sys/arch/i386/i386/machdep.c      Sat Nov 17 07:22:34 2001 +0000
+++ b/sys/arch/i386/i386/machdep.c      Sat Nov 17 08:20:58 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.460 2001/11/15 07:03:30 lukem Exp $      */
+/*     $NetBSD: machdep.c,v 1.461 2001/11/17 08:20:58 christos Exp $   */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc.
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.460 2001/11/15 07:03:30 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.461 2001/11/17 08:20:58 christos Exp $");
 
 #include "opt_cputype.h"
 #include "opt_ddb.h"
@@ -213,6 +213,8 @@
 int    i386_has_sse;
 int    i386_has_sse2;
 
+int    tmx86_has_longrun;
+
 #define        CPUID2FAMILY(cpuid)     (((cpuid) >> 8) & 15)
 #define        CPUID2MODEL(cpuid)      (((cpuid) >> 4) & 15)
 #define        CPUID2STEPPING(cpuid)   ((cpuid) & 15)
@@ -273,6 +275,7 @@
 void cyrix6x86_cpu_setup __P((void));
 void winchip_cpu_setup __P((void));
 void amd_family5_setup __P((void));
+void transmeta_cpu_setup __P((void));
 
 void intel_cpuid_cpu_cacheinfo __P((struct cpu_info *));
 void amd_cpuid_cpu_cacheinfo __P((struct cpu_info *));
@@ -883,6 +886,55 @@
                        NULL,
                        NULL,
                } }
+       },
+       {
+               "GenuineTMx86",
+               CPUVENDOR_TRANSMETA,
+               "Transmeta",
+               /* Family 4, Transmeta never had any of these */
+               { {
+                       CPUCLASS_486, 
+                       {
+                               0, 0, 0, 0, 0, 0, 0,
+                               0, 0, 0, 0, 0, 0, 0, 0, 0,
+                               "486 compatible"        /* Default */
+                       },
+                       NULL,
+                       NULL,
+               },
+               /* Family 5 */
+               {
+                       CPUCLASS_586,
+                       {
+                               0, 0, 0, 0, 0, 0, 0,
+                               0, 0, 0, 0, 0, 0, 0, 0, 0,
+                               "Crusoe"                /* Default */
+                       },
+                       transmeta_cpu_setup,
+                       NULL,
+               },
+               /* Family 6, not yet available from Transmeta */
+               {
+                       CPUCLASS_686,
+                       {
+                               0, 0, 0, 0, 0, 0, 0,
+                               0, 0, 0, 0, 0, 0, 0, 0, 0,
+                               "Pentium Pro compatible"        /* Default */
+                       },
+                       NULL,
+                       NULL,
+               },
+               /* Family > 6, not yet available from Transmeta */
+               {
+                       CPUCLASS_686,
+                       {
+                               0, 0, 0, 0, 0, 0, 0,
+                               0, 0, 0, 0, 0, 0, 0, 0, 0,
+                               "Pentium Pro compatible"        /* Default */
+                       },
+                       NULL,
+                       NULL,
+               } }
        }
 };
 
@@ -978,6 +1030,178 @@
        }
 }
 
+/*
+ * Transmeta Crusoe LongRun Support by Tamotsu Hattori.
+ * Port from FreeBSD-current(August, 2001) to NetBSD by tshiozak.
+ */
+
+#define MSR_TMx86_LONGRUN              0x80868010
+#define MSR_TMx86_LONGRUN_FLAGS                0x80868011
+
+#define LONGRUN_MODE_MASK(x)           ((x) & 0x000000007f)
+#define LONGRUN_MODE_RESERVED(x)       ((x) & 0xffffff80)
+#define LONGRUN_MODE_WRITE(x, y)       (LONGRUN_MODE_RESERVED(x) | LONGRUN_MODE_MASK(y))
+
+#define LONGRUN_MODE_MINFREQUENCY      0x00
+#define LONGRUN_MODE_ECONOMY           0x01
+#define LONGRUN_MODE_PERFORMANCE       0x02
+#define LONGRUN_MODE_MAXFREQUENCY      0x03
+#define LONGRUN_MODE_UNKNOWN           0x04
+#define LONGRUN_MODE_MAX               0x04
+
+union msrinfo {
+       u_int64_t       msr;
+       u_int32_t       regs[2];
+};
+
+u_int32_t longrun_modes[LONGRUN_MODE_MAX][3] = {
+       /*  MSR low, MSR high, flags bit0 */
+       {         0,      0,            0},     /* LONGRUN_MODE_MINFREQUENCY */
+       {         0,    100,            0},     /* LONGRUN_MODE_ECONOMY */
+       {         0,    100,            1},     /* LONGRUN_MODE_PERFORMANCE */
+       {       100,    100,            1},     /* LONGRUN_MODE_MAXFREQUENCY */
+};
+
+static u_int 
+tmx86_get_longrun_mode(void)
+{
+       u_long          eflags;
+       union msrinfo   msrinfo;
+       u_int           low, high, flags, mode;
+
+       eflags = read_eflags();
+       disable_intr();
+
+       msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
+       low = LONGRUN_MODE_MASK(msrinfo.regs[0]);
+       high = LONGRUN_MODE_MASK(msrinfo.regs[1]);
+       flags = rdmsr(MSR_TMx86_LONGRUN_FLAGS) & 0x01;
+
+       for (mode = 0; mode < LONGRUN_MODE_MAX; mode++) {
+               if (low   == longrun_modes[mode][0] &&
+                   high  == longrun_modes[mode][1] &&
+                   flags == longrun_modes[mode][2]) {
+                       goto out;
+               }
+       }
+       mode = LONGRUN_MODE_UNKNOWN;
+out:
+       write_eflags(eflags);
+       return (mode);
+}
+
+static u_int 
+tmx86_get_longrun_status(u_int * frequency, u_int * voltage, u_int * percentage)
+{
+       u_long          eflags;
+       u_int           regs[4];
+
+       eflags = read_eflags();
+       disable_intr();
+
+       do_cpuid(0x80860007, regs);
+       *frequency = regs[0];
+       *voltage = regs[1];
+       *percentage = regs[2];
+
+       write_eflags(eflags);
+       return (1);
+}
+
+static u_int 
+tmx86_set_longrun_mode(u_int mode)
+{
+       u_long          eflags;
+       union msrinfo   msrinfo;
+
+       if (mode >= LONGRUN_MODE_UNKNOWN) {
+               return (0);
+       }
+
+       eflags = read_eflags();
+       disable_intr();
+
+       /* Write LongRun mode values to Model Specific Register. */
+       msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN);
+       msrinfo.regs[0] = LONGRUN_MODE_WRITE(msrinfo.regs[0],
+                                            longrun_modes[mode][0]);
+       msrinfo.regs[1] = LONGRUN_MODE_WRITE(msrinfo.regs[1],
+                                            longrun_modes[mode][1]);
+       wrmsr(MSR_TMx86_LONGRUN, msrinfo.msr);
+
+       /* Write LongRun mode flags to Model Specific Register. */
+       msrinfo.msr = rdmsr(MSR_TMx86_LONGRUN_FLAGS);
+       msrinfo.regs[0] = (msrinfo.regs[0] & ~0x01) | longrun_modes[mode][2];
+       wrmsr(MSR_TMx86_LONGRUN_FLAGS, msrinfo.msr);
+
+       write_eflags(eflags);
+       return (1);
+}
+
+static u_int                    crusoe_longrun;
+static u_int                    crusoe_frequency;
+static u_int                    crusoe_voltage;
+static u_int                    crusoe_percentage;
+
+static void
+tmx86_get_longrun_status_all(void)
+{
+       tmx86_get_longrun_status(&crusoe_frequency,
+                                &crusoe_voltage, &crusoe_percentage);
+}
+
+
+static void
+print_transmeta_info(void)
+{
+       u_int regs[4], nreg = 0;
+
+       do_cpuid(0x80860000, regs);
+       nreg = regs[0];
+       if (nreg >= 0x80860001) {
+               do_cpuid(0x80860001, regs);
+               printf("  Processor revision %u.%u.%u.%u\n",
+                      (regs[1] >> 24) & 0xff,
+                      (regs[1] >> 16) & 0xff,
+                      (regs[1] >> 8) & 0xff,
+                      regs[1] & 0xff);
+       }
+       if (nreg >= 0x80860002) {
+               do_cpuid(0x80860002, regs);
+               printf("  Code Morphing Software revision %u.%u.%u-%u-%u\n",
+                      (regs[1] >> 24) & 0xff,
+                      (regs[1] >> 16) & 0xff,
+                      (regs[1] >> 8) & 0xff,
+                      regs[1] & 0xff,
+                      regs[2]);
+       }
+       if (nreg >= 0x80860006) {
+               char info[65];
+               do_cpuid(0x80860003, (u_int*) &info[0]);
+               do_cpuid(0x80860004, (u_int*) &info[16]);
+               do_cpuid(0x80860005, (u_int*) &info[32]);
+               do_cpuid(0x80860006, (u_int*) &info[48]);
+               info[64] = 0;
+               printf("  %s\n", info);
+       }
+
+       crusoe_longrun = tmx86_get_longrun_mode();
+       tmx86_get_longrun_status(&crusoe_frequency,
+                                &crusoe_voltage, &crusoe_percentage);
+       printf("  LongRun mode: %d  <%dMHz %dmV %d%%>\n", crusoe_longrun,
+              crusoe_frequency, crusoe_voltage, crusoe_percentage);
+}
+
+void
+transmeta_cpu_setup(void)
+{
+       tmx86_has_longrun = 1;
+       print_transmeta_info();
+}
+
+
+/* ---------------------------------------------------------------------- */
+
 static const struct i386_cache_info *
 cache_info_lookup(const struct i386_cache_info *cai, int count, u_int8_t desc)
 {
@@ -1597,6 +1821,7 @@
 {
        dev_t consdev;
        struct btinfo_bootpath *bibp;
+       int error, mode;
 
        /* all sysctl names at this level are terminal */
        if (namelen != 1)
@@ -1640,7 +1865,34 @@
                return (sysctl_rdint(oldp, oldlenp, newp, i386_has_sse));
        case CPU_SSE2:
                return (sysctl_rdint(oldp, oldlenp, newp, i386_has_sse2));
-
+       case CPU_TMLR_MODE:
+               if (!tmx86_has_longrun)
+                       return (EOPNOTSUPP);
+               mode = (int)(crusoe_longrun = tmx86_get_longrun_mode());
+               error = sysctl_int(oldp, oldlenp, newp, newlen, &mode);
+               if (!error && (u_int)mode!=crusoe_longrun) {
+                       if (tmx86_set_longrun_mode(mode)) {
+                               crusoe_longrun = (u_int)mode;
+                       } else {
+                               error = EINVAL;
+                       }
+               }
+               return (error);
+       case CPU_TMLR_FREQUENCY:
+               if (!tmx86_has_longrun)
+                       return (EOPNOTSUPP);
+               tmx86_get_longrun_status_all();



Home | Main Index | Thread Index | Old Index