/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen 		   */
/*								   */
/* This library is free software; you can redistribute it and/or   */
/* modify it without any restrictions. This library is distributed */
/* in the hope that it will be useful, but without any warranty.   */

/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
/* partially copyrighted (C) 1993 by Hartmut Schirmer */

#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#include "vga.h"
#include "libvga.h"
#include "driver.h"

/* This routine is a pain in my ass and definitely needs to be virtualized..
   M. Weller. (mach32 support) */
void vga_waitretrace() {
	if ((__svgalib_chipset == MACH32)&&SVGAMODE(CM))
		{
		unsigned char csync;

		csync=inb(0xd2ee)>>3;	/* Current sync polarity in bit 2,
					   0-pos, 1-neg  */
		/*Wait until in displayed area..*/
		while((inb(0x2e8)^csync)&2);
		/*Wait until V_SYNC*/
		csync=~csync;
		while((inb(0x2e8)^csync)&2);
		/* Hmm, is a return missing here? -- HH */
		}
	while (!(inb(0x3da) & 8));
	while (inb(0x3da) & 8);
}

static void *linearframebuffer;

unsigned char *vga_getgraphmem() {
	if (vga_getmodeinfo(__svgalib_cur_mode)->flags & IS_LINEAR)
		return linearframebuffer;
	return __svgalib_graph_mem;
}

/* cf. vga_waitretrace, M.Weller */
void vga_setlinearaddressing() {
	int val;
	if (__svgalib_chipset != CIRRUS) {
		vga_modeinfo *mptr;

		mptr=vga_getmodeinfo(__svgalib_cur_mode);
		if( (mptr->flags&(CAPABLE_LINEAR|EXT_INFO_AVAILABLE)) ==
			 (CAPABLE_LINEAR|EXT_INFO_AVAILABLE) ) {
				if(mptr->aperture_size>=mptr->memory) {
					__svgalib_modeinfo_linearset|=IS_LINEAR;
					linearframebuffer=mptr->linear_aperture;
				}
		}
		return;
	}
	outb(0x3c4, 0x07);
	val = inb(0x3c5);
	outb(0x3c5, (val & 0x0f) | (14 << 4));		/* Map at 14Mb */
	linearframebuffer = mmap(
		(caddr_t) 0x40000000,
		0x200000,
		PROT_READ|PROT_WRITE,
		MAP_FIXED|MAP_SHARED,
		__svgalib_mem_fd,
		0x00e00000
		);
	/* Using addr 0 (kernel comes up with 0x40000000), and only MAP_SHARED
	   works, but wastes 2Mb of memory. */
}

int vga_getkey() {
	struct termio zap, original;
	char c;
	int e;

	ioctl(fileno(stdin), TCGETA, &original);	/* Get termio */
	zap = original;
	zap.c_cc[VMIN] = 0;				/* Modify termio  */
	zap.c_cc[VTIME] = 0;
	zap.c_lflag = 0;
	ioctl(fileno(stdin), TCSETA, &zap);		/* Set new termio */
	e = read(fileno(stdin), &c, 1);			/* Read one char */
	ioctl(fileno(stdin), TCSETA, &original);	/* Restore termio */
	if (e != 1)
		return 0;				/* No key pressed. */
	return c;					/* Return key. */
}

static void reserved_message() {
	printf("svgalib: Function not present in shared library image.\n");
	printf("         You need a newer version of svgalib.\n");
}

void vga_reserved14() {
	reserved_message();
}
void vga_reserved15() {
	reserved_message();
}
void vga_reserved16() {
	reserved_message();
}
void vga_reserved17() {
	reserved_message();
}
void vga_reserved18() {
	reserved_message();
}
void vga_reserved19() {
	reserved_message();
}
void vga_reserved20() {
	reserved_message();
}
