Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / hidds / nvidia / nvhardware.c
blob0e1ac06ba198cbe27c3933badfee2d6f13a1a345
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, sd->Device,
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 VGA_RD08(sd->Card.PCIO, 0x3da);
201 if (sd->Card.paletteEnabled)
202 index &= ~0x20;
203 else
204 index |= 0x20;
206 VGA_WR08(sd->Card.PCIO, 0x3c0, index);
207 VGA_WR08(sd->Card.PCIO, 0x3c0, val);
210 static inline UBYTE ATTR_in(struct staticdata *sd, UBYTE index)
212 VGA_RD08(sd->Card.PCIO, 0x3da);
213 if (sd->Card.paletteEnabled)
214 index &= ~0x20;
215 else
216 index |= 0x20;
217 VGA_WR08(sd->Card.PCIO, 0x3c0, index);
219 return VGA_RD08(sd->Card.PCIO, 0x3c1);
222 static inline void MISC_out(struct staticdata *sd, UBYTE val)
224 VGA_WR08(sd->Card.PVIO, 0x3c2, val);
227 static inline UBYTE MISC_in(struct staticdata *sd)
229 return VGA_RD08(sd->Card.PVIO, 0x3cc);
232 void NVLockUnlock(struct staticdata *sd, UBYTE Lock)
234 UBYTE cr11;
236 ObtainSemaphore(&sd->HWLock);
237 VGA_WR08(sd->Card.PCIO, 0x3D4, 0x1F);
238 VGA_WR08(sd->Card.PCIO, 0x3D5, Lock ? 0x99 : 0x57);
240 VGA_WR08(sd->Card.PCIO, 0x3D4, 0x11);
241 cr11 = VGA_RD08(sd->Card.PCIO, 0x3D5);
242 if(Lock) cr11 |= 0x80;
243 else cr11 &= ~0x80;
244 VGA_WR08(sd->Card.PCIO, 0x3D5, cr11);
245 ReleaseSemaphore(&sd->HWLock);
248 int NVShowHideCursor (struct staticdata *sd, UBYTE ShowHide)
250 int current = sd->Card.CurrentState->cursor1;
252 ObtainSemaphore(&sd->HWLock);
253 sd->Card.CurrentState->cursor1 = (sd->Card.CurrentState->cursor1 & 0xFE) |
254 (ShowHide & 0x01);
255 VGA_WR08(sd->Card.PCIO, 0x3D4, 0x31);
256 VGA_WR08(sd->Card.PCIO, 0x3D5, sd->Card.CurrentState->cursor1);
258 if (sd->Card.Architecture == NV_ARCH_40) { /* HW bug */
259 volatile ULONG curpos = sd->Card.PRAMDAC[0x0300/4];
260 sd->Card.PRAMDAC[0x0300/4] = curpos;
263 ReleaseSemaphore(&sd->HWLock);
264 return (current & 0x01);
267 /****************************************************************************\
269 * The video arbitration routines calculate some "magic" numbers. Fixes *
270 * the snow seen when accessing the framebuffer without it. *
271 * It just works (I hope). *
273 \****************************************************************************/
275 typedef struct {
276 int graphics_lwm;
277 int video_lwm;
278 int graphics_burst_size;
279 int video_burst_size;
280 int valid;
281 } nv4_fifo_info;
283 typedef struct {
284 int pclk_khz;
285 int mclk_khz;
286 int nvclk_khz;
287 char mem_page_miss;
288 char mem_latency;
289 int memory_width;
290 char enable_video;
291 char gr_during_vid;
292 char pix_bpp;
293 char mem_aligned;
294 char enable_mp;
295 } nv4_sim_state;
297 typedef struct {
298 int graphics_lwm;
299 int video_lwm;
300 int graphics_burst_size;
301 int video_burst_size;
302 int valid;
303 } nv10_fifo_info;
305 typedef struct {
306 int pclk_khz;
307 int mclk_khz;
308 int nvclk_khz;
309 char mem_page_miss;
310 char mem_latency;
311 int memory_type;
312 int memory_width;
313 char enable_video;
314 char gr_during_vid;
315 char pix_bpp;
316 char mem_aligned;
317 char enable_mp;
318 } nv10_sim_state;
320 static void nvGetClocks(NVPtr pNv, ULONG *MClk, ULONG *NVClk)
322 unsigned int pll, N, M, MB, NB, P;
324 if(pNv->Architecture >= NV_ARCH_40) {
325 pll = pNv->PMC[0x4020/4];
326 P = (pll >> 16) & 0x03;
327 pll = pNv->PMC[0x4024/4];
328 M = pll & 0xFF;
329 N = (pll >> 8) & 0xFF;
330 MB = (pll >> 16) & 0xFF;
331 NB = (pll >> 24) & 0xFF;
332 *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
334 pll = pNv->PMC[0x4000/4];
335 P = (pll >> 16) & 0x03;
336 pll = pNv->PMC[0x4004/4];
337 M = pll & 0xFF;
338 N = (pll >> 8) & 0xFF;
339 MB = (pll >> 16) & 0xFF;
340 NB = (pll >> 24) & 0xFF;
342 *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
343 } else
344 if(pNv->twoStagePLL) {
345 pll = pNv->PRAMDAC0[0x0504/4];
346 M = pll & 0xFF;
347 N = (pll >> 8) & 0xFF;
348 P = (pll >> 16) & 0x0F;
349 pll = pNv->PRAMDAC0[0x0574/4];
350 if(pll & 0x80000000) {
351 MB = pll & 0xFF;
352 NB = (pll >> 8) & 0xFF;
353 } else {
354 MB = 1;
355 NB = 1;
357 *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
359 pll = pNv->PRAMDAC0[0x0500/4];
360 M = pll & 0xFF;
361 N = (pll >> 8) & 0xFF;
362 P = (pll >> 16) & 0x0F;
363 pll = pNv->PRAMDAC0[0x0570/4];
364 if(pll & 0x80000000) {
365 MB = pll & 0xFF;
366 NB = (pll >> 8) & 0xFF;
367 } else {
368 MB = 1;
369 NB = 1;
371 *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
372 } else
373 if(((pNv->Chipset & 0x0ff0) == 0x0300) ||
374 ((pNv->Chipset & 0x0ff0) == 0x0330))
376 pll = pNv->PRAMDAC0[0x0504/4];
377 M = pll & 0x0F;
378 N = (pll >> 8) & 0xFF;
379 P = (pll >> 16) & 0x07;
380 if(pll & 0x00000080) {
381 MB = (pll >> 4) & 0x07;
382 NB = (pll >> 19) & 0x1f;
383 } else {
384 MB = 1;
385 NB = 1;
387 *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
389 pll = pNv->PRAMDAC0[0x0500/4];
390 M = pll & 0x0F;
391 N = (pll >> 8) & 0xFF;
392 P = (pll >> 16) & 0x07;
393 if(pll & 0x00000080) {
394 MB = (pll >> 4) & 0x07;
395 NB = (pll >> 19) & 0x1f;
396 } else {
397 MB = 1;
398 NB = 1;
400 *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
401 } else {
402 pll = pNv->PRAMDAC0[0x0504/4];
403 M = pll & 0xFF;
404 N = (pll >> 8) & 0xFF;
405 P = (pll >> 16) & 0x0F;
406 *MClk = (N * pNv->CrystalFreqKHz / M) >> P;
408 pll = pNv->PRAMDAC0[0x0500/4];
409 M = pll & 0xFF;
410 N = (pll >> 8) & 0xFF;
411 P = (pll >> 16) & 0x0F;
412 *NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
416 static void nv4CalcArbitration (
417 nv4_fifo_info *fifo,
418 nv4_sim_state *arb
421 int data, pagemiss, cas,width, video_enable, bpp;
422 int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
423 int found, mclk_extra, mclk_loop, cbs, m1, p1;
424 int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
425 int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
426 int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
428 fifo->valid = 1;
429 pclk_freq = arb->pclk_khz;
430 mclk_freq = arb->mclk_khz;
431 nvclk_freq = arb->nvclk_khz;
432 pagemiss = arb->mem_page_miss;
433 cas = arb->mem_latency;
434 width = arb->memory_width >> 6;
435 video_enable = arb->enable_video;
436 bpp = arb->pix_bpp;
437 mp_enable = arb->enable_mp;
438 clwm = 0;
439 vlwm = 0;
440 cbs = 128;
441 pclks = 2;
442 nvclks = 2;
443 nvclks += 2;
444 nvclks += 1;
445 mclks = 5;
446 mclks += 3;
447 mclks += 1;
448 mclks += cas;
449 mclks += 1;
450 mclks += 1;
451 mclks += 1;
452 mclks += 1;
453 mclk_extra = 3;
454 nvclks += 2;
455 nvclks += 1;
456 nvclks += 1;
457 nvclks += 1;
458 if (mp_enable)
459 mclks+=4;
460 nvclks += 0;
461 pclks += 0;
462 found = 0;
463 vbs = 0;
464 while (found != 1)
466 fifo->valid = 1;
467 found = 1;
468 mclk_loop = mclks+mclk_extra;
469 us_m = mclk_loop *1000*1000 / mclk_freq;
470 us_n = nvclks*1000*1000 / nvclk_freq;
471 us_p = nvclks*1000*1000 / pclk_freq;
472 if (video_enable)
474 video_drain_rate = pclk_freq * 2;
475 crtc_drain_rate = pclk_freq * bpp/8;
476 vpagemiss = 2;
477 vpagemiss += 1;
478 crtpagemiss = 2;
479 vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
480 if (nvclk_freq * 2 > mclk_freq * width)
481 video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
482 else
483 video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
484 us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
485 vlwm = us_video * video_drain_rate/(1000*1000);
486 vlwm++;
487 vbs = 128;
488 if (vlwm > 128) vbs = 64;
489 if (vlwm > (256-64)) vbs = 32;
490 if (nvclk_freq * 2 > mclk_freq * width)
491 video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
492 else
493 video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
494 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
495 us_crt =
496 us_video
497 +video_fill_us
498 +cpm_us
499 +us_m + us_n +us_p
501 clwm = us_crt * crtc_drain_rate/(1000*1000);
502 clwm++;
504 else
506 crtc_drain_rate = pclk_freq * bpp/8;
507 crtpagemiss = 2;
508 crtpagemiss += 1;
509 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
510 us_crt = cpm_us + us_m + us_n + us_p ;
511 clwm = us_crt * crtc_drain_rate/(1000*1000);
512 clwm++;
514 m1 = clwm + cbs - 512;
515 p1 = m1 * pclk_freq / mclk_freq;
516 p1 = p1 * bpp / 8;
517 if ((p1 < m1) && (m1 > 0))
519 fifo->valid = 0;
520 found = 0;
521 if (mclk_extra ==0) found = 1;
522 mclk_extra--;
524 else if (video_enable)
526 if ((clwm > 511) || (vlwm > 255))
528 fifo->valid = 0;
529 found = 0;
530 if (mclk_extra ==0) found = 1;
531 mclk_extra--;
534 else
536 if (clwm > 519)
538 fifo->valid = 0;
539 found = 0;
540 if (mclk_extra ==0) found = 1;
541 mclk_extra--;
544 if (clwm < 384) clwm = 384;
545 if (vlwm < 128) vlwm = 128;
546 data = (int)(clwm);
547 fifo->graphics_lwm = data;
548 fifo->graphics_burst_size = 128;
549 data = (int)((vlwm+15));
550 fifo->video_lwm = data;
551 fifo->video_burst_size = vbs;
555 static void nv4UpdateArbitrationSettings (
556 ULONG VClk,
557 ULONG pixelDepth,
558 ULONG *burst,
559 ULONG *lwm,
560 NVPtr pNv
563 nv4_fifo_info fifo_data;
564 nv4_sim_state sim_data;
565 ULONG MClk, NVClk, cfg1;
567 nvGetClocks(pNv, &MClk, &NVClk);
569 cfg1 = pNv->PFB[0x00000204/4];
570 sim_data.pix_bpp = (char)pixelDepth;
571 sim_data.enable_video = 0;
572 sim_data.enable_mp = 0;
573 sim_data.memory_width = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64;
574 sim_data.mem_latency = (char)cfg1 & 0x0F;
575 sim_data.mem_aligned = 1;
576 sim_data.mem_page_miss = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
577 sim_data.gr_during_vid = 0;
578 sim_data.pclk_khz = VClk;
579 sim_data.mclk_khz = MClk;
580 sim_data.nvclk_khz = NVClk;
581 nv4CalcArbitration(&fifo_data, &sim_data);
582 if (fifo_data.valid)
584 int b = fifo_data.graphics_burst_size >> 4;
585 *burst = 0;
586 while (b >>= 1) (*burst)++;
587 *lwm = fifo_data.graphics_lwm >> 3;
591 static void nv10CalcArbitration (
592 nv10_fifo_info *fifo,
593 nv10_sim_state *arb
596 int data, pagemiss, width, video_enable, bpp;
597 int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
598 int nvclk_fill;
599 int found, mclk_extra, mclk_loop, cbs, m1;
600 int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
601 int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
602 int vus_m;
603 int vpm_us, us_video, cpm_us, us_crt,clwm;
604 int clwm_rnd_down;
605 int m2us, us_pipe_min, p1clk, p2;
606 int min_mclk_extra;
607 int us_min_mclk_extra;
609 fifo->valid = 1;
610 pclk_freq = arb->pclk_khz; /* freq in KHz */
611 mclk_freq = arb->mclk_khz;
612 nvclk_freq = arb->nvclk_khz;
613 pagemiss = arb->mem_page_miss;
614 width = arb->memory_width/64;
615 video_enable = arb->enable_video;
616 bpp = arb->pix_bpp;
617 mp_enable = arb->enable_mp;
618 clwm = 0;
620 cbs = 512;
622 pclks = 4; /* lwm detect. */
624 nvclks = 3; /* lwm -> sync. */
625 nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
627 mclks = 1; /* 2 edge sync. may be very close to edge so just put one. */
629 mclks += 1; /* arb_hp_req */
630 mclks += 5; /* ap_hp_req tiling pipeline */
632 mclks += 2; /* tc_req latency fifo */
633 mclks += 2; /* fb_cas_n_ memory request to fbio block */
634 mclks += 7; /* sm_d_rdv data returned from fbio block */
636 /* fb.rd.d.Put_gc need to accumulate 256 bits for read */
637 if (arb->memory_type == 0)
638 if (arb->memory_width == 64) /* 64 bit bus */
639 mclks += 4;
640 else
641 mclks += 2;
642 else
643 if (arb->memory_width == 64) /* 64 bit bus */
644 mclks += 2;
645 else
646 mclks += 1;
648 if ((!video_enable) && (arb->memory_width == 128))
650 mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
651 min_mclk_extra = 17;
653 else
655 mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
656 /* mclk_extra = 4; */ /* Margin of error */
657 min_mclk_extra = 18;
660 nvclks += 1; /* 2 edge sync. may be very close to edge so just put one. */
661 nvclks += 1; /* fbi_d_rdv_n */
662 nvclks += 1; /* Fbi_d_rdata */
663 nvclks += 1; /* crtfifo load */
665 if(mp_enable)
666 mclks+=4; /* Mp can get in with a burst of 8. */
667 /* Extra clocks determined by heuristics */
669 nvclks += 0;
670 pclks += 0;
671 found = 0;
672 while(found != 1) {
673 fifo->valid = 1;
674 found = 1;
675 mclk_loop = mclks+mclk_extra;
676 us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
677 us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
678 us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
679 us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
680 us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
681 us_pipe_min = us_m_min + us_n + us_p;
683 vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
685 if(video_enable) {
686 crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
688 vpagemiss = 1; /* self generating page miss */
689 vpagemiss += 1; /* One higher priority before */
691 crtpagemiss = 2; /* self generating page miss */
692 if(mp_enable)
693 crtpagemiss += 1; /* if MA0 conflict */
695 vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
697 us_video = vpm_us + vus_m; /* Video has separate read return path */
699 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
700 us_crt =
701 us_video /* Wait for video */
702 +cpm_us /* CRT Page miss */
703 +us_m + us_n +us_p /* other latency */
706 clwm = us_crt * crtc_drain_rate/(1000*1000);
707 clwm++; /* fixed point <= float_point - 1. Fixes that */
708 } else {
709 crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
711 crtpagemiss = 1; /* self generating page miss */
712 crtpagemiss += 1; /* MA0 page miss */
713 if(mp_enable)
714 crtpagemiss += 1; /* if MA0 conflict */
715 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
716 us_crt = cpm_us + us_m + us_n + us_p ;
717 clwm = us_crt * crtc_drain_rate/(1000*1000);
718 clwm++; /* fixed point <= float_point - 1. Fixes that */
720 /* Finally, a heuristic check when width == 64 bits */
721 if(width == 1){
722 nvclk_fill = nvclk_freq * 8;
723 if(crtc_drain_rate * 100 >= nvclk_fill * 102)
724 clwm = 0xfff; /*Large number to fail */
726 else if(crtc_drain_rate * 100 >= nvclk_fill * 98) {
727 clwm = 1024;
728 cbs = 512;
735 Overfill check:
739 clwm_rnd_down = ((int)clwm/8)*8;
740 if (clwm_rnd_down < clwm)
741 clwm += 8;
743 m1 = clwm + cbs - 1024; /* Amount of overfill */
744 m2us = us_pipe_min + us_min_mclk_extra;
746 /* pclk cycles to drain */
747 p1clk = m2us * pclk_freq/(1000*1000);
748 p2 = p1clk * bpp / 8; /* bytes drained. */
750 if((p2 < m1) && (m1 > 0)) {
751 fifo->valid = 0;
752 found = 0;
753 if(min_mclk_extra == 0) {
754 if(cbs <= 32) {
755 found = 1; /* Can't adjust anymore! */
756 } else {
757 cbs = cbs/2; /* reduce the burst size */
759 } else {
760 min_mclk_extra--;
762 } else {
763 if (clwm > 1023){ /* Have some margin */
764 fifo->valid = 0;
765 found = 0;
766 if(min_mclk_extra == 0)
767 found = 1; /* Can't adjust anymore! */
768 else
769 min_mclk_extra--;
773 if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
774 data = (int)(clwm);
775 /* printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
776 fifo->graphics_lwm = data; fifo->graphics_burst_size = cbs;
778 fifo->video_lwm = 1024; fifo->video_burst_size = 512;
782 static void nv10UpdateArbitrationSettings (
783 ULONG VClk,
784 ULONG pixelDepth,
785 ULONG *burst,
786 ULONG *lwm,
787 NVPtr pNv
790 nv10_fifo_info fifo_data;
791 nv10_sim_state sim_data;
792 ULONG MClk, NVClk, cfg1;
794 nvGetClocks(pNv, &MClk, &NVClk);
796 cfg1 = pNv->PFB[0x0204/4];
797 sim_data.pix_bpp = (char)pixelDepth;
798 sim_data.enable_video = 1;
799 sim_data.enable_mp = 0;
800 sim_data.memory_type = (pNv->PFB[0x0200/4] & 0x01) ? 1 : 0;
801 sim_data.memory_width = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64;
802 sim_data.mem_latency = (char)cfg1 & 0x0F;
803 sim_data.mem_aligned = 1;
804 sim_data.mem_page_miss = (char)(((cfg1>>4) &0x0F) + ((cfg1>>31) & 0x01));
805 sim_data.gr_during_vid = 0;
806 sim_data.pclk_khz = VClk;
807 sim_data.mclk_khz = MClk;
808 sim_data.nvclk_khz = NVClk;
810 nv10CalcArbitration(&fifo_data, &sim_data);
811 if (fifo_data.valid) {
812 int b = fifo_data.graphics_burst_size >> 4;
813 *burst = 0;
814 while (b >>= 1) (*burst)++;
815 *lwm = fifo_data.graphics_lwm >> 3;
819 static void nv30UpdateArbitrationSettings (
820 NVPtr pNv,
821 ULONG *burst,
822 ULONG *lwm
825 ULONG MClk, NVClk;
826 unsigned int fifo_size, burst_size, graphics_lwm;
828 fifo_size = 2048;
829 burst_size = 512;
830 graphics_lwm = fifo_size - burst_size;
832 nvGetClocks(pNv, &MClk, &NVClk);
834 *burst = 0;
835 burst_size >>= 5;
836 while(burst_size >>= 1) (*burst)++;
837 *lwm = graphics_lwm >> 3;
840 static void nForceUpdateArbitrationSettings (
841 ULONG VClk,
842 ULONG pixelDepth,
843 ULONG *burst,
844 ULONG *lwm,
845 struct staticdata *sd,
846 NVPtr pNv
849 nv10_fifo_info fifo_data;
850 nv10_sim_state sim_data;
851 unsigned int M, N, P, pll, MClk, NVClk, memctrl;
853 if((pNv->Chipset & 0x0FF0) == 0x01A0) {
854 unsigned int uMClkPostDiv;
856 uMClkPostDiv = (pciReadLong(sd, 0, 0, 3, 0x6C) >> 8) & 0xf;
857 if(!uMClkPostDiv) uMClkPostDiv = 4;
858 MClk = 400000 / uMClkPostDiv;
859 } else {
860 MClk = pciReadLong(sd, 0, 0, 5, 0x4C) / 1000;
863 pll = pNv->PRAMDAC0[0x0500/4];
864 M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
865 NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
866 sim_data.pix_bpp = (char)pixelDepth;
867 sim_data.enable_video = 0;
868 sim_data.enable_mp = 0;
869 sim_data.memory_type = (pciReadLong(sd, 0, 0, 1, 0x7C) >> 12) & 1;
870 sim_data.memory_width = 64;
872 memctrl = pciReadLong(sd, 0, 0, 3, 0x00) >> 16;
874 if((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
875 int dimm[3];
877 dimm[0] = (pciReadLong(sd, 0, 0, 2, 0x40) >> 8) & 0x4F;
878 dimm[1] = (pciReadLong(sd, 0, 0, 2, 0x44) >> 8) & 0x4F;
879 dimm[2] = (pciReadLong(sd, 0, 0, 2, 0x48) >> 8) & 0x4F;
881 if((dimm[0] + dimm[1]) != dimm[2]) {
882 bug("WARNING: "
883 "your nForce DIMMs are not arranged in optimal banks!\n");
887 sim_data.mem_latency = 3;
888 sim_data.mem_aligned = 1;
889 sim_data.mem_page_miss = 10;
890 sim_data.gr_during_vid = 0;
891 sim_data.pclk_khz = VClk;
892 sim_data.mclk_khz = MClk;
893 sim_data.nvclk_khz = NVClk;
894 nv10CalcArbitration(&fifo_data, &sim_data);
895 if (fifo_data.valid)
897 int b = fifo_data.graphics_burst_size >> 4;
898 *burst = 0;
899 while (b >>= 1) (*burst)++;
900 *lwm = fifo_data.graphics_lwm >> 3;
904 /****************************************************************************\
906 * RIVA Mode State Routines *
908 \****************************************************************************/
911 * Calculate the Video Clock parameters for the PLL.
913 static void CalcVClock (
914 ULONG clockIn,
915 ULONG *clockOut,
916 ULONG *pllOut,
917 NVPtr pNv
920 unsigned lowM, highM;
921 unsigned DeltaNew, DeltaOld;
922 unsigned VClk, Freq;
923 unsigned M, N, P;
925 DeltaOld = 0xFFFFFFFF;
927 VClk = (unsigned)clockIn;
929 if (pNv->CrystalFreqKHz == 13500) {
930 lowM = 7;
931 highM = 13;
932 } else {
933 lowM = 8;
934 highM = 14;
937 for (P = 0; P <= 4; P++) {
938 Freq = VClk << P;
939 if ((Freq >= 128000) && (Freq <= 350000)) {
940 for (M = lowM; M <= highM; M++) {
941 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
942 if(N <= 255) {
943 Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
944 if (Freq > VClk)
945 DeltaNew = Freq - VClk;
946 else
947 DeltaNew = VClk - Freq;
948 if (DeltaNew < DeltaOld) {
949 *pllOut = (P << 16) | (N << 8) | M;
950 *clockOut = Freq;
951 DeltaOld = DeltaNew;
959 static void CalcVClock2Stage (
960 ULONG clockIn,
961 ULONG *clockOut,
962 ULONG *pllOut,
963 ULONG *pllBOut,
964 NVPtr pNv
967 unsigned DeltaNew, DeltaOld;
968 unsigned VClk, Freq;
969 unsigned M, N, P;
971 DeltaOld = 0xFFFFFFFF;
973 *pllBOut = 0x80000401; /* fixed at x4 for now */
975 VClk = (unsigned)clockIn;
977 for (P = 0; P <= 6; P++) {
978 Freq = VClk << P;
979 if ((Freq >= 400000) && (Freq <= 1000000)) {
980 for (M = 1; M <= 13; M++) {
981 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
982 if((N >= 5) && (N <= 255)) {
983 Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
984 if (Freq > VClk)
985 DeltaNew = Freq - VClk;
986 else
987 DeltaNew = VClk - Freq;
988 if (DeltaNew < DeltaOld) {
989 *pllOut = (P << 16) | (N << 8) | M;
990 *clockOut = Freq;
991 DeltaOld = DeltaNew;
1001 * Calculate extended mode parameters (SVGA) and save in a
1002 * mode state structure.
1004 void NVCalcStateExt (
1005 struct staticdata *sd,
1006 NVPtr pNv,
1007 RIVA_HW_STATE *state,
1008 int bpp,
1009 int width,
1010 int hDisplaySize,
1011 int height,
1012 int dotClock,
1013 int flags
1016 ULONG pixelDepth, VClk = 0;
1018 * Save mode parameters.
1020 state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */
1021 state->width = width;
1022 state->height = height;
1024 * Extended RIVA registers.
1026 pixelDepth = (bpp + 1)/8;
1028 if(pNv->twoStagePLL)
1029 CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
1030 else
1031 CalcVClock(dotClock, &VClk, &state->pll, pNv);
1033 switch (pNv->Architecture)
1035 case NV_ARCH_04:
1036 nv4UpdateArbitrationSettings(VClk,
1037 pixelDepth * 8,
1038 &(state->arbitration0),
1039 &(state->arbitration1),
1040 pNv);
1041 state->cursor0 = 0x00;
1042 state->cursor1 = 0xbC;
1043 if (flags & V_DBLSCAN)
1044 state->cursor1 |= 2;
1045 state->cursor2 = 0x00000000;
1046 state->pllsel = 0x10000700;
1047 state->config = 0x00001114;
1048 state->general = bpp == 16 ? 0x00101100 : 0x00100100;
1049 state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1050 break;
1051 case NV_ARCH_10:
1052 case NV_ARCH_20:
1053 case NV_ARCH_30:
1054 default:
1055 if(((pNv->Chipset & 0xffff) == 0x01A0) ||
1056 ((pNv->Chipset & 0xffff) == 0x01f0))
1058 nForceUpdateArbitrationSettings(VClk,
1059 pixelDepth * 8,
1060 &(state->arbitration0),
1061 &(state->arbitration1),
1063 pNv);
1064 } else if (pNv->Architecture < NV_ARCH_30) {
1065 nv10UpdateArbitrationSettings(VClk,
1066 pixelDepth * 8,
1067 &(state->arbitration0),
1068 &(state->arbitration1),
1069 pNv);
1070 } else {
1071 nv30UpdateArbitrationSettings(pNv,
1072 &(state->arbitration0),
1073 &(state->arbitration1));
1075 state->cursor0 = 0x80 | (pNv->CursorStart >> 17);
1076 state->cursor1 = (pNv->CursorStart >> 11) << 2;
1077 state->cursor2 = pNv->CursorStart >> 24;
1078 if (flags & V_DBLSCAN)
1079 state->cursor1 |= 2;
1080 state->pllsel = 0x10000700;
1081 state->config = pNv->PFB[0x00000200/4];
1082 state->general = bpp == 16 ? 0x00101100 : 0x00100100;
1083 state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1084 break;
1086 if(bpp != 8) /* DirectColor */
1087 state->general |= 0x00000030;
1089 state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
1090 state->pixel = (pixelDepth > 2) ? 3 : pixelDepth;
1094 ** stegerg: Status NVLoadStateExt(): should "match" xfree nv NVLoadStateExt()
1095 ** in xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c version:
1096 ** 1.12 2004/11/30 23:50:26 mvojkovi
1098 ** Exception: some waitvsyncpossible stuff commented out
1101 void NVLoadStateExt (
1102 NVPtr pNv,
1103 RIVA_HW_STATE *state
1106 int i;
1108 pNv->PMC[0x0140/4] = 0x00000000;
1109 pNv->PMC[0x0200/4] = 0xFFFF00FF;
1110 pNv->PMC[0x0200/4] = 0xFFFFFFFF;
1112 pNv->PTIMER[0x0200] = 0x00000008;
1113 pNv->PTIMER[0x0210] = 0x00000003;
1114 pNv->PTIMER[0x0140] = 0x00000000;
1115 pNv->PTIMER[0x0100] = 0xFFFFFFFF;
1117 if(pNv->Architecture == NV_ARCH_04) {
1118 pNv->PFB[0x0200/4] = state->config;
1119 } else {
1120 pNv->PFB[0x0240/4] = 0;
1121 pNv->PFB[0x0244/4] = pNv->FrameBufferSize - 1;
1122 pNv->PFB[0x0250/4] = 0;
1123 pNv->PFB[0x0254/4] = pNv->FrameBufferSize - 1;
1124 pNv->PFB[0x0260/4] = 0;
1125 pNv->PFB[0x0264/4] = pNv->FrameBufferSize - 1;
1126 pNv->PFB[0x0270/4] = 0;
1127 pNv->PFB[0x0274/4] = pNv->FrameBufferSize - 1;
1128 pNv->PFB[0x0280/4] = 0;
1129 pNv->PFB[0x0284/4] = pNv->FrameBufferSize - 1;
1130 pNv->PFB[0x0290/4] = 0;
1131 pNv->PFB[0x0294/4] = pNv->FrameBufferSize - 1;
1132 pNv->PFB[0x02A0/4] = 0;
1133 pNv->PFB[0x02A4/4] = pNv->FrameBufferSize - 1;
1134 pNv->PFB[0x02B0/4] = 0;
1135 pNv->PFB[0x02B4/4] = pNv->FrameBufferSize - 1;
1138 if(pNv->Architecture >= NV_ARCH_40) {
1139 pNv->PRAMIN[0x0000] = 0x80000010;
1140 pNv->PRAMIN[0x0001] = 0x00101202;
1141 pNv->PRAMIN[0x0002] = 0x80000011;
1142 pNv->PRAMIN[0x0003] = 0x00101204;
1143 pNv->PRAMIN[0x0004] = 0x80000012;
1144 pNv->PRAMIN[0x0005] = 0x00101206;
1145 pNv->PRAMIN[0x0006] = 0x80000013;
1146 pNv->PRAMIN[0x0007] = 0x00101208;
1147 pNv->PRAMIN[0x0008] = 0x80000014;
1148 pNv->PRAMIN[0x0009] = 0x0010120A;
1149 pNv->PRAMIN[0x000A] = 0x80000015;
1150 pNv->PRAMIN[0x000B] = 0x0010120C;
1151 pNv->PRAMIN[0x000C] = 0x80000016;
1152 pNv->PRAMIN[0x000D] = 0x0010120E;
1153 pNv->PRAMIN[0x000E] = 0x80000017;
1154 pNv->PRAMIN[0x000F] = 0x00101210;
1155 pNv->PRAMIN[0x0800] = 0x00003000;
1156 pNv->PRAMIN[0x0801] = pNv->FrameBufferSize - 1;
1157 pNv->PRAMIN[0x0802] = 0x00000002;
1158 pNv->PRAMIN[0x0808] = 0x02080062;
1159 pNv->PRAMIN[0x0809] = 0x00000000;
1160 pNv->PRAMIN[0x080A] = 0x00001200;
1161 pNv->PRAMIN[0x080B] = 0x00001200;
1162 pNv->PRAMIN[0x080C] = 0x00000000;
1163 pNv->PRAMIN[0x080D] = 0x00000000;
1164 pNv->PRAMIN[0x0810] = 0x02080043;
1165 pNv->PRAMIN[0x0811] = 0x00000000;
1166 pNv->PRAMIN[0x0812] = 0x00000000;
1167 pNv->PRAMIN[0x0813] = 0x00000000;
1168 pNv->PRAMIN[0x0814] = 0x00000000;
1169 pNv->PRAMIN[0x0815] = 0x00000000;
1170 pNv->PRAMIN[0x0818] = 0x02080044;
1171 pNv->PRAMIN[0x0819] = 0x02000000;
1172 pNv->PRAMIN[0x081A] = 0x00000000;
1173 pNv->PRAMIN[0x081B] = 0x00000000;
1174 pNv->PRAMIN[0x081C] = 0x00000000;
1175 pNv->PRAMIN[0x081D] = 0x00000000;
1176 pNv->PRAMIN[0x0820] = 0x02080019;
1177 pNv->PRAMIN[0x0821] = 0x00000000;
1178 pNv->PRAMIN[0x0822] = 0x00000000;
1179 pNv->PRAMIN[0x0823] = 0x00000000;
1180 pNv->PRAMIN[0x0824] = 0x00000000;
1181 pNv->PRAMIN[0x0825] = 0x00000000;
1182 pNv->PRAMIN[0x0828] = 0x020A005C;
1183 pNv->PRAMIN[0x0829] = 0x00000000;
1184 pNv->PRAMIN[0x082A] = 0x00000000;
1185 pNv->PRAMIN[0x082B] = 0x00000000;
1186 pNv->PRAMIN[0x082C] = 0x00000000;
1187 pNv->PRAMIN[0x082D] = 0x00000000;
1188 pNv->PRAMIN[0x0830] = 0x0208009F;
1189 pNv->PRAMIN[0x0831] = 0x00000000;
1190 pNv->PRAMIN[0x0832] = 0x00001200;
1191 pNv->PRAMIN[0x0833] = 0x00001200;
1192 pNv->PRAMIN[0x0834] = 0x00000000;
1193 pNv->PRAMIN[0x0835] = 0x00000000;
1194 pNv->PRAMIN[0x0838] = 0x0208004A;
1195 pNv->PRAMIN[0x0839] = 0x02000000;
1196 pNv->PRAMIN[0x083A] = 0x00000000;
1197 pNv->PRAMIN[0x083B] = 0x00000000;
1198 pNv->PRAMIN[0x083C] = 0x00000000;
1199 pNv->PRAMIN[0x083D] = 0x00000000;
1200 pNv->PRAMIN[0x0840] = 0x02080077;
1201 pNv->PRAMIN[0x0841] = 0x00000000;
1202 pNv->PRAMIN[0x0842] = 0x00001200;
1203 pNv->PRAMIN[0x0843] = 0x00001200;
1204 pNv->PRAMIN[0x0844] = 0x00000000;
1205 pNv->PRAMIN[0x0845] = 0x00000000;
1206 pNv->PRAMIN[0x084C] = 0x00003002;
1207 pNv->PRAMIN[0x084D] = 0x00007FFF;
1208 pNv->PRAMIN[0x084E] = pNv->FbUsableSize | 0x00000002;
1210 #if AROS_BIG_ENDIAN
1211 pNv->PRAMIN[0x080A] |= 0x01000000;
1212 pNv->PRAMIN[0x0812] |= 0x01000000;
1213 pNv->PRAMIN[0x081A] |= 0x01000000;
1214 pNv->PRAMIN[0x0822] |= 0x01000000;
1215 pNv->PRAMIN[0x082A] |= 0x01000000;
1216 pNv->PRAMIN[0x0832] |= 0x01000000;
1217 pNv->PRAMIN[0x083A] |= 0x01000000;
1218 pNv->PRAMIN[0x0842] |= 0x01000000;
1219 pNv->PRAMIN[0x0819] = 0x01000000;
1220 pNv->PRAMIN[0x0839] = 0x01000000;
1221 #endif
1222 } else {
1224 pNv->PRAMIN[0x0000] = 0x80000010;
1225 pNv->PRAMIN[0x0001] = 0x80011201;
1226 pNv->PRAMIN[0x0002] = 0x80000011;
1227 pNv->PRAMIN[0x0003] = 0x80011202;
1228 pNv->PRAMIN[0x0004] = 0x80000012;
1229 pNv->PRAMIN[0x0005] = 0x80011203;
1230 pNv->PRAMIN[0x0006] = 0x80000013;
1231 pNv->PRAMIN[0x0007] = 0x80011204;
1232 pNv->PRAMIN[0x0008] = 0x80000014;
1233 pNv->PRAMIN[0x0009] = 0x80011205;
1234 pNv->PRAMIN[0x000A] = 0x80000015;
1235 pNv->PRAMIN[0x000B] = 0x80011206;
1236 pNv->PRAMIN[0x000C] = 0x80000016;
1237 pNv->PRAMIN[0x000D] = 0x80011207;
1238 pNv->PRAMIN[0x000E] = 0x80000017;
1239 pNv->PRAMIN[0x000F] = 0x80011208;
1240 pNv->PRAMIN[0x0800] = 0x00003000;
1241 pNv->PRAMIN[0x0801] = pNv->FrameBufferSize - 1;
1242 pNv->PRAMIN[0x0802] = 0x00000002;
1243 pNv->PRAMIN[0x0803] = 0x00000002;
1244 if(pNv->Architecture >= NV_ARCH_10)
1245 pNv->PRAMIN[0x0804] = 0x01008062;
1246 else
1247 pNv->PRAMIN[0x0804] = 0x01008042;
1248 pNv->PRAMIN[0x0805] = 0x00000000;
1249 pNv->PRAMIN[0x0806] = 0x12001200;
1250 pNv->PRAMIN[0x0807] = 0x00000000;
1251 pNv->PRAMIN[0x0808] = 0x01008043;
1252 pNv->PRAMIN[0x0809] = 0x00000000;
1253 pNv->PRAMIN[0x080A] = 0x00000000;
1254 pNv->PRAMIN[0x080B] = 0x00000000;
1255 pNv->PRAMIN[0x080C] = 0x01008044;
1256 pNv->PRAMIN[0x080D] = 0x00000002;
1257 pNv->PRAMIN[0x080E] = 0x00000000;
1258 pNv->PRAMIN[0x080F] = 0x00000000;
1259 pNv->PRAMIN[0x0810] = 0x01008019;
1260 pNv->PRAMIN[0x0811] = 0x00000000;
1261 pNv->PRAMIN[0x0812] = 0x00000000;
1262 pNv->PRAMIN[0x0813] = 0x00000000;
1263 pNv->PRAMIN[0x0814] = 0x0100A05C;
1264 pNv->PRAMIN[0x0815] = 0x00000000;
1265 pNv->PRAMIN[0x0816] = 0x00000000;
1266 pNv->PRAMIN[0x0817] = 0x00000000;
1267 // aros: commented out for now
1268 // if(pNv->WaitVSyncPossible)
1269 // pNv->PRAMIN[0x0818] = 0x0100809F;
1270 // else
1271 pNv->PRAMIN[0x0818] = 0x0100805F;
1272 pNv->PRAMIN[0x0819] = 0x00000000;
1273 pNv->PRAMIN[0x081A] = 0x12001200;
1274 pNv->PRAMIN[0x081B] = 0x00000000;
1275 pNv->PRAMIN[0x081C] = 0x0100804A;
1276 pNv->PRAMIN[0x081D] = 0x00000002;
1277 pNv->PRAMIN[0x081E] = 0x00000000;
1278 pNv->PRAMIN[0x081F] = 0x00000000;
1279 pNv->PRAMIN[0x0820] = 0x01018077;
1280 pNv->PRAMIN[0x0821] = 0x00000000;
1281 pNv->PRAMIN[0x0822] = 0x12001200;
1282 pNv->PRAMIN[0x0823] = 0x00000000;
1283 pNv->PRAMIN[0x0824] = 0x00003002;
1284 pNv->PRAMIN[0x0825] = 0x00007FFF;
1285 pNv->PRAMIN[0x0826] = pNv->FbUsableSize | 0x00000002;
1286 pNv->PRAMIN[0x0827] = 0x00000002;
1288 #if AROS_BIG_ENDIAN
1289 pNv->PRAMIN[0x0804] |= 0x00080000;
1290 pNv->PRAMIN[0x0808] |= 0x00080000;
1291 pNv->PRAMIN[0x080C] |= 0x00080000;
1292 pNv->PRAMIN[0x0810] |= 0x00080000;
1293 pNv->PRAMIN[0x0814] |= 0x00080000;
1294 pNv->PRAMIN[0x0818] |= 0x00080000;
1295 pNv->PRAMIN[0x081C] |= 0x00080000;
1296 pNv->PRAMIN[0x0820] |= 0x00080000;
1298 pNv->PRAMIN[0x080D] = 0x00000001;
1299 pNv->PRAMIN[0x081D] = 0x00000001;
1300 #endif
1303 if(pNv->Architecture < NV_ARCH_10) {
1304 if((pNv->Chipset & 0x0fff) == 0x0020) {
1305 pNv->PRAMIN[0x0824] |= 0x00020000;
1306 pNv->PRAMIN[0x0826] += (IPTR)pNv->FbAddress;
1308 pNv->PGRAPH[0x0080/4] = 0x000001FF;
1309 pNv->PGRAPH[0x0080/4] = 0x1230C000;
1310 pNv->PGRAPH[0x0084/4] = 0x72111101;
1311 pNv->PGRAPH[0x0088/4] = 0x11D5F071;
1312 pNv->PGRAPH[0x008C/4] = 0x0004FF31; /* stegerg: strange but that's so in xfree nv driver sources */
1313 pNv->PGRAPH[0x008C/4] = 0x4004FF31; /* stegerg: strange but that's so in xfree nv driver sources */
1315 pNv->PGRAPH[0x0140/4] = 0x00000000;
1316 pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF;
1317 pNv->PGRAPH[0x0170/4] = 0x10010100;
1318 pNv->PGRAPH[0x0710/4] = 0xFFFFFFFF;
1319 pNv->PGRAPH[0x0720/4] = 0x00000001;
1321 pNv->PGRAPH[0x0810/4] = 0x00000000;
1322 pNv->PGRAPH[0x0608/4] = 0xFFFFFFFF;
1323 } else {
1324 pNv->PGRAPH[0x0080/4] = 0xFFFFFFFF;
1325 pNv->PGRAPH[0x0080/4] = 0x00000000;
1327 pNv->PGRAPH[0x0140/4] = 0x00000000;
1328 pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF;
1329 pNv->PGRAPH[0x0144/4] = 0x10010100;
1330 pNv->PGRAPH[0x0714/4] = 0xFFFFFFFF;
1331 pNv->PGRAPH[0x0720/4] = 0x00000001;
1332 pNv->PGRAPH[0x0710/4] &= 0x0007ff00;
1333 pNv->PGRAPH[0x0710/4] |= 0x00020100;
1335 if(pNv->Architecture == NV_ARCH_10) {
1336 pNv->PGRAPH[0x0084/4] = 0x00118700;
1337 pNv->PGRAPH[0x0088/4] = 0x24E00810;
1338 pNv->PGRAPH[0x008C/4] = 0x55DE0030;
1340 for(i = 0; i < 32; i++)
1341 pNv->PGRAPH[(0x0B00/4) + i] = pNv->PFB[(0x0240/4) + i];
1343 pNv->PGRAPH[0x640/4] = 0;
1344 pNv->PGRAPH[0x644/4] = 0;
1345 pNv->PGRAPH[0x684/4] = pNv->FrameBufferSize - 1;
1346 pNv->PGRAPH[0x688/4] = pNv->FrameBufferSize - 1;
1348 pNv->PGRAPH[0x0810/4] = 0x00000000;
1349 pNv->PGRAPH[0x0608/4] = 0xFFFFFFFF;
1350 } else {
1351 if(pNv->Architecture >= NV_ARCH_40) {
1352 pNv->PGRAPH[0x0084/4] = 0x401287c0;
1353 pNv->PGRAPH[0x008C/4] = 0x60de8051;
1354 pNv->PGRAPH[0x0090/4] = 0x00008000;
1355 pNv->PGRAPH[0x0610/4] = 0x00be3c5f;
1357 if((pNv->Chipset & 0xfff0) == 0x0040) {
1358 pNv->PGRAPH[0x09b0/4] = 0x83280fff;
1359 pNv->PGRAPH[0x09b4/4] = 0x000000a0;
1360 } else {
1361 pNv->PGRAPH[0x0820/4] = 0x83280eff;
1362 pNv->PGRAPH[0x0824/4] = 0x000000a0;
1365 switch(pNv->Chipset & 0xfff0) {
1366 case 0x0040:
1367 pNv->PGRAPH[0x09b8/4] = 0x0078e366;
1368 pNv->PGRAPH[0x09bc/4] = 0x0000014c;
1369 pNv->PFB[0x033C/4] &= 0xffff7fff;
1370 break;
1371 case 0x00C0:
1372 pNv->PGRAPH[0x0828/4] = 0x007596ff;
1373 pNv->PGRAPH[0x082C/4] = 0x00000108;
1374 break;
1375 case 0x0160:
1376 pNv->PMC[0x1700/4] = pNv->PFB[0x020C/4];
1377 pNv->PMC[0x1704/4] = 0;
1378 pNv->PMC[0x1708/4] = 0;
1379 pNv->PMC[0x170C/4] = pNv->PFB[0x020C/4];
1380 pNv->PGRAPH[0x0860/4] = 0;
1381 pNv->PGRAPH[0x0864/4] = 0;
1382 pNv->PRAMDAC[0x0608/4] |= 0x00100000;
1383 break;
1384 case 0x0140:
1385 pNv->PGRAPH[0x0828/4] = 0x0072cb77;
1386 pNv->PGRAPH[0x082C/4] = 0x00000108;
1387 break;
1388 default:
1389 break;
1392 pNv->PGRAPH[0x0b38/4] = 0x2ffff800;
1393 pNv->PGRAPH[0x0b3c/4] = 0x00006000;
1394 pNv->PGRAPH[0x032C/4] = 0x01000000;
1395 pNv->PGRAPH[0x0220/4] = 0x00001200;
1396 } else
1397 if(pNv->Architecture == NV_ARCH_30) {
1398 pNv->PGRAPH[0x0084/4] = 0x40108700;
1399 pNv->PGRAPH[0x0890/4] = 0x00140000;
1400 pNv->PGRAPH[0x008C/4] = 0xf00e0431;
1401 pNv->PGRAPH[0x0090/4] = 0x00008000;
1402 pNv->PGRAPH[0x0610/4] = 0xf04b1f36;
1403 pNv->PGRAPH[0x0B80/4] = 0x1002d888;
1404 pNv->PGRAPH[0x0B88/4] = 0x62ff007f;
1405 } else {
1406 pNv->PGRAPH[0x0084/4] = 0x00118700;
1407 pNv->PGRAPH[0x008C/4] = 0xF20E0431;
1408 pNv->PGRAPH[0x0090/4] = 0x00000000;
1409 pNv->PGRAPH[0x009C/4] = 0x00000040;
1411 if((pNv->Chipset & 0x0ff0) >= 0x0250) {
1412 pNv->PGRAPH[0x0890/4] = 0x00080000;
1413 pNv->PGRAPH[0x0610/4] = 0x304B1FB6;
1414 pNv->PGRAPH[0x0B80/4] = 0x18B82880;
1415 pNv->PGRAPH[0x0B84/4] = 0x44000000;
1416 pNv->PGRAPH[0x0098/4] = 0x40000080;
1417 pNv->PGRAPH[0x0B88/4] = 0x000000ff;
1418 } else {
1419 pNv->PGRAPH[0x0880/4] = 0x00080000;
1420 pNv->PGRAPH[0x0094/4] = 0x00000005;
1421 pNv->PGRAPH[0x0B80/4] = 0x45CAA208;
1422 pNv->PGRAPH[0x0B84/4] = 0x24000000;
1423 pNv->PGRAPH[0x0098/4] = 0x00000040;
1424 pNv->PGRAPH[0x0750/4] = 0x00E00038;
1425 pNv->PGRAPH[0x0754/4] = 0x00000030;
1426 pNv->PGRAPH[0x0750/4] = 0x00E10038;
1427 pNv->PGRAPH[0x0754/4] = 0x00000030;
1431 for(i = 0; i < 32; i++)
1432 pNv->PGRAPH[(0x0900/4) + i] = pNv->PFB[(0x0240/4) + i];
1434 if(pNv->Architecture >= NV_ARCH_40) {
1435 if((pNv->Chipset & 0xfff0) == 0x0040) {
1436 pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4];
1437 pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4];
1438 pNv->PGRAPH[0x69A4/4] = pNv->PFB[0x0200/4];
1439 pNv->PGRAPH[0x69A8/4] = pNv->PFB[0x0204/4];
1441 pNv->PGRAPH[0x0820/4] = 0;
1442 pNv->PGRAPH[0x0824/4] = 0;
1443 pNv->PGRAPH[0x0864/4] = pNv->FrameBufferSize - 1;
1444 pNv->PGRAPH[0x0868/4] = pNv->FrameBufferSize - 1;
1445 } else {
1446 pNv->PGRAPH[0x09F0/4] = pNv->PFB[0x0200/4];
1447 pNv->PGRAPH[0x09F4/4] = pNv->PFB[0x0204/4];
1448 pNv->PGRAPH[0x69F0/4] = pNv->PFB[0x0200/4];
1449 pNv->PGRAPH[0x69F4/4] = pNv->PFB[0x0204/4];
1451 pNv->PGRAPH[0x0840/4] = 0;
1452 pNv->PGRAPH[0x0844/4] = 0;
1453 pNv->PGRAPH[0x08a0/4] = pNv->FrameBufferSize - 1;
1454 pNv->PGRAPH[0x08a4/4] = pNv->FrameBufferSize - 1;
1456 } else {
1457 pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4];
1458 pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4];
1459 pNv->PGRAPH[0x0750/4] = 0x00EA0000;
1460 pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0200/4];
1461 pNv->PGRAPH[0x0750/4] = 0x00EA0004;
1462 pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0204/4];
1464 pNv->PGRAPH[0x0820/4] = 0;
1465 pNv->PGRAPH[0x0824/4] = 0;
1466 pNv->PGRAPH[0x0864/4] = pNv->FrameBufferSize - 1;
1467 pNv->PGRAPH[0x0868/4] = pNv->FrameBufferSize - 1;
1470 pNv->PGRAPH[0x0B20/4] = 0x00000000;
1471 pNv->PGRAPH[0x0B04/4] = 0xFFFFFFFF;
1474 pNv->PGRAPH[0x053C/4] = 0;
1475 pNv->PGRAPH[0x0540/4] = 0;
1476 pNv->PGRAPH[0x0544/4] = 0x00007FFF;
1477 pNv->PGRAPH[0x0548/4] = 0x00007FFF;
1479 pNv->PFIFO[0x0140] = 0x00000000;
1480 pNv->PFIFO[0x0141] = 0x00000001;
1481 pNv->PFIFO[0x0480] = 0x00000000;
1482 pNv->PFIFO[0x0494] = 0x00000000;
1483 if(pNv->Architecture >= NV_ARCH_40)
1484 pNv->PFIFO[0x0481] = 0x00010000;
1485 else
1486 pNv->PFIFO[0x0481] = 0x00000100;
1487 pNv->PFIFO[0x0490] = 0x00000000;
1488 pNv->PFIFO[0x0491] = 0x00000000;
1489 if(pNv->Architecture >= NV_ARCH_40)
1490 pNv->PFIFO[0x048B] = 0x00001213;
1491 else
1492 pNv->PFIFO[0x048B] = 0x00001209;
1493 pNv->PFIFO[0x0400] = 0x00000000;
1494 pNv->PFIFO[0x0414] = 0x00000000;
1495 pNv->PFIFO[0x0084] = 0x03000100;
1496 pNv->PFIFO[0x0085] = 0x00000110;
1497 pNv->PFIFO[0x0086] = 0x00000112;
1498 pNv->PFIFO[0x0143] = 0x0000FFFF;
1499 pNv->PFIFO[0x0496] = 0x0000FFFF;
1500 pNv->PFIFO[0x0050] = 0x00000000;
1501 pNv->PFIFO[0x0040] = 0xFFFFFFFF;
1502 pNv->PFIFO[0x0415] = 0x00000001;
1503 pNv->PFIFO[0x048C] = 0x00000000;
1504 pNv->PFIFO[0x04A0] = 0x00000000;
1505 #if AROS_BIG_ENDIAN
1506 pNv->PFIFO[0x0489] = 0x800F0078;
1507 #else
1508 pNv->PFIFO[0x0489] = 0x000F0078;
1509 #endif
1510 pNv->PFIFO[0x0488] = 0x00000001;
1511 pNv->PFIFO[0x0480] = 0x00000001;
1512 pNv->PFIFO[0x0494] = 0x00000001;
1513 pNv->PFIFO[0x0495] = 0x00000001;
1514 pNv->PFIFO[0x0140] = 0x00000001;
1516 if(pNv->Architecture >= NV_ARCH_10) {
1517 if(pNv->twoHeads) {
1518 pNv->PCRTC0[0x0860/4] = state->head;
1519 pNv->PCRTC0[0x2860/4] = state->head2;
1521 pNv->PRAMDAC[0x0404/4] |= (1 << 25);
1523 pNv->PMC[0x8704/4] = 1;
1524 pNv->PMC[0x8140/4] = 0;
1525 pNv->PMC[0x8920/4] = 0;
1526 pNv->PMC[0x8924/4] = 0;
1527 pNv->PMC[0x8908/4] = pNv->FrameBufferSize - 1;
1528 pNv->PMC[0x890C/4] = pNv->FrameBufferSize - 1;
1529 pNv->PMC[0x1588/4] = 0;
1531 pNv->PCRTC[0x0810/4] = state->cursorConfig;
1532 pNv->PCRTC[0x0830/4] = state->displayV - 3;
1533 pNv->PCRTC[0x0834/4] = state->displayV - 1;
1535 if(pNv->FlatPanel) {
1536 if((pNv->Chipset & 0x0ff0) == 0x0110) {
1537 pNv->PRAMDAC[0x0528/4] = state->dither;
1538 } else
1539 if(pNv->twoHeads) {
1540 pNv->PRAMDAC[0x083C/4] = state->dither;
1543 VGA_WR08(pNv->PCIO, 0x03D4, 0x53);
1544 VGA_WR08(pNv->PCIO, 0x03D5, state->timingH);
1545 VGA_WR08(pNv->PCIO, 0x03D4, 0x54);
1546 VGA_WR08(pNv->PCIO, 0x03D5, state->timingV);
1547 VGA_WR08(pNv->PCIO, 0x03D4, 0x21);
1548 VGA_WR08(pNv->PCIO, 0x03D5, 0xfa);
1551 VGA_WR08(pNv->PCIO, 0x03D4, 0x41);
1552 VGA_WR08(pNv->PCIO, 0x03D5, state->extra);
1555 VGA_WR08(pNv->PCIO, 0x03D4, 0x19);
1556 VGA_WR08(pNv->PCIO, 0x03D5, state->repaint0);
1557 VGA_WR08(pNv->PCIO, 0x03D4, 0x1A);
1558 VGA_WR08(pNv->PCIO, 0x03D5, state->repaint1);
1559 VGA_WR08(pNv->PCIO, 0x03D4, 0x25);
1560 VGA_WR08(pNv->PCIO, 0x03D5, state->screen);
1561 VGA_WR08(pNv->PCIO, 0x03D4, 0x28);
1562 VGA_WR08(pNv->PCIO, 0x03D5, state->pixel);
1563 VGA_WR08(pNv->PCIO, 0x03D4, 0x2D);
1564 VGA_WR08(pNv->PCIO, 0x03D5, state->horiz);
1565 VGA_WR08(pNv->PCIO, 0x03D4, 0x1C);
1566 VGA_WR08(pNv->PCIO, 0x03D5, state->fifo);
1567 VGA_WR08(pNv->PCIO, 0x03D4, 0x1B);
1568 VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration0);
1569 VGA_WR08(pNv->PCIO, 0x03D4, 0x20);
1570 VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration1);
1571 if(pNv->Architecture >= NV_ARCH_30) {
1572 VGA_WR08(pNv->PCIO, 0x03D4, 0x47);
1573 VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration1 >> 8);
1575 VGA_WR08(pNv->PCIO, 0x03D4, 0x30);
1576 VGA_WR08(pNv->PCIO, 0x03D5, state->cursor0);
1577 VGA_WR08(pNv->PCIO, 0x03D4, 0x31);
1578 VGA_WR08(pNv->PCIO, 0x03D5, state->cursor1);
1579 VGA_WR08(pNv->PCIO, 0x03D4, 0x2F);
1580 VGA_WR08(pNv->PCIO, 0x03D5, state->cursor2);
1581 VGA_WR08(pNv->PCIO, 0x03D4, 0x39);
1582 VGA_WR08(pNv->PCIO, 0x03D5, state->interlace);
1584 if(!pNv->FlatPanel) {
1585 pNv->PRAMDAC0[0x050C/4] = state->pllsel;
1586 pNv->PRAMDAC0[0x0508/4] = state->vpll;
1587 if(pNv->twoHeads)
1588 pNv->PRAMDAC0[0x0520/4] = state->vpll2;
1589 if(pNv->twoStagePLL) {
1590 pNv->PRAMDAC0[0x0578/4] = state->vpllB;
1591 pNv->PRAMDAC0[0x057C/4] = state->vpll2B;
1593 } else {
1594 pNv->PRAMDAC[0x0848/4] = state->scale;
1597 /* begin flat panel hacks */
1598 /* This is unfortunate, but some chips need this register
1599 tweaked or else you get artifacts where adjacent pixels are
1600 swapped. There are no hard rules for what to set here so all
1601 we can do is experiment and apply hacks. */
1603 if(((pNv->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
1604 /* At least one NV34 laptop needs this workaround. */
1605 pNv->PRAMDAC[0x0828/4] &= ~1;
1608 if((pNv->Chipset & 0xfff0) == 0x0310) {
1609 pNv->PRAMDAC[0x0828/4] |= 1;
1612 /* end flat panel hacks */
1614 pNv->PRAMDAC[0x0600/4] = state->general;
1616 pNv->PCRTC[0x0140/4] = 0;
1617 pNv->PCRTC[0x0100/4] = 1;
1619 pNv->CurrentState = state;
1623 ** stegerg: Status NVUnloadStateExt(): should "match" xfree nv NVUnloadStateExt()
1624 ** in xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c version:
1625 ** 1.12 2004/11/30 23:50:26 mvojkovi
1628 void NVUnloadStateExt
1630 NVPtr pNv,
1631 RIVA_HW_STATE *state
1634 VGA_WR08(pNv->PCIO, 0x03D4, 0x19);
1635 state->repaint0 = VGA_RD08(pNv->PCIO, 0x03D5);
1636 VGA_WR08(pNv->PCIO, 0x03D4, 0x1A);
1637 state->repaint1 = VGA_RD08(pNv->PCIO, 0x03D5);
1638 VGA_WR08(pNv->PCIO, 0x03D4, 0x25);
1639 state->screen = VGA_RD08(pNv->PCIO, 0x03D5);
1640 VGA_WR08(pNv->PCIO, 0x03D4, 0x28);
1641 state->pixel = VGA_RD08(pNv->PCIO, 0x03D5);
1642 VGA_WR08(pNv->PCIO, 0x03D4, 0x2D);
1643 state->horiz = VGA_RD08(pNv->PCIO, 0x03D5);
1644 VGA_WR08(pNv->PCIO, 0x03D4, 0x1C);
1645 state->fifo = VGA_RD08(pNv->PCIO, 0x03D5);
1646 VGA_WR08(pNv->PCIO, 0x03D4, 0x1B);
1647 state->arbitration0 = VGA_RD08(pNv->PCIO, 0x03D5);
1648 VGA_WR08(pNv->PCIO, 0x03D4, 0x20);
1649 state->arbitration1 = VGA_RD08(pNv->PCIO, 0x03D5);
1650 if(pNv->Architecture >= NV_ARCH_30) {
1651 VGA_WR08(pNv->PCIO, 0x03D4, 0x47);
1652 state->arbitration1 |= (VGA_RD08(pNv->PCIO, 0x03D5) & 1) << 8;
1654 VGA_WR08(pNv->PCIO, 0x03D4, 0x30);
1655 state->cursor0 = VGA_RD08(pNv->PCIO, 0x03D5);
1656 VGA_WR08(pNv->PCIO, 0x03D4, 0x31);
1657 state->cursor1 = VGA_RD08(pNv->PCIO, 0x03D5);
1658 VGA_WR08(pNv->PCIO, 0x03D4, 0x2F);
1659 state->cursor2 = VGA_RD08(pNv->PCIO, 0x03D5);
1660 VGA_WR08(pNv->PCIO, 0x03D4, 0x39);
1661 state->interlace = VGA_RD08(pNv->PCIO, 0x03D5);
1662 state->vpll = pNv->PRAMDAC0[0x0508/4];
1663 if(pNv->twoHeads)
1664 state->vpll2 = pNv->PRAMDAC0[0x0520/4];
1665 if(pNv->twoStagePLL) {
1666 state->vpllB = pNv->PRAMDAC0[0x0578/4];
1667 state->vpll2B = pNv->PRAMDAC0[0x057C/4];
1669 state->pllsel = pNv->PRAMDAC0[0x050C/4];
1670 state->general = pNv->PRAMDAC[0x0600/4];
1671 state->scale = pNv->PRAMDAC[0x0848/4];
1672 state->config = pNv->PFB[0x0200/4];
1674 if(pNv->Architecture >= NV_ARCH_10) {
1675 if(pNv->twoHeads) {
1676 state->head = pNv->PCRTC0[0x0860/4];
1677 state->head2 = pNv->PCRTC0[0x2860/4];
1678 VGA_WR08(pNv->PCIO, 0x03D4, 0x44);
1679 state->crtcOwner = VGA_RD08(pNv->PCIO, 0x03D5);
1681 VGA_WR08(pNv->PCIO, 0x03D4, 0x41);
1682 state->extra = VGA_RD08(pNv->PCIO, 0x03D5);
1683 state->cursorConfig = pNv->PCRTC[0x0810/4];
1685 if((pNv->Chipset & 0x0ff0) == 0x0110) {
1686 state->dither = pNv->PRAMDAC[0x0528/4];
1687 } else
1688 if(pNv->twoHeads) {
1689 state->dither = pNv->PRAMDAC[0x083C/4];
1692 if(pNv->FlatPanel) {
1693 VGA_WR08(pNv->PCIO, 0x03D4, 0x53);
1694 state->timingH = VGA_RD08(pNv->PCIO, 0x03D5);
1695 VGA_WR08(pNv->PCIO, 0x03D4, 0x54);
1696 state->timingV = VGA_RD08(pNv->PCIO, 0x03D5);
1701 void NVSetStartAddress (
1702 NVPtr pNv,
1703 ULONG start
1706 pNv->PCRTC[0x800/4] = start;
1709 void NVLoadDAC(
1710 NVPtr pNv
1713 int i;
1715 VGA_WR08(pNv->PDIO, 0x3c6, 0xff);
1716 VGA_WR08(pNv->PDIO, 0x3c8, 0);
1717 for (i=0; i < 768; i++)
1718 VGA_WR08(pNv->PDIO, 0x3c9, pNv->CurrentState->Regs.dac[i]);
1721 static void InitBaseRegs(struct staticdata *sd, struct CardState *card, Sync *mode)
1723 /* Determine sync polarity */
1724 if (mode->VDisplay < 400)
1725 card->Regs.misc = 0xa3;
1726 else if (mode->VDisplay < 480)
1727 card->Regs.misc = 0x63;
1728 else if (mode->VDisplay < 768)
1729 card->Regs.misc = 0xe3;
1730 else
1731 card->Regs.misc = 0x23;
1733 card->Regs.seq[0] = 0x03;
1734 card->Regs.seq[1] = 0x01;
1735 card->Regs.seq[2] = 0x0f;
1736 card->Regs.seq[3] = 0x00;
1737 card->Regs.seq[4] = 0x0e;
1739 card->Regs.crtc[8] = 0;
1740 card->Regs.crtc[10] = 0; //0x20;
1741 card->Regs.crtc[14] = 0;
1742 card->Regs.crtc[17] = (mode->VSyncEnd & 0x0f) | 0x20;
1743 card->Regs.crtc[18] = (mode->VDisplay - 1) & 0xff;
1744 card->Regs.crtc[19] = card->width >> 4;
1745 card->Regs.crtc[20] = 0;
1746 card->Regs.crtc[21] = (mode->VSyncStart - 1) & 0xff;
1747 card->Regs.crtc[22] = (mode->VSyncEnd - 1) & 0xff;
1748 card->Regs.crtc[23] = 0xc3; // 0xc3
1749 card->Regs.crtc[24] = 0xff;
1750 card->Regs.crtc[40] = 0x40;
1752 card->Regs.gra[0] = 0x00;
1753 card->Regs.gra[1] = 0x00;
1754 card->Regs.gra[2] = 0x00;
1755 card->Regs.gra[3] = 0x00;
1756 card->Regs.gra[4] = 0x00;
1757 card->Regs.gra[5] = 0x40;
1758 card->Regs.gra[6] = 0x05;
1759 card->Regs.gra[7] = 0x0f;
1760 card->Regs.gra[8] = 0xff;
1762 card->Regs.attr[0] = 0x00;
1763 card->Regs.attr[1] = 0x01;
1764 card->Regs.attr[2] = 0x02;
1765 card->Regs.attr[3] = 0x03;
1766 card->Regs.attr[4] = 0x04;
1767 card->Regs.attr[5] = 0x05;
1768 card->Regs.attr[6] = 0x06;
1769 card->Regs.attr[7] = 0x07;
1770 card->Regs.attr[8] = 0x08;
1771 card->Regs.attr[9] = 0x09;
1772 card->Regs.attr[10] = 0x0a;
1773 card->Regs.attr[11] = 0x0b;
1774 card->Regs.attr[12] = 0x0c;
1775 card->Regs.attr[13] = 0x0d;
1776 card->Regs.attr[14] = 0x0e;
1777 card->Regs.attr[15] = 0x0f;
1778 card->Regs.attr[16] = 0x41;
1779 card->Regs.attr[17] = 0x01;
1780 card->Regs.attr[18] = 0x0f;
1781 card->Regs.attr[19] = 0x00;
1782 card->Regs.attr[20] = 0x00;
1785 #define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b))
1786 #define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
1787 #define SetBF(mask,value) ((value) << (0?mask))
1788 #define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
1789 #define SetBitField(value,from,to) SetBF(to, GetBF(value,from))
1790 #define SetBit(n) (1<<(n))
1791 #define Set8Bits(value) ((value)&0xff)
1793 void InitMode(struct staticdata *sd, struct CardState *state,
1794 ULONG width, ULONG height, UBYTE bpp, ULONG pixelc, ULONG base,
1795 ULONG HDisplay, ULONG VDisplay,
1796 ULONG HSyncStart, ULONG HSyncEnd, ULONG HTotal,
1797 ULONG VSyncStart, ULONG VSyncEnd, ULONG VTotal)
1799 D(bug("[NVidia] Init %dx%dx%d @%x mode\n", width, height, bpp, base));
1801 ULONG HBlankStart, HBlankEnd, VBlankStart, VBlankEnd, OrgHDisplay = HDisplay;
1803 Sync mode = {
1804 pixelc, 0,
1805 HDisplay, HSyncStart, HSyncEnd, HTotal,
1806 VDisplay, VSyncStart, VSyncEnd, VTotal
1809 InitBaseRegs(sd, state, &mode);
1811 HDisplay = (HDisplay >> 3) - 1;
1812 HSyncStart = (HSyncStart >> 3) - 1;
1813 HSyncEnd = (HSyncEnd >> 3) - 1;
1814 HTotal = (HTotal >> 3) - 5;
1815 HBlankStart = HDisplay;
1816 HBlankEnd = HTotal + 4;
1818 VDisplay -= 1;
1819 VSyncStart -= 1;
1820 VSyncEnd -= 1;
1821 VTotal -= 2;
1822 VBlankStart = VDisplay;
1823 VBlankEnd = VTotal + 1;
1825 if (bpp <= 8)
1826 state->bitsPerPixel = 8;
1827 else if (bpp <= 16)
1828 state->bitsPerPixel = 16;
1829 else
1830 state->bitsPerPixel = 32;
1832 if (sd->Card.FlatPanel)
1834 VSyncStart = VTotal - 3;
1835 VSyncEnd = VTotal - 2;
1836 VBlankStart = VSyncStart;
1837 HSyncStart = HTotal - 5;
1838 HSyncEnd = HTotal - 2;
1839 HBlankEnd = HTotal + 4;
1842 state->Regs.crtc[0x00] = Set8Bits(HTotal);
1843 state->Regs.crtc[0x01] = Set8Bits(HDisplay);
1844 state->Regs.crtc[0x02] = Set8Bits(HBlankStart);
1845 state->Regs.crtc[0x03] = SetBitField(HBlankEnd, 4:0, 4:0) | SetBit(7);
1846 state->Regs.crtc[0x04] = Set8Bits(HSyncStart);
1847 state->Regs.crtc[0x05] = SetBitField(HBlankEnd, 5:5, 7:7) |
1848 SetBitField(HSyncEnd, 4:0, 4:0);
1849 state->Regs.crtc[0x06] = SetBitField(VTotal, 7:0, 7:0);
1850 state->Regs.crtc[0x07] = SetBitField(VTotal, 8:8, 0:0) |
1851 SetBitField(VDisplay, 8:8, 1:1) |
1852 SetBitField(VSyncStart, 8:8, 2:2) |
1853 SetBitField(VBlankStart, 8:8, 3:3) |
1854 SetBit(4) |
1855 SetBitField(VTotal, 9:9, 5:5) |
1856 SetBitField(VDisplay, 9:9, 6:6) |
1857 SetBitField(VSyncStart, 9:9, 7:7);
1858 state->Regs.crtc[0x09] = SetBitField(VBlankStart, 9:9, 5:5) | SetBit(6); // V_DOUBLESCAN?
1859 state->Regs.crtc[0x10] = Set8Bits(VSyncStart);
1860 state->Regs.crtc[0x11] = SetBitField(VSyncEnd, 3:0, 3:0) | SetBit(5);
1861 state->Regs.crtc[0x12] = Set8Bits(VDisplay);
1862 state->Regs.crtc[0x13] = ((width / 8) * (state->bitsPerPixel / 8));
1863 state->Regs.crtc[0x15] = Set8Bits(VBlankStart);
1864 state->Regs.crtc[0x16] = Set8Bits(VBlankEnd);
1866 state->Regs.attr[0x10] = 0x01;
1868 state->screen =
1869 SetBitField(HBlankEnd, 6:6, 4:4) |
1870 SetBitField(VBlankStart, 10:10, 3:3) |
1871 SetBitField(VSyncStart, 10:10, 2:2) |
1872 SetBitField(VDisplay, 10:10, 1:1) |
1873 SetBitField(VTotal, 10:10, 0:0);
1875 state->horiz =
1876 SetBitField(HTotal, 8:8, 0:0) |
1877 SetBitField(HDisplay, 8:8, 1:1) |
1878 SetBitField(HBlankStart, 8:8, 2:2) |
1879 SetBitField(HSyncStart, 8:8, 3:3);
1881 state->extra =
1882 SetBitField(VTotal, 11:11, 0:0) |
1883 SetBitField(VDisplay, 11:11, 2:2) |
1884 SetBitField(VSyncStart, 11:11, 4:4) |
1885 SetBitField(VBlankStart, 11:11, 6:6);
1887 state->interlace = 0xff;
1889 if (bpp >= 24) bpp = 32;
1891 if (sd->Card.Architecture >= NV_ARCH_10)
1892 sd->Card.CURSOR = (ULONG*)(sd->Card.FrameBuffer + sd->Card.CursorStart);
1894 // NVLockUnlock(sd, 0);
1895 NVCalcStateExt(sd, &sd->Card, state, bpp, width, OrgHDisplay, height, pixelc, 0);
1897 state->scale = sd->Card.PRAMDAC[0x0848/4] & 0xfff000ff;
1898 if (sd->Card.FlatPanel)
1900 state->pixel |= (1 << 7);
1901 if (!sd->Card.fpScaler || (sd->Card.fpWidth <= mode.HDisplay)
1902 || (sd->Card.fpHeight <= mode.VDisplay))
1904 state->scale |= (1 << 8);
1909 state->cursorConfig = 0x00000100;
1910 if (sd->Card.alphaCursor)
1912 state->cursorConfig |= 0x04011000;
1913 state->general |= (1 << 29);
1915 if((sd->Card.Chipset & 0x0ff0) == 0x0110) {
1916 state->dither = sd->Card.PRAMDAC[0x0528/4] & ~0x00010000;
1917 if(0) //sd->Card.FPDither)
1918 state->dither |= 0x00010000;
1919 else
1920 state->cursorConfig |= (1 << 28);
1921 } else
1922 if((sd->Card.Chipset & 0x0ff0) >= 0x0170) {
1923 state->dither = sd->Card.PRAMDAC[0x083C/4] & ~1;
1924 state->cursorConfig |= (1 << 28);
1925 if(0) //pNv->FPDither)
1926 state->dither |= 1;
1927 } else {
1928 state->cursorConfig |= (1 << 28);
1930 } else
1931 state->cursorConfig |= 0x02000000;
1934 // Init DAC
1935 if (bpp >1)
1937 int i;
1938 for (i=0; i <256; i++)
1940 state->Regs.dac[i*3+0] = i;
1941 state->Regs.dac[i*3+1] = i;
1942 state->Regs.dac[i*3+2] = i;
1946 state->offset = base;
1947 state->vpll = state->pll;
1948 state->vpll2 = state->pll;
1949 state->vpllB = state->pllB;
1950 state->vpll2B = state->pllB;
1952 VGA_WR08(sd->Card.PCIO, 0x03D4, 0x1C);
1953 state->fifo = VGA_RD08(sd->Card.PCIO, 0x03D5) & ~(1<<5);
1955 if(sd->Card.CRTCnumber) {
1956 state->head = sd->Card.PCRTC0[0x00000860/4] & ~0x00001000;
1957 state->head2 = sd->Card.PCRTC0[0x00002860/4] | 0x00001000;
1958 state->crtcOwner = 3;
1959 state->pllsel |= 0x20000800;
1960 state->vpll = sd->Card.PRAMDAC0[0x0508/4];
1961 if(sd->Card.twoStagePLL)
1962 state->vpllB = sd->Card.PRAMDAC0[0x0578/4];
1963 } else
1964 if(sd->Card.twoHeads) {
1965 state->head = sd->Card.PCRTC0[0x00000860/4] | 0x00001000;
1966 state->head2 = sd->Card.PCRTC0[0x00002860/4] & ~0x00001000;
1967 state->crtcOwner = 0;
1968 state->vpll2 = sd->Card.PRAMDAC0[0x0520/4];
1969 if(sd->Card.twoStagePLL)
1970 state->vpll2B = sd->Card.PRAMDAC0[0x057C/4];
1973 state->timingH = 0;
1974 state->timingV = 0;
1975 state->displayV = VDisplay;
1978 void acc_reset(struct staticdata *);
1980 void LoadState(struct staticdata *sd, struct CardState *state)
1982 int i;
1984 ObtainSemaphore(&sd->HWLock);
1986 // CRTC_out(sd, 0x11, 0x00);
1988 NVLockUnlock(sd, 0);
1989 NVLoadStateExt(&sd->Card, state);
1991 MISC_out(sd, sd->Card.CurrentState->Regs.misc);
1993 for (i=0; i < 0x05; i++)
1995 SEQ_out(sd, i, sd->Card.CurrentState->Regs.seq[i]);
1998 CRTC_out(sd, 17, sd->Card.CurrentState->Regs.crtc[17] & ~0x80);
1999 for (i=0; i < 0x41; i++)
2001 switch (i)
2003 case 0x19:
2004 case 0x20 ... 0x40:
2005 break;
2006 default:
2007 CRTC_out(sd, i, sd->Card.CurrentState->Regs.crtc[i]);
2008 break;
2012 for (i=0; i < 0x15; i++)
2013 ATTR_out(sd, i, sd->Card.CurrentState->Regs.attr[i]);
2015 for (i=0; i < 0x09; i++)
2016 GRA_out(sd, i, sd->Card.CurrentState->Regs.gra[i]);
2018 NVSetStartAddress(&sd->Card, sd->Card.CurrentState->offset);
2020 sd->Card.currentROP = 0xffffffff;
2021 // VGA_WR08(sd->Card.PVIO, 0x3c3, 1);
2023 NVLoadDAC(&sd->Card);
2024 acc_reset(sd);
2026 ReleaseSemaphore(&sd->HWLock);
2029 void DPMS(struct staticdata *sd, HIDDT_DPMSLevel state)
2031 UBYTE reg;
2033 ObtainSemaphore(&sd->HWLock);
2035 NVLockUnlock(sd,0);
2036 reg = CRTC_in(sd, 0x1a) & ~0xc0;
2038 switch(state)
2040 case vHidd_Gfx_DPMSLevel_Standby:
2041 reg |= 0x80;
2042 break;
2043 case vHidd_Gfx_DPMSLevel_Suspend:
2044 reg |= 0x40;
2045 break;
2046 case vHidd_Gfx_DPMSLevel_Off:
2047 reg |= 0xc0;
2048 break;
2049 default: // On
2050 break;
2053 CRTC_out(sd, 0x1a, reg);
2055 ReleaseSemaphore(&sd->HWLock);
2058 void Protect(struct staticdata *sd, UBYTE protect)
2060 ObtainSemaphore(&sd->HWLock);
2062 if (protect)
2064 UBYTE tmp = SEQ_in(sd, 1);
2065 SEQ_out(sd, 0, 1);
2066 SEQ_out(sd, 1, tmp | 0x20);
2068 else
2070 UBYTE tmp = SEQ_in(sd, 1);
2071 SEQ_out(sd, 1, tmp & ~0x20);
2072 SEQ_out(sd, 0, 3);
2075 ReleaseSemaphore(&sd->HWLock);
2078 static const UBYTE ROPTable[] = {
2079 [vHidd_GC_DrawMode_Clear] = 0x00,
2080 [vHidd_GC_DrawMode_And] = 0x88,
2081 [vHidd_GC_DrawMode_AndReverse] = 0x44,
2082 [vHidd_GC_DrawMode_Copy] = 0xcc,
2083 [vHidd_GC_DrawMode_AndInverted] = 0x22,
2084 [vHidd_GC_DrawMode_NoOp] = 0xaa,
2085 [vHidd_GC_DrawMode_Xor] = 0x66,
2086 [vHidd_GC_DrawMode_Or] = 0xee,
2087 [vHidd_GC_DrawMode_Nor] = 0x11,
2088 [vHidd_GC_DrawMode_Equiv] = 0x99,
2089 [vHidd_GC_DrawMode_Invert] = 0x55,
2090 [vHidd_GC_DrawMode_OrReverse] = 0xdd,
2091 [vHidd_GC_DrawMode_CopyInverted]= 0x33,
2092 [vHidd_GC_DrawMode_OrInverted] = 0xbb,
2093 [vHidd_GC_DrawMode_Nand] = 0x77,
2094 [vHidd_GC_DrawMode_Set] = 0xff,
2097 void NVDmaKickoff(struct Card *pNv)
2099 if(pNv->dmaCurrent != pNv->dmaPut) {
2100 pNv->dmaPut = pNv->dmaCurrent;
2101 WRITE_PUT(pNv, pNv->dmaPut);
2105 /* There is a HW race condition with videoram command buffers.
2106 You can't jump to the location of your put offset. We write put
2107 at the jump offset + SKIPS dwords with noop padding in between
2108 to solve this problem */
2109 #define SKIPS 8
2111 void
2112 NVDmaWait (
2113 struct Card *pNv,
2114 int size
2116 int dmaGet;
2118 size++;
2120 while(pNv->dmaFree < size) {
2121 dmaGet = READ_GET(pNv);
2123 if(pNv->dmaPut >= dmaGet) {
2124 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
2125 if(pNv->dmaFree < size) {
2126 NVDmaNext(pNv, 0x20000000);
2127 if(dmaGet <= SKIPS) {
2128 if(pNv->dmaPut <= SKIPS) /* corner case - will be idle */
2129 WRITE_PUT(pNv, SKIPS + 1);
2130 do { dmaGet = READ_GET(pNv); }
2131 while(dmaGet <= SKIPS);
2133 WRITE_PUT(pNv, SKIPS);
2134 pNv->dmaCurrent = pNv->dmaPut = SKIPS;
2135 pNv->dmaFree = dmaGet - (SKIPS + 1);
2137 } else
2138 pNv->dmaFree = dmaGet - pNv->dmaCurrent - 1;
2142 void NVSetPattern(
2143 struct staticdata *sd,
2144 ULONG clr0,
2145 ULONG clr1,
2146 ULONG pat0,
2147 ULONG pat1
2150 struct Card *pNv = &sd->Card;
2152 NVDmaStart(pNv, PATTERN_COLOR_0, 4);
2153 NVDmaNext (pNv, clr0);
2154 NVDmaNext (pNv, clr1);
2155 NVDmaNext (pNv, pat0);
2156 NVDmaNext (pNv, pat1);
2159 void NVSetRopSolid(struct staticdata *sd, ULONG rop, ULONG planemask)
2161 struct Card *pNv = &sd->Card;
2163 if(planemask != ~0) {
2164 NVSetPattern(sd, 0, planemask, ~0, ~0);
2165 if(pNv->currentROP != (rop + 32)) {
2166 NVDmaStart(pNv, ROP_SET, 1);
2167 NVDmaNext (pNv, ROPTable[rop]);
2168 pNv->currentROP = rop + 32;
2170 } else
2171 if (pNv->currentROP != rop) {
2172 if(pNv->currentROP >= 16)
2173 NVSetPattern(sd, ~0, ~0, ~0, ~0);
2174 NVDmaStart(pNv, ROP_SET, 1);
2175 NVDmaNext (pNv, ROPTable[rop]);
2176 pNv->currentROP = rop;
2180 void acc_reset(struct staticdata *sd)
2182 struct Card *pNv = &sd->Card;
2183 int pitch, i;
2185 LOCK_HW
2187 pitch = pNv->CurrentState->width *
2188 (pNv->CurrentState->bitsPerPixel >> 3);
2190 sd->src_pitch = pitch;
2191 sd->dst_pitch = pitch;
2192 sd->src_offset = pNv->CurrentState->offset;
2193 sd->dst_offset = pNv->CurrentState->offset;
2195 pNv->dmaBase = (ULONG*)(&pNv->FrameBuffer[pNv->FbUsableSize]);
2197 for(i = 0; i < SKIPS; i++)
2198 pNv->dmaBase[i] = 0x00000000;
2200 pNv->dmaBase[0x0 + SKIPS] = 0x00040000;
2201 pNv->dmaBase[0x1 + SKIPS] = 0x80000010;
2202 pNv->dmaBase[0x2 + SKIPS] = 0x00042000;
2203 pNv->dmaBase[0x3 + SKIPS] = 0x80000011;
2204 pNv->dmaBase[0x4 + SKIPS] = 0x00044000;
2205 pNv->dmaBase[0x5 + SKIPS] = 0x80000012;
2206 pNv->dmaBase[0x6 + SKIPS] = 0x00046000;
2207 pNv->dmaBase[0x7 + SKIPS] = 0x80000013;
2208 pNv->dmaBase[0x8 + SKIPS] = 0x00048000;
2209 pNv->dmaBase[0x9 + SKIPS] = 0x80000014;
2210 pNv->dmaBase[0xA + SKIPS] = 0x0004A000;
2211 pNv->dmaBase[0xB + SKIPS] = 0x80000015;
2212 pNv->dmaBase[0xC + SKIPS] = 0x0004C000;
2213 pNv->dmaBase[0xD + SKIPS] = 0x80000016;
2214 pNv->dmaBase[0xE + SKIPS] = 0x0004E000;
2215 pNv->dmaBase[0xF + SKIPS] = 0x80000017;
2217 pNv->dmaPut = 0;
2218 pNv->dmaCurrent = 16 + SKIPS;
2219 pNv->dmaMax = 8191;
2220 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
2222 switch(pNv->CurrentState->bpp) {
2223 case 32:
2224 case 24:
2225 sd->surface_format = SURFACE_FORMAT_DEPTH24;
2226 sd->pattern_format = PATTERN_FORMAT_DEPTH24;
2227 sd->rect_format = RECT_FORMAT_DEPTH24;
2228 sd->line_format = LINE_FORMAT_DEPTH24;
2229 break;
2230 case 16:
2231 case 15:
2232 sd->surface_format = SURFACE_FORMAT_DEPTH16;
2233 sd->pattern_format = PATTERN_FORMAT_DEPTH16;
2234 sd->rect_format = RECT_FORMAT_DEPTH16;
2235 sd->line_format = LINE_FORMAT_DEPTH16;
2236 break;
2237 default:
2238 sd->surface_format = SURFACE_FORMAT_DEPTH8;
2239 sd->pattern_format = PATTERN_FORMAT_DEPTH8;
2240 sd->rect_format = RECT_FORMAT_DEPTH8;
2241 sd->line_format = LINE_FORMAT_DEPTH8;
2242 break;
2245 NVDmaStart(pNv, SURFACE_FORMAT, 4);
2246 NVDmaNext (pNv, sd->surface_format);
2247 NVDmaNext (pNv, sd->dst_pitch | (sd->src_pitch << 16));
2248 NVDmaNext (pNv, sd->src_offset);
2249 NVDmaNext (pNv, sd->dst_offset);
2251 NVDmaStart(pNv, PATTERN_FORMAT, 1);
2252 NVDmaNext (pNv, sd->pattern_format);
2254 NVDmaStart(pNv, RECT_FORMAT, 1);
2255 NVDmaNext (pNv, sd->rect_format);
2257 NVDmaStart(pNv, LINE_FORMAT, 1);
2258 NVDmaNext (pNv, sd->line_format);
2260 NVSetRopSolid(sd, vHidd_GC_DrawMode_Copy, ~0);
2262 NVDmaKickoff(pNv);
2264 UNLOCK_HW
2267 void NVSync(struct staticdata *sd)
2269 struct Card *pNv = &sd->Card;
2271 if(pNv->DMAKickoffCallback)
2272 (*pNv->DMAKickoffCallback)(sd);
2274 while(READ_GET(pNv) != pNv->dmaPut);
2276 while(pNv->PGRAPH[0x0700/4]);
2278 sd->gpu_busy = FALSE;
2281 void NVDMAKickoffCallback(struct staticdata *sd)
2283 struct Card *pNv = &sd->Card;
2285 NVDmaKickoff(pNv);
2286 pNv->DMAKickoffCallback = NULL;
2289 void NVSelectHead(struct staticdata *sd, UBYTE head)
2291 if (head)
2293 sd->Card.PCIO = sd->Card.PCIO0 + 0x2000;
2294 sd->Card.PCRTC = sd->Card.PCRTC0 + 0x800;
2295 sd->Card.PRAMDAC = sd->Card.PRAMDAC0 + 0x800;
2296 sd->Card.PDIO = sd->Card.PDIO0 + 0x2000;
2298 else
2300 sd->Card.PCIO = sd->Card.PCIO0;
2301 sd->Card.PCRTC = sd->Card.PCRTC0;
2302 sd->Card.PRAMDAC = sd->Card.PRAMDAC0;
2303 sd->Card.PDIO = sd->Card.PDIO0;
2307 BOOL NVIsConnected (struct staticdata *sd, UBYTE output)
2309 NVPtr pNv = &sd->Card;
2310 volatile ULONG *PRAMDAC = pNv->PRAMDAC0;
2311 ULONG reg52C, reg608;
2312 BOOL present;
2313 int i;
2315 if(output) PRAMDAC += 0x800;
2317 reg52C = PRAMDAC[0x052C/4];
2318 reg608 = PRAMDAC[0x0608/4];
2320 PRAMDAC[0x0608/4] = reg608 & ~0x00010000;
2322 PRAMDAC[0x052C/4] = reg52C & 0x0000FEEE;
2324 //usleep(1000);
2325 for (i=0; i < 800000000; i++)
2329 PRAMDAC[0x052C/4] |= 1;
2331 pNv->PRAMDAC0[0x0610/4] = 0x94050140;
2332 pNv->PRAMDAC0[0x0608/4] |= 0x00001000;
2334 //usleep(1000);
2335 for (i=0; i < 800000000; i++)
2339 present = (PRAMDAC[0x0608/4] & (1 << 28)) ? TRUE : FALSE;
2341 pNv->PRAMDAC0[0x0608/4] &= 0x0000EFFF;
2343 PRAMDAC[0x052C/4] = reg52C;
2344 PRAMDAC[0x0608/4] = reg608;
2346 return present;