📄 s3.c
字号:
return NULL; l1 = strlen(match1); if (match2 != NULL) l2 = strlen(match2); else /* for compiler-warnings */ l2 = 0; for (i=0; i<BIOS_BSIZE-l1; i++) if (bios[i] == match1[0] && !memcmp(&bios[i],match1,l1)) if (match2 == NULL) return &bios[i+l1]; else for(j=i+l1; (j<BIOS_BSIZE-l2) && bios[j]; j++) if (bios[j] == match2[0] && !memcmp(&bios[j],match2,l2)) return &bios[j+l2]; return NULL;}static int s3DetectMIRO_20SV_Rev(int BIOSbase){ char *match1 = "miroCRYSTAL\37720SV", *match2 = "Rev."; unsigned char *p; if ((p = find_bios_string(BIOSbase,match1,match2)) != NULL) { if (s3BiosVendor == UNKNOWN_BIOS) s3BiosVendor = MIRO_BIOS; if (*p >= '0' && *p <= '9') return *p - '0'; } return -1;}static int check_SPEA_bios(int BIOSbase){ char *match = " SPEA/Video"; unsigned char *p; if ((p = find_bios_string(BIOSbase,match,NULL)) != NULL) { if (s3BiosVendor == UNKNOWN_BIOS) s3BiosVendor = SPEA_BIOS; return 1; } return 0;}/* * s3GetPCIInfo -- probe for PCI information */S3PCIInformation *s3GetPCIInfo(){ static S3PCIInformation info = {0, }; pciConfigPtr pcrp, *pcrpp; Bool found = FALSE; int i = 0; pcrpp = xf86scanpci(s3InfoRec.scrnIndex); if (!pcrpp) return NULL; while ((pcrp = pcrpp[i])) { if (pcrp->_vendor == PCI_S3_VENDOR_ID) { found = TRUE; switch (pcrp->_device) { case PCI_TRIO_32_64: info.ChipType = S3_TRIO_32_64; break; case PCI_928: info.ChipType = S3_928; break; case PCI_864_0: case PCI_864_1: info.ChipType = S3_864; break; case PCI_964_0: case PCI_964_1: info.ChipType = S3_964; break; case PCI_868: info.ChipType = S3_868; break; case PCI_968: info.ChipType = S3_968; break; case PCI_ViRGE: info.ChipType = S3_ViRGE; break; case PCI_ViRGE_VX: info.ChipType = S3_ViRGE_VX; break; case PCI_ViRGE_DXGX: info.ChipType = S3_ViRGE_DXGX; break; case PCI_AURORA64VP: info.ChipType = S3_AURORA64VP; break; case PCI_TRIO64UVP: info.ChipType = S3_TRIO64UVP; break; case PCI_TRIO64V2_DXGX: info.ChipType = S3_TRIO64V2; break; case PCI_PLATO_PX: info.ChipType = S3_PLATO_PX; break; default: info.ChipType = S3_UNKNOWN; info.DevID = pcrp->_device; break; } info.ChipRev = pcrp->_rev_id; info.MemBase = pcrp->_base0 & 0xFF800000;#ifdef PC98_GA968 xf86writepci(s3InfoRec.scrnIndex, pcrp->_bus, pcrp->_cardnum, pcrp->_func, PCI_CMD_STAT_REG, PCI_CMD_MASK, PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE);#endif break; } i++; } /* for new mmio we have to ensure that the PCI base address is * 64MB aligned and that there are no address collitions within 64MB. * S3 868/968 only pretend to need 32MB and thus fool * the BIOS PCI auto configuration :-( */ if (found && info.ChipType != S3_928 && info.ChipType != S3_864 && info.ChipType != S3_964 && !(info.ChipType == S3_TRIO_32_64 && info.ChipRev < 0x40) /* only Trio64V+ */ ) { unsigned long base0; char *probed; char map_64m[64]; int j; if (s3InfoRec.MemBase == 0) { base0 = info.MemBase; probed = XCONFIG_PROBED; } else { base0 = s3InfoRec.MemBase; probed = XCONFIG_GIVEN; } /* map allocated 64MB blocks */ for (j=0; j<64; j++) map_64m[j] = 0; map_64m[63] = 1; /* don't use the last 64MB area */ for (j=0; (pcrp = pcrpp[j]); j++) { if (i != j) { map_64m[ (pcrp->_base0 >> 26) & 0x3f] = 1; map_64m[ (pcrp->_base1 >> 26) & 0x3f] = 1; map_64m[ (pcrp->_base2 >> 26) & 0x3f] = 1; map_64m[ (pcrp->_base3 >> 26) & 0x3f] = 1; map_64m[ (pcrp->_base4 >> 26) & 0x3f] = 1; map_64m[ (pcrp->_base5 >> 26) & 0x3f] = 1; } } /* check for 64MB alignment and free space */ if ((base0 & 0x3ffffff) || map_64m[(base0 >> 26) & 0x3f]) { for (j=63; j>=16 && map_64m[j]; j--); info.MemBase = ((unsigned long)j) << 26; ErrorF("%s %s: PCI: base address not correctly aligned or address conflict\n", probed, s3InfoRec.name); ErrorF("\t\tbase address changed from 0x%08lx to 0x%08lx\n", base0, info.MemBase); xf86writepci(s3InfoRec.scrnIndex, pcrpp[i]->_bus, pcrpp[i]->_cardnum, pcrpp[i]->_func, PCI_MAP_REG_START, ~0L, info.MemBase | PCI_MAP_MEMORY | PCI_MAP_MEMORY_TYPE_32BIT); } s3Port59 = (info.MemBase >> 24) & 0xfc; s3Port5A = 0; } else { if (s3InfoRec.MemBase != 0) { s3Port59 = s3InfoRec.MemBase >> 24; s3Port5A = (s3InfoRec.MemBase >> 16) & 0x08; } else { s3Port59 = info.MemBase >> 24; s3Port5A = (info.MemBase >> 16) & 0x08; } } /* Free PCI information */ xf86cleanpci(); if (found && xf86Verbose) { if (info.ChipType != S3_UNKNOWN) { ErrorF("%s %s: PCI: %s rev %x, Linear FB @ 0x%08lx\n", XCONFIG_PROBED, s3InfoRec.name, xf86TokenToString(s3ChipTable, info.ChipType), info.ChipRev, info.MemBase); } else { ErrorF("%s %s: PCI: unknown (please report), ID 0x%04x rev %x," " Linear FB @ 0x%08lx\n", XCONFIG_PROBED, s3InfoRec.name, info.DevID, info.ChipRev, info.MemBase); } } if (found) return &info; else return NULL;}/* * s3Probe -- probe and initialize the hardware driver */ /* * 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 with too small a width * pixMuxClockOK - FALSE if pixmux isn't possible because * of a clock with too low of a value. * pixMuxNeeded - TRUE when all modes require pixmux due * to !allowPixMuxSwitching or too much * memory (This is a different usage * from what was in the old s3.c) * */Bool pixMuxPossible = FALSE;Bool allowPixMuxInterlace = FALSE;Bool allowPixMuxSwitching = FALSE;Bool pixMuxNeeded = FALSE; Bool pixMuxInterlaceOK = TRUE; Bool pixMuxWidthOK = TRUE;Bool pixMuxClockOK = TRUE;int nonMuxMaxClock = 0;int nonMuxMaxMemory = 8192;int maxDisplayWidth;int maxDisplayHeight;int pixMuxMinWidth = 1024;int pixMuxMinClock = 0;Bool pixMuxLimitedWidths = TRUE;int numClocks;Bools3Probe(){ DisplayModePtr pMode, pEnd; unsigned char config; int i, j; OFlagSet validOptions; char *card, *serno, *elsa_modes; int card_id, max_pix_clock, max_mem_clock, hwconf; int lookupFlags; unsigned char tmp, cr66; Bool OldPixMuxStatus; 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); xf86AddIOPorts(s3InfoRec.scrnIndex, Num_S3_IOPorts, S3_IOPorts); /* 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 /***********************************************\ | Is it an S3? | \***********************************************/ 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, 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)) { if (S3_ANY_ViRGE_SERIES(s3ChipId)) { ErrorF("%s %s: S3 ViRGE chipset: please use \"XF86_S3V\" server\n", XCONFIG_PROBED,s3InfoRec.name); } else { ErrorF("%s %s: Unknown S3 chipset: chip_id = 0x%02x rev. %x\n", XCONFIG_PROBED,s3InfoRec.name,s3ChipId,s3ChipRev); } xf86DisableIOPorts(s3InfoRec.scrnIndex); return(FALSE); } /***************************************\ | Which driver ? | \***************************************/ 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; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -