#ifdef VGA_RESET
#include <lib/libsa/stand.h>
#include "boot.h"
#include "iso_font.h"
#define VGA_SR_PORT 0x3c4
#define VGA_CR_PORT 0x3d4
#define VGA_CR_DATA 0x3d5
#define VGA_GR_PORT 0x3ce
#define VGA_GR_DATA 0x3cf
#define SRREGS 4
#define CRREGS 24
#define GRREGS 9
#define LINES 25
#define COLS 80
#define PCI_VENDOR_S3 0x5333
#define PCI_VENDOR_CIRRUS 0x1013
#define PCI_VENDOR_DIAMOND 0x100E
#define PCI_VENDOR_MATROX 0x102B
#define PCI_VENDOR_PARADISE 0x101C
static void write_attr(u_int8_t, u_int8_t, u_int8_t);
static void set_text_regs(void);
static void set_text_clut(int);
static void load_font(u_int8_t *);
static void unlock_S3(void);
static void clear_video_memory(void);
extern char *videomem;
typedef struct vga_reg {
u_int8_t idx;
u_int8_t val;
} vga_reg_t;
static vga_reg_t SR_regs[SRREGS] = {
{ 0x1, 0x0 },
{ 0x2, 0x3 },
{ 0x3, 0x0 },
{ 0x4, 0x2 }
};
static vga_reg_t CR_regs[CRREGS] = {
{ 0x0, 0x61 },
{ 0x1, 0x4f },
{ 0x2, 0x50 },
{ 0x3, 0x82 },
{ 0x4, 0x55 },
{ 0x5, 0x81 },
{ 0x6, 0xf0 },
{ 0x7, 0x1f },
{ 0x8, 0x00 },
{ 0x9, 0x4f },
{ 0xa, 0x0d },
{ 0xb, 0x0e },
{ 0xc, 0x00 },
{ 0xd, 0x00 },
{ 0xe, 0x00 },
{ 0xf, 0x00 },
{ 0x10, 0x9a },
{ 0x11, 0x8c },
{ 0x12, 0x8f },
{ 0x13, 0x28 },
{ 0x14, 0x1f },
{ 0x15, 0x97 },
{ 0x16, 0x00 },
{ 0x17, 0xa3 },
};
static vga_reg_t GR_regs[GRREGS] = {
{ 0x0, 0x00 },
{ 0x1, 0x00 },
{ 0x2, 0x00 },
{ 0x3, 0x00 },
{ 0x4, 0x00 },
{ 0x5, 0x10 },
{ 0x6, 0x0e },
{ 0x7, 0x00 },
{ 0x8, 0xff },
};
static const u_int8_t vga_dacpal[] = {
0x00, 0x00, 0x00,
0x00, 0x00, 0x2a,
0x00, 0x2a, 0x00,
0x00, 0x2a, 0x2a,
0x2a, 0x00, 0x00,
0x2a, 0x00, 0x2a,
0x2a, 0x15, 0x00,
0x2a, 0x2a, 0x2a,
0x15, 0x15, 0x15,
0x15, 0x15, 0x3f,
0x15, 0x3f, 0x15,
0x15, 0x3f, 0x3f,
0x3f, 0x15, 0x15,
0x3f, 0x15, 0x3f,
0x3f, 0x3f, 0x15,
0x3f, 0x3f, 0x3f
};
static const u_int8_t vga_atc[] = {
0x00,
0x01,
0x02,
0x03,
0x04,
0x05,
0x14,
0x07,
0x38,
0x39,
0x3a,
0x3b,
0x3c,
0x3d,
0x3e,
0x3f,
0x0c,
0x00,
0x0f,
0x08,
0x00
};
void
vga_reset(u_char *ISA_mem)
{
int slot, cardfound;
outb(VGA_GR_PORT, 0x06);
if ((inb(VGA_GR_DATA) & 0x01) == 0)
return;
slot = -1;
while ((slot = scan_PCI(slot)) > -1) {
cardfound = 0;
switch (PCI_vendor(slot)) {
case PCI_VENDOR_CIRRUS:
unlockVideo(slot);
outw(VGA_SR_PORT, 0x0612);
outw(VGA_SR_PORT, 0x0700);
cardfound++;
break;
case PCI_VENDOR_PARADISE:
unlockVideo(slot);
outw(VGA_GR_PORT, 0x0f05);
outw(VGA_SR_PORT, 0x0648);
outw(VGA_CR_PORT, 0x2985);
outw(VGA_CR_PORT, 0x34a6);
outb(VGA_GR_PORT, 0x0b);
outb(VGA_GR_DATA, inb(VGA_GR_DATA) & ~0x30);
outw(VGA_SR_PORT, 0x1400);
outb(VGA_GR_PORT, 0x0e);
outb(VGA_GR_DATA, inb(VGA_GR_DATA) & ~0x01);
outb(0xd00, 0xff);
if (!(inb(0xd01) & 0x03)) {
outb(VGA_CR_PORT, 0x33);
outb(VGA_CR_DATA, inb(VGA_CR_DATA) & ~0x90);
outb(VGA_CR_PORT, 0x32);
outb(VGA_CR_DATA, inb(VGA_CR_DATA) | 0x04);
outw(VGA_CR_PORT, 0x0250);
outw(VGA_CR_PORT, 0x07ba);
outw(VGA_CR_PORT, 0x0900);
outw(VGA_CR_PORT, 0x15e7);
outw(VGA_CR_PORT, 0x2a95);
}
outw(VGA_CR_PORT, 0x34a0);
cardfound++;
break;
case PCI_VENDOR_S3:
unlockVideo(slot);
unlock_S3();
cardfound++;
break;
default:
break;
}
if (cardfound) {
outw(VGA_SR_PORT, 0x0120);
set_text_regs();
set_text_clut(0);
load_font(ISA_mem);
set_text_regs();
outw(VGA_SR_PORT, 0x0100);
clear_video_memory();
if (PCI_vendor(slot) == PCI_VENDOR_S3)
outb(0x3c2, 0x63);
delay(1000);
}
}
return;
}
static void
write_attr(u_int8_t index, u_int8_t data, u_int8_t videoOn)
{
(void)inb(0x3da);
if (videoOn)
outb(0x3c0, (index & 0x1F) | 0x20);
else
outb(0x3c0, (index & 0x1F));
outb(0x3c0, data);
}
static void
set_text_regs(void)
{
int i;
for (i = 0; i < SRREGS; i++) {
outb(VGA_SR_PORT, SR_regs[i].idx);
outb(VGA_SR_PORT + 1, SR_regs[i].val);
}
for (i = 0; i < CRREGS; i++) {
outb(VGA_CR_PORT, CR_regs[i].idx);
outb(VGA_CR_PORT + 1, CR_regs[i].val);
}
for (i = 0; i < GRREGS; i++) {
outb(VGA_GR_PORT, GR_regs[i].idx);
outb(VGA_GR_PORT + 1, GR_regs[i].val);
}
outb(0x3c2, 0x67);
outb(0x3c6, 0xff);
for (i = 0; i < 0x14; i++)
write_attr(i, vga_atc[i], 0);
write_attr(0x14, 0x00, 1);
}
static void
set_text_clut(int shift)
{
int i;
outb(0x3C6, 0xFF);
inb(0x3C7);
outb(0x3C8, 0);
inb(0x3C7);
for (i = 0; i < (16 * 3); ) {
outb(0x3c9, vga_dacpal[i++] << shift);
outb(0x3c9, vga_dacpal[i++] << shift);
outb(0x3c9, vga_dacpal[i++] << shift);
}
}
static void
load_font(u_int8_t *ISA_mem)
{
int i, j;
u_int8_t *font_page = (u_int8_t *)&ISA_mem[0xA0000];
outb(0x3C2, 0x67);
inb(0x3DA);
outb(0x3C0, 0x30);
outb(0x3C0, 0x01);
outw(0x3C4, 0x0001);
outw(0x3C4, 0x0204);
outw(0x3C4, 0x0406);
outw(0x3C4, 0x0003);
outw(0x3CE, 0x0402);
outw(0x3CE, 0x0500);
outw(0x3CE, 0x0605);
for (i = 0; i < sizeof(font); i += 16) {
for (j = 0; j < 16; j++) {
__asm__ volatile("eieio" ::: "memory");
font_page[(2*i)+j] = font[i+j];
}
}
}
static void
unlock_S3(void)
{
int s3_devid;
outw(VGA_CR_PORT, 0x3848);
outw(VGA_CR_PORT, 0x39a5);
outb(VGA_CR_PORT, 0x2d);
s3_devid = inb(VGA_CR_DATA) << 8;
outb(VGA_CR_PORT, 0x2e);
s3_devid |= inb(VGA_CR_DATA);
if (s3_devid != 0x8812) {
outb(0x46E8, 0x10);
outb(0x3C3, 0x10);
outb(0x102, 0x01);
outb(0x46E8, 0x08);
outb(0x3C3, 0x08);
outb(0x4AE8, 0x00);
outb(VGA_CR_PORT, 0x38);
outb(VGA_CR_DATA, 0x48);
outb(VGA_CR_PORT, 0x39);
outb(VGA_CR_DATA, 0xA5);
outb(VGA_CR_PORT, 0x40);
outb(VGA_CR_DATA, inb(0x3D5)|0x01);
outb(VGA_CR_PORT, 0x33);
outb(VGA_CR_DATA, inb(0x3D5)&~0x52);
outb(VGA_CR_PORT, 0x35);
outb(VGA_CR_DATA, inb(0x3D5)&~0x30);
outb(VGA_CR_PORT, 0x3A);
outb(VGA_CR_DATA, 0x00);
outb(VGA_CR_PORT, 0x53);
outb(VGA_CR_DATA, 0x00);
outb(VGA_CR_PORT, 0x31);
outb(VGA_CR_DATA, inb(0x3D5)&~0x4B);
outb(VGA_CR_PORT, 0x58);
outb(VGA_CR_DATA, 0);
outb(VGA_CR_PORT, 0x54);
outb(VGA_CR_DATA, 0x38);
outb(VGA_CR_PORT, 0x60);
outb(VGA_CR_DATA, 0x07);
outb(VGA_CR_PORT, 0x61);
outb(VGA_CR_DATA, 0x80);
outb(VGA_CR_PORT, 0x62);
outb(VGA_CR_DATA, 0xA1);
outb(VGA_CR_PORT, 0x69);
outb(VGA_CR_DATA, 0);
outb(VGA_CR_PORT, 0x32);
outb(VGA_CR_DATA, inb(0x3D5)&~0x10);
} else {
outw(VGA_SR_PORT, 0x0806);
outw(VGA_SR_PORT, 0x1041);
outw(VGA_SR_PORT, 0x1128);
outw(VGA_CR_PORT, 0x4000);
outw(VGA_CR_PORT, 0x3100);
outw(VGA_CR_PORT, 0x3a05);
outw(VGA_CR_PORT, 0x6688);
outw(VGA_CR_PORT, 0x5800);
outw(VGA_CR_PORT, 0x4500);
outw(VGA_SR_PORT, 0x5410);
outw(VGA_SR_PORT, 0x561f);
outw(VGA_SR_PORT, 0x1b80);
outw(VGA_CR_PORT, 0x3900);
outw(VGA_CR_PORT, 0x3800);
}
}
static void
clear_video_memory(void)
{
int i, j;
for (i = 0; i < LINES; i++) {
for (j = 0; j < COLS; j++) {
videomem[((i * COLS)+j) * 2] = 0x20;
videomem[((i * COLS)+j) * 2 + 1] = 0x07;
}
}
}
#endif