Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
 
2
/* Portions of this file derived from work with the following copyright */
3
 
4
 /***************************************************************************\
5
|*                                                                           *|
6
|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
7
|*                                                                           *|
8
|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
9
|*     international laws.  Users and possessors of this source code are     *|
10
|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
11
|*     use this code in individual and commercial software.                  *|
12
|*                                                                           *|
13
|*     Any use of this source code must include,  in the user documenta-     *|
14
|*     tion and  internal comments to the code,  notices to the end user     *|
15
|*     as follows:                                                           *|
16
|*                                                                           *|
17
|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
18
|*                                                                           *|
19
|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
20
|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
21
|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
22
|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
23
|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
24
|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
25
|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
26
|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
27
|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
28
|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
29
|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
30
|*                                                                           *|
31
|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
32
|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
33
|*     consisting  of "commercial  computer  software"  and  "commercial     *|
34
|*     computer  software  documentation,"  as such  terms  are  used in     *|
35
|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
36
|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
37
|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
38
|*     all U.S. Government End Users  acquire the source code  with only     *|
39
|*     those rights set forth herein.                                        *|
40
|*                                                                           *|
41
 \***************************************************************************/
42
 
43
#include "u.h"
44
#include "../port/lib.h"
45
#include "mem.h"
46
#include "dat.h"
47
#include "fns.h"
48
#include "io.h"
49
#include "../port/error.h"
50
 
51
#define	Image	IMAGE
52
#include <draw.h>
53
#include <memdraw.h>
54
#include <cursor.h>
55
#include "screen.h"
56
#include "nv_dma.h"
57
 
58
enum {
59
	Pramin = 0x00710000,
60
	Pramdac = 0x00680000,
61
	Fifo = 0x00800000,
62
	Pgraph = 0x00400000,
63
	Pfb = 0x00100000
64
};
65
 
66
enum {
67
	hwCurPos = Pramdac + 0x0300,
68
};
69
 
70
#define SKIPS 8
71
 
72
struct {
73
	ulong	*dmabase;
74
	int		dmacurrent;
75
	int		dmaput;
76
	int		dmafree;
77
	int		dmamax;
78
} nv;
79
 
80
static Pcidev*
81
nvidiapci(void)
82
{
83
	Pcidev *p;
84
 
85
	p = nil;
86
	while((p = pcimatch(p, 0x10DE, 0)) != nil){
87
		if(p->did >= 0x20 && p->ccrb == 3)	/* video card */
88
			return p;
89
	}
90
	return nil;
91
}
92
 
93
static void
94
nvidialinear(VGAscr*, int, int)
95
{
96
}
97
 
98
static void
99
nvidiaenable(VGAscr* scr)
100
{
101
	Pcidev *p;
102
	ulong *q;
103
	int tmp;
104
 
105
	if(scr->mmio)
106
		return;
107
	p = nvidiapci();
108
	if(p == nil)
109
		return;
110
	scr->id = p->did;
111
	scr->pci = p;
112
 
113
	scr->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
114
	if(scr->mmio == nil)
115
		return;
116
	addvgaseg("nvidiammio", p->mem[0].bar&~0x0F, p->mem[0].size);
117
 
118
	vgalinearpci(scr);
119
	if(scr->apsize)
120
		addvgaseg("nvidiascreen", scr->paddr, scr->apsize);
121
 
122
	/* find video memory size */
123
	switch (scr->id & 0x0ff0) {
124
	case 0x0020:
125
	case 0x00A0:
126
		q = (void*)((uchar*)scr->mmio + Pfb);
127
		tmp = *q;
128
		if (tmp & 0x0100) {
129
			scr->storage = ((tmp >> 12) & 0x0F) * 1024 + 1024 * 2;
130
		} else {
131
			tmp &= 0x03;
132
			if (tmp)
133
				scr->storage = (1024*1024*2) << tmp;
134
			else
135
				scr->storage = 1024*1024*32;
136
		}
137
		break;
138
	case 0x01A0:
139
		p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
140
		tmp = pcicfgr32(p, 0x7C);
141
		scr->storage = (((tmp >> 6) & 31) + 1) * 1024 * 1024;
142
		break;
143
	case 0x01F0:
144
		p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
145
		tmp = pcicfgr32(p, 0x84);
146
		scr->storage = (((tmp >> 4) & 127) + 1) * 1024 * 1024;
147
		break;
148
	default:
149
		q = (void*)((uchar*)scr->mmio + Pfb + 0x020C);
150
		tmp = (*q >> 20) & 0xFFF;
151
		if (tmp == 0)
152
			tmp = 16;
153
		scr->storage = tmp*1024*1024;
154
		break;
155
	}
156
}
157
 
158
static void
159
nvidiacurdisable(VGAscr* scr)
160
{
161
	if(scr->mmio == 0)
162
		return;
163
 
164
	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
165
}
166
 
167
 
168
static void
169
nvidiacurload(VGAscr* scr, Cursor* curs)
170
{
171
	ulong*	p;
172
	int	i,j;
173
	ushort	c,s;
174
	ulong	tmp;
175
 
176
	if(scr->mmio == 0)
177
		return;
178
 
179
	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
180
 
181
	switch (scr->id & 0x0ff0) {
182
	case 0x0020:
183
	case 0x00A0:
184
		p = (void*)((uchar*)scr->mmio + Pramin + 0x1E00 * 4);
185
		break;
186
	default:
187
		/*
188
		 * Reset the cursor location, since the kernel may
189
		 * have allocated less storage than aux/vga
190
		 * expected.
191
		 */
192
		tmp = scr->apsize - 96*1024;
193
		p = (void*)((uchar*)scr->vaddr + tmp);
194
		vgaxo(Crtx, 0x30, 0x80|(tmp>>17));
195
		vgaxo(Crtx, 0x31, (tmp>>11)<<2);
196
		vgaxo(Crtx, 0x2F, tmp>>24);
197
		break;
198
	}
199
 
200
	for(i=0; i<16; i++) {
201
		c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1];
202
		s = (curs->set[2 * i] << 8) | curs->set[2 * i+1];
203
		tmp = 0;
204
		for (j=0; j<16; j++){
205
			if(s&0x8000)
206
				tmp |= 0x80000000;
207
			else if(c&0x8000)
208
				tmp |= 0xFFFF0000;
209
			if (j&0x1){
210
				*p++ = tmp;
211
				tmp = 0;
212
			} else {
213
				tmp>>=16;
214
			}
215
			c<<=1;
216
			s<<=1;
217
		}
218
		for (j=0; j<8; j++)
219
			*p++ = 0;
220
	}
221
	for (i=0; i<256; i++)
222
		*p++ = 0;
223
 
224
	scr->offset = curs->offset;
225
	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
226
 
227
	return;
228
}
229
 
230
static int
231
nvidiacurmove(VGAscr* scr, Point p)
232
{
233
	ulong*	cursorpos;
234
 
235
	if(scr->mmio == 0)
236
		return 1;
237
 
238
	cursorpos = (void*)((uchar*)scr->mmio + hwCurPos);
239
	*cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF);
240
 
241
	return 0;
242
}
243
 
244
static void
245
nvidiacurenable(VGAscr* scr)
246
{
247
	nvidiaenable(scr);
248
	if(scr->mmio == 0)
249
		return;
250
 
251
	vgaxo(Crtx, 0x1F, 0x57);
252
 
253
	nvidiacurload(scr, &arrow);
254
	nvidiacurmove(scr, ZP);
255
 
256
	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
257
}
258
 
259
void
260
writeput(VGAscr *scr, int data)
261
{
262
	uchar	*p, scratch;
263
	ulong	*fifo;
264
 
265
	outb(0x3D0,0);
266
	p = scr->vaddr;
267
	scratch = *p;
268
	fifo = (void*)((uchar*)scr->mmio + Fifo);
269
	fifo[0x10] = (data << 2);
270
	USED(scratch);
271
}
272
 
273
ulong
274
readget(VGAscr *scr)
275
{
276
	ulong	*fifo;
277
 
278
	fifo = (void*)((uchar*)scr->mmio + Fifo);
279
	return (fifo[0x0011] >> 2);
280
}
281
 
282
void
283
nvdmakickoff(VGAscr *scr)
284
{
285
	if(nv.dmacurrent != nv.dmaput) {
286
		nv.dmaput = nv.dmacurrent;
287
		writeput(scr, nv.dmaput);
288
	}
289
}
290
 
291
static void
292
nvdmanext(ulong data)
293
{
294
	nv.dmabase[nv.dmacurrent++] = data;
295
}
296
 
297
void
298
nvdmawait(VGAscr *scr, int size)
299
{
300
	int dmaget;
301
 
302
	size++;
303
 
304
	while(nv.dmafree < size) {
305
		dmaget = readget(scr);
306
 
307
		if(nv.dmaput >= dmaget) {
308
			nv.dmafree = nv.dmamax - nv.dmacurrent;
309
			if(nv.dmafree < size) {
310
				nvdmanext(0x20000000);
311
				if(dmaget <= SKIPS) {
312
					if (nv.dmaput <= SKIPS) /* corner case - will be idle */
313
						writeput(scr, SKIPS + 1);
314
					do { dmaget = readget(scr); }
315
					while(dmaget <= SKIPS);
316
				}
317
				writeput(scr, SKIPS);
318
				nv.dmacurrent = nv.dmaput = SKIPS;
319
				nv.dmafree = dmaget - (SKIPS + 1);
320
			}
321
		} else
322
			nv.dmafree = dmaget - nv.dmacurrent - 1;
323
	}
324
}
325
 
326
 
327
static void
328
nvdmastart(VGAscr *scr, ulong tag, int size)
329
{
330
	if (nv.dmafree <= size)
331
		nvdmawait(scr, size);
332
	nvdmanext((size << 18) | tag);
333
	nv.dmafree -= (size + 1);
334
}
335
 
336
static void
337
waitforidle(VGAscr *scr)
338
{
339
	ulong*	pgraph;
340
	int x;
341
 
342
	pgraph = (void*)((uchar*)scr->mmio + Pgraph);
343
 
344
	x = 0;
345
	while((readget(scr) != nv.dmaput) && x++ < 1000000)
346
		;
347
	if(x >= 1000000)
348
		iprint("idle stat %lud put %d scr %#p pc %#p\n", readget(scr), nv.dmaput, scr, getcallerpc(&scr));
349
 
350
	x = 0;
351
	while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000)
352
		;
353
 
354
	if(x >= 1000000)
355
		iprint("idle stat %lud scrio %#p scr %#p pc %#p\n", *pgraph, scr->mmio, scr, getcallerpc(&scr));
356
}
357
 
358
static void
359
nvresetgraphics(VGAscr *scr)
360
{
361
	ulong	surfaceFormat, patternFormat, rectFormat, lineFormat;
362
	int		pitch, i;
363
 
364
	pitch = scr->gscreen->width*BY2WD;
365
 
366
	/*
367
	 * DMA is at the end of the virtual window,
368
	 * but we might have cut it short when mapping it.
369
	 */
370
	if(nv.dmabase == nil){
371
		if(scr->storage <= scr->apsize)
372
			nv.dmabase = (ulong*)((uchar*)scr->vaddr + scr->storage - 128*1024);
373
		else{
374
			nv.dmabase = (void*)vmap(scr->paddr + scr->storage - 128*1024, 128*1024);
375
			if(nv.dmabase == 0){
376
				hwaccel = 0;
377
				hwblank = 0;
378
				print("vmap nvidia dma failed\n");
379
				return;
380
			}
381
		}
382
	}
383
 
384
	for(i=0; i<SKIPS; i++)
385
		nv.dmabase[i] = 0x00000000;
386
 
387
	nv.dmabase[0x0 + SKIPS] = 0x00040000;
388
	nv.dmabase[0x1 + SKIPS] = 0x80000010;
389
	nv.dmabase[0x2 + SKIPS] = 0x00042000;
390
	nv.dmabase[0x3 + SKIPS] = 0x80000011;
391
	nv.dmabase[0x4 + SKIPS] = 0x00044000;
392
	nv.dmabase[0x5 + SKIPS] = 0x80000012;
393
	nv.dmabase[0x6 + SKIPS] = 0x00046000;
394
	nv.dmabase[0x7 + SKIPS] = 0x80000013;
395
	nv.dmabase[0x8 + SKIPS] = 0x00048000;
396
	nv.dmabase[0x9 + SKIPS] = 0x80000014;
397
	nv.dmabase[0xA + SKIPS] = 0x0004A000;
398
	nv.dmabase[0xB + SKIPS] = 0x80000015;
399
	nv.dmabase[0xC + SKIPS] = 0x0004C000;
400
	nv.dmabase[0xD + SKIPS] = 0x80000016;
401
	nv.dmabase[0xE + SKIPS] = 0x0004E000;
402
	nv.dmabase[0xF + SKIPS] = 0x80000017;
403
 
404
	nv.dmaput = 0;
405
	nv.dmacurrent = 16 + SKIPS;
406
	nv.dmamax = 8191;
407
	nv.dmafree = nv.dmamax - nv.dmacurrent;
408
 
409
	switch(scr->gscreen->depth) {
410
	case 32:
411
	case 24:
412
		surfaceFormat = SURFACE_FORMAT_DEPTH24;
413
		patternFormat = PATTERN_FORMAT_DEPTH24;
414
		rectFormat = RECT_FORMAT_DEPTH24;
415
		lineFormat = LINE_FORMAT_DEPTH24;
416
		break;
417
	case 16:
418
	case 15:
419
		surfaceFormat = SURFACE_FORMAT_DEPTH16;
420
		patternFormat = PATTERN_FORMAT_DEPTH16;
421
		rectFormat = RECT_FORMAT_DEPTH16;
422
		lineFormat = LINE_FORMAT_DEPTH16;
423
		break;
424
	default:
425
		surfaceFormat = SURFACE_FORMAT_DEPTH8;
426
		patternFormat = PATTERN_FORMAT_DEPTH8;
427
		rectFormat = RECT_FORMAT_DEPTH8;
428
		lineFormat = LINE_FORMAT_DEPTH8;
429
		break;
430
	}
431
 
432
	nvdmastart(scr, SURFACE_FORMAT, 4);
433
	nvdmanext(surfaceFormat);
434
	nvdmanext(pitch | (pitch << 16));
435
	nvdmanext(0);
436
	nvdmanext(0);
437
 
438
	nvdmastart(scr, PATTERN_FORMAT, 1);
439
	nvdmanext(patternFormat);
440
 
441
	nvdmastart(scr, RECT_FORMAT, 1);
442
	nvdmanext(rectFormat);
443
 
444
	nvdmastart(scr, LINE_FORMAT, 1);
445
	nvdmanext(lineFormat);
446
 
447
	nvdmastart(scr, PATTERN_COLOR_0, 4);
448
	nvdmanext(~0);
449
	nvdmanext(~0);
450
	nvdmanext(~0);
451
	nvdmanext(~0);
452
 
453
	nvdmastart(scr, ROP_SET, 1);
454
	nvdmanext(0xCC);
455
 
456
	nvdmakickoff(scr);
457
	waitforidle(scr);
458
}
459
 
460
 
461
static int
462
nvidiahwfill(VGAscr *scr, Rectangle r, ulong sval)
463
{
464
	nvdmastart(scr, RECT_SOLID_COLOR, 1);
465
	nvdmanext(sval);
466
 
467
	nvdmastart(scr, RECT_SOLID_RECTS(0), 2);
468
	nvdmanext((r.min.x << 16) | r.min.y);
469
	nvdmanext((Dx(r) << 16) | Dy(r));
470
 
471
	//if ( (Dy(r) * Dx(r)) >= 512)
472
		nvdmakickoff(scr);
473
 
474
	waitforidle(scr);
475
 
476
	return 1;
477
}
478
 
479
static int
480
nvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
481
{
482
	nvdmastart(scr, BLIT_POINT_SRC, 3);
483
	nvdmanext((sr.min.y << 16) | sr.min.x);
484
	nvdmanext((r.min.y << 16) | r.min.x);
485
	nvdmanext((Dy(r) << 16) | Dx(r));
486
 
487
	//if ( (Dy(r) * Dx(r)) >= 512)
488
		nvdmakickoff(scr);
489
 
490
	waitforidle(scr);
491
 
492
	return 1;
493
}
494
 
495
void
496
nvidiablank(VGAscr*, int blank)
497
{
498
	uchar seq1, crtc1A;
499
 
500
	seq1 = vgaxi(Seqx, 1) & ~0x20;
501
	crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0;
502
 
503
	if(blank){
504
		seq1 |= 0x20;
505
//		crtc1A |= 0xC0;
506
		crtc1A |= 0x80;
507
	}
508
 
509
	vgaxo(Seqx, 1, seq1);
510
	vgaxo(Crtx, 0x1A, crtc1A);
511
}
512
 
513
static void
514
nvidiadrawinit(VGAscr *scr)
515
{
516
	nvresetgraphics(scr);
517
	scr->blank = nvidiablank;
518
	hwblank = 1;
519
	scr->fill = nvidiahwfill;
520
	scr->scroll = nvidiahwscroll;
521
}
522
 
523
VGAdev vganvidiadev = {
524
	"nvidia",
525
 
526
	nvidiaenable,
527
	nil,
528
	nil,
529
	nvidialinear,
530
	nvidiadrawinit,
531
};
532
 
533
VGAcur vganvidiacur = {
534
	"nvidiahwgc",
535
 
536
	nvidiacurenable,
537
	nvidiacurdisable,
538
	nvidiacurload,
539
	nvidiacurmove,
540
};