more rendering corrections
[AROS.git] / workbench / hidds / hidd.nvidia / nvhardware.c
blob7627563c0d946eb1a67d2fdf6f2d564f7a252616
1 /*
2 Copyright © 2004-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: nvidia.hidd initialization
6 Lang: English
7 */
9 /***************************************************************************\
10 |* *|
11 |* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
12 |* *|
13 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
14 |* international laws. Users and possessors of this source code are *|
15 |* hereby granted a nonexclusive, royalty-free copyright license to *|
16 |* use this code in individual and commercial software. *|
17 |* *|
18 |* Any use of this source code must include, in the user documenta- *|
19 |* tion and internal comments to the code, notices to the end user *|
20 |* as follows: *|
21 |* *|
22 |* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
23 |* *|
24 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
25 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
26 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
27 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
28 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
29 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
30 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
31 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
32 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
33 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
34 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
35 |* *|
36 |* U.S. Government End Users. This source code is a "commercial *|
37 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
38 |* consisting of "commercial computer software" and "commercial *|
39 |* computer software documentation," as such terms are used in *|
40 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
41 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
42 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
43 |* all U.S. Government End Users acquire the source code with only *|
44 |* those rights set forth herein. *|
45 |* *|
46 \***************************************************************************/
49 #include <aros/libcall.h>
50 #include <aros/asmcall.h>
52 #include <exec/types.h>
53 #include <exec/nodes.h>
54 #include <exec/execbase.h>
55 #include <exec/resident.h>
56 #include <exec/libraries.h>
57 #include <exec/memory.h>
58 #include <exec/lists.h>
59 #include <exec/semaphores.h>
61 #include <utility/utility.h>
62 #include <utility/hooks.h>
63 #include <utility/tagitem.h>
65 #include <oop/oop.h>
67 #include <hidd/pci.h>
68 #include <hidd/graphics.h>
70 #define DEBUG 0
71 #include <aros/debug.h>
73 #include <proto/exec.h>
74 #include <proto/oop.h>
76 #include "nv.h"
77 #include "nv_local.h"
78 #include "nv_dma.h"
80 #define _sd sd
81 static inline __attribute__((always_inline))
82 ULONG pciReadLong(struct staticdata *sd,
83 UBYTE bus, UBYTE dev, UBYTE sub, UBYTE reg)
85 struct pHidd_PCIDriver_ReadConfigLong __msg = {
86 sd->mid_ReadLong,
87 bus, dev, sub, reg
88 }, *msg = &__msg;
90 return (ULONG)OOP_DoMethod(sd->pcidriver, (OOP_Msg)msg);
93 void nv4GetConfig(struct staticdata *sd)
95 struct Card *pNv = &sd->Card;
97 if (pNv->PFB[0x0000/4] & 0x00000100) {
98 pNv->RamAmountKBytes = ((pNv->PFB[0x0000/4] >> 12) & 0x0F) * 1024 * 2
99 + 1024 * 2;
100 } else {
101 switch (pNv->PFB[0x0000/4] & 0x00000003) {
102 case 0:
103 pNv->RamAmountKBytes = 1024 * 32;
104 break;
105 case 1:
106 pNv->RamAmountKBytes = 1024 * 4;
107 break;
108 case 2:
109 pNv->RamAmountKBytes = 1024 * 8;
110 break;
111 case 3:
112 default:
113 pNv->RamAmountKBytes = 1024 * 16;
114 break;
117 pNv->CrystalFreqKHz = (pNv->PEXTDEV[0x0000/4] & 0x00000040) ? 14318 : 13500;
118 pNv->CURSOR = &(pNv->PRAMIN[0x1E00]);
119 pNv->MinVClockFreqKHz = 12000;
120 pNv->MaxVClockFreqKHz = 350000;
123 void nv10GetConfig (struct staticdata *sd)
125 struct Card *pNv = &sd->Card;
126 ULONG implementation = pNv->Chipset & 0x0ff0;
128 #if AROS_BIG_ENDIAN
129 /* turn on big endian register access */
130 if(!(pNv->PMC[0x0004/4] & 0x01000001)) {
131 pNv->PMC[0x0004/4] = 0x01000001;
132 // mem_barrier();
134 #endif
136 if(implementation == 0x01a0) {
137 int amt = pciReadLong(sd, 0, 0, 1, 0x7C);
138 pNv->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
139 } else if(implementation == 0x01f0) {
140 int amt = pciReadLong(sd, 0, 0, 1, 0x84);
141 pNv->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
142 } else {
143 pNv->RamAmountKBytes = (pNv->PFB[0x020C/4] & 0xFFF00000) >> 10;
146 pNv->CrystalFreqKHz = (pNv->PEXTDEV[0x0000/4] & (1 << 6)) ? 14318 : 13500;
148 if(pNv->twoHeads && (implementation != 0x0110))
150 if(pNv->PEXTDEV[0x0000/4] & (1 << 22))
151 pNv->CrystalFreqKHz = 27000;
154 pNv->CursorStart = (pNv->RamAmountKBytes - 96) * 1024;
155 pNv->CURSOR = NULL; /* can't set this here */
156 pNv->MinVClockFreqKHz = 12000;
157 pNv->MaxVClockFreqKHz = pNv->twoStagePLL ? 400000 : 350000;
162 static inline void CRTC_out(struct staticdata *sd, UBYTE index, UBYTE val)
164 VGA_WR08(sd->Card.PCIO, 0x3d4, index);
165 VGA_WR08(sd->Card.PCIO, 0x3d5, val);
168 static inline UBYTE CRTC_in(struct staticdata *sd, UBYTE index)
170 VGA_WR08(sd->Card.PCIO, 0x3d4, index);
171 return VGA_RD08(sd->Card.PCIO, 0x3d5);
174 static inline void GRA_out(struct staticdata *sd, UBYTE index, UBYTE val)
176 VGA_WR08(sd->Card.PVIO, 0x3ce, index);
177 VGA_WR08(sd->Card.PVIO, 0x3cf, val);
180 static inline UBYTE GRA_in(struct staticdata *sd, UBYTE index)
182 VGA_WR08(sd->Card.PVIO, 0x3ce, index);
183 return VGA_RD08(sd->Card.PVIO, 0x3cf);
186 static inline void SEQ_out(struct staticdata *sd, UBYTE index, UBYTE val)
188 VGA_WR08(sd->Card.PVIO, 0x3c4, index);
189 VGA_WR08(sd->Card.PVIO, 0x3c5, val);
192 static inline UBYTE SEQ_in(struct staticdata *sd, UBYTE index)
194 VGA_WR08(sd->Card.PVIO, 0x3c4, index);
195 return VGA_RD08(sd->Card.PVIO, 0x3c5);
198 static inline void ATTR_out(struct staticdata *sd, UBYTE index, UBYTE val)
200 UBYTE tmp;
202 tmp = VGA_RD08(sd->Card.PCIO, 0x3da);
203 if (sd->Card.paletteEnabled)
204 index &= ~0x20;
205 else
206 index |= 0x20;
208 VGA_WR08(sd->Card.PCIO, 0x3c0, index);
209 VGA_WR08(sd->Card.PCIO, 0x3c0, val);
212 static inline UBYTE ATTR_in(struct staticdata *sd, UBYTE index)
214 UBYTE tmp;
216 tmp = VGA_RD08(sd->Card.PCIO, 0x3da);
217 if (sd->Card.paletteEnabled)
218 index &= ~0x20;
219 else
220 index |= 0x20;
221 VGA_WR08(sd->Card.PCIO, 0x3c0, index);
223 return VGA_RD08(sd->Card.PCIO, 0x3c1);
226 static inline void MISC_out(struct staticdata *sd, UBYTE val)
228 VGA_WR08(sd->Card.PVIO, 0x3c2, val);
231 static inline UBYTE MISC_in(struct staticdata *sd)
233 return VGA_RD08(sd->Card.PVIO, 0x3cc);
236 void NVLockUnlock(struct staticdata *sd, UBYTE Lock)
238 UBYTE cr11;
240 ObtainSemaphore(&sd->HWLock);
241 VGA_WR08(sd->Card.PCIO, 0x3D4, 0x1F);
242 VGA_WR08(sd->Card.PCIO, 0x3D5, Lock ? 0x99 : 0x57);
244 VGA_WR08(sd->Card.PCIO, 0x3D4, 0x11);
245 cr11 = VGA_RD08(sd->Card.PCIO, 0x3D5);
246 if(Lock) cr11 |= 0x80;
247 else cr11 &= ~0x80;
248 VGA_WR08(sd->Card.PCIO, 0x3D5, cr11);
249 ReleaseSemaphore(&sd->HWLock);
252 int NVShowHideCursor (struct staticdata *sd, UBYTE ShowHide)
254 int current = sd->Card.CurrentState->cursor1;
256 ObtainSemaphore(&sd->HWLock);
257 sd->Card.CurrentState->cursor1 = (sd->Card.CurrentState->cursor1 & 0xFE) |
258 (ShowHide & 0x01);
259 VGA_WR08(sd->Card.PCIO, 0x3D4, 0x31);
260 VGA_WR08(sd->Card.PCIO, 0x3D5, sd->Card.CurrentState->cursor1);
262 if (sd->Card.Architecture == NV_ARCH_40) { /* HW bug */
263 volatile ULONG curpos = sd->Card.PRAMDAC[0x0300/4];
264 sd->Card.PRAMDAC[0x0300/4] = curpos;
267 ReleaseSemaphore(&sd->HWLock);
268 return (current & 0x01);
271 /****************************************************************************\
273 * The video arbitration routines calculate some "magic" numbers. Fixes *
274 * the snow seen when accessing the framebuffer without it. *
275 * It just works (I hope). *
277 \****************************************************************************/
279 typedef struct {
280 int graphics_lwm;
281 int video_lwm;
282 int graphics_burst_size;
283 int video_burst_size;
284 int valid;
285 } nv4_fifo_info;
287 typedef struct {
288 int pclk_khz;
289 int mclk_khz;
290 int nvclk_khz;
291 char mem_page_miss;
292 char mem_latency;
293 int memory_width;
294 char enable_video;
295 char gr_during_vid;
296 char pix_bpp;
297 char mem_aligned;
298 char enable_mp;
299 } nv4_sim_state;
301 typedef struct {
302 int graphics_lwm;
303 int video_lwm;
304 int graphics_burst_size;
305 int video_burst_size;
306 int valid;
307 } nv10_fifo_info;
309 typedef struct {
310 int pclk_khz;
311 int mclk_khz;
312 int nvclk_khz;
313 char mem_page_miss;
314 char mem_latency;
315 int memory_type;
316 int memory_width;
317 char enable_video;
318 char gr_during_vid;
319 char pix_bpp;
320 char mem_aligned;
321 char enable_mp;
322 } nv10_sim_state;
324 static void nvGetClocks(NVPtr pNv, ULONG *MClk, ULONG *NVClk)
326 unsigned int pll, N, M, MB, NB, P;
328 if(pNv->Architecture >= NV_ARCH_40) {
329 pll = pNv->PMC[0x4020/4];
330 P = (pll >> 16) & 0x03;
331 pll = pNv->PMC[0x4024/4];
332 M = pll & 0xFF;
333 N = (pll >> 8) & 0xFF;
334 MB = (pll >> 16) & 0xFF;
335 NB = (pll >> 24) & 0xFF;
336 *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
338 pll = pNv->PMC[0x4000/4];
339 P = (pll >> 16) & 0x03;
340 pll = pNv->PMC[0x4004/4];
341 M = pll & 0xFF;
342 N = (pll >> 8) & 0xFF;
343 MB = (pll >> 16) & 0xFF;
344 NB = (pll >> 24) & 0xFF;
346 *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
347 } else
348 if(pNv->twoStagePLL) {
349 pll = pNv->PRAMDAC0[0x0504/4];
350 M = pll & 0xFF;
351 N = (pll >> 8) & 0xFF;
352 P = (pll >> 16) & 0x0F;
353 pll = pNv->PRAMDAC0[0x0574/4];
354 if(pll & 0x80000000) {
355 MB = pll & 0xFF;
356 NB = (pll >> 8) & 0xFF;
357 } else {
358 MB = 1;
359 NB = 1;
361 *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
363 pll = pNv->PRAMDAC0[0x0500/4];
364 M = pll & 0xFF;
365 N = (pll >> 8) & 0xFF;
366 P = (pll >> 16) & 0x0F;
367 pll = pNv->PRAMDAC0[0x0570/4];
368 if(pll & 0x80000000) {
369 MB = pll & 0xFF;
370 NB = (pll >> 8) & 0xFF;
371 } else {
372 MB = 1;
373 NB = 1;
375 *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
376 } else
377 if(((pNv->Chipset & 0x0ff0) == 0x0300) ||
378 ((pNv->Chipset & 0x0ff0) == 0x0330))
380 pll = pNv->PRAMDAC0[0x0504/4];
381 M = pll & 0x0F;
382 N = (pll >> 8) & 0xFF;
383 P = (pll >> 16) & 0x07;
384 if(pll & 0x00000080) {
385 MB = (pll >> 4) & 0x07;
386 NB = (pll >> 19) & 0x1f;
387 } else {
388 MB = 1;
389 NB = 1;
391 *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
393 pll = pNv->PRAMDAC0[0x0500/4];
394 M = pll & 0x0F;
395 N = (pll >> 8) & 0xFF;
396 P = (pll >> 16) & 0x07;
397 if(pll & 0x00000080) {
398 MB = (pll >> 4) & 0x07;
399 NB = (pll >> 19) & 0x1f;
400 } else {
401 MB = 1;
402 NB = 1;
404 *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
405 } else {
406 pll = pNv->PRAMDAC0[0x0504/4];
407 M = pll & 0xFF;
408 N = (pll >> 8) & 0xFF;
409 P = (pll >> 16) & 0x0F;
410 *MClk = (N * pNv->CrystalFreqKHz / M) >> P;
412 pll = pNv->PRAMDAC0[0x0500/4];
413 M = pll & 0xFF;
414 N = (pll >> 8) & 0xFF;
415 P = (pll >> 16) & 0x0F;
416 *NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
420 static void nv4CalcArbitration (
421 nv4_fifo_info *fifo,
422 nv4_sim_state *arb
425 int data, pagemiss, cas,width, video_enable, bpp;
426 int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
427 int found, mclk_extra, mclk_loop, cbs, m1, p1;
428 int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
429 int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
430 int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
432 fifo->valid = 1;
433 pclk_freq = arb->pclk_khz;
434 mclk_freq = arb->mclk_khz;
435 nvclk_freq = arb->nvclk_khz;
436 pagemiss = arb->mem_page_miss;
437 cas = arb->mem_latency;
438 width = arb->memory_width >> 6;
439 video_enable = arb->enable_video;
440 bpp = arb->pix_bpp;
441 mp_enable = arb->enable_mp;
442 clwm = 0;
443 vlwm = 0;
444 cbs = 128;
445 pclks = 2;
446 nvclks = 2;
447 nvclks += 2;
448 nvclks += 1;
449 mclks = 5;
450 mclks += 3;
451 mclks += 1;
452 mclks += cas;
453 mclks += 1;
454 mclks += 1;
455 mclks += 1;
456 mclks += 1;
457 mclk_extra = 3;
458 nvclks += 2;
459 nvclks += 1;
460 nvclks += 1;
461 nvclks += 1;
462 if (mp_enable)
463 mclks+=4;
464 nvclks += 0;
465 pclks += 0;
466 found = 0;
467 vbs = 0;
468 while (found != 1)
470 fifo->valid = 1;
471 found = 1;
472 mclk_loop = mclks+mclk_extra;
473 us_m = mclk_loop *1000*1000 / mclk_freq;
474 us_n = nvclks*1000*1000 / nvclk_freq;
475 us_p = nvclks*1000*1000 / pclk_freq;
476 if (video_enable)
478 video_drain_rate = pclk_freq * 2;
479 crtc_drain_rate = pclk_freq * bpp/8;
480 vpagemiss = 2;
481 vpagemiss += 1;
482 crtpagemiss = 2;
483 vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
484 if (nvclk_freq * 2 > mclk_freq * width)
485 video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
486 else
487 video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
488 us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
489 vlwm = us_video * video_drain_rate/(1000*1000);
490 vlwm++;
491 vbs = 128;
492 if (vlwm > 128) vbs = 64;
493 if (vlwm > (256-64)) vbs = 32;
494 if (nvclk_freq * 2 > mclk_freq * width)
495 video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
496 else
497 video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
498 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
499 us_crt =
500 us_video
501 +video_fill_us
502 +cpm_us
503 +us_m + us_n +us_p
505 clwm = us_crt * crtc_drain_rate/(1000*1000);
506 clwm++;
508 else
510 crtc_drain_rate = pclk_freq * bpp/8;
511 crtpagemiss = 2;
512 crtpagemiss += 1;
513 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
514 us_crt = cpm_us + us_m + us_n + us_p ;
515 clwm = us_crt * crtc_drain_rate/(1000*1000);
516 clwm++;
518 m1 = clwm + cbs - 512;
519 p1 = m1 * pclk_freq / mclk_freq;
520 p1 = p1 * bpp / 8;
521 if ((p1 < m1) && (m1 > 0))
523 fifo->valid = 0;
524 found = 0;
525 if (mclk_extra ==0) found = 1;
526 mclk_extra--;
528 else if (video_enable)
530 if ((clwm > 511) || (vlwm > 255))
532 fifo->valid = 0;
533 found = 0;
534 if (mclk_extra ==0) found = 1;
535 mclk_extra--;
538 else
540 if (clwm > 519)
542 fifo->valid = 0;
543 found = 0;
544 if (mclk_extra ==0) found = 1;
545 mclk_extra--;
548 if (clwm < 384) clwm = 384;
549 if (vlwm < 128) vlwm = 128;
550 data = (int)(clwm);
551 fifo->graphics_lwm = data;
552 fifo->graphics_burst_size = 128;
553 data = (int)((vlwm+15));
554 fifo->video_lwm = data;
555 fifo->video_burst_size = vbs;
559 static void nv4UpdateArbitrationSettings (
560 ULONG VClk,
561 ULONG pixelDepth,
562 ULONG *burst,
563 ULONG *lwm,
564 NVPtr pNv
567 nv4_fifo_info fifo_data;
568 nv4_sim_state sim_data;
569 ULONG MClk, NVClk, cfg1;
571 nvGetClocks(pNv, &MClk, &NVClk);
573 cfg1 = pNv->PFB[0x00000204/4];
574 sim_data.pix_bpp = (char)pixelDepth;
575 sim_data.enable_video = 0;
576 sim_data.enable_mp = 0;
577 sim_data.memory_width = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64;
578 sim_data.mem_latency = (char)cfg1 & 0x0F;
579 sim_data.mem_aligned = 1;
580 sim_data.mem_page_miss = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
581 sim_data.gr_during_vid = 0;
582 sim_data.pclk_khz = VClk;
583 sim_data.mclk_khz = MClk;
584 sim_data.nvclk_khz = NVClk;
585 nv4CalcArbitration(&fifo_data, &sim_data);
586 if (fifo_data.valid)
588 int b = fifo_data.graphics_burst_size >> 4;
589 *burst = 0;
590 while (b >>= 1) (*burst)++;
591 *lwm = fifo_data.graphics_lwm >> 3;
595 static void nv10CalcArbitration (
596 nv10_fifo_info *fifo,
597 nv10_sim_state *arb
600 int data, pagemiss, width, video_enable, bpp;
601 int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
602 int nvclk_fill;
603 int found, mclk_extra, mclk_loop, cbs, m1;
604 int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
605 int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
606 int vus_m;
607 int vpm_us, us_video, cpm_us, us_crt,clwm;
608 int clwm_rnd_down;
609 int m2us, us_pipe_min, p1clk, p2;
610 int min_mclk_extra;
611 int us_min_mclk_extra;
613 fifo->valid = 1;
614 pclk_freq = arb->pclk_khz; /* freq in KHz */
615 mclk_freq = arb->mclk_khz;
616 nvclk_freq = arb->nvclk_khz;
617 pagemiss = arb->mem_page_miss;
618 width = arb->memory_width/64;
619 video_enable = arb->enable_video;
620 bpp = arb->pix_bpp;
621 mp_enable = arb->enable_mp;
622 clwm = 0;
624 cbs = 512;
626 pclks = 4; /* lwm detect. */
628 nvclks = 3; /* lwm -> sync. */
629 nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
631 mclks = 1; /* 2 edge sync. may be very close to edge so just put one. */
633 mclks += 1; /* arb_hp_req */
634 mclks += 5; /* ap_hp_req tiling pipeline */
636 mclks += 2; /* tc_req latency fifo */
637 mclks += 2; /* fb_cas_n_ memory request to fbio block */
638 mclks += 7; /* sm_d_rdv data returned from fbio block */
640 /* fb.rd.d.Put_gc need to accumulate 256 bits for read */
641 if (arb->memory_type == 0)
642 if (arb->memory_width == 64) /* 64 bit bus */
643 mclks += 4;
644 else
645 mclks += 2;
646 else
647 if (arb->memory_width == 64) /* 64 bit bus */
648 mclks += 2;
649 else
650 mclks += 1;
652 if ((!video_enable) && (arb->memory_width == 128))
654 mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
655 min_mclk_extra = 17;
657 else
659 mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
660 /* mclk_extra = 4; */ /* Margin of error */
661 min_mclk_extra = 18;
664 nvclks += 1; /* 2 edge sync. may be very close to edge so just put one. */
665 nvclks += 1; /* fbi_d_rdv_n */
666 nvclks += 1; /* Fbi_d_rdata */
667 nvclks += 1; /* crtfifo load */
669 if(mp_enable)
670 mclks+=4; /* Mp can get in with a burst of 8. */
671 /* Extra clocks determined by heuristics */
673 nvclks += 0;
674 pclks += 0;
675 found = 0;
676 while(found != 1) {
677 fifo->valid = 1;
678 found = 1;
679 mclk_loop = mclks+mclk_extra;
680 us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
681 us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
682 us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
683 us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
684 us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
685 us_pipe_min = us_m_min + us_n + us_p;
687 vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
689 if(video_enable) {
690 crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
692 vpagemiss = 1; /* self generating page miss */
693 vpagemiss += 1; /* One higher priority before */
695 crtpagemiss = 2; /* self generating page miss */
696 if(mp_enable)
697 crtpagemiss += 1; /* if MA0 conflict */
699 vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
701 us_video = vpm_us + vus_m; /* Video has separate read return path */
703 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
704 us_crt =
705 us_video /* Wait for video */
706 +cpm_us /* CRT Page miss */
707 +us_m + us_n +us_p /* other latency */
710 clwm = us_crt * crtc_drain_rate/(1000*1000);
711 clwm++; /* fixed point <= float_point - 1. Fixes that */
712 } else {
713 crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
715 crtpagemiss = 1; /* self generating page miss */
716 crtpagemiss += 1; /* MA0 page miss */
717 if(mp_enable)
718 crtpagemiss += 1; /* if MA0 conflict */
719 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
720 us_crt = cpm_us + us_m + us_n + us_p ;
721 clwm = us_crt * crtc_drain_rate/(1000*1000);
722 clwm++; /* fixed point <= float_point - 1. Fixes that */
724 /* Finally, a heuristic check when width == 64 bits */
725 if(width == 1){
726 nvclk_fill = nvclk_freq * 8;
727 if(crtc_drain_rate * 100 >= nvclk_fill * 102)
728 clwm = 0xfff; /*Large number to fail */
730 else if(crtc_drain_rate * 100 >= nvclk_fill * 98) {
731 clwm = 1024;
732 cbs = 512;
739 Overfill check:
743 clwm_rnd_down = ((int)clwm/8)*8;
744 if (clwm_rnd_down < clwm)
745 clwm += 8;
747 m1 = clwm + cbs - 1024; /* Amount of overfill */
748 m2us = us_pipe_min + us_min_mclk_extra;
750 /* pclk cycles to drain */
751 p1clk = m2us * pclk_freq/(1000*1000);
752 p2 = p1clk * bpp / 8; /* bytes drained. */
754 if((p2 < m1) && (m1 > 0)) {
755 fifo->valid = 0;
756 found = 0;
757 if(min_mclk_extra == 0) {
758 if(cbs <= 32) {
759 found = 1; /* Can't adjust anymore! */
760 } else {
761 cbs = cbs/2; /* reduce the burst size */
763 } else {
764 min_mclk_extra--;
766 } else {
767 if (clwm > 1023){ /* Have some margin */
768 fifo->valid = 0;
769 found = 0;
770 if(min_mclk_extra == 0)
771 found = 1; /* Can't adjust anymore! */
772 else
773 min_mclk_extra--;
777 if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
778 data = (int)(clwm);
779 /* printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
780 fifo->graphics_lwm = data; fifo->graphics_burst_size = cbs;
782 fifo->video_lwm = 1024; fifo->video_burst_size = 512;
786 static void nv10UpdateArbitrationSettings (
787 ULONG VClk,
788 ULONG pixelDepth,
789 ULONG *burst,
790 ULONG *lwm,
791 NVPtr pNv
794 nv10_fifo_info fifo_data;
795 nv10_sim_state sim_data;
796 ULONG MClk, NVClk, cfg1;
798 nvGetClocks(pNv, &MClk, &NVClk);
800 cfg1 = pNv->PFB[0x0204/4];
801 sim_data.pix_bpp = (char)pixelDepth;
802 sim_data.enable_video = 1;
803 sim_data.enable_mp = 0;
804 sim_data.memory_type = (pNv->PFB[0x0200/4] & 0x01) ? 1 : 0;
805 sim_data.memory_width = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64;
806 sim_data.mem_latency = (char)cfg1 & 0x0F;
807 sim_data.mem_aligned = 1;
808 sim_data.mem_page_miss = (char)(((cfg1>>4) &0x0F) + ((cfg1>>31) & 0x01));
809 sim_data.gr_during_vid = 0;
810 sim_data.pclk_khz = VClk;
811 sim_data.mclk_khz = MClk;
812 sim_data.nvclk_khz = NVClk;
814 nv10CalcArbitration(&fifo_data, &sim_data);
815 if (fifo_data.valid) {
816 int b = fifo_data.graphics_burst_size >> 4;
817 *burst = 0;
818 while (b >>= 1) (*burst)++;
819 *lwm = fifo_data.graphics_lwm >> 3;
823 static void nv30UpdateArbitrationSettings (
824 NVPtr pNv,
825 ULONG *burst,
826 ULONG *lwm
829 ULONG MClk, NVClk;
830 unsigned int fifo_size, burst_size, graphics_lwm;
832 fifo_size = 2048;
833 burst_size = 512;
834 graphics_lwm = fifo_size - burst_size;
836 nvGetClocks(pNv, &MClk, &NVClk);
838 *burst = 0;
839 burst_size >>= 5;
840 while(burst_size >>= 1) (*burst)++;
841 *lwm = graphics_lwm >> 3;
844 static void nForceUpdateArbitrationSettings (
845 ULONG VClk,
846 ULONG pixelDepth,
847 ULONG *burst,
848 ULONG *lwm,
849 struct staticdata *sd,
850 NVPtr pNv
853 nv10_fifo_info fifo_data;
854 nv10_sim_state sim_data;
855 unsigned int M, N, P, pll, MClk, NVClk, memctrl;
857 if((pNv->Chipset & 0x0FF0) == 0x01A0) {
858 unsigned int uMClkPostDiv;
860 uMClkPostDiv = (pciReadLong(sd, 0, 0, 3, 0x6C) >> 8) & 0xf;
861 if(!uMClkPostDiv) uMClkPostDiv = 4;
862 MClk = 400000 / uMClkPostDiv;
863 } else {
864 MClk = pciReadLong(sd, 0, 0, 5, 0x4C) / 1000;
867 pll = pNv->PRAMDAC0[0x0500/4];
868 M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
869 NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
870 sim_data.pix_bpp = (char)pixelDepth;
871 sim_data.enable_video = 0;
872 sim_data.enable_mp = 0;
873 sim_data.memory_type = (pciReadLong(sd, 0, 0, 1, 0x7C) >> 12) & 1;
874 sim_data.memory_width = 64;
876 memctrl = pciReadLong(sd, 0, 0, 3, 0x00) >> 16;
878 if((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
879 int dimm[3];
881 dimm[0] = (pciReadLong(sd, 0, 0, 2, 0x40) >> 8) & 0x4F;
882 dimm[1] = (pciReadLong(sd, 0, 0, 2, 0x44) >> 8) & 0x4F;
883 dimm[2] = (pciReadLong(sd, 0, 0, 2, 0x48) >> 8) & 0x4F;
885 if((dimm[0] + dimm[1]) != dimm[2]) {
886 bug("WARNING: "
887 "your nForce DIMMs are not arranged in optimal banks!\n");
891 sim_data.mem_latency = 3;
892 sim_data.mem_aligned = 1;
893 sim_data.mem_page_miss = 10;
894 sim_data.gr_during_vid = 0;
895 sim_data.pclk_khz = VClk;
896 sim_data.mclk_khz = MClk;
897 sim_data.nvclk_khz = NVClk;
898 nv10CalcArbitration(&fifo_data, &sim_data);
899 if (fifo_data.valid)
901 int b = fifo_data.graphics_burst_size >> 4;
902 *burst = 0;
903 while (b >>= 1) (*burst)++;
904 *lwm = fifo_data.graphics_lwm >> 3;
908 /****************************************************************************\
910 * RIVA Mode State Routines *
912 \****************************************************************************/
915 * Calculate the Video Clock parameters for the PLL.
917 static void CalcVClock (
918 ULONG clockIn,
919 ULONG *clockOut,
920 ULONG *pllOut,
921 NVPtr pNv
924 unsigned lowM, highM;
925 unsigned DeltaNew, DeltaOld;
926 unsigned VClk, Freq;
927 unsigned M, N, P;
929 DeltaOld = 0xFFFFFFFF;
931 VClk = (unsigned)clockIn;
933 if (pNv->CrystalFreqKHz == 13500) {
934 lowM = 7;
935 highM = 13;
936 } else {
937 lowM = 8;
938 highM = 14;
941 for (P = 0; P <= 4; P++) {
942 Freq = VClk << P;
943 if ((Freq >= 128000) && (Freq <= 350000)) {
944 for (M = lowM; M <= highM; M++) {
945 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
946 if(N <= 255) {
947 Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
948 if (Freq > VClk)
949 DeltaNew = Freq - VClk;
950 else
951 DeltaNew = VClk - Freq;
952 if (DeltaNew < DeltaOld) {
953 *pllOut = (P << 16) | (N << 8) | M;
954 *clockOut = Freq;
955 DeltaOld = DeltaNew;
963 static void CalcVClock2Stage (
964 ULONG clockIn,
965 ULONG *clockOut,
966 ULONG *pllOut,
967 ULONG *pllBOut,
968 NVPtr pNv
971 unsigned DeltaNew, DeltaOld;
972 unsigned VClk, Freq;
973 unsigned M, N, P;
975 DeltaOld = 0xFFFFFFFF;
977 *pllBOut = 0x80000401; /* fixed at x4 for now */
979 VClk = (unsigned)clockIn;
981 for (P = 0; P <= 6; P++) {
982 Freq = VClk << P;
983 if ((Freq >= 400000) && (Freq <= 1000000)) {
984 for (M = 1; M <= 13; M++) {
985 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
986 if((N >= 5) && (N <= 255)) {
987 Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
988 if (Freq > VClk)
989 DeltaNew = Freq - VClk;
990 else
991 DeltaNew = VClk - Freq;
992 if (DeltaNew < DeltaOld) {
993 *pllOut = (P << 16) | (N << 8) | M;
994 *clockOut = Freq;
995 DeltaOld = DeltaNew;
1005 * Calculate extended mode parameters (SVGA) and save in a
1006 * mode state structure.
1008 void NVCalcStateExt (
1009 struct staticdata *sd,
1010 NVPtr pNv,
1011 RIVA_HW_STATE *state,
1012 int bpp,
1013 int width,
1014 int hDisplaySize,
1015 int height,
1016 int dotClock,
1017 int flags
1020 ULONG pixelDepth, VClk;
1022 * Save mode parameters.
1024 state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */
1025 state->width = width;
1026 state->height = height;
1028 * Extended RIVA registers.
1030 pixelDepth = (bpp + 1)/8;
1032 if(pNv->twoStagePLL)
1033 CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
1034 else
1035 CalcVClock(dotClock, &VClk, &state->pll, pNv);
1037 switch (pNv->Architecture)
1039 case NV_ARCH_04:
1040 nv4UpdateArbitrationSettings(VClk,
1041 pixelDepth * 8,
1042 &(state->arbitration0),
1043 &(state->arbitration1),
1044 pNv);
1045 state->cursor0 = 0x00;
1046 state->cursor1 = 0xbC;
1047 if (flags & V_DBLSCAN)
1048 state->cursor1 |= 2;
1049 state->cursor2 = 0x00000000;
1050 state->pllsel = 0x10000700;
1051 state->config = 0x00001114;
1052 state->general = bpp == 16 ? 0x00101100 : 0x00100100;
1053 state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1054 break;
1055 case NV_ARCH_10:
1056 case NV_ARCH_20:
1057 case NV_ARCH_30:
1058 default:
1059 if(((pNv->Chipset & 0xffff) == 0x01A0) ||
1060 ((pNv->Chipset & 0xffff) == 0x01f0))
1062 nForceUpdateArbitrationSettings(VClk,
1063 pixelDepth * 8,
1064 &(state->arbitration0),
1065 &(state->arbitration1),
1067 pNv);
1068 } else if (pNv->Architecture < NV_ARCH_30) {
1069 nv10UpdateArbitrationSettings(VClk,
1070 pixelDepth * 8,
1071 &(state->arbitration0),
1072 &(state->arbitration1),
1073 pNv);
1074 } else {
1075 nv30UpdateArbitrationSettings(pNv,
1076 &(state->arbitration0),
1077 &(state->arbitration1));
1079 state->cursor0 = 0x80 | (pNv->CursorStart >> 17);
1080 state->cursor1 = (pNv->CursorStart >> 11) << 2;
1081 state->cursor2 = pNv->CursorStart >> 24;
1082 if (flags & V_DBLSCAN)
1083 state->cursor1 |= 2;
1084 state->pllsel = 0x10000700;
1085 state->config = pNv->PFB[0x00000200/4];
1086 state->general = bpp == 16 ? 0x00101100 : 0x00100100;
1087 state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1088 break;
1090 if(bpp != 8) /* DirectColor */
1091 state->general |= 0x00000030;
1093 state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
1094 state->pixel = (pixelDepth > 2) ? 3 : pixelDepth;
1098 ** stegerg: Status NVLoadStateExt(): should "match" xfree nv NVLoadStateExt()
1099 ** in xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c version:
1100 ** 1.12 2004/11/30 23:50:26 mvojkovi
1102 ** Exception: some waitvsyncpossible stuff commented out
1105 void NVLoadStateExt (
1106 NVPtr pNv,
1107 RIVA_HW_STATE *state
1110 int i;
1112 pNv->PMC[0x0140/4] = 0x00000000;
1113 pNv->PMC[0x0200/4] = 0xFFFF00FF;
1114 pNv->PMC[0x0200/4] = 0xFFFFFFFF;
1116 pNv->PTIMER[0x0200] = 0x00000008;
1117 pNv->PTIMER[0x0210] = 0x00000003;
1118 pNv->PTIMER[0x0140] = 0x00000000;
1119 pNv->PTIMER[0x0100] = 0xFFFFFFFF;
1121 if(pNv->Architecture == NV_ARCH_04) {
1122 pNv->PFB[0x0200/4] = state->config;
1123 } else {
1124 pNv->PFB[0x0240/4] = 0;
1125 pNv->PFB[0x0244/4] = pNv->FrameBufferSize - 1;
1126 pNv->PFB[0x0250/4] = 0;
1127 pNv->PFB[0x0254/4] = pNv->FrameBufferSize - 1;
1128 pNv->PFB[0x0260/4] = 0;
1129 pNv->PFB[0x0264/4] = pNv->FrameBufferSize - 1;
1130 pNv->PFB[0x0270/4] = 0;
1131 pNv->PFB[0x0274/4] = pNv->FrameBufferSize - 1;
1132 pNv->PFB[0x0280/4] = 0;
1133 pNv->PFB[0x0284/4] = pNv->FrameBufferSize - 1;
1134 pNv->PFB[0x0290/4] = 0;
1135 pNv->PFB[0x0294/4] = pNv->FrameBufferSize - 1;
1136 pNv->PFB[0x02A0/4] = 0;
1137 pNv->PFB[0x02A4/4] = pNv->FrameBufferSize - 1;
1138 pNv->PFB[0x02B0/4] = 0;
1139 pNv->PFB[0x02B4/4] = pNv->FrameBufferSize - 1;
1142 if(pNv->Architecture >= NV_ARCH_40) {
1143 pNv->PRAMIN[0x0000] = 0x80000010;
1144 pNv->PRAMIN[0x0001] = 0x00101202;
1145 pNv->PRAMIN[0x0002] = 0x80000011;
1146 pNv->PRAMIN[0x0003] = 0x00101204;
1147 pNv->PRAMIN[0x0004] = 0x80000012;
1148 pNv->PRAMIN[0x0005] = 0x00101206;
1149 pNv->PRAMIN[0x0006] = 0x80000013;
1150 pNv->PRAMIN[0x0007] = 0x00101208;
1151 pNv->PRAMIN[0x0008] = 0x80000014;
1152 pNv->PRAMIN[0x0009] = 0x0010120A;
1153 pNv->PRAMIN[0x000A] = 0x80000015;
1154 pNv->PRAMIN[0x000B] = 0x0010120C;
1155 pNv->PRAMIN[0x000C] = 0x80000016;
1156 pNv->PRAMIN[0x000D] = 0x0010120E;
1157 pNv->PRAMIN[0x000E] = 0x80000017;
1158 pNv->PRAMIN[0x000F] = 0x00101210;
1159 pNv->PRAMIN[0x0800] = 0x00003000;
1160 pNv->PRAMIN[0x0801] = pNv->FrameBufferSize - 1;
1161 pNv->PRAMIN[0x0802] = 0x00000002;
1162 pNv->PRAMIN[0x0808] = 0x02080062;
1163 pNv->PRAMIN[0x0809] = 0x00000000;
1164 pNv->PRAMIN[0x080A] = 0x00001200;
1165 pNv->PRAMIN[0x080B] = 0x00001200;
1166 pNv->PRAMIN[0x080C] = 0x00000000;
1167 pNv->PRAMIN[0x080D] = 0x00000000;
1168 pNv->PRAMIN[0x0810] = 0x02080043;
1169 pNv->PRAMIN[0x0811] = 0x00000000;
1170 pNv->PRAMIN[0x0812] = 0x00000000;
1171 pNv->PRAMIN[0x0813] = 0x00000000;
1172 pNv->PRAMIN[0x0814] = 0x00000000;
1173 pNv->PRAMIN[0x0815] = 0x00000000;
1174 pNv->PRAMIN[0x0818] = 0x02080044;
1175 pNv->PRAMIN[0x0819] = 0x02000000;
1176 pNv->PRAMIN[0x081A] = 0x00000000;
1177 pNv->PRAMIN[0x081B] = 0x00000000;
1178 pNv->PRAMIN[0x081C] = 0x00000000;
1179 pNv->PRAMIN[0x081D] = 0x00000000;
1180 pNv->PRAMIN[0x0820] = 0x02080019;
1181 pNv->PRAMIN[0x0821] = 0x00000000;
1182 pNv->PRAMIN[0x0822] = 0x00000000;
1183 pNv->PRAMIN[0x0823] = 0x00000000;
1184 pNv->PRAMIN[0x0824] = 0x00000000;
1185 pNv->PRAMIN[0x0825] = 0x00000000;
1186 pNv->PRAMIN[0x0828] = 0x020A005C;
1187 pNv->PRAMIN[0x0829] = 0x00000000;
1188 pNv->PRAMIN[0x082A] = 0x00000000;
1189 pNv->PRAMIN[0x082B] = 0x00000000;
1190 pNv->PRAMIN[0x082C] = 0x00000000;
1191 pNv->PRAMIN[0x082D] = 0x00000000;
1192 pNv->PRAMIN[0x0830] = 0x0208009F;
1193 pNv->PRAMIN[0x0831] = 0x00000000;
1194 pNv->PRAMIN[0x0832] = 0x00001200;
1195 pNv->PRAMIN[0x0833] = 0x00001200;
1196 pNv->PRAMIN[0x0834] = 0x00000000;
1197 pNv->PRAMIN[0x0835] = 0x00000000;
1198 pNv->PRAMIN[0x0838] = 0x0208004A;
1199 pNv->PRAMIN[0x0839] = 0x02000000;
1200 pNv->PRAMIN[0x083A] = 0x00000000;
1201 pNv->PRAMIN[0x083B] = 0x00000000;
1202 pNv->PRAMIN[0x083C] = 0x00000000;
1203 pNv->PRAMIN[0x083D] = 0x00000000;
1204 pNv->PRAMIN[0x0840] = 0x02080077;
1205 pNv->PRAMIN[0x0841] = 0x00000000;
1206 pNv->PRAMIN[0x0842] = 0x00001200;
1207 pNv->PRAMIN[0x0843] = 0x00001200;
1208 pNv->PRAMIN[0x0844] = 0x00000000;
1209 pNv->PRAMIN[0x0845] = 0x00000000;
1210 pNv->PRAMIN[0x084C] = 0x00003002;
1211 pNv->PRAMIN[0x084D] = 0x00007FFF;
1212 pNv->PRAMIN[0x084E] = pNv->FbUsableSize | 0x00000002;
1214 #if AROS_BIG_ENDIAN
1215 pNv->PRAMIN[0x080A] |= 0x01000000;
1216 pNv->PRAMIN[0x0812] |= 0x01000000;
1217 pNv->PRAMIN[0x081A] |= 0x01000000;
1218 pNv->PRAMIN[0x0822] |= 0x01000000;
1219 pNv->PRAMIN[0x082A] |= 0x01000000;
1220 pNv->PRAMIN[0x0832] |= 0x01000000;
1221 pNv->PRAMIN[0x083A] |= 0x01000000;
1222 pNv->PRAMIN[0x0842] |= 0x01000000;
1223 pNv->PRAMIN[0x0819] = 0x01000000;
1224 pNv->PRAMIN[0x0839] = 0x01000000;
1225 #endif
1226 } else {
1228 pNv->PRAMIN[0x0000] = 0x80000010;
1229 pNv->PRAMIN[0x0001] = 0x80011201;
1230 pNv->PRAMIN[0x0002] = 0x80000011;
1231 pNv->PRAMIN[0x0003] = 0x80011202;
1232 pNv->PRAMIN[0x0004] = 0x80000012;
1233 pNv->PRAMIN[0x0005] = 0x80011203;
1234 pNv->PRAMIN[0x0006] = 0x80000013;
1235 pNv->PRAMIN[0x0007] = 0x80011204;
1236 pNv->PRAMIN[0x0008] = 0x80000014;
1237 pNv->PRAMIN[0x0009] = 0x80011205;
1238 pNv->PRAMIN[0x000A] = 0x80000015;
1239 pNv->PRAMIN[0x000B] = 0x80011206;
1240 pNv->PRAMIN[0x000C] = 0x80000016;
1241 pNv->PRAMIN[0x000D] = 0x80011207;
1242 pNv->PRAMIN[0x000E] = 0x80000017;
1243 pNv->PRAMIN[0x000F] = 0x80011208;
1244 pNv->PRAMIN[0x0800] = 0x00003000;
1245 pNv->PRAMIN[0x0801] = pNv->FrameBufferSize - 1;
1246 pNv->PRAMIN[0x0802] = 0x00000002;
1247 pNv->PRAMIN[0x0803] = 0x00000002;
1248 if(pNv->Architecture >= NV_ARCH_10)
1249 pNv->PRAMIN[0x0804] = 0x01008062;
1250 else
1251 pNv->PRAMIN[0x0804] = 0x01008042;
1252 pNv->PRAMIN[0x0805] = 0x00000000;
1253 pNv->PRAMIN[0x0806] = 0x12001200;
1254 pNv->PRAMIN[0x0807] = 0x00000000;
1255 pNv->PRAMIN[0x0808] = 0x01008043;
1256 pNv->PRAMIN[0x0809] = 0x00000000;
1257 pNv->PRAMIN[0x080A] = 0x00000000;
1258 pNv->PRAMIN[0x080B] = 0x00000000;
1259 pNv->PRAMIN[0x080C] = 0x01008044;
1260 pNv->PRAMIN[0x080D] = 0x00000002;
1261 pNv->PRAMIN[0x080E] = 0x00000000;
1262 pNv->PRAMIN[0x080F] = 0x00000000;
1263 pNv->PRAMIN[0x0810] = 0x01008019;
1264 pNv->PRAMIN[0x0811] = 0x00000000;
1265 pNv->PRAMIN[0x0812] = 0x00000000;
1266 pNv->PRAMIN[0x0813] = 0x00000000;
1267 pNv->PRAMIN[0x0814] = 0x0100A05C;
1268 pNv->PRAMIN[0x0815] = 0x00000000;
1269 pNv->PRAMIN[0x0816] = 0x00000000;
1270 pNv->PRAMIN[0x0817] = 0x00000000;
1271 // aros: commented out for now
1272 // if(pNv->WaitVSyncPossible)
1273 // pNv->PRAMIN[0x0818] = 0x0100809F;
1274 // else
1275 pNv->PRAMIN[0x0818] = 0x0100805F;
1276 pNv->PRAMIN[0x0819] = 0x00000000;
1277 pNv->PRAMIN[0x081A] = 0x12001200;
1278 pNv->PRAMIN[0x081B] = 0x00000000;
1279 pNv->PRAMIN[0x081C] = 0x0100804A;
1280 pNv->PRAMIN[0x081D] = 0x00000002;
1281 pNv->PRAMIN[0x081E] = 0x00000000;
1282 pNv->PRAMIN[0x081F] = 0x00000000;
1283 pNv->PRAMIN[0x0820] = 0x01018077;
1284 pNv->PRAMIN[0x0821] = 0x00000000;
1285 pNv->PRAMIN[0x0822] = 0x12001200;
1286 pNv->PRAMIN[0x0823] = 0x00000000;
1287 pNv->PRAMIN[0x0824] = 0x00003002;
1288 pNv->PRAMIN[0x0825] = 0x00007FFF;
1289 pNv->PRAMIN[0x0826] = pNv->FbUsableSize | 0x00000002;
1290 pNv->PRAMIN[0x0827] = 0x00000002;
1292 #if AROS_BIG_ENDIAN
1293 pNv->PRAMIN[0x0804] |= 0x00080000;
1294 pNv->PRAMIN[0x0808] |= 0x00080000;
1295 pNv->PRAMIN[0x080C] |= 0x00080000;
1296 pNv->PRAMIN[0x0810] |= 0x00080000;
1297 pNv->PRAMIN[0x0814] |= 0x00080000;
1298 pNv->PRAMIN[0x0818] |= 0x00080000;
1299 pNv->PRAMIN[0x081C] |= 0x00080000;
1300 pNv->PRAMIN[0x0820] |= 0x00080000;
1302 pNv->PRAMIN[0x080D] = 0x00000001;
1303 pNv->PRAMIN[0x081D] = 0x00000001;
1304 #endif
1307 if(pNv->Architecture < NV_ARCH_10) {
1308 if((pNv->Chipset & 0x0fff) == 0x0020) {
1309 pNv->PRAMIN[0x0824] |= 0x00020000;
1310 pNv->PRAMIN[0x0826] += (IPTR)pNv->FbAddress;
1312 pNv->PGRAPH[0x0080/4] = 0x000001FF;
1313 pNv->PGRAPH[0x0080/4] = 0x1230C000;
1314 pNv->PGRAPH[0x0084/4] = 0x72111101;
1315 pNv->PGRAPH[0x0088/4] = 0x11D5F071;
1316 pNv->PGRAPH[0x008C/4] = 0x0004FF31; /* stegerg: strange but that's so in xfree nv driver sources */
1317 pNv->PGRAPH[0x008C/4] = 0x4004FF31; /* stegerg: strange but that's so in xfree nv driver sources */
1319 pNv->PGRAPH[0x0140/4] = 0x00000000;
1320 pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF;
1321 pNv->PGRAPH[0x0170/4] = 0x10010100;
1322 pNv->PGRAPH[0x0710/4] = 0xFFFFFFFF;
1323 pNv->PGRAPH[0x0720/4] = 0x00000001;
1325 pNv->PGRAPH[0x0810/4] = 0x00000000;
1326 pNv->PGRAPH[0x0608/4] = 0xFFFFFFFF;
1327 } else {
1328 pNv->PGRAPH[0x0080/4] = 0xFFFFFFFF;
1329 pNv->PGRAPH[0x0080/4] = 0x00000000;
1331 pNv->PGRAPH[0x0140/4] = 0x00000000;
1332 pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF;
1333 pNv->PGRAPH[0x0144/4] = 0x10010100;
1334 pNv->PGRAPH[0x0714/4] = 0xFFFFFFFF;
1335 pNv->PGRAPH[0x0720/4] = 0x00000001;
1336 pNv->PGRAPH[0x0710/4] &= 0x0007ff00;
1337 pNv->PGRAPH[0x0710/4] |= 0x00020100;
1339 if(pNv->Architecture == NV_ARCH_10) {
1340 pNv->PGRAPH[0x0084/4] = 0x00118700;
1341 pNv->PGRAPH[0x0088/4] = 0x24E00810;
1342 pNv->PGRAPH[0x008C/4] = 0x55DE0030;
1344 for(i = 0; i < 32; i++)
1345 pNv->PGRAPH[(0x0B00/4) + i] = pNv->PFB[(0x0240/4) + i];
1347 pNv->PGRAPH[0x640/4] = 0;
1348 pNv->PGRAPH[0x644/4] = 0;
1349 pNv->PGRAPH[0x684/4] = pNv->FrameBufferSize - 1;
1350 pNv->PGRAPH[0x688/4] = pNv->FrameBufferSize - 1;
1352 pNv->PGRAPH[0x0810/4] = 0x00000000;
1353 pNv->PGRAPH[0x0608/4] = 0xFFFFFFFF;
1354 } else {
1355 if(pNv->Architecture >= NV_ARCH_40) {
1356 pNv->PGRAPH[0x0084/4] = 0x401287c0;
1357 pNv->PGRAPH[0x008C/4] = 0x60de8051;
1358 pNv->PGRAPH[0x0090/4] = 0x00008000;
1359 pNv->PGRAPH[0x0610/4] = 0x00be3c5f;
1361 if((pNv->Chipset & 0xfff0) == 0x0040) {
1362 pNv->PGRAPH[0x09b0/4] = 0x83280fff;
1363 pNv->PGRAPH[0x09b4/4] = 0x000000a0;
1364 } else {
1365 pNv->PGRAPH[0x0820/4] = 0x83280eff;
1366 pNv->PGRAPH[0x0824/4] = 0x000000a0;
1369 switch(pNv->Chipset & 0xfff0) {
1370 case 0x0040:
1371 pNv->PGRAPH[0x09b8/4] = 0x0078e366;
1372 pNv->PGRAPH[0x09bc/4] = 0x0000014c;
1373 pNv->PFB[0x033C/4] &= 0xffff7fff;
1374 break;
1375 case 0x00C0:
1376 pNv->PGRAPH[0x0828/4] = 0x007596ff;
1377 pNv->PGRAPH[0x082C/4] = 0x00000108;
1378 break;
1379 case 0x0160:
1380 pNv->PMC[0x1700/4] = pNv->PFB[0x020C/4];
1381 pNv->PMC[0x1704/4] = 0;
1382 pNv->PMC[0x1708/4] = 0;
1383 pNv->PMC[0x170C/4] = pNv->PFB[0x020C/4];
1384 pNv->PGRAPH[0x0860/4] = 0;
1385 pNv->PGRAPH[0x0864/4] = 0;
1386 pNv->PRAMDAC[0x0608/4] |= 0x00100000;
1387 break;
1388 case 0x0140:
1389 pNv->PGRAPH[0x0828/4] = 0x0072cb77;
1390 pNv->PGRAPH[0x082C/4] = 0x00000108;
1391 break;
1392 default:
1393 break;
1396 pNv->PGRAPH[0x0b38/4] = 0x2ffff800;
1397 pNv->PGRAPH[0x0b3c/4] = 0x00006000;
1398 pNv->PGRAPH[0x032C/4] = 0x01000000;
1399 pNv->PGRAPH[0x0220/4] = 0x00001200;
1400 } else
1401 if(pNv->Architecture == NV_ARCH_30) {
1402 pNv->PGRAPH[0x0084/4] = 0x40108700;
1403 pNv->PGRAPH[0x0890/4] = 0x00140000;
1404 pNv->PGRAPH[0x008C/4] = 0xf00e0431;
1405 pNv->PGRAPH[0x0090/4] = 0x00008000;
1406 pNv->PGRAPH[0x0610/4] = 0xf04b1f36;
1407 pNv->PGRAPH[0x0B80/4] = 0x1002d888;
1408 pNv->PGRAPH[0x0B88/4] = 0x62ff007f;
1409 } else {
1410 pNv->PGRAPH[0x0084/4] = 0x00118700;
1411 pNv->PGRAPH[0x008C/4] = 0xF20E0431;
1412 pNv->PGRAPH[0x0090/4] = 0x00000000;
1413 pNv->PGRAPH[0x009C/4] = 0x00000040;
1415 if((pNv->Chipset & 0x0ff0) >= 0x0250) {
1416 pNv->PGRAPH[0x0890/4] = 0x00080000;
1417 pNv->PGRAPH[0x0610/4] = 0x304B1FB6;
1418 pNv->PGRAPH[0x0B80/4] = 0x18B82880;
1419 pNv->PGRAPH[0x0B84/4] = 0x44000000;
1420 pNv->PGRAPH[0x0098/4] = 0x40000080;
1421 pNv->PGRAPH[0x0B88/4] = 0x000000ff;
1422 } else {
1423 pNv->PGRAPH[0x0880/4] = 0x00080000;
1424 pNv->PGRAPH[0x0094/4] = 0x00000005;
1425 pNv->PGRAPH[0x0B80/4] = 0x45CAA208;
1426 pNv->PGRAPH[0x0B84/4] = 0x24000000;
1427 pNv->PGRAPH[0x0098/4] = 0x00000040;
1428 pNv->PGRAPH[0x0750/4] = 0x00E00038;
1429 pNv->PGRAPH[0x0754/4] = 0x00000030;
1430 pNv->PGRAPH[0x0750/4] = 0x00E10038;
1431 pNv->PGRAPH[0x0754/4] = 0x00000030;
1435 for(i = 0; i < 32; i++)
1436 pNv->PGRAPH[(0x0900/4) + i] = pNv->PFB[(0x0240/4) + i];
1438 if(pNv->Architecture >= NV_ARCH_40) {
1439 if((pNv->Chipset & 0xfff0) == 0x0040) {
1440 pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4];
1441 pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4];
1442 pNv->PGRAPH[0x69A4/4] = pNv->PFB[0x0200/4];
1443 pNv->PGRAPH[0x69A8/4] = pNv->PFB[0x0204/4];
1445 pNv->PGRAPH[0x0820/4] = 0;
1446 pNv->PGRAPH[0x0824/4] = 0;
1447 pNv->PGRAPH[0x0864/4] = pNv->FrameBufferSize - 1;
1448 pNv->PGRAPH[0x0868/4] = pNv->FrameBufferSize - 1;
1449 } else {
1450 pNv->PGRAPH[0x09F0/4] = pNv->PFB[0x0200/4];
1451 pNv->PGRAPH[0x09F4/4] = pNv->PFB[0x0204/4];
1452 pNv->PGRAPH[0x69F0/4] = pNv->PFB[0x0200/4];
1453 pNv->PGRAPH[0x69F4/4] = pNv->PFB[0x0204/4];
1455 pNv->PGRAPH[0x0840/4] = 0;
1456 pNv->PGRAPH[0x0844/4] = 0;
1457 pNv->PGRAPH[0x08a0/4] = pNv->FrameBufferSize - 1;
1458 pNv->PGRAPH[0x08a4/4] = pNv->FrameBufferSize - 1;
1460 } else {
1461 pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4];
1462 pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4];
1463 pNv->PGRAPH[0x0750/4] = 0x00EA0000;
1464 pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0200/4];
1465 pNv->PGRAPH[0x0750/4] = 0x00EA0004;
1466 pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0204/4];
1468 pNv->PGRAPH[0x0820/4] = 0;
1469 pNv->PGRAPH[0x0824/4] = 0;
1470 pNv->PGRAPH[0x0864/4] = pNv->FrameBufferSize - 1;
1471 pNv->PGRAPH[0x0868/4] = pNv->FrameBufferSize - 1;
1474 pNv->PGRAPH[0x0B20/4] = 0x00000000;
1475 pNv->PGRAPH[0x0B04/4] = 0xFFFFFFFF;
1478 pNv->PGRAPH[0x053C/4] = 0;
1479 pNv->PGRAPH[0x0540/4] = 0;
1480 pNv->PGRAPH[0x0544/4] = 0x00007FFF;
1481 pNv->PGRAPH[0x0548/4] = 0x00007FFF;
1483 pNv->PFIFO[0x0140] = 0x00000000;
1484 pNv->PFIFO[0x0141] = 0x00000001;
1485 pNv->PFIFO[0x0480] = 0x00000000;
1486 pNv->PFIFO[0x0494] = 0x00000000;
1487 if(pNv->Architecture >= NV_ARCH_40)
1488 pNv->PFIFO[0x0481] = 0x00010000;
1489 else
1490 pNv->PFIFO[0x0481] = 0x00000100;
1491 pNv->PFIFO[0x0490] = 0x00000000;
1492 pNv->PFIFO[0x0491] = 0x00000000;
1493 if(pNv->Architecture >= NV_ARCH_40)
1494 pNv->PFIFO[0x048B] = 0x00001213;
1495 else
1496 pNv->PFIFO[0x048B] = 0x00001209;
1497 pNv->PFIFO[0x0400] = 0x00000000;
1498 pNv->PFIFO[0x0414] = 0x00000000;
1499 pNv->PFIFO[0x0084] = 0x03000100;
1500 pNv->PFIFO[0x0085] = 0x00000110;
1501 pNv->PFIFO[0x0086] = 0x00000112;
1502 pNv->PFIFO[0x0143] = 0x0000FFFF;
1503 pNv->PFIFO[0x0496] = 0x0000FFFF;
1504 pNv->PFIFO[0x0050] = 0x00000000;
1505 pNv->PFIFO[0x0040] = 0xFFFFFFFF;
1506 pNv->PFIFO[0x0415] = 0x00000001;
1507 pNv->PFIFO[0x048C] = 0x00000000;
1508 pNv->PFIFO[0x04A0] = 0x00000000;
1509 #if AROS_BIG_ENDIAN
1510 pNv->PFIFO[0x0489] = 0x800F0078;
1511 #else
1512 pNv->PFIFO[0x0489] = 0x000F0078;
1513 #endif
1514 pNv->PFIFO[0x0488] = 0x00000001;
1515 pNv->PFIFO[0x0480] = 0x00000001;
1516 pNv->PFIFO[0x0494] = 0x00000001;
1517 pNv->PFIFO[0x0495] = 0x00000001;
1518 pNv->PFIFO[0x0140] = 0x00000001;
1520 if(pNv->Architecture >= NV_ARCH_10) {
1521 if(pNv->twoHeads) {
1522 pNv->PCRTC0[0x0860/4] = state->head;
1523 pNv->PCRTC0[0x2860/4] = state->head2;
1525 pNv->PRAMDAC[0x0404/4] |= (1 << 25);
1527 pNv->PMC[0x8704/4] = 1;
1528 pNv->PMC[0x8140/4] = 0;
1529 pNv->PMC[0x8920/4] = 0;
1530 pNv->PMC[0x8924/4] = 0;
1531 pNv->PMC[0x8908/4] = pNv->FrameBufferSize - 1;
1532 pNv->PMC[0x890C/4] = pNv->FrameBufferSize - 1;
1533 pNv->PMC[0x1588/4] = 0;
1535 pNv->PCRTC[0x0810/4] = state->cursorConfig;
1536 pNv->PCRTC[0x0830/4] = state->displayV - 3;
1537 pNv->PCRTC[0x0834/4] = state->displayV - 1;
1539 if(pNv->FlatPanel) {
1540 if((pNv->Chipset & 0x0ff0) == 0x0110) {
1541 pNv->PRAMDAC[0x0528/4] = state->dither;
1542 } else
1543 if(pNv->twoHeads) {
1544 pNv->PRAMDAC[0x083C/4] = state->dither;
1547 VGA_WR08(pNv->PCIO, 0x03D4, 0x53);
1548 VGA_WR08(pNv->PCIO, 0x03D5, state->timingH);
1549 VGA_WR08(pNv->PCIO, 0x03D4, 0x54);
1550 VGA_WR08(pNv->PCIO, 0x03D5, state->timingV);
1551 VGA_WR08(pNv->PCIO, 0x03D4, 0x21);
1552 VGA_WR08(pNv->PCIO, 0x03D5, 0xfa);
1555 VGA_WR08(pNv->PCIO, 0x03D4, 0x41);
1556 VGA_WR08(pNv->PCIO, 0x03D5, state->extra);
1559 VGA_WR08(pNv->PCIO, 0x03D4, 0x19);
1560 VGA_WR08(pNv->PCIO, 0x03D5, state->repaint0);
1561 VGA_WR08(pNv->PCIO, 0x03D4, 0x1A);
1562 VGA_WR08(pNv->PCIO, 0x03D5, state->repaint1);
1563 VGA_WR08(pNv->PCIO, 0x03D4, 0x25);
1564 VGA_WR08(pNv->PCIO, 0x03D5, state->screen);
1565 VGA_WR08(pNv->PCIO, 0x03D4, 0x28);
1566 VGA_WR08(pNv->PCIO, 0x03D5, state->pixel);
1567 VGA_WR08(pNv->PCIO, 0x03D4, 0x2D);
1568 VGA_WR08(pNv->PCIO, 0x03D5, state->horiz);
1569 VGA_WR08(pNv->PCIO, 0x03D4, 0x1C);
1570 VGA_WR08(pNv->PCIO, 0x03D5, state->fifo);
1571 VGA_WR08(pNv->PCIO, 0x03D4, 0x1B);
1572 VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration0);
1573 VGA_WR08(pNv->PCIO, 0x03D4, 0x20);
1574 VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration1);
1575 if(pNv->Architecture >= NV_ARCH_30) {
1576 VGA_WR08(pNv->PCIO, 0x03D4, 0x47);
1577 VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration1 >> 8);
1579 VGA_WR08(pNv->PCIO, 0x03D4, 0x30);
1580 VGA_WR08(pNv->PCIO, 0x03D5, state->cursor0);
1581 VGA_WR08(pNv->PCIO, 0x03D4, 0x31);
1582 VGA_WR08(pNv->PCIO, 0x03D5, state->cursor1);
1583 VGA_WR08(pNv->PCIO, 0x03D4, 0x2F);
1584 VGA_WR08(pNv->PCIO, 0x03D5, state->cursor2);
1585 VGA_WR08(pNv->PCIO, 0x03D4, 0x39);
1586 VGA_WR08(pNv->PCIO, 0x03D5, state->interlace);
1588 if(!pNv->FlatPanel) {
1589 pNv->PRAMDAC0[0x050C/4] = state->pllsel;
1590 pNv->PRAMDAC0[0x0508/4] = state->vpll;
1591 if(pNv->twoHeads)
1592 pNv->PRAMDAC0[0x0520/4] = state->vpll2;
1593 if(pNv->twoStagePLL) {
1594 pNv->PRAMDAC0[0x0578/4] = state->vpllB;
1595 pNv->PRAMDAC0[0x057C/4] = state->vpll2B;
1597 } else {
1598 pNv->PRAMDAC[0x0848/4] = state->scale;
1601 /* begin flat panel hacks */
1602 /* This is unfortunate, but some chips need this register
1603 tweaked or else you get artifacts where adjacent pixels are
1604 swapped. There are no hard rules for what to set here so all
1605 we can do is experiment and apply hacks. */
1607 if(((pNv->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
1608 /* At least one NV34 laptop needs this workaround. */
1609 pNv->PRAMDAC[0x0828/4] &= ~1;
1612 if((pNv->Chipset & 0xfff0) == 0x0310) {
1613 pNv->PRAMDAC[0x0828/4] |= 1;
1616 /* end flat panel hacks */
1618 pNv->PRAMDAC[0x0600/4] = state->general;
1620 pNv->PCRTC[0x0140/4] = 0;
1621 pNv->PCRTC[0x0100/4] = 1;
1623 pNv->CurrentState = state;
1627 ** stegerg: Status NVUnloadStateExt(): should "match" xfree nv NVUnloadStateExt()
1628 ** in xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c version:
1629 ** 1.12 2004/11/30 23:50:26 mvojkovi
1632 void NVUnloadStateExt
1634 NVPtr pNv,
1635 RIVA_HW_STATE *state
1638 VGA_WR08(pNv->PCIO, 0x03D4, 0x19);
1639 state->repaint0 = VGA_RD08(pNv->PCIO, 0x03D5);
1640 VGA_WR08(pNv->PCIO, 0x03D4, 0x1A);
1641 state->repaint1 = VGA_RD08(pNv->PCIO, 0x03D5);
1642 VGA_WR08(pNv->PCIO, 0x03D4, 0x25);
1643 state->screen = VGA_RD08(pNv->PCIO, 0x03D5);
1644 VGA_WR08(pNv->PCIO, 0x03D4, 0x28);
1645 state->pixel = VGA_RD08(pNv->PCIO, 0x03D5);
1646 VGA_WR08(pNv->PCIO, 0x03D4, 0x2D);
1647 state->horiz = VGA_RD08(pNv->PCIO, 0x03D5);
1648 VGA_WR08(pNv->PCIO, 0x03D4, 0x1C);
1649 state->fifo = VGA_RD08(pNv->PCIO, 0x03D5);
1650 VGA_WR08(pNv->PCIO, 0x03D4, 0x1B);
1651 state->arbitration0 = VGA_RD08(pNv->PCIO, 0x03D5);
1652 VGA_WR08(pNv->PCIO, 0x03D4, 0x20);
1653 state->arbitration1 = VGA_RD08(pNv->PCIO, 0x03D5);
1654 if(pNv->Architecture >= NV_ARCH_30) {
1655 VGA_WR08(pNv->PCIO, 0x03D4, 0x47);
1656 state->arbitration1 |= (VGA_RD08(pNv->PCIO, 0x03D5) & 1) << 8;
1658 VGA_WR08(pNv->PCIO, 0x03D4, 0x30);
1659 state->cursor0 = VGA_RD08(pNv->PCIO, 0x03D5);
1660 VGA_WR08(pNv->PCIO, 0x03D4, 0x31);
1661 state->cursor1 = VGA_RD08(pNv->PCIO, 0x03D5);
1662 VGA_WR08(pNv->PCIO, 0x03D4, 0x2F);
1663 state->cursor2 = VGA_RD08(pNv->PCIO, 0x03D5);
1664 VGA_WR08(pNv->PCIO, 0x03D4, 0x39);
1665 state->interlace = VGA_RD08(pNv->PCIO, 0x03D5);
1666 state->vpll = pNv->PRAMDAC0[0x0508/4];
1667 if(pNv->twoHeads)
1668 state->vpll2 = pNv->PRAMDAC0[0x0520/4];
1669 if(pNv->twoStagePLL) {
1670 state->vpllB = pNv->PRAMDAC0[0x0578/4];
1671 state->vpll2B = pNv->PRAMDAC0[0x057C/4];
1673 state->pllsel = pNv->PRAMDAC0[0x050C/4];
1674 state->general = pNv->PRAMDAC[0x0600/4];
1675 state->scale = pNv->PRAMDAC[0x0848/4];
1676 state->config = pNv->PFB[0x0200/4];
1678 if(pNv->Architecture >= NV_ARCH_10) {
1679 if(pNv->twoHeads) {
1680 state->head = pNv->PCRTC0[0x0860/4];
1681 state->head2 = pNv->PCRTC0[0x2860/4];
1682 VGA_WR08(pNv->PCIO, 0x03D4, 0x44);
1683 state->crtcOwner = VGA_RD08(pNv->PCIO, 0x03D5);
1685 VGA_WR08(pNv->PCIO, 0x03D4, 0x41);
1686 state->extra = VGA_RD08(pNv->PCIO, 0x03D5);
1687 state->cursorConfig = pNv->PCRTC[0x0810/4];
1689 if((pNv->Chipset & 0x0ff0) == 0x0110) {
1690 state->dither = pNv->PRAMDAC[0x0528/4];
1691 } else
1692 if(pNv->twoHeads) {
1693 state->dither = pNv->PRAMDAC[0x083C/4];
1696 if(pNv->FlatPanel) {
1697 VGA_WR08(pNv->PCIO, 0x03D4, 0x53);
1698 state->timingH = VGA_RD08(pNv->PCIO, 0x03D5);
1699 VGA_WR08(pNv->PCIO, 0x03D4, 0x54);
1700 state->timingV = VGA_RD08(pNv->PCIO, 0x03D5);
1705 void NVSetStartAddress (
1706 NVPtr pNv,
1707 ULONG start
1710 pNv->PCRTC[0x800/4] = start;
1713 void NVLoadDAC(
1714 NVPtr pNv
1717 int i;
1719 VGA_WR08(pNv->PDIO, 0x3c6, 0xff);
1720 VGA_WR08(pNv->PDIO, 0x3c8, 0);
1721 for (i=0; i < 768; i++)
1722 VGA_WR08(pNv->PDIO, 0x3c9, pNv->CurrentState->Regs.dac[i]);
1725 static void InitBaseRegs(struct staticdata *sd, struct CardState *card, Sync *mode)
1727 /* Determine sync polarity */
1728 if (mode->VDisplay < 400)
1729 card->Regs.misc = 0xa3;
1730 else if (mode->VDisplay < 480)
1731 card->Regs.misc = 0x63;
1732 else if (mode->VDisplay < 768)
1733 card->Regs.misc = 0xe3;
1734 else
1735 card->Regs.misc = 0x23;
1737 card->Regs.seq[0] = 0x03;
1738 card->Regs.seq[1] = 0x01;
1739 card->Regs.seq[2] = 0x0f;
1740 card->Regs.seq[3] = 0x00;
1741 card->Regs.seq[4] = 0x0e;
1743 card->Regs.crtc[8] = 0;
1744 card->Regs.crtc[10] = 0; //0x20;
1745 card->Regs.crtc[14] = 0;
1746 card->Regs.crtc[17] = (mode->VSyncEnd & 0x0f) | 0x20;
1747 card->Regs.crtc[18] = (mode->VDisplay - 1) & 0xff;
1748 card->Regs.crtc[19] = card->width >> 4;
1749 card->Regs.crtc[20] = 0;
1750 card->Regs.crtc[21] = (mode->VSyncStart - 1) & 0xff;
1751 card->Regs.crtc[22] = (mode->VSyncEnd - 1) & 0xff;
1752 card->Regs.crtc[23] = 0xc3; // 0xc3
1753 card->Regs.crtc[24] = 0xff;
1754 card->Regs.crtc[40] = 0x40;
1756 card->Regs.gra[0] = 0x00;
1757 card->Regs.gra[1] = 0x00;
1758 card->Regs.gra[2] = 0x00;
1759 card->Regs.gra[3] = 0x00;
1760 card->Regs.gra[4] = 0x00;
1761 card->Regs.gra[5] = 0x40;
1762 card->Regs.gra[6] = 0x05;
1763 card->Regs.gra[7] = 0x0f;
1764 card->Regs.gra[8] = 0xff;
1766 card->Regs.attr[0] = 0x00;
1767 card->Regs.attr[1] = 0x01;
1768 card->Regs.attr[2] = 0x02;
1769 card->Regs.attr[3] = 0x03;
1770 card->Regs.attr[4] = 0x04;
1771 card->Regs.attr[5] = 0x05;
1772 card->Regs.attr[6] = 0x06;
1773 card->Regs.attr[7] = 0x07;
1774 card->Regs.attr[8] = 0x08;
1775 card->Regs.attr[9] = 0x09;
1776 card->Regs.attr[10] = 0x0a;
1777 card->Regs.attr[11] = 0x0b;
1778 card->Regs.attr[12] = 0x0c;
1779 card->Regs.attr[13] = 0x0d;
1780 card->Regs.attr[14] = 0x0e;
1781 card->Regs.attr[15] = 0x0f;
1782 card->Regs.attr[16] = 0x41;
1783 card->Regs.attr[17] = 0x01;
1784 card->Regs.attr[18] = 0x0f;
1785 card->Regs.attr[19] = 0x00;
1786 card->Regs.attr[20] = 0x00;
1789 #define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b))
1790 #define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
1791 #define SetBF(mask,value) ((value) << (0?mask))
1792 #define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
1793 #define SetBitField(value,from,to) SetBF(to, GetBF(value,from))
1794 #define SetBit(n) (1<<(n))
1795 #define Set8Bits(value) ((value)&0xff)
1797 void InitMode(struct staticdata *sd, struct CardState *state,
1798 ULONG width, ULONG height, UBYTE bpp, ULONG pixelc, ULONG base,
1799 ULONG HDisplay, ULONG VDisplay,
1800 ULONG HSyncStart, ULONG HSyncEnd, ULONG HTotal,
1801 ULONG VSyncStart, ULONG VSyncEnd, ULONG VTotal)
1803 D(bug("[NVidia] Init %dx%dx%d @%x mode\n", width, height, bpp, base));
1805 ULONG HBlankStart, HBlankEnd, VBlankStart, VBlankEnd, OrgHDisplay = HDisplay;
1807 Sync mode = {
1808 pixelc, 0,
1809 HDisplay, HSyncStart, HSyncEnd, HTotal,
1810 VDisplay, VSyncStart, VSyncEnd, VTotal
1813 InitBaseRegs(sd, state, &mode);
1815 HDisplay = (HDisplay >> 3) - 1;
1816 HSyncStart = (HSyncStart >> 3) - 1;
1817 HSyncEnd = (HSyncEnd >> 3) - 1;
1818 HTotal = (HTotal >> 3) - 5;
1819 HBlankStart = HDisplay;
1820 HBlankEnd = HTotal + 4;
1822 VDisplay -= 1;
1823 VSyncStart -= 1;
1824 VSyncEnd -= 1;
1825 VTotal -= 2;
1826 VBlankStart = VDisplay;
1827 VBlankEnd = VTotal + 1;
1829 if (bpp <= 8)
1830 state->bitsPerPixel = 8;
1831 else if (bpp <= 16)
1832 state->bitsPerPixel = 16;
1833 else
1834 state->bitsPerPixel = 32;
1836 if (sd->Card.FlatPanel)
1838 VSyncStart = VTotal - 3;
1839 VSyncEnd = VTotal - 2;
1840 VBlankStart = VSyncStart;
1841 HSyncStart = HTotal - 5;
1842 HSyncEnd = HTotal - 2;
1843 HBlankEnd = HTotal + 4;
1846 state->Regs.crtc[0x00] = Set8Bits(HTotal);
1847 state->Regs.crtc[0x01] = Set8Bits(HDisplay);
1848 state->Regs.crtc[0x02] = Set8Bits(HBlankStart);
1849 state->Regs.crtc[0x03] = SetBitField(HBlankEnd, 4:0, 4:0) | SetBit(7);
1850 state->Regs.crtc[0x04] = Set8Bits(HSyncStart);
1851 state->Regs.crtc[0x05] = SetBitField(HBlankEnd, 5:5, 7:7) |
1852 SetBitField(HSyncEnd, 4:0, 4:0);
1853 state->Regs.crtc[0x06] = SetBitField(VTotal, 7:0, 7:0);
1854 state->Regs.crtc[0x07] = SetBitField(VTotal, 8:8, 0:0) |
1855 SetBitField(VDisplay, 8:8, 1:1) |
1856 SetBitField(VSyncStart, 8:8, 2:2) |
1857 SetBitField(VBlankStart, 8:8, 3:3) |
1858 SetBit(4) |
1859 SetBitField(VTotal, 9:9, 5:5) |
1860 SetBitField(VDisplay, 9:9, 6:6) |
1861 SetBitField(VSyncStart, 9:9, 7:7);
1862 state->Regs.crtc[0x09] = SetBitField(VBlankStart, 9:9, 5:5) | SetBit(6); // V_DOUBLESCAN?
1863 state->Regs.crtc[0x10] = Set8Bits(VSyncStart);
1864 state->Regs.crtc[0x11] = SetBitField(VSyncEnd, 3:0, 3:0) | SetBit(5);
1865 state->Regs.crtc[0x12] = Set8Bits(VDisplay);
1866 state->Regs.crtc[0x13] = ((width / 8) * (state->bitsPerPixel / 8));
1867 state->Regs.crtc[0x15] = Set8Bits(VBlankStart);
1868 state->Regs.crtc[0x16] = Set8Bits(VBlankEnd);
1870 state->Regs.attr[0x10] = 0x01;
1872 state->screen =
1873 SetBitField(HBlankEnd, 6:6, 4:4) |
1874 SetBitField(VBlankStart, 10:10, 3:3) |
1875 SetBitField(VSyncStart, 10:10, 2:2) |
1876 SetBitField(VDisplay, 10:10, 1:1) |
1877 SetBitField(VTotal, 10:10, 0:0);
1879 state->horiz =
1880 SetBitField(HTotal, 8:8, 0:0) |
1881 SetBitField(HDisplay, 8:8, 1:1) |
1882 SetBitField(HBlankStart, 8:8, 2:2) |
1883 SetBitField(HSyncStart, 8:8, 3:3);
1885 state->extra =
1886 SetBitField(VTotal, 11:11, 0:0) |
1887 SetBitField(VDisplay, 11:11, 2:2) |
1888 SetBitField(VSyncStart, 11:11, 4:4) |
1889 SetBitField(VBlankStart, 11:11, 6:6);
1891 state->interlace = 0xff;
1893 if (bpp >= 24) bpp = 32;
1895 if (sd->Card.Architecture >= NV_ARCH_10)
1896 sd->Card.CURSOR = (ULONG*)(sd->Card.FrameBuffer + sd->Card.CursorStart);
1898 // NVLockUnlock(sd, 0);
1899 NVCalcStateExt(sd, &sd->Card, state, bpp, width, OrgHDisplay, height, pixelc, 0);
1901 state->scale = sd->Card.PRAMDAC[0x0848/4] & 0xfff000ff;
1902 if (sd->Card.FlatPanel)
1904 state->pixel |= (1 << 7);
1905 if (!sd->Card.fpScaler || (sd->Card.fpWidth <= mode.HDisplay)
1906 || (sd->Card.fpHeight <= mode.VDisplay))
1908 state->scale |= (1 << 8);
1913 state->cursorConfig = 0x00000100;
1914 if (sd->Card.alphaCursor)
1916 state->cursorConfig |= 0x04011000;
1917 state->general |= (1 << 29);
1919 if((sd->Card.Chipset & 0x0ff0) == 0x0110) {
1920 state->dither = sd->Card.PRAMDAC[0x0528/4] & ~0x00010000;
1921 if(0) //sd->Card.FPDither)
1922 state->dither |= 0x00010000;
1923 else
1924 state->cursorConfig |= (1 << 28);
1925 } else
1926 if((sd->Card.Chipset & 0x0ff0) >= 0x0170) {
1927 state->dither = sd->Card.PRAMDAC[0x083C/4] & ~1;
1928 state->cursorConfig |= (1 << 28);
1929 if(0) //pNv->FPDither)
1930 state->dither |= 1;
1931 } else {
1932 state->cursorConfig |= (1 << 28);
1934 } else
1935 state->cursorConfig |= 0x02000000;
1938 // Init DAC
1939 if (bpp >1)
1941 int i;
1942 for (i=0; i <256; i++)
1944 state->Regs.dac[i*3+0] = i;
1945 state->Regs.dac[i*3+1] = i;
1946 state->Regs.dac[i*3+2] = i;
1950 state->offset = base;
1951 state->vpll = state->pll;
1952 state->vpll2 = state->pll;
1953 state->vpllB = state->pllB;
1954 state->vpll2B = state->pllB;
1956 VGA_WR08(sd->Card.PCIO, 0x03D4, 0x1C);
1957 state->fifo = VGA_RD08(sd->Card.PCIO, 0x03D5) & ~(1<<5);
1959 if(sd->Card.CRTCnumber) {
1960 state->head = sd->Card.PCRTC0[0x00000860/4] & ~0x00001000;
1961 state->head2 = sd->Card.PCRTC0[0x00002860/4] | 0x00001000;
1962 state->crtcOwner = 3;
1963 state->pllsel |= 0x20000800;
1964 state->vpll = sd->Card.PRAMDAC0[0x0508/4];
1965 if(sd->Card.twoStagePLL)
1966 state->vpllB = sd->Card.PRAMDAC0[0x0578/4];
1967 } else
1968 if(sd->Card.twoHeads) {
1969 state->head = sd->Card.PCRTC0[0x00000860/4] | 0x00001000;
1970 state->head2 = sd->Card.PCRTC0[0x00002860/4] & ~0x00001000;
1971 state->crtcOwner = 0;
1972 state->vpll2 = sd->Card.PRAMDAC0[0x0520/4];
1973 if(sd->Card.twoStagePLL)
1974 state->vpll2B = sd->Card.PRAMDAC0[0x057C/4];
1977 state->timingH = 0;
1978 state->timingV = 0;
1979 state->displayV = VDisplay;
1982 void acc_reset(struct staticdata *);
1984 void LoadState(struct staticdata *sd, struct CardState *state)
1986 int i;
1988 ObtainSemaphore(&sd->HWLock);
1990 // CRTC_out(sd, 0x11, 0x00);
1992 NVLockUnlock(sd, 0);
1993 NVLoadStateExt(&sd->Card, state);
1995 MISC_out(sd, sd->Card.CurrentState->Regs.misc);
1997 for (i=0; i < 0x05; i++)
1999 SEQ_out(sd, i, sd->Card.CurrentState->Regs.seq[i]);
2002 CRTC_out(sd, 17, sd->Card.CurrentState->Regs.crtc[17] & ~0x80);
2003 for (i=0; i < 0x41; i++)
2005 switch (i)
2007 case 0x19:
2008 case 0x20 ... 0x40:
2009 break;
2010 default:
2011 CRTC_out(sd, i, sd->Card.CurrentState->Regs.crtc[i]);
2012 break;
2016 for (i=0; i < 0x15; i++)
2017 ATTR_out(sd, i, sd->Card.CurrentState->Regs.attr[i]);
2019 for (i=0; i < 0x09; i++)
2020 GRA_out(sd, i, sd->Card.CurrentState->Regs.gra[i]);
2022 NVSetStartAddress(&sd->Card, sd->Card.CurrentState->offset);
2024 sd->Card.currentROP = 0xffffffff;
2025 // VGA_WR08(sd->Card.PVIO, 0x3c3, 1);
2027 NVLoadDAC(&sd->Card);
2028 acc_reset(sd);
2030 ReleaseSemaphore(&sd->HWLock);
2033 void DPMS(struct staticdata *sd, HIDDT_DPMSLevel state)
2035 UBYTE reg;
2037 ObtainSemaphore(&sd->HWLock);
2039 NVLockUnlock(sd,0);
2040 reg = CRTC_in(sd, 0x1a) & ~0xc0;
2042 switch(state)
2044 case vHidd_Gfx_DPMSLevel_Standby:
2045 reg |= 0x80;
2046 break;
2047 case vHidd_Gfx_DPMSLevel_Suspend:
2048 reg |= 0x40;
2049 break;
2050 case vHidd_Gfx_DPMSLevel_Off:
2051 reg |= 0xc0;
2052 break;
2053 default: // On
2054 break;
2057 CRTC_out(sd, 0x1a, reg);
2059 ReleaseSemaphore(&sd->HWLock);
2062 void Protect(struct staticdata *sd, UBYTE protect)
2064 ObtainSemaphore(&sd->HWLock);
2066 if (protect)
2068 UBYTE tmp = SEQ_in(sd, 1);
2069 SEQ_out(sd, 0, 1);
2070 SEQ_out(sd, 1, tmp | 0x20);
2072 else
2074 UBYTE tmp = SEQ_in(sd, 1);
2075 SEQ_out(sd, 1, tmp & ~0x20);
2076 SEQ_out(sd, 0, 3);
2079 ReleaseSemaphore(&sd->HWLock);
2082 static const UBYTE ROPTable[] = {
2083 [vHidd_GC_DrawMode_Clear] = 0x00,
2084 [vHidd_GC_DrawMode_And] = 0x88,
2085 [vHidd_GC_DrawMode_AndReverse] = 0x44,
2086 [vHidd_GC_DrawMode_Copy] = 0xcc,
2087 [vHidd_GC_DrawMode_AndInverted] = 0x22,
2088 [vHidd_GC_DrawMode_NoOp] = 0xaa,
2089 [vHidd_GC_DrawMode_Xor] = 0x66,
2090 [vHidd_GC_DrawMode_Or] = 0xee,
2091 [vHidd_GC_DrawMode_Nor] = 0x11,
2092 [vHidd_GC_DrawMode_Equiv] = 0x99,
2093 [vHidd_GC_DrawMode_Invert] = 0x55,
2094 [vHidd_GC_DrawMode_OrReverse] = 0xdd,
2095 [vHidd_GC_DrawMode_CopyInverted]= 0x33,
2096 [vHidd_GC_DrawMode_OrInverted] = 0xbb,
2097 [vHidd_GC_DrawMode_Nand] = 0x77,
2098 [vHidd_GC_DrawMode_Set] = 0xff,
2101 void NVDmaKickoff(struct Card *pNv)
2103 if(pNv->dmaCurrent != pNv->dmaPut) {
2104 pNv->dmaPut = pNv->dmaCurrent;
2105 WRITE_PUT(pNv, pNv->dmaPut);
2109 /* There is a HW race condition with videoram command buffers.
2110 You can't jump to the location of your put offset. We write put
2111 at the jump offset + SKIPS dwords with noop padding in between
2112 to solve this problem */
2113 #define SKIPS 8
2115 void
2116 NVDmaWait (
2117 struct Card *pNv,
2118 int size
2120 int dmaGet;
2122 size++;
2124 while(pNv->dmaFree < size) {
2125 dmaGet = READ_GET(pNv);
2127 if(pNv->dmaPut >= dmaGet) {
2128 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
2129 if(pNv->dmaFree < size) {
2130 NVDmaNext(pNv, 0x20000000);
2131 if(dmaGet <= SKIPS) {
2132 if(pNv->dmaPut <= SKIPS) /* corner case - will be idle */
2133 WRITE_PUT(pNv, SKIPS + 1);
2134 do { dmaGet = READ_GET(pNv); }
2135 while(dmaGet <= SKIPS);
2137 WRITE_PUT(pNv, SKIPS);
2138 pNv->dmaCurrent = pNv->dmaPut = SKIPS;
2139 pNv->dmaFree = dmaGet - (SKIPS + 1);
2141 } else
2142 pNv->dmaFree = dmaGet - pNv->dmaCurrent - 1;
2146 void NVSetPattern(
2147 struct staticdata *sd,
2148 ULONG clr0,
2149 ULONG clr1,
2150 ULONG pat0,
2151 ULONG pat1
2154 struct Card *pNv = &sd->Card;
2156 NVDmaStart(pNv, PATTERN_COLOR_0, 4);
2157 NVDmaNext (pNv, clr0);
2158 NVDmaNext (pNv, clr1);
2159 NVDmaNext (pNv, pat0);
2160 NVDmaNext (pNv, pat1);
2163 void NVSetRopSolid(struct staticdata *sd, ULONG rop, ULONG planemask)
2165 struct Card *pNv = &sd->Card;
2167 if(planemask != ~0) {
2168 NVSetPattern(sd, 0, planemask, ~0, ~0);
2169 if(pNv->currentROP != (rop + 32)) {
2170 NVDmaStart(pNv, ROP_SET, 1);
2171 NVDmaNext (pNv, ROPTable[rop]);
2172 pNv->currentROP = rop + 32;
2174 } else
2175 if (pNv->currentROP != rop) {
2176 if(pNv->currentROP >= 16)
2177 NVSetPattern(sd, ~0, ~0, ~0, ~0);
2178 NVDmaStart(pNv, ROP_SET, 1);
2179 NVDmaNext (pNv, ROPTable[rop]);
2180 pNv->currentROP = rop;
2184 void acc_reset(struct staticdata *sd)
2186 struct Card *pNv = &sd->Card;
2187 int pitch, i;
2189 LOCK_HW
2191 pitch = pNv->CurrentState->width *
2192 (pNv->CurrentState->bitsPerPixel >> 3);
2194 sd->src_pitch = pitch;
2195 sd->dst_pitch = pitch;
2196 sd->src_offset = pNv->CurrentState->offset;
2197 sd->dst_offset = pNv->CurrentState->offset;
2199 pNv->dmaBase = (ULONG*)(&pNv->FrameBuffer[pNv->FbUsableSize]);
2201 for(i = 0; i < SKIPS; i++)
2202 pNv->dmaBase[i] = 0x00000000;
2204 pNv->dmaBase[0x0 + SKIPS] = 0x00040000;
2205 pNv->dmaBase[0x1 + SKIPS] = 0x80000010;
2206 pNv->dmaBase[0x2 + SKIPS] = 0x00042000;
2207 pNv->dmaBase[0x3 + SKIPS] = 0x80000011;
2208 pNv->dmaBase[0x4 + SKIPS] = 0x00044000;
2209 pNv->dmaBase[0x5 + SKIPS] = 0x80000012;
2210 pNv->dmaBase[0x6 + SKIPS] = 0x00046000;
2211 pNv->dmaBase[0x7 + SKIPS] = 0x80000013;
2212 pNv->dmaBase[0x8 + SKIPS] = 0x00048000;
2213 pNv->dmaBase[0x9 + SKIPS] = 0x80000014;
2214 pNv->dmaBase[0xA + SKIPS] = 0x0004A000;
2215 pNv->dmaBase[0xB + SKIPS] = 0x80000015;
2216 pNv->dmaBase[0xC + SKIPS] = 0x0004C000;
2217 pNv->dmaBase[0xD + SKIPS] = 0x80000016;
2218 pNv->dmaBase[0xE + SKIPS] = 0x0004E000;
2219 pNv->dmaBase[0xF + SKIPS] = 0x80000017;
2221 pNv->dmaPut = 0;
2222 pNv->dmaCurrent = 16 + SKIPS;
2223 pNv->dmaMax = 8191;
2224 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
2226 switch(pNv->CurrentState->bpp) {
2227 case 32:
2228 case 24:
2229 sd->surface_format = SURFACE_FORMAT_DEPTH24;
2230 sd->pattern_format = PATTERN_FORMAT_DEPTH24;
2231 sd->rect_format = RECT_FORMAT_DEPTH24;
2232 sd->line_format = LINE_FORMAT_DEPTH24;
2233 break;
2234 case 16:
2235 case 15:
2236 sd->surface_format = SURFACE_FORMAT_DEPTH16;
2237 sd->pattern_format = PATTERN_FORMAT_DEPTH16;
2238 sd->rect_format = RECT_FORMAT_DEPTH16;
2239 sd->line_format = LINE_FORMAT_DEPTH16;
2240 break;
2241 default:
2242 sd->surface_format = SURFACE_FORMAT_DEPTH8;
2243 sd->pattern_format = PATTERN_FORMAT_DEPTH8;
2244 sd->rect_format = RECT_FORMAT_DEPTH8;
2245 sd->line_format = LINE_FORMAT_DEPTH8;
2246 break;
2249 NVDmaStart(pNv, SURFACE_FORMAT, 4);
2250 NVDmaNext (pNv, sd->surface_format);
2251 NVDmaNext (pNv, sd->dst_pitch | (sd->src_pitch << 16));
2252 NVDmaNext (pNv, sd->src_offset);
2253 NVDmaNext (pNv, sd->dst_offset);
2255 NVDmaStart(pNv, PATTERN_FORMAT, 1);
2256 NVDmaNext (pNv, sd->pattern_format);
2258 NVDmaStart(pNv, RECT_FORMAT, 1);
2259 NVDmaNext (pNv, sd->rect_format);
2261 NVDmaStart(pNv, LINE_FORMAT, 1);
2262 NVDmaNext (pNv, sd->line_format);
2264 NVSetRopSolid(sd, vHidd_GC_DrawMode_Copy, ~0);
2266 NVDmaKickoff(pNv);
2268 UNLOCK_HW
2271 void NVSync(struct staticdata *sd)
2273 struct Card *pNv = &sd->Card;
2275 if(pNv->DMAKickoffCallback)
2276 (*pNv->DMAKickoffCallback)(sd);
2278 while(READ_GET(pNv) != pNv->dmaPut);
2280 while(pNv->PGRAPH[0x0700/4]);
2282 sd->gpu_busy = FALSE;
2285 void NVDMAKickoffCallback(struct staticdata *sd)
2287 struct Card *pNv = &sd->Card;
2289 NVDmaKickoff(pNv);
2290 pNv->DMAKickoffCallback = NULL;
2293 void NVSelectHead(struct staticdata *sd, UBYTE head)
2295 if (head)
2297 sd->Card.PCIO = sd->Card.PCIO0 + 0x2000;
2298 sd->Card.PCRTC = sd->Card.PCRTC0 + 0x800;
2299 sd->Card.PRAMDAC = sd->Card.PRAMDAC0 + 0x800;
2300 sd->Card.PDIO = sd->Card.PDIO0 + 0x2000;
2302 else
2304 sd->Card.PCIO = sd->Card.PCIO0;
2305 sd->Card.PCRTC = sd->Card.PCRTC0;
2306 sd->Card.PRAMDAC = sd->Card.PRAMDAC0;
2307 sd->Card.PDIO = sd->Card.PDIO0;
2311 BOOL NVIsConnected (struct staticdata *sd, UBYTE output)
2313 NVPtr pNv = &sd->Card;
2314 volatile ULONG *PRAMDAC = pNv->PRAMDAC0;
2315 ULONG reg52C, reg608;
2316 BOOL present;
2317 int i;
2319 if(output) PRAMDAC += 0x800;
2321 reg52C = PRAMDAC[0x052C/4];
2322 reg608 = PRAMDAC[0x0608/4];
2324 PRAMDAC[0x0608/4] = reg608 & ~0x00010000;
2326 PRAMDAC[0x052C/4] = reg52C & 0x0000FEEE;
2328 //usleep(1000);
2329 for (i=0; i < 800000000; i++)
2333 PRAMDAC[0x052C/4] |= 1;
2335 pNv->PRAMDAC0[0x0610/4] = 0x94050140;
2336 pNv->PRAMDAC0[0x0608/4] |= 0x00001000;
2338 //usleep(1000);
2339 for (i=0; i < 800000000; i++)
2343 present = (PRAMDAC[0x0608/4] & (1 << 28)) ? TRUE : FALSE;
2345 pNv->PRAMDAC0[0x0608/4] &= 0x0000EFFF;
2347 PRAMDAC[0x052C/4] = reg52C;
2348 PRAMDAC[0x0608/4] = reg608;
2350 return present;