added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / common / hidd.nvidia / nvhardware.c
blob1444906b5d49dae35e3348981d102b78461549ae
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((implementation == 0x0170) ||
149 (implementation == 0x0180) ||
150 (implementation == 0x01F0) ||
151 (implementation >= 0x0250))
153 if(pNv->PEXTDEV[0x0000/4] & (1 << 22))
154 pNv->CrystalFreqKHz = 27000;
157 pNv->CursorStart = (pNv->RamAmountKBytes - 96) * 1024;
158 pNv->CURSOR = NULL; /* can't set this here */
159 pNv->MinVClockFreqKHz = 12000;
160 pNv->MaxVClockFreqKHz = pNv->twoStagePLL ? 400000 : 350000;
165 static inline void CRTC_out(struct staticdata *sd, UBYTE index, UBYTE val)
167 VGA_WR08(sd->Card.PCIO, 0x3d4, index);
168 VGA_WR08(sd->Card.PCIO, 0x3d5, val);
171 static inline UBYTE CRTC_in(struct staticdata *sd, UBYTE index)
173 VGA_WR08(sd->Card.PCIO, 0x3d4, index);
174 return VGA_RD08(sd->Card.PCIO, 0x3d5);
177 static inline void GRA_out(struct staticdata *sd, UBYTE index, UBYTE val)
179 VGA_WR08(sd->Card.PVIO, 0x3ce, index);
180 VGA_WR08(sd->Card.PVIO, 0x3cf, val);
183 static inline UBYTE GRA_in(struct staticdata *sd, UBYTE index)
185 VGA_WR08(sd->Card.PVIO, 0x3ce, index);
186 return VGA_RD08(sd->Card.PVIO, 0x3cf);
189 static inline void SEQ_out(struct staticdata *sd, UBYTE index, UBYTE val)
191 VGA_WR08(sd->Card.PVIO, 0x3c4, index);
192 VGA_WR08(sd->Card.PVIO, 0x3c5, val);
195 static inline UBYTE SEQ_in(struct staticdata *sd, UBYTE index)
197 VGA_WR08(sd->Card.PVIO, 0x3c4, index);
198 return VGA_RD08(sd->Card.PVIO, 0x3c5);
201 static inline void ATTR_out(struct staticdata *sd, UBYTE index, UBYTE val)
203 UBYTE tmp;
205 tmp = VGA_RD08(sd->Card.PCIO, 0x3da);
206 if (sd->Card.paletteEnabled)
207 index &= ~0x20;
208 else
209 index |= 0x20;
211 VGA_WR08(sd->Card.PCIO, 0x3c0, index);
212 VGA_WR08(sd->Card.PCIO, 0x3c0, val);
215 static inline UBYTE ATTR_in(struct staticdata *sd, UBYTE index)
217 UBYTE tmp;
219 tmp = VGA_RD08(sd->Card.PCIO, 0x3da);
220 if (sd->Card.paletteEnabled)
221 index &= ~0x20;
222 else
223 index |= 0x20;
224 VGA_WR08(sd->Card.PCIO, 0x3c0, index);
226 return VGA_RD08(sd->Card.PCIO, 0x3c1);
229 static inline void MISC_out(struct staticdata *sd, UBYTE val)
231 VGA_WR08(sd->Card.PVIO, 0x3c2, val);
234 static inline UBYTE MISC_in(struct staticdata *sd)
236 return VGA_RD08(sd->Card.PVIO, 0x3cc);
239 void NVLockUnlock(struct staticdata *sd, UBYTE Lock)
241 UBYTE cr11;
243 ObtainSemaphore(&sd->HWLock);
244 VGA_WR08(sd->Card.PCIO, 0x3D4, 0x1F);
245 VGA_WR08(sd->Card.PCIO, 0x3D5, Lock ? 0x99 : 0x57);
247 VGA_WR08(sd->Card.PCIO, 0x3D4, 0x11);
248 cr11 = VGA_RD08(sd->Card.PCIO, 0x3D5);
249 if(Lock) cr11 |= 0x80;
250 else cr11 &= ~0x80;
251 VGA_WR08(sd->Card.PCIO, 0x3D5, cr11);
252 ReleaseSemaphore(&sd->HWLock);
255 int NVShowHideCursor (struct staticdata *sd, UBYTE ShowHide)
257 int current = sd->Card.CurrentState->cursor1;
259 ObtainSemaphore(&sd->HWLock);
260 sd->Card.CurrentState->cursor1 = (sd->Card.CurrentState->cursor1 & 0xFE) |
261 (ShowHide & 0x01);
262 VGA_WR08(sd->Card.PCIO, 0x3D4, 0x31);
263 VGA_WR08(sd->Card.PCIO, 0x3D5, sd->Card.CurrentState->cursor1);
265 if (sd->Card.Architecture == NV_ARCH_40) { /* HW bug */
266 volatile ULONG curpos = sd->Card.PRAMDAC[0x0300/4];
267 sd->Card.PRAMDAC[0x0300/4] = curpos;
270 ReleaseSemaphore(&sd->HWLock);
271 return (current & 0x01);
274 /****************************************************************************\
276 * The video arbitration routines calculate some "magic" numbers. Fixes *
277 * the snow seen when accessing the framebuffer without it. *
278 * It just works (I hope). *
280 \****************************************************************************/
282 typedef struct {
283 int graphics_lwm;
284 int video_lwm;
285 int graphics_burst_size;
286 int video_burst_size;
287 int valid;
288 } nv4_fifo_info;
290 typedef struct {
291 int pclk_khz;
292 int mclk_khz;
293 int nvclk_khz;
294 char mem_page_miss;
295 char mem_latency;
296 int memory_width;
297 char enable_video;
298 char gr_during_vid;
299 char pix_bpp;
300 char mem_aligned;
301 char enable_mp;
302 } nv4_sim_state;
304 typedef struct {
305 int graphics_lwm;
306 int video_lwm;
307 int graphics_burst_size;
308 int video_burst_size;
309 int valid;
310 } nv10_fifo_info;
312 typedef struct {
313 int pclk_khz;
314 int mclk_khz;
315 int nvclk_khz;
316 char mem_page_miss;
317 char mem_latency;
318 int memory_type;
319 int memory_width;
320 char enable_video;
321 char gr_during_vid;
322 char pix_bpp;
323 char mem_aligned;
324 char enable_mp;
325 } nv10_sim_state;
327 static void nvGetClocks(NVPtr pNv, ULONG *MClk, ULONG *NVClk)
329 unsigned int pll, N, M, MB, NB, P;
331 if(pNv->Architecture >= NV_ARCH_40) {
332 pll = pNv->PMC[0x4020/4];
333 P = (pll >> 16) & 0x03;
334 pll = pNv->PMC[0x4024/4];
335 M = pll & 0xFF;
336 N = (pll >> 8) & 0xFF;
337 MB = (pll >> 16) & 0xFF;
338 NB = (pll >> 24) & 0xFF;
339 *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
341 pll = pNv->PMC[0x4000/4];
342 P = (pll >> 16) & 0x03;
343 pll = pNv->PMC[0x4004/4];
344 M = pll & 0xFF;
345 N = (pll >> 8) & 0xFF;
346 MB = (pll >> 16) & 0xFF;
347 NB = (pll >> 24) & 0xFF;
349 *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
350 } else
351 if(pNv->twoStagePLL) {
352 pll = pNv->PRAMDAC0[0x0504/4];
353 M = pll & 0xFF;
354 N = (pll >> 8) & 0xFF;
355 P = (pll >> 16) & 0x0F;
356 pll = pNv->PRAMDAC0[0x0574/4];
357 if(pll & 0x80000000) {
358 MB = pll & 0xFF;
359 NB = (pll >> 8) & 0xFF;
360 } else {
361 MB = 1;
362 NB = 1;
364 *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
366 pll = pNv->PRAMDAC0[0x0500/4];
367 M = pll & 0xFF;
368 N = (pll >> 8) & 0xFF;
369 P = (pll >> 16) & 0x0F;
370 pll = pNv->PRAMDAC0[0x0570/4];
371 if(pll & 0x80000000) {
372 MB = pll & 0xFF;
373 NB = (pll >> 8) & 0xFF;
374 } else {
375 MB = 1;
376 NB = 1;
378 *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
379 } else
380 if(((pNv->Chipset & 0x0ff0) == 0x0300) ||
381 ((pNv->Chipset & 0x0ff0) == 0x0330))
383 pll = pNv->PRAMDAC0[0x0504/4];
384 M = pll & 0x0F;
385 N = (pll >> 8) & 0xFF;
386 P = (pll >> 16) & 0x07;
387 if(pll & 0x00000080) {
388 MB = (pll >> 4) & 0x07;
389 NB = (pll >> 19) & 0x1f;
390 } else {
391 MB = 1;
392 NB = 1;
394 *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
396 pll = pNv->PRAMDAC0[0x0500/4];
397 M = pll & 0x0F;
398 N = (pll >> 8) & 0xFF;
399 P = (pll >> 16) & 0x07;
400 if(pll & 0x00000080) {
401 MB = (pll >> 4) & 0x07;
402 NB = (pll >> 19) & 0x1f;
403 } else {
404 MB = 1;
405 NB = 1;
407 *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
408 } else {
409 pll = pNv->PRAMDAC0[0x0504/4];
410 M = pll & 0xFF;
411 N = (pll >> 8) & 0xFF;
412 P = (pll >> 16) & 0x0F;
413 *MClk = (N * pNv->CrystalFreqKHz / M) >> P;
415 pll = pNv->PRAMDAC0[0x0500/4];
416 M = pll & 0xFF;
417 N = (pll >> 8) & 0xFF;
418 P = (pll >> 16) & 0x0F;
419 *NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
423 static void nv4CalcArbitration (
424 nv4_fifo_info *fifo,
425 nv4_sim_state *arb
428 int data, pagemiss, cas,width, video_enable, bpp;
429 int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
430 int found, mclk_extra, mclk_loop, cbs, m1, p1;
431 int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
432 int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
433 int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
435 fifo->valid = 1;
436 pclk_freq = arb->pclk_khz;
437 mclk_freq = arb->mclk_khz;
438 nvclk_freq = arb->nvclk_khz;
439 pagemiss = arb->mem_page_miss;
440 cas = arb->mem_latency;
441 width = arb->memory_width >> 6;
442 video_enable = arb->enable_video;
443 bpp = arb->pix_bpp;
444 mp_enable = arb->enable_mp;
445 clwm = 0;
446 vlwm = 0;
447 cbs = 128;
448 pclks = 2;
449 nvclks = 2;
450 nvclks += 2;
451 nvclks += 1;
452 mclks = 5;
453 mclks += 3;
454 mclks += 1;
455 mclks += cas;
456 mclks += 1;
457 mclks += 1;
458 mclks += 1;
459 mclks += 1;
460 mclk_extra = 3;
461 nvclks += 2;
462 nvclks += 1;
463 nvclks += 1;
464 nvclks += 1;
465 if (mp_enable)
466 mclks+=4;
467 nvclks += 0;
468 pclks += 0;
469 found = 0;
470 vbs = 0;
471 while (found != 1)
473 fifo->valid = 1;
474 found = 1;
475 mclk_loop = mclks+mclk_extra;
476 us_m = mclk_loop *1000*1000 / mclk_freq;
477 us_n = nvclks*1000*1000 / nvclk_freq;
478 us_p = nvclks*1000*1000 / pclk_freq;
479 if (video_enable)
481 video_drain_rate = pclk_freq * 2;
482 crtc_drain_rate = pclk_freq * bpp/8;
483 vpagemiss = 2;
484 vpagemiss += 1;
485 crtpagemiss = 2;
486 vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
487 if (nvclk_freq * 2 > mclk_freq * width)
488 video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
489 else
490 video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
491 us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
492 vlwm = us_video * video_drain_rate/(1000*1000);
493 vlwm++;
494 vbs = 128;
495 if (vlwm > 128) vbs = 64;
496 if (vlwm > (256-64)) vbs = 32;
497 if (nvclk_freq * 2 > mclk_freq * width)
498 video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
499 else
500 video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
501 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
502 us_crt =
503 us_video
504 +video_fill_us
505 +cpm_us
506 +us_m + us_n +us_p
508 clwm = us_crt * crtc_drain_rate/(1000*1000);
509 clwm++;
511 else
513 crtc_drain_rate = pclk_freq * bpp/8;
514 crtpagemiss = 2;
515 crtpagemiss += 1;
516 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
517 us_crt = cpm_us + us_m + us_n + us_p ;
518 clwm = us_crt * crtc_drain_rate/(1000*1000);
519 clwm++;
521 m1 = clwm + cbs - 512;
522 p1 = m1 * pclk_freq / mclk_freq;
523 p1 = p1 * bpp / 8;
524 if ((p1 < m1) && (m1 > 0))
526 fifo->valid = 0;
527 found = 0;
528 if (mclk_extra ==0) found = 1;
529 mclk_extra--;
531 else if (video_enable)
533 if ((clwm > 511) || (vlwm > 255))
535 fifo->valid = 0;
536 found = 0;
537 if (mclk_extra ==0) found = 1;
538 mclk_extra--;
541 else
543 if (clwm > 519)
545 fifo->valid = 0;
546 found = 0;
547 if (mclk_extra ==0) found = 1;
548 mclk_extra--;
551 if (clwm < 384) clwm = 384;
552 if (vlwm < 128) vlwm = 128;
553 data = (int)(clwm);
554 fifo->graphics_lwm = data;
555 fifo->graphics_burst_size = 128;
556 data = (int)((vlwm+15));
557 fifo->video_lwm = data;
558 fifo->video_burst_size = vbs;
562 static void nv4UpdateArbitrationSettings (
563 ULONG VClk,
564 ULONG pixelDepth,
565 ULONG *burst,
566 ULONG *lwm,
567 NVPtr pNv
570 nv4_fifo_info fifo_data;
571 nv4_sim_state sim_data;
572 ULONG MClk, NVClk, cfg1;
574 nvGetClocks(pNv, &MClk, &NVClk);
576 cfg1 = pNv->PFB[0x00000204/4];
577 sim_data.pix_bpp = (char)pixelDepth;
578 sim_data.enable_video = 0;
579 sim_data.enable_mp = 0;
580 sim_data.memory_width = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64;
581 sim_data.mem_latency = (char)cfg1 & 0x0F;
582 sim_data.mem_aligned = 1;
583 sim_data.mem_page_miss = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
584 sim_data.gr_during_vid = 0;
585 sim_data.pclk_khz = VClk;
586 sim_data.mclk_khz = MClk;
587 sim_data.nvclk_khz = NVClk;
588 nv4CalcArbitration(&fifo_data, &sim_data);
589 if (fifo_data.valid)
591 int b = fifo_data.graphics_burst_size >> 4;
592 *burst = 0;
593 while (b >>= 1) (*burst)++;
594 *lwm = fifo_data.graphics_lwm >> 3;
598 static void nv10CalcArbitration (
599 nv10_fifo_info *fifo,
600 nv10_sim_state *arb
603 int data, pagemiss, width, video_enable, bpp;
604 int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
605 int nvclk_fill;
606 int found, mclk_extra, mclk_loop, cbs, m1;
607 int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
608 int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
609 int vus_m;
610 int vpm_us, us_video, cpm_us, us_crt,clwm;
611 int clwm_rnd_down;
612 int m2us, us_pipe_min, p1clk, p2;
613 int min_mclk_extra;
614 int us_min_mclk_extra;
616 fifo->valid = 1;
617 pclk_freq = arb->pclk_khz; /* freq in KHz */
618 mclk_freq = arb->mclk_khz;
619 nvclk_freq = arb->nvclk_khz;
620 pagemiss = arb->mem_page_miss;
621 width = arb->memory_width/64;
622 video_enable = arb->enable_video;
623 bpp = arb->pix_bpp;
624 mp_enable = arb->enable_mp;
625 clwm = 0;
627 cbs = 512;
629 pclks = 4; /* lwm detect. */
631 nvclks = 3; /* lwm -> sync. */
632 nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
634 mclks = 1; /* 2 edge sync. may be very close to edge so just put one. */
636 mclks += 1; /* arb_hp_req */
637 mclks += 5; /* ap_hp_req tiling pipeline */
639 mclks += 2; /* tc_req latency fifo */
640 mclks += 2; /* fb_cas_n_ memory request to fbio block */
641 mclks += 7; /* sm_d_rdv data returned from fbio block */
643 /* fb.rd.d.Put_gc need to accumulate 256 bits for read */
644 if (arb->memory_type == 0)
645 if (arb->memory_width == 64) /* 64 bit bus */
646 mclks += 4;
647 else
648 mclks += 2;
649 else
650 if (arb->memory_width == 64) /* 64 bit bus */
651 mclks += 2;
652 else
653 mclks += 1;
655 if ((!video_enable) && (arb->memory_width == 128))
657 mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
658 min_mclk_extra = 17;
660 else
662 mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
663 /* mclk_extra = 4; */ /* Margin of error */
664 min_mclk_extra = 18;
667 nvclks += 1; /* 2 edge sync. may be very close to edge so just put one. */
668 nvclks += 1; /* fbi_d_rdv_n */
669 nvclks += 1; /* Fbi_d_rdata */
670 nvclks += 1; /* crtfifo load */
672 if(mp_enable)
673 mclks+=4; /* Mp can get in with a burst of 8. */
674 /* Extra clocks determined by heuristics */
676 nvclks += 0;
677 pclks += 0;
678 found = 0;
679 while(found != 1) {
680 fifo->valid = 1;
681 found = 1;
682 mclk_loop = mclks+mclk_extra;
683 us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
684 us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
685 us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
686 us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
687 us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
688 us_pipe_min = us_m_min + us_n + us_p;
690 vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
692 if(video_enable) {
693 crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
695 vpagemiss = 1; /* self generating page miss */
696 vpagemiss += 1; /* One higher priority before */
698 crtpagemiss = 2; /* self generating page miss */
699 if(mp_enable)
700 crtpagemiss += 1; /* if MA0 conflict */
702 vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
704 us_video = vpm_us + vus_m; /* Video has separate read return path */
706 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
707 us_crt =
708 us_video /* Wait for video */
709 +cpm_us /* CRT Page miss */
710 +us_m + us_n +us_p /* other latency */
713 clwm = us_crt * crtc_drain_rate/(1000*1000);
714 clwm++; /* fixed point <= float_point - 1. Fixes that */
715 } else {
716 crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
718 crtpagemiss = 1; /* self generating page miss */
719 crtpagemiss += 1; /* MA0 page miss */
720 if(mp_enable)
721 crtpagemiss += 1; /* if MA0 conflict */
722 cpm_us = crtpagemiss * pagemiss *1000*1000/ mclk_freq;
723 us_crt = cpm_us + us_m + us_n + us_p ;
724 clwm = us_crt * crtc_drain_rate/(1000*1000);
725 clwm++; /* fixed point <= float_point - 1. Fixes that */
727 /* Finally, a heuristic check when width == 64 bits */
728 if(width == 1){
729 nvclk_fill = nvclk_freq * 8;
730 if(crtc_drain_rate * 100 >= nvclk_fill * 102)
731 clwm = 0xfff; /*Large number to fail */
733 else if(crtc_drain_rate * 100 >= nvclk_fill * 98) {
734 clwm = 1024;
735 cbs = 512;
742 Overfill check:
746 clwm_rnd_down = ((int)clwm/8)*8;
747 if (clwm_rnd_down < clwm)
748 clwm += 8;
750 m1 = clwm + cbs - 1024; /* Amount of overfill */
751 m2us = us_pipe_min + us_min_mclk_extra;
753 /* pclk cycles to drain */
754 p1clk = m2us * pclk_freq/(1000*1000);
755 p2 = p1clk * bpp / 8; /* bytes drained. */
757 if((p2 < m1) && (m1 > 0)) {
758 fifo->valid = 0;
759 found = 0;
760 if(min_mclk_extra == 0) {
761 if(cbs <= 32) {
762 found = 1; /* Can't adjust anymore! */
763 } else {
764 cbs = cbs/2; /* reduce the burst size */
766 } else {
767 min_mclk_extra--;
769 } else {
770 if (clwm > 1023){ /* Have some margin */
771 fifo->valid = 0;
772 found = 0;
773 if(min_mclk_extra == 0)
774 found = 1; /* Can't adjust anymore! */
775 else
776 min_mclk_extra--;
780 if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
781 data = (int)(clwm);
782 /* printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
783 fifo->graphics_lwm = data; fifo->graphics_burst_size = cbs;
785 fifo->video_lwm = 1024; fifo->video_burst_size = 512;
789 static void nv10UpdateArbitrationSettings (
790 ULONG VClk,
791 ULONG pixelDepth,
792 ULONG *burst,
793 ULONG *lwm,
794 NVPtr pNv
797 nv10_fifo_info fifo_data;
798 nv10_sim_state sim_data;
799 ULONG MClk, NVClk, cfg1;
801 nvGetClocks(pNv, &MClk, &NVClk);
803 cfg1 = pNv->PFB[0x0204/4];
804 sim_data.pix_bpp = (char)pixelDepth;
805 sim_data.enable_video = 1;
806 sim_data.enable_mp = 0;
807 sim_data.memory_type = (pNv->PFB[0x0200/4] & 0x01) ? 1 : 0;
808 sim_data.memory_width = (pNv->PEXTDEV[0x0000/4] & 0x10) ? 128 : 64;
809 sim_data.mem_latency = (char)cfg1 & 0x0F;
810 sim_data.mem_aligned = 1;
811 sim_data.mem_page_miss = (char)(((cfg1>>4) &0x0F) + ((cfg1>>31) & 0x01));
812 sim_data.gr_during_vid = 0;
813 sim_data.pclk_khz = VClk;
814 sim_data.mclk_khz = MClk;
815 sim_data.nvclk_khz = NVClk;
817 nv10CalcArbitration(&fifo_data, &sim_data);
818 if (fifo_data.valid) {
819 int b = fifo_data.graphics_burst_size >> 4;
820 *burst = 0;
821 while (b >>= 1) (*burst)++;
822 *lwm = fifo_data.graphics_lwm >> 3;
826 static void nv30UpdateArbitrationSettings (
827 NVPtr pNv,
828 ULONG *burst,
829 ULONG *lwm
832 ULONG MClk, NVClk;
833 unsigned int fifo_size, burst_size, graphics_lwm;
835 fifo_size = 2048;
836 burst_size = 512;
837 graphics_lwm = fifo_size - burst_size;
839 nvGetClocks(pNv, &MClk, &NVClk);
841 *burst = 0;
842 burst_size >>= 5;
843 while(burst_size >>= 1) (*burst)++;
844 *lwm = graphics_lwm >> 3;
847 static void nForceUpdateArbitrationSettings (
848 ULONG VClk,
849 ULONG pixelDepth,
850 ULONG *burst,
851 ULONG *lwm,
852 struct staticdata *sd,
853 NVPtr pNv
856 nv10_fifo_info fifo_data;
857 nv10_sim_state sim_data;
858 unsigned int M, N, P, pll, MClk, NVClk, memctrl;
860 if((pNv->Chipset & 0x0FF0) == 0x01A0) {
861 unsigned int uMClkPostDiv;
863 uMClkPostDiv = (pciReadLong(sd, 0, 0, 3, 0x6C) >> 8) & 0xf;
864 if(!uMClkPostDiv) uMClkPostDiv = 4;
865 MClk = 400000 / uMClkPostDiv;
866 } else {
867 MClk = pciReadLong(sd, 0, 0, 5, 0x4C) / 1000;
870 pll = pNv->PRAMDAC0[0x0500/4];
871 M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
872 NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
873 sim_data.pix_bpp = (char)pixelDepth;
874 sim_data.enable_video = 0;
875 sim_data.enable_mp = 0;
876 sim_data.memory_type = (pciReadLong(sd, 0, 0, 1, 0x7C) >> 12) & 1;
877 sim_data.memory_width = 64;
879 memctrl = pciReadLong(sd, 0, 0, 3, 0x00) >> 16;
881 if((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
882 int dimm[3];
884 dimm[0] = (pciReadLong(sd, 0, 0, 2, 0x40) >> 8) & 0x4F;
885 dimm[1] = (pciReadLong(sd, 0, 0, 2, 0x44) >> 8) & 0x4F;
886 dimm[2] = (pciReadLong(sd, 0, 0, 2, 0x48) >> 8) & 0x4F;
888 if((dimm[0] + dimm[1]) != dimm[2]) {
889 bug("WARNING: "
890 "your nForce DIMMs are not arranged in optimal banks!\n");
894 sim_data.mem_latency = 3;
895 sim_data.mem_aligned = 1;
896 sim_data.mem_page_miss = 10;
897 sim_data.gr_during_vid = 0;
898 sim_data.pclk_khz = VClk;
899 sim_data.mclk_khz = MClk;
900 sim_data.nvclk_khz = NVClk;
901 nv10CalcArbitration(&fifo_data, &sim_data);
902 if (fifo_data.valid)
904 int b = fifo_data.graphics_burst_size >> 4;
905 *burst = 0;
906 while (b >>= 1) (*burst)++;
907 *lwm = fifo_data.graphics_lwm >> 3;
911 /****************************************************************************\
913 * RIVA Mode State Routines *
915 \****************************************************************************/
918 * Calculate the Video Clock parameters for the PLL.
920 static void CalcVClock (
921 ULONG clockIn,
922 ULONG *clockOut,
923 ULONG *pllOut,
924 NVPtr pNv
927 unsigned lowM, highM;
928 unsigned DeltaNew, DeltaOld;
929 unsigned VClk, Freq;
930 unsigned M, N, P;
932 DeltaOld = 0xFFFFFFFF;
934 VClk = (unsigned)clockIn;
936 if (pNv->CrystalFreqKHz == 13500) {
937 lowM = 7;
938 highM = 13;
939 } else {
940 lowM = 8;
941 highM = 14;
944 for (P = 0; P <= 4; P++) {
945 Freq = VClk << P;
946 if ((Freq >= 128000) && (Freq <= 350000)) {
947 for (M = lowM; M <= highM; M++) {
948 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
949 if(N <= 255) {
950 Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
951 if (Freq > VClk)
952 DeltaNew = Freq - VClk;
953 else
954 DeltaNew = VClk - Freq;
955 if (DeltaNew < DeltaOld) {
956 *pllOut = (P << 16) | (N << 8) | M;
957 *clockOut = Freq;
958 DeltaOld = DeltaNew;
966 static void CalcVClock2Stage (
967 ULONG clockIn,
968 ULONG *clockOut,
969 ULONG *pllOut,
970 ULONG *pllBOut,
971 NVPtr pNv
974 unsigned DeltaNew, DeltaOld;
975 unsigned VClk, Freq;
976 unsigned M, N, P;
978 DeltaOld = 0xFFFFFFFF;
980 *pllBOut = 0x80000401; /* fixed at x4 for now */
982 VClk = (unsigned)clockIn;
984 for (P = 0; P <= 6; P++) {
985 Freq = VClk << P;
986 if ((Freq >= 400000) && (Freq <= 1000000)) {
987 for (M = 1; M <= 13; M++) {
988 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
989 if((N >= 5) && (N <= 255)) {
990 Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
991 if (Freq > VClk)
992 DeltaNew = Freq - VClk;
993 else
994 DeltaNew = VClk - Freq;
995 if (DeltaNew < DeltaOld) {
996 *pllOut = (P << 16) | (N << 8) | M;
997 *clockOut = Freq;
998 DeltaOld = DeltaNew;
1008 * Calculate extended mode parameters (SVGA) and save in a
1009 * mode state structure.
1011 void NVCalcStateExt (
1012 struct staticdata *sd,
1013 NVPtr pNv,
1014 RIVA_HW_STATE *state,
1015 int bpp,
1016 int width,
1017 int hDisplaySize,
1018 int height,
1019 int dotClock,
1020 int flags
1023 ULONG pixelDepth, VClk;
1025 * Save mode parameters.
1027 state->bpp = bpp; /* this is not bitsPerPixel, it's 8,15,16,32 */
1028 state->width = width;
1029 state->height = height;
1031 * Extended RIVA registers.
1033 pixelDepth = (bpp + 1)/8;
1035 if(pNv->twoStagePLL)
1036 CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
1037 else
1038 CalcVClock(dotClock, &VClk, &state->pll, pNv);
1040 switch (pNv->Architecture)
1042 case NV_ARCH_04:
1043 nv4UpdateArbitrationSettings(VClk,
1044 pixelDepth * 8,
1045 &(state->arbitration0),
1046 &(state->arbitration1),
1047 pNv);
1048 state->cursor0 = 0x00;
1049 state->cursor1 = 0xbC;
1050 if (flags & V_DBLSCAN)
1051 state->cursor1 |= 2;
1052 state->cursor2 = 0x00000000;
1053 state->pllsel = 0x10000700;
1054 state->config = 0x00001114;
1055 state->general = bpp == 16 ? 0x00101100 : 0x00100100;
1056 state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1057 break;
1058 case NV_ARCH_10:
1059 case NV_ARCH_20:
1060 case NV_ARCH_30:
1061 default:
1062 if(((pNv->Chipset & 0xffff) == 0x01A0) ||
1063 ((pNv->Chipset & 0xffff) == 0x01f0))
1065 nForceUpdateArbitrationSettings(VClk,
1066 pixelDepth * 8,
1067 &(state->arbitration0),
1068 &(state->arbitration1),
1070 pNv);
1071 } else if (pNv->Architecture < NV_ARCH_30) {
1072 nv10UpdateArbitrationSettings(VClk,
1073 pixelDepth * 8,
1074 &(state->arbitration0),
1075 &(state->arbitration1),
1076 pNv);
1077 } else {
1078 nv30UpdateArbitrationSettings(pNv,
1079 &(state->arbitration0),
1080 &(state->arbitration1));
1082 state->cursor0 = 0x80 | (pNv->CursorStart >> 17);
1083 state->cursor1 = (pNv->CursorStart >> 11) << 2;
1084 state->cursor2 = pNv->CursorStart >> 24;
1085 if (flags & V_DBLSCAN)
1086 state->cursor1 |= 2;
1087 state->pllsel = 0x10000700;
1088 state->config = pNv->PFB[0x00000200/4];
1089 state->general = bpp == 16 ? 0x00101100 : 0x00100100;
1090 state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1091 break;
1093 if(bpp != 8) /* DirectColor */
1094 state->general |= 0x00000030;
1096 state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
1097 state->pixel = (pixelDepth > 2) ? 3 : pixelDepth;
1101 ** stegerg: Status NVLoadStateExt(): should "match" xfree nv NVLoadStateExt()
1102 ** in xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c version:
1103 ** 1.12 2004/11/30 23:50:26 mvojkovi
1105 ** Exception: some waitvsyncpossible stuff commented out
1108 void NVLoadStateExt (
1109 NVPtr pNv,
1110 RIVA_HW_STATE *state
1113 int i;
1115 pNv->PMC[0x0140/4] = 0x00000000;
1116 pNv->PMC[0x0200/4] = 0xFFFF00FF;
1117 pNv->PMC[0x0200/4] = 0xFFFFFFFF;
1119 pNv->PTIMER[0x0200] = 0x00000008;
1120 pNv->PTIMER[0x0210] = 0x00000003;
1121 pNv->PTIMER[0x0140] = 0x00000000;
1122 pNv->PTIMER[0x0100] = 0xFFFFFFFF;
1124 if(pNv->Architecture == NV_ARCH_04) {
1125 pNv->PFB[0x0200/4] = state->config;
1126 } else {
1127 pNv->PFB[0x0240/4] = 0;
1128 pNv->PFB[0x0244/4] = pNv->FrameBufferSize - 1;
1129 pNv->PFB[0x0250/4] = 0;
1130 pNv->PFB[0x0254/4] = pNv->FrameBufferSize - 1;
1131 pNv->PFB[0x0260/4] = 0;
1132 pNv->PFB[0x0264/4] = pNv->FrameBufferSize - 1;
1133 pNv->PFB[0x0270/4] = 0;
1134 pNv->PFB[0x0274/4] = pNv->FrameBufferSize - 1;
1135 pNv->PFB[0x0280/4] = 0;
1136 pNv->PFB[0x0284/4] = pNv->FrameBufferSize - 1;
1137 pNv->PFB[0x0290/4] = 0;
1138 pNv->PFB[0x0294/4] = pNv->FrameBufferSize - 1;
1139 pNv->PFB[0x02A0/4] = 0;
1140 pNv->PFB[0x02A4/4] = pNv->FrameBufferSize - 1;
1141 pNv->PFB[0x02B0/4] = 0;
1142 pNv->PFB[0x02B4/4] = pNv->FrameBufferSize - 1;
1145 if(pNv->Architecture >= NV_ARCH_40) {
1146 pNv->PRAMIN[0x0000] = 0x80000010;
1147 pNv->PRAMIN[0x0001] = 0x00101202;
1148 pNv->PRAMIN[0x0002] = 0x80000011;
1149 pNv->PRAMIN[0x0003] = 0x00101204;
1150 pNv->PRAMIN[0x0004] = 0x80000012;
1151 pNv->PRAMIN[0x0005] = 0x00101206;
1152 pNv->PRAMIN[0x0006] = 0x80000013;
1153 pNv->PRAMIN[0x0007] = 0x00101208;
1154 pNv->PRAMIN[0x0008] = 0x80000014;
1155 pNv->PRAMIN[0x0009] = 0x0010120A;
1156 pNv->PRAMIN[0x000A] = 0x80000015;
1157 pNv->PRAMIN[0x000B] = 0x0010120C;
1158 pNv->PRAMIN[0x000C] = 0x80000016;
1159 pNv->PRAMIN[0x000D] = 0x0010120E;
1160 pNv->PRAMIN[0x000E] = 0x80000017;
1161 pNv->PRAMIN[0x000F] = 0x00101210;
1162 pNv->PRAMIN[0x0800] = 0x00003000;
1163 pNv->PRAMIN[0x0801] = pNv->FrameBufferSize - 1;
1164 pNv->PRAMIN[0x0802] = 0x00000002;
1165 pNv->PRAMIN[0x0808] = 0x02080062;
1166 pNv->PRAMIN[0x0809] = 0x00000000;
1167 pNv->PRAMIN[0x080A] = 0x00001200;
1168 pNv->PRAMIN[0x080B] = 0x00001200;
1169 pNv->PRAMIN[0x080C] = 0x00000000;
1170 pNv->PRAMIN[0x080D] = 0x00000000;
1171 pNv->PRAMIN[0x0810] = 0x02080043;
1172 pNv->PRAMIN[0x0811] = 0x00000000;
1173 pNv->PRAMIN[0x0812] = 0x00000000;
1174 pNv->PRAMIN[0x0813] = 0x00000000;
1175 pNv->PRAMIN[0x0814] = 0x00000000;
1176 pNv->PRAMIN[0x0815] = 0x00000000;
1177 pNv->PRAMIN[0x0818] = 0x02080044;
1178 pNv->PRAMIN[0x0819] = 0x02000000;
1179 pNv->PRAMIN[0x081A] = 0x00000000;
1180 pNv->PRAMIN[0x081B] = 0x00000000;
1181 pNv->PRAMIN[0x081C] = 0x00000000;
1182 pNv->PRAMIN[0x081D] = 0x00000000;
1183 pNv->PRAMIN[0x0820] = 0x02080019;
1184 pNv->PRAMIN[0x0821] = 0x00000000;
1185 pNv->PRAMIN[0x0822] = 0x00000000;
1186 pNv->PRAMIN[0x0823] = 0x00000000;
1187 pNv->PRAMIN[0x0824] = 0x00000000;
1188 pNv->PRAMIN[0x0825] = 0x00000000;
1189 pNv->PRAMIN[0x0828] = 0x020A005C;
1190 pNv->PRAMIN[0x0829] = 0x00000000;
1191 pNv->PRAMIN[0x082A] = 0x00000000;
1192 pNv->PRAMIN[0x082B] = 0x00000000;
1193 pNv->PRAMIN[0x082C] = 0x00000000;
1194 pNv->PRAMIN[0x082D] = 0x00000000;
1195 pNv->PRAMIN[0x0830] = 0x0208009F;
1196 pNv->PRAMIN[0x0831] = 0x00000000;
1197 pNv->PRAMIN[0x0832] = 0x00001200;
1198 pNv->PRAMIN[0x0833] = 0x00001200;
1199 pNv->PRAMIN[0x0834] = 0x00000000;
1200 pNv->PRAMIN[0x0835] = 0x00000000;
1201 pNv->PRAMIN[0x0838] = 0x0208004A;
1202 pNv->PRAMIN[0x0839] = 0x02000000;
1203 pNv->PRAMIN[0x083A] = 0x00000000;
1204 pNv->PRAMIN[0x083B] = 0x00000000;
1205 pNv->PRAMIN[0x083C] = 0x00000000;
1206 pNv->PRAMIN[0x083D] = 0x00000000;
1207 pNv->PRAMIN[0x0840] = 0x02080077;
1208 pNv->PRAMIN[0x0841] = 0x00000000;
1209 pNv->PRAMIN[0x0842] = 0x00001200;
1210 pNv->PRAMIN[0x0843] = 0x00001200;
1211 pNv->PRAMIN[0x0844] = 0x00000000;
1212 pNv->PRAMIN[0x0845] = 0x00000000;
1213 pNv->PRAMIN[0x084C] = 0x00003002;
1214 pNv->PRAMIN[0x084D] = 0x00007FFF;
1215 pNv->PRAMIN[0x084E] = pNv->FbUsableSize | 0x00000002;
1217 #if AROS_BIG_ENDIAN
1218 pNv->PRAMIN[0x080A] |= 0x01000000;
1219 pNv->PRAMIN[0x0812] |= 0x01000000;
1220 pNv->PRAMIN[0x081A] |= 0x01000000;
1221 pNv->PRAMIN[0x0822] |= 0x01000000;
1222 pNv->PRAMIN[0x082A] |= 0x01000000;
1223 pNv->PRAMIN[0x0832] |= 0x01000000;
1224 pNv->PRAMIN[0x083A] |= 0x01000000;
1225 pNv->PRAMIN[0x0842] |= 0x01000000;
1226 pNv->PRAMIN[0x0819] = 0x01000000;
1227 pNv->PRAMIN[0x0839] = 0x01000000;
1228 #endif
1229 } else {
1231 pNv->PRAMIN[0x0000] = 0x80000010;
1232 pNv->PRAMIN[0x0001] = 0x80011201;
1233 pNv->PRAMIN[0x0002] = 0x80000011;
1234 pNv->PRAMIN[0x0003] = 0x80011202;
1235 pNv->PRAMIN[0x0004] = 0x80000012;
1236 pNv->PRAMIN[0x0005] = 0x80011203;
1237 pNv->PRAMIN[0x0006] = 0x80000013;
1238 pNv->PRAMIN[0x0007] = 0x80011204;
1239 pNv->PRAMIN[0x0008] = 0x80000014;
1240 pNv->PRAMIN[0x0009] = 0x80011205;
1241 pNv->PRAMIN[0x000A] = 0x80000015;
1242 pNv->PRAMIN[0x000B] = 0x80011206;
1243 pNv->PRAMIN[0x000C] = 0x80000016;
1244 pNv->PRAMIN[0x000D] = 0x80011207;
1245 pNv->PRAMIN[0x000E] = 0x80000017;
1246 pNv->PRAMIN[0x000F] = 0x80011208;
1247 pNv->PRAMIN[0x0800] = 0x00003000;
1248 pNv->PRAMIN[0x0801] = pNv->FrameBufferSize - 1;
1249 pNv->PRAMIN[0x0802] = 0x00000002;
1250 pNv->PRAMIN[0x0803] = 0x00000002;
1251 if(pNv->Architecture >= NV_ARCH_10)
1252 pNv->PRAMIN[0x0804] = 0x01008062;
1253 else
1254 pNv->PRAMIN[0x0804] = 0x01008042;
1255 pNv->PRAMIN[0x0805] = 0x00000000;
1256 pNv->PRAMIN[0x0806] = 0x12001200;
1257 pNv->PRAMIN[0x0807] = 0x00000000;
1258 pNv->PRAMIN[0x0808] = 0x01008043;
1259 pNv->PRAMIN[0x0809] = 0x00000000;
1260 pNv->PRAMIN[0x080A] = 0x00000000;
1261 pNv->PRAMIN[0x080B] = 0x00000000;
1262 pNv->PRAMIN[0x080C] = 0x01008044;
1263 pNv->PRAMIN[0x080D] = 0x00000002;
1264 pNv->PRAMIN[0x080E] = 0x00000000;
1265 pNv->PRAMIN[0x080F] = 0x00000000;
1266 pNv->PRAMIN[0x0810] = 0x01008019;
1267 pNv->PRAMIN[0x0811] = 0x00000000;
1268 pNv->PRAMIN[0x0812] = 0x00000000;
1269 pNv->PRAMIN[0x0813] = 0x00000000;
1270 pNv->PRAMIN[0x0814] = 0x0100A05C;
1271 pNv->PRAMIN[0x0815] = 0x00000000;
1272 pNv->PRAMIN[0x0816] = 0x00000000;
1273 pNv->PRAMIN[0x0817] = 0x00000000;
1274 // aros: commented out for now
1275 // if(pNv->WaitVSyncPossible)
1276 // pNv->PRAMIN[0x0818] = 0x0100809F;
1277 // else
1278 pNv->PRAMIN[0x0818] = 0x0100805F;
1279 pNv->PRAMIN[0x0819] = 0x00000000;
1280 pNv->PRAMIN[0x081A] = 0x12001200;
1281 pNv->PRAMIN[0x081B] = 0x00000000;
1282 pNv->PRAMIN[0x081C] = 0x0100804A;
1283 pNv->PRAMIN[0x081D] = 0x00000002;
1284 pNv->PRAMIN[0x081E] = 0x00000000;
1285 pNv->PRAMIN[0x081F] = 0x00000000;
1286 pNv->PRAMIN[0x0820] = 0x01018077;
1287 pNv->PRAMIN[0x0821] = 0x00000000;
1288 pNv->PRAMIN[0x0822] = 0x12001200;
1289 pNv->PRAMIN[0x0823] = 0x00000000;
1290 pNv->PRAMIN[0x0824] = 0x00003002;
1291 pNv->PRAMIN[0x0825] = 0x00007FFF;
1292 pNv->PRAMIN[0x0826] = pNv->FbUsableSize | 0x00000002;
1293 pNv->PRAMIN[0x0827] = 0x00000002;
1295 #if AROS_BIG_ENDIAN
1296 pNv->PRAMIN[0x0804] |= 0x00080000;
1297 pNv->PRAMIN[0x0808] |= 0x00080000;
1298 pNv->PRAMIN[0x080C] |= 0x00080000;
1299 pNv->PRAMIN[0x0810] |= 0x00080000;
1300 pNv->PRAMIN[0x0814] |= 0x00080000;
1301 pNv->PRAMIN[0x0818] |= 0x00080000;
1302 pNv->PRAMIN[0x081C] |= 0x00080000;
1303 pNv->PRAMIN[0x0820] |= 0x00080000;
1305 pNv->PRAMIN[0x080D] = 0x00000001;
1306 pNv->PRAMIN[0x081D] = 0x00000001;
1307 #endif
1310 if(pNv->Architecture < NV_ARCH_10) {
1311 if((pNv->Chipset & 0x0fff) == 0x0020) {
1312 pNv->PRAMIN[0x0824] |= 0x00020000;
1313 pNv->PRAMIN[0x0826] += (IPTR)pNv->FbAddress;
1315 pNv->PGRAPH[0x0080/4] = 0x000001FF;
1316 pNv->PGRAPH[0x0080/4] = 0x1230C000;
1317 pNv->PGRAPH[0x0084/4] = 0x72111101;
1318 pNv->PGRAPH[0x0088/4] = 0x11D5F071;
1319 pNv->PGRAPH[0x008C/4] = 0x0004FF31; /* stegerg: strange but that's so in xfree nv driver sources */
1320 pNv->PGRAPH[0x008C/4] = 0x4004FF31; /* stegerg: strange but that's so in xfree nv driver sources */
1322 pNv->PGRAPH[0x0140/4] = 0x00000000;
1323 pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF;
1324 pNv->PGRAPH[0x0170/4] = 0x10010100;
1325 pNv->PGRAPH[0x0710/4] = 0xFFFFFFFF;
1326 pNv->PGRAPH[0x0720/4] = 0x00000001;
1328 pNv->PGRAPH[0x0810/4] = 0x00000000;
1329 pNv->PGRAPH[0x0608/4] = 0xFFFFFFFF;
1330 } else {
1331 pNv->PGRAPH[0x0080/4] = 0xFFFFFFFF;
1332 pNv->PGRAPH[0x0080/4] = 0x00000000;
1334 pNv->PGRAPH[0x0140/4] = 0x00000000;
1335 pNv->PGRAPH[0x0100/4] = 0xFFFFFFFF;
1336 pNv->PGRAPH[0x0144/4] = 0x10010100;
1337 pNv->PGRAPH[0x0714/4] = 0xFFFFFFFF;
1338 pNv->PGRAPH[0x0720/4] = 0x00000001;
1339 pNv->PGRAPH[0x0710/4] &= 0x0007ff00;
1340 pNv->PGRAPH[0x0710/4] |= 0x00020100;
1342 if(pNv->Architecture == NV_ARCH_10) {
1343 pNv->PGRAPH[0x0084/4] = 0x00118700;
1344 pNv->PGRAPH[0x0088/4] = 0x24E00810;
1345 pNv->PGRAPH[0x008C/4] = 0x55DE0030;
1347 for(i = 0; i < 32; i++)
1348 pNv->PGRAPH[(0x0B00/4) + i] = pNv->PFB[(0x0240/4) + i];
1350 pNv->PGRAPH[0x640/4] = 0;
1351 pNv->PGRAPH[0x644/4] = 0;
1352 pNv->PGRAPH[0x684/4] = pNv->FrameBufferSize - 1;
1353 pNv->PGRAPH[0x688/4] = pNv->FrameBufferSize - 1;
1355 pNv->PGRAPH[0x0810/4] = 0x00000000;
1356 pNv->PGRAPH[0x0608/4] = 0xFFFFFFFF;
1357 } else {
1358 if(pNv->Architecture >= NV_ARCH_40) {
1359 pNv->PGRAPH[0x0084/4] = 0x401287c0;
1360 pNv->PGRAPH[0x008C/4] = 0x60de8051;
1361 pNv->PGRAPH[0x0090/4] = 0x00008000;
1362 pNv->PGRAPH[0x0610/4] = 0x00be3c5f;
1364 if((pNv->Chipset & 0xfff0) == 0x0040) {
1365 pNv->PGRAPH[0x09b0/4] = 0x83280fff;
1366 pNv->PGRAPH[0x09b4/4] = 0x000000a0;
1367 } else {
1368 pNv->PGRAPH[0x0820/4] = 0x83280eff;
1369 pNv->PGRAPH[0x0824/4] = 0x000000a0;
1372 switch(pNv->Chipset & 0xfff0) {
1373 case 0x0040:
1374 pNv->PGRAPH[0x09b8/4] = 0x0078e366;
1375 pNv->PGRAPH[0x09bc/4] = 0x0000014c;
1376 pNv->PFB[0x033C/4] &= 0xffff7fff;
1377 break;
1378 case 0x00C0:
1379 pNv->PGRAPH[0x0828/4] = 0x007596ff;
1380 pNv->PGRAPH[0x082C/4] = 0x00000108;
1381 break;
1382 case 0x0160:
1383 pNv->PMC[0x1700/4] = pNv->PFB[0x020C/4];
1384 pNv->PMC[0x1704/4] = 0;
1385 pNv->PMC[0x1708/4] = 0;
1386 pNv->PMC[0x170C/4] = pNv->PFB[0x020C/4];
1387 pNv->PGRAPH[0x0860/4] = 0;
1388 pNv->PGRAPH[0x0864/4] = 0;
1389 pNv->PRAMDAC[0x0608/4] |= 0x00100000;
1390 break;
1391 case 0x0140:
1392 pNv->PGRAPH[0x0828/4] = 0x0072cb77;
1393 pNv->PGRAPH[0x082C/4] = 0x00000108;
1394 break;
1395 default:
1396 break;
1399 pNv->PGRAPH[0x0b38/4] = 0x2ffff800;
1400 pNv->PGRAPH[0x0b3c/4] = 0x00006000;
1401 pNv->PGRAPH[0x032C/4] = 0x01000000;
1402 pNv->PGRAPH[0x0220/4] = 0x00001200;
1403 } else
1404 if(pNv->Architecture == NV_ARCH_30) {
1405 pNv->PGRAPH[0x0084/4] = 0x40108700;
1406 pNv->PGRAPH[0x0890/4] = 0x00140000;
1407 pNv->PGRAPH[0x008C/4] = 0xf00e0431;
1408 pNv->PGRAPH[0x0090/4] = 0x00008000;
1409 pNv->PGRAPH[0x0610/4] = 0xf04b1f36;
1410 pNv->PGRAPH[0x0B80/4] = 0x1002d888;
1411 pNv->PGRAPH[0x0B88/4] = 0x62ff007f;
1412 } else {
1413 pNv->PGRAPH[0x0084/4] = 0x00118700;
1414 pNv->PGRAPH[0x008C/4] = 0xF20E0431;
1415 pNv->PGRAPH[0x0090/4] = 0x00000000;
1416 pNv->PGRAPH[0x009C/4] = 0x00000040;
1418 if((pNv->Chipset & 0x0ff0) >= 0x0250) {
1419 pNv->PGRAPH[0x0890/4] = 0x00080000;
1420 pNv->PGRAPH[0x0610/4] = 0x304B1FB6;
1421 pNv->PGRAPH[0x0B80/4] = 0x18B82880;
1422 pNv->PGRAPH[0x0B84/4] = 0x44000000;
1423 pNv->PGRAPH[0x0098/4] = 0x40000080;
1424 pNv->PGRAPH[0x0B88/4] = 0x000000ff;
1425 } else {
1426 pNv->PGRAPH[0x0880/4] = 0x00080000;
1427 pNv->PGRAPH[0x0094/4] = 0x00000005;
1428 pNv->PGRAPH[0x0B80/4] = 0x45CAA208;
1429 pNv->PGRAPH[0x0B84/4] = 0x24000000;
1430 pNv->PGRAPH[0x0098/4] = 0x00000040;
1431 pNv->PGRAPH[0x0750/4] = 0x00E00038;
1432 pNv->PGRAPH[0x0754/4] = 0x00000030;
1433 pNv->PGRAPH[0x0750/4] = 0x00E10038;
1434 pNv->PGRAPH[0x0754/4] = 0x00000030;
1438 for(i = 0; i < 32; i++)
1439 pNv->PGRAPH[(0x0900/4) + i] = pNv->PFB[(0x0240/4) + i];
1441 if(pNv->Architecture >= NV_ARCH_40) {
1442 if((pNv->Chipset & 0xfff0) == 0x0040) {
1443 pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4];
1444 pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4];
1445 pNv->PGRAPH[0x69A4/4] = pNv->PFB[0x0200/4];
1446 pNv->PGRAPH[0x69A8/4] = pNv->PFB[0x0204/4];
1448 pNv->PGRAPH[0x0820/4] = 0;
1449 pNv->PGRAPH[0x0824/4] = 0;
1450 pNv->PGRAPH[0x0864/4] = pNv->FrameBufferSize - 1;
1451 pNv->PGRAPH[0x0868/4] = pNv->FrameBufferSize - 1;
1452 } else {
1453 pNv->PGRAPH[0x09F0/4] = pNv->PFB[0x0200/4];
1454 pNv->PGRAPH[0x09F4/4] = pNv->PFB[0x0204/4];
1455 pNv->PGRAPH[0x69F0/4] = pNv->PFB[0x0200/4];
1456 pNv->PGRAPH[0x69F4/4] = pNv->PFB[0x0204/4];
1458 pNv->PGRAPH[0x0840/4] = 0;
1459 pNv->PGRAPH[0x0844/4] = 0;
1460 pNv->PGRAPH[0x08a0/4] = pNv->FrameBufferSize - 1;
1461 pNv->PGRAPH[0x08a4/4] = pNv->FrameBufferSize - 1;
1463 } else {
1464 pNv->PGRAPH[0x09A4/4] = pNv->PFB[0x0200/4];
1465 pNv->PGRAPH[0x09A8/4] = pNv->PFB[0x0204/4];
1466 pNv->PGRAPH[0x0750/4] = 0x00EA0000;
1467 pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0200/4];
1468 pNv->PGRAPH[0x0750/4] = 0x00EA0004;
1469 pNv->PGRAPH[0x0754/4] = pNv->PFB[0x0204/4];
1471 pNv->PGRAPH[0x0820/4] = 0;
1472 pNv->PGRAPH[0x0824/4] = 0;
1473 pNv->PGRAPH[0x0864/4] = pNv->FrameBufferSize - 1;
1474 pNv->PGRAPH[0x0868/4] = pNv->FrameBufferSize - 1;
1477 pNv->PGRAPH[0x0B20/4] = 0x00000000;
1478 pNv->PGRAPH[0x0B04/4] = 0xFFFFFFFF;
1481 pNv->PGRAPH[0x053C/4] = 0;
1482 pNv->PGRAPH[0x0540/4] = 0;
1483 pNv->PGRAPH[0x0544/4] = 0x00007FFF;
1484 pNv->PGRAPH[0x0548/4] = 0x00007FFF;
1486 pNv->PFIFO[0x0140] = 0x00000000;
1487 pNv->PFIFO[0x0141] = 0x00000001;
1488 pNv->PFIFO[0x0480] = 0x00000000;
1489 pNv->PFIFO[0x0494] = 0x00000000;
1490 if(pNv->Architecture >= NV_ARCH_40)
1491 pNv->PFIFO[0x0481] = 0x00010000;
1492 else
1493 pNv->PFIFO[0x0481] = 0x00000100;
1494 pNv->PFIFO[0x0490] = 0x00000000;
1495 pNv->PFIFO[0x0491] = 0x00000000;
1496 if(pNv->Architecture >= NV_ARCH_40)
1497 pNv->PFIFO[0x048B] = 0x00001213;
1498 else
1499 pNv->PFIFO[0x048B] = 0x00001209;
1500 pNv->PFIFO[0x0400] = 0x00000000;
1501 pNv->PFIFO[0x0414] = 0x00000000;
1502 pNv->PFIFO[0x0084] = 0x03000100;
1503 pNv->PFIFO[0x0085] = 0x00000110;
1504 pNv->PFIFO[0x0086] = 0x00000112;
1505 pNv->PFIFO[0x0143] = 0x0000FFFF;
1506 pNv->PFIFO[0x0496] = 0x0000FFFF;
1507 pNv->PFIFO[0x0050] = 0x00000000;
1508 pNv->PFIFO[0x0040] = 0xFFFFFFFF;
1509 pNv->PFIFO[0x0415] = 0x00000001;
1510 pNv->PFIFO[0x048C] = 0x00000000;
1511 pNv->PFIFO[0x04A0] = 0x00000000;
1512 #if AROS_BIG_ENDIAN
1513 pNv->PFIFO[0x0489] = 0x800F0078;
1514 #else
1515 pNv->PFIFO[0x0489] = 0x000F0078;
1516 #endif
1517 pNv->PFIFO[0x0488] = 0x00000001;
1518 pNv->PFIFO[0x0480] = 0x00000001;
1519 pNv->PFIFO[0x0494] = 0x00000001;
1520 pNv->PFIFO[0x0495] = 0x00000001;
1521 pNv->PFIFO[0x0140] = 0x00000001;
1523 if(pNv->Architecture >= NV_ARCH_10) {
1524 if(pNv->twoHeads) {
1525 pNv->PCRTC0[0x0860/4] = state->head;
1526 pNv->PCRTC0[0x2860/4] = state->head2;
1528 pNv->PRAMDAC[0x0404/4] |= (1 << 25);
1530 pNv->PMC[0x8704/4] = 1;
1531 pNv->PMC[0x8140/4] = 0;
1532 pNv->PMC[0x8920/4] = 0;
1533 pNv->PMC[0x8924/4] = 0;
1534 pNv->PMC[0x8908/4] = pNv->FrameBufferSize - 1;
1535 pNv->PMC[0x890C/4] = pNv->FrameBufferSize - 1;
1536 pNv->PMC[0x1588/4] = 0;
1538 pNv->PCRTC[0x0810/4] = state->cursorConfig;
1539 pNv->PCRTC[0x0830/4] = state->displayV - 3;
1540 pNv->PCRTC[0x0834/4] = state->displayV - 1;
1542 if(pNv->FlatPanel) {
1543 if((pNv->Chipset & 0x0ff0) == 0x0110) {
1544 pNv->PRAMDAC[0x0528/4] = state->dither;
1545 } else
1546 if(pNv->twoHeads) {
1547 pNv->PRAMDAC[0x083C/4] = state->dither;
1550 VGA_WR08(pNv->PCIO, 0x03D4, 0x53);
1551 VGA_WR08(pNv->PCIO, 0x03D5, state->timingH);
1552 VGA_WR08(pNv->PCIO, 0x03D4, 0x54);
1553 VGA_WR08(pNv->PCIO, 0x03D5, state->timingV);
1554 VGA_WR08(pNv->PCIO, 0x03D4, 0x21);
1555 VGA_WR08(pNv->PCIO, 0x03D5, 0xfa);
1558 VGA_WR08(pNv->PCIO, 0x03D4, 0x41);
1559 VGA_WR08(pNv->PCIO, 0x03D5, state->extra);
1562 VGA_WR08(pNv->PCIO, 0x03D4, 0x19);
1563 VGA_WR08(pNv->PCIO, 0x03D5, state->repaint0);
1564 VGA_WR08(pNv->PCIO, 0x03D4, 0x1A);
1565 VGA_WR08(pNv->PCIO, 0x03D5, state->repaint1);
1566 VGA_WR08(pNv->PCIO, 0x03D4, 0x25);
1567 VGA_WR08(pNv->PCIO, 0x03D5, state->screen);
1568 VGA_WR08(pNv->PCIO, 0x03D4, 0x28);
1569 VGA_WR08(pNv->PCIO, 0x03D5, state->pixel);
1570 VGA_WR08(pNv->PCIO, 0x03D4, 0x2D);
1571 VGA_WR08(pNv->PCIO, 0x03D5, state->horiz);
1572 VGA_WR08(pNv->PCIO, 0x03D4, 0x1C);
1573 VGA_WR08(pNv->PCIO, 0x03D5, state->fifo);
1574 VGA_WR08(pNv->PCIO, 0x03D4, 0x1B);
1575 VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration0);
1576 VGA_WR08(pNv->PCIO, 0x03D4, 0x20);
1577 VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration1);
1578 if(pNv->Architecture >= NV_ARCH_30) {
1579 VGA_WR08(pNv->PCIO, 0x03D4, 0x47);
1580 VGA_WR08(pNv->PCIO, 0x03D5, state->arbitration1 >> 8);
1582 VGA_WR08(pNv->PCIO, 0x03D4, 0x30);
1583 VGA_WR08(pNv->PCIO, 0x03D5, state->cursor0);
1584 VGA_WR08(pNv->PCIO, 0x03D4, 0x31);
1585 VGA_WR08(pNv->PCIO, 0x03D5, state->cursor1);
1586 VGA_WR08(pNv->PCIO, 0x03D4, 0x2F);
1587 VGA_WR08(pNv->PCIO, 0x03D5, state->cursor2);
1588 VGA_WR08(pNv->PCIO, 0x03D4, 0x39);
1589 VGA_WR08(pNv->PCIO, 0x03D5, state->interlace);
1591 if(!pNv->FlatPanel) {
1592 pNv->PRAMDAC0[0x050C/4] = state->pllsel;
1593 pNv->PRAMDAC0[0x0508/4] = state->vpll;
1594 if(pNv->twoHeads)
1595 pNv->PRAMDAC0[0x0520/4] = state->vpll2;
1596 if(pNv->twoStagePLL) {
1597 pNv->PRAMDAC0[0x0578/4] = state->vpllB;
1598 pNv->PRAMDAC0[0x057C/4] = state->vpll2B;
1600 } else {
1601 pNv->PRAMDAC[0x0848/4] = state->scale;
1604 /* begin flat panel hacks */
1605 /* This is unfortunate, but some chips need this register
1606 tweaked or else you get artifacts where adjacent pixels are
1607 swapped. There are no hard rules for what to set here so all
1608 we can do is experiment and apply hacks. */
1610 if(((pNv->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
1611 /* At least one NV34 laptop needs this workaround. */
1612 pNv->PRAMDAC[0x0828/4] &= ~1;
1615 if((pNv->Chipset & 0xfff0) == 0x0310) {
1616 pNv->PRAMDAC[0x0828/4] |= 1;
1619 /* end flat panel hacks */
1621 pNv->PRAMDAC[0x0600/4] = state->general;
1623 pNv->PCRTC[0x0140/4] = 0;
1624 pNv->PCRTC[0x0100/4] = 1;
1626 pNv->CurrentState = state;
1630 ** stegerg: Status NVUnloadStateExt(): should "match" xfree nv NVUnloadStateExt()
1631 ** in xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c version:
1632 ** 1.12 2004/11/30 23:50:26 mvojkovi
1635 void NVUnloadStateExt
1637 NVPtr pNv,
1638 RIVA_HW_STATE *state
1641 VGA_WR08(pNv->PCIO, 0x03D4, 0x19);
1642 state->repaint0 = VGA_RD08(pNv->PCIO, 0x03D5);
1643 VGA_WR08(pNv->PCIO, 0x03D4, 0x1A);
1644 state->repaint1 = VGA_RD08(pNv->PCIO, 0x03D5);
1645 VGA_WR08(pNv->PCIO, 0x03D4, 0x25);
1646 state->screen = VGA_RD08(pNv->PCIO, 0x03D5);
1647 VGA_WR08(pNv->PCIO, 0x03D4, 0x28);
1648 state->pixel = VGA_RD08(pNv->PCIO, 0x03D5);
1649 VGA_WR08(pNv->PCIO, 0x03D4, 0x2D);
1650 state->horiz = VGA_RD08(pNv->PCIO, 0x03D5);
1651 VGA_WR08(pNv->PCIO, 0x03D4, 0x1C);
1652 state->fifo = VGA_RD08(pNv->PCIO, 0x03D5);
1653 VGA_WR08(pNv->PCIO, 0x03D4, 0x1B);
1654 state->arbitration0 = VGA_RD08(pNv->PCIO, 0x03D5);
1655 VGA_WR08(pNv->PCIO, 0x03D4, 0x20);
1656 state->arbitration1 = VGA_RD08(pNv->PCIO, 0x03D5);
1657 if(pNv->Architecture >= NV_ARCH_30) {
1658 VGA_WR08(pNv->PCIO, 0x03D4, 0x47);
1659 state->arbitration1 |= (VGA_RD08(pNv->PCIO, 0x03D5) & 1) << 8;
1661 VGA_WR08(pNv->PCIO, 0x03D4, 0x30);
1662 state->cursor0 = VGA_RD08(pNv->PCIO, 0x03D5);
1663 VGA_WR08(pNv->PCIO, 0x03D4, 0x31);
1664 state->cursor1 = VGA_RD08(pNv->PCIO, 0x03D5);
1665 VGA_WR08(pNv->PCIO, 0x03D4, 0x2F);
1666 state->cursor2 = VGA_RD08(pNv->PCIO, 0x03D5);
1667 VGA_WR08(pNv->PCIO, 0x03D4, 0x39);
1668 state->interlace = VGA_RD08(pNv->PCIO, 0x03D5);
1669 state->vpll = pNv->PRAMDAC0[0x0508/4];
1670 if(pNv->twoHeads)
1671 state->vpll2 = pNv->PRAMDAC0[0x0520/4];
1672 if(pNv->twoStagePLL) {
1673 state->vpllB = pNv->PRAMDAC0[0x0578/4];
1674 state->vpll2B = pNv->PRAMDAC0[0x057C/4];
1676 state->pllsel = pNv->PRAMDAC0[0x050C/4];
1677 state->general = pNv->PRAMDAC[0x0600/4];
1678 state->scale = pNv->PRAMDAC[0x0848/4];
1679 state->config = pNv->PFB[0x0200/4];
1681 if(pNv->Architecture >= NV_ARCH_10) {
1682 if(pNv->twoHeads) {
1683 state->head = pNv->PCRTC0[0x0860/4];
1684 state->head2 = pNv->PCRTC0[0x2860/4];
1685 VGA_WR08(pNv->PCIO, 0x03D4, 0x44);
1686 state->crtcOwner = VGA_RD08(pNv->PCIO, 0x03D5);
1688 VGA_WR08(pNv->PCIO, 0x03D4, 0x41);
1689 state->extra = VGA_RD08(pNv->PCIO, 0x03D5);
1690 state->cursorConfig = pNv->PCRTC[0x0810/4];
1692 if((pNv->Chipset & 0x0ff0) == 0x0110) {
1693 state->dither = pNv->PRAMDAC[0x0528/4];
1694 } else
1695 if(pNv->twoHeads) {
1696 state->dither = pNv->PRAMDAC[0x083C/4];
1699 if(pNv->FlatPanel) {
1700 VGA_WR08(pNv->PCIO, 0x03D4, 0x53);
1701 state->timingH = VGA_RD08(pNv->PCIO, 0x03D5);
1702 VGA_WR08(pNv->PCIO, 0x03D4, 0x54);
1703 state->timingV = VGA_RD08(pNv->PCIO, 0x03D5);
1708 void NVSetStartAddress (
1709 NVPtr pNv,
1710 ULONG start
1713 pNv->PCRTC[0x800/4] = start;
1716 void NVLoadDAC(
1717 NVPtr pNv
1720 int i;
1722 VGA_WR08(pNv->PDIO, 0x3c6, 0xff);
1723 VGA_WR08(pNv->PDIO, 0x3c8, 0);
1724 for (i=0; i < 768; i++)
1725 VGA_WR08(pNv->PDIO, 0x3c9, pNv->CurrentState->Regs.dac[i]);
1728 static void InitBaseRegs(struct staticdata *sd, struct CardState *card, Sync *mode)
1730 /* Determine sync polarity */
1731 if (mode->VDisplay < 400)
1732 card->Regs.misc = 0xa3;
1733 else if (mode->VDisplay < 480)
1734 card->Regs.misc = 0x63;
1735 else if (mode->VDisplay < 768)
1736 card->Regs.misc = 0xe3;
1737 else
1738 card->Regs.misc = 0x23;
1740 card->Regs.seq[0] = 0x03;
1741 card->Regs.seq[1] = 0x01;
1742 card->Regs.seq[2] = 0x0f;
1743 card->Regs.seq[3] = 0x00;
1744 card->Regs.seq[4] = 0x0e;
1746 card->Regs.crtc[8] = 0;
1747 card->Regs.crtc[10] = 0; //0x20;
1748 card->Regs.crtc[14] = 0;
1749 card->Regs.crtc[17] = (mode->VSyncEnd & 0x0f) | 0x20;
1750 card->Regs.crtc[18] = (mode->VDisplay - 1) & 0xff;
1751 card->Regs.crtc[19] = card->width >> 4;
1752 card->Regs.crtc[20] = 0;
1753 card->Regs.crtc[21] = (mode->VSyncStart - 1) & 0xff;
1754 card->Regs.crtc[22] = (mode->VSyncEnd - 1) & 0xff;
1755 card->Regs.crtc[23] = 0xc3; // 0xc3
1756 card->Regs.crtc[24] = 0xff;
1757 card->Regs.crtc[40] = 0x40;
1759 card->Regs.gra[0] = 0x00;
1760 card->Regs.gra[1] = 0x00;
1761 card->Regs.gra[2] = 0x00;
1762 card->Regs.gra[3] = 0x00;
1763 card->Regs.gra[4] = 0x00;
1764 card->Regs.gra[5] = 0x40;
1765 card->Regs.gra[6] = 0x05;
1766 card->Regs.gra[7] = 0x0f;
1767 card->Regs.gra[8] = 0xff;
1769 card->Regs.attr[0] = 0x00;
1770 card->Regs.attr[1] = 0x01;
1771 card->Regs.attr[2] = 0x02;
1772 card->Regs.attr[3] = 0x03;
1773 card->Regs.attr[4] = 0x04;
1774 card->Regs.attr[5] = 0x05;
1775 card->Regs.attr[6] = 0x06;
1776 card->Regs.attr[7] = 0x07;
1777 card->Regs.attr[8] = 0x08;
1778 card->Regs.attr[9] = 0x09;
1779 card->Regs.attr[10] = 0x0a;
1780 card->Regs.attr[11] = 0x0b;
1781 card->Regs.attr[12] = 0x0c;
1782 card->Regs.attr[13] = 0x0d;
1783 card->Regs.attr[14] = 0x0e;
1784 card->Regs.attr[15] = 0x0f;
1785 card->Regs.attr[16] = 0x41;
1786 card->Regs.attr[17] = 0x01;
1787 card->Regs.attr[18] = 0x0f;
1788 card->Regs.attr[19] = 0x00;
1789 card->Regs.attr[20] = 0x00;
1792 #define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b))
1793 #define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
1794 #define SetBF(mask,value) ((value) << (0?mask))
1795 #define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
1796 #define SetBitField(value,from,to) SetBF(to, GetBF(value,from))
1797 #define SetBit(n) (1<<(n))
1798 #define Set8Bits(value) ((value)&0xff)
1800 void InitMode(struct staticdata *sd, struct CardState *state,
1801 ULONG width, ULONG height, UBYTE bpp, ULONG pixelc, ULONG base,
1802 ULONG HDisplay, ULONG VDisplay,
1803 ULONG HSyncStart, ULONG HSyncEnd, ULONG HTotal,
1804 ULONG VSyncStart, ULONG VSyncEnd, ULONG VTotal)
1806 D(bug("[NVidia] Init %dx%dx%d @%x mode\n", width, height, bpp, base));
1808 ULONG HBlankStart, HBlankEnd, VBlankStart, VBlankEnd, OrgHDisplay = HDisplay;
1810 Sync mode = {
1811 pixelc, 0,
1812 HDisplay, HSyncStart, HSyncEnd, HTotal,
1813 VDisplay, VSyncStart, VSyncEnd, VTotal
1816 InitBaseRegs(sd, state, &mode);
1818 HDisplay = (HDisplay >> 3) - 1;
1819 HSyncStart = (HSyncStart >> 3) - 1;
1820 HSyncEnd = (HSyncEnd >> 3) - 1;
1821 HTotal = (HTotal >> 3) - 5;
1822 HBlankStart = HDisplay;
1823 HBlankEnd = HTotal + 4;
1825 VDisplay -= 1;
1826 VSyncStart -= 1;
1827 VSyncEnd -= 1;
1828 VTotal -= 2;
1829 VBlankStart = VDisplay;
1830 VBlankEnd = VTotal + 1;
1832 if (bpp <= 8)
1833 state->bitsPerPixel = 8;
1834 else if (bpp <= 16)
1835 state->bitsPerPixel = 16;
1836 else
1837 state->bitsPerPixel = 32;
1839 if (sd->Card.FlatPanel)
1841 VSyncStart = VTotal - 3;
1842 VSyncEnd = VTotal - 2;
1843 VBlankStart = VSyncStart;
1844 HSyncStart = HTotal - 5;
1845 HSyncEnd = HTotal - 2;
1846 HBlankEnd = HTotal + 4;
1849 state->Regs.crtc[0x00] = Set8Bits(HTotal);
1850 state->Regs.crtc[0x01] = Set8Bits(HDisplay);
1851 state->Regs.crtc[0x02] = Set8Bits(HBlankStart);
1852 state->Regs.crtc[0x03] = SetBitField(HBlankEnd, 4:0, 4:0) | SetBit(7);
1853 state->Regs.crtc[0x04] = Set8Bits(HSyncStart);
1854 state->Regs.crtc[0x05] = SetBitField(HBlankEnd, 5:5, 7:7) |
1855 SetBitField(HSyncEnd, 4:0, 4:0);
1856 state->Regs.crtc[0x06] = SetBitField(VTotal, 7:0, 7:0);
1857 state->Regs.crtc[0x07] = SetBitField(VTotal, 8:8, 0:0) |
1858 SetBitField(VDisplay, 8:8, 1:1) |
1859 SetBitField(VSyncStart, 8:8, 2:2) |
1860 SetBitField(VBlankStart, 8:8, 3:3) |
1861 SetBit(4) |
1862 SetBitField(VTotal, 9:9, 5:5) |
1863 SetBitField(VDisplay, 9:9, 6:6) |
1864 SetBitField(VSyncStart, 9:9, 7:7);
1865 state->Regs.crtc[0x09] = SetBitField(VBlankStart, 9:9, 5:5) | SetBit(6); // V_DOUBLESCAN?
1866 state->Regs.crtc[0x10] = Set8Bits(VSyncStart);
1867 state->Regs.crtc[0x11] = SetBitField(VSyncEnd, 3:0, 3:0) | SetBit(5);
1868 state->Regs.crtc[0x12] = Set8Bits(VDisplay);
1869 state->Regs.crtc[0x13] = ((width / 8) * (state->bitsPerPixel / 8));
1870 state->Regs.crtc[0x15] = Set8Bits(VBlankStart);
1871 state->Regs.crtc[0x16] = Set8Bits(VBlankEnd);
1873 state->Regs.attr[0x10] = 0x01;
1875 state->screen =
1876 SetBitField(HBlankEnd, 6:6, 4:4) |
1877 SetBitField(VBlankStart, 10:10, 3:3) |
1878 SetBitField(VSyncStart, 10:10, 2:2) |
1879 SetBitField(VDisplay, 10:10, 1:1) |
1880 SetBitField(VTotal, 10:10, 0:0);
1882 state->horiz =
1883 SetBitField(HTotal, 8:8, 0:0) |
1884 SetBitField(HDisplay, 8:8, 1:1) |
1885 SetBitField(HBlankStart, 8:8, 2:2) |
1886 SetBitField(HSyncStart, 8:8, 3:3);
1888 state->extra =
1889 SetBitField(VTotal, 11:11, 0:0) |
1890 SetBitField(VDisplay, 11:11, 2:2) |
1891 SetBitField(VSyncStart, 11:11, 4:4) |
1892 SetBitField(VBlankStart, 11:11, 6:6);
1894 state->interlace = 0xff;
1896 if (bpp >= 24) bpp = 32;
1898 if (sd->Card.Architecture >= NV_ARCH_10)
1899 sd->Card.CURSOR = (ULONG*)(sd->Card.FrameBuffer + sd->Card.CursorStart);
1901 // NVLockUnlock(sd, 0);
1902 NVCalcStateExt(sd, &sd->Card, state, bpp, width, OrgHDisplay, height, pixelc, 0);
1904 state->scale = sd->Card.PRAMDAC[0x0848/4] & 0xfff000ff;
1905 if (sd->Card.FlatPanel)
1907 state->pixel |= (1 << 7);
1908 if (!sd->Card.fpScaler || (sd->Card.fpWidth <= mode.HDisplay)
1909 || (sd->Card.fpHeight <= mode.VDisplay))
1911 state->scale |= (1 << 8);
1916 state->cursorConfig = 0x00000100;
1917 if (sd->Card.alphaCursor)
1919 state->cursorConfig |= 0x04011000;
1920 state->general |= (1 << 29);
1922 if((sd->Card.Chipset & 0x0ff0) == 0x0110) {
1923 state->dither = sd->Card.PRAMDAC[0x0528/4] & ~0x00010000;
1924 if(0) //sd->Card.FPDither)
1925 state->dither |= 0x00010000;
1926 else
1927 state->cursorConfig |= (1 << 28);
1928 } else
1929 if((sd->Card.Chipset & 0x0ff0) >= 0x0170) {
1930 state->dither = sd->Card.PRAMDAC[0x083C/4] & ~1;
1931 state->cursorConfig |= (1 << 28);
1932 if(0) //pNv->FPDither)
1933 state->dither |= 1;
1934 } else {
1935 state->cursorConfig |= (1 << 28);
1937 } else
1938 state->cursorConfig |= 0x02000000;
1941 // Init DAC
1942 if (bpp >1)
1944 int i;
1945 for (i=0; i <256; i++)
1947 state->Regs.dac[i*3+0] = i;
1948 state->Regs.dac[i*3+1] = i;
1949 state->Regs.dac[i*3+2] = i;
1953 state->offset = base;
1954 state->vpll = state->pll;
1955 state->vpll2 = state->pll;
1956 state->vpllB = state->pllB;
1957 state->vpll2B = state->pllB;
1959 VGA_WR08(sd->Card.PCIO, 0x03D4, 0x1C);
1960 state->fifo = VGA_RD08(sd->Card.PCIO, 0x03D5) & ~(1<<5);
1962 if(sd->Card.CRTCnumber) {
1963 state->head = sd->Card.PCRTC0[0x00000860/4] & ~0x00001000;
1964 state->head2 = sd->Card.PCRTC0[0x00002860/4] | 0x00001000;
1965 state->crtcOwner = 3;
1966 state->pllsel |= 0x20000800;
1967 state->vpll = sd->Card.PRAMDAC0[0x0508/4];
1968 if(sd->Card.twoStagePLL)
1969 state->vpllB = sd->Card.PRAMDAC0[0x0578/4];
1970 } else
1971 if(sd->Card.twoHeads) {
1972 state->head = sd->Card.PCRTC0[0x00000860/4] | 0x00001000;
1973 state->head2 = sd->Card.PCRTC0[0x00002860/4] & ~0x00001000;
1974 state->crtcOwner = 0;
1975 state->vpll2 = sd->Card.PRAMDAC0[0x0520/4];
1976 if(sd->Card.twoStagePLL)
1977 state->vpll2B = sd->Card.PRAMDAC0[0x057C/4];
1980 state->timingH = 0;
1981 state->timingV = 0;
1982 state->displayV = VDisplay;
1985 void acc_reset(struct staticdata *);
1987 void LoadState(struct staticdata *sd, struct CardState *state)
1989 int i;
1991 ObtainSemaphore(&sd->HWLock);
1993 // CRTC_out(sd, 0x11, 0x00);
1995 NVLockUnlock(sd, 0);
1996 NVLoadStateExt(&sd->Card, state);
1998 MISC_out(sd, sd->Card.CurrentState->Regs.misc);
2000 for (i=0; i < 0x05; i++)
2002 SEQ_out(sd, i, sd->Card.CurrentState->Regs.seq[i]);
2005 CRTC_out(sd, 17, sd->Card.CurrentState->Regs.crtc[17] & ~0x80);
2006 for (i=0; i < 0x41; i++)
2008 switch (i)
2010 case 0x19:
2011 case 0x20 ... 0x40:
2012 break;
2013 default:
2014 CRTC_out(sd, i, sd->Card.CurrentState->Regs.crtc[i]);
2015 break;
2019 for (i=0; i < 0x15; i++)
2020 ATTR_out(sd, i, sd->Card.CurrentState->Regs.attr[i]);
2022 for (i=0; i < 0x09; i++)
2023 GRA_out(sd, i, sd->Card.CurrentState->Regs.gra[i]);
2025 NVSetStartAddress(&sd->Card, sd->Card.CurrentState->offset);
2027 sd->Card.currentROP = 0xffffffff;
2028 // VGA_WR08(sd->Card.PVIO, 0x3c3, 1);
2030 NVLoadDAC(&sd->Card);
2031 acc_reset(sd);
2033 ReleaseSemaphore(&sd->HWLock);
2036 void DPMS(struct staticdata *sd, HIDDT_DPMSLevel state)
2038 UBYTE reg;
2040 ObtainSemaphore(&sd->HWLock);
2042 NVLockUnlock(sd,0);
2043 reg = CRTC_in(sd, 0x1a) & ~0xc0;
2045 switch(state)
2047 case vHidd_Gfx_DPMSLevel_Standby:
2048 reg |= 0x80;
2049 break;
2050 case vHidd_Gfx_DPMSLevel_Suspend:
2051 reg |= 0x40;
2052 break;
2053 case vHidd_Gfx_DPMSLevel_Off:
2054 reg |= 0xc0;
2055 break;
2056 default: // On
2057 break;
2060 CRTC_out(sd, 0x1a, reg);
2062 ReleaseSemaphore(&sd->HWLock);
2065 void Protect(struct staticdata *sd, UBYTE protect)
2067 ObtainSemaphore(&sd->HWLock);
2069 if (protect)
2071 UBYTE tmp = SEQ_in(sd, 1);
2072 SEQ_out(sd, 0, 1);
2073 SEQ_out(sd, 1, tmp | 0x20);
2075 else
2077 UBYTE tmp = SEQ_in(sd, 1);
2078 SEQ_out(sd, 1, tmp & ~0x20);
2079 SEQ_out(sd, 0, 3);
2082 ReleaseSemaphore(&sd->HWLock);
2085 static const UBYTE ROPTable[] = {
2086 [vHidd_GC_DrawMode_Clear] = 0x00,
2087 [vHidd_GC_DrawMode_And] = 0x88,
2088 [vHidd_GC_DrawMode_AndReverse] = 0x44,
2089 [vHidd_GC_DrawMode_Copy] = 0xcc,
2090 [vHidd_GC_DrawMode_AndInverted] = 0x22,
2091 [vHidd_GC_DrawMode_NoOp] = 0xaa,
2092 [vHidd_GC_DrawMode_Xor] = 0x66,
2093 [vHidd_GC_DrawMode_Or] = 0xee,
2094 [vHidd_GC_DrawMode_Nor] = 0x11,
2095 [vHidd_GC_DrawMode_Equiv] = 0x99,
2096 [vHidd_GC_DrawMode_Invert] = 0x55,
2097 [vHidd_GC_DrawMode_OrReverse] = 0xdd,
2098 [vHidd_GC_DrawMode_CopyInverted]= 0x33,
2099 [vHidd_GC_DrawMode_OrInverted] = 0xbb,
2100 [vHidd_GC_DrawMode_Nand] = 0x77,
2101 [vHidd_GC_DrawMode_Set] = 0xff,
2104 void NVDmaKickoff(struct Card *pNv)
2106 if(pNv->dmaCurrent != pNv->dmaPut) {
2107 pNv->dmaPut = pNv->dmaCurrent;
2108 WRITE_PUT(pNv, pNv->dmaPut);
2112 /* There is a HW race condition with videoram command buffers.
2113 You can't jump to the location of your put offset. We write put
2114 at the jump offset + SKIPS dwords with noop padding in between
2115 to solve this problem */
2116 #define SKIPS 8
2118 void
2119 NVDmaWait (
2120 struct Card *pNv,
2121 int size
2123 int dmaGet;
2125 size++;
2127 while(pNv->dmaFree < size) {
2128 dmaGet = READ_GET(pNv);
2130 if(pNv->dmaPut >= dmaGet) {
2131 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
2132 if(pNv->dmaFree < size) {
2133 NVDmaNext(pNv, 0x20000000);
2134 if(dmaGet <= SKIPS) {
2135 if(pNv->dmaPut <= SKIPS) /* corner case - will be idle */
2136 WRITE_PUT(pNv, SKIPS + 1);
2137 do { dmaGet = READ_GET(pNv); }
2138 while(dmaGet <= SKIPS);
2140 WRITE_PUT(pNv, SKIPS);
2141 pNv->dmaCurrent = pNv->dmaPut = SKIPS;
2142 pNv->dmaFree = dmaGet - (SKIPS + 1);
2144 } else
2145 pNv->dmaFree = dmaGet - pNv->dmaCurrent - 1;
2149 void NVSetPattern(
2150 struct staticdata *sd,
2151 ULONG clr0,
2152 ULONG clr1,
2153 ULONG pat0,
2154 ULONG pat1
2157 struct Card *pNv = &sd->Card;
2159 NVDmaStart(pNv, PATTERN_COLOR_0, 4);
2160 NVDmaNext (pNv, clr0);
2161 NVDmaNext (pNv, clr1);
2162 NVDmaNext (pNv, pat0);
2163 NVDmaNext (pNv, pat1);
2166 void NVSetRopSolid(struct staticdata *sd, ULONG rop, ULONG planemask)
2168 struct Card *pNv = &sd->Card;
2170 if(planemask != ~0) {
2171 NVSetPattern(sd, 0, planemask, ~0, ~0);
2172 if(pNv->currentROP != (rop + 32)) {
2173 NVDmaStart(pNv, ROP_SET, 1);
2174 NVDmaNext (pNv, ROPTable[rop]);
2175 pNv->currentROP = rop + 32;
2177 } else
2178 if (pNv->currentROP != rop) {
2179 if(pNv->currentROP >= 16)
2180 NVSetPattern(sd, ~0, ~0, ~0, ~0);
2181 NVDmaStart(pNv, ROP_SET, 1);
2182 NVDmaNext (pNv, ROPTable[rop]);
2183 pNv->currentROP = rop;
2187 void acc_reset(struct staticdata *sd)
2189 struct Card *pNv = &sd->Card;
2190 int pitch, i;
2192 LOCK_HW
2194 pitch = pNv->CurrentState->width *
2195 (pNv->CurrentState->bitsPerPixel >> 3);
2197 sd->src_pitch = pitch;
2198 sd->dst_pitch = pitch;
2199 sd->src_offset = pNv->CurrentState->offset;
2200 sd->dst_offset = pNv->CurrentState->offset;
2202 pNv->dmaBase = (ULONG*)(&pNv->FrameBuffer[pNv->FbUsableSize]);
2204 for(i = 0; i < SKIPS; i++)
2205 pNv->dmaBase[i] = 0x00000000;
2207 pNv->dmaBase[0x0 + SKIPS] = 0x00040000;
2208 pNv->dmaBase[0x1 + SKIPS] = 0x80000010;
2209 pNv->dmaBase[0x2 + SKIPS] = 0x00042000;
2210 pNv->dmaBase[0x3 + SKIPS] = 0x80000011;
2211 pNv->dmaBase[0x4 + SKIPS] = 0x00044000;
2212 pNv->dmaBase[0x5 + SKIPS] = 0x80000012;
2213 pNv->dmaBase[0x6 + SKIPS] = 0x00046000;
2214 pNv->dmaBase[0x7 + SKIPS] = 0x80000013;
2215 pNv->dmaBase[0x8 + SKIPS] = 0x00048000;
2216 pNv->dmaBase[0x9 + SKIPS] = 0x80000014;
2217 pNv->dmaBase[0xA + SKIPS] = 0x0004A000;
2218 pNv->dmaBase[0xB + SKIPS] = 0x80000015;
2219 pNv->dmaBase[0xC + SKIPS] = 0x0004C000;
2220 pNv->dmaBase[0xD + SKIPS] = 0x80000016;
2221 pNv->dmaBase[0xE + SKIPS] = 0x0004E000;
2222 pNv->dmaBase[0xF + SKIPS] = 0x80000017;
2224 pNv->dmaPut = 0;
2225 pNv->dmaCurrent = 16 + SKIPS;
2226 pNv->dmaMax = 8191;
2227 pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
2229 switch(pNv->CurrentState->bpp) {
2230 case 32:
2231 case 24:
2232 sd->surface_format = SURFACE_FORMAT_DEPTH24;
2233 sd->pattern_format = PATTERN_FORMAT_DEPTH24;
2234 sd->rect_format = RECT_FORMAT_DEPTH24;
2235 sd->line_format = LINE_FORMAT_DEPTH24;
2236 break;
2237 case 16:
2238 case 15:
2239 sd->surface_format = SURFACE_FORMAT_DEPTH16;
2240 sd->pattern_format = PATTERN_FORMAT_DEPTH16;
2241 sd->rect_format = RECT_FORMAT_DEPTH16;
2242 sd->line_format = LINE_FORMAT_DEPTH16;
2243 break;
2244 default:
2245 sd->surface_format = SURFACE_FORMAT_DEPTH8;
2246 sd->pattern_format = PATTERN_FORMAT_DEPTH8;
2247 sd->rect_format = RECT_FORMAT_DEPTH8;
2248 sd->line_format = LINE_FORMAT_DEPTH8;
2249 break;
2252 NVDmaStart(pNv, SURFACE_FORMAT, 4);
2253 NVDmaNext (pNv, sd->surface_format);
2254 NVDmaNext (pNv, sd->dst_pitch | (sd->src_pitch << 16));
2255 NVDmaNext (pNv, sd->src_offset);
2256 NVDmaNext (pNv, sd->dst_offset);
2258 NVDmaStart(pNv, PATTERN_FORMAT, 1);
2259 NVDmaNext (pNv, sd->pattern_format);
2261 NVDmaStart(pNv, RECT_FORMAT, 1);
2262 NVDmaNext (pNv, sd->rect_format);
2264 NVDmaStart(pNv, LINE_FORMAT, 1);
2265 NVDmaNext (pNv, sd->line_format);
2267 NVSetRopSolid(sd, vHidd_GC_DrawMode_Copy, ~0);
2269 NVDmaKickoff(pNv);
2271 UNLOCK_HW
2274 void NVSync(struct staticdata *sd)
2276 struct Card *pNv = &sd->Card;
2278 if(pNv->DMAKickoffCallback)
2279 (*pNv->DMAKickoffCallback)(sd);
2281 while(READ_GET(pNv) != pNv->dmaPut);
2283 while(pNv->PGRAPH[0x0700/4]);
2285 sd->gpu_busy = FALSE;
2288 void NVDMAKickoffCallback(struct staticdata *sd)
2290 struct Card *pNv = &sd->Card;
2292 NVDmaKickoff(pNv);
2293 pNv->DMAKickoffCallback = NULL;
2296 void NVSelectHead(struct staticdata *sd, UBYTE head)
2298 if (head)
2300 sd->Card.PCIO = sd->Card.PCIO0 + 0x2000;
2301 sd->Card.PCRTC = sd->Card.PCRTC0 + 0x800;
2302 sd->Card.PRAMDAC = sd->Card.PRAMDAC0 + 0x800;
2303 sd->Card.PDIO = sd->Card.PDIO0 + 0x2000;
2305 else
2307 sd->Card.PCIO = sd->Card.PCIO0;
2308 sd->Card.PCRTC = sd->Card.PCRTC0;
2309 sd->Card.PRAMDAC = sd->Card.PRAMDAC0;
2310 sd->Card.PDIO = sd->Card.PDIO0;
2314 BOOL NVIsConnected (struct staticdata *sd, UBYTE output)
2316 NVPtr pNv = &sd->Card;
2317 volatile ULONG *PRAMDAC = pNv->PRAMDAC0;
2318 ULONG reg52C, reg608;
2319 BOOL present;
2320 int i;
2322 if(output) PRAMDAC += 0x800;
2324 reg52C = PRAMDAC[0x052C/4];
2325 reg608 = PRAMDAC[0x0608/4];
2327 PRAMDAC[0x0608/4] = reg608 & ~0x00010000;
2329 PRAMDAC[0x052C/4] = reg52C & 0x0000FEEE;
2331 //usleep(1000);
2332 for (i=0; i < 800000000; i++)
2336 PRAMDAC[0x052C/4] |= 1;
2338 pNv->PRAMDAC0[0x0610/4] = 0x94050140;
2339 pNv->PRAMDAC0[0x0608/4] |= 0x00001000;
2341 //usleep(1000);
2342 for (i=0; i < 800000000; i++)
2346 present = (PRAMDAC[0x0608/4] & (1 << 28)) ? TRUE : FALSE;
2348 pNv->PRAMDAC0[0x0608/4] &= 0x0000EFFF;
2350 PRAMDAC[0x052C/4] = reg52C;
2351 PRAMDAC[0x0608/4] = reg608;
2353 return present;