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