if (s3vPriv.chip == S3_ViRGE_MX &&
if (S3_ViRGE_MX_SERIES(s3vPriv.chip) &&
S3VInit(mode)DisplayModePtr mode;{unsigned char tmp;int width,dclk;int i, j;   /* First we adjust the horizontal timings if needed */   if(s3vPriv.HorizScaleFactor != 1)      if (!mode->CrtcHAdjusted) {             mode->CrtcHDisplay *= s3vPriv.HorizScaleFactor;             mode->CrtcHSyncStart *= s3vPriv.HorizScaleFactor;             mode->CrtcHSyncEnd *= s3vPriv.HorizScaleFactor;             mode->CrtcHTotal *= s3vPriv.HorizScaleFactor;             mode->CrtcHSkew *= s3vPriv.HorizScaleFactor;             mode->CrtcHAdjusted = TRUE;             }   if(!vgaHWInit (mode, sizeof(vgaS3VRec)))      return FALSE;   /* Now we fill in the rest of the stuff we need for the virge */   /* Start with MMIO, linear addr. regs */   outb(vgaCRIndex, 0x3a);   tmp = inb(vgaCRReg);   if(!OFLG_ISSET(OPTION_PCI_BURST_ON, &vga256InfoRec.options))       new->CR3A = tmp | 0x95;      /* ENH 256, no PCI burst! */   else       new->CR3A = (tmp & 0x7f) | 0x15; /* ENH 256, PCI burst */   new->CR53 = 0x08;     /* Enables MMIO */   new->CR31 = 0x8c;     /* Dis. 64k window, en. ENH maps */       /* Enables S3D graphic engine and PCI disconnects */   if(s3vPriv.chip == S3_ViRGE_VX){      new->CR66 = 0x90;        new->CR63 = 0x09;      }   else {      new->CR66 = 0x89;       new->CR63 = 0;      }    /* Now set linear addr. registers *//* LAW size: we have 2 cases, 2MB, 4MB or >= 4MB for VX */   outb(vgaCRIndex, 0x58);   new->CR58 = inb(vgaCRReg) & 0x80;   if(vga256InfoRec.videoRam == 2048){         new->CR58 |= 0x02 | 0x10;       }   else {      new->CR58 |= 0x03 | 0x10; /* 4MB window on virge, 8MB on VX */      }    if(s3vPriv.chip == S3_ViRGE_VX)      new->CR58 |= 0x40;   if (OFLG_ISSET(OPTION_EARLY_RAS_PRECHARGE, &vga256InfoRec.options))      new->CR58 |= 0x80;   if (OFLG_ISSET(OPTION_LATE_RAS_PRECHARGE, &vga256InfoRec.options))      new->CR58 &= 0x7f;/* ** On PCI bus, no need to reprogram the linear window base address *//* Now do clock PLL programming. Use the s3gendac function to get m,n *//* Also determine if we need doubling etc. */   dclk = vga256InfoRec.clock[mode->Clock];   new->CR67 = 0x00;             /* Defaults */   new->SR15 = 0x03 | 0x80;    new->SR18 = 0x00;   new->CR43 = 0x00;   new->CR45 = 0x00;   new->CR65 = 0x00;   new->CR54 = 0x00;   outb(vgaCRIndex, 0x40);   new->CR40 = inb(vgaCRReg) & ~0x01;      /* Memory controller registers. Optimize for better graphics engine     * performance. These settings are adjusted/overridden below for other bpp/    * XConfig options.The idea here is to give a longer number of contiguous    * MCLK's to both refresh and the graphics engine, to diminish the     * relative penalty of 3 or 4 mclk's needed to setup memory transfers.     */   new->MMPR0 = 0x010400; /* defaults */   new->MMPR1 = 0x00;      new->MMPR2 = 0x0808;     new->MMPR3 = 0x08080810;    if (OFLG_ISSET(OPTION_FIFO_AGGRESSIVE, &vga256InfoRec.options) ||       OFLG_ISSET(OPTION_FIFO_MODERATE, &vga256InfoRec.options) ||      OFLG_ISSET(OPTION_FIFO_CONSERV, &vga256InfoRec.options)) {         new->MMPR1 = 0x0200;   /* Low P. stream waits before filling */         new->MMPR2 = 0x1808;   /* Let the FIFO refill itself */         new->MMPR3 = 0x08081810; /* And let the GE hold the bus for a while */      }   /* And setup here the new value for MCLK. We use the XConfig     * option "set_mclk", whose value gets stored in vga256InfoRec.s3MClk.    * I'm not sure what the maximum "permitted" value should be, probably    * 100 MHz is more than enough for now.      */   if(s3vPriv.MCLK> 0) {       commonCalcClock(s3vPriv.MCLK, 1, 1, 31, 0, 3,	   135000, 270000, &new->SR11, &new->SR10);       }   else {       new->SR10 = 255; /* This is a reserved value, so we use as flag */       new->SR11 = 255;        }   if(s3vPriv.chip == S3_ViRGE_VX){       if (vgaBitsPerPixel == 8) {          if (dclk <= 110000) new->CR67 = 0x00; /* 8bpp, 135MHz */          else new->CR67 = 0x10;                /* 8bpp, 220MHz */          }       else if ((vgaBitsPerPixel == 16) && (vga256InfoRec.weight.green == 5)) {          if (dclk <= 110000) new->CR67 = 0x20; /* 15bpp, 135MHz */          else new->CR67 = 0x30;                /* 15bpp, 220MHz */          }       else if (vgaBitsPerPixel == 16) {          if (dclk <= 110000) new->CR67 = 0x40; /* 16bpp, 135MHz */          else new->CR67 = 0x50;                /* 16bpp, 220MHz */          }       else if ((vgaBitsPerPixel == 24) || (vgaBitsPerPixel == 32)) {          new->CR67 = 0xd0 | 0x0c;              /* 24bpp, 135MHz, STREAMS */          S3VInitSTREAMS(new->STREAMS, mode);          new->MMPR0 = 0xc098;            /* Adjust FIFO slots */          }       commonCalcClock(dclk, 1, 1, 31, 0, 4, 	   220000, 440000, &new->SR13, &new->SR12);      }   else if (s3vPriv.chip == S3_ViRGE_GX2 || s3vPriv.chip == S3_ViRGE_MX) {       if (vgaBitsPerPixel == 8) {          if (dclk <= 85000) new->CR67 = 0x00;  /* 8bpp,  85MHz */          else new->CR67 = 0x10;                /* 8bpp, 170MHz */          }       else if (vgaBitsPerPixel == 16) {	  if (vga256InfoRec.weight.green == 5)	     new->CR67 = 0x30;                  /* 15bpp */	  else	     new->CR67 = 0x50;                  /* 16bpp */          }       else if ((vgaBitsPerPixel == 24) /* || (vgaBitsPerPixel == 32) */ ) {          new->CR67 = 0x74;              /* 24bpp, STREAMS */          S3VInitSTREAMS(new->STREAMS, mode);          new->MMPR0 = 0xc098;            /* Adjust FIFO slots */          }       else if (vgaBitsPerPixel == 32) {          new->CR67 = 0xd0;              /* 32bpp */          /* new->MMPR0 = 0xc098;            /* Adjust FIFO slots */          }       {         unsigned char ndiv;	 if (s3vPriv.chip == S3_ViRGE_MX) {	   int lcd_freq;	   outb(0x3c4, 0x08);  /* unlock extended SEQ regs */	   outb(0x3c5, 0x06);	   outb(0x3c4, 0x31);	   if (inb(0x3c5) & 0x10) { /* LCD on */	     if (!vga256InfoRec.LCDClk) {  /* entered only once for first mode */	       int h_lcd, v_lcd;	       outb(0x3c4, 0x61);	       h_lcd = inb(0x3c5);	       outb(0x3c4, 0x66);	       h_lcd |= ((inb(0x3c5) & 0x02) << 7);	       h_lcd = (h_lcd+1) * 8;	       outb(0x3c4, 0x69);	       v_lcd = inb(0x3c5);	       outb(0x3c4, 0x6e);	       v_lcd |= ((inb(0x3c5) & 0x70) << 4);	       v_lcd++;	       	       /* check if first mode has physical LCD resolution */	       if (vga256InfoRec.modes->HDisplay == h_lcd && vga256InfoRec.modes->VDisplay == v_lcd)		 vga256InfoRec.LCDClk = vga256InfoRec.clock[vga256InfoRec.modes->Clock];	       else {		 int n1, n2, sr12, sr13, sr29;		 outb(0x3c4, 0x12);		 sr12 = inb(0x3c5);		 outb(0x3c4, 0x13);		 sr13 = inb(0x3c5) & 0x7f;		 outb(0x3c4, 0x29);		 sr29 = inb(0x3c5);		 n1 = sr12 & 0x1f;		 n2 = ((sr12>>6) & 0x03) | ((sr29 & 0x01) << 2);		 vga256InfoRec.LCDClk = ((2 * 1431818 * (sr13+2)) / (n1+2) / (1 << n2) + 50) / 100;	       }	     }	     commonCalcClock(vga256InfoRec.LCDClk/2, 1, 1, 31, 0, 4,			     170000, 340000, &new->SR13, &ndiv);	   }	   else	     commonCalcClock(dclk/2, 1, 1, 31, 0, 4,			     170000, 340000, &new->SR13, &ndiv);	 }	 else  /* S3_ViRGE_GX2 */	   commonCalcClock(dclk, 1, 1, 31, 0, 4,			   170000, 340000, &new->SR13, &ndiv);         new->SR29 = ndiv >> 7;         new->SR12 = (ndiv & 0x1f) | ((ndiv & 0x60) << 1);       }   }   else {           /* Is this correct for DX/GX as well? */      if (vgaBitsPerPixel == 8) {         if(dclk > 80000) {                     /* We need pixmux */            new->CR67 = 0x10;            new->SR15 |= 0x10;                   /* Set DCLK/2 bit */            new->SR18 = 0x80;                   /* Enable pixmux */            }         }      else if ((vgaBitsPerPixel == 16) && (vga256InfoRec.weight.green == 5)) {         new->CR67 = 0x30;                       /* 15bpp */         }      else if (vgaBitsPerPixel == 16) {         new->CR67 = 0x50;         }      else if (vgaBitsPerPixel == 24) {          new->CR67 = 0xd0 | 0x0c;         S3VInitSTREAMS(new->STREAMS, mode);         new->MMPR0 = 0xc000;            /* Adjust FIFO slots */         }      else if (vgaBitsPerPixel == 32) {          new->CR67 = 0xd0 | 0x0c;         S3VInitSTREAMS(new->STREAMS, mode);         new->MMPR0 = 0x10000;            /* Still more FIFO slots */         }      commonCalcClock(dclk, 1, 1, 31, 0, 3, 	135000, 270000, &new->SR13, &new->SR12);      }   /* Now adjust the value of the FIFO based upon options specified */   if(OFLG_ISSET(OPTION_FIFO_MODERATE, &vga256InfoRec.options)) {      if(vgaBitsPerPixel < 24)         new->MMPR0 -= 0x8000;      else          new->MMPR0 -= 0x4000;      }   else if(OFLG_ISSET(OPTION_FIFO_AGGRESSIVE, &vga256InfoRec.options)) {      if(vgaBitsPerPixel < 24)         new->MMPR0 -= 0xc000;      else          new->MMPR0 -= 0x6000;      }   /* If we have an interlace mode, set the interlace bit. Note that mode    * vertical timings are already adjusted by the standard VGA code     */   if(mode->Flags & V_INTERLACE) {        new->CR42 = 0x20; /* Set interlace mode */        }   else {        new->CR42 = 0x00;        }   /* Set display fifo */   new->CR34 = 0x10;     /* Now we adjust registers for extended mode timings */   /* This is taken without change from the accel/s3_virge code */   i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) |       ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) |       ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) |       ((mode->CrtcHSyncStart & 0x800) >> 7);   if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64)      i |= 0x08;   /* add another 64 DCLKs to blank pulse width */   if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32)      i |= 0x20;   /* add another 32 DCLKs to hsync pulse width */   j = (  new->std.CRTC[0] + ((i&0x01)<<8)        + new->std.CRTC[4] + ((i&0x10)<<4) + 1) / 2;   if (j-(new->std.CRTC[4] + ((i&0x10)<<4)) < 4)      if (new->std.CRTC[4] + ((i&0x10)<<4) + 4 <= new->std.CRTC[0]+ ((i&0x01)<<8))         j = new->std.CRTC[4] + ((i&0x10)<<4) + 4;      else         j = new->std.CRTC[0]+ ((i&0x01)<<8) + 1;   new->CR3B = j & 0xFF;   i |= (j & 0x100) >> 2;   new->CR3C = (new->std.CRTC[0] + ((i&0x01)<<8))/2;   new->CR5D = i;   new->CR5E = (((mode->CrtcVTotal - 2) & 0x400) >> 10)  |               (((mode->CrtcVDisplay - 1) & 0x400) >> 9) |               (((mode->CrtcVSyncStart) & 0x400) >> 8)   |               (((mode->CrtcVSyncStart) & 0x400) >> 6)   | 0x40;      width = (vga256InfoRec.displayWidth * (vgaBitsPerPixel / 8))>> 3;   new->std.CRTC[19] = 0xFF & width;   new->CR51 = (0x300 & width) >> 4; /* Extension bits */      /* And finally, select clock source 2 for programmable PLL */   new->std.MiscOutReg |= 0x0c;         new->CR33 = 0x20;   if (s3vPriv.chip == S3_ViRGE_DXGX) {      new->CR86 = 0x80;  /* disable DAC power saving to avoid bright left edge */   }   if (s3vPriv.chip == S3_ViRGE_DXGX || s3vPriv.chip == S3_ViRGE_GX2) {      new->CR90 = 0x00;  /* disable the stream display fetch length control */   }	    /* Now we handle various XConfig memory options and others */   outb(vgaCRIndex, 0x36);   new->CR36 = inb(vgaCRReg);   /* option "slow_edodram" sets EDO to 2 cycle mode on ViRGE */   if (s3vPriv.chip == S3_ViRGE) {      if(OFLG_ISSET(OPTION_SLOW_EDODRAM, &vga256InfoRec.options))          new->CR36 = (new->CR36 & 0xf3) | 0x08;      else           new->CR36 &= 0xf3;      }      /* Option "fpm_vram" for ViRGE_VX sets memory in fast page mode */   if (s3vPriv.chip == S3_ViRGE_VX) {      if(OFLG_ISSET(OPTION_FPM_VRAM, &vga256InfoRec.options))          new->CR36 |=  0x0c;      else          new->CR36 &= ~0x0c;      }   if (mode->Private) {      if (mode->Private[0] & (1 << S3_INVERT_VCLK)) {	 if (mode->Private[S3_INVERT_VCLK])	    new->CR67 |= 1;	 else	    new->CR67 &= ~1;      }      if (mode->Private[0] & (1 << S3_BLANK_DELAY)) {	 if (s3vPriv.chip == S3_ViRGE_VX)	    new->CR6D = mode->Private[S3_BLANK_DELAY];	 else {	    new->CR65 = (new->CR65 & ~0x38) 	       | (mode->Private[S3_BLANK_DELAY] & 0x07) << 3;	    outb(vgaCRIndex, 0x6d);	    new->CR6D = inb(vgaCRReg);	 }      }      if (mode->Private[0] & (1 << S3_EARLY_SC)) {	 if (mode->Private[S3_EARLY_SC])	    new->CR65 |= 2;	 else	    new->CR65 &= ~2;      }   }   else {      outb(vgaCRIndex, 0x6d);      new->CR6D = inb(vgaCRReg);   }   outb(vgaCRIndex, 0x68);   new->CR68 = inb(vgaCRReg);   new->CR69 = 0;   if (s3vPriv.chip == S3_ViRGE_MX &&        OFLG_ISSET(OPTION_LCD_CENTER, &vga256InfoRec.options)) {     new->SR54 = 0x10 ;     new->SR55 = 0x80 ;     new->SR56 = 0x10 ;     new->SR57 = 0x80 ;   } else {     new->SR54 = 0x1f ;     new->SR55 = 0x9f ;     new->SR56 = 0x1f ;     new->SR57 = 0xff ;   }   return TRUE;}