singrdk/base/Kernel/Singularity.Drivers/Vga.cs

885 lines
30 KiB
C#
Raw Permalink Normal View History

2008-03-05 09:52:00 -05:00
////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Vga.cs
//
// Notes:
//
// Useful reference URLs:
// http://www.xs4all.nl/~ganswijk/chipdir/reg/vga.txt "The VGA Registers"
// http://osdev.neopages.net/FreeVGA/vga/graphreg.htm
//
2008-11-17 18:29:00 -05:00
using System;
2008-03-05 09:52:00 -05:00
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Hal;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Configuration;
namespace Microsoft.Singularity.Drivers
{
// create the resource object for CTR to fill in
[DriverCategory]
[Signature("pci/cc_0300")]
internal class VgaResources : DriverCategoryDeclaration
{
[IoFixedPortRange(Base = 0x3c0, Length = 0x20, Shared = true)]
IoPortRange dev;
[IoFixedMemoryRange(Base = 0xa0000, Length = 0x20000, Shared = true)]
public IoMemoryRange screenMemory;
[IoFixedMemoryRange(Base = 0xb8000, Length = 0x8000, Shared = true)]
public IoMemoryRange textBuffer;
// Provide to unify creation.
public static IDevice! DeviceCreate(IoConfig! configobj, String! instanceName)
{
DebugStub.Print("Creating VGA Display\n");
return new Vga();
}
}
public class Vga : ISvgaDevice
{
public const ushort ATC_ADDR_PORT = 0x00; // 3c0: Attribute Controller Address and
public const ushort MISC_OUTPUT_REG_WRITE_PORT = 0x02; // 3c2: Miscellaneous Output reg write port
public const ushort SEQ_ADDR_PORT = 0x04; // 3c4: Sequence Controller Address and
public const ushort SEQ_DATA_PORT = 0x05; // 3c5: Data registers
public const ushort DAC_PIXEL_MASK_PORT = 0x06; // 3c6: DAC pixel mask reg
public const ushort DAC_ADDR_WRITE_PORT = 0x08; // 3c8: DAC register write index reg
public const ushort DAC_DATA_REG_PORT = 0x09; // 3c9: DAC data transfer reg
public const ushort GRAPH_ADDR_PORT = 0x0e; // 3ce: Graphics Controller Address
public const ushort GRAPH_DATA_PORT = 0x0f; // 3cf: Graphics Controller Data
public const ushort CRTC_ADDR_COLOR_PORT = 0x14; // 3d4: CRT Controller Address and
public const ushort INPUT_STATUS_COLOR_PORT = 0x1a; // 3da: Input Status 1 register read port in color mode
public const int SCREEN_HEIGHT = 480;
public const int SCREEN_WIDTH = 640;
public void BitBltPng(int x, int y, byte[] buffer)
{ /// dummy def
}
public Vga()
{
IoPortRange dev = new IoPortRange(0x3c0, 0x20, Access.ReadWrite);
atcAddrPort = dev.PortAtOffset(ATC_ADDR_PORT, 2, Access.ReadWrite);
miscOutputRegWritePort = dev.PortAtOffset(MISC_OUTPUT_REG_WRITE_PORT, 2, Access.ReadWrite);
seqAddrPort = dev.PortAtOffset(SEQ_ADDR_PORT, 2, Access.Write);
seqDataPort = dev.PortAtOffset(SEQ_DATA_PORT, 2, Access.ReadWrite);
dacPixelMaskPort = dev.PortAtOffset(DAC_PIXEL_MASK_PORT, 2, Access.Write);
dacAddressWritePort = dev.PortAtOffset(DAC_ADDR_WRITE_PORT, 2, Access.Write);
dacDataRegPort = dev.PortAtOffset(DAC_DATA_REG_PORT, 2, Access.Write);
graphAddrPort = dev.PortAtOffset(GRAPH_ADDR_PORT, 2, Access.Write);
graphDataPort = dev.PortAtOffset(GRAPH_DATA_PORT, 2, Access.ReadWrite);
crtcAddressColorPort = dev.PortAtOffset(CRTC_ADDR_COLOR_PORT, 2, Access.ReadWrite);
inputStatusColorPort = dev.PortAtOffset(INPUT_STATUS_COLOR_PORT, 2, Access.ReadWrite);
screenBuffer = IoMemory.AllocateIo(0xa0000, 0x20000, true, true);
textBuffer = IoMemory.AllocateIo(0xb8000, 0x8000, true, true);
}
2008-11-17 18:29:00 -05:00
private HalConsole lastScreen;
2008-03-05 09:52:00 -05:00
//
// VGA register definitions
//
private IoPort atcAddrPort; // Attribute Controller Address and
private IoPort miscOutputRegWritePort; // Miscellaneous Output reg write port
private IoPort seqAddrPort; // Sequence Controller Address and
private IoPort seqDataPort; // Data registers
private IoPort dacPixelMaskPort; // DAC pixel mask reg
private IoPort dacAddressWritePort; // DAC register write index reg
private IoPort dacDataRegPort; // DAC data transfer reg
private IoPort graphAddrPort; // Graphics Controller Address
private IoPort graphDataPort; // Graphics Controller Data
private IoPort crtcAddressColorPort; // CRT Controller Address and
private IoPort inputStatusColorPort; // Input Status 1 register read port in color mode
private IoMemory screenBuffer;
private IoMemory textBuffer;
//
// VGA indexed register indexes.
//
private const byte SEQ_RESET_REG = 0;
private const byte SEQ_CLOCK_REG = 1;
private const byte SEQ_PLANEMASK_REG = 2;
private const byte SEQ_CHARSET_REG = 3;
private const byte SEQ_MEMORY_REG = 4;
private const byte GRAPH_SET_REG = 0;
private const byte GRAPH_ENABLE_REG = 1;
private const byte GRAPH_COMPARE_REG = 2;
private const byte GRAPH_OPERATION_REG = 3;
private const byte GRAPH_READSEL_REG = 4;
private const byte GRAPH_MODE_REG = 5;
private const byte GRAPH_MISC_REG = 6;
private const byte GRAPH_DONTCARE_REG = 7;
private const byte GRAPH_BITMASK_REG = 8;
private const byte WRITE_MODE_0 = 0;
private const byte WRITE_MODE_1 = 1;
private const byte WRITE_MODE_2 = 2;
private const byte WRITE_MODE_3 = 3;
private const byte READ_MODE_0 = 0;
private const byte READ_MODE_1 = 8;
//
// Values for Attribute Controller Index register to turn video off
// and on, by setting bit 5 to 0 (off) or 1 (on).
//
private const byte VIDEO_ENABLE = 0x20;
private const uint BI_RLE4 = 2;
//
// globals to track screen position
//
private const int DELTA = 80;
static private byte[] lMaskTable = new byte[8] {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
static private byte[] rMaskTable = new byte[8] {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
static private byte[] PixelMask = new byte[8] {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
private void ReadWriteMode(byte mode)
{
graphAddrPort.Write8(GRAPH_MODE_REG);
graphDataPort.Write8(mode);
}
private void Plot(int x, int y, byte color)
{
int offset = y * DELTA + (x / 8);
ReadWriteMode(READ_MODE_1 | WRITE_MODE_2);
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(PixelMask[x % 8]);
// The read triggers the latch register.
screenBuffer.Read8(offset);
screenBuffer.Write8(offset, color);
}
private void Fill(int x1, int y1, int x2, int y2, byte color)
{
if (x1 < 0 || x1 >= SCREEN_WIDTH ||
x2 < 0 || x2 >= SCREEN_WIDTH ||
y1 < 0 || y1 >= SCREEN_HEIGHT ||
y2 < 0 || y2 >= SCREEN_HEIGHT) {
throw new OverflowException("Draw bounds invalid.");
}
byte lMask = lMaskTable[x1 % 8];
byte rMask = rMaskTable[x2 % 8];
int bank1 = x1 / 8;
int bank2 = x2 / 8;
int count = bank2 - bank1;
if (count == 0) {
lMask &= rMask;
}
ReadWriteMode(READ_MODE_1 | WRITE_MODE_2);
//
// Do the left edge
//
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(lMask);
int pDst = y1 * DELTA + bank1;
for (int y = y1; y <= y2; y++) {
// The read triggers the latch register.
screenBuffer.Read8(pDst);
screenBuffer.Write8(pDst, color);
pDst += DELTA;
}
if (count != 0) {
//
// Do the right edge
//
pDst = y1 * DELTA + bank2;
count--;
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(rMask);
for (int y = y1; y <= y2; y++) {
// The read triggers the latch register.
screenBuffer.Read8(pDst);
screenBuffer.Write8(pDst, color);
pDst += DELTA;
}
//
// Do the center section
//
if (count != 0) {
pDst = y1 * DELTA + bank1 + 1;
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(0xff);
for (int y = y1; y <= y2; y++) {
screenBuffer.Write8(pDst, (byte)color, count);
pDst += DELTA;
}
}
}
}
private void BitBlt4(int x, int y, int width, int height,
byte[] buffer, int offset, int ScanWidth)
{
byte[] Plane = new byte [81];
bool bRightEdge = false;
bool bCenterSection = false;
byte lMask = lMaskTable[x % 8];
byte rMask = rMaskTable[(x + width - 1) % 8];
int bank1 = x / 8;
int bank2 = (x + width - 1) / 8;
int count = bank2 - bank1;
if (bank1 == bank2) {
lMask &= rMask;
}
if (count != 0) {
bRightEdge = true;
count--;
if (count != 0) {
bCenterSection = true;
}
}
int pDst = (y * DELTA) + (x / 8);
int pSrc = offset;
ReadWriteMode(READ_MODE_0 | WRITE_MODE_0);
for (uint j = 0; j < height; j++) {
for (byte plane = 1; plane < 16; plane <<= 1) {
int pSrcTemp = pSrc;
int pDstTemp = pDst;
//
// Convert the packed bitmap data into planar data
// for this plane.
//
int bank = bank1;
Plane[bank] = 0;
byte Mask = PixelMask[x % 8];
uint toggle = 0;
for (uint i = 0; i < width; i++) {
if ((toggle++ & 0x1) != 0) {
if ((buffer[pSrcTemp] & plane) != 0) {
Plane[bank] |= Mask;
}
pSrcTemp++;
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
if (((buffer[pSrcTemp] >> 4) & plane) != 0) {
Plane[bank] |= Mask;
}
}
Mask >>= 1;
if (Mask == 0) {
bank++;
Plane[bank] = 0;
Mask = 0x80;
}
}
//
// Set up the vga so that we see the correct bit plane.
//
seqAddrPort.Write8(SEQ_PLANEMASK_REG);
seqDataPort.Write8(plane);
//
// bank will go from bank1 to bank2
//
bank = bank1;
pDstTemp = pDst;
//
// Set Bitmask for left edge.
//
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(lMask);
// The read triggers the latch register.
screenBuffer.Read8(pDstTemp);
screenBuffer.Write8(pDstTemp++, Plane[bank++]);
if (bCenterSection) {
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(0xff);
screenBuffer.Write8(pDstTemp, Plane, bank, count);
bank += count;
pDstTemp += count;
}
if (bRightEdge) {
//
// Set bitmask for right edge.
//
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(rMask);
// The read triggers the latch register.
screenBuffer.Read8(pDstTemp);
screenBuffer.Write8(pDstTemp, Plane[bank]);
}
}
pDst += DELTA;
pSrc += ScanWidth;
}
// Restore the settings.
seqAddrPort.Write8(SEQ_PLANEMASK_REG);
seqDataPort.Write8(0x0f);
}
private void BitBlt1(int x, int y, int width, int height,
byte[] buffer, int offset, int ScanWidth, byte color)
{
int bank1 = x / 8;
int bank2 = (x + width - 1) / 8;
byte lMask = lMaskTable[x % 8];
byte rMask = rMaskTable[(x + width - 1) % 8];
if (bank1 == bank2) {
lMask &= rMask;
}
int pSrc = offset;
int pDst = (y * DELTA) + (x / 8);
int shift = x % 8;
ReadWriteMode(READ_MODE_0 | WRITE_MODE_0);
graphAddrPort.Write8(GRAPH_ENABLE_REG);
graphDataPort.Write8((byte)(color ^ 0x0f));
for (uint j = 0; j < height; j++) {
int pDstTemp = pDst;
int pSrcTemp = pSrc;
int count = width;
//
// non aligned case
//
if (shift != 0) {
//
// Left Edge.
//
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(lMask);
// The read triggers the latch register.
screenBuffer.Read8(pDstTemp);
screenBuffer.Write8(pDstTemp++, (byte)(buffer[pSrcTemp] >> shift));
count -= (8 - shift);
//
// Now do center section
//
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(0xff);
while (count > 7) {
screenBuffer.Write8(pDstTemp++,
(byte)((buffer[pSrcTemp] << (8 - shift)) |
(buffer[pSrcTemp+1] >> shift)));
pSrcTemp++;
count -= 8;
}
//
// Now do the right edge.
//
if (count != 0) {
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(rMask);
// The read triggers the latch register.
screenBuffer.Read8(pDstTemp);
screenBuffer.Write8(pDstTemp++,
(byte)(buffer[pSrcTemp] << (8 - shift)));
}
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
//
// Aligned case.
//
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(0xff);
screenBuffer.Write8(pDstTemp, buffer, pSrcTemp, count / 8);
pSrcTemp += count / 8;
pDstTemp += count / 8;
count %= 8;
//
// Now do any remaining bits.
//
if (count != 0) {
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(rMask);
// The read triggers the latch register.
screenBuffer.Read8(pDstTemp);
screenBuffer.Write8(pDstTemp++, buffer[pSrcTemp]);
}
}
pSrc += ScanWidth;
pDst += DELTA;
}
graphAddrPort.Write8(GRAPH_ENABLE_REG);
graphDataPort.Write8(0x00);
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(0xff);
}
// Display a bitmap at a given location.
public void BitBltBmp(int x, int y, byte[] buffer)
{
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
int lDelta;
int cbScanLine;
int used;
int offset = 0;
bfh = BITMAPFILEHEADER.Read(buffer, offset, out used);
bih = BITMAPINFOHEADER.Read(buffer, used, out used);
if (bih.biWidth == 0 || bih.biHeight == 0) {
return;
}
if (x < 0) {
x = SCREEN_WIDTH + x - bih.biWidth;
}
if (y < 0) {
y = SCREEN_HEIGHT + y - bih.biHeight;
}
if (x < 0 || x + bih.biWidth > SCREEN_WIDTH ||
y < 0 || y + bih.biHeight > SCREEN_HEIGHT) {
throw new OverflowException("Draw bounds invalid.");
}
offset = offset + bfh.bfOffBits;
used = offset;
//
// Make sure this is a 1bpp or 4bpp bitmap.
//
if ((bih.biBitCount * bih.biPlanes) <= 4 || bih.biCompression != 0) {
cbScanLine = (((bih.biWidth * bih.biBitCount) + 31) & ~31) / 8;
if (bih.biHeight < 0) {
// top down bitmap
lDelta = cbScanLine;
bih.biHeight = -bih.biHeight;
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
// bottom up bitmap
offset += cbScanLine * (bih.biHeight - 1);
lDelta = -cbScanLine;
}
if (used + cbScanLine * bih.biHeight > buffer.Length) {
DebugStub.Print("{0} + {1} * {2} = {3} > {4}\n",
__arglist(
used,
cbScanLine,
bih.biHeight,
used + cbScanLine * bih.biHeight,
buffer.Length);
throw new OverflowException("Bitmap invalid.");
}
if (bih.biBitCount == 1) {
BitBlt1(x, y, bih.biWidth, bih.biHeight, buffer, offset, lDelta, 15);
}
else if (bih.biBitCount == 4) {
BitBlt4(x, y, bih.biWidth, bih.biHeight, buffer, offset, lDelta);
}
2008-11-17 18:29:00 -05:00
}
else {
2008-03-05 09:52:00 -05:00
//
// We don't support this type of bitmap.
//
DebugStub.Print("((bih.biBitCount * bih.biPlanes) not supported");
}
}
public void Scroll(int x1, int y1, int x2, int y2, int CharHeight)
{
if (x1 < 0 || x1 >= SCREEN_WIDTH ||
x2 < 0 || x2 >= SCREEN_WIDTH ||
y1 < 0 || y1 >= SCREEN_HEIGHT ||
y2 < 0 || y2 >= SCREEN_HEIGHT ||
y2 - y1 < CharHeight) {
throw new OverflowException("Draw bounds invalid.");
}
int width = (x2 / 8) - (x1 / 8) + 1;
ReadWriteMode(READ_MODE_0 | WRITE_MODE_1);
graphAddrPort.Write8(GRAPH_BITMASK_REG); // enable write to all bits in plane
graphDataPort.Write8(0xff);
int pDst = y1 * DELTA + (x1 / 8);
int pSrc = pDst + DELTA * CharHeight;
for (int i = y1; i <= y2 - CharHeight; i++) {
int pDstTemp = pDst;
int pSrcTemp = pSrc;
for (int j = 0; j < width; j++) {
// The read triggers the latch register.
screenBuffer.Read8(pSrcTemp++);
// The write triggers a write from the latch register, value ignored.
screenBuffer.Write8(pDstTemp++, 0);
}
pDst += DELTA;
pSrc += DELTA;
}
}
public void Plot(int x, int y, RGB color)
{
Plot(x, y, (byte)color);
}
public void Fill(int x1, int y1, int x2, int y2, RGB color)
{
Fill(x1, y1, x2, y2, (byte)color);
}
public void BitBltChr(int x, int y, int width, int height,
byte[] buffer, int offset, int ScanWidth,
RGB color, RGB background)
{
BitBlt1(x, y, width, height, buffer, offset + height - ScanWidth, -ScanWidth, (byte)color);
}
private void SetPaletteEntry(byte index, uint RGB)
{
dacAddressWritePort.Write8(index);
dacDataRegPort.Write8((byte)(RGB & 0xff));
dacDataRegPort.Write8((byte)((RGB >> 8) & 0xff));
dacDataRegPort.Write8((byte)((RGB >> 16) & 0xff));
}
private void InitializePalette()
{
uint[] Palette = new uint[]
{
0x00000000,
0x00000020,
0x00002000,
0x00002020,
0x00200000,
0x00200020,
0x00202000,
0x00202020,
0x00303030,
0x0000003f,
0x00003f00,
0x00003f3f,
0x003f0000,
0x003f003f,
0x003f3f00,
0x003f3f3f,
};
for (byte i = 0; i < Palette.Length; i++) {
SetPaletteEntry(i, Palette[i]);
}
}
// This routine initializes the VGA.
public void Initialize()
{
DebugStub.Print("Initializing VGA Driver\n");
Vga640x480();
DebugStub.Print(" VGA.AtInitialization\n");
AtInitialization();
DebugStub.Print(" VGA.InitializePalette\n");
InitializePalette();
DebugStub.Print(" VGA.Fill\n");
Fill(0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, 11);
DebugStub.Print(" VGA.new SVGA\n");
SvgaWindow console = new SvgaWindow(this, 0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1);
lastScreen = Console.Screen;
Console.Screen = console;
Console.WriteLine("Singularity VGA Driver");
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
}
public void Finalize()
{
if (lastScreen != null) {
Console.Screen = lastScreen;
}
AtInitialization();
InitializePalette();
VgaTextMode();
for (int i = 0; i < 50 * 80 * 2; i++) {
textBuffer.Write16(i, 0x1f41);
}
}
private void IndxOut(IoPort port, byte[] values)
{
for (ushort i = 0; i < values.Length; i++) {
port.Write16((ushort)(i + ((ushort)values[i] << 8)));
}
}
private void AtcOut(IoPort port, byte[] values)
{
for (byte i = 0; i < values.Length; i++) {
port.Write8(i);
port.Write8(values[i]);
}
}
//
private void VgaTextMode()
{
// start sync reset program up sequencer
IndxOut(seqAddrPort, new byte[] { 0x01,0x00,0x03,0x00,0x02 } );
miscOutputRegWritePort.Write8(0x67);
graphAddrPort.Write16(0x0e06);
// EndSyncResetCmd
seqAddrPort.Write16(0x0300);
// Unlock the CTC registers.
crtcAddressColorPort.Write16(0x0E11);
// program crtc registers
IndxOut(crtcAddressColorPort, new byte[] { 0x5F,0x4f,0x50,0x82,0x55,0x81,
0xbf,0x1f,0x00,0x4f,0x0d,0x0e,
0x00,0x00,0x00,0x00,0x9c,0x8e,
0x8f,0x28,0x1f,0x96,0xb9,0xa3,
0xFF } );
// prepare atc for writing
inputStatusColorPort.Read8();
AtcOut(atcAddrPort, new byte[] { 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,
0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0x04,0x00,0x0F,0x08,0x00 } );
// program graphics controller registers
IndxOut(graphAddrPort, new byte[] { 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff});
// DAC mask registers
dacPixelMaskPort.Write8(0xFF);
// prepare atc for writing
inputStatusColorPort.Read8();
// turn video on.
atcAddrPort.Write8(VIDEO_ENABLE);
}
//
// Code to put vga into mode 12.
//
private void Vga640x480()
{
DebugStub.Print(" Vga640x480:1\n");
// start sync reset program up sequencer
seqAddrPort.Write8(SEQ_RESET_REG);
seqDataPort.Write8(0);
seqAddrPort.Write8(SEQ_CLOCK_REG);
seqDataPort.Write8(0x01);
seqAddrPort.Write8(SEQ_PLANEMASK_REG);
seqDataPort.Write8(0x0f);
seqAddrPort.Write8(SEQ_CHARSET_REG);
seqDataPort.Write8(0x00);
seqAddrPort.Write8(SEQ_MEMORY_REG);
seqDataPort.Write8(0x06);
DebugStub.Print(" Vga640x480:2\n");
miscOutputRegWritePort.Write8(0xe3);
DebugStub.Print(" Vga640x480:3\n");
// Set chain mode in sync reset
graphAddrPort.Write8(GRAPH_MISC_REG);
graphDataPort.Write8(0x05); // graphics and 64KB buffer
DebugStub.Print(" Vga640x480:4\n");
// EndSyncResetCmd
seqAddrPort.Write8(SEQ_RESET_REG);
seqDataPort.Write8(0x03);
DebugStub.Print(" Vga640x480:5\n");
// Unlock CRTC registers 0-7
crtcAddressColorPort.Write16(0x0511);
DebugStub.Print(" Vga640x480:6\n");
// program crtc registers
IndxOut(crtcAddressColorPort, new byte[] { 0x5F,0x4F,0x50,0x82,0x54,0x80,
0x0B,0x3E,0x00,0x40,0x00,0x00,
0x00,0x00,0x00,0x00,0xEA,0x8C,
0xDF,0x28,0x00,0xE7,0x04,0xE3,
0xFF } );
// prepare atc for writing
inputStatusColorPort.Read8();
DebugStub.Print(" Vga640x480:7\n");
// program attribute controller registers
AtcOut(atcAddrPort, new byte[] { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x01,0x00,0x0F,0x00,0x00 } );
DebugStub.Print(" Vga640x480:8\n");
// program graphics controller registers
graphAddrPort.Write8(GRAPH_SET_REG);
graphDataPort.Write8(0x00);
graphAddrPort.Write8(GRAPH_ENABLE_REG);
graphDataPort.Write8(0x00);
graphAddrPort.Write8(GRAPH_COMPARE_REG);
graphDataPort.Write8(0x00);
graphAddrPort.Write8(GRAPH_OPERATION_REG);
graphDataPort.Write8(0x00);
graphAddrPort.Write8(GRAPH_READSEL_REG);
graphDataPort.Write8(0x00);
graphAddrPort.Write8(GRAPH_MODE_REG);
graphDataPort.Write8(0x00);
graphAddrPort.Write8(GRAPH_MISC_REG);
graphDataPort.Write8(0x05);
graphAddrPort.Write8(GRAPH_DONTCARE_REG);
graphDataPort.Write8(0x00); // was 0x0f
graphAddrPort.Write8(GRAPH_BITMASK_REG);
graphDataPort.Write8(0xff);
DebugStub.Print(" Vga640x480:9\n");
// DAC mask registers
dacPixelMaskPort.Write8(0xFF);
DebugStub.Print(" Vga640x480:10\n");
// prepare atc for writing
inputStatusColorPort.Read8();
DebugStub.Print(" Vga640x480:11\n");
// turn video on.
atcAddrPort.Write8(VIDEO_ENABLE);
}
//
// Initialize AT registers
//
private void AtInitialization()
{
// prepare atc for writing
inputStatusColorPort.Read8();
// program attribute controller registers
AtcOut(atcAddrPort, new byte[] { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
});
// prepare atc for writing
inputStatusColorPort.Read8();
// turn video on.
atcAddrPort.Write8(VIDEO_ENABLE);
}
}
}