VGA for Sparc64

Added 8x16 font, low-level VGA register programming and mode switching
functions from LinuxBIOS.

Fixed incorrect VGA_BASE.



git-svn-id: svn://coreboot.org/openbios/openbios-devel@69 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
Stefan Reinauer
2006-07-18 21:48:00 +00:00
parent e492087dbe
commit 7c2a631397
9 changed files with 5526 additions and 3 deletions

View File

@@ -8,6 +8,7 @@
#include "openbios/config.h"
#include "openbios/kernel.h"
#include "openbios.h"
#include "video_subr.h"
#ifdef CONFIG_DEBUG_CONSOLE
@@ -122,7 +123,8 @@ static void serial_cls(void)
#define ATTRIBUTE 7 /* The attribute of an character. */
#define APB_MEM_BASE 0x1ff00000000ULL
#define VGA_BASE (APB_MEM_BASE + 0x4b8000ULL) /* The video memory address. */
#define VGA_BASE (APB_MEM_BASE + 0x4a0000ULL) /* Beginning of video memory address. */
#define TEXT_BASE (VGA_BASE + 0x18000ULL) /* The text memory address. */
/* VGA Index and Data Registers */
#define VGA_REG_INDEX 0x03D4 /* VGA index register */
@@ -137,7 +139,7 @@ static void serial_cls(void)
/* Save the X and Y position. */
static int xpos, ypos;
/* Point to the video memory. */
static volatile unsigned char *video = (unsigned char *) VGA_BASE;
static unsigned char *video = (unsigned char *) TEXT_BASE;
static void video_initcursor(void)
{
@@ -236,9 +238,19 @@ static void video_cls(void)
video_poscursor(xpos, ypos);
}
#ifdef CONFIG_DRIVER_VGA
#include "../../modules/font_8x16.c"
#endif
void video_init(void)
{
video=(unsigned char *)VGA_BASE;
video=(unsigned char *)TEXT_BASE;
#ifdef CONFIG_DRIVER_VGA
vga_load_regs();
vga_font_load((unsigned char *)VGA_BASE, fontdata_8x16, 16, 256);
vga_set_amode();
#endif
}
/*

View File

@@ -71,6 +71,7 @@
<option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="4"/>
<option name="CONFIG_DEBUG_IDE" type="boolean" value="true"/>
<option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="true"/>
<option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/>
</config>

View File

@@ -71,6 +71,7 @@
<option name="CONFIG_IDE_NUM_CHANNELS" type="integer" value="4"/>
<option name="CONFIG_DEBUG_IDE" type="boolean" value="true"/>
<option name="CONFIG_DRIVER_FLOPPY" type="boolean" value="true"/>
<option name="CONFIG_DRIVER_VGA" type="boolean" value="true"/>
</config>

View File

@@ -12,6 +12,8 @@
<object source="sbus.c" condition="DRIVER_SBUS"/>
<object source="esp.c" condition="DRIVER_ESP"/>
<object source="obio.c" condition="DRIVER_OBIO"/>
<object source="vga_load_regs.c" condition="DRIVER_VGA"/>
<object source="vga_set_mode.c" condition="DRIVER_VGA"/>
</library>
<dictionary name="openbios" target="forth">

228
drivers/vga.h Normal file
View File

@@ -0,0 +1,228 @@
/*
*
* modified
* by Steve M. Gehlbach <steve@kesa.com>
*
* Originally from linux/drivers/video/vga16.c by
* Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
* Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
* Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
* Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
*
*/
#ifndef VGA_H_INCL
#define VGA_H_INCL 1
//#include <cpu/p5/io.h>
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int
#define __u32 u32
#define VERROR -1
#define CHAR_HEIGHT 16
#define LINES 25
#define COLS 80
// macros for writing to vga regs
#define write_crtc(data,addr) outb(addr,CRT_IC); outb(data,CRT_DC)
#define write_att(data,addr) inb(IS1_RC); inb(0x80); outb(addr,ATT_IW); inb(0x80); outb(data,ATT_IW); inb(0x80)
#define write_seq(data,addr) outb(addr,SEQ_I); outb(data,SEQ_D)
#define write_gra(data,addr) outb(addr,GRA_I); outb(data,GRA_D)
u8 read_seq_b(u16 addr);
u8 read_gra_b(u16 addr);
u8 read_crtc_b(u16 addr);
u8 read_att_b(u16 addr);
#ifdef VGA_HARDWARE_FIXUP
void vga_hardware_fixup(void);
#else
#define vga_hardware_fixup() do{} while(0)
#endif
#define SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
#define SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
#define SYNC_EXT 4 /* external sync */
#define SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
#define SYNC_BROADCAST 16 /* broadcast video timings */
/* vtotal = 144d/288n/576i => PAL */
/* vtotal = 121d/242n/484i => NTSC */
#define SYNC_ON_GREEN 32 /* sync on green */
#define VMODE_NONINTERLACED 0 /* non interlaced */
#define VMODE_INTERLACED 1 /* interlaced */
#define VMODE_DOUBLE 2 /* double scan */
#define VMODE_MASK 255
#define VMODE_YWRAP 256 /* ywrap instead of panning */
#define VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
#define VMODE_CONUPDATE 512 /* don't update x/yoffset */
/* VGA data register ports */
#define CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */
#define CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */
#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */
#define GRA_D 0x3CF /* Graphics Controller Data Register */
#define SEQ_D 0x3C5 /* Sequencer Data Register */
#define MIS_R 0x3CC // Misc Output Read Register
#define MIS_W 0x3C2 // Misc Output Write Register
#define IS1_RC 0x3DA /* Input Status Register 1 - color emulation */
#define IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */
#define PEL_D 0x3C9 /* PEL Data Register */
#define PEL_MSK 0x3C6 /* PEL mask register */
/* EGA-specific registers */
#define GRA_E0 0x3CC /* Graphics enable processor 0 */
#define GRA_E1 0x3CA /* Graphics enable processor 1 */
/* VGA index register ports */
#define CRT_IC 0x3D4 /* CRT Controller Index - color emulation */
#define CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */
#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */
#define GRA_I 0x3CE /* Graphics Controller Index */
#define SEQ_I 0x3C4 /* Sequencer Index */
#define PEL_IW 0x3C8 /* PEL Write Index */
#define PEL_IR 0x3C7 /* PEL Read Index */
/* standard VGA indexes max counts */
#define CRTC_C 25 /* 25 CRT Controller Registers sequentially set*/
// the remainder are not in the par array
#define ATT_C 21 /* 21 Attribute Controller Registers */
#define GRA_C 9 /* 9 Graphics Controller Registers */
#define SEQ_C 5 /* 5 Sequencer Registers */
#define MIS_C 1 /* 1 Misc Output Register */
#define CRTC_H_TOTAL 0
#define CRTC_H_DISP 1
#define CRTC_H_BLANK_START 2
#define CRTC_H_BLANK_END 3
#define CRTC_H_SYNC_START 4
#define CRTC_H_SYNC_END 5
#define CRTC_V_TOTAL 6
#define CRTC_OVERFLOW 7
#define CRTC_PRESET_ROW 8
#define CRTC_MAX_SCAN 9
#define CRTC_CURSOR_START 0x0A
#define CRTC_CURSOR_END 0x0B
#define CRTC_START_HI 0x0C
#define CRTC_START_LO 0x0D
#define CRTC_CURSOR_HI 0x0E
#define CRTC_CURSOR_LO 0x0F
#define CRTC_V_SYNC_START 0x10
#define CRTC_V_SYNC_END 0x11
#define CRTC_V_DISP_END 0x12
#define CRTC_OFFSET 0x13
#define CRTC_UNDERLINE 0x14
#define CRTC_V_BLANK_START 0x15
#define CRTC_V_BLANK_END 0x16
#define CRTC_MODE 0x17
#define CRTC_LINE_COMPARE 0x18
#define ATC_MODE 0x10
#define ATC_OVERSCAN 0x11
#define ATC_PLANE_ENABLE 0x12
#define ATC_PEL 0x13
#define ATC_COLOR_PAGE 0x14
#define SEQ_CLOCK_MODE 0x01
#define SEQ_PLANE_WRITE 0x02
#define SEQ_CHARACTER_MAP 0x03
#define SEQ_MEMORY_MODE 0x04
#define GDC_SR_VALUE 0x00
#define GDC_SR_ENABLE 0x01
#define GDC_COMPARE_VALUE 0x02
#define GDC_DATA_ROTATE 0x03
#define GDC_PLANE_READ 0x04
#define GDC_MODE 0x05
#define GDC_MISC 0x06
#define GDC_COMPARE_MASK 0x07
#define GDC_BIT_MASK 0x08
// text attributes
#define VGA_ATTR_CLR_RED 0x4
#define VGA_ATTR_CLR_GRN 0x2
#define VGA_ATTR_CLR_BLU 0x1
#define VGA_ATTR_CLR_YEL (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN)
#define VGA_ATTR_CLR_CYN (VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU)
#define VGA_ATTR_CLR_MAG (VGA_ATTR_CLR_BLU | VGA_ATTR_CLR_RED)
#define VGA_ATTR_CLR_BLK 0
#define VGA_ATTR_CLR_WHT (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU)
#define VGA_ATTR_BNK 0x80
#define VGA_ATTR_ITN 0x08
/*
* vga register parameters
* these are copied to the
* registers.
*
*/
struct vga_par {
u8 crtc[CRTC_C];
u8 atc[ATT_C];
u8 gdc[GRA_C];
u8 seq[SEQ_C];
u8 misc; // the misc register, MIS_W
u8 vss;
};
/* Interpretation of offset for color fields: All offsets are from the right,
* inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
* can use the offset as right argument to <<). A pixel afterwards is a bit
* stream and is written to video memory as that unmodified. This implies
* big-endian byte order if bits_per_pixel is greater than 8.
*/
struct fb_bitfield {
__u32 offset; /* beginning of bitfield */
__u32 length; /* length of bitfield */
__u32 msb_right; /* != 0 : Most significant bit is */
/* right */
};
struct screeninfo {
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what */
__u32 grayscale; /* != 0 Graylevels instead of colors */
struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */
__u32 nonstd; /* != 0 Non standard pixel format */
__u32 activate; /* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */
__u32 accel_flags; /* acceleration flags (hints) */
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* sync polarity */
__u32 vmode; /* interlaced etc */
__u32 reserved[6]; /* Reserved for future compatibility */
};
#endif

427
drivers/vga_load_regs.c Normal file
View File

@@ -0,0 +1,427 @@
#include "asm/io.h"
#include "video_subr.h"
#include "string.h"
#include "vga.h"
/*
* $Id$
* $Source$
*
* from the Linux kernel code base.
* orig by Ben Pfaff and Petr Vandrovec.
*
* modified by
* Steve M. Gehlbach <steve@kesa.com>
*
* NOTE: to change the horiz and vertical pixels,
* change the xres,yres,xres_virt,yres_virt setting
* in the screeninfo structure below. You may also need
* to change the border settings as well.
*
* Convert the screeninfo structure to data for
* writing to the vga registers
*
*/
// prototypes
static int vga_decode_var(const struct screeninfo *var, struct vga_par *par);
static int vga_set_regs(const struct vga_par *par);
extern const u8 VgaLookupTable[];
u8 read_seq_b(u16 addr) {
outb(addr,SEQ_I);
return inb(SEQ_D);
}
u8 read_gra_b(u16 addr) {
outb(addr,GRA_I);
return inb(GRA_D);
}
u8 read_crtc_b(u16 addr) {
outb(addr,CRT_IC);
return inb(CRT_DC);
}
u8 read_att_b(u16 addr) {
inb(IS1_RC);
inb(0x80);
outb(addr,ATT_IW);
return inb(ATT_R);
}
/*
From: The Frame Buffer Device
by Geert Uytterhoeven <geert@linux-m68k.org>
in the linux kernel docs.
The following picture summarizes all timings. The horizontal retrace time is
the sum of the left margin, the right margin and the hsync length, while the
vertical retrace time is the sum of the upper margin, the lower margin and the
vsync length.
+----------+---------------------------------------------+----------+-------+
| | ^ | | |
| | |upper_margin | | |
| | | | | |
+----------###############################################----------+-------+
| # ^ # | |
| # | # | |
| # | # | |
| # | # | |
| left # | # right | hsync |
| margin # | xres # margin | len |
|<-------->#<---------------+--------------------------->#<-------->|<----->|
| # | # | |
| # | # | |
| # | # | |
| # |yres # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
| # | # | |
+----------###############################################----------+-------+
| | ^ | | |
| | |lower_margin | | |
| | | | | |
+----------+---------------------------------------------+----------+-------+
| | ^ | | |
| | |vsync_len | | |
| | | | | |
+----------+---------------------------------------------+----------+-------+
All horizontal timings are in number of dotclocks
(in picoseconds, 1E-12 s), and vertical timings in number of scanlines.
The vga uses the following fields:
- pixclock: pixel clock in ps (pico seconds)
- xres,yres,xres_v,yres_v
- left_margin: time from sync to picture
- right_margin: time from picture to sync
- upper_margin: time from sync to picture
- lower_margin: time from picture to sync
- hsync_len: length of horizontal sync
- vsync_len: length of vertical sync
*/
/* our display parameters per the above */
static const struct screeninfo vga_settings = {
640,400,640,400,/* xres,yres,xres_virt,yres_virt */
0,0, /* xoffset,yoffset */
4, /* bits_per_pixel NOT USED*/
0, /* greyscale ? */
{0,0,0}, /* R */
{0,0,0}, /* G */
{0,0,0}, /* B */
{0,0,0}, /* transparency */
0, /* standard pixel format */
0, // activate now
-1,-1, // height and width in mm
0, // accel flags
39721, // pixclock: 79442 -> 12.587 Mhz (NOT USED)
// 70616 -> 14.161
// 39721 -> 25.175
// 35308 -> 28.322
48, 16, 39, 8, // margins left,right,upper,lower
96, // hsync length
2, // vsync length
0, // sync polarity
0, // non interlaced, single mode
{0,0,0,0,0,0} // compatibility
};
// ALPHA-MODE
// Hard coded to BIOS VGA mode 3 (alpha color text)
// screen size settable in screeninfo structure
static int vga_decode_var(const struct screeninfo *var,
struct vga_par *par)
{
u8 VgaAttributeTable[16] =
{ 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x014, 0x007, 0x038, 0x039, 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x03F};
u32 xres, right, hslen, left, xtotal;
u32 yres, lower, vslen, upper, ytotal;
u32 vxres, xoffset, vyres, yoffset;
u32 pos;
u8 r7, rMode;
int i;
xres = (var->xres + 7) & ~7;
vxres = (var->xres_virtual + 0xF) & ~0xF;
xoffset = (var->xoffset + 7) & ~7;
left = (var->left_margin + 7) & ~7;
right = (var->right_margin + 7) & ~7;
hslen = (var->hsync_len + 7) & ~7;
if (vxres < xres)
vxres = xres;
if (xres + xoffset > vxres)
xoffset = vxres - xres;
xres >>= 3;
right >>= 3;
hslen >>= 3;
left >>= 3;
vxres >>= 3;
xtotal = xres + right + hslen + left;
if (xtotal >= 256)
return VERROR; //xtotal too big
if (hslen > 32)
return VERROR; //hslen too big
if (right + hslen + left > 64)
return VERROR; //hblank too big
par->crtc[CRTC_H_TOTAL] = xtotal - 5;
par->crtc[CRTC_H_BLANK_START] = xres - 1;
par->crtc[CRTC_H_DISP] = xres - 1;
pos = xres + right;
par->crtc[CRTC_H_SYNC_START] = pos;
pos += hslen;
par->crtc[CRTC_H_SYNC_END] = (pos & 0x1F) | 0x20 ; //<--- stpc text mode p178
pos += left - 2; /* blank_end + 2 <= total + 5 */
par->crtc[CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
if (pos & 0x20)
par->crtc[CRTC_H_SYNC_END] |= 0x80;
yres = var->yres;
lower = var->lower_margin;
vslen = var->vsync_len;
upper = var->upper_margin;
vyres = var->yres_virtual;
yoffset = var->yoffset;
if (yres > vyres)
vyres = yres;
if (vxres * vyres > 65536) {
vyres = 65536 / vxres;
if (vyres < yres)
return VERROR; // out of memory
}
if (yoffset + yres > vyres)
yoffset = vyres - yres;
if (var->vmode & VMODE_DOUBLE) {
yres <<= 1;
lower <<= 1;
vslen <<= 1;
upper <<= 1;
}
ytotal = yres + lower + vslen + upper;
if (ytotal > 1024) {
ytotal >>= 1;
yres >>= 1;
lower >>= 1;
vslen >>= 1;
upper >>= 1;
rMode = 0x04;
} else
rMode = 0x00;
if (ytotal > 1024)
return VERROR; //ytotal too big
if (vslen > 16)
return VERROR; //vslen too big
par->crtc[CRTC_V_TOTAL] = ytotal - 2;
r7 = 0x10; /* disable linecompare */
if (ytotal & 0x100) r7 |= 0x01;
if (ytotal & 0x200) r7 |= 0x20;
par->crtc[CRTC_PRESET_ROW] = 0;
// GMODE <--> ALPHA-MODE
// default using alpha mode so we need to set char rows= CHAR_HEIGHT-1
par->crtc[CRTC_MAX_SCAN] = 0x40 | (CHAR_HEIGHT-1); /* 16 scanlines, linecmp max*/
if (var->vmode & VMODE_DOUBLE)
par->crtc[CRTC_MAX_SCAN] |= 0x80;
par->crtc[CRTC_CURSOR_START] = 0x00; // curs enabled, start line = 0
par->crtc[CRTC_CURSOR_END] = CHAR_HEIGHT-1; // end line = 12
pos = yoffset * vxres + (xoffset >> 3);
par->crtc[CRTC_START_HI] = pos >> 8;
par->crtc[CRTC_START_LO] = pos & 0xFF;
par->crtc[CRTC_CURSOR_HI] = 0x00;
par->crtc[CRTC_CURSOR_LO] = 0x00;
pos = yres - 1;
par->crtc[CRTC_V_DISP_END] = pos & 0xFF;
par->crtc[CRTC_V_BLANK_START] = pos & 0xFF;
if (pos & 0x100)
r7 |= 0x0A; /* 0x02 -> DISP_END, 0x08 -> BLANK_START */
if (pos & 0x200) {
r7 |= 0x40; /* 0x40 -> DISP_END */
par->crtc[CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
}
pos += lower;
par->crtc[CRTC_V_SYNC_START] = pos & 0xFF;
if (pos & 0x100)
r7 |= 0x04;
if (pos & 0x200)
r7 |= 0x80;
pos += vslen;
par->crtc[CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled reg write prot, IRQ */
pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */
par->crtc[CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
but some SVGA chips requires all 8 bits to set */
if (vxres >= 512)
return VERROR; //vxres too long
par->crtc[CRTC_OFFSET] = vxres >> 1;
// put the underline off of the character, necessary in alpha color mode
par->crtc[CRTC_UNDERLINE] = 0x1f;
par->crtc[CRTC_MODE] = rMode | 0xA3; // word mode
par->crtc[CRTC_LINE_COMPARE] = 0xFF;
par->crtc[CRTC_OVERFLOW] = r7;
// not used ??
par->vss = 0x00; /* 3DA */
for (i = 0x00; i < 0x10; i++) {
par->atc[i] = VgaAttributeTable[i];
}
// GMODE <--> ALPHA-MODE
par->atc[ATC_MODE] = 0x0c; // text mode
par->atc[ATC_OVERSCAN] = 0x00; // no border
par->atc[ATC_PLANE_ENABLE] = 0x0F;
par->atc[ATC_PEL] = xoffset & 7;
par->atc[ATC_COLOR_PAGE] = 0x00;
par->misc = 0x67; /* enable CPU, ports 0x3Dx, positive sync*/
if (var->sync & SYNC_HOR_HIGH_ACT)
par->misc &= ~0x40;
if (var->sync & SYNC_VERT_HIGH_ACT)
par->misc &= ~0x80;
par->seq[SEQ_CLOCK_MODE] = 0x01; //8-bit char; 0x01=alpha mode
par->seq[SEQ_PLANE_WRITE] = 0x03; // just char/attr plane
par->seq[SEQ_CHARACTER_MAP] = 0x00;
par->seq[SEQ_MEMORY_MODE] = 0x02; // A/G bit not used in stpc; O/E on, C4 off
par->gdc[GDC_SR_VALUE] = 0x00;
// bits set in the SR_EN regs will enable set/reset action
// based on the bit settings in the SR_VAL register
par->gdc[GDC_SR_ENABLE] = 0x00;
par->gdc[GDC_COMPARE_VALUE] = 0x00;
par->gdc[GDC_DATA_ROTATE] = 0x00;
par->gdc[GDC_PLANE_READ] = 0;
par->gdc[GDC_MODE] = 0x10; //Okay
// GMODE <--> ALPHA-MMODE
par->gdc[GDC_MISC] = 0x0e; // b0=0 ->alpha mode; memory at 0xb8000
par->gdc[GDC_COMPARE_MASK] = 0x00;
par->gdc[GDC_BIT_MASK] = 0xFF;
return 0;
}
/*
* From the Linux kernel.
* orig by Ben Pfaff and Petr Vandrovec.
* see the note in the vga.h for attribution.
*
* modified by
* Steve M. Gehlbach <steve@kesa.com>
* for the linuxbios project
*
* Write the data in the vga parameter structure
* to the vga registers, along with other default
* settings.
*
*/
static int vga_set_regs(const struct vga_par *par)
{
int i;
/* update misc output register */
outb(par->misc, MIS_W);
/* synchronous reset on */
outb(0x00, SEQ_I);
outb(0x00, SEQ_D);
/* write sequencer registers */
outb(1, SEQ_I);
outb(par->seq[1] | 0x20, SEQ_D); // blank display
for (i = 2; i < SEQ_C; i++) {
outb(i, SEQ_I);
outb(par->seq[i], SEQ_D);
}
/* synchronous reset off */
outb(0x00, SEQ_I);
outb(0x03, SEQ_D);
/* deprotect CRT registers 0-7 */
outb(0x11, CRT_IC);
outb(par->crtc[0x11], CRT_DC);
/* write CRT registers */
for (i = 0; i < CRTC_C; i++) {
outb(i, CRT_IC);
outb(par->crtc[i], CRT_DC);
}
/* write graphics controller registers */
for (i = 0; i < GRA_C; i++) {
outb(i, GRA_I);
outb(par->gdc[i], GRA_D);
}
/* write attribute controller registers */
for (i = 0; i < ATT_C; i++) {
inb(IS1_RC); /* reset flip-flop */
inb(0x80); //delay
outb(i, ATT_IW);
inb(0x80); //delay
outb(par->atc[i], ATT_IW);
inb(0x80); //delay
}
// initialize the color table
outb(0, PEL_IW);
i = 0;
// length is a magic number right now
while ( i < (0x3f*3 + 3) ) {
outb(VgaLookupTable[i++], PEL_D);
outb(VgaLookupTable[i++], PEL_D);
outb(VgaLookupTable[i++], PEL_D);
}
outb(0x0ff, PEL_MSK); // palette mask
// very important
// turn on video, disable palette access
inb(IS1_RC); /* reset flip-flop */
inb(0x80); //delay
outb(0x20, ATT_IW);
/* Wait for screen to stabilize. */
//for(i=0;i<1000;i++) { inb(0x80); }
outb(0x01, SEQ_I); // unblank display
outb(par->seq[1], SEQ_D);
// turn on display, disable access to attr palette
inb(IS1_RC);
outb(0x20, ATT_IW);
return 0;
}
void
vga_load_regs(void)
{
struct vga_par par;
vga_decode_var(&vga_settings, &par);
vga_set_regs(&par);
}

148
drivers/vga_set_mode.c Normal file
View File

@@ -0,0 +1,148 @@
/*
* $Id$
* $Source$
*
* by
* Steve M. Gehlbach <steve@kesa.com>
*
* These routines set graphics mode and alpha mode
* for switching back and forth.
*
* Register settings are
* more or less as follows:
*
* Register Graphics Alpha
* 16 color
* ------------------------------------------------
* GDC_MODE 0x00 0x10
* GDC_MISC 0x05 0x0e
* SEQ_MEMORY_MODE 0x06 0x02
* SEQ_PLANE_WRITE 0x0f 0x03
* CRTC_CURSOR_START 0x20 0x00
* CRTC_CURSOR_END 0x00 CHAR_HEIGHT-1
* CRTC_MODE 0xe3 0xa3
* CRTC_MAX_SCAN 0x40 0x40 | CHAR_HEIGHT-1
* ATC_MODE 0x01 0x0c
*
*/
#include "asm/io.h"
#include "vga.h"
void vga_set_gmode (void) {
u8 byte;
byte = read_att_b(ATC_MODE) & ~0x0f;
write_att(byte|0x1, ATC_MODE);
//
// display is off at this point
byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf;
write_seq(byte|0xf,SEQ_PLANE_WRITE); // all planes
byte = read_seq_b(SEQ_MEMORY_MODE);
write_seq(byte|4,SEQ_MEMORY_MODE);
byte = read_gra_b(GDC_MODE) & ~0x10;
write_gra(byte,GDC_MODE);
write_gra(0x05, GDC_MISC);
write_crtc(0x20, CRTC_CURSOR_START);
write_crtc(0x00, CRTC_CURSOR_END);
byte = read_crtc_b(CRTC_MODE) & ~0xe0;
write_crtc(byte|0xe0, CRTC_MODE);
byte = read_crtc_b(CRTC_MAX_SCAN) & ~0x01f;
write_crtc(byte, CRTC_MAX_SCAN);
byte = inb(MIS_R); // get 3c2 value by reading 3cc
outb(byte & ~0xc,MIS_W); // clear last bits to set 25Mhz clock and low page
// turn on display, disable access to attr palette
inb(IS1_RC);
outb(0x20, ATT_IW);
}
void vga_set_amode (void) {
u8 byte;
write_att(0x0c, ATC_MODE);
//reset palette to normal in the case it was changed
write_att(0x0, ATC_COLOR_PAGE);
//
// display is off at this point
write_seq(0x3,SEQ_PLANE_WRITE); // planes 0 & 1
byte = read_seq_b(SEQ_MEMORY_MODE) & ~0x04;
write_seq(byte,SEQ_MEMORY_MODE);
byte = read_gra_b(GDC_MODE) & ~0x60;
write_gra(byte|0x10,GDC_MODE);
write_gra(0x0e, GDC_MISC);
write_crtc(0x00, CRTC_CURSOR_START);
write_crtc(CHAR_HEIGHT-1, CRTC_CURSOR_END);
byte = read_crtc_b(CRTC_MODE) & ~0xe0;
write_crtc(byte|0xa0, CRTC_MODE);
byte = read_crtc_b(CRTC_MAX_SCAN) & ~0x01f;
write_crtc(byte | (CHAR_HEIGHT-1), CRTC_MAX_SCAN);
// turn on display, disable access to attr palette
inb(IS1_RC);
outb(0x20, ATT_IW);
}
/*
* by Steve M. Gehlbach, Ph.D. <steve@kesa.com>
*
* vga_font_load loads a font into font memory. It
* assumes alpha mode has been set.
*
* The font load code follows technique used
* in the tiara project, which came from
* the Universal Talkware Boot Loader,
* http://www.talkware.net.
*/
void vga_font_load(unsigned char *vidmem, const unsigned char *font, int height, int num_chars) {
/* Note: the font table is 'height' long but the font storage area
* is 32 bytes long.
*/
int i,j;
u8 byte;
// set sequencer map 2, odd/even off
byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf;
write_seq(byte|4,SEQ_PLANE_WRITE);
byte = read_seq_b(SEQ_MEMORY_MODE);
write_seq(byte|4,SEQ_MEMORY_MODE);
// select graphics map 2, odd/even off, map starts at 0xa0000
write_gra(2,GDC_PLANE_READ);
byte = read_gra_b(GDC_MODE) & ~0x10;
write_gra(byte,GDC_MODE);
write_gra(0,GDC_MISC);
for (i = 0 ; i < num_chars ; i++) {
for (j = 0 ; j < height ; j++) {
vidmem[i*32+j] = font[i*16+j];
}
}
// set sequencer back to maps 0,1, odd/even on
byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf;
write_seq(byte|3,SEQ_PLANE_WRITE);
byte = read_seq_b(SEQ_MEMORY_MODE) & ~0x4;
write_seq(byte,SEQ_MEMORY_MODE);
// select graphics back to map 0,1, odd/even on
write_gra(0,GDC_PLANE_READ);
byte = read_gra_b(GDC_MODE);
write_gra(byte|0x10,GDC_MODE);
write_gra(0xe,GDC_MISC);
}

11
include/video_subr.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef VIDEO_SUBR_H
#define VIDEO_SUBR_H
void video_tx_byte(unsigned char byte);
void vga_load_regs(void);
void vga_set_amode (void);
void vga_set_gmode (void);
void vga_font_load(unsigned char *vidmem, const unsigned char *font, int height, int num_chars);
extern const unsigned char fontdata_8x16[];
#endif /* VIDEO_SUBR_H */

4693
modules/font_8x16.c Normal file

File diff suppressed because it is too large Load Diff