Some fixes to nv30_exa. Now goes through a couple of composite() calls without crashing.
[nouveau] / src / nv_hw.c
1 /***************************************************************************\
2 |*                                                                           *|
3 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
4 |*                                                                           *|
5 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
6 |*     international laws.  Users and possessors of this source code are     *|
7 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
8 |*     use this code in individual and commercial software.                  *|
9 |*                                                                           *|
10 |*     Any use of this source code must include,  in the user documenta-     *|
11 |*     tion and  internal comments to the code,  notices to the end user     *|
12 |*     as follows:                                                           *|
13 |*                                                                           *|
14 |*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
15 |*                                                                           *|
16 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
17 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
18 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
19 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
20 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
21 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
22 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
23 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
24 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
25 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
26 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
27 |*                                                                           *|
28 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
29 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
30 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
31 |*     computer  software  documentation,"  as such  terms  are  used in     *|
32 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
33 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
34 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
35 |*     all U.S. Government End Users  acquire the source code  with only     *|
36 |*     those rights set forth herein.                                        *|
37 |*                                                                           *|
38  \***************************************************************************/
39 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.21 2006/06/16 00:19:33 mvojkovi Exp $ */
40
41 #include "nv_include.h"
42 #include "nv_local.h"
43 #include "compiler.h"
44
45 uint8_t NVReadVGA0(NVPtr pNv, uint8_t index)
46 {
47         volatile const uint8_t *ptr = pNv->PCIO0;
48         VGA_WR08(ptr, 0x03D4, index);
49         return VGA_RD08(ptr, 0x03D5);
50 }
51
52 void NVWriteVGA0(NVPtr pNv, uint8_t index, uint8_t data)
53 {
54         volatile const uint8_t *ptr = pNv->PCIO0;
55         VGA_WR08(ptr, 0x03D4, index);
56         VGA_WR08(ptr, 0x03D5, data);
57 }
58
59 uint8_t nvReadVGA(NVPtr pNv, uint8_t index)
60 {
61   volatile const uint8_t *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
62   VGA_WR08(ptr, 0x03D4, index);
63   return VGA_RD08(ptr, 0x03D5);
64 }
65
66 void nvWriteVGA(NVPtr pNv, uint8_t index, uint8_t data)
67 {
68   volatile const uint8_t *ptr = pNv->cur_head ? pNv->PCIO1 : pNv->PCIO0;
69   VGA_WR08(ptr, 0x03D4, index);
70   VGA_WR08(ptr, 0x03D5, data);
71 }
72
73 CARD32 nvReadRAMDAC(NVPtr pNv, uint8_t head, uint32_t ramdac_reg)
74 {
75   volatile const void *ptr = head ? pNv->PRAMDAC1 : pNv->PRAMDAC0;
76   return MMIO_IN32(ptr, ramdac_reg);
77 }
78
79 void nvWriteRAMDAC(NVPtr pNv, uint8_t head, uint32_t ramdac_reg, CARD32 val)
80 {
81   volatile const void *ptr = head ? pNv->PRAMDAC1 : pNv->PRAMDAC0;
82   MMIO_OUT32(ptr, ramdac_reg, val);
83 }
84
85 CARD32 nvReadCRTC(NVPtr pNv, uint8_t head, uint32_t reg)
86 {
87   volatile const void *ptr = head ? pNv->PCRTC1 : pNv->PCRTC0;
88   return MMIO_IN32(ptr, reg);
89 }
90
91 void nvWriteCRTC(NVPtr pNv, uint8_t head, uint32_t reg, CARD32 val)
92 {
93   volatile const void *ptr = head ? pNv->PCRTC1 : pNv->PCRTC0;
94   MMIO_OUT32(ptr, reg, val);
95 }
96
97 void NVLockUnlock (
98     NVPtr pNv,
99     Bool  Lock
100 )
101 {
102     CARD8 cr11;
103
104     nvWriteVGA(pNv, NV_VGA_CRTCX_LOCK, Lock ? 0x99 : 0x57 );
105
106     cr11 = nvReadVGA(pNv, NV_VGA_CRTCX_VSYNCE);
107     if(Lock) cr11 |= 0x80;
108     else cr11 &= ~0x80;
109     nvWriteVGA(pNv, NV_VGA_CRTCX_VSYNCE, cr11);
110 }
111
112 int NVShowHideCursor (
113     NVPtr pNv,
114     int   ShowHide
115 )
116 {
117     int current = pNv->CurrentState->cursor1;
118
119     pNv->CurrentState->cursor1 = (pNv->CurrentState->cursor1 & 0xFE) |
120                                  (ShowHide & 0x01);
121
122     nvWriteVGA(pNv, NV_VGA_CRTCX_CURCTL1, pNv->CurrentState->cursor1);
123
124     if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
125        volatile CARD32 curpos = nvReadCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS);
126        nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, curpos);
127     }
128
129     return (current & 0x01);
130 }
131
132 /****************************************************************************\
133 *                                                                            *
134 * The video arbitration routines calculate some "magic" numbers.  Fixes      *
135 * the snow seen when accessing the framebuffer without it.                   *
136 * It just works (I hope).                                                    *
137 *                                                                            *
138 \****************************************************************************/
139
140 typedef struct {
141   int graphics_lwm;
142   int video_lwm;
143   int graphics_burst_size;
144   int video_burst_size;
145   int valid;
146 } nv4_fifo_info;
147
148 typedef struct {
149   int pclk_khz;
150   int mclk_khz;
151   int nvclk_khz;
152   char mem_page_miss;
153   char mem_latency;
154   int memory_width;
155   char enable_video;
156   char gr_during_vid;
157   char pix_bpp;
158   char mem_aligned;
159   char enable_mp;
160 } nv4_sim_state;
161
162 typedef struct {
163   int graphics_lwm;
164   int video_lwm;
165   int graphics_burst_size;
166   int video_burst_size;
167   int valid;
168 } nv10_fifo_info;
169
170 typedef struct {
171   int pclk_khz;
172   int mclk_khz;
173   int nvclk_khz;
174   char mem_page_miss;
175   char mem_latency;
176   int memory_type;
177   int memory_width;
178   char enable_video;
179   char gr_during_vid;
180   char pix_bpp;
181   char mem_aligned;
182   char enable_mp;
183 } nv10_sim_state;
184
185
186 static void nvGetClocks(NVPtr pNv, unsigned int *MClk, unsigned int *NVClk)
187 {
188     unsigned int pll, N, M, MB, NB, P;
189
190     if(pNv->Architecture >= NV_ARCH_40) {
191        pll = nvReadMC(pNv, 0x4020);
192        P = (pll >> 16) & 0x07;
193        pll = nvReadMC(pNv, 0x4024);
194        M = pll & 0xFF;
195        N = (pll >> 8) & 0xFF;
196        if(((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
197           ((pNv->Chipset & 0xfff0) == CHIPSET_G73))
198        {
199           MB = 1;
200           NB = 1;
201        } else {
202           MB = (pll >> 16) & 0xFF;
203           NB = (pll >> 24) & 0xFF;
204        }
205        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
206
207        pll = nvReadMC(pNv, 0x4000);
208        P = (pll >> 16) & 0x07;  
209        pll = nvReadMC(pNv, 0x4004);
210        M = pll & 0xFF;
211        N = (pll >> 8) & 0xFF;
212        MB = (pll >> 16) & 0xFF;
213        NB = (pll >> 24) & 0xFF;
214
215        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
216     } else
217     if(pNv->twoStagePLL) {
218        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL);
219        M = pll & 0xFF;
220        N = (pll >> 8) & 0xFF; 
221        P = (pll >> 16) & 0x0F;
222        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL_B);
223        if(pll & 0x80000000) {
224            MB = pll & 0xFF; 
225            NB = (pll >> 8) & 0xFF;
226        } else {
227            MB = 1;
228            NB = 1;
229        }
230        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
231
232        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
233        M = pll & 0xFF; 
234        N = (pll >> 8) & 0xFF; 
235        P = (pll >> 16) & 0x0F;
236        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL_B);
237        if(pll & 0x80000000) {
238            MB = pll & 0xFF;
239            NB = (pll >> 8) & 0xFF;
240        } else {
241            MB = 1;
242            NB = 1;
243        }
244        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
245     } else 
246     if(((pNv->Chipset & 0x0ff0) == CHIPSET_NV30) ||
247        ((pNv->Chipset & 0x0ff0) == CHIPSET_NV35))
248     {
249        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL);
250        M = pll & 0x0F; 
251        N = (pll >> 8) & 0xFF;
252        P = (pll >> 16) & 0x07;
253        if(pll & 0x00000080) {
254            MB = (pll >> 4) & 0x07;     
255            NB = (pll >> 19) & 0x1f;
256        } else {
257            MB = 1;
258            NB = 1;
259        }
260        *MClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
261
262        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
263        M = pll & 0x0F;
264        N = (pll >> 8) & 0xFF;
265        P = (pll >> 16) & 0x07;
266        if(pll & 0x00000080) {
267            MB = (pll >> 4) & 0x07;
268            NB = (pll >> 19) & 0x1f;
269        } else {
270            MB = 1;
271            NB = 1;
272        }
273        *NVClk = ((N * NB * pNv->CrystalFreqKHz) / (M * MB)) >> P;
274     } else {
275        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_MPLL);
276        M = pll & 0xFF; 
277        N = (pll >> 8) & 0xFF; 
278        P = (pll >> 16) & 0x0F;
279        *MClk = (N * pNv->CrystalFreqKHz / M) >> P;
280
281        pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
282        M = pll & 0xFF; 
283        N = (pll >> 8) & 0xFF; 
284        P = (pll >> 16) & 0x0F;
285        *NVClk = (N * pNv->CrystalFreqKHz / M) >> P;
286     }
287
288 #if 0
289     ErrorF("NVClock = %i MHz, MEMClock = %i MHz\n", *NVClk/1000, *MClk/1000);
290 #endif
291 }
292
293
294 void nv4CalcArbitration (
295     nv4_fifo_info *fifo,
296     nv4_sim_state *arb
297 )
298 {
299     int data, pagemiss, cas,width, video_enable, bpp;
300     int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
301     int found, mclk_extra, mclk_loop, cbs, m1, p1;
302     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
303     int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
304     int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
305
306     fifo->valid = 1;
307     pclk_freq = arb->pclk_khz;
308     mclk_freq = arb->mclk_khz;
309     nvclk_freq = arb->nvclk_khz;
310     pagemiss = arb->mem_page_miss;
311     cas = arb->mem_latency;
312     width = arb->memory_width >> 6;
313     video_enable = arb->enable_video;
314     bpp = arb->pix_bpp;
315     mp_enable = arb->enable_mp;
316     clwm = 0;
317     vlwm = 0;
318     cbs = 128;
319     pclks = 2;
320     nvclks = 2;
321     nvclks += 2;
322     nvclks += 1;
323     mclks = 5;
324     mclks += 3;
325     mclks += 1;
326     mclks += cas;
327     mclks += 1;
328     mclks += 1;
329     mclks += 1;
330     mclks += 1;
331     mclk_extra = 3;
332     nvclks += 2;
333     nvclks += 1;
334     nvclks += 1;
335     nvclks += 1;
336     if (mp_enable)
337         mclks+=4;
338     nvclks += 0;
339     pclks += 0;
340     found = 0;
341     vbs = 0;
342     while (found != 1)
343     {
344         fifo->valid = 1;
345         found = 1;
346         mclk_loop = mclks+mclk_extra;
347         us_m = mclk_loop *1000*1000 / mclk_freq;
348         us_n = nvclks*1000*1000 / nvclk_freq;
349         us_p = nvclks*1000*1000 / pclk_freq;
350         if (video_enable)
351         {
352             video_drain_rate = pclk_freq * 2;
353             crtc_drain_rate = pclk_freq * bpp/8;
354             vpagemiss = 2;
355             vpagemiss += 1;
356             crtpagemiss = 2;
357             vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
358             if (nvclk_freq * 2 > mclk_freq * width)
359                 video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
360             else
361                 video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
362             us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
363             vlwm = us_video * video_drain_rate/(1000*1000);
364             vlwm++;
365             vbs = 128;
366             if (vlwm > 128) vbs = 64;
367             if (vlwm > (256-64)) vbs = 32;
368             if (nvclk_freq * 2 > mclk_freq * width)
369                 video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
370             else
371                 video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
372             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
373             us_crt =
374             us_video
375             +video_fill_us
376             +cpm_us
377             +us_m + us_n +us_p
378             ;
379             clwm = us_crt * crtc_drain_rate/(1000*1000);
380             clwm++;
381         }
382         else
383         {
384             crtc_drain_rate = pclk_freq * bpp/8;
385             crtpagemiss = 2;
386             crtpagemiss += 1;
387             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
388             us_crt =  cpm_us + us_m + us_n + us_p ;
389             clwm = us_crt * crtc_drain_rate/(1000*1000);
390             clwm++;
391         }
392         m1 = clwm + cbs - 512;
393         p1 = m1 * pclk_freq / mclk_freq;
394         p1 = p1 * bpp / 8;
395         if ((p1 < m1) && (m1 > 0))
396         {
397             fifo->valid = 0;
398             found = 0;
399             if (mclk_extra ==0)   found = 1;
400             mclk_extra--;
401         }
402         else if (video_enable)
403         {
404             if ((clwm > 511) || (vlwm > 255))
405             {
406                 fifo->valid = 0;
407                 found = 0;
408                 if (mclk_extra ==0)   found = 1;
409                 mclk_extra--;
410             }
411         }
412         else
413         {
414             if (clwm > 519)
415             {
416                 fifo->valid = 0;
417                 found = 0;
418                 if (mclk_extra ==0)   found = 1;
419                 mclk_extra--;
420             }
421         }
422         if (clwm < 384) clwm = 384;
423         if (vlwm < 128) vlwm = 128;
424         data = (int)(clwm);
425         fifo->graphics_lwm = data;
426         fifo->graphics_burst_size = 128;
427         data = (int)((vlwm+15));
428         fifo->video_lwm = data;
429         fifo->video_burst_size = vbs;
430     }
431 }
432
433 void nv4UpdateArbitrationSettings (
434     unsigned      VClk, 
435     unsigned      pixelDepth, 
436     unsigned     *burst,
437     unsigned     *lwm,
438     NVPtr        pNv
439 )
440 {
441     nv4_fifo_info fifo_data;
442     nv4_sim_state sim_data;
443     unsigned int MClk, NVClk, cfg1;
444
445     nvGetClocks(pNv, &MClk, &NVClk);
446
447     cfg1 = nvReadFB(pNv, NV_PFB_CFG1);
448     sim_data.pix_bpp        = (char)pixelDepth;
449     sim_data.enable_video   = 0;
450     sim_data.enable_mp      = 0;
451     sim_data.memory_width   = (nvReadEXTDEV(pNv, 0x0000) & 0x10) ? 128 : 64;
452     sim_data.mem_latency    = (char)cfg1 & 0x0F;
453     sim_data.mem_aligned    = 1;
454     sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
455     sim_data.gr_during_vid  = 0;
456     sim_data.pclk_khz       = VClk;
457     sim_data.mclk_khz       = MClk;
458     sim_data.nvclk_khz      = NVClk;
459     nv4CalcArbitration(&fifo_data, &sim_data);
460     if (fifo_data.valid)
461     {
462         int  b = fifo_data.graphics_burst_size >> 4;
463         *burst = 0;
464         while (b >>= 1) (*burst)++;
465         *lwm   = fifo_data.graphics_lwm >> 3;
466     }
467 }
468
469 void nv10CalcArbitration (
470     nv10_fifo_info *fifo,
471     nv10_sim_state *arb
472 )
473 {
474     int data, pagemiss, width, video_enable, bpp;
475     int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
476     int nvclk_fill;
477     int found, mclk_extra, mclk_loop, cbs, m1;
478     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
479     int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
480     int vus_m;
481     int vpm_us, us_video, cpm_us, us_crt,clwm;
482     int clwm_rnd_down;
483     int m2us, us_pipe_min, p1clk, p2;
484     int min_mclk_extra;
485     int us_min_mclk_extra;
486
487     fifo->valid = 1;
488     pclk_freq = arb->pclk_khz; /* freq in KHz */
489     mclk_freq = arb->mclk_khz;
490     nvclk_freq = arb->nvclk_khz;
491     pagemiss = arb->mem_page_miss;
492     width = arb->memory_width/64;
493     video_enable = arb->enable_video;
494     bpp = arb->pix_bpp;
495     mp_enable = arb->enable_mp;
496     clwm = 0;
497
498     cbs = 512;
499
500     pclks = 4; /* lwm detect. */
501
502     nvclks = 3; /* lwm -> sync. */
503     nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
504
505     mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
506
507     mclks += 1;   /* arb_hp_req */
508     mclks += 5;   /* ap_hp_req   tiling pipeline */
509
510     mclks += 2;    /* tc_req     latency fifo */
511     mclks += 2;    /* fb_cas_n_  memory request to fbio block */
512     mclks += 7;    /* sm_d_rdv   data returned from fbio block */
513
514     /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
515     if (arb->memory_type == 0)
516       if (arb->memory_width == 64) /* 64 bit bus */
517         mclks += 4;
518       else
519         mclks += 2;
520     else
521       if (arb->memory_width == 64) /* 64 bit bus */
522         mclks += 2;
523       else
524         mclks += 1;
525
526     if ((!video_enable) && (arb->memory_width == 128))
527     {  
528       mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
529       min_mclk_extra = 17;
530     }
531     else
532     {
533       mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
534       /* mclk_extra = 4; */ /* Margin of error */
535       min_mclk_extra = 18;
536     }
537
538     nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
539     nvclks += 1; /* fbi_d_rdv_n */
540     nvclks += 1; /* Fbi_d_rdata */
541     nvclks += 1; /* crtfifo load */
542
543     if(mp_enable)
544       mclks+=4; /* Mp can get in with a burst of 8. */
545     /* Extra clocks determined by heuristics */
546
547     nvclks += 0;
548     pclks += 0;
549     found = 0;
550     while(found != 1) {
551       fifo->valid = 1;
552       found = 1;
553       mclk_loop = mclks+mclk_extra;
554       us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
555       us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
556       us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
557       us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
558       us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
559       us_pipe_min = us_m_min + us_n + us_p;
560
561       vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
562
563       if(video_enable) {
564         crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
565
566         vpagemiss = 1; /* self generating page miss */
567         vpagemiss += 1; /* One higher priority before */
568
569         crtpagemiss = 2; /* self generating page miss */
570         if(mp_enable)
571             crtpagemiss += 1; /* if MA0 conflict */
572
573         vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
574
575         us_video = vpm_us + vus_m; /* Video has separate read return path */
576
577         cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
578         us_crt =
579           us_video  /* Wait for video */
580           +cpm_us /* CRT Page miss */
581           +us_m + us_n +us_p /* other latency */
582           ;
583
584         clwm = us_crt * crtc_drain_rate/(1000*1000);
585         clwm++; /* fixed point <= float_point - 1.  Fixes that */
586       } else {
587         crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
588
589         crtpagemiss = 1; /* self generating page miss */
590         crtpagemiss += 1; /* MA0 page miss */
591         if(mp_enable)
592             crtpagemiss += 1; /* if MA0 conflict */
593         cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
594         us_crt =  cpm_us + us_m + us_n + us_p ;
595         clwm = us_crt * crtc_drain_rate/(1000*1000);
596         clwm++; /* fixed point <= float_point - 1.  Fixes that */
597
598           /* Finally, a heuristic check when width == 64 bits */
599           if(width == 1){
600               nvclk_fill = nvclk_freq * 8;
601               if(crtc_drain_rate * 100 >= nvclk_fill * 102)
602                       clwm = 0xfff; /*Large number to fail */
603
604               else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
605                   clwm = 1024;
606                   cbs = 512;
607               }
608           }
609       }
610
611
612       /*
613         Overfill check:
614
615         */
616
617       clwm_rnd_down = ((int)clwm/8)*8;
618       if (clwm_rnd_down < clwm)
619           clwm += 8;
620
621       m1 = clwm + cbs -  1024; /* Amount of overfill */
622       m2us = us_pipe_min + us_min_mclk_extra;
623
624       /* pclk cycles to drain */
625       p1clk = m2us * pclk_freq/(1000*1000); 
626       p2 = p1clk * bpp / 8; /* bytes drained. */
627
628       if((p2 < m1) && (m1 > 0)) {
629           fifo->valid = 0;
630           found = 0;
631           if(min_mclk_extra == 0)   {
632             if(cbs <= 32) {
633               found = 1; /* Can't adjust anymore! */
634             } else {
635               cbs = cbs/2;  /* reduce the burst size */
636             }
637           } else {
638             min_mclk_extra--;
639           }
640       } else {
641         if (clwm > 1023){ /* Have some margin */
642           fifo->valid = 0;
643           found = 0;
644           if(min_mclk_extra == 0)   
645               found = 1; /* Can't adjust anymore! */
646           else 
647               min_mclk_extra--;
648         }
649       }
650
651       if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
652       data = (int)(clwm);
653       /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
654       fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
655
656       fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
657     }
658 }
659
660 void nv10UpdateArbitrationSettings (
661     unsigned      VClk, 
662     unsigned      pixelDepth, 
663     unsigned     *burst,
664     unsigned     *lwm,
665     NVPtr        pNv
666 )
667 {
668     nv10_fifo_info fifo_data;
669     nv10_sim_state sim_data;
670     unsigned int MClk, NVClk, cfg1;
671
672     nvGetClocks(pNv, &MClk, &NVClk);
673
674     cfg1 = nvReadFB(pNv, NV_PFB_CFG1);
675     sim_data.pix_bpp        = (char)pixelDepth;
676     sim_data.enable_video   = 1;
677     sim_data.enable_mp      = 0;
678     sim_data.memory_type    = (nvReadFB(pNv, NV_PFB_CFG0) & 0x01) ? 1 : 0;
679     sim_data.memory_width   = (nvReadEXTDEV(pNv, 0x0000) & 0x10) ? 128 : 64;
680     sim_data.mem_latency    = (char)cfg1 & 0x0F;
681     sim_data.mem_aligned    = 1;
682     sim_data.mem_page_miss  = (char)(((cfg1>>4) &0x0F) + ((cfg1>>31) & 0x01));
683     sim_data.gr_during_vid  = 0;
684     sim_data.pclk_khz       = VClk;
685     sim_data.mclk_khz       = MClk;
686     sim_data.nvclk_khz      = NVClk;
687     nv10CalcArbitration(&fifo_data, &sim_data);
688     if (fifo_data.valid) {
689         int  b = fifo_data.graphics_burst_size >> 4;
690         *burst = 0;
691         while (b >>= 1) (*burst)++;
692         *lwm   = fifo_data.graphics_lwm >> 3;
693     }
694 }
695
696
697 void nv30UpdateArbitrationSettings (NVPtr pNv,
698                                     unsigned     *burst,
699                                     unsigned     *lwm)   
700 {
701     unsigned int MClk, NVClk;
702     unsigned int fifo_size, burst_size, graphics_lwm;
703
704     fifo_size = 2048;
705     burst_size = 512;
706     graphics_lwm = fifo_size - burst_size;
707
708     nvGetClocks(pNv, &MClk, &NVClk);
709     
710     *burst = 0;
711     burst_size >>= 5;
712     while(burst_size >>= 1) (*burst)++;
713     *lwm = graphics_lwm >> 3;
714 }
715
716 #ifdef XSERVER_LIBPCIACCESS
717
718 struct pci_device GetDeviceByPCITAG(uint32_t bus, uint32_t dev, uint32_t func)
719 {
720         const struct pci_slot_match match[] = { {0, bus, dev, func, 0} };
721         struct pci_device_iterator *iterator = pci_slot_match_iterator_create(&match);
722         /* assume one device to exist */
723         struct pci_device *device = pci_device_next(iterator);
724
725         return *device;
726 }
727
728 #endif /* XSERVER_LIBPCIACCESS */
729
730 void nForceUpdateArbitrationSettings (unsigned VClk,
731                                       unsigned      pixelDepth,
732                                       unsigned     *burst,
733                                       unsigned     *lwm,
734                                       NVPtr        pNv
735 )
736 {
737     nv10_fifo_info fifo_data;
738     nv10_sim_state sim_data;
739     unsigned int M, N, P, pll, MClk, NVClk, memctrl;
740
741 #ifdef XSERVER_LIBPCIACCESS
742         struct pci_device tmp;
743 #endif /* XSERVER_LIBPCIACCESS */
744
745     if((pNv->Chipset & 0x0FF0) == CHIPSET_NFORCE) {
746        unsigned int uMClkPostDiv;
747
748 #ifdef XSERVER_LIBPCIACCESS
749         tmp = GetDeviceByPCITAG(0, 0, 3);
750         PCI_DEV_READ_LONG(&tmp, 0x6C, &uMClkPostDiv);
751         uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
752 #else
753         uMClkPostDiv = (pciReadLong(pciTag(0, 0, 3), 0x6C) >> 8) & 0xf;
754 #endif /* XSERVER_LIBPCIACCESS */
755        if(!uMClkPostDiv) uMClkPostDiv = 4; 
756        MClk = 400000 / uMClkPostDiv;
757     } else {
758 #ifdef XSERVER_LIBPCIACCESS
759         tmp = GetDeviceByPCITAG(0, 0, 5);
760         PCI_DEV_READ_LONG(&tmp, 0x4C, &MClk);
761         MClk /= 1000;
762 #else
763         MClk = pciReadLong(pciTag(0, 0, 5), 0x4C) / 1000;
764 #endif /* XSERVER_LIBPCIACCESS */
765     }
766
767     pll = nvReadRAMDAC0(pNv, NV_RAMDAC_NVPLL);
768     M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
769     NVClk  = (N * pNv->CrystalFreqKHz / M) >> P;
770     sim_data.pix_bpp        = (char)pixelDepth;
771     sim_data.enable_video   = 0;
772     sim_data.enable_mp      = 0;
773 #ifdef XSERVER_LIBPCIACCESS
774         tmp = GetDeviceByPCITAG(0, 0, 1);
775         PCI_DEV_READ_LONG(&tmp, 0x7C, &(sim_data.memory_type));
776         sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
777 #else
778         sim_data.memory_type = (pciReadLong(pciTag(0, 0, 1), 0x7C) >> 12) & 1;
779 #endif /* XSERVER_LIBPCIACCESS */
780     sim_data.memory_width   = 64;
781
782 #ifdef XSERVER_LIBPCIACCESS
783         /* This offset is 0, is this even usefull? */
784         tmp = GetDeviceByPCITAG(0, 0, 3);
785         PCI_DEV_READ_LONG(&tmp, 0x00, &memctrl);
786         memctrl >>= 16;
787 #else
788         memctrl = pciReadLong(pciTag(0, 0, 3), 0x00) >> 16;
789 #endif /* XSERVER_LIBPCIACCESS */
790
791     if((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
792         int dimm[3];
793 #ifdef XSERVER_LIBPCIACCESS
794         tmp = GetDeviceByPCITAG(0, 0, 2);
795         PCI_DEV_READ_LONG(&tmp, 0x40, &dimm[0]);
796         PCI_DEV_READ_LONG(&tmp, 0x44, &dimm[1]);
797         PCI_DEV_READ_LONG(&tmp, 0x48, &dimm[2]);
798         int i;
799         for (i = 0; i < 3; i++) {
800                 dimm[i] = (dimm[i] >> 8) & 0x4F;
801         }
802 #else
803         dimm[0] = (pciReadLong(pciTag(0, 0, 2), 0x40) >> 8) & 0x4F;
804         dimm[1] = (pciReadLong(pciTag(0, 0, 2), 0x44) >> 8) & 0x4F;
805         dimm[2] = (pciReadLong(pciTag(0, 0, 2), 0x48) >> 8) & 0x4F;
806 #endif
807
808         if((dimm[0] + dimm[1]) != dimm[2]) {
809              ErrorF("WARNING: "
810               "your nForce DIMMs are not arranged in optimal banks!\n");
811         } 
812     }
813
814     sim_data.mem_latency    = 3;
815     sim_data.mem_aligned    = 1;
816     sim_data.mem_page_miss  = 10;
817     sim_data.gr_during_vid  = 0;
818     sim_data.pclk_khz       = VClk;
819     sim_data.mclk_khz       = MClk;
820     sim_data.nvclk_khz      = NVClk;
821     nv10CalcArbitration(&fifo_data, &sim_data);
822     if (fifo_data.valid)
823     {
824         int  b = fifo_data.graphics_burst_size >> 4;
825         *burst = 0;
826         while (b >>= 1) (*burst)++;
827         *lwm   = fifo_data.graphics_lwm >> 3;
828     }
829 }
830
831
832 /****************************************************************************\
833 *                                                                            *
834 *                          RIVA Mode State Routines                          *
835 *                                                                            *
836 \****************************************************************************/
837
838 /*
839  * Calculate the Video Clock parameters for the PLL.
840  */
841 static void CalcVClock (
842     int           clockIn,
843     int          *clockOut,
844     CARD32         *pllOut,
845     NVPtr        pNv
846 )
847 {
848     unsigned lowM, highM;
849     unsigned DeltaNew, DeltaOld;
850     unsigned VClk, Freq;
851     unsigned M, N, P;
852     
853     DeltaOld = 0xFFFFFFFF;
854
855     VClk = (unsigned)clockIn;
856     
857     if (pNv->CrystalFreqKHz == 13500) {
858         lowM  = 7;
859         highM = 13;
860     } else {
861         lowM  = 8;
862         highM = 14;
863     }
864
865     for (P = 0; P <= 4; P++) {
866         Freq = VClk << P;
867         if ((Freq >= 128000) && (Freq <= 350000)) {
868             for (M = lowM; M <= highM; M++) {
869                 N = ((VClk << P) * M) / pNv->CrystalFreqKHz;
870                 if(N <= 255) {
871                     Freq = ((pNv->CrystalFreqKHz * N) / M) >> P;
872                     if (Freq > VClk)
873                         DeltaNew = Freq - VClk;
874                     else
875                         DeltaNew = VClk - Freq;
876                     if (DeltaNew < DeltaOld) {
877                         *pllOut   = (P << 16) | (N << 8) | M;
878                         *clockOut = Freq;
879                         DeltaOld  = DeltaNew;
880                     }
881                 }
882             }
883         }
884     }
885 }
886
887 static void CalcVClock2Stage (
888     int           clockIn,
889     int          *clockOut,
890     CARD32         *pllOut,
891     CARD32         *pllBOut,
892     NVPtr        pNv
893 )
894 {
895     unsigned DeltaNew, DeltaOld;
896     unsigned VClk, Freq;
897     unsigned M, N, P;
898
899     DeltaOld = 0xFFFFFFFF;
900
901     *pllBOut = 0x80000401;  /* fixed at x4 for now */
902
903     VClk = (unsigned)clockIn;
904
905     for (P = 0; P <= 6; P++) {
906         Freq = VClk << P;
907         if ((Freq >= 400000) && (Freq <= 1000000)) {
908             for (M = 1; M <= 13; M++) {
909                 N = ((VClk << P) * M) / (pNv->CrystalFreqKHz << 2);
910                 if((N >= 5) && (N <= 255)) {
911                     Freq = (((pNv->CrystalFreqKHz << 2) * N) / M) >> P;
912                     if (Freq > VClk)
913                         DeltaNew = Freq - VClk;
914                     else
915                         DeltaNew = VClk - Freq;
916                     if (DeltaNew < DeltaOld) {
917                         *pllOut   = (P << 16) | (N << 8) | M;
918                         *clockOut = Freq;
919                         DeltaOld  = DeltaNew;
920                     }
921                 }
922             }
923         }
924     }
925 }
926
927 /*
928  * Calculate extended mode parameters (SVGA) and save in a 
929  * mode state structure.
930  */
931 void NVCalcStateExt (
932     NVPtr pNv,
933     RIVA_HW_STATE *state,
934     int            bpp,
935     int            width,
936     int            hDisplaySize,
937     int            height,
938     int            dotClock,
939     int            flags 
940 )
941 {
942     int pixelDepth, VClk;
943         CARD32 CursorStart;
944
945     /*
946      * Save mode parameters.
947      */
948     state->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
949     state->width  = width;
950     state->height = height;
951     /*
952      * Extended RIVA registers.
953      */
954     pixelDepth = (bpp + 1)/8;
955     if(pNv->twoStagePLL)
956         CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB, pNv);
957     else
958         CalcVClock(dotClock, &VClk, &state->pll, pNv);
959
960     switch (pNv->Architecture)
961     {
962         case NV_ARCH_04:
963             nv4UpdateArbitrationSettings(VClk, 
964                                          pixelDepth * 8, 
965                                         &(state->arbitration0),
966                                         &(state->arbitration1),
967                                          pNv);
968             state->cursor0  = 0x00;
969             state->cursor1  = 0xbC;
970             if (flags & V_DBLSCAN)
971                 state->cursor1 |= 2;
972             state->cursor2  = 0x00000000;
973             state->pllsel   = 0x10000700;
974             state->config   = 0x00001114;
975             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
976             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
977             break;
978         case NV_ARCH_10:
979         case NV_ARCH_20:
980         case NV_ARCH_30:
981         default:
982             if(((pNv->Chipset & 0xfff0) == CHIPSET_C51) ||
983                ((pNv->Chipset & 0xfff0) == CHIPSET_C512))
984             {
985                 state->arbitration0 = 128; 
986                 state->arbitration1 = 0x0480; 
987             } else
988             if(((pNv->Chipset & 0xffff) == CHIPSET_NFORCE) ||
989                ((pNv->Chipset & 0xffff) == CHIPSET_NFORCE2))
990             {
991                 nForceUpdateArbitrationSettings(VClk,
992                                           pixelDepth * 8,
993                                          &(state->arbitration0),
994                                          &(state->arbitration1),
995                                           pNv);
996             } else if(pNv->Architecture < NV_ARCH_30) {
997                 nv10UpdateArbitrationSettings(VClk, 
998                                           pixelDepth * 8, 
999                                          &(state->arbitration0),
1000                                          &(state->arbitration1),
1001                                           pNv);
1002             } else {
1003                 nv30UpdateArbitrationSettings(pNv,
1004                                          &(state->arbitration0),
1005                                          &(state->arbitration1));
1006             }
1007             CursorStart = pNv->Cursor->offset;
1008             state->cursor0  = 0x80 | (CursorStart >> 17);
1009             state->cursor1  = (CursorStart >> 11) << 2;
1010             state->cursor2  = CursorStart >> 24;
1011             if (flags & V_DBLSCAN) 
1012                 state->cursor1 |= 2;
1013             state->pllsel   = 0x10000700;
1014             state->config   = nvReadFB(pNv, NV_PFB_CFG0);
1015             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
1016             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1017             break;
1018     }
1019
1020     if(bpp != 8) /* DirectColor */
1021         state->general |= 0x00000030;
1022
1023     state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
1024     state->pixel    = (pixelDepth > 2) ? 3 : pixelDepth;
1025 }
1026
1027
1028 void NVLoadStateExt (
1029     ScrnInfoPtr pScrn,
1030     RIVA_HW_STATE *state
1031 )
1032 {
1033     NVPtr pNv = NVPTR(pScrn);
1034     CARD32 temp;
1035
1036     if(pNv->Architecture >= NV_ARCH_40) {
1037         switch(pNv->Chipset & 0xfff0) {
1038         case CHIPSET_NV44:
1039         case CHIPSET_NV44A:
1040         case CHIPSET_C51:
1041         case CHIPSET_G70:
1042         case CHIPSET_G71:
1043         case CHIPSET_G72:
1044         case CHIPSET_G73:
1045         case CHIPSET_C512:
1046              temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL);
1047              nvWriteCurRAMDAC(pNv, NV_RAMDAC_TEST_CONTROL, temp | 0x00100000);
1048              break;
1049         default:
1050              break;
1051         };
1052     }
1053
1054     if(pNv->Architecture >= NV_ARCH_10) {
1055         if(pNv->twoHeads) {
1056            nvWriteCRTC(pNv, 0, NV_CRTC_FSEL, state->head);
1057            nvWriteCRTC(pNv, 1, NV_CRTC_FSEL, state->head2);
1058         }
1059         temp = nvReadCurRAMDAC(pNv, NV_RAMDAC_NV10_CURSYNC);
1060         nvWriteCurRAMDAC(pNv, NV_RAMDAC_NV10_CURSYNC, temp | (1 << 25));
1061     
1062         nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
1063         nvWriteVIDEO(pNv, NV_PVIDEO_INTR_EN, 0);
1064         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(0), 0);
1065         nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(1), 0);
1066         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(0), pNv->VRAMPhysicalSize - 1);
1067         nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(1), pNv->VRAMPhysicalSize - 1);
1068         nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(0), pNv->VRAMPhysicalSize - 1);
1069         nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(1), pNv->VRAMPhysicalSize - 1);
1070         nvWriteMC(pNv, 0x1588, 0);
1071
1072         nvWriteCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG, state->cursorConfig);
1073         nvWriteCurCRTC(pNv, NV_CRTC_0830, state->displayV - 3);
1074         nvWriteCurCRTC(pNv, NV_CRTC_0834, state->displayV - 1);
1075     
1076         if(pNv->FlatPanel) {
1077            if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
1078                nvWriteCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11, state->dither);
1079            } else 
1080            if(pNv->twoHeads) {
1081                nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER, state->dither);
1082            }
1083     
1084            nvWriteVGA(pNv, NV_VGA_CRTCX_FP_HTIMING, state->timingH);
1085            nvWriteVGA(pNv, NV_VGA_CRTCX_FP_VTIMING, state->timingV);
1086            nvWriteVGA(pNv, NV_VGA_CRTCX_BUFFER, 0xfa);
1087         }
1088
1089         nvWriteVGA(pNv, NV_VGA_CRTCX_EXTRA, state->extra);
1090     }
1091
1092     nvWriteVGA(pNv, NV_VGA_CRTCX_REPAINT0, state->repaint0);
1093     nvWriteVGA(pNv, NV_VGA_CRTCX_REPAINT1, state->repaint1);
1094     nvWriteVGA(pNv, NV_VGA_CRTCX_LSR, state->screen);
1095     nvWriteVGA(pNv, NV_VGA_CRTCX_PIXEL, state->pixel);
1096     nvWriteVGA(pNv, NV_VGA_CRTCX_HEB, state->horiz);
1097     nvWriteVGA(pNv, NV_VGA_CRTCX_FIFO1, state->fifo);
1098     nvWriteVGA(pNv, NV_VGA_CRTCX_FIFO0, state->arbitration0);
1099     nvWriteVGA(pNv, NV_VGA_CRTCX_FIFO_LWM, state->arbitration1);
1100     if(pNv->Architecture >= NV_ARCH_30) {
1101       nvWriteVGA(pNv, NV_VGA_CRTCX_FIFO_LWM_NV30, state->arbitration1 >> 8);
1102     }
1103
1104     nvWriteVGA(pNv, NV_VGA_CRTCX_CURCTL0, state->cursor0);
1105     nvWriteVGA(pNv, NV_VGA_CRTCX_CURCTL1, state->cursor1);
1106     if(pNv->Architecture == NV_ARCH_40) {  /* HW bug */
1107        volatile CARD32 curpos = nvReadCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS);
1108        nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, curpos);
1109     }
1110     nvWriteVGA(pNv, NV_VGA_CRTCX_CURCTL2, state->cursor2);
1111     nvWriteVGA(pNv, NV_VGA_CRTCX_INTERLACE, state->interlace);
1112
1113     if(!pNv->FlatPanel) {
1114        nvWriteRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT, state->pllsel);
1115        nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL, state->vpll);
1116        if(pNv->twoHeads)
1117           nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2, state->vpll2);
1118        if(pNv->twoStagePLL) {
1119           nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL_B, state->vpllB);
1120           nvWriteRAMDAC0(pNv, NV_RAMDAC_VPLL2_B, state->vpll2B);
1121        }
1122     } else {
1123        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL, state->scale);
1124        nvWriteCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC, state->crtcSync);
1125     }
1126     nvWriteCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL, state->general);
1127
1128     nvWriteCurCRTC(pNv, NV_CRTC_INTR_EN_0, 0);
1129     nvWriteCurCRTC(pNv, NV_CRTC_INTR_0, NV_CRTC_INTR_VBLANK);
1130
1131     pNv->CurrentState = state;
1132 }
1133
1134 void NVUnloadStateExt
1135 (
1136     NVPtr pNv,
1137     RIVA_HW_STATE *state
1138 )
1139 {
1140     state->repaint0     = nvReadVGA(pNv, NV_VGA_CRTCX_REPAINT0);
1141     state->repaint1     = nvReadVGA(pNv, NV_VGA_CRTCX_REPAINT1);
1142     state->screen       = nvReadVGA(pNv, NV_VGA_CRTCX_LSR);
1143     state->pixel        = nvReadVGA(pNv, NV_VGA_CRTCX_PIXEL);
1144     state->horiz        = nvReadVGA(pNv, NV_VGA_CRTCX_HEB);
1145     state->fifo         = nvReadVGA(pNv, NV_VGA_CRTCX_FIFO1);
1146     state->arbitration0 = nvReadVGA(pNv, NV_VGA_CRTCX_FIFO0);
1147     state->arbitration1 = nvReadVGA(pNv, NV_VGA_CRTCX_FIFO_LWM);
1148     if(pNv->Architecture >= NV_ARCH_30) {
1149        state->arbitration1 |= (nvReadVGA(pNv, NV_VGA_CRTCX_FIFO_LWM_NV30) & 1) << 8;
1150     }
1151     state->cursor0      = nvReadVGA(pNv, NV_VGA_CRTCX_CURCTL0);
1152     state->cursor1      = nvReadVGA(pNv, NV_VGA_CRTCX_CURCTL1);
1153     state->cursor2      = nvReadVGA(pNv, NV_VGA_CRTCX_CURCTL2);
1154     state->interlace    = nvReadVGA(pNv, NV_VGA_CRTCX_INTERLACE);
1155
1156     state->vpll         = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL);
1157     if(pNv->twoHeads)
1158        state->vpll2     = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2);
1159     if(pNv->twoStagePLL) {
1160         state->vpllB    = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL_B);
1161         state->vpll2B   = nvReadRAMDAC0(pNv, NV_RAMDAC_VPLL2_B);
1162     }
1163     state->pllsel       = nvReadRAMDAC0(pNv, NV_RAMDAC_PLL_SELECT);
1164     state->general      = nvReadCurRAMDAC(pNv, NV_RAMDAC_GENERAL_CONTROL);
1165     state->scale        = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_CONTROL);
1166     state->config       = nvReadFB(pNv, NV_PFB_CFG0);
1167
1168     if(pNv->Architecture >= NV_ARCH_10) {
1169         if(pNv->twoHeads) {
1170            state->head     = nvReadCRTC(pNv, 0, NV_CRTC_FSEL);
1171            state->head2    = nvReadCRTC(pNv, 1, NV_CRTC_FSEL);
1172            state->crtcOwner = nvReadVGA(pNv, NV_VGA_CRTCX_OWNER);
1173         }
1174         state->extra = nvReadVGA(pNv, NV_VGA_CRTCX_EXTRA);
1175
1176         state->cursorConfig = nvReadCurCRTC(pNv, NV_CRTC_CURSOR_CONFIG);
1177
1178         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
1179            state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_DITHER_NV11);
1180         } else 
1181         if(pNv->twoHeads) {
1182             state->dither = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_DITHER);
1183         }
1184
1185         if(pNv->FlatPanel) {
1186            state->timingH = nvReadVGA(pNv, NV_VGA_CRTCX_FP_HTIMING);
1187            state->timingV = nvReadVGA(pNv, NV_VGA_CRTCX_FP_VTIMING);
1188         }
1189     }
1190
1191     if(pNv->FlatPanel) {
1192        state->crtcSync = nvReadCurRAMDAC(pNv, NV_RAMDAC_FP_HCRTC);
1193     }
1194 }
1195
1196 void NVSetStartAddress (
1197     NVPtr   pNv,
1198     CARD32 start
1199 )
1200 {
1201     nvWriteCurCRTC(pNv, NV_CRTC_START, start);
1202 }
1203
1204