From patchwork Sat Aug 15 04:23:10 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Geode LX VGA BIOS Patch Date: Sat, 15 Aug 2009 04:23:10 -0000 From: Chris Kindt X-Patchwork-Id: 128 Message-Id: <4A86382E.80106@umbc.edu> To: coreboot@coreboot.org Updated Patch: seabios-vgarom-geodelx-v2.patch -added clobber list to VSA2 functions -converted _rom_pci data to c structure -replaced asm int10 with direct call -unset CONFIG_GEODELX Signed-off-by: Chris Kindt diff --git a/Makefile b/Makefile index 2b8d0d2..71e6db2 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..a11909b --- /dev/null +++ b/vgasrc/geodelx.c @@ -0,0 +1,570 @@ +// 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. + +#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 Controler 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 contoller) portion of the geodelx +* The dc proivides harware support for VGA graphics +* for features not accessiable from the VGA registers, +* the dc's pci bar can be maped 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 avaliable 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); + return 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