17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "io.h"
77dd7cddfSDavid du Colombier #include "ureg.h"
87dd7cddfSDavid du Colombier #include "../port/error.h"
97dd7cddfSDavid du Colombier
107dd7cddfSDavid du Colombier #define Image IMAGE
117dd7cddfSDavid du Colombier #include <draw.h>
127dd7cddfSDavid du Colombier #include <memdraw.h>
137dd7cddfSDavid du Colombier #include <cursor.h>
147dd7cddfSDavid du Colombier #include "screen.h"
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19)
177dd7cddfSDavid du Colombier
187dd7cddfSDavid du Colombier Point ZP = {0, 0};
197dd7cddfSDavid du Colombier
207dd7cddfSDavid du Colombier Rectangle physgscreenr;
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier Memdata gscreendata;
237dd7cddfSDavid du Colombier Memimage *gscreen;
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier VGAscr vgascreen[1];
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier Cursor arrow = {
287dd7cddfSDavid du Colombier { -1, -1 },
297dd7cddfSDavid du Colombier { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
307dd7cddfSDavid du Colombier 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
317dd7cddfSDavid du Colombier 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
327dd7cddfSDavid du Colombier 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
337dd7cddfSDavid du Colombier },
347dd7cddfSDavid du Colombier { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
357dd7cddfSDavid du Colombier 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
367dd7cddfSDavid du Colombier 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
377dd7cddfSDavid du Colombier 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
387dd7cddfSDavid du Colombier },
397dd7cddfSDavid du Colombier };
407dd7cddfSDavid du Colombier
414de34a7eSDavid du Colombier int didswcursorinit;
424de34a7eSDavid du Colombier
43*cb8c047aSDavid du Colombier static void *softscreen;
44*cb8c047aSDavid du Colombier
457dd7cddfSDavid du Colombier int
screensize(int x,int y,int z,ulong chan)467dd7cddfSDavid du Colombier screensize(int x, int y, int z, ulong chan)
477dd7cddfSDavid du Colombier {
487dd7cddfSDavid du Colombier VGAscr *scr;
49*cb8c047aSDavid du Colombier void *oldsoft;
507dd7cddfSDavid du Colombier
514de34a7eSDavid du Colombier lock(&vgascreenlock);
52*cb8c047aSDavid du Colombier if(waserror()){
53*cb8c047aSDavid du Colombier unlock(&vgascreenlock);
54*cb8c047aSDavid du Colombier nexterror();
55*cb8c047aSDavid du Colombier }
56*cb8c047aSDavid du Colombier
577dd7cddfSDavid du Colombier memimageinit();
587dd7cddfSDavid du Colombier scr = &vgascreen[0];
59*cb8c047aSDavid du Colombier oldsoft = softscreen;
607dd7cddfSDavid du Colombier
614de34a7eSDavid du Colombier if(scr->paddr == 0){
627dd7cddfSDavid du Colombier int width = (x*z)/BI2WD;
63*cb8c047aSDavid du Colombier void *p;
647dd7cddfSDavid du Colombier
65*cb8c047aSDavid du Colombier p = xalloc(width*BY2WD*y);
66*cb8c047aSDavid du Colombier if(p == nil)
67*cb8c047aSDavid du Colombier error("no memory for vga soft screen");
68*cb8c047aSDavid du Colombier gscreendata.bdata = softscreen = p;
69*cb8c047aSDavid du Colombier if(scr->dev && scr->dev->page){
70*cb8c047aSDavid du Colombier scr->vaddr = KADDR(VGAMEM());
717dd7cddfSDavid du Colombier scr->apsize = 1<<16;
727dd7cddfSDavid du Colombier }
73*cb8c047aSDavid du Colombier scr->useflush = 1;
74*cb8c047aSDavid du Colombier }
75*cb8c047aSDavid du Colombier else{
764de34a7eSDavid du Colombier gscreendata.bdata = scr->vaddr;
77*cb8c047aSDavid du Colombier scr->useflush = scr->dev && scr->dev->flush;
784de34a7eSDavid du Colombier }
797dd7cddfSDavid du Colombier
80*cb8c047aSDavid du Colombier scr->gscreen = nil;
81*cb8c047aSDavid du Colombier if(gscreen)
82*cb8c047aSDavid du Colombier freememimage(gscreen);
83*cb8c047aSDavid du Colombier gscreen = allocmemimaged(Rect(0,0,x,y), chan, &gscreendata);
84*cb8c047aSDavid du Colombier if(gscreen == nil)
85*cb8c047aSDavid du Colombier error("no memory for vga memimage");
86*cb8c047aSDavid du Colombier vgaimageinit(chan);
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier scr->palettedepth = 6; /* default */
897dd7cddfSDavid du Colombier scr->gscreendata = &gscreendata;
907dd7cddfSDavid du Colombier scr->memdefont = getmemdefont();
917dd7cddfSDavid du Colombier scr->gscreen = gscreen;
927dd7cddfSDavid du Colombier
937dd7cddfSDavid du Colombier physgscreenr = gscreen->r;
944de34a7eSDavid du Colombier unlock(&vgascreenlock);
95*cb8c047aSDavid du Colombier poperror();
96*cb8c047aSDavid du Colombier if(oldsoft)
97*cb8c047aSDavid du Colombier xfree(oldsoft);
98*cb8c047aSDavid du Colombier
99*cb8c047aSDavid du Colombier memimagedraw(gscreen, gscreen->r, memblack, ZP, nil, ZP, S);
100*cb8c047aSDavid du Colombier flushmemscreen(gscreen->r);
1017dd7cddfSDavid du Colombier
1024de34a7eSDavid du Colombier if(didswcursorinit)
1034de34a7eSDavid du Colombier swcursorinit();
1047dd7cddfSDavid du Colombier drawcmap();
1057dd7cddfSDavid du Colombier return 0;
1067dd7cddfSDavid du Colombier }
1077dd7cddfSDavid du Colombier
1087dd7cddfSDavid du Colombier int
screenaperture(int size,int align)1097dd7cddfSDavid du Colombier screenaperture(int size, int align)
1107dd7cddfSDavid du Colombier {
1117dd7cddfSDavid du Colombier VGAscr *scr;
1127dd7cddfSDavid du Colombier
1137dd7cddfSDavid du Colombier scr = &vgascreen[0];
1147dd7cddfSDavid du Colombier
1154de34a7eSDavid du Colombier if(scr->paddr) /* set up during enable */
1164de34a7eSDavid du Colombier return 0;
1174de34a7eSDavid du Colombier
1184de34a7eSDavid du Colombier if(size == 0)
1194de34a7eSDavid du Colombier return 0;
1204de34a7eSDavid du Colombier
1214de34a7eSDavid du Colombier if(scr->dev && scr->dev->linear){
1224de34a7eSDavid du Colombier scr->dev->linear(scr, size, align);
1237dd7cddfSDavid du Colombier return 0;
1247dd7cddfSDavid du Colombier }
1257dd7cddfSDavid du Colombier
1264de34a7eSDavid du Colombier /*
1274de34a7eSDavid du Colombier * Need to allocate some physical address space.
1284de34a7eSDavid du Colombier * The driver will tell the card to use it.
1294de34a7eSDavid du Colombier */
1304de34a7eSDavid du Colombier size = PGROUND(size);
1314de34a7eSDavid du Colombier scr->paddr = upaalloc(size, align);
1324de34a7eSDavid du Colombier if(scr->paddr == 0)
1334de34a7eSDavid du Colombier return -1;
1344de34a7eSDavid du Colombier scr->vaddr = vmap(scr->paddr, size);
1354de34a7eSDavid du Colombier if(scr->vaddr == nil)
1364de34a7eSDavid du Colombier return -1;
1377dd7cddfSDavid du Colombier scr->apsize = size;
1387dd7cddfSDavid du Colombier
1397dd7cddfSDavid du Colombier return 0;
1407dd7cddfSDavid du Colombier }
1417dd7cddfSDavid du Colombier
1427dd7cddfSDavid du Colombier uchar*
attachscreen(Rectangle * r,ulong * chan,int * d,int * width,int * softscreen)1437dd7cddfSDavid du Colombier attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
1447dd7cddfSDavid du Colombier {
1457dd7cddfSDavid du Colombier VGAscr *scr;
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier scr = &vgascreen[0];
1487dd7cddfSDavid du Colombier if(scr->gscreen == nil || scr->gscreendata == nil)
1497dd7cddfSDavid du Colombier return nil;
1507dd7cddfSDavid du Colombier
1519a747e4fSDavid du Colombier *r = scr->gscreen->clipr;
1527dd7cddfSDavid du Colombier *chan = scr->gscreen->chan;
1537dd7cddfSDavid du Colombier *d = scr->gscreen->depth;
1547dd7cddfSDavid du Colombier *width = scr->gscreen->width;
1557dd7cddfSDavid du Colombier *softscreen = scr->useflush;
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier return scr->gscreendata->bdata;
1587dd7cddfSDavid du Colombier }
1597dd7cddfSDavid du Colombier
1607dd7cddfSDavid du Colombier /*
1617dd7cddfSDavid du Colombier * It would be fair to say that this doesn't work for >8-bit screens.
1627dd7cddfSDavid du Colombier */
1637dd7cddfSDavid du Colombier void
flushmemscreen(Rectangle r)1647dd7cddfSDavid du Colombier flushmemscreen(Rectangle r)
1657dd7cddfSDavid du Colombier {
1667dd7cddfSDavid du Colombier VGAscr *scr;
1677dd7cddfSDavid du Colombier uchar *sp, *disp, *sdisp, *edisp;
1687dd7cddfSDavid du Colombier int y, len, incs, off, page;
1697dd7cddfSDavid du Colombier
1707dd7cddfSDavid du Colombier scr = &vgascreen[0];
1719a747e4fSDavid du Colombier if(scr->dev && scr->dev->flush){
1729a747e4fSDavid du Colombier scr->dev->flush(scr, r);
1739a747e4fSDavid du Colombier return;
1749a747e4fSDavid du Colombier }
1757dd7cddfSDavid du Colombier if(scr->gscreen == nil || scr->useflush == 0)
1767dd7cddfSDavid du Colombier return;
1777dd7cddfSDavid du Colombier if(scr->dev == nil || scr->dev->page == nil)
1787dd7cddfSDavid du Colombier return;
1797dd7cddfSDavid du Colombier
1807dd7cddfSDavid du Colombier if(rectclip(&r, scr->gscreen->r) == 0)
1817dd7cddfSDavid du Colombier return;
1827dd7cddfSDavid du Colombier
1837dd7cddfSDavid du Colombier incs = scr->gscreen->width * BY2WD;
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier switch(scr->gscreen->depth){
1867dd7cddfSDavid du Colombier default:
1877dd7cddfSDavid du Colombier len = 0;
1887dd7cddfSDavid du Colombier panic("flushmemscreen: depth\n");
1897dd7cddfSDavid du Colombier break;
1907dd7cddfSDavid du Colombier case 8:
1917dd7cddfSDavid du Colombier len = Dx(r);
1927dd7cddfSDavid du Colombier break;
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier if(len < 1)
1957dd7cddfSDavid du Colombier return;
1967dd7cddfSDavid du Colombier
1977dd7cddfSDavid du Colombier off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
1987dd7cddfSDavid du Colombier page = off/scr->apsize;
1997dd7cddfSDavid du Colombier off %= scr->apsize;
2004de34a7eSDavid du Colombier disp = scr->vaddr;
2017dd7cddfSDavid du Colombier sdisp = disp+off;
2027dd7cddfSDavid du Colombier edisp = disp+scr->apsize;
2037dd7cddfSDavid du Colombier
2047dd7cddfSDavid du Colombier off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x*scr->gscreen->depth)/8;
2057dd7cddfSDavid du Colombier
2067dd7cddfSDavid du Colombier sp = scr->gscreendata->bdata + off;
2077dd7cddfSDavid du Colombier
2087dd7cddfSDavid du Colombier scr->dev->page(scr, page);
2097dd7cddfSDavid du Colombier for(y = r.min.y; y < r.max.y; y++) {
2107dd7cddfSDavid du Colombier if(sdisp + incs < edisp) {
2117dd7cddfSDavid du Colombier memmove(sdisp, sp, len);
2127dd7cddfSDavid du Colombier sp += incs;
2137dd7cddfSDavid du Colombier sdisp += incs;
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier else {
2167dd7cddfSDavid du Colombier off = edisp - sdisp;
2177dd7cddfSDavid du Colombier page++;
2187dd7cddfSDavid du Colombier if(off <= len){
2197dd7cddfSDavid du Colombier if(off > 0)
2207dd7cddfSDavid du Colombier memmove(sdisp, sp, off);
2217dd7cddfSDavid du Colombier scr->dev->page(scr, page);
2227dd7cddfSDavid du Colombier if(len - off > 0)
2237dd7cddfSDavid du Colombier memmove(disp, sp+off, len - off);
2247dd7cddfSDavid du Colombier }
2257dd7cddfSDavid du Colombier else {
2267dd7cddfSDavid du Colombier memmove(sdisp, sp, len);
2277dd7cddfSDavid du Colombier scr->dev->page(scr, page);
2287dd7cddfSDavid du Colombier }
2297dd7cddfSDavid du Colombier sp += incs;
2307dd7cddfSDavid du Colombier sdisp += incs - scr->apsize;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier }
2337dd7cddfSDavid du Colombier }
2347dd7cddfSDavid du Colombier
2357dd7cddfSDavid du Colombier void
getcolor(ulong p,ulong * pr,ulong * pg,ulong * pb)2367dd7cddfSDavid du Colombier getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
2377dd7cddfSDavid du Colombier {
2387dd7cddfSDavid du Colombier VGAscr *scr;
2397dd7cddfSDavid du Colombier ulong x;
2407dd7cddfSDavid du Colombier
2417dd7cddfSDavid du Colombier scr = &vgascreen[0];
2427dd7cddfSDavid du Colombier if(scr->gscreen == nil)
2437dd7cddfSDavid du Colombier return;
2447dd7cddfSDavid du Colombier
2457dd7cddfSDavid du Colombier switch(scr->gscreen->depth){
2467dd7cddfSDavid du Colombier default:
2477dd7cddfSDavid du Colombier x = 0x0F;
2487dd7cddfSDavid du Colombier break;
2497dd7cddfSDavid du Colombier case 8:
2507dd7cddfSDavid du Colombier x = 0xFF;
2517dd7cddfSDavid du Colombier break;
2527dd7cddfSDavid du Colombier }
2537dd7cddfSDavid du Colombier p &= x;
2547dd7cddfSDavid du Colombier
2557dd7cddfSDavid du Colombier lock(&cursor);
2567dd7cddfSDavid du Colombier *pr = scr->colormap[p][0];
2577dd7cddfSDavid du Colombier *pg = scr->colormap[p][1];
2587dd7cddfSDavid du Colombier *pb = scr->colormap[p][2];
2597dd7cddfSDavid du Colombier unlock(&cursor);
2607dd7cddfSDavid du Colombier }
2617dd7cddfSDavid du Colombier
2627dd7cddfSDavid du Colombier int
setpalette(ulong p,ulong r,ulong g,ulong b)2637dd7cddfSDavid du Colombier setpalette(ulong p, ulong r, ulong g, ulong b)
2647dd7cddfSDavid du Colombier {
2657dd7cddfSDavid du Colombier VGAscr *scr;
2667dd7cddfSDavid du Colombier int d;
2677dd7cddfSDavid du Colombier
2687dd7cddfSDavid du Colombier scr = &vgascreen[0];
2697dd7cddfSDavid du Colombier d = scr->palettedepth;
2707dd7cddfSDavid du Colombier
2717dd7cddfSDavid du Colombier lock(&cursor);
2727dd7cddfSDavid du Colombier scr->colormap[p][0] = r;
2737dd7cddfSDavid du Colombier scr->colormap[p][1] = g;
2747dd7cddfSDavid du Colombier scr->colormap[p][2] = b;
2757dd7cddfSDavid du Colombier vgao(PaddrW, p);
2767dd7cddfSDavid du Colombier vgao(Pdata, r>>(32-d));
2777dd7cddfSDavid du Colombier vgao(Pdata, g>>(32-d));
2787dd7cddfSDavid du Colombier vgao(Pdata, b>>(32-d));
2797dd7cddfSDavid du Colombier unlock(&cursor);
2807dd7cddfSDavid du Colombier
2817dd7cddfSDavid du Colombier return ~0;
2827dd7cddfSDavid du Colombier }
2837dd7cddfSDavid du Colombier
2847dd7cddfSDavid du Colombier /*
2857dd7cddfSDavid du Colombier * On some video cards (e.g. Mach64), the palette is used as the
2867dd7cddfSDavid du Colombier * DAC registers for >8-bit modes. We don't want to set them when the user
2877dd7cddfSDavid du Colombier * is trying to set a colormap and the card is in one of these modes.
2887dd7cddfSDavid du Colombier */
2897dd7cddfSDavid du Colombier int
setcolor(ulong p,ulong r,ulong g,ulong b)2907dd7cddfSDavid du Colombier setcolor(ulong p, ulong r, ulong g, ulong b)
2917dd7cddfSDavid du Colombier {
2927dd7cddfSDavid du Colombier VGAscr *scr;
2937dd7cddfSDavid du Colombier int x;
2947dd7cddfSDavid du Colombier
2957dd7cddfSDavid du Colombier scr = &vgascreen[0];
2967dd7cddfSDavid du Colombier if(scr->gscreen == nil)
2977dd7cddfSDavid du Colombier return 0;
2987dd7cddfSDavid du Colombier
2997dd7cddfSDavid du Colombier switch(scr->gscreen->depth){
3007dd7cddfSDavid du Colombier case 1:
3017dd7cddfSDavid du Colombier case 2:
3027dd7cddfSDavid du Colombier case 4:
3037dd7cddfSDavid du Colombier x = 0x0F;
3047dd7cddfSDavid du Colombier break;
3057dd7cddfSDavid du Colombier case 8:
3067dd7cddfSDavid du Colombier x = 0xFF;
3077dd7cddfSDavid du Colombier break;
3087dd7cddfSDavid du Colombier default:
3097dd7cddfSDavid du Colombier return 0;
3107dd7cddfSDavid du Colombier }
3117dd7cddfSDavid du Colombier p &= x;
3127dd7cddfSDavid du Colombier
3137dd7cddfSDavid du Colombier return setpalette(p, r, g, b);
3147dd7cddfSDavid du Colombier }
3157dd7cddfSDavid du Colombier
3167dd7cddfSDavid du Colombier int
cursoron(int dolock)3177dd7cddfSDavid du Colombier cursoron(int dolock)
3187dd7cddfSDavid du Colombier {
3197dd7cddfSDavid du Colombier VGAscr *scr;
3207dd7cddfSDavid du Colombier int v;
3217dd7cddfSDavid du Colombier
3227dd7cddfSDavid du Colombier scr = &vgascreen[0];
3237dd7cddfSDavid du Colombier if(scr->cur == nil || scr->cur->move == nil)
3247dd7cddfSDavid du Colombier return 0;
3257dd7cddfSDavid du Colombier
3267dd7cddfSDavid du Colombier if(dolock)
3277dd7cddfSDavid du Colombier lock(&cursor);
3287dd7cddfSDavid du Colombier v = scr->cur->move(scr, mousexy());
3297dd7cddfSDavid du Colombier if(dolock)
3307dd7cddfSDavid du Colombier unlock(&cursor);
3317dd7cddfSDavid du Colombier
3327dd7cddfSDavid du Colombier return v;
3337dd7cddfSDavid du Colombier }
3347dd7cddfSDavid du Colombier
3357dd7cddfSDavid du Colombier void
cursoroff(int)3367dd7cddfSDavid du Colombier cursoroff(int)
3377dd7cddfSDavid du Colombier {
3387dd7cddfSDavid du Colombier }
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier void
setcursor(Cursor * curs)3417dd7cddfSDavid du Colombier setcursor(Cursor* curs)
3427dd7cddfSDavid du Colombier {
3437dd7cddfSDavid du Colombier VGAscr *scr;
3447dd7cddfSDavid du Colombier
3457dd7cddfSDavid du Colombier scr = &vgascreen[0];
3467dd7cddfSDavid du Colombier if(scr->cur == nil || scr->cur->load == nil)
3477dd7cddfSDavid du Colombier return;
3487dd7cddfSDavid du Colombier
3497dd7cddfSDavid du Colombier scr->cur->load(scr, curs);
3507dd7cddfSDavid du Colombier }
3517dd7cddfSDavid du Colombier
3527dd7cddfSDavid du Colombier int hwaccel = 1;
3539a747e4fSDavid du Colombier int hwblank = 0; /* turned on by drivers that are known good */
3549a747e4fSDavid du Colombier int panning = 0;
3557dd7cddfSDavid du Colombier
3567dd7cddfSDavid du Colombier int
hwdraw(Memdrawparam * par)3577dd7cddfSDavid du Colombier hwdraw(Memdrawparam *par)
3587dd7cddfSDavid du Colombier {
3597dd7cddfSDavid du Colombier VGAscr *scr;
3604de34a7eSDavid du Colombier Memimage *dst, *src, *mask;
36159cc4ca5SDavid du Colombier int m;
3627dd7cddfSDavid du Colombier
3637dd7cddfSDavid du Colombier if(hwaccel == 0)
3647dd7cddfSDavid du Colombier return 0;
3657dd7cddfSDavid du Colombier
3667dd7cddfSDavid du Colombier scr = &vgascreen[0];
3674de34a7eSDavid du Colombier if((dst=par->dst) == nil || dst->data == nil)
3687dd7cddfSDavid du Colombier return 0;
3694de34a7eSDavid du Colombier if((src=par->src) == nil || src->data == nil)
3704de34a7eSDavid du Colombier return 0;
3714de34a7eSDavid du Colombier if((mask=par->mask) == nil || mask->data == nil)
3724de34a7eSDavid du Colombier return 0;
3734de34a7eSDavid du Colombier
3744de34a7eSDavid du Colombier if(scr->cur == &swcursor){
37558db92f4SDavid du Colombier /*
37658db92f4SDavid du Colombier * always calling swcursorhide here doesn't cure
37758db92f4SDavid du Colombier * leaving cursor tracks nor failing to refresh menus
37858db92f4SDavid du Colombier * with the latest libmemdraw/draw.c.
37958db92f4SDavid du Colombier */
3804de34a7eSDavid du Colombier if(dst->data->bdata == gscreendata.bdata)
3814de34a7eSDavid du Colombier swcursoravoid(par->r);
3824de34a7eSDavid du Colombier if(src->data->bdata == gscreendata.bdata)
3834de34a7eSDavid du Colombier swcursoravoid(par->sr);
3844de34a7eSDavid du Colombier if(mask->data->bdata == gscreendata.bdata)
3854de34a7eSDavid du Colombier swcursoravoid(par->mr);
3864de34a7eSDavid du Colombier }
3877dd7cddfSDavid du Colombier
3887dd7cddfSDavid du Colombier if(dst->data->bdata != gscreendata.bdata)
3897dd7cddfSDavid du Colombier return 0;
3907dd7cddfSDavid du Colombier
3917dd7cddfSDavid du Colombier if(scr->fill==nil && scr->scroll==nil)
3927dd7cddfSDavid du Colombier return 0;
3937dd7cddfSDavid du Colombier
3947dd7cddfSDavid du Colombier /*
3957dd7cddfSDavid du Colombier * If we have an opaque mask and source is one opaque
3967dd7cddfSDavid du Colombier * pixel we can convert to the destination format and just
3977dd7cddfSDavid du Colombier * replicate with memset.
3987dd7cddfSDavid du Colombier */
39959cc4ca5SDavid du Colombier m = Simplesrc|Simplemask|Fullmask;
4006a9fc400SDavid du Colombier if(scr->fill
4016a9fc400SDavid du Colombier && (par->state&m)==m
4026a9fc400SDavid du Colombier && ((par->srgba&0xFF) == 0xFF)
4036a9fc400SDavid du Colombier && (par->op&S) == S)
4047dd7cddfSDavid du Colombier return scr->fill(scr, par->r, par->sdval);
4057dd7cddfSDavid du Colombier
4067dd7cddfSDavid du Colombier /*
4077dd7cddfSDavid du Colombier * If no source alpha, an opaque mask, we can just copy the
4087dd7cddfSDavid du Colombier * source onto the destination. If the channels are the same and
4097dd7cddfSDavid du Colombier * the source is not replicated, memmove suffices.
4107dd7cddfSDavid du Colombier */
4116a9fc400SDavid du Colombier m = Simplemask|Fullmask;
4126a9fc400SDavid du Colombier if(scr->scroll
4136a9fc400SDavid du Colombier && src->data->bdata==dst->data->bdata
4146a9fc400SDavid du Colombier && !(src->flags&Falpha)
4156a9fc400SDavid du Colombier && (par->state&m)==m
4166a9fc400SDavid du Colombier && (par->op&S) == S)
4177dd7cddfSDavid du Colombier return scr->scroll(scr, par->r, par->sr);
4187dd7cddfSDavid du Colombier
4197dd7cddfSDavid du Colombier return 0;
4207dd7cddfSDavid du Colombier }
4217dd7cddfSDavid du Colombier
4227dd7cddfSDavid du Colombier void
blankscreen(int blank)4237dd7cddfSDavid du Colombier blankscreen(int blank)
4247dd7cddfSDavid du Colombier {
4257dd7cddfSDavid du Colombier VGAscr *scr;
4267dd7cddfSDavid du Colombier
4277dd7cddfSDavid du Colombier scr = &vgascreen[0];
4289a747e4fSDavid du Colombier if(hwblank){
4299a747e4fSDavid du Colombier if(scr->blank)
4307dd7cddfSDavid du Colombier scr->blank(scr, blank);
4319a747e4fSDavid du Colombier else
4329a747e4fSDavid du Colombier vgablank(scr, blank);
4339a747e4fSDavid du Colombier }
4347dd7cddfSDavid du Colombier }
4354de34a7eSDavid du Colombier
4364de34a7eSDavid du Colombier void
vgalinearpciid(VGAscr * scr,int vid,int did)4374de34a7eSDavid du Colombier vgalinearpciid(VGAscr *scr, int vid, int did)
4384de34a7eSDavid du Colombier {
4394de34a7eSDavid du Colombier Pcidev *p;
4404de34a7eSDavid du Colombier
4414de34a7eSDavid du Colombier p = nil;
4424de34a7eSDavid du Colombier while((p = pcimatch(p, vid, 0)) != nil){
4434de34a7eSDavid du Colombier if(p->ccrb != 3) /* video card */
4444de34a7eSDavid du Colombier continue;
4454de34a7eSDavid du Colombier if(did != 0 && p->did != did)
4464de34a7eSDavid du Colombier continue;
4474de34a7eSDavid du Colombier break;
4484de34a7eSDavid du Colombier }
4494de34a7eSDavid du Colombier if(p == nil)
4504de34a7eSDavid du Colombier error("pci video card not found");
4514de34a7eSDavid du Colombier
4524de34a7eSDavid du Colombier scr->pci = p;
4534de34a7eSDavid du Colombier vgalinearpci(scr);
4544de34a7eSDavid du Colombier }
4554de34a7eSDavid du Colombier
4564de34a7eSDavid du Colombier void
vgalinearpci(VGAscr * scr)4574de34a7eSDavid du Colombier vgalinearpci(VGAscr *scr)
4584de34a7eSDavid du Colombier {
4594de34a7eSDavid du Colombier ulong paddr;
4604de34a7eSDavid du Colombier int i, size, best;
4614de34a7eSDavid du Colombier Pcidev *p;
4624de34a7eSDavid du Colombier
4634de34a7eSDavid du Colombier p = scr->pci;
4644de34a7eSDavid du Colombier if(p == nil)
4654de34a7eSDavid du Colombier return;
4664de34a7eSDavid du Colombier
4674de34a7eSDavid du Colombier /*
4684de34a7eSDavid du Colombier * Scan for largest memory region on card.
4694de34a7eSDavid du Colombier * Some S3 cards (e.g. Savage) have enormous
4704de34a7eSDavid du Colombier * mmio regions (but even larger frame buffers).
4719c06fe1dSDavid du Colombier * Some 3dfx cards (e.g., Voodoo3) have mmio
4729c06fe1dSDavid du Colombier * buffers the same size as the frame buffer,
4739c06fe1dSDavid du Colombier * but only the frame buffer is marked as
4749c06fe1dSDavid du Colombier * prefetchable (bar&8). If a card doesn't fit
4759c06fe1dSDavid du Colombier * into these heuristics, its driver will have to
4769c06fe1dSDavid du Colombier * call vgalinearaddr directly.
4774de34a7eSDavid du Colombier */
4784de34a7eSDavid du Colombier best = -1;
4794de34a7eSDavid du Colombier for(i=0; i<nelem(p->mem); i++){
4804de34a7eSDavid du Colombier if(p->mem[i].bar&1) /* not memory */
4814de34a7eSDavid du Colombier continue;
4824de34a7eSDavid du Colombier if(p->mem[i].size < 640*480) /* not big enough */
4834de34a7eSDavid du Colombier continue;
4849c06fe1dSDavid du Colombier if(best==-1
4859c06fe1dSDavid du Colombier || p->mem[i].size > p->mem[best].size
4864baec263SDavid du Colombier || (p->mem[i].size == p->mem[best].size
4874baec263SDavid du Colombier && (p->mem[i].bar&8)
4884baec263SDavid du Colombier && !(p->mem[best].bar&8)))
4894de34a7eSDavid du Colombier best = i;
4904de34a7eSDavid du Colombier }
4914de34a7eSDavid du Colombier if(best >= 0){
4924de34a7eSDavid du Colombier paddr = p->mem[best].bar & ~0x0F;
4934de34a7eSDavid du Colombier size = p->mem[best].size;
4944de34a7eSDavid du Colombier vgalinearaddr(scr, paddr, size);
4954de34a7eSDavid du Colombier return;
4964de34a7eSDavid du Colombier }
4974de34a7eSDavid du Colombier error("no video memory found on pci card");
4984de34a7eSDavid du Colombier }
4994de34a7eSDavid du Colombier
5004de34a7eSDavid du Colombier void
vgalinearaddr(VGAscr * scr,ulong paddr,int size)5014de34a7eSDavid du Colombier vgalinearaddr(VGAscr *scr, ulong paddr, int size)
5024de34a7eSDavid du Colombier {
5034de34a7eSDavid du Colombier int x, nsize;
5044de34a7eSDavid du Colombier ulong npaddr;
5054de34a7eSDavid du Colombier
5064de34a7eSDavid du Colombier /*
5074de34a7eSDavid du Colombier * new approach. instead of trying to resize this
5084de34a7eSDavid du Colombier * later, let's assume that we can just allocate the
5094de34a7eSDavid du Colombier * entire window to start with.
5104de34a7eSDavid du Colombier */
5114de34a7eSDavid du Colombier
5124de34a7eSDavid du Colombier if(scr->paddr == paddr && size <= scr->apsize)
5134de34a7eSDavid du Colombier return;
5144de34a7eSDavid du Colombier
5154de34a7eSDavid du Colombier if(scr->paddr){
5164de34a7eSDavid du Colombier /*
5174de34a7eSDavid du Colombier * could call vunmap and vmap,
5184de34a7eSDavid du Colombier * but worried about dangling pointers in devdraw
5194de34a7eSDavid du Colombier */
5204de34a7eSDavid du Colombier error("cannot grow vga frame buffer");
5214de34a7eSDavid du Colombier }
5224de34a7eSDavid du Colombier
5234de34a7eSDavid du Colombier /* round to page boundary, just in case */
5244de34a7eSDavid du Colombier x = paddr&(BY2PG-1);
5254de34a7eSDavid du Colombier npaddr = paddr-x;
5264de34a7eSDavid du Colombier nsize = PGROUND(size+x);
5274de34a7eSDavid du Colombier
5281bd28109SDavid du Colombier /*
5291bd28109SDavid du Colombier * Don't bother trying to map more than 4000x4000x32 = 64MB.
5301bd28109SDavid du Colombier * We only have a 256MB window.
5311bd28109SDavid du Colombier */
5321bd28109SDavid du Colombier if(nsize > 64*MB)
5331bd28109SDavid du Colombier nsize = 64*MB;
5344de34a7eSDavid du Colombier scr->vaddr = vmap(npaddr, nsize);
5354de34a7eSDavid du Colombier if(scr->vaddr == 0)
5364de34a7eSDavid du Colombier error("cannot allocate vga frame buffer");
5374de34a7eSDavid du Colombier scr->vaddr = (char*)scr->vaddr+x;
5384de34a7eSDavid du Colombier scr->paddr = paddr;
5394de34a7eSDavid du Colombier scr->apsize = nsize;
540*cb8c047aSDavid du Colombier /* let mtrr harmlessly fail on old CPUs, e.g., P54C */
541*cb8c047aSDavid du Colombier if(!waserror()){
542*cb8c047aSDavid du Colombier mtrr(npaddr, nsize, "wc");
543*cb8c047aSDavid du Colombier poperror();
544*cb8c047aSDavid du Colombier }
5454de34a7eSDavid du Colombier }
5464de34a7eSDavid du Colombier
5474de34a7eSDavid du Colombier
5484de34a7eSDavid du Colombier /*
5494de34a7eSDavid du Colombier * Software cursor.
5504de34a7eSDavid du Colombier */
5514de34a7eSDavid du Colombier int swvisible; /* is the cursor visible? */
5524de34a7eSDavid du Colombier int swenabled; /* is the cursor supposed to be on the screen? */
5534de34a7eSDavid du Colombier Memimage* swback; /* screen under cursor */
5544de34a7eSDavid du Colombier Memimage* swimg; /* cursor image */
5554de34a7eSDavid du Colombier Memimage* swmask; /* cursor mask */
5564de34a7eSDavid du Colombier Memimage* swimg1;
5574de34a7eSDavid du Colombier Memimage* swmask1;
5584de34a7eSDavid du Colombier
5594de34a7eSDavid du Colombier Point swoffset;
5604de34a7eSDavid du Colombier Rectangle swrect; /* screen rectangle in swback */
5614de34a7eSDavid du Colombier Point swpt; /* desired cursor location */
5624de34a7eSDavid du Colombier Point swvispt; /* actual cursor location */
5634de34a7eSDavid du Colombier int swvers; /* incremented each time cursor image changes */
5644de34a7eSDavid du Colombier int swvisvers; /* the version on the screen */
5654de34a7eSDavid du Colombier
5664de34a7eSDavid du Colombier /*
5674de34a7eSDavid du Colombier * called with drawlock locked for us, most of the time.
5684de34a7eSDavid du Colombier * kernel prints at inopportune times might mean we don't
5694de34a7eSDavid du Colombier * hold the lock, but memimagedraw is now reentrant so
5704de34a7eSDavid du Colombier * that should be okay: worst case we get cursor droppings.
5714de34a7eSDavid du Colombier */
5724de34a7eSDavid du Colombier void
swcursorhide(void)5734de34a7eSDavid du Colombier swcursorhide(void)
5744de34a7eSDavid du Colombier {
5754de34a7eSDavid du Colombier if(swvisible == 0)
5764de34a7eSDavid du Colombier return;
5774de34a7eSDavid du Colombier if(swback == nil)
5784de34a7eSDavid du Colombier return;
5794de34a7eSDavid du Colombier swvisible = 0;
5804de34a7eSDavid du Colombier memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
58126d1d1dfSDavid du Colombier flushmemscreen(swrect);
5824de34a7eSDavid du Colombier }
5834de34a7eSDavid du Colombier
5844de34a7eSDavid du Colombier void
swcursoravoid(Rectangle r)5854de34a7eSDavid du Colombier swcursoravoid(Rectangle r)
5864de34a7eSDavid du Colombier {
5874de34a7eSDavid du Colombier if(swvisible && rectXrect(r, swrect))
5884de34a7eSDavid du Colombier swcursorhide();
5894de34a7eSDavid du Colombier }
5904de34a7eSDavid du Colombier
5914de34a7eSDavid du Colombier void
swcursordraw(void)5924de34a7eSDavid du Colombier swcursordraw(void)
5934de34a7eSDavid du Colombier {
5944de34a7eSDavid du Colombier if(swvisible)
5954de34a7eSDavid du Colombier return;
5964de34a7eSDavid du Colombier if(swenabled == 0)
5974de34a7eSDavid du Colombier return;
5984de34a7eSDavid du Colombier if(swback == nil || swimg1 == nil || swmask1 == nil)
5994de34a7eSDavid du Colombier return;
6004de34a7eSDavid du Colombier assert(!canqlock(&drawlock));
6014de34a7eSDavid du Colombier swvispt = swpt;
6024de34a7eSDavid du Colombier swvisvers = swvers;
6034de34a7eSDavid du Colombier swrect = rectaddpt(Rect(0,0,16,16), swvispt);
6044de34a7eSDavid du Colombier memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
6054de34a7eSDavid du Colombier memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
60626d1d1dfSDavid du Colombier flushmemscreen(swrect);
6074de34a7eSDavid du Colombier swvisible = 1;
6084de34a7eSDavid du Colombier }
6094de34a7eSDavid du Colombier
6104de34a7eSDavid du Colombier /*
6114de34a7eSDavid du Colombier * Need to lock drawlock for ourselves.
6124de34a7eSDavid du Colombier */
6134de34a7eSDavid du Colombier void
swenable(VGAscr *)6144de34a7eSDavid du Colombier swenable(VGAscr*)
6154de34a7eSDavid du Colombier {
6164de34a7eSDavid du Colombier swenabled = 1;
6174de34a7eSDavid du Colombier if(canqlock(&drawlock)){
6184de34a7eSDavid du Colombier swcursordraw();
6194de34a7eSDavid du Colombier qunlock(&drawlock);
6204de34a7eSDavid du Colombier }
6214de34a7eSDavid du Colombier }
6224de34a7eSDavid du Colombier
6234de34a7eSDavid du Colombier void
swdisable(VGAscr *)6244de34a7eSDavid du Colombier swdisable(VGAscr*)
6254de34a7eSDavid du Colombier {
6264de34a7eSDavid du Colombier swenabled = 0;
6274de34a7eSDavid du Colombier if(canqlock(&drawlock)){
6284de34a7eSDavid du Colombier swcursorhide();
6294de34a7eSDavid du Colombier qunlock(&drawlock);
6304de34a7eSDavid du Colombier }
6314de34a7eSDavid du Colombier }
6324de34a7eSDavid du Colombier
6334de34a7eSDavid du Colombier void
swload(VGAscr *,Cursor * curs)6344de34a7eSDavid du Colombier swload(VGAscr*, Cursor *curs)
6354de34a7eSDavid du Colombier {
6364de34a7eSDavid du Colombier uchar *ip, *mp;
6374de34a7eSDavid du Colombier int i, j, set, clr;
6384de34a7eSDavid du Colombier
6394de34a7eSDavid du Colombier if(!swimg || !swmask || !swimg1 || !swmask1)
6404de34a7eSDavid du Colombier return;
6414de34a7eSDavid du Colombier /*
6424de34a7eSDavid du Colombier * Build cursor image and mask.
6434de34a7eSDavid du Colombier * Image is just the usual cursor image
6444de34a7eSDavid du Colombier * but mask is a transparent alpha mask.
6454de34a7eSDavid du Colombier *
6464de34a7eSDavid du Colombier * The 16x16x8 memimages do not have
6474de34a7eSDavid du Colombier * padding at the end of their scan lines.
6484de34a7eSDavid du Colombier */
6494de34a7eSDavid du Colombier ip = byteaddr(swimg, ZP);
6504de34a7eSDavid du Colombier mp = byteaddr(swmask, ZP);
6514de34a7eSDavid du Colombier for(i=0; i<32; i++){
6524de34a7eSDavid du Colombier set = curs->set[i];
6534de34a7eSDavid du Colombier clr = curs->clr[i];
6544de34a7eSDavid du Colombier for(j=0x80; j; j>>=1){
6554de34a7eSDavid du Colombier *ip++ = set&j ? 0x00 : 0xFF;
6564de34a7eSDavid du Colombier *mp++ = (clr|set)&j ? 0xFF : 0x00;
6574de34a7eSDavid du Colombier }
6584de34a7eSDavid du Colombier }
6594de34a7eSDavid du Colombier swoffset = curs->offset;
6604de34a7eSDavid du Colombier swvers++;
6614de34a7eSDavid du Colombier memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
6624de34a7eSDavid du Colombier memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
6634de34a7eSDavid du Colombier }
6644de34a7eSDavid du Colombier
6654de34a7eSDavid du Colombier int
swmove(VGAscr *,Point p)6664de34a7eSDavid du Colombier swmove(VGAscr*, Point p)
6674de34a7eSDavid du Colombier {
6684de34a7eSDavid du Colombier swpt = addpt(p, swoffset);
6694de34a7eSDavid du Colombier return 0;
6704de34a7eSDavid du Colombier }
6714de34a7eSDavid du Colombier
6724de34a7eSDavid du Colombier void
swcursorclock(void)6734de34a7eSDavid du Colombier swcursorclock(void)
6744de34a7eSDavid du Colombier {
6754de34a7eSDavid du Colombier int x;
6764de34a7eSDavid du Colombier
6774de34a7eSDavid du Colombier if(!swenabled)
6784de34a7eSDavid du Colombier return;
6794de34a7eSDavid du Colombier if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
6804de34a7eSDavid du Colombier return;
6814de34a7eSDavid du Colombier
6824de34a7eSDavid du Colombier x = splhi();
6834de34a7eSDavid du Colombier if(swenabled)
6844de34a7eSDavid du Colombier if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
6854de34a7eSDavid du Colombier if(canqlock(&drawlock)){
6864de34a7eSDavid du Colombier swcursorhide();
6874de34a7eSDavid du Colombier swcursordraw();
6884de34a7eSDavid du Colombier qunlock(&drawlock);
6894de34a7eSDavid du Colombier }
6904de34a7eSDavid du Colombier splx(x);
6914de34a7eSDavid du Colombier }
6924de34a7eSDavid du Colombier
6934de34a7eSDavid du Colombier void
swcursorinit(void)6944de34a7eSDavid du Colombier swcursorinit(void)
6954de34a7eSDavid du Colombier {
6964de34a7eSDavid du Colombier static int init, warned;
6974de34a7eSDavid du Colombier VGAscr *scr;
6984de34a7eSDavid du Colombier
6994de34a7eSDavid du Colombier didswcursorinit = 1;
7004de34a7eSDavid du Colombier if(!init){
7014de34a7eSDavid du Colombier init = 1;
70226ad7229SDavid du Colombier addclock0link(swcursorclock, 10);
7034de34a7eSDavid du Colombier }
7044de34a7eSDavid du Colombier scr = &vgascreen[0];
7054de34a7eSDavid du Colombier if(scr==nil || scr->gscreen==nil)
7064de34a7eSDavid du Colombier return;
7074de34a7eSDavid du Colombier
7084de34a7eSDavid du Colombier if(scr->dev == nil || scr->dev->linear == nil){
7094de34a7eSDavid du Colombier if(!warned){
7104de34a7eSDavid du Colombier print("cannot use software cursor on non-linear vga screen\n");
7114de34a7eSDavid du Colombier warned = 1;
7124de34a7eSDavid du Colombier }
7134de34a7eSDavid du Colombier return;
7144de34a7eSDavid du Colombier }
7154de34a7eSDavid du Colombier
7164de34a7eSDavid du Colombier if(swback){
7174de34a7eSDavid du Colombier freememimage(swback);
7184de34a7eSDavid du Colombier freememimage(swmask);
7194de34a7eSDavid du Colombier freememimage(swmask1);
7204de34a7eSDavid du Colombier freememimage(swimg);
7214de34a7eSDavid du Colombier freememimage(swimg1);
7224de34a7eSDavid du Colombier }
7234de34a7eSDavid du Colombier
7244de34a7eSDavid du Colombier swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
7254de34a7eSDavid du Colombier swmask = allocmemimage(Rect(0,0,16,16), GREY8);
7264de34a7eSDavid du Colombier swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
7274de34a7eSDavid du Colombier swimg = allocmemimage(Rect(0,0,16,16), GREY8);
7284de34a7eSDavid du Colombier swimg1 = allocmemimage(Rect(0,0,16,16), GREY1);
7294de34a7eSDavid du Colombier if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
730dc4ee190SDavid du Colombier print("software cursor: allocmemimage fails");
7314de34a7eSDavid du Colombier return;
7324de34a7eSDavid du Colombier }
7334de34a7eSDavid du Colombier
7344de34a7eSDavid du Colombier memfillcolor(swmask, DOpaque);
7354de34a7eSDavid du Colombier memfillcolor(swmask1, DOpaque);
7364de34a7eSDavid du Colombier memfillcolor(swimg, DBlack);
7374de34a7eSDavid du Colombier memfillcolor(swimg1, DBlack);
7384de34a7eSDavid du Colombier }
7394de34a7eSDavid du Colombier
7404de34a7eSDavid du Colombier VGAcur swcursor =
7414de34a7eSDavid du Colombier {
7424de34a7eSDavid du Colombier "soft",
7434de34a7eSDavid du Colombier swenable,
7444de34a7eSDavid du Colombier swdisable,
7454de34a7eSDavid du Colombier swload,
7464de34a7eSDavid du Colombier swmove,
7474de34a7eSDavid du Colombier };
7484de34a7eSDavid du Colombier
749