2 * vga driver using just vesa bios to set up.
4 * note that setting hwaccel to zero will cause cursor ghosts to be
5 * left behind. hwaccel set non-zero repairs this.
8 #include "../port/lib.h"
13 #include "../port/error.h"
26 static void *hardscreen;
27 static uchar modebuf[0x1000];
29 #define WORD(p) ((p)[0] | ((p)[1]<<8))
30 #define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
31 #define PWORD(p, v) (p)[0] = (v); (p)[1] = (v)>>8
32 #define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24
35 vbesetup(Ureg *u, int ax)
40 memset(modebuf, 0, sizeof modebuf);
41 memset(u, 0, sizeof *u);
43 u->es = (pa>>4)&0xF000;
54 cmem = namec("/dev/realmodemem", Aopen, ORDWR, 0);
59 creg = namec("/dev/realmode", Aopen, ORDWR, 0);
65 /* TODO: check read and write return values */
66 devtab[cmem->type]->write(cmem, modebuf, sizeof modebuf, pa);
68 devtab[creg->type]->write(creg, u, sizeof *u, 0);
70 devtab[creg->type]->read(creg, u, sizeof *u, 0);
71 if((u->ax&0xFFFF) != 0x004F)
72 error("vesa bios error");
73 devtab[cmem->type]->read(cmem, modebuf, sizeof modebuf, pa);
87 p = vbesetup(&u, 0x4F00);
88 strcpy((char*)p, "VBE2");
90 if(memcmp((char*)p, "VESA", 4) != 0)
91 error("bad vesa signature");
93 error("bad vesa version");
101 vbesetup(&u, 0x4F03);
107 vbemodeinfo(int mode)
112 p = vbesetup(&u, 0x4F01);
119 vesalinear(VGAscr *scr, int, int)
121 int i, mode, size, havesize;
128 scr->paddr = scr->apsize = 0;
135 * bochs loses the top bits - cannot use this
136 if((mode&(1<<14)) == 0)
137 error("not in linear graphics mode");
140 p = vbemodeinfo(mode);
141 if(!(WORD(p+0) & (1<<4)))
142 error("not in VESA graphics mode");
143 if(!(WORD(p+0) & (1<<7)))
144 error("not in linear graphics mode");
147 size = WORD(p+20)*WORD(p+16);
148 size = PGROUND(size);
151 * figure out max size of memory so that we have
152 * enough if the screen is resized.
156 while(!havesize && (pci = pcimatch(pci, 0, 0)) != nil){
157 if(pci->ccrb != Pcibcdisp)
159 for(i=0; i<nelem(pci->mem); i++)
160 if(paddr == (pci->mem[i].bar&~0x0F)){
161 if(pci->mem[i].size > size)
162 size = pci->mem[i].size;
168 /* no pci - heuristic guess */
170 if(size < 4*1024*1024)
173 size = ROUND(size, 1024*1024);
174 if(size > 16*1024*1024) /* arbitrary */
177 vgalinearaddr(scr, paddr, size);
179 addvgaseg("vesascreen", scr->paddr, scr->apsize);
182 hardscreen = scr->vaddr;
184 scr->paddr = scr->apsize = 0;
189 vesaflush(VGAscr *scr, Rectangle r)
192 ulong *hp, *sp, *esp;
194 if(hardscreen == nil)
196 if(rectclip(&r, scr->gscreen->r) == 0)
198 sp = (ulong*)(scr->gscreendata->bdata + scr->gscreen->zero);
199 t = (r.max.x * scr->gscreen->depth + 2*BI2WD-1) / BI2WD;
200 w = (r.min.x * scr->gscreen->depth) / BI2WD;
202 wid = scr->gscreen->width;
203 off = r.min.y * wid + (r.min.x * scr->gscreen->depth) / BI2WD;
208 esp = sp + Dy(r) * wid;
216 VGAdev vgavesadev = {