Another Updated Patch:
So far I have heard of problems when using a lcd connected to the vga port and when switching from X to back to the console. I was able to replicate problems and address them with this patch.
For the lcd issues, the left side of the screen was distorted and cropped. This was a timing problem from using incorrect modes. My crt was able to function correctly with these modes. There were two issues with the mode table. When creating the patch I copied the original seabios table instead of the geodelx modified table. Then even with the correct geodelx table, the seabios table is still addressed at compile time. The geodelx-v3 patch includes the modified table, while the geodelx-modehack patch is a temporary quick fix to address the right table.
For switching from X to the console, the display controller registers need to be reset to enable vga . These are DC_GENERAL_CFG=0x80 and DC_DISPLAY_CFG=0x48. The linux vgacon vt driver only saves the standard vga io ports and memory. I am looking into doing this with vesa extensions from X. For now an easy way to do this is to re-post the vgabios with vbetool or svgalib. I removed exiting if legacy io checking fails so reposting is possible.
seabios-geodelx-v3.patch -replaced video parameter table -removed quiting when legacy io fails -fixed spelling
seabios-geodelx-modehack.patch -temporary fix to use correct video timing
Chris Kindt
Signed-off-by: Chris Kindt chriskindt@umbc.edu
diff --git a/Makefile b/Makefile index d697fca..a3696c1 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,7 @@ $(OUT)bios.bin: $(OUT)bios.bin.elf
# VGA src files SRCVGA=src/output.c src/util.c vgasrc/vga.c vgasrc/vgafb.c vgasrc/vgaio.c \ - vgasrc/vgatables.c vgasrc/vgafonts.c vgasrc/clext.c + vgasrc/vgatables.c vgasrc/vgafonts.c vgasrc/clext.c vgasrc/geodelx.c
$(OUT)vgaccode.16.s: ; $(call whole-compile, $(CFLAGS16) -S -Isrc, $(SRCVGA),$@)
diff --git a/vgasrc/geodelx.c b/vgasrc/geodelx.c new file mode 100644 index 0000000..c0c8a70 --- /dev/null +++ b/vgasrc/geodelx.c @@ -0,0 +1,573 @@ +// Geode LX VGA functions +// +// Copyright (C) 2009 Chris Kindt +// +// Written for Google Summer of Code 2009 for the coreboot project +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "geodelx.h" +#include "ioport.h" // outb +#include "farptr.h" // SET_FARVAR +#include "biosvar.h" // GET_BDA +#include "vgatables.h" // VGAREG_* +#include "util.h" // memset +#include "config.h" +#include "types.h" +#include "bregs.h" + +#define DEBUG_GEODELX 4 + +/**************************************************************** +* MSR and High Mem access through VSA Virtual Register +****************************************************************/ + +static union u64_u32_u lx_msrRead(u32 msrAddr) +{ + union u64_u32_u val; + asm __volatile__ ( + "movw $0x0AC1C, %%dx \n" + "movl $0xFC530007, %%eax \n" + "outl %%eax, %%dx \n" + "addb $2, %%dl \n" + "inw %%dx, %%ax \n" + : "=a" (val.lo), "=d"(val.hi) + : "c"(msrAddr) + : "cc" + ); + return val; +} + +static void lx_msrWrite(u32 msrAddr,u32 andhi, u32 andlo, u32 orhi, u32 orlo) +{ + asm __volatile__ ( + "push %%eax \n" + "movw $0x0AC1C, %%dx \n" + "movl $0xFC530007, %%eax \n" + "outl %%eax, %%dx \n" + "addb $2, %%dl \n" + "pop %%eax \n" + "outw %%ax, %%dx \n" + : + : "c"(msrAddr), "S" (andhi), "D" (andlo), "b" (orhi), "a" (orlo) + : "%edx","cc" + ); +} + +static u32 lx_memRead(u32 addr) +{ + u32 val; + asm __volatile__ ( + "movw $0x0AC1C, %%dx \n" + "movl $0xFC530001, %%eax \n" + "outl %%eax, %%dx \n" + "addb $2, %%dl \n" + "inw %%dx, %%ax \n" + : "=a" (val) + : "b"(addr) + : "cc" + ); + + return val; +} + +static void lx_memWrite(u32 addr, u32 and, u32 or ) +{ + asm __volatile__ ( + "movw $0x0AC1C, %%dx \n" + "movl $0xFC530001, %%eax \n" + "outl %%eax, %%dx \n" + "addb $2, %%dl \n" + "outw %%ax, %%dx \n" + : + : "b"(addr), "S" (and), "D" (or) + : "%eax","cc" + ); +} + +static int legacyio_check() +{ + int ret=0; + union u64_u32_u val; + + val=lx_msrRead(MSR_GLIU0_BASE4); + if (val.lo != 0x0A0fffe0) + ret|=1; + + val=lx_msrRead(GLIU0_IOD_BM_0); + if (val.lo != 0x3c0ffff0) + ret|=2; + + val=lx_msrRead(GLIU0_IOD_BM_1); + if (val.lo != 0x3d0ffff0) + ret|=4; + + return ret; +} + +/**************************************************************** +* Extened CRTC Register functions +****************************************************************/ +static void crtce_lock() +{ + outb(EXTENDED_REGISTER_LOCK , VGAREG_VGA_CRTC_ADDRESS); + outb(CRTCE_LOCK, VGAREG_VGA_CRTC_DATA); +} + +static void crtce_unlock() +{ + outb(EXTENDED_REGISTER_LOCK , VGAREG_VGA_CRTC_ADDRESS); + outb(CRTCE_UNLOCK, VGAREG_VGA_CRTC_DATA); +} + +static u8 crtce_read(u8 reg) +{ + u8 val; + + crtce_unlock(); + outb(reg , VGAREG_VGA_CRTC_ADDRESS); + val = inb(VGAREG_VGA_CRTC_DATA); + crtce_lock(); + + return val; +} + +static void crtce_write(u8 reg, u8 val) +{ + crtce_unlock(); + outb(reg , VGAREG_VGA_CRTC_ADDRESS); + outb(val, VGAREG_VGA_CRTC_DATA); + crtce_lock(); +} + +/**************************************************************** +* Display Controller Functions +****************************************************************/ +static u32 dc_read(u16 seg, u32 reg) +{ + u32 val, *dest_far = (void*)reg; + val = GET_FARVAR(seg,*dest_far); + return val; +} + +static void dc_write(u16 seg, u32 reg, u32 val) +{ + u32 *dest_far = (void*)reg; + SET_FARVAR(seg,*dest_far,val); +} + +static void dc_set(u16 seg, u32 reg, u32 and, u32 or) +{ + u32 val = dc_read(seg,reg); + val &=and; + val |=or; + dc_write(seg,reg,val); +} + +static void dc_unlock(u16 seg) +{ + dc_write(seg,DC_UNLOCK,DC_LOCK_UNLOCK); +} + +static void dc_lock(u16 seg) +{ + dc_write(seg,DC_UNLOCK,DC_LOCK_LOCK); +} + +static u16 dc_map(u16 seg) +{ + u8 reg; + + reg = crtce_read(EXTENDED_MODE_CONTROL); + reg &= 0xf9; + switch (seg) { + case SEG_GRAPH: + reg |= 0x02; + break; + case SEG_MTEXT: + reg |= 0x04; + break; + case SEG_CTEXT: + reg |= 0x06; + break; + default: + seg=0; + break; + } + + crtce_write(EXTENDED_MODE_CONTROL,reg); + return seg; +} + +static void dc_unmap() +{ + dc_map(0); +} + + +/**************************************************************** +* Init Functions +****************************************************************/ + +/* Set up the dc (display controller) portion of the geodelx +* The dc provides hardware support for VGA graphics +* for features not accessible from the VGA registers, +* the dc's pci bar can be mapped to a vga memory segment +*/ +static int dc_setup() +{ + u32 fb, dc_fb; + u16 seg; + + lxdprintf(2,"DC_SETUP\n"); + + seg = dc_map(SEG_GRAPH); + dc_unlock(seg); + + /* zero memory config */ + dc_write(seg,DC_FB_ST_OFFSET,0x0); + dc_write(seg,DC_CB_ST_OFFSET,0x0); + dc_write(seg,DC_CURS_ST_OFFSET,0x0); + + /* read fb-bar from pci, then point dc to the fb base */ + dc_fb = dc_read(seg,DC_GLIU0_MEM_OFFSET); + outl(LX_PCI_FB,PORT_PCI_CMD); + fb = inl(PORT_PCI_DATA); + if (fb!=dc_fb) { + dc_write(seg,DC_GLIU0_MEM_OFFSET,fb); + } + + dc_set(seg,DC_DISPLAY_CFG,DC_CFG_MSK,DC_GDEN+DC_TRUP); + dc_set(seg,DC_GENERAL_CFG,0,DC_VGAE); + + dc_lock(seg); + dc_unmap(); + + return 0; +} + +/* Setup the vp (video processor) portion of the geodelx +* Under VGA modes the vp was handled by softvg from inside VSA2. +* Without a softvg module, access is only available through a pci bar. +* The High Mem Access virtual register is used to configure the +* pci mmio bar from 16bit friendly io space. +*/ +int vp_setup() +{ + u32 reg,vp; + + lxdprintf(2,"VP_SETUP\n"); + /* set output to crt and RGB/YUV */ + lx_msrWrite(VP_MSR_CONFIG,~0 ,~0xf8,0,0); + + /* get vp register base from pci */ + outl(LX_PCI_VP,PORT_PCI_CMD); + vp = inl(PORT_PCI_DATA); + + /* Set mmio registers + * there may be some timing issues here, the reads seem + * to slow things down enough work reliably + */ + + reg = lx_memRead(vp+VP_MISC); + lxdprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg); + lx_memWrite(vp+VP_MISC,0,VP_BYP_BOTH); + reg = lx_memRead(vp+VP_MISC); + lxdprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg); + + reg = lx_memRead(vp+VP_DCFG); + lxdprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg); + lx_memWrite(vp+VP_DCFG, ~0,VP_CRT_EN+VP_HSYNC_EN+VP_VSYNC_EN+VP_DAC_BL_EN+VP_CRT_SKEW); + reg = lx_memRead(vp+VP_DCFG); + lxdprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg); + + return 0; +} + + +int geodelx_init() +{ + int ret; + + lxdprintf(1,"GEODELX_INIT\n"); + + if ((ret=legacyio_check())) { + lxdprintf(1,"GEODELX_INIT legacyio_check=0x%x\n",ret); + } + + ret |= vp_setup(); + ret |= dc_setup(); + + return ret; +} + +u8 geode_str[] VAR16 = "GeodeLX GPL VGA BIOS"; + +void VISIBLE16 geodelx_demo() +{ + int x; + struct bregs regs; + + lxdprintf(2,"GEODELX_DEMO\n"); + + extern void handle_10(struct bregs *); + regs.eax=0x3; + handle_10(®s); + + for (x=0;x<sizeof(geode_str)-1;x++) { + regs.eax=(0x0e00 + GET_GLOBAL(geode_str[x])); + handle_10(®s); + } +} + +/* PCI Header */ +struct pci_data _rom_pcidata VAR16EXPORT = { + + .signature = PCI_ROM_SIGNATURE, + .vendor = AMD_PCI_ID, + .device = LX_PCI_ID, + .vitaldata = 0, + .dlen = sizeof(struct pci_data), + .drevision = 0, + .class_lo = 0, + .class_hi = 0x0300, + .ilen = 0, + .irevision = 0, + .type = PCIROM_CODETYPE_X86, + .indicator = LAST_IMAGE , + .reserved = 0 +}; + +/* modified from seabios/vgabios with values +* from geode datasheets, table 6-53 in particular */ +struct VideoParam_s lx_video_param_table[] VAR16 = { + // index=0x00 no mode defined + {}, + // index=0x01 no mode defined + {}, + // index=0x02 no mode defined + {}, + // index=0x03 no mode defined + {}, + // index=0x04 vga mode 0x04 + { 40, 24, 8, 0x0800, /* tw, th-1, ch, slength */ + { 0x09, 0x03, 0x00, 0x02 }, /* sequ_regs */ + 0x63, /* miscreg */ + { 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f, + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2, + 0xff }, /* crtc_regs */ + { 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x01, 0x00, 0x03, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x05 vga mode 0x05 */ + { 40, 24, 8, 0x0800, /* tw, th-1, ch, slength */ + { 0x09, 0x03, 0x00, 0x02 }, /* sequ_regs */ + 0x63, /* miscreg */ + { 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f, + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8e, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xa2, + 0xff }, /* crtc_regs */ + { 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x01, 0x00, 0x03, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x06 vga mode 0x06 */ + { 80, 24, 8, 0x1000, /* tw, th-1, ch, slength */ + { 0x01, 0x01, 0x00, 0x06 }, /* sequ_regs */ + 0x63, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f, + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xc2, + 0xff }, /* crtc_regs */ + { 0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x01, 0x00, 0x01, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x07 vga mode 0x07 */ + { 80, 24, 16, 0x1000, /* tw, th-1, ch, slength */ + { 0x00, 0x03, 0x00, 0x02 }, /* sequ_regs */ + 0x66, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8d, 0x8f, 0x28, 0x0f, 0x97, 0xb9, 0xa3, + 0xff }, /* crtc_regs */ + { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x0e, 0x00, 0x0f, 0x08 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x08 no mode defined */ + {}, + /* index=0x09 no mode defined */ + {}, + /* index=0x0a no mode defined */ + {}, + /* index=0x0b no mode defined */ + {}, + /* index=0x0c no mode defined */ + {}, + /* index=0x0d vga mode 0x0d */ + { 40, 24, 8, 0x2000, /* tw, th-1, ch, slength */ + { 0x09, 0x0f, 0x00, 0x06 }, /* sequ_regs */ + 0x63, /* miscreg */ + { 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8d, 0x8f, 0x14, 0x00, 0x97, 0xb9, 0xe3, + 0xff }, /* crtc_regs */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x0e vga mode 0x0e */ + { 80, 24, 8, 0x4000, /* tw, th-1, ch, slength */ + { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ + 0x63, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f, + 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8d, 0x8f, 0x28, 0x00, 0x97, 0xb9, 0xe3, + 0xff }, /* crtc_regs */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x0f no mode defined */ + {}, + /* index=0x10 no mode defined */ + {}, + /* index=0x11 vga mode 0x0f */ + { 80, 24, 14, 0x8000, /* tw, th-1, ch, slength */ + { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ + 0xa3, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x65, 0xb9, 0xe3, + 0xff }, /* crtc_regs */ + { 0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x12 vga mode 0x10 */ + { 80, 24, 14, 0x8000, /* tw, th-1, ch, slength */ + { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ + 0xa3, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x83, 0x85, 0x5d, 0x28, 0x0f, 0x65, 0xb9, 0xe3, + 0xff }, /* crtc_regs */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x13 no mode defined */ + {}, + /* index=0x14 no mode defined */ + {}, + /* index=0x15 no mode defined */ + {}, + /* index=0x16 no mode defined */ + {}, + /* index=0x17 vga mode 0x01 */ + { 40, 24, 16, 0x0800, /* tw, th-1, ch, slength */ + { 0x08, 0x03, 0x00, 0x02 }, /* sequ_regs */ + 0x67, /* miscreg */ + { 0x2d, 0x27, 0x28, 0x90, 0x29, 0x8e, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8d, 0x8f, 0x14, 0x1f, 0x97, 0xb9, 0xa3, + 0xff }, /* crtc_regs */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x0c, 0x00, 0x0f, 0x08 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff }, /* grdc_regs */ + }, + + /* index=0x18 vga mode 0x03 */ + { 80, 24, 16, 0x1000, /* tw, th-1, ch, slength */ + { 0x00, 0x03, 0x00, 0x02 }, /* sequ_regs */ + 0x67, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8d, 0x8f, 0x28, 0x1f, 0x97, 0xb9, 0xa3, + 0xff }, /* crtc_regs */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x0c, 0x00, 0x0f, 0x08 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff }, /* grdc_regs */ + }, + /* index=0x19 vga mode 0x07 */ + { 80, 24, 16, 0x1000, /* tw, th-1, ch, slength */ + { 0x00, 0x03, 0x00, 0x02 }, /* sequ_regs */ + 0x66, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f, + 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8d, 0x8f, 0x28, 0x0f, 0x97, 0xb9, 0xa3, + 0xff }, /* crtc_regs */ + { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x0e, 0x00, 0x0f, 0x08 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x1a vga mode 0x11 */ + { 80, 29, 16, 0x0000, /* tw, th-1, ch, slength */ + { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ + 0xe3, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, + 0xff }, /* crtc_regs */ + { 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, + 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, + 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x1b vga mode 0x12 */ + { 80, 29, 16, 0x0000, /* tw, th-1, ch, slength */ + { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ + 0xe3, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe9, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, + 0xff }, /* crtc_regs */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x1c vga mode 0x13 */ + { 40, 24, 8, 0x0000, /* tw, th-1, ch, slength */ + { 0x01, 0x0f, 0x00, 0x0e }, /* sequ_regs */ + 0x63, /* miscreg */ + { 0x5f, 0x4f, 0x50, 0x82, 0x51, 0x9e, 0xbf, 0x1f, + 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9b, 0x8d, 0x8f, 0x28, 0x40, 0x98, 0xb9, 0xa3, + 0xff }, /* crtc_regs */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x41, 0x00, 0x0f, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff }, /* grdc_regs */ + }, + /* index=0x1d vga mode 0x6a */ + { 100, 36, 16, 0x0000, /* tw, th-1, ch, slength */ + { 0x01, 0x0f, 0x00, 0x06 }, /* sequ_regs */ + 0xe3, /* miscreg */ + { 0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x59, 0x8d, 0x57, 0x32, 0x00, 0x57, 0x73, 0xe3, + 0xff }, /* crtc_regs */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x01, 0x00, 0x0f, 0x00 }, /* actl_regs */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */ + }, +}; + + + diff --git a/vgasrc/geodelx.h b/vgasrc/geodelx.h new file mode 100644 index 0000000..d825c87 --- /dev/null +++ b/vgasrc/geodelx.h @@ -0,0 +1,144 @@ +// Geode LX VGA functions +// +// Copyright (C) 2009 Chris Kindt +// +// Writen for Google Summer of Code 2009 for the coreboot project +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + + +#ifndef GEODELX_H +#define GEODELX_H + +#include "ioport.h" // outb +#include "farptr.h" // SET_FARVAR +#include "biosvar.h" // GET_BDA +#include "vgatables.h" // VGAREG_* +#include "util.h" // memset +#include "types.h" + +#define lxdprintf(lvl, fmt, args...) do { \ + if (DEBUG_GEODELX && (lvl) <= DEBUG_GEODELX) \ + __dprintf((fmt) , ##args ); \ + } while (0) + + +#define VRC_INDEX 0xAC1C // Index register +#define VRC_DATA 0xAC1E // Data register +#define VR_UNLOCK 0xFC53 // Virtual register unlock code + +#define EXTENDED_REGISTER_LOCK 0x30 +#define EXTENDED_MODE_CONTROL 0x43 +#define EXTENDED_START_ADDR 0x44 + +#define CRTCE_UNLOCK 0x4c +#define CRTCE_LOCK 0xff + +/* PCI */ +#define AMD_PCI_ID 0x1022 +#define LX_PCI_ID 0x2081 + +#define VENDOR_ID 0x00 +#define COMMAND 0x04 +#define IO_SPACE (1 << 0) +#define MEM_SPACE (1 << 1) +#define BUS_MASTER (1 << 2) +#define SPECIAL_CYCLES (1 << 3) +#define MEM_WR_INVALIDATE (1 << 4) +#define VGA_PALETTE_SNOOP (1 << 5) +#define PARITY_RESPONSE (1 << 6) +#define WAIT_CYCLE_CONTROL (1 << 7) +#define SERR_ENABLE (1 << 8) +#define FAST_BACK_TO_BACK (1 << 9) + +#define BAR0 0x10 +#define BAR1 0x14 +#define BAR2 0x18 +#define BAR3 0x1C +#define BAR4 0x20 +#define BAR5 0x24 +// Graphics-specific registers: +#define OEM_BAR0 0x50 +#define OEM_BAR1 0x54 +#define OEM_BAR2 0x58 +#define OEM_BAR3 0x5C + +#define LX_PCI_ADDR 0x80000900 +#define LX_PCI_CMD (LX_PCI_ADDR + 0x04) +#define LX_PCI_FB (LX_PCI_ADDR + 0x10) +#define LX_PCI_DC (LX_PCI_ADDR + 0x18) +#define LX_PCI_VP (LX_PCI_ADDR + 0x1c) + +#define DC_LOCK_LOCK 0x00000000 +#define DC_LOCK_UNLOCK 0x00004758 + +/* LX MSRs */ +#define MSR_GLIU0 (1 << 28) +#define MSR_GLIU0_BASE4 (MSR_GLIU0 + 0x23) +#define GLIU0_IOD_BM_0 (MSR_GLIU0 + 0xE0) +#define GLIU0_IOD_BM_1 (MSR_GLIU0 + 0xE1) +#define DC_SPARE 0x80000011 +#define VP_MSR_CONFIG 0x48002001 + +/* DC REG OFFSET */ +#define DC_UNLOCK 0x0 +#define DC_GENERAL_CFG 0x4 +#define DC_DISPLAY_CFG 0x8 +#define DC_ARB_CFG 0xc +#define DC_FB_ST_OFFSET 0x10 +#define DC_CB_ST_OFFSET 0x14 +#define DC_CURS_ST_OFFSET 0x18 +#define DC_GLIU0_MEM_OFFSET 0x84 + +/* VP REG OFFSET */ +#define VP_VCFG 0x0 +#define VP_DCFG 0x8 +#define VP_MISC 0x50 + + +/* DC bits */ +#define DC_VGAE (1 << 7) +#define DC_GDEN (1 << 3) +#define DC_TRUP (1 << 6) + +/* VP bits */ +#define VP_CRT_EN (1 << 0) +#define VP_HSYNC_EN (1 << 1) +#define VP_VSYNC_EN (1 << 2) +#define VP_DAC_BL_EN (1 << 3) +#define VP_CRT_SKEW (1 << 16) +#define VP_BYP_BOTH (1 << 0) + +/* Masks */ +#define VP_MSR_CFG_MSK 0x0 +#define DC_CFG_MSK 0xf000a6 + +extern struct VideoParam_s lx_video_param_table[]; +extern u8 geode_str[]; + +struct pci_data { + u32 signature; + u16 vendor; + u16 device; + u16 vitaldata; + u16 dlen; + u8 drevision; + u8 class_lo; + u16 class_hi; + u16 ilen; + u16 irevision; + u8 type; + u8 indicator; + u16 reserved; +} PACKED; + +#define PCI_ROM_SIGNATURE 0x52494350 // PCIR +#define PCIROM_CODETYPE_X86 0 +#define LAST_IMAGE 0x80 +#define PNP_SIGNATURE 0x506e5024 // $PnP + + +int geodelx_init(); +void geodelx_demo(); + +#endif diff --git a/vgasrc/vga.c b/vgasrc/vga.c index 88cbb01..3be0a1d 100644 --- a/vgasrc/vga.c +++ b/vgasrc/vga.c @@ -15,10 +15,12 @@ #include "biosvar.h" // GET_BDA #include "util.h" // memset #include "vgatables.h" // find_vga_entry +#include "geodelx.h"
// XXX #define CONFIG_VBE 0 #define CONFIG_CIRRUS 0 +#define CONFIG_GEODELX 0
// XXX #define DEBUG_VGA_POST 1 @@ -1362,6 +1364,9 @@ vga_post(struct bregs *regs)
vgahw_init();
+ if(CONFIG_GEODELX) + geodelx_init(); + init_bios_area();
if (CONFIG_VBE) @@ -1376,9 +1381,16 @@ vga_post(struct bregs *regs) // XXX - clear screen and display info
// XXX: fill it - SET_VGA(video_save_pointer_table[0], (u32)video_param_table); + if(CONFIG_GEODELX) + SET_VGA(video_save_pointer_table[0], (u32)lx_video_param_table); + else + SET_VGA(video_save_pointer_table[0], (u32)video_param_table); + SET_VGA(video_save_pointer_table[1], get_global_seg());
+ if(CONFIG_GEODELX) + geodelx_demo(); + // Fixup checksum extern u8 _rom_header_size, _rom_header_checksum; SET_VGA(_rom_header_checksum, 0); diff --git a/vgasrc/vgaentry.S b/vgasrc/vgaentry.S index 7802bdb..844ca3e 100644 --- a/vgasrc/vgaentry.S +++ b/vgasrc/vgaentry.S @@ -28,7 +28,26 @@ _rom_header_size: _rom_header_entry: jmp _optionrom_entry _rom_header_checksum: - .space 22 + +.ifdef _rom_pcidata + .org 0x18 + .word _rom_pcidata +.else + .space 20 +.endif + +.ifdef _rom_pnpdata + .org 0x1a + .word _rom_pnpdata +.else + .space 2 +.endif + +/* used by x */ +_rom_header_vga_magic: + .org 0x1e + .asciz "IBM VGA Compatible" +
/****************************************************************
diff --git a/vgasrc/vgatables.c b/vgasrc/vgatables.c index 0587e65..66ad3fc 100644 --- a/vgasrc/vgatables.c +++ b/vgasrc/vgatables.c @@ -380,7 +380,10 @@ static u8 palette3[] VAR16 = { ****************************************************************/
#define PAL(x) x, sizeof(x) -#define VPARAM(x) &video_param_table[x] + +extern struct VideoParam_s lx_video_param_table[]; +#define VPARAM(x) &lx_video_param_table[x] +//#define VPARAM(x) &video_param_table[x]
static struct vgamode_s vga_modes[] VAR16 = { //mode vparam model bits sstart pelm dac