]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgaigfx.c
vgaigfx: check gtt to determine graphics memory size, add hw cursor support for g35...
[plan9front.git] / sys / src / 9 / pc / vgaigfx.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
9 #define Image   IMAGE
10 #include <draw.h>
11 #include <memdraw.h>
12 #include <cursor.h>
13 #include "screen.h"
14
15 static ulong
16 stolenmb(Pcidev *p)
17 {
18         switch(p->did){
19         case 0x0166:    /* Ivy Bridge */
20                 switch((pcicfgr16(p, 0x50) >> 3) & 0x1f){
21                 case 0x01:      return 32  - 2;
22                 case 0x02:      return 64  - 2;
23                 case 0x03:      return 96  - 2;
24                 case 0x04:      return 128 - 2;
25                 case 0x05:      return 32  - 2;
26                 case 0x06:      return 48  - 2;
27                 case 0x07:      return 64  - 2;
28                 case 0x08:      return 128 - 2;
29                 case 0x09:      return 256 - 2;
30                 case 0x0A:      return 96  - 2;
31                 case 0x0B:      return 160 - 2;
32                 case 0x0C:      return 224 - 2;
33                 case 0x0D:      return 352 - 2;
34                 case 0x0E:      return 448 - 2;
35                 case 0x0F:      return 480 - 2;
36                 case 0x10:      return 512 - 2;
37                 }
38                 break;
39         case 0x2a42:    /* X200 */
40         case 0x2a02:    /* CF-R7 */
41                 switch((pcicfgr16(p, 0x52) >> 4) & 7){
42                 case 0x01:      return 1;
43                 case 0x02:      return 4;
44                 case 0x03:      return 8;
45                 case 0x04:      return 16;
46                 case 0x05:      return 32;
47                 case 0x06:      return 48;
48                 case 0x07:      return 64;
49                 }
50                 break;
51         }
52         return 0;
53 }
54
55 static uintptr
56 gmsize(Pcidev *pci, void *mmio)
57 {
58         u32int x, i, npg, *gtt;
59
60         npg = stolenmb(pci)<<(20-12);
61         if(npg == 0)
62                 return 0;
63         gtt = (u32int*)((uchar*)mmio + pci->mem[0].size/2);
64         if((gtt[0]&1) == 0)
65                 return 0;
66         x = (gtt[0]>>12)+1;
67         for(i=1; i<npg; i++){
68                 if((gtt[i]&1) == 0 || (gtt[i]>>12) != x)
69                         break;
70                 x++;
71         }
72         if(0) print("igfx: graphics memory at %p-%p (%ud MB)\n", 
73                 (uintptr)(x-i)<<12, (uintptr)x<<12, (i>>(20-12)));
74         return (uintptr)i<<12;
75 }
76
77 static void
78 igfxenable(VGAscr* scr)
79 {
80         Pcidev *p;
81         
82         if(scr->mmio != nil)
83                 return;
84         p = scr->pci;
85         if(p == nil)
86                 return;
87         scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
88         if(scr->mmio == nil)
89                 return;
90         addvgaseg("igfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
91         if(scr->paddr == 0)
92                 vgalinearpci(scr);
93         if(scr->apsize){
94                 addvgaseg("igfxscreen", scr->paddr, scr->apsize);
95                 scr->storage = gmsize(p, scr->mmio);
96                 if(scr->storage < MB)
97                         scr->storage = 0;
98                 else if(scr->storage > scr->apsize)
99                         scr->storage = scr->apsize;
100                 if(scr->storage != 0)
101                         scr->storage -= PGROUND(64*64*4);
102         }
103 }
104
105 VGAdev vgaigfxdev = {
106         "igfx",
107         igfxenable,
108 };
109
110 static void
111 igfxcurload(VGAscr* scr, Cursor* curs)
112 {
113         uchar set, clr;
114         u32int *p;
115         int i, j;
116
117         if(scr->storage == 0)
118                 return;
119         p = (u32int*)((uchar*)scr->vaddr + scr->storage);
120         memset(p, 0, 64*64*4);
121         for(i=0;i<32;i++) {
122                 set = curs->set[i];
123                 clr = curs->clr[i];
124                 for(j=0x80; j; j>>=1){
125                         if((set|clr)&j)
126                                 *p++ = (0xFF<<24) | (set&j ? 0x000000 : 0xFFFFFF);
127                         else
128                                 *p++ = 0;
129                 }
130                 if(i & 1)
131                         p += 64-16;
132         }
133         scr->offset = curs->offset;
134 }
135
136 enum {
137         CURCTL = 0,
138         CURBASE,
139         CURPOS,
140
141         NPIPE = 3,
142 };
143
144 static u32int*
145 igfxcurregs(VGAscr* scr, int pipe)
146 {
147         u32int o;
148
149         if(scr->mmio == nil || scr->storage == 0)
150                 return nil;
151         o = pipe*0x1000;
152         /* check PIPExCONF if enabled */
153         if((scr->mmio[(0x70008 | o)/4] & (1<<31)) == 0)
154                 return nil;
155         switch(scr->pci->did){
156         case 0x0166:    /* Ivy Bridge */
157                 if(pipe > 2)
158                         return nil;
159                 break;
160         case 0x2a42:    /* X200 */
161         case 0x2a02:    /* CF-R7 */
162                 if(pipe > 1)
163                         return nil;
164                 o = pipe*0x40;
165                 break;
166         default:
167                 if(pipe > 0)
168                         return nil;
169         }
170         return (u32int*)((uchar*)scr->mmio + (0x70080 + o));
171 }
172
173 static int
174 igfxcurmove(VGAscr* scr, Point p)
175 {
176         int i, x, y;
177         u32int *r;
178
179         for(i=0; i<NPIPE; i++){
180                 if((r = igfxcurregs(scr, i)) != nil){
181                         x = p.x + scr->offset.x;
182                         if(x < 0) x = -x | 0x8000;
183                         y = p.y + scr->offset.y;
184                         if(y < 0) y = -y | 0x8000;
185                         r[CURPOS] = (y << 16) | x;
186                 }
187         }
188         return 0;
189 }
190
191 static void
192 igfxcurenable(VGAscr* scr)
193 {
194         u32int *r;
195         int i;
196
197         igfxenable(scr);
198         igfxcurload(scr, &arrow);
199         igfxcurmove(scr, ZP);
200
201         for(i=0; i<NPIPE; i++){
202                 if((r = igfxcurregs(scr, i)) != nil){
203                         r[CURCTL] = (r[CURCTL] & ~(3<<28 | 1<<5)) | (i<<28) | 7;
204                         r[CURBASE] = scr->storage;
205                 }
206         }
207 }
208
209 static void
210 igfxcurdisable(VGAscr* scr)
211 {
212         u32int *r;
213         int i;
214
215         for(i=0; i<NPIPE; i++){
216                 if((r = igfxcurregs(scr, i)) != nil){
217                         r[CURCTL] &= ~(1<<5 | 7);
218                         r[CURBASE] = 0;
219                 }
220         }
221 }
222
223 VGAcur vgaigfxcur = {
224         "igfxhwgc",
225         igfxcurenable,
226         igfxcurdisable,
227         igfxcurload,
228         igfxcurmove,
229 };