252 lines
8.0 KiB
C
252 lines
8.0 KiB
C
/*
|
|
* Copyright (c) LSE
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY LSE AS IS AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL LSE BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include <k/compiler.h>
|
|
|
|
#include "libvga.h"
|
|
#include "io.h"
|
|
|
|
/*
|
|
** Use to save the VGA plane 2, which contains the text font,
|
|
** when we switch into graphic mode.
|
|
*/
|
|
static unsigned char libvga_txt_mode_font[320 * 200];
|
|
|
|
/*
|
|
** Registers value for graphic mode.
|
|
*/
|
|
static unsigned char libvga_regs_320x200x256[] = {
|
|
/* MISC */
|
|
0x63,
|
|
/* SEQ */
|
|
0x03, 0x01, 0x0F, 0x00, 0x0E,
|
|
/* CRTC */
|
|
0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F,
|
|
0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
|
|
0xFF,
|
|
/* GC */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
|
|
0xFF,
|
|
/* AC */
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
|
0x41, 0x00, 0x0F, 0x00, 0x00
|
|
};
|
|
|
|
/*
|
|
** Registers value for basic text mode.
|
|
*/
|
|
static unsigned char libvga_regs_80x25xtext[] = {
|
|
/* MISC */
|
|
0x67,
|
|
/* SEQ */
|
|
0x03, 0x00, 0x03, 0x00, 0x02,
|
|
/* CRTC */
|
|
0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F,
|
|
0x00, 0x4F, 0x0D, 0x0E, 0x00, 0x00, 0x00, 0x50,
|
|
0x9C, 0x0E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
|
|
0xFF,
|
|
/* GC */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00,
|
|
0xFF,
|
|
/* AC */
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
|
|
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
|
0x0C, 0x00, 0x0F, 0x08, 0x00
|
|
};
|
|
|
|
/*
|
|
** Basic Windows BITMAP pallet.
|
|
** This palette is automatically loaded when switching to mode 13h
|
|
*/
|
|
static unsigned int libvga_default_palette[256] = {
|
|
0x0, 0x800000, 0x8000, 0x808000,
|
|
0x80, 0x800080, 0x8080, 0xc0c0c0,
|
|
0xc0dcc0, 0xa6caf0, 0x402000, 0x602000,
|
|
0x802000, 0xa02000, 0xc02000, 0xe02000,
|
|
0x4000, 0x204000, 0x404000, 0x604000,
|
|
0x804000, 0xa04000, 0xc04000, 0xe04000,
|
|
0x6000, 0x206000, 0x406000, 0x606000,
|
|
0x806000, 0xa06000, 0xc06000, 0xe06000,
|
|
0x8000, 0x208000, 0x408000, 0x608000,
|
|
0x808000, 0xa08000, 0xc08000, 0xe08000,
|
|
0xa000, 0x20a000, 0x40a000, 0x60a000,
|
|
0x80a000, 0xa0a000, 0xc0a000, 0xe0a000,
|
|
0xc000, 0x20c000, 0x40c000, 0x60c000,
|
|
0x80c000, 0xa0c000, 0xc0c000, 0xe0c000,
|
|
0xe000, 0x20e000, 0x40e000, 0x60e000,
|
|
0x80e000, 0xa0e000, 0xc0e000, 0xe0e000,
|
|
0x40, 0x200040, 0x400040, 0x600040,
|
|
0x800040, 0xa00040, 0xc00040, 0xe00040,
|
|
0x2040, 0x202040, 0x402040, 0x602040,
|
|
0x802040, 0xa02040, 0xc02040, 0xe02040,
|
|
0x4040, 0x204040, 0x404040, 0x604040,
|
|
0x804040, 0xa04040, 0xc04040, 0xe04040,
|
|
0x6040, 0x206040, 0x406040, 0x606040,
|
|
0x806040, 0xa06040, 0xc06040, 0xe06040,
|
|
0x8040, 0x208040, 0x408040, 0x608040,
|
|
0x808040, 0xa08040, 0xc08040, 0xe08040,
|
|
0xa040, 0x20a040, 0x40a040, 0x60a040,
|
|
0x80a040, 0xa0a040, 0xc0a040, 0xe0a040,
|
|
0xc040, 0x20c040, 0x40c040, 0x60c040,
|
|
0x80c040, 0xa0c040, 0xc0c040, 0xe0c040,
|
|
0xe040, 0x20e040, 0x40e040, 0x60e040,
|
|
0x80e040, 0xa0e040, 0xc0e040, 0xe0e040,
|
|
0x80, 0x200080, 0x400080, 0x600080,
|
|
0x800080, 0xa00080, 0xc00080, 0xe00080,
|
|
0x2080, 0x202080, 0x402080, 0x602080,
|
|
0x802080, 0xa02080, 0xc02080, 0xe02080,
|
|
0x4080, 0x204080, 0x404080, 0x604080,
|
|
0x804080, 0xa04080, 0xc04080, 0xe04080,
|
|
0x6080, 0x206080, 0x406080, 0x606080,
|
|
0x806080, 0xa06080, 0xc06080, 0xe06080,
|
|
0x8080, 0x208080, 0x408080, 0x608080,
|
|
0x808080, 0xa08080, 0xc08080, 0xe08080,
|
|
0xa080, 0x20a080, 0x40a080, 0x60a080,
|
|
0x80a080, 0xa0a080, 0xc0a080, 0xe0a080,
|
|
0xc080, 0x20c080, 0x40c080, 0x60c080,
|
|
0x80c080, 0xa0c080, 0xc0c080, 0xe0c080,
|
|
0xe080, 0x20e080, 0x40e080, 0x60e080,
|
|
0x80e080, 0xa0e080, 0xc0e080, 0xe0e080,
|
|
0xc0, 0x2000c0, 0x4000c0, 0x6000c0,
|
|
0x8000c0, 0xa000c0, 0xc000c0, 0xe000c0,
|
|
0x20c0, 0x2020c0, 0x4020c0, 0x6020c0,
|
|
0x8020c0, 0xa020c0, 0xc020c0, 0xe020c0,
|
|
0x40c0, 0x2040c0, 0x4040c0, 0x6040c0,
|
|
0x8040c0, 0xa040c0, 0xc040c0, 0xe040c0,
|
|
0x60c0, 0x2060c0, 0x4060c0, 0x6060c0,
|
|
0x8060c0, 0xa060c0, 0xc060c0, 0xe060c0,
|
|
0x80c0, 0x2080c0, 0x4080c0, 0x6080c0,
|
|
0x8080c0, 0xa080c0, 0xc080c0, 0xe080c0,
|
|
0xa0c0, 0x20a0c0, 0x40a0c0, 0x60a0c0,
|
|
0x80a0c0, 0xa0a0c0, 0xc0a0c0, 0xe0a0c0,
|
|
0xc0c0, 0x20c0c0, 0x40c0c0, 0x60c0c0,
|
|
0x80c0c0, 0xa0c0c0, 0xfffbf0, 0xa0a0a4,
|
|
0x808080, 0xff0000, 0xff00, 0xffff00,
|
|
0xff, 0xff00ff, 0xffff, 0xffffff
|
|
};
|
|
|
|
static void libvga_write_regs(unsigned char *regs)
|
|
{
|
|
unsigned int i;
|
|
unsigned int a;
|
|
|
|
/* write the MISC register */
|
|
outb(VGA_MISC_WRITE, *regs);
|
|
regs++;
|
|
|
|
/* write SEQ registers */
|
|
for (i = 0; i < VGA_NUM_SEQ_REGS; i++) {
|
|
outb(VGA_SEQ_INDEX, i);
|
|
outb(VGA_SEQ_DATA, *regs);
|
|
regs++;
|
|
}
|
|
|
|
/* write CRTC registers */
|
|
outb(VGA_CRTC_INDEX, 0x03);
|
|
a = inb(VGA_CRTC_DATA);
|
|
outb(VGA_CRTC_DATA, a | 0x80);
|
|
outb(VGA_CRTC_INDEX, 0x11);
|
|
a = inb(VGA_CRTC_DATA);
|
|
outb(VGA_CRTC_DATA, a & ~0x80);
|
|
regs[0x03] |= 0x80;
|
|
regs[0x11] &= ~0x80;
|
|
for (i = 0; i < VGA_NUM_CRTC_REGS; i++) {
|
|
outb(VGA_CRTC_INDEX, i);
|
|
outb(VGA_CRTC_DATA, *regs);
|
|
regs++;
|
|
}
|
|
|
|
/* write GC registers */
|
|
for (i = 0; i < VGA_NUM_GC_REGS; i++) {
|
|
outb(VGA_GC_INDEX, i);
|
|
outb(VGA_GC_DATA, *regs);
|
|
regs++;
|
|
}
|
|
|
|
/* write AC registers */
|
|
inb(VGA_INSTAT_READ);
|
|
for (i = 0; i < VGA_NUM_AC_REGS; i++) {
|
|
outb(VGA_AC_INDEX, i);
|
|
outb(VGA_AC_WRITE, *regs);
|
|
regs++;
|
|
}
|
|
inb(VGA_INSTAT_READ);
|
|
outb(VGA_AC_INDEX, 0x20);
|
|
|
|
/* write the default palette to the DAC */
|
|
outb(VGA_DAC_MASK, 0xFF);
|
|
libvga_set_palette(libvga_default_palette, array_size(libvga_default_palette));
|
|
}
|
|
|
|
void libvga_set_palette(unsigned int *new_palette, size_t size)
|
|
{
|
|
outb(VGA_DAC_WRITE_INDEX, 0);
|
|
for (size_t i = 0; i < size; i++) {
|
|
outb(VGA_DAC_DATA, ((new_palette[i] >> 16) >> 2) & 0xFF);
|
|
outb(VGA_DAC_DATA, ((new_palette[i] >> 8) >> 2) & 0xFF);
|
|
outb(VGA_DAC_DATA, ((new_palette[i]) >> 2) & 0xFF);
|
|
}
|
|
}
|
|
|
|
char *libvga_get_framebuffer(void)
|
|
{
|
|
unsigned int mmap_select;
|
|
|
|
outb(VGA_GC_INDEX, 6);
|
|
mmap_select = inb(VGA_GC_DATA);
|
|
mmap_select >>= 2;
|
|
mmap_select &= 3;
|
|
switch (mmap_select) {
|
|
case 0:
|
|
case 1:
|
|
return (char *)0xA0000;
|
|
case 2:
|
|
return (char *)0xB0000;
|
|
case 3:
|
|
return (char *)0xB8000;
|
|
}
|
|
return (char *)0;
|
|
}
|
|
|
|
void libvga_switch_mode13h(void)
|
|
{
|
|
libvga_write_regs(libvga_regs_320x200x256);
|
|
|
|
// plane 2 is now map in the memory, save it
|
|
char *vram = libvga_get_framebuffer();
|
|
for (size_t i = 0; i < array_size(libvga_txt_mode_font); i++)
|
|
libvga_txt_mode_font[i] = vram[i];
|
|
}
|
|
|
|
void libvga_switch_mode3h(void)
|
|
{
|
|
// restore the VGA plane 2 to the text font
|
|
char *vram = libvga_get_framebuffer();
|
|
for (size_t i = 0; i < array_size(libvga_txt_mode_font); i++)
|
|
vram[i] = libvga_txt_mode_font[i];
|
|
|
|
libvga_write_regs(libvga_regs_80x25xtext);
|
|
}
|