import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / 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@pobox.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         case NV_ARCH_20:
1224             nv10UpdateArbitrationSettings(VClk, 
1225                                           pixelDepth * 8, 
1226                                          &(state->arbitration0),
1227                                          &(state->arbitration1),
1228                                           chip);
1229             state->cursor0  = 0x00;
1230             state->cursor1  = 0xFC;
1231             state->cursor2  = 0x00000000;
1232             state->pllsel   = 0x10000700;
1233             state->config   = chip->PFB[0x00000200/4];
1234             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
1235             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
1236             break;
1237     }
1238     state->vpll     = (p << 16) | (n << 8) | m;
1239     state->screen   = ((hTotal   & 0x040) >> 2)
1240                     | ((vDisplay & 0x400) >> 7)
1241                     | ((vStart   & 0x400) >> 8)
1242                     | ((vDisplay & 0x400) >> 9)
1243                     | ((vTotal   & 0x400) >> 10);
1244     state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
1245     state->horiz    = hTotal     < 260 ? 0x00 : 0x01;
1246     state->pixel    = pixelDepth > 2   ? 3    : pixelDepth;
1247     state->offset0  =
1248     state->offset1  =
1249     state->offset2  =
1250     state->offset3  = 0;
1251     state->pitch0   =
1252     state->pitch1   =
1253     state->pitch2   =
1254     state->pitch3   = pixelDepth * width;
1255 }
1256 /*
1257  * Load fixed function state and pre-calculated/stored state.
1258  */
1259 #define LOAD_FIXED_STATE(tbl,dev)                                       \
1260     for (i = 0; i < sizeof(tbl##Table##dev)/8; i++)                 \
1261         chip->dev[tbl##Table##dev[i][0]] = tbl##Table##dev[i][1]
1262 #define LOAD_FIXED_STATE_8BPP(tbl,dev)                                  \
1263     for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++)            \
1264         chip->dev[tbl##Table##dev##_8BPP[i][0]] = tbl##Table##dev##_8BPP[i][1]
1265 #define LOAD_FIXED_STATE_15BPP(tbl,dev)                                 \
1266     for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++)           \
1267         chip->dev[tbl##Table##dev##_15BPP[i][0]] = tbl##Table##dev##_15BPP[i][1]
1268 #define LOAD_FIXED_STATE_16BPP(tbl,dev)                                 \
1269     for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++)           \
1270         chip->dev[tbl##Table##dev##_16BPP[i][0]] = tbl##Table##dev##_16BPP[i][1]
1271 #define LOAD_FIXED_STATE_32BPP(tbl,dev)                                 \
1272     for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++)           \
1273         chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1]
1274 static void UpdateFifoState
1275 (
1276     RIVA_HW_INST  *chip
1277 )
1278 {
1279     int i;
1280
1281     switch (chip->Architecture)
1282     {
1283         case NV_ARCH_04:
1284             LOAD_FIXED_STATE(nv4,FIFO);
1285             chip->Tri03 = 0L;
1286             chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
1287             break;
1288         case NV_ARCH_10:
1289         case NV_ARCH_20:
1290             /*
1291              * Initialize state for the RivaTriangle3D05 routines.
1292              */
1293             LOAD_FIXED_STATE(nv10tri05,PGRAPH);
1294             LOAD_FIXED_STATE(nv10,FIFO);
1295             chip->Tri03 = 0L;
1296             chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
1297             break;
1298     }
1299 }
1300 static void LoadStateExt
1301 (
1302     RIVA_HW_INST  *chip,
1303     RIVA_HW_STATE *state
1304 )
1305 {
1306     int i;
1307
1308     /*
1309      * Load HW fixed function state.
1310      */
1311     LOAD_FIXED_STATE(Riva,PMC);
1312     LOAD_FIXED_STATE(Riva,PTIMER);
1313     switch (chip->Architecture)
1314     {
1315         case NV_ARCH_03:
1316             /*
1317              * Make sure frame buffer config gets set before loading PRAMIN.
1318              */
1319             chip->PFB[0x00000200/4] = state->config;
1320             LOAD_FIXED_STATE(nv3,PFIFO);
1321             LOAD_FIXED_STATE(nv3,PRAMIN);
1322             LOAD_FIXED_STATE(nv3,PGRAPH);
1323             switch (state->bpp)
1324             {
1325                 case 15:
1326                 case 16:
1327                     LOAD_FIXED_STATE_15BPP(nv3,PRAMIN);
1328                     LOAD_FIXED_STATE_15BPP(nv3,PGRAPH);
1329                     chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1330                     break;
1331                 case 24:
1332                 case 32:
1333                     LOAD_FIXED_STATE_32BPP(nv3,PRAMIN);
1334                     LOAD_FIXED_STATE_32BPP(nv3,PGRAPH);
1335                     chip->Tri03 = 0L;
1336                     break;
1337                 case 8:
1338                 default:
1339                     LOAD_FIXED_STATE_8BPP(nv3,PRAMIN);
1340                     LOAD_FIXED_STATE_8BPP(nv3,PGRAPH);
1341                     chip->Tri03 = 0L;
1342                     break;
1343             }
1344             for (i = 0x00000; i < 0x00800; i++)
1345                 chip->PRAMIN[0x00000502 + i] = (i << 12) | 0x03;
1346             chip->PGRAPH[0x00000630/4] = state->offset0;
1347             chip->PGRAPH[0x00000634/4] = state->offset1;
1348             chip->PGRAPH[0x00000638/4] = state->offset2;
1349             chip->PGRAPH[0x0000063C/4] = state->offset3;
1350             chip->PGRAPH[0x00000650/4] = state->pitch0;
1351             chip->PGRAPH[0x00000654/4] = state->pitch1;
1352             chip->PGRAPH[0x00000658/4] = state->pitch2;
1353             chip->PGRAPH[0x0000065C/4] = state->pitch3;
1354             break;
1355         case NV_ARCH_04:
1356             /*
1357              * Make sure frame buffer config gets set before loading PRAMIN.
1358              */
1359             chip->PFB[0x00000200/4] = state->config;
1360             LOAD_FIXED_STATE(nv4,PFIFO);
1361             LOAD_FIXED_STATE(nv4,PRAMIN);
1362             LOAD_FIXED_STATE(nv4,PGRAPH);
1363             switch (state->bpp)
1364             {
1365                 case 15:
1366                     LOAD_FIXED_STATE_15BPP(nv4,PRAMIN);
1367                     LOAD_FIXED_STATE_15BPP(nv4,PGRAPH);
1368                     chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1369                     break;
1370                 case 16:
1371                     LOAD_FIXED_STATE_16BPP(nv4,PRAMIN);
1372                     LOAD_FIXED_STATE_16BPP(nv4,PGRAPH);
1373                     chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1374                     break;
1375                 case 24:
1376                 case 32:
1377                     LOAD_FIXED_STATE_32BPP(nv4,PRAMIN);
1378                     LOAD_FIXED_STATE_32BPP(nv4,PGRAPH);
1379                     chip->Tri03 = 0L;
1380                     break;
1381                 case 8:
1382                 default:
1383                     LOAD_FIXED_STATE_8BPP(nv4,PRAMIN);
1384                     LOAD_FIXED_STATE_8BPP(nv4,PGRAPH);
1385                     chip->Tri03 = 0L;
1386                     break;
1387             }
1388             chip->PGRAPH[0x00000640/4] = state->offset0;
1389             chip->PGRAPH[0x00000644/4] = state->offset1;
1390             chip->PGRAPH[0x00000648/4] = state->offset2;
1391             chip->PGRAPH[0x0000064C/4] = state->offset3;
1392             chip->PGRAPH[0x00000670/4] = state->pitch0;
1393             chip->PGRAPH[0x00000674/4] = state->pitch1;
1394             chip->PGRAPH[0x00000678/4] = state->pitch2;
1395             chip->PGRAPH[0x0000067C/4] = state->pitch3;
1396             break;
1397         case NV_ARCH_10:
1398         case NV_ARCH_20:
1399             LOAD_FIXED_STATE(nv10,PFIFO);
1400             LOAD_FIXED_STATE(nv10,PRAMIN);
1401             LOAD_FIXED_STATE(nv10,PGRAPH);
1402             switch (state->bpp)
1403             {
1404                 case 15:
1405                     LOAD_FIXED_STATE_15BPP(nv10,PRAMIN);
1406                     LOAD_FIXED_STATE_15BPP(nv10,PGRAPH);
1407                     chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1408                     break;
1409                 case 16:
1410                     LOAD_FIXED_STATE_16BPP(nv10,PRAMIN);
1411                     LOAD_FIXED_STATE_16BPP(nv10,PGRAPH);
1412                     chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
1413                     break;
1414                 case 24:
1415                 case 32:
1416                     LOAD_FIXED_STATE_32BPP(nv10,PRAMIN);
1417                     LOAD_FIXED_STATE_32BPP(nv10,PGRAPH);
1418                     chip->Tri03 = 0L;
1419                     break;
1420                 case 8:
1421                 default:
1422                     LOAD_FIXED_STATE_8BPP(nv10,PRAMIN);
1423                     LOAD_FIXED_STATE_8BPP(nv10,PGRAPH);
1424                     chip->Tri03 = 0L;
1425                     break;
1426             }
1427
1428             if (chip->Architecture == NV_ARCH_10) {
1429                 chip->PGRAPH[0x00000640/4] = state->offset0;
1430                 chip->PGRAPH[0x00000644/4] = state->offset1;
1431                 chip->PGRAPH[0x00000648/4] = state->offset2;
1432                 chip->PGRAPH[0x0000064C/4] = state->offset3;
1433                 chip->PGRAPH[0x00000670/4] = state->pitch0;
1434                 chip->PGRAPH[0x00000674/4] = state->pitch1;
1435                 chip->PGRAPH[0x00000678/4] = state->pitch2;
1436                 chip->PGRAPH[0x0000067C/4] = state->pitch3;
1437                 chip->PGRAPH[0x00000680/4] = state->pitch3;
1438             } else {
1439                 chip->PGRAPH[0x00000820/4] = state->offset0;
1440                 chip->PGRAPH[0x00000824/4] = state->offset1;
1441                 chip->PGRAPH[0x00000828/4] = state->offset2;
1442                 chip->PGRAPH[0x0000082C/4] = state->offset3;
1443                 chip->PGRAPH[0x00000850/4] = state->pitch0;
1444                 chip->PGRAPH[0x00000854/4] = state->pitch1;
1445                 chip->PGRAPH[0x00000858/4] = state->pitch2;
1446                 chip->PGRAPH[0x0000085C/4] = state->pitch3;
1447                 chip->PGRAPH[0x00000860/4] = state->pitch3;
1448                 chip->PGRAPH[0x00000864/4] = state->pitch3;
1449                 chip->PGRAPH[0x000009A4/4] = chip->PFB[0x00000200/4];
1450                 chip->PGRAPH[0x000009A8/4] = chip->PFB[0x00000204/4];
1451             }
1452             chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
1453             chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
1454             chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4];
1455             chip->PGRAPH[0x00000B0C/4] = chip->PFB[0x0000024C/4];
1456             chip->PGRAPH[0x00000B10/4] = chip->PFB[0x00000250/4];
1457             chip->PGRAPH[0x00000B14/4] = chip->PFB[0x00000254/4];
1458             chip->PGRAPH[0x00000B18/4] = chip->PFB[0x00000258/4];
1459             chip->PGRAPH[0x00000B1C/4] = chip->PFB[0x0000025C/4];
1460             chip->PGRAPH[0x00000B20/4] = chip->PFB[0x00000260/4];
1461             chip->PGRAPH[0x00000B24/4] = chip->PFB[0x00000264/4];
1462             chip->PGRAPH[0x00000B28/4] = chip->PFB[0x00000268/4];
1463             chip->PGRAPH[0x00000B2C/4] = chip->PFB[0x0000026C/4];
1464             chip->PGRAPH[0x00000B30/4] = chip->PFB[0x00000270/4];
1465             chip->PGRAPH[0x00000B34/4] = chip->PFB[0x00000274/4];
1466             chip->PGRAPH[0x00000B38/4] = chip->PFB[0x00000278/4];
1467             chip->PGRAPH[0x00000B3C/4] = chip->PFB[0x0000027C/4];
1468             chip->PGRAPH[0x00000B40/4] = chip->PFB[0x00000280/4];
1469             chip->PGRAPH[0x00000B44/4] = chip->PFB[0x00000284/4];
1470             chip->PGRAPH[0x00000B48/4] = chip->PFB[0x00000288/4];
1471             chip->PGRAPH[0x00000B4C/4] = chip->PFB[0x0000028C/4];
1472             chip->PGRAPH[0x00000B50/4] = chip->PFB[0x00000290/4];
1473             chip->PGRAPH[0x00000B54/4] = chip->PFB[0x00000294/4];
1474             chip->PGRAPH[0x00000B58/4] = chip->PFB[0x00000298/4];
1475             chip->PGRAPH[0x00000B5C/4] = chip->PFB[0x0000029C/4];
1476             chip->PGRAPH[0x00000B60/4] = chip->PFB[0x000002A0/4];
1477             chip->PGRAPH[0x00000B64/4] = chip->PFB[0x000002A4/4];
1478             chip->PGRAPH[0x00000B68/4] = chip->PFB[0x000002A8/4];
1479             chip->PGRAPH[0x00000B6C/4] = chip->PFB[0x000002AC/4];
1480             chip->PGRAPH[0x00000B70/4] = chip->PFB[0x000002B0/4];
1481             chip->PGRAPH[0x00000B74/4] = chip->PFB[0x000002B4/4];
1482             chip->PGRAPH[0x00000B78/4] = chip->PFB[0x000002B8/4];
1483             chip->PGRAPH[0x00000B7C/4] = chip->PFB[0x000002BC/4];
1484             chip->PGRAPH[0x00000F40/4] = 0x10000000;
1485             chip->PGRAPH[0x00000F44/4] = 0x00000000;
1486             chip->PGRAPH[0x00000F50/4] = 0x00000040;
1487             chip->PGRAPH[0x00000F54/4] = 0x00000008;
1488             chip->PGRAPH[0x00000F50/4] = 0x00000200;
1489             for (i = 0; i < (3*16); i++)
1490                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1491             chip->PGRAPH[0x00000F50/4] = 0x00000040;
1492             chip->PGRAPH[0x00000F54/4] = 0x00000000;
1493             chip->PGRAPH[0x00000F50/4] = 0x00000800;
1494             for (i = 0; i < (16*16); i++)
1495                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1496             chip->PGRAPH[0x00000F40/4] = 0x30000000;
1497             chip->PGRAPH[0x00000F44/4] = 0x00000004;
1498             chip->PGRAPH[0x00000F50/4] = 0x00006400;
1499             for (i = 0; i < (59*4); i++)
1500                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1501             chip->PGRAPH[0x00000F50/4] = 0x00006800;
1502             for (i = 0; i < (47*4); i++)
1503                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1504             chip->PGRAPH[0x00000F50/4] = 0x00006C00;
1505             for (i = 0; i < (3*4); i++)
1506                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1507             chip->PGRAPH[0x00000F50/4] = 0x00007000;
1508             for (i = 0; i < (19*4); i++)
1509                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1510             chip->PGRAPH[0x00000F50/4] = 0x00007400;
1511             for (i = 0; i < (12*4); i++)
1512                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1513             chip->PGRAPH[0x00000F50/4] = 0x00007800;
1514             for (i = 0; i < (12*4); i++)
1515                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1516             chip->PGRAPH[0x00000F50/4] = 0x00004400;
1517             for (i = 0; i < (8*4); i++)
1518                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1519             chip->PGRAPH[0x00000F50/4] = 0x00000000;
1520             for (i = 0; i < 16; i++)
1521                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1522             chip->PGRAPH[0x00000F50/4] = 0x00000040;
1523             for (i = 0; i < 4; i++)
1524                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
1525             break;
1526     }
1527     LOAD_FIXED_STATE(Riva,FIFO);
1528     UpdateFifoState(chip);
1529     /*
1530      * Load HW mode state.
1531      */
1532     VGA_WR08(chip->PCIO, 0x03D4, 0x19);
1533     VGA_WR08(chip->PCIO, 0x03D5, state->repaint0);
1534     VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
1535     VGA_WR08(chip->PCIO, 0x03D5, state->repaint1);
1536     VGA_WR08(chip->PCIO, 0x03D4, 0x25);
1537     VGA_WR08(chip->PCIO, 0x03D5, state->screen);
1538     VGA_WR08(chip->PCIO, 0x03D4, 0x28);
1539     VGA_WR08(chip->PCIO, 0x03D5, state->pixel);
1540     VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
1541     VGA_WR08(chip->PCIO, 0x03D5, state->horiz);
1542     VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
1543     VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0);
1544     VGA_WR08(chip->PCIO, 0x03D4, 0x20);
1545     VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1);
1546     VGA_WR08(chip->PCIO, 0x03D4, 0x30);
1547     VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
1548     VGA_WR08(chip->PCIO, 0x03D4, 0x31);
1549     VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
1550     chip->PRAMDAC[0x00000300/4]  = state->cursor2;
1551     chip->PRAMDAC[0x00000508/4]  = state->vpll;
1552     chip->PRAMDAC[0x0000050C/4]  = state->pllsel;
1553     chip->PRAMDAC[0x00000600/4]  = state->general;
1554     /*
1555      * Turn off VBlank enable and reset.
1556      */
1557     *(chip->VBLANKENABLE) = 0;
1558     *(chip->VBLANK)       = chip->VBlankBit;
1559     /*
1560      * Set interrupt enable.
1561      */    
1562     chip->PMC[0x00000140/4]  = chip->EnableIRQ & 0x01;
1563     /*
1564      * Set current state pointer.
1565      */
1566     chip->CurrentState = state;
1567     /*
1568      * Reset FIFO free and empty counts.
1569      */
1570     chip->FifoFreeCount  = 0;
1571     /* Free count from first subchannel */
1572     chip->FifoEmptyCount = chip->Rop->FifoFree; 
1573 }
1574 static void UnloadStateExt
1575 (
1576     RIVA_HW_INST  *chip,
1577     RIVA_HW_STATE *state
1578 )
1579 {
1580     /*
1581      * Save current HW state.
1582      */
1583     VGA_WR08(chip->PCIO, 0x03D4, 0x19);
1584     state->repaint0     = VGA_RD08(chip->PCIO, 0x03D5);
1585     VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
1586     state->repaint1     = VGA_RD08(chip->PCIO, 0x03D5);
1587     VGA_WR08(chip->PCIO, 0x03D4, 0x25);
1588     state->screen       = VGA_RD08(chip->PCIO, 0x03D5);
1589     VGA_WR08(chip->PCIO, 0x03D4, 0x28);
1590     state->pixel        = VGA_RD08(chip->PCIO, 0x03D5);
1591     VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
1592     state->horiz        = VGA_RD08(chip->PCIO, 0x03D5);
1593     VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
1594     state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5);
1595     VGA_WR08(chip->PCIO, 0x03D4, 0x20);
1596     state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5);
1597     VGA_WR08(chip->PCIO, 0x03D4, 0x30);
1598     state->cursor0      = VGA_RD08(chip->PCIO, 0x03D5);
1599     VGA_WR08(chip->PCIO, 0x03D4, 0x31);
1600     state->cursor1      = VGA_RD08(chip->PCIO, 0x03D5);
1601     state->cursor2      = chip->PRAMDAC[0x00000300/4];
1602     state->vpll         = chip->PRAMDAC[0x00000508/4];
1603     state->pllsel       = chip->PRAMDAC[0x0000050C/4];
1604     state->general      = chip->PRAMDAC[0x00000600/4];
1605     state->config       = chip->PFB[0x00000200/4];
1606     switch (chip->Architecture)
1607     {
1608         case NV_ARCH_03:
1609             state->offset0  = chip->PGRAPH[0x00000630/4];
1610             state->offset1  = chip->PGRAPH[0x00000634/4];
1611             state->offset2  = chip->PGRAPH[0x00000638/4];
1612             state->offset3  = chip->PGRAPH[0x0000063C/4];
1613             state->pitch0   = chip->PGRAPH[0x00000650/4];
1614             state->pitch1   = chip->PGRAPH[0x00000654/4];
1615             state->pitch2   = chip->PGRAPH[0x00000658/4];
1616             state->pitch3   = chip->PGRAPH[0x0000065C/4];
1617             break;
1618         case NV_ARCH_04:
1619             state->offset0  = chip->PGRAPH[0x00000640/4];
1620             state->offset1  = chip->PGRAPH[0x00000644/4];
1621             state->offset2  = chip->PGRAPH[0x00000648/4];
1622             state->offset3  = chip->PGRAPH[0x0000064C/4];
1623             state->pitch0   = chip->PGRAPH[0x00000670/4];
1624             state->pitch1   = chip->PGRAPH[0x00000674/4];
1625             state->pitch2   = chip->PGRAPH[0x00000678/4];
1626             state->pitch3   = chip->PGRAPH[0x0000067C/4];
1627             break;
1628         case NV_ARCH_10:
1629         case NV_ARCH_20:
1630             state->offset0  = chip->PGRAPH[0x00000640/4];
1631             state->offset1  = chip->PGRAPH[0x00000644/4];
1632             state->offset2  = chip->PGRAPH[0x00000648/4];
1633             state->offset3  = chip->PGRAPH[0x0000064C/4];
1634             state->pitch0   = chip->PGRAPH[0x00000670/4];
1635             state->pitch1   = chip->PGRAPH[0x00000674/4];
1636             state->pitch2   = chip->PGRAPH[0x00000678/4];
1637             state->pitch3   = chip->PGRAPH[0x0000067C/4];
1638             break;
1639     }
1640 }
1641 static void SetStartAddress
1642 (
1643     RIVA_HW_INST *chip,
1644     unsigned      start
1645 )
1646 {
1647     int offset = start >> 2;
1648     int pan    = (start & 3) << 1;
1649     unsigned char tmp;
1650
1651     /*
1652      * Unlock extended registers.
1653      */
1654     chip->LockUnlock(chip, 0);
1655     /*
1656      * Set start address.
1657      */
1658     VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset);
1659     offset >>= 8;
1660     VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset);
1661     offset >>= 8;
1662     VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5);
1663     VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F));
1664     VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5);
1665     VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60));
1666     /*
1667      * 4 pixel pan register.
1668      */
1669     offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A);
1670     VGA_WR08(chip->PCIO, 0x3C0, 0x13);
1671     VGA_WR08(chip->PCIO, 0x3C0, pan);
1672 }
1673 static void nv3SetSurfaces2D
1674 (
1675     RIVA_HW_INST *chip,
1676     unsigned     surf0,
1677     unsigned     surf1
1678 )
1679 {
1680     RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1681
1682     RIVA_FIFO_FREE(*chip,Tri03,5);
1683     chip->FIFO[0x00003800] = 0x80000003;
1684     Surface->Offset        = surf0;
1685     chip->FIFO[0x00003800] = 0x80000004;
1686     Surface->Offset        = surf1;
1687     chip->FIFO[0x00003800] = 0x80000013;
1688 }
1689 static void nv4SetSurfaces2D
1690 (
1691     RIVA_HW_INST *chip,
1692     unsigned     surf0,
1693     unsigned     surf1
1694 )
1695 {
1696     RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1697
1698     chip->FIFO[0x00003800] = 0x80000003;
1699     Surface->Offset        = surf0;
1700     chip->FIFO[0x00003800] = 0x80000004;
1701     Surface->Offset        = surf1;
1702     chip->FIFO[0x00003800] = 0x80000014;
1703 }
1704 static void nv10SetSurfaces2D
1705 (
1706     RIVA_HW_INST *chip,
1707     unsigned     surf0,
1708     unsigned     surf1
1709 )
1710 {
1711     RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1712
1713     chip->FIFO[0x00003800] = 0x80000003;
1714     Surface->Offset        = surf0;
1715     chip->FIFO[0x00003800] = 0x80000004;
1716     Surface->Offset        = surf1;
1717     chip->FIFO[0x00003800] = 0x80000014;
1718 }
1719 static void nv3SetSurfaces3D
1720 (
1721     RIVA_HW_INST *chip,
1722     unsigned     surf0,
1723     unsigned     surf1
1724 )
1725 {
1726     RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1727
1728     RIVA_FIFO_FREE(*chip,Tri03,5);
1729     chip->FIFO[0x00003800] = 0x80000005;
1730     Surface->Offset        = surf0;
1731     chip->FIFO[0x00003800] = 0x80000006;
1732     Surface->Offset        = surf1;
1733     chip->FIFO[0x00003800] = 0x80000013;
1734 }
1735 static void nv4SetSurfaces3D
1736 (
1737     RIVA_HW_INST *chip,
1738     unsigned     surf0,
1739     unsigned     surf1
1740 )
1741 {
1742     RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
1743
1744     chip->FIFO[0x00003800] = 0x80000005;
1745     Surface->Offset        = surf0;
1746     chip->FIFO[0x00003800] = 0x80000006;
1747     Surface->Offset        = surf1;
1748     chip->FIFO[0x00003800] = 0x80000014;
1749 }
1750 static void nv10SetSurfaces3D
1751 (
1752     RIVA_HW_INST *chip,
1753     unsigned     surf0,
1754     unsigned     surf1
1755 )
1756 {
1757     RivaSurface3D *Surfaces3D = (RivaSurface3D *)&(chip->FIFO[0x0000E000/4]);
1758
1759     RIVA_FIFO_FREE(*chip,Tri03,4);
1760     chip->FIFO[0x00003800]         = 0x80000007;
1761     Surfaces3D->RenderBufferOffset = surf0;
1762     Surfaces3D->ZBufferOffset      = surf1;
1763     chip->FIFO[0x00003800]         = 0x80000014;
1764 }
1765
1766 /****************************************************************************\
1767 *                                                                            *
1768 *                      Probe RIVA Chip Configuration                         *
1769 *                                                                            *
1770 \****************************************************************************/
1771
1772 static void nv3GetConfig
1773 (
1774     RIVA_HW_INST *chip
1775 )
1776 {
1777     /*
1778      * Fill in chip configuration.
1779      */
1780     if (chip->PFB[0x00000000/4] & 0x00000020)
1781     {
1782         if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20)
1783          && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02))
1784         {        
1785             /*
1786              * SDRAM 128 ZX.
1787              */
1788             chip->RamBandwidthKBytesPerSec = 800000;
1789             switch (chip->PFB[0x00000000/4] & 0x03)
1790             {
1791                 case 2:
1792                     chip->RamAmountKBytes = 1024 * 4;
1793                     break;
1794                 case 1:
1795                     chip->RamAmountKBytes = 1024 * 2;
1796                     break;
1797                 default:
1798                     chip->RamAmountKBytes = 1024 * 8;
1799                     break;
1800             }
1801         }            
1802         else            
1803         {
1804             chip->RamBandwidthKBytesPerSec = 1000000;
1805             chip->RamAmountKBytes          = 1024 * 8;
1806         }            
1807     }
1808     else
1809     {
1810         /*
1811          * SGRAM 128.
1812          */
1813         chip->RamBandwidthKBytesPerSec = 1000000;
1814         switch (chip->PFB[0x00000000/4] & 0x00000003)
1815         {
1816             case 0:
1817                 chip->RamAmountKBytes = 1024 * 8;
1818                 break;
1819             case 2:
1820                 chip->RamAmountKBytes = 1024 * 4;
1821                 break;
1822             default:
1823                 chip->RamAmountKBytes = 1024 * 2;
1824                 break;
1825         }
1826     }        
1827     chip->CrystalFreqKHz   = (chip->PEXTDEV[0x00000000/4] & 0x00000020) ? 14318 : 13500;
1828     chip->CURSOR           = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]);
1829     chip->CURSORPOS        = &(chip->PRAMDAC[0x0300/4]);
1830     chip->VBLANKENABLE     = &(chip->PGRAPH[0x0140/4]);
1831     chip->VBLANK           = &(chip->PGRAPH[0x0100/4]);
1832     chip->VBlankBit        = 0x00000100;
1833     chip->MaxVClockFreqKHz = 256000;
1834     /*
1835      * Set chip functions.
1836      */
1837     chip->Busy            = nv3Busy;
1838     chip->ShowHideCursor  = ShowHideCursor;
1839     chip->CalcStateExt    = CalcStateExt;
1840     chip->LoadStateExt    = LoadStateExt;
1841     chip->UnloadStateExt  = UnloadStateExt;
1842     chip->SetStartAddress = SetStartAddress;
1843     chip->SetSurfaces2D   = nv3SetSurfaces2D;
1844     chip->SetSurfaces3D   = nv3SetSurfaces3D;
1845     chip->LockUnlock      = nv3LockUnlock;
1846 }
1847 static void nv4GetConfig
1848 (
1849     RIVA_HW_INST *chip
1850 )
1851 {
1852     /*
1853      * Fill in chip configuration.
1854      */
1855     if (chip->PFB[0x00000000/4] & 0x00000100)
1856     {
1857         chip->RamAmountKBytes = ((chip->PFB[0x00000000/4] >> 12) & 0x0F) * 1024 * 2
1858                               + 1024 * 2;
1859     }
1860     else
1861     {
1862         switch (chip->PFB[0x00000000/4] & 0x00000003)
1863         {
1864             case 0:
1865                 chip->RamAmountKBytes = 1024 * 32;
1866                 break;
1867             case 1:
1868                 chip->RamAmountKBytes = 1024 * 4;
1869                 break;
1870             case 2:
1871                 chip->RamAmountKBytes = 1024 * 8;
1872                 break;
1873             case 3:
1874             default:
1875                 chip->RamAmountKBytes = 1024 * 16;
1876                 break;
1877         }
1878     }
1879     switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
1880     {
1881         case 3:
1882             chip->RamBandwidthKBytesPerSec = 800000;
1883             break;
1884         default:
1885             chip->RamBandwidthKBytesPerSec = 1000000;
1886             break;
1887     }
1888     chip->CrystalFreqKHz   = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
1889     chip->CURSOR           = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
1890     chip->CURSORPOS        = &(chip->PRAMDAC[0x0300/4]);
1891     chip->VBLANKENABLE     = &(chip->PCRTC[0x0140/4]);
1892     chip->VBLANK           = &(chip->PCRTC[0x0100/4]);
1893     chip->VBlankBit        = 0x00000001;
1894     chip->MaxVClockFreqKHz = 350000;
1895     /*
1896      * Set chip functions.
1897      */
1898     chip->Busy            = nv4Busy;
1899     chip->ShowHideCursor  = ShowHideCursor;
1900     chip->CalcStateExt    = CalcStateExt;
1901     chip->LoadStateExt    = LoadStateExt;
1902     chip->UnloadStateExt  = UnloadStateExt;
1903     chip->SetStartAddress = SetStartAddress;
1904     chip->SetSurfaces2D   = nv4SetSurfaces2D;
1905     chip->SetSurfaces3D   = nv4SetSurfaces3D;
1906     chip->LockUnlock      = nv4LockUnlock;
1907 }
1908 static void nv10GetConfig
1909 (
1910     RIVA_HW_INST *chip
1911 )
1912 {
1913     /*
1914      * Fill in chip configuration.
1915      */
1916     switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF)
1917     {
1918         case 0x02:
1919             chip->RamAmountKBytes = 1024 * 2;
1920             break;
1921         case 0x04:
1922             chip->RamAmountKBytes = 1024 * 4;
1923             break;
1924         case 0x08:
1925             chip->RamAmountKBytes = 1024 * 8;
1926             break;
1927         case 0x10:
1928             chip->RamAmountKBytes = 1024 * 16;
1929             break;
1930         case 0x20:
1931             chip->RamAmountKBytes = 1024 * 32;
1932             break;
1933         case 0x40:
1934             chip->RamAmountKBytes = 1024 * 64;
1935             break;
1936         case 0x80:
1937             chip->RamAmountKBytes = 1024 * 128;
1938             break;
1939         default:
1940             chip->RamAmountKBytes = 1024 * 16;
1941             break;
1942     }
1943     switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
1944     {
1945         case 3:
1946             chip->RamBandwidthKBytesPerSec = 800000;
1947             break;
1948         default:
1949             chip->RamBandwidthKBytesPerSec = 1000000;
1950             break;
1951     }
1952     chip->CrystalFreqKHz   = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
1953     chip->CURSOR           = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
1954     chip->CURSORPOS        = &(chip->PRAMDAC[0x0300/4]);
1955     chip->VBLANKENABLE     = &(chip->PCRTC[0x0140/4]);
1956     chip->VBLANK           = &(chip->PCRTC[0x0100/4]);
1957     chip->VBlankBit        = 0x00000001;
1958     chip->MaxVClockFreqKHz = 350000;
1959     /*
1960      * Set chip functions.
1961      */
1962     chip->Busy            = nv10Busy;
1963     chip->ShowHideCursor  = ShowHideCursor;
1964     chip->CalcStateExt    = CalcStateExt;
1965     chip->LoadStateExt    = LoadStateExt;
1966     chip->UnloadStateExt  = UnloadStateExt;
1967     chip->SetStartAddress = SetStartAddress;
1968     chip->SetSurfaces2D   = nv10SetSurfaces2D;
1969     chip->SetSurfaces3D   = nv10SetSurfaces3D;
1970     chip->LockUnlock      = nv10LockUnlock;
1971 }
1972 int RivaGetConfig
1973 (
1974     RIVA_HW_INST *chip
1975 )
1976 {
1977     /*
1978      * Save this so future SW know whats it's dealing with.
1979      */
1980     chip->Version = RIVA_SW_VERSION;
1981     /*
1982      * Chip specific configuration.
1983      */
1984     switch (chip->Architecture)
1985     {
1986         case NV_ARCH_03:
1987             nv3GetConfig(chip);
1988             break;
1989         case NV_ARCH_04:
1990             nv4GetConfig(chip);
1991             break;
1992         case NV_ARCH_10:
1993         case NV_ARCH_20:
1994             nv10GetConfig(chip);
1995             break;
1996         default:
1997             return (-1);
1998     }
1999     /*
2000      * Fill in FIFO pointers.
2001      */
2002     chip->Rop    = (RivaRop                 *)&(chip->FIFO[0x00000000/4]);
2003     chip->Clip   = (RivaClip                *)&(chip->FIFO[0x00002000/4]);
2004     chip->Patt   = (RivaPattern             *)&(chip->FIFO[0x00004000/4]);
2005     chip->Pixmap = (RivaPixmap              *)&(chip->FIFO[0x00006000/4]);
2006     chip->Blt    = (RivaScreenBlt           *)&(chip->FIFO[0x00008000/4]);
2007     chip->Bitmap = (RivaBitmap              *)&(chip->FIFO[0x0000A000/4]);
2008     chip->Line   = (RivaLine                *)&(chip->FIFO[0x0000C000/4]);
2009     chip->Tri03  = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
2010     return (0);
2011 }
2012