# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	sys/drivers/mtrr
#	sys/drivers/mtrr/Makefile
#	sys/drivers/mtrr/compat.h
#	sys/drivers/mtrr/cpufunc.h
#	sys/drivers/mtrr/cputypes.h
#	sys/drivers/mtrr/i686_mem.c
#	sys/drivers/mtrr/k6_mem.c
#	sys/drivers/mtrr/kprotos.h
#	sys/drivers/mtrr/memrange.h
#	sys/drivers/mtrr/mtrr.4
#	sys/drivers/mtrr/mtrr.c
#	sys/drivers/mtrr/mtrr.cfg
#	sys/drivers/mtrr/mtrr.man
#	sys/drivers/mtrr/specialreg.h
#	sys/drivers/mtrr/support.S
#
echo c - sys/drivers/mtrr
mkdir -p sys/drivers/mtrr > /dev/null 2>&1
echo x - sys/drivers/mtrr/Makefile
sed 's/^X//' >sys/drivers/mtrr/Makefile << 'END-of-sys/drivers/mtrr/Makefile'
X#************************************************************
X# 
X# $XFree86: xc/programs/Xserver/hw/xfree86/etc/MTRR-Lynx.shar,v 1.1 1999/12/08 06:10:11 dawes Exp $
X# 
X#************************************************************
X
XLYNXVER := $(shell uname -r | cut -c1,3,5)
X
Xifeq "240" "$(LYNXVER)"
Xabort ::
X	@echo "This driver will not work on LynxOS version earlier than 2.5.0"
X	@exit 1
Xendif
X
XUSR_HFILES=/usr/include/sys/memrange.h
X
XFILES = mtrrdrvr.o 
XHFILES = compat.h kprotos.h \
X	 cpufunc.h cputypes.h specialreg.h \
X	 $(USR_HFILES)
X
XLIBRARY= drivers
X
XDFILES = mtrr.x support.x i686_mem.x k6_mem.x
XDOBJS=$(DFILES:.x=.o)
X
Xifneq "240" "$(LYNXVER)"
Xinclude	../../OBJ_RULES
Xendif
X
Xifneq "386" "$(PROCESSOR)"
Xabort ::
X	@echo "This driver will only work on LynxOS x86"
X	@exit 1
Xendif
X
XDRV_LD=$(KERN_LD)
Xifeq "250" "$(LYNXVER)"
XDRV_LD=$(NEW_GCC_LD)
Xendif
X
XSPECIAL_INCLUDES = 
XSPECIAL_CFLAGS = -DKERNEL -D__NO_INCLUDE_WARN__ -Wall -Wunused
XASFLAGS=-DLOCORE
X
X%.o: %.S 
X	$(ansi_compile) $(ASFLAGS) $(OPTIMIZE)
X
Xinstall all :: $(ALL_LIBRARIES)
X
Xclean:
X	$(RM) $(FILES) $(DOBJS)
X
Xclobber: clean
X
X$(DOBJS) : $(HFILES)
X
Xmtrrdrvr.o : $(DOBJS)
X	$(DRV_LD) -r -o $@ $(DOBJS)
X
X#
X# automatically copy user include files in place
X#
X$(USR_HFILES) : memrange.h
X	install -c -u 0 -g 0 -m 0444 memrange.h $(ENV_PREFIX)/usr/include/sys
X
Xinstall :: mtrr.4
X	install -c -u 0 -g 0 -m 0444 mtrr.4 $(ENV_PREFIX)/usr/man/cat4
X
Xmtrr.4 : mtrr.man
X	groff -mandoc -Tascii mtrr.man > mtrr.4
END-of-sys/drivers/mtrr/Makefile
echo x - sys/drivers/mtrr/compat.h
sed 's/^X//' >sys/drivers/mtrr/compat.h << 'END-of-sys/drivers/mtrr/compat.h'
X/*
X * Copyright 1999 by Thomas Mueller
X *
X * Permission to use, copy, modify, distribute, and sell this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the names of the above listed copyright holder(s)
X * not be used in advertising or publicity pertaining to distribution of
X * the software without specific, written prior permission.  The above listed  
X * copyright holder(s) make(s) no representations about the suitability of this
X * software for any purpose.  It is provided "as is" without express or
X * implied warranty.
X * 
X * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD
X * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
X * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
X * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
X * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
X * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
X * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X * 
X */
X
X#ifndef __compat_h
X#define __compat_h
X
X#include <ansidecl.h>
X
X#define __STRING(x)	#x		/* stringify without expanding x */
X#define __XSTRING(x)	__STRING(x)	/* expand x, then stringify */
X
X#include <minmax.h>
X
X#ifndef min
X#define min(a,b)	MIN(a,b)
X#endif
X
X#ifdef NEED_PCI_COMPAT
X#include "pci_compat.h"
X#endif
X
X#ifdef NEED_KERNEL_UIO
X#include <uio.h>
X/* flags for uiomove() missing from sys/uio.h
X *
X * uiomove() will only be present with TCP/IP
X * included in the kernel!
X */
X
X/* Segment flag values. */
Xenum uio_seg {
X	UIO_USERSPACE,		/* from user data space */
X	UIO_SYSSPACE,		/* from system space */
X	UIO_USERISPACE		/* from user I space */
X};
X
X#undef UIO_READ
X#undef UIO_WRITE
X
Xenum	uio_rw { UIO_READ, UIO_WRITE };
X
X/*
X * struct uio as it lokks in the kernel.
X * I guess it'd be better to use a replacement for
X * uiomove as well. one never knows how the kernel
X * structure looks like....
X */
X#define uio kernel_uio
X
Xstruct kernel_uio {
X	struct	iovec *uio_iov;
X	int	uio_iovcnt;
X	off_t	uio_offset;
X	int	uio_resid;
X	enum	uio_seg uio_segflg;
X	enum	uio_rw uio_rw;
X	struct	pentry *uio_procp;
X};
X
Xextern int	uiomove		_AP((caddr_t, int, struct uio *));
X#endif
X
X/*
X * LynxOS doesn't have vm_offset_t
X */
Xtypedef unsigned int vm_offset_t;
Xtypedef unsigned int vm_size_t;
X
X
X#ifndef bootverbose
X#define bootverbose	(0)
X#endif
X
X#define printf				kkprintf
X#define sprintf				ksprintf
X#define copyin(user, kern, len)		bcopy(user, kern, len)
X#define copyout(kern, user, len)	bcopy(kern, user, len)
X#define DELAY(x)			usec_delay(x)
X#define hz				tickspersec
Xextern void	usec_delay	_AP((unsigned long));
X
Xextern int	tickspersec;
Xextern void	microtime	_AP((struct timeval *));
X
X#define PZERO			22
X#define PRIMASK			0x0ff
X#define PCATCH			0x100
Xextern int	tsleep		_AP((int *sema, int flag, char *name, int ticks));
X/* careful with this one ... */
X#define wakeup(x)		ssignal(x)
X
X#define PAGE_SIZE	PAGESIZE
X#define vtophys(x)	((unsigned long)(get_phys((long)x) - PHYSBASE + DRAMBASE))
X#define btoc(x)		(((unsigned)(x)+PAGE_OFFSET_MASK)>>PAGESHIFT)
X
X#define IO_NDELAY	FNDELAY
X#define ERESTART	0		/* usually we don't do this */
X
X/* device driver entry points */
X
Xtypedef int d_open_t	_AP((void *, int devno, struct file *));
Xtypedef int d_close_t	_AP((void *, struct file *));
Xtypedef int d_read_t	_AP((void *, struct file *, char *, int));
Xtypedef int d_write_t	_AP((void *, struct file *, char *, int));
Xtypedef int d_select_t	_AP((void *, struct file *, int, struct sel *));
Xtypedef int d_ioctl_t	_AP((void *, struct file *f, int cmd, char *arg));
Xtypedef char *d_install_t	_AP((void *));
Xtypedef int d_uninstall_t	_AP((void *));
X/* not really a device driver entry point on LynxOS (yet?) */
Xtypedef int d_mmap_t	_AP((void *, vm_offset_t));
X
X#define powerof2(x)	((((x)-1)&(x))==0)
X#include <cpufunc.h>
X
X#endif
END-of-sys/drivers/mtrr/compat.h
echo x - sys/drivers/mtrr/cpufunc.h
sed 's/^X//' >sys/drivers/mtrr/cpufunc.h << 'END-of-sys/drivers/mtrr/cpufunc.h'
X/*-
X * Copyright (c) 1993 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $FreeBSD: src/sys/i386/include/cpufunc.h,v 1.85.2.1 1999/08/29 16:06:26 peter Exp $
X */
X
X/*
X * Functions to provide access to special i386 instructions.
X */
X
X#ifndef _MACHINE_CPUFUNC_H_
X#define	_MACHINE_CPUFUNC_H_
X
X#define readb(va)	(*(volatile u_int8_t *) (va))
X#define readw(va)	(*(volatile u_int16_t *) (va))
X#define readl(va)	(*(volatile u_int32_t *) (va))
X
X#define writeb(va, d)	(*(volatile u_int8_t *) (va) = (d))
X#define writew(va, d)	(*(volatile u_int16_t *) (va) = (d))
X#define writel(va, d)	(*(volatile u_int32_t *) (va) = (d))
X
X#ifdef	__GNUC__
X
X#ifdef SMP
X#include <machine/lock.h>		/* XXX */
X#endif
X
X#ifdef SWTCH_OPTIM_STATS
Xextern	int	tlb_flush_count;	/* XXX */
X#endif
X
Xstatic __inline void
Xbreakpoint(void)
X{
X	__asm __volatile("int $3");
X}
X
Xstatic __inline void
Xdisable_intr(void)
X{
X	__asm __volatile("cli" : : : "memory");
X#ifdef SMP
X	MPINTR_LOCK();
X#endif
X}
X
Xstatic __inline void
Xenable_intr(void)
X{
X#ifdef SMP
X	MPINTR_UNLOCK();
X#endif
X	__asm __volatile("sti");
X}
X
X#define	HAVE_INLINE_FFS
X
Xstatic __inline int
Xffs(int mask)
X{
X	int	result;
X	/*
X	 * bsfl turns out to be not all that slow on 486's.  It can beaten
X	 * using a binary search to reduce to 4 bits and then a table lookup,
X	 * but only if the code is inlined and in the cache, and the code
X	 * is quite large so inlining it probably busts the cache.
X	 *
X	 * Note that gcc-2's builtin ffs would be used if we didn't declare
X	 * this inline or turn off the builtin.  The builtin is faster but
X	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and 2.6.
X	 */
X	__asm __volatile("testl %0,%0; je 1f; bsfl %0,%0; incl %0; 1:"
X			 : "=r" (result) : "0" (mask));
X	return (result);
X}
X
X#define	HAVE_INLINE_FLS
X
Xstatic __inline int
Xfls(int mask)
X{
X	int	result;
X	__asm __volatile("testl %0,%0; je 1f; bsrl %0,%0; incl %0; 1:"
X			 : "=r" (result) : "0" (mask));
X	return (result);
X}
X
X#if __GNUC__ < 2
X
X#define	inb(port)		inbv(port)
X#define	outb(port, data)	outbv(port, data)
X
X#else /* __GNUC >= 2 */
X
X/*
X * The following complications are to get around gcc not having a
X * constraint letter for the range 0..255.  We still put "d" in the
X * constraint because "i" isn't a valid constraint when the port
X * isn't constant.  This only matters for -O0 because otherwise
X * the non-working version gets optimized away.
X * 
X * Use an expression-statement instead of a conditional expression
X * because gcc-2.6.0 would promote the operands of the conditional
X * and produce poor code for "if ((inb(var) & const1) == const2)".
X *
X * The unnecessary test `(port) < 0x10000' is to generate a warning if
X * the `port' has type u_short or smaller.  Such types are pessimal.
X * This actually only works for signed types.  The range check is
X * careful to avoid generating warnings.
X */
X#define	inb(port) __extension__ ({					\
X	u_char	_data;							\
X	if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100	\
X	    && (port) < 0x10000)					\
X		_data = inbc(port);					\
X	else								\
X		_data = inbv(port);					\
X	_data; })
X
X#define	outb(port, data) (						\
X	__builtin_constant_p(port) && ((port) & 0xffff) < 0x100		\
X	&& (port) < 0x10000						\
X	? outbc(port, data) : outbv(port, data))
X
Xstatic __inline u_char
Xinbc(u_int port)
X{
X	u_char	data;
X
X	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
X	return (data);
X}
X
Xstatic __inline void
Xoutbc(u_int port, u_char data)
X{
X	__asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
X}
X
X#endif /* __GNUC <= 2 */
X
Xstatic __inline u_char
Xinbv(u_int port)
X{
X	u_char	data;
X	/*
X	 * We use %%dx and not %1 here because i/o is done at %dx and not at
X	 * %edx, while gcc generates inferior code (movw instead of movl)
X	 * if we tell it to load (u_short) port.
X	 */
X	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
X	return (data);
X}
X
Xstatic __inline u_int
Xinl(u_int port)
X{
X	u_int	data;
X
X	__asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
X	return (data);
X}
X
Xstatic __inline void
Xinsb(u_int port, void *addr, size_t cnt)
X{
X	__asm __volatile("cld; rep; insb"
X			 : "=D" (addr), "=c" (cnt)
X			 :  "0" (addr),  "1" (cnt), "d" (port)
X			 : "memory");
X}
X
Xstatic __inline void
Xinsw(u_int port, void *addr, size_t cnt)
X{
X	__asm __volatile("cld; rep; insw"
X			 : "=D" (addr), "=c" (cnt)
X			 :  "0" (addr),  "1" (cnt), "d" (port)
X			 : "memory");
X}
X
Xstatic __inline void
Xinsl(u_int port, void *addr, size_t cnt)
X{
X	__asm __volatile("cld; rep; insl"
X			 : "=D" (addr), "=c" (cnt)
X			 :  "0" (addr),  "1" (cnt), "d" (port)
X			 : "memory");
X}
X
Xstatic __inline void
Xinvd(void)
X{
X	__asm __volatile("invd");
X}
X
X#if defined(SMP) && defined(KERNEL)
X
X/*
X * When using APIC IPI's, invlpg() is not simply the invlpg instruction
X * (this is a bug) and the inlining cost is prohibitive since the call
X * executes into the IPI transmission system.
X */
Xvoid	invlpg		__P((u_int addr));
Xvoid	invltlb		__P((void));
X
Xstatic __inline void
Xcpu_invlpg(void *addr)
X{
X	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
X}
X
Xstatic __inline void
Xcpu_invltlb(void)
X{
X	u_int	temp;
X	/*
X	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
X	 * is inlined.
X	 */
X	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
X			 : : "memory");
X#if defined(SWTCH_OPTIM_STATS)
X	++tlb_flush_count;
X#endif
X}
X
X#else /* !(SMP && KERNEL) */
X
Xstatic __inline void
Xinvlpg(u_int addr)
X{
X	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
X}
X
Xstatic __inline void
Xinvltlb(void)
X{
X	u_int	temp;
X	/*
X	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
X	 * is inlined.
X	 */
X	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
X			 : : "memory");
X#ifdef SWTCH_OPTIM_STATS
X	++tlb_flush_count;
X#endif
X}
X
X#endif /* SMP && KERNEL */
X
Xstatic __inline u_short
Xinw(u_int port)
X{
X	u_short	data;
X
X	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
X	return (data);
X}
X
Xstatic __inline u_int
Xloadandclear(u_int *addr)
X{
X	u_int	result;
X
X	__asm __volatile("xorl %0,%0; xchgl %1,%0"
X			 : "=&r" (result) : "m" (*addr));
X	return (result);
X}
X
Xstatic __inline void
Xoutbv(u_int port, u_char data)
X{
X	u_char	al;
X	/*
X	 * Use an unnecessary assignment to help gcc's register allocator.
X	 * This make a large difference for gcc-1.40 and a tiny difference
X	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
X	 * best results.  gcc-2.6.0 can't handle this.
X	 */
X	al = data;
X	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
X}
X
Xstatic __inline void
Xoutl(u_int port, u_int data)
X{
X	/*
X	 * outl() and outw() aren't used much so we haven't looked at
X	 * possible micro-optimizations such as the unnecessary
X	 * assignment for them.
X	 */
X	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
X}
X
Xstatic __inline void
Xoutsb(u_int port, const void *addr, size_t cnt)
X{
X	__asm __volatile("cld; rep; outsb"
X			 : "=S" (addr), "=c" (cnt)
X			 :  "0" (addr),  "1" (cnt), "d" (port));
X}
X
Xstatic __inline void
Xoutsw(u_int port, const void *addr, size_t cnt)
X{
X	__asm __volatile("cld; rep; outsw"
X			 : "=S" (addr), "=c" (cnt)
X			 :  "0" (addr),  "1" (cnt), "d" (port));
X}
X
Xstatic __inline void
Xoutsl(u_int port, const void *addr, size_t cnt)
X{
X	__asm __volatile("cld; rep; outsl"
X			 : "=S" (addr), "=c" (cnt)
X			 :  "0" (addr),  "1" (cnt), "d" (port));
X}
X
Xstatic __inline void
Xoutw(u_int port, u_short data)
X{
X	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
X}
X
Xstatic __inline u_int
Xrcr2(void)
X{
X	u_int	data;
X
X	__asm __volatile("movl %%cr2,%0" : "=r" (data));
X	return (data);
X}
X
Xstatic __inline u_int
Xread_eflags(void)
X{
X	u_int	ef;
X
X	__asm __volatile("pushfl; popl %0" : "=r" (ef));
X	return (ef);
X}
X
Xstatic __inline u_int64_t
Xrdmsr(u_int msr)
X{
X	u_int64_t rv;
X
X	__asm __volatile(".byte 0x0f, 0x32" : "=A" (rv) : "c" (msr));
X	return (rv);
X}
X
Xstatic __inline u_int64_t
Xrdpmc(u_int pmc)
X{
X	u_int64_t rv;
X
X	__asm __volatile(".byte 0x0f, 0x33" : "=A" (rv) : "c" (pmc));
X	return (rv);
X}
X
Xstatic __inline u_int64_t
Xrdtsc(void)
X{
X	u_int64_t rv;
X
X	__asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
X	return (rv);
X}
X
Xstatic __inline void
Xsetbits(volatile u_int *addr, u_int bits)
X{
X	__asm __volatile(
X#ifdef SMP
X			 "lock; "
X#endif
X			 "orl %1,%0" : "=m" (*addr) : "ir" (bits));
X}
X
Xstatic __inline void
Xwbinvd(void)
X{
X	__asm __volatile("wbinvd");
X}
X
Xstatic __inline void
Xwrite_eflags(u_int ef)
X{
X	__asm __volatile("pushl %0; popfl" : : "r" (ef));
X}
X
Xstatic __inline void
Xwrmsr(u_int msr, u_int64_t newval)
X{
X	__asm __volatile(".byte 0x0f, 0x30" : : "A" (newval), "c" (msr));
X}
X
X#else /* !__GNUC__ */
X
Xint	breakpoint	__P((void));
Xvoid	disable_intr	__P((void));
Xvoid	enable_intr	__P((void));
Xu_char	inb		__P((u_int port));
Xu_int	inl		__P((u_int port));
Xvoid	insb		__P((u_int port, void *addr, size_t cnt));
Xvoid	insl		__P((u_int port, void *addr, size_t cnt));
Xvoid	insw		__P((u_int port, void *addr, size_t cnt));
Xvoid	invd		__P((void));
Xvoid	invlpg		__P((u_int addr));
Xvoid	invltlb		__P((void));
Xu_short	inw		__P((u_int port));
Xu_int	loadandclear	__P((u_int *addr));
Xvoid	outb		__P((u_int port, u_char data));
Xvoid	outl		__P((u_int port, u_int data));
Xvoid	outsb		__P((u_int port, void *addr, size_t cnt));
Xvoid	outsl		__P((u_int port, void *addr, size_t cnt));
Xvoid	outsw		__P((u_int port, void *addr, size_t cnt));
Xvoid	outw		__P((u_int port, u_short data));
Xu_int	rcr2		__P((void));
Xu_int64_t rdmsr		__P((u_int msr));
Xu_int64_t rdpmc		__P((u_int pmc));
Xu_int64_t rdtsc		__P((void));
Xu_int	read_eflags	__P((void));
Xvoid	setbits		__P((volatile u_int *addr, u_int bits));
Xvoid	wbinvd		__P((void));
Xvoid	write_eflags	__P((u_int ef));
Xvoid	wrmsr		__P((u_int msr, u_int64_t newval));
X
X#endif	/* __GNUC__ */
X
Xvoid	load_cr0	__P((u_int cr0));
Xvoid	load_cr3	__P((u_int cr3));
Xvoid	load_cr4	__P((u_int cr4));
Xvoid	ltr		__P((u_short sel));
Xu_int	rcr0		__P((void));
Xu_int	rcr3		__P((void));
Xu_int	rcr4		__P((void));
X
X#endif /* !_MACHINE_CPUFUNC_H_ */
END-of-sys/drivers/mtrr/cpufunc.h
echo x - sys/drivers/mtrr/cputypes.h
sed 's/^X//' >sys/drivers/mtrr/cputypes.h << 'END-of-sys/drivers/mtrr/cputypes.h'
X/*
X * Copyright (c) 1993 Christopher G. Demetriou
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. The name of the author may not be used to endorse or promote products
X *    derived from this software without specific prior written permission
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
X * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
X * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
X * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
X * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
X * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
X * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X *
X * $FreeBSD: src/sys/i386/include/cputypes.h,v 1.11.2.2 1999/08/29 16:06:26 peter Exp $
X */
X
X#ifndef _MACHINE_CPUTYPES_H_
X#define	_MACHINE_CPUTYPES_H_
X
X/*
X * Classes of processor.
X */
X#define	CPUCLASS_286	0
X#define	CPUCLASS_386	1
X#define	CPUCLASS_486	2
X#define	CPUCLASS_586	3
X#define	CPUCLASS_686	4
X
X/*
X * Kinds of processor.
X */
X#define	CPU_286		0	/* Intel 80286 */
X#define	CPU_386SX	1	/* Intel 80386SX */
X#define	CPU_386		2	/* Intel 80386DX */
X#define	CPU_486SX	3	/* Intel 80486SX */
X#define	CPU_486		4	/* Intel 80486DX */
X#define	CPU_586		5	/* Intel P.....m (I hate lawyers; it's TM) */
X#define	CPU_486DLC	6	/* Cyrix 486DLC */
X#define	CPU_686		7	/* Pentium Pro */
X#define	CPU_M1SC	8	/* Cyrix M1sc (aka 5x86) */
X#define	CPU_M1		9	/* Cyrix M1 (aka 6x86) */
X#define	CPU_BLUE	10	/* IBM BlueLighting CPU */
X#define	CPU_M2		11	/* Cyrix M2 (aka enhanced 6x86 with MMX */
X#define	CPU_NX586	12	/* NexGen (now AMD) 586 */
X#define	CPU_CY486DX	13	/* Cyrix 486S/DX/DX2/DX4 */
X#define CPU_PII		14	/* Intel Pentium II */
X#define CPU_PIII	15	/* Intel Pentium III */
X
X#ifndef LOCORE
Xstruct cpu_nameclass {
X	char	*cpu_name;
X	int	cpu_class;
X};
X
Xextern int	cpu;
Xextern int	cpu_class;
X#endif
X
X#endif /* !_MACHINE_CPUTYPES_H_ */
END-of-sys/drivers/mtrr/cputypes.h
echo x - sys/drivers/mtrr/i686_mem.c
sed 's/^X//' >sys/drivers/mtrr/i686_mem.c << 'END-of-sys/drivers/mtrr/i686_mem.c'
X/*-
X * Copyright (c) 1999 Michael Smith <msmith@freebsd.org>
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $FreeBSD: src/sys/i386/i386/i686_mem.c,v 1.8 1999/10/12 22:53:05 green Exp $
X */
X
X#ifndef __Lynx__
X#include "opt_smp.h"
X#endif
X
X#include <sys/param.h>
X#include <sys/kernel.h>
X#ifndef __Lynx__
X#include <sys/systm.h>
X#include <sys/malloc.h>
X#else
X#include <proc.h>
X#include <mem.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <errno.h>
X#include <string.h>
X#endif
X#include <sys/memrange.h>
X
X#ifndef __Lynx__
X#include <machine/md_var.h>
X#include <machine/specialreg.h>
X#else
X#include "kprotos.h"
X#include "compat.h"
X
Xextern	u_int	cpu_feature;
Xextern	u_int	cpu_high;
Xextern	u_int	cpu_id;
Xextern	char	cpu_vendor[];
X#include <specialreg.h>
X#endif
X
X#ifdef SMP
X#include <machine/smp.h>
X#endif
X
X/*
X * i686 memory range operations
X *
X * This code will probably be impenetrable without reference to the
X * Intel Pentium Pro documentation.
X */
X
Xstatic char *mem_owner_bios = "BIOS";
X
X#define MR686_FIXMTRR	(1<<0)
X
X#define mrwithin(mr, a) \
X    (((a) >= (mr)->mr_base) && ((a) < ((mr)->mr_base + (mr)->mr_len)))
X#define mroverlap(mra, mrb) \
X    (mrwithin(mra, mrb->mr_base) || mrwithin(mrb, mra->mr_base))
X
X#define mrvalid(base, len) 						\
X    ((!(base & ((1 << 12) - 1))) && 	/* base is multiple of 4k */	\
X     ((len) >= (1 << 12)) && 		/* length is >= 4k */		\
X     powerof2((len)) && 		/* ... and power of two */	\
X     !((base) & ((len) - 1)))		/* range is not discontiuous */
X
X#define mrcopyflags(curr, new) (((curr) & ~MDF_ATTRMASK) | ((new) & MDF_ATTRMASK))
X
Xstatic void			i686_mrinit(struct mem_range_softc *sc);
Xstatic int			i686_mrset(struct mem_range_softc *sc,
X					   struct mem_range_desc *mrd,
X					   int *arg);
Xstatic void			i686_mrAPinit(struct mem_range_softc *sc);
X
Xstatic struct mem_range_ops i686_mrops = {
X    i686_mrinit,
X    i686_mrset,
X    i686_mrAPinit
X};
X
X/* XXX for AP startup hook */
Xstatic u_int64_t		mtrrcap, mtrrdef;
X
Xstatic struct mem_range_desc	*mem_range_match(struct mem_range_softc *sc,
X						 struct mem_range_desc *mrd);
Xstatic void			i686_mrfetch(struct mem_range_softc *sc);
Xstatic int			i686_mtrrtype(int flags);
Xstatic void			i686_mrstore(struct mem_range_softc *sc);
Xstatic void			i686_mrstoreone(void *arg);
Xstatic struct mem_range_desc	*i686_mtrrfixsearch(struct mem_range_softc *sc,
X						    u_int64_t addr);
Xstatic int			i686_mrsetlow(struct mem_range_softc *sc,
X					      struct mem_range_desc *mrd,
X					      int *arg);
Xstatic int			i686_mrsetvariable(struct mem_range_softc *sc,
X						   struct mem_range_desc *mrd,
X						   int *arg);
X
X/* i686 MTRR type to memory range type conversion */
Xstatic int i686_mtrrtomrt[] = {
X    MDF_UNCACHEABLE,
X    MDF_WRITECOMBINE,
X    0,
X    0,
X    MDF_WRITETHROUGH,
X    MDF_WRITEPROTECT,
X    MDF_WRITEBACK
X};
X
X/* 
X * i686 MTRR conflict matrix for overlapping ranges 
X *
X * Specifically, this matrix allows writeback and uncached ranges
X * to overlap (the overlapped region is uncached).  The array index
X * is the translated i686 code for the flags (because they map well).
X */
Xstatic int i686_mtrrconflict[] = {
X    MDF_WRITECOMBINE | MDF_WRITETHROUGH | MDF_WRITEPROTECT,
X    MDF_ATTRMASK,
X    0,
X    0,
X    MDF_ATTRMASK,
X    MDF_ATTRMASK,
X    MDF_WRITECOMBINE | MDF_WRITETHROUGH | MDF_WRITEPROTECT
X};
X
X/*
X * Look for an exactly-matching range.
X */
Xstatic struct mem_range_desc *
Xmem_range_match(struct mem_range_softc *sc, struct mem_range_desc *mrd) 
X{
X    struct mem_range_desc	*cand;
X    int				i;
X	
X    for (i = 0, cand = sc->mr_desc; i < sc->mr_ndesc; i++, cand++)
X	if ((cand->mr_base == mrd->mr_base) &&
X	    (cand->mr_len == mrd->mr_len))
X	    return(cand);
X    return(NULL);
X}
X
X/*
X * Fetch the current mtrr settings from the current CPU (assumed to all
X * be in sync in the SMP case).  Note that if we are here, we assume
X * that MTRRs are enabled, and we may or may not have fixed MTRRs.
X */
Xstatic void
Xi686_mrfetch(struct mem_range_softc *sc)
X{
X    struct mem_range_desc	*mrd;
X    u_int64_t			msrv;
X    int				i, j, msr;
X
X    mrd = sc->mr_desc;
X
X    /* Get fixed-range MTRRs */
X    if (sc->mr_cap & MR686_FIXMTRR) {
X	msr = MSR_MTRR64kBase;
X	for (i = 0; i < (MTRR_N64K / 8); i++, msr++) {
X	    msrv = rdmsr(msr);
X	    for (j = 0; j < 8; j++, mrd++) {
X		mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) |
X		    i686_mtrrtomrt[msrv & 0xff] |
X		    MDF_ACTIVE;
X		if (mrd->mr_owner[0] == 0)
X		    strcpy(mrd->mr_owner, mem_owner_bios);
X		msrv = msrv >> 8;
X	    }
X	}
X	msr = MSR_MTRR16kBase;
X	for (i = 0; i < (MTRR_N16K / 8); i++, msr++) {
X	    msrv = rdmsr(msr);
X	    for (j = 0; j < 8; j++, mrd++) {
X		mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) |
X		    i686_mtrrtomrt[msrv & 0xff] |
X		    MDF_ACTIVE;
X		if (mrd->mr_owner[0] == 0)
X		    strcpy(mrd->mr_owner, mem_owner_bios);
X		msrv = msrv >> 8;
X	    }
X	}
X	msr = MSR_MTRR4kBase;
X	for (i = 0; i < (MTRR_N4K / 8); i++, msr++) {
X	    msrv = rdmsr(msr);
X	    for (j = 0; j < 8; j++, mrd++) {
X		mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) |
X		    i686_mtrrtomrt[msrv & 0xff] |
X		    MDF_ACTIVE;
X		if (mrd->mr_owner[0] == 0)
X		    strcpy(mrd->mr_owner, mem_owner_bios);
X		msrv = msrv >> 8;
X	    }
X	}
X    }
X
X    /* Get remainder which must be variable MTRRs */
X    msr = MSR_MTRRVarBase;
X    for (; (mrd - sc->mr_desc) < sc->mr_ndesc; msr += 2, mrd++) {
X	msrv = rdmsr(msr);
X	mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) |
X	    i686_mtrrtomrt[msrv & 0xff];
X	mrd->mr_base = msrv & 0x0000000ffffff000LL;
X	msrv = rdmsr(msr + 1);
X	mrd->mr_flags = (msrv & 0x800) ? 
X	    (mrd->mr_flags | MDF_ACTIVE) :
X	    (mrd->mr_flags & ~MDF_ACTIVE);
X	/* Compute the range from the mask. Ick. */
X	mrd->mr_len = (~(msrv & 0x0000000ffffff000LL) & 0x0000000fffffffffLL) + 1;
X	if (!mrvalid(mrd->mr_base, mrd->mr_len))
X	    mrd->mr_flags |= MDF_BOGUS;
X	/* If unclaimed and active, must be the BIOS */
X	if ((mrd->mr_flags & MDF_ACTIVE) && (mrd->mr_owner[0] == 0))
X	    strcpy(mrd->mr_owner, mem_owner_bios);
X    }
X}
X
X/*
X * Return the MTRR memory type matching a region's flags
X */
Xstatic int
Xi686_mtrrtype(int flags)
X{
X    int		i;
X
X    flags &= MDF_ATTRMASK;
X
X    for (i = 0; i < (sizeof(i686_mtrrtomrt) / sizeof(i686_mtrrtomrt[0])); i++) {
X	if (i686_mtrrtomrt[i] == 0)
X	    continue;
X	if (flags == i686_mtrrtomrt[i])
X	    return(i);
X    }
X    return(-1);
X}
X
X/*
X * Update running CPU(s) MTRRs to match the ranges in the descriptor
X * list.
X *
X * XXX Must be called with interrupts enabled.
X */
Xstatic void
Xi686_mrstore(struct mem_range_softc *sc)
X{
X#ifdef SMP
X    /*
X     * We should use all_but_self_ipi() to call other CPUs into a 
X     * locking gate, then call a target function to do this work.
X     * The "proper" solution involves a generalised locking gate
X     * implementation, not ready yet.
X     */
X    smp_rendezvous(NULL, i686_mrstoreone, NULL, (void *)sc);
X#else
X    disable_intr();				/* disable interrupts */
X    i686_mrstoreone((void *)sc);
X    enable_intr();
X#endif
X}
X
X/*
X * Update the current CPU's MTRRs with those represented in the
X * descriptor list.  Note that we do this wholesale rather than
X * just stuffing one entry; this is simpler (but slower, of course).
X */
Xstatic void
Xi686_mrstoreone(void *arg)
X{
X    struct mem_range_softc 	*sc = (struct mem_range_softc *)arg;
X    struct mem_range_desc	*mrd;
X    u_int64_t			msrv;
X    int				i, j, msr;
X    u_int			cr4save;
X
X    mrd = sc->mr_desc;
X
X    cr4save = rcr4();				/* save cr4 */
X    if (cr4save & CR4_PGE)
X	load_cr4(cr4save & ~CR4_PGE);
X    load_cr0((rcr0() & ~CR0_NW) | CR0_CD);	/* disable caches (CD = 1, NW = 0) */
X    wbinvd();					/* flush caches, TLBs */
X    wrmsr(MSR_MTRRdefType, rdmsr(MSR_MTRRdefType) & ~0x800);	/* disable MTRRs (E = 0) */
X
X    /* Set fixed-range MTRRs */
X    if (sc->mr_cap & MR686_FIXMTRR) {
X	msr = MSR_MTRR64kBase;
X	for (i = 0; i < (MTRR_N64K / 8); i++, msr++) {
X	    msrv = 0;
X	    for (j = 7; j >= 0; j--) {
X		msrv = msrv << 8;
X		msrv |= (i686_mtrrtype((mrd + j)->mr_flags) & 0xff);
X	    }
X	    wrmsr(msr, msrv);
X	    mrd += 8;
X	}
X	msr = MSR_MTRR16kBase;
X	for (i = 0; i < (MTRR_N16K / 8); i++, msr++) {
X	    msrv = 0;
X	    for (j = 7; j >= 0; j--) {
X		msrv = msrv << 8;
X		msrv |= (i686_mtrrtype((mrd + j)->mr_flags) & 0xff);
X	    }
X	    wrmsr(msr, msrv);
X	    mrd += 8;
X	}
X	msr = MSR_MTRR4kBase;
X	for (i = 0; i < (MTRR_N4K / 8); i++, msr++) {
X	    msrv = 0;
X	    for (j = 7; j >= 0; j--) {
X		msrv = msrv << 8;
X		msrv |= (i686_mtrrtype((mrd + j)->mr_flags) & 0xff);
X	    }
X	    wrmsr(msr, msrv);
X	    mrd += 8;
X	}
X    }
X
X    /* Set remainder which must be variable MTRRs */
X    msr = MSR_MTRRVarBase;
X    for (; (mrd - sc->mr_desc) < sc->mr_ndesc; msr += 2, mrd++) {
X	/* base/type register */
X	if (mrd->mr_flags & MDF_ACTIVE) {
X	    msrv = mrd->mr_base & 0x0000000ffffff000LL;
X	    msrv |= (i686_mtrrtype(mrd->mr_flags) & 0xff);
X	} else {
X	    msrv = 0;
X	}
X	wrmsr(msr, msrv);	
X	    
X	/* mask/active register */
X	if (mrd->mr_flags & MDF_ACTIVE) {
X	    msrv = 0x800 | (~(mrd->mr_len - 1) & 0x0000000ffffff000LL);
X	} else {
X	    msrv = 0;
X	}
X	wrmsr(msr + 1, msrv);
X    }
X    wbinvd();							/* flush caches, TLBs */
X    wrmsr(MSR_MTRRdefType, rdmsr(MSR_MTRRdefType) | 0x800);	/* restore MTRR state */
X    load_cr0(rcr0() & ~(CR0_CD | CR0_NW));  			/* enable caches CD = 0 and NW = 0 */
X    load_cr4(cr4save);						/* restore cr4 */
X}
X
X/*
X * Hunt for the fixed MTRR referencing (addr)
X */
Xstatic struct mem_range_desc *
Xi686_mtrrfixsearch(struct mem_range_softc *sc, u_int64_t addr)
X{
X    struct mem_range_desc *mrd;
X    int			i;
X    
X    for (i = 0, mrd = sc->mr_desc; i < (MTRR_N64K + MTRR_N16K + MTRR_N4K); i++, mrd++)
X	if ((addr >= mrd->mr_base) && (addr < (mrd->mr_base + mrd->mr_len)))
X	    return(mrd);
X    return(NULL);
X}
X
X/*
X * Try to satisfy the given range request by manipulating the fixed MTRRs that
X * cover low memory.
X *
X * Note that we try to be generous here; we'll bloat the range out to the 
X * next higher/lower boundary to avoid the consumer having to know too much
X * about the mechanisms here.
X *
X * XXX note that this will have to be updated when we start supporting "busy" ranges.
X */
Xstatic int
Xi686_mrsetlow(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg)
X{
X    struct mem_range_desc	*first_md, *last_md, *curr_md;
X
X    /* range check */
X    if (((first_md = i686_mtrrfixsearch(sc, mrd->mr_base)) == NULL) ||
X	((last_md = i686_mtrrfixsearch(sc, mrd->mr_base + mrd->mr_len - 1)) == NULL))
X	return(EINVAL);
X
X    /* set flags, clear set-by-firmware flag */
X    for (curr_md = first_md; curr_md <= last_md; curr_md++) {
X	curr_md->mr_flags = mrcopyflags(curr_md->mr_flags & ~MDF_FIRMWARE, mrd->mr_flags);
X	bcopy(mrd->mr_owner, curr_md->mr_owner, sizeof(mrd->mr_owner));
X    }
X
X    return(0);
X}
X
X
X/*
X * Modify/add a variable MTRR to satisfy the request.
X *
X * XXX needs to be updated to properly support "busy" ranges.
X */
Xstatic int
Xi686_mrsetvariable(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg)
X{
X    struct mem_range_desc	*curr_md, *free_md;
X    int				i;
X    
X    /* 
X     * Scan the currently active variable descriptors, look for 
X     * one we exactly match (straight takeover) and for possible
X     * accidental overlaps.
X     * Keep track of the first empty variable descriptor in case we
X     * can't perform a takeover.
X     */
X    i = (sc->mr_cap & MR686_FIXMTRR) ? MTRR_N64K + MTRR_N16K + MTRR_N4K : 0;
X    curr_md = sc->mr_desc + i;
X    free_md = NULL;
X    for (; i < sc->mr_ndesc; i++, curr_md++) {
X	if (curr_md->mr_flags & MDF_ACTIVE) {
X	    /* exact match? */
X	    if ((curr_md->mr_base == mrd->mr_base) &&
X		(curr_md->mr_len == mrd->mr_len)) {
X		/* whoops, owned by someone */
X		if (curr_md->mr_flags & MDF_BUSY)
X		    return(EBUSY);
X		/* Ok, just hijack this entry */
X		free_md = curr_md;
X		break;
X	    }
X	    /* non-exact overlap ? */
X	    if (mroverlap(curr_md, mrd)) {
X		/* between conflicting region types? */
X		if ((i686_mtrrconflict[i686_mtrrtype(curr_md->mr_flags)] & mrd->mr_flags) ||
X		    (i686_mtrrconflict[i686_mtrrtype(mrd->mr_flags)] & curr_md->mr_flags))
X		    return(EINVAL);
X	    }
X	} else if (free_md == NULL) {
X	    free_md = curr_md;
X	}
X    }
X    /* got somewhere to put it? */
X    if (free_md == NULL)
X	return(ENOSPC);
X
X    /* Set up new descriptor */
X    free_md->mr_base = mrd->mr_base;
X    free_md->mr_len = mrd->mr_len;
X    free_md->mr_flags = mrcopyflags(MDF_ACTIVE, mrd->mr_flags);
X    bcopy(mrd->mr_owner, free_md->mr_owner, sizeof(mrd->mr_owner));
X    return(0);
X}
X
X/*
X * Handle requests to set memory range attributes by manipulating MTRRs.
X *
X */
Xstatic int
Xi686_mrset(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg)
X{
X    struct mem_range_desc	*targ;
X    int				error = 0;
X
X    switch(*arg) {
X    case MEMRANGE_SET_UPDATE:
X	/* make sure that what's being asked for is even possible at all */
X	if (!mrvalid(mrd->mr_base, mrd->mr_len) ||
X	    (i686_mtrrtype(mrd->mr_flags & MDF_ATTRMASK) == -1))
X	    return(EINVAL);
X
X#define FIXTOP	((MTRR_N64K * 0x10000) + (MTRR_N16K * 0x4000) + (MTRR_N4K * 0x1000))
X
X	/* are the "low memory" conditions applicable? */
X	if ((sc->mr_cap & MR686_FIXMTRR) &&
X	    ((mrd->mr_base + mrd->mr_len) <= FIXTOP)) {
X	    if ((error = i686_mrsetlow(sc, mrd, arg)) != 0)
X		return(error);
X	} else {
X	    /* it's time to play with variable MTRRs */
X	    if ((error = i686_mrsetvariable(sc, mrd, arg)) != 0)
X		return(error);
X	}
X	break;
X
X    case MEMRANGE_SET_REMOVE:
X	if ((targ = mem_range_match(sc, mrd)) == NULL)
X	    return(ENOENT);
X	if (targ->mr_flags & MDF_FIXACTIVE)
X	    return(EPERM);
X	if (targ->mr_flags & MDF_BUSY)
X	    return(EBUSY);
X	targ->mr_flags &= ~MDF_ACTIVE;
X	targ->mr_owner[0] = 0;
X	break;
X
X    default:
X	return(EOPNOTSUPP);
X    }
X
X    /* update the hardware */
X    i686_mrstore(sc);
X    i686_mrfetch(sc);	/* refetch to see where we're at */
X    return(0);
X}
X
X/*
X * Work out how many ranges we support, initialise storage for them, 
X * fetch the initial settings.
X */
Xstatic void
Xi686_mrinit(struct mem_range_softc *sc)
X{
X    struct mem_range_desc	*mrd;
X    int				nmdesc = 0;
X    int				i;
X
X    mtrrcap = rdmsr(MSR_MTRRcap);
X    mtrrdef = rdmsr(MSR_MTRRdefType);
X
X    /* For now, bail out if MTRRs are not enabled */
X    if (!(mtrrdef & 0x800)) {
X	if (bootverbose)
X	    printf("CPU supports MTRRs but not enabled\n");
X	return;
X    }
X    nmdesc = mtrrcap & 0xff;
X    if (bootverbose)
X        printf("Pentium Pro MTRR support enabled\n");
X
X    /* If fixed MTRRs supported and enabled */
X    if ((mtrrcap & 0x100) && (mtrrdef & 0x400)) {
X	sc->mr_cap = MR686_FIXMTRR;
X	nmdesc += MTRR_N64K + MTRR_N16K + MTRR_N4K;
X    }
X
X#ifndef __Lynx__
X    sc->mr_desc = 
X	(struct mem_range_desc *)malloc(nmdesc * sizeof(struct mem_range_desc), 
X					M_MEMDESC, M_WAITOK);
X#else
X    sc->mr_desc = 
X	(struct mem_range_desc *)sysbrk(nmdesc * sizeof(struct mem_range_desc));
X#endif
X    bzero(sc->mr_desc, nmdesc * sizeof(struct mem_range_desc));
X    sc->mr_ndesc = nmdesc;
X
X    mrd = sc->mr_desc;
X
X    /* Populate the fixed MTRR entries' base/length */
X    if (sc->mr_cap & MR686_FIXMTRR) {
X	for (i = 0; i < MTRR_N64K; i++, mrd++) {
X	    mrd->mr_base = i * 0x10000;
X	    mrd->mr_len = 0x10000;
X	    mrd->mr_flags = MDF_FIXBASE | MDF_FIXLEN | MDF_FIXACTIVE;
X	}
X	for (i = 0; i < MTRR_N16K; i++, mrd++) {
X	    mrd->mr_base = i * 0x4000 + 0x80000;
X	    mrd->mr_len = 0x4000;
X	    mrd->mr_flags = MDF_FIXBASE | MDF_FIXLEN | MDF_FIXACTIVE;
X	}
X	for (i = 0; i < MTRR_N4K; i++, mrd++) {
X	    mrd->mr_base = i * 0x1000 + 0xc0000;
X	    mrd->mr_len = 0x1000;
X	    mrd->mr_flags = MDF_FIXBASE | MDF_FIXLEN | MDF_FIXACTIVE;
X	}
X    }
X
X    /* 
X     * Get current settings, anything set now is considered to have 
X     * been set by the firmware. (XXX has something already played here?)
X     */
X    i686_mrfetch(sc);
X    mrd = sc->mr_desc;
X    for (i = 0; i < sc->mr_ndesc; i++, mrd++) {
X	if (mrd->mr_flags & MDF_ACTIVE)
X	    mrd->mr_flags |= MDF_FIRMWARE;
X    }
X}
X
X/*
X * Initialise MTRRs on an AP after the BSP has run the init code.
X */
Xstatic void
Xi686_mrAPinit(struct mem_range_softc *sc)
X{
X    i686_mrstoreone((void *)sc);	/* set MTRRs to match BSP */
X    wrmsr(MSR_MTRRdefType, mtrrdef);	/* set MTRR behaviour to match BSP */
X}
X
X#ifndef __Lynx__
Xstatic 
X#endif
Xvoid
Xi686_mem_drvinit(void *unused)
X{
X    /* Try for i686 MTRRs */
X    if ((cpu_feature & CPUID_MTRR) &&
X	((cpu_id & 0xf00) == 0x600) &&
X	((strcmp(cpu_vendor, "GenuineIntel") == 0) ||
X	(strcmp(cpu_vendor, "AuthenticAMD") == 0))) {
X	mem_range_softc.mr_op = &i686_mrops;
X    }
X}
X
X#ifndef __Lynx__
XSYSINIT(i686memdev,SI_SUB_DRIVERS,SI_ORDER_FIRST,i686_mem_drvinit,NULL)
X#endif
X
END-of-sys/drivers/mtrr/i686_mem.c
echo x - sys/drivers/mtrr/k6_mem.c
sed 's/^X//' >sys/drivers/mtrr/k6_mem.c << 'END-of-sys/drivers/mtrr/k6_mem.c'
X/*-
X * Copyright (c) 1999 Brian Fundakowski Feldman
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $FreeBSD: src/sys/i386/i386/k6_mem.c,v 1.4 1999/09/05 15:45:57 green Exp $
X *
X */
X
X#include <sys/param.h>
X#include <sys/kernel.h>
X#ifndef __Lynx__
X#include <sys/systm.h>
X#include <sys/ioccom.h>
X#include <sys/malloc.h>
X#else
X#include <proc.h>
X#include <mem.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <errno.h>
X#include <string.h>
X#endif
X#include <sys/memrange.h>
X
X#ifndef __Lynx__
X#include <machine/md_var.h>
X#include <machine/specialreg.h>
X#else
X#include "kprotos.h"
X#include "compat.h"
X
Xextern	u_int	cpu_feature;
Xextern	u_int	cpu_high;
Xextern	u_int	cpu_id;
Xextern	char	cpu_vendor[];
X#include <specialreg.h>
X#endif
X
X/*
X * A K6-2 MTRR is defined as the highest 15 bits having the address, the next
X * 15 having the mask, the 1st bit being "write-combining" and the 0th bit
X * being "uncacheable".
X *
X *	Address		    Mask	WC  UC
X * | XXXXXXXXXXXXXXX | XXXXXXXXXXXXXXX | X | X |
X *
X * There are two of these in the 64-bit UWCCR.
X */
X
X/*
X * NOTE: I do _not_ comment my code unless it's truly necessary. Don't
X * 	 expect anything frivolous here, and do NOT touch my bit-shifts
X *	 unless you want to break this.
X */
X
X#define UWCCR 0xc0000085
X
X#define k6_reg_get(reg, addr, mask, wc, uc)	do {			\
X		addr = (reg) & 0xfffe0000;				\
X		mask = ((reg) & 0x1fffc) >> 2;				\
X		wc = ((reg) & 0x2) >> 1;				\
X		uc = (reg) & 0x1;					\
X	} while (0)
X
X#define k6_reg_make(addr, mask, wc, uc) 				\
X		((addr) | ((mask) << 2) | ((wc) << 1) | uc)
X
Xstatic void k6_mrinit(struct mem_range_softc *sc);
Xstatic int k6_mrset(struct mem_range_softc *, struct mem_range_desc *, int *);
Xstatic __inline int k6_mrmake(struct mem_range_desc *, u_int32_t *);
X#ifndef __Lynx__
Xstatic 
X#endif
X	void k6_mem_drvinit(void *);
X
Xstatic struct mem_range_ops k6_mrops = {
X	k6_mrinit,
X	k6_mrset,
X	NULL
X};
X
Xstatic __inline int
Xk6_mrmake(struct mem_range_desc *desc, u_int32_t *mtrr) {
X	u_int32_t len = 0, wc, uc;
X	register int bit;
X
X	if (desc->mr_base &~ 0xfffe0000)
X		return EINVAL;
X	if (desc->mr_len < 131072 || !powerof2(desc->mr_len))
X		return EINVAL;
X	if (desc->mr_flags &~ (MDF_WRITECOMBINE|MDF_UNCACHEABLE))
X		return EOPNOTSUPP;
X
X	for (bit = ffs(desc->mr_len >> 17) - 1; bit < 15; bit++)
X		len |= 1 << (14 - bit); 
X	wc = (desc->mr_flags & MDF_WRITECOMBINE) ? 1 : 0;
X	uc = (desc->mr_flags & MDF_UNCACHEABLE) ? 1 : 0;
X
X	*mtrr = k6_reg_make(desc->mr_base, len, wc, uc);
X	return 0;
X}
X
Xstatic void
Xk6_mrinit(struct mem_range_softc *sc) {
X	u_int64_t reg;
X	u_int32_t addr, mask, wc, uc;
X	int d;
X
X	sc->mr_cap = 0;
X	sc->mr_ndesc = 2; /* XXX (BFF) For now, we only have one msr for this */
X#ifndef __Lynx__
X	sc->mr_desc = malloc(sc->mr_ndesc * sizeof(struct mem_range_desc),
X			     M_MEMDESC, M_NOWAIT);
X#else
X	sc->mr_desc = (struct mem_range_desc *) sysbrk(sc->mr_ndesc * sizeof(struct mem_range_desc));
X#endif
X	if (sc->mr_desc == NULL)
X		panic("k6_mrinit: malloc returns NULL");
X	bzero(sc->mr_desc, sc->mr_ndesc * sizeof(struct mem_range_desc));
X
X	reg = rdmsr(UWCCR);
X	for (d = 0; d < sc->mr_ndesc; d++) {
X		u_int32_t one = (reg & (0xffffffff << (32 * d))) >> (32 * d);
X
X		k6_reg_get(one, addr, mask, wc, uc);
X		sc->mr_desc[d].mr_base = addr;
X		sc->mr_desc[d].mr_len = ffs(mask) << 17;
X		if (wc)
X			sc->mr_desc[d].mr_flags |= MDF_WRITECOMBINE;
X		if (uc)
X			sc->mr_desc[d].mr_flags |= MDF_UNCACHEABLE;
X	}
X	
X	if (bootverbose)
X		printf("K6-family MTRR support enabled (%d registers)\n", sc->mr_ndesc);
X}
X
Xstatic int
Xk6_mrset(struct mem_range_softc *sc, struct mem_range_desc *desc, int *arg) {
X	u_int64_t reg;
X	u_int32_t mtrr;
X	int error, d;
X
X	switch (*arg) {
X	case MEMRANGE_SET_UPDATE:
X		error = k6_mrmake(desc, &mtrr);
X		if (error)
X			return error;
X		for (d = 0; d < sc->mr_ndesc; d++) {
X			if (!sc->mr_desc[d].mr_len) {
X				sc->mr_desc[d] = *desc;
X				goto out;
X			}
X			if (sc->mr_desc[d].mr_base == desc->mr_base &&
X			    sc->mr_desc[d].mr_len == desc->mr_len)
X				return EEXIST;
X		}
X
X		return ENOSPC;
X	case MEMRANGE_SET_REMOVE:
X		mtrr = 0;
X		for (d = 0; d < sc->mr_ndesc; d++)
X			if (sc->mr_desc[d].mr_base == desc->mr_base &&
X			    sc->mr_desc[d].mr_len == desc->mr_len) {
X				bzero(&sc->mr_desc[d], sizeof(sc->mr_desc[d]));
X				goto out;
X			}
X
X		return ENOENT;
X	default:
X		return EOPNOTSUPP;
X	}
X
Xout:
X	
X	disable_intr();
X	wbinvd();
X	reg = rdmsr(UWCCR);
X	reg &= ~(0xffffffff << (32 * d));
X	reg |= mtrr << (32 * d);
X	wrmsr(UWCCR, reg);
X	wbinvd();
X	enable_intr();
X
X	return 0;
X}
X
X#ifndef __Lynx__
Xstatic
X#endif
Xvoid
Xk6_mem_drvinit(void *unused) {
X	if (!strcmp(cpu_vendor, "AuthenticAMD") &&
X	    (cpu_id & 0xf00) == 0x500 &&
X	    	((cpu_id & 0xf0) > 0x80 ||
X		    ((cpu_id & 0xf0) == 0x80 &&
X		     (cpu_id & 0xf) > 0x7))
X	    )
X		mem_range_softc.mr_op = &k6_mrops;
X}
X
X#ifndef __Lynx__
XSYSINIT(k6memdev, SI_SUB_DRIVERS, SI_ORDER_FIRST, k6_mem_drvinit, NULL)
X#endif
END-of-sys/drivers/mtrr/k6_mem.c
echo x - sys/drivers/mtrr/kprotos.h
sed 's/^X//' >sys/drivers/mtrr/kprotos.h << 'END-of-sys/drivers/mtrr/kprotos.h'
X/*
X * Copyright 1999 by Thomas Mueller
X *
X * Permission to use, copy, modify, distribute, and sell this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the names of the above listed copyright holder(s)
X * not be used in advertising or publicity pertaining to distribution of
X * the software without specific, written prior permission.  The above listed  
X * copyright holder(s) make(s) no representations about the suitability of this
X * software for any purpose.  It is provided "as is" without express or
X * implied warranty.
X * 
X * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD
X * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
X * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
X * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
X * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
X * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
X * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X * 
X */
X
X#ifndef __kprotos_h
X#define __kprotos_h
X
X/* definitions for driver service calls which are currently (3.0.1)
X * commented out in the system headers (and probably will be
X * present in future versions).
X */
X
X/* from kernel.h: */
X
Xextern void get_timestamp   _AP((struct timespec *));
X
X/* address fault handling */
X
Xextern int recoset              _AP((void));
Xextern void noreco              _AP((void));
X
X/* kernel printf's */
X
Xextern void cprintf             _AP((char *, ...));
Xextern void kkprintf            _AP((char *, ...));
Xextern void ksprintf            _AP((char *, ...));
X
X/* I/O interrupts */
X
Xextern int iointset   _AP((int vector, void (*function)(void *), char *argument));
Xextern int iointclr             _AP((int));
Xextern void ioint_link          _AP((int));
X
Xextern void panic               _AP((char *));
X
X/* timeout */
X
Xextern int timeout              _AP((void (*)(char *), char *, int));
Xextern void cancel_timeout      _AP((int));
X
X/* time */
Xextern unsigned long nanotime	_AP((unsigned long *secs));
X
X/* kernel semaphores */
Xextern int ssignal              _AP((int *));
Xextern int ssignaln             _AP((int *, int));
Xextern int sreset               _AP((int *));
Xextern int swait                _AP((int *, int));
Xextern int scount               _AP((int *));
X
X/* kernel-level errno */
X
Xextern int pgeterr              _AP((void));
X
X/* from mem.h: */
X
Xextern int sysfree              _AP((char *, int));
X
X/* allocate physically-contiguous memory */
Xextern char *alloc_cmem         _AP((int size));
Xextern void free_cmem           _AP((char *, int size));
Xextern char *permap		_AP((long physaddr, long size));
X
Xextern int mem_map		_AP((struct memblock *mblock, int tjob));
Xextern int mem_unmap		_AP((struct memblock *mblock, int tjob));
X
X/* from st.h: */
X
X/* system threads */
X
Xextern int ststart     _AP((void (*)(), int, int, char *, int, char *));
Xextern void stsetprio           _AP((int stid, int prio));
Xextern int stgetprio            _AP((int stid));
Xextern int stgetid              _AP((void));
Xextern void stgetowne           _AP((int stid));
Xextern void stkill              _AP((int stid, int signal));
Xextern void stsignal  _AP((int (*handler)(char *arg, int signum), char *arg));
X
X/* get priority of current proces */
Xextern int _getpriority         _AP((void));
X
X/* tracking priorities */
Xextern void priot_remove        _AP((struct priotrack *p, int prio));
Xextern int priot_max            _AP((struct priotrack *p));
Xextern void priot_removen   _AP((struct priotrack *p, int prio, int n));
X
X/* user proc signals */
Xextern int _kill		_AP((int pid, int signal));
Xextern int _killpg		_AP((int pgrp, int signal));
Xextern int getpid		_AP((void));
Xextern int suser		_AP((void));
X
X#endif
END-of-sys/drivers/mtrr/kprotos.h
echo x - sys/drivers/mtrr/memrange.h
sed 's/^X//' >sys/drivers/mtrr/memrange.h << 'END-of-sys/drivers/mtrr/memrange.h'
X/* This is /usr/include/sys/memrange.h from FreeBSD 3.3 */
X
X/*
X * Memory range attribute operations, peformed on /dev/mem
X */
X
X/* Memory range attributes */
X#define MDF_UNCACHEABLE		(1<<0)	/* region not cached */
X#define MDF_WRITECOMBINE	(1<<1)	/* region supports "write combine" action */
X#define MDF_WRITETHROUGH	(1<<2)	/* write-through cached */
X#define MDF_WRITEBACK		(1<<3)	/* write-back cached */
X#define MDF_WRITEPROTECT	(1<<4)	/* read-only region */
X#define MDF_ATTRMASK		(0x00ffffff)
X
X#define MDF_FIXBASE		(1<<24)	/* fixed base */
X#define MDF_FIXLEN		(1<<25)	/* fixed length */
X#define MDF_FIRMWARE		(1<<26)	/* set by firmware (XXX not useful?) */
X#define MDF_ACTIVE		(1<<27)	/* currently active */
X#define MDF_BOGUS		(1<<28)	/* we don't like it */
X#define MDF_FIXACTIVE		(1<<29)	/* can't be turned off */
X#define MDF_BUSY		(1<<30)	/* range is in use */
X
Xstruct mem_range_desc
X{
X	u_int64_t	mr_base;
X	u_int64_t	mr_len;
X	int		mr_flags;
X	char		mr_owner[8];
X};
X
Xstruct mem_range_op
X{
X	struct mem_range_desc	*mo_desc;
X	int			mo_arg[2];
X#define MEMRANGE_SET_UPDATE	0
X#define MEMRANGE_SET_REMOVE	1
X	/* XXX want a flag that says "set and undo when I exit" */
X};
X
X#define MEMRANGE_GET	_IOWR('m', 50, struct mem_range_op)
X#define MEMRANGE_SET	_IOW('m', 51, struct mem_range_op)
X
X#ifdef KERNEL
X
X#ifndef __Lynx__
XMALLOC_DECLARE(M_MEMDESC);
X#endif
X
Xstruct mem_range_softc;
Xstruct mem_range_ops
X{
X	void	(*init)(struct mem_range_softc *sc);
X	int	(*set)(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg);
X    	void	(*initAP)(struct mem_range_softc *sc);
X};
X
Xstruct mem_range_softc 
X{
X	struct mem_range_ops	*mr_op;
X	int			mr_cap;
X	int			mr_ndesc;
X	struct mem_range_desc 	*mr_desc;
X};
X
Xextern struct mem_range_softc mem_range_softc;
X
Xextern int mem_range_attr_get(struct mem_range_desc *mrd, int *arg);
Xextern int mem_range_attr_set(struct mem_range_desc *mrd, int *arg);
Xextern void mem_range_AP_init(void);
X#endif
X
END-of-sys/drivers/mtrr/memrange.h
echo x - sys/drivers/mtrr/mtrr.4
sed 's/^X//' >sys/drivers/mtrr/mtrr.4 << 'END-of-sys/drivers/mtrr/mtrr.4'
X
XMTRR(4)              device facilities (i386 Architecture)             MTRR(4)
X
XNNAAMMEE
X     mmttrrrr - MTRR device driver
X
XDDEESSCCRRIIPPTTIIOONN
X     The _/_d_e_v_/_m_t_r_r driver provides access to the CPUs memory type range regis-
X     ters (MTRR) for use by the XFree86 X servers.
X
XIIOOCCTTLL IINNTTEERRFFAACCEE
X     Several CPU architectures allow attributes to be associated with ranges
X     of physical memory.  These attributes can be manipulated via iiooccttll()
X     calls performed on //ddeevv//mmttrrrr. Declarations and data types are to be found
X     in _<_s_y_s_/_m_e_m_r_a_n_g_e_._h_>
X
X     The specific attributes, and number of programmable ranges may vary be-
X     tween architectures.  The full set of supported attributes is:
X
X     MDF_UNCACHEABLE
X       The region is not cached.
X
X     MDF_WRITECOMBINE
X       Writes to the region may be combined or performed out of order.
X
X     MDF_WRITETHROUGH
X       Writes to the region are committed synchronously.
X
X     MDF_WRITEBACK
X       Writes to the region are committed asynchronously.
X
X     MDF_WRITEPROTECT
X       The region cannot be written to.
X
X     Memory ranges are described by _s_t_r_u_c_t _m_e_m___r_a_n_g_e___d_e_s_c:
X
X           u_int64_t       mr_base;        /* physical base address */
X           u_int64_t       mr_len;         /* physical length of region */
X           int             mr_flags;       /* attributes of region */
X           char            mr_owner[8];
X
X     In addition to the region attributes listed above, the following flags
X     may also be set in the _m_r___f_l_a_g_s field:
X
X     MDF_FIXBASE
X       The region's base address cannot be changed.
X
X     MDF_FIXLEN
X       The region's length cannot be changed.
X
X     MDF_FIRMWARE
X       The region is believed to have been established by the system firmare.
X
X     MDF_ACTIVE
X       The region is currently active.
X
X     MDF_BOGUS
X       We believe the region to be invalid or otherwise erroneous.
X
X     MDF_FIXACTIVE
X       The region cannot be disabled.
X
X     MDF_BUSY
X       The region is currently owned by another process and may not be al-
X       tered.
X
X     Operations are performed using _s_t_r_u_c_t _m_e_m___r_a_n_g_e___o_p:
X
X           struct mem_range_desc   *mo_desc;
X           int                     mo_arg[2];
X
X     The _M_E_M_R_A_N_G_E___G_E_T ioctl is used to retrieve current memory range at-
X     tributes. If _m_o___a_r_g_[_0_] is set to 0, it will be updated with the total
X     number of memory range descriptors.  If greater than 0, the array at
X     _m_o___d_e_s_c will be filled with a corresponding number of descriptor struc-
X     tures, or the maximum, whichever is less.
X
X     The _M_E_M_R_A_N_G_E___S_E_T ioctl is used to add, alter and remove memory range at-
X     tributes.  A range with the MDF_FIXACTIVE flag may not be removed; a
X     range with the MDF_BUSY flag may not be removed or updated.
X
X     _m_o___a_r_g_[_0_] should be set to MEMRANGE_SET_UPDATE to update an existing or
X     establish a new range, or to MEMRANGE_SET_REMOVE to remove a range.
X
XRREETTUURRNN VVAALLUUEESS
X     EOPNOTSUPP
X       Memory range operations are not supported on this architecture.
X
X     ENXIO
X       No memory range descriptors are available (eg. firmware has not enabled
X       any).
X
X     EINVAL
X       The memory range supplied as an argument is invalid or overlaps another
X       range in a fashion not supported by this architecture.
X
X     EBUSY
X       An attempt to remove or update a range failed because the range is
X       busy.
X
X     EBUSY
X       An attempt to open the device driver more than once.
X
X     ENOSPC
X       An attempt to create a new range failed due to a shortage of hardware
X       resources (eg. descriptor slots).
X
X     ENOENT
X       An attempt to remove a range failed because no range matches the de-
X       scriptor base/length supplued.
X
X     EPERM
X       An attempt to remove a range failed because the range is permanently
X       enabled.
X
X     EPERM
X       The effective user ID of the calling process is not 0.
X
XSSEEEE AALLSSOO
X     XFree86(1),
X
XHHIISSTTOORRYY
X     _/_d_e_v_/_m_t_r_r is modeled after the _/_d_e_v_/_m_e_m ioctl interface on FreeBSD 3.3.
X
XAAUUTTHHOORR
X     The MTRR driver was written by Thomas Mueller.
X
X     This manual page was derived from the NetBSD and OpenBSD aperture driver
X     included in the XFree86 distribution which was written for the XFree86
X     Project Inc. by Matthieu Herrb. The memory range attributes support was
X     originally written by Michael Smith for FreeBSD.
X
XBBUUGGSS
X     This driver allows access to all addresses above _p_h_y_s_m_e_m. It should be
X     restricted to the actual address range of the video memory.
X
X     Busy range attributes are not yet managed correctly.
X
X     Memory range attributes configuration should probably be controlled
X     through _/_d_e_v_/_m_e_m.
X
X LynxOS                        November 18, 1999                             3
END-of-sys/drivers/mtrr/mtrr.4
echo x - sys/drivers/mtrr/mtrr.c
sed 's/^X//' >sys/drivers/mtrr/mtrr.c << 'END-of-sys/drivers/mtrr/mtrr.c'
X/*
X * Copyright 1999 by Thomas Mueller
X * All rights reserved.
X *
X * Permission to use, copy, modify, distribute, and sell this software and its
X * documentation for any purpose is hereby granted without fee, provided that
X * the above copyright notice appear in all copies and that both that
X * copyright notice and this permission notice appear in supporting
X * documentation, and that the names of the above listed copyright holder(s)
X * not be used in advertising or publicity pertaining to distribution of
X * the software without specific, written prior permission.  The above listed  
X * copyright holder(s) make(s) no representations about the suitability of this
X * software for any purpose.  It is provided "as is" without express or
X * implied warranty.
X * 
X * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD
X * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
X * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
X * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
X * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
X * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
X * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X * 
X */
X
X/*----------------------------------------------------------------------
X**
X**   PentiumPRO/II/III, K6-II/III and Athlon MTRR support character 
X**   device driver. Ported from FreeBSDs /dev/mem memrange ioctl 
X**   interface for use by XFree86 4.0 X Server
X**
X**----------------------------------------------------------------------
X*/
X
Xstatic const char __RCSid[] = "$XFree86: xc/programs/Xserver/hw/xfree86/etc/MTRR-Lynx.shar,v 1.1 1999/12/08 06:10:11 dawes Exp $";
X
X/*
X** Includes and imports
X*/
X
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/ioctl.h>
X#include <conf.h>  
X#include <kernel.h>
X#include <proc.h>
X#include <mem.h>
X#include <varargs.h>
X#include <string.h> 
X#include <errno.h>  
X
X#include <sys/memrange.h>
X
X#include "kprotos.h"
X#include "compat.h"
X
Xextern void cpuid		_AP((void));
Xextern void i686_mem_drvinit	_AP((void *unused));
Xextern void k6_mem_drvinit	_AP((void *unused));
X
Xd_open_t	mtrr_open;
Xd_close_t	mtrr_close;
Xd_read_t	mtrr_read;
Xd_write_t	mtrr_write;
Xd_ioctl_t	mtrr_ioctl;
Xd_select_t	mtrr_select;
X
Xstatic int mem_range_attr_get	_AP((struct mem_range_desc *mrd, int *arg));
Xstatic int mem_range_attr_set	_AP((struct mem_range_desc *mrd, int *arg));
X
Xstruct mem_range_softc mem_range_softc;
X
Xtypedef char *mtrr_ptr_t;		/* dummy */
X
Xstruct mtrr_statics {
X	int	open;
X};
X
Xint mtrrinfo = 0;		/* dummy device info */
X
Xchar *
Xmtrr_install(void *info)
X{
X	struct mtrr_statics *s;
X
X	if ((s = (struct mtrr_statics *) sysbrk(sizeof(struct mtrr_statics))) == NULL) {
X		pseterr(ENOMEM);
X		return (char *) SYSERR;
X	}
X	s->open = 0;
X
X	bzero(&mem_range_softc, sizeof(mem_range_softc));
X
X	/* what are we running on? (only CPUID probe!) */
X	cpuid();
X
X	/* add others as they come... */
X	i686_mem_drvinit(NULL);
X	k6_mem_drvinit(NULL);
X
X	/* Initialise memory range handling */
X	if (mem_range_softc.mr_op != NULL) {
X		mem_range_softc.mr_op->init(&mem_range_softc);
X		return (char *) s;
X	}
X
X	return (char *) SYSERR;
X}
X
Xvoid
Xmtrr_uninstall(void *arg)
X{
X	sysfree(arg, sizeof(struct mtrr_statics));
X}
X
X/*
X * 
X */
Xint
Xmtrr_open(void *arg, int dev, struct file *f)
X{
X	struct mtrr_statics *s = arg;
X
X	if (!suser()) {
X		pseterr(EPERM);
X		return SYSERR;
X	}
X	if (s->open) {
X		pseterr(EBUSY);
X		return SYSERR;
X	}
X	s->open = 1;
X	return OK;
X}
X
X
X/*
X * 
X */
Xint
Xmtrr_close(void *arg, struct file *f)
X{
X	struct mtrr_statics *s = arg;
X
X	s->open = 0;
X	return OK;
X}
X
X/*
X * 
X */
Xint
Xmtrr_read(void *arg, struct file *f, char *buf, int count)
X{
X	pseterr(ENXIO);
X	return SYSERR;
X}
X
X
X/*
X * 
X */
Xint
Xmtrr_write(void *arg, struct file *f, char *buf, int count)
X{
X	pseterr(ENXIO);
X	return SYSERR;
X}
X
Xint
Xmtrr_select(void *arg, struct file *f, int what, struct sel *ffs)
X{
X	pseterr(ENXIO);
X	return SYSERR;
X}
X
X
X/* ====================================================================== */
X
X/* memrange interface taken from FreeBSD code in /sys/i386/i386/mem.c 
X * copyrighted as follows:
X */
X
X/*-
X * Copyright (c) 1988 University of Utah.
X * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * the Systems Programming Group of the University of Utah Computer
X * Science Department, and code derived from software contributed to
X * Berkeley by William Jolitz.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X *	from: Utah $Hdr: mem.c 1.13 89/10/08$
X *	from: @(#)mem.c	7.2 (Berkeley) 5/9/91
X * $FreeBSD: src/sys/i386/i386/mem.c,v 1.53.2.5 1999/08/31 06:45:41 msmith Exp $
X */
X
X
X/*
X * Operations for changing memory attributes.
X *
X * This is basically just an ioctl shim for mem_range_attr_get
X * and mem_range_attr_set.
X */
Xint 
Xmtrr_ioctl(void *arg, struct file *f, int cmd, char *data)
X{
X	int nd, error = 0;
X	struct mem_range_op *mo = (struct mem_range_op *)data;
X	struct mem_range_desc *md;
X
X	/* is this for us? */
X	if ((cmd != MEMRANGE_GET) &&
X	    (cmd != MEMRANGE_SET)) {
X		pseterr(EINVAL);
X		return SYSERR;
X	}
X
X	/* any chance we can handle this? */
X	if (mem_range_softc.mr_op == NULL) {
X		pseterr(EOPNOTSUPP);
X		return SYSERR;
X	}
X
X	/* do we have any descriptors? */
X	if (mem_range_softc.mr_ndesc == 0) {
X		pseterr(ENXIO);
X		return SYSERR;
X	}
X
X	switch(cmd) {
X	case MEMRANGE_GET:
X		if (wbounds((unsigned long)mo) < sizeof(*mo)) {
X			pseterr(EFAULT);
X			return SYSERR;
X		}
X		nd = imin(mo->mo_arg[0], mem_range_softc.mr_ndesc);
X		if (nd > 0) {
X			if (wbounds((unsigned long)mo->mo_desc) < nd * sizeof(struct mem_range_desc)) {
X				pseterr(EFAULT);
X				return SYSERR;
X			}
X			md = (struct mem_range_desc *)
X				sysbrk(nd * sizeof(struct mem_range_desc));
X			error = mem_range_attr_get(md, &nd);
X			if (!error) {
X				   bcopy(md, mo->mo_desc, 
X					nd * sizeof(struct mem_range_desc));
X			}
X			sysfree((char *)md, nd * sizeof(struct mem_range_desc));
X		} else {
X			nd = mem_range_softc.mr_ndesc;
X		}
X		mo->mo_arg[0] = nd;
X		break;
X		
X	case MEMRANGE_SET:
X		if (rbounds((unsigned long)mo) < sizeof(*mo) ||
X		    rbounds((unsigned long)mo->mo_desc) < sizeof(struct mem_range_desc)) {
X			pseterr(EFAULT);
X			return SYSERR;
X		}
X		md = (struct mem_range_desc *)sysbrk(sizeof(struct mem_range_desc));
X		bcopy(mo->mo_desc, md, sizeof(struct mem_range_desc));
X		/* clamp description string */
X		md->mr_owner[sizeof(md->mr_owner) - 1] = 0;
X		if (error == 0)
X			error = mem_range_attr_set(md, &mo->mo_arg[0]);
X		sysfree((char *)md, sizeof(struct mem_range_desc));
X		break;
X	    
X	default:
X		error = EOPNOTSUPP;
X	}
X	if (error) {
X		pseterr(error);
X		return SYSERR;
X	}
X	return OK;
X}
X
X/*
X * Implementation-neutral, kernel-callable functions for manipulating
X * memory range attributes.
X */
Xstatic int
Xmem_range_attr_get(mrd, arg)
X	struct mem_range_desc *mrd;
X	int *arg;
X{
X	/* can we handle this? */
X	if (mem_range_softc.mr_op == NULL)
X		return(EOPNOTSUPP);
X
X	if (*arg == 0) {
X		*arg = mem_range_softc.mr_ndesc;
X	} else {
X		bcopy(mem_range_softc.mr_desc, mrd, (*arg) * sizeof(struct mem_range_desc));
X	}
X	return(0);
X}
X
Xstatic int
Xmem_range_attr_set(mrd, arg)
X	struct mem_range_desc *mrd; 
X	int *arg;
X{
X	/* can we handle this? */
X	if (mem_range_softc.mr_op == NULL)
X		return(EOPNOTSUPP);
X
X	return(mem_range_softc.mr_op->set(&mem_range_softc, mrd, arg));
X}
END-of-sys/drivers/mtrr/mtrr.c
echo x - sys/drivers/mtrr/mtrr.cfg
sed 's/^X//' >sys/drivers/mtrr/mtrr.cfg << 'END-of-sys/drivers/mtrr/mtrr.cfg'
X#!DYNAMINST!C:mtrr.dldd
XC:mtrr: \
X    :mtrr_open:mtrr_close:mtrr_read:mtrr_write: \
X    :mtrr_select:mtrr_ioctl:mtrr_install:mtrr_uninstall
XD:MTRR device:mtrrinfo::
XN:mtrr:0:
X
END-of-sys/drivers/mtrr/mtrr.cfg
echo x - sys/drivers/mtrr/mtrr.man
sed 's/^X//' >sys/drivers/mtrr/mtrr.man << 'END-of-sys/drivers/mtrr/mtrr.man'
X.\"
X.\" Copyright 1999 Thomas Mueller
X.\" All rights reserved.
X.\"
X.\" Redistribution and use in source and binary forms, with or without
X.\" modification, are permitted provided that the following conditions
X.\" are met:
X.\" 1. Redistributions of source code must retain the above copyright
X.\"    notice, this list of conditions and the following disclaimer.
X.\" 2. Redistributions in binary form must reproduce the above copyright
X.\"    notice, this list of conditions and the following disclaimer in the
X.\"    documentation and/or other materials provided with the distribution.
X.\" 3. The name of the author may not be used to endorse or promote products
X.\"    derived from this software without specific prior written permission
X.\"
X.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
X.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
X.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
X.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
X.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
X.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
X.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
X.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
X.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
X.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X.\"
X.Dd November 18, 1999
X.Dt MTRR 4 i386
X.Os LynxOS
X.Sh NAME
X.Nm mtrr
X.Nd
XMTRR device driver
X.Sh DESCRIPTION
XThe
X.Pa /dev/mtrr
Xdriver provides access to the CPUs memory type range registers (MTRR)
Xfor use by the XFree86 X servers.
X.Sh IOCTL INTERFACE
XSeveral CPU architectures allow attributes to be associated with ranges 
Xof physical memory.  These attributes can be manipulated via
X.Fn ioctl
Xcalls performed on
X.Nm /dev/mtrr .
XDeclarations and data types are to be found in
X.Pa <sys/memrange.h>
X.Pp
XThe specific attributes, and number of programmable ranges may vary between
Xarchitectures.  The full set of supported attributes is:
X.Bl -tag -width 10
X.It MDF_UNCACHEABLE
XThe region is not cached.
X.It MDF_WRITECOMBINE
XWrites to the region may be combined or performed out of order.
X.It MDF_WRITETHROUGH
XWrites to the region are committed synchronously.
X.It MDF_WRITEBACK
XWrites to the region are committed asynchronously.
X.It MDF_WRITEPROTECT
XThe region cannot be written to.
X.El
X.Pp
XMemory ranges are described by
X.Fa struct mem_range_desc :
X.Bd -literal -offset indent
Xu_int64_t	mr_base;	/\(** physical base address \(**/
Xu_int64_t	mr_len;		/\(** physical length of region \(**/
Xint		mr_flags;	/\(** attributes of region \(**/
Xchar		mr_owner[8];
X.Ed
X.Pp
XIn addition to the region attributes listed above, the following flags
Xmay also be set in the
X.Fa mr_flags
Xfield:
X.Bl -tag -width 10
X.It MDF_FIXBASE
XThe region's base address cannot be changed.
X.It MDF_FIXLEN
XThe region's length cannot be changed.
X.It MDF_FIRMWARE
XThe region is believed to have been established by the system firmare.
X.It MDF_ACTIVE
XThe region is currently active.
X.It MDF_BOGUS
XWe believe the region to be invalid or otherwise erroneous.
X.It MDF_FIXACTIVE
XThe region cannot be disabled.
X.It MDF_BUSY
XThe region is currently owned by another process and may not be 
Xaltered.
X.El
X.Pp
XOperations are performed using
X.Fa struct mem_range_op :
X.Bd -literal -offset indent
Xstruct mem_range_desc	*mo_desc;
Xint			mo_arg[2];
X.Ed
X.Pp
XThe
X.Fa MEMRANGE_GET
Xioctl is used to retrieve current memory range attributes. If
X.Fa mo_arg[0]
Xis set to 0, it will be updated with the total number of memory range
Xdescriptors.  If greater than 0, the array at
X.Fa mo_desc
Xwill be filled with a corresponding number of descriptor structures,
Xor the maximum, whichever is less.
X.Pp
XThe 
X.Fa MEMRANGE_SET
Xioctl is used to add, alter and remove memory range attributes.  A range
Xwith the MDF_FIXACTIVE flag may not be removed; a range with the MDF_BUSY
Xflag may not be removed or updated.
X.Pp
X.Fa mo_arg[0] 
Xshould be set to MEMRANGE_SET_UPDATE to update an existing
Xor establish a new range, or to MEMRANGE_SET_REMOVE to remove a range.
X.Pp
X.Sh RETURN VALUES
X.Bl -tag -width 10
X.It EOPNOTSUPP
XMemory range operations are not supported on this architecture.
X.It ENXIO
XNo memory range descriptors are available (eg. firmware has not enabled
Xany).
X.It EINVAL
XThe memory range supplied as an argument is invalid or overlaps another
Xrange in a fashion not supported by this architecture.
X.It EBUSY
XAn attempt to remove or update a range failed because the range is busy.
X.It EBUSY
XAn attempt to open the device driver more than once.
X.It ENOSPC
XAn attempt to create a new range failed due to a shortage of hardware
Xresources (eg. descriptor slots).
X.It ENOENT
XAn attempt to remove a range failed because no range matches the descriptor
Xbase/length supplued.
X.It EPERM
XAn attempt to remove a range failed because the range is permanently
Xenabled.
X.It EPERM
XThe effective user ID of the calling process is not 0.
X.El
X.Sh SEE ALSO
X.Xr XFree86 1 ,
X.Sh HISTORY
X.Pa /dev/mtrr
Xis modeled after the
X.Pa /dev/mem
Xioctl interface on FreeBSD 3.3.
X.Sh AUTHOR
XThe MTRR driver was written by Thomas Mueller.
X.Pp
XThis manual page was derived from the NetBSD and OpenBSD
Xaperture driver included in the XFree86 distribution which
Xwas written for the XFree86 Project Inc. by
XMatthieu Herrb. The memory range 
Xattributes support was originally written by Michael Smith for FreeBSD.
X.Sh BUGS
XThis driver allows access to all addresses above
X.Va physmem .
XIt should be restricted to the actual address range of the video
Xmemory.
X.Pp
XBusy range attributes are not yet managed correctly.
X.Pp
XMemory range attributes configuration should probably be controlled through 
X.Pa /dev/mem . 
END-of-sys/drivers/mtrr/mtrr.man
echo x - sys/drivers/mtrr/specialreg.h
sed 's/^X//' >sys/drivers/mtrr/specialreg.h << 'END-of-sys/drivers/mtrr/specialreg.h'
X/*-
X * Copyright (c) 1991 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X *	from: @(#)specialreg.h	7.1 (Berkeley) 5/9/91
X * $FreeBSD: src/sys/i386/include/specialreg.h,v 1.16.2.2 1999/08/31 01:19:23 msmith Exp $
X */
X
X#ifndef _MACHINE_SPECIALREG_H_
X#define	_MACHINE_SPECIALREG_H_
X
X/*
X * Bits in 386 special registers:
X */
X#define	CR0_PE	0x00000001	/* Protected mode Enable */
X#define	CR0_MP	0x00000002	/* "Math" Present (NPX or NPX emulator) */
X#define	CR0_EM	0x00000004	/* EMulate non-NPX coproc. (trap ESC only) */
X#define	CR0_TS	0x00000008	/* Task Switched (if MP, trap ESC and WAIT) */
X#ifdef notused
X#define	CR0_ET	0x00000010	/* Extension Type (387 (if set) vs 287) */
X#endif
X#ifndef CR0_PG
X#define	CR0_PG	0x80000000	/* PaGing enable */
X#endif
X
X/*
X * Bits in 486 special registers:
X */
X#define	CR0_NE	0x00000020	/* Numeric Error enable (EX16 vs IRQ13) */
X#define	CR0_WP	0x00010000	/* Write Protect (honor page protect in
X							   all modes) */
X#define	CR0_AM	0x00040000	/* Alignment Mask (set to enable AC flag) */
X#define	CR0_NW  0x20000000	/* Not Write-through */
X#define	CR0_CD  0x40000000	/* Cache Disable */
X
X/*
X * Bits in PPro special registers
X */
X#define	CR4_VME	0x00000001	/* Virtual 8086 mode extensions */
X#define	CR4_PVI	0x00000002	/* Protected-mode virtual interrupts */
X#ifndef CR4_TSD
X#define	CR4_TSD	0x00000004	/* Time stamp disable */
X#endif
X#define	CR4_DE	0x00000008	/* Debugging extensions */
X#define	CR4_PSE	0x00000010	/* Page size extensions */
X#define	CR4_PAE	0x00000020	/* Physical address extension */
X#define	CR4_MCE	0x00000040	/* Machine check enable */
X#define	CR4_PGE	0x00000080	/* Page global enable */
X#define	CR4_PCE	0x00000100	/* Performance monitoring counter enable */
X
X/*
X * CPUID instruction features register
X */
X#define	CPUID_FPU	0x0001
X#define	CPUID_VME	0x0002
X#define	CPUID_DE	0x0004
X#define	CPUID_PSE	0x0008
X#define	CPUID_TSC	0x0010
X#define	CPUID_MSR	0x0020
X#define	CPUID_PAE	0x0040
X#define	CPUID_MCE	0x0080
X#define	CPUID_CX8	0x0100
X#define	CPUID_APIC	0x0200
X#define	CPUID_B10	0x0400
X#define	CPUID_B11	0x0800
X#define	CPUID_MTRR	0x1000
X#define	CPUID_PGE	0x2000
X#define	CPUID_MCA	0x4000
X#define	CPUID_CMOV	0x8000
X
X/*
X * Model-specific registers for the i386 family
X */
X#define MSR_P5_MC_ADDR		0x000
X#define MSR_P5_MC_TYPE		0x001
X#define MSR_TSC			0x010
X#define MSR_APICBASE		0x01b
X#define MSR_EBL_CR_POWERON	0x02a
X#define MSR_BIOS_UPDT_TRIG	0x079
X#define MSR_BIOS_SIGN		0x08b
X#define MSR_PERFCTR0		0x0c1
X#define MSR_PERFCTR1		0x0c2
X#define MSR_MTRRcap		0x0fe
X#define MSR_MCG_CAP		0x179
X#define MSR_MCG_STATUS		0x17a
X#define MSR_MCG_CTL		0x17b
X#define MSR_EVNTSEL0		0x186
X#define MSR_EVNTSEL1		0x187
X#define MSR_DEBUGCTLMSR		0x1d9
X#define MSR_LASTBRANCHFROMIP	0x1db
X#define MSR_LASTBRANCHTOIP	0x1dc
X#define MSR_LASTINTFROMIP	0x1dd
X#define MSR_LASTINTTOIP		0x1de
X#define MSR_ROB_CR_BKUPTMPDR6	0x1e0
X#define MSR_MTRRVarBase		0x200
X#define MSR_MTRR64kBase		0x250
X#define MSR_MTRR16kBase		0x258
X#define MSR_MTRR4kBase		0x268
X#define MSR_MTRRdefType		0x2ff
X#define MSR_MC0_CTL		0x400
X#define MSR_MC0_STATUS		0x401
X#define MSR_MC0_ADDR		0x402
X#define MSR_MC0_MISC		0x403
X#define MSR_MC1_CTL		0x404
X#define MSR_MC1_STATUS		0x405
X#define MSR_MC1_ADDR		0x406
X#define MSR_MC1_MISC		0x407
X#define MSR_MC2_CTL		0x408
X#define MSR_MC2_STATUS		0x409
X#define MSR_MC2_ADDR		0x40a
X#define MSR_MC2_MISC		0x40b
X#define MSR_MC4_CTL		0x40c
X#define MSR_MC4_STATUS		0x40d
X#define MSR_MC4_ADDR		0x40e
X#define MSR_MC4_MISC		0x40f
X#define MSR_MC3_CTL		0x410
X#define MSR_MC3_STATUS		0x411
X#define MSR_MC3_ADDR		0x412
X#define MSR_MC3_MISC		0x413
X
X/*
X * Constants related to MTRRs
X */
X#define MTRR_N64K		8	/* numbers of fixed-size entries */
X#define MTRR_N16K		16
X#define MTRR_N4K		64
X
X/*
X * Cyrix configuration registers, accessible as IO ports.
X */
X#define	CCR0			0xc0	/* Configuration control register 0 */
X#define	CCR0_NC0		0x01	/* First 64K of each 1M memory region is
X								   non-cacheable */
X#define	CCR0_NC1		0x02	/* 640K-1M region is non-cacheable */
X#define	CCR0_A20M		0x04	/* Enables A20M# input pin */
X#define	CCR0_KEN		0x08	/* Enables KEN# input pin */
X#define	CCR0_FLUSH		0x10	/* Enables FLUSH# input pin */
X#define	CCR0_BARB		0x20	/* Flushes internal cache when entering hold
X								   state */
X#define	CCR0_CO			0x40	/* Cache org: 1=direct mapped, 0=2x set
X								   assoc */
X#define	CCR0_SUSPEND	0x80	/* Enables SUSP# and SUSPA# pins */
X
X#define	CCR1			0xc1	/* Configuration control register 1 */
X#define	CCR1_RPL		0x01	/* Enables RPLSET and RPLVAL# pins */
X#define	CCR1_SMI		0x02	/* Enables SMM pins */
X#define	CCR1_SMAC		0x04	/* System management memory access */
X#define	CCR1_MMAC		0x08	/* Main memory access */
X#define	CCR1_NO_LOCK	0x10	/* Negate LOCK# */
X#define	CCR1_SM3		0x80	/* SMM address space address region 3 */
X
X#define	CCR2			0xc2
X#define	CCR2_WB			0x02	/* Enables WB cache interface pins */
X#define	CCR2_SADS		0x02	/* Slow ADS */
X#define	CCR2_LOCK_NW	0x04	/* LOCK NW Bit */
X#define	CCR2_SUSP_HLT	0x08	/* Suspend on HALT */
X#define	CCR2_WT1		0x10	/* WT region 1 */
X#define	CCR2_WPR1		0x10	/* Write-protect region 1 */
X#define CCR2_BARB		0x20	/* Flushes write-back cache when entering
X								   hold state. */
X#define	CCR2_BWRT		0x40	/* Enables burst write cycles */
X#define	CCR2_USE_SUSP	0x80	/* Enables suspend pins */
X
X#define	CCR3			0xc3
X#define	CCR3_SMILOCK	0x01	/* SMM register lock */
X#define	CCR3_NMI		0x02	/* Enables NMI during SMM */
X#define	CCR3_LINBRST	0x04	/* Linear address burst cycles */
X#define	CCR3_SMMMODE	0x08	/* SMM Mode */
X#define	CCR3_MAPEN0		0x10	/* Enables Map0 */
X#define	CCR3_MAPEN1		0x20	/* Enables Map1 */
X#define	CCR3_MAPEN2		0x40	/* Enables Map2 */
X#define	CCR3_MAPEN3		0x80	/* Enables Map3 */
X
X#define	CCR4			0xe8
X#define	CCR4_IOMASK		0x07
X#define	CCR4_MEM		0x08	/* Enables momory bypassing */
X#define	CCR4_DTE		0x10	/* Enables directory table entry cache */
X#define	CCR4_FASTFPE	0x20	/* Fast FPU exception */
X#define	CCR4_CPUID		0x80	/* Enables CPUID instruction */
X
X#define	CCR5			0xe9
X#define	CCR5_WT_ALLOC	0x01	/* Write-through allocate */
X#define	CCR5_SLOP		0x02	/* LOOP instruction slowed down */
X#define	CCR5_LBR1		0x10	/* Local bus region 1 */
X#define	CCR5_ARREN		0x20	/* Enables ARR region */
X
X#define	CCR6			0xea
X
X#define	CCR7			0xeb
X
X/* Performance Control Register (5x86 only). */
X#define	PCR0			0x20
X#define	PCR0_RSTK		0x01	/* Enables return stack */
X#define	PCR0_BTB		0x02	/* Enables branch target buffer */
X#define	PCR0_LOOP		0x04	/* Enables loop */
X#define	PCR0_AIS		0x08	/* Enables all instrcutions stalled to
X								   serialize pipe. */
X#define	PCR0_MLR		0x10	/* Enables reordering of misaligned loads */
X#define	PCR0_BTBRT		0x40	/* Enables BTB test register. */
X#define	PCR0_LSSER		0x80	/* Disable reorder */
X
X/* Device Identification Registers */
X#define	DIR0			0xfe
X#define	DIR1			0xff
X
X/*
X * The following four 3-byte registers control the non-cacheable regions.
X * These registers must be written as three separate bytes.
X *
X * NCRx+0: A31-A24 of starting address
X * NCRx+1: A23-A16 of starting address
X * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx.
X *
X * The non-cacheable region's starting address must be aligned to the
X * size indicated by the NCR_SIZE_xx field.
X */
X#define	NCR1	0xc4
X#define	NCR2	0xc7
X#define	NCR3	0xca
X#define	NCR4	0xcd
X
X#define	NCR_SIZE_0K	0
X#define	NCR_SIZE_4K	1
X#define	NCR_SIZE_8K	2
X#define	NCR_SIZE_16K	3
X#define	NCR_SIZE_32K	4
X#define	NCR_SIZE_64K	5
X#define	NCR_SIZE_128K	6
X#define	NCR_SIZE_256K	7
X#define	NCR_SIZE_512K	8
X#define	NCR_SIZE_1M	9
X#define	NCR_SIZE_2M	10
X#define	NCR_SIZE_4M	11
X#define	NCR_SIZE_8M	12
X#define	NCR_SIZE_16M	13
X#define	NCR_SIZE_32M	14
X#define	NCR_SIZE_4G	15
X
X/*
X * The address region registers are used to specify the location and
X * size for the eight address regions.
X *
X * ARRx + 0: A31-A24 of start address
X * ARRx + 1: A23-A16 of start address
X * ARRx + 2: A15-A12 of start address | ARR_SIZE_xx
X */
X#define	ARR0	0xc4
X#define	ARR1	0xc7
X#define	ARR2	0xca
X#define	ARR3	0xcd
X#define	ARR4	0xd0
X#define	ARR5	0xd3
X#define	ARR6	0xd6
X#define	ARR7	0xd9
X
X#define	ARR_SIZE_0K		0
X#define	ARR_SIZE_4K		1
X#define	ARR_SIZE_8K		2
X#define	ARR_SIZE_16K	3
X#define	ARR_SIZE_32K	4
X#define	ARR_SIZE_64K	5
X#define	ARR_SIZE_128K	6
X#define	ARR_SIZE_256K	7
X#define	ARR_SIZE_512K	8
X#define	ARR_SIZE_1M		9
X#define	ARR_SIZE_2M		10
X#define	ARR_SIZE_4M		11
X#define	ARR_SIZE_8M		12
X#define	ARR_SIZE_16M	13
X#define	ARR_SIZE_32M	14
X#define	ARR_SIZE_4G		15
X
X/*
X * The region control registers specify the attributes associated with
X * the ARRx addres regions.
X */
X#define	RCR0	0xdc
X#define	RCR1	0xdd
X#define	RCR2	0xde
X#define	RCR3	0xdf
X#define	RCR4	0xe0
X#define	RCR5	0xe1
X#define	RCR6	0xe2
X#define	RCR7	0xe3
X
X#define RCR_RCD	0x01	/* Disables caching for ARRx (x = 0-6). */
X#define RCR_RCE	0x01	/* Enables caching for ARR7. */
X#define RCR_WWO	0x02	/* Weak write ordering. */
X#define	RCR_WL	0x04	/* Weak locking. */
X#define RCR_WG	0x08	/* Write gathering. */
X#define	RCR_WT	0x10	/* Write-through. */
X#define	RCR_NLB	0x20	/* LBA# pin is not asserted. */
X
X/* AMD Write Allocate Top-Of-Memory and Control Register */
X#define	AMD_WT_ALLOC_TME	0x40000	/* top-of-memory enable */
X#define	AMD_WT_ALLOC_PRE	0x20000	/* programmable range enable */
X#define	AMD_WT_ALLOC_FRE	0x10000	/* fixed (A0000-FFFFF) range enable */
X
X
X#ifndef LOCORE
Xstatic __inline u_char
Xread_cyrix_reg(u_char reg)
X{
X	outb(0x22, reg);
X	return inb(0x23);
X}
X
Xstatic __inline void
Xwrite_cyrix_reg(u_char reg, u_char data)
X{
X	outb(0x22, reg);
X	outb(0x23, data);
X}
X#endif
X
X#endif /* !_MACHINE_SPECIALREG_H_ */
END-of-sys/drivers/mtrr/specialreg.h
echo x - sys/drivers/mtrr/support.S
sed 's/^X//' >sys/drivers/mtrr/support.S << 'END-of-sys/drivers/mtrr/support.S'
X/* support.S - from the FreeBSD file with the same name
X *             but stripped down to cpuid and CRx functions
X */
X
X/*-
X * Copyright (c) 1993 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $FreeBSD: src/sys/i386/i386/support.s,v 1.60.2.1 1999/08/29 16:05:52 peter Exp $
X */
X
X
X/*
X * CNAME and HIDENAME manage the relationship between symbol names in C
X * and the equivalent assembly language names.  CNAME is given a name as
X * it would be used in a C program.  It expands to the equivalent assembly
X * language name.  HIDENAME is given an assembly-language name, and expands
X * to a possibly-modified form that will be invisible to C programs.
X */
X#define CNAME(csym)		csym
X#define HIDENAME(asmsym)	__CONCAT(.,asmsym)
X
X#define ALIGN_DATA	.p2align 2	/* 4 byte alignment, zero filled */
X#define ALIGN_TEXT	.p2align 2,0x90	/* 4-byte alignment, nop filled */
X#define SUPERALIGN_TEXT	.p2align 4,0x90	/* 16-byte alignment, nop filled */
X
X#define ENTRY(name)		ALIGN_TEXT; .globl CNAME(name); \
X				CNAME(name):
X
X
X#include <cputypes.h>
X
X	.data
X	.globl	cpu,cpu_vendor,cpu_id,
X	.globl	cpu_high, cpu_feature
Xcpu:		.long	0			/* are we 386, 386sx, or 486 */
Xcpu_id:		.long	0			/* stepping ID */
Xcpu_high:	.long	0			/* highest arg to CPUID */ 
Xcpu_feature:	.long	0			/* features */
Xcpu_vendor:	.space	20			/* CPU origin code */
X
X	.text
X
X/* load_cr0(cr0) */
XENTRY(load_cr0)
X	movl	4(%esp),%eax
X	movl	%eax,%cr0
X	ret
X
X/* rcr0() */
XENTRY(rcr0)
X	movl	%cr0,%eax
X	ret
X
X/* rcr4() */
XENTRY(rcr4)
X	movl	%cr4,%eax
X	ret
X
X/* void load_cr4(caddr_t cr4) */
XENTRY(load_cr4)
X	movl	4(%esp),%eax
X	movl	%eax,%cr4
X	ret
X
X#define R(foo) ((foo))
X
XENTRY(cpuid)
X	push	%ebp
X	mov	%esp,%ebp
X	push	%ebx
X	push	%ecx
X	push	%edx
X        xorl    %eax,%eax
X        .byte   0x0f,0xa2                       /* cpuid 0 */
X	movl	%eax,R(cpu_high)		/* highest capability */
X	movl	%ebx,R(cpu_vendor)		/* store vendor string */
X	movl	%edx,R(cpu_vendor+4)
X	movl	%ecx,R(cpu_vendor+8)
X	movb	$0,R(cpu_vendor+12) 
X        
X	movl	$1,%eax
X	.byte	0x0f,0xa2			/* cpuid 1 */
X	movl	%eax,R(cpu_id) 		/* store cpu_id */
X	movl	%edx,R(cpu_feature)		/* store cpu_feature */
X	rorl	$8,%eax 			/* extract family type */
X	andl	$15,%eax
X	cmpl	$5,%eax 
X	jae	.L1
X        
X        /* less than Pentium; must be 486 */
X        movl    $CPU_486,R(cpu)
X        jmp     .L3
X
X.L1:
X        /* a Pentium? */
X        cmpl    $5,%eax
X        jne     .L2
X        movl    $CPU_586,R(cpu)
X        jmp     .L3
X.L2:
X        /* Greater than Pentium...call it a Pentium Pro */
X        movl    $CPU_686,R(cpu)
X.L3:
X	pop	%edx
X	pop	%ecx
X	pop	%ebx
X	leave
X	ret
X	nop
X
END-of-sys/drivers/mtrr/support.S
exit

