--- xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c.orig Wed Jan 9 05:59:29 2002 +++ xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c Wed Sep 4 10:51:58 2002 @@ -87,6 +87,8 @@ * switched VT's */ +#include + #include "xf86.h" #include "xf86_ansic.h" #include "xf86_OSproc.h" @@ -145,6 +147,7 @@ static void I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); +static void I830StolenMemoryHack (ScrnInfoPtr pScrn); #ifdef I830DEBUG void DPRINTF_stub (const char *filename,int line,const char *function,const char *fmt, ...) { @@ -476,33 +479,32 @@ static int I830DetectMemory (ScrnInfoPtr pScrn) { - I810Ptr pI810; - VESAPtr pVesa; - PCITAG bridge; - CARD16 gmch_ctrl; - int memsize; - - pI810 = I810PTR (pScrn); - pVesa = pI810->vesa; - - bridge = pciTag (0,0,0); /* This is always the host bridge */ - gmch_ctrl = pciReadWord (bridge,I830_GMCH_CTRL); - - switch (gmch_ctrl & I830_GMCH_GMS_MASK) - { - case I830_GMCH_GMS_STOLEN_512: - memsize = KB (512); + I810Ptr pI810; + VESAPtr pVesa; + PCITAG bridge; + CARD16 gmch_ctrl; + int memsize; + + pI810 = I810PTR (pScrn); + pVesa = pI810->vesa; + + bridge = pciTag (0,0,0); /* This is always the host bridge */ + gmch_ctrl = pciReadWord (bridge,I830_GMCH_CTRL); + + switch (gmch_ctrl & I830_GMCH_GMS_MASK) { + case I830_GMCH_GMS_STOLEN_512: + memsize = KB (512) - KB (132); xf86DrvMsg (pScrn->scrnIndex,X_INFO,"detected %dK stolen memory.\n",memsize / 1024); break; - case I830_GMCH_GMS_STOLEN_1024: - memsize = MB (1); + case I830_GMCH_GMS_STOLEN_1024: + memsize = MB (1) - KB (132); xf86DrvMsg (pScrn->scrnIndex,X_INFO,"detected %dK stolen memory.\n",memsize / 1024); break; - case I830_GMCH_GMS_STOLEN_8192: - memsize = MB (8); + case I830_GMCH_GMS_STOLEN_8192: + memsize = MB (8) - KB (132); xf86DrvMsg (pScrn->scrnIndex,X_INFO,"detected %dK stolen memory.\n",memsize / 1024); break; - case I830_GMCH_GMS_LOCAL: + case I830_GMCH_GMS_LOCAL: /* I'd like to use the VGA controller registers here, but MMIOBase isn't * yet, so for now, we'll just use the BIOS instead... */ pVesa->pInt->num = 0x10; @@ -511,13 +513,13 @@ memsize = pVesa->pInt->cx * KB (1); xf86DrvMsg (pScrn->scrnIndex,X_INFO,"detected %dK local memory.\n",memsize / 1024); break; - default: + default: /* not that this is possible, but anyway (: */ memsize = 0; xf86DrvMsg (pScrn->scrnIndex,X_INFO,"no video memory detected.\n"); - } + } - return (memsize); + return (memsize); } Bool I830BIOSPreInit (ScrnInfoPtr pScrn,int flags) @@ -743,6 +745,8 @@ xf86DrvMsg (pScrn->scrnIndex,from,"Will alloc AGP framebuffer: %d kByte\n",pScrn->videoRam); + I830StolenMemoryHack (pScrn); + /* * If the driver can do gamma correction, it should call xf86SetGamma() here. */ @@ -1474,13 +1478,12 @@ /* At the moment some of the BIOS vesa mode sets doesn't seem to work, so * we set those modes using the legacy BIOS calls */ -Bool I830VESASetVBEMode (ScrnInfoPtr pScrn,int mode,CRTCInfoBlock *block) -{ - I810Ptr pI810; - VESAPtr pVesa; +Bool I830VESASetVBEMode (ScrnInfoPtr pScrn,int mode,CRTCInfoBlock *block) { + I810Ptr pI810; + VESAPtr pVesa; - pI810 = I810PTR (pScrn); - pVesa = pI810->vesa; + pI810 = I810PTR (pScrn); + pVesa = pI810->vesa; DPRINTF(PFX,"Setting mode 0x%.8x\n",mode); @@ -1503,7 +1506,6 @@ default: pVesa->pInt->ax = 0x4f02; pVesa->pInt->bx = mode & ~(1 << 11); -/* This doesn't work. The BIOS is f**cked */ #if 0 if (block != NULL) { @@ -2517,3 +2519,51 @@ return (*pScreen->CloseScreen)(scrnIndex, pScreen); } +/* Magic bit swiveling to enable high resolution with 16bpp in BIOSes that + * preallocate only 1MB of video memory. + */ +static void +I830StolenMemoryHack (ScrnInfoPtr pScrn) +{ + I810Ptr pI810; + unsigned long swf1; + int devmem; + char *MMIOBase; + + pI810 = I810PTR (pScrn); + + if (pI810->StolenSize < MB (8) - KB (132)) { + + if ((devmem = open ("/dev/mem", O_RDWR)) < 0) { + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, + "Cannot open /dev/mem: " + "resolution limited by 1MB video RAM\n"); + return; + } + + MMIOBase = (char *) mmap (NULL, I810_REG_SIZE, + PROT_READ | PROT_WRITE, MAP_SHARED, + devmem, (off_t) pI810->MMIOAddr); + + if (MMIOBase == (char *) -1) { + close (devmem); + xf86DrvMsg (pScrn->scrnIndex, X_WARNING, + "Cannot mmap IO registers: " + "resolution limited by 1MB video RAM\n"); + return; + } + + swf1 = *((unsigned long *) (MMIOBase + 0x71414)); + DPRINTF (PFX, "SWF1[before] == 0x%.8x\n", swf1); + swf1 &= ~0xf; + swf1 |= 8; + *((unsigned long *) (MMIOBase + 0x71414)) = swf1; + DPRINTF (PFX, "SWF1[after ] == 0x%.8x\n", swf1); + + munmap (MMIOBase, I810_REG_SIZE); + close (devmem); + + xf86DrvMsg (pScrn->scrnIndex, X_INFO, "1MB stolen memory hack enabled\n"); + + } +}