Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
};