Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright (c) 1993-1999 NVIDIA, Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the
      6  * "Software"), to deal in the Software without restriction, including
      7  * without limitation the rights to use, copy, modify, merge, publish,
      8  * distribute, sublicense, and/or sell copies of the Software, and to
      9  * permit persons to whom the Software is furnished to do so, subject to
     10  * the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be included
     13  * in all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     22  */
     23 
     24 #ifdef HAVE_CONFIG_H
     25 #include "config.h"
     26 #endif
     27 
     28 #include "riva_local.h"
     29 #include "compiler.h"
     30 #include "riva_include.h"
     31 #include "riva_hw.h"
     32 #include "riva_tbl.h"
     33 
     34 /*
     35  * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT
     36  * operate identically (except TNT has more memory and better 3D quality.
     37  */
     38 static int nv3Busy
     39 (
     40     RIVA_HW_INST *chip
     41 )
     42 {
     43     return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x000006B0/4] & 0x01));
     44 }
     45 static void vgaLockUnlock
     46 (
     47     RIVA_HW_INST *chip,
     48     Bool           Lock
     49 )
     50 {
     51     CARD8 cr11;
     52     VGA_WR08(chip->PCIO, 0x3D4, 0x11);
     53     cr11 = VGA_RD08(chip->PCIO, 0x3D5);
     54     if(Lock) cr11 |= 0x80;
     55     else cr11 &= ~0x80;
     56     VGA_WR08(chip->PCIO, 0x3D5, cr11);
     57 }
     58 
     59 static void nv3LockUnlock
     60 (
     61     RIVA_HW_INST *chip,
     62     Bool           Lock
     63 )
     64 {
     65     VGA_WR08(chip->PVIO, 0x3C4, 0x06);
     66     VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57);
     67     vgaLockUnlock(chip, Lock);
     68 }
     69 static int ShowHideCursor
     70 (
     71     RIVA_HW_INST *chip,
     72     int           ShowHide
     73 )
     74 {
     75     int current;
     76     current                     =  chip->CurrentState->cursor1;
     77     chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) |
     78 	                          (ShowHide & 0x01);
     79     VGA_WR08(chip->PCIO, 0x3D4, 0x31);
     80     VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1);
     81     return (current & 0x01);
     82 }
     83 
     84 /****************************************************************************\
     85 *                                                                            *
     86 * The video arbitration routines calculate some "magic" numbers.  Fixes      *
     87 * the snow seen when accessing the framebuffer without it.                   *
     88 * It just works (I hope).                                                    *
     89 *                                                                            *
     90 \****************************************************************************/
     91 
     92 #define DEFAULT_GR_LWM 100
     93 #define DEFAULT_VID_LWM 100
     94 #define DEFAULT_GR_BURST_SIZE 256
     95 #define DEFAULT_VID_BURST_SIZE 128
     96 #define VIDEO		0
     97 #define GRAPHICS	1
     98 #define MPORT		2
     99 #define ENGINE		3
    100 #define GFIFO_SIZE	320
    101 #define GFIFO_SIZE_128	256
    102 #define MFIFO_SIZE	120
    103 #define VFIFO_SIZE	256
    104 #define	ABS(a)	((a) > 0 ? (a) : -(a))
    105 typedef struct {
    106   int gdrain_rate;
    107   int vdrain_rate;
    108   int mdrain_rate;
    109   int gburst_size;
    110   int vburst_size;
    111   char vid_en;
    112   char gr_en;
    113   int wcmocc, wcgocc, wcvocc, wcvlwm, wcglwm;
    114   int by_gfacc;
    115   char vid_only_once;
    116   char gr_only_once;
    117   char first_vacc;
    118   char first_gacc;
    119   char first_macc;
    120   int vocc;
    121   int gocc;
    122   int mocc;
    123   char cur;
    124   char engine_en;
    125   char converged;
    126   int priority;
    127 } nv3_arb_info;
    128 typedef struct {
    129   int graphics_lwm;
    130   int video_lwm;
    131   int graphics_burst_size;
    132   int video_burst_size;
    133   int graphics_hi_priority;
    134   int media_hi_priority;
    135   int rtl_values;
    136   int valid;
    137 } nv3_fifo_info;
    138 typedef struct {
    139   char pix_bpp;
    140   char enable_video;
    141   char gr_during_vid;
    142   char enable_mp;
    143   int memory_width;
    144   int video_scale;
    145   int pclk_khz;
    146   int mclk_khz;
    147   int mem_page_miss;
    148   int mem_latency;
    149   char mem_aligned;
    150 } nv3_sim_state;
    151 static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
    152 {
    153     int iter = 0;
    154     int tmp;
    155     int vfsize, mfsize, gfsize;
    156     int mburst_size = 32;
    157     int mmisses, gmisses, vmisses;
    158     int misses;
    159     int vlwm, glwm;
    160     int last, next, cur;
    161     int max_gfsize ;
    162     long ns;
    163 
    164     vlwm = 0;
    165     glwm = 0;
    166     vfsize = 0;
    167     gfsize = 0;
    168     cur = ainfo->cur;
    169     mmisses = 2;
    170     gmisses = 2;
    171     vmisses = 2;
    172     if (ainfo->gburst_size == 128) max_gfsize = GFIFO_SIZE_128;
    173     else  max_gfsize = GFIFO_SIZE;
    174     max_gfsize = GFIFO_SIZE;
    175     while (1)
    176     {
    177         if (ainfo->vid_en)
    178         {
    179             if (ainfo->wcvocc > ainfo->vocc) ainfo->wcvocc = ainfo->vocc;
    180             if (ainfo->wcvlwm > vlwm) ainfo->wcvlwm = vlwm ;
    181             ns = 1000000 * ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
    182             vfsize = ns * ainfo->vdrain_rate / 1000000;
    183             vfsize =  ainfo->wcvlwm - ainfo->vburst_size + vfsize;
    184         }
    185         if (state->enable_mp)
    186         {
    187             if (ainfo->wcmocc > ainfo->mocc) ainfo->wcmocc = ainfo->mocc;
    188         }
    189         if (ainfo->gr_en)
    190         {
    191             if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ;
    192             if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc;
    193             ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
    194             gfsize = (ns * (long) ainfo->gdrain_rate)/1000000;
    195             gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize;
    196         }
    197         mfsize = 0;
    198         if (!state->gr_during_vid && ainfo->vid_en)
    199             if (ainfo->vid_en && (ainfo->vocc < 0) && !ainfo->vid_only_once)
    200                 next = VIDEO;
    201             else if (ainfo->mocc < 0)
    202                 next = MPORT;
    203             else if (ainfo->gocc< ainfo->by_gfacc)
    204                 next = GRAPHICS;
    205             else return (0);
    206         else switch (ainfo->priority)
    207             {
    208                 case VIDEO:
    209                     if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
    210                         next = VIDEO;
    211                     else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
    212                         next = GRAPHICS;
    213                     else if (ainfo->mocc<0)
    214                         next = MPORT;
    215                     else    return (0);
    216                     break;
    217                 case GRAPHICS:
    218                     if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
    219                         next = GRAPHICS;
    220                     else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
    221                         next = VIDEO;
    222                     else if (ainfo->mocc<0)
    223                         next = MPORT;
    224                     else    return (0);
    225                     break;
    226                 default:
    227                     if (ainfo->mocc<0)
    228                         next = MPORT;
    229                     else if (ainfo->gr_en && ainfo->gocc<0 && !ainfo->gr_only_once)
    230                         next = GRAPHICS;
    231                     else if (ainfo->vid_en && ainfo->vocc<0 && !ainfo->vid_only_once)
    232                         next = VIDEO;
    233                     else    return (0);
    234                     break;
    235             }
    236         last = cur;
    237         cur = next;
    238         iter++;
    239         switch (cur)
    240         {
    241             case VIDEO:
    242                 if (last==cur)    misses = 0;
    243                 else if (ainfo->first_vacc)   misses = vmisses;
    244                 else    misses = 1;
    245                 ainfo->first_vacc = 0;
    246                 if (last!=cur)
    247                 {
    248                     ns =  1000000 * (vmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz;
    249                     vlwm = ns * ainfo->vdrain_rate/ 1000000;
    250                     vlwm = ainfo->vocc - vlwm;
    251                 }
    252                 ns = 1000000*(misses*state->mem_page_miss + ainfo->vburst_size)/(state->memory_width/8)/state->mclk_khz;
    253                 ainfo->vocc = ainfo->vocc + ainfo->vburst_size - ns*ainfo->vdrain_rate/1000000;
    254                 ainfo->gocc = ainfo->gocc - ns*ainfo->gdrain_rate/1000000;
    255                 ainfo->mocc = ainfo->mocc - ns*ainfo->mdrain_rate/1000000;
    256                 break;
    257             case GRAPHICS:
    258                 if (last==cur)    misses = 0;
    259                 else if (ainfo->first_gacc)   misses = gmisses;
    260                 else    misses = 1;
    261                 ainfo->first_gacc = 0;
    262                 if (last!=cur)
    263                 {
    264                     ns = 1000000*(gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz ;
    265                     glwm = ns * ainfo->gdrain_rate/1000000;
    266                     glwm = ainfo->gocc - glwm;
    267                 }
    268                 ns = 1000000*(misses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
    269                 ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
    270                 ainfo->gocc = ainfo->gocc + ainfo->gburst_size - ns*ainfo->gdrain_rate/1000000;
    271                 ainfo->mocc = ainfo->mocc + 0 - ns*ainfo->mdrain_rate/1000000;
    272                 break;
    273             default:
    274                 if (last==cur)    misses = 0;
    275                 else if (ainfo->first_macc)   misses = mmisses;
    276                 else    misses = 1;
    277                 ainfo->first_macc = 0;
    278                 ns = 1000000*(misses*state->mem_page_miss + mburst_size/(state->memory_width/8))/state->mclk_khz;
    279                 ainfo->vocc = ainfo->vocc + 0 - ns*ainfo->vdrain_rate/1000000;
    280                 ainfo->gocc = ainfo->gocc + 0 - ns*ainfo->gdrain_rate/1000000;
    281                 ainfo->mocc = ainfo->mocc + mburst_size - ns*ainfo->mdrain_rate/1000000;
    282                 break;
    283         }
    284         if (iter>100)
    285         {
    286             ainfo->converged = 0;
    287             return (1);
    288         }
    289         ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz;
    290         tmp = ns * ainfo->gdrain_rate/1000000;
    291         if (ABS(ainfo->gburst_size) + ((ABS(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize)
    292         {
    293             ainfo->converged = 0;
    294             return (1);
    295         }
    296         ns = 1000000*ainfo->vburst_size/(state->memory_width/8)/state->mclk_khz;
    297         tmp = ns * ainfo->vdrain_rate/1000000;
    298         if (ABS(ainfo->vburst_size) + (ABS(ainfo->wcvlwm + 32) & ~0xf)  - tmp> VFIFO_SIZE)
    299         {
    300             ainfo->converged = 0;
    301             return (1);
    302         }
    303         if (ABS(ainfo->gocc) > max_gfsize)
    304         {
    305             ainfo->converged = 0;
    306             return (1);
    307         }
    308         if (ABS(ainfo->vocc) > VFIFO_SIZE)
    309         {
    310             ainfo->converged = 0;
    311             return (1);
    312         }
    313         if (ABS(ainfo->mocc) > MFIFO_SIZE)
    314         {
    315             ainfo->converged = 0;
    316             return (1);
    317         }
    318         if (ABS(vfsize) > VFIFO_SIZE)
    319         {
    320             ainfo->converged = 0;
    321             return (1);
    322         }
    323         if (ABS(gfsize) > max_gfsize)
    324         {
    325             ainfo->converged = 0;
    326             return (1);
    327         }
    328         if (ABS(mfsize) > MFIFO_SIZE)
    329         {
    330             ainfo->converged = 0;
    331             return (1);
    332         }
    333     }
    334 }
    335 static char nv3_arb(nv3_fifo_info * res_info, nv3_sim_state * state,  nv3_arb_info *ainfo)
    336 {
    337     long ens, vns, mns, gns;
    338     int mmisses, gmisses, vmisses, eburst_size, mburst_size;
    339     int refresh_cycle;
    340 
    341     refresh_cycle = 0;
    342     refresh_cycle = 2*(state->mclk_khz/state->pclk_khz) + 5;
    343     mmisses = 2;
    344     if (state->mem_aligned) gmisses = 2;
    345     else    gmisses = 3;
    346     vmisses = 2;
    347     eburst_size = state->memory_width * 1;
    348     mburst_size = 32;
    349     gns = 1000000 * (gmisses*state->mem_page_miss + state->mem_latency)/state->mclk_khz;
    350     ainfo->by_gfacc = gns*ainfo->gdrain_rate/1000000;
    351     ainfo->wcmocc = 0;
    352     ainfo->wcgocc = 0;
    353     ainfo->wcvocc = 0;
    354     ainfo->wcvlwm = 0;
    355     ainfo->wcglwm = 0;
    356     ainfo->engine_en = 1;
    357     ainfo->converged = 1;
    358     if (ainfo->engine_en)
    359     {
    360         ens =  1000000*(state->mem_page_miss + eburst_size/(state->memory_width/8) +refresh_cycle)/state->mclk_khz;
    361         ainfo->mocc = state->enable_mp ? 0-ens*ainfo->mdrain_rate/1000000 : 0;
    362         ainfo->vocc = ainfo->vid_en ? 0-ens*ainfo->vdrain_rate/1000000 : 0;
    363         ainfo->gocc = ainfo->gr_en ? 0-ens*ainfo->gdrain_rate/1000000 : 0;
    364         ainfo->cur = ENGINE;
    365         ainfo->first_vacc = 1;
    366         ainfo->first_gacc = 1;
    367         ainfo->first_macc = 1;
    368         nv3_iterate(res_info, state,ainfo);
    369     }
    370     if (state->enable_mp)
    371     {
    372         mns = 1000000 * (mmisses*state->mem_page_miss + mburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
    373         ainfo->mocc = state->enable_mp ? 0 : mburst_size - mns*ainfo->mdrain_rate/1000000;
    374         ainfo->vocc = ainfo->vid_en ? 0 : 0- mns*ainfo->vdrain_rate/1000000;
    375         ainfo->gocc = ainfo->gr_en ? 0: 0- mns*ainfo->gdrain_rate/1000000;
    376         ainfo->cur = MPORT;
    377         ainfo->first_vacc = 1;
    378         ainfo->first_gacc = 1;
    379         ainfo->first_macc = 0;
    380         nv3_iterate(res_info, state,ainfo);
    381     }
    382     if (ainfo->gr_en)
    383     {
    384         ainfo->first_vacc = 1;
    385         ainfo->first_gacc = 0;
    386         ainfo->first_macc = 1;
    387         gns = 1000000*(gmisses*state->mem_page_miss + ainfo->gburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
    388         ainfo->gocc = ainfo->gburst_size - gns*ainfo->gdrain_rate/1000000;
    389         ainfo->vocc = ainfo->vid_en? 0-gns*ainfo->vdrain_rate/1000000 : 0;
    390         ainfo->mocc = state->enable_mp ?  0-gns*ainfo->mdrain_rate/1000000: 0;
    391         ainfo->cur = GRAPHICS;
    392         nv3_iterate(res_info, state,ainfo);
    393     }
    394     if (ainfo->vid_en)
    395     {
    396         ainfo->first_vacc = 0;
    397         ainfo->first_gacc = 1;
    398         ainfo->first_macc = 1;
    399         vns = 1000000*(vmisses*state->mem_page_miss + ainfo->vburst_size/(state->memory_width/8) + refresh_cycle)/state->mclk_khz;
    400         ainfo->vocc = ainfo->vburst_size - vns*ainfo->vdrain_rate/1000000;
    401         ainfo->gocc = ainfo->gr_en? (0-vns*ainfo->gdrain_rate/1000000) : 0;
    402         ainfo->mocc = state->enable_mp? 0-vns*ainfo->mdrain_rate/1000000 :0 ;
    403         ainfo->cur = VIDEO;
    404         nv3_iterate(res_info, state, ainfo);
    405     }
    406     if (ainfo->converged)
    407     {
    408         res_info->graphics_lwm = (int)ABS(ainfo->wcglwm) + 16;
    409         res_info->video_lwm = (int)ABS(ainfo->wcvlwm) + 32;
    410         res_info->graphics_burst_size = ainfo->gburst_size;
    411         res_info->video_burst_size = ainfo->vburst_size;
    412         res_info->graphics_hi_priority = (ainfo->priority == GRAPHICS);
    413         res_info->media_hi_priority = (ainfo->priority == MPORT);
    414         if (res_info->video_lwm > 160)
    415         {
    416             res_info->graphics_lwm = 256;
    417             res_info->video_lwm = 128;
    418             res_info->graphics_burst_size = 64;
    419             res_info->video_burst_size = 64;
    420             res_info->graphics_hi_priority = 0;
    421             res_info->media_hi_priority = 0;
    422             ainfo->converged = 0;
    423             return (0);
    424         }
    425         if (res_info->video_lwm > 128)
    426         {
    427             res_info->video_lwm = 128;
    428         }
    429         return (1);
    430     }
    431     else
    432     {
    433         res_info->graphics_lwm = 256;
    434         res_info->video_lwm = 128;
    435         res_info->graphics_burst_size = 64;
    436         res_info->video_burst_size = 64;
    437         res_info->graphics_hi_priority = 0;
    438         res_info->media_hi_priority = 0;
    439         return (0);
    440     }
    441 }
    442 static char nv3_get_param(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
    443 {
    444     int done, g,v, p;
    445 
    446     done = 0;
    447     for (p=0; p < 2; p++)
    448     {
    449         for (g=128 ; g > 32; g= g>> 1)
    450         {
    451             for (v=128; v >=32; v = v>> 1)
    452             {
    453                 ainfo->priority = p;
    454                 ainfo->gburst_size = g;
    455                 ainfo->vburst_size = v;
    456                 done = nv3_arb(res_info, state,ainfo);
    457                 if (done && (g==128))
    458                     if ((res_info->graphics_lwm + g) > 256)
    459                         done = 0;
    460                 if (done)
    461                     goto Done;
    462             }
    463         }
    464     }
    465 
    466  Done:
    467     return done;
    468 }
    469 static void nv3CalcArbitration
    470 (
    471     nv3_fifo_info * res_info,
    472     nv3_sim_state * state
    473 )
    474 {
    475     nv3_fifo_info save_info;
    476     nv3_arb_info ainfo;
    477     char   res_gr, res_vid;
    478 
    479     ainfo.gr_en = 1;
    480     ainfo.vid_en = state->enable_video;
    481     ainfo.vid_only_once = 0;
    482     ainfo.gr_only_once = 0;
    483     ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
    484     ainfo.vdrain_rate = (int) state->pclk_khz * 2;
    485     if (state->video_scale != 0)
    486         ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale;
    487     ainfo.mdrain_rate = 33000;
    488     res_info->rtl_values = 0;
    489     if (!state->gr_during_vid && state->enable_video)
    490     {
    491         ainfo.gr_only_once = 1;
    492         ainfo.gr_en = 1;
    493         ainfo.gdrain_rate = 0;
    494         res_vid = nv3_get_param(res_info, state,  &ainfo);
    495         res_vid = ainfo.converged;
    496         save_info.video_lwm = res_info->video_lwm;
    497         save_info.video_burst_size = res_info->video_burst_size;
    498         ainfo.vid_en = 1;
    499         ainfo.vid_only_once = 1;
    500         ainfo.gr_en = 1;
    501         ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
    502         ainfo.vdrain_rate = 0;
    503         res_gr = nv3_get_param(res_info, state,  &ainfo);
    504         res_gr = ainfo.converged;
    505         res_info->video_lwm = save_info.video_lwm;
    506         res_info->video_burst_size = save_info.video_burst_size;
    507         res_info->valid = res_gr & res_vid;
    508     }
    509     else
    510     {
    511         if (!ainfo.gr_en) ainfo.gdrain_rate = 0;
    512         if (!ainfo.vid_en) ainfo.vdrain_rate = 0;
    513         res_gr = nv3_get_param(res_info, state,  &ainfo);
    514         res_info->valid = ainfo.converged;
    515     }
    516 }
    517 static void nv3UpdateArbitrationSettings
    518 (
    519     unsigned      VClk,
    520     unsigned      pixelDepth,
    521     unsigned     *burst,
    522     unsigned     *lwm,
    523     RIVA_HW_INST *chip
    524 )
    525 {
    526     nv3_fifo_info fifo_data;
    527     nv3_sim_state sim_data;
    528     unsigned int M, N, P, pll, MClk;
    529 
    530     pll = chip->PRAMDAC[0x00000504/4];
    531     M = (pll >> 0) & 0xFF; N = (pll >> 8) & 0xFF; P = (pll >> 16) & 0x0F;
    532     MClk = (N * chip->CrystalFreqKHz / M) >> P;
    533     sim_data.pix_bpp        = (char)pixelDepth;
    534     sim_data.enable_video   = 0;
    535     sim_data.enable_mp      = 0;
    536     sim_data.video_scale    = 1;
    537     sim_data.memory_width   = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64;
    538     sim_data.memory_width   = 128;
    539 
    540     sim_data.mem_latency    = 9;
    541     sim_data.mem_aligned    = 1;
    542     sim_data.mem_page_miss  = 11;
    543     sim_data.gr_during_vid  = 0;
    544     sim_data.pclk_khz       = VClk;
    545     sim_data.mclk_khz       = MClk;
    546     nv3CalcArbitration(&fifo_data, &sim_data);
    547     if (fifo_data.valid)
    548     {
    549         int  b = fifo_data.graphics_burst_size >> 4;
    550         *burst = 0;
    551         while (b >>= 1) (*burst)++;
    552         *lwm   = fifo_data.graphics_lwm >> 3;
    553     }
    554     else
    555     {
    556         *lwm   = 0x24;
    557         *burst = 0x2;
    558     }
    559 }
    560 
    561 /****************************************************************************\
    562 *                                                                            *
    563 *                          RIVA Mode State Routines                          *
    564 *                                                                            *
    565 \****************************************************************************/
    566 
    567 /*
    568  * Calculate the Video Clock parameters for the PLL.
    569  */
    570 static int CalcVClock
    571 (
    572     int           clockIn,
    573     int          *clockOut,
    574     int          *mOut,
    575     int          *nOut,
    576     int          *pOut,
    577     RIVA_HW_INST *chip
    578 )
    579 {
    580     unsigned lowM, highM, highP;
    581     unsigned DeltaNew, DeltaOld;
    582     unsigned VClk, Freq;
    583     unsigned M, N, P;
    584 
    585     DeltaOld = 0xFFFFFFFF;
    586 
    587     VClk     = (unsigned)clockIn;
    588 
    589     if (chip->CrystalFreqKHz == 13500)
    590     {
    591         lowM  = 7;
    592         highM = 12;
    593     }
    594     else
    595     {
    596         lowM  = 8;
    597         highM = 13;
    598     }
    599 
    600     highP = 3;
    601     for (P = 0; P <= highP; P ++)
    602     {
    603         Freq = VClk << P;
    604         if ((Freq >= 128000) && (Freq <= chip->MaxVClockFreqKHz))
    605         {
    606             for (M = lowM; M <= highM; M++)
    607             {
    608                 N    = (VClk << P) * M / chip->CrystalFreqKHz;
    609                 if(N <= 255) {
    610                     Freq = (chip->CrystalFreqKHz * N / M) >> P;
    611                     if (Freq > VClk)
    612                         DeltaNew = Freq - VClk;
    613                     else
    614                         DeltaNew = VClk - Freq;
    615                     if (DeltaNew < DeltaOld)
    616                     {
    617                         *mOut     = M;
    618                         *nOut     = N;
    619                         *pOut     = P;
    620                         *clockOut = Freq;
    621                         DeltaOld  = DeltaNew;
    622                     }
    623                 }
    624             }
    625         }
    626     }
    627     return (DeltaOld != 0xFFFFFFFF);
    628 }
    629 /*
    630  * Calculate extended mode parameters (SVGA) and save in a
    631  * mode state structure.
    632  */
    633 static void CalcStateExt
    634 (
    635     RIVA_HW_INST  *chip,
    636     RIVA_HW_STATE *state,
    637     int            bpp,
    638     int            width,
    639     int            hDisplaySize,
    640     int            height,
    641     int            dotClock,
    642     int		   flags
    643 )
    644 {
    645     int pixelDepth, VClk = 0, m = 0, n = 0, p = 0;
    646     /*
    647      * Save mode parameters.
    648      */
    649     state->bpp    = bpp;    /* this is not bitsPerPixel, it's 8,15,16,32 */
    650     state->width  = width;
    651     state->height = height;
    652     /*
    653      * Extended RIVA registers.
    654      */
    655     pixelDepth = (bpp + 1)/8;
    656     CalcVClock(dotClock, &VClk, &m, &n, &p, chip);
    657 
    658     nv3UpdateArbitrationSettings(VClk,
    659                                  pixelDepth * 8,
    660                                  &(state->arbitration0),
    661                                  &(state->arbitration1),
    662                                  chip);
    663     state->cursor0  = 0x00;
    664     state->cursor1  = 0x78;
    665     if (flags & V_DBLSCAN)
    666        state->cursor1 |= 2;
    667     state->cursor2  = 0x00000000;
    668     state->pllsel   = 0x10010100;
    669     state->config   = ((width + 31)/32)
    670                       | (((pixelDepth > 2) ? 3 : pixelDepth) << 8)
    671                       | 0x1000;
    672     state->general  = 0x00100100;
    673     state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02;
    674 
    675 
    676     state->vpll     = (p << 16) | (n << 8) | m;
    677     state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
    678     state->pixel    = pixelDepth > 2   ? 3    : pixelDepth;
    679     state->offset   = 0;
    680     state->pitch    = pixelDepth * width;
    681 }
    682 /*
    683  * Load fixed function state and pre-calculated/stored state.
    684  */
    685 #define LOAD_FIXED_STATE(tbl,dev)                                       \
    686     for (i = 0; i < sizeof(tbl##Table##dev)/8; i++)                 \
    687         chip->dev[tbl##Table##dev[i][0]] = tbl##Table##dev[i][1]
    688 #define LOAD_FIXED_STATE_8BPP(tbl,dev)                                  \
    689     for (i = 0; i < sizeof(tbl##Table##dev##_8BPP)/8; i++)            \
    690         chip->dev[tbl##Table##dev##_8BPP[i][0]] = tbl##Table##dev##_8BPP[i][1]
    691 #define LOAD_FIXED_STATE_15BPP(tbl,dev)                                 \
    692     for (i = 0; i < sizeof(tbl##Table##dev##_15BPP)/8; i++)           \
    693         chip->dev[tbl##Table##dev##_15BPP[i][0]] = tbl##Table##dev##_15BPP[i][1]
    694 #define LOAD_FIXED_STATE_16BPP(tbl,dev)                                 \
    695     for (i = 0; i < sizeof(tbl##Table##dev##_16BPP)/8; i++)           \
    696         chip->dev[tbl##Table##dev##_16BPP[i][0]] = tbl##Table##dev##_16BPP[i][1]
    697 #define LOAD_FIXED_STATE_32BPP(tbl,dev)                                 \
    698     for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++)           \
    699         chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1]
    700 static void UpdateFifoState
    701 (
    702     RIVA_HW_INST  *chip
    703 )
    704 {
    705 }
    706 static void LoadStateExt
    707 (
    708     RIVA_HW_INST  *chip,
    709     RIVA_HW_STATE *state
    710 )
    711 {
    712     int i;
    713 
    714     /*
    715      * Load HW fixed function state.
    716      */
    717     LOAD_FIXED_STATE(Riva,PMC);
    718     LOAD_FIXED_STATE(Riva,PTIMER);
    719      /*
    720       * Make sure frame buffer config gets set before loading PRAMIN.
    721       */
    722     chip->PFB[0x00000200/4] = state->config;
    723     LOAD_FIXED_STATE(nv3,PFIFO);
    724     LOAD_FIXED_STATE(nv3,PRAMIN);
    725     LOAD_FIXED_STATE(nv3,PGRAPH);
    726     switch (state->bpp)
    727     {
    728      case 15:
    729      case 16:
    730          LOAD_FIXED_STATE_15BPP(nv3,PRAMIN);
    731          LOAD_FIXED_STATE_15BPP(nv3,PGRAPH);
    732          break;
    733      case 24:
    734      case 32:
    735          LOAD_FIXED_STATE_32BPP(nv3,PRAMIN);
    736          LOAD_FIXED_STATE_32BPP(nv3,PGRAPH);
    737          break;
    738      case 8:
    739      default:
    740          LOAD_FIXED_STATE_8BPP(nv3,PRAMIN);
    741         LOAD_FIXED_STATE_8BPP(nv3,PGRAPH);
    742         break;
    743     }
    744     for (i = 0x00000; i < 0x00800; i++)
    745         chip->PRAMIN[0x00000502 + i] = (i << 12) | 0x03;
    746     chip->PGRAPH[0x00000630/4] = state->offset;
    747     chip->PGRAPH[0x00000634/4] = state->offset;
    748     chip->PGRAPH[0x00000638/4] = state->offset;
    749     chip->PGRAPH[0x0000063C/4] = state->offset;
    750     chip->PGRAPH[0x00000650/4] = state->pitch;
    751     chip->PGRAPH[0x00000654/4] = state->pitch;
    752     chip->PGRAPH[0x00000658/4] = state->pitch;
    753     chip->PGRAPH[0x0000065C/4] = state->pitch;
    754 
    755     LOAD_FIXED_STATE(Riva,FIFO);
    756     UpdateFifoState(chip);
    757 
    758     /*
    759      * Load HW mode state.
    760      */
    761     VGA_WR08(chip->PCIO, 0x03D4, 0x19);
    762     VGA_WR08(chip->PCIO, 0x03D5, state->repaint0);
    763     VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
    764     VGA_WR08(chip->PCIO, 0x03D5, state->repaint1);
    765     VGA_WR08(chip->PCIO, 0x03D4, 0x25);
    766     VGA_WR08(chip->PCIO, 0x03D5, state->screen);
    767     VGA_WR08(chip->PCIO, 0x03D4, 0x28);
    768     VGA_WR08(chip->PCIO, 0x03D5, state->pixel);
    769     VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
    770     VGA_WR08(chip->PCIO, 0x03D5, state->horiz);
    771     VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
    772     VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0);
    773     VGA_WR08(chip->PCIO, 0x03D4, 0x20);
    774     VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1);
    775     VGA_WR08(chip->PCIO, 0x03D4, 0x30);
    776     VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
    777     VGA_WR08(chip->PCIO, 0x03D4, 0x31);
    778     VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
    779     VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
    780     VGA_WR08(chip->PCIO, 0x03D5, state->cursor2);
    781     VGA_WR08(chip->PCIO, 0x03D4, 0x39);
    782     VGA_WR08(chip->PCIO, 0x03D5, state->interlace);
    783 
    784     chip->PRAMDAC[0x00000508/4] = state->vpll;
    785     chip->PRAMDAC[0x0000050C/4] = state->pllsel;
    786     chip->PRAMDAC[0x00000600/4]  = state->general;
    787 
    788     /*
    789      * Turn off VBlank enable and reset.
    790      */
    791     chip->PCRTC[0x00000140/4] = 0;
    792     chip->PCRTC[0x00000100/4] = chip->VBlankBit;
    793     /*
    794      * Set interrupt enable.
    795      */
    796     chip->PMC[0x00000140/4]  = chip->EnableIRQ & 0x01;
    797     /*
    798      * Set current state pointer.
    799      */
    800     chip->CurrentState = state;
    801     /*
    802      * Reset FIFO free and empty counts.
    803      */
    804     chip->FifoFreeCount  = 0;
    805     /* Free count from first subchannel */
    806     chip->FifoEmptyCount = chip->Rop->FifoFree;
    807 }
    808 
    809 static void UnloadStateExt
    810 (
    811     RIVA_HW_INST  *chip,
    812     RIVA_HW_STATE *state
    813 )
    814 {
    815     /*
    816      * Save current HW state.
    817      */
    818     VGA_WR08(chip->PCIO, 0x03D4, 0x19);
    819     state->repaint0     = VGA_RD08(chip->PCIO, 0x03D5);
    820     VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
    821     state->repaint1     = VGA_RD08(chip->PCIO, 0x03D5);
    822     VGA_WR08(chip->PCIO, 0x03D4, 0x25);
    823     state->screen       = VGA_RD08(chip->PCIO, 0x03D5);
    824     VGA_WR08(chip->PCIO, 0x03D4, 0x28);
    825     state->pixel        = VGA_RD08(chip->PCIO, 0x03D5);
    826     VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
    827     state->horiz        = VGA_RD08(chip->PCIO, 0x03D5);
    828     VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
    829     state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5);
    830     VGA_WR08(chip->PCIO, 0x03D4, 0x20);
    831     state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5);
    832     VGA_WR08(chip->PCIO, 0x03D4, 0x30);
    833     state->cursor0      = VGA_RD08(chip->PCIO, 0x03D5);
    834     VGA_WR08(chip->PCIO, 0x03D4, 0x31);
    835     state->cursor1      = VGA_RD08(chip->PCIO, 0x03D5);
    836     VGA_WR08(chip->PCIO, 0x03D4, 0x2F);
    837     state->cursor2      = VGA_RD08(chip->PCIO, 0x03D5);
    838     VGA_WR08(chip->PCIO, 0x03D4, 0x39);
    839     state->interlace    = VGA_RD08(chip->PCIO, 0x03D5);
    840     state->vpll         = chip->PRAMDAC[0x00000508/4];
    841     state->pllsel       = chip->PRAMDAC[0x0000050C/4];
    842     state->general      = chip->PRAMDAC[0x00000600/4];
    843     state->config       = chip->PFB[0x00000200/4];
    844     state->offset       = chip->PGRAPH[0x00000630/4];
    845     state->pitch        = chip->PGRAPH[0x00000650/4];
    846 }
    847 
    848 static void SetStartAddress
    849 (
    850     RIVA_HW_INST *chip,
    851     unsigned      start
    852 )
    853 {
    854     int offset = start >> 2;
    855     int pan    = (start & 3) << 1;
    856     unsigned char tmp;
    857 
    858     /*
    859      * Unlock extended registers.
    860      */
    861     chip->LockUnlock(chip, 0);
    862     /*
    863      * Set start address.
    864      */
    865     VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset);
    866     offset >>= 8;
    867     VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset);
    868     offset >>= 8;
    869     VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5);
    870     VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F));
    871     VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5);
    872     VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60));
    873     /*
    874      * 4 pixel pan register.
    875      */
    876     offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A);
    877     VGA_WR08(chip->PCIO, 0x3C0, 0x13);
    878     VGA_WR08(chip->PCIO, 0x3C0, pan);
    879 }
    880 /****************************************************************************\
    881 *                                                                            *
    882 *                      Probe RIVA Chip Configuration                         *
    883 *                                                                            *
    884 \****************************************************************************/
    885 
    886 static void nv3GetConfig
    887 (
    888     RIVA_HW_INST *chip
    889 )
    890 {
    891     /*
    892      * Fill in chip configuration.
    893      */
    894     if (chip->PFB[0x00000000/4] & 0x00000020)
    895     {
    896         if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20)
    897          && ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02))
    898         {
    899             /*
    900              * SDRAM 128 ZX.
    901              */
    902             chip->RamBandwidthKBytesPerSec = 800000;
    903             switch (chip->PFB[0x00000000/4] & 0x03)
    904             {
    905                 case 2:
    906                     chip->RamAmountKBytes = 1024 * 4;
    907                     break;
    908                 case 1:
    909                     chip->RamAmountKBytes = 1024 * 2;
    910                     break;
    911                 default:
    912                     chip->RamAmountKBytes = 1024 * 8;
    913                     break;
    914             }
    915         }
    916         else
    917         {
    918             chip->RamBandwidthKBytesPerSec = 1000000;
    919             chip->RamAmountKBytes          = 1024 * 8;
    920         }
    921     }
    922     else
    923     {
    924         /*
    925          * SGRAM 128.
    926          */
    927         chip->RamBandwidthKBytesPerSec = 1000000;
    928         switch (chip->PFB[0x00000000/4] & 0x00000003)
    929         {
    930             case 0:
    931                 chip->RamAmountKBytes = 1024 * 8;
    932                 break;
    933             case 2:
    934                 chip->RamAmountKBytes = 1024 * 4;
    935                 break;
    936             default:
    937                 chip->RamAmountKBytes = 1024 * 2;
    938                 break;
    939         }
    940     }
    941     chip->CrystalFreqKHz   = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
    942     chip->CURSOR           = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]);
    943     chip->VBlankBit        = 0x00000100;
    944     chip->MaxVClockFreqKHz = 256000;
    945     /*
    946      * Set chip functions.
    947      */
    948     chip->Busy            = nv3Busy;
    949     chip->ShowHideCursor  = ShowHideCursor;
    950     chip->CalcStateExt    = CalcStateExt;
    951     chip->LoadStateExt    = LoadStateExt;
    952     chip->UnloadStateExt  = UnloadStateExt;
    953     chip->SetStartAddress = SetStartAddress;
    954     chip->LockUnlock      = nv3LockUnlock;
    955 }
    956 int RivaGetConfig
    957 (
    958     RivaPtr pRiva
    959 )
    960 {
    961     RIVA_HW_INST *chip = &pRiva->riva;
    962 
    963     nv3GetConfig(chip);
    964     /*
    965      * Fill in FIFO pointers.
    966      */
    967     chip->Rop    = (RivaRop                 *)&(chip->FIFO[0x00000000/4]);
    968     chip->Clip   = (RivaClip                *)&(chip->FIFO[0x00002000/4]);
    969     chip->Patt   = (RivaPattern             *)&(chip->FIFO[0x00004000/4]);
    970     chip->Pixmap = (RivaPixmap              *)&(chip->FIFO[0x00006000/4]);
    971     chip->Blt    = (RivaScreenBlt           *)&(chip->FIFO[0x00008000/4]);
    972     chip->Bitmap = (RivaBitmap              *)&(chip->FIFO[0x0000A000/4]);
    973     chip->Line   = (RivaLine                *)&(chip->FIFO[0x0000C000/4]);
    974     return (0);
    975 }
    976