FreeBSD/Linux Kernel Cross Reference
sys/pc/vganvidia.c
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 };
Cache object: 79c06e56ac2659de26002015018c3376
|