2 * vga driver using just vesa bios to set up.
5 #include "../port/lib.h"
10 #include "../port/error.h"
13 #include "/386/include/ureg.h"
14 typedef struct Ureg386 Ureg386;
26 static uchar modebuf[0x1000];
27 static Chan *creg, *cmem;
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
34 typedef struct Vmode Vmode;
46 vbesetup(Ureg386 *u, int ax)
48 memset(modebuf, 0, sizeof modebuf);
49 memset(u, 0, sizeof *u);
51 u->es = (RealModeBuf>>4)&0xF000;
52 u->di = RealModeBuf&0xFFFF;
59 if(devtab[cmem->type]->write(cmem, modebuf, sizeof(modebuf), RealModeBuf) != sizeof(modebuf))
60 error("write modebuf");
62 if(devtab[creg->type]->write(creg, u, sizeof(*u), 0) != sizeof(*u))
64 if(devtab[creg->type]->read(creg, u, sizeof(*u), 0) != sizeof(*u))
66 if((u->ax&0xFFFF) != 0x004F)
67 error("vesa bios error");
68 if(devtab[cmem->type]->read(cmem, modebuf, sizeof(modebuf), RealModeBuf) != sizeof(modebuf))
69 error("read modebuf");
78 p = vbesetup(&u, 0x4F00);
79 strcpy((char*)p, "VBE2");
81 if(memcmp((char*)p, "VESA", 4) != 0)
82 error("bad vesa signature");
84 error("bad vesa version");
103 p = vbesetup(&u, 0x4F01);
110 vmode(Vmode *m, uchar *p)
113 if(!(m->attr & (1<<4)))
114 return "not in VESA graphics mode";
115 if(!(m->attr & (1<<7)))
116 return "not in linear graphics mode";
121 m->paddr = LONG(p+40);
123 snprint(m->chan, sizeof m->chan, "%c%d",
124 (m->attr & (1<<3)) ? 'm' : 'k', m->depth);
126 rgbmask2chan(m->chan, m->depth,
127 (1UL<<p[31])-1 << p[32],
128 (1UL<<p[33])-1 << p[34],
129 (1UL<<p[35])-1 << p[36]);
134 vesalinear(VGAscr *scr, int, int)
136 int i, mode, size, havesize;
144 * bochs loses the top bits - cannot use this
145 if((mode&(1<<14)) == 0)
146 error("not in linear graphics mode");
149 if((err = vmode(&m, vbemodeinfo(mode))) != nil)
155 * figure out max size of memory so that we have
156 * enough if the screen is resized.
160 while(!havesize && (pci = pcimatch(pci, 0, 0)) != nil){
161 if(pci->ccrb != Pcibcdisp)
163 for(i=0; i<nelem(pci->mem); i++){
166 if(pci->mem[i].bar&1) /* not memory */
168 a = pci->mem[i].bar & ~0xF;
169 e = a + pci->mem[i].size;
170 if(m.paddr >= a && (m.paddr+size) <= e){
178 /* no pci - heuristic guess */
180 if(size < 4*1024*1024)
183 size = ROUND(size, 1024*1024);
185 vgalinearaddr(scr, m.paddr, size);
187 addvgaseg("vesascreen", scr->paddr, scr->apsize);
195 cmem = namec("/dev/realmodemem", Aopen, ORDWR, 0);
201 creg = namec("/dev/realmode", Aopen, ORDWR, 0);
206 vesadisable(VGAscr *)
216 vesablank(VGAscr *, int blank)
220 vbesetup(&u, 0x4f10);
221 u.bx = blank ? 0x0101 : 0x0001;
224 * dont wait forever when called from mouse kproc.
225 * some BIOS get stuck in i/o poll loop after
226 * blank/unblank for some reason. (Thinkpad A22p)
243 vesadrawinit(VGAscr *scr)
245 scr->blank = vesablank;
248 VGAdev vgavesadev = {
258 * called from multibootargs() to convert
259 * vbe mode info (passed from bootloader)
260 * to *bootscreen= parameter
263 vesabootscreenconf(char *s, char *e, uchar *p)
267 if(vmode(&m, p) != nil)
269 return seprint(s, e, "*bootscreen=%dx%dx%d %s %#lux\n",
270 m.bpl * 8 / m.depth, m.dy, m.depth, m.chan, m.paddr);