2 * vga driver using just vesa bios to set up.
5 #include "../port/lib.h"
10 #include "../port/error.h"
27 static uchar modebuf[0x1000];
28 static Chan *creg, *cmem;
33 #define WORD(p) ((p)[0] | ((p)[1]<<8))
34 #define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
35 #define PWORD(p, v) (p)[0] = (v); (p)[1] = (v)>>8
36 #define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24
39 vbesetup(Ureg *u, int ax)
41 memset(modebuf, 0, sizeof modebuf);
42 memset(u, 0, sizeof *u);
44 u->es = (RealModeBuf>>4)&0xF000;
45 u->di = RealModeBuf&0xFFFF;
52 if(devtab[cmem->type]->write(cmem, modebuf, sizeof(modebuf), RealModeBuf) != sizeof(modebuf))
53 error("write modebuf");
55 if(devtab[creg->type]->write(creg, u, sizeof(*u), 0) != sizeof(*u))
57 if(devtab[creg->type]->read(creg, u, sizeof(*u), 0) != sizeof(*u))
59 if((u->ax&0xFFFF) != 0x004F)
60 error("vesa bios error");
61 if(devtab[cmem->type]->read(cmem, modebuf, sizeof(modebuf), RealModeBuf) != sizeof(modebuf))
62 error("read modebuf");
71 p = vbesetup(&u, 0x4F00);
72 strcpy((char*)p, "VBE2");
74 if(memcmp((char*)p, "VESA", 4) != 0)
75 error("bad vesa signature");
77 error("bad vesa version");
96 p = vbesetup(&u, 0x4F01);
103 vesalinear(VGAscr *scr, int, int)
105 int i, mode, size, havesize;
113 * bochs loses the top bits - cannot use this
114 if((mode&(1<<14)) == 0)
115 error("not in linear graphics mode");
118 p = vbemodeinfo(mode);
119 if(!(WORD(p+0) & (1<<4)))
120 error("not in VESA graphics mode");
121 if(!(WORD(p+0) & (1<<7)))
122 error("not in linear graphics mode");
125 size = WORD(p+20)*WORD(p+16);
128 * figure out max size of memory so that we have
129 * enough if the screen is resized.
133 while(!havesize && (pci = pcimatch(pci, 0, 0)) != nil){
134 if(pci->ccrb != Pcibcdisp)
136 for(i=0; i<nelem(pci->mem); i++){
139 if(pci->mem[i].bar&1) /* not memory */
141 a = pci->mem[i].bar & ~0xF;
142 e = a + pci->mem[i].size;
143 if(paddr >= a && (paddr+size) <= e){
151 /* no pci - heuristic guess */
153 if(size < 4*1024*1024)
156 size = ROUND(size, 1024*1024);
158 vgalinearaddr(scr, paddr, size);
160 addvgaseg("vesascreen", scr->paddr, scr->apsize);
168 return vesactl == Cdisable;
176 while(vesactl != Cdisable){
178 sleep(&vesar, vesadisabled, nil);
180 vbesetup(&u, 0x4f10);
181 if(vesactl == Cblank)
187 * dont wait forever here. some BIOS get stuck
188 * in i/o poll loop after blank/unblank for some
189 * reason. (Thinkpad A22p)
215 cmem = namec("/dev/realmodemem", Aopen, ORDWR, 0);
221 creg = namec("/dev/realmode", Aopen, ORDWR, 0);
226 kproc("vesa", vesaproc, nil);
230 vesadisable(VGAscr *)
235 /* wait for vesaproc to finish */
241 vesablank(VGAscr *, int blank)
243 if(vesactl != Cdisable){
244 vesactl = blank ? Cblank : Cenable;
250 vesadrawinit(VGAscr *scr)
252 scr->blank = vesablank;
255 VGAdev vgavesadev = {