summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/9/pc/vgaigfx.c82
-rw-r--r--sys/src/cmd/aux/vga/igfx.c73
2 files changed, 87 insertions, 68 deletions
diff --git a/sys/src/9/pc/vgaigfx.c b/sys/src/9/pc/vgaigfx.c
index c0f3037b3..baaee2564 100644
--- a/sys/src/9/pc/vgaigfx.c
+++ b/sys/src/9/pc/vgaigfx.c
@@ -12,72 +12,24 @@
#include <cursor.h>
#include "screen.h"
-static ulong
-stolenmb(Pcidev *p)
-{
- switch(p->did){
- case 0x0412: /* Haswell HD Graphics 4600 */
- case 0x0a16: /* Haswell HD Graphics 4400 */
- case 0x0126: /* Sandy Bridge HD Graphics 3000 */
- case 0x0166: /* Ivy Bridge */
- case 0x0102: /* Core-5 Sandy Bridge */
- case 0x0152: /* Core-i3 */
- switch((pcicfgr16(p, 0x50) >> 3) & 0x1f){
- case 0x01: return 32 - 2;
- case 0x02: return 64 - 2; /* 0102 Dell machine here */
- case 0x03: return 96 - 2;
- case 0x04: return 128 - 2;
- case 0x05: return 32 - 2;
- case 0x06: return 48 - 2;
- case 0x07: return 64 - 2;
- case 0x08: return 128 - 2;
- case 0x09: return 256 - 2;
- case 0x0A: return 96 - 2;
- case 0x0B: return 160 - 2;
- case 0x0C: return 224 - 2;
- case 0x0D: return 352 - 2;
- case 0x0E: return 448 - 2;
- case 0x0F: return 480 - 2;
- case 0x10: return 512 - 2;
- }
- break;
- case 0x2a42: /* X200 */
- case 0x29a2: /* 82P965/G965 HECI desktop */
- case 0x2a02: /* CF-R7 */
- switch((pcicfgr16(p, 0x52) >> 4) & 7){
- case 0x01: return 1;
- case 0x02: return 4;
- case 0x03: return 8;
- case 0x04: return 16;
- case 0x05: return 32;
- case 0x06: return 48;
- case 0x07: return 64;
- }
- break;
- }
- return 0;
-}
-
static uintptr
-gmsize(Pcidev *pci, void *mmio)
+igfxcuralloc(Pcidev *pci, void *mmio, int apsize)
{
- u32int x, i, npg, *gtt;
+ int n;
+ u32int pa, *buf, *p, *e;
- npg = stolenmb(pci)<<(20-12);
- if(npg == 0)
- return 0;
- gtt = (u32int*)((uchar*)mmio + pci->mem[0].size/2);
- if((gtt[0]&1) == 0)
+ buf = mallocalign(64*64*4, BY2PG, 0, 0);
+ if(buf == nil){
+ print("igfx: no memory for cursor image\n");
return 0;
- x = (gtt[0]>>12)+1;
- for(i=1; i<npg; i++){
- if((gtt[i]&1) == 0 || (gtt[i]>>12) != x)
- break;
- x++;
}
- if(0) print("igfx: graphics memory at %p-%p (%ud MB)\n",
- (uintptr)(x-i)<<12, (uintptr)x<<12, (i>>(20-12)));
- return (uintptr)i<<12;
+ n = (apsize > 128*MB ? 128*1024 : apsize/1024) / 4 - 4;
+ p = (u32int*)((uchar*)mmio + pci->mem[0].size/2) + n;
+ *(u32int*)((uchar*)mmio + 0x2170) = 0; /* flush write buffers */
+ for(e=p+4, pa=PADDR(buf); p<e; p++, pa+=1<<12)
+ *p = pa | 1;
+ *(u32int*)((uchar*)mmio + 0x2170) = 0; /* flush write buffers */
+ return (uintptr)n << 12;
}
static void
@@ -98,13 +50,7 @@ igfxenable(VGAscr* scr)
vgalinearpci(scr);
if(scr->apsize){
addvgaseg("igfxscreen", scr->paddr, scr->apsize);
- scr->storage = gmsize(p, scr->mmio);
- if(scr->storage < MB)
- scr->storage = 0;
- else if(scr->storage > scr->apsize)
- scr->storage = scr->apsize;
- if(scr->storage != 0)
- scr->storage -= PGROUND(64*64*4);
+ scr->storage = igfxcuralloc(p, scr->mmio, scr->apsize);
}
scr->softscreen = 1;
}
diff --git a/sys/src/cmd/aux/vga/igfx.c b/sys/src/cmd/aux/vga/igfx.c
index cc595c132..48a2a363e 100644
--- a/sys/src/cmd/aux/vga/igfx.c
+++ b/sys/src/cmd/aux/vga/igfx.c
@@ -1593,6 +1593,76 @@ disablepipe(Igfx *igfx, int x)
csr(igfx, igfx->dpllsel[0].a, 8<<(x*4), 0);
}
+void
+checkgtt(Igfx *igfx, Mode *m)
+{
+ int fd, c;
+ ulong n;
+ char buf[64], *fl[5];
+ u32int i, j, pa, nilpte, *gtt;
+
+ if(igfx->mmio == nil)
+ return;
+ gtt = (u32int*)((uchar*)igfx->mmio + igfx->pci->mem[0].size/2);
+ pa = (gtt[0] & ~((1<<12)-1)) + (1<<12) | 1;
+ for(i=1; i<64*1024/4-4; i++, pa+=1<<12)
+ if((gtt[i] & ~((1<<11)-1<<1)) != pa)
+ break;
+ n = m->x * m->y * m->z / 8;
+ if(i<<12 >= n)
+ return;
+
+ /* unmap pages past stolen memory */
+ nilpte = gtt[64*1024/4-5];
+ wr(igfx, 0x2170, 0); /* flush write buffers */
+ for(j=i; j<64*1024/4-5; j++){
+ if((gtt[j] & 1) == 0 || (gtt[j] & ~((1<<11)-1<<1)) == pa)
+ break;
+ pa = gtt[j];
+ gtt[j] = nilpte;
+ }
+ wr(igfx, 0x2170, 0); /* flush write buffers */
+
+ trace("%s: mapping %lud additional bytes for requested mode\n", igfx->ctlr->name, n - (i<<12));
+ snprint(buf, sizeof buf, "#g/igfxtra");
+ if((fd = open(buf, OREAD)) >= 0){
+ close(fd);
+ if(remove(buf) < 0)
+ goto err;
+ }
+ if((fd = create(buf, OREAD, DMDIR|0777)) < 0)
+ goto err;
+ close(fd);
+ strncat(buf, "/ctl", sizeof(buf)-strlen("/ctl"));
+ if((fd = open(buf, ORDWR|OTRUNC)) < 0)
+ goto err;
+ snprint(buf, sizeof buf, "va 0x10000000 %#lux fixed", n - (i<<12));
+ if(write(fd, buf, strlen(buf)) < 0){
+ close(fd);
+ goto err;
+ }
+ seek(fd, 0, 0);
+ if((c = read(fd, buf, sizeof buf)) <= 0){
+ close(fd);
+ goto err;
+ }
+ close(fd);
+ buf[c-1] = 0;
+ if(getfields(buf, fl, nelem(fl), 0, " ") != nelem(fl)
+ || (pa = strtoul(fl[4], nil, 16)) == 0){
+ werrstr("invalid physical base address");
+ goto err;
+ }
+ n >>= 12;
+ wr(igfx, 0x2170, 0); /* flush write buffers */
+ for(; i<n; i++, pa+=1<<12)
+ gtt[i] = pa | 1;
+ wr(igfx, 0x2170, 0); /* flush write buffers */
+ return;
+err:
+ trace("%s: checkgtt: %r\n", igfx->ctlr->name);
+}
+
static void
load(Vga* vga, Ctlr* ctlr)
{
@@ -1638,6 +1708,9 @@ load(Vga* vga, Ctlr* ctlr)
for(x = 0; x < igfx->npipe; x++)
disablepipe(igfx, x);
+ /* check if enough memory has been mapped for requested mode */
+ checkgtt(igfx, vga->mode);
+
if(igfx->type == TypeG45){
/* toggle dsp a on and off (from enable sequence) */
csr(igfx, igfx->pipe[0].conf.a, 3<<18, 0);