patch-2.4.5 linux/arch/i386/kernel/mtrr.c
Next file: linux/arch/i386/kernel/pci-i386.c
Previous file: linux/arch/i386/kernel/i386_ksyms.c
Back to the patch index
Back to the overall index
- Lines: 238
- Date:
Thu May 24 15:14:08 2001
- Orig file:
v2.4.4/linux/arch/i386/kernel/mtrr.c
- Orig date:
Wed Apr 11 19:02:27 2001
diff -u --recursive --new-file v2.4.4/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
@@ -646,12 +646,32 @@
unsigned long low;
} centaur_mcr[8];
+static u8 centaur_mcr_reserved;
+static u8 centaur_mcr_type; /* 0 for winchip, 1 for winchip2 */
+
+/*
+ * Report boot time MCR setups
+ */
+
+void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
+{
+ centaur_mcr[mcr].low = lo;
+ centaur_mcr[mcr].high = hi;
+}
+
static void centaur_get_mcr (unsigned int reg, unsigned long *base,
unsigned long *size, mtrr_type *type)
{
*base = centaur_mcr[reg].high >> PAGE_SHIFT;
*size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT;
*type = MTRR_TYPE_WRCOMB; /* If it is there, it is write-combining */
+ if(centaur_mcr_type==1 && ((centaur_mcr[reg].low&31)&2))
+ *type = MTRR_TYPE_UNCACHABLE;
+ if(centaur_mcr_type==1 && (centaur_mcr[reg].low&31)==25)
+ *type = MTRR_TYPE_WRBACK;
+ if(centaur_mcr_type==0 && (centaur_mcr[reg].low&31)==31)
+ *type = MTRR_TYPE_WRBACK;
+
} /* End Function centaur_get_mcr */
static void (*get_mtrr) (unsigned int reg, unsigned long *base,
@@ -794,7 +814,15 @@
else
{
high = base << PAGE_SHIFT;
- low = -size << PAGE_SHIFT | 0x1f; /* only support write-combining... */
+ if(centaur_mcr_type == 0)
+ low = -size << PAGE_SHIFT | 0x1f; /* only support write-combining... */
+ else
+ {
+ if(type == MTRR_TYPE_UNCACHABLE)
+ low = -size << PAGE_SHIFT | 0x02; /* NC */
+ else
+ low = -size << PAGE_SHIFT | 0x09; /* WWO,WC */
+ }
}
centaur_mcr[reg].high = high;
centaur_mcr[reg].low = low;
@@ -1104,6 +1132,28 @@
return -ENOSPC;
} /* End Function generic_get_free_region */
+static int centaur_get_free_region (unsigned long base, unsigned long size)
+/* [SUMMARY] Get a free MTRR.
+ <base> The starting (base) address of the region.
+ <size> The size (in bytes) of the region.
+ [RETURNS] The index of the region on success, else -1 on error.
+*/
+{
+ int i, max;
+ mtrr_type ltype;
+ unsigned long lbase, lsize;
+
+ max = get_num_var_ranges ();
+ for (i = 0; i < max; ++i)
+ {
+ if(centaur_mcr_reserved & (1<<i))
+ continue;
+ (*get_mtrr) (i, &lbase, &lsize, <ype);
+ if (lsize == 0) return i;
+ }
+ return -ENOSPC;
+} /* End Function generic_get_free_region */
+
static int cyrix_get_free_region (unsigned long base, unsigned long size)
/* [SUMMARY] Get a free ARR.
<base> The starting (base) address of the region.
@@ -1164,9 +1214,9 @@
*
* The available types are
*
- * %MTRR_TYPE_UNCACHEABLE - No caching
+ * %MTRR_TYPE_UNCACHABLE - No caching
*
- * %MTRR_TYPE_WRITEBACK - Write data back in bursts whenever
+ * %MTRR_TYPE_WRBACK - Write data back in bursts whenever
*
* %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
*
@@ -1229,9 +1279,13 @@
case MTRR_IF_CENTAUR_MCR:
if ( mtrr_if == MTRR_IF_CENTAUR_MCR )
{
- if (type != MTRR_TYPE_WRCOMB)
+ /*
+ * FIXME: Winchip2 supports uncached
+ */
+ if (type != MTRR_TYPE_WRCOMB && (centaur_mcr_type == 0 || type != MTRR_TYPE_UNCACHABLE))
{
- printk (KERN_WARNING "mtrr: only write-combining is supported\n");
+ printk (KERN_WARNING "mtrr: only write-combining%s supported\n",
+ centaur_mcr_type?" and uncacheable are":" is");
return -EINVAL;
}
}
@@ -1348,9 +1402,9 @@
*
* The available types are
*
- * %MTRR_TYPE_UNCACHEABLE - No caching
+ * %MTRR_TYPE_UNCACHABLE - No caching
*
- * %MTRR_TYPE_WRITEBACK - Write data back in bursts whenever
+ * %MTRR_TYPE_WRBACK - Write data back in bursts whenever
*
* %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts
*
@@ -1943,27 +1997,101 @@
if ( ccrc[6] ) printk ("mtrr: ARR3 was write protected, unprotected\n");
} /* End Function cyrix_arr_init */
-static void __init centaur_mcr_init(void)
+/*
+ * Initialise the later (saner) Winchip MCR variant. In this version
+ * the BIOS can pass us the registers it has used (but not their values)
+ * and the control register is read/write
+ */
+
+static void __init centaur_mcr1_init(void)
+{
+ unsigned i;
+ u32 lo, hi;
+
+ /* Unfortunately, MCR's are read-only, so there is no way to
+ * find out what the bios might have done.
+ */
+
+ rdmsr(0x120, lo, hi);
+ if(((lo>>17)&7)==1) /* Type 1 Winchip2 MCR */
+ {
+ lo&= ~0x1C0; /* clear key */
+ lo|= 0x040; /* set key to 1 */
+ wrmsr(0x120, lo, hi); /* unlock MCR */
+ }
+
+ centaur_mcr_type = 1;
+
+ /*
+ * Clear any unconfigured MCR's.
+ */
+
+ for (i = 0; i < 8; ++i)
+ {
+ if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
+ {
+ if(!(lo & (1<<(9+i))))
+ wrmsr (0x110 + i , 0, 0);
+ else
+ /*
+ * If the BIOS set up an MCR we cannot see it
+ * but we don't wish to obliterate it
+ */
+ centaur_mcr_reserved |= (1<<i);
+ }
+ }
+ /*
+ * Throw the main write-combining switch...
+ * However if OOSTORE is enabled then people have already done far
+ * cleverer things and we should behave.
+ */
+
+ lo |= 15; /* Write combine enables */
+ wrmsr(0x120, lo, hi);
+} /* End Function centaur_mcr1_init */
+
+/*
+ * Initialise the original winchip with read only MCR registers
+ * no used bitmask for the BIOS to pass on and write only control
+ */
+
+static void __init centaur_mcr0_init(void)
{
unsigned i;
- struct set_mtrr_context ctxt;
- set_mtrr_prepare (&ctxt);
/* Unfortunately, MCR's are read-only, so there is no way to
* find out what the bios might have done.
*/
- /* Clear all MCR's.
+
+ /* Clear any unconfigured MCR's.
* This way we are sure that the centaur_mcr array contains the actual
* values. The disadvantage is that any BIOS tweaks are thus undone.
+ *
*/
for (i = 0; i < 8; ++i)
{
- centaur_mcr[i].high = 0;
- centaur_mcr[i].low = 0;
- wrmsr (0x110 + i , 0, 0);
+ if(centaur_mcr[i]. high == 0 && centaur_mcr[i].low == 0)
+ wrmsr (0x110 + i , 0, 0);
}
- /* Throw the main write-combining switch... */
- wrmsr (0x120, 0x01f0001f, 0);
+
+ wrmsr(0x120, 0x01F0001F, 0); /* Write only */
+} /* End Function centaur_mcr0_init */
+
+/*
+ * Initialise Winchip series MCR registers
+ */
+
+static void __init centaur_mcr_init(void)
+{
+ struct set_mtrr_context ctxt;
+
+ set_mtrr_prepare (&ctxt);
+
+ if(boot_cpu_data.x86_model==4)
+ centaur_mcr0_init();
+ else if(boot_cpu_data.x86_model==8 || boot_cpu_data.x86_model == 9)
+ centaur_mcr1_init();
+
set_mtrr_done (&ctxt);
} /* End Function centaur_mcr_init */
@@ -2036,6 +2164,7 @@
mtrr_if = MTRR_IF_CENTAUR_MCR;
get_mtrr = centaur_get_mcr;
set_mtrr_up = centaur_set_mcr_up;
+ get_free_region = centaur_get_free_region;
centaur_mcr_init();
size_or_mask = 0xfff00000; /* 32 bits */
size_and_mask = 0;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)