#include <sys/types.h>
#include <pexpert/protos.h>
#include <pexpert/pexpert.h>
#include "video_console.h"
typedef short csrpos_t;
#define ONE_SPACE 2
#define ONE_LINE (vga_cols * ONE_SPACE)
#define ONE_PAGE (vga_rows * ONE_LINE)
#define SPACE_CHAR 0x20
#define VGA_FB_START 0x0b8000
#define VGA_FB_SIZE 0x8000
#define VGA_IDX_REG 0x3d4
#define VGA_IO_REG 0x3d5
#define VGA_C_LOW 0x0f
#define VGA_C_HIGH 0x0e
#define VGA_ATTR_NORMAL 0x07
#define VGA_ATTR_REVERSE 0x70
#define XY_TO_CSRPOS(x, y) (((y) * vga_cols + (x)) * ONE_SPACE)
static short vga_idx_reg = 0;
static short vga_io_reg = 0;
static short vga_cols = 80;
static short vga_rows = 25;
static char vga_attr = 0;
static char vga_attr_rev = 0;
static char * vram_start = 0;
extern void kd_slmwd(u_char * pos, int count, u_short val);
extern void kd_slmscu(u_char * from, u_char * to, int count);
extern void kd_slmscd(u_char * from, u_char * to, int count);
static void
move_up( csrpos_t from,
csrpos_t to,
int count)
{
kd_slmscu( vram_start + from, vram_start + to, count );
}
static void
move_down( csrpos_t from,
csrpos_t to,
int count )
{
kd_slmscd( vram_start + from, vram_start + to, count );
}
static void
clear_block( csrpos_t start,
int size,
char attr)
{
kd_slmwd( vram_start + start, size,
((unsigned short) attr << 8) + SPACE_CHAR);
}
static void
set_cursor_position( csrpos_t newpos )
{
short curpos;
curpos = newpos / ONE_SPACE;
outb(vga_idx_reg, VGA_C_HIGH);
outb(vga_io_reg, (u_char)(curpos >> 8));
outb(vga_idx_reg, VGA_C_LOW);
outb(vga_io_reg, (u_char)(curpos & 0xff));
}
static void
display_char( csrpos_t pos,
char ch,
char attr )
{
*(vram_start + pos) = ch;
*(vram_start + pos + 1) = attr;
}
static void
vga_init(int cols, int rows, unsigned char * addr)
{
vram_start = addr;
vga_idx_reg = VGA_IDX_REG;
vga_io_reg = VGA_IO_REG;
vga_rows = rows;
vga_cols = cols;
vga_attr = VGA_ATTR_NORMAL;
vga_attr_rev = VGA_ATTR_REVERSE;
set_cursor_position(0);
}
void
tc_scrollup( int lines )
{
csrpos_t to;
csrpos_t from;
int size;
to = 0;
from = ONE_LINE * lines;
size = ( ONE_PAGE - ( ONE_LINE * lines ) ) / ONE_SPACE;
move_up(from, to, size);
to = ( ( vga_rows - lines) * ONE_LINE );
size = ( ONE_LINE * lines ) / ONE_SPACE;
clear_block(to, size, vga_attr);
}
void
tc_scrolldown( int lines )
{
csrpos_t to;
csrpos_t from;
int size;
to = ONE_PAGE - ONE_SPACE;
from = ONE_PAGE - ( ONE_LINE * lines ) - ONE_SPACE;
size = ( ONE_PAGE - ( ONE_LINE * lines ) ) / ONE_SPACE;
move_down(from, to, size);
to = 0;
size = ( ONE_LINE * lines ) / ONE_SPACE;
clear_block(to, size, vga_attr);
}
enum {
kVGAColorBlack = 0,
kVGAColorBlue,
kVGAColorGreen,
kVGAColorCyan,
kVGAColorRed,
kVGAColorMagenta,
kVGAColorBrown,
kVGAColorWhite,
kVGAColorGray,
kVGAColorLightBlue,
kVGAColorLightGreen,
kVGAColorLightCyan,
kVGAColorLightRed,
kVGAColorLightMagenta,
kVGAColorLightBrown,
kVGAColorBrightWhite
};
void
tc_update_color( int color, int fore )
{
unsigned char mask_on, mask_off;
switch ( color )
{
case 1: mask_on = kVGAColorRed; break;
case 3: mask_on = kVGAColorLightBrown; break;
case 4: mask_on = kVGAColorBlue; break;
case 6: mask_on = kVGAColorCyan; break;
default: mask_on = color; break;
}
if ( fore )
{
mask_off = 0x0f;
}
else
{
mask_off = 0xf0;
mask_on <<= 4;
}
vga_attr = (vga_attr & ~mask_off) | mask_on;
vga_attr_rev = ( ((vga_attr << 4) & 0xf0) |
((vga_attr >> 4) & 0x0f) );
}
void
tc_show_cursor( int x, int y )
{
set_cursor_position( XY_TO_CSRPOS(x, y) );
}
void
tc_hide_cursor( int x, int y )
{
return;
}
void
tc_clear_screen(int x, int y, int operation)
{
csrpos_t start;
int count;
switch ( operation )
{
case 0:
start = XY_TO_CSRPOS(x, y);
count = ONE_PAGE - start;
break;
case 1:
start = 0;
count = XY_TO_CSRPOS(x, y) + ONE_SPACE;
break;
default:
case 2:
start = 0;
count = ONE_PAGE;
break;
}
clear_block(start, count, vga_attr);
}
void
tc_putchar( unsigned char ch, int x, int y, int attrs )
{
char my_attr = vga_attr;
if ( attrs & 4 ) my_attr = vga_attr_rev;
display_char( XY_TO_CSRPOS(x, y), ch, vga_attr );
}
void
tc_initialize(struct vc_info * vinfo_p)
{
vinfo_p->v_rows = vinfo_p->v_height;
vinfo_p->v_columns = vinfo_p->v_width;
vga_init( vinfo_p->v_columns,
vinfo_p->v_rows,
(unsigned char *) vinfo_p->v_baseaddr);
}