#include <cursor.h>
#include "screen.h"
+extern VGAcur vgasoftcur;
+
Rectangle physgscreenr;
Memimage *gscreen;
VGAscr vgascreen[1];
-Cursor arrow = {
- { -1, -1 },
- { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
- 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
- 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
- 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
- },
- { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
- 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
- 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
- 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
- },
-};
-
int
screensize(int x, int y, int, ulong chan)
{
poperror();
drawcmap();
- swcursorinit();
qunlock(&drawlock);
poperror();
screenaperture(int size, int align)
{
VGAscr *scr;
+ ulong pa;
scr = &vgascreen[0];
* The driver will tell the card to use it.
*/
size = PGROUND(size);
- scr->paddr = upaalloc(size, align);
- if(scr->paddr == 0)
+ pa = upaalloc(-1, size, align);
+ if(pa == -1)
return -1;
- scr->vaddr = vmap(scr->paddr, size);
+ scr->paddr = pa;
+ scr->vaddr = vmap(pa, size);
if(scr->vaddr == nil)
return -1;
scr->apsize = size;
return 0;
}
-uchar*
+Memdata*
attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
{
VGAscr *scr;
*chan = scr->gscreen->chan;
*d = scr->gscreen->depth;
*width = scr->gscreen->width;
- if(scr->gscreendata->allocd){
- /*
- * we use a memimage as softscreen. devdraw will create its own
- * screen image on the backing store of that image. when our gscreen
- * and devdraws screenimage gets freed, the imagedata will
- * be released.
- */
- *softscreen = 0xa110c;
- scr->gscreendata->ref++;
- } else
- *softscreen = scr->useflush ? 1 : 0;
- return scr->gscreendata->bdata;
+ *softscreen = (scr->gscreendata->allocd || scr->useflush) ? 1 : 0;
+
+ scr->gscreendata->ref++;
+ return scr->gscreendata;
}
void
}
p &= x;
- lock(&cursor);
*pr = scr->colormap[p][0];
*pg = scr->colormap[p][1];
*pb = scr->colormap[p][2];
- unlock(&cursor);
}
int
scr = &vgascreen[0];
d = scr->palettedepth;
- lock(&cursor);
scr->colormap[p][0] = r;
scr->colormap[p][1] = g;
scr->colormap[p][2] = b;
vgao(Pdata, r>>(32-d));
vgao(Pdata, g>>(32-d));
vgao(Pdata, b>>(32-d));
- unlock(&cursor);
return ~0;
}
return setpalette(p, r, g, b);
}
-void
-swenable(VGAscr*)
-{
- swcursorload(&arrow);
-}
-
-void
-swdisable(VGAscr*)
-{
-}
-
-void
-swload(VGAscr*, Cursor *curs)
-{
- swcursorload(curs);
-}
-
-int
-swmove(VGAscr*, Point p)
-{
- swcursorhide();
- swcursordraw(p);
- return 0;
-}
-
-VGAcur swcursor =
-{
- "soft",
- swenable,
- swdisable,
- swload,
- swmove,
-};
-
-
void
cursoron(void)
{
scr = &vgascreen[0];
cur = scr->cur;
- if(cur == nil || cur->move == nil)
- return;
-
- if(cur == &swcursor)
- qlock(&drawlock);
- lock(&cursor);
- cur->move(scr, mousexy());
- unlock(&cursor);
- if(cur == &swcursor)
- qunlock(&drawlock);
+ if(cur && cur->move)
+ cur->move(scr, mousexy());
}
void
setcursor(Cursor* curs)
{
VGAscr *scr;
+ VGAcur *cur;
scr = &vgascreen[0];
- if(scr->cur == nil || scr->cur->load == nil)
- return;
-
- scr->cur->load(scr, curs);
+ cur = scr->cur;
+ if(cur && cur->load)
+ cur->load(scr, curs);
}
-int hwaccel = 1;
-int hwblank = 0; /* turned on by drivers that are known good */
+int hwaccel = 0;
+int hwblank = 0;
int panning = 0;
int
src = nil;
if((mask = par->mask) && mask->data == nil)
mask = nil;
- if(scr->cur == &swcursor){
+ if(scr->cur == &vgasoftcur){
if(dst->data->bdata == scrd->bdata)
swcursoravoid(par->r);
if(src && src->data->bdata == scrd->bdata)
if(mask && mask->data->bdata == scrd->bdata)
swcursoravoid(par->mr);
}
- if(hwaccel == 0)
+ if(!hwaccel || scr->softscreen)
return 0;
if(dst->data->bdata != scrd->bdata || src == nil || mask == nil)
return 0;
- if(scr->fill==nil && scr->scroll==nil)
- return 0;
/*
* If we have an opaque mask and source is one opaque
}
}
-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 == nil)
+ return "cannot map vga frame buffer";
+
+ patwc(scr->vaddr, nsize);
+
+ scr->vaddr = (char*)scr->vaddr+x;
+ scr->paddr = paddr;
+ scr->apsize = nsize;
+
+ mtrr(npaddr, nsize, "wc");
+
+ 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.
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;
+
+ 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);
+ }
+ }
+ }
+ upaalloc(pa, sz, 0);
+ return vgalinearaddr0(scr, pa, sz);
+}
- /* let mtrr harmlessly fail on old CPUs, e.g., P54C */
- if(!waserror()){
- mtrr(npaddr, nsize, "wc");
- poperror();
+char*
+rgbmask2chan(char *buf, int depth, u32int rm, u32int gm, u32int bm)
+{
+ u32int m[4], dm; /* r,g,b,x */
+ char tmp[32];
+ int c, n;
+
+ dm = 1<<depth-1;
+ dm |= dm-1;
+
+ m[0] = rm & dm;
+ m[1] = gm & dm;
+ m[2] = bm & dm;
+ m[3] = (~(m[0] | m[1] | m[2])) & dm;
+
+ buf[0] = 0;
+Next:
+ for(c=0; c<4; c++){
+ for(n = 0; m[c] & (1<<n); n++)
+ ;
+ if(n){
+ m[0] >>= n, m[1] >>= n, m[2] >>= n, m[3] >>= n;
+ snprint(tmp, sizeof tmp, "%c%d%s", "rgbx"[c], n, buf);
+ strcpy(buf, tmp);
+ goto Next;
+ }
}
+ return buf;
}
/*
* called early on boot to attach to framebuffer
- * setup by bootloader or firmware.
+ * setup by bootloader/firmware or plan9.
*/
void
bootscreeninit(void)
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");
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;
scr->useflush = 0;
scr->dev = nil;
- hwblank = 0;
- hwaccel = 0;
-
physgscreenr = gscreen->r;
vgaimageinit(chan);
vgascreenwin(scr);
- /* turn mouse cursor on */
- swcursorinit();
- scr->cur = &swcursor;
+ scr->cur = &vgasoftcur;
scr->cur->enable(scr);
- cursoron();
+
+ conf.monitor = 1;
+}
+
+/*
+ * called from devvga when the framebuffer is setup
+ * to set *bootscreen= that can be passed on to a
+ * new kernel on reboot.
+ */
+void
+bootscreenconf(VGAscr *scr)
+{
+ char conf[100], chan[30];
+
+ conf[0] = '\0';
+ if(scr != nil && scr->paddr != 0 && scr->gscreen != nil)
+ snprint(conf, sizeof(conf), "%dx%dx%d %s %#p %d\n",
+ scr->gscreen->r.max.x, scr->gscreen->r.max.y,
+ scr->gscreen->depth, chantostr(chan, scr->gscreen->chan),
+ scr->paddr, scr->apsize);
+ ksetenv("*bootscreen", conf, 1);
}