FreeBSD/Linux Kernel Cross Reference
sys/pc/vgavesa.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8 #include "ureg.h"
9
10 #define Image IMAGE
11 #include <draw.h>
12 #include <memdraw.h>
13 #include <cursor.h>
14 #include "screen.h"
15
16
17 static void *hardscreen;
18
19 #define WORD(p) ((p)[0] | ((p)[1]<<8))
20 #define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
21 #define PWORD(p, v) (p)[0] = (v); (p)[1] = (v)>>8
22 #define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24
23
24 extern void realmode(Ureg*);
25
26 static uchar*
27 vbesetup(Ureg *u, int ax)
28 {
29 ulong pa;
30
31 pa = PADDR(RMBUF);
32 memset(u, 0, sizeof *u);
33 u->ax = ax;
34 u->es = (pa>>4)&0xF000;
35 u->di = pa&0xFFFF;
36 return (void*)RMBUF;
37 }
38
39 static void
40 vbecall(Ureg *u)
41 {
42 u->trap = 0x10;
43 realmode(u);
44 if((u->ax&0xFFFF) != 0x004F)
45 error("vesa bios error");
46 }
47
48 static void
49 vbecheck(void)
50 {
51 Ureg u;
52 uchar *p;
53
54 p = vbesetup(&u, 0x4F00);
55 strcpy((char*)p, "VBE2");
56 vbecall(&u);
57 if(memcmp((char*)p, "VESA", 4) != 0)
58 error("bad vesa signature");
59 if(p[5] < 2)
60 error("bad vesa version");
61 }
62
63 static int
64 vbegetmode(void)
65 {
66 Ureg u;
67
68 vbesetup(&u, 0x4F03);
69 vbecall(&u);
70 return u.bx;
71 }
72
73 static uchar*
74 vbemodeinfo(int mode)
75 {
76 uchar *p;
77 Ureg u;
78
79 p = vbesetup(&u, 0x4F01);
80 u.cx = mode;
81 vbecall(&u);
82 return p;
83 }
84
85 static void
86 vesalinear(VGAscr *, int, int)
87 {
88 int i, mode, size;
89 uchar *p;
90 ulong paddr;
91 Pcidev *pci;
92
93 vbecheck();
94 mode = vbegetmode();
95 /* bochs loses the top bits - cannot use this
96 if((mode&(1<<14)) == 0)
97 error("not in linear graphics mode");
98 */
99 mode &= 0x3FFF;
100 p = vbemodeinfo(mode);
101 if(!(WORD(p+0) & (1<<4)))
102 error("not in VESA graphics mode");
103 if(!(WORD(p+0) & (1<<7)))
104 error("not in linear graphics mode");
105
106 paddr = LONG(p+40);
107 size = WORD(p+20)*WORD(p+16);
108 size = PGROUND(size);
109
110 /*
111 * figure out max size of memory so that we have
112 * enough if the screen is resized.
113 */
114 pci = nil;
115 while((pci = pcimatch(pci, 0, 0)) != nil){
116 if(pci->ccrb != Pcibcdisp)
117 continue;
118 for(i=0; i<nelem(pci->mem); i++)
119 if(paddr == (pci->mem[i].bar&~0x0F)){
120 if(pci->mem[i].size > size)
121 size = pci->mem[i].size;
122 goto havesize;
123 }
124 }
125
126 /* no pci - heuristic guess */
127 if(size < 4*1024*1024)
128 size = 4*1024*1024;
129 else
130 size = ROUND(size, 1024*1024);
131
132 havesize:
133 if(size > 16*1024*1024) /* probably arbitrary; could increase */
134 size = 16*1024*1024;
135 hardscreen = vmap(paddr, size);
136 mtrr(paddr, size, "wc");
137 // vgalinearaddr(scr, paddr, size);
138 }
139
140 static void
141 vesaflush(VGAscr *scr, Rectangle r)
142 {
143 int t, w, wid, off;
144 ulong *hp, *sp, *esp;
145
146 if(rectclip(&r, scr->gscreen->r) == 0)
147 return;
148
149 hp = hardscreen;
150 sp = (ulong*)(scr->gscreendata->bdata + scr->gscreen->zero);
151 t = (r.max.x * scr->gscreen->depth + 2*BI2WD-1) / BI2WD;
152 w = (r.min.x * scr->gscreen->depth) / BI2WD;
153 w = (t - w) * BY2WD;
154 wid = scr->gscreen->width;
155 off = r.min.y * wid + (r.min.x * scr->gscreen->depth) / BI2WD;
156
157 hp += off;
158 sp += off;
159 esp = sp + Dy(r) * wid;
160 while(sp < esp){
161 memmove(hp, sp, w);
162 hp += wid;
163 sp += wid;
164 }
165 }
166
167 VGAdev vgavesadev = {
168 "vesa",
169 0,
170 0,
171 0,
172 vesalinear,
173 0,
174 0,
175 0,
176 0,
177 vesaflush,
178 };
Cache object: 28614c7e2c2ad42b848b6734ff76e26b
|