ref: bcc65db171bea6617ab7872342d543e50b09ca63
parent: d7785060fb66c9c4fc19475668bd861fb6462941
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Oct 19 17:00:34 EDT 2014
pc, pc64: lookup pci device for bootscreen() and maximize framebuffer aperture so can change screen resolution
--- a/sys/src/9/pc/screen.c
+++ b/sys/src/9/pc/screen.c
@@ -472,16 +472,65 @@
}
}
-void
-vgalinearpci(VGAscr *scr)
+static char*
+vgalinearaddr0(VGAscr *scr, ulong paddr, int size)
{
+ int x, nsize;
+ ulong npaddr;
+
+ /*
+ * new approach. instead of trying to resize this
+ * later, let's assume that we can just allocate the
+ * entire window to start with.
+ */
+ if(scr->paddr == paddr && size <= scr->apsize)
+ return nil;
+
+ if(scr->paddr){
+ /*
+ * could call vunmap and vmap,
+ * but worried about dangling pointers in devdraw
+ */
+ return "cannot grow vga frame buffer";
+ }
+
+ /* round to page boundary, just in case */
+ x = paddr&(BY2PG-1);
+ npaddr = paddr-x;
+ nsize = PGROUND(size+x);
+
+ /*
+ * Don't bother trying to map more than 4000x4000x32 = 64MB.
+ * We only have a 256MB window.
+ */
+ if(nsize > 64*MB)
+ nsize = 64*MB;
+ scr->vaddr = vmap(npaddr, nsize);
+ if(scr->vaddr == 0)
+ return "cannot allocate vga frame buffer";
+ scr->vaddr = (char*)scr->vaddr+x;
+ scr->paddr = paddr;
+ scr->apsize = nsize;
+
+ if(up != nil){
+ /* let mtrr harmlessly fail on old CPUs, e.g., P54C */
+ if(!waserror()){
+ mtrr(npaddr, nsize, "wc");
+ poperror();
+ }
+ }
+
+ return nil;
+}
+
+static char*
+vgalinearpci0(VGAscr *scr)
+{
ulong paddr;
int i, size, best;
Pcidev *p;
p = scr->pci;
- if(p == nil)
- return;
/*
* Scan for largest memory region on card.
@@ -510,57 +559,51 @@
if(best >= 0){
paddr = p->mem[best].bar & ~0x0F;
size = p->mem[best].size;
- vgalinearaddr(scr, paddr, size);
- return;
+ return vgalinearaddr0(scr, paddr, size);
}
- error("no video memory found on pci card");
+ return "no video memory found on pci card";
}
void
-vgalinearaddr(VGAscr *scr, ulong paddr, int size)
+vgalinearpci(VGAscr *scr)
{
- int x, nsize;
- ulong npaddr;
+ char *err;
- /*
- * new approach. instead of trying to resize this
- * later, let's assume that we can just allocate the
- * entire window to start with.
- */
- if(scr->paddr == paddr && size <= scr->apsize)
+ if(scr->pci == nil)
return;
+ if((err = vgalinearpci0(scr)) != nil)
+ error(err);
+}
- if(scr->paddr){
- /*
- * could call vunmap and vmap,
- * but worried about dangling pointers in devdraw
- */
- error("cannot grow vga frame buffer");
- }
+void
+vgalinearaddr(VGAscr *scr, ulong paddr, int size)
+{
+ char *err;
- /* round to page boundary, just in case */
- x = paddr&(BY2PG-1);
- npaddr = paddr-x;
- nsize = PGROUND(size+x);
+ if((err = vgalinearaddr0(scr, paddr, size)) != nil)
+ error(err);
+}
- /*
- * Don't bother trying to map more than 4000x4000x32 = 64MB.
- * We only have a 256MB window.
- */
- if(nsize > 64*MB)
- nsize = 64*MB;
- scr->vaddr = vmap(npaddr, nsize);
- if(scr->vaddr == 0)
- error("cannot allocate vga frame buffer");
- scr->vaddr = (char*)scr->vaddr+x;
- scr->paddr = paddr;
- scr->apsize = nsize;
+static char*
+bootmapfb(VGAscr *scr, ulong pa, ulong sz)
+{
+ ulong start, end;
+ Pcidev *p;
+ int i;
- /* let mtrr harmlessly fail on old CPUs, e.g., P54C */
- if(!waserror()){
- mtrr(npaddr, nsize, "wc");
- poperror();
+ for(p = pcimatch(nil, 0, 0); p != nil; p = pcimatch(p, 0, 0)){
+ for(i=0; i<nelem(p->mem); i++){
+ if(p->mem[i].bar & 1)
+ continue;
+ start = p->mem[i].bar & ~0xF;
+ end = start + p->mem[i].size;
+ if(pa == start && (pa + sz) <= end){
+ scr->pci = p;
+ return vgalinearpci0(scr);
+ }
+ }
}
+ return vgalinearaddr0(scr, pa, sz);
}
/*
@@ -574,7 +617,7 @@
VGAscr *scr;
int x, y, z;
ulong chan, pa, sz;
- char *s, *p;
+ char *s, *p, *err;
/* *bootscreen=WIDTHxHEIGHTxDEPTH CHAN PA [SZ] */
s = getconf("*bootscreen");
@@ -609,21 +652,12 @@
if(sz < x * y * (z+7)/8)
sz = x * y * (z+7)/8;
- /* round to pages */
- z = pa&(BY2PG-1);
- pa -= z;
- sz += z;
-
/* map framebuffer */
scr = &vgascreen[0];
- scr->apsize = PGROUND(sz);
- scr->vaddr = vmap(pa, scr->apsize);
- if(scr->vaddr == 0){
- scr->apsize = 0;
+ if((err = bootmapfb(scr, pa, sz)) != nil){
+ print("bootmapfb: %s\n", err);
return;
}
- scr->vaddr = (char*)scr->vaddr + z;
- scr->paddr = pa + z;
if(memimageinit() < 0)
return;