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 #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) + buf = mallocalign(64*64*4, BY2PG, 0, 0); + if(buf == nil){ + print("igfx: no memory for cursor image\n"); return 0; - gtt = (u32int*)((uchar*)mmio + pci->mem[0].size/2); - if((gtt[0]&1) == 0) - return 0; - x = (gtt[0]>>12)+1; - for(i=1; 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); papsize){ 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(; ictlr->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);