FreeBSD/Linux Kernel Cross Reference
sys/pc/vgamga4xx.c
1
2 /*
3 * Matrox G200, G400 and G450.
4 * Written by Philippe Anel <xigh@free.fr>
5 *
6 * 2006-08-07 : Minor fix to allow the G200 cards to work fine. YDSTORG is now initialized.
7 * : Also support for 16 and 24 bit modes is added.
8 * : by Leonardo Valencia <leoval@anixcorp.com>
9 */
10
11 #include "u.h"
12 #include "../port/lib.h"
13 #include "mem.h"
14 #include "dat.h"
15 #include "fns.h"
16 #include "io.h"
17 #include "../port/error.h"
18
19 #define Image IMAGE
20 #include <draw.h>
21 #include <memdraw.h>
22 #include <cursor.h>
23 #include "screen.h"
24
25 enum {
26 MATROX = 0x102B,
27 MGA550 = 0x2527,
28 MGA4xx = 0x0525,
29 MGA200 = 0x0521,
30
31 FCOL = 0x1c24,
32 FXRIGHT = 0x1cac,
33 FXLEFT = 0x1ca8,
34 YDST = 0x1c90,
35 YLEN = 0x1c5c,
36 DWGCTL = 0x1c00,
37 DWG_TRAP = 0x04,
38 DWG_BITBLT = 0x08,
39 DWG_ILOAD = 0x09,
40 DWG_LINEAR = 0x0080,
41 DWG_SOLID = 0x0800,
42 DWG_ARZERO = 0x1000,
43 DWG_SGNZERO = 0x2000,
44 DWG_SHIFTZERO = 0x4000,
45 DWG_REPLACE = 0x000C0000,
46 DWG_BFCOL = 0x04000000,
47 SRCORG = 0x2cb4,
48 PITCH = 0x1c8c,
49 DSTORG = 0x2cb8,
50 YDSTORG = 0x1c94,
51 PLNWRT = 0x1c1c,
52 ZORG = 0x1c0c,
53 MACCESS = 0x1c04,
54 STATUS = 0x1e14,
55 FXBNDRY = 0x1C84,
56 CXBNDRY = 0x1C80,
57 YTOP = 0x1C98,
58 YBOT = 0x1C9C,
59 YDSTLEN = 0x1C88,
60 AR0 = 0x1C60,
61 AR1 = 0x1C64,
62 AR2 = 0x1C68,
63 AR3 = 0x1C6C,
64 AR4 = 0x1C70,
65 AR5 = 0x1C74,
66 SGN = 0x1C58,
67 SGN_LEFT = 1,
68 SGN_UP = 4,
69
70 GO = 0x0100,
71 FIFOSTATUS = 0x1E10,
72 CACHEFLUSH = 0x1FFF,
73
74 CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */
75 CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */
76
77 FILL_OPERAND = 0x800c7804,
78 };
79
80 static Pcidev *
81 mgapcimatch(void)
82 {
83 Pcidev *p;
84
85 p = pcimatch(nil, MATROX, MGA4xx);
86 if(p == nil)
87 p = pcimatch(nil, MATROX, MGA550);
88 if(p == nil)
89 p = pcimatch(nil, MATROX, MGA200);
90 return p;
91 }
92
93
94 static void
95 mgawrite8(VGAscr *scr, int index, uchar val)
96 {
97 ((uchar*)scr->mmio)[index] = val;
98 }
99
100 static uchar
101 mgaread8(VGAscr *scr, int index)
102 {
103 return ((uchar*)scr->mmio)[index];
104 }
105
106 static uchar
107 crtcextset(VGAscr *scr, int index, uchar set, uchar clr)
108 {
109 uchar tmp;
110
111 mgawrite8(scr, CRTCEXTIDX, index);
112 tmp = mgaread8(scr, CRTCEXTDATA);
113 mgawrite8(scr, CRTCEXTIDX, index);
114 mgawrite8(scr, CRTCEXTDATA, (tmp & ~clr) | set);
115
116 return tmp;
117 }
118
119 static void
120 mga4xxenable(VGAscr* scr)
121 {
122 Pcidev *pci;
123 int size;
124 int i, n, k;
125 uchar *p;
126 uchar x[16];
127 uchar crtcext3;
128
129 if(scr->mmio)
130 return;
131
132 pci = mgapcimatch();
133 if(pci == nil)
134 return;
135
136 scr->mmio = vmap(pci->mem[1].bar&~0x0F, 16*1024);
137 if(scr->mmio == nil)
138 return;
139
140 addvgaseg("mga4xxmmio", pci->mem[1].bar&~0x0F, pci->mem[1].size);
141
142 /* need to map frame buffer here too, so vga can find memory size */
143 if(pci->did == MGA4xx || pci->did == MGA550)
144 size = 32*MB;
145 else
146 size = 8*MB;
147 vgalinearaddr(scr, pci->mem[0].bar&~0x0F, size);
148
149 if(scr->paddr){
150
151 /* Find out how much memory is here, some multiple of 2 MB */
152
153 /* First Set MGA Mode ... */
154 crtcext3 = crtcextset(scr, 3, 0x80, 0x00);
155
156 p = scr->vaddr;
157 n = (size / MB) / 2;
158 for(i = 0; i < n; i++){
159 k = (2*i+1)*MB;
160 p[k] = 0;
161 p[k] = i+1;
162 *((uchar*)scr->mmio + CACHEFLUSH) = 0;
163 x[i] = p[k];
164 }
165 for(i = 1; i < n; i++)
166 if(x[i] != i+1)
167 break;
168 scr->apsize = 2*i*MB; /* sketchy */
169 addvgaseg("mga4xxscreen", scr->paddr, scr->apsize);
170 crtcextset(scr, 3, crtcext3, 0xff);
171 }
172 }
173
174 enum{
175 Index = 0x00, /* Index */
176 Data = 0x0A, /* Data */
177
178 Cxlsb = 0x0C, /* Cursor X LSB */
179 Cxmsb = 0x0D, /* Cursor X MSB */
180 Cylsb = 0x0E, /* Cursor Y LSB */
181 Cymsb = 0x0F, /* Cursor Y MSB */
182
183 Icuradrl = 0x04, /* Cursor Base Address Low */
184 Icuradrh = 0x05, /* Cursor Base Address High */
185 Icctl = 0x06, /* Indirect Cursor Control */
186 };
187
188 static void
189 dac4xxdisable(VGAscr *scr)
190 {
191 uchar *dac4xx;
192
193 if(scr->mmio == 0)
194 return;
195
196 dac4xx = (uchar*)scr->mmio+0x3C00;
197
198 *(dac4xx+Index) = Icctl;
199 *(dac4xx+Data) = 0x00;
200 }
201
202 static void
203 dac4xxload(VGAscr *scr, Cursor *curs)
204 {
205 int y;
206 uchar *p;
207 uchar *dac4xx;
208
209 if(scr->mmio == 0)
210 return;
211
212 dac4xx = (uchar*)scr->mmio+0x3C00;
213
214 dac4xxdisable(scr);
215
216 p = (uchar*)scr->storage;
217 for(y = 0; y < 64; y++){
218 *p++ = 0; *p++ = 0; *p++ = 0;
219 *p++ = 0; *p++ = 0; *p++ = 0;
220 if(y < 16){
221 *p++ = curs->set[1+y*2];
222 *p++ = curs->set[y*2];
223 } else{
224 *p++ = 0; *p++ = 0;
225 }
226
227 *p++ = 0; *p++ = 0; *p++ = 0;
228 *p++ = 0; *p++ = 0; *p++ = 0;
229 if(y < 16){
230 *p++ = curs->set[1+y*2]|curs->clr[1+2*y];
231 *p++ = curs->set[y*2]|curs->clr[2*y];
232 } else{
233 *p++ = 0; *p++ = 0;
234 }
235 }
236 scr->offset.x = 64 + curs->offset.x;
237 scr->offset.y = 64 + curs->offset.y;
238
239 *(dac4xx+Index) = Icctl;
240 *(dac4xx+Data) = 0x03;
241 }
242
243 static int
244 dac4xxmove(VGAscr *scr, Point p)
245 {
246 int x, y;
247 uchar *dac4xx;
248
249 if(scr->mmio == 0)
250 return 1;
251
252 dac4xx = (uchar*)scr->mmio + 0x3C00;
253
254 x = p.x + scr->offset.x;
255 y = p.y + scr->offset.y;
256
257 *(dac4xx+Cxlsb) = x & 0xFF;
258 *(dac4xx+Cxmsb) = (x>>8) & 0x0F;
259
260 *(dac4xx+Cylsb) = y & 0xFF;
261 *(dac4xx+Cymsb) = (y>>8) & 0x0F;
262
263 return 0;
264 }
265
266 static void
267 dac4xxenable(VGAscr *scr)
268 {
269 uchar *dac4xx;
270 ulong storage;
271
272 if(scr->mmio == 0)
273 return;
274 dac4xx = (uchar*)scr->mmio+0x3C00;
275
276 dac4xxdisable(scr);
277
278 storage = (scr->apsize-4096)&~0x3ff;
279
280 *(dac4xx+Index) = Icuradrl;
281 *(dac4xx+Data) = 0xff & (storage >> 10);
282 *(dac4xx+Index) = Icuradrh;
283 *(dac4xx+Data) = 0xff & (storage >> 18);
284
285 scr->storage = (ulong)scr->vaddr + storage;
286
287 /* Show X11-Like Cursor */
288 *(dac4xx+Index) = Icctl;
289 *(dac4xx+Data) = 0x03;
290
291 /* Cursor Color 0 : White */
292 *(dac4xx+Index) = 0x08;
293 *(dac4xx+Data) = 0xff;
294 *(dac4xx+Index) = 0x09;
295 *(dac4xx+Data) = 0xff;
296 *(dac4xx+Index) = 0x0a;
297 *(dac4xx+Data) = 0xff;
298
299 /* Cursor Color 1 : Black */
300 *(dac4xx+Index) = 0x0c;
301 *(dac4xx+Data) = 0x00;
302 *(dac4xx+Index) = 0x0d;
303 *(dac4xx+Data) = 0x00;
304 *(dac4xx+Index) = 0x0e;
305 *(dac4xx+Data) = 0x00;
306
307 /* Cursor Color 2 : Red */
308 *(dac4xx+Index) = 0x10;
309 *(dac4xx+Data) = 0xff;
310 *(dac4xx+Index) = 0x11;
311 *(dac4xx+Data) = 0x00;
312 *(dac4xx+Index) = 0x12;
313 *(dac4xx+Data) = 0x00;
314
315 /*
316 * Load, locate and enable the
317 * 64x64 cursor in X11 mode.
318 */
319 dac4xxload(scr, &arrow);
320 dac4xxmove(scr, ZP);
321 }
322
323 static void
324 mga4xxblank(VGAscr *scr, int blank)
325 {
326 char *cp;
327 uchar *mga;
328 uchar seq1, crtcext1;
329
330 /* blank = 0 -> turn screen on */
331 /* blank = 1 -> turn screen off */
332
333 if(scr->mmio == 0)
334 return;
335 mga = (uchar*)scr->mmio;
336
337 if(blank == 0){
338 seq1 = 0x00;
339 crtcext1 = 0x00;
340 } else {
341 seq1 = 0x20;
342 crtcext1 = 0x10; /* Default value ... : standby */
343 cp = getconf("*dpms");
344 if(cp){
345 if(cistrcmp(cp, "standby") == 0)
346 crtcext1 = 0x10;
347 else if(cistrcmp(cp, "suspend") == 0)
348 crtcext1 = 0x20;
349 else if(cistrcmp(cp, "off") == 0)
350 crtcext1 = 0x30;
351 }
352 }
353
354 *(mga + 0x1fc4) = 1;
355 seq1 |= *(mga + 0x1fc5) & ~0x20;
356 *(mga + 0x1fc5) = seq1;
357
358 *(mga + 0x1fde) = 1;
359 crtcext1 |= *(mga + 0x1fdf) & ~0x30;
360 *(mga + 0x1fdf) = crtcext1;
361 }
362
363 static void
364 mgawrite32(uchar *mga, ulong reg, ulong val)
365 {
366 *((ulong*)(&mga[reg])) = val;
367 }
368
369 static ulong
370 mgaread32(uchar *mga, ulong reg)
371 {
372 return *((ulong*)(&mga[reg]));
373 }
374
375 static void
376 mga_fifo(uchar *mga, uchar n)
377 {
378 ulong t;
379
380 #define Timeout 100
381 for (t = 0; t < Timeout; t++)
382 if ((mgaread32(mga, FIFOSTATUS) & 0xff) >= n)
383 break;
384 if (t >= Timeout)
385 print("mga4xx: fifo timeout");
386 }
387
388 static int
389 mga4xxfill(VGAscr *scr, Rectangle r, ulong color)
390 {
391 uchar *mga;
392
393 if(scr->mmio == 0)
394 return 0;
395 mga = (uchar*)scr->mmio;
396
397 mga_fifo(mga, 7);
398 mgawrite32(mga, DWGCTL, 0);
399 mgawrite32(mga, FCOL, color);
400 mgawrite32(mga, FXLEFT, r.min.x);
401 mgawrite32(mga, FXRIGHT, r.max.x);
402 mgawrite32(mga, YDST, r.min.y);
403 mgawrite32(mga, YLEN, Dy(r));
404 mgawrite32(mga, DWGCTL + GO, FILL_OPERAND);
405
406 while(mgaread32(mga, STATUS) & 0x00010000)
407 ;
408
409 return 1;
410 }
411
412 static int
413 mga4xxscroll(VGAscr *scr, Rectangle dr, Rectangle sr)
414 {
415 uchar * mga;
416 int pitch;
417 int width, height;
418 ulong start, end, sgn;
419 Point sp, dp;
420
421 if(scr->mmio == 0)
422 return 0;
423 mga = (uchar*)scr->mmio;
424
425 assert(Dx(sr) == Dx(dr) && Dy(sr) == Dy(dr));
426
427 sp = sr.min;
428 dp = dr.min;
429 if(eqpt(sp, dp))
430 return 1;
431
432 pitch = Dx(scr->gscreen->r);
433 width = Dx(sr);
434 height = Dy(sr);
435 sgn = 0;
436
437 if(dp.y > sp.y && dp.y < sp.y + height){
438 sp.y += height - 1;
439 dp.y += height - 1;
440 sgn |= SGN_UP;
441 }
442
443 width--;
444 start = end = sp.x + (sp.y * pitch);
445
446 if(dp.x > sp.x && dp.x < sp.x + width){
447 start += width;
448 sgn |= SGN_LEFT;
449 }
450 else
451 end += width;
452
453 mga_fifo(mga, 8);
454 mgawrite32(mga, DWGCTL, 0);
455 mgawrite32(mga, SGN, sgn);
456 mgawrite32(mga, AR5, sgn & SGN_UP ? -pitch : pitch);
457 mgawrite32(mga, AR0, end);
458 mgawrite32(mga, AR3, start);
459 mgawrite32(mga, FXBNDRY, ((dp.x + width) << 16) | dp.x);
460 mgawrite32(mga, YDSTLEN, (dp.y << 16) | height);
461 mgawrite32(mga, DWGCTL + GO, DWG_BITBLT | DWG_SHIFTZERO | DWG_BFCOL | DWG_REPLACE);
462
463 while(mgaread32(mga, STATUS) & 0x00010000)
464 ;
465
466 return 1;
467 }
468
469 static void
470 mga4xxdrawinit(VGAscr *scr)
471 {
472 uchar *mga;
473
474 if(scr->mmio == 0)
475 return;
476
477 mga = (uchar*)scr->mmio;
478
479 mgawrite32(mga, SRCORG, 0);
480 mgawrite32(mga, DSTORG, 0);
481 mgawrite32(mga, YDSTORG, 0);
482 mgawrite32(mga, ZORG, 0);
483 mgawrite32(mga, PLNWRT, ~0);
484 mgawrite32(mga, FCOL, 0xffff0000);
485 mgawrite32(mga, CXBNDRY, 0xFFFF0000);
486 mgawrite32(mga, YTOP, 0);
487 mgawrite32(mga, YBOT, 0x01FFFFFF);
488 mgawrite32(mga, PITCH, Dx(scr->gscreen->r) & ((1 << 13) - 1));
489 switch(scr->gscreen->depth){
490 case 8:
491 mgawrite32(mga, MACCESS, 0);
492 break;
493 case 16:
494 mgawrite32(mga, MACCESS, 1);
495 break;
496 case 24:
497 mgawrite32(mga, MACCESS, 3);
498 break;
499 case 32:
500 mgawrite32(mga, MACCESS, 2);
501 break;
502 default:
503 return; /* depth not supported ! */
504 }
505 scr->fill = mga4xxfill;
506 scr->scroll = mga4xxscroll;
507 scr->blank = mga4xxblank;
508 }
509
510 VGAdev vgamga4xxdev = {
511 "mga4xx",
512 mga4xxenable, /* enable */
513 0, /* disable */
514 0, /* page */
515 0, /* linear */
516 mga4xxdrawinit,
517 };
518
519 VGAcur vgamga4xxcur = {
520 "mga4xxhwgc",
521 dac4xxenable,
522 dac4xxdisable,
523 dac4xxload,
524 dac4xxmove,
525 };
Cache object: 2395aa54ef613aac7d5369b2379e49c1
|