C4's Cyrix 486 patches for Linux-  Version 0.25
-----------------------------------------------

Arggh-File (or what to do if the patch doesn't install/compile/work)
--------------------------------------------------------------------

Failure modes:

1- patch doesn't install correctly

Version 0.1 and 0.15 of the patch assumes the config.in file is in pre-pl11
format. Version 0.2 and higher will support the pl11+ config.in format.

Read the kernel config docs and manually install the patches in pl11+
config.in format.

If this isn't the problem, try installing the patches by hand.  If you have
a Cyrix processor and don't plan to compile your kernel sources or run your
kernel on other non-Cyrix machines, you can forget about config.in, and
install the patches in 'setup.S.diff' manually.

2- make complains about setup.o bigger than XXX sectors

Try using setup.S.diff.alt instead.  If that doesn't do the trick, go
through the patched setup.S and #if 0..#endif out some of the SVGA support
(prime candidates include Oak VGA, Everex EEGA, Chip&Tech VGA, Genoa, etc
since these are older type boards that people aren't likely to have) just
don't comment out the board that you have :-) .

DO NOT alter DEF_SETUPSECT to allow more sectors.  This will NOT work.

3- Everything compiles but I don't get any speed increase.

First question- Do you have a *Cyrix* 486DLC, DRu2 or DRx2 processor (TI made
some of the 486DLC parts for Cyrix, so some may be labelled TI instead) and
not an IBM or other DLC part?  These patches have only been tested on Cyrix
parts and may not work on other parts.

If you do have a Cyrix part, try the following:

1- Boot MS-DOS from a clean floppy- do *NOT* run the Cyrix cache software.
2- Run CX_486.EXE without any arguments.
3- Does the status screen indicate the the CD bit is 0 (ie cache enabled)?
   Yes- try procedure A below        No- try procedure B below


Procedure A:
------------
If the CD bit is zero, it indicates that the cache can be used, and everything
SHOULD have worked..   To use this procedure, you need to have "modules" **
installed in your kernel.  If you don't, install it first.  If you do, 
snip the following code fragment:

---------8<---snip---8<----------
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/interrupt.h>
#include <linux/config.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>

#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/bitops.h>

#define CCR0 0xc0
#define CCR1 0xc1
#define NCR1 0xc4
#define NCR2 0xc7
#define NCR3 0xca
#define NCR4 0xcd

char kernel_version[]="1.0.7";

extern int init_module() {

        int address=0x22;	int data=0x23;

	printk("cyrix: reading register settings\n");
	outb_p(CCR0,address);	printk("CCR0=%x  ",inb_p(data));
	outb_p(CCR1,address);	printk("CCR1=%x  ",inb_p(data));
	outb_p(NCR1,address);	printk("NCR1=%x ",inb_p(data));
	outb_p(NCR1+1,address);	printk("%x ",inb_p(data));
	outb_p(NCR1+2,address);	printk("%x\n",inb_p(data));


	printk("cyrix: setting registers\n");
	outb_p(CCR0,address);	outb_p(0x12,data); /* 0x23 for DLC part */
	outb_p(CCR1,address);	outb_p(0x00,data);
	outb_p(NCR1,address);	outb_p(0x00,data);
	outb_p(NCR1+1,address);	outb_p(0x00,data);
	outb_p(NCR1+2,address);	outb_p(0x00,data);
	outb_p(NCR2,address);	outb_p(0x00,data);
	outb_p(NCR2+1,address);	outb_p(0x00,data);
	outb_p(NCR2+2,address);	outb_p(0x00,data);
	outb_p(NCR3,address);	outb_p(0x00,data);
	outb_p(NCR3+1,address);	outb_p(0x00,data);
	outb_p(NCR3+2,address);	outb_p(0x00,data);
	outb_p(NCR4,address);	outb_p(0x00,data);
	outb_p(NCR4+1,address);	outb_p(0x00,data);
	outb_p(NCR4+2,address);	outb_p(0x00,data);

	printk("cyrix: reading register settings\n");
	outb_p(CCR0,address);	printk("CCR0=%x  ",inb_p(data));
	outb_p(CCR1,address);	printk("CCR1=%x  ",inb_p(data));
	outb_p(NCR1,address);	printk("NCR1=%x ",inb_p(data));
	outb_p(NCR1+1,address);	printk("%x ",inb_p(data));
	outb_p(NCR1+2,address);	printk("%x\n",inb_p(data));

	return 0;
}

extern void cleanup_module() {}
---------8<---snip---8<----------

Compile it with cc -DKERNEL -D__KERNEL__ -DDYN_MODULE -c set486.c -fomit-frame-pointer -O6

Run the code with 'insmod set486.o;rmmod set486'

The diagnostics should show that CCR0 is 0x12 (or 0x22 for a DLC part),
CCR1 is 0x00 and NCR1 is 0x00.  If this is OK, go to procedure C.

** Note- there have been reports that the modules patch in the SLS pl13
distribution aren't installed correctly.  Make sure that your modules
work before trying the above.

Procedure B:
------------
Your BIOS is enabling the CD bit in the cr0 register.  We need to diable
this bit before the cache will work.  Find some place to put the following
bit of 386 assembly code (this should probably go in the kernel proper
as a bit of __asm__'ed assembly code)


        ; enable cache filling
	push	eax

        mov     eax,cr0
        and     eax,0x9fffffffh
        mov     cr0,eax

        pop     eax

Alternately, you can try applying the patch in head.S.diff.  This patch
is experimental, and may cause your machine to lock up.  Use at your
own risk.

Procedure C:
------------
To verify that the cache is working, we'll just run a fragment of the kernel
code- in this case, the bit that calculates the BogoMips (tm).  Again, you'll
need "modules" installed in your kernel to use this:

---------8<---snip---8<----------
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/interrupt.h>
#include <linux/config.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>

#include <asm/system.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/bitops.h>

char kernel_version[]="1.0.7";

unsigned long loops_per_sec=1;

extern __inline__ void __delay(int loops)
{
  __asm__("\n1:\tdecl %0\n\tjns 1b\n": :"a" (loops):"ax");
}

extern int init_module() {
  
  int ticks;
  
  printk("Calibrating delay loop.. ");
  while (loops_per_sec <<= 1) {
    ticks = jiffies;
    __delay(loops_per_sec);
    ticks = jiffies - ticks;
    if (ticks >= HZ) {
      __asm__("mull %1 ; divl %2"
	      :"=a" (loops_per_sec)
	      :"d" (HZ),
	      "r" (ticks),
	      "0" (loops_per_sec)
	      :"dx");
      printk("ok - %d.%02d BogoMips (tm)\n",
	     loops_per_sec/500000,
	     (loops_per_sec/5000) % 100);
      return 0;
    }
  }
  printk("failed\n");
}

extern void cleanup_module() {}
---------8<---snip---8<----------

Compile with cc -DKERNEL -D__KERNEL__ -DDYN_MODULE -c bogo.c -O6 -m486 -fdefer-pop -finline-functions -fomit-frame-pointer -fstrength-reduce -fthread-jumps -funroll-loops -fcse-follow-jumps -frerun-cse-after-loop -fexpensive-optimizations 

Run the benchmark with: insmod bogo.o;rmmod bogo

The number display should be about 1.5-2 times greater than when you had the
386 installed.

There have been reports that certain hardware setups cause the BogoMips 
calculation at bootup to be calculated incorrectly (BogoMips too low) for
some reason.  Running the above benchmark after the boot has been completed
shows that the patch was successful and that the cache was indeed activated.
One possible explanation of this is the use of different-speed SIMMs in the
system or incorrect wait state settings.  

If it still doesn't work after these tests, then it beats the hell out of me..
Perhaps it is working and you just don't know it..  Or perhaps your system
just isn't compatible with the Cyrix part, or maybe you got a bum chip..
Take it up with Cyrix.












