}    if (OFLG_ISSET(OPTION_SW_CURSOR, &s3InfoRec.options)) { s3CursorStartY = s3InfoRec.virtualY; s3CursorLines = 0; } else { int st_addr = s3InfoRec.videoRam * 1024 - 1024; s3CursorStartX = st_addr % s3BppDisplayWidth; s3CursorStartY = st_addr / s3BppDisplayWidth; s3CursorLines = ((s3CursorStartX + 1023) / s3BppDisplayWidth) + 1;
s3Probe(){   DisplayModePtr pMode, pEnd;   unsigned char config, config2;   int i, j, numClocks;   int tx, ty;   OFlagSet validOptions;   char *card, *serno;   int card_id, max_pix_clock, max_mem_clock, hwconf;   int lookupFlags;   int MemOffScreen = 0;   unsigned char tmp;   /*    * These characterise a RAMDACs pixel multiplexing capabilities and    * requirements:    *    *   pixMuxPossible         - pixmux is supported for the current RAMDAC    *   allowPixMuxInterlace   - pixmux supports interlaced modes    *   allowPixMuxSwitching   - possible to use pixmux for some modes    *                            and non-pixmux for others    *   pixMuxMinWidth         - smallest physical width supported in    *                            pixmux mode    *   nonMuxMaxClock         - highest dot clock supported without pixmux    *   pixMuxMinClock         - lowest dot clock supported with pixmux    *   nonMuxMaxMemory        - max video memory accessible without pixmux    *   pixMuxLimitedWidths    - pixmux only works for logical display    *                            widths 1024 and 2048    *   pixMuxInterlaceOK      - FALSE if pixmux isn't possible because    *                            there is an interlaced mode present    *   pixMuxWidthOK          - FALSE if pixmux isn't possible because    *                            there is mode has too small a width    */   Bool pixMuxPossible = FALSE;   Bool allowPixMuxInterlace = FALSE;   Bool allowPixMuxSwitching = FALSE;   Bool pixMuxNeeded = FALSE;   int pixMuxMinWidth = 1024;   int nonMuxMaxClock = 0;   int pixMuxMinClock = 0;   int nonMuxMaxMemory = 8192;   Bool pixMuxLimitedWidths = TRUE;   Bool pixMuxInterlaceOK = TRUE;   Bool pixMuxWidthOK = TRUE;   S3PCIInformation *pciInfo = NULL;#if !defined(PC98) || defined(PC98_GA968)   /* Do general PCI probe first */   pciInfo = s3GetPCIInfo();   if (pciInfo && pciInfo->MemBase)      s3MemBase = pciInfo->MemBase;#endif   xf86ClearIOPortList(s3InfoRec.scrnIndex);   xf86AddIOPorts(s3InfoRec.scrnIndex, Num_VGA_IOPorts, VGA_IOPorts);#if 0   xf86AddIOPorts(s3InfoRec.scrnIndex, Num_S3_IOPorts, S3_IOPorts);#endif   /* Enable I/O access */   xf86EnableIOPorts(s3InfoRec.scrnIndex);#ifdef PC98#ifdef PC98_PW   pc98BoardType = PW;#endif#ifdef PC98_NEC   pc98BoardType = NECWAB;#endif#ifdef PC98_PWLB   pc98BoardType = PWLB;#endif#ifdef PC98_GA968   pc98BoardType = GA968;#endif   if (OFLG_ISSET(OPTION_PCSKB, &s3InfoRec.options))	pc98BoardType = PCSKB;   if (OFLG_ISSET(OPTION_PCSKB4, &s3InfoRec.options))	pc98BoardType = PCSKB4;   if (OFLG_ISSET(OPTION_PCHKB, &s3InfoRec.options))	pc98BoardType = PCHKB;   if (OFLG_ISSET(OPTION_NECWAB, &s3InfoRec.options))	pc98BoardType = NECWAB;   if (OFLG_ISSET(OPTION_PW805I, &s3InfoRec.options))	pc98BoardType = PW805I;   if (OFLG_ISSET(OPTION_PWLB, &s3InfoRec.options))	pc98BoardType = PWLB;   if (OFLG_ISSET(OPTION_PW968, &s3InfoRec.options))	pc98BoardType = PW968;   ErrorF("   PC98:Board Type = %X \n",pc98BoardType);   if(BoardInit() == FALSE)	return(FALSE);#endif   vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;   vgaCRIndex = vgaIOBase + 4;   vgaCRReg = vgaIOBase + 5;   outb(vgaCRIndex, 0x11);	/* for register CR11 */   tmp = inb(vgaCRReg);         /* enable CR0-7 and disable interrupts */   outb(vgaCRReg, tmp & 0x0f);   outb(vgaCRIndex, 0x38);		/* check if we have an S3 */   outb(vgaCRReg, 0x00);   /* Make sure we can't write when locked */   if (testinx2(vgaCRIndex, 0x35, 0x0f)) {      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return(FALSE);   }   outb(vgaCRIndex, 0x38);	/* for register CR38, (REG_LOCK1) */   outb(vgaCRReg, 0x48);	/* unlock S3 register set for read/write */   /* Make sure we can write when unlocked */   if (!testinx2(vgaCRIndex, 0x35, 0x0f)) {      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return(FALSE);   }   outb(vgaCRIndex, 0x36);		/* for register CR36 (CONFG_REG1), */   config = inb(vgaCRReg);		/* get amount of vram installed */   outb(vgaCRIndex, 0x37);		/* for register CR37 (CONFG_REG2), */   config2 = inb(vgaCRReg);		/* get amount of off-screen ram  */   outb(vgaCRIndex, 0x30);   s3ChipId = inb(vgaCRReg);         /* get chip id */   s3ChipRev = s3ChipId & 0x0f;   if (s3ChipId >= 0xe0) {      outb(vgaCRIndex, 0x2d);      s3ChipId = inb(vgaCRReg) << 8;      outb(vgaCRIndex, 0x2e);      s3ChipId |= inb(vgaCRReg);      outb(vgaCRIndex, 0x2f);      s3ChipRev = inb(vgaCRReg);   }   if (s3InfoRec.chipID) {      ErrorF("%s %s: S3 chipset override, using chip_id = 0x%02x instead of 0x%02x\n",	     XCONFIG_GIVEN, s3InfoRec.name, s3InfoRec.chipID, s3ChipId);      s3ChipId = s3InfoRec.chipID;   }   if (s3InfoRec.chipRev) {      ErrorF("%s %s: S3 chipset override, using chip_rev = %x instead of %x\n",	     XCONFIG_GIVEN, s3InfoRec.name, s3InfoRec.chipRev, s3ChipRev);      s3ChipRev = s3InfoRec.chipRev;   }   if (!S3_ANY_SERIES(s3ChipId)) {      ErrorF("%s %s: Unknown S3 chipset: chip_id = 0x%02x rev. %x\n",	     XCONFIG_PROBED,s3InfoRec.name,s3ChipId,s3ChipRev);      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return(FALSE);   }   for (i = 0; s3Drivers[i]; i++) {      if ((s3Drivers[i]->ChipProbe)()) {	 xf86ProbeFailed = FALSE;	 s3InfoRec.Init = s3Drivers[i]->ChipInitialize;	 s3InfoRec.EnterLeaveVT = s3Drivers[i]->ChipEnterLeaveVT;	 s3InfoRec.AdjustFrame = s3Drivers[i]->ChipAdjustFrame;	 s3InfoRec.SwitchMode = s3Drivers[i]->ChipSwitchMode;	 break;      }   }   if (xf86ProbeFailed) {      if (s3InfoRec.chipset) {	 ErrorF("%s: '%s' is an invalid chipset", s3InfoRec.name,		s3InfoRec.chipset);      }      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return(FALSE);   }   if (s3InfoRec.ramdac) {      s3RamdacType = xf86StringToToken(s3DacTable, s3InfoRec.ramdac);      if (s3RamdacType < 0) {	 ErrorF("%s %s: Unknown RAMDAC type \"%s\"\n", XCONFIG_GIVEN,		s3InfoRec.name, s3InfoRec.ramdac);	 xf86DisableIOPorts(s3InfoRec.scrnIndex);	 return(FALSE);      }   }   OFLG_ZERO(&validOptions);   OFLG_SET(OPTION_CLKDIV2, &validOptions);   OFLG_SET(OPTION_SW_CURSOR, &validOptions);   OFLG_SET(OPTION_SHOWCACHE, &validOptions);   OFLG_SET(OPTION_NO_FONT_CACHE, &validOptions);   OFLG_SET(OPTION_NO_PIXMAP_CACHE, &validOptions);   OFLG_SET(OPTION_DAC_8_BIT, &validOptions);   OFLG_SET(OPTION_DAC_6_BIT, &validOptions);   OFLG_SET(OPTION_SYNC_ON_GREEN, &validOptions);#ifdef PC98   OFLG_SET(OPTION_PCSKB, &validOptions);   OFLG_SET(OPTION_PCSKB4, &validOptions);   OFLG_SET(OPTION_PCHKB, &validOptions);   OFLG_SET(OPTION_NECWAB, &validOptions);   OFLG_SET(OPTION_PW805I, &validOptions);   OFLG_SET(OPTION_PWLB, &validOptions);   OFLG_SET(OPTION_PW968, &validOptions);   OFLG_SET(OPTION_EPSON_MEM_WIN, &validOptions);   OFLG_SET(OPTION_PW_MUX, &validOptions);   OFLG_SET(OPTION_NOINIT, &validOptions);#endif   OFLG_SET(OPTION_POWER_SAVER, &validOptions);   OFLG_SET(OPTION_SLOW_DRAM, &validOptions);   OFLG_SET(OPTION_SLOW_EDODRAM, &validOptions);   OFLG_SET(OPTION_SLOW_VRAM, &validOptions);   OFLG_SET(OPTION_SLOW_DRAM_REFRESH, &validOptions);   OFLG_SET(OPTION_FAST_VRAM, &validOptions);   OFLG_SET(OPTION_FPM_VRAM, &validOptions);   OFLG_SET(OPTION_EDO_VRAM, &validOptions);   OFLG_SET(OPTION_EARLY_RAS_PRECHARGE, &validOptions);   OFLG_SET(OPTION_LATE_RAS_PRECHARGE, &validOptions);   xf86VerifyOptions(&validOptions, &s3InfoRec);#ifdef PC98   if (OFLG_ISSET(OPTION_PW_MUX, &s3InfoRec.options)) {      OFLG_SET(OPTION_SPEA_MERCURY, &s3InfoRec.options);    }#endif   /* ViRGE is always PCI (or VLB if ever?!),  ViRGE/VX is only PCI */   s3Localbus = TRUE;   if (S3_ViRGE_SERIES(s3ChipId) && s3ChipRev < 0x06) {      if (config & 0x02) {	 if (xf86Verbose)	    ErrorF("%s %s: card type: PCI\n", XCONFIG_PROBED, s3InfoRec.name);      } else {	 if (xf86Verbose)	    ErrorF("%s %s: card type: VLB\n",		   XCONFIG_PROBED, s3InfoRec.name);	 s3VLB = TRUE;      }   }   /* reset S3 graphics engine to avoid memory corruption */   if (!S3_ViRGE_VX_SERIES(s3ChipId)) {      outb(vgaCRIndex, 0x66);      i = inb(vgaCRReg);      outb(vgaCRReg, i |  0x02);      usleep(10000);  /* wait a little bit... */   }   if (find_bios_string(s3InfoRec.BIOSbase,"S3 86C325",			"MELCO WGP-VG VIDEO BIOS") != NULL) {      if (s3BiosVendor == UNKNOWN_BIOS)	 s3BiosVendor = MELCO_BIOS;      if (xf86Verbose)	 ErrorF("%s %s: MELCO BIOS found\n",		XCONFIG_PROBED, s3InfoRec.name);      if (s3InfoRec.MemClk <= 0)       s3InfoRec.MemClk       =  74000;      if (s3InfoRec.dacSpeeds[0] <= 0) s3InfoRec.dacSpeeds[0] = 191500;      if (s3InfoRec.dacSpeeds[1] <= 0) s3InfoRec.dacSpeeds[1] = 162500;      if (s3InfoRec.dacSpeeds[2] <= 0) s3InfoRec.dacSpeeds[2] = 111500;      if (s3InfoRec.dacSpeeds[3] <= 0) s3InfoRec.dacSpeeds[3] =  83500;   }   card_id = s3DetectELSA(s3InfoRec.BIOSbase, &card, &serno, &max_pix_clock,			  &max_mem_clock, &hwconf);   if (!S3_ViRGE_VX_SERIES(s3ChipId)) {      outb(vgaCRIndex, 0x66);      outb(vgaCRReg, i & ~0x02);  /* clear reset flag */      usleep(10000);  /* wait a little bit... */   }   if (card_id > 0) {      if (s3BiosVendor == UNKNOWN_BIOS)	 s3BiosVendor = ELSA_BIOS;      if (xf86Verbose)         ErrorF("%s %s: card: %s, Ser.No. %s\n",	        XCONFIG_PROBED, s3InfoRec.name, card, serno);      xfree(card);      xfree(serno);      if (s3InfoRec.dacSpeeds[0] <= 0)	 s3InfoRec.dacSpeeds[0] = max_pix_clock;      do {	 switch (card_id) {	 default:	    continue; /* unknown card_id, don't set ICD2061A flags */	 }	 /* a known ELSA card_id was returned, set ICD 2061A clock support	    if there is no ClockChip specified in XF86Config */	 if (!OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions)) {	    OFLG_SET(CLOCK_OPTION_ICD2061A, &s3InfoRec.clockOptions);	    OFLG_SET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions);	    clockchip_probed = XCONFIG_PROBED;	 }      } while (0);   }   if (xf86Verbose) {      char *chipname = "unknown";      if (S3_ViRGE_SERIES(s3ChipId)) {	 chipname = "ViRGE";      }      else if (S3_ViRGE_GX2_SERIES(s3ChipId)) {	 chipname = "ViRGE/GX";      }      else if (S3_ViRGE_MX_SERIES(s3ChipId)) {	 chipname = "ViRGE/MX";      }      else if (S3_ViRGE_DXGX_SERIES(s3ChipId)) {	 outb(vgaCRIndex, 0x39);	 outb(vgaCRReg, 0xa5);	 outb(vgaCRIndex, 0x6f);	 if (inb(vgaCRReg) & 1)	    chipname = "ViRGE/GX";	 else	    chipname = "ViRGE/DX";      }      else if (S3_ViRGE_VX_SERIES(s3ChipId)) {	 chipname = "ViRGE/VX";      }      ErrorF("%s %s: chipset:   %s rev. %x\n",	     XCONFIG_PROBED, s3InfoRec.name, chipname, s3ChipRev);   }   if (xf86Verbose) {      ErrorF("%s %s: chipset driver: %s\n",	     OFLG_ISSET(XCONFIG_CHIPSET, &s3InfoRec.xconfigFlag) ?		XCONFIG_GIVEN : XCONFIG_PROBED,	     s3InfoRec.name, s3InfoRec.chipset);   }   if (!s3InfoRec.videoRam) {      if (S3_ViRGE_VX_SERIES(s3ChipId)) {	 switch((config2 & 0x60) >> 5) {	 case 1:	    MemOffScreen = 4 * 1024;	    break;	 case 2:	    MemOffScreen = 2 * 1024;	    break;	 }	 switch ((config & 0x60) >> 5) {	 case 0:	    s3InfoRec.videoRam = 2 * 1024;	    break;	 case 1:	    s3InfoRec.videoRam = 4 * 1024;	    break;	 case 2:	    s3InfoRec.videoRam = 6 * 1024;	    break;	 case 3:	    s3InfoRec.videoRam = 8 * 1024;	    break;	 }	 s3InfoRec.videoRam -= MemOffScreen;      }      else if (S3_ViRGE_GX2_SERIES(s3ChipId) || S3_ViRGE_MX_SERIES(s3ChipId)) {         switch((config & 0xC0) >> 6) {         case 1:            s3InfoRec.videoRam = 4 * 1024;            break;         case 3:            s3InfoRec.videoRam = 2 * 1024;            break;         }      }      else {	 switch((config & 0xE0) >> 5) {	 case 0:	    s3InfoRec.videoRam = 4 * 1024;	    break;	 case 4:	    s3InfoRec.videoRam = 2 * 1024;	    break;	 case 6:#if 0	    /*	     * normally this setting is illegal for older ViRGE	     * chips, but it is in fact used for example on the	     * Elsa Gloria L board	     */	    if (S3_ViRGE_DXGX_SERIES(s3ChipId))#endif	       s3InfoRec.videoRam = 1 * 1024;	    break;	 }      }      if (xf86Verbose) {	 if (MemOffScreen)	    ErrorF("%s %s: videoram:  %dk (plus %dk off-screen)\n",		   XCONFIG_PROBED, s3InfoRec.name, s3InfoRec.videoRam,		   MemOffScreen);	 else	    ErrorF("%s %s: videoram:  %dk\n",		   XCONFIG_PROBED, s3InfoRec.name, s3InfoRec.videoRam);      }   } else {      if (xf86Verbose) {	 ErrorF("%s %s: videoram:  %dk\n",              XCONFIG_GIVEN, s3InfoRec.name, s3InfoRec.videoRam);      }   }   if (xf86bpp < 0) {      xf86bpp = s3InfoRec.depth;   }   if (xf86weight.red == 0 || xf86weight.green == 0 || xf86weight.blue == 0) {      xf86weight = s3InfoRec.weight;   }   switch (xf86bpp) {   case 8:      break;   case 15:      s3InfoRec.depth = 15;      xf86bpp = 16;      s3Weight = RGB16_555;      xf86weight.red = xf86weight.green = xf86weight.blue = 5;s3InfoRec.weight.red = s3InfoRec.weight.green = s3InfoRec.weight.blue = 5;      s3InfoRec.bitsPerPixel = 16;      if (s3InfoRec.defaultVisual < 0)	 s3InfoRec.defaultVisual = TrueColor;      if (defaultColorVisualClass < 0)	 defaultColorVisualClass = s3InfoRec.defaultVisual;      break;   case 16:      if (xf86weight.red==5 && xf86weight.green==5 && xf86weight.blue==5) {	 s3Weight = RGB16_555;	 s3InfoRec.depth = 15;s3InfoRec.weight.red = s3InfoRec.weight.green = s3InfoRec.weight.blue = 5;      }      else if (xf86weight.red==5 && xf86weight.green==6 && xf86weight.blue==5) {	 s3Weight = RGB16_565;	 s3InfoRec.depth = 16;s3InfoRec.weight.red = s3InfoRec.weight.blue = 5;s3InfoRec.weight.green = 6;      }      else {	 ErrorF(	   "Invalid color weighting %1d%1d%1d (only 555 and 565 are valid)\n",	   xf86weight.red,xf86weight.green,xf86weight.blue);	 xf86DisableIOPorts(s3InfoRec.scrnIndex);	 return(FALSE);      }      s3InfoRec.bitsPerPixel = 16;      if (s3InfoRec.defaultVisual < 0)	 s3InfoRec.defaultVisual = TrueColor;      if (defaultColorVisualClass < 0)	 defaultColorVisualClass = s3InfoRec.defaultVisual;      break;   case 24:   case 32:      xf86bpp = 32;      s3InfoRec.depth = 24;	   /* actually 24 bpp */      s3InfoRec.bitsPerPixel = 32; /* to work with things higher up */      s3Weight = RGB32_888;      /* s3MaxClock = S3_MAX_32BPP_CLOCK; */      xf86weight.red =  xf86weight.green = xf86weight.blue = 8;s3InfoRec.weight.red = s3InfoRec.weight.green = s3InfoRec.weight.blue = 8;      s3InfoRec.defaultVisual = TrueColor;      defaultColorVisualClass = s3InfoRec.defaultVisual;      break;   #if 0   case 32:      s3InfoRec.depth = 24;      s3InfoRec.bitsPerPixel = 32; /* Use sparse 24 bpp (RGBX) */      s3Weight = RGB32_888;      /* s3MaxClock = S3_MAX_32BPP_CLOCK; */      xf86weight.red =  xf86weight.green = xf86weight.blue = 8;      if (s3InfoRec.defaultVisual < 0)	 s3InfoRec.defaultVisual = TrueColor;      if (defaultColorVisualClass < 0)	 defaultColorVisualClass = s3InfoRec.defaultVisual;      break;   #endif   default:      ErrorF(	"Invalid value for bpp.  Valid values are 8, 15, 16, and 24/32"	/*", 24 and 32"*/	".\n");      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return(FALSE);   }   if (s3InfoRec.bitsPerPixel > 8 &&       defaultColorVisualClass >= 0 && defaultColorVisualClass != TrueColor) {      ErrorF("Invalid default visual type: %d (%s)\n", defaultColorVisualClass,	     xf86VisualNames[defaultColorVisualClass]);      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return(FALSE);   }   s3Bpp = xf86bpp / 8;   realS3Bpp = s3Bpp;   if (s3Bpp == 4) realS3Bpp = 3;   if (S3_ANY_ViRGE_SERIES(s3ChipId)) {      if (s3RamdacType != UNKNOWN_DAC && !DAC_IS_TRIO) {	 ErrorF("%s %s: for ViRGE chips you shouldn't specify a Ramdac\n",		XCONFIG_PROBED, s3InfoRec.name);	 OFLG_CLR(XCONFIG_RAMDAC, &s3InfoRec.xconfigFlag);      }      if (!DAC_IS_TRIO) {	 s3RamdacType = S3_TRIO64_DAC;	 s3InfoRec.ramdac = xf86TokenToString(s3DacTable, s3RamdacType);      }      if (S3_ViRGE_DXGX_SERIES(s3ChipId)) {	 if ( OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions) &&	     !OFLG_ISSET(CLOCK_OPTION_S3TRIO, &s3InfoRec.clockOptions) &&	     !OFLG_ISSET(CLOCK_OPTION_S3TRIO64V2, &s3InfoRec.clockOptions)) {	    ErrorF("%s %s: for ViRGE/DX/GX chips you shouldn't specify any Clockchip\n"		   "\t other than \"s3_trio64v2\" or maybe \"s3_trio64\"\n",		   XCONFIG_PROBED, s3InfoRec.name);	    /* Clear the other clock options */	    OFLG_ZERO(&s3InfoRec.clockOptions);	 }	 if (S3_ViRGE_DXGX_SERIES(s3ChipId) &&	     !OFLG_ISSET(CLOCK_OPTION_S3TRIO, &s3InfoRec.clockOptions)) {	    OFLG_SET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions);	    OFLG_SET(CLOCK_OPTION_S3TRIO64V2, &s3InfoRec.clockOptions);	    clockchip_probed = XCONFIG_PROBED;	 }      }      else      if ( OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions) &&	  !OFLG_ISSET(CLOCK_OPTION_S3TRIO, &s3InfoRec.clockOptions)) {	 ErrorF("%s %s: for ViRGE chips you shouldn't specify a Clockchip\n",		XCONFIG_PROBED, s3InfoRec.name);	 /* Clear the other clock options */	 OFLG_ZERO(&s3InfoRec.clockOptions);      }      if (!OFLG_ISSET(CLOCK_OPTION_S3TRIO, &s3InfoRec.clockOptions) && 	  !OFLG_ISSET(CLOCK_OPTION_S3TRIO64V2, &s3InfoRec.clockOptions)) {	 OFLG_SET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions);	 OFLG_SET(CLOCK_OPTION_S3TRIO, &s3InfoRec.clockOptions);	 clockchip_probed = XCONFIG_PROBED;      }   }   /* If we still don't know the ramdac type, set it to NORMAL_DAC */   if (s3RamdacType == UNKNOWN_DAC) {      s3RamdacType = NORMAL_DAC;   }   /* make sure s3InfoRec.ramdac is set correctly */   s3InfoRec.ramdac = xf86TokenToString(s3DacTable, s3RamdacType);   /* Check Ramdac type is supported on the current S3 chipset */   {      char *chips = NULL;      switch (s3RamdacType) {      case BT485_DAC:      case ATT20C505_DAC:      case TI3020_DAC:      case TI3025_DAC:      case TI3026_DAC:      case TI3030_DAC:      case IBMRGB524_DAC:      case IBMRGB525_DAC:      case IBMRGB528_DAC:      case ATT20C498_DAC:      case ATT22C498_DAC:      case ATT20C409_DAC:      case STG1700_DAC:      case STG1703_DAC:      case S3_SDAC_DAC:      case S3_GENDAC_DAC:      case S3_TRIO32_DAC:	 chips = "S3 chips other than S3 ViRGE";	 break;      case S3_TRIO64_DAC:	 if (!S3_ANY_ViRGE_SERIES(s3ChipId))	    chips = "ViRGE";	 break;      }      if (chips) {	 ErrorF("%s %s: Ramdac \"%s\" is only supported with %s\n",		XCONFIG_PROBED, s3InfoRec.name, s3InfoRec.ramdac, chips);	 OFLG_CLR(XCONFIG_RAMDAC, &s3InfoRec.xconfigFlag);	 /* Treat the ramdac as a "normal" dac */	 s3RamdacType = NORMAL_DAC;	 s3InfoRec.ramdac = xf86TokenToString(s3DacTable, s3RamdacType);      }   }   if (S3_ANY_ViRGE_SERIES(s3ChipId)) {      if (!DAC_IS_TRIO) {	 ErrorF("%s %s: for ViRGE chips you shouldn't specify a Ramdac\n",		XCONFIG_PROBED, s3InfoRec.name);	 OFLG_CLR(XCONFIG_RAMDAC, &s3InfoRec.xconfigFlag);	 s3RamdacType = S3_TRIO64_DAC;	 s3InfoRec.ramdac = xf86TokenToString(s3DacTable, s3RamdacType);      }   }   if (xf86Verbose) {      ErrorF("%s %s: Ramdac type: %s\n",	     OFLG_ISSET(XCONFIG_RAMDAC, &s3InfoRec.xconfigFlag) ?	     XCONFIG_GIVEN : XCONFIG_PROBED, s3InfoRec.name, s3InfoRec.ramdac);   }   /* Now check/set the DAC speed */   if (s3InfoRec.dacSpeeds[3] <= 0 && s3InfoRec.dacSpeeds[2] > 0)       s3InfoRec.dacSpeeds[3] = s3InfoRec.dacSpeeds[2];   if (S3_ViRGE_VX_SERIES(s3ChipId)) {      if (s3InfoRec.dacSpeeds[0] <= 0) s3InfoRec.dacSpeeds[0] = 220000;      if (s3InfoRec.dacSpeeds[1] <= 0) s3InfoRec.dacSpeeds[1] = 220000;      if (s3InfoRec.dacSpeeds[2] <= 0) s3InfoRec.dacSpeeds[2] = 135000;      if (s3InfoRec.dacSpeeds[3] <= 0) s3InfoRec.dacSpeeds[3] = 135000;   }   else if (S3_ViRGE_DXGX_SERIES(s3ChipId)) {      if (s3InfoRec.dacSpeeds[0] <= 0) s3InfoRec.dacSpeeds[0] = 170000;      if (s3InfoRec.dacSpeeds[1] <= 0) s3InfoRec.dacSpeeds[1] = 170000;      if (s3InfoRec.dacSpeeds[2] <= 0) s3InfoRec.dacSpeeds[2] = 135000;      if (s3InfoRec.dacSpeeds[3] <= 0) s3InfoRec.dacSpeeds[3] = 135000;   }   else {      if (s3InfoRec.dacSpeeds[0] <= 0) s3InfoRec.dacSpeeds[0] = 135000;      if (s3InfoRec.dacSpeeds[1] <= 0) s3InfoRec.dacSpeeds[1] =  95000;      if (s3InfoRec.dacSpeeds[2] <= 0) s3InfoRec.dacSpeeds[2] =  57000;      if (s3InfoRec.dacSpeeds[3] <= 0) s3InfoRec.dacSpeeds[3] =  57000;   }   if (s3InfoRec.dacSpeedBpp <= 0)/*      if (xf86bpp > 24 && s3InfoRec.dacSpeeds[3] > 0)	 s3InfoRec.dacSpeedBpp = s3InfoRec.dacSpeeds[3];*/      if (0) /* no real 32 bpp here */ ;      else if (xf86bpp >= 24 && s3InfoRec.dacSpeeds[2] > 0)	 s3InfoRec.dacSpeedBpp = s3InfoRec.dacSpeeds[2];      else if (xf86bpp > 8 && xf86bpp < 24 && s3InfoRec.dacSpeeds[1] > 0)	 s3InfoRec.dacSpeedBpp = s3InfoRec.dacSpeeds[1];      else if (xf86bpp <= 8 && s3InfoRec.dacSpeeds[0] > 0)	 s3InfoRec.dacSpeedBpp = s3InfoRec.dacSpeeds[0];   if (xf86Verbose) {      ErrorF("%s %s: Ramdac speed: %d MHz",	     OFLG_ISSET(XCONFIG_DACSPEED, &s3InfoRec.xconfigFlag) ?	     XCONFIG_GIVEN : XCONFIG_PROBED, s3InfoRec.name,	     s3InfoRec.dacSpeeds[0] / 1000);      if (s3InfoRec.dacSpeedBpp != s3InfoRec.dacSpeeds[0])	 ErrorF("  (%d MHz for %d bpp)",s3InfoRec.dacSpeedBpp / 1000, xf86bpp);      ErrorF("\n");   }   /* Check when pixmux is supported */   if (DAC_IS_TRIO)	 if (S3_ViRGE_VX_SERIES(s3ChipId)) {	    if (xf86bpp <= 16) s3ATT498PixMux = TRUE;	 }	 else	    if (xf86bpp <=  8) s3ATT498PixMux = TRUE;   if (s3ATT498PixMux) {      pixMuxPossible = TRUE;      if (DAC_IS_TRIO) {	 if (S3_ViRGE_VX_SERIES(s3ChipId)) {	    nonMuxMaxClock = 110000;  /* could be 135000 */	    pixMuxMinClock = 110000;  /* could be 135000 */	 } else {	    nonMuxMaxClock = 80000;	    pixMuxMinClock = 80000;	 }      }      else {	 nonMuxMaxClock = 67500;	 pixMuxMinClock = 67500;      }      allowPixMuxInterlace = TRUE;      allowPixMuxSwitching = TRUE;      pixMuxLimitedWidths = FALSE;      pixMuxMinWidth = 0;   }   /*    * clock options are now done after the ramdacs because the next    * generation ramdacs will have a built in clock (i.e. TI 3025)    */   if (OFLG_ISSET(CLOCK_OPTION_S3TRIO, &s3InfoRec.clockOptions) ||       OFLG_ISSET(CLOCK_OPTION_S3TRIO64V2, &s3InfoRec.clockOptions)) {      unsigned char sr8;      int m,n,n1,n2, mclk;      s3ClockSelectFunc = s3GendacClockSelect;      numClocks = 3;      outb(0x3c4, 0x08);      sr8 = inb(0x3c5);      outb(0x3c5, 0x06);      outb(0x3c4, 0x11);      m = inb(0x3c5);      outb(0x3c4, 0x10);      n = inb(0x3c5);      outb(0x3c4, 0x08);      outb(0x3c5, sr8);      m &= 0x7f;      n1 = n & 0x1f;      n2 = (n>>5) & 0x03;      mclk = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;      if (xf86Verbose)	 ErrorF("%s %s: Using Trio32/64 programmable clock (MCLK %1.3f MHz)\n"		,clockchip_probed, s3InfoRec.name		,mclk / 1000.0);      if (s3InfoRec.s3MClk > 0) {	 if (xf86Verbose)	    ErrorF("%s %s: using specified MCLK value of %1.3f MHz for DRAM timings\n",		   XCONFIG_GIVEN, s3InfoRec.name, s3InfoRec.s3MClk / 1000.0);      }      else {	 s3InfoRec.s3MClk = mclk;      }      if (s3InfoRec.MemClk > 0) {	 /* some sanity checks */	 if (s3InfoRec.MemClk < 40000 || s3InfoRec.MemClk > 100000) {	    ErrorF("%s %s: MCLK %1.3f MHz too low/high, not changed!\n",		   OFLG_ISSET(XCONFIG_DACSPEED, &s3InfoRec.xconfigFlag) ?		   XCONFIG_GIVEN : XCONFIG_PROBED, s3InfoRec.name, 		   s3InfoRec.MemClk / 1000.0);	    s3InfoRec.MemClk = 0;	 }	 else if (xf86Verbose)	    ErrorF("%s %s: set MCLK to %1.3f MHz\n",		   XCONFIG_GIVEN, s3InfoRec.name, s3InfoRec.MemClk / 1000.0);      }   } else {      s3ClockSelectFunc = s3ClockSelect;      numClocks = 16;      if (!s3InfoRec.clocks)         vgaGetClocks(numClocks, s3ClockSelectFunc);   }   /*    * Set the maximum raw clock for programmable clock chips.    * Setting maxRawClock to 0 means no clock-chip limit imposed.    */   if (OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions)) {      if (OFLG_ISSET(CLOCK_OPTION_ICD2061A, &s3InfoRec.clockOptions)) {	 maxRawClock = 120000;      } else if (OFLG_ISSET(CLOCK_OPTION_S3TRIO, &s3InfoRec.clockOptions) ||		 OFLG_ISSET(CLOCK_OPTION_S3TRIO64V2, &s3InfoRec.clockOptions)) {	 if (S3_ViRGE_VX_SERIES(s3ChipId))	    maxRawClock = s3InfoRec.dacSpeeds[0];	 else if (S3_ViRGE_DXGX_SERIES(s3ChipId))	    maxRawClock = s3InfoRec.dacSpeeds[0];	 else	    maxRawClock = s3InfoRec.dacSpeeds[0];      } else {	 /* Shouldn't get here */	 maxRawClock = 0;      }   } else {      maxRawClock = 0;   }   /*    * Set pixel clock limit based on RAMDAC type/speed/bpp and pixmux usage.    * Also scale maxRawClock so that it can be compared with a pixel clock,    * and re-adjust the pixel clock limit if required.    */   switch (s3RamdacType) {   case S3_TRIO64_DAC:      s3InfoRec.maxClock = s3InfoRec.dacSpeedBpp;      break;   default:      /* For DACs we don't have special code for, keep this as a limit */      s3InfoRec.maxClock = s3MaxClock;   }   /* Check that maxClock is not higher than dacSpeeds[0] */   if (s3InfoRec.maxClock > s3InfoRec.dacSpeeds[0])      s3InfoRec.maxClock = s3InfoRec.dacSpeeds[0];   /* Check if this exceeds the clock chip's limit */   if (clockDoublingPossible)      maxRawClock *= 2;   if (maxRawClock > 0 && s3InfoRec.maxClock > maxRawClock)      s3InfoRec.maxClock = maxRawClock;   if (xf86Verbose) {      if (! OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions)) {	 for (j = 0; j < s3InfoRec.clocks; j++) {	    if ((j % 8) == 0) {	       if (j != 0)		  ErrorF("\n");               ErrorF("%s %s: clocks:",                OFLG_ISSET(XCONFIG_CLOCKS,&s3InfoRec.xconfigFlag) ?                    XCONFIG_GIVEN : XCONFIG_PROBED ,                s3InfoRec.name);	    }	    ErrorF(" %6.2f", (double)s3InfoRec.clock[j] / 1000.0);         }         ErrorF("\n");      }   }   if (pixMuxPossible && s3InfoRec.videoRam > nonMuxMaxMemory)      pixMuxNeeded = TRUE;   /* Adjust s3InfoRec.clock[] when not using a programable clock chip */   if (!OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions)) {      Bool clocksChanged = FALSE;      Bool numClocksChanged = FALSE;      int newNumClocks = s3InfoRec.clocks;      for (j = 0; j < s3InfoRec.clocks; j++) {	 switch(s3RamdacType) {	 case NORMAL_DAC:	    /* only suports 8bpp -- nothing to do */	    break;	 case S3_TRIO64_DAC:	    /*	     * We should never get here since these have a programmable	     * clock built in.	     */	    break;	 default:	    /* Do nothing */	    break;	 }      }      if (numClocksChanged)	 s3InfoRec.clocks = newNumClocks;      if (xf86Verbose && clocksChanged) {	 ErrorF("%s %s: Effective pixel clocks available for depth %d:\n",		XCONFIG_PROBED, s3InfoRec.name, s3InfoRec.depth);	 for (j = 0; j < s3InfoRec.clocks; j++) {	    if ((j % 8) == 0) {	       if (j != 0)		  ErrorF("\n");               ErrorF("%s %s: pixel clocks:", XCONFIG_PROBED, s3InfoRec.name);	    }	    ErrorF(" %6.2f", (double)s3InfoRec.clock[j] / 1000.0);         }         ErrorF("\n");      }   }   /* At this point, the s3InfoRec.clock[] values are pixel clocks */   maxDisplayWidth = 2048;   /* S3 ViRGE has only 11 bit X/Y addresses, limiting to 2048 :-( */   maxDisplayHeight = 2048 - 3; /* Cursor can take up to 3 lines */   if (s3InfoRec.virtualX > maxDisplayWidth) {      ErrorF("%s: Virtual width (%d) is too large.  Maximum is %d\n",	     s3InfoRec.name, s3InfoRec.virtualX, maxDisplayWidth);      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return (FALSE);   }   if (s3InfoRec.virtualY > maxDisplayHeight) {      ErrorF("%s: Virtual height (%d) is too large.  Maximum is %d\n",	     s3InfoRec.name, s3InfoRec.virtualY, maxDisplayHeight);      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return (FALSE);   }   lookupFlags = LOOKUP_DEFAULT;redo_mode_lookup:   tx = s3InfoRec.virtualX;   ty = s3InfoRec.virtualY;   pMode = s3InfoRec.modes;   if (pMode == NULL) {      ErrorF("No modes supplied in XF86Config\n");      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return (FALSE);   }   pEnd = NULL;   do {      DisplayModePtr pModeSv;      pModeSv = pMode->next;      /*       * xf86LookupMode returns FALSE if it ran into an invalid       * parameter       */      if (!xf86LookupMode(pMode, &s3InfoRec, lookupFlags)) {	 xf86DeleteMode(&s3InfoRec, pMode);      } else if (pMode->HDisplay > maxDisplayWidth) {	 ErrorF("%s %s: Width of mode \"%s\" is too large (max is %d)\n",		XCONFIG_PROBED, s3InfoRec.name, pMode->name, maxDisplayWidth);	 xf86DeleteMode(&s3InfoRec, pMode);      } else if (pMode->VDisplay > maxDisplayHeight) {	 ErrorF("%s %s: Height of mode \"%s\" is too large (max is %d)\n",		XCONFIG_PROBED, s3InfoRec.name, pMode->name, maxDisplayHeight);	 xf86DeleteMode(&s3InfoRec, pMode);      } else if ((pMode->HDisplay * (1 + pMode->VDisplay) * realS3Bpp/*s3Bpp*/) >		 s3InfoRec.videoRam * 1024) {	 ErrorF("%s %s: Too little memory for mode \"%s\"\n", XCONFIG_PROBED,		s3InfoRec.name, pMode->name);	 if (!OFLG_ISSET(OPTION_SW_CURSOR,   &s3InfoRec.options))	 ErrorF("%s %s: NB. 1 scan line is required for the hardware cursor\n",	        XCONFIG_PROBED, s3InfoRec.name);	 xf86DeleteMode(&s3InfoRec, pMode);      } else if (((tx > 0) && (pMode->HDisplay > tx)) ||		 ((ty > 0) && (pMode->VDisplay > ty))) {	 ErrorF("%s %s: Resolution %dx%d too large for virtual %dx%d\n",		XCONFIG_PROBED, s3InfoRec.name,		pMode->HDisplay, pMode->VDisplay, tx, ty);	 xf86DeleteMode(&s3InfoRec, pMode);      } else {	 /*	  * Successfully looked up this mode.  If pEnd isn't	  * initialized, set it to this mode.	  */	 if (pEnd == (DisplayModePtr) NULL)	    pEnd = pMode;	 s3InfoRec.virtualX = max(s3InfoRec.virtualX, pMode->HDisplay);	 s3InfoRec.virtualY = max(s3InfoRec.virtualY, pMode->VDisplay);	 /*	  * Check what impact each mode has on pixel multiplexing,	  * and mark those modes for which pixmux must be used.	  */	 if (pixMuxPossible) {	    if (s3Bpp == 1 && s3ATT498PixMux		&& !OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE,			       &s3InfoRec.clockOptions)) {	       if (pMode->Clock > 15) {		  pMode->Flags |= V_PIXMUX;		  pixMuxNeeded = TRUE;	       }	    }	    else if (s3InfoRec.clock[pMode->Clock] > nonMuxMaxClock) {	       pMode->Flags |= V_PIXMUX;	       pixMuxNeeded = TRUE;	    }	    if (s3InfoRec.videoRam > nonMuxMaxMemory)	       pMode->Flags |= V_PIXMUX;	    /* XXXX this needs some changes */	    if ((OFLG_ISSET(OPTION_STB_PEGASUS, &s3InfoRec.options) ||		 OFLG_ISSET(OPTION_MIRO_MAGIC_S4, &s3InfoRec.options)) &&		s3InfoRec.virtualX * s3InfoRec.virtualY > 2*1024*1024) {	      /* PIXMUX must be used to access more than 2mb memory. */	      pMode->Flags |= V_PIXMUX;	      pixMuxNeeded = TRUE;	    }	    /*	     * Check if pixmux can't be used.  There are two cases:	     *	     *   1. No switching between mux and non-mux modes.  In this case	     *      the presence of any mode which can't be used in pixmux	     *      mode is flagged.	     *   2. Switching allowed.  In this cases the presence of modes	     *      which require mux for one feature, but can't use it	     *      because of another is flagged.	     */	    if (!allowPixMuxSwitching || (pMode->Flags & V_PIXMUX)) {	       if (pMode->HDisplay < pixMuxMinWidth)		  pixMuxWidthOK = FALSE;	       if ((pMode->Flags & V_INTERLACE) && !allowPixMuxInterlace)		  pixMuxInterlaceOK = FALSE;	    }	 }      }      pMode = pModeSv;   } while (pMode != pEnd);   if ((tx != s3InfoRec.virtualX) || (ty != s3InfoRec.virtualY))      OFLG_CLR(XCONFIG_VIRTUAL,&s3InfoRec.xconfigFlag);   /*    * Are we using pixel multiplexing, or does the mode combination mean    * we can't continue.  Note, this is a case we can't really deal with    * by deleting modes -- there is no unique choice of modes to delete,    * so let the user deal with it.    */   if (pixMuxPossible && pixMuxNeeded) {      if (!pixMuxWidthOK) {	 pMode = s3InfoRec.modes;	 pEnd = NULL;	 do {	    DisplayModePtr pModeSv;	    pModeSv = pMode->next;	    if (pMode->HDisplay < pixMuxMinWidth) {	       xf86DeleteMode(&s3InfoRec, pMode);	    } else {	       if (pEnd == (DisplayModePtr) NULL)		  pEnd = pMode;	    }	    pMode = pModeSv;	 } while (pMode != pEnd);	 if (s3InfoRec.videoRam > nonMuxMaxMemory) {	    ErrorF("%s %s: To access more than %dkB video memory the RAMDAC "		   "must\n", XCONFIG_PROBED, s3InfoRec.name, nonMuxMaxMemory);	    ErrorF("\toperate in pixel multiplex mode, but pixel "		   "multiplexing\n");	    ErrorF("\tcannot be used for modes of width less than %d.\n",		   pixMuxMinWidth);	    ErrorF("\tAdjust the Modes and/or VideoRam and Virtual lines in\n");	    ErrorF("\tyour XF86Config to meet these requirements\n");	 } else {	    if (nonMuxMaxClock > 0) {	       ErrorF("%s %s: Modes with a dot-clock above %dMHz require the "		      "RAMDAC to\n", XCONFIG_PROBED, s3InfoRec.name,		      nonMuxMaxClock / 1000);	       ErrorF("\toperate in pixel multiplex mode, but pixel "		      "multiplexing\n");	       ErrorF("\tcannot be used for modes with width less than %d.\n",		      pixMuxMinWidth);	    } else {	       ErrorF("%s %s: The RAMDAC must operate in pixel multiplex "		      "mode,\n", XCONFIG_PROBED, s3InfoRec.name);	       ErrorF("\tbut pixel multiplexing cannot be used for modes\n");	       ErrorF("\twith width less than %d.\n", pixMuxMinWidth);	    }	    ErrorF("\tAdjust the Modes line in your XF86Config to meet these ");	    ErrorF("\trequirements.\n");	 }      }      if (!pixMuxInterlaceOK) {	 if (s3InfoRec.videoRam > nonMuxMaxMemory) {	    ErrorF("%s %s: To access more than %dkB video memory the RAMDAC "		   "must\n", XCONFIG_PROBED, s3InfoRec.name, nonMuxMaxMemory);	    ErrorF("\toperate in pixel multiplex mode, but pixel "		   "multiplexing\n");	    ErrorF("\tcannot be used for interlaced modes.\n");#if 1	    ErrorF("\tRescanning modes with interlaced modes elimintated.\n");#else	    ErrorF("Adjust the Modes and/or VideoRam and Virtual lines in\n");	    ErrorF("your XF86Config to meet these requirements\n");#endif	 } else {	    if (nonMuxMaxClock > 0) {	       ErrorF("%s %s: Modes with a dot-clock above %dMHz require the "		      "RAMDAC to\n", XCONFIG_PROBED, s3InfoRec.name,		      nonMuxMaxClock / 1000);	       ErrorF("\toperate in pixel multiplex mode, but pixel "		      "multiplexing\n");	       ErrorF("\tcannot be used for interlaced modes.\n");	    } else {	       ErrorF("%s %s: The RAMDAC must operate in pixel multiplex "		      "mode,\n", XCONFIG_PROBED, s3InfoRec.name);	       ErrorF("\tbut pixel multiplexing cannot be used for interlaced "		      "modes.\n");	    }#if 1	    ErrorF("\tRescanning modes with interlaced modes elimintated.\n");#else	    ErrorF("Adjust the Modes line in your XF86Config to meet these ");	    ErrorF("requirements.\n");#endif	 }	 pixMuxInterlaceOK = TRUE;	 lookupFlags = LOOKUP_NO_INTERLACED;	 goto redo_mode_lookup;      }#if 0      if (!pixMuxWidthOK || !pixMuxInterlaceOK) {	 xf86DisableIOPorts(s3InfoRec.scrnIndex);	 return(FALSE);      } else#endif      {	 if (xf86Verbose)	    ErrorF("%s %s: Operating RAMDAC in pixel multiplex mode\n",		   XCONFIG_PROBED, s3InfoRec.name);	 s3UsingPixMux = TRUE;      }   }   if (s3UsingPixMux && !allowPixMuxSwitching) {      /* Mark all modes as V_PIXMUX */      pEnd = pMode = s3InfoRec.modes;      do {	 pMode->Flags |= V_PIXMUX;         pMode = pMode->next;      } while (pMode != pEnd);   }   /*    * For programmable clocks, fill in the SynthClock value    * and set V_DBLCLK as required for each mode    */   if (OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE, &s3InfoRec.clockOptions)) {      /* First just copy the pixel values */      pEnd = pMode = s3InfoRec.modes;      do {	 pMode->SynthClock = s3InfoRec.clock[pMode->Clock];	 pMode = pMode->next;      } while (pMode != pEnd);      /* Now make adjustments */      pEnd = pMode = s3InfoRec.modes;      do {	 switch(s3RamdacType) {	 case NORMAL_DAC:	    /* only suports 8bpp -- nothing to do */	    break;	 case S3_TRIO64_DAC:	    switch (s3Bpp) {	    case 1:#if 0	       /* XXXX pMode->SynthClock /= 2 might be better with sr15 &= ~0x40		  in s3init.c if screen wouldn't completely blank... */	       if (pMode->SynthClock > nonMuxMaxClock) {		  pMode->SynthClock /= 2;		  pMode->Flags |= V_DBLCLK;	       }#endif	       break;	    case 2:	    case 4:	       /* No change for 16bpp and 24bpp */	       break;	    }	    break;	 default:	    /* Do nothing */	    break;	 }	 pMode = pMode->next;      } while (pMode != pEnd);   }   pEnd = pMode = s3InfoRec.modes;   do {      /* Setup the Mode.Private if required */      if (!pMode->PrivSize || !pMode->Private) {	 pMode->PrivSize = S3_MODEPRIV_SIZE;	 pMode->Private = (INT32 *)xcalloc(sizeof(INT32), S3_MODEPRIV_SIZE);	 pMode->Private[0] = 0;      }      /* Set default for invert_vclk */      if (!(pMode->Private[0] & (1 << S3_INVERT_VCLK))) {	 pMode->Private[S3_INVERT_VCLK] = 0;	 pMode->Private[0] |= 1 << S3_INVERT_VCLK;      }      /* Set default for blank_delay */      if (!(pMode->Private[0] & (1 << S3_BLANK_DELAY))) {	 pMode->Private[0] |= (1 << S3_BLANK_DELAY);	 if (S3_ViRGE_VX_SERIES(s3ChipId))	    if (s3Bpp == 1)	       pMode->Private[S3_BLANK_DELAY] = 0x20;	    else if (s3Bpp == 2)	       pMode->Private[S3_BLANK_DELAY] = 0x31;	    else	       pMode->Private[S3_BLANK_DELAY] = 0x70;	 else	    if (s3Bpp == 1)	       pMode->Private[S3_BLANK_DELAY] = 0x00;	    else if (s3Bpp == 2)	       pMode->Private[S3_BLANK_DELAY] = 0x02;	    else	       pMode->Private[S3_BLANK_DELAY] = 0x04;      }      /* Set default for early_sc */      if (!(pMode->Private[0] & (1 << S3_EARLY_SC))) {	 pMode->Private[0] |= 1 << S3_EARLY_SC;	 pMode->Private[S3_EARLY_SC] = 0;      }      pMode = pMode->next;   } while (pMode != pEnd);   if (S3_ViRGE_VX_SERIES(s3ChipId)) {      if (!OFLG_ISSET(OPTION_DAC_6_BIT, &s3InfoRec.options) || s3Bpp > 1)	 s3DAC8Bit = TRUE;   }   if (OFLG_ISSET(OPTION_DAC_8_BIT, &s3InfoRec.options) && !s3DAC8Bit) {      ErrorF("%s %s: Option \"dac_8_bit\" not recognised for RAMDAC \"%s\"\n",	     XCONFIG_PROBED, s3InfoRec.name, s3InfoRec.ramdac);   }   if (xf86Verbose) {      if (s3InfoRec.bitsPerPixel == 8)	 ErrorF("%s %s: Using %d bits per RGB value\n",		OFLG_ISSET(OPTION_DAC_8_BIT, &s3InfoRec.options) ||		OFLG_ISSET(OPTION_DAC_6_BIT, &s3InfoRec.options) ?		XCONFIG_GIVEN : XCONFIG_PROBED, s3InfoRec.name,		s3DAC8Bit ?  8 : 6);      else if (s3InfoRec.bitsPerPixel == 16)	 ErrorF("%s %s: Using 16 bpp.  Color weight: %1d%1d%1d\n",		XCONFIG_GIVEN, s3InfoRec.name, xf86weight.red,		xf86weight.green, xf86weight.blue);      else if (realS3Bpp == 3)	 ErrorF("%s %s: Using packed 24 bpp.  Color weight: %1d%1d%1d\n",		XCONFIG_GIVEN, s3InfoRec.name, xf86weight.red,		xf86weight.green, xf86weight.blue);      else if (s3InfoRec.bitsPerPixel == 32)	 ErrorF("%s %s: Using sparse 32 bpp.  Color weight: %1d%1d%1d\n",		XCONFIG_GIVEN, s3InfoRec.name, xf86weight.red,		xf86weight.green, xf86weight.blue);   }   /* Select the appropriate logical line width */   if (s3UsingPixMux && pixMuxLimitedWidths) {      if (s3InfoRec.virtualX <= 1024) {	 s3DisplayWidth = 1024;      } else if (s3InfoRec.virtualX <= 2048) {	 s3DisplayWidth = 2048;      } else { /* should never get here */	 ErrorF("Internal error in DisplayWidth check, virtual width = %d\n",	        s3InfoRec.virtualX);	 xf86DisableIOPorts(s3InfoRec.scrnIndex);	 return (FALSE);      }   } else {      if (s3InfoRec.virtualX <= 640) {	 s3DisplayWidth = 640;      } else if (s3InfoRec.virtualX <= 800) {	 s3DisplayWidth = 800;      } else if (s3InfoRec.virtualX <= 1024) {	 s3DisplayWidth = 1024;      } else if (s3InfoRec.virtualX <= 1152) {	 s3DisplayWidth = 1152;      } else if (s3InfoRec.virtualX <= 1280) {	 s3DisplayWidth = 1280;      } else if (s3InfoRec.virtualX <= 1600) {	 s3DisplayWidth = 1600;      } else if (s3InfoRec.virtualX <= 2048) {	 s3DisplayWidth = 2048;      } else { /* should never get here */	 ErrorF("Internal error in DisplayWidth check, virtual width = %d\n",	        s3InfoRec.virtualX);	 xf86DisableIOPorts(s3InfoRec.scrnIndex);	 return (FALSE);      }   }   s3BppDisplayWidth = realS3Bpp /*s3Bpp*/ * s3DisplayWidth;   /*    * Work out where to locate S3's HW cursor storage.  It must be on a    * 1k boundary.  We now set the cursor at the top of video memory -1K    * to fix some problems on OS/2. SM[07/03/97]    */   if (OFLG_ISSET(OPTION_SW_CURSOR, &s3InfoRec.options)) {      s3CursorStartY = s3InfoRec.virtualY;      s3CursorLines = 0;   } else {      int st_addr = s3InfoRec.videoRam * 1024 - 1024;      s3CursorStartX = st_addr % s3BppDisplayWidth;      s3CursorStartY = st_addr / s3BppDisplayWidth;      s3CursorLines = ((s3CursorStartX + 1023) / s3BppDisplayWidth) + 1;   }   /*    * Reduce the videoRam value if necessary to prevent Y coords exceeding    * the 12-bit (4096) limit when small display widths are used on cards    * with a lot of memory    */   if (s3InfoRec.videoRam * 1024 / s3BppDisplayWidth > 4096) {      s3InfoRec.videoRam = s3BppDisplayWidth * 4096 / 1024;      ErrorF("%s %s: videoram usage reduced to %dk to avoid co-ord overflow\n",	     XCONFIG_PROBED, s3InfoRec.name, s3InfoRec.videoRam);   }   /*    * This one is difficult to deal with by deleting modes.  Do you delete    * modes to reduce the vertical size or to reduce the displayWidth?  Either    * way it will require the recalculation of everything above.  This one    * is in the too-hard basket.    */   if ((s3BppDisplayWidth * s3InfoRec.virtualY) >       (s3InfoRec.videoRam * 1024 - 1024)) { /* XXXX improve this message */      ErrorF("%s %s: Display size %dx%d is too large: ",             OFLG_ISSET(XCONFIG_VIRTUAL,&s3InfoRec.xconfigFlag) ?                 XCONFIG_GIVEN : XCONFIG_PROBED,             s3InfoRec.name,	     s3DisplayWidth, s3InfoRec.virtualY);      xf86DisableIOPorts(s3InfoRec.scrnIndex);      return (FALSE);   }   if (xf86Verbose) {      ErrorF("%s %s: Virtual resolution set to %dx%d\n",             OFLG_ISSET(XCONFIG_VIRTUAL,&s3InfoRec.xconfigFlag) ?                 XCONFIG_GIVEN : XCONFIG_PROBED,             s3InfoRec.name,	     s3InfoRec.virtualX, s3InfoRec.virtualY);   }#ifdef DPMSExtension   if (DPMSEnabledSwitch ||       (OFLG_ISSET(OPTION_POWER_SAVER, &s3InfoRec.options) &&	!DPMSDisabledSwitch))      defaultDPMSEnabled = DPMSEnabled = TRUE;#endif   if (! (s3Port59 | s3Port5A)) { /* s3Port59/s3Port5A not yet initialized */      if (s3InfoRec.MemBase != 0) {	 s3Port59 =  s3InfoRec.MemBase >> 24;	 s3Port5A = (s3InfoRec.MemBase >> 16) & 0x08;      }      else {	 outb(vgaCRIndex, 0x59);	 s3Port59 = inb(vgaCRReg);	 outb(vgaCRIndex, 0x5a);	 s3Port5A = inb(vgaCRReg);      }   }#ifdef XFreeXDGA      s3InfoRec.displayWidth = s3DisplayWidth;      s3InfoRec.directMode = XF86DGADirectPresent;#endif   in_s3Probe = FALSE;   return TRUE;}