File: /usr/src/linux/drivers/video/riva/riva_hw.c

1      /***************************************************************************\
2     |*                                                                           *|
3     |*       Copyright 1993-1999 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-1999 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     
40     /*
41      * GPL licensing note -- nVidia is allowing a liberal interpretation of
42      * the documentation restriction above, to merely say that this nVidia's
43      * copyright and disclaimer should be included with all code derived
44      * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99 
45      */
46     
47     /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.8 2000/02/08 17:19:11 dawes Exp $ */
48     
49     #include "riva_hw.h"
50     #include "riva_tbl.h"
51     /*
52      * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT
53      * operate identically (except TNT has more memory and better 3D quality.
54      */
55     static int nv3Busy
56     (
57         RIVA_HW_INST *chip
58     )
59     {
60         return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x000006B0/4] & 0x01));
61     }
62     static int nv4Busy
63     (
64         RIVA_HW_INST *chip
65     )
66     {
67         return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01));
68     }
69     static int nv10Busy
70     (
71         RIVA_HW_INST *chip
72     )
73     {
74         return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01));
75     }
76     static void nv3LockUnlock
77     (
78         RIVA_HW_INST *chip,
79         int           LockUnlock
80     )
81     {
82         VGA_WR08(chip->PVIO, 0x3C4, 0x06);
83         VGA_WR08(chip->PVIO, 0x3C5, LockUnlock ? 0x99 : 0x57);
84     }
85     static void nv4LockUnlock
86     (
87         RIVA_HW_INST *chip,
88         int           LockUnlock
89     )
90     {
91         VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
92         VGA_WR08(chip->PCIO, 0x3D5, LockUnlock ? 0x99 : 0x57);
93     }
94     static void nv10LockUnlock
95     (
96         RIVA_HW_INST *chip,
97         int           LockUnlock
98     )
99     {
100         VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
101         VGA_WR08(chip->PCIO, 0x3D5, LockUnlock ? 0x99 : 0x57);
102     }
103     
104     static int ShowHideCursor
105     (
106         RIVA_HW_INST *chip,
107         int           ShowHide
108     )
109     {
110         int current;
111         current                     =  chip->CurrentState->cursor1;
112         chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) |
113     	                          (ShowHide & 0x01);
114         VGA_WR08(chip->PCIO, 0x3D4, 0x31);
115         VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1);
116         return (current & 0x01);
117     }
118     
119     /****************************************************************************\
120     *                                                                            *
121     * The video arbitration routines calculate some "magic" numbers.  Fixes      *
122     * the snow seen when accessing the framebuffer without it.                   *
123     * It just works (I hope).                                                    *
124     *                                                                            *
125     \****************************************************************************/
126     
127     #define DEFAULT_GR_LWM 100
128     #define DEFAULT_VID_LWM 100
129     #define DEFAULT_GR_BURST_SIZE 256
130     #define DEFAULT_VID_BURST_SIZE 128
131     #define VIDEO		0
132     #define GRAPHICS	1
133     #define MPORT		2
134     #define ENGINE		3
135     #define GFIFO_SIZE	320
136     #define GFIFO_SIZE_128	256
137     #define MFIFO_SIZE	120
138     #define VFIFO_SIZE	256
139     #define	ABS(a)	(a>0?a:-a)
140     typedef struct {
141       int gdrain_rate;
142       int vdrain_rate;
143       int mdrain_rate;
144       int gburst_size;
145       int vburst_size;
146       char vid_en;
147       char gr_en;
148       int wcmocc, wcgocc, wcvocc, wcvlwm, wcglwm;
149       int by_gfacc;
150       char vid_only_once;
151       char gr_only_once;
152       char first_vacc;
153       char first_gacc;
154       char first_macc;
155       int vocc;
156       int gocc;
157       int mocc;
158       char cur;
159       char engine_en;
160       char converged;
161       int priority;
162     } nv3_arb_info;
163     typedef struct {
164       int graphics_lwm;
165       int video_lwm;
166       int graphics_burst_size;
167       int video_burst_size;
168       int graphics_hi_priority;
169       int media_hi_priority;
170       int rtl_values;
171       int valid;
172     } nv3_fifo_info;
173     typedef struct {
174       char pix_bpp;
175       char enable_video;
176       char gr_during_vid;
177       char enable_mp;
178       int memory_width;
179       int video_scale;
180       int pclk_khz;
181       int mclk_khz;
182       int mem_page_miss;
183       int mem_latency;
184       char mem_aligned;
185     } nv3_sim_state;
186     typedef struct {
187       int graphics_lwm;
188       int video_lwm;
189       int graphics_burst_size;
190       int video_burst_size;
191       int valid;
192     } nv4_fifo_info;
193     typedef struct {
194       int pclk_khz;
195       int mclk_khz;
196       int nvclk_khz;
197       char mem_page_miss;
198       char mem_latency;
199       int memory_width;
200       char enable_video;
201       char gr_during_vid;
202       char pix_bpp;
203       char mem_aligned;
204       char enable_mp;
205     } nv4_sim_state;
206     typedef struct {
207       int graphics_lwm;
208       int video_lwm;
209       int graphics_burst_size;
210       int video_burst_size;
211       int valid;
212     } nv10_fifo_info;
213     typedef struct {
214       int pclk_khz;
215       int mclk_khz;
216       int nvclk_khz;
217       char mem_page_miss;
218       char mem_latency;
219       int memory_type;
220       int memory_width;
221       char enable_video;
222       char gr_during_vid;
223       char pix_bpp;
224       char mem_aligned;
225       char enable_mp;
226     } nv10_sim_state;
227     static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
228     {
229         int iter = 0;
230         int tmp;
231         int vfsize, mfsize, gfsize;
232         int mburst_size = 32;
233         int mmisses, gmisses, vmisses;
234         int misses;
235         int vlwm, glwm, mlwm;
236         int last, next, cur;
237         int max_gfsize ;
238         long ns;
239     
240         vlwm = 0;
241         glwm = 0;
242         mlwm = 0;
243         vfsize = 0;
244         gfsize = 0;
245         cur = ainfo->cur;
246         mmisses = 2;
247         gmisses = 2;
248         vmisses = 2;
249         if (ainfo->gburst_size == 128) max_gfsize = GFIFO_SIZE_128;
250         else  max_gfsize = GFIFO_SIZE;
251         max_gfsize = GFIFO_SIZE;
252         while (1)
253         {
254             if (ainfo->vid_en)
255             {
256                 if (ainfo->wcvocc > ainfo->vocc) ainfo->wcvocc = ainfo->vocc;
257                 if (ainfo->wcvlwm > vlwm) ainfo->wcvlwm = vlwm ;
258                 ns = 1000000 * ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
259                 vfsize = ns * ainfo->vdrain_rate / 1000000;
260                 vfsize =  ainfo->wcvlwm - ainfo->vburst_size + vfsize;
261             }
262             if (state->enable_mp)
263             {
264                 if (ainfo->wcmocc > ainfo->mocc) ainfo->wcmocc = ainfo->mocc;
265             }
266             if (ainfo->gr_en)
267             {
268                 if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ;
269                 if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc;
270                 ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
271                 gfsize = (ns * (long) ainfo->gdrain_rate)/1000000;
272                 gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize;
273             }
274             mfsize = 0;
275             if (!state->gr_during_vid && ainfo->vid_en)
276                 if (ainfo->vid_en && (ainfo->vocc < 0) && !ainfo->vid_only_once)
277                     next = VIDEO;
278                 else if (ainfo->mocc < 0)
279                     next = MPORT;
280                 else if (ainfo->gocc< ainfo->by_gfacc)
281                     next = GRAPHICS;
282                 else return (0);
283             else switch (ainfo->priority)
284                 {
285                     case VIDEO:
286                         if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
287                             next = VIDEO;
288                         else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
289                             next = GRAPHICS;
290                         else if (ainfo->mocc<0)
291                             next = MPORT;
292                         else    return (0);
293                         break;
294                     case GRAPHICS:
295                         if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
296                             next = GRAPHICS;
297                         else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
298                             next = VIDEO;
299                         else if (ainfo->mocc<0)
300                             next = MPORT;
301                         else    return (0);
302                         break;
303                     default:
304                         if (ainfo->mocc<0)
305                             next = MPORT;
306                         else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
307                             next = GRAPHICS;
308                         else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
309                             next = VIDEO;
310                         else    return (0);
311                         break;
312                 }
313             last = cur;
314             cur = next;
315             iter++;
316             switch (cur)
317             {
318                 case VIDEO:
319                     if (last==cur)    misses = 0;
320                     else if (ainfo->first_vacc)   misses = vmisses;
321                     else    misses = 1;
322                     ainfo->first_vacc = 0;
323                     if (last!=cur)
324                     {
325                         ns =  1000000 * (vmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz; 
326                         vlwm = ns * ainfo->vdrain_rate/ 1000000;
327                         vlwm = ainfo->vocc - vlwm;
328                     }
329                     ns = 1000000*(misses*state->mem_page_miss + ainfo->vburst_size)/(state->memory_width/8)/state->mclk_khz;
330                     ainfo->vocc = ainfo->vocc + ainfo->vburst_size - ns*ainfo->vdrain_rate/1000000;
331                     ainfo->gocc = ainfo->gocc - ns*ainfo->gdrain_rate/1000000;
332                     ainfo->mocc = ainfo->mocc - ns*ainfo->mdrain_rate/1000000;
333                     break;
334                 case GRAPHICS:
335                     if (last==cur)    misses = 0;
336                     else if (ainfo->first_gacc)   misses = gmisses;
337                     else    misses = 1;
338                     ainfo->first_gacc = 0;
339                     if (last!=cur)
340                     {
341                         ns = 1000000*(gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz ;
342                         glwm = ns * ainfo->gdrain_rate/1000000;
343                         glwm = ainfo->gocc - glwm;
344                     }
345                     ns = 1000000*(misses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
346                     ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
347                     ainfo->gocc = ainfo->gocc + ainfo->gburst_size - ns*ainfo->gdrain_rate/1000000;
348                     ainfo->mocc = ainfo->mocc + 0 - ns*ainfo->mdrain_rate/1000000;
349                     break;
350                 default:
351                     if (last==cur)    misses = 0;
352                     else if (ainfo->first_macc)   misses = mmisses;
353                     else    misses = 1;
354                     ainfo->first_macc = 0;
355                     ns = 1000000*(misses*state->mem_page_miss + mburst_size/(state->memory_width/8))/state->mclk_khz;
356                     ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
357                     ainfo->gocc = ainfo->gocc + 0 - ns*ainfo->gdrain_rate/1000000;
358                     ainfo->mocc = ainfo->mocc + mburst_size - ns*ainfo->mdrain_rate/1000000;
359                     break;
360             }
361             if (iter>100)
362             {
363                 ainfo->converged = 0;
364                 return (1);
365             }
366             ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz;
367             tmp = ns * ainfo->gdrain_rate/1000000;
368             if (ABS(ainfo->gburst_size) + ((ABS(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize)
369             {
370                 ainfo->converged = 0;
371                 return (1);
372             }
373             ns = 1000000*ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
374             tmp = ns * ainfo->vdrain_rate/1000000;
375             if (ABS(ainfo->vburst_size) + (ABS(ainfo->wcvlwm + 32) & ~0xf)  - tmp> VFIFO_SIZE)
376             {
377                 ainfo->converged = 0;
378                 return (1);
379             }
380             if (ABS(ainfo->gocc) > max_gfsize)
381             {
382                 ainfo->converged = 0;
383                 return (1);
384             }
385             if (ABS(ainfo->vocc) > VFIFO_SIZE)
386             {
387                 ainfo->converged = 0;
388                 return (1);
389             }
390             if (ABS(ainfo->mocc) > MFIFO_SIZE)
391             {
392                 ainfo->converged = 0;
393                 return (1);
394             }
395             if (ABS(vfsize) > VFIFO_SIZE)
396             {
397                 ainfo->converged = 0;
398                 return (1);
399             }
400             if (ABS(gfsize) > max_gfsize)
401             {
402                 ainfo->converged = 0;
403                 return (1);
404             }
405             if (ABS(mfsize) > MFIFO_SIZE)
406             {
407                 ainfo->converged = 0;
408                 return (1);
409             }
410         }
411     }
412     static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state,  nv3_arb_info *ainfo) 
413     {
414         long ens, vns, mns, gns;
415         int mmisses, gmisses, vmisses, eburst_size, mburst_size;
416         int refresh_cycle;
417     
418         refresh_cycle = 0;
419         refresh_cycle = 2*(state->mclk_khz/state->pclk_khz) + 5;
420         mmisses = 2;
421         if (state->mem_aligned) gmisses = 2;
422         else    gmisses = 3;
423         vmisses = 2;
424         eburst_size = state->memory_width * 1;
425         mburst_size = 32;
426         gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz;
427         ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000;
428         ainfo->wcmocc = 0;
429         ainfo->wcgocc = 0;
430         ainfo->wcvocc = 0;
431         ainfo->wcvlwm = 0;
432         ainfo->wcglwm = 0;
433         ainfo->engine_en = 1;
434         ainfo->converged = 1;
435         if (ainfo->engine_en)
436         {
437             ens =  1000000*(state->mem_page_miss + eburst_size/(state->memory_width/8) +refresh_cycle)/state->mclk_khz;
438             ainfo->mocc = state->enable_mp ? 0-ens*ainfo->mdrain_rate/1000000 : 0;
439             ainfo->vocc = ainfo->vid_en ? 0-ens*ainfo->vdrain_rate/1000000 : 0;
440             ainfo->gocc = ainfo->gr_en ? 0-ens*ainfo->gdrain_rate/1000000 : 0;
441             ainfo->cur = ENGINE;
442             ainfo->first_vacc = 1;
443             ainfo->first_gacc = 1;
444             ainfo->first_macc = 1;
445             nv3_iterate(res_info, state,ainfo);
446         }
447         if (state->enable_mp)
448         {
449             mns = 1000000 * (mmisses*state->mem_page_miss + mburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
450             ainfo->mocc = state->enable_mp ? 0 : mburst_size - mns*ainfo->mdrain_rate/1000000;
451             ainfo->vocc = ainfo->vid_en ? 0 : 0- mns*ainfo->vdrain_rate/1000000;
452             ainfo->gocc = ainfo->gr_en ? 0: 0- mns*ainfo->gdrain_rate/1000000;
453             ainfo->cur = MPORT;
454             ainfo->first_vacc = 1;
455             ainfo->first_gacc = 1;
456             ainfo->first_macc = 0;
457             nv3_iterate(res_info, state,ainfo);
458         }
459         if (ainfo->gr_en)
460         {
461             ainfo->first_vacc = 1;
462             ainfo->first_gacc = 0;
463             ainfo->first_macc = 1;
464             gns = 1000000*(gmisses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
465             ainfo->gocc = ainfo->gburst_size - gns*ainfo->gdrain_rate/1000000;
466             ainfo->vocc = ainfo->vid_en? 0-gns*ainfo->vdrain_rate/1000000 : 0;
467             ainfo->mocc = state->enable_mp ?  0-gns*ainfo->mdrain_rate/1000000: 0;
468             ainfo->cur = GRAPHICS;
469             nv3_iterate(res_info, state,ainfo);
470         }
471         if (ainfo->vid_en)
472         {
473             ainfo->first_vacc = 0;
474             ainfo->first_gacc = 1;
475             ainfo->first_macc = 1;
476             vns = 1000000*(vmisses*state->mem_page_miss + ainfo->vburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
477             ainfo->vocc = ainfo->vburst_size - vns*ainfo->vdrain_rate/1000000;
478             ainfo->gocc = ainfo->gr_en? (0-vns*ainfo->gdrain_rate/1000000) : 0;
479             ainfo->mocc = state->enable_mp? 0-vns*ainfo->mdrain_rate/1000000 :0 ;
480             ainfo->cur = VIDEO;
481             nv3_iterate(res_info, state, ainfo);
482         }
483         if (ainfo->converged)
484         {
485             res_info->graphics_lwm = (int)ABS(ainfo->wcglwm) + 16;
486             res_info->video_lwm = (int)ABS(ainfo->wcvlwm) + 32;
487             res_info->graphics_burst_size = ainfo->gburst_size;
488             res_info->video_burst_size = ainfo->vburst_size;
489             res_info->graphics_hi_priority = (ainfo->priority == GRAPHICS);
490             res_info->media_hi_priority = (ainfo->priority == MPORT);
491             if (res_info->video_lwm > 160)
492             {
493                 res_info->graphics_lwm = 256;
494                 res_info->video_lwm = 128;
495                 res_info->graphics_burst_size = 64;
496                 res_info->video_burst_size = 64;
497                 res_info->graphics_hi_priority = 0;
498                 res_info->media_hi_priority = 0;
499                 ainfo->converged = 0;
500                 return (0);
501             }
502             if (res_info->video_lwm > 128)
503             {
504                 res_info->video_lwm = 128;
505             }
506             return (1);
507         }
508         else
509         {
510             res_info->graphics_lwm = 256;
511             res_info->video_lwm = 128;
512             res_info->graphics_burst_size = 64;
513             res_info->video_burst_size = 64;
514             res_info->graphics_hi_priority = 0;
515             res_info->media_hi_priority = 0;
516             return (0);
517         }
518     }
519     static char nv3_get_param(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
520     {
521         int done, g,v, p;
522         
523         done = 0;
524         for (p=0; p < 2; p++)
525         {
526             for (g=128 ; g > 32; g= g>> 1)
527             {
528                 for (v=128; v >=32; v = v>> 1)
529                 {
530                     ainfo->priority = p;
531                     ainfo->gburst_size = g;     
532                     ainfo->vburst_size = v;
533                     done = nv3_arb(res_info, state,ainfo);
534                     if (done && (g==128))
535                         if ((res_info->graphics_lwm + g) > 256)
536                             done = 0;
537                     if (done)
538                         goto Done;
539                 }
540             }
541         }
542     
543      Done:
544         return done;
545     }
546     static void nv3CalcArbitration 
547     (
548         nv3_fifo_info * res_info,
549         nv3_sim_state * state
550     )
551     {
552         nv3_fifo_info save_info;
553         nv3_arb_info ainfo;
554         char   res_gr, res_vid;
555     
556         ainfo.gr_en = 1;
557         ainfo.vid_en = state->enable_video;
558         ainfo.vid_only_once = 0;
559         ainfo.gr_only_once = 0;
560         ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
561         ainfo.vdrain_rate = (int) state->pclk_khz * 2;
562         if (state->video_scale != 0)
563             ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale;
564         ainfo.mdrain_rate = 33000;
565         res_info->rtl_values = 0;
566         if (!state->gr_during_vid && state->enable_video)
567         {
568             ainfo.gr_only_once = 1;
569             ainfo.gr_en = 1;
570             ainfo.gdrain_rate = 0;
571             res_vid = nv3_get_param(res_info, state,  &ainfo);
572             res_vid = ainfo.converged;
573             save_info.video_lwm = res_info->video_lwm;
574             save_info.video_burst_size = res_info->video_burst_size;
575             ainfo.vid_en = 1;
576             ainfo.vid_only_once = 1;
577             ainfo.gr_en = 1;
578             ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
579             ainfo.vdrain_rate = 0;
580             res_gr = nv3_get_param(res_info, state,  &ainfo);
581             res_gr = ainfo.converged;
582             res_info->video_lwm = save_info.video_lwm;
583             res_info->video_burst_size = save_info.video_burst_size;
584             res_info->valid = res_gr & res_vid;
585         }
586         else
587         {
588             if (!ainfo.gr_en) ainfo.gdrain_rate = 0;
589             if (!ainfo.vid_en) ainfo.vdrain_rate = 0;
590             res_gr = nv3_get_param(res_info, state,  &ainfo);
591             res_info->valid = ainfo.converged;
592         }
593     }
594     static void nv3UpdateArbitrationSettings
595     (
596         unsigned      VClk, 
597         unsigned      pixelDepth, 
598         unsigned     *burst,
599         unsigned     *lwm,
600         RIVA_HW_INST *chip
601     )
602     {
603         nv3_fifo_info fifo_data;
604         nv3_sim_state sim_data;
605         unsigned int M, N, P, pll, MClk;
606         
607         pll = chip->PRAMDAC[0x00000504/4];
608         M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
609         MClk = (N * chip->CrystalFreqKHz / M) >> P;
610         sim_data.pix_bpp        = (char)pixelDepth;
611         sim_data.enable_video   = 0;
612         sim_data.enable_mp      = 0;
613         sim_data.video_scale    = 1;
614         sim_data.memory_width   = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64;
615         sim_data.memory_width   = 128;
616     
617         sim_data.mem_latency    = 9;
618         sim_data.mem_aligned    = 1;
619         sim_data.mem_page_miss  = 11;
620         sim_data.gr_during_vid  = 0;
621         sim_data.pclk_khz       = VClk;
622         sim_data.mclk_khz       = MClk;
623         nv3CalcArbitration(&fifo_data, &sim_data);
624         if (fifo_data.valid)
625         {
626             int  b = fifo_data.graphics_burst_size >> 4;
627             *burst = 0;
628             while (b >>= 1) (*burst)++;
629             *lwm   = fifo_data.graphics_lwm >> 3;
630         }
631         else
632         {
633             *lwm   = 0x24;
634             *burst = 0x2;
635         }
636     }
637     static void nv4CalcArbitration 
638     (
639         nv4_fifo_info *fifo,
640         nv4_sim_state *arb
641     )
642     {
643         int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
644         int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
645         int found, mclk_extra, mclk_loop, cbs, m1, p1;
646         int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
647         int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
648         int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt,clwm;
649         int craw, vraw;
650     
651         fifo->valid = 1;
652         pclk_freq = arb->pclk_khz;
653         mclk_freq = arb->mclk_khz;
654         nvclk_freq = arb->nvclk_khz;
655         pagemiss = arb->mem_page_miss;
656         cas = arb->mem_latency;
657         width = arb->memory_width >> 6;
658         video_enable = arb->enable_video;
659         color_key_enable = arb->gr_during_vid;
660         bpp = arb->pix_bpp;
661         align = arb->mem_aligned;
662         mp_enable = arb->enable_mp;
663         clwm = 0;
664         vlwm = 0;
665         cbs = 128;
666         pclks = 2;
667         nvclks = 2;
668         nvclks += 2;
669         nvclks += 1;
670         mclks = 5;
671         mclks += 3;
672         mclks += 1;
673         mclks += cas;
674         mclks += 1;
675         mclks += 1;
676         mclks += 1;
677         mclks += 1;
678         mclk_extra = 3;
679         nvclks += 2;
680         nvclks += 1;
681         nvclks += 1;
682         nvclks += 1;
683         if (mp_enable)
684             mclks+=4;
685         nvclks += 0;
686         pclks += 0;
687         found = 0;
688         vbs = 0;
689         while (found != 1)
690         {
691             fifo->valid = 1;
692             found = 1;
693             mclk_loop = mclks+mclk_extra;
694             us_m = mclk_loop *1000*1000 / mclk_freq;
695             us_n = nvclks*1000*1000 / nvclk_freq;
696             us_p = nvclks*1000*1000 / pclk_freq;
697             if (video_enable)
698             {
699                 video_drain_rate = pclk_freq * 2;
700                 crtc_drain_rate = pclk_freq * bpp/8;
701                 vpagemiss = 2;
702                 vpagemiss += 1;
703                 crtpagemiss = 2;
704                 vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
705                 if (nvclk_freq * 2 > mclk_freq * width)
706                     video_fill_us = cbs*1000*1000 / 16 / nvclk_freq ;
707                 else
708                     video_fill_us = cbs*1000*1000 / (8 * width) / mclk_freq;
709                 us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
710                 vlwm = us_video * video_drain_rate/(1000*1000);
711                 vlwm++;
712                 vbs = 128;
713                 if (vlwm > 128) vbs = 64;
714                 if (vlwm > (256-64)) vbs = 32;
715                 if (nvclk_freq * 2 > mclk_freq * width)
716                     video_fill_us = vbs *1000*1000/ 16 / nvclk_freq ;
717                 else
718                     video_fill_us = vbs*1000*1000 / (8 * width) / mclk_freq;
719                 cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
720                 us_crt =
721                 us_video
722                 +video_fill_us
723                 +cpm_us
724                 +us_m + us_n +us_p
725                 ;
726                 clwm = us_crt * crtc_drain_rate/(1000*1000);
727                 clwm++;
728             }
729             else
730             {
731                 crtc_drain_rate = pclk_freq * bpp/8;
732                 crtpagemiss = 2;
733                 crtpagemiss += 1;
734                 cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
735                 us_crt =  cpm_us + us_m + us_n + us_p ;
736                 clwm = us_crt * crtc_drain_rate/(1000*1000);
737                 clwm++;
738             }
739             m1 = clwm + cbs - 512;
740             p1 = m1 * pclk_freq / mclk_freq;
741             p1 = p1 * bpp / 8;
742             if ((p1 < m1) && (m1 > 0))
743             {
744                 fifo->valid = 0;
745                 found = 0;
746                 if (mclk_extra ==0)   found = 1;
747                 mclk_extra--;
748             }
749             else if (video_enable)
750             {
751                 if ((clwm > 511) || (vlwm > 255))
752                 {
753                     fifo->valid = 0;
754                     found = 0;
755                     if (mclk_extra ==0)   found = 1;
756                     mclk_extra--;
757                 }
758             }
759             else
760             {
761                 if (clwm > 519)
762                 {
763                     fifo->valid = 0;
764                     found = 0;
765                     if (mclk_extra ==0)   found = 1;
766                     mclk_extra--;
767                 }
768             }
769             craw = clwm;
770             vraw = vlwm;
771             if (clwm < 384) clwm = 384;
772             if (vlwm < 128) vlwm = 128;
773             data = (int)(clwm);
774             fifo->graphics_lwm = data;
775             fifo->graphics_burst_size = 128;
776             data = (int)((vlwm+15));
777             fifo->video_lwm = data;
778             fifo->video_burst_size = vbs;
779         }
780     }
781     static void nv4UpdateArbitrationSettings
782     (
783         unsigned      VClk, 
784         unsigned      pixelDepth, 
785         unsigned     *burst,
786         unsigned     *lwm,
787         RIVA_HW_INST *chip
788     )
789     {
790         nv4_fifo_info fifo_data;
791         nv4_sim_state sim_data;
792         unsigned int M, N, P, pll, MClk, NVClk, cfg1;
793     
794         pll = chip->PRAMDAC[0x00000504/4];
795         M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
796         MClk  = (N * chip->CrystalFreqKHz / M) >> P;
797         pll = chip->PRAMDAC[0x00000500/4];
798         M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
799         NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
800         cfg1 = chip->PFB[0x00000204/4];
801         sim_data.pix_bpp        = (char)pixelDepth;
802         sim_data.enable_video   = 0;
803         sim_data.enable_mp      = 0;
804         sim_data.memory_width   = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64;
805         sim_data.mem_latency    = (char)cfg1 & 0x0F;
806         sim_data.mem_aligned    = 1;
807         sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
808         sim_data.gr_during_vid  = 0;
809         sim_data.pclk_khz       = VClk;
810         sim_data.mclk_khz       = MClk;
811         sim_data.nvclk_khz      = NVClk;
812         nv4CalcArbitration(&fifo_data, &sim_data);
813         if (fifo_data.valid)
814         {
815             int  b = fifo_data.graphics_burst_size >> 4;
816             *burst = 0;
817             while (b >>= 1) (*burst)++;
818             *lwm   = fifo_data.graphics_lwm >> 3;
819         }
820     }
821     static void nv10CalcArbitration 
822     (
823         nv10_fifo_info *fifo,
824         nv10_sim_state *arb
825     )
826     {
827         int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
828         int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
829         int nvclk_fill, us_extra;
830         int found, mclk_extra, mclk_loop, cbs, m1;
831         int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
832         int us_m, us_m_min, us_n, us_p, video_drain_rate, crtc_drain_rate;
833         int vus_m, vus_n, vus_p;
834         int vpm_us, us_video, vlwm, cpm_us, us_crt,clwm;
835         int clwm_rnd_down;
836         int craw, m2us, us_pipe, us_pipe_min, vus_pipe, p1clk, p2;
837         int pclks_2_top_fifo, min_mclk_extra;
838         int us_min_mclk_extra;
839     
840         fifo->valid = 1;
841         pclk_freq = arb->pclk_khz; /* freq in KHz */
842         mclk_freq = arb->mclk_khz;
843         nvclk_freq = arb->nvclk_khz;
844         pagemiss = arb->mem_page_miss;
845         cas = arb->mem_latency;
846         width = arb->memory_width/64;
847         video_enable = arb->enable_video;
848         color_key_enable = arb->gr_during_vid;
849         bpp = arb->pix_bpp;
850         align = arb->mem_aligned;
851         mp_enable = arb->enable_mp;
852         clwm = 0;
853         vlwm = 1024;
854     
855         cbs = 512;
856         vbs = 512;
857     
858         pclks = 4; /* lwm detect. */
859     
860         nvclks = 3; /* lwm -> sync. */
861         nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
862     
863         mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
864     
865         mclks += 1;   /* arb_hp_req */
866         mclks += 5;   /* ap_hp_req   tiling pipeline */
867     
868         mclks += 2;    /* tc_req     latency fifo */
869         mclks += 2;    /* fb_cas_n_  memory request to fbio block */
870         mclks += 7;    /* sm_d_rdv   data returned from fbio block */
871     
872         /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
873         if (arb->memory_type == 0)
874           if (arb->memory_width == 64) /* 64 bit bus */
875             mclks += 4;
876           else
877             mclks += 2;
878         else
879           if (arb->memory_width == 64) /* 64 bit bus */
880             mclks += 2;
881           else
882             mclks += 1;
883     
884         if ((!video_enable) && (arb->memory_width == 128))
885         {  
886           mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
887           min_mclk_extra = 17;
888         }
889         else
890         {
891           mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
892           /* mclk_extra = 4; */ /* Margin of error */
893           min_mclk_extra = 18;
894         }
895     
896         nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
897         nvclks += 1; /* fbi_d_rdv_n */
898         nvclks += 1; /* Fbi_d_rdata */
899         nvclks += 1; /* crtfifo load */
900     
901         if(mp_enable)
902           mclks+=4; /* Mp can get in with a burst of 8. */
903         /* Extra clocks determined by heuristics */
904     
905         nvclks += 0;
906         pclks += 0;
907         found = 0;
908         while(found != 1) {
909           fifo->valid = 1;
910           found = 1;
911           mclk_loop = mclks+mclk_extra;
912           us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
913           us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
914           us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
915           us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
916           us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
917           us_pipe = us_m + us_n + us_p;
918           us_pipe_min = us_m_min + us_n + us_p;
919           us_extra = 0;
920     
921           vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
922           vus_n = (4)*1000*1000 / nvclk_freq;/* nvclk latency in us */
923           vus_p = 0*1000*1000 / pclk_freq;/* pclk latency in us */
924           vus_pipe = vus_m + vus_n + vus_p;
925     
926           if(video_enable) {
927             video_drain_rate = pclk_freq * 4; /* MB/s */
928             crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
929     
930             vpagemiss = 1; /* self generating page miss */
931             vpagemiss += 1; /* One higher priority before */
932     
933             crtpagemiss = 2; /* self generating page miss */
934             if(mp_enable)
935                 crtpagemiss += 1; /* if MA0 conflict */
936     
937             vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
938     
939             us_video = vpm_us + vus_m; /* Video has separate read return path */
940     
941             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
942             us_crt =
943               us_video  /* Wait for video */
944               +cpm_us /* CRT Page miss */
945               +us_m + us_n +us_p /* other latency */
946               ;
947     
948             clwm = us_crt * crtc_drain_rate/(1000*1000);
949             clwm++; /* fixed point <= float_point - 1.  Fixes that */
950           } else {
951             crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
952     
953             crtpagemiss = 1; /* self generating page miss */
954             crtpagemiss += 1; /* MA0 page miss */
955             if(mp_enable)
956                 crtpagemiss += 1; /* if MA0 conflict */
957             cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
958             us_crt =  cpm_us + us_m + us_n + us_p ;
959             clwm = us_crt * crtc_drain_rate/(1000*1000);
960             clwm++; /* fixed point <= float_point - 1.  Fixes that */
961     
962       /*
963               //
964               // Another concern, only for high pclks so don't do this
965               // with video:
966               // What happens if the latency to fetch the cbs is so large that
967               // fifo empties.  In that case we need to have an alternate clwm value
968               // based off the total burst fetch
969               //
970               us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
971               us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq;
972               clwm_mt = us_crt * crtc_drain_rate/(1000*1000);
973               clwm_mt ++;
974               if(clwm_mt > clwm)
975                   clwm = clwm_mt;
976       */
977               /* Finally, a heuristic check when width == 64 bits */
978               if(width == 1){
979                   nvclk_fill = nvclk_freq * 8;
980                   if(crtc_drain_rate * 100 >= nvclk_fill * 102)
981                           clwm = 0xfff; /*Large number to fail */
982     
983                   else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
984                       clwm = 1024;
985                       cbs = 512;
986                       us_extra = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
987                   }
988               }
989           }
990     
991     
992           /*
993             Overfill check:
994     
995             */
996     
997           clwm_rnd_down = ((int)clwm/8)*8;
998           if (clwm_rnd_down < clwm)
999               clwm += 8;
1000     
1001           m1 = clwm + cbs -  1024; /* Amount of overfill */
1002           m2us = us_pipe_min + us_min_mclk_extra;
1003           pclks_2_top_fifo = (1024-clwm)/(8*width);
1004     
1005           /* pclk cycles to drain */
1006           p1clk = m2us * pclk_freq/(1000*1000); 
1007           p2 = p1clk * bpp / 8; /* bytes drained. */
1008     
1009           if((p2 < m1) && (m1 > 0)) {
1010               fifo->valid = 0;
1011               found = 0;
1012               if(min_mclk_extra == 0)   {
1013                 if(cbs <= 32) {
1014                   found = 1; /* Can't adjust anymore! */
1015                 } else {
1016                   cbs = cbs/2;  /* reduce the burst size */
1017                 }
1018               } else {
1019                 min_mclk_extra--;
1020               }
1021           } else {
1022             if (clwm > 1023){ /* Have some margin */
1023               fifo->valid = 0;
1024               found = 0;
1025               if(min_mclk_extra == 0)   
1026                   found = 1; /* Can't adjust anymore! */
1027               else 
1028                   min_mclk_extra--;
1029             }
1030           }
1031           craw = clwm;
1032     
1033           if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
1034           data = (int)(clwm);
1035           /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
1036           fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
1037     
1038           /*  printf("VID LWM: %f bytes, prog: 0x%x, bs: %d\n, ", vlwm, data, vbs ); */
1039           fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
1040         }
1041     }
1042     static void nv10UpdateArbitrationSettings
1043     (
1044         unsigned      VClk, 
1045         unsigned      pixelDepth, 
1046         unsigned     *burst,
1047         unsigned     *lwm,
1048         RIVA_HW_INST *chip
1049     )
1050     {
1051         nv10_fifo_info fifo_data;
1052         nv10_sim_state sim_data;
1053         unsigned int M, N, P, pll, MClk, NVClk, cfg1;
1054     
1055         pll = chip->PRAMDAC[0x00000504/4];
1056         M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
1057         MClk  = (N * chip->CrystalFreqKHz / M) >> P;
1058         pll = chip->PRAMDAC[0x00000500/4];
1059         M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
1060         NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
1061         cfg1 = chip->PFB[0x00000204/4];
1062         sim_data.pix_bpp        = (char)pixelDepth;
1063         sim_data.enable_video   = 0;
1064         sim_data.enable_mp      = 0;
1065         sim_data.memory_type    = (chip->PFB[0x00000200/4] & 0x01) ? 1 : 0;
1066         sim_data.memory_width   = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64;
1067         sim_data.mem_latency    = (char)cfg1 & 0x0F;
1068         sim_data.mem_aligned    = 1;
1069         sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
1070         sim_data.gr_during_vid  = 0;
1071         sim_data.pclk_khz       = VClk;
1072         sim_data.mclk_khz       = MClk;
1073         sim_data.nvclk_khz      = NVClk;
1074         nv10CalcArbitration(&fifo_data, &sim_data);
1075         if (fifo_data.valid)
1076         {
1077             int  b = fifo_data.graphics_burst_size >> 4;
1078             *burst = 0;
1079             while (b >>= 1) (*burst)++;
1080             *lwm   = fifo_data.graphics_lwm >> 3;
1081         }
1082     }
1083     
1084     /****************************************************************************\
1085     *                                                                            *
1086     *                          RIVA Mode State Routines                          *
1087     *                                                                            *
1088     \****************************************************************************/
1089     
1090     /*
1091      * Calculate the Video Clock parameters for the PLL.
1092      */
1093     static int CalcVClock
1094     (
1095         int           clockIn,
1096         int           double_scan,
1097         int          *clockOut,
1098         int          *mOut,
1099         int          *nOut,
1100         int          *pOut,
1101         RIVA_HW_INST *chip
1102     )
1103     {
1104         unsigned lowM, highM, highP;
1105         unsigned DeltaNew, DeltaOld;
1106         unsigned VClk, Freq;
1107         unsigned M, N, P;
1108         
1109         DeltaOld = 0xFFFFFFFF;
1110     
1111         VClk     = (unsigned)clockIn;
1112         if (double_scan)
1113             VClk *= 2;
1114         
1115         if (chip->CrystalFreqKHz == 14318)
1116         {
1117             lowM  = 8;
1118             highM = 14 - (chip->Architecture == NV_ARCH_03);
1119         }
1120         else
1121         {
1122             lowM  = 7;
1123             highM = 13 - (chip->Architecture == NV_ARCH_03);
1124         }                      
1125     
1126         highP = 4 - (chip->Architecture == NV_ARCH_03);
1127         for (P = 0; P <= highP; P ++)
1128         {
1129             Freq = VClk << P;
1130             if ((Freq >= 128000) && (Freq <= chip->MaxVClockFreqKHz))
1131             {
1132                 for (M = lowM; M <= highM; M++)
1133                 {
1134                     N    = (VClk * M / chip->CrystalFreqKHz) << P;
1135                     Freq = (chip->CrystalFreqKHz * N / M) >> P;
1136                     if (Freq > VClk)
1137                         DeltaNew = Freq - VClk;
1138                     else
1139                         DeltaNew = VClk - Freq;
1140                     if (DeltaNew < DeltaOld)
1141                     {
1142                         *mOut     = M;
1143                         *nOut     = N;
1144                         *pOut     = P;
1145                         *clockOut = Freq;
1146                         DeltaOld  = DeltaNew;
1147                     }
1148                 }
1149             }
1150         }
1151         return (DeltaOld != 0xFFFFFFFF);
1152     }
1153     /*
1154      * Calculate extended mode parameters (SVGA) and save in a 
1155      * mode state structure.
1156      */
1157     static void CalcStateExt
1158     (
1159         RIVA_HW_INST  *chip,
1160         RIVA_HW_STATE *state,
1161         int            bpp,
1162         int            width,
1163         int            hDisplaySize,
1164         int            hDisplay,
1165         int            hStart,
1166         int            hEnd,
1167         int            hTotal,
1168         int            height,
1169         int            vDisplay,
1170         int            vStart,
1171         int            vEnd,
1172         int            vTotal,
1173         int            dotClock
1174     )
1175     {
1176         int pixelDepth, VClk, m, n, p;
1177         /*
1178          * Save mode parameters.
1179          */
1180         state->bpp    = bpp;
1181         state->width  = width;
1182         state->height = height;
1183         /*
1184          * Extended RIVA registers.
1185          */
1186         pixelDepth = (bpp + 1)/8;
1187         CalcVClock(dotClock, hDisplaySize < 512,  /* double scan? */
1188                    &VClk, &m, &n, &p, chip);
1189     
1190         switch (chip->Architecture)
1191         {
1192             case NV_ARCH_03:
1193                 nv3UpdateArbitrationSettings(VClk, 
1194                                              pixelDepth * 8, 
1195                                             &(state->arbitration0),
1196                                             &(state->arbitration1),
1197                                              chip);
1198                 state->cursor0  = 0x00;
1199                 state->cursor1  = 0x78;
1200                 state->cursor2  = 0x00000000;
1201                 state->pllsel   = 0x10010100;
1202                 state->config   = ((width + 31)/32)
1203                                 | (((pixelDepth > 2) ? 3 : pixelDepth) << 8)
1204                                 | 0x1000;
1205                 state->general  = 0x00100100;
1206                 state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02;
1207                 break;
1208             case NV_ARCH_04:
1209                 nv4UpdateArbitrationSettings(VClk, 
1210                                              pixelDepth * 8, 
1211                                             &(state->arbitration0),
1212                                             &(state->arbitration1),
1213                                              chip);
1214                 state->cursor0  = 0x00;
1215                 state->cursor1  = 0xFC;
1216                 state->cursor2  = 0x00000000;
1217                 state->pllsel   = 0x10000700;
1218                 state->config   = 0x00001114;
1219                 state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
1220                 state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1221                 break;
1222             case NV_ARCH_10:
1223                 nv10UpdateArbitrationSettings(VClk, 
1224                                               pixelDepth * 8, 
1225                                              &(state->arbitration0),
1226                                              &(state->arbitration1),
1227                                               chip);
1228                 state->cursor0  = 0x00;
1229                 state->cursor1  = 0xFC;
1230                 state->cursor2  = 0x00000000;
1231                 state->pllsel   = 0x10000700;
1232                 state->config   = chip->PFB[0x00000200/4];
1233                 state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
1234                 state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1235                 break;
1236         }
1237         state->vpll     = (p << 16) | (n << 8) | m;
1238         state->screen   = ((hTotal   & 0x040) >> 2)
1239                         | ((vDisplay & 0x400) >> 7)
1240                         | ((vStart   & 0x400) >> 8)
1241                         | ((vDisplay & 0x400) >> 9)
1242                         | ((vTotal   & 0x400) >> 10);
1243         state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
1244         state->horiz    = hTotal     < 260 ? 0x00 : 0x01;
1245         state->pixel    = pixelDepth > 2   ? 3    : pixelDepth;
1246         state->offset0  =
1247         state->offset1  =
1248         state->offset2  =
1249         state->offset3  = 0;
1250         state->pitch0   =
1251         state->pitch1   =
1252         state->pitch2   =
1253         state->pitch3   = pixelDepth * width;
1254     }
1255     /*
1256      * Load fixed function state and pre-calculated/stored state.
1257      */
1258     #define LOAD_FIXED_STATE(tbl,dev)                                       \
1259         for (i = 0; i < sizeof(tbl##Table##dev)/8; i++)                 \
1260             chip->dev[tbl##Table##dev[i][0]] = tbl##Table##dev[i][1]
1261     #define LOAD_FIXED_STATE_8BPP(tbl,dev)                                  \
1262         for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++)            \
1263             chip->dev[tbl##Table##dev##_8BPP[i][0]] = tbl##Table##dev##_8BPP[i][1]
1264     #define LOAD_FIXED_STATE_15BPP(tbl,dev)                                 \
1265         for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++)           \
1266             chip->dev[tbl##Table##dev##_15BPP[i][0]] = tbl##Table##dev##_15BPP[i][1]
1267     #define LOAD_FIXED_STATE_16BPP(tbl,dev)                                 \
1268         for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++)           \
1269             chip->dev[tbl##Table##dev##_16BPP[i][0]] = tbl##Table##dev##_16BPP[i][1]
1270     #define LOAD_FIXED_STATE_32BPP(tbl,dev)                                 \
1271         for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++)           \
1272             chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1]
1273     static void UpdateFifoState
1274     (
1275         RIVA_HW_INST  *chip
1276     )
1277     {
1278         int i;
1279     
1280         switch (chip->Architecture)
1281         {
1282             case NV_ARCH_04:
1283                 LOAD_FIXED_STATE(nv4,FIFO);
1284                 chip->Tri03 = 0L;
1285                 chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
1286                 break;
1287             case NV_ARCH_10:
1288                 /*
1289                  * Initialize state for the RivaTriangle3D05 routines.
1290                  */
1291                 LOAD_FIXED_STATE(nv10tri05,PGRAPH);
1292                 LOAD_FIXED_STATE(nv10,FIFO);
1293                 chip->Tri03 = 0L;
1294                 chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
1295                 break;
1296         }
1297     }
1298     static void LoadStateExt
1299     (
1300         RIVA_HW_INST  *chip,
1301         RIVA_HW_STATE *state
1302     )
1303     {
1304         int i;
1305     
1306         /*
1307          * Load HW fixed function state.
1308          */
1309         LOAD_FIXED_STATE(Riva,PMC);
1310         LOAD_FIXED_STATE(Riva,PTIMER);
1311         switch (chip->Architecture)
1312         {
1313             case NV_ARCH_03:
1314                 /*
1315                  * Make sure frame buffer config gets set before loading PRAMIN.
1316                  */
1317                 chip->PFB[0x00000200/4] = state->config;
1318                 LOAD_FIXED_STATE(nv3,PFIFO);
1319                 LOAD_FIXED_STATE(nv3,PRAMIN);
1320                 LOAD_FIXED_STATE(nv3,PGRAPH);
1321                 switch (state->bpp)
1322                 {
1323                     case 15:
1324                     case 16:
1325                         LOAD_FIXED_STATE_15BPP(nv3,PRAMIN);
1326                         LOAD_FIXED_STATE_15BPP(nv3,PGRAPH);
1327                         chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1328                         break;
1329                     case 24:
1330                     case 32:
1331                         LOAD_FIXED_STATE_32BPP(nv3,PRAMIN);
1332                         LOAD_FIXED_STATE_32BPP(nv3,PGRAPH);
1333                         chip->Tri03 = 0L;
1334                         break;
1335                     case 8:
1336                     default:
1337                         LOAD_FIXED_STATE_8BPP(nv3,PRAMIN);
1338                         LOAD_FIXED_STATE_8BPP(nv3,PGRAPH);
1339                         chip->Tri03 = 0L;
1340                         break;
1341                 }
1342                 for (i = 0x00000; i < 0x00800; i++)
1343                     chip->PRAMIN[0x00000502 + i] = (i << 12) | 0x03;
1344                 chip->PGRAPH[0x00000630/4] = state->offset0;
1345                 chip->PGRAPH[0x00000634/4] = state->offset1;
1346                 chip->PGRAPH[0x00000638/4] = state->offset2;
1347                 chip->PGRAPH[0x0000063C/4] = state->offset3;
1348                 chip->PGRAPH[0x00000650/4] = state->pitch0;
1349                 chip->PGRAPH[0x00000654/4] = state->pitch1;
1350                 chip->PGRAPH[0x00000658/4] = state->pitch2;
1351                 chip->PGRAPH[0x0000065C/4] = state->pitch3;
1352                 break;
1353             case NV_ARCH_04:
1354                 /*
1355                  * Make sure frame buffer config gets set before loading PRAMIN.
1356                  */
1357                 chip->PFB[0x00000200/4] = state->config;
1358                 LOAD_FIXED_STATE(nv4,PFIFO);
1359                 LOAD_FIXED_STATE(nv4,PRAMIN);
1360                 LOAD_FIXED_STATE(nv4,PGRAPH);
1361                 switch (state->bpp)
1362                 {
1363                     case 15:
1364                         LOAD_FIXED_STATE_15BPP(nv4,PRAMIN);
1365                         LOAD_FIXED_STATE_15BPP(nv4,PGRAPH);
1366                         chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1367                         break;
1368                     case 16:
1369                         LOAD_FIXED_STATE_16BPP(nv4,PRAMIN);
1370                         LOAD_FIXED_STATE_16BPP(nv4,PGRAPH);
1371                         chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1372                         break;
1373                     case 24:
1374                     case 32:
1375                         LOAD_FIXED_STATE_32BPP(nv4,PRAMIN);
1376                         LOAD_FIXED_STATE_32BPP(nv4,PGRAPH);
1377                         chip->Tri03 = 0L;
1378                         break;
1379                     case 8:
1380                     default:
1381                         LOAD_FIXED_STATE_8BPP(nv4,PRAMIN);
1382                         LOAD_FIXED_STATE_8BPP(nv4,PGRAPH);
1383                         chip->Tri03 = 0L;
1384                         break;
1385                 }
1386                 chip->PGRAPH[0x00000640/4] = state->offset0;
1387                 chip->PGRAPH[0x00000644/4] = state->offset1;
1388                 chip->PGRAPH[0x00000648/4] = state->offset2;
1389                 chip->PGRAPH[0x0000064C/4] = state->offset3;
1390                 chip->PGRAPH[0x00000670/4] = state->pitch0;
1391                 chip->PGRAPH[0x00000674/4] = state->pitch1;
1392                 chip->PGRAPH[0x00000678/4] = state->pitch2;
1393                 chip->PGRAPH[0x0000067C/4] = state->pitch3;
1394                 break;
1395             case NV_ARCH_10:
1396                 LOAD_FIXED_STATE(nv10,PFIFO);
1397                 LOAD_FIXED_STATE(nv10,PRAMIN);
1398                 LOAD_FIXED_STATE(nv10,PGRAPH);
1399                 switch (state->bpp)
1400                 {
1401                     case 15:
1402                         LOAD_FIXED_STATE_15BPP(nv10,PRAMIN);
1403                         LOAD_FIXED_STATE_15BPP(nv10,PGRAPH);
1404                         chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1405                         break;
1406                     case 16:
1407                         LOAD_FIXED_STATE_16BPP(nv10,PRAMIN);
1408                         LOAD_FIXED_STATE_16BPP(nv10,PGRAPH);
1409                         chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1410                         break;
1411                     case 24:
1412                     case 32:
1413                         LOAD_FIXED_STATE_32BPP(nv10,PRAMIN);
1414                         LOAD_FIXED_STATE_32BPP(nv10,PGRAPH);
1415                         chip->Tri03 = 0L;
1416                         break;
1417                     case 8:
1418                     default:
1419                         LOAD_FIXED_STATE_8BPP(nv10,PRAMIN);
1420                         LOAD_FIXED_STATE_8BPP(nv10,PGRAPH);
1421                         chip->Tri03 = 0L;
1422                         break;
1423                 }
1424                 chip->PGRAPH[0x00000640/4] = state->offset0;
1425                 chip->PGRAPH[0x00000644/4] = state->offset1;
1426                 chip->PGRAPH[0x00000648/4] = state->offset2;
1427                 chip->PGRAPH[0x0000064C/4] = state->offset3;
1428                 chip->PGRAPH[0x00000670/4] = state->pitch0;
1429                 chip->PGRAPH[0x00000674/4] = state->pitch1;
1430                 chip->PGRAPH[0x00000678/4] = state->pitch2;
1431                 chip->PGRAPH[0x0000067C/4] = state->pitch3;
1432                 chip->PGRAPH[0x00000680/4] = state->pitch3;
1433                 chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
1434                 chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
1435                 chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4];
1436                 chip->PGRAPH[0x00000B0C/4] = chip->PFB[0x0000024C/4];
1437                 chip->PGRAPH[0x00000B10/4] = chip->PFB[0x00000250/4];
1438                 chip->PGRAPH[0x00000B14/4] = chip->PFB[0x00000254/4];
1439                 chip->PGRAPH[0x00000B18/4] = chip->PFB[0x00000258/4];
1440                 chip->PGRAPH[0x00000B1C/4] = chip->PFB[0x0000025C/4];
1441                 chip->PGRAPH[0x00000B20/4] = chip->PFB[0x00000260/4];
1442                 chip->PGRAPH[0x00000B24/4] = chip->PFB[0x00000264/4];
1443                 chip->PGRAPH[0x00000B28/4] = chip->PFB[0x00000268/4];
1444                 chip->PGRAPH[0x00000B2C/4] = chip->PFB[0x0000026C/4];
1445                 chip->PGRAPH[0x00000B30/4] = chip->PFB[0x00000270/4];
1446                 chip->PGRAPH[0x00000B34/4] = chip->PFB[0x00000274/4];
1447                 chip->PGRAPH[0x00000B38/4] = chip->PFB[0x00000278/4];
1448                 chip->PGRAPH[0x00000B3C/4] = chip->PFB[0x0000027C/4];
1449                 chip->PGRAPH[0x00000B40/4] = chip->PFB[0x00000280/4];
1450                 chip->PGRAPH[0x00000B44/4] = chip->PFB[0x00000284/4];
1451                 chip->PGRAPH[0x00000B48/4] = chip->PFB[0x00000288/4];
1452                 chip->PGRAPH[0x00000B4C/4] = chip->PFB[0x0000028C/4];
1453                 chip->PGRAPH[0x00000B50/4] = chip->PFB[0x00000290/4];
1454                 chip->PGRAPH[0x00000B54/4] = chip->PFB[0x00000294/4];
1455                 chip->PGRAPH[0x00000B58/4] = chip->PFB[0x00000298/4];
1456                 chip->PGRAPH[0x00000B5C/4] = chip->PFB[0x0000029C/4];
1457                 chip->PGRAPH[0x00000B60/4] = chip->PFB[0x000002A0/4];
1458                 chip->PGRAPH[0x00000B64/4] = chip->PFB[0x000002A4/4];
1459                 chip->PGRAPH[0x00000B68/4] = chip->PFB[0x000002A8/4];
1460                 chip->PGRAPH[0x00000B6C/4] = chip->PFB[0x000002AC/4];
1461                 chip->PGRAPH[0x00000B70/4] = chip->PFB[0x000002B0/4];
1462                 chip->PGRAPH[0x00000B74/4] = chip->PFB[0x000002B4/4];
1463                 chip->PGRAPH[0x00000B78/4] = chip->PFB[0x000002B8/4];
1464                 chip->PGRAPH[0x00000B7C/4] = chip->PFB[0x000002BC/4];
1465                 chip->PGRAPH[0x00000F40/4] = 0x10000000;
1466                 chip->PGRAPH[0x00000F44/4] = 0x00000000;
1467                 chip->PGRAPH[0x00000F50/4] = 0x00000040;
1468                 chip->PGRAPH[0x00000F54/4] = 0x00000008;
1469                 chip->PGRAPH[0x00000F50/4] = 0x00000200;
1470                 for (i = 0; i < (3*16); i++)
1471                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1472                 chip->PGRAPH[0x00000F50/4] = 0x00000040;
1473                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1474                 chip->PGRAPH[0x00000F50/4] = 0x00000800;
1475                 for (i = 0; i < (16*16); i++)
1476                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1477                 chip->PGRAPH[0x00000F40/4] = 0x30000000;
1478                 chip->PGRAPH[0x00000F44/4] = 0x00000004;
1479                 chip->PGRAPH[0x00000F50/4] = 0x00006400;
1480                 for (i = 0; i < (59*4); i++)
1481                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1482                 chip->PGRAPH[0x00000F50/4] = 0x00006800;
1483                 for (i = 0; i < (47*4); i++)
1484                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1485                 chip->PGRAPH[0x00000F50/4] = 0x00006C00;
1486                 for (i = 0; i < (3*4); i++)
1487                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1488                 chip->PGRAPH[0x00000F50/4] = 0x00007000;
1489                 for (i = 0; i < (19*4); i++)
1490                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1491                 chip->PGRAPH[0x00000F50/4] = 0x00007400;
1492                 for (i = 0; i < (12*4); i++)
1493                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1494                 chip->PGRAPH[0x00000F50/4] = 0x00007800;
1495                 for (i = 0; i < (12*4); i++)
1496                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1497                 chip->PGRAPH[0x00000F50/4] = 0x00004400;
1498                 for (i = 0; i < (8*4); i++)
1499                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1500                 chip->PGRAPH[0x00000F50/4] = 0x00000000;
1501                 for (i = 0; i < 16; i++)
1502                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1503                 chip->PGRAPH[0x00000F50/4] = 0x00000040;
1504                 for (i = 0; i < 4; i++)
1505                     chip->PGRAPH[0x00000F54/4] = 0x00000000;
1506                 break;
1507         }
1508         LOAD_FIXED_STATE(Riva,FIFO);
1509         UpdateFifoState(chip);
1510         /*
1511          * Load HW mode state.
1512          */
1513         VGA_WR08(chip->PCIO, 0x03D4, 0x19);
1514         VGA_WR08(chip->PCIO, 0x03D5, state->repaint0);
1515         VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
1516         VGA_WR08(chip->PCIO, 0x03D5, state->repaint1);
1517         VGA_WR08(chip->PCIO, 0x03D4, 0x25);
1518         VGA_WR08(chip->PCIO, 0x03D5, state->screen);
1519         VGA_WR08(chip->PCIO, 0x03D4, 0x28);
1520         VGA_WR08(chip->PCIO, 0x03D5, state->pixel);
1521         VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
1522         VGA_WR08(chip->PCIO, 0x03D5, state->horiz);
1523         VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
1524         VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0);
1525         VGA_WR08(chip->PCIO, 0x03D4, 0x20);
1526         VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1);
1527         VGA_WR08(chip->PCIO, 0x03D4, 0x30);
1528         VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
1529         VGA_WR08(chip->PCIO, 0x03D4, 0x31);
1530         VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
1531         chip->PRAMDAC[0x00000300/4]  = state->cursor2;
1532         chip->PRAMDAC[0x00000508/4]  = state->vpll;
1533         chip->PRAMDAC[0x0000050C/4]  = state->pllsel;
1534         chip->PRAMDAC[0x00000600/4]  = state->general;
1535         /*
1536          * Turn off VBlank enable and reset.
1537          */
1538         *(chip->VBLANKENABLE) = 0;
1539         *(chip->VBLANK)       = chip->VBlankBit;
1540         /*
1541          * Set interrupt enable.
1542          */    
1543         chip->PMC[0x00000140/4]  = chip->EnableIRQ & 0x01;
1544         /*
1545          * Set current state pointer.
1546          */
1547         chip->CurrentState = state;
1548         /*
1549          * Reset FIFO free and empty counts.
1550          */
1551         chip->FifoFreeCount  = 0;
1552         /* Free count from first subchannel */
1553         chip->FifoEmptyCount = chip->Rop->FifoFree; 
1554     }
1555     static void UnloadStateExt
1556     (
1557         RIVA_HW_INST  *chip,
1558         RIVA_HW_STATE *state
1559     )
1560     {
1561         /*
1562          * Save current HW state.
1563          */
1564         VGA_WR08(chip->PCIO, 0x03D4, 0x19);
1565         state->repaint0     = VGA_RD08(chip->PCIO, 0x03D5);
1566         VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
1567         state->repaint1     = VGA_RD08(chip->PCIO, 0x03D5);
1568         VGA_WR08(chip->PCIO, 0x03D4, 0x25);
1569         state->screen       = VGA_RD08(chip->PCIO, 0x03D5);
1570         VGA_WR08(chip->PCIO, 0x03D4, 0x28);
1571         state->pixel        = VGA_RD08(chip->PCIO, 0x03D5);
1572         VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
1573         state->horiz        = VGA_RD08(chip->PCIO, 0x03D5);
1574         VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
1575         state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5);
1576         VGA_WR08(chip->PCIO, 0x03D4, 0x20);
1577         state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5);
1578         VGA_WR08(chip->PCIO, 0x03D4, 0x30);
1579         state->cursor0      = VGA_RD08(chip->PCIO, 0x03D5);
1580         VGA_WR08(chip->PCIO, 0x03D4, 0x31);
1581         state->cursor1      = VGA_RD08(chip->PCIO, 0x03D5);
1582         state->cursor2      = chip->PRAMDAC[0x00000300/4];
1583         state->vpll         = chip->PRAMDAC[0x00000508/4];
1584         state->pllsel       = chip->PRAMDAC[0x0000050C/4];
1585         state->general      = chip->PRAMDAC[0x00000600/4];
1586         state->config       = chip->PFB[0x00000200/4];
1587         switch (chip->Architecture)
1588         {
1589             case NV_ARCH_03:
1590                 state->offset0  = chip->PGRAPH[0x00000630/4];
1591                 state->offset1  = chip->PGRAPH[0x00000634/4];
1592                 state->offset2  = chip->PGRAPH[0x00000638/4];
1593                 state->offset3  = chip->PGRAPH[0x0000063C/4];
1594                 state->pitch0   = chip->PGRAPH[0x00000650/4];
1595                 state->pitch1   = chip->PGRAPH[0x00000654/4];
1596                 state->pitch2   = chip->PGRAPH[0x00000658/4];
1597                 state->pitch3   = chip->PGRAPH[0x0000065C/4];
1598                 break;
1599             case NV_ARCH_04:
1600                 state->offset0  = chip->PGRAPH[0x00000640/4];
1601                 state->offset1  = chip->PGRAPH[0x00000644/4];
1602                 state->offset2  = chip->PGRAPH[0x00000648/4];
1603                 state->offset3  = chip->PGRAPH[0x0000064C/4];
1604                 state->pitch0   = chip->PGRAPH[0x00000670/4];
1605                 state->pitch1   = chip->PGRAPH[0x00000674/4];
1606                 state->pitch2   = chip->PGRAPH[0x00000678/4];
1607                 state->pitch3   = chip->PGRAPH[0x0000067C/4];
1608                 break;
1609             case NV_ARCH_10:
1610                 state->offset0  = chip->PGRAPH[0x00000640/4];
1611                 state->offset1  = chip->PGRAPH[0x00000644/4];
1612                 state->offset2  = chip->PGRAPH[0x00000648/4];
1613                 state->offset3  = chip->PGRAPH[0x0000064C/4];
1614                 state->pitch0   = chip->PGRAPH[0x00000670/4];
1615                 state->pitch1   = chip->PGRAPH[0x00000674/4];
1616                 state->pitch2   = chip->PGRAPH[0x00000678/4];
1617                 state->pitch3   = chip->PGRAPH[0x0000067C/4];
1618                 break;
1619         }
1620     }
1621     static void SetStartAddress
1622     (
1623         RIVA_HW_INST *chip,
1624         unsigned      start
1625     )
1626     {
1627         int offset = start >> 2;
1628         int pan    = (start & 3) << 1;
1629         unsigned char tmp;
1630     
1631         /*
1632          * Unlock extended registers.
1633          */
1634         chip->LockUnlock(chip, 0);
1635         /*
1636          * Set start address.
1637          */
1638         VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset);
1639         offset >>= 8;
1640         VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset);
1641         offset >>= 8;
1642         VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5);
1643         VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F));
1644         VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5);
1645         VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60));
1646         /*
1647          * 4 pixel pan register.
1648          */
1649         offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A);
1650         VGA_WR08(chip->PCIO, 0x3C0, 0x13);
1651         VGA_WR08(chip->PCIO, 0x3C0, pan);
1652     }
1653     static void nv3SetSurfaces2D
1654     (
1655         RIVA_HW_INST *chip,
1656         unsigned     surf0,
1657         unsigned     surf1
1658     )
1659     {
1660         RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1661     
1662         RIVA_FIFO_FREE(*chip,Tri03,5);
1663         chip->FIFO[0x00003800] = 0x80000003;
1664         Surface->Offset        = surf0;
1665         chip->FIFO[0x00003800] = 0x80000004;
1666         Surface->Offset        = surf1;
1667         chip->FIFO[0x00003800] = 0x80000013;
1668     }
1669     static void nv4SetSurfaces2D
1670     (
1671         RIVA_HW_INST *chip,
1672         unsigned     surf0,
1673         unsigned     surf1
1674     )
1675     {
1676         RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1677     
1678         chip->FIFO[0x00003800] = 0x80000003;
1679         Surface->Offset        = surf0;
1680         chip->FIFO[0x00003800] = 0x80000004;
1681         Surface->Offset        = surf1;
1682         chip->FIFO[0x00003800] = 0x80000014;
1683     }
1684     static void nv10SetSurfaces2D
1685     (
1686         RIVA_HW_INST *chip,
1687         unsigned     surf0,
1688         unsigned     surf1
1689     )
1690     {
1691         RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1692     
1693         chip->FIFO[0x00003800] = 0x80000003;
1694         Surface->Offset        = surf0;
1695         chip->FIFO[0x00003800] = 0x80000004;
1696         Surface->Offset        = surf1;
1697         chip->FIFO[0x00003800] = 0x80000014;
1698     }
1699     static void nv3SetSurfaces3D
1700     (
1701         RIVA_HW_INST *chip,
1702         unsigned     surf0,
1703         unsigned     surf1
1704     )
1705     {
1706         RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1707     
1708         RIVA_FIFO_FREE(*chip,Tri03,5);
1709         chip->FIFO[0x00003800] = 0x80000005;
1710         Surface->Offset        = surf0;
1711         chip->FIFO[0x00003800] = 0x80000006;
1712         Surface->Offset        = surf1;
1713         chip->FIFO[0x00003800] = 0x80000013;
1714     }
1715     static void nv4SetSurfaces3D
1716     (
1717         RIVA_HW_INST *chip,
1718         unsigned     surf0,
1719         unsigned     surf1
1720     )
1721     {
1722         RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1723     
1724         chip->FIFO[0x00003800] = 0x80000005;
1725         Surface->Offset        = surf0;
1726         chip->FIFO[0x00003800] = 0x80000006;
1727         Surface->Offset        = surf1;
1728         chip->FIFO[0x00003800] = 0x80000014;
1729     }
1730     static void nv10SetSurfaces3D
1731     (
1732         RIVA_HW_INST *chip,
1733         unsigned     surf0,
1734         unsigned     surf1
1735     )
1736     {
1737         RivaSurface3D *Surfaces3D = (RivaSurface3D *)&(chip->FIFO[0x0000E000/4]);
1738     
1739         RIVA_FIFO_FREE(*chip,Tri03,4);
1740         chip->FIFO[0x00003800]         = 0x80000007;
1741         Surfaces3D->RenderBufferOffset = surf0;
1742         Surfaces3D->ZBufferOffset      = surf1;
1743         chip->FIFO[0x00003800]         = 0x80000014;
1744     }
1745     
1746     /****************************************************************************\
1747     *                                                                            *
1748     *                      Probe RIVA Chip Configuration                         *
1749     *                                                                            *
1750     \****************************************************************************/
1751     
1752     static void nv3GetConfig
1753     (
1754         RIVA_HW_INST *chip
1755     )
1756     {
1757         /*
1758          * Fill in chip configuration.
1759          */
1760         if (chip->PFB[0x00000000/4] & 0x00000020)
1761         {
1762             if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20)
1763              && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02))
1764             {        
1765                 /*
1766                  * SDRAM 128 ZX.
1767                  */
1768                 chip->RamBandwidthKBytesPerSec = 800000;
1769                 switch (chip->PFB[0x00000000/4] & 0x03)
1770                 {
1771                     case 2:
1772                         chip->RamAmountKBytes = 1024 * 4;
1773                         break;
1774                     case 1:
1775                         chip->RamAmountKBytes = 1024 * 2;
1776                         break;
1777                     default:
1778                         chip->RamAmountKBytes = 1024 * 8;
1779                         break;
1780                 }
1781             }            
1782             else            
1783             {
1784                 chip->RamBandwidthKBytesPerSec = 1000000;
1785                 chip->RamAmountKBytes          = 1024 * 8;
1786             }            
1787         }
1788         else
1789         {
1790             /*
1791              * SGRAM 128.
1792              */
1793             chip->RamBandwidthKBytesPerSec = 1000000;
1794             switch (chip->PFB[0x00000000/4] & 0x00000003)
1795             {
1796                 case 0:
1797                     chip->RamAmountKBytes = 1024 * 8;
1798                     break;
1799                 case 2:
1800                     chip->RamAmountKBytes = 1024 * 4;
1801                     break;
1802                 default:
1803                     chip->RamAmountKBytes = 1024 * 2;
1804                     break;
1805             }
1806         }        
1807         chip->CrystalFreqKHz   = (chip->PEXTDEV[0x00000000/4] & 0x00000020) ? 14318 : 13500;
1808         chip->CURSOR           = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]);
1809         chip->CURSORPOS        = &(chip->PRAMDAC[0x0300/4]);
1810         chip->VBLANKENABLE     = &(chip->PGRAPH[0x0140/4]);
1811         chip->VBLANK           = &(chip->PGRAPH[0x0100/4]);
1812         chip->VBlankBit        = 0x00000100;
1813         chip->MaxVClockFreqKHz = 256000;
1814         /*
1815          * Set chip functions.
1816          */
1817         chip->Busy            = nv3Busy;
1818         chip->ShowHideCursor  = ShowHideCursor;
1819         chip->CalcStateExt    = CalcStateExt;
1820         chip->LoadStateExt    = LoadStateExt;
1821         chip->UnloadStateExt  = UnloadStateExt;
1822         chip->SetStartAddress = SetStartAddress;
1823         chip->SetSurfaces2D   = nv3SetSurfaces2D;
1824         chip->SetSurfaces3D   = nv3SetSurfaces3D;
1825         chip->LockUnlock      = nv3LockUnlock;
1826     }
1827     static void nv4GetConfig
1828     (
1829         RIVA_HW_INST *chip
1830     )
1831     {
1832         /*
1833          * Fill in chip configuration.
1834          */
1835         if (chip->PFB[0x00000000/4] & 0x00000100)
1836         {
1837             chip->RamAmountKBytes = ((chip->PFB[0x00000000/4] >> 12) & 0x0F) * 1024 * 2
1838                                   + 1024 * 2;
1839         }
1840         else
1841         {
1842             switch (chip->PFB[0x00000000/4] & 0x00000003)
1843             {
1844                 case 0:
1845                     chip->RamAmountKBytes = 1024 * 32;
1846                     break;
1847                 case 1:
1848                     chip->RamAmountKBytes = 1024 * 4;
1849                     break;
1850                 case 2:
1851                     chip->RamAmountKBytes = 1024 * 8;
1852                     break;
1853                 case 3:
1854                 default:
1855                     chip->RamAmountKBytes = 1024 * 16;
1856                     break;
1857             }
1858         }
1859         switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
1860         {
1861             case 3:
1862                 chip->RamBandwidthKBytesPerSec = 800000;
1863                 break;
1864             default:
1865                 chip->RamBandwidthKBytesPerSec = 1000000;
1866                 break;
1867         }
1868         chip->CrystalFreqKHz   = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
1869         chip->CURSOR           = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
1870         chip->CURSORPOS        = &(chip->PRAMDAC[0x0300/4]);
1871         chip->VBLANKENABLE     = &(chip->PCRTC[0x0140/4]);
1872         chip->VBLANK           = &(chip->PCRTC[0x0100/4]);
1873         chip->VBlankBit        = 0x00000001;
1874         chip->MaxVClockFreqKHz = 350000;
1875         /*
1876          * Set chip functions.
1877          */
1878         chip->Busy            = nv4Busy;
1879         chip->ShowHideCursor  = ShowHideCursor;
1880         chip->CalcStateExt    = CalcStateExt;
1881         chip->LoadStateExt    = LoadStateExt;
1882         chip->UnloadStateExt  = UnloadStateExt;
1883         chip->SetStartAddress = SetStartAddress;
1884         chip->SetSurfaces2D   = nv4SetSurfaces2D;
1885         chip->SetSurfaces3D   = nv4SetSurfaces3D;
1886         chip->LockUnlock      = nv4LockUnlock;
1887     }
1888     static void nv10GetConfig
1889     (
1890         RIVA_HW_INST *chip
1891     )
1892     {
1893         /*
1894          * Fill in chip configuration.
1895          */
1896         switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF)
1897         {
1898             case 0x02:
1899                 chip->RamAmountKBytes = 1024 * 2;
1900                 break;
1901             case 0x04:
1902                 chip->RamAmountKBytes = 1024 * 4;
1903                 break;
1904             case 0x08:
1905                 chip->RamAmountKBytes = 1024 * 8;
1906                 break;
1907             case 0x10:
1908                 chip->RamAmountKBytes = 1024 * 16;
1909                 break;
1910             case 0x20:
1911                 chip->RamAmountKBytes = 1024 * 32;
1912                 break;
1913             case 0x40:
1914                 chip->RamAmountKBytes = 1024 * 64;
1915                 break;
1916             case 0x80:
1917                 chip->RamAmountKBytes = 1024 * 128;
1918                 break;
1919             default:
1920                 chip->RamAmountKBytes = 1024 * 16;
1921                 break;
1922         }
1923         switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
1924         {
1925             case 3:
1926                 chip->RamBandwidthKBytesPerSec = 800000;
1927                 break;
1928             default:
1929                 chip->RamBandwidthKBytesPerSec = 1000000;
1930                 break;
1931         }
1932         chip->CrystalFreqKHz   = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
1933         chip->CURSOR           = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
1934         chip->CURSORPOS        = &(chip->PRAMDAC[0x0300/4]);
1935         chip->VBLANKENABLE     = &(chip->PCRTC[0x0140/4]);
1936         chip->VBLANK           = &(chip->PCRTC[0x0100/4]);
1937         chip->VBlankBit        = 0x00000001;
1938         chip->MaxVClockFreqKHz = 350000;
1939         /*
1940          * Set chip functions.
1941          */
1942         chip->Busy            = nv10Busy;
1943         chip->ShowHideCursor  = ShowHideCursor;
1944         chip->CalcStateExt    = CalcStateExt;
1945         chip->LoadStateExt    = LoadStateExt;
1946         chip->UnloadStateExt  = UnloadStateExt;
1947         chip->SetStartAddress = SetStartAddress;
1948         chip->SetSurfaces2D   = nv10SetSurfaces2D;
1949         chip->SetSurfaces3D   = nv10SetSurfaces3D;
1950         chip->LockUnlock      = nv10LockUnlock;
1951     }
1952     int RivaGetConfig
1953     (
1954         RIVA_HW_INST *chip
1955     )
1956     {
1957         /*
1958          * Save this so future SW know whats it's dealing with.
1959          */
1960         chip->Version = RIVA_SW_VERSION;
1961         /*
1962          * Chip specific configuration.
1963          */
1964         switch (chip->Architecture)
1965         {
1966             case NV_ARCH_03:
1967                 nv3GetConfig(chip);
1968                 break;
1969             case NV_ARCH_04:
1970                 nv4GetConfig(chip);
1971                 break;
1972             case NV_ARCH_10:
1973                 nv10GetConfig(chip);
1974                 break;
1975             default:
1976                 return (-1);
1977         }
1978         /*
1979          * Fill in FIFO pointers.
1980          */
1981         chip->Rop    = (RivaRop                 *)&(chip->FIFO[0x00000000/4]);
1982         chip->Clip   = (RivaClip                *)&(chip->FIFO[0x00002000/4]);
1983         chip->Patt   = (RivaPattern             *)&(chip->FIFO[0x00004000/4]);
1984         chip->Pixmap = (RivaPixmap              *)&(chip->FIFO[0x00006000/4]);
1985         chip->Blt    = (RivaScreenBlt           *)&(chip->FIFO[0x00008000/4]);
1986         chip->Bitmap = (RivaBitmap              *)&(chip->FIFO[0x0000A000/4]);
1987         chip->Line   = (RivaLine                *)&(chip->FIFO[0x0000C000/4]);
1988         chip->Tri03  = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1989         return (0);
1990     }
1991     
1992