reactos/rosapps/sysutils/utils/pice/module/vga.c

573 lines
14 KiB
C

/*++
Copyright (c) 1998-2001 Klaus P. Gerlicher
Module Name:
vga.c
Abstract:
VGA HW dependent draw routines
Environment:
Kernel mode only
Author:
Klaus P. Gerlicher
Reactos Port by Eugene Ingerman
Revision History:
04-Aug-1998: created
15-Nov-2000: general cleanup of source files
Copyright notice:
This file may be distributed under the terms of the GNU Public License.
--*/
////////////////////////////////////////////////////
// INCLUDES
////
#include "remods.h"
#include "precomp.h"
//#include <asm/io.h>
//#include <linux/ctype.h>
////////////////////////////////////////////////////
// PROTOTYPES
////
extern void pice_save_current_registers(void);
extern void pice_restore_current_registers(void);
extern void pice_set_mode_3_80x50(void);
extern void pice_set_mode_3_80x25(void);
extern UCHAR cGraphTable[8*256];
// storage for original VGA font
UCHAR cGraphTable2[16*256];
////////////////////////////////////////////////////
// DEFINES
////
#define VGA_EXTENDED // define this for 80x50 console mode
#ifndef VGA_EXTENDED
#define SCREEN_BUFFER_SIZE (80*25*2)
#else
#define SCREEN_BUFFER_SIZE (80*50*2)
#endif
/* Port addresses of control regs */
#define MISCOUTPUT 0x3c2
#define FEATURECONTROL 0x3da
#define SEQUENCER 0x3c4
#define CRTC 0x03d4
#define GRAPHICS 0x3ce
#define ATTRIBS 0x03c0
#define PELADDRESSWRITE 0x3c8
#define PELDATAREG 0x3c9
/* Number of regs on the various controllers */
#define MAXSEQ 5
#define MAXCRTC 0x19
#define MAXGRAPH 0x9
#define MAXATTRIB 0x015
////////////////////////////////////////////////////
// GLOBALS
////
// used for HERCULES text and VGA text mode
WINDOW wWindowVga[4]=
#ifndef VGA_EXTENDED
{
{1,3,1,0,FALSE},
{5,4,1,0,FALSE},
{10,9,1,0,FALSE},
{20,4,1,0,FALSE}
};
#else // VGA_EXTENDED
{
{1,3,1,0,FALSE},
{5,4,1,0,FALSE},
{10,24,1,0,FALSE},
{35,14,1,0,FALSE}
};
#endif // VGA_EXTENDED
PUCHAR pScreenBufferVga;
PUCHAR pScreenBufferSaveVga = NULL;
PUCHAR pScreenBufferTempVga;
PUCHAR pScreenBufferHardwareVga;
PUCHAR pFontBufferVga = NULL;
UCHAR offset_a = 0;
UCHAR offset_c = 0,offset_d = 0;
UCHAR offset_e = 0,offset_f = 0;
struct _attr
{
union
{
struct
{
UCHAR fgcol : 4;
UCHAR bkcol : 3;
UCHAR blink : 1;
}bits;
UCHAR Asuchar;
}u;
}attr;
unsigned char oldgraphicsmode;
unsigned char oldgraphicsmisc;
unsigned char oldsqregmapmask;
unsigned char oldsqregmemory;
unsigned char oldgraphicssetresetenable;
unsigned char oldgraphicsreadmapsel;
unsigned char read_vga_reg(int port, int reg)
{
outportb(port,reg);
return(inportb(port+1));
}
void write_vga_reg(int port, unsigned char reg, unsigned char value)
{
outportb(port,reg);
outportb(port+1,value);
}
/* Registers within controllers */
#define VREND 0x11
#define GRREGSETRESET 0
#define GRREGENABLESETRESET 1
#define GRREGREADMAPSEL 4
#define SQREGMAPMASK 2
#define SQREGMEMORY 4
#define GRREGWRMODE 5
#define GRREGMISC 6
void map_font_memory(void)
{
oldgraphicssetresetenable = read_vga_reg(GRAPHICS, GRREGENABLESETRESET);
oldgraphicsmode = read_vga_reg(GRAPHICS, GRREGWRMODE);
oldgraphicsmisc = read_vga_reg(GRAPHICS, GRREGMISC);
oldgraphicsreadmapsel = read_vga_reg(GRAPHICS, GRREGREADMAPSEL);
oldsqregmapmask = read_vga_reg(SEQUENCER, SQREGMAPMASK);
oldsqregmemory = read_vga_reg(SEQUENCER, SQREGMEMORY);
/* Make sure set/reset enable is off */
write_vga_reg(GRAPHICS,GRREGENABLESETRESET,0);
/* Select read plane 2 */
write_vga_reg(GRAPHICS,GRREGREADMAPSEL,0x02);
/* Make sure write and read mode = 0 */
write_vga_reg(GRAPHICS,GRREGWRMODE,0x00);
/* Set mapping to 64K at a000:0 & turn off odd/even at the graphics reg */
write_vga_reg(GRAPHICS,GRREGMISC, 0x04);
/* Set sequencer plane to 2 */
write_vga_reg(SEQUENCER,SQREGMAPMASK, 0x04);
/* Turn off odd/even at the sequencer */
write_vga_reg(SEQUENCER,SQREGMEMORY, 0x07);
}
void unmap_font_memory(void)
{
write_vga_reg(GRAPHICS,GRREGENABLESETRESET,oldgraphicssetresetenable);
write_vga_reg(GRAPHICS,GRREGWRMODE,oldgraphicsmode);
write_vga_reg(GRAPHICS,GRREGREADMAPSEL,oldgraphicsreadmapsel);
write_vga_reg(GRAPHICS,GRREGMISC, oldgraphicsmisc);
write_vga_reg(SEQUENCER,SQREGMAPMASK, oldsqregmapmask);
write_vga_reg(SEQUENCER,SQREGMEMORY, oldsqregmemory);
}
/* Font and palette constants */
#define BYTESPERFONT 8
#define FONTENTRIES 256
#define FONTBUFFERSIZE 8192
void save_font(UCHAR* graph_table)
{
PUCHAR FontBase = pFontBufferVga;
int i,j;
map_font_memory();
for (i=0; i < FONTENTRIES; i++)
for (j=0; j < 16; j++)
graph_table[i*16+j] = FontBase[i*32+j];
unmap_font_memory();
}
void load_font(UCHAR* graph_table,int bEnter)
{
PUCHAR FontBase = pFontBufferVga;
int i,j;
map_font_memory();
if(bEnter)
{
#ifdef VGA_EXTENDED
for (i=0; i < FONTENTRIES; i++)
for (j=0; j < 8; j++)
FontBase[i*32+j] = graph_table[i*BYTESPERFONT+j];
#else // VGA_EXTENDED
for (i=0; i < FONTENTRIES; i++)
for (j=0; j < 16; j++)
FontBase[i*32+j] = graph_table[i*BYTESPERFONT+(j/2)] << (j&1);
#endif // VGA_EXTENDED
}
else
{
for (i=0; i < FONTENTRIES; i++)
for (j=0; j < 16; j++)
FontBase[i*32+j] = graph_table[i*16+j];
}
unmap_font_memory();
}
//*************************************************************************
// SetForegroundColorVga()
//
//*************************************************************************
void SetForegroundColorVga(ECOLORS col)
{
attr.u.bits.fgcol = col;
attr.u.bits.blink = 0;
}
//*************************************************************************
// SetBackgroundColorVga()
//
//*************************************************************************
void SetBackgroundColorVga(ECOLORS col)
{
attr.u.bits.bkcol = col;
attr.u.bits.blink = 0;
}
//*************************************************************************
// PrintGrafVga()
//
//*************************************************************************
void PrintGrafVga(ULONG x,ULONG y,UCHAR c)
{
((PUSHORT)pScreenBufferVga)[y*GLOBAL_SCREEN_WIDTH + x] = (USHORT)((attr.u.Asuchar<<8)|c);
}
//*************************************************************************
// ShowCursor()
//
// show hardware cursor
//*************************************************************************
void ShowCursorVga(void)
{
ENTER_FUNC();
bCursorEnabled=TRUE;
outb_p(0x0a,0x3d4);
outb_p(inb_p(0x3d5)&~0x20,0x3d5);
LEAVE_FUNC();
}
//*************************************************************************
// HideCursorVga()
//
// hide hardware cursor
//*************************************************************************
void HideCursorVga(void)
{
ENTER_FUNC();
bCursorEnabled=FALSE;
outb_p(0x0a,0x3d4);
outb_p(inb_p(0x3d5)|0x20,0x3d5);
LEAVE_FUNC();
}
//*************************************************************************
// CopyLineTo()
//
// copy a line from src to dest
//*************************************************************************
void CopyLineToVga(USHORT dest,USHORT src)
{
PUSHORT p = (PUSHORT)pScreenBufferVga;
ENTER_FUNC();
PICE_memcpy(&p[dest*GLOBAL_SCREEN_WIDTH],&p[src*GLOBAL_SCREEN_WIDTH],GLOBAL_SCREEN_WIDTH*sizeof(USHORT));
LEAVE_FUNC();
}
//*************************************************************************
// InvertLineVga()
//
// invert a line on the screen
//*************************************************************************
void InvertLineVga(ULONG line)
{
ULONG i;
PUSHORT p = (PUSHORT)pScreenBufferVga;
USHORT attr;
if(line < GLOBAL_SCREEN_HEIGHT)
{
attr = p[line*GLOBAL_SCREEN_WIDTH]>>8;
attr = ((attr & 0x07)<<4) | ((attr & 0xF0)>>4);
attr <<= 8;
for(i=0;i<GLOBAL_SCREEN_WIDTH;i++)
p[line*GLOBAL_SCREEN_WIDTH + i] = (p[line*GLOBAL_SCREEN_WIDTH + i] & 0x00FF) | attr;
}
}
//*************************************************************************
// HatchLineVga()
//
// hatches a line on the screen
//*************************************************************************
void HatchLineVga(ULONG line)
{
ULONG i;
PUSHORT p = (PUSHORT)pScreenBufferVga;
if(line < GLOBAL_SCREEN_HEIGHT)
{
for(i=0;i<GLOBAL_SCREEN_WIDTH;i++)
p[line*GLOBAL_SCREEN_WIDTH + i] = (p[line*GLOBAL_SCREEN_WIDTH + i] & 0xF0FF) | 0x0c00;
}
}
//*************************************************************************
// ClrLineVga()
//
// clear a line on the screen
//*************************************************************************
void ClrLineVga(ULONG line)
{
ULONG i;
PUSHORT p = (PUSHORT)pScreenBufferVga;
if(line < GLOBAL_SCREEN_HEIGHT)
{
for(i=0;i<GLOBAL_SCREEN_WIDTH;i++)
p[line*GLOBAL_SCREEN_WIDTH + i] = (USHORT)((attr.u.Asuchar<<8) | 0x20);
}
}
//*************************************************************************
// PrintLogoVga()
//
//*************************************************************************
void PrintLogoVga(BOOLEAN bShow)
{
NOT_IMPLEMENTED();
}
//*************************************************************************
// PrintCursorVga()
//
// emulate a blinking cursor block
//*************************************************************************
void PrintCursorVga(BOOLEAN bForce)
{
static ULONG count=0;
USHORT charoffset;
UCHAR data;
ULONG x=wWindow[OUTPUT_WINDOW].usCurX,y=wWindow[OUTPUT_WINDOW].y+wWindow[OUTPUT_WINDOW].usCurY;
if( count++>250 )
{
count=0;
charoffset = (y* GLOBAL_SCREEN_WIDTH + x);
outb_p(0x0e,0x3d4);
data=(UCHAR)((charoffset>>8)&0xFF);
outb_p(data,0x3d5);
outb_p(0x0f,0x3d4);
data=(UCHAR)(charoffset & 0xFF);
outb_p(data,0x3d5);
}
}
//*************************************************************************
// SaveGraphicsVga()
//
//*************************************************************************
void SaveGraphicsStateVga(void)
{
UCHAR data;
// save current regs
pice_save_current_registers();
// unprotect crtc regs 0-7
outb_p(0x11,0x3d4);
data = inb_p(0x3d5);
outb_p(data & 0x7F,0x3d5);
// save current font
save_font(cGraphTable2);
// restore original regs
#ifdef VGA_EXTENDED
pice_set_mode_3_80x50();
#else
pice_set_mode_3_80x25();
#endif
// load a font
load_font(cGraphTable,1);
// copy the screen content to temp area
PICE_memcpy(pScreenBufferTempVga,pScreenBufferHardwareVga,SCREEN_BUFFER_SIZE);
// copy the console to the screen
PICE_memcpy(pScreenBufferHardwareVga,pScreenBufferVga,SCREEN_BUFFER_SIZE);
// save original pointer
pScreenBufferSaveVga = pScreenBufferVga;
// pScreenBufferVga now points to screen
pScreenBufferVga = pScreenBufferHardwareVga;
}
//*************************************************************************
// RestoreGraphicsStateVga()
//
//*************************************************************************
void RestoreGraphicsStateVga(void)
{
UCHAR data;
// unprotect crtc regs 0-7
outb_p(0x11,0x3d4);
data = inb_p(0x3d5);
outb_p(data & 0x7F,0x3d5);
// restore original regs
pice_restore_current_registers();
// load a font
load_font(cGraphTable2,0);
pScreenBufferVga = pScreenBufferSaveVga;
// copy screen to the console
PICE_memcpy(pScreenBufferVga,pScreenBufferHardwareVga,SCREEN_BUFFER_SIZE);
// copy the temp area to the screen
PICE_memcpy(pScreenBufferHardwareVga,pScreenBufferTempVga,SCREEN_BUFFER_SIZE);
}
//*************************************************************************
// ConsoleInitVga()
//
// init terminal screen
//*************************************************************************
BOOLEAN ConsoleInitVga(void)
{
BOOLEAN bResult = FALSE;
PUSHORT p;
PHYSICAL_ADDRESS FrameBuffer;
PHYSICAL_ADDRESS FontBuffer;
ENTER_FUNC();
ohandlers.CopyLineTo = CopyLineToVga;
ohandlers.PrintGraf = PrintGrafVga;
ohandlers.ClrLine = ClrLineVga;
ohandlers.InvertLine = InvertLineVga;
ohandlers.HatchLine = HatchLineVga;
ohandlers.PrintLogo = PrintLogoVga;
ohandlers.PrintCursor = PrintCursorVga;
ohandlers.SaveGraphicsState = SaveGraphicsStateVga;
ohandlers.RestoreGraphicsState = RestoreGraphicsStateVga;
ohandlers.ShowCursor = ShowCursorVga;
ohandlers.HideCursor = HideCursorVga;
ohandlers.SetForegroundColor = SetForegroundColorVga;
ohandlers.SetBackgroundColor = SetBackgroundColorVga;
ihandlers.GetKeyPolled = KeyboardGetKeyPolled;
ihandlers.FlushKeyboardQueue = KeyboardFlushKeyboardQueue;
SetWindowGeometry(wWindowVga);
GLOBAL_SCREEN_WIDTH = 80;
#ifndef VGA_EXTENDED
GLOBAL_SCREEN_HEIGHT = 25;
#else // VGA_EXTENDED
GLOBAL_SCREEN_HEIGHT = 50;
#endif // VGA_EXTENDED
attr.u.Asuchar = 0x07;
// the real framebuffer
FrameBuffer.u.LowPart = 0xB8000;
pScreenBufferHardwareVga = MmMapIoSpace(FrameBuffer,SCREEN_BUFFER_SIZE,MmNonCached);
//The real font buffer
FontBuffer.u.LowPart = 0xA0000;
pFontBufferVga = MmMapIoSpace(FontBuffer,FONTBUFFERSIZE,MmNonCached);
// the console
pScreenBufferVga = PICE_malloc(SCREEN_BUFFER_SIZE,NONPAGEDPOOL);
// the save area
pScreenBufferTempVga = PICE_malloc(SCREEN_BUFFER_SIZE,NONPAGEDPOOL);
if(pScreenBufferVga)
{
DPRINT((0,"VGA memory phys. 0x000b0000 mapped to virt. 0x%x\n",pScreenBufferVga));
bResult = TRUE;
p = (PUSHORT)pScreenBufferVga;
PICE_memset(pScreenBufferVga,0x0,SCREEN_BUFFER_SIZE);
DPRINT((0,"VGA memory cleared!\n"));
EmptyRingBuffer();
DPRINT((0,"ConsoleInitVga() SUCCESS!\n"));
}
LEAVE_FUNC();
return bResult;
}
//*************************************************************************
// ConsoleShutdownVga()
//
// exit terminal screen
//*************************************************************************
void ConsoleShutdownVga(void)
{
ENTER_FUNC();
if(pScreenBufferVga)
{
PICE_free(pScreenBufferVga);
PICE_free(pScreenBufferTempVga);
MmUnmapIoSpace(pScreenBufferHardwareVga,SCREEN_BUFFER_SIZE);
MmUnmapIoSpace(pFontBufferVga,FONTBUFFERSIZE);
}
LEAVE_FUNC();
}