
/* 
	Simple test program for Cirrus linear addressing/color expansion.
	vgagl can take advantage of it (linear addressing).
*/


#include <stdlib.h>
#include <vga.h>
#include <time.h>
#include "../libvga.h"


#define USE_LINEAR_ADDRESSING
#define USE_BY16_ADDRESSING


unsigned char *vbuf;


/* This function is Cirrus specific and has nothing to do with linear
 * addressing. */
void by8test() {
	int i;
	int startclock, diffclock;

	/* Enable extended write modes and BY8/16 addressing. */
	outb(0x3ce, 0x0b);

#ifdef USE_BY16_ADDRESSING
	outb(0x3cf, inb(0x3cf) | 0x16);
#else
	outb(0x3cf, inb(0x3cf) | 0x06);
#endif
	/* Set extended write mode 4. */
	outb(0x3ce, 0x05);
	outb(0x3cf, (inb(0x3cf) & 0xf8) | 4);

	/* Set pixel mask register (coincides with VGA plane mask register). */
	outw(0x3c4, 0xff02);

	startclock = clock();
	for (i = 0; i < 248; i++) {
		int j;
		outw(0x3ce, 0x01 + (i << 8));	/* Set foreground color. */
#ifdef USE_BY16_ADDRESSING
		outw(0x3ce, 0x11 + (i << 8));	/* Set high byte. */
		memset(vbuf, 0xff, 640 * 480 / 16);
#else
		memset(vbuf, 0xff, 640 * 480 / 8);
#endif
	}
	diffclock = clock() - startclock;
	printf("Color expansion framebuffer fill speed: %dK/s\n",
		640 * 480 * 248 / diffclock / 10);
}


void main() {
	int i;

	if (!(vga_getmodeinfo(G640x480x256)->flags & CAPABLE_LINEAR)) {
		printf("Linear addressing not supported for this chipset.\n");
		exit(1);
	}
	vga_setmode(G640x480x256);
	vga_setpage(0);
#ifdef USE_LINEAR_ADDRESSING	
	vga_setlinearaddressing();
#endif
	
	/* Should not mess with bank register after this. */

	vbuf = vga_getgraphmem();
	printf("vbuf mapped at %08x.\n", vbuf);

#ifdef USE_LINEAR_ADDRESSING
	memset(vbuf, 88, 640 * 480);
	sleep(1);
	
	memset(vbuf, 0, 640 * 480);
	for (i = 0; i < 100000; i++)
		*(vbuf + (rand() & 0xfffff)) = rand();
#endif

	if (vga_getcurrentchipset() == CIRRUS)
		/* Show the bandwidth of the extended write modes of the */
		/* Cirrus chip. */
		by8test();

	getchar();
	vga_setmode(TEXT);
}
